release-request-0fb8c0d2-10c3-458e-be49-8ef0a73436b5-for-git_oc-iot-release-4189695 snap-temp-L73600000083212332

Change-Id: I13a70479170f967340683e6b314c0fb25ad9894b
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935 b/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
index 6708c5e..33e96f7 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
+++ b/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
@@ -1,4 +1,4 @@
-What		/sys/bus/iio/devices/iio:deviceX/in_proximity_raw
+What		/sys/bus/iio/devices/iio:deviceX/in_proximity_input
 Date:		March 2014
 KernelVersion:	3.15
 Contact:	Matt Ranostay <mranostay@gmail.com>
diff --git a/Documentation/Makefile b/Documentation/Makefile
index bc05482..fc75959 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -1,4 +1,4 @@
 subdir-y := accounting auxdisplay blackfin connector \
-	filesystems filesystems ia64 laptops mic misc-devices \
+	filesystems filesystems ia64 laptops misc-devices \
 	networking pcmcia prctl ptp spi timers vDSO video4linux \
 	watchdog
diff --git a/Documentation/android.txt b/Documentation/android.txt
new file mode 100644
index 0000000..0f40a78
--- /dev/null
+++ b/Documentation/android.txt
@@ -0,0 +1,121 @@
+				=============
+				A N D R O I D
+				=============
+
+Copyright (C) 2009 Google, Inc.
+Written by Mike Chan <mike@android.com>
+
+CONTENTS:
+---------
+
+1. Android
+  1.1 Required enabled config options
+  1.2 Required disabled config options
+  1.3 Recommended enabled config options
+2. Contact
+
+
+1. Android
+==========
+
+Android (www.android.com) is an open source operating system for mobile devices.
+This document describes configurations needed to run the Android framework on
+top of the Linux kernel.
+
+To see a working defconfig look at msm_defconfig or goldfish_defconfig
+which can be found at http://android.git.kernel.org in kernel/common.git
+and kernel/msm.git
+
+
+1.1 Required enabled config options
+-----------------------------------
+After building a standard defconfig, ensure that these options are enabled in
+your .config or defconfig if they are not already. Based off the msm_defconfig.
+You should keep the rest of the default options enabled in the defconfig
+unless you know what you are doing.
+
+ANDROID_PARANOID_NETWORK
+ASHMEM
+CONFIG_FB_MODE_HELPERS
+CONFIG_FONT_8x16
+CONFIG_FONT_8x8
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM
+DAB
+EARLYSUSPEND
+FB
+FB_CFB_COPYAREA
+FB_CFB_FILLRECT
+FB_CFB_IMAGEBLIT
+FB_DEFERRED_IO
+FB_TILEBLITTING
+HIGH_RES_TIMERS
+INOTIFY
+INOTIFY_USER
+INPUT_EVDEV
+INPUT_GPIO
+INPUT_MISC
+LEDS_CLASS
+LEDS_GPIO
+LOCK_KERNEL
+LkOGGER
+LOW_MEMORY_KILLER
+MISC_DEVICES
+NEW_LEDS
+NO_HZ
+POWER_SUPPLY
+PREEMPT
+RAMFS
+RTC_CLASS
+RTC_LIB
+SWITCH
+SWITCH_GPIO
+TMPFS
+UID_STAT
+UID16
+USB_FUNCTION
+USB_FUNCTION_ADB
+USER_WAKELOCK
+VIDEO_OUTPUT_CONTROL
+WAKELOCK
+YAFFS_AUTO_YAFFS2
+YAFFS_FS
+YAFFS_YAFFS1
+YAFFS_YAFFS2
+
+
+1.2 Required disabled config options
+------------------------------------
+CONFIG_YAFFS_DISABLE_LAZY_LOAD
+DNOTIFY
+
+
+1.3 Recommended enabled config options
+------------------------------
+ANDROID_PMEM
+PSTORE_CONSOLE
+PSTORE_RAM
+SCHEDSTATS
+DEBUG_PREEMPT
+DEBUG_MUTEXES
+DEBUG_SPINLOCK_SLEEP
+DEBUG_INFO
+FRAME_POINTER
+CPU_FREQ
+CPU_FREQ_TABLE
+CPU_FREQ_DEFAULT_GOV_ONDEMAND
+CPU_FREQ_GOV_ONDEMAND
+CRC_CCITT
+EMBEDDED
+INPUT_TOUCHSCREEN
+I2C
+I2C_BOARDINFO
+LOG_BUF_SHIFT=17
+SERIAL_CORE
+SERIAL_CORE_CONSOLE
+
+
+2. Contact
+==========
+website: http://android.git.kernel.org
+
+mailing-lists: android-kernel@googlegroups.com
diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index 701d39d..56d6d8b 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -109,7 +109,13 @@
 			1 - 4K
 			2 - 16K
 			3 - 64K
-  Bits 3-63:	Reserved.
+  Bit 3:	Kernel physical placement
+			0 - 2MB aligned base should be as close as possible
+			    to the base of DRAM, since memory below it is not
+			    accessible via the linear mapping
+			1 - 2MB aligned base may be anywhere in physical
+			    memory
+  Bits 4-63:	Reserved.
 
 - When image_size is zero, a bootloader should attempt to keep as much
   memory as possible free for use by the kernel immediately after the
@@ -117,14 +123,14 @@
   depending on selected features, and is effectively unbound.
 
 The Image must be placed text_offset bytes from a 2MB aligned base
-address near the start of usable system RAM and called there. Memory
-below that base address is currently unusable by Linux, and therefore it
-is strongly recommended that this location is the start of system RAM.
-The region between the 2 MB aligned base address and the start of the
-image has no special significance to the kernel, and may be used for
-other purposes.
+address anywhere in usable system RAM and called there. The region
+between the 2 MB aligned base address and the start of the image has no
+special significance to the kernel, and may be used for other purposes.
 At least image_size bytes from the start of the image must be free for
 use by the kernel.
+NOTE: versions prior to v4.6 cannot make use of memory below the
+physical offset of the Image so it is recommended that the Image be
+placed as close as possible to the start of system RAM.
 
 Any memory described to the kernel (even that below the start of the
 image) which is not marked as reserved from the kernel (e.g., with a
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
new file mode 100644
index 0000000..ba4b6ac
--- /dev/null
+++ b/Documentation/arm64/silicon-errata.txt
@@ -0,0 +1,59 @@
+                Silicon Errata and Software Workarounds
+                =======================================
+
+Author: Will Deacon <will.deacon@arm.com>
+Date  : 27 November 2015
+
+It is an unfortunate fact of life that hardware is often produced with
+so-called "errata", which can cause it to deviate from the architecture
+under specific circumstances.  For hardware produced by ARM, these
+errata are broadly classified into the following categories:
+
+  Category A: A critical error without a viable workaround.
+  Category B: A significant or critical error with an acceptable
+              workaround.
+  Category C: A minor error that is not expected to occur under normal
+              operation.
+
+For more information, consult one of the "Software Developers Errata
+Notice" documents available on infocenter.arm.com (registration
+required).
+
+As far as Linux is concerned, Category B errata may require some special
+treatment in the operating system. For example, avoiding a particular
+sequence of code, or configuring the processor in a particular way. A
+less common situation may require similar actions in order to declassify
+a Category A erratum into a Category C erratum. These are collectively
+known as "software workarounds" and are only required in the minority of
+cases (e.g. those cases that both require a non-secure workaround *and*
+can be triggered by Linux).
+
+For software workarounds that may adversely impact systems unaffected by
+the erratum in question, a Kconfig entry is added under "Kernel
+Features" -> "ARM errata workarounds via the alternatives framework".
+These are enabled by default and patched in at runtime when an affected
+CPU is detected. For less-intrusive workarounds, a Kconfig option is not
+available and the code is structured (preferably with a comment) in such
+a way that the erratum will not be hit.
+
+This approach can make it slightly onerous to determine exactly which
+errata are worked around in an arbitrary kernel source tree, so this
+file acts as a registry of software workarounds in the Linux Kernel and
+will be updated when new workarounds are committed and backported to
+stable kernels.
+
+| Implementor    | Component       | Erratum ID      | Kconfig                 |
++----------------+-----------------+-----------------+-------------------------+
+| ARM            | Cortex-A53      | #826319         | ARM64_ERRATUM_826319    |
+| ARM            | Cortex-A53      | #827319         | ARM64_ERRATUM_827319    |
+| ARM            | Cortex-A53      | #824069         | ARM64_ERRATUM_824069    |
+| ARM            | Cortex-A53      | #819472         | ARM64_ERRATUM_819472    |
+| ARM            | Cortex-A53      | #845719         | ARM64_ERRATUM_845719    |
+| ARM            | Cortex-A53      | #843419         | ARM64_ERRATUM_843419    |
+| ARM            | Cortex-A57      | #832075         | ARM64_ERRATUM_832075    |
+| ARM            | Cortex-A57      | #852523         | N/A                     |
+| ARM            | Cortex-A57      | #834220         | ARM64_ERRATUM_834220    |
+|                |                 |                 |                         |
+| Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375    |
+| Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154    |
+| Cavium         | ThunderX Core   | #27456          | CAVIUM_ERRATUM_27456    |
diff --git a/Documentation/arm64/tagged-pointers.txt b/Documentation/arm64/tagged-pointers.txt
index d9995f1..a25a99e 100644
--- a/Documentation/arm64/tagged-pointers.txt
+++ b/Documentation/arm64/tagged-pointers.txt
@@ -11,24 +11,56 @@
 The kernel configures the translation tables so that translations made
 via TTBR0 (i.e. userspace mappings) have the top byte (bits 63:56) of
 the virtual address ignored by the translation hardware. This frees up
-this byte for application use, with the following caveats:
+this byte for application use.
 
-	(1) The kernel requires that all user addresses passed to EL1
-	    are tagged with tag 0x00. This means that any syscall
-	    parameters containing user virtual addresses *must* have
-	    their top byte cleared before trapping to the kernel.
 
-	(2) Non-zero tags are not preserved when delivering signals.
-	    This means that signal handlers in applications making use
-	    of tags cannot rely on the tag information for user virtual
-	    addresses being maintained for fields inside siginfo_t.
-	    One exception to this rule is for signals raised in response
-	    to watchpoint debug exceptions, where the tag information
-	    will be preserved.
+Passing tagged addresses to the kernel
+--------------------------------------
 
-	(3) Special care should be taken when using tagged pointers,
-	    since it is likely that C compilers will not hazard two
-	    virtual addresses differing only in the upper byte.
+All interpretation of userspace memory addresses by the kernel assumes
+an address tag of 0x00.
+
+This includes, but is not limited to, addresses found in:
+
+ - pointer arguments to system calls, including pointers in structures
+   passed to system calls,
+
+ - the stack pointer (sp), e.g. when interpreting it to deliver a
+   signal,
+
+ - the frame pointer (x29) and frame records, e.g. when interpreting
+   them to generate a backtrace or call graph.
+
+Using non-zero address tags in any of these locations may result in an
+error code being returned, a (fatal) signal being raised, or other modes
+of failure.
+
+For these reasons, passing non-zero address tags to the kernel via
+system calls is forbidden, and using a non-zero address tag for sp is
+strongly discouraged.
+
+Programs maintaining a frame pointer and frame records that use non-zero
+address tags may suffer impaired or inaccurate debug and profiling
+visibility.
+
+
+Preserving tags
+---------------
+
+Non-zero tags are not preserved when delivering signals. This means that
+signal handlers in applications making use of tags cannot rely on the
+tag information for user virtual addresses being maintained for fields
+inside siginfo_t. One exception to this rule is for signals raised in
+response to watchpoint debug exceptions, where the tag information will
+be preserved.
 
 The architecture prevents the use of a tagged PC, so the upper byte will
 be set to a sign-extension of bit 55 on exception return.
+
+
+Other considerations
+--------------------
+
+Special care should be taken when using tagged pointers, since it is
+likely that C compilers will not hazard two virtual addresses differing
+only in the upper byte.
diff --git a/Documentation/block/mmc-max-speed.txt b/Documentation/block/mmc-max-speed.txt
new file mode 100644
index 0000000..3f052b9
--- /dev/null
+++ b/Documentation/block/mmc-max-speed.txt
@@ -0,0 +1,38 @@
+eMMC Block layer simulation speed controls in /sys/block/mmcblk*/
+===============================================
+
+Turned on with CONFIG_MMC_SIMULATE_MAX_SPEED which enables MMC device speed
+limiting. Used to test and simulate the behavior of the system when
+confronted with a slow MMC.
+
+Enables max_read_speed, max_write_speed and cache_size attributes and module
+default parameters to control the write or read maximum KB/second speed
+behaviors.
+
+NB: There is room for improving the algorithm for aspects tied directly to
+eMMC specific behavior. For instance, wear leveling and stalls from an
+exhausted erase pool. We would expect that if there was a need to provide
+similar speed simulation controls to other types of block devices, aspects of
+their behavior are modelled separately (e.g. head seek times, heat assist,
+shingling and rotational latency).
+
+/sys/block/mmcblk0/max_read_speed:
+
+Number of KB/second reads allowed to the block device. Used to test and
+simulate the behavior of the system when confronted with a slow reading MMC.
+Set to 0 or "off" to place no speed limit.
+
+/sys/block/mmcblk0/max_write_speed:
+
+Number of KB/second writes allowed to the block device. Used to test and
+simulate the behavior of the system when confronted with a slow writing MMC.
+Set to 0 or "off" to place no speed limit.
+
+/sys/block/mmcblk0/cache_size:
+
+Number of MB of high speed memory or high speed SLC cache expected on the
+eMMC device being simulated. Used to help simulate the write-back behavior
+more accurately. The assumption is the cache has no delay, but draws down
+in the background to the MLC/TLC primary store at the max_write_speed rate.
+Any write speed delays will show up when the cache is full, or when an I/O
+request to flush is issued.
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index 2d984e2..c6256ae 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -578,15 +578,6 @@
 be called for a newly-created cgroup if an error occurs after this
 subsystem's create() method has been called for the new cgroup).
 
-int allow_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
-(cgroup_mutex held by caller)
-
-Called prior to moving a task into a cgroup; if the subsystem
-returns an error, this will abort the attach operation.  Used
-to extend the permission checks - if all subsystems in a cgroup
-return 0, the attach will be allowed to proceed, even if the
-default permission check (root or same user) fails.
-
 int can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
 (cgroup_mutex held by caller)
 
diff --git a/Documentation/device-mapper/boot.txt b/Documentation/device-mapper/boot.txt
index 9dd04b3..adcaad5 100644
--- a/Documentation/device-mapper/boot.txt
+++ b/Documentation/device-mapper/boot.txt
@@ -1,29 +1,25 @@
 Boot time creation of mapped devices
-====================================
+===================================
+
 It is possible to configure a device mapper device to act as the root
 device for your system in two ways.
 
 The first is to build an initial ramdisk which boots to a minimal
 userspace which configures the device, then pivot_root(8) in to it.
 
-The second is to possible when the device-mapper and any targets are
-compiled into the kernel (not a module), one or more device-mappers may
-be created and used as the root device at boot time with the parameters
-given with the boot line dm=...
+For simple device mapper configurations, it is possible to boot directly
+using the following kernel command line:
 
-Multiple device-mappers can be stacked by specifying the number of
-devices. A device can have multiple tables if the the number of tables
-is specified.
+dm="<name> <uuid> <ro>,table line 1,...,table line n"
 
-	<dm>		::= <num-mappers> <device-mapper>+
-	<device-mapper>	::= <head> "," <table>+
-	<head>		::= <name> <uuid> <mode> [<num-tables>]
-	<table>		::= <start> <length> <type> <options> ","
-	<mode>		::= "ro" | "rw"
-	<uuid>		::= xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | "none"
-	<type>		::= "verity" | "bootcache" | ...
+name = the name to associate with the device
+	after boot, udev, if used, will use that name to label
+	the device node.
+uuid = may be 'none' or the UUID desired for the device.
+ro = may be "ro" or "rw".  If "ro", the device and device table will be
+	marked read-only.
 
-Each tables line may be as normal when using the dmsetup tool except for
+Each table line may be as normal when using the dmsetup tool except for
 two variations:
 1. Any use of commas will be interpreted as a newline
 2. Quotation marks cannot be escaped and cannot be used without
@@ -32,33 +28,15 @@
 Unless renamed by udev, the device node created will be dm-0 as the
 first minor number for the device-mapper is used during early creation.
 
-The <num-tables> field is optional and assumed to be 1.
+Example
+=======
 
-Examples
-========
-An example of booting to a linear array made up of user-mode linux block
-devices:
+- Booting to a linear array made up of user-mode linux block devices:
 
-  dm="1 lroot none rw 2, 0 4096 linear 98:16 0, 4096 4096 linear 98:32 0" \
+  dm="lroot none 0, 0 4096 linear 98:16 0, 4096 4096 linear 98:32 0" \
   root=/dev/dm-0
 
-This will boot to a rw dm-linear target of 8192 sectors split across two
+Will boot to a rw dm-linear target of 8192 sectors split across two
 block devices identified by their major:minor numbers.  After boot, udev
 will rename this target to /dev/mapper/lroot (depending on the rules).
 No uuid was assigned.
-
-An example of multiple device-mappers, with the dm="..." contents shown
-here split on multiple lines for readability:
-
-  3 vboot none ro,
-      0 1768000 bootcache
-        device=aa55b119-2a47-8c45-946a-5ac57765011f+1
-        signature=76e9be054b15884a9fa85973e9cb274c93afadb6
-        cache_start=1768000 max_blocks=100000 size_limit=23 max_trace=20000,
-    vroot none ro,
-      0 1740800 verity payload=254:0 hashtree=254:0 hashstart=1740800 alg=sha1
-        root_hexdigest=76e9be054b15884a9fa85973e9cb274c93afadb6
-        salt=5b3549d54d6c7a3837b9b81ed72e49463a64c03680c47835bef94d768e5646fe,
-    vram none rw 2,
-      0 32768 linear 1:0 0,
-      32768 32768 linear 1:1 0,
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index 8fb0749..3a07a87 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -200,7 +200,6 @@
 			    "qcom,gcc-msm8660"
 			    "qcom,kpss-acc-v1"
 			    "qcom,kpss-acc-v2"
-			    "rockchip,rk3036-smp"
 			    "rockchip,rk3066-smp"
 			    "ste,dbx500-smp"
 
diff --git a/Documentation/devicetree/bindings/arm/rockchip.txt b/Documentation/devicetree/bindings/arm/rockchip.txt
index c10e534..8e985dd 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.txt
+++ b/Documentation/devicetree/bindings/arm/rockchip.txt
@@ -1,10 +1,6 @@
 Rockchip platforms device tree bindings
 ---------------------------------------
 
-- Kylin RK3036 board:
-    Required root node properties:
-      - compatible = "rockchip,kylin-rk3036", "rockchip,rk3036";
-
 - MarsBoard RK3066 board:
     Required root node properties:
       - compatible = "haoyu,marsboard-rk3066", "rockchip,rk3066a";
diff --git a/Documentation/devicetree/bindings/clock/imx31-clock.txt b/Documentation/devicetree/bindings/clock/imx31-clock.txt
index 19df842..8163d56 100644
--- a/Documentation/devicetree/bindings/clock/imx31-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx31-clock.txt
@@ -77,7 +77,7 @@
 clks: ccm@53f80000{
 	compatible = "fsl,imx31-ccm";
 	reg = <0x53f80000 0x4000>;
-	interrupts = <0 31 0x04 0 53 0x04>;
+	interrupts = <31>, <53>;
 	#clock-cells = <1>;
 };
 
diff --git a/Documentation/devicetree/bindings/clock/imx35-clock.txt b/Documentation/devicetree/bindings/clock/imx35-clock.txt
index a703564..f497832 100644
--- a/Documentation/devicetree/bindings/clock/imx35-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx35-clock.txt
@@ -94,6 +94,7 @@
 	csi_sel			79
 	iim_gate		80
 	gpu2d_gate		81
+	ckli_gate		82
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 8a47b77..e8c74a6 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -18,6 +18,7 @@
 	"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
 	"allwinner,sun4i-a10-axi-clk" - for the AXI clock
 	"allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
+	"allwinner,sun4i-a10-gates-clk" - for generic gates on all compatible SoCs
 	"allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
 	"allwinner,sun4i-a10-ahb-clk" - for the AHB clock
 	"allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13
@@ -43,6 +44,7 @@
 	"allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
 	"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
 	"allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
+	"allwinner,sun8i-h3-apb0-gates-clk" - for the APB0 gates on H3
 	"allwinner,sun9i-a80-apb0-gates-clk" - for the APB0 gates on A80
 	"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
 	"allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
diff --git a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt
deleted file mode 100644
index 8096a29..0000000
--- a/Documentation/devicetree/bindings/display/rockchip/inno_hdmi-rockchip.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-Rockchip specific extensions to the Innosilicon HDMI
-================================
-
-Required properties:
-- compatible:
-	"rockchip,rk3036-inno-hdmi";
-- reg:
-	Physical base address and length of the controller's registers.
-- clocks, clock-names:
-	Phandle to hdmi controller clock, name should be "pclk"
-- interrupts:
-	HDMI interrupt number
-- ports:
-	Contain one port node with endpoint definitions as defined in
-	Documentation/devicetree/bindings/graph.txt.
-- pinctrl-0, pinctrl-name:
-	Switch the iomux of HPD/CEC pins to HDMI function.
-
-Example:
-hdmi: hdmi@20034000 {
-	compatible = "rockchip,rk3036-inno-hdmi";
-	reg = <0x20034000 0x4000>;
-	interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-	clocks = <&cru  PCLK_HDMI>;
-	clock-names = "pclk";
-	pinctrl-names = "default";
-	pinctrl-0 = <&hdmi_ctl>;
-	status = "disabled";
-
-	hdmi_in: port {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		hdmi_in_lcdc: endpoint@0 {
-			reg = <0>;
-			remote-endpoint = <&lcdc_out_hdmi>;
-		};
-	};
-};
-
-&pinctrl {
-	hdmi {
-		hdmi_ctl: hdmi-ctl {
-			rockchip,pins = <1 8  RK_FUNC_1 &pcfg_pull_none>,
-					<1 9  RK_FUNC_1 &pcfg_pull_none>,
-					<1 10 RK_FUNC_1 &pcfg_pull_none>,
-					<1 11 RK_FUNC_1 &pcfg_pull_none>;
-		};
-	};
-
-};
diff --git a/Documentation/devicetree/bindings/dma/arm-pl330.txt b/Documentation/devicetree/bindings/dma/arm-pl330.txt
index db7e226..2675658 100644
--- a/Documentation/devicetree/bindings/dma/arm-pl330.txt
+++ b/Documentation/devicetree/bindings/dma/arm-pl330.txt
@@ -15,7 +15,6 @@
     cells in the dmas property of client device.
   - dma-channels: contains the total number of DMA channels supported by the DMAC
   - dma-requests: contains the total number of DMA requests supported by the DMAC
-  - arm,pl330-broken-no-flushp: quirk for avoiding to execute DMAFLUSHP
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/goldfish/audio.txt b/Documentation/devicetree/bindings/goldfish/audio.txt
new file mode 100644
index 0000000..d043fda
--- /dev/null
+++ b/Documentation/devicetree/bindings/goldfish/audio.txt
@@ -0,0 +1,17 @@
+Android Goldfish Audio
+
+Android goldfish audio device generated by android emulator.
+
+Required properties:
+
+- compatible : should contain "google,goldfish-audio" to match emulator
+- reg        : <registers mapping>
+- interrupts : <interrupt mapping>
+
+Example:
+
+	goldfish_audio@9030000 {
+		compatible = "google,goldfish-audio";
+		reg = <0x9030000 0x100>;
+		interrupts = <0x4>;
+	};
diff --git a/Documentation/devicetree/bindings/goldfish/battery.txt b/Documentation/devicetree/bindings/goldfish/battery.txt
new file mode 100644
index 0000000..4fb6139
--- /dev/null
+++ b/Documentation/devicetree/bindings/goldfish/battery.txt
@@ -0,0 +1,17 @@
+Android Goldfish Battery
+
+Android goldfish battery device generated by android emulator.
+
+Required properties:
+
+- compatible : should contain "google,goldfish-battery" to match emulator
+- reg        : <registers mapping>
+- interrupts : <interrupt mapping>
+
+Example:
+
+	goldfish_battery@9020000 {
+		compatible = "google,goldfish-battery";
+		reg = <0x9020000 0x1000>;
+		interrupts = <0x3>;
+	};
diff --git a/Documentation/devicetree/bindings/goldfish/events.txt b/Documentation/devicetree/bindings/goldfish/events.txt
new file mode 100644
index 0000000..5babf46
--- /dev/null
+++ b/Documentation/devicetree/bindings/goldfish/events.txt
@@ -0,0 +1,17 @@
+Android Goldfish Events Keypad
+
+Android goldfish events keypad device generated by android emulator.
+
+Required properties:
+
+- compatible : should contain "google,goldfish-events-keypad" to match emulator
+- reg        : <registers mapping>
+- interrupts : <interrupt mapping>
+
+Example:
+
+	goldfish-events@9040000 {
+		compatible = "google,goldfish-events-keypad";
+		reg = <0x9040000 0x1000>;
+		interrupts = <0x5>;
+	};
diff --git a/Documentation/devicetree/bindings/goldfish/pipe.txt b/Documentation/devicetree/bindings/goldfish/pipe.txt
deleted file mode 100644
index e417a31..0000000
--- a/Documentation/devicetree/bindings/goldfish/pipe.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Android Goldfish QEMU Pipe
-
-Andorid pipe virtual device generated by android emulator.
-
-Required properties:
-
-- compatible : should contain "google,android-pipe" to match emulator
-- reg        : <registers mapping>
-- interrupts : <interrupt mapping>
-
-Example:
-
-	android_pipe@a010000 {
-		compatible = "google,android-pipe";
-		reg = <ff018000 0x2000>;
-		interrupts = <0x12>;
-	};
diff --git a/Documentation/devicetree/bindings/goldfish/tty.txt b/Documentation/devicetree/bindings/goldfish/tty.txt
new file mode 100644
index 0000000..8264827
--- /dev/null
+++ b/Documentation/devicetree/bindings/goldfish/tty.txt
@@ -0,0 +1,17 @@
+Android Goldfish TTY
+
+Android goldfish tty device generated by android emulator.
+
+Required properties:
+
+- compatible : should contain "google,goldfish-tty" to match emulator
+- reg        : <registers mapping>
+- interrupts : <interrupt mapping>
+
+Example:
+
+	goldfish_tty@1f004000 {
+		compatible = "google,goldfish-tty";
+		reg = <0x1f004000 0x1000>;
+		interrupts = <0xc>;
+	};
diff --git a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt
index a9a5fe1..ec9d656 100644
--- a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt
@@ -12,6 +12,11 @@
 - vref-supply: The regulator supply ADC reference voltage.
 - #io-channel-cells: Should be 1, see ../iio-bindings.txt
 
+Optional properties:
+- resets: Must contain an entry for each entry in reset-names if need support
+	  this option. See ../reset/reset.txt for details.
+- reset-names: Must include the name "saradc-apb".
+
 Example:
 	saradc: saradc@2006c000 {
 		compatible = "rockchip,saradc";
@@ -19,6 +24,8 @@
 		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
 		clock-names = "saradc", "apb_pclk";
+		resets = <&cru SRST_SARADC>;
+		reset-names = "saradc-apb";
 		#io-channel-cells = <1>;
 		vref-supply = <&vcc18>;
 	};
diff --git a/Documentation/devicetree/bindings/misc/memory-state-time.txt b/Documentation/devicetree/bindings/misc/memory-state-time.txt
new file mode 100644
index 0000000..c99a506
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/memory-state-time.txt
@@ -0,0 +1,8 @@
+Memory bandwidth and frequency state tracking
+
+Required properties:
+- compatible : should be:
+       "memory-state-time"
+- freq-tbl: Should contain entries with each frequency in Hz.
+- bw-buckets: Should contain upper-bound limits for each bandwidth bucket in Mbps.
+       Must match the framework power_profile.xml for the device.
diff --git a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
index d00bfd8..e0381c2 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
@@ -81,9 +81,9 @@
 	l14, l15, l16, l17, l18
 
 pm8941:
-	s1, s2, s3, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14,
-	l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2, lvs3,
-	mvs1, mvs2
+	s1, s2, s3, s4, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13,
+	l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2, lvs3,
+	5vs1, 5vs2
 
 The content of each sub-node is defined by the standard binding for regulators -
 see regulator.txt - with additional custom properties described below:
diff --git a/Documentation/devicetree/bindings/scheduler/sched-energy-costs.txt b/Documentation/devicetree/bindings/scheduler/sched-energy-costs.txt
new file mode 100644
index 0000000..11216f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/scheduler/sched-energy-costs.txt
@@ -0,0 +1,360 @@
+===========================================================
+Energy cost bindings for Energy Aware Scheduling
+===========================================================
+
+===========================================================
+1 - Introduction
+===========================================================
+
+This note specifies bindings required for energy-aware scheduling
+(EAS)[1]. Historically, the scheduler's primary objective has been
+performance.  EAS aims to provide an alternative objective - energy
+efficiency. EAS relies on a simple platform energy cost model to
+guide scheduling decisions.  The model only considers the CPU
+subsystem.
+
+This note is aligned with the definition of the layout of physical
+CPUs in the system as described in the ARM topology binding
+description [2]. The concept is applicable to any system so long as
+the cost model data is provided for those processing elements in
+that system's topology that EAS is required to service.
+
+Processing elements refer to hardware threads, CPUs and clusters of
+related CPUs in increasing order of hierarchy.
+
+EAS requires two key cost metrics - busy costs and idle costs. Busy
+costs comprise of a list of compute capacities for the processing
+element in question and the corresponding power consumption at that
+capacity.  Idle costs comprise of a list of power consumption values
+for each idle state [C-state] that the processing element supports.
+For a detailed description of these metrics, their derivation and
+their use see [3].
+
+These cost metrics are required for processing elements in all
+scheduling domain levels that EAS is required to service.
+
+===========================================================
+2 - energy-costs node
+===========================================================
+
+Energy costs for the processing elements in scheduling domains that
+EAS is required to service are defined in the energy-costs node
+which acts as a container for the actual per processing element cost
+nodes. A single energy-costs node is required for a given system.
+
+- energy-costs node
+
+	Usage: Required
+
+	Description: The energy-costs node is a container node and
+	it's sub-nodes describe costs for each processing element at
+	all scheduling domain levels that EAS is required to
+	service.
+
+	Node name must be "energy-costs".
+
+	The energy-costs node's parent node must be the cpus node.
+
+	The energy-costs node's child nodes can be:
+
+	- one or more cost nodes.
+
+	Any other configuration is considered invalid.
+
+The energy-costs node can only contain a single type of child node
+whose bindings are described in paragraph 4.
+
+===========================================================
+3 - energy-costs node child nodes naming convention
+===========================================================
+
+energy-costs child nodes must follow a naming convention where the
+node name must be "thread-costN", "core-costN", "cluster-costN"
+depending on whether the costs in the node are for a thread, core or
+cluster.  N (where N = {0, 1, ...}) is the node number and has no
+bearing to the OS' logical thread, core or cluster index.
+
+===========================================================
+4 - cost node bindings
+===========================================================
+
+Bindings for cost nodes are defined as follows:
+
+- cluster-cost node
+
+	Description: must be declared within an energy-costs node. A
+	system can contain multiple clusters and each cluster
+	serviced by EAS	must have a corresponding cluster-costs
+	node.
+
+	The cluster-cost node name must be "cluster-costN" as
+	described in 3 above.
+
+	A cluster-cost node must be a leaf node with no children.
+
+	Properties for cluster-cost nodes are described in paragraph
+	5 below.
+
+	Any other configuration is considered invalid.
+
+- core-cost node
+
+	Description: must be declared within an energy-costs node. A
+	system can contain multiple cores and each core serviced by
+	EAS must have a corresponding core-cost node.
+
+	The core-cost node name must be "core-costN" as described in
+	3 above.
+
+	A core-cost node must be a leaf node with no children.
+
+	Properties for core-cost nodes are described in paragraph
+	5 below.
+
+	Any other configuration is considered invalid.
+
+- thread-cost node
+
+	Description: must be declared within an energy-costs node. A
+	system can contain cores with multiple hardware threads and
+	each thread serviced by EAS must have a corresponding
+	thread-cost node.
+
+	The core-cost node name must be "core-costN" as described in
+	3 above.
+
+	A core-cost node must be a leaf node with no children.
+
+	Properties for thread-cost nodes are described in paragraph
+	5 below.
+
+	Any other configuration is considered invalid.
+
+===========================================================
+5 - Cost node properties
+==========================================================
+
+All cost node types must have only the following properties:
+
+- busy-cost-data
+
+	Usage: required
+	Value type: An array of 2-item tuples. Each item is of type
+	u32.
+	Definition: The first item in the tuple is the capacity
+	value as described in [3]. The second item in the tuple is
+	the energy cost value as described in [3].
+
+- idle-cost-data
+
+	Usage: required
+	Value type: An array of 1-item tuples. The item is of type
+	u32.
+	Definition: The item in the tuple is the energy cost value
+	as described in [3].
+
+===========================================================
+4 - Extensions to the cpu node
+===========================================================
+
+The cpu node is extended with a property that establishes the
+connection between the processing element represented by the cpu
+node and the cost-nodes associated with this processing element.
+
+The connection is expressed in line with the topological hierarchy
+that this processing element belongs to starting with the level in
+the hierarchy that this processing element itself belongs to through
+to the highest level that EAS is required to service.  The
+connection cannot be sparse and must be contiguous from the
+processing element's level through to the highest desired level. The
+highest desired level must be the same for all processing elements.
+
+Example: Given that a cpu node may represent a thread that is a part
+of a core, this property may contain multiple elements which
+associate the thread with cost nodes describing the costs for the
+thread itself, the core the thread belongs to, the cluster the core
+belongs to and so on. The elements must be ordered from the lowest
+level nodes to the highest desired level that EAS must service. The
+highest desired level must be the same for all cpu nodes. The
+elements must not be sparse: there must be elements for the current
+thread, the next level of hierarchy (core) and so on without any
+'holes'.
+
+Example: Given that a cpu node may represent a core that is a part
+of a cluster of related cpus this property may contain multiple
+elements which associate the core with cost nodes describing the
+costs for the core itself, the cluster the core belongs to and so
+on. The elements must be ordered from the lowest level nodes to the
+highest desired level that EAS must service. The highest desired
+level must be the same for all cpu nodes. The elements must not be
+sparse: there must be elements for the current thread, the next
+level of hierarchy (core) and so on without any 'holes'.
+
+If the system comprises of hierarchical clusters of clusters, this
+property will contain multiple associations with the relevant number
+of cluster elements in hierarchical order.
+
+Property added to the cpu node:
+
+- sched-energy-costs
+
+	Usage: required
+	Value type: List of phandles
+	Definition: a list of phandles to specific cost nodes in the
+	energy-costs parent node that correspond to the processing
+	element represented by this cpu node in hierarchical order
+	of topology.
+
+	The order of phandles in the list is significant. The first
+	phandle is to the current processing element's own cost
+	node.  Subsequent phandles are to higher hierarchical level
+	cost nodes up until the maximum level that EAS is to
+	service.
+
+	All cpu nodes must have the same highest level cost node.
+
+	The phandle list must not be sparsely populated with handles
+	to non-contiguous hierarchical levels. See commentary above
+	for clarity.
+
+	Any other configuration is invalid.
+
+===========================================================
+5 - Example dts
+===========================================================
+
+Example 1 (ARM 64-bit, 6-cpu system, two clusters of cpus, one
+cluster of 2 Cortex-A57 cpus, one cluster of 4 Cortex-A53 cpus):
+
+cpus {
+	#address-cells = <2>;
+	#size-cells = <0>;
+	.
+	.
+	.
+	A57_0: cpu@0 {
+		compatible = "arm,cortex-a57","arm,armv8";
+		reg = <0x0 0x0>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A57_L2>;
+		clocks = <&scpi_dvfs 0>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
+	};
+
+	A57_1: cpu@1 {
+		compatible = "arm,cortex-a57","arm,armv8";
+		reg = <0x0 0x1>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A57_L2>;
+		clocks = <&scpi_dvfs 0>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
+	};
+
+	A53_0: cpu@100 {
+		compatible = "arm,cortex-a53","arm,armv8";
+		reg = <0x0 0x100>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A53_L2>;
+		clocks = <&scpi_dvfs 1>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
+	};
+
+	A53_1: cpu@101 {
+		compatible = "arm,cortex-a53","arm,armv8";
+		reg = <0x0 0x101>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A53_L2>;
+		clocks = <&scpi_dvfs 1>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
+	};
+
+	A53_2: cpu@102 {
+		compatible = "arm,cortex-a53","arm,armv8";
+		reg = <0x0 0x102>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A53_L2>;
+		clocks = <&scpi_dvfs 1>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
+	};
+
+	A53_3: cpu@103 {
+		compatible = "arm,cortex-a53","arm,armv8";
+		reg = <0x0 0x103>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A53_L2>;
+		clocks = <&scpi_dvfs 1>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
+	};
+
+	energy-costs {
+		CPU_COST_0: core-cost0 {
+			busy-cost-data = <
+				417   168
+				579   251
+				744   359
+				883   479
+				1024  616
+			>;
+			idle-cost-data = <
+				15
+				0
+			>;
+		};
+		CPU_COST_1: core-cost1 {
+			busy-cost-data = <
+				235 33
+				302 46
+				368 61
+				406 76
+				447 93
+			>;
+			idle-cost-data = <
+				6
+				0
+			>;
+		};
+		CLUSTER_COST_0: cluster-cost0 {
+			busy-cost-data = <
+				417   24
+				579   32
+				744   43
+				883   49
+				1024  64
+			>;
+			idle-cost-data = <
+				65
+				24
+			>;
+		};
+		CLUSTER_COST_1: cluster-cost1 {
+			busy-cost-data = <
+				235 26
+				303 30
+				368 39
+				406 47
+				447 57
+			>;
+			idle-cost-data = <
+				56
+				17
+			>;
+		};
+	};
+};
+
+===============================================================================
+[1] https://lkml.org/lkml/2015/5/12/728
+[2] Documentation/devicetree/bindings/topology.txt
+[3] Documentation/scheduler/sched-energy.txt
diff --git a/Documentation/devicetree/bindings/sound/inno-rk3036.txt b/Documentation/devicetree/bindings/sound/inno-rk3036.txt
deleted file mode 100644
index 758de8e..0000000
--- a/Documentation/devicetree/bindings/sound/inno-rk3036.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Inno audio codec for RK3036
-
-Inno audio codec is integrated inside RK3036 SoC.
-
-Required properties:
-- compatible : Should be "rockchip,rk3036-codec".
-- reg : The registers of codec.
-- clock-names : Should be "acodec_pclk".
-- clocks : The clock of codec.
-- rockchip,grf : The phandle of grf device node.
-
-Example:
-
-	acodec: acodec-ana@20030000 {
-		compatible = "rk3036-codec";
-		reg = <0x20030000 0x4000>;
-		rockchip,grf = <&grf>;
-		clock-names = "acodec_pclk";
-		clocks = <&cru ACLK_VCODEC>;
-	};
diff --git a/Documentation/devicetree/bindings/sound/rt5616.txt b/Documentation/devicetree/bindings/sound/rt5616.txt
deleted file mode 100644
index efc48c6..0000000
--- a/Documentation/devicetree/bindings/sound/rt5616.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-RT5616 audio CODEC
-
-This device supports I2C only.
-
-Required properties:
-
-- compatible : "realtek,rt5616".
-
-- reg : The I2C address of the device.
-
-Pins on the device (for linking into audio routes) for RT5616:
-
-  * IN1P
-  * IN2P
-  * IN2N
-  * LOUTL
-  * LOUTR
-  * HPOL
-  * HPOR
-
-Example:
-
-codec: rt5616@1b {
-	compatible = "realtek,rt5616";
-	reg = <0x1b>;
-};
diff --git a/Documentation/features/time/irq-time-acct/arch-support.txt b/Documentation/features/time/irq-time-acct/arch-support.txt
index e633162..4199ffec 100644
--- a/Documentation/features/time/irq-time-acct/arch-support.txt
+++ b/Documentation/features/time/irq-time-acct/arch-support.txt
@@ -9,7 +9,7 @@
     |       alpha: |  ..  |
     |         arc: | TODO |
     |         arm: |  ok  |
-    |       arm64: |  ..  |
+    |       arm64: |  ok  |
     |       avr32: | TODO |
     |    blackfin: | TODO |
     |         c6x: | TODO |
diff --git a/Documentation/features/vm/huge-vmap/arch-support.txt b/Documentation/features/vm/huge-vmap/arch-support.txt
index af6816b..df1d1f3 100644
--- a/Documentation/features/vm/huge-vmap/arch-support.txt
+++ b/Documentation/features/vm/huge-vmap/arch-support.txt
@@ -9,7 +9,7 @@
     |       alpha: | TODO |
     |         arc: | TODO |
     |         arm: | TODO |
-    |       arm64: | TODO |
+    |       arm64: |  ok  |
     |       avr32: | TODO |
     |    blackfin: | TODO |
     |         c6x: | TODO |
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 1c42519..fea4777 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -347,7 +347,7 @@
 a7cb1000-a7cb2000 ---p 00000000 00:00 0
 a7cb2000-a7eb2000 rw-p 00000000 00:00 0
 a7eb2000-a7eb3000 ---p 00000000 00:00 0
-a7eb3000-a7ed5000 rw-p 00000000 00:00 0          [stack:1001]
+a7eb3000-a7ed5000 rw-p 00000000 00:00 0
 a7ed5000-a8008000 r-xp 00000000 03:00 4222       /lib/libc.so.6
 a8008000-a800a000 r--p 00133000 03:00 4222       /lib/libc.so.6
 a800a000-a800b000 rw-p 00135000 03:00 4222       /lib/libc.so.6
@@ -379,7 +379,6 @@
 
  [heap]                   = the heap of the program
  [stack]                  = the stack of the main process
- [stack:1001]             = the stack of the thread with tid 1001
  [vdso]                   = the "virtual dynamic shared object",
                             the kernel system call handler
  [anon:<name>]            = an anonymous mapping that has been
@@ -389,10 +388,8 @@
 
 The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint
 of the individual tasks of a process. In this file you will see a mapping marked
-as [stack] if that task sees it as a stack. This is a key difference from the
-content of /proc/PID/maps, where you will see all mappings that are being used
-as stack by all of those tasks. Hence, for the example above, the task-level
-map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
+as [stack] if that task sees it as a stack. Hence, for the example above, the
+task-level map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
 
 08048000-08049000 r-xp 00000000 03:00 8312       /opt/test
 08049000-0804a000 rw-p 00001000 03:00 8312       /opt/test
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b3d9c98..21321b9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -919,6 +919,8 @@
 	dm=		[DM] Allows early creation of a device-mapper device.
 			See Documentation/device-mapper/boot.txt.
 
+	dmasound=	[HW,OSS] Sound subsystem buff
+
 	dma_debug=off	If the kernel is compiled with DMA_API_DEBUG support,
 			this option disables the debugging code at boot.
 
@@ -1259,6 +1261,10 @@
 			When zero, profiling data is discarded and associated
 			debugfs files are removed at module unload time.
 
+	goldfish	[X86] Enable the goldfish android emulator platform.
+			Don't use this when you are not running on the
+			android emulator
+
 	gpt		[EFI] Forces disk with valid GPT signature but
 			invalid Protective MBR to be treated as GPT. If the
 			primary GPT is corrupted, it enables the backup/alternate
@@ -1375,7 +1381,14 @@
 	i8042.nopnp	[HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
 			     controllers
 	i8042.notimeout	[HW] Ignore timeout condition signalled by controller
-	i8042.reset	[HW] Reset the controller during init and cleanup
+	i8042.reset	[HW] Reset the controller during init, cleanup and
+			     suspend-to-ram transitions, only during s2r
+			     transitions, or never reset
+			Format: { 1 | Y | y | 0 | N | n }
+			1, Y, y: always reset controller
+			0, N, n: don't ever reset controller
+			Default: only on s2r transitions on x86; most other
+			architectures force reset to be always executed
 	i8042.unlock	[HW] Unlock (ignore) the keylock
 	i8042.kbdreset  [HW] Reset device connected to KBD port
 
@@ -3413,6 +3426,10 @@
 
 	ro		[KNL] Mount root device read-only on boot
 
+	rodata=		[KNL]
+		on	Mark read-only kernel memory as read-only (default).
+		off	Leave read-only kernel memory writable for debugging.
+
 	root=		[KNL] Root filesystem
 			See name_to_dev_t comment in init/do_mounts.c.
 
@@ -3573,6 +3590,13 @@
 	spia_pedr=
 	spia_peddr=
 
+	stack_guard_gap=	[MM]
+			override the default stack gap protection. The value
+			is in page units and it defines how many pages prior
+			to (for stacks growing down) resp. after (for stacks
+			growing up) the main stack are reserved for no other
+			mapping. Default value is 256 pages.
+
 	stacktrace	[FTRACE]
 			Enabled the stack tracer on boot up.
 
diff --git a/Documentation/mic/Makefile b/Documentation/mic/Makefile
deleted file mode 100644
index a191d45..0000000
--- a/Documentation/mic/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-subdir-y := mpssd
diff --git a/Documentation/mic/mpssd/Makefile b/Documentation/mic/mpssd/Makefile
deleted file mode 100644
index 06871b0..0000000
--- a/Documentation/mic/mpssd/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-ifndef CROSS_COMPILE
-# List of programs to build
-hostprogs-$(CONFIG_X86_64) := mpssd
-
-mpssd-objs := mpssd.o sysfs.o
-
-# Tell kbuild to always build the programs
-always := $(hostprogs-y)
-
-HOSTCFLAGS += -I$(objtree)/usr/include -I$(srctree)/tools/include
-
-ifdef DEBUG
-HOSTCFLAGS += -DDEBUG=$(DEBUG)
-endif
-
-HOSTLOADLIBES_mpssd := -lpthread
-
-install:
-	install mpssd /usr/sbin/mpssd
-	install micctrl /usr/sbin/micctrl
-endif
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
index a78bf1f..39b7f61 100644
--- a/Documentation/module-signing.txt
+++ b/Documentation/module-signing.txt
@@ -271,3 +271,9 @@
 the private key to sign modules and compromise the operating system.  The
 private key must be either destroyed or moved to a secure location and not kept
 in the root node of the kernel source tree.
+
+If you use the same private key to sign modules for multiple kernel
+configurations, you must ensure that the module version information is
+sufficient to prevent loading a module into a different kernel.  Either
+set CONFIG_MODVERSIONS=y or ensure that each configuration has a different
+kernel release string by changing EXTRAVERSION or CONFIG_LOCALVERSION.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 2ea4c45..5f1ea84 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -584,6 +584,16 @@
 
 	See include/net/tcp.h and the code for more details.
 
+tcp_fwmark_accept - BOOLEAN
+	If set, incoming connections to listening sockets that do not have a
+	socket mark will set the mark of the accepting socket to the fwmark of
+	the incoming SYN packet. This will cause all packets on that connection
+	(starting from the first SYNACK) to be sent with that fwmark. The
+	listening socket's mark is unchanged. Listening sockets that already
+	have a fwmark set via setsockopt(SOL_SOCKET, SO_MARK, ...) are
+	unaffected.
+	Default: 0
+
 tcp_syn_retries - INTEGER
 	Number of times initial SYNs for an active TCP connection attempt
 	will be retransmitted. Should not be higher than 255. Default value
@@ -1403,11 +1413,20 @@
 	Functional default: enabled if accept_ra is enabled.
 			    disabled if accept_ra is disabled.
 
+accept_ra_rt_info_min_plen - INTEGER
+	Minimum prefix length of Route Information in RA.
+
+	Route Information w/ prefix smaller than this variable shall
+	be ignored.
+
+	Functional default: 0 if accept_ra_rtr_pref is enabled.
+			    -1 if accept_ra_rtr_pref is disabled.
+
 accept_ra_rt_info_max_plen - INTEGER
 	Maximum prefix length of Route Information in RA.
 
-	Route Information w/ prefix larger than or equal to this
-	variable shall be ignored.
+	Route Information w/ prefix larger than this variable shall
+	be ignored.
 
 	Functional default: 0 if accept_ra_rtr_pref is enabled.
 			    -1 if accept_ra_rtr_pref is disabled.
diff --git a/Documentation/networking/netlink_mmap.txt b/Documentation/networking/netlink_mmap.txt
deleted file mode 100644
index 54f1047..0000000
--- a/Documentation/networking/netlink_mmap.txt
+++ /dev/null
@@ -1,332 +0,0 @@
-This file documents how to use memory mapped I/O with netlink.
-
-Author: Patrick McHardy <kaber@trash.net>
-
-Overview
---------
-
-Memory mapped netlink I/O can be used to increase throughput and decrease
-overhead of unicast receive and transmit operations. Some netlink subsystems
-require high throughput, these are mainly the netfilter subsystems
-nfnetlink_queue and nfnetlink_log, but it can also help speed up large
-dump operations of f.i. the routing database.
-
-Memory mapped netlink I/O used two circular ring buffers for RX and TX which
-are mapped into the processes address space.
-
-The RX ring is used by the kernel to directly construct netlink messages into
-user-space memory without copying them as done with regular socket I/O,
-additionally as long as the ring contains messages no recvmsg() or poll()
-syscalls have to be issued by user-space to get more message.
-
-The TX ring is used to process messages directly from user-space memory, the
-kernel processes all messages contained in the ring using a single sendmsg()
-call.
-
-Usage overview
---------------
-
-In order to use memory mapped netlink I/O, user-space needs three main changes:
-
-- ring setup
-- conversion of the RX path to get messages from the ring instead of recvmsg()
-- conversion of the TX path to construct messages into the ring
-
-Ring setup is done using setsockopt() to provide the ring parameters to the
-kernel, then a call to mmap() to map the ring into the processes address space:
-
-- setsockopt(fd, SOL_NETLINK, NETLINK_RX_RING, &params, sizeof(params));
-- setsockopt(fd, SOL_NETLINK, NETLINK_TX_RING, &params, sizeof(params));
-- ring = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
-
-Usage of either ring is optional, but even if only the RX ring is used the
-mapping still needs to be writable in order to update the frame status after
-processing.
-
-Conversion of the reception path involves calling poll() on the file
-descriptor, once the socket is readable the frames from the ring are
-processed in order until no more messages are available, as indicated by
-a status word in the frame header.
-
-On kernel side, in order to make use of memory mapped I/O on receive, the
-originating netlink subsystem needs to support memory mapped I/O, otherwise
-it will use an allocated socket buffer as usual and the contents will be
- copied to the ring on transmission, nullifying most of the performance gains.
-Dumps of kernel databases automatically support memory mapped I/O.
-
-Conversion of the transmit path involves changing message construction to
-use memory from the TX ring instead of (usually) a buffer declared on the
-stack and setting up the frame header appropriately. Optionally poll() can
-be used to wait for free frames in the TX ring.
-
-Structured and definitions for using memory mapped I/O are contained in
-<linux/netlink.h>.
-
-RX and TX rings
-----------------
-
-Each ring contains a number of continuous memory blocks, containing frames of
-fixed size dependent on the parameters used for ring setup.
-
-Ring:	[ block 0 ]
-		[ frame 0 ]
-		[ frame 1 ]
-	[ block 1 ]
-		[ frame 2 ]
-		[ frame 3 ]
-	...
-	[ block n ]
-		[ frame 2 * n ]
-		[ frame 2 * n + 1 ]
-
-The blocks are only visible to the kernel, from the point of view of user-space
-the ring just contains the frames in a continuous memory zone.
-
-The ring parameters used for setting up the ring are defined as follows:
-
-struct nl_mmap_req {
-	unsigned int	nm_block_size;
-	unsigned int	nm_block_nr;
-	unsigned int	nm_frame_size;
-	unsigned int	nm_frame_nr;
-};
-
-Frames are grouped into blocks, where each block is a continuous region of memory
-and holds nm_block_size / nm_frame_size frames. The total number of frames in
-the ring is nm_frame_nr. The following invariants hold:
-
-- frames_per_block = nm_block_size / nm_frame_size
-
-- nm_frame_nr = frames_per_block * nm_block_nr
-
-Some parameters are constrained, specifically:
-
-- nm_block_size must be a multiple of the architectures memory page size.
-  The getpagesize() function can be used to get the page size.
-
-- nm_frame_size must be equal or larger to NL_MMAP_HDRLEN, IOW a frame must be
-  able to hold at least the frame header
-
-- nm_frame_size must be smaller or equal to nm_block_size
-
-- nm_frame_size must be a multiple of NL_MMAP_MSG_ALIGNMENT
-
-- nm_frame_nr must equal the actual number of frames as specified above.
-
-When the kernel can't allocate physically continuous memory for a ring block,
-it will fall back to use physically discontinuous memory. This might affect
-performance negatively, in order to avoid this the nm_frame_size parameter
-should be chosen to be as small as possible for the required frame size and
-the number of blocks should be increased instead.
-
-Ring frames
-------------
-
-Each frames contain a frame header, consisting of a synchronization word and some
-meta-data, and the message itself.
-
-Frame:	[ header message ]
-
-The frame header is defined as follows:
-
-struct nl_mmap_hdr {
-	unsigned int	nm_status;
-	unsigned int	nm_len;
-	__u32		nm_group;
-	/* credentials */
-	__u32		nm_pid;
-	__u32		nm_uid;
-	__u32		nm_gid;
-};
-
-- nm_status is used for synchronizing processing between the kernel and user-
-  space and specifies ownership of the frame as well as the operation to perform
-
-- nm_len contains the length of the message contained in the data area
-
-- nm_group specified the destination multicast group of message
-
-- nm_pid, nm_uid and nm_gid contain the netlink pid, UID and GID of the sending
-  process. These values correspond to the data available using SOCK_PASSCRED in
-  the SCM_CREDENTIALS cmsg.
-
-The possible values in the status word are:
-
-- NL_MMAP_STATUS_UNUSED:
-	RX ring:	frame belongs to the kernel and contains no message
-			for user-space. Approriate action is to invoke poll()
-			to wait for new messages.
-
-	TX ring:	frame belongs to user-space and can be used for
-			message construction.
-
-- NL_MMAP_STATUS_RESERVED:
-	RX ring only:	frame is currently used by the kernel for message
-			construction and contains no valid message yet.
-			Appropriate action is to invoke poll() to wait for
-			new messages.
-
-- NL_MMAP_STATUS_VALID:
-	RX ring:	frame contains a valid message. Approriate action is
-			to process the message and release the frame back to
-			the kernel by setting the status to
-			NL_MMAP_STATUS_UNUSED or queue the frame by setting the
-			status to NL_MMAP_STATUS_SKIP.
-
-	TX ring:	the frame contains a valid message from user-space to
-			be processed by the kernel. After completing processing
-			the kernel will release the frame back to user-space by
-			setting the status to NL_MMAP_STATUS_UNUSED.
-
-- NL_MMAP_STATUS_COPY:
-	RX ring only:	a message is ready to be processed but could not be
-			stored in the ring, either because it exceeded the
-			frame size or because the originating subsystem does
-			not support memory mapped I/O. Appropriate action is
-			to invoke recvmsg() to receive the message and release
-			the frame back to the kernel by setting the status to
-			NL_MMAP_STATUS_UNUSED.
-
-- NL_MMAP_STATUS_SKIP:
-	RX ring only:	user-space queued the message for later processing, but
-			processed some messages following it in the ring. The
-			kernel should skip this frame when looking for unused
-			frames.
-
-The data area of a frame begins at a offset of NL_MMAP_HDRLEN relative to the
-frame header.
-
-TX limitations
---------------
-
-As of Jan 2015 the message is always copied from the ring frame to an
-allocated buffer due to unresolved security concerns.
-See commit 4682a0358639b29cf ("netlink: Always copy on mmap TX.").
-
-Example
--------
-
-Ring setup:
-
-	unsigned int block_size = 16 * getpagesize();
-	struct nl_mmap_req req = {
-		.nm_block_size		= block_size,
-		.nm_block_nr		= 64,
-		.nm_frame_size		= 16384,
-		.nm_frame_nr		= 64 * block_size / 16384,
-	};
-	unsigned int ring_size;
-	void *rx_ring, *tx_ring;
-
-	/* Configure ring parameters */
-	if (setsockopt(fd, SOL_NETLINK, NETLINK_RX_RING, &req, sizeof(req)) < 0)
-		exit(1);
-	if (setsockopt(fd, SOL_NETLINK, NETLINK_TX_RING, &req, sizeof(req)) < 0)
-		exit(1)
-
-	/* Calculate size of each individual ring */
-	ring_size = req.nm_block_nr * req.nm_block_size;
-
-	/* Map RX/TX rings. The TX ring is located after the RX ring */
-	rx_ring = mmap(NULL, 2 * ring_size, PROT_READ | PROT_WRITE,
-		       MAP_SHARED, fd, 0);
-	if ((long)rx_ring == -1L)
-		exit(1);
-	tx_ring = rx_ring + ring_size:
-
-Message reception:
-
-This example assumes some ring parameters of the ring setup are available.
-
-	unsigned int frame_offset = 0;
-	struct nl_mmap_hdr *hdr;
-	struct nlmsghdr *nlh;
-	unsigned char buf[16384];
-	ssize_t len;
-
-	while (1) {
-		struct pollfd pfds[1];
-
-		pfds[0].fd	= fd;
-		pfds[0].events	= POLLIN | POLLERR;
-		pfds[0].revents	= 0;
-
-		if (poll(pfds, 1, -1) < 0 && errno != -EINTR)
-			exit(1);
-
-		/* Check for errors. Error handling omitted */
-		if (pfds[0].revents & POLLERR)
-			<handle error>
-
-		/* If no new messages, poll again */
-		if (!(pfds[0].revents & POLLIN))
-			continue;
-
-		/* Process all frames */
-		while (1) {
-			/* Get next frame header */
-			hdr = rx_ring + frame_offset;
-
-			if (hdr->nm_status == NL_MMAP_STATUS_VALID) {
-				/* Regular memory mapped frame */
-				nlh = (void *)hdr + NL_MMAP_HDRLEN;
-				len = hdr->nm_len;
-
-				/* Release empty message immediately. May happen
-				 * on error during message construction.
-				 */
-				if (len == 0)
-					goto release;
-			} else if (hdr->nm_status == NL_MMAP_STATUS_COPY) {
-				/* Frame queued to socket receive queue */
-				len = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
-				if (len <= 0)
-					break;
-				nlh = buf;
-			} else
-				/* No more messages to process, continue polling */
-				break;
-
-			process_msg(nlh);
-release:
-			/* Release frame back to the kernel */
-			hdr->nm_status = NL_MMAP_STATUS_UNUSED;
-
-			/* Advance frame offset to next frame */
-			frame_offset = (frame_offset + frame_size) % ring_size;
-		}
-	}
-
-Message transmission:
-
-This example assumes some ring parameters of the ring setup are available.
-A single message is constructed and transmitted, to send multiple messages
-at once they would be constructed in consecutive frames before a final call
-to sendto().
-
-	unsigned int frame_offset = 0;
-	struct nl_mmap_hdr *hdr;
-	struct nlmsghdr *nlh;
-	struct sockaddr_nl addr = {
-		.nl_family	= AF_NETLINK,
-	};
-
-	hdr = tx_ring + frame_offset;
-	if (hdr->nm_status != NL_MMAP_STATUS_UNUSED)
-		/* No frame available. Use poll() to avoid. */
-		exit(1);
-
-	nlh = (void *)hdr + NL_MMAP_HDRLEN;
-
-	/* Build message */
-	build_message(nlh);
-
-	/* Fill frame header: length and status need to be set */
-	hdr->nm_len	= nlh->nlmsg_len;
-	hdr->nm_status	= NL_MMAP_STATUS_VALID;
-
-	if (sendto(fd, NULL, 0, 0, &addr, sizeof(addr)) < 0)
-		exit(1);
-
-	/* Advance frame offset to next frame */
-	frame_offset = (frame_offset + frame_size) % ring_size;
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index 4976389e..dd15a69 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -831,7 +831,7 @@
 range dealing with pin config and pin multiplexing get placed into a
 different memory range and a separate section of the data sheet.
 
-A flag "strict" in struct pinctrl_desc is available to check and deny
+A flag "strict" in struct pinmux_ops is available to check and deny
 simultaneous access to the same pin from GPIO and pin multiplexing
 consumers on hardware of this type. The pinctrl driver should set this flag
 accordingly.
diff --git a/Documentation/scheduler/sched-energy.txt b/Documentation/scheduler/sched-energy.txt
new file mode 100644
index 0000000..dab2f90
--- /dev/null
+++ b/Documentation/scheduler/sched-energy.txt
@@ -0,0 +1,362 @@
+Energy cost model for energy-aware scheduling (EXPERIMENTAL)
+
+Introduction
+=============
+
+The basic energy model uses platform energy data stored in sched_group_energy
+data structures attached to the sched_groups in the sched_domain hierarchy. The
+energy cost model offers two functions that can be used to guide scheduling
+decisions:
+
+1.	static unsigned int sched_group_energy(struct energy_env *eenv)
+2.	static int energy_diff(struct energy_env *eenv)
+
+sched_group_energy() estimates the energy consumed by all cpus in a specific
+sched_group including any shared resources owned exclusively by this group of
+cpus. Resources shared with other cpus are excluded (e.g. later level caches).
+
+energy_diff() estimates the total energy impact of a utilization change. That
+is, adding, removing, or migrating utilization (tasks).
+
+Both functions use a struct energy_env to specify the scenario to be evaluated:
+
+	struct energy_env {
+		struct sched_group      *sg_top;
+		struct sched_group      *sg_cap;
+		int                     cap_idx;
+		int                     util_delta;
+		int                     src_cpu;
+		int                     dst_cpu;
+		int                     energy;
+	};
+
+sg_top: sched_group to be evaluated. Not used by energy_diff().
+
+sg_cap: sched_group covering the cpus in the same frequency domain. Set by
+sched_group_energy().
+
+cap_idx: Capacity state to be used for energy calculations. Set by
+find_new_capacity().
+
+util_delta: Amount of utilization to be added, removed, or migrated.
+
+src_cpu: Source cpu from where 'util_delta' utilization is removed. Should be
+-1 if no source (e.g. task wake-up).
+
+dst_cpu: Destination cpu where 'util_delta' utilization is added. Should be -1
+if utilization is removed (e.g. terminating tasks).
+
+energy: Result of sched_group_energy().
+
+The metric used to represent utilization is the actual per-entity running time
+averaged over time using a geometric series. Very similar to the existing
+per-entity load-tracking, but _not_ scaled by task priority and capped by the
+capacity of the cpu. The latter property does mean that utilization may
+underestimate the compute requirements for task on fully/over utilized cpus.
+The greatest potential for energy savings without affecting performance too much
+is scenarios where the system isn't fully utilized. If the system is deemed
+fully utilized load-balancing should be done with task load (includes task
+priority) instead in the interest of fairness and performance.
+
+
+Background and Terminology
+===========================
+
+To make it clear from the start:
+
+energy = [joule] (resource like a battery on powered devices)
+power = energy/time = [joule/second] = [watt]
+
+The goal of energy-aware scheduling is to minimize energy, while still getting
+the job done. That is, we want to maximize:
+
+	performance [inst/s]
+	--------------------
+	    power [W]
+
+which is equivalent to minimizing:
+
+	energy [J]
+	-----------
+	instruction
+
+while still getting 'good' performance. It is essentially an alternative
+optimization objective to the current performance-only objective for the
+scheduler. This alternative considers two objectives: energy-efficiency and
+performance. Hence, there needs to be a user controllable knob to switch the
+objective. Since it is early days, this is currently a sched_feature
+(ENERGY_AWARE).
+
+The idea behind introducing an energy cost model is to allow the scheduler to
+evaluate the implications of its decisions rather than applying energy-saving
+techniques blindly that may only have positive effects on some platforms. At
+the same time, the energy cost model must be as simple as possible to minimize
+the scheduler latency impact.
+
+Platform topology
+------------------
+
+The system topology (cpus, caches, and NUMA information, not peripherals) is
+represented in the scheduler by the sched_domain hierarchy which has
+sched_groups attached at each level that covers one or more cpus (see
+sched-domains.txt for more details). To add energy awareness to the scheduler
+we need to consider power and frequency domains.
+
+Power domain:
+
+A power domain is a part of the system that can be powered on/off
+independently. Power domains are typically organized in a hierarchy where you
+may be able to power down just a cpu or a group of cpus along with any
+associated resources (e.g.  shared caches). Powering up a cpu means that all
+power domains it is a part of in the hierarchy must be powered up. Hence, it is
+more expensive to power up the first cpu that belongs to a higher level power
+domain than powering up additional cpus in the same high level domain. Two
+level power domain hierarchy example:
+
+		Power source
+		         +-------------------------------+----...
+per group PD		 G                               G
+		         |           +----------+        |
+		    +--------+-------| Shared   |  (other groups)
+per-cpu PD	    G        G       | resource |
+		    |        |       +----------+
+		+-------+ +-------+
+		| CPU 0 | | CPU 1 |
+		+-------+ +-------+
+
+Frequency domain:
+
+Frequency domains (P-states) typically cover the same group of cpus as one of
+the power domain levels. That is, there might be several smaller power domains
+sharing the same frequency (P-state) or there might be a power domain spanning
+multiple frequency domains.
+
+From a scheduling point of view there is no need to know the actual frequencies
+[Hz]. All the scheduler cares about is the compute capacity available at the
+current state (P-state) the cpu is in and any other available states. For that
+reason, and to also factor in any cpu micro-architecture differences, compute
+capacity scaling states are called 'capacity states' in this document. For SMP
+systems this is equivalent to P-states. For mixed micro-architecture systems
+(like ARM big.LITTLE) it is P-states scaled according to the micro-architecture
+performance relative to the other cpus in the system.
+
+Energy modelling:
+------------------
+
+Due to the hierarchical nature of the power domains, the most obvious way to
+model energy costs is therefore to associate power and energy costs with
+domains (groups of cpus). Energy costs of shared resources are associated with
+the group of cpus that share the resources, only the cost of powering the
+cpu itself and any private resources (e.g. private L1 caches) is associated
+with the per-cpu groups (lowest level).
+
+For example, for an SMP system with per-cpu power domains and a cluster level
+(group of cpus) power domain we get the overall energy costs to be:
+
+	energy = energy_cluster + n * energy_cpu
+
+where 'n' is the number of cpus powered up and energy_cluster is the cost paid
+as soon as any cpu in the cluster is powered up.
+
+The power and frequency domains can naturally be mapped onto the existing
+sched_domain hierarchy and sched_groups by adding the necessary data to the
+existing data structures.
+
+The energy model considers energy consumption from two contributors (shown in
+the illustration below):
+
+1. Busy energy: Energy consumed while a cpu and the higher level groups that it
+belongs to are busy running tasks. Busy energy is associated with the state of
+the cpu, not an event. The time the cpu spends in this state varies. Thus, the
+most obvious platform parameter for this contribution is busy power
+(energy/time).
+
+2. Idle energy: Energy consumed while a cpu and higher level groups that it
+belongs to are idle (in a C-state). Like busy energy, idle energy is associated
+with the state of the cpu. Thus, the platform parameter for this contribution
+is idle power (energy/time).
+
+Energy consumed during transitions from an idle-state (C-state) to a busy state
+(P-state) or going the other way is ignored by the model to simplify the energy
+model calculations.
+
+
+	Power
+	^
+	|            busy->idle             idle->busy
+	|            transition             transition
+	|
+	|                _                      __
+	|               / \                    /  \__________________
+	|______________/   \                  /
+	|                   \                /
+	|  Busy              \    Idle      /        Busy
+	|  low P-state        \____________/         high P-state
+	|
+	+------------------------------------------------------------> time
+
+Busy    |--------------|                          |-----------------|
+
+Wakeup                 |------|            |------|
+
+Idle                          |------------|
+
+
+The basic algorithm
+====================
+
+The basic idea is to determine the total energy impact when utilization is
+added or removed by estimating the impact at each level in the sched_domain
+hierarchy starting from the bottom (sched_group contains just a single cpu).
+The energy cost comes from busy time (sched_group is awake because one or more
+cpus are busy) and idle time (in an idle-state). Energy model numbers account
+for energy costs associated with all cpus in the sched_group as a group.
+
+	for_each_domain(cpu, sd) {
+		sg = sched_group_of(cpu)
+		energy_before = curr_util(sg) * busy_power(sg)
+				+ (1-curr_util(sg)) * idle_power(sg)
+		energy_after = new_util(sg) * busy_power(sg)
+				+ (1-new_util(sg)) * idle_power(sg)
+		energy_diff += energy_before - energy_after
+
+	}
+
+	return energy_diff
+
+{curr, new}_util: The cpu utilization at the lowest level and the overall
+non-idle time for the entire group for higher levels. Utilization is in the
+range 0.0 to 1.0 in the pseudo-code.
+
+busy_power: The power consumption of the sched_group.
+
+idle_power: The power consumption of the sched_group when idle.
+
+Note: It is a fundamental assumption that the utilization is (roughly) scale
+invariant. Task utilization tracking factors in any frequency scaling and
+performance scaling differences due to difference cpu microarchitectures such
+that task utilization can be used across the entire system.
+
+
+Platform energy data
+=====================
+
+struct sched_group_energy can be attached to sched_groups in the sched_domain
+hierarchy and has the following members:
+
+cap_states:
+	List of struct capacity_state representing the supported capacity states
+	(P-states). struct capacity_state has two members: cap and power, which
+	represents the compute capacity and the busy_power of the state. The
+	list must be ordered by capacity low->high.
+
+nr_cap_states:
+	Number of capacity states in cap_states list.
+
+idle_states:
+	List of struct idle_state containing idle_state power cost for each
+	idle-state supported by the system orderd by shallowest state first.
+	All states must be included at all level in the hierarchy, i.e. a
+	sched_group spanning just a single cpu must also include coupled
+	idle-states (cluster states). In addition to the cpuidle idle-states,
+	the list must also contain an entry for the idling using the arch
+	default idle (arch_idle_cpu()). Despite this state may not be a true
+	hardware idle-state it is considered the shallowest idle-state in the
+	energy model and must be the first entry. cpus may enter this state
+	(possibly 'active idling') if cpuidle decides not enter a cpuidle
+	idle-state. Default idle may not be used when cpuidle is enabled.
+	In this case, it should just be a copy of the first cpuidle idle-state.
+
+nr_idle_states:
+	Number of idle states in idle_states list.
+
+There are no unit requirements for the energy cost data. Data can be normalized
+with any reference, however, the normalization must be consistent across all
+energy cost data. That is, one bogo-joule/watt must be the same quantity for
+data, but we don't care what it is.
+
+A recipe for platform characterization
+=======================================
+
+Obtaining the actual model data for a particular platform requires some way of
+measuring power/energy. There isn't a tool to help with this (yet). This
+section provides a recipe for use as reference. It covers the steps used to
+characterize the ARM TC2 development platform. This sort of measurements is
+expected to be done anyway when tuning cpuidle and cpufreq for a given
+platform.
+
+The energy model needs two types of data (struct sched_group_energy holds
+these) for each sched_group where energy costs should be taken into account:
+
+1. Capacity state information
+
+A list containing the compute capacity and power consumption when fully
+utilized attributed to the group as a whole for each available capacity state.
+At the lowest level (group contains just a single cpu) this is the power of the
+cpu alone without including power consumed by resources shared with other cpus.
+It basically needs to fit the basic modelling approach described in "Background
+and Terminology" section:
+
+	energy_system = energy_shared + n * energy_cpu
+
+for a system containing 'n' busy cpus. Only 'energy_cpu' should be included at
+the lowest level. 'energy_shared' is included at the next level which
+represents the group of cpus among which the resources are shared.
+
+This model is, of course, a simplification of reality. Thus, power/energy
+attributions might not always exactly represent how the hardware is designed.
+Also, busy power is likely to depend on the workload. It is therefore
+recommended to use a representative mix of workloads when characterizing the
+capacity states.
+
+If the group has no capacity scaling support, the list will contain a single
+state where power is the busy power attributed to the group. The capacity
+should be set to a default value (1024).
+
+When frequency domains include multiple power domains, the group representing
+the frequency domain and all child groups share capacity states. This must be
+indicated by setting the SD_SHARE_CAP_STATES sched_domain flag. All groups at
+all levels that share the capacity state must have the list of capacity states
+with the power set to the contribution of the individual group.
+
+2. Idle power information
+
+Stored in the idle_states list. The power number is the group idle power
+consumption in each idle state as well when the group is idle but has not
+entered an idle-state ('active idle' as mentioned earlier). Due to the way the
+energy model is defined, the idle power of the deepest group idle state can
+alternatively be accounted for in the parent group busy power. In that case the
+group idle state power values are offset such that the idle power of the
+deepest state is zero. It is less intuitive, but it is easier to measure as
+idle power consumed by the group and the busy/idle power of the parent group
+cannot be distinguished without per group measurement points.
+
+Measuring capacity states and idle power:
+
+The capacity states' capacity and power can be estimated by running a benchmark
+workload at each available capacity state. By restricting the benchmark to run
+on subsets of cpus it is possible to extrapolate the power consumption of
+shared resources.
+
+ARM TC2 has two clusters of two and three cpus respectively. Each cluster has a
+shared L2 cache. TC2 has on-chip energy counters per cluster. Running a
+benchmark workload on just one cpu in a cluster means that power is consumed in
+the cluster (higher level group) and a single cpu (lowest level group). Adding
+another benchmark task to another cpu increases the power consumption by the
+amount consumed by the additional cpu. Hence, it is possible to extrapolate the
+cluster busy power.
+
+For platforms that don't have energy counters or equivalent instrumentation
+built-in, it may be possible to use an external DAQ to acquire similar data.
+
+If the benchmark includes some performance score (for example sysbench cpu
+benchmark), this can be used to record the compute capacity.
+
+Measuring idle power requires insight into the idle state implementation on the
+particular platform. Specifically, if the platform has coupled idle-states (or
+package states). To measure non-coupled per-cpu idle-states it is necessary to
+keep one cpu busy to keep any shared resources alive to isolate the idle power
+of the cpu from idle/busy power of the shared resources. The cpu can be tricked
+into different per-cpu idle states by disabling the other states. Based on
+various combinations of measurements with specific cpus busy and disabling
+idle-states it is possible to extrapolate the idle-state power.
diff --git a/Documentation/scheduler/sched-tune.txt b/Documentation/scheduler/sched-tune.txt
new file mode 100644
index 0000000..9bd2231
--- /dev/null
+++ b/Documentation/scheduler/sched-tune.txt
@@ -0,0 +1,366 @@
+             Central, scheduler-driven, power-performance control
+                               (EXPERIMENTAL)
+
+Abstract
+========
+
+The topic of a single simple power-performance tunable, that is wholly
+scheduler centric, and has well defined and predictable properties has come up
+on several occasions in the past [1,2]. With techniques such as a scheduler
+driven DVFS [3], we now have a good framework for implementing such a tunable.
+This document describes the overall ideas behind its design and implementation.
+
+
+Table of Contents
+=================
+
+1. Motivation
+2. Introduction
+3. Signal Boosting Strategy
+4. OPP selection using boosted CPU utilization
+5. Per task group boosting
+6. Question and Answers
+   - What about "auto" mode?
+   - What about boosting on a congested system?
+   - How CPUs are boosted when we have tasks with multiple boost values?
+7. References
+
+
+1. Motivation
+=============
+
+Sched-DVFS [3] is a new event-driven cpufreq governor which allows the
+scheduler to select the optimal DVFS operating point (OPP) for running a task
+allocated to a CPU. The introduction of sched-DVFS enables running workloads at
+the most energy efficient OPPs.
+
+However, sometimes it may be desired to intentionally boost the performance of
+a workload even if that could imply a reasonable increase in energy
+consumption. For example, in order to reduce the response time of a task, we
+may want to run the task at a higher OPP than the one that is actually required
+by it's CPU bandwidth demand.
+
+This last requirement is especially important if we consider that one of the
+main goals of the sched-DVFS component is to replace all currently available
+CPUFreq policies. Since sched-DVFS is event based, as opposed to the sampling
+driven governors we currently have, it is already more responsive at selecting
+the optimal OPP to run tasks allocated to a CPU. However, just tracking the
+actual task load demand may not be enough from a performance standpoint.  For
+example, it is not possible to get behaviors similar to those provided by the
+"performance" and "interactive" CPUFreq governors.
+
+This document describes an implementation of a tunable, stacked on top of the
+sched-DVFS which extends its functionality to support task performance
+boosting.
+
+By "performance boosting" we mean the reduction of the time required to
+complete a task activation, i.e. the time elapsed from a task wakeup to its
+next deactivation (e.g. because it goes back to sleep or it terminates).  For
+example, if we consider a simple periodic task which executes the same workload
+for 5[s] every 20[s] while running at a certain OPP, a boosted execution of
+that task must complete each of its activations in less than 5[s].
+
+A previous attempt [5] to introduce such a boosting feature has not been
+successful mainly because of the complexity of the proposed solution.  The
+approach described in this document exposes a single simple interface to
+user-space.  This single tunable knob allows the tuning of system wide
+scheduler behaviours ranging from energy efficiency at one end through to
+incremental performance boosting at the other end.  This first tunable affects
+all tasks. However, a more advanced extension of the concept is also provided
+which uses CGroups to boost the performance of only selected tasks while using
+the energy efficient default for all others.
+
+The rest of this document introduces in more details the proposed solution
+which has been named SchedTune.
+
+
+2. Introduction
+===============
+
+SchedTune exposes a simple user-space interface with a single power-performance
+tunable:
+
+  /proc/sys/kernel/sched_cfs_boost
+
+This permits expressing a boost value as an integer in the range [0..100].
+
+A value of 0 (default) configures the CFS scheduler for maximum energy
+efficiency. This means that sched-DVFS runs the tasks at the minimum OPP
+required to satisfy their workload demand.
+A value of 100 configures scheduler for maximum performance, which translates
+to the selection of the maximum OPP on that CPU.
+
+The range between 0 and 100 can be set to satisfy other scenarios suitably. For
+example to satisfy interactive response or depending on other system events
+(battery level etc).
+
+A CGroup based extension is also provided, which permits further user-space
+defined task classification to tune the scheduler for different goals depending
+on the specific nature of the task, e.g. background vs interactive vs
+low-priority.
+
+The overall design of the SchedTune module is built on top of "Per-Entity Load
+Tracking" (PELT) signals and sched-DVFS by introducing a bias on the Operating
+Performance Point (OPP) selection.
+Each time a task is allocated on a CPU, sched-DVFS has the opportunity to tune
+the operating frequency of that CPU to better match the workload demand. The
+selection of the actual OPP being activated is influenced by the global boost
+value, or the boost value for the task CGroup when in use.
+
+This simple biasing approach leverages existing frameworks, which means minimal
+modifications to the scheduler, and yet it allows to achieve a range of
+different behaviours all from a single simple tunable knob.
+The only new concept introduced is that of signal boosting.
+
+
+3. Signal Boosting Strategy
+===========================
+
+The whole PELT machinery works based on the value of a few load tracking signals
+which basically track the CPU bandwidth requirements for tasks and the capacity
+of CPUs. The basic idea behind the SchedTune knob is to artificially inflate
+some of these load tracking signals to make a task or RQ appears more demanding
+that it actually is.
+
+Which signals have to be inflated depends on the specific "consumer".  However,
+independently from the specific (signal, consumer) pair, it is important to
+define a simple and possibly consistent strategy for the concept of boosting a
+signal.
+
+A boosting strategy defines how the "abstract" user-space defined
+sched_cfs_boost value is translated into an internal "margin" value to be added
+to a signal to get its inflated value:
+
+  margin         := boosting_strategy(sched_cfs_boost, signal)
+  boosted_signal := signal + margin
+
+Different boosting strategies were identified and analyzed before selecting the
+one found to be most effective.
+
+Signal Proportional Compensation (SPC)
+--------------------------------------
+
+In this boosting strategy the sched_cfs_boost value is used to compute a
+margin which is proportional to the complement of the original signal.
+When a signal has a maximum possible value, its complement is defined as
+the delta from the actual value and its possible maximum.
+
+Since the tunable implementation uses signals which have SCHED_LOAD_SCALE as
+the maximum possible value, the margin becomes:
+
+	margin := sched_cfs_boost * (SCHED_LOAD_SCALE - signal)
+
+Using this boosting strategy:
+- a 100% sched_cfs_boost means that the signal is scaled to the maximum value
+- each value in the range of sched_cfs_boost effectively inflates the signal in
+  question by a quantity which is proportional to the maximum value.
+
+For example, by applying the SPC boosting strategy to the selection of the OPP
+to run a task it is possible to achieve these behaviors:
+
+-   0% boosting: run the task at the minimum OPP required by its workload
+- 100% boosting: run the task at the maximum OPP available for the CPU
+-  50% boosting: run at the half-way OPP between minimum and maximum
+
+Which means that, at 50% boosting, a task will be scheduled to run at half of
+the maximum theoretically achievable performance on the specific target
+platform.
+
+A graphical representation of an SPC boosted signal is represented in the
+following figure where:
+ a) "-" represents the original signal
+ b) "b" represents a  50% boosted signal
+ c) "p" represents a 100% boosted signal
+
+
+   ^
+   |  SCHED_LOAD_SCALE
+   +-----------------------------------------------------------------+
+   |pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp
+   |
+   |                                             boosted_signal
+   |                                          bbbbbbbbbbbbbbbbbbbbbbbb
+   |
+   |                                            original signal
+   |                  bbbbbbbbbbbbbbbbbbbbbbbb+----------------------+
+   |                                          |
+   |bbbbbbbbbbbbbbbbbb                        |
+   |                                          |
+   |                                          |
+   |                                          |
+   |                  +-----------------------+
+   |                  |
+   |                  |
+   |                  |
+   |------------------+
+   |
+   |
+   +----------------------------------------------------------------------->
+
+The plot above shows a ramped load signal (titled 'original_signal') and it's
+boosted equivalent. For each step of the original signal the boosted signal
+corresponding to a 50% boost is midway from the original signal and the upper
+bound. Boosting by 100% generates a boosted signal which is always saturated to
+the upper bound.
+
+
+4. OPP selection using boosted CPU utilization
+==============================================
+
+It is worth calling out that the implementation does not introduce any new load
+signals. Instead, it provides an API to tune existing signals. This tuning is
+done on demand and only in scheduler code paths where it is sensible to do so.
+The new API calls are defined to return either the default signal or a boosted
+one, depending on the value of sched_cfs_boost. This is a clean an non invasive
+modification of the existing existing code paths.
+
+The signal representing a CPU's utilization is boosted according to the
+previously described SPC boosting strategy. To sched-DVFS, this allows a CPU
+(ie CFS run-queue) to appear more used then it actually is.
+
+Thus, with the sched_cfs_boost enabled we have the following main functions to
+get the current utilization of a CPU:
+
+  cpu_util()
+  boosted_cpu_util()
+
+The new boosted_cpu_util() is similar to the first but returns a boosted
+utilization signal which is a function of the sched_cfs_boost value.
+
+This function is used in the CFS scheduler code paths where sched-DVFS needs to
+decide the OPP to run a CPU at.
+For example, this allows selecting the highest OPP for a CPU which has
+the boost value set to 100%.
+
+
+5. Per task group boosting
+==========================
+
+The availability of a single knob which is used to boost all tasks in the
+system is certainly a simple solution but it quite likely doesn't fit many
+utilization scenarios, especially in the mobile device space.
+
+For example, on battery powered devices there usually are many background
+services which are long running and need energy efficient scheduling. On the
+other hand, some applications are more performance sensitive and require an
+interactive response and/or maximum performance, regardless of the energy cost.
+To better service such scenarios, the SchedTune implementation has an extension
+that provides a more fine grained boosting interface.
+
+A new CGroup controller, namely "schedtune", could be enabled which allows to
+defined and configure task groups with different boosting values.
+Tasks that require special performance can be put into separate CGroups.
+The value of the boost associated with the tasks in this group can be specified
+using a single knob exposed by the CGroup controller:
+
+   schedtune.boost
+
+This knob allows the definition of a boost value that is to be used for
+SPC boosting of all tasks attached to this group.
+
+The current schedtune controller implementation is really simple and has these
+main characteristics:
+
+  1) It is only possible to create 1 level depth hierarchies
+
+     The root control groups define the system-wide boost value to be applied
+     by default to all tasks. Its direct subgroups are named "boost groups" and
+     they define the boost value for specific set of tasks.
+     Further nested subgroups are not allowed since they do not have a sensible
+     meaning from a user-space standpoint.
+
+  2) It is possible to define only a limited number of "boost groups"
+
+     This number is defined at compile time and by default configured to 16.
+     This is a design decision motivated by two main reasons:
+     a) In a real system we do not expect utilization scenarios with more then few
+	boost groups. For example, a reasonable collection of groups could be
+        just "background", "interactive" and "performance".
+     b) It simplifies the implementation considerably, especially for the code
+	which has to compute the per CPU boosting once there are multiple
+        RUNNABLE tasks with different boost values.
+
+Such a simple design should allow servicing the main utilization scenarios identified
+so far. It provides a simple interface which can be used to manage the
+power-performance of all tasks or only selected tasks.
+Moreover, this interface can be easily integrated by user-space run-times (e.g.
+Android, ChromeOS) to implement a QoS solution for task boosting based on tasks
+classification, which has been a long standing requirement.
+
+Setup and usage
+---------------
+
+0. Use a kernel with CGROUP_SCHEDTUNE support enabled
+
+1. Check that the "schedtune" CGroup controller is available:
+
+   root@linaro-nano:~# cat /proc/cgroups
+   #subsys_name	hierarchy	num_cgroups	enabled
+   cpuset  	0		1		1
+   cpu     	0		1		1
+   schedtune	0		1		1
+
+2. Mount a tmpfs to create the CGroups mount point (Optional)
+
+   root@linaro-nano:~# sudo mount -t tmpfs cgroups /sys/fs/cgroup
+
+3. Mount the "schedtune" controller
+
+   root@linaro-nano:~# mkdir /sys/fs/cgroup/stune
+   root@linaro-nano:~# sudo mount -t cgroup -o schedtune stune /sys/fs/cgroup/stune
+
+4. Setup the system-wide boost value (Optional)
+
+   If not configured the root control group has a 0% boost value, which
+   basically disables boosting for all tasks in the system thus running in
+   an energy-efficient mode.
+
+   root@linaro-nano:~# echo $SYSBOOST > /sys/fs/cgroup/stune/schedtune.boost
+
+5. Create task groups and configure their specific boost value (Optional)
+
+   For example here we create a "performance" boost group configure to boost
+   all its tasks to 100%
+
+   root@linaro-nano:~# mkdir /sys/fs/cgroup/stune/performance
+   root@linaro-nano:~# echo 100 > /sys/fs/cgroup/stune/performance/schedtune.boost
+
+6. Move tasks into the boost group
+
+   For example, the following moves the tasks with PID $TASKPID (and all its
+   threads) into the "performance" boost group.
+
+   root@linaro-nano:~# echo "TASKPID > /sys/fs/cgroup/stune/performance/cgroup.procs
+
+This simple configuration allows only the threads of the $TASKPID task to run,
+when needed, at the highest OPP in the most capable CPU of the system.
+
+
+6. Question and Answers
+=======================
+
+What about "auto" mode?
+-----------------------
+
+The 'auto' mode as described in [5] can be implemented by interfacing SchedTune
+with some suitable user-space element. This element could use the exposed
+system-wide or cgroup based interface.
+
+How are multiple groups of tasks with different boost values managed?
+---------------------------------------------------------------------
+
+The current SchedTune implementation keeps track of the boosted RUNNABLE tasks
+on a CPU. Once sched-DVFS selects the OPP to run a CPU at, the CPU utilization
+is boosted with a value which is the maximum of the boost values of the
+currently RUNNABLE tasks in its RQ.
+
+This allows sched-DVFS to boost a CPU only while there are boosted tasks ready
+to run and switch back to the energy efficient mode as soon as the last boosted
+task is dequeued.
+
+
+7. References
+=============
+[1] http://lwn.net/Articles/552889
+[2] http://lkml.org/lkml/2012/5/18/91
+[3] http://lkml.org/lkml/2015/6/26/620
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
index 8638f61..37eca00 100644
--- a/Documentation/scsi/scsi_eh.txt
+++ b/Documentation/scsi/scsi_eh.txt
@@ -263,19 +263,23 @@
 
  3. scmd recovered
     ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd
-	- shost->host_failed--
 	- clear scmd->eh_eflags
 	- scsi_setup_cmd_retry()
 	- move from local eh_work_q to local eh_done_q
     LOCKING: none
+    CONCURRENCY: at most one thread per separate eh_work_q to
+		 keep queue manipulation lockless
 
  4. EH completes
     ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper
-	    layer of failure.
+	    layer of failure. May be called concurrently but must have
+	    a no more than one thread per separate eh_work_q to
+	    manipulate the queue locklessly
 	- scmd is removed from eh_done_q and scmd->eh_entry is cleared
 	- if retry is necessary, scmd is requeued using
           scsi_queue_insert()
 	- otherwise, scsi_finish_command() is invoked for scmd
+	- zero shost->host_failed
     LOCKING: queue or finish function performs appropriate locking
 
 
diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt
index bc3842d..e2dea3d 100644
--- a/Documentation/serial/tty.txt
+++ b/Documentation/serial/tty.txt
@@ -213,9 +213,6 @@
 
 TTY_OTHER_CLOSED	Device is a pty and the other side has closed.
 
-TTY_OTHER_DONE		Device is a pty and the other side has closed and
-			all pending input processing has been completed.
-
 TTY_NO_WRITE_SPLIT	Prevent driver from splitting up writes into
 			smaller chunks.
 
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
index 88152f2..35e17f7 100644
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -32,6 +32,8 @@
 - nr_open
 - overflowuid
 - overflowgid
+- pipe-user-pages-hard
+- pipe-user-pages-soft
 - protected_hardlinks
 - protected_symlinks
 - suid_dumpable
@@ -159,6 +161,27 @@
 
 ==============================================================
 
+pipe-user-pages-hard:
+
+Maximum total number of pages a non-privileged user may allocate for pipes.
+Once this limit is reached, no new pipes may be allocated until usage goes
+below the limit again. When set to 0, no limit is applied, which is the default
+setting.
+
+==============================================================
+
+pipe-user-pages-soft:
+
+Maximum total number of pages a non-privileged user may allocate for pipes
+before the pipe size gets limited to a single page. Once this limit is reached,
+new pipes will be limited to a single page in size for this user in order to
+limit total memory usage, and trying to increase them using fcntl() will be
+denied until usage goes below the limit again. The default value allows to
+allocate up to 1024 pipes at their default size. When set to 0, no limit is
+applied.
+
+==============================================================
+
 protected_hardlinks:
 
 A long-standing class of security issues is the hardlink-based
@@ -242,6 +265,13 @@
 
 ==============================================================
 
+mount-max:
+
+This denotes the maximum number of mounts that may exist
+in a mount namespace.
+
+==============================================================
+
 
 2. /proc/sys/fs/binfmt_misc
 ----------------------------------------------------------
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 5728779..e7018fc 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -825,14 +825,13 @@
        Each write syscall must fully contain the sysctl value to be
        written, and multiple writes on the same sysctl file descriptor
        will rewrite the sysctl value, regardless of file position.
-   0 - (default) Same behavior as above, but warn about processes that
-       perform writes to a sysctl file descriptor when the file position
-       is not 0.
-   1 - Respect file position when writing sysctl strings. Multiple writes
-       will append to the sysctl value buffer. Anything past the max length
-       of the sysctl value buffer will be ignored. Writes to numeric sysctl
-       entries must always be at file position 0 and the value must be
-       fully contained in the buffer sent in the write syscall.
+   0 - Same behavior as above, but warn about processes that perform writes
+       to a sysctl file descriptor when the file position is not 0.
+   1 - (default) Respect file position when writing sysctl strings. Multiple
+       writes will append to the sysctl value buffer. Anything past the max
+       length of the sysctl value buffer will be ignored. Writes to numeric
+       sysctl entries must always be at file position 0 and the value must
+       be fully contained in the buffer sent in the write syscall.
 
 ==============================================================
 
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index cf2f9e9..fa16fb2 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -357,6 +357,26 @@
 		  to correlate events across hypervisor/guest if
 		  tb_offset is known.
 
+	  mono: This uses the fast monotonic clock (CLOCK_MONOTONIC)
+		which is monotonic and is subject to NTP rate adjustments.
+
+	  mono_raw:
+		This is the raw monotonic clock (CLOCK_MONOTONIC_RAW)
+		which is montonic but is not subject to any rate adjustments
+		and ticks at the same rate as the hardware clocksource.
+
+	  boot: This is the boot clock (CLOCK_BOOTTIME) and is based on the
+		fast monotonic clock, but also accounts for time spent in
+		suspend. Since the clock access is designed for use in
+		tracing in the suspend path, some side effects are possible
+		if clock is accessed after the suspend time is accounted before
+		the fast mono clock is updated. In this case, the clock update
+		appears to happen slightly sooner than it normally would have.
+		Also on 32-bit systems, its possible that the 64-bit boot offset
+		sees a partial update. These effects are rare and post
+		processing should be able to handle them. See comments on
+		ktime_get_boot_fast_ns function for more information.
+
 	To set a clock, simply echo the clock name into this file.
 
 	  echo global > trace_clock
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 092ee9f..df8ab4f 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1991,6 +1991,7 @@
   PPC   | KVM_REG_PPC_TM_VSCR           | 32
   PPC   | KVM_REG_PPC_TM_DSCR           | 64
   PPC   | KVM_REG_PPC_TM_TAR            | 64
+  PPC   | KVM_REG_PPC_TM_XER            | 64
         |                               |
   MIPS  | KVM_REG_MIPS_R0               | 64
           ...
diff --git a/Documentation/x86/pat.txt b/Documentation/x86/pat.txt
index 54944c7..2a4ee63 100644
--- a/Documentation/x86/pat.txt
+++ b/Documentation/x86/pat.txt
@@ -196,3 +196,35 @@
 "debugpat" boot parameter. With this parameter, various debug messages are
 printed to dmesg log.
 
+PAT Initialization
+------------------
+
+The following table describes how PAT is initialized under various
+configurations. The PAT MSR must be updated by Linux in order to support WC
+and WT attributes. Otherwise, the PAT MSR has the value programmed in it
+by the firmware. Note, Xen enables WC attribute in the PAT MSR for guests.
+
+ MTRR PAT   Call Sequence               PAT State  PAT MSR
+ =========================================================
+ E    E     MTRR -> PAT init            Enabled    OS
+ E    D     MTRR -> PAT init            Disabled    -
+ D    E     MTRR -> PAT disable         Disabled   BIOS
+ D    D     MTRR -> PAT disable         Disabled    -
+ -    np/E  PAT  -> PAT disable         Disabled   BIOS
+ -    np/D  PAT  -> PAT disable         Disabled    -
+ E    !P/E  MTRR -> PAT init            Disabled   BIOS
+ D    !P/E  MTRR -> PAT disable         Disabled   BIOS
+ !M   !P/E  MTRR stub -> PAT disable    Disabled   BIOS
+
+ Legend
+ ------------------------------------------------
+ E         Feature enabled in CPU
+ D	   Feature disabled/unsupported in CPU
+ np	   "nopat" boot option specified
+ !P	   CONFIG_X86_PAT option unset
+ !M	   CONFIG_MTRR option unset
+ Enabled   PAT state set to enabled
+ Disabled  PAT state set to disabled
+ OS        PAT initializes PAT MSR with OS setting
+ BIOS      PAT keeps PAT MSR with BIOS setting
+
diff --git a/Makefile b/Makefile
index 3c2f46c..0372b75 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 4
-SUBLEVEL = 10
+SUBLEVEL = 77
 EXTRAVERSION =
 NAME = Blurry Fish Butt
 
@@ -128,6 +128,10 @@
 # Cancel implicit rules on top Makefile
 $(CURDIR)/Makefile Makefile: ;
 
+ifneq ($(words $(subst :, ,$(CURDIR))), 1)
+  $(error main directory cannot contain spaces nor colons)
+endif
+
 ifneq ($(KBUILD_OUTPUT),)
 # Invoke a second make in the output directory, passing relevant variables
 # check that the output directory actually exists
@@ -142,7 +146,7 @@
 $(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
 	@:
 
-sub-make: FORCE
+sub-make:
 	$(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \
 	-f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS))
 
@@ -364,7 +368,7 @@
 LDFLAGS_MODULE  =
 CFLAGS_KERNEL	=
 AFLAGS_KERNEL	=
-CFLAGS_GCOV	= -fprofile-arcs -ftest-coverage
+CFLAGS_GCOV	= -fprofile-arcs -ftest-coverage -fno-tree-loop-im
 
 
 # Use USERINCLUDE when you must reference the UAPI directories only.
@@ -391,15 +395,12 @@
 		   -fno-strict-aliasing -fno-common \
 		   -Werror-implicit-function-declaration \
 		   -Wno-format-security \
-		   -std=gnu89
+		   -std=gnu89 $(call cc-option,-fno-PIE)
 
-# We must turn off the Android-specific compiler options as early as possible
-# otherwise cc-option calls below may erroneously fail.
-KBUILD_CFLAGS	+= $(call cc-option,-mno-android,)
 
 KBUILD_AFLAGS_KERNEL :=
 KBUILD_CFLAGS_KERNEL :=
-KBUILD_AFLAGS   := -D__ASSEMBLY__
+KBUILD_AFLAGS   := -D__ASSEMBLY__ $(call cc-option,-fno-PIE)
 KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
@@ -499,6 +500,12 @@
                 endif
         endif
 endif
+# install and module_install need also be processed one by one
+ifneq ($(filter install,$(MAKECMDGOALS)),)
+        ifneq ($(filter modules_install,$(MAKECMDGOALS)),)
+	        mixed-targets := 1
+        endif
+endif
 
 ifeq ($(mixed-targets),1)
 # ===========================================================================
@@ -610,16 +617,28 @@
 include arch/$(SRCARCH)/Makefile
 
 KBUILD_CFLAGS	+= $(call cc-option,-fno-delete-null-pointer-checks,)
+KBUILD_CFLAGS	+= $(call cc-disable-warning,maybe-uninitialized,)
+KBUILD_CFLAGS	+= $(call cc-disable-warning,frame-address,)
 
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS	+= -Os $(call cc-disable-warning,maybe-uninitialized,)
+KBUILD_CFLAGS	+= -Os
 else
+ifdef CONFIG_PROFILE_ALL_BRANCHES
 KBUILD_CFLAGS	+= -O2
+else
+KBUILD_CFLAGS   += -O2
+endif
 endif
 
 # Tell gcc to never replace conditional load with a non-conditional one
 KBUILD_CFLAGS	+= $(call cc-option,--param=allow-store-data-races=0)
 
+# check for 'asm goto'
+ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
+	KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
+	KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
+endif
+
 ifdef CONFIG_READABLE_ASM
 # Disable optimizations that make assembler listings hard to read.
 # reorder blocks reorders the control in the function
@@ -686,9 +705,10 @@
 KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior)
 else
 
-# This warning generated too much noise in a regular build.
-# Use make W=1 to enable this warning (see scripts/Makefile.build)
+# These warnings generated too much noise in a regular build.
+# Use make W=1 to enable them (see scripts/Makefile.build)
 KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
+KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable)
 endif
 
 ifdef CONFIG_FRAME_POINTER
@@ -774,12 +794,6 @@
 # use the deterministic mode of AR if available
 KBUILD_ARFLAGS := $(call ar-option,D)
 
-# check for 'asm goto'
-ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
-	KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
-	KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
-endif
-
 include scripts/Makefile.kasan
 include scripts/Makefile.extrawarn
 
@@ -986,7 +1000,7 @@
 
 archprepare: archheaders archscripts prepare1 scripts_basic
 
-prepare0: archprepare FORCE
+prepare0: archprepare
 	$(Q)$(MAKE) $(build)=.
 
 # All the preparing..
@@ -1031,7 +1045,7 @@
 export INSTALL_FW_PATH
 
 PHONY += firmware_install
-firmware_install: FORCE
+firmware_install:
 	@mkdir -p $(objtree)/firmware
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install
 
@@ -1051,7 +1065,7 @@
 archscripts:
 
 PHONY += __headers
-__headers: $(version_h) scripts_basic asm-generic archheaders archscripts FORCE
+__headers: $(version_h) scripts_basic asm-generic archheaders archscripts
 	$(Q)$(MAKE) $(build)=scripts build_unifdef
 
 PHONY += headers_install_all
@@ -1263,7 +1277,7 @@
 	@echo  '  firmware_install- Install all firmware to INSTALL_FW_PATH'
 	@echo  '                    (default: $$(INSTALL_MOD_PATH)/lib/firmware)'
 	@echo  '  dir/            - Build all files in dir and below'
-	@echo  '  dir/file.[oisS] - Build specified target only'
+	@echo  '  dir/file.[ois]  - Build specified target only'
 	@echo  '  dir/file.lst    - Build specified mixed source/assembly target only'
 	@echo  '                    (requires a recent binutils and recent build (System.map))'
 	@echo  '  dir/file.ko     - Build module including final link'
@@ -1503,11 +1517,11 @@
 # Clear a bunch of variables before executing the submake
 tools/: FORCE
 	$(Q)mkdir -p $(objtree)/tools
-	$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(O) subdir=tools -C $(src)/tools/
+	$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/
 
 tools/%: FORCE
 	$(Q)mkdir -p $(objtree)/tools
-	$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(O) subdir=tools -C $(src)/tools/ $*
+	$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/ $*
 
 # Single targets
 # ---------------------------------------------------------------------------
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
deleted file mode 100644
index 0cd7cd8..0000000
--- a/PREUPLOAD.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-[Builtin Hooks]
-checkpatch = true
-commit_msg_bug_field = true
diff --git a/android/configs/README b/android/configs/README
new file mode 100644
index 0000000..8798731
--- /dev/null
+++ b/android/configs/README
@@ -0,0 +1,15 @@
+The files in this directory are meant to be used as a base for an Android
+kernel config. All devices should have the options in android-base.cfg enabled.
+While not mandatory, the options in android-recommended.cfg enable advanced
+Android features.
+
+Assuming you already have a minimalist defconfig for your device, a possible
+way to enable these options would be:
+
+     ARCH=<arch> scripts/kconfig/merge_config.sh <path_to>/<device>_defconfig android/configs/android-base.cfg android/configs/android-recommended.cfg
+
+This will generate a .config that can then be used to save a new defconfig or
+compile a new kernel with Android features enabled.
+
+Because there is no tool to consistently generate these config fragments,
+lets keep them alphabetically sorted instead of random.
diff --git a/android/configs/android-base-arm64.cfg b/android/configs/android-base-arm64.cfg
new file mode 100644
index 0000000..43f23d6
--- /dev/null
+++ b/android/configs/android-base-arm64.cfg
@@ -0,0 +1,5 @@
+#  KEEP ALPHABETICALLY SORTED
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+CONFIG_SWP_EMULATION=y
diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg
new file mode 100644
index 0000000..28dce6c
--- /dev/null
+++ b/android/configs/android-base.cfg
@@ -0,0 +1,169 @@
+#  KEEP ALPHABETICALLY SORTED
+# CONFIG_DEVKMEM is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFS_FS is not set
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_USELIB is not set
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_DEVICES=binder,hwbinder,vndbinder
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ASHMEM=y
+CONFIG_AUDIT=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_DEFAULT_SECURITY_SELINUX=y
+CONFIG_EMBEDDED=y
+CONFIG_FB=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_INET_ESP=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IPV6=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_KEY=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_NAT=y
+CONFIG_NO_HZ=y
+CONFIG_PACKET=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PPP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PREEMPT=y
+CONFIG_PROFILING=y
+CONFIG_QFMT_V2=y
+CONFIG_QUOTA=y
+CONFIG_QUOTACTL=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_TREE=y
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_SECCOMP=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_STAGING=y
+CONFIG_SYNC=y
+CONFIG_TUN=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_UNIX=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_GADGET=y
+CONFIG_XFRM_USER=y
diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg
new file mode 100644
index 0000000..eecf8d80
--- /dev/null
+++ b/android/configs/android-recommended.cfg
@@ -0,0 +1,134 @@
+#  KEEP ALPHABETICALLY SORTED
+# CONFIG_AIO is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_PM_WAKELOCKS_GC is not set
+# CONFIG_VT is not set
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
+CONFIG_ARM_KERNMEM_PERMS=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_COMPACTION=y
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_DEBUG_RODATA=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_FUSE_FS=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HIDRAW=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_EMS_FF=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_HOLTEK=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_PRIMAX=y
+CONFIG_HID_PRODIKEYS=y
+CONFIG_HID_ROCCAT=y
+CONFIG_HID_SAITEK=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SPEEDLINK=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_WALTOP=y
+CONFIG_HID_WIIMOTE=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_GPIO=y
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_KEYRESET=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_TABLET=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_ION=y
+CONFIG_JOYSTICK_XPAD=y
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KSM=y
+CONFIG_LOGIG940_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGITECH_FF=y
+CONFIG_MD=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_MSDOS_FS=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANTHERLORD_FF=y
+CONFIG_PERF_EVENTS=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_RUNTIME=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+CONFIG_POWER_SUPPLY=y
+CONFIG_PSTORE=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_RAM=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_SND=y
+CONFIG_SOUND=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_TABLET_USB_ACECAD=y
+CONFIG_TABLET_USB_AIPTEK=y
+CONFIG_TABLET_USB_GTCO=y
+CONFIG_TABLET_USB_HANWANG=y
+CONFIG_TABLET_USB_KBTAB=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_TASK_XACCT=y
+CONFIG_TIMER_STATS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UHID=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_USBNET=y
+CONFIG_VFAT_FS=y
diff --git a/arch/Kconfig b/arch/Kconfig
index ba1b626..98f64ad 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -423,6 +423,15 @@
 
 endchoice
 
+config HAVE_ARCH_WITHIN_STACK_FRAMES
+	bool
+	help
+	  An architecture should select this if it can walk the kernel stack
+	  frames to determine if an object is part of either the arguments
+	  or local variables (i.e. that it excludes saved return addresses,
+	  and similar) by implementing an inline arch_within_stack_frames(),
+	  which is used by CONFIG_HARDENED_USERCOPY.
+
 config HAVE_CONTEXT_TRACKING
 	bool
 	help
@@ -511,6 +520,13 @@
 	  - arch_mmap_rnd()
 	  - arch_randomize_brk()
 
+config HAVE_COPY_THREAD_TLS
+	bool
+	help
+	  Architecture provides copy_thread_tls to accept tls argument via
+	  normal C parameter passing, rather than extracting the syscall
+	  argument from pt_regs.
+
 config HAVE_ARCH_MMAP_RND_BITS
 	bool
 	help
@@ -579,13 +595,6 @@
 	  This value can be changed after boot using the
 	  /proc/sys/vm/mmap_rnd_compat_bits tunable
 
-config HAVE_COPY_THREAD_TLS
-	bool
-	help
-	  Architecture provides copy_thread_tls to accept tls argument via
-	  normal C parameter passing, rather than extracting the syscall
-	  argument from pt_regs.
-
 #
 # ABI hall of shame
 #
diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h
index 9b0d400..c0ddbbf 100644
--- a/arch/alpha/include/asm/uaccess.h
+++ b/arch/alpha/include/asm/uaccess.h
@@ -371,14 +371,6 @@
 	return __cu_len;
 }
 
-extern inline long
-__copy_tofrom_user(void *to, const void *from, long len, const void __user *validate)
-{
-	if (__access_ok((unsigned long)validate, len, get_fs()))
-		len = __copy_tofrom_user_nocheck(to, from, len);
-	return len;
-}
-
 #define __copy_to_user(to, from, n)					\
 ({									\
 	__chk_user_ptr(to);						\
@@ -393,17 +385,22 @@
 #define __copy_to_user_inatomic __copy_to_user
 #define __copy_from_user_inatomic __copy_from_user
 
-
 extern inline long
 copy_to_user(void __user *to, const void *from, long n)
 {
-	return __copy_tofrom_user((__force void *)to, from, n, to);
+	if (likely(__access_ok((unsigned long)to, n, get_fs())))
+		n = __copy_tofrom_user_nocheck((__force void *)to, from, n);
+	return n;
 }
 
 extern inline long
 copy_from_user(void *to, const void __user *from, long n)
 {
-	return __copy_tofrom_user(to, (__force void *)from, n, from);
+	if (likely(__access_ok((unsigned long)from, n, get_fs())))
+		n = __copy_tofrom_user_nocheck(to, (__force void *)from, n);
+	else
+		memset(to, 0, n);
+	return n;
 }
 
 extern void __do_clear_user(void);
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 6cc0816..63f06a2 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -1188,8 +1188,10 @@
 	if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
 		return -EFAULT;
 
-	err = 0;
-	err |= put_user(status, ustatus);
+	err = put_user(status, ustatus);
+	if (ret < 0)
+		return err ? err : ret;
+
 	err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
 	err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
 	err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 6312f60..2d785f5 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -387,7 +387,7 @@
 
 config ARC_STAR_9000923308
 	bool "Workaround for llock/scond livelock"
-	default y
+	default n
 	depends on ISA_ARCV2 && SMP && ARC_HAS_LLSC
 
 config ARC_HAS_SWAPE
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index aeb1902..c05ea2b 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -18,6 +18,20 @@
 cflags-$(CONFIG_ISA_ARCOMPACT)	+= -mA7
 cflags-$(CONFIG_ISA_ARCV2)	+= -mcpu=archs
 
+is_700 = $(shell $(CC) -dM -E - < /dev/null | grep -q "ARC700" && echo 1 || echo 0)
+
+ifdef CONFIG_ISA_ARCOMPACT
+ifeq ($(is_700), 0)
+    $(error Toolchain not configured for ARCompact builds)
+endif
+endif
+
+ifdef CONFIG_ISA_ARCV2
+ifeq ($(is_700), 1)
+    $(error Toolchain not configured for ARCv2 builds)
+endif
+endif
+
 ifdef CONFIG_ARC_CURR_IN_REG
 # For a global register defintion, make sure it gets passed to every file
 # We had a customer reported bug where some code built in kernel was NOT using
@@ -48,8 +62,6 @@
 
 endif
 
-cflags-$(CONFIG_ARC_DW2_UNWIND)		+= -fasynchronous-unwind-tables
-
 # By default gcc 4.8 generates dwarf4 which kernel unwinder can't grok
 ifeq ($(atleast_gcc48),y)
 cflags-$(CONFIG_ARC_DW2_UNWIND)		+= -gdwarf-2
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 7fac7d8..2c30a01 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -374,12 +374,6 @@
 	return IS_ENABLED(CONFIG_ISA_ARCOMPACT);
 }
 
-#if defined(CONFIG_ISA_ARCOMPACT) && !defined(_CPU_DEFAULT_A7)
-#error "Toolchain not configured for ARCompact builds"
-#elif defined(CONFIG_ISA_ARCV2) && !defined(_CPU_DEFAULT_HS)
-#error "Toolchain not configured for ARCv2 builds"
-#endif
-
 #endif /* __ASEMBLY__ */
 
 #endif /* _ASM_ARC_ARCREGS_H */
diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h
index fbe3587..56aeb5e 100644
--- a/arch/arc/include/asm/cacheflush.h
+++ b/arch/arc/include/asm/cacheflush.h
@@ -85,6 +85,10 @@
  */
 #define PG_dc_clean	PG_arch_1
 
+#define CACHE_COLORS_NUM	4
+#define CACHE_COLORS_MSK	(CACHE_COLORS_NUM - 1)
+#define CACHE_COLOR(addr)	(((unsigned long)(addr) >> (PAGE_SHIFT)) & CACHE_COLORS_MSK)
+
 /*
  * Simple wrapper over config option
  * Bootup code ensures that hardware matches kernel configuration
@@ -94,8 +98,6 @@
 	return IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
 }
 
-#define CACHE_COLOR(addr)	(((unsigned long)(addr) >> (PAGE_SHIFT)) & 1)
-
 /*
  * checks if two addresses (after page aligning) index into same cache set
  */
diff --git a/arch/arc/include/asm/delay.h b/arch/arc/include/asm/delay.h
index 08e7e2a..d5da211 100644
--- a/arch/arc/include/asm/delay.h
+++ b/arch/arc/include/asm/delay.h
@@ -22,10 +22,13 @@
 static inline void __delay(unsigned long loops)
 {
 	__asm__ __volatile__(
-	"	lp  1f	\n"
-	"	nop	\n"
-	"1:		\n"
-	: "+l"(loops));
+	"	mov lp_count, %0	\n"
+	"	lp  1f			\n"
+	"	nop			\n"
+	"1:				\n"
+	:
+        : "r"(loops)
+        : "lp_count");
 }
 
 extern void __bad_udelay(void);
diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
index b5ff87e..aee1a77 100644
--- a/arch/arc/include/asm/entry-arcv2.h
+++ b/arch/arc/include/asm/entry-arcv2.h
@@ -16,6 +16,7 @@
 	;
 	; Now manually save: r12, sp, fp, gp, r25
 
+	PUSH	r30
 	PUSH	r12
 
 	; Saving pt_regs->sp correctly requires some extra work due to the way
@@ -72,6 +73,7 @@
 	POPAX	AUX_USER_SP
 1:
 	POP	r12
+	POP	r30
 
 .endm
 
diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
index ad7860c..51597f3 100644
--- a/arch/arc/include/asm/entry.h
+++ b/arch/arc/include/asm/entry.h
@@ -142,7 +142,7 @@
 
 #ifdef CONFIG_ARC_CURR_IN_REG
 	; Retrieve orig r25 and save it with rest of callee_regs
-	ld.as   r12, [r12, PT_user_r25]
+	ld	r12, [r12, PT_user_r25]
 	PUSH	r12
 #else
 	PUSH	r25
@@ -198,7 +198,7 @@
 
 	; SP is back to start of pt_regs
 #ifdef CONFIG_ARC_CURR_IN_REG
-	st.as   r12, [sp, PT_user_r25]
+	st	r12, [sp, PT_user_r25]
 #endif
 .endm
 
diff --git a/arch/arc/include/asm/irqflags-compact.h b/arch/arc/include/asm/irqflags-compact.h
index c1d3645..4c6eed8 100644
--- a/arch/arc/include/asm/irqflags-compact.h
+++ b/arch/arc/include/asm/irqflags-compact.h
@@ -188,10 +188,10 @@
 .endm
 
 .macro IRQ_ENABLE  scratch
+	TRACE_ASM_IRQ_ENABLE
 	lr	\scratch, [status32]
 	or	\scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
 	flag	\scratch
-	TRACE_ASM_IRQ_ENABLE
 .endm
 
 #endif	/* __ASSEMBLY__ */
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
index 57af2f0..e5fec32 100644
--- a/arch/arc/include/asm/pgtable.h
+++ b/arch/arc/include/asm/pgtable.h
@@ -110,7 +110,7 @@
 #define ___DEF (_PAGE_PRESENT | _PAGE_CACHEABLE)
 
 /* Set of bits not changed in pte_modify */
-#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_SPECIAL)
 
 /* More Abbrevaited helpers */
 #define PAGE_U_NONE     __pgprot(___DEF)
@@ -277,8 +277,7 @@
 
 #define mk_pte(page, prot)	pfn_pte(page_to_pfn(page), prot)
 #define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
-#define pfn_pte(pfn, prot)	(__pte(((pte_t)(pfn) << PAGE_SHIFT) | \
-				 pgprot_val(prot)))
+#define pfn_pte(pfn, prot)	(__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
 #define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 
 /*
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 69095da..47111d5 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -84,7 +84,7 @@
 	unsigned long fp;
 	unsigned long sp;	/* user/kernel sp depending on where we came from  */
 
-	unsigned long r12;
+	unsigned long r12, r30;
 
 	/*------- Below list auto saved by h/w -----------*/
 	unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h
index d1da603..d4d8df7 100644
--- a/arch/arc/include/asm/uaccess.h
+++ b/arch/arc/include/asm/uaccess.h
@@ -83,7 +83,10 @@
 	"2:	;nop\n"				\
 	"	.section .fixup, \"ax\"\n"	\
 	"	.align 4\n"			\
-	"3:	mov %0, %3\n"			\
+	"3:	# return -EFAULT\n"		\
+	"	mov %0, %3\n"			\
+	"	# zero out dst ptr\n"		\
+	"	mov %1,  0\n"			\
 	"	j   2b\n"			\
 	"	.previous\n"			\
 	"	.section __ex_table, \"a\"\n"	\
@@ -101,7 +104,11 @@
 	"2:	;nop\n"				\
 	"	.section .fixup, \"ax\"\n"	\
 	"	.align 4\n"			\
-	"3:	mov %0, %3\n"			\
+	"3:	# return -EFAULT\n"		\
+	"	mov %0, %3\n"			\
+	"	# zero out dst ptr\n"		\
+	"	mov %1,  0\n"			\
+	"	mov %R1, 0\n"			\
 	"	j   2b\n"			\
 	"	.previous\n"			\
 	"	.section __ex_table, \"a\"\n"	\
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index e1b8744..0513180 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -332,10 +332,6 @@
 		pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n");
 	else if (!cpu->extn.fpu_dp && fpu_enabled)
 		panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
-
-	if (is_isa_arcv2() && IS_ENABLED(CONFIG_SMP) && cpu->isa.atomic &&
-	    !IS_ENABLED(CONFIG_ARC_STAR_9000923308))
-		panic("llock/scond livelock workaround missing\n");
 }
 
 /*
diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c
index 004b7f0..257b869 100644
--- a/arch/arc/kernel/signal.c
+++ b/arch/arc/kernel/signal.c
@@ -107,13 +107,13 @@
 	struct user_regs_struct uregs;
 
 	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
-	if (!err)
-		set_current_blocked(&set);
-
 	err |= __copy_from_user(&uregs.scratch,
 				&(sf->uc.uc_mcontext.regs.scratch),
 				sizeof(sf->uc.uc_mcontext.regs.scratch));
+	if (err)
+		return err;
 
+	set_current_blocked(&set);
 	regs->bta	= uregs.scratch.bta;
 	regs->lp_start	= uregs.scratch.lp_start;
 	regs->lp_end	= uregs.scratch.lp_end;
@@ -138,7 +138,7 @@
 	regs->r0	= uregs.scratch.r0;
 	regs->sp	= uregs.scratch.sp;
 
-	return err;
+	return 0;
 }
 
 static inline int is_do_ss_needed(unsigned int magic)
diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c
index 001de4c..11b5095 100644
--- a/arch/arc/kernel/stacktrace.c
+++ b/arch/arc/kernel/stacktrace.c
@@ -142,7 +142,7 @@
 	 * prelogue is setup (callee regs saved and then fp set and not other
 	 * way around
 	 */
-	pr_warn("CONFIG_ARC_DW2_UNWIND needs to be enabled\n");
+	pr_warn_once("CONFIG_ARC_DW2_UNWIND needs to be enabled\n");
 	return 0;
 
 #endif
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index dfad287..dbedc57 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -130,14 +130,17 @@
 		cycle_t  full;
 	} stamp;
 
-
-	__asm__ __volatile(
-	"1:						\n"
-	"	lr		%0, [AUX_RTC_LOW]	\n"
-	"	lr		%1, [AUX_RTC_HIGH]	\n"
-	"	lr		%2, [AUX_RTC_CTRL]	\n"
-	"	bbit0.nt	%2, 31, 1b		\n"
-	: "=r" (stamp.low), "=r" (stamp.high), "=r" (status));
+	/*
+	 * hardware has an internal state machine which tracks readout of
+	 * low/high and updates the CTRL.status if
+	 *  - interrupt/exception taken between the two reads
+	 *  - high increments after low has been read
+	 */
+	do {
+		stamp.low = read_aux_reg(AUX_RTC_LOW);
+		stamp.high = read_aux_reg(AUX_RTC_HIGH);
+		status = read_aux_reg(AUX_RTC_CTRL);
+	} while (!(status & _BITUL(31)));
 
 	return stamp.full;
 }
diff --git a/arch/arc/kernel/unaligned.c b/arch/arc/kernel/unaligned.c
index abd961f..5f69c3b 100644
--- a/arch/arc/kernel/unaligned.c
+++ b/arch/arc/kernel/unaligned.c
@@ -241,8 +241,9 @@
 	if (state.fault)
 		goto fault;
 
+	/* clear any remanants of delay slot */
 	if (delay_mode(regs)) {
-		regs->ret = regs->bta;
+		regs->ret = regs->bta & ~1U;
 		regs->status32 &= ~STATUS_DE_MASK;
 	} else {
 		regs->ret += state.instr_len;
diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c
index ff7ff6c..d81b6d7 100644
--- a/arch/arc/mm/cache.c
+++ b/arch/arc/mm/cache.c
@@ -914,6 +914,15 @@
 
 	printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
 
+	/*
+	 * Only master CPU needs to execute rest of function:
+	 *  - Assume SMP so all cores will have same cache config so
+	 *    any geomtry checks will be same for all
+	 *  - IOC setup / dma callbacks only need to be setup once
+	 */
+	if (cpu)
+		return;
+
 	if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) {
 		struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache;
 
@@ -951,11 +960,16 @@
 		/* check for D-Cache aliasing on ARCompact: ARCv2 has PIPT */
 		if (is_isa_arcompact()) {
 			int handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
+			int num_colors = dc->sz_k/dc->assoc/TO_KB(PAGE_SIZE);
 
-			if (dc->alias && !handled)
-				panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
-			else if (!dc->alias && handled)
+			if (dc->alias) {
+				if (!handled)
+					panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
+				if (CACHE_COLORS_NUM != num_colors)
+					panic("CACHE_COLORS_NUM not optimized for config\n");
+			} else if (!dc->alias && handled) {
 				panic("Disable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
+			}
 		}
 	}
 
diff --git a/arch/arc/mm/mmap.c b/arch/arc/mm/mmap.c
index 2e06d56..cf4ae69 100644
--- a/arch/arc/mm/mmap.c
+++ b/arch/arc/mm/mmap.c
@@ -64,7 +64,7 @@
 
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 05450ca..586134e0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -33,6 +33,7 @@
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT)
 	select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
+	select HAVE_ARCH_HARDENED_USERCOPY
 	select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32
 	select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32
 	select HAVE_ARCH_MMAP_RND_BITS if MMU
@@ -1862,6 +1863,21 @@
 	  This was deprecated in 2001 and announced to live on for 5 years.
 	  Some old boot loaders still use this way.
 
+config BUILD_ARM_APPENDED_DTB_IMAGE
+	bool "Build a concatenated zImage/dtb by default"
+	depends on OF
+	help
+	  Enabling this option will cause a concatenated zImage and list of
+	  DTBs to be built by default (instead of a standalone zImage.)
+	  The image will built in arch/arm/boot/zImage-dtb
+
+config BUILD_ARM_APPENDED_DTB_IMAGE_NAMES
+	string "Default dtb names"
+	depends on BUILD_ARM_APPENDED_DTB_IMAGE
+	help
+	  Space separated list of names of dtbs to append when
+	  building a concatenated zImage-dtb.
+
 # Compressed boot loader in ROM.  Yes, we really want to ask about
 # TEXT and BSS so we preserve their values in the config files.
 config ZBOOT_ROM_TEXT
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 2c2b28e..88e479c 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -296,6 +296,8 @@
 # Default target when executing plain make
 ifeq ($(CONFIG_XIP_KERNEL),y)
 KBUILD_IMAGE := xipImage
+else ifeq ($(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE),y)
+KBUILD_IMAGE := zImage-dtb
 else
 KBUILD_IMAGE := zImage
 endif
@@ -346,6 +348,9 @@
 	$(Q)$(MAKE) $(build)=arch/arm/vdso $@
 endif
 
+zImage-dtb: vmlinux scripts dtbs
+	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
index 3c79f85..ad7a025 100644
--- a/arch/arm/boot/.gitignore
+++ b/arch/arm/boot/.gitignore
@@ -4,3 +4,4 @@
 bootpImage
 uImage
 *.dtb
+zImage-dtb
\ No newline at end of file
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 9eca7ae..4a04ed3 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -14,6 +14,7 @@
 ifneq ($(MACHINE),)
 include $(MACHINE)/Makefile.boot
 endif
+include $(srctree)/arch/arm/boot/dts/Makefile
 
 # Note: the following conditions must always be true:
 #   ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
@@ -27,6 +28,14 @@
 
 targets := Image zImage xipImage bootpImage uImage
 
+DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES))
+ifneq ($(DTB_NAMES),)
+DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
+else
+DTB_LIST := $(dtb-y)
+endif
+DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST))
+
 ifeq ($(CONFIG_XIP_KERNEL),y)
 
 $(obj)/xipImage: vmlinux FORCE
@@ -55,6 +64,10 @@
 	$(call if_changed,objcopy)
 	@$(kecho) '  Kernel: $@ is ready'
 
+$(obj)/zImage-dtb:	$(obj)/zImage $(DTB_OBJS) FORCE
+	$(call if_changed,cat)
+	@echo '  Kernel: $@ is ready'
+
 endif
 
 ifneq ($(LOADADDR),)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 8cfbc4a..3f9a9eb 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -106,14 +106,6 @@
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
-ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
-CFLAGS_atags_to_fdt.o := -fno-stack-protector
-CFLAGS_fdt.o := -fno-stack-protector
-CFLAGS_fdt_ro.o := -fno-stack-protector
-CFLAGS_fdt_rw.o := -fno-stack-protector
-CFLAGS_fdt_wip.o := -fno-stack-protector
-endif
-
 ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj)
 asflags-y := -DZIMAGE
 
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index ae85dcd..d2e43b0 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -776,7 +776,7 @@
 		orrne	r0, r0, #1		@ MMU enabled
 		movne	r1, #0xfffffffd		@ domain 0 = client
 		bic     r6, r6, #1 << 31        @ 32-bit translation system
-		bic     r6, r6, #3 << 0         @ use only ttbr0
+		bic     r6, r6, #(7 << 0) | (1 << 4)	@ use only ttbr0
 		mcrne	p15, 0, r3, c2, c0, 0	@ load page table pointer
 		mcrne	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
 		mcr	p15, 0, r0, c7, c5, 4	@ ISB
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 9958c2f..97d1b37 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -512,8 +512,6 @@
 dtb-$(CONFIG_ARCH_REALVIEW) += \
 	arm-realview-pb1176.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += \
-	rk3036-evb.dtb \
-	rk3036-kylin.dtb \
 	rk3066a-bqcurie2.dtb \
 	rk3066a-marsboard.dtb \
 	rk3066a-rayeager.dtb \
@@ -784,5 +782,15 @@
 dtstree		:= $(srctree)/$(src)
 dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
 
-always		:= $(dtb-y)
+DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES))
+ifneq ($(DTB_NAMES),)
+DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
+else
+DTB_LIST := $(dtb-y)
+endif
+
+targets += dtbs dtbs_install
+targets += $(DTB_LIST)
+
+always		:= $(DTB_LIST)
 clean-files	:= *.dtb
diff --git a/arch/arm/boot/dts/armada-385-linksys.dtsi b/arch/arm/boot/dts/armada-385-linksys.dtsi
index 85d2c37..22f7a13 100644
--- a/arch/arm/boot/dts/armada-385-linksys.dtsi
+++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
@@ -58,8 +58,8 @@
 	soc {
 		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
 			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
-			  MBUS_ID(0x09, 0x09) 0 0xf1100000 0x10000
-			  MBUS_ID(0x09, 0x05) 0 0xf1110000 0x10000>;
+			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
+			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>;
 
 		internal-regs {
 
@@ -245,7 +245,7 @@
 		button@2 {
 			label = "Factory Reset Button";
 			linux,code = <KEY_RESTART>;
-			gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+			gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
 		};
 	};
 
@@ -260,7 +260,7 @@
 		};
 
 		sata {
-			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+			gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
 			default-state = "off";
 		};
 	};
@@ -313,7 +313,7 @@
 
 &pinctrl {
 	keys_pin: keys-pin {
-		marvell,pins = "mpp24", "mpp47";
+		marvell,pins = "mpp24", "mpp29";
 		marvell,function = "gpio";
 	};
 
diff --git a/arch/arm/boot/dts/armada-390.dtsi b/arch/arm/boot/dts/armada-390.dtsi
index 094e39c..6cd18d8 100644
--- a/arch/arm/boot/dts/armada-390.dtsi
+++ b/arch/arm/boot/dts/armada-390.dtsi
@@ -47,6 +47,8 @@
 #include "armada-39x.dtsi"
 
 / {
+	compatible = "marvell,armada390";
+
 	soc {
 		internal-regs {
 			pinctrl@18000 {
@@ -54,4 +56,5 @@
 				reg = <0x18000 0x20>;
 			};
 		};
+	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
index b89e6cf..7a46154 100644
--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
+++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
@@ -304,13 +304,13 @@
 		button@1 {
 			label = "WPS";
 			linux,code = <KEY_WPS_BUTTON>;
-			gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+			gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
 		};
 
 		button@2 {
 			label = "Factory Reset Button";
 			linux,code = <KEY_RESTART>;
-			gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+			gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index e74df32..20618a8 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -122,6 +122,8 @@
 			uart1: serial@f8020000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_uart1_default>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
 				status = "okay";
 			};
 
diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
index f3e2b96..0bd325c 100644
--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
@@ -162,9 +162,10 @@
 			};
 
 			adc0: adc@f8018000 {
+				atmel,adc-vref = <3300>;
+				atmel,adc-channels-used = <0xfe>;
 				pinctrl-0 = <
 					&pinctrl_adc0_adtrg
-					&pinctrl_adc0_ad0
 					&pinctrl_adc0_ad1
 					&pinctrl_adc0_ad2
 					&pinctrl_adc0_ad3
@@ -172,8 +173,6 @@
 					&pinctrl_adc0_ad5
 					&pinctrl_adc0_ad6
 					&pinctrl_adc0_ad7
-					&pinctrl_adc0_ad8
-					&pinctrl_adc0_ad9
 					>;
 				status = "okay";
 			};
diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
index da84e65..e27024c 100644
--- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
@@ -110,6 +110,8 @@
 			};
 
 			usart3: serial@fc00c000 {
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
 				status = "okay";
 			};
 
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 0827d59..cd0cd5f 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -106,7 +106,7 @@
 
 			pmc: pmc@fffffc00 {
 				compatible = "atmel,at91sam9x5-pmc", "syscon";
-				reg = <0xfffffc00 0x100>;
+				reg = <0xfffffc00 0x200>;
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
 				interrupt-controller;
 				#address-cells = <1>;
diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi
index 6f50f67..de8ac99 100644
--- a/arch/arm/boot/dts/bcm5301x.dtsi
+++ b/arch/arm/boot/dts/bcm5301x.dtsi
@@ -54,14 +54,14 @@
 		timer@0200 {
 			compatible = "arm,cortex-a9-global-timer";
 			reg = <0x0200 0x100>;
-			interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_PPI 11 IRQ_TYPE_EDGE_RISING>;
 			clocks = <&clk_periph>;
 		};
 
 		local-timer@0600 {
 			compatible = "arm,cortex-a9-twd-timer";
 			reg = <0x0600 0x100>;
-			interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_PPI 13 IRQ_TYPE_EDGE_RISING>;
 			clocks = <&clk_periph>;
 		};
 
diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
index 4f935ad..6881757 100644
--- a/arch/arm/boot/dts/da850-evm.dts
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -85,6 +85,7 @@
 				#size-cells = <1>;
 				compatible = "m25p64";
 				spi-max-frequency = <30000000>;
+				m25p,fast-read;
 				reg = <0>;
 				partition@0 {
 					label = "U-Boot-SPL";
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index a50be64..59411e4 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -298,6 +298,8 @@
 		compatible = "maxim,max8997-pmic";
 
 		reg = <0x66>;
+		interrupt-parent = <&gpx0>;
+		interrupts = <7 0>;
 
 		max8997,pmic-buck1-uses-gpio-dvs;
 		max8997,pmic-buck2-uses-gpio-dvs;
diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi
index 5fdb222..cbe5fd5 100644
--- a/arch/arm/boot/dts/imx31.dtsi
+++ b/arch/arm/boot/dts/imx31.dtsi
@@ -30,11 +30,11 @@
 		};
 	};
 
-	avic: avic-interrupt-controller@60000000 {
+	avic: interrupt-controller@68000000 {
 		compatible = "fsl,imx31-avic", "fsl,avic";
 		interrupt-controller;
 		#interrupt-cells = <1>;
-		reg = <0x60000000 0x100000>;
+		reg = <0x68000000 0x100000>;
 	};
 
 	soc {
@@ -110,13 +110,6 @@
 				interrupts = <19>;
 				clocks = <&clks 25>;
 			};
-
-			clks: ccm@53f80000{
-				compatible = "fsl,imx31-ccm";
-				reg = <0x53f80000 0x4000>;
-				interrupts = <0 31 0x04 0 53 0x04>;
-				#clock-cells = <1>;
-			};
 		};
 
 		aips@53f00000 { /* AIPS2 */
@@ -126,6 +119,13 @@
 			reg = <0x53f00000 0x100000>;
 			ranges;
 
+			clks: ccm@53f80000{
+				compatible = "fsl,imx31-ccm";
+				reg = <0x53f80000 0x4000>;
+				interrupts = <31>, <53>;
+				#clock-cells = <1>;
+			};
+
 			gpt: timer@53f90000 {
 				compatible = "fsl,imx31-gpt";
 				reg = <0x53f90000 0x4000>;
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 4b0ec07..8ca9217 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -30,7 +30,7 @@
 				/* kHz    uV */
 				996000  1250000
 				792000  1175000
-				396000  1075000
+				396000  1150000
 			>;
 			fsl,soc-operating-points = <
 				/* ARM kHz  SOC-PU uV */
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
index a35d54f..ddfdb75 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
@@ -319,8 +319,6 @@
 		compatible = "fsl,imx6q-nitrogen6_max-sgtl5000",
 			     "fsl,imx-audio-sgtl5000";
 		model = "imx6q-nitrogen6_max-sgtl5000";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_sgtl5000>;
 		ssi-controller = <&ssi1>;
 		audio-codec = <&codec>;
 		audio-routing =
@@ -401,6 +399,8 @@
 
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_sgtl5000>;
 		reg = <0x0a>;
 		clocks = <&clks 201>;
 		VDDA-supply = <&reg_2p5v>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 2b6cc8b..e6af41c 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -221,7 +221,7 @@
 					clocks = <&clks IMX6QDL_CLK_SPDIF_GCLK>, <&clks IMX6QDL_CLK_OSC>,
 						 <&clks IMX6QDL_CLK_SPDIF>, <&clks IMX6QDL_CLK_ASRC>,
 						 <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_ESAI_EXTAL>,
-						 <&clks IMX6QDL_CLK_IPG>, <&clks IMX6QDL_CLK_MLB>,
+						 <&clks IMX6QDL_CLK_IPG>, <&clks IMX6QDL_CLK_DUMMY>,
 						 <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_SPBA>;
 					clock-names = "core",  "rxtx0",
 						      "rxtx1", "rxtx2",
diff --git a/arch/arm/boot/dts/kirkwood-ib62x0.dts b/arch/arm/boot/dts/kirkwood-ib62x0.dts
index bfa5edd..2c1e7f0 100644
--- a/arch/arm/boot/dts/kirkwood-ib62x0.dts
+++ b/arch/arm/boot/dts/kirkwood-ib62x0.dts
@@ -113,7 +113,7 @@
 
 	partition@e0000 {
 		label = "u-boot environment";
-		reg = <0xe0000 0x100000>;
+		reg = <0xe0000 0x20000>;
 	};
 
 	partition@100000 {
diff --git a/arch/arm/boot/dts/omap3-overo-base.dtsi b/arch/arm/boot/dts/omap3-overo-base.dtsi
index a29ad16..64c5af3 100644
--- a/arch/arm/boot/dts/omap3-overo-base.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-base.dtsi
@@ -223,7 +223,9 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x00000000 0x20000000>;
+	ranges = <0 0 0x30000000 0x1000000>,	/* CS0 */
+		 <4 0 0x2b000000 0x1000000>,	/* CS4 */
+		 <5 0 0x2c000000 0x1000000>;	/* CS5 */
 
 	nand@0,0 {
 		linux,mtd-name= "micron,mt29c4g96maz";
diff --git a/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi b/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi
index 17b82f8..6404778 100644
--- a/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi
@@ -55,8 +55,6 @@
 #include "omap-gpmc-smsc9221.dtsi"
 
 &gpmc {
-	ranges = <5 0 0x2c000000 0x1000000>;	/* CS5 */
-
 	ethernet@gpmc {
 		reg = <5 0 0xff>;
 		interrupt-parent = <&gpio6>;
diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
index 9e24b6a..1b304e2 100644
--- a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
@@ -27,8 +27,6 @@
 #include "omap-gpmc-smsc9221.dtsi"
 
 &gpmc {
-	ranges = <5 0 0x2c000000 0x1000000>;	/* CS5 */
-
 	ethernet@gpmc {
 		reg = <5 0 0xff>;
 		interrupt-parent = <&gpio6>;
diff --git a/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi
index 334109e..82e98ee 100644
--- a/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi
@@ -15,9 +15,6 @@
 #include "omap-gpmc-smsc9221.dtsi"
 
 &gpmc {
-	ranges = <4 0 0x2b000000 0x1000000>,	/* CS4 */
-		 <5 0 0x2c000000 0x1000000>;	/* CS5 */
-
 	smsc1: ethernet@gpmc {
 		reg = <5 0 0xff>;
 		interrupt-parent = <&gpio6>;
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index a4c1762..e00d50e 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -5,6 +5,7 @@
 #include <dt-bindings/reset/qcom,gcc-msm8960.h>
 #include <dt-bindings/clock/qcom,mmcc-msm8960.h>
 #include <dt-bindings/soc/qcom,gsbi.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 / {
 	model = "Qualcomm APQ8064";
@@ -354,22 +355,50 @@
 
 					compatible = "qcom,pm8921-gpio";
 					reg = <0x150>;
-					interrupts = <192 1>, <193 1>, <194 1>,
-						     <195 1>, <196 1>, <197 1>,
-						     <198 1>, <199 1>, <200 1>,
-						     <201 1>, <202 1>, <203 1>,
-						     <204 1>, <205 1>, <206 1>,
-						     <207 1>, <208 1>, <209 1>,
-						     <210 1>, <211 1>, <212 1>,
-						     <213 1>, <214 1>, <215 1>,
-						     <216 1>, <217 1>, <218 1>,
-						     <219 1>, <220 1>, <221 1>,
-						     <222 1>, <223 1>, <224 1>,
-						     <225 1>, <226 1>, <227 1>,
-						     <228 1>, <229 1>, <230 1>,
-						     <231 1>, <232 1>, <233 1>,
-						     <234 1>, <235 1>;
-
+					interrupts = <192 IRQ_TYPE_NONE>,
+						     <193 IRQ_TYPE_NONE>,
+						     <194 IRQ_TYPE_NONE>,
+						     <195 IRQ_TYPE_NONE>,
+						     <196 IRQ_TYPE_NONE>,
+						     <197 IRQ_TYPE_NONE>,
+						     <198 IRQ_TYPE_NONE>,
+						     <199 IRQ_TYPE_NONE>,
+						     <200 IRQ_TYPE_NONE>,
+						     <201 IRQ_TYPE_NONE>,
+						     <202 IRQ_TYPE_NONE>,
+						     <203 IRQ_TYPE_NONE>,
+						     <204 IRQ_TYPE_NONE>,
+						     <205 IRQ_TYPE_NONE>,
+						     <206 IRQ_TYPE_NONE>,
+						     <207 IRQ_TYPE_NONE>,
+						     <208 IRQ_TYPE_NONE>,
+						     <209 IRQ_TYPE_NONE>,
+						     <210 IRQ_TYPE_NONE>,
+						     <211 IRQ_TYPE_NONE>,
+						     <212 IRQ_TYPE_NONE>,
+						     <213 IRQ_TYPE_NONE>,
+						     <214 IRQ_TYPE_NONE>,
+						     <215 IRQ_TYPE_NONE>,
+						     <216 IRQ_TYPE_NONE>,
+						     <217 IRQ_TYPE_NONE>,
+						     <218 IRQ_TYPE_NONE>,
+						     <219 IRQ_TYPE_NONE>,
+						     <220 IRQ_TYPE_NONE>,
+						     <221 IRQ_TYPE_NONE>,
+						     <222 IRQ_TYPE_NONE>,
+						     <223 IRQ_TYPE_NONE>,
+						     <224 IRQ_TYPE_NONE>,
+						     <225 IRQ_TYPE_NONE>,
+						     <226 IRQ_TYPE_NONE>,
+						     <227 IRQ_TYPE_NONE>,
+						     <228 IRQ_TYPE_NONE>,
+						     <229 IRQ_TYPE_NONE>,
+						     <230 IRQ_TYPE_NONE>,
+						     <231 IRQ_TYPE_NONE>,
+						     <232 IRQ_TYPE_NONE>,
+						     <233 IRQ_TYPE_NONE>,
+						     <234 IRQ_TYPE_NONE>,
+						     <235 IRQ_TYPE_NONE>;
 					gpio-controller;
 					#gpio-cells = <2>;
 
@@ -381,9 +410,18 @@
 					gpio-controller;
 					#gpio-cells = <2>;
 					interrupts =
-					<128 1>, <129 1>, <130 1>, <131 1>,
-					<132 1>, <133 1>, <134 1>, <135 1>,
-					<136 1>, <137 1>, <138 1>, <139 1>;
+					<128 IRQ_TYPE_NONE>,
+					<129 IRQ_TYPE_NONE>,
+					<130 IRQ_TYPE_NONE>,
+					<131 IRQ_TYPE_NONE>,
+					<132 IRQ_TYPE_NONE>,
+					<133 IRQ_TYPE_NONE>,
+					<134 IRQ_TYPE_NONE>,
+					<135 IRQ_TYPE_NONE>,
+					<136 IRQ_TYPE_NONE>,
+					<137 IRQ_TYPE_NONE>,
+					<138 IRQ_TYPE_NONE>,
+					<139 IRQ_TYPE_NONE>;
 				};
 
 				rtc@11d {
diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi
index a9977d6..1696535 100644
--- a/arch/arm/boot/dts/r8a7794.dtsi
+++ b/arch/arm/boot/dts/r8a7794.dtsi
@@ -1023,7 +1023,7 @@
 		mstp7_clks: mstp7_clks@e615014c {
 			compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
-			clocks = <&mp_clk>, <&mp_clk>,
+			clocks = <&mp_clk>, <&hp_clk>,
 				 <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>,
 				 <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>;
 			#clock-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3036-evb.dts b/arch/arm/boot/dts/rk3036-evb.dts
deleted file mode 100644
index d7d3719..0000000
--- a/arch/arm/boot/dts/rk3036-evb.dts
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *  Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/dts-v1/;
-
-#include "rk3036.dtsi"
-
-/ {
-	model = "Rockchip RK3036 Evaluation board";
-	compatible = "rockchip,rk3036-evb", "rockchip,rk3036";
-};
-
-&emac {
-	pinctrl-names = "default";
-	pinctrl-0 = <&emac_xfer>, <&emac_mdio>, <&rmii_rst>;
-	phy = <&phy0>;
-	status = "okay";
-
-	phy0: ethernet-phy@0 {
-		reg = <0>;
-	};
-};
-
-&i2c1 {
-	status = "okay";
-
-	hym8563: hym8563@51 {
-		compatible = "haoyu,hym8563";
-		reg = <0x51>;
-		#clock-cells = <0>;
-		clock-frequency = <32768>;
-		clock-output-names = "xin32k";
-	};
-};
-
-&uart2 {
-	status = "okay";
-};
-
-&pinctrl {
-	pcfg_output_high: pcfg-output-high {
-		output-high;
-	};
-
-	emac {
-		rmii_rst: rmii-rst {
-			rockchip,pins = <2 22 RK_FUNC_GPIO &pcfg_output_high>;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/rk3036-kylin.dts b/arch/arm/boot/dts/rk3036-kylin.dts
deleted file mode 100644
index 84911b4..0000000
--- a/arch/arm/boot/dts/rk3036-kylin.dts
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *  Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/dts-v1/;
-
-#include "rk3036.dtsi"
-
-/ {
-	model = "Rockchip RK3036 KylinBoard";
-	compatible = "rockchip,rk3036-kylin", "rockchip,rk3036";
-
-	bcmdhd_wlan_0: bcmdhd_wlan@0 {
-		compatible = "android,bcmdhd_wlan";
-		gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
-		wlreg_on-supply = <&sdio_pwrseq>;
-	};
-
-	leds: gpio-leds {
-		compatible = "gpio-leds";
-
-		work {
-			gpios = <&gpio2 30 GPIO_ACTIVE_HIGH>;
-			label = "kylin:red:led";
-			pinctrl-names = "default";
-			pinctrl-0 = <&led_ctl>;
-		};
-	};
-
-	sdio_pwrseq: sdio-pwrseq {
-		compatible = "mmc-pwrseq-simple";
-		pinctrl-names = "default";
-		pinctrl-0 = <&bt_wake_h>;
-
-		/*
-		 * On the module itself this is one of these (depending
-		 * on the actual card populated):
-		 * - SDIO_RESET_L_WL_REG_ON
-		 * - SDIO_RESET_L_WL_RST
-		 * - SDIO_RESET_L_BT_EN
-		 */
-		reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>, /* WL_REG_ON */
-			      <&gpio0 27 GPIO_ACTIVE_LOW>, /* WL_RST */
-			      <&gpio2 9  GPIO_ACTIVE_LOW>; /* BT_EN */
-	};
-
-	sound {
-		compatible = "simple-audio-card";
-		simple-audio-card,format = "i2s";
-		simple-audio-card,name = "rockchip,rt5616-codec";
-		simple-audio-card,mclk-fs = <512>;
-		simple-audio-card,widgets =
-			"Microphone", "Microphone Jack",
-			"Headphone", "Headphone Jack";
-		simple-audio-card,routing =
-			"MIC1", "Microphone Jack",
-			"MIC2", "Microphone Jack",
-			"Microphone Jack", "micbias1",
-			"Headphone Jack", "HPOL",
-			"Headphone Jack", "HPOR";
-
-		simple-audio-card,cpu {
-			sound-dai = <&i2s>;
-		};
-
-		simple-audio-card,codec {
-			sound-dai = <&rt5616>;
-		};
-	};
-
-	vcc_sys: vsys-regulator {
-		compatible = "regulator-fixed";
-		regulator-name = "vcc_sys";
-		regulator-min-microvolt = <5000000>;
-		regulator-max-microvolt = <5000000>;
-		regulator-always-on;
-		regulator-boot-on;
-	};
-};
-
-&acodec {
-	status = "okay";
-};
-
-&emac {
-	pinctrl-names = "default";
-	pinctrl-0 = <&emac_xfer>, <&emac_mdio>, <&rmii_rst>;
-	phy = <&phy0>;
-	status = "okay";
-
-	phy0: ethernet-phy@0 {
-		reg = <0>;
-	};
-};
-
-&emmc {
-	status = "okay";
-};
-
-&hdmi {
-	status = "okay";
-};
-
-&i2c1 {
-	clock-frequency = <400000>;
-
-	status = "okay";
-
-	rk808: pmic@1b {
-		compatible = "rockchip,rk808";
-		reg = <0x1b>;
-		interrupt-parent = <&gpio2>;
-		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pmic_int &global_pwroff>;
-		rockchip,system-power-controller;
-		wakeup-source;
-		#clock-cells = <1>;
-		clock-output-names = "xin32k", "rk808-clkout2";
-
-		vcc1-supply = <&vcc_sys>;
-		vcc2-supply = <&vcc_sys>;
-		vcc3-supply = <&vcc_sys>;
-		vcc4-supply = <&vcc_sys>;
-		vcc6-supply = <&vcc_sys>;
-		vcc7-supply = <&vcc_sys>;
-		vcc8-supply = <&vcc_18>;
-		vcc9-supply = <&vcc_io>;
-		vcc10-supply = <&vcc_io>;
-		vcc11-supply = <&vcc_sys>;
-		vcc12-supply = <&vcc_io>;
-		vddio-supply = <&vccio_pmu>;
-
-		regulators {
-			vdd_cpu: DCDC_REG1 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <750000>;
-				regulator-max-microvolt = <1350000>;
-				regulator-name = "vdd_arm";
-				regulator-state-mem {
-					regulator-off-in-suspend;
-				};
-			};
-
-			vdd_gpu: DCDC_REG2 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <850000>;
-				regulator-max-microvolt = <1250000>;
-				regulator-name = "vdd_gpu";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-					regulator-suspend-microvolt = <1000000>;
-				};
-			};
-
-			vcc_ddr: DCDC_REG3 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-name = "vcc_ddr";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-				};
-			};
-
-			vcc_io: DCDC_REG4 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-name = "vcc_io";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-					regulator-suspend-microvolt = <3300000>;
-				};
-			};
-
-			vccio_pmu: LDO_REG1 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-name = "vccio_pmu";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-					regulator-suspend-microvolt = <3300000>;
-				};
-			};
-
-			vcc_tp: LDO_REG2 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-name = "vcc_tp";
-				regulator-state-mem {
-					regulator-off-in-suspend;
-				};
-			};
-
-			vdd_10: LDO_REG3 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1000000>;
-				regulator-max-microvolt = <1000000>;
-				regulator-name = "vdd_10";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-					regulator-suspend-microvolt = <1000000>;
-				};
-			};
-
-			vcc18_lcd: LDO_REG4 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-name = "vcc18_lcd";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-					regulator-suspend-microvolt = <1800000>;
-				};
-			};
-
-			vccio_sd: LDO_REG5 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-name = "vccio_sd";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-					regulator-suspend-microvolt = <3300000>;
-				};
-			};
-
-			vout5: LDO_REG6 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <2500000>;
-				regulator-name = "vout5";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-					regulator-suspend-microvolt = <1800000>;
-				};
-			};
-
-			vcc_18: LDO_REG7 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-name = "vcc_18";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-					regulator-suspend-microvolt = <1800000>;
-				};
-			};
-
-			vcca_codec: LDO_REG8 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-name = "vcca_codec";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-					regulator-suspend-microvolt = <1800000>;
-				};
-			};
-
-			vcc_wl: SWITCH_REG1 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-name = "vcc_wl";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-				};
-			};
-
-			vcc_lcd: SWITCH_REG2 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-name = "vcc_lcd";
-				regulator-state-mem {
-					regulator-on-in-suspend;
-				};
-			};
-		};
-	};
-};
-
-&i2c2 {
-	status = "okay";
-
-	rt5616: rt5616@1b {
-		compatible = "rt5616";
-		reg = <0x1b>;
-		clocks = <&cru SCLK_I2S_OUT>;
-		clock-names = "mclk";
-		#sound-dai-cells = <0>;
-	};
-};
-
-&i2s {
-	#sound-dai-cells = <0>;
-	status = "okay";
-};
-
-&sdio {
-	status = "okay";
-
-	broken-cd;
-	bus-width = <4>;
-	cap-sd-highspeed;
-	cap-sdio-irq;
-	default-sample-phase = <90>;
-	keep-power-in-suspend;
-	mmc-pwrseq = <&sdio_pwrseq>;
-	non-removable;
-	num-slots = <1>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&sdio_clk &sdio_cmd &sdio_bus4>;
-	sd-uhs-sdr12;
-	sd-uhs-sdr25;
-	sd-uhs-sdr50;
-	sd-uhs-sdr104;
-};
-
-&sdmmc {
-	bus-width = <4>;
-	cap-mmc-highspeed;
-	cap-sd-highspeed;
-	card-detect-delay = <200>;
-	disable-wp;
-	num-slots = <1>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
-};
-
-&uart0 {
-	status = "okay";
-};
-
-&uart2 {
-	status = "okay";
-};
-
-&usb_host {
-	status = "okay";
-};
-
-&usb_otg {
-	status = "okay";
-};
-
-&vop {
-	status = "okay";
-};
-
-&vop_mmu {
-	status = "okay";
-};
-
-&pinctrl {
-	pcfg_output_high: pcfg-output-high {
-		output-high;
-	};
-
-	emac {
-		rmii_rst: rmii-rst {
-			rockchip,pins = <2 22 RK_FUNC_GPIO &pcfg_output_high>;
-		};
-	};
-
-	leds {
-		led_ctl: led-ctl {
-			rockchip,pins = <2 30 RK_FUNC_GPIO &pcfg_pull_none>;
-		};
-	};
-
-	pmic {
-		pmic_int: pmic-int {
-			rockchip,pins = <2 2 RK_FUNC_GPIO &pcfg_pull_default>;
-		};
-	};
-
-	sdio {
-		bt_wake_h: bt-wake-h {
-			rockchip,pins = <2 8 RK_FUNC_GPIO &pcfg_pull_default>;
-		};
-	};
-
-	sdmmc {
-		sdmmc_pwr: sdmmc-pwr {
-			rockchip,pins = <2 28 RK_FUNC_GPIO &pcfg_pull_none>;
-		};
-	};
-
-	sleep {
-		global_pwroff: global-pwroff {
-			rockchip,pins = <2 7 RK_FUNC_1 &pcfg_pull_none>;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
deleted file mode 100644
index aaab5fd..0000000
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/rockchip.h>
-#include <dt-bindings/clock/rk3036-cru.h>
-#include "skeleton.dtsi"
-
-/ {
-	compatible = "rockchip,rk3036";
-
-	interrupt-parent = <&gic>;
-
-	aliases {
-		i2c0 = &i2c0;
-		i2c1 = &i2c1;
-		i2c2 = &i2c2;
-		mshc0 = &emmc;
-		mshc1 = &sdmmc;
-		mshc2 = &sdio;
-		serial0 = &uart0;
-		serial1 = &uart1;
-		serial2 = &uart2;
-		spi = &spi;
-	};
-
-	memory {
-		device_type = "memory";
-		reg = <0x60000000 0x40000000>;
-	};
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		enable-method = "rockchip,rk3036-smp";
-
-		cpu0: cpu@f00 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a7";
-			reg = <0xf00>;
-			resets = <&cru SRST_CORE0>;
-			operating-points = <
-				/* KHz    uV */
-				 816000 1000000
-			>;
-			clock-latency = <40000>;
-			clocks = <&cru ARMCLK>;
-		};
-
-		cpu1: cpu@f01 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a7";
-			reg = <0xf01>;
-			resets = <&cru SRST_CORE1>;
-		};
-	};
-
-	amba {
-		compatible = "arm,amba-bus";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		pdma: pdma@20078000 {
-			compatible = "arm,pl330", "arm,primecell";
-			reg = <0x20078000 0x4000>;
-			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
-			#dma-cells = <1>;
-			arm,pl330-broken-no-flushp;
-			clocks = <&cru ACLK_DMAC2>;
-			clock-names = "apb_pclk";
-		};
-	};
-
-	arm-pmu {
-		compatible = "arm,cortex-a7-pmu";
-		interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-affinity = <&cpu0>, <&cpu1>;
-	};
-
-	display-subsystem {
-		compatible = "rockchip,display-subsystem";
-		ports = <&vop_out>;
-	};
-
-	timer {
-		compatible = "arm,armv7-timer";
-		arm,cpu-registers-not-fw-configured;
-		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
-			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
-			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
-			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
-		clock-frequency = <24000000>;
-	};
-
-	xin24m: oscillator {
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		clock-output-names = "xin24m";
-		#clock-cells = <0>;
-	};
-
-	bus_intmem@10080000 {
-		compatible = "mmio-sram";
-		reg = <0x10080000 0x2000>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges = <0 0x10080000 0x2000>;
-
-		smp-sram@0 {
-			compatible = "rockchip,rk3066-smp-sram";
-			reg = <0x00 0x10>;
-		};
-	};
-
-	vop: vop@10118000 {
-		compatible = "rockchip,rk3036-vop";
-		reg = <0x10118000 0x19c>;
-		interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru ACLK_LCDC>, <&cru SCLK_LCDC>, <&cru HCLK_LCDC>;
-		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
-		resets = <&cru SRST_LCDC1_A>, <&cru SRST_LCDC1_H>, <&cru SRST_LCDC1_D>;
-		reset-names = "axi", "ahb", "dclk";
-		iommus = <&vop_mmu>;
-		status = "disabled";
-
-		vop_out: port {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			vop_out_hdmi: endpoint@0 {
-				reg = <0>;
-				remote-endpoint = <&hdmi_in_vop>;
-			};
-		};
-	};
-
-	vop_mmu: iommu@10118300 {
-		compatible = "rockchip,iommu";
-		reg = <0x10118300 0x100>;
-		interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-names = "vop_mmu";
-		#iommu-cells = <0>;
-		status = "disabled";
-	};
-
-	gic: interrupt-controller@10139000 {
-		compatible = "arm,gic-400";
-		interrupt-controller;
-		#interrupt-cells = <3>;
-		#address-cells = <0>;
-
-		reg = <0x10139000 0x1000>,
-		      <0x1013a000 0x1000>,
-		      <0x1013c000 0x2000>,
-		      <0x1013e000 0x2000>;
-		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
-	};
-
-	usb_otg: usb@10180000 {
-		compatible = "rockchip,rk3288-usb", "rockchip,rk3066-usb",
-				"snps,dwc2";
-		reg = <0x10180000 0x40000>;
-		interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru HCLK_OTG0>;
-		clock-names = "otg";
-		dr_mode = "otg";
-		g-np-tx-fifo-size = <16>;
-		g-rx-fifo-size = <275>;
-		g-tx-fifo-size = <256 128 128 64 64 32>;
-		g-use-dma;
-		status = "disabled";
-	};
-
-	usb_host: usb@101c0000 {
-		compatible = "rockchip,rk3288-usb", "rockchip,rk3066-usb",
-				"snps,dwc2";
-		reg = <0x101c0000 0x40000>;
-		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru HCLK_OTG1>;
-		clock-names = "otg";
-		dr_mode = "host";
-		status = "disabled";
-	};
-
-	emac: ethernet@10200000 {
-		compatible = "rockchip,rk3036-emac", "snps,arc-emac";
-		reg = <0x10200000 0x4000>;
-		interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		rockchip,grf = <&grf>;
-		clocks = <&cru HCLK_MAC>, <&cru SCLK_MACREF>, <&cru SCLK_MAC>;
-		clock-names = "hclk", "macref", "macclk";
-		/*
-		 * Fix the emac parent clock is DPLL instead of APLL.
-		 * since that will cause some unstable things if the cpufreq
-		 * is working. (e.g: the accurate 50MHz what mac_ref need)
-		 */
-		assigned-clocks = <&cru SCLK_MACPLL>;
-		assigned-clock-parents = <&cru PLL_DPLL>;
-		max-speed = <100>;
-		phy-mode = "rmii";
-		status = "disabled";
-	};
-
-	sdmmc: dwmmc@10214000 {
-		compatible = "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc";
-		reg = <0x10214000 0x4000>;
-		clock-frequency = <37500000>;
-		clock-freq-min-max = <400000 37500000>;
-		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
-		clock-names = "biu", "ciu";
-		fifo-depth = <0x100>;
-		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
-		status = "disabled";
-	};
-
-	sdio: dwmmc@10218000 {
-		compatible = "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc";
-		reg = <0x10218000 0x4000>;
-		clock-freq-min-max = <400000 37500000>;
-		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
-			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
-		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
-		fifo-depth = <0x100>;
-		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
-		status = "disabled";
-	};
-
-	emmc: dwmmc@1021c000 {
-		compatible = "rockchip,rk3288-dw-mshc";
-		reg = <0x1021c000 0x4000>;
-		interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
-		broken-cd;
-		bus-width = <8>;
-		cap-mmc-highspeed;
-		clock-frequency = <37500000>;
-		clock-freq-min-max = <400000 37500000>;
-		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
-			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
-		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
-		default-sample-phase = <158>;
-		disable-wp;
-		dmas = <&pdma 12>;
-		dma-names = "rx-tx";
-		fifo-depth = <0x100>;
-		mmc-ddr-1_8v;
-		non-removable;
-		num-slots = <1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
-		status = "disabled";
-	};
-
-	i2s: i2s@10220000 {
-		compatible = "rockchip,rk3036-i2s", "rockchip,rk3066-i2s";
-		reg = <0x10220000 0x4000>;
-		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clock-names = "i2s_clk", "i2s_hclk";
-		clocks = <&cru SCLK_I2S>, <&cru HCLK_I2S>;
-		dmas = <&pdma 0>, <&pdma 1>;
-		dma-names = "tx", "rx";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2s_bus>;
-		status = "disabled";
-	};
-
-	cru: clock-controller@20000000 {
-		compatible = "rockchip,rk3036-cru";
-		reg = <0x20000000 0x1000>;
-		rockchip,grf = <&grf>;
-		#clock-cells = <1>;
-		#reset-cells = <1>;
-		assigned-clocks = <&cru PLL_GPLL>;
-		assigned-clock-rates = <594000000>;
-	};
-
-	grf: syscon@20008000 {
-		compatible = "rockchip,rk3036-grf", "syscon";
-		reg = <0x20008000 0x1000>;
-	};
-
-	acodec: acodec-ana@20030000 {
-		compatible = "rk3036-codec";
-		reg = <0x20030000 0x4000>;
-		rockchip,grf = <&grf>;
-		clock-names = "acodec_pclk";
-		clocks = <&cru PCLK_ACODEC>;
-		status = "disabled";
-	};
-
-	hdmi: hdmi@20034000 {
-		compatible = "rockchip,rk3036-inno-hdmi";
-		reg = <0x20034000 0x4000>;
-		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru  PCLK_HDMI>;
-		clock-names = "pclk";
-		rockchip,grf = <&grf>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&hdmi_ctl>;
-		status = "disabled";
-
-		hdmi_in: port {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			hdmi_in_vop: endpoint@0 {
-				reg = <0>;
-				remote-endpoint = <&vop_out_hdmi>;
-			};
-		};
-	};
-
-	timer: timer@20044000 {
-		compatible = "rockchip,rk3036-timer", "rockchip,rk3288-timer";
-		reg = <0x20044000 0x20>;
-		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&xin24m>, <&cru PCLK_TIMER>;
-		clock-names = "timer", "pclk";
-	};
-
-	pwm0: pwm@20050000 {
-		compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm";
-		reg = <0x20050000 0x10>;
-		#pwm-cells = <3>;
-		clocks = <&cru PCLK_PWM>;
-		clock-names = "pwm";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pwm0_pin>;
-		status = "disabled";
-	};
-
-	pwm1: pwm@20050010 {
-		compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm";
-		reg = <0x20050010 0x10>;
-		#pwm-cells = <3>;
-		clocks = <&cru PCLK_PWM>;
-		clock-names = "pwm";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pwm1_pin>;
-		status = "disabled";
-	};
-
-	pwm2: pwm@20050020 {
-		compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm";
-		reg = <0x20050020 0x10>;
-		#pwm-cells = <3>;
-		clocks = <&cru PCLK_PWM>;
-		clock-names = "pwm";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pwm2_pin>;
-		status = "disabled";
-	};
-
-	pwm3: pwm@20050030 {
-		compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm";
-		reg = <0x20050030 0x10>;
-		#pwm-cells = <2>;
-		clocks = <&cru PCLK_PWM>;
-		clock-names = "pwm";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pwm3_pin>;
-		status = "disabled";
-	};
-
-	i2c1: i2c@20056000 {
-		compatible = "rockchip,rk3288-i2c";
-		reg = <0x20056000 0x1000>;
-		interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clock-names = "i2c";
-		clocks = <&cru PCLK_I2C1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c1_xfer>;
-		status = "disabled";
-	};
-
-	i2c2: i2c@2005a000 {
-		compatible = "rockchip,rk3288-i2c";
-		reg = <0x2005a000 0x1000>;
-		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clock-names = "i2c";
-		clocks = <&cru PCLK_I2C2>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_xfer>;
-		status = "disabled";
-	};
-
-	uart0: serial@20060000 {
-		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
-		reg = <0x20060000 0x100>;
-		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
-		reg-shift = <2>;
-		reg-io-width = <4>;
-		clock-frequency = <24000000>;
-		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
-		clock-names = "baudclk", "apb_pclk";
-		pinctrl-names = "default";
-		pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
-		status = "disabled";
-	};
-
-	uart1: serial@20064000 {
-		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
-		reg = <0x20064000 0x100>;
-		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
-		reg-shift = <2>;
-		reg-io-width = <4>;
-		clock-frequency = <24000000>;
-		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
-		clock-names = "baudclk", "apb_pclk";
-		pinctrl-names = "default";
-		pinctrl-0 = <&uart1_xfer>;
-		status = "disabled";
-	};
-
-	uart2: serial@20068000 {
-		compatible = "rockchip,rk3036-uart", "snps,dw-apb-uart";
-		reg = <0x20068000 0x100>;
-		interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
-		reg-shift = <2>;
-		reg-io-width = <4>;
-		clock-frequency = <24000000>;
-		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
-		clock-names = "baudclk", "apb_pclk";
-		pinctrl-names = "default";
-		pinctrl-0 = <&uart2_xfer>;
-		status = "disabled";
-	};
-
-	i2c0: i2c@20072000 {
-		compatible = "rockchip,rk3288-i2c";
-		reg = <0x20072000 0x1000>;
-		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clock-names = "i2c";
-		clocks = <&cru PCLK_I2C0>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c0_xfer>;
-		status = "disabled";
-	};
-
-	spi: spi@20074000 {
-		compatible = "rockchip,rockchip-spi";
-		reg = <0x20074000 0x1000>;
-		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-		clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>;
-		clock-names = "apb-pclk","spi_pclk";
-		dmas = <&pdma 8>, <&pdma 9>;
-		dma-names = "tx", "rx";
-		pinctrl-names = "default";
-		pinctrl-0 = <&spi_txd &spi_rxd &spi_clk &spi_cs0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		status = "disabled";
-	};
-
-	pinctrl: pinctrl {
-		compatible = "rockchip,rk3036-pinctrl";
-		rockchip,grf = <&grf>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		gpio0: gpio0@2007c000 {
-			compatible = "rockchip,gpio-bank";
-			reg = <0x2007c000 0x100>;
-			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&cru PCLK_GPIO0>;
-
-			gpio-controller;
-			#gpio-cells = <2>;
-
-			interrupt-controller;
-			#interrupt-cells = <2>;
-		};
-
-		gpio1: gpio1@20080000 {
-			compatible = "rockchip,gpio-bank";
-			reg = <0x20080000 0x100>;
-			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&cru PCLK_GPIO1>;
-
-			gpio-controller;
-			#gpio-cells = <2>;
-
-			interrupt-controller;
-			#interrupt-cells = <2>;
-		};
-
-		gpio2: gpio2@20084000 {
-			compatible = "rockchip,gpio-bank";
-			reg = <0x20084000 0x100>;
-			interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&cru PCLK_GPIO2>;
-
-			gpio-controller;
-			#gpio-cells = <2>;
-
-			interrupt-controller;
-			#interrupt-cells = <2>;
-		};
-
-		pcfg_pull_default: pcfg_pull_default {
-			bias-pull-pin-default;
-		};
-
-		pcfg_pull_none: pcfg-pull-none {
-			bias-disable;
-		};
-
-		pwm0 {
-			pwm0_pin: pwm0-pin {
-				rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
-			};
-		};
-
-		pwm1 {
-			pwm1_pin: pwm1-pin {
-				rockchip,pins = <0 1 RK_FUNC_2 &pcfg_pull_none>;
-			};
-		};
-
-		pwm2 {
-			pwm2_pin: pwm2-pin {
-				rockchip,pins = <0 1 2 &pcfg_pull_none>;
-			};
-		};
-
-		pwm3 {
-			pwm3_pin: pwm3-pin {
-				rockchip,pins = <0 27 1 &pcfg_pull_none>;
-			};
-		};
-
-		sdmmc {
-			sdmmc_clk: sdmmc-clk {
-				rockchip,pins = <1 16 RK_FUNC_1 &pcfg_pull_none>;
-			};
-
-			sdmmc_cmd: sdmmc-cmd {
-				rockchip,pins = <1 15 RK_FUNC_1 &pcfg_pull_default>;
-			};
-
-			sdmmc_cd: sdmcc-cd {
-				rockchip,pins = <1 17 RK_FUNC_1 &pcfg_pull_default>;
-			};
-
-			sdmmc_bus1: sdmmc-bus1 {
-				rockchip,pins = <1 18 RK_FUNC_1 &pcfg_pull_default>;
-			};
-
-			sdmmc_bus4: sdmmc-bus4 {
-				rockchip,pins = <1 18 RK_FUNC_1 &pcfg_pull_default>,
-						<1 19 RK_FUNC_1 &pcfg_pull_default>,
-						<1 20 RK_FUNC_1 &pcfg_pull_default>,
-						<1 21 RK_FUNC_1 &pcfg_pull_default>;
-			};
-		};
-
-		sdio {
-			sdio_bus1: sdio-bus1 {
-				rockchip,pins = <0 11 RK_FUNC_1 &pcfg_pull_default>;
-			};
-
-			sdio_bus4: sdio-bus4 {
-				rockchip,pins = <0 11 RK_FUNC_1 &pcfg_pull_default>,
-						<0 12 RK_FUNC_1 &pcfg_pull_default>,
-						<0 13 RK_FUNC_1 &pcfg_pull_default>,
-						<0 14 RK_FUNC_1 &pcfg_pull_default>;
-			};
-
-			sdio_cmd: sdio-cmd {
-				rockchip,pins = <0 8 RK_FUNC_1 &pcfg_pull_default>;
-			};
-
-			sdio_clk: sdio-clk {
-				rockchip,pins = <0 9 RK_FUNC_1 &pcfg_pull_none>;
-			};
-		};
-
-		emmc {
-			/*
-			 * We run eMMC at max speed; bump up drive strength.
-			 * We also have external pulls, so disable the internal ones.
-			 */
-			emmc_clk: emmc-clk {
-				rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none>;
-			};
-
-			emmc_cmd: emmc-cmd {
-				rockchip,pins = <2 1 RK_FUNC_2 &pcfg_pull_default>;
-			};
-
-			emmc_bus8: emmc-bus8 {
-				rockchip,pins = <1 24 RK_FUNC_2 &pcfg_pull_default>,
-						<1 25 RK_FUNC_2 &pcfg_pull_default>,
-						<1 26 RK_FUNC_2 &pcfg_pull_default>,
-						<1 27 RK_FUNC_2 &pcfg_pull_default>,
-						<1 28 RK_FUNC_2 &pcfg_pull_default>,
-						<1 29 RK_FUNC_2 &pcfg_pull_default>,
-						<1 30 RK_FUNC_2 &pcfg_pull_default>,
-						<1 31 RK_FUNC_2 &pcfg_pull_default>;
-			};
-		};
-
-		emac {
-			emac_xfer: emac-xfer {
-				rockchip,pins = <2 10 RK_FUNC_1 &pcfg_pull_default>, /* crs_dvalid */
-						<2 13 RK_FUNC_1 &pcfg_pull_default>, /* tx_en */
-						<2 14 RK_FUNC_1 &pcfg_pull_default>, /* mac_clk */
-						<2 15 RK_FUNC_1 &pcfg_pull_default>, /* rx_err */
-						<2 16 RK_FUNC_1 &pcfg_pull_default>, /* rxd1 */
-						<2 17 RK_FUNC_1 &pcfg_pull_default>, /* rxd0 */
-						<2 18 RK_FUNC_1 &pcfg_pull_default>, /* txd1 */
-						<2 19 RK_FUNC_1 &pcfg_pull_default>; /* txd0 */
-			};
-
-			emac_mdio: emac-mdio {
-				rockchip,pins = <2 12 RK_FUNC_1 &pcfg_pull_default>, /* mac_md */
-						<2 25 RK_FUNC_1 &pcfg_pull_default>; /* mac_mdclk */
-			};
-		};
-
-		i2c0 {
-			i2c0_xfer: i2c0-xfer {
-				rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>,
-						<0 1 RK_FUNC_1 &pcfg_pull_none>;
-			};
-		};
-
-		i2c1 {
-			i2c1_xfer: i2c1-xfer {
-				rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_none>,
-						<0 3 RK_FUNC_1 &pcfg_pull_none>;
-			};
-		};
-
-		i2c2 {
-			i2c2_xfer: i2c2-xfer {
-				rockchip,pins = <2 20 RK_FUNC_1 &pcfg_pull_none>,
-						<2 21 RK_FUNC_1 &pcfg_pull_none>;
-			};
-		};
-
-		i2s {
-			i2s_bus: i2s-bus {
-				rockchip,pins = <1 0 RK_FUNC_1 &pcfg_pull_default>,
-						<1 1 RK_FUNC_1 &pcfg_pull_default>,
-						<1 2 RK_FUNC_1 &pcfg_pull_default>,
-						<1 3 RK_FUNC_1 &pcfg_pull_default>,
-						<1 4 RK_FUNC_1 &pcfg_pull_default>,
-						<1 5 RK_FUNC_1 &pcfg_pull_default>;
-			};
-		};
-
-		hdmi {
-			hdmi_ctl: hdmi-ctl {
-				rockchip,pins = <1 8  RK_FUNC_1 &pcfg_pull_none>,
-						<1 9  RK_FUNC_1 &pcfg_pull_none>,
-						<1 10 RK_FUNC_1 &pcfg_pull_none>,
-						<1 11 RK_FUNC_1 &pcfg_pull_none>;
-			};
-		};
-
-		uart0 {
-			uart0_xfer: uart0-xfer {
-				rockchip,pins = <0 16 RK_FUNC_1 &pcfg_pull_default>,
-						<0 17 RK_FUNC_1 &pcfg_pull_none>;
-			};
-
-			uart0_cts: uart0-cts {
-				rockchip,pins = <0 18 RK_FUNC_1 &pcfg_pull_default>;
-			};
-
-			uart0_rts: uart0-rts {
-				rockchip,pins = <0 19 RK_FUNC_1 &pcfg_pull_none>;
-			};
-		};
-
-		uart1 {
-			uart1_xfer: uart1-xfer {
-				rockchip,pins = <2 22 RK_FUNC_1 &pcfg_pull_default>,
-						<2 23 RK_FUNC_1 &pcfg_pull_none>;
-			};
-			/* no rts / cts for uart1 */
-		};
-
-		uart2 {
-			uart2_xfer: uart2-xfer {
-				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_default>,
-						<1 19 RK_FUNC_2 &pcfg_pull_none>;
-			};
-			/* no rts / cts for uart2 */
-		};
-
-		spi {
-			spi_txd:spi-txd {
-				rockchip,pins = <1 29 RK_FUNC_3 &pcfg_pull_default>;
-			};
-
-			spi_rxd:spi-rxd {
-				rockchip,pins = <1 28 RK_FUNC_3 &pcfg_pull_default>;
-			};
-
-			spi_clk:spi-clk {
-				rockchip,pins = <2 0 RK_FUNC_2 &pcfg_pull_default>;
-			};
-
-			spi_cs0:spi-cs0 {
-				rockchip,pins = <1 30 RK_FUNC_3 &pcfg_pull_default>;
-
-			};
-
-			spi_cs1:spi-cs1 {
-				rockchip,pins = <1 31 RK_FUNC_3 &pcfg_pull_default>;
-
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/sama5d2-pinfunc.h b/arch/arm/boot/dts/sama5d2-pinfunc.h
index b0c912fe..8a394f3 100644
--- a/arch/arm/boot/dts/sama5d2-pinfunc.h
+++ b/arch/arm/boot/dts/sama5d2-pinfunc.h
@@ -837,8 +837,8 @@
 #define PIN_PD23__ISC_FIELD		PINMUX_PIN(PIN_PD23, 6, 4)
 #define PIN_PD24			120
 #define PIN_PD24__GPIO			PINMUX_PIN(PIN_PD24, 0, 0)
-#define PIN_PD24__UTXD2			PINMUX_PIN(PIN_PD23, 1, 2)
-#define PIN_PD24__FLEXCOM4_IO3		PINMUX_PIN(PIN_PD23, 3, 3)
+#define PIN_PD24__UTXD2			PINMUX_PIN(PIN_PD24, 1, 2)
+#define PIN_PD24__FLEXCOM4_IO3		PINMUX_PIN(PIN_PD24, 3, 3)
 #define PIN_PD25			121
 #define PIN_PD25__GPIO			PINMUX_PIN(PIN_PD25, 0, 0)
 #define PIN_PD25__SPI1_SPCK		PINMUX_PIN(PIN_PD25, 1, 3)
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 4dfca8f..1bc61ec 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -856,6 +856,13 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf801c000 0x100>;
 				interrupts = <24 IRQ_TYPE_LEVEL_HIGH 7>;
+				dmas = <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(35))>,
+				       <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(36))>;
+				dma-names = "tx", "rx";
 				clocks = <&uart0_clk>;
 				clock-names = "usart";
 				status = "disabled";
@@ -865,6 +872,13 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf8020000 0x100>;
 				interrupts = <25 IRQ_TYPE_LEVEL_HIGH 7>;
+				dmas = <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(37))>,
+				       <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(38))>;
+				dma-names = "tx", "rx";
 				clocks = <&uart1_clk>;
 				clock-names = "usart";
 				status = "disabled";
@@ -874,6 +888,13 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf8024000 0x100>;
 				interrupts = <26 IRQ_TYPE_LEVEL_HIGH 7>;
+				dmas = <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(39))>,
+				       <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(40))>;
+				dma-names = "tx", "rx";
 				clocks = <&uart2_clk>;
 				clock-names = "usart";
 				status = "disabled";
@@ -985,6 +1006,13 @@
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xfc008000 0x100>;
 				interrupts = <27 IRQ_TYPE_LEVEL_HIGH 7>;
+				dmas = <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(41))>,
+				       <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(42))>;
+				dma-names = "tx", "rx";
 				clocks = <&uart3_clk>;
 				clock-names = "usart";
 				status = "disabled";
@@ -993,6 +1021,13 @@
 			uart4: serial@fc00c000 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xfc00c000 0x100>;
+				dmas = <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(43))>,
+				       <&dma0
+					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+					 AT91_XDMAC_DT_PERID(44))>;
+				dma-names = "tx", "rx";
 				interrupts = <28 IRQ_TYPE_LEVEL_HIGH 7>;
 				clocks = <&uart4_clk>;
 				clock-names = "usart";
diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
index 81f8121..bbf9537 100644
--- a/arch/arm/boot/dts/stih407-family.dtsi
+++ b/arch/arm/boot/dts/stih407-family.dtsi
@@ -497,8 +497,9 @@
 			interrupt-names = "mmcirq";
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_mmc0>;
-			clock-names = "mmc";
-			clocks = <&clk_s_c0_flexgen CLK_MMC_0>;
+			clock-names = "mmc", "icn";
+			clocks = <&clk_s_c0_flexgen CLK_MMC_0>,
+				 <&clk_s_c0_flexgen CLK_RX_ICN_HVA>;
 			bus-width = <8>;
 			non-removable;
 		};
@@ -512,8 +513,9 @@
 			interrupt-names = "mmcirq";
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_sd1>;
-			clock-names = "mmc";
-			clocks = <&clk_s_c0_flexgen CLK_MMC_1>;
+			clock-names = "mmc", "icn";
+			clocks = <&clk_s_c0_flexgen CLK_MMC_1>,
+				 <&clk_s_c0_flexgen CLK_RX_ICN_HVA>;
 			resets = <&softreset STIH407_MMC1_SOFTRESET>;
 			bus-width = <4>;
 		};
diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi
index 18ed1ad..4031886 100644
--- a/arch/arm/boot/dts/stih410.dtsi
+++ b/arch/arm/boot/dts/stih410.dtsi
@@ -41,7 +41,8 @@
 			compatible = "st,st-ohci-300x";
 			reg = <0x9a03c00 0x100>;
 			interrupts = <GIC_SPI 180 IRQ_TYPE_NONE>;
-			clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>;
+			clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
+				 <&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
 			resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>,
 				 <&softreset STIH407_USB2_PORT0_SOFTRESET>;
 			reset-names = "power", "softreset";
@@ -57,7 +58,8 @@
 			interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb0>;
-			clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>;
+			clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
+				 <&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
 			resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>,
 				 <&softreset STIH407_USB2_PORT0_SOFTRESET>;
 			reset-names = "power", "softreset";
@@ -71,7 +73,8 @@
 			compatible = "st,st-ohci-300x";
 			reg = <0x9a83c00 0x100>;
 			interrupts = <GIC_SPI 181 IRQ_TYPE_NONE>;
-			clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>;
+			clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
+				 <&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
 			resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>,
 				 <&softreset STIH407_USB2_PORT1_SOFTRESET>;
 			reset-names = "power", "softreset";
@@ -87,7 +90,8 @@
 			interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb1>;
-			clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>;
+			clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
+				 <&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
 			resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>,
 				 <&softreset STIH407_USB2_PORT1_SOFTRESET>;
 			reset-names = "power", "softreset";
diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
index 97570cb..1d23527 100644
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -84,6 +84,7 @@
 		regulator-name = "emac-3v3";
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <20000>;
 		enable-active-high;
 		gpio = <&pio 7 15 GPIO_ACTIVE_HIGH>;
 	};
diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
index 2b17c51..6de83a6 100644
--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts
+++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
@@ -66,6 +66,7 @@
 		regulator-name = "emac-3v3";
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <20000>;
 		enable-active-high;
 		gpio = <&pio 7 19 GPIO_ACTIVE_HIGH>;
 	};
diff --git a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
index 7afc7a6..e28f080 100644
--- a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
+++ b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
@@ -80,6 +80,7 @@
 		regulator-name = "emac-3v3";
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <20000>;
 		enable-active-high;
 		gpio = <&pio 7 19 GPIO_ACTIVE_HIGH>;   /* PH19 */
 	};
diff --git a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
index 9fea918..39731a7 100644
--- a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
+++ b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
@@ -79,6 +79,7 @@
 		regulator-name = "emac-3v3";
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <20000>;
 		enable-active-high;
 		gpio = <&pio 0 2 GPIO_ACTIVE_HIGH>;
 	};
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index d910d3a..84bdba4 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -83,7 +83,7 @@
 			trips {
 				cpu_alert0: cpu_alert0 {
 					/* milliCelsius */
-					temperature = <850000>;
+					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
diff --git a/arch/arm/boot/dts/sun5i-r8-chip.dts b/arch/arm/boot/dts/sun5i-r8-chip.dts
index 530ab28..d21f50b 100644
--- a/arch/arm/boot/dts/sun5i-r8-chip.dts
+++ b/arch/arm/boot/dts/sun5i-r8-chip.dts
@@ -52,7 +52,7 @@
 
 / {
 	model = "NextThing C.H.I.P.";
-	compatible = "nextthing,chip", "allwinner,sun5i-r8";
+	compatible = "nextthing,chip", "allwinner,sun5i-r8", "allwinner,sun5i-a13";
 
 	aliases {
 		i2c0 = &i2c0;
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index ed7e100..d9ee0fd 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -565,6 +565,7 @@
 			regulator-name = "+3VS,vdd_pnl";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
+			regulator-boot-on;
 			gpio = <&gpio TEGRA_GPIO(A, 4) GPIO_ACTIVE_HIGH>;
 			enable-active-high;
 		};
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 9353184..ce01364 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -17,3 +17,7 @@
 
 config SHARP_SCOOP
 	bool
+
+config FIQ_GLUE
+	bool
+	select FIQ
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 27f23b1..04aca89 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -4,6 +4,7 @@
 
 obj-y				+= firmware.o
 
+obj-$(CONFIG_FIQ_GLUE)		+= fiq_glue.o fiq_glue_setup.o
 obj-$(CONFIG_ICST)		+= icst.o
 obj-$(CONFIG_SA1111)		+= sa1111.o
 obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
diff --git a/arch/arm/common/fiq_glue.S b/arch/arm/common/fiq_glue.S
new file mode 100644
index 0000000..24b42ce
--- /dev/null
+++ b/arch/arm/common/fiq_glue.S
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+		.text
+
+		.global fiq_glue_end
+
+		/* fiq stack: r0-r15,cpsr,spsr of interrupted mode */
+
+ENTRY(fiq_glue)
+		/* store pc, cpsr from previous mode, reserve space for spsr */
+		mrs	r12, spsr
+		sub	lr, lr, #4
+		subs	r10, #1
+		bne	nested_fiq
+
+		str	r12, [sp, #-8]!
+		str	lr, [sp, #-4]!
+
+		/* store r8-r14 from previous mode */
+		sub	sp, sp, #(7 * 4)
+		stmia	sp, {r8-r14}^
+		nop
+
+		/* store r0-r7 from previous mode */
+		stmfd	sp!, {r0-r7}
+
+		/* setup func(data,regs) arguments */
+		mov	r0, r9
+		mov	r1, sp
+		mov	r3, r8
+
+		mov	r7, sp
+
+		/* Get sp and lr from non-user modes */
+		and	r4, r12, #MODE_MASK
+		cmp	r4, #USR_MODE
+		beq	fiq_from_usr_mode
+
+		mov	r7, sp
+		orr	r4, r4, #(PSR_I_BIT | PSR_F_BIT)
+		msr	cpsr_c, r4
+		str	sp, [r7, #(4 * 13)]
+		str	lr, [r7, #(4 * 14)]
+		mrs	r5, spsr
+		str	r5, [r7, #(4 * 17)]
+
+		cmp	r4, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT)
+		/* use fiq stack if we reenter this mode */
+		subne	sp, r7, #(4 * 3)
+
+fiq_from_usr_mode:
+		msr	cpsr_c, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT)
+		mov	r2, sp
+		sub	sp, r7, #12
+		stmfd	sp!, {r2, ip, lr}
+		/* call func(data,regs) */
+		blx	r3
+		ldmfd	sp, {r2, ip, lr}
+		mov	sp, r2
+
+		/* restore/discard saved state */
+		cmp	r4, #USR_MODE
+		beq	fiq_from_usr_mode_exit
+
+		msr	cpsr_c, r4
+		ldr	sp, [r7, #(4 * 13)]
+		ldr	lr, [r7, #(4 * 14)]
+		msr	spsr_cxsf, r5
+
+fiq_from_usr_mode_exit:
+		msr	cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
+
+		ldmfd	sp!, {r0-r7}
+		ldr	lr, [sp, #(4 * 7)]
+		ldr	r12, [sp, #(4 * 8)]
+		add	sp, sp, #(10 * 4)
+exit_fiq:
+		msr	spsr_cxsf, r12
+		add	r10, #1
+		cmp	r11, #0
+		moveqs	pc, lr
+		bx	r11 /* jump to custom fiq return function */
+
+nested_fiq:
+		orr	r12, r12, #(PSR_F_BIT)
+		b	exit_fiq
+
+fiq_glue_end:
+
+ENTRY(fiq_glue_setup) /* func, data, sp, smc call number */
+		stmfd		sp!, {r4}
+		mrs		r4, cpsr
+		msr		cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
+		movs		r8, r0
+		mov		r9, r1
+		mov		sp, r2
+		mov		r11, r3
+		moveq		r10, #0
+		movne		r10, #1
+		msr		cpsr_c, r4
+		ldmfd		sp!, {r4}
+		bx		lr
+
diff --git a/arch/arm/common/fiq_glue_setup.c b/arch/arm/common/fiq_glue_setup.c
new file mode 100644
index 0000000..8cb1b61
--- /dev/null
+++ b/arch/arm/common/fiq_glue_setup.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
+#include <asm/fiq.h>
+#include <asm/fiq_glue.h>
+
+extern unsigned char fiq_glue, fiq_glue_end;
+extern void fiq_glue_setup(void *func, void *data, void *sp,
+			   fiq_return_handler_t fiq_return_handler);
+
+static struct fiq_handler fiq_debbuger_fiq_handler = {
+	.name = "fiq_glue",
+};
+DEFINE_PER_CPU(void *, fiq_stack);
+static struct fiq_glue_handler *current_handler;
+static fiq_return_handler_t fiq_return_handler;
+static DEFINE_MUTEX(fiq_glue_lock);
+
+static void fiq_glue_setup_helper(void *info)
+{
+	struct fiq_glue_handler *handler = info;
+	fiq_glue_setup(handler->fiq, handler,
+		__get_cpu_var(fiq_stack) + THREAD_START_SP,
+		fiq_return_handler);
+}
+
+int fiq_glue_register_handler(struct fiq_glue_handler *handler)
+{
+	int ret;
+	int cpu;
+
+	if (!handler || !handler->fiq)
+		return -EINVAL;
+
+	mutex_lock(&fiq_glue_lock);
+	if (fiq_stack) {
+		ret = -EBUSY;
+		goto err_busy;
+	}
+
+	for_each_possible_cpu(cpu) {
+		void *stack;
+		stack = (void *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
+		if (WARN_ON(!stack)) {
+			ret = -ENOMEM;
+			goto err_alloc_fiq_stack;
+		}
+		per_cpu(fiq_stack, cpu) = stack;
+	}
+
+	ret = claim_fiq(&fiq_debbuger_fiq_handler);
+	if (WARN_ON(ret))
+		goto err_claim_fiq;
+
+	current_handler = handler;
+	on_each_cpu(fiq_glue_setup_helper, handler, true);
+	set_fiq_handler(&fiq_glue, &fiq_glue_end - &fiq_glue);
+
+	mutex_unlock(&fiq_glue_lock);
+	return 0;
+
+err_claim_fiq:
+err_alloc_fiq_stack:
+	for_each_possible_cpu(cpu) {
+		__free_pages(per_cpu(fiq_stack, cpu), THREAD_SIZE_ORDER);
+		per_cpu(fiq_stack, cpu) = NULL;
+	}
+err_busy:
+	mutex_unlock(&fiq_glue_lock);
+	return ret;
+}
+
+static void fiq_glue_update_return_handler(void (*fiq_return)(void))
+{
+	fiq_return_handler = fiq_return;
+	if (current_handler)
+		on_each_cpu(fiq_glue_setup_helper, current_handler, true);
+}
+
+int fiq_glue_set_return_handler(void (*fiq_return)(void))
+{
+	int ret;
+
+	mutex_lock(&fiq_glue_lock);
+	if (fiq_return_handler) {
+		ret = -EBUSY;
+		goto err_busy;
+	}
+	fiq_glue_update_return_handler(fiq_return);
+	ret = 0;
+err_busy:
+	mutex_unlock(&fiq_glue_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(fiq_glue_set_return_handler);
+
+int fiq_glue_clear_return_handler(void (*fiq_return)(void))
+{
+	int ret;
+
+	mutex_lock(&fiq_glue_lock);
+	if (WARN_ON(fiq_return_handler != fiq_return)) {
+		ret = -EINVAL;
+		goto err_inval;
+	}
+	fiq_glue_update_return_handler(NULL);
+	ret = 0;
+err_inval:
+	mutex_unlock(&fiq_glue_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(fiq_glue_clear_return_handler);
+
+/**
+ * fiq_glue_resume - Restore fiqs after suspend or low power idle states
+ *
+ * This must be called before calling local_fiq_enable after returning from a
+ * power state where the fiq mode registers were lost. If a driver provided
+ * a resume hook when it registered the handler it will be called.
+ */
+
+void fiq_glue_resume(void)
+{
+	if (!current_handler)
+		return;
+	fiq_glue_setup(current_handler->fiq, current_handler,
+		__get_cpu_var(fiq_stack) + THREAD_START_SP,
+		fiq_return_handler);
+	if (current_handler->resume)
+		current_handler->resume(current_handler);
+}
+
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 3d22494..a3a9ad4 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -869,9 +869,9 @@
 
 #ifdef CONFIG_PM
 
-static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
+static int sa1111_suspend_noirq(struct device *dev)
 {
-	struct sa1111 *sachip = platform_get_drvdata(dev);
+	struct sa1111 *sachip = dev_get_drvdata(dev);
 	struct sa1111_save_data *save;
 	unsigned long flags;
 	unsigned int val;
@@ -934,9 +934,9 @@
  *	restored by their respective drivers, and must be called
  *	via LDM after this function.
  */
-static int sa1111_resume(struct platform_device *dev)
+static int sa1111_resume_noirq(struct device *dev)
 {
-	struct sa1111 *sachip = platform_get_drvdata(dev);
+	struct sa1111 *sachip = dev_get_drvdata(dev);
 	struct sa1111_save_data *save;
 	unsigned long flags, id;
 	void __iomem *base;
@@ -952,7 +952,7 @@
 	id = sa1111_readl(sachip->base + SA1111_SKID);
 	if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
 		__sa1111_remove(sachip);
-		platform_set_drvdata(dev, NULL);
+		dev_set_drvdata(dev, NULL);
 		kfree(save);
 		return 0;
 	}
@@ -1003,8 +1003,8 @@
 }
 
 #else
-#define sa1111_suspend NULL
-#define sa1111_resume  NULL
+#define sa1111_suspend_noirq NULL
+#define sa1111_resume_noirq  NULL
 #endif
 
 static int sa1111_probe(struct platform_device *pdev)
@@ -1038,6 +1038,11 @@
 	return 0;
 }
 
+static struct dev_pm_ops sa1111_pm_ops = {
+	.suspend_noirq = sa1111_suspend_noirq,
+	.resume_noirq = sa1111_resume_noirq,
+};
+
 /*
  *	Not sure if this should be on the system bus or not yet.
  *	We really want some way to register a system device at
@@ -1050,10 +1055,9 @@
 static struct platform_driver sa1111_device_driver = {
 	.probe		= sa1111_probe,
 	.remove		= sa1111_remove,
-	.suspend	= sa1111_suspend,
-	.resume		= sa1111_resume,
 	.driver		= {
 		.name	= "sa1111",
+		.pm	= &sa1111_pm_ops,
 	},
 };
 
diff --git a/arch/arm/configs/ranchu_defconfig b/arch/arm/configs/ranchu_defconfig
new file mode 100644
index 0000000..49e7bbd
--- /dev/null
+++ b/arch/arm/configs/ranchu_defconfig
@@ -0,0 +1,316 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_ARCH_MMAP_RND_BITS=16
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_VIRT=y
+CONFIG_ARM_KERNMEM_PERMS=y
+CONFIG_SMP=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_KSM=y
+CONFIG_SECCOMP=y
+CONFIG_CMDLINE="console=ttyAMA0"
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_VIRTIO_BLK=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_VIRTIO_NET=y
+CONFIG_SMSC911X=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_USB_USBNET=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=y
+CONFIG_TABLET_USB_AIPTEK=y
+CONFIG_TABLET_USB_GTCO=y
+CONFIG_TABLET_USB_HANWANG=y
+CONFIG_TABLET_USB_KBTAB=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=y
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_FB=y
+CONFIG_FB_GOLDFISH=y
+CONFIG_FB_SIMPLE=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_PRODIKEYS=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_HOLTEK=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WALTOP=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_PRIMAX=y
+CONFIG_HID_ROCCAT=y
+CONFIG_HID_SAITEK=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SPEEDLINK=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_WIIMOTE=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PL031=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
+CONFIG_SW_SYNC_USER=y
+CONFIG_ION=y
+CONFIG_GOLDFISH_AUDIO=y
+CONFIG_GOLDFISH=y
+CONFIG_GOLDFISH_PIPE=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_PSTORE=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_RAM=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_PANIC_TIMEOUT=5
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_VIRTUALIZATION=y
diff --git a/arch/arm/configs/rk3036_kylin_defconfig b/arch/arm/configs/rk3036_kylin_defconfig
deleted file mode 100644
index 692c393..0000000
--- a/arch/arm/configs/rk3036_kylin_defconfig
+++ /dev/null
@@ -1,230 +0,0 @@
-CONFIG_CROSS_COMPILE="arm-linux-gnueabi-"
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_DEFAULT_HOSTNAME="radxarock"
-CONFIG_SYSVIPC=y
-# CONFIG_USELIB is not set
-CONFIG_AUDIT=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_PERF_EVENTS=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
-CONFIG_JUMP_LABEL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_FORCE_LOAD=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_ROCKCHIP=y
-CONFIG_PL310_ERRATA_588369=y
-CONFIG_PL310_ERRATA_727915=y
-CONFIG_ARM_ERRATA_720789=y
-CONFIG_ARM_ERRATA_754322=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
-# CONFIG_COMPACTION is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
-CONFIG_CLEANCACHE=y
-CONFIG_FRONTSWAP=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_ARM_ATAG_DTB_COMPAT=y
-CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=y
-CONFIG_CPUFREQ_DT=y
-CONFIG_CPU_IDLE=y
-CONFIG_VFP=y
-CONFIG_NEON=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_CFG80211_WEXT=y
-CONFIG_RFKILL=y
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=1
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_SRAM=y
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-# CONFIG_NET_CADENCE is not set
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CIRRUS is not set
-# CONFIG_NET_VENDOR_FARADAY is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_SAMSUNG is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SMSC is not set
-CONFIG_STMMAC_ETH=y
-# CONFIG_NET_VENDOR_VIA is not set
-# CONFIG_NET_VENDOR_WIZNET is not set
-CONFIG_SMSC_PHY=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=600
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_KEYBOARD_GPIO_POLLED=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_INPUT_MISC=y
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_DW=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_I2C_RK3X=y
-CONFIG_GPIO_DWAPB=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_POWER_RESET=y
-CONFIG_SENSORS_IIO_HWMON=y
-CONFIG_THERMAL=y
-CONFIG_CPU_THERMAL=y
-CONFIG_WATCHDOG=y
-CONFIG_SOFT_WATCHDOG=y
-CONFIG_MFD_RK808=y
-CONFIG_MFD_TPS65910=y
-CONFIG_REGULATOR_DEBUG=y
-CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_REGULATOR_ACT8865=y
-CONFIG_REGULATOR_FAN53555=y
-CONFIG_REGULATOR_RK808=y
-CONFIG_DRM=y
-CONFIG_DRM_ROCKCHIP=y
-CONFIG_ROCKCHIP_DW_HDMI=y
-CONFIG_ROCKCHIP_INNO_HDMI=y
-CONFIG_DRM_PANEL_SIMPLE=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_GENERIC is not set
-CONFIG_BACKLIGHT_PWM=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SOC=y
-CONFIG_SND_SOC_ROCKCHIP=y
-CONFIG_SND_SOC_ROCKCHIP_I2S=y
-CONFIG_SND_SIMPLE_CARD=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_OTG=y
-CONFIG_USB_MON=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_DWC2=y
-CONFIG_USB_DWC2_PLATFORM=y
-CONFIG_NOP_USB_XCEIV=y
-CONFIG_USB_ULPI=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_G_ANDROID=y
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK_MINORS=32
-CONFIG_MMC_DW=y
-CONFIG_MMC_DW_ROCKCHIP=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_ONESHOT=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_HYM8563=y
-CONFIG_RTC_DRV_RK808=y
-CONFIG_DMADEVICES=y
-CONFIG_DMADEVICES_DEBUG=y
-CONFIG_DMADEVICES_VDEBUG=y
-CONFIG_PL330_DMA=y
-CONFIG_ASYNC_TX_DMA=y
-CONFIG_STAGING=y
-CONFIG_R8188EU=y
-CONFIG_R8723AU=y
-CONFIG_ASHMEM=y
-CONFIG_ANDROID_TIMED_GPIO=y
-CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
-CONFIG_SW_SYNC_USER=y
-CONFIG_ION=y
-CONFIG_ION_DUMMY=y
-CONFIG_COMMON_CLK_RK808=y
-CONFIG_ROCKCHIP_IOMMU=y
-CONFIG_IIO=y
-CONFIG_ROCKCHIP_SARADC=y
-CONFIG_INV_MPU6050_IIO=y
-CONFIG_AK8975=y
-CONFIG_PWM=y
-CONFIG_PWM_ROCKCHIP=y
-CONFIG_PHY_ROCKCHIP_USB=y
-CONFIG_ANDROID=y
-CONFIG_ANDROID_BINDER_IPC=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_SECURITY=y
-# CONFIG_DNOTIFY is not set
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_PRINTK_TIME=y
-CONFIG_DYNAMIC_DEBUG=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_FRAME_WARN=2048
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-CONFIG_TIMER_STATS=y
-CONFIG_KGDB=y
-CONFIG_DEBUG_LL=y
-CONFIG_DEBUG_RK29_UART2=y
-CONFIG_DEBUG_UART_8250_WORD=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
-CONFIG_SECURITY_SELINUX=y
-CONFIG_SECURITY_SELINUX_DISABLE=y
-# CONFIG_SECURITY_SELINUX_AVC_STATS is not set
-CONFIG_CRYPTO_ANSI_CPRNG=y
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c
index b445a5d..1f7b98e 100644
--- a/arch/arm/crypto/aes-ce-glue.c
+++ b/arch/arm/crypto/aes-ce-glue.c
@@ -87,8 +87,13 @@
 		u32 *rki = ctx->key_enc + (i * kwords);
 		u32 *rko = rki + kwords;
 
+#ifndef CONFIG_CPU_BIG_ENDIAN
 		rko[0] = ror32(ce_aes_sub(rki[kwords - 1]), 8);
 		rko[0] = rko[0] ^ rki[0] ^ rcon[i];
+#else
+		rko[0] = rol32(ce_aes_sub(rki[kwords - 1]), 8);
+		rko[0] = rko[0] ^ rki[0] ^ (rcon[i] << 24);
+#endif
 		rko[1] = rko[0] ^ rki[1];
 		rko[2] = rko[1] ^ rki[2];
 		rko[3] = rko[2] ^ rki[3];
@@ -279,7 +284,7 @@
 		err = blkcipher_walk_done(desc, &walk,
 					  walk.nbytes % AES_BLOCK_SIZE);
 	}
-	if (nbytes) {
+	if (walk.nbytes % AES_BLOCK_SIZE) {
 		u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
 		u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE;
 		u8 __aligned(8) tail[AES_BLOCK_SIZE];
@@ -364,7 +369,7 @@
 	.cra_blkcipher = {
 		.min_keysize	= AES_MIN_KEY_SIZE,
 		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
+		.ivsize		= 0,
 		.setkey		= ce_aes_setkey,
 		.encrypt	= ecb_encrypt,
 		.decrypt	= ecb_decrypt,
@@ -441,7 +446,7 @@
 	.cra_ablkcipher = {
 		.min_keysize	= AES_MIN_KEY_SIZE,
 		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
+		.ivsize		= 0,
 		.setkey		= ablk_set_key,
 		.encrypt	= ablk_encrypt,
 		.decrypt	= ablk_decrypt,
diff --git a/arch/arm/crypto/ghash-ce-glue.c b/arch/arm/crypto/ghash-ce-glue.c
index 03a39fe..9d9ba9a 100644
--- a/arch/arm/crypto/ghash-ce-glue.c
+++ b/arch/arm/crypto/ghash-ce-glue.c
@@ -226,6 +226,27 @@
 	}
 }
 
+static int ghash_async_import(struct ahash_request *req, const void *in)
+{
+	struct ahash_request *cryptd_req = ahash_request_ctx(req);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm);
+	struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+
+	desc->tfm = cryptd_ahash_child(ctx->cryptd_tfm);
+	desc->flags = req->base.flags;
+
+	return crypto_shash_import(desc, in);
+}
+
+static int ghash_async_export(struct ahash_request *req, void *out)
+{
+	struct ahash_request *cryptd_req = ahash_request_ctx(req);
+	struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+
+	return crypto_shash_export(desc, out);
+}
+
 static int ghash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
 			      unsigned int keylen)
 {
@@ -274,7 +295,10 @@
 	.final			= ghash_async_final,
 	.setkey			= ghash_async_setkey,
 	.digest			= ghash_async_digest,
+	.import			= ghash_async_import,
+	.export			= ghash_async_export,
 	.halg.digestsize	= GHASH_DIGEST_SIZE,
+	.halg.statesize		= sizeof(struct ghash_desc_ctx),
 	.halg.base		= {
 		.cra_name	= "ghash",
 		.cra_driver_name = "ghash-ce",
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index d5525bf..9156fc3 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -491,7 +491,6 @@
 #endif
 
 #ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
 void set_kernel_text_rw(void);
 void set_kernel_text_ro(void);
 #else
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 85e374f..e9d04f4 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -81,6 +81,9 @@
 #define ARM_CPU_XSCALE_ARCH_V2		0x4000
 #define ARM_CPU_XSCALE_ARCH_V3		0x6000
 
+/* Qualcomm implemented cores */
+#define ARM_CPU_PART_SCORPION		0x510002d0
+
 extern unsigned int processor_id;
 
 #ifdef CONFIG_CPU_CP15
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index ccb3aa6..b91a2d1 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -119,7 +119,7 @@
 /* The ARM override for dma_max_pfn() */
 static inline unsigned long dma_max_pfn(struct device *dev)
 {
-	return PHYS_PFN_OFFSET + dma_to_pfn(dev, *dev->dma_mask);
+	return dma_to_pfn(dev, *dev->dma_mask);
 }
 #define dma_max_pfn(dev) dma_max_pfn(dev)
 
diff --git a/arch/arm/include/asm/fiq_glue.h b/arch/arm/include/asm/fiq_glue.h
new file mode 100644
index 0000000..a9e244f9
--- /dev/null
+++ b/arch/arm/include/asm/fiq_glue.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_FIQ_GLUE_H
+#define __ASM_FIQ_GLUE_H
+
+struct fiq_glue_handler {
+	void (*fiq)(struct fiq_glue_handler *h, void *regs, void *svc_sp);
+	void (*resume)(struct fiq_glue_handler *h);
+};
+typedef void (*fiq_return_handler_t)(void);
+
+int fiq_glue_register_handler(struct fiq_glue_handler *handler);
+int fiq_glue_set_return_handler(fiq_return_handler_t fiq_return);
+int fiq_glue_clear_return_handler(fiq_return_handler_t fiq_return);
+
+#ifdef CONFIG_FIQ_GLUE
+void fiq_glue_resume(void);
+#else
+static inline void fiq_glue_resume(void) {}
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/floppy.h b/arch/arm/include/asm/floppy.h
index f488255..85a34cc 100644
--- a/arch/arm/include/asm/floppy.h
+++ b/arch/arm/include/asm/floppy.h
@@ -17,7 +17,7 @@
 
 #define fd_outb(val,port)			\
 	do {					\
-		if ((port) == FD_DOR)		\
+		if ((port) == (u32)FD_DOR)	\
 			fd_setdor((val));	\
 		else				\
 			outb((val),(port));	\
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 194c91b..c35c349 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -79,6 +79,8 @@
 #define rr_lo_hi(a1, a2) a1, a2
 #endif
 
+#define kvm_ksym_ref(kva)	(kva)
+
 #ifndef __ASSEMBLY__
 struct kvm;
 struct kvm_vcpu;
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 405aa18..23d5cad 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -204,18 +204,12 @@
 	 * and iterate over the range.
 	 */
 
-	bool need_flush = !vcpu_has_cache_enabled(vcpu) || ipa_uncached;
-
 	VM_BUG_ON(size & ~PAGE_MASK);
 
-	if (!need_flush && !icache_is_pipt())
-		goto vipt_cache;
-
 	while (size) {
 		void *va = kmap_atomic_pfn(pfn);
 
-		if (need_flush)
-			kvm_flush_dcache_to_poc(va, PAGE_SIZE);
+		kvm_flush_dcache_to_poc(va, PAGE_SIZE);
 
 		if (icache_is_pipt())
 			__cpuc_coherent_user_range((unsigned long)va,
@@ -227,7 +221,6 @@
 		kunmap_atomic(va);
 	}
 
-vipt_cache:
 	if (!icache_is_pipt() && !icache_is_vivt_asid_tagged()) {
 		/* any kind of VIPT cache */
 		__flush_icache_all();
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index aeddd28..92fd2c8 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -193,6 +193,7 @@
 
 #define pmd_large(pmd)		(pmd_val(pmd) & 2)
 #define pmd_bad(pmd)		(pmd_val(pmd) & 2)
+#define pmd_present(pmd)	(pmd_val(pmd))
 
 #define copy_pmd(pmdpd,pmdps)		\
 	do {				\
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index a745a2a..9459ca8 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -212,6 +212,7 @@
 						: !!(pmd_val(pmd) & (val)))
 #define pmd_isclear(pmd, val)	(!(pmd_val(pmd) & (val)))
 
+#define pmd_present(pmd)	(pmd_isset((pmd), L_PMD_SECT_VALID))
 #define pmd_young(pmd)		(pmd_isset((pmd), PMD_SECT_AF))
 #define pte_special(pte)	(pte_isset((pte), L_PTE_SPECIAL))
 static inline pte_t pte_mkspecial(pte_t pte)
@@ -249,6 +250,7 @@
 PMD_BIT_FUNC(mksplitting, |= L_PMD_SECT_SPLITTING);
 PMD_BIT_FUNC(mkwrite,   &= ~L_PMD_SECT_RDONLY);
 PMD_BIT_FUNC(mkdirty,   |= L_PMD_SECT_DIRTY);
+PMD_BIT_FUNC(mkclean,   &= ~L_PMD_SECT_DIRTY);
 PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
 
 #define pmd_mkhuge(pmd)		(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
@@ -257,10 +259,10 @@
 #define pfn_pmd(pfn,prot)	(__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
 #define mk_pmd(page,prot)	pfn_pmd(page_to_pfn(page),prot)
 
-/* represent a notpresent pmd by zero, this is used by pmdp_invalidate */
+/* represent a notpresent pmd by faulting entry, this is used by pmdp_invalidate */
 static inline pmd_t pmd_mknotpresent(pmd_t pmd)
 {
-	return __pmd(0);
+	return __pmd(pmd_val(pmd) & ~L_PMD_SECT_VALID);
 }
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 348caab..d622040 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -182,7 +182,6 @@
 #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
 
 #define pmd_none(pmd)		(!pmd_val(pmd))
-#define pmd_present(pmd)	(pmd_val(pmd))
 
 static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 {
diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h
index 370f7a7..d060641 100644
--- a/arch/arm/include/asm/topology.h
+++ b/arch/arm/include/asm/topology.h
@@ -3,6 +3,7 @@
 
 #ifdef CONFIG_ARM_CPU_TOPOLOGY
 
+#include <linux/cpufreq.h>
 #include <linux/cpumask.h>
 
 struct cputopo_arm {
@@ -24,6 +25,12 @@
 void store_cpu_topology(unsigned int cpuid);
 const struct cpumask *cpu_coregroup_mask(int cpu);
 
+#ifdef CONFIG_CPU_FREQ
+#define arch_scale_freq_capacity cpufreq_scale_freq_capacity
+#endif
+#define arch_scale_cpu_capacity scale_cpu_capacity
+extern unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu);
+
 #else
 
 static inline void init_cpu_topology(void) { }
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 35c9db8..7fb5919 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -496,7 +496,10 @@
 static inline unsigned long __must_check
 __copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-	unsigned int __ua_flags = uaccess_save_and_enable();
+	unsigned int __ua_flags;
+
+	check_object_size(to, n, false);
+	__ua_flags = uaccess_save_and_enable();
 	n = arm_copy_from_user(to, from, n);
 	uaccess_restore(__ua_flags);
 	return n;
@@ -511,11 +514,15 @@
 __copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 #ifndef CONFIG_UACCESS_WITH_MEMCPY
-	unsigned int __ua_flags = uaccess_save_and_enable();
+	unsigned int __ua_flags;
+
+	check_object_size(from, n, true);
+	__ua_flags = uaccess_save_and_enable();
 	n = arm_copy_to_user(to, from, n);
 	uaccess_restore(__ua_flags);
 	return n;
 #else
+	check_object_size(from, n, true);
 	return arm_copy_to_user(to, from, n);
 #endif
 }
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index af9e59b..3c78949 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -73,7 +73,6 @@
 obj-$(CONFIG_PERF_EVENTS)	+= perf_regs.o perf_callchain.o
 obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event_xscale.o perf_event_v6.o \
 				   perf_event_v7.o
-CFLAGS_pj4-cp0.o		:= -marm
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 obj-$(CONFIG_VDSO)		+= vdso.o
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 871b826..a586cfe 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -10,7 +10,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/compiler.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
@@ -41,19 +40,10 @@
  * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
  *            (http://gcc.gnu.org/PR8896) and incorrect structure
  *	      initialisation in fs/jffs2/erase.c
- * GCC 4.8.0-4.8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854
- *	      miscompiles find_get_entry(), and can result in EXT3 and EXT4
- *	      filesystem corruption (possibly other FS too).
  */
-#ifdef __GNUC__
 #if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
 #error Your compiler is too buggy; it is known to miscompile kernels.
-#error    Known good compilers: 3.3, 4.x
-#endif
-#if GCC_VERSION >= 40800 && GCC_VERSION < 40803
-#error Your compiler is too buggy; it is known to miscompile kernels
-#error and result in filesystem corruption and oopses.
-#endif
+#error    Known good compilers: 3.3
 #endif
 
 int main(void)
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 65addcb..b3b950f 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -87,6 +87,8 @@
 		return;
 
 	for_each_child_of_node(cpus, cpu) {
+		const __be32 *cell;
+		int prop_bytes;
 		u32 hwid;
 
 		if (of_node_cmp(cpu->type, "cpu"))
@@ -98,7 +100,8 @@
 		 * properties is considered invalid to build the
 		 * cpu_logical_map.
 		 */
-		if (of_property_read_u32(cpu, "reg", &hwid)) {
+		cell = of_get_property(cpu, "reg", &prop_bytes);
+		if (!cell || prop_bytes < sizeof(*cell)) {
 			pr_debug(" * %s missing reg property\n",
 				     cpu->full_name);
 			of_node_put(cpu);
@@ -106,10 +109,15 @@
 		}
 
 		/*
-		 * 8 MSBs must be set to 0 in the DT since the reg property
+		 * Bits n:24 must be set to 0 in the DT since the reg property
 		 * defines the MPIDR[23:0].
 		 */
-		if (hwid & ~MPIDR_HWID_BITMASK) {
+		do {
+			hwid = be32_to_cpu(*cell++);
+			prop_bytes -= sizeof(*cell);
+		} while (!hwid && prop_bytes > 0);
+
+		if (prop_bytes || (hwid & ~MPIDR_HWID_BITMASK)) {
 			of_node_put(cpu);
 			return;
 		}
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 6284779..abcbea1 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -1066,6 +1066,22 @@
 		return 0;
 	}
 
+	/*
+	 * Scorpion CPUs (at least those in APQ8060) seem to set DBGPRSR.SPD
+	 * whenever a WFI is issued, even if the core is not powered down, in
+	 * violation of the architecture.  When DBGPRSR.SPD is set, accesses to
+	 * breakpoint and watchpoint registers are treated as undefined, so
+	 * this results in boot time and runtime failures when these are
+	 * accessed and we unexpectedly take a trap.
+	 *
+	 * It's not clear if/how this can be worked around, so we blacklist
+	 * Scorpion CPUs to avoid these issues.
+	*/
+	if (read_cpuid_part() == ARM_CPU_PART_SCORPION) {
+		pr_info("Scorpion CPU detected. Hardware breakpoints and watchpoints disabled\n");
+		return 0;
+	}
+
 	has_ossr = core_has_os_save_restore();
 
 	/* Determine how many BRPs/WRPs are available. */
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c
index 9232cae..f3c6622 100644
--- a/arch/arm/kernel/kgdb.c
+++ b/arch/arm/kernel/kgdb.c
@@ -140,6 +140,8 @@
 
 static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
 {
+	if (user_mode(regs))
+		return -1;
 	kgdb_handle_exception(1, SIGTRAP, 0, regs);
 
 	return 0;
@@ -147,6 +149,8 @@
 
 static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
 {
+	if (user_mode(regs))
+		return -1;
 	compiled_break = 1;
 	kgdb_handle_exception(1, SIGTRAP, 0, regs);
 
diff --git a/arch/arm/kernel/pj4-cp0.c b/arch/arm/kernel/pj4-cp0.c
index 8153e36..7c9248b 100644
--- a/arch/arm/kernel/pj4-cp0.c
+++ b/arch/arm/kernel/pj4-cp0.c
@@ -66,9 +66,13 @@
 
 	__asm__ __volatile__ (
 		"mcr	p15, 0, %1, c1, c0, 2\n\t"
+#ifdef CONFIG_THUMB2_KERNEL
+		"isb\n\t"
+#else
 		"mrc	p15, 0, %0, c1, c0, 2\n\t"
 		"mov	%0, %0\n\t"
 		"sub	pc, pc, #4\n\t"
+#endif
 		: "=r" (temp) : "r" (value));
 }
 
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index ef9119f..d54c53b 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -600,7 +600,7 @@
 		   const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	struct pt_regs newregs;
+	struct pt_regs newregs = *task_pt_regs(target);
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				 &newregs,
@@ -733,8 +733,8 @@
 	if (ret)
 		return ret;
 
-	vfp_flush_hwstate(thread);
 	thread->vfpstate.hard = new_vfp;
+	vfp_flush_hwstate(thread);
 
 	return 0;
 }
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 20edd34..bf63b46 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -772,7 +772,7 @@
 	struct resource *res;
 
 	kernel_code.start   = virt_to_phys(_text);
-	kernel_code.end     = virt_to_phys(_etext - 1);
+	kernel_code.end     = virt_to_phys(__init_begin - 1);
 	kernel_data.start   = virt_to_phys(_sdata);
 	kernel_data.end     = virt_to_phys(_end - 1);
 
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
index 2e72be4..7cb079e 100644
--- a/arch/arm/kernel/smp_tlb.c
+++ b/arch/arm/kernel/smp_tlb.c
@@ -9,6 +9,7 @@
  */
 #include <linux/preempt.h>
 #include <linux/smp.h>
+#include <linux/uaccess.h>
 
 #include <asm/smp_plat.h>
 #include <asm/tlbflush.h>
@@ -40,8 +41,11 @@
 static inline void ipi_flush_tlb_page(void *arg)
 {
 	struct tlb_args *ta = (struct tlb_args *)arg;
+	unsigned int __ua_flags = uaccess_save_and_enable();
 
 	local_flush_tlb_page(ta->ta_vma, ta->ta_start);
+
+	uaccess_restore(__ua_flags);
 }
 
 static inline void ipi_flush_tlb_kernel_page(void *arg)
@@ -54,8 +58,11 @@
 static inline void ipi_flush_tlb_range(void *arg)
 {
 	struct tlb_args *ta = (struct tlb_args *)arg;
+	unsigned int __ua_flags = uaccess_save_and_enable();
 
 	local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+
+	uaccess_restore(__ua_flags);
 }
 
 static inline void ipi_flush_tlb_kernel_range(void *arg)
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 087acb5..5f221ac 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -279,8 +279,12 @@
 	mm_segment_t fs;
 	long ret, err, i;
 
-	if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event)))
+	if (maxevents <= 0 ||
+			maxevents > (INT_MAX/sizeof(*kbuf)) ||
+			maxevents > (INT_MAX/sizeof(*events)))
 		return -EINVAL;
+	if (!access_ok(VERIFY_WRITE, events, sizeof(*events) * maxevents))
+		return -EFAULT;
 	kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL);
 	if (!kbuf)
 		return -ENOMEM;
@@ -317,6 +321,8 @@
 
 	if (nsops < 1 || nsops > SEMOPM)
 		return -EINVAL;
+	if (!access_ok(VERIFY_READ, tsops, sizeof(*tsops) * nsops))
+		return -EFAULT;
 	sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
 	if (!sops)
 		return -ENOMEM;
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 08b7847..4f2c51e 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -42,9 +42,15 @@
  */
 static DEFINE_PER_CPU(unsigned long, cpu_scale);
 
-unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
+unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu)
 {
+#ifdef CONFIG_CPU_FREQ
+	unsigned long max_freq_scale = cpufreq_scale_max_freq_capacity(cpu);
+
+	return per_cpu(cpu_scale, cpu) * max_freq_scale >> SCHED_CAPACITY_SHIFT;
+#else
 	return per_cpu(cpu_scale, cpu);
+#endif
 }
 
 static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
@@ -153,6 +159,8 @@
 
 }
 
+static const struct sched_group_energy * const cpu_core_energy(int cpu);
+
 /*
  * Look for a customed capacity of a CPU in the cpu_capacity table during the
  * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the
@@ -160,10 +168,14 @@
  */
 static void update_cpu_capacity(unsigned int cpu)
 {
-	if (!cpu_capacity(cpu))
-		return;
+	unsigned long capacity = SCHED_CAPACITY_SCALE;
 
-	set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity);
+	if (cpu_core_energy(cpu)) {
+		int max_cap_idx = cpu_core_energy(cpu)->nr_cap_states - 1;
+		capacity = cpu_core_energy(cpu)->cap_states[max_cap_idx].cap;
+	}
+
+	set_capacity_scale(cpu, capacity);
 
 	pr_info("CPU%u: update cpu_capacity %lu\n",
 		cpu, arch_scale_cpu_capacity(NULL, cpu));
@@ -275,17 +287,138 @@
 		cpu_topology[cpuid].socket_id, mpidr);
 }
 
+/*
+ * ARM TC2 specific energy cost model data. There are no unit requirements for
+ * the data. Data can be normalized to any reference point, but the
+ * normalization must be consistent. That is, one bogo-joule/watt must be the
+ * same quantity for all data, but we don't care what it is.
+ */
+static struct idle_state idle_states_cluster_a7[] = {
+	 { .power = 25 }, /* arch_cpu_idle() (active idle) = WFI */
+	 { .power = 25 }, /* WFI */
+	 { .power = 10 }, /* cluster-sleep-l */
+	};
+
+static struct idle_state idle_states_cluster_a15[] = {
+	 { .power = 70 }, /* arch_cpu_idle() (active idle) = WFI */
+	 { .power = 70 }, /* WFI */
+	 { .power = 25 }, /* cluster-sleep-b */
+	};
+
+static struct capacity_state cap_states_cluster_a7[] = {
+	/* Cluster only power */
+	 { .cap =  150, .power = 2967, }, /*  350 MHz */
+	 { .cap =  172, .power = 2792, }, /*  400 MHz */
+	 { .cap =  215, .power = 2810, }, /*  500 MHz */
+	 { .cap =  258, .power = 2815, }, /*  600 MHz */
+	 { .cap =  301, .power = 2919, }, /*  700 MHz */
+	 { .cap =  344, .power = 2847, }, /*  800 MHz */
+	 { .cap =  387, .power = 3917, }, /*  900 MHz */
+	 { .cap =  430, .power = 4905, }, /* 1000 MHz */
+	};
+
+static struct capacity_state cap_states_cluster_a15[] = {
+	/* Cluster only power */
+	 { .cap =  426, .power =  7920, }, /*  500 MHz */
+	 { .cap =  512, .power =  8165, }, /*  600 MHz */
+	 { .cap =  597, .power =  8172, }, /*  700 MHz */
+	 { .cap =  682, .power =  8195, }, /*  800 MHz */
+	 { .cap =  768, .power =  8265, }, /*  900 MHz */
+	 { .cap =  853, .power =  8446, }, /* 1000 MHz */
+	 { .cap =  938, .power = 11426, }, /* 1100 MHz */
+	 { .cap = 1024, .power = 15200, }, /* 1200 MHz */
+	};
+
+static struct sched_group_energy energy_cluster_a7 = {
+	  .nr_idle_states = ARRAY_SIZE(idle_states_cluster_a7),
+	  .idle_states    = idle_states_cluster_a7,
+	  .nr_cap_states  = ARRAY_SIZE(cap_states_cluster_a7),
+	  .cap_states     = cap_states_cluster_a7,
+};
+
+static struct sched_group_energy energy_cluster_a15 = {
+	  .nr_idle_states = ARRAY_SIZE(idle_states_cluster_a15),
+	  .idle_states    = idle_states_cluster_a15,
+	  .nr_cap_states  = ARRAY_SIZE(cap_states_cluster_a15),
+	  .cap_states     = cap_states_cluster_a15,
+};
+
+static struct idle_state idle_states_core_a7[] = {
+	 { .power = 0 }, /* arch_cpu_idle (active idle) = WFI */
+	 { .power = 0 }, /* WFI */
+	 { .power = 0 }, /* cluster-sleep-l */
+	};
+
+static struct idle_state idle_states_core_a15[] = {
+	 { .power = 0 }, /* arch_cpu_idle (active idle) = WFI */
+	 { .power = 0 }, /* WFI */
+	 { .power = 0 }, /* cluster-sleep-b */
+	};
+
+static struct capacity_state cap_states_core_a7[] = {
+	/* Power per cpu */
+	 { .cap =  150, .power =  187, }, /*  350 MHz */
+	 { .cap =  172, .power =  275, }, /*  400 MHz */
+	 { .cap =  215, .power =  334, }, /*  500 MHz */
+	 { .cap =  258, .power =  407, }, /*  600 MHz */
+	 { .cap =  301, .power =  447, }, /*  700 MHz */
+	 { .cap =  344, .power =  549, }, /*  800 MHz */
+	 { .cap =  387, .power =  761, }, /*  900 MHz */
+	 { .cap =  430, .power = 1024, }, /* 1000 MHz */
+	};
+
+static struct capacity_state cap_states_core_a15[] = {
+	/* Power per cpu */
+	 { .cap =  426, .power = 2021, }, /*  500 MHz */
+	 { .cap =  512, .power = 2312, }, /*  600 MHz */
+	 { .cap =  597, .power = 2756, }, /*  700 MHz */
+	 { .cap =  682, .power = 3125, }, /*  800 MHz */
+	 { .cap =  768, .power = 3524, }, /*  900 MHz */
+	 { .cap =  853, .power = 3846, }, /* 1000 MHz */
+	 { .cap =  938, .power = 5177, }, /* 1100 MHz */
+	 { .cap = 1024, .power = 6997, }, /* 1200 MHz */
+	};
+
+static struct sched_group_energy energy_core_a7 = {
+	  .nr_idle_states = ARRAY_SIZE(idle_states_core_a7),
+	  .idle_states    = idle_states_core_a7,
+	  .nr_cap_states  = ARRAY_SIZE(cap_states_core_a7),
+	  .cap_states     = cap_states_core_a7,
+};
+
+static struct sched_group_energy energy_core_a15 = {
+	  .nr_idle_states = ARRAY_SIZE(idle_states_core_a15),
+	  .idle_states    = idle_states_core_a15,
+	  .nr_cap_states  = ARRAY_SIZE(cap_states_core_a15),
+	  .cap_states     = cap_states_core_a15,
+};
+
+/* sd energy functions */
+static inline
+const struct sched_group_energy * const cpu_cluster_energy(int cpu)
+{
+	return cpu_topology[cpu].socket_id ? &energy_cluster_a7 :
+			&energy_cluster_a15;
+}
+
+static inline
+const struct sched_group_energy * const cpu_core_energy(int cpu)
+{
+	return cpu_topology[cpu].socket_id ? &energy_core_a7 :
+			&energy_core_a15;
+}
+
 static inline int cpu_corepower_flags(void)
 {
-	return SD_SHARE_PKG_RESOURCES  | SD_SHARE_POWERDOMAIN;
+	return SD_SHARE_PKG_RESOURCES  | SD_SHARE_POWERDOMAIN | \
+	       SD_SHARE_CAP_STATES;
 }
 
 static struct sched_domain_topology_level arm_topology[] = {
 #ifdef CONFIG_SCHED_MC
-	{ cpu_corepower_mask, cpu_corepower_flags, SD_INIT_NAME(GMC) },
-	{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
+	{ cpu_coregroup_mask, cpu_corepower_flags, cpu_core_energy, SD_INIT_NAME(MC) },
 #endif
-	{ cpu_cpu_mask, SD_INIT_NAME(DIE) },
+	{ cpu_cpu_mask, NULL, cpu_cluster_energy, SD_INIT_NAME(DIE) },
 	{ NULL, },
 };
 
diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c
index 54a5aea..bbbffe94 100644
--- a/arch/arm/kernel/vdso.c
+++ b/arch/arm/kernel/vdso.c
@@ -17,6 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/cache.h>
 #include <linux/elf.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
@@ -39,7 +40,7 @@
 static struct page **vdso_text_pagelist;
 
 /* Total number of pages needed for the data and text portions of the VDSO. */
-unsigned int vdso_total_pages __read_mostly;
+unsigned int vdso_total_pages __ro_after_init;
 
 /*
  * The VDSO data page.
@@ -47,13 +48,13 @@
 static union vdso_data_store vdso_data_store __page_aligned_data;
 static struct vdso_data *vdso_data = &vdso_data_store.data;
 
-static struct page *vdso_data_page;
-static struct vm_special_mapping vdso_data_mapping = {
+static struct page *vdso_data_page __ro_after_init;
+static const struct vm_special_mapping vdso_data_mapping = {
 	.name = "[vvar]",
 	.pages = &vdso_data_page,
 };
 
-static struct vm_special_mapping vdso_text_mapping = {
+static struct vm_special_mapping vdso_text_mapping __ro_after_init = {
 	.name = "[vdso]",
 };
 
@@ -67,7 +68,7 @@
 /* Cached result of boot-time check for whether the arch timer exists,
  * and if so, whether the virtual counter is useable.
  */
-static bool cntvct_ok __read_mostly;
+static bool cntvct_ok __ro_after_init;
 
 static bool __init cntvct_functional(void)
 {
@@ -224,7 +225,7 @@
 				       VM_READ | VM_MAYREAD,
 				       &vdso_data_mapping);
 
-	return IS_ERR(vma) ? PTR_ERR(vma) : 0;
+	return PTR_ERR_OR_ZERO(vma);
 }
 
 /* assumes mmap_sem is write-locked */
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 8b60fde..be2ab6d 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -120,6 +120,8 @@
 #ifdef CONFIG_DEBUG_RODATA
 	. = ALIGN(1<<SECTION_SHIFT);
 #endif
+	_etext = .;			/* End of text section */
+
 	RO_DATA(PAGE_SIZE)
 
 	. = ALIGN(4);
@@ -150,8 +152,6 @@
 
 	NOTES
 
-	_etext = .;			/* End of text and rodata section */
-
 #ifndef CONFIG_XIP_KERNEL
 # ifdef CONFIG_ARM_KERNMEM_PERMS
 	. = ALIGN(1<<SECTION_SHIFT);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index e06fd29..c17cb14 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -155,8 +155,6 @@
 {
 	int i;
 
-	kvm_free_stage2_pgd(kvm);
-
 	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
 		if (kvm->vcpus[i]) {
 			kvm_arch_vcpu_free(kvm->vcpus[i]);
@@ -969,7 +967,7 @@
 	pgd_ptr = kvm_mmu_get_httbr();
 	stack_page = __this_cpu_read(kvm_arm_hyp_stack_page);
 	hyp_stack_ptr = stack_page + PAGE_SIZE;
-	vector_ptr = (unsigned long)__kvm_hyp_vector;
+	vector_ptr = (unsigned long)kvm_ksym_ref(__kvm_hyp_vector);
 
 	__cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr);
 
@@ -1061,7 +1059,8 @@
 	/*
 	 * Map the Hyp-code called directly from the host
 	 */
-	err = create_hyp_mappings(__kvm_hyp_code_start, __kvm_hyp_code_end);
+	err = create_hyp_mappings(kvm_ksym_ref(__kvm_hyp_code_start),
+				  kvm_ksym_ref(__kvm_hyp_code_end));
 	if (err) {
 		kvm_err("Cannot map world-switch code\n");
 		goto out_free_mappings;
diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S
index 3988e72..bfc5aae 100644
--- a/arch/arm/kvm/init.S
+++ b/arch/arm/kvm/init.S
@@ -110,7 +110,6 @@
 	@  - Write permission implies XN: disabled
 	@  - Instruction cache: enabled
 	@  - Data/Unified cache: enabled
-	@  - Memory alignment checks: enabled
 	@  - MMU: enabled (this code must be run from an identity mapping)
 	mrc	p15, 4, r0, c1, c0, 0	@ HSCR
 	ldr	r2, =HSCTLR_MASK
@@ -118,8 +117,8 @@
 	mrc	p15, 0, r1, c1, c0, 0	@ SCTLR
 	ldr	r2, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C)
 	and	r1, r1, r2
- ARM(	ldr	r2, =(HSCTLR_M | HSCTLR_A)			)
- THUMB(	ldr	r2, =(HSCTLR_M | HSCTLR_A | HSCTLR_TE)		)
+ ARM(	ldr	r2, =(HSCTLR_M)					)
+ THUMB(	ldr	r2, =(HSCTLR_M | HSCTLR_TE)			)
 	orr	r1, r1, r2
 	orr	r0, r0, r1
 	isb
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 61d96a6..1f1ff7e 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -300,6 +300,14 @@
 		next = kvm_pgd_addr_end(addr, end);
 		if (!pgd_none(*pgd))
 			unmap_puds(kvm, pgd, addr, next);
+		/*
+		 * If we are dealing with a large range in
+		 * stage2 table, release the kvm->mmu_lock
+		 * to prevent starvation and lockup detector
+		 * warnings.
+		 */
+		if (kvm && (next != end))
+			cond_resched_lock(&kvm->mmu_lock);
 	} while (pgd++, addr = next, addr != end);
 }
 
@@ -738,6 +746,7 @@
  */
 static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
 {
+	assert_spin_locked(&kvm->mmu_lock);
 	unmap_range(kvm, kvm->arch.pgd, start, size);
 }
 
@@ -796,6 +805,7 @@
 	int idx;
 
 	idx = srcu_read_lock(&kvm->srcu);
+	down_read(&current->mm->mmap_sem);
 	spin_lock(&kvm->mmu_lock);
 
 	slots = kvm_memslots(kvm);
@@ -803,6 +813,7 @@
 		stage2_unmap_memslot(kvm, memslot);
 
 	spin_unlock(&kvm->mmu_lock);
+	up_read(&current->mm->mmap_sem);
 	srcu_read_unlock(&kvm->srcu, idx);
 }
 
@@ -822,7 +833,10 @@
 	if (kvm->arch.pgd == NULL)
 		return;
 
+	spin_lock(&kvm->mmu_lock);
 	unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
+	spin_unlock(&kvm->mmu_lock);
+
 	kvm_free_hwpgd(kvm_get_hwpgd(kvm));
 	if (KVM_PREALLOC_LEVEL > 0)
 		kfree(kvm->arch.pgd);
@@ -855,6 +869,9 @@
 	pmd_t *pmd;
 
 	pud = stage2_get_pud(kvm, cache, addr);
+	if (!pud)
+		return NULL;
+
 	if (pud_none(*pud)) {
 		if (!cache)
 			return NULL;
@@ -886,11 +903,14 @@
 	VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd));
 
 	old_pmd = *pmd;
-	kvm_set_pmd(pmd, *new_pmd);
-	if (pmd_present(old_pmd))
+	if (pmd_present(old_pmd)) {
+		pmd_clear(pmd);
 		kvm_tlb_flush_vmid_ipa(kvm, addr);
-	else
+	} else {
 		get_page(virt_to_page(pmd));
+	}
+
+	kvm_set_pmd(pmd, *new_pmd);
 	return 0;
 }
 
@@ -939,12 +959,14 @@
 
 	/* Create 2nd stage page table mapping - Level 3 */
 	old_pte = *pte;
-	kvm_set_pte(pte, *new_pte);
-	if (pte_present(old_pte))
+	if (pte_present(old_pte)) {
+		kvm_set_pte(pte, __pte(0));
 		kvm_tlb_flush_vmid_ipa(kvm, addr);
-	else
+	} else {
 		get_page(virt_to_page(pte));
+	}
 
+	kvm_set_pte(pte, *new_pte);
 	return 0;
 }
 
@@ -1754,6 +1776,7 @@
 	    (KVM_PHYS_SIZE >> PAGE_SHIFT))
 		return -EFAULT;
 
+	down_read(&current->mm->mmap_sem);
 	/*
 	 * A memory region could potentially cover multiple VMAs, and any holes
 	 * between them, so iterate over all of them to find out if we can map
@@ -1797,8 +1820,10 @@
 			pa += vm_start - vma->vm_start;
 
 			/* IO region dirty page logging not allowed */
-			if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES)
-				return -EINVAL;
+			if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) {
+				ret = -EINVAL;
+				goto out;
+			}
 
 			ret = kvm_phys_addr_ioremap(kvm, gpa, pa,
 						    vm_end - vm_start,
@@ -1810,7 +1835,7 @@
 	} while (hva < reg_end);
 
 	if (change == KVM_MR_FLAGS_ONLY)
-		return ret;
+		goto out;
 
 	spin_lock(&kvm->mmu_lock);
 	if (ret)
@@ -1818,6 +1843,8 @@
 	else
 		stage2_flush_memslot(kvm, memslot);
 	spin_unlock(&kvm->mmu_lock);
+out:
+	up_read(&current->mm->mmap_sem);
 	return ret;
 }
 
@@ -1847,6 +1874,7 @@
 
 void kvm_arch_flush_shadow_all(struct kvm *kvm)
 {
+	kvm_free_stage2_pgd(kvm);
 }
 
 void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index a9b3b90..443db0c 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -208,9 +208,10 @@
 
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
-	int ret = 1;
+	struct kvm *kvm = vcpu->kvm;
 	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
 	unsigned long val;
+	int ret = 1;
 
 	switch (psci_fn) {
 	case PSCI_0_2_FN_PSCI_VERSION:
@@ -230,7 +231,9 @@
 		break;
 	case PSCI_0_2_FN_CPU_ON:
 	case PSCI_0_2_FN64_CPU_ON:
+		mutex_lock(&kvm->lock);
 		val = kvm_psci_vcpu_on(vcpu);
+		mutex_unlock(&kvm->lock);
 		break;
 	case PSCI_0_2_FN_AFFINITY_INFO:
 	case PSCI_0_2_FN64_AFFINITY_INFO:
@@ -279,6 +282,7 @@
 
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
+	struct kvm *kvm = vcpu->kvm;
 	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
 	unsigned long val;
 
@@ -288,7 +292,9 @@
 		val = PSCI_RET_SUCCESS;
 		break;
 	case KVM_PSCI_FN_CPU_ON:
+		mutex_lock(&kvm->lock);
 		val = kvm_psci_vcpu_on(vcpu);
+		mutex_unlock(&kvm->lock);
 		break;
 	default:
 		val = PSCI_RET_NOT_SUPPORTED;
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index 8ecfd15..df73914 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -67,7 +67,7 @@
 ENDPROC(__get_user_4)
 
 ENTRY(__get_user_8)
-	check_uaccess r0, 8, r1, r2, __get_user_bad
+	check_uaccess r0, 8, r1, r2, __get_user_bad8
 #ifdef CONFIG_THUMB2_KERNEL
 5: TUSER(ldr)	r2, [r0]
 6: TUSER(ldr)	r3, [r0, #4]
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 23726fb..d687f86 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -286,6 +286,22 @@
 		at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
 }
 
+static void sama5d3_ddr_standby(void)
+{
+	u32 lpr0;
+	u32 saved_lpr0;
+
+	saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
+	lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
+	lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN;
+
+	at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
+
+	cpu_do_idle();
+
+	at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
+}
+
 /* We manage both DDRAM/SDRAM controllers, we need more than one value to
  * remember.
  */
@@ -320,7 +336,7 @@
 	{ .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
 	{ .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
 	{ .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
-	{ .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby },
+	{ .compatible = "atmel,sama5d3-ddramc", .data = sama5d3_ddr_standby },
 	{ /*sentinel*/ }
 };
 
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 6769978..f5f81a1 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -298,6 +298,16 @@
 	.gpsc		= 1,
 };
 
+/*
+ * In order to avoid adding the emac_clk to the clock lookup table twice (and
+ * screwing up the linked list in the process) create a separate clock for
+ * mdio inheriting the rate from emac_clk.
+ */
+static struct clk mdio_clk = {
+	.name		= "mdio",
+	.parent		= &emac_clk,
+};
+
 static struct clk mcasp_clk = {
 	.name		= "mcasp",
 	.parent		= &pll0_sysclk2,
@@ -462,7 +472,7 @@
 	CLK(NULL,		"arm",		&arm_clk),
 	CLK(NULL,		"rmii",		&rmii_clk),
 	CLK("davinci_emac.1",	NULL,		&emac_clk),
-	CLK("davinci_mdio.0",	"fck",		&emac_clk),
+	CLK("davinci_mdio.0",	"fck",		&mdio_clk),
 	CLK("davinci-mcasp.0",	NULL,		&mcasp_clk),
 	CLK("da8xx_lcdc.0",	"fck",		&lcdc_clk),
 	CLK("da830-mmc.0",	NULL,		&mmcsd0_clk),
diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c
index acaf705..e08d0266 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -46,7 +46,7 @@
 static void __init imx6ul_enet_phy_init(void)
 {
 	if (IS_BUILTIN(CONFIG_PHYLIB))
-		phy_register_fixup_for_uid(PHY_ID_KSZ8081, 0xffffffff,
+		phy_register_fixup_for_uid(PHY_ID_KSZ8081, MICREL_PHY_ID_MASK,
 					   ksz8081_phy_fixup);
 }
 
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 4470376..a19d20f 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -295,7 +295,7 @@
 		val &= ~BM_CLPCR_SBYOS;
 		if (cpu_is_imx6sl())
 			val |= BM_CLPCR_BYPASS_PMIC_READY;
-		if (cpu_is_imx6sl() || cpu_is_imx6sx())
+		if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul())
 			val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
 		else
 			val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
@@ -310,7 +310,7 @@
 		val |= 0x3 << BP_CLPCR_STBY_COUNT;
 		val |= BM_CLPCR_VSTBY;
 		val |= BM_CLPCR_SBYOS;
-		if (cpu_is_imx6sl())
+		if (cpu_is_imx6sl() || cpu_is_imx6sx())
 			val |= BM_CLPCR_BYPASS_PMIC_READY;
 		if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul())
 			val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 55348ee..feed36b 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -162,22 +162,16 @@
 }
 
 /*
- * This ioremap hook is used on Armada 375/38x to ensure that PCIe
- * memory areas are mapped as MT_UNCACHED instead of MT_DEVICE. This
- * is needed as a workaround for a deadlock issue between the PCIe
- * interface and the cache controller.
+ * This ioremap hook is used on Armada 375/38x to ensure that all MMIO
+ * areas are mapped as MT_UNCACHED instead of MT_DEVICE. This is
+ * needed for the HW I/O coherency mechanism to work properly without
+ * deadlock.
  */
 static void __iomem *
-armada_pcie_wa_ioremap_caller(phys_addr_t phys_addr, size_t size,
-			      unsigned int mtype, void *caller)
+armada_wa_ioremap_caller(phys_addr_t phys_addr, size_t size,
+			 unsigned int mtype, void *caller)
 {
-	struct resource pcie_mem;
-
-	mvebu_mbus_get_pcie_mem_aperture(&pcie_mem);
-
-	if (pcie_mem.start <= phys_addr && (phys_addr + size) <= pcie_mem.end)
-		mtype = MT_UNCACHED;
-
+	mtype = MT_UNCACHED;
 	return __arm_ioremap_caller(phys_addr, size, mtype, caller);
 }
 
@@ -186,7 +180,7 @@
 	struct device_node *cache_dn;
 
 	coherency_cpu_base = of_iomap(np, 0);
-	arch_ioremap_caller = armada_pcie_wa_ioremap_caller;
+	arch_ioremap_caller = armada_wa_ioremap_caller;
 
 	/*
 	 * We should switch the PL310 to I/O coherency mode only if
diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
index 6d1dffc..748dde9 100644
--- a/arch/arm/mach-omap2/omap-headsmp.S
+++ b/arch/arm/mach-omap2/omap-headsmp.S
@@ -17,6 +17,7 @@
 
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 
 #include "omap44xx.h"
 
@@ -56,7 +57,7 @@
 	cmp	r0, r4
 	bne	wait_2
 	ldr	r12, =API_HYP_ENTRY
-	adr	r0, hyp_boot
+	badr	r0, hyp_boot
 	smc	#0
 hyp_boot:
 	b	secondary_startup
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 65024af..d3c14da 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -243,10 +243,9 @@
 		save_state = 1;
 		break;
 	case PWRDM_POWER_RET:
-		if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) {
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE))
 			save_state = 0;
-			break;
-		}
+		break;
 	default:
 		/*
 		 * CPUx CSWR is invalid hardware state. Also CPUx OSWR
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
index 907a452b..b31ad59 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
@@ -1474,6 +1474,7 @@
 {
 	RSTCTRL(am33xx_pruss_hwmod, AM43XX_RM_PER_RSTCTRL_OFFSET);
 	RSTCTRL(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTCTRL_OFFSET);
+	RSTST(am33xx_pruss_hwmod, AM43XX_RM_PER_RSTST_OFFSET);
 	RSTST(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTST_OFFSET);
 }
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index aff78d5..131f896 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -723,8 +723,20 @@
  * display serial interface controller
  */
 
+static struct omap_hwmod_class_sysconfig omap3xxx_dsi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
 static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = {
 	.name = "dsi",
+	.sysc	= &omap3xxx_dsi_sysc,
 };
 
 static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = {
diff --git a/arch/arm/mach-omap2/prcm43xx.h b/arch/arm/mach-omap2/prcm43xx.h
index 7c34c44e..babb5db 100644
--- a/arch/arm/mach-omap2/prcm43xx.h
+++ b/arch/arm/mach-omap2/prcm43xx.h
@@ -39,6 +39,7 @@
 
 /* RM RSTST offsets */
 #define AM43XX_RM_GFX_RSTST_OFFSET			0x0014
+#define AM43XX_RM_PER_RSTST_OFFSET			0x0014
 #define AM43XX_RM_WKUP_RSTST_OFFSET			0x0014
 
 /* CM instances */
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index f86692d..83fc403 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -496,8 +496,7 @@
 	__omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
 			2, "timer_sys_ck", NULL, false);
 
-	if (of_have_populated_dt())
-		clocksource_probe();
+	clocksource_probe();
 }
 
 #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM43XX)
@@ -505,6 +504,8 @@
 {
 	__omap_sync32k_timer_init(12, "secure_32k_fck", "ti,timer-secure",
 			2, "timer_sys_ck", NULL, false);
+
+	clocksource_probe();
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
@@ -513,6 +514,8 @@
 {
 	__omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
 			1, "timer_sys_ck", "ti,timer-alwon", true);
+
+	clocksource_probe();
 }
 #endif
 
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index f6d02e4..5c87dff 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -83,7 +83,8 @@
 };
 
 static struct smc91x_platdata smc91x_platdata = {
-	.flags = SMC91X_USE_32BIT | SMC91X_USE_DMA | SMC91X_NOWAIT,
+	.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
+		 SMC91X_USE_DMA | SMC91X_NOWAIT,
 };
 
 static struct platform_device smc91x_device = {
diff --git a/arch/arm/mach-pxa/pxa_cplds_irqs.c b/arch/arm/mach-pxa/pxa_cplds_irqs.c
index 2385052..e362f86 100644
--- a/arch/arm/mach-pxa/pxa_cplds_irqs.c
+++ b/arch/arm/mach-pxa/pxa_cplds_irqs.c
@@ -41,30 +41,35 @@
 	unsigned long pending;
 	unsigned int bit;
 
-	pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask;
-	for_each_set_bit(bit, &pending, CPLDS_NB_IRQ)
-		generic_handle_irq(irq_find_mapping(fpga->irqdomain, bit));
+	do {
+		pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask;
+		for_each_set_bit(bit, &pending, CPLDS_NB_IRQ) {
+			generic_handle_irq(irq_find_mapping(fpga->irqdomain,
+							    bit));
+		}
+	} while (pending);
 
 	return IRQ_HANDLED;
 }
 
-static void cplds_irq_mask_ack(struct irq_data *d)
+static void cplds_irq_mask(struct irq_data *d)
 {
 	struct cplds *fpga = irq_data_get_irq_chip_data(d);
 	unsigned int cplds_irq = irqd_to_hwirq(d);
-	unsigned int set, bit = BIT(cplds_irq);
+	unsigned int bit = BIT(cplds_irq);
 
 	fpga->irq_mask &= ~bit;
 	writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN);
-	set = readl(fpga->base + FPGA_IRQ_SET_CLR);
-	writel(set & ~bit, fpga->base + FPGA_IRQ_SET_CLR);
 }
 
 static void cplds_irq_unmask(struct irq_data *d)
 {
 	struct cplds *fpga = irq_data_get_irq_chip_data(d);
 	unsigned int cplds_irq = irqd_to_hwirq(d);
-	unsigned int bit = BIT(cplds_irq);
+	unsigned int set, bit = BIT(cplds_irq);
+
+	set = readl(fpga->base + FPGA_IRQ_SET_CLR);
+	writel(set & ~bit, fpga->base + FPGA_IRQ_SET_CLR);
 
 	fpga->irq_mask |= bit;
 	writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN);
@@ -72,7 +77,8 @@
 
 static struct irq_chip cplds_irq_chip = {
 	.name		= "pxa_cplds",
-	.irq_mask_ack	= cplds_irq_mask_ack,
+	.irq_ack	= cplds_irq_mask,
+	.irq_mask	= cplds_irq_mask,
 	.irq_unmask	= cplds_irq_unmask,
 	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
 };
diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c
index 13b1d45..9001312 100644
--- a/arch/arm/mach-pxa/xcep.c
+++ b/arch/arm/mach-pxa/xcep.c
@@ -120,7 +120,8 @@
 };
 
 static struct smc91x_platdata xcep_smc91x_info = {
-	.flags	= SMC91X_USE_32BIT | SMC91X_NOWAIT | SMC91X_USE_DMA,
+	.flags	= SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
+		  SMC91X_NOWAIT | SMC91X_USE_DMA,
 };
 
 static struct platform_device smc91x_device = {
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 44575ed..cf0a7c2 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -95,7 +95,8 @@
 };
 
 static struct smc91x_platdata smc91x_platdata = {
-	.flags = SMC91X_USE_32BIT | SMC91X_NOWAIT,
+	.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
+		 SMC91X_NOWAIT,
 };
 
 static struct platform_device realview_eth_device = {
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5c138f9..3e7a4b7 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -42,7 +42,6 @@
 #define PMU_PWRDN_SCU		4
 
 static struct regmap *pmu;
-static int has_pmu = true;
 
 static int pmu_power_domain_is_on(int pd)
 {
@@ -90,23 +89,20 @@
 	if (!IS_ERR(rstc) && !on)
 		reset_control_assert(rstc);
 
-	if (has_pmu) {
-		ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+	if (ret < 0) {
+		pr_err("%s: could not update power domain\n", __func__);
+		return ret;
+	}
+
+	ret = -1;
+	while (ret != on) {
+		ret = pmu_power_domain_is_on(pd);
 		if (ret < 0) {
-			pr_err("%s: could not update power domain\n",
+			pr_err("%s: could not read power domain state\n",
 			       __func__);
 			return ret;
 		}
-
-		ret = -1;
-		while (ret != on) {
-			ret = pmu_power_domain_is_on(pd);
-			if (ret < 0) {
-				pr_err("%s: could not read power domain state\n",
-				       __func__);
-				return ret;
-			}
-		}
 	}
 
 	if (!IS_ERR(rstc)) {
@@ -126,7 +122,7 @@
 {
 	int ret;
 
-	if (!sram_base_addr || (has_pmu && !pmu)) {
+	if (!sram_base_addr || !pmu) {
 		pr_err("%s: sram or pmu missing for cpu boot\n", __func__);
 		return -ENXIO;
 	}
@@ -279,7 +275,7 @@
 		return;
 	}
 
-	if (has_pmu && rockchip_smp_prepare_pmu())
+	if (rockchip_smp_prepare_pmu())
 		return;
 
 	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
@@ -322,13 +318,6 @@
 		pmu_set_power_domain(0 + i, false);
 }
 
-static void __init rk3036_smp_prepare_cpus(unsigned int max_cpus)
-{
-	has_pmu = false;
-
-	rockchip_smp_prepare_cpus(max_cpus);
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 static int rockchip_cpu_kill(unsigned int cpu)
 {
@@ -351,15 +340,6 @@
 }
 #endif
 
-static struct smp_operations rk3036_smp_ops __initdata = {
-	.smp_prepare_cpus	= rk3036_smp_prepare_cpus,
-	.smp_boot_secondary	= rockchip_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-	.cpu_kill		= rockchip_cpu_kill,
-	.cpu_die		= rockchip_cpu_die,
-#endif
-};
-
 static struct smp_operations rockchip_smp_ops __initdata = {
 	.smp_prepare_cpus	= rockchip_smp_prepare_cpus,
 	.smp_boot_secondary	= rockchip_boot_secondary,
@@ -369,5 +349,4 @@
 #endif
 };
 
-CPU_METHOD_OF_DECLARE(rk3036_smp, "rockchip,rk3036-smp", &rk3036_smp_ops);
 CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 608b31c..251c7b9 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -29,38 +29,31 @@
 #include "core.h"
 #include "pm.h"
 
-#define RK3036_TIMER_PHYS 0x20044000
-
 #define RK3288_GRF_SOC_CON0 0x244
 #define RK3288_TIMER6_7_PHYS 0xff810000
 
-static void rockchip_init_arch_timer_supply(resource_size_t phys, int offs)
-{
-	void __iomem *reg_base = ioremap(phys, SZ_16K);
-
-	/*
-	 * Most/all uboot versions for Rockchip SoCs don't enable
-	 * timer which is needed for the architected timer to work.
-	 * So make sure it is running during early boot.
-	 */
-	if (reg_base) {
-		writel(0, reg_base + offs + 0x10);
-		writel(0xffffffff, reg_base + offs);
-		writel(0xffffffff, reg_base + offs + 0x04);
-		writel(1, reg_base + offs + 0x10);
-		dsb();
-		iounmap(reg_base);
-	} else {
-		pr_err("rockchip: could not map timer registers\n");
-	}
-}
-
 static void __init rockchip_timer_init(void)
 {
 	if (of_machine_is_compatible("rockchip,rk3288")) {
 		struct regmap *grf;
+		void __iomem *reg_base;
 
-		rockchip_init_arch_timer_supply(RK3288_TIMER6_7_PHYS, 0x20);
+		/*
+		 * Most/all uboot versions for rk3288 don't enable timer7
+		 * which is needed for the architected timer to work.
+		 * So make sure it is running during early boot.
+		 */
+		reg_base = ioremap(RK3288_TIMER6_7_PHYS, SZ_16K);
+		if (reg_base) {
+			writel(0, reg_base + 0x30);
+			writel(0xffffffff, reg_base + 0x20);
+			writel(0xffffffff, reg_base + 0x24);
+			writel(1, reg_base + 0x30);
+			dsb();
+			iounmap(reg_base);
+		} else {
+			pr_err("rockchip: could not map timer7 registers\n");
+		}
 
 		/*
 		 * Disable auto jtag/sdmmc switching that causes issues
@@ -71,8 +64,6 @@
 			regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
 		else
 			pr_err("rockchip: could not get grf syscon\n");
-	} else if (of_machine_is_compatible("rockchip,rk3036")) {
-		rockchip_init_arch_timer_supply(RK3036_TIMER_PHYS, 0xa0);
 	}
 
 	of_clk_init(NULL);
@@ -88,7 +79,6 @@
 
 static const char * const rockchip_board_dt_compat[] = {
 	"rockchip,rk2928",
-	"rockchip,rk3036",
 	"rockchip,rk3066a",
 	"rockchip,rk3066b",
 	"rockchip,rk3188",
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index cbf53bb..0db4689 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -125,6 +125,8 @@
 }
 
 static struct clkops clk_36864_ops = {
+	.enable		= clk_cpu_enable,
+	.disable	= clk_cpu_disable,
 	.get_rate	= clk_36864_get_rate,
 };
 
@@ -140,9 +142,8 @@
 	CLKDEV_INIT(NULL, "OSTIMER0", &clk_36864),
 };
 
-static int __init sa11xx_clk_init(void)
+int __init sa11xx_clk_init(void)
 {
 	clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
 	return 0;
 }
-core_initcall(sa11xx_clk_init);
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 345e63f..3e09bed 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -34,6 +34,7 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
+#include <mach/reset.h>
 
 #include "generic.h"
 #include <clocksource/pxa.h>
@@ -95,6 +96,8 @@
 
 void sa11x0_restart(enum reboot_mode mode, const char *cmd)
 {
+	clear_reset_status(RESET_STATUS_ALL);
+
 	if (mode == REBOOT_SOFT) {
 		/* Jump into ROM at address 0 */
 		soft_restart(0);
@@ -388,6 +391,7 @@
 	sa11x0_init_irq_nodt(IRQ_GPIO0_SC, irq_resource.start);
 
 	sa1100_init_gpio();
+	sa11xx_clk_init();
 }
 
 /*
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index 0d92e11..68199b603 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -44,3 +44,5 @@
 #else
 static inline int sa11x0_pm_init(void) { return 0; }
 #endif
+
+int sa11xx_clk_init(void);
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index 1525d7b..88149f8 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -45,7 +45,7 @@
 };
 
 static struct smc91x_platdata smc91x_platdata = {
-	.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+	.flags = SMC91X_USE_16BIT | SMC91X_USE_8BIT | SMC91X_NOWAIT,
 };
 
 static struct platform_device smc91x_device = {
diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
index 62437b5..73e3adb 100644
--- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
@@ -41,40 +41,27 @@
 
 #define REGULATOR_IRQ_MASK	BIT(2)	/* IRQ2, active low */
 
+/* start of DA9210 System Control and Event Registers */
+#define DA9210_REG_MASK_A		0x54
+
 static void __iomem *irqc;
 
-static const u8 da9063_mask_regs[] = {
-	DA9063_REG_IRQ_MASK_A,
-	DA9063_REG_IRQ_MASK_B,
-	DA9063_REG_IRQ_MASK_C,
-	DA9063_REG_IRQ_MASK_D,
+/* first byte sets the memory pointer, following are consecutive reg values */
+static u8 da9063_irq_clr[] = { DA9063_REG_IRQ_MASK_A, 0xff, 0xff, 0xff, 0xff };
+static u8 da9210_irq_clr[] = { DA9210_REG_MASK_A, 0xff, 0xff };
+
+static struct i2c_msg da9xxx_msgs[2] = {
+	{
+		.addr = 0x58,
+		.len = ARRAY_SIZE(da9063_irq_clr),
+		.buf = da9063_irq_clr,
+	}, {
+		.addr = 0x68,
+		.len = ARRAY_SIZE(da9210_irq_clr),
+		.buf = da9210_irq_clr,
+	},
 };
 
-/* DA9210 System Control and Event Registers */
-#define DA9210_REG_MASK_A		0x54
-#define DA9210_REG_MASK_B		0x55
-
-static const u8 da9210_mask_regs[] = {
-	DA9210_REG_MASK_A,
-	DA9210_REG_MASK_B,
-};
-
-static void da9xxx_mask_irqs(struct i2c_client *client, const u8 regs[],
-			     unsigned int nregs)
-{
-	unsigned int i;
-
-	dev_info(&client->dev, "Masking %s interrupt sources\n", client->name);
-
-	for (i = 0; i < nregs; i++) {
-		int error = i2c_smbus_write_byte_data(client, regs[i], ~0);
-		if (error) {
-			dev_err(&client->dev, "i2c error %d\n", error);
-			return;
-		}
-	}
-}
-
 static int regulator_quirk_notify(struct notifier_block *nb,
 				  unsigned long action, void *data)
 {
@@ -93,12 +80,15 @@
 	client = to_i2c_client(dev);
 	dev_dbg(dev, "Detected %s\n", client->name);
 
-	if ((client->addr == 0x58 && !strcmp(client->name, "da9063")))
-		da9xxx_mask_irqs(client, da9063_mask_regs,
-				 ARRAY_SIZE(da9063_mask_regs));
-	else if (client->addr == 0x68 && !strcmp(client->name, "da9210"))
-		da9xxx_mask_irqs(client, da9210_mask_regs,
-				 ARRAY_SIZE(da9210_mask_regs));
+	if ((client->addr == 0x58 && !strcmp(client->name, "da9063")) ||
+	    (client->addr == 0x68 && !strcmp(client->name, "da9210"))) {
+		int ret;
+
+		dev_info(&client->dev, "clearing da9063/da9210 interrupts\n");
+		ret = i2c_transfer(client->adapter, da9xxx_msgs, ARRAY_SIZE(da9xxx_msgs));
+		if (ret != ARRAY_SIZE(da9xxx_msgs))
+			dev_err(&client->dev, "i2c error %d\n", ret);
+	}
 
 	mon = ioread32(irqc + IRQC_MONITOR);
 	if (mon & REGULATOR_IRQ_MASK)
diff --git a/arch/arm/mach-ux500/pm.c b/arch/arm/mach-ux500/pm.c
index 8538910..a970e7f 100644
--- a/arch/arm/mach-ux500/pm.c
+++ b/arch/arm/mach-ux500/pm.c
@@ -134,8 +134,8 @@
  */
 bool prcmu_is_cpu_in_wfi(int cpu)
 {
-	return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 :
-		     PRCM_ARM_WFI_STANDBY_WFI0;
+	return readl(PRCM_ARM_WFI_STANDBY) &
+		(cpu ? PRCM_ARM_WFI_STANDBY_WFI1 : PRCM_ARM_WFI_STANDBY_WFI0);
 }
 
 /*
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 6f39d03..0a43143 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -59,7 +59,7 @@
 static void __init zynq_memory_init(void)
 {
 	if (!__pa(PAGE_OFFSET))
-		memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir));
+		memblock_reserve(__pa(PAGE_OFFSET), 0x80000);
 }
 
 static struct platform_device zynq_cpuidle_device = {
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 2465995..11da0f5 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -270,6 +270,11 @@
  *	- end     - virtual end address of region
  */
 ENTRY(v6_dma_flush_range)
+#ifdef CONFIG_CACHE_FLUSH_RANGE_LIMIT
+	sub	r2, r1, r0
+	cmp	r2, #CONFIG_CACHE_FLUSH_RANGE_LIMIT
+	bhi	v6_dma_flush_dcache_all
+#endif
 #ifdef CONFIG_DMA_CACHE_RWFO
 	ldrb	r2, [r0]		@ read for ownership
 	strb	r2, [r0]		@ write for ownership
@@ -292,6 +297,18 @@
 	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
 	ret	lr
 
+#ifdef CONFIG_CACHE_FLUSH_RANGE_LIMIT
+v6_dma_flush_dcache_all:
+	mov	r0, #0
+#ifdef HARVARD_CACHE
+	mcr	p15, 0, r0, c7, c14, 0		@ D cache clean+invalidate
+#else
+	mcr	p15, 0, r0, c7, c15, 0		@ Cache clean+invalidate
+#endif
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mov	pc, lr
+#endif
+
 /*
  *	dma_map_area(start, size, dir)
  *	- start	- kernel virtual start address
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 506c225..c73f10c 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -610,9 +610,9 @@
 
 void __init early_abt_enable(void)
 {
-	fsr_info[22].fn = early_abort_handler;
+	fsr_info[FSR_FS_AEA].fn = early_abort_handler;
 	local_abt_enable();
-	fsr_info[22].fn = do_bad;
+	fsr_info[FSR_FS_AEA].fn = do_bad;
 }
 
 #ifndef CONFIG_ARM_LPAE
diff --git a/arch/arm/mm/fault.h b/arch/arm/mm/fault.h
index 05ec5e0..7883065 100644
--- a/arch/arm/mm/fault.h
+++ b/arch/arm/mm/fault.h
@@ -11,11 +11,15 @@
 #define FSR_FS5_0		(0x3f)
 
 #ifdef CONFIG_ARM_LPAE
+#define FSR_FS_AEA		17
+
 static inline int fsr_fs(unsigned int fsr)
 {
 	return fsr & FSR_FS5_0;
 }
 #else
+#define FSR_FS_AEA		22
+
 static inline int fsr_fs(unsigned int fsr)
 {
 	return (fsr & FSR_FS3_0) | (fsr & FSR_FS4) >> 6;
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 66353ca..641334e 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -89,7 +89,7 @@
 
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
@@ -140,7 +140,7 @@
 			addr = PAGE_ALIGN(addr);
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-				(!vma || addr + len <= vma->vm_start))
+				(!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 4867f5d..aead23f 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -572,7 +572,7 @@
 	 * in the Short-descriptor translation table format descriptors.
 	 */
 	if (cpu_arch == CPU_ARCH_ARMv7 &&
-		(read_cpuid_ext(CPUID_EXT_MMFR0) & 0xF) == 4) {
+		(read_cpuid_ext(CPUID_EXT_MMFR0) & 0xF) >= 4) {
 		user_pmd_table |= PMD_PXNTABLE;
 	}
 #endif
@@ -1184,15 +1184,15 @@
 
 	high_memory = __va(arm_lowmem_limit - 1) + 1;
 
+	if (!memblock_limit)
+		memblock_limit = arm_lowmem_limit;
+
 	/*
 	 * Round the memblock limit down to a pmd size.  This
 	 * helps to ensure that we will allocate memory from the
 	 * last full pmd, which should be mapped.
 	 */
-	if (memblock_limit)
-		memblock_limit = round_down(memblock_limit, PMD_SIZE);
-	if (!memblock_limit)
-		memblock_limit = arm_lowmem_limit;
+	memblock_limit = round_down(memblock_limit, PMD_SIZE);
 
 	memblock_set_current_limit(memblock_limit);
 }
diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile
index 1160434..59a8fa7 100644
--- a/arch/arm/vdso/Makefile
+++ b/arch/arm/vdso/Makefile
@@ -74,5 +74,5 @@
 	@mkdir -p $(MODLIB)/vdso
 
 PHONY += vdso_install
-vdso_install: $(obj)/vdso.so.dbg $(MODLIB)/vdso FORCE
+vdso_install: $(obj)/vdso.so.dbg $(MODLIB)/vdso
 	$(call cmd,vdso_install)
diff --git a/arch/arm/vdso/vdso.S b/arch/arm/vdso/vdso.S
index b2b97e3..a62a7b6 100644
--- a/arch/arm/vdso/vdso.S
+++ b/arch/arm/vdso/vdso.S
@@ -23,9 +23,8 @@
 #include <linux/const.h>
 #include <asm/page.h>
 
-	__PAGE_ALIGNED_DATA
-
 	.globl vdso_start, vdso_end
+	.section .data..ro_after_init
 	.balign PAGE_SIZE
 vdso_start:
 	.incbin "arch/arm/vdso/vdso.so"
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index fc7ea52..52c8c1f 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -239,8 +239,7 @@
 	 * for secondary CPUs as they are brought up.
 	 * For uniformity we use VCPUOP_register_vcpu_info even on cpu0.
 	 */
-	xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info),
-			                       sizeof(struct vcpu_info));
+	xen_vcpu_info = alloc_percpu(struct vcpu_info);
 	if (xen_vcpu_info == NULL)
 		return -ENOMEM;
 
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 7ef3fdd..35be856 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -13,6 +13,7 @@
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 	select ARCH_WANT_FRAME_POINTERS
+	select ARCH_HAS_UBSAN_SANITIZE_ALL
 	select ARM_AMBA
 	select ARM_ARCH_TIMER
 	select ARM_GIC
@@ -48,6 +49,8 @@
 	select HAVE_ALIGNED_STRUCT_PAGE if SLUB
 	select HAVE_ARCH_AUDITSYSCALL
 	select HAVE_ARCH_BITREVERSE
+	select HAVE_ARCH_HARDENED_USERCOPY
+	select HAVE_ARCH_HUGE_VMAP
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP && !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
 	select HAVE_ARCH_KGDB
@@ -72,6 +75,7 @@
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
+	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_MEMBLOCK
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
@@ -136,6 +140,10 @@
 config NO_IOPORT_MAP
 	def_bool y if !PCI
 
+config ILLEGAL_POINTER_VALUE
+	hex
+	default 0xdead000000000000
+
 config STACKTRACE_SUPPORT
 	def_bool y
 
@@ -391,6 +399,7 @@
 	bool "Cortex-A53: 843419: A load or store might access an incorrect address"
 	depends on MODULES
 	default y
+	select ARM64_MODULE_CMODEL_LARGE
 	help
 	  This option builds kernel modules using the large memory model in
 	  order to avoid the use of the ADRP instruction, which can cause
@@ -420,6 +429,15 @@
 
 	  If unsure, say Y.
 
+config CAVIUM_ERRATUM_23144
+	bool "Cavium erratum 23144: ITS SYNC hang on dual socket system"
+	depends on NUMA
+	default y
+	help
+	  ITS SYNC command hang for cross node io and collections/cpu mapping.
+
+	  If unsure, say Y.
+
 config CAVIUM_ERRATUM_23154
 	bool "Cavium erratum 23154: Access to ICC_IAR1_EL1 is not sync'ed"
 	default y
@@ -430,6 +448,17 @@
 
 	  If unsure, say Y.
 
+config CAVIUM_ERRATUM_27456
+	bool "Cavium erratum 27456: Broadcast TLBI instructions may cause icache corruption"
+	default y
+	help
+	  On ThunderX T88 pass 1.x through 2.1 parts, broadcast TLBI
+	  instructions may cause the icache to become corrupted if it
+	  contains data for a non-current ASID.  The fix is to
+	  invalidate the icache when changing the mm context.
+
+	  If unsure, say Y.
+
 endmenu
 
 
@@ -535,6 +564,9 @@
 source kernel/Kconfig.preempt
 source kernel/Kconfig.hz
 
+config ARCH_SUPPORTS_DEBUG_PAGEALLOC
+	def_bool y
+
 config ARCH_HAS_HOLES_MEMORYMODEL
 	def_bool y if SPARSEMEM
 
@@ -558,9 +590,6 @@
 config SYS_SUPPORTS_HUGETLBFS
 	def_bool y
 
-config ARCH_WANT_GENERAL_HUGETLB
-	def_bool y
-
 config ARCH_WANT_HUGE_PMD_SHARE
 	def_bool y if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36)
 
@@ -686,6 +715,14 @@
 	  If unsure, say Y
 endif
 
+config ARM64_SW_TTBR0_PAN
+	bool "Emulate Privileged Access Never using TTBR0_EL1 switching"
+	help
+	  Enabling this option prevents the kernel from accessing
+	  user-space memory directly by pointing TTBR0_EL1 to a reserved
+	  zeroed area and reserved ASID. The user access routines
+	  restore the valid TTBR0_EL1 temporarily.
+
 menu "ARMv8.1 architectural features"
 
 config ARM64_HW_AFDBM
@@ -733,10 +770,93 @@
 
 endmenu
 
+config ARM64_UAO
+	bool "Enable support for User Access Override (UAO)"
+	default y
+	help
+	  User Access Override (UAO; part of the ARMv8.2 Extensions)
+	  causes the 'unprivileged' variant of the load/store instructions to
+	  be overriden to be privileged.
+
+	  This option changes get_user() and friends to use the 'unprivileged'
+	  variant of the load/store instructions. This ensures that user-space
+	  really did have access to the supplied memory. When addr_limit is
+	  set to kernel memory the UAO bit will be set, allowing privileged
+	  access to kernel memory.
+
+	  Choosing this option will cause copy_to_user() et al to use user-space
+	  memory permissions.
+
+	  The feature is detected at runtime, the kernel will use the
+	  regular load/store instructions if the cpu does not implement the
+	  feature.
+
+config ARM64_MODULE_CMODEL_LARGE
+	bool
+
+config ARM64_MODULE_PLTS
+	bool
+	select ARM64_MODULE_CMODEL_LARGE
+	select HAVE_MOD_ARCH_SPECIFIC
+
+config RELOCATABLE
+	bool
+	help
+	  This builds the kernel as a Position Independent Executable (PIE),
+	  which retains all relocation metadata required to relocate the
+	  kernel binary at runtime to a different virtual address than the
+	  address it was linked at.
+	  Since AArch64 uses the RELA relocation format, this requires a
+	  relocation pass at runtime even if the kernel is loaded at the
+	  same address it was linked at.
+
+config RANDOMIZE_BASE
+	bool "Randomize the address of the kernel image"
+	select ARM64_MODULE_PLTS if MODULES
+	select RELOCATABLE
+	help
+	  Randomizes the virtual address at which the kernel image is
+	  loaded, as a security feature that deters exploit attempts
+	  relying on knowledge of the location of kernel internals.
+
+	  It is the bootloader's job to provide entropy, by passing a
+	  random u64 value in /chosen/kaslr-seed at kernel entry.
+
+	  When booting via the UEFI stub, it will invoke the firmware's
+	  EFI_RNG_PROTOCOL implementation (if available) to supply entropy
+	  to the kernel proper. In addition, it will randomise the physical
+	  location of the kernel Image as well.
+
+	  If unsure, say N.
+
+config RANDOMIZE_MODULE_REGION_FULL
+	bool "Randomize the module region independently from the core kernel"
+	depends on RANDOMIZE_BASE && !DYNAMIC_FTRACE
+	default y
+	help
+	  Randomizes the location of the module region without considering the
+	  location of the core kernel. This way, it is impossible for modules
+	  to leak information about the location of core kernel data structures
+	  but it does imply that function calls between modules and the core
+	  kernel will need to be resolved via veneers in the module PLT.
+
+	  When this option is not set, the module region will be randomized over
+	  a limited range that contains the [_stext, _etext] interval of the
+	  core kernel, so branch relocations are always in range.
+
 endmenu
 
 menu "Boot options"
 
+config ARM64_ACPI_PARKING_PROTOCOL
+	bool "Enable support for the ARM64 ACPI parking protocol"
+	depends on ACPI
+	help
+	  Enable support for the ARM64 ACPI parking protocol. If disabled
+	  the kernel will not allow booting through the ARM64 ACPI parking
+	  protocol even if the corresponding data is present in the ACPI
+	  MADT table.
+
 config CMDLINE
 	string "Default kernel command string"
 	default ""
@@ -802,6 +922,41 @@
 	  However, even with this option, the resultant kernel should
 	  continue to boot on existing non-UEFI platforms.
 
+config BUILD_ARM64_APPENDED_DTB_IMAGE
+	bool "Build a concatenated Image.gz/dtb by default"
+	depends on OF
+	help
+	  Enabling this option will cause a concatenated Image.gz and list of
+	  DTBs to be built by default (instead of a standalone Image.gz.)
+	  The image will built in arch/arm64/boot/Image.gz-dtb
+
+choice
+	prompt "Appended DTB Kernel Image name"
+	depends on BUILD_ARM64_APPENDED_DTB_IMAGE
+	help
+	  Enabling this option will cause a specific kernel image Image or
+	  Image.gz to be used for final image creation.
+	  The image will built in arch/arm64/boot/IMAGE-NAME-dtb
+
+	config IMG_GZ_DTB
+		bool "Image.gz-dtb"
+	config IMG_DTB
+		bool "Image-dtb"
+endchoice
+
+config BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME
+	string
+	depends on BUILD_ARM64_APPENDED_DTB_IMAGE
+	default "Image.gz-dtb" if IMG_GZ_DTB
+	default "Image-dtb" if IMG_DTB
+
+config BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES
+	string "Default dtb names"
+	depends on BUILD_ARM64_APPENDED_DTB_IMAGE
+	help
+	  Space separated list of names of dtbs to append when
+	  building a concatenated Image.gz-dtb.
+
 endmenu
 
 menu "Userspace binary formats"
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index 04fb73b..8b0cd45 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -64,13 +64,13 @@
 
 config DEBUG_RODATA
 	bool "Make kernel text and rodata read-only"
+	default y
 	help
 	  If this is set, kernel text and rodata will be made read-only. This
 	  is to help catch accidental or malicious attempts to change the
-	  kernel's executable code. Additionally splits rodata from kernel
-	  text so it can be made explicitly non-executable.
+	  kernel's executable code.
 
-          If in doubt, say Y
+	  If in doubt, say Y
 
 config DEBUG_ALIGN_RODATA
 	depends on DEBUG_RODATA && ARM64_4K_PAGES
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index f46ed86..ba55698 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -15,6 +15,10 @@
 OBJCOPYFLAGS	:=-O binary -R .note -R .note.gnu.build-id -R .comment -S
 GZFLAGS		:=-9
 
+ifneq ($(CONFIG_RELOCATABLE),)
+LDFLAGS_vmlinux		+= -pie
+endif
+
 KBUILD_DEFCONFIG := defconfig
 
 # Check for binutils support for specific extensions
@@ -27,8 +31,9 @@
 endif
 
 KBUILD_CFLAGS	+= -mgeneral-regs-only $(lseinstr)
-KBUILD_CFLAGS	+= $(call cc-option, -mpc-relative-literal-loads)
 KBUILD_CFLAGS	+= -fno-pic
+KBUILD_CFLAGS	+= -fno-asynchronous-unwind-tables
+KBUILD_CFLAGS	+= $(call cc-option, -mpc-relative-literal-loads)
 KBUILD_AFLAGS	+= $(lseinstr)
 
 ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
@@ -43,10 +48,14 @@
 
 CHECKFLAGS	+= -D__aarch64__
 
-ifeq ($(CONFIG_ARM64_ERRATUM_843419), y)
+ifeq ($(CONFIG_ARM64_MODULE_CMODEL_LARGE), y)
 KBUILD_CFLAGS_MODULE	+= -mcmodel=large
 endif
 
+ifeq ($(CONFIG_ARM64_MODULE_PLTS),y)
+KBUILD_LDFLAGS_MODULE	+= -T $(srctree)/arch/arm64/kernel/module.lds
+endif
+
 # Default value
 head-y		:= arch/arm64/kernel/head.o
 
@@ -75,7 +84,12 @@
 core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
 # Default target when executing plain make
+ifeq ($(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE),y)
+KBUILD_IMAGE	:= $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME))
+else
 KBUILD_IMAGE	:= Image.gz
+endif
+
 KBUILD_DTBS	:= dtbs
 
 all:	$(KBUILD_IMAGE) $(KBUILD_DTBS)
@@ -102,6 +116,9 @@
 dtbs_install:
 	$(Q)$(MAKE) $(dtbinst)=$(boot)/dts
 
+Image-dtb Image.gz-dtb: vmlinux scripts dtbs
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
 PHONY += vdso_install
 vdso_install:
 	$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@
@@ -111,6 +128,16 @@
 	$(Q)$(MAKE) $(clean)=$(boot)
 	$(Q)$(MAKE) $(clean)=$(boot)/dts
 
+# We need to generate vdso-offsets.h before compiling certain files in kernel/.
+# In order to do that, we should use the archprepare target, but we can't since
+# asm-offsets.h is included in some files used to generate vdso-offsets.h, and
+# asm-offsets.h is built in prepare0, for which archprepare is a dependency.
+# Therefore we need to generate the header after prepare0 has been made, hence
+# this hack.
+prepare: vdso_prepare
+vdso_prepare: prepare0
+	$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso include/generated/vdso-offsets.h
+
 define archhelp
   echo  '* Image.gz      - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)'
   echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
diff --git a/arch/arm64/boot/.gitignore b/arch/arm64/boot/.gitignore
index 8dab0bb..34e3520 100644
--- a/arch/arm64/boot/.gitignore
+++ b/arch/arm64/boot/.gitignore
@@ -1,2 +1,4 @@
 Image
+Image-dtb
 Image.gz
+Image.gz-dtb
diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile
index abcbba2..7ab8e74 100644
--- a/arch/arm64/boot/Makefile
+++ b/arch/arm64/boot/Makefile
@@ -14,14 +14,27 @@
 # Based on the ia64 boot/Makefile.
 #
 
+include $(srctree)/arch/arm64/boot/dts/Makefile
+
 targets := Image Image.gz
 
+DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES))
+ifneq ($(DTB_NAMES),)
+DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
+else
+DTB_LIST := $(dtb-y)
+endif
+DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST))
+
 $(obj)/Image: vmlinux FORCE
 	$(call if_changed,objcopy)
 
 $(obj)/Image.bz2: $(obj)/Image FORCE
 	$(call if_changed,bzip2)
 
+$(obj)/Image-dtb: $(obj)/Image $(DTB_OBJS) FORCE
+	$(call if_changed,cat)
+
 $(obj)/Image.gz: $(obj)/Image FORCE
 	$(call if_changed,gzip)
 
@@ -34,6 +47,9 @@
 $(obj)/Image.lzo: $(obj)/Image FORCE
 	$(call if_changed,lzo)
 
+$(obj)/Image.gz-dtb: $(obj)/Image.gz $(DTB_OBJS) FORCE
+	$(call if_changed,cat)
+
 install: $(obj)/Image
 	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
 	$(obj)/Image System.map "$(INSTALL_PATH)"
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index eb3c42d..062edb2 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -21,3 +21,17 @@
 dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(foreach d,$(dts-dirs), $(wildcard $(dtstree)/$(d)/*.dts)))
 
 always		:= $(dtb-y)
+
+targets += dtbs
+
+DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES))
+ifneq ($(DTB_NAMES),)
+DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
+else
+DTB_LIST := $(dtb-y)
+endif
+targets += $(DTB_LIST)
+
+dtbs: $(addprefix $(obj)/, $(DTB_LIST))
+
+clean-files := dts/*.dtb *.dtb
diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts
index 93bc3d7..29315af 100644
--- a/arch/arm64/boot/dts/arm/juno-r1.dts
+++ b/arch/arm64/boot/dts/arm/juno-r1.dts
@@ -60,6 +60,28 @@
 			};
 		};
 
+		idle-states {
+			entry-method = "arm,psci";
+
+			CPU_SLEEP_0: cpu-sleep-0 {
+				compatible = "arm,idle-state";
+				arm,psci-suspend-param = <0x0010000>;
+				local-timer-stop;
+				entry-latency-us = <300>;
+				exit-latency-us = <1200>;
+				min-residency-us = <2000>;
+			};
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				arm,psci-suspend-param = <0x1010000>;
+				local-timer-stop;
+				entry-latency-us = <400>;
+				exit-latency-us = <1200>;
+				min-residency-us = <2500>;
+			};
+		};
+
 		A57_0: cpu@0 {
 			compatible = "arm,cortex-a57","arm,armv8";
 			reg = <0x0 0x0>;
@@ -67,6 +89,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A57_L2>;
 			clocks = <&scpi_dvfs 0>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 
 		A57_1: cpu@1 {
@@ -76,6 +99,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A57_L2>;
 			clocks = <&scpi_dvfs 0>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 
 		A53_0: cpu@100 {
@@ -85,6 +109,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 
 		A53_1: cpu@101 {
@@ -94,6 +119,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 
 		A53_2: cpu@102 {
@@ -103,6 +129,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 
 		A53_3: cpu@103 {
@@ -112,6 +139,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 
 		A57_L2: l2-cache0 {
diff --git a/arch/arm64/boot/dts/arm/juno-sched-energy.dtsi b/arch/arm64/boot/dts/arm/juno-sched-energy.dtsi
new file mode 100644
index 0000000..38207e4
--- /dev/null
+++ b/arch/arm64/boot/dts/arm/juno-sched-energy.dtsi
@@ -0,0 +1,147 @@
+/*
+ * ARM JUNO specific energy cost model data. There are no unit requirements for
+ * the data. Data can be normalized to any reference point, but the
+ * normalization must be consistent. That is, one bogo-joule/watt must be the
+ * same quantity for all data, but we don't care what it is.
+ */
+
+/* static struct idle_state idle_states_cluster_a53[] = { */
+/*        { .power = 56 }, /\* arch_cpu_idle() (active idle) = WFI *\/ */
+/*        { .power = 56 }, /\* WFI *\/ */
+/*        { .power = 56 }, /\* cpu-sleep-0 *\/ */
+/*        { .power = 17 }, /\* cluster-sleep-0 *\/ */
+/* }; */
+
+/* static struct idle_state idle_states_cluster_a57[] = { */
+/*        { .power = 65 }, /\* arch_cpu_idle() (active idle) = WFI *\/ */
+/*        { .power = 65 }, /\* WFI *\/ */
+/*        { .power = 65 }, /\* cpu-sleep-0 *\/ */
+/*        { .power = 24 }, /\* cluster-sleep-0 *\/ */
+/* }; */
+
+/* static struct capacity_state cap_states_cluster_a53[] = { */
+/*         /\* Power per cluster *\/ */
+/*        { .cap =  235, .power = 26, }, /\*  450 MHz *\/ */
+/*        { .cap =  303, .power = 30, }, /\*  575 MHz *\/ */
+/*        { .cap =  368, .power = 39, }, /\*  700 MHz *\/ */
+/*        { .cap =  406, .power = 47, }, /\*  775 MHz *\/ */
+/*        { .cap =  447, .power = 57, }, /\*  850 Mhz *\/ */
+/* }; */
+
+/* static struct capacity_state cap_states_cluster_a57[] = { */
+/*         /\* Power per cluster *\/ */
+/*        { .cap =  417, .power = 24, }, /\*  450 MHz *\/ */
+/*        { .cap =  579, .power = 32, }, /\*  625 MHz *\/ */
+/*        { .cap =  744, .power = 43, }, /\*  800 MHz *\/ */
+/*        { .cap =  883, .power = 49, }, /\*  950 MHz *\/ */
+/*        { .cap = 1024, .power = 64, }, /\* 1100 MHz *\/ */
+/* }; */
+
+/* static struct sched_group_energy energy_cluster_a53 = { */
+/*        .nr_idle_states = ARRAY_SIZE(idle_states_cluster_a53), */
+/*        .idle_states    = idle_states_cluster_a53, */
+/*        .nr_cap_states  = ARRAY_SIZE(cap_states_cluster_a53), */
+/*        .cap_states     = cap_states_cluster_a53, */
+/* }; */
+
+/* static struct sched_group_energy energy_cluster_a57 = { */
+/*        .nr_idle_states = ARRAY_SIZE(idle_states_cluster_a57), */
+/*        .idle_states    = idle_states_cluster_a57, */
+/*        .nr_cap_states  = ARRAY_SIZE(cap_states_cluster_a57), */
+/*        .cap_states     = cap_states_cluster_a57, */
+/* }; */
+
+/* static struct idle_state idle_states_core_a53[] = { */
+/*        { .power = 6 }, /\* arch_cpu_idle() (active idle) = WFI *\/ */
+/*        { .power = 6 }, /\* WFI *\/ */
+/*        { .power = 0 }, /\* cpu-sleep-0 *\/ */
+/*        { .power = 0 }, /\* cluster-sleep-0 *\/ */
+/* }; */
+
+/* static struct idle_state idle_states_core_a57[] = { */
+/*        { .power = 15 }, /\* arch_cpu_idle() (active idle) = WFI *\/ */
+/*        { .power = 15 }, /\* WFI *\/ */
+/*        { .power = 0  }, /\* cpu-sleep-0 *\/ */
+/*        { .power = 0  }, /\* cluster-sleep-0 *\/ */
+/* }; */
+
+/* static struct capacity_state cap_states_core_a53[] = { */
+/*         /\* Power per cpu *\/ */
+/*        { .cap =  235, .power =  33, }, /\*  450 MHz *\/ */
+/*        { .cap =  302, .power =  46, }, /\*  575 MHz *\/ */
+/*        { .cap =  368, .power =  61, }, /\*  700 MHz *\/ */
+/*        { .cap =  406, .power =  76, }, /\*  775 MHz *\/ */
+/*        { .cap =  447, .power =  93, }, /\*  850 Mhz *\/ */
+/* }; */
+
+/* static struct capacity_state cap_states_core_a57[] = { */
+/*         /\* Power per cpu *\/ */
+/*        { .cap =  417, .power = 168, }, /\*  450 MHz *\/ */
+/*        { .cap =  579, .power = 251, }, /\*  625 MHz *\/ */
+/*        { .cap =  744, .power = 359, }, /\*  800 MHz *\/ */
+/*        { .cap =  883, .power = 479, }, /\*  950 MHz *\/ */
+/*        { .cap = 1024, .power = 616, }, /\* 1100 MHz *\/ */
+/* }; */
+
+energy-costs {
+	CPU_COST_A57: core-cost0 {
+		busy-cost-data = <
+			417   168
+			579   251
+			744   359
+			883   479
+		       1023   616
+		>;
+		idle-cost-data = <
+		      15
+		      15
+		       0
+		       0
+		>;
+	};
+	CPU_COST_A53: core-cost1 {
+		busy-cost-data = <
+			235    33
+			302    46
+			368    61
+			406    76
+			447    93
+		>;
+		idle-cost-data = <
+		      6
+		      6
+		      0
+		      0
+		>;
+	};
+	CLUSTER_COST_A57: cluster-cost0 {
+		busy-cost-data = <
+			417    24
+			579    32
+			744    43
+			883    49
+		       1024    64
+		>;
+		idle-cost-data = <
+			 65
+			 65
+			 65
+			 24
+		>;
+	};
+	CLUSTER_COST_A53: cluster-cost1 {
+		busy-cost-data = <
+			235    26
+			303    30
+			368    39
+			406    47
+			447    57
+		>;
+		idle-cost-data = <
+			56
+			56
+			56
+			17
+		>;
+	};
+};
diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
index 53442b5..a500493 100644
--- a/arch/arm64/boot/dts/arm/juno.dts
+++ b/arch/arm64/boot/dts/arm/juno.dts
@@ -60,6 +60,28 @@
 			};
 		};
 
+		idle-states {
+			entry-method = "arm,psci";
+
+			CPU_SLEEP_0: cpu-sleep-0 {
+				compatible = "arm,idle-state";
+				arm,psci-suspend-param = <0x0010000>;
+				local-timer-stop;
+				entry-latency-us = <300>;
+				exit-latency-us = <1200>;
+				min-residency-us = <2000>;
+			};
+
+			CLUSTER_SLEEP_0: cluster-sleep-0 {
+				compatible = "arm,idle-state";
+				arm,psci-suspend-param = <0x1010000>;
+				local-timer-stop;
+				entry-latency-us = <400>;
+				exit-latency-us = <1200>;
+				min-residency-us = <2500>;
+			};
+		};
+
 		A57_0: cpu@0 {
 			compatible = "arm,cortex-a57","arm,armv8";
 			reg = <0x0 0x0>;
@@ -67,6 +89,8 @@
 			enable-method = "psci";
 			next-level-cache = <&A57_L2>;
 			clocks = <&scpi_dvfs 0>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			sched-energy-costs = <&CPU_COST_A57 &CLUSTER_COST_A57>;
 		};
 
 		A57_1: cpu@1 {
@@ -76,6 +100,8 @@
 			enable-method = "psci";
 			next-level-cache = <&A57_L2>;
 			clocks = <&scpi_dvfs 0>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			sched-energy-costs = <&CPU_COST_A57 &CLUSTER_COST_A57>;
 		};
 
 		A53_0: cpu@100 {
@@ -85,6 +111,8 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>;
 		};
 
 		A53_1: cpu@101 {
@@ -94,6 +122,8 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>;
 		};
 
 		A53_2: cpu@102 {
@@ -103,6 +133,8 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>;
 		};
 
 		A53_3: cpu@103 {
@@ -112,6 +144,8 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>;
 		};
 
 		A57_L2: l2-cache0 {
@@ -121,6 +155,8 @@
 		A53_L2: l2-cache1 {
 			compatible = "cache";
 		};
+
+		/include/ "juno-sched-energy.dtsi"
 	};
 
 	pmu_a57 {
diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
index cc093a4..e0ee2b0 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -262,6 +262,8 @@
 		#io-channel-cells = <1>;
 		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
 		clock-names = "saradc", "apb_pclk";
+		resets = <&cru SRST_SARADC>;
+		reset-names = "saradc-apb";
 		status = "disabled";
 	};
 
@@ -517,7 +519,7 @@
 		#address-cells = <0>;
 
 		reg = <0x0 0xffb71000 0x0 0x1000>,
-		      <0x0 0xffb72000 0x0 0x1000>,
+		      <0x0 0xffb72000 0x0 0x2000>,
 		      <0x0 0xffb74000 0x0 0x2000>,
 		      <0x0 0xffb76000 0x0 0x2000>;
 		interrupts = <GIC_PPI 9
diff --git a/arch/arm64/configs/ranchu64_defconfig b/arch/arm64/configs/ranchu64_defconfig
new file mode 100644
index 0000000..fc55008
--- /dev/null
+++ b/arch/arm64/configs/ranchu64_defconfig
@@ -0,0 +1,312 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_ARCH_MMAP_RND_BITS=24
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_NR_CPUS=4
+CONFIG_PREEMPT=y
+CONFIG_KSM=y
+CONFIG_SECCOMP=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_SWP_EMULATION=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+CONFIG_CMDLINE="console=ttyAMA0"
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_EUI64=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_TARGET_HL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_VIRTIO_BLK=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_VIRTIO_NET=y
+CONFIG_SMC91X=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TABLET=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_BATTERY_GOLDFISH=y
+# CONFIG_HWMON is not set
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_FB=y
+CONFIG_FB_GOLDFISH=y
+CONFIG_FB_SIMPLE=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_PRODIKEYS=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_WALTOP=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_PRIMAX=y
+CONFIG_HID_SAITEK=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SPEEDLINK=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_WIIMOTE=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_HID_ZYDACRON=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
+CONFIG_SW_SYNC_USER=y
+CONFIG_ION=y
+CONFIG_GOLDFISH_AUDIO=y
+CONFIG_GOLDFISH=y
+CONFIG_GOLDFISH_PIPE=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_TIMEOUT=5
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_FTRACE is not set
+CONFIG_ATOMIC64_SELFTEST=y
+CONFIG_DEBUG_RODATA=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_SELINUX=y
diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig
index 2cf32e9..de1aab4 100644
--- a/arch/arm64/crypto/Kconfig
+++ b/arch/arm64/crypto/Kconfig
@@ -23,6 +23,11 @@
 	depends on ARM64 && KERNEL_MODE_NEON
 	select CRYPTO_HASH
 
+config CRYPTO_POLY_HASH_ARM64_CE
+	tristate "poly_hash (for HEH encryption mode) using ARMv8 Crypto Extensions"
+	depends on ARM64 && KERNEL_MODE_NEON
+	select CRYPTO_HASH
+
 config CRYPTO_AES_ARM64_CE
 	tristate "AES core cipher using ARMv8 Crypto Extensions"
 	depends on ARM64 && KERNEL_MODE_NEON
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
index abb79b3..f0a8f24 100644
--- a/arch/arm64/crypto/Makefile
+++ b/arch/arm64/crypto/Makefile
@@ -17,6 +17,9 @@
 obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o
 ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o
 
+obj-$(CONFIG_CRYPTO_POLY_HASH_ARM64_CE) += poly-hash-ce.o
+poly-hash-ce-y := poly-hash-ce-glue.o poly-hash-ce-core.o
+
 obj-$(CONFIG_CRYPTO_AES_ARM64_CE) += aes-ce-cipher.o
 CFLAGS_aes-ce-cipher.o += -march=armv8-a+crypto
 
diff --git a/arch/arm64/crypto/aes-ce-ccm-core.S b/arch/arm64/crypto/aes-ce-ccm-core.S
index a2a7fbc..3363560 100644
--- a/arch/arm64/crypto/aes-ce-ccm-core.S
+++ b/arch/arm64/crypto/aes-ce-ccm-core.S
@@ -9,6 +9,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 	.text
 	.arch	armv8-a+crypto
@@ -19,7 +20,7 @@
 	 */
 ENTRY(ce_aes_ccm_auth_data)
 	ldr	w8, [x3]			/* leftover from prev round? */
-	ld1	{v0.2d}, [x0]			/* load mac */
+	ld1	{v0.16b}, [x0]			/* load mac */
 	cbz	w8, 1f
 	sub	w8, w8, #16
 	eor	v1.16b, v1.16b, v1.16b
@@ -31,7 +32,7 @@
 	beq	8f				/* out of input? */
 	cbnz	w8, 0b
 	eor	v0.16b, v0.16b, v1.16b
-1:	ld1	{v3.2d}, [x4]			/* load first round key */
+1:	ld1	{v3.16b}, [x4]			/* load first round key */
 	prfm	pldl1strm, [x1]
 	cmp	w5, #12				/* which key size? */
 	add	x6, x4, #16
@@ -41,17 +42,17 @@
 	mov	v5.16b, v3.16b
 	b	4f
 2:	mov	v4.16b, v3.16b
-	ld1	{v5.2d}, [x6], #16		/* load 2nd round key */
+	ld1	{v5.16b}, [x6], #16		/* load 2nd round key */
 3:	aese	v0.16b, v4.16b
 	aesmc	v0.16b, v0.16b
-4:	ld1	{v3.2d}, [x6], #16		/* load next round key */
+4:	ld1	{v3.16b}, [x6], #16		/* load next round key */
 	aese	v0.16b, v5.16b
 	aesmc	v0.16b, v0.16b
-5:	ld1	{v4.2d}, [x6], #16		/* load next round key */
+5:	ld1	{v4.16b}, [x6], #16		/* load next round key */
 	subs	w7, w7, #3
 	aese	v0.16b, v3.16b
 	aesmc	v0.16b, v0.16b
-	ld1	{v5.2d}, [x6], #16		/* load next round key */
+	ld1	{v5.16b}, [x6], #16		/* load next round key */
 	bpl	3b
 	aese	v0.16b, v4.16b
 	subs	w2, w2, #16			/* last data? */
@@ -60,7 +61,7 @@
 	ld1	{v1.16b}, [x1], #16		/* load next input block */
 	eor	v0.16b, v0.16b, v1.16b		/* xor with mac */
 	bne	1b
-6:	st1	{v0.2d}, [x0]			/* store mac */
+6:	st1	{v0.16b}, [x0]			/* store mac */
 	beq	10f
 	adds	w2, w2, #16
 	beq	10f
@@ -79,7 +80,7 @@
 	adds	w7, w7, #1
 	bne	9b
 	eor	v0.16b, v0.16b, v1.16b
-	st1	{v0.2d}, [x0]
+	st1	{v0.16b}, [x0]
 10:	str	w8, [x3]
 	ret
 ENDPROC(ce_aes_ccm_auth_data)
@@ -89,27 +90,27 @@
 	 * 			 u32 rounds);
 	 */
 ENTRY(ce_aes_ccm_final)
-	ld1	{v3.2d}, [x2], #16		/* load first round key */
-	ld1	{v0.2d}, [x0]			/* load mac */
+	ld1	{v3.16b}, [x2], #16		/* load first round key */
+	ld1	{v0.16b}, [x0]			/* load mac */
 	cmp	w3, #12				/* which key size? */
 	sub	w3, w3, #2			/* modified # of rounds */
-	ld1	{v1.2d}, [x1]			/* load 1st ctriv */
+	ld1	{v1.16b}, [x1]			/* load 1st ctriv */
 	bmi	0f
 	bne	3f
 	mov	v5.16b, v3.16b
 	b	2f
 0:	mov	v4.16b, v3.16b
-1:	ld1	{v5.2d}, [x2], #16		/* load next round key */
+1:	ld1	{v5.16b}, [x2], #16		/* load next round key */
 	aese	v0.16b, v4.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v4.16b
 	aesmc	v1.16b, v1.16b
-2:	ld1	{v3.2d}, [x2], #16		/* load next round key */
+2:	ld1	{v3.16b}, [x2], #16		/* load next round key */
 	aese	v0.16b, v5.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v5.16b
 	aesmc	v1.16b, v1.16b
-3:	ld1	{v4.2d}, [x2], #16		/* load next round key */
+3:	ld1	{v4.16b}, [x2], #16		/* load next round key */
 	subs	w3, w3, #3
 	aese	v0.16b, v3.16b
 	aesmc	v0.16b, v0.16b
@@ -120,47 +121,47 @@
 	aese	v1.16b, v4.16b
 	/* final round key cancels out */
 	eor	v0.16b, v0.16b, v1.16b		/* en-/decrypt the mac */
-	st1	{v0.2d}, [x0]			/* store result */
+	st1	{v0.16b}, [x0]			/* store result */
 	ret
 ENDPROC(ce_aes_ccm_final)
 
 	.macro	aes_ccm_do_crypt,enc
 	ldr	x8, [x6, #8]			/* load lower ctr */
-	ld1	{v0.2d}, [x5]			/* load mac */
-	rev	x8, x8				/* keep swabbed ctr in reg */
+	ld1	{v0.16b}, [x5]			/* load mac */
+CPU_LE(	rev	x8, x8			)	/* keep swabbed ctr in reg */
 0:	/* outer loop */
-	ld1	{v1.1d}, [x6]			/* load upper ctr */
+	ld1	{v1.8b}, [x6]			/* load upper ctr */
 	prfm	pldl1strm, [x1]
 	add	x8, x8, #1
 	rev	x9, x8
 	cmp	w4, #12				/* which key size? */
 	sub	w7, w4, #2			/* get modified # of rounds */
 	ins	v1.d[1], x9			/* no carry in lower ctr */
-	ld1	{v3.2d}, [x3]			/* load first round key */
+	ld1	{v3.16b}, [x3]			/* load first round key */
 	add	x10, x3, #16
 	bmi	1f
 	bne	4f
 	mov	v5.16b, v3.16b
 	b	3f
 1:	mov	v4.16b, v3.16b
-	ld1	{v5.2d}, [x10], #16		/* load 2nd round key */
+	ld1	{v5.16b}, [x10], #16		/* load 2nd round key */
 2:	/* inner loop: 3 rounds, 2x interleaved */
 	aese	v0.16b, v4.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v4.16b
 	aesmc	v1.16b, v1.16b
-3:	ld1	{v3.2d}, [x10], #16		/* load next round key */
+3:	ld1	{v3.16b}, [x10], #16		/* load next round key */
 	aese	v0.16b, v5.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v5.16b
 	aesmc	v1.16b, v1.16b
-4:	ld1	{v4.2d}, [x10], #16		/* load next round key */
+4:	ld1	{v4.16b}, [x10], #16		/* load next round key */
 	subs	w7, w7, #3
 	aese	v0.16b, v3.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v3.16b
 	aesmc	v1.16b, v1.16b
-	ld1	{v5.2d}, [x10], #16		/* load next round key */
+	ld1	{v5.16b}, [x10], #16		/* load next round key */
 	bpl	2b
 	aese	v0.16b, v4.16b
 	aese	v1.16b, v4.16b
@@ -177,14 +178,14 @@
 	eor	v0.16b, v0.16b, v2.16b		/* xor mac with pt ^ rk[last] */
 	st1	{v1.16b}, [x0], #16		/* write output block */
 	bne	0b
-	rev	x8, x8
-	st1	{v0.2d}, [x5]			/* store mac */
+CPU_LE(	rev	x8, x8			)
+	st1	{v0.16b}, [x5]			/* store mac */
 	str	x8, [x6, #8]			/* store lsb end of ctr (BE) */
 5:	ret
 
 6:	eor	v0.16b, v0.16b, v5.16b		/* final round mac */
 	eor	v1.16b, v1.16b, v5.16b		/* final round enc */
-	st1	{v0.2d}, [x5]			/* store mac */
+	st1	{v0.16b}, [x5]			/* store mac */
 	add	w2, w2, #16			/* process partial tail block */
 7:	ldrb	w9, [x1], #1			/* get 1 byte of input */
 	umov	w6, v1.b[0]			/* get top crypted ctr byte */
diff --git a/arch/arm64/crypto/aes-ce-cipher.c b/arch/arm64/crypto/aes-ce-cipher.c
index f7bd9bf..50d9fe1 100644
--- a/arch/arm64/crypto/aes-ce-cipher.c
+++ b/arch/arm64/crypto/aes-ce-cipher.c
@@ -47,24 +47,24 @@
 	kernel_neon_begin_partial(4);
 
 	__asm__("	ld1	{v0.16b}, %[in]			;"
-		"	ld1	{v1.2d}, [%[key]], #16		;"
+		"	ld1	{v1.16b}, [%[key]], #16		;"
 		"	cmp	%w[rounds], #10			;"
 		"	bmi	0f				;"
 		"	bne	3f				;"
 		"	mov	v3.16b, v1.16b			;"
 		"	b	2f				;"
 		"0:	mov	v2.16b, v1.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"1:	aese	v0.16b, v2.16b			;"
 		"	aesmc	v0.16b, v0.16b			;"
-		"2:	ld1	{v1.2d}, [%[key]], #16		;"
+		"2:	ld1	{v1.16b}, [%[key]], #16		;"
 		"	aese	v0.16b, v3.16b			;"
 		"	aesmc	v0.16b, v0.16b			;"
-		"3:	ld1	{v2.2d}, [%[key]], #16		;"
+		"3:	ld1	{v2.16b}, [%[key]], #16		;"
 		"	subs	%w[rounds], %w[rounds], #3	;"
 		"	aese	v0.16b, v1.16b			;"
 		"	aesmc	v0.16b, v0.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"	bpl	1b				;"
 		"	aese	v0.16b, v2.16b			;"
 		"	eor	v0.16b, v0.16b, v3.16b		;"
@@ -92,24 +92,24 @@
 	kernel_neon_begin_partial(4);
 
 	__asm__("	ld1	{v0.16b}, %[in]			;"
-		"	ld1	{v1.2d}, [%[key]], #16		;"
+		"	ld1	{v1.16b}, [%[key]], #16		;"
 		"	cmp	%w[rounds], #10			;"
 		"	bmi	0f				;"
 		"	bne	3f				;"
 		"	mov	v3.16b, v1.16b			;"
 		"	b	2f				;"
 		"0:	mov	v2.16b, v1.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"1:	aesd	v0.16b, v2.16b			;"
 		"	aesimc	v0.16b, v0.16b			;"
-		"2:	ld1	{v1.2d}, [%[key]], #16		;"
+		"2:	ld1	{v1.16b}, [%[key]], #16		;"
 		"	aesd	v0.16b, v3.16b			;"
 		"	aesimc	v0.16b, v0.16b			;"
-		"3:	ld1	{v2.2d}, [%[key]], #16		;"
+		"3:	ld1	{v2.16b}, [%[key]], #16		;"
 		"	subs	%w[rounds], %w[rounds], #3	;"
 		"	aesd	v0.16b, v1.16b			;"
 		"	aesimc	v0.16b, v0.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"	bpl	1b				;"
 		"	aesd	v0.16b, v2.16b			;"
 		"	eor	v0.16b, v0.16b, v3.16b		;"
@@ -173,7 +173,12 @@
 		u32 *rki = ctx->key_enc + (i * kwords);
 		u32 *rko = rki + kwords;
 
+#ifndef CONFIG_CPU_BIG_ENDIAN
 		rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0];
+#else
+		rko[0] = rol32(aes_sub(rki[kwords - 1]), 8) ^ (rcon[i] << 24) ^
+			 rki[0];
+#endif
 		rko[1] = rko[0] ^ rki[1];
 		rko[2] = rko[1] ^ rki[2];
 		rko[3] = rko[2] ^ rki[3];
diff --git a/arch/arm64/crypto/aes-ce.S b/arch/arm64/crypto/aes-ce.S
index 78f3cfe..b46093d 100644
--- a/arch/arm64/crypto/aes-ce.S
+++ b/arch/arm64/crypto/aes-ce.S
@@ -10,6 +10,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #define AES_ENTRY(func)		ENTRY(ce_ ## func)
 #define AES_ENDPROC(func)	ENDPROC(ce_ ## func)
diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c
index 05d9e16..448b874 100644
--- a/arch/arm64/crypto/aes-glue.c
+++ b/arch/arm64/crypto/aes-glue.c
@@ -211,7 +211,7 @@
 		err = blkcipher_walk_done(desc, &walk,
 					  walk.nbytes % AES_BLOCK_SIZE);
 	}
-	if (nbytes) {
+	if (walk.nbytes % AES_BLOCK_SIZE) {
 		u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
 		u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE;
 		u8 __aligned(8) tail[AES_BLOCK_SIZE];
@@ -294,7 +294,7 @@
 	.cra_blkcipher = {
 		.min_keysize	= AES_MIN_KEY_SIZE,
 		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
+		.ivsize		= 0,
 		.setkey		= aes_setkey,
 		.encrypt	= ecb_encrypt,
 		.decrypt	= ecb_decrypt,
@@ -371,7 +371,7 @@
 	.cra_ablkcipher = {
 		.min_keysize	= AES_MIN_KEY_SIZE,
 		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
+		.ivsize		= 0,
 		.setkey		= ablk_set_key,
 		.encrypt	= ablk_encrypt,
 		.decrypt	= ablk_decrypt,
diff --git a/arch/arm64/crypto/aes-modes.S b/arch/arm64/crypto/aes-modes.S
index f6e372c..838dad5 100644
--- a/arch/arm64/crypto/aes-modes.S
+++ b/arch/arm64/crypto/aes-modes.S
@@ -193,15 +193,16 @@
 	cbz		w6, .Lcbcencloop
 
 	ld1		{v0.16b}, [x5]			/* get iv */
-	enc_prepare	w3, x2, x5
+	enc_prepare	w3, x2, x6
 
 .Lcbcencloop:
 	ld1		{v1.16b}, [x1], #16		/* get next pt block */
 	eor		v0.16b, v0.16b, v1.16b		/* ..and xor with iv */
-	encrypt_block	v0, w3, x2, x5, w6
+	encrypt_block	v0, w3, x2, x6, w7
 	st1		{v0.16b}, [x0], #16
 	subs		w4, w4, #1
 	bne		.Lcbcencloop
+	st1		{v0.16b}, [x5]			/* return iv */
 	ret
 AES_ENDPROC(aes_cbc_encrypt)
 
@@ -211,7 +212,7 @@
 	cbz		w6, .LcbcdecloopNx
 
 	ld1		{v7.16b}, [x5]			/* get iv */
-	dec_prepare	w3, x2, x5
+	dec_prepare	w3, x2, x6
 
 .LcbcdecloopNx:
 #if INTERLEAVE >= 2
@@ -248,7 +249,7 @@
 .Lcbcdecloop:
 	ld1		{v1.16b}, [x1], #16		/* get next ct block */
 	mov		v0.16b, v1.16b			/* ...and copy to v0 */
-	decrypt_block	v0, w3, x2, x5, w6
+	decrypt_block	v0, w3, x2, x6, w7
 	eor		v0.16b, v0.16b, v7.16b		/* xor with iv => pt */
 	mov		v7.16b, v1.16b			/* ct is next iv */
 	st1		{v0.16b}, [x0], #16
@@ -256,6 +257,7 @@
 	bne		.Lcbcdecloop
 .Lcbcdecout:
 	FRAME_POP
+	st1		{v7.16b}, [x5]			/* return iv */
 	ret
 AES_ENDPROC(aes_cbc_decrypt)
 
@@ -267,24 +269,15 @@
 
 AES_ENTRY(aes_ctr_encrypt)
 	FRAME_PUSH
-	cbnz		w6, .Lctrfirst		/* 1st time around? */
-	umov		x5, v4.d[1]		/* keep swabbed ctr in reg */
-	rev		x5, x5
-#if INTERLEAVE >= 2
-	cmn		w5, w4			/* 32 bit overflow? */
-	bcs		.Lctrinc
-	add		x5, x5, #1		/* increment BE ctr */
-	b		.LctrincNx
-#else
-	b		.Lctrinc
-#endif
-.Lctrfirst:
+	cbz		w6, .Lctrnotfirst	/* 1st time around? */
 	enc_prepare	w3, x2, x6
 	ld1		{v4.16b}, [x5]
-	umov		x5, v4.d[1]		/* keep swabbed ctr in reg */
-	rev		x5, x5
+
+.Lctrnotfirst:
+	umov		x8, v4.d[1]		/* keep swabbed ctr in reg */
+	rev		x8, x8
 #if INTERLEAVE >= 2
-	cmn		w5, w4			/* 32 bit overflow? */
+	cmn		w8, w4			/* 32 bit overflow? */
 	bcs		.Lctrloop
 .LctrloopNx:
 	subs		w4, w4, #INTERLEAVE
@@ -292,11 +285,11 @@
 #if INTERLEAVE == 2
 	mov		v0.8b, v4.8b
 	mov		v1.8b, v4.8b
-	rev		x7, x5
-	add		x5, x5, #1
+	rev		x7, x8
+	add		x8, x8, #1
 	ins		v0.d[1], x7
-	rev		x7, x5
-	add		x5, x5, #1
+	rev		x7, x8
+	add		x8, x8, #1
 	ins		v1.d[1], x7
 	ld1		{v2.16b-v3.16b}, [x1], #32	/* get 2 input blocks */
 	do_encrypt_block2x
@@ -305,7 +298,7 @@
 	st1		{v0.16b-v1.16b}, [x0], #32
 #else
 	ldr		q8, =0x30000000200000001	/* addends 1,2,3[,0] */
-	dup		v7.4s, w5
+	dup		v7.4s, w8
 	mov		v0.16b, v4.16b
 	add		v7.4s, v7.4s, v8.4s
 	mov		v1.16b, v4.16b
@@ -323,18 +316,12 @@
 	eor		v2.16b, v7.16b, v2.16b
 	eor		v3.16b, v5.16b, v3.16b
 	st1		{v0.16b-v3.16b}, [x0], #64
-	add		x5, x5, #INTERLEAVE
+	add		x8, x8, #INTERLEAVE
 #endif
-	cbz		w4, .LctroutNx
-.LctrincNx:
-	rev		x7, x5
+	rev		x7, x8
 	ins		v4.d[1], x7
+	cbz		w4, .Lctrout
 	b		.LctrloopNx
-.LctroutNx:
-	sub		x5, x5, #1
-	rev		x7, x5
-	ins		v4.d[1], x7
-	b		.Lctrout
 .Lctr1x:
 	adds		w4, w4, #INTERLEAVE
 	beq		.Lctrout
@@ -342,30 +329,39 @@
 .Lctrloop:
 	mov		v0.16b, v4.16b
 	encrypt_block	v0, w3, x2, x6, w7
+
+	adds		x8, x8, #1		/* increment BE ctr */
+	rev		x7, x8
+	ins		v4.d[1], x7
+	bcs		.Lctrcarry		/* overflow? */
+
+.Lctrcarrydone:
 	subs		w4, w4, #1
 	bmi		.Lctrhalfblock		/* blocks < 0 means 1/2 block */
 	ld1		{v3.16b}, [x1], #16
 	eor		v3.16b, v0.16b, v3.16b
 	st1		{v3.16b}, [x0], #16
-	beq		.Lctrout
-.Lctrinc:
-	adds		x5, x5, #1		/* increment BE ctr */
-	rev		x7, x5
-	ins		v4.d[1], x7
-	bcc		.Lctrloop		/* no overflow? */
+	bne		.Lctrloop
+
+.Lctrout:
+	st1		{v4.16b}, [x5]		/* return next CTR value */
+	FRAME_POP
+	ret
+
+.Lctrhalfblock:
+	ld1		{v3.8b}, [x1]
+	eor		v3.8b, v0.8b, v3.8b
+	st1		{v3.8b}, [x0]
+	FRAME_POP
+	ret
+
+.Lctrcarry:
 	umov		x7, v4.d[0]		/* load upper word of ctr  */
 	rev		x7, x7			/* ... to handle the carry */
 	add		x7, x7, #1
 	rev		x7, x7
 	ins		v4.d[0], x7
-	b		.Lctrloop
-.Lctrhalfblock:
-	ld1		{v3.8b}, [x1]
-	eor		v3.8b, v0.8b, v3.8b
-	st1		{v3.8b}, [x0]
-.Lctrout:
-	FRAME_POP
-	ret
+	b		.Lctrcarrydone
 AES_ENDPROC(aes_ctr_encrypt)
 	.ltorg
 
@@ -386,7 +382,8 @@
 	.endm
 
 .Lxts_mul_x:
-	.word		1, 0, 0x87, 0
+CPU_LE(	.quad		1, 0x87		)
+CPU_BE(	.quad		0x87, 1		)
 
 AES_ENTRY(aes_xts_encrypt)
 	FRAME_PUSH
diff --git a/arch/arm64/crypto/aes-neon.S b/arch/arm64/crypto/aes-neon.S
index b93170e..85f07ea 100644
--- a/arch/arm64/crypto/aes-neon.S
+++ b/arch/arm64/crypto/aes-neon.S
@@ -9,6 +9,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #define AES_ENTRY(func)		ENTRY(neon_ ## func)
 #define AES_ENDPROC(func)	ENDPROC(neon_ ## func)
@@ -83,13 +84,13 @@
 	.endm
 
 	.macro		do_block, enc, in, rounds, rk, rkp, i
-	ld1		{v15.16b}, [\rk]
+	ld1		{v15.4s}, [\rk]
 	add		\rkp, \rk, #16
 	mov		\i, \rounds
 1111:	eor		\in\().16b, \in\().16b, v15.16b		/* ^round key */
 	tbl		\in\().16b, {\in\().16b}, v13.16b	/* ShiftRows */
 	sub_bytes	\in
-	ld1		{v15.16b}, [\rkp], #16
+	ld1		{v15.4s}, [\rkp], #16
 	subs		\i, \i, #1
 	beq		2222f
 	.if		\enc == 1
@@ -229,7 +230,7 @@
 	.endm
 
 	.macro		do_block_2x, enc, in0, in1 rounds, rk, rkp, i
-	ld1		{v15.16b}, [\rk]
+	ld1		{v15.4s}, [\rk]
 	add		\rkp, \rk, #16
 	mov		\i, \rounds
 1111:	eor		\in0\().16b, \in0\().16b, v15.16b	/* ^round key */
@@ -237,7 +238,7 @@
 	sub_bytes_2x	\in0, \in1
 	tbl		\in0\().16b, {\in0\().16b}, v13.16b	/* ShiftRows */
 	tbl		\in1\().16b, {\in1\().16b}, v13.16b	/* ShiftRows */
-	ld1		{v15.16b}, [\rkp], #16
+	ld1		{v15.4s}, [\rkp], #16
 	subs		\i, \i, #1
 	beq		2222f
 	.if		\enc == 1
@@ -254,7 +255,7 @@
 	.endm
 
 	.macro		do_block_4x, enc, in0, in1, in2, in3, rounds, rk, rkp, i
-	ld1		{v15.16b}, [\rk]
+	ld1		{v15.4s}, [\rk]
 	add		\rkp, \rk, #16
 	mov		\i, \rounds
 1111:	eor		\in0\().16b, \in0\().16b, v15.16b	/* ^round key */
@@ -266,7 +267,7 @@
 	tbl		\in1\().16b, {\in1\().16b}, v13.16b	/* ShiftRows */
 	tbl		\in2\().16b, {\in2\().16b}, v13.16b	/* ShiftRows */
 	tbl		\in3\().16b, {\in3\().16b}, v13.16b	/* ShiftRows */
-	ld1		{v15.16b}, [\rkp], #16
+	ld1		{v15.4s}, [\rkp], #16
 	subs		\i, \i, #1
 	beq		2222f
 	.if		\enc == 1
@@ -306,12 +307,16 @@
 	.text
 	.align		4
 .LForward_ShiftRows:
-	.byte		0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3
-	.byte		0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb
+CPU_LE(	.byte		0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3	)
+CPU_LE(	.byte		0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb	)
+CPU_BE(	.byte		0xb, 0x6, 0x1, 0xc, 0x7, 0x2, 0xd, 0x8	)
+CPU_BE(	.byte		0x3, 0xe, 0x9, 0x4, 0xf, 0xa, 0x5, 0x0	)
 
 .LReverse_ShiftRows:
-	.byte		0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb
-	.byte		0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3
+CPU_LE(	.byte		0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb	)
+CPU_LE(	.byte		0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3	)
+CPU_BE(	.byte		0x3, 0x6, 0x9, 0xc, 0xf, 0x2, 0x5, 0x8	)
+CPU_BE(	.byte		0xb, 0xe, 0x1, 0x4, 0x7, 0xa, 0xd, 0x0	)
 
 .LForward_Sbox:
 	.byte		0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5
diff --git a/arch/arm64/crypto/ghash-ce-core.S b/arch/arm64/crypto/ghash-ce-core.S
index dc45701..f0bb9f0b 100644
--- a/arch/arm64/crypto/ghash-ce-core.S
+++ b/arch/arm64/crypto/ghash-ce-core.S
@@ -29,8 +29,8 @@
 	 *			   struct ghash_key const *k, const char *head)
 	 */
 ENTRY(pmull_ghash_update)
-	ld1		{SHASH.16b}, [x3]
-	ld1		{XL.16b}, [x1]
+	ld1		{SHASH.2d}, [x3]
+	ld1		{XL.2d}, [x1]
 	movi		MASK.16b, #0xe1
 	ext		SHASH2.16b, SHASH.16b, SHASH.16b, #8
 	shl		MASK.2d, MASK.2d, #57
@@ -74,6 +74,6 @@
 
 	cbnz		w0, 0b
 
-	st1		{XL.16b}, [x1]
+	st1		{XL.2d}, [x1]
 	ret
 ENDPROC(pmull_ghash_update)
diff --git a/arch/arm64/crypto/poly-hash-ce-core.S b/arch/arm64/crypto/poly-hash-ce-core.S
new file mode 100644
index 0000000..8ccb544
--- /dev/null
+++ b/arch/arm64/crypto/poly-hash-ce-core.S
@@ -0,0 +1,163 @@
+/*
+ * Accelerated poly_hash implementation with ARMv8 PMULL instructions.
+ *
+ * Based on ghash-ce-core.S.
+ *
+ * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2017 Google, Inc. <ebiggers@google.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+	KEY	.req	v0
+	KEY2	.req	v1
+	T1	.req	v2
+	T2	.req	v3
+	GSTAR	.req	v4
+	XL	.req	v5
+	XM	.req	v6
+	XH	.req	v7
+
+	.text
+	.arch		armv8-a+crypto
+
+	/* 16-byte aligned (2**4 = 16); not required, but might as well */
+	.align		4
+.Lgstar:
+	.quad		0x87, 0x87
+
+/*
+ * void pmull_poly_hash_update(le128 *digest, const le128 *key,
+ *			       const u8 *src, unsigned int blocks,
+ *			       unsigned int partial);
+ */
+ENTRY(pmull_poly_hash_update)
+
+	/* Load digest into XL */
+	ld1		{XL.16b}, [x0]
+
+	/* Load key into KEY */
+	ld1		{KEY.16b}, [x1]
+
+	/* Load g*(x) = g(x) + x^128 = x^7 + x^2 + x + 1 into both halves of
+	 * GSTAR */
+	adr		x1, .Lgstar
+	ld1		{GSTAR.2d}, [x1]
+
+	/* Set KEY2 to (KEY[1]+KEY[0]):(KEY[1]+KEY[0]).  This is needed for
+	 * Karatsuba multiplication. */
+	ext		KEY2.16b, KEY.16b, KEY.16b, #8
+	eor		KEY2.16b, KEY2.16b, KEY.16b
+
+	/* If 'partial' is nonzero, then we're finishing a pending block and
+	 * should go right to the multiplication. */
+	cbnz		w4, 1f
+
+0:
+	/* Add the next block from 'src' to the digest */
+	ld1		{T1.16b}, [x2], #16
+	eor		XL.16b, XL.16b, T1.16b
+	sub		w3, w3, #1
+
+1:
+	/*
+	 * Multiply the current 128-bit digest (a1:a0, in XL) by the 128-bit key
+	 * (b1:b0, in KEY) using Karatsuba multiplication.
+	 */
+
+	/* T1 = (a1+a0):(a1+a0) */
+	ext		T1.16b, XL.16b, XL.16b, #8
+	eor		T1.16b, T1.16b, XL.16b
+
+	/* XH = a1 * b1 */
+	pmull2		XH.1q, XL.2d, KEY.2d
+
+	/* XL = a0 * b0 */
+	pmull		XL.1q, XL.1d, KEY.1d
+
+	/* XM = (a1+a0) * (b1+b0) */
+	pmull		XM.1q, T1.1d, KEY2.1d
+
+	/* XM += (XH[0]:XL[1]) + XL + XH */
+	ext		T1.16b, XL.16b, XH.16b, #8
+	eor		T2.16b, XL.16b, XH.16b
+	eor		XM.16b, XM.16b, T1.16b
+	eor		XM.16b, XM.16b, T2.16b
+
+	/*
+	 * Now the 256-bit product is in XH[1]:XM:XL[0].  It represents a
+	 * polynomial over GF(2) with degree as large as 255.  We need to
+	 * compute its remainder modulo g(x) = x^128+x^7+x^2+x+1.  For this it
+	 * is sufficient to compute the remainder of the high half 'c(x)x^128'
+	 * add it to the low half.  To reduce the high half we use the Barrett
+	 * reduction method.  The basic idea is that we can express the
+	 * remainder p(x) as g(x)q(x) mod x^128, where q(x) = (c(x)x^128)/g(x).
+	 * As detailed in [1], to avoid having to divide by g(x) at runtime the
+	 * following equivalent expression can be derived:
+	 *
+	 *	p(x) = [ g*(x)((c(x)q+(x))/x^128) ] mod x^128
+	 *
+	 * where g*(x) = x^128+g(x) = x^7+x^2+x+1, and q+(x) = x^256/g(x) = g(x)
+	 * in this case.  This is also equivalent to:
+	 *
+	 *	p(x) = [ g*(x)((c(x)(x^128 + g*(x)))/x^128) ] mod x^128
+	 *	     = [ g*(x)(c(x) + (c(x)g*(x))/x^128) ] mod x^128
+	 *
+	 * Since deg g*(x) < 64:
+	 *
+	 *	p(x) = [ g*(x)(c(x) + ((c(x)/x^64)g*(x))/x^64) ] mod x^128
+	 *	     = [ g*(x)((c(x)/x^64)x^64 + (c(x) mod x^64) +
+	 *				((c(x)/x^64)g*(x))/x^64) ] mod x^128
+	 *
+	 * Letting t(x) = g*(x)(c(x)/x^64):
+	 *
+	 *	p(x) = [ t(x)x^64 + g*(x)((c(x) mod x^64) + t(x)/x^64) ] mod x^128
+	 *
+	 * Therefore, to do the reduction we only need to issue two 64-bit =>
+	 * 128-bit carryless multiplications: g*(x) times c(x)/x^64, and g*(x)
+	 * times ((c(x) mod x^64) + t(x)/x^64).  (Multiplication by x^64 doesn't
+	 * count since it is simply a shift or move.)
+	 *
+	 * An alternate reduction method, also based on Barrett reduction and
+	 * described in [1], uses only shifts and XORs --- no multiplications.
+	 * However, the method with multiplications requires fewer instructions
+	 * and is faster on processors with fast carryless multiplication.
+	 *
+	 * [1] "Intel Carry-Less Multiplication Instruction and its Usage for
+	 * Computing the GCM Mode",
+	 * https://software.intel.com/sites/default/files/managed/72/cc/clmul-wp-rev-2.02-2014-04-20.pdf
+	 */
+
+	/* 256-bit product is XH[1]:XM:XL[0], so c(x) is XH[1]:XM[1] */
+
+	/* T1 = t(x) = g*(x)(c(x)/x^64) */
+	pmull2		T1.1q, GSTAR.2d, XH.2d
+
+	/* T2 = g*(x)((c(x) mod x^64) + t(x)/x^64) */
+	eor		T2.16b, XM.16b, T1.16b
+	pmull2		T2.1q, GSTAR.2d, T2.2d
+
+	/* Make XL[0] be the low half of the 128-bit result by adding the low 64
+	 * bits of the T2 term to what was already there.  The 't(x)x^64' term
+	 * makes no difference, so skip it. */
+	eor		XL.16b, XL.16b, T2.16b
+
+	/* Make XL[1] be the high half of the 128-bit result by adding the high
+	 * 64 bits of the 't(x)x^64' and T2 terms to what was already in XM[0],
+	 * then moving XM[0] to XL[1]. */
+	eor		XM.16b, XM.16b, T1.16b
+	ext		T2.16b, T2.16b, T2.16b, #8
+	eor		XM.16b, XM.16b, T2.16b
+	mov		XL.d[1], XM.d[0]
+
+	/* If more blocks remain, then loop back to process the next block;
+	 * else, store the digest and return. */
+	cbnz		w3, 0b
+	st1		{XL.16b}, [x0]
+	ret
+ENDPROC(pmull_poly_hash_update)
diff --git a/arch/arm64/crypto/poly-hash-ce-glue.c b/arch/arm64/crypto/poly-hash-ce-glue.c
new file mode 100644
index 0000000..e195740
--- /dev/null
+++ b/arch/arm64/crypto/poly-hash-ce-glue.c
@@ -0,0 +1,166 @@
+/*
+ * Accelerated poly_hash implementation with ARMv8 PMULL instructions.
+ *
+ * Based on ghash-ce-glue.c.
+ *
+ * poly_hash is part of the HEH (Hash-Encrypt-Hash) encryption mode, proposed in
+ * Internet Draft https://tools.ietf.org/html/draft-cope-heh-01.
+ *
+ * poly_hash is very similar to GHASH: both algorithms are keyed hashes which
+ * interpret their input data as coefficients of a polynomial over GF(2^128),
+ * then calculate a hash value by evaluating that polynomial at the point given
+ * by the key, e.g. using Horner's rule.  The difference is that poly_hash uses
+ * the more natural "ble" convention to represent GF(2^128) elements, whereas
+ * GHASH uses the less natural "lle" convention (see include/crypto/gf128mul.h).
+ * The ble convention makes it simpler to implement GF(2^128) multiplication.
+ *
+ * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2017 Google Inc. <ebiggers@google.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <asm/neon.h>
+#include <crypto/b128ops.h>
+#include <crypto/internal/hash.h>
+#include <linux/cpufeature.h>
+#include <linux/crypto.h>
+#include <linux/module.h>
+
+/*
+ * Note: in this algorithm we currently use 'le128' to represent GF(2^128)
+ * elements, even though poly_hash-generic uses 'be128'.  Both types are
+ * actually "wrong" because the elements are actually in 'ble' format, and there
+ * should be a ble type to represent this --- as well as lle, bbe, and lbe types
+ * for the other conventions for representing GF(2^128) elements.  But
+ * practically it doesn't matter which type we choose here, so we just use le128
+ * since it's arguably more accurate, while poly_hash-generic still has to use
+ * be128 because the generic GF(2^128) multiplication functions all take be128.
+ */
+
+struct poly_hash_desc_ctx {
+	le128 digest;
+	unsigned int count;
+};
+
+asmlinkage void pmull_poly_hash_update(le128 *digest, const le128 *key,
+				       const u8 *src, unsigned int blocks,
+				       unsigned int partial);
+
+static int poly_hash_setkey(struct crypto_shash *tfm,
+			    const u8 *key, unsigned int keylen)
+{
+	if (keylen != sizeof(le128)) {
+		crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	memcpy(crypto_shash_ctx(tfm), key, sizeof(le128));
+	return 0;
+}
+
+static int poly_hash_init(struct shash_desc *desc)
+{
+	struct poly_hash_desc_ctx *ctx = shash_desc_ctx(desc);
+
+	ctx->digest = (le128) { 0 };
+	ctx->count = 0;
+	return 0;
+}
+
+static int poly_hash_update(struct shash_desc *desc, const u8 *src,
+			    unsigned int len)
+{
+	struct poly_hash_desc_ctx *ctx = shash_desc_ctx(desc);
+	unsigned int partial = ctx->count % sizeof(le128);
+	u8 *dst = (u8 *)&ctx->digest + partial;
+
+	ctx->count += len;
+
+	/* Finishing at least one block? */
+	if (partial + len >= sizeof(le128)) {
+		const le128 *key = crypto_shash_ctx(desc->tfm);
+
+		if (partial) {
+			/* Finish the pending block. */
+			unsigned int n = sizeof(le128) - partial;
+
+			len -= n;
+			do {
+				*dst++ ^= *src++;
+			} while (--n);
+		}
+
+		/*
+		 * Do the real work.  If 'partial' is nonzero, this starts by
+		 * multiplying 'digest' by 'key'.  Then for each additional full
+		 * block it adds the block to 'digest' and multiplies by 'key'.
+		 */
+		kernel_neon_begin_partial(8);
+		pmull_poly_hash_update(&ctx->digest, key, src,
+				       len / sizeof(le128), partial);
+		kernel_neon_end();
+
+		src += len - (len % sizeof(le128));
+		len %= sizeof(le128);
+		dst = (u8 *)&ctx->digest;
+	}
+
+	/* Continue adding the next block to 'digest'. */
+	while (len--)
+		*dst++ ^= *src++;
+	return 0;
+}
+
+static int poly_hash_final(struct shash_desc *desc, u8 *out)
+{
+	struct poly_hash_desc_ctx *ctx = shash_desc_ctx(desc);
+	unsigned int partial = ctx->count % sizeof(le128);
+
+	/* Finish the last block if needed. */
+	if (partial) {
+		const le128 *key = crypto_shash_ctx(desc->tfm);
+
+		kernel_neon_begin_partial(8);
+		pmull_poly_hash_update(&ctx->digest, key, NULL, 0, partial);
+		kernel_neon_end();
+	}
+
+	memcpy(out, &ctx->digest, sizeof(le128));
+	return 0;
+}
+
+static struct shash_alg poly_hash_alg = {
+	.digestsize	= sizeof(le128),
+	.init		= poly_hash_init,
+	.update		= poly_hash_update,
+	.final		= poly_hash_final,
+	.setkey		= poly_hash_setkey,
+	.descsize	= sizeof(struct poly_hash_desc_ctx),
+	.base		= {
+		.cra_name		= "poly_hash",
+		.cra_driver_name	= "poly_hash-ce",
+		.cra_priority		= 300,
+		.cra_ctxsize		= sizeof(le128),
+		.cra_module		= THIS_MODULE,
+	},
+};
+
+static int __init poly_hash_ce_mod_init(void)
+{
+	return crypto_register_shash(&poly_hash_alg);
+}
+
+static void __exit poly_hash_ce_mod_exit(void)
+{
+	crypto_unregister_shash(&poly_hash_alg);
+}
+
+MODULE_DESCRIPTION("Polynomial evaluation hash using ARMv8 Crypto Extensions");
+MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>");
+MODULE_LICENSE("GPL v2");
+
+module_cpu_feature_match(PMULL, poly_hash_ce_mod_init);
+module_exit(poly_hash_ce_mod_exit);
diff --git a/arch/arm64/crypto/sha1-ce-core.S b/arch/arm64/crypto/sha1-ce-core.S
index 033aae6..c98e7e8 100644
--- a/arch/arm64/crypto/sha1-ce-core.S
+++ b/arch/arm64/crypto/sha1-ce-core.S
@@ -78,7 +78,7 @@
 	ld1r		{k3.4s}, [x6]
 
 	/* load state */
-	ldr		dga, [x0]
+	ld1		{dgav.4s}, [x0]
 	ldr		dgb, [x0, #16]
 
 	/* load sha1_ce_state::finalize */
@@ -144,7 +144,7 @@
 	b		1b
 
 	/* store new state */
-3:	str		dga, [x0]
+3:	st1		{dgav.4s}, [x0]
 	str		dgb, [x0, #16]
 	ret
 ENDPROC(sha1_ce_transform)
diff --git a/arch/arm64/crypto/sha2-ce-core.S b/arch/arm64/crypto/sha2-ce-core.S
index 5df9d9d..01cfee0 100644
--- a/arch/arm64/crypto/sha2-ce-core.S
+++ b/arch/arm64/crypto/sha2-ce-core.S
@@ -85,7 +85,7 @@
 	ld1		{v12.4s-v15.4s}, [x8]
 
 	/* load state */
-	ldp		dga, dgb, [x0]
+	ld1		{dgav.4s, dgbv.4s}, [x0]
 
 	/* load sha256_ce_state::finalize */
 	ldr		w4, [x0, #:lo12:sha256_ce_offsetof_finalize]
@@ -148,6 +148,6 @@
 	b		1b
 
 	/* store new state */
-3:	stp		dga, dgb, [x0]
+3:	st1		{dgav.4s, dgbv.4s}, [x0]
 	ret
 ENDPROC(sha2_ce_transform)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index caafd63..0a11cd5 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -22,9 +22,9 @@
 #define ACPI_MADT_GICC_LENGTH	\
 	(acpi_gbl_FADT.header.revision < 6 ? 76 : 80)
 
-#define BAD_MADT_GICC_ENTRY(entry, end)						\
-	(!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) ||	\
-	 (entry)->header.length != ACPI_MADT_GICC_LENGTH)
+#define BAD_MADT_GICC_ENTRY(entry, end)					\
+	(!(entry) || (entry)->header.length != ACPI_MADT_GICC_LENGTH ||	\
+	(unsigned long)(entry) + ACPI_MADT_GICC_LENGTH > (end))
 
 /* Basic configuration for ACPI */
 #ifdef	CONFIG_ACPI
@@ -87,9 +87,26 @@
 static inline void acpi_init_cpus(void) { }
 #endif /* CONFIG_ACPI */
 
+#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
+bool acpi_parking_protocol_valid(int cpu);
+void __init
+acpi_set_mailbox_entry(int cpu, struct acpi_madt_generic_interrupt *processor);
+#else
+static inline bool acpi_parking_protocol_valid(int cpu) { return false; }
+static inline void
+acpi_set_mailbox_entry(int cpu, struct acpi_madt_generic_interrupt *processor)
+{}
+#endif
+
 static inline const char *acpi_get_enable_method(int cpu)
 {
-	return acpi_psci_present() ? "psci" : NULL;
+	if (acpi_psci_present())
+		return "psci";
+
+	if (acpi_parking_protocol_valid(cpu))
+		return "parking-protocol";
+
+	return NULL;
 }
 
 #ifdef	CONFIG_ACPI_APEI
diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
index d56ec07..55101bd 100644
--- a/arch/arm64/include/asm/alternative.h
+++ b/arch/arm64/include/asm/alternative.h
@@ -1,6 +1,9 @@
 #ifndef __ASM_ALTERNATIVE_H
 #define __ASM_ALTERNATIVE_H
 
+#include <asm/cpufeature.h>
+#include <asm/insn.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/init.h>
@@ -19,7 +22,6 @@
 
 void __init apply_alternatives_all(void);
 void apply_alternatives(void *start, size_t length);
-void free_alternatives_memory(void);
 
 #define ALTINSTR_ENTRY(feature)						      \
 	" .word 661b - .\n"				/* label           */ \
@@ -64,6 +66,8 @@
 
 #else
 
+#include <asm/assembler.h>
+
 .macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len
 	.word \orig_offset - .
 	.word \alt_offset - .
@@ -87,26 +91,15 @@
 .endm
 
 /*
- * Begin an alternative code sequence.
+ * Alternative sequences
  *
- * The code that follows this macro will be assembled and linked as
- * normal. There are no restrictions on this code.
- */
-.macro alternative_if_not cap, enable = 1
-	.if \enable
-	.pushsection .altinstructions, "a"
-	altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
-	.popsection
-661:
-	.endif
-.endm
-
-/*
- * Provide the alternative code sequence.
+ * The code for the case where the capability is not present will be
+ * assembled and linked as normal. There are no restrictions on this
+ * code.
  *
- * The code that follows this macro is assembled into a special
- * section to be used for dynamic patching. Code that follows this
- * macro must:
+ * The code for the case where the capability is present will be
+ * assembled into a special section to be used for dynamic patching.
+ * Code for that case must:
  *
  * 1. Be exactly the same length (in bytes) as the default code
  *    sequence.
@@ -115,27 +108,130 @@
  *    alternative sequence it is defined in (branches into an
  *    alternative sequence are not fixed up).
  */
-.macro alternative_else, enable = 1
-	.if \enable
-662:	.pushsection .altinstr_replacement, "ax"
-663:
+
+/*
+ * Begin an alternative code sequence.
+ */
+.macro alternative_if_not cap
+	.set .Lasm_alt_mode, 0
+	.pushsection .altinstructions, "a"
+	altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
+	.popsection
+661:
+.endm
+
+.macro alternative_if cap
+	.set .Lasm_alt_mode, 1
+	.pushsection .altinstructions, "a"
+	altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f
+	.popsection
+	.pushsection .altinstr_replacement, "ax"
+	.align 2	/* So GAS knows label 661 is suitably aligned */
+661:
+.endm
+
+/*
+ * Provide the other half of the alternative code sequence.
+ */
+.macro alternative_else
+662:
+	.if .Lasm_alt_mode==0
+	.pushsection .altinstr_replacement, "ax"
+	.else
+	.popsection
 	.endif
+663:
 .endm
 
 /*
  * Complete an alternative code sequence.
  */
-.macro alternative_endif, enable = 1
-	.if \enable
-664:	.popsection
+.macro alternative_endif
+664:
+	.if .Lasm_alt_mode==0
+	.popsection
+	.endif
 	.org	. - (664b-663b) + (662b-661b)
 	.org	. - (662b-661b) + (664b-663b)
-	.endif
+.endm
+
+/*
+ * Provides a trivial alternative or default sequence consisting solely
+ * of NOPs. The number of NOPs is chosen automatically to match the
+ * previous case.
+ */
+.macro alternative_else_nop_endif
+alternative_else
+	nops	(662b-661b) / AARCH64_INSN_SIZE
+alternative_endif
 .endm
 
 #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...)	\
 	alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
 
+.macro user_alt, label, oldinstr, newinstr, cond
+9999:	alternative_insn "\oldinstr", "\newinstr", \cond
+	_ASM_EXTABLE 9999b, \label
+.endm
+
+/*
+ * Generate the assembly for UAO alternatives with exception table entries.
+ * This is complicated as there is no post-increment or pair versions of the
+ * unprivileged instructions, and USER() only works for single instructions.
+ */
+#ifdef CONFIG_ARM64_UAO
+	.macro uao_ldp l, reg1, reg2, addr, post_inc
+		alternative_if_not ARM64_HAS_UAO
+8888:			ldp	\reg1, \reg2, [\addr], \post_inc;
+8889:			nop;
+			nop;
+		alternative_else
+			ldtr	\reg1, [\addr];
+			ldtr	\reg2, [\addr, #8];
+			add	\addr, \addr, \post_inc;
+		alternative_endif
+
+		_asm_extable	8888b,\l;
+		_asm_extable	8889b,\l;
+	.endm
+
+	.macro uao_stp l, reg1, reg2, addr, post_inc
+		alternative_if_not ARM64_HAS_UAO
+8888:			stp	\reg1, \reg2, [\addr], \post_inc;
+8889:			nop;
+			nop;
+		alternative_else
+			sttr	\reg1, [\addr];
+			sttr	\reg2, [\addr, #8];
+			add	\addr, \addr, \post_inc;
+		alternative_endif
+
+		_asm_extable	8888b,\l;
+		_asm_extable	8889b,\l;
+	.endm
+
+	.macro uao_user_alternative l, inst, alt_inst, reg, addr, post_inc
+		alternative_if_not ARM64_HAS_UAO
+8888:			\inst	\reg, [\addr], \post_inc;
+			nop;
+		alternative_else
+			\alt_inst	\reg, [\addr];
+			add		\addr, \addr, \post_inc;
+		alternative_endif
+
+		_asm_extable	8888b,\l;
+	.endm
+#else
+	.macro uao_ldp l, reg1, reg2, addr, post_inc
+		USER(\l, ldp \reg1, \reg2, [\addr], \post_inc)
+	.endm
+	.macro uao_stp l, reg1, reg2, addr, post_inc
+		USER(\l, stp \reg1, \reg2, [\addr], \post_inc)
+	.endm
+	.macro uao_user_alternative l, inst, alt_inst, reg, addr, post_inc
+		USER(\l, \inst \reg, [\addr], \post_inc)
+	.endm
+#endif
 
 #endif  /*  __ASSEMBLY__  */
 
diff --git a/arch/arm64/include/asm/arch_gicv3.h b/arch/arm64/include/asm/arch_gicv3.h
index 2731d3b..8ec88e5 100644
--- a/arch/arm64/include/asm/arch_gicv3.h
+++ b/arch/arm64/include/asm/arch_gicv3.h
@@ -103,6 +103,7 @@
 	u64 irqstat;
 
 	asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
+	dsb(sy);
 	return irqstat;
 }
 
diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h
new file mode 100644
index 0000000..be2d234
--- /dev/null
+++ b/arch/arm64/include/asm/asm-uaccess.h
@@ -0,0 +1,13 @@
+#ifndef __ASM_ASM_UACCESS_H
+#define __ASM_ASM_UACCESS_H
+
+/*
+ * Remove the address tag from a virtual address, if present.
+ */
+	.macro	clear_address_tag, dst, addr
+	tst	\addr, #(1 << 55)
+	bic	\dst, \addr, #(0xff << 56)
+	csel	\dst, \dst, \addr, eq
+	.endm
+
+#endif
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 12eff92..d8855ca 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -1,5 +1,5 @@
 /*
- * Based on arch/arm/include/asm/assembler.h
+ * Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S
  *
  * Copyright (C) 1996-2000 Russell King
  * Copyright (C) 2012 ARM Ltd.
@@ -23,6 +23,10 @@
 #ifndef __ASM_ASSEMBLER_H
 #define __ASM_ASSEMBLER_H
 
+#include <asm/asm-offsets.h>
+#include <asm/cpufeature.h>
+#include <asm/page.h>
+#include <asm/pgtable-hwdef.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 
@@ -49,6 +53,15 @@
 	msr	daifclr, #2
 	.endm
 
+	.macro	save_and_disable_irq, flags
+	mrs	\flags, daif
+	msr	daifset, #2
+	.endm
+
+	.macro	restore_irq, flags
+	msr	daif, \flags
+	.endm
+
 /*
  * Enable and disable debug exceptions.
  */
@@ -94,12 +107,28 @@
 	dmb	\opt
 	.endm
 
+/*
+ * NOP sequence
+ */
+	.macro	nops, num
+	.rept	\num
+	nop
+	.endr
+	.endm
+
+/*
+ * Emit an entry into the exception table
+ */
+	.macro		_asm_extable, from, to
+	.pushsection	__ex_table, "a"
+	.align		3
+	.long		(\from - .), (\to - .)
+	.popsection
+	.endm
+
 #define USER(l, x...)				\
 9999:	x;					\
-	.section __ex_table,"a";		\
-	.align	3;				\
-	.quad	9999b,l;			\
-	.previous
+	_asm_extable	9999b, l
 
 /*
  * Register aliases.
@@ -193,6 +222,122 @@
 	str	\src, [\tmp, :lo12:\sym]
 	.endm
 
+	/*
+	 * @sym: The name of the per-cpu variable
+	 * @reg: Result of per_cpu(sym, smp_processor_id())
+	 * @tmp: scratch register
+	 */
+	.macro this_cpu_ptr, sym, reg, tmp
+	adr_l	\reg, \sym
+	mrs	\tmp, tpidr_el1
+	add	\reg, \reg, \tmp
+	.endm
+
+/*
+ * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
+ */
+	.macro	vma_vm_mm, rd, rn
+	ldr	\rd, [\rn, #VMA_VM_MM]
+	.endm
+
+/*
+ * mmid - get context id from mm pointer (mm->context.id)
+ */
+	.macro	mmid, rd, rn
+	ldr	\rd, [\rn, #MM_CONTEXT_ID]
+	.endm
+
+/*
+ * dcache_line_size - get the minimum D-cache line size from the CTR register.
+ */
+	.macro	dcache_line_size, reg, tmp
+	mrs	\tmp, ctr_el0			// read CTR
+	ubfm	\tmp, \tmp, #16, #19		// cache line size encoding
+	mov	\reg, #4			// bytes per word
+	lsl	\reg, \reg, \tmp		// actual cache line size
+	.endm
+
+/*
+ * icache_line_size - get the minimum I-cache line size from the CTR register.
+ */
+	.macro	icache_line_size, reg, tmp
+	mrs	\tmp, ctr_el0			// read CTR
+	and	\tmp, \tmp, #0xf		// cache line size encoding
+	mov	\reg, #4			// bytes per word
+	lsl	\reg, \reg, \tmp		// actual cache line size
+	.endm
+
+/*
+ * tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map
+ */
+	.macro	tcr_set_idmap_t0sz, valreg, tmpreg
+#ifndef CONFIG_ARM64_VA_BITS_48
+	ldr_l	\tmpreg, idmap_t0sz
+	bfi	\valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH
+#endif
+	.endm
+
+/*
+ * Macro to perform a data cache maintenance for the interval
+ * [kaddr, kaddr + size)
+ *
+ * 	op:		operation passed to dc instruction
+ * 	domain:		domain used in dsb instruciton
+ * 	kaddr:		starting virtual address of the region
+ * 	size:		size of the region
+ * 	Corrupts:	kaddr, size, tmp1, tmp2
+ */
+	.macro dcache_by_line_op op, domain, kaddr, size, tmp1, tmp2
+	dcache_line_size \tmp1, \tmp2
+	add	\size, \kaddr, \size
+	sub	\tmp2, \tmp1, #1
+	bic	\kaddr, \kaddr, \tmp2
+9998:
+	.if	(\op == cvau || \op == cvac)
+alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
+	dc	\op, \kaddr
+alternative_else
+	dc	civac, \kaddr
+alternative_endif
+	.else
+	dc	\op, \kaddr
+	.endif
+	add	\kaddr, \kaddr, \tmp1
+	cmp	\kaddr, \size
+	b.lo	9998b
+	dsb	\domain
+	.endm
+
+/*
+ * reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present
+ */
+	.macro	reset_pmuserenr_el0, tmpreg
+	mrs	\tmpreg, id_aa64dfr0_el1	// Check ID_AA64DFR0_EL1 PMUVer
+	sbfx	\tmpreg, \tmpreg, #8, #4
+	cmp	\tmpreg, #1			// Skip if no PMU present
+	b.lt	9000f
+	msr	pmuserenr_el0, xzr		// Disable PMU access from EL0
+9000:
+	.endm
+
+/*
+ * copy_page - copy src to dest using temp registers t1-t8
+ */
+	.macro copy_page dest:req src:req t1:req t2:req t3:req t4:req t5:req t6:req t7:req t8:req
+9998:	ldp	\t1, \t2, [\src]
+	ldp	\t3, \t4, [\src, #16]
+	ldp	\t5, \t6, [\src, #32]
+	ldp	\t7, \t8, [\src, #48]
+	add	\src, \src, #64
+	stnp	\t1, \t2, [\dest]
+	stnp	\t3, \t4, [\dest, #16]
+	stnp	\t5, \t6, [\dest, #32]
+	stnp	\t7, \t8, [\dest, #48]
+	add	\dest, \dest, #64
+	tst	\src, #(PAGE_SIZE - 1)
+	b.ne	9998b
+	.endm
+
 /*
  * Annotate a function as position independent, i.e., safe to be called before
  * the kernel virtual mapping is activated.
@@ -204,4 +349,55 @@
 	.size	__pi_##x, . - x;	\
 	ENDPROC(x)
 
+	/*
+	 * Emit a 64-bit absolute little endian symbol reference in a way that
+	 * ensures that it will be resolved at build time, even when building a
+	 * PIE binary. This requires cooperation from the linker script, which
+	 * must emit the lo32/hi32 halves individually.
+	 */
+	.macro	le64sym, sym
+	.long	\sym\()_lo32
+	.long	\sym\()_hi32
+	.endm
+
+	/*
+	 * mov_q - move an immediate constant into a 64-bit register using
+	 *         between 2 and 4 movz/movk instructions (depending on the
+	 *         magnitude and sign of the operand)
+	 */
+	.macro	mov_q, reg, val
+	.if (((\val) >> 31) == 0 || ((\val) >> 31) == 0x1ffffffff)
+	movz	\reg, :abs_g1_s:\val
+	.else
+	.if (((\val) >> 47) == 0 || ((\val) >> 47) == 0x1ffff)
+	movz	\reg, :abs_g2_s:\val
+	.else
+	movz	\reg, :abs_g3:\val
+	movk	\reg, :abs_g2_nc:\val
+	.endif
+	movk	\reg, :abs_g1_nc:\val
+	.endif
+	movk	\reg, :abs_g0_nc:\val
+	.endm
+
+/*
+ * Return the current thread_info.
+ */
+	.macro	get_thread_info, rd
+	mrs	\rd, sp_el0
+	.endm
+
+/*
+ * Errata workaround post TTBR0_EL1 update.
+ */
+	.macro	post_ttbr0_update_workaround
+#ifdef CONFIG_CAVIUM_ERRATUM_27456
+alternative_if ARM64_WORKAROUND_CAVIUM_27456
+	ic	iallu
+	dsb	nsh
+	isb
+alternative_else_nop_endif
+#endif
+	.endm
+
 #endif	/* __ASM_ASSEMBLER_H */
diff --git a/arch/arm64/include/asm/atomic_lse.h b/arch/arm64/include/asm/atomic_lse.h
index 197e06a..39c1d34 100644
--- a/arch/arm64/include/asm/atomic_lse.h
+++ b/arch/arm64/include/asm/atomic_lse.h
@@ -36,7 +36,7 @@
 	"	stclr	%w[i], %[v]\n")
 	: [i] "+r" (w0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 static inline void atomic_or(int i, atomic_t *v)
@@ -48,7 +48,7 @@
 	"	stset	%w[i], %[v]\n")
 	: [i] "+r" (w0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 static inline void atomic_xor(int i, atomic_t *v)
@@ -60,7 +60,7 @@
 	"	steor	%w[i], %[v]\n")
 	: [i] "+r" (w0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 static inline void atomic_add(int i, atomic_t *v)
@@ -72,7 +72,7 @@
 	"	stadd	%w[i], %[v]\n")
 	: [i] "+r" (w0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 #define ATOMIC_OP_ADD_RETURN(name, mb, cl...)				\
@@ -90,7 +90,7 @@
 	"	add	%w[i], %w[i], w30")				\
 	: [i] "+r" (w0), [v] "+Q" (v->counter)				\
 	: "r" (x1)							\
-	: "x30" , ##cl);						\
+	: __LL_SC_CLOBBERS, ##cl);					\
 									\
 	return w0;							\
 }
@@ -116,7 +116,7 @@
 	"	stclr	%w[i], %[v]")
 	: [i] "+r" (w0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 static inline void atomic_sub(int i, atomic_t *v)
@@ -133,7 +133,7 @@
 	"	stadd	%w[i], %[v]")
 	: [i] "+r" (w0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 #define ATOMIC_OP_SUB_RETURN(name, mb, cl...)				\
@@ -153,7 +153,7 @@
 	"	add	%w[i], %w[i], w30")				\
 	: [i] "+r" (w0), [v] "+Q" (v->counter)				\
 	: "r" (x1)							\
-	: "x30" , ##cl);						\
+	: __LL_SC_CLOBBERS , ##cl);					\
 									\
 	return w0;							\
 }
@@ -177,7 +177,7 @@
 	"	stclr	%[i], %[v]\n")
 	: [i] "+r" (x0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 static inline void atomic64_or(long i, atomic64_t *v)
@@ -189,7 +189,7 @@
 	"	stset	%[i], %[v]\n")
 	: [i] "+r" (x0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 static inline void atomic64_xor(long i, atomic64_t *v)
@@ -201,7 +201,7 @@
 	"	steor	%[i], %[v]\n")
 	: [i] "+r" (x0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 static inline void atomic64_add(long i, atomic64_t *v)
@@ -213,7 +213,7 @@
 	"	stadd	%[i], %[v]\n")
 	: [i] "+r" (x0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 #define ATOMIC64_OP_ADD_RETURN(name, mb, cl...)				\
@@ -231,7 +231,7 @@
 	"	add	%[i], %[i], x30")				\
 	: [i] "+r" (x0), [v] "+Q" (v->counter)				\
 	: "r" (x1)							\
-	: "x30" , ##cl);						\
+	: __LL_SC_CLOBBERS, ##cl);					\
 									\
 	return x0;							\
 }
@@ -257,7 +257,7 @@
 	"	stclr	%[i], %[v]")
 	: [i] "+r" (x0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 static inline void atomic64_sub(long i, atomic64_t *v)
@@ -274,7 +274,7 @@
 	"	stadd	%[i], %[v]")
 	: [i] "+r" (x0), [v] "+Q" (v->counter)
 	: "r" (x1)
-	: "x30");
+	: __LL_SC_CLOBBERS);
 }
 
 #define ATOMIC64_OP_SUB_RETURN(name, mb, cl...)				\
@@ -294,7 +294,7 @@
 	"	add	%[i], %[i], x30")				\
 	: [i] "+r" (x0), [v] "+Q" (v->counter)				\
 	: "r" (x1)							\
-	: "x30" , ##cl);						\
+	: __LL_SC_CLOBBERS, ##cl);					\
 									\
 	return x0;							\
 }
@@ -330,7 +330,7 @@
 	"2:")
 	: [ret] "+&r" (x0), [v] "+Q" (v->counter)
 	:
-	: "x30", "cc", "memory");
+	: __LL_SC_CLOBBERS, "cc", "memory");
 
 	return x0;
 }
@@ -359,7 +359,7 @@
 	"	mov	%" #w "[ret], " #w "30")			\
 	: [ret] "+r" (x0), [v] "+Q" (*(unsigned long *)ptr)		\
 	: [old] "r" (x1), [new] "r" (x2)				\
-	: "x30" , ##cl);						\
+	: __LL_SC_CLOBBERS, ##cl);					\
 									\
 	return x0;							\
 }
@@ -416,7 +416,7 @@
 	  [v] "+Q" (*(unsigned long *)ptr)				\
 	: [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4),		\
 	  [oldval1] "r" (oldval1), [oldval2] "r" (oldval2)		\
-	: "x30" , ##cl);						\
+	: __LL_SC_CLOBBERS, ##cl);					\
 									\
 	return x0;							\
 }
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
index 9622eb4..0671711 100644
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -20,6 +20,9 @@
 
 #ifndef __ASSEMBLY__
 
+#define __nops(n)	".rept	" #n "\nnop\n.endr\n"
+#define nops(n)		asm volatile(__nops(n))
+
 #define sev()		asm volatile("sev" : : : "memory")
 #define wfe()		asm volatile("wfe" : : : "memory")
 #define wfi()		asm volatile("wfi" : : : "memory")
@@ -41,23 +44,33 @@
 
 #define smp_store_release(p, v)						\
 do {									\
+	union { typeof(*p) __val; char __c[1]; } __u =			\
+		{ .__val = (__force typeof(*p)) (v) }; 			\
 	compiletime_assert_atomic_type(*p);				\
 	switch (sizeof(*p)) {						\
 	case 1:								\
 		asm volatile ("stlrb %w1, %0"				\
-				: "=Q" (*p) : "r" (v) : "memory");	\
+				: "=Q" (*p)				\
+				: "r" (*(__u8 *)__u.__c)		\
+				: "memory");				\
 		break;							\
 	case 2:								\
 		asm volatile ("stlrh %w1, %0"				\
-				: "=Q" (*p) : "r" (v) : "memory");	\
+				: "=Q" (*p)				\
+				: "r" (*(__u16 *)__u.__c)		\
+				: "memory");				\
 		break;							\
 	case 4:								\
 		asm volatile ("stlr %w1, %0"				\
-				: "=Q" (*p) : "r" (v) : "memory");	\
+				: "=Q" (*p)				\
+				: "r" (*(__u32 *)__u.__c)		\
+				: "memory");				\
 		break;							\
 	case 8:								\
 		asm volatile ("stlr %1, %0"				\
-				: "=Q" (*p) : "r" (v) : "memory");	\
+				: "=Q" (*p)				\
+				: "r" (*(__u64 *)__u.__c)		\
+				: "memory");				\
 		break;							\
 	}								\
 } while (0)
diff --git a/arch/arm64/include/asm/boot.h b/arch/arm64/include/asm/boot.h
index 81151b6..ebf2481 100644
--- a/arch/arm64/include/asm/boot.h
+++ b/arch/arm64/include/asm/boot.h
@@ -11,4 +11,10 @@
 #define MIN_FDT_ALIGN		8
 #define MAX_FDT_SIZE		SZ_2M
 
+/*
+ * arm64 requires the kernel image to placed
+ * TEXT_OFFSET bytes beyond a 2 MB aligned base
+ */
+#define MIN_KIMG_ALIGN		SZ_2M
+
 #endif
diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h
new file mode 100644
index 0000000..ed693c5
--- /dev/null
+++ b/arch/arm64/include/asm/brk-imm.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_BRK_IMM_H
+#define __ASM_BRK_IMM_H
+
+/*
+ * #imm16 values used for BRK instruction generation
+ * Allowed values for kgdb are 0x400 - 0x7ff
+ * 0x100: for triggering a fault on purpose (reserved)
+ * 0x400: for dynamic BRK instruction
+ * 0x401: for compile time BRK instruction
+ * 0x800: kernel-mode BUG() and WARN() traps
+ */
+#define FAULT_BRK_IMM			0x100
+#define KGDB_DYN_DBG_BRK_IMM		0x400
+#define KGDB_COMPILED_DBG_BRK_IMM	0x401
+#define BUG_BRK_IMM			0x800
+
+#endif
diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h
index 4a748ce..561190d 100644
--- a/arch/arm64/include/asm/bug.h
+++ b/arch/arm64/include/asm/bug.h
@@ -18,7 +18,7 @@
 #ifndef _ARCH_ARM64_ASM_BUG_H
 #define _ARCH_ARM64_ASM_BUG_H
 
-#include <asm/debug-monitors.h>
+#include <asm/brk-imm.h>
 
 #ifdef CONFIG_GENERIC_BUG
 #define HAVE_ARCH_BUG
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index 54efeda..22dda61 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -68,6 +68,7 @@
 extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
 extern void flush_icache_range(unsigned long start, unsigned long end);
 extern void __flush_dcache_area(void *addr, size_t len);
+extern void __clean_dcache_area_pou(void *addr, size_t len);
 extern long __flush_cache_user_range(unsigned long start, unsigned long end);
 
 static inline void flush_cache_mm(struct mm_struct *mm)
@@ -155,8 +156,4 @@
 int set_memory_x(unsigned long addr, int numpages);
 int set_memory_nx(unsigned long addr, int numpages);
 
-#ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
-#endif
-
 #endif
diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h
index 9ea611e..270c6b7 100644
--- a/arch/arm64/include/asm/cmpxchg.h
+++ b/arch/arm64/include/asm/cmpxchg.h
@@ -19,7 +19,6 @@
 #define __ASM_CMPXCHG_H
 
 #include <linux/bug.h>
-#include <linux/mmdebug.h>
 
 #include <asm/atomic.h>
 #include <asm/barrier.h>
@@ -49,7 +48,7 @@
 	"	swp" #acq_lse #rel #sz "\t%" #w "3, %" #w "0, %2\n"	\
 	"	nop\n"							\
 	"	" #nop_lse)						\
-	: "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr)			\
+	: "=&r" (ret), "=&r" (tmp), "+Q" (*(unsigned long *)ptr)	\
 	: "r" (x)							\
 	: cl);								\
 									\
diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
index b5e9cee..13a6103 100644
--- a/arch/arm64/include/asm/cpu.h
+++ b/arch/arm64/include/asm/cpu.h
@@ -36,6 +36,7 @@
 	u64		reg_id_aa64isar1;
 	u64		reg_id_aa64mmfr0;
 	u64		reg_id_aa64mmfr1;
+	u64		reg_id_aa64mmfr2;
 	u64		reg_id_aa64pfr0;
 	u64		reg_id_aa64pfr1;
 
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 8f271b8..4c56ecd 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -30,8 +30,13 @@
 #define ARM64_HAS_LSE_ATOMICS			5
 #define ARM64_WORKAROUND_CAVIUM_23154		6
 #define ARM64_WORKAROUND_834220			7
+#define ARM64_HAS_NO_HW_PREFETCH		8
+#define ARM64_HAS_UAO				9
+#define ARM64_ALT_PAN_NOT_UAO			10
+#define ARM64_HAS_VIRT_HOST_EXTN		11
+#define ARM64_WORKAROUND_CAVIUM_27456		12
 
-#define ARM64_NCAPS				8
+#define ARM64_NCAPS				13
 
 #ifndef __ASSEMBLY__
 
@@ -76,7 +81,7 @@
 	const char *desc;
 	u16 capability;
 	bool (*matches)(const struct arm64_cpu_capabilities *);
-	void (*enable)(void *);		/* Called on all active CPUs */
+	int (*enable)(void *);		/* Called on all active CPUs */
 	union {
 		struct {	/* To be used for erratum handling only */
 			u32 midr_model;
@@ -176,7 +181,7 @@
 
 static inline bool cpu_supports_mixed_endian_el0(void)
 {
-	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
+	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(SYS_ID_AA64MMFR0_EL1));
 }
 
 static inline bool system_supports_mixed_endian_el0(void)
@@ -184,6 +189,12 @@
 	return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1));
 }
 
+static inline bool system_uses_ttbr0_pan(void)
+{
+	return IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) &&
+		!cpus_have_cap(ARM64_HAS_PAN);
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 1a59493..b3a83da 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -32,12 +32,6 @@
 #define MPIDR_AFFINITY_LEVEL(mpidr, level) \
 	((mpidr >> MPIDR_LEVEL_SHIFT(level)) & MPIDR_LEVEL_MASK)
 
-#define read_cpuid(reg) ({						\
-	u64 __val;							\
-	asm("mrs	%0, " #reg : "=r" (__val));			\
-	__val;								\
-})
-
 #define MIDR_REVISION_MASK	0xf
 #define MIDR_REVISION(midr)	((midr) & MIDR_REVISION_MASK)
 #define MIDR_PARTNUM_SHIFT	4
@@ -57,11 +51,22 @@
 #define MIDR_IMPLEMENTOR(midr)	\
 	(((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
 
-#define MIDR_CPU_PART(imp, partnum) \
+#define MIDR_CPU_MODEL(imp, partnum) \
 	(((imp)			<< MIDR_IMPLEMENTOR_SHIFT) | \
 	(0xf			<< MIDR_ARCHITECTURE_SHIFT) | \
 	((partnum)		<< MIDR_PARTNUM_SHIFT))
 
+#define MIDR_CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \
+			     MIDR_ARCHITECTURE_MASK)
+
+#define MIDR_IS_CPU_MODEL_RANGE(midr, model, rv_min, rv_max)		\
+({									\
+	u32 _model = (midr) & MIDR_CPU_MODEL_MASK;			\
+	u32 rv = (midr) & (MIDR_REVISION_MASK | MIDR_VARIANT_MASK);	\
+									\
+	_model == (model) && rv >= (rv_min) && rv <= (rv_max);		\
+ })
+
 #define ARM_CPU_IMP_ARM			0x41
 #define ARM_CPU_IMP_APM			0x50
 #define ARM_CPU_IMP_CAVIUM		0x43
@@ -75,8 +80,20 @@
 
 #define CAVIUM_CPU_PART_THUNDERX	0x0A1
 
+#define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
+#define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
+#define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
+
 #ifndef __ASSEMBLY__
 
+#include <asm/sysreg.h>
+
+#define read_cpuid(reg) ({						\
+	u64 __val;							\
+	asm("mrs_s	%0, " __stringify(reg) : "=r" (__val));		\
+	__val;								\
+})
+
 /*
  * The CPU ID never changes at run time, so we might as well tell the
  * compiler that it's constant.  Use this function to read the CPU ID
@@ -84,12 +101,12 @@
  */
 static inline u32 __attribute_const__ read_cpuid_id(void)
 {
-	return read_cpuid(MIDR_EL1);
+	return read_cpuid(SYS_MIDR_EL1);
 }
 
 static inline u64 __attribute_const__ read_cpuid_mpidr(void)
 {
-	return read_cpuid(MPIDR_EL1);
+	return read_cpuid(SYS_MPIDR_EL1);
 }
 
 static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
@@ -104,7 +121,7 @@
 
 static inline u32 __attribute_const__ read_cpuid_cachetype(void)
 {
-	return read_cpuid(CTR_EL0);
+	return read_cpuid(SYS_CTR_EL0);
 }
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
index 279c85b5..2fcb9b7 100644
--- a/arch/arm64/include/asm/debug-monitors.h
+++ b/arch/arm64/include/asm/debug-monitors.h
@@ -20,6 +20,7 @@
 
 #include <linux/errno.h>
 #include <linux/types.h>
+#include <asm/brk-imm.h>
 #include <asm/esr.h>
 #include <asm/insn.h>
 #include <asm/ptrace.h>
@@ -47,19 +48,6 @@
 #define BREAK_INSTR_SIZE		AARCH64_INSN_SIZE
 
 /*
- * #imm16 values used for BRK instruction generation
- * Allowed values for kgbd are 0x400 - 0x7ff
- * 0x100: for triggering a fault on purpose (reserved)
- * 0x400: for dynamic BRK instruction
- * 0x401: for compile time BRK instruction
- * 0x800: kernel-mode BUG() and WARN() traps
- */
-#define FAULT_BRK_IMM			0x100
-#define KGDB_DYN_DBG_BRK_IMM		0x400
-#define KGDB_COMPILED_DBG_BRK_IMM	0x401
-#define BUG_BRK_IMM			0x800
-
-/*
  * BRK instruction encoding
  * The #imm16 value should be placed at bits[20:5] within BRK ins
  */
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index ef57220..932f5a5 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -1,8 +1,11 @@
 #ifndef _ASM_EFI_H
 #define _ASM_EFI_H
 
+#include <asm/cpufeature.h>
 #include <asm/io.h>
+#include <asm/mmu_context.h>
 #include <asm/neon.h>
+#include <asm/tlbflush.h>
 
 #ifdef CONFIG_EFI
 extern void efi_init(void);
@@ -10,6 +13,8 @@
 #define efi_init()
 #endif
 
+int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
+
 #define efi_call_virt(f, ...)						\
 ({									\
 	efi_##f##_t *__f;						\
@@ -63,6 +68,34 @@
  *   Services are enabled and the EFI_RUNTIME_SERVICES bit set.
  */
 
+static inline void efi_set_pgd(struct mm_struct *mm)
+{
+	__switch_mm(mm);
+
+	if (system_uses_ttbr0_pan()) {
+		if (mm != current->active_mm) {
+			/*
+			 * Update the current thread's saved ttbr0 since it is
+			 * restored as part of a return from exception. Set
+			 * the hardware TTBR0_EL1 using cpu_switch_mm()
+			 * directly to enable potential errata workarounds.
+			 */
+			update_saved_ttbr0(current, mm);
+			cpu_switch_mm(mm->pgd, mm);
+		} else {
+			/*
+			 * Defer the switch to the current thread's TTBR0_EL1
+			 * until uaccess_enable(). Restore the current
+			 * thread's saved ttbr0 corresponding to its active_mm
+			 * (if different from init_mm).
+			 */
+			cpu_set_reserved_ttbr0();
+			if (current->active_mm != &init_mm)
+				update_saved_ttbr0(current, current->active_mm);
+		}
+	}
+}
+
 void efi_virtmap_load(void);
 void efi_virtmap_unload(void);
 
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index faad6df..7875c88 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -24,15 +24,6 @@
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
-#define ELF_CORE_COPY_REGS(dest, regs)	\
-	*(struct user_pt_regs *)&(dest) = (regs)->user_regs;
-
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-typedef struct user_fpsimd_state elf_fpregset_t;
-
 /*
  * AArch64 static relocation types.
  */
@@ -86,6 +77,8 @@
 #define R_AARCH64_MOVW_PREL_G2_NC	292
 #define R_AARCH64_MOVW_PREL_G3		293
 
+#define R_AARCH64_RELATIVE		1027
+
 /*
  * These are used to set parameters in the core dumps.
  */
@@ -127,6 +120,17 @@
  */
 #define ELF_ET_DYN_BASE	(2 * TASK_SIZE_64 / 3)
 
+#ifndef __ASSEMBLY__
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
+#define ELF_CORE_COPY_REGS(dest, regs)	\
+	*(struct user_pt_regs *)&(dest) = (regs)->user_regs;
+
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+typedef struct user_fpsimd_state elf_fpregset_t;
+
 /*
  * When the program starts, a1 contains a pointer to a function to be
  * registered with atexit, as per the SVR4 ABI.  A value of 0 means we have no
@@ -136,6 +140,7 @@
 
 #define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
 
+/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
 #define ARCH_DLINFO							\
 do {									\
 	NEW_AUX_ENT(AT_SYSINFO_EHDR,					\
@@ -156,14 +161,14 @@
 #define STACK_RND_MASK			(0x3ffff >> (PAGE_SHIFT - 12))
 #endif
 
-#ifdef CONFIG_COMPAT
-
 #ifdef __AARCH64EB__
 #define COMPAT_ELF_PLATFORM		("v8b")
 #else
 #define COMPAT_ELF_PLATFORM		("v8l")
 #endif
 
+#ifdef CONFIG_COMPAT
+
 #define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
 
 /* AArch32 registers. */
@@ -186,4 +191,6 @@
 
 #endif /* CONFIG_COMPAT */
 
+#endif /* !__ASSEMBLY__ */
+
 #endif
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index 77eeb2c..f772e15 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -74,6 +74,7 @@
 
 #define ESR_ELx_EC_SHIFT	(26)
 #define ESR_ELx_EC_MASK		(UL(0x3F) << ESR_ELx_EC_SHIFT)
+#define ESR_ELx_EC(esr)		(((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT)
 
 #define ESR_ELx_IL		(UL(1) << 25)
 #define ESR_ELx_ISS_MASK	(ESR_ELx_IL - 1)
diff --git a/arch/arm64/include/asm/exec.h b/arch/arm64/include/asm/exec.h
index db0563c..f7865dd 100644
--- a/arch/arm64/include/asm/exec.h
+++ b/arch/arm64/include/asm/exec.h
@@ -18,6 +18,9 @@
 #ifndef __ASM_EXEC_H
 #define __ASM_EXEC_H
 
+#include <linux/sched.h>
+
 extern unsigned long arch_align_stack(unsigned long sp);
+void uao_thread_switch(struct task_struct *next);
 
 #endif	/* __ASM_EXEC_H */
diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
index 3097045..1a617d4 100644
--- a/arch/arm64/include/asm/fixmap.h
+++ b/arch/arm64/include/asm/fixmap.h
@@ -62,6 +62,16 @@
 
 	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
+
+	/*
+	 * Used for kernel page table creation, so unmapped memory may be used
+	 * for tables.
+	 */
+	FIX_PTE,
+	FIX_PMD,
+	FIX_PUD,
+	FIX_PGD,
+
 	__end_of_fixed_addresses
 };
 
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index c5534fa..3c60f37 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -28,6 +28,8 @@
 
 extern unsigned long ftrace_graph_call;
 
+extern void return_to_handler(void);
+
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
 	/*
diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h
index 007a69f..85c4a89 100644
--- a/arch/arm64/include/asm/futex.h
+++ b/arch/arm64/include/asm/futex.h
@@ -21,15 +21,12 @@
 #include <linux/futex.h>
 #include <linux/uaccess.h>
 
-#include <asm/alternative.h>
-#include <asm/cpufeature.h>
 #include <asm/errno.h>
-#include <asm/sysreg.h>
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg)		\
+do {									\
+	uaccess_enable();						\
 	asm volatile(							\
-	ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,		\
-		    CONFIG_ARM64_PAN)					\
 "	prfm	pstl1strm, %2\n"					\
 "1:	ldxr	%w1, %2\n"						\
 	insn "\n"							\
@@ -42,15 +39,13 @@
 "4:	mov	%w0, %w5\n"						\
 "	b	3b\n"							\
 "	.popsection\n"							\
-"	.pushsection __ex_table,\"a\"\n"				\
-"	.align	3\n"							\
-"	.quad	1b, 4b, 2b, 4b\n"					\
-"	.popsection\n"							\
-	ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,		\
-		    CONFIG_ARM64_PAN)					\
+	_ASM_EXTABLE(1b, 4b)						\
+	_ASM_EXTABLE(2b, 4b)						\
 	: "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp)	\
 	: "r" (oparg), "Ir" (-EFAULT)					\
-	: "memory")
+	: "memory");							\
+	uaccess_disable();						\
+} while (0)
 
 static inline int
 futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
@@ -120,6 +115,7 @@
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
+	uaccess_enable();
 	asm volatile("// futex_atomic_cmpxchg_inatomic\n"
 "	prfm	pstl1strm, %2\n"
 "1:	ldxr	%w1, %2\n"
@@ -133,13 +129,12 @@
 "4:	mov	%w0, %w6\n"
 "	b	3b\n"
 "	.popsection\n"
-"	.pushsection __ex_table,\"a\"\n"
-"	.align	3\n"
-"	.quad	1b, 4b, 2b, 4b\n"
-"	.popsection\n"
+	_ASM_EXTABLE(1b, 4b)
+	_ASM_EXTABLE(2b, 4b)
 	: "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)
 	: "r" (oldval), "r" (newval), "Ir" (-EFAULT)
 	: "memory");
+	uaccess_disable();
 
 	*uval = val;
 	return ret;
diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h
index a57601f..8740297 100644
--- a/arch/arm64/include/asm/hardirq.h
+++ b/arch/arm64/include/asm/hardirq.h
@@ -20,7 +20,7 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
-#define NR_IPI	5
+#define NR_IPI	6
 
 typedef struct {
 	unsigned int __softirq_pending;
diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index bb4052e..bbc1e35 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -26,36 +26,7 @@
 	return *ptep;
 }
 
-static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
-				   pte_t *ptep, pte_t pte)
-{
-	set_pte_at(mm, addr, ptep, pte);
-}
 
-static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
-					 unsigned long addr, pte_t *ptep)
-{
-	ptep_clear_flush(vma, addr, ptep);
-}
-
-static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
-					   unsigned long addr, pte_t *ptep)
-{
-	ptep_set_wrprotect(mm, addr, ptep);
-}
-
-static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
-					    unsigned long addr, pte_t *ptep)
-{
-	return ptep_get_and_clear(mm, addr, ptep);
-}
-
-static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
-					     unsigned long addr, pte_t *ptep,
-					     pte_t pte, int dirty)
-{
-	return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
-}
 
 static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
 					  unsigned long addr, unsigned long end,
@@ -97,4 +68,19 @@
 	clear_bit(PG_dcache_clean, &page->flags);
 }
 
+extern pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
+				struct page *page, int writable);
+#define arch_make_huge_pte arch_make_huge_pte
+extern void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+			    pte_t *ptep, pte_t pte);
+extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+				      unsigned long addr, pte_t *ptep,
+				      pte_t pte, int dirty);
+extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+				     unsigned long addr, pte_t *ptep);
+extern void huge_ptep_set_wrprotect(struct mm_struct *mm,
+				    unsigned long addr, pte_t *ptep);
+extern void huge_ptep_clear_flush(struct vm_area_struct *vma,
+				  unsigned long addr, pte_t *ptep);
+
 #endif /* __ASM_HUGETLB_H */
diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
index 9732908..c72b8e2 100644
--- a/arch/arm64/include/asm/hw_breakpoint.h
+++ b/arch/arm64/include/asm/hw_breakpoint.h
@@ -68,7 +68,11 @@
 /* Lengths */
 #define ARM_BREAKPOINT_LEN_1	0x1
 #define ARM_BREAKPOINT_LEN_2	0x3
+#define ARM_BREAKPOINT_LEN_3	0x7
 #define ARM_BREAKPOINT_LEN_4	0xf
+#define ARM_BREAKPOINT_LEN_5	0x1f
+#define ARM_BREAKPOINT_LEN_6	0x3f
+#define ARM_BREAKPOINT_LEN_7	0x7f
 #define ARM_BREAKPOINT_LEN_8	0xff
 
 /* Kernel stepping */
@@ -110,7 +114,7 @@
 struct pmu;
 
 extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
-				  int *gen_len, int *gen_type);
+				  int *gen_len, int *gen_type, int *offset);
 extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
 extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
 extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index 8e8d306..b77197d 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -1,10 +1,45 @@
 #ifndef __ASM_IRQ_H
 #define __ASM_IRQ_H
 
+#define IRQ_STACK_SIZE			THREAD_SIZE
+#define IRQ_STACK_START_SP		THREAD_START_SP
+
+#ifndef __ASSEMBLER__
+
+#include <linux/percpu.h>
+
 #include <asm-generic/irq.h>
+#include <asm/thread_info.h>
 
 struct pt_regs;
 
+DECLARE_PER_CPU(unsigned long [IRQ_STACK_SIZE/sizeof(long)], irq_stack);
+
+/*
+ * The highest address on the stack, and the first to be used. Used to
+ * find the dummy-stack frame put down by el?_irq() in entry.S, which
+ * is structured as follows:
+ *
+ *       ------------
+ *       |          |  <- irq_stack_ptr
+ *   top ------------
+ *       |   x19    | <- irq_stack_ptr - 0x08
+ *       ------------
+ *       |   x29    | <- irq_stack_ptr - 0x10
+ *       ------------
+ *
+ * where x19 holds a copy of the task stack pointer where the struct pt_regs
+ * from kernel_entry can be found.
+ *
+ */
+#define IRQ_STACK_PTR(cpu) ((unsigned long)per_cpu(irq_stack, cpu) + IRQ_STACK_START_SP)
+
+/*
+ * The offset from irq_stack_ptr where entry.S will store the original
+ * stack pointer. Used by unwind_frame() and dump_backtrace().
+ */
+#define IRQ_STACK_TO_TASK_STACK(ptr) (*((unsigned long *)((ptr) - 0x08)))
+
 extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 
 static inline int nr_legacy_irqs(void)
@@ -12,4 +47,14 @@
 	return 0;
 }
 
+static inline bool on_irq_stack(unsigned long sp, int cpu)
+{
+	/* variable names the same as kernel/stacktrace.c */
+	unsigned long low = (unsigned long)per_cpu(irq_stack, cpu);
+	unsigned long high = low + IRQ_STACK_START_SP;
+
+	return (low <= sp && sp <= high);
+}
+
+#endif /* !__ASSEMBLER__ */
 #endif
diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h
index 2774fa3..71ad0f9 100644
--- a/arch/arm64/include/asm/kasan.h
+++ b/arch/arm64/include/asm/kasan.h
@@ -7,13 +7,14 @@
 
 #include <linux/linkage.h>
 #include <asm/memory.h>
+#include <asm/pgtable-types.h>
 
 /*
  * KASAN_SHADOW_START: beginning of the kernel virtual addresses.
  * KASAN_SHADOW_END: KASAN_SHADOW_START + 1/8 of kernel virtual addresses.
  */
 #define KASAN_SHADOW_START      (VA_START)
-#define KASAN_SHADOW_END        (KASAN_SHADOW_START + (1UL << (VA_BITS - 3)))
+#define KASAN_SHADOW_END        (KASAN_SHADOW_START + KASAN_SHADOW_SIZE)
 
 /*
  * This value is used to map an address to the corresponding shadow
@@ -28,10 +29,12 @@
 #define KASAN_SHADOW_OFFSET     (KASAN_SHADOW_END - (1ULL << (64 - 3)))
 
 void kasan_init(void);
+void kasan_copy_shadow(pgd_t *pgdir);
 asmlinkage void kasan_early_init(void);
 
 #else
 static inline void kasan_init(void) { }
+static inline void kasan_copy_shadow(pgd_t *pgdir) { }
 #endif
 
 #endif
diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
index a459714..7803343 100644
--- a/arch/arm64/include/asm/kernel-pgtable.h
+++ b/arch/arm64/include/asm/kernel-pgtable.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_KERNEL_PGTABLE_H
 #define __ASM_KERNEL_PGTABLE_H
 
+#include <asm/pgtable.h>
+#include <asm/sparsemem.h>
 
 /*
  * The linear mapping and the start of memory are both 2M aligned (per
@@ -53,6 +55,12 @@
 #define SWAPPER_DIR_SIZE	(SWAPPER_PGTABLE_LEVELS * PAGE_SIZE)
 #define IDMAP_DIR_SIZE		(IDMAP_PGTABLE_LEVELS * PAGE_SIZE)
 
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+#define RESERVED_TTBR0_SIZE	(PAGE_SIZE)
+#else
+#define RESERVED_TTBR0_SIZE	(0)
+#endif
+
 /* Initial memory map size */
 #if ARM64_SWAPPER_USES_SECTION_MAPS
 #define SWAPPER_BLOCK_SHIFT	SECTION_SHIFT
@@ -79,5 +87,31 @@
 #define SWAPPER_MM_MMUFLAGS	(PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS)
 #endif
 
+/*
+ * To make optimal use of block mappings when laying out the linear
+ * mapping, round down the base of physical memory to a size that can
+ * be mapped efficiently, i.e., either PUD_SIZE (4k granule) or PMD_SIZE
+ * (64k granule), or a multiple that can be mapped using contiguous bits
+ * in the page tables: 32 * PMD_SIZE (16k granule)
+ */
+#if defined(CONFIG_ARM64_4K_PAGES)
+#define ARM64_MEMSTART_SHIFT		PUD_SHIFT
+#elif defined(CONFIG_ARM64_16K_PAGES)
+#define ARM64_MEMSTART_SHIFT		(PMD_SHIFT + 5)
+#else
+#define ARM64_MEMSTART_SHIFT		PMD_SHIFT
+#endif
+
+/*
+ * sparsemem vmemmap imposes an additional requirement on the alignment of
+ * memstart_addr, due to the fact that the base of the vmemmap region
+ * has a direct correspondence, and needs to appear sufficiently aligned
+ * in the virtual address space.
+ */
+#if defined(CONFIG_SPARSEMEM_VMEMMAP) && ARM64_MEMSTART_SHIFT < SECTION_SIZE_BITS
+#define ARM64_MEMSTART_ALIGN	(1UL << SECTION_SIZE_BITS)
+#else
+#define ARM64_MEMSTART_ALIGN	(1UL << ARM64_MEMSTART_SHIFT)
+#endif
 
 #endif	/* __ASM_KERNEL_PGTABLE_H */
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 5e6857b..2d960f85 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -107,8 +107,6 @@
 #define TCR_EL2_MASK	(TCR_EL2_TG0 | TCR_EL2_SH0 | \
 			 TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ)
 
-#define TCR_EL2_FLAGS	(TCR_EL2_RES1 | TCR_EL2_PS_40B)
-
 /* VTCR_EL2 Registers bits */
 #define VTCR_EL2_RES1		(1 << 31)
 #define VTCR_EL2_PS_MASK	(7 << 16)
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 5e37710..419bc66 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -102,6 +102,8 @@
 #define KVM_ARM64_DEBUG_DIRTY_SHIFT	0
 #define KVM_ARM64_DEBUG_DIRTY		(1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
 
+#define kvm_ksym_ref(sym)		phys_to_virt((u64)&sym - kimage_voffset)
+
 #ifndef __ASSEMBLY__
 struct kvm;
 struct kvm_vcpu;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index a35ce72..90c6368 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -222,7 +222,7 @@
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
 
-u64 kvm_call_hyp(void *hypfn, ...);
+u64 __kvm_call_hyp(void *hypfn, ...);
 void force_vm_exit(const cpumask_t *mask);
 void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
 
@@ -243,8 +243,8 @@
 	 * Call initialization code, and switch to the full blown
 	 * HYP code.
 	 */
-	kvm_call_hyp((void *)boot_pgd_ptr, pgd_ptr,
-		     hyp_stack_ptr, vector_ptr);
+	__kvm_call_hyp((void *)boot_pgd_ptr, pgd_ptr,
+		       hyp_stack_ptr, vector_ptr);
 }
 
 static inline void kvm_arch_hardware_disable(void) {}
@@ -258,4 +258,6 @@
 void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
 void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu);
 
+#define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
+
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6150567..819b21a 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -236,8 +236,7 @@
 {
 	void *va = page_address(pfn_to_page(pfn));
 
-	if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached)
-		kvm_flush_dcache_to_poc(va, size);
+	kvm_flush_dcache_to_poc(va, size);
 
 	if (!icache_is_aliasing()) {		/* PIPT */
 		flush_icache_range((unsigned long)va,
diff --git a/arch/arm64/include/asm/lse.h b/arch/arm64/include/asm/lse.h
index 3de42d6..23acc00 100644
--- a/arch/arm64/include/asm/lse.h
+++ b/arch/arm64/include/asm/lse.h
@@ -26,6 +26,7 @@
 
 /* Macro for constructing calls to out-of-line ll/sc atomics */
 #define __LL_SC_CALL(op)	"bl\t" __stringify(__LL_SC_PREFIX(op)) "\n"
+#define __LL_SC_CLOBBERS	"x16", "x17", "x30"
 
 /* In-line patching at runtime */
 #define ARM64_LSE_ATOMIC_INSN(llsc, lse)				\
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 853953c..ba1b340 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -24,6 +24,7 @@
 #include <linux/compiler.h>
 #include <linux/const.h>
 #include <linux/types.h>
+#include <asm/bug.h>
 #include <asm/sizes.h>
 
 /*
@@ -45,15 +46,15 @@
  * VA_START - the first kernel virtual address.
  * TASK_SIZE - the maximum size of a user space task.
  * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area.
- * The module space lives between the addresses given by TASK_SIZE
- * and PAGE_OFFSET - it must be within 128MB of the kernel text.
  */
 #define VA_BITS			(CONFIG_ARM64_VA_BITS)
 #define VA_START		(UL(0xffffffffffffffff) << VA_BITS)
 #define PAGE_OFFSET		(UL(0xffffffffffffffff) << (VA_BITS - 1))
-#define MODULES_END		(PAGE_OFFSET)
-#define MODULES_VADDR		(MODULES_END - SZ_64M)
-#define PCI_IO_END		(MODULES_VADDR - SZ_2M)
+#define KIMAGE_VADDR		(MODULES_END)
+#define MODULES_END		(MODULES_VADDR + MODULES_VSIZE)
+#define MODULES_VADDR		(VA_START + KASAN_SHADOW_SIZE)
+#define MODULES_VSIZE		(SZ_128M)
+#define PCI_IO_END		(PAGE_OFFSET - SZ_2M)
 #define PCI_IO_START		(PCI_IO_END - PCI_IO_SIZE)
 #define FIXADDR_TOP		(PCI_IO_START - SZ_2M)
 #define TASK_SIZE_64		(UL(1) << VA_BITS)
@@ -71,12 +72,27 @@
 #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 4))
 
 /*
+ * The size of the KASAN shadow region. This should be 1/8th of the
+ * size of the entire kernel virtual address space.
+ */
+#ifdef CONFIG_KASAN
+#define KASAN_SHADOW_SIZE	(UL(1) << (VA_BITS - 3))
+#else
+#define KASAN_SHADOW_SIZE	(0)
+#endif
+
+/*
  * Physical vs virtual RAM address space conversion.  These are
  * private definitions which should NOT be used outside memory.h
  * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
  */
-#define __virt_to_phys(x)	(((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET))
-#define __phys_to_virt(x)	((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET))
+#define __virt_to_phys(x) ({						\
+	phys_addr_t __x = (phys_addr_t)(x);				\
+	__x & BIT(VA_BITS - 1) ? (__x & ~PAGE_OFFSET) + PHYS_OFFSET :	\
+				 (__x - kimage_voffset); })
+
+#define __phys_to_virt(x)	((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
+#define __phys_to_kimg(x)	((unsigned long)((x) + kimage_voffset))
 
 /*
  * Convert a page to/from a physical address
@@ -100,19 +116,40 @@
 #define MT_S2_NORMAL		0xf
 #define MT_S2_DEVICE_nGnRE	0x1
 
+#ifdef CONFIG_ARM64_4K_PAGES
+#define IOREMAP_MAX_ORDER	(PUD_SHIFT)
+#else
+#define IOREMAP_MAX_ORDER	(PMD_SHIFT)
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+#define __early_init_dt_declare_initrd(__start, __end)			\
+	do {								\
+		initrd_start = (__start);				\
+		initrd_end = (__end);					\
+	} while (0)
+#endif
+
 #ifndef __ASSEMBLY__
 
-extern phys_addr_t		memstart_addr;
+#include <linux/bitops.h>
+#include <linux/mmdebug.h>
+
+extern s64			memstart_addr;
 /* PHYS_OFFSET - the physical address of the start of memory. */
-#define PHYS_OFFSET		({ memstart_addr; })
+#define PHYS_OFFSET		({ VM_BUG_ON(memstart_addr & 1); memstart_addr; })
+
+/* the virtual base of the kernel image (minus TEXT_OFFSET) */
+extern u64			kimage_vaddr;
+
+/* the offset between the kernel virtual and physical mappings */
+extern u64			kimage_voffset;
 
 /*
- * The maximum physical address that the linear direct mapping
- * of system RAM can cover. (PAGE_OFFSET can be interpreted as
- * a 2's complement signed quantity and negated to derive the
- * maximum size of the linear mapping.)
+ * Allow all memory at the discovery stage. We will clip it later.
  */
-#define MAX_MEMBLOCK_ADDR	({ memstart_addr - PAGE_OFFSET - 1; })
+#define MIN_MEMBLOCK_ADDR	0
+#define MAX_MEMBLOCK_ADDR	U64_MAX
 
 /*
  * PFNs are used to describe any physical page; this means
@@ -156,7 +193,11 @@
 #define ARCH_PFN_OFFSET		((unsigned long)PHYS_PFN_OFFSET)
 
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define	virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define _virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+#define _virt_addr_is_linear(kaddr)	(((u64)(kaddr)) >= PAGE_OFFSET)
+#define virt_addr_valid(kaddr)		(_virt_addr_is_linear(kaddr) && \
+					 _virt_addr_valid(kaddr))
 
 #endif
 
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index 2416578..e53d30c 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -23,10 +23,12 @@
 #include <linux/sched.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
 #include <asm/proc-fns.h>
 #include <asm-generic/mm_hooks.h>
 #include <asm/cputype.h>
 #include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 
 #ifdef CONFIG_PID_IN_CONTEXTIDR
 static inline void contextidr_thread_switch(struct task_struct *next)
@@ -48,7 +50,7 @@
  */
 static inline void cpu_set_reserved_ttbr0(void)
 {
-	unsigned long ttbr = page_to_phys(empty_zero_page);
+	unsigned long ttbr = virt_to_phys(empty_zero_page);
 
 	asm(
 	"	msr	ttbr0_el1, %0			// set TTBR0\n"
@@ -73,7 +75,7 @@
 /*
  * Set TCR.T0SZ to its default value (based on VA_BITS)
  */
-static inline void cpu_set_default_tcr_t0sz(void)
+static inline void __cpu_set_tcr_t0sz(unsigned long t0sz)
 {
 	unsigned long tcr;
 
@@ -86,7 +88,62 @@
 	"	msr	tcr_el1, %0	;"
 	"	isb"
 	: "=&r" (tcr)
-	: "r"(TCR_T0SZ(VA_BITS)), "I"(TCR_T0SZ_OFFSET), "I"(TCR_TxSZ_WIDTH));
+	: "r"(t0sz), "I"(TCR_T0SZ_OFFSET), "I"(TCR_TxSZ_WIDTH));
+}
+
+#define cpu_set_default_tcr_t0sz()	__cpu_set_tcr_t0sz(TCR_T0SZ(VA_BITS))
+#define cpu_set_idmap_tcr_t0sz()	__cpu_set_tcr_t0sz(idmap_t0sz)
+
+/*
+ * Remove the idmap from TTBR0_EL1 and install the pgd of the active mm.
+ *
+ * The idmap lives in the same VA range as userspace, but uses global entries
+ * and may use a different TCR_EL1.T0SZ. To avoid issues resulting from
+ * speculative TLB fetches, we must temporarily install the reserved page
+ * tables while we invalidate the TLBs and set up the correct TCR_EL1.T0SZ.
+ *
+ * If current is a not a user task, the mm covers the TTBR1_EL1 page tables,
+ * which should not be installed in TTBR0_EL1. In this case we can leave the
+ * reserved page tables in place.
+ */
+static inline void cpu_uninstall_idmap(void)
+{
+	struct mm_struct *mm = current->active_mm;
+
+	cpu_set_reserved_ttbr0();
+	local_flush_tlb_all();
+	cpu_set_default_tcr_t0sz();
+
+	if (mm != &init_mm && !system_uses_ttbr0_pan())
+		cpu_switch_mm(mm->pgd, mm);
+}
+
+static inline void cpu_install_idmap(void)
+{
+	cpu_set_reserved_ttbr0();
+	local_flush_tlb_all();
+	cpu_set_idmap_tcr_t0sz();
+
+	cpu_switch_mm(idmap_pg_dir, &init_mm);
+}
+
+/*
+ * Atomically replaces the active TTBR1_EL1 PGD with a new VA-compatible PGD,
+ * avoiding the possibility of conflicting TLB entries being allocated.
+ */
+static inline void cpu_replace_ttbr1(pgd_t *pgd)
+{
+	typedef void (ttbr_replace_func)(phys_addr_t);
+	extern ttbr_replace_func idmap_cpu_replace_ttbr1;
+	ttbr_replace_func *replace_phys;
+
+	phys_addr_t pgd_phys = virt_to_phys(pgd);
+
+	replace_phys = (void *)virt_to_phys(idmap_cpu_replace_ttbr1);
+
+	cpu_install_idmap();
+	replace_phys(pgd_phys);
+	cpu_uninstall_idmap();
 }
 
 /*
@@ -117,21 +174,27 @@
 {
 }
 
-/*
- * This is the actual mm switch as far as the scheduler
- * is concerned.  No registers are touched.  We avoid
- * calling the CPU specific function when the mm hasn't
- * actually changed.
- */
-static inline void
-switch_mm(struct mm_struct *prev, struct mm_struct *next,
-	  struct task_struct *tsk)
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+static inline void update_saved_ttbr0(struct task_struct *tsk,
+				      struct mm_struct *mm)
+{
+	if (system_uses_ttbr0_pan()) {
+		BUG_ON(mm->pgd == swapper_pg_dir);
+		task_thread_info(tsk)->ttbr0 =
+			virt_to_phys(mm->pgd) | ASID(mm) << 48;
+	}
+}
+#else
+static inline void update_saved_ttbr0(struct task_struct *tsk,
+				      struct mm_struct *mm)
+{
+}
+#endif
+
+static inline void __switch_mm(struct mm_struct *next)
 {
 	unsigned int cpu = smp_processor_id();
 
-	if (prev == next)
-		return;
-
 	/*
 	 * init_mm.pgd does not contain any user mappings and it is always
 	 * active for kernel addresses in TTBR1. Just set the reserved TTBR0.
@@ -144,7 +207,25 @@
 	check_and_switch_context(next, cpu);
 }
 
+static inline void
+switch_mm(struct mm_struct *prev, struct mm_struct *next,
+	  struct task_struct *tsk)
+{
+	if (prev != next)
+		__switch_mm(next);
+
+	/*
+	 * Update the saved TTBR0_EL1 of the scheduled-in task as the previous
+	 * value may have not been initialised yet (activate_mm caller) or the
+	 * ASID has changed since the last run (following the context switch
+	 * of another thread of the same process). Avoid setting the reserved
+	 * TTBR0_EL1 to swapper_pg_dir (init_mm; e.g. via idle_task_exit).
+	 */
+	if (next != &init_mm)
+		update_saved_ttbr0(tsk, next);
+}
+
 #define deactivate_mm(tsk,mm)	do { } while (0)
-#define activate_mm(prev,next)	switch_mm(prev, next, NULL)
+#define activate_mm(prev,next)	switch_mm(prev, next, current)
 
 #endif
diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h
index e80e232..06ff7fd 100644
--- a/arch/arm64/include/asm/module.h
+++ b/arch/arm64/include/asm/module.h
@@ -17,7 +17,29 @@
 #define __ASM_MODULE_H
 
 #include <asm-generic/module.h>
+#include <asm/memory.h>
 
 #define MODULE_ARCH_VERMAGIC	"aarch64"
 
+#ifdef CONFIG_ARM64_MODULE_PLTS
+struct mod_arch_specific {
+	struct elf64_shdr	*plt;
+	int			plt_num_entries;
+	int			plt_max_entries;
+};
+#endif
+
+u64 module_emit_plt_entry(struct module *mod, const Elf64_Rela *rela,
+			  Elf64_Sym *sym);
+
+#ifdef CONFIG_RANDOMIZE_BASE
+#ifdef CONFIG_MODVERSIONS
+#define ARCH_RELOCATES_KCRCTAB
+#define reloc_start 		(kimage_vaddr - KIMAGE_VADDR)
+#endif
+extern u64 module_alloc_base;
+#else
+#define module_alloc_base	((u64)_etext - MODULES_VSIZE)
+#endif
+
 #endif /* __ASM_MODULE_H */
diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h
index 0a456be..8a33685 100644
--- a/arch/arm64/include/asm/percpu.h
+++ b/arch/arm64/include/asm/percpu.h
@@ -44,48 +44,44 @@
 									\
 	switch (size) {							\
 	case 1:								\
-		do {							\
-			asm ("//__per_cpu_" #op "_1\n"			\
-			"ldxrb	  %w[ret], %[ptr]\n"			\
+		asm ("//__per_cpu_" #op "_1\n"				\
+		"1:	ldxrb	  %w[ret], %[ptr]\n"			\
 			#asm_op " %w[ret], %w[ret], %w[val]\n"		\
-			"stxrb	  %w[loop], %w[ret], %[ptr]\n"		\
-			: [loop] "=&r" (loop), [ret] "=&r" (ret),	\
-			  [ptr] "+Q"(*(u8 *)ptr)			\
-			: [val] "Ir" (val));				\
-		} while (loop);						\
+		"	stxrb	  %w[loop], %w[ret], %[ptr]\n"		\
+		"	cbnz	  %w[loop], 1b"				\
+		: [loop] "=&r" (loop), [ret] "=&r" (ret),		\
+		  [ptr] "+Q"(*(u8 *)ptr)				\
+		: [val] "Ir" (val));					\
 		break;							\
 	case 2:								\
-		do {							\
-			asm ("//__per_cpu_" #op "_2\n"			\
-			"ldxrh	  %w[ret], %[ptr]\n"			\
+		asm ("//__per_cpu_" #op "_2\n"				\
+		"1:	ldxrh	  %w[ret], %[ptr]\n"			\
 			#asm_op " %w[ret], %w[ret], %w[val]\n"		\
-			"stxrh	  %w[loop], %w[ret], %[ptr]\n"		\
-			: [loop] "=&r" (loop), [ret] "=&r" (ret),	\
-			  [ptr]  "+Q"(*(u16 *)ptr)			\
-			: [val] "Ir" (val));				\
-		} while (loop);						\
+		"	stxrh	  %w[loop], %w[ret], %[ptr]\n"		\
+		"	cbnz	  %w[loop], 1b"				\
+		: [loop] "=&r" (loop), [ret] "=&r" (ret),		\
+		  [ptr]  "+Q"(*(u16 *)ptr)				\
+		: [val] "Ir" (val));					\
 		break;							\
 	case 4:								\
-		do {							\
-			asm ("//__per_cpu_" #op "_4\n"			\
-			"ldxr	  %w[ret], %[ptr]\n"			\
+		asm ("//__per_cpu_" #op "_4\n"				\
+		"1:	ldxr	  %w[ret], %[ptr]\n"			\
 			#asm_op " %w[ret], %w[ret], %w[val]\n"		\
-			"stxr	  %w[loop], %w[ret], %[ptr]\n"		\
-			: [loop] "=&r" (loop), [ret] "=&r" (ret),	\
-			  [ptr] "+Q"(*(u32 *)ptr)			\
-			: [val] "Ir" (val));				\
-		} while (loop);						\
+		"	stxr	  %w[loop], %w[ret], %[ptr]\n"		\
+		"	cbnz	  %w[loop], 1b"				\
+		: [loop] "=&r" (loop), [ret] "=&r" (ret),		\
+		  [ptr] "+Q"(*(u32 *)ptr)				\
+		: [val] "Ir" (val));					\
 		break;							\
 	case 8:								\
-		do {							\
-			asm ("//__per_cpu_" #op "_8\n"			\
-			"ldxr	  %[ret], %[ptr]\n"			\
+		asm ("//__per_cpu_" #op "_8\n"				\
+		"1:	ldxr	  %[ret], %[ptr]\n"			\
 			#asm_op " %[ret], %[ret], %[val]\n"		\
-			"stxr	  %w[loop], %[ret], %[ptr]\n"		\
-			: [loop] "=&r" (loop), [ret] "=&r" (ret),	\
-			  [ptr] "+Q"(*(u64 *)ptr)			\
-			: [val] "Ir" (val));				\
-		} while (loop);						\
+		"	stxr	  %w[loop], %[ret], %[ptr]\n"		\
+		"	cbnz	  %w[loop], 1b"				\
+		: [loop] "=&r" (loop), [ret] "=&r" (ret),		\
+		  [ptr] "+Q"(*(u64 *)ptr)				\
+		: [val] "Ir" (val));					\
 		break;							\
 	default:							\
 		BUILD_BUG();						\
@@ -150,44 +146,40 @@
 
 	switch (size) {
 	case 1:
-		do {
-			asm ("//__percpu_xchg_1\n"
-			"ldxrb %w[ret], %[ptr]\n"
-			"stxrb %w[loop], %w[val], %[ptr]\n"
-			: [loop] "=&r"(loop), [ret] "=&r"(ret),
-			  [ptr] "+Q"(*(u8 *)ptr)
-			: [val] "r" (val));
-		} while (loop);
+		asm ("//__percpu_xchg_1\n"
+		"1:	ldxrb	%w[ret], %[ptr]\n"
+		"	stxrb	%w[loop], %w[val], %[ptr]\n"
+		"	cbnz	%w[loop], 1b"
+		: [loop] "=&r"(loop), [ret] "=&r"(ret),
+		  [ptr] "+Q"(*(u8 *)ptr)
+		: [val] "r" (val));
 		break;
 	case 2:
-		do {
-			asm ("//__percpu_xchg_2\n"
-			"ldxrh %w[ret], %[ptr]\n"
-			"stxrh %w[loop], %w[val], %[ptr]\n"
-			: [loop] "=&r"(loop), [ret] "=&r"(ret),
-			  [ptr] "+Q"(*(u16 *)ptr)
-			: [val] "r" (val));
-		} while (loop);
+		asm ("//__percpu_xchg_2\n"
+		"1:	ldxrh	%w[ret], %[ptr]\n"
+		"	stxrh	%w[loop], %w[val], %[ptr]\n"
+		"	cbnz	%w[loop], 1b"
+		: [loop] "=&r"(loop), [ret] "=&r"(ret),
+		  [ptr] "+Q"(*(u16 *)ptr)
+		: [val] "r" (val));
 		break;
 	case 4:
-		do {
-			asm ("//__percpu_xchg_4\n"
-			"ldxr %w[ret], %[ptr]\n"
-			"stxr %w[loop], %w[val], %[ptr]\n"
-			: [loop] "=&r"(loop), [ret] "=&r"(ret),
-			  [ptr] "+Q"(*(u32 *)ptr)
-			: [val] "r" (val));
-		} while (loop);
+		asm ("//__percpu_xchg_4\n"
+		"1:	ldxr	%w[ret], %[ptr]\n"
+		"	stxr	%w[loop], %w[val], %[ptr]\n"
+		"	cbnz	%w[loop], 1b"
+		: [loop] "=&r"(loop), [ret] "=&r"(ret),
+		  [ptr] "+Q"(*(u32 *)ptr)
+		: [val] "r" (val));
 		break;
 	case 8:
-		do {
-			asm ("//__percpu_xchg_8\n"
-			"ldxr %[ret], %[ptr]\n"
-			"stxr %w[loop], %[val], %[ptr]\n"
-			: [loop] "=&r"(loop), [ret] "=&r"(ret),
-			  [ptr] "+Q"(*(u64 *)ptr)
-			: [val] "r" (val));
-		} while (loop);
+		asm ("//__percpu_xchg_8\n"
+		"1:	ldxr	%[ret], %[ptr]\n"
+		"	stxr	%w[loop], %[val], %[ptr]\n"
+		"	cbnz	%w[loop], 1b"
+		: [loop] "=&r"(loop), [ret] "=&r"(ret),
+		  [ptr] "+Q"(*(u64 *)ptr)
+		: [val] "r" (val));
 		break;
 	default:
 		BUILD_BUG();
diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h
index c150539..ff98585 100644
--- a/arch/arm64/include/asm/pgalloc.h
+++ b/arch/arm64/include/asm/pgalloc.h
@@ -42,11 +42,20 @@
 	free_page((unsigned long)pmd);
 }
 
-static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+static inline void __pud_populate(pud_t *pud, phys_addr_t pmd, pudval_t prot)
 {
-	set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE));
+	set_pud(pud, __pud(pmd | prot));
 }
 
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+	__pud_populate(pud, __pa(pmd), PMD_TYPE_TABLE);
+}
+#else
+static inline void __pud_populate(pud_t *pud, phys_addr_t pmd, pudval_t prot)
+{
+	BUILD_BUG();
+}
 #endif	/* CONFIG_PGTABLE_LEVELS > 2 */
 
 #if CONFIG_PGTABLE_LEVELS > 3
@@ -62,11 +71,20 @@
 	free_page((unsigned long)pud);
 }
 
-static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t pud, pgdval_t prot)
 {
-	set_pgd(pgd, __pgd(__pa(pud) | PUD_TYPE_TABLE));
+	set_pgd(pgdp, __pgd(pud | prot));
 }
 
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+	__pgd_populate(pgd, __pa(pud), PUD_TYPE_TABLE);
+}
+#else
+static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t pud, pgdval_t prot)
+{
+	BUILD_BUG();
+}
 #endif	/* CONFIG_PGTABLE_LEVELS > 3 */
 
 extern pgd_t *pgd_alloc(struct mm_struct *mm);
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index d6739e8..9786f77 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -90,7 +90,23 @@
 /*
  * Contiguous page definitions.
  */
-#define CONT_PTES		(_AC(1, UL) << CONT_SHIFT)
+#ifdef CONFIG_ARM64_64K_PAGES
+#define CONT_PTE_SHIFT		5
+#define CONT_PMD_SHIFT		5
+#elif defined(CONFIG_ARM64_16K_PAGES)
+#define CONT_PTE_SHIFT		7
+#define CONT_PMD_SHIFT		5
+#else
+#define CONT_PTE_SHIFT		4
+#define CONT_PMD_SHIFT		4
+#endif
+
+#define CONT_PTES		(1 << CONT_PTE_SHIFT)
+#define CONT_PTE_SIZE		(CONT_PTES * PAGE_SIZE)
+#define CONT_PTE_MASK		(~(CONT_PTE_SIZE - 1))
+#define CONT_PMDS		(1 << CONT_PMD_SHIFT)
+#define CONT_PMD_SIZE		(CONT_PMDS * PMD_SIZE)
+#define CONT_PMD_MASK		(~(CONT_PMD_SIZE - 1))
 /* the the numerical offset of the PTE within a range of CONT_PTES */
 #define CONT_RANGE_OFFSET(addr) (((addr)>>PAGE_SHIFT)&(CONT_PTES-1))
 
@@ -117,7 +133,6 @@
  * Section
  */
 #define PMD_SECT_VALID		(_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_PROT_NONE	(_AT(pmdval_t, 1) << 58)
 #define PMD_SECT_USER		(_AT(pmdval_t, 1) << 6)		/* AP[1] */
 #define PMD_SECT_RDONLY		(_AT(pmdval_t, 1) << 7)		/* AP[2] */
 #define PMD_SECT_S		(_AT(pmdval_t, 3) << 8)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index c63868a..0e7e800 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -36,19 +36,13 @@
  *
  * VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array
  *	(rounded up to PUD_SIZE).
- * VMALLOC_START: beginning of the kernel VA space
+ * VMALLOC_START: beginning of the kernel vmalloc space
  * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
  *	fixed mappings and modules
  */
 #define VMEMMAP_SIZE		ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
 
-#ifndef CONFIG_KASAN
-#define VMALLOC_START		(VA_START)
-#else
-#include <asm/kasan.h>
-#define VMALLOC_START		(KASAN_SHADOW_END + SZ_64K)
-#endif
-
+#define VMALLOC_START		(MODULES_END)
 #define VMALLOC_END		(PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
 
 #define VMEMMAP_START		(VMALLOC_END + SZ_64K)
@@ -59,6 +53,7 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/fixmap.h>
 #include <linux/mmdebug.h>
 
 extern void __pte_error(const char *file, int line, unsigned long val);
@@ -123,8 +118,8 @@
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-extern struct page *empty_zero_page;
-#define ZERO_PAGE(vaddr)	(empty_zero_page)
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+#define ZERO_PAGE(vaddr)	virt_to_page(empty_zero_page)
 
 #define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
 
@@ -136,16 +131,6 @@
 #define pte_clear(mm,addr,ptep)	set_pte(ptep, __pte(0))
 #define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
 
-/* Find an entry in the third-level page table. */
-#define pte_index(addr)		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-
-#define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + pte_index(addr))
-
-#define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
-#define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr))
-#define pte_unmap(pte)			do { } while (0)
-#define pte_unmap_nested(pte)		do { } while (0)
-
 /*
  * The following only work if pte_present(). Undefined behaviour otherwise.
  */
@@ -168,6 +153,16 @@
 #define pte_valid(pte)		(!!(pte_val(pte) & PTE_VALID))
 #define pte_valid_not_user(pte) \
 	((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
+#define pte_valid_young(pte) \
+	((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF))
+
+/*
+ * Could the pte be present in the TLB? We must check mm_tlb_flush_pending
+ * so that we don't erroneously return false for pages that have been
+ * remapped as PROT_NONE but are yet to be flushed from the TLB.
+ */
+#define pte_accessible(mm, pte)	\
+	(mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid_young(pte))
 
 static inline pte_t clear_pte_bit(pte_t pte, pgprot_t prot)
 {
@@ -218,7 +213,8 @@
 
 static inline pte_t pte_mkcont(pte_t pte)
 {
-	return set_pte_bit(pte, __pgprot(PTE_CONT));
+	pte = set_pte_bit(pte, __pgprot(PTE_CONT));
+	return set_pte_bit(pte, __pgprot(PTE_TYPE_PAGE));
 }
 
 static inline pte_t pte_mknoncont(pte_t pte)
@@ -226,6 +222,11 @@
 	return clear_pte_bit(pte, __pgprot(PTE_CONT));
 }
 
+static inline pmd_t pmd_mkcont(pmd_t pmd)
+{
+	return __pmd(pmd_val(pmd) | PMD_SECT_CONT);
+}
+
 static inline void set_pte(pte_t *ptep, pte_t pte)
 {
 	*ptep = pte;
@@ -299,7 +300,7 @@
 /*
  * Hugetlb definitions.
  */
-#define HUGE_MAX_HSTATE		2
+#define HUGE_MAX_HSTATE		4
 #define HPAGE_SHIFT		PMD_SHIFT
 #define HPAGE_SIZE		(_AC(1, UL) << HPAGE_SHIFT)
 #define HPAGE_MASK		(~(HPAGE_SIZE - 1))
@@ -347,6 +348,7 @@
 #endif /* CONFIG_HAVE_RCU_TABLE_FREE */
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
+#define pmd_present(pmd)	pte_present(pmd_pte(pmd))
 #define pmd_dirty(pmd)		pte_dirty(pmd_pte(pmd))
 #define pmd_young(pmd)		pte_young(pmd_pte(pmd))
 #define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
@@ -355,7 +357,7 @@
 #define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
 #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
 #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
-#define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
+#define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_SECT_VALID))
 
 #define __HAVE_ARCH_PMD_WRITE
 #define pmd_write(pmd)		pte_write(pmd_pte(pmd))
@@ -394,7 +396,6 @@
 				     unsigned long size, pgprot_t vma_prot);
 
 #define pmd_none(pmd)		(!pmd_val(pmd))
-#define pmd_present(pmd)	(pmd_val(pmd))
 
 #define pmd_bad(pmd)		(!(pmd_val(pmd) & 2))
 
@@ -425,13 +426,31 @@
 	set_pmd(pmdp, __pmd(0));
 }
 
-static inline pte_t *pmd_page_vaddr(pmd_t pmd)
+static inline phys_addr_t pmd_page_paddr(pmd_t pmd)
 {
-	return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
+	return pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK;
 }
 
+/* Find an entry in the third-level page table. */
+#define pte_index(addr)		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+#define pte_offset_phys(dir,addr)	(pmd_page_paddr(*(dir)) + pte_index(addr) * sizeof(pte_t))
+#define pte_offset_kernel(dir,addr)	((pte_t *)__va(pte_offset_phys((dir), (addr))))
+
+#define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
+#define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr))
+#define pte_unmap(pte)			do { } while (0)
+#define pte_unmap_nested(pte)		do { } while (0)
+
+#define pte_set_fixmap(addr)		((pte_t *)set_fixmap_offset(FIX_PTE, addr))
+#define pte_set_fixmap_offset(pmd, addr)	pte_set_fixmap(pte_offset_phys(pmd, addr))
+#define pte_clear_fixmap()		clear_fixmap(FIX_PTE)
+
 #define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
 
+/* use ONLY for statically allocated translation tables */
+#define pte_offset_kimg(dir,addr)	((pte_t *)__phys_to_kimg(pte_offset_phys((dir), (addr))))
+
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
@@ -458,21 +477,37 @@
 	set_pud(pudp, __pud(0));
 }
 
-static inline pmd_t *pud_page_vaddr(pud_t pud)
+static inline phys_addr_t pud_page_paddr(pud_t pud)
 {
-	return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
+	return pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK;
 }
 
 /* Find an entry in the second-level page table. */
 #define pmd_index(addr)		(((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
 
-static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
-{
-	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
-}
+#define pmd_offset_phys(dir, addr)	(pud_page_paddr(*(dir)) + pmd_index(addr) * sizeof(pmd_t))
+#define pmd_offset(dir, addr)		((pmd_t *)__va(pmd_offset_phys((dir), (addr))))
+
+#define pmd_set_fixmap(addr)		((pmd_t *)set_fixmap_offset(FIX_PMD, addr))
+#define pmd_set_fixmap_offset(pud, addr)	pmd_set_fixmap(pmd_offset_phys(pud, addr))
+#define pmd_clear_fixmap()		clear_fixmap(FIX_PMD)
 
 #define pud_page(pud)		pfn_to_page(__phys_to_pfn(pud_val(pud) & PHYS_MASK))
 
+/* use ONLY for statically allocated translation tables */
+#define pmd_offset_kimg(dir,addr)	((pmd_t *)__phys_to_kimg(pmd_offset_phys((dir), (addr))))
+
+#else
+
+#define pud_page_paddr(pud)	({ BUILD_BUG(); 0; })
+
+/* Match pmd_offset folding in <asm/generic/pgtable-nopmd.h> */
+#define pmd_set_fixmap(addr)		NULL
+#define pmd_set_fixmap_offset(pudp, addr)	((pmd_t *)pudp)
+#define pmd_clear_fixmap()
+
+#define pmd_offset_kimg(dir,addr)	((pmd_t *)dir)
+
 #endif	/* CONFIG_PGTABLE_LEVELS > 2 */
 
 #if CONFIG_PGTABLE_LEVELS > 3
@@ -494,21 +529,37 @@
 	set_pgd(pgdp, __pgd(0));
 }
 
-static inline pud_t *pgd_page_vaddr(pgd_t pgd)
+static inline phys_addr_t pgd_page_paddr(pgd_t pgd)
 {
-	return __va(pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK);
+	return pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK;
 }
 
 /* Find an entry in the frst-level page table. */
 #define pud_index(addr)		(((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
 
-static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr)
-{
-	return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr);
-}
+#define pud_offset_phys(dir, addr)	(pgd_page_paddr(*(dir)) + pud_index(addr) * sizeof(pud_t))
+#define pud_offset(dir, addr)		((pud_t *)__va(pud_offset_phys((dir), (addr))))
+
+#define pud_set_fixmap(addr)		((pud_t *)set_fixmap_offset(FIX_PUD, addr))
+#define pud_set_fixmap_offset(pgd, addr)	pud_set_fixmap(pud_offset_phys(pgd, addr))
+#define pud_clear_fixmap()		clear_fixmap(FIX_PUD)
 
 #define pgd_page(pgd)		pfn_to_page(__phys_to_pfn(pgd_val(pgd) & PHYS_MASK))
 
+/* use ONLY for statically allocated translation tables */
+#define pud_offset_kimg(dir,addr)	((pud_t *)__phys_to_kimg(pud_offset_phys((dir), (addr))))
+
+#else
+
+#define pgd_page_paddr(pgd)	({ BUILD_BUG(); 0;})
+
+/* Match pud_offset folding in <asm/generic/pgtable-nopud.h> */
+#define pud_set_fixmap(addr)		NULL
+#define pud_set_fixmap_offset(pgdp, addr)	((pud_t *)pgdp)
+#define pud_clear_fixmap()
+
+#define pud_offset_kimg(dir,addr)	((pud_t *)dir)
+
 #endif  /* CONFIG_PGTABLE_LEVELS > 3 */
 
 #define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
@@ -516,11 +567,16 @@
 /* to find an entry in a page-table-directory */
 #define pgd_index(addr)		(((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
 
-#define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
+#define pgd_offset_raw(pgd, addr)	((pgd) + pgd_index(addr))
+
+#define pgd_offset(mm, addr)	(pgd_offset_raw((mm)->pgd, (addr)))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
 
+#define pgd_set_fixmap(addr)	((pgd_t *)set_fixmap_offset(FIX_PGD, addr))
+#define pgd_clear_fixmap()	clear_fixmap(FIX_PGD)
+
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
 	const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
@@ -538,6 +594,21 @@
 }
 
 #ifdef CONFIG_ARM64_HW_AFDBM
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+extern int ptep_set_access_flags(struct vm_area_struct *vma,
+				 unsigned long address, pte_t *ptep,
+				 pte_t entry, int dirty);
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
+static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
+					unsigned long address, pmd_t *pmdp,
+					pmd_t entry, int dirty)
+{
+	return ptep_set_access_flags(vma, address, (pte_t *)pmdp, pmd_pte(entry), dirty);
+}
+#endif
+
 /*
  * Atomic pte/pmd modifications.
  */
@@ -590,9 +661,9 @@
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
-static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
-				       unsigned long address, pmd_t *pmdp)
+#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
+static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
+					    unsigned long address, pmd_t *pmdp)
 {
 	return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
 }
@@ -666,7 +737,8 @@
 
 #include <asm-generic/pgtable.h>
 
-#define pgtable_cache_init() do { } while (0)
+void pgd_cache_init(void);
+#define pgtable_cache_init	pgd_cache_init
 
 /*
  * On AArch64, the cache coherency is handled via the set_pte_at() function.
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 4acb7ca..4be934f 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -29,8 +29,10 @@
 
 #include <linux/string.h>
 
+#include <asm/alternative.h>
 #include <asm/fpsimd.h>
 #include <asm/hw_breakpoint.h>
+#include <asm/lse.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
@@ -177,15 +179,18 @@
 }
 
 #define ARCH_HAS_SPINLOCK_PREFETCH
-static inline void spin_lock_prefetch(const void *x)
+static inline void spin_lock_prefetch(const void *ptr)
 {
-	prefetchw(x);
+	asm volatile(ARM64_LSE_ATOMIC_INSN(
+		     "prfm pstl1strm, %a0",
+		     "nop") : : "p" (ptr));
 }
 
 #define HAVE_ARCH_PICK_MMAP_LAYOUT
 
 #endif
 
-void cpu_enable_pan(void *__unused);
+int cpu_enable_pan(void *__unused);
+int cpu_enable_uao(void *__unused);
 
 #endif /* __ASM_PROCESSOR_H */
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index e9e5467..7f94755 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -58,6 +58,7 @@
 #define COMPAT_PSR_Z_BIT	0x40000000
 #define COMPAT_PSR_N_BIT	0x80000000
 #define COMPAT_PSR_IT_MASK	0x0600fc00	/* If-Then execution state mask */
+#define COMPAT_PSR_GE_MASK	0x000f0000
 
 #ifdef CONFIG_CPU_BIG_ENDIAN
 #define COMPAT_PSR_ENDSTATE	COMPAT_PSR_E_BIT
@@ -116,6 +117,8 @@
 	};
 	u64 orig_x0;
 	u64 syscallno;
+	u64 orig_addr_limit;
+	u64 unused;	// maintain 16 byte alignment
 };
 
 #define arch_has_single_step()	(1)
@@ -151,35 +154,9 @@
 	return regs->regs[0];
 }
 
-/*
- * Are the current registers suitable for user mode? (used to maintain
- * security in signal handlers)
- */
-static inline int valid_user_regs(struct user_pt_regs *regs)
-{
-	if (user_mode(regs) && (regs->pstate & PSR_I_BIT) == 0) {
-		regs->pstate &= ~(PSR_F_BIT | PSR_A_BIT);
-
-		/* The T bit is reserved for AArch64 */
-		if (!(regs->pstate & PSR_MODE32_BIT))
-			regs->pstate &= ~COMPAT_PSR_T_BIT;
-
-		return 1;
-	}
-
-	/*
-	 * Force PSR to something logical...
-	 */
-	regs->pstate &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | \
-			COMPAT_PSR_T_BIT | PSR_MODE32_BIT;
-
-	if (!(regs->pstate & PSR_MODE32_BIT)) {
-		regs->pstate &= ~COMPAT_PSR_T_BIT;
-		regs->pstate |= PSR_MODE_EL0t;
-	}
-
-	return 0;
-}
+/* We must avoid circular header include via sched.h */
+struct task_struct;
+int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task);
 
 #define instruction_pointer(regs)	((unsigned long)(regs)->pc)
 
diff --git a/arch/arm64/include/asm/shmparam.h b/arch/arm64/include/asm/shmparam.h
index 4df608a..e368a55 100644
--- a/arch/arm64/include/asm/shmparam.h
+++ b/arch/arm64/include/asm/shmparam.h
@@ -21,7 +21,7 @@
  * alignment value. Since we don't have aliasing D-caches, the rest of
  * the time we can safely use PAGE_SIZE.
  */
-#define COMPAT_SHMLBA	0x4000
+#define COMPAT_SHMLBA	(4 * PAGE_SIZE)
 
 #include <asm-generic/shmparam.h>
 
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index d9c3d6a..2013a4d 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -64,6 +64,15 @@
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 
+#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
+extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask);
+#else
+static inline void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
+{
+	BUILD_BUG();
+}
+#endif
+
 extern int __cpu_disable(void);
 
 extern void __cpu_die(unsigned int cpu);
diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h
index c85e96d..43a6688 100644
--- a/arch/arm64/include/asm/spinlock.h
+++ b/arch/arm64/include/asm/spinlock.h
@@ -26,9 +26,32 @@
  * The memory barriers are implicit with the load-acquire and store-release
  * instructions.
  */
+static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
+{
+	unsigned int tmp;
+	arch_spinlock_t lockval;
 
-#define arch_spin_unlock_wait(lock) \
-	do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
+	asm volatile(
+"	sevl\n"
+"1:	wfe\n"
+"2:	ldaxr	%w0, %2\n"
+"	eor	%w1, %w0, %w0, ror #16\n"
+"	cbnz	%w1, 1b\n"
+	/* Serialise against any concurrent lockers */
+	ARM64_LSE_ATOMIC_INSN(
+	/* LL/SC */
+"	stxr	%w1, %w0, %2\n"
+"	nop\n"
+"	nop\n",
+	/* LSE atomics */
+"	mov	%w1, %w0\n"
+"	cas	%w0, %w0, %2\n"
+"	eor	%w1, %w1, %w0\n")
+"	cbnz	%w1, 2b\n"
+	: "=&r" (lockval), "=&r" (tmp), "+Q" (*lock)
+	:
+	: "memory");
+}
 
 #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
 
@@ -312,4 +335,14 @@
 #define arch_read_relax(lock)	cpu_relax()
 #define arch_write_relax(lock)	cpu_relax()
 
+/*
+ * Accesses appearing in program order before a spin_lock() operation
+ * can be reordered with accesses inside the critical section, by virtue
+ * of arch_spin_lock being constructed using acquire semantics.
+ *
+ * In cases where this is problematic (e.g. try_to_wake_up), an
+ * smp_mb__before_spinlock() can restore the required ordering.
+ */
+#define smp_mb__before_spinlock()	smp_mb()
+
 #endif /* __ASM_SPINLOCK_H */
diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index 7318f6d..801a16db 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -16,14 +16,19 @@
 #ifndef __ASM_STACKTRACE_H
 #define __ASM_STACKTRACE_H
 
+struct task_struct;
+
 struct stackframe {
 	unsigned long fp;
 	unsigned long sp;
 	unsigned long pc;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	unsigned int graph;
+#endif
 };
 
-extern int unwind_frame(struct stackframe *frame);
-extern void walk_stackframe(struct stackframe *frame,
+extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame);
+extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
 			    int (*fn)(struct stackframe *, void *), void *data);
 
 #endif	/* __ASM_STACKTRACE_H */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index d48ab5b..1a78d6e 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -20,6 +20,8 @@
 #ifndef __ASM_SYSREG_H
 #define __ASM_SYSREG_H
 
+#include <linux/stringify.h>
+
 #include <asm/opcodes.h>
 
 /*
@@ -70,15 +72,19 @@
 
 #define SYS_ID_AA64MMFR0_EL1		sys_reg(3, 0, 0, 7, 0)
 #define SYS_ID_AA64MMFR1_EL1		sys_reg(3, 0, 0, 7, 1)
+#define SYS_ID_AA64MMFR2_EL1		sys_reg(3, 0, 0, 7, 2)
 
 #define SYS_CNTFRQ_EL0			sys_reg(3, 3, 14, 0, 0)
 #define SYS_CTR_EL0			sys_reg(3, 3, 0, 0, 1)
 #define SYS_DCZID_EL0			sys_reg(3, 3, 0, 0, 7)
 
 #define REG_PSTATE_PAN_IMM		sys_reg(0, 0, 4, 0, 4)
+#define REG_PSTATE_UAO_IMM		sys_reg(0, 0, 4, 0, 3)
 
 #define SET_PSTATE_PAN(x) __inst_arm(0xd5000000 | REG_PSTATE_PAN_IMM |\
 				     (!!x)<<8 | 0x1f)
+#define SET_PSTATE_UAO(x) __inst_arm(0xd5000000 | REG_PSTATE_UAO_IMM |\
+				     (!!x)<<8 | 0x1f)
 
 /* SCTLR_EL1 */
 #define SCTLR_EL1_CP15BEN	(0x1 << 5)
@@ -135,6 +141,9 @@
 #define ID_AA64MMFR1_VMIDBITS_SHIFT	4
 #define ID_AA64MMFR1_HADBS_SHIFT	0
 
+/* id_aa64mmfr2 */
+#define ID_AA64MMFR2_UAO_SHIFT		4
+
 /* id_aa64dfr0 */
 #define ID_AA64DFR0_CTX_CMPS_SHIFT	28
 #define ID_AA64DFR0_WRPS_SHIFT		20
@@ -194,32 +203,34 @@
 #ifdef __ASSEMBLY__
 
 	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
-	.equ	__reg_num_x\num, \num
+	.equ	.L__reg_num_x\num, \num
 	.endr
-	.equ	__reg_num_xzr, 31
+	.equ	.L__reg_num_xzr, 31
 
 	.macro	mrs_s, rt, sreg
-	.inst	0xd5200000|(\sreg)|(__reg_num_\rt)
+	.inst	0xd5200000|(\sreg)|(.L__reg_num_\rt)
 	.endm
 
 	.macro	msr_s, sreg, rt
-	.inst	0xd5000000|(\sreg)|(__reg_num_\rt)
+	.inst	0xd5000000|(\sreg)|(.L__reg_num_\rt)
 	.endm
 
 #else
 
+#include <linux/types.h>
+
 asm(
 "	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n"
-"	.equ	__reg_num_x\\num, \\num\n"
+"	.equ	.L__reg_num_x\\num, \\num\n"
 "	.endr\n"
-"	.equ	__reg_num_xzr, 31\n"
+"	.equ	.L__reg_num_xzr, 31\n"
 "\n"
 "	.macro	mrs_s, rt, sreg\n"
-"	.inst	0xd5200000|(\\sreg)|(__reg_num_\\rt)\n"
+"	.inst	0xd5200000|(\\sreg)|(.L__reg_num_\\rt)\n"
 "	.endm\n"
 "\n"
 "	.macro	msr_s, sreg, rt\n"
-"	.inst	0xd5000000|(\\sreg)|(__reg_num_\\rt)\n"
+"	.inst	0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n"
 "	.endm\n"
 );
 
@@ -232,6 +243,23 @@
 	val |= set;
 	asm volatile("msr sctlr_el1, %0" : : "r" (val));
 }
+
+/*
+ * Unlike read_cpuid, calls to read_sysreg are never expected to be
+ * optimized away or replaced with synthetic values.
+ */
+#define read_sysreg(r) ({					\
+	u64 __val;						\
+	asm volatile("mrs %0, " __stringify(r) : "=r" (__val));	\
+	__val;							\
+})
+
+#define write_sysreg(v, r) do {					\
+	u64 __val = (u64)v;					\
+	asm volatile("msr " __stringify(r) ", %0"		\
+		     : : "r" (__val));				\
+} while (0)
+
 #endif
 
 #endif	/* __ASM_SYSREG_H */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 90c7ff2..794d226 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -48,6 +48,9 @@
 	unsigned long		flags;		/* low level flags */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	u64			ttbr0;		/* saved TTBR0_EL1 */
+#endif
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
 	int			cpu;		/* cpu */
 };
@@ -73,10 +76,16 @@
  */
 static inline struct thread_info *current_thread_info(void) __attribute_const__;
 
+/*
+ * struct thread_info can be accessed directly via sp_el0.
+ */
 static inline struct thread_info *current_thread_info(void)
 {
-	return (struct thread_info *)
-		(current_stack_pointer & ~(THREAD_SIZE - 1));
+	unsigned long sp_el0;
+
+	asm ("mrs %0, sp_el0" : "=r" (sp_el0));
+
+	return (struct thread_info *)sp_el0;
 }
 
 #define thread_saved_pc(tsk)	\
diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h
index a3e9d6f..bbd362c 100644
--- a/arch/arm64/include/asm/topology.h
+++ b/arch/arm64/include/asm/topology.h
@@ -22,6 +22,15 @@
 void store_cpu_topology(unsigned int cpuid);
 const struct cpumask *cpu_coregroup_mask(int cpu);
 
+struct sched_domain;
+#ifdef CONFIG_CPU_FREQ
+#define arch_scale_freq_capacity cpufreq_scale_freq_capacity
+extern unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu);
+extern unsigned long cpufreq_scale_max_freq_capacity(int cpu);
+#endif
+#define arch_scale_cpu_capacity scale_cpu_capacity
+extern unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu);
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_ARM_TOPOLOGY_H */
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index b2ede967..064cef9 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -18,16 +18,21 @@
 #ifndef __ASM_UACCESS_H
 #define __ASM_UACCESS_H
 
+#include <asm/alternative.h>
+#include <asm/kernel-pgtable.h>
+#include <asm/sysreg.h>
+
+#ifndef __ASSEMBLY__
+
 /*
  * User space memory access functions
  */
+#include <linux/bitops.h>
 #include <linux/string.h>
 #include <linux/thread_info.h>
 
-#include <asm/alternative.h>
 #include <asm/cpufeature.h>
 #include <asm/ptrace.h>
-#include <asm/sysreg.h>
 #include <asm/errno.h>
 #include <asm/memory.h>
 #include <asm/compiler.h>
@@ -36,11 +41,11 @@
 #define VERIFY_WRITE 1
 
 /*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue.  No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
+ * The exception table consists of pairs of relative offsets: the first
+ * is the relative offset to an instruction that is allowed to fault,
+ * and the second is the relative offset at which the program should
+ * continue. No registers are modified, so it is entirely up to the
+ * continuation code to figure out what to do.
  *
  * All the routines below use bits of fixup code that are out of line
  * with the main instruction path.  This means when everything is well,
@@ -50,9 +55,11 @@
 
 struct exception_table_entry
 {
-	unsigned long insn, fixup;
+	int insn, fixup;
 };
 
+#define ARCH_HAS_RELATIVE_EXTABLE
+
 extern int fixup_exception(struct pt_regs *regs);
 
 #define KERNEL_DS	(-1UL)
@@ -64,6 +71,16 @@
 static inline void set_fs(mm_segment_t fs)
 {
 	current_thread_info()->addr_limit = fs;
+
+	/*
+	 * Enable/disable UAO so that copy_to_user() etc can access
+	 * kernel memory with the unprivileged instructions.
+	 */
+	if (IS_ENABLED(CONFIG_ARM64_UAO) && fs == KERNEL_DS)
+		asm(ALTERNATIVE("nop", SET_PSTATE_UAO(1), ARM64_HAS_UAO));
+	else
+		asm(ALTERNATIVE("nop", SET_PSTATE_UAO(0), ARM64_HAS_UAO,
+				CONFIG_ARM64_UAO));
 }
 
 #define segment_eq(a, b)	((a) == (b))
@@ -92,19 +109,126 @@
  */
 #define __range_ok(addr, size)						\
 ({									\
+	unsigned long __addr = (unsigned long __force)(addr);		\
 	unsigned long flag, roksum;					\
 	__chk_user_ptr(addr);						\
 	asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls"		\
 		: "=&r" (flag), "=&r" (roksum)				\
-		: "1" (addr), "Ir" (size),				\
+		: "1" (__addr), "Ir" (size),				\
 		  "r" (current_thread_info()->addr_limit)		\
 		: "cc");						\
 	flag;								\
 })
 
+/*
+ * When dealing with data aborts, watchpoints, or instruction traps we may end
+ * up with a tagged userland pointer. Clear the tag to get a sane pointer to
+ * pass on to access_ok(), for instance.
+ */
+#define untagged_addr(addr)		sign_extend64(addr, 55)
+
 #define access_ok(type, addr, size)	__range_ok(addr, size)
 #define user_addr_max			get_fs
 
+#define _ASM_EXTABLE(from, to)						\
+	"	.pushsection	__ex_table, \"a\"\n"			\
+	"	.align		3\n"					\
+	"	.long		(" #from " - .), (" #to " - .)\n"	\
+	"	.popsection\n"
+
+/*
+ * User access enabling/disabling.
+ */
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+static inline void __uaccess_ttbr0_disable(void)
+{
+	unsigned long ttbr;
+
+	/* reserved_ttbr0 placed at the end of swapper_pg_dir */
+	ttbr = read_sysreg(ttbr1_el1) + SWAPPER_DIR_SIZE;
+	write_sysreg(ttbr, ttbr0_el1);
+	isb();
+}
+
+static inline void __uaccess_ttbr0_enable(void)
+{
+	unsigned long flags;
+
+	/*
+	 * Disable interrupts to avoid preemption between reading the 'ttbr0'
+	 * variable and the MSR. A context switch could trigger an ASID
+	 * roll-over and an update of 'ttbr0'.
+	 */
+	local_irq_save(flags);
+	write_sysreg(current_thread_info()->ttbr0, ttbr0_el1);
+	isb();
+	local_irq_restore(flags);
+}
+
+static inline bool uaccess_ttbr0_disable(void)
+{
+	if (!system_uses_ttbr0_pan())
+		return false;
+	__uaccess_ttbr0_disable();
+	return true;
+}
+
+static inline bool uaccess_ttbr0_enable(void)
+{
+	if (!system_uses_ttbr0_pan())
+		return false;
+	__uaccess_ttbr0_enable();
+	return true;
+}
+#else
+static inline bool uaccess_ttbr0_disable(void)
+{
+	return false;
+}
+
+static inline bool uaccess_ttbr0_enable(void)
+{
+	return false;
+}
+#endif
+
+#define __uaccess_disable(alt)						\
+do {									\
+	if (!uaccess_ttbr0_disable())					\
+		asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), alt,		\
+				CONFIG_ARM64_PAN));			\
+} while (0)
+
+#define __uaccess_enable(alt)						\
+do {									\
+	if (!uaccess_ttbr0_enable())					\
+		asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), alt,		\
+				CONFIG_ARM64_PAN));			\
+} while (0)
+
+static inline void uaccess_disable(void)
+{
+	__uaccess_disable(ARM64_HAS_PAN);
+}
+
+static inline void uaccess_enable(void)
+{
+	__uaccess_enable(ARM64_HAS_PAN);
+}
+
+/*
+ * These functions are no-ops when UAO is present.
+ */
+static inline void uaccess_disable_not_uao(void)
+{
+	__uaccess_disable(ARM64_ALT_PAN_NOT_UAO);
+}
+
+static inline void uaccess_enable_not_uao(void)
+{
+	__uaccess_enable(ARM64_ALT_PAN_NOT_UAO);
+}
+
 /*
  * The "__xxx" versions of the user access functions do not verify the address
  * space - it must have been done previously with a separate "access_ok()"
@@ -113,9 +237,10 @@
  * The "__xxx_error" versions set the third argument to -EFAULT if an error
  * occurs, and leave it unchanged on success.
  */
-#define __get_user_asm(instr, reg, x, addr, err)			\
+#define __get_user_asm(instr, alt_instr, reg, x, addr, err, feature)	\
 	asm volatile(							\
-	"1:	" instr "	" reg "1, [%2]\n"			\
+	"1:"ALTERNATIVE(instr "     " reg "1, [%2]\n",			\
+			alt_instr " " reg "1, [%2]\n", feature)		\
 	"2:\n"								\
 	"	.section .fixup, \"ax\"\n"				\
 	"	.align	2\n"						\
@@ -123,10 +248,7 @@
 	"	mov	%1, #0\n"					\
 	"	b	2b\n"						\
 	"	.previous\n"						\
-	"	.section __ex_table,\"a\"\n"				\
-	"	.align	3\n"						\
-	"	.quad	1b, 3b\n"					\
-	"	.previous"						\
+	_ASM_EXTABLE(1b, 3b)						\
 	: "+r" (err), "=&r" (x)						\
 	: "r" (addr), "i" (-EFAULT))
 
@@ -134,27 +256,29 @@
 do {									\
 	unsigned long __gu_val;						\
 	__chk_user_ptr(ptr);						\
-	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,	\
-			CONFIG_ARM64_PAN));				\
+	uaccess_enable_not_uao();					\
 	switch (sizeof(*(ptr))) {					\
 	case 1:								\
-		__get_user_asm("ldrb", "%w", __gu_val, (ptr), (err));	\
+		__get_user_asm("ldrb", "ldtrb", "%w", __gu_val, (ptr),  \
+			       (err), ARM64_HAS_UAO);			\
 		break;							\
 	case 2:								\
-		__get_user_asm("ldrh", "%w", __gu_val, (ptr), (err));	\
+		__get_user_asm("ldrh", "ldtrh", "%w", __gu_val, (ptr),  \
+			       (err), ARM64_HAS_UAO);			\
 		break;							\
 	case 4:								\
-		__get_user_asm("ldr", "%w", __gu_val, (ptr), (err));	\
+		__get_user_asm("ldr", "ldtr", "%w", __gu_val, (ptr),	\
+			       (err), ARM64_HAS_UAO);			\
 		break;							\
 	case 8:								\
-		__get_user_asm("ldr", "%",  __gu_val, (ptr), (err));	\
+		__get_user_asm("ldr", "ldtr", "%",  __gu_val, (ptr),	\
+			       (err), ARM64_HAS_UAO);			\
 		break;							\
 	default:							\
 		BUILD_BUG();						\
 	}								\
+	uaccess_disable_not_uao();					\
 	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
-	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,	\
-			CONFIG_ARM64_PAN));				\
 } while (0)
 
 #define __get_user(x, ptr)						\
@@ -181,19 +305,17 @@
 		((x) = 0, -EFAULT);					\
 })
 
-#define __put_user_asm(instr, reg, x, addr, err)			\
+#define __put_user_asm(instr, alt_instr, reg, x, addr, err, feature)	\
 	asm volatile(							\
-	"1:	" instr "	" reg "1, [%2]\n"			\
+	"1:"ALTERNATIVE(instr "     " reg "1, [%2]\n",			\
+			alt_instr " " reg "1, [%2]\n", feature)		\
 	"2:\n"								\
 	"	.section .fixup,\"ax\"\n"				\
 	"	.align	2\n"						\
 	"3:	mov	%w0, %3\n"					\
 	"	b	2b\n"						\
 	"	.previous\n"						\
-	"	.section __ex_table,\"a\"\n"				\
-	"	.align	3\n"						\
-	"	.quad	1b, 3b\n"					\
-	"	.previous"						\
+	_ASM_EXTABLE(1b, 3b)						\
 	: "+r" (err)							\
 	: "r" (x), "r" (addr), "i" (-EFAULT))
 
@@ -201,26 +323,28 @@
 do {									\
 	__typeof__(*(ptr)) __pu_val = (x);				\
 	__chk_user_ptr(ptr);						\
-	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,	\
-			CONFIG_ARM64_PAN));				\
+	uaccess_enable_not_uao();					\
 	switch (sizeof(*(ptr))) {					\
 	case 1:								\
-		__put_user_asm("strb", "%w", __pu_val, (ptr), (err));	\
+		__put_user_asm("strb", "sttrb", "%w", __pu_val, (ptr),	\
+			       (err), ARM64_HAS_UAO);			\
 		break;							\
 	case 2:								\
-		__put_user_asm("strh", "%w", __pu_val, (ptr), (err));	\
+		__put_user_asm("strh", "sttrh", "%w", __pu_val, (ptr),	\
+			       (err), ARM64_HAS_UAO);			\
 		break;							\
 	case 4:								\
-		__put_user_asm("str",  "%w", __pu_val, (ptr), (err));	\
+		__put_user_asm("str", "sttr", "%w", __pu_val, (ptr),	\
+			       (err), ARM64_HAS_UAO);			\
 		break;							\
 	case 8:								\
-		__put_user_asm("str",  "%", __pu_val, (ptr), (err));	\
+		__put_user_asm("str", "sttr", "%", __pu_val, (ptr),	\
+			       (err), ARM64_HAS_UAO);			\
 		break;							\
 	default:							\
 		BUILD_BUG();						\
 	}								\
-	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,	\
-			CONFIG_ARM64_PAN));				\
+	uaccess_disable_not_uao();					\
 } while (0)
 
 #define __put_user(x, ptr)						\
@@ -247,24 +371,39 @@
 		-EFAULT;						\
 })
 
-extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
-extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
+extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
+extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
 extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n);
 extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
 
+static inline unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	check_object_size(to, n, false);
+	return __arch_copy_from_user(to, from, n);
+}
+
+static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	check_object_size(from, n, true);
+	return __arch_copy_to_user(to, from, n);
+}
+
 static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-	if (access_ok(VERIFY_READ, from, n))
-		n = __copy_from_user(to, from, n);
-	else /* security hole - plug it */
+	if (access_ok(VERIFY_READ, from, n)) {
+		check_object_size(to, n, false);
+		n = __arch_copy_from_user(to, from, n);
+	} else /* security hole - plug it */
 		memset(to, 0, n);
 	return n;
 }
 
 static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
 {
-	if (access_ok(VERIFY_WRITE, to, n))
-		n = __copy_to_user(to, from, n);
+	if (access_ok(VERIFY_WRITE, to, n)) {
+		check_object_size(from, n, true);
+		n = __arch_copy_to_user(to, from, n);
+	}
 	return n;
 }
 
@@ -290,4 +429,66 @@
 extern __must_check long strlen_user(const char __user *str);
 extern __must_check long strnlen_user(const char __user *str, long n);
 
+#else	/* __ASSEMBLY__ */
+
+#include <asm/assembler.h>
+
+/*
+ * User access enabling/disabling macros.
+ */
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	.macro	__uaccess_ttbr0_disable, tmp1
+	mrs	\tmp1, ttbr1_el1		// swapper_pg_dir
+	add	\tmp1, \tmp1, #SWAPPER_DIR_SIZE	// reserved_ttbr0 at the end of swapper_pg_dir
+	msr	ttbr0_el1, \tmp1		// set reserved TTBR0_EL1
+	isb
+	.endm
+
+	.macro	__uaccess_ttbr0_enable, tmp1
+	get_thread_info \tmp1
+	ldr	\tmp1, [\tmp1, #TSK_TI_TTBR0]	// load saved TTBR0_EL1
+	msr	ttbr0_el1, \tmp1		// set the non-PAN TTBR0_EL1
+	isb
+	.endm
+
+	.macro	uaccess_ttbr0_disable, tmp1
+alternative_if_not ARM64_HAS_PAN
+	__uaccess_ttbr0_disable \tmp1
+alternative_else_nop_endif
+	.endm
+
+	.macro	uaccess_ttbr0_enable, tmp1, tmp2
+alternative_if_not ARM64_HAS_PAN
+	save_and_disable_irq \tmp2		// avoid preemption
+	__uaccess_ttbr0_enable \tmp1
+	restore_irq \tmp2
+alternative_else_nop_endif
+	.endm
+#else
+	.macro	uaccess_ttbr0_disable, tmp1
+	.endm
+
+	.macro	uaccess_ttbr0_enable, tmp1, tmp2
+	.endm
+#endif
+
+/*
+ * These macros are no-ops when UAO is present.
+ */
+	.macro	uaccess_disable_not_uao, tmp1
+	uaccess_ttbr0_disable \tmp1
+alternative_if ARM64_ALT_PAN_NOT_UAO
+	SET_PSTATE_PAN(1)
+alternative_else_nop_endif
+	.endm
+
+	.macro	uaccess_enable_not_uao, tmp1, tmp2
+	uaccess_ttbr0_enable \tmp1, \tmp2
+alternative_if ARM64_ALT_PAN_NOT_UAO
+	SET_PSTATE_PAN(0)
+alternative_else_nop_endif
+	.endm
+
+#endif	/* __ASSEMBLY__ */
+
 #endif /* __ASM_UACCESS_H */
diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h
index de66199..2b9a637 100644
--- a/arch/arm64/include/asm/vdso_datapage.h
+++ b/arch/arm64/include/asm/vdso_datapage.h
@@ -22,6 +22,8 @@
 
 struct vdso_data {
 	__u64 cs_cycle_last;	/* Timebase at clocksource init */
+	__u64 raw_time_sec;	/* Raw time */
+	__u64 raw_time_nsec;
 	__u64 xtime_clock_sec;	/* Kernel time */
 	__u64 xtime_clock_nsec;
 	__u64 xtime_coarse_sec;	/* Coarse time */
@@ -29,8 +31,10 @@
 	__u64 wtm_clock_sec;	/* Wall to monotonic time */
 	__u64 wtm_clock_nsec;
 	__u32 tb_seq_count;	/* Timebase sequence counter */
-	__u32 cs_mult;		/* Clocksource multiplier */
-	__u32 cs_shift;		/* Clocksource shift */
+	/* cs_* members must be adjacent and in this order (ldp accesses) */
+	__u32 cs_mono_mult;	/* NTP-adjusted clocksource multiplier */
+	__u32 cs_shift;		/* Clocksource shift (mono = raw) */
+	__u32 cs_raw_mult;	/* Raw clocksource multiplier */
 	__u32 tz_minuteswest;	/* Whacky timezone stuff */
 	__u32 tz_dsttime;
 	__u32 use_syscall;
diff --git a/arch/arm64/include/asm/word-at-a-time.h b/arch/arm64/include/asm/word-at-a-time.h
index aab5bf0..2b79b8a 100644
--- a/arch/arm64/include/asm/word-at-a-time.h
+++ b/arch/arm64/include/asm/word-at-a-time.h
@@ -16,6 +16,8 @@
 #ifndef __ASM_WORD_AT_A_TIME_H
 #define __ASM_WORD_AT_A_TIME_H
 
+#include <asm/uaccess.h>
+
 #ifndef __AARCH64EB__
 
 #include <linux/kernel.h>
@@ -81,10 +83,7 @@
 #endif
 	"	b	2b\n"
 	"	.popsection\n"
-	"	.pushsection __ex_table,\"a\"\n"
-	"	.align	3\n"
-	"	.quad	1b, 3b\n"
-	"	.popsection"
+	_ASM_EXTABLE(1b, 3b)
 	: "=&r" (ret), "=&r" (offset)
 	: "r" (addr), "Q" (*(unsigned long *)addr));
 
diff --git a/arch/arm64/include/uapi/asm/auxvec.h b/arch/arm64/include/uapi/asm/auxvec.h
index 22d6d88..4cf0c17 100644
--- a/arch/arm64/include/uapi/asm/auxvec.h
+++ b/arch/arm64/include/uapi/asm/auxvec.h
@@ -19,4 +19,6 @@
 /* vDSO location */
 #define AT_SYSINFO_EHDR	33
 
+#define AT_VECTOR_SIZE_ARCH 1 /* entries in ARCH_DLINFO */
+
 #endif
diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h
index 208db3d..d1ff83d 100644
--- a/arch/arm64/include/uapi/asm/ptrace.h
+++ b/arch/arm64/include/uapi/asm/ptrace.h
@@ -45,6 +45,7 @@
 #define PSR_A_BIT	0x00000100
 #define PSR_D_BIT	0x00000200
 #define PSR_PAN_BIT	0x00400000
+#define PSR_UAO_BIT	0x00800000
 #define PSR_Q_BIT	0x08000000
 #define PSR_V_BIT	0x10000000
 #define PSR_C_BIT	0x20000000
@@ -76,6 +77,7 @@
 	__uint128_t	vregs[32];
 	__u32		fpsr;
 	__u32		fpcr;
+	__u32		__reserved[2];
 };
 
 struct user_hwdebug_state {
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 474691f..b570e9e 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -30,6 +30,7 @@
 					   ../../arm/kernel/opcodes.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
+arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
 arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= hw_breakpoint.o
@@ -41,12 +42,10 @@
 arm64-obj-$(CONFIG_PCI)			+= pci.o
 arm64-obj-$(CONFIG_ARMV8_DEPRECATED)	+= armv8_deprecated.o
 arm64-obj-$(CONFIG_ACPI)		+= acpi.o
+arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL)	+= acpi_parking_protocol.o
+arm64-obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
 head-y					:= head.o
 extra-y					+= $(head-y) vmlinux.lds
-
-# vDSO - this must be built first to generate the symbol offsets
-$(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
-$(obj)/vdso/vdso-offsets.h: $(obj)/vdso
diff --git a/arch/arm64/kernel/acpi_parking_protocol.c b/arch/arm64/kernel/acpi_parking_protocol.c
new file mode 100644
index 0000000..4b1e5a7
--- /dev/null
+++ b/arch/arm64/kernel/acpi_parking_protocol.c
@@ -0,0 +1,153 @@
+/*
+ * ARM64 ACPI Parking Protocol implementation
+ *
+ * Authors: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ *	    Mark Salter <msalter@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/acpi.h>
+#include <linux/types.h>
+
+#include <asm/cpu_ops.h>
+
+struct cpu_mailbox_entry {
+	phys_addr_t mailbox_addr;
+	u8 version;
+	u8 gic_cpu_id;
+};
+
+static struct cpu_mailbox_entry cpu_mailbox_entries[NR_CPUS];
+
+void __init acpi_set_mailbox_entry(int cpu,
+				   struct acpi_madt_generic_interrupt *p)
+{
+	struct cpu_mailbox_entry *cpu_entry = &cpu_mailbox_entries[cpu];
+
+	cpu_entry->mailbox_addr = p->parked_address;
+	cpu_entry->version = p->parking_version;
+	cpu_entry->gic_cpu_id = p->cpu_interface_number;
+}
+
+bool acpi_parking_protocol_valid(int cpu)
+{
+	struct cpu_mailbox_entry *cpu_entry = &cpu_mailbox_entries[cpu];
+
+	return cpu_entry->mailbox_addr && cpu_entry->version;
+}
+
+static int acpi_parking_protocol_cpu_init(unsigned int cpu)
+{
+	pr_debug("%s: ACPI parked addr=%llx\n", __func__,
+		  cpu_mailbox_entries[cpu].mailbox_addr);
+
+	return 0;
+}
+
+static int acpi_parking_protocol_cpu_prepare(unsigned int cpu)
+{
+	return 0;
+}
+
+struct parking_protocol_mailbox {
+	__le32 cpu_id;
+	__le32 reserved;
+	__le64 entry_point;
+};
+
+static int acpi_parking_protocol_cpu_boot(unsigned int cpu)
+{
+	struct cpu_mailbox_entry *cpu_entry = &cpu_mailbox_entries[cpu];
+	struct parking_protocol_mailbox __iomem *mailbox;
+	__le32 cpu_id;
+
+	/*
+	 * Map mailbox memory with attribute device nGnRE (ie ioremap -
+	 * this deviates from the parking protocol specifications since
+	 * the mailboxes are required to be mapped nGnRnE; the attribute
+	 * discrepancy is harmless insofar as the protocol specification
+	 * is concerned).
+	 * If the mailbox is mistakenly allocated in the linear mapping
+	 * by FW ioremap will fail since the mapping will be prevented
+	 * by the kernel (it clashes with the linear mapping attributes
+	 * specifications).
+	 */
+	mailbox = ioremap(cpu_entry->mailbox_addr, sizeof(*mailbox));
+	if (!mailbox)
+		return -EIO;
+
+	cpu_id = readl_relaxed(&mailbox->cpu_id);
+	/*
+	 * Check if firmware has set-up the mailbox entry properly
+	 * before kickstarting the respective cpu.
+	 */
+	if (cpu_id != ~0U) {
+		iounmap(mailbox);
+		return -ENXIO;
+	}
+
+	/*
+	 * We write the entry point and cpu id as LE regardless of the
+	 * native endianness of the kernel. Therefore, any boot-loaders
+	 * that read this address need to convert this address to the
+	 * Boot-Loader's endianness before jumping.
+	 */
+	writeq_relaxed(__pa(secondary_entry), &mailbox->entry_point);
+	writel_relaxed(cpu_entry->gic_cpu_id, &mailbox->cpu_id);
+
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+	iounmap(mailbox);
+
+	return 0;
+}
+
+static void acpi_parking_protocol_cpu_postboot(void)
+{
+	int cpu = smp_processor_id();
+	struct cpu_mailbox_entry *cpu_entry = &cpu_mailbox_entries[cpu];
+	struct parking_protocol_mailbox __iomem *mailbox;
+	__le64 entry_point;
+
+	/*
+	 * Map mailbox memory with attribute device nGnRE (ie ioremap -
+	 * this deviates from the parking protocol specifications since
+	 * the mailboxes are required to be mapped nGnRnE; the attribute
+	 * discrepancy is harmless insofar as the protocol specification
+	 * is concerned).
+	 * If the mailbox is mistakenly allocated in the linear mapping
+	 * by FW ioremap will fail since the mapping will be prevented
+	 * by the kernel (it clashes with the linear mapping attributes
+	 * specifications).
+	 */
+	mailbox = ioremap(cpu_entry->mailbox_addr, sizeof(*mailbox));
+	if (!mailbox)
+		return;
+
+	entry_point = readl_relaxed(&mailbox->entry_point);
+	/*
+	 * Check if firmware has cleared the entry_point as expected
+	 * by the protocol specification.
+	 */
+	WARN_ON(entry_point);
+
+	iounmap(mailbox);
+}
+
+const struct cpu_operations acpi_parking_protocol_ops = {
+	.name		= "parking-protocol",
+	.cpu_init	= acpi_parking_protocol_cpu_init,
+	.cpu_prepare	= acpi_parking_protocol_cpu_prepare,
+	.cpu_boot	= acpi_parking_protocol_cpu_boot,
+	.cpu_postboot	= acpi_parking_protocol_cpu_postboot
+};
diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
index ab9db0e..d2ee1b2 100644
--- a/arch/arm64/kernel/alternative.c
+++ b/arch/arm64/kernel/alternative.c
@@ -158,9 +158,3 @@
 
 	__apply_alternatives(&region);
 }
-
-void free_alternatives_memory(void)
-{
-	free_reserved_area(__alt_instructions, __alt_instructions_end,
-			   0, "alternatives");
-}
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 3b6d8cc..c654df0 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -33,8 +33,8 @@
 EXPORT_SYMBOL(clear_page);
 
 	/* user mem (segment) */
-EXPORT_SYMBOL(__copy_from_user);
-EXPORT_SYMBOL(__copy_to_user);
+EXPORT_SYMBOL(__arch_copy_from_user);
+EXPORT_SYMBOL(__arch_copy_to_user);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(__copy_in_user);
 
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 937f5e5..185ac13 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 
-#include <asm/alternative.h>
 #include <asm/cpufeature.h>
 #include <asm/insn.h>
 #include <asm/opcodes.h>
@@ -62,7 +61,7 @@
 };
 
 static LIST_HEAD(insn_emulation);
-static int nr_insn_emulated;
+static int nr_insn_emulated __initdata;
 static DEFINE_RAW_SPINLOCK(insn_emulation_lock);
 
 static void register_emulation_hooks(struct insn_emulation_ops *ops)
@@ -173,7 +172,7 @@
 	return ret;
 }
 
-static void register_insn_emulation(struct insn_emulation_ops *ops)
+static void __init register_insn_emulation(struct insn_emulation_ops *ops)
 {
 	unsigned long flags;
 	struct insn_emulation *insn;
@@ -237,7 +236,7 @@
 	{ }
 };
 
-static void register_insn_emulation_sysctl(struct ctl_table *table)
+static void __init register_insn_emulation_sysctl(struct ctl_table *table)
 {
 	unsigned long flags;
 	int i = 0;
@@ -281,9 +280,9 @@
  * Error-checking SWP macros implemented using ldxr{b}/stxr{b}
  */
 #define __user_swpX_asm(data, addr, res, temp, B)		\
+do {								\
+	uaccess_enable();					\
 	__asm__ __volatile__(					\
-	ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,	\
-		    CONFIG_ARM64_PAN)				\
 	"0:	ldxr"B"		%w2, [%3]\n"			\
 	"1:	stxr"B"		%w0, %w1, [%3]\n"		\
 	"	cbz		%w0, 2f\n"			\
@@ -297,16 +296,14 @@
 	"4:	mov		%w0, %w5\n"			\
 	"	b		3b\n"				\
 	"	.popsection"					\
-	"	.pushsection	 __ex_table,\"a\"\n"		\
-	"	.align		3\n"				\
-	"	.quad		0b, 4b\n"			\
-	"	.quad		1b, 4b\n"			\
-	"	.popsection\n"					\
-	ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,	\
-		CONFIG_ARM64_PAN)				\
+	_ASM_EXTABLE(0b, 4b)					\
+	_ASM_EXTABLE(1b, 4b)					\
 	: "=&r" (res), "+r" (data), "=&r" (temp)		\
-	: "r" (addr), "i" (-EAGAIN), "i" (-EFAULT)		\
-	: "memory")
+	: "r" ((unsigned long)addr), "i" (-EAGAIN),		\
+	  "i" (-EFAULT)						\
+	: "memory");						\
+	uaccess_disable();					\
+} while (0)
 
 #define __user_swp_asm(data, addr, res, temp) \
 	__user_swpX_asm(data, addr, res, temp, "")
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 25de8b2..b84d8e8 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -38,6 +38,9 @@
   DEFINE(TI_ADDR_LIMIT,		offsetof(struct thread_info, addr_limit));
   DEFINE(TI_TASK,		offsetof(struct thread_info, task));
   DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+  DEFINE(TSK_TI_TTBR0,		offsetof(struct thread_info, ttbr0));
+#endif
   BLANK();
   DEFINE(THREAD_CPU_CONTEXT,	offsetof(struct task_struct, thread.cpu_context));
   BLANK();
@@ -58,6 +61,7 @@
   DEFINE(S_PC,			offsetof(struct pt_regs, pc));
   DEFINE(S_ORIG_X0,		offsetof(struct pt_regs, orig_x0));
   DEFINE(S_SYSCALLNO,		offsetof(struct pt_regs, syscallno));
+  DEFINE(S_ORIG_ADDR_LIMIT,	offsetof(struct pt_regs, orig_addr_limit));
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
   DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id.counter));
@@ -75,6 +79,7 @@
   BLANK();
   DEFINE(CLOCK_REALTIME,	CLOCK_REALTIME);
   DEFINE(CLOCK_MONOTONIC,	CLOCK_MONOTONIC);
+  DEFINE(CLOCK_MONOTONIC_RAW,	CLOCK_MONOTONIC_RAW);
   DEFINE(CLOCK_REALTIME_RES,	MONOTONIC_RES_NSEC);
   DEFINE(CLOCK_REALTIME_COARSE,	CLOCK_REALTIME_COARSE);
   DEFINE(CLOCK_MONOTONIC_COARSE,CLOCK_MONOTONIC_COARSE);
@@ -82,6 +87,8 @@
   DEFINE(NSEC_PER_SEC,		NSEC_PER_SEC);
   BLANK();
   DEFINE(VDSO_CS_CYCLE_LAST,	offsetof(struct vdso_data, cs_cycle_last));
+  DEFINE(VDSO_RAW_TIME_SEC,	offsetof(struct vdso_data, raw_time_sec));
+  DEFINE(VDSO_RAW_TIME_NSEC,	offsetof(struct vdso_data, raw_time_nsec));
   DEFINE(VDSO_XTIME_CLK_SEC,	offsetof(struct vdso_data, xtime_clock_sec));
   DEFINE(VDSO_XTIME_CLK_NSEC,	offsetof(struct vdso_data, xtime_clock_nsec));
   DEFINE(VDSO_XTIME_CRS_SEC,	offsetof(struct vdso_data, xtime_coarse_sec));
@@ -89,7 +96,8 @@
   DEFINE(VDSO_WTM_CLK_SEC,	offsetof(struct vdso_data, wtm_clock_sec));
   DEFINE(VDSO_WTM_CLK_NSEC,	offsetof(struct vdso_data, wtm_clock_nsec));
   DEFINE(VDSO_TB_SEQ_COUNT,	offsetof(struct vdso_data, tb_seq_count));
-  DEFINE(VDSO_CS_MULT,		offsetof(struct vdso_data, cs_mult));
+  DEFINE(VDSO_CS_MONO_MULT,	offsetof(struct vdso_data, cs_mono_mult));
+  DEFINE(VDSO_CS_RAW_MULT,	offsetof(struct vdso_data, cs_raw_mult));
   DEFINE(VDSO_CS_SHIFT,		offsetof(struct vdso_data, cs_shift));
   DEFINE(VDSO_TZ_MINWEST,	offsetof(struct vdso_data, tz_minuteswest));
   DEFINE(VDSO_TZ_DSTTIME,	offsetof(struct vdso_data, tz_dsttime));
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index feb6b4e..06afd04 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -21,24 +21,12 @@
 #include <asm/cputype.h>
 #include <asm/cpufeature.h>
 
-#define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
-#define MIDR_CORTEX_A57 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
-#define MIDR_THUNDERX	MIDR_CPU_PART(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
-
-#define CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \
-			MIDR_ARCHITECTURE_MASK)
-
 static bool __maybe_unused
 is_affected_midr_range(const struct arm64_cpu_capabilities *entry)
 {
-	u32 midr = read_cpuid_id();
-
-	if ((midr & CPU_MODEL_MASK) != entry->midr_model)
-		return false;
-
-	midr &= MIDR_REVISION_MASK | MIDR_VARIANT_MASK;
-
-	return (midr >= entry->midr_range_min && midr <= entry->midr_range_max);
+	return MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(), entry->midr_model,
+				       entry->midr_range_min,
+				       entry->midr_range_max);
 }
 
 #define MIDR_RANGE(model, min, max) \
@@ -100,6 +88,15 @@
 		MIDR_RANGE(MIDR_THUNDERX, 0x00, 0x01),
 	},
 #endif
+#ifdef CONFIG_CAVIUM_ERRATUM_27456
+	{
+	/* Cavium ThunderX, T88 pass 1.x - 2.1 */
+		.desc = "Cavium erratum 27456",
+		.capability = ARM64_WORKAROUND_CAVIUM_27456,
+		MIDR_RANGE(MIDR_THUNDERX, 0x00,
+			   (1 << MIDR_VARIANT_SHIFT) | 1),
+	},
+#endif
 	{
 	}
 };
diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c
index b6bd7d4..c7cfb8f 100644
--- a/arch/arm64/kernel/cpu_ops.c
+++ b/arch/arm64/kernel/cpu_ops.c
@@ -25,19 +25,30 @@
 #include <asm/smp_plat.h>
 
 extern const struct cpu_operations smp_spin_table_ops;
+extern const struct cpu_operations acpi_parking_protocol_ops;
 extern const struct cpu_operations cpu_psci_ops;
 
 const struct cpu_operations *cpu_ops[NR_CPUS];
 
-static const struct cpu_operations *supported_cpu_ops[] __initconst = {
+static const struct cpu_operations *dt_supported_cpu_ops[] __initconst = {
 	&smp_spin_table_ops,
 	&cpu_psci_ops,
 	NULL,
 };
 
+static const struct cpu_operations *acpi_supported_cpu_ops[] __initconst = {
+#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
+	&acpi_parking_protocol_ops,
+#endif
+	&cpu_psci_ops,
+	NULL,
+};
+
 static const struct cpu_operations * __init cpu_get_ops(const char *name)
 {
-	const struct cpu_operations **ops = supported_cpu_ops;
+	const struct cpu_operations **ops;
+
+	ops = acpi_disabled ? dt_supported_cpu_ops : acpi_supported_cpu_ops;
 
 	while (*ops) {
 		if (!strcmp(name, (*ops)->name))
@@ -75,8 +86,16 @@
 		}
 	} else {
 		enable_method = acpi_get_enable_method(cpu);
-		if (!enable_method)
-			pr_err("Unsupported ACPI enable-method\n");
+		if (!enable_method) {
+			/*
+			 * In ACPI systems the boot CPU does not require
+			 * checking the enable method since for some
+			 * boot protocol (ie parking protocol) it need not
+			 * be initialized. Don't warn spuriously.
+			 */
+			if (cpu != 0)
+				pr_err("Unsupported ACPI enable-method\n");
+		}
 	}
 
 	return enable_method;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 0669c63..ae88858 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -19,7 +19,9 @@
 #define pr_fmt(fmt) "CPU features: " fmt
 
 #include <linux/bsearch.h>
+#include <linux/cpumask.h>
 #include <linux/sort.h>
+#include <linux/stop_machine.h>
 #include <linux/types.h>
 #include <asm/cpu.h>
 #include <asm/cpufeature.h>
@@ -43,6 +45,7 @@
 #endif
 
 DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
+EXPORT_SYMBOL(cpu_hwcaps);
 
 #define __ARM64_FTR_BITS(SIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
 	{						\
@@ -67,6 +70,10 @@
 		.width = 0,				\
 	}
 
+/* meta feature for alternatives */
+static bool __maybe_unused
+cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry);
+
 static struct arm64_ftr_bits ftr_id_aa64isar0[] = {
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_RDM_SHIFT, 4, 0),
@@ -123,6 +130,11 @@
 	ARM64_FTR_END,
 };
 
+static struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
+	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_UAO_SHIFT, 4, 0),
+	ARM64_FTR_END,
+};
+
 static struct arm64_ftr_bits ftr_ctr[] = {
 	U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 31, 1, 1),	/* RAO */
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 3, 0),
@@ -284,6 +296,7 @@
 	/* Op1 = 0, CRn = 0, CRm = 7 */
 	ARM64_FTR_REG(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0),
 	ARM64_FTR_REG(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1),
+	ARM64_FTR_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2),
 
 	/* Op1 = 3, CRn = 0, CRm = 0 */
 	ARM64_FTR_REG(SYS_CTR_EL0, ftr_ctr),
@@ -408,6 +421,7 @@
 	init_cpu_ftr_reg(SYS_ID_AA64ISAR1_EL1, info->reg_id_aa64isar1);
 	init_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0);
 	init_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1);
+	init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2);
 	init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0);
 	init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
 	init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
@@ -517,6 +531,8 @@
 				      info->reg_id_aa64mmfr0, boot->reg_id_aa64mmfr0);
 	taint |= check_update_ftr_reg(SYS_ID_AA64MMFR1_EL1, cpu,
 				      info->reg_id_aa64mmfr1, boot->reg_id_aa64mmfr1);
+	taint |= check_update_ftr_reg(SYS_ID_AA64MMFR2_EL1, cpu,
+				      info->reg_id_aa64mmfr2, boot->reg_id_aa64mmfr2);
 
 	/*
 	 * EL3 is not our concern.
@@ -621,6 +637,18 @@
 	return has_sre;
 }
 
+static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry)
+{
+	u32 midr = read_cpuid_id();
+	u32 rv_min, rv_max;
+
+	/* Cavium ThunderX pass 1.x and 2.x */
+	rv_min = 0;
+	rv_max = (1 << MIDR_VARIANT_SHIFT) | MIDR_REVISION_MASK;
+
+	return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX, rv_min, rv_max);
+}
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "GIC system register CPU interface",
@@ -651,6 +679,28 @@
 		.min_field_value = 2,
 	},
 #endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
+	{
+		.desc = "Software prefetching using PRFM",
+		.capability = ARM64_HAS_NO_HW_PREFETCH,
+		.matches = has_no_hw_prefetch,
+	},
+#ifdef CONFIG_ARM64_UAO
+	{
+		.desc = "User Access Override",
+		.capability = ARM64_HAS_UAO,
+		.matches = has_cpuid_feature,
+		.sys_reg = SYS_ID_AA64MMFR2_EL1,
+		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
+		.min_field_value = 1,
+		.enable = cpu_enable_uao,
+	},
+#endif /* CONFIG_ARM64_UAO */
+#ifdef CONFIG_ARM64_PAN
+	{
+		.capability = ARM64_ALT_PAN_NOT_UAO,
+		.matches = cpufeature_pan_not_uao,
+	},
+#endif /* CONFIG_ARM64_PAN */
 	{},
 };
 
@@ -684,7 +734,7 @@
 	{},
 };
 
-static void cap_set_hwcap(const struct arm64_cpu_capabilities *cap)
+static void __init cap_set_hwcap(const struct arm64_cpu_capabilities *cap)
 {
 	switch (cap->hwcap_type) {
 	case CAP_HWCAP:
@@ -729,12 +779,12 @@
 	return rc;
 }
 
-static void setup_cpu_hwcaps(void)
+static void __init setup_cpu_hwcaps(void)
 {
 	int i;
 	const struct arm64_cpu_capabilities *hwcaps = arm64_hwcaps;
 
-	for (i = 0; hwcaps[i].desc; i++)
+	for (i = 0; hwcaps[i].matches; i++)
 		if (hwcaps[i].matches(&hwcaps[i]))
 			cap_set_hwcap(&hwcaps[i]);
 }
@@ -744,11 +794,11 @@
 {
 	int i;
 
-	for (i = 0; caps[i].desc; i++) {
+	for (i = 0; caps[i].matches; i++) {
 		if (!caps[i].matches(&caps[i]))
 			continue;
 
-		if (!cpus_have_cap(caps[i].capability))
+		if (!cpus_have_cap(caps[i].capability) && caps[i].desc)
 			pr_info("%s %s\n", info, caps[i].desc);
 		cpus_set_cap(caps[i].capability);
 	}
@@ -758,13 +808,20 @@
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
  */
-static void enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
+static void __init
+enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 {
 	int i;
 
-	for (i = 0; caps[i].desc; i++)
+	for (i = 0; caps[i].matches; i++)
 		if (caps[i].enable && cpus_have_cap(caps[i].capability))
-			on_each_cpu(caps[i].enable, NULL, true);
+			/*
+			 * Use stop_machine() as it schedules the work allowing
+			 * us to modify PSTATE, instead of on_each_cpu() which
+			 * uses an IPI, giving us a PSTATE that disappears when
+			 * we return.
+			 */
+			stop_machine(caps[i].enable, NULL, cpu_online_mask);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -790,35 +847,36 @@
 static u64 __raw_read_system_reg(u32 sys_id)
 {
 	switch (sys_id) {
-	case SYS_ID_PFR0_EL1:		return (u64)read_cpuid(ID_PFR0_EL1);
-	case SYS_ID_PFR1_EL1:		return (u64)read_cpuid(ID_PFR1_EL1);
-	case SYS_ID_DFR0_EL1:		return (u64)read_cpuid(ID_DFR0_EL1);
-	case SYS_ID_MMFR0_EL1:		return (u64)read_cpuid(ID_MMFR0_EL1);
-	case SYS_ID_MMFR1_EL1:		return (u64)read_cpuid(ID_MMFR1_EL1);
-	case SYS_ID_MMFR2_EL1:		return (u64)read_cpuid(ID_MMFR2_EL1);
-	case SYS_ID_MMFR3_EL1:		return (u64)read_cpuid(ID_MMFR3_EL1);
-	case SYS_ID_ISAR0_EL1:		return (u64)read_cpuid(ID_ISAR0_EL1);
-	case SYS_ID_ISAR1_EL1:		return (u64)read_cpuid(ID_ISAR1_EL1);
-	case SYS_ID_ISAR2_EL1:		return (u64)read_cpuid(ID_ISAR2_EL1);
-	case SYS_ID_ISAR3_EL1:		return (u64)read_cpuid(ID_ISAR3_EL1);
-	case SYS_ID_ISAR4_EL1:		return (u64)read_cpuid(ID_ISAR4_EL1);
-	case SYS_ID_ISAR5_EL1:		return (u64)read_cpuid(ID_ISAR4_EL1);
-	case SYS_MVFR0_EL1:		return (u64)read_cpuid(MVFR0_EL1);
-	case SYS_MVFR1_EL1:		return (u64)read_cpuid(MVFR1_EL1);
-	case SYS_MVFR2_EL1:		return (u64)read_cpuid(MVFR2_EL1);
+	case SYS_ID_PFR0_EL1:		return read_cpuid(SYS_ID_PFR0_EL1);
+	case SYS_ID_PFR1_EL1:		return read_cpuid(SYS_ID_PFR1_EL1);
+	case SYS_ID_DFR0_EL1:		return read_cpuid(SYS_ID_DFR0_EL1);
+	case SYS_ID_MMFR0_EL1:		return read_cpuid(SYS_ID_MMFR0_EL1);
+	case SYS_ID_MMFR1_EL1:		return read_cpuid(SYS_ID_MMFR1_EL1);
+	case SYS_ID_MMFR2_EL1:		return read_cpuid(SYS_ID_MMFR2_EL1);
+	case SYS_ID_MMFR3_EL1:		return read_cpuid(SYS_ID_MMFR3_EL1);
+	case SYS_ID_ISAR0_EL1:		return read_cpuid(SYS_ID_ISAR0_EL1);
+	case SYS_ID_ISAR1_EL1:		return read_cpuid(SYS_ID_ISAR1_EL1);
+	case SYS_ID_ISAR2_EL1:		return read_cpuid(SYS_ID_ISAR2_EL1);
+	case SYS_ID_ISAR3_EL1:		return read_cpuid(SYS_ID_ISAR3_EL1);
+	case SYS_ID_ISAR4_EL1:		return read_cpuid(SYS_ID_ISAR4_EL1);
+	case SYS_ID_ISAR5_EL1:		return read_cpuid(SYS_ID_ISAR4_EL1);
+	case SYS_MVFR0_EL1:		return read_cpuid(SYS_MVFR0_EL1);
+	case SYS_MVFR1_EL1:		return read_cpuid(SYS_MVFR1_EL1);
+	case SYS_MVFR2_EL1:		return read_cpuid(SYS_MVFR2_EL1);
 
-	case SYS_ID_AA64PFR0_EL1:	return (u64)read_cpuid(ID_AA64PFR0_EL1);
-	case SYS_ID_AA64PFR1_EL1:	return (u64)read_cpuid(ID_AA64PFR0_EL1);
-	case SYS_ID_AA64DFR0_EL1:	return (u64)read_cpuid(ID_AA64DFR0_EL1);
-	case SYS_ID_AA64DFR1_EL1:	return (u64)read_cpuid(ID_AA64DFR0_EL1);
-	case SYS_ID_AA64MMFR0_EL1:	return (u64)read_cpuid(ID_AA64MMFR0_EL1);
-	case SYS_ID_AA64MMFR1_EL1:	return (u64)read_cpuid(ID_AA64MMFR1_EL1);
-	case SYS_ID_AA64ISAR0_EL1:	return (u64)read_cpuid(ID_AA64ISAR0_EL1);
-	case SYS_ID_AA64ISAR1_EL1:	return (u64)read_cpuid(ID_AA64ISAR1_EL1);
+	case SYS_ID_AA64PFR0_EL1:	return read_cpuid(SYS_ID_AA64PFR0_EL1);
+	case SYS_ID_AA64PFR1_EL1:	return read_cpuid(SYS_ID_AA64PFR0_EL1);
+	case SYS_ID_AA64DFR0_EL1:	return read_cpuid(SYS_ID_AA64DFR0_EL1);
+	case SYS_ID_AA64DFR1_EL1:	return read_cpuid(SYS_ID_AA64DFR0_EL1);
+	case SYS_ID_AA64MMFR0_EL1:	return read_cpuid(SYS_ID_AA64MMFR0_EL1);
+	case SYS_ID_AA64MMFR1_EL1:	return read_cpuid(SYS_ID_AA64MMFR1_EL1);
+	case SYS_ID_AA64MMFR2_EL1:	return read_cpuid(SYS_ID_AA64MMFR2_EL1);
+	case SYS_ID_AA64ISAR0_EL1:	return read_cpuid(SYS_ID_AA64ISAR0_EL1);
+	case SYS_ID_AA64ISAR1_EL1:	return read_cpuid(SYS_ID_AA64ISAR1_EL1);
 
-	case SYS_CNTFRQ_EL0:		return (u64)read_cpuid(CNTFRQ_EL0);
-	case SYS_CTR_EL0:		return (u64)read_cpuid(CTR_EL0);
-	case SYS_DCZID_EL0:		return (u64)read_cpuid(DCZID_EL0);
+	case SYS_CNTFRQ_EL0:		return read_cpuid(SYS_CNTFRQ_EL0);
+	case SYS_CTR_EL0:		return read_cpuid(SYS_CTR_EL0);
+	case SYS_DCZID_EL0:		return read_cpuid(SYS_DCZID_EL0);
 	default:
 		BUG();
 		return 0;
@@ -868,7 +926,7 @@
 		return;
 
 	caps = arm64_features;
-	for (i = 0; caps[i].desc; i++) {
+	for (i = 0; caps[i].matches; i++) {
 		if (!cpus_have_cap(caps[i].capability) || !caps[i].sys_reg)
 			continue;
 		/*
@@ -881,7 +939,7 @@
 			caps[i].enable(NULL);
 	}
 
-	for (i = 0, caps = arm64_hwcaps; caps[i].desc; i++) {
+	for (i = 0, caps = arm64_hwcaps; caps[i].matches; i++) {
 		if (!cpus_have_hwcap(&caps[i]))
 			continue;
 		if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i]))
@@ -897,7 +955,7 @@
 
 #endif	/* CONFIG_HOTPLUG_CPU */
 
-static void setup_feature_capabilities(void)
+static void __init setup_feature_capabilities(void)
 {
 	update_cpu_capabilities(arm64_features, "detected feature:");
 	enable_cpu_capabilities(arm64_features);
@@ -927,3 +985,9 @@
 		pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n",
 			L1_CACHE_BYTES, cls);
 }
+
+static bool __maybe_unused
+cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry)
+{
+	return (cpus_have_cap(ARM64_HAS_PAN) && !cpus_have_cap(ARM64_HAS_UAO));
+}
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 212ae63..95a6fae 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -22,6 +22,8 @@
 
 #include <linux/bitops.h>
 #include <linux/bug.h>
+#include <linux/compat.h>
+#include <linux/elf.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/personality.h>
@@ -85,7 +87,8 @@
 	"idivt",
 	"vfpd32",
 	"lpae",
-	"evtstrm"
+	"evtstrm",
+	NULL
 };
 
 static const char *const compat_hwcap2_str[] = {
@@ -101,6 +104,7 @@
 static int c_show(struct seq_file *m, void *v)
 {
 	int i, j;
+	bool compat = personality(current->personality) == PER_LINUX32;
 
 	for_each_online_cpu(i) {
 		struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
@@ -112,6 +116,9 @@
 		 * "processor".  Give glibc what it expects.
 		 */
 		seq_printf(m, "processor\t: %d\n", i);
+		if (compat)
+			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
+				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
 
 		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
 			   loops_per_jiffy / (500000UL/HZ),
@@ -124,7 +131,7 @@
 		 * software which does already (at least for 32-bit).
 		 */
 		seq_puts(m, "Features\t:");
-		if (personality(current->personality) == PER_LINUX32) {
+		if (compat) {
 #ifdef CONFIG_COMPAT
 			for (j = 0; compat_hwcap_str[j]; j++)
 				if (compat_elf_hwcap & (1 << j))
@@ -201,35 +208,36 @@
 {
 	info->reg_cntfrq = arch_timer_get_cntfrq();
 	info->reg_ctr = read_cpuid_cachetype();
-	info->reg_dczid = read_cpuid(DCZID_EL0);
+	info->reg_dczid = read_cpuid(SYS_DCZID_EL0);
 	info->reg_midr = read_cpuid_id();
 
-	info->reg_id_aa64dfr0 = read_cpuid(ID_AA64DFR0_EL1);
-	info->reg_id_aa64dfr1 = read_cpuid(ID_AA64DFR1_EL1);
-	info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1);
-	info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1);
-	info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
-	info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
-	info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
-	info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
+	info->reg_id_aa64dfr0 = read_cpuid(SYS_ID_AA64DFR0_EL1);
+	info->reg_id_aa64dfr1 = read_cpuid(SYS_ID_AA64DFR1_EL1);
+	info->reg_id_aa64isar0 = read_cpuid(SYS_ID_AA64ISAR0_EL1);
+	info->reg_id_aa64isar1 = read_cpuid(SYS_ID_AA64ISAR1_EL1);
+	info->reg_id_aa64mmfr0 = read_cpuid(SYS_ID_AA64MMFR0_EL1);
+	info->reg_id_aa64mmfr1 = read_cpuid(SYS_ID_AA64MMFR1_EL1);
+	info->reg_id_aa64mmfr2 = read_cpuid(SYS_ID_AA64MMFR2_EL1);
+	info->reg_id_aa64pfr0 = read_cpuid(SYS_ID_AA64PFR0_EL1);
+	info->reg_id_aa64pfr1 = read_cpuid(SYS_ID_AA64PFR1_EL1);
 
-	info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
-	info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
-	info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
-	info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
-	info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
-	info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
-	info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
-	info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
-	info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
-	info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
-	info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
-	info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
-	info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
+	info->reg_id_dfr0 = read_cpuid(SYS_ID_DFR0_EL1);
+	info->reg_id_isar0 = read_cpuid(SYS_ID_ISAR0_EL1);
+	info->reg_id_isar1 = read_cpuid(SYS_ID_ISAR1_EL1);
+	info->reg_id_isar2 = read_cpuid(SYS_ID_ISAR2_EL1);
+	info->reg_id_isar3 = read_cpuid(SYS_ID_ISAR3_EL1);
+	info->reg_id_isar4 = read_cpuid(SYS_ID_ISAR4_EL1);
+	info->reg_id_isar5 = read_cpuid(SYS_ID_ISAR5_EL1);
+	info->reg_id_mmfr0 = read_cpuid(SYS_ID_MMFR0_EL1);
+	info->reg_id_mmfr1 = read_cpuid(SYS_ID_MMFR1_EL1);
+	info->reg_id_mmfr2 = read_cpuid(SYS_ID_MMFR2_EL1);
+	info->reg_id_mmfr3 = read_cpuid(SYS_ID_MMFR3_EL1);
+	info->reg_id_pfr0 = read_cpuid(SYS_ID_PFR0_EL1);
+	info->reg_id_pfr1 = read_cpuid(SYS_ID_PFR1_EL1);
 
-	info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
-	info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
-	info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
+	info->reg_mvfr0 = read_cpuid(SYS_MVFR0_EL1);
+	info->reg_mvfr1 = read_cpuid(SYS_MVFR1_EL1);
+	info->reg_mvfr2 = read_cpuid(SYS_MVFR2_EL1);
 
 	cpuinfo_detect_icache_policy(info);
 
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index c1492ba..c8875b6 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -152,7 +152,6 @@
 	/* Clear the OS lock. */
 	on_each_cpu(clear_os_lock, NULL, 1);
 	isb();
-	local_dbg_enable();
 
 	/* Register hotplug handler. */
 	__register_cpu_notifier(&os_lock_nb);
@@ -423,8 +422,10 @@
 /* ptrace API */
 void user_enable_single_step(struct task_struct *task)
 {
-	set_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP);
-	set_regs_spsr_ss(task_pt_regs(task));
+	struct thread_info *ti = task_thread_info(task);
+
+	if (!test_and_set_ti_thread_flag(ti, TIF_SINGLESTEP))
+		set_regs_spsr_ss(task_pt_regs(task));
 }
 
 void user_disable_single_step(struct task_struct *task)
diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
index a773db9..f82036e 100644
--- a/arch/arm64/kernel/efi-entry.S
+++ b/arch/arm64/kernel/efi-entry.S
@@ -61,7 +61,7 @@
 	 */
 	mov	x20, x0		// DTB address
 	ldr	x0, [sp, #16]	// relocated _text address
-	ldr	x21, =stext_offset
+	movz	x21, #:abs_g0:stext_offset
 	add	x21, x0, x21
 
 	/*
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 4eeb171..b6abc85 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -11,317 +11,34 @@
  *
  */
 
-#include <linux/atomic.h>
 #include <linux/dmi.h>
 #include <linux/efi.h>
-#include <linux/export.h>
-#include <linux/memblock.h>
-#include <linux/mm_types.h>
-#include <linux/bootmem.h>
-#include <linux/of.h>
-#include <linux/of_fdt.h>
-#include <linux/preempt.h>
-#include <linux/rbtree.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
+#include <linux/init.h>
 
-#include <asm/cacheflush.h>
 #include <asm/efi.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu_context.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
 
-struct efi_memory_map memmap;
-
-static u64 efi_system_table;
-
-static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
-
-static struct mm_struct efi_mm = {
-	.mm_rb			= RB_ROOT,
-	.pgd			= efi_pgd,
-	.mm_users		= ATOMIC_INIT(2),
-	.mm_count		= ATOMIC_INIT(1),
-	.mmap_sem		= __RWSEM_INITIALIZER(efi_mm.mmap_sem),
-	.page_table_lock	= __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
-	.mmlist			= LIST_HEAD_INIT(efi_mm.mmlist),
-};
-
-static int __init is_normal_ram(efi_memory_desc_t *md)
+int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
 {
-	if (md->attribute & EFI_MEMORY_WB)
-		return 1;
-	return 0;
-}
-
-/*
- * Translate a EFI virtual address into a physical address: this is necessary,
- * as some data members of the EFI system table are virtually remapped after
- * SetVirtualAddressMap() has been called.
- */
-static phys_addr_t efi_to_phys(unsigned long addr)
-{
-	efi_memory_desc_t *md;
-
-	for_each_efi_memory_desc(&memmap, md) {
-		if (!(md->attribute & EFI_MEMORY_RUNTIME))
-			continue;
-		if (md->virt_addr == 0)
-			/* no virtual mapping has been installed by the stub */
-			break;
-		if (md->virt_addr <= addr &&
-		    (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT))
-			return md->phys_addr + addr - md->virt_addr;
-	}
-	return addr;
-}
-
-static int __init uefi_init(void)
-{
-	efi_char16_t *c16;
-	void *config_tables;
-	u64 table_size;
-	char vendor[100] = "unknown";
-	int i, retval;
-
-	efi.systab = early_memremap(efi_system_table,
-				    sizeof(efi_system_table_t));
-	if (efi.systab == NULL) {
-		pr_warn("Unable to map EFI system table.\n");
-		return -ENOMEM;
-	}
-
-	set_bit(EFI_BOOT, &efi.flags);
-	set_bit(EFI_64BIT, &efi.flags);
+	pteval_t prot_val;
 
 	/*
-	 * Verify the EFI Table
+	 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
+	 * executable, everything else can be mapped with the XN bits
+	 * set.
 	 */
-	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
-		pr_err("System table signature incorrect\n");
-		retval = -EINVAL;
-		goto out;
-	}
-	if ((efi.systab->hdr.revision >> 16) < 2)
-		pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
-			efi.systab->hdr.revision >> 16,
-			efi.systab->hdr.revision & 0xffff);
+	if ((md->attribute & EFI_MEMORY_WB) == 0)
+		prot_val = PROT_DEVICE_nGnRE;
+	else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
+		 !PAGE_ALIGNED(md->phys_addr))
+		prot_val = pgprot_val(PAGE_KERNEL_EXEC);
+	else
+		prot_val = pgprot_val(PAGE_KERNEL);
 
-	/* Show what we know for posterity */
-	c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
-			     sizeof(vendor) * sizeof(efi_char16_t));
-	if (c16) {
-		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
-			vendor[i] = c16[i];
-		vendor[i] = '\0';
-		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
-	}
-
-	pr_info("EFI v%u.%.02u by %s\n",
-		efi.systab->hdr.revision >> 16,
-		efi.systab->hdr.revision & 0xffff, vendor);
-
-	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
-	config_tables = early_memremap(efi_to_phys(efi.systab->tables),
-				       table_size);
-	if (config_tables == NULL) {
-		pr_warn("Unable to map EFI config table array.\n");
-		retval = -ENOMEM;
-		goto out;
-	}
-	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
-					 sizeof(efi_config_table_64_t), NULL);
-
-	early_memunmap(config_tables, table_size);
-out:
-	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
-	return retval;
-}
-
-/*
- * Return true for RAM regions we want to permanently reserve.
- */
-static __init int is_reserve_region(efi_memory_desc_t *md)
-{
-	switch (md->type) {
-	case EFI_LOADER_CODE:
-	case EFI_LOADER_DATA:
-	case EFI_BOOT_SERVICES_CODE:
-	case EFI_BOOT_SERVICES_DATA:
-	case EFI_CONVENTIONAL_MEMORY:
-	case EFI_PERSISTENT_MEMORY:
-		return 0;
-	default:
-		break;
-	}
-	return is_normal_ram(md);
-}
-
-static __init void reserve_regions(void)
-{
-	efi_memory_desc_t *md;
-	u64 paddr, npages, size;
-
-	if (efi_enabled(EFI_DBG))
-		pr_info("Processing EFI memory map:\n");
-
-	for_each_efi_memory_desc(&memmap, md) {
-		paddr = md->phys_addr;
-		npages = md->num_pages;
-
-		if (efi_enabled(EFI_DBG)) {
-			char buf[64];
-
-			pr_info("  0x%012llx-0x%012llx %s",
-				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
-				efi_md_typeattr_format(buf, sizeof(buf), md));
-		}
-
-		memrange_efi_to_native(&paddr, &npages);
-		size = npages << PAGE_SHIFT;
-
-		if (is_normal_ram(md))
-			early_init_dt_add_memory_arch(paddr, size);
-
-		if (is_reserve_region(md)) {
-			memblock_reserve(paddr, size);
-			if (efi_enabled(EFI_DBG))
-				pr_cont("*");
-		}
-
-		if (efi_enabled(EFI_DBG))
-			pr_cont("\n");
-	}
-
-	set_bit(EFI_MEMMAP, &efi.flags);
-}
-
-void __init efi_init(void)
-{
-	struct efi_fdt_params params;
-
-	/* Grab UEFI information placed in FDT by stub */
-	if (!efi_get_fdt_params(&params))
-		return;
-
-	efi_system_table = params.system_table;
-
-	memblock_reserve(params.mmap & PAGE_MASK,
-			 PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
-	memmap.phys_map = params.mmap;
-	memmap.map = early_memremap(params.mmap, params.mmap_size);
-	if (memmap.map == NULL) {
-		/*
-		* If we are booting via UEFI, the UEFI memory map is the only
-		* description of memory we have, so there is little point in
-		* proceeding if we cannot access it.
-		*/
-		panic("Unable to map EFI memory map.\n");
-	}
-	memmap.map_end = memmap.map + params.mmap_size;
-	memmap.desc_size = params.desc_size;
-	memmap.desc_version = params.desc_ver;
-
-	if (uefi_init() < 0)
-		return;
-
-	reserve_regions();
-	early_memunmap(memmap.map, params.mmap_size);
-}
-
-static bool __init efi_virtmap_init(void)
-{
-	efi_memory_desc_t *md;
-
-	init_new_context(NULL, &efi_mm);
-
-	for_each_efi_memory_desc(&memmap, md) {
-		pgprot_t prot;
-
-		if (!(md->attribute & EFI_MEMORY_RUNTIME))
-			continue;
-		if (md->virt_addr == 0)
-			return false;
-
-		pr_info("  EFI remap 0x%016llx => %p\n",
-			md->phys_addr, (void *)md->virt_addr);
-
-		/*
-		 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
-		 * executable, everything else can be mapped with the XN bits
-		 * set.
-		 */
-		if (!is_normal_ram(md))
-			prot = __pgprot(PROT_DEVICE_nGnRE);
-		else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
-			 !PAGE_ALIGNED(md->phys_addr))
-			prot = PAGE_KERNEL_EXEC;
-		else
-			prot = PAGE_KERNEL;
-
-		create_pgd_mapping(&efi_mm, md->phys_addr, md->virt_addr,
-				   md->num_pages << EFI_PAGE_SHIFT, 
-				   __pgprot(pgprot_val(prot) | PTE_NG));
-	}
-	return true;
-}
-
-/*
- * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
- * non-early mapping of the UEFI system table and virtual mappings for all
- * EFI_MEMORY_RUNTIME regions.
- */
-static int __init arm64_enable_runtime_services(void)
-{
-	u64 mapsize;
-
-	if (!efi_enabled(EFI_BOOT)) {
-		pr_info("EFI services will not be available.\n");
-		return 0;
-	}
-
-	if (efi_runtime_disabled()) {
-		pr_info("EFI runtime services will be disabled.\n");
-		return 0;
-	}
-
-	pr_info("Remapping and enabling EFI services.\n");
-
-	mapsize = memmap.map_end - memmap.map;
-	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
-						   mapsize);
-	if (!memmap.map) {
-		pr_err("Failed to remap EFI memory map\n");
-		return -ENOMEM;
-	}
-	memmap.map_end = memmap.map + mapsize;
-	efi.memmap = &memmap;
-
-	efi.systab = (__force void *)ioremap_cache(efi_system_table,
-						   sizeof(efi_system_table_t));
-	if (!efi.systab) {
-		pr_err("Failed to remap EFI System Table\n");
-		return -ENOMEM;
-	}
-	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
-
-	if (!efi_virtmap_init()) {
-		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
-		return -ENOMEM;
-	}
-
-	/* Set up runtime services function pointers */
-	efi_native_runtime_setup();
-	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-
-	efi.runtime_version = efi.systab->hdr.revision;
-
+	create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
+			   md->num_pages << EFI_PAGE_SHIFT,
+			   __pgprot(prot_val | PTE_NG));
 	return 0;
 }
-early_initcall(arm64_enable_runtime_services);
 
 static int __init arm64_dmi_init(void)
 {
@@ -337,23 +54,6 @@
 }
 core_initcall(arm64_dmi_init);
 
-static void efi_set_pgd(struct mm_struct *mm)
-{
-	switch_mm(NULL, mm, NULL);
-}
-
-void efi_virtmap_load(void)
-{
-	preempt_disable();
-	efi_set_pgd(&efi_mm);
-}
-
-void efi_virtmap_unload(void)
-{
-	efi_set_pgd(current->active_mm);
-	preempt_enable();
-}
-
 /*
  * UpdateCapsule() depends on the system being shutdown via
  * ResetSystem().
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 7ed3d75..3f9d786 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -27,7 +27,12 @@
 #include <asm/cpufeature.h>
 #include <asm/errno.h>
 #include <asm/esr.h>
+#include <asm/irq.h>
+#include <asm/memory.h>
+#include <asm/ptrace.h>
 #include <asm/thread_info.h>
+#include <asm/uaccess.h>
+#include <asm/asm-uaccess.h>
 #include <asm/unistd.h>
 
 /*
@@ -88,15 +93,51 @@
 
 	.if	\el == 0
 	mrs	x21, sp_el0
-	get_thread_info tsk			// Ensure MDSCR_EL1.SS is clear,
+	mov	tsk, sp
+	and	tsk, tsk, #~(THREAD_SIZE - 1)	// Ensure MDSCR_EL1.SS is clear,
 	ldr	x19, [tsk, #TI_FLAGS]		// since we can unmask debug
 	disable_step_tsk x19, x20		// exceptions when scheduling.
+
+	mov	x29, xzr			// fp pointed to user-space
 	.else
 	add	x21, sp, #S_FRAME_SIZE
-	.endif
+	get_thread_info tsk
+	/* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
+	ldr	x20, [tsk, #TI_ADDR_LIMIT]
+	str	x20, [sp, #S_ORIG_ADDR_LIMIT]
+	mov	x20, #TASK_SIZE_64
+	str	x20, [tsk, #TI_ADDR_LIMIT]
+	ALTERNATIVE(nop, SET_PSTATE_UAO(0), ARM64_HAS_UAO, CONFIG_ARM64_UAO)
+	.endif /* \el == 0 */
 	mrs	x22, elr_el1
 	mrs	x23, spsr_el1
 	stp	lr, x21, [sp, #S_LR]
+
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	/*
+	 * Set the TTBR0 PAN bit in SPSR. When the exception is taken from
+	 * EL0, there is no need to check the state of TTBR0_EL1 since
+	 * accesses are always enabled.
+	 * Note that the meaning of this bit differs from the ARMv8.1 PAN
+	 * feature as all TTBR0_EL1 accesses are disabled, not just those to
+	 * user mappings.
+	 */
+alternative_if ARM64_HAS_PAN
+	b	1f				// skip TTBR0 PAN
+alternative_else_nop_endif
+
+	.if	\el != 0
+	mrs	x21, ttbr0_el1
+	tst	x21, #0xffff << 48		// Check for the reserved ASID
+	orr	x23, x23, #PSR_PAN_BIT		// Set the emulated PAN in the saved SPSR
+	b.eq	1f				// TTBR0 access already disabled
+	and	x23, x23, #~PSR_PAN_BIT		// Clear the emulated PAN in the saved SPSR
+	.endif
+
+	__uaccess_ttbr0_disable x21
+1:
+#endif
+
 	stp	x22, x23, [sp, #S_PC]
 
 	/*
@@ -108,6 +149,13 @@
 	.endif
 
 	/*
+	 * Set sp_el0 to current thread_info.
+	 */
+	.if	\el == 0
+	msr	sp_el0, tsk
+	.endif
+
+	/*
 	 * Registers that may be useful after this macro is invoked:
 	 *
 	 * x21 - aborted SP
@@ -117,9 +165,51 @@
 	.endm
 
 	.macro	kernel_exit, el
+	.if	\el != 0
+	/* Restore the task's original addr_limit. */
+	ldr	x20, [sp, #S_ORIG_ADDR_LIMIT]
+	str	x20, [tsk, #TI_ADDR_LIMIT]
+
+	/* No need to restore UAO, it will be restored from SPSR_EL1 */
+	.endif
+
 	ldp	x21, x22, [sp, #S_PC]		// load ELR, SPSR
 	.if	\el == 0
 	ct_user_enter
+	.endif
+
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	/*
+	 * Restore access to TTBR0_EL1. If returning to EL0, no need for SPSR
+	 * PAN bit checking.
+	 */
+alternative_if ARM64_HAS_PAN
+	b	2f				// skip TTBR0 PAN
+alternative_else_nop_endif
+
+	.if	\el != 0
+	tbnz	x22, #22, 1f			// Skip re-enabling TTBR0 access if the PSR_PAN_BIT is set
+	.endif
+
+	__uaccess_ttbr0_enable x0
+
+	.if	\el == 0
+	/*
+	 * Enable errata workarounds only if returning to user. The only
+	 * workaround currently required for TTBR0_EL1 changes are for the
+	 * Cavium erratum 27456 (broadcast TLBI instructions may cause I-cache
+	 * corruption).
+	 */
+	post_ttbr0_update_workaround
+	.endif
+1:
+	.if	\el != 0
+	and	x22, x22, #~PSR_PAN_BIT		// ARMv8.0 CPUs do not understand this bit
+	.endif
+2:
+#endif
+
+	.if	\el == 0
 	ldr	x23, [sp, #S_SP]		// load return stack pointer
 	msr	sp_el0, x23
 #ifdef CONFIG_ARM64_ERRATUM_845719
@@ -141,6 +231,7 @@
 alternative_endif
 #endif
 	.endif
+
 	msr	elr_el1, x21			// set up the return data
 	msr	spsr_el1, x22
 	ldp	x0, x1, [sp, #16 * 0]
@@ -163,9 +254,41 @@
 	eret					// return to kernel
 	.endm
 
-	.macro	get_thread_info, rd
-	mov	\rd, sp
-	and	\rd, \rd, #~(THREAD_SIZE - 1)	// top of stack
+	.macro	irq_stack_entry
+	mov	x19, sp			// preserve the original sp
+
+	/*
+	 * Compare sp with the current thread_info, if the top
+	 * ~(THREAD_SIZE - 1) bits match, we are on a task stack, and
+	 * should switch to the irq stack.
+	 */
+	and	x25, x19, #~(THREAD_SIZE - 1)
+	cmp	x25, tsk
+	b.ne	9998f
+
+	this_cpu_ptr irq_stack, x25, x26
+	mov	x26, #IRQ_STACK_START_SP
+	add	x26, x25, x26
+
+	/* switch to the irq stack */
+	mov	sp, x26
+
+	/*
+	 * Add a dummy stack frame, this non-standard format is fixed up
+	 * by unwind_frame()
+	 */
+	stp     x29, x19, [sp, #-16]!
+	mov	x29, sp
+
+9998:
+	.endm
+
+	/*
+	 * x19 should be preserved between irq_stack_entry and
+	 * irq_stack_exit.
+	 */
+	.macro	irq_stack_exit
+	mov	sp, x19
 	.endm
 
 /*
@@ -183,10 +306,11 @@
  * Interrupt handling.
  */
 	.macro	irq_handler
-	adrp	x1, handle_arch_irq
-	ldr	x1, [x1, #:lo12:handle_arch_irq]
+	ldr_l	x1, handle_arch_irq
 	mov	x0, sp
+	irq_stack_entry
 	blr	x1
+	irq_stack_exit
 	.endm
 
 	.text
@@ -229,7 +353,7 @@
  * Invalid mode handlers
  */
 	.macro	inv_entry, el, reason, regsize = 64
-	kernel_entry el, \regsize
+	kernel_entry \el, \regsize
 	mov	x0, sp
 	mov	x1, #\reason
 	mrs	x2, esr_el1
@@ -288,6 +412,8 @@
 	lsr	x24, x1, #ESR_ELx_EC_SHIFT	// exception class
 	cmp	x24, #ESR_ELx_EC_DABT_CUR	// data abort in EL1
 	b.eq	el1_da
+	cmp	x24, #ESR_ELx_EC_IABT_CUR	// instruction abort in EL1
+	b.eq	el1_ia
 	cmp	x24, #ESR_ELx_EC_SYS64		// configurable trap
 	b.eq	el1_undef
 	cmp	x24, #ESR_ELx_EC_SP_ALIGN	// stack alignment exception
@@ -299,16 +425,22 @@
 	cmp	x24, #ESR_ELx_EC_BREAKPT_CUR	// debug exception in EL1
 	b.ge	el1_dbg
 	b	el1_inv
+
+el1_ia:
+	/*
+	 * Fall through to the Data abort case
+	 */
 el1_da:
 	/*
 	 * Data abort handling
 	 */
-	mrs	x0, far_el1
+	mrs	x3, far_el1
 	enable_dbg
 	// re-enable interrupts if they were enabled in the aborted context
 	tbnz	x23, #7, 1f			// PSR_I_BIT
 	enable_irq
 1:
+	clear_address_tag x0, x3
 	mov	x2, sp				// struct pt_regs
 	bl	do_mem_abort
 
@@ -361,7 +493,6 @@
 	irq_handler
 
 #ifdef CONFIG_PREEMPT
-	get_thread_info tsk
 	ldr	w24, [tsk, #TI_PREEMPT]		// get preempt count
 	cbnz	w24, 1f				// preempt count != 0
 	ldr	x0, [tsk, #TI_FLAGS]		// get flags
@@ -470,7 +601,7 @@
 	// enable interrupts before calling the main handler
 	enable_dbg_and_irq
 	ct_user_exit
-	bic	x0, x26, #(0xff << 56)
+	clear_address_tag x0, x26
 	mov	x1, x25
 	mov	x2, sp
 	bl	do_mem_abort
@@ -484,7 +615,7 @@
 	enable_dbg_and_irq
 	ct_user_exit
 	mov	x0, x26
-	orr	x1, x25, #1 << 24		// use reserved ISS bit for instruction aborts
+	mov	x1, x25
 	mov	x2, sp
 	bl	do_mem_abort
 	b	ret_to_user
@@ -549,7 +680,7 @@
 	mov	x0, sp
 	mov	x1, #BAD_SYNC
 	mov	x2, x25
-	bl	bad_mode
+	bl	bad_el0_sync
 	b	ret_to_user
 ENDPROC(el0_sync)
 
@@ -599,6 +730,8 @@
 	ldp	x29, x9, [x8], #16
 	ldr	lr, [x8]
 	mov	sp, x9
+	and	x9, x9, #~(THREAD_SIZE - 1)
+	msr	sp_el0, x9
 	ret
 ENDPROC(cpu_switch_to)
 
@@ -626,14 +759,14 @@
 work_pending:
 	tbnz	x1, #TIF_NEED_RESCHED, work_resched
 	/* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */
-	ldr	x2, [sp, #S_PSTATE]
 	mov	x0, sp				// 'regs'
-	tst	x2, #PSR_MODE_MASK		// user mode regs?
-	b.ne	no_work_pending			// returning to kernel
 	enable_irq				// enable interrupts for do_notify_resume()
 	bl	do_notify_resume
 	b	ret_to_user
 work_resched:
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off		// the IRQs are off here, inform the tracing code
+#endif
 	bl	schedule
 
 /*
@@ -645,7 +778,6 @@
 	and	x2, x1, #_TIF_WORK_MASK
 	cbnz	x2, work_pending
 	enable_step_tsk x1, x2
-no_work_pending:
 	kernel_exit 0
 ENDPROC(ret_to_user)
 
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 4c46c54..acc1afd 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -289,7 +289,7 @@
 	.notifier_call = fpsimd_cpu_pm_notifier,
 };
 
-static void fpsimd_pm_init(void)
+static void __init fpsimd_pm_init(void)
 {
 	cpu_pm_register_notifier(&fpsimd_cpu_pm_notifier_block);
 }
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index c851be7..ebecf9a 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -29,12 +29,11 @@
 
 	/*
 	 * Note:
-	 * Due to modules and __init, code can disappear and change,
-	 * we need to protect against faulting as well as code changing.
-	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
-	 *
-	 * No lock is held here because all the modifications are run
-	 * through stop_machine().
+	 * We are paranoid about modifying text, as if a bug were to happen, it
+	 * could cause us to read or write to someplace that could cause harm.
+	 * Carefully read and modify the code with aarch64_insn_*() which uses
+	 * probe_kernel_*(), and make sure what we read is what we expected it
+	 * to be before modifying it.
 	 */
 	if (validate) {
 		if (aarch64_insn_read((void *)pc, &replaced))
@@ -93,6 +92,11 @@
 	return ftrace_modify_code(pc, old, new, true);
 }
 
+void arch_ftrace_update_code(int command)
+{
+	ftrace_modify_all_code(command);
+}
+
 int __init ftrace_dyn_arch_init(void)
 {
 	return 0;
@@ -125,23 +129,20 @@
 	 * on other archs. It's unlikely on AArch64.
 	 */
 	old = *parent;
-	*parent = return_hooker;
 
 	trace.func = self_addr;
 	trace.depth = current->curr_ret_stack + 1;
 
 	/* Only trace if the calling function expects to */
-	if (!ftrace_graph_entry(&trace)) {
-		*parent = old;
+	if (!ftrace_graph_entry(&trace))
 		return;
-	}
 
 	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
 				       frame_pointer);
-	if (err == -EBUSY) {
-		*parent = old;
+	if (err == -EBUSY)
 		return;
-	}
+	else
+		*parent = return_hooker;
 }
 
 #ifdef CONFIG_DYNAMIC_FTRACE
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index b685257..9971039 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -25,10 +25,12 @@
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/assembler.h>
+#include <asm/boot.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
 #include <asm/cputype.h>
+#include <asm/elf.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/memory.h>
 #include <asm/pgtable-hwdef.h>
@@ -67,12 +69,11 @@
  * in the entry routines.
  */
 	__HEAD
-
+_head:
 	/*
 	 * DO NOT MODIFY. Image header expected by Linux boot-loaders.
 	 */
 #ifdef CONFIG_EFI
-efi_head:
 	/*
 	 * This add instruction has no meaningful effect except that
 	 * its opcode forms the magic "MZ" signature required by UEFI.
@@ -83,9 +84,9 @@
 	b	stext				// branch to kernel start, magic
 	.long	0				// reserved
 #endif
-	.quad	_kernel_offset_le		// Image load offset from start of RAM, little-endian
-	.quad	_kernel_size_le			// Effective size of kernel image, little-endian
-	.quad	_kernel_flags_le		// Informative flags, little-endian
+	le64sym	_kernel_offset_le		// Image load offset from start of RAM, little-endian
+	le64sym	_kernel_size_le			// Effective size of kernel image, little-endian
+	le64sym	_kernel_flags_le		// Informative flags, little-endian
 	.quad	0				// reserved
 	.quad	0				// reserved
 	.quad	0				// reserved
@@ -94,14 +95,14 @@
 	.byte	0x4d
 	.byte	0x64
 #ifdef CONFIG_EFI
-	.long	pe_header - efi_head		// Offset to the PE header.
+	.long	pe_header - _head		// Offset to the PE header.
 #else
 	.word	0				// reserved
 #endif
 
 #ifdef CONFIG_EFI
 	.globl	__efistub_stext_offset
-	.set	__efistub_stext_offset, stext - efi_head
+	.set	__efistub_stext_offset, stext - _head
 	.align 3
 pe_header:
 	.ascii	"PE"
@@ -124,7 +125,7 @@
 	.long	_end - stext			// SizeOfCode
 	.long	0				// SizeOfInitializedData
 	.long	0				// SizeOfUninitializedData
-	.long	__efistub_entry - efi_head	// AddressOfEntryPoint
+	.long	__efistub_entry - _head		// AddressOfEntryPoint
 	.long	__efistub_stext_offset		// BaseOfCode
 
 extra_header_fields:
@@ -139,7 +140,7 @@
 	.short	0				// MinorSubsystemVersion
 	.long	0				// Win32VersionValue
 
-	.long	_end - efi_head			// SizeOfImage
+	.long	_end - _head			// SizeOfImage
 
 	// Everything before the kernel image is considered part of the header
 	.long	__efistub_stext_offset		// SizeOfHeaders
@@ -211,6 +212,7 @@
 	bl	preserve_boot_args
 	bl	el2_setup			// Drop to EL1, w20=cpu_boot_mode
 	adrp	x24, __PHYS_OFFSET
+	and	x23, x24, MIN_KIMG_ALIGN - 1	// KASLR offset, defaults to 0
 	bl	set_cpu_boot_mode_flag
 	bl	__create_page_tables		// x25=TTBR0, x26=TTBR1
 	/*
@@ -219,11 +221,13 @@
 	 * On return, the CPU will be ready for the MMU to be turned on and
 	 * the TCR will have been set.
 	 */
-	ldr	x27, =__mmap_switched		// address to jump to after
+	ldr	x27, 0f				// address to jump to after
 						// MMU has been enabled
 	adr_l	lr, __enable_mmu		// return (PIC) address
 	b	__cpu_setup			// initialise processor
 ENDPROC(stext)
+	.align	3
+0:	.quad	__mmap_switched - (_head - TEXT_OFFSET) + KIMAGE_VADDR
 
 /*
  * Preserve the arguments passed by the bootloader in x0 .. x3
@@ -311,21 +315,21 @@
 __create_page_tables:
 	adrp	x25, idmap_pg_dir
 	adrp	x26, swapper_pg_dir
-	mov	x27, lr
+	mov	x28, lr
 
 	/*
 	 * Invalidate the idmap and swapper page tables to avoid potential
 	 * dirty cache lines being evicted.
 	 */
 	mov	x0, x25
-	add	x1, x26, #SWAPPER_DIR_SIZE
+	add	x1, x26, #SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
 	bl	__inval_cache_range
 
 	/*
 	 * Clear the idmap and swapper page tables.
 	 */
 	mov	x0, x25
-	add	x6, x26, #SWAPPER_DIR_SIZE
+	add	x6, x26, #SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
 1:	stp	xzr, xzr, [x0], #16
 	stp	xzr, xzr, [x0], #16
 	stp	xzr, xzr, [x0], #16
@@ -389,9 +393,11 @@
 	 * Map the kernel image (starting with PHYS_OFFSET).
 	 */
 	mov	x0, x26				// swapper_pg_dir
-	mov	x5, #PAGE_OFFSET
+	ldr	x5, =KIMAGE_VADDR
+	add	x5, x5, x23			// add KASLR displacement
 	create_pgd_entry x0, x5, x3, x6
-	ldr	x6, =KERNEL_END			// __va(KERNEL_END)
+	ldr	w6, kernel_img_size
+	add	x6, x6, x5
 	mov	x3, x24				// phys offset
 	create_block_map x0, x7, x3, x5, x6
 
@@ -401,13 +407,15 @@
 	 * tables again to remove any speculatively loaded cache lines.
 	 */
 	mov	x0, x25
-	add	x1, x26, #SWAPPER_DIR_SIZE
+	add	x1, x26, #SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
 	dmb	sy
 	bl	__inval_cache_range
 
-	mov	lr, x27
-	ret
+	ret	x28
 ENDPROC(__create_page_tables)
+
+kernel_img_size:
+	.long	_end - (_head - TEXT_OFFSET)
 	.ltorg
 
 /*
@@ -415,21 +423,83 @@
  */
 	.set	initial_sp, init_thread_union + THREAD_START_SP
 __mmap_switched:
-	adr_l	x6, __bss_start
-	adr_l	x7, __bss_stop
+	mov	x28, lr				// preserve LR
+	adr_l	x8, vectors			// load VBAR_EL1 with virtual
+	msr	vbar_el1, x8			// vector table address
+	isb
 
-1:	cmp	x6, x7
+	// Clear BSS
+	adr_l	x0, __bss_start
+	mov	x1, xzr
+	adr_l	x2, __bss_stop
+	sub	x2, x2, x0
+	bl	__pi_memset
+	dsb	ishst				// Make zero page visible to PTW
+
+#ifdef CONFIG_RELOCATABLE
+
+	/*
+	 * Iterate over each entry in the relocation table, and apply the
+	 * relocations in place.
+	 */
+	adr_l	x8, __dynsym_start		// start of symbol table
+	adr_l	x9, __reloc_start		// start of reloc table
+	adr_l	x10, __reloc_end		// end of reloc table
+
+0:	cmp	x9, x10
 	b.hs	2f
-	str	xzr, [x6], #8			// Clear BSS
-	b	1b
-2:
+	ldp	x11, x12, [x9], #24
+	ldr	x13, [x9, #-8]
+	cmp	w12, #R_AARCH64_RELATIVE
+	b.ne	1f
+	add	x13, x13, x23			// relocate
+	str	x13, [x11, x23]
+	b	0b
+
+1:	cmp	w12, #R_AARCH64_ABS64
+	b.ne	0b
+	add	x12, x12, x12, lsl #1		// symtab offset: 24x top word
+	add	x12, x8, x12, lsr #(32 - 3)	// ... shifted into bottom word
+	ldrsh	w14, [x12, #6]			// Elf64_Sym::st_shndx
+	ldr	x15, [x12, #8]			// Elf64_Sym::st_value
+	cmp	w14, #-0xf			// SHN_ABS (0xfff1) ?
+	add	x14, x15, x23			// relocate
+	csel	x15, x14, x15, ne
+	add	x15, x13, x15
+	str	x15, [x11, x23]
+	b	0b
+
+2:	adr_l	x8, kimage_vaddr		// make relocated kimage_vaddr
+	dc	cvac, x8			// value visible to secondaries
+	dsb	sy				// with MMU off
+#endif
+
 	adr_l	sp, initial_sp, x4
+	mov	x4, sp
+	and	x4, x4, #~(THREAD_SIZE - 1)
+	msr	sp_el0, x4			// Save thread_info
 	str_l	x21, __fdt_pointer, x5		// Save FDT pointer
-	str_l	x24, memstart_addr, x6		// Save PHYS_OFFSET
+
+	ldr_l	x4, kimage_vaddr		// Save the offset between
+	sub	x4, x4, x24			// the kernel virtual and
+	str_l	x4, kimage_voffset, x5		// physical mappings
+
 	mov	x29, #0
 #ifdef CONFIG_KASAN
 	bl	kasan_early_init
 #endif
+#ifdef CONFIG_RANDOMIZE_BASE
+	tst	x23, ~(MIN_KIMG_ALIGN - 1)	// already running randomized?
+	b.ne	0f
+	mov	x0, x21				// pass FDT address in x0
+	mov	x1, x23				// pass modulo offset in x1
+	bl	kaslr_early_init		// parse FDT for KASLR options
+	cbz	x0, 0f				// KASLR disabled? just proceed
+	orr	x23, x23, x0			// record KASLR offset
+	ret	x28				// we must enable KASLR, return
+						// to __enable_mmu()
+0:
+#endif
 	b	start_kernel
 ENDPROC(__mmap_switched)
 
@@ -438,6 +508,10 @@
  * hotplug and needs to have the same protections as the text region
  */
 	.section ".text","ax"
+
+ENTRY(kimage_vaddr)
+	.quad		_text - TEXT_OFFSET
+
 /*
  * If we're fortunate enough to boot at EL2, ensure that the world is
  * sane before dropping to EL1.
@@ -518,8 +592,9 @@
 	b.lt	4f				// Skip if no PMU present
 	mrs	x0, pmcr_el0			// Disable debug access traps
 	ubfx	x0, x0, #11, #5			// to EL2 and allow access to
-	msr	mdcr_el2, x0			// all PMU counters from EL1
 4:
+	csel	x0, xzr, x0, lt			// all PMU counters from EL1
+	msr	mdcr_el2, x0			// (if they exist)
 
 	/* Stage-2 translation */
 	msr	vttbr_el2, xzr
@@ -603,14 +678,22 @@
 	adrp	x26, swapper_pg_dir
 	bl	__cpu_setup			// initialise processor
 
-	ldr	x21, =secondary_data
-	ldr	x27, =__secondary_switched	// address to jump to after enabling the MMU
+	ldr	x8, kimage_vaddr
+	ldr	w9, 0f
+	sub	x27, x8, w9, sxtw		// address to jump to after enabling the MMU
 	b	__enable_mmu
 ENDPROC(secondary_startup)
+0:	.long	(_text - TEXT_OFFSET) - __secondary_switched
 
 ENTRY(__secondary_switched)
-	ldr	x0, [x21]			// get secondary_data.stack
+	adr_l	x5, vectors
+	msr	vbar_el1, x5
+	isb
+
+	ldr_l	x0, secondary_data		// get secondary_data.stack
 	mov	sp, x0
+	and	x0, x0, #~(THREAD_SIZE - 1)
+	msr	sp_el0, x0			// save thread_info
 	mov	x29, #0
 	b	secondary_start_kernel
 ENDPROC(__secondary_switched)
@@ -628,12 +711,11 @@
  */
 	.section	".idmap.text", "ax"
 __enable_mmu:
+	mrs	x18, sctlr_el1			// preserve old SCTLR_EL1 value
 	mrs	x1, ID_AA64MMFR0_EL1
 	ubfx	x2, x1, #ID_AA64MMFR0_TGRAN_SHIFT, 4
 	cmp	x2, #ID_AA64MMFR0_TGRAN_SUPPORTED
 	b.ne	__no_granule_support
-	ldr	x5, =vectors
-	msr	vbar_el1, x5
 	msr	ttbr0_el1, x25			// load TTBR0
 	msr	ttbr1_el1, x26			// load TTBR1
 	isb
@@ -647,6 +729,29 @@
 	ic	iallu
 	dsb	nsh
 	isb
+#ifdef CONFIG_RANDOMIZE_BASE
+	mov	x19, x0				// preserve new SCTLR_EL1 value
+	blr	x27
+
+	/*
+	 * If we return here, we have a KASLR displacement in x23 which we need
+	 * to take into account by discarding the current kernel mapping and
+	 * creating a new one.
+	 */
+	msr	sctlr_el1, x18			// disable the MMU
+	isb
+	bl	__create_page_tables		// recreate kernel mapping
+
+	tlbi	vmalle1				// Remove any stale TLB entries
+	dsb	nsh
+
+	msr	sctlr_el1, x19			// re-enable the MMU
+	isb
+	ic	iallu				// flush instructions fetched
+	dsb	nsh				// via old mapping
+	isb
+	add	x27, x27, x23			// relocated __mmap_switched
+#endif
 	br	x27
 ENDPROC(__enable_mmu)
 
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index b45c95d..629c002 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -35,6 +35,7 @@
 #include <asm/traps.h>
 #include <asm/cputype.h>
 #include <asm/system_misc.h>
+#include <asm/uaccess.h>
 
 /* Breakpoint currently in use for each BRP. */
 static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
@@ -313,9 +314,21 @@
 	case ARM_BREAKPOINT_LEN_2:
 		len_in_bytes = 2;
 		break;
+	case ARM_BREAKPOINT_LEN_3:
+		len_in_bytes = 3;
+		break;
 	case ARM_BREAKPOINT_LEN_4:
 		len_in_bytes = 4;
 		break;
+	case ARM_BREAKPOINT_LEN_5:
+		len_in_bytes = 5;
+		break;
+	case ARM_BREAKPOINT_LEN_6:
+		len_in_bytes = 6;
+		break;
+	case ARM_BREAKPOINT_LEN_7:
+		len_in_bytes = 7;
+		break;
 	case ARM_BREAKPOINT_LEN_8:
 		len_in_bytes = 8;
 		break;
@@ -345,7 +358,7 @@
  * to generic breakpoint descriptions.
  */
 int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
-			   int *gen_len, int *gen_type)
+			   int *gen_len, int *gen_type, int *offset)
 {
 	/* Type */
 	switch (ctrl.type) {
@@ -365,17 +378,33 @@
 		return -EINVAL;
 	}
 
+	if (!ctrl.len)
+		return -EINVAL;
+	*offset = __ffs(ctrl.len);
+
 	/* Len */
-	switch (ctrl.len) {
+	switch (ctrl.len >> *offset) {
 	case ARM_BREAKPOINT_LEN_1:
 		*gen_len = HW_BREAKPOINT_LEN_1;
 		break;
 	case ARM_BREAKPOINT_LEN_2:
 		*gen_len = HW_BREAKPOINT_LEN_2;
 		break;
+	case ARM_BREAKPOINT_LEN_3:
+		*gen_len = HW_BREAKPOINT_LEN_3;
+		break;
 	case ARM_BREAKPOINT_LEN_4:
 		*gen_len = HW_BREAKPOINT_LEN_4;
 		break;
+	case ARM_BREAKPOINT_LEN_5:
+		*gen_len = HW_BREAKPOINT_LEN_5;
+		break;
+	case ARM_BREAKPOINT_LEN_6:
+		*gen_len = HW_BREAKPOINT_LEN_6;
+		break;
+	case ARM_BREAKPOINT_LEN_7:
+		*gen_len = HW_BREAKPOINT_LEN_7;
+		break;
 	case ARM_BREAKPOINT_LEN_8:
 		*gen_len = HW_BREAKPOINT_LEN_8;
 		break;
@@ -419,9 +448,21 @@
 	case HW_BREAKPOINT_LEN_2:
 		info->ctrl.len = ARM_BREAKPOINT_LEN_2;
 		break;
+	case HW_BREAKPOINT_LEN_3:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_3;
+		break;
 	case HW_BREAKPOINT_LEN_4:
 		info->ctrl.len = ARM_BREAKPOINT_LEN_4;
 		break;
+	case HW_BREAKPOINT_LEN_5:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_5;
+		break;
+	case HW_BREAKPOINT_LEN_6:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_6;
+		break;
+	case HW_BREAKPOINT_LEN_7:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_7;
+		break;
 	case HW_BREAKPOINT_LEN_8:
 		info->ctrl.len = ARM_BREAKPOINT_LEN_8;
 		break;
@@ -513,18 +554,17 @@
 		default:
 			return -EINVAL;
 		}
-
-		info->address &= ~alignment_mask;
-		info->ctrl.len <<= offset;
 	} else {
 		if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE)
 			alignment_mask = 0x3;
 		else
 			alignment_mask = 0x7;
-		if (info->address & alignment_mask)
-			return -EINVAL;
+		offset = info->address & alignment_mask;
 	}
 
+	info->address &= ~alignment_mask;
+	info->ctrl.len <<= offset;
+
 	/*
 	 * Disallow per-task kernel breakpoints since these would
 	 * complicate the stepping code.
@@ -655,12 +695,47 @@
 	return 0;
 }
 
+/*
+ * Arm64 hardware does not always report a watchpoint hit address that matches
+ * one of the watchpoints set. It can also report an address "near" the
+ * watchpoint if a single instruction access both watched and unwatched
+ * addresses. There is no straight-forward way, short of disassembling the
+ * offending instruction, to map that address back to the watchpoint. This
+ * function computes the distance of the memory access from the watchpoint as a
+ * heuristic for the likelyhood that a given access triggered the watchpoint.
+ *
+ * See Section D2.10.5 "Determining the memory location that caused a Watchpoint
+ * exception" of ARMv8 Architecture Reference Manual for details.
+ *
+ * The function returns the distance of the address from the bytes watched by
+ * the watchpoint. In case of an exact match, it returns 0.
+ */
+static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
+					struct arch_hw_breakpoint_ctrl *ctrl)
+{
+	u64 wp_low, wp_high;
+	u32 lens, lene;
+
+	lens = __ffs(ctrl->len);
+	lene = __fls(ctrl->len);
+
+	wp_low = val + lens;
+	wp_high = val + lene;
+	if (addr < wp_low)
+		return wp_low - addr;
+	else if (addr > wp_high)
+		return addr - wp_high;
+	else
+		return 0;
+}
+
 static int watchpoint_handler(unsigned long addr, unsigned int esr,
 			      struct pt_regs *regs)
 {
-	int i, step = 0, *kernel_step, access;
+	int i, step = 0, *kernel_step, access, closest_match = 0;
+	u64 min_dist = -1, dist;
 	u32 ctrl_reg;
-	u64 val, alignment_mask;
+	u64 val;
 	struct perf_event *wp, **slots;
 	struct debug_info *debug_info;
 	struct arch_hw_breakpoint *info;
@@ -669,35 +744,15 @@
 	slots = this_cpu_ptr(wp_on_reg);
 	debug_info = &current->thread.debug;
 
+	/*
+	 * Find all watchpoints that match the reported address. If no exact
+	 * match is found. Attribute the hit to the closest watchpoint.
+	 */
+	rcu_read_lock();
 	for (i = 0; i < core_num_wrps; ++i) {
-		rcu_read_lock();
-
 		wp = slots[i];
-
 		if (wp == NULL)
-			goto unlock;
-
-		info = counter_arch_bp(wp);
-		/* AArch32 watchpoints are either 4 or 8 bytes aligned. */
-		if (is_compat_task()) {
-			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
-				alignment_mask = 0x7;
-			else
-				alignment_mask = 0x3;
-		} else {
-			alignment_mask = 0x7;
-		}
-
-		/* Check if the watchpoint value matches. */
-		val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
-		if (val != (addr & ~alignment_mask))
-			goto unlock;
-
-		/* Possible match, check the byte address select to confirm. */
-		ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
-		decode_ctrl_reg(ctrl_reg, &ctrl);
-		if (!((1 << (addr & alignment_mask)) & ctrl.len))
-			goto unlock;
+			continue;
 
 		/*
 		 * Check that the access type matches.
@@ -706,18 +761,41 @@
 		access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W :
 			 HW_BREAKPOINT_R;
 		if (!(access & hw_breakpoint_type(wp)))
-			goto unlock;
+			continue;
 
+		/* Check if the watchpoint value and byte select match. */
+		val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
+		ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
+		decode_ctrl_reg(ctrl_reg, &ctrl);
+		dist = get_distance_from_watchpoint(addr, val, &ctrl);
+		if (dist < min_dist) {
+			min_dist = dist;
+			closest_match = i;
+		}
+		/* Is this an exact match? */
+		if (dist != 0)
+			continue;
+
+		info = counter_arch_bp(wp);
 		info->trigger = addr;
 		perf_bp_event(wp, regs);
 
 		/* Do we need to handle the stepping? */
 		if (!wp->overflow_handler)
 			step = 1;
-
-unlock:
-		rcu_read_unlock();
 	}
+	if (min_dist > 0 && min_dist != -1) {
+		/* No exact match found. */
+		wp = slots[closest_match];
+		info = counter_arch_bp(wp);
+		info->trigger = addr;
+		perf_bp_event(wp, regs);
+
+		/* Do we need to handle the stepping? */
+		if (!wp->overflow_handler)
+			step = 1;
+	}
+	rcu_read_unlock();
 
 	if (!step)
 		return 0;
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
index bc2abb8..db1bf57 100644
--- a/arch/arm64/kernel/image.h
+++ b/arch/arm64/kernel/image.h
@@ -26,31 +26,40 @@
  * There aren't any ELF relocations we can use to endian-swap values known only
  * at link time (e.g. the subtraction of two symbol addresses), so we must get
  * the linker to endian-swap certain values before emitting them.
+ *
+ * Note that, in order for this to work when building the ELF64 PIE executable
+ * (for KASLR), these values should not be referenced via R_AARCH64_ABS64
+ * relocations, since these are fixed up at runtime rather than at build time
+ * when PIE is in effect. So we need to split them up in 32-bit high and low
+ * words.
  */
 #ifdef CONFIG_CPU_BIG_ENDIAN
-#define DATA_LE64(data)					\
-	((((data) & 0x00000000000000ff) << 56) |	\
-	 (((data) & 0x000000000000ff00) << 40) |	\
-	 (((data) & 0x0000000000ff0000) << 24) |	\
-	 (((data) & 0x00000000ff000000) << 8)  |	\
-	 (((data) & 0x000000ff00000000) >> 8)  |	\
-	 (((data) & 0x0000ff0000000000) >> 24) |	\
-	 (((data) & 0x00ff000000000000) >> 40) |	\
-	 (((data) & 0xff00000000000000) >> 56))
+#define DATA_LE32(data)				\
+	((((data) & 0x000000ff) << 24) |	\
+	 (((data) & 0x0000ff00) << 8)  |	\
+	 (((data) & 0x00ff0000) >> 8)  |	\
+	 (((data) & 0xff000000) >> 24))
 #else
-#define DATA_LE64(data) ((data) & 0xffffffffffffffff)
+#define DATA_LE32(data) ((data) & 0xffffffff)
 #endif
 
+#define DEFINE_IMAGE_LE64(sym, data)				\
+	sym##_lo32 = DATA_LE32((data) & 0xffffffff);		\
+	sym##_hi32 = DATA_LE32((data) >> 32)
+
 #ifdef CONFIG_CPU_BIG_ENDIAN
-#define __HEAD_FLAG_BE	1
+#define __HEAD_FLAG_BE		1
 #else
-#define __HEAD_FLAG_BE	0
+#define __HEAD_FLAG_BE		0
 #endif
 
-#define __HEAD_FLAG_PAGE_SIZE ((PAGE_SHIFT - 10) / 2)
+#define __HEAD_FLAG_PAGE_SIZE	((PAGE_SHIFT - 10) / 2)
 
-#define __HEAD_FLAGS	((__HEAD_FLAG_BE << 0) |	\
-			 (__HEAD_FLAG_PAGE_SIZE << 1))
+#define __HEAD_FLAG_PHYS_BASE	1
+
+#define __HEAD_FLAGS		((__HEAD_FLAG_BE << 0) |	\
+				 (__HEAD_FLAG_PAGE_SIZE << 1) |	\
+				 (__HEAD_FLAG_PHYS_BASE << 3))
 
 /*
  * These will output as part of the Image header, which should be little-endian
@@ -58,13 +67,23 @@
  * endian swapped in head.S, all are done here for consistency.
  */
 #define HEAD_SYMBOLS						\
-	_kernel_size_le		= DATA_LE64(_end - _text);	\
-	_kernel_offset_le	= DATA_LE64(TEXT_OFFSET);	\
-	_kernel_flags_le	= DATA_LE64(__HEAD_FLAGS);
+	DEFINE_IMAGE_LE64(_kernel_size_le, _end - _text);	\
+	DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET);	\
+	DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS);
 
 #ifdef CONFIG_EFI
 
 /*
+ * Prevent the symbol aliases below from being emitted into the kallsyms
+ * table, by forcing them to be absolute symbols (which are conveniently
+ * ignored by scripts/kallsyms) rather than section relative symbols.
+ * The distinction is only relevant for partial linking, and only for symbols
+ * that are defined within a section declaration (which is not the case for
+ * the definitions below) so the resulting values will be identical.
+ */
+#define KALLSYMS_HIDE(sym)	ABSOLUTE(sym)
+
+/*
  * The EFI stub has its own symbol namespace prefixed by __efistub_, to
  * isolate it from the kernel proper. The following symbols are legally
  * accessed by the stub, so provide some aliases to make them accessible.
@@ -73,25 +92,25 @@
  * linked at. The routines below are all implemented in assembler in a
  * position independent manner
  */
-__efistub_memcmp		= __pi_memcmp;
-__efistub_memchr		= __pi_memchr;
-__efistub_memcpy		= __pi_memcpy;
-__efistub_memmove		= __pi_memmove;
-__efistub_memset		= __pi_memset;
-__efistub_strlen		= __pi_strlen;
-__efistub_strcmp		= __pi_strcmp;
-__efistub_strncmp		= __pi_strncmp;
-__efistub___flush_dcache_area	= __pi___flush_dcache_area;
+__efistub_memcmp		= KALLSYMS_HIDE(__pi_memcmp);
+__efistub_memchr		= KALLSYMS_HIDE(__pi_memchr);
+__efistub_memcpy		= KALLSYMS_HIDE(__pi_memcpy);
+__efistub_memmove		= KALLSYMS_HIDE(__pi_memmove);
+__efistub_memset		= KALLSYMS_HIDE(__pi_memset);
+__efistub_strlen		= KALLSYMS_HIDE(__pi_strlen);
+__efistub_strcmp		= KALLSYMS_HIDE(__pi_strcmp);
+__efistub_strncmp		= KALLSYMS_HIDE(__pi_strncmp);
+__efistub___flush_dcache_area	= KALLSYMS_HIDE(__pi___flush_dcache_area);
 
 #ifdef CONFIG_KASAN
-__efistub___memcpy		= __pi_memcpy;
-__efistub___memmove		= __pi_memmove;
-__efistub___memset		= __pi_memset;
+__efistub___memcpy		= KALLSYMS_HIDE(__pi_memcpy);
+__efistub___memmove		= KALLSYMS_HIDE(__pi_memmove);
+__efistub___memset		= KALLSYMS_HIDE(__pi_memset);
 #endif
 
-__efistub__text			= _text;
-__efistub__end			= _end;
-__efistub__edata		= _edata;
+__efistub__text			= KALLSYMS_HIDE(_text);
+__efistub__end			= KALLSYMS_HIDE(_end);
+__efistub__edata		= KALLSYMS_HIDE(_edata);
 
 #endif
 
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
index 9f17ec0..2386b26 100644
--- a/arch/arm64/kernel/irq.c
+++ b/arch/arm64/kernel/irq.c
@@ -30,6 +30,9 @@
 
 unsigned long irq_err_count;
 
+/* irq stack only needs to be 16 byte aligned - not IRQ_STACK_SIZE aligned. */
+DEFINE_PER_CPU(unsigned long [IRQ_STACK_SIZE/sizeof(long)], irq_stack) __aligned(16);
+
 int arch_show_interrupts(struct seq_file *p, int prec)
 {
 	show_ipi_list(p, prec);
diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
new file mode 100644
index 0000000..b054691
--- /dev/null
+++ b/arch/arm64/kernel/kaslr.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/crc32.h>
+#include <linux/init.h>
+#include <linux/libfdt.h>
+#include <linux/mm_types.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+
+#include <asm/fixmap.h>
+#include <asm/kernel-pgtable.h>
+#include <asm/memory.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+
+u64 __read_mostly module_alloc_base;
+u16 __initdata memstart_offset_seed;
+
+static __init u64 get_kaslr_seed(void *fdt)
+{
+	int node, len;
+	u64 *prop;
+	u64 ret;
+
+	node = fdt_path_offset(fdt, "/chosen");
+	if (node < 0)
+		return 0;
+
+	prop = fdt_getprop_w(fdt, node, "kaslr-seed", &len);
+	if (!prop || len != sizeof(u64))
+		return 0;
+
+	ret = fdt64_to_cpu(*prop);
+	*prop = 0;
+	return ret;
+}
+
+static __init const u8 *get_cmdline(void *fdt)
+{
+	static __initconst const u8 default_cmdline[] = CONFIG_CMDLINE;
+
+	if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
+		int node;
+		const u8 *prop;
+
+		node = fdt_path_offset(fdt, "/chosen");
+		if (node < 0)
+			goto out;
+
+		prop = fdt_getprop(fdt, node, "bootargs", NULL);
+		if (!prop)
+			goto out;
+		return prop;
+	}
+out:
+	return default_cmdline;
+}
+
+extern void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size,
+				       pgprot_t prot);
+
+/*
+ * This routine will be executed with the kernel mapped at its default virtual
+ * address, and if it returns successfully, the kernel will be remapped, and
+ * start_kernel() will be executed from a randomized virtual offset. The
+ * relocation will result in all absolute references (e.g., static variables
+ * containing function pointers) to be reinitialized, and zero-initialized
+ * .bss variables will be reset to 0.
+ */
+u64 __init kaslr_early_init(u64 dt_phys, u64 modulo_offset)
+{
+	void *fdt;
+	u64 seed, offset, mask, module_range;
+	const u8 *cmdline, *str;
+	int size;
+
+	/*
+	 * Set a reasonable default for module_alloc_base in case
+	 * we end up running with module randomization disabled.
+	 */
+	module_alloc_base = (u64)_etext - MODULES_VSIZE;
+
+	/*
+	 * Try to map the FDT early. If this fails, we simply bail,
+	 * and proceed with KASLR disabled. We will make another
+	 * attempt at mapping the FDT in setup_machine()
+	 */
+	early_fixmap_init();
+	fdt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL);
+	if (!fdt)
+		return 0;
+
+	/*
+	 * Retrieve (and wipe) the seed from the FDT
+	 */
+	seed = get_kaslr_seed(fdt);
+	if (!seed)
+		return 0;
+
+	/*
+	 * Check if 'nokaslr' appears on the command line, and
+	 * return 0 if that is the case.
+	 */
+	cmdline = get_cmdline(fdt);
+	str = strstr(cmdline, "nokaslr");
+	if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
+		return 0;
+
+	/*
+	 * OK, so we are proceeding with KASLR enabled. Calculate a suitable
+	 * kernel image offset from the seed. Let's place the kernel in the
+	 * lower half of the VMALLOC area (VA_BITS - 2).
+	 * Even if we could randomize at page granularity for 16k and 64k pages,
+	 * let's always round to 2 MB so we don't interfere with the ability to
+	 * map using contiguous PTEs
+	 */
+	mask = ((1UL << (VA_BITS - 2)) - 1) & ~(SZ_2M - 1);
+	offset = seed & mask;
+
+	/* use the top 16 bits to randomize the linear region */
+	memstart_offset_seed = seed >> 48;
+
+	/*
+	 * The kernel Image should not extend across a 1GB/32MB/512MB alignment
+	 * boundary (for 4KB/16KB/64KB granule kernels, respectively). If this
+	 * happens, increase the KASLR offset by the size of the kernel image.
+	 */
+	if ((((u64)_text + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT) !=
+	    (((u64)_end + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT))
+		offset = (offset + (u64)(_end - _text)) & mask;
+
+	if (IS_ENABLED(CONFIG_KASAN))
+		/*
+		 * KASAN does not expect the module region to intersect the
+		 * vmalloc region, since shadow memory is allocated for each
+		 * module at load time, whereas the vmalloc region is shadowed
+		 * by KASAN zero pages. So keep modules out of the vmalloc
+		 * region if KASAN is enabled.
+		 */
+		return offset;
+
+	if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) {
+		/*
+		 * Randomize the module region independently from the core
+		 * kernel. This prevents modules from leaking any information
+		 * about the address of the kernel itself, but results in
+		 * branches between modules and the core kernel that are
+		 * resolved via PLTs. (Branches between modules will be
+		 * resolved normally.)
+		 */
+		module_range = VMALLOC_END - VMALLOC_START - MODULES_VSIZE;
+		module_alloc_base = VMALLOC_START;
+	} else {
+		/*
+		 * Randomize the module region by setting module_alloc_base to
+		 * a PAGE_SIZE multiple in the range [_etext - MODULES_VSIZE,
+		 * _stext) . This guarantees that the resulting region still
+		 * covers [_stext, _etext], and that all relative branches can
+		 * be resolved without veneers.
+		 */
+		module_range = MODULES_VSIZE - (u64)(_etext - _stext);
+		module_alloc_base = (u64)_etext + offset - MODULES_VSIZE;
+	}
+
+	/* use the lower 21 bits to randomize the base of the module region */
+	module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21;
+	module_alloc_base &= PAGE_MASK;
+
+	return offset;
+}
diff --git a/arch/arm64/kernel/module-plts.c b/arch/arm64/kernel/module-plts.c
new file mode 100644
index 0000000..1ce90d8
--- /dev/null
+++ b/arch/arm64/kernel/module-plts.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2014-2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/elf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sort.h>
+
+struct plt_entry {
+	/*
+	 * A program that conforms to the AArch64 Procedure Call Standard
+	 * (AAPCS64) must assume that a veneer that alters IP0 (x16) and/or
+	 * IP1 (x17) may be inserted at any branch instruction that is
+	 * exposed to a relocation that supports long branches. Since that
+	 * is exactly what we are dealing with here, we are free to use x16
+	 * as a scratch register in the PLT veneers.
+	 */
+	__le32	mov0;	/* movn	x16, #0x....			*/
+	__le32	mov1;	/* movk	x16, #0x...., lsl #16		*/
+	__le32	mov2;	/* movk	x16, #0x...., lsl #32		*/
+	__le32	br;	/* br	x16				*/
+};
+
+u64 module_emit_plt_entry(struct module *mod, const Elf64_Rela *rela,
+			  Elf64_Sym *sym)
+{
+	struct plt_entry *plt = (struct plt_entry *)mod->arch.plt->sh_addr;
+	int i = mod->arch.plt_num_entries;
+	u64 val = sym->st_value + rela->r_addend;
+
+	/*
+	 * We only emit PLT entries against undefined (SHN_UNDEF) symbols,
+	 * which are listed in the ELF symtab section, but without a type
+	 * or a size.
+	 * So, similar to how the module loader uses the Elf64_Sym::st_value
+	 * field to store the resolved addresses of undefined symbols, let's
+	 * borrow the Elf64_Sym::st_size field (whose value is never used by
+	 * the module loader, even for symbols that are defined) to record
+	 * the address of a symbol's associated PLT entry as we emit it for a
+	 * zero addend relocation (which is the only kind we have to deal with
+	 * in practice). This allows us to find duplicates without having to
+	 * go through the table every time.
+	 */
+	if (rela->r_addend == 0 && sym->st_size != 0) {
+		BUG_ON(sym->st_size < (u64)plt || sym->st_size >= (u64)&plt[i]);
+		return sym->st_size;
+	}
+
+	mod->arch.plt_num_entries++;
+	BUG_ON(mod->arch.plt_num_entries > mod->arch.plt_max_entries);
+
+	/*
+	 * MOVK/MOVN/MOVZ opcode:
+	 * +--------+------------+--------+-----------+-------------+---------+
+	 * | sf[31] | opc[30:29] | 100101 | hw[22:21] | imm16[20:5] | Rd[4:0] |
+	 * +--------+------------+--------+-----------+-------------+---------+
+	 *
+	 * Rd     := 0x10 (x16)
+	 * hw     := 0b00 (no shift), 0b01 (lsl #16), 0b10 (lsl #32)
+	 * opc    := 0b11 (MOVK), 0b00 (MOVN), 0b10 (MOVZ)
+	 * sf     := 1 (64-bit variant)
+	 */
+	plt[i] = (struct plt_entry){
+		cpu_to_le32(0x92800010 | (((~val      ) & 0xffff)) << 5),
+		cpu_to_le32(0xf2a00010 | ((( val >> 16) & 0xffff)) << 5),
+		cpu_to_le32(0xf2c00010 | ((( val >> 32) & 0xffff)) << 5),
+		cpu_to_le32(0xd61f0200)
+	};
+
+	if (rela->r_addend == 0)
+		sym->st_size = (u64)&plt[i];
+
+	return (u64)&plt[i];
+}
+
+#define cmp_3way(a,b)	((a) < (b) ? -1 : (a) > (b))
+
+static int cmp_rela(const void *a, const void *b)
+{
+	const Elf64_Rela *x = a, *y = b;
+	int i;
+
+	/* sort by type, symbol index and addend */
+	i = cmp_3way(ELF64_R_TYPE(x->r_info), ELF64_R_TYPE(y->r_info));
+	if (i == 0)
+		i = cmp_3way(ELF64_R_SYM(x->r_info), ELF64_R_SYM(y->r_info));
+	if (i == 0)
+		i = cmp_3way(x->r_addend, y->r_addend);
+	return i;
+}
+
+static bool duplicate_rel(const Elf64_Rela *rela, int num)
+{
+	/*
+	 * Entries are sorted by type, symbol index and addend. That means
+	 * that, if a duplicate entry exists, it must be in the preceding
+	 * slot.
+	 */
+	return num > 0 && cmp_rela(rela + num, rela + num - 1) == 0;
+}
+
+static unsigned int count_plts(Elf64_Sym *syms, Elf64_Rela *rela, int num)
+{
+	unsigned int ret = 0;
+	Elf64_Sym *s;
+	int i;
+
+	for (i = 0; i < num; i++) {
+		switch (ELF64_R_TYPE(rela[i].r_info)) {
+		case R_AARCH64_JUMP26:
+		case R_AARCH64_CALL26:
+			/*
+			 * We only have to consider branch targets that resolve
+			 * to undefined symbols. This is not simply a heuristic,
+			 * it is a fundamental limitation, since the PLT itself
+			 * is part of the module, and needs to be within 128 MB
+			 * as well, so modules can never grow beyond that limit.
+			 */
+			s = syms + ELF64_R_SYM(rela[i].r_info);
+			if (s->st_shndx != SHN_UNDEF)
+				break;
+
+			/*
+			 * Jump relocations with non-zero addends against
+			 * undefined symbols are supported by the ELF spec, but
+			 * do not occur in practice (e.g., 'jump n bytes past
+			 * the entry point of undefined function symbol f').
+			 * So we need to support them, but there is no need to
+			 * take them into consideration when trying to optimize
+			 * this code. So let's only check for duplicates when
+			 * the addend is zero: this allows us to record the PLT
+			 * entry address in the symbol table itself, rather than
+			 * having to search the list for duplicates each time we
+			 * emit one.
+			 */
+			if (rela[i].r_addend != 0 || !duplicate_rel(rela, i))
+				ret++;
+			break;
+		}
+	}
+	return ret;
+}
+
+int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
+			      char *secstrings, struct module *mod)
+{
+	unsigned long plt_max_entries = 0;
+	Elf64_Sym *syms = NULL;
+	int i;
+
+	/*
+	 * Find the empty .plt section so we can expand it to store the PLT
+	 * entries. Record the symtab address as well.
+	 */
+	for (i = 0; i < ehdr->e_shnum; i++) {
+		if (strcmp(".plt", secstrings + sechdrs[i].sh_name) == 0)
+			mod->arch.plt = sechdrs + i;
+		else if (sechdrs[i].sh_type == SHT_SYMTAB)
+			syms = (Elf64_Sym *)sechdrs[i].sh_addr;
+	}
+
+	if (!mod->arch.plt) {
+		pr_err("%s: module PLT section missing\n", mod->name);
+		return -ENOEXEC;
+	}
+	if (!syms) {
+		pr_err("%s: module symtab section missing\n", mod->name);
+		return -ENOEXEC;
+	}
+
+	for (i = 0; i < ehdr->e_shnum; i++) {
+		Elf64_Rela *rels = (void *)ehdr + sechdrs[i].sh_offset;
+		int numrels = sechdrs[i].sh_size / sizeof(Elf64_Rela);
+		Elf64_Shdr *dstsec = sechdrs + sechdrs[i].sh_info;
+
+		if (sechdrs[i].sh_type != SHT_RELA)
+			continue;
+
+		/* ignore relocations that operate on non-exec sections */
+		if (!(dstsec->sh_flags & SHF_EXECINSTR))
+			continue;
+
+		/* sort by type, symbol index and addend */
+		sort(rels, numrels, sizeof(Elf64_Rela), cmp_rela, NULL);
+
+		plt_max_entries += count_plts(syms, rels, numrels);
+	}
+
+	mod->arch.plt->sh_type = SHT_NOBITS;
+	mod->arch.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
+	mod->arch.plt->sh_addralign = L1_CACHE_BYTES;
+	mod->arch.plt->sh_size = plt_max_entries * sizeof(struct plt_entry);
+	mod->arch.plt_num_entries = 0;
+	mod->arch.plt_max_entries = plt_max_entries;
+	return 0;
+}
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index 93e9702..7f31698 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -34,10 +34,26 @@
 {
 	void *p;
 
-	p = __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR, MODULES_END,
+	p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base,
+				module_alloc_base + MODULES_VSIZE,
 				GFP_KERNEL, PAGE_KERNEL_EXEC, 0,
 				NUMA_NO_NODE, __builtin_return_address(0));
 
+	if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
+	    !IS_ENABLED(CONFIG_KASAN))
+		/*
+		 * KASAN can only deal with module allocations being served
+		 * from the reserved module region, since the remainder of
+		 * the vmalloc region is already backed by zero shadow pages,
+		 * and punching holes into it is non-trivial. Since the module
+		 * region is not randomized when KASAN is enabled, it is even
+		 * less likely that the module region gets exhausted, so we
+		 * can simply omit this fallback in that case.
+		 */
+		p = __vmalloc_node_range(size, MODULE_ALIGN, VMALLOC_START,
+				VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0,
+				NUMA_NO_NODE, __builtin_return_address(0));
+
 	if (p && (kasan_module_alloc(p, size) < 0)) {
 		vfree(p);
 		return NULL;
@@ -361,6 +377,13 @@
 		case R_AARCH64_CALL26:
 			ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 26,
 					     AARCH64_INSN_IMM_26);
+
+			if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
+			    ovf == -ERANGE) {
+				val = module_emit_plt_entry(me, &rel[i], sym);
+				ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2,
+						     26, AARCH64_INSN_IMM_26);
+			}
 			break;
 
 		default:
diff --git a/arch/arm64/kernel/module.lds b/arch/arm64/kernel/module.lds
new file mode 100644
index 0000000..8949f6c
--- /dev/null
+++ b/arch/arm64/kernel/module.lds
@@ -0,0 +1,3 @@
+SECTIONS {
+	.plt (NOLOAD) : { BYTE(0) }
+}
diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c
index 3aa7483..ff46654 100644
--- a/arch/arm64/kernel/perf_callchain.c
+++ b/arch/arm64/kernel/perf_callchain.c
@@ -164,8 +164,11 @@
 	frame.fp = regs->regs[29];
 	frame.sp = regs->sp;
 	frame.pc = regs->pc;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	frame.graph = current->curr_ret_stack;
+#endif
 
-	walk_stackframe(&frame, callchain_trace, entry);
+	walk_stackframe(current, &frame, callchain_trace, entry);
 }
 
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 62068de..e6afea6 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -46,8 +46,10 @@
 #include <linux/notifier.h>
 #include <trace/events/power.h>
 
+#include <asm/alternative.h>
 #include <asm/compat.h>
 #include <asm/cacheflush.h>
+#include <asm/exec.h>
 #include <asm/fpsimd.h>
 #include <asm/mmu_context.h>
 #include <asm/processor.h>
@@ -346,6 +348,9 @@
 	} else {
 		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->pstate = PSR_MODE_EL1h;
+		if (IS_ENABLED(CONFIG_ARM64_UAO) &&
+		    cpus_have_cap(ARM64_HAS_UAO))
+			childregs->pstate |= PSR_UAO_BIT;
 		p->thread.cpu_context.x19 = stack_start;
 		p->thread.cpu_context.x20 = stk_sz;
 	}
@@ -374,6 +379,17 @@
 	: : "r" (tpidr), "r" (tpidrro));
 }
 
+/* Restore the UAO state depending on next's addr_limit */
+void uao_thread_switch(struct task_struct *next)
+{
+	if (IS_ENABLED(CONFIG_ARM64_UAO)) {
+		if (task_thread_info(next)->addr_limit == KERNEL_DS)
+			asm(ALTERNATIVE("nop", SET_PSTATE_UAO(1), ARM64_HAS_UAO));
+		else
+			asm(ALTERNATIVE("nop", SET_PSTATE_UAO(0), ARM64_HAS_UAO));
+	}
+}
+
 /*
  * Thread switching.
  */
@@ -386,6 +402,7 @@
 	tls_thread_switch(next);
 	hw_breakpoint_thread_switch(next);
 	contextidr_thread_switch(next);
+	uao_thread_switch(next);
 
 	/*
 	 * Complete any pending TLB or cache maintenance on this CPU in case
@@ -410,11 +427,14 @@
 	frame.fp = thread_saved_fp(p);
 	frame.sp = thread_saved_sp(p);
 	frame.pc = thread_saved_pc(p);
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	frame.graph = p->curr_ret_stack;
+#endif
 	stack_page = (unsigned long)task_stack_page(p);
 	do {
 		if (frame.sp < stack_page ||
 		    frame.sp >= stack_page + THREAD_SIZE ||
-		    unwind_frame(&frame))
+		    unwind_frame(p, &frame))
 			return 0;
 		if (!in_sched_functions(frame.pc))
 			return frame.pc;
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index ff7f132..beff0fb 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -39,6 +39,7 @@
 #include <linux/elf.h>
 
 #include <asm/compat.h>
+#include <asm/cpufeature.h>
 #include <asm/debug-monitors.h>
 #include <asm/pgtable.h>
 #include <asm/syscall.h>
@@ -226,13 +227,13 @@
 				     struct arch_hw_breakpoint_ctrl ctrl,
 				     struct perf_event_attr *attr)
 {
-	int err, len, type, disabled = !ctrl.enabled;
+	int err, len, type, offset, disabled = !ctrl.enabled;
 
 	attr->disabled = disabled;
 	if (disabled)
 		return 0;
 
-	err = arch_bp_generic_fields(ctrl, &len, &type);
+	err = arch_bp_generic_fields(ctrl, &len, &type, &offset);
 	if (err)
 		return err;
 
@@ -251,6 +252,7 @@
 
 	attr->bp_len	= len;
 	attr->bp_type	= type;
+	attr->bp_addr	+= offset;
 
 	return 0;
 }
@@ -303,7 +305,7 @@
 	if (IS_ERR(bp))
 		return PTR_ERR(bp);
 
-	*addr = bp ? bp->attr.bp_addr : 0;
+	*addr = bp ? counter_arch_bp(bp)->address : 0;
 	return 0;
 }
 
@@ -449,6 +451,8 @@
 	/* (address, ctrl) registers */
 	limit = regset->n * regset->size;
 	while (count && offset < limit) {
+		if (count < PTRACE_HBP_ADDR_SZ)
+			return -EINVAL;
 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
 					 offset, offset + PTRACE_HBP_ADDR_SZ);
 		if (ret)
@@ -458,6 +462,8 @@
 			return ret;
 		offset += PTRACE_HBP_ADDR_SZ;
 
+		if (!count)
+			break;
 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
 					 offset, offset + PTRACE_HBP_CTRL_SZ);
 		if (ret)
@@ -494,13 +500,13 @@
 		   const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	struct user_pt_regs newregs;
+	struct user_pt_regs newregs = task_pt_regs(target)->user_regs;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
 	if (ret)
 		return ret;
 
-	if (!valid_user_regs(&newregs))
+	if (!valid_user_regs(&newregs, target))
 		return -EINVAL;
 
 	task_pt_regs(target)->user_regs = newregs;
@@ -524,7 +530,8 @@
 		   const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	struct user_fpsimd_state newstate;
+	struct user_fpsimd_state newstate =
+		target->thread.fpsimd_state.user_fpsimd;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
 	if (ret)
@@ -548,7 +555,7 @@
 		   const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	unsigned long tls;
+	unsigned long tls = target->thread.tp_value;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
 	if (ret)
@@ -574,7 +581,8 @@
 			   unsigned int pos, unsigned int count,
 			   const void *kbuf, const void __user *ubuf)
 {
-	int syscallno, ret;
+	int syscallno = task_pt_regs(target)->syscallno;
+	int ret;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1);
 	if (ret)
@@ -770,7 +778,7 @@
 
 	}
 
-	if (valid_user_regs(&newregs.user_regs))
+	if (valid_user_regs(&newregs.user_regs, target))
 		*task_pt_regs(target) = newregs;
 	else
 		ret = -EINVAL;
@@ -846,7 +854,7 @@
 			  const void __user *ubuf)
 {
 	int ret;
-	compat_ulong_t tls;
+	compat_ulong_t tls = target->thread.tp_value;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
 	if (ret)
@@ -1272,3 +1280,79 @@
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
 }
+
+/*
+ * Bits which are always architecturally RES0 per ARM DDI 0487A.h
+ * Userspace cannot use these until they have an architectural meaning.
+ * We also reserve IL for the kernel; SS is handled dynamically.
+ */
+#define SPSR_EL1_AARCH64_RES0_BITS \
+	(GENMASK_ULL(63,32) | GENMASK_ULL(27, 22) | GENMASK_ULL(20, 10) | \
+	 GENMASK_ULL(5, 5))
+#define SPSR_EL1_AARCH32_RES0_BITS \
+	(GENMASK_ULL(63,32) | GENMASK_ULL(24, 22) | GENMASK_ULL(20,20))
+
+static int valid_compat_regs(struct user_pt_regs *regs)
+{
+	regs->pstate &= ~SPSR_EL1_AARCH32_RES0_BITS;
+
+	if (!system_supports_mixed_endian_el0()) {
+		if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+			regs->pstate |= COMPAT_PSR_E_BIT;
+		else
+			regs->pstate &= ~COMPAT_PSR_E_BIT;
+	}
+
+	if (user_mode(regs) && (regs->pstate & PSR_MODE32_BIT) &&
+	    (regs->pstate & COMPAT_PSR_A_BIT) == 0 &&
+	    (regs->pstate & COMPAT_PSR_I_BIT) == 0 &&
+	    (regs->pstate & COMPAT_PSR_F_BIT) == 0) {
+		return 1;
+	}
+
+	/*
+	 * Force PSR to a valid 32-bit EL0t, preserving the same bits as
+	 * arch/arm.
+	 */
+	regs->pstate &= COMPAT_PSR_N_BIT | COMPAT_PSR_Z_BIT |
+			COMPAT_PSR_C_BIT | COMPAT_PSR_V_BIT |
+			COMPAT_PSR_Q_BIT | COMPAT_PSR_IT_MASK |
+			COMPAT_PSR_GE_MASK | COMPAT_PSR_E_BIT |
+			COMPAT_PSR_T_BIT;
+	regs->pstate |= PSR_MODE32_BIT;
+
+	return 0;
+}
+
+static int valid_native_regs(struct user_pt_regs *regs)
+{
+	regs->pstate &= ~SPSR_EL1_AARCH64_RES0_BITS;
+
+	if (user_mode(regs) && !(regs->pstate & PSR_MODE32_BIT) &&
+	    (regs->pstate & PSR_D_BIT) == 0 &&
+	    (regs->pstate & PSR_A_BIT) == 0 &&
+	    (regs->pstate & PSR_I_BIT) == 0 &&
+	    (regs->pstate & PSR_F_BIT) == 0) {
+		return 1;
+	}
+
+	/* Force PSR to a valid 64-bit EL0t */
+	regs->pstate &= PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT;
+
+	return 0;
+}
+
+/*
+ * Are the current registers suitable for user mode? (used to maintain
+ * security in signal handlers)
+ */
+int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task)
+{
+	if (!test_tsk_thread_flag(task, TIF_SINGLESTEP))
+		regs->pstate &= ~DBG_SPSR_SS;
+
+	if (is_compat_thread(task_thread_info(task)))
+		return valid_compat_regs(regs);
+	else
+		return valid_native_regs(regs);
+}
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
index 6c4fd28..1718706 100644
--- a/arch/arm64/kernel/return_address.c
+++ b/arch/arm64/kernel/return_address.c
@@ -43,8 +43,11 @@
 	frame.fp = (unsigned long)__builtin_frame_address(0);
 	frame.sp = current_stack_pointer;
 	frame.pc = (unsigned long)return_address; /* dummy */
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	frame.graph = current->curr_ret_stack;
+#endif
 
-	walk_stackframe(&frame, save_return_addr, &data);
+	walk_stackframe(current, &frame, save_return_addr, &data);
 
 	if (!data.level)
 		return data.addr;
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 8119479..6591bf2 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -62,6 +62,7 @@
 #include <asm/memblock.h>
 #include <asm/efi.h>
 #include <asm/xen/hypervisor.h>
+#include <asm/mmu_context.h>
 
 phys_addr_t __fdt_pointer __initdata;
 
@@ -201,7 +202,7 @@
 	struct resource *res;
 
 	kernel_code.start   = virt_to_phys(_text);
-	kernel_code.end     = virt_to_phys(_etext - 1);
+	kernel_code.end     = virt_to_phys(__init_begin - 1);
 	kernel_data.start   = virt_to_phys(_sdata);
 	kernel_data.end     = virt_to_phys(_end - 1);
 
@@ -313,6 +314,12 @@
 	 */
 	local_async_enable();
 
+	/*
+	 * TTBR0 is only used for the identity mapping at this stage. Make it
+	 * point to zero page to avoid speculatively fetching new entries.
+	 */
+	cpu_uninstall_idmap();
+
 	efi_init();
 	arm64_memblock_init();
 
@@ -340,6 +347,15 @@
 	smp_init_cpus();
 	smp_build_mpidr_hash();
 
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	/*
+	 * Make sure init_thread_info.ttbr0 always generates translation
+	 * faults in case uaccess_enable() is inadvertently called by the init
+	 * thread.
+	 */
+	init_thread_info.ttbr0 = virt_to_phys(empty_zero_page);
+#endif
+
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
@@ -381,3 +397,32 @@
 	return 0;
 }
 subsys_initcall(topology_init);
+
+/*
+ * Dump out kernel offset information on panic.
+ */
+static int dump_kernel_offset(struct notifier_block *self, unsigned long v,
+			      void *p)
+{
+	u64 const kaslr_offset = kimage_vaddr - KIMAGE_VADDR;
+
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_offset > 0) {
+		pr_emerg("Kernel Offset: 0x%llx from 0x%lx\n",
+			 kaslr_offset, KIMAGE_VADDR);
+	} else {
+		pr_emerg("Kernel Offset: disabled\n");
+	}
+	return 0;
+}
+
+static struct notifier_block kernel_offset_notifier = {
+	.notifier_call = dump_kernel_offset
+};
+
+static int __init register_kernel_offset_dumper(void)
+{
+	atomic_notifier_chain_register(&panic_notifier_list,
+				       &kernel_offset_notifier);
+	return 0;
+}
+__initcall(register_kernel_offset_dumper);
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index e18c48c..a8eafdb 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -115,7 +115,7 @@
 	 */
 	regs->syscallno = ~0UL;
 
-	err |= !valid_user_regs(&regs->user_regs);
+	err |= !valid_user_regs(&regs->user_regs, current);
 
 	if (err == 0) {
 		struct fpsimd_context *fpsimd_ctx =
@@ -307,7 +307,7 @@
 	/*
 	 * Check that the resulting registers are actually sane.
 	 */
-	ret |= !valid_user_regs(&regs->user_regs);
+	ret |= !valid_user_regs(&regs->user_regs, current);
 
 	/*
 	 * Fast forward the stepping logic so we step into the signal
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 71ef6dc..1073356 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -356,7 +356,7 @@
 	 */
 	regs->syscallno = ~0UL;
 
-	err |= !valid_user_regs(&regs->user_regs);
+	err |= !valid_user_regs(&regs->user_regs, current);
 
 	aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace;
 	if (err == 0)
diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index f586f7c..e33fe33 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -173,6 +173,9 @@
 	/* load physical address of identity map page table in x1 */
 	adrp	x1, idmap_pg_dir
 	mov	sp, x2
+	/* save thread_info */
+	and	x2, x2, #~(THREAD_SIZE - 1)
+	msr	sp_el0, x2
 	/*
 	 * cpu_do_resume expects x0 to contain context physical address
 	 * pointer and x1 to contain physical address of 1:1 page tables
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index b1adc51..a84623d 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -70,6 +70,7 @@
 	IPI_CPU_STOP,
 	IPI_TIMER,
 	IPI_IRQ_WORK,
+	IPI_WAKEUP
 };
 
 /*
@@ -149,9 +150,7 @@
 	 * TTBR0 is only used for the identity mapping at this stage. Make it
 	 * point to zero page to avoid speculatively fetching new entries.
 	 */
-	cpu_set_reserved_ttbr0();
-	local_flush_tlb_all();
-	cpu_set_default_tcr_t0sz();
+	cpu_uninstall_idmap();
 
 	preempt_disable();
 	trace_hardirqs_off();
@@ -188,7 +187,6 @@
 	set_cpu_online(cpu, true);
 	complete(&cpu_running);
 
-	local_dbg_enable();
 	local_irq_enable();
 	local_async_enable();
 
@@ -334,8 +332,8 @@
 
 void __init smp_prepare_boot_cpu(void)
 {
-	cpuinfo_store_boot_cpu();
 	set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
+	cpuinfo_store_boot_cpu();
 }
 
 static u64 __init of_get_cpu_mpidr(struct device_node *dn)
@@ -445,6 +443,17 @@
 	/* map the logical cpu id to cpu MPIDR */
 	cpu_logical_map(cpu_count) = hwid;
 
+	/*
+	 * Set-up the ACPI parking protocol cpu entries
+	 * while initializing the cpu_logical_map to
+	 * avoid parsing MADT entries multiple times for
+	 * nothing (ie a valid cpu_logical_map entry should
+	 * contain a valid parking protocol data set to
+	 * initialize the cpu if the parking protocol is
+	 * the only available enable method).
+	 */
+	acpi_set_mailbox_entry(cpu_count, processor);
+
 	cpu_count++;
 }
 
@@ -627,6 +636,7 @@
 	S(IPI_CPU_STOP, "CPU stop interrupts"),
 	S(IPI_TIMER, "Timer broadcast interrupts"),
 	S(IPI_IRQ_WORK, "IRQ work interrupts"),
+	S(IPI_WAKEUP, "CPU wake-up interrupts"),
 };
 
 static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
@@ -670,6 +680,13 @@
 	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC);
 }
 
+#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
+void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
+{
+	smp_cross_call(mask, IPI_WAKEUP);
+}
+#endif
+
 #ifdef CONFIG_IRQ_WORK
 void arch_irq_work_raise(void)
 {
@@ -747,6 +764,14 @@
 		break;
 #endif
 
+#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
+	case IPI_WAKEUP:
+		WARN_ONCE(!acpi_parking_protocol_valid(cpu),
+			  "CPU%u: Wake-up IPI outside the ACPI parking protocol\n",
+			  cpu);
+		break;
+#endif
+
 	default:
 		pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
 		break;
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index ccb6078..cfd46c2 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -17,9 +17,11 @@
  */
 #include <linux/kernel.h>
 #include <linux/export.h>
+#include <linux/ftrace.h>
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 
+#include <asm/irq.h>
 #include <asm/stacktrace.h>
 
 /*
@@ -35,25 +37,82 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int notrace unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
+	unsigned long irq_stack_ptr;
+
+	/*
+	 * Switching between stacks is valid when tracing current and in
+	 * non-preemptible context.
+	 */
+	if (tsk == current && !preemptible())
+		irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id());
+	else
+		irq_stack_ptr = 0;
 
 	low  = frame->sp;
-	high = ALIGN(low, THREAD_SIZE);
+	/* irq stacks are not THREAD_SIZE aligned */
+	if (on_irq_stack(frame->sp, raw_smp_processor_id()))
+		high = irq_stack_ptr;
+	else
+		high = ALIGN(low, THREAD_SIZE) - 0x20;
 
-	if (fp < low || fp > high - 0x18 || fp & 0xf)
+	if (fp < low || fp > high || fp & 0xf)
 		return -EINVAL;
 
 	frame->sp = fp + 0x10;
 	frame->fp = *(unsigned long *)(fp);
 	frame->pc = *(unsigned long *)(fp + 8);
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	if (tsk && tsk->ret_stack &&
+			(frame->pc == (unsigned long)return_to_handler)) {
+		/*
+		 * This is a case where function graph tracer has
+		 * modified a return address (LR) in a stack frame
+		 * to hook a function return.
+		 * So replace it to an original value.
+		 */
+		frame->pc = tsk->ret_stack[frame->graph--].ret;
+	}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+	/*
+	 * Check whether we are going to walk through from interrupt stack
+	 * to task stack.
+	 * If we reach the end of the stack - and its an interrupt stack,
+	 * unpack the dummy frame to find the original elr.
+	 *
+	 * Check the frame->fp we read from the bottom of the irq_stack,
+	 * and the original task stack pointer are both in current->stack.
+	 */
+	if (frame->sp == irq_stack_ptr) {
+		struct pt_regs *irq_args;
+		unsigned long orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr);
+
+		if (object_is_on_stack((void *)orig_sp) &&
+		   object_is_on_stack((void *)frame->fp)) {
+			frame->sp = orig_sp;
+
+			/* orig_sp is the saved pt_regs, find the elr */
+			irq_args = (struct pt_regs *)orig_sp;
+			frame->pc = irq_args->pc;
+		} else {
+			/*
+			 * This frame has a non-standard format, and we
+			 * didn't fix it, because the data looked wrong.
+			 * Refuse to output this frame.
+			 */
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
-void notrace walk_stackframe(struct stackframe *frame,
+void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
 		     int (*fn)(struct stackframe *, void *), void *data)
 {
 	while (1) {
@@ -61,7 +120,7 @@
 
 		if (fn(frame, data))
 			break;
-		ret = unwind_frame(frame);
+		ret = unwind_frame(tsk, frame);
 		if (ret < 0)
 			break;
 	}
@@ -112,8 +171,11 @@
 		frame.sp = current_stack_pointer;
 		frame.pc = (unsigned long)save_stack_trace_tsk;
 	}
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	frame.graph = tsk->curr_ret_stack;
+#endif
 
-	walk_stackframe(&frame, save_trace, &data);
+	walk_stackframe(tsk, &frame, save_trace, &data);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index 1095aa4..f42b8b8 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -1,8 +1,11 @@
 #include <linux/ftrace.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
+#include <asm/alternative.h>
 #include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
 #include <asm/debug-monitors.h>
+#include <asm/exec.h>
 #include <asm/pgtable.h>
 #include <asm/memory.h>
 #include <asm/mmu_context.h>
@@ -60,7 +63,6 @@
  */
 int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 {
-	struct mm_struct *mm = current->active_mm;
 	int ret;
 	unsigned long flags;
 
@@ -87,22 +89,11 @@
 	ret = __cpu_suspend_enter(arg, fn);
 	if (ret == 0) {
 		/*
-		 * We are resuming from reset with TTBR0_EL1 set to the
-		 * idmap to enable the MMU; set the TTBR0 to the reserved
-		 * page tables to prevent speculative TLB allocations, flush
-		 * the local tlb and set the default tcr_el1.t0sz so that
-		 * the TTBR0 address space set-up is properly restored.
-		 * If the current active_mm != &init_mm we entered cpu_suspend
-		 * with mappings in TTBR0 that must be restored, so we switch
-		 * them back to complete the address space configuration
-		 * restoration before returning.
+		 * We are resuming from reset with the idmap active in TTBR0_EL1.
+		 * We must uninstall the idmap and restore the expected MMU
+		 * state before we can possibly return to userspace.
 		 */
-		cpu_set_reserved_ttbr0();
-		local_flush_tlb_all();
-		cpu_set_default_tcr_t0sz();
-
-		if (mm != &init_mm)
-			cpu_switch_mm(mm->pgd, mm);
+		cpu_uninstall_idmap();
 
 		/*
 		 * Restore per-cpu offset before any kernel
@@ -111,6 +102,14 @@
 		set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
 
 		/*
+		 * PSTATE was not saved over suspend/resume, re-enable any
+		 * detected features that might not have been set correctly.
+		 */
+		asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,
+				CONFIG_ARM64_PAN));
+		uao_thread_switch(current);
+
+		/*
 		 * Restore HW breakpoint registers to sane values
 		 * before debug exceptions are possibly reenabled
 		 * through local_dbg_restore.
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 13339b6..5977969 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -52,8 +52,11 @@
 	frame.fp = regs->regs[29];
 	frame.sp = regs->sp;
 	frame.pc = regs->pc;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	frame.graph = -1; /* no task info */
+#endif
 	do {
-		int ret = unwind_frame(&frame);
+		int ret = unwind_frame(NULL, &frame);
 		if (ret < 0)
 			return 0;
 	} while (in_lock_functions(frame.pc));
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 694f6de..7758f7f 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -19,10 +19,30 @@
 #include <linux/nodemask.h>
 #include <linux/of.h>
 #include <linux/sched.h>
+#include <linux/sched.h>
+#include <linux/sched_energy.h>
 
 #include <asm/cputype.h>
 #include <asm/topology.h>
 
+static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
+
+unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu)
+{
+#ifdef CONFIG_CPU_FREQ
+	unsigned long max_freq_scale = cpufreq_scale_max_freq_capacity(cpu);
+
+	return per_cpu(cpu_scale, cpu) * max_freq_scale >> SCHED_CAPACITY_SHIFT;
+#else
+	return per_cpu(cpu_scale, cpu);
+#endif
+}
+
+static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
+{
+	per_cpu(cpu_scale, cpu) = capacity;
+}
+
 static int __init get_cpu_for_node(struct device_node *node)
 {
 	struct device_node *cpu_node;
@@ -206,11 +226,72 @@
 struct cpu_topology cpu_topology[NR_CPUS];
 EXPORT_SYMBOL_GPL(cpu_topology);
 
+/* sd energy functions */
+static inline
+const struct sched_group_energy * const cpu_cluster_energy(int cpu)
+{
+	struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL1];
+
+	if (!sge) {
+		pr_warn("Invalid sched_group_energy for Cluster%d\n", cpu);
+		return NULL;
+	}
+
+	return sge;
+}
+
+static inline
+const struct sched_group_energy * const cpu_core_energy(int cpu)
+{
+	struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL0];
+
+	if (!sge) {
+		pr_warn("Invalid sched_group_energy for CPU%d\n", cpu);
+		return NULL;
+	}
+
+	return sge;
+}
+
 const struct cpumask *cpu_coregroup_mask(int cpu)
 {
 	return &cpu_topology[cpu].core_sibling;
 }
 
+static int cpu_cpu_flags(void)
+{
+	return SD_ASYM_CPUCAPACITY;
+}
+
+static inline int cpu_corepower_flags(void)
+{
+	return SD_SHARE_PKG_RESOURCES  | SD_SHARE_POWERDOMAIN | \
+	       SD_SHARE_CAP_STATES;
+}
+
+static struct sched_domain_topology_level arm64_topology[] = {
+#ifdef CONFIG_SCHED_MC
+	{ cpu_coregroup_mask, cpu_corepower_flags, cpu_core_energy, SD_INIT_NAME(MC) },
+#endif
+	{ cpu_cpu_mask, cpu_cpu_flags, cpu_cluster_energy, SD_INIT_NAME(DIE) },
+	{ NULL, },
+};
+
+static void update_cpu_capacity(unsigned int cpu)
+{
+	unsigned long capacity = SCHED_CAPACITY_SCALE;
+
+	if (cpu_core_energy(cpu)) {
+		int max_cap_idx = cpu_core_energy(cpu)->nr_cap_states - 1;
+		capacity = cpu_core_energy(cpu)->cap_states[max_cap_idx].cap;
+	}
+
+	set_capacity_scale(cpu, capacity);
+
+	pr_info("CPU%d: update cpu_capacity %lu\n",
+		cpu, arch_scale_cpu_capacity(NULL, cpu));
+}
+
 static void update_siblings_masks(unsigned int cpuid)
 {
 	struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
@@ -272,6 +353,7 @@
 
 topology_populated:
 	update_siblings_masks(cpuid);
+	update_cpu_capacity(cpuid);
 }
 
 static void __init reset_cpu_topology(void)
@@ -302,4 +384,8 @@
 	 */
 	if (of_have_populated_dt() && parse_dt_topology())
 		reset_cpu_topology();
+	else
+		set_sched_topology(arm64_topology);
+
+	init_sched_energy_costs();
 }
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index e9b9b53..f5c82c7 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -64,8 +64,7 @@
 
 	/*
 	 * We need to switch to kernel mode so that we can use __get_user
-	 * to safely read from kernel space.  Note that we now dump the
-	 * code first, just in case the backtrace kills us.
+	 * to safely read from kernel space.
 	 */
 	fs = get_fs();
 	set_fs(KERNEL_DS);
@@ -111,21 +110,12 @@
 	print_ip_sym(where);
 }
 
-static void dump_instr(const char *lvl, struct pt_regs *regs)
+static void __dump_instr(const char *lvl, struct pt_regs *regs)
 {
 	unsigned long addr = instruction_pointer(regs);
-	mm_segment_t fs;
 	char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
 	int i;
 
-	/*
-	 * We need to switch to kernel mode so that we can use __get_user
-	 * to safely read from kernel space.  Note that we now dump the
-	 * code first, just in case the backtrace kills us.
-	 */
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-
 	for (i = -4; i < 1; i++) {
 		unsigned int val, bad;
 
@@ -139,24 +129,41 @@
 		}
 	}
 	printk("%sCode: %s\n", lvl, str);
+}
 
-	set_fs(fs);
+static void dump_instr(const char *lvl, struct pt_regs *regs)
+{
+	if (!user_mode(regs)) {
+		mm_segment_t fs = get_fs();
+		set_fs(KERNEL_DS);
+		__dump_instr(lvl, regs);
+		set_fs(fs);
+	} else {
+		__dump_instr(lvl, regs);
+	}
 }
 
 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 {
 	struct stackframe frame;
+	unsigned long irq_stack_ptr;
+	int skip;
+
+	/*
+	 * Switching between stacks is valid when tracing current and in
+	 * non-preemptible context.
+	 */
+	if (tsk == current && !preemptible())
+		irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id());
+	else
+		irq_stack_ptr = 0;
 
 	pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
 
 	if (!tsk)
 		tsk = current;
 
-	if (regs) {
-		frame.fp = regs->regs[29];
-		frame.sp = regs->sp;
-		frame.pc = regs->pc;
-	} else if (tsk == current) {
+	if (tsk == current) {
 		frame.fp = (unsigned long)__builtin_frame_address(0);
 		frame.sp = current_stack_pointer;
 		frame.pc = (unsigned long)dump_backtrace;
@@ -168,21 +175,49 @@
 		frame.sp = thread_saved_sp(tsk);
 		frame.pc = thread_saved_pc(tsk);
 	}
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	frame.graph = tsk->curr_ret_stack;
+#endif
 
-	pr_emerg("Call trace:\n");
+	skip = !!regs;
+	printk("Call trace:\n");
 	while (1) {
 		unsigned long where = frame.pc;
 		unsigned long stack;
 		int ret;
 
-		dump_backtrace_entry(where);
-		ret = unwind_frame(&frame);
+		/* skip until specified stack frame */
+		if (!skip) {
+			dump_backtrace_entry(where);
+		} else if (frame.fp == regs->regs[29]) {
+			skip = 0;
+			/*
+			 * Mostly, this is the case where this function is
+			 * called in panic/abort. As exception handler's
+			 * stack frame does not contain the corresponding pc
+			 * at which an exception has taken place, use regs->pc
+			 * instead.
+			 */
+			dump_backtrace_entry(regs->pc);
+		}
+		ret = unwind_frame(tsk, &frame);
 		if (ret < 0)
 			break;
 		stack = frame.sp;
-		if (in_exception_text(where))
+		if (in_exception_text(where)) {
+			/*
+			 * If we switched to the irq_stack before calling this
+			 * exception handler, then the pt_regs will be on the
+			 * task stack. The easiest way to tell is if the large
+			 * pt_regs would overlap with the end of the irq_stack.
+			 */
+			if (stack < irq_stack_ptr &&
+			    (stack + sizeof(struct pt_regs)) > irq_stack_ptr)
+				stack = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr);
+
 			dump_mem("", "Exception stack", stack,
 				 stack + sizeof(struct pt_regs), false);
+		}
 	}
 }
 
@@ -430,20 +465,37 @@
 
 const char *esr_get_class_string(u32 esr)
 {
-	return esr_class_str[esr >> ESR_ELx_EC_SHIFT];
+	return esr_class_str[ESR_ELx_EC(esr)];
 }
 
 /*
- * bad_mode handles the impossible case in the exception vector.
+ * bad_mode handles the impossible case in the exception vector. This is always
+ * fatal.
  */
 asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
 {
+	console_verbose();
+
+	pr_crit("Bad mode in %s handler detected, code 0x%08x -- %s\n",
+		handler[reason], esr, esr_get_class_string(esr));
+
+	die("Oops - bad mode", regs, 0);
+	local_irq_disable();
+	panic("bad mode");
+}
+
+/*
+ * bad_el0_sync handles unexpected, but potentially recoverable synchronous
+ * exceptions taken from EL0. Unlike bad_mode, this returns.
+ */
+asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
+{
 	siginfo_t info;
 	void __user *pc = (void __user *)instruction_pointer(regs);
 	console_verbose();
 
-	pr_crit("Bad mode in %s handler detected, code 0x%08x -- %s\n",
-		handler[reason], esr, esr_get_class_string(esr));
+	pr_crit("Bad EL0 synchronous exception detected on CPU%d, code 0x%08x -- %s\n",
+		smp_processor_id(), esr, esr_get_class_string(esr));
 	__show_regs(regs);
 
 	info.si_signo = SIGILL;
@@ -451,27 +503,30 @@
 	info.si_code  = ILL_ILLOPC;
 	info.si_addr  = pc;
 
-	arm64_notify_die("Oops - bad mode", regs, &info, 0);
+	current->thread.fault_address = 0;
+	current->thread.fault_code = 0;
+
+	force_sig_info(info.si_signo, &info, current);
 }
 
 void __pte_error(const char *file, int line, unsigned long val)
 {
-	pr_crit("%s:%d: bad pte %016lx.\n", file, line, val);
+	pr_err("%s:%d: bad pte %016lx.\n", file, line, val);
 }
 
 void __pmd_error(const char *file, int line, unsigned long val)
 {
-	pr_crit("%s:%d: bad pmd %016lx.\n", file, line, val);
+	pr_err("%s:%d: bad pmd %016lx.\n", file, line, val);
 }
 
 void __pud_error(const char *file, int line, unsigned long val)
 {
-	pr_crit("%s:%d: bad pud %016lx.\n", file, line, val);
+	pr_err("%s:%d: bad pud %016lx.\n", file, line, val);
 }
 
 void __pgd_error(const char *file, int line, unsigned long val)
 {
-	pr_crit("%s:%d: bad pgd %016lx.\n", file, line, val);
+	pr_err("%s:%d: bad pgd %016lx.\n", file, line, val);
 }
 
 /* GENERIC_BUG traps */
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 97bc68f..3b8acfa 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -55,7 +55,7 @@
  */
 static struct page *vectors_page[1];
 
-static int alloc_vectors_page(void)
+static int __init alloc_vectors_page(void)
 {
 	extern char __kuser_helper_start[], __kuser_helper_end[];
 	extern char __aarch32_sigret_code_start[], __aarch32_sigret_code_end[];
@@ -88,7 +88,7 @@
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long addr = AARCH32_VECTORS_BASE;
-	static struct vm_special_mapping spec = {
+	static const struct vm_special_mapping spec = {
 		.name	= "[vectors]",
 		.pages	= vectors_page,
 
@@ -212,10 +212,16 @@
 	vdso_data->wtm_clock_nsec		= tk->wall_to_monotonic.tv_nsec;
 
 	if (!use_syscall) {
+		/* tkr_mono.cycle_last == tkr_raw.cycle_last */
 		vdso_data->cs_cycle_last	= tk->tkr_mono.cycle_last;
+		vdso_data->raw_time_sec		= tk->raw_time.tv_sec;
+		vdso_data->raw_time_nsec	= tk->raw_time.tv_nsec;
 		vdso_data->xtime_clock_sec	= tk->xtime_sec;
 		vdso_data->xtime_clock_nsec	= tk->tkr_mono.xtime_nsec;
-		vdso_data->cs_mult		= tk->tkr_mono.mult;
+		/* tkr_raw.xtime_nsec == 0 */
+		vdso_data->cs_mono_mult		= tk->tkr_mono.mult;
+		vdso_data->cs_raw_mult		= tk->tkr_raw.mult;
+		/* tkr_mono.shift == tkr_raw.shift */
 		vdso_data->cs_shift		= tk->tkr_mono.shift;
 	}
 
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index b467fd0..62c84f7 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -23,7 +23,7 @@
 ccflags-y += -Wl,-shared
 
 obj-y += vdso.o
-extra-y += vdso.lds vdso-offsets.h
+extra-y += vdso.lds
 CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
 
 # Force dependency (incbin is bad)
@@ -42,11 +42,10 @@
 gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
 quiet_cmd_vdsosym = VDSOSYM $@
 define cmd_vdsosym
-	$(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \
-	cp $@ include/generated/
+	$(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
 endef
 
-$(obj)/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
+include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
 	$(call if_changed,vdsosym)
 
 # Assembly rules for the .S files
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index efa79e8..e00b467 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -26,24 +26,109 @@
 #define NSEC_PER_SEC_HI16	0x3b9a
 
 vdso_data	.req	x6
-use_syscall	.req	w7
-seqcnt		.req	w8
+seqcnt		.req	w7
+w_tmp		.req	w8
+x_tmp		.req	x8
+
+/*
+ * Conventions for macro arguments:
+ * - An argument is write-only if its name starts with "res".
+ * - All other arguments are read-only, unless otherwise specified.
+ */
 
 	.macro	seqcnt_acquire
 9999:	ldr	seqcnt, [vdso_data, #VDSO_TB_SEQ_COUNT]
 	tbnz	seqcnt, #0, 9999b
 	dmb	ishld
-	ldr	use_syscall, [vdso_data, #VDSO_USE_SYSCALL]
 	.endm
 
-	.macro	seqcnt_read, cnt
+	.macro	seqcnt_check fail
 	dmb	ishld
-	ldr	\cnt, [vdso_data, #VDSO_TB_SEQ_COUNT]
+	ldr	w_tmp, [vdso_data, #VDSO_TB_SEQ_COUNT]
+	cmp	w_tmp, seqcnt
+	b.ne	\fail
 	.endm
 
-	.macro	seqcnt_check, cnt, fail
-	cmp	\cnt, seqcnt
-	b.ne	\fail
+	.macro	syscall_check fail
+	ldr	w_tmp, [vdso_data, #VDSO_USE_SYSCALL]
+	cbnz	w_tmp, \fail
+	.endm
+
+	.macro get_nsec_per_sec res
+	mov	\res, #NSEC_PER_SEC_LO16
+	movk	\res, #NSEC_PER_SEC_HI16, lsl #16
+	.endm
+
+	/*
+	 * Returns the clock delta, in nanoseconds left-shifted by the clock
+	 * shift.
+	 */
+	.macro	get_clock_shifted_nsec res, cycle_last, mult
+	/* Read the virtual counter. */
+	isb
+	mrs	x_tmp, cntvct_el0
+	/* Calculate cycle delta and convert to ns. */
+	sub	\res, x_tmp, \cycle_last
+	/* We can only guarantee 56 bits of precision. */
+	movn	x_tmp, #0xff00, lsl #48
+	and	\res, x_tmp, \res
+	mul	\res, \res, \mult
+	.endm
+
+	/*
+	 * Returns in res_{sec,nsec} the REALTIME timespec, based on the
+	 * "wall time" (xtime) and the clock_mono delta.
+	 */
+	.macro	get_ts_realtime res_sec, res_nsec, \
+			clock_nsec, xtime_sec, xtime_nsec, nsec_to_sec
+	add	\res_nsec, \clock_nsec, \xtime_nsec
+	udiv	x_tmp, \res_nsec, \nsec_to_sec
+	add	\res_sec, \xtime_sec, x_tmp
+	msub	\res_nsec, x_tmp, \nsec_to_sec, \res_nsec
+	.endm
+
+	/*
+	 * Returns in res_{sec,nsec} the timespec based on the clock_raw delta,
+	 * used for CLOCK_MONOTONIC_RAW.
+	 */
+	.macro	get_ts_clock_raw res_sec, res_nsec, clock_nsec, nsec_to_sec
+	udiv	\res_sec, \clock_nsec, \nsec_to_sec
+	msub	\res_nsec, \res_sec, \nsec_to_sec, \clock_nsec
+	.endm
+
+	/* sec and nsec are modified in place. */
+	.macro add_ts sec, nsec, ts_sec, ts_nsec, nsec_to_sec
+	/* Add timespec. */
+	add	\sec, \sec, \ts_sec
+	add	\nsec, \nsec, \ts_nsec
+
+	/* Normalise the new timespec. */
+	cmp	\nsec, \nsec_to_sec
+	b.lt	9999f
+	sub	\nsec, \nsec, \nsec_to_sec
+	add	\sec, \sec, #1
+9999:
+	cmp	\nsec, #0
+	b.ge	9998f
+	add	\nsec, \nsec, \nsec_to_sec
+	sub	\sec, \sec, #1
+9998:
+	.endm
+
+	.macro clock_gettime_return, shift=0
+	.if \shift == 1
+	lsr	x11, x11, x12
+	.endif
+	stp	x10, x11, [x1, #TSPEC_TV_SEC]
+	mov	x0, xzr
+	ret
+	.endm
+
+	.macro jump_slot jumptable, index, label
+	.if (. - \jumptable) != 4 * (\index)
+	.error "Jump slot index mismatch"
+	.endif
+	b	\label
 	.endm
 
 	.text
@@ -51,18 +136,25 @@
 /* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */
 ENTRY(__kernel_gettimeofday)
 	.cfi_startproc
-	mov	x2, x30
-	.cfi_register x30, x2
-
-	/* Acquire the sequence counter and get the timespec. */
 	adr	vdso_data, _vdso_data
-1:	seqcnt_acquire
-	cbnz	use_syscall, 4f
-
 	/* If tv is NULL, skip to the timezone code. */
 	cbz	x0, 2f
-	bl	__do_get_tspec
-	seqcnt_check w9, 1b
+
+	/* Compute the time of day. */
+1:	seqcnt_acquire
+	syscall_check fail=4f
+	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+	/* w11 = cs_mono_mult, w12 = cs_shift */
+	ldp	w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
+	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
+	seqcnt_check fail=1b
+
+	get_nsec_per_sec res=x9
+	lsl	x9, x9, x12
+
+	get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
+	get_ts_realtime res_sec=x10, res_nsec=x11, \
+		clock_nsec=x15, xtime_sec=x13, xtime_nsec=x14, nsec_to_sec=x9
 
 	/* Convert ns to us. */
 	mov	x13, #1000
@@ -76,95 +168,126 @@
 	stp	w4, w5, [x1, #TZ_MINWEST]
 3:
 	mov	x0, xzr
-	ret	x2
+	ret
 4:
 	/* Syscall fallback. */
 	mov	x8, #__NR_gettimeofday
 	svc	#0
-	ret	x2
+	ret
 	.cfi_endproc
 ENDPROC(__kernel_gettimeofday)
 
+#define JUMPSLOT_MAX CLOCK_MONOTONIC_COARSE
+
 /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
 ENTRY(__kernel_clock_gettime)
 	.cfi_startproc
-	cmp	w0, #CLOCK_REALTIME
-	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
-	b.ne	2f
-
-	mov	x2, x30
-	.cfi_register x30, x2
-
-	/* Get kernel timespec. */
+	cmp	w0, #JUMPSLOT_MAX
+	b.hi	syscall
 	adr	vdso_data, _vdso_data
-1:	seqcnt_acquire
-	cbnz	use_syscall, 7f
+	adr	x_tmp, jumptable
+	add	x_tmp, x_tmp, w0, uxtw #2
+	br	x_tmp
 
-	bl	__do_get_tspec
-	seqcnt_check w9, 1b
+	ALIGN
+jumptable:
+	jump_slot jumptable, CLOCK_REALTIME, realtime
+	jump_slot jumptable, CLOCK_MONOTONIC, monotonic
+	b	syscall
+	b	syscall
+	jump_slot jumptable, CLOCK_MONOTONIC_RAW, monotonic_raw
+	jump_slot jumptable, CLOCK_REALTIME_COARSE, realtime_coarse
+	jump_slot jumptable, CLOCK_MONOTONIC_COARSE, monotonic_coarse
 
-	mov	x30, x2
+	.if (. - jumptable) != 4 * (JUMPSLOT_MAX + 1)
+	.error	"Wrong jumptable size"
+	.endif
 
-	cmp	w0, #CLOCK_MONOTONIC
-	b.ne	6f
+	ALIGN
+realtime:
+	seqcnt_acquire
+	syscall_check fail=syscall
+	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+	/* w11 = cs_mono_mult, w12 = cs_shift */
+	ldp	w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
+	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
+	seqcnt_check fail=realtime
 
-	/* Get wtm timespec. */
-	ldp	x13, x14, [vdso_data, #VDSO_WTM_CLK_SEC]
+	/* All computations are done with left-shifted nsecs. */
+	get_nsec_per_sec res=x9
+	lsl	x9, x9, x12
 
-	/* Check the sequence counter. */
-	seqcnt_read w9
-	seqcnt_check w9, 1b
-	b	4f
-2:
-	cmp	w0, #CLOCK_REALTIME_COARSE
-	ccmp	w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
-	b.ne	8f
+	get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
+	get_ts_realtime res_sec=x10, res_nsec=x11, \
+		clock_nsec=x15, xtime_sec=x13, xtime_nsec=x14, nsec_to_sec=x9
+	clock_gettime_return, shift=1
 
-	/* xtime_coarse_nsec is already right-shifted */
-	mov	x12, #0
+	ALIGN
+monotonic:
+	seqcnt_acquire
+	syscall_check fail=syscall
+	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+	/* w11 = cs_mono_mult, w12 = cs_shift */
+	ldp	w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
+	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
+	ldp	x3, x4, [vdso_data, #VDSO_WTM_CLK_SEC]
+	seqcnt_check fail=monotonic
 
-	/* Get coarse timespec. */
-	adr	vdso_data, _vdso_data
-3:	seqcnt_acquire
-	ldp	x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC]
+	/* All computations are done with left-shifted nsecs. */
+	lsl	x4, x4, x12
+	get_nsec_per_sec res=x9
+	lsl	x9, x9, x12
 
-	/* Get wtm timespec. */
-	ldp	x13, x14, [vdso_data, #VDSO_WTM_CLK_SEC]
+	get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
+	get_ts_realtime res_sec=x10, res_nsec=x11, \
+		clock_nsec=x15, xtime_sec=x13, xtime_nsec=x14, nsec_to_sec=x9
 
-	/* Check the sequence counter. */
-	seqcnt_read w9
-	seqcnt_check w9, 3b
+	add_ts sec=x10, nsec=x11, ts_sec=x3, ts_nsec=x4, nsec_to_sec=x9
+	clock_gettime_return, shift=1
 
-	cmp	w0, #CLOCK_MONOTONIC_COARSE
-	b.ne	6f
-4:
-	/* Add on wtm timespec. */
-	add	x10, x10, x13
+	ALIGN
+monotonic_raw:
+	seqcnt_acquire
+	syscall_check fail=syscall
+	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+	/* w11 = cs_raw_mult, w12 = cs_shift */
+	ldp	w12, w11, [vdso_data, #VDSO_CS_SHIFT]
+	ldp	x13, x14, [vdso_data, #VDSO_RAW_TIME_SEC]
+	seqcnt_check fail=monotonic_raw
+
+	/* All computations are done with left-shifted nsecs. */
 	lsl	x14, x14, x12
-	add	x11, x11, x14
+	get_nsec_per_sec res=x9
+	lsl	x9, x9, x12
 
-	/* Normalise the new timespec. */
-	mov	x15, #NSEC_PER_SEC_LO16
-	movk	x15, #NSEC_PER_SEC_HI16, lsl #16
-	lsl	x15, x15, x12
-	cmp	x11, x15
-	b.lt	5f
-	sub	x11, x11, x15
-	add	x10, x10, #1
-5:
-	cmp	x11, #0
-	b.ge	6f
-	add	x11, x11, x15
-	sub	x10, x10, #1
+	get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
+	get_ts_clock_raw res_sec=x10, res_nsec=x11, \
+		clock_nsec=x15, nsec_to_sec=x9
 
-6:	/* Store to the user timespec. */
-	lsr	x11, x11, x12
-	stp	x10, x11, [x1, #TSPEC_TV_SEC]
-	mov	x0, xzr
-	ret
-7:
-	mov	x30, x2
-8:	/* Syscall fallback. */
+	add_ts sec=x10, nsec=x11, ts_sec=x13, ts_nsec=x14, nsec_to_sec=x9
+	clock_gettime_return, shift=1
+
+	ALIGN
+realtime_coarse:
+	seqcnt_acquire
+	ldp	x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC]
+	seqcnt_check fail=realtime_coarse
+	clock_gettime_return
+
+	ALIGN
+monotonic_coarse:
+	seqcnt_acquire
+	ldp	x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC]
+	ldp	x13, x14, [vdso_data, #VDSO_WTM_CLK_SEC]
+	seqcnt_check fail=monotonic_coarse
+
+	/* Computations are done in (non-shifted) nsecs. */
+	get_nsec_per_sec res=x9
+	add_ts sec=x10, nsec=x11, ts_sec=x13, ts_nsec=x14, nsec_to_sec=x9
+	clock_gettime_return
+
+	ALIGN
+syscall: /* Syscall fallback. */
 	mov	x8, #__NR_clock_gettime
 	svc	#0
 	ret
@@ -176,6 +299,7 @@
 	.cfi_startproc
 	cmp	w0, #CLOCK_REALTIME
 	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
+	ccmp	w0, #CLOCK_MONOTONIC_RAW, #0x4, ne
 	b.ne	1f
 
 	ldr	x2, 5f
@@ -203,46 +327,3 @@
 	.quad	CLOCK_COARSE_RES
 	.cfi_endproc
 ENDPROC(__kernel_clock_getres)
-
-/*
- * Read the current time from the architected counter.
- * Expects vdso_data to be initialised.
- * Clobbers the temporary registers (x9 - x15).
- * Returns:
- *  - w9		= vDSO sequence counter
- *  - (x10, x11)	= (ts->tv_sec, shifted ts->tv_nsec)
- *  - w12		= cs_shift
- */
-ENTRY(__do_get_tspec)
-	.cfi_startproc
-
-	/* Read from the vDSO data page. */
-	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
-	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
-	ldp	w11, w12, [vdso_data, #VDSO_CS_MULT]
-	seqcnt_read w9
-
-	/* Read the virtual counter. */
-	isb
-	mrs	x15, cntvct_el0
-
-	/* Calculate cycle delta and convert to ns. */
-	sub	x10, x15, x10
-	/* We can only guarantee 56 bits of precision. */
-	movn	x15, #0xff00, lsl #48
-	and	x10, x15, x10
-	mul	x10, x10, x11
-
-	/* Use the kernel time to calculate the new timespec. */
-	mov	x11, #NSEC_PER_SEC_LO16
-	movk	x11, #NSEC_PER_SEC_HI16, lsl #16
-	lsl	x11, x11, x12
-	add	x15, x10, x14
-	udiv	x14, x15, x11
-	add	x10, x13, x14
-	mul	x13, x14, x11
-	sub	x11, x15, x13
-
-	ret
-	.cfi_endproc
-ENDPROC(__do_get_tspec)
diff --git a/arch/arm64/kernel/vdso/vdso.S b/arch/arm64/kernel/vdso/vdso.S
index 60c1db5..82379a7 100644
--- a/arch/arm64/kernel/vdso/vdso.S
+++ b/arch/arm64/kernel/vdso/vdso.S
@@ -21,9 +21,8 @@
 #include <linux/const.h>
 #include <asm/page.h>
 
-	__PAGE_ALIGNED_DATA
-
 	.globl vdso_start, vdso_end
+	.section .rodata
 	.balign PAGE_SIZE
 vdso_start:
 	.incbin "arch/arm64/kernel/vdso/vdso.so"
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 71426a7..f1d6c49 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -87,15 +87,16 @@
 		EXIT_CALL
 		*(.discard)
 		*(.discard.*)
+		*(.interp .dynamic)
 	}
 
-	. = PAGE_OFFSET + TEXT_OFFSET;
+	. = KIMAGE_VADDR + TEXT_OFFSET;
 
 	.head.text : {
 		_text = .;
 		HEAD_TEXT
 	}
-	ALIGN_DEBUG_RO
+	ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
 	.text : {			/* Real text segment		*/
 		_stext = .;		/* Text and read-only data	*/
 			__exception_text_start = .;
@@ -113,12 +114,12 @@
 		*(.got)			/* Global offset table		*/
 	}
 
-	ALIGN_DEBUG_RO
-	RO_DATA(PAGE_SIZE)
-	EXCEPTION_TABLE(8)
+	ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
+	_etext = .;			/* End of text section */
+
+	RO_DATA(PAGE_SIZE)		/* everything from this point to     */
+	EXCEPTION_TABLE(8)		/* __init_begin will be marked RO NX */
 	NOTES
-	ALIGN_DEBUG_RO
-	_etext = .;			/* End of text and rodata section */
 
 	ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
 	__init_begin = .;
@@ -128,7 +129,6 @@
 		ARM_EXIT_KEEP(EXIT_TEXT)
 	}
 
-	ALIGN_DEBUG_RO_MIN(16)
 	.init.data : {
 		INIT_DATA
 		INIT_SETUP(16)
@@ -143,9 +143,6 @@
 
 	PERCPU_SECTION(L1_CACHE_BYTES)
 
-	. = ALIGN(PAGE_SIZE);
-	__init_end = .;
-
 	. = ALIGN(4);
 	.altinstructions : {
 		__alt_instructions = .;
@@ -155,8 +152,25 @@
 	.altinstr_replacement : {
 		*(.altinstr_replacement)
 	}
+	.rela : ALIGN(8) {
+		__reloc_start = .;
+		*(.rela .rela*)
+		__reloc_end = .;
+	}
+	.dynsym : ALIGN(8) {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+	.dynstr : {
+		*(.dynstr)
+	}
+	.hash : {
+		*(.hash)
+	}
 
 	. = ALIGN(PAGE_SIZE);
+	__init_end = .;
+
 	_data = .;
 	_sdata = .;
 	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
@@ -171,6 +185,11 @@
 	swapper_pg_dir = .;
 	. += SWAPPER_DIR_SIZE;
 
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	reserved_ttbr0 = .;
+	. += RESERVED_TTBR0_SIZE;
+#endif
+
 	_end = .;
 
 	STABS_DEBUG
@@ -190,4 +209,4 @@
 /*
  * If padding is applied before .head.text, virt<->phys conversions will fail.
  */
-ASSERT(_text == (PAGE_OFFSET + TEXT_OFFSET), "HEAD is misaligned")
+ASSERT(_text == (KIMAGE_VADDR + TEXT_OFFSET), "HEAD is misaligned")
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index 178ba22..84c338f 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -64,7 +64,7 @@
 	mrs	x4, tcr_el1
 	ldr	x5, =TCR_EL2_MASK
 	and	x4, x4, x5
-	ldr	x5, =TCR_EL2_FLAGS
+	mov	x5, #TCR_EL2_RES1
 	orr	x4, x4, x5
 
 #ifndef CONFIG_ARM64_VA_BITS_48
@@ -85,15 +85,18 @@
 	ldr_l	x5, idmap_t0sz
 	bfi	x4, x5, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
 #endif
-	msr	tcr_el2, x4
-
-	ldr	x4, =VTCR_EL2_FLAGS
 	/*
 	 * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS bits in
-	 * VTCR_EL2.
+	 * TCR_EL2 and VTCR_EL2.
 	 */
 	mrs	x5, ID_AA64MMFR0_EL1
 	bfi	x4, x5, #16, #3
+
+	msr	tcr_el2, x4
+
+	ldr	x4, =VTCR_EL2_FLAGS
+	bfi	x4, x5, #16, #3
+
 	msr	vtcr_el2, x4
 
 	mrs	x4, mair_el1
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 86c2898..309e347 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -923,7 +923,7 @@
 	.align	2
 
 /*
- * u64 kvm_call_hyp(void *hypfn, ...);
+ * u64 __kvm_call_hyp(void *hypfn, ...);
  *
  * This is not really a variadic function in the classic C-way and care must
  * be taken when calling this to ensure parameters are passed in registers
@@ -940,10 +940,10 @@
  * used to implement __hyp_get_vectors in the same way as in
  * arch/arm64/kernel/hyp_stub.S.
  */
-ENTRY(kvm_call_hyp)
+ENTRY(__kvm_call_hyp)
 	hvc	#0
 	ret
-ENDPROC(kvm_call_hyp)
+ENDPROC(__kvm_call_hyp)
 
 .macro invalid_vector	label, target
 	.align	2
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 648112e..3972e65 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -130,7 +130,7 @@
 		esr |= (ESR_ELx_EC_IABT_CUR << ESR_ELx_EC_SHIFT);
 
 	if (!is_iabt)
-		esr |= ESR_ELx_EC_DABT_LOW;
+		esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
 
 	vcpu_sys_reg(vcpu, ESR_EL1) = esr | ESR_ELx_FSC_EXTABT;
 }
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index d2650e8..c2489f6 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1054,8 +1054,8 @@
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt = (hsr >> 5) & 0xf;
-	int Rt2 = (hsr >> 10) & 0xf;
+	int Rt = (hsr >> 5) & 0x1f;
+	int Rt2 = (hsr >> 10) & 0x1f;
 
 	params.is_aarch32 = true;
 	params.is_32bit = false;
@@ -1106,7 +1106,7 @@
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt  = (hsr >> 5) & 0xf;
+	int Rt  = (hsr >> 5) & 0x1f;
 
 	params.is_aarch32 = true;
 	params.is_32bit = true;
diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile
index 1a811ec..c86b790 100644
--- a/arch/arm64/lib/Makefile
+++ b/arch/arm64/lib/Makefile
@@ -4,15 +4,16 @@
 		   memcmp.o strcmp.o strncmp.o strlen.o strnlen.o	\
 		   strchr.o strrchr.o
 
-# Tell the compiler to treat all general purpose registers as
-# callee-saved, which allows for efficient runtime patching of the bl
-# instruction in the caller with an atomic instruction when supported by
-# the CPU. Result and argument registers are handled correctly, based on
-# the function prototype.
+# Tell the compiler to treat all general purpose registers (with the
+# exception of the IP registers, which are already handled by the caller
+# in case of a PLT) as callee-saved, which allows for efficient runtime
+# patching of the bl instruction in the caller with an atomic instruction
+# when supported by the CPU. Result and argument registers are handled
+# correctly, based on the function prototype.
 lib-$(CONFIG_ARM64_LSE_ATOMICS) += atomic_ll_sc.o
 CFLAGS_atomic_ll_sc.o	:= -fcall-used-x0 -ffixed-x1 -ffixed-x2		\
 		   -ffixed-x3 -ffixed-x4 -ffixed-x5 -ffixed-x6		\
 		   -ffixed-x7 -fcall-saved-x8 -fcall-saved-x9		\
 		   -fcall-saved-x10 -fcall-saved-x11 -fcall-saved-x12	\
 		   -fcall-saved-x13 -fcall-saved-x14 -fcall-saved-x15	\
-		   -fcall-saved-x16 -fcall-saved-x17 -fcall-saved-x18
+		   -fcall-saved-x18
diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S
index a9723c7..d7150e3 100644
--- a/arch/arm64/lib/clear_user.S
+++ b/arch/arm64/lib/clear_user.S
@@ -17,10 +17,7 @@
  */
 #include <linux/linkage.h>
 
-#include <asm/alternative.h>
-#include <asm/assembler.h>
-#include <asm/cpufeature.h>
-#include <asm/sysreg.h>
+#include <asm/uaccess.h>
 
 	.text
 
@@ -33,29 +30,27 @@
  * Alignment fixed up by hardware.
  */
 ENTRY(__clear_user)
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \
-	    CONFIG_ARM64_PAN)
+	uaccess_enable_not_uao x2, x3
 	mov	x2, x1			// save the size for fixup return
 	subs	x1, x1, #8
 	b.mi	2f
 1:
-USER(9f, str	xzr, [x0], #8	)
+uao_user_alternative 9f, str, sttr, xzr, x0, 8
 	subs	x1, x1, #8
 	b.pl	1b
 2:	adds	x1, x1, #4
 	b.mi	3f
-USER(9f, str	wzr, [x0], #4	)
+uao_user_alternative 9f, str, sttr, wzr, x0, 4
 	sub	x1, x1, #4
 3:	adds	x1, x1, #2
 	b.mi	4f
-USER(9f, strh	wzr, [x0], #2	)
+uao_user_alternative 9f, strh, sttrh, wzr, x0, 2
 	sub	x1, x1, #2
 4:	adds	x1, x1, #1
 	b.mi	5f
-USER(9f, strb	wzr, [x0]	)
+uao_user_alternative 9f, strb, sttrb, wzr, x0, 0
 5:	mov	x0, #0
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \
-	    CONFIG_ARM64_PAN)
+	uaccess_disable_not_uao x2
 	ret
 ENDPROC(__clear_user)
 
diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S
index 4699cd7..90154f3 100644
--- a/arch/arm64/lib/copy_from_user.S
+++ b/arch/arm64/lib/copy_from_user.S
@@ -16,11 +16,8 @@
 
 #include <linux/linkage.h>
 
-#include <asm/alternative.h>
-#include <asm/assembler.h>
 #include <asm/cache.h>
-#include <asm/cpufeature.h>
-#include <asm/sysreg.h>
+#include <asm/uaccess.h>
 
 /*
  * Copy from user space to a kernel buffer (alignment handled by the hardware)
@@ -34,7 +31,7 @@
  */
 
 	.macro ldrb1 ptr, regB, val
-	USER(9998f, ldrb  \ptr, [\regB], \val)
+	uao_user_alternative 9998f, ldrb, ldtrb, \ptr, \regB, \val
 	.endm
 
 	.macro strb1 ptr, regB, val
@@ -42,7 +39,7 @@
 	.endm
 
 	.macro ldrh1 ptr, regB, val
-	USER(9998f, ldrh  \ptr, [\regB], \val)
+	uao_user_alternative 9998f, ldrh, ldtrh, \ptr, \regB, \val
 	.endm
 
 	.macro strh1 ptr, regB, val
@@ -50,7 +47,7 @@
 	.endm
 
 	.macro ldr1 ptr, regB, val
-	USER(9998f, ldr \ptr, [\regB], \val)
+	uao_user_alternative 9998f, ldr, ldtr, \ptr, \regB, \val
 	.endm
 
 	.macro str1 ptr, regB, val
@@ -58,7 +55,7 @@
 	.endm
 
 	.macro ldp1 ptr, regB, regC, val
-	USER(9998f, ldp \ptr, \regB, [\regC], \val)
+	uao_ldp 9998f, \ptr, \regB, \regC, \val
 	.endm
 
 	.macro stp1 ptr, regB, regC, val
@@ -66,16 +63,14 @@
 	.endm
 
 end	.req	x5
-ENTRY(__copy_from_user)
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \
-	    CONFIG_ARM64_PAN)
+ENTRY(__arch_copy_from_user)
+	uaccess_enable_not_uao x3, x4
 	add	end, x0, x2
 #include "copy_template.S"
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \
-	    CONFIG_ARM64_PAN)
+	uaccess_disable_not_uao x3
 	mov	x0, #0				// Nothing to copy
 	ret
-ENDPROC(__copy_from_user)
+ENDPROC(__arch_copy_from_user)
 
 	.section .fixup,"ax"
 	.align	2
diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S
index 81c8fc9..718b1c4 100644
--- a/arch/arm64/lib/copy_in_user.S
+++ b/arch/arm64/lib/copy_in_user.S
@@ -18,11 +18,8 @@
 
 #include <linux/linkage.h>
 
-#include <asm/alternative.h>
-#include <asm/assembler.h>
 #include <asm/cache.h>
-#include <asm/cpufeature.h>
-#include <asm/sysreg.h>
+#include <asm/uaccess.h>
 
 /*
  * Copy from user space to user space (alignment handled by the hardware)
@@ -35,45 +32,43 @@
  *	x0 - bytes not copied
  */
 	.macro ldrb1 ptr, regB, val
-	USER(9998f, ldrb  \ptr, [\regB], \val)
+	uao_user_alternative 9998f, ldrb, ldtrb, \ptr, \regB, \val
 	.endm
 
 	.macro strb1 ptr, regB, val
-	USER(9998f, strb \ptr, [\regB], \val)
+	uao_user_alternative 9998f, strb, sttrb, \ptr, \regB, \val
 	.endm
 
 	.macro ldrh1 ptr, regB, val
-	USER(9998f, ldrh  \ptr, [\regB], \val)
+	uao_user_alternative 9998f, ldrh, ldtrh, \ptr, \regB, \val
 	.endm
 
 	.macro strh1 ptr, regB, val
-	USER(9998f, strh \ptr, [\regB], \val)
+	uao_user_alternative 9998f, strh, sttrh, \ptr, \regB, \val
 	.endm
 
 	.macro ldr1 ptr, regB, val
-	USER(9998f, ldr \ptr, [\regB], \val)
+	uao_user_alternative 9998f, ldr, ldtr, \ptr, \regB, \val
 	.endm
 
 	.macro str1 ptr, regB, val
-	USER(9998f, str \ptr, [\regB], \val)
+	uao_user_alternative 9998f, str, sttr, \ptr, \regB, \val
 	.endm
 
 	.macro ldp1 ptr, regB, regC, val
-	USER(9998f, ldp \ptr, \regB, [\regC], \val)
+	uao_ldp 9998f, \ptr, \regB, \regC, \val
 	.endm
 
 	.macro stp1 ptr, regB, regC, val
-	USER(9998f, stp \ptr, \regB, [\regC], \val)
+	uao_stp 9998f, \ptr, \regB, \regC, \val
 	.endm
 
 end	.req	x5
 ENTRY(__copy_in_user)
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \
-	    CONFIG_ARM64_PAN)
+	uaccess_enable_not_uao x3, x4
 	add	end, x0, x2
 #include "copy_template.S"
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \
-	    CONFIG_ARM64_PAN)
+	uaccess_disable_not_uao x3
 	mov	x0, #0
 	ret
 ENDPROC(__copy_in_user)
diff --git a/arch/arm64/lib/copy_page.S b/arch/arm64/lib/copy_page.S
index 512b9a7..4c1e700 100644
--- a/arch/arm64/lib/copy_page.S
+++ b/arch/arm64/lib/copy_page.S
@@ -18,6 +18,8 @@
 #include <linux/const.h>
 #include <asm/assembler.h>
 #include <asm/page.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative.h>
 
 /*
  * Copy a page from src to dest (both are page aligned)
@@ -27,20 +29,65 @@
  *	x1 - src
  */
 ENTRY(copy_page)
-	/* Assume cache line size is 64 bytes. */
-	prfm	pldl1strm, [x1, #64]
-1:	ldp	x2, x3, [x1]
+alternative_if_not ARM64_HAS_NO_HW_PREFETCH
+	nop
+	nop
+alternative_else
+	# Prefetch two cache lines ahead.
+	prfm    pldl1strm, [x1, #128]
+	prfm    pldl1strm, [x1, #256]
+alternative_endif
+
+	ldp	x2, x3, [x1]
 	ldp	x4, x5, [x1, #16]
 	ldp	x6, x7, [x1, #32]
 	ldp	x8, x9, [x1, #48]
-	add	x1, x1, #64
-	prfm	pldl1strm, [x1, #64]
+	ldp	x10, x11, [x1, #64]
+	ldp	x12, x13, [x1, #80]
+	ldp	x14, x15, [x1, #96]
+	ldp	x16, x17, [x1, #112]
+
+	mov	x18, #(PAGE_SIZE - 128)
+	add	x1, x1, #128
+1:
+	subs	x18, x18, #128
+
+alternative_if_not ARM64_HAS_NO_HW_PREFETCH
+	nop
+alternative_else
+	prfm    pldl1strm, [x1, #384]
+alternative_endif
+
+	stnp	x2, x3, [x0]
+	ldp	x2, x3, [x1]
+	stnp	x4, x5, [x0, #16]
+	ldp	x4, x5, [x1, #16]
+	stnp	x6, x7, [x0, #32]
+	ldp	x6, x7, [x1, #32]
+	stnp	x8, x9, [x0, #48]
+	ldp	x8, x9, [x1, #48]
+	stnp	x10, x11, [x0, #64]
+	ldp	x10, x11, [x1, #64]
+	stnp	x12, x13, [x0, #80]
+	ldp	x12, x13, [x1, #80]
+	stnp	x14, x15, [x0, #96]
+	ldp	x14, x15, [x1, #96]
+	stnp	x16, x17, [x0, #112]
+	ldp	x16, x17, [x1, #112]
+
+	add	x0, x0, #128
+	add	x1, x1, #128
+
+	b.gt	1b
+
 	stnp	x2, x3, [x0]
 	stnp	x4, x5, [x0, #16]
 	stnp	x6, x7, [x0, #32]
 	stnp	x8, x9, [x0, #48]
-	add	x0, x0, #64
-	tst	x1, #(PAGE_SIZE - 1)
-	b.ne	1b
+	stnp	x10, x11, [x0, #64]
+	stnp	x12, x13, [x0, #80]
+	stnp	x14, x15, [x0, #96]
+	stnp	x16, x17, [x0, #112]
+
 	ret
 ENDPROC(copy_page)
diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S
index 7512bbb..e99e31c 100644
--- a/arch/arm64/lib/copy_to_user.S
+++ b/arch/arm64/lib/copy_to_user.S
@@ -16,11 +16,8 @@
 
 #include <linux/linkage.h>
 
-#include <asm/alternative.h>
-#include <asm/assembler.h>
 #include <asm/cache.h>
-#include <asm/cpufeature.h>
-#include <asm/sysreg.h>
+#include <asm/uaccess.h>
 
 /*
  * Copy to user space from a kernel buffer (alignment handled by the hardware)
@@ -37,7 +34,7 @@
 	.endm
 
 	.macro strb1 ptr, regB, val
-	USER(9998f, strb \ptr, [\regB], \val)
+	uao_user_alternative 9998f, strb, sttrb, \ptr, \regB, \val
 	.endm
 
 	.macro ldrh1 ptr, regB, val
@@ -45,7 +42,7 @@
 	.endm
 
 	.macro strh1 ptr, regB, val
-	USER(9998f, strh \ptr, [\regB], \val)
+	uao_user_alternative 9998f, strh, sttrh, \ptr, \regB, \val
 	.endm
 
 	.macro ldr1 ptr, regB, val
@@ -53,7 +50,7 @@
 	.endm
 
 	.macro str1 ptr, regB, val
-	USER(9998f, str \ptr, [\regB], \val)
+	uao_user_alternative 9998f, str, sttr, \ptr, \regB, \val
 	.endm
 
 	.macro ldp1 ptr, regB, regC, val
@@ -61,20 +58,18 @@
 	.endm
 
 	.macro stp1 ptr, regB, regC, val
-	USER(9998f, stp \ptr, \regB, [\regC], \val)
+	uao_stp 9998f, \ptr, \regB, \regC, \val
 	.endm
 
 end	.req	x5
-ENTRY(__copy_to_user)
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \
-	    CONFIG_ARM64_PAN)
+ENTRY(__arch_copy_to_user)
+	uaccess_enable_not_uao x3, x4
 	add	end, x0, x2
 #include "copy_template.S"
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \
-	    CONFIG_ARM64_PAN)
+	uaccess_disable_not_uao x3
 	mov	x0, #0
 	ret
-ENDPROC(__copy_to_user)
+ENDPROC(__arch_copy_to_user)
 
 	.section .fixup,"ax"
 	.align	2
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index cfa44a6..3be2cda 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -23,8 +23,7 @@
 #include <asm/assembler.h>
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
-
-#include "proc-macros.S"
+#include <asm/uaccess.h>
 
 /*
  *	flush_icache_range(start,end)
@@ -50,11 +49,12 @@
  *	- end     - virtual end address of region
  */
 ENTRY(__flush_cache_user_range)
+	uaccess_ttbr0_enable x2, x3
 	dcache_line_size x2, x3
 	sub	x3, x2, #1
 	bic	x4, x0, x3
 1:
-USER(9f, dc	cvau, x4	)		// clean D line to PoU
+user_alt 9f, "dc cvau, x4",  "dc civac, x4",  ARM64_WORKAROUND_CLEAN_CACHE
 	add	x4, x4, x2
 	cmp	x4, x1
 	b.lo	1b
@@ -71,36 +71,44 @@
 	dsb	ish
 	isb
 	mov	x0, #0
+1:
+	uaccess_ttbr0_disable x1
 	ret
 9:
 	mov	x0, #-EFAULT
-	ret
+	b	1b
 ENDPROC(flush_icache_range)
 ENDPROC(__flush_cache_user_range)
 
 /*
  *	__flush_dcache_area(kaddr, size)
  *
- *	Ensure that the data held in the page kaddr is written back to the
- *	page in question.
+ *	Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
+ *	are cleaned and invalidated to the PoC.
  *
  *	- kaddr   - kernel address
  *	- size    - size in question
  */
 ENTRY(__flush_dcache_area)
-	dcache_line_size x2, x3
-	add	x1, x0, x1
-	sub	x3, x2, #1
-	bic	x0, x0, x3
-1:	dc	civac, x0			// clean & invalidate D line / unified line
-	add	x0, x0, x2
-	cmp	x0, x1
-	b.lo	1b
-	dsb	sy
+	dcache_by_line_op civac, sy, x0, x1, x2, x3
 	ret
 ENDPIPROC(__flush_dcache_area)
 
 /*
+ *	__clean_dcache_area_pou(kaddr, size)
+ *
+ * 	Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
+ * 	are cleaned to the PoU.
+ *
+ *	- kaddr   - kernel address
+ *	- size    - size in question
+ */
+ENTRY(__clean_dcache_area_pou)
+	dcache_by_line_op cvau, ish, x0, x1, x2, x3
+	ret
+ENDPROC(__clean_dcache_area_pou)
+
+/*
  *	__inval_cache_range(start, end)
  *	- start   - start address of region
  *	- end     - end address of region
diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index e87f53f..2512808 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -182,12 +182,17 @@
 	raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
 
 switch_mm_fastpath:
-	cpu_switch_mm(mm->pgd, mm);
+	/*
+	 * Defer TTBR0_EL1 setting for user threads to uaccess_enable() when
+	 * emulating PAN.
+	 */
+	if (!system_uses_ttbr0_pan())
+		cpu_switch_mm(mm->pgd, mm);
 }
 
 static int asids_init(void)
 {
-	int fld = cpuid_feature_extract_field(read_cpuid(ID_AA64MMFR0_EL1), 4);
+	int fld = cpuid_feature_extract_field(read_cpuid(SYS_ID_AA64MMFR0_EL1), 4);
 
 	switch (fld) {
 	default:
diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c
index 13bbc3be..22e4cb4 100644
--- a/arch/arm64/mm/copypage.c
+++ b/arch/arm64/mm/copypage.c
@@ -24,8 +24,9 @@
 
 void __cpu_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
 {
+	struct page *page = virt_to_page(kto);
 	copy_page(kto, kfrom);
-	__flush_dcache_area(kto, PAGE_SIZE);
+	flush_dcache_page(page);
 }
 EXPORT_SYMBOL_GPL(__cpu_copy_user_page);
 
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index ddfb97a..925b2b3 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -40,7 +40,7 @@
 static struct gen_pool *atomic_pool;
 
 #define DEFAULT_DMA_COHERENT_POOL_SIZE  SZ_256K
-static size_t atomic_pool_size = DEFAULT_DMA_COHERENT_POOL_SIZE;
+static size_t atomic_pool_size __initdata = DEFAULT_DMA_COHERENT_POOL_SIZE;
 
 static int __init early_coherent_pool(char *p)
 {
@@ -896,7 +896,7 @@
 	return 0;
 }
 
-static int register_iommu_dma_ops_notifier(struct bus_type *bus)
+static int __init register_iommu_dma_ops_notifier(struct bus_type *bus)
 {
 	struct notifier_block *nb = kzalloc(sizeof(*nb), GFP_KERNEL);
 	int ret;
diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
index 5a22a11..6be9184 100644
--- a/arch/arm64/mm/dump.c
+++ b/arch/arm64/mm/dump.c
@@ -35,7 +35,9 @@
 };
 
 enum address_markers_idx {
-	VMALLOC_START_NR = 0,
+	MODULES_START_NR = 0,
+	MODULES_END_NR,
+	VMALLOC_START_NR,
 	VMALLOC_END_NR,
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 	VMEMMAP_START_NR,
@@ -45,12 +47,12 @@
 	FIXADDR_END_NR,
 	PCI_START_NR,
 	PCI_END_NR,
-	MODULES_START_NR,
-	MODUELS_END_NR,
 	KERNEL_SPACE_NR,
 };
 
 static struct addr_marker address_markers[] = {
+	{ MODULES_VADDR,	"Modules start" },
+	{ MODULES_END,		"Modules end" },
 	{ VMALLOC_START,	"vmalloc() Area" },
 	{ VMALLOC_END,		"vmalloc() End" },
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
@@ -61,9 +63,7 @@
 	{ FIXADDR_TOP,		"Fixmap end" },
 	{ PCI_IO_START,		"PCI I/O start" },
 	{ PCI_IO_END,		"PCI I/O end" },
-	{ MODULES_VADDR,	"Modules start" },
-	{ MODULES_END,		"Modules end" },
-	{ PAGE_OFFSET,		"Kernel Mapping" },
+	{ PAGE_OFFSET,		"Linear Mapping" },
 	{ -1,			NULL },
 };
 
@@ -90,6 +90,11 @@
 
 static const struct prot_bits pte_bits[] = {
 	{
+		.mask	= PTE_VALID,
+		.val	= PTE_VALID,
+		.set	= " ",
+		.clear	= "F",
+	}, {
 		.mask	= PTE_USER,
 		.val	= PTE_USER,
 		.set	= "USR",
diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c
index 7944427..81acd47 100644
--- a/arch/arm64/mm/extable.c
+++ b/arch/arm64/mm/extable.c
@@ -11,7 +11,7 @@
 
 	fixup = search_exception_tables(instruction_pointer(regs));
 	if (fixup)
-		regs->pc = fixup->fixup;
+		regs->pc = (unsigned long)&fixup->fixup + fixup->fixup;
 
 	return fixup != NULL;
 }
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 92ddac1..2581ede 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -29,7 +29,9 @@
 #include <linux/sched.h>
 #include <linux/highmem.h>
 #include <linux/perf_event.h>
+#include <linux/preempt.h>
 
+#include <asm/bug.h>
 #include <asm/cpufeature.h>
 #include <asm/exception.h>
 #include <asm/debug-monitors.h>
@@ -81,6 +83,61 @@
 	printk("\n");
 }
 
+#ifdef CONFIG_ARM64_HW_AFDBM
+/*
+ * This function sets the access flags (dirty, accessed), as well as write
+ * permission, and only to a more permissive setting.
+ *
+ * It needs to cope with hardware update of the accessed/dirty state by other
+ * agents in the system and can safely skip the __sync_icache_dcache() call as,
+ * like set_pte_at(), the PTE is never changed from no-exec to exec here.
+ *
+ * Returns whether or not the PTE actually changed.
+ */
+int ptep_set_access_flags(struct vm_area_struct *vma,
+			  unsigned long address, pte_t *ptep,
+			  pte_t entry, int dirty)
+{
+	pteval_t old_pteval;
+	unsigned int tmp;
+
+	if (pte_same(*ptep, entry))
+		return 0;
+
+	/* only preserve the access flags and write permission */
+	pte_val(entry) &= PTE_AF | PTE_WRITE | PTE_DIRTY;
+
+	/*
+	 * PTE_RDONLY is cleared by default in the asm below, so set it in
+	 * back if necessary (read-only or clean PTE).
+	 */
+	if (!pte_write(entry) || !pte_sw_dirty(entry))
+		pte_val(entry) |= PTE_RDONLY;
+
+	/*
+	 * Setting the flags must be done atomically to avoid racing with the
+	 * hardware update of the access/dirty state.
+	 */
+	asm volatile("//	ptep_set_access_flags\n"
+	"	prfm	pstl1strm, %2\n"
+	"1:	ldxr	%0, %2\n"
+	"	and	%0, %0, %3		// clear PTE_RDONLY\n"
+	"	orr	%0, %0, %4		// set flags\n"
+	"	stxr	%w1, %0, %2\n"
+	"	cbnz	%w1, 1b\n"
+	: "=&r" (old_pteval), "=&r" (tmp), "+Q" (pte_val(*ptep))
+	: "L" (~PTE_RDONLY), "r" (pte_val(entry)));
+
+	flush_tlb_fix_spurious_fault(vma, address);
+	return 1;
+}
+#endif
+
+static bool is_el1_instruction_abort(unsigned int esr)
+{
+	return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_CUR;
+}
+
 /*
  * The kernel tried to access some page that wasn't present.
  */
@@ -89,8 +146,9 @@
 {
 	/*
 	 * Are we prepared to handle this kernel fault?
+	 * We are almost certainly not prepared to handle instruction faults.
 	 */
-	if (fixup_exception(regs))
+	if (!is_el1_instruction_abort(esr) && fixup_exception(regs))
 		return;
 
 	/*
@@ -152,8 +210,6 @@
 #define VM_FAULT_BADMAP		0x010000
 #define VM_FAULT_BADACCESS	0x020000
 
-#define ESR_LNX_EXEC		(1 << 24)
-
 static int __do_page_fault(struct mm_struct *mm, unsigned long addr,
 			   unsigned int mm_flags, unsigned long vm_flags,
 			   struct task_struct *tsk)
@@ -192,6 +248,26 @@
 	return fault;
 }
 
+static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs)
+{
+	unsigned int ec       = ESR_ELx_EC(esr);
+	unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE;
+
+	if (ec != ESR_ELx_EC_DABT_CUR && ec != ESR_ELx_EC_IABT_CUR)
+		return false;
+
+	if (system_uses_ttbr0_pan())
+		return fsc_type == ESR_ELx_FSC_FAULT &&
+			(regs->pstate & PSR_PAN_BIT);
+	else
+		return fsc_type == ESR_ELx_FSC_PERM;
+}
+
+static bool is_el0_instruction_abort(unsigned int esr)
+{
+	return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW;
+}
+
 static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 				   struct pt_regs *regs)
 {
@@ -218,19 +294,24 @@
 	if (user_mode(regs))
 		mm_flags |= FAULT_FLAG_USER;
 
-	if (esr & ESR_LNX_EXEC) {
+	if (is_el0_instruction_abort(esr)) {
 		vm_flags = VM_EXEC;
 	} else if ((esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM)) {
 		vm_flags = VM_WRITE;
 		mm_flags |= FAULT_FLAG_WRITE;
 	}
 
-	/*
-	 * PAN bit set implies the fault happened in kernel space, but not
-	 * in the arch's user access functions.
-	 */
-	if (IS_ENABLED(CONFIG_ARM64_PAN) && (regs->pstate & PSR_PAN_BIT))
-		goto no_context;
+	if (addr < USER_DS && is_permission_fault(esr, regs)) {
+		/* regs->orig_addr_limit may be 0 if we entered from EL0 */
+		if (regs->orig_addr_limit == KERNEL_DS)
+			die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
+
+		if (is_el1_instruction_abort(esr))
+			die("Attempting to execute userspace memory", regs, esr);
+
+		if (!search_exception_tables(regs->pc))
+			die("Accessing user space memory outside uaccess.h routines", regs, esr);
+	}
 
 	/*
 	 * As per x86, we may deadlock here. However, since the kernel only
@@ -379,7 +460,7 @@
 	return 1;
 }
 
-static struct fault_info {
+static const struct fault_info {
 	int	(*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
 	int	sig;
 	int	code;
@@ -556,8 +637,30 @@
 }
 
 #ifdef CONFIG_ARM64_PAN
-void cpu_enable_pan(void *__unused)
+int cpu_enable_pan(void *__unused)
 {
+	/*
+	 * We modify PSTATE. This won't work from irq context as the PSTATE
+	 * is discarded once we return from the exception.
+	 */
+	WARN_ON_ONCE(in_interrupt());
+
 	config_sctlr_el1(SCTLR_EL1_SPAN, 0);
+	asm(SET_PSTATE_PAN(1));
+	return 0;
 }
 #endif /* CONFIG_ARM64_PAN */
+
+#ifdef CONFIG_ARM64_UAO
+/*
+ * Kernel threads have fs=KERNEL_DS by default, and don't need to call
+ * set_fs(), devtmpfs in particular relies on this behaviour.
+ * We need to enable the feature at runtime (instead of adding it to
+ * PSR_MODE_EL1h) as the feature may not be implemented by the cpu.
+ */
+int cpu_enable_uao(void *__unused)
+{
+	asm(SET_PSTATE_UAO(1));
+	return 0;
+}
+#endif /* CONFIG_ARM64_UAO */
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
index c26b804..46649d6 100644
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -34,19 +34,24 @@
 		__flush_icache_all();
 }
 
+static void sync_icache_aliases(void *kaddr, unsigned long len)
+{
+	unsigned long addr = (unsigned long)kaddr;
+
+	if (icache_is_aliasing()) {
+		__clean_dcache_area_pou(kaddr, len);
+		__flush_icache_all();
+	} else {
+		flush_icache_range(addr, addr + len);
+	}
+}
+
 static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
 				unsigned long uaddr, void *kaddr,
 				unsigned long len)
 {
-	if (vma->vm_flags & VM_EXEC) {
-		unsigned long addr = (unsigned long)kaddr;
-		if (icache_is_aliasing()) {
-			__flush_dcache_area(kaddr, len);
-			__flush_icache_all();
-		} else {
-			flush_icache_range(addr, addr + len);
-		}
-	}
+	if (vma->vm_flags & VM_EXEC)
+		sync_icache_aliases(kaddr, len);
 }
 
 /*
@@ -74,13 +79,11 @@
 	if (!page_mapping(page))
 		return;
 
-	if (!test_and_set_bit(PG_dcache_clean, &page->flags)) {
-		__flush_dcache_area(page_address(page),
-				PAGE_SIZE << compound_order(page));
+	if (!test_and_set_bit(PG_dcache_clean, &page->flags))
+		sync_icache_aliases(page_address(page),
+				    PAGE_SIZE << compound_order(page));
+	else if (icache_is_aivivt())
 		__flush_icache_all();
-	} else if (icache_is_aivivt()) {
-		__flush_icache_all();
-	}
 }
 
 /*
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 383b03f..da30529 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -41,15 +41,273 @@
 #endif
 }
 
+static int find_num_contig(struct mm_struct *mm, unsigned long addr,
+			   pte_t *ptep, pte_t pte, size_t *pgsize)
+{
+	pgd_t *pgd = pgd_offset(mm, addr);
+	pud_t *pud;
+	pmd_t *pmd;
+
+	*pgsize = PAGE_SIZE;
+	if (!pte_cont(pte))
+		return 1;
+	if (!pgd_present(*pgd)) {
+		VM_BUG_ON(!pgd_present(*pgd));
+		return 1;
+	}
+	pud = pud_offset(pgd, addr);
+	if (!pud_present(*pud)) {
+		VM_BUG_ON(!pud_present(*pud));
+		return 1;
+	}
+	pmd = pmd_offset(pud, addr);
+	if (!pmd_present(*pmd)) {
+		VM_BUG_ON(!pmd_present(*pmd));
+		return 1;
+	}
+	if ((pte_t *)pmd == ptep) {
+		*pgsize = PMD_SIZE;
+		return CONT_PMDS;
+	}
+	return CONT_PTES;
+}
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+			    pte_t *ptep, pte_t pte)
+{
+	size_t pgsize;
+	int i;
+	int ncontig = find_num_contig(mm, addr, ptep, pte, &pgsize);
+	unsigned long pfn;
+	pgprot_t hugeprot;
+
+	if (ncontig == 1) {
+		set_pte_at(mm, addr, ptep, pte);
+		return;
+	}
+
+	pfn = pte_pfn(pte);
+	hugeprot = __pgprot(pte_val(pfn_pte(pfn, __pgprot(0))) ^ pte_val(pte));
+	for (i = 0; i < ncontig; i++) {
+		pr_debug("%s: set pte %p to 0x%llx\n", __func__, ptep,
+			 pte_val(pfn_pte(pfn, hugeprot)));
+		set_pte_at(mm, addr, ptep, pfn_pte(pfn, hugeprot));
+		ptep++;
+		pfn += pgsize >> PAGE_SHIFT;
+		addr += pgsize;
+	}
+}
+
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+		      unsigned long addr, unsigned long sz)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pte_t *pte = NULL;
+
+	pr_debug("%s: addr:0x%lx sz:0x%lx\n", __func__, addr, sz);
+	pgd = pgd_offset(mm, addr);
+	pud = pud_alloc(mm, pgd, addr);
+	if (!pud)
+		return NULL;
+
+	if (sz == PUD_SIZE) {
+		pte = (pte_t *)pud;
+	} else if (sz == (PAGE_SIZE * CONT_PTES)) {
+		pmd_t *pmd = pmd_alloc(mm, pud, addr);
+
+		WARN_ON(addr & (sz - 1));
+		/*
+		 * Note that if this code were ever ported to the
+		 * 32-bit arm platform then it will cause trouble in
+		 * the case where CONFIG_HIGHPTE is set, since there
+		 * will be no pte_unmap() to correspond with this
+		 * pte_alloc_map().
+		 */
+		pte = pte_alloc_map(mm, NULL, pmd, addr);
+	} else if (sz == PMD_SIZE) {
+		if (IS_ENABLED(CONFIG_ARCH_WANT_HUGE_PMD_SHARE) &&
+		    pud_none(*pud))
+			pte = huge_pmd_share(mm, addr, pud);
+		else
+			pte = (pte_t *)pmd_alloc(mm, pud, addr);
+	} else if (sz == (PMD_SIZE * CONT_PMDS)) {
+		pmd_t *pmd;
+
+		pmd = pmd_alloc(mm, pud, addr);
+		WARN_ON(addr & (sz - 1));
+		return (pte_t *)pmd;
+	}
+
+	pr_debug("%s: addr:0x%lx sz:0x%lx ret pte=%p/0x%llx\n", __func__, addr,
+	       sz, pte, pte_val(*pte));
+	return pte;
+}
+
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd = NULL;
+	pte_t *pte = NULL;
+
+	pgd = pgd_offset(mm, addr);
+	pr_debug("%s: addr:0x%lx pgd:%p\n", __func__, addr, pgd);
+	if (!pgd_present(*pgd))
+		return NULL;
+	pud = pud_offset(pgd, addr);
+	if (!pud_present(*pud))
+		return NULL;
+
+	if (pud_huge(*pud))
+		return (pte_t *)pud;
+	pmd = pmd_offset(pud, addr);
+	if (!pmd_present(*pmd))
+		return NULL;
+
+	if (pte_cont(pmd_pte(*pmd))) {
+		pmd = pmd_offset(
+			pud, (addr & CONT_PMD_MASK));
+		return (pte_t *)pmd;
+	}
+	if (pmd_huge(*pmd))
+		return (pte_t *)pmd;
+	pte = pte_offset_kernel(pmd, addr);
+	if (pte_present(*pte) && pte_cont(*pte)) {
+		pte = pte_offset_kernel(
+			pmd, (addr & CONT_PTE_MASK));
+		return pte;
+	}
+	return NULL;
+}
+
+pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
+			 struct page *page, int writable)
+{
+	size_t pagesize = huge_page_size(hstate_vma(vma));
+
+	if (pagesize == CONT_PTE_SIZE) {
+		entry = pte_mkcont(entry);
+	} else if (pagesize == CONT_PMD_SIZE) {
+		entry = pmd_pte(pmd_mkcont(pte_pmd(entry)));
+	} else if (pagesize != PUD_SIZE && pagesize != PMD_SIZE) {
+		pr_warn("%s: unrecognized huge page size 0x%lx\n",
+			__func__, pagesize);
+	}
+	return entry;
+}
+
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+			      unsigned long addr, pte_t *ptep)
+{
+	pte_t pte;
+
+	if (pte_cont(*ptep)) {
+		int ncontig, i;
+		size_t pgsize;
+		pte_t *cpte;
+		bool is_dirty = false;
+
+		cpte = huge_pte_offset(mm, addr);
+		ncontig = find_num_contig(mm, addr, cpte, *cpte, &pgsize);
+		/* save the 1st pte to return */
+		pte = ptep_get_and_clear(mm, addr, cpte);
+		for (i = 1; i < ncontig; ++i) {
+			/*
+			 * If HW_AFDBM is enabled, then the HW could
+			 * turn on the dirty bit for any of the page
+			 * in the set, so check them all.
+			 */
+			++cpte;
+			if (pte_dirty(ptep_get_and_clear(mm, addr, cpte)))
+				is_dirty = true;
+		}
+		if (is_dirty)
+			return pte_mkdirty(pte);
+		else
+			return pte;
+	} else {
+		return ptep_get_and_clear(mm, addr, ptep);
+	}
+}
+
+int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+			       unsigned long addr, pte_t *ptep,
+			       pte_t pte, int dirty)
+{
+	pte_t *cpte;
+
+	if (pte_cont(pte)) {
+		int ncontig, i, changed = 0;
+		size_t pgsize = 0;
+		unsigned long pfn = pte_pfn(pte);
+		/* Select all bits except the pfn */
+		pgprot_t hugeprot =
+			__pgprot(pte_val(pfn_pte(pfn, __pgprot(0))) ^
+				 pte_val(pte));
+
+		cpte = huge_pte_offset(vma->vm_mm, addr);
+		pfn = pte_pfn(*cpte);
+		ncontig = find_num_contig(vma->vm_mm, addr, cpte,
+					  *cpte, &pgsize);
+		for (i = 0; i < ncontig; ++i, ++cpte) {
+			changed = ptep_set_access_flags(vma, addr, cpte,
+							pfn_pte(pfn,
+								hugeprot),
+							dirty);
+			pfn += pgsize >> PAGE_SHIFT;
+		}
+		return changed;
+	} else {
+		return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+	}
+}
+
+void huge_ptep_set_wrprotect(struct mm_struct *mm,
+			     unsigned long addr, pte_t *ptep)
+{
+	if (pte_cont(*ptep)) {
+		int ncontig, i;
+		pte_t *cpte;
+		size_t pgsize = 0;
+
+		cpte = huge_pte_offset(mm, addr);
+		ncontig = find_num_contig(mm, addr, cpte, *cpte, &pgsize);
+		for (i = 0; i < ncontig; ++i, ++cpte)
+			ptep_set_wrprotect(mm, addr, cpte);
+	} else {
+		ptep_set_wrprotect(mm, addr, ptep);
+	}
+}
+
+void huge_ptep_clear_flush(struct vm_area_struct *vma,
+			   unsigned long addr, pte_t *ptep)
+{
+	if (pte_cont(*ptep)) {
+		int ncontig, i;
+		pte_t *cpte;
+		size_t pgsize = 0;
+
+		cpte = huge_pte_offset(vma->vm_mm, addr);
+		ncontig = find_num_contig(vma->vm_mm, addr, cpte,
+					  *cpte, &pgsize);
+		for (i = 0; i < ncontig; ++i, ++cpte)
+			ptep_clear_flush(vma, addr, cpte);
+	} else {
+		ptep_clear_flush(vma, addr, ptep);
+	}
+}
+
 static __init int setup_hugepagesz(char *opt)
 {
 	unsigned long ps = memparse(opt, &opt);
+
 	if (ps == PMD_SIZE) {
 		hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
 	} else if (ps == PUD_SIZE) {
 		hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
 	} else {
-		pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
+		pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10);
 		return 0;
 	}
 	return 1;
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 2242389..6788780 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -35,7 +35,10 @@
 #include <linux/efi.h>
 #include <linux/swiotlb.h>
 
+#include <asm/boot.h>
 #include <asm/fixmap.h>
+#include <asm/kasan.h>
+#include <asm/kernel-pgtable.h>
 #include <asm/memory.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
@@ -45,7 +48,13 @@
 
 #include "mm.h"
 
-phys_addr_t memstart_addr __read_mostly = 0;
+/*
+ * We need to be able to catch inadvertent references to memstart_addr
+ * that occur (potentially in generic code) before arm64_memblock_init()
+ * executes, which assigns it its actual value. So use a default value
+ * that cannot be mistaken for a real physical address.
+ */
+s64 memstart_addr __read_mostly = -1;
 phys_addr_t arm64_dma_phys_limit __read_mostly;
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -58,8 +67,8 @@
 	if (*endp == ',') {
 		size = memparse(endp + 1, NULL);
 
-		initrd_start = (unsigned long)__va(start);
-		initrd_end = (unsigned long)__va(start + size);
+		initrd_start = start;
+		initrd_end = start + size;
 	}
 	return 0;
 }
@@ -71,7 +80,7 @@
  * currently assumes that for memory starting above 4G, 32-bit devices will
  * use a DMA offset.
  */
-static phys_addr_t max_zone_dma_phys(void)
+static phys_addr_t __init max_zone_dma_phys(void)
 {
 	phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
 	return min(offset + (1ULL << 32), memblock_end_of_DRAM());
@@ -122,17 +131,17 @@
 
 int pfn_valid(unsigned long pfn)
 {
-	return (pfn & PFN_MASK) == pfn && memblock_is_memory(pfn << PAGE_SHIFT);
+	return (pfn & PFN_MASK) == pfn && memblock_is_map_memory(pfn << PAGE_SHIFT);
 }
 EXPORT_SYMBOL(pfn_valid);
 #endif
 
 #ifndef CONFIG_SPARSEMEM
-static void arm64_memory_present(void)
+static void __init arm64_memory_present(void)
 {
 }
 #else
-static void arm64_memory_present(void)
+static void __init arm64_memory_present(void)
 {
 	struct memblock_region *reg;
 
@@ -161,7 +170,61 @@
 
 void __init arm64_memblock_init(void)
 {
-	memblock_enforce_memory_limit(memory_limit);
+	const s64 linear_region_size = -(s64)PAGE_OFFSET;
+
+	/*
+	 * Ensure that the linear region takes up exactly half of the kernel
+	 * virtual address space. This way, we can distinguish a linear address
+	 * from a kernel/module/vmalloc address by testing a single bit.
+	 */
+	BUILD_BUG_ON(linear_region_size != BIT(VA_BITS - 1));
+
+	/*
+	 * Select a suitable value for the base of physical memory.
+	 */
+	memstart_addr = round_down(memblock_start_of_DRAM(),
+				   ARM64_MEMSTART_ALIGN);
+
+	/*
+	 * Remove the memory that we will not be able to cover with the
+	 * linear mapping. Take care not to clip the kernel which may be
+	 * high in memory.
+	 */
+	memblock_remove(max_t(u64, memstart_addr + linear_region_size, __pa(_end)),
+			ULLONG_MAX);
+	if (memstart_addr + linear_region_size < memblock_end_of_DRAM()) {
+		/* ensure that memstart_addr remains sufficiently aligned */
+		memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size,
+					 ARM64_MEMSTART_ALIGN);
+		memblock_remove(0, memstart_addr);
+	}
+
+	/*
+	 * Apply the memory limit if it was set. Since the kernel may be loaded
+	 * high up in memory, add back the kernel region that must be accessible
+	 * via the linear mapping.
+	 */
+	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
+		memblock_enforce_memory_limit(memory_limit);
+		memblock_add(__pa(_text), (u64)(_end - _text));
+	}
+
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
+		extern u16 memstart_offset_seed;
+		u64 range = linear_region_size -
+			    (memblock_end_of_DRAM() - memblock_start_of_DRAM());
+
+		/*
+		 * If the size of the linear region exceeds, by a sufficient
+		 * margin, the size of the region that the available physical
+		 * memory spans, randomize the linear region as well.
+		 */
+		if (memstart_offset_seed > 0 && range >= ARM64_MEMSTART_ALIGN) {
+			range = range / ARM64_MEMSTART_ALIGN + 1;
+			memstart_addr -= ARM64_MEMSTART_ALIGN *
+					 ((range * memstart_offset_seed) >> 16);
+		}
+	}
 
 	/*
 	 * Register the kernel text, kernel data, initrd, and initial
@@ -169,8 +232,13 @@
 	 */
 	memblock_reserve(__pa(_text), _end - _text);
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
+	if (initrd_start) {
+		memblock_reserve(initrd_start, initrd_end - initrd_start);
+
+		/* the generic initrd code expects virtual addresses */
+		initrd_start = __phys_to_virt(initrd_start);
+		initrd_end = __phys_to_virt(initrd_end);
+	}
 #endif
 
 	early_init_fdt_scan_reserved_mem();
@@ -304,35 +372,38 @@
 #ifdef CONFIG_KASAN
 		  "    kasan   : 0x%16lx - 0x%16lx   (%6ld GB)\n"
 #endif
+		  "    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n"
 		  "    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n"
+		  "      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n"
+		  "      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n"
+		  "    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n"
+		  "      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n"
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 		  "    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n"
 		  "              0x%16lx - 0x%16lx   (%6ld MB actual)\n"
 #endif
 		  "    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n"
 		  "    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n"
-		  "    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n"
-		  "    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n"
-		  "      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-		  "      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-		  "      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		  "    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n",
 #ifdef CONFIG_KASAN
 		  MLG(KASAN_SHADOW_START, KASAN_SHADOW_END),
 #endif
+		  MLM(MODULES_VADDR, MODULES_END),
 		  MLG(VMALLOC_START, VMALLOC_END),
+		  MLK_ROUNDUP(__init_begin, __init_end),
+		  MLK_ROUNDUP(_text, _etext),
+		  MLK_ROUNDUP(__start_rodata, __init_begin),
+		  MLK_ROUNDUP(_sdata, _edata),
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 		  MLG(VMEMMAP_START,
 		      VMEMMAP_START + VMEMMAP_SIZE),
-		  MLM((unsigned long)virt_to_page(PAGE_OFFSET),
+		  MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
 		      (unsigned long)virt_to_page(high_memory)),
 #endif
 		  MLK(FIXADDR_START, FIXADDR_TOP),
 		  MLM(PCI_IO_START, PCI_IO_END),
-		  MLM(MODULES_VADDR, MODULES_END),
-		  MLM(PAGE_OFFSET, (unsigned long)high_memory),
-		  MLK_ROUNDUP(__init_begin, __init_end),
-		  MLK_ROUNDUP(_text, _etext),
-		  MLK_ROUNDUP(_sdata, _edata));
+		  MLM(__phys_to_virt(memblock_start_of_DRAM()),
+		      (unsigned long)high_memory));
 
 #undef MLK
 #undef MLM
@@ -360,9 +431,8 @@
 
 void free_initmem(void)
 {
-	fixup_init();
 	free_initmem_default(0);
-	free_alternatives_memory();
+	fixup_init();
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -383,3 +453,28 @@
 
 __setup("keepinitrd", keepinitrd_setup);
 #endif
+
+/*
+ * Dump out memory limit information on panic.
+ */
+static int dump_mem_limit(struct notifier_block *self, unsigned long v, void *p)
+{
+	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
+		pr_emerg("Memory Limit: %llu MB\n", memory_limit >> 20);
+	} else {
+		pr_emerg("Memory Limit: none\n");
+	}
+	return 0;
+}
+
+static struct notifier_block mem_limit_notifier = {
+	.notifier_call = dump_mem_limit,
+};
+
+static int __init register_mem_limit_dumper(void)
+{
+	atomic_notifier_chain_register(&panic_notifier_list,
+				       &mem_limit_notifier);
+	return 0;
+}
+__initcall(register_mem_limit_dumper);
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index cf038c7..757009d 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -16,9 +16,12 @@
 #include <linux/memblock.h>
 #include <linux/start_kernel.h>
 
+#include <asm/mmu_context.h>
+#include <asm/kernel-pgtable.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
+#include <asm/sections.h>
 #include <asm/tlbflush.h>
 
 static pgd_t tmp_pg_dir[PTRS_PER_PGD] __initdata __aligned(PGD_SIZE);
@@ -32,7 +35,7 @@
 	if (pmd_none(*pmd))
 		pmd_populate_kernel(&init_mm, pmd, kasan_zero_pte);
 
-	pte = pte_offset_kernel(pmd, addr);
+	pte = pte_offset_kimg(pmd, addr);
 	do {
 		next = addr + PAGE_SIZE;
 		set_pte(pte, pfn_pte(virt_to_pfn(kasan_zero_page),
@@ -50,7 +53,7 @@
 	if (pud_none(*pud))
 		pud_populate(&init_mm, pud, kasan_zero_pmd);
 
-	pmd = pmd_offset(pud, addr);
+	pmd = pmd_offset_kimg(pud, addr);
 	do {
 		next = pmd_addr_end(addr, end);
 		kasan_early_pte_populate(pmd, addr, next);
@@ -67,7 +70,7 @@
 	if (pgd_none(*pgd))
 		pgd_populate(&init_mm, pgd, kasan_zero_pud);
 
-	pud = pud_offset(pgd, addr);
+	pud = pud_offset_kimg(pgd, addr);
 	do {
 		next = pud_addr_end(addr, end);
 		kasan_early_pmd_populate(pud, addr, next);
@@ -96,6 +99,21 @@
 	kasan_map_early_shadow();
 }
 
+/*
+ * Copy the current shadow region into a new pgdir.
+ */
+void __init kasan_copy_shadow(pgd_t *pgdir)
+{
+	pgd_t *pgd, *pgd_new, *pgd_end;
+
+	pgd = pgd_offset_k(KASAN_SHADOW_START);
+	pgd_end = pgd_offset_k(KASAN_SHADOW_END);
+	pgd_new = pgd_offset_raw(pgdir, KASAN_SHADOW_START);
+	do {
+		set_pgd(pgd_new, *pgd);
+	} while (pgd++, pgd_new++, pgd != pgd_end);
+}
+
 static void __init clear_pgds(unsigned long start,
 			unsigned long end)
 {
@@ -108,18 +126,18 @@
 		set_pgd(pgd_offset_k(start), __pgd(0));
 }
 
-static void __init cpu_set_ttbr1(unsigned long ttbr1)
-{
-	asm(
-	"	msr	ttbr1_el1, %0\n"
-	"	isb"
-	:
-	: "r" (ttbr1));
-}
-
 void __init kasan_init(void)
 {
+	u64 kimg_shadow_start, kimg_shadow_end;
+	u64 mod_shadow_start, mod_shadow_end;
 	struct memblock_region *reg;
+	int i;
+
+	kimg_shadow_start = (u64)kasan_mem_to_shadow(_text);
+	kimg_shadow_end = (u64)kasan_mem_to_shadow(_end);
+
+	mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
+	mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
 
 	/*
 	 * We are going to perform proper setup of shadow memory.
@@ -129,13 +147,33 @@
 	 * setup will be finished.
 	 */
 	memcpy(tmp_pg_dir, swapper_pg_dir, sizeof(tmp_pg_dir));
-	cpu_set_ttbr1(__pa(tmp_pg_dir));
-	flush_tlb_all();
+	dsb(ishst);
+	cpu_replace_ttbr1(tmp_pg_dir);
 
 	clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
 
+	vmemmap_populate(kimg_shadow_start, kimg_shadow_end,
+			 pfn_to_nid(virt_to_pfn(_text)));
+
+	/*
+	 * vmemmap_populate() has populated the shadow region that covers the
+	 * kernel image with SWAPPER_BLOCK_SIZE mappings, so we have to round
+	 * the start and end addresses to SWAPPER_BLOCK_SIZE as well, to prevent
+	 * kasan_populate_zero_shadow() from replacing the page table entries
+	 * (PMD or PTE) at the edges of the shadow region for the kernel
+	 * image.
+	 */
+	kimg_shadow_start = round_down(kimg_shadow_start, SWAPPER_BLOCK_SIZE);
+	kimg_shadow_end = round_up(kimg_shadow_end, SWAPPER_BLOCK_SIZE);
+
 	kasan_populate_zero_shadow((void *)KASAN_SHADOW_START,
-			kasan_mem_to_shadow((void *)MODULES_VADDR));
+				   (void *)mod_shadow_start);
+	kasan_populate_zero_shadow((void *)kimg_shadow_end,
+				   kasan_mem_to_shadow((void *)PAGE_OFFSET));
+
+	if (kimg_shadow_start > mod_shadow_end)
+		kasan_populate_zero_shadow((void *)mod_shadow_end,
+					   (void *)kimg_shadow_start);
 
 	for_each_memblock(memory, reg) {
 		void *start = (void *)__phys_to_virt(reg->base);
@@ -155,9 +193,16 @@
 				pfn_to_nid(virt_to_pfn(start)));
 	}
 
+	/*
+	 * KAsan may reuse the contents of kasan_zero_pte directly, so we
+	 * should make sure that it maps the zero page read-only.
+	 */
+	for (i = 0; i < PTRS_PER_PTE; i++)
+		set_pte(&kasan_zero_pte[i],
+			pfn_pte(virt_to_pfn(kasan_zero_page), PAGE_KERNEL_RO));
+
 	memset(kasan_zero_page, 0, PAGE_SIZE);
-	cpu_set_ttbr1(__pa(swapper_pg_dir));
-	flush_tlb_all();
+	cpu_replace_ttbr1(swapper_pg_dir);
 
 	/* At this point kasan is fully initialized. Enable error messages */
 	init_task.kasan_depth = 0;
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 116ad65..6d2e411 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -30,8 +30,10 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 
+#include <asm/barrier.h>
 #include <asm/cputype.h>
 #include <asm/fixmap.h>
+#include <asm/kasan.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
@@ -44,13 +46,20 @@
 
 u64 idmap_t0sz = TCR_T0SZ(VA_BITS);
 
+u64 kimage_voffset __read_mostly;
+EXPORT_SYMBOL(kimage_voffset);
+
 /*
  * Empty_zero_page is a special page that is used for zero-initialized data
  * and COW.
  */
-struct page *empty_zero_page;
+unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss;
 EXPORT_SYMBOL(empty_zero_page);
 
+static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
+static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused;
+static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused;
+
 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 			      unsigned long size, pgprot_t vma_prot)
 {
@@ -62,16 +71,30 @@
 }
 EXPORT_SYMBOL(phys_mem_access_prot);
 
-static void __init *early_alloc(unsigned long sz)
+static phys_addr_t __init early_pgtable_alloc(void)
 {
 	phys_addr_t phys;
 	void *ptr;
 
-	phys = memblock_alloc(sz, sz);
+	phys = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
 	BUG_ON(!phys);
-	ptr = __va(phys);
-	memset(ptr, 0, sz);
-	return ptr;
+
+	/*
+	 * The FIX_{PGD,PUD,PMD} slots may be in active use, but the FIX_PTE
+	 * slot will be free, so we can (ab)use the FIX_PTE slot to initialise
+	 * any level of table.
+	 */
+	ptr = pte_set_fixmap(phys);
+
+	memset(ptr, 0, PAGE_SIZE);
+
+	/*
+	 * Implicit barriers also ensure the zeroed page is visible to the page
+	 * table walker
+	 */
+	pte_clear_fixmap();
+
+	return phys;
 }
 
 /*
@@ -95,24 +118,30 @@
 static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
 				  unsigned long end, unsigned long pfn,
 				  pgprot_t prot,
-				  void *(*alloc)(unsigned long size))
+				  phys_addr_t (*pgtable_alloc)(void))
 {
 	pte_t *pte;
 
 	if (pmd_none(*pmd) || pmd_sect(*pmd)) {
-		pte = alloc(PTRS_PER_PTE * sizeof(pte_t));
+		phys_addr_t pte_phys;
+		BUG_ON(!pgtable_alloc);
+		pte_phys = pgtable_alloc();
+		pte = pte_set_fixmap(pte_phys);
 		if (pmd_sect(*pmd))
 			split_pmd(pmd, pte);
-		__pmd_populate(pmd, __pa(pte), PMD_TYPE_TABLE);
+		__pmd_populate(pmd, pte_phys, PMD_TYPE_TABLE);
 		flush_tlb_all();
+		pte_clear_fixmap();
 	}
 	BUG_ON(pmd_bad(*pmd));
 
-	pte = pte_offset_kernel(pmd, addr);
+	pte = pte_set_fixmap_offset(pmd, addr);
 	do {
 		set_pte(pte, pfn_pte(pfn, prot));
 		pfn++;
 	} while (pte++, addr += PAGE_SIZE, addr != end);
+
+	pte_clear_fixmap();
 }
 
 static void split_pud(pud_t *old_pud, pmd_t *pmd)
@@ -127,10 +156,29 @@
 	} while (pmd++, i++, i < PTRS_PER_PMD);
 }
 
-static void alloc_init_pmd(struct mm_struct *mm, pud_t *pud,
-				  unsigned long addr, unsigned long end,
+#ifdef CONFIG_DEBUG_PAGEALLOC
+static bool block_mappings_allowed(phys_addr_t (*pgtable_alloc)(void))
+{
+
+	/*
+	 * If debug_page_alloc is enabled we must map the linear map
+	 * using pages. However, other mappings created by
+	 * create_mapping_noalloc must use sections in some cases. Allow
+	 * sections to be used in those cases, where no pgtable_alloc
+	 * function is provided.
+	 */
+	return !pgtable_alloc || !debug_pagealloc_enabled();
+}
+#else
+static bool block_mappings_allowed(phys_addr_t (*pgtable_alloc)(void))
+{
+	return true;
+}
+#endif
+
+static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
 				  phys_addr_t phys, pgprot_t prot,
-				  void *(*alloc)(unsigned long size))
+				  phys_addr_t (*pgtable_alloc)(void))
 {
 	pmd_t *pmd;
 	unsigned long next;
@@ -139,7 +187,10 @@
 	 * Check for initial section mappings in the pgd/pud and remove them.
 	 */
 	if (pud_none(*pud) || pud_sect(*pud)) {
-		pmd = alloc(PTRS_PER_PMD * sizeof(pmd_t));
+		phys_addr_t pmd_phys;
+		BUG_ON(!pgtable_alloc);
+		pmd_phys = pgtable_alloc();
+		pmd = pmd_set_fixmap(pmd_phys);
 		if (pud_sect(*pud)) {
 			/*
 			 * need to have the 1G of mappings continue to be
@@ -147,19 +198,20 @@
 			 */
 			split_pud(pud, pmd);
 		}
-		pud_populate(mm, pud, pmd);
+		__pud_populate(pud, pmd_phys, PUD_TYPE_TABLE);
 		flush_tlb_all();
+		pmd_clear_fixmap();
 	}
 	BUG_ON(pud_bad(*pud));
 
-	pmd = pmd_offset(pud, addr);
+	pmd = pmd_set_fixmap_offset(pud, addr);
 	do {
 		next = pmd_addr_end(addr, end);
 		/* try section mapping first */
-		if (((addr | next | phys) & ~SECTION_MASK) == 0) {
+		if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
+		      block_mappings_allowed(pgtable_alloc)) {
 			pmd_t old_pmd =*pmd;
-			set_pmd(pmd, __pmd(phys |
-					   pgprot_val(mk_sect_prot(prot))));
+			pmd_set_huge(pmd, phys, prot);
 			/*
 			 * Check for previous table entries created during
 			 * boot (__create_page_tables) and flush them.
@@ -167,17 +219,19 @@
 			if (!pmd_none(old_pmd)) {
 				flush_tlb_all();
 				if (pmd_table(old_pmd)) {
-					phys_addr_t table = __pa(pte_offset_map(&old_pmd, 0));
+					phys_addr_t table = pmd_page_paddr(old_pmd);
 					if (!WARN_ON_ONCE(slab_is_available()))
 						memblock_free(table, PAGE_SIZE);
 				}
 			}
 		} else {
 			alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
-				       prot, alloc);
+				       prot, pgtable_alloc);
 		}
 		phys += next - addr;
 	} while (pmd++, addr = next, addr != end);
+
+	pmd_clear_fixmap();
 }
 
 static inline bool use_1G_block(unsigned long addr, unsigned long next,
@@ -192,31 +246,32 @@
 	return true;
 }
 
-static void alloc_init_pud(struct mm_struct *mm, pgd_t *pgd,
-				  unsigned long addr, unsigned long end,
+static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
 				  phys_addr_t phys, pgprot_t prot,
-				  void *(*alloc)(unsigned long size))
+				  phys_addr_t (*pgtable_alloc)(void))
 {
 	pud_t *pud;
 	unsigned long next;
 
 	if (pgd_none(*pgd)) {
-		pud = alloc(PTRS_PER_PUD * sizeof(pud_t));
-		pgd_populate(mm, pgd, pud);
+		phys_addr_t pud_phys;
+		BUG_ON(!pgtable_alloc);
+		pud_phys = pgtable_alloc();
+		__pgd_populate(pgd, pud_phys, PUD_TYPE_TABLE);
 	}
 	BUG_ON(pgd_bad(*pgd));
 
-	pud = pud_offset(pgd, addr);
+	pud = pud_set_fixmap_offset(pgd, addr);
 	do {
 		next = pud_addr_end(addr, end);
 
 		/*
 		 * For 4K granule only, attempt to put down a 1GB block
 		 */
-		if (use_1G_block(addr, next, phys)) {
+		if (use_1G_block(addr, next, phys) &&
+		    block_mappings_allowed(pgtable_alloc)) {
 			pud_t old_pud = *pud;
-			set_pud(pud, __pud(phys |
-					   pgprot_val(mk_sect_prot(prot))));
+			pud_set_huge(pud, phys, prot);
 
 			/*
 			 * If we have an old value for a pud, it will
@@ -228,51 +283,74 @@
 			if (!pud_none(old_pud)) {
 				flush_tlb_all();
 				if (pud_table(old_pud)) {
-					phys_addr_t table = __pa(pmd_offset(&old_pud, 0));
+					phys_addr_t table = pud_page_paddr(old_pud);
 					if (!WARN_ON_ONCE(slab_is_available()))
 						memblock_free(table, PAGE_SIZE);
 				}
 			}
 		} else {
-			alloc_init_pmd(mm, pud, addr, next, phys, prot, alloc);
+			alloc_init_pmd(pud, addr, next, phys, prot,
+				       pgtable_alloc);
 		}
 		phys += next - addr;
 	} while (pud++, addr = next, addr != end);
+
+	pud_clear_fixmap();
 }
 
 /*
  * Create the page directory entries and any necessary page tables for the
  * mapping specified by 'md'.
  */
-static void  __create_mapping(struct mm_struct *mm, pgd_t *pgd,
-				    phys_addr_t phys, unsigned long virt,
+static void init_pgd(pgd_t *pgd, phys_addr_t phys, unsigned long virt,
 				    phys_addr_t size, pgprot_t prot,
-				    void *(*alloc)(unsigned long size))
+				    phys_addr_t (*pgtable_alloc)(void))
 {
 	unsigned long addr, length, end, next;
 
+	/*
+	 * If the virtual and physical address don't have the same offset
+	 * within a page, we cannot map the region as the caller expects.
+	 */
+	if (WARN_ON((phys ^ virt) & ~PAGE_MASK))
+		return;
+
+	phys &= PAGE_MASK;
 	addr = virt & PAGE_MASK;
 	length = PAGE_ALIGN(size + (virt & ~PAGE_MASK));
 
 	end = addr + length;
 	do {
 		next = pgd_addr_end(addr, end);
-		alloc_init_pud(mm, pgd, addr, next, phys, prot, alloc);
+		alloc_init_pud(pgd, addr, next, phys, prot, pgtable_alloc);
 		phys += next - addr;
 	} while (pgd++, addr = next, addr != end);
 }
 
-static void *late_alloc(unsigned long size)
+static phys_addr_t late_pgtable_alloc(void)
 {
-	void *ptr;
-
-	BUG_ON(size > PAGE_SIZE);
-	ptr = (void *)__get_free_page(PGALLOC_GFP);
+	void *ptr = (void *)__get_free_page(PGALLOC_GFP);
 	BUG_ON(!ptr);
-	return ptr;
+
+	/* Ensure the zeroed page is visible to the page table walker */
+	dsb(ishst);
+	return __pa(ptr);
 }
 
-static void __init create_mapping(phys_addr_t phys, unsigned long virt,
+static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
+				 unsigned long virt, phys_addr_t size,
+				 pgprot_t prot,
+				 phys_addr_t (*alloc)(void))
+{
+	init_pgd(pgd_offset_raw(pgdir, virt), phys, virt, size, prot, alloc);
+}
+
+/*
+ * This function can only be used to modify existing table entries,
+ * without allocating new levels of table. Note that this permits the
+ * creation of new section or page entries.
+ */
+static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
 				  phys_addr_t size, pgprot_t prot)
 {
 	if (virt < VMALLOC_START) {
@@ -280,16 +358,16 @@
 			&phys, virt);
 		return;
 	}
-	__create_mapping(&init_mm, pgd_offset_k(virt & PAGE_MASK), phys, virt,
-			 size, prot, early_alloc);
+	__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
+			     NULL);
 }
 
 void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
 			       unsigned long virt, phys_addr_t size,
 			       pgprot_t prot)
 {
-	__create_mapping(mm, pgd_offset(mm, virt), phys, virt, size, prot,
-				late_alloc);
+	__create_pgd_mapping(mm->pgd, phys, virt, size, prot,
+			     late_pgtable_alloc);
 }
 
 static void create_mapping_late(phys_addr_t phys, unsigned long virt,
@@ -301,69 +379,57 @@
 		return;
 	}
 
-	return __create_mapping(&init_mm, pgd_offset_k(virt & PAGE_MASK),
-				phys, virt, size, prot, late_alloc);
+	__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
+			     late_pgtable_alloc);
 }
 
-#ifdef CONFIG_DEBUG_RODATA
-static void __init __map_memblock(phys_addr_t start, phys_addr_t end)
+static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
 {
-	/*
-	 * Set up the executable regions using the existing section mappings
-	 * for now. This will get more fine grained later once all memory
-	 * is mapped
-	 */
-	unsigned long kernel_x_start = round_down(__pa(_stext), SWAPPER_BLOCK_SIZE);
-	unsigned long kernel_x_end = round_up(__pa(__init_end), SWAPPER_BLOCK_SIZE);
+	unsigned long kernel_start = __pa(_stext);
+	unsigned long kernel_end = __pa(__init_begin);
 
-	if (end < kernel_x_start) {
-		create_mapping(start, __phys_to_virt(start),
-			end - start, PAGE_KERNEL);
-	} else if (start >= kernel_x_end) {
-		create_mapping(start, __phys_to_virt(start),
-			end - start, PAGE_KERNEL);
-	} else {
-		if (start < kernel_x_start)
-			create_mapping(start, __phys_to_virt(start),
-				kernel_x_start - start,
-				PAGE_KERNEL);
-		create_mapping(kernel_x_start,
-				__phys_to_virt(kernel_x_start),
-				kernel_x_end - kernel_x_start,
-				PAGE_KERNEL_EXEC);
-		if (kernel_x_end < end)
-			create_mapping(kernel_x_end,
-				__phys_to_virt(kernel_x_end),
-				end - kernel_x_end,
-				PAGE_KERNEL);
+	/*
+	 * Take care not to create a writable alias for the
+	 * read-only text and rodata sections of the kernel image.
+	 */
+
+	/* No overlap with the kernel text/rodata */
+	if (end < kernel_start || start >= kernel_end) {
+		__create_pgd_mapping(pgd, start, __phys_to_virt(start),
+				     end - start, PAGE_KERNEL,
+				     early_pgtable_alloc);
+		return;
 	}
 
-}
-#else
-static void __init __map_memblock(phys_addr_t start, phys_addr_t end)
-{
-	create_mapping(start, __phys_to_virt(start), end - start,
-			PAGE_KERNEL_EXEC);
-}
-#endif
-
-static void __init map_mem(void)
-{
-	struct memblock_region *reg;
-	phys_addr_t limit;
+	/*
+	 * This block overlaps the kernel text/rodata mapping.
+	 * Map the portion(s) which don't overlap.
+	 */
+	if (start < kernel_start)
+		__create_pgd_mapping(pgd, start,
+				     __phys_to_virt(start),
+				     kernel_start - start, PAGE_KERNEL,
+				     early_pgtable_alloc);
+	if (kernel_end < end)
+		__create_pgd_mapping(pgd, kernel_end,
+				     __phys_to_virt(kernel_end),
+				     end - kernel_end, PAGE_KERNEL,
+				     early_pgtable_alloc);
 
 	/*
-	 * Temporarily limit the memblock range. We need to do this as
-	 * create_mapping requires puds, pmds and ptes to be allocated from
-	 * memory addressable from the initial direct kernel mapping.
-	 *
-	 * The initial direct kernel mapping, located at swapper_pg_dir, gives
-	 * us PUD_SIZE (with SECTION maps) or PMD_SIZE (without SECTION maps,
-	 * memory starting from PHYS_OFFSET (which must be aligned to 2MB as
-	 * per Documentation/arm64/booting.txt).
+	 * Map the linear alias of the [_stext, __init_begin) interval as
+	 * read-only/non-executable. This makes the contents of the
+	 * region accessible to subsystems such as hibernate, but
+	 * protects it from inadvertent modification or execution.
 	 */
-	limit = PHYS_OFFSET + SWAPPER_INIT_MAP_SIZE;
-	memblock_set_current_limit(limit);
+	__create_pgd_mapping(pgd, kernel_start, __phys_to_virt(kernel_start),
+			     kernel_end - kernel_start, PAGE_KERNEL_RO,
+			     early_pgtable_alloc);
+}
+
+static void __init map_mem(pgd_t *pgd)
+{
+	struct memblock_region *reg;
 
 	/* map all the memory banks */
 	for_each_memblock(memory, reg) {
@@ -372,70 +438,97 @@
 
 		if (start >= end)
 			break;
+		if (memblock_is_nomap(reg))
+			continue;
 
-		if (ARM64_SWAPPER_USES_SECTION_MAPS) {
-			/*
-			 * For the first memory bank align the start address and
-			 * current memblock limit to prevent create_mapping() from
-			 * allocating pte page tables from unmapped memory. With
-			 * the section maps, if the first block doesn't end on section
-			 * size boundary, create_mapping() will try to allocate a pte
-			 * page, which may be returned from an unmapped area.
-			 * When section maps are not used, the pte page table for the
-			 * current limit is already present in swapper_pg_dir.
-			 */
-			if (start < limit)
-				start = ALIGN(start, SECTION_SIZE);
-			if (end < limit) {
-				limit = end & SECTION_MASK;
-				memblock_set_current_limit(limit);
-			}
-		}
-		__map_memblock(start, end);
+		__map_memblock(pgd, start, end);
 	}
-
-	/* Limit no longer required. */
-	memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
 }
 
-static void __init fixup_executable(void)
-{
-#ifdef CONFIG_DEBUG_RODATA
-	/* now that we are actually fully mapped, make the start/end more fine grained */
-	if (!IS_ALIGNED((unsigned long)_stext, SWAPPER_BLOCK_SIZE)) {
-		unsigned long aligned_start = round_down(__pa(_stext),
-							 SWAPPER_BLOCK_SIZE);
-
-		create_mapping(aligned_start, __phys_to_virt(aligned_start),
-				__pa(_stext) - aligned_start,
-				PAGE_KERNEL);
-	}
-
-	if (!IS_ALIGNED((unsigned long)__init_end, SWAPPER_BLOCK_SIZE)) {
-		unsigned long aligned_end = round_up(__pa(__init_end),
-							  SWAPPER_BLOCK_SIZE);
-		create_mapping(__pa(__init_end), (unsigned long)__init_end,
-				aligned_end - __pa(__init_end),
-				PAGE_KERNEL);
-	}
-#endif
-}
-
-#ifdef CONFIG_DEBUG_RODATA
 void mark_rodata_ro(void)
 {
-	create_mapping_late(__pa(_stext), (unsigned long)_stext,
-				(unsigned long)_etext - (unsigned long)_stext,
-				PAGE_KERNEL_ROX);
+	unsigned long section_size;
 
+	section_size = (unsigned long)_etext - (unsigned long)_stext;
+	create_mapping_late(__pa(_stext), (unsigned long)_stext,
+			    section_size, PAGE_KERNEL_ROX);
+	/*
+	 * mark .rodata as read only. Use __init_begin rather than __end_rodata
+	 * to cover NOTES and EXCEPTION_TABLE.
+	 */
+	section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata;
+	create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata,
+			    section_size, PAGE_KERNEL_RO);
 }
-#endif
 
 void fixup_init(void)
 {
-	create_mapping_late(__pa(__init_begin), (unsigned long)__init_begin,
-			(unsigned long)__init_end - (unsigned long)__init_begin,
-			PAGE_KERNEL);
+	/*
+	 * Unmap the __init region but leave the VM area in place. This
+	 * prevents the region from being reused for kernel modules, which
+	 * is not supported by kallsyms.
+	 */
+	unmap_kernel_range((u64)__init_begin, (u64)(__init_end - __init_begin));
+}
+
+static void __init map_kernel_chunk(pgd_t *pgd, void *va_start, void *va_end,
+				    pgprot_t prot, struct vm_struct *vma)
+{
+	phys_addr_t pa_start = __pa(va_start);
+	unsigned long size = va_end - va_start;
+
+	BUG_ON(!PAGE_ALIGNED(pa_start));
+	BUG_ON(!PAGE_ALIGNED(size));
+
+	__create_pgd_mapping(pgd, pa_start, (unsigned long)va_start, size, prot,
+			     early_pgtable_alloc);
+
+	vma->addr	= va_start;
+	vma->phys_addr	= pa_start;
+	vma->size	= size;
+	vma->flags	= VM_MAP;
+	vma->caller	= __builtin_return_address(0);
+
+	vm_area_add_early(vma);
+}
+
+/*
+ * Create fine-grained mappings for the kernel.
+ */
+static void __init map_kernel(pgd_t *pgd)
+{
+	static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_init, vmlinux_data;
+
+	map_kernel_chunk(pgd, _stext, _etext, PAGE_KERNEL_EXEC, &vmlinux_text);
+	map_kernel_chunk(pgd, __start_rodata, __init_begin, PAGE_KERNEL, &vmlinux_rodata);
+	map_kernel_chunk(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC,
+			 &vmlinux_init);
+	map_kernel_chunk(pgd, _data, _end, PAGE_KERNEL, &vmlinux_data);
+
+	if (!pgd_val(*pgd_offset_raw(pgd, FIXADDR_START))) {
+		/*
+		 * The fixmap falls in a separate pgd to the kernel, and doesn't
+		 * live in the carveout for the swapper_pg_dir. We can simply
+		 * re-use the existing dir for the fixmap.
+		 */
+		set_pgd(pgd_offset_raw(pgd, FIXADDR_START),
+			*pgd_offset_k(FIXADDR_START));
+	} else if (CONFIG_PGTABLE_LEVELS > 3) {
+		/*
+		 * The fixmap shares its top level pgd entry with the kernel
+		 * mapping. This can really only occur when we are running
+		 * with 16k/4 levels, so we can simply reuse the pud level
+		 * entry instead.
+		 */
+		BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
+		set_pud(pud_set_fixmap_offset(pgd, FIXADDR_START),
+			__pud(__pa(bm_pmd) | PUD_TYPE_TABLE));
+		pud_clear_fixmap();
+	} else {
+		BUG();
+	}
+
+	kasan_copy_shadow(pgd);
 }
 
 /*
@@ -444,28 +537,38 @@
  */
 void __init paging_init(void)
 {
-	void *zero_page;
+	phys_addr_t pgd_phys = early_pgtable_alloc();
+	pgd_t *pgd = pgd_set_fixmap(pgd_phys);
 
-	map_mem();
-	fixup_executable();
+	map_kernel(pgd);
+	map_mem(pgd);
 
-	/* allocate the zero page. */
-	zero_page = early_alloc(PAGE_SIZE);
+	/*
+	 * We want to reuse the original swapper_pg_dir so we don't have to
+	 * communicate the new address to non-coherent secondaries in
+	 * secondary_entry, and so cpu_switch_mm can generate the address with
+	 * adrp+add rather than a load from some global variable.
+	 *
+	 * To do this we need to go via a temporary pgd.
+	 */
+	cpu_replace_ttbr1(__va(pgd_phys));
+	memcpy(swapper_pg_dir, pgd, PAGE_SIZE);
+	cpu_replace_ttbr1(swapper_pg_dir);
 
-	bootmem_init();
-
-	empty_zero_page = virt_to_page(zero_page);
+	pgd_clear_fixmap();
+	memblock_free(pgd_phys, PAGE_SIZE);
 
 	/* Ensure the zero page is visible to the page table walker */
 	dsb(ishst);
 
 	/*
-	 * TTBR0 is only used for the identity mapping at this stage. Make it
-	 * point to zero page to avoid speculatively fetching new entries.
+	 * We only reuse the PGD from the swapper_pg_dir, not the pud + pmd
+	 * allocated with it.
 	 */
-	cpu_set_reserved_ttbr0();
-	local_flush_tlb_all();
-	cpu_set_default_tcr_t0sz();
+	memblock_free(__pa(swapper_pg_dir) + PAGE_SIZE,
+		      SWAPPER_DIR_SIZE - PAGE_SIZE);
+
+	bootmem_init();
 }
 
 /*
@@ -552,21 +655,13 @@
 }
 #endif	/* CONFIG_SPARSEMEM_VMEMMAP */
 
-static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
-#if CONFIG_PGTABLE_LEVELS > 2
-static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
-#endif
-#if CONFIG_PGTABLE_LEVELS > 3
-static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
-#endif
-
 static inline pud_t * fixmap_pud(unsigned long addr)
 {
 	pgd_t *pgd = pgd_offset_k(addr);
 
 	BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd));
 
-	return pud_offset(pgd, addr);
+	return pud_offset_kimg(pgd, addr);
 }
 
 static inline pmd_t * fixmap_pmd(unsigned long addr)
@@ -575,16 +670,12 @@
 
 	BUG_ON(pud_none(*pud) || pud_bad(*pud));
 
-	return pmd_offset(pud, addr);
+	return pmd_offset_kimg(pud, addr);
 }
 
 static inline pte_t * fixmap_pte(unsigned long addr)
 {
-	pmd_t *pmd = fixmap_pmd(addr);
-
-	BUG_ON(pmd_none(*pmd) || pmd_bad(*pmd));
-
-	return pte_offset_kernel(pmd, addr);
+	return &bm_pte[pte_index(addr)];
 }
 
 void __init early_fixmap_init(void)
@@ -595,15 +686,26 @@
 	unsigned long addr = FIXADDR_START;
 
 	pgd = pgd_offset_k(addr);
-	pgd_populate(&init_mm, pgd, bm_pud);
-	pud = pud_offset(pgd, addr);
+	if (CONFIG_PGTABLE_LEVELS > 3 &&
+	    !(pgd_none(*pgd) || pgd_page_paddr(*pgd) == __pa(bm_pud))) {
+		/*
+		 * We only end up here if the kernel mapping and the fixmap
+		 * share the top level pgd entry, which should only happen on
+		 * 16k/4 levels configurations.
+		 */
+		BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
+		pud = pud_offset_kimg(pgd, addr);
+	} else {
+		pgd_populate(&init_mm, pgd, bm_pud);
+		pud = fixmap_pud(addr);
+	}
 	pud_populate(&init_mm, pud, bm_pmd);
-	pmd = pmd_offset(pud, addr);
+	pmd = fixmap_pmd(addr);
 	pmd_populate_kernel(&init_mm, pmd, bm_pte);
 
 	/*
 	 * The boot-ioremap range spans multiple pmds, for which
-	 * we are not preparted:
+	 * we are not prepared:
 	 */
 	BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
 		     != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
@@ -642,19 +744,18 @@
 	}
 }
 
-void *__init fixmap_remap_fdt(phys_addr_t dt_phys)
+void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
 {
 	const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
-	pgprot_t prot = PAGE_KERNEL_RO;
-	int size, offset;
+	int offset;
 	void *dt_virt;
 
 	/*
 	 * Check whether the physical FDT address is set and meets the minimum
 	 * alignment requirement. Since we are relying on MIN_FDT_ALIGN to be
-	 * at least 8 bytes so that we can always access the size field of the
-	 * FDT header after mapping the first chunk, double check here if that
-	 * is indeed the case.
+	 * at least 8 bytes so that we can always access the magic and size
+	 * fields of the FDT header after mapping the first chunk, double check
+	 * here if that is indeed the case.
 	 */
 	BUILD_BUG_ON(MIN_FDT_ALIGN < 8);
 	if (!dt_phys || dt_phys % MIN_FDT_ALIGN)
@@ -663,7 +764,7 @@
 	/*
 	 * Make sure that the FDT region can be mapped without the need to
 	 * allocate additional translation table pages, so that it is safe
-	 * to call create_mapping() this early.
+	 * to call create_mapping_noalloc() this early.
 	 *
 	 * On 64k pages, the FDT will be mapped using PTEs, so we need to
 	 * be in the same PMD as the rest of the fixmap.
@@ -679,21 +780,73 @@
 	dt_virt = (void *)dt_virt_base + offset;
 
 	/* map the first chunk so we can read the size from the header */
-	create_mapping(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
-		       SWAPPER_BLOCK_SIZE, prot);
+	create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
+			dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
 
-	if (fdt_check_header(dt_virt) != 0)
+	if (fdt_magic(dt_virt) != FDT_MAGIC)
 		return NULL;
 
-	size = fdt_totalsize(dt_virt);
-	if (size > MAX_FDT_SIZE)
+	*size = fdt_totalsize(dt_virt);
+	if (*size > MAX_FDT_SIZE)
 		return NULL;
 
-	if (offset + size > SWAPPER_BLOCK_SIZE)
-		create_mapping(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
-			       round_up(offset + size, SWAPPER_BLOCK_SIZE), prot);
-
-	memblock_reserve(dt_phys, size);
+	if (offset + *size > SWAPPER_BLOCK_SIZE)
+		create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
+			       round_up(offset + *size, SWAPPER_BLOCK_SIZE), prot);
 
 	return dt_virt;
 }
+
+void *__init fixmap_remap_fdt(phys_addr_t dt_phys)
+{
+	void *dt_virt;
+	int size;
+
+	dt_virt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO);
+	if (!dt_virt)
+		return NULL;
+
+	memblock_reserve(dt_phys, size);
+	return dt_virt;
+}
+
+int __init arch_ioremap_pud_supported(void)
+{
+	/* only 4k granule supports level 1 block mappings */
+	return IS_ENABLED(CONFIG_ARM64_4K_PAGES);
+}
+
+int __init arch_ioremap_pmd_supported(void)
+{
+	return 1;
+}
+
+int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot)
+{
+	BUG_ON(phys & ~PUD_MASK);
+	set_pud(pud, __pud(phys | PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))));
+	return 1;
+}
+
+int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot)
+{
+	BUG_ON(phys & ~PMD_MASK);
+	set_pmd(pmd, __pmd(phys | PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))));
+	return 1;
+}
+
+int pud_clear_huge(pud_t *pud)
+{
+	if (!pud_sect(*pud))
+		return 0;
+	pud_clear(pud);
+	return 1;
+}
+
+int pmd_clear_huge(pmd_t *pmd)
+{
+	if (!pmd_sect(*pmd))
+		return 0;
+	pmd_clear(pmd);
+	return 1;
+}
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index cf62407..ca6d268 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -36,29 +37,14 @@
 	return 0;
 }
 
-static int change_memory_common(unsigned long addr, int numpages,
+/*
+ * This function assumes that the range is mapped with PAGE_SIZE pages.
+ */
+static int __change_memory_common(unsigned long start, unsigned long size,
 				pgprot_t set_mask, pgprot_t clear_mask)
 {
-	unsigned long start = addr;
-	unsigned long size = PAGE_SIZE*numpages;
-	unsigned long end = start + size;
-	int ret;
 	struct page_change_data data;
-
-	if (!PAGE_ALIGNED(addr)) {
-		start &= PAGE_MASK;
-		end = start + size;
-		WARN_ON_ONCE(1);
-	}
-
-	if (start < MODULES_VADDR || start >= MODULES_END)
-		return -EINVAL;
-
-	if (end < MODULES_VADDR || end >= MODULES_END)
-		return -EINVAL;
-
-	if (!numpages)
-		return 0;
+	int ret;
 
 	data.set_mask = set_mask;
 	data.clear_mask = clear_mask;
@@ -66,10 +52,49 @@
 	ret = apply_to_page_range(&init_mm, start, size, change_page_range,
 					&data);
 
-	flush_tlb_kernel_range(start, end);
+	flush_tlb_kernel_range(start, start + size);
 	return ret;
 }
 
+static int change_memory_common(unsigned long addr, int numpages,
+				pgprot_t set_mask, pgprot_t clear_mask)
+{
+	unsigned long start = addr;
+	unsigned long size = PAGE_SIZE*numpages;
+	unsigned long end = start + size;
+	struct vm_struct *area;
+
+	if (!PAGE_ALIGNED(addr)) {
+		start &= PAGE_MASK;
+		end = start + size;
+		WARN_ON_ONCE(1);
+	}
+
+	/*
+	 * Kernel VA mappings are always live, and splitting live section
+	 * mappings into page mappings may cause TLB conflicts. This means
+	 * we have to ensure that changing the permission bits of the range
+	 * we are operating on does not result in such splitting.
+	 *
+	 * Let's restrict ourselves to mappings created by vmalloc (or vmap).
+	 * Those are guaranteed to consist entirely of page mappings, and
+	 * splitting is never needed.
+	 *
+	 * So check whether the [addr, addr + size) interval is entirely
+	 * covered by precisely one VM area that has the VM_ALLOC flag set.
+	 */
+	area = find_vm_area((void *)addr);
+	if (!area ||
+	    end > (unsigned long)area->addr + area->size ||
+	    !(area->flags & VM_ALLOC))
+		return -EINVAL;
+
+	if (!numpages)
+		return 0;
+
+	return __change_memory_common(start, size, set_mask, clear_mask);
+}
+
 int set_memory_ro(unsigned long addr, int numpages)
 {
 	return change_memory_common(addr, numpages,
@@ -99,3 +124,19 @@
 					__pgprot(PTE_PXN));
 }
 EXPORT_SYMBOL_GPL(set_memory_x);
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void __kernel_map_pages(struct page *page, int numpages, int enable)
+{
+	unsigned long addr = (unsigned long) page_address(page);
+
+	if (enable)
+		__change_memory_common(addr, PAGE_SIZE * numpages,
+					__pgprot(PTE_VALID),
+					__pgprot(0));
+	else
+		__change_memory_common(addr, PAGE_SIZE * numpages,
+					__pgprot(0),
+					__pgprot(PTE_VALID));
+}
+#endif
diff --git a/arch/arm64/mm/pgd.c b/arch/arm64/mm/pgd.c
index cb3ba1b..ae11d4e 100644
--- a/arch/arm64/mm/pgd.c
+++ b/arch/arm64/mm/pgd.c
@@ -46,14 +46,14 @@
 		kmem_cache_free(pgd_cache, pgd);
 }
 
-static int __init pgd_cache_init(void)
+void __init pgd_cache_init(void)
 {
+	if (PGD_SIZE == PAGE_SIZE)
+		return;
+
 	/*
 	 * Naturally aligned pgds required by the architecture.
 	 */
-	if (PGD_SIZE != PAGE_SIZE)
-		pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE,
-					      SLAB_PANIC, NULL);
-	return 0;
+	pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE,
+				      SLAB_PANIC, NULL);
 }
-core_initcall(pgd_cache_init);
diff --git a/arch/arm64/mm/proc-macros.S b/arch/arm64/mm/proc-macros.S
deleted file mode 100644
index d69dfff..0000000
--- a/arch/arm64/mm/proc-macros.S
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Based on arch/arm/mm/proc-macros.S
- *
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-
-/*
- * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
- */
-	.macro	vma_vm_mm, rd, rn
-	ldr	\rd, [\rn, #VMA_VM_MM]
-	.endm
-
-/*
- * mmid - get context id from mm pointer (mm->context.id)
- */
-	.macro	mmid, rd, rn
-	ldr	\rd, [\rn, #MM_CONTEXT_ID]
-	.endm
-
-/*
- * dcache_line_size - get the minimum D-cache line size from the CTR register.
- */
-	.macro	dcache_line_size, reg, tmp
-	mrs	\tmp, ctr_el0			// read CTR
-	ubfm	\tmp, \tmp, #16, #19		// cache line size encoding
-	mov	\reg, #4			// bytes per word
-	lsl	\reg, \reg, \tmp		// actual cache line size
-	.endm
-
-/*
- * icache_line_size - get the minimum I-cache line size from the CTR register.
- */
-	.macro	icache_line_size, reg, tmp
-	mrs	\tmp, ctr_el0			// read CTR
-	and	\tmp, \tmp, #0xf		// cache line size encoding
-	mov	\reg, #4			// bytes per word
-	lsl	\reg, \reg, \tmp		// actual cache line size
-	.endm
-
-/*
- * tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map
- */
-	.macro	tcr_set_idmap_t0sz, valreg, tmpreg
-#ifndef CONFIG_ARM64_VA_BITS_48
-	ldr_l	\tmpreg, idmap_t0sz
-	bfi	\valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH
-#endif
-	.endm
-
-/*
- * reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present
- */
-	.macro	reset_pmuserenr_el0, tmpreg
-	mrs	\tmpreg, id_aa64dfr0_el1	// Check ID_AA64DFR0_EL1 PMUVer
-	sbfx	\tmpreg, \tmpreg, #8, #4
-	cmp	\tmpreg, #1			// Skip if no PMU present
-	b.lt	9000f
-	msr	pmuserenr_el0, xzr		// Disable PMU access from EL0
-9000:
-	.endm
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index b8f04b3..85a542b 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -23,10 +23,9 @@
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/hwcap.h>
-#include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
-
-#include "proc-macros.S"
+#include <asm/cpufeature.h>
+#include <asm/alternative.h>
 
 #ifdef CONFIG_ARM64_64K_PAGES
 #define TCR_TG_FLAGS	TCR_TG0_64K | TCR_TG1_64K
@@ -137,10 +136,37 @@
 	bfi	x0, x1, #48, #16		// set the ASID
 	msr	ttbr0_el1, x0			// set TTBR0
 	isb
+	post_ttbr0_update_workaround
 	ret
 ENDPROC(cpu_do_switch_mm)
 
-	.section ".text.init", #alloc, #execinstr
+	.pushsection ".idmap.text", "ax"
+/*
+ * void idmap_cpu_replace_ttbr1(phys_addr_t new_pgd)
+ *
+ * This is the low-level counterpart to cpu_replace_ttbr1, and should not be
+ * called by anything else. It can only be executed from a TTBR0 mapping.
+ */
+ENTRY(idmap_cpu_replace_ttbr1)
+	mrs	x2, daif
+	msr	daifset, #0xf
+
+	adrp	x1, empty_zero_page
+	msr	ttbr1_el1, x1
+	isb
+
+	tlbi	vmalle1
+	dsb	nsh
+	isb
+
+	msr	ttbr1_el1, x0
+	isb
+
+	msr	daif, x2
+
+	ret
+ENDPROC(idmap_cpu_replace_ttbr1)
+	.popsection
 
 /*
  *	__cpu_setup
@@ -156,6 +182,8 @@
 	msr	cpacr_el1, x0			// Enable FP/ASIMD
 	mov	x0, #1 << 12			// Reset mdscr_el1 and disable
 	msr	mdscr_el1, x0			// access to the DCC from EL0
+	isb					// Unmask debug exceptions now,
+	enable_dbg				// since this is per-cpu
 	reset_pmuserenr_el0 x0			// Disable PMU access from EL0
 	/*
 	 * Memory region attributes for LPAE:
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index b162ad7..6297140 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -728,14 +728,14 @@
 		int ret;
 
 		ret = build_insn(insn, ctx);
-
-		if (ctx->image == NULL)
-			ctx->offset[i] = ctx->idx;
-
 		if (ret > 0) {
 			i++;
+			if (ctx->image == NULL)
+				ctx->offset[i] = ctx->idx;
 			continue;
 		}
+		if (ctx->image == NULL)
+			ctx->offset[i] = ctx->idx;
 		if (ret)
 			return ret;
 	}
diff --git a/arch/arm64/xen/hypercall.S b/arch/arm64/xen/hypercall.S
index 8bbe940..b96db5d 100644
--- a/arch/arm64/xen/hypercall.S
+++ b/arch/arm64/xen/hypercall.S
@@ -49,6 +49,7 @@
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/uaccess.h>
 #include <xen/interface/xen.h>
 
 
@@ -89,6 +90,20 @@
 	mov x2, x3
 	mov x3, x4
 	mov x4, x5
+	/*
+	 * Privcmd calls are issued by the userspace. The kernel needs to
+	 * enable access to TTBR0_EL1 as the hypervisor would issue stage 1
+	 * translations to user memory via AT instructions. Since AT
+	 * instructions are not affected by the PAN bit (ARMv8.1), we only
+	 * need the explicit uaccess_enable/disable if the TTBR0 PAN emulation
+	 * is enabled (it implies that hardware UAO and PAN disabled).
+	 */
+	uaccess_ttbr0_enable x6, x7
 	hvc XEN_IMM
+
+	/*
+	 * Disable userspace access from kernel once the hyp call completed.
+	 */
+	uaccess_ttbr0_disable x6
 	ret
 ENDPROC(privcmd_call);
diff --git a/arch/avr32/include/asm/uaccess.h b/arch/avr32/include/asm/uaccess.h
index 68cf638..b1ec1fa 100644
--- a/arch/avr32/include/asm/uaccess.h
+++ b/arch/avr32/include/asm/uaccess.h
@@ -74,7 +74,7 @@
 
 extern __kernel_size_t copy_to_user(void __user *to, const void *from,
 				    __kernel_size_t n);
-extern __kernel_size_t copy_from_user(void *to, const void __user *from,
+extern __kernel_size_t ___copy_from_user(void *to, const void __user *from,
 				      __kernel_size_t n);
 
 static inline __kernel_size_t __copy_to_user(void __user *to, const void *from,
@@ -88,6 +88,15 @@
 {
 	return __copy_user(to, (const void __force *)from, n);
 }
+static inline __kernel_size_t copy_from_user(void *to,
+					       const void __user *from,
+					       __kernel_size_t n)
+{
+	size_t res = ___copy_from_user(to, from, n);
+	if (unlikely(res))
+		memset(to + (n - res), 0, res);
+	return res;
+}
 
 #define __copy_to_user_inatomic __copy_to_user
 #define __copy_from_user_inatomic __copy_from_user
diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c
index d93ead0..7c6cf14 100644
--- a/arch/avr32/kernel/avr32_ksyms.c
+++ b/arch/avr32/kernel/avr32_ksyms.c
@@ -36,7 +36,7 @@
 /*
  * Userspace access stuff.
  */
-EXPORT_SYMBOL(copy_from_user);
+EXPORT_SYMBOL(___copy_from_user);
 EXPORT_SYMBOL(copy_to_user);
 EXPORT_SYMBOL(__copy_user);
 EXPORT_SYMBOL(strncpy_from_user);
diff --git a/arch/avr32/lib/copy_user.S b/arch/avr32/lib/copy_user.S
index ea59c04..0753734 100644
--- a/arch/avr32/lib/copy_user.S
+++ b/arch/avr32/lib/copy_user.S
@@ -23,13 +23,13 @@
 	 */
 	.text
 	.align	1
-	.global	copy_from_user
-	.type	copy_from_user, @function
-copy_from_user:
+	.global	___copy_from_user
+	.type	___copy_from_user, @function
+___copy_from_user:
 	branch_if_kernel r8, __copy_user
 	ret_if_privileged r8, r11, r10, r10
 	rjmp	__copy_user
-	.size	copy_from_user, . - copy_from_user
+	.size	___copy_from_user, . - ___copy_from_user
 
 	.global	copy_to_user
 	.type	copy_to_user, @function
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index 4f61378..4561281 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -435,7 +435,7 @@
 	struct resource *regs;
 	struct pio_device *pio;
 
-	if (pdev->id > MAX_NR_PIO_DEVICES) {
+	if (pdev->id >= MAX_NR_PIO_DEVICES) {
 		dev_err(&pdev->dev, "only %d PIO devices supported\n",
 			MAX_NR_PIO_DEVICES);
 		return;
diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h
index 90612a7..8cd0184 100644
--- a/arch/blackfin/include/asm/uaccess.h
+++ b/arch/blackfin/include/asm/uaccess.h
@@ -177,11 +177,12 @@
 static inline unsigned long __must_check
 copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-	if (access_ok(VERIFY_READ, from, n))
+	if (likely(access_ok(VERIFY_READ, from, n))) {
 		memcpy(to, (const void __force *)from, n);
-	else
-		return n;
-	return 0;
+		return 0;
+	}
+	memset(to, 0, n);
+	return n;
 }
 
 static inline unsigned long __must_check
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index c6db52b..10c5777 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -146,7 +146,8 @@
 #include <linux/smc91x.h>
 
 static struct smc91x_platdata smc91x_info = {
-	.flags = SMC91X_USE_32BIT | SMC91X_NOWAIT,
+	.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
+		 SMC91X_NOWAIT,
 	.leda = RPC_LED_100_10,
 	.ledb = RPC_LED_TX_RX,
 };
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 2de71e8..93c2246 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -134,7 +134,8 @@
 #include <linux/smc91x.h>
 
 static struct smc91x_platdata smc91x_info = {
-	.flags = SMC91X_USE_32BIT | SMC91X_NOWAIT,
+	.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
+		 SMC91X_NOWAIT,
 	.leda = RPC_LED_100_10,
 	.ledb = RPC_LED_TX_RX,
 };
diff --git a/arch/c6x/kernel/ptrace.c b/arch/c6x/kernel/ptrace.c
index 3c494e8..a511ac1 100644
--- a/arch/c6x/kernel/ptrace.c
+++ b/arch/c6x/kernel/ptrace.c
@@ -69,46 +69,6 @@
 				   0, sizeof(*regs));
 }
 
-static int gpr_set(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   const void *kbuf, const void __user *ubuf)
-{
-	int ret;
-	struct pt_regs *regs = task_pt_regs(target);
-
-	/* Don't copyin TSR or CSR */
-	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &regs,
-				 0, PT_TSR * sizeof(long));
-	if (ret)
-		return ret;
-
-	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
-					PT_TSR * sizeof(long),
-					(PT_TSR + 1) * sizeof(long));
-	if (ret)
-		return ret;
-
-	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &regs,
-				 (PT_TSR + 1) * sizeof(long),
-				 PT_CSR * sizeof(long));
-	if (ret)
-		return ret;
-
-	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
-					PT_CSR * sizeof(long),
-					(PT_CSR + 1) * sizeof(long));
-	if (ret)
-		return ret;
-
-	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &regs,
-				 (PT_CSR + 1) * sizeof(long), -1);
-	return ret;
-}
-
 enum c6x_regset {
 	REGSET_GPR,
 };
@@ -120,7 +80,6 @@
 		.size = sizeof(u32),
 		.align = sizeof(u32),
 		.get = gpr_get,
-		.set = gpr_set
 	},
 };
 
diff --git a/arch/cris/boot/rescue/Makefile b/arch/cris/boot/rescue/Makefile
index 52bd0bd..d98edbb 100644
--- a/arch/cris/boot/rescue/Makefile
+++ b/arch/cris/boot/rescue/Makefile
@@ -10,6 +10,9 @@
 
 asflags-y += $(LINUXINCLUDE)
 ccflags-y += -O2 $(LINUXINCLUDE)
+
+ifdef CONFIG_ETRAX_AXISFLASHMAP
+
 arch-$(CONFIG_ETRAX_ARCH_V10) = v10
 arch-$(CONFIG_ETRAX_ARCH_V32) = v32
 
@@ -28,6 +31,11 @@
 	$(call if_changed,objcopy)
 	cp -p $(obj)/rescue.bin $(objtree)
 
+else
+$(obj)/rescue.bin:
+
+endif
+
 $(obj)/testrescue.bin: $(obj)/testrescue.o
 	$(OBJCOPY) $(OBJCOPYFLAGS) $(obj)/testrescue.o tr.bin
 # Pad it to 784 bytes
diff --git a/arch/cris/include/asm/uaccess.h b/arch/cris/include/asm/uaccess.h
index e3530d0..56c7d57 100644
--- a/arch/cris/include/asm/uaccess.h
+++ b/arch/cris/include/asm/uaccess.h
@@ -194,30 +194,6 @@
 extern unsigned long __copy_user_zeroing(void *to, const void __user *from, unsigned long n);
 extern unsigned long __do_clear_user(void __user *to, unsigned long n);
 
-static inline unsigned long
-__generic_copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-	if (access_ok(VERIFY_WRITE, to, n))
-		return __copy_user(to, from, n);
-	return n;
-}
-
-static inline unsigned long
-__generic_copy_from_user(void *to, const void __user *from, unsigned long n)
-{
-	if (access_ok(VERIFY_READ, from, n))
-		return __copy_user_zeroing(to, from, n);
-	return n;
-}
-
-static inline unsigned long
-__generic_clear_user(void __user *to, unsigned long n)
-{
-	if (access_ok(VERIFY_WRITE, to, n))
-		return __do_clear_user(to, n);
-	return n;
-}
-
 static inline long
 __strncpy_from_user(char *dst, const char __user *src, long count)
 {
@@ -282,7 +258,7 @@
 	else if (n == 24)
 		__asm_copy_from_user_24(to, from, ret);
 	else
-		ret = __generic_copy_from_user(to, from, n);
+		ret = __copy_user_zeroing(to, from, n);
 
 	return ret;
 }
@@ -333,7 +309,7 @@
 	else if (n == 24)
 		__asm_copy_to_user_24(to, from, ret);
 	else
-		ret = __generic_copy_to_user(to, from, n);
+		ret = __copy_user(to, from, n);
 
 	return ret;
 }
@@ -366,26 +342,43 @@
 	else if (n == 24)
 		__asm_clear_24(to, ret);
 	else
-		ret = __generic_clear_user(to, n);
+		ret = __do_clear_user(to, n);
 
 	return ret;
 }
 
 
-#define clear_user(to, n)				\
-	(__builtin_constant_p(n) ?			\
-	 __constant_clear_user(to, n) :			\
-	 __generic_clear_user(to, n))
+static inline size_t clear_user(void __user *to, size_t n)
+{
+	if (unlikely(!access_ok(VERIFY_WRITE, to, n)))
+		return n;
+	if (__builtin_constant_p(n))
+		return __constant_clear_user(to, n);
+	else
+		return __do_clear_user(to, n);
+}
 
-#define copy_from_user(to, from, n)			\
-	(__builtin_constant_p(n) ?			\
-	 __constant_copy_from_user(to, from, n) :	\
-	 __generic_copy_from_user(to, from, n))
+static inline size_t copy_from_user(void *to, const void __user *from, size_t n)
+{
+	if (unlikely(!access_ok(VERIFY_READ, from, n))) {
+		memset(to, 0, n);
+		return n;
+	}
+	if (__builtin_constant_p(n))
+		return __constant_copy_from_user(to, from, n);
+	else
+		return __copy_user_zeroing(to, from, n);
+}
 
-#define copy_to_user(to, from, n)			\
-	(__builtin_constant_p(n) ?			\
-	 __constant_copy_to_user(to, from, n) :		\
-	 __generic_copy_to_user(to, from, n))
+static inline size_t copy_to_user(void __user *to, const void *from, size_t n)
+{
+	if (unlikely(!access_ok(VERIFY_WRITE, to, n)))
+		return n;
+	if (__builtin_constant_p(n))
+		return __constant_copy_to_user(to, from, n);
+	else
+		return __copy_user(to, from, n);
+}
 
 /* We let the __ versions of copy_from/to_user inline, because they're often
  * used in fast paths and have only a small space overhead.
diff --git a/arch/frv/include/asm/uaccess.h b/arch/frv/include/asm/uaccess.h
index 3ac9a59..87d9e34 100644
--- a/arch/frv/include/asm/uaccess.h
+++ b/arch/frv/include/asm/uaccess.h
@@ -263,19 +263,25 @@
 extern long __memset_user(void *dst, unsigned long count);
 extern long __memcpy_user(void *dst, const void *src, unsigned long count);
 
-#define clear_user(dst,count)			__memset_user(____force(dst), (count))
+#define __clear_user(dst,count)			__memset_user(____force(dst), (count))
 #define __copy_from_user_inatomic(to, from, n)	__memcpy_user((to), ____force(from), (n))
 #define __copy_to_user_inatomic(to, from, n)	__memcpy_user(____force(to), (from), (n))
 
 #else
 
-#define clear_user(dst,count)			(memset(____force(dst), 0, (count)), 0)
+#define __clear_user(dst,count)			(memset(____force(dst), 0, (count)), 0)
 #define __copy_from_user_inatomic(to, from, n)	(memcpy((to), ____force(from), (n)), 0)
 #define __copy_to_user_inatomic(to, from, n)	(memcpy(____force(to), (from), (n)), 0)
 
 #endif
 
-#define __clear_user clear_user
+static inline unsigned long __must_check
+clear_user(void __user *to, unsigned long n)
+{
+	if (likely(__access_ok(to, n)))
+		n = __clear_user(to, n);
+	return n;
+}
 
 static inline unsigned long __must_check
 __copy_to_user(void __user *to, const void *from, unsigned long n)
diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c
index 836f147..efa59f1 100644
--- a/arch/frv/mm/elf-fdpic.c
+++ b/arch/frv/mm/elf-fdpic.c
@@ -74,7 +74,7 @@
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma(current->mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			goto success;
 	}
 
diff --git a/arch/h8300/include/asm/thread_info.h b/arch/h8300/include/asm/thread_info.h
index b408fe6..3cef068 100644
--- a/arch/h8300/include/asm/thread_info.h
+++ b/arch/h8300/include/asm/thread_info.h
@@ -31,7 +31,6 @@
 	int		   cpu;			/* cpu we're on */
 	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
 	mm_segment_t		addr_limit;
-	struct restart_block restart_block;
 };
 
 /*
@@ -44,9 +43,6 @@
 	.cpu =		0,			\
 	.preempt_count = INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
-	.restart_block	= {			\
-		.fn = do_no_restart_syscall,	\
-	},					\
 }
 
 #define init_thread_info	(init_thread_union.thread_info)
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index 9207554..0dc1c8f 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -95,7 +95,8 @@
 	long *reg = (long *)&regs;
 
 	/* build user regs in buffer */
-	for (r = 0; r < ARRAY_SIZE(register_offset); r++)
+	BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0);
+	for (r = 0; r < sizeof(regs) / sizeof(long); r++)
 		*reg++ = h8300_get_reg(target, r);
 
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
@@ -113,7 +114,8 @@
 	long *reg;
 
 	/* build user regs in buffer */
-	for (reg = (long *)&regs, r = 0; r < ARRAY_SIZE(register_offset); r++)
+	BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0);
+	for (reg = (long *)&regs, r = 0; r < sizeof(regs) / sizeof(long); r++)
 		*reg++ = h8300_get_reg(target, r);
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
@@ -122,7 +124,7 @@
 		return ret;
 
 	/* write back to pt_regs */
-	for (reg = (long *)&regs, r = 0; r < ARRAY_SIZE(register_offset); r++)
+	for (reg = (long *)&regs, r = 0; r < sizeof(regs) / sizeof(long); r++)
 		h8300_put_reg(target, r, *reg++);
 	return 0;
 }
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 380fffd..036ad04 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -79,7 +79,7 @@
 	unsigned int er0;
 
 	/* Always make any pending restarted system calls return -EINTR */
-	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+	current->restart_block.fn = do_no_restart_syscall;
 
 	/* restore passed registers */
 #define COPY(r)  do { err |= get_user(regs->r, &usc->sc_##r); } while (0)
diff --git a/arch/hexagon/include/asm/uaccess.h b/arch/hexagon/include/asm/uaccess.h
index f000a38..f61cfb2 100644
--- a/arch/hexagon/include/asm/uaccess.h
+++ b/arch/hexagon/include/asm/uaccess.h
@@ -103,7 +103,8 @@
 {
 	long res = __strnlen_user(src, n);
 
-	/* return from strnlen can't be zero -- that would be rubbish. */
+	if (unlikely(!res))
+		return -EFAULT;
 
 	if (res > n) {
 		copy_from_user(dst, src, n);
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 970d0bd..648f1ce 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -95,8 +95,8 @@
   echo '* unwcheck	- Check vmlinux for invalid unwind info'
 endef
 
-archprepare: make_nr_irqs_h FORCE
+archprepare: make_nr_irqs_h
 PHONY += make_nr_irqs_h FORCE
 
-make_nr_irqs_h: FORCE
+make_nr_irqs_h:
 	$(Q)$(MAKE) $(build)=arch/ia64/kernel include/generated/nr-irqs.h
diff --git a/arch/ia64/include/asm/early_ioremap.h b/arch/ia64/include/asm/early_ioremap.h
new file mode 100644
index 0000000..eec9e1d
--- /dev/null
+++ b/arch/ia64/include/asm/early_ioremap.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_IA64_EARLY_IOREMAP_H
+#define _ASM_IA64_EARLY_IOREMAP_H
+
+extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
+#define early_memremap(phys_addr, size)        early_ioremap(phys_addr, size)
+
+extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
+#define early_memunmap(addr, size)             early_iounmap(addr, size)
+
+#endif
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index 8fdb9c7..5de673a 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -20,6 +20,7 @@
  */
 
 #include <asm/unaligned.h>
+#include <asm/early_ioremap.h>
 
 /* We don't use IO slowdowns on the ia64, but.. */
 #define __SLOW_DOWN_IO	do { } while (0)
@@ -427,10 +428,6 @@
 extern void __iomem * ioremap(unsigned long offset, unsigned long size);
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap (volatile void __iomem *addr);
-extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
-#define early_memremap(phys_addr, size)        early_ioremap(phys_addr, size)
-extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
-#define early_memunmap(addr, size)             early_iounmap(addr, size)
 static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size)
 {
 	return ioremap(phys_addr, size);
diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h
index 4f3fb6cc..40c2027 100644
--- a/arch/ia64/include/asm/uaccess.h
+++ b/arch/ia64/include/asm/uaccess.h
@@ -263,17 +263,15 @@
 	__cu_len;									\
 })
 
-#define copy_from_user(to, from, n)							\
-({											\
-	void *__cu_to = (to);								\
-	const void __user *__cu_from = (from);						\
-	long __cu_len = (n);								\
-											\
-	__chk_user_ptr(__cu_from);							\
-	if (__access_ok(__cu_from, __cu_len, get_fs()))					\
-		__cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len);	\
-	__cu_len;									\
-})
+static inline unsigned long
+copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	if (likely(__access_ok(from, n, get_fs())))
+		n = __copy_user((__force void __user *) to, from, n);
+	else
+		memset(to, 0, n);
+	return n;
+}
 
 #define __copy_in_user(to, from, size)	__copy_user((to), (from), (size))
 
diff --git a/arch/m32r/include/asm/uaccess.h b/arch/m32r/include/asm/uaccess.h
index cac7014..6f89821 100644
--- a/arch/m32r/include/asm/uaccess.h
+++ b/arch/m32r/include/asm/uaccess.h
@@ -219,7 +219,7 @@
 #define __get_user_nocheck(x, ptr, size)				\
 ({									\
 	long __gu_err = 0;						\
-	unsigned long __gu_val;						\
+	unsigned long __gu_val = 0;					\
 	might_fault();							\
 	__get_user_size(__gu_val, (ptr), (size), __gu_err);		\
 	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
diff --git a/arch/m68k/include/asm/delay.h b/arch/m68k/include/asm/delay.h
index d28fa8f..c598d84 100644
--- a/arch/m68k/include/asm/delay.h
+++ b/arch/m68k/include/asm/delay.h
@@ -114,6 +114,6 @@
  */
 #define	HZSCALE		(268435456 / (1000000 / HZ))
 
-#define ndelay(n) __delay(DIV_ROUND_UP((n) * ((((HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6), 1000));
+#define ndelay(n) __delay(DIV_ROUND_UP((n) * ((((HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6), 1000))
 
 #endif /* defined(_M68K_DELAY_H) */
diff --git a/arch/metag/include/asm/atomic.h b/arch/metag/include/asm/atomic.h
index 470e365..8ff0a70 100644
--- a/arch/metag/include/asm/atomic.h
+++ b/arch/metag/include/asm/atomic.h
@@ -39,11 +39,10 @@
 #define atomic_dec(v) atomic_sub(1, (v))
 
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+#define atomic_dec_if_positive(v)       atomic_sub_if_positive(1, v)
 
 #endif
 
-#define atomic_dec_if_positive(v)       atomic_sub_if_positive(1, v)
-
 #include <asm-generic/atomic64.h>
 
 #endif /* __ASM_METAG_ATOMIC_H */
diff --git a/arch/metag/include/asm/atomic_lnkget.h b/arch/metag/include/asm/atomic_lnkget.h
index a625818..88fa25f 100644
--- a/arch/metag/include/asm/atomic_lnkget.h
+++ b/arch/metag/include/asm/atomic_lnkget.h
@@ -61,7 +61,7 @@
 		"	CMPT	%0, #HI(0x02000000)\n"			\
 		"	BNZ 1b\n"					\
 		: "=&d" (temp), "=&da" (result)				\
-		: "da" (&v->counter), "bd" (i)				\
+		: "da" (&v->counter), "br" (i)				\
 		: "cc");						\
 									\
 	smp_mb();							\
diff --git a/arch/metag/include/asm/cmpxchg_lnkget.h b/arch/metag/include/asm/cmpxchg_lnkget.h
index 0154e28..2369ad3 100644
--- a/arch/metag/include/asm/cmpxchg_lnkget.h
+++ b/arch/metag/include/asm/cmpxchg_lnkget.h
@@ -73,7 +73,7 @@
 		      "	DCACHE	[%2], %0\n"
 #endif
 		      "2:\n"
-		      : "=&d" (temp), "=&da" (retval)
+		      : "=&d" (temp), "=&d" (retval)
 		      : "da" (m), "bd" (old), "da" (new)
 		      : "cc"
 		      );
diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h
index 8282cbc..3db3812 100644
--- a/arch/metag/include/asm/uaccess.h
+++ b/arch/metag/include/asm/uaccess.h
@@ -28,24 +28,32 @@
 
 #define segment_eq(a, b)	((a).seg == (b).seg)
 
-#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
-/*
- * Explicitly allow NULL pointers here. Parts of the kernel such
- * as readv/writev use access_ok to validate pointers, but want
- * to allow NULL pointers for various reasons. NULL pointers are
- * safe to allow through because the first page is not mappable on
- * Meta.
- *
- * We also wish to avoid letting user code access the system area
- * and the kernel half of the address space.
- */
-#define __user_bad(addr, size) (((addr) > 0 && (addr) < META_MEMORY_BASE) || \
-				((addr) > PAGE_OFFSET &&		\
-				 (addr) < LINCORE_BASE))
-
 static inline int __access_ok(unsigned long addr, unsigned long size)
 {
-	return __kernel_ok || !__user_bad(addr, size);
+	/*
+	 * Allow access to the user mapped memory area, but not the system area
+	 * before it. The check extends to the top of the address space when
+	 * kernel access is allowed (there's no real reason to user copy to the
+	 * system area in any case).
+	 */
+	if (likely(addr >= META_MEMORY_BASE && addr < get_fs().seg &&
+		   size <= get_fs().seg - addr))
+		return true;
+	/*
+	 * Explicitly allow NULL pointers here. Parts of the kernel such
+	 * as readv/writev use access_ok to validate pointers, but want
+	 * to allow NULL pointers for various reasons. NULL pointers are
+	 * safe to allow through because the first page is not mappable on
+	 * Meta.
+	 */
+	if (!addr)
+		return true;
+	/* Allow access to core code memory area... */
+	if (addr >= LINCORE_CODE_BASE && addr <= LINCORE_CODE_LIMIT &&
+	    size <= LINCORE_CODE_LIMIT + 1 - addr)
+		return true;
+	/* ... but no other areas. */
+	return false;
 }
 
 #define access_ok(type, addr, size) __access_ok((unsigned long)(addr),	\
@@ -186,8 +194,13 @@
 extern long __must_check __strncpy_from_user(char *dst, const char __user *src,
 					     long count);
 
-#define strncpy_from_user(dst, src, count) __strncpy_from_user(dst, src, count)
-
+static inline long
+strncpy_from_user(char *dst, const char __user *src, long count)
+{
+	if (!access_ok(VERIFY_READ, src, 1))
+		return -EFAULT;
+	return __strncpy_from_user(dst, src, count);
+}
 /*
  * Return the size of a string (including the ending 0)
  *
@@ -197,19 +210,21 @@
 
 #define strlen_user(str) strnlen_user(str, 32767)
 
-extern unsigned long __must_check __copy_user_zeroing(void *to,
-						      const void __user *from,
-						      unsigned long n);
+extern unsigned long raw_copy_from_user(void *to, const void __user *from,
+					unsigned long n);
 
 static inline unsigned long
 copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-	if (access_ok(VERIFY_READ, from, n))
-		return __copy_user_zeroing(to, from, n);
-	return n;
+	unsigned long res = n;
+	if (likely(access_ok(VERIFY_READ, from, n)))
+		res = raw_copy_from_user(to, from, n);
+	if (unlikely(res))
+		memset(to + (n - res), 0, res);
+	return res;
 }
 
-#define __copy_from_user(to, from, n) __copy_user_zeroing(to, from, n)
+#define __copy_from_user(to, from, n) raw_copy_from_user(to, from, n)
 #define __copy_from_user_inatomic __copy_from_user
 
 extern unsigned long __must_check __copy_user(void __user *to,
diff --git a/arch/metag/kernel/ptrace.c b/arch/metag/kernel/ptrace.c
index 7563628..5e2dc7d 100644
--- a/arch/metag/kernel/ptrace.c
+++ b/arch/metag/kernel/ptrace.c
@@ -24,6 +24,16 @@
  * user_regset definitions.
  */
 
+static unsigned long user_txstatus(const struct pt_regs *regs)
+{
+	unsigned long data = (unsigned long)regs->ctx.Flags;
+
+	if (regs->ctx.SaveMask & TBICTX_CBUF_BIT)
+		data |= USER_GP_REGS_STATUS_CATCH_BIT;
+
+	return data;
+}
+
 int metag_gp_regs_copyout(const struct pt_regs *regs,
 			  unsigned int pos, unsigned int count,
 			  void *kbuf, void __user *ubuf)
@@ -62,9 +72,7 @@
 	if (ret)
 		goto out;
 	/* TXSTATUS */
-	data = (unsigned long)regs->ctx.Flags;
-	if (regs->ctx.SaveMask & TBICTX_CBUF_BIT)
-		data |= USER_GP_REGS_STATUS_CATCH_BIT;
+	data = user_txstatus(regs);
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				  &data, 4*25, 4*26);
 	if (ret)
@@ -119,6 +127,7 @@
 	if (ret)
 		goto out;
 	/* TXSTATUS */
+	data = user_txstatus(regs);
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				 &data, 4*25, 4*26);
 	if (ret)
@@ -244,6 +253,8 @@
 	unsigned long long *ptr;
 	int ret, i;
 
+	if (count < 4*13)
+		return -EINVAL;
 	/* Read the entire pipeline before making any changes */
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				 &rp, 0, 4*13);
@@ -303,7 +314,7 @@
 			const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	void __user *tls;
+	void __user *tls = target->thread.tls_ptr;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
 	if (ret)
diff --git a/arch/metag/lib/usercopy.c b/arch/metag/lib/usercopy.c
index b3ebfe9..2792fc6 100644
--- a/arch/metag/lib/usercopy.c
+++ b/arch/metag/lib/usercopy.c
@@ -29,7 +29,6 @@
 		COPY						 \
 		"1:\n"						 \
 		"	.section .fixup,\"ax\"\n"		 \
-		"	MOV D1Ar1,#0\n"				 \
 		FIXUP						 \
 		"	MOVT    D1Ar1,#HI(1b)\n"		 \
 		"	JUMP    D1Ar1,#LO(1b)\n"		 \
@@ -260,27 +259,31 @@
 		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
 		"22:\n"							\
 		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
-		"SUB	%3, %3, #32\n"					\
 		"23:\n"							\
-		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
+		"SUB	%3, %3, #32\n"					\
 		"24:\n"							\
+		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
+		"25:\n"							\
 		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
+		"26:\n"							\
 		"SUB	%3, %3, #32\n"					\
 		"DCACHE	[%1+#-64], D0Ar6\n"				\
 		"BR	$Lloop"id"\n"					\
 									\
 		"MOV	RAPF, %1\n"					\
-		"25:\n"							\
-		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
-		"26:\n"							\
-		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
-		"SUB	%3, %3, #32\n"					\
 		"27:\n"							\
 		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
 		"28:\n"							\
 		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
-		"SUB	%0, %0, #8\n"					\
 		"29:\n"							\
+		"SUB	%3, %3, #32\n"					\
+		"30:\n"							\
+		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
+		"31:\n"							\
+		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
+		"32:\n"							\
+		"SUB	%0, %0, #8\n"					\
+		"33:\n"							\
 		"SETL	[%0++], D0.7, D1.7\n"				\
 		"SUB	%3, %3, #32\n"					\
 		"1:"							\
@@ -312,11 +315,15 @@
 		"	.long 26b,3b\n"					\
 		"	.long 27b,3b\n"					\
 		"	.long 28b,3b\n"					\
-		"	.long 29b,4b\n"					\
+		"	.long 29b,3b\n"					\
+		"	.long 30b,3b\n"					\
+		"	.long 31b,3b\n"					\
+		"	.long 32b,3b\n"					\
+		"	.long 33b,4b\n"					\
 		"	.previous\n"					\
 		: "=r" (to), "=r" (from), "=r" (ret), "=d" (n)		\
 		: "0" (to), "1" (from), "2" (ret), "3" (n)		\
-		: "D1Ar1", "D0Ar2", "memory")
+		: "D1Ar1", "D0Ar2", "cc", "memory")
 
 /*	rewind 'to' and 'from'  pointers when a fault occurs
  *
@@ -342,7 +349,7 @@
 #define __asm_copy_to_user_64bit_rapf_loop(to,	from, ret, n, id)\
 	__asm_copy_user_64bit_rapf_loop(to, from, ret, n, id,		\
 		"LSR	D0Ar2, D0Ar2, #8\n"				\
-		"AND	D0Ar2, D0Ar2, #0x7\n"				\
+		"ANDS	D0Ar2, D0Ar2, #0x7\n"				\
 		"ADDZ	D0Ar2, D0Ar2, #4\n"				\
 		"SUB	D0Ar2, D0Ar2, #1\n"				\
 		"MOV	D1Ar1, #4\n"					\
@@ -403,47 +410,55 @@
 		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
 		"22:\n"							\
 		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
-		"SUB	%3, %3, #16\n"					\
 		"23:\n"							\
-		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
-		"24:\n"							\
-		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
 		"SUB	%3, %3, #16\n"					\
-		"25:\n"							\
+		"24:\n"							\
 		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
-		"26:\n"							\
+		"25:\n"							\
 		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
+		"26:\n"							\
 		"SUB	%3, %3, #16\n"					\
 		"27:\n"							\
 		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
 		"28:\n"							\
 		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
+		"29:\n"							\
+		"SUB	%3, %3, #16\n"					\
+		"30:\n"							\
+		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
+		"31:\n"							\
+		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
+		"32:\n"							\
 		"SUB	%3, %3, #16\n"					\
 		"DCACHE	[%1+#-64], D0Ar6\n"				\
 		"BR	$Lloop"id"\n"					\
 									\
 		"MOV	RAPF, %1\n"					\
-		"29:\n"							\
-		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
-		"30:\n"							\
-		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
-		"SUB	%3, %3, #16\n"					\
-		"31:\n"							\
-		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
-		"32:\n"							\
-		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
-		"SUB	%3, %3, #16\n"					\
 		"33:\n"							\
 		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
 		"34:\n"							\
 		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
-		"SUB	%3, %3, #16\n"					\
 		"35:\n"							\
-		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
+		"SUB	%3, %3, #16\n"					\
 		"36:\n"							\
-		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
-		"SUB	%0, %0, #4\n"					\
+		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
 		"37:\n"							\
+		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
+		"38:\n"							\
+		"SUB	%3, %3, #16\n"					\
+		"39:\n"							\
+		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
+		"40:\n"							\
+		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
+		"41:\n"							\
+		"SUB	%3, %3, #16\n"					\
+		"42:\n"							\
+		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
+		"43:\n"							\
+		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
+		"44:\n"							\
+		"SUB	%0, %0, #4\n"					\
+		"45:\n"							\
 		"SETD	[%0++], D0.7\n"					\
 		"SUB	%3, %3, #16\n"					\
 		"1:"							\
@@ -483,11 +498,19 @@
 		"	.long 34b,3b\n"					\
 		"	.long 35b,3b\n"					\
 		"	.long 36b,3b\n"					\
-		"	.long 37b,4b\n"					\
+		"	.long 37b,3b\n"					\
+		"	.long 38b,3b\n"					\
+		"	.long 39b,3b\n"					\
+		"	.long 40b,3b\n"					\
+		"	.long 41b,3b\n"					\
+		"	.long 42b,3b\n"					\
+		"	.long 43b,3b\n"					\
+		"	.long 44b,3b\n"					\
+		"	.long 45b,4b\n"					\
 		"	.previous\n"					\
 		: "=r" (to), "=r" (from), "=r" (ret), "=d" (n)		\
 		: "0" (to), "1" (from), "2" (ret), "3" (n)		\
-		: "D1Ar1", "D0Ar2", "memory")
+		: "D1Ar1", "D0Ar2", "cc", "memory")
 
 /*	rewind 'to' and 'from'  pointers when a fault occurs
  *
@@ -513,7 +536,7 @@
 #define __asm_copy_to_user_32bit_rapf_loop(to, from, ret, n, id)\
 	__asm_copy_user_32bit_rapf_loop(to, from, ret, n, id,		\
 		"LSR	D0Ar2, D0Ar2, #8\n"				\
-		"AND	D0Ar2, D0Ar2, #0x7\n"				\
+		"ANDS	D0Ar2, D0Ar2, #0x7\n"				\
 		"ADDZ	D0Ar2, D0Ar2, #4\n"				\
 		"SUB	D0Ar2, D0Ar2, #1\n"				\
 		"MOV	D1Ar1, #4\n"					\
@@ -538,23 +561,31 @@
 	if ((unsigned long) src & 1) {
 		__asm_copy_to_user_1(dst, src, retn);
 		n--;
+		if (retn)
+			return retn + n;
 	}
 	if ((unsigned long) dst & 1) {
 		/* Worst case - byte copy */
 		while (n > 0) {
 			__asm_copy_to_user_1(dst, src, retn);
 			n--;
+			if (retn)
+				return retn + n;
 		}
 	}
 	if (((unsigned long) src & 2) && n >= 2) {
 		__asm_copy_to_user_2(dst, src, retn);
 		n -= 2;
+		if (retn)
+			return retn + n;
 	}
 	if ((unsigned long) dst & 2) {
 		/* Second worst case - word copy */
 		while (n >= 2) {
 			__asm_copy_to_user_2(dst, src, retn);
 			n -= 2;
+			if (retn)
+				return retn + n;
 		}
 	}
 
@@ -569,6 +600,8 @@
 		while (n >= 8) {
 			__asm_copy_to_user_8x64(dst, src, retn);
 			n -= 8;
+			if (retn)
+				return retn + n;
 		}
 	}
 	if (n >= RAPF_MIN_BUF_SIZE) {
@@ -581,6 +614,8 @@
 		while (n >= 8) {
 			__asm_copy_to_user_8x64(dst, src, retn);
 			n -= 8;
+			if (retn)
+				return retn + n;
 		}
 	}
 #endif
@@ -588,11 +623,15 @@
 	while (n >= 16) {
 		__asm_copy_to_user_16(dst, src, retn);
 		n -= 16;
+		if (retn)
+			return retn + n;
 	}
 
 	while (n >= 4) {
 		__asm_copy_to_user_4(dst, src, retn);
 		n -= 4;
+		if (retn)
+			return retn + n;
 	}
 
 	switch (n) {
@@ -609,6 +648,10 @@
 		break;
 	}
 
+	/*
+	 * If we get here, retn correctly reflects the number of failing
+	 * bytes.
+	 */
 	return retn;
 }
 EXPORT_SYMBOL(__copy_user);
@@ -617,16 +660,14 @@
 	__asm_copy_user_cont(to, from, ret,	\
 		"	GETB D1Ar1,[%1++]\n"	\
 		"2:	SETB [%0++],D1Ar1\n",	\
-		"3:	ADD  %2,%2,#1\n"	\
-		"	SETB [%0++],D1Ar1\n",	\
+		"3:	ADD  %2,%2,#1\n",	\
 		"	.long 2b,3b\n")
 
 #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_user_cont(to, from, ret,		\
 		"	GETW D1Ar1,[%1++]\n"		\
 		"2:	SETW [%0++],D1Ar1\n" COPY,	\
-		"3:	ADD  %2,%2,#2\n"		\
-		"	SETW [%0++],D1Ar1\n" FIXUP,	\
+		"3:	ADD  %2,%2,#2\n" FIXUP,		\
 		"	.long 2b,3b\n" TENTRY)
 
 #define __asm_copy_from_user_2(to, from, ret) \
@@ -636,145 +677,26 @@
 	__asm_copy_from_user_2x_cont(to, from, ret,	\
 		"	GETB D1Ar1,[%1++]\n"		\
 		"4:	SETB [%0++],D1Ar1\n",		\
-		"5:	ADD  %2,%2,#1\n"		\
-		"	SETB [%0++],D1Ar1\n",		\
+		"5:	ADD  %2,%2,#1\n",		\
 		"	.long 4b,5b\n")
 
 #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_user_cont(to, from, ret,		\
 		"	GETD D1Ar1,[%1++]\n"		\
 		"2:	SETD [%0++],D1Ar1\n" COPY,	\
-		"3:	ADD  %2,%2,#4\n"		\
-		"	SETD [%0++],D1Ar1\n" FIXUP,	\
+		"3:	ADD  %2,%2,#4\n" FIXUP,		\
 		"	.long 2b,3b\n" TENTRY)
 
 #define __asm_copy_from_user_4(to, from, ret) \
 	__asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
 
-#define __asm_copy_from_user_5(to, from, ret) \
-	__asm_copy_from_user_4x_cont(to, from, ret,	\
-		"	GETB D1Ar1,[%1++]\n"		\
-		"4:	SETB [%0++],D1Ar1\n",		\
-		"5:	ADD  %2,%2,#1\n"		\
-		"	SETB [%0++],D1Ar1\n",		\
-		"	.long 4b,5b\n")
-
-#define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
-	__asm_copy_from_user_4x_cont(to, from, ret,	\
-		"	GETW D1Ar1,[%1++]\n"		\
-		"4:	SETW [%0++],D1Ar1\n" COPY,	\
-		"5:	ADD  %2,%2,#2\n"		\
-		"	SETW [%0++],D1Ar1\n" FIXUP,	\
-		"	.long 4b,5b\n" TENTRY)
-
-#define __asm_copy_from_user_6(to, from, ret) \
-	__asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_7(to, from, ret) \
-	__asm_copy_from_user_6x_cont(to, from, ret,	\
-		"	GETB D1Ar1,[%1++]\n"		\
-		"6:	SETB [%0++],D1Ar1\n",		\
-		"7:	ADD  %2,%2,#1\n"		\
-		"	SETB [%0++],D1Ar1\n",		\
-		"	.long 6b,7b\n")
-
-#define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
-	__asm_copy_from_user_4x_cont(to, from, ret,	\
-		"	GETD D1Ar1,[%1++]\n"		\
-		"4:	SETD [%0++],D1Ar1\n" COPY,	\
-		"5:	ADD  %2,%2,#4\n"			\
-		"	SETD [%0++],D1Ar1\n" FIXUP,		\
-		"	.long 4b,5b\n" TENTRY)
-
-#define __asm_copy_from_user_8(to, from, ret) \
-	__asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_9(to, from, ret) \
-	__asm_copy_from_user_8x_cont(to, from, ret,	\
-		"	GETB D1Ar1,[%1++]\n"		\
-		"6:	SETB [%0++],D1Ar1\n",		\
-		"7:	ADD  %2,%2,#1\n"		\
-		"	SETB [%0++],D1Ar1\n",		\
-		"	.long 6b,7b\n")
-
-#define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
-	__asm_copy_from_user_8x_cont(to, from, ret,	\
-		"	GETW D1Ar1,[%1++]\n"		\
-		"6:	SETW [%0++],D1Ar1\n" COPY,	\
-		"7:	ADD  %2,%2,#2\n"		\
-		"	SETW [%0++],D1Ar1\n" FIXUP,	\
-		"	.long 6b,7b\n" TENTRY)
-
-#define __asm_copy_from_user_10(to, from, ret) \
-	__asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_11(to, from, ret)		\
-	__asm_copy_from_user_10x_cont(to, from, ret,	\
-		"	GETB D1Ar1,[%1++]\n"		\
-		"8:	SETB [%0++],D1Ar1\n",		\
-		"9:	ADD  %2,%2,#1\n"		\
-		"	SETB [%0++],D1Ar1\n",		\
-		"	.long 8b,9b\n")
-
-#define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
-	__asm_copy_from_user_8x_cont(to, from, ret,	\
-		"	GETD D1Ar1,[%1++]\n"		\
-		"6:	SETD [%0++],D1Ar1\n" COPY,	\
-		"7:	ADD  %2,%2,#4\n"		\
-		"	SETD [%0++],D1Ar1\n" FIXUP,	\
-		"	.long 6b,7b\n" TENTRY)
-
-#define __asm_copy_from_user_12(to, from, ret) \
-	__asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_13(to, from, ret) \
-	__asm_copy_from_user_12x_cont(to, from, ret,	\
-		"	GETB D1Ar1,[%1++]\n"		\
-		"8:	SETB [%0++],D1Ar1\n",		\
-		"9:	ADD  %2,%2,#1\n"		\
-		"	SETB [%0++],D1Ar1\n",		\
-		"	.long 8b,9b\n")
-
-#define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
-	__asm_copy_from_user_12x_cont(to, from, ret,	\
-		"	GETW D1Ar1,[%1++]\n"		\
-		"8:	SETW [%0++],D1Ar1\n" COPY,	\
-		"9:	ADD  %2,%2,#2\n"		\
-		"	SETW [%0++],D1Ar1\n" FIXUP,	\
-		"	.long 8b,9b\n" TENTRY)
-
-#define __asm_copy_from_user_14(to, from, ret) \
-	__asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_15(to, from, ret) \
-	__asm_copy_from_user_14x_cont(to, from, ret,	\
-		"	GETB D1Ar1,[%1++]\n"		\
-		"10:	SETB [%0++],D1Ar1\n",		\
-		"11:	ADD  %2,%2,#1\n"		\
-		"	SETB [%0++],D1Ar1\n",		\
-		"	.long 10b,11b\n")
-
-#define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
-	__asm_copy_from_user_12x_cont(to, from, ret,	\
-		"	GETD D1Ar1,[%1++]\n"		\
-		"8:	SETD [%0++],D1Ar1\n" COPY,	\
-		"9:	ADD  %2,%2,#4\n"		\
-		"	SETD [%0++],D1Ar1\n" FIXUP,	\
-		"	.long 8b,9b\n" TENTRY)
-
-#define __asm_copy_from_user_16(to, from, ret) \
-	__asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
-
 #define __asm_copy_from_user_8x64(to, from, ret) \
 	asm volatile (				\
 		"	GETL D0Ar2,D1Ar1,[%1++]\n"	\
 		"2:	SETL [%0++],D0Ar2,D1Ar1\n"	\
 		"1:\n"					\
 		"	.section .fixup,\"ax\"\n"	\
-		"	MOV D1Ar1,#0\n"			\
-		"	MOV D0Ar2,#0\n"			\
 		"3:	ADD  %2,%2,#8\n"		\
-		"	SETL [%0++],D0Ar2,D1Ar1\n"	\
 		"	MOVT    D0Ar2,#HI(1b)\n"	\
 		"	JUMP    D0Ar2,#LO(1b)\n"	\
 		"	.previous\n"			\
@@ -789,36 +711,57 @@
  *
  *	Rationale:
  *		A fault occurs while reading from user buffer, which is the
- *		source. Since the fault is at a single address, we only
- *		need to rewind by 8 bytes.
+ *		source.
  *		Since we don't write to kernel buffer until we read first,
  *		the kernel buffer is at the right state and needn't be
- *		corrected.
+ *		corrected, but the source must be rewound to the beginning of
+ *		the block, which is LSM_STEP*8 bytes.
+ *		LSM_STEP is bits 10:8 in TXSTATUS which is already read
+ *		and stored in D0Ar2
+ *
+ *		NOTE: If a fault occurs at the last operation in M{G,S}ETL
+ *			LSM_STEP will be 0. ie: we do 4 writes in our case, if
+ *			a fault happens at the 4th write, LSM_STEP will be 0
+ *			instead of 4. The code copes with that.
  */
 #define __asm_copy_from_user_64bit_rapf_loop(to, from, ret, n, id)	\
 	__asm_copy_user_64bit_rapf_loop(to, from, ret, n, id,		\
-		"SUB	%1, %1, #8\n")
+		"LSR	D0Ar2, D0Ar2, #5\n"				\
+		"ANDS	D0Ar2, D0Ar2, #0x38\n"				\
+		"ADDZ	D0Ar2, D0Ar2, #32\n"				\
+		"SUB	%1, %1, D0Ar2\n")
 
 /*	rewind 'from' pointer when a fault occurs
  *
  *	Rationale:
  *		A fault occurs while reading from user buffer, which is the
- *		source. Since the fault is at a single address, we only
- *		need to rewind by 4 bytes.
+ *		source.
  *		Since we don't write to kernel buffer until we read first,
  *		the kernel buffer is at the right state and needn't be
- *		corrected.
+ *		corrected, but the source must be rewound to the beginning of
+ *		the block, which is LSM_STEP*4 bytes.
+ *		LSM_STEP is bits 10:8 in TXSTATUS which is already read
+ *		and stored in D0Ar2
+ *
+ *		NOTE: If a fault occurs at the last operation in M{G,S}ETL
+ *			LSM_STEP will be 0. ie: we do 4 writes in our case, if
+ *			a fault happens at the 4th write, LSM_STEP will be 0
+ *			instead of 4. The code copes with that.
  */
 #define __asm_copy_from_user_32bit_rapf_loop(to, from, ret, n, id)	\
 	__asm_copy_user_32bit_rapf_loop(to, from, ret, n, id,		\
-		"SUB	%1, %1, #4\n")
+		"LSR	D0Ar2, D0Ar2, #6\n"				\
+		"ANDS	D0Ar2, D0Ar2, #0x1c\n"				\
+		"ADDZ	D0Ar2, D0Ar2, #16\n"				\
+		"SUB	%1, %1, D0Ar2\n")
 
 
-/* Copy from user to kernel, zeroing the bytes that were inaccessible in
-   userland.  The return-value is the number of bytes that were
-   inaccessible.  */
-unsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
-				  unsigned long n)
+/*
+ * Copy from user to kernel. The return-value is the number of bytes that were
+ * inaccessible.
+ */
+unsigned long raw_copy_from_user(void *pdst, const void __user *psrc,
+				 unsigned long n)
 {
 	register char *dst asm ("A0.2") = pdst;
 	register const char __user *src asm ("A1.2") = psrc;
@@ -830,6 +773,8 @@
 	if ((unsigned long) src & 1) {
 		__asm_copy_from_user_1(dst, src, retn);
 		n--;
+		if (retn)
+			return retn + n;
 	}
 	if ((unsigned long) dst & 1) {
 		/* Worst case - byte copy */
@@ -837,12 +782,14 @@
 			__asm_copy_from_user_1(dst, src, retn);
 			n--;
 			if (retn)
-				goto copy_exception_bytes;
+				return retn + n;
 		}
 	}
 	if (((unsigned long) src & 2) && n >= 2) {
 		__asm_copy_from_user_2(dst, src, retn);
 		n -= 2;
+		if (retn)
+			return retn + n;
 	}
 	if ((unsigned long) dst & 2) {
 		/* Second worst case - word copy */
@@ -850,16 +797,10 @@
 			__asm_copy_from_user_2(dst, src, retn);
 			n -= 2;
 			if (retn)
-				goto copy_exception_bytes;
+				return retn + n;
 		}
 	}
 
-	/* We only need one check after the unalignment-adjustments,
-	   because if both adjustments were done, either both or
-	   neither reference had an exception.  */
-	if (retn != 0)
-		goto copy_exception_bytes;
-
 #ifdef USE_RAPF
 	/* 64 bit copy loop */
 	if (!(((unsigned long) src | (unsigned long) dst) & 7)) {
@@ -872,7 +813,7 @@
 			__asm_copy_from_user_8x64(dst, src, retn);
 			n -= 8;
 			if (retn)
-				goto copy_exception_bytes;
+				return retn + n;
 		}
 	}
 
@@ -888,7 +829,7 @@
 			__asm_copy_from_user_8x64(dst, src, retn);
 			n -= 8;
 			if (retn)
-				goto copy_exception_bytes;
+				return retn + n;
 		}
 	}
 #endif
@@ -898,7 +839,7 @@
 		n -= 4;
 
 		if (retn)
-			goto copy_exception_bytes;
+			return retn + n;
 	}
 
 	/* If we get here, there were no memory read faults.  */
@@ -924,21 +865,8 @@
 	/* If we get here, retn correctly reflects the number of failing
 	   bytes.  */
 	return retn;
-
- copy_exception_bytes:
-	/* We already have "retn" bytes cleared, and need to clear the
-	   remaining "n" bytes.  A non-optimized simple byte-for-byte in-line
-	   memset is preferred here, since this isn't speed-critical code and
-	   we'd rather have this a leaf-function than calling memset.  */
-	{
-		char *endp;
-		for (endp = dst + n; dst < endp; dst++)
-			*dst = 0;
-	}
-
-	return retn + n;
 }
-EXPORT_SYMBOL(__copy_user_zeroing);
+EXPORT_SYMBOL(raw_copy_from_user);
 
 #define __asm_clear_8x64(to, ret) \
 	asm volatile (					\
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index 331b0d3..8266767 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -227,7 +227,7 @@
 
 #define __get_user(x, ptr)						\
 ({									\
-	unsigned long __gu_val;						\
+	unsigned long __gu_val = 0;					\
 	/*unsigned long __gu_ptr = (unsigned long)(ptr);*/		\
 	long __gu_err;							\
 	switch (sizeof(*(ptr))) {					\
@@ -373,10 +373,13 @@
 static inline long copy_from_user(void *to,
 		const void __user *from, unsigned long n)
 {
+	unsigned long res = n;
 	might_fault();
-	if (access_ok(VERIFY_READ, from, n))
-		return __copy_from_user(to, from, n);
-	return n;
+	if (likely(access_ok(VERIFY_READ, from, n)))
+		res = __copy_from_user(to, from, n);
+	if (unlikely(res))
+		memset(to + (n - res), 0, res);
+	return res;
 }
 
 #define __copy_to_user(to, from, n)	\
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index db45961..8b0424a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -9,6 +9,7 @@
 	select HAVE_CONTEXT_TRACKING
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_IDE
+	select HAVE_IRQ_EXIT_ON_IRQ_STACK
 	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
@@ -1463,7 +1464,7 @@
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_MSA
 	select GENERIC_CSUM
-	select MIPS_O32_FP64_SUPPORT if MIPS32_O32
+	select MIPS_O32_FP64_SUPPORT if 32BIT || MIPS32_O32
 	help
 	  Choose this option to build a kernel for release 6 or later of the
 	  MIPS64 architecture.  New MIPS processors, starting with the Warrior
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index f0e314c..7f975b2 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -113,42 +113,6 @@
 	help
 	  Add several files to the debugfs to test spinlock speed.
 
-if CPU_MIPSR6
-
-choice
-	prompt "Compact branch policy"
-	default MIPS_COMPACT_BRANCHES_OPTIMAL
-
-config MIPS_COMPACT_BRANCHES_NEVER
-	bool "Never (force delay slot branches)"
-	help
-	  Pass the -mcompact-branches=never flag to the compiler in order to
-	  force it to always emit branches with delay slots, and make no use
-	  of the compact branch instructions introduced by MIPSr6. This is
-	  useful if you suspect there may be an issue with compact branches in
-	  either the compiler or the CPU.
-
-config MIPS_COMPACT_BRANCHES_OPTIMAL
-	bool "Optimal (use where beneficial)"
-	help
-	  Pass the -mcompact-branches=optimal flag to the compiler in order for
-	  it to make use of compact branch instructions where it deems them
-	  beneficial, and use branches with delay slots elsewhere. This is the
-	  default compiler behaviour, and should be used unless you have a
-	  reason to choose otherwise.
-
-config MIPS_COMPACT_BRANCHES_ALWAYS
-	bool "Always (force compact branches)"
-	help
-	  Pass the -mcompact-branches=always flag to the compiler in order to
-	  force it to always emit compact branches, making no use of branch
-	  instructions with delay slots. This can result in more compact code
-	  which may be beneficial in some scenarios.
-
-endchoice
-
-endif # CPU_MIPSR6
-
 config SCACHE_DEBUGFS
 	bool "L2 cache debugfs entries"
 	depends on DEBUG_FS
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 3f70ba5..252e347 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -204,10 +204,6 @@
 cflags-$(toolchain-msa)			+= -DTOOLCHAIN_SUPPORTS_MSA
 endif
 
-cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER)	+= -mcompact-branches=never
-cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL)	+= -mcompact-branches=optimal
-cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_ALWAYS)	+= -mcompact-branches=always
-
 #
 # Firmware support
 #
diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c
index 3cedd1f..8ae4067 100644
--- a/arch/mips/ath79/common.c
+++ b/arch/mips/ath79/common.c
@@ -76,14 +76,14 @@
 {
 	BUG_ON(!ath79_ddr_pci_win_base);
 
-	__raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0);
-	__raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 1);
-	__raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 2);
-	__raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 3);
-	__raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 4);
-	__raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 5);
-	__raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 6);
-	__raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 7);
+	__raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0x0);
+	__raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 0x4);
+	__raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 0x8);
+	__raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 0xc);
+	__raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 0x10);
+	__raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 0x14);
+	__raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 0x18);
+	__raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 0x1c);
 }
 EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows);
 
diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c
index b955faf..d1adc59 100644
--- a/arch/mips/ath79/early_printk.c
+++ b/arch/mips/ath79/early_printk.c
@@ -31,13 +31,15 @@
 	} while (1);
 }
 
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
 static void prom_putchar_ar71xx(unsigned char ch)
 {
 	void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
 
-	prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
+	prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
 	__raw_writel(ch, base + UART_TX * 4);
-	prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
+	prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
 }
 
 static void prom_putchar_ar933x(unsigned char ch)
diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c
index 52caa75..e2f50d6 100644
--- a/arch/mips/bcm47xx/buttons.c
+++ b/arch/mips/bcm47xx/buttons.c
@@ -17,6 +17,12 @@
 		.active_low	= 1,					\
 	}
 
+#define BCM47XX_GPIO_KEY_H(_gpio, _code)				\
+	{								\
+		.code		= _code,				\
+		.gpio		= _gpio,				\
+	}
+
 /* Asus */
 
 static const struct gpio_keys_button
@@ -79,8 +85,8 @@
 
 static const struct gpio_keys_button
 bcm47xx_buttons_asus_wl500w[] __initconst = {
-	BCM47XX_GPIO_KEY(6, KEY_RESTART),
-	BCM47XX_GPIO_KEY(7, KEY_WPS_BUTTON),
+	BCM47XX_GPIO_KEY_H(6, KEY_RESTART),
+	BCM47XX_GPIO_KEY_H(7, KEY_WPS_BUTTON),
 };
 
 static const struct gpio_keys_button
diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S
index 64e08df..8b70041 100644
--- a/arch/mips/cavium-octeon/octeon-memcpy.S
+++ b/arch/mips/cavium-octeon/octeon-memcpy.S
@@ -208,18 +208,18 @@
 	ADD	src, src, 16*NBYTES
 EXC(	STORE	t3, UNIT(7)(dst),	s_exc_p9u)
 	ADD	dst, dst, 16*NBYTES
-EXC(	LOAD	t0, UNIT(-8)(src),	l_exc_copy)
-EXC(	LOAD	t1, UNIT(-7)(src),	l_exc_copy)
-EXC(	LOAD	t2, UNIT(-6)(src),	l_exc_copy)
-EXC(	LOAD	t3, UNIT(-5)(src),	l_exc_copy)
+EXC(	LOAD	t0, UNIT(-8)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t1, UNIT(-7)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t2, UNIT(-6)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t3, UNIT(-5)(src),	l_exc_copy_rewind16)
 EXC(	STORE	t0, UNIT(-8)(dst),	s_exc_p8u)
 EXC(	STORE	t1, UNIT(-7)(dst),	s_exc_p7u)
 EXC(	STORE	t2, UNIT(-6)(dst),	s_exc_p6u)
 EXC(	STORE	t3, UNIT(-5)(dst),	s_exc_p5u)
-EXC(	LOAD	t0, UNIT(-4)(src),	l_exc_copy)
-EXC(	LOAD	t1, UNIT(-3)(src),	l_exc_copy)
-EXC(	LOAD	t2, UNIT(-2)(src),	l_exc_copy)
-EXC(	LOAD	t3, UNIT(-1)(src),	l_exc_copy)
+EXC(	LOAD	t0, UNIT(-4)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t1, UNIT(-3)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t2, UNIT(-2)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t3, UNIT(-1)(src),	l_exc_copy_rewind16)
 EXC(	STORE	t0, UNIT(-4)(dst),	s_exc_p4u)
 EXC(	STORE	t1, UNIT(-3)(dst),	s_exc_p3u)
 EXC(	STORE	t2, UNIT(-2)(dst),	s_exc_p2u)
@@ -383,6 +383,10 @@
 	 nop
 	END(memcpy)
 
+l_exc_copy_rewind16:
+	/* Rewind src and dst by 16*NBYTES for l_exc_copy */
+	SUB	src, src, 16*NBYTES
+	SUB	dst, dst, 16*NBYTES
 l_exc_copy:
 	/*
 	 * Copy bytes from src until faulting load address (or until a
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 57ed466..2f140d7 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -68,8 +68,8 @@
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 48e16d9..b155084 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -134,7 +134,7 @@
 CONFIG_SCSI_QLOGIC_1280=y
 CONFIG_SCSI_PMCRAID=m
 CONFIG_SCSI_BFA_FC=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
 CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_HP_SW=m
 CONFIG_SCSI_DH_EMC=m
@@ -206,7 +206,6 @@
 # CONFIG_MLX4_DEBUG is not set
 CONFIG_TEHUTI=m
 CONFIG_BNX2X=m
-CONFIG_QLGE=m
 CONFIG_SFC=m
 CONFIG_BE2NET=m
 CONFIG_LIBERTAS_THINFIRM=m
diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig
index 004cf52..c24b878 100644
--- a/arch/mips/configs/lemote2f_defconfig
+++ b/arch/mips/configs/lemote2f_defconfig
@@ -39,7 +39,7 @@
 CONFIG_PM_STD_PARTITION="/dev/hda3"
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEBUG=y
-CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT=y
 CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=m
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 5afb484..739ccd0 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -59,8 +59,8 @@
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig
index 98f1387..47f4ecf 100644
--- a/arch/mips/configs/malta_kvm_defconfig
+++ b/arch/mips/configs/malta_kvm_defconfig
@@ -60,8 +60,8 @@
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig
index 3b5d591..e79d325 100644
--- a/arch/mips/configs/malta_kvm_guest_defconfig
+++ b/arch/mips/configs/malta_kvm_guest_defconfig
@@ -59,8 +59,8 @@
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
diff --git a/arch/mips/configs/maltaup_xpa_defconfig b/arch/mips/configs/maltaup_xpa_defconfig
index 7322157..ae87ad8 100644
--- a/arch/mips/configs/maltaup_xpa_defconfig
+++ b/arch/mips/configs/maltaup_xpa_defconfig
@@ -61,8 +61,8 @@
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
diff --git a/arch/mips/configs/nlm_xlp_defconfig b/arch/mips/configs/nlm_xlp_defconfig
index b3d1d37..47492fe 100644
--- a/arch/mips/configs/nlm_xlp_defconfig
+++ b/arch/mips/configs/nlm_xlp_defconfig
@@ -111,7 +111,7 @@
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
diff --git a/arch/mips/configs/nlm_xlr_defconfig b/arch/mips/configs/nlm_xlr_defconfig
index 3d8016d..472a818 100644
--- a/arch/mips/configs/nlm_xlr_defconfig
+++ b/arch/mips/configs/nlm_xlr_defconfig
@@ -91,7 +91,7 @@
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 8c6f508..554d1da 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -146,7 +146,25 @@
 		/*
 		 * Find irq with highest priority
 		 */
-		 PTR_LA	t1,cpu_mask_nr_tbl
+		# open coded PTR_LA t1, cpu_mask_nr_tbl
+#if (_MIPS_SZPTR == 32)
+		# open coded la t1, cpu_mask_nr_tbl
+		lui	t1, %hi(cpu_mask_nr_tbl)
+		addiu	t1, %lo(cpu_mask_nr_tbl)
+
+#endif
+#if (_MIPS_SZPTR == 64)
+		# open coded dla t1, cpu_mask_nr_tbl
+		.set	push
+		.set	noat
+		lui	t1, %highest(cpu_mask_nr_tbl)
+		lui	AT, %hi(cpu_mask_nr_tbl)
+		daddiu	t1, t1, %higher(cpu_mask_nr_tbl)
+		daddiu	AT, AT, %lo(cpu_mask_nr_tbl)
+		dsll	t1, 32
+		daddu	t1, t1, AT
+		.set	pop
+#endif
 1:		lw	t2,(t1)
 		nop
 		and	t2,t0
@@ -195,7 +213,25 @@
 		/*
 		 * Find irq with highest priority
 		 */
-		 PTR_LA	t1,asic_mask_nr_tbl
+		# open coded PTR_LA t1,asic_mask_nr_tbl
+#if (_MIPS_SZPTR == 32)
+		# open coded la t1, asic_mask_nr_tbl
+		lui	t1, %hi(asic_mask_nr_tbl)
+		addiu	t1, %lo(asic_mask_nr_tbl)
+
+#endif
+#if (_MIPS_SZPTR == 64)
+		# open coded dla t1, asic_mask_nr_tbl
+		.set	push
+		.set	noat
+		lui	t1, %highest(asic_mask_nr_tbl)
+		lui	AT, %hi(asic_mask_nr_tbl)
+		daddiu	t1, t1, %higher(asic_mask_nr_tbl)
+		daddiu	AT, AT, %lo(asic_mask_nr_tbl)
+		dsll	t1, 32
+		daddu	t1, t1, AT
+		.set	pop
+#endif
 2:		lw	t2,(t1)
 		nop
 		and	t2,t0
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 867f924..8dedee1 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -135,6 +135,7 @@
 	ldc1	$f28, THREAD_FPR28(\thread)
 	ldc1	$f30, THREAD_FPR30(\thread)
 	ctc1	\tmp, fcr31
+	.set	pop
 	.endm
 
 	.macro	fpu_restore_16odd thread
@@ -298,21 +299,21 @@
 	.set	pop
 	.endm
 
-	.macro	copy_u_w	ws, n
+	.macro	copy_s_w	ws, n
 	.set	push
 	.set	mips32r2
 	.set	fp=64
 	.set	msa
-	copy_u.w $1, $w\ws[\n]
+	copy_s.w $1, $w\ws[\n]
 	.set	pop
 	.endm
 
-	.macro	copy_u_d	ws, n
+	.macro	copy_s_d	ws, n
 	.set	push
 	.set	mips64r2
 	.set	fp=64
 	.set	msa
-	copy_u.d $1, $w\ws[\n]
+	copy_s.d $1, $w\ws[\n]
 	.set	pop
 	.endm
 
@@ -346,8 +347,8 @@
 #define STH_MSA_INSN		0x5800081f
 #define STW_MSA_INSN		0x5800082f
 #define STD_MSA_INSN		0x5800083f
-#define COPY_UW_MSA_INSN	0x58f00056
-#define COPY_UD_MSA_INSN	0x58f80056
+#define COPY_SW_MSA_INSN	0x58b00056
+#define COPY_SD_MSA_INSN	0x58b80056
 #define INSERT_W_MSA_INSN	0x59300816
 #define INSERT_D_MSA_INSN	0x59380816
 #else
@@ -361,8 +362,8 @@
 #define STH_MSA_INSN		0x78000825
 #define STW_MSA_INSN		0x78000826
 #define STD_MSA_INSN		0x78000827
-#define COPY_UW_MSA_INSN	0x78f00059
-#define COPY_UD_MSA_INSN	0x78f80059
+#define COPY_SW_MSA_INSN	0x78b00059
+#define COPY_SD_MSA_INSN	0x78b80059
 #define INSERT_W_MSA_INSN	0x79300819
 #define INSERT_D_MSA_INSN	0x79380819
 #endif
@@ -393,7 +394,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
+	PTR_ADDU $1, \base, \off
 	.word	LDB_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
@@ -402,7 +403,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
+	PTR_ADDU $1, \base, \off
 	.word	LDH_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
@@ -411,7 +412,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
+	PTR_ADDU $1, \base, \off
 	.word	LDW_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
@@ -420,7 +421,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
+	PTR_ADDU $1, \base, \off
 	.word	LDD_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
@@ -429,7 +430,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
+	PTR_ADDU $1, \base, \off
 	.word	STB_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
@@ -438,7 +439,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
+	PTR_ADDU $1, \base, \off
 	.word	STH_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
@@ -447,7 +448,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
+	PTR_ADDU $1, \base, \off
 	.word	STW_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
@@ -456,26 +457,26 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
+	PTR_ADDU $1, \base, \off
 	.word	STD_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
 
-	.macro	copy_u_w	ws, n
+	.macro	copy_s_w	ws, n
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
 	.insn
-	.word	COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
+	.word	COPY_SW_MSA_INSN | (\n << 16) | (\ws << 11)
 	.set	pop
 	.endm
 
-	.macro	copy_u_d	ws, n
+	.macro	copy_s_d	ws, n
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
 	.insn
-	.word	COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
+	.word	COPY_SD_MSA_INSN | (\n << 16) | (\ws << 11)
 	.set	pop
 	.endm
 
diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
index 723229f..176de58 100644
--- a/arch/mips/include/asm/cacheflush.h
+++ b/arch/mips/include/asm/cacheflush.h
@@ -51,7 +51,6 @@
 	unsigned long start, unsigned long end);
 extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
 extern void __flush_dcache_page(struct page *page);
-extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page);
 
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 static inline void flush_dcache_page(struct page *page)
@@ -77,11 +76,6 @@
 static inline void flush_icache_page(struct vm_area_struct *vma,
 	struct page *page)
 {
-	if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) &&
-	    Page_dcache_dirty(page)) {
-		__flush_icache_page(vma, page);
-		ClearPageDcacheDirty(page);
-	}
 }
 
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h
index 3ceacde..17f89f9 100644
--- a/arch/mips/include/asm/checksum.h
+++ b/arch/mips/include/asm/checksum.h
@@ -186,7 +186,9 @@
 	"	daddu	%0, %4		\n"
 	"	dsll32	$1, %0, 0	\n"
 	"	daddu	%0, $1		\n"
+	"	sltu	$1, %0, $1	\n"
 	"	dsra32	%0, %0, 0	\n"
+	"	addu	%0, $1		\n"
 #endif
 	"	.set	pop"
 	: "=r" (sum)
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index 15e0fec..ebb9efb 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -17,6 +17,18 @@
 
 #include <irq.h>
 
+#define IRQ_STACK_SIZE			THREAD_SIZE
+
+extern void *irq_stack[NR_CPUS];
+
+static inline bool on_irq_stack(int cpu, unsigned long sp)
+{
+	unsigned long low = (unsigned long)irq_stack[cpu];
+	unsigned long high = low + IRQ_STACK_SIZE;
+
+	return (low <= sp && sp <= high);
+}
+
 #ifdef CONFIG_I8259
 static inline int irq_canonicalize(int irq)
 {
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 6ded8d3..c8c04a1 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -372,6 +372,7 @@
 #define KVM_MIPS_GUEST_TLB_SIZE	64
 struct kvm_vcpu_arch {
 	void *host_ebase, *guest_ebase;
+	int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu);
 	unsigned long host_stack;
 	unsigned long host_gp;
 
@@ -399,7 +400,10 @@
 	/* Host KSEG0 address of the EI/DI offset */
 	void *kseg0_commpage;
 
-	u32 io_gpr;		/* GPR used as IO source/target */
+	/* Resume PC after MMIO completion */
+	unsigned long io_pc;
+	/* GPR used as IO source/target */
+	u32 io_gpr;
 
 	struct hrtimer comparecount_timer;
 	/* Count timer control KVM register */
@@ -421,8 +425,6 @@
 	/* Bitmask of pending exceptions to be cleared */
 	unsigned long pending_exceptions_clr;
 
-	unsigned long pending_load_cause;
-
 	/* Save/Restore the entryhi register when are are preempted/scheduled back in */
 	unsigned long preempt_entryhi;
 
@@ -784,7 +786,7 @@
 
 uint32_t kvm_mips_read_count(struct kvm_vcpu *vcpu);
 void kvm_mips_write_count(struct kvm_vcpu *vcpu, uint32_t count);
-void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare);
+void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare, bool ack);
 void kvm_mips_init_count(struct kvm_vcpu *vcpu);
 int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl);
 int kvm_mips_set_count_resume(struct kvm_vcpu *vcpu, s64 count_resume);
diff --git a/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h b/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h
index 2f82bfa..c9f5769 100644
--- a/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h
+++ b/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h
@@ -11,11 +11,13 @@
 #define CP0_EBASE $15, 1
 
 	.macro  kernel_entry_setup
+#ifdef CONFIG_SMP
 	mfc0	t0, CP0_EBASE
 	andi	t0, t0, 0x3ff		# CPUNum
 	beqz	t0, 1f
 	# CPUs other than zero goto smp_bootstrap
 	j	smp_bootstrap
+#endif /* CONFIG_SMP */
 
 1:
 	.endm
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index bbb85fe..6e4effa 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -147,6 +147,19 @@
 		_restore_msa(t);
 }
 
+static inline void init_msa_upper(void)
+{
+	/*
+	 * Check cpu_has_msa only if it's a constant. This will allow the
+	 * compiler to optimise out code for CPUs without MSA without adding
+	 * an extra redundant check for CPUs with MSA.
+	 */
+	if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa)
+		return;
+
+	_init_msa_upper();
+}
+
 #ifdef TOOLCHAIN_SUPPORTS_MSA
 
 #define __BUILD_MSA_CTL_REG(name, cs)				\
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 18826aa..4e68c64 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -127,10 +127,14 @@
 	}								\
 } while(0)
 
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pteval);
+
 #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 
 #define pte_none(pte)		(!(((pte).pte_high) & ~_PAGE_GLOBAL))
 #define pte_present(pte)	((pte).pte_low & _PAGE_PRESENT)
+#define pte_no_exec(pte)	((pte).pte_low & _PAGE_NO_EXEC)
 
 static inline void set_pte(pte_t *ptep, pte_t pte)
 {
@@ -148,7 +152,6 @@
 			buddy->pte_high |= _PAGE_GLOBAL;
 	}
 }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -166,6 +169,7 @@
 
 #define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
+#define pte_no_exec(pte)	(pte_val(pte) & _PAGE_NO_EXEC)
 
 /*
  * Certain architectures need to do special things when pte's
@@ -218,7 +222,6 @@
 	}
 #endif
 }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -234,6 +237,22 @@
 }
 #endif
 
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pteval)
+{
+	extern void __update_cache(unsigned long address, pte_t pte);
+
+	if (!pte_present(pteval))
+		goto cache_sync_done;
+
+	if (pte_present(*ptep) && (pte_pfn(*ptep) == pte_pfn(pteval)))
+		goto cache_sync_done;
+
+	__update_cache(addr, pteval);
+cache_sync_done:
+	set_pte(ptep, pteval);
+}
+
 /*
  * (pmds are folded into puds so this doesn't get actually called,
  * but the define is needed for a generic inline function.)
@@ -430,15 +449,12 @@
 
 extern void __update_tlb(struct vm_area_struct *vma, unsigned long address,
 	pte_t pte);
-extern void __update_cache(struct vm_area_struct *vma, unsigned long address,
-	pte_t pte);
 
 static inline void update_mmu_cache(struct vm_area_struct *vma,
 	unsigned long address, pte_t *ptep)
 {
 	pte_t pte = *ptep;
 	__update_tlb(vma, address, pte);
-	__update_cache(vma, address, pte);
 }
 
 static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 3f832c3..041153f 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -45,7 +45,7 @@
  * User space process size: 2GB. This is hardcoded into a few places,
  * so don't change it unless you know what you are doing.
  */
-#define TASK_SIZE	0x7fff8000UL
+#define TASK_SIZE	0x80000000UL
 #endif
 
 #define STACK_TOP_MAX	TASK_SIZE
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index f6fc6aa..b657861 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -152,7 +152,7 @@
 
 static inline long regs_return_value(struct pt_regs *regs)
 {
-	if (is_syscall_success(regs))
+	if (is_syscall_success(regs) || !user_mode(regs))
 		return regs->regs[2];
 	else
 		return -regs->regs[2];
diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index 40196be..2365ce0 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -112,7 +112,7 @@
 		"	andi	%[ticket], %[ticket], 0xffff		\n"
 		"	bne	%[ticket], %[my_ticket], 4f		\n"
 		"	 subu	%[ticket], %[my_ticket], %[ticket]	\n"
-		"2:							\n"
+		"2:	.insn						\n"
 		"	.subsection 2					\n"
 		"4:	andi	%[ticket], %[ticket], 0xffff		\n"
 		"	sll	%[ticket], 5				\n"
@@ -187,7 +187,7 @@
 		"	sc	%[ticket], %[ticket_ptr]		\n"
 		"	beqz	%[ticket], 1b				\n"
 		"	 li	%[ticket], 1				\n"
-		"2:							\n"
+		"2:	.insn						\n"
 		"	.subsection 2					\n"
 		"3:	b	2b					\n"
 		"	 li	%[ticket], 0				\n"
@@ -367,7 +367,7 @@
 		"	.set	reorder					\n"
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
-		"2:							\n"
+		"2:	.insn						\n"
 		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
 		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
@@ -407,7 +407,7 @@
 			"	lui	%1, 0x8000			\n"
 			"	sc	%1, %0				\n"
 			"	li	%2, 1				\n"
-			"2:						\n"
+			"2:	.insn					\n"
 			: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp),
 			  "=&r" (ret)
 			: GCC_OFF_SMALL_ASM() (rw->lock)
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index a71da57..5347f13 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -216,12 +216,19 @@
 		LONG_S	$25, PT_R25(sp)
 		LONG_S	$28, PT_R28(sp)
 		LONG_S	$31, PT_R31(sp)
+
+		/* Set thread_info if we're coming from user mode */
+		mfc0	k0, CP0_STATUS
+		sll	k0, 3		/* extract cu0 bit */
+		bltz	k0, 9f
+
 		ori	$28, sp, _THREAD_MASK
 		xori	$28, _THREAD_MASK
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 		.set    mips64
 		pref    0, 0($28)       /* Prefetch the current pointer */
 #endif
+9:
 		.set	pop
 		.endm
 
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index 28b5d84..ebb5c0f 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -105,7 +105,7 @@
 	__clear_software_ll_bit();					\
 	if (cpu_has_userlocal)						\
 		write_c0_userlocal(task_thread_info(next)->tp_value);	\
-	__restore_watch();						\
+	__restore_watch(next);						\
 	(last) = resume(prev, next, task_thread_info(next));		\
 } while (0)
 
diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index 095ecaf..c74c32c 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
+#include <linux/string.h>
 #include <asm/asm-eva.h>
 
 /*
@@ -1170,6 +1171,8 @@
 			__cu_len = __invoke_copy_from_user(__cu_to,	\
 							   __cu_from,	\
 							   __cu_len);   \
+		} else {						\
+			memset(__cu_to, 0, __cu_len);			\
 		}							\
 	}								\
 	__cu_len;							\
diff --git a/arch/mips/include/asm/uprobes.h b/arch/mips/include/asm/uprobes.h
index 34c325c..70a4a2f 100644
--- a/arch/mips/include/asm/uprobes.h
+++ b/arch/mips/include/asm/uprobes.h
@@ -36,7 +36,6 @@
 	unsigned long	resume_epc;
 	u32	insn[2];
 	u32	ixol[2];
-	union	mips_instruction orig_inst[MAX_UINSN_BYTES / 4];
 };
 
 struct arch_uprobe_task {
diff --git a/arch/mips/include/asm/watch.h b/arch/mips/include/asm/watch.h
index 20126ec..6ffe3ea 100644
--- a/arch/mips/include/asm/watch.h
+++ b/arch/mips/include/asm/watch.h
@@ -12,21 +12,21 @@
 
 #include <asm/mipsregs.h>
 
-void mips_install_watch_registers(void);
+void mips_install_watch_registers(struct task_struct *t);
 void mips_read_watch_registers(void);
 void mips_clear_watch_registers(void);
 void mips_probe_watch_registers(struct cpuinfo_mips *c);
 
 #ifdef CONFIG_HARDWARE_WATCHPOINTS
-#define __restore_watch() do {						\
+#define __restore_watch(task) do {					\
 	if (unlikely(test_bit(TIF_LOAD_WATCH,				\
-			      &current_thread_info()->flags))) {	\
-		mips_install_watch_registers();				\
+			      &task_thread_info(task)->flags))) {	\
+		mips_install_watch_registers(task);			\
 	}								\
 } while (0)
 
 #else
-#define __restore_watch() do {} while (0)
+#define __restore_watch(task) do {} while (0)
 #endif
 
 #endif /* _ASM_WATCH_H */
diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h
index 2cb7fde..e2b5337 100644
--- a/arch/mips/include/uapi/asm/siginfo.h
+++ b/arch/mips/include/uapi/asm/siginfo.h
@@ -28,7 +28,7 @@
 
 #define __ARCH_SIGSYS
 
-#include <uapi/asm-generic/siginfo.h>
+#include <asm-generic/siginfo.h>
 
 /* We can't use generic siginfo_t, because our si_code and si_errno are swapped */
 typedef struct siginfo {
@@ -42,13 +42,13 @@
 
 		/* kill() */
 		struct {
-			pid_t _pid;		/* sender's pid */
+			__kernel_pid_t _pid;	/* sender's pid */
 			__ARCH_SI_UID_T _uid;	/* sender's uid */
 		} _kill;
 
 		/* POSIX.1b timers */
 		struct {
-			timer_t _tid;		/* timer id */
+			__kernel_timer_t _tid;	/* timer id */
 			int _overrun;		/* overrun count */
 			char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
 			sigval_t _sigval;	/* same as below */
@@ -57,26 +57,26 @@
 
 		/* POSIX.1b signals */
 		struct {
-			pid_t _pid;		/* sender's pid */
+			__kernel_pid_t _pid;	/* sender's pid */
 			__ARCH_SI_UID_T _uid;	/* sender's uid */
 			sigval_t _sigval;
 		} _rt;
 
 		/* SIGCHLD */
 		struct {
-			pid_t _pid;		/* which child */
+			__kernel_pid_t _pid;	/* which child */
 			__ARCH_SI_UID_T _uid;	/* sender's uid */
 			int _status;		/* exit code */
-			clock_t _utime;
-			clock_t _stime;
+			__kernel_clock_t _utime;
+			__kernel_clock_t _stime;
 		} _sigchld;
 
 		/* IRIX SIGCHLD */
 		struct {
-			pid_t _pid;		/* which child */
-			clock_t _utime;
+			__kernel_pid_t _pid;	/* which child */
+			__kernel_clock_t _utime;
 			int _status;		/* exit code */
-			clock_t _stime;
+			__kernel_clock_t _stime;
 		} _irix_sigchld;
 
 		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -118,6 +118,4 @@
 #define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */
 #define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */
 
-#include <asm-generic/siginfo.h>
-
 #endif /* _UAPI_ASM_SIGINFO_H */
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 154e203..ec053ce 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -101,6 +101,7 @@
 	OFFSET(TI_REGS, thread_info, regs);
 	DEFINE(_THREAD_SIZE, THREAD_SIZE);
 	DEFINE(_THREAD_MASK, THREAD_MASK);
+	DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
 	BLANK();
 }
 
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index d8f9b35..e9fed8c 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -816,8 +816,10 @@
 			break;
 		}
 		/* Compact branch: BNEZC || JIALC */
-		if (insn.i_format.rs)
+		if (!insn.i_format.rs) {
+			/* JIALC: set $31/ra */
 			regs->regs[31] = epc + 4;
+		}
 		regs->cp0_epc += 8;
 		break;
 #endif
diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c
index d434d5d..610f0f3 100644
--- a/arch/mips/kernel/crash.c
+++ b/arch/mips/kernel/crash.c
@@ -14,12 +14,22 @@
 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
 
 #ifdef CONFIG_SMP
-static void crash_shutdown_secondary(void *ignore)
+static void crash_shutdown_secondary(void *passed_regs)
 {
-	struct pt_regs *regs;
+	struct pt_regs *regs = passed_regs;
 	int cpu = smp_processor_id();
 
-	regs = task_pt_regs(current);
+	/*
+	 * If we are passed registers, use those.  Otherwise get the
+	 * regs from the last interrupt, which should be correct, as
+	 * we are in an interrupt.  But if the regs are not there,
+	 * pull them from the top of the stack.  They are probably
+	 * wrong, but we need something to keep from crashing again.
+	 */
+	if (!regs)
+		regs = get_irq_regs();
+	if (!regs)
+		regs = task_pt_regs(current);
 
 	if (!cpu_online(cpu))
 		return;
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
index 1f91056..d76275d 100644
--- a/arch/mips/kernel/csrc-r4k.c
+++ b/arch/mips/kernel/csrc-r4k.c
@@ -23,7 +23,7 @@
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static u64 notrace r4k_read_sched_clock(void)
+static u64 __maybe_unused notrace r4k_read_sched_clock(void)
 {
 	return read_c0_count();
 }
@@ -82,7 +82,9 @@
 
 	clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
 
+#ifndef CONFIG_CPU_FREQ
 	sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency);
+#endif
 
 	return 0;
 }
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 4a4d9e0..3afffc3 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -206,7 +206,7 @@
 	else if ((prog_req.fr1 && prog_req.frdefault) ||
 		 (prog_req.single && !prog_req.frdefault))
 		/* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
-		state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
+		state->overall_fp_mode = ((raw_current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
 					  cpu_has_mips_r2_r6) ?
 					  FP_FR1 : FP_FR0;
 	else if (prog_req.fr1)
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 7791840..db07793 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -11,6 +11,7 @@
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/compiler.h>
+#include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
@@ -137,6 +138,7 @@
 	andi	t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
 	beqz	t0, work_notifysig
 work_resched:
+	TRACE_IRQS_OFF
 	jal	schedule
 
 	local_irq_disable		# make sure need_resched and
@@ -173,6 +175,7 @@
 	beqz	t0, work_pending	# trace bit set?
 	local_irq_enable		# could let syscall_trace_leave()
 					# call schedule() instead
+	TRACE_IRQS_ON
 	move	a0, sp
 	jal	syscall_trace_leave
 	b	resume_userspace
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index baa7b6f..619e30e 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -188,9 +188,44 @@
 
 	LONG_L	s0, TI_REGS($28)
 	LONG_S	sp, TI_REGS($28)
-	PTR_LA	ra, ret_from_irq
-	PTR_LA  v0, plat_irq_dispatch
-	jr	v0
+
+	/*
+	 * SAVE_ALL ensures we are using a valid kernel stack for the thread.
+	 * Check if we are already using the IRQ stack.
+	 */
+	move	s1, sp # Preserve the sp
+
+	/* Get IRQ stack for this CPU */
+	ASM_CPUID_MFC0	k0, ASM_SMP_CPUID_REG
+#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
+	lui	k1, %hi(irq_stack)
+#else
+	lui	k1, %highest(irq_stack)
+	daddiu	k1, %higher(irq_stack)
+	dsll	k1, 16
+	daddiu	k1, %hi(irq_stack)
+	dsll	k1, 16
+#endif
+	LONG_SRL	k0, SMP_CPUID_PTRSHIFT
+	LONG_ADDU	k1, k0
+	LONG_L	t0, %lo(irq_stack)(k1)
+
+	# Check if already on IRQ stack
+	PTR_LI	t1, ~(_THREAD_SIZE-1)
+	and	t1, t1, sp
+	beq	t0, t1, 2f
+
+	/* Switch to IRQ stack */
+	li	t1, _IRQ_STACK_SIZE
+	PTR_ADD sp, t0, t1
+
+2:
+	jal	plat_irq_dispatch
+
+	/* Restore sp */
+	move	sp, s1
+
+	j	ret_from_irq
 #ifdef CONFIG_CPU_MICROMIPS
 	nop
 #endif
@@ -263,8 +298,44 @@
 
 	LONG_L	s0, TI_REGS($28)
 	LONG_S	sp, TI_REGS($28)
-	PTR_LA	ra, ret_from_irq
-	jr	v0
+
+	/*
+	 * SAVE_ALL ensures we are using a valid kernel stack for the thread.
+	 * Check if we are already using the IRQ stack.
+	 */
+	move	s1, sp # Preserve the sp
+
+	/* Get IRQ stack for this CPU */
+	ASM_CPUID_MFC0	k0, ASM_SMP_CPUID_REG
+#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
+	lui	k1, %hi(irq_stack)
+#else
+	lui	k1, %highest(irq_stack)
+	daddiu	k1, %higher(irq_stack)
+	dsll	k1, 16
+	daddiu	k1, %hi(irq_stack)
+	dsll	k1, 16
+#endif
+	LONG_SRL	k0, SMP_CPUID_PTRSHIFT
+	LONG_ADDU	k1, k0
+	LONG_L	t0, %lo(irq_stack)(k1)
+
+	# Check if already on IRQ stack
+	PTR_LI	t1, ~(_THREAD_SIZE-1)
+	and	t1, t1, sp
+	beq	t0, t1, 2f
+
+	/* Switch to IRQ stack */
+	li	t1, _IRQ_STACK_SIZE
+	PTR_ADD sp, t0, t1
+
+2:
+	jalr	v0
+
+	/* Restore sp */
+	move	sp, s1
+
+	j	ret_from_irq
 	END(except_vec_vi_handler)
 
 /*
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 8eb5af8..dc1180a 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -25,6 +25,8 @@
 #include <linux/atomic.h>
 #include <asm/uaccess.h>
 
+void *irq_stack[NR_CPUS];
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
@@ -55,6 +57,15 @@
 		irq_set_noprobe(i);
 
 	arch_init_irq();
+
+	for_each_possible_cpu(i) {
+		int irq_pages = IRQ_STACK_SIZE / PAGE_SIZE;
+		void *s = (void *)__get_free_pages(GFP_KERNEL, irq_pages);
+
+		irq_stack[i] = s;
+		pr_debug("CPU%d IRQ stack at 0x%p - 0x%p\n", i,
+			irq_stack[i], irq_stack[i] + IRQ_STACK_SIZE);
+	}
 }
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index de63d36..732d617 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -244,9 +244,6 @@
 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
 {
 	int reg;
-	struct thread_info *ti = task_thread_info(p);
-	unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
-	struct pt_regs *regs = (struct pt_regs *)ksp - 1;
 #if (KGDB_GDB_REG_SIZE == 32)
 	u32 *ptr = (u32 *)gdb_regs;
 #else
@@ -254,25 +251,46 @@
 #endif
 
 	for (reg = 0; reg < 16; reg++)
-		*(ptr++) = regs->regs[reg];
+		*(ptr++) = 0;
 
 	/* S0 - S7 */
-	for (reg = 16; reg < 24; reg++)
-		*(ptr++) = regs->regs[reg];
+	*(ptr++) = p->thread.reg16;
+	*(ptr++) = p->thread.reg17;
+	*(ptr++) = p->thread.reg18;
+	*(ptr++) = p->thread.reg19;
+	*(ptr++) = p->thread.reg20;
+	*(ptr++) = p->thread.reg21;
+	*(ptr++) = p->thread.reg22;
+	*(ptr++) = p->thread.reg23;
 
 	for (reg = 24; reg < 28; reg++)
 		*(ptr++) = 0;
 
 	/* GP, SP, FP, RA */
-	for (reg = 28; reg < 32; reg++)
-		*(ptr++) = regs->regs[reg];
+	*(ptr++) = (long)p;
+	*(ptr++) = p->thread.reg29;
+	*(ptr++) = p->thread.reg30;
+	*(ptr++) = p->thread.reg31;
 
-	*(ptr++) = regs->cp0_status;
-	*(ptr++) = regs->lo;
-	*(ptr++) = regs->hi;
-	*(ptr++) = regs->cp0_badvaddr;
-	*(ptr++) = regs->cp0_cause;
-	*(ptr++) = regs->cp0_epc;
+	*(ptr++) = p->thread.cp0_status;
+
+	/* lo, hi */
+	*(ptr++) = 0;
+	*(ptr++) = 0;
+
+	/*
+	 * BadVAddr, Cause
+	 * Ideally these would come from the last exception frame up the stack
+	 * but that requires unwinding, otherwise we can't know much for sure.
+	 */
+	*(ptr++) = 0;
+	*(ptr++) = 0;
+
+	/*
+	 * PC
+	 * use return address (RA), i.e. the moment after return from resume()
+	 */
+	*(ptr++) = p->thread.reg31;
 }
 
 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c
index 1f5aac7..e338406 100644
--- a/arch/mips/kernel/mips-r2-to-r6-emul.c
+++ b/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -28,6 +28,7 @@
 #include <asm/inst.h>
 #include <asm/mips-r2-to-r6-emul.h>
 #include <asm/local.h>
+#include <asm/mipsregs.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
@@ -433,8 +434,8 @@
 	rs = regs->regs[MIPSInst_RS(ir)];
 	res = (u64)rt * (u64)rs;
 	rt = res;
-	regs->lo = (s64)rt;
-	regs->hi = (s64)(res >> 32);
+	regs->lo = (s64)(s32)rt;
+	regs->hi = (s64)(s32)(res >> 32);
 
 	MIPS_R2_STATS(muls);
 
@@ -670,9 +671,9 @@
 	res += ((((s64)rt) << 32) | (u32)rs);
 
 	rt = res;
-	regs->lo = (s64)rt;
+	regs->lo = (s64)(s32)rt;
 	rs = res >> 32;
-	regs->hi = (s64)rs;
+	regs->hi = (s64)(s32)rs;
 
 	MIPS_R2_STATS(dsps);
 
@@ -728,9 +729,9 @@
 	res = ((((s64)rt) << 32) | (u32)rs) - res;
 
 	rt = res;
-	regs->lo = (s64)rt;
+	regs->lo = (s64)(s32)rt;
 	rs = res >> 32;
-	regs->hi = (s64)rs;
+	regs->hi = (s64)(s32)rs;
 
 	MIPS_R2_STATS(dsps);
 
@@ -1163,7 +1164,9 @@
 		regs->regs[31] = r31;
 		regs->cp0_epc = epc;
 		if (!used_math()) {     /* First time FPU user.  */
+			preempt_disable();
 			err = init_fpu();
+			preempt_enable();
 			set_used_math();
 		}
 		lose_fpu(1);    /* Save FPU state for the emulator. */
@@ -1251,10 +1254,10 @@
 			"	j	10b\n"
 			"	.previous\n"
 			"	.section	__ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1326,10 +1329,10 @@
 			"	j	10b\n"
 			"       .previous\n"
 			"	.section	__ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1397,10 +1400,10 @@
 			"	j	9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1467,10 +1470,10 @@
 			"	j	9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1582,14 +1585,14 @@
 			"	j	9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
-			"	.word	5b,8b\n"
-			"	.word	6b,8b\n"
-			"	.word	7b,8b\n"
-			"	.word	0b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
+			STR(PTR) " 5b,8b\n"
+			STR(PTR) " 6b,8b\n"
+			STR(PTR) " 7b,8b\n"
+			STR(PTR) " 0b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1701,14 +1704,14 @@
 			"	j      9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word  1b,8b\n"
-			"	.word  2b,8b\n"
-			"	.word  3b,8b\n"
-			"	.word  4b,8b\n"
-			"	.word  5b,8b\n"
-			"	.word  6b,8b\n"
-			"	.word  7b,8b\n"
-			"	.word  0b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
+			STR(PTR) " 5b,8b\n"
+			STR(PTR) " 6b,8b\n"
+			STR(PTR) " 7b,8b\n"
+			STR(PTR) " 0b,8b\n"
 			"	.previous\n"
 			"	.set    pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1820,14 +1823,14 @@
 			"	j	9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
-			"	.word	5b,8b\n"
-			"	.word	6b,8b\n"
-			"	.word	7b,8b\n"
-			"	.word	0b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
+			STR(PTR) " 5b,8b\n"
+			STR(PTR) " 6b,8b\n"
+			STR(PTR) " 7b,8b\n"
+			STR(PTR) " 0b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1938,14 +1941,14 @@
 			"       j	9b\n"
 			"       .previous\n"
 			"       .section        __ex_table,\"a\"\n"
-			"       .word	1b,8b\n"
-			"       .word	2b,8b\n"
-			"       .word	3b,8b\n"
-			"       .word	4b,8b\n"
-			"       .word	5b,8b\n"
-			"       .word	6b,8b\n"
-			"       .word	7b,8b\n"
-			"       .word	0b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
+			STR(PTR) " 5b,8b\n"
+			STR(PTR) " 6b,8b\n"
+			STR(PTR) " 7b,8b\n"
+			STR(PTR) " 0b,8b\n"
 			"       .previous\n"
 			"       .set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -2000,7 +2003,7 @@
 			"j	2b\n"
 			".previous\n"
 			".section        __ex_table,\"a\"\n"
-			".word  1b, 3b\n"
+			STR(PTR) " 1b,3b\n"
 			".previous\n"
 			: "=&r"(res), "+&r"(err)
 			: "r"(vaddr), "i"(SIGSEGV)
@@ -2058,7 +2061,7 @@
 			"j	2b\n"
 			".previous\n"
 			".section        __ex_table,\"a\"\n"
-			".word	1b, 3b\n"
+			STR(PTR) " 1b,3b\n"
 			".previous\n"
 			: "+&r"(res), "+&r"(err)
 			: "r"(vaddr), "i"(SIGSEGV));
@@ -2119,7 +2122,7 @@
 			"j	2b\n"
 			".previous\n"
 			".section        __ex_table,\"a\"\n"
-			".word  1b, 3b\n"
+			STR(PTR) " 1b,3b\n"
 			".previous\n"
 			: "=&r"(res), "+&r"(err)
 			: "r"(vaddr), "i"(SIGSEGV)
@@ -2182,7 +2185,7 @@
 			"j	2b\n"
 			".previous\n"
 			".section        __ex_table,\"a\"\n"
-			".word	1b, 3b\n"
+			STR(PTR) " 1b,3b\n"
 			".previous\n"
 			: "+&r"(res), "+&r"(err)
 			: "r"(vaddr), "i"(SIGSEGV));
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index f63a289..0b3e58a 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -55,7 +55,6 @@
  * state. Actually per-core rather than per-CPU.
  */
 static DEFINE_PER_CPU_ALIGNED(u32*, ready_count);
-static DEFINE_PER_CPU_ALIGNED(void*, ready_count_alloc);
 
 /* Indicates online CPUs coupled with the current CPU */
 static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled);
@@ -625,7 +624,6 @@
 {
 	enum cps_pm_state state;
 	unsigned core = cpu_data[cpu].core;
-	unsigned dlinesz = cpu_data[cpu].dcache.linesz;
 	void *entry_fn, *core_rc;
 
 	for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) {
@@ -645,16 +643,11 @@
 	}
 
 	if (!per_cpu(ready_count, core)) {
-		core_rc = kmalloc(dlinesz * 2, GFP_KERNEL);
+		core_rc = kmalloc(sizeof(u32), GFP_KERNEL);
 		if (!core_rc) {
 			pr_err("Failed allocate core %u ready_count\n", core);
 			return -ENOMEM;
 		}
-		per_cpu(ready_count_alloc, core) = core_rc;
-
-		/* Ensure ready_count is aligned to a cacheline boundary */
-		core_rc += dlinesz - 1;
-		core_rc = (void *)((unsigned long)core_rc & ~(dlinesz - 1));
 		per_cpu(ready_count, core) = core_rc;
 	}
 
diff --git a/arch/mips/kernel/pm.c b/arch/mips/kernel/pm.c
index fefdf39..dc81489 100644
--- a/arch/mips/kernel/pm.c
+++ b/arch/mips/kernel/pm.c
@@ -56,7 +56,7 @@
 		write_c0_userlocal(current_thread_info()->tp_value);
 
 	/* Restore watch registers */
-	__restore_watch();
+	__restore_watch(current);
 }
 
 /**
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index f2975d4..8c26eca 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -32,6 +32,7 @@
 #include <asm/cpu.h>
 #include <asm/dsp.h>
 #include <asm/fpu.h>
+#include <asm/irq.h>
 #include <asm/msa.h>
 #include <asm/pgtable.h>
 #include <asm/mipsregs.h>
@@ -191,11 +192,9 @@
 #define J_TARGET(pc,target)	\
 		(((unsigned long)(pc) & 0xf0000000) | ((target) << 2))
 
-static inline int is_ra_save_ins(union mips_instruction *ip)
+static inline int is_ra_save_ins(union mips_instruction *ip, int *poff)
 {
 #ifdef CONFIG_CPU_MICROMIPS
-	union mips_instruction mmi;
-
 	/*
 	 * swsp ra,offset
 	 * swm16 reglist,offset(sp)
@@ -205,29 +204,71 @@
 	 *
 	 * microMIPS is way more fun...
 	 */
-	if (mm_insn_16bit(ip->halfword[0])) {
-		mmi.word = (ip->halfword[0] << 16);
-		return (mmi.mm16_r5_format.opcode == mm_swsp16_op &&
-			mmi.mm16_r5_format.rt == 31) ||
-		       (mmi.mm16_m_format.opcode == mm_pool16c_op &&
-			mmi.mm16_m_format.func == mm_swm16_op);
+	if (mm_insn_16bit(ip->halfword[1])) {
+		switch (ip->mm16_r5_format.opcode) {
+		case mm_swsp16_op:
+			if (ip->mm16_r5_format.rt != 31)
+				return 0;
+
+			*poff = ip->mm16_r5_format.simmediate;
+			*poff = (*poff << 2) / sizeof(ulong);
+			return 1;
+
+		case mm_pool16c_op:
+			switch (ip->mm16_m_format.func) {
+			case mm_swm16_op:
+				*poff = ip->mm16_m_format.imm;
+				*poff += 1 + ip->mm16_m_format.rlist;
+				*poff = (*poff << 2) / sizeof(ulong);
+				return 1;
+
+			default:
+				return 0;
+			}
+
+		default:
+			return 0;
+		}
 	}
-	else {
-		mmi.halfword[0] = ip->halfword[1];
-		mmi.halfword[1] = ip->halfword[0];
-		return (mmi.mm_m_format.opcode == mm_pool32b_op &&
-			mmi.mm_m_format.rd > 9 &&
-			mmi.mm_m_format.base == 29 &&
-			mmi.mm_m_format.func == mm_swm32_func) ||
-		       (mmi.i_format.opcode == mm_sw32_op &&
-			mmi.i_format.rs == 29 &&
-			mmi.i_format.rt == 31);
+
+	switch (ip->i_format.opcode) {
+	case mm_sw32_op:
+		if (ip->i_format.rs != 29)
+			return 0;
+		if (ip->i_format.rt != 31)
+			return 0;
+
+		*poff = ip->i_format.simmediate / sizeof(ulong);
+		return 1;
+
+	case mm_pool32b_op:
+		switch (ip->mm_m_format.func) {
+		case mm_swm32_func:
+			if (ip->mm_m_format.rd < 0x10)
+				return 0;
+			if (ip->mm_m_format.base != 29)
+				return 0;
+
+			*poff = ip->mm_m_format.simmediate;
+			*poff += (ip->mm_m_format.rd & 0xf) * sizeof(u32);
+			*poff /= sizeof(ulong);
+			return 1;
+		default:
+			return 0;
+		}
+
+	default:
+		return 0;
 	}
 #else
 	/* sw / sd $ra, offset($sp) */
-	return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
-		ip->i_format.rs == 29 &&
-		ip->i_format.rt == 31;
+	if ((ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
+		ip->i_format.rs == 29 && ip->i_format.rt == 31) {
+		*poff = ip->i_format.simmediate / sizeof(ulong);
+		return 1;
+	}
+
+	return 0;
 #endif
 }
 
@@ -242,13 +283,16 @@
 	 *
 	 * microMIPS is kind of more fun...
 	 */
-	union mips_instruction mmi;
+	if (mm_insn_16bit(ip->halfword[1])) {
+		if ((ip->mm16_r5_format.opcode == mm_pool16c_op &&
+		    (ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op))
+			return 1;
+		return 0;
+	}
 
-	mmi.word = (ip->halfword[0] << 16);
-
-	if ((mmi.mm16_r5_format.opcode == mm_pool16c_op &&
-	    (mmi.mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op) ||
-	    ip->j_format.opcode == mm_jal32_op)
+	if (ip->j_format.opcode == mm_j32_op)
+		return 1;
+	if (ip->j_format.opcode == mm_jal32_op)
 		return 1;
 	if (ip->r_format.opcode != mm_pool32a_op ||
 			ip->r_format.func != mm_pool32axf_op)
@@ -276,15 +320,13 @@
 	 *
 	 * microMIPS is not more fun...
 	 */
-	if (mm_insn_16bit(ip->halfword[0])) {
-		union mips_instruction mmi;
-
-		mmi.word = (ip->halfword[0] << 16);
-		return (mmi.mm16_r3_format.opcode == mm_pool16d_op &&
-			mmi.mm16_r3_format.simmediate && mm_addiusp_func) ||
-		       (mmi.mm16_r5_format.opcode == mm_pool16d_op &&
-			mmi.mm16_r5_format.rt == 29);
+	if (mm_insn_16bit(ip->halfword[1])) {
+		return (ip->mm16_r3_format.opcode == mm_pool16d_op &&
+			ip->mm16_r3_format.simmediate && mm_addiusp_func) ||
+		       (ip->mm16_r5_format.opcode == mm_pool16d_op &&
+			ip->mm16_r5_format.rt == 29);
 	}
+
 	return ip->mm_i_format.opcode == mm_addiu32_op &&
 	       ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29;
 #else
@@ -299,30 +341,36 @@
 
 static int get_frame_info(struct mips_frame_info *info)
 {
-#ifdef CONFIG_CPU_MICROMIPS
-	union mips_instruction *ip = (void *) (((char *) info->func) - 1);
-#else
-	union mips_instruction *ip = info->func;
-#endif
-	unsigned max_insns = info->func_size / sizeof(union mips_instruction);
-	unsigned i;
+	bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
+	union mips_instruction insn, *ip, *ip_end;
+	const unsigned int max_insns = 128;
+	unsigned int i;
 
 	info->pc_offset = -1;
 	info->frame_size = 0;
 
+	ip = (void *)msk_isa16_mode((ulong)info->func);
 	if (!ip)
 		goto err;
 
-	if (max_insns == 0)
-		max_insns = 128U;	/* unknown function size */
-	max_insns = min(128U, max_insns);
+	ip_end = (void *)ip + info->func_size;
 
-	for (i = 0; i < max_insns; i++, ip++) {
+	for (i = 0; i < max_insns && ip < ip_end; i++, ip++) {
+		if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
+			insn.halfword[0] = 0;
+			insn.halfword[1] = ip->halfword[0];
+		} else if (is_mmips) {
+			insn.halfword[0] = ip->halfword[1];
+			insn.halfword[1] = ip->halfword[0];
+		} else {
+			insn.word = ip->word;
+		}
 
-		if (is_jump_ins(ip))
+		if (is_jump_ins(&insn))
 			break;
+
 		if (!info->frame_size) {
-			if (is_sp_move_ins(ip))
+			if (is_sp_move_ins(&insn))
 			{
 #ifdef CONFIG_CPU_MICROMIPS
 				if (mm_insn_16bit(ip->halfword[0]))
@@ -345,11 +393,9 @@
 			}
 			continue;
 		}
-		if (info->pc_offset == -1 && is_ra_save_ins(ip)) {
-			info->pc_offset =
-				ip->i_format.simmediate / sizeof(long);
+		if (info->pc_offset == -1 &&
+		    is_ra_save_ins(&insn, &info->pc_offset))
 			break;
-		}
 	}
 	if (info->frame_size && info->pc_offset >= 0) /* nested */
 		return 0;
@@ -457,7 +503,7 @@
 		    *sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) {
 			regs = (struct pt_regs *)*sp;
 			pc = regs->cp0_epc;
-			if (__kernel_text_address(pc)) {
+			if (!user_mode(regs) && __kernel_text_address(pc)) {
 				*sp = regs->regs[29];
 				*ra = regs->regs[31];
 				return pc;
@@ -507,7 +553,19 @@
 unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
 			   unsigned long pc, unsigned long *ra)
 {
-	unsigned long stack_page = (unsigned long)task_stack_page(task);
+	unsigned long stack_page = 0;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		if (on_irq_stack(cpu, *sp)) {
+			stack_page = (unsigned long)irq_stack[cpu];
+			break;
+		}
+	}
+
+	if (!stack_page)
+		stack_page = (unsigned long)task_stack_page(task);
+
 	return unwind_stack_by_address(stack_page, sp, pc, ra);
 }
 #endif
@@ -593,16 +651,19 @@
 		return -EOPNOTSUPP;
 
 	/* Avoid inadvertently triggering emulation */
-	if ((value & PR_FP_MODE_FR) && cpu_has_fpu &&
-	    !(current_cpu_data.fpu_id & MIPS_FPIR_F64))
+	if ((value & PR_FP_MODE_FR) && raw_cpu_has_fpu &&
+	    !(raw_current_cpu_data.fpu_id & MIPS_FPIR_F64))
 		return -EOPNOTSUPP;
-	if ((value & PR_FP_MODE_FRE) && cpu_has_fpu && !cpu_has_fre)
+	if ((value & PR_FP_MODE_FRE) && raw_cpu_has_fpu && !cpu_has_fre)
 		return -EOPNOTSUPP;
 
 	/* FR = 0 not supported in MIPS R6 */
-	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
+	if (!(value & PR_FP_MODE_FR) && raw_cpu_has_fpu && cpu_has_mips_r6)
 		return -EOPNOTSUPP;
 
+	/* Proceed with the mode switch */
+	preempt_disable();
+
 	/* Save FP & vector context, then disable FPU & MSA */
 	if (task->signal == current->signal)
 		lose_fpu(1);
@@ -661,6 +722,7 @@
 
 	/* Allow threads to use FP again */
 	atomic_set(&task->mm->context.fp_mode_switching, 0);
+	preempt_enable();
 
 	return 0;
 }
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 4f0ac78..c95bf18 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -57,8 +57,7 @@
 	/* Begin with data registers set to all 1s... */
 	memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr));
 
-	/* ...and FCSR zeroed */
-	target->thread.fpu.fcr31 = 0;
+	/* FCSR has been preset by `mips_set_personality_nan'.  */
 
 	/*
 	 * Record that the target has "used" math, such that the context
@@ -80,6 +79,22 @@
 }
 
 /*
+ * Poke at FCSR according to its mask.  Don't set the cause bits as
+ * this is currently not handled correctly in FP context restoration
+ * and will cause an oops if a corresponding enable bit is set.
+ */
+static void ptrace_setfcr31(struct task_struct *child, u32 value)
+{
+	u32 fcr31;
+	u32 mask;
+
+	value &= ~FPU_CSR_ALL_X;
+	fcr31 = child->thread.fpu.fcr31;
+	mask = boot_cpu_data.fpu_msk31;
+	child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
+}
+
+/*
  * Read a general register set.	 We always use the 64-bit format, even
  * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
  * Registers are sign extended to fill the available space.
@@ -159,9 +174,7 @@
 {
 	union fpureg *fregs;
 	u64 fpr_val;
-	u32 fcr31;
 	u32 value;
-	u32 mask;
 	int i;
 
 	if (!access_ok(VERIFY_READ, data, 33 * 8))
@@ -176,9 +189,7 @@
 	}
 
 	__get_user(value, data + 64);
-	fcr31 = child->thread.fpu.fcr31;
-	mask = boot_cpu_data.fpu_msk31;
-	child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
+	ptrace_setfcr31(child, value);
 
 	/* FIR may not be written.  */
 
@@ -474,7 +485,8 @@
 					  &target->thread.fpu,
 					  0, sizeof(elf_fpregset_t));
 
-	for (i = 0; i < NUM_FPU_REGS; i++) {
+	BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
+	for (i = 0; i < NUM_FPU_REGS && count >= sizeof(elf_fpreg_t); i++) {
 		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 					 &fpr_val, i * sizeof(elf_fpreg_t),
 					 (i + 1) * sizeof(elf_fpreg_t));
@@ -808,7 +820,7 @@
 			break;
 #endif
 		case FPC_CSR:
-			child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
+			ptrace_setfcr31(child, data);
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index f09546e..bc74485 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -244,17 +244,17 @@
 	.set	push
 	.set	noat
 #ifdef CONFIG_64BIT
-	copy_u_d \wr, 1
+	copy_s_d \wr, 1
 	EX sd	$1, \off(\base)
 #elif defined(CONFIG_CPU_LITTLE_ENDIAN)
-	copy_u_w \wr, 2
+	copy_s_w \wr, 2
 	EX sw	$1, \off(\base)
-	copy_u_w \wr, 3
+	copy_s_w \wr, 3
 	EX sw	$1, (\off+4)(\base)
 #else /* CONFIG_CPU_BIG_ENDIAN */
-	copy_u_w \wr, 2
+	copy_s_w \wr, 2
 	EX sw	$1, (\off+4)(\base)
-	copy_u_w \wr, 3
+	copy_s_w \wr, 3
 	EX sw	$1, \off(\base)
 #endif
 	.set	pop
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 5a69eb4..ee93d5f 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -344,7 +344,7 @@
 	PTR	sys_ni_syscall			/* available, was setaltroot */
 	PTR	sys_add_key
 	PTR	sys_request_key
-	PTR	sys_keyctl			/* 6245 */
+	PTR	compat_sys_keyctl		/* 6245 */
 	PTR	sys_set_thread_area
 	PTR	sys_inotify_init
 	PTR	sys_inotify_add_watch
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index e4b6d7c..b77052e 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -500,7 +500,7 @@
 	PTR	sys_ni_syscall			/* available, was setaltroot */
 	PTR	sys_add_key			/* 4280 */
 	PTR	sys_request_key
-	PTR	sys_keyctl
+	PTR	compat_sys_keyctl
 	PTR	sys_set_thread_area
 	PTR	sys_inotify_init
 	PTR	sys_inotify_add_watch		/* 4285 */
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 66aac55..8acae31 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -706,6 +706,9 @@
 	for_each_memblock(reserved, reg)
 		if (reg->size != 0)
 			reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+
+	reserve_bootmem_region(__pa_symbol(&__nosave_begin),
+			__pa_symbol(&__nosave_end)); /* Reserve for hibernation */
 }
 
 static void __init resource_init(void)
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index bf792e2..9e35b6b 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -195,6 +195,9 @@
 	unsigned int csr;
 	int i, err;
 
+	if (!config_enabled(CONFIG_CPU_HAS_MSA))
+		return SIGSYS;
+
 	if (size != sizeof(*msa))
 		return -EINVAL;
 
@@ -398,8 +401,8 @@
 	}
 
 fp_done:
-	if (used & USED_EXTCONTEXT)
-		err |= restore_extcontext(sc_to_extcontext(sc));
+	if (!err && (used & USED_EXTCONTEXT))
+		err = restore_extcontext(sc_to_extcontext(sc));
 
 	return err ?: sig;
 }
@@ -767,15 +770,7 @@
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
 	struct mips_abi *abi = current->thread.abi;
-#ifdef CONFIG_CPU_MICROMIPS
-	void *vdso;
-	unsigned long tmp = (unsigned long)current->mm->context.vdso;
-
-	set_isa16_mode(tmp);
-	vdso = (void *)tmp;
-#else
 	void *vdso = current->mm->context.vdso;
-#endif
 
 	if (regs->regs[0]) {
 		switch(regs->regs[2]) {
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 2b521e0..7fef02a 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -174,6 +174,9 @@
 	cpumask_set_cpu(cpu, &cpu_coherent_mask);
 	notify_cpu_starting(cpu);
 
+	cpumask_set_cpu(cpu, &cpu_callin_map);
+	synchronise_count_slave(cpu);
+
 	set_cpu_online(cpu, true);
 
 	set_cpu_sibling_map(cpu);
@@ -181,10 +184,6 @@
 
 	calculate_cpu_foreign_map();
 
-	cpumask_set_cpu(cpu, &cpu_callin_map);
-
-	synchronise_count_slave(cpu);
-
 	/*
 	 * irq will be enabled in ->smp_finish(), enabling it too early
 	 * is dangerous.
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index ca9a810..31ca2ed 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -144,7 +144,7 @@
 	if (!task)
 		task = current;
 
-	if (raw_show_trace || !__kernel_text_address(pc)) {
+	if (raw_show_trace || user_mode(regs) || !__kernel_text_address(pc)) {
 		show_raw_backtrace(sp);
 		return;
 	}
@@ -194,6 +194,8 @@
 {
 	struct pt_regs regs;
 	mm_segment_t old_fs = get_fs();
+
+	regs.cp0_status = KSU_KERNEL;
 	if (sp) {
 		regs.regs[29] = (unsigned long)sp;
 		regs.regs[31] = 0;
@@ -1241,7 +1243,7 @@
 		err = init_fpu();
 		if (msa && !err) {
 			enable_msa();
-			_init_msa_upper();
+			init_msa_upper();
 			set_thread_flag(TIF_USEDMSA);
 			set_thread_flag(TIF_MSA_CTX_LIVE);
 		}
@@ -1304,7 +1306,7 @@
 	 */
 	prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
 	if (!prior_msa && was_fpu_owner) {
-		_init_msa_upper();
+		init_msa_upper();
 
 		goto out;
 	}
@@ -1321,7 +1323,7 @@
 		 * of each vector register such that it cannot see data left
 		 * behind by another task.
 		 */
-		_init_msa_upper();
+		init_msa_upper();
 	} else {
 		/* We need to restore the vector context. */
 		restore_msa(current);
diff --git a/arch/mips/kernel/uprobes.c b/arch/mips/kernel/uprobes.c
index 8452d93..4e7b89f 100644
--- a/arch/mips/kernel/uprobes.c
+++ b/arch/mips/kernel/uprobes.c
@@ -157,7 +157,6 @@
 int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs)
 {
 	struct uprobe_task *utask = current->utask;
-	union mips_instruction insn;
 
 	/*
 	 * Now find the EPC where to resume after the breakpoint has been
@@ -168,10 +167,10 @@
 		unsigned long epc;
 
 		epc = regs->cp0_epc;
-		__compute_return_epc_for_insn(regs, insn);
+		__compute_return_epc_for_insn(regs,
+			(union mips_instruction) aup->insn[0]);
 		aup->resume_epc = regs->cp0_epc;
 	}
-
 	utask->autask.saved_trap_nr = current->thread.trap_nr;
 	current->thread.trap_nr = UPROBE_TRAP_NR;
 	regs->cp0_epc = current->utask->xol_vaddr;
@@ -257,7 +256,7 @@
 	ra = regs->regs[31];
 
 	/* Replace the return address with the trampoline address */
-	regs->regs[31] = ra;
+	regs->regs[31] = trampoline_vaddr;
 
 	return ra;
 }
@@ -280,24 +279,6 @@
 	return uprobe_write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
 }
 
-/**
- * set_orig_insn - Restore the original instruction.
- * @mm: the probed process address space.
- * @auprobe: arch specific probepoint information.
- * @vaddr: the virtual address to insert the opcode.
- *
- * For mm @mm, restore the original opcode (opcode) at @vaddr.
- * Return 0 (success) or a negative errno.
- *
- * This overrides the weak version in kernel/events/uprobes.c.
- */
-int set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
-		 unsigned long vaddr)
-{
-	return uprobe_write_opcode(mm, vaddr,
-			*(uprobe_opcode_t *)&auprobe->orig_inst[0].word);
-}
-
 void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
 				  void *src, unsigned long len)
 {
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 975e997..5649a9e 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -39,16 +39,16 @@
 static void __init init_vdso_image(struct mips_vdso_image *image)
 {
 	unsigned long num_pages, i;
+	unsigned long data_pfn;
 
 	BUG_ON(!PAGE_ALIGNED(image->data));
 	BUG_ON(!PAGE_ALIGNED(image->size));
 
 	num_pages = image->size / PAGE_SIZE;
 
-	for (i = 0; i < num_pages; i++) {
-		image->mapping.pages[i] =
-			virt_to_page(image->data + (i * PAGE_SIZE));
-	}
+	data_pfn = __phys_to_pfn(__pa_symbol(image->data));
+	for (i = 0; i < num_pages; i++)
+		image->mapping.pages[i] = pfn_to_page(data_pfn + i);
 }
 
 static int __init init_vdso(void)
diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c
index 2a03abb..9b78e37 100644
--- a/arch/mips/kernel/watch.c
+++ b/arch/mips/kernel/watch.c
@@ -15,10 +15,9 @@
  * Install the watch registers for the current thread.	A maximum of
  * four registers are installed although the machine may have more.
  */
-void mips_install_watch_registers(void)
+void mips_install_watch_registers(struct task_struct *t)
 {
-	struct mips3264_watch_reg_state *watches =
-		&current->thread.watch.mips3264;
+	struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264;
 	switch (current_cpu_data.watch_reg_use_cnt) {
 	default:
 		BUG();
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 41b1b09..4c85ab8 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -302,12 +302,31 @@
  */
 static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
 {
-	ktime_t expires;
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	ktime_t expires, threshold;
+	uint32_t count, compare;
 	int running;
 
-	/* Is the hrtimer pending? */
+	/* Calculate the biased and scaled guest CP0_Count */
+	count = vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
+	compare = kvm_read_c0_guest_compare(cop0);
+
+	/*
+	 * Find whether CP0_Count has reached the closest timer interrupt. If
+	 * not, we shouldn't inject it.
+	 */
+	if ((int32_t)(count - compare) < 0)
+		return count;
+
+	/*
+	 * The CP0_Count we're going to return has already reached the closest
+	 * timer interrupt. Quickly check if it really is a new interrupt by
+	 * looking at whether the interval until the hrtimer expiry time is
+	 * less than 1/4 of the timer period.
+	 */
 	expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer);
-	if (ktime_compare(now, expires) >= 0) {
+	threshold = ktime_add_ns(now, vcpu->arch.count_period / 4);
+	if (ktime_before(expires, threshold)) {
 		/*
 		 * Cancel it while we handle it so there's no chance of
 		 * interference with the timeout handler.
@@ -329,8 +348,7 @@
 		}
 	}
 
-	/* Return the biased and scaled guest CP0_Count */
-	return vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
+	return count;
 }
 
 /**
@@ -420,32 +438,6 @@
 }
 
 /**
- * kvm_mips_update_hrtimer() - Update next expiry time of hrtimer.
- * @vcpu:	Virtual CPU.
- *
- * Recalculates and updates the expiry time of the hrtimer. This can be used
- * after timer parameters have been altered which do not depend on the time that
- * the change occurs (in those cases kvm_mips_freeze_hrtimer() and
- * kvm_mips_resume_hrtimer() are used directly).
- *
- * It is guaranteed that no timer interrupts will be lost in the process.
- *
- * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
- */
-static void kvm_mips_update_hrtimer(struct kvm_vcpu *vcpu)
-{
-	ktime_t now;
-	uint32_t count;
-
-	/*
-	 * freeze_hrtimer takes care of a timer interrupts <= count, and
-	 * resume_hrtimer the hrtimer takes care of a timer interrupts > count.
-	 */
-	now = kvm_mips_freeze_hrtimer(vcpu, &count);
-	kvm_mips_resume_hrtimer(vcpu, now, count);
-}
-
-/**
  * kvm_mips_write_count() - Modify the count and update timer.
  * @vcpu:	Virtual CPU.
  * @count:	Guest CP0_Count value to set.
@@ -540,23 +532,42 @@
  * kvm_mips_write_compare() - Modify compare and update timer.
  * @vcpu:	Virtual CPU.
  * @compare:	New CP0_Compare value.
+ * @ack:	Whether to acknowledge timer interrupt.
  *
  * Update CP0_Compare to a new value and update the timeout.
+ * If @ack, atomically acknowledge any pending timer interrupt, otherwise ensure
+ * any pending timer interrupt is preserved.
  */
-void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare)
+void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare, bool ack)
 {
 	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	int dc;
+	u32 old_compare = kvm_read_c0_guest_compare(cop0);
+	ktime_t now;
+	uint32_t count;
 
 	/* if unchanged, must just be an ack */
-	if (kvm_read_c0_guest_compare(cop0) == compare)
+	if (old_compare == compare) {
+		if (!ack)
+			return;
+		kvm_mips_callbacks->dequeue_timer_int(vcpu);
+		kvm_write_c0_guest_compare(cop0, compare);
 		return;
+	}
 
-	/* Update compare */
+	/* freeze_hrtimer() takes care of timer interrupts <= count */
+	dc = kvm_mips_count_disabled(vcpu);
+	if (!dc)
+		now = kvm_mips_freeze_hrtimer(vcpu, &count);
+
+	if (ack)
+		kvm_mips_callbacks->dequeue_timer_int(vcpu);
+
 	kvm_write_c0_guest_compare(cop0, compare);
 
-	/* Update timeout if count enabled */
-	if (!kvm_mips_count_disabled(vcpu))
-		kvm_mips_update_hrtimer(vcpu);
+	/* resume_hrtimer() takes care of timer interrupts > count */
+	if (!dc)
+		kvm_mips_resume_hrtimer(vcpu, now, count);
 }
 
 /**
@@ -741,15 +752,15 @@
 	struct mips_coproc *cop0 = vcpu->arch.cop0;
 	enum emulation_result er = EMULATE_DONE;
 
-	if (kvm_read_c0_guest_status(cop0) & ST0_EXL) {
+	if (kvm_read_c0_guest_status(cop0) & ST0_ERL) {
+		kvm_clear_c0_guest_status(cop0, ST0_ERL);
+		vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
+	} else if (kvm_read_c0_guest_status(cop0) & ST0_EXL) {
 		kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc,
 			  kvm_read_c0_guest_epc(cop0));
 		kvm_clear_c0_guest_status(cop0, ST0_EXL);
 		vcpu->arch.pc = kvm_read_c0_guest_epc(cop0);
 
-	} else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) {
-		kvm_clear_c0_guest_status(cop0, ST0_ERL);
-		vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
 	} else {
 		kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n",
 			vcpu->arch.pc);
@@ -796,6 +807,47 @@
 	return EMULATE_FAIL;
 }
 
+/**
+ * kvm_mips_invalidate_guest_tlb() - Indicates a change in guest MMU map.
+ * @vcpu:	VCPU with changed mappings.
+ * @tlb:	TLB entry being removed.
+ *
+ * This is called to indicate a single change in guest MMU mappings, so that we
+ * can arrange TLB flushes on this and other CPUs.
+ */
+static void kvm_mips_invalidate_guest_tlb(struct kvm_vcpu *vcpu,
+					  struct kvm_mips_tlb *tlb)
+{
+	int cpu, i;
+	bool user;
+
+	/* No need to flush for entries which are already invalid */
+	if (!((tlb->tlb_lo0 | tlb->tlb_lo1) & MIPS3_PG_V))
+		return;
+	/* User address space doesn't need flushing for KSeg2/3 changes */
+	user = tlb->tlb_hi < KVM_GUEST_KSEG0;
+
+	preempt_disable();
+
+	/*
+	 * Probe the shadow host TLB for the entry being overwritten, if one
+	 * matches, invalidate it
+	 */
+	kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
+
+	/* Invalidate the whole ASID on other CPUs */
+	cpu = smp_processor_id();
+	for_each_possible_cpu(i) {
+		if (i == cpu)
+			continue;
+		if (user)
+			vcpu->arch.guest_user_asid[i] = 0;
+		vcpu->arch.guest_kernel_asid[i] = 0;
+	}
+
+	preempt_enable();
+}
+
 /* Write Guest TLB Entry @ Index */
 enum emulation_result kvm_mips_emul_tlbwi(struct kvm_vcpu *vcpu)
 {
@@ -815,11 +867,8 @@
 	}
 
 	tlb = &vcpu->arch.guest_tlb[index];
-	/*
-	 * Probe the shadow host TLB for the entry being overwritten, if one
-	 * matches, invalidate it
-	 */
-	kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
+
+	kvm_mips_invalidate_guest_tlb(vcpu, tlb);
 
 	tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
 	tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
@@ -848,11 +897,7 @@
 
 	tlb = &vcpu->arch.guest_tlb[index];
 
-	/*
-	 * Probe the shadow host TLB for the entry being overwritten, if one
-	 * matches, invalidate it
-	 */
-	kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
+	kvm_mips_invalidate_guest_tlb(vcpu, tlb);
 
 	tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
 	tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
@@ -971,6 +1016,7 @@
 	int32_t rt, rd, copz, sel, co_bit, op;
 	uint32_t pc = vcpu->arch.pc;
 	unsigned long curr_pc;
+	int cpu, i;
 
 	/*
 	 * Update PC and hold onto current PC in case there is
@@ -1078,8 +1124,16 @@
 						vcpu->arch.gprs[rt]
 						& ASID_MASK);
 
+					preempt_disable();
 					/* Blow away the shadow host TLBs */
 					kvm_mips_flush_host_tlb(1);
+					cpu = smp_processor_id();
+					for_each_possible_cpu(i)
+						if (i != cpu) {
+							vcpu->arch.guest_user_asid[i] = 0;
+							vcpu->arch.guest_kernel_asid[i] = 0;
+						}
+					preempt_enable();
 				}
 				kvm_write_c0_guest_entryhi(cop0,
 							   vcpu->arch.gprs[rt]);
@@ -1095,9 +1149,9 @@
 
 				/* If we are writing to COMPARE */
 				/* Clear pending timer interrupt, if any */
-				kvm_mips_callbacks->dequeue_timer_int(vcpu);
 				kvm_mips_write_compare(vcpu,
-						       vcpu->arch.gprs[rt]);
+						       vcpu->arch.gprs[rt],
+						       true);
 			} else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) {
 				unsigned int old_val, val, change;
 
@@ -1419,6 +1473,7 @@
 					    struct kvm_vcpu *vcpu)
 {
 	enum emulation_result er = EMULATE_DO_MMIO;
+	unsigned long curr_pc;
 	int32_t op, base, rt, offset;
 	uint32_t bytes;
 
@@ -1427,7 +1482,18 @@
 	offset = inst & 0xffff;
 	op = (inst >> 26) & 0x3f;
 
-	vcpu->arch.pending_load_cause = cause;
+	/*
+	 * Find the resume PC now while we have safe and easy access to the
+	 * prior branch instruction, and save it for
+	 * kvm_mips_complete_mmio_load() to restore later.
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+	vcpu->arch.io_pc = vcpu->arch.pc;
+	vcpu->arch.pc = curr_pc;
+
 	vcpu->arch.io_gpr = rt;
 
 	switch (op) {
@@ -1618,8 +1684,14 @@
 
 	preempt_disable();
 	if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) {
-		if (kvm_mips_host_tlb_lookup(vcpu, va) < 0)
-			kvm_mips_handle_kseg0_tlb_fault(va, vcpu);
+		if (kvm_mips_host_tlb_lookup(vcpu, va) < 0 &&
+		    kvm_mips_handle_kseg0_tlb_fault(va, vcpu)) {
+			kvm_err("%s: handling mapped kseg0 tlb fault for %lx, vcpu: %p, ASID: %#lx\n",
+				__func__, va, vcpu, read_c0_entryhi());
+			er = EMULATE_FAIL;
+			preempt_enable();
+			goto done;
+		}
 	} else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) ||
 		   KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) {
 		int index;
@@ -1654,14 +1726,19 @@
 								run, vcpu);
 				preempt_enable();
 				goto dont_update_pc;
-			} else {
-				/*
-				 * We fault an entry from the guest tlb to the
-				 * shadow host TLB
-				 */
-				kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
-								     NULL,
-								     NULL);
+			}
+			/*
+			 * We fault an entry from the guest tlb to the
+			 * shadow host TLB
+			 */
+			if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
+								 NULL, NULL)) {
+				kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n",
+					__func__, va, index, vcpu,
+					read_c0_entryhi());
+				er = EMULATE_FAIL;
+				preempt_enable();
+				goto done;
 			}
 		}
 	} else {
@@ -2396,9 +2473,8 @@
 		goto done;
 	}
 
-	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
-	if (er == EMULATE_FAIL)
-		return er;
+	/* Restore saved resume PC */
+	vcpu->arch.pc = vcpu->arch.io_pc;
 
 	switch (run->mmio.len) {
 	case 4:
@@ -2420,11 +2496,6 @@
 		break;
 	}
 
-	if (vcpu->arch.pending_load_cause & CAUSEF_BD)
-		kvm_debug("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
-			  vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
-			  vcpu->mmio_needed);
-
 done:
 	return er;
 }
@@ -2622,8 +2693,13 @@
 			 * OK we have a Guest TLB entry, now inject it into the
 			 * shadow host TLB
 			 */
-			kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL,
-							     NULL);
+			if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
+								 NULL, NULL)) {
+				kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n",
+					__func__, va, index, vcpu,
+					read_c0_entryhi());
+				er = EMULATE_FAIL;
+			}
 		}
 	}
 
diff --git a/arch/mips/kvm/interrupt.h b/arch/mips/kvm/interrupt.h
index 4ab4bdf..2143884 100644
--- a/arch/mips/kvm/interrupt.h
+++ b/arch/mips/kvm/interrupt.h
@@ -28,6 +28,7 @@
 #define MIPS_EXC_MAX                12
 /* XXXSL More to follow */
 
+extern char __kvm_mips_vcpu_run_end[];
 extern char mips32_exception[], mips32_exceptionEnd[];
 extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
 
diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S
index 7e22108..7770643 100644
--- a/arch/mips/kvm/locore.S
+++ b/arch/mips/kvm/locore.S
@@ -227,6 +227,7 @@
 
 	/* Jump to guest */
 	eret
+EXPORT(__kvm_mips_vcpu_run_end)
 
 VECTOR(MIPSX(exception), unknown)
 /* Find out what mode we came from and jump to the proper handler. */
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index 2683d04..a017b23 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -314,9 +314,18 @@
 	memcpy(gebase + offset, mips32_GuestException,
 	       mips32_GuestExceptionEnd - mips32_GuestException);
 
+#ifdef MODULE
+	offset += mips32_GuestExceptionEnd - mips32_GuestException;
+	memcpy(gebase + offset, (char *)__kvm_mips_vcpu_run,
+	       __kvm_mips_vcpu_run_end - (char *)__kvm_mips_vcpu_run);
+	vcpu->arch.vcpu_run = gebase + offset;
+#else
+	vcpu->arch.vcpu_run = __kvm_mips_vcpu_run;
+#endif
+
 	/* Invalidate the icache for these ranges */
-	local_flush_icache_range((unsigned long)gebase,
-				(unsigned long)gebase + ALIGN(size, PAGE_SIZE));
+	flush_icache_range((unsigned long)gebase,
+			   (unsigned long)gebase + ALIGN(size, PAGE_SIZE));
 
 	/*
 	 * Allocate comm page for guest kernel, a TLB will be reserved for
@@ -403,7 +412,7 @@
 	/* Disable hardware page table walking while in guest */
 	htw_stop();
 
-	r = __kvm_mips_vcpu_run(run, vcpu);
+	r = vcpu->arch.vcpu_run(run, vcpu);
 
 	/* Re-enable HTW before enabling interrupts */
 	htw_start();
diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c
index aed0ac2..eff71c7 100644
--- a/arch/mips/kvm/tlb.c
+++ b/arch/mips/kvm/tlb.c
@@ -152,7 +152,7 @@
 	srcu_idx = srcu_read_lock(&kvm->srcu);
 	pfn = kvm_mips_gfn_to_pfn(kvm, gfn);
 
-	if (kvm_mips_is_error_pfn(pfn)) {
+	if (is_error_noslot_pfn(pfn)) {
 		kvm_err("Couldn't get pfn for gfn %#" PRIx64 "!\n", gfn);
 		err = -EFAULT;
 		goto out;
@@ -276,7 +276,7 @@
 	}
 
 	gfn = (KVM_GUEST_CPHYSADDR(badvaddr) >> PAGE_SHIFT);
-	if (gfn >= kvm->arch.guest_pmap_npages) {
+	if ((gfn | 1) >= kvm->arch.guest_pmap_npages) {
 		kvm_err("%s: Invalid gfn: %#llx, BadVaddr: %#lx\n", __func__,
 			gfn, badvaddr);
 		kvm_mips_dump_host_tlbs();
@@ -361,25 +361,39 @@
 	unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
 	struct kvm *kvm = vcpu->kvm;
 	pfn_t pfn0, pfn1;
+	gfn_t gfn0, gfn1;
+	long tlb_lo[2];
 
-	if ((tlb->tlb_hi & VPN2_MASK) == 0) {
-		pfn0 = 0;
-		pfn1 = 0;
-	} else {
-		if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0)
-					   >> PAGE_SHIFT) < 0)
-			return -1;
+	tlb_lo[0] = tlb->tlb_lo0;
+	tlb_lo[1] = tlb->tlb_lo1;
 
-		if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1)
-					   >> PAGE_SHIFT) < 0)
-			return -1;
+	/*
+	 * The commpage address must not be mapped to anything else if the guest
+	 * TLB contains entries nearby, or commpage accesses will break.
+	 */
+	if (!((tlb->tlb_hi ^ KVM_GUEST_COMMPAGE_ADDR) &
+			VPN2_MASK & (PAGE_MASK << 1)))
+		tlb_lo[(KVM_GUEST_COMMPAGE_ADDR >> PAGE_SHIFT) & 1] = 0;
 
-		pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0)
-					    >> PAGE_SHIFT];
-		pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1)
-					    >> PAGE_SHIFT];
+	gfn0 = mips3_tlbpfn_to_paddr(tlb_lo[0]) >> PAGE_SHIFT;
+	gfn1 = mips3_tlbpfn_to_paddr(tlb_lo[1]) >> PAGE_SHIFT;
+	if (gfn0 >= kvm->arch.guest_pmap_npages ||
+	    gfn1 >= kvm->arch.guest_pmap_npages) {
+		kvm_err("%s: Invalid gfn: [%#llx, %#llx], EHi: %#lx\n",
+			__func__, gfn0, gfn1, tlb->tlb_hi);
+		kvm_mips_dump_guest_tlbs(vcpu);
+		return -1;
 	}
 
+	if (kvm_mips_map_page(kvm, gfn0) < 0)
+		return -1;
+
+	if (kvm_mips_map_page(kvm, gfn1) < 0)
+		return -1;
+
+	pfn0 = kvm->arch.guest_pmap[gfn0];
+	pfn1 = kvm->arch.guest_pmap[gfn1];
+
 	if (hpa0)
 		*hpa0 = pfn0 << PAGE_SHIFT;
 
@@ -391,9 +405,9 @@
 					       kvm_mips_get_kernel_asid(vcpu) :
 					       kvm_mips_get_user_asid(vcpu));
 	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
-		   (tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V);
+		   (tlb_lo[0] & MIPS3_PG_D) | (tlb_lo[0] & MIPS3_PG_V);
 	entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
-		   (tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V);
+		   (tlb_lo[1] & MIPS3_PG_D) | (tlb_lo[1] & MIPS3_PG_V);
 
 	kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,
 		  tlb->tlb_lo0, tlb->tlb_lo1);
@@ -794,10 +808,16 @@
 				local_irq_restore(flags);
 				return KVM_INVALID_INST;
 			}
-			kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
-							     &vcpu->arch.
-							     guest_tlb[index],
-							     NULL, NULL);
+			if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
+						&vcpu->arch.guest_tlb[index],
+						NULL, NULL)) {
+				kvm_err("%s: handling mapped seg tlb fault failed for %p, index: %u, vcpu: %p, ASID: %#lx\n",
+					__func__, opc, index, vcpu,
+					read_c0_entryhi());
+				kvm_mips_dump_guest_tlbs(vcpu);
+				local_irq_restore(flags);
+				return KVM_INVALID_INST;
+			}
 			inst = *(opc);
 		}
 		local_irq_restore(flags);
diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c
index d836ed5..307cc4c 100644
--- a/arch/mips/kvm/trap_emul.c
+++ b/arch/mips/kvm/trap_emul.c
@@ -547,7 +547,7 @@
 		kvm_mips_write_count(vcpu, v);
 		break;
 	case KVM_REG_MIPS_CP0_COMPARE:
-		kvm_mips_write_compare(vcpu, v);
+		kvm_mips_write_compare(vcpu, v, false);
 		break;
 	case KVM_REG_MIPS_CP0_CAUSE:
 		/*
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 80554e8..daf580c 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -467,7 +467,7 @@
 
 		if (!np_xbar)
 			panic("Failed to load xbar nodes from devicetree");
-		if (of_address_to_resource(np_pmu, 0, &res_xbar))
+		if (of_address_to_resource(np_xbar, 0, &res_xbar))
 			panic("Failed to get xbar resources");
 		if (request_mem_region(res_xbar.start, resource_size(&res_xbar),
 			res_xbar.name) < 0)
@@ -545,7 +545,7 @@
 		clkdev_add_pmu("1a800000.pcie", "msi", 1, 1, PMU1_PCIE2_MSI);
 		clkdev_add_pmu("1a800000.pcie", "pdi", 1, 1, PMU1_PCIE2_PDI);
 		clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL);
-		clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DP);
+		clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH | PMU_PPE_DP);
 		clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
 		clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
 	} else if (of_machine_is_compatible("lantiq,ar10")) {
@@ -553,7 +553,7 @@
 				  ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz());
 		clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
 		clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
-		clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH |
+		clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH |
 			       PMU_PPE_DP | PMU_PPE_TC);
 		clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
 		clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
@@ -575,11 +575,11 @@
 		clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS);
 
 		clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
-		clkdev_add_pmu("1e108000.eth", NULL, 1, 0,
+		clkdev_add_pmu("1e108000.eth", NULL, 0, 0,
 				PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
 				PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
 				PMU_PPE_QSB | PMU_PPE_TOP);
-		clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
+		clkdev_add_pmu("1f203000.rcu", "gphy", 0, 0, PMU_GPHY);
 		clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
 		clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
 		clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c
index beb80f31..927dc94 100644
--- a/arch/mips/lib/ashldi3.c
+++ b/arch/mips/lib/ashldi3.c
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-long long __ashldi3(long long u, word_type b)
+long long notrace __ashldi3(long long u, word_type b)
 {
 	DWunion uu, w;
 	word_type bm;
diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c
index c884a91..9fdf1a5 100644
--- a/arch/mips/lib/ashrdi3.c
+++ b/arch/mips/lib/ashrdi3.c
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-long long __ashrdi3(long long u, word_type b)
+long long notrace __ashrdi3(long long u, word_type b)
 {
 	DWunion uu, w;
 	word_type bm;
diff --git a/arch/mips/lib/bswapdi.c b/arch/mips/lib/bswapdi.c
index 77e5f9c..e3e77aa 100644
--- a/arch/mips/lib/bswapdi.c
+++ b/arch/mips/lib/bswapdi.c
@@ -1,6 +1,6 @@
 #include <linux/module.h>
 
-unsigned long long __bswapdi2(unsigned long long u)
+unsigned long long notrace __bswapdi2(unsigned long long u)
 {
 	return (((u) & 0xff00000000000000ull) >> 56) |
 	       (((u) & 0x00ff000000000000ull) >> 40) |
diff --git a/arch/mips/lib/bswapsi.c b/arch/mips/lib/bswapsi.c
index 2b302ff..530a8af 100644
--- a/arch/mips/lib/bswapsi.c
+++ b/arch/mips/lib/bswapsi.c
@@ -1,6 +1,6 @@
 #include <linux/module.h>
 
-unsigned int __bswapsi2(unsigned int u)
+unsigned int notrace __bswapsi2(unsigned int u)
 {
 	return (((u) & 0xff000000) >> 24) |
 	       (((u) & 0x00ff0000) >>  8) |
diff --git a/arch/mips/lib/cmpdi2.c b/arch/mips/lib/cmpdi2.c
index 8c13064..06857da 100644
--- a/arch/mips/lib/cmpdi2.c
+++ b/arch/mips/lib/cmpdi2.c
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-word_type __cmpdi2(long long a, long long b)
+word_type notrace __cmpdi2(long long a, long long b)
 {
 	const DWunion au = {
 		.ll = a
diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c
index dcf8d68..3645474 100644
--- a/arch/mips/lib/lshrdi3.c
+++ b/arch/mips/lib/lshrdi3.c
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-long long __lshrdi3(long long u, word_type b)
+long long notrace __lshrdi3(long long u, word_type b)
 {
 	DWunion uu, w;
 	word_type bm;
diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c
index bb4cb2f..bd599f5 100644
--- a/arch/mips/lib/ucmpdi2.c
+++ b/arch/mips/lib/ucmpdi2.c
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+word_type notrace __ucmpdi2(unsigned long long a, unsigned long long b)
 {
 	const DWunion au = {.ll = a};
 	const DWunion bu = {.ll = b};
diff --git a/arch/mips/loongson64/loongson-3/hpet.c b/arch/mips/loongson64/loongson-3/hpet.c
index a2631a5..444802e 100644
--- a/arch/mips/loongson64/loongson-3/hpet.c
+++ b/arch/mips/loongson64/loongson-3/hpet.c
@@ -13,8 +13,8 @@
 #define SMBUS_PCI_REG64		0x64
 #define SMBUS_PCI_REGB4		0xb4
 
-#define HPET_MIN_CYCLES		64
-#define HPET_MIN_PROG_DELTA	(HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
+#define HPET_MIN_CYCLES		16
+#define HPET_MIN_PROG_DELTA	(HPET_MIN_CYCLES * 12)
 
 static DEFINE_SPINLOCK(hpet_lock);
 DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
@@ -157,14 +157,14 @@
 static int hpet_next_event(unsigned long delta,
 		struct clock_event_device *evt)
 {
-	unsigned int cnt;
-	int res;
+	u32 cnt;
+	s32 res;
 
 	cnt = hpet_read(HPET_COUNTER);
-	cnt += delta;
+	cnt += (u32) delta;
 	hpet_write(HPET_T0_CMP, cnt);
 
-	res = (int)(cnt - hpet_read(HPET_COUNTER));
+	res = (s32)(cnt - hpet_read(HPET_COUNTER));
 
 	return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
@@ -230,7 +230,7 @@
 
 	cd = &per_cpu(hpet_clockevent_device, cpu);
 	cd->name = "hpet";
-	cd->rating = 320;
+	cd->rating = 100;
 	cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
 	cd->set_state_shutdown = hpet_set_state_shutdown;
 	cd->set_state_periodic = hpet_set_state_periodic;
diff --git a/arch/mips/loongson64/loongson-3/numa.c b/arch/mips/loongson64/loongson-3/numa.c
index 6f9e010..282c5a8 100644
--- a/arch/mips/loongson64/loongson-3/numa.c
+++ b/arch/mips/loongson64/loongson-3/numa.c
@@ -213,10 +213,10 @@
 		BOOTMEM_DEFAULT);
 
 	if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
-		/* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
+		/* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */
 		reserve_bootmem_node(NODE_DATA(node),
-				(node_addrspace_offset | 0xff800000),
-				8 << 20, BOOTMEM_DEFAULT);
+				(node_addrspace_offset | 0xfe000000),
+				32 << 20, BOOTMEM_DEFAULT);
 	}
 
 	sparse_memory_present_with_active_regions(node);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 32f0e19..734a2c7 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -445,9 +445,11 @@
 	case spec_op:
 		switch (insn.r_format.func) {
 		case jalr_op:
-			regs->regs[insn.r_format.rd] =
-				regs->cp0_epc + dec_insn.pc_inc +
-				dec_insn.next_pc_inc;
+			if (insn.r_format.rd != 0) {
+				regs->regs[insn.r_format.rd] =
+					regs->cp0_epc + dec_insn.pc_inc +
+					dec_insn.next_pc_inc;
+			}
 			/* Fall through */
 		case jr_op:
 			/* For R6, JR already emulated in jalr_op */
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index aab218c..e87bccd 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 
 #include <asm/cacheflush.h>
+#include <asm/highmem.h>
 #include <asm/processor.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
@@ -83,8 +84,6 @@
 	struct address_space *mapping = page_mapping(page);
 	unsigned long addr;
 
-	if (PageHighMem(page))
-		return;
 	if (mapping && !mapping_mapped(mapping)) {
 		SetPageDcacheDirty(page);
 		return;
@@ -95,8 +94,15 @@
 	 * case is for exec env/arg pages and those are %99 certainly going to
 	 * get faulted into the tlb (and thus flushed) anyways.
 	 */
-	addr = (unsigned long) page_address(page);
+	if (PageHighMem(page))
+		addr = (unsigned long)kmap_atomic(page);
+	else
+		addr = (unsigned long)page_address(page);
+
 	flush_data_cache_page(addr);
+
+	if (PageHighMem(page))
+		__kunmap_atomic((void *)addr);
 }
 
 EXPORT_SYMBOL(__flush_dcache_page);
@@ -119,33 +125,28 @@
 
 EXPORT_SYMBOL(__flush_anon_page);
 
-void __flush_icache_page(struct vm_area_struct *vma, struct page *page)
-{
-	unsigned long addr;
-
-	if (PageHighMem(page))
-		return;
-
-	addr = (unsigned long) page_address(page);
-	flush_data_cache_page(addr);
-}
-EXPORT_SYMBOL_GPL(__flush_icache_page);
-
-void __update_cache(struct vm_area_struct *vma, unsigned long address,
-	pte_t pte)
+void __update_cache(unsigned long address, pte_t pte)
 {
 	struct page *page;
 	unsigned long pfn, addr;
-	int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
+	int exec = !pte_no_exec(pte) && !cpu_has_ic_fills_f_dc;
 
 	pfn = pte_pfn(pte);
 	if (unlikely(!pfn_valid(pfn)))
 		return;
 	page = pfn_to_page(pfn);
-	if (page_mapping(page) && Page_dcache_dirty(page)) {
-		addr = (unsigned long) page_address(page);
+	if (Page_dcache_dirty(page)) {
+		if (PageHighMem(page))
+			addr = (unsigned long)kmap_atomic(page);
+		else
+			addr = (unsigned long)page_address(page);
+
 		if (exec || pages_do_alias(addr, address & PAGE_MASK))
 			flush_data_cache_page(addr);
+
+		if (PageHighMem(page))
+			__kunmap_atomic((void *)addr);
+
 		ClearPageDcacheDirty(page);
 	}
 }
diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
index 3530376..c5fdea5 100644
--- a/arch/mips/mm/mmap.c
+++ b/arch/mips/mm/mmap.c
@@ -92,7 +92,7 @@
 
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
diff --git a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c
index dc7c5a5..efaf364 100644
--- a/arch/mips/mm/sc-ip22.c
+++ b/arch/mips/mm/sc-ip22.c
@@ -31,26 +31,40 @@
 	unsigned long tmp;
 
 	__asm__ __volatile__(
-	".set\tpush\t\t\t# indy_sc_wipe\n\t"
-	".set\tnoreorder\n\t"
-	".set\tmips3\n\t"
-	".set\tnoat\n\t"
-	"mfc0\t%2, $12\n\t"
-	"li\t$1, 0x80\t\t\t# Go 64 bit\n\t"
-	"mtc0\t$1, $12\n\t"
-
-	"dli\t$1, 0x9000000080000000\n\t"
-	"or\t%0, $1\t\t\t# first line to flush\n\t"
-	"or\t%1, $1\t\t\t# last line to flush\n\t"
-	".set\tat\n\t"
-
-	"1:\tsw\t$0, 0(%0)\n\t"
-	"bne\t%0, %1, 1b\n\t"
-	" daddu\t%0, 32\n\t"
-
-	"mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t"
-	"nop; nop; nop; nop;\n\t"
-	".set\tpop"
+	"	.set	push			# indy_sc_wipe		\n"
+	"	.set	noreorder					\n"
+	"	.set	mips3						\n"
+	"	.set	noat						\n"
+	"	mfc0	%2, $12						\n"
+	"	li	$1, 0x80		# Go 64 bit		\n"
+	"	mtc0	$1, $12						\n"
+	"								\n"
+	"	#							\n"
+	"	# Open code a dli $1, 0x9000000080000000		\n"
+	"	#							\n"
+	"	# Required because binutils 2.25 will happily accept	\n"
+	"	# 64 bit instructions in .set mips3 mode but puke on	\n"
+	"	# 64 bit constants when generating 32 bit ELF		\n"
+	"	#							\n"
+	"	lui	$1,0x9000					\n"
+	"	dsll	$1,$1,0x10					\n"
+	"	ori	$1,$1,0x8000					\n"
+	"	dsll	$1,$1,0x10					\n"
+	"								\n"
+	"	or	%0, $1			# first line to flush	\n"
+	"	or	%1, $1			# last line to flush	\n"
+	"	.set	at						\n"
+	"								\n"
+	"1:	sw	$0, 0(%0)					\n"
+	"	bne	%0, %1, 1b					\n"
+	"	 daddu	%0, 32						\n"
+	"								\n"
+	"	mtc0	%2, $12			# Back to 32 bit	\n"
+	"	nop				# pipeline hazard	\n"
+	"	nop							\n"
+	"	nop							\n"
+	"	nop							\n"
+	"	.set	pop						\n"
 	: "=r" (first), "=r" (last), "=&r" (tmp)
 	: "0" (first), "1" (last));
 }
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 29f73e0..63b7d6f 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -757,7 +757,8 @@
 static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r,
 				    struct uasm_label **l,
 				    unsigned int pte,
-				    unsigned int ptr)
+				    unsigned int ptr,
+				    unsigned int flush)
 {
 #ifdef CONFIG_SMP
 	UASM_i_SC(p, pte, 0, ptr);
@@ -766,6 +767,22 @@
 #else
 	UASM_i_SW(p, pte, 0, ptr);
 #endif
+	if (cpu_has_ftlb && flush) {
+		BUG_ON(!cpu_has_tlbinv);
+
+		UASM_i_MFC0(p, ptr, C0_ENTRYHI);
+		uasm_i_ori(p, ptr, ptr, MIPS_ENTRYHI_EHINV);
+		UASM_i_MTC0(p, ptr, C0_ENTRYHI);
+		build_tlb_write_entry(p, l, r, tlb_indexed);
+
+		uasm_i_xori(p, ptr, ptr, MIPS_ENTRYHI_EHINV);
+		UASM_i_MTC0(p, ptr, C0_ENTRYHI);
+		build_huge_update_entries(p, pte, ptr);
+		build_huge_tlb_write_entry(p, l, r, pte, tlb_random, 0);
+
+		return;
+	}
+
 	build_huge_update_entries(p, pte, ptr);
 	build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0);
 }
@@ -2082,7 +2099,7 @@
 		uasm_l_tlbl_goaround2(&l, p);
 	}
 	uasm_i_ori(&p, wr.r1, wr.r1, (_PAGE_ACCESSED | _PAGE_VALID));
-	build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
+	build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 1);
 #endif
 
 	uasm_l_nopage_tlbl(&l, p);
@@ -2137,7 +2154,7 @@
 	build_tlb_probe_entry(&p);
 	uasm_i_ori(&p, wr.r1, wr.r1,
 		   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
-	build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
+	build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 1);
 #endif
 
 	uasm_l_nopage_tlbs(&l, p);
@@ -2193,7 +2210,7 @@
 	build_tlb_probe_entry(&p);
 	uasm_i_ori(&p, wr.r1, wr.r1,
 		   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
-	build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
+	build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 0);
 #endif
 
 	uasm_l_nopage_tlbm(&l, p);
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
index b4a83789..5abe51c 100644
--- a/arch/mips/mm/uasm-mips.c
+++ b/arch/mips/mm/uasm-mips.c
@@ -65,7 +65,7 @@
 #ifndef CONFIG_CPU_MIPSR6
 	{ insn_cache,  M(cache_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 #else
-	{ insn_cache,  M6(cache_op, 0, 0, 0, cache6_op),  RS | RT | SIMM9 },
+	{ insn_cache,  M6(spec3_op, 0, 0, 0, cache6_op),  RS | RT | SIMM9 },
 #endif
 	{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
 	{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c
index 4740c82..36b09b2 100644
--- a/arch/mips/mti-malta/malta-setup.c
+++ b/arch/mips/mti-malta/malta-setup.c
@@ -39,6 +39,9 @@
 #include <linux/console.h>
 #endif
 
+#define ROCIT_CONFIG_GEN0		0x1f403000
+#define  ROCIT_CONFIG_GEN0_PCI_IOCU	BIT(7)
+
 extern void malta_be_init(void);
 extern int malta_be_handler(struct pt_regs *regs, int is_fixup);
 
@@ -107,6 +110,8 @@
 static int __init plat_enable_iocoherency(void)
 {
 	int supported = 0;
+	u32 cfg;
+
 	if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
 		if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
 			BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
@@ -129,7 +134,8 @@
 	} else if (mips_cm_numiocu() != 0) {
 		/* Nothing special needs to be done to enable coherency */
 		pr_info("CMP IOCU detected\n");
-		if ((*(unsigned int *)0xbf403000 & 0x81) != 0x81) {
+		cfg = __raw_readl((u32 *)CKSEG1ADDR(ROCIT_CONFIG_GEN0));
+		if (!(cfg & ROCIT_CONFIG_GEN0_PCI_IOCU)) {
 			pr_crit("IOCU OPERATION DISABLED BY SWITCH - DEFAULTING TO SW IO COHERENCY\n");
 			return 0;
 		}
diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index edbab9b..c474981 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -50,7 +50,6 @@
 #include <asm/netlogic/xlp-hal/sys.h>
 #include <asm/netlogic/xlp-hal/cpucontrol.h>
 
-#define CP0_EBASE	$15
 #define SYS_CPU_COHERENT_BASE	CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \
 			XLP_IO_SYS_OFFSET(0) + XLP_IO_PCI_HDRSZ + \
 			SYS_CPU_NONCOHERENT_MODE * 4
@@ -92,7 +91,7 @@
  * registers. On XLPII CPUs, usual cache instructions work.
  */
 .macro	xlp_flush_l1_dcache
-	mfc0	t0, CP0_EBASE, 0
+	mfc0	t0, CP0_PRID
 	andi	t0, t0, PRID_IMP_MASK
 	slt	t1, t0, 0x1200
 	beqz	t1, 15f
@@ -171,7 +170,7 @@
 	nop
 
 1:	/* Entry point on core wakeup */
-	mfc0	t0, CP0_EBASE, 0	/* processor ID */
+	mfc0	t0, CP0_PRID		/* processor ID */
 	andi	t0, PRID_IMP_MASK
 	li	t1, 0x1500		/* XLP 9xx */
 	beq	t0, t1, 2f		/* does not need to set coherent */
@@ -182,8 +181,8 @@
 	nop
 
 	/* set bit in SYS coherent register for the core */
-	mfc0	t0, CP0_EBASE, 1
-	mfc0	t1, CP0_EBASE, 1
+	mfc0	t0, CP0_EBASE
+	mfc0	t1, CP0_EBASE
 	srl	t1, 5
 	andi	t1, 0x3			/* t1 <- node */
 	li	t2, 0x40000
@@ -232,7 +231,7 @@
 
 	 * NOTE: All GPR contents are lost after the mtcr above!
 	 */
-	mfc0	v0, CP0_EBASE, 1
+	mfc0	v0, CP0_EBASE
 	andi	v0, 0x3ff		/* v0 <- node/core */
 
 	/*
diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S
index 805355b..f0cc4c9 100644
--- a/arch/mips/netlogic/common/smpboot.S
+++ b/arch/mips/netlogic/common/smpboot.S
@@ -48,8 +48,6 @@
 #include <asm/netlogic/xlp-hal/sys.h>
 #include <asm/netlogic/xlp-hal/cpucontrol.h>
 
-#define CP0_EBASE	$15
-
 	.set	noreorder
 	.set	noat
 	.set	arch=xlr		/* for mfcr/mtcr, XLR is sufficient */
@@ -86,7 +84,7 @@
 	PTR_L	gp, 0(t1)
 
 	/* a0 has the processor id */
-	mfc0	a0, CP0_EBASE, 1
+	mfc0	a0, CP0_EBASE
 	andi	a0, 0x3ff		/* a0 <- node/core */
 	PTR_LA	t0, nlm_early_init_secondary
 	jalr	t0
diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
index dfb04fc..48d6349 100644
--- a/arch/mips/ralink/mt7620.c
+++ b/arch/mips/ralink/mt7620.c
@@ -107,31 +107,31 @@
 };
 
 static struct rt2880_pmx_func pwm1_grp_mt7628[] = {
-	FUNC("sdcx", 3, 19, 1),
+	FUNC("sdxc d6", 3, 19, 1),
 	FUNC("utif", 2, 19, 1),
 	FUNC("gpio", 1, 19, 1),
-	FUNC("pwm", 0, 19, 1),
+	FUNC("pwm1", 0, 19, 1),
 };
 
 static struct rt2880_pmx_func pwm0_grp_mt7628[] = {
-	FUNC("sdcx", 3, 18, 1),
+	FUNC("sdxc d7", 3, 18, 1),
 	FUNC("utif", 2, 18, 1),
 	FUNC("gpio", 1, 18, 1),
-	FUNC("pwm", 0, 18, 1),
+	FUNC("pwm0", 0, 18, 1),
 };
 
 static struct rt2880_pmx_func uart2_grp_mt7628[] = {
-	FUNC("sdcx", 3, 20, 2),
+	FUNC("sdxc d5 d4", 3, 20, 2),
 	FUNC("pwm", 2, 20, 2),
 	FUNC("gpio", 1, 20, 2),
-	FUNC("uart", 0, 20, 2),
+	FUNC("uart2", 0, 20, 2),
 };
 
 static struct rt2880_pmx_func uart1_grp_mt7628[] = {
-	FUNC("sdcx", 3, 45, 2),
+	FUNC("sw_r", 3, 45, 2),
 	FUNC("pwm", 2, 45, 2),
 	FUNC("gpio", 1, 45, 2),
-	FUNC("uart", 0, 45, 2),
+	FUNC("uart1", 0, 45, 2),
 };
 
 static struct rt2880_pmx_func i2c_grp_mt7628[] = {
@@ -143,21 +143,21 @@
 
 static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 36, 1) };
 static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 37, 1) };
-static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 15, 38) };
+static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 38, 1) };
 static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) };
 
 static struct rt2880_pmx_func sd_mode_grp_mt7628[] = {
 	FUNC("jtag", 3, 22, 8),
 	FUNC("utif", 2, 22, 8),
 	FUNC("gpio", 1, 22, 8),
-	FUNC("sdcx", 0, 22, 8),
+	FUNC("sdxc", 0, 22, 8),
 };
 
 static struct rt2880_pmx_func uart0_grp_mt7628[] = {
 	FUNC("-", 3, 12, 2),
 	FUNC("-", 2, 12, 2),
 	FUNC("gpio", 1, 12, 2),
-	FUNC("uart", 0, 12, 2),
+	FUNC("uart0", 0, 12, 2),
 };
 
 static struct rt2880_pmx_func i2s_grp_mt7628[] = {
@@ -171,7 +171,7 @@
 	FUNC("-", 3, 6, 1),
 	FUNC("refclk", 2, 6, 1),
 	FUNC("gpio", 1, 6, 1),
-	FUNC("spi", 0, 6, 1),
+	FUNC("spi cs1", 0, 6, 1),
 };
 
 static struct rt2880_pmx_func spis_grp_mt7628[] = {
@@ -188,28 +188,44 @@
 	FUNC("gpio", 0, 11, 1),
 };
 
-#define MT7628_GPIO_MODE_MASK	0x3
+static struct rt2880_pmx_func wled_kn_grp_mt7628[] = {
+	FUNC("rsvd", 3, 35, 1),
+	FUNC("rsvd", 2, 35, 1),
+	FUNC("gpio", 1, 35, 1),
+	FUNC("wled_kn", 0, 35, 1),
+};
 
-#define MT7628_GPIO_MODE_PWM1	30
-#define MT7628_GPIO_MODE_PWM0	28
-#define MT7628_GPIO_MODE_UART2	26
-#define MT7628_GPIO_MODE_UART1	24
-#define MT7628_GPIO_MODE_I2C	20
-#define MT7628_GPIO_MODE_REFCLK	18
-#define MT7628_GPIO_MODE_PERST	16
-#define MT7628_GPIO_MODE_WDT	14
-#define MT7628_GPIO_MODE_SPI	12
-#define MT7628_GPIO_MODE_SDMODE	10
-#define MT7628_GPIO_MODE_UART0	8
-#define MT7628_GPIO_MODE_I2S	6
-#define MT7628_GPIO_MODE_CS1	4
-#define MT7628_GPIO_MODE_SPIS	2
-#define MT7628_GPIO_MODE_GPIO	0
+static struct rt2880_pmx_func wled_an_grp_mt7628[] = {
+	FUNC("rsvd", 3, 44, 1),
+	FUNC("rsvd", 2, 44, 1),
+	FUNC("gpio", 1, 44, 1),
+	FUNC("wled_an", 0, 44, 1),
+};
+
+#define MT7628_GPIO_MODE_MASK		0x3
+
+#define MT7628_GPIO_MODE_WLED_KN	48
+#define MT7628_GPIO_MODE_WLED_AN	32
+#define MT7628_GPIO_MODE_PWM1		30
+#define MT7628_GPIO_MODE_PWM0		28
+#define MT7628_GPIO_MODE_UART2		26
+#define MT7628_GPIO_MODE_UART1		24
+#define MT7628_GPIO_MODE_I2C		20
+#define MT7628_GPIO_MODE_REFCLK		18
+#define MT7628_GPIO_MODE_PERST		16
+#define MT7628_GPIO_MODE_WDT		14
+#define MT7628_GPIO_MODE_SPI		12
+#define MT7628_GPIO_MODE_SDMODE		10
+#define MT7628_GPIO_MODE_UART0		8
+#define MT7628_GPIO_MODE_I2S		6
+#define MT7628_GPIO_MODE_CS1		4
+#define MT7628_GPIO_MODE_SPIS		2
+#define MT7628_GPIO_MODE_GPIO		0
 
 static struct rt2880_pmx_group mt7628an_pinmux_data[] = {
-	GRP_G("pmw1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK,
+	GRP_G("pwm1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK,
 				1, MT7628_GPIO_MODE_PWM1),
-	GRP_G("pmw1", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK,
+	GRP_G("pwm0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK,
 				1, MT7628_GPIO_MODE_PWM0),
 	GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK,
 				1, MT7628_GPIO_MODE_UART2),
@@ -233,6 +249,10 @@
 				1, MT7628_GPIO_MODE_SPIS),
 	GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK,
 				1, MT7628_GPIO_MODE_GPIO),
+	GRP_G("wled_an", wled_an_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_WLED_AN),
+	GRP_G("wled_kn", wled_kn_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_WLED_KN),
 	{ 0 }
 };
 
@@ -439,7 +459,7 @@
 	ralink_clk_add("10000c00.uartlite", periph_rate);
 	ralink_clk_add("10180000.wmac", xtal_rate);
 
-	if (IS_ENABLED(CONFIG_USB) && is_mt76x8()) {
+	if (IS_ENABLED(CONFIG_USB) && !is_mt76x8()) {
 		/*
 		 * When the CPU goes into sleep mode, the BUS clock will be
 		 * too low for USB to function properly. Adjust the busses
diff --git a/arch/mips/ralink/prom.c b/arch/mips/ralink/prom.c
index 39a9142f..7ecb4af 100644
--- a/arch/mips/ralink/prom.c
+++ b/arch/mips/ralink/prom.c
@@ -30,8 +30,10 @@
 	return soc_info.sys_type;
 }
 
-static __init void prom_init_cmdline(int argc, char **argv)
+static __init void prom_init_cmdline(void)
 {
+	int argc;
+	char **argv;
 	int i;
 
 	pr_debug("prom: fw_arg0=%08x fw_arg1=%08x fw_arg2=%08x fw_arg3=%08x\n",
@@ -60,14 +62,11 @@
 
 void __init prom_init(void)
 {
-	int argc;
-	char **argv;
-
 	prom_soc_init(&soc_info);
 
 	pr_info("SoC Type: %s\n", get_system_type());
 
-	prom_init_cmdline(argc, argv);
+	prom_init_cmdline();
 }
 
 void __init prom_free_prom_memory(void)
diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c
index 844f5cd..9dd6774 100644
--- a/arch/mips/ralink/rt288x.c
+++ b/arch/mips/ralink/rt288x.c
@@ -40,16 +40,6 @@
 	{ 0 }
 };
 
-static void rt288x_wdt_reset(void)
-{
-	u32 t;
-
-	/* enable WDT reset output on pin SRAM_CS_N */
-	t = rt_sysc_r32(SYSC_REG_CLKCFG);
-	t |= CLKCFG_SRAM_CS_N_WDT;
-	rt_sysc_w32(t, SYSC_REG_CLKCFG);
-}
-
 void __init ralink_clk_init(void)
 {
 	unsigned long cpu_rate, wmac_rate = 40000000;
@@ -119,5 +109,5 @@
 	soc_info->mem_size_max = RT2880_MEM_SIZE_MAX;
 
 	rt2880_pinmux_data = rt2880_pinmux_data_act;
-	ralink_soc == RT2880_SOC;
+	ralink_soc = RT2880_SOC;
 }
diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
index 9e45725..15b32cd 100644
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
@@ -89,17 +89,6 @@
 	{ 0 }
 };
 
-static void rt305x_wdt_reset(void)
-{
-	u32 t;
-
-	/* enable WDT reset output on pin SRAM_CS_N */
-	t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG);
-	t |= RT305X_SYSCFG_SRAM_CS0_MODE_WDT <<
-		RT305X_SYSCFG_SRAM_CS0_MODE_SHIFT;
-	rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG);
-}
-
 static unsigned long rt5350_get_mem_size(void)
 {
 	void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE);
diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c
index 582995a..3c57509 100644
--- a/arch/mips/ralink/rt3883.c
+++ b/arch/mips/ralink/rt3883.c
@@ -36,7 +36,7 @@
 static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) };
 static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) };
 static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) };
-static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna a", 0, 35, 3) };
+static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna g", 0, 35, 3) };
 static struct rt2880_pmx_func pci_func[] = {
 	FUNC("pci-dev", 0, 40, 32),
 	FUNC("pci-host2", 1, 40, 32),
@@ -44,7 +44,7 @@
 	FUNC("pci-fnc", 3, 40, 32)
 };
 static struct rt2880_pmx_func ge1_func[] = { FUNC("ge1", 0, 72, 12) };
-static struct rt2880_pmx_func ge2_func[] = { FUNC("ge1", 0, 84, 12) };
+static struct rt2880_pmx_func ge2_func[] = { FUNC("ge2", 0, 84, 12) };
 
 static struct rt2880_pmx_group rt3883_pinmux_data[] = {
 	GRP("i2c", i2c_func, 1, RT3883_GPIO_MODE_I2C),
@@ -63,16 +63,6 @@
 	{ 0 }
 };
 
-static void rt3883_wdt_reset(void)
-{
-	u32 t;
-
-	/* enable WDT reset output on GPIO 2 */
-	t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1);
-	t |= RT3883_SYSCFG1_GPIO2_AS_WDT_OUT;
-	rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1);
-}
-
 void __init ralink_clk_init(void)
 {
 	unsigned long cpu_rate, sys_rate;
diff --git a/arch/mips/sgi-ip22/Platform b/arch/mips/sgi-ip22/Platform
index b7a4b7e..e8f6b3a 100644
--- a/arch/mips/sgi-ip22/Platform
+++ b/arch/mips/sgi-ip22/Platform
@@ -25,7 +25,7 @@
 # Simplified: what IP22 does at 128MB+ in ksegN, IP28 does at 512MB+ in xkphys
 #
 ifdef CONFIG_SGI_IP28
-  ifeq ($(call cc-option-yn,-mr10k-cache-barrier=store), n)
+  ifeq ($(call cc-option-yn,-march=r10000 -mr10k-cache-barrier=store), n)
       $(error gcc doesn't support needed option -mr10k-cache-barrier=store)
   endif
 endif
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
index 1456890..6c7d785 100644
--- a/arch/mips/vdso/Makefile
+++ b/arch/mips/vdso/Makefile
@@ -5,10 +5,12 @@
 ccflags-vdso := \
 	$(filter -I%,$(KBUILD_CFLAGS)) \
 	$(filter -E%,$(KBUILD_CFLAGS)) \
+	$(filter -mmicromips,$(KBUILD_CFLAGS)) \
 	$(filter -march=%,$(KBUILD_CFLAGS))
 cflags-vdso := $(ccflags-vdso) \
 	$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
-	-O2 -g -fPIC -fno-common -fno-builtin -G 0 -DDISABLE_BRANCH_PROFILING \
+	-O2 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \
+	-DDISABLE_BRANCH_PROFILING \
 	$(call cc-option, -fno-stack-protector)
 aflags-vdso := $(ccflags-vdso) \
 	$(filter -I%,$(KBUILD_CFLAGS)) \
@@ -73,7 +75,7 @@
 $(obj-vdso): KBUILD_CFLAGS := $(cflags-vdso) $(native-abi)
 $(obj-vdso): KBUILD_AFLAGS := $(aflags-vdso) $(native-abi)
 
-$(obj)/vdso.lds: KBUILD_CPPFLAGS := $(native-abi)
+$(obj)/vdso.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) $(native-abi)
 
 $(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
 	$(call if_changed,vdsold)
diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h
index 5372787..4af43d9 100644
--- a/arch/mn10300/include/asm/uaccess.h
+++ b/arch/mn10300/include/asm/uaccess.h
@@ -181,6 +181,7 @@
 		"2:\n"						\
 		"	.section	.fixup,\"ax\"\n"	\
 		"3:\n\t"					\
+		"	mov		0,%1\n"			\
 		"	mov		%3,%0\n"		\
 		"	jmp		2b\n"			\
 		"	.previous\n"				\
diff --git a/arch/mn10300/lib/usercopy.c b/arch/mn10300/lib/usercopy.c
index 7826e6c..ce8899e 100644
--- a/arch/mn10300/lib/usercopy.c
+++ b/arch/mn10300/lib/usercopy.c
@@ -9,7 +9,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the Licence, or (at your option) any later version.
  */
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 unsigned long
 __generic_copy_to_user(void *to, const void *from, unsigned long n)
@@ -24,6 +24,8 @@
 {
 	if (access_ok(VERIFY_READ, from, n))
 		__copy_user_zeroing(to, from, n);
+	else
+		memset(to, 0, n);
 	return n;
 }
 
diff --git a/arch/nios2/include/asm/uaccess.h b/arch/nios2/include/asm/uaccess.h
index caa51ff..0ab8232 100644
--- a/arch/nios2/include/asm/uaccess.h
+++ b/arch/nios2/include/asm/uaccess.h
@@ -102,9 +102,12 @@
 static inline long copy_from_user(void *to, const void __user *from,
 				unsigned long n)
 {
-	if (!access_ok(VERIFY_READ, from, n))
-		return n;
-	return __copy_from_user(to, from, n);
+	unsigned long res = n;
+	if (access_ok(VERIFY_READ, from, n))
+		res = __copy_from_user(to, from, n);
+	if (unlikely(res))
+		memset(to + (n - res), 0, res);
+	return res;
 }
 
 static inline long copy_to_user(void __user *to, const void *from,
@@ -139,7 +142,7 @@
 
 #define __get_user_unknown(val, size, ptr, err) do {			\
 	err = 0;							\
-	if (copy_from_user(&(val), ptr, size)) {			\
+	if (__copy_from_user(&(val), ptr, size)) {			\
 		err = -EFAULT;						\
 	}								\
 	} while (0)
@@ -166,7 +169,7 @@
 	({								\
 	long __gu_err = -EFAULT;					\
 	const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);		\
-	unsigned long __gu_val;						\
+	unsigned long __gu_val = 0;					\
 	__get_user_common(__gu_val, sizeof(*(ptr)), __gu_ptr, __gu_err);\
 	(x) = (__force __typeof__(x))__gu_val;				\
 	__gu_err;							\
diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c
index 718dd19..de73beb 100644
--- a/arch/nios2/kernel/prom.c
+++ b/arch/nios2/kernel/prom.c
@@ -48,6 +48,13 @@
 	return alloc_bootmem_align(size, align);
 }
 
+int __init early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size,
+					     bool nomap)
+{
+	reserve_bootmem(base, size, BOOTMEM_DEFAULT);
+	return 0;
+}
+
 void __init early_init_devtree(void *params)
 {
 	__be32 *dtb = (u32 *)__dtb_start;
diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c
index a4ff86d..6c4e351 100644
--- a/arch/nios2/kernel/setup.c
+++ b/arch/nios2/kernel/setup.c
@@ -195,6 +195,9 @@
 	}
 #endif /* CONFIG_BLK_DEV_INITRD */
 
+	early_init_fdt_reserve_self();
+	early_init_fdt_scan_reserved_mem();
+
 	unflatten_and_copy_device_tree();
 
 	setup_cpuinfo();
diff --git a/arch/openrisc/include/asm/uaccess.h b/arch/openrisc/include/asm/uaccess.h
index a6bd07c..5cc6b4f 100644
--- a/arch/openrisc/include/asm/uaccess.h
+++ b/arch/openrisc/include/asm/uaccess.h
@@ -273,28 +273,20 @@
 static inline unsigned long
 copy_from_user(void *to, const void *from, unsigned long n)
 {
-	unsigned long over;
+	unsigned long res = n;
 
-	if (access_ok(VERIFY_READ, from, n))
-		return __copy_tofrom_user(to, from, n);
-	if ((unsigned long)from < TASK_SIZE) {
-		over = (unsigned long)from + n - TASK_SIZE;
-		return __copy_tofrom_user(to, from, n - over) + over;
-	}
-	return n;
+	if (likely(access_ok(VERIFY_READ, from, n)))
+		res = __copy_tofrom_user(to, from, n);
+	if (unlikely(res))
+		memset(to + (n - res), 0, res);
+	return res;
 }
 
 static inline unsigned long
 copy_to_user(void *to, const void *from, unsigned long n)
 {
-	unsigned long over;
-
-	if (access_ok(VERIFY_WRITE, to, n))
-		return __copy_tofrom_user(to, from, n);
-	if ((unsigned long)to < TASK_SIZE) {
-		over = (unsigned long)to + n - TASK_SIZE;
-		return __copy_tofrom_user(to, from, n - over) + over;
-	}
+	if (likely(access_ok(VERIFY_WRITE, to, n)))
+		n = __copy_tofrom_user(to, from, n);
 	return n;
 }
 
@@ -303,13 +295,8 @@
 static inline __must_check unsigned long
 clear_user(void *addr, unsigned long size)
 {
-
-	if (access_ok(VERIFY_WRITE, addr, size))
-		return __clear_user(addr, size);
-	if ((unsigned long)addr < TASK_SIZE) {
-		unsigned long over = (unsigned long)addr + size - TASK_SIZE;
-		return __clear_user(addr, size - over) + over;
-	}
+	if (likely(access_ok(VERIFY_WRITE, addr, size)))
+		size = __clear_user(addr, size);
 	return size;
 }
 
diff --git a/arch/parisc/include/asm/bitops.h b/arch/parisc/include/asm/bitops.h
index 3f9406d..da87943 100644
--- a/arch/parisc/include/asm/bitops.h
+++ b/arch/parisc/include/asm/bitops.h
@@ -6,7 +6,7 @@
 #endif
 
 #include <linux/compiler.h>
-#include <asm/types.h>		/* for BITS_PER_LONG/SHIFT_PER_LONG */
+#include <asm/types.h>
 #include <asm/byteorder.h>
 #include <asm/barrier.h>
 #include <linux/atomic.h>
@@ -17,6 +17,12 @@
  * to include/asm-i386/bitops.h or kerneldoc
  */
 
+#if __BITS_PER_LONG == 64
+#define SHIFT_PER_LONG 6
+#else
+#define SHIFT_PER_LONG 5
+#endif
+
 #define CHOP_SHIFTCOUNT(x) (((unsigned long) (x)) & (BITS_PER_LONG - 1))
 
 
diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h
index 3d0e17b..df0f52b 100644
--- a/arch/parisc/include/asm/cache.h
+++ b/arch/parisc/include/asm/cache.h
@@ -22,6 +22,9 @@
 
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
+/* Read-only memory is marked before mark_rodata_ro() is called. */
+#define __ro_after_init	__read_mostly
+
 void parisc_cache_init(void);	/* initializes cache-flushing */
 void disable_sr_hashing_asm(int); /* low level support for above */
 void disable_sr_hashing(void);   /* turns off space register hashing */
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h
index 845272c..7bd69bd 100644
--- a/arch/parisc/include/asm/cacheflush.h
+++ b/arch/parisc/include/asm/cacheflush.h
@@ -121,10 +121,6 @@
 	}
 }
 
-#ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
-#endif
-
 #include <asm/kmap_types.h>
 
 #define ARCH_HAS_KMAP
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index 291cee2..3a4ed9f 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -65,9 +65,9 @@
 		unsigned long flags;				\
 		spin_lock_irqsave(&pa_tlb_lock, flags);		\
 		old_pte = *ptep;				\
-		set_pte(ptep, pteval);				\
 		if (pte_inserted(old_pte))			\
 			purge_tlb_entries(mm, addr);		\
+		set_pte(ptep, pteval);				\
 		spin_unlock_irqrestore(&pa_tlb_lock, flags);	\
 	} while (0)
 
@@ -83,10 +83,10 @@
 	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e))
 
 /* This is the size of the initially mapped kernel memory */
-#ifdef CONFIG_64BIT
-#define KERNEL_INITIAL_ORDER	25	/* 1<<25 = 32MB */
+#if defined(CONFIG_64BIT)
+#define KERNEL_INITIAL_ORDER	26	/* 1<<26 = 64MB */
 #else
-#define KERNEL_INITIAL_ORDER	24	/* 1<<24 = 16MB */
+#define KERNEL_INITIAL_ORDER	25	/* 1<<25 = 32MB */
 #endif
 #define KERNEL_INITIAL_SIZE	(1 << KERNEL_INITIAL_ORDER)
 
@@ -478,8 +478,8 @@
 		spin_unlock_irqrestore(&pa_tlb_lock, flags);
 		return 0;
 	}
-	set_pte(ptep, pte_mkold(pte));
 	purge_tlb_entries(vma->vm_mm, addr);
+	set_pte(ptep, pte_mkold(pte));
 	spin_unlock_irqrestore(&pa_tlb_lock, flags);
 	return 1;
 }
@@ -492,9 +492,9 @@
 
 	spin_lock_irqsave(&pa_tlb_lock, flags);
 	old_pte = *ptep;
-	set_pte(ptep, __pte(0));
 	if (pte_inserted(old_pte))
 		purge_tlb_entries(mm, addr);
+	set_pte(ptep, __pte(0));
 	spin_unlock_irqrestore(&pa_tlb_lock, flags);
 
 	return old_pte;
@@ -504,8 +504,8 @@
 {
 	unsigned long flags;
 	spin_lock_irqsave(&pa_tlb_lock, flags);
-	set_pte(ptep, pte_wrprotect(*ptep));
 	purge_tlb_entries(mm, addr);
+	set_pte(ptep, pte_wrprotect(*ptep));
 	spin_unlock_irqrestore(&pa_tlb_lock, flags);
 }
 
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index 1960b87..4ad5146 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -10,6 +10,7 @@
 #include <asm-generic/uaccess-unaligned.h>
 
 #include <linux/bug.h>
+#include <linux/string.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
@@ -245,13 +246,14 @@
                                           unsigned long n)
 {
         int sz = __compiletime_object_size(to);
-        int ret = -EFAULT;
+        unsigned long ret = n;
 
         if (likely(sz == -1 || !__builtin_constant_p(n) || sz >= n))
                 ret = __copy_from_user(to, from, n);
         else
                 copy_from_user_overflow();
-
+	if (unlikely(ret))
+		memset(to + (n - ret), 0, ret);
         return ret;
 }
 
diff --git a/arch/parisc/include/uapi/asm/bitsperlong.h b/arch/parisc/include/uapi/asm/bitsperlong.h
index e0a23c7..07fa7e5 100644
--- a/arch/parisc/include/uapi/asm/bitsperlong.h
+++ b/arch/parisc/include/uapi/asm/bitsperlong.h
@@ -3,10 +3,8 @@
 
 #if defined(__LP64__)
 #define __BITS_PER_LONG 64
-#define SHIFT_PER_LONG 6
 #else
 #define __BITS_PER_LONG 32
-#define SHIFT_PER_LONG 5
 #endif
 
 #include <asm-generic/bitsperlong.h>
diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
index c0ae625..274d5bc 100644
--- a/arch/parisc/include/uapi/asm/errno.h
+++ b/arch/parisc/include/uapi/asm/errno.h
@@ -97,10 +97,10 @@
 #define	ENOTCONN	235	/* Transport endpoint is not connected */
 #define	ESHUTDOWN	236	/* Cannot send after transport endpoint shutdown */
 #define	ETOOMANYREFS	237	/* Too many references: cannot splice */
-#define EREFUSED	ECONNREFUSED	/* for HP's NFS apparently */
 #define	ETIMEDOUT	238	/* Connection timed out */
 #define	ECONNREFUSED	239	/* Connection refused */
-#define EREMOTERELEASE	240	/* Remote peer released connection */
+#define	EREFUSED	ECONNREFUSED	/* for HP's NFS apparently */
+#define	EREMOTERELEASE	240	/* Remote peer released connection */
 #define	EHOSTDOWN	241	/* Host is down */
 #define	EHOSTUNREACH	242	/* No route to host */
 
diff --git a/arch/parisc/include/uapi/asm/swab.h b/arch/parisc/include/uapi/asm/swab.h
index e78403b..928e1bb 100644
--- a/arch/parisc/include/uapi/asm/swab.h
+++ b/arch/parisc/include/uapi/asm/swab.h
@@ -1,6 +1,7 @@
 #ifndef _PARISC_SWAB_H
 #define _PARISC_SWAB_H
 
+#include <asm/bitsperlong.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
 
@@ -38,7 +39,7 @@
 }
 #define __arch_swab32 __arch_swab32
 
-#if BITS_PER_LONG > 32
+#if __BITS_PER_LONG > 32
 /*
 ** From "PA-RISC 2.0 Architecture", HP Professional Books.
 ** See Appendix I page 8 , "Endian Byte Swapping".
@@ -61,6 +62,6 @@
 	return x;
 }
 #define __arch_swab64 __arch_swab64
-#endif /* BITS_PER_LONG > 32 */
+#endif /* __BITS_PER_LONG > 32 */
 
 #endif /* _PARISC_SWAB_H */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index cda6dbb..6857a10 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -351,6 +351,7 @@
 {
 	unsigned long rangetime, alltime;
 	unsigned long size, start;
+	unsigned long threshold;
 
 	alltime = mfctl(16);
 	flush_data_cache();
@@ -364,26 +365,30 @@
 	printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
 		alltime, size, rangetime);
 
-	/* Racy, but if we see an intermediate value, it's ok too... */
-	parisc_cache_flush_threshold = size * alltime / rangetime;
-
-	parisc_cache_flush_threshold = L1_CACHE_ALIGN(parisc_cache_flush_threshold);
-	if (!parisc_cache_flush_threshold)
-		parisc_cache_flush_threshold = FLUSH_THRESHOLD;
-
-	if (parisc_cache_flush_threshold > cache_info.dc_size)
-		parisc_cache_flush_threshold = cache_info.dc_size;
-
-	printk(KERN_INFO "Setting cache flush threshold to %lu kB\n",
+	threshold = L1_CACHE_ALIGN(size * alltime / rangetime);
+	if (threshold > cache_info.dc_size)
+		threshold = cache_info.dc_size;
+	if (threshold)
+		parisc_cache_flush_threshold = threshold;
+	printk(KERN_INFO "Cache flush threshold set to %lu KiB\n",
 		parisc_cache_flush_threshold/1024);
 
 	/* calculate TLB flush threshold */
 
+	/* On SMP machines, skip the TLB measure of kernel text which
+	 * has been mapped as huge pages. */
+	if (num_online_cpus() > 1 && !parisc_requires_coherency()) {
+		threshold = max(cache_info.it_size, cache_info.dt_size);
+		threshold *= PAGE_SIZE;
+		threshold /= num_online_cpus();
+		goto set_tlb_threshold;
+	}
+
 	alltime = mfctl(16);
 	flush_tlb_all();
 	alltime = mfctl(16) - alltime;
 
-	size = PAGE_SIZE;
+	size = 0;
 	start = (unsigned long) _text;
 	rangetime = mfctl(16);
 	while (start < (unsigned long) _end) {
@@ -396,13 +401,12 @@
 	printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n",
 		alltime, size, rangetime);
 
-	parisc_tlb_flush_threshold = size * alltime / rangetime;
-	parisc_tlb_flush_threshold *= num_online_cpus();
-	parisc_tlb_flush_threshold = PAGE_ALIGN(parisc_tlb_flush_threshold);
-	if (!parisc_tlb_flush_threshold)
-		parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD;
+	threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime);
 
-	printk(KERN_INFO "Setting TLB flush threshold to %lu kB\n",
+set_tlb_threshold:
+	if (threshold)
+		parisc_tlb_flush_threshold = threshold;
+	printk(KERN_INFO "TLB flush threshold set to %lu KiB\n",
 		parisc_tlb_flush_threshold/1024);
 }
 
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index b743a80..a4761b7 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -96,7 +96,7 @@
 
 fitmanymiddle:					/* Loop if LOOP >= 2 */
 	addib,COND(>)		-1, %r31, fitmanymiddle	/* Adjusted inner loop decr */
-	pitlbe		0(%sr1, %r28)
+	pitlbe		%r0(%sr1, %r28)
 	pitlbe,m	%arg1(%sr1, %r28)	/* Last pitlbe and addr adjust */
 	addib,COND(>)		-1, %r29, fitmanymiddle	/* Middle loop decr */
 	copy		%arg3, %r31		/* Re-init inner loop count */
@@ -139,7 +139,7 @@
 
 fdtmanymiddle:					/* Loop if LOOP >= 2 */
 	addib,COND(>)		-1, %r31, fdtmanymiddle	/* Adjusted inner loop decr */
-	pdtlbe		0(%sr1, %r28)
+	pdtlbe		%r0(%sr1, %r28)
 	pdtlbe,m	%arg1(%sr1, %r28)	/* Last pdtlbe and addr adjust */
 	addib,COND(>)		-1, %r29, fdtmanymiddle	/* Middle loop decr */
 	copy		%arg3, %r31		/* Re-init inner loop count */
@@ -620,12 +620,12 @@
 	/* Purge any old translations */
 
 #ifdef CONFIG_PA20
-	pdtlb,l		0(%r28)
-	pdtlb,l		0(%r29)
+	pdtlb,l		%r0(%r28)
+	pdtlb,l		%r0(%r29)
 #else
 	tlb_lock	%r20,%r21,%r22
-	pdtlb		0(%r28)
-	pdtlb		0(%r29)
+	pdtlb		%r0(%r28)
+	pdtlb		%r0(%r29)
 	tlb_unlock	%r20,%r21,%r22
 #endif
 
@@ -768,10 +768,10 @@
 	/* Purge any old translation */
 
 #ifdef CONFIG_PA20
-	pdtlb,l		0(%r28)
+	pdtlb,l		%r0(%r28)
 #else
 	tlb_lock	%r20,%r21,%r22
-	pdtlb		0(%r28)
+	pdtlb		%r0(%r28)
 	tlb_unlock	%r20,%r21,%r22
 #endif
 
@@ -852,10 +852,10 @@
 	/* Purge any old translation */
 
 #ifdef CONFIG_PA20
-	pdtlb,l		0(%r28)
+	pdtlb,l		%r0(%r28)
 #else
 	tlb_lock	%r20,%r21,%r22
-	pdtlb		0(%r28)
+	pdtlb		%r0(%r28)
 	tlb_unlock	%r20,%r21,%r22
 #endif
 
@@ -886,19 +886,10 @@
 	fdc,m		r31(%r28)
 	fdc,m		r31(%r28)
 	fdc,m		r31(%r28)
-	cmpb,COND(<<)		%r28, %r25,1b
+	cmpb,COND(<<)	%r28, %r25,1b
 	fdc,m		r31(%r28)
 
 	sync
-
-#ifdef CONFIG_PA20
-	pdtlb,l		0(%r25)
-#else
-	tlb_lock	%r20,%r21,%r22
-	pdtlb		0(%r25)
-	tlb_unlock	%r20,%r21,%r22
-#endif
-
 	bv		%r0(%r2)
 	nop
 	.exit
@@ -925,13 +916,18 @@
 	depwi		0, 31,PAGE_SHIFT, %r28	/* Clear any offset bits */
 #endif
 
-	/* Purge any old translation */
+	/* Purge any old translation.  Note that the FIC instruction
+	 * may use either the instruction or data TLB.  Given that we
+	 * have a flat address space, it's not clear which TLB will be
+	 * used.  So, we purge both entries.  */
 
 #ifdef CONFIG_PA20
+	pdtlb,l		%r0(%r28)
 	pitlb,l         %r0(%sr4,%r28)
 #else
 	tlb_lock        %r20,%r21,%r22
-	pitlb           (%sr4,%r28)
+	pdtlb		%r0(%r28)
+	pitlb           %r0(%sr4,%r28)
 	tlb_unlock      %r20,%r21,%r22
 #endif
 
@@ -968,15 +964,6 @@
 	fic,m		%r31(%sr4,%r28)
 
 	sync
-
-#ifdef CONFIG_PA20
-	pitlb,l         %r0(%sr4,%r25)
-#else
-	tlb_lock        %r20,%r21,%r22
-	pitlb           (%sr4,%r25)
-	tlb_unlock      %r20,%r21,%r22
-#endif
-
 	bv		%r0(%r2)
 	nop
 	.exit
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index b9402c9..af0d7fa 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -95,8 +95,8 @@
 
 		if (!pte_none(*pte))
 			printk(KERN_ERR "map_pte_uncached: page already exists\n");
-		set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
 		purge_tlb_start(flags);
+		set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
 		pdtlb_kernel(orig_vaddr);
 		purge_tlb_end(flags);
 		vaddr += PAGE_SIZE;
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index f7ea626..2e66a88 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -38,6 +38,7 @@
 #include <linux/export.h>
 
 #include <asm/processor.h>
+#include <asm/sections.h>
 #include <asm/pdc.h>
 #include <asm/led.h>
 #include <asm/machdep.h>	/* for pa7300lc_init() proto */
@@ -140,6 +141,13 @@
 #endif
 	printk(KERN_CONT ".\n");
 
+	/*
+	 * Check if initial kernel page mappings are sufficient.
+	 * panic early if not, else we may access kernel functions
+	 * and variables which can't be reached.
+	 */
+	if (__pa((unsigned long) &_end) >= KERNEL_INITIAL_SIZE)
+		panic("KERNEL_INITIAL_ORDER too small!");
 
 	pdc_console_init();
 
@@ -326,6 +334,10 @@
 	/* tell PDC we're Linux. Nevermind failure. */
 	pdc_stable_write(0x40, &osid, sizeof(osid));
 	
+	/* start with known state */
+	flush_cache_all_local();
+	flush_tlb_all_local(NULL);
+
 	processor_init();
 #ifdef CONFIG_SMP
 	pr_info("CPU(s): %d out of %d %s at %d.%06d MHz online\n",
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 5aba01a..4dda73c 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -88,7 +88,7 @@
 		unsigned long len, unsigned long pgoff, unsigned long flags)
 {
 	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
+	struct vm_area_struct *vma, *prev;
 	unsigned long task_size = TASK_SIZE;
 	int do_color_align, last_mmap;
 	struct vm_unmapped_area_info info;
@@ -115,9 +115,10 @@
 		else
 			addr = PAGE_ALIGN(addr);
 
-		vma = find_vma(mm, addr);
+		vma = find_vma_prev(mm, addr, &prev);
 		if (task_size - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)) &&
+		    (!prev || addr >= vm_end_gap(prev)))
 			goto found_addr;
 	}
 
@@ -141,7 +142,7 @@
 			  const unsigned long len, const unsigned long pgoff,
 			  const unsigned long flags)
 {
-	struct vm_area_struct *vma;
+	struct vm_area_struct *vma, *prev;
 	struct mm_struct *mm = current->mm;
 	unsigned long addr = addr0;
 	int do_color_align, last_mmap;
@@ -175,9 +176,11 @@
 			addr = COLOR_ALIGN(addr, last_mmap, pgoff);
 		else
 			addr = PAGE_ALIGN(addr);
-		vma = find_vma(mm, addr);
+
+		vma = find_vma_prev(mm, addr, &prev);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)) &&
+		    (!prev || addr >= vm_end_gap(prev)))
 			goto found_addr;
 	}
 
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index fbafa0d..a86b19f 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -106,8 +106,6 @@
 	mtsp	%r0,%sr4			/* get kernel space into sr4 */
 	mtsp	%r0,%sr5			/* get kernel space into sr5 */
 	mtsp	%r0,%sr6			/* get kernel space into sr6 */
-	mfsp    %sr7,%r1                        /* save user sr7 */
-	mtsp    %r1,%sr3                        /* and store it in sr3 */
 
 #ifdef CONFIG_64BIT
 	/* for now we can *always* set the W bit on entry to the syscall
@@ -133,6 +131,14 @@
 	depdi	0, 31, 32, %r21
 1:	
 #endif
+
+	/* We use a rsm/ssm pair to prevent sr3 from being clobbered
+	 * by external interrupts.
+	 */
+	mfsp    %sr7,%r1                        /* save user sr7 */
+	rsm	PSW_SM_I, %r0			/* disable interrupts */
+	mtsp    %r1,%sr3                        /* and store it in sr3 */
+
 	mfctl   %cr30,%r1
 	xor     %r1,%r30,%r30                   /* ye olde xor trick */
 	xor     %r1,%r30,%r1
@@ -147,6 +153,7 @@
 	 */
 
 	mtsp	%r0,%sr7			/* get kernel space into sr7 */
+	ssm	PSW_SM_I, %r0			/* enable interrupts */
 	STREGM	%r1,FRAME_SIZE(%r30)		/* save r1 (usp) here for now */
 	mfctl	%cr30,%r1			/* get task ptr in %r1 */
 	LDREG	TI_TASK(%r1),%r1
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index d7c0acb..8d49614 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -666,7 +666,7 @@
 		break;
 	}
 
-	if (modify && R1(regs->iir))
+	if (ret == 0 && modify && R1(regs->iir))
 		regs->gr[R1(regs->iir)] = newbase;
 
 
@@ -677,6 +677,14 @@
 
 	if (ret)
 	{
+		/*
+		 * The unaligned handler failed.
+		 * If we were called by __get_user() or __put_user() jump
+		 * to it's exception fixup handler instead of crashing.
+		 */
+		if (!user_mode(regs) && fixup_exception(regs))
+			return;
+
 		printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
 		die_if_kernel("Unaligned data reference", regs, 28);
 
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 308f290..60771df 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -88,8 +88,9 @@
 	/* Start of data section */
 	_sdata = .;
 
-	RO_DATA_SECTION(8)
-
+	/* Architecturally we need to keep __gp below 0x1000000 and thus
+	 * in front of RO_DATA_SECTION() which stores lots of tracepoint
+	 * and ftrace symbols. */
 #ifdef CONFIG_64BIT
 	. = ALIGN(16);
 	/* Linkage tables */
@@ -104,6 +105,8 @@
 	}
 #endif
 
+	RO_DATA_SECTION(8)
+
 	/* unwind info */
 	.PARISC.unwind : {
 		__start___unwind = .;
diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S
index b6fcbaf..3dc44b0 100644
--- a/arch/powerpc/boot/ps3-head.S
+++ b/arch/powerpc/boot/ps3-head.S
@@ -57,11 +57,6 @@
 	bctr
 
 1:
-	/* Save the value at addr zero for a null pointer write check later. */
-
-	li	r4, 0
-	lwz	r3, 0(r4)
-
 	/* Primary delays then goes to _zimage_start in wrapper. */
 
 	or	31, 31, 31 /* db16cyc */
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
index 4ec2d86..a05558a 100644
--- a/arch/powerpc/boot/ps3.c
+++ b/arch/powerpc/boot/ps3.c
@@ -119,13 +119,12 @@
 	flush_cache((void *)0x100, 512);
 }
 
-void platform_init(unsigned long null_check)
+void platform_init(void)
 {
 	const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
 	void *chosen;
 	unsigned long ft_addr;
 	u64 rm_size;
-	unsigned long val;
 
 	console_ops.write = ps3_console_write;
 	platform_ops.exit = ps3_exit;
@@ -153,11 +152,6 @@
 
 	printf(" flat tree at 0x%lx\n\r", ft_addr);
 
-	val = *(unsigned long *)0;
-
-	if (val != null_check)
-		printf("null check failed: %lx != %lx\n\r", val, null_check);
-
 	((kernel_entry_t)0)(ft_addr, 0, NULL);
 
 	ps3_exit();
diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S
index 861e721..f080abf 100644
--- a/arch/powerpc/boot/zImage.lds.S
+++ b/arch/powerpc/boot/zImage.lds.S
@@ -68,6 +68,7 @@
   }
 
 #ifdef CONFIG_PPC64_BOOT_WRAPPER
+  . = ALIGN(256);
   .got :
   {
     __toc_start = .;
diff --git a/arch/powerpc/include/asm/icswx.h b/arch/powerpc/include/asm/icswx.h
index 9f8402b..27e588f 100644
--- a/arch/powerpc/include/asm/icswx.h
+++ b/arch/powerpc/include/asm/icswx.h
@@ -164,6 +164,7 @@
 #define ICSWX_INITIATED		(0x8)
 #define ICSWX_BUSY		(0x4)
 #define ICSWX_REJECTED		(0x2)
+#define ICSWX_XERS0		(0x1)	/* undefined or set from XERSO. */
 
 static inline int icswx(__be32 ccw, struct coprocessor_request_block *crb)
 {
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index cfa758c..a92d95a 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -545,6 +545,7 @@
 	u64 tfiar;
 
 	u32 cr_tm;
+	u64 xer_tm;
 	u64 lr_tm;
 	u64 ctr_tm;
 	u64 amr_tm;
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 2220f7a..627d129 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -707,7 +707,8 @@
 #define   MMCR0_FCWAIT	0x00000002UL /* freeze counter in WAIT state */
 #define   MMCR0_FCHV	0x00000001UL /* freeze conditions in hypervisor mode */
 #define SPRN_MMCR1	798
-#define SPRN_MMCR2	769
+#define SPRN_MMCR2	785
+#define SPRN_UMMCR2	769
 #define SPRN_MMCRA	0x312
 #define   MMCRA_SDSYNC	0x80000000UL /* SDAR synced with SIAR */
 #define   MMCRA_SDAR_DCACHE_MISS 0x40000000UL
@@ -744,13 +745,13 @@
 #define SPRN_PMC6	792
 #define SPRN_PMC7	793
 #define SPRN_PMC8	794
-#define SPRN_SIAR	780
-#define SPRN_SDAR	781
 #define SPRN_SIER	784
 #define   SIER_SIPR		0x2000000	/* Sampled MSR_PR */
 #define   SIER_SIHV		0x1000000	/* Sampled MSR_HV */
 #define   SIER_SIAR_VALID	0x0400000	/* SIAR contents valid */
 #define   SIER_SDAR_VALID	0x0200000	/* SDAR contents valid */
+#define SPRN_SIAR	796
+#define SPRN_SDAR	797
 #define SPRN_TACR	888
 #define SPRN_TCSCR	889
 #define SPRN_CSIGR	890
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index 8b3b46b..3297715 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -44,8 +44,22 @@
 extern int sysfs_add_device_to_node(struct device *dev, int nid);
 extern void sysfs_remove_device_from_node(struct device *dev, int nid);
 
+static inline int early_cpu_to_node(int cpu)
+{
+	int nid;
+
+	nid = numa_cpu_lookup_table[cpu];
+
+	/*
+	 * Fall back to node 0 if nid is unset (it should be, except bugs).
+	 * This allows callers to safely do NODE_DATA(early_cpu_to_node(cpu)).
+	 */
+	return (nid < 0) ? 0 : nid;
+}
 #else
 
+static inline int early_cpu_to_node(int cpu) { return 0; }
+
 static inline void dump_numa_cpu_topology(void) {}
 
 static inline int sysfs_add_device_to_node(struct device *dev, int nid)
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index 2a8ebae..a5ffe02 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -323,30 +323,17 @@
 static inline unsigned long copy_from_user(void *to,
 		const void __user *from, unsigned long n)
 {
-	unsigned long over;
-
-	if (access_ok(VERIFY_READ, from, n))
+	if (likely(access_ok(VERIFY_READ, from, n)))
 		return __copy_tofrom_user((__force void __user *)to, from, n);
-	if ((unsigned long)from < TASK_SIZE) {
-		over = (unsigned long)from + n - TASK_SIZE;
-		return __copy_tofrom_user((__force void __user *)to, from,
-				n - over) + over;
-	}
+	memset(to, 0, n);
 	return n;
 }
 
 static inline unsigned long copy_to_user(void __user *to,
 		const void *from, unsigned long n)
 {
-	unsigned long over;
-
 	if (access_ok(VERIFY_WRITE, to, n))
 		return __copy_tofrom_user(to, (__force void __user *)from, n);
-	if ((unsigned long)to < TASK_SIZE) {
-		over = (unsigned long)to + n - TASK_SIZE;
-		return __copy_tofrom_user(to, (__force void __user *)from,
-				n - over) + over;
-	}
 	return n;
 }
 
@@ -437,10 +424,6 @@
 	might_fault();
 	if (likely(access_ok(VERIFY_WRITE, addr, size)))
 		return __clear_user(addr, size);
-	if ((unsigned long)addr < TASK_SIZE) {
-		unsigned long over = (unsigned long)addr + size - TASK_SIZE;
-		return __clear_user(addr, size - over) + over;
-	}
 	return size;
 }
 
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index ab4d473..720b71a 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -587,6 +587,7 @@
 #define KVM_REG_PPC_TM_VSCR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67)
 #define KVM_REG_PPC_TM_DSCR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68)
 #define KVM_REG_PPC_TM_TAR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69)
+#define KVM_REG_PPC_TM_XER	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x6a)
 
 /* PPC64 eXternal Interrupt Controller Specification */
 #define KVM_DEV_XICS_GRP_SOURCES	1	/* 64-bit source attributes */
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 86150fb..91e5c17 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -808,14 +808,25 @@
 	nb = aligninfo[instr].len;
 	flags = aligninfo[instr].flags;
 
-	/* ldbrx/stdbrx overlap lfs/stfs in the DSISR unfortunately */
-	if (IS_XFORM(instruction) && ((instruction >> 1) & 0x3ff) == 532) {
-		nb = 8;
-		flags = LD+SW;
-	} else if (IS_XFORM(instruction) &&
-		   ((instruction >> 1) & 0x3ff) == 660) {
-		nb = 8;
-		flags = ST+SW;
+	/*
+	 * Handle some cases which give overlaps in the DSISR values.
+	 */
+	if (IS_XFORM(instruction)) {
+		switch (get_xop(instruction)) {
+		case 532:	/* ldbrx */
+			nb = 8;
+			flags = LD+SW;
+			break;
+		case 660:	/* stdbrx */
+			nb = 8;
+			flags = ST+SW;
+			break;
+		case 20:	/* lwarx */
+		case 84:	/* ldarx */
+		case 116:	/* lharx */
+		case 276:	/* lqarx */
+			return 0;	/* not emulated ever */
+		}
 	}
 
 	/* Byteswap little endian loads and stores */
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 221d584..40da691 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -584,6 +584,7 @@
 	DEFINE(VCPU_VRS_TM, offsetof(struct kvm_vcpu, arch.vr_tm.vr));
 	DEFINE(VCPU_VRSAVE_TM, offsetof(struct kvm_vcpu, arch.vrsave_tm));
 	DEFINE(VCPU_CR_TM, offsetof(struct kvm_vcpu, arch.cr_tm));
+	DEFINE(VCPU_XER_TM, offsetof(struct kvm_vcpu, arch.xer_tm));
 	DEFINE(VCPU_LR_TM, offsetof(struct kvm_vcpu, arch.lr_tm));
 	DEFINE(VCPU_CTR_TM, offsetof(struct kvm_vcpu, arch.ctr_tm));
 	DEFINE(VCPU_AMR_TM, offsetof(struct kvm_vcpu, arch.amr_tm));
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 40e4d4a..6696c19 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -304,9 +304,17 @@
 	 *
 	 * For pHyp, we have to enable IO for log retrieval. Otherwise,
 	 * 0xFF's is always returned from PCI config space.
+	 *
+	 * When the @severity is EEH_LOG_PERM, the PE is going to be
+	 * removed. Prior to that, the drivers for devices included in
+	 * the PE will be closed. The drivers rely on working IO path
+	 * to bring the devices to quiet state. Otherwise, PCI traffic
+	 * from those devices after they are removed is like to cause
+	 * another unexpected EEH error.
 	 */
 	if (!(pe->type & EEH_PE_PHB)) {
-		if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG))
+		if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG) ||
+		    severity == EEH_LOG_PERM)
 			eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
 
 		/*
@@ -677,7 +685,7 @@
 	/* Check if the request is finished successfully */
 	if (active_flag) {
 		rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
-		if (rc <= 0)
+		if (rc < 0)
 			return rc;
 
 		if (rc & active_flag)
@@ -1072,7 +1080,7 @@
 	struct pci_controller *phb;
 	struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
 
-	if (!edev || !eeh_enabled())
+	if (!edev)
 		return;
 
 	if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE))
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 52c1e27..9837c98 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -166,6 +166,16 @@
 	if (!edev)
 		return NULL;
 
+	/*
+	 * We cannot access the config space on some adapters.
+	 * Otherwise, it will cause fenced PHB. We don't save
+	 * the content in their config space and will restore
+	 * from the initial config space saved when the EEH
+	 * device is created.
+	 */
+	if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED))
+		return NULL;
+
 	pdev = eeh_dev_to_pci_dev(edev);
 	if (!pdev)
 		return NULL;
@@ -305,6 +315,19 @@
 	if (!edev)
 		return NULL;
 
+	/*
+	 * The content in the config space isn't saved because
+	 * the blocked config space on some adapters. We have
+	 * to restore the initial saved config space when the
+	 * EEH device is created.
+	 */
+	if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) {
+		if (list_is_last(&edev->list, &edev->pe->edevs))
+			eeh_pe_restore_bars(edev->pe);
+
+		return NULL;
+	}
+
 	pdev = eeh_dev_to_pci_dev(edev);
 	if (!pdev)
 		return NULL;
@@ -462,7 +485,7 @@
 static void *__eeh_clear_pe_frozen_state(void *data, void *flag)
 {
 	struct eeh_pe *pe = (struct eeh_pe *)data;
-	bool *clear_sw_state = flag;
+	bool clear_sw_state = *(bool *)flag;
 	int i, rc = 1;
 
 	for (i = 0; rc && i < 3; i++)
@@ -504,9 +527,6 @@
 	/* Save states */
 	eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL);
 
-	/* Report error */
-	eeh_pe_dev_traverse(pe, eeh_report_error, &result);
-
 	/* Issue reset */
 	ret = eeh_reset_pe(pe);
 	if (ret) {
@@ -592,8 +612,10 @@
 
 	/* Clear frozen state */
 	rc = eeh_clear_pe_frozen_state(pe, false);
-	if (rc)
+	if (rc) {
+		pci_unlock_rescan_remove();
 		return rc;
+	}
 
 	/* Give the system 5 seconds to finish running the user-space
 	 * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes,
@@ -633,7 +655,7 @@
  */
 #define MAX_WAIT_FOR_RECOVERY 300
 
-static void eeh_handle_normal_event(struct eeh_pe *pe)
+static bool eeh_handle_normal_event(struct eeh_pe *pe)
 {
 	struct pci_bus *frozen_bus;
 	int rc = 0;
@@ -643,7 +665,7 @@
 	if (!frozen_bus) {
 		pr_err("%s: Cannot find PCI bus for PHB#%d-PE#%x\n",
 			__func__, pe->phb->global_number, pe->addr);
-		return;
+		return false;
 	}
 
 	eeh_pe_update_time_stamp(pe);
@@ -768,7 +790,7 @@
 	pr_info("EEH: Notify device driver to resume\n");
 	eeh_pe_dev_traverse(pe, eeh_report_resume, NULL);
 
-	return;
+	return false;
 
 excess_failures:
 	/*
@@ -809,7 +831,11 @@
 		pci_lock_rescan_remove();
 		pcibios_remove_pci_devices(frozen_bus);
 		pci_unlock_rescan_remove();
+
+		/* The passed PE should no longer be used */
+		return true;
 	}
+	return false;
 }
 
 static void eeh_handle_special_event(void)
@@ -875,7 +901,14 @@
 		 */
 		if (rc == EEH_NEXT_ERR_FROZEN_PE ||
 		    rc == EEH_NEXT_ERR_FENCED_PHB) {
-			eeh_handle_normal_event(pe);
+			/*
+			 * eeh_handle_normal_event() can make the PE stale if it
+			 * determines that the PE cannot possibly be recovered.
+			 * Don't modify the PE state if that's the case.
+			 */
+			if (eeh_handle_normal_event(pe))
+				continue;
+
 			eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
 		} else {
 			pci_lock_rescan_remove();
@@ -889,6 +922,14 @@
 				/* Notify all devices to be down */
 				eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
 				bus = eeh_pe_bus_get(phb_pe);
+				if (!bus) {
+					pr_err("%s: Cannot find PCI bus for "
+					       "PHB#%d-PE#%x\n",
+					       __func__,
+					       pe->phb->global_number,
+					       pe->addr);
+					break;
+				}
 				eeh_pe_dev_traverse(pe,
 					eeh_report_failure, NULL);
 				pcibios_remove_pci_devices(bus);
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index a94f155..f6fd033 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -334,13 +334,13 @@
 tabort_syscall:
 	/* Firstly we need to enable TM in the kernel */
 	mfmsr	r10
-	li	r13, 1
-	rldimi	r10, r13, MSR_TM_LG, 63-MSR_TM_LG
+	li	r9, 1
+	rldimi	r10, r9, MSR_TM_LG, 63-MSR_TM_LG
 	mtmsrd	r10, 0
 
 	/* tabort, this dooms the transaction, nothing else */
-	li	r13, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)
-	TABORT(R13)
+	li	r9, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)
+	TABORT(R9)
 
 	/*
 	 * Return directly to userspace. We have corrupted user register state,
@@ -348,8 +348,8 @@
 	 * resume after the tbegin of the aborted transaction with the
 	 * checkpointed register state.
 	 */
-	li	r13, MSR_RI
-	andc	r10, r10, r13
+	li	r9, MSR_RI
+	andc	r10, r10, r9
 	mtmsrd	r10, 1
 	mtspr	SPRN_SRR0, r11
 	mtspr	SPRN_SRR1, r12
@@ -716,7 +716,7 @@
 
 	addi	r8,r1,INT_FRAME_SIZE	/* Get the kprobed function entry */
 
-	lwz	r3,GPR1(r1)
+	ld	r3,GPR1(r1)
 	subi	r3,r3,INT_FRAME_SIZE	/* dst: Allocate a trampoline exception frame */
 	mr	r4,r1			/* src:  current exception frame */
 	mr	r1,r3			/* Reroute the trampoline frame to r1 */
@@ -730,8 +730,8 @@
 	addi	r6,r6,8
 	bdnz	2b
 
-	/* Do real store operation to complete stwu */
-	lwz	r5,GPR1(r1)
+	/* Do real store operation to complete stdu */
+	ld	r5,GPR1(r1)
 	std	r8,0(r5)
 
 	/* Clear _TIF_EMULATE_STACK_STORE flag */
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 488e631..5cc93f0 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -735,8 +735,14 @@
 	andis.	r15,r14,(DBSR_IC|DBSR_BT)@h
 	beq+	1f
 
+#ifdef CONFIG_RELOCATABLE
+	ld	r15,PACATOC(r13)
+	ld	r14,interrupt_base_book3e@got(r15)
+	ld	r15,__end_interrupts@got(r15)
+#else
 	LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
 	LOAD_REG_IMMEDIATE(r15,__end_interrupts)
+#endif
 	cmpld	cr0,r10,r14
 	cmpld	cr1,r10,r15
 	blt+	cr0,1f
@@ -799,8 +805,14 @@
 	andis.	r15,r14,(DBSR_IC|DBSR_BT)@h
 	beq+	1f
 
+#ifdef CONFIG_RELOCATABLE
+	ld	r15,PACATOC(r13)
+	ld	r14,interrupt_base_book3e@got(r15)
+	ld	r15,__end_interrupts@got(r15)
+#else
 	LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
 	LOAD_REG_IMMEDIATE(r15,__end_interrupts)
+#endif
 	cmpld	cr0,r10,r14
 	cmpld	cr1,r10,r15
 	blt+	cr0,1f
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 0a0399c2..b81ccc5 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -962,11 +962,6 @@
 #endif
 	STD_RELON_EXCEPTION_PSERIES(0x5700, 0x1700, altivec_assist)
 
-	/* Other future vectors */
-	.align	7
-	.globl	__end_interrupts
-__end_interrupts:
-
 	.align	7
 system_call_entry:
 	b	system_call_common
@@ -1253,6 +1248,17 @@
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
 	STD_RELON_EXCEPTION_HV_OOL(0xf80, hv_facility_unavailable)
 
+	/*
+	 * The __end_interrupts marker must be past the out-of-line (OOL)
+	 * handlers, so that they are copied to real address 0x100 when running
+	 * a relocatable kernel. This ensures they can be reached from the short
+	 * trampoline handlers (like 0x4f00, 0x4f20, etc.) which branch
+	 * directly, without using LOAD_HANDLER().
+	 */
+	.align	7
+	.globl	__end_interrupts
+__end_interrupts:
+
 #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * Data area reserved for FWNMI option.
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 05e804c..fdf4878 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -227,8 +227,10 @@
 	rcu_read_lock();
 
 	bp = __this_cpu_read(bp_per_reg);
-	if (!bp)
+	if (!bp) {
+		rc = NOTIFY_DONE;
 		goto out;
+	}
 	info = counter_arch_bp(bp);
 
 	/*
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index ac86c53..e524a77 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -180,6 +180,7 @@
 static int ibmebus_create_devices(const struct of_device_id *matches)
 {
 	struct device_node *root, *child;
+	struct device *dev;
 	int ret = 0;
 
 	root = of_find_node_by_path("/");
@@ -188,9 +189,12 @@
 		if (!of_match_node(matches, child))
 			continue;
 
-		if (bus_find_device(&ibmebus_bus_type, NULL, child,
-				    ibmebus_match_node))
+		dev = bus_find_device(&ibmebus_bus_type, NULL, child,
+				      ibmebus_match_node);
+		if (dev) {
+			put_device(dev);
 			continue;
+		}
 
 		ret = ibmebus_create_device(child);
 		if (ret) {
@@ -262,6 +266,7 @@
 				   const char *buf, size_t count)
 {
 	struct device_node *dn = NULL;
+	struct device *dev;
 	char *path;
 	ssize_t rc = 0;
 
@@ -269,8 +274,10 @@
 	if (!path)
 		return -ENOMEM;
 
-	if (bus_find_device(&ibmebus_bus_type, NULL, path,
-			    ibmebus_match_path)) {
+	dev = bus_find_device(&ibmebus_bus_type, NULL, path,
+			      ibmebus_match_path);
+	if (dev) {
+		put_device(dev);
 		printk(KERN_WARNING "%s: %s has already been probed\n",
 		       __func__, path);
 		rc = -EEXIST;
@@ -307,6 +314,7 @@
 	if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
 				   ibmebus_match_path))) {
 		of_device_unregister(to_platform_device(dev));
+		put_device(dev);
 
 		kfree(path);
 		return count;
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index 112ccf4..73f6387 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -44,7 +44,7 @@
 	std	r0,0(r1);					\
 	ptesync;						\
 	ld	r0,0(r1);					\
-1:	cmp	cr0,r0,r0;					\
+1:	cmpd	cr0,r0,r0;					\
 	bne	1b;						\
 	IDLE_INST;						\
 	b	.
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 7c053f2..1138fec 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -514,6 +514,15 @@
 #endif
 #endif
 
+	/*
+	 * jprobes use jprobe_return() which skips the normal return
+	 * path of the function, and this messes up the accounting of the
+	 * function graph tracer.
+	 *
+	 * Pause function graph tracing while performing the jprobe function.
+	 */
+	pause_graph_tracing();
+
 	return 1;
 }
 
@@ -536,6 +545,8 @@
 	 * saved regs...
 	 */
 	memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
+	/* It's OK to start function graph tracing again */
+	unpause_graph_tracing();
 	preempt_enable_no_resched();
 	return 1;
 }
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index b2eb468..da3c4c3 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -204,6 +204,8 @@
 {
 	int index;
 
+	add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
+
 	/*
 	 * For now just print it to console.
 	 * TODO: log this error event to FSP or nvram.
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index ed3ab50..df4efa3 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -313,7 +313,7 @@
 	lis	r3, KERNELBASE@h
 	iccci	0,r3
 #endif
-#elif CONFIG_FSL_BOOKE
+#elif defined(CONFIG_FSL_BOOKE)
 BEGIN_FTR_SECTION
 	mfspr   r3,SPRN_L1CSR0
 	ori     r3,r3,L1CSR0_CFI|L1CSR0_CLFC
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 32e2652..1eb698f 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -969,7 +969,7 @@
 
 		/* Make partition a free partition */
 		part->header.signature = NVRAM_SIG_FREE;
-		strncpy(part->header.name, "wwwwwwwwwwww", 12);
+		memset(part->header.name, 'w', 12);
 		part->header.checksum = nvram_checksum(&part->header);
 		rc = nvram_write_header(part);
 		if (rc <= 0) {
@@ -987,8 +987,8 @@
 		}
 		if (prev) {
 			prev->header.length += part->header.length;
-			prev->header.checksum = nvram_checksum(&part->header);
-			rc = nvram_write_header(part);
+			prev->header.checksum = nvram_checksum(&prev->header);
+			rc = nvram_write_header(prev);
 			if (rc <= 0) {
 				printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
 				return rc;
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index a7b91b5..b7abf3c 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1239,6 +1239,16 @@
 		current->thread.regs = regs - 1;
 	}
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	/*
+	 * Clear any transactional state, we're exec()ing. The cause is
+	 * not important as there will never be a recheckpoint so it's not
+	 * user visible.
+	 */
+	if (MSR_TM_SUSPENDED(mfmsr()))
+		tm_reclaim_current(0);
+#endif
+
 	memset(regs->gpr, 0, sizeof(regs->gpr));
 	regs->ctr = 0;
 	regs->link = 0;
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 92dea8d..3139533 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -655,6 +655,7 @@
 	W(0xffff0000), W(0x003e0000),	/* POWER6 */
 	W(0xffff0000), W(0x003f0000),	/* POWER7 */
 	W(0xffff0000), W(0x004b0000),	/* POWER8E */
+	W(0xffff0000), W(0x004c0000),   /* POWER8NVL */
 	W(0xffff0000), W(0x004d0000),	/* POWER8 */
 	W(0xffffffff), W(0x0f000004),	/* all 2.07-compliant */
 	W(0xffffffff), W(0x0f000003),	/* all 2.06-compliant */
@@ -693,7 +694,7 @@
 	OV4_MIN_ENT_CAP,		/* minimum VP entitled capacity */
 
 	/* option vector 5: PAPR/OF options */
-	VECTOR_LENGTH(18),		/* length */
+	VECTOR_LENGTH(21),		/* length */
 	0,				/* don't ignore, don't halt */
 	OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
 	OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
@@ -717,15 +718,18 @@
 	 * must match by the macro below. Update the definition if
 	 * the structure layout changes.
 	 */
-#define IBM_ARCH_VEC_NRCORES_OFFSET	125
+#define IBM_ARCH_VEC_NRCORES_OFFSET	133
 	W(NR_CPUS),			/* number of cores supported */
 	0,
 	0,
 	0,
 	0,
 	OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) |
-	OV5_FEAT(OV5_PFO_HW_842),
-	OV5_FEAT(OV5_SUB_PROCESSORS),
+	OV5_FEAT(OV5_PFO_HW_842),				/* Byte 17 */
+	0,							/* Byte 18 */
+	0,							/* Byte 19 */
+	0,							/* Byte 20 */
+	OV5_FEAT(OV5_SUB_PROCESSORS),				/* Byte 21 */
 
 	/* option vector 6: IBM PAPR hints */
 	VECTOR_LENGTH(3),		/* length */
@@ -2660,6 +2664,9 @@
 
 	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
 
+	if (!PHANDLE_VALID(cpu_pkg))
+		return;
+
 	prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
 	prom.cpu = be32_to_cpu(rval);
 
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 737c0d0..b38fd08 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -376,7 +376,7 @@
 
 #else
 	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-		     offsetof(struct thread_fp_state, fpr[32][0]));
+		     offsetof(struct thread_fp_state, fpr[32]));
 
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				   &target->thread.fp_state, 0, -1);
@@ -404,7 +404,7 @@
 	return 0;
 #else
 	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-		     offsetof(struct thread_fp_state, fpr[32][0]));
+		     offsetof(struct thread_fp_state, fpr[32]));
 
 	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				  &target->thread.fp_state, 0, -1);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 5c03a6a..fe6e800 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -220,6 +220,15 @@
 		unsigned long lpcr = mfspr(SPRN_LPCR);
 		mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3);
 	}
+
+	/*
+	 * Fixup HFSCR:TM based on CPU features. The bit is set by our
+	 * early asm init because at that point we haven't updated our
+	 * CPU features from firmware and device-tree. Here we have,
+	 * so let's do it.
+	 */
+	if (cpu_has_feature(CPU_FTR_HVMODE) && !cpu_has_feature(CPU_FTR_TM_COMP))
+		mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM);
 }
 
 /*
@@ -742,7 +751,7 @@
 
 static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
 {
-	return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align,
+	return __alloc_bootmem_node(NODE_DATA(early_cpu_to_node(cpu)), size, align,
 				    __pa(MAX_DMA_ADDRESS));
 }
 
@@ -753,7 +762,7 @@
 
 static int pcpu_cpu_distance(unsigned int from, unsigned int to)
 {
-	if (cpu_to_node(from) == cpu_to_node(to))
+	if (early_cpu_to_node(from) == early_cpu_to_node(to))
 		return LOCAL_DISTANCE;
 	else
 		return REMOTE_DISTANCE;
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index bf8f34a..b7019b5 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -110,17 +110,11 @@
 	std	r3, STK_PARAM(R3)(r1)
 	SAVE_NVGPRS(r1)
 
-	/* We need to setup MSR for VSX register save instructions.  Here we
-	 * also clear the MSR RI since when we do the treclaim, we won't have a
-	 * valid kernel pointer for a while.  We clear RI here as it avoids
-	 * adding another mtmsr closer to the treclaim.  This makes the region
-	 * maked as non-recoverable wider than it needs to be but it saves on
-	 * inserting another mtmsrd later.
-	 */
+	/* We need to setup MSR for VSX register save instructions. */
 	mfmsr	r14
 	mr	r15, r14
 	ori	r15, r15, MSR_FP
-	li	r16, MSR_RI
+	li	r16, 0
 	ori	r16, r16, MSR_EE /* IRQs hard off */
 	andc	r15, r15, r16
 	oris	r15, r15, MSR_VEC@h
@@ -176,7 +170,17 @@
 1:	tdeqi   r6, 0
 	EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
 
-	/* The moment we treclaim, ALL of our GPRs will switch
+	/* Clear MSR RI since we are about to change r1, EE is already off. */
+	li	r4, 0
+	mtmsrd	r4, 1
+
+	/*
+	 * BE CAREFUL HERE:
+	 * At this point we can't take an SLB miss since we have MSR_RI
+	 * off. Load only to/from the stack/paca which are in SLB bolted regions
+	 * until we turn MSR RI back on.
+	 *
+	 * The moment we treclaim, ALL of our GPRs will switch
 	 * to user register state.  (FPRs, CCR etc. also!)
 	 * Use an sprg and a tm_scratch in the PACA to shuffle.
 	 */
@@ -197,6 +201,11 @@
 
 	/* Store the PPR in r11 and reset to decent value */
 	std	r11, GPR11(r1)			/* Temporary stash */
+
+	/* Reset MSR RI so we can take SLB faults again */
+	li	r11, MSR_RI
+	mtmsrd	r11, 1
+
 	mfspr	r11, SPRN_PPR
 	HMT_MEDIUM
 
@@ -397,11 +406,6 @@
 	ld	r5, THREAD_TM_DSCR(r3)
 	ld	r6, THREAD_TM_PPR(r3)
 
-	/* Clear the MSR RI since we are about to change R1.  EE is already off
-	 */
-	li	r4, 0
-	mtmsrd	r4, 1
-
 	REST_GPR(0, r7)				/* GPR0 */
 	REST_2GPRS(2, r7)			/* GPR2-3 */
 	REST_GPR(4, r7)				/* GPR4 */
@@ -439,10 +443,33 @@
 	ld	r6, _CCR(r7)
 	mtcr    r6
 
-	REST_GPR(1, r7)				/* GPR1 */
-	REST_GPR(5, r7)				/* GPR5-7 */
 	REST_GPR(6, r7)
-	ld	r7, GPR7(r7)
+
+	/*
+	 * Store r1 and r5 on the stack so that we can access them
+	 * after we clear MSR RI.
+	 */
+
+	REST_GPR(5, r7)
+	std	r5, -8(r1)
+	ld	r5, GPR1(r7)
+	std	r5, -16(r1)
+
+	REST_GPR(7, r7)
+
+	/* Clear MSR RI since we are about to change r1. EE is already off */
+	li	r5, 0
+	mtmsrd	r5, 1
+
+	/*
+	 * BE CAREFUL HERE:
+	 * At this point we can't take an SLB miss since we have MSR_RI
+	 * off. Load only to/from the stack/paca which are in SLB bolted regions
+	 * until we turn MSR RI back on.
+	 */
+
+	ld	r5, -8(r1)
+	ld	r1, -16(r1)
 
 	/* Commit register state as checkpointed state: */
 	TRECHKPT
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 37de90f..e4dcb0a 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -297,8 +297,6 @@
 
 	__this_cpu_inc(irq_stat.mce_exceptions);
 
-	add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
-
 	if (cur_cpu_spec && cur_cpu_spec->machine_check_early)
 		handled = cur_cpu_spec->machine_check_early(regs);
 	return handled;
@@ -704,6 +702,8 @@
 
 	__this_cpu_inc(irq_stat.mce_exceptions);
 
+	add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
+
 	/* See if any machine dependent calls. In theory, we would want
 	 * to call the CPU first, and call the ppc_md. one if the CPU
 	 * one returns a positive number. However there is existing code
diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S
index 2f01c4a..7612eeb 100644
--- a/arch/powerpc/kernel/vdso64/datapage.S
+++ b/arch/powerpc/kernel/vdso64/datapage.S
@@ -59,7 +59,7 @@
 	bl	V_LOCAL_FUNC(__get_datapage)
 	mtlr	r12
 	addi	r3,r3,CFG_SYSCALL_MAP64
-	cmpli	cr0,r4,0
+	cmpldi	cr0,r4,0
 	crclr	cr0*4+so
 	beqlr
 	li	r0,__NR_syscalls
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
index a76b4af..3820213 100644
--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -145,7 +145,7 @@
 	bne	cr0,99f
 
 	li	r3,0
-	cmpli	cr0,r4,0
+	cmpldi	cr0,r4,0
 	crclr	cr0*4+so
 	beqlr
 	lis	r5,CLOCK_REALTIME_RES@h
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 2afdb9c..729f8fa 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -498,6 +498,7 @@
 	case SPRN_MMCR0:
 	case SPRN_MMCR1:
 	case SPRN_MMCR2:
+	case SPRN_UMMCR2:
 #endif
 		break;
 unprivileged:
@@ -640,6 +641,7 @@
 	case SPRN_MMCR0:
 	case SPRN_MMCR1:
 	case SPRN_MMCR2:
+	case SPRN_UMMCR2:
 	case SPRN_TIR:
 #endif
 		*spr_val = 0;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index a7352b5..396dc44e 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1186,6 +1186,9 @@
 	case KVM_REG_PPC_TM_CR:
 		*val = get_reg_val(id, vcpu->arch.cr_tm);
 		break;
+	case KVM_REG_PPC_TM_XER:
+		*val = get_reg_val(id, vcpu->arch.xer_tm);
+		break;
 	case KVM_REG_PPC_TM_LR:
 		*val = get_reg_val(id, vcpu->arch.lr_tm);
 		break;
@@ -1393,6 +1396,9 @@
 	case KVM_REG_PPC_TM_CR:
 		vcpu->arch.cr_tm = set_reg_val(id, *val);
 		break;
+	case KVM_REG_PPC_TM_XER:
+		vcpu->arch.xer_tm = set_reg_val(id, *val);
+		break;
 	case KVM_REG_PPC_TM_LR:
 		vcpu->arch.lr_tm = set_reg_val(id, *val);
 		break;
@@ -2687,6 +2693,27 @@
 		return -EINVAL;
 	}
 
+	/*
+	 * Don't allow entry with a suspended transaction, because
+	 * the guest entry/exit code will lose it.
+	 * If the guest has TM enabled, save away their TM-related SPRs
+	 * (they will get restored by the TM unavailable interrupt).
+	 */
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	if (cpu_has_feature(CPU_FTR_TM) && current->thread.regs &&
+	    (current->thread.regs->msr & MSR_TM)) {
+		if (MSR_TM_ACTIVE(current->thread.regs->msr)) {
+			run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+			run->fail_entry.hardware_entry_failure_reason = 0;
+			return -EINVAL;
+		}
+		current->thread.tm_tfhar = mfspr(SPRN_TFHAR);
+		current->thread.tm_tfiar = mfspr(SPRN_TFIAR);
+		current->thread.tm_texasr = mfspr(SPRN_TEXASR);
+		current->thread.regs->msr &= ~MSR_TM;
+	}
+#endif
+
 	kvmppc_core_prepare_to_enter(vcpu);
 
 	/* No need to go into the guest when all we'll do is come back out */
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 9170051..d509ff5 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -653,6 +653,8 @@
 					      HPTE_V_ABSENT);
 			do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags),
 				  true);
+			/* Don't lose R/C bit updates done by hardware */
+			r |= be64_to_cpu(hpte[1]) & (HPTE_R_R | HPTE_R_C);
 			hpte[1] = cpu_to_be64(r);
 		}
 	}
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 463af88..1a743f8 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -655,112 +655,8 @@
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 BEGIN_FTR_SECTION
-	b	skip_tm
-END_FTR_SECTION_IFCLR(CPU_FTR_TM)
-
-	/* Turn on TM/FP/VSX/VMX so we can restore them. */
-	mfmsr	r5
-	li	r6, MSR_TM >> 32
-	sldi	r6, r6, 32
-	or	r5, r5, r6
-	ori	r5, r5, MSR_FP
-	oris	r5, r5, (MSR_VEC | MSR_VSX)@h
-	mtmsrd	r5
-
-	/*
-	 * The user may change these outside of a transaction, so they must
-	 * always be context switched.
-	 */
-	ld	r5, VCPU_TFHAR(r4)
-	ld	r6, VCPU_TFIAR(r4)
-	ld	r7, VCPU_TEXASR(r4)
-	mtspr	SPRN_TFHAR, r5
-	mtspr	SPRN_TFIAR, r6
-	mtspr	SPRN_TEXASR, r7
-
-	ld	r5, VCPU_MSR(r4)
-	rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
-	beq	skip_tm	/* TM not active in guest */
-
-	/* Make sure the failure summary is set, otherwise we'll program check
-	 * when we trechkpt.  It's possible that this might have been not set
-	 * on a kvmppc_set_one_reg() call but we shouldn't let this crash the
-	 * host.
-	 */
-	oris	r7, r7, (TEXASR_FS)@h
-	mtspr	SPRN_TEXASR, r7
-
-	/*
-	 * We need to load up the checkpointed state for the guest.
-	 * We need to do this early as it will blow away any GPRs, VSRs and
-	 * some SPRs.
-	 */
-
-	mr	r31, r4
-	addi	r3, r31, VCPU_FPRS_TM
-	bl	load_fp_state
-	addi	r3, r31, VCPU_VRS_TM
-	bl	load_vr_state
-	mr	r4, r31
-	lwz	r7, VCPU_VRSAVE_TM(r4)
-	mtspr	SPRN_VRSAVE, r7
-
-	ld	r5, VCPU_LR_TM(r4)
-	lwz	r6, VCPU_CR_TM(r4)
-	ld	r7, VCPU_CTR_TM(r4)
-	ld	r8, VCPU_AMR_TM(r4)
-	ld	r9, VCPU_TAR_TM(r4)
-	mtlr	r5
-	mtcr	r6
-	mtctr	r7
-	mtspr	SPRN_AMR, r8
-	mtspr	SPRN_TAR, r9
-
-	/*
-	 * Load up PPR and DSCR values but don't put them in the actual SPRs
-	 * till the last moment to avoid running with userspace PPR and DSCR for
-	 * too long.
-	 */
-	ld	r29, VCPU_DSCR_TM(r4)
-	ld	r30, VCPU_PPR_TM(r4)
-
-	std	r2, PACATMSCRATCH(r13) /* Save TOC */
-
-	/* Clear the MSR RI since r1, r13 are all going to be foobar. */
-	li	r5, 0
-	mtmsrd	r5, 1
-
-	/* Load GPRs r0-r28 */
-	reg = 0
-	.rept	29
-	ld	reg, VCPU_GPRS_TM(reg)(r31)
-	reg = reg + 1
-	.endr
-
-	mtspr	SPRN_DSCR, r29
-	mtspr	SPRN_PPR, r30
-
-	/* Load final GPRs */
-	ld	29, VCPU_GPRS_TM(29)(r31)
-	ld	30, VCPU_GPRS_TM(30)(r31)
-	ld	31, VCPU_GPRS_TM(31)(r31)
-
-	/* TM checkpointed state is now setup.  All GPRs are now volatile. */
-	TRECHKPT
-
-	/* Now let's get back the state we need. */
-	HMT_MEDIUM
-	GET_PACA(r13)
-	ld	r29, HSTATE_DSCR(r13)
-	mtspr	SPRN_DSCR, r29
-	ld	r4, HSTATE_KVM_VCPU(r13)
-	ld	r1, HSTATE_HOST_R1(r13)
-	ld	r2, PACATMSCRATCH(r13)
-
-	/* Set the MSR RI since we have our registers back. */
-	li	r5, MSR_RI
-	mtmsrd	r5, 1
-skip_tm:
+	bl	kvmppc_restore_tm
+END_FTR_SECTION_IFSET(CPU_FTR_TM)
 #endif
 
 	/* Load guest PMU registers */
@@ -841,12 +737,6 @@
 	/* Skip next section on POWER7 */
 	b	8f
 END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
-	/* Turn on TM so we can access TFHAR/TFIAR/TEXASR */
-	mfmsr	r8
-	li	r0, 1
-	rldimi	r8, r0, MSR_TM_LG, 63-MSR_TM_LG
-	mtmsrd	r8
-
 	/* Load up POWER8-specific registers */
 	ld	r5, VCPU_IAMR(r4)
 	lwz	r6, VCPU_PSPB(r4)
@@ -1436,106 +1326,8 @@
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 BEGIN_FTR_SECTION
-	b	2f
-END_FTR_SECTION_IFCLR(CPU_FTR_TM)
-	/* Turn on TM. */
-	mfmsr	r8
-	li	r0, 1
-	rldimi	r8, r0, MSR_TM_LG, 63-MSR_TM_LG
-	mtmsrd	r8
-
-	ld	r5, VCPU_MSR(r9)
-	rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
-	beq	1f	/* TM not active in guest. */
-
-	li	r3, TM_CAUSE_KVM_RESCHED
-
-	/* Clear the MSR RI since r1, r13 are all going to be foobar. */
-	li	r5, 0
-	mtmsrd	r5, 1
-
-	/* All GPRs are volatile at this point. */
-	TRECLAIM(R3)
-
-	/* Temporarily store r13 and r9 so we have some regs to play with */
-	SET_SCRATCH0(r13)
-	GET_PACA(r13)
-	std	r9, PACATMSCRATCH(r13)
-	ld	r9, HSTATE_KVM_VCPU(r13)
-
-	/* Get a few more GPRs free. */
-	std	r29, VCPU_GPRS_TM(29)(r9)
-	std	r30, VCPU_GPRS_TM(30)(r9)
-	std	r31, VCPU_GPRS_TM(31)(r9)
-
-	/* Save away PPR and DSCR soon so don't run with user values. */
-	mfspr	r31, SPRN_PPR
-	HMT_MEDIUM
-	mfspr	r30, SPRN_DSCR
-	ld	r29, HSTATE_DSCR(r13)
-	mtspr	SPRN_DSCR, r29
-
-	/* Save all but r9, r13 & r29-r31 */
-	reg = 0
-	.rept	29
-	.if (reg != 9) && (reg != 13)
-	std	reg, VCPU_GPRS_TM(reg)(r9)
-	.endif
-	reg = reg + 1
-	.endr
-	/* ... now save r13 */
-	GET_SCRATCH0(r4)
-	std	r4, VCPU_GPRS_TM(13)(r9)
-	/* ... and save r9 */
-	ld	r4, PACATMSCRATCH(r13)
-	std	r4, VCPU_GPRS_TM(9)(r9)
-
-	/* Reload stack pointer and TOC. */
-	ld	r1, HSTATE_HOST_R1(r13)
-	ld	r2, PACATOC(r13)
-
-	/* Set MSR RI now we have r1 and r13 back. */
-	li	r5, MSR_RI
-	mtmsrd	r5, 1
-
-	/* Save away checkpinted SPRs. */
-	std	r31, VCPU_PPR_TM(r9)
-	std	r30, VCPU_DSCR_TM(r9)
-	mflr	r5
-	mfcr	r6
-	mfctr	r7
-	mfspr	r8, SPRN_AMR
-	mfspr	r10, SPRN_TAR
-	std	r5, VCPU_LR_TM(r9)
-	stw	r6, VCPU_CR_TM(r9)
-	std	r7, VCPU_CTR_TM(r9)
-	std	r8, VCPU_AMR_TM(r9)
-	std	r10, VCPU_TAR_TM(r9)
-
-	/* Restore r12 as trap number. */
-	lwz	r12, VCPU_TRAP(r9)
-
-	/* Save FP/VSX. */
-	addi	r3, r9, VCPU_FPRS_TM
-	bl	store_fp_state
-	addi	r3, r9, VCPU_VRS_TM
-	bl	store_vr_state
-	mfspr	r6, SPRN_VRSAVE
-	stw	r6, VCPU_VRSAVE_TM(r9)
-1:
-	/*
-	 * We need to save these SPRs after the treclaim so that the software
-	 * error code is recorded correctly in the TEXASR.  Also the user may
-	 * change these outside of a transaction, so they must always be
-	 * context switched.
-	 */
-	mfspr	r5, SPRN_TFHAR
-	mfspr	r6, SPRN_TFIAR
-	mfspr	r7, SPRN_TEXASR
-	std	r5, VCPU_TFHAR(r9)
-	std	r6, VCPU_TFIAR(r9)
-	std	r7, VCPU_TEXASR(r9)
-2:
+	bl	kvmppc_save_tm
+END_FTR_SECTION_IFSET(CPU_FTR_TM)
 #endif
 
 	/* Increment yield count if they have a VPA */
@@ -2245,6 +2037,13 @@
 	/* save FP state */
 	bl	kvmppc_save_fp
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+BEGIN_FTR_SECTION
+	ld	r9, HSTATE_KVM_VCPU(r13)
+	bl	kvmppc_save_tm
+END_FTR_SECTION_IFSET(CPU_FTR_TM)
+#endif
+
 	/*
 	 * Set DEC to the smaller of DEC and HDEC, so that we wake
 	 * no later than the end of our timeslice (HDEC interrupts
@@ -2321,6 +2120,12 @@
 	bl	kvmhv_accumulate_time
 #endif
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+BEGIN_FTR_SECTION
+	bl	kvmppc_restore_tm
+END_FTR_SECTION_IFSET(CPU_FTR_TM)
+#endif
+
 	/* load up FP state */
 	bl	kvmppc_load_fp
 
@@ -2629,6 +2434,243 @@
 	mr	r4,r31
 	blr
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+/*
+ * Save transactional state and TM-related registers.
+ * Called with r9 pointing to the vcpu struct.
+ * This can modify all checkpointed registers, but
+ * restores r1, r2 and r9 (vcpu pointer) before exit.
+ */
+kvmppc_save_tm:
+	mflr	r0
+	std	r0, PPC_LR_STKOFF(r1)
+
+	/* Turn on TM. */
+	mfmsr	r8
+	li	r0, 1
+	rldimi	r8, r0, MSR_TM_LG, 63-MSR_TM_LG
+	mtmsrd	r8
+
+	ld	r5, VCPU_MSR(r9)
+	rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
+	beq	1f	/* TM not active in guest. */
+
+	std	r1, HSTATE_HOST_R1(r13)
+	li	r3, TM_CAUSE_KVM_RESCHED
+
+	/* Clear the MSR RI since r1, r13 are all going to be foobar. */
+	li	r5, 0
+	mtmsrd	r5, 1
+
+	/* All GPRs are volatile at this point. */
+	TRECLAIM(R3)
+
+	/* Temporarily store r13 and r9 so we have some regs to play with */
+	SET_SCRATCH0(r13)
+	GET_PACA(r13)
+	std	r9, PACATMSCRATCH(r13)
+	ld	r9, HSTATE_KVM_VCPU(r13)
+
+	/* Get a few more GPRs free. */
+	std	r29, VCPU_GPRS_TM(29)(r9)
+	std	r30, VCPU_GPRS_TM(30)(r9)
+	std	r31, VCPU_GPRS_TM(31)(r9)
+
+	/* Save away PPR and DSCR soon so don't run with user values. */
+	mfspr	r31, SPRN_PPR
+	HMT_MEDIUM
+	mfspr	r30, SPRN_DSCR
+	ld	r29, HSTATE_DSCR(r13)
+	mtspr	SPRN_DSCR, r29
+
+	/* Save all but r9, r13 & r29-r31 */
+	reg = 0
+	.rept	29
+	.if (reg != 9) && (reg != 13)
+	std	reg, VCPU_GPRS_TM(reg)(r9)
+	.endif
+	reg = reg + 1
+	.endr
+	/* ... now save r13 */
+	GET_SCRATCH0(r4)
+	std	r4, VCPU_GPRS_TM(13)(r9)
+	/* ... and save r9 */
+	ld	r4, PACATMSCRATCH(r13)
+	std	r4, VCPU_GPRS_TM(9)(r9)
+
+	/* Reload stack pointer and TOC. */
+	ld	r1, HSTATE_HOST_R1(r13)
+	ld	r2, PACATOC(r13)
+
+	/* Set MSR RI now we have r1 and r13 back. */
+	li	r5, MSR_RI
+	mtmsrd	r5, 1
+
+	/* Save away checkpinted SPRs. */
+	std	r31, VCPU_PPR_TM(r9)
+	std	r30, VCPU_DSCR_TM(r9)
+	mflr	r5
+	mfcr	r6
+	mfctr	r7
+	mfspr	r8, SPRN_AMR
+	mfspr	r10, SPRN_TAR
+	mfxer	r11
+	std	r5, VCPU_LR_TM(r9)
+	stw	r6, VCPU_CR_TM(r9)
+	std	r7, VCPU_CTR_TM(r9)
+	std	r8, VCPU_AMR_TM(r9)
+	std	r10, VCPU_TAR_TM(r9)
+	std	r11, VCPU_XER_TM(r9)
+
+	/* Restore r12 as trap number. */
+	lwz	r12, VCPU_TRAP(r9)
+
+	/* Save FP/VSX. */
+	addi	r3, r9, VCPU_FPRS_TM
+	bl	store_fp_state
+	addi	r3, r9, VCPU_VRS_TM
+	bl	store_vr_state
+	mfspr	r6, SPRN_VRSAVE
+	stw	r6, VCPU_VRSAVE_TM(r9)
+1:
+	/*
+	 * We need to save these SPRs after the treclaim so that the software
+	 * error code is recorded correctly in the TEXASR.  Also the user may
+	 * change these outside of a transaction, so they must always be
+	 * context switched.
+	 */
+	mfspr	r5, SPRN_TFHAR
+	mfspr	r6, SPRN_TFIAR
+	mfspr	r7, SPRN_TEXASR
+	std	r5, VCPU_TFHAR(r9)
+	std	r6, VCPU_TFIAR(r9)
+	std	r7, VCPU_TEXASR(r9)
+
+	ld	r0, PPC_LR_STKOFF(r1)
+	mtlr	r0
+	blr
+
+/*
+ * Restore transactional state and TM-related registers.
+ * Called with r4 pointing to the vcpu struct.
+ * This potentially modifies all checkpointed registers.
+ * It restores r1, r2, r4 from the PACA.
+ */
+kvmppc_restore_tm:
+	mflr	r0
+	std	r0, PPC_LR_STKOFF(r1)
+
+	/* Turn on TM/FP/VSX/VMX so we can restore them. */
+	mfmsr	r5
+	li	r6, MSR_TM >> 32
+	sldi	r6, r6, 32
+	or	r5, r5, r6
+	ori	r5, r5, MSR_FP
+	oris	r5, r5, (MSR_VEC | MSR_VSX)@h
+	mtmsrd	r5
+
+	/*
+	 * The user may change these outside of a transaction, so they must
+	 * always be context switched.
+	 */
+	ld	r5, VCPU_TFHAR(r4)
+	ld	r6, VCPU_TFIAR(r4)
+	ld	r7, VCPU_TEXASR(r4)
+	mtspr	SPRN_TFHAR, r5
+	mtspr	SPRN_TFIAR, r6
+	mtspr	SPRN_TEXASR, r7
+
+	ld	r5, VCPU_MSR(r4)
+	rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
+	beqlr		/* TM not active in guest */
+	std	r1, HSTATE_HOST_R1(r13)
+
+	/* Make sure the failure summary is set, otherwise we'll program check
+	 * when we trechkpt.  It's possible that this might have been not set
+	 * on a kvmppc_set_one_reg() call but we shouldn't let this crash the
+	 * host.
+	 */
+	oris	r7, r7, (TEXASR_FS)@h
+	mtspr	SPRN_TEXASR, r7
+
+	/*
+	 * We need to load up the checkpointed state for the guest.
+	 * We need to do this early as it will blow away any GPRs, VSRs and
+	 * some SPRs.
+	 */
+
+	mr	r31, r4
+	addi	r3, r31, VCPU_FPRS_TM
+	bl	load_fp_state
+	addi	r3, r31, VCPU_VRS_TM
+	bl	load_vr_state
+	mr	r4, r31
+	lwz	r7, VCPU_VRSAVE_TM(r4)
+	mtspr	SPRN_VRSAVE, r7
+
+	ld	r5, VCPU_LR_TM(r4)
+	lwz	r6, VCPU_CR_TM(r4)
+	ld	r7, VCPU_CTR_TM(r4)
+	ld	r8, VCPU_AMR_TM(r4)
+	ld	r9, VCPU_TAR_TM(r4)
+	ld	r10, VCPU_XER_TM(r4)
+	mtlr	r5
+	mtcr	r6
+	mtctr	r7
+	mtspr	SPRN_AMR, r8
+	mtspr	SPRN_TAR, r9
+	mtxer	r10
+
+	/*
+	 * Load up PPR and DSCR values but don't put them in the actual SPRs
+	 * till the last moment to avoid running with userspace PPR and DSCR for
+	 * too long.
+	 */
+	ld	r29, VCPU_DSCR_TM(r4)
+	ld	r30, VCPU_PPR_TM(r4)
+
+	std	r2, PACATMSCRATCH(r13) /* Save TOC */
+
+	/* Clear the MSR RI since r1, r13 are all going to be foobar. */
+	li	r5, 0
+	mtmsrd	r5, 1
+
+	/* Load GPRs r0-r28 */
+	reg = 0
+	.rept	29
+	ld	reg, VCPU_GPRS_TM(reg)(r31)
+	reg = reg + 1
+	.endr
+
+	mtspr	SPRN_DSCR, r29
+	mtspr	SPRN_PPR, r30
+
+	/* Load final GPRs */
+	ld	29, VCPU_GPRS_TM(29)(r31)
+	ld	30, VCPU_GPRS_TM(30)(r31)
+	ld	31, VCPU_GPRS_TM(31)(r31)
+
+	/* TM checkpointed state is now setup.  All GPRs are now volatile. */
+	TRECHKPT
+
+	/* Now let's get back the state we need. */
+	HMT_MEDIUM
+	GET_PACA(r13)
+	ld	r29, HSTATE_DSCR(r13)
+	mtspr	SPRN_DSCR, r29
+	ld	r4, HSTATE_KVM_VCPU(r13)
+	ld	r1, HSTATE_HOST_R1(r13)
+	ld	r2, PACATMSCRATCH(r13)
+
+	/* Set the MSR RI since we have our registers back. */
+	li	r5, MSR_RI
+	mtmsrd	r5, 1
+
+	ld	r0, PPC_LR_STKOFF(r1)
+	mtlr	r0
+	blr
+#endif
+
 /*
  * We come here if we get any exception or interrupt while we are
  * executing host real mode code while in guest MMU context.
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index fd58751..6d63cd6 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -2033,7 +2033,7 @@
 		if (type == KVMPPC_DEBUG_NONE)
 			continue;
 
-		if (type & !(KVMPPC_DEBUG_WATCH_READ |
+		if (type & ~(KVMPPC_DEBUG_WATCH_READ |
 			     KVMPPC_DEBUG_WATCH_WRITE |
 			     KVMPPC_DEBUG_BREAKPOINT))
 			return -EINVAL;
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 5cc2e7a..b379146 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -302,7 +302,6 @@
 			advance = 0;
 			printk(KERN_ERR "Couldn't emulate instruction 0x%08x "
 			       "(op %d xop %d)\n", inst, get_op(inst), get_xop(inst));
-			kvmppc_core_queue_program(vcpu, 0);
 		}
 	}
 
diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S
index f09899e..7b22624 100644
--- a/arch/powerpc/lib/copyuser_64.S
+++ b/arch/powerpc/lib/copyuser_64.S
@@ -359,6 +359,7 @@
 	addi	r3,r3,8
 171:
 177:
+179:
 	addi	r3,r3,8
 370:
 372:
@@ -373,7 +374,6 @@
 173:
 174:
 175:
-179:
 181:
 184:
 186:
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index dc885b3..4014881 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1806,8 +1806,6 @@
 		goto instr_done;
 
 	case LARX:
-		if (regs->msr & MSR_LE)
-			return 0;
 		if (op.ea & (size - 1))
 			break;		/* can't handle misaligned */
 		err = -EFAULT;
@@ -1829,8 +1827,6 @@
 		goto ldst_done;
 
 	case STCX:
-		if (regs->msr & MSR_LE)
-			return 0;
 		if (op.ea & (size - 1))
 			break;		/* can't handle misaligned */
 		err = -EFAULT;
@@ -1854,8 +1850,6 @@
 		goto ldst_done;
 
 	case LOAD:
-		if (regs->msr & MSR_LE)
-			return 0;
 		err = read_mem(&regs->gpr[op.reg], op.ea, size, regs);
 		if (!err) {
 			if (op.type & SIGNEXT)
@@ -1867,8 +1861,6 @@
 
 #ifdef CONFIG_PPC_FPU
 	case LOAD_FP:
-		if (regs->msr & MSR_LE)
-			return 0;
 		if (size == 4)
 			err = do_fp_load(op.reg, do_lfs, op.ea, size, regs);
 		else
@@ -1877,15 +1869,11 @@
 #endif
 #ifdef CONFIG_ALTIVEC
 	case LOAD_VMX:
-		if (regs->msr & MSR_LE)
-			return 0;
 		err = do_vec_load(op.reg, do_lvx, op.ea & ~0xfUL, regs);
 		goto ldst_done;
 #endif
 #ifdef CONFIG_VSX
 	case LOAD_VSX:
-		if (regs->msr & MSR_LE)
-			return 0;
 		err = do_vsx_load(op.reg, do_lxvd2x, op.ea, regs);
 		goto ldst_done;
 #endif
@@ -1908,8 +1896,6 @@
 		goto instr_done;
 
 	case STORE:
-		if (regs->msr & MSR_LE)
-			return 0;
 		if ((op.type & UPDATE) && size == sizeof(long) &&
 		    op.reg == 1 && op.update_reg == 1 &&
 		    !(regs->msr & MSR_PR) &&
@@ -1922,8 +1908,6 @@
 
 #ifdef CONFIG_PPC_FPU
 	case STORE_FP:
-		if (regs->msr & MSR_LE)
-			return 0;
 		if (size == 4)
 			err = do_fp_store(op.reg, do_stfs, op.ea, size, regs);
 		else
@@ -1932,15 +1916,11 @@
 #endif
 #ifdef CONFIG_ALTIVEC
 	case STORE_VMX:
-		if (regs->msr & MSR_LE)
-			return 0;
 		err = do_vec_store(op.reg, do_stvx, op.ea & ~0xfUL, regs);
 		goto ldst_done;
 #endif
 #ifdef CONFIG_VSX
 	case STORE_VSX:
-		if (regs->msr & MSR_LE)
-			return 0;
 		err = do_vsx_store(op.reg, do_stxvd2x, op.ea, regs);
 		goto ldst_done;
 #endif
diff --git a/arch/powerpc/mm/copro_fault.c b/arch/powerpc/mm/copro_fault.c
index 6527882..ddfd274 100644
--- a/arch/powerpc/mm/copro_fault.c
+++ b/arch/powerpc/mm/copro_fault.c
@@ -106,6 +106,8 @@
 	switch (REGION_ID(ea)) {
 	case USER_REGION_ID:
 		pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea);
+		if (mm == NULL)
+			return 1;
 		psize = get_slice_psize(mm, ea);
 		ssize = user_segment_size(ea);
 		vsid = get_vsid(mm->context.id, ea, ssize);
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index c8822af..19d9b2d 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -645,6 +645,10 @@
 	unsigned long psize = batch->psize;
 	int ssize = batch->ssize;
 	int i;
+	unsigned int use_local;
+
+	use_local = local && mmu_has_feature(MMU_FTR_TLBIEL) &&
+		mmu_psize_defs[psize].tlbiel && !cxl_ctx_in_use();
 
 	local_irq_save(flags);
 
@@ -671,8 +675,7 @@
 		} pte_iterate_hashed_end();
 	}
 
-	if (mmu_has_feature(MMU_FTR_TLBIEL) &&
-	    mmu_psize_defs[psize].tlbiel && local) {
+	if (use_local) {
 		asm volatile("ptesync":::"memory");
 		for (i = 0; i < number; i++) {
 			vpn = batch->vpn[i];
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index 736d18b..0b48ce4 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -113,7 +113,12 @@
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
 	b	slb_finish_load_1T
 
-0:
+0:	/*
+	 * For userspace addresses, make sure this is region 0.
+	 */
+	cmpdi	r9, 0
+	bne	8f
+
 	/* when using slices, we extract the psize off the slice bitmaps
 	 * and then we need to get the sllp encoding off the mmu_psize_defs
 	 * array.
@@ -174,6 +179,16 @@
 	b	slb_finish_load
 
 8:	/* invalid EA */
+	/*
+	 * It's possible the bad EA is too large to fit in the SLB cache, which
+	 * would mean we'd fail to invalidate it on context switch. So mark the
+	 * SLB cache as full so we force a full flush. We also set cr7+eq to
+	 * mark the address as a kernel address, so slb_finish_load() skips
+	 * trying to insert it into the SLB cache.
+	 */
+	li	r9,SLB_CACHE_ENTRIES + 1
+	sth	r9,PACASLBCACHEPTR(r13)
+	crset	4*cr7+eq
 	li	r10,0			/* BAD_VSID */
 	li	r9,0			/* BAD_VSID */
 	li	r11,SLB_VSID_USER	/* flags don't much matter */
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 0f432a7..6ad12b2 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -105,7 +105,7 @@
 	if ((mm->task_size - len) < addr)
 		return 0;
 	vma = find_vma(mm, addr);
-	return (!vma || (addr + len) <= vma->vm_start);
+	return (!vma || (addr + len) <= vm_start_gap(vma));
 }
 
 static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice)
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 2ba60259..9273685 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -956,6 +956,11 @@
 		}
 
 		bus = eeh_pe_bus_get(pe);
+		if (!bus) {
+			pr_err("%s: Cannot find PCI bus for PHB#%d-PE#%x\n",
+			       __func__, pe->phb->global_number, pe->addr);
+			return -EIO;
+		}
 		if (pci_is_root_bus(bus) ||
 			pci_is_root_bus(bus->parent))
 			ret = pnv_eeh_root_reset(hose, option);
@@ -1163,7 +1168,7 @@
 		return;
 	}
 
-	switch (data->type) {
+	switch (be16_to_cpu(data->type)) {
 	case OPAL_P7IOC_DIAG_TYPE_RGC:
 		pr_info("P7IOC diag-data for RGC\n\n");
 		pnv_eeh_dump_hub_diag_common(data);
@@ -1395,7 +1400,7 @@
 
 				/* Try best to clear it */
 				opal_pci_eeh_freeze_clear(phb->opal_id,
-					frozen_pe_no,
+					be64_to_cpu(frozen_pe_no),
 					OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
 				ret = EEH_NEXT_ERR_NONE;
 			} else if ((*pe)->state & EEH_PE_ISOLATED ||
diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c
index 2ee9643..4c82782 100644
--- a/arch/powerpc/platforms/powernv/opal-dump.c
+++ b/arch/powerpc/platforms/powernv/opal-dump.c
@@ -370,6 +370,7 @@
 	uint32_t dump_id, dump_size, dump_type;
 	struct dump_obj *dump;
 	char name[22];
+	struct kobject *kobj;
 
 	rc = dump_read_info(&dump_id, &dump_size, &dump_type);
 	if (rc != OPAL_SUCCESS)
@@ -381,8 +382,12 @@
 	 * that gracefully and not create two conflicting
 	 * entries.
 	 */
-	if (kset_find_obj(dump_kset, name))
+	kobj = kset_find_obj(dump_kset, name);
+	if (kobj) {
+		/* Drop reference added by kset_find_obj() */
+		kobject_put(kobj);
 		return 0;
+	}
 
 	dump = create_dump_obj(dump_id, dump_size, dump_type);
 	if (!dump)
diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c
index 37f959b..f2344cb 100644
--- a/arch/powerpc/platforms/powernv/opal-elog.c
+++ b/arch/powerpc/platforms/powernv/opal-elog.c
@@ -247,6 +247,7 @@
 	uint64_t elog_type;
 	int rc;
 	char name[2+16+1];
+	struct kobject *kobj;
 
 	rc = opal_get_elog_size(&id, &size, &type);
 	if (rc != OPAL_SUCCESS) {
@@ -269,8 +270,12 @@
 	 * that gracefully and not create two conflicting
 	 * entries.
 	 */
-	if (kset_find_obj(elog_kset, name))
+	kobj = kset_find_obj(elog_kset, name);
+	if (kobj) {
+		/* Drop reference added by kset_find_obj() */
+		kobject_put(kobj);
 		return IRQ_HANDLED;
+	}
 
 	create_elog_obj(log_id, elog_size, elog_type);
 
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index e45b88a..ae877c7 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -148,7 +148,7 @@
 opal_tracepoint_return:
 	std	r3,STK_REG(R31)(r1)
 	mr	r4,r3
-	ld	r0,STK_REG(R23)(r1)
+	ld	r3,STK_REG(R23)(r1)
 	bl	__trace_opal_exit
 	ld	r3,STK_REG(R31)(r1)
 	addi	r1,r1,STACKFRAMESIZE
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index ad8c3f4..dd5e0f3 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -197,8 +197,8 @@
 			be64_to_cpu(data->dma1ErrorLog1));
 
 	for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
-		if ((data->pestA[i] >> 63) == 0 &&
-		    (data->pestB[i] >> 63) == 0)
+		if ((be64_to_cpu(data->pestA[i]) >> 63) == 0 &&
+		    (be64_to_cpu(data->pestB[i]) >> 63) == 0)
 			continue;
 
 		pr_info("PE[%3d] A/B: %016llx %016llx\n",
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index f244dcb..96536c9 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -280,7 +280,6 @@
 	if (rc)
 		return rc;
 
-	of_node_put(dn); /* Must decrement the refcount */
 	return 0;
 }
 
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index ac3ffd9..405baaf 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -615,29 +615,50 @@
 {
 	int config_addr;
 	int ret;
+	/* Waiting 0.2s maximum before skipping configuration */
+	int max_wait = 200;
 
 	/* Figure out the PE address */
 	config_addr = pe->config_addr;
 	if (pe->addr)
 		config_addr = pe->addr;
 
-	/* Use new configure-pe function, if supported */
-	if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
-		ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
-				config_addr, BUID_HI(pe->phb->buid),
-				BUID_LO(pe->phb->buid));
-	} else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
-		ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
-				config_addr, BUID_HI(pe->phb->buid),
-				BUID_LO(pe->phb->buid));
-	} else {
-		return -EFAULT;
+	while (max_wait > 0) {
+		/* Use new configure-pe function, if supported */
+		if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
+			ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
+					config_addr, BUID_HI(pe->phb->buid),
+					BUID_LO(pe->phb->buid));
+		} else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
+			ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
+					config_addr, BUID_HI(pe->phb->buid),
+					BUID_LO(pe->phb->buid));
+		} else {
+			return -EFAULT;
+		}
+
+		if (!ret)
+			return ret;
+
+		/*
+		 * If RTAS returns a delay value that's above 100ms, cut it
+		 * down to 100ms in case firmware made a mistake.  For more
+		 * on how these delay values work see rtas_busy_delay_time
+		 */
+		if (ret > RTAS_EXTENDED_DELAY_MIN+2 &&
+		    ret <= RTAS_EXTENDED_DELAY_MAX)
+			ret = RTAS_EXTENDED_DELAY_MIN+2;
+
+		max_wait -= rtas_busy_delay_time(ret);
+
+		if (max_wait < 0)
+			break;
+
+		rtas_busy_delay(ret);
 	}
 
-	if (ret)
-		pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
-			__func__, pe->phb->global_number, pe->addr, ret);
-
+	pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+		__func__, pe->phb->global_number, pe->addr, ret);
 	return ret;
 }
 
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index e9ff44c..e8b1027 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -110,6 +110,7 @@
 	for (i = 0; i < num_lmbs; i++) {
 		lmbs[i].base_addr = be64_to_cpu(lmbs[i].base_addr);
 		lmbs[i].drc_index = be32_to_cpu(lmbs[i].drc_index);
+		lmbs[i].aa_index = be32_to_cpu(lmbs[i].aa_index);
 		lmbs[i].flags = be32_to_cpu(lmbs[i].flags);
 	}
 
@@ -553,6 +554,7 @@
 	for (i = 0; i < num_lmbs; i++) {
 		lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr);
 		lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index);
+		lmbs[i].aa_index = cpu_to_be32(lmbs[i].aa_index);
 		lmbs[i].flags = cpu_to_be32(lmbs[i].flags);
 	}
 
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index bd98ce2..3e8865b 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -912,7 +912,8 @@
 static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 			struct ddw_query_response *query)
 {
-	struct eeh_dev *edev;
+	struct device_node *dn;
+	struct pci_dn *pdn;
 	u32 cfg_addr;
 	u64 buid;
 	int ret;
@@ -923,11 +924,10 @@
 	 * Retrieve them from the pci device, not the node with the
 	 * dma-window property
 	 */
-	edev = pci_dev_to_eeh_dev(dev);
-	cfg_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		cfg_addr = edev->pe_config_addr;
-	buid = edev->phb->buid;
+	dn = pci_device_to_OF_node(dev);
+	pdn = PCI_DN(dn);
+	buid = pdn->phb->buid;
+	cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
 
 	ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
 		  cfg_addr, BUID_HI(buid), BUID_LO(buid));
@@ -941,7 +941,8 @@
 			struct ddw_create_response *create, int page_shift,
 			int window_shift)
 {
-	struct eeh_dev *edev;
+	struct device_node *dn;
+	struct pci_dn *pdn;
 	u32 cfg_addr;
 	u64 buid;
 	int ret;
@@ -952,11 +953,10 @@
 	 * Retrieve them from the pci device, not the node with the
 	 * dma-window property
 	 */
-	edev = pci_dev_to_eeh_dev(dev);
-	cfg_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		cfg_addr = edev->pe_config_addr;
-	buid = edev->phb->buid;
+	dn = pci_device_to_OF_node(dev);
+	pdn = PCI_DN(dn);
+	buid = pdn->phb->buid;
+	cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
 
 	do {
 		/* extra outputs are LIOBN and dma-addr (hi, lo) */
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index b7a67e3..3ae4328 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -406,7 +406,7 @@
 					     unsigned long *vpn, int count,
 					     int psize, int ssize)
 {
-	unsigned long param[8];
+	unsigned long param[PLPAR_HCALL9_BUFSIZE];
 	int i = 0, pix = 0, rc;
 	unsigned long flags = 0;
 	int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
@@ -523,7 +523,7 @@
 	unsigned long flags = 0;
 	struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
 	int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
-	unsigned long param[9];
+	unsigned long param[PLPAR_HCALL9_BUFSIZE];
 	unsigned long hash, index, shift, hidx, slot;
 	real_pte_t pte;
 	int psize, ssize;
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c
index 4da604e..ca15613 100644
--- a/arch/s390/boot/compressed/misc.c
+++ b/arch/s390/boot/compressed/misc.c
@@ -141,31 +141,34 @@
 
 unsigned long decompress_kernel(void)
 {
-	unsigned long output_addr;
-	unsigned char *output;
+	void *output, *kernel_end;
 
-	output_addr = ((unsigned long) &_end + HEAP_SIZE + 4095UL) & -4096UL;
-	check_ipl_parmblock((void *) 0, output_addr + SZ__bss_start);
-	memset(&_bss, 0, &_ebss - &_bss);
-	free_mem_ptr = (unsigned long)&_end;
-	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-	output = (unsigned char *) output_addr;
+	output = (void *) ALIGN((unsigned long) &_end + HEAP_SIZE, PAGE_SIZE);
+	kernel_end = output + SZ__bss_start;
+	check_ipl_parmblock((void *) 0, (unsigned long) kernel_end);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/*
 	 * Move the initrd right behind the end of the decompressed
-	 * kernel image.
+	 * kernel image. This also prevents initrd corruption caused by
+	 * bss clearing since kernel_end will always be located behind the
+	 * current bss section..
 	 */
-	if (INITRD_START && INITRD_SIZE &&
-	    INITRD_START < (unsigned long) output + SZ__bss_start) {
-		check_ipl_parmblock(output + SZ__bss_start,
-				    INITRD_START + INITRD_SIZE);
-		memmove(output + SZ__bss_start,
-			(void *) INITRD_START, INITRD_SIZE);
-		INITRD_START = (unsigned long) output + SZ__bss_start;
+	if (INITRD_START && INITRD_SIZE && kernel_end > (void *) INITRD_START) {
+		check_ipl_parmblock(kernel_end, INITRD_SIZE);
+		memmove(kernel_end, (void *) INITRD_START, INITRD_SIZE);
+		INITRD_START = (unsigned long) kernel_end;
 	}
 #endif
 
+	/*
+	 * Clear bss section. free_mem_ptr and free_mem_end_ptr need to be
+	 * initialized afterwards since they reside in bss.
+	 */
+	memset(&_bss, 0, &_ebss - &_bss);
+	free_mem_ptr = (unsigned long) &_end;
+	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
+
 	puts("Uncompressing Linux... ");
 	__decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
 	puts("Ok, booting the kernel.\n");
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
index b8045b9..683a966 100644
--- a/arch/s390/crypto/prng.c
+++ b/arch/s390/crypto/prng.c
@@ -565,8 +565,10 @@
 		prng_data->prngws.byte_counter += n;
 		prng_data->prngws.reseed_counter += n;
 
-		if (copy_to_user(ubuf, prng_data->buf, chunk))
-			return -EFAULT;
+		if (copy_to_user(ubuf, prng_data->buf, chunk)) {
+			ret = -EFAULT;
+			break;
+		}
 
 		nbytes -= chunk;
 		ret += chunk;
@@ -669,11 +671,13 @@
 static struct miscdevice prng_sha512_dev = {
 	.name	= "prandom",
 	.minor	= MISC_DYNAMIC_MINOR,
+	.mode	= 0644,
 	.fops	= &prng_sha512_fops,
 };
 static struct miscdevice prng_tdes_dev = {
 	.name	= "prandom",
 	.minor	= MISC_DYNAMIC_MINOR,
+	.mode	= 0644,
 	.fops	= &prng_tdes_fops,
 };
 
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 0450357..b63b9a4 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -525,11 +525,11 @@
 static int diag224_get_name_table(void)
 {
 	/* memory must be below 2GB */
-	diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+	diag224_cpu_names = (char *) __get_free_page(GFP_KERNEL | GFP_DMA);
 	if (!diag224_cpu_names)
 		return -ENOMEM;
 	if (diag224(diag224_cpu_names)) {
-		kfree(diag224_cpu_names);
+		free_page((unsigned long) diag224_cpu_names);
 		return -EOPNOTSUPP;
 	}
 	EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
@@ -538,7 +538,7 @@
 
 static void diag224_delete_name_table(void)
 {
-	kfree(diag224_cpu_names);
+	free_page((unsigned long) diag224_cpu_names);
 }
 
 static int diag224_idx2name(int index, char *name)
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h
index d7697ab..8e136b8 100644
--- a/arch/s390/include/asm/ctl_reg.h
+++ b/arch/s390/include/asm/ctl_reg.h
@@ -15,7 +15,9 @@
 	BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\
 	asm volatile(							\
 		"	lctlg	%1,%2,%0\n"				\
-		: : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high));\
+		:							\
+		: "Q" (*(addrtype *)(&array)), "i" (low), "i" (high)	\
+		: "memory");						\
 }
 
 #define __ctl_store(array, low, high) {					\
diff --git a/arch/s390/include/asm/fpu/api.h b/arch/s390/include/asm/fpu/api.h
index 5e04f3c..8ae236b0 100644
--- a/arch/s390/include/asm/fpu/api.h
+++ b/arch/s390/include/asm/fpu/api.h
@@ -22,7 +22,7 @@
 		"	la	%0,0\n"
 		"1:\n"
 		EX_TABLE(0b,1b)
-		: "=d" (rc), "=d" (orig_fpc)
+		: "=d" (rc), "=&d" (orig_fpc)
 		: "d" (fpc), "0" (-EINVAL));
 	return rc;
 }
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h
index d29ad95..081b2ad 100644
--- a/arch/s390/include/asm/mmu.h
+++ b/arch/s390/include/asm/mmu.h
@@ -11,7 +11,7 @@
 	spinlock_t list_lock;
 	struct list_head pgtable_list;
 	struct list_head gmap_list;
-	unsigned long asce_bits;
+	unsigned long asce;
 	unsigned long asce_limit;
 	unsigned long vdso_base;
 	/* The mmu context allocates 4K page tables. */
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index e485817..22877c9 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -26,12 +26,28 @@
 	mm->context.has_pgste = 0;
 	mm->context.use_skey = 0;
 #endif
-	if (mm->context.asce_limit == 0) {
+	switch (mm->context.asce_limit) {
+	case 1UL << 42:
+		/*
+		 * forked 3-level task, fall through to set new asce with new
+		 * mm->pgd
+		 */
+	case 0:
 		/* context created by exec, set asce limit to 4TB */
-		mm->context.asce_bits = _ASCE_TABLE_LENGTH |
-			_ASCE_USER_BITS | _ASCE_TYPE_REGION3;
 		mm->context.asce_limit = STACK_TOP_MAX;
-	} else if (mm->context.asce_limit == (1UL << 31)) {
+		mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH |
+				   _ASCE_USER_BITS | _ASCE_TYPE_REGION3;
+		break;
+	case 1UL << 53:
+		/* forked 4-level task, set new asce with new mm->pgd */
+		mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH |
+				   _ASCE_USER_BITS | _ASCE_TYPE_REGION2;
+		break;
+	case 1UL << 31:
+		/* forked 2-level compat task, set new asce with new mm->pgd */
+		mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH |
+				   _ASCE_USER_BITS | _ASCE_TYPE_SEGMENT;
+		/* pgd_alloc() did not increase mm->nr_pmds */
 		mm_inc_nr_pmds(mm);
 	}
 	crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
@@ -42,7 +58,7 @@
 
 static inline void set_user_asce(struct mm_struct *mm)
 {
-	S390_lowcore.user_asce = mm->context.asce_bits | __pa(mm->pgd);
+	S390_lowcore.user_asce = mm->context.asce;
 	if (current->thread.mm_segment.ar4)
 		__ctl_load(S390_lowcore.user_asce, 7, 7);
 	set_cpu_flag(CIF_ASCE);
@@ -71,7 +87,7 @@
 {
 	int cpu = smp_processor_id();
 
-	S390_lowcore.user_asce = next->context.asce_bits | __pa(next->pgd);
+	S390_lowcore.user_asce = next->context.asce;
 	if (prev == next)
 		return;
 	if (MACHINE_HAS_TLB_LC)
diff --git a/arch/s390/include/asm/pci_dma.h b/arch/s390/include/asm/pci_dma.h
index 1aac41e..92df3eb 100644
--- a/arch/s390/include/asm/pci_dma.h
+++ b/arch/s390/include/asm/pci_dma.h
@@ -23,6 +23,8 @@
 #define ZPCI_IOTA_FS_2G			2
 #define ZPCI_KEY			(PAGE_DEFAULT_KEY << 5)
 
+#define ZPCI_TABLE_SIZE_RT	(1UL << 42)
+
 #define ZPCI_IOTA_STO_FLAG	(ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_ST)
 #define ZPCI_IOTA_RTTO_FLAG	(ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RT)
 #define ZPCI_IOTA_RSTO_FLAG	(ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RS)
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index d7cc79f..5991cdcb5 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -56,8 +56,8 @@
 	return _REGION2_ENTRY_EMPTY;
 }
 
-int crst_table_upgrade(struct mm_struct *, unsigned long limit);
-void crst_table_downgrade(struct mm_struct *, unsigned long limit);
+int crst_table_upgrade(struct mm_struct *);
+void crst_table_downgrade(struct mm_struct *);
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
 {
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 024f85f..e2c0e4e 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -829,6 +829,8 @@
 {
 	pgste_t pgste;
 
+	if (pte_present(entry))
+		pte_val(entry) &= ~_PAGE_UNUSED;
 	if (mm_has_pgste(mm)) {
 		pgste = pgste_get_lock(ptep);
 		pgste_val(pgste) &= ~_PGSTE_GPS_ZERO;
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index b16c3d0..c61ed78 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -74,7 +74,8 @@
  * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
  */
 
-#define TASK_SIZE_OF(tsk)	((tsk)->mm->context.asce_limit)
+#define TASK_SIZE_OF(tsk)	((tsk)->mm ? \
+				 (tsk)->mm->context.asce_limit : TASK_MAX_SIZE)
 #define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_31BIT) ? \
 					(1UL << 30) : (1UL << 41))
 #define TASK_SIZE		TASK_SIZE_OF(current)
@@ -163,7 +164,7 @@
 	regs->psw.mask	= PSW_USER_BITS | PSW_MASK_BA;			\
 	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
 	regs->gprs[15]	= new_stackp;					\
-	crst_table_downgrade(current->mm, 1UL << 31);			\
+	crst_table_downgrade(current->mm);				\
 	execve_tail();							\
 } while (0)
 
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h
index ca148f7..0a20316 100644
--- a/arch/s390/include/asm/tlbflush.h
+++ b/arch/s390/include/asm/tlbflush.h
@@ -81,7 +81,8 @@
 }
 
 /*
- * Flush TLB entries for a specific ASCE on all CPUs.
+ * Flush TLB entries for a specific ASCE on all CPUs. Should never be used
+ * when more than one asce (e.g. gmap) ran on this mm.
  */
 static inline void __tlb_flush_asce(struct mm_struct *mm, unsigned long asce)
 {
@@ -110,8 +111,7 @@
 static inline void __tlb_flush_kernel(void)
 {
 	if (MACHINE_HAS_IDTE)
-		__tlb_flush_idte((unsigned long) init_mm.pgd |
-				 init_mm.context.asce_bits);
+		__tlb_flush_idte(init_mm.context.asce);
 	else
 		__tlb_flush_global();
 }
@@ -133,8 +133,7 @@
 static inline void __tlb_flush_kernel(void)
 {
 	if (MACHINE_HAS_TLB_LC)
-		__tlb_flush_idte_local((unsigned long) init_mm.pgd |
-				       init_mm.context.asce_bits);
+		__tlb_flush_idte_local(init_mm.context.asce);
 	else
 		__tlb_flush_local();
 }
@@ -148,8 +147,7 @@
 	 * only ran on the local cpu.
 	 */
 	if (MACHINE_HAS_IDTE && list_empty(&mm->context.gmap_list))
-		__tlb_flush_asce(mm, (unsigned long) mm->pgd |
-				 mm->context.asce_bits);
+		__tlb_flush_asce(mm, mm->context.asce);
 	else
 		__tlb_flush_full(mm);
 }
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 9dd4cc4..c8d837f 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -150,7 +150,7 @@
 		"	jg	2b\n"				\
 		".popsection\n"					\
 		EX_TABLE(0b,3b) EX_TABLE(1b,3b)			\
-		: "=d" (__rc), "=Q" (*(to))			\
+		: "=d" (__rc), "+Q" (*(to))			\
 		: "d" (size), "Q" (*(from)),			\
 		  "d" (__reg0), "K" (-EFAULT)			\
 		: "cc");					\
@@ -215,28 +215,28 @@
 	__chk_user_ptr(ptr);					\
 	switch (sizeof(*(ptr))) {				\
 	case 1: {						\
-		unsigned char __x;				\
+		unsigned char __x = 0;				\
 		__gu_err = __get_user_fn(&__x, ptr,		\
 					 sizeof(*(ptr)));	\
 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	case 2: {						\
-		unsigned short __x;				\
+		unsigned short __x = 0;				\
 		__gu_err = __get_user_fn(&__x, ptr,		\
 					 sizeof(*(ptr)));	\
 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	case 4: {						\
-		unsigned int __x;				\
+		unsigned int __x = 0;				\
 		__gu_err = __get_user_fn(&__x, ptr,		\
 					 sizeof(*(ptr)));	\
 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
 		break;						\
 	};							\
 	case 8: {						\
-		unsigned long long __x;				\
+		unsigned long long __x = 0;			\
 		__gu_err = __get_user_fn(&__x, ptr,		\
 					 sizeof(*(ptr)));	\
 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index 171e09b..df46859 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -23,6 +23,8 @@
 #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
 #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
 
+#define LINUX_NOTE_NAME "LINUX"
+
 static struct memblock_region oldmem_region;
 
 static struct memblock_type oldmem_type = {
@@ -312,7 +314,7 @@
 static void *nt_s390_timer(void *ptr, struct save_area *sa)
 {
 	return nt_init(ptr, NT_S390_TIMER, &sa->timer, sizeof(sa->timer),
-			 KEXEC_CORE_NOTE_NAME);
+			 LINUX_NOTE_NAME);
 }
 
 /*
@@ -321,7 +323,7 @@
 static void *nt_s390_tod_cmp(void *ptr, struct save_area *sa)
 {
 	return nt_init(ptr, NT_S390_TODCMP, &sa->clk_cmp,
-		       sizeof(sa->clk_cmp), KEXEC_CORE_NOTE_NAME);
+		       sizeof(sa->clk_cmp), LINUX_NOTE_NAME);
 }
 
 /*
@@ -330,7 +332,7 @@
 static void *nt_s390_tod_preg(void *ptr, struct save_area *sa)
 {
 	return nt_init(ptr, NT_S390_TODPREG, &sa->tod_reg,
-		       sizeof(sa->tod_reg), KEXEC_CORE_NOTE_NAME);
+		       sizeof(sa->tod_reg), LINUX_NOTE_NAME);
 }
 
 /*
@@ -339,7 +341,7 @@
 static void *nt_s390_ctrs(void *ptr, struct save_area *sa)
 {
 	return nt_init(ptr, NT_S390_CTRS, &sa->ctrl_regs,
-		       sizeof(sa->ctrl_regs), KEXEC_CORE_NOTE_NAME);
+		       sizeof(sa->ctrl_regs), LINUX_NOTE_NAME);
 }
 
 /*
@@ -348,7 +350,7 @@
 static void *nt_s390_prefix(void *ptr, struct save_area *sa)
 {
 	return nt_init(ptr, NT_S390_PREFIX, &sa->pref_reg,
-			 sizeof(sa->pref_reg), KEXEC_CORE_NOTE_NAME);
+			 sizeof(sa->pref_reg), LINUX_NOTE_NAME);
 }
 
 /*
@@ -357,7 +359,7 @@
 static void *nt_s390_vx_high(void *ptr, __vector128 *vx_regs)
 {
 	return nt_init(ptr, NT_S390_VXRS_HIGH, &vx_regs[16],
-		       16 * sizeof(__vector128), KEXEC_CORE_NOTE_NAME);
+		       16 * sizeof(__vector128), LINUX_NOTE_NAME);
 }
 
 /*
@@ -370,12 +372,12 @@
 	int i;
 
 	note = (Elf64_Nhdr *)ptr;
-	note->n_namesz = strlen(KEXEC_CORE_NOTE_NAME) + 1;
+	note->n_namesz = strlen(LINUX_NOTE_NAME) + 1;
 	note->n_descsz = 16 * 8;
 	note->n_type = NT_S390_VXRS_LOW;
 	len = sizeof(Elf64_Nhdr);
 
-	memcpy(ptr + len, KEXEC_CORE_NOTE_NAME, note->n_namesz);
+	memcpy(ptr + len, LINUX_NOTE_NAME, note->n_namesz);
 	len = roundup(len + note->n_namesz, 4);
 
 	ptr += len;
@@ -462,6 +464,20 @@
 }
 
 /*
+ * Initialize final note (needed for /proc/vmcore code)
+ */
+static void *nt_final(void *ptr)
+{
+	Elf64_Nhdr *note;
+
+	note = (Elf64_Nhdr *) ptr;
+	note->n_namesz = 0;
+	note->n_descsz = 0;
+	note->n_type = 0;
+	return PTR_ADD(ptr, sizeof(Elf64_Nhdr));
+}
+
+/*
  * Initialize ELF header (new kernel)
  */
 static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt)
@@ -551,6 +567,7 @@
 		ptr = fill_cpu_elf_notes(ptr, &sa_ext->sa, sa_ext->vx_regs);
 	}
 	ptr = nt_vmcoreinfo(ptr);
+	ptr = nt_final(ptr);
 	memset(phdr, 0, sizeof(*phdr));
 	phdr->p_type = PT_NOTE;
 	phdr->p_offset = notes_offset;
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 424e680..4612ed7 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -229,12 +229,17 @@
 	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce
 .Lsie_done:
 # some program checks are suppressing. C code (e.g. do_protection_exception)
-# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other
-# instructions between sie64a and .Lsie_done should not cause program
-# interrupts. So lets use a nop (47 00 00 00) as a landing pad.
+# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
+# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
+# Other instructions between sie64a and .Lsie_done should not cause program
+# interrupts. So lets use 3 nops as a landing pad for all possible rewinds.
 # See also .Lcleanup_sie
-.Lrewind_pad:
-	nop	0
+.Lrewind_pad6:
+	nopr	7
+.Lrewind_pad4:
+	nopr	7
+.Lrewind_pad2:
+	nopr	7
 	.globl sie_exit
 sie_exit:
 	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
@@ -247,7 +252,9 @@
 	stg	%r14,__SF_EMPTY+16(%r15)	# set exit reason code
 	j	sie_exit
 
-	EX_TABLE(.Lrewind_pad,.Lsie_fault)
+	EX_TABLE(.Lrewind_pad6,.Lsie_fault)
+	EX_TABLE(.Lrewind_pad4,.Lsie_fault)
+	EX_TABLE(.Lrewind_pad2,.Lsie_fault)
 	EX_TABLE(sie_exit,.Lsie_fault)
 #endif
 
@@ -308,6 +315,7 @@
 	lg	%r14,__LC_VDSO_PER_CPU
 	lmg	%r0,%r10,__PT_R0(%r11)
 	mvc	__LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lsysc_exit_timer:
 	stpt	__LC_EXIT_TIMER
 	mvc	__VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
 	lmg	%r11,%r15,__PT_R11(%r11)
@@ -593,6 +601,7 @@
 	lg	%r14,__LC_VDSO_PER_CPU
 	lmg	%r0,%r10,__PT_R0(%r11)
 	mvc	__LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lio_exit_timer:
 	stpt	__LC_EXIT_TIMER
 	mvc	__VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
 	lmg	%r11,%r15,__PT_R11(%r11)
@@ -1118,15 +1127,23 @@
 	br	%r14
 
 .Lcleanup_sysc_restore:
+	# check if stpt has been executed
 	clg	%r9,BASED(.Lcleanup_sysc_restore_insn)
+	jh	0f
+	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+	cghi	%r11,__LC_SAVE_AREA_ASYNC
 	je	0f
+	mvc	__LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:	clg	%r9,BASED(.Lcleanup_sysc_restore_insn+8)
+	je	1f
 	lg	%r9,24(%r11)		# get saved pointer to pt_regs
 	mvc	__LC_RETURN_PSW(16),__PT_PSW(%r9)
 	mvc	0(64,%r11),__PT_R8(%r9)
 	lmg	%r0,%r7,__PT_R0(%r9)
-0:	lmg	%r8,%r9,__LC_RETURN_PSW
+1:	lmg	%r8,%r9,__LC_RETURN_PSW
 	br	%r14
 .Lcleanup_sysc_restore_insn:
+	.quad	.Lsysc_exit_timer
 	.quad	.Lsysc_done - 4
 
 .Lcleanup_io_tif:
@@ -1134,15 +1151,20 @@
 	br	%r14
 
 .Lcleanup_io_restore:
+	# check if stpt has been executed
 	clg	%r9,BASED(.Lcleanup_io_restore_insn)
-	je	0f
+	jh	0f
+	mvc	__LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:	clg	%r9,BASED(.Lcleanup_io_restore_insn+8)
+	je	1f
 	lg	%r9,24(%r11)		# get saved r11 pointer to pt_regs
 	mvc	__LC_RETURN_PSW(16),__PT_PSW(%r9)
 	mvc	0(64,%r11),__PT_R8(%r9)
 	lmg	%r0,%r7,__PT_R0(%r9)
-0:	lmg	%r8,%r9,__LC_RETURN_PSW
+1:	lmg	%r8,%r9,__LC_RETURN_PSW
 	br	%r14
 .Lcleanup_io_restore_insn:
+	.quad	.Lio_exit_timer
 	.quad	.Lio_done - 4
 
 .Lcleanup_idle:
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index b1f0a90..42570d8 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -2070,13 +2070,6 @@
 	S390_lowcore.program_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
 
-	/*
-	 * Clear subchannel ID and number to signal new kernel that no CCW or
-	 * SCSI IPL has been done (for kexec and kdump)
-	 */
-	S390_lowcore.subchannel_id = 0;
-	S390_lowcore.subchannel_nr = 0;
-
 	/* Store status at absolute zero */
 	store_status();
 
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 01c37b3..02bd587 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -963,6 +963,11 @@
 	if (target == current)
 		save_fpu_regs();
 
+	if (MACHINE_HAS_VX)
+		convert_vx_to_fp(fprs, target->thread.fpu.vxrs);
+	else
+		memcpy(&fprs, target->thread.fpu.fprs, sizeof(fprs));
+
 	/* If setting FPC, must validate it first. */
 	if (count > 0 && pos < offsetof(s390_fp_regs, fprs)) {
 		u32 ufpc[2] = { target->thread.fpu.fpc, 0 };
@@ -1067,6 +1072,9 @@
 	if (target == current)
 		save_fpu_regs();
 
+	for (i = 0; i < __NUM_VXRS_LOW; i++)
+		vxrs[i] = *((__u64 *)(target->thread.fpu.vxrs + i) + 1);
+
 	rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
 	if (rc == 0)
 		for (i = 0; i < __NUM_VXRS_LOW; i++)
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 1f581eb..d097d71 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -805,10 +805,10 @@
 {
 	struct sysinfo_3_2_2 *vmms;
 
-	vmms = (struct sysinfo_3_2_2 *) alloc_page(GFP_KERNEL);
-	if (vmms && stsi(vmms, 3, 2, 2) == 0 && vmms->count)
-		add_device_randomness(&vmms, vmms->count);
-	free_page((unsigned long) vmms);
+	vmms = (struct sysinfo_3_2_2 *) memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+	if (stsi(vmms, 3, 2, 2) == 0 && vmms->count)
+		add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count);
+	memblock_free((unsigned long) vmms, PAGE_SIZE);
 }
 
 /*
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 575dc12..23e3f5d 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -295,6 +295,9 @@
 	struct kvm_memory_slot *memslot;
 	int is_dirty = 0;
 
+	if (kvm_is_ucontrol(kvm))
+		return -EINVAL;
+
 	mutex_lock(&kvm->slots_lock);
 
 	r = -EINVAL;
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index c722400..feff9ca 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -89,7 +89,8 @@
 		asce_bits = _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
 		pgd_type = _REGION3_ENTRY_EMPTY;
 	}
-	S390_lowcore.kernel_asce = (__pa(init_mm.pgd) & PAGE_MASK) | asce_bits;
+	init_mm.context.asce = (__pa(init_mm.pgd) & PAGE_MASK) | asce_bits;
+	S390_lowcore.kernel_asce = init_mm.context.asce;
 	clear_table((unsigned long *) init_mm.pgd, pgd_type,
 		    sizeof(unsigned long)*2048);
 	vmem_map_init();
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index ea01477..126c4a9 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -97,7 +97,7 @@
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
@@ -135,7 +135,7 @@
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
-				(!vma || addr + len <= vma->vm_start))
+				(!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
@@ -174,7 +174,7 @@
 	if (!(flags & MAP_FIXED))
 		addr = 0;
 	if ((addr + len) >= TASK_SIZE)
-		return crst_table_upgrade(current->mm, 1UL << 53);
+		return crst_table_upgrade(current->mm);
 	return 0;
 }
 
@@ -191,7 +191,7 @@
 		return area;
 	if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) {
 		/* Upgrade the page table to 4 levels and retry. */
-		rc = crst_table_upgrade(mm, 1UL << 53);
+		rc = crst_table_upgrade(mm);
 		if (rc)
 			return (unsigned long) rc;
 		area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
@@ -213,7 +213,7 @@
 		return area;
 	if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) {
 		/* Upgrade the page table to 4 levels and retry. */
-		rc = crst_table_upgrade(mm, 1UL << 53);
+		rc = crst_table_upgrade(mm);
 		if (rc)
 			return (unsigned long) rc;
 		area = arch_get_unmapped_area_topdown(filp, addr, len,
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 54ef3bc..05ae254 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -49,81 +49,52 @@
 	__tlb_flush_local();
 }
 
-int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
+int crst_table_upgrade(struct mm_struct *mm)
 {
 	unsigned long *table, *pgd;
-	unsigned long entry;
-	int flush;
 
-	BUG_ON(limit > (1UL << 53));
-	flush = 0;
-repeat:
+	/* upgrade should only happen from 3 to 4 levels */
+	BUG_ON(mm->context.asce_limit != (1UL << 42));
+
 	table = crst_table_alloc(mm);
 	if (!table)
 		return -ENOMEM;
+
 	spin_lock_bh(&mm->page_table_lock);
-	if (mm->context.asce_limit < limit) {
-		pgd = (unsigned long *) mm->pgd;
-		if (mm->context.asce_limit <= (1UL << 31)) {
-			entry = _REGION3_ENTRY_EMPTY;
-			mm->context.asce_limit = 1UL << 42;
-			mm->context.asce_bits = _ASCE_TABLE_LENGTH |
-						_ASCE_USER_BITS |
-						_ASCE_TYPE_REGION3;
-		} else {
-			entry = _REGION2_ENTRY_EMPTY;
-			mm->context.asce_limit = 1UL << 53;
-			mm->context.asce_bits = _ASCE_TABLE_LENGTH |
-						_ASCE_USER_BITS |
-						_ASCE_TYPE_REGION2;
-		}
-		crst_table_init(table, entry);
-		pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
-		mm->pgd = (pgd_t *) table;
-		mm->task_size = mm->context.asce_limit;
-		table = NULL;
-		flush = 1;
-	}
+	pgd = (unsigned long *) mm->pgd;
+	crst_table_init(table, _REGION2_ENTRY_EMPTY);
+	pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
+	mm->pgd = (pgd_t *) table;
+	mm->context.asce_limit = 1UL << 53;
+	mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH |
+			   _ASCE_USER_BITS | _ASCE_TYPE_REGION2;
+	mm->task_size = mm->context.asce_limit;
 	spin_unlock_bh(&mm->page_table_lock);
-	if (table)
-		crst_table_free(mm, table);
-	if (mm->context.asce_limit < limit)
-		goto repeat;
-	if (flush)
-		on_each_cpu(__crst_table_upgrade, mm, 0);
+
+	on_each_cpu(__crst_table_upgrade, mm, 0);
 	return 0;
 }
 
-void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
+void crst_table_downgrade(struct mm_struct *mm)
 {
 	pgd_t *pgd;
 
+	/* downgrade should only happen from 3 to 2 levels (compat only) */
+	BUG_ON(mm->context.asce_limit != (1UL << 42));
+
 	if (current->active_mm == mm) {
 		clear_user_asce();
 		__tlb_flush_mm(mm);
 	}
-	while (mm->context.asce_limit > limit) {
-		pgd = mm->pgd;
-		switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
-		case _REGION_ENTRY_TYPE_R2:
-			mm->context.asce_limit = 1UL << 42;
-			mm->context.asce_bits = _ASCE_TABLE_LENGTH |
-						_ASCE_USER_BITS |
-						_ASCE_TYPE_REGION3;
-			break;
-		case _REGION_ENTRY_TYPE_R3:
-			mm->context.asce_limit = 1UL << 31;
-			mm->context.asce_bits = _ASCE_TABLE_LENGTH |
-						_ASCE_USER_BITS |
-						_ASCE_TYPE_SEGMENT;
-			break;
-		default:
-			BUG();
-		}
-		mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
-		mm->task_size = mm->context.asce_limit;
-		crst_table_free(mm, (unsigned long *) pgd);
-	}
+
+	pgd = mm->pgd;
+	mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
+	mm->context.asce_limit = 1UL << 31;
+	mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH |
+			   _ASCE_USER_BITS | _ASCE_TYPE_SEGMENT;
+	mm->task_size = mm->context.asce_limit;
+	crst_table_free(mm, (unsigned long *) pgd);
+
 	if (current->active_mm == mm)
 		set_user_asce(mm);
 }
@@ -195,7 +166,7 @@
 static void gmap_flush_tlb(struct gmap *gmap)
 {
 	if (MACHINE_HAS_IDTE)
-		__tlb_flush_asce(gmap->mm, gmap->asce);
+		__tlb_flush_idte(gmap->asce);
 	else
 		__tlb_flush_global();
 }
@@ -234,7 +205,7 @@
 
 	/* Flush tlb. */
 	if (MACHINE_HAS_IDTE)
-		__tlb_flush_asce(gmap->mm, gmap->asce);
+		__tlb_flush_idte(gmap->asce);
 	else
 		__tlb_flush_global();
 
@@ -1266,11 +1237,28 @@
  */
 bool gmap_test_and_clear_dirty(unsigned long address, struct gmap *gmap)
 {
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
 	pte_t *pte;
 	spinlock_t *ptl;
 	bool dirty = false;
 
-	pte = get_locked_pte(gmap->mm, address, &ptl);
+	pgd = pgd_offset(gmap->mm, address);
+	pud = pud_alloc(gmap->mm, pgd, address);
+	if (!pud)
+		return false;
+	pmd = pmd_alloc(gmap->mm, pud, address);
+	if (!pmd)
+		return false;
+	/* We can't run guests backed by huge pages, but userspace can
+	 * still set them up and then try to migrate them without any
+	 * migration support.
+	 */
+	if (pmd_large(*pmd))
+		return true;
+
+	pte = pte_alloc_map_lock(gmap->mm, pmd, address, &ptl);
 	if (unlikely(!pte))
 		return false;
 
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index ef7d6c8..f354fd8 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -372,7 +372,7 @@
 	ro_end = (unsigned long)&_eshared & PAGE_MASK;
 	for_each_memblock(memory, reg) {
 		start = reg->base;
-		end = reg->base + reg->size - 1;
+		end = reg->base + reg->size;
 		if (start >= ro_end || end <= ro_start)
 			vmem_add_mem(start, end - start, 0);
 		else if (start >= ro_start && end <= ro_end)
diff --git a/arch/s390/net/bpf_jit.h b/arch/s390/net/bpf_jit.h
index f010c93..fda605d 100644
--- a/arch/s390/net/bpf_jit.h
+++ b/arch/s390/net/bpf_jit.h
@@ -37,7 +37,7 @@
  *	      |		      |     |
  *	      +---------------+     |
  *	      | 8 byte skbp   |     |
- * R15+170 -> +---------------+     |
+ * R15+176 -> +---------------+     |
  *	      | 8 byte hlen   |     |
  * R15+168 -> +---------------+     |
  *	      | 4 byte align  |     |
@@ -58,7 +58,7 @@
 #define STK_OFF		(STK_SPACE - STK_160_UNUSED)
 #define STK_OFF_TMP	160	/* Offset of tmp buffer on stack */
 #define STK_OFF_HLEN	168	/* Offset of SKB header length on stack */
-#define STK_OFF_SKBP	170	/* Offset of SKB pointer on stack */
+#define STK_OFF_SKBP	176	/* Offset of SKB pointer on stack */
 
 #define STK_OFF_R6	(160 - 11 * 8)	/* Offset of r6 on stack */
 #define STK_OFF_TCCNT	(160 - 12 * 8)	/* Offset of tail_call_cnt on stack */
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 9a0c4c2..0e2919d 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -45,7 +45,7 @@
 	int labels[1];		/* Labels for local jumps */
 };
 
-#define BPF_SIZE_MAX	0x7ffff	/* Max size for program (20 bit signed displ) */
+#define BPF_SIZE_MAX	0xffff	/* Max size for program (16 bit branches) */
 
 #define SEEN_SKB	1	/* skb access */
 #define SEEN_MEM	2	/* use mem[] for temporary storage */
@@ -446,7 +446,7 @@
 		emit_load_skb_data_hlen(jit);
 	if (jit->seen & SEEN_SKB_CHANGE)
 		/* stg %b1,ST_OFF_SKBP(%r0,%r15) */
-		EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
+		EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_1, REG_0, REG_15,
 			      STK_OFF_SKBP);
 	/* Clear A (%b0) and X (%b7) registers for converted BPF programs */
 	if (is_classic) {
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 1944239..f2f6720 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -701,8 +701,7 @@
 		goto out;
 
 	zpci_map_resources(pdev);
-	zpci_register_ioat(zdev, 0, zdev->start_dma + PAGE_OFFSET,
-			   zdev->start_dma + zdev->iommu_size - 1,
+	zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
 			   (u64) zdev->dma_table);
 
 out:
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index d348f2c..4004e03 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -455,29 +455,42 @@
 	zdev->dma_table = dma_alloc_cpu_table();
 	if (!zdev->dma_table) {
 		rc = -ENOMEM;
-		goto out_clean;
+		goto out;
 	}
 
-	zdev->iommu_size = (unsigned long) high_memory - PAGE_OFFSET;
+	/*
+	 * Restrict the iommu bitmap size to the minimum of the following:
+	 * - main memory size
+	 * - 3-level pagetable address limit minus start_dma offset
+	 * - DMA address range allowed by the hardware (clp query pci fn)
+	 *
+	 * Also set zdev->end_dma to the actual end address of the usable
+	 * range, instead of the theoretical maximum as reported by hardware.
+	 */
+	zdev->iommu_size = min3((u64) high_memory,
+				ZPCI_TABLE_SIZE_RT - zdev->start_dma,
+				zdev->end_dma - zdev->start_dma + 1);
+	zdev->end_dma = zdev->start_dma + zdev->iommu_size - 1;
 	zdev->iommu_pages = zdev->iommu_size >> PAGE_SHIFT;
 	zdev->iommu_bitmap = vzalloc(zdev->iommu_pages / 8);
 	if (!zdev->iommu_bitmap) {
 		rc = -ENOMEM;
-		goto out_reg;
+		goto free_dma_table;
 	}
 
-	rc = zpci_register_ioat(zdev,
-				0,
-				zdev->start_dma + PAGE_OFFSET,
-				zdev->start_dma + zdev->iommu_size - 1,
+	rc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
 				(u64) zdev->dma_table);
 	if (rc)
-		goto out_reg;
-	return 0;
+		goto free_bitmap;
 
-out_reg:
+	return 0;
+free_bitmap:
+	vfree(zdev->iommu_bitmap);
+	zdev->iommu_bitmap = NULL;
+free_dma_table:
 	dma_free_cpu_table(zdev->dma_table);
-out_clean:
+	zdev->dma_table = NULL;
+out:
 	return rc;
 }
 
diff --git a/arch/score/include/asm/uaccess.h b/arch/score/include/asm/uaccess.h
index 20a3591..01aec8c 100644
--- a/arch/score/include/asm/uaccess.h
+++ b/arch/score/include/asm/uaccess.h
@@ -163,7 +163,7 @@
 		__get_user_asm(val, "lw", ptr);				\
 		 break;							\
 	case 8: 							\
-		if ((copy_from_user((void *)&val, ptr, 8)) == 0)	\
+		if (__copy_from_user((void *)&val, ptr, 8) == 0)	\
 			__gu_err = 0;					\
 		else							\
 			__gu_err = -EFAULT;				\
@@ -188,6 +188,8 @@
 									\
 	if (likely(access_ok(VERIFY_READ, __gu_ptr, size)))		\
 		__get_user_common((x), size, __gu_ptr);			\
+	else								\
+		(x) = 0;						\
 									\
 	__gu_err;							\
 })
@@ -201,6 +203,7 @@
 		"2:\n"							\
 		".section .fixup,\"ax\"\n"				\
 		"3:li	%0, %4\n"					\
+		"li	%1, 0\n"					\
 		"j	2b\n"						\
 		".previous\n"						\
 		".section __ex_table,\"a\"\n"				\
@@ -298,35 +301,34 @@
 static inline unsigned long
 copy_from_user(void *to, const void *from, unsigned long len)
 {
-	unsigned long over;
+	unsigned long res = len;
 
-	if (access_ok(VERIFY_READ, from, len))
-		return __copy_tofrom_user(to, from, len);
+	if (likely(access_ok(VERIFY_READ, from, len)))
+		res = __copy_tofrom_user(to, from, len);
 
-	if ((unsigned long)from < TASK_SIZE) {
-		over = (unsigned long)from + len - TASK_SIZE;
-		return __copy_tofrom_user(to, from, len - over) + over;
-	}
-	return len;
+	if (unlikely(res))
+		memset(to + (len - res), 0, res);
+
+	return res;
 }
 
 static inline unsigned long
 copy_to_user(void *to, const void *from, unsigned long len)
 {
-	unsigned long over;
+	if (likely(access_ok(VERIFY_WRITE, to, len)))
+		len = __copy_tofrom_user(to, from, len);
 
-	if (access_ok(VERIFY_WRITE, to, len))
-		return __copy_tofrom_user(to, from, len);
-
-	if ((unsigned long)to < TASK_SIZE) {
-		over = (unsigned long)to + len - TASK_SIZE;
-		return __copy_tofrom_user(to, from, len - over) + over;
-	}
 	return len;
 }
 
-#define __copy_from_user(to, from, len)	\
-		__copy_tofrom_user((to), (from), (len))
+static inline unsigned long
+__copy_from_user(void *to, const void *from, unsigned long len)
+{
+	unsigned long left = __copy_tofrom_user(to, from, len);
+	if (unlikely(left))
+		memset(to + (len - left), 0, left);
+	return left;
+}
 
 #define __copy_to_user(to, from, len)		\
 		__copy_tofrom_user((to), (from), (len))
@@ -340,17 +342,17 @@
 static inline unsigned long
 __copy_from_user_inatomic(void *to, const void *from, unsigned long len)
 {
-	return __copy_from_user(to, from, len);
+	return __copy_tofrom_user(to, from, len);
 }
 
-#define __copy_in_user(to, from, len)	__copy_from_user(to, from, len)
+#define __copy_in_user(to, from, len)	__copy_tofrom_user(to, from, len)
 
 static inline unsigned long
 copy_in_user(void *to, const void *from, unsigned long len)
 {
 	if (access_ok(VERIFY_READ, from, len) &&
 		      access_ok(VERFITY_WRITE, to, len))
-		return copy_from_user(to, from, len);
+		return __copy_tofrom_user(to, from, len);
 }
 
 /*
diff --git a/arch/sh/include/asm/uaccess.h b/arch/sh/include/asm/uaccess.h
index a49635c..92ade79 100644
--- a/arch/sh/include/asm/uaccess.h
+++ b/arch/sh/include/asm/uaccess.h
@@ -151,7 +151,10 @@
 	__kernel_size_t __copy_size = (__kernel_size_t) n;
 
 	if (__copy_size && __access_ok(__copy_from, __copy_size))
-		return __copy_user(to, from, __copy_size);
+		__copy_size = __copy_user(to, from, __copy_size);
+
+	if (unlikely(__copy_size))
+		memset(to + (n - __copy_size), 0, __copy_size);
 
 	return __copy_size;
 }
diff --git a/arch/sh/include/asm/uaccess_64.h b/arch/sh/include/asm/uaccess_64.h
index c01376c..ca5073d 100644
--- a/arch/sh/include/asm/uaccess_64.h
+++ b/arch/sh/include/asm/uaccess_64.h
@@ -24,6 +24,7 @@
 #define __get_user_size(x,ptr,size,retval)			\
 do {								\
 	retval = 0;						\
+	x = 0;							\
 	switch (size) {						\
 	case 1:							\
 		retval = __get_user_asm_b((void *)&x,		\
diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c
index 6777177..7df7d59 100644
--- a/arch/sh/mm/mmap.c
+++ b/arch/sh/mm/mmap.c
@@ -63,7 +63,7 @@
 
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
@@ -113,7 +113,7 @@
 
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 56442d2..eb94874 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -182,9 +182,9 @@
 	int "Maximum number of CPUs"
 	depends on SMP
 	range 2 32 if SPARC32
-	range 2 1024 if SPARC64
+	range 2 4096 if SPARC64
 	default 32 if SPARC32
-	default 64 if SPARC64
+	default 4096 if SPARC64
 
 source kernel/Kconfig.hz
 
diff --git a/arch/sparc/include/asm/head_64.h b/arch/sparc/include/asm/head_64.h
index 10e9dab..f0700cf 100644
--- a/arch/sparc/include/asm/head_64.h
+++ b/arch/sparc/include/asm/head_64.h
@@ -15,6 +15,10 @@
 
 #define	PTREGS_OFF	(STACK_BIAS + STACKFRAME_SZ)
 
+#define	RTRAP_PSTATE		(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
+#define	RTRAP_PSTATE_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
+#define RTRAP_PSTATE_AG_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
+
 #define __CHEETAH_ID	0x003e0014
 #define __JALAPENO_ID	0x003e0016
 #define __SERRANO_ID	0x003e0022
diff --git a/arch/sparc/include/asm/mmu_64.h b/arch/sparc/include/asm/mmu_64.h
index 70067ce..83b36a5 100644
--- a/arch/sparc/include/asm/mmu_64.h
+++ b/arch/sparc/include/asm/mmu_64.h
@@ -52,7 +52,7 @@
 #define CTX_NR_MASK		TAG_CONTEXT_BITS
 #define CTX_HW_MASK		(CTX_NR_MASK | CTX_PGSZ_MASK)
 
-#define CTX_FIRST_VERSION	((_AC(1,UL) << CTX_VERSION_SHIFT) + _AC(1,UL))
+#define CTX_FIRST_VERSION	BIT(CTX_VERSION_SHIFT)
 #define CTX_VALID(__ctx)	\
 	 (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK))
 #define CTX_HWBITS(__ctx)	((__ctx.sparc64_ctx_val) & CTX_HW_MASK)
@@ -92,7 +92,8 @@
 typedef struct {
 	spinlock_t		lock;
 	unsigned long		sparc64_ctx_val;
-	unsigned long		huge_pte_count;
+	unsigned long		hugetlb_pte_count;
+	unsigned long		thp_pte_count;
 	struct tsb_config	tsb_block[MM_NUM_TSBS];
 	struct hv_tsb_descr	tsb_descr[MM_NUM_TSBS];
 } mm_context_t;
diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h
index b84be67..349dd23 100644
--- a/arch/sparc/include/asm/mmu_context_64.h
+++ b/arch/sparc/include/asm/mmu_context_64.h
@@ -17,13 +17,8 @@
 extern unsigned long tlb_context_cache;
 extern unsigned long mmu_context_bmap[];
 
+DECLARE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm);
 void get_new_mmu_context(struct mm_struct *mm);
-#ifdef CONFIG_SMP
-void smp_new_mmu_context_version(void);
-#else
-#define smp_new_mmu_context_version() do { } while (0)
-#endif
-
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
 void destroy_context(struct mm_struct *mm);
 
@@ -74,8 +69,9 @@
 static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
 {
 	unsigned long ctx_valid, flags;
-	int cpu;
+	int cpu = smp_processor_id();
 
+	per_cpu(per_cpu_secondary_mm, cpu) = mm;
 	if (unlikely(mm == &init_mm))
 		return;
 
@@ -121,7 +117,6 @@
 	 * for the first time, we must flush that context out of the
 	 * local TLB.
 	 */
-	cpu = smp_processor_id();
 	if (!ctx_valid || !cpumask_test_cpu(cpu, mm_cpumask(mm))) {
 		cpumask_set_cpu(cpu, mm_cpumask(mm));
 		__flush_tlb_mm(CTX_HWBITS(mm->context),
@@ -131,26 +126,7 @@
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
-
-/* Activate a new MM instance for the current task. */
-static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
-{
-	unsigned long flags;
-	int cpu;
-
-	spin_lock_irqsave(&mm->context.lock, flags);
-	if (!CTX_VALID(mm->context))
-		get_new_mmu_context(mm);
-	cpu = smp_processor_id();
-	if (!cpumask_test_cpu(cpu, mm_cpumask(mm)))
-		cpumask_set_cpu(cpu, mm_cpumask(mm));
-
-	load_secondary_context(mm);
-	__flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT);
-	tsb_context_switch(mm);
-	spin_unlock_irqrestore(&mm->context.lock, flags);
-}
-
+#define activate_mm(active_mm, mm) switch_mm(active_mm, mm, NULL)
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC64_MMU_CONTEXT_H) */
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
index 91b963a..29c3b40 100644
--- a/arch/sparc/include/asm/pgtable_32.h
+++ b/arch/sparc/include/asm/pgtable_32.h
@@ -91,9 +91,9 @@
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-extern unsigned long empty_zero_page;
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
-#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
 /*
  * In general all page table modifications should use the V8 atomic
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 131d36f..9d81579 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -375,7 +375,7 @@
 #define pgprot_noncached pgprot_noncached
 
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-static inline pte_t pte_mkhuge(pte_t pte)
+static inline unsigned long __pte_huge_mask(void)
 {
 	unsigned long mask;
 
@@ -390,8 +390,19 @@
 	: "=r" (mask)
 	: "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V));
 
-	return __pte(pte_val(pte) | mask);
+	return mask;
 }
+
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+	return __pte(pte_val(pte) | __pte_huge_mask());
+}
+
+static inline bool is_hugetlb_pte(pte_t pte)
+{
+	return !!(pte_val(pte) & __pte_huge_mask());
+}
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 static inline pmd_t pmd_mkhuge(pmd_t pmd)
 {
@@ -403,6 +414,11 @@
 	return __pmd(pte_val(pte));
 }
 #endif
+#else
+static inline bool is_hugetlb_pte(pte_t pte)
+{
+	return false;
+}
 #endif
 
 static inline pte_t pte_mkdirty(pte_t pte)
@@ -652,6 +668,14 @@
 	return pte_pfn(pte);
 }
 
+#define __HAVE_ARCH_PMD_WRITE
+static inline unsigned long pmd_write(pmd_t pmd)
+{
+	pte_t pte = __pte(pmd_val(pmd));
+
+	return pte_write(pte);
+}
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 static inline unsigned long pmd_dirty(pmd_t pmd)
 {
@@ -667,13 +691,6 @@
 	return pte_young(pte);
 }
 
-static inline unsigned long pmd_write(pmd_t pmd)
-{
-	pte_t pte = __pte(pmd_val(pmd));
-
-	return pte_write(pte);
-}
-
 static inline unsigned long pmd_trans_huge(pmd_t pmd)
 {
 	pte_t pte = __pte(pmd_val(pmd));
@@ -865,6 +882,19 @@
 void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
 		   pte_t *ptep, pte_t orig, int fullmm);
 
+static void maybe_tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
+				pte_t *ptep, pte_t orig, int fullmm)
+{
+	/* It is more efficient to let flush_tlb_kernel_range()
+	 * handle init_mm tlb flushes.
+	 *
+	 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
+	 *             and SUN4V pte layout, so this inline test is fine.
+	 */
+	if (likely(mm != &init_mm) && pte_accessible(mm, orig))
+		tlb_batch_add(mm, vaddr, ptep, orig, fullmm);
+}
+
 #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
 static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
 					    unsigned long addr,
@@ -881,15 +911,7 @@
 	pte_t orig = *ptep;
 
 	*ptep = pte;
-
-	/* It is more efficient to let flush_tlb_kernel_range()
-	 * handle init_mm tlb flushes.
-	 *
-	 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
-	 *             and SUN4V pte layout, so this inline test is fine.
-	 */
-	if (likely(mm != &init_mm) && pte_accessible(mm, orig))
-		tlb_batch_add(mm, addr, ptep, orig, fullmm);
+	maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm);
 }
 
 #define set_pte_at(mm,addr,ptep,pte)	\
diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h
index 2669370..522b43d 100644
--- a/arch/sparc/include/asm/pil.h
+++ b/arch/sparc/include/asm/pil.h
@@ -20,7 +20,6 @@
 #define PIL_SMP_CALL_FUNC	1
 #define PIL_SMP_RECEIVE_SIGNAL	2
 #define PIL_SMP_CAPTURE		3
-#define PIL_SMP_CTX_NEW_VERSION	4
 #define PIL_DEVICE_IRQ		5
 #define PIL_SMP_CALL_FUNC_SNGL	6
 #define PIL_DEFERRED_PCR_WORK	7
diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h
index 29d64b1..be0cc1b 100644
--- a/arch/sparc/include/asm/setup.h
+++ b/arch/sparc/include/asm/setup.h
@@ -16,7 +16,7 @@
  */
 extern unsigned char boot_cpu_id;
 
-extern unsigned long empty_zero_page;
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 extern int serial_console;
 static inline int con_is_present(void)
diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h
index dea1cfa..a8e192e 100644
--- a/arch/sparc/include/asm/tlbflush_64.h
+++ b/arch/sparc/include/asm/tlbflush_64.h
@@ -8,6 +8,7 @@
 #define TLB_BATCH_NR	192
 
 struct tlb_batch {
+	bool huge;
 	struct mm_struct *mm;
 	unsigned long tlb_nr;
 	unsigned long active;
@@ -16,7 +17,7 @@
 
 void flush_tsb_kernel_range(unsigned long start, unsigned long end);
 void flush_tsb_user(struct tlb_batch *tb);
-void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr);
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge);
 
 /* TLB flush operations. */
 
diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h
index 71b5a67..781b9f1 100644
--- a/arch/sparc/include/asm/ttable.h
+++ b/arch/sparc/include/asm/ttable.h
@@ -589,8 +589,8 @@
 	 restored;					\
 	nop; nop; nop; nop; nop; nop;			\
 	nop; nop; nop; nop; nop;			\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup_dax;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup_mna;		\
 	ba,a,pt	%xcc, user_rtt_fill_fixup;
 
 
@@ -652,8 +652,8 @@
 	 restored;					\
 	nop; nop; nop; nop; nop;			\
 	nop; nop; nop;					\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup_dax;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup_mna;		\
 	ba,a,pt	%xcc, user_rtt_fill_fixup;
 
 
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h
index 64ee103..dfb542c 100644
--- a/arch/sparc/include/asm/uaccess_32.h
+++ b/arch/sparc/include/asm/uaccess_32.h
@@ -328,8 +328,10 @@
 {
 	if (n && __access_ok((unsigned long) from, n))
 		return __copy_user((__force void __user *) to, from, n);
-	else
+	else {
+		memset(to, 0, n);
 		return n;
+	}
 }
 
 static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h
index ea6e9a2..f428512 100644
--- a/arch/sparc/include/asm/uaccess_64.h
+++ b/arch/sparc/include/asm/uaccess_64.h
@@ -98,7 +98,6 @@
         unsigned int insn, fixup;
 };
 
-void __ret_efault(void);
 void __retl_efault(void);
 
 /* Uh, these should become the main single-value transfer routines..
@@ -179,20 +178,6 @@
 	 __gu_ret;							     \
 })
 
-#define __get_user_nocheck_ret(data, addr, size, type, retval) ({	\
-	register unsigned long __gu_val __asm__ ("l1");			\
-	switch (size) {							\
-	case 1: __get_user_asm_ret(__gu_val, ub, addr, retval); break;	\
-	case 2: __get_user_asm_ret(__gu_val, uh, addr, retval); break;	\
-	case 4: __get_user_asm_ret(__gu_val, uw, addr, retval); break;	\
-	case 8: __get_user_asm_ret(__gu_val, x, addr, retval); break;	\
-	default:							\
-		if (__get_user_bad())					\
-			return retval;					\
-	}								\
-	data = (__force type) __gu_val;					\
-})
-
 #define __get_user_asm(x, size, addr, ret)				\
 __asm__ __volatile__(							\
 		"/* Get user asm, inline. */\n"				\
@@ -214,80 +199,35 @@
 	       : "=r" (ret), "=r" (x) : "r" (__m(addr)),		\
 		 "i" (-EFAULT))
 
-#define __get_user_asm_ret(x, size, addr, retval)			\
-if (__builtin_constant_p(retval) && retval == -EFAULT)			\
-	__asm__ __volatile__(						\
-		"/* Get user asm ret, inline. */\n"			\
-	"1:\t"	"ld"#size "a [%1] %%asi, %0\n\n\t"			\
-		".section __ex_table,\"a\"\n\t"				\
-		".align	4\n\t"						\
-		".word	1b,__ret_efault\n\n\t"				\
-		".previous\n\t"						\
-	       : "=r" (x) : "r" (__m(addr)));				\
-else									\
-	__asm__ __volatile__(						\
-		"/* Get user asm ret, inline. */\n"			\
-	"1:\t"	"ld"#size "a [%1] %%asi, %0\n\n\t"			\
-		".section .fixup,#alloc,#execinstr\n\t"			\
-		".align	4\n"						\
-	"3:\n\t"							\
-		"ret\n\t"						\
-		" restore %%g0, %2, %%o0\n\n\t"				\
-		".previous\n\t"						\
-		".section __ex_table,\"a\"\n\t"				\
-		".align	4\n\t"						\
-		".word	1b, 3b\n\n\t"					\
-		".previous\n\t"						\
-	       : "=r" (x) : "r" (__m(addr)), "i" (retval))
-
 int __get_user_bad(void);
 
 unsigned long __must_check ___copy_from_user(void *to,
 					     const void __user *from,
 					     unsigned long size);
-unsigned long copy_from_user_fixup(void *to, const void __user *from,
-				   unsigned long size);
 static inline unsigned long __must_check
 copy_from_user(void *to, const void __user *from, unsigned long size)
 {
-	unsigned long ret = ___copy_from_user(to, from, size);
-
-	if (unlikely(ret))
-		ret = copy_from_user_fixup(to, from, size);
-
-	return ret;
+	return ___copy_from_user(to, from, size);
 }
 #define __copy_from_user copy_from_user
 
 unsigned long __must_check ___copy_to_user(void __user *to,
 					   const void *from,
 					   unsigned long size);
-unsigned long copy_to_user_fixup(void __user *to, const void *from,
-				 unsigned long size);
 static inline unsigned long __must_check
 copy_to_user(void __user *to, const void *from, unsigned long size)
 {
-	unsigned long ret = ___copy_to_user(to, from, size);
-
-	if (unlikely(ret))
-		ret = copy_to_user_fixup(to, from, size);
-	return ret;
+	return ___copy_to_user(to, from, size);
 }
 #define __copy_to_user copy_to_user
 
 unsigned long __must_check ___copy_in_user(void __user *to,
 					   const void __user *from,
 					   unsigned long size);
-unsigned long copy_in_user_fixup(void __user *to, void __user *from,
-				 unsigned long size);
 static inline unsigned long __must_check
 copy_in_user(void __user *to, void __user *from, unsigned long size)
 {
-	unsigned long ret = ___copy_in_user(to, from, size);
-
-	if (unlikely(ret))
-		ret = copy_in_user_fixup(to, from, size);
-	return ret;
+	return ___copy_in_user(to, from, size);
 }
 #define __copy_in_user copy_in_user
 
diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h
index 8174f6c..9dca7a8 100644
--- a/arch/sparc/include/asm/vio.h
+++ b/arch/sparc/include/asm/vio.h
@@ -327,6 +327,7 @@
 	int			compat_len;
 
 	u64			dev_no;
+	u64			id;
 
 	unsigned long		channel_id;
 
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 7cf9c6e..fdb1332 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -21,6 +21,7 @@
 CFLAGS_REMOVE_pcr.o := -pg
 endif
 
+obj-$(CONFIG_SPARC64)   += urtt_fill.o
 obj-$(CONFIG_SPARC32)   += entry.o wof.o wuf.o
 obj-$(CONFIG_SPARC32)   += etrap_32.o
 obj-$(CONFIG_SPARC32)   += rtrap_32.o
diff --git a/arch/sparc/kernel/cherrs.S b/arch/sparc/kernel/cherrs.S
index 4ee1ad4..655628de 100644
--- a/arch/sparc/kernel/cherrs.S
+++ b/arch/sparc/kernel/cherrs.S
@@ -214,8 +214,7 @@
 	subcc		%g1, %g2, %g1		! Next cacheline
 	bge,pt		%icc, 1b
 	 nop
-	ba,pt		%xcc, dcpe_icpe_tl1_common
-	 nop
+	ba,a,pt		%xcc, dcpe_icpe_tl1_common
 
 do_dcpe_tl1_fatal:
 	sethi		%hi(1f), %g7
@@ -224,8 +223,7 @@
 	mov		0x2, %o0
 	call		cheetah_plus_parity_error
 	 add		%sp, PTREGS_OFF, %o1
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		do_dcpe_tl1,.-do_dcpe_tl1
 
 	.globl		do_icpe_tl1
@@ -259,8 +257,7 @@
 	subcc		%g1, %g2, %g1
 	bge,pt		%icc, 1b
 	 nop
-	ba,pt		%xcc, dcpe_icpe_tl1_common
-	 nop
+	ba,a,pt		%xcc, dcpe_icpe_tl1_common
 
 do_icpe_tl1_fatal:
 	sethi		%hi(1f), %g7
@@ -269,8 +266,7 @@
 	mov		0x3, %o0
 	call		cheetah_plus_parity_error
 	 add		%sp, PTREGS_OFF, %o1
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		do_icpe_tl1,.-do_icpe_tl1
 	
 	.type		dcpe_icpe_tl1_common,#function
@@ -456,7 +452,7 @@
 	 cmp		%g2, 0x63
 	be		c_cee
 	 nop
-	ba,pt		%xcc, c_deferred
+	ba,a,pt		%xcc, c_deferred
 	.size		__cheetah_log_error,.-__cheetah_log_error
 
 	/* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
diff --git a/arch/sparc/kernel/dtlb_prot.S b/arch/sparc/kernel/dtlb_prot.S
index d668ca14..4087a62 100644
--- a/arch/sparc/kernel/dtlb_prot.S
+++ b/arch/sparc/kernel/dtlb_prot.S
@@ -25,13 +25,13 @@
 
 /* PROT ** ICACHE line 2: More real fault processing */
 	ldxa		[%g4] ASI_DMMU, %g5		! Put tagaccess in %g5
+	srlx		%g5, PAGE_SHIFT, %g5
+	sllx		%g5, PAGE_SHIFT, %g5		! Clear context ID bits
 	bgu,pn		%xcc, winfix_trampoline		! Yes, perform winfixup
 	 mov		FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4
 	ba,pt		%xcc, sparc64_realfault_common	! Nope, normal fault
 	 nop
 	nop
-	nop
-	nop
 
 /* PROT ** ICACHE line 3: Unused...	*/
 	nop
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 33c02b1..a83707c 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -948,7 +948,24 @@
 	cmp	%o0, 0
 	bne	3f
 	 mov	-ENOSYS, %o0
+
+	/* Syscall tracing can modify the registers.  */
+	ld	[%sp + STACKFRAME_SZ + PT_G1], %g1
+	sethi	%hi(sys_call_table), %l7
+	ld	[%sp + STACKFRAME_SZ + PT_I0], %i0
+	or	%l7, %lo(sys_call_table), %l7
+	ld	[%sp + STACKFRAME_SZ + PT_I1], %i1
+	ld	[%sp + STACKFRAME_SZ + PT_I2], %i2
+	ld	[%sp + STACKFRAME_SZ + PT_I3], %i3
+	ld	[%sp + STACKFRAME_SZ + PT_I4], %i4
+	ld	[%sp + STACKFRAME_SZ + PT_I5], %i5
+	cmp	%g1, NR_syscalls
+	bgeu	3f
+	 mov	-ENOSYS, %o0
+
+	sll	%g1, 2, %l4
 	mov	%i0, %o0
+	ld	[%l7 + %l4], %l7
 	mov	%i1, %o1
 	mov	%i2, %o2
 	mov	%i3, %o3
diff --git a/arch/sparc/kernel/fpu_traps.S b/arch/sparc/kernel/fpu_traps.S
index a686482..336d275 100644
--- a/arch/sparc/kernel/fpu_traps.S
+++ b/arch/sparc/kernel/fpu_traps.S
@@ -100,8 +100,8 @@
 	fmuld		%f0, %f2, %f26
 	faddd		%f0, %f2, %f28
 	fmuld		%f0, %f2, %f30
-	b,pt		%xcc, fpdis_exit
-	 nop
+	ba,a,pt		%xcc, fpdis_exit
+
 2:	andcc		%g5, FPRS_DU, %g0
 	bne,pt		%icc, 3f
 	 fzero		%f32
@@ -144,8 +144,8 @@
 	fmuld		%f32, %f34, %f58
 	faddd		%f32, %f34, %f60
 	fmuld		%f32, %f34, %f62
-	ba,pt		%xcc, fpdis_exit
-	 nop
+	ba,a,pt		%xcc, fpdis_exit
+
 3:	mov		SECONDARY_CONTEXT, %g3
 	add		%g6, TI_FPREGS, %g1
 
@@ -197,8 +197,7 @@
 fp_other_bounce:
 	call		do_fpother
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		fp_other_bounce,.-fp_other_bounce
 
 	.align		32
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index f2d30ca..7eeeb1d 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -461,9 +461,8 @@
 	subcc	%g3, 1, %g3
 	bne,pt	%xcc, 41b
 	add	%g1, 1, %g1
-	mov	SUN4V_CHIP_SPARC64X, %g4
 	ba,pt	%xcc, 5f
-	nop
+	 mov	SUN4V_CHIP_SPARC64X, %g4
 
 49:
 	mov	SUN4V_CHIP_UNKNOWN, %g4
@@ -548,8 +547,7 @@
 	stxa		%g0, [%g7] ASI_DMMU
 	membar	#Sync
 
-	ba,pt		%xcc, sun4u_continue
-	 nop
+	ba,a,pt		%xcc, sun4u_continue
 
 sun4v_init:
 	/* Set ctx 0 */
@@ -560,14 +558,12 @@
 	mov		SECONDARY_CONTEXT, %g7
 	stxa		%g0, [%g7] ASI_MMU
 	membar		#Sync
-	ba,pt		%xcc, niagara_tlb_fixup
-	 nop
+	ba,a,pt		%xcc, niagara_tlb_fixup
 
 sun4u_continue:
 	BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup)
 
-	ba,pt	%xcc, spitfire_tlb_fixup
-	 nop
+	ba,a,pt	%xcc, spitfire_tlb_fixup
 
 niagara_tlb_fixup:
 	mov	3, %g2		/* Set TLB type to hypervisor. */
@@ -639,8 +635,7 @@
 	call	hypervisor_patch_cachetlbops
 	 nop
 
-	ba,pt	%xcc, tlb_fixup_done
-	 nop
+	ba,a,pt	%xcc, tlb_fixup_done
 
 cheetah_tlb_fixup:
 	mov	2, %g2		/* Set TLB type to cheetah+. */
@@ -659,8 +654,7 @@
 	call	cheetah_patch_cachetlbops
 	 nop
 
-	ba,pt	%xcc, tlb_fixup_done
-	 nop
+	ba,a,pt	%xcc, tlb_fixup_done
 
 spitfire_tlb_fixup:
 	/* Set TLB type to spitfire. */
@@ -782,8 +776,7 @@
 	call	%o1
 	 add	%sp, (2047 + 128), %o0
 
-	ba,pt	%xcc, 2f
-	 nop
+	ba,a,pt	%xcc, 2f
 
 1:	sethi	%hi(sparc64_ttable_tl0), %o0
 	set	prom_set_trap_table_name, %g2
@@ -822,8 +815,7 @@
 
 	BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
 
-	ba,pt	%xcc, 2f
-	 nop
+	ba,a,pt	%xcc, 2f
 
 	/* Disable STICK_INT interrupts. */
 1:
@@ -930,47 +922,11 @@
 tlb_type:	.word	0	/* Must NOT end up in BSS */
 	.section	".fixup",#alloc,#execinstr
 
-	.globl	__ret_efault, __retl_efault, __ret_one, __retl_one
-ENTRY(__ret_efault)
-	ret
-	 restore %g0, -EFAULT, %o0
-ENDPROC(__ret_efault)
-
 ENTRY(__retl_efault)
 	retl
 	 mov	-EFAULT, %o0
 ENDPROC(__retl_efault)
 
-ENTRY(__retl_one)
-	retl
-	 mov	1, %o0
-ENDPROC(__retl_one)
-
-ENTRY(__retl_one_fp)
-	VISExitHalf
-	retl
-	 mov	1, %o0
-ENDPROC(__retl_one_fp)
-
-ENTRY(__ret_one_asi)
-	wr	%g0, ASI_AIUS, %asi
-	ret
-	 restore %g0, 1, %o0
-ENDPROC(__ret_one_asi)
-
-ENTRY(__retl_one_asi)
-	wr	%g0, ASI_AIUS, %asi
-	retl
-	 mov	1, %o0
-ENDPROC(__retl_one_asi)
-
-ENTRY(__retl_one_asi_fp)
-	wr	%g0, ASI_AIUS, %asi
-	VISExitHalf
-	retl
-	 mov	1, %o0
-ENDPROC(__retl_one_asi_fp)
-
 ENTRY(__retl_o1)
 	retl
 	 mov	%o1, %o0
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index e22416c..bfbde8c 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -1034,17 +1034,26 @@
 {
 #ifdef CONFIG_SMP
 	unsigned long page;
+	void *mondo, *p;
 
-	BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64));
+	BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > PAGE_SIZE);
+
+	/* Make sure mondo block is 64byte aligned */
+	p = kzalloc(127, GFP_KERNEL);
+	if (!p) {
+		prom_printf("SUN4V: Error, cannot allocate mondo block.\n");
+		prom_halt();
+	}
+	mondo = (void *)(((unsigned long)p + 63) & ~0x3f);
+	tb->cpu_mondo_block_pa = __pa(mondo);
 
 	page = get_zeroed_page(GFP_KERNEL);
 	if (!page) {
-		prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n");
+		prom_printf("SUN4V: Error, cannot allocate cpu list page.\n");
 		prom_halt();
 	}
 
-	tb->cpu_mondo_block_pa = __pa(page);
-	tb->cpu_list_pa = __pa(page + 64);
+	tb->cpu_list_pa = __pa(page);
 #endif
 }
 
diff --git a/arch/sparc/kernel/jump_label.c b/arch/sparc/kernel/jump_label.c
index 59bbeff..07933b9 100644
--- a/arch/sparc/kernel/jump_label.c
+++ b/arch/sparc/kernel/jump_label.c
@@ -13,19 +13,30 @@
 void arch_jump_label_transform(struct jump_entry *entry,
 			       enum jump_label_type type)
 {
-	u32 val;
 	u32 *insn = (u32 *) (unsigned long) entry->code;
+	u32 val;
 
 	if (type == JUMP_LABEL_JMP) {
 		s32 off = (s32)entry->target - (s32)entry->code;
+		bool use_v9_branch = false;
+
+		BUG_ON(off & 3);
 
 #ifdef CONFIG_SPARC64
-		/* ba,pt %xcc, . + (off << 2) */
-		val = 0x10680000 | ((u32) off >> 2);
-#else
-		/* ba . + (off << 2) */
-		val = 0x10800000 | ((u32) off >> 2);
+		if (off <= 0xfffff && off >= -0x100000)
+			use_v9_branch = true;
 #endif
+		if (use_v9_branch) {
+			/* WDISP19 - target is . + immed << 2 */
+			/* ba,pt %xcc, . + off */
+			val = 0x10680000 | (((u32) off >> 2) & 0x7ffff);
+		} else {
+			/* WDISP22 - target is . + immed << 2 */
+			BUG_ON(off > 0x7fffff);
+			BUG_ON(off < -0x800000);
+			/* ba . + off */
+			val = 0x10800000 | (((u32) off >> 2) & 0x3fffff);
+		}
 	} else {
 		val = 0x01000000;
 	}
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index e7f652b..44f32dd4 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -37,7 +37,6 @@
 /* smp_64.c */
 void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs);
 void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs);
-void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs);
 void __irq_entry smp_penguin_jailcell(int irq, struct pt_regs *regs);
 void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs);
 
diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S
index ef0d8e9..f22bec0 100644
--- a/arch/sparc/kernel/ktlb.S
+++ b/arch/sparc/kernel/ktlb.S
@@ -20,6 +20,10 @@
 	mov		TLB_TAG_ACCESS, %g4
 	ldxa		[%g4] ASI_IMMU, %g4
 
+	/* The kernel executes in context zero, therefore we do not
+	 * need to clear the context ID bits out of %g4 here.
+	 */
+
 	/* sun4v_itlb_miss branches here with the missing virtual
 	 * address already loaded into %g4
 	 */
@@ -128,6 +132,10 @@
 	mov		TLB_TAG_ACCESS, %g4
 	ldxa		[%g4] ASI_DMMU, %g4
 
+	/* The kernel executes in context zero, therefore we do not
+	 * need to clear the context ID bits out of %g4 here.
+	 */
+
 	/* sun4v_dtlb_miss branches here with the missing virtual
 	 * address already loaded into %g4
 	 */
@@ -251,6 +259,10 @@
 	nop
 	.previous
 
+	/* The kernel executes in context zero, therefore we do not
+	 * need to clear the context ID bits out of %g5 here.
+	 */
+
 	be,pt	%xcc, sparc64_realfault_common
 	 mov	FAULT_CODE_DTLB, %g4
 	ba,pt	%xcc, winfix_trampoline
diff --git a/arch/sparc/kernel/misctrap.S b/arch/sparc/kernel/misctrap.S
index 753b4f0..34b4933 100644
--- a/arch/sparc/kernel/misctrap.S
+++ b/arch/sparc/kernel/misctrap.S
@@ -18,8 +18,7 @@
 109:	or		%g7, %lo(109b), %g7
 	call		do_privact
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		__do_privact,.-__do_privact
 
 	.type		do_mna,#function
@@ -46,8 +45,7 @@
 	mov		%l5, %o2
 	call		mem_address_unaligned
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		do_mna,.-do_mna
 
 	.type		do_lddfmna,#function
@@ -65,8 +63,7 @@
 	mov		%l5, %o2
 	call		handle_lddfmna
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		do_lddfmna,.-do_lddfmna
 
 	.type		do_stdfmna,#function
@@ -84,8 +81,7 @@
 	mov		%l5, %o2
 	call		handle_stdfmna
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		do_stdfmna,.-do_stdfmna
 
 	.type		breakpoint_trap,#function
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index badf095..9f9614d 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -994,6 +994,23 @@
 	/* No special bus mastering setup handling */
 }
 
+#ifdef CONFIG_PCI_IOV
+int pcibios_add_device(struct pci_dev *dev)
+{
+	struct pci_dev *pdev;
+
+	/* Add sriov arch specific initialization here.
+	 * Copy dev_archdata from PF to VF
+	 */
+	if (dev->is_virtfn) {
+		pdev = dev->physfn;
+		memcpy(&dev->dev.archdata, &pdev->dev.archdata,
+		       sizeof(struct dev_archdata));
+	}
+	return 0;
+}
+#endif /* CONFIG_PCI_IOV */
+
 static int __init pcibios_init(void)
 {
 	pci_dfl_cache_line_size = 64 >> 2;
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 9ddc492..c156617 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -311,7 +311,7 @@
 	}
 
 	if (!ret) {
-		unsigned long y;
+		unsigned long y = regs->y;
 
 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 					 &y,
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index d08bdaf..216948c 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -14,10 +14,6 @@
 #include <asm/visasm.h>
 #include <asm/processor.h>
 
-#define		RTRAP_PSTATE		(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
-#define		RTRAP_PSTATE_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
-#define		RTRAP_PSTATE_AG_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
-
 #ifdef CONFIG_CONTEXT_TRACKING
 # define SCHEDULE_USER schedule_user
 #else
@@ -242,52 +238,17 @@
 		 wrpr			%g1, %cwp
 		ba,a,pt			%xcc, user_rtt_fill_64bit
 
+user_rtt_fill_fixup_dax:
+		ba,pt	%xcc, user_rtt_fill_fixup_common
+		 mov	1, %g3
+
+user_rtt_fill_fixup_mna:
+		ba,pt	%xcc, user_rtt_fill_fixup_common
+		 mov	2, %g3
+
 user_rtt_fill_fixup:
-		rdpr	%cwp, %g1
-		add	%g1, 1, %g1
-		wrpr	%g1, 0x0, %cwp
-
-		rdpr	%wstate, %g2
-		sll	%g2, 3, %g2
-		wrpr	%g2, 0x0, %wstate
-
-		/* We know %canrestore and %otherwin are both zero.  */
-
-		sethi	%hi(sparc64_kern_pri_context), %g2
-		ldx	[%g2 + %lo(sparc64_kern_pri_context)], %g2
-		mov	PRIMARY_CONTEXT, %g1
-
-661:		stxa	%g2, [%g1] ASI_DMMU
-		.section .sun4v_1insn_patch, "ax"
-		.word	661b
-		stxa	%g2, [%g1] ASI_MMU
-		.previous
-
-		sethi	%hi(KERNBASE), %g1
-		flush	%g1
-
-		or	%g4, FAULT_CODE_WINFIXUP, %g4
-		stb	%g4, [%g6 + TI_FAULT_CODE]
-		stx	%g5, [%g6 + TI_FAULT_ADDR]
-
-		mov	%g6, %l1
-		wrpr	%g0, 0x0, %tl
-
-661:		nop
-		.section		.sun4v_1insn_patch, "ax"
-		.word			661b
-		SET_GL(0)
-		.previous
-
-		wrpr	%g0, RTRAP_PSTATE, %pstate
-
-		mov	%l1, %g6
-		ldx	[%g6 + TI_TASK], %g4
-		LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
-		call	do_sparc64_fault
-		 add	%sp, PTREGS_OFF, %o0
-		ba,pt	%xcc, rtrap
-		 nop
+		ba,pt	%xcc, user_rtt_fill_fixup_common
+		 clr	%g3
 
 user_rtt_pre_restore:
 		add			%g1, 1, %g1
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index 4eed773..77655f0 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -138,12 +138,24 @@
 	return 0;
 }
 
+/* Checks if the fp is valid.  We always build signal frames which are
+ * 16-byte aligned, therefore we can always enforce that the restore
+ * frame has that property as well.
+ */
+static bool invalid_frame_pointer(void __user *fp, int fplen)
+{
+	if ((((unsigned long) fp) & 15) ||
+	    ((unsigned long)fp) > 0x100000000ULL - fplen)
+		return true;
+	return false;
+}
+
 void do_sigreturn32(struct pt_regs *regs)
 {
 	struct signal_frame32 __user *sf;
 	compat_uptr_t fpu_save;
 	compat_uptr_t rwin_save;
-	unsigned int psr;
+	unsigned int psr, ufp;
 	unsigned pc, npc;
 	sigset_t set;
 	compat_sigset_t seta;
@@ -158,11 +170,16 @@
 	sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
 
 	/* 1. Make sure we are not getting garbage from the user */
-	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
-	    (((unsigned long) sf) & 3))
+	if (invalid_frame_pointer(sf, sizeof(*sf)))
 		goto segv;
 
-	if (get_user(pc, &sf->info.si_regs.pc) ||
+	if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
+		goto segv;
+
+	if (ufp & 0x7)
+		goto segv;
+
+	if (__get_user(pc, &sf->info.si_regs.pc) ||
 	    __get_user(npc, &sf->info.si_regs.npc))
 		goto segv;
 
@@ -227,7 +244,7 @@
 asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
 {
 	struct rt_signal_frame32 __user *sf;
-	unsigned int psr, pc, npc;
+	unsigned int psr, pc, npc, ufp;
 	compat_uptr_t fpu_save;
 	compat_uptr_t rwin_save;
 	sigset_t set;
@@ -242,11 +259,16 @@
 	sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];
 
 	/* 1. Make sure we are not getting garbage from the user */
-	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
-	    (((unsigned long) sf) & 3))
+	if (invalid_frame_pointer(sf, sizeof(*sf)))
 		goto segv;
 
-	if (get_user(pc, &sf->regs.pc) || 
+	if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+		goto segv;
+
+	if (ufp & 0x7)
+		goto segv;
+
+	if (__get_user(pc, &sf->regs.pc) ||
 	    __get_user(npc, &sf->regs.npc))
 		goto segv;
 
@@ -307,14 +329,6 @@
 	force_sig(SIGSEGV, current);
 }
 
-/* Checks if the fp is valid */
-static int invalid_frame_pointer(void __user *fp, int fplen)
-{
-	if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen)
-		return 1;
-	return 0;
-}
-
 static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
 	unsigned long sp;
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 52aa5e4..9c0c8fd 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -60,10 +60,22 @@
 #define SF_ALIGNEDSZ  (((sizeof(struct signal_frame) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 
+/* Checks if the fp is valid.  We always build signal frames which are
+ * 16-byte aligned, therefore we can always enforce that the restore
+ * frame has that property as well.
+ */
+static inline bool invalid_frame_pointer(void __user *fp, int fplen)
+{
+	if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen))
+		return true;
+
+	return false;
+}
+
 asmlinkage void do_sigreturn(struct pt_regs *regs)
 {
+	unsigned long up_psr, pc, npc, ufp;
 	struct signal_frame __user *sf;
-	unsigned long up_psr, pc, npc;
 	sigset_t set;
 	__siginfo_fpu_t __user *fpu_save;
 	__siginfo_rwin_t __user *rwin_save;
@@ -77,10 +89,13 @@
 	sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
 
 	/* 1. Make sure we are not getting garbage from the user */
-	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
+	if (invalid_frame_pointer(sf, sizeof(*sf)))
 		goto segv_and_exit;
 
-	if (((unsigned long) sf) & 3)
+	if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
+		goto segv_and_exit;
+
+	if (ufp & 0x7)
 		goto segv_and_exit;
 
 	err = __get_user(pc,  &sf->info.si_regs.pc);
@@ -127,7 +142,7 @@
 asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_signal_frame __user *sf;
-	unsigned int psr, pc, npc;
+	unsigned int psr, pc, npc, ufp;
 	__siginfo_fpu_t __user *fpu_save;
 	__siginfo_rwin_t __user *rwin_save;
 	sigset_t set;
@@ -135,8 +150,13 @@
 
 	synchronize_user_stack();
 	sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
-	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
-	    (((unsigned long) sf) & 0x03))
+	if (invalid_frame_pointer(sf, sizeof(*sf)))
+		goto segv;
+
+	if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+		goto segv;
+
+	if (ufp & 0x7)
 		goto segv;
 
 	err = __get_user(pc, &sf->regs.pc);
@@ -178,15 +198,6 @@
 	force_sig(SIGSEGV, current);
 }
 
-/* Checks if the fp is valid */
-static inline int invalid_frame_pointer(void __user *fp, int fplen)
-{
-	if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
-		return 1;
-
-	return 0;
-}
-
 static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
 	unsigned long sp = regs->u_regs[UREG_FP];
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index d88beff4..5ee930c 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -52,7 +52,7 @@
 	unsigned char fenab;
 	int err;
 
-	flush_user_windows();
+	synchronize_user_stack();
 	if (get_thread_wsaved()					||
 	    (((unsigned long)ucp) & (sizeof(unsigned long)-1))	||
 	    (!__access_ok(ucp, sizeof(*ucp))))
@@ -234,6 +234,17 @@
 	goto out;
 }
 
+/* Checks if the fp is valid.  We always build rt signal frames which
+ * are 16-byte aligned, therefore we can always enforce that the
+ * restore frame has that property as well.
+ */
+static bool invalid_frame_pointer(void __user *fp)
+{
+	if (((unsigned long) fp) & 15)
+		return true;
+	return false;
+}
+
 struct rt_signal_frame {
 	struct sparc_stackf	ss;
 	siginfo_t		info;
@@ -246,8 +257,8 @@
 
 void do_rt_sigreturn(struct pt_regs *regs)
 {
+	unsigned long tpc, tnpc, tstate, ufp;
 	struct rt_signal_frame __user *sf;
-	unsigned long tpc, tnpc, tstate;
 	__siginfo_fpu_t __user *fpu_save;
 	__siginfo_rwin_t __user *rwin_save;
 	sigset_t set;
@@ -261,10 +272,16 @@
 		(regs->u_regs [UREG_FP] + STACK_BIAS);
 
 	/* 1. Make sure we are not getting garbage from the user */
-	if (((unsigned long) sf) & 3)
+	if (invalid_frame_pointer(sf))
 		goto segv;
 
-	err = get_user(tpc, &sf->regs.tpc);
+	if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+		goto segv;
+
+	if ((ufp + STACK_BIAS) & 0x7)
+		goto segv;
+
+	err = __get_user(tpc, &sf->regs.tpc);
 	err |= __get_user(tnpc, &sf->regs.tnpc);
 	if (test_thread_flag(TIF_32BIT)) {
 		tpc &= 0xffffffff;
@@ -308,14 +325,6 @@
 	force_sig(SIGSEGV, current);
 }
 
-/* Checks if the fp is valid */
-static int invalid_frame_pointer(void __user *fp)
-{
-	if (((unsigned long) fp) & 15)
-		return 1;
-	return 0;
-}
-
 static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
 	unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
diff --git a/arch/sparc/kernel/sigutil_32.c b/arch/sparc/kernel/sigutil_32.c
index 0f6eebe..e5fe8ce 100644
--- a/arch/sparc/kernel/sigutil_32.c
+++ b/arch/sparc/kernel/sigutil_32.c
@@ -48,6 +48,10 @@
 int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
 {
 	int err;
+
+	if (((unsigned long) fpu) & 3)
+		return -EFAULT;
+
 #ifdef CONFIG_SMP
 	if (test_tsk_thread_flag(current, TIF_USEDFPU))
 		regs->psr &= ~PSR_EF;
@@ -97,7 +101,10 @@
 	struct thread_info *t = current_thread_info();
 	int i, wsaved, err;
 
-	__get_user(wsaved, &rp->wsaved);
+	if (((unsigned long) rp) & 3)
+		return -EFAULT;
+
+	get_user(wsaved, &rp->wsaved);
 	if (wsaved > NSWINS)
 		return -EFAULT;
 
diff --git a/arch/sparc/kernel/sigutil_64.c b/arch/sparc/kernel/sigutil_64.c
index 387834a..36aadcb 100644
--- a/arch/sparc/kernel/sigutil_64.c
+++ b/arch/sparc/kernel/sigutil_64.c
@@ -37,7 +37,10 @@
 	unsigned long fprs;
 	int err;
 
-	err = __get_user(fprs, &fpu->si_fprs);
+	if (((unsigned long) fpu) & 7)
+		return -EFAULT;
+
+	err = get_user(fprs, &fpu->si_fprs);
 	fprs_write(0);
 	regs->tstate &= ~TSTATE_PEF;
 	if (fprs & FPRS_DL)
@@ -72,7 +75,10 @@
 	struct thread_info *t = current_thread_info();
 	int i, wsaved, err;
 
-	__get_user(wsaved, &rp->wsaved);
+	if (((unsigned long) rp) & 7)
+		return -EFAULT;
+
+	get_user(wsaved, &rp->wsaved);
 	if (wsaved > NSWINS)
 		return -EFAULT;
 
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 19cd08d..95a9fa0 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -959,37 +959,6 @@
 	preempt_enable();
 }
 
-void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
-{
-	struct mm_struct *mm;
-	unsigned long flags;
-
-	clear_softint(1 << irq);
-
-	/* See if we need to allocate a new TLB context because
-	 * the version of the one we are using is now out of date.
-	 */
-	mm = current->active_mm;
-	if (unlikely(!mm || (mm == &init_mm)))
-		return;
-
-	spin_lock_irqsave(&mm->context.lock, flags);
-
-	if (unlikely(!CTX_VALID(mm->context)))
-		get_new_mmu_context(mm);
-
-	spin_unlock_irqrestore(&mm->context.lock, flags);
-
-	load_secondary_context(mm);
-	__flush_tlb_mm(CTX_HWBITS(mm->context),
-		       SECONDARY_CONTEXT);
-}
-
-void smp_new_mmu_context_version(void)
-{
-	smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0);
-}
-
 #ifdef CONFIG_KGDB
 void kgdb_roundup_cpus(unsigned long flags)
 {
diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c
index a92d5d2..51b2532 100644
--- a/arch/sparc/kernel/sparc_ksyms_64.c
+++ b/arch/sparc/kernel/sparc_ksyms_64.c
@@ -27,7 +27,6 @@
 EXPORT_SYMBOL_GPL(real_hard_smp_processor_id);
 
 /* from head_64.S */
-EXPORT_SYMBOL(__ret_efault);
 EXPORT_SYMBOL(tlb_type);
 EXPORT_SYMBOL(sun4v_chip_type);
 EXPORT_SYMBOL(prom_root_node);
diff --git a/arch/sparc/kernel/spiterrs.S b/arch/sparc/kernel/spiterrs.S
index c357e40..4a73009 100644
--- a/arch/sparc/kernel/spiterrs.S
+++ b/arch/sparc/kernel/spiterrs.S
@@ -85,8 +85,7 @@
 	ba,pt		%xcc, etraptl1
 	 rd		%pc, %g7
 
-	ba,pt		%xcc, 2f
-	 nop
+	ba,a,pt		%xcc, 2f
 
 1:	ba,pt		%xcc, etrap_irq
 	 rd		%pc, %g7
@@ -100,8 +99,7 @@
 	mov		%l5, %o2
 	call		spitfire_access_error
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		__spitfire_access_error,.-__spitfire_access_error
 
 	/* This is the trap handler entry point for ECC correctable
@@ -179,8 +177,7 @@
 	mov		%l5, %o2
 	call		spitfire_data_access_exception_tl1
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		__spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1
 
 	.type		__spitfire_data_access_exception,#function
@@ -200,8 +197,7 @@
 	mov		%l5, %o2
 	call		spitfire_data_access_exception
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		__spitfire_data_access_exception,.-__spitfire_data_access_exception
 
 	.type		__spitfire_insn_access_exception_tl1,#function
@@ -220,8 +216,7 @@
 	mov		%l5, %o2
 	call		spitfire_insn_access_exception_tl1
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		__spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1
 
 	.type		__spitfire_insn_access_exception,#function
@@ -240,6 +235,5 @@
 	mov		%l5, %o2
 	call		spitfire_insn_access_exception
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 	.size		__spitfire_insn_access_exception,.-__spitfire_insn_access_exception
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index b489e97..98a5cf3 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -118,7 +118,7 @@
 
 		vma = find_vma(mm, addr);
 		if (task_size - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
@@ -181,7 +181,7 @@
 
 		vma = find_vma(mm, addr);
 		if (task_size - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index bb00089..c4a1b5c 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -158,7 +158,25 @@
 	 add	%sp, PTREGS_OFF, %o0
 	brnz,pn	%o0, 3f
 	 mov	-ENOSYS, %o0
+
+	/* Syscall tracing can modify the registers.  */
+	ldx	[%sp + PTREGS_OFF + PT_V9_G1], %g1
+	sethi	%hi(sys_call_table32), %l7
+	ldx	[%sp + PTREGS_OFF + PT_V9_I0], %i0
+	or	%l7, %lo(sys_call_table32), %l7
+	ldx	[%sp + PTREGS_OFF + PT_V9_I1], %i1
+	ldx	[%sp + PTREGS_OFF + PT_V9_I2], %i2
+	ldx	[%sp + PTREGS_OFF + PT_V9_I3], %i3
+	ldx	[%sp + PTREGS_OFF + PT_V9_I4], %i4
+	ldx	[%sp + PTREGS_OFF + PT_V9_I5], %i5
+
+	cmp	%g1, NR_syscalls
+	bgeu,pn	%xcc, 3f
+	 mov	-ENOSYS, %o0
+
+	sll	%g1, 2, %l4
 	srl	%i0, 0, %o0
+	lduw	[%l7 + %l4], %l7
 	srl	%i4, 0, %o4
 	srl	%i1, 0, %o1
 	srl	%i2, 0, %o2
@@ -170,7 +188,25 @@
 	 add	%sp, PTREGS_OFF, %o0
 	brnz,pn	%o0, 3f
 	 mov	-ENOSYS, %o0
+
+	/* Syscall tracing can modify the registers.  */
+	ldx	[%sp + PTREGS_OFF + PT_V9_G1], %g1
+	sethi	%hi(sys_call_table64), %l7
+	ldx	[%sp + PTREGS_OFF + PT_V9_I0], %i0
+	or	%l7, %lo(sys_call_table64), %l7
+	ldx	[%sp + PTREGS_OFF + PT_V9_I1], %i1
+	ldx	[%sp + PTREGS_OFF + PT_V9_I2], %i2
+	ldx	[%sp + PTREGS_OFF + PT_V9_I3], %i3
+	ldx	[%sp + PTREGS_OFF + PT_V9_I4], %i4
+	ldx	[%sp + PTREGS_OFF + PT_V9_I5], %i5
+
+	cmp	%g1, NR_syscalls
+	bgeu,pn	%xcc, 3f
+	 mov	-ENOSYS, %o0
+
+	sll	%g1, 2, %l4
 	mov	%i0, %o0
+	lduw	[%l7 + %l4], %l7
 	mov	%i1, %o1
 	mov	%i2, %o2
 	mov	%i3, %o3
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index d21cd62..cc97a43 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -85,7 +85,7 @@
 
 void bad_trap(struct pt_regs *regs, long lvl)
 {
-	char buffer[32];
+	char buffer[36];
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "bad trap", regs,
@@ -116,7 +116,7 @@
 
 void bad_trap_tl1(struct pt_regs *regs, long lvl)
 {
-	char buffer[32];
+	char buffer[36];
 	
 	if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
 		       0, lvl, SIGTRAP) == NOTIFY_STOP)
diff --git a/arch/sparc/kernel/tsb.S b/arch/sparc/kernel/tsb.S
index be98685..395ec18 100644
--- a/arch/sparc/kernel/tsb.S
+++ b/arch/sparc/kernel/tsb.S
@@ -29,13 +29,17 @@
 	 */
 tsb_miss_dtlb:
 	mov		TLB_TAG_ACCESS, %g4
+	ldxa		[%g4] ASI_DMMU, %g4
+	srlx		%g4, PAGE_SHIFT, %g4
 	ba,pt		%xcc, tsb_miss_page_table_walk
-	 ldxa		[%g4] ASI_DMMU, %g4
+	 sllx		%g4, PAGE_SHIFT, %g4
 
 tsb_miss_itlb:
 	mov		TLB_TAG_ACCESS, %g4
+	ldxa		[%g4] ASI_IMMU, %g4
+	srlx		%g4, PAGE_SHIFT, %g4
 	ba,pt		%xcc, tsb_miss_page_table_walk
-	 ldxa		[%g4] ASI_IMMU, %g4
+	 sllx		%g4, PAGE_SHIFT, %g4
 
 	/* At this point we have:
 	 * %g1 --	PAGE_SIZE TSB entry address
@@ -284,6 +288,10 @@
 	nop
 	.previous
 
+	/* Clear context ID bits.  */
+	srlx		%g5, PAGE_SHIFT, %g5
+	sllx		%g5, PAGE_SHIFT, %g5
+
 	be,pt	%xcc, sparc64_realfault_common
 	 mov	FAULT_CODE_DTLB, %g4
 	ba,pt	%xcc, winfix_trampoline
@@ -462,13 +470,16 @@
 	.type	copy_tsb,#function
 copy_tsb:		/* %o0=old_tsb_base, %o1=old_tsb_size
 			 * %o2=new_tsb_base, %o3=new_tsb_size
+			 * %o4=page_size_shift
 			 */
 	sethi		%uhi(TSB_PASS_BITS), %g7
 	srlx		%o3, 4, %o3
-	add		%o0, %o1, %g1	/* end of old tsb */
+	add		%o0, %o1, %o1	/* end of old tsb */
 	sllx		%g7, 32, %g7
 	sub		%o3, 1, %o3	/* %o3 == new tsb hash mask */
 
+	mov		%o4, %g1	/* page_size_shift */
+
 661:	prefetcha	[%o0] ASI_N, #one_read
 	.section	.tsb_phys_patch, "ax"
 	.word		661b
@@ -493,9 +504,9 @@
 	/* This can definitely be computed faster... */
 	srlx		%o0, 4, %o5	/* Build index */
 	and		%o5, 511, %o5	/* Mask index */
-	sllx		%o5, PAGE_SHIFT, %o5 /* Put into vaddr position */
+	sllx		%o5, %g1, %o5	/* Put into vaddr position */
 	or		%o4, %o5, %o4	/* Full VADDR. */
-	srlx		%o4, PAGE_SHIFT, %o4 /* Shift down to create index */
+	srlx		%o4, %g1, %o4	/* Shift down to create index */
 	and		%o4, %o3, %o4	/* Mask with new_tsb_nents-1 */
 	sllx		%o4, 4, %o4	/* Shift back up into tsb ent offset */
 	TSB_STORE(%o2 + %o4, %g2)	/* Store TAG */
@@ -503,7 +514,7 @@
 	TSB_STORE(%o2 + %o4, %g3)	/* Store TTE */
 
 80:	add		%o0, 16, %o0
-	cmp		%o0, %g1
+	cmp		%o0, %o1
 	bne,pt		%xcc, 90b
 	 nop
 
diff --git a/arch/sparc/kernel/ttable_64.S b/arch/sparc/kernel/ttable_64.S
index c6dfdaa..170ead6 100644
--- a/arch/sparc/kernel/ttable_64.S
+++ b/arch/sparc/kernel/ttable_64.S
@@ -50,7 +50,7 @@
 tl0_irq1:	TRAP_IRQ(smp_call_function_client, 1)
 tl0_irq2:	TRAP_IRQ(smp_receive_signal_client, 2)
 tl0_irq3:	TRAP_IRQ(smp_penguin_jailcell, 3)
-tl0_irq4:	TRAP_IRQ(smp_new_mmu_context_version_client, 4)
+tl0_irq4:       BTRAP(0x44)
 #else
 tl0_irq1:	BTRAP(0x41)
 tl0_irq2:	BTRAP(0x42)
diff --git a/arch/sparc/kernel/urtt_fill.S b/arch/sparc/kernel/urtt_fill.S
new file mode 100644
index 0000000..5604a2b
--- /dev/null
+++ b/arch/sparc/kernel/urtt_fill.S
@@ -0,0 +1,98 @@
+#include <asm/thread_info.h>
+#include <asm/trap_block.h>
+#include <asm/spitfire.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+
+		.text
+		.align	8
+		.globl	user_rtt_fill_fixup_common
+user_rtt_fill_fixup_common:
+		rdpr	%cwp, %g1
+		add	%g1, 1, %g1
+		wrpr	%g1, 0x0, %cwp
+
+		rdpr	%wstate, %g2
+		sll	%g2, 3, %g2
+		wrpr	%g2, 0x0, %wstate
+
+		/* We know %canrestore and %otherwin are both zero.  */
+
+		sethi	%hi(sparc64_kern_pri_context), %g2
+		ldx	[%g2 + %lo(sparc64_kern_pri_context)], %g2
+		mov	PRIMARY_CONTEXT, %g1
+
+661:		stxa	%g2, [%g1] ASI_DMMU
+		.section .sun4v_1insn_patch, "ax"
+		.word	661b
+		stxa	%g2, [%g1] ASI_MMU
+		.previous
+
+		sethi	%hi(KERNBASE), %g1
+		flush	%g1
+
+		mov	%g4, %l4
+		mov	%g5, %l5
+		brnz,pn	%g3, 1f
+		 mov	%g3, %l3
+
+		or	%g4, FAULT_CODE_WINFIXUP, %g4
+		stb	%g4, [%g6 + TI_FAULT_CODE]
+		stx	%g5, [%g6 + TI_FAULT_ADDR]
+1:
+		mov	%g6, %l1
+		wrpr	%g0, 0x0, %tl
+
+661:		nop
+		.section		.sun4v_1insn_patch, "ax"
+		.word			661b
+		SET_GL(0)
+		.previous
+
+		wrpr	%g0, RTRAP_PSTATE, %pstate
+
+		mov	%l1, %g6
+		ldx	[%g6 + TI_TASK], %g4
+		LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
+
+		brnz,pn	%l3, 1f
+		 nop
+
+		call	do_sparc64_fault
+		 add	%sp, PTREGS_OFF, %o0
+		ba,pt	%xcc, rtrap
+		 nop
+
+1:		cmp	%g3, 2
+		bne,pn	%xcc, 2f
+		 nop
+
+		sethi	%hi(tlb_type), %g1
+		lduw	[%g1 + %lo(tlb_type)], %g1
+		cmp	%g1, 3
+		bne,pt	%icc, 1f
+		 add	%sp, PTREGS_OFF, %o0
+		mov	%l4, %o2
+		call	sun4v_do_mna
+		 mov	%l5, %o1
+		ba,a,pt	%xcc, rtrap
+1:		mov	%l4, %o1
+		mov	%l5, %o2
+		call	mem_address_unaligned
+		 nop
+		ba,a,pt	%xcc, rtrap
+
+2:		sethi	%hi(tlb_type), %g1
+		mov	%l4, %o1
+		lduw	[%g1 + %lo(tlb_type)], %g1
+		mov	%l5, %o2
+		cmp	%g1, 3
+		bne,pt	%icc, 1f
+		 add	%sp, PTREGS_OFF, %o0
+		call	sun4v_data_access_exception
+		 nop
+		ba,a,pt	%xcc, rtrap
+
+1:		call	spitfire_data_access_exception
+		 nop
+		ba,a,pt	%xcc, rtrap
diff --git a/arch/sparc/kernel/utrap.S b/arch/sparc/kernel/utrap.S
index b7f0f3f..c731e80 100644
--- a/arch/sparc/kernel/utrap.S
+++ b/arch/sparc/kernel/utrap.S
@@ -11,8 +11,7 @@
 	mov		%l4, %o1
         call		bad_trap
 	 add		%sp, PTREGS_OFF, %o0
-	ba,pt		%xcc, rtrap
-	 nop
+	ba,a,pt		%xcc, rtrap
 
 invoke_utrap:
 	sllx		%g3, 3, %g3
diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c
index cb5789c..34824ca 100644
--- a/arch/sparc/kernel/vio.c
+++ b/arch/sparc/kernel/vio.c
@@ -284,13 +284,16 @@
 	if (!id) {
 		dev_set_name(&vdev->dev, "%s", bus_id_name);
 		vdev->dev_no = ~(u64)0;
+		vdev->id = ~(u64)0;
 	} else if (!cfg_handle) {
 		dev_set_name(&vdev->dev, "%s-%llu", bus_id_name, *id);
 		vdev->dev_no = *id;
+		vdev->id = ~(u64)0;
 	} else {
 		dev_set_name(&vdev->dev, "%s-%llu-%llu", bus_id_name,
 			     *cfg_handle, *id);
 		vdev->dev_no = *cfg_handle;
+		vdev->id = *id;
 	}
 
 	vdev->dev.parent = parent;
@@ -333,27 +336,84 @@
 	(void) vio_create_one(hp, node, &root_vdev->dev);
 }
 
+struct vio_md_node_query {
+	const char *type;
+	u64 dev_no;
+	u64 id;
+};
+
 static int vio_md_node_match(struct device *dev, void *arg)
 {
+	struct vio_md_node_query *query = (struct vio_md_node_query *) arg;
 	struct vio_dev *vdev = to_vio_dev(dev);
 
-	if (vdev->mp == (u64) arg)
-		return 1;
+	if (vdev->dev_no != query->dev_no)
+		return 0;
+	if (vdev->id != query->id)
+		return 0;
+	if (strcmp(vdev->type, query->type))
+		return 0;
 
-	return 0;
+	return 1;
 }
 
 static void vio_remove(struct mdesc_handle *hp, u64 node)
 {
+	const char *type;
+	const u64 *id, *cfg_handle;
+	u64 a;
+	struct vio_md_node_query query;
 	struct device *dev;
 
-	dev = device_find_child(&root_vdev->dev, (void *) node,
+	type = mdesc_get_property(hp, node, "device-type", NULL);
+	if (!type) {
+		type = mdesc_get_property(hp, node, "name", NULL);
+		if (!type)
+			type = mdesc_node_name(hp, node);
+	}
+
+	query.type = type;
+
+	id = mdesc_get_property(hp, node, "id", NULL);
+	cfg_handle = NULL;
+	mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
+		u64 target;
+
+		target = mdesc_arc_target(hp, a);
+		cfg_handle = mdesc_get_property(hp, target,
+						"cfg-handle", NULL);
+		if (cfg_handle)
+			break;
+	}
+
+	if (!id) {
+		query.dev_no = ~(u64)0;
+		query.id = ~(u64)0;
+	} else if (!cfg_handle) {
+		query.dev_no = *id;
+		query.id = ~(u64)0;
+	} else {
+		query.dev_no = *cfg_handle;
+		query.id = *id;
+	}
+
+	dev = device_find_child(&root_vdev->dev, &query,
 				vio_md_node_match);
 	if (dev) {
 		printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev));
 
 		device_unregister(dev);
 		put_device(dev);
+	} else {
+		if (!id)
+			printk(KERN_ERR "VIO: Removed unknown %s node.\n",
+			       type);
+		else if (!cfg_handle)
+			printk(KERN_ERR "VIO: Removed unknown %s node %llu.\n",
+			       type, *id);
+		else
+			printk(KERN_ERR "VIO: Removed unknown %s node %llu-%llu.\n",
+			       type, *cfg_handle, *id);
 	}
 }
 
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index f1a2f68..4a41d41 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -33,6 +33,10 @@
 jiffies = jiffies_64;
 #endif
 
+#ifdef CONFIG_SPARC64
+ASSERT((swapper_tsb == 0x0000000000408000), "Error: sparc64 early assembler too large")
+#endif
+
 SECTIONS
 {
 #ifdef CONFIG_SPARC64
diff --git a/arch/sparc/kernel/winfixup.S b/arch/sparc/kernel/winfixup.S
index 1e67ce9..855019a 100644
--- a/arch/sparc/kernel/winfixup.S
+++ b/arch/sparc/kernel/winfixup.S
@@ -32,8 +32,7 @@
 	 rd	%pc, %g7
 	call	do_sparc64_fault
 	 add	%sp, PTREGS_OFF, %o0
-	ba,pt	%xcc, rtrap
-	 nop
+	ba,a,pt	%xcc, rtrap
 
 	/* Be very careful about usage of the trap globals here.
 	 * You cannot touch %g5 as that has the fault information.
diff --git a/arch/sparc/lib/GENcopy_from_user.S b/arch/sparc/lib/GENcopy_from_user.S
index b7d0bd6..69a439f 100644
--- a/arch/sparc/lib/GENcopy_from_user.S
+++ b/arch/sparc/lib/GENcopy_from_user.S
@@ -3,11 +3,11 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_LD(x)		\
+#define EX_LD(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one;	\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/GENcopy_to_user.S b/arch/sparc/lib/GENcopy_to_user.S
index 780550e..9947427 100644
--- a/arch/sparc/lib/GENcopy_to_user.S
+++ b/arch/sparc/lib/GENcopy_to_user.S
@@ -3,11 +3,11 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_ST(x)		\
+#define EX_ST(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one;	\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/GENmemcpy.S b/arch/sparc/lib/GENmemcpy.S
index 89358ee..059ea24 100644
--- a/arch/sparc/lib/GENmemcpy.S
+++ b/arch/sparc/lib/GENmemcpy.S
@@ -4,21 +4,18 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #define GLOBAL_SPARE	%g7
 #else
 #define GLOBAL_SPARE	%g5
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)	x
+#define EX_LD(x,y)	x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)	x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)	x
+#define EX_ST(x,y)	x
 #endif
 
 #ifndef LOAD
@@ -45,6 +42,29 @@
 	.register	%g3,#scratch
 
 	.text
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+ENTRY(GEN_retl_o4_1)
+	add	%o4, %o2, %o4
+	retl
+	 add	%o4, 1, %o0
+ENDPROC(GEN_retl_o4_1)
+ENTRY(GEN_retl_g1_8)
+	add	%g1, %o2, %g1
+	retl
+	 add	%g1, 8, %o0
+ENDPROC(GEN_retl_g1_8)
+ENTRY(GEN_retl_o2_4)
+	retl
+	 add	%o2, 4, %o0
+ENDPROC(GEN_retl_o2_4)
+ENTRY(GEN_retl_o2_1)
+	retl
+	 add	%o2, 1, %o0
+ENDPROC(GEN_retl_o2_1)
+#endif
+
 	.align		64
 
 	.globl	FUNC_NAME
@@ -73,8 +93,8 @@
 	sub		%g0, %o4, %o4
 	sub		%o2, %o4, %o2
 1:	subcc		%o4, 1, %o4
-	EX_LD(LOAD(ldub, %o1, %g1))
-	EX_ST(STORE(stb, %g1, %o0))
+	EX_LD(LOAD(ldub, %o1, %g1),GEN_retl_o4_1)
+	EX_ST(STORE(stb, %g1, %o0),GEN_retl_o4_1)
 	add		%o1, 1, %o1
 	bne,pt		%XCC, 1b
 	add		%o0, 1, %o0
@@ -82,8 +102,8 @@
 	andn		%o2, 0x7, %g1
 	sub		%o2, %g1, %o2
 1:	subcc		%g1, 0x8, %g1
-	EX_LD(LOAD(ldx, %o1, %g2))
-	EX_ST(STORE(stx, %g2, %o0))
+	EX_LD(LOAD(ldx, %o1, %g2),GEN_retl_g1_8)
+	EX_ST(STORE(stx, %g2, %o0),GEN_retl_g1_8)
 	add		%o1, 0x8, %o1
 	bne,pt		%XCC, 1b
 	 add		%o0, 0x8, %o0
@@ -100,8 +120,8 @@
 
 1:
 	subcc		%o2, 4, %o2
-	EX_LD(LOAD(lduw, %o1, %g1))
-	EX_ST(STORE(stw, %g1, %o1 + %o3))
+	EX_LD(LOAD(lduw, %o1, %g1),GEN_retl_o2_4)
+	EX_ST(STORE(stw, %g1, %o1 + %o3),GEN_retl_o2_4)
 	bgu,pt		%XCC, 1b
 	 add		%o1, 4, %o1
 
@@ -111,8 +131,8 @@
 	.align		32
 90:
 	subcc		%o2, 1, %o2
-	EX_LD(LOAD(ldub, %o1, %g1))
-	EX_ST(STORE(stb, %g1, %o1 + %o3))
+	EX_LD(LOAD(ldub, %o1, %g1),GEN_retl_o2_1)
+	EX_ST(STORE(stb, %g1, %o1 + %o3),GEN_retl_o2_1)
 	bgu,pt		%XCC, 90b
 	 add		%o1, 1, %o1
 	retl
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 3269b02..4f2384a 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -38,7 +38,7 @@
 lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o
 lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o
 
-lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
+lib-$(CONFIG_SPARC64) += copy_in_user.o memmove.o
 lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
 
 obj-$(CONFIG_SPARC64) += iomap.o
diff --git a/arch/sparc/lib/NG2copy_from_user.S b/arch/sparc/lib/NG2copy_from_user.S
index d5242b8..b79a699 100644
--- a/arch/sparc/lib/NG2copy_from_user.S
+++ b/arch/sparc/lib/NG2copy_from_user.S
@@ -3,19 +3,19 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_LD(x)		\
+#define EX_LD(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_asi;\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
-#define EX_LD_FP(x)		\
+#define EX_LD_FP(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_asi_fp;\
+	.word 98b, y##_fp;	\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/NG2copy_to_user.S b/arch/sparc/lib/NG2copy_to_user.S
index 4e962d9..dcec55f 100644
--- a/arch/sparc/lib/NG2copy_to_user.S
+++ b/arch/sparc/lib/NG2copy_to_user.S
@@ -3,19 +3,19 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_ST(x)		\
+#define EX_ST(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_asi;\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
-#define EX_ST_FP(x)		\
+#define EX_ST_FP(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_asi_fp;\
+	.word 98b, y##_fp;	\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/NG2memcpy.S b/arch/sparc/lib/NG2memcpy.S
index d5f585d..c629dbd 100644
--- a/arch/sparc/lib/NG2memcpy.S
+++ b/arch/sparc/lib/NG2memcpy.S
@@ -4,6 +4,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/visasm.h>
 #include <asm/asi.h>
 #define GLOBAL_SPARE	%g7
@@ -32,21 +33,17 @@
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)	x
+#define EX_LD(x,y)	x
 #endif
 #ifndef EX_LD_FP
-#define EX_LD_FP(x)	x
+#define EX_LD_FP(x,y)	x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)	x
+#define EX_ST(x,y)	x
 #endif
 #ifndef EX_ST_FP
-#define EX_ST_FP(x)	x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)	x
+#define EX_ST_FP(x,y)	x
 #endif
 
 #ifndef LOAD
@@ -140,45 +137,110 @@
 	fsrc2		%x6, %f12; \
 	fsrc2		%x7, %f14;
 #define FREG_LOAD_1(base, x0) \
-	EX_LD_FP(LOAD(ldd, base + 0x00, %x0))
+	EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1)
 #define FREG_LOAD_2(base, x0, x1) \
-	EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-	EX_LD_FP(LOAD(ldd, base + 0x08, %x1));
+	EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_3(base, x0, x1, x2) \
-	EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-	EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-	EX_LD_FP(LOAD(ldd, base + 0x10, %x2));
+	EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_4(base, x0, x1, x2, x3) \
-	EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-	EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-	EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
-	EX_LD_FP(LOAD(ldd, base + 0x18, %x3));
+	EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_5(base, x0, x1, x2, x3, x4) \
-	EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-	EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-	EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
-	EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
-	EX_LD_FP(LOAD(ldd, base + 0x20, %x4));
+	EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_6(base, x0, x1, x2, x3, x4, x5) \
-	EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-	EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-	EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
-	EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
-	EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \
-	EX_LD_FP(LOAD(ldd, base + 0x28, %x5));
+	EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x28, %x5), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_7(base, x0, x1, x2, x3, x4, x5, x6) \
-	EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-	EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-	EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
-	EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
-	EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \
-	EX_LD_FP(LOAD(ldd, base + 0x28, %x5)); \
-	EX_LD_FP(LOAD(ldd, base + 0x30, %x6));
+	EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x28, %x5), NG2_retl_o2_plus_g1); \
+	EX_LD_FP(LOAD(ldd, base + 0x30, %x6), NG2_retl_o2_plus_g1);
 
 	.register	%g2,#scratch
 	.register	%g3,#scratch
 
 	.text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+__restore_fp:
+	VISExitHalf
+__restore_asi:
+	retl
+	 wr	%g0, ASI_AIUS, %asi
+ENTRY(NG2_retl_o2)
+	ba,pt	%xcc, __restore_asi
+	 mov	%o2, %o0
+ENDPROC(NG2_retl_o2)
+ENTRY(NG2_retl_o2_plus_1)
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, 1, %o0
+ENDPROC(NG2_retl_o2_plus_1)
+ENTRY(NG2_retl_o2_plus_4)
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, 4, %o0
+ENDPROC(NG2_retl_o2_plus_4)
+ENTRY(NG2_retl_o2_plus_8)
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, 8, %o0
+ENDPROC(NG2_retl_o2_plus_8)
+ENTRY(NG2_retl_o2_plus_o4_plus_1)
+	add	%o4, 1, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG2_retl_o2_plus_o4_plus_1)
+ENTRY(NG2_retl_o2_plus_o4_plus_8)
+	add	%o4, 8, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG2_retl_o2_plus_o4_plus_8)
+ENTRY(NG2_retl_o2_plus_o4_plus_16)
+	add	%o4, 16, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG2_retl_o2_plus_o4_plus_16)
+ENTRY(NG2_retl_o2_plus_g1_fp)
+	ba,pt	%xcc, __restore_fp
+	 add	%o2, %g1, %o0
+ENDPROC(NG2_retl_o2_plus_g1_fp)
+ENTRY(NG2_retl_o2_plus_g1_plus_64_fp)
+	add	%g1, 64, %g1
+	ba,pt	%xcc, __restore_fp
+	 add	%o2, %g1, %o0
+ENDPROC(NG2_retl_o2_plus_g1_plus_64_fp)
+ENTRY(NG2_retl_o2_plus_g1_plus_1)
+	add	%g1, 1, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %g1, %o0
+ENDPROC(NG2_retl_o2_plus_g1_plus_1)
+ENTRY(NG2_retl_o2_and_7_plus_o4)
+	and	%o2, 7, %o2
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG2_retl_o2_and_7_plus_o4)
+ENTRY(NG2_retl_o2_and_7_plus_o4_plus_8)
+	and	%o2, 7, %o2
+	add	%o4, 8, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG2_retl_o2_and_7_plus_o4_plus_8)
+#endif
+
 	.align		64
 
 	.globl	FUNC_NAME
@@ -230,8 +292,8 @@
 	sub		%g0, %o4, %o4	! bytes to align dst
 	sub		%o2, %o4, %o2
 1:	subcc		%o4, 1, %o4
-	EX_LD(LOAD(ldub, %o1, %g1))
-	EX_ST(STORE(stb, %g1, %o0))
+	EX_LD(LOAD(ldub, %o1, %g1), NG2_retl_o2_plus_o4_plus_1)
+	EX_ST(STORE(stb, %g1, %o0), NG2_retl_o2_plus_o4_plus_1)
 	add		%o1, 1, %o1
 	bne,pt		%XCC, 1b
 	add		%o0, 1, %o0
@@ -281,11 +343,11 @@
 	 nop
 	/* fall through for 0 < low bits < 8 */
 110:	sub		%o4, 64, %g2
-	EX_LD_FP(LOAD_BLK(%g2, %f0))
-1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-	EX_LD_FP(LOAD_BLK(%o4, %f16))
+	EX_LD_FP(LOAD_BLK(%g2, %f0), NG2_retl_o2_plus_g1)
+1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+	EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
 	FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f14, f16)
-	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
 	FREG_MOVE_8(f16, f18, f20, f22, f24, f26, f28, f30)
 	subcc		%g1, 64, %g1
 	add		%o4, 64, %o4
@@ -296,10 +358,10 @@
 
 120:	sub		%o4, 56, %g2
 	FREG_LOAD_7(%g2, f0, f2, f4, f6, f8, f10, f12)
-1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-	EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+	EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
 	FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f16, f18)
-	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
 	FREG_MOVE_7(f18, f20, f22, f24, f26, f28, f30)
 	subcc		%g1, 64, %g1
 	add		%o4, 64, %o4
@@ -310,10 +372,10 @@
 
 130:	sub		%o4, 48, %g2
 	FREG_LOAD_6(%g2, f0, f2, f4, f6, f8, f10)
-1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-	EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+	EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
 	FREG_FROB(f0, f2, f4, f6, f8, f10, f16, f18, f20)
-	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
 	FREG_MOVE_6(f20, f22, f24, f26, f28, f30)
 	subcc		%g1, 64, %g1
 	add		%o4, 64, %o4
@@ -324,10 +386,10 @@
 
 140:	sub		%o4, 40, %g2
 	FREG_LOAD_5(%g2, f0, f2, f4, f6, f8)
-1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-	EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+	EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
 	FREG_FROB(f0, f2, f4, f6, f8, f16, f18, f20, f22)
-	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
 	FREG_MOVE_5(f22, f24, f26, f28, f30)
 	subcc		%g1, 64, %g1
 	add		%o4, 64, %o4
@@ -338,10 +400,10 @@
 
 150:	sub		%o4, 32, %g2
 	FREG_LOAD_4(%g2, f0, f2, f4, f6)
-1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-	EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+	EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
 	FREG_FROB(f0, f2, f4, f6, f16, f18, f20, f22, f24)
-	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
 	FREG_MOVE_4(f24, f26, f28, f30)
 	subcc		%g1, 64, %g1
 	add		%o4, 64, %o4
@@ -352,10 +414,10 @@
 
 160:	sub		%o4, 24, %g2
 	FREG_LOAD_3(%g2, f0, f2, f4)
-1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-	EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+	EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
 	FREG_FROB(f0, f2, f4, f16, f18, f20, f22, f24, f26)
-	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
 	FREG_MOVE_3(f26, f28, f30)
 	subcc		%g1, 64, %g1
 	add		%o4, 64, %o4
@@ -366,10 +428,10 @@
 
 170:	sub		%o4, 16, %g2
 	FREG_LOAD_2(%g2, f0, f2)
-1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-	EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+	EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
 	FREG_FROB(f0, f2, f16, f18, f20, f22, f24, f26, f28)
-	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
 	FREG_MOVE_2(f28, f30)
 	subcc		%g1, 64, %g1
 	add		%o4, 64, %o4
@@ -380,10 +442,10 @@
 
 180:	sub		%o4, 8, %g2
 	FREG_LOAD_1(%g2, f0)
-1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-	EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+	EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
 	FREG_FROB(f0, f16, f18, f20, f22, f24, f26, f28, f30)
-	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
 	FREG_MOVE_1(f30)
 	subcc		%g1, 64, %g1
 	add		%o4, 64, %o4
@@ -393,10 +455,10 @@
 	 nop
 
 190:
-1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+1:	EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
 	subcc		%g1, 64, %g1
-	EX_LD_FP(LOAD_BLK(%o4, %f0))
-	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+	EX_LD_FP(LOAD_BLK(%o4, %f0), NG2_retl_o2_plus_g1_plus_64)
+	EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1_plus_64)
 	add		%o4, 64, %o4
 	bne,pt		%xcc, 1b
 	 LOAD(prefetch, %o4 + 64, #one_read)
@@ -423,28 +485,28 @@
 	andn		%o2, 0xf, %o4
 	and		%o2, 0xf, %o2
 1:	subcc		%o4, 0x10, %o4
-	EX_LD(LOAD(ldx, %o1, %o5))
+	EX_LD(LOAD(ldx, %o1, %o5), NG2_retl_o2_plus_o4_plus_16)
 	add		%o1, 0x08, %o1
-	EX_LD(LOAD(ldx, %o1, %g1))
+	EX_LD(LOAD(ldx, %o1, %g1), NG2_retl_o2_plus_o4_plus_16)
 	sub		%o1, 0x08, %o1
-	EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE))
+	EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_o4_plus_16)
 	add		%o1, 0x8, %o1
-	EX_ST(STORE(stx, %g1, %o1 + GLOBAL_SPARE))
+	EX_ST(STORE(stx, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_o4_plus_8)
 	bgu,pt		%XCC, 1b
 	 add		%o1, 0x8, %o1
 73:	andcc		%o2, 0x8, %g0
 	be,pt		%XCC, 1f
 	 nop
 	sub		%o2, 0x8, %o2
-	EX_LD(LOAD(ldx, %o1, %o5))
-	EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE))
+	EX_LD(LOAD(ldx, %o1, %o5), NG2_retl_o2_plus_8)
+	EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_8)
 	add		%o1, 0x8, %o1
 1:	andcc		%o2, 0x4, %g0
 	be,pt		%XCC, 1f
 	 nop
 	sub		%o2, 0x4, %o2
-	EX_LD(LOAD(lduw, %o1, %o5))
-	EX_ST(STORE(stw, %o5, %o1 + GLOBAL_SPARE))
+	EX_LD(LOAD(lduw, %o1, %o5), NG2_retl_o2_plus_4)
+	EX_ST(STORE(stw, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_4)
 	add		%o1, 0x4, %o1
 1:	cmp		%o2, 0
 	be,pt		%XCC, 85f
@@ -460,8 +522,8 @@
 	sub		%o2, %g1, %o2
 
 1:	subcc		%g1, 1, %g1
-	EX_LD(LOAD(ldub, %o1, %o5))
-	EX_ST(STORE(stb, %o5, %o1 + GLOBAL_SPARE))
+	EX_LD(LOAD(ldub, %o1, %o5), NG2_retl_o2_plus_g1_plus_1)
+	EX_ST(STORE(stb, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_g1_plus_1)
 	bgu,pt		%icc, 1b
 	 add		%o1, 1, %o1
 
@@ -477,16 +539,16 @@
 
 8:	mov		64, GLOBAL_SPARE
 	andn		%o1, 0x7, %o1
-	EX_LD(LOAD(ldx, %o1, %g2))
+	EX_LD(LOAD(ldx, %o1, %g2), NG2_retl_o2)
 	sub		GLOBAL_SPARE, %g1, GLOBAL_SPARE
 	andn		%o2, 0x7, %o4
 	sllx		%g2, %g1, %g2
 1:	add		%o1, 0x8, %o1
-	EX_LD(LOAD(ldx, %o1, %g3))
+	EX_LD(LOAD(ldx, %o1, %g3), NG2_retl_o2_and_7_plus_o4)
 	subcc		%o4, 0x8, %o4
 	srlx		%g3, GLOBAL_SPARE, %o5
 	or		%o5, %g2, %o5
-	EX_ST(STORE(stx, %o5, %o0))
+	EX_ST(STORE(stx, %o5, %o0), NG2_retl_o2_and_7_plus_o4_plus_8)
 	add		%o0, 0x8, %o0
 	bgu,pt		%icc, 1b
 	 sllx		%g3, %g1, %g2
@@ -506,8 +568,8 @@
 
 1:
 	subcc		%o2, 4, %o2
-	EX_LD(LOAD(lduw, %o1, %g1))
-	EX_ST(STORE(stw, %g1, %o1 + GLOBAL_SPARE))
+	EX_LD(LOAD(lduw, %o1, %g1), NG2_retl_o2_plus_4)
+	EX_ST(STORE(stw, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_4)
 	bgu,pt		%XCC, 1b
 	 add		%o1, 4, %o1
 
@@ -517,8 +579,8 @@
 	.align		32
 90:
 	subcc		%o2, 1, %o2
-	EX_LD(LOAD(ldub, %o1, %g1))
-	EX_ST(STORE(stb, %g1, %o1 + GLOBAL_SPARE))
+	EX_LD(LOAD(ldub, %o1, %g1), NG2_retl_o2_plus_1)
+	EX_ST(STORE(stb, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_1)
 	bgu,pt		%XCC, 90b
 	 add		%o1, 1, %o1
 	retl
diff --git a/arch/sparc/lib/NG4copy_from_user.S b/arch/sparc/lib/NG4copy_from_user.S
index 2e8ee7a..16a286c 100644
--- a/arch/sparc/lib/NG4copy_from_user.S
+++ b/arch/sparc/lib/NG4copy_from_user.S
@@ -3,19 +3,19 @@
  * Copyright (C) 2012 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_LD(x)		\
+#define EX_LD(x, y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_asi;\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
-#define EX_LD_FP(x)		\
+#define EX_LD_FP(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_asi_fp;\
+	.word 98b, y##_fp;	\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/NG4copy_to_user.S b/arch/sparc/lib/NG4copy_to_user.S
index be0bf45..6b0276f 100644
--- a/arch/sparc/lib/NG4copy_to_user.S
+++ b/arch/sparc/lib/NG4copy_to_user.S
@@ -3,19 +3,19 @@
  * Copyright (C) 2012 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_ST(x)		\
+#define EX_ST(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_asi;\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
-#define EX_ST_FP(x)		\
+#define EX_ST_FP(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_asi_fp;\
+	.word 98b, y##_fp;	\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/NG4memcpy.S b/arch/sparc/lib/NG4memcpy.S
index 8e13ee1..75bb93b 100644
--- a/arch/sparc/lib/NG4memcpy.S
+++ b/arch/sparc/lib/NG4memcpy.S
@@ -4,6 +4,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/visasm.h>
 #include <asm/asi.h>
 #define GLOBAL_SPARE	%g7
@@ -46,22 +47,19 @@
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)	x
+#define EX_LD(x,y)	x
 #endif
 #ifndef EX_LD_FP
-#define EX_LD_FP(x)	x
+#define EX_LD_FP(x,y)	x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)	x
+#define EX_ST(x,y)	x
 #endif
 #ifndef EX_ST_FP
-#define EX_ST_FP(x)	x
+#define EX_ST_FP(x,y)	x
 #endif
 
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)	x
-#endif
 
 #ifndef LOAD
 #define LOAD(type,addr,dest)	type [addr], dest
@@ -94,6 +92,158 @@
 	.register	%g3,#scratch
 
 	.text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+__restore_asi_fp:
+	VISExitHalf
+__restore_asi:
+	retl
+	 wr	%g0, ASI_AIUS, %asi
+
+ENTRY(NG4_retl_o2)
+	ba,pt	%xcc, __restore_asi
+	 mov	%o2, %o0
+ENDPROC(NG4_retl_o2)
+ENTRY(NG4_retl_o2_plus_1)
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, 1, %o0
+ENDPROC(NG4_retl_o2_plus_1)
+ENTRY(NG4_retl_o2_plus_4)
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, 4, %o0
+ENDPROC(NG4_retl_o2_plus_4)
+ENTRY(NG4_retl_o2_plus_o5)
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5)
+ENTRY(NG4_retl_o2_plus_o5_plus_4)
+	add	%o5, 4, %o5
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_4)
+ENTRY(NG4_retl_o2_plus_o5_plus_8)
+	add	%o5, 8, %o5
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_8)
+ENTRY(NG4_retl_o2_plus_o5_plus_16)
+	add	%o5, 16, %o5
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_16)
+ENTRY(NG4_retl_o2_plus_o5_plus_24)
+	add	%o5, 24, %o5
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_24)
+ENTRY(NG4_retl_o2_plus_o5_plus_32)
+	add	%o5, 32, %o5
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_32)
+ENTRY(NG4_retl_o2_plus_g1)
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %g1, %o0
+ENDPROC(NG4_retl_o2_plus_g1)
+ENTRY(NG4_retl_o2_plus_g1_plus_1)
+	add	%g1, 1, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %g1, %o0
+ENDPROC(NG4_retl_o2_plus_g1_plus_1)
+ENTRY(NG4_retl_o2_plus_g1_plus_8)
+	add	%g1, 8, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %g1, %o0
+ENDPROC(NG4_retl_o2_plus_g1_plus_8)
+ENTRY(NG4_retl_o2_plus_o4)
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4)
+ENTRY(NG4_retl_o2_plus_o4_plus_8)
+	add	%o4, 8, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_8)
+ENTRY(NG4_retl_o2_plus_o4_plus_16)
+	add	%o4, 16, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_16)
+ENTRY(NG4_retl_o2_plus_o4_plus_24)
+	add	%o4, 24, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_24)
+ENTRY(NG4_retl_o2_plus_o4_plus_32)
+	add	%o4, 32, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_32)
+ENTRY(NG4_retl_o2_plus_o4_plus_40)
+	add	%o4, 40, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_40)
+ENTRY(NG4_retl_o2_plus_o4_plus_48)
+	add	%o4, 48, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_48)
+ENTRY(NG4_retl_o2_plus_o4_plus_56)
+	add	%o4, 56, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_56)
+ENTRY(NG4_retl_o2_plus_o4_plus_64)
+	add	%o4, 64, %o4
+	ba,pt	%xcc, __restore_asi
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_64)
+ENTRY(NG4_retl_o2_plus_o4_fp)
+	ba,pt	%xcc, __restore_asi_fp
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_8_fp)
+	add	%o4, 8, %o4
+	ba,pt	%xcc, __restore_asi_fp
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_8_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_16_fp)
+	add	%o4, 16, %o4
+	ba,pt	%xcc, __restore_asi_fp
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_16_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_24_fp)
+	add	%o4, 24, %o4
+	ba,pt	%xcc, __restore_asi_fp
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_24_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_32_fp)
+	add	%o4, 32, %o4
+	ba,pt	%xcc, __restore_asi_fp
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_32_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_40_fp)
+	add	%o4, 40, %o4
+	ba,pt	%xcc, __restore_asi_fp
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_40_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_48_fp)
+	add	%o4, 48, %o4
+	ba,pt	%xcc, __restore_asi_fp
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_48_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_56_fp)
+	add	%o4, 56, %o4
+	ba,pt	%xcc, __restore_asi_fp
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_56_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_64_fp)
+	add	%o4, 64, %o4
+	ba,pt	%xcc, __restore_asi_fp
+	 add	%o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_64_fp)
+#endif
 	.align		64
 
 	.globl	FUNC_NAME
@@ -124,12 +274,13 @@
 	brz,pt		%g1, 51f
 	 sub		%o2, %g1, %o2
 
-1:	EX_LD(LOAD(ldub, %o1 + 0x00, %g2))
+
+1:	EX_LD(LOAD(ldub, %o1 + 0x00, %g2), NG4_retl_o2_plus_g1)
 	add		%o1, 1, %o1
 	subcc		%g1, 1, %g1
 	add		%o0, 1, %o0
 	bne,pt		%icc, 1b
-	 EX_ST(STORE(stb, %g2, %o0 - 0x01))
+	 EX_ST(STORE(stb, %g2, %o0 - 0x01), NG4_retl_o2_plus_g1_plus_1)
 
 51:	LOAD(prefetch, %o1 + 0x040, #n_reads_strong)
 	LOAD(prefetch, %o1 + 0x080, #n_reads_strong)
@@ -154,43 +305,43 @@
 	brz,pt		%g1, .Llarge_aligned
 	 sub		%o2, %g1, %o2
 
-1:	EX_LD(LOAD(ldx, %o1 + 0x00, %g2))
+1:	EX_LD(LOAD(ldx, %o1 + 0x00, %g2), NG4_retl_o2_plus_g1)
 	add		%o1, 8, %o1
 	subcc		%g1, 8, %g1
 	add		%o0, 8, %o0
 	bne,pt		%icc, 1b
-	 EX_ST(STORE(stx, %g2, %o0 - 0x08))
+	 EX_ST(STORE(stx, %g2, %o0 - 0x08), NG4_retl_o2_plus_g1_plus_8)
 
 .Llarge_aligned:
 	/* len >= 0x80 && src 8-byte aligned && dest 8-byte aligned */
 	andn		%o2, 0x3f, %o4
 	sub		%o2, %o4, %o2
 
-1:	EX_LD(LOAD(ldx, %o1 + 0x00, %g1))
+1:	EX_LD(LOAD(ldx, %o1 + 0x00, %g1), NG4_retl_o2_plus_o4)
 	add		%o1, 0x40, %o1
-	EX_LD(LOAD(ldx, %o1 - 0x38, %g2))
+	EX_LD(LOAD(ldx, %o1 - 0x38, %g2), NG4_retl_o2_plus_o4)
 	subcc		%o4, 0x40, %o4
-	EX_LD(LOAD(ldx, %o1 - 0x30, %g3))
-	EX_LD(LOAD(ldx, %o1 - 0x28, GLOBAL_SPARE))
-	EX_LD(LOAD(ldx, %o1 - 0x20, %o5))
-	EX_ST(STORE_INIT(%g1, %o0))
+	EX_LD(LOAD(ldx, %o1 - 0x30, %g3), NG4_retl_o2_plus_o4_plus_64)
+	EX_LD(LOAD(ldx, %o1 - 0x28, GLOBAL_SPARE), NG4_retl_o2_plus_o4_plus_64)
+	EX_LD(LOAD(ldx, %o1 - 0x20, %o5), NG4_retl_o2_plus_o4_plus_64)
+	EX_ST(STORE_INIT(%g1, %o0), NG4_retl_o2_plus_o4_plus_64)
 	add		%o0, 0x08, %o0
-	EX_ST(STORE_INIT(%g2, %o0))
+	EX_ST(STORE_INIT(%g2, %o0), NG4_retl_o2_plus_o4_plus_56)
 	add		%o0, 0x08, %o0
-	EX_LD(LOAD(ldx, %o1 - 0x18, %g2))
-	EX_ST(STORE_INIT(%g3, %o0))
+	EX_LD(LOAD(ldx, %o1 - 0x18, %g2), NG4_retl_o2_plus_o4_plus_48)
+	EX_ST(STORE_INIT(%g3, %o0), NG4_retl_o2_plus_o4_plus_48)
 	add		%o0, 0x08, %o0
-	EX_LD(LOAD(ldx, %o1 - 0x10, %g3))
-	EX_ST(STORE_INIT(GLOBAL_SPARE, %o0))
+	EX_LD(LOAD(ldx, %o1 - 0x10, %g3), NG4_retl_o2_plus_o4_plus_40)
+	EX_ST(STORE_INIT(GLOBAL_SPARE, %o0), NG4_retl_o2_plus_o4_plus_40)
 	add		%o0, 0x08, %o0
-	EX_LD(LOAD(ldx, %o1 - 0x08, GLOBAL_SPARE))
-	EX_ST(STORE_INIT(%o5, %o0))
+	EX_LD(LOAD(ldx, %o1 - 0x08, GLOBAL_SPARE), NG4_retl_o2_plus_o4_plus_32)
+	EX_ST(STORE_INIT(%o5, %o0), NG4_retl_o2_plus_o4_plus_32)
 	add		%o0, 0x08, %o0
-	EX_ST(STORE_INIT(%g2, %o0))
+	EX_ST(STORE_INIT(%g2, %o0), NG4_retl_o2_plus_o4_plus_24)
 	add		%o0, 0x08, %o0
-	EX_ST(STORE_INIT(%g3, %o0))
+	EX_ST(STORE_INIT(%g3, %o0), NG4_retl_o2_plus_o4_plus_16)
 	add		%o0, 0x08, %o0
-	EX_ST(STORE_INIT(GLOBAL_SPARE, %o0))
+	EX_ST(STORE_INIT(GLOBAL_SPARE, %o0), NG4_retl_o2_plus_o4_plus_8)
 	add		%o0, 0x08, %o0
 	bne,pt		%icc, 1b
 	 LOAD(prefetch, %o1 + 0x200, #n_reads_strong)
@@ -216,17 +367,17 @@
 	sub		%o2, %o4, %o2
 	alignaddr	%o1, %g0, %g1
 	add		%o1, %o4, %o1
-	EX_LD_FP(LOAD(ldd, %g1 + 0x00, %f0))
-1:	EX_LD_FP(LOAD(ldd, %g1 + 0x08, %f2))
+	EX_LD_FP(LOAD(ldd, %g1 + 0x00, %f0), NG4_retl_o2_plus_o4)
+1:	EX_LD_FP(LOAD(ldd, %g1 + 0x08, %f2), NG4_retl_o2_plus_o4)
 	subcc		%o4, 0x40, %o4
-	EX_LD_FP(LOAD(ldd, %g1 + 0x10, %f4))
-	EX_LD_FP(LOAD(ldd, %g1 + 0x18, %f6))
-	EX_LD_FP(LOAD(ldd, %g1 + 0x20, %f8))
-	EX_LD_FP(LOAD(ldd, %g1 + 0x28, %f10))
-	EX_LD_FP(LOAD(ldd, %g1 + 0x30, %f12))
-	EX_LD_FP(LOAD(ldd, %g1 + 0x38, %f14))
+	EX_LD_FP(LOAD(ldd, %g1 + 0x10, %f4), NG4_retl_o2_plus_o4_plus_64)
+	EX_LD_FP(LOAD(ldd, %g1 + 0x18, %f6), NG4_retl_o2_plus_o4_plus_64)
+	EX_LD_FP(LOAD(ldd, %g1 + 0x20, %f8), NG4_retl_o2_plus_o4_plus_64)
+	EX_LD_FP(LOAD(ldd, %g1 + 0x28, %f10), NG4_retl_o2_plus_o4_plus_64)
+	EX_LD_FP(LOAD(ldd, %g1 + 0x30, %f12), NG4_retl_o2_plus_o4_plus_64)
+	EX_LD_FP(LOAD(ldd, %g1 + 0x38, %f14), NG4_retl_o2_plus_o4_plus_64)
 	faligndata	%f0, %f2, %f16
-	EX_LD_FP(LOAD(ldd, %g1 + 0x40, %f0))
+	EX_LD_FP(LOAD(ldd, %g1 + 0x40, %f0), NG4_retl_o2_plus_o4_plus_64)
 	faligndata	%f2, %f4, %f18
 	add		%g1, 0x40, %g1
 	faligndata	%f4, %f6, %f20
@@ -235,14 +386,14 @@
 	faligndata	%f10, %f12, %f26
 	faligndata	%f12, %f14, %f28
 	faligndata	%f14, %f0, %f30
-	EX_ST_FP(STORE(std, %f16, %o0 + 0x00))
-	EX_ST_FP(STORE(std, %f18, %o0 + 0x08))
-	EX_ST_FP(STORE(std, %f20, %o0 + 0x10))
-	EX_ST_FP(STORE(std, %f22, %o0 + 0x18))
-	EX_ST_FP(STORE(std, %f24, %o0 + 0x20))
-	EX_ST_FP(STORE(std, %f26, %o0 + 0x28))
-	EX_ST_FP(STORE(std, %f28, %o0 + 0x30))
-	EX_ST_FP(STORE(std, %f30, %o0 + 0x38))
+	EX_ST_FP(STORE(std, %f16, %o0 + 0x00), NG4_retl_o2_plus_o4_plus_64)
+	EX_ST_FP(STORE(std, %f18, %o0 + 0x08), NG4_retl_o2_plus_o4_plus_56)
+	EX_ST_FP(STORE(std, %f20, %o0 + 0x10), NG4_retl_o2_plus_o4_plus_48)
+	EX_ST_FP(STORE(std, %f22, %o0 + 0x18), NG4_retl_o2_plus_o4_plus_40)
+	EX_ST_FP(STORE(std, %f24, %o0 + 0x20), NG4_retl_o2_plus_o4_plus_32)
+	EX_ST_FP(STORE(std, %f26, %o0 + 0x28), NG4_retl_o2_plus_o4_plus_24)
+	EX_ST_FP(STORE(std, %f28, %o0 + 0x30), NG4_retl_o2_plus_o4_plus_16)
+	EX_ST_FP(STORE(std, %f30, %o0 + 0x38), NG4_retl_o2_plus_o4_plus_8)
 	add		%o0, 0x40, %o0
 	bne,pt		%icc, 1b
 	 LOAD(prefetch, %g1 + 0x200, #n_reads_strong)
@@ -270,37 +421,38 @@
 	andncc		%o2, 0x20 - 1, %o5
 	be,pn		%icc, 2f
 	 sub		%o2, %o5, %o2
-1:	EX_LD(LOAD(ldx, %o1 + 0x00, %g1))
-	EX_LD(LOAD(ldx, %o1 + 0x08, %g2))
-	EX_LD(LOAD(ldx, %o1 + 0x10, GLOBAL_SPARE))
-	EX_LD(LOAD(ldx, %o1 + 0x18, %o4))
+1:	EX_LD(LOAD(ldx, %o1 + 0x00, %g1), NG4_retl_o2_plus_o5)
+	EX_LD(LOAD(ldx, %o1 + 0x08, %g2), NG4_retl_o2_plus_o5)
+	EX_LD(LOAD(ldx, %o1 + 0x10, GLOBAL_SPARE), NG4_retl_o2_plus_o5)
+	EX_LD(LOAD(ldx, %o1 + 0x18, %o4), NG4_retl_o2_plus_o5)
 	add		%o1, 0x20, %o1
 	subcc		%o5, 0x20, %o5
-	EX_ST(STORE(stx, %g1, %o0 + 0x00))
-	EX_ST(STORE(stx, %g2, %o0 + 0x08))
-	EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x10))
-	EX_ST(STORE(stx, %o4, %o0 + 0x18))
+	EX_ST(STORE(stx, %g1, %o0 + 0x00), NG4_retl_o2_plus_o5_plus_32)
+	EX_ST(STORE(stx, %g2, %o0 + 0x08), NG4_retl_o2_plus_o5_plus_24)
+	EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x10), NG4_retl_o2_plus_o5_plus_24)
+	EX_ST(STORE(stx, %o4, %o0 + 0x18), NG4_retl_o2_plus_o5_plus_8)
 	bne,pt		%icc, 1b
 	 add		%o0, 0x20, %o0
 2:	andcc		%o2, 0x18, %o5
 	be,pt		%icc, 3f
 	 sub		%o2, %o5, %o2
-1:	EX_LD(LOAD(ldx, %o1 + 0x00, %g1))
+
+1:	EX_LD(LOAD(ldx, %o1 + 0x00, %g1), NG4_retl_o2_plus_o5)
 	add		%o1, 0x08, %o1
 	add		%o0, 0x08, %o0
 	subcc		%o5, 0x08, %o5
 	bne,pt		%icc, 1b
-	 EX_ST(STORE(stx, %g1, %o0 - 0x08))
+	 EX_ST(STORE(stx, %g1, %o0 - 0x08), NG4_retl_o2_plus_o5_plus_8)
 3:	brz,pt		%o2, .Lexit
 	 cmp		%o2, 0x04
 	bl,pn		%icc, .Ltiny
 	 nop
-	EX_LD(LOAD(lduw, %o1 + 0x00, %g1))
+	EX_LD(LOAD(lduw, %o1 + 0x00, %g1), NG4_retl_o2)
 	add		%o1, 0x04, %o1
 	add		%o0, 0x04, %o0
 	subcc		%o2, 0x04, %o2
 	bne,pn		%icc, .Ltiny
-	 EX_ST(STORE(stw, %g1, %o0 - 0x04))
+	 EX_ST(STORE(stw, %g1, %o0 - 0x04), NG4_retl_o2_plus_4)
 	ba,a,pt		%icc, .Lexit
 .Lmedium_unaligned:
 	/* First get dest 8 byte aligned.  */
@@ -309,12 +461,12 @@
 	brz,pt		%g1, 2f
 	 sub		%o2, %g1, %o2
 
-1:	EX_LD(LOAD(ldub, %o1 + 0x00, %g2))
+1:	EX_LD(LOAD(ldub, %o1 + 0x00, %g2), NG4_retl_o2_plus_g1)
 	add		%o1, 1, %o1
 	subcc		%g1, 1, %g1
 	add		%o0, 1, %o0
 	bne,pt		%icc, 1b
-	 EX_ST(STORE(stb, %g2, %o0 - 0x01))
+	 EX_ST(STORE(stb, %g2, %o0 - 0x01), NG4_retl_o2_plus_g1_plus_1)
 2:
 	and		%o1, 0x7, %g1
 	brz,pn		%g1, .Lmedium_noprefetch
@@ -322,16 +474,16 @@
 	mov		64, %g2
 	sub		%g2, %g1, %g2
 	andn		%o1, 0x7, %o1
-	EX_LD(LOAD(ldx, %o1 + 0x00, %o4))
+	EX_LD(LOAD(ldx, %o1 + 0x00, %o4), NG4_retl_o2)
 	sllx		%o4, %g1, %o4
 	andn		%o2, 0x08 - 1, %o5
 	sub		%o2, %o5, %o2
-1:	EX_LD(LOAD(ldx, %o1 + 0x08, %g3))
+1:	EX_LD(LOAD(ldx, %o1 + 0x08, %g3), NG4_retl_o2_plus_o5)
 	add		%o1, 0x08, %o1
 	subcc		%o5, 0x08, %o5
 	srlx		%g3, %g2, GLOBAL_SPARE
 	or		GLOBAL_SPARE, %o4, GLOBAL_SPARE
-	EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x00))
+	EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x00), NG4_retl_o2_plus_o5_plus_8)
 	add		%o0, 0x08, %o0
 	bne,pt		%icc, 1b
 	 sllx		%g3, %g1, %o4
@@ -342,17 +494,17 @@
 	ba,pt		%icc, .Lsmall_unaligned
 
 .Ltiny:
-	EX_LD(LOAD(ldub, %o1 + 0x00, %g1))
+	EX_LD(LOAD(ldub, %o1 + 0x00, %g1), NG4_retl_o2)
 	subcc		%o2, 1, %o2
 	be,pn		%icc, .Lexit
-	 EX_ST(STORE(stb, %g1, %o0 + 0x00))
-	EX_LD(LOAD(ldub, %o1 + 0x01, %g1))
+	 EX_ST(STORE(stb, %g1, %o0 + 0x00), NG4_retl_o2_plus_1)
+	EX_LD(LOAD(ldub, %o1 + 0x01, %g1), NG4_retl_o2)
 	subcc		%o2, 1, %o2
 	be,pn		%icc, .Lexit
-	 EX_ST(STORE(stb, %g1, %o0 + 0x01))
-	EX_LD(LOAD(ldub, %o1 + 0x02, %g1))
+	 EX_ST(STORE(stb, %g1, %o0 + 0x01), NG4_retl_o2_plus_1)
+	EX_LD(LOAD(ldub, %o1 + 0x02, %g1), NG4_retl_o2)
 	ba,pt		%icc, .Lexit
-	 EX_ST(STORE(stb, %g1, %o0 + 0x02))
+	 EX_ST(STORE(stb, %g1, %o0 + 0x02), NG4_retl_o2)
 
 .Lsmall:
 	andcc		%g2, 0x3, %g0
@@ -360,22 +512,22 @@
 	 andn		%o2, 0x4 - 1, %o5
 	sub		%o2, %o5, %o2
 1:
-	EX_LD(LOAD(lduw, %o1 + 0x00, %g1))
+	EX_LD(LOAD(lduw, %o1 + 0x00, %g1), NG4_retl_o2_plus_o5)
 	add		%o1, 0x04, %o1
 	subcc		%o5, 0x04, %o5
 	add		%o0, 0x04, %o0
 	bne,pt		%icc, 1b
-	 EX_ST(STORE(stw, %g1, %o0 - 0x04))
+	 EX_ST(STORE(stw, %g1, %o0 - 0x04), NG4_retl_o2_plus_o5_plus_4)
 	brz,pt		%o2, .Lexit
 	 nop
 	ba,a,pt		%icc, .Ltiny
 
 .Lsmall_unaligned:
-1:	EX_LD(LOAD(ldub, %o1 + 0x00, %g1))
+1:	EX_LD(LOAD(ldub, %o1 + 0x00, %g1), NG4_retl_o2)
 	add		%o1, 1, %o1
 	add		%o0, 1, %o0
 	subcc		%o2, 1, %o2
 	bne,pt		%icc, 1b
-	 EX_ST(STORE(stb, %g1, %o0 - 0x01))
+	 EX_ST(STORE(stb, %g1, %o0 - 0x01), NG4_retl_o2_plus_1)
 	ba,a,pt		%icc, .Lexit
 	.size		FUNC_NAME, .-FUNC_NAME
diff --git a/arch/sparc/lib/NGcopy_from_user.S b/arch/sparc/lib/NGcopy_from_user.S
index 5d1e4d1..9cd42fc 100644
--- a/arch/sparc/lib/NGcopy_from_user.S
+++ b/arch/sparc/lib/NGcopy_from_user.S
@@ -3,11 +3,11 @@
  * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_LD(x)		\
+#define EX_LD(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __ret_one_asi;\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/NGcopy_to_user.S b/arch/sparc/lib/NGcopy_to_user.S
index ff630dc..5c358af 100644
--- a/arch/sparc/lib/NGcopy_to_user.S
+++ b/arch/sparc/lib/NGcopy_to_user.S
@@ -3,11 +3,11 @@
  * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_ST(x)		\
+#define EX_ST(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __ret_one_asi;\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/NGmemcpy.S b/arch/sparc/lib/NGmemcpy.S
index 96a14ca..d88c4ed 100644
--- a/arch/sparc/lib/NGmemcpy.S
+++ b/arch/sparc/lib/NGmemcpy.S
@@ -4,6 +4,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/asi.h>
 #include <asm/thread_info.h>
 #define GLOBAL_SPARE	%g7
@@ -27,15 +28,11 @@
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)	x
+#define EX_LD(x,y)	x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)	x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)	x
+#define EX_ST(x,y)	x
 #endif
 
 #ifndef LOAD
@@ -79,6 +76,92 @@
 	.register	%g3,#scratch
 
 	.text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+__restore_asi:
+	ret
+	wr	%g0, ASI_AIUS, %asi
+	 restore
+ENTRY(NG_ret_i2_plus_i4_plus_1)
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %i5, %i0
+ENDPROC(NG_ret_i2_plus_i4_plus_1)
+ENTRY(NG_ret_i2_plus_g1)
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1)
+ENTRY(NG_ret_i2_plus_g1_minus_8)
+	sub	%g1, 8, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_8)
+ENTRY(NG_ret_i2_plus_g1_minus_16)
+	sub	%g1, 16, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_16)
+ENTRY(NG_ret_i2_plus_g1_minus_24)
+	sub	%g1, 24, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_24)
+ENTRY(NG_ret_i2_plus_g1_minus_32)
+	sub	%g1, 32, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_32)
+ENTRY(NG_ret_i2_plus_g1_minus_40)
+	sub	%g1, 40, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_40)
+ENTRY(NG_ret_i2_plus_g1_minus_48)
+	sub	%g1, 48, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_48)
+ENTRY(NG_ret_i2_plus_g1_minus_56)
+	sub	%g1, 56, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_56)
+ENTRY(NG_ret_i2_plus_i4)
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %i4, %i0
+ENDPROC(NG_ret_i2_plus_i4)
+ENTRY(NG_ret_i2_plus_i4_minus_8)
+	sub	%i4, 8, %i4
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %i4, %i0
+ENDPROC(NG_ret_i2_plus_i4_minus_8)
+ENTRY(NG_ret_i2_plus_8)
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, 8, %i0
+ENDPROC(NG_ret_i2_plus_8)
+ENTRY(NG_ret_i2_plus_4)
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, 4, %i0
+ENDPROC(NG_ret_i2_plus_4)
+ENTRY(NG_ret_i2_plus_1)
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, 1, %i0
+ENDPROC(NG_ret_i2_plus_1)
+ENTRY(NG_ret_i2_plus_g1_plus_1)
+	add	%g1, 1, %g1
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_plus_1)
+ENTRY(NG_ret_i2)
+	ba,pt	%xcc, __restore_asi
+	 mov	%i2, %i0
+ENDPROC(NG_ret_i2)
+ENTRY(NG_ret_i2_and_7_plus_i4)
+	and	%i2, 7, %i2
+	ba,pt	%xcc, __restore_asi
+	 add	%i2, %i4, %i0
+ENDPROC(NG_ret_i2_and_7_plus_i4)
+#endif
+
 	.align		64
 
 	.globl	FUNC_NAME
@@ -126,8 +209,8 @@
 	sub		%g0, %i4, %i4	! bytes to align dst
 	sub		%i2, %i4, %i2
 1:	subcc		%i4, 1, %i4
-	EX_LD(LOAD(ldub, %i1, %g1))
-	EX_ST(STORE(stb, %g1, %o0))
+	EX_LD(LOAD(ldub, %i1, %g1), NG_ret_i2_plus_i4_plus_1)
+	EX_ST(STORE(stb, %g1, %o0), NG_ret_i2_plus_i4_plus_1)
 	add		%i1, 1, %i1
 	bne,pt		%XCC, 1b
 	add		%o0, 1, %o0
@@ -160,7 +243,7 @@
 	and		%i4, 0x7, GLOBAL_SPARE
 	sll		GLOBAL_SPARE, 3, GLOBAL_SPARE
 	mov		64, %i5
-	EX_LD(LOAD_TWIN(%i1, %g2, %g3))
+	EX_LD(LOAD_TWIN(%i1, %g2, %g3), NG_ret_i2_plus_g1)
 	sub		%i5, GLOBAL_SPARE, %i5
 	mov		16, %o4
 	mov		32, %o5
@@ -178,31 +261,31 @@
 	srlx		WORD3, PRE_SHIFT, TMP; \
 	or		WORD2, TMP, WORD2;
 
-8:	EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3))
+8:	EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3), NG_ret_i2_plus_g1)
 	MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1)
 	LOAD(prefetch, %i1 + %i3, #one_read)
 
-	EX_ST(STORE_INIT(%g2, %o0 + 0x00))
-	EX_ST(STORE_INIT(%g3, %o0 + 0x08))
+	EX_ST(STORE_INIT(%g2, %o0 + 0x00), NG_ret_i2_plus_g1)
+	EX_ST(STORE_INIT(%g3, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8)
 
-	EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3))
+	EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3), NG_ret_i2_plus_g1_minus_16)
 	MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1)
 
-	EX_ST(STORE_INIT(%o2, %o0 + 0x10))
-	EX_ST(STORE_INIT(%o3, %o0 + 0x18))
+	EX_ST(STORE_INIT(%o2, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16)
+	EX_ST(STORE_INIT(%o3, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24)
 
-	EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+	EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1_minus_32)
 	MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1)
 
-	EX_ST(STORE_INIT(%g2, %o0 + 0x20))
-	EX_ST(STORE_INIT(%g3, %o0 + 0x28))
+	EX_ST(STORE_INIT(%g2, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32)
+	EX_ST(STORE_INIT(%g3, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40)
 
-	EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3))
+	EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3), NG_ret_i2_plus_g1_minus_48)
 	add		%i1, 64, %i1
 	MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1)
 
-	EX_ST(STORE_INIT(%o2, %o0 + 0x30))
-	EX_ST(STORE_INIT(%o3, %o0 + 0x38))
+	EX_ST(STORE_INIT(%o2, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48)
+	EX_ST(STORE_INIT(%o3, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56)
 
 	subcc		%g1, 64, %g1
 	bne,pt		%XCC, 8b
@@ -211,31 +294,31 @@
 	ba,pt		%XCC, 60f
 	 add		%i1, %i4, %i1
 
-9:	EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3))
+9:	EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3), NG_ret_i2_plus_g1)
 	MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1)
 	LOAD(prefetch, %i1 + %i3, #one_read)
 
-	EX_ST(STORE_INIT(%g3, %o0 + 0x00))
-	EX_ST(STORE_INIT(%o2, %o0 + 0x08))
+	EX_ST(STORE_INIT(%g3, %o0 + 0x00), NG_ret_i2_plus_g1)
+	EX_ST(STORE_INIT(%o2, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8)
 
-	EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3))
+	EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3), NG_ret_i2_plus_g1_minus_16)
 	MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1)
 
-	EX_ST(STORE_INIT(%o3, %o0 + 0x10))
-	EX_ST(STORE_INIT(%g2, %o0 + 0x18))
+	EX_ST(STORE_INIT(%o3, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16)
+	EX_ST(STORE_INIT(%g2, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24)
 
-	EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+	EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1_minus_32)
 	MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1)
 
-	EX_ST(STORE_INIT(%g3, %o0 + 0x20))
-	EX_ST(STORE_INIT(%o2, %o0 + 0x28))
+	EX_ST(STORE_INIT(%g3, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32)
+	EX_ST(STORE_INIT(%o2, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40)
 
-	EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3))
+	EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3), NG_ret_i2_plus_g1_minus_48)
 	add		%i1, 64, %i1
 	MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1)
 
-	EX_ST(STORE_INIT(%o3, %o0 + 0x30))
-	EX_ST(STORE_INIT(%g2, %o0 + 0x38))
+	EX_ST(STORE_INIT(%o3, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48)
+	EX_ST(STORE_INIT(%g2, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56)
 
 	subcc		%g1, 64, %g1
 	bne,pt		%XCC, 9b
@@ -249,25 +332,25 @@
 	 * one twin load ahead, then add 8 back into source when
 	 * we finish the loop.
 	 */
-	EX_LD(LOAD_TWIN(%i1, %o4, %o5))
+	EX_LD(LOAD_TWIN(%i1, %o4, %o5), NG_ret_i2_plus_g1)
 	mov	16, %o7
 	mov	32, %g2
 	mov	48, %g3
 	mov	64, %o1
-1:	EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+1:	EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1)
 	LOAD(prefetch, %i1 + %o1, #one_read)
-	EX_ST(STORE_INIT(%o5, %o0 + 0x00))	! initializes cache line
-	EX_ST(STORE_INIT(%o2, %o0 + 0x08))
-	EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5))
-	EX_ST(STORE_INIT(%o3, %o0 + 0x10))
-	EX_ST(STORE_INIT(%o4, %o0 + 0x18))
-	EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3))
-	EX_ST(STORE_INIT(%o5, %o0 + 0x20))
-	EX_ST(STORE_INIT(%o2, %o0 + 0x28))
-	EX_LD(LOAD_TWIN(%i1 + %o1, %o4, %o5))
+	EX_ST(STORE_INIT(%o5, %o0 + 0x00), NG_ret_i2_plus_g1)	! initializes cache line
+	EX_ST(STORE_INIT(%o2, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8)
+	EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5), NG_ret_i2_plus_g1_minus_16)
+	EX_ST(STORE_INIT(%o3, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16)
+	EX_ST(STORE_INIT(%o4, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24)
+	EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3), NG_ret_i2_plus_g1_minus_32)
+	EX_ST(STORE_INIT(%o5, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32)
+	EX_ST(STORE_INIT(%o2, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40)
+	EX_LD(LOAD_TWIN(%i1 + %o1, %o4, %o5), NG_ret_i2_plus_g1_minus_48)
 	add		%i1, 64, %i1
-	EX_ST(STORE_INIT(%o3, %o0 + 0x30))
-	EX_ST(STORE_INIT(%o4, %o0 + 0x38))
+	EX_ST(STORE_INIT(%o3, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48)
+	EX_ST(STORE_INIT(%o4, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56)
 	subcc		%g1, 64, %g1
 	bne,pt		%XCC, 1b
 	 add		%o0, 64, %o0
@@ -282,20 +365,20 @@
 	mov	32, %g2
 	mov	48, %g3
 	mov	64, %o1
-1:	EX_LD(LOAD_TWIN(%i1 + %g0, %o4, %o5))
-	EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+1:	EX_LD(LOAD_TWIN(%i1 + %g0, %o4, %o5), NG_ret_i2_plus_g1)
+	EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1)
 	LOAD(prefetch, %i1 + %o1, #one_read)
-	EX_ST(STORE_INIT(%o4, %o0 + 0x00))	! initializes cache line
-	EX_ST(STORE_INIT(%o5, %o0 + 0x08))
-	EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5))
-	EX_ST(STORE_INIT(%o2, %o0 + 0x10))
-	EX_ST(STORE_INIT(%o3, %o0 + 0x18))
-	EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3))
+	EX_ST(STORE_INIT(%o4, %o0 + 0x00), NG_ret_i2_plus_g1)	! initializes cache line
+	EX_ST(STORE_INIT(%o5, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8)
+	EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5), NG_ret_i2_plus_g1_minus_16)
+	EX_ST(STORE_INIT(%o2, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16)
+	EX_ST(STORE_INIT(%o3, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24)
+	EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3), NG_ret_i2_plus_g1_minus_32)
 	add	%i1, 64, %i1
-	EX_ST(STORE_INIT(%o4, %o0 + 0x20))
-	EX_ST(STORE_INIT(%o5, %o0 + 0x28))
-	EX_ST(STORE_INIT(%o2, %o0 + 0x30))
-	EX_ST(STORE_INIT(%o3, %o0 + 0x38))
+	EX_ST(STORE_INIT(%o4, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32)
+	EX_ST(STORE_INIT(%o5, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40)
+	EX_ST(STORE_INIT(%o2, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48)
+	EX_ST(STORE_INIT(%o3, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56)
 	subcc	%g1, 64, %g1
 	bne,pt	%XCC, 1b
 	 add	%o0, 64, %o0
@@ -321,28 +404,28 @@
 	andn		%i2, 0xf, %i4
 	and		%i2, 0xf, %i2
 1:	subcc		%i4, 0x10, %i4
-	EX_LD(LOAD(ldx, %i1, %o4))
+	EX_LD(LOAD(ldx, %i1, %o4), NG_ret_i2_plus_i4)
 	add		%i1, 0x08, %i1
-	EX_LD(LOAD(ldx, %i1, %g1))
+	EX_LD(LOAD(ldx, %i1, %g1), NG_ret_i2_plus_i4)
 	sub		%i1, 0x08, %i1
-	EX_ST(STORE(stx, %o4, %i1 + %i3))
+	EX_ST(STORE(stx, %o4, %i1 + %i3), NG_ret_i2_plus_i4)
 	add		%i1, 0x8, %i1
-	EX_ST(STORE(stx, %g1, %i1 + %i3))
+	EX_ST(STORE(stx, %g1, %i1 + %i3), NG_ret_i2_plus_i4_minus_8)
 	bgu,pt		%XCC, 1b
 	 add		%i1, 0x8, %i1
 73:	andcc		%i2, 0x8, %g0
 	be,pt		%XCC, 1f
 	 nop
 	sub		%i2, 0x8, %i2
-	EX_LD(LOAD(ldx, %i1, %o4))
-	EX_ST(STORE(stx, %o4, %i1 + %i3))
+	EX_LD(LOAD(ldx, %i1, %o4), NG_ret_i2_plus_8)
+	EX_ST(STORE(stx, %o4, %i1 + %i3), NG_ret_i2_plus_8)
 	add		%i1, 0x8, %i1
 1:	andcc		%i2, 0x4, %g0
 	be,pt		%XCC, 1f
 	 nop
 	sub		%i2, 0x4, %i2
-	EX_LD(LOAD(lduw, %i1, %i5))
-	EX_ST(STORE(stw, %i5, %i1 + %i3))
+	EX_LD(LOAD(lduw, %i1, %i5), NG_ret_i2_plus_4)
+	EX_ST(STORE(stw, %i5, %i1 + %i3), NG_ret_i2_plus_4)
 	add		%i1, 0x4, %i1
 1:	cmp		%i2, 0
 	be,pt		%XCC, 85f
@@ -358,8 +441,8 @@
 	sub		%i2, %g1, %i2
 
 1:	subcc		%g1, 1, %g1
-	EX_LD(LOAD(ldub, %i1, %i5))
-	EX_ST(STORE(stb, %i5, %i1 + %i3))
+	EX_LD(LOAD(ldub, %i1, %i5), NG_ret_i2_plus_g1_plus_1)
+	EX_ST(STORE(stb, %i5, %i1 + %i3), NG_ret_i2_plus_g1_plus_1)
 	bgu,pt		%icc, 1b
 	 add		%i1, 1, %i1
 
@@ -375,16 +458,16 @@
 
 8:	mov		64, %i3
 	andn		%i1, 0x7, %i1
-	EX_LD(LOAD(ldx, %i1, %g2))
+	EX_LD(LOAD(ldx, %i1, %g2), NG_ret_i2)
 	sub		%i3, %g1, %i3
 	andn		%i2, 0x7, %i4
 	sllx		%g2, %g1, %g2
 1:	add		%i1, 0x8, %i1
-	EX_LD(LOAD(ldx, %i1, %g3))
+	EX_LD(LOAD(ldx, %i1, %g3), NG_ret_i2_and_7_plus_i4)
 	subcc		%i4, 0x8, %i4
 	srlx		%g3, %i3, %i5
 	or		%i5, %g2, %i5
-	EX_ST(STORE(stx, %i5, %o0))
+	EX_ST(STORE(stx, %i5, %o0), NG_ret_i2_and_7_plus_i4)
 	add		%o0, 0x8, %o0
 	bgu,pt		%icc, 1b
 	 sllx		%g3, %g1, %g2
@@ -404,8 +487,8 @@
 
 1:
 	subcc		%i2, 4, %i2
-	EX_LD(LOAD(lduw, %i1, %g1))
-	EX_ST(STORE(stw, %g1, %i1 + %i3))
+	EX_LD(LOAD(lduw, %i1, %g1), NG_ret_i2_plus_4)
+	EX_ST(STORE(stw, %g1, %i1 + %i3), NG_ret_i2_plus_4)
 	bgu,pt		%XCC, 1b
 	 add		%i1, 4, %i1
 
@@ -415,8 +498,8 @@
 	.align		32
 90:
 	subcc		%i2, 1, %i2
-	EX_LD(LOAD(ldub, %i1, %g1))
-	EX_ST(STORE(stb, %g1, %i1 + %i3))
+	EX_LD(LOAD(ldub, %i1, %g1), NG_ret_i2_plus_1)
+	EX_ST(STORE(stb, %g1, %i1 + %i3), NG_ret_i2_plus_1)
 	bgu,pt		%XCC, 90b
 	 add		%i1, 1, %i1
 	ret
diff --git a/arch/sparc/lib/U1copy_from_user.S b/arch/sparc/lib/U1copy_from_user.S
index ecc5692..bb6ff73 100644
--- a/arch/sparc/lib/U1copy_from_user.S
+++ b/arch/sparc/lib/U1copy_from_user.S
@@ -3,19 +3,19 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#define EX_LD(x)		\
+#define EX_LD(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one;	\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
-#define EX_LD_FP(x)		\
+#define EX_LD_FP(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_fp;\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/U1copy_to_user.S b/arch/sparc/lib/U1copy_to_user.S
index 9eea392..ed92ce7 100644
--- a/arch/sparc/lib/U1copy_to_user.S
+++ b/arch/sparc/lib/U1copy_to_user.S
@@ -3,19 +3,19 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#define EX_ST(x)		\
+#define EX_ST(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one;	\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
-#define EX_ST_FP(x)		\
+#define EX_ST_FP(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_fp;\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/U1memcpy.S b/arch/sparc/lib/U1memcpy.S
index 3e6209e..f30d2ab 100644
--- a/arch/sparc/lib/U1memcpy.S
+++ b/arch/sparc/lib/U1memcpy.S
@@ -5,6 +5,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/visasm.h>
 #include <asm/asi.h>
 #define GLOBAL_SPARE	g7
@@ -23,21 +24,17 @@
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)	x
+#define EX_LD(x,y)	x
 #endif
 #ifndef EX_LD_FP
-#define EX_LD_FP(x)	x
+#define EX_LD_FP(x,y)	x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)	x
+#define EX_ST(x,y)	x
 #endif
 #ifndef EX_ST_FP
-#define EX_ST_FP(x)	x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)	x
+#define EX_ST_FP(x,y)	x
 #endif
 
 #ifndef LOAD
@@ -78,53 +75,169 @@
 	faligndata		%f7, %f8, %f60;			\
 	faligndata		%f8, %f9, %f62;
 
-#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt)	\
-	EX_LD_FP(LOAD_BLK(%src, %fdest));				\
-	EX_ST_FP(STORE_BLK(%fsrc, %dest));				\
-	add			%src, 0x40, %src;		\
-	subcc			%len, 0x40, %len;		\
-	be,pn			%xcc, jmptgt;			\
-	 add			%dest, 0x40, %dest;		\
+#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, jmptgt)			\
+	EX_LD_FP(LOAD_BLK(%src, %fdest), U1_gs_80_fp);			\
+	EX_ST_FP(STORE_BLK(%fsrc, %dest), U1_gs_80_fp);			\
+	add			%src, 0x40, %src;			\
+	subcc			%GLOBAL_SPARE, 0x40, %GLOBAL_SPARE;	\
+	be,pn			%xcc, jmptgt;				\
+	 add			%dest, 0x40, %dest;			\
 
-#define LOOP_CHUNK1(src, dest, len, branch_dest)		\
-	MAIN_LOOP_CHUNK(src, dest, f0,  f48, len, branch_dest)
-#define LOOP_CHUNK2(src, dest, len, branch_dest)		\
-	MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest)
-#define LOOP_CHUNK3(src, dest, len, branch_dest)		\
-	MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest)
+#define LOOP_CHUNK1(src, dest, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f0,  f48, branch_dest)
+#define LOOP_CHUNK2(src, dest, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f16, f48, branch_dest)
+#define LOOP_CHUNK3(src, dest, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f32, f48, branch_dest)
 
 #define DO_SYNC			membar	#Sync;
 #define STORE_SYNC(dest, fsrc)				\
-	EX_ST_FP(STORE_BLK(%fsrc, %dest));			\
+	EX_ST_FP(STORE_BLK(%fsrc, %dest), U1_gs_80_fp);	\
 	add			%dest, 0x40, %dest;	\
 	DO_SYNC
 
 #define STORE_JUMP(dest, fsrc, target)			\
-	EX_ST_FP(STORE_BLK(%fsrc, %dest));			\
+	EX_ST_FP(STORE_BLK(%fsrc, %dest), U1_gs_40_fp);	\
 	add			%dest, 0x40, %dest;	\
 	ba,pt			%xcc, target;		\
 	 nop;
 
-#define FINISH_VISCHUNK(dest, f0, f1, left)	\
-	subcc			%left, 8, %left;\
-	bl,pn			%xcc, 95f;	\
-	 faligndata		%f0, %f1, %f48;	\
-	EX_ST_FP(STORE(std, %f48, %dest));		\
+#define FINISH_VISCHUNK(dest, f0, f1)			\
+	subcc			%g3, 8, %g3;		\
+	bl,pn			%xcc, 95f;		\
+	 faligndata		%f0, %f1, %f48;		\
+	EX_ST_FP(STORE(std, %f48, %dest), U1_g3_8_fp);	\
 	add			%dest, 8, %dest;
 
-#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)	\
-	subcc			%left, 8, %left;	\
-	bl,pn			%xcc, 95f;		\
+#define UNEVEN_VISCHUNK_LAST(dest, f0, f1)	\
+	subcc			%g3, 8, %g3;	\
+	bl,pn			%xcc, 95f;	\
 	 fsrc2			%f0, %f1;
 
-#define UNEVEN_VISCHUNK(dest, f0, f1, left)		\
-	UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)	\
+#define UNEVEN_VISCHUNK(dest, f0, f1)		\
+	UNEVEN_VISCHUNK_LAST(dest, f0, f1)	\
 	ba,a,pt			%xcc, 93f;
 
 	.register	%g2,#scratch
 	.register	%g3,#scratch
 
 	.text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+ENTRY(U1_g1_1_fp)
+	VISExitHalf
+	add		%g1, 1, %g1
+	add		%g1, %g2, %g1
+	retl
+	 add		%g1, %o2, %o0
+ENDPROC(U1_g1_1_fp)
+ENTRY(U1_g2_0_fp)
+	VISExitHalf
+	retl
+	 add		%g2, %o2, %o0
+ENDPROC(U1_g2_0_fp)
+ENTRY(U1_g2_8_fp)
+	VISExitHalf
+	add		%g2, 8, %g2
+	retl
+	 add		%g2, %o2, %o0
+ENDPROC(U1_g2_8_fp)
+ENTRY(U1_gs_0_fp)
+	VISExitHalf
+	add		%GLOBAL_SPARE, %g3, %o0
+	retl
+	 add		%o0, %o2, %o0
+ENDPROC(U1_gs_0_fp)
+ENTRY(U1_gs_80_fp)
+	VISExitHalf
+	add		%GLOBAL_SPARE, 0x80, %GLOBAL_SPARE
+	add		%GLOBAL_SPARE, %g3, %o0
+	retl
+	 add		%o0, %o2, %o0
+ENDPROC(U1_gs_80_fp)
+ENTRY(U1_gs_40_fp)
+	VISExitHalf
+	add		%GLOBAL_SPARE, 0x40, %GLOBAL_SPARE
+	add		%GLOBAL_SPARE, %g3, %o0
+	retl
+	 add		%o0, %o2, %o0
+ENDPROC(U1_gs_40_fp)
+ENTRY(U1_g3_0_fp)
+	VISExitHalf
+	retl
+	 add		%g3, %o2, %o0
+ENDPROC(U1_g3_0_fp)
+ENTRY(U1_g3_8_fp)
+	VISExitHalf
+	add		%g3, 8, %g3
+	retl
+	 add		%g3, %o2, %o0
+ENDPROC(U1_g3_8_fp)
+ENTRY(U1_o2_0_fp)
+	VISExitHalf
+	retl
+	 mov		%o2, %o0
+ENDPROC(U1_o2_0_fp)
+ENTRY(U1_o2_1_fp)
+	VISExitHalf
+	retl
+	 add		%o2, 1, %o0
+ENDPROC(U1_o2_1_fp)
+ENTRY(U1_gs_0)
+	VISExitHalf
+	retl
+	 add		%GLOBAL_SPARE, %o2, %o0
+ENDPROC(U1_gs_0)
+ENTRY(U1_gs_8)
+	VISExitHalf
+	add		%GLOBAL_SPARE, %o2, %GLOBAL_SPARE
+	retl
+	 add		%GLOBAL_SPARE, 0x8, %o0
+ENDPROC(U1_gs_8)
+ENTRY(U1_gs_10)
+	VISExitHalf
+	add		%GLOBAL_SPARE, %o2, %GLOBAL_SPARE
+	retl
+	 add		%GLOBAL_SPARE, 0x10, %o0
+ENDPROC(U1_gs_10)
+ENTRY(U1_o2_0)
+	retl
+	 mov		%o2, %o0
+ENDPROC(U1_o2_0)
+ENTRY(U1_o2_8)
+	retl
+	 add		%o2, 8, %o0
+ENDPROC(U1_o2_8)
+ENTRY(U1_o2_4)
+	retl
+	 add		%o2, 4, %o0
+ENDPROC(U1_o2_4)
+ENTRY(U1_o2_1)
+	retl
+	 add		%o2, 1, %o0
+ENDPROC(U1_o2_1)
+ENTRY(U1_g1_0)
+	retl
+	 add		%g1, %o2, %o0
+ENDPROC(U1_g1_0)
+ENTRY(U1_g1_1)
+	add		%g1, 1, %g1
+	retl
+	 add		%g1, %o2, %o0
+ENDPROC(U1_g1_1)
+ENTRY(U1_gs_0_o2_adj)
+	and		%o2, 7, %o2
+	retl
+	 add		%GLOBAL_SPARE, %o2, %o0
+ENDPROC(U1_gs_0_o2_adj)
+ENTRY(U1_gs_8_o2_adj)
+	and		%o2, 7, %o2
+	add		%GLOBAL_SPARE, 8, %GLOBAL_SPARE
+	retl
+	 add		%GLOBAL_SPARE, %o2, %o0
+ENDPROC(U1_gs_8_o2_adj)
+#endif
+
 	.align		64
 
 	.globl		FUNC_NAME
@@ -166,8 +279,8 @@
 	 and		%g2, 0x38, %g2
 
 1:	subcc		%g1, 0x1, %g1
-	EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3))
-	EX_ST_FP(STORE(stb, %o3, %o1 + %GLOBAL_SPARE))
+	EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3), U1_g1_1_fp)
+	EX_ST_FP(STORE(stb, %o3, %o1 + %GLOBAL_SPARE), U1_g1_1_fp)
 	bgu,pt		%XCC, 1b
 	 add		%o1, 0x1, %o1
 
@@ -178,20 +291,20 @@
 	be,pt		%icc, 3f
 	 alignaddr	%o1, %g0, %o1
 
-	EX_LD_FP(LOAD(ldd, %o1, %f4))
-1:	EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6))
+	EX_LD_FP(LOAD(ldd, %o1, %f4), U1_g2_0_fp)
+1:	EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6), U1_g2_0_fp)
 	add		%o1, 0x8, %o1
 	subcc		%g2, 0x8, %g2
 	faligndata	%f4, %f6, %f0
-	EX_ST_FP(STORE(std, %f0, %o0))
+	EX_ST_FP(STORE(std, %f0, %o0), U1_g2_8_fp)
 	be,pn		%icc, 3f
 	 add		%o0, 0x8, %o0
 
-	EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4), U1_g2_0_fp)
 	add		%o1, 0x8, %o1
 	subcc		%g2, 0x8, %g2
 	faligndata	%f6, %f4, %f0
-	EX_ST_FP(STORE(std, %f0, %o0))
+	EX_ST_FP(STORE(std, %f0, %o0), U1_g2_8_fp)
 	bne,pt		%icc, 1b
 	 add		%o0, 0x8, %o0
 
@@ -214,13 +327,13 @@
 	add		%g1, %GLOBAL_SPARE, %g1
 	subcc		%o2, %g3, %o2
 
-	EX_LD_FP(LOAD_BLK(%o1, %f0))
+	EX_LD_FP(LOAD_BLK(%o1, %f0), U1_gs_0_fp)
 	add		%o1, 0x40, %o1
 	add		%g1, %g3, %g1
-	EX_LD_FP(LOAD_BLK(%o1, %f16))
+	EX_LD_FP(LOAD_BLK(%o1, %f16), U1_gs_0_fp)
 	add		%o1, 0x40, %o1
 	sub		%GLOBAL_SPARE, 0x80, %GLOBAL_SPARE
-	EX_LD_FP(LOAD_BLK(%o1, %f32))
+	EX_LD_FP(LOAD_BLK(%o1, %f32), U1_gs_80_fp)
 	add		%o1, 0x40, %o1
 
 	/* There are 8 instances of the unrolled loop,
@@ -240,11 +353,11 @@
 
 	.align		64
 1:	FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
-	LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+	LOOP_CHUNK1(o1, o0, 1f)
 	FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
-	LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+	LOOP_CHUNK2(o1, o0, 2f)
 	FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
-	LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+	LOOP_CHUNK3(o1, o0, 3f)
 	ba,pt		%xcc, 1b+4
 	 faligndata	%f0, %f2, %f48
 1:	FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
@@ -261,11 +374,11 @@
 	STORE_JUMP(o0, f48, 56f)
 
 1:	FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
-	LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+	LOOP_CHUNK1(o1, o0, 1f)
 	FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
-	LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+	LOOP_CHUNK2(o1, o0, 2f)
 	FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
-	LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+	LOOP_CHUNK3(o1, o0, 3f)
 	ba,pt		%xcc, 1b+4
 	 faligndata	%f2, %f4, %f48
 1:	FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
@@ -282,11 +395,11 @@
 	STORE_JUMP(o0, f48, 57f)
 
 1:	FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
-	LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+	LOOP_CHUNK1(o1, o0, 1f)
 	FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
-	LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+	LOOP_CHUNK2(o1, o0, 2f)
 	FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
-	LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+	LOOP_CHUNK3(o1, o0, 3f)
 	ba,pt		%xcc, 1b+4
 	 faligndata	%f4, %f6, %f48
 1:	FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
@@ -303,11 +416,11 @@
 	STORE_JUMP(o0, f48, 58f)
 
 1:	FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
-	LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+	LOOP_CHUNK1(o1, o0, 1f)
 	FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
-	LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+	LOOP_CHUNK2(o1, o0, 2f)
 	FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) 
-	LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+	LOOP_CHUNK3(o1, o0, 3f)
 	ba,pt		%xcc, 1b+4
 	 faligndata	%f6, %f8, %f48
 1:	FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
@@ -324,11 +437,11 @@
 	STORE_JUMP(o0, f48, 59f)
 
 1:	FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
-	LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+	LOOP_CHUNK1(o1, o0, 1f)
 	FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
-	LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+	LOOP_CHUNK2(o1, o0, 2f)
 	FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
-	LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+	LOOP_CHUNK3(o1, o0, 3f)
 	ba,pt		%xcc, 1b+4
 	 faligndata	%f8, %f10, %f48
 1:	FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
@@ -345,11 +458,11 @@
 	STORE_JUMP(o0, f48, 60f)
 
 1:	FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
-	LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+	LOOP_CHUNK1(o1, o0, 1f)
 	FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
-	LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+	LOOP_CHUNK2(o1, o0, 2f)
 	FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
-	LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+	LOOP_CHUNK3(o1, o0, 3f)
 	ba,pt		%xcc, 1b+4
 	 faligndata	%f10, %f12, %f48
 1:	FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
@@ -366,11 +479,11 @@
 	STORE_JUMP(o0, f48, 61f)
 
 1:	FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
-	LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+	LOOP_CHUNK1(o1, o0, 1f)
 	FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
-	LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+	LOOP_CHUNK2(o1, o0, 2f)
 	FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
-	LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+	LOOP_CHUNK3(o1, o0, 3f)
 	ba,pt		%xcc, 1b+4
 	 faligndata	%f12, %f14, %f48
 1:	FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
@@ -387,11 +500,11 @@
 	STORE_JUMP(o0, f48, 62f)
 
 1:	FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
-	LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+	LOOP_CHUNK1(o1, o0, 1f)
 	FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
-	LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+	LOOP_CHUNK2(o1, o0, 2f)
 	FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
-	LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+	LOOP_CHUNK3(o1, o0, 3f)
 	ba,pt		%xcc, 1b+4
 	 faligndata	%f14, %f16, %f48
 1:	FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
@@ -407,53 +520,53 @@
 	FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
 	STORE_JUMP(o0, f48, 63f)
 
-40:	FINISH_VISCHUNK(o0, f0,  f2,  g3)
-41:	FINISH_VISCHUNK(o0, f2,  f4,  g3)
-42:	FINISH_VISCHUNK(o0, f4,  f6,  g3)
-43:	FINISH_VISCHUNK(o0, f6,  f8,  g3)
-44:	FINISH_VISCHUNK(o0, f8,  f10, g3)
-45:	FINISH_VISCHUNK(o0, f10, f12, g3)
-46:	FINISH_VISCHUNK(o0, f12, f14, g3)
-47:	UNEVEN_VISCHUNK(o0, f14, f0,  g3)
-48:	FINISH_VISCHUNK(o0, f16, f18, g3)
-49:	FINISH_VISCHUNK(o0, f18, f20, g3)
-50:	FINISH_VISCHUNK(o0, f20, f22, g3)
-51:	FINISH_VISCHUNK(o0, f22, f24, g3)
-52:	FINISH_VISCHUNK(o0, f24, f26, g3)
-53:	FINISH_VISCHUNK(o0, f26, f28, g3)
-54:	FINISH_VISCHUNK(o0, f28, f30, g3)
-55:	UNEVEN_VISCHUNK(o0, f30, f0,  g3)
-56:	FINISH_VISCHUNK(o0, f32, f34, g3)
-57:	FINISH_VISCHUNK(o0, f34, f36, g3)
-58:	FINISH_VISCHUNK(o0, f36, f38, g3)
-59:	FINISH_VISCHUNK(o0, f38, f40, g3)
-60:	FINISH_VISCHUNK(o0, f40, f42, g3)
-61:	FINISH_VISCHUNK(o0, f42, f44, g3)
-62:	FINISH_VISCHUNK(o0, f44, f46, g3)
-63:	UNEVEN_VISCHUNK_LAST(o0, f46, f0,  g3)
+40:	FINISH_VISCHUNK(o0, f0,  f2)
+41:	FINISH_VISCHUNK(o0, f2,  f4)
+42:	FINISH_VISCHUNK(o0, f4,  f6)
+43:	FINISH_VISCHUNK(o0, f6,  f8)
+44:	FINISH_VISCHUNK(o0, f8,  f10)
+45:	FINISH_VISCHUNK(o0, f10, f12)
+46:	FINISH_VISCHUNK(o0, f12, f14)
+47:	UNEVEN_VISCHUNK(o0, f14, f0)
+48:	FINISH_VISCHUNK(o0, f16, f18)
+49:	FINISH_VISCHUNK(o0, f18, f20)
+50:	FINISH_VISCHUNK(o0, f20, f22)
+51:	FINISH_VISCHUNK(o0, f22, f24)
+52:	FINISH_VISCHUNK(o0, f24, f26)
+53:	FINISH_VISCHUNK(o0, f26, f28)
+54:	FINISH_VISCHUNK(o0, f28, f30)
+55:	UNEVEN_VISCHUNK(o0, f30, f0)
+56:	FINISH_VISCHUNK(o0, f32, f34)
+57:	FINISH_VISCHUNK(o0, f34, f36)
+58:	FINISH_VISCHUNK(o0, f36, f38)
+59:	FINISH_VISCHUNK(o0, f38, f40)
+60:	FINISH_VISCHUNK(o0, f40, f42)
+61:	FINISH_VISCHUNK(o0, f42, f44)
+62:	FINISH_VISCHUNK(o0, f44, f46)
+63:	UNEVEN_VISCHUNK_LAST(o0, f46, f0)
 
-93:	EX_LD_FP(LOAD(ldd, %o1, %f2))
+93:	EX_LD_FP(LOAD(ldd, %o1, %f2), U1_g3_0_fp)
 	add		%o1, 8, %o1
 	subcc		%g3, 8, %g3
 	faligndata	%f0, %f2, %f8
-	EX_ST_FP(STORE(std, %f8, %o0))
+	EX_ST_FP(STORE(std, %f8, %o0), U1_g3_8_fp)
 	bl,pn		%xcc, 95f
 	 add		%o0, 8, %o0
-	EX_LD_FP(LOAD(ldd, %o1, %f0))
+	EX_LD_FP(LOAD(ldd, %o1, %f0), U1_g3_0_fp)
 	add		%o1, 8, %o1
 	subcc		%g3, 8, %g3
 	faligndata	%f2, %f0, %f8
-	EX_ST_FP(STORE(std, %f8, %o0))
+	EX_ST_FP(STORE(std, %f8, %o0), U1_g3_8_fp)
 	bge,pt		%xcc, 93b
 	 add		%o0, 8, %o0
 
 95:	brz,pt		%o2, 2f
 	 mov		%g1, %o1
 
-1:	EX_LD_FP(LOAD(ldub, %o1, %o3))
+1:	EX_LD_FP(LOAD(ldub, %o1, %o3), U1_o2_0_fp)
 	add		%o1, 1, %o1
 	subcc		%o2, 1, %o2
-	EX_ST_FP(STORE(stb, %o3, %o0))
+	EX_ST_FP(STORE(stb, %o3, %o0), U1_o2_1_fp)
 	bne,pt		%xcc, 1b
 	 add		%o0, 1, %o0
 
@@ -469,27 +582,27 @@
 
 72:	andn		%o2, 0xf, %GLOBAL_SPARE
 	and		%o2, 0xf, %o2
-1:	EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
-	EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
+1:	EX_LD(LOAD(ldx, %o1 + 0x00, %o5), U1_gs_0)
+	EX_LD(LOAD(ldx, %o1 + 0x08, %g1), U1_gs_0)
 	subcc		%GLOBAL_SPARE, 0x10, %GLOBAL_SPARE
-	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	EX_ST(STORE(stx, %o5, %o1 + %o3), U1_gs_10)
 	add		%o1, 0x8, %o1
-	EX_ST(STORE(stx, %g1, %o1 + %o3))
+	EX_ST(STORE(stx, %g1, %o1 + %o3), U1_gs_8)
 	bgu,pt		%XCC, 1b
 	 add		%o1, 0x8, %o1
 73:	andcc		%o2, 0x8, %g0
 	be,pt		%XCC, 1f
 	 nop
-	EX_LD(LOAD(ldx, %o1, %o5))
+	EX_LD(LOAD(ldx, %o1, %o5), U1_o2_0)
 	sub		%o2, 0x8, %o2
-	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	EX_ST(STORE(stx, %o5, %o1 + %o3), U1_o2_8)
 	add		%o1, 0x8, %o1
 1:	andcc		%o2, 0x4, %g0
 	be,pt		%XCC, 1f
 	 nop
-	EX_LD(LOAD(lduw, %o1, %o5))
+	EX_LD(LOAD(lduw, %o1, %o5), U1_o2_0)
 	sub		%o2, 0x4, %o2
-	EX_ST(STORE(stw, %o5, %o1 + %o3))
+	EX_ST(STORE(stw, %o5, %o1 + %o3), U1_o2_4)
 	add		%o1, 0x4, %o1
 1:	cmp		%o2, 0
 	be,pt		%XCC, 85f
@@ -503,9 +616,9 @@
 	 sub		%g0, %g1, %g1
 	sub		%o2, %g1, %o2
 
-1:	EX_LD(LOAD(ldub, %o1, %o5))
+1:	EX_LD(LOAD(ldub, %o1, %o5), U1_g1_0)
 	subcc		%g1, 1, %g1
-	EX_ST(STORE(stb, %o5, %o1 + %o3))
+	EX_ST(STORE(stb, %o5, %o1 + %o3), U1_g1_1)
 	bgu,pt		%icc, 1b
 	 add		%o1, 1, %o1
 
@@ -521,16 +634,16 @@
 
 8:	mov		64, %o3
 	andn		%o1, 0x7, %o1
-	EX_LD(LOAD(ldx, %o1, %g2))
+	EX_LD(LOAD(ldx, %o1, %g2), U1_o2_0)
 	sub		%o3, %g1, %o3
 	andn		%o2, 0x7, %GLOBAL_SPARE
 	sllx		%g2, %g1, %g2
-1:	EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+1:	EX_LD(LOAD(ldx, %o1 + 0x8, %g3), U1_gs_0_o2_adj)
 	subcc		%GLOBAL_SPARE, 0x8, %GLOBAL_SPARE
 	add		%o1, 0x8, %o1
 	srlx		%g3, %o3, %o5
 	or		%o5, %g2, %o5
-	EX_ST(STORE(stx, %o5, %o0))
+	EX_ST(STORE(stx, %o5, %o0), U1_gs_8_o2_adj)
 	add		%o0, 0x8, %o0
 	bgu,pt		%icc, 1b
 	 sllx		%g3, %g1, %g2
@@ -548,9 +661,9 @@
 	bne,pn		%XCC, 90f
 	 sub		%o0, %o1, %o3
 
-1:	EX_LD(LOAD(lduw, %o1, %g1))
+1:	EX_LD(LOAD(lduw, %o1, %g1), U1_o2_0)
 	subcc		%o2, 4, %o2
-	EX_ST(STORE(stw, %g1, %o1 + %o3))
+	EX_ST(STORE(stw, %g1, %o1 + %o3), U1_o2_4)
 	bgu,pt		%XCC, 1b
 	 add		%o1, 4, %o1
 
@@ -558,9 +671,9 @@
 	 mov		EX_RETVAL(%o4), %o0
 
 	.align		32
-90:	EX_LD(LOAD(ldub, %o1, %g1))
+90:	EX_LD(LOAD(ldub, %o1, %g1), U1_o2_0)
 	subcc		%o2, 1, %o2
-	EX_ST(STORE(stb, %g1, %o1 + %o3))
+	EX_ST(STORE(stb, %g1, %o1 + %o3), U1_o2_1)
 	bgu,pt		%XCC, 90b
 	 add		%o1, 1, %o1
 	retl
diff --git a/arch/sparc/lib/U3copy_from_user.S b/arch/sparc/lib/U3copy_from_user.S
index 88ad73d..db73010 100644
--- a/arch/sparc/lib/U3copy_from_user.S
+++ b/arch/sparc/lib/U3copy_from_user.S
@@ -3,19 +3,19 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#define EX_LD(x)		\
+#define EX_LD(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one;	\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
-#define EX_LD_FP(x)		\
+#define EX_LD_FP(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_fp;\
+	.word 98b, y##_fp;	\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/U3copy_to_user.S b/arch/sparc/lib/U3copy_to_user.S
index 845139d..c4ee858 100644
--- a/arch/sparc/lib/U3copy_to_user.S
+++ b/arch/sparc/lib/U3copy_to_user.S
@@ -3,19 +3,19 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#define EX_ST(x)		\
+#define EX_ST(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one;	\
+	.word 98b, y;		\
 	.text;			\
 	.align 4;
 
-#define EX_ST_FP(x)		\
+#define EX_ST_FP(x,y)		\
 98:	x;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one_fp;\
+	.word 98b, y##_fp;	\
 	.text;			\
 	.align 4;
 
diff --git a/arch/sparc/lib/U3memcpy.S b/arch/sparc/lib/U3memcpy.S
index 491ee69..54f9870 100644
--- a/arch/sparc/lib/U3memcpy.S
+++ b/arch/sparc/lib/U3memcpy.S
@@ -4,6 +4,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/visasm.h>
 #include <asm/asi.h>
 #define GLOBAL_SPARE	%g7
@@ -22,21 +23,17 @@
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)	x
+#define EX_LD(x,y)	x
 #endif
 #ifndef EX_LD_FP
-#define EX_LD_FP(x)	x
+#define EX_LD_FP(x,y)	x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)	x
+#define EX_ST(x,y)	x
 #endif
 #ifndef EX_ST_FP
-#define EX_ST_FP(x)	x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)	x
+#define EX_ST_FP(x,y)	x
 #endif
 
 #ifndef LOAD
@@ -77,6 +74,87 @@
 	 */
 
 	.text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+__restore_fp:
+	VISExitHalf
+	retl
+	 nop
+ENTRY(U3_retl_o2_plus_g2_plus_g1_plus_1_fp)
+	add	%g1, 1, %g1
+	add	%g2, %g1, %g2
+	ba,pt	%xcc, __restore_fp
+	 add	%o2, %g2, %o0
+ENDPROC(U3_retl_o2_plus_g2_plus_g1_plus_1_fp)
+ENTRY(U3_retl_o2_plus_g2_fp)
+	ba,pt	%xcc, __restore_fp
+	 add	%o2, %g2, %o0
+ENDPROC(U3_retl_o2_plus_g2_fp)
+ENTRY(U3_retl_o2_plus_g2_plus_8_fp)
+	add	%g2, 8, %g2
+	ba,pt	%xcc, __restore_fp
+	 add	%o2, %g2, %o0
+ENDPROC(U3_retl_o2_plus_g2_plus_8_fp)
+ENTRY(U3_retl_o2)
+	retl
+	 mov	%o2, %o0
+ENDPROC(U3_retl_o2)
+ENTRY(U3_retl_o2_plus_1)
+	retl
+	 add	%o2, 1, %o0
+ENDPROC(U3_retl_o2_plus_1)
+ENTRY(U3_retl_o2_plus_4)
+	retl
+	 add	%o2, 4, %o0
+ENDPROC(U3_retl_o2_plus_4)
+ENTRY(U3_retl_o2_plus_8)
+	retl
+	 add	%o2, 8, %o0
+ENDPROC(U3_retl_o2_plus_8)
+ENTRY(U3_retl_o2_plus_g1_plus_1)
+	add	%g1, 1, %g1
+	retl
+	 add	%o2, %g1, %o0
+ENDPROC(U3_retl_o2_plus_g1_plus_1)
+ENTRY(U3_retl_o2_fp)
+	ba,pt	%xcc, __restore_fp
+	 mov	%o2, %o0
+ENDPROC(U3_retl_o2_fp)
+ENTRY(U3_retl_o2_plus_o3_sll_6_plus_0x80_fp)
+	sll	%o3, 6, %o3
+	add	%o3, 0x80, %o3
+	ba,pt	%xcc, __restore_fp
+	 add	%o2, %o3, %o0
+ENDPROC(U3_retl_o2_plus_o3_sll_6_plus_0x80_fp)
+ENTRY(U3_retl_o2_plus_o3_sll_6_plus_0x40_fp)
+	sll	%o3, 6, %o3
+	add	%o3, 0x40, %o3
+	ba,pt	%xcc, __restore_fp
+	 add	%o2, %o3, %o0
+ENDPROC(U3_retl_o2_plus_o3_sll_6_plus_0x40_fp)
+ENTRY(U3_retl_o2_plus_GS_plus_0x10)
+	add	GLOBAL_SPARE, 0x10, GLOBAL_SPARE
+	retl
+	 add	%o2, GLOBAL_SPARE, %o0
+ENDPROC(U3_retl_o2_plus_GS_plus_0x10)
+ENTRY(U3_retl_o2_plus_GS_plus_0x08)
+	add	GLOBAL_SPARE, 0x08, GLOBAL_SPARE
+	retl
+	 add	%o2, GLOBAL_SPARE, %o0
+ENDPROC(U3_retl_o2_plus_GS_plus_0x08)
+ENTRY(U3_retl_o2_and_7_plus_GS)
+	and	%o2, 7, %o2
+	retl
+	 add	%o2, GLOBAL_SPARE, %o2
+ENDPROC(U3_retl_o2_and_7_plus_GS)
+ENTRY(U3_retl_o2_and_7_plus_GS_plus_8)
+	add	GLOBAL_SPARE, 8, GLOBAL_SPARE
+	and	%o2, 7, %o2
+	retl
+	 add	%o2, GLOBAL_SPARE, %o2
+ENDPROC(U3_retl_o2_and_7_plus_GS_plus_8)
+#endif
+
 	.align		64
 
 	/* The cheetah's flexible spine, oversized liver, enlarged heart,
@@ -126,8 +204,8 @@
 	 and		%g2, 0x38, %g2
 
 1:	subcc		%g1, 0x1, %g1
-	EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3))
-	EX_ST_FP(STORE(stb, %o3, %o1 + GLOBAL_SPARE))
+	EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3), U3_retl_o2_plus_g2_plus_g1_plus_1)
+	EX_ST_FP(STORE(stb, %o3, %o1 + GLOBAL_SPARE), U3_retl_o2_plus_g2_plus_g1_plus_1)
 	bgu,pt		%XCC, 1b
 	 add		%o1, 0x1, %o1
 
@@ -138,20 +216,20 @@
 	be,pt		%icc, 3f
 	 alignaddr	%o1, %g0, %o1
 
-	EX_LD_FP(LOAD(ldd, %o1, %f4))
-1:	EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6))
+	EX_LD_FP(LOAD(ldd, %o1, %f4), U3_retl_o2_plus_g2)
+1:	EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6), U3_retl_o2_plus_g2)
 	add		%o1, 0x8, %o1
 	subcc		%g2, 0x8, %g2
 	faligndata	%f4, %f6, %f0
-	EX_ST_FP(STORE(std, %f0, %o0))
+	EX_ST_FP(STORE(std, %f0, %o0), U3_retl_o2_plus_g2_plus_8)
 	be,pn		%icc, 3f
 	 add		%o0, 0x8, %o0
 
-	EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4), U3_retl_o2_plus_g2)
 	add		%o1, 0x8, %o1
 	subcc		%g2, 0x8, %g2
 	faligndata	%f6, %f4, %f2
-	EX_ST_FP(STORE(std, %f2, %o0))
+	EX_ST_FP(STORE(std, %f2, %o0), U3_retl_o2_plus_g2_plus_8)
 	bne,pt		%icc, 1b
 	 add		%o0, 0x8, %o0
 
@@ -161,25 +239,25 @@
 	LOAD(prefetch, %o1 + 0x080, #one_read)
 	LOAD(prefetch, %o1 + 0x0c0, #one_read)
 	LOAD(prefetch, %o1 + 0x100, #one_read)
-	EX_LD_FP(LOAD(ldd, %o1 + 0x000, %f0))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x000, %f0), U3_retl_o2)
 	LOAD(prefetch, %o1 + 0x140, #one_read)
-	EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2)
 	LOAD(prefetch, %o1 + 0x180, #one_read)
-	EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2)
 	LOAD(prefetch, %o1 + 0x1c0, #one_read)
 	faligndata	%f0, %f2, %f16
-	EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2)
 	faligndata	%f2, %f4, %f18
-	EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2)
 	faligndata	%f4, %f6, %f20
-	EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2)
 	faligndata	%f6, %f8, %f22
 
-	EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2)
 	faligndata	%f8, %f10, %f24
-	EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2)
 	faligndata	%f10, %f12, %f26
-	EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2)
 
 	subcc		GLOBAL_SPARE, 0x80, GLOBAL_SPARE
 	add		%o1, 0x40, %o1
@@ -190,26 +268,26 @@
 
 	.align		64
 1:
-	EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2_plus_o3_sll_6_plus_0x80)
 	faligndata	%f12, %f14, %f28
-	EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2_plus_o3_sll_6_plus_0x80)
 	faligndata	%f14, %f0, %f30
-	EX_ST_FP(STORE_BLK(%f16, %o0))
-	EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
+	EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x80)
+	EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	faligndata	%f0, %f2, %f16
 	add		%o0, 0x40, %o0
 
-	EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	faligndata	%f2, %f4, %f18
-	EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	faligndata	%f4, %f6, %f20
-	EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	subcc		%o3, 0x01, %o3
 	faligndata	%f6, %f8, %f22
-	EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2_plus_o3_sll_6_plus_0x80)
 
 	faligndata	%f8, %f10, %f24
-	EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2_plus_o3_sll_6_plus_0x80)
 	LOAD(prefetch, %o1 + 0x1c0, #one_read)
 	faligndata	%f10, %f12, %f26
 	bg,pt		%XCC, 1b
@@ -217,29 +295,29 @@
 
 	/* Finally we copy the last full 64-byte block. */
 2:
-	EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2_plus_o3_sll_6_plus_0x80)
 	faligndata	%f12, %f14, %f28
-	EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2_plus_o3_sll_6_plus_0x80)
 	faligndata	%f14, %f0, %f30
-	EX_ST_FP(STORE_BLK(%f16, %o0))
-	EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
+	EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x80)
+	EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	faligndata	%f0, %f2, %f16
-	EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	faligndata	%f2, %f4, %f18
-	EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	faligndata	%f4, %f6, %f20
-	EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	faligndata	%f6, %f8, %f22
-	EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	faligndata	%f8, %f10, %f24
 	cmp		%g1, 0
 	be,pt		%XCC, 1f
 	 add		%o0, 0x40, %o0
-	EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 1:	faligndata	%f10, %f12, %f26
 	faligndata	%f12, %f14, %f28
 	faligndata	%f14, %f0, %f30
-	EX_ST_FP(STORE_BLK(%f16, %o0))
+	EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 	add		%o0, 0x40, %o0
 	add		%o1, 0x40, %o1
 	membar		#Sync
@@ -259,20 +337,20 @@
 
 	sub		%o2, %g2, %o2
 	be,a,pt		%XCC, 1f
-	 EX_LD_FP(LOAD(ldd, %o1 + 0x00, %f0))
+	 EX_LD_FP(LOAD(ldd, %o1 + 0x00, %f0), U3_retl_o2_plus_g2)
 
-1:	EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f2))
+1:	EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f2), U3_retl_o2_plus_g2)
 	add		%o1, 0x8, %o1
 	subcc		%g2, 0x8, %g2
 	faligndata	%f0, %f2, %f8
-	EX_ST_FP(STORE(std, %f8, %o0))
+	EX_ST_FP(STORE(std, %f8, %o0), U3_retl_o2_plus_g2_plus_8)
 	be,pn		%XCC, 2f
 	 add		%o0, 0x8, %o0
-	EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f0))
+	EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f0), U3_retl_o2_plus_g2)
 	add		%o1, 0x8, %o1
 	subcc		%g2, 0x8, %g2
 	faligndata	%f2, %f0, %f8
-	EX_ST_FP(STORE(std, %f8, %o0))
+	EX_ST_FP(STORE(std, %f8, %o0), U3_retl_o2_plus_g2_plus_8)
 	bne,pn		%XCC, 1b
 	 add		%o0, 0x8, %o0
 
@@ -292,30 +370,33 @@
 	 andcc		%o2, 0x8, %g0
 	be,pt		%icc, 1f
 	 nop
-	EX_LD(LOAD(ldx, %o1, %o5))
-	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	EX_LD(LOAD(ldx, %o1, %o5), U3_retl_o2)
+	EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2)
 	add		%o1, 0x8, %o1
+	sub		%o2, 8, %o2
 
 1:	andcc		%o2, 0x4, %g0
 	be,pt		%icc, 1f
 	 nop
-	EX_LD(LOAD(lduw, %o1, %o5))
-	EX_ST(STORE(stw, %o5, %o1 + %o3))
+	EX_LD(LOAD(lduw, %o1, %o5), U3_retl_o2)
+	EX_ST(STORE(stw, %o5, %o1 + %o3), U3_retl_o2)
 	add		%o1, 0x4, %o1
+	sub		%o2, 4, %o2
 
 1:	andcc		%o2, 0x2, %g0
 	be,pt		%icc, 1f
 	 nop
-	EX_LD(LOAD(lduh, %o1, %o5))
-	EX_ST(STORE(sth, %o5, %o1 + %o3))
+	EX_LD(LOAD(lduh, %o1, %o5), U3_retl_o2)
+	EX_ST(STORE(sth, %o5, %o1 + %o3), U3_retl_o2)
 	add		%o1, 0x2, %o1
+	sub		%o2, 2, %o2
 
 1:	andcc		%o2, 0x1, %g0
 	be,pt		%icc, 85f
 	 nop
-	EX_LD(LOAD(ldub, %o1, %o5))
+	EX_LD(LOAD(ldub, %o1, %o5), U3_retl_o2)
 	ba,pt		%xcc, 85f
-	 EX_ST(STORE(stb, %o5, %o1 + %o3))
+	 EX_ST(STORE(stb, %o5, %o1 + %o3), U3_retl_o2)
 
 	.align		64
 70: /* 16 < len <= 64 */
@@ -326,26 +407,26 @@
 	andn		%o2, 0xf, GLOBAL_SPARE
 	and		%o2, 0xf, %o2
 1:	subcc		GLOBAL_SPARE, 0x10, GLOBAL_SPARE
-	EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
-	EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
-	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	EX_LD(LOAD(ldx, %o1 + 0x00, %o5), U3_retl_o2_plus_GS_plus_0x10)
+	EX_LD(LOAD(ldx, %o1 + 0x08, %g1), U3_retl_o2_plus_GS_plus_0x10)
+	EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2_plus_GS_plus_0x10)
 	add		%o1, 0x8, %o1
-	EX_ST(STORE(stx, %g1, %o1 + %o3))
+	EX_ST(STORE(stx, %g1, %o1 + %o3), U3_retl_o2_plus_GS_plus_0x08)
 	bgu,pt		%XCC, 1b
 	 add		%o1, 0x8, %o1
 73:	andcc		%o2, 0x8, %g0
 	be,pt		%XCC, 1f
 	 nop
 	sub		%o2, 0x8, %o2
-	EX_LD(LOAD(ldx, %o1, %o5))
-	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	EX_LD(LOAD(ldx, %o1, %o5), U3_retl_o2_plus_8)
+	EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2_plus_8)
 	add		%o1, 0x8, %o1
 1:	andcc		%o2, 0x4, %g0
 	be,pt		%XCC, 1f
 	 nop
 	sub		%o2, 0x4, %o2
-	EX_LD(LOAD(lduw, %o1, %o5))
-	EX_ST(STORE(stw, %o5, %o1 + %o3))
+	EX_LD(LOAD(lduw, %o1, %o5), U3_retl_o2_plus_4)
+	EX_ST(STORE(stw, %o5, %o1 + %o3), U3_retl_o2_plus_4)
 	add		%o1, 0x4, %o1
 1:	cmp		%o2, 0
 	be,pt		%XCC, 85f
@@ -361,8 +442,8 @@
 	sub		%o2, %g1, %o2
 
 1:	subcc		%g1, 1, %g1
-	EX_LD(LOAD(ldub, %o1, %o5))
-	EX_ST(STORE(stb, %o5, %o1 + %o3))
+	EX_LD(LOAD(ldub, %o1, %o5), U3_retl_o2_plus_g1_plus_1)
+	EX_ST(STORE(stb, %o5, %o1 + %o3), U3_retl_o2_plus_g1_plus_1)
 	bgu,pt		%icc, 1b
 	 add		%o1, 1, %o1
 
@@ -378,16 +459,16 @@
 
 8:	mov		64, %o3
 	andn		%o1, 0x7, %o1
-	EX_LD(LOAD(ldx, %o1, %g2))
+	EX_LD(LOAD(ldx, %o1, %g2), U3_retl_o2)
 	sub		%o3, %g1, %o3
 	andn		%o2, 0x7, GLOBAL_SPARE
 	sllx		%g2, %g1, %g2
-1:	EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+1:	EX_LD(LOAD(ldx, %o1 + 0x8, %g3), U3_retl_o2_and_7_plus_GS)
 	subcc		GLOBAL_SPARE, 0x8, GLOBAL_SPARE
 	add		%o1, 0x8, %o1
 	srlx		%g3, %o3, %o5
 	or		%o5, %g2, %o5
-	EX_ST(STORE(stx, %o5, %o0))
+	EX_ST(STORE(stx, %o5, %o0), U3_retl_o2_and_7_plus_GS_plus_8)
 	add		%o0, 0x8, %o0
 	bgu,pt		%icc, 1b
 	 sllx		%g3, %g1, %g2
@@ -407,8 +488,8 @@
 
 1:
 	subcc		%o2, 4, %o2
-	EX_LD(LOAD(lduw, %o1, %g1))
-	EX_ST(STORE(stw, %g1, %o1 + %o3))
+	EX_LD(LOAD(lduw, %o1, %g1), U3_retl_o2_plus_4)
+	EX_ST(STORE(stw, %g1, %o1 + %o3), U3_retl_o2_plus_4)
 	bgu,pt		%XCC, 1b
 	 add		%o1, 4, %o1
 
@@ -418,8 +499,8 @@
 	.align		32
 90:
 	subcc		%o2, 1, %o2
-	EX_LD(LOAD(ldub, %o1, %g1))
-	EX_ST(STORE(stb, %g1, %o1 + %o3))
+	EX_LD(LOAD(ldub, %o1, %g1), U3_retl_o2_plus_1)
+	EX_ST(STORE(stb, %g1, %o1 + %o3), U3_retl_o2_plus_1)
 	bgu,pt		%XCC, 90b
 	 add		%o1, 1, %o1
 	retl
diff --git a/arch/sparc/lib/copy_in_user.S b/arch/sparc/lib/copy_in_user.S
index 302c0e6..4c89b48 100644
--- a/arch/sparc/lib/copy_in_user.S
+++ b/arch/sparc/lib/copy_in_user.S
@@ -8,18 +8,33 @@
 
 #define XCC xcc
 
-#define EX(x,y)			\
+#define EX(x,y,z)		\
 98:	x,y;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_one;	\
+	.word 98b, z;		\
 	.text;			\
 	.align 4;
 
+#define EX_O4(x,y) EX(x,y,__retl_o4_plus_8)
+#define EX_O2_4(x,y) EX(x,y,__retl_o2_plus_4)
+#define EX_O2_1(x,y) EX(x,y,__retl_o2_plus_1)
+
 	.register	%g2,#scratch
 	.register	%g3,#scratch
 
 	.text
+__retl_o4_plus_8:
+	add	%o4, %o2, %o4
+	retl
+	 add	%o4, 8, %o0
+__retl_o2_plus_4:
+	retl
+	 add	%o2, 4, %o0
+__retl_o2_plus_1:
+	retl
+	 add	%o2, 1, %o0
+
 	.align	32
 
 	/* Don't try to get too fancy here, just nice and
@@ -44,8 +59,8 @@
 	andn		%o2, 0x7, %o4
 	and		%o2, 0x7, %o2
 1:	subcc		%o4, 0x8, %o4
-	EX(ldxa [%o1] %asi, %o5)
-	EX(stxa %o5, [%o0] %asi)
+	EX_O4(ldxa [%o1] %asi, %o5)
+	EX_O4(stxa %o5, [%o0] %asi)
 	add		%o1, 0x8, %o1
 	bgu,pt		%XCC, 1b
 	 add		%o0, 0x8, %o0
@@ -53,8 +68,8 @@
 	be,pt		%XCC, 1f
 	 nop
 	sub		%o2, 0x4, %o2
-	EX(lduwa [%o1] %asi, %o5)
-	EX(stwa %o5, [%o0] %asi)
+	EX_O2_4(lduwa [%o1] %asi, %o5)
+	EX_O2_4(stwa %o5, [%o0] %asi)
 	add		%o1, 0x4, %o1
 	add		%o0, 0x4, %o0
 1:	cmp		%o2, 0
@@ -70,8 +85,8 @@
 
 82:
 	subcc		%o2, 4, %o2
-	EX(lduwa [%o1] %asi, %g1)
-	EX(stwa %g1, [%o0] %asi)
+	EX_O2_4(lduwa [%o1] %asi, %g1)
+	EX_O2_4(stwa %g1, [%o0] %asi)
 	add		%o1, 4, %o1
 	bgu,pt		%XCC, 82b
 	 add		%o0, 4, %o0
@@ -82,8 +97,8 @@
 	.align	32
 90:
 	subcc		%o2, 1, %o2
-	EX(lduba [%o1] %asi, %g1)
-	EX(stba %g1, [%o0] %asi)
+	EX_O2_1(lduba [%o1] %asi, %g1)
+	EX_O2_1(stba %g1, [%o0] %asi)
 	add		%o1, 1, %o1
 	bgu,pt		%XCC, 90b
 	 add		%o0, 1, %o0
diff --git a/arch/sparc/lib/user_fixup.c b/arch/sparc/lib/user_fixup.c
deleted file mode 100644
index ac96ae2..0000000
--- a/arch/sparc/lib/user_fixup.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* user_fixup.c: Fix up user copy faults.
- *
- * Copyright (C) 2004 David S. Miller <davem@redhat.com>
- */
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-
-#include <asm/uaccess.h>
-
-/* Calculating the exact fault address when using
- * block loads and stores can be very complicated.
- *
- * Instead of trying to be clever and handling all
- * of the cases, just fix things up simply here.
- */
-
-static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset)
-{
-	unsigned long fault_addr = current_thread_info()->fault_address;
-	unsigned long end = start + size;
-
-	if (fault_addr < start || fault_addr >= end) {
-		*offset = 0;
-	} else {
-		*offset = fault_addr - start;
-		size = end - fault_addr;
-	}
-	return size;
-}
-
-unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
-{
-	unsigned long offset;
-
-	size = compute_size((unsigned long) from, size, &offset);
-	if (likely(size))
-		memset(to + offset, 0, size);
-
-	return size;
-}
-EXPORT_SYMBOL(copy_from_user_fixup);
-
-unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
-{
-	unsigned long offset;
-
-	return compute_size((unsigned long) to, size, &offset);
-}
-EXPORT_SYMBOL(copy_to_user_fixup);
-
-unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
-{
-	unsigned long fault_addr = current_thread_info()->fault_address;
-	unsigned long start = (unsigned long) to;
-	unsigned long end = start + size;
-
-	if (fault_addr >= start && fault_addr < end)
-		return end - fault_addr;
-
-	start = (unsigned long) from;
-	end = start + size;
-	if (fault_addr >= start && fault_addr < end)
-		return end - fault_addr;
-
-	return size;
-}
-EXPORT_SYMBOL(copy_in_user_fixup);
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index dbabe57..e15f337 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -479,14 +479,14 @@
 	up_read(&mm->mmap_sem);
 
 	mm_rss = get_mm_rss(mm);
-#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	mm_rss -= (mm->context.huge_pte_count * (HPAGE_SIZE / PAGE_SIZE));
+#if defined(CONFIG_TRANSPARENT_HUGEPAGE)
+	mm_rss -= (mm->context.thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
 #endif
 	if (unlikely(mm_rss >
 		     mm->context.tsb_block[MM_TSB_BASE].tsb_rss_limit))
 		tsb_grow(mm, MM_TSB_BASE, mm_rss);
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	mm_rss = mm->context.huge_pte_count;
+	mm_rss = mm->context.hugetlb_pte_count + mm->context.thp_pte_count;
 	if (unlikely(mm_rss >
 		     mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) {
 		if (mm->context.tsb_block[MM_TSB_HUGE].tsb)
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c
index 131eaf4..ffa842b 100644
--- a/arch/sparc/mm/hugetlbpage.c
+++ b/arch/sparc/mm/hugetlbpage.c
@@ -115,7 +115,7 @@
 		addr = ALIGN(addr, HPAGE_SIZE);
 		vma = find_vma(mm, addr);
 		if (task_size - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 	if (mm->get_unmapped_area == arch_get_unmapped_area)
@@ -176,17 +176,31 @@
 		     pte_t *ptep, pte_t entry)
 {
 	int i;
+	pte_t orig[2];
+	unsigned long nptes;
 
 	if (!pte_present(*ptep) && pte_present(entry))
-		mm->context.huge_pte_count++;
+		mm->context.hugetlb_pte_count++;
 
 	addr &= HPAGE_MASK;
-	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		set_pte_at(mm, addr, ptep, entry);
+
+	nptes = 1 << HUGETLB_PAGE_ORDER;
+	orig[0] = *ptep;
+	orig[1] = *(ptep + nptes / 2);
+	for (i = 0; i < nptes; i++) {
+		*ptep = entry;
 		ptep++;
 		addr += PAGE_SIZE;
 		pte_val(entry) += PAGE_SIZE;
 	}
+
+	/* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
+	addr -= REAL_HPAGE_SIZE;
+	ptep -= nptes / 2;
+	maybe_tlb_batch_add(mm, addr, ptep, orig[1], 0);
+	addr -= REAL_HPAGE_SIZE;
+	ptep -= nptes / 2;
+	maybe_tlb_batch_add(mm, addr, ptep, orig[0], 0);
 }
 
 pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
@@ -194,19 +208,28 @@
 {
 	pte_t entry;
 	int i;
+	unsigned long nptes;
 
 	entry = *ptep;
 	if (pte_present(entry))
-		mm->context.huge_pte_count--;
+		mm->context.hugetlb_pte_count--;
 
 	addr &= HPAGE_MASK;
-
-	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		pte_clear(mm, addr, ptep);
+	nptes = 1 << HUGETLB_PAGE_ORDER;
+	for (i = 0; i < nptes; i++) {
+		*ptep = __pte(0UL);
 		addr += PAGE_SIZE;
 		ptep++;
 	}
 
+	/* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
+	addr -= REAL_HPAGE_SIZE;
+	ptep -= nptes / 2;
+	maybe_tlb_batch_add(mm, addr, ptep, entry, 0);
+	addr -= REAL_HPAGE_SIZE;
+	ptep -= nptes / 2;
+	maybe_tlb_batch_add(mm, addr, ptep, entry, 0);
+
 	return entry;
 }
 
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
index eb82871..3b7092d 100644
--- a/arch/sparc/mm/init_32.c
+++ b/arch/sparc/mm/init_32.c
@@ -301,7 +301,7 @@
 
 
 	/* Saves us work later. */
-	memset((void *)&empty_zero_page, 0, PAGE_SIZE);
+	memset((void *)empty_zero_page, 0, PAGE_SIZE);
 
 	i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5);
 	i += 1;
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 3025bd5..384aba1 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -324,18 +324,6 @@
 	tsb_insert(tsb, tag, tte);
 }
 
-#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-static inline bool is_hugetlb_pte(pte_t pte)
-{
-	if ((tlb_type == hypervisor &&
-	     (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) ||
-	    (tlb_type != hypervisor &&
-	     (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U))
-		return true;
-	return false;
-}
-#endif
-
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
 {
 	struct mm_struct *mm;
@@ -358,7 +346,8 @@
 	spin_lock_irqsave(&mm->context.lock, flags);
 
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	if (mm->context.huge_pte_count && is_hugetlb_pte(pte))
+	if ((mm->context.hugetlb_pte_count || mm->context.thp_pte_count) &&
+	    is_hugetlb_pte(pte))
 		__update_mmu_tsb_insert(mm, MM_TSB_HUGE, REAL_HPAGE_SHIFT,
 					address, pte_val(pte));
 	else
@@ -667,10 +656,58 @@
 
 /* get_new_mmu_context() uses "cache + 1".  */
 DEFINE_SPINLOCK(ctx_alloc_lock);
-unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
+unsigned long tlb_context_cache = CTX_FIRST_VERSION;
 #define MAX_CTX_NR	(1UL << CTX_NR_BITS)
 #define CTX_BMAP_SLOTS	BITS_TO_LONGS(MAX_CTX_NR)
 DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR);
+DEFINE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm) = {0};
+
+static void mmu_context_wrap(void)
+{
+	unsigned long old_ver = tlb_context_cache & CTX_VERSION_MASK;
+	unsigned long new_ver, new_ctx, old_ctx;
+	struct mm_struct *mm;
+	int cpu;
+
+	bitmap_zero(mmu_context_bmap, 1 << CTX_NR_BITS);
+
+	/* Reserve kernel context */
+	set_bit(0, mmu_context_bmap);
+
+	new_ver = (tlb_context_cache & CTX_VERSION_MASK) + CTX_FIRST_VERSION;
+	if (unlikely(new_ver == 0))
+		new_ver = CTX_FIRST_VERSION;
+	tlb_context_cache = new_ver;
+
+	/*
+	 * Make sure that any new mm that are added into per_cpu_secondary_mm,
+	 * are going to go through get_new_mmu_context() path.
+	 */
+	mb();
+
+	/*
+	 * Updated versions to current on those CPUs that had valid secondary
+	 * contexts
+	 */
+	for_each_online_cpu(cpu) {
+		/*
+		 * If a new mm is stored after we took this mm from the array,
+		 * it will go into get_new_mmu_context() path, because we
+		 * already bumped the version in tlb_context_cache.
+		 */
+		mm = per_cpu(per_cpu_secondary_mm, cpu);
+
+		if (unlikely(!mm || mm == &init_mm))
+			continue;
+
+		old_ctx = mm->context.sparc64_ctx_val;
+		if (likely((old_ctx & CTX_VERSION_MASK) == old_ver)) {
+			new_ctx = (old_ctx & ~CTX_VERSION_MASK) | new_ver;
+			set_bit(new_ctx & CTX_NR_MASK, mmu_context_bmap);
+			mm->context.sparc64_ctx_val = new_ctx;
+		}
+	}
+}
 
 /* Caller does TLB context flushing on local CPU if necessary.
  * The caller also ensures that CTX_VALID(mm->context) is false.
@@ -686,48 +723,30 @@
 {
 	unsigned long ctx, new_ctx;
 	unsigned long orig_pgsz_bits;
-	int new_version;
 
 	spin_lock(&ctx_alloc_lock);
+retry:
+	/* wrap might have happened, test again if our context became valid */
+	if (unlikely(CTX_VALID(mm->context)))
+		goto out;
 	orig_pgsz_bits = (mm->context.sparc64_ctx_val & CTX_PGSZ_MASK);
 	ctx = (tlb_context_cache + 1) & CTX_NR_MASK;
 	new_ctx = find_next_zero_bit(mmu_context_bmap, 1 << CTX_NR_BITS, ctx);
-	new_version = 0;
 	if (new_ctx >= (1 << CTX_NR_BITS)) {
 		new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1);
 		if (new_ctx >= ctx) {
-			int i;
-			new_ctx = (tlb_context_cache & CTX_VERSION_MASK) +
-				CTX_FIRST_VERSION;
-			if (new_ctx == 1)
-				new_ctx = CTX_FIRST_VERSION;
-
-			/* Don't call memset, for 16 entries that's just
-			 * plain silly...
-			 */
-			mmu_context_bmap[0] = 3;
-			mmu_context_bmap[1] = 0;
-			mmu_context_bmap[2] = 0;
-			mmu_context_bmap[3] = 0;
-			for (i = 4; i < CTX_BMAP_SLOTS; i += 4) {
-				mmu_context_bmap[i + 0] = 0;
-				mmu_context_bmap[i + 1] = 0;
-				mmu_context_bmap[i + 2] = 0;
-				mmu_context_bmap[i + 3] = 0;
-			}
-			new_version = 1;
-			goto out;
+			mmu_context_wrap();
+			goto retry;
 		}
 	}
+	if (mm->context.sparc64_ctx_val)
+		cpumask_clear(mm_cpumask(mm));
 	mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63));
 	new_ctx |= (tlb_context_cache & CTX_VERSION_MASK);
-out:
 	tlb_context_cache = new_ctx;
 	mm->context.sparc64_ctx_val = new_ctx | orig_pgsz_bits;
+out:
 	spin_unlock(&ctx_alloc_lock);
-
-	if (unlikely(new_version))
-		smp_new_mmu_context_version();
 }
 
 static int numa_enabled = 1;
@@ -811,8 +830,10 @@
 };
 static struct mdesc_mblock *mblocks;
 static int num_mblocks;
+static int find_numa_node_for_addr(unsigned long pa,
+				   struct node_mem_mask *pnode_mask);
 
-static unsigned long ra_to_pa(unsigned long addr)
+static unsigned long __init ra_to_pa(unsigned long addr)
 {
 	int i;
 
@@ -828,8 +849,11 @@
 	return addr;
 }
 
-static int find_node(unsigned long addr)
+static int __init find_node(unsigned long addr)
 {
+	static bool search_mdesc = true;
+	static struct node_mem_mask last_mem_mask = { ~0UL, ~0UL };
+	static int last_index;
 	int i;
 
 	addr = ra_to_pa(addr);
@@ -839,13 +863,30 @@
 		if ((addr & p->mask) == p->val)
 			return i;
 	}
-	/* The following condition has been observed on LDOM guests.*/
-	WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node"
-		" rule. Some physical memory will be owned by node 0.");
-	return 0;
+	/* The following condition has been observed on LDOM guests because
+	 * node_masks only contains the best latency mask and value.
+	 * LDOM guest's mdesc can contain a single latency group to
+	 * cover multiple address range. Print warning message only if the
+	 * address cannot be found in node_masks nor mdesc.
+	 */
+	if ((search_mdesc) &&
+	    ((addr & last_mem_mask.mask) != last_mem_mask.val)) {
+		/* find the available node in the mdesc */
+		last_index = find_numa_node_for_addr(addr, &last_mem_mask);
+		numadbg("find_node: latency group for address 0x%lx is %d\n",
+			addr, last_index);
+		if ((last_index < 0) || (last_index >= num_node_masks)) {
+			/* WARN_ONCE() and use default group 0 */
+			WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node rule. Some physical memory will be owned by node 0.");
+			search_mdesc = false;
+			last_index = 0;
+		}
+	}
+
+	return last_index;
 }
 
-static u64 memblock_nid_range(u64 start, u64 end, int *nid)
+static u64 __init memblock_nid_range(u64 start, u64 end, int *nid)
 {
 	*nid = find_node(start);
 	start += PAGE_SIZE;
@@ -1169,6 +1210,41 @@
 	return numa_latency[from][to];
 }
 
+static int find_numa_node_for_addr(unsigned long pa,
+				   struct node_mem_mask *pnode_mask)
+{
+	struct mdesc_handle *md = mdesc_grab();
+	u64 node, arc;
+	int i = 0;
+
+	node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
+	if (node == MDESC_NODE_NULL)
+		goto out;
+
+	mdesc_for_each_node_by_name(md, node, "group") {
+		mdesc_for_each_arc(arc, md, node, MDESC_ARC_TYPE_FWD) {
+			u64 target = mdesc_arc_target(md, arc);
+			struct mdesc_mlgroup *m = find_mlgroup(target);
+
+			if (!m)
+				continue;
+			if ((pa & m->mask) == m->match) {
+				if (pnode_mask) {
+					pnode_mask->mask = m->mask;
+					pnode_mask->val = m->match;
+				}
+				mdesc_release(md);
+				return i;
+			}
+		}
+		i++;
+	}
+
+out:
+	mdesc_release(md);
+	return -1;
+}
+
 static int find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp)
 {
 	int i;
@@ -1267,13 +1343,6 @@
 	int i, j, err, count;
 	u64 node;
 
-	/* Some sane defaults for numa latency values */
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		for (j = 0; j < MAX_NUMNODES; j++)
-			numa_latency[i][j] = (i == j) ?
-				LOCAL_DISTANCE : REMOTE_DISTANCE;
-	}
-
 	node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
 	if (node == MDESC_NODE_NULL) {
 		mdesc_release(md);
@@ -1369,10 +1438,18 @@
 
 static int __init bootmem_init_numa(void)
 {
+	int i, j;
 	int err = -1;
 
 	numadbg("bootmem_init_numa()\n");
 
+	/* Some sane defaults for numa latency values */
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		for (j = 0; j < MAX_NUMNODES; j++)
+			numa_latency[i][j] = (i == j) ?
+				LOCAL_DISTANCE : REMOTE_DISTANCE;
+	}
+
 	if (numa_enabled) {
 		if (tlb_type == hypervisor)
 			err = numa_parse_mdesc();
@@ -1446,7 +1523,7 @@
 	if ((long)addr < 0L) {
 		unsigned long pa = __pa(addr);
 
-		if ((addr >> max_phys_bits) != 0UL)
+		if ((pa >> max_phys_bits) != 0UL)
 			return false;
 
 		return pfn_valid(pa >> PAGE_SHIFT);
@@ -2832,9 +2909,10 @@
 	 * the Data-TLB for huge pages.
 	 */
 	if (tlb_type == cheetah_plus) {
+		bool need_context_reload = false;
 		unsigned long ctx;
 
-		spin_lock(&ctx_alloc_lock);
+		spin_lock_irq(&ctx_alloc_lock);
 		ctx = mm->context.sparc64_ctx_val;
 		ctx &= ~CTX_PGSZ_MASK;
 		ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT;
@@ -2853,9 +2931,12 @@
 			 * also executing in this address space.
 			 */
 			mm->context.sparc64_ctx_val = ctx;
-			on_each_cpu(context_reload, mm, 0);
+			need_context_reload = true;
 		}
-		spin_unlock(&ctx_alloc_lock);
+		spin_unlock_irq(&ctx_alloc_lock);
+
+		if (need_context_reload)
+			on_each_cpu(context_reload, mm, 0);
 	}
 }
 #endif
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
index 9df2190..3659d37 100644
--- a/arch/sparc/mm/tlb.c
+++ b/arch/sparc/mm/tlb.c
@@ -67,7 +67,7 @@
 }
 
 static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
-			      bool exec)
+			      bool exec, bool huge)
 {
 	struct tlb_batch *tb = &get_cpu_var(tlb_batch);
 	unsigned long nr;
@@ -84,13 +84,21 @@
 	}
 
 	if (!tb->active) {
-		flush_tsb_user_page(mm, vaddr);
+		flush_tsb_user_page(mm, vaddr, huge);
 		global_flush_tlb_page(mm, vaddr);
 		goto out;
 	}
 
-	if (nr == 0)
+	if (nr == 0) {
 		tb->mm = mm;
+		tb->huge = huge;
+	}
+
+	if (tb->huge != huge) {
+		flush_tlb_pending();
+		tb->huge = huge;
+		nr = 0;
+	}
 
 	tb->vaddrs[nr] = vaddr;
 	tb->tlb_nr = ++nr;
@@ -104,6 +112,8 @@
 void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
 		   pte_t *ptep, pte_t orig, int fullmm)
 {
+	bool huge = is_hugetlb_pte(orig);
+
 	if (tlb_type != hypervisor &&
 	    pte_dirty(orig)) {
 		unsigned long paddr, pfn = pte_pfn(orig);
@@ -129,7 +139,7 @@
 
 no_cache_flush:
 	if (!fullmm)
-		tlb_batch_add_one(mm, vaddr, pte_exec(orig));
+		tlb_batch_add_one(mm, vaddr, pte_exec(orig), huge);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -145,7 +155,7 @@
 		if (pte_val(*pte) & _PAGE_VALID) {
 			bool exec = pte_exec(*pte);
 
-			tlb_batch_add_one(mm, vaddr, exec);
+			tlb_batch_add_one(mm, vaddr, exec, false);
 		}
 		pte++;
 		vaddr += PAGE_SIZE;
@@ -165,9 +175,9 @@
 
 	if ((pmd_val(pmd) ^ pmd_val(orig)) & _PAGE_PMD_HUGE) {
 		if (pmd_val(pmd) & _PAGE_PMD_HUGE)
-			mm->context.huge_pte_count++;
+			mm->context.thp_pte_count++;
 		else
-			mm->context.huge_pte_count--;
+			mm->context.thp_pte_count--;
 
 		/* Do not try to allocate the TSB hash table if we
 		 * don't have one already.  We have various locks held
@@ -185,8 +195,9 @@
 			pte_t orig_pte = __pte(pmd_val(orig));
 			bool exec = pte_exec(orig_pte);
 
-			tlb_batch_add_one(mm, addr, exec);
-			tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec);
+			tlb_batch_add_one(mm, addr, exec, true);
+			tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec,
+					true);
 		} else {
 			tlb_batch_pmd_scan(mm, addr, orig);
 		}
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index a065766..2664112 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -27,6 +27,20 @@
 	return (tag == (vaddr >> 22));
 }
 
+static void flush_tsb_kernel_range_scan(unsigned long start, unsigned long end)
+{
+	unsigned long idx;
+
+	for (idx = 0; idx < KERNEL_TSB_NENTRIES; idx++) {
+		struct tsb *ent = &swapper_tsb[idx];
+		unsigned long match = idx << 13;
+
+		match |= (ent->tag << 22);
+		if (match >= start && match < end)
+			ent->tag = (1UL << TSB_TAG_INVALID_BIT);
+	}
+}
+
 /* TSB flushes need only occur on the processor initiating the address
  * space modification, not on each cpu the address space has run on.
  * Only the TLB flush needs that treatment.
@@ -36,6 +50,9 @@
 {
 	unsigned long v;
 
+	if ((end - start) >> PAGE_SHIFT >= 2 * KERNEL_TSB_NENTRIES)
+		return flush_tsb_kernel_range_scan(start, end);
+
 	for (v = start; v < end; v += PAGE_SIZE) {
 		unsigned long hash = tsb_hash(v, PAGE_SHIFT,
 					      KERNEL_TSB_NENTRIES);
@@ -76,14 +93,15 @@
 
 	spin_lock_irqsave(&mm->context.lock, flags);
 
-	base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
-	nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
-	if (tlb_type == cheetah_plus || tlb_type == hypervisor)
-		base = __pa(base);
-	__flush_tsb_one(tb, PAGE_SHIFT, base, nentries);
-
+	if (!tb->huge) {
+		base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
+		nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
+		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+			base = __pa(base);
+		__flush_tsb_one(tb, PAGE_SHIFT, base, nentries);
+	}
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
+	if (tb->huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) {
 		base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
 		nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
 		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
@@ -94,20 +112,21 @@
 	spin_unlock_irqrestore(&mm->context.lock, flags);
 }
 
-void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr)
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge)
 {
 	unsigned long nentries, base, flags;
 
 	spin_lock_irqsave(&mm->context.lock, flags);
 
-	base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
-	nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
-	if (tlb_type == cheetah_plus || tlb_type == hypervisor)
-		base = __pa(base);
-	__flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
-
+	if (!huge) {
+		base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
+		nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
+		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+			base = __pa(base);
+		__flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
+	}
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
+	if (huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) {
 		base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
 		nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
 		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
@@ -432,7 +451,8 @@
 		extern void copy_tsb(unsigned long old_tsb_base,
 				     unsigned long old_tsb_size,
 				     unsigned long new_tsb_base,
-				     unsigned long new_tsb_size);
+				     unsigned long new_tsb_size,
+				     unsigned long page_size_shift);
 		unsigned long old_tsb_base = (unsigned long) old_tsb;
 		unsigned long new_tsb_base = (unsigned long) new_tsb;
 
@@ -440,7 +460,9 @@
 			old_tsb_base = __pa(old_tsb_base);
 			new_tsb_base = __pa(new_tsb_base);
 		}
-		copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size);
+		copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size,
+			tsb_index == MM_TSB_BASE ?
+			PAGE_SHIFT : REAL_HPAGE_SHIFT);
 	}
 
 	mm->context.tsb_block[tsb_index].tsb = new_tsb;
@@ -468,7 +490,7 @@
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	unsigned long huge_pte_count;
+	unsigned long total_huge_pte_count;
 #endif
 	unsigned int i;
 
@@ -477,12 +499,14 @@
 	mm->context.sparc64_ctx_val = 0UL;
 
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	/* We reset it to zero because the fork() page copying
+	/* We reset them to zero because the fork() page copying
 	 * will re-increment the counters as the parent PTEs are
 	 * copied into the child address space.
 	 */
-	huge_pte_count = mm->context.huge_pte_count;
-	mm->context.huge_pte_count = 0;
+	total_huge_pte_count = mm->context.hugetlb_pte_count +
+			 mm->context.thp_pte_count;
+	mm->context.hugetlb_pte_count = 0;
+	mm->context.thp_pte_count = 0;
 #endif
 
 	/* copy_mm() copies over the parent's mm_struct before calling
@@ -498,8 +522,8 @@
 	tsb_grow(mm, MM_TSB_BASE, get_mm_rss(mm));
 
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	if (unlikely(huge_pte_count))
-		tsb_grow(mm, MM_TSB_HUGE, huge_pte_count);
+	if (unlikely(total_huge_pte_count))
+		tsb_grow(mm, MM_TSB_HUGE, total_huge_pte_count);
 #endif
 
 	if (unlikely(!mm->context.tsb_block[MM_TSB_BASE].tsb))
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index b4f4733..fcf4d27 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -30,7 +30,7 @@
 	.text
 	.align		32
 	.globl		__flush_tlb_mm
-__flush_tlb_mm:		/* 18 insns */
+__flush_tlb_mm:		/* 19 insns */
 	/* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
 	ldxa		[%o1] ASI_DMMU, %g2
 	cmp		%g2, %o0
@@ -81,7 +81,7 @@
 
 	.align		32
 	.globl		__flush_tlb_pending
-__flush_tlb_pending:	/* 26 insns */
+__flush_tlb_pending:	/* 27 insns */
 	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
 	rdpr		%pstate, %g7
 	sllx		%o1, 3, %o1
@@ -113,12 +113,14 @@
 
 	.align		32
 	.globl		__flush_tlb_kernel_range
-__flush_tlb_kernel_range:	/* 16 insns */
+__flush_tlb_kernel_range:	/* 31 insns */
 	/* %o0=start, %o1=end */
 	cmp		%o0, %o1
 	be,pn		%xcc, 2f
+	 sub		%o1, %o0, %o3
+	srlx		%o3, 18, %o4
+	brnz,pn		%o4, __spitfire_flush_tlb_kernel_range_slow
 	 sethi		%hi(PAGE_SIZE), %o4
-	sub		%o1, %o0, %o3
 	sub		%o3, %o4, %o3
 	or		%o0, 0x20, %o0		! Nucleus
 1:	stxa		%g0, [%o0 + %o3] ASI_DMMU_DEMAP
@@ -131,6 +133,41 @@
 	retl
 	 nop
 	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+__spitfire_flush_tlb_kernel_range_slow:
+	mov		63 * 8, %o4
+1:	ldxa		[%o4] ASI_ITLB_DATA_ACCESS, %o3
+	andcc		%o3, 0x40, %g0			/* _PAGE_L_4U */
+	bne,pn		%xcc, 2f
+	 mov		TLB_TAG_ACCESS, %o3
+	stxa		%g0, [%o3] ASI_IMMU
+	stxa		%g0, [%o4] ASI_ITLB_DATA_ACCESS
+	membar		#Sync
+2:	ldxa		[%o4] ASI_DTLB_DATA_ACCESS, %o3
+	andcc		%o3, 0x40, %g0
+	bne,pn		%xcc, 2f
+	 mov		TLB_TAG_ACCESS, %o3
+	stxa		%g0, [%o3] ASI_DMMU
+	stxa		%g0, [%o4] ASI_DTLB_DATA_ACCESS
+	membar		#Sync
+2:	sub		%o4, 8, %o4
+	brgez,pt	%o4, 1b
+	 nop
+	retl
+	 nop
 
 __spitfire_flush_tlb_mm_slow:
 	rdpr		%pstate, %g1
@@ -285,6 +322,40 @@
 	retl
 	 wrpr		%g7, 0x0, %pstate
 
+__cheetah_flush_tlb_kernel_range:	/* 31 insns */
+	/* %o0=start, %o1=end */
+	cmp		%o0, %o1
+	be,pn		%xcc, 2f
+	 sub		%o1, %o0, %o3
+	srlx		%o3, 18, %o4
+	brnz,pn		%o4, 3f
+	 sethi		%hi(PAGE_SIZE), %o4
+	sub		%o3, %o4, %o3
+	or		%o0, 0x20, %o0		! Nucleus
+1:	stxa		%g0, [%o0 + %o3] ASI_DMMU_DEMAP
+	stxa		%g0, [%o0 + %o3] ASI_IMMU_DEMAP
+	membar		#Sync
+	brnz,pt		%o3, 1b
+	 sub		%o3, %o4, %o3
+2:	sethi		%hi(KERNBASE), %o3
+	flush		%o3
+	retl
+	 nop
+3:	mov		0x80, %o4
+	stxa		%g0, [%o4] ASI_DMMU_DEMAP
+	membar		#Sync
+	stxa		%g0, [%o4] ASI_IMMU_DEMAP
+	membar		#Sync
+	retl
+	 nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
 #ifdef DCACHE_ALIASING_POSSIBLE
 __cheetah_flush_dcache_page: /* 11 insns */
 	sethi		%hi(PAGE_OFFSET), %g1
@@ -309,19 +380,28 @@
 	ret
 	 restore
 
-__hypervisor_flush_tlb_mm: /* 10 insns */
+__hypervisor_flush_tlb_mm: /* 19 insns */
 	mov		%o0, %o2	/* ARG2: mmu context */
 	mov		0, %o0		/* ARG0: CPU lists unimplemented */
 	mov		0, %o1		/* ARG1: CPU lists unimplemented */
 	mov		HV_MMU_ALL, %o3	/* ARG3: flags */
 	mov		HV_FAST_MMU_DEMAP_CTX, %o5
 	ta		HV_FAST_TRAP
-	brnz,pn		%o0, __hypervisor_tlb_tl0_error
+	brnz,pn		%o0, 1f
 	 mov		HV_FAST_MMU_DEMAP_CTX, %o1
 	retl
 	 nop
+1:	sethi		%hi(__hypervisor_tlb_tl0_error), %o5
+	jmpl		%o5 + %lo(__hypervisor_tlb_tl0_error), %g0
+	 nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
 
-__hypervisor_flush_tlb_page: /* 11 insns */
+__hypervisor_flush_tlb_page: /* 22 insns */
 	/* %o0 = context, %o1 = vaddr */
 	mov		%o0, %g2
 	mov		%o1, %o0              /* ARG0: vaddr + IMMU-bit */
@@ -330,12 +410,23 @@
 	srlx		%o0, PAGE_SHIFT, %o0
 	sllx		%o0, PAGE_SHIFT, %o0
 	ta		HV_MMU_UNMAP_ADDR_TRAP
-	brnz,pn		%o0, __hypervisor_tlb_tl0_error
+	brnz,pn		%o0, 1f
 	 mov		HV_MMU_UNMAP_ADDR_TRAP, %o1
 	retl
 	 nop
+1:	sethi		%hi(__hypervisor_tlb_tl0_error), %o2
+	jmpl		%o2 + %lo(__hypervisor_tlb_tl0_error), %g0
+	 nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
 
-__hypervisor_flush_tlb_pending: /* 16 insns */
+__hypervisor_flush_tlb_pending: /* 27 insns */
 	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
 	sllx		%o1, 3, %g1
 	mov		%o2, %g2
@@ -347,31 +438,57 @@
 	srlx		%o0, PAGE_SHIFT, %o0
 	sllx		%o0, PAGE_SHIFT, %o0
 	ta		HV_MMU_UNMAP_ADDR_TRAP
-	brnz,pn		%o0, __hypervisor_tlb_tl0_error
+	brnz,pn		%o0, 1f
 	 mov		HV_MMU_UNMAP_ADDR_TRAP, %o1
 	brnz,pt		%g1, 1b
 	 nop
 	retl
 	 nop
+1:	sethi		%hi(__hypervisor_tlb_tl0_error), %o2
+	jmpl		%o2 + %lo(__hypervisor_tlb_tl0_error), %g0
+	 nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
 
-__hypervisor_flush_tlb_kernel_range: /* 16 insns */
+__hypervisor_flush_tlb_kernel_range: /* 31 insns */
 	/* %o0=start, %o1=end */
 	cmp		%o0, %o1
 	be,pn		%xcc, 2f
-	 sethi		%hi(PAGE_SIZE), %g3
-	mov		%o0, %g1
-	sub		%o1, %g1, %g2
+	 sub		%o1, %o0, %g2
+	srlx		%g2, 18, %g3
+	brnz,pn		%g3, 4f
+	 mov		%o0, %g1
+	sethi		%hi(PAGE_SIZE), %g3
 	sub		%g2, %g3, %g2
 1:	add		%g1, %g2, %o0	/* ARG0: virtual address */
 	mov		0, %o1		/* ARG1: mmu context */
 	mov		HV_MMU_ALL, %o2	/* ARG2: flags */
 	ta		HV_MMU_UNMAP_ADDR_TRAP
-	brnz,pn		%o0, __hypervisor_tlb_tl0_error
+	brnz,pn		%o0, 3f
 	 mov		HV_MMU_UNMAP_ADDR_TRAP, %o1
 	brnz,pt		%g2, 1b
 	 sub		%g2, %g3, %g2
 2:	retl
 	 nop
+3:	sethi		%hi(__hypervisor_tlb_tl0_error), %o2
+	jmpl		%o2 + %lo(__hypervisor_tlb_tl0_error), %g0
+	 nop
+4:	mov		0, %o0		/* ARG0: CPU lists unimplemented */
+	mov		0, %o1		/* ARG1: CPU lists unimplemented */
+	mov		0, %o2		/* ARG2: mmu context == nucleus */
+	mov		HV_MMU_ALL, %o3	/* ARG3: flags */
+	mov		HV_FAST_MMU_DEMAP_CTX, %o5
+	ta		HV_FAST_TRAP
+	brnz,pn		%o0, 3b
+	 mov		HV_FAST_MMU_DEMAP_CTX, %o1
+	retl
+	 nop
 
 #ifdef DCACHE_ALIASING_POSSIBLE
 	/* XXX Niagara and friends have an 8K cache, so no aliasing is
@@ -394,43 +511,6 @@
 	retl
 	 nop
 
-	.globl		cheetah_patch_cachetlbops
-cheetah_patch_cachetlbops:
-	save		%sp, -128, %sp
-
-	sethi		%hi(__flush_tlb_mm), %o0
-	or		%o0, %lo(__flush_tlb_mm), %o0
-	sethi		%hi(__cheetah_flush_tlb_mm), %o1
-	or		%o1, %lo(__cheetah_flush_tlb_mm), %o1
-	call		tlb_patch_one
-	 mov		19, %o2
-
-	sethi		%hi(__flush_tlb_page), %o0
-	or		%o0, %lo(__flush_tlb_page), %o0
-	sethi		%hi(__cheetah_flush_tlb_page), %o1
-	or		%o1, %lo(__cheetah_flush_tlb_page), %o1
-	call		tlb_patch_one
-	 mov		22, %o2
-
-	sethi		%hi(__flush_tlb_pending), %o0
-	or		%o0, %lo(__flush_tlb_pending), %o0
-	sethi		%hi(__cheetah_flush_tlb_pending), %o1
-	or		%o1, %lo(__cheetah_flush_tlb_pending), %o1
-	call		tlb_patch_one
-	 mov		27, %o2
-
-#ifdef DCACHE_ALIASING_POSSIBLE
-	sethi		%hi(__flush_dcache_page), %o0
-	or		%o0, %lo(__flush_dcache_page), %o0
-	sethi		%hi(__cheetah_flush_dcache_page), %o1
-	or		%o1, %lo(__cheetah_flush_dcache_page), %o1
-	call		tlb_patch_one
-	 mov		11, %o2
-#endif /* DCACHE_ALIASING_POSSIBLE */
-
-	ret
-	 restore
-
 #ifdef CONFIG_SMP
 	/* These are all called by the slaves of a cross call, at
 	 * trap level 1, with interrupts fully disabled.
@@ -447,7 +527,7 @@
 	 */
 	.align		32
 	.globl		xcall_flush_tlb_mm
-xcall_flush_tlb_mm:	/* 21 insns */
+xcall_flush_tlb_mm:	/* 24 insns */
 	mov		PRIMARY_CONTEXT, %g2
 	ldxa		[%g2] ASI_DMMU, %g3
 	srlx		%g3, CTX_PGSZ1_NUC_SHIFT, %g4
@@ -469,9 +549,12 @@
 	nop
 	nop
 	nop
+	nop
+	nop
+	nop
 
 	.globl		xcall_flush_tlb_page
-xcall_flush_tlb_page:	/* 17 insns */
+xcall_flush_tlb_page:	/* 20 insns */
 	/* %g5=context, %g1=vaddr */
 	mov		PRIMARY_CONTEXT, %g4
 	ldxa		[%g4] ASI_DMMU, %g2
@@ -490,15 +573,20 @@
 	retry
 	nop
 	nop
+	nop
+	nop
+	nop
 
 	.globl		xcall_flush_tlb_kernel_range
-xcall_flush_tlb_kernel_range:	/* 25 insns */
+xcall_flush_tlb_kernel_range:	/* 44 insns */
 	sethi		%hi(PAGE_SIZE - 1), %g2
 	or		%g2, %lo(PAGE_SIZE - 1), %g2
 	andn		%g1, %g2, %g1
 	andn		%g7, %g2, %g7
 	sub		%g7, %g1, %g3
-	add		%g2, 1, %g2
+	srlx		%g3, 18, %g2
+	brnz,pn		%g2, 2f
+	 add		%g2, 1, %g2
 	sub		%g3, %g2, %g3
 	or		%g1, 0x20, %g1		! Nucleus
 1:	stxa		%g0, [%g1 + %g3] ASI_DMMU_DEMAP
@@ -507,8 +595,25 @@
 	brnz,pt		%g3, 1b
 	 sub		%g3, %g2, %g3
 	retry
-	nop
-	nop
+2:	mov		63 * 8, %g1
+1:	ldxa		[%g1] ASI_ITLB_DATA_ACCESS, %g2
+	andcc		%g2, 0x40, %g0			/* _PAGE_L_4U */
+	bne,pn		%xcc, 2f
+	 mov		TLB_TAG_ACCESS, %g2
+	stxa		%g0, [%g2] ASI_IMMU
+	stxa		%g0, [%g1] ASI_ITLB_DATA_ACCESS
+	membar		#Sync
+2:	ldxa		[%g1] ASI_DTLB_DATA_ACCESS, %g2
+	andcc		%g2, 0x40, %g0
+	bne,pn		%xcc, 2f
+	 mov		TLB_TAG_ACCESS, %g2
+	stxa		%g0, [%g2] ASI_DMMU
+	stxa		%g0, [%g1] ASI_DTLB_DATA_ACCESS
+	membar		#Sync
+2:	sub		%g1, 8, %g1
+	brgez,pt	%g1, 1b
+	 nop
+	retry
 	nop
 	nop
 	nop
@@ -637,6 +742,52 @@
 
 	retry
 
+__cheetah_xcall_flush_tlb_kernel_range:	/* 44 insns */
+	sethi		%hi(PAGE_SIZE - 1), %g2
+	or		%g2, %lo(PAGE_SIZE - 1), %g2
+	andn		%g1, %g2, %g1
+	andn		%g7, %g2, %g7
+	sub		%g7, %g1, %g3
+	srlx		%g3, 18, %g2
+	brnz,pn		%g2, 2f
+	 add		%g2, 1, %g2
+	sub		%g3, %g2, %g3
+	or		%g1, 0x20, %g1		! Nucleus
+1:	stxa		%g0, [%g1 + %g3] ASI_DMMU_DEMAP
+	stxa		%g0, [%g1 + %g3] ASI_IMMU_DEMAP
+	membar		#Sync
+	brnz,pt		%g3, 1b
+	 sub		%g3, %g2, %g3
+	retry
+2:	mov		0x80, %g2
+	stxa		%g0, [%g2] ASI_DMMU_DEMAP
+	membar		#Sync
+	stxa		%g0, [%g2] ASI_IMMU_DEMAP
+	membar		#Sync
+	retry
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
 #ifdef DCACHE_ALIASING_POSSIBLE
 	.align		32
 	.globl		xcall_flush_dcache_page_cheetah
@@ -700,7 +851,7 @@
 	ba,a,pt	%xcc, rtrap
 
 	.globl		__hypervisor_xcall_flush_tlb_mm
-__hypervisor_xcall_flush_tlb_mm: /* 21 insns */
+__hypervisor_xcall_flush_tlb_mm: /* 24 insns */
 	/* %g5=ctx, g1,g2,g3,g4,g7=scratch, %g6=unusable */
 	mov		%o0, %g2
 	mov		%o1, %g3
@@ -714,7 +865,7 @@
 	mov		HV_FAST_MMU_DEMAP_CTX, %o5
 	ta		HV_FAST_TRAP
 	mov		HV_FAST_MMU_DEMAP_CTX, %g6
-	brnz,pn		%o0, __hypervisor_tlb_xcall_error
+	brnz,pn		%o0, 1f
 	 mov		%o0, %g5
 	mov		%g2, %o0
 	mov		%g3, %o1
@@ -723,9 +874,12 @@
 	mov		%g7, %o5
 	membar		#Sync
 	retry
+1:	sethi		%hi(__hypervisor_tlb_xcall_error), %g4
+	jmpl		%g4 + %lo(__hypervisor_tlb_xcall_error), %g0
+	 nop
 
 	.globl		__hypervisor_xcall_flush_tlb_page
-__hypervisor_xcall_flush_tlb_page: /* 17 insns */
+__hypervisor_xcall_flush_tlb_page: /* 20 insns */
 	/* %g5=ctx, %g1=vaddr */
 	mov		%o0, %g2
 	mov		%o1, %g3
@@ -737,42 +891,64 @@
 	sllx		%o0, PAGE_SHIFT, %o0
 	ta		HV_MMU_UNMAP_ADDR_TRAP
 	mov		HV_MMU_UNMAP_ADDR_TRAP, %g6
-	brnz,a,pn	%o0, __hypervisor_tlb_xcall_error
+	brnz,a,pn	%o0, 1f
 	 mov		%o0, %g5
 	mov		%g2, %o0
 	mov		%g3, %o1
 	mov		%g4, %o2
 	membar		#Sync
 	retry
+1:	sethi		%hi(__hypervisor_tlb_xcall_error), %g4
+	jmpl		%g4 + %lo(__hypervisor_tlb_xcall_error), %g0
+	 nop
 
 	.globl		__hypervisor_xcall_flush_tlb_kernel_range
-__hypervisor_xcall_flush_tlb_kernel_range: /* 25 insns */
+__hypervisor_xcall_flush_tlb_kernel_range: /* 44 insns */
 	/* %g1=start, %g7=end, g2,g3,g4,g5,g6=scratch */
 	sethi		%hi(PAGE_SIZE - 1), %g2
 	or		%g2, %lo(PAGE_SIZE - 1), %g2
 	andn		%g1, %g2, %g1
 	andn		%g7, %g2, %g7
 	sub		%g7, %g1, %g3
+	srlx		%g3, 18, %g7
 	add		%g2, 1, %g2
 	sub		%g3, %g2, %g3
 	mov		%o0, %g2
 	mov		%o1, %g4
-	mov		%o2, %g7
+	brnz,pn		%g7, 2f
+	 mov		%o2, %g7
 1:	add		%g1, %g3, %o0	/* ARG0: virtual address */
 	mov		0, %o1		/* ARG1: mmu context */
 	mov		HV_MMU_ALL, %o2	/* ARG2: flags */
 	ta		HV_MMU_UNMAP_ADDR_TRAP
 	mov		HV_MMU_UNMAP_ADDR_TRAP, %g6
-	brnz,pn		%o0, __hypervisor_tlb_xcall_error
+	brnz,pn		%o0, 1f
 	 mov		%o0, %g5
 	sethi		%hi(PAGE_SIZE), %o2
 	brnz,pt		%g3, 1b
 	 sub		%g3, %o2, %g3
-	mov		%g2, %o0
+5:	mov		%g2, %o0
 	mov		%g4, %o1
 	mov		%g7, %o2
 	membar		#Sync
 	retry
+1:	sethi		%hi(__hypervisor_tlb_xcall_error), %g4
+	jmpl		%g4 + %lo(__hypervisor_tlb_xcall_error), %g0
+	 nop
+2:	mov		%o3, %g1
+	mov		%o5, %g3
+	mov		0, %o0		/* ARG0: CPU lists unimplemented */
+	mov		0, %o1		/* ARG1: CPU lists unimplemented */
+	mov		0, %o2		/* ARG2: mmu context == nucleus */
+	mov		HV_MMU_ALL, %o3	/* ARG3: flags */
+	mov		HV_FAST_MMU_DEMAP_CTX, %o5
+	ta		HV_FAST_TRAP
+	mov		%g1, %o3
+	brz,pt		%o0, 5b
+	 mov		%g3, %o5
+	mov		HV_FAST_MMU_DEMAP_CTX, %g6
+	ba,pt		%xcc, 1b
+	 clr		%g5
 
 	/* These just get rescheduled to PIL vectors. */
 	.globl		xcall_call_function
@@ -795,11 +971,6 @@
 	wr		%g0, (1 << PIL_SMP_CAPTURE), %set_softint
 	retry
 
-	.globl		xcall_new_mmu_context_version
-xcall_new_mmu_context_version:
-	wr		%g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
-	retry
-
 #ifdef CONFIG_KGDB
 	.globl		xcall_kgdb_capture
 xcall_kgdb_capture:
@@ -809,6 +980,58 @@
 
 #endif /* CONFIG_SMP */
 
+	.globl		cheetah_patch_cachetlbops
+cheetah_patch_cachetlbops:
+	save		%sp, -128, %sp
+
+	sethi		%hi(__flush_tlb_mm), %o0
+	or		%o0, %lo(__flush_tlb_mm), %o0
+	sethi		%hi(__cheetah_flush_tlb_mm), %o1
+	or		%o1, %lo(__cheetah_flush_tlb_mm), %o1
+	call		tlb_patch_one
+	 mov		19, %o2
+
+	sethi		%hi(__flush_tlb_page), %o0
+	or		%o0, %lo(__flush_tlb_page), %o0
+	sethi		%hi(__cheetah_flush_tlb_page), %o1
+	or		%o1, %lo(__cheetah_flush_tlb_page), %o1
+	call		tlb_patch_one
+	 mov		22, %o2
+
+	sethi		%hi(__flush_tlb_pending), %o0
+	or		%o0, %lo(__flush_tlb_pending), %o0
+	sethi		%hi(__cheetah_flush_tlb_pending), %o1
+	or		%o1, %lo(__cheetah_flush_tlb_pending), %o1
+	call		tlb_patch_one
+	 mov		27, %o2
+
+	sethi		%hi(__flush_tlb_kernel_range), %o0
+	or		%o0, %lo(__flush_tlb_kernel_range), %o0
+	sethi		%hi(__cheetah_flush_tlb_kernel_range), %o1
+	or		%o1, %lo(__cheetah_flush_tlb_kernel_range), %o1
+	call		tlb_patch_one
+	 mov		31, %o2
+
+#ifdef DCACHE_ALIASING_POSSIBLE
+	sethi		%hi(__flush_dcache_page), %o0
+	or		%o0, %lo(__flush_dcache_page), %o0
+	sethi		%hi(__cheetah_flush_dcache_page), %o1
+	or		%o1, %lo(__cheetah_flush_dcache_page), %o1
+	call		tlb_patch_one
+	 mov		11, %o2
+#endif /* DCACHE_ALIASING_POSSIBLE */
+
+#ifdef CONFIG_SMP
+	sethi		%hi(xcall_flush_tlb_kernel_range), %o0
+	or		%o0, %lo(xcall_flush_tlb_kernel_range), %o0
+	sethi		%hi(__cheetah_xcall_flush_tlb_kernel_range), %o1
+	or		%o1, %lo(__cheetah_xcall_flush_tlb_kernel_range), %o1
+	call		tlb_patch_one
+	 mov		44, %o2
+#endif /* CONFIG_SMP */
+
+	ret
+	 restore
 
 	.globl		hypervisor_patch_cachetlbops
 hypervisor_patch_cachetlbops:
@@ -819,28 +1042,28 @@
 	sethi		%hi(__hypervisor_flush_tlb_mm), %o1
 	or		%o1, %lo(__hypervisor_flush_tlb_mm), %o1
 	call		tlb_patch_one
-	 mov		10, %o2
+	 mov		19, %o2
 
 	sethi		%hi(__flush_tlb_page), %o0
 	or		%o0, %lo(__flush_tlb_page), %o0
 	sethi		%hi(__hypervisor_flush_tlb_page), %o1
 	or		%o1, %lo(__hypervisor_flush_tlb_page), %o1
 	call		tlb_patch_one
-	 mov		11, %o2
+	 mov		22, %o2
 
 	sethi		%hi(__flush_tlb_pending), %o0
 	or		%o0, %lo(__flush_tlb_pending), %o0
 	sethi		%hi(__hypervisor_flush_tlb_pending), %o1
 	or		%o1, %lo(__hypervisor_flush_tlb_pending), %o1
 	call		tlb_patch_one
-	 mov		16, %o2
+	 mov		27, %o2
 
 	sethi		%hi(__flush_tlb_kernel_range), %o0
 	or		%o0, %lo(__flush_tlb_kernel_range), %o0
 	sethi		%hi(__hypervisor_flush_tlb_kernel_range), %o1
 	or		%o1, %lo(__hypervisor_flush_tlb_kernel_range), %o1
 	call		tlb_patch_one
-	 mov		16, %o2
+	 mov		31, %o2
 
 #ifdef DCACHE_ALIASING_POSSIBLE
 	sethi		%hi(__flush_dcache_page), %o0
@@ -857,21 +1080,21 @@
 	sethi		%hi(__hypervisor_xcall_flush_tlb_mm), %o1
 	or		%o1, %lo(__hypervisor_xcall_flush_tlb_mm), %o1
 	call		tlb_patch_one
-	 mov		21, %o2
+	 mov		24, %o2
 
 	sethi		%hi(xcall_flush_tlb_page), %o0
 	or		%o0, %lo(xcall_flush_tlb_page), %o0
 	sethi		%hi(__hypervisor_xcall_flush_tlb_page), %o1
 	or		%o1, %lo(__hypervisor_xcall_flush_tlb_page), %o1
 	call		tlb_patch_one
-	 mov		17, %o2
+	 mov		20, %o2
 
 	sethi		%hi(xcall_flush_tlb_kernel_range), %o0
 	or		%o0, %lo(xcall_flush_tlb_kernel_range), %o0
 	sethi		%hi(__hypervisor_xcall_flush_tlb_kernel_range), %o1
 	or		%o1, %lo(__hypervisor_xcall_flush_tlb_kernel_range), %o1
 	call		tlb_patch_one
-	 mov		25, %o2
+	 mov		44, %o2
 #endif /* CONFIG_SMP */
 
 	ret
diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h
index c505d77..e9d54a0 100644
--- a/arch/tile/include/asm/elf.h
+++ b/arch/tile/include/asm/elf.h
@@ -129,6 +129,7 @@
 struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 				       int executable_stack);
+/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
 #define ARCH_DLINFO \
 do { \
 	NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); \
diff --git a/arch/tile/include/uapi/asm/auxvec.h b/arch/tile/include/uapi/asm/auxvec.h
index c93e927..f497123 100644
--- a/arch/tile/include/uapi/asm/auxvec.h
+++ b/arch/tile/include/uapi/asm/auxvec.h
@@ -18,4 +18,6 @@
 /* The vDSO location. */
 #define AT_SYSINFO_EHDR         33
 
+#define AT_VECTOR_SIZE_ARCH 1 /* entries in ARCH_DLINFO */
+
 #endif /* _ASM_TILE_AUXVEC_H */
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index bdc126f..6239aa1 100644
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -111,7 +111,7 @@
 			  const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	struct pt_regs regs;
+	struct pt_regs regs = *task_pt_regs(target);
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &regs, 0,
 				 sizeof(regs));
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c
index 178989e..ea960d6 100644
--- a/arch/tile/kernel/time.c
+++ b/arch/tile/kernel/time.c
@@ -218,8 +218,8 @@
  */
 unsigned long long sched_clock(void)
 {
-	return clocksource_cyc2ns(get_cycles(),
-				  sched_clock_mult, SCHED_CLOCK_SHIFT);
+	return mult_frac(get_cycles(),
+			 sched_clock_mult, 1ULL << SCHED_CLOCK_SHIFT);
 }
 
 int setup_profiling_timer(unsigned int multiplier)
diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c
index c034dc3..c97ee6c 100644
--- a/arch/tile/mm/hugetlbpage.c
+++ b/arch/tile/mm/hugetlbpage.c
@@ -232,7 +232,7 @@
 		addr = ALIGN(addr, huge_page_size(h));
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 	if (current->mm->get_unmapped_area == arch_get_unmapped_area)
diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S
index 1dd5bd8..1330553 100644
--- a/arch/um/include/asm/common.lds.S
+++ b/arch/um/include/asm/common.lds.S
@@ -81,7 +81,7 @@
   .altinstr_replacement : { *(.altinstr_replacement) }
   /* .exit.text is discard at runtime, not link time, to deal with references
      from .altinstructions and .eh_frame */
-  .exit.text : { *(.exit.text) }
+  .exit.text : { EXIT_TEXT }
   .exit.data : { *(.exit.data) }
 
   .preinit_array : {
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ffbfa85..cc9dbc5 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -46,6 +46,8 @@
 	select ARCH_WANTS_DYNAMIC_TASK_STRUCT
 	select ARCH_WANT_FRAME_POINTERS
 	select ARCH_WANT_IPC_PARSE_VERSION	if X86_32
+	select HAVE_ARCH_MMAP_RND_BITS		if MMU
+	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if MMU && COMPAT
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select BUILDTIME_EXTABLE_SORT
 	select CLKEVT_I8253
@@ -77,17 +79,17 @@
 	select HAVE_ALIGNED_STRUCT_PAGE		if SLUB
 	select HAVE_AOUT			if X86_32
 	select HAVE_ARCH_AUDITSYSCALL
+	select HAVE_ARCH_HARDENED_USERCOPY
 	select HAVE_ARCH_HUGE_VMAP		if X86_64 || X86_PAE
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_KASAN			if X86_64 && SPARSEMEM_VMEMMAP
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_KMEMCHECK
-	select HAVE_ARCH_MMAP_RND_BITS		if MMU
-	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if MMU && COMPAT
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_SOFT_DIRTY		if X86_64
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+	select HAVE_ARCH_WITHIN_STACK_FRAMES
 	select HAVE_BPF_JIT			if X86_64
 	select HAVE_CC_STACKPROTECTOR
 	select HAVE_CMPXCHG_DOUBLE
@@ -305,6 +307,9 @@
 config FIX_EARLYCON_MEM
 	def_bool y
 
+config DEBUG_RODATA
+	def_bool y
+
 config PGTABLE_LEVELS
 	int
 	default 4 if X86_64
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 137dfa9..1f6c306a 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -91,28 +91,16 @@
 	  issues with the mapping of the EFI runtime regions into that
 	  table.
 
-config DEBUG_RODATA
-	bool "Write protect kernel read-only data structures"
-	default y
-	depends on DEBUG_KERNEL
-	---help---
-	  Mark the kernel read-only data as write-protected in the pagetables,
-	  in order to catch accidental (and incorrect) writes to such const
-	  data. This is recommended so that we can catch kernel bugs sooner.
-	  If in doubt, say "Y".
-
 config DEBUG_RODATA_TEST
-	bool "Testcase for the DEBUG_RODATA feature"
-	depends on DEBUG_RODATA
+	bool "Testcase for the marking rodata read-only"
 	default y
 	---help---
-	  This option enables a testcase for the DEBUG_RODATA
-	  feature as well as for the change_page_attr() infrastructure.
+	  This option enables a testcase for the setting rodata read-only
+	  as well as for the change_page_attr() infrastructure.
 	  If in doubt, say "N"
 
 config DEBUG_WX
 	bool "Warn on W+X mappings at boot"
-	depends on DEBUG_RODATA
 	select X86_PTDUMP_CORE
 	---help---
 	  Generate a warning if any W+X mappings are found at boot.
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 4086abc..53949c8 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -97,6 +97,8 @@
         KBUILD_CFLAGS += $(call cc-option,-mno-80387)
         KBUILD_CFLAGS += $(call cc-option,-mno-fp-ret-in-387)
 
+        KBUILD_CFLAGS += -fno-pic
+
 	# Use -mpreferred-stack-boundary=3 if supported.
 	KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
 
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 2ee62db..c0cc2a6 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -162,6 +162,9 @@
 	for i in lib lib64 share end ; do \
 		if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
 			cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
+			if [ -f /usr/$$i/syslinux/ldlinux.c32 ]; then \
+				cp /usr/$$i/syslinux/ldlinux.c32 $(obj)/isoimage ; \
+			fi ; \
 			break ; \
 		fi ; \
 		if [ $$i = end ] ; then exit 1 ; fi ; \
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 9011a88..ed1e920 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -16,7 +16,7 @@
 #ifndef BOOT_BOOT_H
 #define BOOT_BOOT_H
 
-#define STACK_SIZE	512	/* Minimum number of bytes for stack */
+#define STACK_SIZE	1024	/* Minimum number of bytes for stack */
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 0a291cd..efa6073 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -22,7 +22,7 @@
 	vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
-KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
+KBUILD_CFLAGS += -fno-strict-aliasing $(call cc-option, -fPIE, -fPIC)
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 cflags-$(CONFIG_X86_32) := -march=i386
 cflags-$(CONFIG_X86_64) := -mcmodel=small
@@ -35,6 +35,18 @@
 GCOV_PROFILE := n
 
 LDFLAGS := -m elf_$(UTS_MACHINE)
+ifeq ($(CONFIG_RELOCATABLE),y)
+# If kernel is relocatable, build compressed kernel as PIE.
+ifeq ($(CONFIG_X86_32),y)
+LDFLAGS += $(call ld-option, -pie) $(call ld-option, --no-dynamic-linker)
+else
+# To build 64-bit compressed kernel as PIE, we disable relocation
+# overflow check to avoid relocation overflow error with a new linker
+# command-line option, -z noreloc-overflow.
+LDFLAGS += $(shell $(LD) --help 2>&1 | grep -q "\-z noreloc-overflow" \
+	&& echo "-z noreloc-overflow -pie --no-dynamic-linker")
+endif
+endif
 LDFLAGS_vmlinux := -T
 
 hostprogs-y	:= mkpiggy
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 8ef964d..0256064 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -31,6 +31,34 @@
 #include <asm/asm-offsets.h>
 #include <asm/bootparam.h>
 
+/*
+ * The 32-bit x86 assembler in binutils 2.26 will generate R_386_GOT32X
+ * relocation to get the symbol address in PIC.  When the compressed x86
+ * kernel isn't built as PIC, the linker optimizes R_386_GOT32X
+ * relocations to their fixed symbol addresses.  However, when the
+ * compressed x86 kernel is loaded at a different address, it leads
+ * to the following load failure:
+ *
+ *   Failed to allocate space for phdrs
+ *
+ * during the decompression stage.
+ *
+ * If the compressed x86 kernel is relocatable at run-time, it should be
+ * compiled with -fPIE, instead of -fPIC, if possible and should be built as
+ * Position Independent Executable (PIE) so that linker won't optimize
+ * R_386_GOT32X relocation to its fixed symbol address.  Older
+ * linkers generate R_386_32 relocations against locally defined symbols,
+ * _bss, _ebss, _got and _egot, in PIE.  It isn't wrong, just less
+ * optimal than R_386_RELATIVE.  But the x86 kernel fails to properly handle
+ * R_386_32 relocations when relocating the kernel.  To generate
+ * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
+ * hidden:
+ */
+	.hidden _bss
+	.hidden _ebss
+	.hidden _got
+	.hidden _egot
+
 	__HEAD
 ENTRY(startup_32)
 #ifdef CONFIG_EFI_STUB
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index b0c0d16..86558a1 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -33,6 +33,14 @@
 #include <asm/asm-offsets.h>
 #include <asm/bootparam.h>
 
+/*
+ * Locally defined symbols should be marked hidden:
+ */
+	.hidden _bss
+	.hidden _ebss
+	.hidden _got
+	.hidden _egot
+
 	__HEAD
 	.code32
 ENTRY(startup_32)
diff --git a/arch/x86/configs/i386_ranchu_defconfig b/arch/x86/configs/i386_ranchu_defconfig
new file mode 100644
index 0000000..65ed8c8
--- /dev/null
+++ b/arch/x86/configs/i386_ranchu_defconfig
@@ -0,0 +1,423 @@
+# CONFIG_64BIT is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_ARCH_MMAP_RND_BITS=16
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SGI_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_SMP=y
+CONFIG_X86_BIGSMP=y
+CONFIG_MCORE2=y
+CONFIG_X86_GENERIC=y
+CONFIG_HPET_TIMER=y
+CONFIG_NR_CPUS=512
+CONFIG_PREEMPT=y
+# CONFIG_X86_MCE is not set
+CONFIG_X86_REBOOTFIXUPS=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_KSM=y
+CONFIG_CMA=y
+# CONFIG_MTRR_SANITIZER is not set
+CONFIG_EFI=y
+CONFIG_EFI_STUB=y
+CONFIG_HZ_100=y
+CONFIG_PHYSICAL_START=0x100000
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_DEBUG=y
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_STAT is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEASPM is not set
+CONFIG_PCCARD=y
+CONFIG_YENTA=y
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETLABEL=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=16
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_VIRTIO_BLK=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_AMD=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_SCH=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_MIRROR=y
+CONFIG_DM_ZERO=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_NETCONSOLE=y
+CONFIG_TUN=y
+CONFIG_VIRTIO_NET=y
+CONFIG_BNX2=y
+CONFIG_TIGON3=y
+CONFIG_NET_TULIP=y
+CONFIG_E100=y
+CONFIG_E1000=y
+CONFIG_E1000E=y
+CONFIG_SKY2=y
+CONFIG_NE2K_PCI=y
+CONFIG_FORCEDETH=y
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_R8169=y
+CONFIG_FDDI=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_USB_USBNET=y
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=y
+CONFIG_TABLET_USB_AIPTEK=y
+CONFIG_TABLET_USB_GTCO=y
+CONFIG_TABLET_USB_HANWANG=y
+CONFIG_TABLET_USB_KBTAB=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_NVRAM=y
+CONFIG_I2C_I801=y
+CONFIG_BATTERY_GOLDFISH=y
+CONFIG_WATCHDOG=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_DRM=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_EFI=y
+CONFIG_FB_GOLDFISH=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_PRODIKEYS=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_HOLTEK=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WALTOP=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_PRIMAX=y
+CONFIG_HID_ROCCAT=y
+CONFIG_HID_SAITEK=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SPEEDLINK=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_WIIMOTE=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+CONFIG_USB_PRINTER=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_EDAC=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_DMADEVICES=y
+CONFIG_VIRTIO_PCI=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
+CONFIG_ION=y
+CONFIG_GOLDFISH_AUDIO=y
+CONFIG_GOLDFISH_SYNC=y
+CONFIG_SND_HDA_INTEL=y
+CONFIG_GOLDFISH=y
+CONFIG_GOLDFISH_PIPE=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ISCSI_IBFT_FIND=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_PSTORE=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_RAM=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=2048
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_SCHED_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
+CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_CRYPTO_AES_586=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_ASYMMETRIC_KEY_TYPE=y
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
+CONFIG_X509_CERTIFICATE_PARSER=y
+CONFIG_PKCS7_MESSAGE_PARSER=y
+CONFIG_PKCS7_TEST_KEY=y
+# CONFIG_VIRTUALIZATION is not set
+CONFIG_CRC_T10DIF=y
diff --git a/arch/x86/configs/tiny.config b/arch/x86/configs/tiny.config
index 4e2ecfa..4b429df 100644
--- a/arch/x86/configs/tiny.config
+++ b/arch/x86/configs/tiny.config
@@ -1 +1,3 @@
 CONFIG_NOHIGHMEM=y
+# CONFIG_HIGHMEM4G is not set
+# CONFIG_HIGHMEM64G is not set
diff --git a/arch/x86/configs/x86_64_ranchu_defconfig b/arch/x86/configs/x86_64_ranchu_defconfig
new file mode 100644
index 0000000..d977bd9
--- /dev/null
+++ b/arch/x86/configs/x86_64_ranchu_defconfig
@@ -0,0 +1,418 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_ARCH_MMAP_RND_BITS=32
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SGI_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_SMP=y
+CONFIG_MCORE2=y
+CONFIG_MAXSMP=y
+CONFIG_PREEMPT=y
+# CONFIG_X86_MCE is not set
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_KSM=y
+CONFIG_CMA=y
+# CONFIG_MTRR_SANITIZER is not set
+CONFIG_EFI=y
+CONFIG_EFI_STUB=y
+CONFIG_HZ_100=y
+CONFIG_PHYSICAL_START=0x100000
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_DEBUG=y
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_STAT is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEASPM is not set
+CONFIG_PCCARD=y
+CONFIG_YENTA=y
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=y
+CONFIG_IA32_EMULATION=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETLABEL=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DMA_CMA=y
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_VIRTIO_BLK=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_AMD=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_SCH=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_MIRROR=y
+CONFIG_DM_ZERO=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_NETCONSOLE=y
+CONFIG_TUN=y
+CONFIG_VIRTIO_NET=y
+CONFIG_BNX2=y
+CONFIG_TIGON3=y
+CONFIG_NET_TULIP=y
+CONFIG_E100=y
+CONFIG_E1000=y
+CONFIG_E1000E=y
+CONFIG_SKY2=y
+CONFIG_NE2K_PCI=y
+CONFIG_FORCEDETH=y
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_R8169=y
+CONFIG_FDDI=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_USB_USBNET=y
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=y
+CONFIG_TABLET_USB_AIPTEK=y
+CONFIG_TABLET_USB_GTCO=y
+CONFIG_TABLET_USB_HANWANG=y
+CONFIG_TABLET_USB_KBTAB=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_NVRAM=y
+CONFIG_I2C_I801=y
+CONFIG_BATTERY_GOLDFISH=y
+CONFIG_WATCHDOG=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_DRM=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_EFI=y
+CONFIG_FB_GOLDFISH=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_PRODIKEYS=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_HOLTEK=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WALTOP=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_PRIMAX=y
+CONFIG_HID_ROCCAT=y
+CONFIG_HID_SAITEK=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SPEEDLINK=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_WIIMOTE=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+CONFIG_USB_PRINTER=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_EDAC=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_DMADEVICES=y
+CONFIG_VIRTIO_PCI=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
+CONFIG_ION=y
+CONFIG_GOLDFISH_AUDIO=y
+CONFIG_GOLDFISH_SYNC=y
+CONFIG_SND_HDA_INTEL=y
+CONFIG_GOLDFISH=y
+CONFIG_GOLDFISH_PIPE=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ISCSI_IBFT_FIND=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_PSTORE=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_RAM=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_SCHED_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
+CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_ASYMMETRIC_KEY_TYPE=y
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
+CONFIG_X509_CERTIFICATE_PARSER=y
+CONFIG_PKCS7_MESSAGE_PARSER=y
+CONFIG_PKCS7_TEST_KEY=y
+# CONFIG_VIRTUALIZATION is not set
+CONFIG_CRC_T10DIF=y
diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c
index 440df0c..a69321a 100644
--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c
+++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c
@@ -219,6 +219,29 @@
 	}
 }
 
+static int ghash_async_import(struct ahash_request *req, const void *in)
+{
+	struct ahash_request *cryptd_req = ahash_request_ctx(req);
+	struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
+
+	ghash_async_init(req);
+	memcpy(dctx, in, sizeof(*dctx));
+	return 0;
+
+}
+
+static int ghash_async_export(struct ahash_request *req, void *out)
+{
+	struct ahash_request *cryptd_req = ahash_request_ctx(req);
+	struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
+
+	memcpy(out, dctx, sizeof(*dctx));
+	return 0;
+
+}
+
 static int ghash_async_digest(struct ahash_request *req)
 {
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -288,8 +311,11 @@
 	.final		= ghash_async_final,
 	.setkey		= ghash_async_setkey,
 	.digest		= ghash_async_digest,
+	.export		= ghash_async_export,
+	.import		= ghash_async_import,
 	.halg = {
 		.digestsize	= GHASH_DIGEST_SIZE,
+		.statesize = sizeof(struct ghash_desc_ctx),
 		.base = {
 			.cra_name		= "ghash",
 			.cra_driver_name	= "ghash-clmulni",
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index f3b6d54..ae678ad 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -766,8 +766,8 @@
 	jmp	ftrace_stub
 #endif
 
-.globl ftrace_stub
-ftrace_stub:
+/* This is weak to keep gas from relaxing the jumps */
+WEAK(ftrace_stub)
 	ret
 END(ftrace_caller)
 
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index f17705e..e62f440 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -294,7 +294,7 @@
 # 285 sys_setaltroot
 286	i386	add_key			sys_add_key
 287	i386	request_key		sys_request_key
-288	i386	keyctl			sys_keyctl
+288	i386	keyctl			sys_keyctl			compat_sys_keyctl
 289	i386	ioprio_set		sys_ioprio_set
 290	i386	ioprio_get		sys_ioprio_get
 291	i386	inotify_init		sys_inotify_init
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
index 265c0ed..7af017a 100644
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -187,10 +187,10 @@
 $(MODLIB)/vdso: FORCE
 	@mkdir -p $(MODLIB)/vdso
 
-$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso FORCE
+$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso
 	$(call cmd,vdso_install)
 
 PHONY += vdso_install $(vdso_img_insttargets)
-vdso_install: $(vdso_img_insttargets) FORCE
+vdso_install: $(vdso_img_insttargets)
 
 clean-files := vdso32.so vdso32.so.dbg vdso64* vdso-image-*.c vdsox32.so*
diff --git a/arch/x86/entry/vdso/vdso2c.h b/arch/x86/entry/vdso/vdso2c.h
index 0224987..3f69326 100644
--- a/arch/x86/entry/vdso/vdso2c.h
+++ b/arch/x86/entry/vdso/vdso2c.h
@@ -140,7 +140,7 @@
 	fprintf(outfile, "#include <asm/vdso.h>\n");
 	fprintf(outfile, "\n");
 	fprintf(outfile,
-		"static unsigned char raw_data[%lu] __page_aligned_data = {",
+		"static unsigned char raw_data[%lu] __ro_after_init __aligned(PAGE_SIZE) = {",
 		mapping_size);
 	for (j = 0; j < stripped_len; j++) {
 		if (j % 10 == 0)
diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c
index 08a317a..a7508d7 100644
--- a/arch/x86/entry/vdso/vdso32-setup.c
+++ b/arch/x86/entry/vdso/vdso32-setup.c
@@ -31,8 +31,10 @@
 {
 	vdso32_enabled = simple_strtoul(s, NULL, 0);
 
-	if (vdso32_enabled > 1)
+	if (vdso32_enabled > 1) {
 		pr_warn("vdso32 values other than 0 and 1 are no longer allowed; vdso disabled\n");
+		vdso32_enabled = 0;
+	}
 
 	return 1;
 }
@@ -63,13 +65,18 @@
 /* Register vsyscall32 into the ABI table */
 #include <linux/sysctl.h>
 
+static const int zero;
+static const int one = 1;
+
 static struct ctl_table abi_table2[] = {
 	{
 		.procname	= "vsyscall32",
 		.data		= &vdso32_enabled,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= (int *)&zero,
+		.extra2		= (int *)&one,
 	},
 	{}
 };
diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h
index e63aa38..61518cf 100644
--- a/arch/x86/include/asm/cacheflush.h
+++ b/arch/x86/include/asm/cacheflush.h
@@ -91,16 +91,10 @@
 
 #define mmio_flush_range(addr, size) clflush_cache_range(addr, size)
 
-#ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
 extern const int rodata_test_data;
 extern int kernel_set_to_readonly;
 void set_kernel_text_rw(void);
 void set_kernel_text_ro(void);
-#else
-static inline void set_kernel_text_rw(void) { }
-static inline void set_kernel_text_ro(void) { }
-#endif
 
 #ifdef CONFIG_DEBUG_RODATA_TEST
 int rodata_test(void);
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 0010c78..08b1f2f 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -25,6 +25,8 @@
 #define EFI32_LOADER_SIGNATURE	"EL32"
 #define EFI64_LOADER_SIGNATURE	"EL64"
 
+#define MAX_CMDLINE_ADDRESS	UINT_MAX
+
 #ifdef CONFIG_X86_32
 
 
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 1514753..d262f98 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -278,7 +278,7 @@
 
 #define	ARCH_DLINFO_IA32						\
 do {									\
-	if (vdso32_enabled) {						\
+	if (VDSO_CURRENT_BASE) {					\
 		NEW_AUX_ENT(AT_SYSINFO,	VDSO_ENTRY);			\
 		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE);	\
 	}								\
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index e9cd7be..19d14ac 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -221,6 +221,9 @@
 	void (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
 			  u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 	void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked);
+
+	unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt);
+	void (*set_hflags)(struct x86_emulate_ctxt *ctxt, unsigned hflags);
 };
 
 typedef u32 __attribute__((vector_size(16))) sse128_t;
@@ -290,7 +293,6 @@
 
 	/* interruptibility state, as a result of execution of STI or MOV SS */
 	int interruptibility;
-	int emul_flags;
 
 	bool perm_ok; /* do not check permissions if true */
 	bool ud;	/* inject an #UD if host doesn't support insn */
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index c1adf33..bc62e7c 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -17,15 +17,8 @@
 }
 #endif /* CONFIG_KVM_GUEST */
 
-#ifdef CONFIG_DEBUG_RODATA
 #define KVM_HYPERCALL \
         ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL)
-#else
-/* On AMD processors, vmcall will generate a trap that we will
- * then rewrite to the appropriate instruction.
- */
-#define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1"
-#endif
 
 /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall
  * instruction.  The hypervisor may replace it with something else but only the
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index b94f6f6..dbff145 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -24,6 +24,7 @@
 #define _ASM_X86_MTRR_H
 
 #include <uapi/asm/mtrr.h>
+#include <asm/pat.h>
 
 
 /*
@@ -83,9 +84,12 @@
 static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 {
 }
+static inline void mtrr_bp_init(void)
+{
+	pat_disable("MTRRs disabled, skipping PAT initialization too.");
+}
 
 #define mtrr_ap_init() do {} while (0)
-#define mtrr_bp_init() do {} while (0)
 #define set_mtrr_aps_delayed_init() do {} while (0)
 #define mtrr_aps_init() do {} while (0)
 #define mtrr_bp_restore() do {} while (0)
diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h
index ca6c228..fffb279 100644
--- a/arch/x86/include/asm/pat.h
+++ b/arch/x86/include/asm/pat.h
@@ -5,8 +5,9 @@
 #include <asm/pgtable_types.h>
 
 bool pat_enabled(void);
+void pat_disable(const char *reason);
 extern void pat_init(void);
-void pat_init_cache_modes(u64);
+extern void init_cache_modes(void);
 
 extern int reserve_memtype(u64 start, u64 end,
 		enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm);
diff --git a/arch/x86/include/asm/pmem.h b/arch/x86/include/asm/pmem.h
index d8ce3ec..6503526 100644
--- a/arch/x86/include/asm/pmem.h
+++ b/arch/x86/include/asm/pmem.h
@@ -72,8 +72,8 @@
  * @size:	number of bytes to write back
  *
  * Write back a cache range using the CLWB (cache line write back)
- * instruction.  This function requires explicit ordering with an
- * arch_wmb_pmem() call.  This API is internal to the x86 PMEM implementation.
+ * instruction. Note that @size is internally rounded up to be cache
+ * line size aligned.
  */
 static inline void __arch_wb_cache_pmem(void *vaddr, size_t size)
 {
@@ -87,15 +87,6 @@
 		clwb(p);
 }
 
-/*
- * copy_from_iter_nocache() on x86 only uses non-temporal stores for iovec
- * iterators, so for other types (bvec & kvec) we must do a cache write-back.
- */
-static inline bool __iter_needs_pmem_wb(struct iov_iter *i)
-{
-	return iter_is_iovec(i) == false;
-}
-
 /**
  * arch_copy_from_iter_pmem - copy data from an iterator to PMEM
  * @addr:	PMEM destination address
@@ -114,8 +105,36 @@
 	/* TODO: skip the write-back by always using non-temporal stores */
 	len = copy_from_iter_nocache(vaddr, bytes, i);
 
-	if (__iter_needs_pmem_wb(i))
-		__arch_wb_cache_pmem(vaddr, bytes);
+	/*
+	 * In the iovec case on x86_64 copy_from_iter_nocache() uses
+	 * non-temporal stores for the bulk of the transfer, but we need
+	 * to manually flush if the transfer is unaligned. A cached
+	 * memory copy is used when destination or size is not naturally
+	 * aligned. That is:
+	 *   - Require 8-byte alignment when size is 8 bytes or larger.
+	 *   - Require 4-byte alignment when size is 4 bytes.
+	 *
+	 * In the non-iovec case the entire destination needs to be
+	 * flushed.
+	 */
+	if (iter_is_iovec(i)) {
+		unsigned long flushed, dest = (unsigned long) addr;
+
+		if (bytes < 8) {
+			if (!IS_ALIGNED(dest, 4) || (bytes != 4))
+				__arch_wb_cache_pmem(addr, bytes);
+		} else {
+			if (!IS_ALIGNED(dest, 8)) {
+				dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
+				__arch_wb_cache_pmem(addr, 1);
+			}
+
+			flushed = dest - (unsigned long) addr;
+			if (bytes > flushed && !IS_ALIGNED(bytes - flushed, 8))
+				__arch_wb_cache_pmem(addr + bytes - 1, 1);
+		}
+	} else
+		__arch_wb_cache_pmem(addr, bytes);
 
 	return len;
 }
diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h
index 7a6bed5..baad72e 100644
--- a/arch/x86/include/asm/pvclock.h
+++ b/arch/x86/include/asm/pvclock.h
@@ -76,6 +76,8 @@
 	u8 ret_flags;
 
 	version = src->version;
+	/* Make the latest version visible */
+	smp_rmb();
 
 	offset = pvclock_get_nsec_offset(src);
 	ret = src->system_time + offset;
diff --git a/arch/x86/include/asm/sections.h b/arch/x86/include/asm/sections.h
index 0a52424..13b6cdd 100644
--- a/arch/x86/include/asm/sections.h
+++ b/arch/x86/include/asm/sections.h
@@ -7,7 +7,7 @@
 extern char __brk_base[], __brk_limit[];
 extern struct exception_table_entry __stop___ex_table[];
 
-#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
+#if defined(CONFIG_X86_64)
 extern char __end_rodata_hpage_align[];
 #endif
 
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index c7b5510..0c977fc 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -177,6 +177,50 @@
 	return sp;
 }
 
+/*
+ * Walks up the stack frames to make sure that the specified object is
+ * entirely contained by a single stack frame.
+ *
+ * Returns:
+ *		 1 if within a frame
+ *		-1 if placed across a frame boundary (or outside stack)
+ *		 0 unable to determine (no frame pointers, etc)
+ */
+static inline int arch_within_stack_frames(const void * const stack,
+					   const void * const stackend,
+					   const void *obj, unsigned long len)
+{
+#if defined(CONFIG_FRAME_POINTER)
+	const void *frame = NULL;
+	const void *oldframe;
+
+	oldframe = __builtin_frame_address(1);
+	if (oldframe)
+		frame = __builtin_frame_address(2);
+	/*
+	 * low ----------------------------------------------> high
+	 * [saved bp][saved ip][args][local vars][saved bp][saved ip]
+	 *                     ^----------------^
+	 *               allow copies only within here
+	 */
+	while (stack <= frame && frame < stackend) {
+		/*
+		 * If obj + len extends past the last frame, this
+		 * check won't pass and the next frame will be 0,
+		 * causing us to bail out and correctly report
+		 * the copy as invalid.
+		 */
+		if (obj + len <= frame)
+			return obj >= oldframe + 2 * sizeof(void *) ? 1 : -1;
+		oldframe = frame;
+		frame = *(const void * const *)frame;
+	}
+	return -1;
+#else
+	return 0;
+#endif
+}
+
 #else /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_X86_64
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 6df2029..6433e28 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -32,7 +32,7 @@
 /* Initialize cr4 shadow for this CPU. */
 static inline void cr4_init_shadow(void)
 {
-	this_cpu_write(cpu_tlbstate.cr4, __read_cr4());
+	this_cpu_write(cpu_tlbstate.cr4, __read_cr4_safe());
 }
 
 /* Set in this cpu's CR4. */
@@ -86,7 +86,14 @@
 
 static inline void __native_flush_tlb(void)
 {
+	/*
+	 * If current->mm == NULL then we borrow a mm which may change during a
+	 * task switch and therefore we must not be preempted while we write CR3
+	 * back:
+	 */
+	preempt_disable();
 	native_write_cr3(native_read_cr3());
+	preempt_enable();
 }
 
 static inline void __native_flush_tlb_global_irq_disabled(void)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 09b1b0a..7402eb4 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -134,6 +134,9 @@
 extern int __get_user_8(void);
 extern int __get_user_bad(void);
 
+#define __uaccess_begin() stac()
+#define __uaccess_end()   clac()
+
 /*
  * This is a type: either unsigned long, if the argument fits into
  * that type, or otherwise unsigned long long.
@@ -193,10 +196,10 @@
 
 #ifdef CONFIG_X86_32
 #define __put_user_asm_u64(x, addr, err, errret)			\
-	asm volatile(ASM_STAC "\n"					\
+	asm volatile("\n"						\
 		     "1:	movl %%eax,0(%2)\n"			\
 		     "2:	movl %%edx,4(%2)\n"			\
-		     "3: " ASM_CLAC "\n"				\
+		     "3:"						\
 		     ".section .fixup,\"ax\"\n"				\
 		     "4:	movl %3,%0\n"				\
 		     "	jmp 3b\n"					\
@@ -207,10 +210,10 @@
 		     : "A" (x), "r" (addr), "i" (errret), "0" (err))
 
 #define __put_user_asm_ex_u64(x, addr)					\
-	asm volatile(ASM_STAC "\n"					\
+	asm volatile("\n"						\
 		     "1:	movl %%eax,0(%1)\n"			\
 		     "2:	movl %%edx,4(%1)\n"			\
-		     "3: " ASM_CLAC "\n"				\
+		     "3:"						\
 		     _ASM_EXTABLE_EX(1b, 2b)				\
 		     _ASM_EXTABLE_EX(2b, 3b)				\
 		     : : "A" (x), "r" (addr))
@@ -304,6 +307,10 @@
 	}								\
 } while (0)
 
+/*
+ * This doesn't do __uaccess_begin/end - the exception handling
+ * around it must do that.
+ */
 #define __put_user_size_ex(x, ptr, size)				\
 do {									\
 	__chk_user_ptr(ptr);						\
@@ -332,7 +339,7 @@
 #define __get_user_asm_u64(x, ptr, retval, errret) \
 	 __get_user_asm(x, ptr, retval, "q", "", "=r", errret)
 #define __get_user_asm_ex_u64(x, ptr) \
-	 __get_user_asm_ex(x, ptr, "q", "", "=r")
+	 __get_user_asm_ex(x, ptr, "q", "", "=&r")
 #endif
 
 #define __get_user_size(x, ptr, size, retval, errret)			\
@@ -358,9 +365,9 @@
 } while (0)
 
 #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
-	asm volatile(ASM_STAC "\n"					\
+	asm volatile("\n"						\
 		     "1:	mov"itype" %2,%"rtype"1\n"		\
-		     "2: " ASM_CLAC "\n"				\
+		     "2:\n"						\
 		     ".section .fixup,\"ax\"\n"				\
 		     "3:	mov %3,%0\n"				\
 		     "	xor"itype" %"rtype"1,%"rtype"1\n"		\
@@ -370,18 +377,22 @@
 		     : "=r" (err), ltype(x)				\
 		     : "m" (__m(addr)), "i" (errret), "0" (err))
 
+/*
+ * This doesn't do __uaccess_begin/end - the exception handling
+ * around it must do that.
+ */
 #define __get_user_size_ex(x, ptr, size)				\
 do {									\
 	__chk_user_ptr(ptr);						\
 	switch (size) {							\
 	case 1:								\
-		__get_user_asm_ex(x, ptr, "b", "b", "=q");		\
+		__get_user_asm_ex(x, ptr, "b", "b", "=&q");		\
 		break;							\
 	case 2:								\
-		__get_user_asm_ex(x, ptr, "w", "w", "=r");		\
+		__get_user_asm_ex(x, ptr, "w", "w", "=&r");		\
 		break;							\
 	case 4:								\
-		__get_user_asm_ex(x, ptr, "l", "k", "=r");		\
+		__get_user_asm_ex(x, ptr, "l", "k", "=&r");		\
 		break;							\
 	case 8:								\
 		__get_user_asm_ex_u64(x, ptr);				\
@@ -395,12 +406,14 @@
 	asm volatile("1:	mov"itype" %1,%"rtype"0\n"		\
 		     "2:\n"						\
 		     _ASM_EXTABLE_EX(1b, 2b)				\
-		     : ltype(x) : "m" (__m(addr)))
+		     : ltype(x) : "m" (__m(addr)), "0" (0))
 
 #define __put_user_nocheck(x, ptr, size)			\
 ({								\
 	int __pu_err;						\
+	__uaccess_begin();					\
 	__put_user_size((x), (ptr), (size), __pu_err, -EFAULT);	\
+	__uaccess_end();					\
 	__builtin_expect(__pu_err, 0);				\
 })
 
@@ -408,7 +421,9 @@
 ({									\
 	int __gu_err;							\
 	unsigned long __gu_val;						\
+	__uaccess_begin();						\
 	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
+	__uaccess_end();						\
 	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
 	__builtin_expect(__gu_err, 0);					\
 })
@@ -423,9 +438,9 @@
  * aliasing issues.
  */
 #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
-	asm volatile(ASM_STAC "\n"					\
+	asm volatile("\n"						\
 		     "1:	mov"itype" %"rtype"1,%2\n"		\
-		     "2: " ASM_CLAC "\n"				\
+		     "2:\n"						\
 		     ".section .fixup,\"ax\"\n"				\
 		     "3:	mov %3,%0\n"				\
 		     "	jmp 2b\n"					\
@@ -445,11 +460,11 @@
  */
 #define uaccess_try	do {						\
 	current_thread_info()->uaccess_err = 0;				\
-	stac();								\
+	__uaccess_begin();						\
 	barrier();
 
 #define uaccess_catch(err)						\
-	clac();								\
+	__uaccess_end();						\
 	(err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0);	\
 } while (0)
 
@@ -547,12 +562,13 @@
 	__typeof__(ptr) __uval = (uval);				\
 	__typeof__(*(ptr)) __old = (old);				\
 	__typeof__(*(ptr)) __new = (new);				\
+	__uaccess_begin();						\
 	switch (size) {							\
 	case 1:								\
 	{								\
-		asm volatile("\t" ASM_STAC "\n"				\
+		asm volatile("\n"					\
 			"1:\t" LOCK_PREFIX "cmpxchgb %4, %2\n"		\
-			"2:\t" ASM_CLAC "\n"				\
+			"2:\n"						\
 			"\t.section .fixup, \"ax\"\n"			\
 			"3:\tmov     %3, %0\n"				\
 			"\tjmp     2b\n"				\
@@ -566,9 +582,9 @@
 	}								\
 	case 2:								\
 	{								\
-		asm volatile("\t" ASM_STAC "\n"				\
+		asm volatile("\n"					\
 			"1:\t" LOCK_PREFIX "cmpxchgw %4, %2\n"		\
-			"2:\t" ASM_CLAC "\n"				\
+			"2:\n"						\
 			"\t.section .fixup, \"ax\"\n"			\
 			"3:\tmov     %3, %0\n"				\
 			"\tjmp     2b\n"				\
@@ -582,9 +598,9 @@
 	}								\
 	case 4:								\
 	{								\
-		asm volatile("\t" ASM_STAC "\n"				\
+		asm volatile("\n"					\
 			"1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"		\
-			"2:\t" ASM_CLAC "\n"				\
+			"2:\n"						\
 			"\t.section .fixup, \"ax\"\n"			\
 			"3:\tmov     %3, %0\n"				\
 			"\tjmp     2b\n"				\
@@ -601,9 +617,9 @@
 		if (!IS_ENABLED(CONFIG_X86_64))				\
 			__cmpxchg_wrong_size();				\
 									\
-		asm volatile("\t" ASM_STAC "\n"				\
+		asm volatile("\n"					\
 			"1:\t" LOCK_PREFIX "cmpxchgq %4, %2\n"		\
-			"2:\t" ASM_CLAC "\n"				\
+			"2:\n"						\
 			"\t.section .fixup, \"ax\"\n"			\
 			"3:\tmov     %3, %0\n"				\
 			"\tjmp     2b\n"				\
@@ -618,6 +634,7 @@
 	default:							\
 		__cmpxchg_wrong_size();					\
 	}								\
+	__uaccess_end();						\
 	*__uval = __old;						\
 	__ret;								\
 })
@@ -689,7 +706,7 @@
 
 #endif
 
-static inline unsigned long __must_check
+static __always_inline unsigned long __must_check
 copy_from_user(void *to, const void __user *from, unsigned long n)
 {
 	int sz = __compiletime_object_size(to);
@@ -714,9 +731,10 @@
 	 * case, and do only runtime checking for non-constant sizes.
 	 */
 
-	if (likely(sz < 0 || sz >= n))
+	if (likely(sz < 0 || sz >= n)) {
+		check_object_size(to, n, false);
 		n = _copy_from_user(to, from, n);
-	else if(__builtin_constant_p(n))
+	} else if (__builtin_constant_p(n))
 		copy_from_user_overflow();
 	else
 		__copy_from_user_overflow(sz, n);
@@ -724,7 +742,7 @@
 	return n;
 }
 
-static inline unsigned long __must_check
+static __always_inline unsigned long __must_check
 copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 	int sz = __compiletime_object_size(from);
@@ -732,9 +750,10 @@
 	might_fault();
 
 	/* See the comment in copy_from_user() above. */
-	if (likely(sz < 0 || sz >= n))
+	if (likely(sz < 0 || sz >= n)) {
+		check_object_size(from, n, true);
 		n = _copy_to_user(to, from, n);
-	else if(__builtin_constant_p(n))
+	} else if (__builtin_constant_p(n))
 		copy_to_user_overflow();
 	else
 		__copy_to_user_overflow(sz, n);
@@ -745,5 +764,30 @@
 #undef __copy_from_user_overflow
 #undef __copy_to_user_overflow
 
+/*
+ * The "unsafe" user accesses aren't really "unsafe", but the naming
+ * is a big fat warning: you have to not only do the access_ok()
+ * checking before using them, but you have to surround them with the
+ * user_access_begin/end() pair.
+ */
+#define user_access_begin()	__uaccess_begin()
+#define user_access_end()	__uaccess_end()
+
+#define unsafe_put_user(x, ptr, err_label)					\
+do {										\
+	int __pu_err;								\
+	__put_user_size((x), (ptr), sizeof(*(ptr)), __pu_err, -EFAULT);		\
+	if (unlikely(__pu_err)) goto err_label;					\
+} while (0)
+
+#define unsafe_get_user(x, ptr, err_label)					\
+do {										\
+	int __gu_err;								\
+	unsigned long __gu_val;							\
+	__get_user_size(__gu_val, (ptr), sizeof(*(ptr)), __gu_err, -EFAULT);	\
+	(x) = (__force __typeof__(*(ptr)))__gu_val;				\
+	if (unlikely(__gu_err)) goto err_label;					\
+} while (0)
+
 #endif /* _ASM_X86_UACCESS_H */
 
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index f5dcb52..c3724ac 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -43,25 +43,34 @@
 static __always_inline unsigned long __must_check
 __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 {
+	check_object_size(from, n, true);
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__put_user_size(*(u8 *)from, (u8 __user *)to,
 					1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__put_user_size(*(u16 *)from, (u16 __user *)to,
 					2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__put_user_size(*(u32 *)from, (u32 __user *)to,
 					4, ret, 4);
+			__uaccess_end();
 			return ret;
 		case 8:
+			__uaccess_begin();
 			__put_user_size(*(u64 *)from, (u64 __user *)to,
 					8, ret, 8);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -103,13 +112,19 @@
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -143,18 +158,25 @@
 __copy_from_user(void *to, const void __user *from, unsigned long n)
 {
 	might_fault();
+	check_object_size(to, n, false);
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -170,13 +192,19 @@
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index f2f9b39..2957c82 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -53,38 +53,53 @@
 {
 	int ret = 0;
 
+	check_object_size(dst, size, false);
 	if (!__builtin_constant_p(size))
 		return copy_user_generic(dst, (__force void *)src, size);
 	switch (size) {
-	case 1:__get_user_asm(*(u8 *)dst, (u8 __user *)src,
+	case 1:
+		__uaccess_begin();
+		__get_user_asm(*(u8 *)dst, (u8 __user *)src,
 			      ret, "b", "b", "=q", 1);
+		__uaccess_end();
 		return ret;
-	case 2:__get_user_asm(*(u16 *)dst, (u16 __user *)src,
+	case 2:
+		__uaccess_begin();
+		__get_user_asm(*(u16 *)dst, (u16 __user *)src,
 			      ret, "w", "w", "=r", 2);
+		__uaccess_end();
 		return ret;
-	case 4:__get_user_asm(*(u32 *)dst, (u32 __user *)src,
+	case 4:
+		__uaccess_begin();
+		__get_user_asm(*(u32 *)dst, (u32 __user *)src,
 			      ret, "l", "k", "=r", 4);
+		__uaccess_end();
 		return ret;
-	case 8:__get_user_asm(*(u64 *)dst, (u64 __user *)src,
+	case 8:
+		__uaccess_begin();
+		__get_user_asm(*(u64 *)dst, (u64 __user *)src,
 			      ret, "q", "", "=r", 8);
+		__uaccess_end();
 		return ret;
 	case 10:
+		__uaccess_begin();
 		__get_user_asm(*(u64 *)dst, (u64 __user *)src,
 			       ret, "q", "", "=r", 10);
-		if (unlikely(ret))
-			return ret;
-		__get_user_asm(*(u16 *)(8 + (char *)dst),
-			       (u16 __user *)(8 + (char __user *)src),
-			       ret, "w", "w", "=r", 2);
+		if (likely(!ret))
+			__get_user_asm(*(u16 *)(8 + (char *)dst),
+				       (u16 __user *)(8 + (char __user *)src),
+				       ret, "w", "w", "=r", 2);
+		__uaccess_end();
 		return ret;
 	case 16:
+		__uaccess_begin();
 		__get_user_asm(*(u64 *)dst, (u64 __user *)src,
 			       ret, "q", "", "=r", 16);
-		if (unlikely(ret))
-			return ret;
-		__get_user_asm(*(u64 *)(8 + (char *)dst),
-			       (u64 __user *)(8 + (char __user *)src),
-			       ret, "q", "", "=r", 8);
+		if (likely(!ret))
+			__get_user_asm(*(u64 *)(8 + (char *)dst),
+				       (u64 __user *)(8 + (char __user *)src),
+				       ret, "q", "", "=r", 8);
+		__uaccess_end();
 		return ret;
 	default:
 		return copy_user_generic(dst, (__force void *)src, size);
@@ -103,38 +118,55 @@
 {
 	int ret = 0;
 
+	check_object_size(src, size, true);
 	if (!__builtin_constant_p(size))
 		return copy_user_generic((__force void *)dst, src, size);
 	switch (size) {
-	case 1:__put_user_asm(*(u8 *)src, (u8 __user *)dst,
+	case 1:
+		__uaccess_begin();
+		__put_user_asm(*(u8 *)src, (u8 __user *)dst,
 			      ret, "b", "b", "iq", 1);
+		__uaccess_end();
 		return ret;
-	case 2:__put_user_asm(*(u16 *)src, (u16 __user *)dst,
+	case 2:
+		__uaccess_begin();
+		__put_user_asm(*(u16 *)src, (u16 __user *)dst,
 			      ret, "w", "w", "ir", 2);
+		__uaccess_end();
 		return ret;
-	case 4:__put_user_asm(*(u32 *)src, (u32 __user *)dst,
+	case 4:
+		__uaccess_begin();
+		__put_user_asm(*(u32 *)src, (u32 __user *)dst,
 			      ret, "l", "k", "ir", 4);
+		__uaccess_end();
 		return ret;
-	case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst,
+	case 8:
+		__uaccess_begin();
+		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
 			      ret, "q", "", "er", 8);
+		__uaccess_end();
 		return ret;
 	case 10:
+		__uaccess_begin();
 		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
 			       ret, "q", "", "er", 10);
-		if (unlikely(ret))
-			return ret;
-		asm("":::"memory");
-		__put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst,
-			       ret, "w", "w", "ir", 2);
+		if (likely(!ret)) {
+			asm("":::"memory");
+			__put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst,
+				       ret, "w", "w", "ir", 2);
+		}
+		__uaccess_end();
 		return ret;
 	case 16:
+		__uaccess_begin();
 		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
 			       ret, "q", "", "er", 16);
-		if (unlikely(ret))
-			return ret;
-		asm("":::"memory");
-		__put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
-			       ret, "q", "", "er", 8);
+		if (likely(!ret)) {
+			asm("":::"memory");
+			__put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
+				       ret, "q", "", "er", 8);
+		}
+		__uaccess_end();
 		return ret;
 	default:
 		return copy_user_generic((__force void *)dst, src, size);
@@ -160,39 +192,47 @@
 	switch (size) {
 	case 1: {
 		u8 tmp;
+		__uaccess_begin();
 		__get_user_asm(tmp, (u8 __user *)src,
 			       ret, "b", "b", "=q", 1);
 		if (likely(!ret))
 			__put_user_asm(tmp, (u8 __user *)dst,
 				       ret, "b", "b", "iq", 1);
+		__uaccess_end();
 		return ret;
 	}
 	case 2: {
 		u16 tmp;
+		__uaccess_begin();
 		__get_user_asm(tmp, (u16 __user *)src,
 			       ret, "w", "w", "=r", 2);
 		if (likely(!ret))
 			__put_user_asm(tmp, (u16 __user *)dst,
 				       ret, "w", "w", "ir", 2);
+		__uaccess_end();
 		return ret;
 	}
 
 	case 4: {
 		u32 tmp;
+		__uaccess_begin();
 		__get_user_asm(tmp, (u32 __user *)src,
 			       ret, "l", "k", "=r", 4);
 		if (likely(!ret))
 			__put_user_asm(tmp, (u32 __user *)dst,
 				       ret, "l", "k", "ir", 4);
+		__uaccess_end();
 		return ret;
 	}
 	case 8: {
 		u64 tmp;
+		__uaccess_begin();
 		__get_user_asm(tmp, (u64 __user *)src,
 			       ret, "q", "", "=r", 8);
 		if (likely(!ret))
 			__put_user_asm(tmp, (u64 __user *)dst,
 				       ret, "q", "", "er", 8);
+		__uaccess_end();
 		return ret;
 	}
 	default:
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 29fa475..c986d0b 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -71,8 +71,8 @@
 	while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL)
 		i++;
 
-	if (i == 0)
-		return 0;
+	if (!i)
+		return -ENODEV;
 
 	nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL);
 	if (!nb)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 2f69e3b..a3e1f84 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1587,6 +1587,9 @@
 	unsigned long flags;
 	int ret, ir_stat;
 
+	if (skip_ioapic_setup)
+		return;
+
 	ir_stat = irq_remapping_prepare();
 	if (ir_stat < 0 && !x2apic_supported())
 		return;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index fdb0fbf..1e5d2f0 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1875,6 +1875,7 @@
 	.irq_ack		= irq_chip_ack_parent,
 	.irq_eoi		= ioapic_ack_level,
 	.irq_set_affinity	= ioapic_set_affinity,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -1886,6 +1887,7 @@
 	.irq_ack		= irq_chip_ack_parent,
 	.irq_eoi		= ioapic_ir_ack_level,
 	.irq_set_affinity	= ioapic_set_affinity,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -2115,6 +2117,7 @@
 			if (idx != -1 && irq_trigger(idx))
 				unmask_ioapic_irq(irq_get_chip_data(0));
 		}
+		irq_domain_deactivate_irq(irq_data);
 		irq_domain_activate_irq(irq_data);
 		if (timer_irq_works()) {
 			if (disable_timer_pin_1 > 0)
@@ -2136,6 +2139,7 @@
 		 * legacy devices should be connected to IO APIC #0
 		 */
 		replace_pin_at_irq_node(data, node, apic1, pin1, apic2, pin2);
+		irq_domain_deactivate_irq(irq_data);
 		irq_domain_activate_irq(irq_data);
 		legacy_pic->unmask(0);
 		if (timer_irq_works()) {
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index df6b4ee..0988e20 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -659,11 +659,28 @@
  */
 void irq_force_complete_move(struct irq_desc *desc)
 {
-	struct irq_data *irqdata = irq_desc_get_irq_data(desc);
-	struct apic_chip_data *data = apic_chip_data(irqdata);
-	struct irq_cfg *cfg = data ? &data->cfg : NULL;
+	struct irq_data *irqdata;
+	struct apic_chip_data *data;
+	struct irq_cfg *cfg;
 	unsigned int cpu;
 
+	/*
+	 * The function is called for all descriptors regardless of which
+	 * irqdomain they belong to. For example if an IRQ is provided by
+	 * an irq_chip as part of a GPIO driver, the chip data for that
+	 * descriptor is specific to the irq_chip in question.
+	 *
+	 * Check first that the chip_data is what we expect
+	 * (apic_chip_data) before touching it any further.
+	 */
+	irqdata = irq_domain_get_irq_data(x86_vector_domain,
+					  irq_desc_get_irq(desc));
+	if (!irqdata)
+		return;
+
+	data = apic_chip_data(irqdata);
+	cfg = data ? &data->cfg : NULL;
+
 	if (!cfg)
 		return;
 
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index a8816b3..e2defc7 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -352,7 +352,6 @@
 #ifdef CONFIG_SMP
 	unsigned bits;
 	int cpu = smp_processor_id();
-	unsigned int socket_id, core_complex_id;
 
 	bits = c->x86_coreid_bits;
 	/* Low order bits define the core id (index of core in socket) */
@@ -370,10 +369,7 @@
 	 if (c->x86 != 0x17 || !cpuid_edx(0x80000006))
 		return;
 
-	socket_id	= (c->apicid >> bits) - 1;
-	core_complex_id	= (c->apicid & ((1 << bits) - 1)) >> 3;
-
-	per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
+	per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
 #endif
 }
 
@@ -656,6 +652,17 @@
 		set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
 }
 
+#define MSR_AMD64_DE_CFG	0xC0011029
+
+static void init_amd_ln(struct cpuinfo_x86 *c)
+{
+	/*
+	 * Apply erratum 665 fix unconditionally so machines without a BIOS
+	 * fix work.
+	 */
+	msr_set_bit(MSR_AMD64_DE_CFG, 31);
+}
+
 static void init_amd_bd(struct cpuinfo_x86 *c)
 {
 	u64 value;
@@ -713,6 +720,7 @@
 	case 6:	   init_amd_k7(c); break;
 	case 0xf:  init_amd_k8(c); break;
 	case 0x10: init_amd_gh(c); break;
+	case 0x12: init_amd_ln(c); break;
 	case 0x15: init_amd_bd(c); break;
 	}
 
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index c2b7522..637ca41 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -737,21 +737,20 @@
 		identify_cpu_without_cpuid(c);
 
 	/* cyrix could have cpuid enabled via c_identify()*/
-	if (!have_cpuid_p())
-		return;
+	if (have_cpuid_p()) {
+		cpu_detect(c);
+		get_cpu_vendor(c);
+		get_cpu_cap(c);
 
-	cpu_detect(c);
-	get_cpu_vendor(c);
-	get_cpu_cap(c);
+		if (this_cpu->c_early_init)
+			this_cpu->c_early_init(c);
 
-	if (this_cpu->c_early_init)
-		this_cpu->c_early_init(c);
+		c->cpu_index = 0;
+		filter_cpuid_features(c, false);
 
-	c->cpu_index = 0;
-	filter_cpuid_features(c, false);
-
-	if (this_cpu->c_bsp_init)
-		this_cpu->c_bsp_init(c);
+		if (this_cpu->c_bsp_init)
+			this_cpu->c_bsp_init(c);
+	}
 
 	setup_force_cpu_cap(X86_FEATURE_ALWAYS);
 	fpu__init_system(c);
@@ -1130,7 +1129,7 @@
 {
 	int bit;
 
-	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
+	if (get_option(&arg, &bit) && bit >= 0 && bit < NCAPINTS * 32)
 		setup_clear_cpu_cap(bit);
 	else
 		return 0;
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index e99b150..62aca44 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -53,7 +53,7 @@
 	"load_store",
 	"insn_fetch",
 	"combined_unit",
-	"",
+	"decode_unit",
 	"northbridge",
 	"execution_unit",
 };
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 20e242e..83b5f7a 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -30,6 +30,7 @@
 #include <asm/apic.h>
 #include <asm/timer.h>
 #include <asm/reboot.h>
+#include <asm/nmi.h>
 
 struct ms_hyperv_info ms_hyperv;
 EXPORT_SYMBOL_GPL(ms_hyperv);
@@ -152,6 +153,31 @@
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+static unsigned char hv_get_nmi_reason(void)
+{
+	return 0;
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+/*
+ * Prior to WS2016 Debug-VM sends NMIs to all CPUs which makes
+ * it dificult to process CHANNELMSG_UNLOAD in case of crash. Handle
+ * unknown NMI on the first CPU which gets it.
+ */
+static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
+{
+	static atomic_t nmi_cpu = ATOMIC_INIT(-1);
+
+	if (!unknown_nmi_panic)
+		return NMI_DONE;
+
+	if (atomic_cmpxchg(&nmi_cpu, -1, raw_smp_processor_id()) != -1)
+		return NMI_HANDLED;
+
+	return NMI_DONE;
+}
+#endif
+
 static void __init ms_hyperv_init_platform(void)
 {
 	/*
@@ -177,6 +203,9 @@
 		printk(KERN_INFO "HyperV: LAPIC Timer Frequency: %#x\n",
 				lapic_timer_frequency);
 	}
+
+	register_nmi_handler(NMI_UNKNOWN, hv_nmi_unknown, NMI_FLAG_FIRST,
+			     "hv_nmi_unknown");
 #endif
 
 	if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
@@ -191,6 +220,13 @@
 	machine_ops.crash_shutdown = hv_machine_crash_shutdown;
 #endif
 	mark_tsc_unstable("running on Hyper-V");
+
+	/*
+	 * Generation 2 instances don't support reading the NMI status from
+	 * 0x61 port.
+	 */
+	if (efi_enabled(EFI_BOOT))
+		x86_platform.get_nmi_reason = hv_get_nmi_reason;
 }
 
 const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 3b533cf..b5624fa 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -444,11 +444,24 @@
 		pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20);
 }
 
+/* PAT setup for BP. We need to go through sync steps here */
+void __init mtrr_bp_pat_init(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	prepare_set();
+
+	pat_init();
+
+	post_set();
+	local_irq_restore(flags);
+}
+
 /* Grab all of the MTRR state for this CPU into *state */
 bool __init get_mtrr_state(void)
 {
 	struct mtrr_var_range *vrs;
-	unsigned long flags;
 	unsigned lo, dummy;
 	unsigned int i;
 
@@ -481,15 +494,6 @@
 
 	mtrr_state_set = 1;
 
-	/* PAT setup for BP. We need to go through sync steps here */
-	local_irq_save(flags);
-	prepare_set();
-
-	pat_init();
-
-	post_set();
-	local_irq_restore(flags);
-
 	return !!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED);
 }
 
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index f891b47..fa77ac8 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -752,6 +752,9 @@
 			/* BIOS may override */
 			__mtrr_enabled = get_mtrr_state();
 
+			if (mtrr_enabled())
+				mtrr_bp_pat_init();
+
 			if (mtrr_cleanup(phys_addr)) {
 				changed_by_mtrr_cleanup = 1;
 				mtrr_if->set_all();
@@ -759,8 +762,16 @@
 		}
 	}
 
-	if (!mtrr_enabled())
+	if (!mtrr_enabled()) {
 		pr_info("MTRR: Disabled\n");
+
+		/*
+		 * PAT initialization relies on MTRR's rendezvous handler.
+		 * Skip PAT init until the handler can initialize both
+		 * features independently.
+		 */
+		pat_disable("MTRRs disabled, skipping PAT initialization too.");
+	}
 }
 
 void mtrr_ap_init(void)
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index 951884d..6c7ced0 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -52,6 +52,7 @@
 void fill_mtrr_var_range(unsigned int index,
 		u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi);
 bool get_mtrr_state(void);
+void mtrr_bp_pat_init(void);
 
 extern void set_mtrr_ops(const struct mtrr_ops *ops);
 
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index a3aeb2c..5b2f230 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -67,7 +67,7 @@
 	int shift = 64 - x86_pmu.cntval_bits;
 	u64 prev_raw_count, new_raw_count;
 	int idx = hwc->idx;
-	s64 delta;
+	u64 delta;
 
 	if (idx == INTEL_PMC_IDX_FIXED_BTS)
 		return 0;
@@ -1996,8 +1996,8 @@
 
 static void refresh_pce(void *ignored)
 {
-	if (current->mm)
-		load_mm_cr4(current->mm);
+	if (current->active_mm)
+		load_mm_cr4(current->active_mm);
 }
 
 static void x86_pmu_event_mapped(struct perf_event *event)
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 078de2e..5cc2242 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -3601,7 +3601,7 @@
 				c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
 			}
 			c->idxmsk64 &=
-				~(~0UL << (INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed));
+				~(~0ULL << (INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed));
 			c->weight = hweight64(c->idxmsk64);
 		}
 	}
@@ -3636,7 +3636,7 @@
 
 	/* Support full width counters using alternative MSR range */
 	if (x86_pmu.intel_cap.full_width_write) {
-		x86_pmu.max_period = x86_pmu.cntval_mask;
+		x86_pmu.max_period = x86_pmu.cntval_mask >> 1;
 		x86_pmu.perfctr = MSR_IA32_PMC0;
 		pr_cont("full-width counters, ");
 	}
diff --git a/arch/x86/kernel/cpu/perf_event_intel_cqm.c b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
index a316ca9..fc704ed 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_cqm.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
@@ -211,6 +211,20 @@
 	list_add_tail(&entry->list, &cqm_rmid_limbo_lru);
 }
 
+static void cqm_cleanup(void)
+{
+	int i;
+
+	if (!cqm_rmid_ptrs)
+		return;
+
+	for (i = 0; i < cqm_max_rmid; i++)
+		kfree(cqm_rmid_ptrs[i]);
+
+	kfree(cqm_rmid_ptrs);
+	cqm_rmid_ptrs = NULL;
+}
+
 static int intel_cqm_setup_rmid_cache(void)
 {
 	struct cqm_rmid_entry *entry;
@@ -218,7 +232,7 @@
 	int r = 0;
 
 	nr_rmids = cqm_max_rmid + 1;
-	cqm_rmid_ptrs = kmalloc(sizeof(struct cqm_rmid_entry *) *
+	cqm_rmid_ptrs = kzalloc(sizeof(struct cqm_rmid_entry *) *
 				nr_rmids, GFP_KERNEL);
 	if (!cqm_rmid_ptrs)
 		return -ENOMEM;
@@ -249,11 +263,9 @@
 	mutex_unlock(&cache_mutex);
 
 	return 0;
-fail:
-	while (r--)
-		kfree(cqm_rmid_ptrs[r]);
 
-	kfree(cqm_rmid_ptrs);
+fail:
+	cqm_cleanup();
 	return -ENOMEM;
 }
 
@@ -281,9 +293,13 @@
 
 	/*
 	 * Events that target same task are placed into the same cache group.
+	 * Mark it as a multi event group, so that we update ->count
+	 * for every event rather than just the group leader later.
 	 */
-	if (a->hw.target == b->hw.target)
+	if (a->hw.target == b->hw.target) {
+		b->hw.is_group_event = true;
 		return true;
+	}
 
 	/*
 	 * Are we an inherited event?
@@ -849,6 +865,7 @@
 	bool conflict = false;
 	u32 rmid;
 
+	event->hw.is_group_event = false;
 	list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) {
 		rmid = iter->hw.cqm_rmid;
 
@@ -940,7 +957,9 @@
 		return __perf_event_count(event);
 
 	/*
-	 * Only the group leader gets to report values. This stops us
+	 * Only the group leader gets to report values except in case of
+	 * multiple events in the same group, we still need to read the
+	 * other events.This stops us
 	 * reporting duplicate values to userspace, and gives us a clear
 	 * rule for which task gets to report the values.
 	 *
@@ -948,7 +967,7 @@
 	 * specific packages - we forfeit that ability when we create
 	 * task events.
 	 */
-	if (!cqm_group_leader(event))
+	if (!cqm_group_leader(event) && !event->hw.is_group_event)
 		return 0;
 
 	/*
@@ -1315,7 +1334,7 @@
 
 static int __init intel_cqm_init(void)
 {
-	char *str, scale[20];
+	char *str = NULL, scale[20];
 	int i, cpu, ret;
 
 	if (!x86_match_cpu(intel_cqm_match))
@@ -1375,16 +1394,25 @@
 		cqm_pick_event_reader(i);
 	}
 
-	__perf_cpu_notifier(intel_cqm_cpu_notifier);
-
 	ret = perf_pmu_register(&intel_cqm_pmu, "intel_cqm", -1);
-	if (ret)
+	if (ret) {
 		pr_err("Intel CQM perf registration failed: %d\n", ret);
-	else
-		pr_info("Intel CQM monitoring enabled\n");
+		goto out;
+	}
 
+	pr_info("Intel CQM monitoring enabled\n");
+
+	/*
+	 * Register the hot cpu notifier once we are sure cqm
+	 * is enabled to avoid notifier leak.
+	 */
+	__perf_cpu_notifier(intel_cqm_cpu_notifier);
 out:
 	cpu_notifier_register_done();
+	if (ret) {
+		kfree(str);
+		cqm_cleanup();
+	}
 
 	return ret;
 }
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 7abb2b8..1e7de3c 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -1110,6 +1110,13 @@
 	void *at;
 	u64 pebs_status;
 
+	/*
+	 * fmt0 does not have a status bitfield (does not use
+	 * perf_record_nhm format)
+	 */
+	if (x86_pmu.intel_cap.pebs_format < 1)
+		return base;
+
 	if (base == NULL)
 		return NULL;
 
@@ -1195,7 +1202,7 @@
 	if (!event->attr.precise_ip)
 		return;
 
-	n = (top - at) / x86_pmu.pebs_record_size;
+	n = top - at;
 	if (n <= 0)
 		return;
 
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index 659f01e..8900400 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -410,6 +410,9 @@
 		cpuc->lbr_entries[i].to		= msr_lastbranch.to;
 		cpuc->lbr_entries[i].mispred	= 0;
 		cpuc->lbr_entries[i].predicted	= 0;
+		cpuc->lbr_entries[i].in_tx	= 0;
+		cpuc->lbr_entries[i].abort	= 0;
+		cpuc->lbr_entries[i].cycles	= 0;
 		cpuc->lbr_entries[i].reserved	= 0;
 	}
 	cpuc->lbr_stack.nr = i;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
index 868e119..49e35d0 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_pt.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c
@@ -694,6 +694,7 @@
 
 	/* clear STOP and INT from current entry */
 	buf->topa_index[buf->stop_pos]->stop = 0;
+	buf->topa_index[buf->stop_pos]->intr = 0;
 	buf->topa_index[buf->intr_pos]->intr = 0;
 
 	/* how many pages till the STOP marker */
@@ -718,6 +719,7 @@
 	buf->intr_pos = idx;
 
 	buf->topa_index[buf->stop_pos]->stop = 1;
+	buf->topa_index[buf->stop_pos]->intr = 1;
 	buf->topa_index[buf->intr_pos]->intr = 1;
 
 	return 0;
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 569c1e4..52a2526 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -753,7 +753,7 @@
 /*
  * Find the highest page frame number we have available
  */
-static unsigned long __init e820_end_pfn(unsigned long limit_pfn)
+static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
 {
 	int i;
 	unsigned long last_pfn = 0;
@@ -764,11 +764,7 @@
 		unsigned long start_pfn;
 		unsigned long end_pfn;
 
-		/*
-		 * Persistent memory is accounted as ram for purposes of
-		 * establishing max_pfn and mem_map.
-		 */
-		if (ei->type != E820_RAM && ei->type != E820_PRAM)
+		if (ei->type != type)
 			continue;
 
 		start_pfn = ei->addr >> PAGE_SHIFT;
@@ -793,12 +789,12 @@
 }
 unsigned long __init e820_end_of_ram_pfn(void)
 {
-	return e820_end_pfn(MAX_ARCH_PFN);
+	return e820_end_pfn(MAX_ARCH_PFN, E820_RAM);
 }
 
 unsigned long __init e820_end_of_low_ram_pfn(void)
 {
-	return e820_end_pfn(1UL << (32-PAGE_SHIFT));
+	return e820_end_pfn(1UL << (32 - PAGE_SHIFT), E820_RAM);
 }
 
 static void early_panic(char *msg)
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index db9a675..a257d60 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -11,7 +11,11 @@
 
 #include <linux/pci.h>
 #include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/pci_ids.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_regs.h>
 #include <drm/i915_drm.h>
 #include <asm/pci-direct.h>
 #include <asm/dma.h>
@@ -21,6 +25,9 @@
 #include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/irq_remapping.h>
+#include <asm/early_ioremap.h>
+
+#define dev_err(msg)  pr_err("pci 0000:%02x:%02x.%d: %s", bus, slot, func, msg)
 
 static void __init fix_hypertransport_config(int num, int slot, int func)
 {
@@ -76,6 +83,13 @@
 #ifdef CONFIG_ACPI
 #ifdef CONFIG_X86_IO_APIC
 	/*
+	 * Only applies to Nvidia root ports (bus 0) and not to
+	 * Nvidia graphics cards with PCI ports on secondary buses.
+	 */
+	if (num)
+		return;
+
+	/*
 	 * All timer overrides on Nvidia are
 	 * wrong unless HPET is enabled.
 	 * Unfortunately that's not true on many Asus boards.
@@ -317,12 +331,11 @@
 
 static u32 __init i865_stolen_base(int num, int slot, int func, size_t stolen_size)
 {
-	/*
-	 * FIXME is the graphics stolen memory region
-	 * always at TOUD? Ie. is it always the last
-	 * one to be allocated by the BIOS?
-	 */
-	return read_pci_config_16(0, 0, 0, I865_TOUD) << 16;
+	u16 toud = 0;
+
+	toud = read_pci_config_16(0, 0, 0, I865_TOUD);
+
+	return (phys_addr_t)(toud << 16) + i845_tseg_size();
 }
 
 static size_t __init i830_stolen_size(int num, int slot, int func)
@@ -589,6 +602,61 @@
 #endif
 }
 
+#define BCM4331_MMIO_SIZE	16384
+#define BCM4331_PM_CAP		0x40
+#define bcma_aread32(reg)	ioread32(mmio + 1 * BCMA_CORE_SIZE + reg)
+#define bcma_awrite32(reg, val)	iowrite32(val, mmio + 1 * BCMA_CORE_SIZE + reg)
+
+static void __init apple_airport_reset(int bus, int slot, int func)
+{
+	void __iomem *mmio;
+	u16 pmcsr;
+	u64 addr;
+	int i;
+
+	if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc."))
+		return;
+
+	/* Card may have been put into PCI_D3hot by grub quirk */
+	pmcsr = read_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL);
+
+	if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) {
+		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+		write_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL, pmcsr);
+		mdelay(10);
+
+		pmcsr = read_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL);
+		if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) {
+			dev_err("Cannot power up Apple AirPort card\n");
+			return;
+		}
+	}
+
+	addr  =      read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0);
+	addr |= (u64)read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_1) << 32;
+	addr &= PCI_BASE_ADDRESS_MEM_MASK;
+
+	mmio = early_ioremap(addr, BCM4331_MMIO_SIZE);
+	if (!mmio) {
+		dev_err("Cannot iomap Apple AirPort card\n");
+		return;
+	}
+
+	pr_info("Resetting Apple AirPort card (left enabled by EFI)\n");
+
+	for (i = 0; bcma_aread32(BCMA_RESET_ST) && i < 30; i++)
+		udelay(10);
+
+	bcma_awrite32(BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
+	bcma_aread32(BCMA_RESET_CTL);
+	udelay(1);
+
+	bcma_awrite32(BCMA_RESET_CTL, 0);
+	bcma_aread32(BCMA_RESET_CTL);
+	udelay(10);
+
+	early_iounmap(mmio, BCM4331_MMIO_SIZE);
+}
 
 #define QFLAG_APPLY_ONCE 	0x1
 #define QFLAG_APPLIED		0x2
@@ -602,12 +670,6 @@
 	void (*f)(int num, int slot, int func);
 };
 
-/*
- * Only works for devices on the root bus. If you add any devices
- * not on bus 0 readd another loop level in early_quirks(). But
- * be careful because at least the Nvidia quirk here relies on
- * only matching on bus 0.
- */
 static struct chipset early_qrk[] __initdata = {
 	{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
 	  PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, nvidia_bugs },
@@ -637,9 +699,13 @@
 	 */
 	{ PCI_VENDOR_ID_INTEL, 0x0f00,
 		PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
+	{ PCI_VENDOR_ID_BROADCOM, 0x4331,
+	  PCI_CLASS_NETWORK_OTHER, PCI_ANY_ID, 0, apple_airport_reset},
 	{}
 };
 
+static void __init early_pci_scan_bus(int bus);
+
 /**
  * check_dev_quirk - apply early quirks to a given PCI device
  * @num: bus number
@@ -648,7 +714,7 @@
  *
  * Check the vendor & device ID against the early quirks table.
  *
- * If the device is single function, let early_quirks() know so we don't
+ * If the device is single function, let early_pci_scan_bus() know so we don't
  * poke at this device again.
  */
 static int __init check_dev_quirk(int num, int slot, int func)
@@ -657,6 +723,7 @@
 	u16 vendor;
 	u16 device;
 	u8 type;
+	u8 sec;
 	int i;
 
 	class = read_pci_config_16(num, slot, func, PCI_CLASS_DEVICE);
@@ -684,25 +751,36 @@
 
 	type = read_pci_config_byte(num, slot, func,
 				    PCI_HEADER_TYPE);
+
+	if ((type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
+		sec = read_pci_config_byte(num, slot, func, PCI_SECONDARY_BUS);
+		if (sec > num)
+			early_pci_scan_bus(sec);
+	}
+
 	if (!(type & 0x80))
 		return -1;
 
 	return 0;
 }
 
-void __init early_quirks(void)
+static void __init early_pci_scan_bus(int bus)
 {
 	int slot, func;
 
-	if (!early_pci_allowed())
-		return;
-
 	/* Poor man's PCI discovery */
-	/* Only scan the root bus */
 	for (slot = 0; slot < 32; slot++)
 		for (func = 0; func < 8; func++) {
 			/* Only probe function 0 on single fn devices */
-			if (check_dev_quirk(0, slot, func))
+			if (check_dev_quirk(bus, slot, func))
 				break;
 		}
 }
+
+void __init early_quirks(void)
+{
+	if (!early_pci_allowed())
+		return;
+
+	early_pci_scan_bus(0);
+}
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index be39b5f..1011c05 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -96,6 +96,7 @@
  * Boot time FPU feature detection code:
  */
 unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu;
+EXPORT_SYMBOL_GPL(mxcsr_feature_mask);
 
 static void __init fpu__init_system_mxcsr(void)
 {
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 311bcf3..1b96bfe 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -81,9 +81,9 @@
 static unsigned long text_ip_addr(unsigned long ip)
 {
 	/*
-	 * On x86_64, kernel text mappings are mapped read-only with
-	 * CONFIG_DEBUG_RODATA. So we use the kernel identity mapping instead
-	 * of the kernel text mapping to modify the kernel text.
+	 * On x86_64, kernel text mappings are mapped read-only, so we use
+	 * the kernel identity mapping instead of the kernel text mapping
+	 * to modify the kernel text.
 	 *
 	 * For 32bit kernels, these mappings are same and we can use
 	 * kernel identity mapping to modify code.
@@ -977,6 +977,18 @@
 	unsigned long return_hooker = (unsigned long)
 				&return_to_handler;
 
+	/*
+	 * When resuming from suspend-to-ram, this function can be indirectly
+	 * called from early CPU startup code while the CPU is in real mode,
+	 * which would fail miserably.  Make sure the stack pointer is a
+	 * virtual address.
+	 *
+	 * This check isn't as accurate as virt_addr_valid(), but it should be
+	 * good enough for this purpose, and it's fast.
+	 */
+	if (unlikely((long)__builtin_frame_address(0) >= 0))
+		return;
+
 	if (unlikely(ftrace_graph_is_dead()))
 		return;
 
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index f129a9a..b6b0077 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -4,6 +4,7 @@
  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
  */
 
+#define DISABLE_BRANCH_PROFILING
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <linux/types.h>
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 6bc9ae2..8f1a3f4 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -571,7 +571,7 @@
 	movl %eax,%ds
 	movl %eax,%es
 
-	cmpl $(__KERNEL_CS),32(%esp)
+	cmpw $(__KERNEL_CS),32(%esp)
 	jne 10f
 
 	leal 28(%esp),%eax	# Pointer to %eip
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index b8e6ff5..acc9b8f 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -351,6 +351,7 @@
 	} else {
 		struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
 
+		irq_domain_deactivate_irq(irq_get_irq_data(hdev->irq));
 		irq_domain_activate_irq(irq_get_irq_data(hdev->irq));
 		disable_irq(hdev->irq);
 		irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 44256a6..ed15cd48 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -750,9 +750,7 @@
 int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
 	int err;
-#ifdef CONFIG_DEBUG_RODATA
 	char opc[BREAK_INSTR_SIZE];
-#endif /* CONFIG_DEBUG_RODATA */
 
 	bpt->type = BP_BREAKPOINT;
 	err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
@@ -761,7 +759,6 @@
 		return err;
 	err = probe_kernel_write((char *)bpt->bpt_addr,
 				 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
-#ifdef CONFIG_DEBUG_RODATA
 	if (!err)
 		return err;
 	/*
@@ -778,13 +775,12 @@
 	if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE))
 		return -EINVAL;
 	bpt->type = BP_POKE_BREAKPOINT;
-#endif /* CONFIG_DEBUG_RODATA */
+
 	return err;
 }
 
 int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 {
-#ifdef CONFIG_DEBUG_RODATA
 	int err;
 	char opc[BREAK_INSTR_SIZE];
 
@@ -801,8 +797,8 @@
 	if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE))
 		goto knl_write;
 	return err;
+
 knl_write:
-#endif /* CONFIG_DEBUG_RODATA */
 	return probe_kernel_write((char *)bpt->bpt_addr,
 				  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 }
diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h
index c6ee63f..d688826 100644
--- a/arch/x86/kernel/kprobes/common.h
+++ b/arch/x86/kernel/kprobes/common.h
@@ -67,7 +67,7 @@
 #endif
 
 /* Ensure if the instruction can be boostable */
-extern int can_boost(kprobe_opcode_t *instruction);
+extern int can_boost(kprobe_opcode_t *instruction, void *addr);
 /* Recover instruction if given address is probed */
 extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf,
 					 unsigned long addr);
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 1deffe6..99d293e 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -163,12 +163,12 @@
  * Returns non-zero if opcode is boostable.
  * RIP relative instructions are adjusted at copying time in 64 bits mode
  */
-int can_boost(kprobe_opcode_t *opcodes)
+int can_boost(kprobe_opcode_t *opcodes, void *addr)
 {
 	kprobe_opcode_t opcode;
 	kprobe_opcode_t *orig_opcodes = opcodes;
 
-	if (search_exception_tables((unsigned long)opcodes))
+	if (search_exception_tables((unsigned long)addr))
 		return 0;	/* Page fault may occur on this address. */
 
 retry:
@@ -413,7 +413,7 @@
 	 * __copy_instruction can modify the displacement of the instruction,
 	 * but it doesn't affect boostable check.
 	 */
-	if (can_boost(p->ainsn.insn))
+	if (can_boost(p->ainsn.insn, p->addr))
 		p->ainsn.boostable = 0;
 	else
 		p->ainsn.boostable = -1;
@@ -959,7 +959,19 @@
 		 * normal page fault.
 		 */
 		regs->ip = (unsigned long)cur->addr;
+		/*
+		 * Trap flag (TF) has been set here because this fault
+		 * happened where the single stepping will be done.
+		 * So clear it by resetting the current kprobe:
+		 */
+		regs->flags &= ~X86_EFLAGS_TF;
+
+		/*
+		 * If the TF flag was set before the kprobe hit,
+		 * don't touch it:
+		 */
 		regs->flags |= kcb->kprobe_old_flags;
+
 		if (kcb->kprobe_status == KPROBE_REENTER)
 			restore_previous_kprobe(kcb);
 		else
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
index 7b3b9d1..c9d488f 100644
--- a/arch/x86/kernel/kprobes/opt.c
+++ b/arch/x86/kernel/kprobes/opt.c
@@ -177,7 +177,7 @@
 
 	while (len < RELATIVEJUMP_SIZE) {
 		ret = __copy_instruction(dest + len, src + len);
-		if (!ret || !can_boost(dest + len))
+		if (!ret || !can_boost(dest + len, src + len))
 			return -EINVAL;
 		len += ret;
 	}
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 47190bd..cec49ec 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -161,8 +161,8 @@
 			 */
 			rcu_irq_exit();
 			native_safe_halt();
-			rcu_irq_enter();
 			local_irq_disable();
+			rcu_irq_enter();
 		}
 	}
 	if (!n.halted)
diff --git a/arch/x86/kernel/mcount_64.S b/arch/x86/kernel/mcount_64.S
index 87e1762..5d9afbc 100644
--- a/arch/x86/kernel/mcount_64.S
+++ b/arch/x86/kernel/mcount_64.S
@@ -180,7 +180,8 @@
 	jmp ftrace_stub
 #endif
 
-GLOBAL(ftrace_stub)
+/* This is weak to keep gas from relaxing the jumps */
+WEAK(ftrace_stub)
 	retq
 END(ftrace_caller)
 
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index c2130ae..f534a0e 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -55,12 +55,12 @@
      ".popsection");
 
 /* identity function, which can be inlined */
-u32 _paravirt_ident_32(u32 x)
+u32 notrace _paravirt_ident_32(u32 x)
 {
 	return x;
 }
 
-u64 _paravirt_ident_64(u64 x)
+u64 notrace _paravirt_ident_64(u64 x)
 {
 	return x;
 }
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 0497f71..c055e9a 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -296,7 +296,7 @@
 
 	/* were we called with bad_dma_address? */
 	badend = DMA_ERROR_CODE + (EMERGENCY_PAGES * PAGE_SIZE);
-	if (unlikely((dma_addr >= DMA_ERROR_CODE) && (dma_addr < badend))) {
+	if (unlikely(dma_addr < badend)) {
 		WARN(1, KERN_ERR "Calgary: driver tried unmapping bad DMA "
 		       "address 0x%Lx\n", dma_addr);
 		return;
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 558f50e..479a409 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -188,8 +188,8 @@
 		return sp;
 
 	prev_esp = (u32 *)(context);
-	if (prev_esp)
-		return (unsigned long)prev_esp;
+	if (*prev_esp)
+		return (unsigned long)*prev_esp;
 
 	return (unsigned long)regs;
 }
diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c
index 2f355d2..bf0ce75 100644
--- a/arch/x86/kernel/pvclock.c
+++ b/arch/x86/kernel/pvclock.c
@@ -66,6 +66,8 @@
 
 	do {
 		version = __pvclock_read_cycles(src, &ret, &flags);
+		/* Make sure that the version double-check is last. */
+		smp_rmb();
 	} while ((src->version & 1) || version != src->version);
 
 	return flags & valid_flags;
@@ -80,6 +82,8 @@
 
 	do {
 		version = __pvclock_read_cycles(src, &ret, &flags);
+		/* Make sure that the version double-check is last. */
+		smp_rmb();
 	} while ((src->version & 1) || version != src->version);
 
 	if (unlikely((flags & PVCLOCK_GUEST_STOPPED) != 0)) {
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index d2bbe34..e67b834 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1048,6 +1048,13 @@
 	if (mtrr_trim_uncached_memory(max_pfn))
 		max_pfn = e820_end_of_ram_pfn();
 
+	/*
+	 * This call is required when the CPU does not support PAT. If
+	 * mtrr_bp_init() invoked it already via pat_init() the call has no
+	 * effect.
+	 */
+	init_cache_modes();
+
 #ifdef CONFIG_X86_32
 	/* max_low_pfn get updated here */
 	find_low_pfn_range();
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index 10e0272..136ad7c 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -143,7 +143,7 @@
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma(mm, addr);
 		if (end - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
@@ -186,7 +186,7 @@
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-				(!vma || addr + len <= vma->vm_start))
+				(!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
diff --git a/arch/x86/kernel/test_nx.c b/arch/x86/kernel/test_nx.c
index 3f92ce0..27538f1 100644
--- a/arch/x86/kernel/test_nx.c
+++ b/arch/x86/kernel/test_nx.c
@@ -142,7 +142,6 @@
 	 * by the error message
 	 */
 
-#ifdef CONFIG_DEBUG_RODATA
 	/* Test 3: Check if the .rodata section is executable */
 	if (rodata_test_data != 0xC3) {
 		printk(KERN_ERR "test_nx: .rodata marker has invalid value\n");
@@ -151,7 +150,6 @@
 		printk(KERN_ERR "test_nx: .rodata section is executable\n");
 		ret = -ENODEV;
 	}
-#endif
 
 #if 0
 	/* Test 4: Check if the .data section of a module is executable */
diff --git a/arch/x86/kernel/test_rodata.c b/arch/x86/kernel/test_rodata.c
index 5ecbfe5..cb4a01b 100644
--- a/arch/x86/kernel/test_rodata.c
+++ b/arch/x86/kernel/test_rodata.c
@@ -76,5 +76,5 @@
 }
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Testcase for the DEBUG_RODATA infrastructure");
+MODULE_DESCRIPTION("Testcase for marking rodata as read-only");
 MODULE_AUTHOR("Arjan van de Ven <arjan@linux.intel.com>");
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index ade185a..679302c 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -109,6 +109,12 @@
 	preempt_count_dec();
 }
 
+/*
+ * In IST context, we explicitly disable preemption.  This serves two
+ * purposes: it makes it much less likely that we would accidentally
+ * schedule in IST context and it will force a warning if we somehow
+ * manage to schedule by accident.
+ */
 void ist_enter(struct pt_regs *regs)
 {
 	if (user_mode(regs)) {
@@ -123,13 +129,7 @@
 		rcu_nmi_enter();
 	}
 
-	/*
-	 * We are atomic because we're on the IST stack; or we're on
-	 * x86_32, in which case we still shouldn't schedule; or we're
-	 * on x86_64 and entered from user mode, in which case we're
-	 * still atomic unless ist_begin_non_atomic is called.
-	 */
-	preempt_count_add(HARDIRQ_OFFSET);
+	preempt_disable();
 
 	/* This code is a bit fragile.  Test it. */
 	RCU_LOCKDEP_WARN(!rcu_is_watching(), "ist_enter didn't work");
@@ -137,7 +137,7 @@
 
 void ist_exit(struct pt_regs *regs)
 {
-	preempt_count_sub(HARDIRQ_OFFSET);
+	preempt_enable_no_resched();
 
 	if (!user_mode(regs))
 		rcu_nmi_exit();
@@ -168,7 +168,7 @@
 	BUG_ON((unsigned long)(current_top_of_stack() -
 			       current_stack_pointer()) >= THREAD_SIZE);
 
-	preempt_count_sub(HARDIRQ_OFFSET);
+	preempt_enable_no_resched();
 }
 
 /**
@@ -178,7 +178,7 @@
  */
 void ist_end_non_atomic(void)
 {
-	preempt_count_add(HARDIRQ_OFFSET);
+	preempt_disable();
 }
 
 static nokprobe_inline int
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index bf4db6e..c6aace2 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -357,20 +357,22 @@
 		*cursor &= 0xfe;
 	}
 	/*
-	 * Similar treatment for VEX3 prefix.
-	 * TODO: add XOP/EVEX treatment when insn decoder supports them
+	 * Similar treatment for VEX3/EVEX prefix.
+	 * TODO: add XOP treatment when insn decoder supports them
 	 */
-	if (insn->vex_prefix.nbytes == 3) {
+	if (insn->vex_prefix.nbytes >= 3) {
 		/*
 		 * vex2:     c5    rvvvvLpp   (has no b bit)
 		 * vex3/xop: c4/8f rxbmmmmm wvvvvLpp
 		 * evex:     62    rxbR00mm wvvvv1pp zllBVaaa
-		 *   (evex will need setting of both b and x since
-		 *   in non-sib encoding evex.x is 4th bit of MODRM.rm)
-		 * Setting VEX3.b (setting because it has inverted meaning):
+		 * Setting VEX3.b (setting because it has inverted meaning).
+		 * Setting EVEX.x since (in non-SIB encoding) EVEX.x
+		 * is the 4th bit of MODRM.rm, and needs the same treatment.
+		 * For VEX3-encoded insns, VEX3.x value has no effect in
+		 * non-SIB encoding, the change is superfluous but harmless.
 		 */
 		cursor = auprobe->insn + insn_offset_vex_prefix(insn) + 1;
-		*cursor |= 0x20;
+		*cursor |= 0x60;
 	}
 
 	/*
@@ -415,12 +417,10 @@
 
 	reg = MODRM_REG(insn);	/* Fetch modrm.reg */
 	reg2 = 0xff;		/* Fetch vex.vvvv */
-	if (insn->vex_prefix.nbytes == 2)
-		reg2 = insn->vex_prefix.bytes[1];
-	else if (insn->vex_prefix.nbytes == 3)
+	if (insn->vex_prefix.nbytes)
 		reg2 = insn->vex_prefix.bytes[2];
 	/*
-	 * TODO: add XOP, EXEV vvvv reading.
+	 * TODO: add XOP vvvv reading.
 	 *
 	 * vex.vvvv field is in bits 6-3, bits are inverted.
 	 * But in 32-bit mode, high-order bit may be ignored.
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 74e4bf1..fe133b7 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -41,29 +41,28 @@
 jiffies_64 = jiffies;
 #endif
 
-#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
+#if defined(CONFIG_X86_64)
 /*
- * On 64-bit, align RODATA to 2MB so that even with CONFIG_DEBUG_RODATA
- * we retain large page mappings for boundaries spanning kernel text, rodata
- * and data sections.
+ * On 64-bit, align RODATA to 2MB so we retain large page mappings for
+ * boundaries spanning kernel text, rodata and data sections.
  *
  * However, kernel identity mappings will have different RWX permissions
  * to the pages mapping to text and to the pages padding (which are freed) the
  * text section. Hence kernel identity mappings will be broken to smaller
  * pages. For 64-bit, kernel text and kernel identity mappings are different,
- * so we can enable protection checks that come with CONFIG_DEBUG_RODATA,
- * as well as retain 2MB large page mappings for kernel text.
+ * so we can enable protection checks as well as retain 2MB large page
+ * mappings for kernel text.
  */
-#define X64_ALIGN_DEBUG_RODATA_BEGIN	. = ALIGN(HPAGE_SIZE);
+#define X64_ALIGN_RODATA_BEGIN	. = ALIGN(HPAGE_SIZE);
 
-#define X64_ALIGN_DEBUG_RODATA_END				\
+#define X64_ALIGN_RODATA_END					\
 		. = ALIGN(HPAGE_SIZE);				\
 		__end_rodata_hpage_align = .;
 
 #else
 
-#define X64_ALIGN_DEBUG_RODATA_BEGIN
-#define X64_ALIGN_DEBUG_RODATA_END
+#define X64_ALIGN_RODATA_BEGIN
+#define X64_ALIGN_RODATA_END
 
 #endif
 
@@ -112,13 +111,11 @@
 
 	EXCEPTION_TABLE(16) :text = 0x9090
 
-#if defined(CONFIG_DEBUG_RODATA)
 	/* .text should occupy whole number of pages */
 	. = ALIGN(PAGE_SIZE);
-#endif
-	X64_ALIGN_DEBUG_RODATA_BEGIN
+	X64_ALIGN_RODATA_BEGIN
 	RO_DATA(PAGE_SIZE)
-	X64_ALIGN_DEBUG_RODATA_END
+	X64_ALIGN_RODATA_END
 
 	/* Data */
 	.data : AT(ADDR(.data) - LOAD_OFFSET) {
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 6525e92..9357b29 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -509,6 +509,7 @@
 			do_cpuid_1_ent(&entry[i], function, idx);
 			if (idx == 1) {
 				entry[i].eax &= kvm_supported_word10_x86_features;
+				cpuid_mask(&entry[i].eax, 10);
 				entry[i].ebx = 0;
 				if (entry[i].eax & (F(XSAVES)|F(XSAVEC)))
 					entry[i].ebx =
@@ -736,18 +737,20 @@
 static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i)
 {
 	struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i];
-	int j, nent = vcpu->arch.cpuid_nent;
+	struct kvm_cpuid_entry2 *ej;
+	int j = i;
+	int nent = vcpu->arch.cpuid_nent;
 
 	e->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT;
 	/* when no next entry is found, the current entry[i] is reselected */
-	for (j = i + 1; ; j = (j + 1) % nent) {
-		struct kvm_cpuid_entry2 *ej = &vcpu->arch.cpuid_entries[j];
-		if (ej->function == e->function) {
-			ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
-			return j;
-		}
-	}
-	return 0; /* silence gcc, even though control never reaches here */
+	do {
+		j = (j + 1) % nent;
+		ej = &vcpu->arch.cpuid_entries[j];
+	} while (ej->function != e->function);
+
+	ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
+
+	return j;
 }
 
 /* find an entry with matching function, matching index (if needed), and that
@@ -817,12 +820,6 @@
 	if (!best)
 		best = check_cpuid_limit(vcpu, function, index);
 
-	/*
-	 * Perfmon not yet supported for L2 guest.
-	 */
-	if (is_guest_mode(vcpu) && function == 0xa)
-		best = NULL;
-
 	if (best) {
 		*eax = best->eax;
 		*ebx = best->ebx;
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b9b09fe..04b2f3c 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -172,6 +172,7 @@
 #define NearBranch  ((u64)1 << 52)  /* Near branches */
 #define No16	    ((u64)1 << 53)  /* No 16 bit operand */
 #define IncSP       ((u64)1 << 54)  /* SP is incremented before ModRM calc */
+#define Aligned16   ((u64)1 << 55)  /* Aligned to 16 byte boundary (e.g. FXSAVE) */
 
 #define DstXacc     (DstAccLo | SrcAccHi | SrcWrite)
 
@@ -434,6 +435,26 @@
 FOP_START(salc) "pushf; sbb %al, %al; popf \n\t" FOP_RET
 FOP_END;
 
+/*
+ * XXX: inoutclob user must know where the argument is being expanded.
+ *      Relying on CC_HAVE_ASM_GOTO would allow us to remove _fault.
+ */
+#define asm_safe(insn, inoutclob...) \
+({ \
+	int _fault = 0; \
+ \
+	asm volatile("1:" insn "\n" \
+	             "2:\n" \
+	             ".pushsection .fixup, \"ax\"\n" \
+	             "3: movl $1, %[_fault]\n" \
+	             "   jmp  2b\n" \
+	             ".popsection\n" \
+	             _ASM_EXTABLE(1b, 3b) \
+	             : [_fault] "+qm"(_fault) inoutclob ); \
+ \
+	_fault ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE; \
+})
+
 static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
 				    enum x86_intercept intercept,
 				    enum x86_intercept_stage stage)
@@ -620,21 +641,24 @@
  * depending on whether they're AVX encoded or not.
  *
  * Also included is CMPXCHG16B which is not a vector instruction, yet it is
- * subject to the same check.
+ * subject to the same check.  FXSAVE and FXRSTOR are checked here too as their
+ * 512 bytes of data must be aligned to a 16 byte boundary.
  */
-static bool insn_aligned(struct x86_emulate_ctxt *ctxt, unsigned size)
+static unsigned insn_alignment(struct x86_emulate_ctxt *ctxt, unsigned size)
 {
 	if (likely(size < 16))
-		return false;
+		return 1;
 
 	if (ctxt->d & Aligned)
-		return true;
+		return size;
 	else if (ctxt->d & Unaligned)
-		return false;
+		return 1;
 	else if (ctxt->d & Avx)
-		return false;
+		return 1;
+	else if (ctxt->d & Aligned16)
+		return 16;
 	else
-		return true;
+		return size;
 }
 
 static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
@@ -692,7 +716,7 @@
 		}
 		break;
 	}
-	if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0))
+	if (la & (insn_alignment(ctxt, size) - 1))
 		return emulate_gp(ctxt, 0);
 	return X86EMUL_CONTINUE;
 bad:
@@ -779,6 +803,20 @@
 	return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
 }
 
+static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
+			       struct segmented_address addr,
+			       void *data,
+			       unsigned int size)
+{
+	int rc;
+	ulong linear;
+
+	rc = linearize(ctxt, addr, size, true, &linear);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+	return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
+}
+
 /*
  * Prefetch the remaining bytes of the instruction without crossing page
  * boundary if they are not in fetch_cache yet.
@@ -1532,7 +1570,6 @@
 				    &ctxt->exception);
 }
 
-/* Does not support long mode */
 static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 				     u16 selector, int seg, u8 cpl,
 				     enum x86_transfer_type transfer,
@@ -1569,20 +1606,34 @@
 
 	rpl = selector & 3;
 
-	/* NULL selector is not valid for TR, CS and SS (except for long mode) */
-	if ((seg == VCPU_SREG_CS
-	     || (seg == VCPU_SREG_SS
-		 && (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl))
-	     || seg == VCPU_SREG_TR)
-	    && null_selector)
-		goto exception;
-
 	/* TR should be in GDT only */
 	if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
 		goto exception;
 
-	if (null_selector) /* for NULL selector skip all following checks */
+	/* NULL selector is not valid for TR, CS and (except for long mode) SS */
+	if (null_selector) {
+		if (seg == VCPU_SREG_CS || seg == VCPU_SREG_TR)
+			goto exception;
+
+		if (seg == VCPU_SREG_SS) {
+			if (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl)
+				goto exception;
+
+			/*
+			 * ctxt->ops->set_segment expects the CPL to be in
+			 * SS.DPL, so fake an expand-up 32-bit data segment.
+			 */
+			seg_desc.type = 3;
+			seg_desc.p = 1;
+			seg_desc.s = 1;
+			seg_desc.dpl = cpl;
+			seg_desc.d = 1;
+			seg_desc.g = 1;
+		}
+
+		/* Skip all following checks */
 		goto load;
+	}
 
 	ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr);
 	if (ret != X86EMUL_CONTINUE)
@@ -1698,6 +1749,21 @@
 				   u16 selector, int seg)
 {
 	u8 cpl = ctxt->ops->cpl(ctxt);
+
+	/*
+	 * None of MOV, POP and LSS can load a NULL selector in CPL=3, but
+	 * they can load it at CPL<3 (Intel's manual says only LSS can,
+	 * but it's wrong).
+	 *
+	 * However, the Intel manual says that putting IST=1/DPL=3 in
+	 * an interrupt gate will result in SS=3 (the AMD manual instead
+	 * says it doesn't), so allow SS=3 in __load_segment_descriptor
+	 * and only forbid it here.
+	 */
+	if (seg == VCPU_SREG_SS && selector == 3 &&
+	    ctxt->mode == X86EMUL_MODE_PROT64)
+		return emulate_exception(ctxt, GP_VECTOR, 0, true);
+
 	return __load_segment_descriptor(ctxt, selector, seg, cpl,
 					 X86_TRANSFER_NONE, NULL);
 }
@@ -2093,16 +2159,10 @@
 static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
 {
 	int rc;
-	unsigned short sel, old_sel;
-	struct desc_struct old_desc, new_desc;
-	const struct x86_emulate_ops *ops = ctxt->ops;
+	unsigned short sel;
+	struct desc_struct new_desc;
 	u8 cpl = ctxt->ops->cpl(ctxt);
 
-	/* Assignment of RIP may only fail in 64-bit mode */
-	if (ctxt->mode == X86EMUL_MODE_PROT64)
-		ops->get_segment(ctxt, &old_sel, &old_desc, NULL,
-				 VCPU_SREG_CS);
-
 	memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
 
 	rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl,
@@ -2112,12 +2172,10 @@
 		return rc;
 
 	rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc);
-	if (rc != X86EMUL_CONTINUE) {
-		WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
-		/* assigning eip failed; restore the old cs */
-		ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS);
-		return rc;
-	}
+	/* Error handling is not implemented. */
+	if (rc != X86EMUL_CONTINUE)
+		return X86EMUL_UNHANDLEABLE;
+
 	return rc;
 }
 
@@ -2177,14 +2235,8 @@
 {
 	int rc;
 	unsigned long eip, cs;
-	u16 old_cs;
 	int cpl = ctxt->ops->cpl(ctxt);
-	struct desc_struct old_desc, new_desc;
-	const struct x86_emulate_ops *ops = ctxt->ops;
-
-	if (ctxt->mode == X86EMUL_MODE_PROT64)
-		ops->get_segment(ctxt, &old_cs, &old_desc, NULL,
-				 VCPU_SREG_CS);
+	struct desc_struct new_desc;
 
 	rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
 	if (rc != X86EMUL_CONTINUE)
@@ -2201,10 +2253,10 @@
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 	rc = assign_eip_far(ctxt, eip, &new_desc);
-	if (rc != X86EMUL_CONTINUE) {
-		WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
-		ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
-	}
+	/* Error handling is not implemented. */
+	if (rc != X86EMUL_CONTINUE)
+		return X86EMUL_UNHANDLEABLE;
+
 	return rc;
 }
 
@@ -2479,7 +2531,7 @@
 	u64 smbase;
 	int ret;
 
-	if ((ctxt->emul_flags & X86EMUL_SMM_MASK) == 0)
+	if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_MASK) == 0)
 		return emulate_ud(ctxt);
 
 	/*
@@ -2528,11 +2580,11 @@
 		return X86EMUL_UNHANDLEABLE;
 	}
 
-	if ((ctxt->emul_flags & X86EMUL_SMM_INSIDE_NMI_MASK) == 0)
+	if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_INSIDE_NMI_MASK) == 0)
 		ctxt->ops->set_nmi_mask(ctxt, false);
 
-	ctxt->emul_flags &= ~X86EMUL_SMM_INSIDE_NMI_MASK;
-	ctxt->emul_flags &= ~X86EMUL_SMM_MASK;
+	ctxt->ops->set_hflags(ctxt, ctxt->ops->get_hflags(ctxt) &
+		~(X86EMUL_SMM_INSIDE_NMI_MASK | X86EMUL_SMM_MASK));
 	return X86EMUL_CONTINUE;
 }
 
@@ -3660,8 +3712,8 @@
 	}
 	/* Disable writeback. */
 	ctxt->dst.type = OP_NONE;
-	return segmented_write(ctxt, ctxt->dst.addr.mem,
-			       &desc_ptr, 2 + ctxt->op_bytes);
+	return segmented_write_std(ctxt, ctxt->dst.addr.mem,
+				   &desc_ptr, 2 + ctxt->op_bytes);
 }
 
 static int em_sgdt(struct x86_emulate_ctxt *ctxt)
@@ -3844,6 +3896,131 @@
 	return X86EMUL_CONTINUE;
 }
 
+static int check_fxsr(struct x86_emulate_ctxt *ctxt)
+{
+	u32 eax = 1, ebx, ecx = 0, edx;
+
+	ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+	if (!(edx & FFL(FXSR)))
+		return emulate_ud(ctxt);
+
+	if (ctxt->ops->get_cr(ctxt, 0) & (X86_CR0_TS | X86_CR0_EM))
+		return emulate_nm(ctxt);
+
+	/*
+	 * Don't emulate a case that should never be hit, instead of working
+	 * around a lack of fxsave64/fxrstor64 on old compilers.
+	 */
+	if (ctxt->mode >= X86EMUL_MODE_PROT64)
+		return X86EMUL_UNHANDLEABLE;
+
+	return X86EMUL_CONTINUE;
+}
+
+/*
+ * FXSAVE and FXRSTOR have 4 different formats depending on execution mode,
+ *  1) 16 bit mode
+ *  2) 32 bit mode
+ *     - like (1), but FIP and FDP (foo) are only 16 bit.  At least Intel CPUs
+ *       preserve whole 32 bit values, though, so (1) and (2) are the same wrt.
+ *       save and restore
+ *  3) 64-bit mode with REX.W prefix
+ *     - like (2), but XMM 8-15 are being saved and restored
+ *  4) 64-bit mode without REX.W prefix
+ *     - like (3), but FIP and FDP are 64 bit
+ *
+ * Emulation uses (3) for (1) and (2) and preserves XMM 8-15 to reach the
+ * desired result.  (4) is not emulated.
+ *
+ * Note: Guest and host CPUID.(EAX=07H,ECX=0H):EBX[bit 13] (deprecate FPU CS
+ * and FPU DS) should match.
+ */
+static int em_fxsave(struct x86_emulate_ctxt *ctxt)
+{
+	struct fxregs_state fx_state;
+	size_t size;
+	int rc;
+
+	rc = check_fxsr(ctxt);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	ctxt->ops->get_fpu(ctxt);
+
+	rc = asm_safe("fxsave %[fx]", , [fx] "+m"(fx_state));
+
+	ctxt->ops->put_fpu(ctxt);
+
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	if (ctxt->ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR)
+		size = offsetof(struct fxregs_state, xmm_space[8 * 16/4]);
+	else
+		size = offsetof(struct fxregs_state, xmm_space[0]);
+
+	return segmented_write_std(ctxt, ctxt->memop.addr.mem, &fx_state, size);
+}
+
+static int fxrstor_fixup(struct x86_emulate_ctxt *ctxt,
+		struct fxregs_state *new)
+{
+	int rc = X86EMUL_CONTINUE;
+	struct fxregs_state old;
+
+	rc = asm_safe("fxsave %[fx]", , [fx] "+m"(old));
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	/*
+	 * 64 bit host will restore XMM 8-15, which is not correct on non-64
+	 * bit guests.  Load the current values in order to preserve 64 bit
+	 * XMMs after fxrstor.
+	 */
+#ifdef CONFIG_X86_64
+	/* XXX: accessing XMM 8-15 very awkwardly */
+	memcpy(&new->xmm_space[8 * 16/4], &old.xmm_space[8 * 16/4], 8 * 16);
+#endif
+
+	/*
+	 * Hardware doesn't save and restore XMM 0-7 without CR4.OSFXSR, but
+	 * does save and restore MXCSR.
+	 */
+	if (!(ctxt->ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))
+		memcpy(new->xmm_space, old.xmm_space, 8 * 16);
+
+	return rc;
+}
+
+static int em_fxrstor(struct x86_emulate_ctxt *ctxt)
+{
+	struct fxregs_state fx_state;
+	int rc;
+
+	rc = check_fxsr(ctxt);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	rc = segmented_read_std(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	if (fx_state.mxcsr >> 16)
+		return emulate_gp(ctxt, 0);
+
+	ctxt->ops->get_fpu(ctxt);
+
+	if (ctxt->mode < X86EMUL_MODE_PROT64)
+		rc = fxrstor_fixup(ctxt, &fx_state);
+
+	if (rc == X86EMUL_CONTINUE)
+		rc = asm_safe("fxrstor %[fx]", : [fx] "m"(fx_state));
+
+	ctxt->ops->put_fpu(ctxt);
+
+	return rc;
+}
+
 static bool valid_cr(int nr)
 {
 	switch (nr) {
@@ -4196,7 +4373,9 @@
 };
 
 static const struct group_dual group15 = { {
-	N, N, N, N, N, N, N, GP(0, &pfx_0f_ae_7),
+	I(ModRM | Aligned16, em_fxsave),
+	I(ModRM | Aligned16, em_fxrstor),
+	N, N, N, N, N, GP(0, &pfx_0f_ae_7),
 }, {
 	N, N, N, N, N, N, N, N,
 } };
@@ -5033,7 +5212,7 @@
 	/* Decode and fetch the destination operand: register or memory. */
 	rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
 
-	if (ctxt->rip_relative)
+	if (ctxt->rip_relative && likely(ctxt->memopp))
 		ctxt->memopp->addr.mem.ea = address_mask(ctxt,
 					ctxt->memopp->addr.mem.ea + ctxt->_eip);
 
@@ -5068,21 +5247,13 @@
 
 static int flush_pending_x87_faults(struct x86_emulate_ctxt *ctxt)
 {
-	bool fault = false;
+	int rc;
 
 	ctxt->ops->get_fpu(ctxt);
-	asm volatile("1: fwait \n\t"
-		     "2: \n\t"
-		     ".pushsection .fixup,\"ax\" \n\t"
-		     "3: \n\t"
-		     "movb $1, %[fault] \n\t"
-		     "jmp 2b \n\t"
-		     ".popsection \n\t"
-		     _ASM_EXTABLE(1b, 3b)
-		     : [fault]"+qm"(fault));
+	rc = asm_safe("fwait");
 	ctxt->ops->put_fpu(ctxt);
 
-	if (unlikely(fault))
+	if (unlikely(rc != X86EMUL_CONTINUE))
 		return emulate_exception(ctxt, MF_VECTOR, 0, false);
 
 	return X86EMUL_CONTINUE;
@@ -5125,6 +5296,7 @@
 	const struct x86_emulate_ops *ops = ctxt->ops;
 	int rc = X86EMUL_CONTINUE;
 	int saved_dst_type = ctxt->dst.type;
+	unsigned emul_flags;
 
 	ctxt->mem_read.pos = 0;
 
@@ -5139,6 +5311,7 @@
 		goto done;
 	}
 
+	emul_flags = ctxt->ops->get_hflags(ctxt);
 	if (unlikely(ctxt->d &
 		     (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) {
 		if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
@@ -5172,7 +5345,7 @@
 				fetch_possible_mmx_operand(ctxt, &ctxt->dst);
 		}
 
-		if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) {
+		if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) {
 			rc = emulator_check_intercept(ctxt, ctxt->intercept,
 						      X86_ICPT_PRE_EXCEPT);
 			if (rc != X86EMUL_CONTINUE)
@@ -5201,7 +5374,7 @@
 				goto done;
 		}
 
-		if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
+		if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
 			rc = emulator_check_intercept(ctxt, ctxt->intercept,
 						      X86_ICPT_POST_EXCEPT);
 			if (rc != X86EMUL_CONTINUE)
@@ -5255,7 +5428,7 @@
 
 special_insn:
 
-	if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
+	if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
 		rc = emulator_check_intercept(ctxt, ctxt->intercept,
 					      X86_ICPT_POST_MEMACCESS);
 		if (rc != X86EMUL_CONTINUE)
diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c
index 88d0a92..3aab53f 100644
--- a/arch/x86/kvm/ioapic.c
+++ b/arch/x86/kvm/ioapic.c
@@ -580,7 +580,7 @@
 	ioapic->irr = 0;
 	ioapic->irr_delivered = 0;
 	ioapic->id = 0;
-	memset(ioapic->irq_eoi, 0x00, IOAPIC_NUM_PINS);
+	memset(ioapic->irq_eoi, 0x00, sizeof(ioapic->irq_eoi));
 	rtc_irq_eoi_tracking_reset(ioapic);
 }
 
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 84b96d3..d09544e 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -38,6 +38,15 @@
 			   bool line_status)
 {
 	struct kvm_pic *pic = pic_irqchip(kvm);
+
+	/*
+	 * XXX: rejecting pic routes when pic isn't in use would be better,
+	 * but the default routing table is installed while kvm->arch.vpic is
+	 * NULL and KVM_CREATE_IRQCHIP can race with KVM_IRQ_LINE.
+	 */
+	if (!pic)
+		return -1;
+
 	return kvm_pic_set_irq(pic, e->irqchip.pin, irq_source_id, level);
 }
 
@@ -46,6 +55,10 @@
 			      bool line_status)
 {
 	struct kvm_ioapic *ioapic = kvm->arch.vioapic;
+
+	if (!ioapic)
+		return -1;
+
 	return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, irq_source_id, level,
 				line_status);
 }
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 4d30b86..1c96f09 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2187,3 +2187,9 @@
 	jump_label_rate_limit(&apic_hw_disabled, HZ);
 	jump_label_rate_limit(&apic_sw_disabled, HZ);
 }
+
+void kvm_lapic_exit(void)
+{
+	static_key_deferred_flush(&apic_hw_disabled);
+	static_key_deferred_flush(&apic_sw_disabled);
+}
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index fde8e35d..eb418fd 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -95,6 +95,7 @@
 
 int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
 void kvm_lapic_init(void);
+void kvm_lapic_exit(void);
 
 static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off)
 {
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 8eb8a93..1049c3c 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3433,12 +3433,15 @@
 	return kvm_setup_async_pf(vcpu, gva, kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch);
 }
 
-static bool can_do_async_pf(struct kvm_vcpu *vcpu)
+bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu)
 {
 	if (unlikely(!lapic_in_kernel(vcpu) ||
 		     kvm_event_needs_reinjection(vcpu)))
 		return false;
 
+	if (is_guest_mode(vcpu))
+		return false;
+
 	return kvm_x86_ops->interrupt_allowed(vcpu);
 }
 
@@ -3454,7 +3457,7 @@
 	if (!async)
 		return false; /* *pfn has correct page already */
 
-	if (!prefault && can_do_async_pf(vcpu)) {
+	if (!prefault && kvm_can_do_async_pf(vcpu)) {
 		trace_kvm_try_async_get_page(gva, gfn);
 		if (kvm_find_async_pf_gfn(vcpu, gfn)) {
 			trace_kvm_async_pf_doublefault(gva, gfn);
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 55ffb7b..e60fc80 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -74,6 +74,7 @@
 int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct);
 void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu);
 void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly);
+bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu);
 
 static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
 {
diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
index 3f8c732..0149ac5 100644
--- a/arch/x86/kvm/mtrr.c
+++ b/arch/x86/kvm/mtrr.c
@@ -44,8 +44,6 @@
 	case MSR_MTRRdefType:
 	case MSR_IA32_CR_PAT:
 		return true;
-	case 0x2f8:
-		return true;
 	}
 	return false;
 }
@@ -541,6 +539,7 @@
 
 	iter->fixed = false;
 	iter->start_max = iter->start;
+	iter->range = NULL;
 	iter->range = list_prepare_entry(iter->range, &mtrr_state->head, node);
 
 	__mtrr_lookup_var_next(iter);
diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c
index ab38af4..23a7c7b 100644
--- a/arch/x86/kvm/pmu_intel.c
+++ b/arch/x86/kvm/pmu_intel.c
@@ -294,7 +294,7 @@
 			((u64)1 << edx.split.bit_width_fixed) - 1;
 	}
 
-	pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
+	pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) |
 		(((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
 	pmu->global_ctrl_mask = ~pmu->global_ctrl;
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index f34ab71..bbaa11f 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -408,6 +408,7 @@
 	struct list_head vmcs02_pool;
 	int vmcs02_num;
 	u64 vmcs01_tsc_offset;
+	bool change_vmcs01_virtual_x2apic_mode;
 	/* L2 must run next, and mustn't decide to exit to L1. */
 	bool nested_run_pending;
 	/*
@@ -1246,10 +1247,10 @@
 	return vmcs12->pin_based_vm_exec_control & PIN_BASED_POSTED_INTR;
 }
 
-static inline bool is_exception(u32 intr_info)
+static inline bool is_nmi(u32 intr_info)
 {
 	return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
-		== (INTR_TYPE_HARD_EXCEPTION | INTR_INFO_VALID_MASK);
+		== (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK);
 }
 
 static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
@@ -2263,7 +2264,7 @@
 	if (!(vmcs12->exception_bitmap & (1u << nr)))
 		return 0;
 
-	nested_vmx_vmexit(vcpu, to_vmx(vcpu)->exit_reason,
+	nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
 			  vmcs_read32(VM_EXIT_INTR_INFO),
 			  vmcs_readl(EXIT_QUALIFICATION));
 	return 1;
@@ -3498,7 +3499,7 @@
 	}
 
 	vmcs_write16(sf->selector, var.selector);
-	vmcs_write32(sf->base, var.base);
+	vmcs_writel(sf->base, var.base);
 	vmcs_write32(sf->limit, var.limit);
 	vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(&var));
 }
@@ -4866,6 +4867,12 @@
 	if (vmx_xsaves_supported())
 		vmcs_write64(XSS_EXIT_BITMAP, VMX_XSS_EXIT_BITMAP);
 
+	if (enable_pml) {
+		ASSERT(vmx->pml_pg);
+		vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
+		vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
+	}
+
 	return 0;
 }
 
@@ -4954,8 +4961,8 @@
 		vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
 
 	cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
-	vmx_set_cr0(vcpu, cr0); /* enter rmode */
 	vmx->vcpu.arch.cr0 = cr0;
+	vmx_set_cr0(vcpu, cr0); /* enter rmode */
 	vmx_set_cr4(vcpu, 0);
 	vmx_set_efer(vcpu, 0);
 	vmx_fpu_activate(vcpu);
@@ -5233,7 +5240,7 @@
 	if (is_machine_check(intr_info))
 		return handle_machine_check(vcpu);
 
-	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
+	if (is_nmi(intr_info))
 		return 1;  /* already handled by vmx_vcpu_run() */
 
 	if (is_no_device(intr_info)) {
@@ -6579,7 +6586,13 @@
 
 	/* Checks for #GP/#SS exceptions. */
 	exn = false;
-	if (is_protmode(vcpu)) {
+	if (is_long_mode(vcpu)) {
+		/* Long mode: #GP(0)/#SS(0) if the memory address is in a
+		 * non-canonical form. This is the only check on the memory
+		 * destination for long mode!
+		 */
+		exn = is_noncanonical_address(*ret);
+	} else if (is_protmode(vcpu)) {
 		/* Protected mode: apply checks for segment validity in the
 		 * following order:
 		 * - segment type check (#GP(0) may be thrown)
@@ -6596,17 +6609,10 @@
 			 * execute-only code segment
 			 */
 			exn = ((s.type & 0xa) == 8);
-	}
-	if (exn) {
-		kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
-		return 1;
-	}
-	if (is_long_mode(vcpu)) {
-		/* Long mode: #GP(0)/#SS(0) if the memory address is in a
-		 * non-canonical form. This is an only check for long mode.
-		 */
-		exn = is_noncanonical_address(*ret);
-	} else if (is_protmode(vcpu)) {
+		if (exn) {
+			kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
+			return 1;
+		}
 		/* Protected mode: #GP(0)/#SS(0) if the segment is unusable.
 		 */
 		exn = (s.unusable != 0);
@@ -6672,14 +6678,20 @@
 		}
 
 		page = nested_get_page(vcpu, vmptr);
-		if (page == NULL ||
-		    *(u32 *)kmap(page) != VMCS12_REVISION) {
+		if (page == NULL) {
 			nested_vmx_failInvalid(vcpu);
+			skip_emulated_instruction(vcpu);
+			return 1;
+		}
+		if (*(u32 *)kmap(page) != VMCS12_REVISION) {
 			kunmap(page);
+			nested_release_page_clean(page);
+			nested_vmx_failInvalid(vcpu);
 			skip_emulated_instruction(vcpu);
 			return 1;
 		}
 		kunmap(page);
+		nested_release_page_clean(page);
 		vmx->nested.vmxon_ptr = vmptr;
 		break;
 	case EXIT_REASON_VMCLEAR:
@@ -7722,7 +7734,7 @@
 
 	switch (exit_reason) {
 	case EXIT_REASON_EXCEPTION_NMI:
-		if (!is_exception(intr_info))
+		if (is_nmi(intr_info))
 			return false;
 		else if (is_page_fault(intr_info))
 			return enable_ept;
@@ -7742,8 +7754,6 @@
 	case EXIT_REASON_TASK_SWITCH:
 		return true;
 	case EXIT_REASON_CPUID:
-		if (kvm_register_read(vcpu, VCPU_REGS_RAX) == 0xa)
-			return false;
 		return true;
 	case EXIT_REASON_HLT:
 		return nested_cpu_has(vmcs12, CPU_BASED_HLT_EXITING);
@@ -7828,6 +7838,9 @@
 		return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES);
 	case EXIT_REASON_PCOMMIT:
 		return nested_cpu_has2(vmcs12, SECONDARY_EXEC_PCOMMIT);
+	case EXIT_REASON_PML_FULL:
+		/* We don't expose PML support to L1. */
+		return false;
 	default:
 		return true;
 	}
@@ -7839,22 +7852,6 @@
 	*info2 = vmcs_read32(VM_EXIT_INTR_INFO);
 }
 
-static int vmx_create_pml_buffer(struct vcpu_vmx *vmx)
-{
-	struct page *pml_pg;
-
-	pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO);
-	if (!pml_pg)
-		return -ENOMEM;
-
-	vmx->pml_pg = pml_pg;
-
-	vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
-	vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
-
-	return 0;
-}
-
 static void vmx_destroy_pml_buffer(struct vcpu_vmx *vmx)
 {
 	if (vmx->pml_pg) {
@@ -7915,7 +7912,7 @@
 static void vmx_dump_sel(char *name, uint32_t sel)
 {
 	pr_err("%s sel=0x%04x, attr=0x%05x, limit=0x%08x, base=0x%016lx\n",
-	       name, vmcs_read32(sel),
+	       name, vmcs_read16(sel),
 	       vmcs_read32(sel + GUEST_ES_AR_BYTES - GUEST_ES_SELECTOR),
 	       vmcs_read32(sel + GUEST_ES_LIMIT - GUEST_ES_SELECTOR),
 	       vmcs_readl(sel + GUEST_ES_BASE - GUEST_ES_SELECTOR));
@@ -8125,6 +8122,7 @@
 	if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
 			(exit_reason != EXIT_REASON_EXCEPTION_NMI &&
 			exit_reason != EXIT_REASON_EPT_VIOLATION &&
+			exit_reason != EXIT_REASON_PML_FULL &&
 			exit_reason != EXIT_REASON_TASK_SWITCH)) {
 		vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
 		vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
@@ -8184,6 +8182,12 @@
 {
 	u32 sec_exec_control;
 
+	/* Postpone execution until vmcs01 is the current VMCS. */
+	if (is_guest_mode(vcpu)) {
+		to_vmx(vcpu)->nested.change_vmcs01_virtual_x2apic_mode = true;
+		return;
+	}
+
 	/*
 	 * There is not point to enable virtualize x2apic without enable
 	 * apicv
@@ -8322,8 +8326,7 @@
 		kvm_machine_check();
 
 	/* We need to handle NMIs before interrupts are enabled */
-	if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
-	    (exit_intr_info & INTR_INFO_VALID_MASK)) {
+	if (is_nmi(exit_intr_info)) {
 		kvm_before_handle_nmi(&vmx->vcpu);
 		asm("int $2");
 		kvm_after_handle_nmi(&vmx->vcpu);
@@ -8737,6 +8740,22 @@
 	put_cpu();
 }
 
+/*
+ * Ensure that the current vmcs of the logical processor is the
+ * vmcs01 of the vcpu before calling free_nested().
+ */
+static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       int r;
+
+       r = vcpu_load(vcpu);
+       BUG_ON(r);
+       vmx_load_vmcs01(vcpu);
+       free_nested(vmx);
+       vcpu_put(vcpu);
+}
+
 static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -8745,8 +8764,7 @@
 		vmx_destroy_pml_buffer(vmx);
 	free_vpid(vmx->vpid);
 	leave_guest_mode(vcpu);
-	vmx_load_vmcs01(vcpu);
-	free_nested(vmx);
+	vmx_free_vcpu_nested(vcpu);
 	free_loaded_vmcs(vmx->loaded_vmcs);
 	kfree(vmx->guest_msrs);
 	kvm_vcpu_uninit(vcpu);
@@ -8768,14 +8786,26 @@
 	if (err)
 		goto free_vcpu;
 
+	err = -ENOMEM;
+
+	/*
+	 * If PML is turned on, failure on enabling PML just results in failure
+	 * of creating the vcpu, therefore we can simplify PML logic (by
+	 * avoiding dealing with cases, such as enabling PML partially on vcpus
+	 * for the guest, etc.
+	 */
+	if (enable_pml) {
+		vmx->pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (!vmx->pml_pg)
+			goto uninit_vcpu;
+	}
+
 	vmx->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	BUILD_BUG_ON(ARRAY_SIZE(vmx_msr_index) * sizeof(vmx->guest_msrs[0])
 		     > PAGE_SIZE);
 
-	err = -ENOMEM;
-	if (!vmx->guest_msrs) {
-		goto uninit_vcpu;
-	}
+	if (!vmx->guest_msrs)
+		goto free_pml;
 
 	vmx->loaded_vmcs = &vmx->vmcs01;
 	vmx->loaded_vmcs->vmcs = alloc_vmcs();
@@ -8819,18 +8849,6 @@
 	vmx->nested.current_vmptr = -1ull;
 	vmx->nested.current_vmcs12 = NULL;
 
-	/*
-	 * If PML is turned on, failure on enabling PML just results in failure
-	 * of creating the vcpu, therefore we can simplify PML logic (by
-	 * avoiding dealing with cases, such as enabling PML partially on vcpus
-	 * for the guest, etc.
-	 */
-	if (enable_pml) {
-		err = vmx_create_pml_buffer(vmx);
-		if (err)
-			goto free_vmcs;
-	}
-
 	return &vmx->vcpu;
 
 free_vmcs:
@@ -8838,6 +8856,8 @@
 	free_loaded_vmcs(vmx->loaded_vmcs);
 free_msrs:
 	kfree(vmx->guest_msrs);
+free_pml:
+	vmx_destroy_pml_buffer(vmx);
 uninit_vcpu:
 	kvm_vcpu_uninit(&vmx->vcpu);
 free_vcpu:
@@ -9740,6 +9760,18 @@
 
 	}
 
+	if (enable_pml) {
+		/*
+		 * Conceptually we want to copy the PML address and index from
+		 * vmcs01 here, and then back to vmcs01 on nested vmexit. But,
+		 * since we always flush the log on each vmexit, this happens
+		 * to be equivalent to simply resetting the fields in vmcs02.
+		 */
+		ASSERT(vmx->pml_pg);
+		vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
+		vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
+	}
+
 	if (nested_cpu_has_ept(vmcs12)) {
 		kvm_mmu_unload(vcpu);
 		nested_ept_init_mmu_context(vcpu);
@@ -10468,6 +10500,12 @@
 	/* Update TSC_OFFSET if TSC was changed while L2 ran */
 	vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset);
 
+	if (vmx->nested.change_vmcs01_virtual_x2apic_mode) {
+		vmx->nested.change_vmcs01_virtual_x2apic_mode = false;
+		vmx_set_virtual_x2apic_mode(vcpu,
+				vcpu->arch.apic_base & X2APIC_ENABLE);
+	}
+
 	/* This is needed for same reason as it was needed in prepare_vmcs02 */
 	vmx->host_rsp = 0;
 
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 605cea7..8e526c6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -199,7 +199,18 @@
 	struct kvm_shared_msrs *locals
 		= container_of(urn, struct kvm_shared_msrs, urn);
 	struct kvm_shared_msr_values *values;
+	unsigned long flags;
 
+	/*
+	 * Disabling irqs at this point since the following code could be
+	 * interrupted and executed through kvm_arch_hardware_disable()
+	 */
+	local_irq_save(flags);
+	if (locals->registered) {
+		locals->registered = false;
+		user_return_notifier_unregister(urn);
+	}
+	local_irq_restore(flags);
 	for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
 		values = &locals->values[slot];
 		if (values->host != values->curr) {
@@ -207,8 +218,6 @@
 			values->curr = values->host;
 		}
 	}
-	locals->registered = false;
-	user_return_notifier_unregister(urn);
 }
 
 static void shared_msr_update(unsigned slot, u32 msr)
@@ -2735,7 +2744,6 @@
 	}
 
 	kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
-	vcpu->arch.switch_db_regs |= KVM_DEBUGREG_RELOAD;
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -2941,6 +2949,8 @@
 	memset(&events->reserved, 0, sizeof(events->reserved));
 }
 
+static void kvm_set_hflags(struct kvm_vcpu *vcpu, unsigned emul_flags);
+
 static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
 					      struct kvm_vcpu_events *events)
 {
@@ -2950,6 +2960,12 @@
 			      | KVM_VCPUEVENT_VALID_SMM))
 		return -EINVAL;
 
+	/* INITs are latched while in SMM */
+	if (events->flags & KVM_VCPUEVENT_VALID_SMM &&
+	    (events->smi.smm || events->smi.pending) &&
+	    vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED)
+		return -EINVAL;
+
 	process_nmi(vcpu);
 	vcpu->arch.exception.pending = events->exception.injected;
 	vcpu->arch.exception.nr = events->exception.nr;
@@ -2973,10 +2989,13 @@
 		vcpu->arch.apic->sipi_vector = events->sipi_vector;
 
 	if (events->flags & KVM_VCPUEVENT_VALID_SMM) {
+		u32 hflags = vcpu->arch.hflags;
 		if (events->smi.smm)
-			vcpu->arch.hflags |= HF_SMM_MASK;
+			hflags |= HF_SMM_MASK;
 		else
-			vcpu->arch.hflags &= ~HF_SMM_MASK;
+			hflags &= ~HF_SMM_MASK;
+		kvm_set_hflags(vcpu, hflags);
+
 		vcpu->arch.smi_pending = events->smi.pending;
 		if (events->smi.smm_inside_nmi)
 			vcpu->arch.hflags |= HF_SMM_INSIDE_NMI_MASK;
@@ -3014,6 +3033,11 @@
 	if (dbgregs->flags)
 		return -EINVAL;
 
+	if (dbgregs->dr6 & ~0xffffffffull)
+		return -EINVAL;
+	if (dbgregs->dr7 & ~0xffffffffull)
+		return -EINVAL;
+
 	memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db));
 	kvm_update_dr0123(vcpu);
 	vcpu->arch.dr6 = dbgregs->dr6;
@@ -3039,6 +3063,7 @@
 	memcpy(dest, xsave, XSAVE_HDR_OFFSET);
 
 	/* Set XSTATE_BV */
+	xstate_bv &= vcpu->arch.guest_supported_xcr0 | XFEATURE_MASK_FPSSE;
 	*(u64 *)(dest + XSAVE_HDR_OFFSET) = xstate_bv;
 
 	/*
@@ -3115,11 +3140,14 @@
 	}
 }
 
+#define XSAVE_MXCSR_OFFSET 24
+
 static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
 					struct kvm_xsave *guest_xsave)
 {
 	u64 xstate_bv =
 		*(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)];
+	u32 mxcsr = *(u32 *)&guest_xsave->region[XSAVE_MXCSR_OFFSET / sizeof(u32)];
 
 	if (cpu_has_xsave) {
 		/*
@@ -3127,11 +3155,13 @@
 		 * CPUID leaf 0xD, index 0, EDX:EAX.  This is for compatibility
 		 * with old userspace.
 		 */
-		if (xstate_bv & ~kvm_supported_xcr0())
+		if (xstate_bv & ~kvm_supported_xcr0() ||
+			mxcsr & ~mxcsr_feature_mask)
 			return -EINVAL;
 		load_xsave(vcpu, (u8 *)guest_xsave->region);
 	} else {
-		if (xstate_bv & ~XFEATURE_MASK_FPSSE)
+		if (xstate_bv & ~XFEATURE_MASK_FPSSE ||
+			mxcsr & ~mxcsr_feature_mask)
 			return -EINVAL;
 		memcpy(&vcpu->arch.guest_fpu.state.fxsave,
 			guest_xsave->region, sizeof(struct fxregs_state));
@@ -3313,6 +3343,7 @@
 	};
 	case KVM_SET_VAPIC_ADDR: {
 		struct kvm_vapic_addr va;
+		int idx;
 
 		r = -EINVAL;
 		if (!lapic_in_kernel(vcpu))
@@ -3320,7 +3351,9 @@
 		r = -EFAULT;
 		if (copy_from_user(&va, argp, sizeof va))
 			goto out;
+		idx = srcu_read_lock(&vcpu->kvm->srcu);
 		r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
+		srcu_read_unlock(&vcpu->kvm->srcu, idx);
 		break;
 	}
 	case KVM_X86_SETUP_MCE: {
@@ -4575,16 +4608,20 @@
 
 static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
 {
-	/* TODO: String I/O for in kernel device */
-	int r;
+	int r = 0, i;
 
-	if (vcpu->arch.pio.in)
-		r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
-				    vcpu->arch.pio.size, pd);
-	else
-		r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
-				     vcpu->arch.pio.port, vcpu->arch.pio.size,
-				     pd);
+	for (i = 0; i < vcpu->arch.pio.count; i++) {
+		if (vcpu->arch.pio.in)
+			r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
+					    vcpu->arch.pio.size, pd);
+		else
+			r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
+					     vcpu->arch.pio.port, vcpu->arch.pio.size,
+					     pd);
+		if (r)
+			break;
+		pd += vcpu->arch.pio.size;
+	}
 	return r;
 }
 
@@ -4622,6 +4659,8 @@
 	if (vcpu->arch.pio.count)
 		goto data_avail;
 
+	memset(vcpu->arch.pio_data, 0, size * count);
+
 	ret = emulator_pio_in_out(vcpu, size, port, val, count, true);
 	if (ret) {
 data_avail:
@@ -4805,6 +4844,8 @@
 
 	if (var.unusable) {
 		memset(desc, 0, sizeof(*desc));
+		if (base3)
+			*base3 = 0;
 		return false;
 	}
 
@@ -4960,6 +5001,16 @@
 	kvm_x86_ops->set_nmi_mask(emul_to_vcpu(ctxt), masked);
 }
 
+static unsigned emulator_get_hflags(struct x86_emulate_ctxt *ctxt)
+{
+	return emul_to_vcpu(ctxt)->arch.hflags;
+}
+
+static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_flags)
+{
+	kvm_set_hflags(emul_to_vcpu(ctxt), emul_flags);
+}
+
 static const struct x86_emulate_ops emulate_ops = {
 	.read_gpr            = emulator_read_gpr,
 	.write_gpr           = emulator_write_gpr,
@@ -4999,6 +5050,8 @@
 	.intercept           = emulator_intercept,
 	.get_cpuid           = emulator_get_cpuid,
 	.set_nmi_mask        = emulator_set_nmi_mask,
+	.get_hflags          = emulator_get_hflags,
+	.set_hflags          = emulator_set_hflags,
 };
 
 static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
@@ -5051,7 +5104,6 @@
 	BUILD_BUG_ON(HF_GUEST_MASK != X86EMUL_GUEST_MASK);
 	BUILD_BUG_ON(HF_SMM_MASK != X86EMUL_SMM_MASK);
 	BUILD_BUG_ON(HF_SMM_INSIDE_NMI_MASK != X86EMUL_SMM_INSIDE_NMI_MASK);
-	ctxt->emul_flags = vcpu->arch.hflags;
 
 	init_decode_cache(ctxt);
 	vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
@@ -5447,8 +5499,6 @@
 		unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
 		toggle_interruptibility(vcpu, ctxt->interruptibility);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
-		if (vcpu->arch.hflags != ctxt->emul_flags)
-			kvm_set_hflags(vcpu, ctxt->emul_flags);
 		kvm_rip_write(vcpu, ctxt->eip);
 		if (r == EMULATE_DONE)
 			kvm_vcpu_check_singlestep(vcpu, rflags, &r);
@@ -5821,6 +5871,7 @@
 
 void kvm_arch_exit(void)
 {
+	kvm_lapic_exit();
 	perf_unregister_guest_info_callbacks(&kvm_guest_cbs);
 
 	if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
@@ -5934,7 +5985,8 @@
 
 	kvm_x86_ops->patch_hypercall(vcpu, instruction);
 
-	return emulator_write_emulated(ctxt, rip, instruction, 3, NULL);
+	return emulator_write_emulated(ctxt, rip, instruction, 3,
+		&ctxt->exception);
 }
 
 static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu)
@@ -6970,6 +7022,12 @@
 	    mp_state->mp_state != KVM_MP_STATE_RUNNABLE)
 		return -EINVAL;
 
+	/* INITs are latched while in SMM */
+	if ((is_smm(vcpu) || vcpu->arch.smi_pending) &&
+	    (mp_state->mp_state == KVM_MP_STATE_SIPI_RECEIVED ||
+	     mp_state->mp_state == KVM_MP_STATE_INIT_RECEIVED))
+		return -EINVAL;
+
 	if (mp_state->mp_state == KVM_MP_STATE_SIPI_RECEIVED) {
 		vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
 		set_bit(KVM_APIC_SIPI, &vcpu->arch.apic->pending_events);
@@ -7248,10 +7306,12 @@
 
 void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 {
+	void *wbinvd_dirty_mask = vcpu->arch.wbinvd_dirty_mask;
+
 	kvmclock_reset(vcpu);
 
-	free_cpumask_var(vcpu->arch.wbinvd_dirty_mask);
 	kvm_x86_ops->vcpu_free(vcpu);
+	free_cpumask_var(wbinvd_dirty_mask);
 }
 
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
@@ -8197,8 +8257,7 @@
 	if (!(vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED))
 		return true;
 	else
-		return !kvm_event_needs_reinjection(vcpu) &&
-			kvm_x86_ops->interrupt_allowed(vcpu);
+		return kvm_can_do_async_pf(vcpu);
 }
 
 void kvm_arch_start_assignment(struct kvm *kvm)
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index 27f89c7..423644c 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -80,7 +80,7 @@
 	movl %edx,%ecx
 	andl $63,%edx
 	shrl $6,%ecx
-	jz 17f
+	jz .L_copy_short_string
 1:	movq (%rsi),%r8
 2:	movq 1*8(%rsi),%r9
 3:	movq 2*8(%rsi),%r10
@@ -101,7 +101,8 @@
 	leaq 64(%rdi),%rdi
 	decl %ecx
 	jnz 1b
-17:	movl %edx,%ecx
+.L_copy_short_string:
+	movl %edx,%ecx
 	andl $7,%edx
 	shrl $3,%ecx
 	jz 20f
@@ -215,6 +216,8 @@
  */
 ENTRY(copy_user_enhanced_fast_string)
 	ASM_STAC
+	cmpl $64,%edx
+	jb .L_copy_short_string	/* less then 64 bytes, avoid the costly 'rep' */
 	movl %edx,%ecx
 1:	rep
 	movsb
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 42982b2..39bdaf3 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -144,7 +144,7 @@
 		addr = ALIGN(addr, huge_page_size(h));
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 	if (mm->get_unmapped_area == arch_get_unmapped_area)
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 493f541..3aebbd6 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -628,21 +628,40 @@
  * devmem_is_allowed() checks to see if /dev/mem access to a certain address
  * is valid. The argument is a physical page number.
  *
- *
- * On x86, access has to be given to the first megabyte of ram because that area
- * contains BIOS code and data regions used by X and dosemu and similar apps.
- * Access has to be given to non-kernel-ram areas as well, these contain the PCI
- * mmio resources as well as potential bios/acpi data regions.
+ * On x86, access has to be given to the first megabyte of RAM because that
+ * area traditionally contains BIOS code and data regions used by X, dosemu,
+ * and similar apps. Since they map the entire memory range, the whole range
+ * must be allowed (for mapping), but any areas that would otherwise be
+ * disallowed are flagged as being "zero filled" instead of rejected.
+ * Access has to be given to non-kernel-ram areas as well, these contain the
+ * PCI mmio resources as well as potential bios/acpi data regions.
  */
 int devmem_is_allowed(unsigned long pagenr)
 {
-	if (pagenr < 256)
-		return 1;
-	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+	if (page_is_ram(pagenr)) {
+		/*
+		 * For disallowed memory regions in the low 1MB range,
+		 * request that the page be shown as all zeros.
+		 */
+		if (pagenr < 256)
+			return 2;
+
 		return 0;
-	if (!page_is_ram(pagenr))
-		return 1;
-	return 0;
+	}
+
+	/*
+	 * This must follow RAM test, since System RAM is considered a
+	 * restricted resource under CONFIG_STRICT_IOMEM.
+	 */
+	if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) {
+		/* Low 1MB bypasses iomem restrictions. */
+		if (pagenr < 256)
+			return 1;
+
+		return 0;
+	}
+
+	return 1;
 }
 
 void free_init_pages(char *what, unsigned long begin, unsigned long end)
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index cb4ef3d..2ebfbaf 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -871,7 +871,6 @@
 	return flag;
 }
 
-#ifdef CONFIG_DEBUG_RODATA
 const int rodata_test_data = 0xC3;
 EXPORT_SYMBOL_GPL(rodata_test_data);
 
@@ -960,5 +959,3 @@
 	if (__supported_pte_mask & _PAGE_NX)
 		debug_checkwx();
 }
-#endif
-
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index ec081fe..e08d141 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1062,7 +1062,6 @@
 	mem_init_print_info(NULL);
 }
 
-#ifdef CONFIG_DEBUG_RODATA
 const int rodata_test_data = 0xC3;
 EXPORT_SYMBOL_GPL(rodata_test_data);
 
@@ -1154,8 +1153,6 @@
 	debug_checkwx();
 }
 
-#endif
-
 int kern_addr_valid(unsigned long addr)
 {
 	unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index d470cf2..4e5ac46 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -1,3 +1,4 @@
+#define DISABLE_BRANCH_PROFILING
 #define pr_fmt(fmt) "kasan: " fmt
 #include <linux/bootmem.h>
 #include <linux/kasan.h>
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 72bb52f..d2dc043 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -94,18 +94,6 @@
 }
 
 /*
- * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
- * does, but not when emulating X86_32
- */
-static unsigned long mmap_legacy_base(unsigned long rnd)
-{
-	if (mmap_is_ia32())
-		return TASK_UNMAPPED_BASE;
-	else
-		return TASK_UNMAPPED_BASE + rnd;
-}
-
-/*
  * This function, called very early during the creation of a new
  * process VM image, sets up which VM layout function to use:
  */
@@ -116,7 +104,7 @@
 	if (current->flags & PF_RANDOMIZE)
 		random_factor = arch_mmap_rnd();
 
-	mm->mmap_legacy_base = mmap_legacy_base(random_factor);
+	mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor;
 
 	if (mmap_is_legacy()) {
 		mm->mmap_base = mm->mmap_legacy_base;
diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index ef05755..7ed47b1 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -293,7 +293,7 @@
 	 * We were not able to extract an address from the instruction,
 	 * probably because there was something invalid in it.
 	 */
-	if (info->si_addr == (void *)-1) {
+	if (info->si_addr == (void __user *)-1) {
 		err = -EINVAL;
 		goto err_out;
 	}
@@ -525,15 +525,7 @@
 	if (!kernel_managing_mpx_tables(current->mm))
 		return -EINVAL;
 
-	if (do_mpx_bt_fault()) {
-		force_sig(SIGSEGV, current);
-		/*
-		 * The force_sig() is essentially "handling" this
-		 * exception, so we do not pass up the error
-		 * from do_mpx_bt_fault().
-		 */
-	}
-	return 0;
+	return do_mpx_bt_fault();
 }
 
 /*
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 47b6436..3686a1d 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -100,5 +100,6 @@
 	printk(KERN_DEBUG "High memory starts at vaddr %08lx\n",
 			(ulong) pfn_to_kaddr(highstart_pfn));
 
+	__vmalloc_start_set = true;
 	setup_bootmem_allocator();
 }
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index b599a78..4540e88 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -278,7 +278,7 @@
 		   __pa_symbol(__end_rodata) >> PAGE_SHIFT))
 		pgprot_val(forbidden) |= _PAGE_RW;
 
-#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
+#if defined(CONFIG_X86_64)
 	/*
 	 * Once the kernel maps the text as RO (kernel_set_to_readonly is set),
 	 * kernel text mappings for the large page aligned text, rodata sections
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 188e3e0..3f1bb4f 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -36,13 +36,22 @@
 #undef pr_fmt
 #define pr_fmt(fmt) "" fmt
 
-static bool boot_cpu_done;
+static bool __read_mostly boot_cpu_done;
+static bool __read_mostly pat_disabled = !IS_ENABLED(CONFIG_X86_PAT);
+static bool __read_mostly pat_initialized;
+static bool __read_mostly init_cm_done;
 
-static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT);
-
-static inline void pat_disable(const char *reason)
+void pat_disable(const char *reason)
 {
-	__pat_enabled = 0;
+	if (pat_disabled)
+		return;
+
+	if (boot_cpu_done) {
+		WARN_ONCE(1, "x86/PAT: PAT cannot be disabled after initialization\n");
+		return;
+	}
+
+	pat_disabled = true;
 	pr_info("x86/PAT: %s\n", reason);
 }
 
@@ -55,7 +64,7 @@
 
 bool pat_enabled(void)
 {
-	return !!__pat_enabled;
+	return pat_initialized;
 }
 EXPORT_SYMBOL_GPL(pat_enabled);
 
@@ -180,7 +189,7 @@
  * configuration.
  * Using lower indices is preferred, so we start with highest index.
  */
-void pat_init_cache_modes(u64 pat)
+static void __init_cache_modes(u64 pat)
 {
 	enum page_cache_mode cache;
 	char pat_msg[33];
@@ -193,6 +202,8 @@
 		update_cache_mode_entry(i, cache);
 	}
 	pr_info("x86/PAT: Configuration [0-7]: %s\n", pat_msg);
+
+	init_cm_done = true;
 }
 
 #define PAT(x, y)	((u64)PAT_ ## y << ((x)*8))
@@ -201,14 +212,11 @@
 {
 	u64 tmp_pat;
 
-	if (!cpu_has_pat) {
+	if (!boot_cpu_has(X86_FEATURE_PAT)) {
 		pat_disable("PAT not supported by CPU.");
 		return;
 	}
 
-	if (!pat_enabled())
-		goto done;
-
 	rdmsrl(MSR_IA32_CR_PAT, tmp_pat);
 	if (!tmp_pat) {
 		pat_disable("PAT MSR is 0, disabled.");
@@ -216,17 +224,14 @@
 	}
 
 	wrmsrl(MSR_IA32_CR_PAT, pat);
+	pat_initialized = true;
 
-done:
-	pat_init_cache_modes(pat);
+	__init_cache_modes(pat);
 }
 
 static void pat_ap_init(u64 pat)
 {
-	if (!pat_enabled())
-		return;
-
-	if (!cpu_has_pat) {
+	if (!boot_cpu_has(X86_FEATURE_PAT)) {
 		/*
 		 * If this happens we are on a secondary CPU, but switched to
 		 * PAT on the boot CPU. We have no way to undo PAT.
@@ -237,18 +242,31 @@
 	wrmsrl(MSR_IA32_CR_PAT, pat);
 }
 
-void pat_init(void)
+void init_cache_modes(void)
 {
-	u64 pat;
-	struct cpuinfo_x86 *c = &boot_cpu_data;
+	u64 pat = 0;
 
-	if (!pat_enabled()) {
+	if (init_cm_done)
+		return;
+
+	if (boot_cpu_has(X86_FEATURE_PAT)) {
+		/*
+		 * CPU supports PAT. Set PAT table to be consistent with
+		 * PAT MSR. This case supports "nopat" boot option, and
+		 * virtual machine environments which support PAT without
+		 * MTRRs. In specific, Xen has unique setup to PAT MSR.
+		 *
+		 * If PAT MSR returns 0, it is considered invalid and emulates
+		 * as No PAT.
+		 */
+		rdmsrl(MSR_IA32_CR_PAT, pat);
+	}
+
+	if (!pat) {
 		/*
 		 * No PAT. Emulate the PAT table that corresponds to the two
-		 * cache bits, PWT (Write Through) and PCD (Cache Disable). This
-		 * setup is the same as the BIOS default setup when the system
-		 * has PAT but the "nopat" boot option has been specified. This
-		 * emulated PAT table is used when MSR_IA32_CR_PAT returns 0.
+		 * cache bits, PWT (Write Through) and PCD (Cache Disable).
+		 * This setup is also the same as the BIOS default setup.
 		 *
 		 * PTE encoding:
 		 *
@@ -265,10 +283,32 @@
 		 */
 		pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) |
 		      PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC);
+	}
 
-	} else if ((c->x86_vendor == X86_VENDOR_INTEL) &&
-		   (((c->x86 == 0x6) && (c->x86_model <= 0xd)) ||
-		    ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) {
+	__init_cache_modes(pat);
+}
+
+/**
+ * pat_init - Initialize PAT MSR and PAT table
+ *
+ * This function initializes PAT MSR and PAT table with an OS-defined value
+ * to enable additional cache attributes, WC and WT.
+ *
+ * This function must be called on all CPUs using the specific sequence of
+ * operations defined in Intel SDM. mtrr_rendezvous_handler() provides this
+ * procedure for PAT.
+ */
+void pat_init(void)
+{
+	u64 pat;
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+
+	if (pat_disabled)
+		return;
+
+	if ((c->x86_vendor == X86_VENDOR_INTEL) &&
+	    (((c->x86 == 0x6) && (c->x86_model <= 0xd)) ||
+	     ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) {
 		/*
 		 * PAT support with the lower four entries. Intel Pentium 2,
 		 * 3, M, and 4 are affected by PAT errata, which makes the
@@ -733,25 +773,6 @@
 	if (file->f_flags & O_DSYNC)
 		pcm = _PAGE_CACHE_MODE_UC_MINUS;
 
-#ifdef CONFIG_X86_32
-	/*
-	 * On the PPro and successors, the MTRRs are used to set
-	 * memory types for physical addresses outside main memory,
-	 * so blindly setting UC or PWT on those pages is wrong.
-	 * For Pentiums and earlier, the surround logic should disable
-	 * caching for the high addresses through the KEN pin, but
-	 * we maintain the tradition of paranoia in this code.
-	 */
-	if (!pat_enabled() &&
-	    !(boot_cpu_has(X86_FEATURE_MTRR) ||
-	      boot_cpu_has(X86_FEATURE_K6_MTRR) ||
-	      boot_cpu_has(X86_FEATURE_CYRIX_ARR) ||
-	      boot_cpu_has(X86_FEATURE_CENTAUR_MCR)) &&
-	    (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
-		pcm = _PAGE_CACHE_MODE_UC;
-	}
-#endif
-
 	*vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
 			     cachemode2protval(pcm));
 	return 1;
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 5fb6ada..5a760fd 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -134,8 +134,6 @@
 {
 	struct flush_tlb_info info;
 
-	if (end == 0)
-		end = start + PAGE_SIZE;
 	info.flush_mm = mm;
 	info.flush_start = start;
 	info.flush_end = end;
@@ -264,7 +262,7 @@
 	}
 
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
-		flush_tlb_others(mm_cpumask(mm), mm, start, 0UL);
+		flush_tlb_others(mm_cpumask(mm), mm, start, start + PAGE_SIZE);
 
 	preempt_enable();
 }
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 3cd6983..3961103 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -114,6 +114,16 @@
 			DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
 		},
 	},
+	/* https://bugzilla.kernel.org/show_bug.cgi?id=42606 */
+	{
+		.callback = set_nouse_crs,
+		.ident = "Supermicro X8DTH",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X8DTH-i/6/iF/6F"),
+			DMI_MATCH(DMI_BIOS_VERSION, "2.0a"),
+		},
+	},
 
 	/* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
 	{
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 8b93e63..ae97f24 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -37,6 +37,7 @@
 
 /* Quirks for the listed devices */
 #define PCI_DEVICE_ID_INTEL_MRFL_MMC	0x1190
+#define PCI_DEVICE_ID_INTEL_MRFL_HSU	0x1191
 
 /* Fixed BAR fields */
 #define PCIE_VNDR_CAP_ID_FIXED_BAR 0x00	/* Fixed BAR (TBD) */
@@ -225,13 +226,20 @@
 		/* Special treatment for IRQ0 */
 		if (dev->irq == 0) {
 			/*
+			 * Skip HS UART common registers device since it has
+			 * IRQ0 assigned and not used by the kernel.
+			 */
+			if (dev->device == PCI_DEVICE_ID_INTEL_MRFL_HSU)
+				return -EBUSY;
+			/*
 			 * TNG has IRQ0 assigned to eMMC controller. But there
 			 * are also other devices with bogus PCI configuration
 			 * that have IRQ0 assigned. This check ensures that
-			 * eMMC gets it.
+			 * eMMC gets it. The rest of devices still could be
+			 * enabled without interrupt line being allocated.
 			 */
 			if (dev->device != PCI_DEVICE_ID_INTEL_MRFL_MMC)
-				return -EBUSY;
+				return 0;
 		}
 		break;
 	default:
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index ff31ab4..7575f07 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -231,23 +231,14 @@
 		return 1;
 
 	for_each_pci_msi_entry(msidesc, dev) {
-		__pci_read_msi_msg(msidesc, &msg);
-		pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
-			((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
-		if (msg.data != XEN_PIRQ_MSI_DATA ||
-		    xen_irq_from_pirq(pirq) < 0) {
-			pirq = xen_allocate_pirq_msi(dev, msidesc);
-			if (pirq < 0) {
-				irq = -ENODEV;
-				goto error;
-			}
-			xen_msi_compose_msg(dev, pirq, &msg);
-			__pci_write_msi_msg(msidesc, &msg);
-			dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
-		} else {
-			dev_dbg(&dev->dev,
-				"xen: msi already bound to pirq=%d\n", pirq);
+		pirq = xen_allocate_pirq_msi(dev, msidesc);
+		if (pirq < 0) {
+			irq = -ENODEV;
+			goto error;
 		}
+		xen_msi_compose_msg(dev, pirq, &msg);
+		__pci_write_msi_msg(msidesc, &msg);
+		dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
 		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq,
 					       (type == PCI_CAP_ID_MSI) ? nvec : 1,
 					       (type == PCI_CAP_ID_MSIX) ?
@@ -488,8 +479,11 @@
 #endif
 	__acpi_register_gsi = acpi_register_gsi_xen;
 	__acpi_unregister_gsi = NULL;
-	/* Pre-allocate legacy irqs */
-	for (irq = 0; irq < nr_legacy_irqs(); irq++) {
+	/*
+	 * Pre-allocate the legacy IRQs.  Use NR_LEGACY_IRQS here
+	 * because we don't have a PIC and thus nr_legacy_irqs() is zero.
+	 */
+	for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
 		int trigger, polarity;
 
 		if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
diff --git a/arch/x86/platform/goldfish/goldfish.c b/arch/x86/platform/goldfish/goldfish.c
index 1693107..0d17c0a 100644
--- a/arch/x86/platform/goldfish/goldfish.c
+++ b/arch/x86/platform/goldfish/goldfish.c
@@ -42,10 +42,22 @@
 	}
 };
 
+static bool goldfish_enable __initdata;
+
+static int __init goldfish_setup(char *str)
+{
+	goldfish_enable = true;
+	return 0;
+}
+__setup("goldfish", goldfish_setup);
+
 static int __init goldfish_init(void)
 {
+	if (!goldfish_enable)
+		return -ENODEV;
+
 	platform_device_register_simple("goldfish_pdev_bus", -1,
-						goldfish_pdev_bus_resources, 2);
+					goldfish_pdev_bus_resources, 2);
 	return 0;
 }
 device_initcall(goldfish_init);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
index de73413..40c6164 100644
--- a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
+++ b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
@@ -17,7 +17,7 @@
 #include <asm/intel-mid.h>
 #include <asm/io_apic.h>
 
-#define TANGIER_EXT_TIMER0_MSI 15
+#define TANGIER_EXT_TIMER0_MSI 12
 
 static struct platform_device wdt_dev = {
 	.name = "intel_mid_wdt",
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 2c835e3..d445c5f 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -12,6 +12,7 @@
 
 KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large
 KBUILD_CFLAGS += -m$(BITS)
+KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
 
 $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
 		$(call if_changed,ld)
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 0c2fae8..73eb7fd 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -992,11 +992,12 @@
 		die("Segment relocations found but --realmode not specified\n");
 
 	/* Order the relocations for more efficient processing */
-	sort_relocs(&relocs16);
 	sort_relocs(&relocs32);
 #if ELF_BITS == 64
 	sort_relocs(&relocs32neg);
 	sort_relocs(&relocs64);
+#else
+	sort_relocs(&relocs16);
 #endif
 
 	/* Print the relocations */
diff --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c
index a629694..e14c43a 100644
--- a/arch/x86/um/ptrace_64.c
+++ b/arch/x86/um/ptrace_64.c
@@ -121,7 +121,7 @@
 	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
 		(addr <= offsetof(struct user, u_debugreg[7]))) {
 		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
+		addr = addr >> 3;
 		if ((addr == 4) || (addr == 5))
 			return -EIO;
 		child->thread.arch.debugregs[addr] = data;
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index beab8c7..ffa4159 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -74,7 +74,6 @@
 #include <asm/mach_traps.h>
 #include <asm/mwait.h>
 #include <asm/pci_x86.h>
-#include <asm/pat.h>
 #include <asm/cpu.h>
 
 #ifdef CONFIG_ACPI
@@ -1519,7 +1518,6 @@
 {
 	struct physdev_set_iopl set_iopl;
 	unsigned long initrd_start = 0;
-	u64 pat;
 	int rc;
 
 	if (!xen_start_info)
@@ -1627,13 +1625,6 @@
 				   xen_start_info->nr_pages);
 	xen_reserve_special_pages();
 
-	/*
-	 * Modify the cache mode translation tables to match Xen's PAT
-	 * configuration.
-	 */
-	rdmsrl(MSR_IA32_CR_PAT, pat);
-	pat_init_cache_modes(pat);
-
 	/* keep using Xen gdt for now; no urgent need to change it */
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index cb5e266..63146c3 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1113,7 +1113,7 @@
 
 	/* NOTE: The loop is more greedy than the cleanup_highmap variant.
 	 * We include the PMD passed in on _both_ boundaries. */
-	for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PAGE_SIZE));
+	for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PTRS_PER_PMD));
 			pmd++, vaddr += PMD_SIZE) {
 		if (pmd_none(*pmd))
 			continue;
@@ -2038,7 +2038,8 @@
 
 /*
  * Translate a virtual address to a physical one without relying on mapped
- * page tables.
+ * page tables. Don't rely on big pages being aligned in (guest) physical
+ * space!
  */
 static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
 {
@@ -2059,7 +2060,7 @@
 						       sizeof(pud)));
 	if (!pud_present(pud))
 		return 0;
-	pa = pud_pfn(pud) << PAGE_SHIFT;
+	pa = pud_val(pud) & PTE_PFN_MASK;
 	if (pud_large(pud))
 		return pa + (vaddr & ~PUD_MASK);
 
@@ -2067,7 +2068,7 @@
 						       sizeof(pmd)));
 	if (!pmd_present(pmd))
 		return 0;
-	pa = pmd_pfn(pmd) << PAGE_SHIFT;
+	pa = pmd_val(pmd) & PTE_PFN_MASK;
 	if (pmd_large(pmd))
 		return pa + (vaddr & ~PMD_MASK);
 
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 7ab2951..df8844a 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -393,6 +393,9 @@
 	unsigned long i = 0;
 	unsigned long n = end_pfn - start_pfn;
 
+	if (remap_pfn == 0)
+		remap_pfn = nr_pages;
+
 	while (i < n) {
 		unsigned long cur_pfn = start_pfn + i;
 		unsigned long left = n - i;
@@ -438,17 +441,29 @@
 	return remap_pfn;
 }
 
-static void __init xen_set_identity_and_remap(unsigned long nr_pages)
+static unsigned long __init xen_count_remap_pages(
+	unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages,
+	unsigned long remap_pages)
+{
+	if (start_pfn >= nr_pages)
+		return remap_pages;
+
+	return remap_pages + min(end_pfn, nr_pages) - start_pfn;
+}
+
+static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages,
+	unsigned long (*func)(unsigned long start_pfn, unsigned long end_pfn,
+			      unsigned long nr_pages, unsigned long last_val))
 {
 	phys_addr_t start = 0;
-	unsigned long last_pfn = nr_pages;
+	unsigned long ret_val = 0;
 	const struct e820entry *entry = xen_e820_map;
 	int i;
 
 	/*
 	 * Combine non-RAM regions and gaps until a RAM region (or the
-	 * end of the map) is reached, then set the 1:1 map and
-	 * remap the memory in those non-RAM regions.
+	 * end of the map) is reached, then call the provided function
+	 * to perform its duty on the non-RAM region.
 	 *
 	 * The combined non-RAM regions are rounded to a whole number
 	 * of pages so any partial pages are accessible via the 1:1
@@ -466,14 +481,13 @@
 				end_pfn = PFN_UP(entry->addr);
 
 			if (start_pfn < end_pfn)
-				last_pfn = xen_set_identity_and_remap_chunk(
-						start_pfn, end_pfn, nr_pages,
-						last_pfn);
+				ret_val = func(start_pfn, end_pfn, nr_pages,
+					       ret_val);
 			start = end;
 		}
 	}
 
-	pr_info("Released %ld page(s)\n", xen_released_pages);
+	return ret_val;
 }
 
 /*
@@ -596,35 +610,6 @@
 	}
 }
 
-static unsigned long __init xen_count_remap_pages(unsigned long max_pfn)
-{
-	unsigned long extra = 0;
-	unsigned long start_pfn, end_pfn;
-	const struct e820entry *entry = xen_e820_map;
-	int i;
-
-	end_pfn = 0;
-	for (i = 0; i < xen_e820_map_entries; i++, entry++) {
-		start_pfn = PFN_DOWN(entry->addr);
-		/* Adjacent regions on non-page boundaries handling! */
-		end_pfn = min(end_pfn, start_pfn);
-
-		if (start_pfn >= max_pfn)
-			return extra + max_pfn - end_pfn;
-
-		/* Add any holes in map to result. */
-		extra += start_pfn - end_pfn;
-
-		end_pfn = PFN_UP(entry->addr + entry->size);
-		end_pfn = min(end_pfn, max_pfn);
-
-		if (entry->type != E820_RAM)
-			extra += end_pfn - start_pfn;
-	}
-
-	return extra;
-}
-
 bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size)
 {
 	struct e820entry *entry;
@@ -728,10 +713,9 @@
 		size = PFN_PHYS(xen_start_info->nr_p2m_frames);
 	}
 
-	if (!xen_is_e820_reserved(start, size)) {
-		memblock_reserve(start, size);
+	memblock_reserve(start, size);
+	if (!xen_is_e820_reserved(start, size))
 		return;
-	}
 
 #ifdef CONFIG_X86_32
 	/*
@@ -742,6 +726,7 @@
 	BUG();
 #else
 	xen_relocate_p2m();
+	memblock_free(start, size);
 #endif
 }
 
@@ -804,7 +789,7 @@
 	max_pages = xen_get_max_pages();
 
 	/* How many extra pages do we need due to remapping? */
-	max_pages += xen_count_remap_pages(max_pfn);
+	max_pages += xen_foreach_remap_area(max_pfn, xen_count_remap_pages);
 
 	if (max_pages > max_pfn)
 		extra_pages += max_pages - max_pfn;
@@ -922,7 +907,9 @@
 	 * Set identity map on non-RAM pages and prepare remapping the
 	 * underlying RAM.
 	 */
-	xen_set_identity_and_remap(max_pfn);
+	xen_foreach_remap_area(max_pfn, xen_set_identity_and_remap_chunk);
+
+	pr_info("Released %ld page(s)\n", xen_released_pages);
 
 	return "Xen";
 }
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 9e2ba5c..f42e78d 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -27,6 +27,12 @@
 
 static void xen_qlock_kick(int cpu)
 {
+	int irq = per_cpu(lock_kicker_irq, cpu);
+
+	/* Don't kick if the target's kicker interrupt is not initialized. */
+	if (irq == -1)
+		return;
+
 	xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR);
 }
 
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index f1ba6a0..8846257 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -343,11 +343,11 @@
 	WARN_ON(!clockevent_state_oneshot(evt));
 
 	single.timeout_abs_ns = get_abs_timeout(delta);
-	single.flags = VCPU_SSHOTTMR_future;
+	/* Get an event anyway, even if the timeout is already expired */
+	single.flags = 0;
 
 	ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single);
-
-	BUG_ON(ret != 0 && ret != -ETIME);
+	BUG_ON(ret != 0);
 
 	return ret;
 }
diff --git a/arch/xtensa/include/asm/irq.h b/arch/xtensa/include/asm/irq.h
index f71f88e..19707db 100644
--- a/arch/xtensa/include/asm/irq.h
+++ b/arch/xtensa/include/asm/irq.h
@@ -29,7 +29,8 @@
 # define PLATFORM_NR_IRQS 0
 #endif
 #define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS
-#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS)
+#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS + 1)
+#define XTENSA_PIC_LINUX_IRQ(hwirq) ((hwirq) + 1)
 
 #if VARIANT_NR_IRQS == 0
 static inline void variant_init_irq(void) { }
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index 4ac3d23..4416944 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -34,11 +34,6 @@
 {
 	int irq = irq_find_mapping(NULL, hwirq);
 
-	if (hwirq >= NR_IRQS) {
-		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
-				__func__, hwirq);
-	}
-
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* Debugging check for stack overflow: is there less than 1KB free? */
 	{
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 9735691..49ccbd9 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -133,6 +133,8 @@
 
 __tagtable(BP_TAG_INITRD, parse_tag_initrd);
 
+#endif /* CONFIG_BLK_DEV_INITRD */
+
 #ifdef CONFIG_OF
 
 static int __init parse_tag_fdt(const bp_tag_t *tag)
@@ -145,8 +147,6 @@
 
 #endif /* CONFIG_OF */
 
-#endif /* CONFIG_BLK_DEV_INITRD */
-
 static int __init parse_tag_cmdline(const bp_tag_t* tag)
 {
 	strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE);
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c
index 83cf496..3aaaae1 100644
--- a/arch/xtensa/kernel/syscall.c
+++ b/arch/xtensa/kernel/syscall.c
@@ -87,7 +87,7 @@
 		/* At this point:  (!vmm || addr < vmm->vm_end). */
 		if (TASK_SIZE - len < addr)
 			return -ENOMEM;
-		if (!vmm || addr + len <= vmm->vm_start)
+		if (!vmm || addr + len <= vm_start_gap(vmm))
 			return addr;
 		addr = vmm->vm_end;
 		if (flags & MAP_SHARED)
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
index dbeea2b..1fda7e2 100644
--- a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
+++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
@@ -24,16 +24,18 @@
 
 /* Interrupt configuration. */
 
-#define PLATFORM_NR_IRQS	10
+#define PLATFORM_NR_IRQS	0
 
 /* Default assignment of LX60 devices to external interrupts. */
 
 #ifdef CONFIG_XTENSA_MX
 #define DUART16552_INTNUM	XCHAL_EXTINT3_NUM
 #define OETH_IRQ		XCHAL_EXTINT4_NUM
+#define C67X00_IRQ		XCHAL_EXTINT8_NUM
 #else
 #define DUART16552_INTNUM	XCHAL_EXTINT0_NUM
 #define OETH_IRQ		XCHAL_EXTINT1_NUM
+#define C67X00_IRQ		XCHAL_EXTINT5_NUM
 #endif
 
 /*
@@ -63,5 +65,5 @@
 
 #define C67X00_PADDR		(XCHAL_KIO_PADDR + 0x0D0D0000)
 #define C67X00_SIZE		0x10
-#define C67X00_IRQ		5
+
 #endif /* __XTENSA_XTAVNET_HARDWARE_H */
diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c
index e9f65f7..d1e9439 100644
--- a/arch/xtensa/platforms/xtfpga/setup.c
+++ b/arch/xtensa/platforms/xtfpga/setup.c
@@ -209,8 +209,8 @@
 		.flags = IORESOURCE_MEM,
 	},
 	[2] = { /* IRQ number */
-		.start = OETH_IRQ,
-		.end   = OETH_IRQ,
+		.start = XTENSA_PIC_LINUX_IRQ(OETH_IRQ),
+		.end   = XTENSA_PIC_LINUX_IRQ(OETH_IRQ),
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -246,8 +246,8 @@
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = { /* IRQ number */
-		.start = C67X00_IRQ,
-		.end   = C67X00_IRQ,
+		.start = XTENSA_PIC_LINUX_IRQ(C67X00_IRQ),
+		.end   = XTENSA_PIC_LINUX_IRQ(C67X00_IRQ),
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -280,7 +280,7 @@
 static struct plat_serial8250_port serial_platform_data[] = {
 	[0] = {
 		.mapbase	= DUART16552_PADDR,
-		.irq		= DUART16552_INTNUM,
+		.irq		= XTENSA_PIC_LINUX_IRQ(DUART16552_INTNUM),
 		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
 				  UPF_IOREMAP,
 		.iotype		= UPIO_MEM32,
diff --git a/block/bio.c b/block/bio.c
index d4d1443..14263fa 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -373,10 +373,14 @@
 	bio_list_init(&punt);
 	bio_list_init(&nopunt);
 
-	while ((bio = bio_list_pop(current->bio_list)))
+	while ((bio = bio_list_pop(&current->bio_list[0])))
 		bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio);
+	current->bio_list[0] = nopunt;
 
-	*current->bio_list = nopunt;
+	bio_list_init(&nopunt);
+	while ((bio = bio_list_pop(&current->bio_list[1])))
+		bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio);
+	current->bio_list[1] = nopunt;
 
 	spin_lock(&bs->rescue_lock);
 	bio_list_merge(&bs->rescue_list, &punt);
@@ -464,7 +468,9 @@
 		 * we retry with the original gfp_flags.
 		 */
 
-		if (current->bio_list && !bio_list_empty(current->bio_list))
+		if (current->bio_list &&
+		    (!bio_list_empty(&current->bio_list[0]) ||
+		     !bio_list_empty(&current->bio_list[1])))
 			gfp_mask &= ~__GFP_DIRECT_RECLAIM;
 
 		p = mempool_alloc(bs->bio_pool, gfp_mask);
@@ -584,6 +590,8 @@
 	bio->bi_rw = bio_src->bi_rw;
 	bio->bi_iter = bio_src->bi_iter;
 	bio->bi_io_vec = bio_src->bi_io_vec;
+
+	bio_clone_blkcg_association(bio, bio_src);
 }
 EXPORT_SYMBOL(__bio_clone_fast);
 
@@ -689,6 +697,8 @@
 		}
 	}
 
+	bio_clone_blkcg_association(bio, bio_src);
+
 	return bio;
 }
 EXPORT_SYMBOL(bio_clone_bioset);
@@ -2014,6 +2024,17 @@
 	}
 }
 
+/**
+ * bio_clone_blkcg_association - clone blkcg association from src to dst bio
+ * @dst: destination bio
+ * @src: source bio
+ */
+void bio_clone_blkcg_association(struct bio *dst, struct bio *src)
+{
+	if (src->bi_css)
+		WARN_ON(bio_associate_blkcg(dst, src->bi_css));
+}
+
 #endif /* CONFIG_BLK_CGROUP */
 
 static void __init biovec_init_slabs(void)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 5a37188..8161090 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -788,6 +788,7 @@
 {
 	struct gendisk *disk;
 	struct blkcg_gq *blkg;
+	struct module *owner;
 	unsigned int major, minor;
 	int key_len, part, ret;
 	char *body;
@@ -804,7 +805,9 @@
 	if (!disk)
 		return -ENODEV;
 	if (part) {
+		owner = disk->fops->owner;
 		put_disk(disk);
+		module_put(owner);
 		return -ENODEV;
 	}
 
@@ -820,7 +823,9 @@
 		ret = PTR_ERR(blkg);
 		rcu_read_unlock();
 		spin_unlock_irq(disk->queue->queue_lock);
+		owner = disk->fops->owner;
 		put_disk(disk);
+		module_put(owner);
 		/*
 		 * If queue was bypassing, we should retry.  Do so after a
 		 * short msleep().  It isn't strictly necessary but queue
@@ -851,9 +856,13 @@
 void blkg_conf_finish(struct blkg_conf_ctx *ctx)
 	__releases(ctx->disk->queue->queue_lock) __releases(rcu)
 {
+	struct module *owner;
+
 	spin_unlock_irq(ctx->disk->queue->queue_lock);
 	rcu_read_unlock();
+	owner = ctx->disk->fops->owner;
 	put_disk(ctx->disk);
+	module_put(owner);
 }
 EXPORT_SYMBOL_GPL(blkg_conf_finish);
 
@@ -1331,10 +1340,8 @@
 			struct blkcg_policy_data *cpd;
 
 			cpd = pol->cpd_alloc_fn(GFP_KERNEL);
-			if (!cpd) {
-				mutex_unlock(&blkcg_pol_mutex);
+			if (!cpd)
 				goto err_free_cpds;
-			}
 
 			blkcg->cpd[pol->plid] = cpd;
 			cpd->blkcg = blkcg;
diff --git a/block/blk-core.c b/block/blk-core.c
index f8e64ca..be43481 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -40,6 +40,8 @@
 #include "blk.h"
 #include "blk-mq.h"
 
+#include <linux/math64.h>
+
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
@@ -515,7 +517,9 @@
 
 void blk_set_queue_dying(struct request_queue *q)
 {
-	queue_flag_set_unlocked(QUEUE_FLAG_DYING, q);
+	spin_lock_irq(q->queue_lock);
+	queue_flag_set(QUEUE_FLAG_DYING, q);
+	spin_unlock_irq(q->queue_lock);
 
 	if (q->mq_ops)
 		blk_mq_wake_waiters(q);
@@ -2019,7 +2023,14 @@
  */
 blk_qc_t generic_make_request(struct bio *bio)
 {
-	struct bio_list bio_list_on_stack;
+	/*
+	 * bio_list_on_stack[0] contains bios submitted by the current
+	 * make_request_fn.
+	 * bio_list_on_stack[1] contains bios that were submitted before
+	 * the current make_request_fn, but that haven't been processed
+	 * yet.
+	 */
+	struct bio_list bio_list_on_stack[2];
 	blk_qc_t ret = BLK_QC_T_NONE;
 
 	if (!generic_make_request_checks(bio))
@@ -2036,7 +2047,7 @@
 	 * should be added at the tail
 	 */
 	if (current->bio_list) {
-		bio_list_add(current->bio_list, bio);
+		bio_list_add(&current->bio_list[0], bio);
 		goto out;
 	}
 
@@ -2055,24 +2066,39 @@
 	 * bio_list, and call into ->make_request() again.
 	 */
 	BUG_ON(bio->bi_next);
-	bio_list_init(&bio_list_on_stack);
-	current->bio_list = &bio_list_on_stack;
+	bio_list_init(&bio_list_on_stack[0]);
+	current->bio_list = bio_list_on_stack;
 	do {
 		struct request_queue *q = bdev_get_queue(bio->bi_bdev);
 
 		if (likely(blk_queue_enter(q, __GFP_DIRECT_RECLAIM) == 0)) {
+			struct bio_list lower, same;
+
+			/* Create a fresh bio_list for all subordinate requests */
+			bio_list_on_stack[1] = bio_list_on_stack[0];
+			bio_list_init(&bio_list_on_stack[0]);
 
 			ret = q->make_request_fn(q, bio);
 
 			blk_queue_exit(q);
-
-			bio = bio_list_pop(current->bio_list);
+			/* sort new bios into those for a lower level
+			 * and those for the same level
+			 */
+			bio_list_init(&lower);
+			bio_list_init(&same);
+			while ((bio = bio_list_pop(&bio_list_on_stack[0])) != NULL)
+				if (q == bdev_get_queue(bio->bi_bdev))
+					bio_list_add(&same, bio);
+				else
+					bio_list_add(&lower, bio);
+			/* now assemble so we handle the lowest level first */
+			bio_list_merge(&bio_list_on_stack[0], &lower);
+			bio_list_merge(&bio_list_on_stack[0], &same);
+			bio_list_merge(&bio_list_on_stack[0], &bio_list_on_stack[1]);
 		} else {
-			struct bio *bio_next = bio_list_pop(current->bio_list);
-
 			bio_io_error(bio);
-			bio = bio_next;
 		}
+		bio = bio_list_pop(&bio_list_on_stack[0]);
 	} while (bio);
 	current->bio_list = NULL; /* deactivate */
 
@@ -3539,3 +3565,85 @@
 
 	return 0;
 }
+
+/*
+ * Blk IO latency support. We want this to be as cheap as possible, so doing
+ * this lockless (and avoiding atomics), a few off by a few errors in this
+ * code is not harmful, and we don't want to do anything that is
+ * perf-impactful.
+ * TODO : If necessary, we can make the histograms per-cpu and aggregate
+ * them when printing them out.
+ */
+void
+blk_zero_latency_hist(struct io_latency_state *s)
+{
+	memset(s->latency_y_axis_read, 0,
+	       sizeof(s->latency_y_axis_read));
+	memset(s->latency_y_axis_write, 0,
+	       sizeof(s->latency_y_axis_write));
+	s->latency_reads_elems = 0;
+	s->latency_writes_elems = 0;
+}
+EXPORT_SYMBOL(blk_zero_latency_hist);
+
+ssize_t
+blk_latency_hist_show(struct io_latency_state *s, char *buf)
+{
+	int i;
+	int bytes_written = 0;
+	u_int64_t num_elem, elem;
+	int pct;
+
+	num_elem = s->latency_reads_elems;
+	if (num_elem > 0) {
+		bytes_written += scnprintf(buf + bytes_written,
+			   PAGE_SIZE - bytes_written,
+			   "IO svc_time Read Latency Histogram (n = %llu):\n",
+			   num_elem);
+		for (i = 0;
+		     i < ARRAY_SIZE(latency_x_axis_us);
+		     i++) {
+			elem = s->latency_y_axis_read[i];
+			pct = div64_u64(elem * 100, num_elem);
+			bytes_written += scnprintf(buf + bytes_written,
+						   PAGE_SIZE - bytes_written,
+						   "\t< %5lluus%15llu%15d%%\n",
+						   latency_x_axis_us[i],
+						   elem, pct);
+		}
+		/* Last element in y-axis table is overflow */
+		elem = s->latency_y_axis_read[i];
+		pct = div64_u64(elem * 100, num_elem);
+		bytes_written += scnprintf(buf + bytes_written,
+					   PAGE_SIZE - bytes_written,
+					   "\t> %5dms%15llu%15d%%\n", 10,
+					   elem, pct);
+	}
+	num_elem = s->latency_writes_elems;
+	if (num_elem > 0) {
+		bytes_written += scnprintf(buf + bytes_written,
+			   PAGE_SIZE - bytes_written,
+			   "IO svc_time Write Latency Histogram (n = %llu):\n",
+			   num_elem);
+		for (i = 0;
+		     i < ARRAY_SIZE(latency_x_axis_us);
+		     i++) {
+			elem = s->latency_y_axis_write[i];
+			pct = div64_u64(elem * 100, num_elem);
+			bytes_written += scnprintf(buf + bytes_written,
+						   PAGE_SIZE - bytes_written,
+						   "\t< %5lluus%15llu%15d%%\n",
+						   latency_x_axis_us[i],
+						   elem, pct);
+		}
+		/* Last element in y-axis table is overflow */
+		elem = s->latency_y_axis_write[i];
+		pct = div64_u64(elem * 100, num_elem);
+		bytes_written += scnprintf(buf + bytes_written,
+					   PAGE_SIZE - bytes_written,
+					   "\t> %5dms%15llu%15d%%\n", 10,
+					   elem, pct);
+	}
+	return bytes_written;
+}
+EXPORT_SYMBOL(blk_latency_hist_show);
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index d69c5c7..478f572 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -412,12 +412,13 @@
 
 	bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE |
 		template->flags;
-	bi->interval_exp = ilog2(queue_logical_block_size(disk->queue));
+	bi->interval_exp = template->interval_exp ? :
+		ilog2(queue_logical_block_size(disk->queue));
 	bi->profile = template->profile ? template->profile : &nop_profile;
 	bi->tuple_size = template->tuple_size;
 	bi->tag_size = template->tag_size;
 
-	blk_integrity_revalidate(disk);
+	disk->queue->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
 }
 EXPORT_SYMBOL(blk_integrity_register);
 
@@ -430,26 +431,11 @@
  */
 void blk_integrity_unregister(struct gendisk *disk)
 {
-	blk_integrity_revalidate(disk);
+	disk->queue->backing_dev_info.capabilities &= ~BDI_CAP_STABLE_WRITES;
 	memset(&disk->queue->integrity, 0, sizeof(struct blk_integrity));
 }
 EXPORT_SYMBOL(blk_integrity_unregister);
 
-void blk_integrity_revalidate(struct gendisk *disk)
-{
-	struct blk_integrity *bi = &disk->queue->integrity;
-
-	if (!(disk->flags & GENHD_FL_UP))
-		return;
-
-	if (bi->profile)
-		disk->queue->backing_dev_info.capabilities |=
-			BDI_CAP_STABLE_WRITES;
-	else
-		disk->queue->backing_dev_info.capabilities &=
-			~BDI_CAP_STABLE_WRITES;
-}
-
 void blk_integrity_add(struct gendisk *disk)
 {
 	if (kobject_init_and_add(&disk->integrity_kobj, &integrity_ktype,
diff --git a/block/blk-map.c b/block/blk-map.c
index f565e11..69953bd 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -90,6 +90,9 @@
 	if (!iter || !iter->count)
 		return -EINVAL;
 
+	if (!iter_is_iovec(iter))
+		return -EINVAL;
+
 	iov_for_each(iov, i, *iter) {
 		unsigned long uaddr = (unsigned long) iov.iov_base;
 
diff --git a/block/blk-merge.c b/block/blk-merge.c
index b966db8..7225511 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -92,9 +92,31 @@
 	bool do_split = true;
 	struct bio *new = NULL;
 	const unsigned max_sectors = get_max_io_size(q, bio);
+	unsigned bvecs = 0;
 
 	bio_for_each_segment(bv, bio, iter) {
 		/*
+		 * With arbitrary bio size, the incoming bio may be very
+		 * big. We have to split the bio into small bios so that
+		 * each holds at most BIO_MAX_PAGES bvecs because
+		 * bio_clone() can fail to allocate big bvecs.
+		 *
+		 * It should have been better to apply the limit per
+		 * request queue in which bio_clone() is involved,
+		 * instead of globally. The biggest blocker is the
+		 * bio_clone() in bio bounce.
+		 *
+		 * If bio is splitted by this reason, we should have
+		 * allowed to continue bios merging, but don't do
+		 * that now for making the change simple.
+		 *
+		 * TODO: deal with bio bounce's bio_clone() gracefully
+		 * and convert the global limit into per-queue limit.
+		 */
+		if (bvecs++ >= BIO_MAX_PAGES)
+			goto split;
+
+		/*
 		 * If the queue doesn't support SG gaps and adding this
 		 * offset would create a gap, disallow it.
 		 */
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 6d6f8fe..0d1af3e 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -601,8 +601,10 @@
 		 * If a request wasn't started before the queue was
 		 * marked dying, kill it here or it'll go unnoticed.
 		 */
-		if (unlikely(blk_queue_dying(rq->q)))
-			blk_mq_complete_request(rq, -EIO);
+		if (unlikely(blk_queue_dying(rq->q))) {
+			rq->errors = -EIO;
+			blk_mq_end_request(rq, rq->errors);
+		}
 		return;
 	}
 	if (rq->cmd_flags & REQ_NO_TIMEOUT)
@@ -778,7 +780,7 @@
 		switch (ret) {
 		case BLK_MQ_RQ_QUEUE_OK:
 			queued++;
-			continue;
+			break;
 		case BLK_MQ_RQ_QUEUE_BUSY:
 			list_add(&rq->queuelist, &rq_list);
 			__blk_mq_requeue_request(rq);
@@ -840,7 +842,7 @@
 		return WORK_CPU_UNBOUND;
 
 	if (--hctx->next_cpu_batch <= 0) {
-		int cpu = hctx->next_cpu, next_cpu;
+		int next_cpu;
 
 		next_cpu = cpumask_next(hctx->next_cpu, hctx->cpumask);
 		if (next_cpu >= nr_cpu_ids)
@@ -848,8 +850,6 @@
 
 		hctx->next_cpu = next_cpu;
 		hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH;
-
-		return cpu;
 	}
 
 	return hctx->next_cpu;
@@ -1259,12 +1259,9 @@
 
 	blk_queue_split(q, &bio, q->bio_split);
 
-	if (!is_flush_fua && !blk_queue_nomerges(q)) {
-		if (blk_attempt_plug_merge(q, bio, &request_count,
-					   &same_queue_rq))
-			return BLK_QC_T_NONE;
-	} else
-		request_count = blk_plug_queued_count(q);
+	if (!is_flush_fua && !blk_queue_nomerges(q) &&
+	    blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq))
+		return BLK_QC_T_NONE;
 
 	rq = blk_mq_map_request(q, bio, &data);
 	if (unlikely(!rq))
@@ -1311,9 +1308,9 @@
 		blk_mq_put_ctx(data.ctx);
 		if (!old_rq)
 			goto done;
-		if (!blk_mq_direct_issue_request(old_rq, &cookie))
-			goto done;
-		blk_mq_insert_request(old_rq, false, true, true);
+		if (test_bit(BLK_MQ_S_STOPPED, &data.hctx->state) ||
+		    blk_mq_direct_issue_request(old_rq, &cookie) != 0)
+			blk_mq_insert_request(old_rq, false, true, true);
 		goto done;
 	}
 
@@ -1355,9 +1352,11 @@
 
 	blk_queue_split(q, &bio, q->bio_split);
 
-	if (!is_flush_fua && !blk_queue_nomerges(q) &&
-	    blk_attempt_plug_merge(q, bio, &request_count, NULL))
-		return BLK_QC_T_NONE;
+	if (!is_flush_fua && !blk_queue_nomerges(q)) {
+		if (blk_attempt_plug_merge(q, bio, &request_count, NULL))
+			return BLK_QC_T_NONE;
+	} else
+		request_count = blk_plug_queued_count(q);
 
 	rq = blk_mq_map_request(q, bio, &data);
 	if (unlikely(!rq))
@@ -1471,7 +1470,7 @@
 	INIT_LIST_HEAD(&tags->page_list);
 
 	tags->rqs = kzalloc_node(set->queue_depth * sizeof(struct request *),
-				 GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+				 GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
 				 set->numa_node);
 	if (!tags->rqs) {
 		blk_mq_free_tags(tags);
@@ -1497,7 +1496,7 @@
 
 		do {
 			page = alloc_pages_node(set->numa_node,
-				GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
+				GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
 				this_order);
 			if (page)
 				break;
@@ -1518,7 +1517,7 @@
 		 * Allow kmemleak to scan these pages as they contain pointers
 		 * to additional allocations like via ops->init_request().
 		 */
-		kmemleak_alloc(p, order_to_size(this_order), 1, GFP_KERNEL);
+		kmemleak_alloc(p, order_to_size(this_order), 1, GFP_NOIO);
 		entries_per_page = order_to_size(this_order) / rq_size;
 		to_do = min(entries_per_page, set->queue_depth - i);
 		left -= to_do * rq_size;
diff --git a/block/bsg.c b/block/bsg.c
index d214e92..b9a5361 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -655,6 +655,9 @@
 
 	dprintk("%s: write %Zd bytes\n", bd->name, count);
 
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+		return -EINVAL;
+
 	bsg_set_block(bd, file);
 
 	bytes_written = 0;
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 1f9093e..e04a7b8 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1572,7 +1572,7 @@
 {
 	struct cfq_group_data *cgd;
 
-	cgd = kzalloc(sizeof(*cgd), GFP_KERNEL);
+	cgd = kzalloc(sizeof(*cgd), gfp);
 	if (!cgd)
 		return NULL;
 	return &cgd->cpd;
@@ -3003,7 +3003,6 @@
 	if (time_before(jiffies, rq->fifo_time))
 		rq = NULL;
 
-	cfq_log_cfqq(cfqq->cfqd, cfqq, "fifo=%p", rq);
 	return rq;
 }
 
@@ -3377,6 +3376,9 @@
 {
 	unsigned int max_dispatch;
 
+	if (cfq_cfqq_must_dispatch(cfqq))
+		return true;
+
 	/*
 	 * Drain async requests before we start sync IO
 	 */
@@ -3468,15 +3470,20 @@
 
 	BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
 
+	rq = cfq_check_fifo(cfqq);
+	if (rq)
+		cfq_mark_cfqq_must_dispatch(cfqq);
+
 	if (!cfq_may_dispatch(cfqd, cfqq))
 		return false;
 
 	/*
 	 * follow expired path, else get first next available
 	 */
-	rq = cfq_check_fifo(cfqq);
 	if (!rq)
 		rq = cfqq->next_rq;
+	else
+		cfq_log_cfqq(cfqq->cfqd, cfqq, "fifo=%p", rq);
 
 	/*
 	 * insert request into driver dispatch list
@@ -3944,7 +3951,7 @@
 	 * if the new request is sync, but the currently running queue is
 	 * not, let the sync request have priority.
 	 */
-	if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq))
+	if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq) && !cfq_cfqq_must_dispatch(cfqq))
 		return true;
 
 	if (new_cfqq->cfqg != cfqq->cfqg)
diff --git a/block/genhd.c b/block/genhd.c
index e5cafa5..a87e776 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -612,7 +612,7 @@
 
 	/* Register BDI before referencing it from bdev */
 	bdi = &disk->queue->backing_dev_info;
-	bdi_register_dev(bdi, disk_devt(disk));
+	bdi_register_owner(bdi, disk_to_dev(disk));
 
 	blk_register_region(disk_devt(disk), disk->minors, NULL,
 			    exact_match, exact_lock, disk);
@@ -664,7 +664,6 @@
 
 	kobject_put(disk->part0.holder_dir);
 	kobject_put(disk->slave_dir);
-	disk->driverfs_dev = NULL;
 	if (!sysfs_deprecated)
 		sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
 	pm_runtime_set_memalloc_noio(disk_to_dev(disk), false);
@@ -831,6 +830,7 @@
 	if (iter) {
 		class_dev_iter_exit(iter);
 		kfree(iter);
+		seqf->private = NULL;
 	}
 }
 
@@ -1117,6 +1117,22 @@
 		blk_put_queue(disk->queue);
 	kfree(disk);
 }
+
+static int disk_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+	struct disk_part_iter piter;
+	struct hd_struct *part;
+	int cnt = 0;
+
+	disk_part_iter_init(&piter, disk, 0);
+	while((part = disk_part_iter_next(&piter)))
+		cnt++;
+	disk_part_iter_exit(&piter);
+	add_uevent_var(env, "NPARTS=%u", cnt);
+	return 0;
+}
+
 struct class block_class = {
 	.name		= "block",
 };
@@ -1136,6 +1152,7 @@
 	.groups		= disk_attr_groups,
 	.release	= disk_release,
 	.devnode	= block_devnode,
+	.uevent		= disk_uevent,
 };
 
 #ifdef CONFIG_PROC_FS
diff --git a/block/ioprio.c b/block/ioprio.c
index cc7800e..01b8116 100644
--- a/block/ioprio.c
+++ b/block/ioprio.c
@@ -150,8 +150,10 @@
 	if (ret)
 		goto out;
 	ret = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, IOPRIO_NORM);
+	task_lock(p);
 	if (p->io_context)
 		ret = p->io_context->ioprio;
+	task_unlock(p);
 out:
 	return ret;
 }
diff --git a/block/partition-generic.c b/block/partition-generic.c
index 91327db..19cf33b 100644
--- a/block/partition-generic.c
+++ b/block/partition-generic.c
@@ -446,7 +446,6 @@
 
 	if (disk->fops->revalidate_disk)
 		disk->fops->revalidate_disk(disk);
-	blk_integrity_revalidate(disk);
 	check_disk_size_change(disk, bdev);
 	bdev->bd_invalidated = 0;
 	if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
diff --git a/block/partitions/msdos.c b/block/partitions/msdos.c
index 93e7c1b..5610cd5 100644
--- a/block/partitions/msdos.c
+++ b/block/partitions/msdos.c
@@ -300,6 +300,8 @@
 			continue;
 		bsd_start = le32_to_cpu(p->p_offset);
 		bsd_size = le32_to_cpu(p->p_size);
+		if (memcmp(flavour, "bsd\0", 4) == 0)
+			bsd_start += offset;
 		if (offset == bsd_start && size == bsd_size)
 			/* full parent partition, we have it already */
 			continue;
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 0774799..c6fee74 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -182,6 +182,9 @@
 	__set_bit(WRITE_16, filter->write_ok);
 	__set_bit(WRITE_LONG, filter->write_ok);
 	__set_bit(WRITE_LONG_2, filter->write_ok);
+	__set_bit(WRITE_SAME, filter->write_ok);
+	__set_bit(WRITE_SAME_16, filter->write_ok);
+	__set_bit(WRITE_SAME_32, filter->write_ok);
 	__set_bit(ERASE, filter->write_ok);
 	__set_bit(GPCMD_MODE_SELECT_10, filter->write_ok);
 	__set_bit(MODE_SELECT, filter->write_ok);
diff --git a/build.config.goldfish.arm b/build.config.goldfish.arm
new file mode 100644
index 0000000..866da93
--- /dev/null
+++ b/build.config.goldfish.arm
@@ -0,0 +1,12 @@
+ARCH=arm
+BRANCH=android-4.4
+CROSS_COMPILE=arm-linux-androidkernel-
+DEFCONFIG=ranchu_defconfig
+EXTRA_CMDS=''
+KERNEL_DIR=common
+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin
+FILES="
+arch/arm/boot/zImage
+vmlinux
+System.map
+"
diff --git a/build.config.goldfish.arm64 b/build.config.goldfish.arm64
new file mode 100644
index 0000000..9c963cf
--- /dev/null
+++ b/build.config.goldfish.arm64
@@ -0,0 +1,12 @@
+ARCH=arm64
+BRANCH=android-4.4
+CROSS_COMPILE=aarch64-linux-android-
+DEFCONFIG=ranchu64_defconfig
+EXTRA_CMDS=''
+KERNEL_DIR=common
+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin
+FILES="
+arch/arm64/boot/Image
+vmlinux
+System.map
+"
diff --git a/build.config.goldfish.mips b/build.config.goldfish.mips
new file mode 100644
index 0000000..8af53d2
--- /dev/null
+++ b/build.config.goldfish.mips
@@ -0,0 +1,11 @@
+ARCH=mips
+BRANCH=android-4.4
+CROSS_COMPILE=mips64el-linux-android-
+DEFCONFIG=ranchu_defconfig
+EXTRA_CMDS=''
+KERNEL_DIR=common
+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/mips/mips64el-linux-android-4.9/bin
+FILES="
+vmlinux
+System.map
+"
diff --git a/build.config.goldfish.mips64 b/build.config.goldfish.mips64
new file mode 100644
index 0000000..2a33d36
--- /dev/null
+++ b/build.config.goldfish.mips64
@@ -0,0 +1,11 @@
+ARCH=mips
+BRANCH=android-4.4
+CROSS_COMPILE=mips64el-linux-android-
+DEFCONFIG=ranchu64_defconfig
+EXTRA_CMDS=''
+KERNEL_DIR=common
+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/mips/mips64el-linux-android-4.9/bin
+FILES="
+vmlinux
+System.map
+"
diff --git a/build.config.goldfish.x86 b/build.config.goldfish.x86
new file mode 100644
index 0000000..f86253f
--- /dev/null
+++ b/build.config.goldfish.x86
@@ -0,0 +1,12 @@
+ARCH=x86
+BRANCH=android-4.4
+CROSS_COMPILE=x86_64-linux-android-
+DEFCONFIG=i386_ranchu_defconfig
+EXTRA_CMDS=''
+KERNEL_DIR=common
+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin
+FILES="
+arch/x86/boot/bzImage
+vmlinux
+System.map
+"
diff --git a/build.config.goldfish.x86_64 b/build.config.goldfish.x86_64
new file mode 100644
index 0000000..e173886
--- /dev/null
+++ b/build.config.goldfish.x86_64
@@ -0,0 +1,12 @@
+ARCH=x86_64
+BRANCH=android-4.4
+CROSS_COMPILE=x86_64-linux-android-
+DEFCONFIG=x86_64_ranchu_defconfig
+EXTRA_CMDS=''
+KERNEL_DIR=common
+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin
+FILES="
+arch/x86/boot/bzImage
+vmlinux
+System.map
+"
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 7240821..3240d39 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -289,6 +289,24 @@
 	  CBC: Cipher Block Chaining mode
 	  This block cipher algorithm is required for IPSec.
 
+config CRYPTO_HEH
+	tristate "HEH support"
+	select CRYPTO_CMAC
+	select CRYPTO_ECB
+	select CRYPTO_GF128MUL
+	select CRYPTO_MANAGER
+	select CRYPTO_POLY_HASH_ARM64_CE if ARM64 && KERNEL_MODE_NEON
+	help
+	  HEH: Hash-Encrypt-Hash mode
+	  HEH is a proposed block cipher mode of operation which extends the
+	  strong pseudo-random permutation (SPRP) property of block ciphers to
+	  arbitrary-length input strings.  This provides a stronger notion of
+	  security than existing block cipher modes of operation (e.g. CBC, CTR,
+	  XTS), though it is usually less performant.  Applications include disk
+	  encryption and encryption of file names and contents.  Currently, this
+	  implementation only provides a symmetric cipher interface, so it can't
+	  yet be used as an AEAD.
+
 config CRYPTO_CTR
 	tristate "CTR support"
 	select CRYPTO_BLKCIPHER
diff --git a/crypto/Makefile b/crypto/Makefile
index f7aba92..8507d1f 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -33,6 +33,7 @@
 
 $(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
 $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
+$(obj)/rsa_helper.o: $(obj)/rsapubkey-asn1.h $(obj)/rsaprivkey-asn1.h
 clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
 clean-files += rsaprivkey-asn1.c rsaprivkey-asn1.h
 
@@ -61,10 +62,12 @@
 obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o
 obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o
 obj-$(CONFIG_CRYPTO_WP512) += wp512.o
+CFLAGS_wp512.o := $(call cc-option,-fno-schedule-insns)  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149
 obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
 obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+obj-$(CONFIG_CRYPTO_HEH) += heh.o
 obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
 obj-$(CONFIG_CRYPTO_CTS) += cts.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
@@ -84,6 +87,7 @@
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o
 obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent_generic.o
+CFLAGS_serpent_generic.o := $(call cc-option,-fsched-pressure)  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149
 obj-$(CONFIG_CRYPTO_AES) += aes_generic.o
 obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o
 obj-$(CONFIG_CRYPTO_CAST_COMMON) += cast_common.o
diff --git a/crypto/ahash.c b/crypto/ahash.c
index d19b523..f9caf0f 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -31,6 +31,7 @@
 	crypto_completion_t complete;
 	void *data;
 	u8 *result;
+	u32 flags;
 	void *ubuf[] CRYPTO_MINALIGN_ATTR;
 };
 
@@ -69,8 +70,9 @@
 	struct scatterlist *sg;
 
 	sg = walk->sg;
-	walk->pg = sg_page(sg);
 	walk->offset = sg->offset;
+	walk->pg = sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
+	walk->offset = offset_in_page(walk->offset);
 	walk->entrylen = sg->length;
 
 	if (walk->entrylen > walk->total)
@@ -269,6 +271,8 @@
 	priv->result = req->result;
 	priv->complete = req->base.complete;
 	priv->data = req->base.data;
+	priv->flags = req->base.flags;
+
 	/*
 	 * WARNING: We do not backup req->priv here! The req->priv
 	 *          is for internal use of the Crypto API and the
@@ -283,38 +287,44 @@
 	return 0;
 }
 
-static void ahash_restore_req(struct ahash_request *req)
+static void ahash_restore_req(struct ahash_request *req, int err)
 {
 	struct ahash_request_priv *priv = req->priv;
 
+	if (!err)
+		memcpy(priv->result, req->result,
+		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
+
 	/* Restore the original crypto request. */
 	req->result = priv->result;
-	req->base.complete = priv->complete;
-	req->base.data = priv->data;
+
+	ahash_request_set_callback(req, priv->flags,
+				   priv->complete, priv->data);
 	req->priv = NULL;
 
 	/* Free the req->priv.priv from the ADJUSTED request. */
 	kzfree(priv);
 }
 
-static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
+static void ahash_notify_einprogress(struct ahash_request *req)
 {
 	struct ahash_request_priv *priv = req->priv;
+	struct crypto_async_request oreq;
 
-	if (err == -EINPROGRESS)
-		return;
+	oreq.data = priv->data;
 
-	if (!err)
-		memcpy(priv->result, req->result,
-		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
-
-	ahash_restore_req(req);
+	priv->complete(&oreq, -EINPROGRESS);
 }
 
 static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
 {
 	struct ahash_request *areq = req->data;
 
+	if (err == -EINPROGRESS) {
+		ahash_notify_einprogress(areq);
+		return;
+	}
+
 	/*
 	 * Restore the original request, see ahash_op_unaligned() for what
 	 * goes where.
@@ -325,7 +335,7 @@
 	 */
 
 	/* First copy req->result into req->priv.result */
-	ahash_op_unaligned_finish(areq, err);
+	ahash_restore_req(areq, err);
 
 	/* Complete the ORIGINAL request. */
 	areq->base.complete(&areq->base, err);
@@ -341,7 +351,12 @@
 		return err;
 
 	err = op(req);
-	ahash_op_unaligned_finish(req, err);
+	if (err == -EINPROGRESS ||
+	    (err == -EBUSY && (ahash_request_flags(req) &
+			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
+		return err;
+
+	ahash_restore_req(req, err);
 
 	return err;
 }
@@ -376,25 +391,14 @@
 }
 EXPORT_SYMBOL_GPL(crypto_ahash_digest);
 
-static void ahash_def_finup_finish2(struct ahash_request *req, int err)
-{
-	struct ahash_request_priv *priv = req->priv;
-
-	if (err == -EINPROGRESS)
-		return;
-
-	if (!err)
-		memcpy(priv->result, req->result,
-		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
-
-	ahash_restore_req(req);
-}
-
 static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
 {
 	struct ahash_request *areq = req->data;
 
-	ahash_def_finup_finish2(areq, err);
+	if (err == -EINPROGRESS)
+		return;
+
+	ahash_restore_req(areq, err);
 
 	areq->base.complete(&areq->base, err);
 }
@@ -405,11 +409,15 @@
 		goto out;
 
 	req->base.complete = ahash_def_finup_done2;
-	req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
 	err = crypto_ahash_reqtfm(req)->final(req);
+	if (err == -EINPROGRESS ||
+	    (err == -EBUSY && (ahash_request_flags(req) &
+			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
+		return err;
 
 out:
-	ahash_def_finup_finish2(req, err);
+	ahash_restore_req(req, err);
 	return err;
 }
 
@@ -417,7 +425,16 @@
 {
 	struct ahash_request *areq = req->data;
 
+	if (err == -EINPROGRESS) {
+		ahash_notify_einprogress(areq);
+		return;
+	}
+
+	areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
 	err = ahash_def_finup_finish1(areq, err);
+	if (areq->priv)
+		return;
 
 	areq->base.complete(&areq->base, err);
 }
@@ -432,6 +449,11 @@
 		return err;
 
 	err = tfm->update(req);
+	if (err == -EINPROGRESS ||
+	    (err == -EBUSY && (ahash_request_flags(req) &
+			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
+		return err;
+
 	return ahash_def_finup_finish1(req, err);
 }
 
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 59bf491..43f5bdb 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -357,6 +357,7 @@
 	struct crypto_larval *larval;
 	int err;
 
+	alg->cra_flags &= ~CRYPTO_ALG_DEAD;
 	err = crypto_check_alg(alg);
 	if (err)
 		return err;
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 6d4d456..faea9d72 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -29,6 +29,11 @@
 	struct scatterlist sg[ALG_MAX_PAGES];
 };
 
+struct aead_tfm {
+	struct crypto_aead *aead;
+	bool has_key;
+};
+
 struct aead_ctx {
 	struct aead_sg_list tsgl;
 	/*
@@ -513,24 +518,146 @@
 	.poll		=	aead_poll,
 };
 
+static int aead_check_key(struct socket *sock)
+{
+	int err = 0;
+	struct sock *psk;
+	struct alg_sock *pask;
+	struct aead_tfm *tfm;
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+
+	lock_sock(sk);
+	if (ask->refcnt)
+		goto unlock_child;
+
+	psk = ask->parent;
+	pask = alg_sk(ask->parent);
+	tfm = pask->private;
+
+	err = -ENOKEY;
+	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
+	if (!tfm->has_key)
+		goto unlock;
+
+	if (!pask->refcnt++)
+		sock_hold(psk);
+
+	ask->refcnt = 1;
+	sock_put(psk);
+
+	err = 0;
+
+unlock:
+	release_sock(psk);
+unlock_child:
+	release_sock(sk);
+
+	return err;
+}
+
+static int aead_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t size)
+{
+	int err;
+
+	err = aead_check_key(sock);
+	if (err)
+		return err;
+
+	return aead_sendmsg(sock, msg, size);
+}
+
+static ssize_t aead_sendpage_nokey(struct socket *sock, struct page *page,
+				       int offset, size_t size, int flags)
+{
+	int err;
+
+	err = aead_check_key(sock);
+	if (err)
+		return err;
+
+	return aead_sendpage(sock, page, offset, size, flags);
+}
+
+static int aead_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t ignored, int flags)
+{
+	int err;
+
+	err = aead_check_key(sock);
+	if (err)
+		return err;
+
+	return aead_recvmsg(sock, msg, ignored, flags);
+}
+
+static struct proto_ops algif_aead_ops_nokey = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.accept		=	sock_no_accept,
+	.setsockopt	=	sock_no_setsockopt,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	aead_sendmsg_nokey,
+	.sendpage	=	aead_sendpage_nokey,
+	.recvmsg	=	aead_recvmsg_nokey,
+	.poll		=	aead_poll,
+};
+
 static void *aead_bind(const char *name, u32 type, u32 mask)
 {
-	return crypto_alloc_aead(name, type, mask);
+	struct aead_tfm *tfm;
+	struct crypto_aead *aead;
+
+	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+	if (!tfm)
+		return ERR_PTR(-ENOMEM);
+
+	aead = crypto_alloc_aead(name, type, mask);
+	if (IS_ERR(aead)) {
+		kfree(tfm);
+		return ERR_CAST(aead);
+	}
+
+	tfm->aead = aead;
+
+	return tfm;
 }
 
 static void aead_release(void *private)
 {
-	crypto_free_aead(private);
+	struct aead_tfm *tfm = private;
+
+	crypto_free_aead(tfm->aead);
+	kfree(tfm);
 }
 
 static int aead_setauthsize(void *private, unsigned int authsize)
 {
-	return crypto_aead_setauthsize(private, authsize);
+	struct aead_tfm *tfm = private;
+
+	return crypto_aead_setauthsize(tfm->aead, authsize);
 }
 
 static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
 {
-	return crypto_aead_setkey(private, key, keylen);
+	struct aead_tfm *tfm = private;
+	int err;
+
+	err = crypto_aead_setkey(tfm->aead, key, keylen);
+	tfm->has_key = !err;
+
+	return err;
 }
 
 static void aead_sock_destruct(struct sock *sk)
@@ -546,12 +673,14 @@
 	af_alg_release_parent(sk);
 }
 
-static int aead_accept_parent(void *private, struct sock *sk)
+static int aead_accept_parent_nokey(void *private, struct sock *sk)
 {
 	struct aead_ctx *ctx;
 	struct alg_sock *ask = alg_sk(sk);
-	unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(private);
-	unsigned int ivlen = crypto_aead_ivsize(private);
+	struct aead_tfm *tfm = private;
+	struct crypto_aead *aead = tfm->aead;
+	unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(aead);
+	unsigned int ivlen = crypto_aead_ivsize(aead);
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
@@ -577,7 +706,7 @@
 
 	ask->private = ctx;
 
-	aead_request_set_tfm(&ctx->aead_req, private);
+	aead_request_set_tfm(&ctx->aead_req, aead);
 	aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				  af_alg_complete, &ctx->completion);
 
@@ -586,13 +715,25 @@
 	return 0;
 }
 
+static int aead_accept_parent(void *private, struct sock *sk)
+{
+	struct aead_tfm *tfm = private;
+
+	if (!tfm->has_key)
+		return -ENOKEY;
+
+	return aead_accept_parent_nokey(private, sk);
+}
+
 static const struct af_alg_type algif_type_aead = {
 	.bind		=	aead_bind,
 	.release	=	aead_release,
 	.setkey		=	aead_setkey,
 	.setauthsize	=	aead_setauthsize,
 	.accept		=	aead_accept_parent,
+	.accept_nokey	=	aead_accept_parent_nokey,
 	.ops		=	&algif_aead_ops,
+	.ops_nokey	=	&algif_aead_ops_nokey,
 	.name		=	"aead",
 	.owner		=	THIS_MODULE
 };
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index 68a5cea..8d8b3ee 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -184,7 +184,7 @@
 	struct alg_sock *ask = alg_sk(sk);
 	struct hash_ctx *ctx = ask->private;
 	struct ahash_request *req = &ctx->req;
-	char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req))];
+	char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req)) ? : 1];
 	struct sock *sk2;
 	struct alg_sock *ask2;
 	struct hash_ctx *ctx2;
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 4870f28..05bfe56 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -14,6 +14,7 @@
 	select MPILIB
 	select PUBLIC_KEY_ALGO_RSA
 	select CRYPTO_HASH_INFO
+	select CRYPTO_AKCIPHER
 	help
 	  This option provides support for asymmetric public key type handling.
 	  If signature generation and/or verification are to be used,
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 758acab..8f3056c 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -547,9 +547,7 @@
 	struct pkcs7_signed_info *sinfo = ctx->sinfo;
 
 	if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) ||
-	    !test_bit(sinfo_has_message_digest, &sinfo->aa_set) ||
-	    (ctx->msg->data_type == OID_msIndirectData &&
-	     !test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))) {
+	    !test_bit(sinfo_has_message_digest, &sinfo->aa_set)) {
 		pr_warn("Missing required AuthAttr\n");
 		return -EBADMSG;
 	}
diff --git a/crypto/async_tx/async_pq.c b/crypto/async_tx/async_pq.c
index c0748bb..84f8d4d 100644
--- a/crypto/async_tx/async_pq.c
+++ b/crypto/async_tx/async_pq.c
@@ -368,8 +368,6 @@
 
 		dma_set_unmap(tx, unmap);
 		async_tx_submit(chan, tx, submit);
-
-		return tx;
 	} else {
 		struct page *p_src = P(blocks, disks);
 		struct page *q_src = Q(blocks, disks);
@@ -424,9 +422,11 @@
 		submit->cb_param = cb_param_orig;
 		submit->flags = flags_orig;
 		async_tx_sync_epilog(submit);
-
-		return NULL;
+		tx = NULL;
 	}
+	dmaengine_unmap_put(unmap);
+
+	return tx;
 }
 EXPORT_SYMBOL_GPL(async_syndrome_val);
 
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 8cc1622..7bbfadc 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -234,6 +234,8 @@
 		return blkcipher_walk_done(desc, walk, -EINVAL);
 	}
 
+	bsize = min(walk->walk_blocksize, n);
+
 	walk->flags &= ~(BLKCIPHER_WALK_SLOW | BLKCIPHER_WALK_COPY |
 			 BLKCIPHER_WALK_DIFF);
 	if (!scatterwalk_aligned(&walk->in, walk->alignmask) ||
@@ -246,7 +248,6 @@
 		}
 	}
 
-	bsize = min(walk->walk_blocksize, n);
 	n = scatterwalk_clamp(&walk->in, n);
 	n = scatterwalk_clamp(&walk->out, n);
 
@@ -372,6 +373,27 @@
 }
 EXPORT_SYMBOL_GPL(blkcipher_aead_walk_virt_block);
 
+/*
+ * This function allows ablkcipher algorithms to use the blkcipher_walk API to
+ * walk over their data.  The specified crypto_ablkcipher tfm is used to
+ * initialize the struct blkcipher_walk, and the crypto_blkcipher specified in
+ * desc->tfm is never used so it can be left NULL.  (Yes, this design is ugly,
+ * but it parallels blkcipher_aead_walk_virt_block() above.  In the 4.10 kernel
+ * this is starting to be cleaned up...)
+ */
+int blkcipher_ablkcipher_walk_virt(struct blkcipher_desc *desc,
+				   struct blkcipher_walk *walk,
+				   struct crypto_ablkcipher *tfm)
+{
+	walk->flags &= ~BLKCIPHER_WALK_PHYS;
+	walk->walk_blocksize = crypto_ablkcipher_blocksize(tfm);
+	walk->cipher_blocksize = walk->walk_blocksize;
+	walk->ivsize = crypto_ablkcipher_ivsize(tfm);
+	walk->alignmask = crypto_ablkcipher_alignmask(tfm);
+	return blkcipher_walk_first(desc, walk);
+}
+EXPORT_SYMBOL_GPL(blkcipher_ablkcipher_walk_virt);
+
 static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,
 			    unsigned int keylen)
 {
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index c81861b..26a504d 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -594,9 +594,14 @@
 
 static int cryptd_hash_import(struct ahash_request *req, const void *in)
 {
-	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+	struct shash_desc *desc = cryptd_shash_desc(req);
 
-	return crypto_shash_import(&rctx->desc, in);
+	desc->tfm = ctx->child;
+	desc->flags = req->base.flags;
+
+	return crypto_shash_import(desc, in);
 }
 
 static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
@@ -637,6 +642,7 @@
 	inst->alg.halg.base.cra_flags = type;
 
 	inst->alg.halg.digestsize = salg->digestsize;
+	inst->alg.halg.statesize = salg->statesize;
 	inst->alg.halg.base.cra_ctxsize = sizeof(struct cryptd_hash_ctx);
 
 	inst->alg.halg.base.cra_init = cryptd_hash_init_tfm;
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 43fe85f..7097a33 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -455,6 +455,7 @@
 	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
 	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
 	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
 	[CRYPTO_MSG_DELRNG	- CRYPTO_MSG_BASE] = 0,
 };
 
diff --git a/crypto/echainiv.c b/crypto/echainiv.c
index b96a8456..343a74e 100644
--- a/crypto/echainiv.c
+++ b/crypto/echainiv.c
@@ -1,8 +1,8 @@
 /*
  * echainiv: Encrypted Chain IV Generator
  *
- * This generator generates an IV based on a sequence number by xoring it
- * with a salt and then encrypting it with the same key as used to encrypt
+ * This generator generates an IV based on a sequence number by multiplying
+ * it with a salt and then encrypting it with the same key as used to encrypt
  * the plain text.  This algorithm requires that the block size be equal
  * to the IV size.  It is mainly useful for CBC.
  *
@@ -23,81 +23,17 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/percpu.h>
-#include <linux/spinlock.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 
-#define MAX_IV_SIZE 16
-
-static DEFINE_PER_CPU(u32 [MAX_IV_SIZE / sizeof(u32)], echainiv_iv);
-
-/* We don't care if we get preempted and read/write IVs from the next CPU. */
-static void echainiv_read_iv(u8 *dst, unsigned size)
-{
-	u32 *a = (u32 *)dst;
-	u32 __percpu *b = echainiv_iv;
-
-	for (; size >= 4; size -= 4) {
-		*a++ = this_cpu_read(*b);
-		b++;
-	}
-}
-
-static void echainiv_write_iv(const u8 *src, unsigned size)
-{
-	const u32 *a = (const u32 *)src;
-	u32 __percpu *b = echainiv_iv;
-
-	for (; size >= 4; size -= 4) {
-		this_cpu_write(*b, *a);
-		a++;
-		b++;
-	}
-}
-
-static void echainiv_encrypt_complete2(struct aead_request *req, int err)
-{
-	struct aead_request *subreq = aead_request_ctx(req);
-	struct crypto_aead *geniv;
-	unsigned int ivsize;
-
-	if (err == -EINPROGRESS)
-		return;
-
-	if (err)
-		goto out;
-
-	geniv = crypto_aead_reqtfm(req);
-	ivsize = crypto_aead_ivsize(geniv);
-
-	echainiv_write_iv(subreq->iv, ivsize);
-
-	if (req->iv != subreq->iv)
-		memcpy(req->iv, subreq->iv, ivsize);
-
-out:
-	if (req->iv != subreq->iv)
-		kzfree(subreq->iv);
-}
-
-static void echainiv_encrypt_complete(struct crypto_async_request *base,
-					 int err)
-{
-	struct aead_request *req = base->data;
-
-	echainiv_encrypt_complete2(req, err);
-	aead_request_complete(req, err);
-}
-
 static int echainiv_encrypt(struct aead_request *req)
 {
 	struct crypto_aead *geniv = crypto_aead_reqtfm(req);
 	struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
 	struct aead_request *subreq = aead_request_ctx(req);
-	crypto_completion_t compl;
-	void *data;
+	__be64 nseqno;
+	u64 seqno;
 	u8 *info;
 	unsigned int ivsize = crypto_aead_ivsize(geniv);
 	int err;
@@ -107,8 +43,6 @@
 
 	aead_request_set_tfm(subreq, ctx->child);
 
-	compl = echainiv_encrypt_complete;
-	data = req;
 	info = req->iv;
 
 	if (req->src != req->dst) {
@@ -123,29 +57,30 @@
 			return err;
 	}
 
-	if (unlikely(!IS_ALIGNED((unsigned long)info,
-				 crypto_aead_alignmask(geniv) + 1))) {
-		info = kmalloc(ivsize, req->base.flags &
-				       CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
-								  GFP_ATOMIC);
-		if (!info)
-			return -ENOMEM;
-
-		memcpy(info, req->iv, ivsize);
-	}
-
-	aead_request_set_callback(subreq, req->base.flags, compl, data);
+	aead_request_set_callback(subreq, req->base.flags,
+				  req->base.complete, req->base.data);
 	aead_request_set_crypt(subreq, req->dst, req->dst,
 			       req->cryptlen, info);
 	aead_request_set_ad(subreq, req->assoclen);
 
-	crypto_xor(info, ctx->salt, ivsize);
-	scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
-	echainiv_read_iv(info, ivsize);
+	memcpy(&nseqno, info + ivsize - 8, 8);
+	seqno = be64_to_cpu(nseqno);
+	memset(info, 0, ivsize);
 
-	err = crypto_aead_encrypt(subreq);
-	echainiv_encrypt_complete2(req, err);
-	return err;
+	scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
+
+	do {
+		u64 a;
+
+		memcpy(&a, ctx->salt + ivsize - 8, 8);
+
+		a |= 1;
+		a *= seqno;
+
+		memcpy(info + ivsize - 8, &a, 8);
+	} while ((ivsize -= 8));
+
+	return crypto_aead_encrypt(subreq);
 }
 
 static int echainiv_decrypt(struct aead_request *req)
@@ -192,8 +127,7 @@
 	alg = crypto_spawn_aead_alg(spawn);
 
 	err = -EINVAL;
-	if (inst->alg.ivsize & (sizeof(u32) - 1) ||
-	    inst->alg.ivsize > MAX_IV_SIZE)
+	if (inst->alg.ivsize & (sizeof(u64) - 1) || !inst->alg.ivsize)
 		goto free_inst;
 
 	inst->alg.encrypt = echainiv_encrypt;
@@ -202,7 +136,6 @@
 	inst->alg.init = aead_init_geniv;
 	inst->alg.exit = aead_exit_geniv;
 
-	inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
 	inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx);
 	inst->alg.base.cra_ctxsize += inst->alg.ivsize;
 
diff --git a/crypto/gcm.c b/crypto/gcm.c
index bec329b..0a12c09 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -117,7 +117,7 @@
 	struct crypto_ablkcipher *ctr = ctx->ctr;
 	struct {
 		be128 hash;
-		u8 iv[8];
+		u8 iv[16];
 
 		struct crypto_gcm_setkey_result result;
 
@@ -152,10 +152,8 @@
 
 	err = crypto_ablkcipher_encrypt(&data->req);
 	if (err == -EINPROGRESS || err == -EBUSY) {
-		err = wait_for_completion_interruptible(
-			&data->result.completion);
-		if (!err)
-			err = data->result.err;
+		wait_for_completion(&data->result.completion);
+		err = data->result.err;
 	}
 
 	if (err)
@@ -639,7 +637,9 @@
 
 	ghash_alg = crypto_find_alg(ghash_name, &crypto_ahash_type,
 				    CRYPTO_ALG_TYPE_HASH,
-				    CRYPTO_ALG_TYPE_AHASH_MASK);
+				    CRYPTO_ALG_TYPE_AHASH_MASK |
+				    crypto_requires_sync(algt->type,
+							 algt->mask));
 	if (IS_ERR(ghash_alg))
 		return PTR_ERR(ghash_alg);
 
diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c
index 5276607..f3d9f6d 100644
--- a/crypto/gf128mul.c
+++ b/crypto/gf128mul.c
@@ -44,7 +44,7 @@
  ---------------------------------------------------------------------------
  Issue 31/01/2006
 
- This file provides fast multiplication in GF(128) as required by several
+ This file provides fast multiplication in GF(2^128) as required by several
  cryptographic authentication modes
 */
 
@@ -88,37 +88,52 @@
 	q(0xf8), q(0xf9), q(0xfa), q(0xfb), q(0xfc), q(0xfd), q(0xfe), q(0xff) \
 }
 
-/*	Given the value i in 0..255 as the byte overflow when a field element
-    in GHASH is multiplied by x^8, this function will return the values that
-    are generated in the lo 16-bit word of the field value by applying the
-    modular polynomial. The values lo_byte and hi_byte are returned via the
-    macro xp_fun(lo_byte, hi_byte) so that the values can be assembled into
-    memory as required by a suitable definition of this macro operating on
-    the table above
-*/
+/*
+ * Given a value i in 0..255 as the byte overflow when a field element
+ * in GF(2^128) is multiplied by x^8, the following macro returns the
+ * 16-bit value that must be XOR-ed into the low-degree end of the
+ * product to reduce it modulo the irreducible polynomial x^128 + x^7 +
+ * x^2 + x + 1.
+ *
+ * There are two versions of the macro, and hence two tables: one for
+ * the "be" convention where the highest-order bit is the coefficient of
+ * the highest-degree polynomial term, and one for the "le" convention
+ * where the highest-order bit is the coefficient of the lowest-degree
+ * polynomial term.  In both cases the values are stored in CPU byte
+ * endianness such that the coefficients are ordered consistently across
+ * bytes, i.e. in the "be" table bits 15..0 of the stored value
+ * correspond to the coefficients of x^15..x^0, and in the "le" table
+ * bits 15..0 correspond to the coefficients of x^0..x^15.
+ *
+ * Therefore, provided that the appropriate byte endianness conversions
+ * are done by the multiplication functions (and these must be in place
+ * anyway to support both little endian and big endian CPUs), the "be"
+ * table can be used for multiplications of both "bbe" and "ble"
+ * elements, and the "le" table can be used for multiplications of both
+ * "lle" and "lbe" elements.
+ */
 
-#define xx(p, q)	0x##p##q
-
-#define xda_bbe(i) ( \
-	(i & 0x80 ? xx(43, 80) : 0) ^ (i & 0x40 ? xx(21, c0) : 0) ^ \
-	(i & 0x20 ? xx(10, e0) : 0) ^ (i & 0x10 ? xx(08, 70) : 0) ^ \
-	(i & 0x08 ? xx(04, 38) : 0) ^ (i & 0x04 ? xx(02, 1c) : 0) ^ \
-	(i & 0x02 ? xx(01, 0e) : 0) ^ (i & 0x01 ? xx(00, 87) : 0) \
+#define xda_be(i) ( \
+	(i & 0x80 ? 0x4380 : 0) ^ (i & 0x40 ? 0x21c0 : 0) ^ \
+	(i & 0x20 ? 0x10e0 : 0) ^ (i & 0x10 ? 0x0870 : 0) ^ \
+	(i & 0x08 ? 0x0438 : 0) ^ (i & 0x04 ? 0x021c : 0) ^ \
+	(i & 0x02 ? 0x010e : 0) ^ (i & 0x01 ? 0x0087 : 0) \
 )
 
-#define xda_lle(i) ( \
-	(i & 0x80 ? xx(e1, 00) : 0) ^ (i & 0x40 ? xx(70, 80) : 0) ^ \
-	(i & 0x20 ? xx(38, 40) : 0) ^ (i & 0x10 ? xx(1c, 20) : 0) ^ \
-	(i & 0x08 ? xx(0e, 10) : 0) ^ (i & 0x04 ? xx(07, 08) : 0) ^ \
-	(i & 0x02 ? xx(03, 84) : 0) ^ (i & 0x01 ? xx(01, c2) : 0) \
+#define xda_le(i) ( \
+	(i & 0x80 ? 0xe100 : 0) ^ (i & 0x40 ? 0x7080 : 0) ^ \
+	(i & 0x20 ? 0x3840 : 0) ^ (i & 0x10 ? 0x1c20 : 0) ^ \
+	(i & 0x08 ? 0x0e10 : 0) ^ (i & 0x04 ? 0x0708 : 0) ^ \
+	(i & 0x02 ? 0x0384 : 0) ^ (i & 0x01 ? 0x01c2 : 0) \
 )
 
-static const u16 gf128mul_table_lle[256] = gf128mul_dat(xda_lle);
-static const u16 gf128mul_table_bbe[256] = gf128mul_dat(xda_bbe);
+static const u16 gf128mul_table_le[256] = gf128mul_dat(xda_le);
+static const u16 gf128mul_table_be[256] = gf128mul_dat(xda_be);
 
-/* These functions multiply a field element by x, by x^4 and by x^8
- * in the polynomial field representation. It uses 32-bit word operations
- * to gain speed but compensates for machine endianess and hence works
+/*
+ * The following functions multiply a field element by x or by x^8 in
+ * the polynomial field representation.  They use 64-bit word operations
+ * to gain speed but compensate for machine endianness and hence work
  * correctly on both styles of machine.
  */
 
@@ -126,7 +141,7 @@
 {
 	u64 a = be64_to_cpu(x->a);
 	u64 b = be64_to_cpu(x->b);
-	u64 _tt = gf128mul_table_lle[(b << 7) & 0xff];
+	u64 _tt = gf128mul_table_le[(b << 7) & 0xff];
 
 	r->b = cpu_to_be64((b >> 1) | (a << 63));
 	r->a = cpu_to_be64((a >> 1) ^ (_tt << 48));
@@ -136,7 +151,7 @@
 {
 	u64 a = be64_to_cpu(x->a);
 	u64 b = be64_to_cpu(x->b);
-	u64 _tt = gf128mul_table_bbe[a >> 63];
+	u64 _tt = gf128mul_table_be[a >> 63];
 
 	r->a = cpu_to_be64((a << 1) | (b >> 63));
 	r->b = cpu_to_be64((b << 1) ^ _tt);
@@ -146,7 +161,7 @@
 {
 	u64 a = le64_to_cpu(x->a);
 	u64 b = le64_to_cpu(x->b);
-	u64 _tt = gf128mul_table_bbe[b >> 63];
+	u64 _tt = gf128mul_table_be[b >> 63];
 
 	r->a = cpu_to_le64((a << 1) ^ _tt);
 	r->b = cpu_to_le64((b << 1) | (a >> 63));
@@ -157,7 +172,7 @@
 {
 	u64 a = be64_to_cpu(x->a);
 	u64 b = be64_to_cpu(x->b);
-	u64 _tt = gf128mul_table_lle[b & 0xff];
+	u64 _tt = gf128mul_table_le[b & 0xff];
 
 	x->b = cpu_to_be64((b >> 8) | (a << 56));
 	x->a = cpu_to_be64((a >> 8) ^ (_tt << 48));
@@ -167,12 +182,22 @@
 {
 	u64 a = be64_to_cpu(x->a);
 	u64 b = be64_to_cpu(x->b);
-	u64 _tt = gf128mul_table_bbe[a >> 56];
+	u64 _tt = gf128mul_table_be[a >> 56];
 
 	x->a = cpu_to_be64((a << 8) | (b >> 56));
 	x->b = cpu_to_be64((b << 8) ^ _tt);
 }
 
+static void gf128mul_x8_ble(be128 *x)
+{
+	u64 a = le64_to_cpu(x->b);
+	u64 b = le64_to_cpu(x->a);
+	u64 _tt = gf128mul_table_be[a >> 56];
+
+	x->b = cpu_to_le64((a << 8) | (b >> 56));
+	x->a = cpu_to_le64((b << 8) ^ _tt);
+}
+
 void gf128mul_lle(be128 *r, const be128 *b)
 {
 	be128 p[8];
@@ -249,9 +274,48 @@
 }
 EXPORT_SYMBOL(gf128mul_bbe);
 
+void gf128mul_ble(be128 *r, const be128 *b)
+{
+	be128 p[8];
+	int i;
+
+	p[0] = *r;
+	for (i = 0; i < 7; ++i)
+		gf128mul_x_ble((be128 *)&p[i + 1], (be128 *)&p[i]);
+
+	memset(r, 0, sizeof(*r));
+	for (i = 0;;) {
+		u8 ch = ((u8 *)b)[15 - i];
+
+		if (ch & 0x80)
+			be128_xor(r, r, &p[7]);
+		if (ch & 0x40)
+			be128_xor(r, r, &p[6]);
+		if (ch & 0x20)
+			be128_xor(r, r, &p[5]);
+		if (ch & 0x10)
+			be128_xor(r, r, &p[4]);
+		if (ch & 0x08)
+			be128_xor(r, r, &p[3]);
+		if (ch & 0x04)
+			be128_xor(r, r, &p[2]);
+		if (ch & 0x02)
+			be128_xor(r, r, &p[1]);
+		if (ch & 0x01)
+			be128_xor(r, r, &p[0]);
+
+		if (++i >= 16)
+			break;
+
+		gf128mul_x8_ble(r);
+	}
+}
+EXPORT_SYMBOL(gf128mul_ble);
+
+
 /*      This version uses 64k bytes of table space.
     A 16 byte buffer has to be multiplied by a 16 byte key
-    value in GF(128).  If we consider a GF(128) value in
+    value in GF(2^128).  If we consider a GF(2^128) value in
     the buffer's lowest byte, we can construct a table of
     the 256 16 byte values that result from the 256 values
     of this byte.  This requires 4096 bytes. But we also
@@ -352,8 +416,8 @@
 	int i;
 
 	for (i = 0; i < 16; i++)
-		kfree(t->t[i]);
-	kfree(t);
+		kzfree(t->t[i]);
+	kzfree(t);
 }
 EXPORT_SYMBOL(gf128mul_free_64k);
 
@@ -385,7 +449,7 @@
 
 /*      This version uses 4k bytes of table space.
     A 16 byte buffer has to be multiplied by a 16 byte key
-    value in GF(128).  If we consider a GF(128) value in a
+    value in GF(2^128).  If we consider a GF(2^128) value in a
     single byte, we can construct a table of the 256 16 byte
     values that result from the 256 values of this byte.
     This requires 4096 bytes. If we take the highest byte in
@@ -443,6 +507,28 @@
 }
 EXPORT_SYMBOL(gf128mul_init_4k_bbe);
 
+struct gf128mul_4k *gf128mul_init_4k_ble(const be128 *g)
+{
+	struct gf128mul_4k *t;
+	int j, k;
+
+	t = kzalloc(sizeof(*t), GFP_KERNEL);
+	if (!t)
+		goto out;
+
+	t->t[1] = *g;
+	for (j = 1; j <= 64; j <<= 1)
+		gf128mul_x_ble(&t->t[j + j], &t->t[j]);
+
+	for (j = 2; j < 256; j += j)
+		for (k = 1; k < j; ++k)
+			be128_xor(&t->t[j + k], &t->t[j], &t->t[k]);
+
+out:
+	return t;
+}
+EXPORT_SYMBOL(gf128mul_init_4k_ble);
+
 void gf128mul_4k_lle(be128 *a, struct gf128mul_4k *t)
 {
 	u8 *ap = (u8 *)a;
@@ -473,5 +559,20 @@
 }
 EXPORT_SYMBOL(gf128mul_4k_bbe);
 
+void gf128mul_4k_ble(be128 *a, struct gf128mul_4k *t)
+{
+	u8 *ap = (u8 *)a;
+	be128 r[1];
+	int i = 15;
+
+	*r = t->t[ap[15]];
+	while (i--) {
+		gf128mul_x8_ble(r);
+		be128_xor(r, r, &t->t[ap[i]]);
+	}
+	*a = *r;
+}
+EXPORT_SYMBOL(gf128mul_4k_ble);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Functions for multiplying elements of GF(2^128)");
diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c
index bac7099..12ad3e3 100644
--- a/crypto/ghash-generic.c
+++ b/crypto/ghash-generic.c
@@ -14,24 +14,13 @@
 
 #include <crypto/algapi.h>
 #include <crypto/gf128mul.h>
+#include <crypto/ghash.h>
 #include <crypto/internal/hash.h>
 #include <linux/crypto.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-#define GHASH_BLOCK_SIZE	16
-#define GHASH_DIGEST_SIZE	16
-
-struct ghash_ctx {
-	struct gf128mul_4k *gf128;
-};
-
-struct ghash_desc_ctx {
-	u8 buffer[GHASH_BLOCK_SIZE];
-	u32 bytes;
-};
-
 static int ghash_init(struct shash_desc *desc)
 {
 	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
diff --git a/crypto/heh.c b/crypto/heh.c
new file mode 100644
index 0000000..10c00aa
--- /dev/null
+++ b/crypto/heh.c
@@ -0,0 +1,1033 @@
+/*
+ * HEH: Hash-Encrypt-Hash mode
+ *
+ * Copyright (c) 2016 Google Inc.
+ *
+ * Authors:
+ *	Alex Cope <alexcope@google.com>
+ *	Eric Biggers <ebiggers@google.com>
+ */
+
+/*
+ * Hash-Encrypt-Hash (HEH) is a proposed block cipher mode of operation which
+ * extends the strong pseudo-random permutation (SPRP) property of block ciphers
+ * (e.g. AES) to arbitrary length input strings.  It uses two keyed invertible
+ * hash functions with a layer of ECB encryption applied in-between.  The
+ * algorithm is specified by the following Internet Draft:
+ *
+ *	https://tools.ietf.org/html/draft-cope-heh-01
+ *
+ * Although HEH can be used as either a regular symmetric cipher or as an AEAD,
+ * currently this module only provides it as a symmetric cipher.  Additionally,
+ * only 16-byte nonces are supported.
+ */
+
+#include <crypto/gf128mul.h>
+#include <crypto/internal/hash.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/skcipher.h>
+#include "internal.h"
+
+/*
+ * The block size is the size of GF(2^128) elements and also the required block
+ * size of the underlying block cipher.
+ */
+#define HEH_BLOCK_SIZE		16
+
+struct heh_instance_ctx {
+	struct crypto_shash_spawn cmac;
+	struct crypto_shash_spawn poly_hash;
+	struct crypto_skcipher_spawn ecb;
+};
+
+struct heh_tfm_ctx {
+	struct crypto_shash *cmac;
+	struct crypto_shash *poly_hash; /* keyed with tau_key */
+	struct crypto_ablkcipher *ecb;
+};
+
+struct heh_cmac_data {
+	u8 nonce[HEH_BLOCK_SIZE];
+	__le32 nonce_length;
+	__le32 aad_length;
+	__le32 message_length;
+	__le32 padding;
+};
+
+struct heh_req_ctx { /* aligned to alignmask */
+	be128 beta1_key;
+	be128 beta2_key;
+	union {
+		struct {
+			struct heh_cmac_data data;
+			struct shash_desc desc;
+			/* + crypto_shash_descsize(cmac) */
+		} cmac;
+		struct {
+			struct shash_desc desc;
+			/* + crypto_shash_descsize(poly_hash) */
+		} poly_hash;
+		struct {
+			u8 keystream[HEH_BLOCK_SIZE];
+			u8 tmp[HEH_BLOCK_SIZE];
+			struct scatterlist tmp_sgl[2];
+			struct ablkcipher_request req;
+			/* + crypto_ablkcipher_reqsize(ecb) */
+		} ecb;
+	} u;
+};
+
+/*
+ * Get the offset in bytes to the last full block, or equivalently the length of
+ * all full blocks excluding the last
+ */
+static inline unsigned int get_tail_offset(unsigned int len)
+{
+	len -= len % HEH_BLOCK_SIZE;
+	return len - HEH_BLOCK_SIZE;
+}
+
+static inline struct heh_req_ctx *heh_req_ctx(struct ablkcipher_request *req)
+{
+	unsigned int alignmask = crypto_ablkcipher_alignmask(
+						crypto_ablkcipher_reqtfm(req));
+
+	return (void *)PTR_ALIGN((u8 *)ablkcipher_request_ctx(req),
+				 alignmask + 1);
+}
+
+static inline void async_done(struct crypto_async_request *areq, int err,
+			      int (*next_step)(struct ablkcipher_request *,
+					       u32))
+{
+	struct ablkcipher_request *req = areq->data;
+
+	if (err)
+		goto out;
+
+	err = next_step(req, req->base.flags & ~CRYPTO_TFM_REQ_MAY_SLEEP);
+	if (err == -EINPROGRESS ||
+	    (err == -EBUSY && (req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))
+		return;
+out:
+	ablkcipher_request_complete(req, err);
+}
+
+/*
+ * Generate the per-message "beta" keys used by the hashing layers of HEH.  The
+ * first beta key is the CMAC of the nonce, the additional authenticated data
+ * (AAD), and the lengths in bytes of the nonce, AAD, and message.  The nonce
+ * and AAD are each zero-padded to the next 16-byte block boundary, and the
+ * lengths are serialized as 4-byte little endian integers and zero-padded to
+ * the next 16-byte block boundary.
+ * The second beta key is the first one interpreted as an element in GF(2^128)
+ * and multiplied by x.
+ *
+ * Note that because the nonce and AAD may, in general, be variable-length, the
+ * key generation must be done by a pseudo-random function (PRF) on
+ * variable-length inputs.  CBC-MAC does not satisfy this, as it is only a PRF
+ * on fixed-length inputs.  CMAC remedies this flaw.  Including the lengths of
+ * the nonce, AAD, and message is also critical to avoid collisions.
+ *
+ * That being said, this implementation does not yet operate as an AEAD and
+ * therefore there is never any AAD, nor are variable-length nonces supported.
+ */
+static int generate_betas(struct ablkcipher_request *req,
+			  be128 *beta1_key, be128 *beta2_key)
+{
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+	struct heh_tfm_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	struct heh_req_ctx *rctx = heh_req_ctx(req);
+	struct heh_cmac_data *data = &rctx->u.cmac.data;
+	struct shash_desc *desc = &rctx->u.cmac.desc;
+	int err;
+
+	BUILD_BUG_ON(sizeof(*data) != 2 * HEH_BLOCK_SIZE);
+	memcpy(data->nonce, req->info, HEH_BLOCK_SIZE);
+	data->nonce_length = cpu_to_le32(HEH_BLOCK_SIZE);
+	data->aad_length = cpu_to_le32(0);
+	data->message_length = cpu_to_le32(req->nbytes);
+	data->padding = cpu_to_le32(0);
+
+	desc->tfm = ctx->cmac;
+	desc->flags = req->base.flags;
+
+	err = crypto_shash_digest(desc, (const u8 *)data, sizeof(*data),
+				  (u8 *)beta1_key);
+	if (err)
+		return err;
+
+	gf128mul_x_ble(beta2_key, beta1_key);
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ * This is the generic version of poly_hash.  It does the GF(2^128)
+ * multiplication by 'tau_key' using a precomputed table, without using any
+ * special CPU instructions.  On some platforms, an accelerated version (with
+ * higher cra_priority) may be used instead.
+ */
+
+struct poly_hash_tfm_ctx {
+	struct gf128mul_4k *tau_key;
+};
+
+struct poly_hash_desc_ctx {
+	be128 digest;
+	unsigned int count;
+};
+
+static int poly_hash_setkey(struct crypto_shash *tfm,
+			    const u8 *key, unsigned int keylen)
+{
+	struct poly_hash_tfm_ctx *tctx = crypto_shash_ctx(tfm);
+	be128 key128;
+
+	if (keylen != HEH_BLOCK_SIZE) {
+		crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	if (tctx->tau_key)
+		gf128mul_free_4k(tctx->tau_key);
+	memcpy(&key128, key, HEH_BLOCK_SIZE);
+	tctx->tau_key = gf128mul_init_4k_ble(&key128);
+	if (!tctx->tau_key)
+		return -ENOMEM;
+	return 0;
+}
+
+static int poly_hash_init(struct shash_desc *desc)
+{
+	struct poly_hash_desc_ctx *ctx = shash_desc_ctx(desc);
+
+	ctx->digest = (be128) { 0 };
+	ctx->count = 0;
+	return 0;
+}
+
+static int poly_hash_update(struct shash_desc *desc, const u8 *src,
+			    unsigned int len)
+{
+	struct poly_hash_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
+	struct poly_hash_desc_ctx *ctx = shash_desc_ctx(desc);
+	unsigned int partial = ctx->count % HEH_BLOCK_SIZE;
+	u8 *dst = (u8 *)&ctx->digest + partial;
+
+	ctx->count += len;
+
+	/* Finishing at least one block? */
+	if (partial + len >= HEH_BLOCK_SIZE) {
+
+		if (partial) {
+			/* Finish the pending block. */
+			unsigned int n = HEH_BLOCK_SIZE - partial;
+
+			len -= n;
+			do {
+				*dst++ ^= *src++;
+			} while (--n);
+
+			gf128mul_4k_ble(&ctx->digest, tctx->tau_key);
+		}
+
+		/* Process zero or more full blocks. */
+		while (len >= HEH_BLOCK_SIZE) {
+			be128 coeff;
+
+			memcpy(&coeff, src, HEH_BLOCK_SIZE);
+			be128_xor(&ctx->digest, &ctx->digest, &coeff);
+			src += HEH_BLOCK_SIZE;
+			len -= HEH_BLOCK_SIZE;
+			gf128mul_4k_ble(&ctx->digest, tctx->tau_key);
+		}
+		dst = (u8 *)&ctx->digest;
+	}
+
+	/* Continue adding the next block to 'digest'. */
+	while (len--)
+		*dst++ ^= *src++;
+	return 0;
+}
+
+static int poly_hash_final(struct shash_desc *desc, u8 *out)
+{
+	struct poly_hash_desc_ctx *ctx = shash_desc_ctx(desc);
+
+	/* Finish the last block if needed. */
+	if (ctx->count % HEH_BLOCK_SIZE) {
+		struct poly_hash_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
+
+		gf128mul_4k_ble(&ctx->digest, tctx->tau_key);
+	}
+
+	memcpy(out, &ctx->digest, HEH_BLOCK_SIZE);
+	return 0;
+}
+
+static void poly_hash_exit(struct crypto_tfm *tfm)
+{
+	struct poly_hash_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
+
+	gf128mul_free_4k(tctx->tau_key);
+}
+
+static struct shash_alg poly_hash_alg = {
+	.digestsize	= HEH_BLOCK_SIZE,
+	.init		= poly_hash_init,
+	.update		= poly_hash_update,
+	.final		= poly_hash_final,
+	.setkey		= poly_hash_setkey,
+	.descsize	= sizeof(struct poly_hash_desc_ctx),
+	.base		= {
+		.cra_name		= "poly_hash",
+		.cra_driver_name	= "poly_hash-generic",
+		.cra_priority		= 100,
+		.cra_ctxsize		= sizeof(struct poly_hash_tfm_ctx),
+		.cra_exit		= poly_hash_exit,
+		.cra_module		= THIS_MODULE,
+	},
+};
+
+/*****************************************************************************/
+
+/*
+ * Split the message into 16 byte blocks, padding out the last block, and use
+ * the blocks as coefficients in the evaluation of a polynomial over GF(2^128)
+ * at the secret point 'tau_key'. For ease of implementing the higher-level
+ * heh_hash_inv() function, the constant and degree-1 coefficients are swapped
+ * if there is a partial block.
+ *
+ * Mathematically, compute:
+ *   if (no partial block)
+ *     k^{N-1} * m_0 + ... + k * m_{N-2} + m_{N-1}
+ *   else if (partial block)
+ *     k^N * m_0 + ... + k^2 * m_{N-2} + k * m_N + m_{N-1}
+ *
+ * where:
+ *	t is tau_key
+ *	N is the number of full blocks in the message
+ *	m_i is the i-th full block in the message for i = 0 to N-1 inclusive
+ *	m_N is the partial block of the message zero-padded up to 16 bytes
+ *
+ * Note that most of this is now separated out into its own keyed hash
+ * algorithm, to allow optimized implementations.  However, we still handle the
+ * swapping of the last two coefficients here in the HEH template because this
+ * simplifies the poly_hash algorithms: they don't have to buffer an extra
+ * block, don't have to duplicate as much code, and are more similar to GHASH.
+ */
+static int poly_hash(struct ablkcipher_request *req, struct scatterlist *sgl,
+		     be128 *hash)
+{
+	struct heh_req_ctx *rctx = heh_req_ctx(req);
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+	struct heh_tfm_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	struct shash_desc *desc = &rctx->u.poly_hash.desc;
+	unsigned int tail_offset = get_tail_offset(req->nbytes);
+	unsigned int tail_len = req->nbytes - tail_offset;
+	be128 tail[2];
+	unsigned int i, n;
+	struct sg_mapping_iter miter;
+	int err;
+
+	desc->tfm = ctx->poly_hash;
+	desc->flags = req->base.flags;
+
+	/* Handle all full blocks except the last */
+	err = crypto_shash_init(desc);
+	sg_miter_start(&miter, sgl, sg_nents(sgl),
+		       SG_MITER_FROM_SG | SG_MITER_ATOMIC);
+	for (i = 0; i < tail_offset && !err; i += n) {
+		sg_miter_next(&miter);
+		n = min_t(unsigned int, miter.length, tail_offset - i);
+		err = crypto_shash_update(desc, miter.addr, n);
+	}
+	sg_miter_stop(&miter);
+	if (err)
+		return err;
+
+	/* Handle the last full block and the partial block */
+	scatterwalk_map_and_copy(tail, sgl, tail_offset, tail_len, 0);
+
+	if (tail_len != HEH_BLOCK_SIZE) {
+		/* handle the partial block */
+		memset((u8 *)tail + tail_len, 0, sizeof(tail) - tail_len);
+		err = crypto_shash_update(desc, (u8 *)&tail[1], HEH_BLOCK_SIZE);
+		if (err)
+			return err;
+	}
+	err = crypto_shash_final(desc, (u8 *)hash);
+	if (err)
+		return err;
+	be128_xor(hash, hash, &tail[0]);
+	return 0;
+}
+
+/*
+ * Transform all full blocks except the last.
+ * This is used by both the hash and inverse hash phases.
+ */
+static int heh_tfm_blocks(struct ablkcipher_request *req,
+			  struct scatterlist *src_sgl,
+			  struct scatterlist *dst_sgl, unsigned int len,
+			  const be128 *hash, const be128 *beta_key)
+{
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+	struct blkcipher_desc desc = { .flags = req->base.flags };
+	struct blkcipher_walk walk;
+	be128 e = *beta_key;
+	int err;
+	unsigned int nbytes;
+
+	blkcipher_walk_init(&walk, dst_sgl, src_sgl, len);
+
+	err = blkcipher_ablkcipher_walk_virt(&desc, &walk, tfm);
+
+	while ((nbytes = walk.nbytes)) {
+		const be128 *src = (be128 *)walk.src.virt.addr;
+		be128 *dst = (be128 *)walk.dst.virt.addr;
+
+		do {
+			gf128mul_x_ble(&e, &e);
+			be128_xor(dst, src, hash);
+			be128_xor(dst, dst, &e);
+			src++;
+			dst++;
+		} while ((nbytes -= HEH_BLOCK_SIZE) >= HEH_BLOCK_SIZE);
+		err = blkcipher_walk_done(&desc, &walk, nbytes);
+	}
+	return err;
+}
+
+/*
+ * The hash phase of HEH.  Given a message, compute:
+ *
+ *     (m_0 + H, ..., m_{N-2} + H, H, m_N) + (xb, x^2b, ..., x^{N-1}b, b, 0)
+ *
+ * where:
+ *	N is the number of full blocks in the message
+ *	m_i is the i-th full block in the message for i = 0 to N-1 inclusive
+ *	m_N is the unpadded partial block, possibly empty
+ *	H is the poly_hash() of the message, keyed by tau_key
+ *	b is beta_key
+ *	x is the element x in our representation of GF(2^128)
+ *
+ * Note that the partial block remains unchanged, but it does affect the result
+ * of poly_hash() and therefore the transformation of all the full blocks.
+ */
+static int heh_hash(struct ablkcipher_request *req, const be128 *beta_key)
+{
+	be128 hash;
+	unsigned int tail_offset = get_tail_offset(req->nbytes);
+	unsigned int partial_len = req->nbytes % HEH_BLOCK_SIZE;
+	int err;
+
+	/* poly_hash() the full message including the partial block */
+	err = poly_hash(req, req->src, &hash);
+	if (err)
+		return err;
+
+	/* Transform all full blocks except the last */
+	err = heh_tfm_blocks(req, req->src, req->dst, tail_offset, &hash,
+			     beta_key);
+	if (err)
+		return err;
+
+	/* Set the last full block to hash XOR beta_key */
+	be128_xor(&hash, &hash, beta_key);
+	scatterwalk_map_and_copy(&hash, req->dst, tail_offset, HEH_BLOCK_SIZE,
+				 1);
+
+	/* Copy the partial block if needed */
+	if (partial_len != 0 && req->src != req->dst) {
+		unsigned int offs = tail_offset + HEH_BLOCK_SIZE;
+
+		scatterwalk_map_and_copy(&hash, req->src, offs, partial_len, 0);
+		scatterwalk_map_and_copy(&hash, req->dst, offs, partial_len, 1);
+	}
+	return 0;
+}
+
+/*
+ * The inverse hash phase of HEH.  This undoes the result of heh_hash().
+ */
+static int heh_hash_inv(struct ablkcipher_request *req, const be128 *beta_key)
+{
+	be128 hash;
+	be128 tmp;
+	struct scatterlist tmp_sgl[2];
+	struct scatterlist *tail_sgl;
+	unsigned int tail_offset = get_tail_offset(req->nbytes);
+	struct scatterlist *sgl = req->dst;
+	int err;
+
+	/*
+	 * The last full block was computed as hash XOR beta_key, so XOR it with
+	 * beta_key to recover hash.
+	 */
+	tail_sgl = scatterwalk_ffwd(tmp_sgl, sgl, tail_offset);
+	scatterwalk_map_and_copy(&hash, tail_sgl, 0, HEH_BLOCK_SIZE, 0);
+	be128_xor(&hash, &hash, beta_key);
+
+	/* Transform all full blocks except the last */
+	err = heh_tfm_blocks(req, sgl, sgl, tail_offset, &hash, beta_key);
+	if (err)
+		return err;
+
+	/*
+	 * Recover the last full block.  We know 'hash', i.e. the poly_hash() of
+	 * the the original message.  The last full block was the constant term
+	 * of the polynomial.  To recover the last full block, temporarily zero
+	 * it, compute the poly_hash(), and take the difference from 'hash'.
+	 */
+	memset(&tmp, 0, sizeof(tmp));
+	scatterwalk_map_and_copy(&tmp, tail_sgl, 0, HEH_BLOCK_SIZE, 1);
+	err = poly_hash(req, sgl, &tmp);
+	if (err)
+		return err;
+	be128_xor(&tmp, &tmp, &hash);
+	scatterwalk_map_and_copy(&tmp, tail_sgl, 0, HEH_BLOCK_SIZE, 1);
+	return 0;
+}
+
+static int heh_hash_inv_step(struct ablkcipher_request *req, u32 flags)
+{
+	struct heh_req_ctx *rctx = heh_req_ctx(req);
+
+	return heh_hash_inv(req, &rctx->beta2_key);
+}
+
+static int heh_ecb_step_3(struct ablkcipher_request *req, u32 flags)
+{
+	struct heh_req_ctx *rctx = heh_req_ctx(req);
+	u8 partial_block[HEH_BLOCK_SIZE] __aligned(__alignof__(u32));
+	unsigned int tail_offset = get_tail_offset(req->nbytes);
+	unsigned int partial_offset = tail_offset + HEH_BLOCK_SIZE;
+	unsigned int partial_len = req->nbytes - partial_offset;
+
+	/*
+	 * Extract the pad in req->dst at tail_offset, and xor the partial block
+	 * with it to create encrypted partial block
+	 */
+	scatterwalk_map_and_copy(rctx->u.ecb.keystream, req->dst, tail_offset,
+				 HEH_BLOCK_SIZE, 0);
+	scatterwalk_map_and_copy(partial_block, req->dst, partial_offset,
+				 partial_len, 0);
+	crypto_xor(partial_block, rctx->u.ecb.keystream, partial_len);
+
+	/*
+	 * Store the encrypted final block and partial block back in dst_sg
+	 */
+	scatterwalk_map_and_copy(&rctx->u.ecb.tmp, req->dst, tail_offset,
+				 HEH_BLOCK_SIZE, 1);
+	scatterwalk_map_and_copy(partial_block, req->dst, partial_offset,
+				 partial_len, 1);
+
+	return heh_hash_inv_step(req, flags);
+}
+
+static void heh_ecb_step_2_done(struct crypto_async_request *areq, int err)
+{
+	return async_done(areq, err, heh_ecb_step_3);
+}
+
+static int heh_ecb_step_2(struct ablkcipher_request *req, u32 flags)
+{
+	struct heh_req_ctx *rctx = heh_req_ctx(req);
+	unsigned int partial_len = req->nbytes % HEH_BLOCK_SIZE;
+	struct scatterlist *tmp_sgl;
+	int err;
+	unsigned int tail_offset = get_tail_offset(req->nbytes);
+
+	if (partial_len == 0)
+		return heh_hash_inv_step(req, flags);
+
+	/*
+	 * Extract the final full block, store it in tmp, and then xor that with
+	 * the value saved in u.ecb.keystream
+	 */
+	scatterwalk_map_and_copy(rctx->u.ecb.tmp, req->dst, tail_offset,
+				 HEH_BLOCK_SIZE, 0);
+	crypto_xor(rctx->u.ecb.keystream, rctx->u.ecb.tmp, HEH_BLOCK_SIZE);
+
+	/*
+	 * Encrypt the value in rctx->u.ecb.keystream to create the pad for the
+	 * partial block.
+	 * We cannot encrypt stack buffers, so re-use the dst_sg to do this
+	 * encryption to avoid a malloc. The value at tail_offset is stored in
+	 * tmp, and will be restored later.
+	 */
+	scatterwalk_map_and_copy(rctx->u.ecb.keystream, req->dst, tail_offset,
+				 HEH_BLOCK_SIZE, 1);
+	tmp_sgl = scatterwalk_ffwd(rctx->u.ecb.tmp_sgl, req->dst, tail_offset);
+	ablkcipher_request_set_callback(&rctx->u.ecb.req, flags,
+					heh_ecb_step_2_done, req);
+	ablkcipher_request_set_crypt(&rctx->u.ecb.req, tmp_sgl, tmp_sgl,
+				     HEH_BLOCK_SIZE, NULL);
+	err = crypto_ablkcipher_encrypt(&rctx->u.ecb.req);
+	if (err)
+		return err;
+	return heh_ecb_step_3(req, flags);
+}
+
+static void heh_ecb_full_done(struct crypto_async_request *areq, int err)
+{
+	return async_done(areq, err, heh_ecb_step_2);
+}
+
+/*
+ * The encrypt phase of HEH.  This uses ECB encryption, with special handling
+ * for the partial block at the end if any.  The source data is already in
+ * req->dst, so the encryption happens in-place.
+ *
+ * After the encrypt phase we continue on to the inverse hash phase.  The
+ * functions calls are chained to support asynchronous ECB algorithms.
+ */
+static int heh_ecb(struct ablkcipher_request *req, bool decrypt)
+{
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+	struct heh_tfm_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	struct heh_req_ctx *rctx = heh_req_ctx(req);
+	struct ablkcipher_request *ecb_req = &rctx->u.ecb.req;
+	unsigned int tail_offset = get_tail_offset(req->nbytes);
+	unsigned int full_len = tail_offset + HEH_BLOCK_SIZE;
+	int err;
+
+	/*
+	 * Save the last full block before it is encrypted/decrypted. This will
+	 * be used later to encrypt/decrypt the partial block
+	 */
+	scatterwalk_map_and_copy(rctx->u.ecb.keystream, req->dst, tail_offset,
+				 HEH_BLOCK_SIZE, 0);
+
+	/* Encrypt/decrypt all full blocks */
+	ablkcipher_request_set_tfm(ecb_req, ctx->ecb);
+	ablkcipher_request_set_callback(ecb_req, req->base.flags,
+				      heh_ecb_full_done, req);
+	ablkcipher_request_set_crypt(ecb_req, req->dst, req->dst, full_len,
+				     NULL);
+	if (decrypt)
+		err = crypto_ablkcipher_decrypt(ecb_req);
+	else
+		err = crypto_ablkcipher_encrypt(ecb_req);
+	if (err)
+		return err;
+
+	return heh_ecb_step_2(req, req->base.flags);
+}
+
+static int heh_crypt(struct ablkcipher_request *req, bool decrypt)
+{
+	struct heh_req_ctx *rctx = heh_req_ctx(req);
+	int err;
+
+	/* Inputs must be at least one full block */
+	if (req->nbytes < HEH_BLOCK_SIZE)
+		return -EINVAL;
+
+	err = generate_betas(req, &rctx->beta1_key, &rctx->beta2_key);
+	if (err)
+		return err;
+
+	if (decrypt)
+		swap(rctx->beta1_key, rctx->beta2_key);
+
+	err = heh_hash(req, &rctx->beta1_key);
+	if (err)
+		return err;
+
+	return heh_ecb(req, decrypt);
+}
+
+static int heh_encrypt(struct ablkcipher_request *req)
+{
+	return heh_crypt(req, false);
+}
+
+static int heh_decrypt(struct ablkcipher_request *req)
+{
+	return heh_crypt(req, true);
+}
+
+static int heh_setkey(struct crypto_ablkcipher *parent, const u8 *key,
+		      unsigned int keylen)
+{
+	struct heh_tfm_ctx *ctx = crypto_ablkcipher_ctx(parent);
+	struct crypto_shash *cmac = ctx->cmac;
+	struct crypto_ablkcipher *ecb = ctx->ecb;
+	SHASH_DESC_ON_STACK(desc, cmac);
+	u8 *derived_keys;
+	u8 digest[HEH_BLOCK_SIZE];
+	unsigned int i;
+	int err;
+
+	/* set prf_key = key */
+	crypto_shash_clear_flags(cmac, CRYPTO_TFM_REQ_MASK);
+	crypto_shash_set_flags(cmac, crypto_ablkcipher_get_flags(parent) &
+				     CRYPTO_TFM_REQ_MASK);
+	err = crypto_shash_setkey(cmac, key, keylen);
+	crypto_ablkcipher_set_flags(parent, crypto_shash_get_flags(cmac) &
+					    CRYPTO_TFM_RES_MASK);
+	if (err)
+		return err;
+
+	/*
+	 * Generate tau_key and ecb_key as follows:
+	 * tau_key = cmac(prf_key, 0x00...01)
+	 * ecb_key = cmac(prf_key, 0x00...02) || cmac(prf_key, 0x00...03) || ...
+	 *           truncated to keylen bytes
+	 */
+	derived_keys = kzalloc(round_up(HEH_BLOCK_SIZE + keylen,
+					HEH_BLOCK_SIZE), GFP_KERNEL);
+	if (!derived_keys)
+		return -ENOMEM;
+	desc->tfm = cmac;
+	desc->flags = (crypto_shash_get_flags(cmac) & CRYPTO_TFM_REQ_MASK);
+	for (i = 0; i < keylen + HEH_BLOCK_SIZE; i += HEH_BLOCK_SIZE) {
+		derived_keys[i + HEH_BLOCK_SIZE - 1] =
+					0x01 + i / HEH_BLOCK_SIZE;
+		err = crypto_shash_digest(desc, derived_keys + i,
+					  HEH_BLOCK_SIZE, digest);
+		if (err)
+			goto out;
+		memcpy(derived_keys + i, digest, HEH_BLOCK_SIZE);
+	}
+
+	err = crypto_shash_setkey(ctx->poly_hash, derived_keys, HEH_BLOCK_SIZE);
+	if (err)
+		goto out;
+
+	crypto_ablkcipher_clear_flags(ecb, CRYPTO_TFM_REQ_MASK);
+	crypto_ablkcipher_set_flags(ecb, crypto_ablkcipher_get_flags(parent) &
+					 CRYPTO_TFM_REQ_MASK);
+	err = crypto_ablkcipher_setkey(ecb, derived_keys + HEH_BLOCK_SIZE,
+				       keylen);
+	crypto_ablkcipher_set_flags(parent, crypto_ablkcipher_get_flags(ecb) &
+					    CRYPTO_TFM_RES_MASK);
+out:
+	kzfree(derived_keys);
+	return err;
+}
+
+static int heh_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+	struct heh_instance_ctx *ictx = crypto_instance_ctx(inst);
+	struct heh_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_shash *cmac;
+	struct crypto_shash *poly_hash;
+	struct crypto_ablkcipher *ecb;
+	unsigned int reqsize;
+	int err;
+
+	cmac = crypto_spawn_shash(&ictx->cmac);
+	if (IS_ERR(cmac))
+		return PTR_ERR(cmac);
+
+	poly_hash = crypto_spawn_shash(&ictx->poly_hash);
+	err = PTR_ERR(poly_hash);
+	if (IS_ERR(poly_hash))
+		goto err_free_cmac;
+
+	ecb = crypto_spawn_skcipher(&ictx->ecb);
+	err = PTR_ERR(ecb);
+	if (IS_ERR(ecb))
+		goto err_free_poly_hash;
+
+	ctx->cmac = cmac;
+	ctx->poly_hash = poly_hash;
+	ctx->ecb = ecb;
+
+	reqsize = crypto_tfm_alg_alignmask(tfm) &
+		  ~(crypto_tfm_ctx_alignment() - 1);
+	reqsize += max3(offsetof(struct heh_req_ctx, u.cmac.desc) +
+			  sizeof(struct shash_desc) +
+			  crypto_shash_descsize(cmac),
+			offsetof(struct heh_req_ctx, u.poly_hash.desc) +
+			  sizeof(struct shash_desc) +
+			  crypto_shash_descsize(poly_hash),
+			offsetof(struct heh_req_ctx, u.ecb.req) +
+			  sizeof(struct ablkcipher_request) +
+			  crypto_ablkcipher_reqsize(ecb));
+	tfm->crt_ablkcipher.reqsize = reqsize;
+
+	return 0;
+
+err_free_poly_hash:
+	crypto_free_shash(poly_hash);
+err_free_cmac:
+	crypto_free_shash(cmac);
+	return err;
+}
+
+static void heh_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct heh_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto_free_shash(ctx->cmac);
+	crypto_free_shash(ctx->poly_hash);
+	crypto_free_ablkcipher(ctx->ecb);
+}
+
+static void heh_free_instance(struct crypto_instance *inst)
+{
+	struct heh_instance_ctx *ctx = crypto_instance_ctx(inst);
+
+	crypto_drop_shash(&ctx->cmac);
+	crypto_drop_shash(&ctx->poly_hash);
+	crypto_drop_skcipher(&ctx->ecb);
+	kfree(inst);
+}
+
+/*
+ * Create an instance of HEH as a ablkcipher.
+ *
+ * This relies on underlying CMAC and ECB algorithms, usually cmac(aes) and
+ * ecb(aes).  For performance reasons we support asynchronous ECB algorithms.
+ * However, we do not yet support asynchronous CMAC algorithms because CMAC is
+ * only used on a small fixed amount of data per request, independent of the
+ * request length.  This would change if AEAD or variable-length nonce support
+ * were to be exposed.
+ */
+static int heh_create_common(struct crypto_template *tmpl, struct rtattr **tb,
+			     const char *full_name, const char *cmac_name,
+			     const char *poly_hash_name, const char *ecb_name)
+{
+	struct crypto_attr_type *algt;
+	struct crypto_instance *inst;
+	struct heh_instance_ctx *ctx;
+	struct shash_alg *cmac;
+	struct shash_alg *poly_hash;
+	struct crypto_alg *ecb;
+	int err;
+
+	algt = crypto_get_attr_type(tb);
+	if (IS_ERR(algt))
+		return PTR_ERR(algt);
+
+	/* User must be asking for something compatible with ablkcipher */
+	if ((algt->type ^ CRYPTO_ALG_TYPE_ABLKCIPHER) & algt->mask)
+		return -EINVAL;
+
+	/* Allocate the ablkcipher instance */
+	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	ctx = crypto_instance_ctx(inst);
+
+	/* Set up the cmac spawn */
+	ctx->cmac.base.inst = inst;
+	err = crypto_grab_shash(&ctx->cmac, cmac_name, 0, 0);
+	if (err)
+		goto err_free_inst;
+	cmac = crypto_spawn_shash_alg(&ctx->cmac);
+	err = -EINVAL;
+	if (cmac->digestsize != HEH_BLOCK_SIZE)
+		goto err_drop_cmac;
+
+	/* Set up the poly_hash spawn */
+	ctx->poly_hash.base.inst = inst;
+	err = crypto_grab_shash(&ctx->poly_hash, poly_hash_name, 0, 0);
+	if (err)
+		goto err_drop_cmac;
+	poly_hash = crypto_spawn_shash_alg(&ctx->poly_hash);
+	err = -EINVAL;
+	if (poly_hash->digestsize != HEH_BLOCK_SIZE)
+		goto err_drop_poly_hash;
+
+	/* Set up the ecb spawn */
+	ctx->ecb.base.inst = inst;
+	err = crypto_grab_skcipher(&ctx->ecb, ecb_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
+	if (err)
+		goto err_drop_poly_hash;
+	ecb = crypto_skcipher_spawn_alg(&ctx->ecb);
+
+	/* HEH only supports block ciphers with 16 byte block size */
+	err = -EINVAL;
+	if (ecb->cra_blocksize != HEH_BLOCK_SIZE)
+		goto err_drop_ecb;
+
+	/* The underlying "ECB" algorithm must not require an IV */
+	err = -EINVAL;
+	if ((ecb->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_BLKCIPHER) {
+		if (ecb->cra_blkcipher.ivsize != 0)
+			goto err_drop_ecb;
+	} else {
+		if (ecb->cra_ablkcipher.ivsize != 0)
+			goto err_drop_ecb;
+	}
+
+	/* Set the instance names */
+	err = -ENAMETOOLONG;
+	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+		     "heh_base(%s,%s,%s)", cmac->base.cra_driver_name,
+		     poly_hash->base.cra_driver_name,
+		     ecb->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+		goto err_drop_ecb;
+
+	err = -ENAMETOOLONG;
+	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+		     "%s", full_name) >= CRYPTO_MAX_ALG_NAME)
+		goto err_drop_ecb;
+
+	/* Finish initializing the instance */
+
+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+				(ecb->cra_flags & CRYPTO_ALG_ASYNC);
+	inst->alg.cra_blocksize = HEH_BLOCK_SIZE;
+	inst->alg.cra_ctxsize = sizeof(struct heh_tfm_ctx);
+	inst->alg.cra_alignmask = ecb->cra_alignmask | (__alignof__(be128) - 1);
+	inst->alg.cra_priority = ecb->cra_priority;
+	inst->alg.cra_type = &crypto_ablkcipher_type;
+	inst->alg.cra_init = heh_init_tfm;
+	inst->alg.cra_exit = heh_exit_tfm;
+
+	inst->alg.cra_ablkcipher.setkey = heh_setkey;
+	inst->alg.cra_ablkcipher.encrypt = heh_encrypt;
+	inst->alg.cra_ablkcipher.decrypt = heh_decrypt;
+	if ((ecb->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_BLKCIPHER) {
+		inst->alg.cra_ablkcipher.min_keysize = ecb->cra_blkcipher.min_keysize;
+		inst->alg.cra_ablkcipher.max_keysize = ecb->cra_blkcipher.max_keysize;
+	} else {
+		inst->alg.cra_ablkcipher.min_keysize = ecb->cra_ablkcipher.min_keysize;
+		inst->alg.cra_ablkcipher.max_keysize = ecb->cra_ablkcipher.max_keysize;
+	}
+	inst->alg.cra_ablkcipher.ivsize = HEH_BLOCK_SIZE;
+
+	/* Register the instance */
+	err = crypto_register_instance(tmpl, inst);
+	if (err)
+		goto err_drop_ecb;
+	return 0;
+
+err_drop_ecb:
+	crypto_drop_skcipher(&ctx->ecb);
+err_drop_poly_hash:
+	crypto_drop_shash(&ctx->poly_hash);
+err_drop_cmac:
+	crypto_drop_shash(&ctx->cmac);
+err_free_inst:
+	kfree(inst);
+	return err;
+}
+
+static int heh_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	const char *cipher_name;
+	char full_name[CRYPTO_MAX_ALG_NAME];
+	char cmac_name[CRYPTO_MAX_ALG_NAME];
+	char ecb_name[CRYPTO_MAX_ALG_NAME];
+
+	/* Get the name of the requested block cipher (e.g. aes) */
+	cipher_name = crypto_attr_alg_name(tb[1]);
+	if (IS_ERR(cipher_name))
+		return PTR_ERR(cipher_name);
+
+	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "heh(%s)", cipher_name) >=
+	    CRYPTO_MAX_ALG_NAME)
+		return -ENAMETOOLONG;
+
+	if (snprintf(cmac_name, CRYPTO_MAX_ALG_NAME, "cmac(%s)", cipher_name) >=
+	    CRYPTO_MAX_ALG_NAME)
+		return -ENAMETOOLONG;
+
+	if (snprintf(ecb_name, CRYPTO_MAX_ALG_NAME, "ecb(%s)", cipher_name) >=
+	    CRYPTO_MAX_ALG_NAME)
+		return -ENAMETOOLONG;
+
+	return heh_create_common(tmpl, tb, full_name, cmac_name, "poly_hash",
+				 ecb_name);
+}
+
+static struct crypto_template heh_tmpl = {
+	.name = "heh",
+	.create = heh_create,
+	.free = heh_free_instance,
+	.module = THIS_MODULE,
+};
+
+static int heh_base_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	char full_name[CRYPTO_MAX_ALG_NAME];
+	const char *cmac_name;
+	const char *poly_hash_name;
+	const char *ecb_name;
+
+	cmac_name = crypto_attr_alg_name(tb[1]);
+	if (IS_ERR(cmac_name))
+		return PTR_ERR(cmac_name);
+
+	poly_hash_name = crypto_attr_alg_name(tb[2]);
+	if (IS_ERR(poly_hash_name))
+		return PTR_ERR(poly_hash_name);
+
+	ecb_name = crypto_attr_alg_name(tb[3]);
+	if (IS_ERR(ecb_name))
+		return PTR_ERR(ecb_name);
+
+	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "heh_base(%s,%s,%s)",
+		     cmac_name, poly_hash_name, ecb_name) >=
+	    CRYPTO_MAX_ALG_NAME)
+		return -ENAMETOOLONG;
+
+	return heh_create_common(tmpl, tb, full_name, cmac_name, poly_hash_name,
+				 ecb_name);
+}
+
+/*
+ * If HEH is instantiated as "heh_base" instead of "heh", then specific
+ * implementations of cmac, poly_hash, and ecb can be specified instead of just
+ * the cipher.
+ */
+static struct crypto_template heh_base_tmpl = {
+	.name = "heh_base",
+	.create = heh_base_create,
+	.free = heh_free_instance,
+	.module = THIS_MODULE,
+};
+
+static int __init heh_module_init(void)
+{
+	int err;
+
+	err = crypto_register_template(&heh_tmpl);
+	if (err)
+		return err;
+
+	err = crypto_register_template(&heh_base_tmpl);
+	if (err)
+		goto out_undo_heh;
+
+	err = crypto_register_shash(&poly_hash_alg);
+	if (err)
+		goto out_undo_heh_base;
+
+	return 0;
+
+out_undo_heh_base:
+	crypto_unregister_template(&heh_base_tmpl);
+out_undo_heh:
+	crypto_unregister_template(&heh_tmpl);
+	return err;
+}
+
+static void __exit heh_module_exit(void)
+{
+	crypto_unregister_template(&heh_tmpl);
+	crypto_unregister_template(&heh_base_tmpl);
+	crypto_unregister_shash(&poly_hash_alg);
+}
+
+module_init(heh_module_init);
+module_exit(heh_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Hash-Encrypt-Hash block cipher mode");
+MODULE_ALIAS_CRYPTO("heh");
+MODULE_ALIAS_CRYPTO("heh_base");
diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c
index fe5b495a..b4f3930 100644
--- a/crypto/mcryptd.c
+++ b/crypto/mcryptd.c
@@ -258,18 +258,22 @@
 	goto out;
 }
 
-static inline void mcryptd_check_internal(struct rtattr **tb, u32 *type,
+static inline bool mcryptd_check_internal(struct rtattr **tb, u32 *type,
 					  u32 *mask)
 {
 	struct crypto_attr_type *algt;
 
 	algt = crypto_get_attr_type(tb);
 	if (IS_ERR(algt))
-		return;
-	if ((algt->type & CRYPTO_ALG_INTERNAL))
-		*type |= CRYPTO_ALG_INTERNAL;
-	if ((algt->mask & CRYPTO_ALG_INTERNAL))
-		*mask |= CRYPTO_ALG_INTERNAL;
+		return false;
+
+	*type |= algt->type & CRYPTO_ALG_INTERNAL;
+	*mask |= algt->mask & CRYPTO_ALG_INTERNAL;
+
+	if (*type & *mask & CRYPTO_ALG_INTERNAL)
+		return true;
+	else
+		return false;
 }
 
 static int mcryptd_hash_init_tfm(struct crypto_tfm *tfm)
@@ -498,7 +502,8 @@
 	u32 mask = 0;
 	int err;
 
-	mcryptd_check_internal(tb, &type, &mask);
+	if (!mcryptd_check_internal(tb, &type, &mask))
+		return -EINVAL;
 
 	salg = shash_attr_alg(tb[1], type, mask);
 	if (IS_ERR(salg))
@@ -526,6 +531,7 @@
 	inst->alg.halg.base.cra_flags = type;
 
 	inst->alg.halg.digestsize = salg->digestsize;
+	inst->alg.halg.statesize = salg->statesize;
 	inst->alg.halg.base.cra_ctxsize = sizeof(struct mcryptd_hash_ctx);
 
 	inst->alg.halg.base.cra_init = mcryptd_hash_init_tfm;
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index ea5815c..bc769c4 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -72,7 +72,8 @@
 
 void scatterwalk_done(struct scatter_walk *walk, int out, int more)
 {
-	if (!(scatterwalk_pagelen(walk) & (PAGE_SIZE - 1)) || !more)
+	if (!more || walk->offset >= walk->sg->offset + walk->sg->length ||
+	    !(walk->offset & (PAGE_SIZE - 1)))
 		scatterwalk_pagedone(walk, out, more);
 }
 EXPORT_SYMBOL_GPL(scatterwalk_done);
diff --git a/crypto/shash.c b/crypto/shash.c
index 3597545..9ae1e89 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -683,6 +683,14 @@
 }
 EXPORT_SYMBOL_GPL(shash_free_instance);
 
+int crypto_grab_shash(struct crypto_shash_spawn *spawn,
+		      const char *name, u32 type, u32 mask)
+{
+	spawn->base.frontend = &crypto_shash_type;
+	return crypto_grab_spawn(&spawn->base, name, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_grab_shash);
+
 int crypto_init_shash_spawn(struct crypto_shash_spawn *spawn,
 			    struct shash_alg *alg,
 			    struct crypto_instance *inst)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index ae8c57fd..6d4da8f 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -488,6 +488,8 @@
 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				  tcrypt_complete, &result);
 
+	iv_len = crypto_aead_ivsize(tfm);
+
 	for (i = 0, j = 0; i < tcount; i++) {
 		if (template[i].np)
 			continue;
@@ -508,7 +510,6 @@
 
 		memcpy(input, template[i].input, template[i].ilen);
 		memcpy(assoc, template[i].assoc, template[i].alen);
-		iv_len = crypto_aead_ivsize(tfm);
 		if (template[i].iv)
 			memcpy(iv, template[i].iv, iv_len);
 		else
@@ -617,7 +618,7 @@
 		j++;
 
 		if (template[i].iv)
-			memcpy(iv, template[i].iv, MAX_IVLEN);
+			memcpy(iv, template[i].iv, iv_len);
 		else
 			memset(iv, 0, MAX_IVLEN);
 
@@ -1849,6 +1850,7 @@
 static int do_test_rsa(struct crypto_akcipher *tfm,
 		       struct akcipher_testvec *vecs)
 {
+	char *xbuf[XBUFSIZE];
 	struct akcipher_request *req;
 	void *outbuf_enc = NULL;
 	void *outbuf_dec = NULL;
@@ -1857,9 +1859,12 @@
 	int err = -ENOMEM;
 	struct scatterlist src, dst, src_tab[2];
 
+	if (testmgr_alloc_buf(xbuf))
+		return err;
+
 	req = akcipher_request_alloc(tfm, GFP_KERNEL);
 	if (!req)
-		return err;
+		goto free_xbuf;
 
 	init_completion(&result.completion);
 
@@ -1877,9 +1882,14 @@
 	if (!outbuf_enc)
 		goto free_req;
 
+	if (WARN_ON(vecs->m_size > PAGE_SIZE))
+		goto free_all;
+
+	memcpy(xbuf[0], vecs->m, vecs->m_size);
+
 	sg_init_table(src_tab, 2);
-	sg_set_buf(&src_tab[0], vecs->m, 8);
-	sg_set_buf(&src_tab[1], vecs->m + 8, vecs->m_size - 8);
+	sg_set_buf(&src_tab[0], xbuf[0], 8);
+	sg_set_buf(&src_tab[1], xbuf[0] + 8, vecs->m_size - 8);
 	sg_init_one(&dst, outbuf_enc, out_len_max);
 	akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size,
 				   out_len_max);
@@ -1898,7 +1908,7 @@
 		goto free_all;
 	}
 	/* verify that encrypted message is equal to expected */
-	if (memcmp(vecs->c, sg_virt(req->dst), vecs->c_size)) {
+	if (memcmp(vecs->c, outbuf_enc, vecs->c_size)) {
 		pr_err("alg: rsa: encrypt test failed. Invalid output\n");
 		err = -EINVAL;
 		goto free_all;
@@ -1913,7 +1923,13 @@
 		err = -ENOMEM;
 		goto free_all;
 	}
-	sg_init_one(&src, vecs->c, vecs->c_size);
+
+	if (WARN_ON(vecs->c_size > PAGE_SIZE))
+		goto free_all;
+
+	memcpy(xbuf[0], vecs->c, vecs->c_size);
+
+	sg_init_one(&src, xbuf[0], vecs->c_size);
 	sg_init_one(&dst, outbuf_dec, out_len_max);
 	init_completion(&result.completion);
 	akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max);
@@ -1940,6 +1956,8 @@
 	kfree(outbuf_enc);
 free_req:
 	akcipher_request_free(req);
+free_xbuf:
+	testmgr_free_buf(xbuf);
 	return err;
 }
 
@@ -3197,6 +3215,21 @@
 			}
 		}
 	}, {
+		.alg = "heh(aes)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = aes_heh_enc_tv_template,
+					.count = AES_HEH_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = aes_heh_dec_tv_template,
+					.count = AES_HEH_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "hmac(crc32)",
 		.test = alg_test_hash,
 		.suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index da0a8fd..ba6530d 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -14139,6 +14139,8 @@
 #define AES_DEC_TEST_VECTORS 4
 #define AES_CBC_ENC_TEST_VECTORS 5
 #define AES_CBC_DEC_TEST_VECTORS 5
+#define AES_HEH_ENC_TEST_VECTORS 4
+#define AES_HEH_DEC_TEST_VECTORS 4
 #define HMAC_MD5_ECB_CIPHER_NULL_ENC_TEST_VECTORS 2
 #define HMAC_MD5_ECB_CIPHER_NULL_DEC_TEST_VECTORS 2
 #define HMAC_SHA1_ECB_CIPHER_NULL_ENC_TEST_VEC 2
@@ -14511,6 +14513,198 @@
 	},
 };
 
+static struct cipher_testvec aes_heh_enc_tv_template[] = {
+	{
+		.key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+		.klen   = 16,
+		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+		.ilen   = 16,
+		.result = "\xd8\xbd\x40\xbf\xca\xe5\xee\x81"
+			  "\x0f\x3d\x1f\x1f\xae\x89\x07\x55",
+		.rlen   = 16,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 8, 8 },
+	}, {
+		.key    = "\xa8\xda\x24\x9b\x5e\xfa\x13\xc2"
+			  "\xc1\x94\xbf\x32\xba\x38\xa3\x77",
+		.klen   = 16,
+		.iv	= "\x4d\x47\x61\x37\x2b\x47\x86\xf0"
+			  "\xd6\x47\xb5\xc2\xe8\xcf\x85\x27",
+		.input	= "\xb8\xee\x29\xe4\xa5\xd1\xe7\x55"
+			  "\xd0\xfd\xe7\x22\x63\x76\x36\xe2"
+			  "\xf8\x0c\xf8\xfe\x65\x76\xe7\xca"
+			  "\xc1\x42\xf5\xca\x5a\xa8\xac\x2a",
+		.ilen   = 32,
+		.result = "\x59\xf2\x78\x4e\x10\x94\xf9\x5c"
+			  "\x22\x23\x78\x2a\x30\x48\x11\x97"
+			  "\xb1\xfe\x70\xc4\xef\xdf\x04\xef"
+			  "\x16\x39\x04\xcf\xc0\x95\x9a\x98",
+		.rlen   = 32,
+		.also_non_np = 1,
+		.np	= 3,
+		.tap	= { 16, 13, 3 },
+	}, {
+		.key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+		.klen   = 16,
+		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00",
+		.ilen   = 63,
+		.result = "\xe0\x40\xeb\xe9\x52\xbe\x65\x60"
+			  "\xe4\x68\x68\xa3\x73\x75\xb8\x52"
+			  "\xef\x38\x6a\x87\x25\x25\xf6\x04"
+			  "\xe5\x8e\xbe\x14\x8b\x02\x14\x1f"
+			  "\xa9\x73\xb7\xad\x15\xbe\x9c\xa0"
+			  "\xd2\x8a\x2c\xdc\xd4\xe3\x05\x55"
+			  "\x0a\xf5\xf8\x51\xee\xe5\x62\xa5"
+			  "\x71\xa7\x7c\x15\x5d\x7a\x9e",
+		.rlen   = 63,
+		.also_non_np = 1,
+		.np	= 8,
+		.tap	= { 20, 20, 10, 8, 2, 1, 1, 1 },
+	}, {
+		.key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
+			  "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
+			  "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+		.klen   = 16,
+		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x01"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00",
+		.ilen   = 63,
+		.result = "\x4b\x1a\x15\xa0\xaf\x08\x6d\x70"
+			  "\xf0\xa7\x97\xb5\x31\x4b\x8c\xc3"
+			  "\x4d\xf2\x7a\x9d\xdd\xd4\x15\x99"
+			  "\x57\xad\xc6\xb1\x35\x69\xf5\x6a"
+			  "\x2d\x70\xe4\x97\x49\xb2\x9f\x71"
+			  "\xde\x22\xb5\x70\x8c\x69\x24\xd3"
+			  "\xad\x80\x58\x48\x90\xe4\xed\xba"
+			  "\x76\x3d\x71\x7c\x57\x25\x87",
+		.rlen   = 63,
+		.also_non_np = 1,
+		.np	= 8,
+		.tap	= { 20, 20, 10, 8, 2, 1, 1, 1 },
+	}
+};
+
+static struct cipher_testvec aes_heh_dec_tv_template[] = {
+	{
+		.key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+		.klen   = 16,
+		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input = "\xd8\xbd\x40\xbf\xca\xe5\xee\x81"
+			  "\x0f\x3d\x1f\x1f\xae\x89\x07\x55",
+		.ilen   = 16,
+		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+		.rlen   = 16,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 8, 8 },
+	}, {
+		.key    = "\xa8\xda\x24\x9b\x5e\xfa\x13\xc2"
+			  "\xc1\x94\xbf\x32\xba\x38\xa3\x77",
+		.klen   = 16,
+		.iv	= "\x4d\x47\x61\x37\x2b\x47\x86\xf0"
+			  "\xd6\x47\xb5\xc2\xe8\xcf\x85\x27",
+		.input = "\x59\xf2\x78\x4e\x10\x94\xf9\x5c"
+			  "\x22\x23\x78\x2a\x30\x48\x11\x97"
+			  "\xb1\xfe\x70\xc4\xef\xdf\x04\xef"
+			  "\x16\x39\x04\xcf\xc0\x95\x9a\x98",
+		.ilen   = 32,
+		.result	= "\xb8\xee\x29\xe4\xa5\xd1\xe7\x55"
+			  "\xd0\xfd\xe7\x22\x63\x76\x36\xe2"
+			  "\xf8\x0c\xf8\xfe\x65\x76\xe7\xca"
+			  "\xc1\x42\xf5\xca\x5a\xa8\xac\x2a",
+		.rlen   = 32,
+		.also_non_np = 1,
+		.np	= 3,
+		.tap	= { 16, 13, 3 },
+	}, {
+		.key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+		.klen   = 16,
+		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input = "\xe0\x40\xeb\xe9\x52\xbe\x65\x60"
+			  "\xe4\x68\x68\xa3\x73\x75\xb8\x52"
+			  "\xef\x38\x6a\x87\x25\x25\xf6\x04"
+			  "\xe5\x8e\xbe\x14\x8b\x02\x14\x1f"
+			  "\xa9\x73\xb7\xad\x15\xbe\x9c\xa0"
+			  "\xd2\x8a\x2c\xdc\xd4\xe3\x05\x55"
+			  "\x0a\xf5\xf8\x51\xee\xe5\x62\xa5"
+			  "\x71\xa7\x7c\x15\x5d\x7a\x9e",
+		.ilen   = 63,
+		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00",
+		.rlen   = 63,
+		.also_non_np = 1,
+		.np	= 8,
+		.tap	= { 20, 20, 10, 8, 2, 1, 1, 1 },
+	}, {
+		.key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
+			  "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
+			  "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+		.klen   = 16,
+		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input = "\x4b\x1a\x15\xa0\xaf\x08\x6d\x70"
+			  "\xf0\xa7\x97\xb5\x31\x4b\x8c\xc3"
+			  "\x4d\xf2\x7a\x9d\xdd\xd4\x15\x99"
+			  "\x57\xad\xc6\xb1\x35\x69\xf5\x6a"
+			  "\x2d\x70\xe4\x97\x49\xb2\x9f\x71"
+			  "\xde\x22\xb5\x70\x8c\x69\x24\xd3"
+			  "\xad\x80\x58\x48\x90\xe4\xed\xba"
+			  "\x76\x3d\x71\x7c\x57\x25\x87",
+		.ilen   = 63,
+		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x01"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00",
+		.rlen   = 63,
+		.also_non_np = 1,
+		.np	= 8,
+		.tap	= { 20, 20, 10, 8, 2, 1, 1, 1 },
+	}
+};
+
 static struct cipher_testvec aes_cbc_enc_tv_template[] = {
 	{ /* From RFC 3602 */
 		.key    = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
@@ -21778,7 +21972,7 @@
 			  "\x09\x75\x9a\x9b\x3c\x9b\x27\x39",
 		.klen	= 32,
 		.iv	= "\x03\xf9\xd9\x4e\x63\xb5\x3d\x9d"
-			  "\x43\xf6\x1e\x50",
+			  "\x43\xf6\x1e\x50\0\0\0\0",
 		.assoc	= "\x57\xf5\x6b\x8b\x57\x5c\x3d\x3b"
 			  "\x13\x02\x01\x0c\x83\x4c\x96\x35"
 			  "\x8e\xd6\x39\xcf\x7d\x14\x9b\x94"
diff --git a/drivers/Makefile b/drivers/Makefile
index 795d0ca..098997f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -98,6 +98,7 @@
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_PCI)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/
+obj-$(CONFIG_OF)		+= usb/
 obj-$(CONFIG_SERIO)		+= input/serio/
 obj-$(CONFIG_GAMEPORT)		+= input/gameport/
 obj-$(CONFIG_INPUT)		+= input/
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 675eaf3..b9cebca 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -2,7 +2,6 @@
 # Makefile for the Linux ACPI interpreter
 #
 
-ccflags-y			:= -Os
 ccflags-$(CONFIG_ACPI_DEBUG)	+= -DACPI_DEBUG_OUTPUT
 
 #
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index 296b7a1..5365ff6 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -24,9 +24,11 @@
 ACPI_MODULE_NAME("platform");
 
 static const struct acpi_device_id forbidden_id_list[] = {
-	{"PNP0000", 0},	/* PIC */
-	{"PNP0100", 0},	/* Timer */
-	{"PNP0200", 0},	/* AT DMA Controller */
+	{"PNP0000",  0},	/* PIC */
+	{"PNP0100",  0},	/* Timer */
+	{"PNP0200",  0},	/* AT DMA Controller */
+	{"ACPI0009", 0},	/* IOxAPIC */
+	{"ACPI000A", 0},	/* IOAPIC */
 	{"", 0},
 };
 
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index 5fdac39..549cdbe 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -1211,6 +1211,9 @@
 	union acpi_object *dod = NULL;
 	union acpi_object *obj;
 
+	if (!video->cap._DOD)
+		return AE_NOT_EXIST;
+
 	status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer);
 	if (!ACPI_SUCCESS(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD"));
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index 5f97468..b2e50d8 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -504,11 +504,20 @@
 	 * Evaluate the \_Sx namespace object containing the register values
 	 * for this state
 	 */
-	info->relative_pathname =
-	    ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
+	info->relative_pathname = ACPI_CAST_PTR(char,
+						acpi_gbl_sleep_state_names
+						[sleep_state]);
+
 	status = acpi_ns_evaluate(info);
 	if (ACPI_FAILURE(status)) {
-		goto cleanup;
+		if (status == AE_NOT_FOUND) {
+
+			/* The _Sx states are optional, ignore NOT_FOUND */
+
+			goto final_cleanup;
+		}
+
+		goto warning_cleanup;
 	}
 
 	/* Must have a return object */
@@ -517,7 +526,7 @@
 		ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
 			    info->relative_pathname));
 		status = AE_AML_NO_RETURN_VALUE;
-		goto cleanup;
+		goto warning_cleanup;
 	}
 
 	/* Return object must be of type Package */
@@ -526,7 +535,7 @@
 		ACPI_ERROR((AE_INFO,
 			    "Sleep State return object is not a Package"));
 		status = AE_AML_OPERAND_TYPE;
-		goto cleanup1;
+		goto return_value_cleanup;
 	}
 
 	/*
@@ -570,16 +579,17 @@
 		break;
 	}
 
-cleanup1:
+return_value_cleanup:
 	acpi_ut_remove_reference(info->return_object);
 
-cleanup:
+warning_cleanup:
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status,
 				"While evaluating Sleep State [%s]",
 				info->relative_pathname));
 	}
 
+final_cleanup:
 	ACPI_FREE(info);
 	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 3dd9c46..eac4f3b 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -657,7 +657,7 @@
 	ghes_do_proc(ghes, ghes->estatus);
 out:
 	ghes_clear_estatus(ghes);
-	return 0;
+	return rc;
 }
 
 static void ghes_add_timer(struct ghes *ghes)
@@ -847,6 +847,8 @@
 		if (ghes_read_estatus(ghes, 1)) {
 			ghes_clear_estatus(ghes);
 			continue;
+		} else {
+			ret = NMI_HANDLED;
 		}
 
 		sev = ghes_severity(ghes->estatus->error_severity);
@@ -858,12 +860,11 @@
 
 		__process_error(ghes);
 		ghes_clear_estatus(ghes);
-
-		ret = NMI_HANDLED;
 	}
 
 #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
-	irq_work_queue(&ghes_proc_irq_work);
+	if (ret == NMI_HANDLED)
+		irq_work_queue(&ghes_proc_irq_work);
 #endif
 	atomic_dec(&ghes_in_nmi);
 	return ret;
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 96809cd..2f24b57 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -346,6 +346,34 @@
 		      DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343"),
 		},
 	},
+	{
+	 .callback = dmi_enable_rev_override,
+	 .ident = "DELL Precision 5520",
+	 .matches = {
+		      DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		      DMI_MATCH(DMI_PRODUCT_NAME, "Precision 5520"),
+		},
+	},
+	{
+	 .callback = dmi_enable_rev_override,
+	 .ident = "DELL Precision 3520",
+	 .matches = {
+		      DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		      DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3520"),
+		},
+	},
+	/*
+	 * Resolves a quirk with the Dell Latitude 3350 that
+	 * causes the ethernet adapter to not function.
+	 */
+	{
+	 .callback = dmi_enable_rev_override,
+	 .ident = "DELL Latitude 3350",
+	 .matches = {
+		      DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		      DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 3350"),
+		},
+	},
 #endif
 	{}
 };
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 6730f96..0afd198 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -216,8 +216,10 @@
 			continue;
 
 		cpc_ptr = per_cpu(cpc_desc_ptr, i);
-		if (!cpc_ptr)
-			continue;
+		if (!cpc_ptr) {
+			retval = -EFAULT;
+			goto err_ret;
+		}
 
 		pdomain = &(cpc_ptr->domain_info);
 		cpumask_set_cpu(i, pr->shared_cpu_map);
@@ -239,8 +241,10 @@
 				continue;
 
 			match_cpc_ptr = per_cpu(cpc_desc_ptr, j);
-			if (!match_cpc_ptr)
-				continue;
+			if (!match_cpc_ptr) {
+				retval = -EFAULT;
+				goto err_ret;
+			}
 
 			match_pdomain = &(match_cpc_ptr->domain_info);
 			if (match_pdomain->domain != pdomain->domain)
@@ -270,8 +274,10 @@
 				continue;
 
 			match_cpc_ptr = per_cpu(cpc_desc_ptr, j);
-			if (!match_cpc_ptr)
-				continue;
+			if (!match_cpc_ptr) {
+				retval = -EFAULT;
+				goto err_ret;
+			}
 
 			match_pdomain = &(match_cpc_ptr->domain_info);
 			if (match_pdomain->domain != pdomain->domain)
@@ -502,9 +508,6 @@
 	/* Store CPU Logical ID */
 	cpc_ptr->cpu_id = pr->id;
 
-	/* Plug it into this CPUs CPC descriptor. */
-	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
-
 	/* Parse PSD data for this CPU */
 	ret = acpi_get_psd(cpc_ptr, handle);
 	if (ret)
@@ -517,6 +520,9 @@
 			goto out_free;
 	}
 
+	/* Plug PSD data into this CPUs CPC descriptor. */
+	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
+
 	/* Everything looks okay */
 	pr_debug("Parsed CPC struct for CPU: %d\n", pr->id);
 
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index b420fb4..43f2032 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -101,6 +101,7 @@
 #define ACPI_EC_UDELAY_POLL	550	/* Wait 1ms for EC transaction polling */
 #define ACPI_EC_CLEAR_MAX	100	/* Maximum number of events to query
 					 * when trying to clear the EC */
+#define ACPI_EC_MAX_QUERIES	16	/* Maximum number of parallel queries */
 
 enum {
 	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
@@ -121,6 +122,10 @@
 module_param(ec_delay, uint, 0644);
 MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
 
+static unsigned int ec_max_queries __read_mostly = ACPI_EC_MAX_QUERIES;
+module_param(ec_max_queries, uint, 0644);
+MODULE_PARM_DESC(ec_max_queries, "Maximum parallel _Qxx evaluations");
+
 static bool ec_busy_polling __read_mostly;
 module_param(ec_busy_polling, bool, 0644);
 MODULE_PARM_DESC(ec_busy_polling, "Use busy polling to advance EC transaction");
@@ -174,6 +179,7 @@
 
 struct acpi_ec *boot_ec, *first_ec;
 EXPORT_SYMBOL(first_ec);
+static struct workqueue_struct *ec_query_wq;
 
 static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
 static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
@@ -1097,7 +1103,7 @@
 	 * work queue execution.
 	 */
 	ec_dbg_evt("Query(0x%02x) scheduled", value);
-	if (!schedule_work(&q->work)) {
+	if (!queue_work(ec_query_wq, &q->work)) {
 		ec_dbg_evt("Query(0x%02x) overlapped", value);
 		result = -EBUSY;
 	}
@@ -1657,15 +1663,41 @@
 		},
 };
 
+static inline int acpi_ec_query_init(void)
+{
+	if (!ec_query_wq) {
+		ec_query_wq = alloc_workqueue("kec_query", 0,
+					      ec_max_queries);
+		if (!ec_query_wq)
+			return -ENODEV;
+	}
+	return 0;
+}
+
+static inline void acpi_ec_query_exit(void)
+{
+	if (ec_query_wq) {
+		destroy_workqueue(ec_query_wq);
+		ec_query_wq = NULL;
+	}
+}
+
 int __init acpi_ec_init(void)
 {
-	int result = 0;
+	int result;
 
+	/* register workqueue for _Qxx evaluations */
+	result = acpi_ec_query_init();
+	if (result)
+		goto err_exit;
 	/* Now register the driver for the EC */
 	result = acpi_bus_register_driver(&acpi_ec_driver);
-	if (result < 0)
-		return -ENODEV;
+	if (result)
+		goto err_exit;
 
+err_exit:
+	if (result)
+		acpi_ec_query_exit();
 	return result;
 }
 
@@ -1675,5 +1707,6 @@
 {
 
 	acpi_bus_unregister_driver(&acpi_ec_driver);
+	acpi_ec_query_exit();
 }
 #endif	/* 0 */
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index 11d8209..67d7489 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -965,7 +965,7 @@
 		+ num_mappings * sizeof(struct nfit_set_info_map);
 }
 
-static int cmp_map(const void *m0, const void *m1)
+static int cmp_map_compat(const void *m0, const void *m1)
 {
 	const struct nfit_set_info_map *map0 = m0;
 	const struct nfit_set_info_map *map1 = m1;
@@ -974,6 +974,18 @@
 			sizeof(u64));
 }
 
+static int cmp_map(const void *m0, const void *m1)
+{
+	const struct nfit_set_info_map *map0 = m0;
+	const struct nfit_set_info_map *map1 = m1;
+
+	if (map0->region_offset < map1->region_offset)
+		return -1;
+	else if (map0->region_offset > map1->region_offset)
+		return 1;
+	return 0;
+}
+
 /* Retrieve the nth entry referencing this spa */
 static struct acpi_nfit_memory_map *memdev_from_spa(
 		struct acpi_nfit_desc *acpi_desc, u16 range_index, int n)
@@ -1029,6 +1041,12 @@
 	sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
 			cmp_map, NULL);
 	nd_set->cookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
+
+	/* support namespaces created with the wrong sort order */
+	sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
+			cmp_map_compat, NULL);
+	nd_set->altcookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
+
 	ndr_desc->nd_set = nd_set;
 	devm_kfree(dev, info);
 
@@ -1072,11 +1090,12 @@
 {
 	struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR];
 	u64 offset = nfit_blk->stat_offset + mmio->size * bw;
+	const u32 STATUS_MASK = 0x80000037;
 
 	if (mmio->num_lines)
 		offset = to_interleave_offset(offset, mmio);
 
-	return readl(mmio->addr.base + offset);
+	return readl(mmio->addr.base + offset) & STATUS_MASK;
 }
 
 static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw,
@@ -1805,6 +1824,9 @@
 
 	dev_dbg(dev, "%s: event: %d\n", __func__, event);
 
+	if (event != NFIT_NOTIFY_UPDATE)
+		return;
+
 	device_lock(dev);
 	if (!dev->driver) {
 		/* dev->driver may be null if we're being removed */
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h
index 3d549a3..13d6ec1 100644
--- a/drivers/acpi/nfit.h
+++ b/drivers/acpi/nfit.h
@@ -45,6 +45,10 @@
 	ND_BLK_DCR_LATCH = 2,
 };
 
+enum nfit_root_notifiers {
+	NFIT_NOTIFY_UPDATE = 0x80,
+};
+
 struct nfit_spa {
 	struct acpi_nfit_system_address *spa;
 	struct list_head list;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 72b6e9e..d176e0e 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -327,10 +327,18 @@
 
 	/* SRAT: Static Resource Affinity Table */
 	if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
-		acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
-				     acpi_parse_x2apic_affinity, 0);
-		acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
-				     acpi_parse_processor_affinity, 0);
+		struct acpi_subtable_proc srat_proc[2];
+
+		memset(srat_proc, 0, sizeof(srat_proc));
+		srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
+		srat_proc[0].handler = acpi_parse_processor_affinity;
+		srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY;
+		srat_proc[1].handler = acpi_parse_x2apic_affinity;
+
+		acpi_table_parse_entries_array(ACPI_SIG_SRAT,
+					sizeof(struct acpi_table_srat),
+					srat_proc, ARRAY_SIZE(srat_proc), 0);
+
 		cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
 					    acpi_parse_memory_affinity,
 					    NR_NODE_MEMBLKS);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 32d684a..a000ecb 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -135,7 +135,7 @@
 	unsigned int	enable:1;
 	unsigned int	dmi:1;
 	unsigned int	cmdline:1;
-	unsigned int	default_disabling:1;
+	u8		default_disabling;
 } osi_linux = {0, 0, 0, 0};
 
 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
@@ -1444,10 +1444,13 @@
 	if (*str == '!') {
 		str++;
 		if (*str == '\0') {
-			osi_linux.default_disabling = 1;
+			/* Do not override acpi_osi=!* */
+			if (!osi_linux.default_disabling)
+				osi_linux.default_disabling =
+					ACPI_DISABLE_ALL_VENDOR_STRINGS;
 			return;
 		} else if (*str == '*') {
-			acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS);
+			osi_linux.default_disabling = ACPI_DISABLE_ALL_STRINGS;
 			for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
 				osi = &osi_setup_entries[i];
 				osi->enable = false;
@@ -1520,10 +1523,13 @@
 	acpi_status status;
 
 	if (osi_linux.default_disabling) {
-		status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
+		status = acpi_update_interfaces(osi_linux.default_disabling);
 
 		if (ACPI_SUCCESS(status))
-			printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n");
+			printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors%s\n",
+				osi_linux.default_disabling ==
+				ACPI_DISABLE_ALL_STRINGS ?
+				" and feature groups" : "");
 	}
 
 	for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index fcd4ce6..1c2b846 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -200,6 +200,7 @@
 		return -EINVAL;
 
 	/* The state of the list is 'on' IFF all resources are 'on'. */
+	cur_state = 0;
 	list_for_each_entry(entry, list, node) {
 		struct acpi_power_resource *resource = entry->resource;
 		acpi_handle handle = resource->device.handle;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 78d5f02..dcb3d62 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1958,7 +1958,7 @@
 
 static struct acpi_probe_entry *ape;
 static int acpi_probe_count;
-static DEFINE_SPINLOCK(acpi_probe_lock);
+static DEFINE_MUTEX(acpi_probe_mutex);
 
 static int __init acpi_match_madt(struct acpi_subtable_header *header,
 				  const unsigned long end)
@@ -1977,7 +1977,7 @@
 	if (acpi_disabled)
 		return 0;
 
-	spin_lock(&acpi_probe_lock);
+	mutex_lock(&acpi_probe_mutex);
 	for (ape = ap_head; nr; ape++, nr--) {
 		if (ACPI_COMPARE_NAME(ACPI_SIG_MADT, ape->id)) {
 			acpi_probe_count = 0;
@@ -1990,7 +1990,7 @@
 				count++;
 		}
 	}
-	spin_unlock(&acpi_probe_lock);
+	mutex_unlock(&acpi_probe_mutex);
 
 	return count;
 }
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 0243d37..4b3a9e2 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -555,23 +555,22 @@
 static int get_status(u32 index, acpi_event_status *status,
 		      acpi_handle *handle)
 {
-	int result = 0;
+	int result;
 
 	if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
-		goto end;
+		return -EINVAL;
 
 	if (index < num_gpes) {
 		result = acpi_get_gpe_device(index, handle);
 		if (result) {
 			ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND,
 					"Invalid GPE 0x%x", index));
-			goto end;
+			return result;
 		}
 		result = acpi_get_gpe_status(*handle, index, status);
 	} else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS))
 		result = acpi_get_event_status(index - num_gpes, status);
 
-end:
 	return result;
 }
 
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 80e55cb..b48ecbf 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -271,6 +271,26 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro12,1"),
 		},
 	},
+	{
+	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1123661 */
+	 .callback = video_detect_force_native,
+	 .ident = "Dell XPS 17 L702X",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"),
+		},
+	},
+	{
+	/* https://bugzilla.redhat.com/show_bug.cgi?id=1204476 */
+	/* https://bugs.launchpad.net/ubuntu/+source/linux-lts-trusty/+bug/1416940 */
+	.callback = video_detect_force_native,
+	.ident = "HP Pavilion dv6",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6 Notebook PC"),
+		},
+	},
+
 	{ },
 };
 
diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index bdfc6c6..4d4cdc1 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -19,6 +19,18 @@
 	  Android process, using Binder to identify, invoke and pass arguments
 	  between said processes.
 
+config ANDROID_BINDER_DEVICES
+	string "Android Binder devices"
+	depends on ANDROID_BINDER_IPC
+	default "binder,hwbinder,vndbinder"
+	---help---
+	  Default value for the binder.devices parameter.
+
+	  The binder.devices parameter is a comma-separated list of strings
+	  that specifies the names of the binder device nodes that will be
+	  created. Each binder device has its own context manager, and is
+	  therefore logically separated from the other devices.
+
 config ANDROID_BINDER_IPC_32BIT
 	bool
 	depends on !64BIT && ANDROID_BINDER_IPC
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index 3b7e4b0..4b7c726 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -1,3 +1,3 @@
 ccflags-y += -I$(src)			# needed for trace events
 
-obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o
+obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 57f52a2..6b24f70 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -15,6 +15,40 @@
  *
  */
 
+/*
+ * Locking overview
+ *
+ * There are 3 main spinlocks which must be acquired in the
+ * order shown:
+ *
+ * 1) proc->outer_lock : protects binder_ref
+ *    binder_proc_lock() and binder_proc_unlock() are
+ *    used to acq/rel.
+ * 2) node->lock : protects most fields of binder_node.
+ *    binder_node_lock() and binder_node_unlock() are
+ *    used to acq/rel
+ * 3) proc->inner_lock : protects the thread and node lists
+ *    (proc->threads, proc->waiting_threads, proc->nodes)
+ *    and all todo lists associated with the binder_proc
+ *    (proc->todo, thread->todo, proc->delivered_death and
+ *    node->async_todo), as well as thread->transaction_stack
+ *    binder_inner_proc_lock() and binder_inner_proc_unlock()
+ *    are used to acq/rel
+ *
+ * Any lock under procA must never be nested under any lock at the same
+ * level or below on procB.
+ *
+ * Functions that require a lock held on entry indicate which lock
+ * in the suffix of the function name:
+ *
+ * foo_olocked() : requires node->outer_lock
+ * foo_nlocked() : requires node->lock
+ * foo_ilocked() : requires proc->inner_lock
+ * foo_oilocked(): requires proc->outer_lock and proc->inner_lock
+ * foo_nilocked(): requires node->lock and proc->inner_lock
+ * ...
+ */
+
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <asm/cacheflush.h>
@@ -24,7 +58,6 @@
 #include <linux/fs.h>
 #include <linux/list.h>
 #include <linux/miscdevice.h>
-#include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/nsproxy.h>
@@ -34,31 +67,31 @@
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
 #include <linux/pid_namespace.h>
 #include <linux/security.h>
+#include <linux/spinlock.h>
 
 #ifdef CONFIG_ANDROID_BINDER_IPC_32BIT
 #define BINDER_IPC_32BIT 1
 #endif
 
 #include <uapi/linux/android/binder.h>
+#include "binder_alloc.h"
 #include "binder_trace.h"
 
-static DEFINE_MUTEX(binder_main_lock);
-static DEFINE_MUTEX(binder_deferred_lock);
-static DEFINE_MUTEX(binder_mmap_lock);
-
-static HLIST_HEAD(binder_procs);
 static HLIST_HEAD(binder_deferred_list);
+static DEFINE_MUTEX(binder_deferred_lock);
+
+static HLIST_HEAD(binder_devices);
+static HLIST_HEAD(binder_procs);
+static DEFINE_MUTEX(binder_procs_lock);
+
 static HLIST_HEAD(binder_dead_nodes);
+static DEFINE_SPINLOCK(binder_dead_nodes_lock);
 
 static struct dentry *binder_debugfs_dir_entry_root;
 static struct dentry *binder_debugfs_dir_entry_proc;
-static struct binder_node *binder_context_mgr_node;
-static kuid_t binder_context_mgr_uid = INVALID_UID;
-static int binder_last_id;
+static atomic_t binder_last_id;
 static struct workqueue_struct *binder_deferred_workqueue;
 
 #define BINDER_DEBUG_ENTRY(name) \
@@ -105,16 +138,15 @@
 	BINDER_DEBUG_TRANSACTION_COMPLETE   = 1U << 10,
 	BINDER_DEBUG_FREE_BUFFER            = 1U << 11,
 	BINDER_DEBUG_INTERNAL_REFS          = 1U << 12,
-	BINDER_DEBUG_BUFFER_ALLOC           = 1U << 13,
-	BINDER_DEBUG_PRIORITY_CAP           = 1U << 14,
-	BINDER_DEBUG_BUFFER_ALLOC_ASYNC     = 1U << 15,
+	BINDER_DEBUG_PRIORITY_CAP           = 1U << 13,
+	BINDER_DEBUG_SPINLOCKS              = 1U << 14,
 };
 static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
 	BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
 module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
 
-static bool binder_debug_no_lock;
-module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO);
+static char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
+module_param_named(devices, binder_devices_param, charp, S_IRUGO);
 
 static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
 static int binder_stop_on_user_error;
@@ -146,6 +178,17 @@
 			binder_stop_on_user_error = 2; \
 	} while (0)
 
+#define to_flat_binder_object(hdr) \
+	container_of(hdr, struct flat_binder_object, hdr)
+
+#define to_binder_fd_object(hdr) container_of(hdr, struct binder_fd_object, hdr)
+
+#define to_binder_buffer_object(hdr) \
+	container_of(hdr, struct binder_buffer_object, hdr)
+
+#define to_binder_fd_array_object(hdr) \
+	container_of(hdr, struct binder_fd_array_object, hdr)
+
 enum binder_stat_types {
 	BINDER_STAT_PROC,
 	BINDER_STAT_THREAD,
@@ -158,26 +201,27 @@
 };
 
 struct binder_stats {
-	int br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1];
-	int obj_created[BINDER_STAT_COUNT];
-	int obj_deleted[BINDER_STAT_COUNT];
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
 };
 
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
 {
-	binder_stats.obj_deleted[type]++;
+	atomic_inc(&binder_stats.obj_deleted[type]);
 }
 
 static inline void binder_stats_created(enum binder_stat_types type)
 {
-	binder_stats.obj_created[type]++;
+	atomic_inc(&binder_stats.obj_created[type]);
 }
 
 struct binder_transaction_log_entry {
 	int debug_id;
+	int debug_id_done;
 	int call_type;
 	int from_proc;
 	int from_thread;
@@ -187,10 +231,14 @@
 	int to_node;
 	int data_size;
 	int offsets_size;
+	int return_error_line;
+	uint32_t return_error;
+	uint32_t return_error_param;
+	const char *context_name;
 };
 struct binder_transaction_log {
-	int next;
-	int full;
+	atomic_t cur;
+	bool full;
 	struct binder_transaction_log_entry entry[32];
 };
 static struct binder_transaction_log binder_transaction_log;
@@ -200,22 +248,50 @@
 	struct binder_transaction_log *log)
 {
 	struct binder_transaction_log_entry *e;
+	unsigned int cur = atomic_inc_return(&log->cur);
 
-	e = &log->entry[log->next];
-	memset(e, 0, sizeof(*e));
-	log->next++;
-	if (log->next == ARRAY_SIZE(log->entry)) {
-		log->next = 0;
+	if (cur >= ARRAY_SIZE(log->entry))
 		log->full = 1;
-	}
+	e = &log->entry[cur % ARRAY_SIZE(log->entry)];
+	WRITE_ONCE(e->debug_id_done, 0);
+	/*
+	 * write-barrier to synchronize access to e->debug_id_done.
+	 * We make sure the initialized 0 value is seen before
+	 * memset() other fields are zeroed by memset.
+	 */
+	smp_wmb();
+	memset(e, 0, sizeof(*e));
 	return e;
 }
 
+struct binder_context {
+	struct binder_node *binder_context_mgr_node;
+	struct mutex context_mgr_node_lock;
+
+	kuid_t binder_context_mgr_uid;
+	const char *name;
+};
+
+struct binder_device {
+	struct hlist_node hlist;
+	struct miscdevice miscdev;
+	struct binder_context context;
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
 struct binder_work {
 	struct list_head entry;
+
 	enum {
 		BINDER_WORK_TRANSACTION = 1,
 		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
 		BINDER_WORK_NODE,
 		BINDER_WORK_DEAD_BINDER,
 		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
@@ -223,8 +299,76 @@
 	} type;
 };
 
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/**
+ * struct binder_node - binder node bookkeeping
+ * @debug_id:             unique ID for debugging
+ *                        (invariant after initialized)
+ * @lock:                 lock for node fields
+ * @work:                 worklist element for node work
+ *                        (protected by @proc->inner_lock)
+ * @rb_node:              element for proc->nodes tree
+ *                        (protected by @proc->inner_lock)
+ * @dead_node:            element for binder_dead_nodes list
+ *                        (protected by binder_dead_nodes_lock)
+ * @proc:                 binder_proc that owns this node
+ *                        (invariant after initialized)
+ * @refs:                 list of references on this node
+ *                        (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ *                        initiating a transaction
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_weak_refs:      weak user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_strong_refs:    strong user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @tmp_refs:             temporary kernel refs
+ *                        (protected by @proc->inner_lock while @proc
+ *                        is valid, and by binder_dead_nodes_lock
+ *                        if @proc is NULL. During inc/dec and node release
+ *                        it is also protected by @lock to provide safety
+ *                        as the node dies and @proc becomes NULL)
+ * @ptr:                  userspace pointer for node
+ *                        (invariant, no lock needed)
+ * @cookie:               userspace cookie for node
+ *                        (invariant, no lock needed)
+ * @has_strong_ref:       userspace notified of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_weak_ref:         userspace notified of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_weak_ref:     userspace has acked notification of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ *                        (protected by @lock)
+ * @sched_policy:         minimum scheduling policy for node
+ *                        (invariant after initialized)
+ * @accept_fds:           file descriptor operations supported for node
+ *                        (invariant after initialized)
+ * @min_priority:         minimum scheduling priority
+ *                        (invariant after initialized)
+ * @inherit_rt:           inherit RT scheduling policy from caller
+ *                        (invariant after initialized)
+ * @async_todo:           list of async work items
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
 struct binder_node {
 	int debug_id;
+	spinlock_t lock;
 	struct binder_work work;
 	union {
 		struct rb_node rb_node;
@@ -235,87 +379,185 @@
 	int internal_strong_refs;
 	int local_weak_refs;
 	int local_strong_refs;
+	int tmp_refs;
 	binder_uintptr_t ptr;
 	binder_uintptr_t cookie;
-	unsigned has_strong_ref:1;
-	unsigned pending_strong_ref:1;
-	unsigned has_weak_ref:1;
-	unsigned pending_weak_ref:1;
-	unsigned has_async_transaction:1;
-	unsigned accept_fds:1;
-	unsigned min_priority:8;
+	struct {
+		/*
+		 * bitfield elements protected by
+		 * proc inner_lock
+		 */
+		u8 has_strong_ref:1;
+		u8 pending_strong_ref:1;
+		u8 has_weak_ref:1;
+		u8 pending_weak_ref:1;
+	};
+	struct {
+		/*
+		 * invariant after initialization
+		 */
+		u8 sched_policy:2;
+		u8 inherit_rt:1;
+		u8 accept_fds:1;
+		u8 min_priority;
+	};
+	bool has_async_transaction;
 	struct list_head async_todo;
 };
 
 struct binder_ref_death {
+	/**
+	 * @work: worklist element for death notifications
+	 *        (protected by inner_lock of the proc that
+	 *        this ref belongs to)
+	 */
 	struct binder_work work;
 	binder_uintptr_t cookie;
 };
 
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:        unique ID for the ref
+ * @desc:            unique userspace handle for ref
+ * @strong:          strong ref count (debugging only if not locked)
+ * @weak:            weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+	int debug_id;
+	uint32_t desc;
+	int strong;
+	int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:        binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ *               (protected by @node->lock)
+ * @proc:        binder_proc containing ref
+ * @node:        binder_node of target node. When cleaning up a
+ *               ref for deletion in binder_cleanup_ref, a non-NULL
+ *               @node indicates the node must be freed
+ * @death:       pointer to death notification (ref_death) if requested
+ *               (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
 struct binder_ref {
 	/* Lookups needed: */
 	/*   node + proc => ref (transaction) */
 	/*   desc + proc => ref (transaction, inc/dec ref) */
 	/*   node => refs + procs (proc exit) */
-	int debug_id;
+	struct binder_ref_data data;
 	struct rb_node rb_node_desc;
 	struct rb_node rb_node_node;
 	struct hlist_node node_entry;
 	struct binder_proc *proc;
 	struct binder_node *node;
-	uint32_t desc;
-	int strong;
-	int weak;
 	struct binder_ref_death *death;
 };
 
-struct binder_buffer {
-	struct list_head entry; /* free and allocated entries by address */
-	struct rb_node rb_node; /* free entry by size or allocated entry */
-				/* by address */
-	unsigned free:1;
-	unsigned allow_user_free:1;
-	unsigned async_transaction:1;
-	unsigned debug_id:29;
-
-	struct binder_transaction *transaction;
-
-	struct binder_node *target_node;
-	size_t data_size;
-	size_t offsets_size;
-	uint8_t data[0];
-};
-
 enum binder_deferred_state {
 	BINDER_DEFERRED_PUT_FILES    = 0x01,
 	BINDER_DEFERRED_FLUSH        = 0x02,
 	BINDER_DEFERRED_RELEASE      = 0x04,
 };
 
+/**
+ * struct binder_priority - scheduler policy and priority
+ * @sched_policy            scheduler policy
+ * @prio                    [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT
+ *
+ * The binder driver supports inheriting the following scheduler policies:
+ * SCHED_NORMAL
+ * SCHED_BATCH
+ * SCHED_FIFO
+ * SCHED_RR
+ */
+struct binder_priority {
+	unsigned int sched_policy;
+	int prio;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @files                 files_struct for process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @wait:                 wait queue head to wait for proc work
+ *                        (invariant after initialized)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ *
+ * Bookkeeping structure for binder processes
+ */
 struct binder_proc {
 	struct hlist_node proc_node;
 	struct rb_root threads;
 	struct rb_root nodes;
 	struct rb_root refs_by_desc;
 	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
 	int pid;
-	struct vm_area_struct *vma;
-	struct mm_struct *vma_vm_mm;
 	struct task_struct *tsk;
 	struct files_struct *files;
 	struct hlist_node deferred_work_node;
 	int deferred_work;
-	void *buffer;
-	ptrdiff_t user_buffer_offset;
+	bool is_dead;
 
-	struct list_head buffers;
-	struct rb_root free_buffers;
-	struct rb_root allocated_buffers;
-	size_t free_async_space;
-
-	struct page **pages;
-	size_t buffer_size;
-	uint32_t buffer_free;
 	struct list_head todo;
 	wait_queue_head_t wait;
 	struct binder_stats stats;
@@ -323,9 +565,13 @@
 	int max_threads;
 	int requested_threads;
 	int requested_threads_started;
-	int ready_threads;
-	long default_priority;
+	int tmp_ref;
+	struct binder_priority default_priority;
 	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
 };
 
 enum {
@@ -334,22 +580,60 @@
 	BINDER_LOOPER_STATE_EXITED      = 0x04,
 	BINDER_LOOPER_STATE_INVALID     = 0x08,
 	BINDER_LOOPER_STATE_WAITING     = 0x10,
-	BINDER_LOOPER_STATE_NEED_RETURN = 0x20
+	BINDER_LOOPER_STATE_POLL        = 0x20,
 };
 
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ * @task:                 struct task_struct for this thread
+ *
+ * Bookkeeping structure for binder threads.
+ */
 struct binder_thread {
 	struct binder_proc *proc;
 	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
 	int pid;
-	int looper;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
 	struct binder_transaction *transaction_stack;
 	struct list_head todo;
-	uint32_t return_error; /* Write failed, return error code in read buf */
-	uint32_t return_error2; /* Write failed, return error code in read */
-		/* buffer. Used when sending a reply to a dead process that */
-		/* we are also waiting on */
+	struct binder_error return_error;
+	struct binder_error reply_error;
 	wait_queue_head_t wait;
 	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+	struct task_struct *task;
 };
 
 struct binder_transaction {
@@ -366,13 +650,257 @@
 	struct binder_buffer *buffer;
 	unsigned int	code;
 	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
+	struct binder_priority	priority;
+	struct binder_priority	saved_priority;
+	bool    set_priority_called;
 	kuid_t	sender_euid;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
 };
 
+/**
+ * binder_proc_lock() - Acquire outer lock for given binder_proc
+ * @proc:         struct binder_proc to acquire
+ *
+ * Acquires proc->outer_lock. Used to protect binder_ref
+ * structures associated with the given proc.
+ */
+#define binder_proc_lock(proc) _binder_proc_lock(proc, __LINE__)
+static void
+_binder_proc_lock(struct binder_proc *proc, int line)
+{
+	binder_debug(BINDER_DEBUG_SPINLOCKS,
+		     "%s: line=%d\n", __func__, line);
+	spin_lock(&proc->outer_lock);
+}
+
+/**
+ * binder_proc_unlock() - Release spinlock for given binder_proc
+ * @proc:         struct binder_proc to acquire
+ *
+ * Release lock acquired via binder_proc_lock()
+ */
+#define binder_proc_unlock(_proc) _binder_proc_unlock(_proc, __LINE__)
+static void
+_binder_proc_unlock(struct binder_proc *proc, int line)
+{
+	binder_debug(BINDER_DEBUG_SPINLOCKS,
+		     "%s: line=%d\n", __func__, line);
+	spin_unlock(&proc->outer_lock);
+}
+
+/**
+ * binder_inner_proc_lock() - Acquire inner lock for given binder_proc
+ * @proc:         struct binder_proc to acquire
+ *
+ * Acquires proc->inner_lock. Used to protect todo lists
+ */
+#define binder_inner_proc_lock(proc) _binder_inner_proc_lock(proc, __LINE__)
+static void
+_binder_inner_proc_lock(struct binder_proc *proc, int line)
+{
+	binder_debug(BINDER_DEBUG_SPINLOCKS,
+		     "%s: line=%d\n", __func__, line);
+	spin_lock(&proc->inner_lock);
+}
+
+/**
+ * binder_inner_proc_unlock() - Release inner lock for given binder_proc
+ * @proc:         struct binder_proc to acquire
+ *
+ * Release lock acquired via binder_inner_proc_lock()
+ */
+#define binder_inner_proc_unlock(proc) _binder_inner_proc_unlock(proc, __LINE__)
+static void
+_binder_inner_proc_unlock(struct binder_proc *proc, int line)
+{
+	binder_debug(BINDER_DEBUG_SPINLOCKS,
+		     "%s: line=%d\n", __func__, line);
+	spin_unlock(&proc->inner_lock);
+}
+
+/**
+ * binder_node_lock() - Acquire spinlock for given binder_node
+ * @node:         struct binder_node to acquire
+ *
+ * Acquires node->lock. Used to protect binder_node fields
+ */
+#define binder_node_lock(node) _binder_node_lock(node, __LINE__)
+static void
+_binder_node_lock(struct binder_node *node, int line)
+{
+	binder_debug(BINDER_DEBUG_SPINLOCKS,
+		     "%s: line=%d\n", __func__, line);
+	spin_lock(&node->lock);
+}
+
+/**
+ * binder_node_unlock() - Release spinlock for given binder_proc
+ * @node:         struct binder_node to acquire
+ *
+ * Release lock acquired via binder_node_lock()
+ */
+#define binder_node_unlock(node) _binder_node_unlock(node, __LINE__)
+static void
+_binder_node_unlock(struct binder_node *node, int line)
+{
+	binder_debug(BINDER_DEBUG_SPINLOCKS,
+		     "%s: line=%d\n", __func__, line);
+	spin_unlock(&node->lock);
+}
+
+/**
+ * binder_node_inner_lock() - Acquire node and inner locks
+ * @node:         struct binder_node to acquire
+ *
+ * Acquires node->lock. If node->proc also acquires
+ * proc->inner_lock. Used to protect binder_node fields
+ */
+#define binder_node_inner_lock(node) _binder_node_inner_lock(node, __LINE__)
+static void
+_binder_node_inner_lock(struct binder_node *node, int line)
+{
+	binder_debug(BINDER_DEBUG_SPINLOCKS,
+		     "%s: line=%d\n", __func__, line);
+	spin_lock(&node->lock);
+	if (node->proc)
+		binder_inner_proc_lock(node->proc);
+}
+
+/**
+ * binder_node_unlock() - Release node and inner locks
+ * @node:         struct binder_node to acquire
+ *
+ * Release lock acquired via binder_node_lock()
+ */
+#define binder_node_inner_unlock(node) _binder_node_inner_unlock(node, __LINE__)
+static void
+_binder_node_inner_unlock(struct binder_node *node, int line)
+{
+	struct binder_proc *proc = node->proc;
+
+	binder_debug(BINDER_DEBUG_SPINLOCKS,
+		     "%s: line=%d\n", __func__, line);
+	if (proc)
+		binder_inner_proc_unlock(proc);
+	spin_unlock(&node->lock);
+}
+
+static bool binder_worklist_empty_ilocked(struct list_head *list)
+{
+	return list_empty(list);
+}
+
+/**
+ * binder_worklist_empty() - Check if no items on the work list
+ * @proc:       binder_proc associated with list
+ * @list:	list to check
+ *
+ * Return: true if there are no items on list, else false
+ */
+static bool binder_worklist_empty(struct binder_proc *proc,
+				  struct list_head *list)
+{
+	bool ret;
+
+	binder_inner_proc_lock(proc);
+	ret = binder_worklist_empty_ilocked(list);
+	binder_inner_proc_unlock(proc);
+	return ret;
+}
+
+static void
+binder_enqueue_work_ilocked(struct binder_work *work,
+			   struct list_head *target_list)
+{
+	BUG_ON(target_list == NULL);
+	BUG_ON(work->entry.next && !list_empty(&work->entry));
+	list_add_tail(&work->entry, target_list);
+}
+
+/**
+ * binder_enqueue_work() - Add an item to the work list
+ * @proc:         binder_proc associated with list
+ * @work:         struct binder_work to add to list
+ * @target_list:  list to add work to
+ *
+ * Adds the work to the specified list. Asserts that work
+ * is not already on a list.
+ */
+static void
+binder_enqueue_work(struct binder_proc *proc,
+		    struct binder_work *work,
+		    struct list_head *target_list)
+{
+	binder_inner_proc_lock(proc);
+	binder_enqueue_work_ilocked(work, target_list);
+	binder_inner_proc_unlock(proc);
+}
+
+static void
+binder_dequeue_work_ilocked(struct binder_work *work)
+{
+	list_del_init(&work->entry);
+}
+
+/**
+ * binder_dequeue_work() - Removes an item from the work list
+ * @proc:         binder_proc associated with list
+ * @work:         struct binder_work to remove from list
+ *
+ * Removes the specified work item from whatever list it is on.
+ * Can safely be called if work is not on any list.
+ */
+static void
+binder_dequeue_work(struct binder_proc *proc, struct binder_work *work)
+{
+	binder_inner_proc_lock(proc);
+	binder_dequeue_work_ilocked(work);
+	binder_inner_proc_unlock(proc);
+}
+
+static struct binder_work *binder_dequeue_work_head_ilocked(
+					struct list_head *list)
+{
+	struct binder_work *w;
+
+	w = list_first_entry_or_null(list, struct binder_work, entry);
+	if (w)
+		list_del_init(&w->entry);
+	return w;
+}
+
+/**
+ * binder_dequeue_work_head() - Dequeues the item at head of list
+ * @proc:         binder_proc associated with list
+ * @list:         list to dequeue head
+ *
+ * Removes the head of the list if there are items on the list
+ *
+ * Return: pointer dequeued binder_work, NULL if list was empty
+ */
+static struct binder_work *binder_dequeue_work_head(
+					struct binder_proc *proc,
+					struct list_head *list)
+{
+	struct binder_work *w;
+
+	binder_inner_proc_lock(proc);
+	w = binder_dequeue_work_head_ilocked(list);
+	binder_inner_proc_unlock(proc);
+	return w;
+}
+
 static void
 binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer);
+static void binder_free_thread(struct binder_thread *thread);
+static void binder_free_proc(struct binder_proc *proc);
+static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
 
 static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
 {
@@ -423,453 +951,268 @@
 	return retval;
 }
 
-static inline void binder_lock(const char *tag)
+static bool binder_has_work_ilocked(struct binder_thread *thread,
+				    bool do_proc_work)
 {
-	trace_binder_lock(tag);
-	mutex_lock(&binder_main_lock);
-	trace_binder_locked(tag);
+	return !binder_worklist_empty_ilocked(&thread->todo) ||
+		thread->looper_need_return ||
+		(do_proc_work &&
+		 !binder_worklist_empty_ilocked(&thread->proc->todo));
 }
 
-static inline void binder_unlock(const char *tag)
+static bool binder_has_work(struct binder_thread *thread, bool do_proc_work)
 {
-	trace_binder_unlock(tag);
-	mutex_unlock(&binder_main_lock);
+	bool has_work;
+
+	binder_inner_proc_lock(thread->proc);
+	has_work = binder_has_work_ilocked(thread, do_proc_work);
+	binder_inner_proc_unlock(thread->proc);
+
+	return has_work;
 }
 
-static void binder_set_nice(long nice)
+static bool binder_available_for_proc_work_ilocked(struct binder_thread *thread)
 {
-	long min_nice;
+	return !thread->transaction_stack &&
+		binder_worklist_empty_ilocked(&thread->todo) &&
+		(thread->looper & (BINDER_LOOPER_STATE_ENTERED |
+				   BINDER_LOOPER_STATE_REGISTERED));
+}
 
-	if (can_nice(current, nice)) {
-		set_user_nice(current, nice);
+static void binder_wakeup_poll_threads_ilocked(struct binder_proc *proc,
+					       bool sync)
+{
+	struct rb_node *n;
+	struct binder_thread *thread;
+
+	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
+		thread = rb_entry(n, struct binder_thread, rb_node);
+		if (thread->looper & BINDER_LOOPER_STATE_POLL &&
+		    binder_available_for_proc_work_ilocked(thread)) {
+			if (sync)
+				wake_up_interruptible_sync(&thread->wait);
+			else
+				wake_up_interruptible(&thread->wait);
+		}
+	}
+}
+
+/**
+ * binder_select_thread_ilocked() - selects a thread for doing proc work.
+ * @proc:	process to select a thread from
+ *
+ * Note that calling this function moves the thread off the waiting_threads
+ * list, so it can only be woken up by the caller of this function, or a
+ * signal. Therefore, callers *should* always wake up the thread this function
+ * returns.
+ *
+ * Return:	If there's a thread currently waiting for process work,
+ *		returns that thread. Otherwise returns NULL.
+ */
+static struct binder_thread *
+binder_select_thread_ilocked(struct binder_proc *proc)
+{
+	struct binder_thread *thread;
+
+	BUG_ON(!spin_is_locked(&proc->inner_lock));
+	thread = list_first_entry_or_null(&proc->waiting_threads,
+					  struct binder_thread,
+					  waiting_thread_node);
+
+	if (thread)
+		list_del_init(&thread->waiting_thread_node);
+
+	return thread;
+}
+
+/**
+ * binder_wakeup_thread_ilocked() - wakes up a thread for doing proc work.
+ * @proc:	process to wake up a thread in
+ * @thread:	specific thread to wake-up (may be NULL)
+ * @sync:	whether to do a synchronous wake-up
+ *
+ * This function wakes up a thread in the @proc process.
+ * The caller may provide a specific thread to wake-up in
+ * the @thread parameter. If @thread is NULL, this function
+ * will wake up threads that have called poll().
+ *
+ * Note that for this function to work as expected, callers
+ * should first call binder_select_thread() to find a thread
+ * to handle the work (if they don't have a thread already),
+ * and pass the result into the @thread parameter.
+ */
+static void binder_wakeup_thread_ilocked(struct binder_proc *proc,
+					 struct binder_thread *thread,
+					 bool sync)
+{
+	BUG_ON(!spin_is_locked(&proc->inner_lock));
+
+	if (thread) {
+		if (sync)
+			wake_up_interruptible_sync(&thread->wait);
+		else
+			wake_up_interruptible(&thread->wait);
 		return;
 	}
-	min_nice = rlimit_to_nice(current->signal->rlim[RLIMIT_NICE].rlim_cur);
-	binder_debug(BINDER_DEBUG_PRIORITY_CAP,
-		     "%d: nice value %ld not allowed use %ld instead\n",
-		      current->pid, nice, min_nice);
-	set_user_nice(current, min_nice);
-	if (min_nice <= MAX_NICE)
-		return;
-	binder_user_error("%d RLIMIT_NICE not set\n", current->pid);
+
+	/* Didn't find a thread waiting for proc work; this can happen
+	 * in two scenarios:
+	 * 1. All threads are busy handling transactions
+	 *    In that case, one of those threads should call back into
+	 *    the kernel driver soon and pick up this work.
+	 * 2. Threads are using the (e)poll interface, in which case
+	 *    they may be blocked on the waitqueue without having been
+	 *    added to waiting_threads. For this case, we just iterate
+	 *    over all threads not handling transaction work, and
+	 *    wake them all up. We wake all because we don't know whether
+	 *    a thread that called into (e)poll is handling non-binder
+	 *    work currently.
+	 */
+	binder_wakeup_poll_threads_ilocked(proc, sync);
 }
 
-static size_t binder_buffer_size(struct binder_proc *proc,
-				 struct binder_buffer *buffer)
+static void binder_wakeup_proc_ilocked(struct binder_proc *proc)
 {
-	if (list_is_last(&buffer->entry, &proc->buffers))
-		return proc->buffer + proc->buffer_size - (void *)buffer->data;
-	return (size_t)list_entry(buffer->entry.next,
-			  struct binder_buffer, entry) - (size_t)buffer->data;
+	struct binder_thread *thread = binder_select_thread_ilocked(proc);
+
+	binder_wakeup_thread_ilocked(proc, thread, /* sync = */false);
 }
 
-static void binder_insert_free_buffer(struct binder_proc *proc,
-				      struct binder_buffer *new_buffer)
+static bool is_rt_policy(int policy)
 {
-	struct rb_node **p = &proc->free_buffers.rb_node;
-	struct rb_node *parent = NULL;
-	struct binder_buffer *buffer;
-	size_t buffer_size;
-	size_t new_buffer_size;
-
-	BUG_ON(!new_buffer->free);
-
-	new_buffer_size = binder_buffer_size(proc, new_buffer);
-
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "%d: add free buffer, size %zd, at %p\n",
-		      proc->pid, new_buffer_size, new_buffer);
-
-	while (*p) {
-		parent = *p;
-		buffer = rb_entry(parent, struct binder_buffer, rb_node);
-		BUG_ON(!buffer->free);
-
-		buffer_size = binder_buffer_size(proc, buffer);
-
-		if (new_buffer_size < buffer_size)
-			p = &parent->rb_left;
-		else
-			p = &parent->rb_right;
-	}
-	rb_link_node(&new_buffer->rb_node, parent, p);
-	rb_insert_color(&new_buffer->rb_node, &proc->free_buffers);
+	return policy == SCHED_FIFO || policy == SCHED_RR;
 }
 
-static void binder_insert_allocated_buffer(struct binder_proc *proc,
-					   struct binder_buffer *new_buffer)
+static bool is_fair_policy(int policy)
 {
-	struct rb_node **p = &proc->allocated_buffers.rb_node;
-	struct rb_node *parent = NULL;
-	struct binder_buffer *buffer;
-
-	BUG_ON(new_buffer->free);
-
-	while (*p) {
-		parent = *p;
-		buffer = rb_entry(parent, struct binder_buffer, rb_node);
-		BUG_ON(buffer->free);
-
-		if (new_buffer < buffer)
-			p = &parent->rb_left;
-		else if (new_buffer > buffer)
-			p = &parent->rb_right;
-		else
-			BUG();
-	}
-	rb_link_node(&new_buffer->rb_node, parent, p);
-	rb_insert_color(&new_buffer->rb_node, &proc->allocated_buffers);
+	return policy == SCHED_NORMAL || policy == SCHED_BATCH;
 }
 
-static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc,
-						  uintptr_t user_ptr)
+static bool binder_supported_policy(int policy)
 {
-	struct rb_node *n = proc->allocated_buffers.rb_node;
-	struct binder_buffer *buffer;
-	struct binder_buffer *kern_ptr;
-
-	kern_ptr = (struct binder_buffer *)(user_ptr - proc->user_buffer_offset
-		- offsetof(struct binder_buffer, data));
-
-	while (n) {
-		buffer = rb_entry(n, struct binder_buffer, rb_node);
-		BUG_ON(buffer->free);
-
-		if (kern_ptr < buffer)
-			n = n->rb_left;
-		else if (kern_ptr > buffer)
-			n = n->rb_right;
-		else
-			return buffer;
-	}
-	return NULL;
+	return is_fair_policy(policy) || is_rt_policy(policy);
 }
 
-static int binder_update_page_range(struct binder_proc *proc, int allocate,
-				    void *start, void *end,
-				    struct vm_area_struct *vma)
+static int to_userspace_prio(int policy, int kernel_priority)
 {
-	void *page_addr;
-	unsigned long user_page_addr;
-	struct page **page;
-	struct mm_struct *mm;
-
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "%d: %s pages %p-%p\n", proc->pid,
-		     allocate ? "allocate" : "free", start, end);
-
-	if (end <= start)
-		return 0;
-
-	trace_binder_update_page_range(proc, allocate, start, end);
-
-	if (vma)
-		mm = NULL;
+	if (is_fair_policy(policy))
+		return PRIO_TO_NICE(kernel_priority);
 	else
-		mm = get_task_mm(proc->tsk);
-
-	if (mm) {
-		down_write(&mm->mmap_sem);
-		vma = proc->vma;
-		if (vma && mm != proc->vma_vm_mm) {
-			pr_err("%d: vma mm and task mm mismatch\n",
-				proc->pid);
-			vma = NULL;
-		}
-	}
-
-	if (allocate == 0)
-		goto free_range;
-
-	if (vma == NULL) {
-		pr_err("%d: binder_alloc_buf failed to map pages in userspace, no vma\n",
-			proc->pid);
-		goto err_no_vma;
-	}
-
-	for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
-		int ret;
-
-		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
-
-		BUG_ON(*page);
-		*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
-		if (*page == NULL) {
-			pr_err("%d: binder_alloc_buf failed for page at %p\n",
-				proc->pid, page_addr);
-			goto err_alloc_page_failed;
-		}
-		ret = map_kernel_range_noflush((unsigned long)page_addr,
-					PAGE_SIZE, PAGE_KERNEL, page);
-		flush_cache_vmap((unsigned long)page_addr,
-				(unsigned long)page_addr + PAGE_SIZE);
-		if (ret != 1) {
-			pr_err("%d: binder_alloc_buf failed to map page at %p in kernel\n",
-			       proc->pid, page_addr);
-			goto err_map_kernel_failed;
-		}
-		user_page_addr =
-			(uintptr_t)page_addr + proc->user_buffer_offset;
-		ret = vm_insert_page(vma, user_page_addr, page[0]);
-		if (ret) {
-			pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n",
-			       proc->pid, user_page_addr);
-			goto err_vm_insert_page_failed;
-		}
-		/* vm_insert_page does not seem to increment the refcount */
-	}
-	if (mm) {
-		up_write(&mm->mmap_sem);
-		mmput(mm);
-	}
-	return 0;
-
-free_range:
-	for (page_addr = end - PAGE_SIZE; page_addr >= start;
-	     page_addr -= PAGE_SIZE) {
-		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
-		if (vma)
-			zap_page_range(vma, (uintptr_t)page_addr +
-				proc->user_buffer_offset, PAGE_SIZE, NULL);
-err_vm_insert_page_failed:
-		unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
-err_map_kernel_failed:
-		__free_page(*page);
-		*page = NULL;
-err_alloc_page_failed:
-		;
-	}
-err_no_vma:
-	if (mm) {
-		up_write(&mm->mmap_sem);
-		mmput(mm);
-	}
-	return -ENOMEM;
+		return MAX_USER_RT_PRIO - 1 - kernel_priority;
 }
 
-static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
-					      size_t data_size,
-					      size_t offsets_size, int is_async)
+static int to_kernel_prio(int policy, int user_priority)
 {
-	struct rb_node *n = proc->free_buffers.rb_node;
-	struct binder_buffer *buffer;
-	size_t buffer_size;
-	struct rb_node *best_fit = NULL;
-	void *has_page_addr;
-	void *end_page_addr;
-	size_t size;
+	if (is_fair_policy(policy))
+		return NICE_TO_PRIO(user_priority);
+	else
+		return MAX_USER_RT_PRIO - 1 - user_priority;
+}
 
-	if (proc->vma == NULL) {
-		pr_err("%d: binder_alloc_buf, no vma\n",
-		       proc->pid);
-		return NULL;
-	}
+static void binder_set_priority(struct task_struct *task,
+				struct binder_priority desired)
+{
+	int priority; /* user-space prio value */
+	bool has_cap_nice;
+	unsigned int policy = desired.sched_policy;
 
-	size = ALIGN(data_size, sizeof(void *)) +
-		ALIGN(offsets_size, sizeof(void *));
+	if (task->policy == policy && task->normal_prio == desired.prio)
+		return;
 
-	if (size < data_size || size < offsets_size) {
-		binder_user_error("%d: got transaction with invalid size %zd-%zd\n",
-				proc->pid, data_size, offsets_size);
-		return NULL;
-	}
+	has_cap_nice = has_capability_noaudit(task, CAP_SYS_NICE);
 
-	if (is_async &&
-	    proc->free_async_space < size + sizeof(struct binder_buffer)) {
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-			     "%d: binder_alloc_buf size %zd failed, no async space left\n",
-			      proc->pid, size);
-		return NULL;
-	}
+	priority = to_userspace_prio(policy, desired.prio);
 
-	while (n) {
-		buffer = rb_entry(n, struct binder_buffer, rb_node);
-		BUG_ON(!buffer->free);
-		buffer_size = binder_buffer_size(proc, buffer);
+	if (is_rt_policy(policy) && !has_cap_nice) {
+		long max_rtprio = task_rlimit(task, RLIMIT_RTPRIO);
 
-		if (size < buffer_size) {
-			best_fit = n;
-			n = n->rb_left;
-		} else if (size > buffer_size)
-			n = n->rb_right;
-		else {
-			best_fit = n;
-			break;
+		if (max_rtprio == 0) {
+			policy = SCHED_NORMAL;
+			priority = MIN_NICE;
+		} else if (priority > max_rtprio) {
+			priority = max_rtprio;
 		}
 	}
-	if (best_fit == NULL) {
-		pr_err("%d: binder_alloc_buf size %zd failed, no address space\n",
-			proc->pid, size);
-		return NULL;
-	}
-	if (n == NULL) {
-		buffer = rb_entry(best_fit, struct binder_buffer, rb_node);
-		buffer_size = binder_buffer_size(proc, buffer);
-	}
 
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "%d: binder_alloc_buf size %zd got buffer %p size %zd\n",
-		      proc->pid, size, buffer, buffer_size);
+	if (is_fair_policy(policy) && !has_cap_nice) {
+		long min_nice = rlimit_to_nice(task_rlimit(task, RLIMIT_NICE));
 
-	has_page_addr =
-		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
-	if (n == NULL) {
-		if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
-			buffer_size = size; /* no room for other buffers */
-		else
-			buffer_size = size + sizeof(struct binder_buffer);
-	}
-	end_page_addr =
-		(void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
-	if (end_page_addr > has_page_addr)
-		end_page_addr = has_page_addr;
-	if (binder_update_page_range(proc, 1,
-	    (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL))
-		return NULL;
-
-	rb_erase(best_fit, &proc->free_buffers);
-	buffer->free = 0;
-	binder_insert_allocated_buffer(proc, buffer);
-	if (buffer_size != size) {
-		struct binder_buffer *new_buffer = (void *)buffer->data + size;
-
-		list_add(&new_buffer->entry, &buffer->entry);
-		new_buffer->free = 1;
-		binder_insert_free_buffer(proc, new_buffer);
-	}
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "%d: binder_alloc_buf size %zd got %p\n",
-		      proc->pid, size, buffer);
-	buffer->data_size = data_size;
-	buffer->offsets_size = offsets_size;
-	buffer->async_transaction = is_async;
-	if (is_async) {
-		proc->free_async_space -= size + sizeof(struct binder_buffer);
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
-			     "%d: binder_alloc_buf size %zd async free %zd\n",
-			      proc->pid, size, proc->free_async_space);
-	}
-
-	return buffer;
-}
-
-static void *buffer_start_page(struct binder_buffer *buffer)
-{
-	return (void *)((uintptr_t)buffer & PAGE_MASK);
-}
-
-static void *buffer_end_page(struct binder_buffer *buffer)
-{
-	return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK);
-}
-
-static void binder_delete_free_buffer(struct binder_proc *proc,
-				      struct binder_buffer *buffer)
-{
-	struct binder_buffer *prev, *next = NULL;
-	int free_page_end = 1;
-	int free_page_start = 1;
-
-	BUG_ON(proc->buffers.next == &buffer->entry);
-	prev = list_entry(buffer->entry.prev, struct binder_buffer, entry);
-	BUG_ON(!prev->free);
-	if (buffer_end_page(prev) == buffer_start_page(buffer)) {
-		free_page_start = 0;
-		if (buffer_end_page(prev) == buffer_end_page(buffer))
-			free_page_end = 0;
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-			     "%d: merge free, buffer %p share page with %p\n",
-			      proc->pid, buffer, prev);
-	}
-
-	if (!list_is_last(&buffer->entry, &proc->buffers)) {
-		next = list_entry(buffer->entry.next,
-				  struct binder_buffer, entry);
-		if (buffer_start_page(next) == buffer_end_page(buffer)) {
-			free_page_end = 0;
-			if (buffer_start_page(next) ==
-			    buffer_start_page(buffer))
-				free_page_start = 0;
-			binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-				     "%d: merge free, buffer %p share page with %p\n",
-				      proc->pid, buffer, prev);
+		if (min_nice > MAX_NICE) {
+			binder_user_error("%d RLIMIT_NICE not set\n",
+					  task->pid);
+			return;
+		} else if (priority < min_nice) {
+			priority = min_nice;
 		}
 	}
-	list_del(&buffer->entry);
-	if (free_page_start || free_page_end) {
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-			     "%d: merge free, buffer %p do not share page%s%s with %p or %p\n",
-			     proc->pid, buffer, free_page_start ? "" : " end",
-			     free_page_end ? "" : " start", prev, next);
-		binder_update_page_range(proc, 0, free_page_start ?
-			buffer_start_page(buffer) : buffer_end_page(buffer),
-			(free_page_end ? buffer_end_page(buffer) :
-			buffer_start_page(buffer)) + PAGE_SIZE, NULL);
+
+	if (policy != desired.sched_policy ||
+	    to_kernel_prio(policy, priority) != desired.prio)
+		binder_debug(BINDER_DEBUG_PRIORITY_CAP,
+			     "%d: priority %d not allowed, using %d instead\n",
+			      task->pid, desired.prio,
+			      to_kernel_prio(policy, priority));
+
+	/* Set the actual priority */
+	if (task->policy != policy || is_rt_policy(policy)) {
+		struct sched_param params;
+
+		params.sched_priority = is_rt_policy(policy) ? priority : 0;
+
+		sched_setscheduler_nocheck(task,
+					   policy | SCHED_RESET_ON_FORK,
+					   &params);
 	}
+	if (is_fair_policy(policy))
+		set_user_nice(task, priority);
 }
 
-static void binder_free_buf(struct binder_proc *proc,
-			    struct binder_buffer *buffer)
+static void binder_transaction_priority(struct task_struct *task,
+					struct binder_transaction *t,
+					struct binder_priority node_prio,
+					bool inherit_rt)
 {
-	size_t size, buffer_size;
+	struct binder_priority desired_prio;
 
-	buffer_size = binder_buffer_size(proc, buffer);
+	if (t->set_priority_called)
+		return;
 
-	size = ALIGN(buffer->data_size, sizeof(void *)) +
-		ALIGN(buffer->offsets_size, sizeof(void *));
+	t->set_priority_called = true;
+	t->saved_priority.sched_policy = task->policy;
+	t->saved_priority.prio = task->normal_prio;
 
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "%d: binder_free_buf %p size %zd buffer_size %zd\n",
-		      proc->pid, buffer, size, buffer_size);
-
-	BUG_ON(buffer->free);
-	BUG_ON(size > buffer_size);
-	BUG_ON(buffer->transaction != NULL);
-	BUG_ON((void *)buffer < proc->buffer);
-	BUG_ON((void *)buffer > proc->buffer + proc->buffer_size);
-
-	if (buffer->async_transaction) {
-		proc->free_async_space += size + sizeof(struct binder_buffer);
-
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
-			     "%d: binder_free_buf size %zd async free %zd\n",
-			      proc->pid, size, proc->free_async_space);
+	if (!inherit_rt && is_rt_policy(desired_prio.sched_policy)) {
+		desired_prio.prio = NICE_TO_PRIO(0);
+		desired_prio.sched_policy = SCHED_NORMAL;
+	} else {
+		desired_prio.prio = t->priority.prio;
+		desired_prio.sched_policy = t->priority.sched_policy;
 	}
 
-	binder_update_page_range(proc, 0,
-		(void *)PAGE_ALIGN((uintptr_t)buffer->data),
-		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK),
-		NULL);
-	rb_erase(&buffer->rb_node, &proc->allocated_buffers);
-	buffer->free = 1;
-	if (!list_is_last(&buffer->entry, &proc->buffers)) {
-		struct binder_buffer *next = list_entry(buffer->entry.next,
-						struct binder_buffer, entry);
-
-		if (next->free) {
-			rb_erase(&next->rb_node, &proc->free_buffers);
-			binder_delete_free_buffer(proc, next);
-		}
+	if (node_prio.prio < t->priority.prio ||
+	    (node_prio.prio == t->priority.prio &&
+	     node_prio.sched_policy == SCHED_FIFO)) {
+		/*
+		 * In case the minimum priority on the node is
+		 * higher (lower value), use that priority. If
+		 * the priority is the same, but the node uses
+		 * SCHED_FIFO, prefer SCHED_FIFO, since it can
+		 * run unbounded, unlike SCHED_RR.
+		 */
+		desired_prio = node_prio;
 	}
-	if (proc->buffers.next != &buffer->entry) {
-		struct binder_buffer *prev = list_entry(buffer->entry.prev,
-						struct binder_buffer, entry);
 
-		if (prev->free) {
-			binder_delete_free_buffer(proc, buffer);
-			rb_erase(&prev->rb_node, &proc->free_buffers);
-			buffer = prev;
-		}
-	}
-	binder_insert_free_buffer(proc, buffer);
+	binder_set_priority(task, desired_prio);
 }
 
-static struct binder_node *binder_get_node(struct binder_proc *proc,
-					   binder_uintptr_t ptr)
+static struct binder_node *binder_get_node_ilocked(struct binder_proc *proc,
+						   binder_uintptr_t ptr)
 {
 	struct rb_node *n = proc->nodes.rb_node;
 	struct binder_node *node;
 
+	BUG_ON(!spin_is_locked(&proc->inner_lock));
+
 	while (n) {
 		node = rb_entry(n, struct binder_node, rb_node);
 
@@ -877,21 +1220,46 @@
 			n = n->rb_left;
 		else if (ptr > node->ptr)
 			n = n->rb_right;
-		else
+		else {
+			/*
+			 * take an implicit weak reference
+			 * to ensure node stays alive until
+			 * call to binder_put_node()
+			 */
+			binder_inc_node_tmpref_ilocked(node);
 			return node;
+		}
 	}
 	return NULL;
 }
 
-static struct binder_node *binder_new_node(struct binder_proc *proc,
-					   binder_uintptr_t ptr,
-					   binder_uintptr_t cookie)
+static struct binder_node *binder_get_node(struct binder_proc *proc,
+					   binder_uintptr_t ptr)
+{
+	struct binder_node *node;
+
+	binder_inner_proc_lock(proc);
+	node = binder_get_node_ilocked(proc, ptr);
+	binder_inner_proc_unlock(proc);
+	return node;
+}
+
+static struct binder_node *binder_init_node_ilocked(
+						struct binder_proc *proc,
+						struct binder_node *new_node,
+						struct flat_binder_object *fp)
 {
 	struct rb_node **p = &proc->nodes.rb_node;
 	struct rb_node *parent = NULL;
 	struct binder_node *node;
+	binder_uintptr_t ptr = fp ? fp->binder : 0;
+	binder_uintptr_t cookie = fp ? fp->cookie : 0;
+	__u32 flags = fp ? fp->flags : 0;
+	s8 priority;
 
+	BUG_ON(!spin_is_locked(&proc->inner_lock));
 	while (*p) {
+
 		parent = *p;
 		node = rb_entry(parent, struct binder_node, rb_node);
 
@@ -899,39 +1267,86 @@
 			p = &(*p)->rb_left;
 		else if (ptr > node->ptr)
 			p = &(*p)->rb_right;
-		else
-			return NULL;
+		else {
+			/*
+			 * A matching node is already in
+			 * the rb tree. Abandon the init
+			 * and return it.
+			 */
+			binder_inc_node_tmpref_ilocked(node);
+			return node;
+		}
 	}
-
-	node = kzalloc(sizeof(*node), GFP_KERNEL);
-	if (node == NULL)
-		return NULL;
+	node = new_node;
 	binder_stats_created(BINDER_STAT_NODE);
+	node->tmp_refs++;
 	rb_link_node(&node->rb_node, parent, p);
 	rb_insert_color(&node->rb_node, &proc->nodes);
-	node->debug_id = ++binder_last_id;
+	node->debug_id = atomic_inc_return(&binder_last_id);
 	node->proc = proc;
 	node->ptr = ptr;
 	node->cookie = cookie;
 	node->work.type = BINDER_WORK_NODE;
+	priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
+	node->sched_policy = (flags & FLAT_BINDER_FLAG_PRIORITY_MASK) >>
+		FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT;
+	node->min_priority = to_kernel_prio(node->sched_policy, priority);
+	node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+	node->inherit_rt = !!(flags & FLAT_BINDER_FLAG_INHERIT_RT);
+	spin_lock_init(&node->lock);
 	INIT_LIST_HEAD(&node->work.entry);
 	INIT_LIST_HEAD(&node->async_todo);
 	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
 		     "%d:%d node %d u%016llx c%016llx created\n",
 		     proc->pid, current->pid, node->debug_id,
 		     (u64)node->ptr, (u64)node->cookie);
+
 	return node;
 }
 
-static int binder_inc_node(struct binder_node *node, int strong, int internal,
-			   struct list_head *target_list)
+static struct binder_node *binder_new_node(struct binder_proc *proc,
+					   struct flat_binder_object *fp)
 {
+	struct binder_node *node;
+	struct binder_node *new_node = kzalloc(sizeof(*node), GFP_KERNEL);
+
+	if (!new_node)
+		return NULL;
+	binder_inner_proc_lock(proc);
+	node = binder_init_node_ilocked(proc, new_node, fp);
+	binder_inner_proc_unlock(proc);
+	if (node != new_node)
+		/*
+		 * The node was already added by another thread
+		 */
+		kfree(new_node);
+
+	return node;
+}
+
+static void binder_free_node(struct binder_node *node)
+{
+	kfree(node);
+	binder_stats_deleted(BINDER_STAT_NODE);
+}
+
+static int binder_inc_node_nilocked(struct binder_node *node, int strong,
+				    int internal,
+				    struct list_head *target_list)
+{
+	struct binder_proc *proc = node->proc;
+
+	BUG_ON(!spin_is_locked(&node->lock));
+	if (proc)
+		BUG_ON(!spin_is_locked(&proc->inner_lock));
 	if (strong) {
 		if (internal) {
 			if (target_list == NULL &&
 			    node->internal_strong_refs == 0 &&
-			    !(node == binder_context_mgr_node &&
-			    node->has_strong_ref)) {
+			    !(node->proc &&
+			      node == node->proc->context->
+				      binder_context_mgr_node &&
+			      node->has_strong_ref)) {
 				pr_err("invalid inc strong node for %d\n",
 					node->debug_id);
 				return -EINVAL;
@@ -940,8 +1355,8 @@
 		} else
 			node->local_strong_refs++;
 		if (!node->has_strong_ref && target_list) {
-			list_del_init(&node->work.entry);
-			list_add_tail(&node->work.entry, target_list);
+			binder_dequeue_work_ilocked(&node->work);
+			binder_enqueue_work_ilocked(&node->work, target_list);
 		}
 	} else {
 		if (!internal)
@@ -952,58 +1367,169 @@
 					node->debug_id);
 				return -EINVAL;
 			}
-			list_add_tail(&node->work.entry, target_list);
+			binder_enqueue_work_ilocked(&node->work, target_list);
 		}
 	}
 	return 0;
 }
 
-static int binder_dec_node(struct binder_node *node, int strong, int internal)
+static int binder_inc_node(struct binder_node *node, int strong, int internal,
+			   struct list_head *target_list)
 {
+	int ret;
+
+	binder_node_inner_lock(node);
+	ret = binder_inc_node_nilocked(node, strong, internal, target_list);
+	binder_node_inner_unlock(node);
+
+	return ret;
+}
+
+static bool binder_dec_node_nilocked(struct binder_node *node,
+				     int strong, int internal)
+{
+	struct binder_proc *proc = node->proc;
+
+	BUG_ON(!spin_is_locked(&node->lock));
+	if (proc)
+		BUG_ON(!spin_is_locked(&proc->inner_lock));
 	if (strong) {
 		if (internal)
 			node->internal_strong_refs--;
 		else
 			node->local_strong_refs--;
 		if (node->local_strong_refs || node->internal_strong_refs)
-			return 0;
+			return false;
 	} else {
 		if (!internal)
 			node->local_weak_refs--;
-		if (node->local_weak_refs || !hlist_empty(&node->refs))
-			return 0;
+		if (node->local_weak_refs || node->tmp_refs ||
+				!hlist_empty(&node->refs))
+			return false;
 	}
-	if (node->proc && (node->has_strong_ref || node->has_weak_ref)) {
+
+	if (proc && (node->has_strong_ref || node->has_weak_ref)) {
 		if (list_empty(&node->work.entry)) {
-			list_add_tail(&node->work.entry, &node->proc->todo);
-			wake_up_interruptible(&node->proc->wait);
+			binder_enqueue_work_ilocked(&node->work, &proc->todo);
+			binder_wakeup_proc_ilocked(proc);
 		}
 	} else {
 		if (hlist_empty(&node->refs) && !node->local_strong_refs &&
-		    !node->local_weak_refs) {
-			list_del_init(&node->work.entry);
-			if (node->proc) {
-				rb_erase(&node->rb_node, &node->proc->nodes);
+		    !node->local_weak_refs && !node->tmp_refs) {
+			if (proc) {
+				binder_dequeue_work_ilocked(&node->work);
+				rb_erase(&node->rb_node, &proc->nodes);
 				binder_debug(BINDER_DEBUG_INTERNAL_REFS,
 					     "refless node %d deleted\n",
 					     node->debug_id);
 			} else {
+				BUG_ON(!list_empty(&node->work.entry));
+				spin_lock(&binder_dead_nodes_lock);
+				/*
+				 * tmp_refs could have changed so
+				 * check it again
+				 */
+				if (node->tmp_refs) {
+					spin_unlock(&binder_dead_nodes_lock);
+					return false;
+				}
 				hlist_del(&node->dead_node);
+				spin_unlock(&binder_dead_nodes_lock);
 				binder_debug(BINDER_DEBUG_INTERNAL_REFS,
 					     "dead node %d deleted\n",
 					     node->debug_id);
 			}
-			kfree(node);
-			binder_stats_deleted(BINDER_STAT_NODE);
+			return true;
 		}
 	}
-
-	return 0;
+	return false;
 }
 
+static void binder_dec_node(struct binder_node *node, int strong, int internal)
+{
+	bool free_node;
 
-static struct binder_ref *binder_get_ref(struct binder_proc *proc,
-					 uint32_t desc)
+	binder_node_inner_lock(node);
+	free_node = binder_dec_node_nilocked(node, strong, internal);
+	binder_node_inner_unlock(node);
+	if (free_node)
+		binder_free_node(node);
+}
+
+static void binder_inc_node_tmpref_ilocked(struct binder_node *node)
+{
+	/*
+	 * No call to binder_inc_node() is needed since we
+	 * don't need to inform userspace of any changes to
+	 * tmp_refs
+	 */
+	node->tmp_refs++;
+}
+
+/**
+ * binder_inc_node_tmpref() - take a temporary reference on node
+ * @node:	node to reference
+ *
+ * Take reference on node to prevent the node from being freed
+ * while referenced only by a local variable. The inner lock is
+ * needed to serialize with the node work on the queue (which
+ * isn't needed after the node is dead). If the node is dead
+ * (node->proc is NULL), use binder_dead_nodes_lock to protect
+ * node->tmp_refs against dead-node-only cases where the node
+ * lock cannot be acquired (eg traversing the dead node list to
+ * print nodes)
+ */
+static void binder_inc_node_tmpref(struct binder_node *node)
+{
+	binder_node_lock(node);
+	if (node->proc)
+		binder_inner_proc_lock(node->proc);
+	else
+		spin_lock(&binder_dead_nodes_lock);
+	binder_inc_node_tmpref_ilocked(node);
+	if (node->proc)
+		binder_inner_proc_unlock(node->proc);
+	else
+		spin_unlock(&binder_dead_nodes_lock);
+	binder_node_unlock(node);
+}
+
+/**
+ * binder_dec_node_tmpref() - remove a temporary reference on node
+ * @node:	node to reference
+ *
+ * Release temporary reference on node taken via binder_inc_node_tmpref()
+ */
+static void binder_dec_node_tmpref(struct binder_node *node)
+{
+	bool free_node;
+
+	binder_node_inner_lock(node);
+	if (!node->proc)
+		spin_lock(&binder_dead_nodes_lock);
+	node->tmp_refs--;
+	BUG_ON(node->tmp_refs < 0);
+	if (!node->proc)
+		spin_unlock(&binder_dead_nodes_lock);
+	/*
+	 * Call binder_dec_node() to check if all refcounts are 0
+	 * and cleanup is needed. Calling with strong=0 and internal=1
+	 * causes no actual reference to be released in binder_dec_node().
+	 * If that changes, a change is needed here too.
+	 */
+	free_node = binder_dec_node_nilocked(node, 0, 1);
+	binder_node_inner_unlock(node);
+	if (free_node)
+		binder_free_node(node);
+}
+
+static void binder_put_node(struct binder_node *node)
+{
+	binder_dec_node_tmpref(node);
+}
+
+static struct binder_ref *binder_get_ref_olocked(struct binder_proc *proc,
+						 u32 desc, bool need_strong_ref)
 {
 	struct rb_node *n = proc->refs_by_desc.rb_node;
 	struct binder_ref *ref;
@@ -1011,23 +1537,48 @@
 	while (n) {
 		ref = rb_entry(n, struct binder_ref, rb_node_desc);
 
-		if (desc < ref->desc)
+		if (desc < ref->data.desc) {
 			n = n->rb_left;
-		else if (desc > ref->desc)
+		} else if (desc > ref->data.desc) {
 			n = n->rb_right;
-		else
+		} else if (need_strong_ref && !ref->data.strong) {
+			binder_user_error("tried to use weak ref as strong ref\n");
+			return NULL;
+		} else {
 			return ref;
+		}
 	}
 	return NULL;
 }
 
-static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
-						  struct binder_node *node)
+/**
+ * binder_get_ref_for_node_olocked() - get the ref associated with given node
+ * @proc:	binder_proc that owns the ref
+ * @node:	binder_node of target
+ * @new_ref:	newly allocated binder_ref to be initialized or %NULL
+ *
+ * Look up the ref for the given node and return it if it exists
+ *
+ * If it doesn't exist and the caller provides a newly allocated
+ * ref, initialize the fields of the newly allocated ref and insert
+ * into the given proc rb_trees and node refs list.
+ *
+ * Return:	the ref for node. It is possible that another thread
+ *		allocated/initialized the ref first in which case the
+ *		returned ref would be different than the passed-in
+ *		new_ref. new_ref must be kfree'd by the caller in
+ *		this case.
+ */
+static struct binder_ref *binder_get_ref_for_node_olocked(
+					struct binder_proc *proc,
+					struct binder_node *node,
+					struct binder_ref *new_ref)
 {
-	struct rb_node *n;
+	struct binder_context *context = proc->context;
 	struct rb_node **p = &proc->refs_by_node.rb_node;
 	struct rb_node *parent = NULL;
-	struct binder_ref *ref, *new_ref;
+	struct binder_ref *ref;
+	struct rb_node *n;
 
 	while (*p) {
 		parent = *p;
@@ -1040,22 +1591,22 @@
 		else
 			return ref;
 	}
-	new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
-	if (new_ref == NULL)
+	if (!new_ref)
 		return NULL;
+
 	binder_stats_created(BINDER_STAT_REF);
-	new_ref->debug_id = ++binder_last_id;
+	new_ref->data.debug_id = atomic_inc_return(&binder_last_id);
 	new_ref->proc = proc;
 	new_ref->node = node;
 	rb_link_node(&new_ref->rb_node_node, parent, p);
 	rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
 
-	new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1;
+	new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1;
 	for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
 		ref = rb_entry(n, struct binder_ref, rb_node_desc);
-		if (ref->desc > new_ref->desc)
+		if (ref->data.desc > new_ref->data.desc)
 			break;
-		new_ref->desc = ref->desc + 1;
+		new_ref->data.desc = ref->data.desc + 1;
 	}
 
 	p = &proc->refs_by_desc.rb_node;
@@ -1063,121 +1614,423 @@
 		parent = *p;
 		ref = rb_entry(parent, struct binder_ref, rb_node_desc);
 
-		if (new_ref->desc < ref->desc)
+		if (new_ref->data.desc < ref->data.desc)
 			p = &(*p)->rb_left;
-		else if (new_ref->desc > ref->desc)
+		else if (new_ref->data.desc > ref->data.desc)
 			p = &(*p)->rb_right;
 		else
 			BUG();
 	}
 	rb_link_node(&new_ref->rb_node_desc, parent, p);
 	rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc);
-	if (node) {
-		hlist_add_head(&new_ref->node_entry, &node->refs);
 
-		binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-			     "%d new ref %d desc %d for node %d\n",
-			      proc->pid, new_ref->debug_id, new_ref->desc,
-			      node->debug_id);
-	} else {
-		binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-			     "%d new ref %d desc %d for dead node\n",
-			      proc->pid, new_ref->debug_id, new_ref->desc);
-	}
+	binder_node_lock(node);
+	hlist_add_head(&new_ref->node_entry, &node->refs);
+
+	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+		     "%d new ref %d desc %d for node %d\n",
+		      proc->pid, new_ref->data.debug_id, new_ref->data.desc,
+		      node->debug_id);
+	binder_node_unlock(node);
 	return new_ref;
 }
 
-static void binder_delete_ref(struct binder_ref *ref)
+static void binder_cleanup_ref_olocked(struct binder_ref *ref)
 {
+	bool delete_node = false;
+
 	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
 		     "%d delete ref %d desc %d for node %d\n",
-		      ref->proc->pid, ref->debug_id, ref->desc,
+		      ref->proc->pid, ref->data.debug_id, ref->data.desc,
 		      ref->node->debug_id);
 
 	rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);
 	rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);
-	if (ref->strong)
-		binder_dec_node(ref->node, 1, 1);
+
+	binder_node_inner_lock(ref->node);
+	if (ref->data.strong)
+		binder_dec_node_nilocked(ref->node, 1, 1);
+
 	hlist_del(&ref->node_entry);
-	binder_dec_node(ref->node, 0, 1);
+	delete_node = binder_dec_node_nilocked(ref->node, 0, 1);
+	binder_node_inner_unlock(ref->node);
+	/*
+	 * Clear ref->node unless we want the caller to free the node
+	 */
+	if (!delete_node) {
+		/*
+		 * The caller uses ref->node to determine
+		 * whether the node needs to be freed. Clear
+		 * it since the node is still alive.
+		 */
+		ref->node = NULL;
+	}
+
 	if (ref->death) {
 		binder_debug(BINDER_DEBUG_DEAD_BINDER,
 			     "%d delete ref %d desc %d has death notification\n",
-			      ref->proc->pid, ref->debug_id, ref->desc);
-		list_del(&ref->death->work.entry);
-		kfree(ref->death);
+			      ref->proc->pid, ref->data.debug_id,
+			      ref->data.desc);
+		binder_dequeue_work(ref->proc, &ref->death->work);
 		binder_stats_deleted(BINDER_STAT_DEATH);
 	}
-	kfree(ref);
 	binder_stats_deleted(BINDER_STAT_REF);
 }
 
-static int binder_inc_ref(struct binder_ref *ref, int strong,
-			  struct list_head *target_list)
+/**
+ * binder_inc_ref_olocked() - increment the ref for given handle
+ * @ref:         ref to be incremented
+ * @strong:      if true, strong increment, else weak
+ * @target_list: list to queue node work on
+ *
+ * Increment the ref. @ref->proc->outer_lock must be held on entry
+ *
+ * Return: 0, if successful, else errno
+ */
+static int binder_inc_ref_olocked(struct binder_ref *ref, int strong,
+				  struct list_head *target_list)
 {
 	int ret;
 
 	if (strong) {
-		if (ref->strong == 0) {
+		if (ref->data.strong == 0) {
 			ret = binder_inc_node(ref->node, 1, 1, target_list);
 			if (ret)
 				return ret;
 		}
-		ref->strong++;
+		ref->data.strong++;
 	} else {
-		if (ref->weak == 0) {
+		if (ref->data.weak == 0) {
 			ret = binder_inc_node(ref->node, 0, 1, target_list);
 			if (ret)
 				return ret;
 		}
-		ref->weak++;
+		ref->data.weak++;
 	}
 	return 0;
 }
 
-
-static int binder_dec_ref(struct binder_ref *ref, int strong)
+/**
+ * binder_dec_ref() - dec the ref for given handle
+ * @ref:	ref to be decremented
+ * @strong:	if true, strong decrement, else weak
+ *
+ * Decrement the ref.
+ *
+ * Return: true if ref is cleaned up and ready to be freed
+ */
+static bool binder_dec_ref_olocked(struct binder_ref *ref, int strong)
 {
 	if (strong) {
-		if (ref->strong == 0) {
+		if (ref->data.strong == 0) {
 			binder_user_error("%d invalid dec strong, ref %d desc %d s %d w %d\n",
-					  ref->proc->pid, ref->debug_id,
-					  ref->desc, ref->strong, ref->weak);
-			return -EINVAL;
+					  ref->proc->pid, ref->data.debug_id,
+					  ref->data.desc, ref->data.strong,
+					  ref->data.weak);
+			return false;
 		}
-		ref->strong--;
-		if (ref->strong == 0) {
-			int ret;
-
-			ret = binder_dec_node(ref->node, strong, 1);
-			if (ret)
-				return ret;
-		}
+		ref->data.strong--;
+		if (ref->data.strong == 0)
+			binder_dec_node(ref->node, strong, 1);
 	} else {
-		if (ref->weak == 0) {
+		if (ref->data.weak == 0) {
 			binder_user_error("%d invalid dec weak, ref %d desc %d s %d w %d\n",
-					  ref->proc->pid, ref->debug_id,
-					  ref->desc, ref->strong, ref->weak);
-			return -EINVAL;
+					  ref->proc->pid, ref->data.debug_id,
+					  ref->data.desc, ref->data.strong,
+					  ref->data.weak);
+			return false;
 		}
-		ref->weak--;
+		ref->data.weak--;
 	}
-	if (ref->strong == 0 && ref->weak == 0)
-		binder_delete_ref(ref);
-	return 0;
+	if (ref->data.strong == 0 && ref->data.weak == 0) {
+		binder_cleanup_ref_olocked(ref);
+		return true;
+	}
+	return false;
 }
 
-static void binder_pop_transaction(struct binder_thread *target_thread,
-				   struct binder_transaction *t)
+/**
+ * binder_get_node_from_ref() - get the node from the given proc/desc
+ * @proc:	proc containing the ref
+ * @desc:	the handle associated with the ref
+ * @need_strong_ref: if true, only return node if ref is strong
+ * @rdata:	the id/refcount data for the ref
+ *
+ * Given a proc and ref handle, return the associated binder_node
+ *
+ * Return: a binder_node or NULL if not found or not strong when strong required
+ */
+static struct binder_node *binder_get_node_from_ref(
+		struct binder_proc *proc,
+		u32 desc, bool need_strong_ref,
+		struct binder_ref_data *rdata)
 {
-	if (target_thread) {
-		BUG_ON(target_thread->transaction_stack != t);
-		BUG_ON(target_thread->transaction_stack->from != target_thread);
-		target_thread->transaction_stack =
-			target_thread->transaction_stack->from_parent;
-		t->from = NULL;
+	struct binder_node *node;
+	struct binder_ref *ref;
+
+	binder_proc_lock(proc);
+	ref = binder_get_ref_olocked(proc, desc, need_strong_ref);
+	if (!ref)
+		goto err_no_ref;
+	node = ref->node;
+	/*
+	 * Take an implicit reference on the node to ensure
+	 * it stays alive until the call to binder_put_node()
+	 */
+	binder_inc_node_tmpref(node);
+	if (rdata)
+		*rdata = ref->data;
+	binder_proc_unlock(proc);
+
+	return node;
+
+err_no_ref:
+	binder_proc_unlock(proc);
+	return NULL;
+}
+
+/**
+ * binder_free_ref() - free the binder_ref
+ * @ref:	ref to free
+ *
+ * Free the binder_ref. Free the binder_node indicated by ref->node
+ * (if non-NULL) and the binder_ref_death indicated by ref->death.
+ */
+static void binder_free_ref(struct binder_ref *ref)
+{
+	if (ref->node)
+		binder_free_node(ref->node);
+	kfree(ref->death);
+	kfree(ref);
+}
+
+/**
+ * binder_update_ref_for_handle() - inc/dec the ref for given handle
+ * @proc:	proc containing the ref
+ * @desc:	the handle associated with the ref
+ * @increment:	true=inc reference, false=dec reference
+ * @strong:	true=strong reference, false=weak reference
+ * @rdata:	the id/refcount data for the ref
+ *
+ * Given a proc and ref handle, increment or decrement the ref
+ * according to "increment" arg.
+ *
+ * Return: 0 if successful, else errno
+ */
+static int binder_update_ref_for_handle(struct binder_proc *proc,
+		uint32_t desc, bool increment, bool strong,
+		struct binder_ref_data *rdata)
+{
+	int ret = 0;
+	struct binder_ref *ref;
+	bool delete_ref = false;
+
+	binder_proc_lock(proc);
+	ref = binder_get_ref_olocked(proc, desc, strong);
+	if (!ref) {
+		ret = -EINVAL;
+		goto err_no_ref;
 	}
-	t->need_reply = 0;
+	if (increment)
+		ret = binder_inc_ref_olocked(ref, strong, NULL);
+	else
+		delete_ref = binder_dec_ref_olocked(ref, strong);
+
+	if (rdata)
+		*rdata = ref->data;
+	binder_proc_unlock(proc);
+
+	if (delete_ref)
+		binder_free_ref(ref);
+	return ret;
+
+err_no_ref:
+	binder_proc_unlock(proc);
+	return ret;
+}
+
+/**
+ * binder_dec_ref_for_handle() - dec the ref for given handle
+ * @proc:	proc containing the ref
+ * @desc:	the handle associated with the ref
+ * @strong:	true=strong reference, false=weak reference
+ * @rdata:	the id/refcount data for the ref
+ *
+ * Just calls binder_update_ref_for_handle() to decrement the ref.
+ *
+ * Return: 0 if successful, else errno
+ */
+static int binder_dec_ref_for_handle(struct binder_proc *proc,
+		uint32_t desc, bool strong, struct binder_ref_data *rdata)
+{
+	return binder_update_ref_for_handle(proc, desc, false, strong, rdata);
+}
+
+
+/**
+ * binder_inc_ref_for_node() - increment the ref for given proc/node
+ * @proc:	 proc containing the ref
+ * @node:	 target node
+ * @strong:	 true=strong reference, false=weak reference
+ * @target_list: worklist to use if node is incremented
+ * @rdata:	 the id/refcount data for the ref
+ *
+ * Given a proc and node, increment the ref. Create the ref if it
+ * doesn't already exist
+ *
+ * Return: 0 if successful, else errno
+ */
+static int binder_inc_ref_for_node(struct binder_proc *proc,
+			struct binder_node *node,
+			bool strong,
+			struct list_head *target_list,
+			struct binder_ref_data *rdata)
+{
+	struct binder_ref *ref;
+	struct binder_ref *new_ref = NULL;
+	int ret = 0;
+
+	binder_proc_lock(proc);
+	ref = binder_get_ref_for_node_olocked(proc, node, NULL);
+	if (!ref) {
+		binder_proc_unlock(proc);
+		new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+		if (!new_ref)
+			return -ENOMEM;
+		binder_proc_lock(proc);
+		ref = binder_get_ref_for_node_olocked(proc, node, new_ref);
+	}
+	ret = binder_inc_ref_olocked(ref, strong, target_list);
+	*rdata = ref->data;
+	binder_proc_unlock(proc);
+	if (new_ref && ref != new_ref)
+		/*
+		 * Another thread created the ref first so
+		 * free the one we allocated
+		 */
+		kfree(new_ref);
+	return ret;
+}
+
+static void binder_pop_transaction_ilocked(struct binder_thread *target_thread,
+					   struct binder_transaction *t)
+{
+	BUG_ON(!target_thread);
+	BUG_ON(!spin_is_locked(&target_thread->proc->inner_lock));
+	BUG_ON(target_thread->transaction_stack != t);
+	BUG_ON(target_thread->transaction_stack->from != target_thread);
+	target_thread->transaction_stack =
+		target_thread->transaction_stack->from_parent;
+	t->from = NULL;
+}
+
+/**
+ * binder_thread_dec_tmpref() - decrement thread->tmp_ref
+ * @thread:	thread to decrement
+ *
+ * A thread needs to be kept alive while being used to create or
+ * handle a transaction. binder_get_txn_from() is used to safely
+ * extract t->from from a binder_transaction and keep the thread
+ * indicated by t->from from being freed. When done with that
+ * binder_thread, this function is called to decrement the
+ * tmp_ref and free if appropriate (thread has been released
+ * and no transaction being processed by the driver)
+ */
+static void binder_thread_dec_tmpref(struct binder_thread *thread)
+{
+	/*
+	 * atomic is used to protect the counter value while
+	 * it cannot reach zero or thread->is_dead is false
+	 */
+	binder_inner_proc_lock(thread->proc);
+	atomic_dec(&thread->tmp_ref);
+	if (thread->is_dead && !atomic_read(&thread->tmp_ref)) {
+		binder_inner_proc_unlock(thread->proc);
+		binder_free_thread(thread);
+		return;
+	}
+	binder_inner_proc_unlock(thread->proc);
+}
+
+/**
+ * binder_proc_dec_tmpref() - decrement proc->tmp_ref
+ * @proc:	proc to decrement
+ *
+ * A binder_proc needs to be kept alive while being used to create or
+ * handle a transaction. proc->tmp_ref is incremented when
+ * creating a new transaction or the binder_proc is currently in-use
+ * by threads that are being released. When done with the binder_proc,
+ * this function is called to decrement the counter and free the
+ * proc if appropriate (proc has been released, all threads have
+ * been released and not currenly in-use to process a transaction).
+ */
+static void binder_proc_dec_tmpref(struct binder_proc *proc)
+{
+	binder_inner_proc_lock(proc);
+	proc->tmp_ref--;
+	if (proc->is_dead && RB_EMPTY_ROOT(&proc->threads) &&
+			!proc->tmp_ref) {
+		binder_inner_proc_unlock(proc);
+		binder_free_proc(proc);
+		return;
+	}
+	binder_inner_proc_unlock(proc);
+}
+
+/**
+ * binder_get_txn_from() - safely extract the "from" thread in transaction
+ * @t:	binder transaction for t->from
+ *
+ * Atomically return the "from" thread and increment the tmp_ref
+ * count for the thread to ensure it stays alive until
+ * binder_thread_dec_tmpref() is called.
+ *
+ * Return: the value of t->from
+ */
+static struct binder_thread *binder_get_txn_from(
+		struct binder_transaction *t)
+{
+	struct binder_thread *from;
+
+	spin_lock(&t->lock);
+	from = t->from;
+	if (from)
+		atomic_inc(&from->tmp_ref);
+	spin_unlock(&t->lock);
+	return from;
+}
+
+/**
+ * binder_get_txn_from_and_acq_inner() - get t->from and acquire inner lock
+ * @t:	binder transaction for t->from
+ *
+ * Same as binder_get_txn_from() except it also acquires the proc->inner_lock
+ * to guarantee that the thread cannot be released while operating on it.
+ * The caller must call binder_inner_proc_unlock() to release the inner lock
+ * as well as call binder_dec_thread_txn() to release the reference.
+ *
+ * Return: the value of t->from
+ */
+static struct binder_thread *binder_get_txn_from_and_acq_inner(
+		struct binder_transaction *t)
+{
+	struct binder_thread *from;
+
+	from = binder_get_txn_from(t);
+	if (!from)
+		return NULL;
+	binder_inner_proc_lock(from->proc);
+	if (t->from) {
+		BUG_ON(from != t->from);
+		return from;
+	}
+	binder_inner_proc_unlock(from->proc);
+	binder_thread_dec_tmpref(from);
+	return NULL;
+}
+
+static void binder_free_transaction(struct binder_transaction *t)
+{
 	if (t->buffer)
 		t->buffer->transaction = NULL;
 	kfree(t);
@@ -1192,30 +2045,28 @@
 
 	BUG_ON(t->flags & TF_ONE_WAY);
 	while (1) {
-		target_thread = t->from;
+		target_thread = binder_get_txn_from_and_acq_inner(t);
 		if (target_thread) {
-			if (target_thread->return_error != BR_OK &&
-			   target_thread->return_error2 == BR_OK) {
-				target_thread->return_error2 =
-					target_thread->return_error;
-				target_thread->return_error = BR_OK;
-			}
-			if (target_thread->return_error == BR_OK) {
-				binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-					     "send failed reply for transaction %d to %d:%d\n",
-					      t->debug_id,
-					      target_thread->proc->pid,
-					      target_thread->pid);
+			binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+				     "send failed reply for transaction %d to %d:%d\n",
+				      t->debug_id,
+				      target_thread->proc->pid,
+				      target_thread->pid);
 
-				binder_pop_transaction(target_thread, t);
-				target_thread->return_error = error_code;
+			binder_pop_transaction_ilocked(target_thread, t);
+			if (target_thread->reply_error.cmd == BR_OK) {
+				target_thread->reply_error.cmd = error_code;
+				binder_enqueue_work_ilocked(
+					&target_thread->reply_error.work,
+					&target_thread->todo);
 				wake_up_interruptible(&target_thread->wait);
 			} else {
-				pr_err("reply failed, target thread, %d:%d, has error code %d already\n",
-					target_thread->proc->pid,
-					target_thread->pid,
-					target_thread->return_error);
+				WARN(1, "Unexpected reply error: %u\n",
+						target_thread->reply_error.cmd);
 			}
+			binder_inner_proc_unlock(target_thread->proc);
+			binder_thread_dec_tmpref(target_thread);
+			binder_free_transaction(t);
 			return;
 		}
 		next = t->from_parent;
@@ -1224,7 +2075,7 @@
 			     "send failed reply for transaction %d, target dead\n",
 			     t->debug_id);
 
-		binder_pop_transaction(target_thread, t);
+		binder_free_transaction(t);
 		if (next == NULL) {
 			binder_debug(BINDER_DEBUG_DEAD_BINDER,
 				     "reply failed, no target thread at root\n");
@@ -1237,11 +2088,158 @@
 	}
 }
 
+/**
+ * binder_validate_object() - checks for a valid metadata object in a buffer.
+ * @buffer:	binder_buffer that we're parsing.
+ * @offset:	offset in the buffer at which to validate an object.
+ *
+ * Return:	If there's a valid metadata object at @offset in @buffer, the
+ *		size of that object. Otherwise, it returns zero.
+ */
+static size_t binder_validate_object(struct binder_buffer *buffer, u64 offset)
+{
+	/* Check if we can read a header first */
+	struct binder_object_header *hdr;
+	size_t object_size = 0;
+
+	if (offset > buffer->data_size - sizeof(*hdr) ||
+	    buffer->data_size < sizeof(*hdr) ||
+	    !IS_ALIGNED(offset, sizeof(u32)))
+		return 0;
+
+	/* Ok, now see if we can read a complete object. */
+	hdr = (struct binder_object_header *)(buffer->data + offset);
+	switch (hdr->type) {
+	case BINDER_TYPE_BINDER:
+	case BINDER_TYPE_WEAK_BINDER:
+	case BINDER_TYPE_HANDLE:
+	case BINDER_TYPE_WEAK_HANDLE:
+		object_size = sizeof(struct flat_binder_object);
+		break;
+	case BINDER_TYPE_FD:
+		object_size = sizeof(struct binder_fd_object);
+		break;
+	case BINDER_TYPE_PTR:
+		object_size = sizeof(struct binder_buffer_object);
+		break;
+	case BINDER_TYPE_FDA:
+		object_size = sizeof(struct binder_fd_array_object);
+		break;
+	default:
+		return 0;
+	}
+	if (offset <= buffer->data_size - object_size &&
+	    buffer->data_size >= object_size)
+		return object_size;
+	else
+		return 0;
+}
+
+/**
+ * binder_validate_ptr() - validates binder_buffer_object in a binder_buffer.
+ * @b:		binder_buffer containing the object
+ * @index:	index in offset array at which the binder_buffer_object is
+ *		located
+ * @start:	points to the start of the offset array
+ * @num_valid:	the number of valid offsets in the offset array
+ *
+ * Return:	If @index is within the valid range of the offset array
+ *		described by @start and @num_valid, and if there's a valid
+ *		binder_buffer_object at the offset found in index @index
+ *		of the offset array, that object is returned. Otherwise,
+ *		%NULL is returned.
+ *		Note that the offset found in index @index itself is not
+ *		verified; this function assumes that @num_valid elements
+ *		from @start were previously verified to have valid offsets.
+ */
+static struct binder_buffer_object *binder_validate_ptr(struct binder_buffer *b,
+							binder_size_t index,
+							binder_size_t *start,
+							binder_size_t num_valid)
+{
+	struct binder_buffer_object *buffer_obj;
+	binder_size_t *offp;
+
+	if (index >= num_valid)
+		return NULL;
+
+	offp = start + index;
+	buffer_obj = (struct binder_buffer_object *)(b->data + *offp);
+	if (buffer_obj->hdr.type != BINDER_TYPE_PTR)
+		return NULL;
+
+	return buffer_obj;
+}
+
+/**
+ * binder_validate_fixup() - validates pointer/fd fixups happen in order.
+ * @b:			transaction buffer
+ * @objects_start	start of objects buffer
+ * @buffer:		binder_buffer_object in which to fix up
+ * @offset:		start offset in @buffer to fix up
+ * @last_obj:		last binder_buffer_object that we fixed up in
+ * @last_min_offset:	minimum fixup offset in @last_obj
+ *
+ * Return:		%true if a fixup in buffer @buffer at offset @offset is
+ *			allowed.
+ *
+ * For safety reasons, we only allow fixups inside a buffer to happen
+ * at increasing offsets; additionally, we only allow fixup on the last
+ * buffer object that was verified, or one of its parents.
+ *
+ * Example of what is allowed:
+ *
+ * A
+ *   B (parent = A, offset = 0)
+ *   C (parent = A, offset = 16)
+ *     D (parent = C, offset = 0)
+ *   E (parent = A, offset = 32) // min_offset is 16 (C.parent_offset)
+ *
+ * Examples of what is not allowed:
+ *
+ * Decreasing offsets within the same parent:
+ * A
+ *   C (parent = A, offset = 16)
+ *   B (parent = A, offset = 0) // decreasing offset within A
+ *
+ * Referring to a parent that wasn't the last object or any of its parents:
+ * A
+ *   B (parent = A, offset = 0)
+ *   C (parent = A, offset = 0)
+ *   C (parent = A, offset = 16)
+ *     D (parent = B, offset = 0) // B is not A or any of A's parents
+ */
+static bool binder_validate_fixup(struct binder_buffer *b,
+				  binder_size_t *objects_start,
+				  struct binder_buffer_object *buffer,
+				  binder_size_t fixup_offset,
+				  struct binder_buffer_object *last_obj,
+				  binder_size_t last_min_offset)
+{
+	if (!last_obj) {
+		/* Nothing to fix up in */
+		return false;
+	}
+
+	while (last_obj != buffer) {
+		/*
+		 * Safe to retrieve the parent of last_obj, since it
+		 * was already previously verified by the driver.
+		 */
+		if ((last_obj->flags & BINDER_BUFFER_FLAG_HAS_PARENT) == 0)
+			return false;
+		last_min_offset = last_obj->parent_offset + sizeof(uintptr_t);
+		last_obj = (struct binder_buffer_object *)
+			(b->data + *(objects_start + last_obj->parent));
+	}
+	return (fixup_offset >= last_min_offset);
+}
+
 static void binder_transaction_buffer_release(struct binder_proc *proc,
 					      struct binder_buffer *buffer,
 					      binder_size_t *failed_at)
 {
-	binder_size_t *offp, *off_end;
+	binder_size_t *offp, *off_start, *off_end;
 	int debug_id = buffer->debug_id;
 
 	binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1252,28 +2250,30 @@
 	if (buffer->target_node)
 		binder_dec_node(buffer->target_node, 1, 0);
 
-	offp = (binder_size_t *)(buffer->data +
-				 ALIGN(buffer->data_size, sizeof(void *)));
+	off_start = (binder_size_t *)(buffer->data +
+				      ALIGN(buffer->data_size, sizeof(void *)));
 	if (failed_at)
 		off_end = failed_at;
 	else
-		off_end = (void *)offp + buffer->offsets_size;
-	for (; offp < off_end; offp++) {
-		struct flat_binder_object *fp;
+		off_end = (void *)off_start + buffer->offsets_size;
+	for (offp = off_start; offp < off_end; offp++) {
+		struct binder_object_header *hdr;
+		size_t object_size = binder_validate_object(buffer, *offp);
 
-		if (*offp > buffer->data_size - sizeof(*fp) ||
-		    buffer->data_size < sizeof(*fp) ||
-		    !IS_ALIGNED(*offp, sizeof(u32))) {
-			pr_err("transaction release %d bad offset %lld, size %zd\n",
+		if (object_size == 0) {
+			pr_err("transaction release %d bad object at offset %lld, size %zd\n",
 			       debug_id, (u64)*offp, buffer->data_size);
 			continue;
 		}
-		fp = (struct flat_binder_object *)(buffer->data + *offp);
-		switch (fp->type) {
+		hdr = (struct binder_object_header *)(buffer->data + *offp);
+		switch (hdr->type) {
 		case BINDER_TYPE_BINDER:
 		case BINDER_TYPE_WEAK_BINDER: {
-			struct binder_node *node = binder_get_node(proc, fp->binder);
+			struct flat_binder_object *fp;
+			struct binder_node *node;
 
+			fp = to_flat_binder_object(hdr);
+			node = binder_get_node(proc, fp->binder);
 			if (node == NULL) {
 				pr_err("transaction release %d bad node %016llx\n",
 				       debug_id, (u64)fp->binder);
@@ -1282,87 +2282,523 @@
 			binder_debug(BINDER_DEBUG_TRANSACTION,
 				     "        node %d u%016llx\n",
 				     node->debug_id, (u64)node->ptr);
-			binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
+			binder_dec_node(node, hdr->type == BINDER_TYPE_BINDER,
+					0);
+			binder_put_node(node);
 		} break;
 		case BINDER_TYPE_HANDLE:
 		case BINDER_TYPE_WEAK_HANDLE: {
-			struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+			struct flat_binder_object *fp;
+			struct binder_ref_data rdata;
+			int ret;
 
-			if (ref == NULL) {
-				pr_err("transaction release %d bad handle %d\n",
-				 debug_id, fp->handle);
+			fp = to_flat_binder_object(hdr);
+			ret = binder_dec_ref_for_handle(proc, fp->handle,
+				hdr->type == BINDER_TYPE_HANDLE, &rdata);
+
+			if (ret) {
+				pr_err("transaction release %d bad handle %d, ret = %d\n",
+				 debug_id, fp->handle, ret);
 				break;
 			}
 			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        ref %d desc %d (node %d)\n",
-				     ref->debug_id, ref->desc, ref->node->debug_id);
-			binder_dec_ref(ref, fp->type == BINDER_TYPE_HANDLE);
+				     "        ref %d desc %d\n",
+				     rdata.debug_id, rdata.desc);
 		} break;
 
-		case BINDER_TYPE_FD:
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        fd %d\n", fp->handle);
-			if (failed_at)
-				task_close_fd(proc, fp->handle);
-			break;
+		case BINDER_TYPE_FD: {
+			struct binder_fd_object *fp = to_binder_fd_object(hdr);
 
+			binder_debug(BINDER_DEBUG_TRANSACTION,
+				     "        fd %d\n", fp->fd);
+			if (failed_at)
+				task_close_fd(proc, fp->fd);
+		} break;
+		case BINDER_TYPE_PTR:
+			/*
+			 * Nothing to do here, this will get cleaned up when the
+			 * transaction buffer gets freed
+			 */
+			break;
+		case BINDER_TYPE_FDA: {
+			struct binder_fd_array_object *fda;
+			struct binder_buffer_object *parent;
+			uintptr_t parent_buffer;
+			u32 *fd_array;
+			size_t fd_index;
+			binder_size_t fd_buf_size;
+
+			fda = to_binder_fd_array_object(hdr);
+			parent = binder_validate_ptr(buffer, fda->parent,
+						     off_start,
+						     offp - off_start);
+			if (!parent) {
+				pr_err("transaction release %d bad parent offset",
+				       debug_id);
+				continue;
+			}
+			/*
+			 * Since the parent was already fixed up, convert it
+			 * back to kernel address space to access it
+			 */
+			parent_buffer = parent->buffer -
+				binder_alloc_get_user_buffer_offset(
+						&proc->alloc);
+
+			fd_buf_size = sizeof(u32) * fda->num_fds;
+			if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
+				pr_err("transaction release %d invalid number of fds (%lld)\n",
+				       debug_id, (u64)fda->num_fds);
+				continue;
+			}
+			if (fd_buf_size > parent->length ||
+			    fda->parent_offset > parent->length - fd_buf_size) {
+				/* No space for all file descriptors here. */
+				pr_err("transaction release %d not enough space for %lld fds in buffer\n",
+				       debug_id, (u64)fda->num_fds);
+				continue;
+			}
+			fd_array = (u32 *)(parent_buffer + fda->parent_offset);
+			for (fd_index = 0; fd_index < fda->num_fds; fd_index++)
+				task_close_fd(proc, fd_array[fd_index]);
+		} break;
 		default:
 			pr_err("transaction release %d bad object type %x\n",
-				debug_id, fp->type);
+				debug_id, hdr->type);
 			break;
 		}
 	}
 }
 
+static int binder_translate_binder(struct flat_binder_object *fp,
+				   struct binder_transaction *t,
+				   struct binder_thread *thread)
+{
+	struct binder_node *node;
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+	struct binder_ref_data rdata;
+	int ret = 0;
+
+	node = binder_get_node(proc, fp->binder);
+	if (!node) {
+		node = binder_new_node(proc, fp);
+		if (!node)
+			return -ENOMEM;
+	}
+	if (fp->cookie != node->cookie) {
+		binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n",
+				  proc->pid, thread->pid, (u64)fp->binder,
+				  node->debug_id, (u64)fp->cookie,
+				  (u64)node->cookie);
+		ret = -EINVAL;
+		goto done;
+	}
+	if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
+		ret = -EPERM;
+		goto done;
+	}
+
+	ret = binder_inc_ref_for_node(target_proc, node,
+			fp->hdr.type == BINDER_TYPE_BINDER,
+			&thread->todo, &rdata);
+	if (ret)
+		goto done;
+
+	if (fp->hdr.type == BINDER_TYPE_BINDER)
+		fp->hdr.type = BINDER_TYPE_HANDLE;
+	else
+		fp->hdr.type = BINDER_TYPE_WEAK_HANDLE;
+	fp->binder = 0;
+	fp->handle = rdata.desc;
+	fp->cookie = 0;
+
+	trace_binder_transaction_node_to_ref(t, node, &rdata);
+	binder_debug(BINDER_DEBUG_TRANSACTION,
+		     "        node %d u%016llx -> ref %d desc %d\n",
+		     node->debug_id, (u64)node->ptr,
+		     rdata.debug_id, rdata.desc);
+done:
+	binder_put_node(node);
+	return ret;
+}
+
+static int binder_translate_handle(struct flat_binder_object *fp,
+				   struct binder_transaction *t,
+				   struct binder_thread *thread)
+{
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+	struct binder_node *node;
+	struct binder_ref_data src_rdata;
+	int ret = 0;
+
+	node = binder_get_node_from_ref(proc, fp->handle,
+			fp->hdr.type == BINDER_TYPE_HANDLE, &src_rdata);
+	if (!node) {
+		binder_user_error("%d:%d got transaction with invalid handle, %d\n",
+				  proc->pid, thread->pid, fp->handle);
+		return -EINVAL;
+	}
+	if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
+		ret = -EPERM;
+		goto done;
+	}
+
+	binder_node_lock(node);
+	if (node->proc == target_proc) {
+		if (fp->hdr.type == BINDER_TYPE_HANDLE)
+			fp->hdr.type = BINDER_TYPE_BINDER;
+		else
+			fp->hdr.type = BINDER_TYPE_WEAK_BINDER;
+		fp->binder = node->ptr;
+		fp->cookie = node->cookie;
+		if (node->proc)
+			binder_inner_proc_lock(node->proc);
+		binder_inc_node_nilocked(node,
+					 fp->hdr.type == BINDER_TYPE_BINDER,
+					 0, NULL);
+		if (node->proc)
+			binder_inner_proc_unlock(node->proc);
+		trace_binder_transaction_ref_to_node(t, node, &src_rdata);
+		binder_debug(BINDER_DEBUG_TRANSACTION,
+			     "        ref %d desc %d -> node %d u%016llx\n",
+			     src_rdata.debug_id, src_rdata.desc, node->debug_id,
+			     (u64)node->ptr);
+		binder_node_unlock(node);
+	} else {
+		int ret;
+		struct binder_ref_data dest_rdata;
+
+		binder_node_unlock(node);
+		ret = binder_inc_ref_for_node(target_proc, node,
+				fp->hdr.type == BINDER_TYPE_HANDLE,
+				NULL, &dest_rdata);
+		if (ret)
+			goto done;
+
+		fp->binder = 0;
+		fp->handle = dest_rdata.desc;
+		fp->cookie = 0;
+		trace_binder_transaction_ref_to_ref(t, node, &src_rdata,
+						    &dest_rdata);
+		binder_debug(BINDER_DEBUG_TRANSACTION,
+			     "        ref %d desc %d -> ref %d desc %d (node %d)\n",
+			     src_rdata.debug_id, src_rdata.desc,
+			     dest_rdata.debug_id, dest_rdata.desc,
+			     node->debug_id);
+	}
+done:
+	binder_put_node(node);
+	return ret;
+}
+
+static int binder_translate_fd(int fd,
+			       struct binder_transaction *t,
+			       struct binder_thread *thread,
+			       struct binder_transaction *in_reply_to)
+{
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+	int target_fd;
+	struct file *file;
+	int ret;
+	bool target_allows_fd;
+
+	if (in_reply_to)
+		target_allows_fd = !!(in_reply_to->flags & TF_ACCEPT_FDS);
+	else
+		target_allows_fd = t->buffer->target_node->accept_fds;
+	if (!target_allows_fd) {
+		binder_user_error("%d:%d got %s with fd, %d, but target does not allow fds\n",
+				  proc->pid, thread->pid,
+				  in_reply_to ? "reply" : "transaction",
+				  fd);
+		ret = -EPERM;
+		goto err_fd_not_accepted;
+	}
+
+	file = fget(fd);
+	if (!file) {
+		binder_user_error("%d:%d got transaction with invalid fd, %d\n",
+				  proc->pid, thread->pid, fd);
+		ret = -EBADF;
+		goto err_fget;
+	}
+	ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file);
+	if (ret < 0) {
+		ret = -EPERM;
+		goto err_security;
+	}
+
+	target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
+	if (target_fd < 0) {
+		ret = -ENOMEM;
+		goto err_get_unused_fd;
+	}
+	task_fd_install(target_proc, target_fd, file);
+	trace_binder_transaction_fd(t, fd, target_fd);
+	binder_debug(BINDER_DEBUG_TRANSACTION, "        fd %d -> %d\n",
+		     fd, target_fd);
+
+	return target_fd;
+
+err_get_unused_fd:
+err_security:
+	fput(file);
+err_fget:
+err_fd_not_accepted:
+	return ret;
+}
+
+static int binder_translate_fd_array(struct binder_fd_array_object *fda,
+				     struct binder_buffer_object *parent,
+				     struct binder_transaction *t,
+				     struct binder_thread *thread,
+				     struct binder_transaction *in_reply_to)
+{
+	binder_size_t fdi, fd_buf_size, num_installed_fds;
+	int target_fd;
+	uintptr_t parent_buffer;
+	u32 *fd_array;
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+
+	fd_buf_size = sizeof(u32) * fda->num_fds;
+	if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
+		binder_user_error("%d:%d got transaction with invalid number of fds (%lld)\n",
+				  proc->pid, thread->pid, (u64)fda->num_fds);
+		return -EINVAL;
+	}
+	if (fd_buf_size > parent->length ||
+	    fda->parent_offset > parent->length - fd_buf_size) {
+		/* No space for all file descriptors here. */
+		binder_user_error("%d:%d not enough space to store %lld fds in buffer\n",
+				  proc->pid, thread->pid, (u64)fda->num_fds);
+		return -EINVAL;
+	}
+	/*
+	 * Since the parent was already fixed up, convert it
+	 * back to the kernel address space to access it
+	 */
+	parent_buffer = parent->buffer -
+		binder_alloc_get_user_buffer_offset(&target_proc->alloc);
+	fd_array = (u32 *)(parent_buffer + fda->parent_offset);
+	if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) {
+		binder_user_error("%d:%d parent offset not aligned correctly.\n",
+				  proc->pid, thread->pid);
+		return -EINVAL;
+	}
+	for (fdi = 0; fdi < fda->num_fds; fdi++) {
+		target_fd = binder_translate_fd(fd_array[fdi], t, thread,
+						in_reply_to);
+		if (target_fd < 0)
+			goto err_translate_fd_failed;
+		fd_array[fdi] = target_fd;
+	}
+	return 0;
+
+err_translate_fd_failed:
+	/*
+	 * Failed to allocate fd or security error, free fds
+	 * installed so far.
+	 */
+	num_installed_fds = fdi;
+	for (fdi = 0; fdi < num_installed_fds; fdi++)
+		task_close_fd(target_proc, fd_array[fdi]);
+	return target_fd;
+}
+
+static int binder_fixup_parent(struct binder_transaction *t,
+			       struct binder_thread *thread,
+			       struct binder_buffer_object *bp,
+			       binder_size_t *off_start,
+			       binder_size_t num_valid,
+			       struct binder_buffer_object *last_fixup_obj,
+			       binder_size_t last_fixup_min_off)
+{
+	struct binder_buffer_object *parent;
+	u8 *parent_buffer;
+	struct binder_buffer *b = t->buffer;
+	struct binder_proc *proc = thread->proc;
+	struct binder_proc *target_proc = t->to_proc;
+
+	if (!(bp->flags & BINDER_BUFFER_FLAG_HAS_PARENT))
+		return 0;
+
+	parent = binder_validate_ptr(b, bp->parent, off_start, num_valid);
+	if (!parent) {
+		binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
+				  proc->pid, thread->pid);
+		return -EINVAL;
+	}
+
+	if (!binder_validate_fixup(b, off_start,
+				   parent, bp->parent_offset,
+				   last_fixup_obj,
+				   last_fixup_min_off)) {
+		binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n",
+				  proc->pid, thread->pid);
+		return -EINVAL;
+	}
+
+	if (parent->length < sizeof(binder_uintptr_t) ||
+	    bp->parent_offset > parent->length - sizeof(binder_uintptr_t)) {
+		/* No space for a pointer here! */
+		binder_user_error("%d:%d got transaction with invalid parent offset\n",
+				  proc->pid, thread->pid);
+		return -EINVAL;
+	}
+	parent_buffer = (u8 *)(parent->buffer -
+			binder_alloc_get_user_buffer_offset(
+				&target_proc->alloc));
+	*(binder_uintptr_t *)(parent_buffer + bp->parent_offset) = bp->buffer;
+
+	return 0;
+}
+
+/**
+ * binder_proc_transaction() - sends a transaction to a process and wakes it up
+ * @t:		transaction to send
+ * @proc:	process to send the transaction to
+ * @thread:	thread in @proc to send the transaction to (may be NULL)
+ *
+ * This function queues a transaction to the specified process. It will try
+ * to find a thread in the target process to handle the transaction and
+ * wake it up. If no thread is found, the work is queued to the proc
+ * waitqueue.
+ *
+ * If the @thread parameter is not NULL, the transaction is always queued
+ * to the waitlist of that specific thread.
+ *
+ * Return:	true if the transactions was successfully queued
+ *		false if the target process or thread is dead
+ */
+static bool binder_proc_transaction(struct binder_transaction *t,
+				    struct binder_proc *proc,
+				    struct binder_thread *thread)
+{
+	struct list_head *target_list = NULL;
+	struct binder_node *node = t->buffer->target_node;
+	struct binder_priority node_prio;
+	bool oneway = !!(t->flags & TF_ONE_WAY);
+	bool wakeup = true;
+
+	BUG_ON(!node);
+	binder_node_lock(node);
+	node_prio.prio = node->min_priority;
+	node_prio.sched_policy = node->sched_policy;
+
+	if (oneway) {
+		BUG_ON(thread);
+		if (node->has_async_transaction) {
+			target_list = &node->async_todo;
+			wakeup = false;
+		} else {
+			node->has_async_transaction = 1;
+		}
+	}
+
+	binder_inner_proc_lock(proc);
+
+	if (proc->is_dead || (thread && thread->is_dead)) {
+		binder_inner_proc_unlock(proc);
+		binder_node_unlock(node);
+		return false;
+	}
+
+	if (!thread && !target_list)
+		thread = binder_select_thread_ilocked(proc);
+
+	if (thread) {
+		target_list = &thread->todo;
+		binder_transaction_priority(thread->task, t, node_prio,
+					    node->inherit_rt);
+	} else if (!target_list) {
+		target_list = &proc->todo;
+	} else {
+		BUG_ON(target_list != &node->async_todo);
+	}
+
+	binder_enqueue_work_ilocked(&t->work, target_list);
+
+	if (wakeup)
+		binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */);
+
+	binder_inner_proc_unlock(proc);
+	binder_node_unlock(node);
+
+	return true;
+}
+
 static void binder_transaction(struct binder_proc *proc,
 			       struct binder_thread *thread,
-			       struct binder_transaction_data *tr, int reply)
+			       struct binder_transaction_data *tr, int reply,
+			       binder_size_t extra_buffers_size)
 {
+	int ret;
 	struct binder_transaction *t;
 	struct binder_work *tcomplete;
-	binder_size_t *offp, *off_end;
+	binder_size_t *offp, *off_end, *off_start;
 	binder_size_t off_min;
-	struct binder_proc *target_proc;
+	u8 *sg_bufp, *sg_buf_end;
+	struct binder_proc *target_proc = NULL;
 	struct binder_thread *target_thread = NULL;
 	struct binder_node *target_node = NULL;
-	struct list_head *target_list;
-	wait_queue_head_t *target_wait;
 	struct binder_transaction *in_reply_to = NULL;
 	struct binder_transaction_log_entry *e;
-	uint32_t return_error;
+	uint32_t return_error = 0;
+	uint32_t return_error_param = 0;
+	uint32_t return_error_line = 0;
+	struct binder_buffer_object *last_fixup_obj = NULL;
+	binder_size_t last_fixup_min_off = 0;
+	struct binder_context *context = proc->context;
+	int t_debug_id = atomic_inc_return(&binder_last_id);
 
 	e = binder_transaction_log_add(&binder_transaction_log);
+	e->debug_id = t_debug_id;
 	e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
 	e->from_proc = proc->pid;
 	e->from_thread = thread->pid;
 	e->target_handle = tr->target.handle;
 	e->data_size = tr->data_size;
 	e->offsets_size = tr->offsets_size;
+	e->context_name = proc->context->name;
 
 	if (reply) {
+		binder_inner_proc_lock(proc);
 		in_reply_to = thread->transaction_stack;
 		if (in_reply_to == NULL) {
+			binder_inner_proc_unlock(proc);
 			binder_user_error("%d:%d got reply transaction with no transaction stack\n",
 					  proc->pid, thread->pid);
 			return_error = BR_FAILED_REPLY;
+			return_error_param = -EPROTO;
+			return_error_line = __LINE__;
 			goto err_empty_call_stack;
 		}
-		binder_set_nice(in_reply_to->saved_priority);
 		if (in_reply_to->to_thread != thread) {
+			spin_lock(&in_reply_to->lock);
 			binder_user_error("%d:%d got reply transaction with bad transaction stack, transaction %d has target %d:%d\n",
 				proc->pid, thread->pid, in_reply_to->debug_id,
 				in_reply_to->to_proc ?
 				in_reply_to->to_proc->pid : 0,
 				in_reply_to->to_thread ?
 				in_reply_to->to_thread->pid : 0);
+			spin_unlock(&in_reply_to->lock);
+			binder_inner_proc_unlock(proc);
 			return_error = BR_FAILED_REPLY;
+			return_error_param = -EPROTO;
+			return_error_line = __LINE__;
 			in_reply_to = NULL;
 			goto err_bad_call_stack;
 		}
 		thread->transaction_stack = in_reply_to->to_parent;
-		target_thread = in_reply_to->from;
+		binder_inner_proc_unlock(proc);
+		target_thread = binder_get_txn_from_and_acq_inner(in_reply_to);
 		if (target_thread == NULL) {
 			return_error = BR_DEAD_REPLY;
+			return_error_line = __LINE__;
 			goto err_dead_binder;
 		}
 		if (target_thread->transaction_stack != in_reply_to) {
@@ -1371,106 +2807,156 @@
 				target_thread->transaction_stack ?
 				target_thread->transaction_stack->debug_id : 0,
 				in_reply_to->debug_id);
+			binder_inner_proc_unlock(target_thread->proc);
 			return_error = BR_FAILED_REPLY;
+			return_error_param = -EPROTO;
+			return_error_line = __LINE__;
 			in_reply_to = NULL;
 			target_thread = NULL;
 			goto err_dead_binder;
 		}
 		target_proc = target_thread->proc;
+		target_proc->tmp_ref++;
+		binder_inner_proc_unlock(target_thread->proc);
 	} else {
 		if (tr->target.handle) {
 			struct binder_ref *ref;
 
-			ref = binder_get_ref(proc, tr->target.handle);
-			if (ref == NULL) {
+			/*
+			 * There must already be a strong ref
+			 * on this node. If so, do a strong
+			 * increment on the node to ensure it
+			 * stays alive until the transaction is
+			 * done.
+			 */
+			binder_proc_lock(proc);
+			ref = binder_get_ref_olocked(proc, tr->target.handle,
+						     true);
+			if (ref) {
+				binder_inc_node(ref->node, 1, 0, NULL);
+				target_node = ref->node;
+			}
+			binder_proc_unlock(proc);
+			if (target_node == NULL) {
 				binder_user_error("%d:%d got transaction to invalid handle\n",
 					proc->pid, thread->pid);
 				return_error = BR_FAILED_REPLY;
+				return_error_param = -EINVAL;
+				return_error_line = __LINE__;
 				goto err_invalid_target_handle;
 			}
-			target_node = ref->node;
 		} else {
-			target_node = binder_context_mgr_node;
+			mutex_lock(&context->context_mgr_node_lock);
+			target_node = context->binder_context_mgr_node;
 			if (target_node == NULL) {
 				return_error = BR_DEAD_REPLY;
+				mutex_unlock(&context->context_mgr_node_lock);
+				return_error_line = __LINE__;
 				goto err_no_context_mgr_node;
 			}
+			binder_inc_node(target_node, 1, 0, NULL);
+			mutex_unlock(&context->context_mgr_node_lock);
 		}
 		e->to_node = target_node->debug_id;
+		binder_node_lock(target_node);
 		target_proc = target_node->proc;
 		if (target_proc == NULL) {
+			binder_node_unlock(target_node);
 			return_error = BR_DEAD_REPLY;
+			return_error_line = __LINE__;
 			goto err_dead_binder;
 		}
+		binder_inner_proc_lock(target_proc);
+		target_proc->tmp_ref++;
+		binder_inner_proc_unlock(target_proc);
+		binder_node_unlock(target_node);
 		if (security_binder_transaction(proc->tsk,
 						target_proc->tsk) < 0) {
 			return_error = BR_FAILED_REPLY;
+			return_error_param = -EPERM;
+			return_error_line = __LINE__;
 			goto err_invalid_target_handle;
 		}
+		binder_inner_proc_lock(proc);
 		if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
 			struct binder_transaction *tmp;
 
 			tmp = thread->transaction_stack;
 			if (tmp->to_thread != thread) {
+				spin_lock(&tmp->lock);
 				binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n",
 					proc->pid, thread->pid, tmp->debug_id,
 					tmp->to_proc ? tmp->to_proc->pid : 0,
 					tmp->to_thread ?
 					tmp->to_thread->pid : 0);
+				spin_unlock(&tmp->lock);
+				binder_inner_proc_unlock(proc);
 				return_error = BR_FAILED_REPLY;
+				return_error_param = -EPROTO;
+				return_error_line = __LINE__;
 				goto err_bad_call_stack;
 			}
 			while (tmp) {
-				if (tmp->from && tmp->from->proc == target_proc)
-					target_thread = tmp->from;
+				struct binder_thread *from;
+
+				spin_lock(&tmp->lock);
+				from = tmp->from;
+				if (from && from->proc == target_proc) {
+					atomic_inc(&from->tmp_ref);
+					target_thread = from;
+					spin_unlock(&tmp->lock);
+					break;
+				}
+				spin_unlock(&tmp->lock);
 				tmp = tmp->from_parent;
 			}
 		}
+		binder_inner_proc_unlock(proc);
 	}
-	if (target_thread) {
+	if (target_thread)
 		e->to_thread = target_thread->pid;
-		target_list = &target_thread->todo;
-		target_wait = &target_thread->wait;
-	} else {
-		target_list = &target_proc->todo;
-		target_wait = &target_proc->wait;
-	}
 	e->to_proc = target_proc->pid;
 
 	/* TODO: reuse incoming transaction for reply */
 	t = kzalloc(sizeof(*t), GFP_KERNEL);
 	if (t == NULL) {
 		return_error = BR_FAILED_REPLY;
+		return_error_param = -ENOMEM;
+		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
 	binder_stats_created(BINDER_STAT_TRANSACTION);
+	spin_lock_init(&t->lock);
 
 	tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
 	if (tcomplete == NULL) {
 		return_error = BR_FAILED_REPLY;
+		return_error_param = -ENOMEM;
+		return_error_line = __LINE__;
 		goto err_alloc_tcomplete_failed;
 	}
 	binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
 
-	t->debug_id = ++binder_last_id;
-	e->debug_id = t->debug_id;
+	t->debug_id = t_debug_id;
 
 	if (reply)
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld\n",
+			     "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld-%lld\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_thread->pid,
 			     (u64)tr->data.ptr.buffer,
 			     (u64)tr->data.ptr.offsets,
-			     (u64)tr->data_size, (u64)tr->offsets_size);
+			     (u64)tr->data_size, (u64)tr->offsets_size,
+			     (u64)extra_buffers_size);
 	else
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld\n",
+			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld-%lld\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_node->debug_id,
 			     (u64)tr->data.ptr.buffer,
 			     (u64)tr->data.ptr.offsets,
-			     (u64)tr->data_size, (u64)tr->offsets_size);
+			     (u64)tr->data_size, (u64)tr->offsets_size,
+			     (u64)extra_buffers_size);
 
 	if (!reply && !(tr->flags & TF_ONE_WAY))
 		t->from = thread;
@@ -1481,14 +2967,30 @@
 	t->to_thread = target_thread;
 	t->code = tr->code;
 	t->flags = tr->flags;
-	t->priority = task_nice(current);
+	if (!(t->flags & TF_ONE_WAY) &&
+	    binder_supported_policy(current->policy)) {
+		/* Inherit supported policies for synchronous transactions */
+		t->priority.sched_policy = current->policy;
+		t->priority.prio = current->normal_prio;
+	} else {
+		/* Otherwise, fall back to the default priority */
+		t->priority = target_proc->default_priority;
+	}
 
 	trace_binder_transaction(reply, t, target_node);
 
-	t->buffer = binder_alloc_buf(target_proc, tr->data_size,
-		tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
-	if (t->buffer == NULL) {
-		return_error = BR_FAILED_REPLY;
+	t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
+		tr->offsets_size, extra_buffers_size,
+		!reply && (t->flags & TF_ONE_WAY));
+	if (IS_ERR(t->buffer)) {
+		/*
+		 * -ESRCH indicates VMA cleared. The target is dying.
+		 */
+		return_error_param = PTR_ERR(t->buffer);
+		return_error = return_error_param == -ESRCH ?
+			BR_DEAD_REPLY : BR_FAILED_REPLY;
+		return_error_line = __LINE__;
+		t->buffer = NULL;
 		goto err_binder_alloc_buf_failed;
 	}
 	t->buffer->allow_user_free = 0;
@@ -1496,17 +2998,17 @@
 	t->buffer->transaction = t;
 	t->buffer->target_node = target_node;
 	trace_binder_transaction_alloc_buf(t->buffer);
-	if (target_node)
-		binder_inc_node(target_node, 1, 0, NULL);
-
-	offp = (binder_size_t *)(t->buffer->data +
-				 ALIGN(tr->data_size, sizeof(void *)));
+	off_start = (binder_size_t *)(t->buffer->data +
+				      ALIGN(tr->data_size, sizeof(void *)));
+	offp = off_start;
 
 	if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
 			   tr->data.ptr.buffer, tr->data_size)) {
 		binder_user_error("%d:%d got transaction with invalid data ptr\n",
 				proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
+		return_error_param = -EFAULT;
+		return_error_line = __LINE__;
 		goto err_copy_data_failed;
 	}
 	if (copy_from_user(offp, (const void __user *)(uintptr_t)
@@ -1514,219 +3016,239 @@
 		binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
 				proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
+		return_error_param = -EFAULT;
+		return_error_line = __LINE__;
 		goto err_copy_data_failed;
 	}
 	if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) {
 		binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n",
 				proc->pid, thread->pid, (u64)tr->offsets_size);
 		return_error = BR_FAILED_REPLY;
+		return_error_param = -EINVAL;
+		return_error_line = __LINE__;
 		goto err_bad_offset;
 	}
-	off_end = (void *)offp + tr->offsets_size;
+	if (!IS_ALIGNED(extra_buffers_size, sizeof(u64))) {
+		binder_user_error("%d:%d got transaction with unaligned buffers size, %lld\n",
+				  proc->pid, thread->pid,
+				  (u64)extra_buffers_size);
+		return_error = BR_FAILED_REPLY;
+		return_error_param = -EINVAL;
+		return_error_line = __LINE__;
+		goto err_bad_offset;
+	}
+	off_end = (void *)off_start + tr->offsets_size;
+	sg_bufp = (u8 *)(PTR_ALIGN(off_end, sizeof(void *)));
+	sg_buf_end = sg_bufp + extra_buffers_size;
 	off_min = 0;
 	for (; offp < off_end; offp++) {
-		struct flat_binder_object *fp;
+		struct binder_object_header *hdr;
+		size_t object_size = binder_validate_object(t->buffer, *offp);
 
-		if (*offp > t->buffer->data_size - sizeof(*fp) ||
-		    *offp < off_min ||
-		    t->buffer->data_size < sizeof(*fp) ||
-		    !IS_ALIGNED(*offp, sizeof(u32))) {
-			binder_user_error("%d:%d got transaction with invalid offset, %lld (min %lld, max %lld)\n",
+		if (object_size == 0 || *offp < off_min) {
+			binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
 					  proc->pid, thread->pid, (u64)*offp,
 					  (u64)off_min,
-					  (u64)(t->buffer->data_size -
-					  sizeof(*fp)));
+					  (u64)t->buffer->data_size);
 			return_error = BR_FAILED_REPLY;
+			return_error_param = -EINVAL;
+			return_error_line = __LINE__;
 			goto err_bad_offset;
 		}
-		fp = (struct flat_binder_object *)(t->buffer->data + *offp);
-		off_min = *offp + sizeof(struct flat_binder_object);
-		switch (fp->type) {
+
+		hdr = (struct binder_object_header *)(t->buffer->data + *offp);
+		off_min = *offp + object_size;
+		switch (hdr->type) {
 		case BINDER_TYPE_BINDER:
 		case BINDER_TYPE_WEAK_BINDER: {
-			struct binder_ref *ref;
-			struct binder_node *node = binder_get_node(proc, fp->binder);
+			struct flat_binder_object *fp;
 
-			if (node == NULL) {
-				node = binder_new_node(proc, fp->binder, fp->cookie);
-				if (node == NULL) {
-					return_error = BR_FAILED_REPLY;
-					goto err_binder_new_node_failed;
-				}
-				node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
-				node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
-			}
-			if (fp->cookie != node->cookie) {
-				binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n",
-					proc->pid, thread->pid,
-					(u64)fp->binder, node->debug_id,
-					(u64)fp->cookie, (u64)node->cookie);
+			fp = to_flat_binder_object(hdr);
+			ret = binder_translate_binder(fp, t, thread);
+			if (ret < 0) {
 				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_for_node_failed;
+				return_error_param = ret;
+				return_error_line = __LINE__;
+				goto err_translate_failed;
 			}
-			if (security_binder_transfer_binder(proc->tsk,
-							    target_proc->tsk)) {
-				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_for_node_failed;
-			}
-			ref = binder_get_ref_for_node(target_proc, node);
-			if (ref == NULL) {
-				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_for_node_failed;
-			}
-			if (fp->type == BINDER_TYPE_BINDER)
-				fp->type = BINDER_TYPE_HANDLE;
-			else
-				fp->type = BINDER_TYPE_WEAK_HANDLE;
-			fp->handle = ref->desc;
-			binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
-				       &thread->todo);
-
-			trace_binder_transaction_node_to_ref(t, node, ref);
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        node %d u%016llx -> ref %d desc %d\n",
-				     node->debug_id, (u64)node->ptr,
-				     ref->debug_id, ref->desc);
 		} break;
 		case BINDER_TYPE_HANDLE:
 		case BINDER_TYPE_WEAK_HANDLE: {
-			struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+			struct flat_binder_object *fp;
 
-			if (ref == NULL) {
-				binder_user_error("%d:%d got transaction with invalid handle, %d\n",
-						proc->pid,
-						thread->pid, fp->handle);
+			fp = to_flat_binder_object(hdr);
+			ret = binder_translate_handle(fp, t, thread);
+			if (ret < 0) {
 				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_failed;
-			}
-			if (security_binder_transfer_binder(proc->tsk,
-							    target_proc->tsk)) {
-				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_failed;
-			}
-			if (ref->node->proc == target_proc) {
-				if (fp->type == BINDER_TYPE_HANDLE)
-					fp->type = BINDER_TYPE_BINDER;
-				else
-					fp->type = BINDER_TYPE_WEAK_BINDER;
-				fp->binder = ref->node->ptr;
-				fp->cookie = ref->node->cookie;
-				binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
-				trace_binder_transaction_ref_to_node(t, ref);
-				binder_debug(BINDER_DEBUG_TRANSACTION,
-					     "        ref %d desc %d -> node %d u%016llx\n",
-					     ref->debug_id, ref->desc, ref->node->debug_id,
-					     (u64)ref->node->ptr);
-			} else {
-				struct binder_ref *new_ref;
-
-				new_ref = binder_get_ref_for_node(target_proc, ref->node);
-				if (new_ref == NULL) {
-					return_error = BR_FAILED_REPLY;
-					goto err_binder_get_ref_for_node_failed;
-				}
-				fp->handle = new_ref->desc;
-				binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
-				trace_binder_transaction_ref_to_ref(t, ref,
-								    new_ref);
-				binder_debug(BINDER_DEBUG_TRANSACTION,
-					     "        ref %d desc %d -> ref %d desc %d (node %d)\n",
-					     ref->debug_id, ref->desc, new_ref->debug_id,
-					     new_ref->desc, ref->node->debug_id);
+				return_error_param = ret;
+				return_error_line = __LINE__;
+				goto err_translate_failed;
 			}
 		} break;
 
 		case BINDER_TYPE_FD: {
-			int target_fd;
-			struct file *file;
+			struct binder_fd_object *fp = to_binder_fd_object(hdr);
+			int target_fd = binder_translate_fd(fp->fd, t, thread,
+							    in_reply_to);
 
-			if (reply) {
-				if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
-					binder_user_error("%d:%d got reply with fd, %d, but target does not allow fds\n",
-						proc->pid, thread->pid, fp->handle);
-					return_error = BR_FAILED_REPLY;
-					goto err_fd_not_allowed;
-				}
-			} else if (!target_node->accept_fds) {
-				binder_user_error("%d:%d got transaction with fd, %d, but target does not allow fds\n",
-					proc->pid, thread->pid, fp->handle);
-				return_error = BR_FAILED_REPLY;
-				goto err_fd_not_allowed;
-			}
-
-			file = fget(fp->handle);
-			if (file == NULL) {
-				binder_user_error("%d:%d got transaction with invalid fd, %d\n",
-					proc->pid, thread->pid, fp->handle);
-				return_error = BR_FAILED_REPLY;
-				goto err_fget_failed;
-			}
-			if (security_binder_transfer_file(proc->tsk,
-							  target_proc->tsk,
-							  file) < 0) {
-				fput(file);
-				return_error = BR_FAILED_REPLY;
-				goto err_get_unused_fd_failed;
-			}
-			target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
 			if (target_fd < 0) {
-				fput(file);
 				return_error = BR_FAILED_REPLY;
-				goto err_get_unused_fd_failed;
+				return_error_param = target_fd;
+				return_error_line = __LINE__;
+				goto err_translate_failed;
 			}
-			task_fd_install(target_proc, target_fd, file);
-			trace_binder_transaction_fd(t, fp->handle, target_fd);
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        fd %d -> %d\n", fp->handle, target_fd);
-			/* TODO: fput? */
-			fp->handle = target_fd;
+			fp->pad_binder = 0;
+			fp->fd = target_fd;
 		} break;
+		case BINDER_TYPE_FDA: {
+			struct binder_fd_array_object *fda =
+				to_binder_fd_array_object(hdr);
+			struct binder_buffer_object *parent =
+				binder_validate_ptr(t->buffer, fda->parent,
+						    off_start,
+						    offp - off_start);
+			if (!parent) {
+				binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
+						  proc->pid, thread->pid);
+				return_error = BR_FAILED_REPLY;
+				return_error_param = -EINVAL;
+				return_error_line = __LINE__;
+				goto err_bad_parent;
+			}
+			if (!binder_validate_fixup(t->buffer, off_start,
+						   parent, fda->parent_offset,
+						   last_fixup_obj,
+						   last_fixup_min_off)) {
+				binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n",
+						  proc->pid, thread->pid);
+				return_error = BR_FAILED_REPLY;
+				return_error_param = -EINVAL;
+				return_error_line = __LINE__;
+				goto err_bad_parent;
+			}
+			ret = binder_translate_fd_array(fda, parent, t, thread,
+							in_reply_to);
+			if (ret < 0) {
+				return_error = BR_FAILED_REPLY;
+				return_error_param = ret;
+				return_error_line = __LINE__;
+				goto err_translate_failed;
+			}
+			last_fixup_obj = parent;
+			last_fixup_min_off =
+				fda->parent_offset + sizeof(u32) * fda->num_fds;
+		} break;
+		case BINDER_TYPE_PTR: {
+			struct binder_buffer_object *bp =
+				to_binder_buffer_object(hdr);
+			size_t buf_left = sg_buf_end - sg_bufp;
 
+			if (bp->length > buf_left) {
+				binder_user_error("%d:%d got transaction with too large buffer\n",
+						  proc->pid, thread->pid);
+				return_error = BR_FAILED_REPLY;
+				return_error_param = -EINVAL;
+				return_error_line = __LINE__;
+				goto err_bad_offset;
+			}
+			if (copy_from_user(sg_bufp,
+					   (const void __user *)(uintptr_t)
+					   bp->buffer, bp->length)) {
+				binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
+						  proc->pid, thread->pid);
+				return_error_param = -EFAULT;
+				return_error = BR_FAILED_REPLY;
+				return_error_line = __LINE__;
+				goto err_copy_data_failed;
+			}
+			/* Fixup buffer pointer to target proc address space */
+			bp->buffer = (uintptr_t)sg_bufp +
+				binder_alloc_get_user_buffer_offset(
+						&target_proc->alloc);
+			sg_bufp += ALIGN(bp->length, sizeof(u64));
+
+			ret = binder_fixup_parent(t, thread, bp, off_start,
+						  offp - off_start,
+						  last_fixup_obj,
+						  last_fixup_min_off);
+			if (ret < 0) {
+				return_error = BR_FAILED_REPLY;
+				return_error_param = ret;
+				return_error_line = __LINE__;
+				goto err_translate_failed;
+			}
+			last_fixup_obj = bp;
+			last_fixup_min_off = 0;
+		} break;
 		default:
 			binder_user_error("%d:%d got transaction with invalid object type, %x\n",
-				proc->pid, thread->pid, fp->type);
+				proc->pid, thread->pid, hdr->type);
 			return_error = BR_FAILED_REPLY;
+			return_error_param = -EINVAL;
+			return_error_line = __LINE__;
 			goto err_bad_object_type;
 		}
 	}
+	tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
+	binder_enqueue_work(proc, tcomplete, &thread->todo);
+	t->work.type = BINDER_WORK_TRANSACTION;
+
 	if (reply) {
+		binder_inner_proc_lock(target_proc);
+		if (target_thread->is_dead) {
+			binder_inner_proc_unlock(target_proc);
+			goto err_dead_proc_or_thread;
+		}
 		BUG_ON(t->buffer->async_transaction != 0);
-		binder_pop_transaction(target_thread, in_reply_to);
+		binder_pop_transaction_ilocked(target_thread, in_reply_to);
+		binder_enqueue_work_ilocked(&t->work, &target_thread->todo);
+		binder_inner_proc_unlock(target_proc);
+		wake_up_interruptible_sync(&target_thread->wait);
+		binder_set_priority(current, in_reply_to->saved_priority);
+		binder_free_transaction(in_reply_to);
 	} else if (!(t->flags & TF_ONE_WAY)) {
 		BUG_ON(t->buffer->async_transaction != 0);
+		binder_inner_proc_lock(proc);
 		t->need_reply = 1;
 		t->from_parent = thread->transaction_stack;
 		thread->transaction_stack = t;
+		binder_inner_proc_unlock(proc);
+		if (!binder_proc_transaction(t, target_proc, target_thread)) {
+			binder_inner_proc_lock(proc);
+			binder_pop_transaction_ilocked(thread, t);
+			binder_inner_proc_unlock(proc);
+			goto err_dead_proc_or_thread;
+		}
 	} else {
 		BUG_ON(target_node == NULL);
 		BUG_ON(t->buffer->async_transaction != 1);
-		if (target_node->has_async_transaction) {
-			target_list = &target_node->async_todo;
-			target_wait = NULL;
-		} else
-			target_node->has_async_transaction = 1;
+		if (!binder_proc_transaction(t, target_proc, NULL))
+			goto err_dead_proc_or_thread;
 	}
-	t->work.type = BINDER_WORK_TRANSACTION;
-	list_add_tail(&t->work.entry, target_list);
-	tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
-	list_add_tail(&tcomplete->entry, &thread->todo);
-	if (target_wait)
-		wake_up_interruptible(target_wait);
+	if (target_thread)
+		binder_thread_dec_tmpref(target_thread);
+	binder_proc_dec_tmpref(target_proc);
+	/*
+	 * write barrier to synchronize with initialization
+	 * of log entry
+	 */
+	smp_wmb();
+	WRITE_ONCE(e->debug_id_done, t_debug_id);
 	return;
 
-err_get_unused_fd_failed:
-err_fget_failed:
-err_fd_not_allowed:
-err_binder_get_ref_for_node_failed:
-err_binder_get_ref_failed:
-err_binder_new_node_failed:
+err_dead_proc_or_thread:
+	return_error = BR_DEAD_REPLY;
+	return_error_line = __LINE__;
+err_translate_failed:
 err_bad_object_type:
 err_bad_offset:
+err_bad_parent:
 err_copy_data_failed:
 	trace_binder_transaction_failed_buffer_release(t->buffer);
 	binder_transaction_buffer_release(target_proc, t->buffer, offp);
+	target_node = NULL;
 	t->buffer->transaction = NULL;
-	binder_free_buf(target_proc, t->buffer);
+	binder_alloc_free_buf(&target_proc->alloc, t->buffer);
 err_binder_alloc_buf_failed:
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
@@ -1739,24 +3261,50 @@
 err_dead_binder:
 err_invalid_target_handle:
 err_no_context_mgr_node:
+	if (target_thread)
+		binder_thread_dec_tmpref(target_thread);
+	if (target_proc)
+		binder_proc_dec_tmpref(target_proc);
+	if (target_node)
+		binder_dec_node(target_node, 1, 0);
+
 	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-		     "%d:%d transaction failed %d, size %lld-%lld\n",
-		     proc->pid, thread->pid, return_error,
-		     (u64)tr->data_size, (u64)tr->offsets_size);
+		     "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n",
+		     proc->pid, thread->pid, return_error, return_error_param,
+		     (u64)tr->data_size, (u64)tr->offsets_size,
+		     return_error_line);
 
 	{
 		struct binder_transaction_log_entry *fe;
 
+		e->return_error = return_error;
+		e->return_error_param = return_error_param;
+		e->return_error_line = return_error_line;
 		fe = binder_transaction_log_add(&binder_transaction_log_failed);
 		*fe = *e;
+		/*
+		 * write barrier to synchronize with initialization
+		 * of log entry
+		 */
+		smp_wmb();
+		WRITE_ONCE(e->debug_id_done, t_debug_id);
+		WRITE_ONCE(fe->debug_id_done, t_debug_id);
 	}
 
-	BUG_ON(thread->return_error != BR_OK);
+	BUG_ON(thread->return_error.cmd != BR_OK);
 	if (in_reply_to) {
-		thread->return_error = BR_TRANSACTION_COMPLETE;
+		binder_set_priority(current, in_reply_to->saved_priority);
+		thread->return_error.cmd = BR_TRANSACTION_COMPLETE;
+		binder_enqueue_work(thread->proc,
+				    &thread->return_error.work,
+				    &thread->todo);
 		binder_send_failed_reply(in_reply_to, return_error);
-	} else
-		thread->return_error = return_error;
+	} else {
+		thread->return_error.cmd = return_error;
+		binder_enqueue_work(thread->proc,
+				    &thread->return_error.work,
+				    &thread->todo);
+	}
 }
 
 static int binder_thread_write(struct binder_proc *proc,
@@ -1765,19 +3313,22 @@
 			binder_size_t *consumed)
 {
 	uint32_t cmd;
+	struct binder_context *context = proc->context;
 	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
 	void __user *ptr = buffer + *consumed;
 	void __user *end = buffer + size;
 
-	while (ptr < end && thread->return_error == BR_OK) {
+	while (ptr < end && thread->return_error.cmd == BR_OK) {
+		int ret;
+
 		if (get_user(cmd, (uint32_t __user *)ptr))
 			return -EFAULT;
 		ptr += sizeof(uint32_t);
 		trace_binder_command(cmd);
 		if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
-			binder_stats.bc[_IOC_NR(cmd)]++;
-			proc->stats.bc[_IOC_NR(cmd)]++;
-			thread->stats.bc[_IOC_NR(cmd)]++;
+			atomic_inc(&binder_stats.bc[_IOC_NR(cmd)]);
+			atomic_inc(&proc->stats.bc[_IOC_NR(cmd)]);
+			atomic_inc(&thread->stats.bc[_IOC_NR(cmd)]);
 		}
 		switch (cmd) {
 		case BC_INCREFS:
@@ -1785,51 +3336,61 @@
 		case BC_RELEASE:
 		case BC_DECREFS: {
 			uint32_t target;
-			struct binder_ref *ref;
 			const char *debug_string;
+			bool strong = cmd == BC_ACQUIRE || cmd == BC_RELEASE;
+			bool increment = cmd == BC_INCREFS || cmd == BC_ACQUIRE;
+			struct binder_ref_data rdata;
 
 			if (get_user(target, (uint32_t __user *)ptr))
 				return -EFAULT;
+
 			ptr += sizeof(uint32_t);
-			if (target == 0 && binder_context_mgr_node &&
-			    (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
-				ref = binder_get_ref_for_node(proc,
-					       binder_context_mgr_node);
-				if (ref->desc != target) {
-					binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n",
-						proc->pid, thread->pid,
-						ref->desc);
-				}
-			} else
-				ref = binder_get_ref(proc, target);
-			if (ref == NULL) {
-				binder_user_error("%d:%d refcount change on invalid ref %d\n",
-					proc->pid, thread->pid, target);
-				break;
+			ret = -1;
+			if (increment && !target) {
+				struct binder_node *ctx_mgr_node;
+				mutex_lock(&context->context_mgr_node_lock);
+				ctx_mgr_node = context->binder_context_mgr_node;
+				if (ctx_mgr_node)
+					ret = binder_inc_ref_for_node(
+							proc, ctx_mgr_node,
+							strong, NULL, &rdata);
+				mutex_unlock(&context->context_mgr_node_lock);
+			}
+			if (ret)
+				ret = binder_update_ref_for_handle(
+						proc, target, increment, strong,
+						&rdata);
+			if (!ret && rdata.desc != target) {
+				binder_user_error("%d:%d tried to acquire reference to desc %d, got %d instead\n",
+					proc->pid, thread->pid,
+					target, rdata.desc);
 			}
 			switch (cmd) {
 			case BC_INCREFS:
 				debug_string = "IncRefs";
-				binder_inc_ref(ref, 0, NULL);
 				break;
 			case BC_ACQUIRE:
 				debug_string = "Acquire";
-				binder_inc_ref(ref, 1, NULL);
 				break;
 			case BC_RELEASE:
 				debug_string = "Release";
-				binder_dec_ref(ref, 1);
 				break;
 			case BC_DECREFS:
 			default:
 				debug_string = "DecRefs";
-				binder_dec_ref(ref, 0);
+				break;
+			}
+			if (ret) {
+				binder_user_error("%d:%d %s %d refcount change on invalid ref %d ret %d\n",
+					proc->pid, thread->pid, debug_string,
+					strong, target, ret);
 				break;
 			}
 			binder_debug(BINDER_DEBUG_USER_REFS,
-				     "%d:%d %s ref %d desc %d s %d w %d for node %d\n",
-				     proc->pid, thread->pid, debug_string, ref->debug_id,
-				     ref->desc, ref->strong, ref->weak, ref->node->debug_id);
+				     "%d:%d %s ref %d desc %d s %d w %d\n",
+				     proc->pid, thread->pid, debug_string,
+				     rdata.debug_id, rdata.desc, rdata.strong,
+				     rdata.weak);
 			break;
 		}
 		case BC_INCREFS_DONE:
@@ -1837,6 +3398,7 @@
 			binder_uintptr_t node_ptr;
 			binder_uintptr_t cookie;
 			struct binder_node *node;
+			bool free_node;
 
 			if (get_user(node_ptr, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
@@ -1861,13 +3423,17 @@
 					"BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
 					(u64)node_ptr, node->debug_id,
 					(u64)cookie, (u64)node->cookie);
+				binder_put_node(node);
 				break;
 			}
+			binder_node_inner_lock(node);
 			if (cmd == BC_ACQUIRE_DONE) {
 				if (node->pending_strong_ref == 0) {
 					binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n",
 						proc->pid, thread->pid,
 						node->debug_id);
+					binder_node_inner_unlock(node);
+					binder_put_node(node);
 					break;
 				}
 				node->pending_strong_ref = 0;
@@ -1876,16 +3442,23 @@
 					binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n",
 						proc->pid, thread->pid,
 						node->debug_id);
+					binder_node_inner_unlock(node);
+					binder_put_node(node);
 					break;
 				}
 				node->pending_weak_ref = 0;
 			}
-			binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0);
+			free_node = binder_dec_node_nilocked(node,
+					cmd == BC_ACQUIRE_DONE, 0);
+			WARN_ON(free_node);
 			binder_debug(BINDER_DEBUG_USER_REFS,
-				     "%d:%d %s node %d ls %d lw %d\n",
+				     "%d:%d %s node %d ls %d lw %d tr %d\n",
 				     proc->pid, thread->pid,
 				     cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
-				     node->debug_id, node->local_strong_refs, node->local_weak_refs);
+				     node->debug_id, node->local_strong_refs,
+				     node->local_weak_refs, node->tmp_refs);
+			binder_node_inner_unlock(node);
+			binder_put_node(node);
 			break;
 		}
 		case BC_ATTEMPT_ACQUIRE:
@@ -1903,7 +3476,8 @@
 				return -EFAULT;
 			ptr += sizeof(binder_uintptr_t);
 
-			buffer = binder_buffer_lookup(proc, data_ptr);
+			buffer = binder_alloc_prepare_to_free(&proc->alloc,
+							      data_ptr);
 			if (buffer == NULL) {
 				binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n",
 					proc->pid, thread->pid, (u64)data_ptr);
@@ -1925,18 +3499,39 @@
 				buffer->transaction = NULL;
 			}
 			if (buffer->async_transaction && buffer->target_node) {
-				BUG_ON(!buffer->target_node->has_async_transaction);
-				if (list_empty(&buffer->target_node->async_todo))
-					buffer->target_node->has_async_transaction = 0;
+				struct binder_node *buf_node;
+				struct binder_work *w;
+
+				buf_node = buffer->target_node;
+				binder_node_inner_lock(buf_node);
+				BUG_ON(!buf_node->has_async_transaction);
+				BUG_ON(buf_node->proc != proc);
+				w = binder_dequeue_work_head_ilocked(
+						&buf_node->async_todo);
+				if (!w)
+					buf_node->has_async_transaction = 0;
 				else
-					list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
+					binder_enqueue_work_ilocked(
+							w, &thread->todo);
+				binder_node_inner_unlock(buf_node);
 			}
 			trace_binder_transaction_buffer_release(buffer);
 			binder_transaction_buffer_release(proc, buffer, NULL);
-			binder_free_buf(proc, buffer);
+			binder_alloc_free_buf(&proc->alloc, buffer);
 			break;
 		}
 
+		case BC_TRANSACTION_SG:
+		case BC_REPLY_SG: {
+			struct binder_transaction_data_sg tr;
+
+			if (copy_from_user(&tr, ptr, sizeof(tr)))
+				return -EFAULT;
+			ptr += sizeof(tr);
+			binder_transaction(proc, thread, &tr.transaction_data,
+					   cmd == BC_REPLY_SG, tr.buffers_size);
+			break;
+		}
 		case BC_TRANSACTION:
 		case BC_REPLY: {
 			struct binder_transaction_data tr;
@@ -1944,7 +3539,8 @@
 			if (copy_from_user(&tr, ptr, sizeof(tr)))
 				return -EFAULT;
 			ptr += sizeof(tr);
-			binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
+			binder_transaction(proc, thread, &tr,
+					   cmd == BC_REPLY, 0);
 			break;
 		}
 
@@ -1952,6 +3548,7 @@
 			binder_debug(BINDER_DEBUG_THREADS,
 				     "%d:%d BC_REGISTER_LOOPER\n",
 				     proc->pid, thread->pid);
+			binder_inner_proc_lock(proc);
 			if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
 				thread->looper |= BINDER_LOOPER_STATE_INVALID;
 				binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n",
@@ -1965,6 +3562,7 @@
 				proc->requested_threads_started++;
 			}
 			thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
+			binder_inner_proc_unlock(proc);
 			break;
 		case BC_ENTER_LOOPER:
 			binder_debug(BINDER_DEBUG_THREADS,
@@ -1989,7 +3587,7 @@
 			uint32_t target;
 			binder_uintptr_t cookie;
 			struct binder_ref *ref;
-			struct binder_ref_death *death;
+			struct binder_ref_death *death = NULL;
 
 			if (get_user(target, (uint32_t __user *)ptr))
 				return -EFAULT;
@@ -1997,7 +3595,29 @@
 			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(binder_uintptr_t);
-			ref = binder_get_ref(proc, target);
+			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
+				/*
+				 * Allocate memory for death notification
+				 * before taking lock
+				 */
+				death = kzalloc(sizeof(*death), GFP_KERNEL);
+				if (death == NULL) {
+					WARN_ON(thread->return_error.cmd !=
+						BR_OK);
+					thread->return_error.cmd = BR_ERROR;
+					binder_enqueue_work(
+						thread->proc,
+						&thread->return_error.work,
+						&thread->todo);
+					binder_debug(
+						BINDER_DEBUG_FAILED_TRANSACTION,
+						"%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n",
+						proc->pid, thread->pid);
+					break;
+				}
+			}
+			binder_proc_lock(proc);
+			ref = binder_get_ref_olocked(proc, target, false);
 			if (ref == NULL) {
 				binder_user_error("%d:%d %s invalid ref %d\n",
 					proc->pid, thread->pid,
@@ -2005,6 +3625,8 @@
 					"BC_REQUEST_DEATH_NOTIFICATION" :
 					"BC_CLEAR_DEATH_NOTIFICATION",
 					target);
+				binder_proc_unlock(proc);
+				kfree(death);
 				break;
 			}
 
@@ -2014,21 +3636,18 @@
 				     cmd == BC_REQUEST_DEATH_NOTIFICATION ?
 				     "BC_REQUEST_DEATH_NOTIFICATION" :
 				     "BC_CLEAR_DEATH_NOTIFICATION",
-				     (u64)cookie, ref->debug_id, ref->desc,
-				     ref->strong, ref->weak, ref->node->debug_id);
+				     (u64)cookie, ref->data.debug_id,
+				     ref->data.desc, ref->data.strong,
+				     ref->data.weak, ref->node->debug_id);
 
+			binder_node_lock(ref->node);
 			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
 				if (ref->death) {
 					binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n",
 						proc->pid, thread->pid);
-					break;
-				}
-				death = kzalloc(sizeof(*death), GFP_KERNEL);
-				if (death == NULL) {
-					thread->return_error = BR_ERROR;
-					binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-						     "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n",
-						     proc->pid, thread->pid);
+					binder_node_unlock(ref->node);
+					binder_proc_unlock(proc);
+					kfree(death);
 					break;
 				}
 				binder_stats_created(BINDER_STAT_DEATH);
@@ -2037,17 +3656,29 @@
 				ref->death = death;
 				if (ref->node->proc == NULL) {
 					ref->death->work.type = BINDER_WORK_DEAD_BINDER;
-					if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
-						list_add_tail(&ref->death->work.entry, &thread->todo);
-					} else {
-						list_add_tail(&ref->death->work.entry, &proc->todo);
-						wake_up_interruptible(&proc->wait);
+					if (thread->looper &
+					    (BINDER_LOOPER_STATE_REGISTERED |
+					     BINDER_LOOPER_STATE_ENTERED))
+						binder_enqueue_work(
+							proc,
+							&ref->death->work,
+							&thread->todo);
+					else {
+						binder_inner_proc_lock(proc);
+						binder_enqueue_work_ilocked(
+							&ref->death->work,
+							&proc->todo);
+						binder_wakeup_proc_ilocked(
+							proc);
+						binder_inner_proc_unlock(proc);
 					}
 				}
 			} else {
 				if (ref->death == NULL) {
 					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n",
 						proc->pid, thread->pid);
+					binder_node_unlock(ref->node);
+					binder_proc_unlock(proc);
 					break;
 				}
 				death = ref->death;
@@ -2056,22 +3687,35 @@
 						proc->pid, thread->pid,
 						(u64)death->cookie,
 						(u64)cookie);
+					binder_node_unlock(ref->node);
+					binder_proc_unlock(proc);
 					break;
 				}
 				ref->death = NULL;
+				binder_inner_proc_lock(proc);
 				if (list_empty(&death->work.entry)) {
 					death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
-					if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
-						list_add_tail(&death->work.entry, &thread->todo);
-					} else {
-						list_add_tail(&death->work.entry, &proc->todo);
-						wake_up_interruptible(&proc->wait);
+					if (thread->looper &
+					    (BINDER_LOOPER_STATE_REGISTERED |
+					     BINDER_LOOPER_STATE_ENTERED))
+						binder_enqueue_work_ilocked(
+								&death->work,
+								&thread->todo);
+					else {
+						binder_enqueue_work_ilocked(
+								&death->work,
+								&proc->todo);
+						binder_wakeup_proc_ilocked(
+								proc);
 					}
 				} else {
 					BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
 					death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
 				}
+				binder_inner_proc_unlock(proc);
 			}
+			binder_node_unlock(ref->node);
+			binder_proc_unlock(proc);
 		} break;
 		case BC_DEAD_BINDER_DONE: {
 			struct binder_work *w;
@@ -2082,8 +3726,13 @@
 				return -EFAULT;
 
 			ptr += sizeof(cookie);
-			list_for_each_entry(w, &proc->delivered_death, entry) {
-				struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
+			binder_inner_proc_lock(proc);
+			list_for_each_entry(w, &proc->delivered_death,
+					    entry) {
+				struct binder_ref_death *tmp_death =
+					container_of(w,
+						     struct binder_ref_death,
+						     work);
 
 				if (tmp_death->cookie == cookie) {
 					death = tmp_death;
@@ -2097,19 +3746,25 @@
 			if (death == NULL) {
 				binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n",
 					proc->pid, thread->pid, (u64)cookie);
+				binder_inner_proc_unlock(proc);
 				break;
 			}
-
-			list_del_init(&death->work.entry);
+			binder_dequeue_work_ilocked(&death->work);
 			if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) {
 				death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
-				if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
-					list_add_tail(&death->work.entry, &thread->todo);
-				} else {
-					list_add_tail(&death->work.entry, &proc->todo);
-					wake_up_interruptible(&proc->wait);
+				if (thread->looper &
+					(BINDER_LOOPER_STATE_REGISTERED |
+					 BINDER_LOOPER_STATE_ENTERED))
+					binder_enqueue_work_ilocked(
+						&death->work, &thread->todo);
+				else {
+					binder_enqueue_work_ilocked(
+							&death->work,
+							&proc->todo);
+					binder_wakeup_proc_ilocked(proc);
 				}
 			}
+			binder_inner_proc_unlock(proc);
 		} break;
 
 		default:
@@ -2127,23 +3782,79 @@
 {
 	trace_binder_return(cmd);
 	if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
-		binder_stats.br[_IOC_NR(cmd)]++;
-		proc->stats.br[_IOC_NR(cmd)]++;
-		thread->stats.br[_IOC_NR(cmd)]++;
+		atomic_inc(&binder_stats.br[_IOC_NR(cmd)]);
+		atomic_inc(&proc->stats.br[_IOC_NR(cmd)]);
+		atomic_inc(&thread->stats.br[_IOC_NR(cmd)]);
 	}
 }
 
-static int binder_has_proc_work(struct binder_proc *proc,
-				struct binder_thread *thread)
-{
-	return !list_empty(&proc->todo) ||
-		(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
-}
-
 static int binder_has_thread_work(struct binder_thread *thread)
 {
-	return !list_empty(&thread->todo) || thread->return_error != BR_OK ||
-		(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
+	return !binder_worklist_empty(thread->proc, &thread->todo) ||
+		thread->looper_need_return;
+}
+
+static int binder_put_node_cmd(struct binder_proc *proc,
+			       struct binder_thread *thread,
+			       void __user **ptrp,
+			       binder_uintptr_t node_ptr,
+			       binder_uintptr_t node_cookie,
+			       int node_debug_id,
+			       uint32_t cmd, const char *cmd_name)
+{
+	void __user *ptr = *ptrp;
+
+	if (put_user(cmd, (uint32_t __user *)ptr))
+		return -EFAULT;
+	ptr += sizeof(uint32_t);
+
+	if (put_user(node_ptr, (binder_uintptr_t __user *)ptr))
+		return -EFAULT;
+	ptr += sizeof(binder_uintptr_t);
+
+	if (put_user(node_cookie, (binder_uintptr_t __user *)ptr))
+		return -EFAULT;
+	ptr += sizeof(binder_uintptr_t);
+
+	binder_stat_br(proc, thread, cmd);
+	binder_debug(BINDER_DEBUG_USER_REFS, "%d:%d %s %d u%016llx c%016llx\n",
+		     proc->pid, thread->pid, cmd_name, node_debug_id,
+		     (u64)node_ptr, (u64)node_cookie);
+
+	*ptrp = ptr;
+	return 0;
+}
+
+static int binder_wait_for_work(struct binder_thread *thread,
+				bool do_proc_work)
+{
+	DEFINE_WAIT(wait);
+	struct binder_proc *proc = thread->proc;
+	int ret = 0;
+
+	freezer_do_not_count();
+	binder_inner_proc_lock(proc);
+	for (;;) {
+		prepare_to_wait(&thread->wait, &wait, TASK_INTERRUPTIBLE);
+		if (binder_has_work_ilocked(thread, do_proc_work))
+			break;
+		if (do_proc_work)
+			list_add(&thread->waiting_thread_node,
+				 &proc->waiting_threads);
+		binder_inner_proc_unlock(proc);
+		schedule();
+		binder_inner_proc_lock(proc);
+		list_del_init(&thread->waiting_thread_node);
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+	}
+	finish_wait(&thread->wait, &wait);
+	binder_inner_proc_unlock(proc);
+	freezer_count();
+
+	return ret;
 }
 
 static int binder_thread_read(struct binder_proc *proc,
@@ -2165,37 +3876,15 @@
 	}
 
 retry:
-	wait_for_proc_work = thread->transaction_stack == NULL &&
-				list_empty(&thread->todo);
-
-	if (thread->return_error != BR_OK && ptr < end) {
-		if (thread->return_error2 != BR_OK) {
-			if (put_user(thread->return_error2, (uint32_t __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(uint32_t);
-			binder_stat_br(proc, thread, thread->return_error2);
-			if (ptr == end)
-				goto done;
-			thread->return_error2 = BR_OK;
-		}
-		if (put_user(thread->return_error, (uint32_t __user *)ptr))
-			return -EFAULT;
-		ptr += sizeof(uint32_t);
-		binder_stat_br(proc, thread, thread->return_error);
-		thread->return_error = BR_OK;
-		goto done;
-	}
-
+	binder_inner_proc_lock(proc);
+	wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);
+	binder_inner_proc_unlock(proc);
 
 	thread->looper |= BINDER_LOOPER_STATE_WAITING;
-	if (wait_for_proc_work)
-		proc->ready_threads++;
-
-	binder_unlock(__func__);
 
 	trace_binder_wait_for_work(wait_for_proc_work,
 				   !!thread->transaction_stack,
-				   !list_empty(&thread->todo));
+				   !binder_worklist_empty(proc, &thread->todo));
 	if (wait_for_proc_work) {
 		if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
 					BINDER_LOOPER_STATE_ENTERED))) {
@@ -2204,24 +3893,16 @@
 			wait_event_interruptible(binder_user_error_wait,
 						 binder_stop_on_user_error < 2);
 		}
-		binder_set_nice(proc->default_priority);
-		if (non_block) {
-			if (!binder_has_proc_work(proc, thread))
-				ret = -EAGAIN;
-		} else
-			ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
-	} else {
-		if (non_block) {
-			if (!binder_has_thread_work(thread))
-				ret = -EAGAIN;
-		} else
-			ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
+		binder_set_priority(current, proc->default_priority);
 	}
 
-	binder_lock(__func__);
+	if (non_block) {
+		if (!binder_has_work(thread, wait_for_proc_work))
+			ret = -EAGAIN;
+	} else {
+		ret = binder_wait_for_work(thread, wait_for_proc_work);
+	}
 
-	if (wait_for_proc_work)
-		proc->ready_threads--;
 	thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
 
 	if (ret)
@@ -2230,31 +3911,52 @@
 	while (1) {
 		uint32_t cmd;
 		struct binder_transaction_data tr;
-		struct binder_work *w;
+		struct binder_work *w = NULL;
+		struct list_head *list = NULL;
 		struct binder_transaction *t = NULL;
+		struct binder_thread *t_from;
 
-		if (!list_empty(&thread->todo)) {
-			w = list_first_entry(&thread->todo, struct binder_work,
-					     entry);
-		} else if (!list_empty(&proc->todo) && wait_for_proc_work) {
-			w = list_first_entry(&proc->todo, struct binder_work,
-					     entry);
-		} else {
+		binder_inner_proc_lock(proc);
+		if (!binder_worklist_empty_ilocked(&thread->todo))
+			list = &thread->todo;
+		else if (!binder_worklist_empty_ilocked(&proc->todo) &&
+			   wait_for_proc_work)
+			list = &proc->todo;
+		else {
+			binder_inner_proc_unlock(proc);
+
 			/* no data added */
-			if (ptr - buffer == 4 &&
-			    !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN))
+			if (ptr - buffer == 4 && !thread->looper_need_return)
 				goto retry;
 			break;
 		}
 
-		if (end - ptr < sizeof(tr) + 4)
+		if (end - ptr < sizeof(tr) + 4) {
+			binder_inner_proc_unlock(proc);
 			break;
+		}
+		w = binder_dequeue_work_head_ilocked(list);
 
 		switch (w->type) {
 		case BINDER_WORK_TRANSACTION: {
+			binder_inner_proc_unlock(proc);
 			t = container_of(w, struct binder_transaction, work);
 		} break;
+		case BINDER_WORK_RETURN_ERROR: {
+			struct binder_error *e = container_of(
+					w, struct binder_error, work);
+
+			WARN_ON(e->cmd == BR_OK);
+			binder_inner_proc_unlock(proc);
+			if (put_user(e->cmd, (uint32_t __user *)ptr))
+				return -EFAULT;
+			e->cmd = BR_OK;
+			ptr += sizeof(uint32_t);
+
+			binder_stat_br(proc, thread, cmd);
+		} break;
 		case BINDER_WORK_TRANSACTION_COMPLETE: {
+			binder_inner_proc_unlock(proc);
 			cmd = BR_TRANSACTION_COMPLETE;
 			if (put_user(cmd, (uint32_t __user *)ptr))
 				return -EFAULT;
@@ -2264,113 +3966,134 @@
 			binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE,
 				     "%d:%d BR_TRANSACTION_COMPLETE\n",
 				     proc->pid, thread->pid);
-
-			list_del(&w->entry);
 			kfree(w);
 			binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 		} break;
 		case BINDER_WORK_NODE: {
 			struct binder_node *node = container_of(w, struct binder_node, work);
-			uint32_t cmd = BR_NOOP;
-			const char *cmd_name;
-			int strong = node->internal_strong_refs || node->local_strong_refs;
-			int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;
+			int strong, weak;
+			binder_uintptr_t node_ptr = node->ptr;
+			binder_uintptr_t node_cookie = node->cookie;
+			int node_debug_id = node->debug_id;
+			int has_weak_ref;
+			int has_strong_ref;
+			void __user *orig_ptr = ptr;
 
-			if (weak && !node->has_weak_ref) {
-				cmd = BR_INCREFS;
-				cmd_name = "BR_INCREFS";
+			BUG_ON(proc != node->proc);
+			strong = node->internal_strong_refs ||
+					node->local_strong_refs;
+			weak = !hlist_empty(&node->refs) ||
+					node->local_weak_refs ||
+					node->tmp_refs || strong;
+			has_strong_ref = node->has_strong_ref;
+			has_weak_ref = node->has_weak_ref;
+
+			if (weak && !has_weak_ref) {
 				node->has_weak_ref = 1;
 				node->pending_weak_ref = 1;
 				node->local_weak_refs++;
-			} else if (strong && !node->has_strong_ref) {
-				cmd = BR_ACQUIRE;
-				cmd_name = "BR_ACQUIRE";
+			}
+			if (strong && !has_strong_ref) {
 				node->has_strong_ref = 1;
 				node->pending_strong_ref = 1;
 				node->local_strong_refs++;
-			} else if (!strong && node->has_strong_ref) {
-				cmd = BR_RELEASE;
-				cmd_name = "BR_RELEASE";
+			}
+			if (!strong && has_strong_ref)
 				node->has_strong_ref = 0;
-			} else if (!weak && node->has_weak_ref) {
-				cmd = BR_DECREFS;
-				cmd_name = "BR_DECREFS";
+			if (!weak && has_weak_ref)
 				node->has_weak_ref = 0;
-			}
-			if (cmd != BR_NOOP) {
-				if (put_user(cmd, (uint32_t __user *)ptr))
-					return -EFAULT;
-				ptr += sizeof(uint32_t);
-				if (put_user(node->ptr,
-					     (binder_uintptr_t __user *)ptr))
-					return -EFAULT;
-				ptr += sizeof(binder_uintptr_t);
-				if (put_user(node->cookie,
-					     (binder_uintptr_t __user *)ptr))
-					return -EFAULT;
-				ptr += sizeof(binder_uintptr_t);
+			if (!weak && !strong) {
+				binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+					     "%d:%d node %d u%016llx c%016llx deleted\n",
+					     proc->pid, thread->pid,
+					     node_debug_id,
+					     (u64)node_ptr,
+					     (u64)node_cookie);
+				rb_erase(&node->rb_node, &proc->nodes);
+				binder_inner_proc_unlock(proc);
+				binder_node_lock(node);
+				/*
+				 * Acquire the node lock before freeing the
+				 * node to serialize with other threads that
+				 * may have been holding the node lock while
+				 * decrementing this node (avoids race where
+				 * this thread frees while the other thread
+				 * is unlocking the node after the final
+				 * decrement)
+				 */
+				binder_node_unlock(node);
+				binder_free_node(node);
+			} else
+				binder_inner_proc_unlock(proc);
 
-				binder_stat_br(proc, thread, cmd);
-				binder_debug(BINDER_DEBUG_USER_REFS,
-					     "%d:%d %s %d u%016llx c%016llx\n",
-					     proc->pid, thread->pid, cmd_name,
-					     node->debug_id,
-					     (u64)node->ptr, (u64)node->cookie);
-			} else {
-				list_del_init(&w->entry);
-				if (!weak && !strong) {
-					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "%d:%d node %d u%016llx c%016llx deleted\n",
-						     proc->pid, thread->pid,
-						     node->debug_id,
-						     (u64)node->ptr,
-						     (u64)node->cookie);
-					rb_erase(&node->rb_node, &proc->nodes);
-					kfree(node);
-					binder_stats_deleted(BINDER_STAT_NODE);
-				} else {
-					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "%d:%d node %d u%016llx c%016llx state unchanged\n",
-						     proc->pid, thread->pid,
-						     node->debug_id,
-						     (u64)node->ptr,
-						     (u64)node->cookie);
-				}
-			}
+			if (weak && !has_weak_ref)
+				ret = binder_put_node_cmd(
+						proc, thread, &ptr, node_ptr,
+						node_cookie, node_debug_id,
+						BR_INCREFS, "BR_INCREFS");
+			if (!ret && strong && !has_strong_ref)
+				ret = binder_put_node_cmd(
+						proc, thread, &ptr, node_ptr,
+						node_cookie, node_debug_id,
+						BR_ACQUIRE, "BR_ACQUIRE");
+			if (!ret && !strong && has_strong_ref)
+				ret = binder_put_node_cmd(
+						proc, thread, &ptr, node_ptr,
+						node_cookie, node_debug_id,
+						BR_RELEASE, "BR_RELEASE");
+			if (!ret && !weak && has_weak_ref)
+				ret = binder_put_node_cmd(
+						proc, thread, &ptr, node_ptr,
+						node_cookie, node_debug_id,
+						BR_DECREFS, "BR_DECREFS");
+			if (orig_ptr == ptr)
+				binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+					     "%d:%d node %d u%016llx c%016llx state unchanged\n",
+					     proc->pid, thread->pid,
+					     node_debug_id,
+					     (u64)node_ptr,
+					     (u64)node_cookie);
+			if (ret)
+				return ret;
 		} break;
 		case BINDER_WORK_DEAD_BINDER:
 		case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
 		case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
 			struct binder_ref_death *death;
 			uint32_t cmd;
+			binder_uintptr_t cookie;
 
 			death = container_of(w, struct binder_ref_death, work);
 			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
 				cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
 			else
 				cmd = BR_DEAD_BINDER;
-			if (put_user(cmd, (uint32_t __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(uint32_t);
-			if (put_user(death->cookie,
-				     (binder_uintptr_t __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(binder_uintptr_t);
-			binder_stat_br(proc, thread, cmd);
+			cookie = death->cookie;
+
 			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
 				     "%d:%d %s %016llx\n",
 				      proc->pid, thread->pid,
 				      cmd == BR_DEAD_BINDER ?
 				      "BR_DEAD_BINDER" :
 				      "BR_CLEAR_DEATH_NOTIFICATION_DONE",
-				      (u64)death->cookie);
-
+				      (u64)cookie);
 			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
-				list_del(&w->entry);
+				binder_inner_proc_unlock(proc);
 				kfree(death);
 				binder_stats_deleted(BINDER_STAT_DEATH);
-			} else
-				list_move(&w->entry, &proc->delivered_death);
+			} else {
+				binder_enqueue_work_ilocked(
+						w, &proc->delivered_death);
+				binder_inner_proc_unlock(proc);
+			}
+			if (put_user(cmd, (uint32_t __user *)ptr))
+				return -EFAULT;
+			ptr += sizeof(uint32_t);
+			if (put_user(cookie,
+				     (binder_uintptr_t __user *)ptr))
+				return -EFAULT;
+			ptr += sizeof(binder_uintptr_t);
+			binder_stat_br(proc, thread, cmd);
 			if (cmd == BR_DEAD_BINDER)
 				goto done; /* DEAD_BINDER notifications can cause transactions */
 		} break;
@@ -2382,16 +4105,14 @@
 		BUG_ON(t->buffer == NULL);
 		if (t->buffer->target_node) {
 			struct binder_node *target_node = t->buffer->target_node;
+			struct binder_priority node_prio;
 
 			tr.target.ptr = target_node->ptr;
 			tr.cookie =  target_node->cookie;
-			t->saved_priority = task_nice(current);
-			if (t->priority < target_node->min_priority &&
-			    !(t->flags & TF_ONE_WAY))
-				binder_set_nice(t->priority);
-			else if (!(t->flags & TF_ONE_WAY) ||
-				 t->saved_priority > target_node->min_priority)
-				binder_set_nice(target_node->min_priority);
+			node_prio.sched_policy = target_node->sched_policy;
+			node_prio.prio = target_node->min_priority;
+			binder_transaction_priority(current, t, node_prio,
+						    target_node->inherit_rt);
 			cmd = BR_TRANSACTION;
 		} else {
 			tr.target.ptr = 0;
@@ -2402,8 +4123,9 @@
 		tr.flags = t->flags;
 		tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);
 
-		if (t->from) {
-			struct task_struct *sender = t->from->proc->tsk;
+		t_from = binder_get_txn_from(t);
+		if (t_from) {
+			struct task_struct *sender = t_from->proc->tsk;
 
 			tr.sender_pid = task_tgid_nr_ns(sender,
 							task_active_pid_ns(current));
@@ -2413,18 +4135,24 @@
 
 		tr.data_size = t->buffer->data_size;
 		tr.offsets_size = t->buffer->offsets_size;
-		tr.data.ptr.buffer = (binder_uintptr_t)(
-					(uintptr_t)t->buffer->data +
-					proc->user_buffer_offset);
+		tr.data.ptr.buffer = (binder_uintptr_t)
+			((uintptr_t)t->buffer->data +
+			binder_alloc_get_user_buffer_offset(&proc->alloc));
 		tr.data.ptr.offsets = tr.data.ptr.buffer +
 					ALIGN(t->buffer->data_size,
 					    sizeof(void *));
 
-		if (put_user(cmd, (uint32_t __user *)ptr))
+		if (put_user(cmd, (uint32_t __user *)ptr)) {
+			if (t_from)
+				binder_thread_dec_tmpref(t_from);
 			return -EFAULT;
+		}
 		ptr += sizeof(uint32_t);
-		if (copy_to_user(ptr, &tr, sizeof(tr)))
+		if (copy_to_user(ptr, &tr, sizeof(tr))) {
+			if (t_from)
+				binder_thread_dec_tmpref(t_from);
 			return -EFAULT;
+		}
 		ptr += sizeof(tr);
 
 		trace_binder_transaction_received(t);
@@ -2434,21 +4162,22 @@
 			     proc->pid, thread->pid,
 			     (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
 			     "BR_REPLY",
-			     t->debug_id, t->from ? t->from->proc->pid : 0,
-			     t->from ? t->from->pid : 0, cmd,
+			     t->debug_id, t_from ? t_from->proc->pid : 0,
+			     t_from ? t_from->pid : 0, cmd,
 			     t->buffer->data_size, t->buffer->offsets_size,
 			     (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);
 
-		list_del(&t->work.entry);
+		if (t_from)
+			binder_thread_dec_tmpref(t_from);
 		t->buffer->allow_user_free = 1;
 		if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
+			binder_inner_proc_lock(thread->proc);
 			t->to_parent = thread->transaction_stack;
 			t->to_thread = thread;
 			thread->transaction_stack = t;
+			binder_inner_proc_unlock(thread->proc);
 		} else {
-			t->buffer->transaction = NULL;
-			kfree(t);
-			binder_stats_deleted(BINDER_STAT_TRANSACTION);
+			binder_free_transaction(t);
 		}
 		break;
 	}
@@ -2456,29 +4185,36 @@
 done:
 
 	*consumed = ptr - buffer;
-	if (proc->requested_threads + proc->ready_threads == 0 &&
+	binder_inner_proc_lock(proc);
+	if (proc->requested_threads == 0 &&
+	    list_empty(&thread->proc->waiting_threads) &&
 	    proc->requested_threads_started < proc->max_threads &&
 	    (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
 	     BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
 	     /*spawn a new thread if we leave this out */) {
 		proc->requested_threads++;
+		binder_inner_proc_unlock(proc);
 		binder_debug(BINDER_DEBUG_THREADS,
 			     "%d:%d BR_SPAWN_LOOPER\n",
 			     proc->pid, thread->pid);
 		if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
 			return -EFAULT;
 		binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
-	}
+	} else
+		binder_inner_proc_unlock(proc);
 	return 0;
 }
 
-static void binder_release_work(struct list_head *list)
+static void binder_release_work(struct binder_proc *proc,
+				struct list_head *list)
 {
 	struct binder_work *w;
 
-	while (!list_empty(list)) {
-		w = list_first_entry(list, struct binder_work, entry);
-		list_del_init(&w->entry);
+	while (1) {
+		w = binder_dequeue_work_head(proc, list);
+		if (!w)
+			return;
+
 		switch (w->type) {
 		case BINDER_WORK_TRANSACTION: {
 			struct binder_transaction *t;
@@ -2491,11 +4227,17 @@
 				binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
 					"undelivered transaction %d\n",
 					t->debug_id);
-				t->buffer->transaction = NULL;
-				kfree(t);
-				binder_stats_deleted(BINDER_STAT_TRANSACTION);
+				binder_free_transaction(t);
 			}
 		} break;
+		case BINDER_WORK_RETURN_ERROR: {
+			struct binder_error *e = container_of(
+					w, struct binder_error, work);
+
+			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+				"undelivered TRANSACTION_ERROR: %u\n",
+				e->cmd);
+		} break;
 		case BINDER_WORK_TRANSACTION_COMPLETE: {
 			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
 				"undelivered TRANSACTION_COMPLETE\n");
@@ -2522,7 +4264,8 @@
 
 }
 
-static struct binder_thread *binder_get_thread(struct binder_proc *proc)
+static struct binder_thread *binder_get_thread_ilocked(
+		struct binder_proc *proc, struct binder_thread *new_thread)
 {
 	struct binder_thread *thread = NULL;
 	struct rb_node *parent = NULL;
@@ -2537,38 +4280,102 @@
 		else if (current->pid > thread->pid)
 			p = &(*p)->rb_right;
 		else
-			break;
+			return thread;
 	}
-	if (*p == NULL) {
-		thread = kzalloc(sizeof(*thread), GFP_KERNEL);
-		if (thread == NULL)
+	if (!new_thread)
+		return NULL;
+	thread = new_thread;
+	binder_stats_created(BINDER_STAT_THREAD);
+	thread->proc = proc;
+	thread->pid = current->pid;
+	get_task_struct(current);
+	thread->task = current;
+	atomic_set(&thread->tmp_ref, 0);
+	init_waitqueue_head(&thread->wait);
+	INIT_LIST_HEAD(&thread->todo);
+	rb_link_node(&thread->rb_node, parent, p);
+	rb_insert_color(&thread->rb_node, &proc->threads);
+	thread->looper_need_return = true;
+	thread->return_error.work.type = BINDER_WORK_RETURN_ERROR;
+	thread->return_error.cmd = BR_OK;
+	thread->reply_error.work.type = BINDER_WORK_RETURN_ERROR;
+	thread->reply_error.cmd = BR_OK;
+	INIT_LIST_HEAD(&new_thread->waiting_thread_node);
+	return thread;
+}
+
+static struct binder_thread *binder_get_thread(struct binder_proc *proc)
+{
+	struct binder_thread *thread;
+	struct binder_thread *new_thread;
+
+	binder_inner_proc_lock(proc);
+	thread = binder_get_thread_ilocked(proc, NULL);
+	binder_inner_proc_unlock(proc);
+	if (!thread) {
+		new_thread = kzalloc(sizeof(*thread), GFP_KERNEL);
+		if (new_thread == NULL)
 			return NULL;
-		binder_stats_created(BINDER_STAT_THREAD);
-		thread->proc = proc;
-		thread->pid = current->pid;
-		init_waitqueue_head(&thread->wait);
-		INIT_LIST_HEAD(&thread->todo);
-		rb_link_node(&thread->rb_node, parent, p);
-		rb_insert_color(&thread->rb_node, &proc->threads);
-		thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
-		thread->return_error = BR_OK;
-		thread->return_error2 = BR_OK;
+		binder_inner_proc_lock(proc);
+		thread = binder_get_thread_ilocked(proc, new_thread);
+		binder_inner_proc_unlock(proc);
+		if (thread != new_thread)
+			kfree(new_thread);
 	}
 	return thread;
 }
 
-static int binder_free_thread(struct binder_proc *proc,
-			      struct binder_thread *thread)
+static void binder_free_proc(struct binder_proc *proc)
+{
+	BUG_ON(!list_empty(&proc->todo));
+	BUG_ON(!list_empty(&proc->delivered_death));
+	binder_alloc_deferred_release(&proc->alloc);
+	put_task_struct(proc->tsk);
+	binder_stats_deleted(BINDER_STAT_PROC);
+	kfree(proc);
+}
+
+static void binder_free_thread(struct binder_thread *thread)
+{
+	BUG_ON(!list_empty(&thread->todo));
+	binder_stats_deleted(BINDER_STAT_THREAD);
+	binder_proc_dec_tmpref(thread->proc);
+	put_task_struct(thread->task);
+	kfree(thread);
+}
+
+static int binder_thread_release(struct binder_proc *proc,
+				 struct binder_thread *thread)
 {
 	struct binder_transaction *t;
 	struct binder_transaction *send_reply = NULL;
 	int active_transactions = 0;
+	struct binder_transaction *last_t = NULL;
 
+	binder_inner_proc_lock(thread->proc);
+	/*
+	 * take a ref on the proc so it survives
+	 * after we remove this thread from proc->threads.
+	 * The corresponding dec is when we actually
+	 * free the thread in binder_free_thread()
+	 */
+	proc->tmp_ref++;
+	/*
+	 * take a ref on this thread to ensure it
+	 * survives while we are releasing it
+	 */
+	atomic_inc(&thread->tmp_ref);
 	rb_erase(&thread->rb_node, &proc->threads);
 	t = thread->transaction_stack;
-	if (t && t->to_thread == thread)
-		send_reply = t;
+	if (t) {
+		spin_lock(&t->lock);
+		if (t->to_thread == thread)
+			send_reply = t;
+	}
+	thread->is_dead = true;
+
 	while (t) {
+		last_t = t;
 		active_transactions++;
 		binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
 			     "release %d:%d transaction %d %s, still active\n",
@@ -2589,12 +4396,16 @@
 			t = t->from_parent;
 		} else
 			BUG();
+		spin_unlock(&last_t->lock);
+		if (t)
+			spin_lock(&t->lock);
 	}
+	binder_inner_proc_unlock(thread->proc);
+
 	if (send_reply)
 		binder_send_failed_reply(send_reply, BR_DEAD_REPLY);
-	binder_release_work(&thread->todo);
-	kfree(thread);
-	binder_stats_deleted(BINDER_STAT_THREAD);
+	binder_release_work(proc, &thread->todo);
+	binder_thread_dec_tmpref(thread);
 	return active_transactions;
 }
 
@@ -2603,30 +4414,24 @@
 {
 	struct binder_proc *proc = filp->private_data;
 	struct binder_thread *thread = NULL;
-	int wait_for_proc_work;
-
-	binder_lock(__func__);
+	bool wait_for_proc_work;
 
 	thread = binder_get_thread(proc);
 
-	wait_for_proc_work = thread->transaction_stack == NULL &&
-		list_empty(&thread->todo) && thread->return_error == BR_OK;
+	binder_inner_proc_lock(thread->proc);
+	thread->looper |= BINDER_LOOPER_STATE_POLL;
+	wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);
 
-	binder_unlock(__func__);
+	binder_inner_proc_unlock(thread->proc);
 
-	if (wait_for_proc_work) {
-		if (binder_has_proc_work(proc, thread))
-			return POLLIN;
-		poll_wait(filp, &proc->wait, wait);
-		if (binder_has_proc_work(proc, thread))
-			return POLLIN;
-	} else {
-		if (binder_has_thread_work(thread))
-			return POLLIN;
-		poll_wait(filp, &thread->wait, wait);
-		if (binder_has_thread_work(thread))
-			return POLLIN;
-	}
+	if (binder_has_work(thread, wait_for_proc_work))
+		return POLLIN;
+
+	poll_wait(filp, &thread->wait, wait);
+
+	if (binder_has_thread_work(thread))
+		return POLLIN;
+
 	return 0;
 }
 
@@ -2673,8 +4478,10 @@
 					 &bwr.read_consumed,
 					 filp->f_flags & O_NONBLOCK);
 		trace_binder_read_done(ret);
-		if (!list_empty(&proc->todo))
-			wake_up_interruptible(&proc->wait);
+		binder_inner_proc_lock(proc);
+		if (!binder_worklist_empty_ilocked(&proc->todo))
+			binder_wakeup_proc_ilocked(proc);
+		binder_inner_proc_unlock(proc);
 		if (ret < 0) {
 			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
 				ret = -EFAULT;
@@ -2698,9 +4505,12 @@
 {
 	int ret = 0;
 	struct binder_proc *proc = filp->private_data;
+	struct binder_context *context = proc->context;
+	struct binder_node *new_node;
 	kuid_t curr_euid = current_euid();
 
-	if (binder_context_mgr_node != NULL) {
+	mutex_lock(&context->context_mgr_node_lock);
+	if (context->binder_context_mgr_node) {
 		pr_err("BINDER_SET_CONTEXT_MGR already set\n");
 		ret = -EBUSY;
 		goto out;
@@ -2708,28 +4518,33 @@
 	ret = security_binder_set_context_mgr(proc->tsk);
 	if (ret < 0)
 		goto out;
-	if (uid_valid(binder_context_mgr_uid)) {
-		if (!uid_eq(binder_context_mgr_uid, curr_euid)) {
+	if (uid_valid(context->binder_context_mgr_uid)) {
+		if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {
 			pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
 			       from_kuid(&init_user_ns, curr_euid),
 			       from_kuid(&init_user_ns,
-					binder_context_mgr_uid));
+					 context->binder_context_mgr_uid));
 			ret = -EPERM;
 			goto out;
 		}
 	} else {
-		binder_context_mgr_uid = curr_euid;
+		context->binder_context_mgr_uid = curr_euid;
 	}
-	binder_context_mgr_node = binder_new_node(proc, 0, 0);
-	if (binder_context_mgr_node == NULL) {
+	new_node = binder_new_node(proc, NULL);
+	if (!new_node) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	binder_context_mgr_node->local_weak_refs++;
-	binder_context_mgr_node->local_strong_refs++;
-	binder_context_mgr_node->has_strong_ref = 1;
-	binder_context_mgr_node->has_weak_ref = 1;
+	binder_node_lock(new_node);
+	new_node->local_weak_refs++;
+	new_node->local_strong_refs++;
+	new_node->has_strong_ref = 1;
+	new_node->has_weak_ref = 1;
+	context->binder_context_mgr_node = new_node;
+	binder_node_unlock(new_node);
+	binder_put_node(new_node);
 out:
+	mutex_unlock(&context->context_mgr_node_lock);
 	return ret;
 }
 
@@ -2750,7 +4565,6 @@
 	if (ret)
 		goto err_unlocked;
 
-	binder_lock(__func__);
 	thread = binder_get_thread(proc);
 	if (thread == NULL) {
 		ret = -ENOMEM;
@@ -2763,12 +4577,19 @@
 		if (ret)
 			goto err;
 		break;
-	case BINDER_SET_MAX_THREADS:
-		if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
+	case BINDER_SET_MAX_THREADS: {
+		int max_threads;
+
+		if (copy_from_user(&max_threads, ubuf,
+				   sizeof(max_threads))) {
 			ret = -EINVAL;
 			goto err;
 		}
+		binder_inner_proc_lock(proc);
+		proc->max_threads = max_threads;
+		binder_inner_proc_unlock(proc);
 		break;
+	}
 	case BINDER_SET_CONTEXT_MGR:
 		ret = binder_ioctl_set_ctx_mgr(filp);
 		if (ret)
@@ -2777,7 +4598,7 @@
 	case BINDER_THREAD_EXIT:
 		binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
 			     proc->pid, thread->pid);
-		binder_free_thread(proc, thread);
+		binder_thread_release(proc, thread);
 		thread = NULL;
 		break;
 	case BINDER_VERSION: {
@@ -2801,8 +4622,7 @@
 	ret = 0;
 err:
 	if (thread)
-		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
-	binder_unlock(__func__);
+		thread->looper_need_return = false;
 	wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
 	if (ret && ret != -ERESTARTSYS)
 		pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
@@ -2831,8 +4651,7 @@
 		     proc->pid, vma->vm_start, vma->vm_end,
 		     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
 		     (unsigned long)pgprot_val(vma->vm_page_prot));
-	proc->vma = NULL;
-	proc->vma_vm_mm = NULL;
+	binder_alloc_vma_close(&proc->alloc);
 	binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
 }
 
@@ -2850,20 +4669,18 @@
 static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 	int ret;
-	struct vm_struct *area;
 	struct binder_proc *proc = filp->private_data;
 	const char *failure_string;
-	struct binder_buffer *buffer;
 
-	if (proc->tsk != current)
+	if (proc->tsk != current->group_leader)
 		return -EINVAL;
 
 	if ((vma->vm_end - vma->vm_start) > SZ_4M)
 		vma->vm_end = vma->vm_start + SZ_4M;
 
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
-		     proc->pid, vma->vm_start, vma->vm_end,
+		     "%s: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
+		     __func__, proc->pid, vma->vm_start, vma->vm_end,
 		     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
 		     (unsigned long)pgprot_val(vma->vm_page_prot));
 
@@ -2873,73 +4690,15 @@
 		goto err_bad_arg;
 	}
 	vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
-
-	mutex_lock(&binder_mmap_lock);
-	if (proc->buffer) {
-		ret = -EBUSY;
-		failure_string = "already mapped";
-		goto err_already_mapped;
-	}
-
-	area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
-	if (area == NULL) {
-		ret = -ENOMEM;
-		failure_string = "get_vm_area";
-		goto err_get_vm_area_failed;
-	}
-	proc->buffer = area->addr;
-	proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
-	mutex_unlock(&binder_mmap_lock);
-
-#ifdef CONFIG_CPU_CACHE_VIPT
-	if (cache_is_vipt_aliasing()) {
-		while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) {
-			pr_info("binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);
-			vma->vm_start += PAGE_SIZE;
-		}
-	}
-#endif
-	proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);
-	if (proc->pages == NULL) {
-		ret = -ENOMEM;
-		failure_string = "alloc page array";
-		goto err_alloc_pages_failed;
-	}
-	proc->buffer_size = vma->vm_end - vma->vm_start;
-
 	vma->vm_ops = &binder_vm_ops;
 	vma->vm_private_data = proc;
 
-	if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {
-		ret = -ENOMEM;
-		failure_string = "alloc small buf";
-		goto err_alloc_small_buf_failed;
-	}
-	buffer = proc->buffer;
-	INIT_LIST_HEAD(&proc->buffers);
-	list_add(&buffer->entry, &proc->buffers);
-	buffer->free = 1;
-	binder_insert_free_buffer(proc, buffer);
-	proc->free_async_space = proc->buffer_size / 2;
-	barrier();
+	ret = binder_alloc_mmap_handler(&proc->alloc, vma);
+	if (ret)
+		return ret;
 	proc->files = get_files_struct(current);
-	proc->vma = vma;
-	proc->vma_vm_mm = vma->vm_mm;
-
-	/*pr_info("binder_mmap: %d %lx-%lx maps %p\n",
-		 proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
 	return 0;
 
-err_alloc_small_buf_failed:
-	kfree(proc->pages);
-	proc->pages = NULL;
-err_alloc_pages_failed:
-	mutex_lock(&binder_mmap_lock);
-	vfree(proc->buffer);
-	proc->buffer = NULL;
-err_get_vm_area_failed:
-err_already_mapped:
-	mutex_unlock(&binder_mmap_lock);
 err_bad_arg:
 	pr_err("binder_mmap: %d %lx-%lx %s failed %d\n",
 	       proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
@@ -2949,6 +4708,7 @@
 static int binder_open(struct inode *nodp, struct file *filp)
 {
 	struct binder_proc *proc;
+	struct binder_device *binder_dev;
 
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
 		     current->group_leader->pid, current->pid);
@@ -2956,28 +4716,49 @@
 	proc = kzalloc(sizeof(*proc), GFP_KERNEL);
 	if (proc == NULL)
 		return -ENOMEM;
-	get_task_struct(current);
-	proc->tsk = current;
+	spin_lock_init(&proc->inner_lock);
+	spin_lock_init(&proc->outer_lock);
+	get_task_struct(current->group_leader);
+	proc->tsk = current->group_leader;
 	INIT_LIST_HEAD(&proc->todo);
-	init_waitqueue_head(&proc->wait);
-	proc->default_priority = task_nice(current);
+	if (binder_supported_policy(current->policy)) {
+		proc->default_priority.sched_policy = current->policy;
+		proc->default_priority.prio = current->normal_prio;
+	} else {
+		proc->default_priority.sched_policy = SCHED_NORMAL;
+		proc->default_priority.prio = NICE_TO_PRIO(0);
+	}
 
-	binder_lock(__func__);
+	binder_dev = container_of(filp->private_data, struct binder_device,
+				  miscdev);
+	proc->context = &binder_dev->context;
+	binder_alloc_init(&proc->alloc);
 
 	binder_stats_created(BINDER_STAT_PROC);
-	hlist_add_head(&proc->proc_node, &binder_procs);
 	proc->pid = current->group_leader->pid;
 	INIT_LIST_HEAD(&proc->delivered_death);
+	INIT_LIST_HEAD(&proc->waiting_threads);
 	filp->private_data = proc;
 
-	binder_unlock(__func__);
+	mutex_lock(&binder_procs_lock);
+	hlist_add_head(&proc->proc_node, &binder_procs);
+	mutex_unlock(&binder_procs_lock);
 
 	if (binder_debugfs_dir_entry_proc) {
 		char strbuf[11];
 
 		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
+		/*
+		 * proc debug entries are shared between contexts, so
+		 * this will fail if the process tries to open the driver
+		 * again with a different context. The priting code will
+		 * anyway print all contexts that a given PID has, so this
+		 * is not a problem.
+		 */
 		proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO,
-			binder_debugfs_dir_entry_proc, proc, &binder_proc_fops);
+			binder_debugfs_dir_entry_proc,
+			(void *)(unsigned long)proc->pid,
+			&binder_proc_fops);
 	}
 
 	return 0;
@@ -2997,16 +4778,17 @@
 	struct rb_node *n;
 	int wake_count = 0;
 
+	binder_inner_proc_lock(proc);
 	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
 		struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
 
-		thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
+		thread->looper_need_return = true;
 		if (thread->looper & BINDER_LOOPER_STATE_WAITING) {
 			wake_up_interruptible(&thread->wait);
 			wake_count++;
 		}
 	}
-	wake_up_interruptible_all(&proc->wait);
+	binder_inner_proc_unlock(proc);
 
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
 		     "binder_flush: %d woke %d threads\n", proc->pid,
@@ -3027,13 +4809,21 @@
 {
 	struct binder_ref *ref;
 	int death = 0;
+	struct binder_proc *proc = node->proc;
 
-	list_del_init(&node->work.entry);
-	binder_release_work(&node->async_todo);
+	binder_release_work(proc, &node->async_todo);
 
-	if (hlist_empty(&node->refs)) {
-		kfree(node);
-		binder_stats_deleted(BINDER_STAT_NODE);
+	binder_node_lock(node);
+	binder_inner_proc_lock(proc);
+	binder_dequeue_work_ilocked(&node->work);
+	/*
+	 * The caller must have taken a temporary ref on the node,
+	 */
+	BUG_ON(!node->tmp_refs);
+	if (hlist_empty(&node->refs) && node->tmp_refs == 1) {
+		binder_inner_proc_unlock(proc);
+		binder_node_unlock(node);
+		binder_free_node(node);
 
 		return refs;
 	}
@@ -3041,59 +4831,84 @@
 	node->proc = NULL;
 	node->local_strong_refs = 0;
 	node->local_weak_refs = 0;
+	binder_inner_proc_unlock(proc);
+
+	spin_lock(&binder_dead_nodes_lock);
 	hlist_add_head(&node->dead_node, &binder_dead_nodes);
+	spin_unlock(&binder_dead_nodes_lock);
 
 	hlist_for_each_entry(ref, &node->refs, node_entry) {
 		refs++;
-
-		if (!ref->death)
+		/*
+		 * Need the node lock to synchronize
+		 * with new notification requests and the
+		 * inner lock to synchronize with queued
+		 * death notifications.
+		 */
+		binder_inner_proc_lock(ref->proc);
+		if (!ref->death) {
+			binder_inner_proc_unlock(ref->proc);
 			continue;
+		}
 
 		death++;
 
-		if (list_empty(&ref->death->work.entry)) {
-			ref->death->work.type = BINDER_WORK_DEAD_BINDER;
-			list_add_tail(&ref->death->work.entry,
-				      &ref->proc->todo);
-			wake_up_interruptible(&ref->proc->wait);
-		} else
-			BUG();
+		BUG_ON(!list_empty(&ref->death->work.entry));
+		ref->death->work.type = BINDER_WORK_DEAD_BINDER;
+		binder_enqueue_work_ilocked(&ref->death->work,
+					    &ref->proc->todo);
+		binder_wakeup_proc_ilocked(ref->proc);
+		binder_inner_proc_unlock(ref->proc);
 	}
 
 	binder_debug(BINDER_DEBUG_DEAD_BINDER,
 		     "node %d now dead, refs %d, death %d\n",
 		     node->debug_id, refs, death);
+	binder_node_unlock(node);
+	binder_put_node(node);
 
 	return refs;
 }
 
 static void binder_deferred_release(struct binder_proc *proc)
 {
-	struct binder_transaction *t;
+	struct binder_context *context = proc->context;
 	struct rb_node *n;
-	int threads, nodes, incoming_refs, outgoing_refs, buffers,
-		active_transactions, page_count;
+	int threads, nodes, incoming_refs, outgoing_refs, active_transactions;
 
-	BUG_ON(proc->vma);
 	BUG_ON(proc->files);
 
+	mutex_lock(&binder_procs_lock);
 	hlist_del(&proc->proc_node);
+	mutex_unlock(&binder_procs_lock);
 
-	if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
+	mutex_lock(&context->context_mgr_node_lock);
+	if (context->binder_context_mgr_node &&
+	    context->binder_context_mgr_node->proc == proc) {
 		binder_debug(BINDER_DEBUG_DEAD_BINDER,
 			     "%s: %d context_mgr_node gone\n",
 			     __func__, proc->pid);
-		binder_context_mgr_node = NULL;
+		context->binder_context_mgr_node = NULL;
 	}
+	mutex_unlock(&context->context_mgr_node_lock);
+	binder_inner_proc_lock(proc);
+	/*
+	 * Make sure proc stays alive after we
+	 * remove all the threads
+	 */
+	proc->tmp_ref++;
 
+	proc->is_dead = true;
 	threads = 0;
 	active_transactions = 0;
 	while ((n = rb_first(&proc->threads))) {
 		struct binder_thread *thread;
 
 		thread = rb_entry(n, struct binder_thread, rb_node);
+		binder_inner_proc_unlock(proc);
 		threads++;
-		active_transactions += binder_free_thread(proc, thread);
+		active_transactions += binder_thread_release(proc, thread);
+		binder_inner_proc_lock(proc);
 	}
 
 	nodes = 0;
@@ -3103,73 +4918,42 @@
 
 		node = rb_entry(n, struct binder_node, rb_node);
 		nodes++;
+		/*
+		 * take a temporary ref on the node before
+		 * calling binder_node_release() which will either
+		 * kfree() the node or call binder_put_node()
+		 */
+		binder_inc_node_tmpref_ilocked(node);
 		rb_erase(&node->rb_node, &proc->nodes);
+		binder_inner_proc_unlock(proc);
 		incoming_refs = binder_node_release(node, incoming_refs);
+		binder_inner_proc_lock(proc);
 	}
+	binder_inner_proc_unlock(proc);
 
 	outgoing_refs = 0;
+	binder_proc_lock(proc);
 	while ((n = rb_first(&proc->refs_by_desc))) {
 		struct binder_ref *ref;
 
 		ref = rb_entry(n, struct binder_ref, rb_node_desc);
 		outgoing_refs++;
-		binder_delete_ref(ref);
+		binder_cleanup_ref_olocked(ref);
+		binder_proc_unlock(proc);
+		binder_free_ref(ref);
+		binder_proc_lock(proc);
 	}
+	binder_proc_unlock(proc);
 
-	binder_release_work(&proc->todo);
-	binder_release_work(&proc->delivered_death);
-
-	buffers = 0;
-	while ((n = rb_first(&proc->allocated_buffers))) {
-		struct binder_buffer *buffer;
-
-		buffer = rb_entry(n, struct binder_buffer, rb_node);
-
-		t = buffer->transaction;
-		if (t) {
-			t->buffer = NULL;
-			buffer->transaction = NULL;
-			pr_err("release proc %d, transaction %d, not freed\n",
-			       proc->pid, t->debug_id);
-			/*BUG();*/
-		}
-
-		binder_free_buf(proc, buffer);
-		buffers++;
-	}
-
-	binder_stats_deleted(BINDER_STAT_PROC);
-
-	page_count = 0;
-	if (proc->pages) {
-		int i;
-
-		for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) {
-			void *page_addr;
-
-			if (!proc->pages[i])
-				continue;
-
-			page_addr = proc->buffer + i * PAGE_SIZE;
-			binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-				     "%s: %d: page %d at %p not freed\n",
-				     __func__, proc->pid, i, page_addr);
-			unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
-			__free_page(proc->pages[i]);
-			page_count++;
-		}
-		kfree(proc->pages);
-		vfree(proc->buffer);
-	}
-
-	put_task_struct(proc->tsk);
+	binder_release_work(proc, &proc->todo);
+	binder_release_work(proc, &proc->delivered_death);
 
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n",
+		     "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n",
 		     __func__, proc->pid, threads, nodes, incoming_refs,
-		     outgoing_refs, active_transactions, buffers, page_count);
+		     outgoing_refs, active_transactions);
 
-	kfree(proc);
+	binder_proc_dec_tmpref(proc);
 }
 
 static void binder_deferred_func(struct work_struct *work)
@@ -3180,7 +4964,6 @@
 	int defer;
 
 	do {
-		binder_lock(__func__);
 		mutex_lock(&binder_deferred_lock);
 		if (!hlist_empty(&binder_deferred_list)) {
 			proc = hlist_entry(binder_deferred_list.first,
@@ -3207,7 +4990,6 @@
 		if (defer & BINDER_DEFERRED_RELEASE)
 			binder_deferred_release(proc); /* frees proc */
 
-		binder_unlock(__func__);
 		if (files)
 			put_files_struct(files);
 	} while (proc);
@@ -3227,41 +5009,53 @@
 	mutex_unlock(&binder_deferred_lock);
 }
 
-static void print_binder_transaction(struct seq_file *m, const char *prefix,
-				     struct binder_transaction *t)
+static void print_binder_transaction_ilocked(struct seq_file *m,
+					     struct binder_proc *proc,
+					     const char *prefix,
+					     struct binder_transaction *t)
 {
+	struct binder_proc *to_proc;
+	struct binder_buffer *buffer = t->buffer;
+
+	WARN_ON(!spin_is_locked(&proc->inner_lock));
+	spin_lock(&t->lock);
+	to_proc = t->to_proc;
 	seq_printf(m,
-		   "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
+		   "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %d:%d r%d",
 		   prefix, t->debug_id, t,
 		   t->from ? t->from->proc->pid : 0,
 		   t->from ? t->from->pid : 0,
-		   t->to_proc ? t->to_proc->pid : 0,
+		   to_proc ? to_proc->pid : 0,
 		   t->to_thread ? t->to_thread->pid : 0,
-		   t->code, t->flags, t->priority, t->need_reply);
-	if (t->buffer == NULL) {
+		   t->code, t->flags, t->priority.sched_policy,
+		   t->priority.prio, t->need_reply);
+	spin_unlock(&t->lock);
+
+	if (proc != to_proc) {
+		/*
+		 * Can only safely deref buffer if we are holding the
+		 * correct proc inner lock for this node
+		 */
+		seq_puts(m, "\n");
+		return;
+	}
+
+	if (buffer == NULL) {
 		seq_puts(m, " buffer free\n");
 		return;
 	}
-	if (t->buffer->target_node)
-		seq_printf(m, " node %d",
-			   t->buffer->target_node->debug_id);
+	if (buffer->target_node)
+		seq_printf(m, " node %d", buffer->target_node->debug_id);
 	seq_printf(m, " size %zd:%zd data %p\n",
-		   t->buffer->data_size, t->buffer->offsets_size,
-		   t->buffer->data);
-}
-
-static void print_binder_buffer(struct seq_file *m, const char *prefix,
-				struct binder_buffer *buffer)
-{
-	seq_printf(m, "%s %d: %p size %zd:%zd %s\n",
-		   prefix, buffer->debug_id, buffer->data,
 		   buffer->data_size, buffer->offsets_size,
-		   buffer->transaction ? "active" : "delivered");
+		   buffer->data);
 }
 
-static void print_binder_work(struct seq_file *m, const char *prefix,
-			      const char *transaction_prefix,
-			      struct binder_work *w)
+static void print_binder_work_ilocked(struct seq_file *m,
+				     struct binder_proc *proc,
+				     const char *prefix,
+				     const char *transaction_prefix,
+				     struct binder_work *w)
 {
 	struct binder_node *node;
 	struct binder_transaction *t;
@@ -3269,8 +5063,16 @@
 	switch (w->type) {
 	case BINDER_WORK_TRANSACTION:
 		t = container_of(w, struct binder_transaction, work);
-		print_binder_transaction(m, transaction_prefix, t);
+		print_binder_transaction_ilocked(
+				m, proc, transaction_prefix, t);
 		break;
+	case BINDER_WORK_RETURN_ERROR: {
+		struct binder_error *e = container_of(
+				w, struct binder_error, work);
+
+		seq_printf(m, "%stransaction error: %u\n",
+			   prefix, e->cmd);
+	} break;
 	case BINDER_WORK_TRANSACTION_COMPLETE:
 		seq_printf(m, "%stransaction complete\n", prefix);
 		break;
@@ -3295,70 +5097,90 @@
 	}
 }
 
-static void print_binder_thread(struct seq_file *m,
-				struct binder_thread *thread,
-				int print_always)
+static void print_binder_thread_ilocked(struct seq_file *m,
+					struct binder_thread *thread,
+					int print_always)
 {
 	struct binder_transaction *t;
 	struct binder_work *w;
 	size_t start_pos = m->count;
 	size_t header_pos;
 
-	seq_printf(m, "  thread %d: l %02x\n", thread->pid, thread->looper);
+	WARN_ON(!spin_is_locked(&thread->proc->inner_lock));
+	seq_printf(m, "  thread %d: l %02x need_return %d tr %d\n",
+			thread->pid, thread->looper,
+			thread->looper_need_return,
+			atomic_read(&thread->tmp_ref));
 	header_pos = m->count;
 	t = thread->transaction_stack;
 	while (t) {
 		if (t->from == thread) {
-			print_binder_transaction(m,
-						 "    outgoing transaction", t);
+			print_binder_transaction_ilocked(m, thread->proc,
+					"    outgoing transaction", t);
 			t = t->from_parent;
 		} else if (t->to_thread == thread) {
-			print_binder_transaction(m,
+			print_binder_transaction_ilocked(m, thread->proc,
 						 "    incoming transaction", t);
 			t = t->to_parent;
 		} else {
-			print_binder_transaction(m, "    bad transaction", t);
+			print_binder_transaction_ilocked(m, thread->proc,
+					"    bad transaction", t);
 			t = NULL;
 		}
 	}
 	list_for_each_entry(w, &thread->todo, entry) {
-		print_binder_work(m, "    ", "    pending transaction", w);
+		print_binder_work_ilocked(m, thread->proc, "    ",
+					  "    pending transaction", w);
 	}
 	if (!print_always && m->count == header_pos)
 		m->count = start_pos;
 }
 
-static void print_binder_node(struct seq_file *m, struct binder_node *node)
+static void print_binder_node_nilocked(struct seq_file *m,
+				       struct binder_node *node)
 {
 	struct binder_ref *ref;
 	struct binder_work *w;
 	int count;
 
+	WARN_ON(!spin_is_locked(&node->lock));
+	if (node->proc)
+		WARN_ON(!spin_is_locked(&node->proc->inner_lock));
+
 	count = 0;
 	hlist_for_each_entry(ref, &node->refs, node_entry)
 		count++;
 
-	seq_printf(m, "  node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d",
+	seq_printf(m, "  node %d: u%016llx c%016llx pri %d:%d hs %d hw %d ls %d lw %d is %d iw %d tr %d",
 		   node->debug_id, (u64)node->ptr, (u64)node->cookie,
+		   node->sched_policy, node->min_priority,
 		   node->has_strong_ref, node->has_weak_ref,
 		   node->local_strong_refs, node->local_weak_refs,
-		   node->internal_strong_refs, count);
+		   node->internal_strong_refs, count, node->tmp_refs);
 	if (count) {
 		seq_puts(m, " proc");
 		hlist_for_each_entry(ref, &node->refs, node_entry)
 			seq_printf(m, " %d", ref->proc->pid);
 	}
 	seq_puts(m, "\n");
-	list_for_each_entry(w, &node->async_todo, entry)
-		print_binder_work(m, "    ",
-				  "    pending async transaction", w);
+	if (node->proc) {
+		list_for_each_entry(w, &node->async_todo, entry)
+			print_binder_work_ilocked(m, node->proc, "    ",
+					  "    pending async transaction", w);
+	}
 }
 
-static void print_binder_ref(struct seq_file *m, struct binder_ref *ref)
+static void print_binder_ref_olocked(struct seq_file *m,
+				     struct binder_ref *ref)
 {
-	seq_printf(m, "  ref %d: desc %d %snode %d s %d w %d d %p\n",
-		   ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ",
-		   ref->node->debug_id, ref->strong, ref->weak, ref->death);
+	WARN_ON(!spin_is_locked(&ref->proc->outer_lock));
+	binder_node_lock(ref->node);
+	seq_printf(m, "  ref %d: desc %d %snode %d s %d w %d d %pK\n",
+		   ref->data.debug_id, ref->data.desc,
+		   ref->node->proc ? "" : "dead ",
+		   ref->node->debug_id, ref->data.strong,
+		   ref->data.weak, ref->death);
+	binder_node_unlock(ref->node);
 }
 
 static void print_binder_proc(struct seq_file *m,
@@ -3368,35 +5190,60 @@
 	struct rb_node *n;
 	size_t start_pos = m->count;
 	size_t header_pos;
+	struct binder_node *last_node = NULL;
 
 	seq_printf(m, "proc %d\n", proc->pid);
+	seq_printf(m, "context %s\n", proc->context->name);
 	header_pos = m->count;
 
+	binder_inner_proc_lock(proc);
 	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
-		print_binder_thread(m, rb_entry(n, struct binder_thread,
+		print_binder_thread_ilocked(m, rb_entry(n, struct binder_thread,
 						rb_node), print_all);
+
 	for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) {
 		struct binder_node *node = rb_entry(n, struct binder_node,
 						    rb_node);
-		if (print_all || node->has_async_transaction)
-			print_binder_node(m, node);
+		/*
+		 * take a temporary reference on the node so it
+		 * survives and isn't removed from the tree
+		 * while we print it.
+		 */
+		binder_inc_node_tmpref_ilocked(node);
+		/* Need to drop inner lock to take node lock */
+		binder_inner_proc_unlock(proc);
+		if (last_node)
+			binder_put_node(last_node);
+		binder_node_inner_lock(node);
+		print_binder_node_nilocked(m, node);
+		binder_node_inner_unlock(node);
+		last_node = node;
+		binder_inner_proc_lock(proc);
 	}
+	binder_inner_proc_unlock(proc);
+	if (last_node)
+		binder_put_node(last_node);
+
 	if (print_all) {
+		binder_proc_lock(proc);
 		for (n = rb_first(&proc->refs_by_desc);
 		     n != NULL;
 		     n = rb_next(n))
-			print_binder_ref(m, rb_entry(n, struct binder_ref,
-						     rb_node_desc));
+			print_binder_ref_olocked(m, rb_entry(n,
+							    struct binder_ref,
+							    rb_node_desc));
+		binder_proc_unlock(proc);
 	}
-	for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n))
-		print_binder_buffer(m, "  buffer",
-				    rb_entry(n, struct binder_buffer, rb_node));
+	binder_alloc_print_allocated(m, &proc->alloc);
+	binder_inner_proc_lock(proc);
 	list_for_each_entry(w, &proc->todo, entry)
-		print_binder_work(m, "  ", "  pending transaction", w);
+		print_binder_work_ilocked(m, proc, "  ",
+					  "  pending transaction", w);
 	list_for_each_entry(w, &proc->delivered_death, entry) {
 		seq_puts(m, "  has delivered dead binder\n");
 		break;
 	}
+	binder_inner_proc_unlock(proc);
 	if (!print_all && m->count == header_pos)
 		m->count = start_pos;
 }
@@ -3439,7 +5286,9 @@
 	"BC_EXIT_LOOPER",
 	"BC_REQUEST_DEATH_NOTIFICATION",
 	"BC_CLEAR_DEATH_NOTIFICATION",
-	"BC_DEAD_BINDER_DONE"
+	"BC_DEAD_BINDER_DONE",
+	"BC_TRANSACTION_SG",
+	"BC_REPLY_SG",
 };
 
 static const char * const binder_objstat_strings[] = {
@@ -3460,17 +5309,21 @@
 	BUILD_BUG_ON(ARRAY_SIZE(stats->bc) !=
 		     ARRAY_SIZE(binder_command_strings));
 	for (i = 0; i < ARRAY_SIZE(stats->bc); i++) {
-		if (stats->bc[i])
+		int temp = atomic_read(&stats->bc[i]);
+
+		if (temp)
 			seq_printf(m, "%s%s: %d\n", prefix,
-				   binder_command_strings[i], stats->bc[i]);
+				   binder_command_strings[i], temp);
 	}
 
 	BUILD_BUG_ON(ARRAY_SIZE(stats->br) !=
 		     ARRAY_SIZE(binder_return_strings));
 	for (i = 0; i < ARRAY_SIZE(stats->br); i++) {
-		if (stats->br[i])
+		int temp = atomic_read(&stats->br[i]);
+
+		if (temp)
 			seq_printf(m, "%s%s: %d\n", prefix,
-				   binder_return_strings[i], stats->br[i]);
+				   binder_return_strings[i], temp);
 	}
 
 	BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
@@ -3478,11 +5331,15 @@
 	BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
 		     ARRAY_SIZE(stats->obj_deleted));
 	for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) {
-		if (stats->obj_created[i] || stats->obj_deleted[i])
-			seq_printf(m, "%s%s: active %d total %d\n", prefix,
+		int created = atomic_read(&stats->obj_created[i]);
+		int deleted = atomic_read(&stats->obj_deleted[i]);
+
+		if (created || deleted)
+			seq_printf(m, "%s%s: active %d total %d\n",
+				prefix,
 				binder_objstat_strings[i],
-				stats->obj_created[i] - stats->obj_deleted[i],
-				stats->obj_created[i]);
+				created - deleted,
+				created);
 	}
 }
 
@@ -3490,50 +5347,59 @@
 				    struct binder_proc *proc)
 {
 	struct binder_work *w;
+	struct binder_thread *thread;
 	struct rb_node *n;
-	int count, strong, weak;
+	int count, strong, weak, ready_threads;
+	size_t free_async_space =
+		binder_alloc_get_free_async_space(&proc->alloc);
 
 	seq_printf(m, "proc %d\n", proc->pid);
+	seq_printf(m, "context %s\n", proc->context->name);
 	count = 0;
+	ready_threads = 0;
+	binder_inner_proc_lock(proc);
 	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
 		count++;
+
+	list_for_each_entry(thread, &proc->waiting_threads, waiting_thread_node)
+		ready_threads++;
+
 	seq_printf(m, "  threads: %d\n", count);
 	seq_printf(m, "  requested threads: %d+%d/%d\n"
 			"  ready threads %d\n"
 			"  free async space %zd\n", proc->requested_threads,
 			proc->requested_threads_started, proc->max_threads,
-			proc->ready_threads, proc->free_async_space);
+			ready_threads,
+			free_async_space);
 	count = 0;
 	for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n))
 		count++;
+	binder_inner_proc_unlock(proc);
 	seq_printf(m, "  nodes: %d\n", count);
 	count = 0;
 	strong = 0;
 	weak = 0;
+	binder_proc_lock(proc);
 	for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
 		struct binder_ref *ref = rb_entry(n, struct binder_ref,
 						  rb_node_desc);
 		count++;
-		strong += ref->strong;
-		weak += ref->weak;
+		strong += ref->data.strong;
+		weak += ref->data.weak;
 	}
+	binder_proc_unlock(proc);
 	seq_printf(m, "  refs: %d s %d w %d\n", count, strong, weak);
 
-	count = 0;
-	for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n))
-		count++;
+	count = binder_alloc_get_allocated_count(&proc->alloc);
 	seq_printf(m, "  buffers: %d\n", count);
 
 	count = 0;
+	binder_inner_proc_lock(proc);
 	list_for_each_entry(w, &proc->todo, entry) {
-		switch (w->type) {
-		case BINDER_WORK_TRANSACTION:
+		if (w->type == BINDER_WORK_TRANSACTION)
 			count++;
-			break;
-		default:
-			break;
-		}
 	}
+	binder_inner_proc_unlock(proc);
 	seq_printf(m, "  pending transactions: %d\n", count);
 
 	print_binder_stats(m, "  ", &proc->stats);
@@ -3544,107 +5410,131 @@
 {
 	struct binder_proc *proc;
 	struct binder_node *node;
-	int do_lock = !binder_debug_no_lock;
-
-	if (do_lock)
-		binder_lock(__func__);
+	struct binder_node *last_node = NULL;
 
 	seq_puts(m, "binder state:\n");
 
+	spin_lock(&binder_dead_nodes_lock);
 	if (!hlist_empty(&binder_dead_nodes))
 		seq_puts(m, "dead nodes:\n");
-	hlist_for_each_entry(node, &binder_dead_nodes, dead_node)
-		print_binder_node(m, node);
+	hlist_for_each_entry(node, &binder_dead_nodes, dead_node) {
+		/*
+		 * take a temporary reference on the node so it
+		 * survives and isn't removed from the list
+		 * while we print it.
+		 */
+		node->tmp_refs++;
+		spin_unlock(&binder_dead_nodes_lock);
+		if (last_node)
+			binder_put_node(last_node);
+		binder_node_lock(node);
+		print_binder_node_nilocked(m, node);
+		binder_node_unlock(node);
+		last_node = node;
+		spin_lock(&binder_dead_nodes_lock);
+	}
+	spin_unlock(&binder_dead_nodes_lock);
+	if (last_node)
+		binder_put_node(last_node);
 
+	mutex_lock(&binder_procs_lock);
 	hlist_for_each_entry(proc, &binder_procs, proc_node)
 		print_binder_proc(m, proc, 1);
-	if (do_lock)
-		binder_unlock(__func__);
+	mutex_unlock(&binder_procs_lock);
+
 	return 0;
 }
 
 static int binder_stats_show(struct seq_file *m, void *unused)
 {
 	struct binder_proc *proc;
-	int do_lock = !binder_debug_no_lock;
-
-	if (do_lock)
-		binder_lock(__func__);
 
 	seq_puts(m, "binder stats:\n");
 
 	print_binder_stats(m, "", &binder_stats);
 
+	mutex_lock(&binder_procs_lock);
 	hlist_for_each_entry(proc, &binder_procs, proc_node)
 		print_binder_proc_stats(m, proc);
-	if (do_lock)
-		binder_unlock(__func__);
+	mutex_unlock(&binder_procs_lock);
+
 	return 0;
 }
 
 static int binder_transactions_show(struct seq_file *m, void *unused)
 {
 	struct binder_proc *proc;
-	int do_lock = !binder_debug_no_lock;
-
-	if (do_lock)
-		binder_lock(__func__);
 
 	seq_puts(m, "binder transactions:\n");
+	mutex_lock(&binder_procs_lock);
 	hlist_for_each_entry(proc, &binder_procs, proc_node)
 		print_binder_proc(m, proc, 0);
-	if (do_lock)
-		binder_unlock(__func__);
+	mutex_unlock(&binder_procs_lock);
+
 	return 0;
 }
 
 static int binder_proc_show(struct seq_file *m, void *unused)
 {
 	struct binder_proc *itr;
-	struct binder_proc *proc = m->private;
-	int do_lock = !binder_debug_no_lock;
-	bool valid_proc = false;
+	int pid = (unsigned long)m->private;
 
-	if (do_lock)
-		binder_lock(__func__);
-
+	mutex_lock(&binder_procs_lock);
 	hlist_for_each_entry(itr, &binder_procs, proc_node) {
-		if (itr == proc) {
-			valid_proc = true;
-			break;
+		if (itr->pid == pid) {
+			seq_puts(m, "binder proc state:\n");
+			print_binder_proc(m, itr, 1);
 		}
 	}
-	if (valid_proc) {
-		seq_puts(m, "binder proc state:\n");
-		print_binder_proc(m, proc, 1);
-	}
-	if (do_lock)
-		binder_unlock(__func__);
+	mutex_unlock(&binder_procs_lock);
+
 	return 0;
 }
 
 static void print_binder_transaction_log_entry(struct seq_file *m,
 					struct binder_transaction_log_entry *e)
 {
+	int debug_id = READ_ONCE(e->debug_id_done);
+	/*
+	 * read barrier to guarantee debug_id_done read before
+	 * we print the log values
+	 */
+	smp_rmb();
 	seq_printf(m,
-		   "%d: %s from %d:%d to %d:%d node %d handle %d size %d:%d\n",
+		   "%d: %s from %d:%d to %d:%d context %s node %d handle %d size %d:%d ret %d/%d l=%d",
 		   e->debug_id, (e->call_type == 2) ? "reply" :
 		   ((e->call_type == 1) ? "async" : "call "), e->from_proc,
-		   e->from_thread, e->to_proc, e->to_thread, e->to_node,
-		   e->target_handle, e->data_size, e->offsets_size);
+		   e->from_thread, e->to_proc, e->to_thread, e->context_name,
+		   e->to_node, e->target_handle, e->data_size, e->offsets_size,
+		   e->return_error, e->return_error_param,
+		   e->return_error_line);
+	/*
+	 * read-barrier to guarantee read of debug_id_done after
+	 * done printing the fields of the entry
+	 */
+	smp_rmb();
+	seq_printf(m, debug_id && debug_id == READ_ONCE(e->debug_id_done) ?
+			"\n" : " (incomplete)\n");
 }
 
 static int binder_transaction_log_show(struct seq_file *m, void *unused)
 {
 	struct binder_transaction_log *log = m->private;
+	unsigned int log_cur = atomic_read(&log->cur);
+	unsigned int count;
+	unsigned int cur;
 	int i;
 
-	if (log->full) {
-		for (i = log->next; i < ARRAY_SIZE(log->entry); i++)
-			print_binder_transaction_log_entry(m, &log->entry[i]);
+	count = log_cur + 1;
+	cur = count < ARRAY_SIZE(log->entry) && !log->full ?
+		0 : count % ARRAY_SIZE(log->entry);
+	if (count > ARRAY_SIZE(log->entry) || log->full)
+		count = ARRAY_SIZE(log->entry);
+	for (i = 0; i < count; i++) {
+		unsigned int index = cur++ % ARRAY_SIZE(log->entry);
+
+		print_binder_transaction_log_entry(m, &log->entry[index]);
 	}
-	for (i = 0; i < log->next; i++)
-		print_binder_transaction_log_entry(m, &log->entry[i]);
 	return 0;
 }
 
@@ -3659,21 +5549,48 @@
 	.release = binder_release,
 };
 
-static struct miscdevice binder_miscdev = {
-	.minor = MISC_DYNAMIC_MINOR,
-	.name = "binder",
-	.fops = &binder_fops
-};
-
 BINDER_DEBUG_ENTRY(state);
 BINDER_DEBUG_ENTRY(stats);
 BINDER_DEBUG_ENTRY(transactions);
 BINDER_DEBUG_ENTRY(transaction_log);
 
+static int __init init_binder_device(const char *name)
+{
+	int ret;
+	struct binder_device *binder_device;
+
+	binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL);
+	if (!binder_device)
+		return -ENOMEM;
+
+	binder_device->miscdev.fops = &binder_fops;
+	binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
+	binder_device->miscdev.name = name;
+
+	binder_device->context.binder_context_mgr_uid = INVALID_UID;
+	binder_device->context.name = name;
+	mutex_init(&binder_device->context.context_mgr_node_lock);
+
+	ret = misc_register(&binder_device->miscdev);
+	if (ret < 0) {
+		kfree(binder_device);
+		return ret;
+	}
+
+	hlist_add_head(&binder_device->hlist, &binder_devices);
+
+	return ret;
+}
+
 static int __init binder_init(void)
 {
 	int ret;
+	char *device_name, *device_names;
+	struct binder_device *device;
+	struct hlist_node *tmp;
 
+	atomic_set(&binder_transaction_log.cur, ~0U);
+	atomic_set(&binder_transaction_log_failed.cur, ~0U);
 	binder_deferred_workqueue = create_singlethread_workqueue("binder");
 	if (!binder_deferred_workqueue)
 		return -ENOMEM;
@@ -3682,7 +5599,7 @@
 	if (binder_debugfs_dir_entry_root)
 		binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
 						 binder_debugfs_dir_entry_root);
-	ret = misc_register(&binder_miscdev);
+
 	if (binder_debugfs_dir_entry_root) {
 		debugfs_create_file("state",
 				    S_IRUGO,
@@ -3710,6 +5627,37 @@
 				    &binder_transaction_log_failed,
 				    &binder_transaction_log_fops);
 	}
+
+	/*
+	 * Copy the module_parameter string, because we don't want to
+	 * tokenize it in-place.
+	 */
+	device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL);
+	if (!device_names) {
+		ret = -ENOMEM;
+		goto err_alloc_device_names_failed;
+	}
+	strcpy(device_names, binder_devices_param);
+
+	while ((device_name = strsep(&device_names, ","))) {
+		ret = init_binder_device(device_name);
+		if (ret)
+			goto err_init_binder_device_failed;
+	}
+
+	return ret;
+
+err_init_binder_device_failed:
+	hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
+		misc_deregister(&device->miscdev);
+		hlist_del(&device->hlist);
+		kfree(device);
+	}
+err_alloc_device_names_failed:
+	debugfs_remove_recursive(binder_debugfs_dir_entry_root);
+
+	destroy_workqueue(binder_deferred_workqueue);
+
 	return ret;
 }
 
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
new file mode 100644
index 0000000..aabfeba
--- /dev/null
+++ b/drivers/android/binder_alloc.c
@@ -0,0 +1,802 @@
+/* binder_alloc.c
+ *
+ * Android IPC Subsystem
+ *
+ * Copyright (C) 2007-2017 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/cacheflush.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/rtmutex.h>
+#include <linux/rbtree.h>
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include "binder_alloc.h"
+#include "binder_trace.h"
+
+static DEFINE_MUTEX(binder_alloc_mmap_lock);
+
+enum {
+	BINDER_DEBUG_OPEN_CLOSE             = 1U << 1,
+	BINDER_DEBUG_BUFFER_ALLOC           = 1U << 2,
+	BINDER_DEBUG_BUFFER_ALLOC_ASYNC     = 1U << 3,
+};
+static uint32_t binder_alloc_debug_mask;
+
+module_param_named(debug_mask, binder_alloc_debug_mask,
+		   uint, S_IWUSR | S_IRUGO);
+
+#define binder_alloc_debug(mask, x...) \
+	do { \
+		if (binder_alloc_debug_mask & mask) \
+			pr_info(x); \
+	} while (0)
+
+static size_t binder_alloc_buffer_size(struct binder_alloc *alloc,
+				       struct binder_buffer *buffer)
+{
+	if (list_is_last(&buffer->entry, &alloc->buffers))
+		return alloc->buffer +
+		       alloc->buffer_size - (void *)buffer->data;
+	return (size_t)list_entry(buffer->entry.next,
+			  struct binder_buffer, entry) - (size_t)buffer->data;
+}
+
+static void binder_insert_free_buffer(struct binder_alloc *alloc,
+				      struct binder_buffer *new_buffer)
+{
+	struct rb_node **p = &alloc->free_buffers.rb_node;
+	struct rb_node *parent = NULL;
+	struct binder_buffer *buffer;
+	size_t buffer_size;
+	size_t new_buffer_size;
+
+	BUG_ON(!new_buffer->free);
+
+	new_buffer_size = binder_alloc_buffer_size(alloc, new_buffer);
+
+	binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+		     "%d: add free buffer, size %zd, at %pK\n",
+		      alloc->pid, new_buffer_size, new_buffer);
+
+	while (*p) {
+		parent = *p;
+		buffer = rb_entry(parent, struct binder_buffer, rb_node);
+		BUG_ON(!buffer->free);
+
+		buffer_size = binder_alloc_buffer_size(alloc, buffer);
+
+		if (new_buffer_size < buffer_size)
+			p = &parent->rb_left;
+		else
+			p = &parent->rb_right;
+	}
+	rb_link_node(&new_buffer->rb_node, parent, p);
+	rb_insert_color(&new_buffer->rb_node, &alloc->free_buffers);
+}
+
+static void binder_insert_allocated_buffer_locked(
+		struct binder_alloc *alloc, struct binder_buffer *new_buffer)
+{
+	struct rb_node **p = &alloc->allocated_buffers.rb_node;
+	struct rb_node *parent = NULL;
+	struct binder_buffer *buffer;
+
+	BUG_ON(new_buffer->free);
+
+	while (*p) {
+		parent = *p;
+		buffer = rb_entry(parent, struct binder_buffer, rb_node);
+		BUG_ON(buffer->free);
+
+		if (new_buffer < buffer)
+			p = &parent->rb_left;
+		else if (new_buffer > buffer)
+			p = &parent->rb_right;
+		else
+			BUG();
+	}
+	rb_link_node(&new_buffer->rb_node, parent, p);
+	rb_insert_color(&new_buffer->rb_node, &alloc->allocated_buffers);
+}
+
+static struct binder_buffer *binder_alloc_prepare_to_free_locked(
+		struct binder_alloc *alloc,
+		uintptr_t user_ptr)
+{
+	struct rb_node *n = alloc->allocated_buffers.rb_node;
+	struct binder_buffer *buffer;
+	struct binder_buffer *kern_ptr;
+
+	kern_ptr = (struct binder_buffer *)(user_ptr - alloc->user_buffer_offset
+		- offsetof(struct binder_buffer, data));
+
+	while (n) {
+		buffer = rb_entry(n, struct binder_buffer, rb_node);
+		BUG_ON(buffer->free);
+
+		if (kern_ptr < buffer)
+			n = n->rb_left;
+		else if (kern_ptr > buffer)
+			n = n->rb_right;
+		else {
+			/*
+			 * Guard against user threads attempting to
+			 * free the buffer twice
+			 */
+			if (buffer->free_in_progress) {
+				pr_err("%d:%d FREE_BUFFER u%016llx user freed buffer twice\n",
+				       alloc->pid, current->pid, (u64)user_ptr);
+				return NULL;
+			}
+			buffer->free_in_progress = 1;
+			return buffer;
+		}
+	}
+	return NULL;
+}
+
+/**
+ * binder_alloc_buffer_lookup() - get buffer given user ptr
+ * @alloc:	binder_alloc for this proc
+ * @user_ptr:	User pointer to buffer data
+ *
+ * Validate userspace pointer to buffer data and return buffer corresponding to
+ * that user pointer. Search the rb tree for buffer that matches user data
+ * pointer.
+ *
+ * Return:	Pointer to buffer or NULL
+ */
+struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc,
+						   uintptr_t user_ptr)
+{
+	struct binder_buffer *buffer;
+
+	mutex_lock(&alloc->mutex);
+	buffer = binder_alloc_prepare_to_free_locked(alloc, user_ptr);
+	mutex_unlock(&alloc->mutex);
+	return buffer;
+}
+
+static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
+				    void *start, void *end,
+				    struct vm_area_struct *vma)
+{
+	void *page_addr;
+	unsigned long user_page_addr;
+	struct page **page;
+	struct mm_struct *mm;
+
+	binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+		     "%d: %s pages %pK-%pK\n", alloc->pid,
+		     allocate ? "allocate" : "free", start, end);
+
+	if (end <= start)
+		return 0;
+
+	trace_binder_update_page_range(alloc, allocate, start, end);
+
+	if (vma)
+		mm = NULL;
+	else
+		mm = get_task_mm(alloc->tsk);
+
+	if (mm) {
+		down_write(&mm->mmap_sem);
+		vma = alloc->vma;
+		if (vma && mm != alloc->vma_vm_mm) {
+			pr_err("%d: vma mm and task mm mismatch\n",
+				alloc->pid);
+			vma = NULL;
+		}
+	}
+
+	if (allocate == 0)
+		goto free_range;
+
+	if (vma == NULL) {
+		pr_err("%d: binder_alloc_buf failed to map pages in userspace, no vma\n",
+			alloc->pid);
+		goto err_no_vma;
+	}
+
+	for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
+		int ret;
+
+		page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE];
+
+		BUG_ON(*page);
+		*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
+		if (*page == NULL) {
+			pr_err("%d: binder_alloc_buf failed for page at %pK\n",
+				alloc->pid, page_addr);
+			goto err_alloc_page_failed;
+		}
+		ret = map_kernel_range_noflush((unsigned long)page_addr,
+					PAGE_SIZE, PAGE_KERNEL, page);
+		flush_cache_vmap((unsigned long)page_addr,
+				(unsigned long)page_addr + PAGE_SIZE);
+		if (ret != 1) {
+			pr_err("%d: binder_alloc_buf failed to map page at %pK in kernel\n",
+			       alloc->pid, page_addr);
+			goto err_map_kernel_failed;
+		}
+		user_page_addr =
+			(uintptr_t)page_addr + alloc->user_buffer_offset;
+		ret = vm_insert_page(vma, user_page_addr, page[0]);
+		if (ret) {
+			pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n",
+			       alloc->pid, user_page_addr);
+			goto err_vm_insert_page_failed;
+		}
+		/* vm_insert_page does not seem to increment the refcount */
+	}
+	if (mm) {
+		up_write(&mm->mmap_sem);
+		mmput(mm);
+	}
+	return 0;
+
+free_range:
+	for (page_addr = end - PAGE_SIZE; page_addr >= start;
+	     page_addr -= PAGE_SIZE) {
+		page = &alloc->pages[(page_addr - alloc->buffer) / PAGE_SIZE];
+		if (vma)
+			zap_page_range(vma, (uintptr_t)page_addr +
+				alloc->user_buffer_offset, PAGE_SIZE, NULL);
+err_vm_insert_page_failed:
+		unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
+err_map_kernel_failed:
+		__free_page(*page);
+		*page = NULL;
+err_alloc_page_failed:
+		;
+	}
+err_no_vma:
+	if (mm) {
+		up_write(&mm->mmap_sem);
+		mmput(mm);
+	}
+	return vma ? -ENOMEM : -ESRCH;
+}
+
+struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc,
+						  size_t data_size,
+						  size_t offsets_size,
+						  size_t extra_buffers_size,
+						  int is_async)
+{
+	struct rb_node *n = alloc->free_buffers.rb_node;
+	struct binder_buffer *buffer;
+	size_t buffer_size;
+	struct rb_node *best_fit = NULL;
+	void *has_page_addr;
+	void *end_page_addr;
+	size_t size, data_offsets_size;
+	int ret;
+
+	if (alloc->vma == NULL) {
+		pr_err("%d: binder_alloc_buf, no vma\n",
+		       alloc->pid);
+		return ERR_PTR(-ESRCH);
+	}
+
+	data_offsets_size = ALIGN(data_size, sizeof(void *)) +
+		ALIGN(offsets_size, sizeof(void *));
+
+	if (data_offsets_size < data_size || data_offsets_size < offsets_size) {
+		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+				"%d: got transaction with invalid size %zd-%zd\n",
+				alloc->pid, data_size, offsets_size);
+		return ERR_PTR(-EINVAL);
+	}
+	size = data_offsets_size + ALIGN(extra_buffers_size, sizeof(void *));
+	if (size < data_offsets_size || size < extra_buffers_size) {
+		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+				"%d: got transaction with invalid extra_buffers_size %zd\n",
+				alloc->pid, extra_buffers_size);
+		return ERR_PTR(-EINVAL);
+	}
+	if (is_async &&
+	    alloc->free_async_space < size + sizeof(struct binder_buffer)) {
+		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+			     "%d: binder_alloc_buf size %zd failed, no async space left\n",
+			      alloc->pid, size);
+		return ERR_PTR(-ENOSPC);
+	}
+
+	while (n) {
+		buffer = rb_entry(n, struct binder_buffer, rb_node);
+		BUG_ON(!buffer->free);
+		buffer_size = binder_alloc_buffer_size(alloc, buffer);
+
+		if (size < buffer_size) {
+			best_fit = n;
+			n = n->rb_left;
+		} else if (size > buffer_size)
+			n = n->rb_right;
+		else {
+			best_fit = n;
+			break;
+		}
+	}
+	if (best_fit == NULL) {
+		size_t allocated_buffers = 0;
+		size_t largest_alloc_size = 0;
+		size_t total_alloc_size = 0;
+		size_t free_buffers = 0;
+		size_t largest_free_size = 0;
+		size_t total_free_size = 0;
+
+		for (n = rb_first(&alloc->allocated_buffers); n != NULL;
+		     n = rb_next(n)) {
+			buffer = rb_entry(n, struct binder_buffer, rb_node);
+			buffer_size = binder_alloc_buffer_size(alloc, buffer);
+			allocated_buffers++;
+			total_alloc_size += buffer_size;
+			if (buffer_size > largest_alloc_size)
+				largest_alloc_size = buffer_size;
+		}
+		for (n = rb_first(&alloc->free_buffers); n != NULL;
+		     n = rb_next(n)) {
+			buffer = rb_entry(n, struct binder_buffer, rb_node);
+			buffer_size = binder_alloc_buffer_size(alloc, buffer);
+			free_buffers++;
+			total_free_size += buffer_size;
+			if (buffer_size > largest_free_size)
+				largest_free_size = buffer_size;
+		}
+		pr_err("%d: binder_alloc_buf size %zd failed, no address space\n",
+			alloc->pid, size);
+		pr_err("allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n",
+		       total_alloc_size, allocated_buffers, largest_alloc_size,
+		       total_free_size, free_buffers, largest_free_size);
+		return ERR_PTR(-ENOSPC);
+	}
+	if (n == NULL) {
+		buffer = rb_entry(best_fit, struct binder_buffer, rb_node);
+		buffer_size = binder_alloc_buffer_size(alloc, buffer);
+	}
+
+	binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+		     "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n",
+		      alloc->pid, size, buffer, buffer_size);
+
+	has_page_addr =
+		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
+	if (n == NULL) {
+		if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
+			buffer_size = size; /* no room for other buffers */
+		else
+			buffer_size = size + sizeof(struct binder_buffer);
+	}
+	end_page_addr =
+		(void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
+	if (end_page_addr > has_page_addr)
+		end_page_addr = has_page_addr;
+	ret = binder_update_page_range(alloc, 1,
+	    (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	rb_erase(best_fit, &alloc->free_buffers);
+	buffer->free = 0;
+	buffer->free_in_progress = 0;
+	binder_insert_allocated_buffer_locked(alloc, buffer);
+	if (buffer_size != size) {
+		struct binder_buffer *new_buffer = (void *)buffer->data + size;
+
+		list_add(&new_buffer->entry, &buffer->entry);
+		new_buffer->free = 1;
+		binder_insert_free_buffer(alloc, new_buffer);
+	}
+	binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+		     "%d: binder_alloc_buf size %zd got %pK\n",
+		      alloc->pid, size, buffer);
+	buffer->data_size = data_size;
+	buffer->offsets_size = offsets_size;
+	buffer->async_transaction = is_async;
+	buffer->extra_buffers_size = extra_buffers_size;
+	if (is_async) {
+		alloc->free_async_space -= size + sizeof(struct binder_buffer);
+		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
+			     "%d: binder_alloc_buf size %zd async free %zd\n",
+			      alloc->pid, size, alloc->free_async_space);
+	}
+	return buffer;
+}
+
+/**
+ * binder_alloc_new_buf() - Allocate a new binder buffer
+ * @alloc:              binder_alloc for this proc
+ * @data_size:          size of user data buffer
+ * @offsets_size:       user specified buffer offset
+ * @extra_buffers_size: size of extra space for meta-data (eg, security context)
+ * @is_async:           buffer for async transaction
+ *
+ * Allocate a new buffer given the requested sizes. Returns
+ * the kernel version of the buffer pointer. The size allocated
+ * is the sum of the three given sizes (each rounded up to
+ * pointer-sized boundary)
+ *
+ * Return:	The allocated buffer or %NULL if error
+ */
+struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
+					   size_t data_size,
+					   size_t offsets_size,
+					   size_t extra_buffers_size,
+					   int is_async)
+{
+	struct binder_buffer *buffer;
+
+	mutex_lock(&alloc->mutex);
+	buffer = binder_alloc_new_buf_locked(alloc, data_size, offsets_size,
+					     extra_buffers_size, is_async);
+	mutex_unlock(&alloc->mutex);
+	return buffer;
+}
+
+static void *buffer_start_page(struct binder_buffer *buffer)
+{
+	return (void *)((uintptr_t)buffer & PAGE_MASK);
+}
+
+static void *buffer_end_page(struct binder_buffer *buffer)
+{
+	return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK);
+}
+
+static void binder_delete_free_buffer(struct binder_alloc *alloc,
+				      struct binder_buffer *buffer)
+{
+	struct binder_buffer *prev, *next = NULL;
+	int free_page_end = 1;
+	int free_page_start = 1;
+
+	BUG_ON(alloc->buffers.next == &buffer->entry);
+	prev = list_entry(buffer->entry.prev, struct binder_buffer, entry);
+	BUG_ON(!prev->free);
+	if (buffer_end_page(prev) == buffer_start_page(buffer)) {
+		free_page_start = 0;
+		if (buffer_end_page(prev) == buffer_end_page(buffer))
+			free_page_end = 0;
+		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+			     "%d: merge free, buffer %pK share page with %pK\n",
+			      alloc->pid, buffer, prev);
+	}
+
+	if (!list_is_last(&buffer->entry, &alloc->buffers)) {
+		next = list_entry(buffer->entry.next,
+				  struct binder_buffer, entry);
+		if (buffer_start_page(next) == buffer_end_page(buffer)) {
+			free_page_end = 0;
+			if (buffer_start_page(next) ==
+			    buffer_start_page(buffer))
+				free_page_start = 0;
+			binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+				     "%d: merge free, buffer %pK share page with %pK\n",
+				      alloc->pid, buffer, prev);
+		}
+	}
+	list_del(&buffer->entry);
+	if (free_page_start || free_page_end) {
+		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+			     "%d: merge free, buffer %pK do not share page%s%s with %pK or %pK\n",
+			     alloc->pid, buffer, free_page_start ? "" : " end",
+			     free_page_end ? "" : " start", prev, next);
+		binder_update_page_range(alloc, 0, free_page_start ?
+			buffer_start_page(buffer) : buffer_end_page(buffer),
+			(free_page_end ? buffer_end_page(buffer) :
+			buffer_start_page(buffer)) + PAGE_SIZE, NULL);
+	}
+}
+
+static void binder_free_buf_locked(struct binder_alloc *alloc,
+				   struct binder_buffer *buffer)
+{
+	size_t size, buffer_size;
+
+	buffer_size = binder_alloc_buffer_size(alloc, buffer);
+
+	size = ALIGN(buffer->data_size, sizeof(void *)) +
+		ALIGN(buffer->offsets_size, sizeof(void *)) +
+		ALIGN(buffer->extra_buffers_size, sizeof(void *));
+
+	binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+		     "%d: binder_free_buf %pK size %zd buffer_size %zd\n",
+		      alloc->pid, buffer, size, buffer_size);
+
+	BUG_ON(buffer->free);
+	BUG_ON(size > buffer_size);
+	BUG_ON(buffer->transaction != NULL);
+	BUG_ON((void *)buffer < alloc->buffer);
+	BUG_ON((void *)buffer > alloc->buffer + alloc->buffer_size);
+
+	if (buffer->async_transaction) {
+		alloc->free_async_space += size + sizeof(struct binder_buffer);
+
+		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
+			     "%d: binder_free_buf size %zd async free %zd\n",
+			      alloc->pid, size, alloc->free_async_space);
+	}
+
+	binder_update_page_range(alloc, 0,
+		(void *)PAGE_ALIGN((uintptr_t)buffer->data),
+		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK),
+		NULL);
+
+	rb_erase(&buffer->rb_node, &alloc->allocated_buffers);
+	buffer->free = 1;
+	if (!list_is_last(&buffer->entry, &alloc->buffers)) {
+		struct binder_buffer *next = list_entry(buffer->entry.next,
+						struct binder_buffer, entry);
+
+		if (next->free) {
+			rb_erase(&next->rb_node, &alloc->free_buffers);
+			binder_delete_free_buffer(alloc, next);
+		}
+	}
+	if (alloc->buffers.next != &buffer->entry) {
+		struct binder_buffer *prev = list_entry(buffer->entry.prev,
+						struct binder_buffer, entry);
+
+		if (prev->free) {
+			binder_delete_free_buffer(alloc, buffer);
+			rb_erase(&prev->rb_node, &alloc->free_buffers);
+			buffer = prev;
+		}
+	}
+	binder_insert_free_buffer(alloc, buffer);
+}
+
+/**
+ * binder_alloc_free_buf() - free a binder buffer
+ * @alloc:	binder_alloc for this proc
+ * @buffer:	kernel pointer to buffer
+ *
+ * Free the buffer allocated via binder_alloc_new_buffer()
+ */
+void binder_alloc_free_buf(struct binder_alloc *alloc,
+			    struct binder_buffer *buffer)
+{
+	mutex_lock(&alloc->mutex);
+	binder_free_buf_locked(alloc, buffer);
+	mutex_unlock(&alloc->mutex);
+}
+
+/**
+ * binder_alloc_mmap_handler() - map virtual address space for proc
+ * @alloc:	alloc structure for this proc
+ * @vma:	vma passed to mmap()
+ *
+ * Called by binder_mmap() to initialize the space specified in
+ * vma for allocating binder buffers
+ *
+ * Return:
+ *      0 = success
+ *      -EBUSY = address space already mapped
+ *      -ENOMEM = failed to map memory to given address space
+ */
+int binder_alloc_mmap_handler(struct binder_alloc *alloc,
+			      struct vm_area_struct *vma)
+{
+	int ret;
+	struct vm_struct *area;
+	const char *failure_string;
+	struct binder_buffer *buffer;
+
+	mutex_lock(&binder_alloc_mmap_lock);
+	if (alloc->buffer) {
+		ret = -EBUSY;
+		failure_string = "already mapped";
+		goto err_already_mapped;
+	}
+
+	area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
+	if (area == NULL) {
+		ret = -ENOMEM;
+		failure_string = "get_vm_area";
+		goto err_get_vm_area_failed;
+	}
+	alloc->buffer = area->addr;
+	alloc->user_buffer_offset =
+		vma->vm_start - (uintptr_t)alloc->buffer;
+	mutex_unlock(&binder_alloc_mmap_lock);
+
+#ifdef CONFIG_CPU_CACHE_VIPT
+	if (cache_is_vipt_aliasing()) {
+		while (CACHE_COLOUR(
+				(vma->vm_start ^ (uint32_t)alloc->buffer))) {
+			pr_info("binder_mmap: %d %lx-%lx maps %pK bad alignment\n",
+				alloc->pid, vma->vm_start, vma->vm_end,
+				alloc->buffer);
+			vma->vm_start += PAGE_SIZE;
+		}
+	}
+#endif
+	alloc->pages = kzalloc(sizeof(alloc->pages[0]) *
+				   ((vma->vm_end - vma->vm_start) / PAGE_SIZE),
+			       GFP_KERNEL);
+	if (alloc->pages == NULL) {
+		ret = -ENOMEM;
+		failure_string = "alloc page array";
+		goto err_alloc_pages_failed;
+	}
+	alloc->buffer_size = vma->vm_end - vma->vm_start;
+
+	if (binder_update_page_range(alloc, 1, alloc->buffer,
+				     alloc->buffer + PAGE_SIZE, vma)) {
+		ret = -ENOMEM;
+		failure_string = "alloc small buf";
+		goto err_alloc_small_buf_failed;
+	}
+	buffer = alloc->buffer;
+	INIT_LIST_HEAD(&alloc->buffers);
+	list_add(&buffer->entry, &alloc->buffers);
+	buffer->free = 1;
+	binder_insert_free_buffer(alloc, buffer);
+	alloc->free_async_space = alloc->buffer_size / 2;
+	barrier();
+	alloc->vma = vma;
+	alloc->vma_vm_mm = vma->vm_mm;
+
+	return 0;
+
+err_alloc_small_buf_failed:
+	kfree(alloc->pages);
+	alloc->pages = NULL;
+err_alloc_pages_failed:
+	mutex_lock(&binder_alloc_mmap_lock);
+	vfree(alloc->buffer);
+	alloc->buffer = NULL;
+err_get_vm_area_failed:
+err_already_mapped:
+	mutex_unlock(&binder_alloc_mmap_lock);
+	pr_err("%s: %d %lx-%lx %s failed %d\n", __func__,
+	       alloc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
+	return ret;
+}
+
+
+void binder_alloc_deferred_release(struct binder_alloc *alloc)
+{
+	struct rb_node *n;
+	int buffers, page_count;
+
+	BUG_ON(alloc->vma);
+
+	buffers = 0;
+	mutex_lock(&alloc->mutex);
+	while ((n = rb_first(&alloc->allocated_buffers))) {
+		struct binder_buffer *buffer;
+
+		buffer = rb_entry(n, struct binder_buffer, rb_node);
+
+		/* Transaction should already have been freed */
+		BUG_ON(buffer->transaction);
+
+		binder_free_buf_locked(alloc, buffer);
+		buffers++;
+	}
+
+	page_count = 0;
+	if (alloc->pages) {
+		int i;
+
+		for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
+			void *page_addr;
+
+			if (!alloc->pages[i])
+				continue;
+
+			page_addr = alloc->buffer + i * PAGE_SIZE;
+			binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
+				     "%s: %d: page %d at %pK not freed\n",
+				     __func__, alloc->pid, i, page_addr);
+			unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
+			__free_page(alloc->pages[i]);
+			page_count++;
+		}
+		kfree(alloc->pages);
+		vfree(alloc->buffer);
+	}
+	mutex_unlock(&alloc->mutex);
+
+	binder_alloc_debug(BINDER_DEBUG_OPEN_CLOSE,
+		     "%s: %d buffers %d, pages %d\n",
+		     __func__, alloc->pid, buffers, page_count);
+}
+
+static void print_binder_buffer(struct seq_file *m, const char *prefix,
+				struct binder_buffer *buffer)
+{
+	seq_printf(m, "%s %d: %pK size %zd:%zd:%zd %s\n",
+		   prefix, buffer->debug_id, buffer->data,
+		   buffer->data_size, buffer->offsets_size,
+		   buffer->extra_buffers_size,
+		   buffer->transaction ? "active" : "delivered");
+}
+
+/**
+ * binder_alloc_print_allocated() - print buffer info
+ * @m:     seq_file for output via seq_printf()
+ * @alloc: binder_alloc for this proc
+ *
+ * Prints information about every buffer associated with
+ * the binder_alloc state to the given seq_file
+ */
+void binder_alloc_print_allocated(struct seq_file *m,
+				  struct binder_alloc *alloc)
+{
+	struct rb_node *n;
+
+	mutex_lock(&alloc->mutex);
+	for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n))
+		print_binder_buffer(m, "  buffer",
+				    rb_entry(n, struct binder_buffer, rb_node));
+	mutex_unlock(&alloc->mutex);
+}
+
+/**
+ * binder_alloc_get_allocated_count() - return count of buffers
+ * @alloc: binder_alloc for this proc
+ *
+ * Return: count of allocated buffers
+ */
+int binder_alloc_get_allocated_count(struct binder_alloc *alloc)
+{
+	struct rb_node *n;
+	int count = 0;
+
+	mutex_lock(&alloc->mutex);
+	for (n = rb_first(&alloc->allocated_buffers); n != NULL; n = rb_next(n))
+		count++;
+	mutex_unlock(&alloc->mutex);
+	return count;
+}
+
+
+/**
+ * binder_alloc_vma_close() - invalidate address space
+ * @alloc: binder_alloc for this proc
+ *
+ * Called from binder_vma_close() when releasing address space.
+ * Clears alloc->vma to prevent new incoming transactions from
+ * allocating more buffers.
+ */
+void binder_alloc_vma_close(struct binder_alloc *alloc)
+{
+	WRITE_ONCE(alloc->vma, NULL);
+	WRITE_ONCE(alloc->vma_vm_mm, NULL);
+}
+
+/**
+ * binder_alloc_init() - called by binder_open() for per-proc initialization
+ * @alloc: binder_alloc for this proc
+ *
+ * Called from binder_open() to initialize binder_alloc fields for
+ * new binder proc
+ */
+void binder_alloc_init(struct binder_alloc *alloc)
+{
+	alloc->tsk = current->group_leader;
+	alloc->pid = current->group_leader->pid;
+	mutex_init(&alloc->mutex);
+}
+
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
new file mode 100644
index 0000000..088e4ff
--- /dev/null
+++ b/drivers/android/binder_alloc.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2017 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_BINDER_ALLOC_H
+#define _LINUX_BINDER_ALLOC_H
+
+#include <linux/rbtree.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/rtmutex.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+struct binder_transaction;
+
+/**
+ * struct binder_buffer - buffer used for binder transactions
+ * @entry:              entry alloc->buffers
+ * @rb_node:            node for allocated_buffers/free_buffers rb trees
+ * @free:               true if buffer is free
+ * @allow_user_free:    describe the second member of struct blah,
+ * @async_transaction:  describe the second member of struct blah,
+ * @debug_id:           describe the second member of struct blah,
+ * @transaction:        describe the second member of struct blah,
+ * @target_node:        describe the second member of struct blah,
+ * @data_size:          describe the second member of struct blah,
+ * @offsets_size:       describe the second member of struct blah,
+ * @extra_buffers_size: describe the second member of struct blah,
+ * @data:i              describe the second member of struct blah,
+ *
+ * Bookkeeping structure for binder transaction buffers
+ */
+struct binder_buffer {
+	struct list_head entry; /* free and allocated entries by address */
+	struct rb_node rb_node; /* free entry by size or allocated entry */
+				/* by address */
+	unsigned free:1;
+	unsigned allow_user_free:1;
+	unsigned async_transaction:1;
+	unsigned free_in_progress:1;
+	unsigned debug_id:28;
+
+	struct binder_transaction *transaction;
+
+	struct binder_node *target_node;
+	size_t data_size;
+	size_t offsets_size;
+	size_t extra_buffers_size;
+	uint8_t data[0];
+};
+
+/**
+ * struct binder_alloc - per-binder proc state for binder allocator
+ * @vma:                vm_area_struct passed to mmap_handler
+ *                      (invarient after mmap)
+ * @tsk:                tid for task that called init for this proc
+ *                      (invariant after init)
+ * @vma_vm_mm:          copy of vma->vm_mm (invarient after mmap)
+ * @buffer:             base of per-proc address space mapped via mmap
+ * @user_buffer_offset: offset between user and kernel VAs for buffer
+ * @buffers:            list of all buffers for this proc
+ * @free_buffers:       rb tree of buffers available for allocation
+ *                      sorted by size
+ * @allocated_buffers:  rb tree of allocated buffers sorted by address
+ * @free_async_space:   VA space available for async buffers. This is
+ *                      initialized at mmap time to 1/2 the full VA space
+ * @pages:              array of physical page addresses for each
+ *                      page of mmap'd space
+ * @buffer_size:        size of address space specified via mmap
+ * @pid:                pid for associated binder_proc (invariant after init)
+ *
+ * Bookkeeping structure for per-proc address space management for binder
+ * buffers. It is normally initialized during binder_init() and binder_mmap()
+ * calls. The address space is used for both user-visible buffers and for
+ * struct binder_buffer objects used to track the user buffers
+ */
+struct binder_alloc {
+	struct mutex mutex;
+	struct task_struct *tsk;
+	struct vm_area_struct *vma;
+	struct mm_struct *vma_vm_mm;
+	void *buffer;
+	ptrdiff_t user_buffer_offset;
+	struct list_head buffers;
+	struct rb_root free_buffers;
+	struct rb_root allocated_buffers;
+	size_t free_async_space;
+	struct page **pages;
+	size_t buffer_size;
+	uint32_t buffer_free;
+	int pid;
+};
+
+extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
+						  size_t data_size,
+						  size_t offsets_size,
+						  size_t extra_buffers_size,
+						  int is_async);
+extern void binder_alloc_init(struct binder_alloc *alloc);
+extern void binder_alloc_vma_close(struct binder_alloc *alloc);
+extern struct binder_buffer *
+binder_alloc_prepare_to_free(struct binder_alloc *alloc,
+			     uintptr_t user_ptr);
+extern void binder_alloc_free_buf(struct binder_alloc *alloc,
+				  struct binder_buffer *buffer);
+extern int binder_alloc_mmap_handler(struct binder_alloc *alloc,
+				     struct vm_area_struct *vma);
+extern void binder_alloc_deferred_release(struct binder_alloc *alloc);
+extern int binder_alloc_get_allocated_count(struct binder_alloc *alloc);
+extern void binder_alloc_print_allocated(struct seq_file *m,
+					 struct binder_alloc *alloc);
+
+/**
+ * binder_alloc_get_free_async_space() - get free space available for async
+ * @alloc:	binder_alloc for this proc
+ *
+ * Return:	the bytes remaining in the address-space for async transactions
+ */
+static inline size_t
+binder_alloc_get_free_async_space(struct binder_alloc *alloc)
+{
+	size_t free_async_space;
+
+	mutex_lock(&alloc->mutex);
+	free_async_space = alloc->free_async_space;
+	mutex_unlock(&alloc->mutex);
+	return free_async_space;
+}
+
+/**
+ * binder_alloc_get_user_buffer_offset() - get offset between kernel/user addrs
+ * @alloc:	binder_alloc for this proc
+ *
+ * Return:	the offset between kernel and user-space addresses to use for
+ * virtual address conversion
+ */
+static inline ptrdiff_t
+binder_alloc_get_user_buffer_offset(struct binder_alloc *alloc)
+{
+	/*
+	 * user_buffer_offset is constant if vma is set and
+	 * undefined if vma is not set. It is possible to
+	 * get here with !alloc->vma if the target process
+	 * is dying while a transaction is being initiated.
+	 * Returning the old value is ok in this case and
+	 * the transaction will fail.
+	 */
+	return alloc->user_buffer_offset;
+}
+
+#endif /* _LINUX_BINDER_ALLOC_H */
+
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 7f20f3d..7967db1 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -23,7 +23,8 @@
 struct binder_buffer;
 struct binder_node;
 struct binder_proc;
-struct binder_ref;
+struct binder_alloc;
+struct binder_ref_data;
 struct binder_thread;
 struct binder_transaction;
 
@@ -146,8 +147,8 @@
 
 TRACE_EVENT(binder_transaction_node_to_ref,
 	TP_PROTO(struct binder_transaction *t, struct binder_node *node,
-		 struct binder_ref *ref),
-	TP_ARGS(t, node, ref),
+		 struct binder_ref_data *rdata),
+	TP_ARGS(t, node, rdata),
 
 	TP_STRUCT__entry(
 		__field(int, debug_id)
@@ -160,8 +161,8 @@
 		__entry->debug_id = t->debug_id;
 		__entry->node_debug_id = node->debug_id;
 		__entry->node_ptr = node->ptr;
-		__entry->ref_debug_id = ref->debug_id;
-		__entry->ref_desc = ref->desc;
+		__entry->ref_debug_id = rdata->debug_id;
+		__entry->ref_desc = rdata->desc;
 	),
 	TP_printk("transaction=%d node=%d src_ptr=0x%016llx ==> dest_ref=%d dest_desc=%d",
 		  __entry->debug_id, __entry->node_debug_id,
@@ -170,8 +171,9 @@
 );
 
 TRACE_EVENT(binder_transaction_ref_to_node,
-	TP_PROTO(struct binder_transaction *t, struct binder_ref *ref),
-	TP_ARGS(t, ref),
+	TP_PROTO(struct binder_transaction *t, struct binder_node *node,
+		 struct binder_ref_data *rdata),
+	TP_ARGS(t, node, rdata),
 
 	TP_STRUCT__entry(
 		__field(int, debug_id)
@@ -182,10 +184,10 @@
 	),
 	TP_fast_assign(
 		__entry->debug_id = t->debug_id;
-		__entry->ref_debug_id = ref->debug_id;
-		__entry->ref_desc = ref->desc;
-		__entry->node_debug_id = ref->node->debug_id;
-		__entry->node_ptr = ref->node->ptr;
+		__entry->ref_debug_id = rdata->debug_id;
+		__entry->ref_desc = rdata->desc;
+		__entry->node_debug_id = node->debug_id;
+		__entry->node_ptr = node->ptr;
 	),
 	TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%016llx",
 		  __entry->debug_id, __entry->node_debug_id,
@@ -194,9 +196,10 @@
 );
 
 TRACE_EVENT(binder_transaction_ref_to_ref,
-	TP_PROTO(struct binder_transaction *t, struct binder_ref *src_ref,
-		 struct binder_ref *dest_ref),
-	TP_ARGS(t, src_ref, dest_ref),
+	TP_PROTO(struct binder_transaction *t, struct binder_node *node,
+		 struct binder_ref_data *src_ref,
+		 struct binder_ref_data *dest_ref),
+	TP_ARGS(t, node, src_ref, dest_ref),
 
 	TP_STRUCT__entry(
 		__field(int, debug_id)
@@ -208,7 +211,7 @@
 	),
 	TP_fast_assign(
 		__entry->debug_id = t->debug_id;
-		__entry->node_debug_id = src_ref->node->debug_id;
+		__entry->node_debug_id = node->debug_id;
 		__entry->src_ref_debug_id = src_ref->debug_id;
 		__entry->src_ref_desc = src_ref->desc;
 		__entry->dest_ref_debug_id = dest_ref->debug_id;
@@ -268,9 +271,9 @@
 	TP_ARGS(buffer));
 
 TRACE_EVENT(binder_update_page_range,
-	TP_PROTO(struct binder_proc *proc, bool allocate,
+	TP_PROTO(struct binder_alloc *alloc, bool allocate,
 		 void *start, void *end),
-	TP_ARGS(proc, allocate, start, end),
+	TP_ARGS(alloc, allocate, start, end),
 	TP_STRUCT__entry(
 		__field(int, proc)
 		__field(bool, allocate)
@@ -278,9 +281,9 @@
 		__field(size_t, size)
 	),
 	TP_fast_assign(
-		__entry->proc = proc->pid;
+		__entry->proc = alloc->pid;
 		__entry->allocate = allocate;
-		__entry->offset = start - proc->buffer;
+		__entry->offset = start - alloc->buffer;
 		__entry->size = end - start;
 	),
 	TP_printk("proc=%d allocate=%d offset=%zu size=%zu",
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b79cb10..b0b77b6 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4138,6 +4138,12 @@
 	 */
 	{ "ST380013AS",		"3.20",		ATA_HORKAGE_MAX_SEC_1024 },
 
+	/*
+	 * These devices time out with higher max sects.
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=121671
+	 */
+	{ "LITEON CX1-JB*-HP",	NULL,		ATA_HORKAGE_MAX_SEC_1024 },
+
 	/* Devices we expect to fail diagnostics */
 
 	/* Devices where NCQ should be avoided */
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 961acc7..91a9e6a 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -606,7 +606,7 @@
 	ata_scsi_port_error_handler(host, ap);
 
 	/* finish or retry handled scmd's and clean up */
-	WARN_ON(host->host_failed || !list_empty(&eh_work_q));
+	WARN_ON(!list_empty(&eh_work_q));
 
 	DPRINTK("EXIT\n");
 }
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index bd74ee5..729f263 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4121,6 +4121,9 @@
 	host->iomap = NULL;
 	hpriv->base = devm_ioremap(&pdev->dev, res->start,
 				   resource_size(res));
+	if (!hpriv->base)
+		return -ENOMEM;
+
 	hpriv->base -= SATAHC0_REG_BASE;
 
 	hpriv->clk = clk_get(&pdev->dev, NULL);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b7d56c5..f18856f 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -836,11 +836,29 @@
 	return NULL;
 }
 
+static inline bool live_in_glue_dir(struct kobject *kobj,
+				    struct device *dev)
+{
+	if (!kobj || !dev->class ||
+	    kobj->kset != &dev->class->p->glue_dirs)
+		return false;
+	return true;
+}
+
+static inline struct kobject *get_glue_dir(struct device *dev)
+{
+	return dev->kobj.parent;
+}
+
+/*
+ * make sure cleaning up dir as the last step, we need to make
+ * sure .release handler of kobject is run with holding the
+ * global lock
+ */
 static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
 {
 	/* see if we live in a "glue" directory */
-	if (!glue_dir || !dev->class ||
-	    glue_dir->kset != &dev->class->p->glue_dirs)
+	if (!live_in_glue_dir(glue_dir, dev))
 		return;
 
 	mutex_lock(&gdp_mutex);
@@ -848,11 +866,6 @@
 	mutex_unlock(&gdp_mutex);
 }
 
-static void cleanup_device_parent(struct device *dev)
-{
-	cleanup_glue_dir(dev, dev->kobj.parent);
-}
-
 static int device_add_class_symlinks(struct device *dev)
 {
 	struct device_node *of_node = dev_of_node(dev);
@@ -1028,6 +1041,7 @@
 	struct kobject *kobj;
 	struct class_interface *class_intf;
 	int error = -EINVAL;
+	struct kobject *glue_dir = NULL;
 
 	dev = get_device(dev);
 	if (!dev)
@@ -1072,8 +1086,10 @@
 	/* first, register with generic layer. */
 	/* we require the name to be set before, and pass NULL */
 	error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
-	if (error)
+	if (error) {
+		glue_dir = get_glue_dir(dev);
 		goto Error;
+	}
 
 	/* notify platform of device entry */
 	if (platform_notify)
@@ -1154,9 +1170,10 @@
 	device_remove_file(dev, &dev_attr_uevent);
  attrError:
 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
+	glue_dir = get_glue_dir(dev);
 	kobject_del(&dev->kobj);
  Error:
-	cleanup_device_parent(dev);
+	cleanup_glue_dir(dev, glue_dir);
 	put_device(parent);
 name_error:
 	kfree(dev->p);
@@ -1232,6 +1249,7 @@
 void device_del(struct device *dev)
 {
 	struct device *parent = dev->parent;
+	struct kobject *glue_dir = NULL;
 	struct class_interface *class_intf;
 
 	/* Notify clients of device removal.  This call must come
@@ -1276,8 +1294,9 @@
 		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 					     BUS_NOTIFY_REMOVED_DEVICE, dev);
 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
-	cleanup_device_parent(dev);
+	glue_dir = get_glue_dir(dev);
 	kobject_del(&dev->kobj);
+	cleanup_glue_dir(dev, glue_dir);
 	put_device(parent);
 }
 EXPORT_SYMBOL_GPL(device_del);
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index d95c597..a00f7b7 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -335,7 +335,7 @@
 		return;
 	}
 
-	unmap_kernel_range((unsigned long)cpu_addr, size);
+	unmap_kernel_range((unsigned long)cpu_addr, PAGE_ALIGN(size));
 	vunmap(cpu_addr);
 }
 #endif
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8524450..ccfd268 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -942,13 +942,14 @@
 		timeout = MAX_JIFFY_OFFSET;
 	}
 
-	retval = wait_for_completion_interruptible_timeout(&buf->completion,
+	timeout = wait_for_completion_interruptible_timeout(&buf->completion,
 			timeout);
-	if (retval == -ERESTARTSYS || !retval) {
+	if (timeout == -ERESTARTSYS || !timeout) {
+		retval = timeout;
 		mutex_lock(&fw_lock);
 		fw_load_abort(fw_priv);
 		mutex_unlock(&fw_lock);
-	} else if (retval > 0) {
+	} else if (timeout > 0) {
 		retval = 0;
 	}
 
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 25425d3..48c0a1d 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -388,30 +388,29 @@
 {
 	struct memory_block *mem = to_memory_block(dev);
 	unsigned long start_pfn, end_pfn;
+	unsigned long valid_start, valid_end;
 	unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
-	struct page *first_page;
 	struct zone *zone;
 
 	start_pfn = section_nr_to_pfn(mem->start_section_nr);
 	end_pfn = start_pfn + nr_pages;
-	first_page = pfn_to_page(start_pfn);
 
 	/* The block contains more than one zone can not be offlined. */
-	if (!test_pages_in_a_zone(start_pfn, end_pfn))
+	if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end))
 		return sprintf(buf, "none\n");
 
-	zone = page_zone(first_page);
+	zone = page_zone(pfn_to_page(valid_start));
 
 	if (zone_idx(zone) == ZONE_MOVABLE - 1) {
 		/*The mem block is the last memoryblock of this zone.*/
-		if (end_pfn == zone_end_pfn(zone))
+		if (valid_end == zone_end_pfn(zone))
 			return sprintf(buf, "%s %s\n",
 					zone->name, (zone + 1)->name);
 	}
 
 	if (zone_idx(zone) == ZONE_MOVABLE) {
 		/*The mem block is the first memoryblock of ZONE_MOVABLE.*/
-		if (start_pfn == zone->zone_start_pfn)
+		if (valid_start == zone->zone_start_pfn)
 			return sprintf(buf, "%s %s\n",
 					zone->name, (zone - 1)->name);
 	}
diff --git a/drivers/base/module.c b/drivers/base/module.c
index db930d3..2a21578 100644
--- a/drivers/base/module.c
+++ b/drivers/base/module.c
@@ -24,10 +24,12 @@
 
 static void module_create_drivers_dir(struct module_kobject *mk)
 {
-	if (!mk || mk->drivers_dir)
-		return;
+	static DEFINE_MUTEX(drivers_dir_mutex);
 
-	mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
+	mutex_lock(&drivers_dir_mutex);
+	if (mk && !mk->drivers_dir)
+		mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
+	mutex_unlock(&drivers_dir_mutex);
 }
 
 void module_add_driver(struct module *mod, struct device_driver *drv)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 176b59f..cb4ad6e 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -96,7 +96,7 @@
 		int ret;
 
 		ret = of_irq_get(dev->dev.of_node, num);
-		if (ret >= 0 || ret == -EPROBE_DEFER)
+		if (ret > 0 || ret == -EPROBE_DEFER)
 			return ret;
 	}
 
@@ -154,7 +154,7 @@
 		int ret;
 
 		ret = of_irq_get_byname(dev->dev.of_node, name);
-		if (ret >= 0 || ret == -EPROBE_DEFER)
+		if (ret > 0 || ret == -EPROBE_DEFER)
 			return ret;
 	}
 
@@ -807,7 +807,7 @@
 				     const char *buf, size_t count)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	char *driver_override, *old = pdev->driver_override, *cp;
+	char *driver_override, *old, *cp;
 
 	if (count > PATH_MAX)
 		return -EINVAL;
@@ -820,12 +820,15 @@
 	if (cp)
 		*cp = '\0';
 
+	device_lock(dev);
+	old = pdev->driver_override;
 	if (strlen(driver_override)) {
 		pdev->driver_override = driver_override;
 	} else {
 		kfree(driver_override);
 		pdev->driver_override = NULL;
 	}
+	device_unlock(dev);
 
 	kfree(old);
 
@@ -836,8 +839,12 @@
 				    struct device_attribute *attr, char *buf)
 {
 	struct platform_device *pdev = to_platform_device(dev);
+	ssize_t len;
 
-	return sprintf(buf, "%s\n", pdev->driver_override);
+	device_lock(dev);
+	len = sprintf(buf, "%s\n", pdev->driver_override);
+	device_unlock(dev);
+	return len;
 }
 static DEVICE_ATTR_RW(driver_override);
 
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 77379f3..6c5bc3f 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1025,6 +1025,8 @@
 	TRACE_DEVICE(dev);
 	TRACE_SUSPEND(0);
 
+	dpm_wait_for_children(dev, async);
+
 	if (async_error)
 		goto Complete;
 
@@ -1036,8 +1038,6 @@
 	if (dev->power.syscore || dev->power.direct_complete)
 		goto Complete;
 
-	dpm_wait_for_children(dev, async);
-
 	if (dev->pm_domain) {
 		info = "noirq power domain ";
 		callback = pm_noirq_op(&dev->pm_domain->ops, state);
@@ -1172,6 +1172,8 @@
 
 	__pm_runtime_disable(dev, false);
 
+	dpm_wait_for_children(dev, async);
+
 	if (async_error)
 		goto Complete;
 
@@ -1183,8 +1185,6 @@
 	if (dev->power.syscore || dev->power.direct_complete)
 		goto Complete;
 
-	dpm_wait_for_children(dev, async);
-
 	if (dev->pm_domain) {
 		info = "late power domain ";
 		callback = pm_late_early_op(&dev->pm_domain->ops, state);
@@ -1265,14 +1265,15 @@
 		error = device_suspend_late(dev);
 
 		mutex_lock(&dpm_list_mtx);
+		if (!list_empty(&dev->power.entry))
+			list_move(&dev->power.entry, &dpm_late_early_list);
+
 		if (error) {
 			pm_dev_err(dev, state, " late", error);
 			dpm_save_failed_dev(dev_name(dev));
 			put_device(dev);
 			break;
 		}
-		if (!list_empty(&dev->power.entry))
-			list_move(&dev->power.entry, &dpm_late_early_list);
 		put_device(dev);
 
 		if (async_error)
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 297beae..297aa5c 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -20,14 +20,22 @@
 extern void pm_runtime_init(struct device *dev);
 extern void pm_runtime_remove(struct device *dev);
 
+#define WAKE_IRQ_DEDICATED_ALLOCATED	BIT(0)
+#define WAKE_IRQ_DEDICATED_MANAGED	BIT(1)
+#define WAKE_IRQ_DEDICATED_MASK		(WAKE_IRQ_DEDICATED_ALLOCATED | \
+					 WAKE_IRQ_DEDICATED_MANAGED)
+
 struct wake_irq {
 	struct device *dev;
+	unsigned int status;
 	int irq;
-	bool dedicated_irq:1;
 };
 
 extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
 extern void dev_pm_disarm_wake_irq(struct wake_irq *wirq);
+extern void dev_pm_enable_wake_irq_check(struct device *dev,
+					 bool can_change_status);
+extern void dev_pm_disable_wake_irq_check(struct device *dev);
 
 #ifdef CONFIG_PM_SLEEP
 
@@ -102,6 +110,15 @@
 {
 }
 
+static inline void dev_pm_enable_wake_irq_check(struct device *dev,
+						bool can_change_status)
+{
+}
+
+static inline void dev_pm_disable_wake_irq_check(struct device *dev)
+{
+}
+
 #endif
 
 #ifdef CONFIG_PM_SLEEP
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index e1a10a0..3a20dc5 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -515,7 +515,7 @@
 
 	callback = RPM_GET_CALLBACK(dev, runtime_suspend);
 
-	dev_pm_enable_wake_irq(dev);
+	dev_pm_enable_wake_irq_check(dev, true);
 	retval = rpm_callback(callback, dev);
 	if (retval)
 		goto fail;
@@ -554,7 +554,7 @@
 	return retval;
 
  fail:
-	dev_pm_disable_wake_irq(dev);
+	dev_pm_disable_wake_irq_check(dev);
 	__update_runtime_status(dev, RPM_ACTIVE);
 	dev->power.deferred_resume = false;
 	wake_up_all(&dev->power.wait_queue);
@@ -737,12 +737,12 @@
 
 	callback = RPM_GET_CALLBACK(dev, runtime_resume);
 
-	dev_pm_disable_wake_irq(dev);
+	dev_pm_disable_wake_irq_check(dev);
 	retval = rpm_callback(callback, dev);
 	if (retval) {
 		__update_runtime_status(dev, RPM_SUSPENDED);
 		pm_runtime_cancel_pending(dev);
-		dev_pm_enable_wake_irq(dev);
+		dev_pm_enable_wake_irq_check(dev, false);
 	} else {
  no_callback:
 		__update_runtime_status(dev, RPM_ACTIVE);
@@ -889,13 +889,13 @@
 	unsigned long flags;
 	int retval;
 
-	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
-
 	if (rpmflags & RPM_GET_PUT) {
 		if (!atomic_dec_and_test(&dev->power.usage_count))
 			return 0;
 	}
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	spin_lock_irqsave(&dev->power.lock, flags);
 	retval = rpm_idle(dev, rpmflags);
 	spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -921,13 +921,13 @@
 	unsigned long flags;
 	int retval;
 
-	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
-
 	if (rpmflags & RPM_GET_PUT) {
 		if (!atomic_dec_and_test(&dev->power.usage_count))
 			return 0;
 	}
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	spin_lock_irqsave(&dev->power.lock, flags);
 	retval = rpm_suspend(dev, rpmflags);
 	spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -952,7 +952,8 @@
 	unsigned long flags;
 	int retval;
 
-	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&
+			dev->power.runtime_status != RPM_ACTIVE);
 
 	if (rpmflags & RPM_GET_PUT)
 		atomic_inc(&dev->power.usage_count);
@@ -1468,11 +1469,16 @@
 		goto out;
 	}
 
-	ret = callback(dev);
+	ret = pm_runtime_set_active(dev);
 	if (ret)
 		goto out;
 
-	pm_runtime_set_active(dev);
+	ret = callback(dev);
+	if (ret) {
+		pm_runtime_set_suspended(dev);
+		goto out;
+	}
+
 	pm_runtime_mark_last_busy(dev);
 out:
 	pm_runtime_enable(dev);
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index 0d77cd6..404d94c 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -110,8 +110,10 @@
 	dev->power.wakeirq = NULL;
 	spin_unlock_irqrestore(&dev->power.lock, flags);
 
-	if (wirq->dedicated_irq)
+	if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED) {
 		free_irq(wirq->irq, wirq);
+		wirq->status &= ~WAKE_IRQ_DEDICATED_MASK;
+	}
 	kfree(wirq);
 }
 EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq);
@@ -179,7 +181,6 @@
 
 	wirq->dev = dev;
 	wirq->irq = irq;
-	wirq->dedicated_irq = true;
 	irq_set_status_flags(irq, IRQ_NOAUTOEN);
 
 	/*
@@ -195,6 +196,8 @@
 	if (err)
 		goto err_free_irq;
 
+	wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED;
+
 	return err;
 
 err_free_irq:
@@ -210,9 +213,9 @@
  * dev_pm_enable_wake_irq - Enable device wake-up interrupt
  * @dev: Device
  *
- * Called from the bus code or the device driver for
- * runtime_suspend() to enable the wake-up interrupt while
- * the device is running.
+ * Optionally called from the bus code or the device driver for
+ * runtime_resume() to override the PM runtime core managed wake-up
+ * interrupt handling to enable the wake-up interrupt.
  *
  * Note that for runtime_suspend()) the wake-up interrupts
  * should be unconditionally enabled unlike for suspend()
@@ -222,7 +225,7 @@
 {
 	struct wake_irq *wirq = dev->power.wakeirq;
 
-	if (wirq && wirq->dedicated_irq)
+	if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
 		enable_irq(wirq->irq);
 }
 EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq);
@@ -231,20 +234,73 @@
  * dev_pm_disable_wake_irq - Disable device wake-up interrupt
  * @dev: Device
  *
- * Called from the bus code or the device driver for
- * runtime_resume() to disable the wake-up interrupt while
- * the device is running.
+ * Optionally called from the bus code or the device driver for
+ * runtime_suspend() to override the PM runtime core managed wake-up
+ * interrupt handling to disable the wake-up interrupt.
  */
 void dev_pm_disable_wake_irq(struct device *dev)
 {
 	struct wake_irq *wirq = dev->power.wakeirq;
 
-	if (wirq && wirq->dedicated_irq)
+	if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
 		disable_irq_nosync(wirq->irq);
 }
 EXPORT_SYMBOL_GPL(dev_pm_disable_wake_irq);
 
 /**
+ * dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt
+ * @dev: Device
+ * @can_change_status: Can change wake-up interrupt status
+ *
+ * Enables wakeirq conditionally. We need to enable wake-up interrupt
+ * lazily on the first rpm_suspend(). This is needed as the consumer device
+ * starts in RPM_SUSPENDED state, and the the first pm_runtime_get() would
+ * otherwise try to disable already disabled wakeirq. The wake-up interrupt
+ * starts disabled with IRQ_NOAUTOEN set.
+ *
+ * Should be only called from rpm_suspend() and rpm_resume() path.
+ * Caller must hold &dev->power.lock to change wirq->status
+ */
+void dev_pm_enable_wake_irq_check(struct device *dev,
+				  bool can_change_status)
+{
+	struct wake_irq *wirq = dev->power.wakeirq;
+
+	if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK)))
+		return;
+
+	if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) {
+		goto enable;
+	} else if (can_change_status) {
+		wirq->status |= WAKE_IRQ_DEDICATED_MANAGED;
+		goto enable;
+	}
+
+	return;
+
+enable:
+	enable_irq(wirq->irq);
+}
+
+/**
+ * dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt
+ * @dev: Device
+ *
+ * Disables wake-up interrupt conditionally based on status.
+ * Should be only called from rpm_suspend() and rpm_resume() path.
+ */
+void dev_pm_disable_wake_irq_check(struct device *dev)
+{
+	struct wake_irq *wirq = dev->power.wakeirq;
+
+	if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK)))
+		return;
+
+	if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
+		disable_irq_nosync(wirq->irq);
+}
+
+/**
  * dev_pm_arm_wake_irq - Arm device wake-up
  * @wirq: Device wake-up interrupt
  *
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 09c07f5..0e49410 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -1042,7 +1042,7 @@
 		active_time = ktime_set(0, 0);
 	}
 
-	seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n",
+	seq_printf(m, "%-32s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n",
 		   ws->name, active_count, ws->event_count,
 		   ws->wakeup_count, ws->expire_count,
 		   ktime_to_ms(active_time), ktime_to_ms(total_time),
@@ -1062,7 +1062,7 @@
 {
 	struct wakeup_source *ws;
 
-	seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
+	seq_puts(m, "name\t\t\t\t\tactive_count\tevent_count\twakeup_count\t"
 		"expire_count\tactive_since\ttotal_time\tmax_time\t"
 		"last_change\tprevent_suspend_time\n");
 
diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c
index 7e58f65..4a36e41 100644
--- a/drivers/base/regmap/regmap-spmi.c
+++ b/drivers/base/regmap/regmap-spmi.c
@@ -142,7 +142,7 @@
 	while (val_size) {
 		len = min_t(size_t, val_size, 8);
 
-		err = spmi_ext_register_readl(context, addr, val, val_size);
+		err = spmi_ext_register_readl(context, addr, val, len);
 		if (err)
 			goto err_out;
 
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 38f1567..71df8f2 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -8,8 +8,6 @@
 #include <linux/bcma/bcma.h>
 #include <linux/delay.h>
 
-#define BCMA_CORE_SIZE		0x1000
-
 #define bcma_err(bus, fmt, ...) \
 	pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
 #define bcma_warn(bus, fmt, ...) \
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 59d8d0d..327f9e3 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -640,8 +640,11 @@
 					       drv);
 	int err = 0;
 
+	get_device(dev);
 	if (adrv->probe)
 		err = adrv->probe(core);
+	if (err)
+		put_device(dev);
 
 	return err;
 }
@@ -654,6 +657,7 @@
 
 	if (adrv->remove)
 		adrv->remove(core);
+	put_device(dev);
 
 	return 0;
 }
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 9462d27..8bdc34d 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -479,8 +479,14 @@
  * this masks out the remaining bits.
  * Returns the number of bits cleared.
  */
+#ifndef BITS_PER_PAGE
 #define BITS_PER_PAGE		(1UL << (PAGE_SHIFT + 3))
 #define BITS_PER_PAGE_MASK	(BITS_PER_PAGE - 1)
+#else
+# if BITS_PER_PAGE != (1UL << (PAGE_SHIFT + 3))
+#  error "ambiguous BITS_PER_PAGE"
+# endif
+#endif
 #define BITS_PER_LONG_MASK	(BITS_PER_LONG - 1)
 static int bm_clear_surplus(struct drbd_bitmap *b)
 {
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 74d97f4..1d58854 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1802,7 +1802,7 @@
  * do we need to block DRBD_SIG if sock == &meta.socket ??
  * otherwise wake_asender() might interrupt some send_*Ack !
  */
-		rv = kernel_sendmsg(sock, &msg, &iov, 1, size);
+		rv = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
 		if (rv == -EAGAIN) {
 			if (we_should_drop_the_connection(connection, sock))
 				break;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 80cf8ad..cec36d5 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1108,9 +1108,12 @@
 	if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE)
 		return -EINVAL;
 
+	/* I/O need to be drained during transfer transition */
+	blk_mq_freeze_queue(lo->lo_queue);
+
 	err = loop_release_xfer(lo);
 	if (err)
-		return err;
+		goto exit;
 
 	if (info->lo_encrypt_type) {
 		unsigned int type = info->lo_encrypt_type;
@@ -1125,12 +1128,14 @@
 
 	err = loop_init_xfer(lo, xfer, info);
 	if (err)
-		return err;
+		goto exit;
 
 	if (lo->lo_offset != info->lo_offset ||
 	    lo->lo_sizelimit != info->lo_sizelimit)
-		if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit))
-			return -EFBIG;
+		if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
+			err = -EFBIG;
+			goto exit;
+		}
 
 	loop_config_discard(lo);
 
@@ -1148,13 +1153,6 @@
 	     (info->lo_flags & LO_FLAGS_AUTOCLEAR))
 		lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
 
-	if ((info->lo_flags & LO_FLAGS_PARTSCAN) &&
-	     !(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
-		lo->lo_flags |= LO_FLAGS_PARTSCAN;
-		lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
-		loop_reread_partitions(lo, lo->lo_device);
-	}
-
 	lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
 	lo->lo_init[0] = info->lo_init[0];
 	lo->lo_init[1] = info->lo_init[1];
@@ -1167,7 +1165,17 @@
 	/* update dio if lo_offset or transfer is changed */
 	__loop_update_dio(lo, lo->use_dio);
 
-	return 0;
+ exit:
+	blk_mq_unfreeze_queue(lo->lo_queue);
+
+	if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) &&
+	     !(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
+		lo->lo_flags |= LO_FLAGS_PARTSCAN;
+		lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
+		loop_reread_partitions(lo, lo->lo_device);
+	}
+
+	return err;
 }
 
 static int
@@ -1657,7 +1665,7 @@
 	blk_mq_start_request(bd->rq);
 
 	if (lo->lo_state != Lo_bound)
-		return -EIO;
+		return BLK_MQ_RQ_QUEUE_ERROR;
 
 	if (lo->use_dio && !(cmd->rq->cmd_flags & (REQ_FLUSH |
 					REQ_DISCARD)))
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 370c2f7..62a93b6 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -574,13 +574,13 @@
 
 	if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) {
 		bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
-		clear_page(mem);
+		memset(mem, 0, PAGE_SIZE);
 		return 0;
 	}
 
 	cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO);
 	if (size == PAGE_SIZE)
-		copy_page(mem, cmem);
+		memcpy(mem, cmem, PAGE_SIZE);
 	else
 		ret = zcomp_decompress(zram->comp, cmem, size, mem);
 	zs_unmap_object(meta->mem_pool, handle);
@@ -738,7 +738,7 @@
 
 	if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) {
 		src = kmap_atomic(page);
-		copy_page(cmem, src);
+		memcpy(cmem, src, PAGE_SIZE);
 		kunmap_atomic(src);
 	} else {
 		memcpy(cmem, src, clen);
@@ -1368,7 +1368,8 @@
 	zram = idr_find(&zram_index_idr, dev_id);
 	if (zram) {
 		ret = zram_remove(zram);
-		idr_remove(&zram_index_idr, dev_id);
+		if (!ret)
+			idr_remove(&zram_index_idr, dev_id);
 	} else {
 		ret = -ENODEV;
 	}
@@ -1377,8 +1378,14 @@
 	return ret ? ret : count;
 }
 
+/*
+ * NOTE: hot_add attribute is not the usual read-only sysfs attribute. In a
+ * sense that reading from this file does alter the state of your system -- it
+ * creates a new un-initialized zram device and returns back this device's
+ * device_id (or an error code if it fails to create a new device).
+ */
 static struct class_attribute zram_control_class_attrs[] = {
-	__ATTR_RO(hot_add),
+	__ATTR(hot_add, 0400, hot_add_show, NULL),
 	__ATTR_WO(hot_remove),
 	__ATTR_NULL,
 };
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 0beaa52..5df8e12 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -94,6 +94,7 @@
 	{ USB_DEVICE(0x04CA, 0x300f) },
 	{ USB_DEVICE(0x04CA, 0x3010) },
 	{ USB_DEVICE(0x04CA, 0x3014) },
+	{ USB_DEVICE(0x04CA, 0x3018) },
 	{ USB_DEVICE(0x0930, 0x0219) },
 	{ USB_DEVICE(0x0930, 0x021c) },
 	{ USB_DEVICE(0x0930, 0x0220) },
@@ -160,6 +161,7 @@
 	{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 7910759..cd6b141 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -208,6 +208,7 @@
 	{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
@@ -2056,12 +2057,13 @@
 		return -EINVAL;
 	}
 
-	/* At the moment only the hardware variant iBT 3.0 (LnP/SfP) is
-	 * supported by this firmware loading method. This check has been
-	 * put in place to ensure correct forward compatibility options
-	 * when newer hardware variants come along.
+	/* At the moment the iBT 3.0 hardware variants 0x0b (LnP/SfP)
+	 * and 0x0c (WsP) are supported by this firmware loading method.
+	 *
+	 * This check has been put in place to ensure correct forward
+	 * compatibility options when newer hardware variants come along.
 	 */
-	if (ver->hw_variant != 0x0b) {
+	if (ver->hw_variant != 0x0b && ver->hw_variant != 0x0c) {
 		BT_ERR("%s: Unsupported Intel hardware variant (%u)",
 		       hdev->name, ver->hw_variant);
 		kfree_skb(skb);
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index cb852cc..f9b569e 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -287,6 +287,9 @@
 
 	hu->priv = bcm;
 
+	if (!hu->tty->dev)
+		goto out;
+
 	mutex_lock(&bcm_device_lock);
 	list_for_each(p, &bcm_device_list) {
 		struct bcm_device *dev = list_entry(p, struct bcm_device, list);
@@ -307,7 +310,7 @@
 	}
 
 	mutex_unlock(&bcm_device_lock);
-
+out:
 	return 0;
 }
 
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index 4a414a5..0c63fce 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -307,6 +307,9 @@
 	struct list_head *p;
 	int err = -ENODEV;
 
+	if (!hu->tty->dev)
+		return err;
+
 	mutex_lock(&intel_device_list_lock);
 
 	list_for_each(p, &intel_device_list) {
@@ -379,6 +382,9 @@
 	struct intel_data *intel = container_of(work, struct intel_data,
 						busy_work);
 
+	if (!intel->hu->tty->dev)
+		return;
+
 	/* Link is busy, delay the suspend */
 	mutex_lock(&intel_device_list_lock);
 	list_for_each(p, &intel_device_list) {
@@ -913,6 +919,8 @@
 	list_for_each(p, &intel_device_list) {
 		struct intel_device *dev = list_entry(p, struct intel_device,
 						      list);
+		if (!hu->tty->dev)
+			break;
 		if (hu->tty->dev->parent == dev->pdev->dev.parent) {
 			if (device_may_wakeup(&dev->pdev->dev))
 				idev = dev;
@@ -1094,6 +1102,9 @@
 
 	BT_DBG("hu %p skb %p", hu, skb);
 
+	if (!hu->tty->dev)
+		goto out_enqueue;
+
 	/* Be sure our controller is resumed and potential LPM transaction
 	 * completed before enqueuing any packet.
 	 */
@@ -1110,7 +1121,7 @@
 		}
 	}
 	mutex_unlock(&intel_device_list_lock);
-
+out_enqueue:
 	skb_queue_tail(&intel->txq, skb);
 
 	return 0;
@@ -1234,8 +1245,7 @@
 
 	idev->pdev = pdev;
 
-	idev->reset = devm_gpiod_get_optional(&pdev->dev, "reset",
-					      GPIOD_OUT_LOW);
+	idev->reset = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(idev->reset)) {
 		dev_err(&pdev->dev, "Unable to retrieve gpio\n");
 		return PTR_ERR(idev->reset);
@@ -1247,8 +1257,7 @@
 
 		dev_err(&pdev->dev, "No IRQ, falling back to gpio-irq\n");
 
-		host_wake = devm_gpiod_get_optional(&pdev->dev, "host-wake",
-						    GPIOD_IN);
+		host_wake = devm_gpiod_get(&pdev->dev, "host-wake", GPIOD_IN);
 		if (IS_ERR(host_wake)) {
 			dev_err(&pdev->dev, "Unable to retrieve IRQ\n");
 			goto no_irq;
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index ed888e3..597b2d1 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -50,6 +50,7 @@
 	wait_queue_head_t read_wait;
 	struct sk_buff_head readq;
 
+	struct mutex open_mutex;
 	struct delayed_work open_timeout;
 };
 
@@ -87,12 +88,15 @@
 	return 0;
 }
 
-static int vhci_create_device(struct vhci_data *data, __u8 opcode)
+static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
 {
 	struct hci_dev *hdev;
 	struct sk_buff *skb;
 	__u8 dev_type;
 
+	if (data->hdev)
+		return -EBADFD;
+
 	/* bits 0-1 are dev_type (BR/EDR or AMP) */
 	dev_type = opcode & 0x03;
 
@@ -151,6 +155,17 @@
 	return 0;
 }
 
+static int vhci_create_device(struct vhci_data *data, __u8 opcode)
+{
+	int err;
+
+	mutex_lock(&data->open_mutex);
+	err = __vhci_create_device(data, opcode);
+	mutex_unlock(&data->open_mutex);
+
+	return err;
+}
+
 static inline ssize_t vhci_get_user(struct vhci_data *data,
 				    struct iov_iter *from)
 {
@@ -189,11 +204,6 @@
 		break;
 
 	case HCI_VENDOR_PKT:
-		if (data->hdev) {
-			kfree_skb(skb);
-			return -EBADFD;
-		}
-
 		cancel_delayed_work_sync(&data->open_timeout);
 
 		opcode = *((__u8 *) skb->data);
@@ -320,6 +330,7 @@
 	skb_queue_head_init(&data->readq);
 	init_waitqueue_head(&data->read_wait);
 
+	mutex_init(&data->open_mutex);
 	INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);
 
 	file->private_data = data;
@@ -333,15 +344,18 @@
 static int vhci_release(struct inode *inode, struct file *file)
 {
 	struct vhci_data *data = file->private_data;
-	struct hci_dev *hdev = data->hdev;
+	struct hci_dev *hdev;
 
 	cancel_delayed_work_sync(&data->open_timeout);
 
+	hdev = data->hdev;
+
 	if (hdev) {
 		hci_unregister_dev(hdev);
 		hci_free_dev(hdev);
 	}
 
+	skb_queue_purge(&data->readq);
 	file->private_data = NULL;
 	kfree(data);
 
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
index 7082c72..0f54cb7 100644
--- a/drivers/bus/arm-ccn.c
+++ b/drivers/bus/arm-ccn.c
@@ -187,6 +187,7 @@
 	struct arm_ccn_component *xp;
 
 	struct arm_ccn_dt dt;
+	int mn_id;
 };
 
 
@@ -326,6 +327,7 @@
 static ssize_t arm_ccn_pmu_event_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
+	struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
 	struct arm_ccn_pmu_event *event = container_of(attr,
 			struct arm_ccn_pmu_event, attr);
 	ssize_t res;
@@ -352,6 +354,9 @@
 			res += snprintf(buf + res, PAGE_SIZE - res,
 					",cmp_l=?,cmp_h=?,mask=?");
 		break;
+	case CCN_TYPE_MN:
+		res += snprintf(buf + res, PAGE_SIZE - res, ",node=%d", ccn->mn_id);
+		break;
 	default:
 		res += snprintf(buf + res, PAGE_SIZE - res, ",node=?");
 		break;
@@ -381,9 +386,9 @@
 }
 
 static struct arm_ccn_pmu_event arm_ccn_pmu_events[] = {
-	CCN_EVENT_MN(eobarrier, "dir=0,vc=0,cmp_h=0x1c00", CCN_IDX_MASK_OPCODE),
-	CCN_EVENT_MN(ecbarrier, "dir=0,vc=0,cmp_h=0x1e00", CCN_IDX_MASK_OPCODE),
-	CCN_EVENT_MN(dvmop, "dir=0,vc=0,cmp_h=0x2800", CCN_IDX_MASK_OPCODE),
+	CCN_EVENT_MN(eobarrier, "dir=1,vc=0,cmp_h=0x1c00", CCN_IDX_MASK_OPCODE),
+	CCN_EVENT_MN(ecbarrier, "dir=1,vc=0,cmp_h=0x1e00", CCN_IDX_MASK_OPCODE),
+	CCN_EVENT_MN(dvmop, "dir=1,vc=0,cmp_h=0x2800", CCN_IDX_MASK_OPCODE),
 	CCN_EVENT_HNI(txdatflits, "dir=1,vc=3", CCN_IDX_MASK_ANY),
 	CCN_EVENT_HNI(rxdatflits, "dir=0,vc=3", CCN_IDX_MASK_ANY),
 	CCN_EVENT_HNI(txreqflits, "dir=1,vc=0", CCN_IDX_MASK_ANY),
@@ -757,6 +762,12 @@
 
 	/* Validate node/xp vs topology */
 	switch (type) {
+	case CCN_TYPE_MN:
+		if (node_xp != ccn->mn_id) {
+			dev_warn(ccn->dev, "Invalid MN ID %d!\n", node_xp);
+			return -EINVAL;
+		}
+		break;
 	case CCN_TYPE_XP:
 		if (node_xp >= ccn->num_xps) {
 			dev_warn(ccn->dev, "Invalid XP ID %d!\n", node_xp);
@@ -884,6 +895,10 @@
 	struct arm_ccn_component *xp;
 	u32 val, dt_cfg;
 
+	/* Nothing to do for cycle counter */
+	if (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER)
+		return;
+
 	if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP)
 		xp = &ccn->xp[CCN_CONFIG_XP(event->attr.config)];
 	else
@@ -986,7 +1001,7 @@
 
 	/* Comparison values */
 	writel(cmp_l & 0xffffffff, source->base + CCN_XP_DT_CMP_VAL_L(wp));
-	writel((cmp_l >> 32) & 0xefffffff,
+	writel((cmp_l >> 32) & 0x7fffffff,
 			source->base + CCN_XP_DT_CMP_VAL_L(wp) + 4);
 	writel(cmp_h & 0xffffffff, source->base + CCN_XP_DT_CMP_VAL_H(wp));
 	writel((cmp_h >> 32) & 0x0fffffff,
@@ -994,7 +1009,7 @@
 
 	/* Mask */
 	writel(mask_l & 0xffffffff, source->base + CCN_XP_DT_CMP_MASK_L(wp));
-	writel((mask_l >> 32) & 0xefffffff,
+	writel((mask_l >> 32) & 0x7fffffff,
 			source->base + CCN_XP_DT_CMP_MASK_L(wp) + 4);
 	writel(mask_h & 0xffffffff, source->base + CCN_XP_DT_CMP_MASK_H(wp));
 	writel((mask_h >> 32) & 0x0fffffff,
@@ -1368,6 +1383,8 @@
 
 	switch (type) {
 	case CCN_TYPE_MN:
+		ccn->mn_id = id;
+		return 0;
 	case CCN_TYPE_DT:
 		return 0;
 	case CCN_TYPE_XP:
diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c
index 6575c0f..27ea64f 100644
--- a/drivers/bus/vexpress-config.c
+++ b/drivers/bus/vexpress-config.c
@@ -171,6 +171,7 @@
 {
 	struct device_node *bridge;
 	struct device *parent;
+	int ret;
 
 	bridge = of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
 	if (!bridge)
@@ -181,7 +182,11 @@
 	if (WARN_ON(!parent))
 		return -ENODEV;
 
-	return of_platform_populate(node, NULL, NULL, parent);
+	ret = of_platform_populate(node, NULL, NULL, parent);
+
+	put_device(parent);
+
+	return ret;
 }
 
 static int __init vexpress_config_init(void)
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index a043107..3143db5 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -583,10 +583,12 @@
 	  controlling the behavior of this hardware.
 
 config DEVPORT
-	bool
-	depends on !M68K
+	bool "/dev/port character device"
 	depends on ISA || PCI
 	default y
+	help
+	  Say Y here if you want to support the /dev/port device. The /dev/port
+	  device is similar to /dev/mem, but for I/O ports.
 
 source "drivers/s390/char/Kconfig"
 
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 6f497aa..cf25020 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -84,14 +84,14 @@
 
 static void add_early_randomness(struct hwrng *rng)
 {
-	unsigned char bytes[16];
 	int bytes_read;
+	size_t size = min_t(size_t, 16, rng_buffer_size());
 
 	mutex_lock(&reading_mutex);
-	bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
+	bytes_read = rng_get_data(rng, rng_buffer, size, 1);
 	mutex_unlock(&reading_mutex);
 	if (bytes_read > 0)
-		add_device_randomness(bytes, bytes_read);
+		add_device_randomness(rng_buffer, bytes_read);
 }
 
 static inline void cleanup_rng(struct kref *kref)
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
index 30cf462..7845a38 100644
--- a/drivers/char/hw_random/exynos-rng.c
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -89,6 +89,7 @@
 						struct exynos_rng, rng);
 	u32 *data = buf;
 	int retry = 100;
+	int ret = 4;
 
 	pm_runtime_get_sync(exynos_rng->dev);
 
@@ -97,23 +98,27 @@
 	while (!(exynos_rng_readl(exynos_rng,
 			EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE) && --retry)
 		cpu_relax();
-	if (!retry)
-		return -ETIMEDOUT;
+	if (!retry) {
+		ret = -ETIMEDOUT;
+		goto out;
+	}
 
 	exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET);
 
 	*data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET);
 
+out:
 	pm_runtime_mark_last_busy(exynos_rng->dev);
 	pm_runtime_put_sync_autosuspend(exynos_rng->dev);
 
-	return 4;
+	return ret;
 }
 
 static int exynos_rng_probe(struct platform_device *pdev)
 {
 	struct exynos_rng *exynos_rng;
 	struct resource *res;
+	int ret;
 
 	exynos_rng = devm_kzalloc(&pdev->dev, sizeof(struct exynos_rng),
 					GFP_KERNEL);
@@ -141,7 +146,13 @@
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
-	return devm_hwrng_register(&pdev->dev, &exynos_rng->rng);
+	ret = devm_hwrng_register(&pdev->dev, &exynos_rng->rng);
+	if (ret) {
+		pm_runtime_dont_use_autosuspend(&pdev->dev);
+		pm_runtime_disable(&pdev->dev);
+	}
+
+	return ret;
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 8a1432e..f5c26a5 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -384,7 +384,12 @@
 	}
 
 	pm_runtime_enable(&pdev->dev);
-	pm_runtime_get_sync(&pdev->dev);
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to runtime_get device: %d\n", ret);
+		pm_runtime_put_noidle(&pdev->dev);
+		goto err_ioremap;
+	}
 
 	ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) :
 				get_omap_rng_device_details(priv);
@@ -435,8 +440,15 @@
 static int __maybe_unused omap_rng_resume(struct device *dev)
 {
 	struct omap_rng_dev *priv = dev_get_drvdata(dev);
+	int ret;
 
-	pm_runtime_get_sync(dev);
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		dev_err(dev, "Failed to runtime_get device: %d\n", ret);
+		pm_runtime_put_noidle(dev);
+		return ret;
+	}
+
 	priv->pdata->init(priv);
 
 	return 0;
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index e3536da..a084a47 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3819,6 +3819,7 @@
 	while (!list_empty(&intf->waiting_rcv_msgs)) {
 		smi_msg = list_entry(intf->waiting_rcv_msgs.next,
 				     struct ipmi_smi_msg, link);
+		list_del(&smi_msg->link);
 		if (!run_to_completion)
 			spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock,
 					       flags);
@@ -3828,11 +3829,14 @@
 		if (rv > 0) {
 			/*
 			 * To preserve message order, quit if we
-			 * can't handle a message.
+			 * can't handle a message.  Add the message
+			 * back at the head, this is safe because this
+			 * tasklet is the only thing that pulls the
+			 * messages.
 			 */
+			list_add(&smi_msg->link, &intf->waiting_rcv_msgs);
 			break;
 		} else {
-			list_del(&smi_msg->link);
 			if (rv == 0)
 				/* Message handled */
 				ipmi_free_smi_msg(smi_msg);
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 90e6246..0d83cfb 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -888,6 +888,7 @@
 		 * for details on the intricacies of this.
 		 */
 		int left;
+		unsigned char *data_to_send;
 
 		ssif_inc_stat(ssif_info, sent_messages_parts);
 
@@ -896,6 +897,7 @@
 			left = 32;
 		/* Length byte. */
 		ssif_info->multi_data[ssif_info->multi_pos] = left;
+		data_to_send = ssif_info->multi_data + ssif_info->multi_pos;
 		ssif_info->multi_pos += left;
 		if (left < 32)
 			/*
@@ -909,7 +911,7 @@
 		rv = ssif_i2c_send(ssif_info, msg_written_handler,
 				  I2C_SMBUS_WRITE,
 				  SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE,
-				  ssif_info->multi_data + ssif_info->multi_pos,
+				  data_to_send,
 				  I2C_SMBUS_BLOCK_DATA);
 		if (rv < 0) {
 			/* request failed, just return the error. */
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index c4094c4..34ef474 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -859,7 +859,11 @@
 	} else if (!strcmp(str, "auto")) {
 		parport_nr[0] = LP_PARPORT_AUTO;
 	} else if (!strcmp(str, "none")) {
-		parport_nr[parport_ptr++] = LP_PARPORT_NONE;
+		if (parport_ptr < LP_NO)
+			parport_nr[parport_ptr++] = LP_PARPORT_NONE;
+		else
+			printk(KERN_INFO "lp: too many ports, %s ignored.\n",
+			       str);
 	} else if (!strcmp(str, "reset")) {
 		reset = 1;
 	}
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 6b1721f..2898d19 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -59,6 +59,10 @@
 #endif
 
 #ifdef CONFIG_STRICT_DEVMEM
+static inline int page_is_allowed(unsigned long pfn)
+{
+	return devmem_is_allowed(pfn);
+}
 static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 {
 	u64 from = ((u64)pfn) << PAGE_SHIFT;
@@ -78,6 +82,10 @@
 	return 1;
 }
 #else
+static inline int page_is_allowed(unsigned long pfn)
+{
+	return 1;
+}
 static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 {
 	return 1;
@@ -125,23 +133,31 @@
 
 	while (count > 0) {
 		unsigned long remaining;
+		int allowed;
 
 		sz = size_inside_page(p, count);
 
-		if (!range_is_allowed(p >> PAGE_SHIFT, count))
+		allowed = page_is_allowed(p >> PAGE_SHIFT);
+		if (!allowed)
 			return -EPERM;
+		if (allowed == 2) {
+			/* Show zeros for restricted memory. */
+			remaining = clear_user(buf, sz);
+		} else {
+			/*
+			 * On ia64 if a page has been mapped somewhere as
+			 * uncached, then it must also be accessed uncached
+			 * by the kernel or data corruption may occur.
+			 */
+			ptr = xlate_dev_mem_ptr(p);
+			if (!ptr)
+				return -EFAULT;
 
-		/*
-		 * On ia64 if a page has been mapped somewhere as uncached, then
-		 * it must also be accessed uncached by the kernel or data
-		 * corruption may occur.
-		 */
-		ptr = xlate_dev_mem_ptr(p);
-		if (!ptr)
-			return -EFAULT;
+			remaining = copy_to_user(buf, ptr, sz);
 
-		remaining = copy_to_user(buf, ptr, sz);
-		unxlate_dev_mem_ptr(p, ptr);
+			unxlate_dev_mem_ptr(p, ptr);
+		}
+
 		if (remaining)
 			return -EFAULT;
 
@@ -184,30 +200,36 @@
 #endif
 
 	while (count > 0) {
+		int allowed;
+
 		sz = size_inside_page(p, count);
 
-		if (!range_is_allowed(p >> PAGE_SHIFT, sz))
+		allowed = page_is_allowed(p >> PAGE_SHIFT);
+		if (!allowed)
 			return -EPERM;
 
-		/*
-		 * On ia64 if a page has been mapped somewhere as uncached, then
-		 * it must also be accessed uncached by the kernel or data
-		 * corruption may occur.
-		 */
-		ptr = xlate_dev_mem_ptr(p);
-		if (!ptr) {
-			if (written)
-				break;
-			return -EFAULT;
-		}
+		/* Skip actual writing when a page is marked as restricted. */
+		if (allowed == 1) {
+			/*
+			 * On ia64 if a page has been mapped somewhere as
+			 * uncached, then it must also be accessed uncached
+			 * by the kernel or data corruption may occur.
+			 */
+			ptr = xlate_dev_mem_ptr(p);
+			if (!ptr) {
+				if (written)
+					break;
+				return -EFAULT;
+			}
 
-		copied = copy_from_user(ptr, buf, sz);
-		unxlate_dev_mem_ptr(p, ptr);
-		if (copied) {
-			written += sz - copied;
-			if (written)
-				break;
-			return -EFAULT;
+			copied = copy_from_user(ptr, buf, sz);
+			unxlate_dev_mem_ptr(p, ptr);
+			if (copied) {
+				written += sz - copied;
+				if (written)
+					break;
+				return -EFAULT;
+			}
 		}
 
 		buf += sz;
@@ -321,6 +343,11 @@
 static int mmap_mem(struct file *file, struct vm_area_struct *vma)
 {
 	size_t size = vma->vm_end - vma->vm_start;
+	phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
+
+	/* It's illegal to wrap around the end of the physical address space. */
+	if (offset + (phys_addr_t)size - 1 < offset)
+		return -EINVAL;
 
 	if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
 		return -EINVAL;
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index fc061f7..a7de8ae 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -374,7 +374,7 @@
 
 	rc = write_sync_reg(SCR_HOST_TO_READER_START, dev);
 	if (rc <= 0) {
-		DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
+		DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
 		DEBUGP(2, dev, "<- cm4040_write (failed)\n");
 		if (rc == -ERESTARTSYS)
 			return rc;
@@ -387,7 +387,7 @@
 	for (i = 0; i < bytes_to_write; i++) {
 		rc = wait_for_bulk_out_ready(dev);
 		if (rc <= 0) {
-			DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n",
+			DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2zx\n",
 			       rc);
 			DEBUGP(2, dev, "<- cm4040_write (failed)\n");
 			if (rc == -ERESTARTSYS)
@@ -403,7 +403,7 @@
 	rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev);
 
 	if (rc <= 0) {
-		DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
+		DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
 		DEBUGP(2, dev, "<- cm4040_write (failed)\n");
 		if (rc == -ERESTARTSYS)
 			return rc;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index b583e53..1822472 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -722,15 +722,18 @@
 	}
 }
 
-static void credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
 {
 	const int nbits_max = (int)(~0U >> (ENTROPY_SHIFT + 1));
 
+	if (nbits < 0)
+		return -EINVAL;
+
 	/* Cap the value to avoid overflows */
 	nbits = min(nbits,  nbits_max);
-	nbits = max(nbits, -nbits_max);
 
 	credit_entropy_bits(r, nbits);
+	return 0;
 }
 
 /*********************************************************************
@@ -945,6 +948,7 @@
 	/* award one bit for the contents of the fast pool */
 	credit_entropy_bits(r, credit + 1);
 }
+EXPORT_SYMBOL_GPL(add_interrupt_randomness);
 
 #ifdef CONFIG_BLOCK
 void add_disk_randomness(struct gendisk *disk)
@@ -1457,12 +1461,16 @@
 static ssize_t
 urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
+	static int maxwarn = 10;
 	int ret;
 
-	if (unlikely(nonblocking_pool.initialized == 0))
-		printk_once(KERN_NOTICE "random: %s urandom read "
-			    "with %d bits of entropy available\n",
-			    current->comm, nonblocking_pool.entropy_total);
+	if (unlikely(nonblocking_pool.initialized == 0) &&
+	    maxwarn > 0) {
+		maxwarn--;
+		printk(KERN_NOTICE "random: %s: uninitialized urandom read "
+		       "(%zd bytes read, %d bits of entropy available)\n",
+		       current->comm, nbytes, nonblocking_pool.entropy_total);
+	}
 
 	nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
 	ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
@@ -1542,8 +1550,7 @@
 			return -EPERM;
 		if (get_user(ent_count, p))
 			return -EFAULT;
-		credit_entropy_bits_safe(&input_pool, ent_count);
-		return 0;
+		return credit_entropy_bits_safe(&input_pool, ent_count);
 	case RNDADDENTROPY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
@@ -1557,8 +1564,7 @@
 				    size);
 		if (retval < 0)
 			return retval;
-		credit_entropy_bits_safe(&input_pool, ent_count);
-		return 0;
+		return credit_entropy_bits_safe(&input_pool, ent_count);
 	case RNDZAPENTCNT:
 	case RNDCLEARPOOL:
 		/*
@@ -1792,13 +1798,15 @@
 	return 0;
 }
 
+static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash)
+		__aligned(sizeof(unsigned long));
+
 /*
  * Get a random word for internal kernel use only. Similar to urandom but
  * with the goal of minimal entropy pool depletion. As a result, the random
  * value is not cryptographically secure but for several uses the cost of
  * depleting entropy is too high
  */
-static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
 unsigned int get_random_int(void)
 {
 	__u32 *hash;
@@ -1868,12 +1876,18 @@
 {
 	struct entropy_store *poolp = &input_pool;
 
-	/* Suspend writing if we're above the trickle threshold.
-	 * We'll be woken up again once below random_write_wakeup_thresh,
-	 * or when the calling thread is about to terminate.
-	 */
-	wait_event_interruptible(random_write_wait, kthread_should_stop() ||
+	if (unlikely(nonblocking_pool.initialized == 0))
+		poolp = &nonblocking_pool;
+	else {
+		/* Suspend writing if we're above the trickle
+		 * threshold.  We'll be woken up again once below
+		 * random_write_wakeup_thresh, or when the calling
+		 * thread is about to terminate.
+		 */
+		wait_event_interruptible(random_write_wait,
+					 kthread_should_stop() ||
 			ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
+	}
 	mix_pool_bytes(poolp, buffer, count);
 	credit_entropy_bits(poolp, entropy);
 }
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index de0337e..4f3137d 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -139,7 +139,7 @@
 
 	/* atomic tpm command send and result receive */
 	out_size = tpm_transmit(priv->chip, priv->data_buffer,
-				sizeof(priv->data_buffer));
+				sizeof(priv->data_buffer), 0);
 	if (out_size < 0) {
 		mutex_unlock(&priv->buffer_mutex);
 		return out_size;
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index c50637d..17abe52 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -328,8 +328,8 @@
 /*
  * Internal kernel interface to transmit TPM commands
  */
-ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
-		     size_t bufsiz)
+ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
+		     unsigned int flags)
 {
 	ssize_t rc;
 	u32 count, ordinal;
@@ -348,7 +348,8 @@
 		return -E2BIG;
 	}
 
-	mutex_lock(&chip->tpm_mutex);
+	if (!(flags & TPM_TRANSMIT_UNLOCKED))
+		mutex_lock(&chip->tpm_mutex);
 
 	rc = chip->ops->send(chip, (u8 *) buf, count);
 	if (rc < 0) {
@@ -391,20 +392,21 @@
 		dev_err(chip->pdev,
 			"tpm_transmit: tpm_recv: error %zd\n", rc);
 out:
-	mutex_unlock(&chip->tpm_mutex);
+	if (!(flags & TPM_TRANSMIT_UNLOCKED))
+		mutex_unlock(&chip->tpm_mutex);
 	return rc;
 }
 
 #define TPM_DIGEST_SIZE 20
 #define TPM_RET_CODE_IDX 6
 
-ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd,
-			 int len, const char *desc)
+ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd,
+			 int len, unsigned int flags, const char *desc)
 {
-	struct tpm_output_header *header;
+	const struct tpm_output_header *header;
 	int err;
 
-	len = tpm_transmit(chip, (u8 *) cmd, len);
+	len = tpm_transmit(chip, (const u8 *)cmd, len, flags);
 	if (len <  0)
 		return len;
 	else if (len < TPM_HEADER_SIZE)
@@ -452,7 +454,8 @@
 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 		tpm_cmd.params.getcap_in.subcap = subcap_id;
 	}
-	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc);
+	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
+			      desc);
 	if (!rc)
 		*cap = tpm_cmd.params.getcap_out.cap;
 	return rc;
@@ -468,7 +471,7 @@
 	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
 
-	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
 			      "attempting to determine the timeouts");
 }
 EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
@@ -489,7 +492,7 @@
 	start_cmd.header.in = tpm_startup_header;
 
 	start_cmd.params.startup_in.startup_type = startup_type;
-	return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE,
+	return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
 				"attempting to start the TPM");
 }
 
@@ -505,7 +508,8 @@
 	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
 	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
-	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL);
+	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
+			      NULL);
 
 	if (rc == TPM_ERR_INVALID_POSTINIT) {
 		/* The TPM is not started, we are the first to talk to it.
@@ -519,7 +523,7 @@
 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 		tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
 		rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
-				  NULL);
+				      0, NULL);
 	}
 	if (rc) {
 		dev_err(chip->pdev,
@@ -580,7 +584,7 @@
 	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION;
 
-	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
 			      "attempting to determine the durations");
 	if (rc)
 		return rc;
@@ -636,7 +640,7 @@
 	struct tpm_cmd_t cmd;
 
 	cmd.header.in = continue_selftest_header;
-	rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, 0,
 			      "continue selftest");
 	return rc;
 }
@@ -656,7 +660,7 @@
 
 	cmd.header.in = pcrread_header;
 	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
-	rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, 0,
 			      "attempting to read a pcr value");
 
 	if (rc == 0)
@@ -754,7 +758,7 @@
 	cmd.header.in = pcrextend_header;
 	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
 	memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
-	rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, 0,
 			      "attempting extend a PCR value");
 
 	tpm_chip_put(chip);
@@ -793,7 +797,7 @@
 		/* Attempt to read a PCR value */
 		cmd.header.in = pcrread_header;
 		cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0);
-		rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE);
+		rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE, 0);
 		/* Some buggy TPMs will not respond to tpm_tis_ready() for
 		 * around 300ms while the self test is ongoing, keep trying
 		 * until the self test duration expires. */
@@ -834,7 +838,7 @@
 	if (chip == NULL)
 		return -ENODEV;
 
-	rc = tpm_transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
+	rc = tpm_transmit_cmd(chip, cmd, buflen, 0, "attempting tpm_cmd");
 
 	tpm_chip_put(chip);
 	return rc;
@@ -936,14 +940,15 @@
 		cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
 		memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
 		       TPM_DIGEST_SIZE);
-		rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
+		rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, 0,
 				      "extending dummy pcr before suspend");
 	}
 
 	/* now do the actual savestate */
 	for (try = 0; try < TPM_RETRY; try++) {
 		cmd.header.in = savestate_header;
-		rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL);
+		rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, 0,
+				      NULL);
 
 		/*
 		 * If the TPM indicates that it is too busy to respond to
@@ -1027,8 +1032,8 @@
 		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
 
 		err = tpm_transmit_cmd(chip, &tpm_cmd,
-				   TPM_GETRANDOM_RESULT_SIZE + num_bytes,
-				   "attempting get random");
+				       TPM_GETRANDOM_RESULT_SIZE + num_bytes,
+				       0, "attempting get random");
 		if (err)
 			break;
 
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index ee66fd4..f880856 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -39,7 +39,7 @@
 	struct tpm_chip *chip = dev_get_drvdata(dev);
 
 	tpm_cmd.header.in = tpm_readpubek_header;
-	err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
+	err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, 0,
 			       "attempting to read the PUBEK");
 	if (err)
 		goto out;
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index a4257a3..2216861 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -498,11 +498,15 @@
 extern dev_t tpm_devt;
 extern const struct file_operations tpm_fops;
 
+enum tpm_transmit_flags {
+	TPM_TRANSMIT_UNLOCKED	= BIT(0),
+};
+
+ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
+		     unsigned int flags);
+ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, int len,
+			 unsigned int flags, const char *desc);
 ssize_t	tpm_getcap(struct device *, __be32, cap_t *, const char *);
-ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
-		     size_t bufsiz);
-ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len,
-			 const char *desc);
 extern int tpm_get_timeouts(struct tpm_chip *);
 extern void tpm_gen_interrupt(struct tpm_chip *);
 extern int tpm_do_selftest(struct tpm_chip *);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index c121304..cb7e4f6 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -264,7 +264,7 @@
 	       sizeof(cmd.params.pcrread_in.pcr_select));
 	cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0,
 			      "attempting to read a pcr value");
 	if (rc == 0) {
 		buf = cmd.params.pcrread_out.digest;
@@ -312,7 +312,7 @@
 	cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
 	memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0,
 			      "attempting extend a PCR value");
 
 	return rc;
@@ -358,7 +358,7 @@
 		cmd.header.in = tpm2_getrandom_header;
 		cmd.params.getrandom_in.size = cpu_to_be16(num_bytes);
 
-		err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+		err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0,
 				       "attempting get random");
 		if (err)
 			break;
@@ -416,12 +416,12 @@
 }
 
 /**
- * tpm2_seal_trusted() - seal a trusted key
- * @chip_num: A specific chip number for the request or TPM_ANY_NUM
- * @options: authentication values and other options
+ * tpm2_seal_trusted() - seal the payload of a trusted key
+ * @chip_num: TPM chip to use
  * @payload: the key data in clear and encrypted form
+ * @options: authentication values and other options
  *
- * Returns < 0 on error and 0 on success.
+ * Return: < 0 on error and 0 on success.
  */
 int tpm2_seal_trusted(struct tpm_chip *chip,
 		      struct trusted_key_payload *payload,
@@ -472,7 +472,7 @@
 		goto out;
 	}
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "sealing data");
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, "sealing data");
 	if (rc)
 		goto out;
 
@@ -494,10 +494,18 @@
 	return rc;
 }
 
-static int tpm2_load(struct tpm_chip *chip,
-		     struct trusted_key_payload *payload,
-		     struct trusted_key_options *options,
-		     u32 *blob_handle)
+/**
+ * tpm2_load_cmd() - execute a TPM2_Load command
+ * @chip_num: TPM chip to use
+ * @payload: the key data in clear and encrypted form
+ * @options: authentication values and other options
+ *
+ * Return: same as with tpm_transmit_cmd
+ */
+static int tpm2_load_cmd(struct tpm_chip *chip,
+			 struct trusted_key_payload *payload,
+			 struct trusted_key_options *options,
+			 u32 *blob_handle, unsigned int flags)
 {
 	struct tpm_buf buf;
 	unsigned int private_len;
@@ -532,7 +540,7 @@
 		goto out;
 	}
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "loading blob");
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, "loading blob");
 	if (!rc)
 		*blob_handle = be32_to_cpup(
 			(__be32 *) &buf.data[TPM_HEADER_SIZE]);
@@ -546,7 +554,16 @@
 	return rc;
 }
 
-static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
+/**
+ * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command
+ * @chip_num: TPM chip to use
+ * @payload: the key data in clear and encrypted form
+ * @options: authentication values and other options
+ *
+ * Return: same as with tpm_transmit_cmd
+ */
+static void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
+				   unsigned int flags)
 {
 	struct tpm_buf buf;
 	int rc;
@@ -560,7 +577,8 @@
 
 	tpm_buf_append_u32(&buf, handle);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context");
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags,
+			      "flushing context");
 	if (rc)
 		dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle,
 			 rc);
@@ -568,10 +586,18 @@
 	tpm_buf_destroy(&buf);
 }
 
-static int tpm2_unseal(struct tpm_chip *chip,
-		       struct trusted_key_payload *payload,
-		       struct trusted_key_options *options,
-		       u32 blob_handle)
+/**
+ * tpm2_unseal_cmd() - execute a TPM2_Unload command
+ * @chip_num: TPM chip to use
+ * @payload: the key data in clear and encrypted form
+ * @options: authentication values and other options
+ *
+ * Return: same as with tpm_transmit_cmd
+ */
+static int tpm2_unseal_cmd(struct tpm_chip *chip,
+			   struct trusted_key_payload *payload,
+			   struct trusted_key_options *options,
+			   u32 blob_handle, unsigned int flags)
 {
 	struct tpm_buf buf;
 	u16 data_len;
@@ -589,7 +615,7 @@
 			     options->blobauth /* hmac */,
 			     TPM_DIGEST_SIZE);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "unsealing");
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, "unsealing");
 	if (rc > 0)
 		rc = -EPERM;
 
@@ -608,12 +634,12 @@
 }
 
 /**
- * tpm_unseal_trusted() - unseal a trusted key
- * @chip_num: A specific chip number for the request or TPM_ANY_NUM
- * @options: authentication values and other options
+ * tpm_unseal_trusted() - unseal the payload of a trusted key
+ * @chip_num: TPM chip to use
  * @payload: the key data in clear and encrypted form
+ * @options: authentication values and other options
  *
- * Returns < 0 on error and 0 on success.
+ * Return: < 0 on error and 0 on success.
  */
 int tpm2_unseal_trusted(struct tpm_chip *chip,
 			struct trusted_key_payload *payload,
@@ -622,14 +648,17 @@
 	u32 blob_handle;
 	int rc;
 
-	rc = tpm2_load(chip, payload, options, &blob_handle);
+	mutex_lock(&chip->tpm_mutex);
+	rc = tpm2_load_cmd(chip, payload, options, &blob_handle,
+			   TPM_TRANSMIT_UNLOCKED);
 	if (rc)
-		return rc;
+		goto out;
 
-	rc = tpm2_unseal(chip, payload, options, blob_handle);
-
-	tpm2_flush_context(chip, blob_handle);
-
+	rc = tpm2_unseal_cmd(chip, payload, options, blob_handle,
+			     TPM_TRANSMIT_UNLOCKED);
+	tpm2_flush_context_cmd(chip, blob_handle, TPM_TRANSMIT_UNLOCKED);
+out:
+	mutex_unlock(&chip->tpm_mutex);
 	return rc;
 }
 
@@ -655,9 +684,9 @@
 	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
 	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc);
+	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, desc);
 	if (!rc)
-		*value = cmd.params.get_tpm_pt_out.value;
+		*value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
 
 	return rc;
 }
@@ -689,7 +718,7 @@
 	cmd.header.in = tpm2_startup_header;
 
 	cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
-	return tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+	return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0,
 				"attempting to start the TPM");
 }
 EXPORT_SYMBOL_GPL(tpm2_startup);
@@ -718,7 +747,7 @@
 	cmd.header.in = tpm2_shutdown_header;
 	cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM");
+	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, "stopping the TPM");
 
 	/* In places where shutdown command is sent there's no much we can do
 	 * except print the error code on a system failure.
@@ -784,7 +813,7 @@
 	cmd.header.in = tpm2_selftest_header;
 	cmd.params.selftest_in.full_test = full;
 
-	rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE,
+	rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, 0,
 			      "continue selftest");
 
 	/* At least some prototype chips seem to give RC_TESTING error
@@ -836,7 +865,7 @@
 		cmd.params.pcrread_in.pcr_select[1] = 0x00;
 		cmd.params.pcrread_in.pcr_select[2] = 0x00;
 
-		rc = tpm_transmit_cmd(chip, (u8 *) &cmd, sizeof(cmd), NULL);
+		rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, NULL);
 		if (rc < 0)
 			break;
 
@@ -885,7 +914,7 @@
 	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
 	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
 
-	rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd));
+	rc = tpm_transmit(chip, (const u8 *)&cmd, sizeof(cmd), 0);
 	if (rc <  0)
 		return rc;
 	else if (rc < TPM_HEADER_SIZE)
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 61e6429..35308df 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -118,8 +118,7 @@
 
 	memcpy_fromio(buf, priv->rsp, 6);
 	expected = be32_to_cpup((__be32 *) &buf[2]);
-
-	if (expected > count)
+	if (expected > count || expected < 6)
 		return -EIO;
 
 	memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6);
@@ -149,6 +148,11 @@
 	struct crb_priv *priv = chip->vendor.priv;
 	int rc = 0;
 
+	/* Zero the cancel register so that the next command will not get
+	 * canceled.
+	 */
+	iowrite32(0, &priv->cca->cancel);
+
 	if (len > le32_to_cpu(ioread32(&priv->cca->cmd_size))) {
 		dev_err(&chip->dev,
 			"invalid command count value %x %zx\n",
@@ -182,8 +186,6 @@
 
 	if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip))
 		dev_err(&chip->dev, "ACPI Start failed\n");
-
-	iowrite32(0, &priv->cca->cancel);
 }
 
 static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 65f7eec..f10a107 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -401,7 +401,7 @@
 	iowrite32(intmask,
 		  chip->vendor.iobase +
 		  TPM_INT_ENABLE(chip->vendor.locality));
-	free_irq(chip->vendor.irq, chip);
+	devm_free_irq(chip->pdev, chip->vendor.irq, chip);
 	chip->vendor.irq = 0;
 }
 
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index 3111f27..849f2e2 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -305,7 +305,6 @@
 	rv = setup_ring(dev, priv);
 	if (rv) {
 		chip = dev_get_drvdata(&dev->dev);
-		tpm_chip_unregister(chip);
 		ring_free(priv);
 		return rv;
 	}
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index d2406fe..be0b09a 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1130,6 +1130,8 @@
 {
 	struct port *port;
 	struct scatterlist sg[1];
+	void *data;
+	int ret;
 
 	if (unlikely(early_put_chars))
 		return early_put_chars(vtermno, buf, count);
@@ -1138,8 +1140,14 @@
 	if (!port)
 		return -EPIPE;
 
-	sg_init_one(sg, buf, count);
-	return __send_to_port(port, sg, 1, count, (void *)buf, false);
+	data = kmemdup(buf, count, GFP_ATOMIC);
+	if (!data)
+		return -ENOMEM;
+
+	sg_init_one(sg, data, count);
+	ret = __send_to_port(port, sg, 1, count, data, false);
+	kfree(data);
+	return ret;
 }
 
 /*
@@ -1533,19 +1541,29 @@
 	spin_lock_irq(&port->inbuf_lock);
 	/* Remove unused data this port might have received. */
 	discard_port_data(port);
+	spin_unlock_irq(&port->inbuf_lock);
 
 	/* Remove buffers we queued up for the Host to send us data in. */
-	while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
-		free_buf(buf, true);
-	spin_unlock_irq(&port->inbuf_lock);
+	do {
+		spin_lock_irq(&port->inbuf_lock);
+		buf = virtqueue_detach_unused_buf(port->in_vq);
+		spin_unlock_irq(&port->inbuf_lock);
+		if (buf)
+			free_buf(buf, true);
+	} while (buf);
 
 	spin_lock_irq(&port->outvq_lock);
 	reclaim_consumed_buffers(port);
+	spin_unlock_irq(&port->outvq_lock);
 
 	/* Free pending buffers from the out-queue. */
-	while ((buf = virtqueue_detach_unused_buf(port->out_vq)))
-		free_buf(buf, true);
-	spin_unlock_irq(&port->outvq_lock);
+	do {
+		spin_lock_irq(&port->outvq_lock);
+		buf = virtqueue_detach_unused_buf(port->out_vq);
+		spin_unlock_irq(&port->outvq_lock);
+		if (buf)
+			free_buf(buf, true);
+	} while (buf);
 }
 
 /*
@@ -1846,7 +1864,7 @@
 {
 	struct ports_device *portdev;
 
-	portdev = container_of(work, struct ports_device, control_work);
+	portdev = container_of(work, struct ports_device, config_work);
 	if (!use_multiport(portdev)) {
 		struct virtio_device *vdev;
 		struct port *port;
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 820714c..af9e9af 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -78,7 +78,9 @@
 obj-$(CONFIG_ARCH_OMAP2PLUS)		+= ti/
 obj-$(CONFIG_ARCH_U8500)		+= ux500/
 obj-$(CONFIG_COMMON_CLK_VERSATILE)	+= versatile/
+ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_X86)			+= x86/
+endif
 obj-$(CONFIG_ARCH_ZX)			+= zte/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
 obj-$(CONFIG_H8300)		+= h8300/
diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c
index 61566bc..a165230 100644
--- a/drivers/clk/at91/clk-h32mx.c
+++ b/drivers/clk/at91/clk-h32mx.c
@@ -116,7 +116,7 @@
 	h32mxclk->pmc = pmc;
 
 	clk = clk_register(NULL, &h32mxclk->hw);
-	if (!clk) {
+	if (IS_ERR(clk)) {
 		kfree(h32mxclk);
 		return;
 	}
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 4f9830c..35ab89f 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -890,8 +890,14 @@
 	struct bcm2835_cprman *cprman = pll->cprman;
 	const struct bcm2835_pll_data *data = pll->data;
 
-	cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
-	cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN);
+	spin_lock(&cprman->regs_lock);
+	cprman_write(cprman, data->cm_ctrl_reg,
+		     cprman_read(cprman, data->cm_ctrl_reg) |
+		     CM_PLL_ANARST);
+	cprman_write(cprman, data->a2w_ctrl_reg,
+		     cprman_read(cprman, data->a2w_ctrl_reg) |
+		     A2W_PLL_CTRL_PWRDN);
+	spin_unlock(&cprman->regs_lock);
 }
 
 static int bcm2835_pll_on(struct clk_hw *hw)
@@ -901,6 +907,10 @@
 	const struct bcm2835_pll_data *data = pll->data;
 	ktime_t timeout;
 
+	cprman_write(cprman, data->a2w_ctrl_reg,
+		     cprman_read(cprman, data->a2w_ctrl_reg) &
+		     ~A2W_PLL_CTRL_PWRDN);
+
 	/* Take the PLL out of reset. */
 	cprman_write(cprman, data->cm_ctrl_reg,
 		     cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST);
@@ -1068,10 +1078,14 @@
 	struct bcm2835_cprman *cprman = divider->cprman;
 	const struct bcm2835_pll_divider_data *data = divider->data;
 
+	spin_lock(&cprman->regs_lock);
 	cprman_write(cprman, data->cm_reg,
 		     (cprman_read(cprman, data->cm_reg) &
 		      ~data->load_mask) | data->hold_mask);
-	cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
+	cprman_write(cprman, data->a2w_reg,
+		     cprman_read(cprman, data->a2w_reg) |
+		     A2W_PLL_CHANNEL_DISABLE);
+	spin_unlock(&cprman->regs_lock);
 }
 
 static int bcm2835_pll_divider_on(struct clk_hw *hw)
@@ -1080,12 +1094,14 @@
 	struct bcm2835_cprman *cprman = divider->cprman;
 	const struct bcm2835_pll_divider_data *data = divider->data;
 
+	spin_lock(&cprman->regs_lock);
 	cprman_write(cprman, data->a2w_reg,
 		     cprman_read(cprman, data->a2w_reg) &
 		     ~A2W_PLL_CHANNEL_DISABLE);
 
 	cprman_write(cprman, data->cm_reg,
 		     cprman_read(cprman, data->cm_reg) & ~data->hold_mask);
+	spin_unlock(&cprman->regs_lock);
 
 	return 0;
 }
@@ -1167,8 +1183,9 @@
 		div &= ~unused_frac_mask;
 	}
 
-	/* Clamp to the limits. */
-	div = max(div, unused_frac_mask + 1);
+	/* clamp to min divider of 1 */
+	div = max_t(u32, div, 1 << CM_DIV_FRAC_BITS);
+	/* clamp to the highest possible fractional divider */
 	div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
 				      CM_DIV_FRAC_BITS - data->frac_bits));
 
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index bbf206e..ac9582d 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -354,7 +354,7 @@
 
 	/* if read only, just return current value */
 	if (divider->flags & CLK_DIVIDER_READ_ONLY) {
-		bestdiv = readl(divider->reg) >> divider->shift;
+		bestdiv = clk_readl(divider->reg) >> divider->shift;
 		bestdiv &= div_mask(divider->width);
 		bestdiv = _get_div(divider->table, bestdiv, divider->flags,
 			divider->width);
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 7bc1c45..a5070f9 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -700,6 +700,7 @@
 					     struct mux_hwclock *hwc,
 					     const struct clk_ops *ops,
 					     unsigned long min_rate,
+					     unsigned long max_rate,
 					     unsigned long pct80_rate,
 					     const char *fmt, int idx)
 {
@@ -728,6 +729,8 @@
 			continue;
 		if (rate < min_rate)
 			continue;
+		if (rate > max_rate)
+			continue;
 
 		parent_names[j] = div->name;
 		hwc->parent_to_clksel[j] = i;
@@ -759,14 +762,18 @@
 	struct mux_hwclock *hwc;
 	const struct clockgen_pll_div *div;
 	unsigned long plat_rate, min_rate;
-	u64 pct80_rate;
+	u64 max_rate, pct80_rate;
 	u32 clksel;
 
 	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
 	if (!hwc)
 		return NULL;
 
-	hwc->reg = cg->regs + 0x20 * idx;
+	if (cg->info.flags & CG_VER3)
+		hwc->reg = cg->regs + 0x70000 + 0x20 * idx;
+	else
+		hwc->reg = cg->regs + 0x20 * idx;
+
 	hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]];
 
 	/*
@@ -783,8 +790,8 @@
 		return NULL;
 	}
 
-	pct80_rate = clk_get_rate(div->clk);
-	pct80_rate *= 8;
+	max_rate = clk_get_rate(div->clk);
+	pct80_rate = max_rate * 8;
 	do_div(pct80_rate, 10);
 
 	plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk);
@@ -794,7 +801,7 @@
 	else
 		min_rate = plat_rate / 2;
 
-	return create_mux_common(cg, hwc, &cmux_ops, min_rate,
+	return create_mux_common(cg, hwc, &cmux_ops, min_rate, max_rate,
 				 pct80_rate, "cg-cmux%d", idx);
 }
 
@@ -809,7 +816,7 @@
 	hwc->reg = cg->regs + 0x20 * idx + 0x10;
 	hwc->info = cg->info.hwaccel[idx];
 
-	return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0,
+	return create_mux_common(cg, hwc, &hwaccel_ops, 0, ULONG_MAX, 0,
 				 "cg-hwaccel%d", idx);
 }
 
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
index 43f9d15..763aed2 100644
--- a/drivers/clk/clk-wm831x.c
+++ b/drivers/clk/clk-wm831x.c
@@ -247,7 +247,7 @@
 	if (ret < 0) {
 		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
 			ret);
-		return true;
+		return false;
 	}
 
 	return (ret & WM831X_CLKOUT_ENA) != 0;
diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
index 27c0da2..b134a8b 100644
--- a/drivers/clk/clk-xgene.c
+++ b/drivers/clk/clk-xgene.c
@@ -351,7 +351,8 @@
 		/* Set new divider */
 		data = xgene_clk_read(pclk->param.divider_reg +
 				pclk->param.reg_divider_offset);
-		data &= ~((1 << pclk->param.reg_divider_width) - 1);
+		data &= ~(((1 << pclk->param.reg_divider_width) - 1)
+				<< pclk->param.reg_divider_shift);
 		data |= divider;
 		xgene_clk_write(data, pclk->param.divider_reg +
 					pclk->param.reg_divider_offset);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bd64a94..f13c3f4 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1443,15 +1443,6 @@
 	else if (core->parent)
 		best_parent_rate = core->parent->rate;
 
-	if (core->flags & CLK_SET_RATE_UNGATE) {
-		unsigned long flags;
-
-		clk_core_prepare(core);
-		flags = clk_enable_lock();
-		clk_core_enable(core);
-		clk_enable_unlock(flags);
-	}
-
 	if (core->new_parent && core->new_parent != core->parent) {
 		old_parent = __clk_set_parent_before(core, core->new_parent);
 		trace_clk_set_parent(core, core->new_parent);
@@ -1478,15 +1469,6 @@
 
 	core->rate = clk_recalc(core, best_parent_rate);
 
-	if (core->flags & CLK_SET_RATE_UNGATE) {
-		unsigned long flags;
-
-		flags = clk_enable_lock();
-		clk_core_disable(core);
-		clk_enable_unlock(flags);
-		clk_core_unprepare(core);
-	}
-
 	if (core->notifier_count && old_rate != core->rate)
 		__clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
 
diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c
index 6a96414..6a49ba2 100644
--- a/drivers/clk/imx/clk-imx31.c
+++ b/drivers/clk/imx/clk-imx31.c
@@ -157,10 +157,8 @@
 	}
 }
 
-int __init mx31_clocks_init(void)
+int __init mx31_clocks_init(unsigned long fref)
 {
-	u32 fref = 26000000; /* default */
-
 	_mx31_clocks_init(fref);
 
 	clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c
index a71d24c..d302ed3 100644
--- a/drivers/clk/imx/clk-imx35.c
+++ b/drivers/clk/imx/clk-imx35.c
@@ -66,7 +66,7 @@
 static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"};
 
 enum mx35_clks {
-	ckih, ckil, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
+	ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
 	arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel,
 	esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre,
 	spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre,
@@ -79,7 +79,7 @@
 	rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate,
 	ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate,
 	wdog_gate, max_gate, admux_gate, csi_gate, csi_div, csi_sel, iim_gate,
-	gpu2d_gate, clk_max
+	gpu2d_gate, ckil, clk_max
 };
 
 static struct clk *clk[clk_max];
@@ -115,7 +115,7 @@
 	}
 
 	clk[ckih] = imx_clk_fixed("ckih", 24000000);
-	clk[ckil] = imx_clk_fixed("ckih", 32768);
+	clk[ckil] = imx_clk_fixed("ckil", 32768);
 	clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "mpll", "ckih", base + MX35_CCM_MPCTL);
 	clk[ppll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "ppll", "ckih", base + MX35_CCM_PPCTL);
 
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index c193508..aab6420 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -550,6 +550,24 @@
 	if (IS_ENABLED(CONFIG_PCI_IMX6))
 		clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]);
 
+	/*
+	 * Initialize the GPU clock muxes, so that the maximum specified clock
+	 * rates for the respective SoC are not exceeded.
+	 */
+	if (clk_on_imx6dl()) {
+		clk_set_parent(clk[IMX6QDL_CLK_GPU3D_CORE_SEL],
+			       clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
+		clk_set_parent(clk[IMX6QDL_CLK_GPU2D_CORE_SEL],
+			       clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
+	} else if (clk_on_imx6q()) {
+		clk_set_parent(clk[IMX6QDL_CLK_GPU3D_CORE_SEL],
+			       clk[IMX6QDL_CLK_MMDC_CH0_AXI]);
+		clk_set_parent(clk[IMX6QDL_CLK_GPU3D_SHADER_SEL],
+			       clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
+		clk_set_parent(clk[IMX6QDL_CLK_GPU2D_CORE_SEL],
+			       clk[IMX6QDL_CLK_PLL3_USB_OTG]);
+	}
+
 	imx_register_uart_clocks(uart_clks);
 }
 CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 251533d..f261b1d 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -313,7 +313,7 @@
 	}
 
 	pxa_unit->apmu_base = of_iomap(np, 1);
-	if (!pxa_unit->mpmu_base) {
+	if (!pxa_unit->apmu_base) {
 		pr_err("failed to map apmu registers\n");
 		return;
 	}
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index 64eaf41..427f4bb 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -262,7 +262,7 @@
 	}
 
 	pxa_unit->apmu_base = of_iomap(np, 1);
-	if (!pxa_unit->mpmu_base) {
+	if (!pxa_unit->apmu_base) {
 		pr_err("failed to map apmu registers\n");
 		return;
 	}
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index 13d6173..cdf5ba5 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -282,7 +282,7 @@
 	}
 
 	pxa_unit->apmu_base = of_iomap(np, 1);
-	if (!pxa_unit->mpmu_base) {
+	if (!pxa_unit->apmu_base) {
 		pr_err("failed to map apmu registers\n");
 		return;
 	}
@@ -294,7 +294,7 @@
 	}
 
 	pxa_unit->apbcp_base = of_iomap(np, 3);
-	if (!pxa_unit->mpmu_base) {
+	if (!pxa_unit->apbcp_base) {
 		pr_err("failed to map apbcp registers\n");
 		return;
 	}
diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index d0a0313..2e7f03d 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -2346,6 +2346,7 @@
 				"pcnoc_bfdcd_clk_src",
 			},
 			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -2381,6 +2382,7 @@
 				"crypto_clk_src",
 			},
 			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
 			.ops = &clk_branch2_ops,
 		},
 	},
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index d599829..b27edd6 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -10,7 +10,6 @@
 obj-y	+= clk-mmc-phase.o
 obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
-obj-y	+= clk-rk3036.o
 obj-y	+= clk-rk3188.o
 obj-y	+= clk-rk3288.o
 obj-y	+= clk-rk3368.o
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index 2685644..33c20c6 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -153,6 +153,7 @@
 		return NULL;
 
 	init.name = name;
+	init.flags = 0;
 	init.num_parents = num_parents;
 	init.parent_names = parent_names;
 	init.ops = &rockchip_mmc_clk_ops;
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index b7e66c9..4881eb8 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -2,9 +2,6 @@
  * Copyright (c) 2014 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
  *
- * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
- * Author: Xing Zheng <zhengxing@rock-chips.com>
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -22,7 +19,6 @@
 #include <linux/delay.h>
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
-#include <linux/clk.h>
 #include "clk.h"
 
 #define PLL_MODE_MASK		0x3
@@ -112,252 +108,6 @@
 }
 
 /**
- * PLL used in RK3036
- */
-
-#define RK3036_PLLCON(i)			(i * 0x4)
-#define RK3036_PLLCON0_FBDIV_MASK		0xfff
-#define RK3036_PLLCON0_FBDIV_SHIFT		0
-#define RK3036_PLLCON0_POSTDIV1_MASK		0x7
-#define RK3036_PLLCON0_POSTDIV1_SHIFT		12
-#define RK3036_PLLCON1_REFDIV_MASK		0x3f
-#define RK3036_PLLCON1_REFDIV_SHIFT		0
-#define RK3036_PLLCON1_POSTDIV2_MASK		0x7
-#define RK3036_PLLCON1_POSTDIV2_SHIFT		6
-#define RK3036_PLLCON1_DSMPD_MASK		0x1
-#define RK3036_PLLCON1_DSMPD_SHIFT		12
-#define RK3036_PLLCON2_FRAC_MASK		0xffffff
-#define RK3036_PLLCON2_FRAC_SHIFT		0
-
-#define RK3036_PLLCON1_PWRDOWN			(1 << 13)
-
-static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll,
-					struct rockchip_pll_rate_table *rate)
-{
-	u32 pllcon;
-
-	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0));
-	rate->fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT)
-				& RK3036_PLLCON0_FBDIV_MASK);
-	rate->postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT)
-				& RK3036_PLLCON0_POSTDIV1_MASK);
-
-	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));
-	rate->refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT)
-				& RK3036_PLLCON1_REFDIV_MASK);
-	rate->postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT)
-				& RK3036_PLLCON1_POSTDIV2_MASK);
-	rate->dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT)
-				& RK3036_PLLCON1_DSMPD_MASK);
-
-	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
-	rate->frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT)
-				& RK3036_PLLCON2_FRAC_MASK);
-}
-
-static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw,
-						     unsigned long prate)
-{
-	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
-	struct rockchip_pll_rate_table cur;
-	u64 rate64 = prate;
-
-	rockchip_rk3036_pll_get_params(pll, &cur);
-
-	rate64 *= cur.fbdiv;
-	do_div(rate64, cur.refdiv);
-
-	if (cur.dsmpd == 0) {
-		/* fractional mode */
-		u64 frac_rate64 = prate * cur.frac;
-
-		do_div(frac_rate64, cur.refdiv);
-		rate64 += frac_rate64 >> 24;
-	}
-
-	do_div(rate64, cur.postdiv1);
-	do_div(rate64, cur.postdiv2);
-
-	return (unsigned long)rate64;
-}
-
-static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
-				const struct rockchip_pll_rate_table *rate)
-{
-	const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
-	struct clk_mux *pll_mux = &pll->pll_mux;
-	struct rockchip_pll_rate_table cur;
-	u32 pllcon;
-	int rate_change_remuxed = 0;
-	int cur_parent;
-	int ret;
-
-	pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
-		__func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv,
-		rate->postdiv2, rate->dsmpd, rate->frac);
-
-	rockchip_rk3036_pll_get_params(pll, &cur);
-	cur.rate = 0;
-
-	cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
-	if (cur_parent == PLL_MODE_NORM) {
-		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
-		rate_change_remuxed = 1;
-	}
-
-	/* update pll values */
-	writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,
-					  RK3036_PLLCON0_FBDIV_SHIFT) |
-		       HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK,
-					     RK3036_PLLCON0_POSTDIV1_SHIFT),
-		       pll->reg_base + RK3036_PLLCON(0));
-
-	writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK,
-						   RK3036_PLLCON1_REFDIV_SHIFT) |
-		       HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK,
-						     RK3036_PLLCON1_POSTDIV2_SHIFT) |
-		       HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK,
-						  RK3036_PLLCON1_DSMPD_SHIFT),
-		       pll->reg_base + RK3036_PLLCON(1));
-
-	/* GPLL CON2 is not HIWORD_MASK */
-	pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
-	pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT);
-	pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
-	writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
-
-	/* wait for the pll to lock */
-	ret = rockchip_pll_wait_lock(pll);
-	if (ret) {
-		pr_warn("%s: pll update unsucessful, trying to restore old params\n",
-			__func__);
-		rockchip_rk3036_pll_set_params(pll, &cur);
-	}
-
-	if (rate_change_remuxed)
-		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
-
-	return ret;
-}
-
-static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate,
-					unsigned long prate)
-{
-	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
-	const struct rockchip_pll_rate_table *rate;
-	unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate);
-	struct regmap *grf = rockchip_clk_get_grf();
-
-	if (IS_ERR(grf)) {
-		pr_debug("%s: grf regmap not available, aborting rate change\n",
-			 __func__);
-		return PTR_ERR(grf);
-	}
-
-	pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
-		 __func__, __clk_get_name(hw->clk), old_rate, drate, prate);
-
-	/* Get required rate settings from table */
-	rate = rockchip_get_pll_settings(pll, drate);
-	if (!rate) {
-		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-			drate, __clk_get_name(hw->clk));
-		return -EINVAL;
-	}
-
-	return rockchip_rk3036_pll_set_params(pll, rate);
-}
-
-static int rockchip_rk3036_pll_enable(struct clk_hw *hw)
-{
-	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
-
-	writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
-	       pll->reg_base + RK3036_PLLCON(1));
-
-	return 0;
-}
-
-static void rockchip_rk3036_pll_disable(struct clk_hw *hw)
-{
-	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
-
-	writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN,
-			     RK3036_PLLCON1_PWRDOWN, 0),
-	       pll->reg_base + RK3036_PLLCON(1));
-}
-
-static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw)
-{
-	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
-	u32 pllcon = readl(pll->reg_base + RK3036_PLLCON(1));
-
-	return !(pllcon & RK3036_PLLCON1_PWRDOWN);
-}
-
-static void rockchip_rk3036_pll_init(struct clk_hw *hw)
-{
-	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
-	const struct rockchip_pll_rate_table *rate;
-	struct rockchip_pll_rate_table cur;
-	unsigned long drate;
-
-	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
-		return;
-
-	drate = clk_hw_get_rate(hw);
-	rate = rockchip_get_pll_settings(pll, drate);
-
-	/* when no rate setting for the current rate, rely on clk_set_rate */
-	if (!rate)
-		return;
-
-	rockchip_rk3036_pll_get_params(pll, &cur);
-
-	pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk),
-		 drate);
-	pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
-		 cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2,
-		 cur.dsmpd, cur.frac);
-	pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
-		 rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2,
-		 rate->dsmpd, rate->frac);
-
-	if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
-		rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
-		rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
-		struct clk *parent = clk_get_parent(hw->clk);
-
-		if (!parent) {
-			pr_warn("%s: parent of %s not available\n",
-				__func__, __clk_get_name(hw->clk));
-			return;
-		}
-
-		pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
-			 __func__, __clk_get_name(hw->clk));
-		rockchip_rk3036_pll_set_params(pll, rate);
-	}
-}
-
-static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = {
-	.recalc_rate = rockchip_rk3036_pll_recalc_rate,
-	.enable = rockchip_rk3036_pll_enable,
-	.disable = rockchip_rk3036_pll_disable,
-	.is_enabled = rockchip_rk3036_pll_is_enabled,
-};
-
-static const struct clk_ops rockchip_rk3036_pll_clk_ops = {
-	.recalc_rate = rockchip_rk3036_pll_recalc_rate,
-	.round_rate = rockchip_pll_round_rate,
-	.set_rate = rockchip_rk3036_pll_set_rate,
-	.enable = rockchip_rk3036_pll_enable,
-	.disable = rockchip_rk3036_pll_disable,
-	.is_enabled = rockchip_rk3036_pll_is_enabled,
-	.init = rockchip_rk3036_pll_init,
-};
-
-/**
  * PLL used in RK3066, RK3188 and RK3288
  */
 
@@ -626,7 +376,7 @@
 	pll_mux->lock = lock;
 	pll_mux->hw.init = &init;
 
-	if (pll_type == pll_rk3036 || pll_type == pll_rk3066)
+	if (pll_type == pll_rk3066)
 		pll_mux->flags |= CLK_MUX_HIWORD_MASK;
 
 	/* the actual muxing is xin24m, pll-output, xin32k */
@@ -671,12 +421,6 @@
 	}
 
 	switch (pll_type) {
-	case pll_rk3036:
-		if (!pll->rate_table)
-			init.ops = &rockchip_rk3036_pll_clk_norate_ops;
-		else
-			init.ops = &rockchip_rk3036_pll_clk_ops;
-		break;
 	case pll_rk3066:
 		if (!pll->rate_table)
 			init.ops = &rockchip_rk3066_pll_clk_norate_ops;
diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c
deleted file mode 100644
index 0fba8a4..0000000
--- a/drivers/clk/rockchip/clk-rk3036.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (c) 2014 MundoReader S.L.
- * Author: Heiko Stuebner <heiko@sntech.de>
- *
- * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
- * Author: Xing Zheng <zhengxing@rock-chips.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk-provider.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/syscore_ops.h>
-#include <dt-bindings/clock/rk3036-cru.h>
-#include "clk.h"
-
-#define RK3036_GRF_SOC_STATUS0	0x14c
-
-enum rk3036_plls {
-	apll, dpll, gpll,
-};
-
-static struct rockchip_pll_rate_table rk3036_pll_rates[] = {
-	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
-	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
-	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
-	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
-	RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
-	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
-	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
-	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
-	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
-	{ /* sentinel */ },
-};
-
-#define RK3036_DIV_CPU_MASK		0x1f
-#define RK3036_DIV_CPU_SHIFT		8
-
-#define RK3036_DIV_PERI_MASK		0xf
-#define RK3036_DIV_PERI_SHIFT		0
-#define RK3036_DIV_ACLK_MASK		0x7
-#define RK3036_DIV_ACLK_SHIFT		4
-#define RK3036_DIV_HCLK_MASK		0x3
-#define RK3036_DIV_HCLK_SHIFT		8
-#define RK3036_DIV_PCLK_MASK		0x7
-#define RK3036_DIV_PCLK_SHIFT		12
-
-#define RK3036_CLKSEL1(_core_periph_div)					\
-	{									\
-		.reg = RK2928_CLKSEL_CON(1),					\
-		.val = HIWORD_UPDATE(_core_periph_div, RK3036_DIV_PERI_MASK,	\
-				RK3036_DIV_PERI_SHIFT)				\
-	}
-
-#define RK3036_CPUCLK_RATE(_prate, _core_periph_div)			\
-	{								\
-		.prate = _prate,					\
-		.divs = {						\
-			RK3036_CLKSEL1(_core_periph_div),		\
-		},							\
-	}
-
-static struct rockchip_cpuclk_rate_table rk3036_cpuclk_rates[] __initdata = {
-	RK3036_CPUCLK_RATE(816000000, 4),
-	RK3036_CPUCLK_RATE(600000000, 4),
-	RK3036_CPUCLK_RATE(312000000, 4),
-};
-
-static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = {
-	.core_reg = RK2928_CLKSEL_CON(0),
-	.div_core_shift = 0,
-	.div_core_mask = 0x1f,
-	.mux_core_shift = 7,
-};
-
-PNAME(mux_pll_p)		= { "xin24m", "xin24m" };
-
-PNAME(mux_armclk_p)		= { "apll", "gpll_armclk" };
-PNAME(mux_busclk_p)		= { "apll", "dpll_cpu", "gpll_cpu" };
-PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr" };
-PNAME(mux_pll_src_3plls_p)	= { "apll", "dpll", "gpll" };
-PNAME(mux_timer_p)		= { "xin24m", "pclk_peri_src" };
-
-PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p)	= { "apll", "dpll", "gpll" "usb480m" };
-
-PNAME(mux_mmc_src_p)	= { "apll", "dpll", "gpll", "xin24m" };
-PNAME(mux_i2s_pre_p)	= { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
-PNAME(mux_i2s_clkout_p)	= { "i2s_pre", "xin12m" };
-PNAME(mux_spdif_p)	= { "spdif_src", "spdif_frac", "xin12m" };
-PNAME(mux_uart0_p)	= { "uart0_src", "uart0_frac", "xin24m" };
-PNAME(mux_uart1_p)	= { "uart1_src", "uart1_frac", "xin24m" };
-PNAME(mux_uart2_p)	= { "uart2_src", "uart2_frac", "xin24m" };
-PNAME(mux_mac_p)	= { "mac_pll_src", "rmii_clkin" };
-PNAME(mux_dclk_p)	= { "dclk_lcdc", "dclk_cru" };
-
-static struct rockchip_pll_clock rk3036_pll_clks[] __initdata = {
-	[apll] = PLL(pll_rk3036, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
-		     RK2928_MODE_CON, 0, 5, 0, rk3036_pll_rates),
-	[dpll] = PLL(pll_rk3036, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4),
-		     RK2928_MODE_CON, 4, 4, 0, NULL),
-	[gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12),
-		     RK2928_MODE_CON, 12, 6, ROCKCHIP_PLL_SYNC_RATE, rk3036_pll_rates),
-};
-
-#define MFLAGS CLK_MUX_HIWORD_MASK
-#define DFLAGS CLK_DIVIDER_HIWORD_MASK
-#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
-
-static struct rockchip_clk_branch rk3036_uart0_fracmux __initdata =
-	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3036_uart1_fracmux __initdata =
-	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3036_uart2_fracmux __initdata =
-	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3036_i2s_fracmux __initdata =
-	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3036_spdif_fracmux __initdata =
-	MUX(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
-			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
-	/*
-	 * Clock-Architecture Diagram 1
-	 */
-
-	GATE(0, "gpll_armclk", "gpll", CLK_IGNORE_UNUSED,
-			RK2928_CLKGATE_CON(0), 6, GFLAGS),
-
-	/*
-	 * Clock-Architecture Diagram 2
-	 */
-
-	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
-			RK2928_CLKGATE_CON(0), 2, GFLAGS),
-	GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
-			RK2928_CLKGATE_CON(0), 8, GFLAGS),
-	COMPOSITE_NOGATE(0, "ddrphy2x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
-
-	COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
-			RK2928_CLKGATE_CON(0), 7, GFLAGS),
-	COMPOSITE_NOMUX(0, "aclk_core_pre", "armclk", CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
-			RK2928_CLKGATE_CON(0), 7, GFLAGS),
-
-	GATE(0, "dpll_cpu", "dpll", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS),
-	GATE(0, "gpll_cpu", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS),
-	COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_busclk_p, 0,
-			RK2928_CLKSEL_CON(0), 14, 2, MFLAGS, 8, 5, DFLAGS),
-	GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
-			RK2928_CLKGATE_CON(0), 3, GFLAGS),
-	COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(1), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
-			RK2928_CLKGATE_CON(0), 5, GFLAGS),
-	COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_READ_ONLY,
-			RK2928_CLKGATE_CON(0), 4, GFLAGS),
-
-	COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS,
-			RK2928_CLKGATE_CON(2), 0, GFLAGS),
-
-	GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
-			RK2928_CLKGATE_CON(2), 1, GFLAGS),
-	DIV(0, "pclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
-	GATE(PCLK_PERI, "pclk_peri", "pclk_peri_src", 0,
-			RK2928_CLKGATE_CON(2), 3, GFLAGS),
-	DIV(0, "hclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
-	GATE(HCLK_PERI, "hclk_peri", "hclk_peri_src", 0,
-			RK2928_CLKGATE_CON(2), 2, GFLAGS),
-
-	COMPOSITE_NODIV(SCLK_TIMER0, "sclk_timer0", mux_timer_p, CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(2), 4, 1, MFLAGS,
-			RK2928_CLKGATE_CON(1), 0, GFLAGS),
-	COMPOSITE_NODIV(SCLK_TIMER1, "sclk_timer1", mux_timer_p, CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(2), 5, 1, MFLAGS,
-			RK2928_CLKGATE_CON(1), 1, GFLAGS),
-	COMPOSITE_NODIV(SCLK_TIMER2, "sclk_timer2", mux_timer_p, CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(2), 6, 1, MFLAGS,
-			RK2928_CLKGATE_CON(2), 4, GFLAGS),
-	COMPOSITE_NODIV(SCLK_TIMER3, "sclk_timer3", mux_timer_p, CLK_IGNORE_UNUSED,
-			RK2928_CLKSEL_CON(2), 7, 1, MFLAGS,
-			RK2928_CLKGATE_CON(2), 5, GFLAGS),
-
-	MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0,
-			RK2928_CLKSEL_CON(13), 10, 2, MFLAGS),
-	COMPOSITE_NOMUX(0, "uart0_src", "uart_pll_clk", 0,
-			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
-			RK2928_CLKGATE_CON(1), 8, GFLAGS),
-	COMPOSITE_NOMUX(0, "uart1_src", "uart_pll_clk", 0,
-			RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
-			RK2928_CLKGATE_CON(1), 10, GFLAGS),
-	COMPOSITE_NOMUX(0, "uart2_src", "uart_pll_clk", 0,
-			RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
-			RK2928_CLKGATE_CON(1), 12, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(17), 0,
-			RK2928_CLKGATE_CON(1), 9, GFLAGS,
-			&rk3036_uart0_fracmux),
-	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(18), 0,
-			RK2928_CLKGATE_CON(1), 11, GFLAGS,
-			&rk3036_uart1_fracmux),
-	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(19), 0,
-			RK2928_CLKGATE_CON(1), 13, GFLAGS,
-			&rk3036_uart2_fracmux),
-
-	COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
-			RK2928_CLKGATE_CON(3), 11, GFLAGS),
-
-	COMPOSITE(0, "aclk_hvec", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS,
-			RK2928_CLKGATE_CON(10), 6, GFLAGS),
-
-	COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,
-			RK2928_CLKGATE_CON(1), 4, GFLAGS),
-	COMPOSITE(0, "hclk_disp_pre", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS,
-			RK2928_CLKGATE_CON(0), 11, GFLAGS),
-	COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS,
-			RK2928_CLKGATE_CON(3), 2, GFLAGS),
-
-	COMPOSITE_NODIV(0, "sclk_sdmmc_src", mux_mmc_src_p, 0,
-			RK2928_CLKSEL_CON(12), 8, 2, MFLAGS,
-			RK2928_CLKGATE_CON(2), 11, GFLAGS),
-	DIV(SCLK_SDMMC, "sclk_sdmmc", "sclk_sdmmc_src", 0,
-			RK2928_CLKSEL_CON(11), 0, 7, DFLAGS),
-
-	COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
-			RK2928_CLKSEL_CON(12), 10, 2, MFLAGS,
-			RK2928_CLKGATE_CON(2), 13, GFLAGS),
-	DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
-			RK2928_CLKSEL_CON(11), 8, 7, DFLAGS),
-
-	COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
-			RK2928_CLKSEL_CON(12), 12, 2, MFLAGS, 0, 7, DFLAGS,
-			RK2928_CLKGATE_CON(2), 14, GFLAGS),
-
-	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK3036_SDMMC_CON0, 1),
-	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3036_SDMMC_CON1, 0),
-
-	MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RK3036_SDIO_CON0, 1),
-	MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RK3036_SDIO_CON1, 0),
-
-	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK3036_EMMC_CON0,  1),
-	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK3036_EMMC_CON1,  0),
-
-	COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS,
-			RK2928_CLKGATE_CON(0), 9, GFLAGS),
-	COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(7), 0,
-			RK2928_CLKGATE_CON(0), 10, GFLAGS,
-			&rk3036_i2s_fracmux),
-	COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_clkout", mux_i2s_clkout_p, 0,
-			RK2928_CLKSEL_CON(3), 12, 1, MFLAGS,
-			RK2928_CLKGATE_CON(0), 13, GFLAGS),
-	GATE(SCLK_I2S, "sclk_i2s", "i2s_pre", CLK_SET_RATE_PARENT,
-			RK2928_CLKGATE_CON(0), 14, GFLAGS),
-
-	COMPOSITE(0, "spdif_src", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(5), 10, 2, MFLAGS, 0, 7, DFLAGS,
-			RK2928_CLKGATE_CON(2), 10, GFLAGS),
-	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0,
-			RK2928_CLKSEL_CON(9), 0,
-			RK2928_CLKGATE_CON(2), 12, GFLAGS,
-			&rk3036_spdif_fracmux),
-
-	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin12m", CLK_IGNORE_UNUSED,
-			RK2928_CLKGATE_CON(1), 5, GFLAGS),
-
-	COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(34), 8, 2, MFLAGS, 0, 5, DFLAGS,
-			RK2928_CLKGATE_CON(3), 13, GFLAGS),
-
-	COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 7, DFLAGS,
-			RK2928_CLKGATE_CON(2), 9, GFLAGS),
-
-	COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS,
-			RK2928_CLKGATE_CON(10), 4, GFLAGS),
-
-	COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_apll_dpll_gpll_usb480m_p, 0,
-			RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS,
-			RK2928_CLKGATE_CON(10), 5, GFLAGS),
-
-	MUX(SCLK_MACPLL, "mac_pll_pre", mux_pll_src_3plls_p, 0,
-			RK2928_CLKSEL_CON(21), 0, 2, MFLAGS),
-	DIV(0, "mac_pll_src", "mac_pll_pre", 0,
-			RK2928_CLKSEL_CON(21), 9, 5, DFLAGS),
-
-	MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(21), 3, 1, MFLAGS),
-
-	COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0,
-			RK2928_CLKSEL_CON(21), 4, 5, DFLAGS,
-			RK2928_CLKGATE_CON(2), 6, GFLAGS),
-
-	MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0,
-			RK2928_CLKSEL_CON(31), 0, 1, MFLAGS),
-
-	/*
-	 * Clock-Architecture Diagram 3
-	 */
-
-	/* aclk_cpu gates */
-	GATE(0, "sclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 12, GFLAGS),
-	GATE(0, "aclk_strc_sys", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS),
-
-	/* hclk_cpu gates */
-	GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 6, GFLAGS),
-
-	/* pclk_cpu gates */
-	GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS),
-	GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS),
-	GATE(PCLK_ACODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
-	GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS),
-
-	/* aclk_vio gates */
-	GATE(ACLK_VIO, "aclk_vio", "aclk_disp1_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 13, GFLAGS),
-	GATE(ACLK_LCDC, "aclk_lcdc", "aclk_disp1_pre", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
-
-	GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS),
-	GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS),
-
-	/* hclk_video gates */
-	GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS),
-
-	/* xin24m gates */
-	GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK2928_CLKGATE_CON(10), 0, GFLAGS),
-	GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK2928_CLKGATE_CON(10), 1, GFLAGS),
-
-	/* aclk_peri gates */
-	GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 3, GFLAGS),
-	GATE(0, "aclk_cpu_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS),
-	GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS),
-	GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15, GFLAGS),
-
-	/* hclk_peri gates */
-	GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS),
-	GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS),
-	GATE(0, "hclk_peri_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS),
-	GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS),
-	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS),
-	GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS),
-	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS),
-	GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS),
-	GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS),
-	GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
-	GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS),
-	GATE(HCLK_MAC, "hclk_mac", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15, GFLAGS),
-
-	/* pclk_peri gates */
-	GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS),
-	GATE(0, "pclk_efuse", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS),
-	GATE(PCLK_TIMER, "pclk_timer", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS),
-	GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS),
-	GATE(PCLK_SPI, "pclk_spi", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS),
-	GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS),
-	GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
-	GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
-	GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS),
-	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
-	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS),
-	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
-	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
-	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
-	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
-};
-
-static const char *const rk3036_critical_clocks[] __initconst = {
-	"aclk_cpu",
-	"aclk_peri",
-	"hclk_peri",
-	"pclk_peri",
-	"uart_pll_clk",
-};
-
-static void __init rk3036_clk_init(struct device_node *np)
-{
-	void __iomem *reg_base;
-	struct clk *clk;
-
-	reg_base = of_iomap(np, 0);
-	if (!reg_base) {
-		pr_err("%s: could not map cru region\n", __func__);
-		return;
-	}
-
-	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
-
-	/* xin12m is created by an cru-internal divider */
-	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock xin12m: %ld\n",
-			__func__, PTR_ERR(clk));
-
-	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock usb480m: %ld\n",
-			__func__, PTR_ERR(clk));
-
-	clk = clk_register_fixed_factor(NULL, "ddrphy", "ddrphy2x", 0, 1, 2);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock ddrphy: %ld\n",
-			__func__, PTR_ERR(clk));
-
-	clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
-					"aclk_vcodec", 0, 1, 4);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
-			__func__, PTR_ERR(clk));
-
-	clk = clk_register_fixed_factor(NULL, "sclk_macref_out",
-					"hclk_peri_src", 0, 1, 2);
-	if (IS_ERR(clk))
-		pr_warn("%s: could not register clock sclk_macref_out: %ld\n",
-			__func__, PTR_ERR(clk));
-
-	rockchip_clk_register_plls(rk3036_pll_clks,
-				   ARRAY_SIZE(rk3036_pll_clks),
-				   RK3036_GRF_SOC_STATUS0);
-	rockchip_clk_register_branches(rk3036_clk_branches,
-				  ARRAY_SIZE(rk3036_clk_branches));
-	rockchip_clk_protect_critical(rk3036_critical_clocks,
-				      ARRAY_SIZE(rk3036_critical_clocks));
-
-	rockchip_clk_register_armclk(ARMCLK, "armclk",
-			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
-			&rk3036_cpuclk_data, rk3036_cpuclk_rates,
-			ARRAY_SIZE(rk3036_cpuclk_rates));
-
-	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
-				  ROCKCHIP_SOFTRST_HIWORD_MASK);
-
-	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST);
-}
-CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init);
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index f23cef0..fe728f8 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -247,30 +247,6 @@
 	{ /* sentinel */ },
 };
 
-static struct rockchip_clk_branch common_hsadc_out_fracmux __initdata =
-	MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
-			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS);
-
-static struct rockchip_clk_branch common_spdif_fracmux __initdata =
-	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch common_uart0_fracmux __initdata =
-	MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
-			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch common_uart1_fracmux __initdata =
-	MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
-			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch common_uart2_fracmux __initdata =
-	MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
-			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch common_uart3_fracmux __initdata =
-	MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
-			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS);
-
 static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	/*
 	 * Clock-Architecture Diagram 2
@@ -359,10 +335,11 @@
 	COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0,
 			RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
 			RK2928_CLKGATE_CON(2), 6, GFLAGS),
-	COMPOSITE_FRACMUX(0, "hsadc_frac", "hsadc_src", 0,
+	COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
 			RK2928_CLKSEL_CON(23), 0,
-			RK2928_CLKGATE_CON(2), 7, GFLAGS,
-			&common_hsadc_out_fracmux),
+			RK2928_CLKGATE_CON(2), 7, GFLAGS),
+	MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
+			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
 	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
 			RK2928_CLKSEL_CON(22), 7, IFLAGS),
 
@@ -373,10 +350,11 @@
 	COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 13, GFLAGS),
-	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_pll", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRAC(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(9), 0,
-			RK2928_CLKGATE_CON(0), 14, GFLAGS,
-			&common_spdif_fracmux),
+			RK2928_CLKGATE_CON(0), 14, GFLAGS),
+	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
 
 	/*
 	 * Clock-Architecture Diagram 4
@@ -407,31 +385,35 @@
 	COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 8, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", 0,
+	COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0,
 			RK2928_CLKSEL_CON(17), 0,
-			RK2928_CLKGATE_CON(1), 9, GFLAGS,
-			&common_uart0_fracmux),
+			RK2928_CLKGATE_CON(1), 9, GFLAGS),
+	MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
+			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 10, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", 0,
+	COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0,
 			RK2928_CLKSEL_CON(18), 0,
-			RK2928_CLKGATE_CON(1), 11, GFLAGS,
-			&common_uart1_fracmux),
+			RK2928_CLKGATE_CON(1), 11, GFLAGS),
+	MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
+			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 12, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", 0,
+	COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0,
 			RK2928_CLKSEL_CON(19), 0,
-			RK2928_CLKGATE_CON(1), 13, GFLAGS,
-			&common_uart2_fracmux),
+			RK2928_CLKGATE_CON(1), 13, GFLAGS),
+	MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
+			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 14, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", 0,
+	COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0,
 			RK2928_CLKSEL_CON(20), 0,
-			RK2928_CLKGATE_CON(1), 15, GFLAGS,
-			&common_uart3_fracmux),
+			RK2928_CLKGATE_CON(1), 15, GFLAGS),
+	MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
+			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS),
 
 	GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS),
 
@@ -541,18 +523,6 @@
 	{ /* sentinel */ },
 };
 
-static struct rockchip_clk_branch rk3066a_i2s0_fracmux __initdata =
-	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
-			RK2928_CLKSEL_CON(2), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3066a_i2s1_fracmux __initdata =
-	MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
-			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3066a_i2s2_fracmux __initdata =
-	MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
-			RK2928_CLKSEL_CON(4), 8, 2, MFLAGS);
-
 static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
 	DIVTBL(0, "aclk_cpu_pre", "armclk", 0,
 			RK2928_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, div_aclk_cpu_t),
@@ -614,24 +584,27 @@
 	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 7, GFLAGS),
-	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
+	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
 			RK2928_CLKSEL_CON(6), 0,
-			RK2928_CLKGATE_CON(0), 8, GFLAGS,
-			&rk3066a_i2s0_fracmux),
+			RK2928_CLKGATE_CON(0), 8, GFLAGS),
+	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+			RK2928_CLKSEL_CON(2), 8, 2, MFLAGS),
 	COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 9, GFLAGS),
-	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", 0,
+	COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0,
 			RK2928_CLKSEL_CON(7), 0,
-			RK2928_CLKGATE_CON(0), 10, GFLAGS,
-			&rk3066a_i2s1_fracmux),
+			RK2928_CLKGATE_CON(0), 10, GFLAGS),
+	MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
 	COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 11, GFLAGS),
-	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", 0,
+	COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0,
 			RK2928_CLKSEL_CON(8), 0,
-			RK2928_CLKGATE_CON(0), 12, GFLAGS,
-			&rk3066a_i2s2_fracmux),
+			RK2928_CLKGATE_CON(0), 12, GFLAGS),
+	MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
+			RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
 
 	GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
 	GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
@@ -665,10 +638,6 @@
 PNAME(mux_hsicphy_p)		= { "sclk_otgphy0", "sclk_otgphy1",
 				    "gpll", "cpll" };
 
-static struct rockchip_clk_branch rk3188_i2s0_fracmux __initdata =
-	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
-			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
-
 static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED,
 			RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
@@ -722,10 +691,11 @@
 	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 9, GFLAGS),
-	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
+	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
 			RK2928_CLKSEL_CON(7), 0,
-			RK2928_CLKGATE_CON(0), 10, GFLAGS,
-			&rk3188_i2s0_fracmux),
+			RK2928_CLKGATE_CON(0), 10, GFLAGS),
+	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
 
 	GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
 	GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index a990422..9040878 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -225,38 +225,6 @@
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
 #define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
 
-static struct rockchip_clk_branch rk3288_i2s_fracmux __initdata =
-	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(4), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3288_spdif_fracmux __initdata =
-	MUX(0, "spdif_mux", mux_spdif_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(5), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3288_spdif_8ch_fracmux __initdata =
-	MUX(0, "spdif_8ch_mux", mux_spdif_8ch_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(40), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3288_uart0_fracmux __initdata =
-	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(13), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3288_uart1_fracmux __initdata =
-	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(14), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3288_uart2_fracmux __initdata =
-	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(15), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3288_uart3_fracmux __initdata =
-	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(16), 8, 2, MFLAGS);
-
-static struct rockchip_clk_branch rk3288_uart4_fracmux __initdata =
-	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(3), 8, 2, MFLAGS);
-
 static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	/*
 	 * Clock-Architecture Diagram 1
@@ -336,10 +304,11 @@
 	COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(4), 1, GFLAGS),
-	COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(8), 0,
-			RK3288_CLKGATE_CON(4), 2, GFLAGS,
-			&rk3288_i2s_fracmux),
+			RK3288_CLKGATE_CON(4), 2, GFLAGS),
+	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
 	COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0,
 			RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
 			RK3288_CLKGATE_CON(4), 0, GFLAGS),
@@ -348,23 +317,23 @@
 
 	MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(5), 15, 1, MFLAGS),
-	COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0,
 			RK3288_CLKSEL_CON(5), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(4), 4, GFLAGS),
-	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
 			RK3288_CLKSEL_CON(9), 0,
-			RK3288_CLKGATE_CON(4), 5, GFLAGS,
-			&rk3288_spdif_fracmux),
-	GATE(SCLK_SPDIF, "sclk_spdif", "spdif_mux", CLK_SET_RATE_PARENT,
+			RK3288_CLKGATE_CON(4), 5, GFLAGS),
+	COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
+			RK3288_CLKSEL_CON(5), 8, 2, MFLAGS,
 			RK3288_CLKGATE_CON(4), 6, GFLAGS),
-	COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0,
 			RK3288_CLKSEL_CON(40), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(4), 7, GFLAGS),
-	COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_pre", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
 			RK3288_CLKSEL_CON(41), 0,
-			RK3288_CLKGATE_CON(4), 8, GFLAGS,
-			&rk3288_spdif_8ch_fracmux),
-	GATE(SCLK_SPDIF8CH, "sclk_spdif_8ch", "spdif_8ch_mux", CLK_SET_RATE_PARENT,
+			RK3288_CLKGATE_CON(4), 8, GFLAGS),
+	COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
+			RK3288_CLKSEL_CON(40), 8, 2, MFLAGS,
 			RK3288_CLKGATE_CON(4), 9, GFLAGS),
 
 	GATE(0, "sclk_acc_efuse", "xin24m", 0,
@@ -567,40 +536,45 @@
 	COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p, 0,
 			RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 8, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(17), 0,
-			RK3288_CLKGATE_CON(1), 9, GFLAGS,
-			&rk3288_uart0_fracmux),
+			RK3288_CLKGATE_CON(1), 9, GFLAGS),
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
 	MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 10, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(18), 0,
-			RK3288_CLKGATE_CON(1), 11, GFLAGS,
-			&rk3288_uart1_fracmux),
+			RK3288_CLKGATE_CON(1), 11, GFLAGS),
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 12, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(19), 0,
-			RK3288_CLKGATE_CON(1), 13, GFLAGS,
-			&rk3288_uart2_fracmux),
+			RK3288_CLKGATE_CON(1), 13, GFLAGS),
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 14, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(20), 0,
-			RK3288_CLKGATE_CON(1), 15, GFLAGS,
-			&rk3288_uart3_fracmux),
+			RK3288_CLKGATE_CON(1), 15, GFLAGS),
+	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(2), 12, GFLAGS),
-	COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(7), 0,
-			RK3288_CLKGATE_CON(2), 13, GFLAGS,
-			&rk3288_uart4_fracmux),
+			RK3288_CLKGATE_CON(2), 13, GFLAGS),
+	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
+			RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
 
 	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index aa47d16..9b6c818 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -109,82 +109,22 @@
 	return ERR_PTR(-ENOMEM);
 }
 
-struct rockchip_clk_frac {
-	struct notifier_block			clk_nb;
-	struct clk_fractional_divider		div;
-	struct clk_gate				gate;
-
-	struct clk_mux				mux;
-	const struct clk_ops			*mux_ops;
-	int					mux_frac_idx;
-
-	bool					rate_change_remuxed;
-	int					rate_change_idx;
-};
-
-#define to_rockchip_clk_frac_nb(nb) \
-			container_of(nb, struct rockchip_clk_frac, clk_nb)
-
-static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
-					 unsigned long event, void *data)
-{
-	struct clk_notifier_data *ndata = data;
-	struct rockchip_clk_frac *frac = to_rockchip_clk_frac_nb(nb);
-	struct clk_mux *frac_mux = &frac->mux;
-	int ret = 0;
-
-	pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
-		 __func__, event, ndata->old_rate, ndata->new_rate);
-	if (event == PRE_RATE_CHANGE) {
-		frac->rate_change_idx = frac->mux_ops->get_parent(&frac_mux->hw);
-		if (frac->rate_change_idx != frac->mux_frac_idx) {
-			frac->mux_ops->set_parent(&frac_mux->hw, frac->mux_frac_idx);
-			frac->rate_change_remuxed = 1;
-		}
-	} else if (event == POST_RATE_CHANGE) {
-		/*
-		 * The POST_RATE_CHANGE notifier runs directly after the
-		 * divider clock is set in clk_change_rate, so we'll have
-		 * remuxed back to the original parent before clk_change_rate
-		 * reaches the mux itself.
-		 */
-		if (frac->rate_change_remuxed) {
-			frac->mux_ops->set_parent(&frac_mux->hw, frac->rate_change_idx);
-			frac->rate_change_remuxed = 0;
-		}
-	}
-
-	return notifier_from_errno(ret);
-}
-
 static struct clk *rockchip_clk_register_frac_branch(const char *name,
 		const char *const *parent_names, u8 num_parents,
 		void __iomem *base, int muxdiv_offset, u8 div_flags,
 		int gate_offset, u8 gate_shift, u8 gate_flags,
-		unsigned long flags, struct rockchip_clk_branch *child,
-		spinlock_t *lock)
+		unsigned long flags, spinlock_t *lock)
 {
-	struct rockchip_clk_frac *frac;
 	struct clk *clk;
 	struct clk_gate *gate = NULL;
 	struct clk_fractional_divider *div = NULL;
 	const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
 
-	if (muxdiv_offset < 0)
-		return ERR_PTR(-EINVAL);
-
-	if (child && child->branch_type != branch_mux) {
-		pr_err("%s: fractional child clock for %s can only be a mux\n",
-		       __func__, name);
-		return ERR_PTR(-EINVAL);
-	}
-
-	frac = kzalloc(sizeof(*frac), GFP_KERNEL);
-	if (!frac)
-		return ERR_PTR(-ENOMEM);
-
 	if (gate_offset >= 0) {
-		gate = &frac->gate;
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate)
+			return ERR_PTR(-ENOMEM);
+
 		gate->flags = gate_flags;
 		gate->reg = base + gate_offset;
 		gate->bit_idx = gate_shift;
@@ -192,7 +132,13 @@
 		gate_ops = &clk_gate_ops;
 	}
 
-	div = &frac->div;
+	if (muxdiv_offset < 0)
+		return ERR_PTR(-EINVAL);
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
 	div->flags = div_flags;
 	div->reg = base + muxdiv_offset;
 	div->mshift = 16;
@@ -208,61 +154,7 @@
 				     NULL, NULL,
 				     &div->hw, div_ops,
 				     gate ? &gate->hw : NULL, gate_ops,
-				     flags | CLK_SET_RATE_UNGATE);
-	if (IS_ERR(clk)) {
-		kfree(frac);
-		return clk;
-	}
-
-	if (child) {
-		struct clk_mux *frac_mux = &frac->mux;
-		struct clk_init_data init;
-		struct clk *mux_clk;
-		int i, ret;
-
-		frac->mux_frac_idx = -1;
-		for (i = 0; i < child->num_parents; i++) {
-			if (!strcmp(name, child->parent_names[i])) {
-				pr_debug("%s: found fractional parent in mux at pos %d\n",
-					 __func__, i);
-				frac->mux_frac_idx = i;
-				break;
-			}
-		}
-
-		frac->mux_ops = &clk_mux_ops;
-		frac->clk_nb.notifier_call = rockchip_clk_frac_notifier_cb;
-
-		frac_mux->reg = base + child->muxdiv_offset;
-		frac_mux->shift = child->mux_shift;
-		frac_mux->mask = BIT(child->mux_width) - 1;
-		frac_mux->flags = child->mux_flags;
-		frac_mux->lock = lock;
-		frac_mux->hw.init = &init;
-
-		init.name = child->name;
-		init.flags = child->flags | CLK_SET_RATE_PARENT;
-		init.ops = frac->mux_ops;
-		init.parent_names = child->parent_names;
-		init.num_parents = child->num_parents;
-
-		mux_clk = clk_register(NULL, &frac_mux->hw);
-		if (IS_ERR(mux_clk))
-			return clk;
-
-		rockchip_clk_add_lookup(mux_clk, child->id);
-
-		/* notifier on the fraction divider to catch rate changes */
-		if (frac->mux_frac_idx >= 0) {
-			ret = clk_notifier_register(clk, &frac->clk_nb);
-			if (ret)
-				pr_err("%s: failed to register clock notifier for %s\n",
-						__func__, name);
-		} else {
-			pr_warn("%s: could not find %s as parent of %s, rate changes may not work\n",
-				__func__, name, child->name);
-		}
-	}
+				     flags);
 
 	return clk;
 }
@@ -366,8 +258,7 @@
 				list->parent_names, list->num_parents,
 				reg_base, list->muxdiv_offset, list->div_flags,
 				list->gate_offset, list->gate_shift,
-				list->gate_flags, flags, list->child,
-				&clk_lock);
+				list->gate_flags, flags, &clk_lock);
 			break;
 		case branch_gate:
 			flags |= CLK_SET_RATE_PARENT;
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index c527454..dc8ecb2 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -2,9 +2,6 @@
  * Copyright (c) 2014 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
  *
- * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
- * Author: Xing Zheng <zhengxing@rock-chips.com>
- *
  * based on
  *
  * samsung/clk.h
@@ -33,7 +30,7 @@
 #define HIWORD_UPDATE(val, mask, shift) \
 		((val) << (shift) | (mask) << ((shift) + 16))
 
-/* register positions shared by RK2928, RK3036, RK3066 and RK3188 */
+/* register positions shared by RK2928, RK3066 and RK3188 */
 #define RK2928_PLL_CON(x)		((x) * 0x4)
 #define RK2928_MODE_CON		0x40
 #define RK2928_CLKSEL_CON(x)	((x) * 0x4 + 0x44)
@@ -43,13 +40,6 @@
 #define RK2928_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
 #define RK2928_MISC_CON		0x134
 
-#define RK3036_SDMMC_CON0		0x144
-#define RK3036_SDMMC_CON1		0x148
-#define RK3036_SDIO_CON0		0x14c
-#define RK3036_SDIO_CON1		0x150
-#define RK3036_EMMC_CON0		0x154
-#define RK3036_EMMC_CON1		0x158
-
 #define RK3288_PLL_CON(x)		RK2928_PLL_CON(x)
 #define RK3288_MODE_CON			0x50
 #define RK3288_CLKSEL_CON(x)		((x) * 0x4 + 0x60)
@@ -84,22 +74,9 @@
 #define RK3368_EMMC_CON1		0x41c
 
 enum rockchip_pll_type {
-	pll_rk3036,
 	pll_rk3066,
 };
 
-#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
-			_postdiv2, _dsmpd, _frac)		\
-{								\
-	.rate	= _rate##U,					\
-	.fbdiv = _fbdiv,					\
-	.postdiv1 = _postdiv1,					\
-	.refdiv = _refdiv,					\
-	.postdiv2 = _postdiv2,					\
-	.dsmpd = _dsmpd,					\
-	.frac = _frac,						\
-}
-
 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no)	\
 {						\
 	.rate	= _rate##U,			\
@@ -124,13 +101,6 @@
 	unsigned int nf;
 	unsigned int no;
 	unsigned int nb;
-	/* for RK3036 */
-	unsigned int fbdiv;
-	unsigned int postdiv1;
-	unsigned int refdiv;
-	unsigned int postdiv2;
-	unsigned int dsmpd;
-	unsigned int frac;
 };
 
 /**
@@ -265,7 +235,6 @@
 	int				gate_offset;
 	u8				gate_shift;
 	u8				gate_flags;
-	struct rockchip_clk_branch	*child;
 };
 
 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
@@ -400,24 +369,6 @@
 		.gate_flags	= gf,				\
 	}
 
-#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \
-	{							\
-		.id		= _id,				\
-		.branch_type	= branch_fraction_divider,	\
-		.name		= cname,			\
-		.parent_names	= (const char *[]){ pname },	\
-		.num_parents	= 1,				\
-		.flags		= f,				\
-		.muxdiv_offset	= mo,				\
-		.div_shift	= 16,				\
-		.div_width	= 16,				\
-		.div_flags	= df,				\
-		.gate_offset	= go,				\
-		.gate_shift	= gs,				\
-		.gate_flags	= gf,				\
-		.child		= ch,				\
-	}
-
 #define MUX(_id, cname, pnames, f, o, s, w, mf)			\
 	{							\
 		.id		= _id,				\
diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c
index 0214c65..97cb422 100644
--- a/drivers/clk/sunxi/clk-simple-gates.c
+++ b/drivers/clk/sunxi/clk-simple-gates.c
@@ -98,6 +98,8 @@
 	sunxi_simple_gates_setup(node, NULL, 0);
 }
 
+CLK_OF_DECLARE(sun4i_a10_gates, "allwinner,sun4i-a10-gates-clk",
+	       sunxi_simple_gates_init);
 CLK_OF_DECLARE(sun4i_a10_apb0, "allwinner,sun4i-a10-apb0-gates-clk",
 	       sunxi_simple_gates_init);
 CLK_OF_DECLARE(sun4i_a10_apb1, "allwinner,sun4i-a10-apb1-gates-clk",
diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c
index 8831e1a..11d8aa3 100644
--- a/drivers/clk/ti/clk-3xxx.c
+++ b/drivers/clk/ti/clk-3xxx.c
@@ -22,13 +22,6 @@
 
 #include "clock.h"
 
-/*
- * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
- * that are sourced by DPLL5, and both of these require this clock
- * to be at 120 MHz for proper operation.
- */
-#define DPLL5_FREQ_FOR_USBHOST		120000000
-
 #define OMAP3430ES2_ST_DSS_IDLE_SHIFT			1
 #define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT		5
 #define OMAP3430ES2_ST_SSI_IDLE_SHIFT			8
@@ -546,14 +539,21 @@
 	struct clk *dpll5_clk;
 	struct clk *dpll5_m2_clk;
 
+	/*
+	 * Errata sprz319f advisory 2.1 documents a USB host clock drift issue
+	 * that can be worked around using specially crafted dpll5 settings
+	 * with a dpll5_m2 divider set to 8. Set the dpll5 rate to 8x the USB
+	 * host clock rate, its .set_rate handler() will detect that frequency
+	 * and use the errata settings.
+	 */
 	dpll5_clk = clk_get(NULL, "dpll5_ck");
-	clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
+	clk_set_rate(dpll5_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST * 8);
 	clk_prepare_enable(dpll5_clk);
 
-	/* Program dpll5_m2_clk divider for no division */
+	/* Program dpll5_m2_clk divider */
 	dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
 	clk_prepare_enable(dpll5_m2_clk);
-	clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
+	clk_set_rate(dpll5_m2_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST);
 
 	clk_disable_unprepare(dpll5_m2_clk);
 	clk_disable_unprepare(dpll5_clk);
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 90f3f47..13c37f4 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -257,11 +257,20 @@
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 				    unsigned long parent_rate);
 
+/*
+ * OMAP3_DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
+ * that are sourced by DPLL5, and both of these require this clock
+ * to be at 120 MHz for proper operation.
+ */
+#define OMAP3_DPLL5_FREQ_FOR_USBHOST	120000000
+
 unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
 int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 			 unsigned long parent_rate);
 int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
 				    unsigned long parent_rate, u8 index);
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+			 unsigned long parent_rate);
 void omap3_clk_lock_dpll5(void);
 
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 5519b38..f9a5089 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -114,6 +114,18 @@
 	.round_rate	= &omap2_dpll_round_rate,
 };
 
+static const struct clk_ops omap3_dpll5_ck_ops = {
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.set_rate	= &omap3_dpll5_set_rate,
+	.set_parent	= &omap3_noncore_dpll_set_parent,
+	.set_rate_and_parent	= &omap3_noncore_dpll_set_rate_and_parent,
+	.determine_rate	= &omap3_noncore_dpll_determine_rate,
+	.round_rate	= &omap2_dpll_round_rate,
+};
+
 static const struct clk_ops omap3_dpll_per_ck_ops = {
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
@@ -461,7 +473,12 @@
 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	};
 
-	of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
+	if ((of_machine_is_compatible("ti,omap3630") ||
+	     of_machine_is_compatible("ti,omap36xx")) &&
+	    !strcmp(node->name, "dpll5_ck"))
+		of_ti_dpll_setup(node, &omap3_dpll5_ck_ops, &dd);
+	else
+		of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
 	       of_ti_omap3_dpll_setup);
diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c
index f4dec00..0e9119f 100644
--- a/drivers/clk/ti/dpll3xxx.c
+++ b/drivers/clk/ti/dpll3xxx.c
@@ -815,3 +815,70 @@
 	return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
 						      index);
 }
+
+/* Apply DM3730 errata sprz319 advisory 2.1. */
+static bool omap3_dpll5_apply_errata(struct clk_hw *hw,
+				     unsigned long parent_rate)
+{
+	struct omap3_dpll5_settings {
+		unsigned int rate, m, n;
+	};
+
+	static const struct omap3_dpll5_settings precomputed[] = {
+		/*
+		 * From DM3730 errata advisory 2.1, table 35 and 36.
+		 * The N value is increased by 1 compared to the tables as the
+		 * errata lists register values while last_rounded_field is the
+		 * real divider value.
+		 */
+		{ 12000000,  80,  0 + 1 },
+		{ 13000000, 443,  5 + 1 },
+		{ 19200000,  50,  0 + 1 },
+		{ 26000000, 443, 11 + 1 },
+		{ 38400000,  25,  0 + 1 }
+	};
+
+	const struct omap3_dpll5_settings *d;
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	struct dpll_data *dd;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(precomputed); ++i) {
+		if (parent_rate == precomputed[i].rate)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(precomputed))
+		return false;
+
+	d = &precomputed[i];
+
+	/* Update the M, N and rounded rate values and program the DPLL. */
+	dd = clk->dpll_data;
+	dd->last_rounded_m = d->m;
+	dd->last_rounded_n = d->n;
+	dd->last_rounded_rate = div_u64((u64)parent_rate * d->m, d->n);
+	omap3_noncore_dpll_program(clk, 0);
+
+	return true;
+}
+
+/**
+ * omap3_dpll5_set_rate - set rate for omap3 dpll5
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Set rate for the DPLL5 clock. Apply the sprz319 advisory 2.1 on OMAP36xx if
+ * the DPLL is used for USB host (detected through the requested rate).
+ */
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+			 unsigned long parent_rate)
+{
+	if (rate == OMAP3_DPLL5_FREQ_FOR_USBHOST * 8) {
+		if (omap3_dpll5_apply_errata(hw, parent_rate))
+			return 0;
+	}
+
+	return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
+}
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index ff44082..47f8aaf 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -482,6 +482,7 @@
 	if (mct_int_type == MCT_INT_SPI) {
 		if (evt->irq != -1)
 			disable_irq_nosync(evt->irq);
+		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
 	} else {
 		disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
 	}
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c
index 6f3719d..e84877a 100644
--- a/drivers/clocksource/sun4i_timer.c
+++ b/drivers/clocksource/sun4i_timer.c
@@ -123,12 +123,16 @@
 	.set_next_event = sun4i_clkevt_next_event,
 };
 
+static void sun4i_timer_clear_interrupt(void)
+{
+	writel(TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_ST_REG);
+}
 
 static irqreturn_t sun4i_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = (struct clock_event_device *)dev_id;
 
-	writel(0x1, timer_base + TIMER_IRQ_ST_REG);
+	sun4i_timer_clear_interrupt();
 	evt->event_handler(evt);
 
 	return IRQ_HANDLED;
@@ -193,6 +197,9 @@
 	/* Make sure timer is stopped before playing with interrupts */
 	sun4i_clkevt_time_stop(0);
 
+	/* clear timer0 interrupt */
+	sun4i_timer_clear_interrupt();
+
 	sun4i_clockevent.cpumask = cpu_possible_mask;
 	sun4i_clockevent.irq = irq;
 
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 75f63ef..91b05e2 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -112,6 +112,23 @@
 	  loading your cpufreq low-level hardware driver, using the
 	  'interactive' governor for latency-sensitive workloads.
 
+config CPU_FREQ_DEFAULT_GOV_SCHED
+	bool "sched"
+	select CPU_FREQ_GOV_SCHED
+	help
+	  Use the CPUfreq governor 'sched' as default. This scales
+	  cpu frequency using CPU utilization estimates from the
+	  scheduler.
+
+config CPU_FREQ_DEFAULT_GOV_SCHEDUTIL
+	bool "schedutil"
+	depends on SMP
+	select CPU_FREQ_GOV_SCHEDUTIL
+	select CPU_FREQ_GOV_PERFORMANCE
+	help
+	  Use the 'schedutil' CPUFreq governor by default. If unsure,
+	  have a look at the help section of that governor. The fallback
+	  governor will be 'performance'.
 endchoice
 
 config CPU_FREQ_GOV_PERFORMANCE
@@ -207,6 +224,36 @@
 
 	  If in doubt, say N.
 
+config CPU_FREQ_GOV_SCHED
+	bool "'sched' cpufreq governor"
+	depends on CPU_FREQ
+	depends on SMP
+	select CPU_FREQ_GOV_COMMON
+	help
+	  'sched' - this governor scales cpu frequency from the
+	  scheduler as a function of cpu capacity utilization. It does
+	  not evaluate utilization on a periodic basis (as ondemand
+	  does) but instead is event-driven by the scheduler.
+
+	  If in doubt, say N.
+
+config CPU_FREQ_GOV_SCHEDUTIL
+	bool "'schedutil' cpufreq policy governor"
+	depends on CPU_FREQ && SMP
+	select CPU_FREQ_GOV_ATTR_SET
+	select IRQ_WORK
+	help
+	  This governor makes decisions based on the utilization data provided
+	  by the scheduler.  It sets the CPU frequency to be proportional to
+	  the utilization/capacity ratio coming from the scheduler.  If the
+	  utilization is frequency-invariant, the new frequency is also
+	  proportional to the maximum available frequency.  If that is not the
+	  case, it is proportional to the current frequency of the CPU.  The
+	  frequency tipping point is at utilization/capacity equal to 80% in
+	  both cases.
+
+	  If in doubt, say N.
+
 comment "CPU frequency scaling drivers"
 
 config CPUFREQ_DT
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index b02ae14..04e6324 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -1,5 +1,5 @@
 # CPUfreq core
-obj-$(CONFIG_CPU_FREQ)			+= cpufreq.o freq_table.o
+obj-$(CONFIG_CPU_FREQ)			+= cpufreq.o freq_table.o cpufreq_governor_attr_set.o
 
 # CPUfreq stats
 obj-$(CONFIG_CPU_FREQ_STAT)             += cpufreq_stats.o
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index e4951271..620ab22 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -29,6 +29,9 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/tick.h>
+#ifdef CONFIG_SMP
+#include <linux/sched.h>
+#endif
 #include <trace/events/power.h>
 
 static LIST_HEAD(cpufreq_policy_list);
@@ -154,6 +157,12 @@
 }
 EXPORT_SYMBOL_GPL(have_governor_per_policy);
 
+bool cpufreq_driver_is_slow(void)
+{
+	return !(cpufreq_driver->flags & CPUFREQ_DRIVER_FAST);
+}
+EXPORT_SYMBOL_GPL(cpufreq_driver_is_slow);
+
 struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
 {
 	if (have_governor_per_policy())
@@ -347,6 +356,50 @@
 #endif
 }
 
+/*********************************************************************
+ *               FREQUENCY INVARIANT CPU CAPACITY                    *
+ *********************************************************************/
+
+static DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;
+static DEFINE_PER_CPU(unsigned long, max_freq_scale) = SCHED_CAPACITY_SCALE;
+
+static void
+scale_freq_capacity(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs)
+{
+	unsigned long cur = freqs ? freqs->new : policy->cur;
+	unsigned long scale = (cur << SCHED_CAPACITY_SHIFT) / policy->max;
+	struct cpufreq_cpuinfo *cpuinfo = &policy->cpuinfo;
+	int cpu;
+
+	pr_debug("cpus %*pbl cur/cur max freq %lu/%u kHz freq scale %lu\n",
+		 cpumask_pr_args(policy->cpus), cur, policy->max, scale);
+
+	for_each_cpu(cpu, policy->cpus)
+		per_cpu(freq_scale, cpu) = scale;
+
+	if (freqs)
+		return;
+
+	scale = (policy->max << SCHED_CAPACITY_SHIFT) / cpuinfo->max_freq;
+
+	pr_debug("cpus %*pbl cur max/max freq %u/%u kHz max freq scale %lu\n",
+		 cpumask_pr_args(policy->cpus), policy->max, cpuinfo->max_freq,
+		 scale);
+
+	for_each_cpu(cpu, policy->cpus)
+		per_cpu(max_freq_scale, cpu) = scale;
+}
+
+unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu)
+{
+	return per_cpu(freq_scale, cpu);
+}
+
+unsigned long cpufreq_scale_max_freq_capacity(int cpu)
+{
+	return per_cpu(max_freq_scale, cpu);
+}
+
 static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
 		struct cpufreq_freqs *freqs, unsigned int state)
 {
@@ -423,6 +476,9 @@
 void cpufreq_freq_transition_begin(struct cpufreq_policy *policy,
 		struct cpufreq_freqs *freqs)
 {
+#ifdef CONFIG_SMP
+	int cpu;
+#endif
 
 	/*
 	 * Catch double invocations of _begin() which lead to self-deadlock.
@@ -450,6 +506,12 @@
 
 	spin_unlock(&policy->transition_lock);
 
+	scale_freq_capacity(policy, freqs);
+#ifdef CONFIG_SMP
+	for_each_cpu(cpu, policy->cpus)
+		trace_cpu_capacity(capacity_curr_of(cpu), cpu);
+#endif
+
 	cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE);
 }
 EXPORT_SYMBOL_GPL(cpufreq_freq_transition_begin);
@@ -469,6 +531,38 @@
 }
 EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end);
 
+/**
+ * cpufreq_driver_resolve_freq - Map a target frequency to a driver-supported
+ * one.
+ * @target_freq: target frequency to resolve.
+ *
+ * The target to driver frequency mapping is cached in the policy.
+ *
+ * Return: Lowest driver-supported frequency greater than or equal to the
+ * given target_freq, subject to policy (min/max) and driver limitations.
+ */
+unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy,
+					 unsigned int target_freq)
+{
+	target_freq = clamp_val(target_freq, policy->min, policy->max);
+	policy->cached_target_freq = target_freq;
+
+	if (cpufreq_driver->target_index) {
+		int idx, rv;
+
+		rv = cpufreq_frequency_table_target(policy, policy->freq_table,
+						    target_freq,
+						    CPUFREQ_RELATION_L,
+						    &idx);
+		if (rv)
+			return target_freq;
+		policy->cached_resolved_idx = idx;
+		return policy->freq_table[idx].frequency;
+        }
+
+	return target_freq;
+}
+EXPORT_SYMBOL_GPL(cpufreq_driver_resolve_freq);
 
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
@@ -626,9 +720,11 @@
 					char *buf)
 {
 	unsigned int cur_freq = __cpufreq_get(policy);
-	if (!cur_freq)
-		return sprintf(buf, "<unknown>");
-	return sprintf(buf, "%u\n", cur_freq);
+
+	if (cur_freq)
+		return sprintf(buf, "%u\n", cur_freq);
+
+	return sprintf(buf, "<unknown>\n");
 }
 
 /**
@@ -1184,6 +1280,9 @@
 		for_each_cpu(j, policy->related_cpus)
 			per_cpu(cpufreq_cpu_data, j) = policy;
 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	} else {
+		policy->min = policy->user_policy.min;
+		policy->max = policy->user_policy.max;
 	}
 
 	if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
@@ -2126,6 +2225,8 @@
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
 			CPUFREQ_NOTIFY, new_policy);
 
+	scale_freq_capacity(new_policy, NULL);
+
 	policy->min = new_policy->min;
 	policy->max = new_policy->max;
 	trace_cpu_frequency_limits(policy->max, policy->min, policy->cpu);
@@ -2447,6 +2548,7 @@
 	if (!(cpufreq_driver->flags & CPUFREQ_STICKY) &&
 	    list_empty(&cpufreq_policy_list)) {
 		/* if all ->init() calls failed, unregister */
+		ret = -ENODEV;
 		pr_debug("%s: No CPU initialized for driver %s\n", __func__,
 			 driver_data->name);
 		goto err_if_unreg;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 1fa1deb..c395f91 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -212,8 +212,8 @@
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
-	/* cannot be lower than 11 otherwise freq will not fall */
-	if (ret != 1 || input < 11 || input > 100 ||
+	/* cannot be lower than 1 otherwise freq will not fall */
+	if (ret != 1 || input < 1 || input > 100 ||
 			input >= cs_tuners->up_threshold)
 		return -EINVAL;
 
diff --git a/drivers/cpufreq/cpufreq_governor_attr_set.c b/drivers/cpufreq/cpufreq_governor_attr_set.c
new file mode 100644
index 0000000..52841f8
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_governor_attr_set.c
@@ -0,0 +1,84 @@
+/*
+ * Abstract code for CPUFreq governor tunable sysfs attributes.
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "cpufreq_governor.h"
+
+static inline struct gov_attr_set *to_gov_attr_set(struct kobject *kobj)
+{
+	return container_of(kobj, struct gov_attr_set, kobj);
+}
+
+static inline struct governor_attr *to_gov_attr(struct attribute *attr)
+{
+	return container_of(attr, struct governor_attr, attr);
+}
+
+static ssize_t governor_show(struct kobject *kobj, struct attribute *attr,
+			     char *buf)
+{
+	struct governor_attr *gattr = to_gov_attr(attr);
+
+	return gattr->show(to_gov_attr_set(kobj), buf);
+}
+
+static ssize_t governor_store(struct kobject *kobj, struct attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct gov_attr_set *attr_set = to_gov_attr_set(kobj);
+	struct governor_attr *gattr = to_gov_attr(attr);
+	int ret;
+
+	mutex_lock(&attr_set->update_lock);
+	ret = attr_set->usage_count ? gattr->store(attr_set, buf, count) : -EBUSY;
+	mutex_unlock(&attr_set->update_lock);
+	return ret;
+}
+
+const struct sysfs_ops governor_sysfs_ops = {
+	.show	= governor_show,
+	.store	= governor_store,
+};
+EXPORT_SYMBOL_GPL(governor_sysfs_ops);
+
+void gov_attr_set_init(struct gov_attr_set *attr_set, struct list_head *list_node)
+{
+	INIT_LIST_HEAD(&attr_set->policy_list);
+	mutex_init(&attr_set->update_lock);
+	attr_set->usage_count = 1;
+	list_add(list_node, &attr_set->policy_list);
+}
+EXPORT_SYMBOL_GPL(gov_attr_set_init);
+
+void gov_attr_set_get(struct gov_attr_set *attr_set, struct list_head *list_node)
+{
+	mutex_lock(&attr_set->update_lock);
+	attr_set->usage_count++;
+	list_add(list_node, &attr_set->policy_list);
+	mutex_unlock(&attr_set->update_lock);
+}
+EXPORT_SYMBOL_GPL(gov_attr_set_get);
+
+unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *list_node)
+{
+	unsigned int count;
+
+	mutex_lock(&attr_set->update_lock);
+	list_del(list_node);
+	count = --attr_set->usage_count;
+	mutex_unlock(&attr_set->update_lock);
+	if (count)
+		return count;
+
+	kobject_put(&attr_set->kobj);
+	mutex_destroy(&attr_set->update_lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gov_attr_set_put);
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index f2929e6..889c9b8 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -312,13 +312,13 @@
 		pcpu->policy->governor_data;
 	u64 now;
 	u64 now_idle;
-	unsigned int delta_idle;
-	unsigned int delta_time;
+	u64 delta_idle;
+	u64 delta_time;
 	u64 active_time;
 
 	now_idle = get_cpu_idle_time(cpu, &now, tunables->io_is_busy);
-	delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle);
-	delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp);
+	delta_idle = (now_idle - pcpu->time_in_idle);
+	delta_time = (now - pcpu->time_in_idle_timestamp);
 
 	if (delta_time <= delta_idle)
 		active_time = 0;
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 4dbf1db..9cc8abd 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 
 static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
 static DEFINE_MUTEX(userspace_mutex);
@@ -31,6 +32,7 @@
 static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
 {
 	int ret = -EINVAL;
+	unsigned int *setspeed = policy->governor_data;
 
 	pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
 
@@ -38,6 +40,8 @@
 	if (!per_cpu(cpu_is_managed, policy->cpu))
 		goto err;
 
+	*setspeed = freq;
+
 	ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
  err:
 	mutex_unlock(&userspace_mutex);
@@ -49,19 +53,45 @@
 	return sprintf(buf, "%u\n", policy->cur);
 }
 
+static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
+{
+	unsigned int *setspeed;
+
+	setspeed = kzalloc(sizeof(*setspeed), GFP_KERNEL);
+	if (!setspeed)
+		return -ENOMEM;
+
+	policy->governor_data = setspeed;
+	return 0;
+}
+
 static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
 				   unsigned int event)
 {
+	unsigned int *setspeed = policy->governor_data;
 	unsigned int cpu = policy->cpu;
 	int rc = 0;
 
+	if (event == CPUFREQ_GOV_POLICY_INIT)
+		return cpufreq_userspace_policy_init(policy);
+
+	if (!setspeed)
+		return -EINVAL;
+
 	switch (event) {
+	case CPUFREQ_GOV_POLICY_EXIT:
+		mutex_lock(&userspace_mutex);
+		policy->governor_data = NULL;
+		kfree(setspeed);
+		mutex_unlock(&userspace_mutex);
+		break;
 	case CPUFREQ_GOV_START:
 		BUG_ON(!policy->cur);
 		pr_debug("started managing cpu %u\n", cpu);
 
 		mutex_lock(&userspace_mutex);
 		per_cpu(cpu_is_managed, cpu) = 1;
+		*setspeed = policy->cur;
 		mutex_unlock(&userspace_mutex);
 		break;
 	case CPUFREQ_GOV_STOP:
@@ -69,20 +99,23 @@
 
 		mutex_lock(&userspace_mutex);
 		per_cpu(cpu_is_managed, cpu) = 0;
+		*setspeed = 0;
 		mutex_unlock(&userspace_mutex);
 		break;
 	case CPUFREQ_GOV_LIMITS:
 		mutex_lock(&userspace_mutex);
-		pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz\n",
-			cpu, policy->min, policy->max,
-			policy->cur);
+		pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
+			cpu, policy->min, policy->max, policy->cur, *setspeed);
 
-		if (policy->max < policy->cur)
+		if (policy->max < *setspeed)
 			__cpufreq_driver_target(policy, policy->max,
 						CPUFREQ_RELATION_H);
-		else if (policy->min > policy->cur)
+		else if (policy->min > *setspeed)
 			__cpufreq_driver_target(policy, policy->min,
 						CPUFREQ_RELATION_L);
+		else
+			__cpufreq_driver_target(policy, *setspeed,
+						CPUFREQ_RELATION_L);
 		mutex_unlock(&userspace_mutex);
 		break;
 	}
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index f53b02a..7ff8b15 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -285,14 +285,14 @@
 	int min, hw_min, max, hw_max, cpu, range, adj_range;
 	u64 value, cap;
 
-	rdmsrl(MSR_HWP_CAPABILITIES, cap);
-	hw_min = HWP_LOWEST_PERF(cap);
-	hw_max = HWP_HIGHEST_PERF(cap);
-	range = hw_max - hw_min;
-
 	get_online_cpus();
 
 	for_each_online_cpu(cpu) {
+		rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
+		hw_min = HWP_LOWEST_PERF(cap);
+		hw_max = HWP_HIGHEST_PERF(cap);
+		range = hw_max - hw_min;
+
 		rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
 		adj_range = limits->min_perf_pct * range / 100;
 		min = hw_min + adj_range;
@@ -662,7 +662,7 @@
 			if (err)
 				goto skip_tar;
 
-			tdp_msr = MSR_CONFIG_TDP_NOMINAL + tdp_ctrl;
+			tdp_msr = MSR_CONFIG_TDP_NOMINAL + (tdp_ctrl & 0x3);
 			err = rdmsrl_safe(tdp_msr, &tdp_ratio);
 			if (err)
 				goto skip_tar;
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index cb50138..c4b0ef6 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -373,8 +373,14 @@
 	if (unlikely(rebooting) && new_index != get_nominal_index())
 		return 0;
 
-	if (!throttled)
+	if (!throttled) {
+		/* we don't want to be preempted while
+		 * checking if the CPU frequency has been throttled
+		 */
+		preempt_disable();
 		powernv_cpufreq_throttle_check(NULL);
+		preempt_enable();
+	}
 
 	freq_data.pstate_id = powernv_freqs[new_index].driver_data;
 
diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c
index d6d4257..5b2db3c 100644
--- a/drivers/cpufreq/s3c2416-cpufreq.c
+++ b/drivers/cpufreq/s3c2416-cpufreq.c
@@ -400,7 +400,6 @@
 	rate = clk_get_rate(s3c_freq->hclk);
 	if (rate < 133 * 1000 * 1000) {
 		pr_err("cpufreq: HCLK not at 133MHz\n");
-		clk_put(s3c_freq->hclk);
 		ret = -EINVAL;
 		goto err_armclk;
 	}
diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
index e342565e..1855b9e 100644
--- a/drivers/cpuidle/cpuidle-arm.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -135,6 +135,7 @@
 		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 		if (!dev) {
 			pr_err("Failed to allocate cpuidle device\n");
+			ret = -ENOMEM;
 			goto out_fail;
 		}
 		dev->cpu = cpu;
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 17a6dc0..1519716 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -192,7 +192,7 @@
 	}
 
 	/* Take note of the planned idle state. */
-	sched_idle_set_state(target_state);
+	sched_idle_set_state(target_state, index);
 
 	trace_cpu_idle_rcuidle(index, dev->cpu);
 	time_start = ktime_get();
@@ -205,7 +205,7 @@
 	trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
 
 	/* The cpu is no longer idle or about to enter idle. */
-	sched_idle_set_state(NULL);
+	sched_idle_set_state(NULL, -1);
 
 	if (broadcast) {
 		if (WARN_ON_ONCE(!irqs_disabled()))
@@ -214,7 +214,7 @@
 		tick_broadcast_exit();
 	}
 
-	if (!cpuidle_state_is_coupled(drv, entered_state))
+	if (!cpuidle_state_is_coupled(drv, index))
 		local_irq_enable();
 
 	diff = ktime_to_us(ktime_sub(time_end, time_start));
@@ -433,6 +433,8 @@
 	list_del(&dev->device_list);
 	per_cpu(cpuidle_devices, dev->cpu) = NULL;
 	module_put(drv->owner);
+
+	dev->registered = 0;
 }
 
 static void __cpuidle_device_init(struct cpuidle_device *dev)
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 22e4463..0846b39 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -178,7 +178,12 @@
 
 	/* for higher loadavg, we are more reluctant */
 
-	mult += 2 * get_loadavg(load);
+	/*
+	 * this doesn't work as intended - it is almost always 0, but can
+	 * sometimes, depending on workload, spike very high into the hundreds
+	 * even when the average cpu load is under 10%.
+	 */
+	/* mult += 2 * get_loadavg(); */
 
 	/* for IO wait tasks (per cpu!) we add 5x each */
 	mult += 10 * nr_iowaiters;
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index ea8189f..f3307fc 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -441,6 +441,9 @@
 			       OP_ALG_AAI_CTR_MOD128);
 	const bool is_rfc3686 = alg->caam.rfc3686;
 
+	if (!ctx->authsize)
+		return 0;
+
 	/* NULL encryption / decryption */
 	if (!ctx->enckeylen)
 		return aead_null_set_sh_desc(aead);
@@ -553,7 +556,10 @@
 
 	/* Read and write assoclen bytes */
 	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
-	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+	if (alg->caam.geniv)
+		append_math_add_imm_u32(desc, VARSEQOUTLEN, REG3, IMM, ivsize);
+	else
+		append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
 
 	/* Skip assoc data */
 	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
@@ -562,6 +568,14 @@
 	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
 			     KEY_VLF);
 
+	if (alg->caam.geniv) {
+		append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
+				LDST_SRCDST_BYTE_CONTEXT |
+				(ctx1_iv_off << LDST_OFFSET_SHIFT));
+		append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO |
+			    (ctx1_iv_off << MOVE_OFFSET_SHIFT) | ivsize);
+	}
+
 	/* Load Counter into CONTEXT1 reg */
 	if (is_rfc3686)
 		append_load_imm_u32(desc, be32_to_cpu(1), LDST_IMM |
@@ -614,7 +628,7 @@
 		keys_fit_inline = true;
 
 	/* aead_givencrypt shared descriptor */
-	desc = ctx->sh_desc_givenc;
+	desc = ctx->sh_desc_enc;
 
 	/* Note: Context registers are saved. */
 	init_sh_desc_key_aead(desc, ctx, keys_fit_inline, is_rfc3686);
@@ -645,13 +659,13 @@
 	append_operation(desc, ctx->class2_alg_type |
 			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
 
-	/* ivsize + cryptlen = seqoutlen - authsize */
-	append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
-
 	/* Read and write assoclen bytes */
 	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
 	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
 
+	/* ivsize + cryptlen = seqoutlen - authsize */
+	append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
 	/* Skip assoc data */
 	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
 
@@ -688,7 +702,9 @@
 
 	/* Will read cryptlen */
 	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-	aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | KEY_VLF |
+			     FIFOLD_TYPE_MSG1OUT2 | FIFOLD_TYPE_LASTBOTH);
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
 
 	/* Write ICV */
 	append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
@@ -697,7 +713,7 @@
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
-	if (dma_mapping_error(jrdev, ctx->sh_desc_givenc_dma)) {
+	if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
@@ -2147,7 +2163,7 @@
 
 	init_aead_job(req, edesc, all_contig, encrypt);
 
-	if (ivsize && (is_rfc3686 || !(alg->caam.geniv && encrypt)))
+	if (ivsize && ((is_rfc3686 && encrypt) || !alg->caam.geniv))
 		append_load_as_imm(desc, req->iv, ivsize,
 				   LDST_CLASS_1_CCB |
 				   LDST_SRCDST_BYTE_CONTEXT |
@@ -2534,20 +2550,6 @@
 	return ret;
 }
 
-static int aead_givdecrypt(struct aead_request *req)
-{
-	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-	unsigned int ivsize = crypto_aead_ivsize(aead);
-
-	if (req->cryptlen < ivsize)
-		return -EINVAL;
-
-	req->cryptlen -= ivsize;
-	req->assoclen += ivsize;
-
-	return aead_decrypt(req);
-}
-
 /*
  * allocate and map the ablkcipher extended descriptor for ablkcipher
  */
@@ -3207,7 +3209,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = AES_BLOCK_SIZE,
 			.maxauthsize = MD5_DIGEST_SIZE,
 		},
@@ -3253,7 +3255,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = AES_BLOCK_SIZE,
 			.maxauthsize = SHA1_DIGEST_SIZE,
 		},
@@ -3299,7 +3301,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = AES_BLOCK_SIZE,
 			.maxauthsize = SHA224_DIGEST_SIZE,
 		},
@@ -3345,7 +3347,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = AES_BLOCK_SIZE,
 			.maxauthsize = SHA256_DIGEST_SIZE,
 		},
@@ -3391,7 +3393,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = AES_BLOCK_SIZE,
 			.maxauthsize = SHA384_DIGEST_SIZE,
 		},
@@ -3437,7 +3439,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = AES_BLOCK_SIZE,
 			.maxauthsize = SHA512_DIGEST_SIZE,
 		},
@@ -3483,7 +3485,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES3_EDE_BLOCK_SIZE,
 			.maxauthsize = MD5_DIGEST_SIZE,
 		},
@@ -3531,7 +3533,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES3_EDE_BLOCK_SIZE,
 			.maxauthsize = SHA1_DIGEST_SIZE,
 		},
@@ -3579,7 +3581,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES3_EDE_BLOCK_SIZE,
 			.maxauthsize = SHA224_DIGEST_SIZE,
 		},
@@ -3627,7 +3629,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES3_EDE_BLOCK_SIZE,
 			.maxauthsize = SHA256_DIGEST_SIZE,
 		},
@@ -3675,7 +3677,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES3_EDE_BLOCK_SIZE,
 			.maxauthsize = SHA384_DIGEST_SIZE,
 		},
@@ -3723,7 +3725,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES3_EDE_BLOCK_SIZE,
 			.maxauthsize = SHA512_DIGEST_SIZE,
 		},
@@ -3769,7 +3771,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES_BLOCK_SIZE,
 			.maxauthsize = MD5_DIGEST_SIZE,
 		},
@@ -3815,7 +3817,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES_BLOCK_SIZE,
 			.maxauthsize = SHA1_DIGEST_SIZE,
 		},
@@ -3861,7 +3863,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES_BLOCK_SIZE,
 			.maxauthsize = SHA224_DIGEST_SIZE,
 		},
@@ -3907,7 +3909,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES_BLOCK_SIZE,
 			.maxauthsize = SHA256_DIGEST_SIZE,
 		},
@@ -3953,7 +3955,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES_BLOCK_SIZE,
 			.maxauthsize = SHA384_DIGEST_SIZE,
 		},
@@ -3999,7 +4001,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = DES_BLOCK_SIZE,
 			.maxauthsize = SHA512_DIGEST_SIZE,
 		},
@@ -4048,7 +4050,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = CTR_RFC3686_IV_SIZE,
 			.maxauthsize = MD5_DIGEST_SIZE,
 		},
@@ -4099,7 +4101,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = CTR_RFC3686_IV_SIZE,
 			.maxauthsize = SHA1_DIGEST_SIZE,
 		},
@@ -4150,7 +4152,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = CTR_RFC3686_IV_SIZE,
 			.maxauthsize = SHA224_DIGEST_SIZE,
 		},
@@ -4201,7 +4203,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = CTR_RFC3686_IV_SIZE,
 			.maxauthsize = SHA256_DIGEST_SIZE,
 		},
@@ -4252,7 +4254,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = CTR_RFC3686_IV_SIZE,
 			.maxauthsize = SHA384_DIGEST_SIZE,
 		},
@@ -4303,7 +4305,7 @@
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
 			.encrypt = aead_encrypt,
-			.decrypt = aead_givdecrypt,
+			.decrypt = aead_decrypt,
 			.ivsize = CTR_RFC3686_IV_SIZE,
 			.maxauthsize = SHA512_DIGEST_SIZE,
 		},
@@ -4542,6 +4544,15 @@
 		if (!aes_inst && (alg_sel == OP_ALG_ALGSEL_AES))
 				continue;
 
+		/*
+		 * Check support for AES modes not available
+		 * on LP devices.
+		 */
+		if ((cha_vid & CHA_ID_LS_AES_MASK) == CHA_ID_LS_AES_LP)
+			if ((alg->class1_alg_type & OP_ALG_AAI_MASK) ==
+			     OP_ALG_AAI_XTS)
+				continue;
+
 		t_alg = caam_alg_alloc(alg);
 		if (IS_ERR(t_alg)) {
 			err = PTR_ERR(t_alg);
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 49106ea..99d5e11 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -1873,6 +1873,7 @@
 			 template->name);
 		snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
 			 template->driver_name);
+		t_alg->ahash_alg.setkey = NULL;
 	}
 	alg->cra_module = THIS_MODULE;
 	alg->cra_init = caam_hash_cra_init;
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 69d4a13..53e6145 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -278,7 +278,8 @@
 			/* Try to run it through DECO0 */
 			ret = run_descriptor_deco0(ctrldev, desc, &status);
 
-			if (ret || status) {
+			if (ret ||
+			    (status && status != JRSTA_SSRC_JUMP_HALT_CC)) {
 				dev_err(ctrldev,
 					"Failed to deinstantiate RNG4 SH%d\n",
 					sh_idx);
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index f7e0d8d..8f50a02 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -248,7 +248,7 @@
 struct device *caam_jr_alloc(void)
 {
 	struct caam_drv_private_jr *jrpriv, *min_jrpriv = NULL;
-	struct device *dev = NULL;
+	struct device *dev = ERR_PTR(-ENODEV);
 	int min_tfm_cnt	= INT_MAX;
 	int tfm_cnt;
 
diff --git a/drivers/crypto/ccp/ccp-crypto-aes-xts.c b/drivers/crypto/ccp/ccp-crypto-aes-xts.c
index 52c7395..0d0d452 100644
--- a/drivers/crypto/ccp/ccp-crypto-aes-xts.c
+++ b/drivers/crypto/ccp/ccp-crypto-aes-xts.c
@@ -122,6 +122,7 @@
 	struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
 	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
 	unsigned int unit;
+	u32 unit_size;
 	int ret;
 
 	if (!ctx->u.aes.key_len)
@@ -133,11 +134,17 @@
 	if (!req->info)
 		return -EINVAL;
 
-	for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++)
-		if (!(req->nbytes & (unit_size_map[unit].size - 1)))
-			break;
+	unit_size = CCP_XTS_AES_UNIT_SIZE__LAST;
+	if (req->nbytes <= unit_size_map[0].size) {
+		for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) {
+			if (!(req->nbytes & (unit_size_map[unit].size - 1))) {
+				unit_size = unit_size_map[unit].value;
+				break;
+			}
+		}
+	}
 
-	if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) ||
+	if ((unit_size == CCP_XTS_AES_UNIT_SIZE__LAST) ||
 	    (ctx->u.aes.key_len != AES_KEYSIZE_128)) {
 		/* Use the fallback to process the request for any
 		 * unsupported unit sizes or key sizes
@@ -158,7 +165,7 @@
 	rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
 	rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
 					   : CCP_AES_ACTION_DECRYPT;
-	rctx->cmd.u.xts.unit_size = unit_size_map[unit].value;
+	rctx->cmd.u.xts.unit_size = unit_size;
 	rctx->cmd.u.xts.key = &ctx->u.aes.key_sg;
 	rctx->cmd.u.xts.key_len = ctx->u.aes.key_len;
 	rctx->cmd.u.xts.iv = &rctx->iv_sg;
diff --git a/drivers/crypto/nx/nx-842-powernv.c b/drivers/crypto/nx/nx-842-powernv.c
index 9ef51fa..6e105e8 100644
--- a/drivers/crypto/nx/nx-842-powernv.c
+++ b/drivers/crypto/nx/nx-842-powernv.c
@@ -442,6 +442,14 @@
 			     (unsigned int)ccw,
 			     (unsigned int)be32_to_cpu(crb->ccw));
 
+	/*
+	 * NX842 coprocessor sets 3rd bit in CR register with XER[S0].
+	 * XER[S0] is the integer summary overflow bit which is nothing
+	 * to do NX. Since this bit can be set with other return values,
+	 * mask this bit.
+	 */
+	ret &= ~ICSWX_XERS0;
+
 	switch (ret) {
 	case ICSWX_INITIATED:
 		ret = wait_for_csb(wmem, csb);
@@ -454,10 +462,6 @@
 		pr_err_ratelimited("ICSWX rejected\n");
 		ret = -EPROTO;
 		break;
-	default:
-		pr_err_ratelimited("Invalid ICSWX return code %x\n", ret);
-		ret = -EPROTO;
-		break;
 	}
 
 	if (!ret)
diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c
index 0794f1c..42f0f22 100644
--- a/drivers/crypto/nx/nx.c
+++ b/drivers/crypto/nx/nx.c
@@ -392,7 +392,7 @@
 		     ((bytes_so_far + sizeof(struct msc_triplet)) <= lenp) &&
 		     i < msc->triplets;
 		     i++) {
-			if (msc->fc > NX_MAX_FC || msc->mode > NX_MAX_MODE) {
+			if (msc->fc >= NX_MAX_FC || msc->mode >= NX_MAX_MODE) {
 				dev_err(dev, "unknown function code/mode "
 					"combo: %d/%d (ignored)\n", msc->fc,
 					msc->mode);
diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile
index 9e9e196..45b5ada 100644
--- a/drivers/crypto/qat/qat_common/Makefile
+++ b/drivers/crypto/qat/qat_common/Makefile
@@ -2,6 +2,7 @@
 			     $(obj)/qat_rsapubkey-asn1.h
 $(obj)/qat_rsaprivkey-asn1.o: $(obj)/qat_rsaprivkey-asn1.c \
 			      $(obj)/qat_rsaprivkey-asn1.h
+$(obj)/qat_asym_algs.o: $(obj)/qat_rsapubkey-asn1.h $(obj)/qat_rsaprivkey-asn1.h
 
 clean-files += qat_rsapubkey-asn1.c qat_rsapubkey-asn1.h
 clean-files += qat_rsaprivkey-asn1.c qat_rsapvivkey-asn1.h
diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h
index 3f76bd4..aa1dbea 100644
--- a/drivers/crypto/qat/qat_common/adf_common_drv.h
+++ b/drivers/crypto/qat/qat_common/adf_common_drv.h
@@ -227,6 +227,8 @@
 				  uint32_t vf_mask);
 void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
 				 uint32_t vf_mask);
+int adf_init_pf_wq(void);
+void adf_exit_pf_wq(void);
 #else
 static inline int adf_sriov_configure(struct pci_dev *pdev, int numvfs)
 {
@@ -236,5 +238,14 @@
 static inline void adf_disable_sriov(struct adf_accel_dev *accel_dev)
 {
 }
+
+static inline int adf_init_pf_wq(void)
+{
+	return 0;
+}
+
+static inline void adf_exit_pf_wq(void)
+{
+}
 #endif
 #endif
diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
index 473d36d..e7480f3 100644
--- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c
+++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
@@ -469,12 +469,17 @@
 	if (adf_init_aer())
 		goto err_aer;
 
+	if (adf_init_pf_wq())
+		goto err_pf_wq;
+
 	if (qat_crypto_register())
 		goto err_crypto_register;
 
 	return 0;
 
 err_crypto_register:
+	adf_exit_pf_wq();
+err_pf_wq:
 	adf_exit_aer();
 err_aer:
 	adf_chr_drv_destroy();
@@ -487,6 +492,7 @@
 {
 	adf_chr_drv_destroy();
 	adf_exit_aer();
+	adf_exit_pf_wq();
 	qat_crypto_unregister();
 	adf_clean_vf_map(false);
 	mutex_destroy(&adf_ctl_lock);
diff --git a/drivers/crypto/qat/qat_common/adf_sriov.c b/drivers/crypto/qat/qat_common/adf_sriov.c
index 1117a8b..38a0415 100644
--- a/drivers/crypto/qat/qat_common/adf_sriov.c
+++ b/drivers/crypto/qat/qat_common/adf_sriov.c
@@ -119,11 +119,6 @@
 	int i;
 	u32 reg;
 
-	/* Workqueue for PF2VF responses */
-	pf2vf_resp_wq = create_workqueue("qat_pf2vf_resp_wq");
-	if (!pf2vf_resp_wq)
-		return -ENOMEM;
-
 	for (i = 0, vf_info = accel_dev->pf.vf_info; i < totalvfs;
 	     i++, vf_info++) {
 		/* This ptr will be populated when VFs will be created */
@@ -216,11 +211,6 @@
 
 	kfree(accel_dev->pf.vf_info);
 	accel_dev->pf.vf_info = NULL;
-
-	if (pf2vf_resp_wq) {
-		destroy_workqueue(pf2vf_resp_wq);
-		pf2vf_resp_wq = NULL;
-	}
 }
 EXPORT_SYMBOL_GPL(adf_disable_sriov);
 
@@ -304,3 +294,19 @@
 	return numvfs;
 }
 EXPORT_SYMBOL_GPL(adf_sriov_configure);
+
+int __init adf_init_pf_wq(void)
+{
+	/* Workqueue for PF2VF responses */
+	pf2vf_resp_wq = create_workqueue("qat_pf2vf_resp_wq");
+
+	return !pf2vf_resp_wq ? -ENOMEM : 0;
+}
+
+void adf_exit_pf_wq(void)
+{
+	if (pf2vf_resp_wq) {
+		destroy_workqueue(pf2vf_resp_wq);
+		pf2vf_resp_wq = NULL;
+	}
+}
diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c
index 59e4c3af..367b666 100644
--- a/drivers/crypto/qat/qat_common/qat_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_algs.c
@@ -1262,8 +1262,8 @@
 			.setkey = qat_alg_ablkcipher_xts_setkey,
 			.decrypt = qat_alg_ablkcipher_decrypt,
 			.encrypt = qat_alg_ablkcipher_encrypt,
-			.min_keysize = AES_MIN_KEY_SIZE,
-			.max_keysize = AES_MAX_KEY_SIZE,
+			.min_keysize = 2 * AES_MIN_KEY_SIZE,
+			.max_keysize = 2 * AES_MAX_KEY_SIZE,
 			.ivsize = AES_BLOCK_SIZE,
 		},
 	},
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
index a19ee12..e72fea73 100644
--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
@@ -35,6 +35,7 @@
 	unsigned int todo;
 	struct sg_mapping_iter mi, mo;
 	unsigned int oi, oo; /* offset for in and out */
+	unsigned long flags;
 
 	if (areq->nbytes == 0)
 		return 0;
@@ -49,7 +50,7 @@
 		return -EINVAL;
 	}
 
-	spin_lock_bh(&ss->slock);
+	spin_lock_irqsave(&ss->slock, flags);
 
 	for (i = 0; i < op->keylen; i += 4)
 		writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
@@ -117,7 +118,7 @@
 	sg_miter_stop(&mi);
 	sg_miter_stop(&mo);
 	writel(0, ss->base + SS_CTL);
-	spin_unlock_bh(&ss->slock);
+	spin_unlock_irqrestore(&ss->slock, flags);
 	return err;
 }
 
@@ -149,6 +150,7 @@
 	unsigned int ob = 0;	/* offset in buf */
 	unsigned int obo = 0;	/* offset in bufo*/
 	unsigned int obl = 0;	/* length of data in bufo */
+	unsigned long flags;
 
 	if (areq->nbytes == 0)
 		return 0;
@@ -181,7 +183,7 @@
 	if (no_chunk == 1)
 		return sun4i_ss_opti_poll(areq);
 
-	spin_lock_bh(&ss->slock);
+	spin_lock_irqsave(&ss->slock, flags);
 
 	for (i = 0; i < op->keylen; i += 4)
 		writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
@@ -308,7 +310,7 @@
 	sg_miter_stop(&mi);
 	sg_miter_stop(&mo);
 	writel(0, ss->base + SS_CTL);
-	spin_unlock_bh(&ss->slock);
+	spin_unlock_irqrestore(&ss->slock, flags);
 
 	return err;
 }
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index a04fea4..9a8a18a 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -835,6 +835,16 @@
 	struct scatterlist *psrc;
 };
 
+struct talitos_export_state {
+	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
+	u8 buf[HASH_MAX_BLOCK_SIZE];
+	unsigned int swinit;
+	unsigned int first;
+	unsigned int last;
+	unsigned int to_hash_later;
+	unsigned int nbuf;
+};
+
 static int aead_setkey(struct crypto_aead *authenc,
 		       const u8 *key, unsigned int keylen)
 {
@@ -1954,6 +1964,46 @@
 	return ahash_process_req(areq, areq->nbytes);
 }
 
+static int ahash_export(struct ahash_request *areq, void *out)
+{
+	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+	struct talitos_export_state *export = out;
+
+	memcpy(export->hw_context, req_ctx->hw_context,
+	       req_ctx->hw_context_size);
+	memcpy(export->buf, req_ctx->buf, req_ctx->nbuf);
+	export->swinit = req_ctx->swinit;
+	export->first = req_ctx->first;
+	export->last = req_ctx->last;
+	export->to_hash_later = req_ctx->to_hash_later;
+	export->nbuf = req_ctx->nbuf;
+
+	return 0;
+}
+
+static int ahash_import(struct ahash_request *areq, const void *in)
+{
+	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+	const struct talitos_export_state *export = in;
+
+	memset(req_ctx, 0, sizeof(*req_ctx));
+	req_ctx->hw_context_size =
+		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
+			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
+			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
+	memcpy(req_ctx->hw_context, export->hw_context,
+	       req_ctx->hw_context_size);
+	memcpy(req_ctx->buf, export->buf, export->nbuf);
+	req_ctx->swinit = export->swinit;
+	req_ctx->first = export->first;
+	req_ctx->last = export->last;
+	req_ctx->to_hash_later = export->to_hash_later;
+	req_ctx->nbuf = export->nbuf;
+
+	return 0;
+}
+
 struct keyhash_result {
 	struct completion completion;
 	int err;
@@ -2348,6 +2398,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = MD5_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "md5",
 				.cra_driver_name = "md5-talitos",
@@ -2363,6 +2414,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA1_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha1",
 				.cra_driver_name = "sha1-talitos",
@@ -2378,6 +2430,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA224_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha224",
 				.cra_driver_name = "sha224-talitos",
@@ -2393,6 +2446,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA256_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha256",
 				.cra_driver_name = "sha256-talitos",
@@ -2408,6 +2462,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA384_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha384",
 				.cra_driver_name = "sha384-talitos",
@@ -2423,6 +2478,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA512_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha512",
 				.cra_driver_name = "sha512-talitos",
@@ -2438,6 +2494,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = MD5_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(md5)",
 				.cra_driver_name = "hmac-md5-talitos",
@@ -2453,6 +2510,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA1_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha1)",
 				.cra_driver_name = "hmac-sha1-talitos",
@@ -2468,6 +2526,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA224_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha224)",
 				.cra_driver_name = "hmac-sha224-talitos",
@@ -2483,6 +2542,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA256_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha256)",
 				.cra_driver_name = "hmac-sha256-talitos",
@@ -2498,6 +2558,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA384_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha384)",
 				.cra_driver_name = "hmac-sha384-talitos",
@@ -2513,6 +2574,7 @@
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA512_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha512)",
 				.cra_driver_name = "hmac-sha512-talitos",
@@ -2704,6 +2766,8 @@
 		t_alg->algt.alg.hash.finup = ahash_finup;
 		t_alg->algt.alg.hash.digest = ahash_digest;
 		t_alg->algt.alg.hash.setkey = ahash_setkey;
+		t_alg->algt.alg.hash.import = ahash_import;
+		t_alg->algt.alg.hash.export = ahash_export;
 
 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
 		    !strncmp(alg->cra_name, "hmac", 4)) {
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 66b1c33..cd43984 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -797,7 +797,7 @@
 						&device_data->state);
 				memmove(req_ctx->state.buffer,
 					device_data->state.buffer,
-					HASH_BLOCK_SIZE / sizeof(u32));
+					HASH_BLOCK_SIZE);
 				if (ret) {
 					dev_err(device_data->dev,
 						"%s: hash_resume_state() failed!\n",
@@ -848,7 +848,7 @@
 
 			memmove(device_data->state.buffer,
 				req_ctx->state.buffer,
-				HASH_BLOCK_SIZE / sizeof(u32));
+				HASH_BLOCK_SIZE);
 			if (ret) {
 				dev_err(device_data->dev, "%s: hash_save_state() failed!\n",
 					__func__);
diff --git a/drivers/crypto/vmx/aes_cbc.c b/drivers/crypto/vmx/aes_cbc.c
index 0b8fe2e..3f8bb9a 100644
--- a/drivers/crypto/vmx/aes_cbc.c
+++ b/drivers/crypto/vmx/aes_cbc.c
@@ -182,7 +182,7 @@
 	.cra_name = "cbc(aes)",
 	.cra_driver_name = "p8_aes_cbc",
 	.cra_module = THIS_MODULE,
-	.cra_priority = 1000,
+	.cra_priority = 2000,
 	.cra_type = &crypto_blkcipher_type,
 	.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK,
 	.cra_alignmask = 0,
@@ -191,7 +191,7 @@
 	.cra_init = p8_aes_cbc_init,
 	.cra_exit = p8_aes_cbc_exit,
 	.cra_blkcipher = {
-			  .ivsize = 0,
+			  .ivsize = AES_BLOCK_SIZE,
 			  .min_keysize = AES_MIN_KEY_SIZE,
 			  .max_keysize = AES_MAX_KEY_SIZE,
 			  .setkey = p8_aes_cbc_setkey,
diff --git a/drivers/crypto/vmx/aes_ctr.c b/drivers/crypto/vmx/aes_ctr.c
index ee1306c..72f1389 100644
--- a/drivers/crypto/vmx/aes_ctr.c
+++ b/drivers/crypto/vmx/aes_ctr.c
@@ -166,7 +166,7 @@
 	.cra_name = "ctr(aes)",
 	.cra_driver_name = "p8_aes_ctr",
 	.cra_module = THIS_MODULE,
-	.cra_priority = 1000,
+	.cra_priority = 2000,
 	.cra_type = &crypto_blkcipher_type,
 	.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK,
 	.cra_alignmask = 0,
@@ -175,7 +175,7 @@
 	.cra_init = p8_aes_ctr_init,
 	.cra_exit = p8_aes_ctr_exit,
 	.cra_blkcipher = {
-			  .ivsize = 0,
+			  .ivsize = AES_BLOCK_SIZE,
 			  .min_keysize = AES_MIN_KEY_SIZE,
 			  .max_keysize = AES_MAX_KEY_SIZE,
 			  .setkey = p8_aes_ctr_setkey,
diff --git a/drivers/crypto/vmx/ghash.c b/drivers/crypto/vmx/ghash.c
index 2183a2e..9cb3a0b 100644
--- a/drivers/crypto/vmx/ghash.c
+++ b/drivers/crypto/vmx/ghash.c
@@ -26,16 +26,13 @@
 #include <linux/hardirq.h>
 #include <asm/switch_to.h>
 #include <crypto/aes.h>
+#include <crypto/ghash.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/internal/hash.h>
 #include <crypto/b128ops.h>
 
 #define IN_INTERRUPT in_interrupt()
 
-#define GHASH_BLOCK_SIZE (16)
-#define GHASH_DIGEST_SIZE (16)
-#define GHASH_KEY_LEN (16)
-
 void gcm_init_p8(u128 htable[16], const u64 Xi[2]);
 void gcm_gmult_p8(u64 Xi[2], const u128 htable[16]);
 void gcm_ghash_p8(u64 Xi[2], const u128 htable[16],
@@ -55,16 +52,11 @@
 
 static int p8_ghash_init_tfm(struct crypto_tfm *tfm)
 {
-	const char *alg;
+	const char *alg = "ghash-generic";
 	struct crypto_shash *fallback;
 	struct crypto_shash *shash_tfm = __crypto_shash_cast(tfm);
 	struct p8_ghash_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	if (!(alg = crypto_tfm_alg_name(tfm))) {
-		printk(KERN_ERR "Failed to get algorithm name.\n");
-		return -ENOENT;
-	}
-
 	fallback = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
 	if (IS_ERR(fallback)) {
 		printk(KERN_ERR
@@ -78,10 +70,18 @@
 	crypto_shash_set_flags(fallback,
 			       crypto_shash_get_flags((struct crypto_shash
 						       *) tfm));
-	ctx->fallback = fallback;
 
-	shash_tfm->descsize = sizeof(struct p8_ghash_desc_ctx)
-	    + crypto_shash_descsize(fallback);
+	/* Check if the descsize defined in the algorithm is still enough. */
+	if (shash_tfm->descsize < sizeof(struct p8_ghash_desc_ctx)
+	    + crypto_shash_descsize(fallback)) {
+		printk(KERN_ERR
+		       "Desc size of the fallback implementation (%s) does not match the expected value: %lu vs %u\n",
+		       alg,
+		       shash_tfm->descsize - sizeof(struct p8_ghash_desc_ctx),
+		       crypto_shash_descsize(fallback));
+		return -EINVAL;
+	}
+	ctx->fallback = fallback;
 
 	return 0;
 }
@@ -113,7 +113,7 @@
 {
 	struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(tfm));
 
-	if (keylen != GHASH_KEY_LEN)
+	if (keylen != GHASH_BLOCK_SIZE)
 		return -EINVAL;
 
 	preempt_disable();
@@ -215,7 +215,8 @@
 	.update = p8_ghash_update,
 	.final = p8_ghash_final,
 	.setkey = p8_ghash_setkey,
-	.descsize = sizeof(struct p8_ghash_desc_ctx),
+	.descsize = sizeof(struct p8_ghash_desc_ctx)
+		+ sizeof(struct ghash_desc_ctx),
 	.base = {
 		 .cra_name = "ghash",
 		 .cra_driver_name = "p8_ghash",
diff --git a/drivers/crypto/vmx/ppc-xlate.pl b/drivers/crypto/vmx/ppc-xlate.pl
index b999733..b18e67d 100644
--- a/drivers/crypto/vmx/ppc-xlate.pl
+++ b/drivers/crypto/vmx/ppc-xlate.pl
@@ -139,6 +139,26 @@
     "	vor	$vx,$vy,$vy";
 };
 
+# Some ABIs specify vrsave, special-purpose register #256, as reserved
+# for system use.
+my $no_vrsave = ($flavour =~ /linux-ppc64le/);
+my $mtspr = sub {
+    my ($f,$idx,$ra) = @_;
+    if ($idx == 256 && $no_vrsave) {
+	"	or	$ra,$ra,$ra";
+    } else {
+	"	mtspr	$idx,$ra";
+    }
+};
+my $mfspr = sub {
+    my ($f,$rd,$idx) = @_;
+    if ($idx == 256 && $no_vrsave) {
+	"	li	$rd,-1";
+    } else {
+	"	mfspr	$rd,$idx";
+    }
+};
+
 # PowerISA 2.06 stuff
 sub vsxmem_op {
     my ($f, $vrt, $ra, $rb, $op) = @_;
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 02f9aa4..66c073f 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -242,7 +242,7 @@
 	u32		mbr_dus;	/* Destination Microblock Stride Register */
 };
 
-
+/* 64-bit alignment needed to update CNDA and CUBC registers in an atomic way. */
 struct at_xdmac_desc {
 	struct at_xdmac_lld		lld;
 	enum dma_transfer_direction	direction;
@@ -253,7 +253,7 @@
 	unsigned int			xfer_size;
 	struct list_head		descs_list;
 	struct list_head		xfer_node;
-};
+} __aligned(sizeof(u64));
 
 static inline void __iomem *at_xdmac_chan_reg_base(struct at_xdmac *atxdmac, unsigned int chan_nb)
 {
@@ -864,8 +864,12 @@
 	 * access. Hopefully we can access DDR through both ports (at least on
 	 * SAMA5D4x), so we can use the same interface for source and dest,
 	 * that solves the fact we don't know the direction.
+	 * ERRATA: Even if useless for memory transfers, the PERID has to not
+	 * match the one of another channel. If not, it could lead to spurious
+	 * flag status.
 	 */
-	u32			chan_cc = AT_XDMAC_CC_DIF(0)
+	u32			chan_cc = AT_XDMAC_CC_PERID(0x3f)
+					| AT_XDMAC_CC_DIF(0)
 					| AT_XDMAC_CC_SIF(0)
 					| AT_XDMAC_CC_MBSIZE_SIXTEEN
 					| AT_XDMAC_CC_TYPE_MEM_TRAN;
@@ -1042,8 +1046,12 @@
 	 * access DDR through both ports (at least on SAMA5D4x), so we can use
 	 * the same interface for source and dest, that solves the fact we
 	 * don't know the direction.
+	 * ERRATA: Even if useless for memory transfers, the PERID has to not
+	 * match the one of another channel. If not, it could lead to spurious
+	 * flag status.
 	 */
-	u32			chan_cc = AT_XDMAC_CC_DAM_INCREMENTED_AM
+	u32			chan_cc = AT_XDMAC_CC_PERID(0x3f)
+					| AT_XDMAC_CC_DAM_INCREMENTED_AM
 					| AT_XDMAC_CC_SAM_INCREMENTED_AM
 					| AT_XDMAC_CC_DIF(0)
 					| AT_XDMAC_CC_SIF(0)
@@ -1144,8 +1152,12 @@
 	 * access. Hopefully we can access DDR through both ports (at least on
 	 * SAMA5D4x), so we can use the same interface for source and dest,
 	 * that solves the fact we don't know the direction.
+	 * ERRATA: Even if useless for memory transfers, the PERID has to not
+	 * match the one of another channel. If not, it could lead to spurious
+	 * flag status.
 	 */
-	u32			chan_cc = AT_XDMAC_CC_DAM_UBS_AM
+	u32			chan_cc = AT_XDMAC_CC_PERID(0x3f)
+					| AT_XDMAC_CC_DAM_UBS_AM
 					| AT_XDMAC_CC_SAM_INCREMENTED_AM
 					| AT_XDMAC_CC_DIF(0)
 					| AT_XDMAC_CC_SIF(0)
@@ -1183,8 +1195,8 @@
 	desc->lld.mbr_cfg = chan_cc;
 
 	dev_dbg(chan2dev(chan),
-		"%s: lld: mbr_da=%pad, mbr_ds=%pad, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
-		__func__, &desc->lld.mbr_da, &desc->lld.mbr_ds, desc->lld.mbr_ubc,
+		"%s: lld: mbr_da=%pad, mbr_ds=0x%08x, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
+		__func__, &desc->lld.mbr_da, desc->lld.mbr_ds, desc->lld.mbr_ubc,
 		desc->lld.mbr_cfg);
 
 	return desc;
@@ -1388,6 +1400,7 @@
 	u32			cur_nda, check_nda, cur_ubc, mask, value;
 	u8			dwidth = 0;
 	unsigned long		flags;
+	bool			initd;
 
 	ret = dma_cookie_status(chan, cookie, txstate);
 	if (ret == DMA_COMPLETE)
@@ -1412,7 +1425,16 @@
 	residue = desc->xfer_size;
 	/*
 	 * Flush FIFO: only relevant when the transfer is source peripheral
-	 * synchronized.
+	 * synchronized. Flush is needed before reading CUBC because data in
+	 * the FIFO are not reported by CUBC. Reporting a residue of the
+	 * transfer length while we have data in FIFO can cause issue.
+	 * Usecase: atmel USART has a timeout which means I have received
+	 * characters but there is no more character received for a while. On
+	 * timeout, it requests the residue. If the data are in the DMA FIFO,
+	 * we will return a residue of the transfer length. It means no data
+	 * received. If an application is waiting for these data, it will hang
+	 * since we won't have another USART timeout without receiving new
+	 * data.
 	 */
 	mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC;
 	value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM;
@@ -1423,34 +1445,43 @@
 	}
 
 	/*
-	 * When processing the residue, we need to read two registers but we
-	 * can't do it in an atomic way. AT_XDMAC_CNDA is used to find where
-	 * we stand in the descriptor list and AT_XDMAC_CUBC is used
-	 * to know how many data are remaining for the current descriptor.
-	 * Since the dma channel is not paused to not loose data, between the
-	 * AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of
-	 * descriptor.
-	 * For that reason, after reading AT_XDMAC_CUBC, we check if we are
-	 * still using the same descriptor by reading a second time
-	 * AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to
-	 * read again AT_XDMAC_CUBC.
+	 * The easiest way to compute the residue should be to pause the DMA
+	 * but doing this can lead to miss some data as some devices don't
+	 * have FIFO.
+	 * We need to read several registers because:
+	 * - DMA is running therefore a descriptor change is possible while
+	 * reading these registers
+	 * - When the block transfer is done, the value of the CUBC register
+	 * is set to its initial value until the fetch of the next descriptor.
+	 * This value will corrupt the residue calculation so we have to skip
+	 * it.
+	 *
+	 * INITD --------                    ------------
+	 *              |____________________|
+	 *       _______________________  _______________
+	 * NDA       @desc2             \/   @desc3
+	 *       _______________________/\_______________
+	 *       __________  ___________  _______________
+	 * CUBC       0    \/ MAX desc1 \/  MAX desc2
+	 *       __________/\___________/\_______________
+	 *
+	 * Since descriptors are aligned on 64 bits, we can assume that
+	 * the update of NDA and CUBC is atomic.
 	 * Memory barriers are used to ensure the read order of the registers.
-	 * A max number of retries is set because unlikely it can never ends if
-	 * we are transferring a lot of data with small buffers.
+	 * A max number of retries is set because unlikely it could never ends.
 	 */
-	cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
-	rmb();
-	cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
 	for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
-		rmb();
 		check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
-
-		if (likely(cur_nda == check_nda))
-			break;
-
-		cur_nda = check_nda;
+		rmb();
+		initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
 		rmb();
 		cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
+		rmb();
+		cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
+		rmb();
+
+		if ((check_nda == cur_nda) && initd)
+			break;
 	}
 
 	if (unlikely(retry >= AT_XDMAC_RESIDUE_MAX_RETRIES)) {
@@ -1459,6 +1490,19 @@
 	}
 
 	/*
+	 * Flush FIFO: only relevant when the transfer is source peripheral
+	 * synchronized. Another flush is needed here because CUBC is updated
+	 * when the controller sends the data write command. It can lead to
+	 * report data that are not written in the memory or the device. The
+	 * FIFO flush ensures that data are really written.
+	 */
+	if ((desc->lld.mbr_cfg & mask) == value) {
+		at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask);
+		while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS))
+			cpu_relax();
+	}
+
+	/*
 	 * Remove size of all microblocks already transferred and the current
 	 * one. Then add the remaining size to transfer of the current
 	 * microblock.
@@ -2023,7 +2067,7 @@
 err_clk_disable:
 	clk_disable_unprepare(atxdmac->clk);
 err_free_irq:
-	free_irq(atxdmac->irq, atxdmac->dma.dev);
+	free_irq(atxdmac->irq, atxdmac);
 	return ret;
 }
 
@@ -2039,7 +2083,7 @@
 
 	synchronize_irq(atxdmac->irq);
 
-	free_irq(atxdmac->irq, atxdmac->dma.dev);
+	free_irq(atxdmac->irq, atxdmac);
 
 	for (i = 0; i < atxdmac->dma.chancnt; i++) {
 		struct at_xdmac_chan *atchan = &atxdmac->chan[i];
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 1ccf64b..3ecec14 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -492,7 +492,6 @@
 	caps->src_addr_widths = device->src_addr_widths;
 	caps->dst_addr_widths = device->dst_addr_widths;
 	caps->directions = device->directions;
-	caps->max_burst = device->max_burst;
 	caps->residue_granularity = device->residue_granularity;
 
 	/*
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index 57ff462..c97336a 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -325,6 +325,8 @@
 		| M2P_CONTROL_ENABLE;
 	m2p_set_control(edmac, control);
 
+	edmac->buffer = 0;
+
 	return 0;
 }
 
diff --git a/drivers/dma/ipu/ipu_irq.c b/drivers/dma/ipu/ipu_irq.c
index 2bf37e6..2846278 100644
--- a/drivers/dma/ipu/ipu_irq.c
+++ b/drivers/dma/ipu/ipu_irq.c
@@ -272,7 +272,7 @@
 	u32 status;
 	int i, line;
 
-	for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) {
+	for (i = 0; i < IPU_IRQ_NR_BANKS; i++) {
 		struct ipu_irq_bank *bank = irq_bank + i;
 
 		raw_spin_lock(&bank_lock);
@@ -286,22 +286,21 @@
 		raw_spin_unlock(&bank_lock);
 		while ((line = ffs(status))) {
 			struct ipu_irq_map *map;
-			unsigned int irq = NO_IRQ;
+			unsigned int irq;
 
 			line--;
 			status &= ~(1UL << line);
 
 			raw_spin_lock(&bank_lock);
 			map = src2map(32 * i + line);
-			if (map)
-				irq = map->irq;
-			raw_spin_unlock(&bank_lock);
-
 			if (!map) {
+				raw_spin_unlock(&bank_lock);
 				pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
 				       line, i);
 				continue;
 			}
+			irq = map->irq;
+			raw_spin_unlock(&bank_lock);
 			generic_handle_irq(irq);
 		}
 	}
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 1b0453b..8250950 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -33,9 +33,6 @@
 #define PL330_MAX_CHAN		8
 #define PL330_MAX_IRQS		32
 #define PL330_MAX_PERI		32
-#define PL330_MAX_BURST         16
-
-#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0)
 
 enum pl330_cachectrl {
 	CCTRL0,		/* Noncacheable and nonbufferable */
@@ -448,6 +445,9 @@
 
 	/* for cyclic capability */
 	bool cyclic;
+
+	/* for runtime pm tracking */
+	bool active;
 };
 
 struct pl330_dmac {
@@ -491,17 +491,6 @@
 	/* Peripheral channels connected to this DMAC */
 	unsigned int num_peripherals;
 	struct dma_pl330_chan *peripherals; /* keep at end */
-	int quirks;
-};
-
-static struct pl330_of_quirks {
-	char *quirk;
-	int id;
-} of_quirks[] = {
-	{
-		.quirk = "arm,pl330-broken-no-flushp",
-		.id = PL330_QUIRK_BROKEN_NO_FLUSHP,
-	}
 };
 
 struct dma_pl330_desc {
@@ -1151,68 +1140,47 @@
 	return off;
 }
 
-static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,
-				 u8 buf[], const struct _xfer_spec *pxs,
-				 int cyc)
+static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs, int cyc)
 {
 	int off = 0;
-	enum pl330_cond cond;
-
-	if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
-		cond = BURST;
-	else
-		cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
 
 	while (cyc--) {
-		off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
-		off += _emit_LDP(dry_run, &buf[off], cond, pxs->desc->peri);
+		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
+		off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
 		off += _emit_ST(dry_run, &buf[off], ALWAYS);
-
-		if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
-			off += _emit_FLUSHP(dry_run, &buf[off],
-					    pxs->desc->peri);
+		off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri);
 	}
 
 	return off;
 }
 
-static inline int _ldst_memtodev(struct pl330_dmac *pl330,
-				 unsigned dry_run, u8 buf[],
-				 const struct _xfer_spec *pxs, int cyc)
+static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs, int cyc)
 {
 	int off = 0;
-	enum pl330_cond cond;
-
-	if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
-		cond = BURST;
-	else
-		cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
-
 
 	while (cyc--) {
-		off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
+		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
 		off += _emit_LD(dry_run, &buf[off], ALWAYS);
-		off += _emit_STP(dry_run, &buf[off], cond, pxs->desc->peri);
-
-		if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
-			off += _emit_FLUSHP(dry_run, &buf[off],
-					    pxs->desc->peri);
+		off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
+		off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri);
 	}
 
 	return off;
 }
 
-static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
+static int _bursts(unsigned dry_run, u8 buf[],
 		const struct _xfer_spec *pxs, int cyc)
 {
 	int off = 0;
 
 	switch (pxs->desc->rqtype) {
 	case DMA_MEM_TO_DEV:
-		off += _ldst_memtodev(pl330, dry_run, &buf[off], pxs, cyc);
+		off += _ldst_memtodev(dry_run, &buf[off], pxs, cyc);
 		break;
 	case DMA_DEV_TO_MEM:
-		off += _ldst_devtomem(pl330, dry_run, &buf[off], pxs, cyc);
+		off += _ldst_devtomem(dry_run, &buf[off], pxs, cyc);
 		break;
 	case DMA_MEM_TO_MEM:
 		off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc);
@@ -1226,7 +1194,7 @@
 }
 
 /* Returns bytes consumed and updates bursts */
-static inline int _loop(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
+static inline int _loop(unsigned dry_run, u8 buf[],
 		unsigned long *bursts, const struct _xfer_spec *pxs)
 {
 	int cyc, cycmax, szlp, szlpend, szbrst, off;
@@ -1234,7 +1202,7 @@
 	struct _arg_LPEND lpend;
 
 	if (*bursts == 1)
-		return _bursts(pl330, dry_run, buf, pxs, 1);
+		return _bursts(dry_run, buf, pxs, 1);
 
 	/* Max iterations possible in DMALP is 256 */
 	if (*bursts >= 256*256) {
@@ -1252,7 +1220,7 @@
 	}
 
 	szlp = _emit_LP(1, buf, 0, 0);
-	szbrst = _bursts(pl330, 1, buf, pxs, 1);
+	szbrst = _bursts(1, buf, pxs, 1);
 
 	lpend.cond = ALWAYS;
 	lpend.forever = false;
@@ -1284,7 +1252,7 @@
 	off += _emit_LP(dry_run, &buf[off], 1, lcnt1);
 	ljmp1 = off;
 
-	off += _bursts(pl330, dry_run, &buf[off], pxs, cyc);
+	off += _bursts(dry_run, &buf[off], pxs, cyc);
 
 	lpend.cond = ALWAYS;
 	lpend.forever = false;
@@ -1307,9 +1275,8 @@
 	return off;
 }
 
-static inline int _setup_loops(struct pl330_dmac *pl330,
-			       unsigned dry_run, u8 buf[],
-			       const struct _xfer_spec *pxs)
+static inline int _setup_loops(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs)
 {
 	struct pl330_xfer *x = &pxs->desc->px;
 	u32 ccr = pxs->ccr;
@@ -1318,16 +1285,15 @@
 
 	while (bursts) {
 		c = bursts;
-		off += _loop(pl330, dry_run, &buf[off], &c, pxs);
+		off += _loop(dry_run, &buf[off], &c, pxs);
 		bursts -= c;
 	}
 
 	return off;
 }
 
-static inline int _setup_xfer(struct pl330_dmac *pl330,
-			      unsigned dry_run, u8 buf[],
-			      const struct _xfer_spec *pxs)
+static inline int _setup_xfer(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs)
 {
 	struct pl330_xfer *x = &pxs->desc->px;
 	int off = 0;
@@ -1338,7 +1304,7 @@
 	off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
 
 	/* Setup Loop(s) */
-	off += _setup_loops(pl330, dry_run, &buf[off], pxs);
+	off += _setup_loops(dry_run, &buf[off], pxs);
 
 	return off;
 }
@@ -1347,9 +1313,8 @@
  * A req is a sequence of one or more xfer units.
  * Returns the number of bytes taken to setup the MC for the req.
  */
-static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run,
-		      struct pl330_thread *thrd, unsigned index,
-		      struct _xfer_spec *pxs)
+static int _setup_req(unsigned dry_run, struct pl330_thread *thrd,
+		unsigned index, struct _xfer_spec *pxs)
 {
 	struct _pl330_req *req = &thrd->req[index];
 	struct pl330_xfer *x;
@@ -1366,7 +1331,7 @@
 	if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
 		return -EINVAL;
 
-	off += _setup_xfer(pl330, dry_run, &buf[off], pxs);
+	off += _setup_xfer(dry_run, &buf[off], pxs);
 
 	/* DMASEV peripheral/event */
 	off += _emit_SEV(dry_run, &buf[off], thrd->ev);
@@ -1460,7 +1425,7 @@
 	xs.desc = desc;
 
 	/* First dry run to check if req is acceptable */
-	ret = _setup_req(pl330, 1, thrd, idx, &xs);
+	ret = _setup_req(1, thrd, idx, &xs);
 	if (ret < 0)
 		goto xfer_exit;
 
@@ -1474,7 +1439,7 @@
 	/* Hook the request */
 	thrd->lstenq = idx;
 	thrd->req[idx].desc = desc;
-	_setup_req(pl330, 0, thrd, idx, &xs);
+	_setup_req(0, thrd, idx, &xs);
 
 	ret = 0;
 
@@ -2032,6 +1997,7 @@
 		_stop(pch->thread);
 		spin_unlock(&pch->thread->dmac->lock);
 		power_down = true;
+		pch->active = false;
 	} else {
 		/* Make sure the PL330 Channel thread is active */
 		spin_lock(&pch->thread->dmac->lock);
@@ -2053,6 +2019,7 @@
 			desc->status = PREP;
 			list_move_tail(&desc->node, &pch->work_list);
 			if (power_down) {
+				pch->active = true;
 				spin_lock(&pch->thread->dmac->lock);
 				_start(pch->thread);
 				spin_unlock(&pch->thread->dmac->lock);
@@ -2167,6 +2134,7 @@
 	unsigned long flags;
 	struct pl330_dmac *pl330 = pch->dmac;
 	LIST_HEAD(list);
+	bool power_down = false;
 
 	pm_runtime_get_sync(pl330->ddma.dev);
 	spin_lock_irqsave(&pch->lock, flags);
@@ -2177,6 +2145,8 @@
 	pch->thread->req[0].desc = NULL;
 	pch->thread->req[1].desc = NULL;
 	pch->thread->req_running = -1;
+	power_down = pch->active;
+	pch->active = false;
 
 	/* Mark all desc done */
 	list_for_each_entry(desc, &pch->submitted_list, node) {
@@ -2194,6 +2164,8 @@
 	list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
 	spin_unlock_irqrestore(&pch->lock, flags);
 	pm_runtime_mark_last_busy(pl330->ddma.dev);
+	if (power_down)
+		pm_runtime_put_autosuspend(pl330->ddma.dev);
 	pm_runtime_put_autosuspend(pl330->ddma.dev);
 
 	return 0;
@@ -2340,6 +2312,7 @@
 		 * updated on work_list emptiness status.
 		 */
 		WARN_ON(list_empty(&pch->submitted_list));
+		pch->active = true;
 		pm_runtime_get_sync(pch->dmac->ddma.dev);
 	}
 	list_splice_tail_init(&pch->submitted_list, &pch->work_list);
@@ -2598,7 +2571,7 @@
 
 		desc->rqtype = direction;
 		desc->rqcfg.brst_size = pch->burst_sz;
-		desc->rqcfg.brst_len = pch->burst_len;
+		desc->rqcfg.brst_len = 1;
 		desc->bytes_requested = period_len;
 		fill_px(&desc->px, dst, src, period_len);
 
@@ -2743,7 +2716,7 @@
 		}
 
 		desc->rqcfg.brst_size = pch->burst_sz;
-		desc->rqcfg.brst_len = pch->burst_len;
+		desc->rqcfg.brst_len = 1;
 		desc->rqtype = direction;
 		desc->bytes_requested = sg_dma_len(sg);
 	}
@@ -2819,7 +2792,6 @@
 	struct resource *res;
 	int i, ret, irq;
 	int num_chan;
-	struct device_node *np = adev->dev.of_node;
 
 	pdat = dev_get_platdata(&adev->dev);
 
@@ -2839,11 +2811,6 @@
 
 	pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
 
-	/* get quirk */
-	for (i = 0; i < ARRAY_SIZE(of_quirks); i++)
-		if (of_property_read_bool(np, of_quirks[i].quirk))
-			pl330->quirks |= of_quirks[i].id;
-
 	res = &adev->res;
 	pl330->base = devm_ioremap_resource(&adev->dev, res);
 	if (IS_ERR(pl330->base))
@@ -2939,8 +2906,6 @@
 	pd->dst_addr_widths = PL330_DMA_BUSWIDTHS;
 	pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
 	pd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
-	pd->max_burst = ((pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ?
-			 1 : PL330_MAX_BURST);
 
 	ret = dma_async_device_register(pd);
 	if (ret) {
diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c
index f1bcc2a..56410ea 100644
--- a/drivers/dma/sh/usb-dmac.c
+++ b/drivers/dma/sh/usb-dmac.c
@@ -117,7 +117,7 @@
 #define USB_DMASWR			0x0008
 #define USB_DMASWR_SWR			(1 << 0)
 #define USB_DMAOR			0x0060
-#define USB_DMAOR_AE			(1 << 2)
+#define USB_DMAOR_AE			(1 << 1)
 #define USB_DMAOR_DME			(1 << 0)
 
 #define USB_DMASAR			0x0000
@@ -600,27 +600,30 @@
 {
 	struct usb_dmac_chan *chan = dev;
 	irqreturn_t ret = IRQ_NONE;
-	u32 mask = USB_DMACHCR_TE;
-	u32 check_bits = USB_DMACHCR_TE | USB_DMACHCR_SP;
+	u32 mask = 0;
 	u32 chcr;
+	bool xfer_end = false;
 
 	spin_lock(&chan->vc.lock);
 
 	chcr = usb_dmac_chan_read(chan, USB_DMACHCR);
-	if (chcr & check_bits)
-		mask |= USB_DMACHCR_DE | check_bits;
+	if (chcr & (USB_DMACHCR_TE | USB_DMACHCR_SP)) {
+		mask |= USB_DMACHCR_DE | USB_DMACHCR_TE | USB_DMACHCR_SP;
+		if (chcr & USB_DMACHCR_DE)
+			xfer_end = true;
+		ret |= IRQ_HANDLED;
+	}
 	if (chcr & USB_DMACHCR_NULL) {
 		/* An interruption of TE will happen after we set FTE */
 		mask |= USB_DMACHCR_NULL;
 		chcr |= USB_DMACHCR_FTE;
 		ret |= IRQ_HANDLED;
 	}
-	usb_dmac_chan_write(chan, USB_DMACHCR, chcr & ~mask);
+	if (mask)
+		usb_dmac_chan_write(chan, USB_DMACHCR, chcr & ~mask);
 
-	if (chcr & check_bits) {
+	if (xfer_end)
 		usb_dmac_isr_transfer_end(chan);
-		ret |= IRQ_HANDLED;
-	}
 
 	spin_unlock(&chan->vc.lock);
 
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 1b2c218..dc68394 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -966,7 +966,7 @@
 	mci->ue_mc += count;
 
 	if (!enable_per_layer_report) {
-		mci->ce_noinfo_count += count;
+		mci->ue_noinfo_count += count;
 		return;
 	}
 
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 58aed67..3c8f19f 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -313,7 +313,6 @@
  * possible dynamic channel DIMM Label attribute files
  *
  */
-
 DEVICE_CHANNEL(ch0_dimm_label, S_IRUGO | S_IWUSR,
 	channel_dimm_label_show, channel_dimm_label_store, 0);
 DEVICE_CHANNEL(ch1_dimm_label, S_IRUGO | S_IWUSR,
@@ -326,6 +325,10 @@
 	channel_dimm_label_show, channel_dimm_label_store, 4);
 DEVICE_CHANNEL(ch5_dimm_label, S_IRUGO | S_IWUSR,
 	channel_dimm_label_show, channel_dimm_label_store, 5);
+DEVICE_CHANNEL(ch6_dimm_label, S_IRUGO | S_IWUSR,
+	channel_dimm_label_show, channel_dimm_label_store, 6);
+DEVICE_CHANNEL(ch7_dimm_label, S_IRUGO | S_IWUSR,
+	channel_dimm_label_show, channel_dimm_label_store, 7);
 
 /* Total possible dynamic DIMM Label attribute file table */
 static struct attribute *dynamic_csrow_dimm_attr[] = {
@@ -335,6 +338,8 @@
 	&dev_attr_legacy_ch3_dimm_label.attr.attr,
 	&dev_attr_legacy_ch4_dimm_label.attr.attr,
 	&dev_attr_legacy_ch5_dimm_label.attr.attr,
+	&dev_attr_legacy_ch6_dimm_label.attr.attr,
+	&dev_attr_legacy_ch7_dimm_label.attr.attr,
 	NULL
 };
 
@@ -351,6 +356,10 @@
 		   channel_ce_count_show, NULL, 4);
 DEVICE_CHANNEL(ch5_ce_count, S_IRUGO,
 		   channel_ce_count_show, NULL, 5);
+DEVICE_CHANNEL(ch6_ce_count, S_IRUGO,
+		   channel_ce_count_show, NULL, 6);
+DEVICE_CHANNEL(ch7_ce_count, S_IRUGO,
+		   channel_ce_count_show, NULL, 7);
 
 /* Total possible dynamic ce_count attribute file table */
 static struct attribute *dynamic_csrow_ce_count_attr[] = {
@@ -360,6 +369,8 @@
 	&dev_attr_legacy_ch3_ce_count.attr.attr,
 	&dev_attr_legacy_ch4_ce_count.attr.attr,
 	&dev_attr_legacy_ch5_ce_count.attr.attr,
+	&dev_attr_legacy_ch6_ce_count.attr.attr,
+	&dev_attr_legacy_ch7_ce_count.attr.attr,
 	NULL
 };
 
@@ -371,9 +382,16 @@
 
 	if (idx >= csrow->nr_channels)
 		return 0;
+
+	if (idx >= ARRAY_SIZE(dynamic_csrow_ce_count_attr) - 1) {
+		WARN_ONCE(1, "idx: %d\n", idx);
+		return 0;
+	}
+
 	/* Only expose populated DIMMs */
 	if (!csrow->channels[idx]->dimm->nr_pages)
 		return 0;
+
 	return attr->mode;
 }
 
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 3764922..ca64b17 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -218,8 +218,11 @@
 	{ 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
 };
 
-#define RIR_RNK_TGT(reg)		GET_BITFIELD(reg, 16, 19)
-#define RIR_OFFSET(reg)		GET_BITFIELD(reg,  2, 14)
+#define RIR_RNK_TGT(type, reg) (((type) == BROADWELL) ? \
+	GET_BITFIELD(reg, 20, 23) : GET_BITFIELD(reg, 16, 19))
+
+#define RIR_OFFSET(type, reg) (((type) == HASWELL || (type) == BROADWELL) ? \
+	GET_BITFIELD(reg,  2, 15) : GET_BITFIELD(reg,  2, 14))
 
 /* Device 16, functions 2-7 */
 
@@ -1175,14 +1178,14 @@
 				pci_read_config_dword(pvt->pci_tad[i],
 						      rir_offset[j][k],
 						      &reg);
-				tmp_mb = RIR_OFFSET(reg) << 6;
+				tmp_mb = RIR_OFFSET(pvt->info.type, reg) << 6;
 
 				gb = div_u64_rem(tmp_mb, 1024, &mb);
 				edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
 					 i, j, k,
 					 gb, (mb*1000)/1024,
 					 ((u64)tmp_mb) << 20L,
-					 (u32)RIR_RNK_TGT(reg),
+					 (u32)RIR_RNK_TGT(pvt->info.type, reg),
 					 reg);
 			}
 		}
@@ -1512,7 +1515,7 @@
 	pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
 			      rir_offset[n_rir][idx],
 			      &reg);
-	*rank = RIR_RNK_TGT(reg);
+	*rank = RIR_RNK_TGT(pvt->info.type, reg);
 
 	edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
 		 n_rir,
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index f4ea80d..b9d2f76 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -73,13 +73,13 @@
 
 #define fwnet_get_hdr_lf(h)		(((h)->w0 & 0xc0000000) >> 30)
 #define fwnet_get_hdr_ether_type(h)	(((h)->w0 & 0x0000ffff))
-#define fwnet_get_hdr_dg_size(h)	(((h)->w0 & 0x0fff0000) >> 16)
+#define fwnet_get_hdr_dg_size(h)	((((h)->w0 & 0x0fff0000) >> 16) + 1)
 #define fwnet_get_hdr_fg_off(h)		(((h)->w0 & 0x00000fff))
 #define fwnet_get_hdr_dgl(h)		(((h)->w1 & 0xffff0000) >> 16)
 
-#define fwnet_set_hdr_lf(lf)		((lf)  << 30)
+#define fwnet_set_hdr_lf(lf)		((lf) << 30)
 #define fwnet_set_hdr_ether_type(et)	(et)
-#define fwnet_set_hdr_dg_size(dgs)	((dgs) << 16)
+#define fwnet_set_hdr_dg_size(dgs)	(((dgs) - 1) << 16)
 #define fwnet_set_hdr_fg_off(fgo)	(fgo)
 
 #define fwnet_set_hdr_dgl(dgl)		((dgl) << 16)
@@ -578,6 +578,9 @@
 	int retval;
 	u16 ether_type;
 
+	if (len <= RFC2374_UNFRAG_HDR_SIZE)
+		return 0;
+
 	hdr.w0 = be32_to_cpu(buf[0]);
 	lf = fwnet_get_hdr_lf(&hdr);
 	if (lf == RFC2374_HDR_UNFRAG) {
@@ -602,7 +605,12 @@
 		return fwnet_finish_incoming_packet(net, skb, source_node_id,
 						    is_broadcast, ether_type);
 	}
+
 	/* A datagram fragment has been received, now the fun begins. */
+
+	if (len <= RFC2374_FRAG_HDR_SIZE)
+		return 0;
+
 	hdr.w1 = ntohl(buf[1]);
 	buf += 2;
 	len -= RFC2374_FRAG_HDR_SIZE;
@@ -614,7 +622,10 @@
 		fg_off = fwnet_get_hdr_fg_off(&hdr);
 	}
 	datagram_label = fwnet_get_hdr_dgl(&hdr);
-	dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */
+	dg_size = fwnet_get_hdr_dg_size(&hdr);
+
+	if (fg_off + len > dg_size)
+		return 0;
 
 	spin_lock_irqsave(&dev->lock, flags);
 
@@ -722,6 +733,22 @@
 	fw_send_response(card, r, rcode);
 }
 
+static int gasp_source_id(__be32 *p)
+{
+	return be32_to_cpu(p[0]) >> 16;
+}
+
+static u32 gasp_specifier_id(__be32 *p)
+{
+	return (be32_to_cpu(p[0]) & 0xffff) << 8 |
+	       (be32_to_cpu(p[1]) & 0xff000000) >> 24;
+}
+
+static u32 gasp_version(__be32 *p)
+{
+	return be32_to_cpu(p[1]) & 0xffffff;
+}
+
 static void fwnet_receive_broadcast(struct fw_iso_context *context,
 		u32 cycle, size_t header_length, void *header, void *data)
 {
@@ -731,9 +758,6 @@
 	__be32 *buf_ptr;
 	int retval;
 	u32 length;
-	u16 source_node_id;
-	u32 specifier_id;
-	u32 ver;
 	unsigned long offset;
 	unsigned long flags;
 
@@ -750,22 +774,17 @@
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	specifier_id =    (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8
-			| (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24;
-	ver = be32_to_cpu(buf_ptr[1]) & 0xffffff;
-	source_node_id = be32_to_cpu(buf_ptr[0]) >> 16;
-
-	if (specifier_id == IANA_SPECIFIER_ID &&
-	    (ver == RFC2734_SW_VERSION
+	if (length > IEEE1394_GASP_HDR_SIZE &&
+	    gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID &&
+	    (gasp_version(buf_ptr) == RFC2734_SW_VERSION
 #if IS_ENABLED(CONFIG_IPV6)
-	     || ver == RFC3146_SW_VERSION
+	     || gasp_version(buf_ptr) == RFC3146_SW_VERSION
 #endif
-	    )) {
-		buf_ptr += 2;
-		length -= IEEE1394_GASP_HDR_SIZE;
-		fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
+	    ))
+		fwnet_incoming_packet(dev, buf_ptr + 2,
+				      length - IEEE1394_GASP_HDR_SIZE,
+				      gasp_source_id(buf_ptr),
 				      context->card->generation, true);
-	}
 
 	packet.payload_length = dev->rcv_buffer_size;
 	packet.interrupt = 1;
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 0b0b635..e1670d5 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -87,21 +87,6 @@
 config EFI_ARMSTUB
 	bool
 
-config EFI_BOOTLOADER_CONTROL
-	tristate "EFI Bootloader Control"
-	depends on EFI_VARS
-	default n
-	---help---
-	  This module installs a reboot hook, such that if reboot() is
-	  invoked with a string argument NNN, "NNN" is copied to the
-	  "LoaderEntryOneShot" EFI variable, to be read by the
-	  bootloader. If the string matches one of the boot labels
-	  defined in its configuration, the bootloader will boot once
-	  to that label. The "LoaderEntryRebootReason" EFI variable is
-	  set with the reboot reason: "reboot" or "shutdown". The
-	  bootloader reads this reboot reason and takes particular
-	  action according to its policy.
-
 endmenu
 
 config UEFI_CPER
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 1ba637e..f292917b 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -18,4 +18,6 @@
 obj-$(CONFIG_EFI_RUNTIME_WRAPPERS)	+= runtime-wrappers.o
 obj-$(CONFIG_EFI_STUB)			+= libstub/
 obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
-obj-$(CONFIG_EFI_BOOTLOADER_CONTROL)	+= efibc.o
+
+arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
+obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
new file mode 100644
index 0000000..a76c35f
--- /dev/null
+++ b/drivers/firmware/efi/arm-init.c
@@ -0,0 +1,221 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 2.4
+ *
+ * Copyright (C) 2013 - 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/memblock.h>
+#include <linux/mm_types.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+
+#include <asm/efi.h>
+
+struct efi_memory_map memmap;
+
+u64 efi_system_table;
+
+static int __init is_normal_ram(efi_memory_desc_t *md)
+{
+	if (md->attribute & EFI_MEMORY_WB)
+		return 1;
+	return 0;
+}
+
+/*
+ * Translate a EFI virtual address into a physical address: this is necessary,
+ * as some data members of the EFI system table are virtually remapped after
+ * SetVirtualAddressMap() has been called.
+ */
+static phys_addr_t efi_to_phys(unsigned long addr)
+{
+	efi_memory_desc_t *md;
+
+	for_each_efi_memory_desc(&memmap, md) {
+		if (!(md->attribute & EFI_MEMORY_RUNTIME))
+			continue;
+		if (md->virt_addr == 0)
+			/* no virtual mapping has been installed by the stub */
+			break;
+		if (md->virt_addr <= addr &&
+		    (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT))
+			return md->phys_addr + addr - md->virt_addr;
+	}
+	return addr;
+}
+
+static int __init uefi_init(void)
+{
+	efi_char16_t *c16;
+	void *config_tables;
+	size_t table_size;
+	char vendor[100] = "unknown";
+	int i, retval;
+
+	efi.systab = early_memremap(efi_system_table,
+				    sizeof(efi_system_table_t));
+	if (efi.systab == NULL) {
+		pr_warn("Unable to map EFI system table.\n");
+		return -ENOMEM;
+	}
+
+	set_bit(EFI_BOOT, &efi.flags);
+	if (IS_ENABLED(CONFIG_64BIT))
+		set_bit(EFI_64BIT, &efi.flags);
+
+	/*
+	 * Verify the EFI Table
+	 */
+	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
+		pr_err("System table signature incorrect\n");
+		retval = -EINVAL;
+		goto out;
+	}
+	if ((efi.systab->hdr.revision >> 16) < 2)
+		pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
+			efi.systab->hdr.revision >> 16,
+			efi.systab->hdr.revision & 0xffff);
+
+	/* Show what we know for posterity */
+	c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
+			     sizeof(vendor) * sizeof(efi_char16_t));
+	if (c16) {
+		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
+			vendor[i] = c16[i];
+		vendor[i] = '\0';
+		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
+	}
+
+	pr_info("EFI v%u.%.02u by %s\n",
+		efi.systab->hdr.revision >> 16,
+		efi.systab->hdr.revision & 0xffff, vendor);
+
+	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
+	config_tables = early_memremap(efi_to_phys(efi.systab->tables),
+				       table_size);
+	if (config_tables == NULL) {
+		pr_warn("Unable to map EFI config table array.\n");
+		retval = -ENOMEM;
+		goto out;
+	}
+	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
+					 sizeof(efi_config_table_t), NULL);
+
+	early_memunmap(config_tables, table_size);
+out:
+	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
+	return retval;
+}
+
+/*
+ * Return true for RAM regions we want to permanently reserve.
+ */
+static __init int is_reserve_region(efi_memory_desc_t *md)
+{
+	switch (md->type) {
+	case EFI_LOADER_CODE:
+	case EFI_LOADER_DATA:
+	case EFI_BOOT_SERVICES_CODE:
+	case EFI_BOOT_SERVICES_DATA:
+	case EFI_CONVENTIONAL_MEMORY:
+	case EFI_PERSISTENT_MEMORY:
+		return 0;
+	default:
+		break;
+	}
+	return is_normal_ram(md);
+}
+
+static __init void reserve_regions(void)
+{
+	efi_memory_desc_t *md;
+	u64 paddr, npages, size;
+
+	if (efi_enabled(EFI_DBG))
+		pr_info("Processing EFI memory map:\n");
+
+	for_each_efi_memory_desc(&memmap, md) {
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+
+		if (efi_enabled(EFI_DBG)) {
+			char buf[64];
+
+			pr_info("  0x%012llx-0x%012llx %s",
+				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
+				efi_md_typeattr_format(buf, sizeof(buf), md));
+		}
+
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		if (is_normal_ram(md))
+			early_init_dt_add_memory_arch(paddr, size);
+
+		if (is_reserve_region(md)) {
+			memblock_mark_nomap(paddr, size);
+			if (efi_enabled(EFI_DBG))
+				pr_cont("*");
+		}
+
+		if (efi_enabled(EFI_DBG))
+			pr_cont("\n");
+	}
+
+	set_bit(EFI_MEMMAP, &efi.flags);
+}
+
+void __init efi_init(void)
+{
+	struct efi_fdt_params params;
+
+	/* Grab UEFI information placed in FDT by stub */
+	if (!efi_get_fdt_params(&params))
+		return;
+
+	efi_system_table = params.system_table;
+
+	memmap.phys_map = params.mmap;
+	memmap.map = early_memremap(params.mmap, params.mmap_size);
+	if (memmap.map == NULL) {
+		/*
+		* If we are booting via UEFI, the UEFI memory map is the only
+		* description of memory we have, so there is little point in
+		* proceeding if we cannot access it.
+		*/
+		panic("Unable to map EFI memory map.\n");
+	}
+	memmap.map_end = memmap.map + params.mmap_size;
+	memmap.desc_size = params.desc_size;
+	memmap.desc_version = params.desc_ver;
+
+	if (uefi_init() < 0)
+		return;
+
+	reserve_regions();
+	early_memunmap(memmap.map, params.mmap_size);
+
+	if (IS_ENABLED(CONFIG_ARM)) {
+		/*
+		 * ARM currently does not allow ioremap_cache() to be called on
+		 * memory regions that are covered by struct page. So remove the
+		 * UEFI memory map from the linear mapping.
+		 */
+		memblock_mark_nomap(params.mmap & PAGE_MASK,
+				    PAGE_ALIGN(params.mmap_size +
+					       (params.mmap & ~PAGE_MASK)));
+	} else {
+		memblock_reserve(params.mmap & PAGE_MASK,
+				 PAGE_ALIGN(params.mmap_size +
+					    (params.mmap & ~PAGE_MASK)));
+	}
+}
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
new file mode 100644
index 0000000..6ae21e4
--- /dev/null
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -0,0 +1,135 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 2.4
+ *
+ * Copyright (C) 2013, 2014 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/efi.h>
+#include <linux/io.h>
+#include <linux/memblock.h>
+#include <linux/mm_types.h>
+#include <linux/preempt.h>
+#include <linux/rbtree.h>
+#include <linux/rwsem.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/cacheflush.h>
+#include <asm/efi.h>
+#include <asm/mmu.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+
+extern u64 efi_system_table;
+
+static struct mm_struct efi_mm = {
+	.mm_rb			= RB_ROOT,
+	.mm_users		= ATOMIC_INIT(2),
+	.mm_count		= ATOMIC_INIT(1),
+	.mmap_sem		= __RWSEM_INITIALIZER(efi_mm.mmap_sem),
+	.page_table_lock	= __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
+	.mmlist			= LIST_HEAD_INIT(efi_mm.mmlist),
+};
+
+static bool __init efi_virtmap_init(void)
+{
+	efi_memory_desc_t *md;
+
+	efi_mm.pgd = pgd_alloc(&efi_mm);
+	init_new_context(NULL, &efi_mm);
+
+	for_each_efi_memory_desc(&memmap, md) {
+		phys_addr_t phys = md->phys_addr;
+		int ret;
+
+		if (!(md->attribute & EFI_MEMORY_RUNTIME))
+			continue;
+		if (md->virt_addr == 0)
+			return false;
+
+		ret = efi_create_mapping(&efi_mm, md);
+		if  (!ret) {
+			pr_info("  EFI remap %pa => %p\n",
+				&phys, (void *)(unsigned long)md->virt_addr);
+		} else {
+			pr_warn("  EFI remap %pa: failed to create mapping (%d)\n",
+				&phys, ret);
+			return false;
+		}
+	}
+	return true;
+}
+
+/*
+ * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
+ * non-early mapping of the UEFI system table and virtual mappings for all
+ * EFI_MEMORY_RUNTIME regions.
+ */
+static int __init arm_enable_runtime_services(void)
+{
+	u64 mapsize;
+
+	if (!efi_enabled(EFI_BOOT)) {
+		pr_info("EFI services will not be available.\n");
+		return 0;
+	}
+
+	if (efi_runtime_disabled()) {
+		pr_info("EFI runtime services will be disabled.\n");
+		return 0;
+	}
+
+	pr_info("Remapping and enabling EFI services.\n");
+
+	mapsize = memmap.map_end - memmap.map;
+	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
+						   mapsize);
+	if (!memmap.map) {
+		pr_err("Failed to remap EFI memory map\n");
+		return -ENOMEM;
+	}
+	memmap.map_end = memmap.map + mapsize;
+	efi.memmap = &memmap;
+
+	efi.systab = (__force void *)ioremap_cache(efi_system_table,
+						   sizeof(efi_system_table_t));
+	if (!efi.systab) {
+		pr_err("Failed to remap EFI System Table\n");
+		return -ENOMEM;
+	}
+	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+
+	if (!efi_virtmap_init()) {
+		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
+		return -ENOMEM;
+	}
+
+	/* Set up runtime services function pointers */
+	efi_native_runtime_setup();
+	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+
+	efi.runtime_version = efi.systab->hdr.revision;
+
+	return 0;
+}
+early_initcall(arm_enable_runtime_services);
+
+void efi_virtmap_load(void)
+{
+	preempt_disable();
+	efi_set_pgd(&efi_mm);
+}
+
+void efi_virtmap_unload(void)
+{
+	efi_set_pgd(current->active_mm);
+	preempt_enable();
+}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 3b52677..c51f3b2 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -25,6 +25,8 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 
+#include <asm/early_ioremap.h>
+
 struct efi __read_mostly efi = {
 	.mps			= EFI_INVALID_TABLE_ADDR,
 	.acpi			= EFI_INVALID_TABLE_ADDR,
diff --git a/drivers/firmware/efi/efibc.c b/drivers/firmware/efi/efibc.c
deleted file mode 100644
index 8dd0c70..0000000
--- a/drivers/firmware/efi/efibc.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * efibc: control EFI bootloaders which obey LoaderEntryOneShot var
- * Copyright (c) 2013-2016, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- */
-
-#define pr_fmt(fmt) "efibc: " fmt
-
-#include <linux/efi.h>
-#include <linux/module.h>
-#include <linux/reboot.h>
-#include <linux/slab.h>
-
-static void efibc_str_to_str16(const char *str, efi_char16_t *str16)
-{
-	size_t i;
-
-	for (i = 0; i < strlen(str); i++)
-		str16[i] = str[i];
-
-	str16[i] = '\0';
-}
-
-static int efibc_set_variable(const char *name, const char *value)
-{
-	int ret;
-	efi_guid_t guid = LINUX_EFI_LOADER_ENTRY_GUID;
-	struct efivar_entry *entry;
-	size_t size = (strlen(value) + 1) * sizeof(efi_char16_t);
-
-	if (size > sizeof(entry->var.Data)) {
-		pr_err("value is too large");
-		return -EINVAL;
-	}
-
-	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-	if (!entry) {
-		pr_err("failed to allocate efivar entry");
-		return -ENOMEM;
-	}
-
-	efibc_str_to_str16(name, entry->var.VariableName);
-	efibc_str_to_str16(value, (efi_char16_t *)entry->var.Data);
-	memcpy(&entry->var.VendorGuid, &guid, sizeof(guid));
-
-	ret = efivar_entry_set(entry,
-			       EFI_VARIABLE_NON_VOLATILE
-			       | EFI_VARIABLE_BOOTSERVICE_ACCESS
-			       | EFI_VARIABLE_RUNTIME_ACCESS,
-			       size, entry->var.Data, NULL);
-	if (ret)
-		pr_err("failed to set %s EFI variable: 0x%x\n",
-		       name, ret);
-
-	kfree(entry);
-	return ret;
-}
-
-static int efibc_reboot_notifier_call(struct notifier_block *notifier,
-				      unsigned long event, void *data)
-{
-	const char *reason = "shutdown";
-	int ret;
-
-	if (event == SYS_RESTART)
-		reason = "reboot";
-
-	ret = efibc_set_variable("LoaderEntryRebootReason", reason);
-	if (ret || !data)
-		return NOTIFY_DONE;
-
-	efibc_set_variable("LoaderEntryOneShot", (char *)data);
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block efibc_reboot_notifier = {
-	.notifier_call = efibc_reboot_notifier_call,
-};
-
-static int __init efibc_init(void)
-{
-	int ret;
-
-	if (!efi_enabled(EFI_RUNTIME_SERVICES))
-		return -ENODEV;
-
-	ret = register_reboot_notifier(&efibc_reboot_notifier);
-	if (ret)
-		pr_err("unable to register reboot notifier\n");
-
-	return ret;
-}
-module_init(efibc_init);
-
-static void __exit efibc_exit(void)
-{
-	unregister_reboot_notifier(&efibc_reboot_notifier);
-}
-module_exit(efibc_exit);
-
-MODULE_AUTHOR("Jeremy Compostella <jeremy.compostella@intel.com>");
-MODULE_AUTHOR("Matt Gumbel <matthew.k.gumbel@intel.com");
-MODULE_DESCRIPTION("EFI Bootloader Control");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 3c0467d..68bdd9f 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -8,7 +8,7 @@
 cflags-$(CONFIG_X86_64)		:= -mcmodel=small
 cflags-$(CONFIG_X86)		+= -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
 				   -fPIC -fno-strict-aliasing -mno-red-zone \
-				   -mno-mmx -mno-sse -DDISABLE_BRANCH_PROFILING
+				   -mno-mmx -mno-sse
 
 cflags-$(CONFIG_ARM64)		:= $(subst -pg,,$(KBUILD_CFLAGS))
 cflags-$(CONFIG_ARM)		:= $(subst -pg,,$(KBUILD_CFLAGS)) \
@@ -16,7 +16,7 @@
 
 cflags-$(CONFIG_EFI_ARMSTUB)	+= -I$(srctree)/scripts/dtc/libfdt
 
-KBUILD_CFLAGS			:= $(cflags-y) \
+KBUILD_CFLAGS			:= $(cflags-y) -DDISABLE_BRANCH_PROFILING \
 				   $(call cc-option,-ffreestanding) \
 				   $(call cc-option,-fno-stack-protector)
 
@@ -34,7 +34,7 @@
 lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o \
 				   $(patsubst %.c,lib-%.o,$(arm-deps))
 
-lib-$(CONFIG_ARM64)		+= arm64-stub.o
+lib-$(CONFIG_ARM64)		+= arm64-stub.o random.o
 CFLAGS_arm64-stub.o 		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 #
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 950c87f..d5aa1d1 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -18,6 +18,8 @@
 
 #include "efistub.h"
 
+bool __nokaslr;
+
 static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg)
 {
 	static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID;
@@ -207,14 +209,6 @@
 		pr_efi_err(sys_table, "Failed to find DRAM base\n");
 		goto fail;
 	}
-	status = handle_kernel_image(sys_table, image_addr, &image_size,
-				     &reserve_addr,
-				     &reserve_size,
-				     dram_base, image);
-	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Failed to relocate kernel\n");
-		goto fail;
-	}
 
 	/*
 	 * Get the command line from EFI, using the LOADED_IMAGE
@@ -224,7 +218,28 @@
 	cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
 	if (!cmdline_ptr) {
 		pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n");
-		goto fail_free_image;
+		goto fail;
+	}
+
+	/* check whether 'nokaslr' was passed on the command line */
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
+		static const u8 default_cmdline[] = CONFIG_CMDLINE;
+		const u8 *str, *cmdline = cmdline_ptr;
+
+		if (IS_ENABLED(CONFIG_CMDLINE_FORCE))
+			cmdline = default_cmdline;
+		str = strstr(cmdline, "nokaslr");
+		if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
+			__nokaslr = true;
+	}
+
+	status = handle_kernel_image(sys_table, image_addr, &image_size,
+				     &reserve_addr,
+				     &reserve_size,
+				     dram_base, image);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to relocate kernel\n");
+		goto fail_free_cmdline;
 	}
 
 	status = efi_parse_options(cmdline_ptr);
@@ -244,7 +259,7 @@
 
 		if (status != EFI_SUCCESS) {
 			pr_efi_err(sys_table, "Failed to load device tree!\n");
-			goto fail_free_cmdline;
+			goto fail_free_image;
 		}
 	}
 
@@ -286,12 +301,11 @@
 	efi_free(sys_table, initrd_size, initrd_addr);
 	efi_free(sys_table, fdt_size, fdt_addr);
 
-fail_free_cmdline:
-	efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
-
 fail_free_image:
 	efi_free(sys_table, image_size, *image_addr);
 	efi_free(sys_table, reserve_size, reserve_addr);
+fail_free_cmdline:
+	efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
 fail:
 	return EFI_ERROR;
 }
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index 78dfbd3..e0e6b74 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -13,6 +13,10 @@
 #include <asm/efi.h>
 #include <asm/sections.h>
 
+#include "efistub.h"
+
+extern bool __nokaslr;
+
 efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
 					unsigned long *image_addr,
 					unsigned long *image_size,
@@ -23,26 +27,52 @@
 {
 	efi_status_t status;
 	unsigned long kernel_size, kernel_memsize = 0;
-	unsigned long nr_pages;
 	void *old_image_addr = (void *)*image_addr;
 	unsigned long preferred_offset;
+	u64 phys_seed = 0;
+
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
+		if (!__nokaslr) {
+			status = efi_get_random_bytes(sys_table_arg,
+						      sizeof(phys_seed),
+						      (u8 *)&phys_seed);
+			if (status == EFI_NOT_FOUND) {
+				pr_efi(sys_table_arg, "EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
+			} else if (status != EFI_SUCCESS) {
+				pr_efi_err(sys_table_arg, "efi_get_random_bytes() failed\n");
+				return status;
+			}
+		} else {
+			pr_efi(sys_table_arg, "KASLR disabled on kernel command line\n");
+		}
+	}
 
 	/*
 	 * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
 	 * a 2 MB aligned base, which itself may be lower than dram_base, as
 	 * long as the resulting offset equals or exceeds it.
 	 */
-	preferred_offset = round_down(dram_base, SZ_2M) + TEXT_OFFSET;
+	preferred_offset = round_down(dram_base, MIN_KIMG_ALIGN) + TEXT_OFFSET;
 	if (preferred_offset < dram_base)
-		preferred_offset += SZ_2M;
+		preferred_offset += MIN_KIMG_ALIGN;
 
-	/* Relocate the image, if required. */
 	kernel_size = _edata - _text;
-	if (*image_addr != preferred_offset) {
-		kernel_memsize = kernel_size + (_end - _edata);
+	kernel_memsize = kernel_size + (_end - _edata);
 
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
 		/*
-		 * First, try a straight allocation at the preferred offset.
+		 * If KASLR is enabled, and we have some randomness available,
+		 * locate the kernel at a randomized offset in physical memory.
+		 */
+		*reserve_size = kernel_memsize + TEXT_OFFSET;
+		status = efi_random_alloc(sys_table_arg, *reserve_size,
+					  MIN_KIMG_ALIGN, reserve_addr,
+					  phys_seed);
+
+		*image_addr = *reserve_addr + TEXT_OFFSET;
+	} else {
+		/*
+		 * Else, try a straight allocation at the preferred offset.
 		 * This will work around the issue where, if dram_base == 0x0,
 		 * efi_low_alloc() refuses to allocate at 0x0 (to prevent the
 		 * address of the allocation to be mistaken for a FAIL return
@@ -52,27 +82,31 @@
 		 * Mustang), we can still place the kernel at the address
 		 * 'dram_base + TEXT_OFFSET'.
 		 */
-		*image_addr = *reserve_addr = preferred_offset;
-		nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) /
-			   EFI_PAGE_SIZE;
-		status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
-					EFI_LOADER_DATA, nr_pages,
-					(efi_physical_addr_t *)reserve_addr);
-		if (status != EFI_SUCCESS) {
-			kernel_memsize += TEXT_OFFSET;
-			status = efi_low_alloc(sys_table_arg, kernel_memsize,
-					       SZ_2M, reserve_addr);
+		if (*image_addr == preferred_offset)
+			return EFI_SUCCESS;
 
-			if (status != EFI_SUCCESS) {
-				pr_efi_err(sys_table_arg, "Failed to relocate kernel\n");
-				return status;
-			}
-			*image_addr = *reserve_addr + TEXT_OFFSET;
-		}
-		memcpy((void *)*image_addr, old_image_addr, kernel_size);
-		*reserve_size = kernel_memsize;
+		*image_addr = *reserve_addr = preferred_offset;
+		*reserve_size = round_up(kernel_memsize, EFI_ALLOC_ALIGN);
+
+		status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
+					EFI_LOADER_DATA,
+					*reserve_size / EFI_PAGE_SIZE,
+					(efi_physical_addr_t *)reserve_addr);
 	}
 
+	if (status != EFI_SUCCESS) {
+		*reserve_size = kernel_memsize + TEXT_OFFSET;
+		status = efi_low_alloc(sys_table_arg, *reserve_size,
+				       MIN_KIMG_ALIGN, reserve_addr);
+
+		if (status != EFI_SUCCESS) {
+			pr_efi_err(sys_table_arg, "Failed to relocate kernel\n");
+			*reserve_size = 0;
+			return status;
+		}
+		*image_addr = *reserve_addr + TEXT_OFFSET;
+	}
+	memcpy((void *)*image_addr, old_image_addr, kernel_size);
 
 	return EFI_SUCCESS;
 }
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index f07d4a6..29ed2f9 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -649,6 +649,10 @@
 	return dst;
 }
 
+#ifndef MAX_CMDLINE_ADDRESS
+#define MAX_CMDLINE_ADDRESS	ULONG_MAX
+#endif
+
 /*
  * Convert the unicode UEFI command line to ASCII to pass to kernel.
  * Size of memory allocated return in *cmd_line_len.
@@ -684,7 +688,8 @@
 
 	options_bytes++;	/* NUL termination */
 
-	status = efi_low_alloc(sys_table_arg, options_bytes, 0, &cmdline_addr);
+	status = efi_high_alloc(sys_table_arg, options_bytes, 0,
+				&cmdline_addr, MAX_CMDLINE_ADDRESS);
 	if (status != EFI_SUCCESS)
 		return NULL;
 
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 6b6548f..5ed3d3f 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -43,4 +43,11 @@
 		     unsigned long desc_size, efi_memory_desc_t *runtime_map,
 		     int *count);
 
+efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table,
+				  unsigned long size, u8 *out);
+
+efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
+			      unsigned long size, unsigned long align,
+			      unsigned long *addr, unsigned long random_seed);
+
 #endif
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index b62e2f5..b1c22cf 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -147,6 +147,20 @@
 	if (status)
 		goto fdt_set_fail;
 
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
+		efi_status_t efi_status;
+
+		efi_status = efi_get_random_bytes(sys_table, sizeof(fdt_val64),
+						  (u8 *)&fdt_val64);
+		if (efi_status == EFI_SUCCESS) {
+			status = fdt_setprop(fdt, node, "kaslr-seed",
+					     &fdt_val64, sizeof(fdt_val64));
+			if (status)
+				goto fdt_set_fail;
+		} else if (efi_status != EFI_NOT_FOUND) {
+			return efi_status;
+		}
+	}
 	return EFI_SUCCESS;
 
 fdt_set_fail:
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
new file mode 100644
index 0000000..53f6d3f
--- /dev/null
+++ b/drivers/firmware/efi/libstub/random.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2016 Linaro Ltd;  <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+
+#include "efistub.h"
+
+struct efi_rng_protocol {
+	efi_status_t (*get_info)(struct efi_rng_protocol *,
+				 unsigned long *, efi_guid_t *);
+	efi_status_t (*get_rng)(struct efi_rng_protocol *,
+				efi_guid_t *, unsigned long, u8 *out);
+};
+
+efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg,
+				  unsigned long size, u8 *out)
+{
+	efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
+	efi_status_t status;
+	struct efi_rng_protocol *rng;
+
+	status = efi_call_early(locate_protocol, &rng_proto, NULL,
+				(void **)&rng);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	return rng->get_rng(rng, NULL, size, out);
+}
+
+/*
+ * Return the number of slots covered by this entry, i.e., the number of
+ * addresses it covers that are suitably aligned and supply enough room
+ * for the allocation.
+ */
+static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
+					 unsigned long size,
+					 unsigned long align)
+{
+	u64 start, end;
+
+	if (md->type != EFI_CONVENTIONAL_MEMORY)
+		return 0;
+
+	start = round_up(md->phys_addr, align);
+	end = round_down(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - size,
+			 align);
+
+	if (start > end)
+		return 0;
+
+	return (end - start + 1) / align;
+}
+
+/*
+ * The UEFI memory descriptors have a virtual address field that is only used
+ * when installing the virtual mapping using SetVirtualAddressMap(). Since it
+ * is unused here, we can reuse it to keep track of each descriptor's slot
+ * count.
+ */
+#define MD_NUM_SLOTS(md)	((md)->virt_addr)
+
+efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
+			      unsigned long size,
+			      unsigned long align,
+			      unsigned long *addr,
+			      unsigned long random_seed)
+{
+	unsigned long map_size, desc_size, total_slots = 0, target_slot;
+	efi_status_t status;
+	efi_memory_desc_t *memory_map;
+	int map_offset;
+
+	status = efi_get_memory_map(sys_table_arg, &memory_map, &map_size,
+				    &desc_size, NULL, NULL);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	if (align < EFI_ALLOC_ALIGN)
+		align = EFI_ALLOC_ALIGN;
+
+	/* count the suitable slots in each memory map entry */
+	for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
+		efi_memory_desc_t *md = (void *)memory_map + map_offset;
+		unsigned long slots;
+
+		slots = get_entry_num_slots(md, size, align);
+		MD_NUM_SLOTS(md) = slots;
+		total_slots += slots;
+	}
+
+	/* find a random number between 0 and total_slots */
+	target_slot = (total_slots * (u16)random_seed) >> 16;
+
+	/*
+	 * target_slot is now a value in the range [0, total_slots), and so
+	 * it corresponds with exactly one of the suitable slots we recorded
+	 * when iterating over the memory map the first time around.
+	 *
+	 * So iterate over the memory map again, subtracting the number of
+	 * slots of each entry at each iteration, until we have found the entry
+	 * that covers our chosen slot. Use the residual value of target_slot
+	 * to calculate the randomly chosen address, and allocate it directly
+	 * using EFI_ALLOCATE_ADDRESS.
+	 */
+	for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
+		efi_memory_desc_t *md = (void *)memory_map + map_offset;
+		efi_physical_addr_t target;
+		unsigned long pages;
+
+		if (target_slot >= MD_NUM_SLOTS(md)) {
+			target_slot -= MD_NUM_SLOTS(md);
+			continue;
+		}
+
+		target = round_up(md->phys_addr, align) + target_slot * align;
+		pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+
+		status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
+					EFI_LOADER_DATA, pages, &target);
+		if (status == EFI_SUCCESS)
+			*addr = target;
+		break;
+	}
+
+	efi_call_early(free_pool, memory_map);
+
+	return status;
+}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b18bea0..469dc37 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -50,6 +50,7 @@
 config OF_GPIO
 	def_bool y
 	depends on OF
+	depends on HAS_IOMEM
 
 config GPIO_ACPI
 	def_bool y
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
index 33a1f97..4ea71d5 100644
--- a/drivers/gpio/gpio-bcm-kona.c
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -551,11 +551,11 @@
 	/* disable interrupts and clear status */
 	for (i = 0; i < kona_gpio->num_bank; i++) {
 		/* Unlock the entire bank first */
-		bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE);
+		bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE);
 		writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
 		writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
 		/* Now re-lock the bank */
-		bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE);
+		bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE);
 	}
 }
 
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c
index 7009747..c50e930 100644
--- a/drivers/gpio/gpio-intel-mid.c
+++ b/drivers/gpio/gpio-intel-mid.c
@@ -17,7 +17,6 @@
  * Moorestown platform Langwell chip.
  * Medfield platform Penwell chip.
  * Clovertrail platform Cloverview chip.
- * Merrifield platform Tangier chip.
  */
 
 #include <linux/module.h>
@@ -64,10 +63,6 @@
 /* intel_mid gpio driver data */
 struct intel_mid_gpio_ddata {
 	u16 ngpio;		/* number of gpio pins */
-	u32 gplr_offset;	/* offset of first GPLR register from base */
-	u32 flis_base;		/* base address of FLIS registers */
-	u32 flis_len;		/* length of FLIS registers */
-	u32 (*get_flis_offset)(int gpio);
 	u32 chip_irq_type;	/* chip interrupt type */
 };
 
@@ -257,15 +252,6 @@
 	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
 };
 
-static const struct intel_mid_gpio_ddata gpio_tangier = {
-	.ngpio = 192,
-	.gplr_offset = 4,
-	.flis_base = 0xff0c0000,
-	.flis_len = 0x8000,
-	.get_flis_offset = NULL,
-	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
-};
-
 static const struct pci_device_id intel_gpio_ids[] = {
 	{
 		/* Lincroft */
@@ -292,11 +278,6 @@
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7),
 		.driver_data = (kernel_ulong_t)&gpio_cloverview_core,
 	},
-	{
-		/* Tangier */
-		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1199),
-		.driver_data = (kernel_ulong_t)&gpio_tangier,
-	},
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, intel_gpio_ids);
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index 48ef368..9e02cb6 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -329,7 +329,7 @@
 				irq_hw_number_t hwirq)
 {
 	irq_set_chip_data(irq, h->host_data);
-	irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq);
+	irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_edge_irq);
 
 	return 0;
 }
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 2d4892c..c844d7e 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -86,7 +86,7 @@
 #define MAX_BANK 5
 #define BANK_SZ 8
 
-#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ)
+#define NBANK(chip) DIV_ROUND_UP(chip->gpio_chip.ngpio, BANK_SZ)
 
 struct pca953x_chip {
 	unsigned gpio_start;
diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c
index 990fa90..3b6bce0 100644
--- a/drivers/gpio/gpio-sa1100.c
+++ b/drivers/gpio/gpio-sa1100.c
@@ -155,7 +155,7 @@
 {
 	irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip,
 				 handle_edge_irq);
-	irq_set_noprobe(irq);
+	irq_set_probe(irq);
 
 	return 0;
 }
diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c
index 3a5c701..8b83099 100644
--- a/drivers/gpio/gpiolib-legacy.c
+++ b/drivers/gpio/gpiolib-legacy.c
@@ -28,6 +28,10 @@
 	if (!desc && gpio_is_valid(gpio))
 		return -EPROBE_DEFER;
 
+	err = gpiod_request(desc, label);
+	if (err)
+		return err;
+
 	if (flags & GPIOF_OPEN_DRAIN)
 		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
 
@@ -37,10 +41,6 @@
 	if (flags & GPIOF_ACTIVE_LOW)
 		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
 
-	err = gpiod_request(desc, label);
-	if (err)
-		return err;
-
 	if (flags & GPIOF_DIR_IN)
 		err = gpiod_direction_input(desc);
 	else
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 4e4c308..06d345b 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -927,14 +927,6 @@
 		spin_lock_irqsave(&gpio_lock, flags);
 	}
 done:
-	if (status < 0) {
-		/* Clear flags that might have been set by the caller before
-		 * requesting the GPIO.
-		 */
-		clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
-		clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
-		clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
-	}
 	spin_unlock_irqrestore(&gpio_lock, flags);
 	return status;
 }
@@ -2062,28 +2054,13 @@
 }
 EXPORT_SYMBOL_GPL(gpiod_get_optional);
 
-/**
- * gpiod_parse_flags - helper function to parse GPIO lookup flags
- * @desc:	gpio to be setup
- * @lflags:	gpio_lookup_flags - returned from of_find_gpio() or
- *		of_get_gpio_hog()
- *
- * Set the GPIO descriptor flags based on the given GPIO lookup flags.
- */
-static void gpiod_parse_flags(struct gpio_desc *desc, unsigned long lflags)
-{
-	if (lflags & GPIO_ACTIVE_LOW)
-		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
-	if (lflags & GPIO_OPEN_DRAIN)
-		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
-	if (lflags & GPIO_OPEN_SOURCE)
-		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
-}
 
 /**
  * gpiod_configure_flags - helper function to configure a given GPIO
  * @desc:	gpio whose value will be assigned
  * @con_id:	function within the GPIO consumer
+ * @lflags:	gpio_lookup_flags - returned from of_find_gpio() or
+ *		of_get_gpio_hog()
  * @dflags:	gpiod_flags - optional GPIO initialization flags
  *
  * Return 0 on success, -ENOENT if no GPIO has been assigned to the
@@ -2091,10 +2068,17 @@
  * occurred while trying to acquire the GPIO.
  */
 static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
-				 enum gpiod_flags dflags)
+		unsigned long lflags, enum gpiod_flags dflags)
 {
 	int status;
 
+	if (lflags & GPIO_ACTIVE_LOW)
+		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+	if (lflags & GPIO_OPEN_DRAIN)
+		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+	if (lflags & GPIO_OPEN_SOURCE)
+		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+
 	/* No particular flag request, return here... */
 	if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
 		pr_debug("no flags found for %s\n", con_id);
@@ -2161,13 +2145,11 @@
 		return desc;
 	}
 
-	gpiod_parse_flags(desc, lookupflags);
-
 	status = gpiod_request(desc, con_id);
 	if (status < 0)
 		return ERR_PTR(status);
 
-	status = gpiod_configure_flags(desc, con_id, flags);
+	status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
 	if (status < 0) {
 		dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
 		gpiod_put(desc);
@@ -2223,6 +2205,10 @@
 	if (IS_ERR(desc))
 		return desc;
 
+	ret = gpiod_request(desc, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
 	if (active_low)
 		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
 
@@ -2233,10 +2219,6 @@
 			set_bit(FLAG_OPEN_SOURCE, &desc->flags);
 	}
 
-	ret = gpiod_request(desc, NULL);
-	if (ret)
-		return ERR_PTR(ret);
-
 	return desc;
 }
 EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
@@ -2289,8 +2271,6 @@
 	chip = gpiod_to_chip(desc);
 	hwnum = gpio_chip_hwgpio(desc);
 
-	gpiod_parse_flags(desc, lflags);
-
 	local_desc = gpiochip_request_own_desc(chip, hwnum, name);
 	if (IS_ERR(local_desc)) {
 		pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n",
@@ -2298,7 +2278,7 @@
 		return PTR_ERR(local_desc);
 	}
 
-	status = gpiod_configure_flags(desc, name, dflags);
+	status = gpiod_configure_flags(desc, name, lflags, dflags);
 	if (status < 0) {
 		pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n",
 		       name, chip->label, hwnum);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 053fc2f..e8e962f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -532,6 +532,7 @@
 	u64				metadata_flags;
 	void				*metadata;
 	u32				metadata_size;
+	unsigned			prime_shared_count;
 	/* list of all virtual address to which this bo
 	 * is associated to
 	 */
@@ -710,9 +711,9 @@
 void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev);
 int amdgpu_gart_init(struct amdgpu_device *adev);
 void amdgpu_gart_fini(struct amdgpu_device *adev);
-void amdgpu_gart_unbind(struct amdgpu_device *adev, unsigned offset,
+void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
 			int pages);
-int amdgpu_gart_bind(struct amdgpu_device *adev, unsigned offset,
+int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
 		     int pages, struct page **pagelist,
 		     dma_addr_t *dma_addr, uint32_t flags);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 9416e0f..f4cae53 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -331,6 +331,19 @@
 			    (le16_to_cpu(path->usConnObjectId) &
 			     OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
 
+			/* Skip TV/CV support */
+			if ((le16_to_cpu(path->usDeviceTag) ==
+			     ATOM_DEVICE_TV1_SUPPORT) ||
+			    (le16_to_cpu(path->usDeviceTag) ==
+			     ATOM_DEVICE_CV_SUPPORT))
+				continue;
+
+			if (con_obj_id >= ARRAY_SIZE(object_connector_convert)) {
+				DRM_ERROR("invalid con_obj_id %d for device tag 0x%04x\n",
+					  con_obj_id, le16_to_cpu(path->usDeviceTag));
+				continue;
+			}
+
 			connector_type =
 				object_connector_convert[con_obj_id];
 			connector_object_id = con_obj_id;
@@ -566,28 +579,19 @@
 		    le16_to_cpu(firmware_info->info.usReferenceClock);
 		ppll->reference_div = 0;
 
-		if (crev < 2)
-			ppll->pll_out_min =
-				le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
-		else
-			ppll->pll_out_min =
-				le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
+		ppll->pll_out_min =
+			le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
 		ppll->pll_out_max =
 		    le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
 
-		if (crev >= 4) {
-			ppll->lcd_pll_out_min =
-				le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
-			if (ppll->lcd_pll_out_min == 0)
-				ppll->lcd_pll_out_min = ppll->pll_out_min;
-			ppll->lcd_pll_out_max =
-				le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
-			if (ppll->lcd_pll_out_max == 0)
-				ppll->lcd_pll_out_max = ppll->pll_out_max;
-		} else {
+		ppll->lcd_pll_out_min =
+			le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
+		if (ppll->lcd_pll_out_min == 0)
 			ppll->lcd_pll_out_min = ppll->pll_out_min;
+		ppll->lcd_pll_out_max =
+			le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
+		if (ppll->lcd_pll_out_max == 0)
 			ppll->lcd_pll_out_max = ppll->pll_out_max;
-		}
 
 		if (ppll->pll_out_min == 0)
 			ppll->pll_out_min = 64800;
@@ -677,6 +681,10 @@
 			DRM_INFO("Changing default dispclk from %dMhz to 600Mhz\n",
 				 adev->clock.default_dispclk / 100);
 			adev->clock.default_dispclk = 60000;
+		} else if (adev->clock.default_dispclk <= 60000) {
+			DRM_INFO("Changing default dispclk from %dMhz to 625Mhz\n",
+				 adev->clock.default_dispclk / 100);
+			adev->clock.default_dispclk = 62500;
 		}
 		adev->clock.dp_extclk =
 			le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 5a8fbad..29adbbe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 
 #include "amdgpu_acpi.h"
 
@@ -256,6 +257,10 @@
 		if (!info)
 			return -EIO;
 		kfree(info);
+
+		/* 200ms delay is required after off */
+		if (state == 0)
+			msleep(200);
 	}
 	return 0;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
index f82a2dd..3c7a723 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
@@ -117,7 +117,7 @@
 			entry->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
 		}
 		entry->tv.bo = &entry->robj->tbo;
-		entry->tv.shared = true;
+		entry->tv.shared = !entry->robj->prime_shared_count;
 
 		if (entry->prefered_domains == AMDGPU_GEM_DOMAIN_GDS)
 			gds_obj = entry->robj;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index 119cdc2..9300833 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -194,12 +194,12 @@
 				bpc = 8;
 				DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n",
 					  connector->name, bpc);
-			} else if (bpc > 8) {
-				/* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
-				DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
-					  connector->name);
-				bpc = 8;
 			}
+		} else if (bpc > 8) {
+			/* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
+			DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
+				  connector->name);
+			bpc = 8;
 		}
 	}
 
@@ -1690,7 +1690,6 @@
 						   DRM_MODE_SCALE_NONE);
 			/* no HPD on analog connectors */
 			amdgpu_connector->hpd.hpd = AMDGPU_HPD_NONE;
-			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 			connector->interlace_allowed = true;
 			connector->doublescan_allowed = true;
 			break;
@@ -1893,8 +1892,10 @@
 	}
 
 	if (amdgpu_connector->hpd.hpd == AMDGPU_HPD_NONE) {
-		if (i2c_bus->valid)
-			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+		if (i2c_bus->valid) {
+			connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+			                    DRM_CONNECTOR_POLL_DISCONNECT;
+		}
 	} else
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 25a3e248..2bc17a9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -124,6 +124,13 @@
 		}
 		break;
 	}
+
+	if (!(*out_ring && (*out_ring)->adev)) {
+		DRM_ERROR("Ring %d is not initialized on IP %d\n",
+			  ring, ip_type);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index c961fe0..16302f7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1793,7 +1793,23 @@
 	}
 
 	drm_kms_helper_poll_enable(dev);
+
+	/*
+	 * Most of the connector probing functions try to acquire runtime pm
+	 * refs to ensure that the GPU is powered on when connector polling is
+	 * performed. Since we're calling this from a runtime PM callback,
+	 * trying to acquire rpm refs will cause us to deadlock.
+	 *
+	 * Since we're guaranteed to be holding the rpm lock, it's safe to
+	 * temporarily disable the rpm helpers so this doesn't deadlock us.
+	 */
+#ifdef CONFIG_PM
+	dev->dev->power.disable_depth++;
+#endif
 	drm_helper_hpd_irq_event(dev);
+#ifdef CONFIG_PM
+	dev->dev->power.disable_depth--;
+#endif
 
 	if (fbcon) {
 		amdgpu_fbdev_set_suspend(adev, 0);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
index 7b7f4ab..14f57d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
@@ -113,24 +113,26 @@
 	printk("\n");
 }
 
+
 u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
 {
 	struct drm_device *dev = adev->ddev;
 	struct drm_crtc *crtc;
 	struct amdgpu_crtc *amdgpu_crtc;
-	u32 line_time_us, vblank_lines;
+	u32 vblank_in_pixels;
 	u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
 
 	if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
 		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 			amdgpu_crtc = to_amdgpu_crtc(crtc);
 			if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
-				line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) /
-					amdgpu_crtc->hw_mode.clock;
-				vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end -
+				vblank_in_pixels =
+					amdgpu_crtc->hw_mode.crtc_htotal *
+					(amdgpu_crtc->hw_mode.crtc_vblank_end -
 					amdgpu_crtc->hw_mode.crtc_vdisplay +
-					(amdgpu_crtc->v_border * 2);
-				vblank_time_us = vblank_lines * line_time_us;
+					(amdgpu_crtc->v_border * 2));
+
+				vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
 				break;
 			}
 		}
@@ -150,7 +152,7 @@
 		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 			amdgpu_crtc = to_amdgpu_crtc(crtc);
 			if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
-				vrefresh = amdgpu_crtc->hw_mode.vrefresh;
+				vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
 				break;
 			}
 		}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
index 7312d72..22a613a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
@@ -221,7 +221,7 @@
  * Unbinds the requested pages from the gart page table and
  * replaces them with the dummy page (all asics).
  */
-void amdgpu_gart_unbind(struct amdgpu_device *adev, unsigned offset,
+void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
 			int pages)
 {
 	unsigned t;
@@ -269,7 +269,7 @@
  * (all asics).
  * Returns 0 for success, -EINVAL for failure.
  */
-int amdgpu_gart_bind(struct amdgpu_device *adev, unsigned offset,
+int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
 		     int pages, struct page **pagelist, dma_addr_t *dma_addr,
 		     uint32_t flags)
 {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 9e25eda..c77a1eb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -288,7 +288,7 @@
 int amdgpu_ib_ring_tests(struct amdgpu_device *adev)
 {
 	unsigned i;
-	int r;
+	int r, ret = 0;
 
 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
 		struct amdgpu_ring *ring = adev->rings[i];
@@ -309,10 +309,11 @@
 			} else {
 				/* still not good, but we can live with it */
 				DRM_ERROR("amdgpu: failed testing IB on ring %d (%d).\n", i, r);
+				ret = r;
 			}
 		}
 	}
-	return 0;
+	return ret;
 }
 
 /*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index 7c42ff6..a092433 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -25,6 +25,7 @@
  *          Alex Deucher
  *          Jerome Glisse
  */
+#include <linux/irq.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/amdgpu_drm.h>
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 4488e82..a5c8240 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -227,7 +227,7 @@
 			type = AMD_IP_BLOCK_TYPE_UVD;
 			ring_mask = adev->uvd.ring.ready ? 1 : 0;
 			ib_start_alignment = AMDGPU_GPU_PAGE_SIZE;
-			ib_size_alignment = 8;
+			ib_size_alignment = 16;
 			break;
 		case AMDGPU_HW_IP_VCE:
 			type = AMD_IP_BLOCK_TYPE_VCE;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
index 59f735a..e6a7d30 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
@@ -77,20 +77,36 @@
 	list_add_tail(&bo->list, &adev->gem.objects);
 	mutex_unlock(&adev->gem.mutex);
 
+	bo->prime_shared_count = 1;
 	return &bo->gem_base;
 }
 
 int amdgpu_gem_prime_pin(struct drm_gem_object *obj)
 {
 	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
-	int ret = 0;
+	long ret = 0;
 
 	ret = amdgpu_bo_reserve(bo, false);
 	if (unlikely(ret != 0))
 		return ret;
 
+	/*
+	 * Wait for all shared fences to complete before we switch to future
+	 * use of exclusive fence on this prime shared bo.
+	 */
+	ret = reservation_object_wait_timeout_rcu(bo->tbo.resv, true, false,
+						  MAX_SCHEDULE_TIMEOUT);
+	if (unlikely(ret < 0)) {
+		DRM_DEBUG_PRIME("Fence wait failed: %li\n", ret);
+		amdgpu_bo_unreserve(bo);
+		return ret;
+	}
+
 	/* pin buffer into GTT */
 	ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL);
+	if (likely(ret == 0))
+		bo->prime_shared_count++;
+
 	amdgpu_bo_unreserve(bo);
 	return ret;
 }
@@ -105,6 +121,8 @@
 		return;
 
 	amdgpu_bo_unpin(bo);
+	if (bo->prime_shared_count)
+		bo->prime_shared_count--;
 	amdgpu_bo_unreserve(bo);
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 1cbb16e..475c38f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -233,8 +233,8 @@
 
 	adev = amdgpu_get_adev(bo->bdev);
 	ring = adev->mman.buffer_funcs_ring;
-	old_start = old_mem->start << PAGE_SHIFT;
-	new_start = new_mem->start << PAGE_SHIFT;
+	old_start = (u64)old_mem->start << PAGE_SHIFT;
+	new_start = (u64)new_mem->start << PAGE_SHIFT;
 
 	switch (old_mem->mem_type) {
 	case TTM_PL_VRAM:
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
index 49aa350..247b088 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
@@ -164,7 +164,7 @@
 	struct drm_device *dev = crtc->dev;
 	struct amdgpu_device *adev = dev->dev_private;
 	int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating);
-	ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args;
+	ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;
 
 	memset(&args, 0, sizeof(args));
 
@@ -177,7 +177,7 @@
 void amdgpu_atombios_crtc_powergate_init(struct amdgpu_device *adev)
 {
 	int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating);
-	ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args;
+	ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;
 
 	memset(&args, 0, sizeof(args));
 
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
index 92b6aca..7f85c2c 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
@@ -243,7 +243,7 @@
 
 /* convert bits per color to bits per pixel */
 /* get bpc from the EDID */
-static int amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc)
+static unsigned amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc)
 {
 	if (bpc == 0)
 		return 24;
@@ -251,64 +251,44 @@
 		return bpc * 3;
 }
 
-/* get the max pix clock supported by the link rate and lane num */
-static int amdgpu_atombios_dp_get_max_dp_pix_clock(int link_rate,
-					    int lane_num,
-					    int bpp)
-{
-	return (link_rate * lane_num * 8) / bpp;
-}
-
 /***** amdgpu specific DP functions *****/
 
-/* First get the min lane# when low rate is used according to pixel clock
- * (prefer low rate), second check max lane# supported by DP panel,
- * if the max lane# < low rate lane# then use max lane# instead.
- */
-static int amdgpu_atombios_dp_get_dp_lane_number(struct drm_connector *connector,
+static int amdgpu_atombios_dp_get_dp_link_config(struct drm_connector *connector,
 						 const u8 dpcd[DP_DPCD_SIZE],
-						 int pix_clock)
+						 unsigned pix_clock,
+						 unsigned *dp_lanes, unsigned *dp_rate)
 {
-	int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
-	int max_link_rate = drm_dp_max_link_rate(dpcd);
-	int max_lane_num = drm_dp_max_lane_count(dpcd);
-	int lane_num;
-	int max_dp_pix_clock;
-
-	for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) {
-		max_dp_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp);
-		if (pix_clock <= max_dp_pix_clock)
-			break;
-	}
-
-	return lane_num;
-}
-
-static int amdgpu_atombios_dp_get_dp_link_clock(struct drm_connector *connector,
-						const u8 dpcd[DP_DPCD_SIZE],
-						int pix_clock)
-{
-	int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
-	int lane_num, max_pix_clock;
+	unsigned bpp =
+		amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
+	static const unsigned link_rates[3] = { 162000, 270000, 540000 };
+	unsigned max_link_rate = drm_dp_max_link_rate(dpcd);
+	unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
+	unsigned lane_num, i, max_pix_clock;
 
 	if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) ==
-	    ENCODER_OBJECT_ID_NUTMEG)
-		return 270000;
-
-	lane_num = amdgpu_atombios_dp_get_dp_lane_number(connector, dpcd, pix_clock);
-	max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(162000, lane_num, bpp);
-	if (pix_clock <= max_pix_clock)
-		return 162000;
-	max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(270000, lane_num, bpp);
-	if (pix_clock <= max_pix_clock)
-		return 270000;
-	if (amdgpu_connector_is_dp12_capable(connector)) {
-		max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(540000, lane_num, bpp);
-		if (pix_clock <= max_pix_clock)
-			return 540000;
+	    ENCODER_OBJECT_ID_NUTMEG) {
+		for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+			max_pix_clock = (lane_num * 270000 * 8) / bpp;
+			if (max_pix_clock >= pix_clock) {
+				*dp_lanes = lane_num;
+				*dp_rate = 270000;
+				return 0;
+			}
+		}
+	} else {
+		for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
+			for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+				max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
+				if (max_pix_clock >= pix_clock) {
+					*dp_lanes = lane_num;
+					*dp_rate = link_rates[i];
+					return 0;
+				}
+			}
+		}
 	}
 
-	return drm_dp_max_link_rate(dpcd);
+	return -EINVAL;
 }
 
 static u8 amdgpu_atombios_dp_encoder_service(struct amdgpu_device *adev,
@@ -422,6 +402,7 @@
 {
 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 	struct amdgpu_connector_atom_dig *dig_connector;
+	int ret;
 
 	if (!amdgpu_connector->con_priv)
 		return;
@@ -429,10 +410,14 @@
 
 	if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
 	    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
-		dig_connector->dp_clock =
-			amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
-		dig_connector->dp_lane_count =
-			amdgpu_atombios_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock);
+		ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd,
+							    mode->clock,
+							    &dig_connector->dp_lane_count,
+							    &dig_connector->dp_clock);
+		if (ret) {
+			dig_connector->dp_clock = 0;
+			dig_connector->dp_lane_count = 0;
+		}
 	}
 }
 
@@ -441,14 +426,17 @@
 {
 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 	struct amdgpu_connector_atom_dig *dig_connector;
-	int dp_clock;
+	unsigned dp_lanes, dp_clock;
+	int ret;
 
 	if (!amdgpu_connector->con_priv)
 		return MODE_CLOCK_HIGH;
 	dig_connector = amdgpu_connector->con_priv;
 
-	dp_clock =
-		amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
+	ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd,
+						    mode->clock, &dp_lanes, &dp_clock);
+	if (ret)
+		return MODE_CLOCK_HIGH;
 
 	if ((dp_clock == 540000) &&
 	    (!amdgpu_connector_is_dp12_capable(connector)))
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
index 1cd6de5..542517d 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
@@ -98,6 +98,7 @@
 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
 			if (dig->backlight_level == 0)
 				amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
 								       ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index 57a2e34..0f0094b5 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -893,6 +893,12 @@
 	u32 vblank_time = amdgpu_dpm_get_vblank_time(adev);
 	u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 300;
 
+	/* disable mclk switching if the refresh is >120Hz, even if the
+	 * blanking period would allow it
+	 */
+	if (amdgpu_dpm_get_vrefresh(adev) > 120)
+		return true;
+
 	if (vblank_time < switch_limit)
 		return true;
 	else
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 5f712ce..c568293 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -52,6 +52,7 @@
 static void cik_sdma_set_irq_funcs(struct amdgpu_device *adev);
 static void cik_sdma_set_buffer_funcs(struct amdgpu_device *adev);
 static void cik_sdma_set_vm_pte_funcs(struct amdgpu_device *adev);
+static int cik_sdma_soft_reset(void *handle);
 
 MODULE_FIRMWARE("radeon/bonaire_sdma.bin");
 MODULE_FIRMWARE("radeon/bonaire_sdma1.bin");
@@ -1030,6 +1031,8 @@
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+	cik_sdma_soft_reset(handle);
+
 	return cik_sdma_hw_init(adev);
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
index 8035d4d..653917a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
@@ -1955,10 +1955,8 @@
 		}
 	} else { /*pi->caps_vce_pg*/
 		cz_update_vce_dpm(adev);
-		cz_enable_vce_dpm(adev, true);
+		cz_enable_vce_dpm(adev, !gate);
 	}
-
-	return;
 }
 
 const struct amd_ip_funcs cz_dpm_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 093599a..3a25da4 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -419,16 +419,6 @@
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
-		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
-			/* don't try to enable hpd on eDP or LVDS avoid breaking the
-			 * aux dp channel on imac and help (but not completely fix)
-			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
-			 * also avoid interrupt storms during dpms.
-			 */
-			continue;
-		}
-
 		switch (amdgpu_connector->hpd.hpd) {
 		case AMDGPU_HPD_1:
 			idx = 0;
@@ -452,6 +442,19 @@
 			continue;
 		}
 
+		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+			/* don't try to enable hpd on eDP or LVDS avoid breaking the
+			 * aux dp channel on imac and help (but not completely fix)
+			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+			 * also avoid interrupt storms during dpms.
+			 */
+			tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+			tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_EN, 0);
+			WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+			continue;
+		}
+
 		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 1);
 		WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
@@ -1123,23 +1126,10 @@
 	a.full = dfixed_const(available_bandwidth);
 	b.full = dfixed_const(wm->num_heads);
 	a.full = dfixed_div(a, b);
+	tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
+	tmp = min(dfixed_trunc(a), tmp);
 
-	b.full = dfixed_const(mc_latency + 512);
-	c.full = dfixed_const(wm->disp_clk);
-	b.full = dfixed_div(b, c);
-
-	c.full = dfixed_const(dmif_size);
-	b.full = dfixed_div(c, b);
-
-	tmp = min(dfixed_trunc(a), dfixed_trunc(b));
-
-	b.full = dfixed_const(1000);
-	c.full = dfixed_const(wm->disp_clk);
-	b.full = dfixed_div(c, b);
-	c.full = dfixed_const(wm->bytes_per_pixel);
-	b.full = dfixed_mul(b, c);
-
-	lb_fill_bw = min(tmp, dfixed_trunc(b));
+	lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
 
 	a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
 	b.full = dfixed_const(1000);
@@ -1247,14 +1237,14 @@
 {
 	struct drm_display_mode *mode = &amdgpu_crtc->base.mode;
 	struct dce10_wm_params wm_low, wm_high;
-	u32 pixel_period;
+	u32 active_time;
 	u32 line_time = 0;
 	u32 latency_watermark_a = 0, latency_watermark_b = 0;
 	u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
 
 	if (amdgpu_crtc->base.enabled && num_heads && mode) {
-		pixel_period = 1000000 / (u32)mode->clock;
-		line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535);
+		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
+		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
 
 		/* watermark for high clocks */
 		if (adev->pm.dpm_enabled) {
@@ -1269,7 +1259,7 @@
 
 		wm_high.disp_clk = mode->clock;
 		wm_high.src_width = mode->crtc_hdisplay;
-		wm_high.active_time = mode->crtc_hdisplay * pixel_period;
+		wm_high.active_time = active_time;
 		wm_high.blank_time = line_time - wm_high.active_time;
 		wm_high.interlaced = false;
 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -1308,7 +1298,7 @@
 
 		wm_low.disp_clk = mode->clock;
 		wm_low.src_width = mode->crtc_hdisplay;
-		wm_low.active_time = mode->crtc_hdisplay * pixel_period;
+		wm_low.active_time = active_time;
 		wm_low.blank_time = line_time - wm_low.active_time;
 		wm_low.interlaced = false;
 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -3729,7 +3719,7 @@
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 		drm_encoder_init(dev, encoder, &dce_v10_0_encoder_funcs,
-				 DRM_MODE_ENCODER_DAC, NULL);
+				 DRM_MODE_ENCODER_DAC);
 		drm_encoder_helper_add(encoder, &dce_v10_0_dac_helper_funcs);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
@@ -3740,15 +3730,15 @@
 		if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 			amdgpu_encoder->rmx_type = RMX_FULL;
 			drm_encoder_init(dev, encoder, &dce_v10_0_encoder_funcs,
-					 DRM_MODE_ENCODER_LVDS, NULL);
+					 DRM_MODE_ENCODER_LVDS);
 			amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_lcd_info(amdgpu_encoder);
 		} else if (amdgpu_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
 			drm_encoder_init(dev, encoder, &dce_v10_0_encoder_funcs,
-					 DRM_MODE_ENCODER_DAC, NULL);
+					 DRM_MODE_ENCODER_DAC);
 			amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_dig_info(amdgpu_encoder);
 		} else {
 			drm_encoder_init(dev, encoder, &dce_v10_0_encoder_funcs,
-					 DRM_MODE_ENCODER_TMDS, NULL);
+					 DRM_MODE_ENCODER_TMDS);
 			amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_dig_info(amdgpu_encoder);
 		}
 		drm_encoder_helper_add(encoder, &dce_v10_0_dig_helper_funcs);
@@ -3766,13 +3756,13 @@
 		amdgpu_encoder->is_ext_encoder = true;
 		if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
 			drm_encoder_init(dev, encoder, &dce_v10_0_encoder_funcs,
-					 DRM_MODE_ENCODER_LVDS, NULL);
+					 DRM_MODE_ENCODER_LVDS);
 		else if (amdgpu_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
 			drm_encoder_init(dev, encoder, &dce_v10_0_encoder_funcs,
-					 DRM_MODE_ENCODER_DAC, NULL);
+					 DRM_MODE_ENCODER_DAC);
 		else
 			drm_encoder_init(dev, encoder, &dce_v10_0_encoder_funcs,
-					 DRM_MODE_ENCODER_TMDS, NULL);
+					 DRM_MODE_ENCODER_TMDS);
 		drm_encoder_helper_add(encoder, &dce_v10_0_ext_helper_funcs);
 		break;
 	}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 8701661..d6d3cda 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -409,16 +409,6 @@
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
-		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
-			/* don't try to enable hpd on eDP or LVDS avoid breaking the
-			 * aux dp channel on imac and help (but not completely fix)
-			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
-			 * also avoid interrupt storms during dpms.
-			 */
-			continue;
-		}
-
 		switch (amdgpu_connector->hpd.hpd) {
 		case AMDGPU_HPD_1:
 			idx = 0;
@@ -442,6 +432,19 @@
 			continue;
 		}
 
+		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+			/* don't try to enable hpd on eDP or LVDS avoid breaking the
+			 * aux dp channel on imac and help (but not completely fix)
+			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+			 * also avoid interrupt storms during dpms.
+			 */
+			tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+			tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_EN, 0);
+			WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+			continue;
+		}
+
 		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 1);
 		WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
@@ -1111,23 +1114,10 @@
 	a.full = dfixed_const(available_bandwidth);
 	b.full = dfixed_const(wm->num_heads);
 	a.full = dfixed_div(a, b);
+	tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
+	tmp = min(dfixed_trunc(a), tmp);
 
-	b.full = dfixed_const(mc_latency + 512);
-	c.full = dfixed_const(wm->disp_clk);
-	b.full = dfixed_div(b, c);
-
-	c.full = dfixed_const(dmif_size);
-	b.full = dfixed_div(c, b);
-
-	tmp = min(dfixed_trunc(a), dfixed_trunc(b));
-
-	b.full = dfixed_const(1000);
-	c.full = dfixed_const(wm->disp_clk);
-	b.full = dfixed_div(c, b);
-	c.full = dfixed_const(wm->bytes_per_pixel);
-	b.full = dfixed_mul(b, c);
-
-	lb_fill_bw = min(tmp, dfixed_trunc(b));
+	lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
 
 	a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
 	b.full = dfixed_const(1000);
@@ -1235,14 +1225,14 @@
 {
 	struct drm_display_mode *mode = &amdgpu_crtc->base.mode;
 	struct dce10_wm_params wm_low, wm_high;
-	u32 pixel_period;
+	u32 active_time;
 	u32 line_time = 0;
 	u32 latency_watermark_a = 0, latency_watermark_b = 0;
 	u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
 
 	if (amdgpu_crtc->base.enabled && num_heads && mode) {
-		pixel_period = 1000000 / (u32)mode->clock;
-		line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535);
+		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
+		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
 
 		/* watermark for high clocks */
 		if (adev->pm.dpm_enabled) {
@@ -1257,7 +1247,7 @@
 
 		wm_high.disp_clk = mode->clock;
 		wm_high.src_width = mode->crtc_hdisplay;
-		wm_high.active_time = mode->crtc_hdisplay * pixel_period;
+		wm_high.active_time = active_time;
 		wm_high.blank_time = line_time - wm_high.active_time;
 		wm_high.interlaced = false;
 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -1296,7 +1286,7 @@
 
 		wm_low.disp_clk = mode->clock;
 		wm_low.src_width = mode->crtc_hdisplay;
-		wm_low.active_time = mode->crtc_hdisplay * pixel_period;
+		wm_low.active_time = active_time;
 		wm_low.blank_time = line_time - wm_low.active_time;
 		wm_low.interlaced = false;
 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -3030,6 +3020,7 @@
 
 	dce_v11_0_afmt_fini(adev);
 
+	drm_mode_config_cleanup(adev->ddev);
 	adev->mode_info.mode_config_initialized = false;
 
 	return 0;
@@ -3700,9 +3691,15 @@
 	default:
 		encoder->possible_crtcs = 0x3;
 		break;
+	case 3:
+		encoder->possible_crtcs = 0x7;
+		break;
 	case 4:
 		encoder->possible_crtcs = 0xf;
 		break;
+	case 5:
+		encoder->possible_crtcs = 0x1f;
+		break;
 	case 6:
 		encoder->possible_crtcs = 0x3f;
 		break;
@@ -3722,7 +3719,7 @@
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 		drm_encoder_init(dev, encoder, &dce_v11_0_encoder_funcs,
-				 DRM_MODE_ENCODER_DAC, NULL);
+				 DRM_MODE_ENCODER_DAC);
 		drm_encoder_helper_add(encoder, &dce_v11_0_dac_helper_funcs);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
@@ -3733,15 +3730,15 @@
 		if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 			amdgpu_encoder->rmx_type = RMX_FULL;
 			drm_encoder_init(dev, encoder, &dce_v11_0_encoder_funcs,
-					 DRM_MODE_ENCODER_LVDS, NULL);
+					 DRM_MODE_ENCODER_LVDS);
 			amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_lcd_info(amdgpu_encoder);
 		} else if (amdgpu_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
 			drm_encoder_init(dev, encoder, &dce_v11_0_encoder_funcs,
-					 DRM_MODE_ENCODER_DAC, NULL);
+					 DRM_MODE_ENCODER_DAC);
 			amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_dig_info(amdgpu_encoder);
 		} else {
 			drm_encoder_init(dev, encoder, &dce_v11_0_encoder_funcs,
-					 DRM_MODE_ENCODER_TMDS, NULL);
+					 DRM_MODE_ENCODER_TMDS);
 			amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_dig_info(amdgpu_encoder);
 		}
 		drm_encoder_helper_add(encoder, &dce_v11_0_dig_helper_funcs);
@@ -3759,13 +3756,13 @@
 		amdgpu_encoder->is_ext_encoder = true;
 		if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
 			drm_encoder_init(dev, encoder, &dce_v11_0_encoder_funcs,
-					 DRM_MODE_ENCODER_LVDS, NULL);
+					 DRM_MODE_ENCODER_LVDS);
 		else if (amdgpu_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
 			drm_encoder_init(dev, encoder, &dce_v11_0_encoder_funcs,
-					 DRM_MODE_ENCODER_DAC, NULL);
+					 DRM_MODE_ENCODER_DAC);
 		else
 			drm_encoder_init(dev, encoder, &dce_v11_0_encoder_funcs,
-					 DRM_MODE_ENCODER_TMDS, NULL);
+					 DRM_MODE_ENCODER_TMDS);
 		drm_encoder_helper_add(encoder, &dce_v11_0_ext_helper_funcs);
 		break;
 	}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index d0e128c..d6e51d4 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -392,15 +392,6 @@
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
-		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
-			/* don't try to enable hpd on eDP or LVDS avoid breaking the
-			 * aux dp channel on imac and help (but not completely fix)
-			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
-			 * also avoid interrupt storms during dpms.
-			 */
-			continue;
-		}
 		switch (amdgpu_connector->hpd.hpd) {
 		case AMDGPU_HPD_1:
 			WREG32(mmDC_HPD1_CONTROL, tmp);
@@ -423,6 +414,45 @@
 		default:
 			break;
 		}
+
+		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+			/* don't try to enable hpd on eDP or LVDS avoid breaking the
+			 * aux dp channel on imac and help (but not completely fix)
+			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+			 * also avoid interrupt storms during dpms.
+			 */
+			u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl;
+
+			switch (amdgpu_connector->hpd.hpd) {
+			case AMDGPU_HPD_1:
+				dc_hpd_int_cntl_reg = mmDC_HPD1_INT_CONTROL;
+				break;
+			case AMDGPU_HPD_2:
+				dc_hpd_int_cntl_reg = mmDC_HPD2_INT_CONTROL;
+				break;
+			case AMDGPU_HPD_3:
+				dc_hpd_int_cntl_reg = mmDC_HPD3_INT_CONTROL;
+				break;
+			case AMDGPU_HPD_4:
+				dc_hpd_int_cntl_reg = mmDC_HPD4_INT_CONTROL;
+				break;
+			case AMDGPU_HPD_5:
+				dc_hpd_int_cntl_reg = mmDC_HPD5_INT_CONTROL;
+				break;
+			case AMDGPU_HPD_6:
+				dc_hpd_int_cntl_reg = mmDC_HPD6_INT_CONTROL;
+				break;
+			default:
+				continue;
+			}
+
+			dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
+			dc_hpd_int_cntl &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
+			WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+			continue;
+		}
+
 		dce_v8_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
 		amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
 	}
@@ -1066,23 +1096,10 @@
 	a.full = dfixed_const(available_bandwidth);
 	b.full = dfixed_const(wm->num_heads);
 	a.full = dfixed_div(a, b);
+	tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
+	tmp = min(dfixed_trunc(a), tmp);
 
-	b.full = dfixed_const(mc_latency + 512);
-	c.full = dfixed_const(wm->disp_clk);
-	b.full = dfixed_div(b, c);
-
-	c.full = dfixed_const(dmif_size);
-	b.full = dfixed_div(c, b);
-
-	tmp = min(dfixed_trunc(a), dfixed_trunc(b));
-
-	b.full = dfixed_const(1000);
-	c.full = dfixed_const(wm->disp_clk);
-	b.full = dfixed_div(c, b);
-	c.full = dfixed_const(wm->bytes_per_pixel);
-	b.full = dfixed_mul(b, c);
-
-	lb_fill_bw = min(tmp, dfixed_trunc(b));
+	lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
 
 	a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
 	b.full = dfixed_const(1000);
@@ -1190,14 +1207,14 @@
 {
 	struct drm_display_mode *mode = &amdgpu_crtc->base.mode;
 	struct dce8_wm_params wm_low, wm_high;
-	u32 pixel_period;
+	u32 active_time;
 	u32 line_time = 0;
 	u32 latency_watermark_a = 0, latency_watermark_b = 0;
 	u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
 
 	if (amdgpu_crtc->base.enabled && num_heads && mode) {
-		pixel_period = 1000000 / (u32)mode->clock;
-		line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535);
+		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
+		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
 
 		/* watermark for high clocks */
 		if (adev->pm.dpm_enabled) {
@@ -1212,7 +1229,7 @@
 
 		wm_high.disp_clk = mode->clock;
 		wm_high.src_width = mode->crtc_hdisplay;
-		wm_high.active_time = mode->crtc_hdisplay * pixel_period;
+		wm_high.active_time = active_time;
 		wm_high.blank_time = line_time - wm_high.active_time;
 		wm_high.interlaced = false;
 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -1251,7 +1268,7 @@
 
 		wm_low.disp_clk = mode->clock;
 		wm_low.src_width = mode->crtc_hdisplay;
-		wm_low.active_time = mode->crtc_hdisplay * pixel_period;
+		wm_low.active_time = active_time;
 		wm_low.blank_time = line_time - wm_low.active_time;
 		wm_low.interlaced = false;
 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -3659,7 +3676,7 @@
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 		drm_encoder_init(dev, encoder, &dce_v8_0_encoder_funcs,
-				 DRM_MODE_ENCODER_DAC, NULL);
+				 DRM_MODE_ENCODER_DAC);
 		drm_encoder_helper_add(encoder, &dce_v8_0_dac_helper_funcs);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
@@ -3670,15 +3687,15 @@
 		if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 			amdgpu_encoder->rmx_type = RMX_FULL;
 			drm_encoder_init(dev, encoder, &dce_v8_0_encoder_funcs,
-					 DRM_MODE_ENCODER_LVDS, NULL);
+					 DRM_MODE_ENCODER_LVDS);
 			amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_lcd_info(amdgpu_encoder);
 		} else if (amdgpu_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
 			drm_encoder_init(dev, encoder, &dce_v8_0_encoder_funcs,
-					 DRM_MODE_ENCODER_DAC, NULL);
+					 DRM_MODE_ENCODER_DAC);
 			amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_dig_info(amdgpu_encoder);
 		} else {
 			drm_encoder_init(dev, encoder, &dce_v8_0_encoder_funcs,
-					 DRM_MODE_ENCODER_TMDS, NULL);
+					 DRM_MODE_ENCODER_TMDS);
 			amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_dig_info(amdgpu_encoder);
 		}
 		drm_encoder_helper_add(encoder, &dce_v8_0_dig_helper_funcs);
@@ -3696,13 +3713,13 @@
 		amdgpu_encoder->is_ext_encoder = true;
 		if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
 			drm_encoder_init(dev, encoder, &dce_v8_0_encoder_funcs,
-					 DRM_MODE_ENCODER_LVDS, NULL);
+					 DRM_MODE_ENCODER_LVDS);
 		else if (amdgpu_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
 			drm_encoder_init(dev, encoder, &dce_v8_0_encoder_funcs,
-					 DRM_MODE_ENCODER_DAC, NULL);
+					 DRM_MODE_ENCODER_DAC);
 		else
 			drm_encoder_init(dev, encoder, &dce_v8_0_encoder_funcs,
-					 DRM_MODE_ENCODER_TMDS, NULL);
+					 DRM_MODE_ENCODER_TMDS);
 		drm_encoder_helper_add(encoder, &dce_v8_0_ext_helper_funcs);
 		break;
 	}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index 9463007..b57fffc 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -5463,7 +5463,7 @@
 	case 2:
 		for (i = 0; i < adev->gfx.num_compute_rings; i++) {
 			ring = &adev->gfx.compute_ring[i];
-			if ((ring->me == me_id) & (ring->pipe == pipe_id))
+			if ((ring->me == me_id) && (ring->pipe == pipe_id))
 				amdgpu_fence_process(ring);
 		}
 		break;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index ea87033..df17fab 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -167,6 +167,7 @@
 		break;
 	case CHIP_KAVERI:
 	case CHIP_KABINI:
+	case CHIP_MULLINS:
 		return 0;
 	default: BUG();
 	}
diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
index 7e9154c..d1c9525 100644
--- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
@@ -2258,7 +2258,7 @@
 	if (pi->caps_stable_p_state) {
 		stable_p_state_sclk = (max_limits->sclk * 75) / 100;
 
-		for (i = table->count - 1; i >= 0; i++) {
+		for (i = table->count - 1; i >= 0; i--) {
 			if (stable_p_state_sclk >= table->entries[i].clk) {
 				stable_p_state_sclk = table->entries[i].clk;
 				break;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 9be0070..eb1da83 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -242,13 +242,19 @@
 	pqm_uninit(&p->pqm);
 
 	/* Iterate over all process device data structure and check
-	 * if we should reset all wavefronts */
-	list_for_each_entry(pdd, &p->per_device_data, per_device_list)
+	 * if we should delete debug managers and reset all wavefronts
+	 */
+	list_for_each_entry(pdd, &p->per_device_data, per_device_list) {
+		if ((pdd->dev->dbgmgr) &&
+				(pdd->dev->dbgmgr->pasid == p->pasid))
+			kfd_dbgmgr_destroy(pdd->dev->dbgmgr);
+
 		if (pdd->reset_wavefronts) {
 			pr_warn("amdkfd: Resetting all wave fronts\n");
 			dbgdev_wave_reset_wavefronts(pdd->dev, p);
 			pdd->reset_wavefronts = false;
 		}
+	}
 
 	mutex_unlock(&p->mutex);
 
@@ -404,42 +410,52 @@
 
 	idx = srcu_read_lock(&kfd_processes_srcu);
 
+	/*
+	 * Look for the process that matches the pasid. If there is no such
+	 * process, we either released it in amdkfd's own notifier, or there
+	 * is a bug. Unfortunately, there is no way to tell...
+	 */
 	hash_for_each_rcu(kfd_processes_table, i, p, kfd_processes)
-		if (p->pasid == pasid)
-			break;
+		if (p->pasid == pasid) {
+
+			srcu_read_unlock(&kfd_processes_srcu, idx);
+
+			pr_debug("Unbinding process %d from IOMMU\n", pasid);
+
+			mutex_lock(&p->mutex);
+
+			if ((dev->dbgmgr) && (dev->dbgmgr->pasid == p->pasid))
+				kfd_dbgmgr_destroy(dev->dbgmgr);
+
+			pqm_uninit(&p->pqm);
+
+			pdd = kfd_get_process_device_data(dev, p);
+
+			if (!pdd) {
+				mutex_unlock(&p->mutex);
+				return;
+			}
+
+			if (pdd->reset_wavefronts) {
+				dbgdev_wave_reset_wavefronts(pdd->dev, p);
+				pdd->reset_wavefronts = false;
+			}
+
+			/*
+			 * Just mark pdd as unbound, because we still need it
+			 * to call amd_iommu_unbind_pasid() in when the
+			 * process exits.
+			 * We don't call amd_iommu_unbind_pasid() here
+			 * because the IOMMU called us.
+			 */
+			pdd->bound = false;
+
+			mutex_unlock(&p->mutex);
+
+			return;
+		}
 
 	srcu_read_unlock(&kfd_processes_srcu, idx);
-
-	BUG_ON(p->pasid != pasid);
-
-	mutex_lock(&p->mutex);
-
-	if ((dev->dbgmgr) && (dev->dbgmgr->pasid == p->pasid))
-		kfd_dbgmgr_destroy(dev->dbgmgr);
-
-	pqm_uninit(&p->pqm);
-
-	pdd = kfd_get_process_device_data(dev, p);
-
-	if (!pdd) {
-		mutex_unlock(&p->mutex);
-		return;
-	}
-
-	if (pdd->reset_wavefronts) {
-		dbgdev_wave_reset_wavefronts(pdd->dev, p);
-		pdd->reset_wavefronts = false;
-	}
-
-	/*
-	 * Just mark pdd as unbound, because we still need it to call
-	 * amd_iommu_unbind_pasid() in when the process exits.
-	 * We don't call amd_iommu_unbind_pasid() here
-	 * because the IOMMU called us.
-	 */
-	pdd->bound = false;
-
-	mutex_unlock(&p->mutex);
 }
 
 struct kfd_process_device *kfd_get_first_process_device_data(struct kfd_process *p)
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 05f6522..b5c64ed 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -113,6 +113,11 @@
 	struct ttm_bo_kmap_obj cache_kmap;
 	int next_cursor;
 	bool support_wide_screen;
+	enum {
+		ast_use_p2a,
+		ast_use_dt,
+		ast_use_defaults
+	} config_mode;
 
 	enum ast_tx_chip tx_chip_type;
 	u8 dp501_maxclk;
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index e0b4586..498a940 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -62,13 +62,84 @@
 	return ret;
 }
 
+static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
+{
+	struct device_node *np = dev->pdev->dev.of_node;
+	struct ast_private *ast = dev->dev_private;
+	uint32_t data, jregd0, jregd1;
+
+	/* Defaults */
+	ast->config_mode = ast_use_defaults;
+	*scu_rev = 0xffffffff;
+
+	/* Check if we have device-tree properties */
+	if (np && !of_property_read_u32(np, "aspeed,scu-revision-id",
+					scu_rev)) {
+		/* We do, disable P2A access */
+		ast->config_mode = ast_use_dt;
+		DRM_INFO("Using device-tree for configuration\n");
+		return;
+	}
+
+	/* Not all families have a P2A bridge */
+	if (dev->pdev->device != PCI_CHIP_AST2000)
+		return;
+
+	/*
+	 * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge
+	 * is disabled. We force using P2A if VGA only mode bit
+	 * is set D[7]
+	 */
+	jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
+	jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
+	if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
+		/* Double check it's actually working */
+		data = ast_read32(ast, 0xf004);
+		if (data != 0xFFFFFFFF) {
+			/* P2A works, grab silicon revision */
+			ast->config_mode = ast_use_p2a;
+
+			DRM_INFO("Using P2A bridge for configuration\n");
+
+			/* Read SCU7c (silicon revision register) */
+			ast_write32(ast, 0xf004, 0x1e6e0000);
+			ast_write32(ast, 0xf000, 0x1);
+			*scu_rev = ast_read32(ast, 0x1207c);
+			return;
+		}
+	}
+
+	/* We have a P2A bridge but it's disabled */
+	DRM_INFO("P2A bridge disabled, using default configuration\n");
+}
 
 static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 {
 	struct ast_private *ast = dev->dev_private;
-	uint32_t data, jreg;
+	uint32_t jreg, scu_rev;
+
+	/*
+	 * If VGA isn't enabled, we need to enable now or subsequent
+	 * access to the scratch registers will fail. We also inform
+	 * our caller that it needs to POST the chip
+	 * (Assumption: VGA not enabled -> need to POST)
+	 */
+	if (!ast_is_vga_enabled(dev)) {
+		ast_enable_vga(dev);
+		DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
+		*need_post = true;
+	} else
+		*need_post = false;
+
+
+	/* Enable extended register access */
+	ast_enable_mmio(dev);
 	ast_open_key(ast);
 
+	/* Find out whether P2A works or whether to use device-tree */
+	ast_detect_config_mode(dev, &scu_rev);
+
+	/* Identify chipset */
 	if (dev->pdev->device == PCI_CHIP_AST1180) {
 		ast->chip = AST1100;
 		DRM_INFO("AST 1180 detected\n");
@@ -80,12 +151,7 @@
 			ast->chip = AST2300;
 			DRM_INFO("AST 2300 detected\n");
 		} else if (dev->pdev->revision >= 0x10) {
-			uint32_t data;
-			ast_write32(ast, 0xf004, 0x1e6e0000);
-			ast_write32(ast, 0xf000, 0x1);
-
-			data = ast_read32(ast, 0x1207c);
-			switch (data & 0x0300) {
+			switch (scu_rev & 0x0300) {
 			case 0x0200:
 				ast->chip = AST1100;
 				DRM_INFO("AST 1100 detected\n");
@@ -110,20 +176,6 @@
 		}
 	}
 
-	/*
-	 * If VGA isn't enabled, we need to enable now or subsequent
-	 * access to the scratch registers will fail. We also inform
-	 * our caller that it needs to POST the chip
-	 * (Assumption: VGA not enabled -> need to POST)
-	 */
-	if (!ast_is_vga_enabled(dev)) {
-		ast_enable_vga(dev);
-		ast_enable_mmio(dev);
-		DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
-		*need_post = true;
-	} else
-		*need_post = false;
-
 	/* Check if we support wide screen */
 	switch (ast->chip) {
 	case AST1180:
@@ -140,14 +192,11 @@
 			ast->support_wide_screen = true;
 		else {
 			ast->support_wide_screen = false;
-			/* Read SCU7c (silicon revision register) */
-			ast_write32(ast, 0xf004, 0x1e6e0000);
-			ast_write32(ast, 0xf000, 0x1);
-			data = ast_read32(ast, 0x1207c);
-			data &= 0x300;
-			if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
+			if (ast->chip == AST2300 &&
+			    (scu_rev & 0x300) == 0x0) /* ast1300 */
 				ast->support_wide_screen = true;
-			if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
+			if (ast->chip == AST2400 &&
+			    (scu_rev & 0x300) == 0x100) /* ast1400 */
 				ast->support_wide_screen = true;
 		}
 		break;
@@ -212,28 +261,49 @@
 
 static int ast_get_dram_info(struct drm_device *dev)
 {
+	struct device_node *np = dev->pdev->dev.of_node;
 	struct ast_private *ast = dev->dev_private;
-	uint32_t data, data2;
-	uint32_t denum, num, div, ref_pll;
+	uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
+	uint32_t denum, num, div, ref_pll, dsel;
 
-	ast_write32(ast, 0xf004, 0x1e6e0000);
-	ast_write32(ast, 0xf000, 0x1);
+	switch (ast->config_mode) {
+	case ast_use_dt:
+		/*
+		 * If some properties are missing, use reasonable
+		 * defaults for AST2400
+		 */
+		if (of_property_read_u32(np, "aspeed,mcr-configuration",
+					 &mcr_cfg))
+			mcr_cfg = 0x00000577;
+		if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
+					 &mcr_scu_mpll))
+			mcr_scu_mpll = 0x000050C0;
+		if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
+					 &mcr_scu_strap))
+			mcr_scu_strap = 0;
+		break;
+	case ast_use_p2a:
+		ast_write32(ast, 0xf004, 0x1e6e0000);
+		ast_write32(ast, 0xf000, 0x1);
+		mcr_cfg = ast_read32(ast, 0x10004);
+		mcr_scu_mpll = ast_read32(ast, 0x10120);
+		mcr_scu_strap = ast_read32(ast, 0x10170);
+		break;
+	case ast_use_defaults:
+	default:
+		ast->dram_bus_width = 16;
+		ast->dram_type = AST_DRAM_1Gx16;
+		ast->mclk = 396;
+		return 0;
+	}
 
-
-	ast_write32(ast, 0x10000, 0xfc600309);
-
-	do {
-		;
-	} while (ast_read32(ast, 0x10000) != 0x01);
-	data = ast_read32(ast, 0x10004);
-
-	if (data & 0x40)
+	if (mcr_cfg & 0x40)
 		ast->dram_bus_width = 16;
 	else
 		ast->dram_bus_width = 32;
 
 	if (ast->chip == AST2300 || ast->chip == AST2400) {
-		switch (data & 0x03) {
+		switch (mcr_cfg & 0x03) {
 		case 0:
 			ast->dram_type = AST_DRAM_512Mx16;
 			break;
@@ -249,13 +319,13 @@
 			break;
 		}
 	} else {
-		switch (data & 0x0c) {
+		switch (mcr_cfg & 0x0c) {
 		case 0:
 		case 4:
 			ast->dram_type = AST_DRAM_512Mx16;
 			break;
 		case 8:
-			if (data & 0x40)
+			if (mcr_cfg & 0x40)
 				ast->dram_type = AST_DRAM_1Gx16;
 			else
 				ast->dram_type = AST_DRAM_512Mx32;
@@ -266,17 +336,15 @@
 		}
 	}
 
-	data = ast_read32(ast, 0x10120);
-	data2 = ast_read32(ast, 0x10170);
-	if (data2 & 0x2000)
+	if (mcr_scu_strap & 0x2000)
 		ref_pll = 14318;
 	else
 		ref_pll = 12000;
 
-	denum = data & 0x1f;
-	num = (data & 0x3fe0) >> 5;
-	data = (data & 0xc000) >> 14;
-	switch (data) {
+	denum = mcr_scu_mpll & 0x1f;
+	num = (mcr_scu_mpll & 0x3fe0) >> 5;
+	dsel = (mcr_scu_mpll & 0xc000) >> 14;
+	switch (dsel) {
 	case 3:
 		div = 0x4;
 		break;
@@ -429,7 +497,9 @@
 	ast_detect_chip(dev, &need_post);
 
 	if (ast->chip != AST1180) {
-		ast_get_dram_info(dev);
+		ret = ast_get_dram_info(dev);
+		if (ret)
+			goto out_free;
 		ast->vram_size = ast_get_vram_info(dev);
 		DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, ast->dram_bus_width, ast->vram_size);
 	}
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 0123458..69d19f3 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -751,7 +751,7 @@
 		return -ENOMEM;
 
 	drm_encoder_init(dev, &ast_encoder->base, &ast_enc_funcs,
-			 DRM_MODE_ENCODER_DAC, NULL);
+			 DRM_MODE_ENCODER_DAC);
 	drm_encoder_helper_add(&ast_encoder->base, &ast_enc_helper_funcs);
 
 	ast_encoder->base.possible_crtcs = 1;
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 810c51d..c7c58be 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -58,13 +58,9 @@
 		/* TODO 1180 */
 	} else {
 		ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT);
-		if (ch) {
-			ast_open_key(ast);
-			ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff);
-			return ch & 0x04;
-		}
+		return !!(ch & 0x01);
 	}
-	return 0;
+	return false;
 }
 
 static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
@@ -375,16 +371,21 @@
 	pci_write_config_dword(ast->dev->pdev, 0x04, reg);
 
 	ast_enable_vga(dev);
-	ast_enable_mmio(dev);
 	ast_open_key(ast);
+	ast_enable_mmio(dev);
 	ast_set_def_ext_reg(dev);
 
-	if (ast->chip == AST2300 || ast->chip == AST2400)
-		ast_init_dram_2300(dev);
-	else
-		ast_init_dram_reg(dev);
+	if (ast->config_mode == ast_use_p2a) {
+		if (ast->chip == AST2300 || ast->chip == AST2400)
+			ast_init_dram_2300(dev);
+		else
+			ast_init_dram_reg(dev);
 
-	ast_init_3rdtx(dev);
+		ast_init_3rdtx(dev);
+	} else {
+		if (ast->tx_chip_type != AST_TX_NONE)
+			ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);	/* Enable DVO */
+	}
 }
 
 /* AST 2300 DRAM settings */
@@ -1630,12 +1631,44 @@
 		temp |= 0x73;
 		ast_write32(ast, 0x12008, temp);
 
+		param.dram_freq = 396;
 		param.dram_type = AST_DDR3;
+		temp = ast_mindwm(ast, 0x1e6e2070);
 		if (temp & 0x01000000)
 			param.dram_type = AST_DDR2;
-		param.dram_chipid = ast->dram_type;
-		param.dram_freq = ast->mclk;
-		param.vram_size = ast->vram_size;
+                switch (temp & 0x18000000) {
+		case 0:
+			param.dram_chipid = AST_DRAM_512Mx16;
+			break;
+		default:
+		case 0x08000000:
+			param.dram_chipid = AST_DRAM_1Gx16;
+			break;
+		case 0x10000000:
+			param.dram_chipid = AST_DRAM_2Gx16;
+			break;
+		case 0x18000000:
+			param.dram_chipid = AST_DRAM_4Gx16;
+			break;
+		}
+                switch (temp & 0x0c) {
+                default:
+		case 0x00:
+			param.vram_size = AST_VIDMEM_SIZE_8M;
+			break;
+
+		case 0x04:
+			param.vram_size = AST_VIDMEM_SIZE_16M;
+			break;
+
+		case 0x08:
+			param.vram_size = AST_VIDMEM_SIZE_32M;
+			break;
+
+		case 0x0c:
+			param.vram_size = AST_VIDMEM_SIZE_64M;
+			break;
+		}
 
 		if (param.dram_type == AST_DDR3) {
 			get_ddr3_info(ast, &param);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index d112900..067e4c1 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -256,7 +256,7 @@
 			       &atmel_hlcdc_panel_encoder_helper_funcs);
 	ret = drm_encoder_init(dev, &panel->base.encoder,
 			       &atmel_hlcdc_panel_encoder_funcs,
-			       DRM_MODE_ENCODER_LVDS, NULL);
+			       DRM_MODE_ENCODER_LVDS);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index d0299ae..e231176 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -316,25 +316,27 @@
 			u32 *coeff_tab = heo_upscaling_ycoef;
 			u32 max_memsize;
 
-			if (state->crtc_w < state->src_w)
+			if (state->crtc_h < state->src_h)
 				coeff_tab = heo_downscaling_ycoef;
 			for (i = 0; i < ARRAY_SIZE(heo_upscaling_ycoef); i++)
 				atmel_hlcdc_layer_update_cfg(&plane->layer,
 							     33 + i,
 							     0xffffffff,
 							     coeff_tab[i]);
-			factor = ((8 * 256 * state->src_w) - (256 * 4)) /
-				 state->crtc_w;
+			factor = ((8 * 256 * state->src_h) - (256 * 4)) /
+				 state->crtc_h;
 			factor++;
-			max_memsize = ((factor * state->crtc_w) + (256 * 4)) /
+			max_memsize = ((factor * state->crtc_h) + (256 * 4)) /
 				      2048;
-			if (max_memsize > state->src_w)
+			if (max_memsize > state->src_h)
 				factor--;
 			factor_reg |= (factor << 16) | 0x80000000;
 		}
 
 		atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff,
 					     factor_reg);
+	} else {
+		atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff, 0);
 	}
 }
 
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index a88be6d..26bcd03 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -196,7 +196,7 @@
 
 	encoder->possible_crtcs = 0x1;
 	drm_encoder_init(dev, encoder, &bochs_encoder_encoder_funcs,
-			 DRM_MODE_ENCODER_DAC, NULL);
+			 DRM_MODE_ENCODER_DAC);
 	drm_encoder_helper_add(encoder, &bochs_encoder_helper_funcs);
 }
 
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 276719e..61385f2 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -489,7 +489,7 @@
 	encoder->possible_crtcs = 0x1;
 
 	drm_encoder_init(dev, encoder, &cirrus_encoder_encoder_funcs,
-			 DRM_MODE_ENCODER_DAC, NULL);
+			 DRM_MODE_ENCODER_DAC);
 	drm_encoder_helper_add(encoder, &cirrus_encoder_helper_funcs);
 
 	return encoder;
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index aeee083..6253775 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -150,7 +150,7 @@
 	for (i = 0; i < state->num_connector; i++) {
 		struct drm_connector *connector = state->connectors[i];
 
-		if (!connector)
+		if (!connector || !connector->funcs)
 			continue;
 
 		/*
@@ -367,6 +367,8 @@
 		drm_property_unreference_blob(state->mode_blob);
 	state->mode_blob = NULL;
 
+	memset(&state->mode, 0, sizeof(state->mode));
+
 	if (blob) {
 		if (blob->length != sizeof(struct drm_mode_modeinfo) ||
 		    drm_mode_convert_umode(&state->mode,
@@ -379,7 +381,6 @@
 		DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
 				 state->mode.name, state);
 	} else {
-		memset(&state->mode, 0, sizeof(state->mode));
 		state->enable = false;
 		DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
 				 state);
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index f8b1e8e..ea443fa 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -108,7 +108,6 @@
 	struct drm_crtc_state *crtc_state;
 	struct drm_connector *connector;
 	struct drm_connector_state *connector_state;
-	int ret;
 
 	/*
 	 * We can only steal an encoder coming from a connector, which means we
@@ -139,9 +138,6 @@
 		if (IS_ERR(connector_state))
 			return PTR_ERR(connector_state);
 
-		ret = drm_atomic_set_crtc_for_connector(connector_state, NULL);
-		if (ret)
-			return ret;
 		connector_state->best_encoder = NULL;
 	}
 
@@ -269,7 +265,7 @@
 	struct drm_connector *connector;
 	struct drm_connector_state *conn_state;
 	int i;
-	bool ret;
+	int ret;
 
 	for_each_crtc_in_state(state, crtc, crtc_state, i) {
 		if (!crtc_state->mode_changed &&
@@ -913,23 +909,9 @@
 	}
 }
 
-/**
- * drm_atomic_helper_framebuffer_changed - check if framebuffer has changed
- * @dev: DRM device
- * @old_state: atomic state object with old state structures
- * @crtc: DRM crtc
- *
- * Checks whether the framebuffer used for this CRTC changes as a result of
- * the atomic update.  This is useful for drivers which cannot use
- * drm_atomic_helper_wait_for_vblanks() and need to reimplement its
- * functionality.
- *
- * Returns:
- * true if the framebuffer changed.
- */
-bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev,
-					   struct drm_atomic_state *old_state,
-					   struct drm_crtc *crtc)
+static bool framebuffer_changed(struct drm_device *dev,
+				struct drm_atomic_state *old_state,
+				struct drm_crtc *crtc)
 {
 	struct drm_plane *plane;
 	struct drm_plane_state *old_plane_state;
@@ -946,7 +928,6 @@
 
 	return false;
 }
-EXPORT_SYMBOL(drm_atomic_helper_framebuffer_changed);
 
 /**
  * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs
@@ -981,8 +962,7 @@
 		if (old_state->legacy_cursor_update)
 			continue;
 
-		if (!drm_atomic_helper_framebuffer_changed(dev,
-				old_state, crtc))
+		if (!framebuffer_changed(dev, old_state, crtc))
 			continue;
 
 		ret = drm_crtc_vblank_get(crtc);
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index 6743ff7..7f4a6c5 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -136,6 +136,7 @@
 		mb();
 		for (; addr < end; addr += size)
 			clflushopt(addr);
+		clflushopt(end - 1); /* force serialisation */
 		mb();
 		return;
 	}
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 89d00d6..5e4bb48 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1075,7 +1075,6 @@
  * @encoder: the encoder to init
  * @funcs: callbacks for this encoder
  * @encoder_type: user visible type of the encoder
- * @name: printf style format string for the encoder name, or NULL for default name
  *
  * Initialises a preallocated encoder. Encoder should be
  * subclassed as part of driver encoder objects.
@@ -1086,7 +1085,7 @@
 int drm_encoder_init(struct drm_device *dev,
 		      struct drm_encoder *encoder,
 		      const struct drm_encoder_funcs *funcs,
-		      int encoder_type, const char *name, ...)
+		      int encoder_type)
 {
 	int ret;
 
@@ -2683,8 +2682,6 @@
 			goto out;
 		}
 
-		drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-
 		/*
 		 * Check whether the primary plane supports the fb pixel format.
 		 * Drivers not implementing the universal planes API use a
@@ -3317,6 +3314,24 @@
 	return 0;
 }
 
+struct drm_mode_rmfb_work {
+	struct work_struct work;
+	struct list_head fbs;
+};
+
+static void drm_mode_rmfb_work_fn(struct work_struct *w)
+{
+	struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
+
+	while (!list_empty(&arg->fbs)) {
+		struct drm_framebuffer *fb =
+			list_first_entry(&arg->fbs, typeof(*fb), filp_head);
+
+		list_del_init(&fb->filp_head);
+		drm_framebuffer_remove(fb);
+	}
+}
+
 /**
  * drm_mode_rmfb - remove an FB from the configuration
  * @dev: drm device for the ioctl
@@ -3357,7 +3372,25 @@
 	mutex_unlock(&dev->mode_config.fb_lock);
 	mutex_unlock(&file_priv->fbs_lock);
 
-	drm_framebuffer_unreference(fb);
+	/*
+	 * we now own the reference that was stored in the fbs list
+	 *
+	 * drm_framebuffer_remove may fail with -EINTR on pending signals,
+	 * so run this in a separate stack as there's no way to correctly
+	 * handle this after the fb is already removed from the lookup table.
+	 */
+	if (atomic_read(&fb->refcount.refcount) > 1) {
+		struct drm_mode_rmfb_work arg;
+
+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+		INIT_LIST_HEAD(&arg.fbs);
+		list_add_tail(&fb->filp_head, &arg.fbs);
+
+		schedule_work(&arg.work);
+		flush_work(&arg.work);
+		destroy_work_on_stack(&arg.work);
+	} else
+		drm_framebuffer_unreference(fb);
 
 	return 0;
 
@@ -3510,7 +3543,6 @@
 	return ret;
 }
 
-
 /**
  * drm_fb_release - remove and free the FBs on this file
  * @priv: drm file for the ioctl
@@ -3525,6 +3557,9 @@
 void drm_fb_release(struct drm_file *priv)
 {
 	struct drm_framebuffer *fb, *tfb;
+	struct drm_mode_rmfb_work arg;
+
+	INIT_LIST_HEAD(&arg.fbs);
 
 	/*
 	 * When the file gets released that means no one else can access the fb
@@ -3537,10 +3572,22 @@
 	 * at it any more.
 	 */
 	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
-		list_del_init(&fb->filp_head);
+		if (atomic_read(&fb->refcount.refcount) > 1) {
+			list_move_tail(&fb->filp_head, &arg.fbs);
+		} else {
+			list_del_init(&fb->filp_head);
 
-		/* This drops the fpriv->fbs reference. */
-		drm_framebuffer_unreference(fb);
+			/* This drops the fpriv->fbs reference. */
+			drm_framebuffer_unreference(fb);
+		}
+	}
+
+	if (!list_empty(&arg.fbs)) {
+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+
+		schedule_work(&arg.work);
+		flush_work(&arg.work);
+		destroy_work_on_stack(&arg.work);
 	}
 }
 
@@ -5184,6 +5231,9 @@
 	unsigned long flags;
 	int ret = -EINVAL;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
 	    page_flip->reserved != 0)
 		return -EINVAL;
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index d268bf1..a3b96d6 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -909,6 +909,7 @@
 		/* no need to clean up vcpi
 		 * as if we have no connector we never setup a vcpi */
 		drm_dp_port_teardown_pdt(port, port->pdt);
+		port->pdt = DP_PEER_DEVICE_NONE;
 	}
 	kfree(port);
 }
@@ -1154,7 +1155,9 @@
 			drm_dp_put_port(port);
 			goto out;
 		}
-		if (port->port_num >= DP_MST_LOGICAL_PORT_0) {
+		if ((port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV ||
+		     port->pdt == DP_PEER_DEVICE_SST_SINK) &&
+		    port->port_num >= DP_MST_LOGICAL_PORT_0) {
 			port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
 			drm_mode_connector_set_tile_property(port->connector);
 		}
@@ -1809,7 +1812,7 @@
 				mgr->payloads[i].num_slots = req_payload.num_slots;
 			} else if (mgr->payloads[i].num_slots) {
 				mgr->payloads[i].num_slots = 0;
-				drm_dp_destroy_payload_step1(mgr, port, port->vcpi.vcpi, &mgr->payloads[i]);
+				drm_dp_destroy_payload_step1(mgr, port, mgr->payloads[i].vcpi, &mgr->payloads[i]);
 				req_payload.payload_state = mgr->payloads[i].payload_state;
 				mgr->payloads[i].start_slot = 0;
 			}
@@ -2872,13 +2875,12 @@
 		mgr->cbs->destroy_connector(mgr, port->connector);
 
 		drm_dp_port_teardown_pdt(port, port->pdt);
+		port->pdt = DP_PEER_DEVICE_NONE;
 
 		if (!port->input && port->vcpi.vcpi > 0) {
-			if (mgr->mst_state) {
-				drm_dp_mst_reset_vcpi_slots(mgr, port);
-				drm_dp_update_payload_part1(mgr);
-				drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
-			}
+			drm_dp_mst_reset_vcpi_slots(mgr, port);
+			drm_dp_update_payload_part1(mgr);
+			drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
 		}
 
 		kref_put(&port->kref, drm_dp_free_mst_port);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index d5d2c03..c0106fd 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -73,6 +73,10 @@
 #define EDID_QUIRK_FORCE_8BPC			(1 << 8)
 /* Force 12bpc */
 #define EDID_QUIRK_FORCE_12BPC			(1 << 9)
+/* Force 6bpc */
+#define EDID_QUIRK_FORCE_6BPC			(1 << 10)
+/* Force 10bpc */
+#define EDID_QUIRK_FORCE_10BPC			(1 << 11)
 
 struct detailed_mode_closure {
 	struct drm_connector *connector;
@@ -99,6 +103,9 @@
 	/* Unknown Acer */
 	{ "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
 
+	/* AEO model 0 reports 8 bpc, but is a 6 bpc panel */
+	{ "AEO", 0, EDID_QUIRK_FORCE_6BPC },
+
 	/* Belinea 10 15 55 */
 	{ "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 },
 	{ "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
@@ -112,6 +119,9 @@
 	{ "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 |
 	  EDID_QUIRK_DETAILED_IN_CM },
 
+	/* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */
+	{ "LGD", 764, EDID_QUIRK_FORCE_10BPC },
+
 	/* LG Philips LCD LP154W01-A5 */
 	{ "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
 	{ "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
@@ -139,6 +149,9 @@
 
 	/* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */
 	{ "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC },
+
+	/* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/
+	{ "ETR", 13896, EDID_QUIRK_FORCE_8BPC },
 };
 
 /*
@@ -3820,9 +3833,15 @@
 
 	drm_add_display_info(edid, &connector->display_info, connector);
 
+	if (quirks & EDID_QUIRK_FORCE_6BPC)
+		connector->display_info.bpc = 6;
+
 	if (quirks & EDID_QUIRK_FORCE_8BPC)
 		connector->display_info.bpc = 8;
 
+	if (quirks & EDID_QUIRK_FORCE_10BPC)
+		connector->display_info.bpc = 10;
+
 	if (quirks & EDID_QUIRK_FORCE_12BPC)
 		connector->display_info.bpc = 12;
 
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 69cbab5..5ad0367 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1899,7 +1899,6 @@
 			  int n, int width, int height)
 {
 	int c, o;
-	struct drm_device *dev = fb_helper->dev;
 	struct drm_connector *connector;
 	const struct drm_connector_helper_funcs *connector_funcs;
 	struct drm_encoder *encoder;
@@ -1918,7 +1917,7 @@
 	if (modes[n] == NULL)
 		return best_score;
 
-	crtcs = kzalloc(dev->mode_config.num_connector *
+	crtcs = kzalloc(fb_helper->connector_count *
 			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
 	if (!crtcs)
 		return best_score;
@@ -1964,7 +1963,7 @@
 		if (score > best_score) {
 			best_score = score;
 			memcpy(best_crtcs, crtcs,
-			       dev->mode_config.num_connector *
+			       fb_helper->connector_count *
 			       sizeof(struct drm_fb_helper_crtc *));
 		}
 	}
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index c7de454..b205224 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -338,27 +338,32 @@
 	spin_unlock(&file_priv->table_lock);
 	idr_preload_end();
 	mutex_unlock(&dev->object_name_lock);
-	if (ret < 0) {
-		drm_gem_object_handle_unreference_unlocked(obj);
-		return ret;
-	}
+	if (ret < 0)
+		goto err_unref;
+
 	*handlep = ret;
 
 	ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp);
-	if (ret) {
-		drm_gem_handle_delete(file_priv, *handlep);
-		return ret;
-	}
+	if (ret)
+		goto err_remove;
 
 	if (dev->driver->gem_open_object) {
 		ret = dev->driver->gem_open_object(obj, file_priv);
-		if (ret) {
-			drm_gem_handle_delete(file_priv, *handlep);
-			return ret;
-		}
+		if (ret)
+			goto err_revoke;
 	}
 
 	return 0;
+
+err_revoke:
+	drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
+err_remove:
+	spin_lock(&file_priv->table_lock);
+	idr_remove(&file_priv->object_idr, *handlep);
+	spin_unlock(&file_priv->table_lock);
+err_unref:
+	drm_gem_object_handle_unreference_unlocked(obj);
+	return ret;
 }
 
 /**
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index 57676f8..a628975 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -1015,6 +1015,7 @@
 	return 0;
 }
 
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
 typedef struct drm_mode_fb_cmd232 {
 	u32 fb_id;
 	u32 width;
@@ -1071,6 +1072,7 @@
 
 	return 0;
 }
+#endif
 
 static drm_ioctl_compat_t *drm_compat_ioctls[] = {
 	[DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
@@ -1104,7 +1106,9 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw,
 #endif
 	[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
 	[DRM_IOCTL_NR(DRM_IOCTL_MODE_ADDFB232)] = compat_drm_mode_addfb2,
+#endif
 };
 
 /**
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index cd74a09..71a10f0 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1401,6 +1401,13 @@
 		return NULL;
 
 	mode->type |= DRM_MODE_TYPE_USERDEF;
+	/* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
+	if (cmd->xres == 1366 && mode->hdisplay == 1368) {
+		mode->hdisplay = 1366;
+		mode->hsync_start--;
+		mode->hsync_end--;
+		drm_mode_set_name(mode);
+	}
 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
 	return mode;
 }
@@ -1487,6 +1494,8 @@
 	if (out->status != MODE_OK)
 		goto out;
 
+	drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
+
 	ret = 0;
 
 out:
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 9f935f5..968b31f 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -339,14 +339,17 @@
  * using the PRIME helpers.
  */
 struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
-				     struct drm_gem_object *obj, int flags)
+				     struct drm_gem_object *obj,
+				     int flags)
 {
-	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-
-	exp_info.ops = &drm_gem_prime_dmabuf_ops;
-	exp_info.size = obj->size;
-	exp_info.flags = flags;
-	exp_info.priv = obj;
+	struct dma_buf_export_info exp_info = {
+		.exp_name = KBUILD_MODNAME, /* white lie for debug */
+		.owner = dev->driver->fops->owner,
+		.ops = &drm_gem_prime_dmabuf_ops,
+		.size = obj->size,
+		.flags = flags,
+		.priv = obj,
+	};
 
 	if (dev->driver->gem_prime_res_obj)
 		exp_info.resv = dev->driver->gem_prime_res_obj(obj);
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index cf17713..124fb9a 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -1313,7 +1313,7 @@
 	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
 
 	drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index 7f55ba6..011211e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -101,7 +101,7 @@
 	return 0;
 
 err:
-	list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
+	list_for_each_entry_continue_reverse(subdrv, &exynos_drm_subdrv_list, list) {
 		if (subdrv->close)
 			subdrv->close(dev, subdrv->dev, file);
 	}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
index 1dbf8dc..c748b87 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -309,7 +309,7 @@
 	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
 
 	drm_encoder_init(dev, encoder, &exynos_dpi_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	drm_encoder_helper_add(encoder, &exynos_dpi_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 0a99160..12b03b3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1831,7 +1831,7 @@
 	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
 
 	drm_encoder_init(drm_dev, encoder, &exynos_dsi_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index c34d49a..669362c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -473,7 +473,7 @@
 	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
 
 	drm_encoder_init(drm_dev, encoder, &exynos_vidi_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	drm_encoder_helper_add(encoder, &exynos_vidi_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index ba3543e..57b6755 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1793,7 +1793,7 @@
 	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
 
 	drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index 8780deb..fe8ab5d 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -57,7 +57,7 @@
 
 	encoder->possible_crtcs = 1;
 	ret = drm_encoder_init(fsl_dev->drm, encoder, &encoder_funcs,
-			       DRM_MODE_ENCODER_LVDS, NULL);
+			       DRM_MODE_ENCODER_LVDS);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index d0717a8..248c33a 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -273,7 +273,7 @@
 
 	encoder = &gma_encoder->base;
 	drm_encoder_init(dev, encoder,
-		&cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC, NULL);
+		&cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC);
 
 	gma_connector_attach_encoder(gma_connector, gma_encoder);
 
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index 7bb1f1a..d3de377 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -220,7 +220,7 @@
  * FIXME: This is the old dp aux helper, gma500 is the last driver that needs to
  * be ported over to the new helper code in drm_dp_helper.c like i915 or radeon.
  */
-static int __deprecated
+static int
 i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
 {
 	int error;
@@ -2020,8 +2020,7 @@
 	encoder = &gma_encoder->base;
 
 	drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, type);
-	drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+	drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS);
 
 	gma_connector_attach_encoder(gma_connector, gma_encoder);
 
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index 8930153..6b1d334 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -312,7 +312,7 @@
 			   DRM_MODE_CONNECTOR_DVID);
 
 	drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	gma_connector_attach_encoder(gma_connector, gma_encoder);
 	gma_encoder->type = INTEL_OUTPUT_HDMI;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index fa90515..211069b 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -652,7 +652,7 @@
 
 	drm_encoder_init(dev, encoder,
 			 &cdv_intel_lvds_enc_funcs,
-			 DRM_MODE_ENCODER_LVDS, NULL);
+			 DRM_MODE_ENCODER_LVDS);
 
 
 	gma_connector_attach_encoder(gma_connector, gma_encoder);
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
index 1a1acd3..d4813e0 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
@@ -994,7 +994,7 @@
 	drm_encoder_init(dev,
 			encoder,
 			p_funcs->encoder_funcs,
-			DRM_MODE_ENCODER_LVDS, NULL);
+			DRM_MODE_ENCODER_LVDS);
 	drm_encoder_helper_add(encoder,
 				p_funcs->encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
index 6b43ae3..1616af2 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
@@ -72,7 +72,7 @@
 	"RX Prot Violation",
 	"HS Generic Write FIFO Full",
 	"LP Generic Write FIFO Full",
-	"Generic Read Data Avail"
+	"Generic Read Data Avail",
 	"Special Packet Sent",
 	"Tearing Effect",
 };
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index 2d18499..2310d87 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
@@ -654,7 +654,7 @@
 
 	drm_encoder_init(dev, encoder,
 			 &oaktrail_hdmi_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	gma_connector_attach_encoder(gma_connector, gma_encoder);
 
diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c
index f7038f1..83bbc27 100644
--- a/drivers/gpu/drm/gma500/oaktrail_lvds.c
+++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c
@@ -323,7 +323,7 @@
 			   DRM_MODE_CONNECTOR_LVDS);
 
 	drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs,
-			 DRM_MODE_ENCODER_LVDS, NULL);
+			 DRM_MODE_ENCODER_LVDS);
 
 	gma_connector_attach_encoder(gma_connector, gma_encoder);
 	gma_encoder->type = INTEL_OUTPUT_LVDS;
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 92e7e57..db98ab5 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -484,6 +484,9 @@
 	.open = drm_open,
 	.release = drm_release,
 	.unlocked_ioctl = psb_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = drm_compat_ioctl,
+#endif
 	.mmap = drm_gem_mmap,
 	.poll = drm_poll,
 	.read = drm_read,
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index f6ca149..61e3a09 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -722,7 +722,7 @@
 
 	drm_encoder_init(dev, encoder,
 			 &psb_intel_lvds_enc_funcs,
-			 DRM_MODE_ENCODER_LVDS, NULL);
+			 DRM_MODE_ENCODER_LVDS);
 
 	gma_connector_attach_encoder(gma_connector, gma_encoder);
 	gma_encoder->type = INTEL_OUTPUT_LVDS;
@@ -783,20 +783,23 @@
 		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
 			mode_dev->panel_fixed_mode =
 			    drm_mode_duplicate(dev, scan);
+			DRM_DEBUG_KMS("Using mode from DDC\n");
 			goto out;	/* FIXME: check for quirks */
 		}
 	}
 
 	/* Failed to get EDID, what about VBT? do we need this? */
-	if (mode_dev->vbt_mode)
+	if (dev_priv->lfp_lvds_vbt_mode) {
 		mode_dev->panel_fixed_mode =
-		    drm_mode_duplicate(dev, mode_dev->vbt_mode);
+			drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
 
-	if (!mode_dev->panel_fixed_mode)
-		if (dev_priv->lfp_lvds_vbt_mode)
-			mode_dev->panel_fixed_mode =
-				drm_mode_duplicate(dev,
-					dev_priv->lfp_lvds_vbt_mode);
+		if (mode_dev->panel_fixed_mode) {
+			mode_dev->panel_fixed_mode->type |=
+				DRM_MODE_TYPE_PREFERRED;
+			DRM_DEBUG_KMS("Using mode from VBT\n");
+			goto out;
+		}
+	}
 
 	/*
 	 * If we didn't get EDID, try checking if the panel is already turned
@@ -813,6 +816,7 @@
 		if (mode_dev->panel_fixed_mode) {
 			mode_dev->panel_fixed_mode->type |=
 			    DRM_MODE_TYPE_PREFERRED;
+			DRM_DEBUG_KMS("Using pre-programmed mode\n");
 			goto out;	/* FIXME: check for quirks */
 		}
 	}
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index 53f427e..58529ce 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -2525,8 +2525,7 @@
 	/* encoder type will be decided later */
 	gma_encoder = &psb_intel_sdvo->base;
 	gma_encoder->type = INTEL_OUTPUT_SDVO;
-	drm_encoder_init(dev, &gma_encoder->base, &psb_intel_sdvo_enc_funcs,
-			 0, NULL);
+	drm_encoder_init(dev, &gma_encoder->base, &psb_intel_sdvo_enc_funcs, 0);
 
 	/* Read the regs to test if we can talk to the device */
 	for (i = 0; i < 0x40; i++) {
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index de8c5a0..896b6aa 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1437,7 +1437,7 @@
 
 	drm_encoder_helper_add(&priv->encoder, &tda998x_encoder_helper_funcs);
 	ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs,
-			       DRM_MODE_ENCODER_TMDS, NULL);
+			       DRM_MODE_ENCODER_TMDS);
 	if (ret)
 		goto err_encoder;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d3ce4da..5044f22 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1159,7 +1159,7 @@
 	struct intel_rps_client semaphores, mmioflips;
 
 	/* manual wa residency calculations */
-	struct intel_rps_ei up_ei, down_ei;
+	struct intel_rps_ei ei;
 
 	/*
 	 * Protects RPS/RC6 register access and PCU communication.
@@ -2150,21 +2150,19 @@
 	/** Record of address bit 17 of each page at last unbind. */
 	unsigned long *bit_17;
 
-	union {
-		/** for phy allocated objects */
-		struct drm_dma_handle *phys_handle;
-
-		struct i915_gem_userptr {
-			uintptr_t ptr;
-			unsigned read_only :1;
-			unsigned workers :4;
+	struct i915_gem_userptr {
+		uintptr_t ptr;
+		unsigned read_only :1;
+		unsigned workers :4;
 #define I915_GEM_USERPTR_MAX_WORKERS 15
 
-			struct i915_mm_struct *mm;
-			struct i915_mmu_object *mmu_object;
-			struct work_struct *work;
-		} userptr;
-	};
+		struct i915_mm_struct *mm;
+		struct i915_mmu_object *mmu_object;
+		struct work_struct *work;
+	} userptr;
+
+	/** for phys allocated objects */
+	struct drm_dma_handle *phys_handle;
 };
 #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
 
@@ -3313,6 +3311,9 @@
 }
 extern void intel_i2c_reset(struct drm_device *dev);
 
+/* intel_bios.c */
+bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port);
+
 /* intel_opregion.c */
 #ifdef CONFIG_ACPI
 extern int intel_opregion_setup(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 86c7500..b37fe0d 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2747,6 +2747,7 @@
 		struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
 
 		ppgtt->base.cleanup(&ppgtt->base);
+		kfree(ppgtt);
 	}
 
 	if (drm_mm_initialized(&vm->mm)) {
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index f7df54a..c0a96f1 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -39,7 +39,7 @@
 	if (!mutex_is_locked(mutex))
 		return false;
 
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)
+#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
 	return mutex->owner == task;
 #else
 	/* Since UP may be pre-empted, we cannot assume that we own the lock */
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 87e919a..5d2323a 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -108,17 +108,28 @@
 		pci_read_config_dword(dev->pdev, 0x5c, &base);
 		base &= ~((1<<20) - 1);
 	} else if (IS_I865G(dev)) {
+		u32 tseg_size = 0;
 		u16 toud = 0;
+		u8 tmp;
 
-		/*
-		 * FIXME is the graphics stolen memory region
-		 * always at TOUD? Ie. is it always the last
-		 * one to be allocated by the BIOS?
-		 */
+		pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
+					 I845_ESMRAMC, &tmp);
+
+		if (tmp & TSEG_ENABLE) {
+			switch (tmp & I845_TSEG_SIZE_MASK) {
+			case I845_TSEG_SIZE_512K:
+				tseg_size = KB(512);
+				break;
+			case I845_TSEG_SIZE_1M:
+				tseg_size = MB(1);
+				break;
+			}
+		}
+
 		pci_bus_read_config_word(dev->pdev->bus, PCI_DEVFN(0, 0),
 					 I865_TOUD, &toud);
 
-		base = toud << 16;
+		base = (toud << 16) + tseg_size;
 	} else if (IS_I85X(dev)) {
 		u32 tseg_size = 0;
 		u32 tom;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 0f42a27..b7b0a38 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -994,68 +994,51 @@
 	ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT);
 }
 
-static bool vlv_c0_above(struct drm_i915_private *dev_priv,
-			 const struct intel_rps_ei *old,
-			 const struct intel_rps_ei *now,
-			 int threshold)
-{
-	u64 time, c0;
-	unsigned int mul = 100;
-
-	if (old->cz_clock == 0)
-		return false;
-
-	if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
-		mul <<= 8;
-
-	time = now->cz_clock - old->cz_clock;
-	time *= threshold * dev_priv->czclk_freq;
-
-	/* Workload can be split between render + media, e.g. SwapBuffers
-	 * being blitted in X after being rendered in mesa. To account for
-	 * this we need to combine both engines into our activity counter.
-	 */
-	c0 = now->render_c0 - old->render_c0;
-	c0 += now->media_c0 - old->media_c0;
-	c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC;
-
-	return c0 >= time;
-}
-
 void gen6_rps_reset_ei(struct drm_i915_private *dev_priv)
 {
-	vlv_c0_read(dev_priv, &dev_priv->rps.down_ei);
-	dev_priv->rps.up_ei = dev_priv->rps.down_ei;
+	memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei));
 }
 
 static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
 {
+	const struct intel_rps_ei *prev = &dev_priv->rps.ei;
 	struct intel_rps_ei now;
 	u32 events = 0;
 
-	if ((pm_iir & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED)) == 0)
+	if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0)
 		return 0;
 
 	vlv_c0_read(dev_priv, &now);
 	if (now.cz_clock == 0)
 		return 0;
 
-	if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) {
-		if (!vlv_c0_above(dev_priv,
-				  &dev_priv->rps.down_ei, &now,
-				  dev_priv->rps.down_threshold))
-			events |= GEN6_PM_RP_DOWN_THRESHOLD;
-		dev_priv->rps.down_ei = now;
+	if (prev->cz_clock) {
+		u64 time, c0;
+		unsigned int mul;
+
+		mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */
+		if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
+			mul <<= 8;
+
+		time = now.cz_clock - prev->cz_clock;
+		time *= dev_priv->czclk_freq;
+
+		/* Workload can be split between render + media,
+		 * e.g. SwapBuffers being blitted in X after being rendered in
+		 * mesa. To account for this we need to combine both engines
+		 * into our activity counter.
+		 */
+		c0 = now.render_c0 - prev->render_c0;
+		c0 += now.media_c0 - prev->media_c0;
+		c0 *= mul;
+
+		if (c0 > time * dev_priv->rps.up_threshold)
+			events = GEN6_PM_RP_UP_THRESHOLD;
+		else if (c0 < time * dev_priv->rps.down_threshold)
+			events = GEN6_PM_RP_DOWN_THRESHOLD;
 	}
 
-	if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) {
-		if (vlv_c0_above(dev_priv,
-				 &dev_priv->rps.up_ei, &now,
-				 dev_priv->rps.up_threshold))
-			events |= GEN6_PM_RP_UP_THRESHOLD;
-		dev_priv->rps.up_ei = now;
-	}
-
+	dev_priv->rps.ei = now;
 	return events;
 }
 
@@ -4390,7 +4373,7 @@
 	/* Let's track the enabled rps events */
 	if (IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
 		/* WaGsvRC0ResidencyMethod:vlv */
-		dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED;
+		dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;
 	else
 		dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7e461dc..cace154 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3240,19 +3240,20 @@
 
 #define PORT_HOTPLUG_STAT	(dev_priv->info.display_mmio_offset + 0x61114)
 /*
- * HDMI/DP bits are gen4+
+ * HDMI/DP bits are g4x+
  *
  * WARNING: Bspec for hpd status bits on gen4 seems to be completely confused.
  * Please check the detailed lore in the commit message for for experimental
  * evidence.
  */
-#define   PORTD_HOTPLUG_LIVE_STATUS_G4X		(1 << 29)
+/* Bspec says GM45 should match G4X/VLV/CHV, but reality disagrees */
+#define   PORTD_HOTPLUG_LIVE_STATUS_GM45	(1 << 29)
+#define   PORTC_HOTPLUG_LIVE_STATUS_GM45	(1 << 28)
+#define   PORTB_HOTPLUG_LIVE_STATUS_GM45	(1 << 27)
+/* G4X/VLV/CHV DP/HDMI bits again match Bspec */
+#define   PORTD_HOTPLUG_LIVE_STATUS_G4X		(1 << 27)
 #define   PORTC_HOTPLUG_LIVE_STATUS_G4X		(1 << 28)
-#define   PORTB_HOTPLUG_LIVE_STATUS_G4X		(1 << 27)
-/* VLV DP/HDMI bits again match Bspec */
-#define   PORTD_HOTPLUG_LIVE_STATUS_VLV		(1 << 27)
-#define   PORTC_HOTPLUG_LIVE_STATUS_VLV		(1 << 28)
-#define   PORTB_HOTPLUG_LIVE_STATUS_VLV		(1 << 29)
+#define   PORTB_HOTPLUG_LIVE_STATUS_G4X		(1 << 29)
 #define   PORTD_HOTPLUG_INT_STATUS		(3 << 21)
 #define   PORTD_HOTPLUG_INT_LONG_PULSE		(2 << 21)
 #define   PORTD_HOTPLUG_INT_SHORT_PULSE		(1 << 21)
@@ -7357,6 +7358,8 @@
 #define  TRANS_CLK_SEL_DISABLED		(0x0<<29)
 #define  TRANS_CLK_SEL_PORT(x)		(((x)+1)<<29)
 
+#define CDCLK_FREQ			0x46200
+
 #define TRANSA_MSA_MISC			0x60410
 #define TRANSB_MSA_MISC			0x61410
 #define TRANSC_MSA_MISC			0x62410
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index ce82f9c..d14bdc5 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -1351,3 +1351,42 @@
 
 	return 0;
 }
+
+/**
+ * intel_bios_is_port_present - is the specified digital port present
+ * @dev_priv:	i915 device instance
+ * @port:	port to check
+ *
+ * Return true if the device in %port is present.
+ */
+bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port)
+{
+	static const struct {
+		u16 dp, hdmi;
+	} port_mapping[] = {
+		[PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, },
+		[PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, },
+		[PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, },
+		[PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
+	};
+	int i;
+
+	/* FIXME maybe deal with port A as well? */
+	if (WARN_ON(port == PORT_A) || port >= ARRAY_SIZE(port_mapping))
+		return false;
+
+	if (!dev_priv->vbt.child_dev_num)
+		return false;
+
+	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+		const union child_device_config *p_child =
+			&dev_priv->vbt.child_dev[i];
+		if ((p_child->common.dvo_port == port_mapping[port].dp ||
+		     p_child->common.dvo_port == port_mapping[port].hdmi) &&
+		    (p_child->common.device_type & (DEVICE_TYPE_TMDS_DVI_SIGNALING |
+						    DEVICE_TYPE_DISPLAYPORT_OUTPUT)))
+			return true;
+	}
+
+	return false;
+}
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 92f9fa1..63fea6a2 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -248,8 +248,14 @@
 		pipe_config->has_pch_encoder = true;
 
 	/* LPT FDI RX only supports 8bpc. */
-	if (HAS_PCH_LPT(dev))
+	if (HAS_PCH_LPT(dev)) {
+		if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
+			DRM_DEBUG_KMS("LPT only supports 24bpp\n");
+			return false;
+		}
+
 		pipe_config->pipe_bpp = 24;
+	}
 
 	/* FDI must always be 2.7 GHz */
 	if (HAS_DDI(dev)) {
@@ -439,6 +445,7 @@
 	struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private;
 	struct edid *edid;
 	struct i2c_adapter *i2c;
+	bool ret = false;
 
 	BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
 
@@ -455,17 +462,17 @@
 		 */
 		if (!is_digital) {
 			DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
-			return true;
+			ret = true;
+		} else {
+			DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
 		}
-
-		DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
 	} else {
 		DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [no valid EDID found]\n");
 	}
 
 	kfree(edid);
 
-	return false;
+	return ret;
 }
 
 static enum drm_connector_status
@@ -802,7 +809,7 @@
 			   &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
 
 	drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs,
-			 DRM_MODE_ENCODER_DAC, NULL);
+			 DRM_MODE_ENCODER_DAC);
 
 	intel_connector_attach_encoder(intel_connector, &crt->base);
 
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 63be0cd..3c6b076 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -3278,7 +3278,7 @@
 	encoder = &intel_encoder->base;
 
 	drm_encoder_init(dev, encoder, &intel_ddi_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	intel_encoder->compute_config = intel_ddi_compute_config;
 	intel_encoder->enable = intel_enable_ddi;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index afa8169..4f5d07b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2950,13 +2950,13 @@
 	}
 }
 
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
-				     struct drm_i915_gem_object *obj,
-				     unsigned int plane)
+u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
+			   struct drm_i915_gem_object *obj,
+			   unsigned int plane)
 {
 	const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
 	struct i915_vma *vma;
-	unsigned char *offset;
+	u64 offset;
 
 	if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
 		view = &i915_ggtt_view_rotated;
@@ -2966,14 +2966,16 @@
 		view->type))
 		return -1;
 
-	offset = (unsigned char *)vma->node.start;
+	offset = vma->node.start;
 
 	if (plane == 1) {
 		offset += vma->ggtt_view.rotation_info.uv_start_page *
 			  PAGE_SIZE;
 	}
 
-	return (unsigned long)offset;
+	WARN_ON(upper_32_bits(offset));
+
+	return lower_32_bits(offset);
 }
 
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
@@ -3099,7 +3101,7 @@
 	u32 tile_height, plane_offset, plane_size;
 	unsigned int rotation;
 	int x_offset, y_offset;
-	unsigned long surf_addr;
+	u32 surf_addr;
 	struct intel_crtc_state *crtc_state = intel_crtc->config;
 	struct intel_plane_state *plane_state;
 	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
@@ -3946,10 +3948,10 @@
 	drm_crtc_vblank_put(&intel_crtc->base);
 
 	wake_up_all(&dev_priv->pending_flip_queue);
-	queue_work(dev_priv->wq, &work->work);
-
 	trace_i915_flip_complete(intel_crtc->plane,
 				 work->pending_flip_obj);
+
+	queue_work(dev_priv->wq, &work->work);
 }
 
 void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
@@ -8228,12 +8230,14 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_encoder *encoder;
+	int i;
 	u32 val, final;
 	bool has_lvds = false;
 	bool has_cpu_edp = false;
 	bool has_panel = false;
 	bool has_ck505 = false;
 	bool can_ssc = false;
+	bool using_ssc_source = false;
 
 	/* We need to take the global config into account */
 	for_each_intel_encoder(dev, encoder) {
@@ -8260,8 +8264,22 @@
 		can_ssc = true;
 	}
 
-	DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
-		      has_panel, has_lvds, has_ck505);
+	/* Check if any DPLLs are using the SSC source */
+	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+		u32 temp = I915_READ(PCH_DPLL(i));
+
+		if (!(temp & DPLL_VCO_ENABLE))
+			continue;
+
+		if ((temp & PLL_REF_INPUT_MASK) ==
+		    PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+			using_ssc_source = true;
+			break;
+		}
+	}
+
+	DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n",
+		      has_panel, has_lvds, has_ck505, using_ssc_source);
 
 	/* Ironlake: try to setup display ref clock before DPLL
 	 * enabling. This is only under driver's control after
@@ -8298,9 +8316,9 @@
 				final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
 		} else
 			final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
-	} else {
-		final |= DREF_SSC_SOURCE_DISABLE;
-		final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+	} else if (using_ssc_source) {
+		final |= DREF_SSC_SOURCE_ENABLE;
+		final |= DREF_SSC1_ENABLE;
 	}
 
 	if (final == val)
@@ -8346,7 +8364,7 @@
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 	} else {
-		DRM_DEBUG_KMS("Disabling SSC entirely\n");
+		DRM_DEBUG_KMS("Disabling CPU source output\n");
 
 		val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
 
@@ -8357,16 +8375,20 @@
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 
-		/* Turn off the SSC source */
-		val &= ~DREF_SSC_SOURCE_MASK;
-		val |= DREF_SSC_SOURCE_DISABLE;
+		if (!using_ssc_source) {
+			DRM_DEBUG_KMS("Disabling SSC source\n");
 
-		/* Turn off SSC1 */
-		val &= ~DREF_SSC1_ENABLE;
+			/* Turn off the SSC source */
+			val &= ~DREF_SSC_SOURCE_MASK;
+			val |= DREF_SSC_SOURCE_DISABLE;
 
-		I915_WRITE(PCH_DREF_CONTROL, val);
-		POSTING_READ(PCH_DREF_CONTROL);
-		udelay(200);
+			/* Turn off SSC1 */
+			val &= ~DREF_SSC1_ENABLE;
+
+			I915_WRITE(PCH_DREF_CONTROL, val);
+			POSTING_READ(PCH_DREF_CONTROL);
+			udelay(200);
+		}
 	}
 
 	BUG_ON(val != final);
@@ -9669,6 +9691,8 @@
 	sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
+	I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
+
 	intel_update_cdclk(dev);
 
 	WARN(cdclk != dev_priv->cdclk_freq,
@@ -11930,21 +11954,11 @@
 		pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
 	}
 
-	/* Clamp bpp to default limit on screens without EDID 1.4 */
-	if (connector->base.display_info.bpc == 0) {
-		int type = connector->base.connector_type;
-		int clamp_bpp = 24;
-
-		/* Fall back to 18 bpp when DP sink capability is unknown. */
-		if (type == DRM_MODE_CONNECTOR_DisplayPort ||
-		    type == DRM_MODE_CONNECTOR_eDP)
-			clamp_bpp = 18;
-
-		if (bpp > clamp_bpp) {
-			DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of %d\n",
-				      bpp, clamp_bpp);
-			pipe_config->pipe_bpp = clamp_bpp;
-		}
+	/* Clamp bpp to 8 on screens without EDID 1.4 */
+	if (connector->base.display_info.bpc == 0 && bpp > 24) {
+		DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
+			      bpp);
+		pipe_config->pipe_bpp = 24;
 	}
 }
 
@@ -14148,6 +14162,8 @@
 		if (I915_READ(PCH_DP_D) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_D, PORT_D);
 	} else if (IS_VALLEYVIEW(dev)) {
+		bool has_edp, has_port;
+
 		/*
 		 * The DP_DETECTED bit is the latched state of the DDC
 		 * SDA pin at boot. However since eDP doesn't require DDC
@@ -14156,27 +14172,37 @@
 		 * Thus we can't rely on the DP_DETECTED bit alone to detect
 		 * eDP ports. Consult the VBT as well as DP_DETECTED to
 		 * detect eDP ports.
+		 *
+		 * Sadly the straps seem to be missing sometimes even for HDMI
+		 * ports (eg. on Voyo V3 - CHT x7-Z8700), so check both strap
+		 * and VBT for the presence of the port. Additionally we can't
+		 * trust the port type the VBT declares as we've seen at least
+		 * HDMI ports that the VBT claim are DP or eDP.
 		 */
-		if (I915_READ(VLV_HDMIB) & SDVO_DETECTED &&
-		    !intel_dp_is_edp(dev, PORT_B))
+		has_edp = intel_dp_is_edp(dev, PORT_B);
+		has_port = intel_bios_is_port_present(dev_priv, PORT_B);
+		if (I915_READ(VLV_DP_B) & DP_DETECTED || has_port)
+			has_edp &= intel_dp_init(dev, VLV_DP_B, PORT_B);
+		if ((I915_READ(VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp)
 			intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
-		if (I915_READ(VLV_DP_B) & DP_DETECTED ||
-		    intel_dp_is_edp(dev, PORT_B))
-			intel_dp_init(dev, VLV_DP_B, PORT_B);
 
-		if (I915_READ(VLV_HDMIC) & SDVO_DETECTED &&
-		    !intel_dp_is_edp(dev, PORT_C))
+		has_edp = intel_dp_is_edp(dev, PORT_C);
+		has_port = intel_bios_is_port_present(dev_priv, PORT_C);
+		if (I915_READ(VLV_DP_C) & DP_DETECTED || has_port)
+			has_edp &= intel_dp_init(dev, VLV_DP_C, PORT_C);
+		if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp)
 			intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
-		if (I915_READ(VLV_DP_C) & DP_DETECTED ||
-		    intel_dp_is_edp(dev, PORT_C))
-			intel_dp_init(dev, VLV_DP_C, PORT_C);
 
 		if (IS_CHERRYVIEW(dev)) {
-			/* eDP not supported on port D, so don't check VBT */
-			if (I915_READ(CHV_HDMID) & SDVO_DETECTED)
-				intel_hdmi_init(dev, CHV_HDMID, PORT_D);
-			if (I915_READ(CHV_DP_D) & DP_DETECTED)
+			/*
+			 * eDP not supported on port D,
+			 * so no need to worry about it
+			 */
+			has_port = intel_bios_is_port_present(dev_priv, PORT_D);
+			if (I915_READ(CHV_DP_D) & DP_DETECTED || has_port)
 				intel_dp_init(dev, CHV_DP_D, PORT_D);
+			if (I915_READ(CHV_HDMID) & SDVO_DETECTED || has_port)
+				intel_hdmi_init(dev, CHV_HDMID, PORT_D);
 		}
 
 		intel_dsi_init(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 883da2d..0f8367d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3628,8 +3628,7 @@
 intel_dp_reset_link_train(struct intel_dp *intel_dp, uint32_t *DP,
 			uint8_t dp_train_pat)
 {
-	if (!intel_dp->train_set_valid)
-		memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
+	memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
 	intel_dp_set_signal_levels(intel_dp, DP);
 	return intel_dp_set_link_train(intel_dp, DP, dp_train_pat);
 }
@@ -3746,22 +3745,6 @@
 			break;
 		}
 
-		/*
-		 * if we used previously trained voltage and pre-emphasis values
-		 * and we don't get clock recovery, reset link training values
-		 */
-		if (intel_dp->train_set_valid) {
-			DRM_DEBUG_KMS("clock recovery not ok, reset");
-			/* clear the flag as we are not reusing train set */
-			intel_dp->train_set_valid = false;
-			if (!intel_dp_reset_link_train(intel_dp, &DP,
-						       DP_TRAINING_PATTERN_1 |
-						       DP_LINK_SCRAMBLING_DISABLE)) {
-				DRM_ERROR("failed to enable link training\n");
-				return;
-			}
-			continue;
-		}
 
 		/* Check to see if we've tried the max voltage */
 		for (i = 0; i < intel_dp->lane_count; i++)
@@ -3854,7 +3837,6 @@
 		/* Make sure clock is still ok */
 		if (!drm_dp_clock_recovery_ok(link_status,
 					      intel_dp->lane_count)) {
-			intel_dp->train_set_valid = false;
 			intel_dp_link_training_clock_recovery(intel_dp);
 			intel_dp_set_link_train(intel_dp, &DP,
 						training_pattern |
@@ -3871,7 +3853,6 @@
 
 		/* Try 5 times, then try clock recovery if that fails */
 		if (tries > 5) {
-			intel_dp->train_set_valid = false;
 			intel_dp_link_training_clock_recovery(intel_dp);
 			intel_dp_set_link_train(intel_dp, &DP,
 						training_pattern |
@@ -3893,10 +3874,8 @@
 
 	intel_dp->DP = DP;
 
-	if (channel_eq) {
-		intel_dp->train_set_valid = true;
+	if (channel_eq)
 		DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
-	}
 }
 
 void intel_dp_stop_link_train(struct intel_dp *intel_dp)
@@ -4613,20 +4592,20 @@
 	return I915_READ(PORT_HOTPLUG_STAT) & bit;
 }
 
-static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv,
-				       struct intel_digital_port *port)
+static bool gm45_digital_port_connected(struct drm_i915_private *dev_priv,
+					struct intel_digital_port *port)
 {
 	u32 bit;
 
 	switch (port->port) {
 	case PORT_B:
-		bit = PORTB_HOTPLUG_LIVE_STATUS_VLV;
+		bit = PORTB_HOTPLUG_LIVE_STATUS_GM45;
 		break;
 	case PORT_C:
-		bit = PORTC_HOTPLUG_LIVE_STATUS_VLV;
+		bit = PORTC_HOTPLUG_LIVE_STATUS_GM45;
 		break;
 	case PORT_D:
-		bit = PORTD_HOTPLUG_LIVE_STATUS_VLV;
+		bit = PORTD_HOTPLUG_LIVE_STATUS_GM45;
 		break;
 	default:
 		MISSING_CASE(port->port);
@@ -4669,7 +4648,7 @@
  *
  * Return %true if @port is connected, %false otherwise.
  */
-bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
+static bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
 					 struct intel_digital_port *port)
 {
 	if (HAS_PCH_IBX(dev_priv))
@@ -4678,8 +4657,8 @@
 		return cpt_digital_port_connected(dev_priv, port);
 	else if (IS_BROXTON(dev_priv))
 		return bxt_digital_port_connected(dev_priv, port);
-	else if (IS_VALLEYVIEW(dev_priv))
-		return vlv_digital_port_connected(dev_priv, port);
+	else if (IS_GM45(dev_priv))
+		return gm45_digital_port_connected(dev_priv, port);
 	else
 		return g4x_digital_port_connected(dev_priv, port);
 }
@@ -5079,13 +5058,15 @@
 
 void intel_dp_encoder_reset(struct drm_encoder *encoder)
 {
-	struct intel_dp *intel_dp;
+	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+	if (!HAS_DDI(dev_priv))
+		intel_dp->DP = I915_READ(intel_dp->output_reg);
 
 	if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP)
 		return;
 
-	intel_dp = enc_to_intel_dp(encoder);
-
 	pps_lock(intel_dp);
 
 	/*
@@ -5157,9 +5138,6 @@
 	intel_display_power_get(dev_priv, power_domain);
 
 	if (long_hpd) {
-		/* indicate that we need to restart link training */
-		intel_dp->train_set_valid = false;
-
 		if (!intel_digital_port_connected(dev_priv, intel_dig_port))
 			goto mst_fail;
 
@@ -6135,8 +6113,9 @@
 	return true;
 }
 
-void
-intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+bool intel_dp_init(struct drm_device *dev,
+		   int output_reg,
+		   enum port port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_digital_port *intel_dig_port;
@@ -6146,7 +6125,7 @@
 
 	intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
 	if (!intel_dig_port)
-		return;
+		return false;
 
 	intel_connector = intel_connector_alloc();
 	if (!intel_connector)
@@ -6156,7 +6135,7 @@
 	encoder = &intel_encoder->base;
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	intel_encoder->compute_config = intel_dp_compute_config;
 	intel_encoder->disable = intel_disable_dp;
@@ -6201,15 +6180,14 @@
 	if (!intel_dp_init_connector(intel_dig_port, intel_connector))
 		goto err_init_connector;
 
-	return;
+	return true;
 
 err_init_connector:
 	drm_encoder_cleanup(encoder);
 	kfree(intel_connector);
 err_connector_alloc:
 	kfree(intel_dig_port);
-
-	return;
+	return false;
 }
 
 void intel_dp_mst_suspend(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 776c3f4..06bd925 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -534,7 +534,7 @@
 	intel_mst->primary = intel_dig_port;
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs,
-			 DRM_MODE_ENCODER_DPMST, NULL);
+			 DRM_MODE_ENCODER_DPMST);
 
 	intel_encoder->type = INTEL_OUTPUT_DP_MST;
 	intel_encoder->crtc_mask = 0x7;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f34a219..722aa15 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -783,7 +783,6 @@
 				     bool has_aux_irq,
 				     int send_bytes,
 				     uint32_t aux_clock_divider);
-	bool train_set_valid;
 
 	/* Displayport compliance testing */
 	unsigned long compliance_test_type;
@@ -1178,9 +1177,9 @@
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
 int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
 
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
-				     struct drm_i915_gem_object *obj,
-				     unsigned int plane);
+u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
+			   struct drm_i915_gem_object *obj,
+			   unsigned int plane);
 
 u32 skl_plane_ctl_format(uint32_t pixel_format);
 u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
@@ -1196,7 +1195,7 @@
 void assert_csr_loaded(struct drm_i915_private *dev_priv);
 
 /* intel_dp.c */
-void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
+bool intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
 bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 			     struct intel_connector *intel_connector);
 void intel_dp_set_link_params(struct intel_dp *intel_dp,
@@ -1232,8 +1231,6 @@
 void intel_edp_drrs_invalidate(struct drm_device *dev,
 		unsigned frontbuffer_bits);
 void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
-bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
-					 struct intel_digital_port *port);
 void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config);
 
 /* intel_dp_mst.c */
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 920ed62..170ae6f 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -1151,8 +1151,7 @@
 
 	connector = &intel_connector->base;
 
-	drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI,
-			 NULL);
+	drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI);
 
 	/* XXX: very likely not all of these are needed */
 	intel_encoder->compute_config = intel_dsi_compute_config;
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 8df7e7d..8492053 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -434,7 +434,7 @@
 
 	intel_encoder = &intel_dvo->base;
 	drm_encoder_init(dev, &intel_encoder->base,
-			 &intel_dvo_enc_funcs, encoder_type, NULL);
+			 &intel_dvo_enc_funcs, encoder_type);
 
 	intel_encoder->disable = intel_disable_dvo;
 	intel_encoder->enable = intel_enable_dvo;
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 4fd5fdf..c0c094d 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -362,12 +362,12 @@
 	uint64_t conn_configured = 0, mask;
 	int pass = 0;
 
-	save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool),
+	save_enabled = kcalloc(fb_helper->connector_count, sizeof(bool),
 			       GFP_KERNEL);
 	if (!save_enabled)
 		return false;
 
-	memcpy(save_enabled, enabled, dev->mode_config.num_connector);
+	memcpy(save_enabled, enabled, fb_helper->connector_count);
 	mask = (1 << fb_helper->connector_count) - 1;
 retry:
 	for (i = 0; i < fb_helper->connector_count; i++) {
@@ -501,7 +501,7 @@
 	if (fallback) {
 bail:
 		DRM_DEBUG_KMS("Not using firmware configuration\n");
-		memcpy(enabled, save_enabled, dev->mode_config.num_connector);
+		memcpy(enabled, save_enabled, fb_helper->connector_count);
 		kfree(save_enabled);
 		return false;
 	}
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 5763037..1ea8532 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1331,19 +1331,18 @@
 }
 
 static bool
-intel_hdmi_set_edid(struct drm_connector *connector, bool force)
+intel_hdmi_set_edid(struct drm_connector *connector)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-	struct edid *edid = NULL;
+	struct edid *edid;
 	bool connected = false;
 
 	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
-	if (force)
-		edid = drm_get_edid(connector,
-				    intel_gmbus_get_adapter(dev_priv,
-				    intel_hdmi->ddc_bus));
+	edid = drm_get_edid(connector,
+			    intel_gmbus_get_adapter(dev_priv,
+			    intel_hdmi->ddc_bus));
 
 	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
 
@@ -1371,37 +1370,16 @@
 intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
 	enum drm_connector_status status;
-	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
-	bool live_status = false;
-	unsigned int try;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, connector->name);
 
 	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
-	for (try = 0; !live_status && try < 9; try++) {
-		if (try)
-			msleep(10);
-		live_status = intel_digital_port_connected(dev_priv,
-				hdmi_to_dig_port(intel_hdmi));
-	}
-
-	if (!live_status) {
-		DRM_DEBUG_KMS("HDMI live status down\n");
-		/*
-		 * Live status register is not reliable on all intel platforms.
-		 * So consider live_status only for certain platforms, for
-		 * others, read EDID to determine presence of sink.
-		 */
-		if (INTEL_INFO(dev_priv)->gen < 7 || IS_IVYBRIDGE(dev_priv))
-			live_status = true;
-	}
-
 	intel_hdmi_unset_edid(connector);
 
-	if (intel_hdmi_set_edid(connector, live_status)) {
+	if (intel_hdmi_set_edid(connector)) {
 		struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
 
 		hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
@@ -1427,7 +1405,7 @@
 	if (connector->status != connector_status_connected)
 		return;
 
-	intel_hdmi_set_edid(connector, true);
+	intel_hdmi_set_edid(connector);
 	hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
 }
 
@@ -2019,6 +1997,50 @@
 	intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
 }
 
+static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv,
+			     enum port port)
+{
+	const struct ddi_vbt_port_info *info =
+		&dev_priv->vbt.ddi_port_info[port];
+	u8 ddc_pin;
+
+	if (info->alternate_ddc_pin) {
+		DRM_DEBUG_KMS("Using DDC pin 0x%x for port %c (VBT)\n",
+			      info->alternate_ddc_pin, port_name(port));
+		return info->alternate_ddc_pin;
+	}
+
+	switch (port) {
+	case PORT_B:
+		if (IS_BROXTON(dev_priv))
+			ddc_pin = GMBUS_PIN_1_BXT;
+		else
+			ddc_pin = GMBUS_PIN_DPB;
+		break;
+	case PORT_C:
+		if (IS_BROXTON(dev_priv))
+			ddc_pin = GMBUS_PIN_2_BXT;
+		else
+			ddc_pin = GMBUS_PIN_DPC;
+		break;
+	case PORT_D:
+		if (IS_CHERRYVIEW(dev_priv))
+			ddc_pin = GMBUS_PIN_DPD_CHV;
+		else
+			ddc_pin = GMBUS_PIN_DPD;
+		break;
+	default:
+		MISSING_CASE(port);
+		ddc_pin = GMBUS_PIN_DPB;
+		break;
+	}
+
+	DRM_DEBUG_KMS("Using DDC pin 0x%x for port %c (platform default)\n",
+		      ddc_pin, port_name(port));
+
+	return ddc_pin;
+}
+
 void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 			       struct intel_connector *intel_connector)
 {
@@ -2028,7 +2050,9 @@
 	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum port port = intel_dig_port->port;
-	uint8_t alternate_ddc_pin;
+
+	DRM_DEBUG_KMS("Adding HDMI connector on port %c\n",
+		      port_name(port));
 
 	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
 			   DRM_MODE_CONNECTOR_HDMIA);
@@ -2038,12 +2062,10 @@
 	connector->doublescan_allowed = 0;
 	connector->stereo_allowed = 1;
 
+	intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port);
+
 	switch (port) {
 	case PORT_B:
-		if (IS_BROXTON(dev_priv))
-			intel_hdmi->ddc_bus = GMBUS_PIN_1_BXT;
-		else
-			intel_hdmi->ddc_bus = GMBUS_PIN_DPB;
 		/*
 		 * On BXT A0/A1, sw needs to activate DDIA HPD logic and
 		 * interrupts to check the external panel connection.
@@ -2054,46 +2076,17 @@
 			intel_encoder->hpd_pin = HPD_PORT_B;
 		break;
 	case PORT_C:
-		if (IS_BROXTON(dev_priv))
-			intel_hdmi->ddc_bus = GMBUS_PIN_2_BXT;
-		else
-			intel_hdmi->ddc_bus = GMBUS_PIN_DPC;
 		intel_encoder->hpd_pin = HPD_PORT_C;
 		break;
 	case PORT_D:
-		if (WARN_ON(IS_BROXTON(dev_priv)))
-			intel_hdmi->ddc_bus = GMBUS_PIN_DISABLED;
-		else if (IS_CHERRYVIEW(dev_priv))
-			intel_hdmi->ddc_bus = GMBUS_PIN_DPD_CHV;
-		else
-			intel_hdmi->ddc_bus = GMBUS_PIN_DPD;
 		intel_encoder->hpd_pin = HPD_PORT_D;
 		break;
 	case PORT_E:
-		/* On SKL PORT E doesn't have seperate GMBUS pin
-		 *  We rely on VBT to set a proper alternate GMBUS pin. */
-		alternate_ddc_pin =
-			dev_priv->vbt.ddi_port_info[PORT_E].alternate_ddc_pin;
-		switch (alternate_ddc_pin) {
-		case DDC_PIN_B:
-			intel_hdmi->ddc_bus = GMBUS_PIN_DPB;
-			break;
-		case DDC_PIN_C:
-			intel_hdmi->ddc_bus = GMBUS_PIN_DPC;
-			break;
-		case DDC_PIN_D:
-			intel_hdmi->ddc_bus = GMBUS_PIN_DPD;
-			break;
-		default:
-			MISSING_CASE(alternate_ddc_pin);
-		}
 		intel_encoder->hpd_pin = HPD_PORT_E;
 		break;
-	case PORT_A:
-		intel_encoder->hpd_pin = HPD_PORT_A;
-		/* Internal port only for eDP. */
 	default:
-		BUG();
+		MISSING_CASE(port);
+		return;
 	}
 
 	if (IS_VALLEYVIEW(dev)) {
@@ -2159,7 +2152,7 @@
 	intel_encoder = &intel_dig_port->base;
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	intel_encoder->compute_config = intel_hdmi_compute_config;
 	if (HAS_PCH_SPLIT(dev)) {
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 5722a39..7f39b8a 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -1025,7 +1025,7 @@
 			   DRM_MODE_CONNECTOR_LVDS);
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
-			 DRM_MODE_ENCODER_LVDS, NULL);
+			 DRM_MODE_ENCODER_LVDS);
 
 	intel_encoder->enable = intel_enable_lvds;
 	intel_encoder->pre_enable = intel_pre_enable_lvds;
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 6dc13c0..e362a30 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -682,7 +682,7 @@
 	}
 
 	if (!acpi_video_bus) {
-		DRM_ERROR("No ACPI video bus found\n");
+		DRM_DEBUG_KMS("No ACPI video bus found\n");
 		return;
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f091ad1..fd4690e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1789,16 +1789,20 @@
 				   const struct intel_plane_state *pstate,
 				   uint32_t mem_value)
 {
-	int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
+	/*
+	 * We treat the cursor plane as always-on for the purposes of watermark
+	 * calculation.  Until we have two-stage watermark programming merged,
+	 * this is necessary to avoid flickering.
+	 */
+	int cpp = 4;
+	int width = pstate->visible ? pstate->base.crtc_w : 64;
 
-	if (!cstate->base.active || !pstate->visible)
+	if (!cstate->base.active)
 		return 0;
 
 	return ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
 			      cstate->base.adjusted_mode.crtc_htotal,
-			      drm_rect_width(&pstate->dst),
-			      bpp,
-			      mem_value);
+			      width, cpp, mem_value);
 }
 
 /* Only for WM_LP. */
@@ -2093,32 +2097,34 @@
 				GEN9_MEM_LATENCY_LEVEL_MASK;
 
 		/*
+		 * If a level n (n > 1) has a 0us latency, all levels m (m >= n)
+		 * need to be disabled. We make sure to sanitize the values out
+		 * of the punit to satisfy this requirement.
+		 */
+		for (level = 1; level <= max_level; level++) {
+			if (wm[level] == 0) {
+				for (i = level + 1; i <= max_level; i++)
+					wm[i] = 0;
+				break;
+			}
+		}
+
+		/*
 		 * WaWmMemoryReadLatency:skl
 		 *
 		 * punit doesn't take into account the read latency so we need
-		 * to add 2us to the various latency levels we retrieve from
-		 * the punit.
-		 *   - W0 is a bit special in that it's the only level that
-		 *   can't be disabled if we want to have display working, so
-		 *   we always add 2us there.
-		 *   - For levels >=1, punit returns 0us latency when they are
-		 *   disabled, so we respect that and don't add 2us then
-		 *
-		 * Additionally, if a level n (n > 1) has a 0us latency, all
-		 * levels m (m >= n) need to be disabled. We make sure to
-		 * sanitize the values out of the punit to satisfy this
-		 * requirement.
+		 * to add 2us to the various latency levels we retrieve from the
+		 * punit when level 0 response data us 0us.
 		 */
-		wm[0] += 2;
-		for (level = 1; level <= max_level; level++)
-			if (wm[level] != 0)
+		if (wm[0] == 0) {
+			wm[0] += 2;
+			for (level = 1; level <= max_level; level++) {
+				if (wm[level] == 0)
+					break;
 				wm[level] += 2;
-			else {
-				for (i = level + 1; i <= max_level; i++)
-					wm[i] = 0;
-
-				break;
 			}
+		}
+
 	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		uint64_t sskpd = I915_READ64(MCH_SSKPD);
 
@@ -3880,6 +3886,8 @@
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
 
+	memset(active, 0, sizeof(*active));
+
 	active->pipe_enabled = intel_crtc->active;
 
 	if (active->pipe_enabled) {
@@ -4368,6 +4376,12 @@
 		break;
 	}
 
+	/* When byt can survive without system hang with dynamic
+	 * sw freq adjustments, this restriction can be lifted.
+	 */
+	if (IS_VALLEYVIEW(dev_priv))
+		goto skip_hw_write;
+
 	I915_WRITE(GEN6_RP_UP_EI,
 		GT_INTERVAL_FROM_US(dev_priv, ei_up));
 	I915_WRITE(GEN6_RP_UP_THRESHOLD,
@@ -4386,6 +4400,7 @@
 		    GEN6_RP_UP_BUSY_AVG |
 		    GEN6_RP_DOWN_IDLE_AVG);
 
+skip_hw_write:
 	dev_priv->rps.power = new_power;
 	dev_priv->rps.up_threshold = threshold_up;
 	dev_priv->rps.down_threshold = threshold_down;
@@ -4396,8 +4411,9 @@
 {
 	u32 mask = 0;
 
+	/* We use UP_EI_EXPIRED interupts for both up/down in manual mode */
 	if (val > dev_priv->rps.min_freq_softlimit)
-		mask |= GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
+		mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
 	if (val < dev_priv->rps.max_freq_softlimit)
 		mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD;
 
@@ -4501,7 +4517,7 @@
 {
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (dev_priv->rps.enabled) {
-		if (dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED))
+		if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED)
 			gen6_rps_reset_ei(dev_priv);
 		I915_WRITE(GEN6_PMINTRMSK,
 			   gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
@@ -4520,7 +4536,8 @@
 		else
 			gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
 		dev_priv->rps.last_adj = 0;
-		I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
+		I915_WRITE(GEN6_PMINTRMSK,
+			   gen6_sanitize_rps_pm_mask(dev_priv, ~0));
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
@@ -6620,6 +6637,12 @@
 	misccpctl = I915_READ(GEN7_MISCCPCTL);
 	I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
 	I915_WRITE(GEN8_L3SQCREG1, BDW_WA_L3SQCREG1_DEFAULT);
+	/*
+	 * Wait at least 100 clocks before re-enabling clock gating. See
+	 * the definition of L3SQCREG1 in BSpec.
+	 */
+	POSTING_READ(GEN8_L3SQCREG1);
+	udelay(1);
 	I915_WRITE(GEN7_MISCCPCTL, misccpctl);
 
 	/*
@@ -6788,7 +6811,18 @@
 
 static void vlv_init_display_clock_gating(struct drm_i915_private *dev_priv)
 {
-	I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
+        u32 val;
+
+        /*
+        * On driver load, a pipe may be active and driving a DSI display.
+        * Preserve DPOUNIT_CLOCK_GATE_DISABLE to avoid the pipe getting stuck
+        * (and never recovering) in this case. intel_dsi_post_disable() will
+        * clear it when we turn off the display.
+        */
+        val = I915_READ(DSPCLK_GATE_D);
+        val &= DPOUNIT_CLOCK_GATE_DISABLE;
+        val |= VRHUNIT_CLOCK_GATE_DISABLE;
+        I915_WRITE(DSPCLK_GATE_D, val);
 
 	/*
 	 * Disable trickle feed and enable pnd deadline calculation
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index c011cf7..c42b636 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2959,8 +2959,7 @@
 	/* encoder type will be decided later */
 	intel_encoder = &intel_sdvo->base;
 	intel_encoder->type = INTEL_OUTPUT_SDVO;
-	drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0,
-			 NULL);
+	drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0);
 
 	/* Read the regs to test if we can talk to the device */
 	for (i = 0; i < 0x40; i++) {
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 56dc132..2cc6aa0 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -195,7 +195,7 @@
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key =
 		&to_intel_plane_state(drm_plane->state)->ckey;
-	unsigned long surf_addr;
+	u32 surf_addr;
 	u32 tile_height, plane_offset, plane_size;
 	unsigned int rotation;
 	int x_offset, y_offset;
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 948cbff..6bea789 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1645,7 +1645,7 @@
 			   DRM_MODE_CONNECTOR_SVIDEO);
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
-			 DRM_MODE_ENCODER_TVDAC, NULL);
+			 DRM_MODE_ENCODER_TVDAC);
 
 	intel_encoder->compute_config = intel_tv_compute_config;
 	intel_encoder->get_config = intel_tv_get_config;
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index 35fcf6b..98605ea 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -251,7 +251,7 @@
 
 	drm_encoder_helper_add(encoder, &dw_hdmi_imx_encoder_helper_funcs);
 	drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
 }
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 7b990b4..5378bdc 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -26,6 +26,7 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_of.h>
+#include <video/imx-ipu-v3.h>
 
 #include "imx-drm.h"
 
@@ -504,6 +505,13 @@
 {
 	struct device_node *np = data;
 
+	/* Special case for DI, dev->of_node may not be set yet */
+	if (strcmp(dev->driver->name, "imx-ipuv3-crtc") == 0) {
+		struct ipu_client_platformdata *pdata = dev->platform_data;
+
+		return pdata->of_node == np;
+	}
+
 	/* Special case for LDB, one device for two channels */
 	if (of_node_cmp(np->name, "lvds-channel") == 0) {
 		np = of_get_parent(np);
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index c79a61b..abacc8f 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -422,7 +422,7 @@
 	drm_encoder_helper_add(&imx_ldb_ch->encoder,
 			&imx_ldb_encoder_helper_funcs);
 	drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs,
-			 DRM_MODE_ENCODER_LVDS, NULL);
+			 DRM_MODE_ENCODER_LVDS);
 
 	drm_connector_helper_add(&imx_ldb_ch->connector,
 			&imx_ldb_connector_helper_funcs);
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index e61a8fc..f959714 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -508,7 +508,7 @@
 
 	drm_encoder_helper_add(&tve->encoder, &imx_tve_encoder_helper_funcs);
 	drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs,
-			 encoder_type, NULL);
+			 encoder_type);
 
 	drm_connector_helper_add(&tve->connector,
 			&imx_tve_connector_helper_funcs);
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index 4ab841e..9b0abd4 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -369,7 +369,7 @@
 
 	ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
 			&ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs,
-			ipu_crtc->dev->of_node);
+			pdata->of_node);
 	if (ret) {
 		dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
 		goto err_put_resources;
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index fcbe4d2..2e9b9f1 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -192,7 +192,7 @@
 
 	drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs);
 	drm_encoder_init(drm, &imxpd->encoder, &imx_pd_encoder_funcs,
-			 DRM_MODE_ENCODER_NONE, NULL);
+			 DRM_MODE_ENCODER_NONE);
 
 	drm_connector_helper_add(&imxpd->connector,
 			&imx_pd_connector_helper_funcs);
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 3180212..e5bb40e 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -194,7 +194,7 @@
 			}
 		}
 
-		fvv = pllreffreq * testn / testm;
+		fvv = pllreffreq * (n + 1) / (m + 1);
 		fvv = (fvv - 800000) / 50000;
 
 		if (fvv > 15)
@@ -214,6 +214,14 @@
 	WREG_DAC(MGA1064_PIX_PLLC_M, m);
 	WREG_DAC(MGA1064_PIX_PLLC_N, n);
 	WREG_DAC(MGA1064_PIX_PLLC_P, p);
+
+	if (mdev->unique_rev_id >= 0x04) {
+		WREG_DAC(0x1a, 0x09);
+		msleep(20);
+		WREG_DAC(0x1a, 0x01);
+
+	}
+
 	return 0;
 }
 
@@ -1538,7 +1546,7 @@
 	encoder->possible_crtcs = 0x1;
 
 	drm_encoder_init(dev, encoder, &mga_encoder_encoder_funcs,
-			 DRM_MODE_ENCODER_DAC, NULL);
+			 DRM_MODE_ENCODER_DAC);
 	drm_encoder_helper_add(encoder, &mga_encoder_helper_funcs);
 
 	return encoder;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
index a21df54..89614c6 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
@@ -262,7 +262,7 @@
 	encoder = &mdp4_dtv_encoder->base;
 
 	drm_encoder_init(dev, encoder, &mdp4_dtv_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &mdp4_dtv_encoder_helper_funcs);
 
 	mdp4_dtv_encoder->src_clk = devm_clk_get(dev->dev, "src_clk");
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
index f824c64..4cd6e72 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
@@ -460,7 +460,7 @@
 	encoder = &mdp4_lcdc_encoder->base;
 
 	drm_encoder_init(dev, encoder, &mdp4_lcdc_encoder_funcs,
-			 DRM_MODE_ENCODER_LVDS, NULL);
+			 DRM_MODE_ENCODER_LVDS);
 	drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs);
 
 	/* TODO: do we need different pll in other cases? */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
index 1aa21db..8e6c9b5 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
@@ -326,7 +326,7 @@
 	mdp5_cmd_enc->ctl = ctl;
 
 	drm_encoder_init(dev, encoder, &mdp5_cmd_encoder_funcs,
-			DRM_MODE_ENCODER_DSI, NULL);
+			DRM_MODE_ENCODER_DSI);
 
 	drm_encoder_helper_add(encoder, &mdp5_cmd_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index 278e307..c9e32b0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -354,7 +354,7 @@
 
 	spin_lock_init(&mdp5_encoder->intf_lock);
 
-	drm_encoder_init(dev, encoder, &mdp5_encoder_funcs, enc_type, NULL);
+	drm_encoder_init(dev, encoder, &mdp5_encoder_funcs, enc_type);
 
 	drm_encoder_helper_add(encoder, &mdp5_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index b88ce51..24d45fc 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -986,6 +986,7 @@
 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
 	.gem_prime_export   = drm_gem_prime_export,
 	.gem_prime_import   = drm_gem_prime_import,
+	.gem_prime_res_obj  = msm_gem_prime_res_obj,
 	.gem_prime_pin      = msm_gem_prime_pin,
 	.gem_prime_unpin    = msm_gem_prime_unpin,
 	.gem_prime_get_sg_table = msm_gem_prime_get_sg_table,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 3be7a56..026e156 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -212,6 +212,7 @@
 void *msm_gem_prime_vmap(struct drm_gem_object *obj);
 void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
+struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj);
 struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
 		struct dma_buf_attachment *attach, struct sg_table *sg);
 int msm_gem_prime_pin(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
index 121975b..1fbddc5 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -70,3 +70,10 @@
 	if (!obj->import_attach)
 		msm_gem_put_pages(obj);
 }
+
+struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj)
+{
+	struct msm_gem_object *msm_obj = to_msm_bo(obj);
+
+	return msm_obj->resv;
+}
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 6d7cd3f..1847f83 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -55,6 +55,14 @@
 	return submit;
 }
 
+static inline unsigned long __must_check
+copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		return __copy_from_user_inatomic(to, from, n);
+	return -EFAULT;
+}
+
 static int submit_lookup_objects(struct msm_gem_submit *submit,
 		struct drm_msm_gem_submit *args, struct drm_file *file)
 {
@@ -62,6 +70,7 @@
 	int ret = 0;
 
 	spin_lock(&file->table_lock);
+	pagefault_disable();
 
 	for (i = 0; i < args->nr_bos; i++) {
 		struct drm_msm_gem_submit_bo submit_bo;
@@ -70,10 +79,15 @@
 		void __user *userptr =
 			to_user_ptr(args->bos + (i * sizeof(submit_bo)));
 
-		ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo));
-		if (ret) {
-			ret = -EFAULT;
-			goto out_unlock;
+		ret = copy_from_user_inatomic(&submit_bo, userptr, sizeof(submit_bo));
+		if (unlikely(ret)) {
+			pagefault_enable();
+			spin_unlock(&file->table_lock);
+			ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo));
+			if (ret)
+				goto out;
+			spin_lock(&file->table_lock);
+			pagefault_disable();
 		}
 
 		if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) {
@@ -113,9 +127,12 @@
 	}
 
 out_unlock:
-	submit->nr_bos = i;
+	pagefault_enable();
 	spin_unlock(&file->table_lock);
 
+out:
+	submit->nr_bos = i;
+
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c
index 0adefac..78cb033 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dac.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c
@@ -550,8 +550,7 @@
 	else
 		helper = &nv04_dac_helper_funcs;
 
-	drm_encoder_init(dev, encoder, &nv04_dac_funcs, DRM_MODE_ENCODER_DAC,
-			 NULL);
+	drm_encoder_init(dev, encoder, &nv04_dac_funcs, DRM_MODE_ENCODER_DAC);
 	drm_encoder_helper_add(encoder, helper);
 
 	encoder->possible_crtcs = entry->heads;
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
index 9164ffb..429ab5e 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
@@ -706,7 +706,7 @@
 	nv_encoder->dcb = entry;
 	nv_encoder->or = ffs(entry->or) - 1;
 
-	drm_encoder_init(connector->dev, encoder, &nv04_dfp_funcs, type, NULL);
+	drm_encoder_init(connector->dev, encoder, &nv04_dfp_funcs, type);
 	drm_encoder_helper_add(encoder, helper);
 
 	encoder->possible_crtcs = entry->heads;
diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c
index 956a833..57c7389 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/hw.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c
@@ -222,6 +222,7 @@
 		uint32_t mpllP;
 
 		pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP);
+		mpllP = (mpllP >> 8) & 0xf;
 		if (!mpllP)
 			mpllP = 4;
 
@@ -232,7 +233,7 @@
 		uint32_t clock;
 
 		pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock);
-		return clock;
+		return clock / 1000;
 	}
 
 	ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
index 8c89c14..5345eb5 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
@@ -225,8 +225,7 @@
 	/* Initialize the common members */
 	encoder = to_drm_encoder(nv_encoder);
 
-	drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC,
-			 NULL);
+	drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC);
 	drm_encoder_helper_add(encoder, &nv04_tv_helper_funcs);
 
 	encoder->possible_crtcs = entry->heads;
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index 72312f1..b734195 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -816,8 +816,7 @@
 	tv_enc->base.dcb = entry;
 	tv_enc->base.or = ffs(entry->or) - 1;
 
-	drm_encoder_init(dev, encoder, &nv17_tv_funcs, DRM_MODE_ENCODER_TVDAC,
-			 NULL);
+	drm_encoder_init(dev, encoder, &nv17_tv_funcs, DRM_MODE_ENCODER_TVDAC);
 	drm_encoder_helper_add(encoder, &nv17_tv_helper_funcs);
 	to_encoder_slave(encoder)->slave_funcs = &nv17_tv_slave_funcs;
 
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
index 82d3e28..7e4f24a 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
@@ -4,6 +4,7 @@
 
 struct nvkm_alarm {
 	struct list_head head;
+	struct list_head exec;
 	u64 timestamp;
 	void (*func)(struct nvkm_alarm *);
 };
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 4dca65a..af224fa 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -333,6 +333,9 @@
 	if (bios->major_version < 5 && bios->data[0x48] & 0x4)
 		return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf;
 
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_MAXWELL)
+		return nvif_rd32(device, 0x001800) & 0x0000000f;
+	else
 	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
 		return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
 	else
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 58a3f7c..00de1bf 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -370,7 +370,8 @@
 		return ret;
 
 	/* enable polling for external displays */
-	drm_kms_helper_poll_enable(dev);
+	if (!dev->mode_config.poll_enabled)
+		drm_kms_helper_poll_enable(dev);
 
 	/* enable hotplug interrupts */
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 1d3ee51..91a61d2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -308,7 +308,16 @@
 	bool boot = false;
 	int ret;
 
-	/* remove conflicting drivers (vesafb, efifb etc) */
+	/* We need to check that the chipset is supported before booting
+	 * fbdev off the hardware, as there's no way to put it back.
+	 */
+	ret = nvkm_device_pci_new(pdev, NULL, "error", true, false, 0, &device);
+	if (ret)
+		return ret;
+
+	nvkm_device_del(&device);
+
+	/* Remove conflicting drivers (vesafb, efifb etc). */
 	aper = alloc_apertures(3);
 	if (!aper)
 		return -ENOMEM;
@@ -734,7 +743,10 @@
 	pci_set_master(pdev);
 
 	ret = nouveau_do_resume(drm_dev, true);
-	drm_kms_helper_poll_enable(drm_dev);
+
+	if (!drm_dev->mode_config.poll_enabled)
+		drm_kms_helper_poll_enable(drm_dev);
+
 	/* do magic */
 	nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25));
 	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 59f27e7..e40a1b0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -557,6 +557,8 @@
 	if (ret)
 		goto fini;
 
+	if (fbcon->helper.fbdev)
+		fbcon->helper.fbdev->pixmap.buf_align = 4;
 	return 0;
 
 fini:
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index 2e3a62d..1621c8a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -99,6 +99,7 @@
 	struct nouveau_bo *bo;
 	struct nouveau_bo *bo_gart;
 	u32 *suspend;
+	struct mutex mutex;
 };
 
 u64  nv84_fence_crtc(struct nouveau_channel *, int);
diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c
index 6ae1b34..b7b9612 100644
--- a/drivers/gpu/drm/nouveau/nouveau_usif.c
+++ b/drivers/gpu/drm/nouveau/nouveau_usif.c
@@ -313,7 +313,8 @@
 	if (nvif_unpack(argv->v0, 0, 0, true)) {
 		/* block access to objects not created via this interface */
 		owner = argv->v0.owner;
-		if (argv->v0.object == 0ULL)
+		if (argv->v0.object == 0ULL &&
+		    argv->v0.type != NVIF_IOCTL_V0_DEL)
 			argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */
 		else
 			argv->v0.owner = NVDRM_OBJECT_USIF;
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
index 789dc29..f905683 100644
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -82,7 +82,6 @@
 	uint32_t fg;
 	uint32_t bg;
 	uint32_t dsize;
-	uint32_t width;
 	uint32_t *data = (uint32_t *)image->data;
 	int ret;
 
@@ -93,9 +92,6 @@
 	if (ret)
 		return ret;
 
-	width = ALIGN(image->width, 8);
-	dsize = ALIGN(width * image->height, 32) >> 5;
-
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
 		fg = ((uint32_t *) info->pseudo_palette)[image->fg_color];
@@ -111,10 +107,11 @@
 			 ((image->dx + image->width) & 0xffff));
 	OUT_RING(chan, bg);
 	OUT_RING(chan, fg);
-	OUT_RING(chan, (image->height << 16) | width);
+	OUT_RING(chan, (image->height << 16) | ALIGN(image->width, 8));
 	OUT_RING(chan, (image->height << 16) | image->width);
 	OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
 
+	dsize = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
 	while (dsize) {
 		int iter_len = dsize > 128 ? 128 : dsize;
 
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 7681838..c053c50 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1717,7 +1717,7 @@
 	encoder = to_drm_encoder(nv_encoder);
 	encoder->possible_crtcs = dcbe->heads;
 	encoder->possible_clones = 0;
-	drm_encoder_init(connector->dev, encoder, &nv50_dac_func, type, NULL);
+	drm_encoder_init(connector->dev, encoder, &nv50_dac_func, type);
 	drm_encoder_helper_add(encoder, &nv50_dac_hfunc);
 
 	drm_mode_connector_attach_encoder(connector, encoder);
@@ -2125,7 +2125,7 @@
 	encoder = to_drm_encoder(nv_encoder);
 	encoder->possible_crtcs = dcbe->heads;
 	encoder->possible_clones = 0;
-	drm_encoder_init(connector->dev, encoder, &nv50_sor_func, type, NULL);
+	drm_encoder_init(connector->dev, encoder, &nv50_sor_func, type);
 	drm_encoder_helper_add(encoder, &nv50_sor_hfunc);
 
 	drm_mode_connector_attach_encoder(connector, encoder);
@@ -2305,7 +2305,7 @@
 	encoder = to_drm_encoder(nv_encoder);
 	encoder->possible_crtcs = dcbe->heads;
 	encoder->possible_clones = 0;
-	drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type, NULL);
+	drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type);
 	drm_encoder_helper_add(encoder, &nv50_pior_hfunc);
 
 	drm_mode_connector_attach_encoder(connector, encoder);
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index e05499d..c8e0965 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -95,7 +95,7 @@
 	struct nouveau_fbdev *nfbdev = info->par;
 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
 	struct nouveau_channel *chan = drm->channel;
-	uint32_t width, dwords, *data = (uint32_t *)image->data;
+	uint32_t dwords, *data = (uint32_t *)image->data;
 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
 	uint32_t *palette = info->pseudo_palette;
 	int ret;
@@ -107,9 +107,6 @@
 	if (ret)
 		return ret;
 
-	width = ALIGN(image->width, 32);
-	dwords = (width * image->height) >> 5;
-
 	BEGIN_NV04(chan, NvSub2D, 0x0814, 2);
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@
 	OUT_RING(chan, 0);
 	OUT_RING(chan, image->dy);
 
+	dwords = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
 	while (dwords) {
 		int push = dwords > 2047 ? 2047 : dwords;
 
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index 412c5be..7bc26ec 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -121,8 +121,10 @@
 	}
 
 	nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
+	mutex_lock(&priv->mutex);
 	nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
 	nouveau_bo_vma_del(priv->bo, &fctx->vma);
+	mutex_unlock(&priv->mutex);
 	nouveau_fence_context_del(&fctx->base);
 	chan->fence = NULL;
 	nouveau_fence_context_free(&fctx->base);
@@ -148,11 +150,13 @@
 	fctx->base.sync32 = nv84_fence_sync32;
 	fctx->base.sequence = nv84_fence_read(chan);
 
+	mutex_lock(&priv->mutex);
 	ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
 	if (ret == 0) {
 		ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
 					&fctx->vma_gart);
 	}
+	mutex_unlock(&priv->mutex);
 
 	/* map display semaphore buffers into channel's vm */
 	for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
@@ -232,6 +236,8 @@
 	priv->base.context_base = fence_context_alloc(priv->base.contexts);
 	priv->base.uevent = true;
 
+	mutex_init(&priv->mutex);
+
 	/* Use VRAM if there is any ; otherwise fallback to system memory */
 	domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
 			 /*
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
index c97395b..22d3257 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
@@ -95,7 +95,7 @@
 	struct nouveau_fbdev *nfbdev = info->par;
 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
 	struct nouveau_channel *chan = drm->channel;
-	uint32_t width, dwords, *data = (uint32_t *)image->data;
+	uint32_t dwords, *data = (uint32_t *)image->data;
 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
 	uint32_t *palette = info->pseudo_palette;
 	int ret;
@@ -107,9 +107,6 @@
 	if (ret)
 		return ret;
 
-	width = ALIGN(image->width, 32);
-	dwords = (width * image->height) >> 5;
-
 	BEGIN_NVC0(chan, NvSub2D, 0x0814, 2);
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@
 	OUT_RING  (chan, 0);
 	OUT_RING  (chan, image->dy);
 
+	dwords = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
 	while (dwords) {
 		int push = dwords > 2047 ? 2047 : dwords;
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index bbc9824..7f8acb3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -714,7 +714,7 @@
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
 	.mc = nv44_mc_new,
-	.mmu = nv44_mmu_new,
+	.mmu = nv04_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
 	.timer = nv41_timer_new,
@@ -1833,7 +1833,7 @@
 	.fb = gk104_fb_new,
 	.fuse = gf100_fuse_new,
 	.gpio = gk104_gpio_new,
-	.i2c = gf119_i2c_new,
+	.i2c = gk104_i2c_new,
 	.ibus = gk104_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
@@ -1941,7 +1941,7 @@
 	.fb = gm107_fb_new,
 	.fuse = gm107_fuse_new,
 	.gpio = gk104_gpio_new,
-	.i2c = gf119_i2c_new,
+	.i2c = gk104_i2c_new,
 	.ibus = gk104_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gm107_ltc_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c
index c1590b7..eb58cd7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c
@@ -59,7 +59,7 @@
 			);
 		}
 		for (i = 0; i < size; i++)
-			nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[0]);
+			nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[i]);
 		for (; i < 0x60; i++)
 			nvkm_wr32(device, 0x61c440 + soff, (i << 8));
 		nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000003);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
index b4b41b1..2aaf0dd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
@@ -40,8 +40,8 @@
 gf119_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 {
 	struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-	const u32 loff = gf119_sor_loff(outp);
-	nvkm_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);
+	const u32 soff = gf119_sor_soff(outp);
+	nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, 0x01010101 * pattern);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
index bfcc640..b7f4b82 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
@@ -36,7 +36,10 @@
 {
 	struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
 	struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
+
+	mutex_lock(&chan->fifo->base.engine.subdev.mutex);
 	nvkm_ramht_remove(imem->ramht, cookie);
+	mutex_unlock(&chan->fifo->base.engine.subdev.mutex);
 }
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
index e7cbc13..89976ff 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
@@ -59,6 +59,7 @@
 	struct nvkm_gpuobj *inst = chan->base.inst;
 	int ret = 0;
 
+	mutex_lock(&subdev->mutex);
 	nvkm_wr32(device, 0x002634, chan->base.chid);
 	if (nvkm_msec(device, 2000,
 		if (nvkm_rd32(device, 0x002634) == chan->base.chid)
@@ -66,10 +67,12 @@
 	) < 0) {
 		nvkm_error(subdev, "channel %d [%s] kick timeout\n",
 			   chan->base.chid, chan->base.object.client->name);
-		ret = -EBUSY;
-		if (suspend)
-			return ret;
+		ret = -ETIMEDOUT;
 	}
+	mutex_unlock(&subdev->mutex);
+
+	if (ret && suspend)
+		return ret;
 
 	if (offset) {
 		nvkm_kmap(inst);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
index 0b81754..aa1692e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
@@ -39,7 +39,9 @@
 	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
 	struct nvkm_client *client = chan->base.object.client;
+	int ret = 0;
 
+	mutex_lock(&subdev->mutex);
 	nvkm_wr32(device, 0x002634, chan->base.chid);
 	if (nvkm_msec(device, 2000,
 		if (!(nvkm_rd32(device, 0x002634) & 0x00100000))
@@ -47,10 +49,10 @@
 	) < 0) {
 		nvkm_error(subdev, "channel %d [%s] kick timeout\n",
 			   chan->base.chid, client->name);
-		return -EBUSY;
+		ret = -ETIMEDOUT;
 	}
-
-	return 0;
+	mutex_unlock(&subdev->mutex);
+	return ret;
 }
 
 static u32
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index 36655a7..eeeea1c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -874,22 +874,41 @@
 }
 
 static const struct nvkm_enum gf100_mp_warp_error[] = {
-	{ 0x00, "NO_ERROR" },
-	{ 0x01, "STACK_MISMATCH" },
+	{ 0x01, "STACK_ERROR" },
+	{ 0x02, "API_STACK_ERROR" },
+	{ 0x03, "RET_EMPTY_STACK_ERROR" },
+	{ 0x04, "PC_WRAP" },
 	{ 0x05, "MISALIGNED_PC" },
-	{ 0x08, "MISALIGNED_GPR" },
-	{ 0x09, "INVALID_OPCODE" },
-	{ 0x0d, "GPR_OUT_OF_BOUNDS" },
-	{ 0x0e, "MEM_OUT_OF_BOUNDS" },
-	{ 0x0f, "UNALIGNED_MEM_ACCESS" },
+	{ 0x06, "PC_OVERFLOW" },
+	{ 0x07, "MISALIGNED_IMMC_ADDR" },
+	{ 0x08, "MISALIGNED_REG" },
+	{ 0x09, "ILLEGAL_INSTR_ENCODING" },
+	{ 0x0a, "ILLEGAL_SPH_INSTR_COMBO" },
+	{ 0x0b, "ILLEGAL_INSTR_PARAM" },
+	{ 0x0c, "INVALID_CONST_ADDR" },
+	{ 0x0d, "OOR_REG" },
+	{ 0x0e, "OOR_ADDR" },
+	{ 0x0f, "MISALIGNED_ADDR" },
 	{ 0x10, "INVALID_ADDR_SPACE" },
-	{ 0x11, "INVALID_PARAM" },
+	{ 0x11, "ILLEGAL_INSTR_PARAM2" },
+	{ 0x12, "INVALID_CONST_ADDR_LDC" },
+	{ 0x13, "GEOMETRY_SM_ERROR" },
+	{ 0x14, "DIVERGENT" },
+	{ 0x15, "WARP_EXIT" },
 	{}
 };
 
 static const struct nvkm_bitfield gf100_mp_global_error[] = {
+	{ 0x00000001, "SM_TO_SM_FAULT" },
+	{ 0x00000002, "L1_ERROR" },
 	{ 0x00000004, "MULTIPLE_WARP_ERRORS" },
-	{ 0x00000008, "OUT_OF_STACK_SPACE" },
+	{ 0x00000008, "PHYSICAL_STACK_OVERFLOW" },
+	{ 0x00000010, "BPT_INT" },
+	{ 0x00000020, "BPT_PAUSE" },
+	{ 0x00000040, "SINGLE_STEP_COMPLETE" },
+	{ 0x20000000, "ECC_SEC_ERROR" },
+	{ 0x40000000, "ECC_DED_ERROR" },
+	{ 0x80000000, "TIMEOUT" },
 	{}
 };
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
index 69de8c6..f1e15a4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
@@ -76,8 +76,8 @@
 		nvkm_wo32(chan->inst, i, 0x00040004);
 	for (i = 0x1f18; i <= 0x3088 ; i += 16) {
 		nvkm_wo32(chan->inst, i + 0, 0x10700ff9);
-		nvkm_wo32(chan->inst, i + 1, 0x0436086c);
-		nvkm_wo32(chan->inst, i + 2, 0x000c001b);
+		nvkm_wo32(chan->inst, i + 4, 0x0436086c);
+		nvkm_wo32(chan->inst, i + 8, 0x000c001b);
 	}
 	for (i = 0x30b8; i < 0x30c8; i += 4)
 		nvkm_wo32(chan->inst, i, 0x0000ffff);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
index 2207dac2..300f5ed 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
@@ -75,8 +75,8 @@
 		nvkm_wo32(chan->inst, i, 0x00040004);
 	for (i = 0x15ac; i <= 0x271c ; i += 16) {
 		nvkm_wo32(chan->inst, i + 0, 0x10700ff9);
-		nvkm_wo32(chan->inst, i + 1, 0x0436086c);
-		nvkm_wo32(chan->inst, i + 2, 0x000c001b);
+		nvkm_wo32(chan->inst, i + 4, 0x0436086c);
+		nvkm_wo32(chan->inst, i + 8, 0x000c001b);
 	}
 	for (i = 0x274c; i < 0x275c; i += 4)
 		nvkm_wo32(chan->inst, i, 0x0000ffff);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
index d4d8942..e55f830 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
@@ -198,7 +198,7 @@
 		}
 
 		if (type == 0x00000010) {
-			if (!nv31_mpeg_mthd(mpeg, mthd, data))
+			if (nv31_mpeg_mthd(mpeg, mthd, data))
 				show &= ~0x01000000;
 		}
 	}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
index d433cfa..36af0a8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
@@ -172,7 +172,7 @@
 		}
 
 		if (type == 0x00000010) {
-			if (!nv44_mpeg_mthd(subdev->device, mthd, data))
+			if (nv44_mpeg_mthd(subdev->device, mthd, data))
 				show &= ~0x01000000;
 		}
 	}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c
index 4bef72a..3fda594 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c
@@ -59,9 +59,11 @@
 nv40_perfctr_next(struct nvkm_pm *pm, struct nvkm_perfdom *dom)
 {
 	struct nvkm_device *device = pm->engine.subdev.device;
-	if (pm->sequence != pm->sequence) {
+	struct nv40_pm *nv40pm = container_of(pm, struct nv40_pm, base);
+
+	if (nv40pm->sequence != pm->sequence) {
 		nvkm_wr32(device, 0x400084, 0x00000020);
-		pm->sequence = pm->sequence;
+		nv40pm->sequence = pm->sequence;
 	}
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
index 212800e..7d1d3c6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
@@ -12,6 +12,7 @@
 	bool rw;
 	bool ignore_checksum;
 	bool no_pcir;
+	bool require_checksum;
 };
 
 int nvbios_extend(struct nvkm_bios *, u32 length);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
index b2557e8..7deb81b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
@@ -86,9 +86,12 @@
 		    nvbios_checksum(&bios->data[image.base], image.size)) {
 			nvkm_debug(subdev, "%08x: checksum failed\n",
 				   image.base);
-			if (mthd->func->rw)
+			if (!mthd->func->require_checksum) {
+				if (mthd->func->rw)
+					score += 1;
 				score += 1;
-			score += 1;
+			} else
+				return 0;
 		} else {
 			score += 3;
 		}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c
index 8fecb5f..06572f8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c
@@ -99,6 +99,7 @@
 	.init = acpi_init,
 	.read = acpi_read_fast,
 	.rw = false,
+	.require_checksum = true,
 };
 
 const struct nvbios_source
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
index 85b1464..587c52f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
@@ -47,8 +47,10 @@
 
 	BUG_ON((first > limit) || (limit >= ltc->num_tags));
 
+	mutex_lock(&ltc->subdev.mutex);
 	ltc->func->cbc_clear(ltc, first, limit);
 	ltc->func->cbc_wait(ltc);
+	mutex_unlock(&ltc->subdev.mutex);
 }
 
 int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
index 949dc61..7c0b586 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
@@ -130,7 +130,7 @@
 		poll = false;
 	}
 
-	if (list_empty(&therm->alarm.head) && poll)
+	if (poll)
 		nvkm_timer_alarm(tmr, 1000000000ULL, &therm->alarm);
 	spin_unlock_irqrestore(&therm->lock, flags);
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c
index 91198d7..e2fecce 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c
@@ -83,7 +83,7 @@
 	spin_unlock_irqrestore(&fan->lock, flags);
 
 	/* schedule next fan update, if not at target speed already */
-	if (list_empty(&fan->alarm.head) && target != duty) {
+	if (target != duty) {
 		u16 bump_period = fan->bios.bump_period;
 		u16 slow_down_period = fan->bios.slow_down_period;
 		u64 delay;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
index 59701b7..ff9fbe7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
@@ -53,7 +53,7 @@
 	duty = !nvkm_gpio_get(gpio, 0, DCB_GPIO_FAN, 0xff);
 	nvkm_gpio_set(gpio, 0, DCB_GPIO_FAN, 0xff, duty);
 
-	if (list_empty(&fan->alarm.head) && percent != (duty * 100)) {
+	if (percent != (duty * 100)) {
 		u64 next_change = (percent * fan->period_us) / 100;
 		if (!duty)
 			next_change = fan->period_us - next_change;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c
index b9703c0..9a79e91 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c
@@ -185,7 +185,7 @@
 	spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags);
 
 	/* schedule the next poll in one second */
-	if (therm->func->temp_get(therm) >= 0 && list_empty(&alarm->head))
+	if (therm->func->temp_get(therm) >= 0)
 		nvkm_timer_alarm(tmr, 1000000000ULL, alarm);
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
index d4dae1f..4603390 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
@@ -36,25 +36,32 @@
 	unsigned long flags;
 	LIST_HEAD(exec);
 
-	/* move any due alarms off the pending list */
+	/* Process pending alarms. */
 	spin_lock_irqsave(&tmr->lock, flags);
 	list_for_each_entry_safe(alarm, atemp, &tmr->alarms, head) {
-		if (alarm->timestamp <= nvkm_timer_read(tmr))
-			list_move_tail(&alarm->head, &exec);
+		/* Have we hit the earliest alarm that hasn't gone off? */
+		if (alarm->timestamp > nvkm_timer_read(tmr)) {
+			/* Schedule it.  If we didn't race, we're done. */
+			tmr->func->alarm_init(tmr, alarm->timestamp);
+			if (alarm->timestamp > nvkm_timer_read(tmr))
+				break;
+		}
+
+		/* Move to completed list.  We'll drop the lock before
+		 * executing the callback so it can reschedule itself.
+		 */
+		list_del_init(&alarm->head);
+		list_add(&alarm->exec, &exec);
 	}
 
-	/* reschedule interrupt for next alarm time */
-	if (!list_empty(&tmr->alarms)) {
-		alarm = list_first_entry(&tmr->alarms, typeof(*alarm), head);
-		tmr->func->alarm_init(tmr, alarm->timestamp);
-	} else {
+	/* Shut down interrupt if no more pending alarms. */
+	if (list_empty(&tmr->alarms))
 		tmr->func->alarm_fini(tmr);
-	}
 	spin_unlock_irqrestore(&tmr->lock, flags);
 
-	/* execute any pending alarm handlers */
-	list_for_each_entry_safe(alarm, atemp, &exec, head) {
-		list_del_init(&alarm->head);
+	/* Execute completed callbacks. */
+	list_for_each_entry_safe(alarm, atemp, &exec, exec) {
+		list_del(&alarm->exec);
 		alarm->func(alarm);
 	}
 }
@@ -65,24 +72,37 @@
 	struct nvkm_alarm *list;
 	unsigned long flags;
 
-	alarm->timestamp = nvkm_timer_read(tmr) + nsec;
-
-	/* append new alarm to list, in soonest-alarm-first order */
+	/* Remove alarm from pending list.
+	 *
+	 * This both protects against the corruption of the list,
+	 * and implements alarm rescheduling/cancellation.
+	 */
 	spin_lock_irqsave(&tmr->lock, flags);
-	if (!nsec) {
-		if (!list_empty(&alarm->head))
-			list_del(&alarm->head);
-	} else {
+	list_del_init(&alarm->head);
+
+	if (nsec) {
+		/* Insert into pending list, ordered earliest to latest. */
+		alarm->timestamp = nvkm_timer_read(tmr) + nsec;
 		list_for_each_entry(list, &tmr->alarms, head) {
 			if (list->timestamp > alarm->timestamp)
 				break;
 		}
+
 		list_add_tail(&alarm->head, &list->head);
+
+		/* Update HW if this is now the earliest alarm. */
+		list = list_first_entry(&tmr->alarms, typeof(*list), head);
+		if (list == alarm) {
+			tmr->func->alarm_init(tmr, alarm->timestamp);
+			/* This shouldn't happen if callers aren't stupid.
+			 *
+			 * Worst case scenario is that it'll take roughly
+			 * 4 seconds for the next alarm to trigger.
+			 */
+			WARN_ON(alarm->timestamp <= nvkm_timer_read(tmr));
+		}
 	}
 	spin_unlock_irqrestore(&tmr->lock, flags);
-
-	/* process pending alarms */
-	nvkm_timer_alarm_trigger(tmr);
 }
 
 void
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c
index 7b9ce87..7f48249 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c
@@ -76,8 +76,8 @@
 	u32 stat = nvkm_rd32(device, NV04_PTIMER_INTR_0);
 
 	if (stat & 0x00000001) {
-		nvkm_timer_alarm_trigger(tmr);
 		nvkm_wr32(device, NV04_PTIMER_INTR_0, 0x00000001);
+		nvkm_timer_alarm_trigger(tmr);
 		stat &= ~0x00000001;
 	}
 
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 0c104ad..7d9b32a 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -178,7 +178,7 @@
 	encoder = &omap_encoder->base;
 
 	drm_encoder_init(dev, encoder, &omap_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);
 
 	return encoder;
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index f92c46e..5edebf4 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -985,7 +985,7 @@
 			   &qxl_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
 
 	drm_encoder_init(dev, &qxl_output->enc, &qxl_enc_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
+			 DRM_MODE_ENCODER_VIRTUAL);
 
 	/* we get HPD via client monitors config */
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c
index 56e1d63..6e6c760 100644
--- a/drivers/gpu/drm/qxl/qxl_draw.c
+++ b/drivers/gpu/drm/qxl/qxl_draw.c
@@ -136,6 +136,8 @@
 				 * correctly globaly, since that would require
 				 * tracking all of our palettes. */
 	ret = qxl_bo_kmap(palette_bo, (void **)&pal);
+	if (ret)
+		return ret;
 	pal->num_ents = 2;
 	pal->unique = unique++;
 	if (visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR) {
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index dac78ad..6755d47 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -275,6 +275,8 @@
 			atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);
 		atombios_blank_crtc(crtc, ATOM_DISABLE);
 		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
+		/* Make sure vblank interrupt is still enabled if needed */
+		radeon_irq_set(rdev);
 		radeon_crtc_load_lut(crtc);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
@@ -1739,6 +1741,7 @@
 static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
 	struct drm_crtc *test_crtc;
 	struct radeon_crtc *test_radeon_crtc;
 
@@ -1748,6 +1751,10 @@
 		test_radeon_crtc = to_radeon_crtc(test_crtc);
 		if (test_radeon_crtc->encoder &&
 		    ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) {
+			/* PPLL2 is exclusive to UNIPHYA on DCE61 */
+			if (ASIC_IS_DCE61(rdev) && !ASIC_IS_DCE8(rdev) &&
+			    test_radeon_crtc->pll_id == ATOM_PPLL2)
+				continue;
 			/* for DP use the same PLL for all */
 			if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)
 				return test_radeon_crtc->pll_id;
@@ -1769,6 +1776,7 @@
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
 	struct drm_crtc *test_crtc;
 	struct radeon_crtc *test_radeon_crtc;
 	u32 adjusted_clock, test_adjusted_clock;
@@ -1784,6 +1792,10 @@
 		test_radeon_crtc = to_radeon_crtc(test_crtc);
 		if (test_radeon_crtc->encoder &&
 		    !ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) {
+			/* PPLL2 is exclusive to UNIPHYA on DCE61 */
+			if (ASIC_IS_DCE61(rdev) && !ASIC_IS_DCE8(rdev) &&
+			    test_radeon_crtc->pll_id == ATOM_PPLL2)
+				continue;
 			/* check if we are already driving this connector with another crtc */
 			if (test_radeon_crtc->connector == radeon_crtc->connector) {
 				/* if we are, return that pll */
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index bd73b40..b576085 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -302,77 +302,43 @@
 		return bpc * 3;
 }
 
-/* get the max pix clock supported by the link rate and lane num */
-static int dp_get_max_dp_pix_clock(int link_rate,
-				   int lane_num,
-				   int bpp)
-{
-	return (link_rate * lane_num * 8) / bpp;
-}
-
 /***** radeon specific DP functions *****/
 
-int radeon_dp_get_max_link_rate(struct drm_connector *connector,
-				const u8 dpcd[DP_DPCD_SIZE])
-{
-	int max_link_rate;
-
-	if (radeon_connector_is_dp12_capable(connector))
-		max_link_rate = min(drm_dp_max_link_rate(dpcd), 540000);
-	else
-		max_link_rate = min(drm_dp_max_link_rate(dpcd), 270000);
-
-	return max_link_rate;
-}
-
-/* First get the min lane# when low rate is used according to pixel clock
- * (prefer low rate), second check max lane# supported by DP panel,
- * if the max lane# < low rate lane# then use max lane# instead.
- */
-static int radeon_dp_get_dp_lane_number(struct drm_connector *connector,
-					const u8 dpcd[DP_DPCD_SIZE],
-					int pix_clock)
+int radeon_dp_get_dp_link_config(struct drm_connector *connector,
+				 const u8 dpcd[DP_DPCD_SIZE],
+				 unsigned pix_clock,
+				 unsigned *dp_lanes, unsigned *dp_rate)
 {
 	int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
-	int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd);
-	int max_lane_num = drm_dp_max_lane_count(dpcd);
-	int lane_num;
-	int max_dp_pix_clock;
-
-	for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) {
-		max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp);
-		if (pix_clock <= max_dp_pix_clock)
-			break;
-	}
-
-	return lane_num;
-}
-
-static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
-				       const u8 dpcd[DP_DPCD_SIZE],
-				       int pix_clock)
-{
-	int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
-	int lane_num, max_pix_clock;
+	static const unsigned link_rates[3] = { 162000, 270000, 540000 };
+	unsigned max_link_rate = drm_dp_max_link_rate(dpcd);
+	unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
+	unsigned lane_num, i, max_pix_clock;
 
 	if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
-	    ENCODER_OBJECT_ID_NUTMEG)
-		return 270000;
-
-	lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock);
-	max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp);
-	if (pix_clock <= max_pix_clock)
-		return 162000;
-	max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp);
-	if (pix_clock <= max_pix_clock)
-		return 270000;
-	if (radeon_connector_is_dp12_capable(connector)) {
-		max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp);
-		if (pix_clock <= max_pix_clock)
-			return 540000;
+	    ENCODER_OBJECT_ID_NUTMEG) {
+		for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+			max_pix_clock = (lane_num * 270000 * 8) / bpp;
+			if (max_pix_clock >= pix_clock) {
+				*dp_lanes = lane_num;
+				*dp_rate = 270000;
+				return 0;
+			}
+		}
+	} else {
+		for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
+			for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+				max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
+				if (max_pix_clock >= pix_clock) {
+					*dp_lanes = lane_num;
+					*dp_rate = link_rates[i];
+					return 0;
+				}
+			}
+		}
 	}
 
-	return radeon_dp_get_max_link_rate(connector, dpcd);
+	return -EINVAL;
 }
 
 static u8 radeon_dp_encoder_service(struct radeon_device *rdev,
@@ -491,6 +457,7 @@
 {
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct radeon_connector_atom_dig *dig_connector;
+	int ret;
 
 	if (!radeon_connector->con_priv)
 		return;
@@ -498,10 +465,14 @@
 
 	if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
 	    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
-		dig_connector->dp_clock =
-			radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
-		dig_connector->dp_lane_count =
-			radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock);
+		ret = radeon_dp_get_dp_link_config(connector, dig_connector->dpcd,
+						   mode->clock,
+						   &dig_connector->dp_lane_count,
+						   &dig_connector->dp_clock);
+		if (ret) {
+			dig_connector->dp_clock = 0;
+			dig_connector->dp_lane_count = 0;
+		}
 	}
 }
 
@@ -510,7 +481,8 @@
 {
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct radeon_connector_atom_dig *dig_connector;
-	int dp_clock;
+	unsigned dp_clock, dp_lanes;
+	int ret;
 
 	if ((mode->clock > 340000) &&
 	    (!radeon_connector_is_dp12_capable(connector)))
@@ -520,8 +492,12 @@
 		return MODE_CLOCK_HIGH;
 	dig_connector = radeon_connector->con_priv;
 
-	dp_clock =
-		radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
+	ret = radeon_dp_get_dp_link_config(connector, dig_connector->dpcd,
+					   mode->clock,
+					   &dp_lanes,
+					   &dp_clock);
+	if (ret)
+		return MODE_CLOCK_HIGH;
 
 	if ((dp_clock == 540000) &&
 	    (!radeon_connector_is_dp12_capable(connector)))
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 9de6503..d4ac8c8 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -120,6 +120,7 @@
 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
 			if (dig->backlight_level == 0)
 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
 			else {
@@ -2773,27 +2774,23 @@
 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 			radeon_encoder->rmx_type = RMX_FULL;
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-					 DRM_MODE_ENCODER_LVDS, NULL);
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
 		} else {
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-					 DRM_MODE_ENCODER_TMDS, NULL);
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
 		}
 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-				 DRM_MODE_ENCODER_DAC, NULL);
+		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-				 DRM_MODE_ENCODER_TVDAC, NULL);
+		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
 		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
 		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
 		break;
@@ -2807,16 +2804,13 @@
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 			radeon_encoder->rmx_type = RMX_FULL;
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-					 DRM_MODE_ENCODER_LVDS, NULL);
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
 		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-					 DRM_MODE_ENCODER_DAC, NULL);
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
 		} else {
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-					 DRM_MODE_ENCODER_TMDS, NULL);
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
 			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
 		}
 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
@@ -2833,14 +2827,11 @@
 		/* these are handled by the primary encoders */
 		radeon_encoder->is_ext_encoder = true;
 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-					 DRM_MODE_ENCODER_LVDS, NULL);
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
 		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-					 DRM_MODE_ENCODER_DAC, NULL);
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
 		else
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs,
-					 DRM_MODE_ENCODER_TMDS, NULL);
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
 		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
 		break;
 	}
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index 4a09947..3c32f09 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -776,6 +776,12 @@
 	u32 vblank_time = r600_dpm_get_vblank_time(rdev);
 	u32 switch_limit = pi->mem_gddr5 ? 450 : 300;
 
+	/* disable mclk switching if the refresh is >120Hz, even if the
+        * blanking period would allow it
+        */
+	if (r600_dpm_get_vrefresh(rdev) > 120)
+		return true;
+
 	if (vblank_time < switch_limit)
 		return true;
 	else
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index f81fb26..134874c 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -7762,7 +7762,7 @@
 		WREG32(DC_HPD5_INT_CONTROL, tmp);
 	}
 	if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp = RREG32(DC_HPD6_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
@@ -7792,7 +7792,7 @@
 		WREG32(DC_HPD5_INT_CONTROL, tmp);
 	}
 	if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp = RREG32(DC_HPD6_INT_CONTROL);
 		tmp |= DC_HPDx_RX_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 3249135..ba9e6ed 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4924,7 +4924,7 @@
 		WREG32(DC_HPD5_INT_CONTROL, tmp);
 	}
 	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp = RREG32(DC_HPD6_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
@@ -4955,7 +4955,7 @@
 		WREG32(DC_HPD5_INT_CONTROL, tmp);
 	}
 	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp = RREG32(DC_HPD6_INT_CONTROL);
 		tmp |= DC_HPDx_RX_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 158872e..a3a3212 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1396,9 +1396,7 @@
 void cayman_cp_int_cntl_setup(struct radeon_device *rdev,
 			      int ring, u32 cp_int_cntl)
 {
-	u32 srbm_gfx_cntl = RREG32(SRBM_GFX_CNTL) & ~3;
-
-	WREG32(SRBM_GFX_CNTL, srbm_gfx_cntl | (ring & 3));
+	WREG32(SRBM_GFX_CNTL, RINGID(ring));
 	WREG32(CP_INT_CNTL, cp_int_cntl);
 }
 
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index cc2fdf0..0e20c08 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -3945,7 +3945,7 @@
 			WREG32(DC_HPD5_INT_CONTROL, tmp);
 		}
 		if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) {
-			tmp = RREG32(DC_HPD5_INT_CONTROL);
+			tmp = RREG32(DC_HPD6_INT_CONTROL);
 			tmp |= DC_HPDx_INT_ACK;
 			WREG32(DC_HPD6_INT_CONTROL, tmp);
 		}
diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c
index fa21544..470af4a 100644
--- a/drivers/gpu/drm/radeon/r600_dpm.c
+++ b/drivers/gpu/drm/radeon/r600_dpm.c
@@ -156,19 +156,20 @@
 	struct drm_device *dev = rdev->ddev;
 	struct drm_crtc *crtc;
 	struct radeon_crtc *radeon_crtc;
-	u32 line_time_us, vblank_lines;
+	u32 vblank_in_pixels;
 	u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
 
 	if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
 		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 			radeon_crtc = to_radeon_crtc(crtc);
 			if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
-				line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
-					radeon_crtc->hw_mode.clock;
-				vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
-					radeon_crtc->hw_mode.crtc_vdisplay +
-					(radeon_crtc->v_border * 2);
-				vblank_time_us = vblank_lines * line_time_us;
+				vblank_in_pixels =
+					radeon_crtc->hw_mode.crtc_htotal *
+					(radeon_crtc->hw_mode.crtc_vblank_end -
+					 radeon_crtc->hw_mode.crtc_vdisplay +
+					 (radeon_crtc->v_border * 2));
+
+				vblank_time_us = vblank_in_pixels * 1000 / radeon_crtc->hw_mode.clock;
 				break;
 			}
 		}
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index de9a2ff..0c5b3ee 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1155,7 +1155,7 @@
 		    le16_to_cpu(firmware_info->info.usReferenceClock);
 		p1pll->reference_div = 0;
 
-		if (crev < 2)
+		if ((frev < 2) && (crev < 2))
 			p1pll->pll_out_min =
 				le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
 		else
@@ -1164,7 +1164,7 @@
 		p1pll->pll_out_max =
 		    le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
 
-		if (crev >= 4) {
+		if (((frev < 2) && (crev >= 4)) || (frev >= 2)) {
 			p1pll->lcd_pll_out_min =
 				le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
 			if (p1pll->lcd_pll_out_min == 0)
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index c4b4f29..69ce955 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 
 #include "radeon_acpi.h"
 
@@ -255,6 +256,10 @@
 		if (!info)
 			return -EIO;
 		kfree(info);
+
+		/* 200ms delay is required after off */
+		if (state == 0)
+			msleep(200);
 	}
 	return 0;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index a9b01bc..fcecaf5 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -3394,6 +3394,13 @@
 	    rdev->pdev->subsystem_vendor == 0x103c &&
 	    rdev->pdev->subsystem_device == 0x280a)
 		return;
+	/* quirk for rs4xx Toshiba Sattellite L20-183 latop to make it resume
+	 * - it hangs on resume inside the dynclk 1 table.
+	 */
+	if (rdev->family == CHIP_RS400 &&
+	    rdev->pdev->subsystem_vendor == 0x1179 &&
+	    rdev->pdev->subsystem_device == 0xff31)
+	        return;
 
 	/* DYN CLK 1 */
 	table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 9cfc1c3..30f0074 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -2058,7 +2058,6 @@
 							   RADEON_OUTPUT_CSC_BYPASS);
 			/* no HPD on analog connectors */
 			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
-			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 			connector->interlace_allowed = true;
 			connector->doublescan_allowed = true;
 			break;
@@ -2308,8 +2307,10 @@
 	}
 
 	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
-		if (i2c_bus->valid)
-			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+		if (i2c_bus->valid) {
+			connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+			                    DRM_CONNECTOR_POLL_DISCONNECT;
+		}
 	} else
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 
@@ -2385,7 +2386,6 @@
 					      1);
 		/* no HPD on analog connectors */
 		radeon_connector->hpd.hpd = RADEON_HPD_NONE;
-		connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 		connector->interlace_allowed = true;
 		connector->doublescan_allowed = true;
 		break;
@@ -2470,10 +2470,13 @@
 	}
 
 	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
-		if (i2c_bus->valid)
-			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+		if (i2c_bus->valid) {
+			connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+			                    DRM_CONNECTOR_POLL_DISCONNECT;
+		}
 	} else
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
+
 	connector->display_info.subpixel_order = subpixel_order;
 	drm_connector_register(connector);
 }
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index afaf346..8901228 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -90,6 +90,9 @@
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct radeon_device *rdev = crtc->dev->dev_private;
 
+	if (radeon_crtc->cursor_out_of_bounds)
+		return;
+
 	if (ASIC_IS_DCE4(rdev)) {
 		WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
 		       upper_32_bits(radeon_crtc->cursor_addr));
@@ -143,21 +146,25 @@
 	int xorigin = 0, yorigin = 0;
 	int w = radeon_crtc->cursor_width;
 
+	radeon_crtc->cursor_x = x;
+	radeon_crtc->cursor_y = y;
+
 	if (ASIC_IS_AVIVO(rdev)) {
 		/* avivo cursor are offset into the total surface */
 		x += crtc->x;
 		y += crtc->y;
 	}
-	DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
 
-	if (x < 0) {
+	if (x < 0)
 		xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
-		x = 0;
-	}
-	if (y < 0) {
+	if (y < 0)
 		yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
-		y = 0;
+
+	if (!ASIC_IS_AVIVO(rdev)) {
+		x += crtc->x;
+		y += crtc->y;
 	}
+	DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
 
 	/* fixed on DCE6 and newer */
 	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
@@ -180,27 +187,31 @@
 		if (i > 1) {
 			int cursor_end, frame_end;
 
-			cursor_end = x - xorigin + w;
+			cursor_end = x + w;
 			frame_end = crtc->x + crtc->mode.crtc_hdisplay;
 			if (cursor_end >= frame_end) {
 				w = w - (cursor_end - frame_end);
 				if (!(frame_end & 0x7f))
 					w--;
-			} else {
-				if (!(cursor_end & 0x7f))
-					w--;
+			} else if (cursor_end <= 0) {
+				goto out_of_bounds;
+			} else if (!(cursor_end & 0x7f)) {
+				w--;
 			}
 			if (w <= 0) {
-				w = 1;
-				cursor_end = x - xorigin + w;
-				if (!(cursor_end & 0x7f)) {
-					x--;
-					WARN_ON_ONCE(x < 0);
-				}
+				goto out_of_bounds;
 			}
 		}
 	}
 
+	if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) ||
+	    x >= (crtc->x + crtc->mode.hdisplay) ||
+	    y >= (crtc->y + crtc->mode.vdisplay))
+		goto out_of_bounds;
+
+	x += xorigin;
+	y += yorigin;
+
 	if (ASIC_IS_DCE4(rdev)) {
 		WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
 		WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
@@ -212,6 +223,9 @@
 		WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
 		       ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
 	} else {
+		x -= crtc->x;
+		y -= crtc->y;
+
 		if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
 			y *= 2;
 
@@ -229,10 +243,20 @@
 		       yorigin * 256);
 	}
 
-	radeon_crtc->cursor_x = x;
-	radeon_crtc->cursor_y = y;
+	if (radeon_crtc->cursor_out_of_bounds) {
+		radeon_crtc->cursor_out_of_bounds = false;
+		if (radeon_crtc->cursor_bo)
+			radeon_show_cursor(crtc);
+	}
 
 	return 0;
+
+ out_of_bounds:
+	if (!radeon_crtc->cursor_out_of_bounds) {
+		radeon_hide_cursor(crtc);
+		radeon_crtc->cursor_out_of_bounds = true;
+	}
+	return 0;
 }
 
 int radeon_crtc_cursor_move(struct drm_crtc *crtc,
@@ -297,22 +321,23 @@
 		return ret;
 	}
 
-	radeon_crtc->cursor_width = width;
-	radeon_crtc->cursor_height = height;
-
 	radeon_lock_cursor(crtc, true);
 
-	if (hot_x != radeon_crtc->cursor_hot_x ||
+	if (width != radeon_crtc->cursor_width ||
+	    height != radeon_crtc->cursor_height ||
+	    hot_x != radeon_crtc->cursor_hot_x ||
 	    hot_y != radeon_crtc->cursor_hot_y) {
 		int x, y;
 
 		x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x;
 		y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y;
 
-		radeon_cursor_move_locked(crtc, x, y);
-
+		radeon_crtc->cursor_width = width;
+		radeon_crtc->cursor_height = height;
 		radeon_crtc->cursor_hot_x = hot_x;
 		radeon_crtc->cursor_hot_y = hot_y;
+
+		radeon_cursor_move_locked(crtc, x, y);
 	}
 
 	radeon_show_cursor(crtc);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index c566993..a775216 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -127,6 +127,10 @@
 	 * https://bugzilla.kernel.org/show_bug.cgi?id=51381
 	 */
 	{ PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
+	/* Asus K53TK laptop with AMD A6-3420M APU and Radeon 7670m GPU
+	 * https://bugs.freedesktop.org/show_bug.cgi?id=101491
+	 */
+	{ PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
 	/* macbook pro 8.2 */
 	{ PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
 	{ 0, 0, 0, 0, 0 },
@@ -630,6 +634,23 @@
 /*
  * GPU helpers function.
  */
+
+/**
+ * radeon_device_is_virtual - check if we are running is a virtual environment
+ *
+ * Check if the asic has been passed through to a VM (all asics).
+ * Used at driver startup.
+ * Returns true if virtual or false if not.
+ */
+static bool radeon_device_is_virtual(void)
+{
+#ifdef CONFIG_X86
+	return boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#else
+	return false;
+#endif
+}
+
 /**
  * radeon_card_posted - check if the hw has already been initialized
  *
@@ -643,6 +664,11 @@
 {
 	uint32_t reg;
 
+	/* for pass through, always force asic_init for CI */
+	if (rdev->family >= CHIP_BONAIRE &&
+	    radeon_device_is_virtual())
+		return false;
+
 	/* required for EFI mode on macbook2,1 which uses an r5xx asic */
 	if (efi_enabled(EFI_BOOT) &&
 	    (rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index 94323f5..6dd39bd 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -525,11 +525,9 @@
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 	{
 	  struct radeon_connector_atom_dig *dig_connector;
-
 	  dig_connector = mst_enc->connector->con_priv;
 	  dig_connector->dp_lane_count = drm_dp_max_lane_count(dig_connector->dpcd);
-	  dig_connector->dp_clock = radeon_dp_get_max_link_rate(&mst_enc->connector->base,
-								dig_connector->dpcd);
+	  dig_connector->dp_clock = drm_dp_max_link_rate(dig_connector->dpcd);
 	  DRM_DEBUG_KMS("dig clock %p %d %d\n", dig_connector,
 			dig_connector->dp_lane_count, dig_connector->dp_clock);
 	}
@@ -641,7 +639,7 @@
 	}
 
 	drm_encoder_init(dev, &radeon_encoder->base, &radeon_dp_mst_enc_funcs,
-			 DRM_MODE_ENCODER_DPMST, NULL);
+			 DRM_MODE_ENCODER_DPMST);
 	drm_encoder_helper_add(encoder, &radeon_mst_helper_funcs);
 
 	mst_enc = radeon_encoder->enc_priv;
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 678b438..89f22bd 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -331,6 +331,8 @@
 			WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
 		}
 		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
+		/* Make sure vblank interrupt is still enabled if needed */
+		radeon_irq_set(rdev);
 		radeon_crtc_load_lut(crtc);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 88dc973..30de433 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -1772,8 +1772,7 @@
 	switch (radeon_encoder->encoder_id) {
 	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
 		encoder->possible_crtcs = 0x1;
-		drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs,
-				 DRM_MODE_ENCODER_LVDS, NULL);
+		drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS);
 		drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
 		if (rdev->is_atom_bios)
 			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
@@ -1782,14 +1781,12 @@
 		radeon_encoder->rmx_type = RMX_FULL;
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs,
-				 DRM_MODE_ENCODER_TMDS, NULL);
+		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS);
 		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);
 		radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-		drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs,
-				 DRM_MODE_ENCODER_DAC, NULL);
+		drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC);
 		drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs);
 		if (rdev->is_atom_bios)
 			radeon_encoder->enc_priv = radeon_atombios_get_primary_dac_info(radeon_encoder);
@@ -1797,8 +1794,7 @@
 			radeon_encoder->enc_priv = radeon_combios_get_primary_dac_info(radeon_encoder);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-		drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs,
-				 DRM_MODE_ENCODER_TVDAC, NULL);
+		drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs, DRM_MODE_ENCODER_TVDAC);
 		drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs);
 		if (rdev->is_atom_bios)
 			radeon_encoder->enc_priv = radeon_atombios_get_tv_dac_info(radeon_encoder);
@@ -1806,8 +1802,7 @@
 			radeon_encoder->enc_priv = radeon_combios_get_tv_dac_info(radeon_encoder);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs,
-				 DRM_MODE_ENCODER_TMDS, NULL);
+		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS);
 		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
 		if (!rdev->is_atom_bios)
 			radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index bba1126..d8f8be6 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -330,6 +330,7 @@
 	u16 lut_r[256], lut_g[256], lut_b[256];
 	bool enabled;
 	bool can_tile;
+	bool cursor_out_of_bounds;
 	uint32_t crtc_offset;
 	struct drm_gem_object *cursor_bo;
 	uint64_t cursor_addr;
@@ -757,8 +758,10 @@
 extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
 extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
 				    struct drm_connector *connector);
-int radeon_dp_get_max_link_rate(struct drm_connector *connector,
-				const u8 *dpcd);
+extern int radeon_dp_get_dp_link_config(struct drm_connector *connector,
+					const u8 *dpcd,
+					unsigned pix_clock,
+					unsigned *dp_lanes, unsigned *dp_rate);
 extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
 					 u8 power_state);
 extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index f342aad..d684e2b 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -213,8 +213,8 @@
 			rbo->placement.num_busy_placement = 0;
 			for (i = 0; i < rbo->placement.num_placement; i++) {
 				if (rbo->placements[i].flags & TTM_PL_FLAG_VRAM) {
-					if (rbo->placements[0].fpfn < fpfn)
-						rbo->placements[0].fpfn = fpfn;
+					if (rbo->placements[i].fpfn < fpfn)
+						rbo->placements[i].fpfn = fpfn;
 				} else {
 					rbo->placement.busy_placement =
 						&rbo->placements[i];
@@ -263,8 +263,8 @@
 
 	rdev = radeon_get_rdev(bo->bdev);
 	ridx = radeon_copy_ring_index(rdev);
-	old_start = old_mem->start << PAGE_SHIFT;
-	new_start = new_mem->start << PAGE_SHIFT;
+	old_start = (u64)old_mem->start << PAGE_SHIFT;
+	new_start = (u64)new_mem->start << PAGE_SHIFT;
 
 	switch (old_mem->mem_type) {
 	case TTM_PL_VRAM:
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index f878d69..5cf3a2c 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -6335,7 +6335,7 @@
 		WREG32(DC_HPD5_INT_CONTROL, tmp);
 	}
 	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp = RREG32(DC_HPD6_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
@@ -6366,7 +6366,7 @@
 		WREG32(DC_HPD5_INT_CONTROL, tmp);
 	}
 	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp = RREG32(DC_HPD6_INT_CONTROL);
 		tmp |= DC_HPDx_RX_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index caa73de..b6f1680 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -2999,6 +2999,37 @@
 	int i;
 	struct si_dpm_quirk *p = si_dpm_quirk_list;
 
+	/* limit all SI kickers */
+	if (rdev->family == CHIP_PITCAIRN) {
+		if ((rdev->pdev->revision == 0x81) ||
+		    (rdev->pdev->device == 0x6810) ||
+		    (rdev->pdev->device == 0x6811) ||
+		    (rdev->pdev->device == 0x6816) ||
+		    (rdev->pdev->device == 0x6817) ||
+		    (rdev->pdev->device == 0x6806))
+			max_mclk = 120000;
+	} else if (rdev->family == CHIP_OLAND) {
+		if ((rdev->pdev->revision == 0xC7) ||
+		    (rdev->pdev->revision == 0x80) ||
+		    (rdev->pdev->revision == 0x81) ||
+		    (rdev->pdev->revision == 0x83) ||
+		    (rdev->pdev->revision == 0x87) ||
+		    (rdev->pdev->device == 0x6604) ||
+		    (rdev->pdev->device == 0x6605)) {
+			max_sclk = 75000;
+			max_mclk = 80000;
+		}
+	} else if (rdev->family == CHIP_HAINAN) {
+		if ((rdev->pdev->revision == 0x81) ||
+		    (rdev->pdev->revision == 0x83) ||
+		    (rdev->pdev->revision == 0xC3) ||
+		    (rdev->pdev->device == 0x6664) ||
+		    (rdev->pdev->device == 0x6665) ||
+		    (rdev->pdev->device == 0x6667)) {
+			max_sclk = 75000;
+			max_mclk = 80000;
+		}
+	}
 	/* Apply dpm quirks */
 	while (p && p->chip_device != 0) {
 		if (rdev->pdev->vendor == p->chip_vendor &&
@@ -3011,10 +3042,6 @@
 		}
 		++p;
 	}
-	/* limit mclk on all R7 370 parts for stability */
-	if (rdev->pdev->device == 0x6811 &&
-	    rdev->pdev->revision == 0x81)
-		max_mclk = 120000;
 
 	if (rps->vce_active) {
 		rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
@@ -4106,7 +4133,7 @@
 							      &rdev->pm.dpm.dyn_state.phase_shedding_limits_table)) {
 				si_populate_smc_voltage_table(rdev, &si_pi->vddc_phase_shed_table, table);
 
-				table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
+				table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING] =
 					cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low);
 
 				si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_phase_shedding_delay,
diff --git a/drivers/gpu/drm/radeon/sislands_smc.h b/drivers/gpu/drm/radeon/sislands_smc.h
index 3c77983..966e3a5 100644
--- a/drivers/gpu/drm/radeon/sislands_smc.h
+++ b/drivers/gpu/drm/radeon/sislands_smc.h
@@ -194,6 +194,7 @@
 #define SISLANDS_SMC_VOLTAGEMASK_VDDC  0
 #define SISLANDS_SMC_VOLTAGEMASK_MVDD  1
 #define SISLANDS_SMC_VOLTAGEMASK_VDDCI 2
+#define SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING 3
 #define SISLANDS_SMC_VOLTAGEMASK_MAX   4
 
 struct SISLANDS_SMC_VOLTAGEMASKTABLE
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index c087007..d0ae1e8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -173,7 +173,7 @@
 			goto done;
 	} else {
 		ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
-				       encoder_type, NULL);
+				       encoder_type);
 		if (ret < 0)
 			goto done;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index 11267de..81da841 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -151,7 +151,7 @@
 		goto error;
 
 	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
-			       DRM_MODE_ENCODER_TMDS, NULL);
+			       DRM_MODE_ENCODER_TMDS);
 	if (ret < 0)
 		goto error;
 
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 053d00b..35215f6 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -25,11 +25,3 @@
 	  for the Synopsys DesignWare HDMI driver. If you want to
 	  enable HDMI on RK3288 based SoC, you should selet this
 	  option.
-
-config ROCKCHIP_INNO_HDMI
-	tristate "Rockchip specific extensions for Innosilicon HDMI"
-	depends on DRM_ROCKCHIP
-	help
-	  This selects support for Rockchip SoC specific extensions
-	  for the Innosilicon HDMI driver. If you want to enable
-	  HDMI on RK3036 based SoC, you should select this option.
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 9894d3a..f3d8a19 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -2,11 +2,9 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
-		rockchip_drm_gem.o rockchip_drm_vop.o
-rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
+rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o rockchip_drm_fbdev.o \
+		rockchip_drm_gem.o
 
 obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
-obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
 
-obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o
+obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index c65ce8c..80d6fc8 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -173,7 +173,7 @@
 	return (valid) ? MODE_OK : MODE_BAD;
 }
 
-static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
+static struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
 	.destroy = drm_encoder_cleanup,
 };
 
@@ -195,15 +195,12 @@
 {
 }
 
-static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
+static void dw_hdmi_rockchip_encoder_commit(struct drm_encoder *encoder)
 {
 	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
 	u32 val;
 	int mux;
 
-	rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
-				      ROCKCHIP_OUT_MODE_AAAA);
-
 	mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
 	if (mux)
 		val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
@@ -215,10 +212,17 @@
 		(mux) ? "LIT" : "BIG");
 }
 
-static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
+static void dw_hdmi_rockchip_encoder_prepare(struct drm_encoder *encoder)
+{
+	rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
+				      ROCKCHIP_OUT_MODE_AAAA);
+}
+
+static struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
 	.mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup,
 	.mode_set   = dw_hdmi_rockchip_encoder_mode_set,
-	.enable     = dw_hdmi_rockchip_encoder_enable,
+	.prepare    = dw_hdmi_rockchip_encoder_prepare,
+	.commit     = dw_hdmi_rockchip_encoder_commit,
 	.disable    = dw_hdmi_rockchip_encoder_disable,
 };
 
@@ -291,7 +295,7 @@
 
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 
 	return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
 }
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
deleted file mode 100644
index 10d62ff..0000000
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
- *    Zheng Yang <zhengyang@rock-chips.com>
- *    Yakir Yang <ykk@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/irq.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/hdmi.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of_device.h>
-
-#include <drm/drm_of.h>
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_edid.h>
-
-#include "rockchip_drm_drv.h"
-#include "rockchip_drm_vop.h"
-
-#include "inno_hdmi.h"
-
-#define to_inno_hdmi(x)	container_of(x, struct inno_hdmi, x)
-
-struct hdmi_data_info {
-	int vic;
-	bool sink_is_hdmi;
-	bool sink_has_audio;
-	unsigned int enc_in_format;
-	unsigned int enc_out_format;
-	unsigned int colorimetry;
-};
-
-struct inno_hdmi_i2c {
-	struct i2c_adapter adap;
-
-	u8 ddc_addr;
-	u8 segment_addr;
-
-	struct mutex lock;
-	struct completion cmp;
-};
-
-struct inno_hdmi {
-	struct device *dev;
-	struct drm_device *drm_dev;
-
-	int irq;
-	struct clk *pclk;
-	void __iomem *regs;
-
-	struct drm_connector	connector;
-	struct drm_encoder	encoder;
-
-	struct inno_hdmi_i2c *i2c;
-	struct i2c_adapter *ddc;
-
-	unsigned int tmds_rate;
-
-	struct hdmi_data_info	hdmi_data;
-	struct drm_display_mode previous_mode;
-};
-
-enum {
-	CSC_ITU601_16_235_TO_RGB_0_255_8BIT,
-	CSC_ITU601_0_255_TO_RGB_0_255_8BIT,
-	CSC_ITU709_16_235_TO_RGB_0_255_8BIT,
-	CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
-	CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
-	CSC_RGB_0_255_TO_RGB_16_235_8BIT,
-};
-
-static const char coeff_csc[][24] = {
-	/*
-	 * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]):
-	 *   R = 1.164*Y + 1.596*V - 204
-	 *   G = 1.164*Y - 0.391*U - 0.813*V + 154
-	 *   B = 1.164*Y + 2.018*U - 258
-	 */
-	{
-		0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
-		0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
-		0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02
-	},
-	/*
-	 * YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
-	 *   R = Y + 1.402*V - 248
-	 *   G = Y - 0.344*U - 0.714*V + 135
-	 *   B = Y + 1.772*U - 227
-	 */
-	{
-		0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
-		0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
-		0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3
-	},
-	/*
-	 * YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
-	 *   R = 1.164*Y + 1.793*V - 248
-	 *   G = 1.164*Y - 0.213*U - 0.534*V + 77
-	 *   B = 1.164*Y + 2.115*U - 289
-	 */
-	{
-		0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
-		0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
-		0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21
-	},
-
-	/*
-	 * RGB2YUV:601 SD mode:
-	 *   Cb = -0.291G - 0.148R + 0.439B + 128
-	 *   Y  = 0.504G  + 0.257R + 0.098B + 16
-	 *   Cr = -0.368G + 0.439R - 0.071B + 128
-	 */
-	{
-		0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
-		0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
-		0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
-	},
-	/*
-	 * RGB2YUV:709 HD mode:
-	 *   Cb = - 0.338G - 0.101R + 0.439B + 128
-	 *   Y  = 0.614G   + 0.183R + 0.062B + 16
-	 *   Cr = - 0.399G + 0.439R - 0.040B + 128
-	 */
-	{
-		0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
-		0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
-		0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
-	},
-	/*
-	 * RGB[0:255]2RGB[16:235]:
-	 *   R' = R x (235-16)/255 + 16;
-	 *   G' = G x (235-16)/255 + 16;
-	 *   B' = B x (235-16)/255 + 16;
-	 */
-	{
-		0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
-		0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-		0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10
-	},
-};
-
-static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
-{
-	return readl_relaxed(hdmi->regs + (offset) * 0x04);
-}
-
-static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
-{
-	writel_relaxed(val, hdmi->regs + (offset) * 0x04);
-}
-
-static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
-			     u32 msk, u32 val)
-{
-	u8 temp = hdmi_readb(hdmi, offset) & ~msk;
-
-	temp |= val & msk;
-	hdmi_writeb(hdmi, offset, temp);
-}
-
-static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
-{
-	int ddc_bus_freq;
-
-	ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
-
-	hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
-	hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
-
-	/* Clear the EDID interrupt flag and mute the interrupt */
-	hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
-	hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
-}
-
-static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
-{
-	if (enable)
-		hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
-	else
-		hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
-}
-
-static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
-{
-	switch (mode) {
-	case NORMAL:
-		inno_hdmi_sys_power(hdmi, false);
-
-		hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f);
-		hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb);
-
-		hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
-		hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
-		hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
-		hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
-		hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
-		hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
-
-		inno_hdmi_sys_power(hdmi, true);
-		break;
-
-	case LOWER_PWR:
-		inno_hdmi_sys_power(hdmi, false);
-		hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
-		hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
-		hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
-		hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
-
-		break;
-
-	default:
-		dev_err(hdmi->dev, "Unknown power mode %d\n", mode);
-	}
-}
-
-static void inno_hdmi_reset(struct inno_hdmi *hdmi)
-{
-	u32 val;
-	u32 msk;
-
-	hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
-	udelay(100);
-
-	hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
-	udelay(100);
-
-	msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
-	val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
-	hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
-
-	inno_hdmi_set_pwr_mode(hdmi, NORMAL);
-}
-
-static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc,
-				  union hdmi_infoframe *frame, u32 frame_index,
-				  u32 mask, u32 disable, u32 enable)
-{
-	if (mask)
-		hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable);
-
-	hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index);
-
-	if (setup_rc >= 0) {
-		u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
-		ssize_t rc, i;
-
-		rc = hdmi_infoframe_pack(frame, packed_frame,
-					 sizeof(packed_frame));
-		if (rc < 0)
-			return rc;
-
-		for (i = 0; i < rc; i++)
-			hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
-				    packed_frame[i]);
-
-		if (mask)
-			hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable);
-	}
-
-	return setup_rc;
-}
-
-static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
-				      struct drm_display_mode *mode)
-{
-	union hdmi_infoframe frame;
-	int rc;
-
-	rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
-							 mode);
-
-	return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,
-		m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1));
-}
-
-static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
-				      struct drm_display_mode *mode)
-{
-	union hdmi_infoframe frame;
-	int rc;
-
-	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
-
-	if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
-		frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
-	else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422)
-		frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
-	else
-		frame.avi.colorspace = HDMI_COLORSPACE_RGB;
-
-	return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0);
-}
-
-static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
-{
-	struct hdmi_data_info *data = &hdmi->hdmi_data;
-	int c0_c2_change = 0;
-	int csc_enable = 0;
-	int csc_mode = 0;
-	int auto_csc = 0;
-	int value;
-	int i;
-
-	/* Input video mode is SDR RGB24bit, data enable signal from external */
-	hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
-		    v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444));
-
-	/* Input color hardcode to RGB, and output color hardcode to RGB888 */
-	value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
-		v_VIDEO_OUTPUT_COLOR(0) |
-		v_VIDEO_INPUT_CSP(0);
-	hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
-
-	if (data->enc_in_format == data->enc_out_format) {
-		if ((data->enc_in_format == HDMI_COLORSPACE_RGB) ||
-		    (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) {
-			value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
-			hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
-
-			hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
-				  m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
-				  v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
-				  v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
-			return 0;
-		}
-	}
-
-	if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) {
-		if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
-		    (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
-			csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
-			auto_csc = AUTO_CSC_DISABLE;
-			c0_c2_change = C0_C2_CHANGE_DISABLE;
-			csc_enable = v_CSC_ENABLE;
-		} else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
-			   (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
-			csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
-			auto_csc = AUTO_CSC_ENABLE;
-			c0_c2_change = C0_C2_CHANGE_DISABLE;
-			csc_enable = v_CSC_DISABLE;
-		}
-	} else {
-		if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
-		    (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
-			csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
-			auto_csc = AUTO_CSC_DISABLE;
-			c0_c2_change = C0_C2_CHANGE_DISABLE;
-			csc_enable = v_CSC_ENABLE;
-		} else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
-			   (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
-			csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
-			auto_csc = AUTO_CSC_ENABLE;
-			c0_c2_change = C0_C2_CHANGE_DISABLE;
-			csc_enable = v_CSC_DISABLE;
-		}
-	}
-
-	for (i = 0; i < 24; i++)
-		hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
-			    coeff_csc[csc_mode][i]);
-
-	value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
-	hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
-	hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
-		  m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) |
-		  v_VIDEO_C0_C2_SWAP(c0_c2_change));
-
-	return 0;
-}
-
-static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
-					 struct drm_display_mode *mode)
-{
-	int value;
-
-	/* Set detail external video timing polarity and interlace mode */
-	value = v_EXTERANL_VIDEO(1);
-	value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
-		 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
-	value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
-		 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
-	value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
-		 v_INETLACE(1) : v_INETLACE(0);
-	hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
-
-	/* Set detail external video timing */
-	value = mode->htotal;
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
-
-	value = mode->htotal - mode->hdisplay;
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
-
-	value = mode->hsync_start - mode->hdisplay;
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
-
-	value = mode->hsync_end - mode->hsync_start;
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
-
-	value = mode->vtotal;
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
-
-	value = mode->vtotal - mode->vdisplay;
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
-
-	value = mode->vsync_start - mode->vdisplay;
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
-
-	value = mode->vsync_end - mode->vsync_start;
-	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
-
-	hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
-	hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
-	hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
-
-	return 0;
-}
-
-static int inno_hdmi_setup(struct inno_hdmi *hdmi,
-			   struct drm_display_mode *mode)
-{
-	hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
-
-	hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
-	hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
-
-	if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) ||
-	    (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) ||
-	    (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) ||
-	    (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18))
-		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
-	else
-		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
-
-	/* Mute video and audio output */
-	hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
-		  v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
-
-	/* Set HDMI Mode */
-	hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
-		    v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi));
-
-	inno_hdmi_config_video_timing(hdmi, mode);
-
-	inno_hdmi_config_video_csc(hdmi);
-
-	if (hdmi->hdmi_data.sink_is_hdmi) {
-		inno_hdmi_config_video_avi(hdmi, mode);
-		inno_hdmi_config_video_vsi(hdmi, mode);
-	}
-
-	/*
-	 * When IP controller have configured to an accurate video
-	 * timing, then the TMDS clock source would be switched to
-	 * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
-	 * clock rate, and reconfigure the DDC clock.
-	 */
-	hdmi->tmds_rate = mode->clock * 1000;
-	inno_hdmi_i2c_init(hdmi);
-
-	/* Unmute video and audio output */
-	hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
-		  v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
-
-	return 0;
-}
-
-static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
-				       struct drm_display_mode *mode,
-				       struct drm_display_mode *adj_mode)
-{
-	struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
-
-	inno_hdmi_setup(hdmi, adj_mode);
-
-	/* Store the display mode for plugin/DPMS poweron events */
-	memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
-}
-
-static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
-{
-	struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
-
-	rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
-				      ROCKCHIP_OUT_MODE_P888);
-
-	inno_hdmi_set_pwr_mode(hdmi, NORMAL);
-}
-
-static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
-{
-	struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
-
-	inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
-}
-
-static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
-					 const struct drm_display_mode *mode,
-					 struct drm_display_mode *adj_mode)
-{
-	return true;
-}
-
-static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
-	.enable     = inno_hdmi_encoder_enable,
-	.disable    = inno_hdmi_encoder_disable,
-	.mode_fixup = inno_hdmi_encoder_mode_fixup,
-	.mode_set   = inno_hdmi_encoder_mode_set,
-};
-
-static struct drm_encoder_funcs inno_hdmi_encoder_funcs = {
-	.destroy = drm_encoder_cleanup,
-};
-
-static enum drm_connector_status
-inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
-{
-	struct inno_hdmi *hdmi = to_inno_hdmi(connector);
-
-	return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
-		connector_status_connected : connector_status_disconnected;
-}
-
-static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
-{
-	struct inno_hdmi *hdmi = to_inno_hdmi(connector);
-	struct edid *edid;
-	int ret = 0;
-
-	if (!hdmi->ddc)
-		return 0;
-
-	edid = drm_get_edid(connector, hdmi->ddc);
-	if (edid) {
-		hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
-		hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
-		drm_mode_connector_update_edid_property(connector, edid);
-		ret = drm_add_edid_modes(connector, edid);
-		kfree(edid);
-	}
-
-	return ret;
-}
-
-static enum drm_mode_status
-inno_hdmi_connector_mode_valid(struct drm_connector *connector,
-			       struct drm_display_mode *mode)
-{
-	return MODE_OK;
-}
-
-static struct drm_encoder *
-inno_hdmi_connector_best_encoder(struct drm_connector *connector)
-{
-	struct inno_hdmi *hdmi = to_inno_hdmi(connector);
-
-	return &hdmi->encoder;
-}
-
-static int
-inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
-				       uint32_t maxX, uint32_t maxY)
-{
-	return drm_helper_probe_single_connector_modes(connector, 1920, 1080);
-}
-
-static void inno_hdmi_connector_destroy(struct drm_connector *connector)
-{
-	drm_connector_unregister(connector);
-	drm_connector_cleanup(connector);
-}
-
-static struct drm_connector_funcs inno_hdmi_connector_funcs = {
-	.dpms = drm_atomic_helper_connector_dpms,
-	.fill_modes = inno_hdmi_probe_single_connector_modes,
-	.detect = inno_hdmi_connector_detect,
-	.destroy = inno_hdmi_connector_destroy,
-	.reset = drm_atomic_helper_connector_reset,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
-	.get_modes = inno_hdmi_connector_get_modes,
-	.mode_valid = inno_hdmi_connector_mode_valid,
-	.best_encoder = inno_hdmi_connector_best_encoder,
-};
-
-static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
-{
-	struct drm_encoder *encoder = &hdmi->encoder;
-	struct device *dev = hdmi->dev;
-
-	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
-
-	/*
-	 * If we failed to find the CRTC(s) which this encoder is
-	 * supposed to be connected to, it's because the CRTC has
-	 * not been registered yet.  Defer probing, and hope that
-	 * the required CRTC is added later.
-	 */
-	if (encoder->possible_crtcs == 0)
-		return -EPROBE_DEFER;
-
-	drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
-	drm_encoder_init(drm, encoder, &inno_hdmi_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
-
-	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
-
-	drm_connector_helper_add(&hdmi->connector,
-				 &inno_hdmi_connector_helper_funcs);
-	drm_connector_init(drm, &hdmi->connector, &inno_hdmi_connector_funcs,
-			   DRM_MODE_CONNECTOR_HDMIA);
-
-	drm_mode_connector_attach_encoder(&hdmi->connector, encoder);
-
-	return 0;
-}
-
-static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
-{
-	struct inno_hdmi_i2c *i2c = hdmi->i2c;
-	u8 stat;
-
-	stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
-	if (!(stat & m_INT_EDID_READY))
-		return IRQ_NONE;
-
-	/* Clear HDMI EDID interrupt flag */
-	hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
-
-	complete(&i2c->cmp);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
-{
-	struct inno_hdmi *hdmi = dev_id;
-	irqreturn_t ret = IRQ_NONE;
-	u8 interrupt;
-
-	if (hdmi->i2c)
-		ret = inno_hdmi_i2c_irq(hdmi);
-
-	interrupt = hdmi_readb(hdmi, HDMI_STATUS);
-	if (interrupt & m_INT_HOTPLUG) {
-		hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
-		ret = IRQ_WAKE_THREAD;
-	}
-
-	return ret;
-}
-
-static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
-{
-	struct inno_hdmi *hdmi = dev_id;
-
-	drm_helper_hpd_irq_event(hdmi->connector.dev);
-
-	return IRQ_HANDLED;
-}
-
-static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
-{
-	int length = msgs->len;
-	u8 *buf = msgs->buf;
-	int ret;
-
-	ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
-	if (!ret)
-		return -EAGAIN;
-
-	while (length--)
-		*buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
-
-	return 0;
-}
-
-static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
-{
-	/*
-	 * The DDC module only support read EDID message, so
-	 * we assume that each word write to this i2c adapter
-	 * should be the offset of EDID word address.
-	 */
-	if ((msgs->len != 1) ||
-	    ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
-		return -EINVAL;
-
-	reinit_completion(&hdmi->i2c->cmp);
-
-	if (msgs->addr == DDC_SEGMENT_ADDR)
-		hdmi->i2c->segment_addr = msgs->buf[0];
-	if (msgs->addr == DDC_ADDR)
-		hdmi->i2c->ddc_addr = msgs->buf[0];
-
-	/* Set edid fifo first addr */
-	hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
-
-	/* Set edid word address 0x00/0x80 */
-	hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
-
-	/* Set edid segment pointer */
-	hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
-
-	return 0;
-}
-
-static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
-			      struct i2c_msg *msgs, int num)
-{
-	struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
-	struct inno_hdmi_i2c *i2c = hdmi->i2c;
-	int i, ret = 0;
-
-	mutex_lock(&i2c->lock);
-
-	/* Clear the EDID interrupt flag and unmute the interrupt */
-	hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
-	hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
-
-	for (i = 0; i < num; i++) {
-		dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
-			i + 1, num, msgs[i].len, msgs[i].flags);
-
-		if (msgs[i].flags & I2C_M_RD)
-			ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
-		else
-			ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
-
-		if (ret < 0)
-			break;
-	}
-
-	if (!ret)
-		ret = num;
-
-	/* Mute HDMI EDID interrupt */
-	hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
-
-	mutex_unlock(&i2c->lock);
-
-	return ret;
-}
-
-static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static const struct i2c_algorithm inno_hdmi_algorithm = {
-	.master_xfer	= inno_hdmi_i2c_xfer,
-	.functionality	= inno_hdmi_i2c_func,
-};
-
-static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
-{
-	struct i2c_adapter *adap;
-	struct inno_hdmi_i2c *i2c;
-	int ret;
-
-	i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
-	if (!i2c)
-		return ERR_PTR(-ENOMEM);
-
-	mutex_init(&i2c->lock);
-	init_completion(&i2c->cmp);
-
-	adap = &i2c->adap;
-	adap->class = I2C_CLASS_DDC;
-	adap->owner = THIS_MODULE;
-	adap->dev.parent = hdmi->dev;
-	adap->dev.of_node = hdmi->dev->of_node;
-	adap->algo = &inno_hdmi_algorithm;
-	strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
-	i2c_set_adapdata(adap, hdmi);
-
-	ret = i2c_add_adapter(adap);
-	if (ret) {
-		dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
-		devm_kfree(hdmi->dev, i2c);
-		return ERR_PTR(ret);
-	}
-
-	hdmi->i2c = i2c;
-
-	dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
-
-	return adap;
-}
-
-static int inno_hdmi_bind(struct device *dev, struct device *master,
-				 void *data)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct drm_device *drm = data;
-	struct inno_hdmi *hdmi;
-	struct resource *iores;
-	int irq;
-	int ret;
-
-	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
-	if (!hdmi)
-		return -ENOMEM;
-
-	hdmi->dev = dev;
-	hdmi->drm_dev = drm;
-
-	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!iores)
-		return -ENXIO;
-
-	hdmi->regs = devm_ioremap_resource(dev, iores);
-	if (IS_ERR(hdmi->regs))
-		return PTR_ERR(hdmi->regs);
-
-	hdmi->pclk = devm_clk_get(hdmi->dev, "pclk");
-	if (IS_ERR(hdmi->pclk)) {
-		dev_err(hdmi->dev, "Unable to get HDMI pclk clk\n");
-		return PTR_ERR(hdmi->pclk);
-	}
-
-	ret = clk_prepare_enable(hdmi->pclk);
-	if (ret) {
-		dev_err(hdmi->dev, "Cannot enable HDMI pclk clock: %d\n", ret);
-		return ret;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	inno_hdmi_reset(hdmi);
-
-	hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
-	if (IS_ERR(hdmi->ddc)) {
-		hdmi->ddc = NULL;
-		return PTR_ERR(hdmi->ddc);
-	}
-
-	/*
-	 * When IP controller haven't configured to an accurate video
-	 * timing, then the TMDS clock source would be switched to
-	 * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
-	 * and reconfigure the DDC clock.
-	 */
-	hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
-	inno_hdmi_i2c_init(hdmi);
-
-	ret = inno_hdmi_register(drm, hdmi);
-	if (ret)
-		return ret;
-
-	dev_set_drvdata(dev, hdmi);
-
-	/* Unmute hotplug interrupt */
-	hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
-
-	ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
-					inno_hdmi_irq, IRQF_SHARED,
-					dev_name(dev), hdmi);
-
-	return ret;
-}
-
-static void inno_hdmi_unbind(struct device *dev, struct device *master,
-			     void *data)
-{
-	struct inno_hdmi *hdmi = dev_get_drvdata(dev);
-
-	hdmi->connector.funcs->destroy(&hdmi->connector);
-	hdmi->encoder.funcs->destroy(&hdmi->encoder);
-
-	clk_disable_unprepare(hdmi->pclk);
-	i2c_put_adapter(hdmi->ddc);
-}
-
-static const struct component_ops inno_hdmi_ops = {
-	.bind	= inno_hdmi_bind,
-	.unbind	= inno_hdmi_unbind,
-};
-
-static int inno_hdmi_probe(struct platform_device *pdev)
-{
-	return component_add(&pdev->dev, &inno_hdmi_ops);
-}
-
-static int inno_hdmi_remove(struct platform_device *pdev)
-{
-	component_del(&pdev->dev, &inno_hdmi_ops);
-
-	return 0;
-}
-
-static const struct of_device_id inno_hdmi_dt_ids[] = {
-	{ .compatible = "rockchip,rk3036-inno-hdmi",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
-
-static struct platform_driver inno_hdmi_driver = {
-	.probe  = inno_hdmi_probe,
-	.remove = inno_hdmi_remove,
-	.driver = {
-		.name = "innohdmi-rockchip",
-		.of_match_table = inno_hdmi_dt_ids,
-	},
-};
-
-module_platform_driver(inno_hdmi_driver);
-
-MODULE_AUTHOR("Zheng Yang <zhengyang@rock-chips.com>");
-MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip Specific INNO-HDMI Driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:innohdmi-rockchip");
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.h b/drivers/gpu/drm/rockchip/inno_hdmi.h
deleted file mode 100644
index aa7c415..0000000
--- a/drivers/gpu/drm/rockchip/inno_hdmi.h
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
- *    Zheng Yang <zhengyang@rock-chips.com>
- *    Yakir Yang <ykk@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __INNO_HDMI_H__
-#define __INNO_HDMI_H__
-
-#define DDC_SEGMENT_ADDR		0x30
-
-enum PWR_MODE {
-	NORMAL,
-	LOWER_PWR,
-};
-
-#define HDMI_SCL_RATE			(100*1000)
-#define DDC_BUS_FREQ_L			0x4b
-#define DDC_BUS_FREQ_H			0x4c
-
-#define HDMI_SYS_CTRL			0x00
-#define m_RST_ANALOG			(1 << 6)
-#define v_RST_ANALOG			(0 << 6)
-#define v_NOT_RST_ANALOG		(1 << 6)
-#define m_RST_DIGITAL			(1 << 5)
-#define v_RST_DIGITAL			(0 << 5)
-#define v_NOT_RST_DIGITAL		(1 << 5)
-#define m_REG_CLK_INV			(1 << 4)
-#define v_REG_CLK_NOT_INV		(0 << 4)
-#define v_REG_CLK_INV			(1 << 4)
-#define m_VCLK_INV			(1 << 3)
-#define v_VCLK_NOT_INV			(0 << 3)
-#define v_VCLK_INV			(1 << 3)
-#define m_REG_CLK_SOURCE		(1 << 2)
-#define v_REG_CLK_SOURCE_TMDS		(0 << 2)
-#define v_REG_CLK_SOURCE_SYS		(1 << 2)
-#define m_POWER				(1 << 1)
-#define v_PWR_ON			(0 << 1)
-#define v_PWR_OFF			(1 << 1)
-#define m_INT_POL			(1 << 0)
-#define v_INT_POL_HIGH			1
-#define v_INT_POL_LOW			0
-
-#define HDMI_VIDEO_CONTRL1		0x01
-#define m_VIDEO_INPUT_FORMAT		(7 << 1)
-#define m_DE_SOURCE			(1 << 0)
-#define v_VIDEO_INPUT_FORMAT(n)		(n << 1)
-#define v_DE_EXTERNAL			1
-#define v_DE_INTERNAL			0
-enum {
-	VIDEO_INPUT_SDR_RGB444 = 0,
-	VIDEO_INPUT_DDR_RGB444 = 5,
-	VIDEO_INPUT_DDR_YCBCR422 = 6
-};
-
-#define HDMI_VIDEO_CONTRL2		0x02
-#define m_VIDEO_OUTPUT_COLOR		(3 << 6)
-#define m_VIDEO_INPUT_BITS		(3 << 4)
-#define m_VIDEO_INPUT_CSP		(1 << 0)
-#define v_VIDEO_OUTPUT_COLOR(n)		(((n) & 0x3) << 6)
-#define v_VIDEO_INPUT_BITS(n)		(n << 4)
-#define v_VIDEO_INPUT_CSP(n)		(n << 0)
-enum {
-	VIDEO_INPUT_12BITS = 0,
-	VIDEO_INPUT_10BITS = 1,
-	VIDEO_INPUT_REVERT = 2,
-	VIDEO_INPUT_8BITS = 3,
-};
-
-#define HDMI_VIDEO_CONTRL		0x03
-#define m_VIDEO_AUTO_CSC		(1 << 7)
-#define v_VIDEO_AUTO_CSC(n)		(n << 7)
-#define m_VIDEO_C0_C2_SWAP		(1 << 0)
-#define v_VIDEO_C0_C2_SWAP(n)		(n << 0)
-enum {
-	C0_C2_CHANGE_ENABLE = 0,
-	C0_C2_CHANGE_DISABLE = 1,
-	AUTO_CSC_DISABLE = 0,
-	AUTO_CSC_ENABLE = 1,
-};
-
-#define HDMI_VIDEO_CONTRL3		0x04
-#define m_COLOR_DEPTH_NOT_INDICATED	(1 << 4)
-#define m_SOF				(1 << 3)
-#define m_COLOR_RANGE			(1 << 2)
-#define m_CSC				(1 << 0)
-#define v_COLOR_DEPTH_NOT_INDICATED(n)	((n) << 4)
-#define v_SOF_ENABLE			(0 << 3)
-#define v_SOF_DISABLE			(1 << 3)
-#define v_COLOR_RANGE_FULL		(1 << 2)
-#define v_COLOR_RANGE_LIMITED		(0 << 2)
-#define v_CSC_ENABLE			1
-#define v_CSC_DISABLE			0
-
-#define HDMI_AV_MUTE			0x05
-#define m_AVMUTE_CLEAR			(1 << 7)
-#define m_AVMUTE_ENABLE			(1 << 6)
-#define m_AUDIO_MUTE			(1 << 1)
-#define m_VIDEO_BLACK			(1 << 0)
-#define v_AVMUTE_CLEAR(n)		(n << 7)
-#define v_AVMUTE_ENABLE(n)		(n << 6)
-#define v_AUDIO_MUTE(n)			(n << 1)
-#define v_VIDEO_MUTE(n)			(n << 0)
-
-#define HDMI_VIDEO_TIMING_CTL		0x08
-#define v_HSYNC_POLARITY(n)		(n << 3)
-#define v_VSYNC_POLARITY(n)		(n << 2)
-#define v_INETLACE(n)			(n << 1)
-#define v_EXTERANL_VIDEO(n)		(n << 0)
-
-#define HDMI_VIDEO_EXT_HTOTAL_L		0x09
-#define HDMI_VIDEO_EXT_HTOTAL_H		0x0a
-#define HDMI_VIDEO_EXT_HBLANK_L		0x0b
-#define HDMI_VIDEO_EXT_HBLANK_H		0x0c
-#define HDMI_VIDEO_EXT_HDELAY_L		0x0d
-#define HDMI_VIDEO_EXT_HDELAY_H		0x0e
-#define HDMI_VIDEO_EXT_HDURATION_L	0x0f
-#define HDMI_VIDEO_EXT_HDURATION_H	0x10
-#define HDMI_VIDEO_EXT_VTOTAL_L		0x11
-#define HDMI_VIDEO_EXT_VTOTAL_H		0x12
-#define HDMI_VIDEO_EXT_VBLANK		0x13
-#define HDMI_VIDEO_EXT_VDELAY		0x14
-#define HDMI_VIDEO_EXT_VDURATION	0x15
-
-#define HDMI_VIDEO_CSC_COEF		0x18
-
-#define HDMI_AUDIO_CTRL1		0x35
-enum {
-	CTS_SOURCE_INTERNAL = 0,
-	CTS_SOURCE_EXTERNAL = 1,
-};
-#define v_CTS_SOURCE(n)			(n << 7)
-
-enum {
-	DOWNSAMPLE_DISABLE = 0,
-	DOWNSAMPLE_1_2 = 1,
-	DOWNSAMPLE_1_4 = 2,
-};
-#define v_DOWN_SAMPLE(n)		(n << 5)
-
-enum {
-	AUDIO_SOURCE_IIS = 0,
-	AUDIO_SOURCE_SPDIF = 1,
-};
-#define v_AUDIO_SOURCE(n)		(n << 3)
-
-#define v_MCLK_ENABLE(n)		(n << 2)
-enum {
-	MCLK_128FS = 0,
-	MCLK_256FS = 1,
-	MCLK_384FS = 2,
-	MCLK_512FS = 3,
-};
-#define v_MCLK_RATIO(n)			(n)
-
-#define AUDIO_SAMPLE_RATE		0x37
-enum {
-	AUDIO_32K = 0x3,
-	AUDIO_441K = 0x0,
-	AUDIO_48K = 0x2,
-	AUDIO_882K = 0x8,
-	AUDIO_96K = 0xa,
-	AUDIO_1764K = 0xc,
-	AUDIO_192K = 0xe,
-};
-
-#define AUDIO_I2S_MODE			0x38
-enum {
-	I2S_CHANNEL_1_2 = 1,
-	I2S_CHANNEL_3_4 = 3,
-	I2S_CHANNEL_5_6 = 7,
-	I2S_CHANNEL_7_8 = 0xf
-};
-#define v_I2S_CHANNEL(n)		((n) << 2)
-enum {
-	I2S_STANDARD = 0,
-	I2S_LEFT_JUSTIFIED = 1,
-	I2S_RIGHT_JUSTIFIED = 2,
-};
-#define v_I2S_MODE(n)			(n)
-
-#define AUDIO_I2S_MAP			0x39
-#define AUDIO_I2S_SWAPS_SPDIF		0x3a
-#define v_SPIDF_FREQ(n)			(n)
-
-#define N_32K				0x1000
-#define N_441K				0x1880
-#define N_882K				0x3100
-#define N_1764K				0x6200
-#define N_48K				0x1800
-#define N_96K				0x3000
-#define N_192K				0x6000
-
-#define HDMI_AUDIO_CHANNEL_STATUS	0x3e
-#define m_AUDIO_STATUS_NLPCM		(1 << 7)
-#define m_AUDIO_STATUS_USE		(1 << 6)
-#define m_AUDIO_STATUS_COPYRIGHT	(1 << 5)
-#define m_AUDIO_STATUS_ADDITION		(3 << 2)
-#define m_AUDIO_STATUS_CLK_ACCURACY	(2 << 0)
-#define v_AUDIO_STATUS_NLPCM(n)		((n & 1) << 7)
-#define AUDIO_N_H			0x3f
-#define AUDIO_N_M			0x40
-#define AUDIO_N_L			0x41
-
-#define HDMI_AUDIO_CTS_H		0x45
-#define HDMI_AUDIO_CTS_M		0x46
-#define HDMI_AUDIO_CTS_L		0x47
-
-#define HDMI_DDC_CLK_L			0x4b
-#define HDMI_DDC_CLK_H			0x4c
-
-#define HDMI_EDID_SEGMENT_POINTER	0x4d
-#define HDMI_EDID_WORD_ADDR		0x4e
-#define HDMI_EDID_FIFO_OFFSET		0x4f
-#define HDMI_EDID_FIFO_ADDR		0x50
-
-#define HDMI_PACKET_SEND_MANUAL		0x9c
-#define HDMI_PACKET_SEND_AUTO		0x9d
-#define m_PACKET_GCP_EN			(1 << 7)
-#define m_PACKET_MSI_EN			(1 << 6)
-#define m_PACKET_SDI_EN			(1 << 5)
-#define m_PACKET_VSI_EN			(1 << 4)
-#define v_PACKET_GCP_EN(n)		((n & 1) << 7)
-#define v_PACKET_MSI_EN(n)		((n & 1) << 6)
-#define v_PACKET_SDI_EN(n)		((n & 1) << 5)
-#define v_PACKET_VSI_EN(n)		((n & 1) << 4)
-
-#define HDMI_CONTROL_PACKET_BUF_INDEX	0x9f
-enum {
-	INFOFRAME_VSI = 0x05,
-	INFOFRAME_AVI = 0x06,
-	INFOFRAME_AAI = 0x08,
-};
-
-#define HDMI_CONTROL_PACKET_ADDR	0xa0
-#define HDMI_MAXIMUM_INFO_FRAME_SIZE	0x11
-enum {
-	AVI_COLOR_MODE_RGB = 0,
-	AVI_COLOR_MODE_YCBCR422 = 1,
-	AVI_COLOR_MODE_YCBCR444 = 2,
-	AVI_COLORIMETRY_NO_DATA = 0,
-
-	AVI_COLORIMETRY_SMPTE_170M = 1,
-	AVI_COLORIMETRY_ITU709 = 2,
-	AVI_COLORIMETRY_EXTENDED = 3,
-
-	AVI_CODED_FRAME_ASPECT_NO_DATA = 0,
-	AVI_CODED_FRAME_ASPECT_4_3 = 1,
-	AVI_CODED_FRAME_ASPECT_16_9 = 2,
-
-	ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
-	ACTIVE_ASPECT_RATE_4_3 = 0x09,
-	ACTIVE_ASPECT_RATE_16_9 = 0x0A,
-	ACTIVE_ASPECT_RATE_14_9 = 0x0B,
-};
-
-#define HDMI_HDCP_CTRL			0x52
-#define m_HDMI_DVI			(1 << 1)
-#define v_HDMI_DVI(n)			(n << 1)
-
-#define HDMI_INTERRUPT_MASK1		0xc0
-#define HDMI_INTERRUPT_STATUS1		0xc1
-#define	m_INT_ACTIVE_VSYNC		(1 << 5)
-#define m_INT_EDID_READY		(1 << 2)
-
-#define HDMI_INTERRUPT_MASK2		0xc2
-#define HDMI_INTERRUPT_STATUS2		0xc3
-#define m_INT_HDCP_ERR			(1 << 7)
-#define m_INT_BKSV_FLAG			(1 << 6)
-#define m_INT_HDCP_OK			(1 << 4)
-
-#define HDMI_STATUS			0xc8
-#define m_HOTPLUG			(1 << 7)
-#define m_MASK_INT_HOTPLUG		(1 << 5)
-#define m_INT_HOTPLUG			(1 << 1)
-#define v_MASK_INT_HOTPLUG(n)		((n & 0x1) << 5)
-
-#define HDMI_COLORBAR                   0xc9
-
-#define HDMI_PHY_SYNC			0xce
-#define HDMI_PHY_SYS_CTL		0xe0
-#define m_TMDS_CLK_SOURCE		(1 << 5)
-#define v_TMDS_FROM_PLL			(0 << 5)
-#define v_TMDS_FROM_GEN			(1 << 5)
-#define m_PHASE_CLK			(1 << 4)
-#define v_DEFAULT_PHASE			(0 << 4)
-#define v_SYNC_PHASE			(1 << 4)
-#define m_TMDS_CURRENT_PWR		(1 << 3)
-#define v_TURN_ON_CURRENT		(0 << 3)
-#define v_CAT_OFF_CURRENT		(1 << 3)
-#define m_BANDGAP_PWR			(1 << 2)
-#define v_BANDGAP_PWR_UP		(0 << 2)
-#define v_BANDGAP_PWR_DOWN		(1 << 2)
-#define m_PLL_PWR			(1 << 1)
-#define v_PLL_PWR_UP			(0 << 1)
-#define v_PLL_PWR_DOWN			(1 << 1)
-#define m_TMDS_CHG_PWR			(1 << 0)
-#define v_TMDS_CHG_PWR_UP		(0 << 0)
-#define v_TMDS_CHG_PWR_DOWN		(1 << 0)
-
-#define HDMI_PHY_CHG_PWR		0xe1
-#define v_CLK_CHG_PWR(n)		((n & 1) << 3)
-#define v_DATA_CHG_PWR(n)		((n & 7) << 0)
-
-#define HDMI_PHY_DRIVER			0xe2
-#define v_CLK_MAIN_DRIVER(n)		(n << 4)
-#define v_DATA_MAIN_DRIVER(n)		(n << 0)
-
-#define HDMI_PHY_PRE_EMPHASIS		0xe3
-#define v_PRE_EMPHASIS(n)		((n & 7) << 4)
-#define v_CLK_PRE_DRIVER(n)		((n & 3) << 2)
-#define v_DATA_PRE_DRIVER(n)		((n & 3) << 0)
-
-#define HDMI_PHY_FEEDBACK_DIV_RATIO_LOW		0xe7
-#define v_FEEDBACK_DIV_LOW(n)			(n & 0xff)
-#define HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH	0xe8
-#define v_FEEDBACK_DIV_HIGH(n)			(n & 1)
-
-#define HDMI_PHY_PRE_DIV_RATIO		0xed
-#define v_PRE_DIV_RATIO(n)		(n & 0x1f)
-
-#define HDMI_CEC_CTRL			0xd0
-#define m_ADJUST_FOR_HISENSE		(1 << 6)
-#define m_REJECT_RX_BROADCAST		(1 << 5)
-#define m_BUSFREETIME_ENABLE		(1 << 2)
-#define m_REJECT_RX			(1 << 1)
-#define m_START_TX			(1 << 0)
-
-#define HDMI_CEC_DATA			0xd1
-#define HDMI_CEC_TX_OFFSET		0xd2
-#define HDMI_CEC_RX_OFFSET		0xd3
-#define HDMI_CEC_CLK_H			0xd4
-#define HDMI_CEC_CLK_L			0xd5
-#define HDMI_CEC_TX_LENGTH		0xd6
-#define HDMI_CEC_RX_LENGTH		0xd7
-#define HDMI_CEC_TX_INT_MASK		0xd8
-#define m_TX_DONE			(1 << 3)
-#define m_TX_NOACK			(1 << 2)
-#define m_TX_BROADCAST_REJ		(1 << 1)
-#define m_TX_BUSNOTFREE			(1 << 0)
-
-#define HDMI_CEC_RX_INT_MASK		0xd9
-#define m_RX_LA_ERR			(1 << 4)
-#define m_RX_GLITCH			(1 << 3)
-#define m_RX_DONE			(1 << 0)
-
-#define HDMI_CEC_TX_INT			0xda
-#define HDMI_CEC_RX_INT			0xdb
-#define HDMI_CEC_BUSFREETIME_L		0xdc
-#define HDMI_CEC_BUSFREETIME_H		0xdd
-#define HDMI_CEC_LOGICADDR		0xde
-
-#endif /* __INNO_HDMI_H__ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 16bb3c9..f22e1e1 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -55,18 +55,20 @@
 
 	return arm_iommu_attach_device(dev, mapping);
 }
+EXPORT_SYMBOL_GPL(rockchip_drm_dma_attach_device);
 
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
 				    struct device *dev)
 {
 	arm_iommu_detach_device(dev);
 }
+EXPORT_SYMBOL_GPL(rockchip_drm_dma_detach_device);
 
-int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
-				 const struct rockchip_crtc_funcs *crtc_funcs)
+int rockchip_register_crtc_funcs(struct drm_device *dev,
+				 const struct rockchip_crtc_funcs *crtc_funcs,
+				 int pipe)
 {
-	int pipe = drm_crtc_index(crtc);
-	struct rockchip_drm_private *priv = crtc->dev->dev_private;
+	struct rockchip_drm_private *priv = dev->dev_private;
 
 	if (pipe > ROCKCHIP_MAX_CRTC)
 		return -EINVAL;
@@ -75,17 +77,18 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(rockchip_register_crtc_funcs);
 
-void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc)
+void rockchip_unregister_crtc_funcs(struct drm_device *dev, int pipe)
 {
-	int pipe = drm_crtc_index(crtc);
-	struct rockchip_drm_private *priv = crtc->dev->dev_private;
+	struct rockchip_drm_private *priv = dev->dev_private;
 
 	if (pipe > ROCKCHIP_MAX_CRTC)
 		return;
 
 	priv->crtc_funcs[pipe] = NULL;
 }
+EXPORT_SYMBOL_GPL(rockchip_unregister_crtc_funcs);
 
 static struct drm_crtc *rockchip_crtc_from_pipe(struct drm_device *drm,
 						int pipe)
@@ -136,9 +139,6 @@
 	if (!private)
 		return -ENOMEM;
 
-	mutex_init(&private->commit.lock);
-	INIT_WORK(&private->commit.work, rockchip_drm_atomic_work);
-
 	drm_dev->dev_private = private;
 
 	drm_mode_config_init(drm_dev);
@@ -212,8 +212,6 @@
 	 */
 	drm_dev->vblank_disable_allowed = true;
 
-	drm_mode_config_reset(drm_dev);
-
 	ret = rockchip_drm_fbdev_init(drm_dev);
 	if (ret)
 		goto err_vblank_cleanup;
@@ -277,8 +275,7 @@
 };
 
 static struct drm_driver rockchip_drm_driver = {
-	.driver_features	= DRIVER_MODESET | DRIVER_GEM |
-				  DRIVER_PRIME | DRIVER_ATOMIC,
+	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
 	.load			= rockchip_drm_load,
 	.unload			= rockchip_drm_unload,
 	.lastclose		= rockchip_drm_lastclose,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index bb8b076..dc4e5f0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -18,7 +18,6 @@
 #define _ROCKCHIP_DRM_DRV_H
 
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_atomic_helper.h>
 #include <drm/drm_gem.h>
 
 #include <linux/module.h>
@@ -39,14 +38,6 @@
 struct rockchip_crtc_funcs {
 	int (*enable_vblank)(struct drm_crtc *crtc);
 	void (*disable_vblank)(struct drm_crtc *crtc);
-	void (*wait_for_update)(struct drm_crtc *crtc);
-};
-
-struct rockchip_atomic_commit {
-	struct work_struct	work;
-	struct drm_atomic_state *state;
-	struct drm_device *dev;
-	struct mutex lock;
 };
 
 /*
@@ -59,14 +50,12 @@
 	struct drm_fb_helper fbdev_helper;
 	struct drm_gem_object *fbdev_bo;
 	const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
-
-	struct rockchip_atomic_commit commit;
 };
 
-void rockchip_drm_atomic_work(struct work_struct *work);
-int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
-				 const struct rockchip_crtc_funcs *crtc_funcs);
-void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
+int rockchip_register_crtc_funcs(struct drm_device *dev,
+				 const struct rockchip_crtc_funcs *crtc_funcs,
+				 int pipe);
+void rockchip_unregister_crtc_funcs(struct drm_device *dev, int pipe);
 int rockchip_drm_encoder_get_mux_id(struct device_node *node,
 				    struct drm_encoder *encoder);
 int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int connector_type,
@@ -75,4 +64,5 @@
 				   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
 				    struct device *dev);
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index f1631e3..002645b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <drm/drm.h>
 #include <drm/drmP.h>
-#include <drm/drm_atomic.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 
@@ -39,6 +38,7 @@
 
 	return rk_fb->obj[plane];
 }
+EXPORT_SYMBOL_GPL(rockchip_fb_get_gem_obj);
 
 static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb)
 {
@@ -66,7 +66,7 @@
 				     rockchip_fb->obj[0], handle);
 }
 
-static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
+static struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
 	.destroy	= rockchip_drm_fb_destroy,
 	.create_handle	= rockchip_drm_fb_create_handle,
 };
@@ -166,150 +166,9 @@
 		drm_fb_helper_hotplug_event(fb_helper);
 }
 
-static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc)
-{
-	struct rockchip_drm_private *priv = crtc->dev->dev_private;
-	int pipe = drm_crtc_index(crtc);
-	const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe];
-
-	if (crtc_funcs && crtc_funcs->wait_for_update)
-		crtc_funcs->wait_for_update(crtc);
-}
-
-/*
- * We can't use drm_atomic_helper_wait_for_vblanks() because rk3288 and rk3066
- * have hardware counters for neither vblanks nor scanlines, which results in
- * a race where:
- *				| <-- HW vsync irq and reg take effect
- *	       plane_commit --> |
- *	get_vblank and wait --> |
- *				| <-- handle_vblank, vblank->count + 1
- *		 cleanup_fb --> |
- *		iommu crash --> |
- *				| <-- HW vsync irq and reg take effect
- *
- * This function is equivalent but uses rockchip_crtc_wait_for_update() instead
- * of waiting for vblank_count to change.
- */
-static void
-rockchip_atomic_wait_for_complete(struct drm_device *dev, struct drm_atomic_state *old_state)
-{
-	struct drm_crtc_state *old_crtc_state;
-	struct drm_crtc *crtc;
-	int i, ret;
-
-	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
-		/* No one cares about the old state, so abuse it for tracking
-		 * and store whether we hold a vblank reference (and should do a
-		 * vblank wait) in the ->enable boolean.
-		 */
-		old_crtc_state->enable = false;
-
-		if (!crtc->state->active)
-			continue;
-
-		if (!drm_atomic_helper_framebuffer_changed(dev,
-				old_state, crtc))
-			continue;
-
-		ret = drm_crtc_vblank_get(crtc);
-		if (ret != 0)
-			continue;
-
-		old_crtc_state->enable = true;
-	}
-
-	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
-		if (!old_crtc_state->enable)
-			continue;
-
-		rockchip_crtc_wait_for_update(crtc);
-		drm_crtc_vblank_put(crtc);
-	}
-}
-
-static void
-rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit)
-{
-	struct drm_atomic_state *state = commit->state;
-	struct drm_device *dev = commit->dev;
-
-	/*
-	 * TODO: do fence wait here.
-	 */
-
-	/*
-	 * Rockchip crtc support runtime PM, can't update display planes
-	 * when crtc is disabled.
-	 *
-	 * drm_atomic_helper_commit comments detail that:
-	 *     For drivers supporting runtime PM the recommended sequence is
-	 *
-	 *     drm_atomic_helper_commit_modeset_disables(dev, state);
-	 *
-	 *     drm_atomic_helper_commit_modeset_enables(dev, state);
-	 *
-	 *     drm_atomic_helper_commit_planes(dev, state, true);
-	 *
-	 * See the kerneldoc entries for these three functions for more details.
-	 */
-	drm_atomic_helper_commit_modeset_disables(dev, state);
-
-	drm_atomic_helper_commit_modeset_enables(dev, state);
-
-	drm_atomic_helper_commit_planes(dev, state, true);
-
-	rockchip_atomic_wait_for_complete(dev, state);
-
-	drm_atomic_helper_cleanup_planes(dev, state);
-
-	drm_atomic_state_free(state);
-}
-
-void rockchip_drm_atomic_work(struct work_struct *work)
-{
-	struct rockchip_atomic_commit *commit = container_of(work,
-					struct rockchip_atomic_commit, work);
-
-	rockchip_atomic_commit_complete(commit);
-}
-
-int rockchip_drm_atomic_commit(struct drm_device *dev,
-			       struct drm_atomic_state *state,
-			       bool async)
-{
-	struct rockchip_drm_private *private = dev->dev_private;
-	struct rockchip_atomic_commit *commit = &private->commit;
-	int ret;
-
-	ret = drm_atomic_helper_prepare_planes(dev, state);
-	if (ret)
-		return ret;
-
-	/* serialize outstanding asynchronous commits */
-	mutex_lock(&commit->lock);
-	flush_work(&commit->work);
-
-	drm_atomic_helper_swap_state(dev, state);
-
-	commit->dev = dev;
-	commit->state = state;
-
-	if (async)
-		schedule_work(&commit->work);
-	else
-		rockchip_atomic_commit_complete(commit);
-
-	mutex_unlock(&commit->lock);
-
-	return 0;
-}
-
 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
 	.fb_create = rockchip_user_fb_create,
 	.output_poll_changed = rockchip_drm_output_poll_changed,
-	.atomic_check = drm_atomic_helper_check,
-	.atomic_commit = rockchip_drm_atomic_commit,
 };
 
 struct drm_framebuffer *
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h
index 73718c5..50432e9 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h
@@ -15,18 +15,7 @@
 #ifndef _ROCKCHIP_DRM_FBDEV_H
 #define _ROCKCHIP_DRM_FBDEV_H
 
-#ifdef CONFIG_DRM_FBDEV_EMULATION
 int rockchip_drm_fbdev_init(struct drm_device *dev);
 void rockchip_drm_fbdev_fini(struct drm_device *dev);
-#else
-static inline int rockchip_drm_fbdev_init(struct drm_device *dev)
-{
-	return 0;
-}
-
-static inline void rockchip_drm_fbdev_fini(struct drm_device *dev)
-{
-}
-#endif
 
 #endif /* _ROCKCHIP_DRM_FBDEV_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 18e0733..d908321 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -234,8 +234,13 @@
 	/*
 	 * align to 64 bytes since Mali requires it.
 	 */
-	args->pitch = ALIGN(min_pitch, 64);
-	args->size = args->pitch * args->height;
+	min_pitch = ALIGN(min_pitch, 64);
+
+	if (args->pitch < min_pitch)
+		args->pitch = min_pitch;
+
+	if (args->size < args->pitch * args->height)
+		args->size = args->pitch * args->height;
 
 	rk_obj = rockchip_gem_create_with_handle(file_priv, dev, args->size,
 						 &args->handle);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 0295584..03c47ee 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -14,7 +14,6 @@
 
 #include <drm/drm.h>
 #include <drm/drmP.h>
-#include <drm/drm_atomic.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_plane_helper.h>
@@ -36,6 +35,11 @@
 #include "rockchip_drm_fb.h"
 #include "rockchip_drm_vop.h"
 
+#define VOP_REG(off, _mask, s) \
+		{.offset = off, \
+		 .mask = _mask, \
+		 .shift = s,}
+
 #define __REG_SET_RELAXED(x, off, mask, shift, v) \
 		vop_mask_write_relaxed(x, off, (mask) << shift, (v) << shift)
 #define __REG_SET_NORMAL(x, off, mask, shift, v) \
@@ -43,35 +47,14 @@
 
 #define REG_SET(x, base, reg, v, mode) \
 		__REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
-#define REG_SET_MASK(x, base, reg, v, mode) \
-		__REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
 
 #define VOP_WIN_SET(x, win, name, v) \
 		REG_SET(x, win->base, win->phy->name, v, RELAXED)
 #define VOP_SCL_SET(x, win, name, v) \
 		REG_SET(x, win->base, win->phy->scl->name, v, RELAXED)
-#define VOP_SCL_SET_EXT(x, win, name, v) \
-		REG_SET(x, win->base, win->phy->scl->ext->name, v, RELAXED)
 #define VOP_CTRL_SET(x, name, v) \
 		REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL)
 
-#define VOP_INTR_GET(vop, name) \
-		vop_read_reg(vop, 0, &vop->data->ctrl->name)
-
-#define VOP_INTR_SET(vop, name, v) \
-		REG_SET(vop, 0, vop->data->intr->name, v, NORMAL)
-#define VOP_INTR_SET_TYPE(vop, name, type, v) \
-	do { \
-		int i, reg = 0; \
-		for (i = 0; i < vop->data->intr->nintrs; i++) { \
-			if (vop->data->intr->intrs[i] & type) \
-				reg |= (v) << i; \
-		} \
-		VOP_INTR_SET(vop, name, reg); \
-	} while (0)
-#define VOP_INTR_GET_TYPE(vop, name, type) \
-		vop_get_intr_type(vop, &vop->data->intr->name, type)
-
 #define VOP_WIN_GET(x, win, name) \
 		vop_read_reg(x, win->base, &win->phy->name)
 
@@ -80,15 +63,12 @@
 
 #define to_vop(x) container_of(x, struct vop, crtc)
 #define to_vop_win(x) container_of(x, struct vop_win, base)
-#define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)
 
-struct vop_plane_state {
-	struct drm_plane_state base;
-	int format;
-	struct drm_rect src;
-	struct drm_rect dest;
+struct vop_win_state {
+	struct list_head head;
+	struct drm_framebuffer *fb;
 	dma_addr_t yrgb_mst;
-	bool enable;
+	struct drm_pending_vblank_event *event;
 };
 
 struct vop_win {
@@ -96,7 +76,8 @@
 	const struct vop_win_data *data;
 	struct vop *vop;
 
-	struct vop_plane_state state;
+	struct list_head pending;
+	struct vop_win_state *active;
 };
 
 struct vop {
@@ -105,12 +86,13 @@
 	struct drm_device *drm_dev;
 	bool is_enabled;
 
+	int connector_type;
+	int connector_out_mode;
+
 	/* mutex vsync_ work */
 	struct mutex vsync_mutex;
 	bool vsync_work_pending;
 	struct completion dsp_hold_completion;
-	struct completion wait_update_complete;
-	struct drm_pending_vblank_event *event;
 
 	const struct vop_data *data;
 
@@ -137,9 +119,263 @@
 	/* vop dclk reset */
 	struct reset_control *dclk_rst;
 
+	int pipe;
+
 	struct vop_win win[];
 };
 
+enum vop_data_format {
+	VOP_FMT_ARGB8888 = 0,
+	VOP_FMT_RGB888,
+	VOP_FMT_RGB565,
+	VOP_FMT_YUV420SP = 4,
+	VOP_FMT_YUV422SP,
+	VOP_FMT_YUV444SP,
+};
+
+struct vop_reg_data {
+	uint32_t offset;
+	uint32_t value;
+};
+
+struct vop_reg {
+	uint32_t offset;
+	uint32_t shift;
+	uint32_t mask;
+};
+
+struct vop_ctrl {
+	struct vop_reg standby;
+	struct vop_reg data_blank;
+	struct vop_reg gate_en;
+	struct vop_reg mmu_en;
+	struct vop_reg rgb_en;
+	struct vop_reg edp_en;
+	struct vop_reg hdmi_en;
+	struct vop_reg mipi_en;
+	struct vop_reg out_mode;
+	struct vop_reg dither_down;
+	struct vop_reg dither_up;
+	struct vop_reg pin_pol;
+
+	struct vop_reg htotal_pw;
+	struct vop_reg hact_st_end;
+	struct vop_reg vtotal_pw;
+	struct vop_reg vact_st_end;
+	struct vop_reg hpost_st_end;
+	struct vop_reg vpost_st_end;
+};
+
+struct vop_scl_regs {
+	struct vop_reg cbcr_vsd_mode;
+	struct vop_reg cbcr_vsu_mode;
+	struct vop_reg cbcr_hsd_mode;
+	struct vop_reg cbcr_ver_scl_mode;
+	struct vop_reg cbcr_hor_scl_mode;
+	struct vop_reg yrgb_vsd_mode;
+	struct vop_reg yrgb_vsu_mode;
+	struct vop_reg yrgb_hsd_mode;
+	struct vop_reg yrgb_ver_scl_mode;
+	struct vop_reg yrgb_hor_scl_mode;
+	struct vop_reg line_load_mode;
+	struct vop_reg cbcr_axi_gather_num;
+	struct vop_reg yrgb_axi_gather_num;
+	struct vop_reg vsd_cbcr_gt2;
+	struct vop_reg vsd_cbcr_gt4;
+	struct vop_reg vsd_yrgb_gt2;
+	struct vop_reg vsd_yrgb_gt4;
+	struct vop_reg bic_coe_sel;
+	struct vop_reg cbcr_axi_gather_en;
+	struct vop_reg yrgb_axi_gather_en;
+
+	struct vop_reg lb_mode;
+	struct vop_reg scale_yrgb_x;
+	struct vop_reg scale_yrgb_y;
+	struct vop_reg scale_cbcr_x;
+	struct vop_reg scale_cbcr_y;
+};
+
+struct vop_win_phy {
+	const struct vop_scl_regs *scl;
+	const uint32_t *data_formats;
+	uint32_t nformats;
+
+	struct vop_reg enable;
+	struct vop_reg format;
+	struct vop_reg rb_swap;
+	struct vop_reg act_info;
+	struct vop_reg dsp_info;
+	struct vop_reg dsp_st;
+	struct vop_reg yrgb_mst;
+	struct vop_reg uv_mst;
+	struct vop_reg yrgb_vir;
+	struct vop_reg uv_vir;
+
+	struct vop_reg dst_alpha_ctl;
+	struct vop_reg src_alpha_ctl;
+};
+
+struct vop_win_data {
+	uint32_t base;
+	const struct vop_win_phy *phy;
+	enum drm_plane_type type;
+};
+
+struct vop_data {
+	const struct vop_reg_data *init_table;
+	unsigned int table_size;
+	const struct vop_ctrl *ctrl;
+	const struct vop_win_data *win;
+	unsigned int win_size;
+};
+
+static const uint32_t formats_01[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV24,
+};
+
+static const uint32_t formats_234[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+};
+
+static const struct vop_scl_regs win_full_scl = {
+	.cbcr_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 31),
+	.cbcr_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 30),
+	.cbcr_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 28),
+	.cbcr_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 26),
+	.cbcr_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 24),
+	.yrgb_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 23),
+	.yrgb_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 22),
+	.yrgb_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 20),
+	.yrgb_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 18),
+	.yrgb_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 16),
+	.line_load_mode = VOP_REG(WIN0_CTRL1, 0x1, 15),
+	.cbcr_axi_gather_num = VOP_REG(WIN0_CTRL1, 0x7, 12),
+	.yrgb_axi_gather_num = VOP_REG(WIN0_CTRL1, 0xf, 8),
+	.vsd_cbcr_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 7),
+	.vsd_cbcr_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 6),
+	.vsd_yrgb_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 5),
+	.vsd_yrgb_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 4),
+	.bic_coe_sel = VOP_REG(WIN0_CTRL1, 0x3, 2),
+	.cbcr_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 1),
+	.yrgb_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 0),
+	.lb_mode = VOP_REG(WIN0_CTRL0, 0x7, 5),
+	.scale_yrgb_x = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 16),
+};
+
+static const struct vop_win_phy win01_data = {
+	.scl = &win_full_scl,
+	.data_formats = formats_01,
+	.nformats = ARRAY_SIZE(formats_01),
+	.enable = VOP_REG(WIN0_CTRL0, 0x1, 0),
+	.format = VOP_REG(WIN0_CTRL0, 0x7, 1),
+	.rb_swap = VOP_REG(WIN0_CTRL0, 0x1, 12),
+	.act_info = VOP_REG(WIN0_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(WIN0_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(WIN0_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(WIN0_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(WIN0_CBR_MST, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(WIN0_VIR, 0x3fff, 0),
+	.uv_vir = VOP_REG(WIN0_VIR, 0x3fff, 16),
+	.src_alpha_ctl = VOP_REG(WIN0_SRC_ALPHA_CTRL, 0xff, 0),
+	.dst_alpha_ctl = VOP_REG(WIN0_DST_ALPHA_CTRL, 0xff, 0),
+};
+
+static const struct vop_win_phy win23_data = {
+	.data_formats = formats_234,
+	.nformats = ARRAY_SIZE(formats_234),
+	.enable = VOP_REG(WIN2_CTRL0, 0x1, 0),
+	.format = VOP_REG(WIN2_CTRL0, 0x7, 1),
+	.rb_swap = VOP_REG(WIN2_CTRL0, 0x1, 12),
+	.dsp_info = VOP_REG(WIN2_DSP_INFO0, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(WIN2_DSP_ST0, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(WIN2_MST0, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(WIN2_VIR0_1, 0x1fff, 0),
+	.src_alpha_ctl = VOP_REG(WIN2_SRC_ALPHA_CTRL, 0xff, 0),
+	.dst_alpha_ctl = VOP_REG(WIN2_DST_ALPHA_CTRL, 0xff, 0),
+};
+
+static const struct vop_ctrl ctrl_data = {
+	.standby = VOP_REG(SYS_CTRL, 0x1, 22),
+	.gate_en = VOP_REG(SYS_CTRL, 0x1, 23),
+	.mmu_en = VOP_REG(SYS_CTRL, 0x1, 20),
+	.rgb_en = VOP_REG(SYS_CTRL, 0x1, 12),
+	.hdmi_en = VOP_REG(SYS_CTRL, 0x1, 13),
+	.edp_en = VOP_REG(SYS_CTRL, 0x1, 14),
+	.mipi_en = VOP_REG(SYS_CTRL, 0x1, 15),
+	.dither_down = VOP_REG(DSP_CTRL1, 0xf, 1),
+	.dither_up = VOP_REG(DSP_CTRL1, 0x1, 6),
+	.data_blank = VOP_REG(DSP_CTRL0, 0x1, 19),
+	.out_mode = VOP_REG(DSP_CTRL0, 0xf, 0),
+	.pin_pol = VOP_REG(DSP_CTRL0, 0xf, 4),
+	.htotal_pw = VOP_REG(DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.hact_st_end = VOP_REG(DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.hpost_st_end = VOP_REG(POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+};
+
+static const struct vop_reg_data vop_init_reg_table[] = {
+	{SYS_CTRL, 0x00c00000},
+	{DSP_CTRL0, 0x00000000},
+	{WIN0_CTRL0, 0x00000080},
+	{WIN1_CTRL0, 0x00000080},
+	/* TODO: Win2/3 support multiple area function, but we haven't found
+	 * a suitable way to use it yet, so let's just use them as other windows
+	 * with only area 0 enabled.
+	 */
+	{WIN2_CTRL0, 0x00000010},
+	{WIN3_CTRL0, 0x00000010},
+};
+
+/*
+ * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
+ * special support to get alpha blending working.  For now, just use overlay
+ * window 3 for the drm cursor.
+ *
+ */
+static const struct vop_win_data rk3288_vop_win_data[] = {
+	{ .base = 0x00, .phy = &win01_data, .type = DRM_PLANE_TYPE_PRIMARY },
+	{ .base = 0x40, .phy = &win01_data, .type = DRM_PLANE_TYPE_OVERLAY },
+	{ .base = 0x00, .phy = &win23_data, .type = DRM_PLANE_TYPE_OVERLAY },
+	{ .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_CURSOR },
+};
+
+static const struct vop_data rk3288_vop = {
+	.init_table = vop_init_reg_table,
+	.table_size = ARRAY_SIZE(vop_init_reg_table),
+	.ctrl = &ctrl_data,
+	.win = rk3288_vop_win_data,
+	.win_size = ARRAY_SIZE(rk3288_vop_win_data),
+};
+
+static const struct of_device_id vop_driver_dt_match[] = {
+	{ .compatible = "rockchip,rk3288-vop",
+	  .data = &rk3288_vop },
+	{},
+};
+MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
+
 static inline void vop_writel(struct vop *vop, uint32_t offset, uint32_t v)
 {
 	writel(v, vop->regs + offset);
@@ -157,6 +393,11 @@
 	return (vop_readl(vop, base + reg->offset) >> reg->shift) & reg->mask;
 }
 
+static inline void vop_cfg_done(struct vop *vop)
+{
+	writel(0x01, vop->regs + REG_CFG_DONE);
+}
+
 static inline void vop_mask_write(struct vop *vop, uint32_t offset,
 				  uint32_t mask, uint32_t v)
 {
@@ -181,25 +422,6 @@
 	}
 }
 
-static inline uint32_t vop_get_intr_type(struct vop *vop,
-					 const struct vop_reg *reg, int type)
-{
-	uint32_t i, ret = 0;
-	uint32_t regs = vop_read_reg(vop, 0, reg);
-
-	for (i = 0; i < vop->data->intr->nintrs; i++) {
-		if ((type & vop->data->intr->intrs[i]) && (regs & 1 << i))
-			ret |= vop->data->intr->intrs[i];
-	}
-
-	return ret;
-}
-
-static inline void vop_cfg_done(struct vop *vop)
-{
-	VOP_CTRL_SET(vop, cfg_done, 1);
-}
-
 static bool has_rb_swapped(uint32_t format)
 {
 	switch (format) {
@@ -315,20 +537,6 @@
 		return;
 	}
 
-	if (!win->phy->scl->ext) {
-		VOP_SCL_SET(vop, win, scale_yrgb_x,
-			    scl_cal_scale2(src_w, dst_w));
-		VOP_SCL_SET(vop, win, scale_yrgb_y,
-			    scl_cal_scale2(src_h, dst_h));
-		if (is_yuv) {
-			VOP_SCL_SET(vop, win, scale_cbcr_x,
-				    scl_cal_scale2(src_w, dst_w));
-			VOP_SCL_SET(vop, win, scale_cbcr_y,
-				    scl_cal_scale2(src_h, dst_h));
-		}
-		return;
-	}
-
 	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
 	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
 
@@ -346,7 +554,7 @@
 			lb_mode = scl_vop_cal_lb_mode(src_w, false);
 	}
 
-	VOP_SCL_SET_EXT(vop, win, lb_mode, lb_mode);
+	VOP_SCL_SET(vop, win, lb_mode, lb_mode);
 	if (lb_mode == LB_RGB_3840X2) {
 		if (yrgb_ver_scl_mode != SCALE_NONE) {
 			DRM_ERROR("ERROR : not allow yrgb ver scale\n");
@@ -370,14 +578,14 @@
 				false, vsu_mode, &vskiplines);
 	VOP_SCL_SET(vop, win, scale_yrgb_y, val);
 
-	VOP_SCL_SET_EXT(vop, win, vsd_yrgb_gt4, vskiplines == 4);
-	VOP_SCL_SET_EXT(vop, win, vsd_yrgb_gt2, vskiplines == 2);
+	VOP_SCL_SET(vop, win, vsd_yrgb_gt4, vskiplines == 4);
+	VOP_SCL_SET(vop, win, vsd_yrgb_gt2, vskiplines == 2);
 
-	VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode);
-	VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode);
-	VOP_SCL_SET_EXT(vop, win, yrgb_hsd_mode, SCALE_DOWN_BIL);
-	VOP_SCL_SET_EXT(vop, win, yrgb_vsd_mode, SCALE_DOWN_BIL);
-	VOP_SCL_SET_EXT(vop, win, yrgb_vsu_mode, vsu_mode);
+	VOP_SCL_SET(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode);
+	VOP_SCL_SET(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode);
+	VOP_SCL_SET(vop, win, yrgb_hsd_mode, SCALE_DOWN_BIL);
+	VOP_SCL_SET(vop, win, yrgb_vsd_mode, SCALE_DOWN_BIL);
+	VOP_SCL_SET(vop, win, yrgb_vsu_mode, vsu_mode);
 	if (is_yuv) {
 		val = scl_vop_cal_scale(cbcr_hor_scl_mode, cbcr_src_w,
 					dst_w, true, 0, NULL);
@@ -386,13 +594,13 @@
 					dst_h, false, vsu_mode, &vskiplines);
 		VOP_SCL_SET(vop, win, scale_cbcr_y, val);
 
-		VOP_SCL_SET_EXT(vop, win, vsd_cbcr_gt4, vskiplines == 4);
-		VOP_SCL_SET_EXT(vop, win, vsd_cbcr_gt2, vskiplines == 2);
-		VOP_SCL_SET_EXT(vop, win, cbcr_hor_scl_mode, cbcr_hor_scl_mode);
-		VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, cbcr_ver_scl_mode);
-		VOP_SCL_SET_EXT(vop, win, cbcr_hsd_mode, SCALE_DOWN_BIL);
-		VOP_SCL_SET_EXT(vop, win, cbcr_vsd_mode, SCALE_DOWN_BIL);
-		VOP_SCL_SET_EXT(vop, win, cbcr_vsu_mode, vsu_mode);
+		VOP_SCL_SET(vop, win, vsd_cbcr_gt4, vskiplines == 4);
+		VOP_SCL_SET(vop, win, vsd_cbcr_gt2, vskiplines == 2);
+		VOP_SCL_SET(vop, win, cbcr_hor_scl_mode, cbcr_hor_scl_mode);
+		VOP_SCL_SET(vop, win, cbcr_ver_scl_mode, cbcr_ver_scl_mode);
+		VOP_SCL_SET(vop, win, cbcr_hsd_mode, SCALE_DOWN_BIL);
+		VOP_SCL_SET(vop, win, cbcr_vsd_mode, SCALE_DOWN_BIL);
+		VOP_SCL_SET(vop, win, cbcr_vsu_mode, vsu_mode);
 	}
 }
 
@@ -405,7 +613,8 @@
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
 
-	VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 1);
+	vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK,
+		       DSP_HOLD_VALID_INTR_EN(1));
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 }
@@ -419,7 +628,8 @@
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
 
-	VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 0);
+	vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK,
+		       DSP_HOLD_VALID_INTR_EN(0));
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 }
@@ -482,7 +692,7 @@
 
 	enable_irq(vop->irq);
 
-	drm_crtc_vblank_on(crtc);
+	drm_vblank_on(vop->drm_dev, vop->pipe);
 
 	return;
 
@@ -494,14 +704,14 @@
 	clk_disable(vop->hclk);
 }
 
-static void vop_crtc_disable(struct drm_crtc *crtc)
+static void vop_disable(struct drm_crtc *crtc)
 {
 	struct vop *vop = to_vop(crtc);
 
 	if (!vop->is_enabled)
 		return;
 
-	drm_crtc_vblank_off(crtc);
+	drm_vblank_off(crtc->dev, vop->pipe);
 
 	/*
 	 * Vop standby will take effect at end of current frame,
@@ -538,188 +748,224 @@
 	pm_runtime_put(vop->dev);
 }
 
-static void vop_plane_destroy(struct drm_plane *plane)
+/*
+ * Caller must hold vsync_mutex.
+ */
+static struct drm_framebuffer *vop_win_last_pending_fb(struct vop_win *vop_win)
 {
-	drm_plane_cleanup(plane);
+	struct vop_win_state *last;
+	struct vop_win_state *active = vop_win->active;
+
+	if (list_empty(&vop_win->pending))
+		return active ? active->fb : NULL;
+
+	last = list_last_entry(&vop_win->pending, struct vop_win_state, head);
+	return last ? last->fb : NULL;
 }
 
-static int vop_plane_atomic_check(struct drm_plane *plane,
-			   struct drm_plane_state *state)
+/*
+ * Caller must hold vsync_mutex.
+ */
+static int vop_win_queue_fb(struct vop_win *vop_win,
+			    struct drm_framebuffer *fb, dma_addr_t yrgb_mst,
+			    struct drm_pending_vblank_event *event)
 {
-	struct drm_crtc *crtc = state->crtc;
-	struct drm_framebuffer *fb = state->fb;
+	struct vop_win_state *state;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	state->fb = fb;
+	state->yrgb_mst = yrgb_mst;
+	state->event = event;
+
+	list_add_tail(&state->head, &vop_win->pending);
+
+	return 0;
+}
+
+static int vop_update_plane_event(struct drm_plane *plane,
+				  struct drm_crtc *crtc,
+				  struct drm_framebuffer *fb, int crtc_x,
+				  int crtc_y, unsigned int crtc_w,
+				  unsigned int crtc_h, uint32_t src_x,
+				  uint32_t src_y, uint32_t src_w,
+				  uint32_t src_h,
+				  struct drm_pending_vblank_event *event)
+{
 	struct vop_win *vop_win = to_vop_win(plane);
-	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
 	const struct vop_win_data *win = vop_win->data;
+	struct vop *vop = to_vop(crtc);
+	struct drm_gem_object *obj;
+	struct rockchip_gem_object *rk_obj;
+	struct drm_gem_object *uv_obj;
+	struct rockchip_gem_object *rk_uv_obj;
+	unsigned long offset;
+	unsigned int actual_w;
+	unsigned int actual_h;
+	unsigned int dsp_stx;
+	unsigned int dsp_sty;
+	unsigned int y_vir_stride;
+	unsigned int uv_vir_stride = 0;
+	dma_addr_t yrgb_mst;
+	dma_addr_t uv_mst = 0;
+	enum vop_data_format format;
+	uint32_t val;
+	bool is_alpha;
+	bool rb_swap;
+	bool is_yuv;
 	bool visible;
 	int ret;
-	struct drm_rect *dest = &vop_plane_state->dest;
-	struct drm_rect *src = &vop_plane_state->src;
-	struct drm_rect clip;
+	struct drm_rect dest = {
+		.x1 = crtc_x,
+		.y1 = crtc_y,
+		.x2 = crtc_x + crtc_w,
+		.y2 = crtc_y + crtc_h,
+	};
+	struct drm_rect src = {
+		/* 16.16 fixed point */
+		.x1 = src_x,
+		.y1 = src_y,
+		.x2 = src_x + src_w,
+		.y2 = src_y + src_h,
+	};
+	const struct drm_rect clip = {
+		.x2 = crtc->mode.hdisplay,
+		.y2 = crtc->mode.vdisplay,
+	};
+	bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
 	int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
 					DRM_PLANE_HELPER_NO_SCALING;
 	int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
 					DRM_PLANE_HELPER_NO_SCALING;
 
-	crtc = crtc ? crtc : plane->state->crtc;
-	/*
-	 * Both crtc or plane->state->crtc can be null.
-	 */
-	if (!crtc || !fb)
-		goto out_disable;
-	src->x1 = state->src_x;
-	src->y1 = state->src_y;
-	src->x2 = state->src_x + state->src_w;
-	src->y2 = state->src_y + state->src_h;
-	dest->x1 = state->crtc_x;
-	dest->y1 = state->crtc_y;
-	dest->x2 = state->crtc_x + state->crtc_w;
-	dest->y2 = state->crtc_y + state->crtc_h;
-
-	clip.x1 = 0;
-	clip.y1 = 0;
-	clip.x2 = crtc->mode.hdisplay;
-	clip.y2 = crtc->mode.vdisplay;
-
-	ret = drm_plane_helper_check_update(plane, crtc, state->fb,
-					    src, dest, &clip,
+	ret = drm_plane_helper_check_update(plane, crtc, fb,
+					    &src, &dest, &clip,
 					    min_scale,
 					    max_scale,
-					    true, true, &visible);
+					    can_position, false, &visible);
 	if (ret)
 		return ret;
 
 	if (!visible)
-		goto out_disable;
+		return 0;
 
-	vop_plane_state->format = vop_convert_format(fb->pixel_format);
-	if (vop_plane_state->format < 0)
-		return vop_plane_state->format;
+	is_alpha = is_alpha_support(fb->pixel_format);
+	rb_swap = has_rb_swapped(fb->pixel_format);
+	is_yuv = is_yuv_support(fb->pixel_format);
 
-	/*
-	 * Src.x1 can be odd when do clip, but yuv plane start point
-	 * need align with 2 pixel.
-	 */
-	if (is_yuv_support(fb->pixel_format) && ((src->x1 >> 16) % 2))
-		return -EINVAL;
-
-	vop_plane_state->enable = true;
-
-	return 0;
-
-out_disable:
-	vop_plane_state->enable = false;
-	return 0;
-}
-
-static void vop_plane_atomic_disable(struct drm_plane *plane,
-				     struct drm_plane_state *old_state)
-{
-	struct vop_plane_state *vop_plane_state = to_vop_plane_state(old_state);
-	struct vop_win *vop_win = to_vop_win(plane);
-	const struct vop_win_data *win = vop_win->data;
-	struct vop *vop = to_vop(old_state->crtc);
-
-	if (!old_state->crtc)
-		return;
-
-	spin_lock(&vop->reg_lock);
-
-	VOP_WIN_SET(vop, win, enable, 0);
-
-	spin_unlock(&vop->reg_lock);
-
-	vop_plane_state->enable = false;
-}
-
-static void vop_plane_atomic_update(struct drm_plane *plane,
-		struct drm_plane_state *old_state)
-{
-	struct drm_plane_state *state = plane->state;
-	struct drm_crtc *crtc = state->crtc;
-	struct vop_win *vop_win = to_vop_win(plane);
-	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
-	const struct vop_win_data *win = vop_win->data;
-	struct vop *vop = to_vop(state->crtc);
-	struct drm_framebuffer *fb = state->fb;
-	unsigned int actual_w, actual_h;
-	unsigned int dsp_stx, dsp_sty;
-	uint32_t act_info, dsp_info, dsp_st;
-	struct drm_rect *src = &vop_plane_state->src;
-	struct drm_rect *dest = &vop_plane_state->dest;
-	struct drm_gem_object *obj, *uv_obj;
-	struct rockchip_gem_object *rk_obj, *rk_uv_obj;
-	unsigned long offset;
-	dma_addr_t dma_addr;
-	uint32_t val;
-	bool rb_swap;
-
-	/*
-	 * can't update plane when vop is disabled.
-	 */
-	if (!crtc)
-		return;
-
-	if (WARN_ON(!vop->is_enabled))
-		return;
-
-	if (!vop_plane_state->enable) {
-		vop_plane_atomic_disable(plane, old_state);
-		return;
-	}
+	format = vop_convert_format(fb->pixel_format);
+	if (format < 0)
+		return format;
 
 	obj = rockchip_fb_get_gem_obj(fb, 0);
+	if (!obj) {
+		DRM_ERROR("fail to get rockchip gem object from framebuffer\n");
+		return -EINVAL;
+	}
+
 	rk_obj = to_rockchip_obj(obj);
 
-	actual_w = drm_rect_width(src) >> 16;
-	actual_h = drm_rect_height(src) >> 16;
-	act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
+	if (is_yuv) {
+		/*
+		 * Src.x1 can be odd when do clip, but yuv plane start point
+		 * need align with 2 pixel.
+		 */
+		val = (src.x1 >> 16) % 2;
+		src.x1 += val << 16;
+		src.x2 += val << 16;
+	}
 
-	dsp_info = (drm_rect_height(dest) - 1) << 16;
-	dsp_info |= (drm_rect_width(dest) - 1) & 0xffff;
+	actual_w = (src.x2 - src.x1) >> 16;
+	actual_h = (src.y2 - src.y1) >> 16;
 
-	dsp_stx = dest->x1 + crtc->mode.htotal - crtc->mode.hsync_start;
-	dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
-	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
+	dsp_stx = dest.x1 + crtc->mode.htotal - crtc->mode.hsync_start;
+	dsp_sty = dest.y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
 
-	offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
-	offset += (src->y1 >> 16) * fb->pitches[0];
-	vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
+	offset = (src.x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
+	offset += (src.y1 >> 16) * fb->pitches[0];
 
-	spin_lock(&vop->reg_lock);
+	yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
+	y_vir_stride = fb->pitches[0] >> 2;
 
-	VOP_WIN_SET(vop, win, format, vop_plane_state->format);
-	VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2);
-	VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
-	if (is_yuv_support(fb->pixel_format)) {
+	if (is_yuv) {
 		int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
 		int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
 		int bpp = drm_format_plane_cpp(fb->pixel_format, 1);
 
 		uv_obj = rockchip_fb_get_gem_obj(fb, 1);
+		if (!uv_obj) {
+			DRM_ERROR("fail to get uv object from framebuffer\n");
+			return -EINVAL;
+		}
 		rk_uv_obj = to_rockchip_obj(uv_obj);
+		uv_vir_stride = fb->pitches[1] >> 2;
 
-		offset = (src->x1 >> 16) * bpp / hsub;
-		offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
+		offset = (src.x1 >> 16) * bpp / hsub;
+		offset += (src.y1 >> 16) * fb->pitches[1] / vsub;
 
-		dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
-		VOP_WIN_SET(vop, win, uv_vir, fb->pitches[1] >> 2);
-		VOP_WIN_SET(vop, win, uv_mst, dma_addr);
+		uv_mst = rk_uv_obj->dma_addr + offset + fb->offsets[1];
+	}
+
+	/*
+	 * If this plane update changes the plane's framebuffer, (or more
+	 * precisely, if this update has a different framebuffer than the last
+	 * update), enqueue it so we can track when it completes.
+	 *
+	 * Only when we discover that this update has completed, can we
+	 * unreference any previous framebuffers.
+	 */
+	mutex_lock(&vop->vsync_mutex);
+	if (fb != vop_win_last_pending_fb(vop_win)) {
+		ret = drm_vblank_get(plane->dev, vop->pipe);
+		if (ret) {
+			DRM_ERROR("failed to get vblank, %d\n", ret);
+			mutex_unlock(&vop->vsync_mutex);
+			return ret;
+		}
+
+		drm_framebuffer_reference(fb);
+
+		ret = vop_win_queue_fb(vop_win, fb, yrgb_mst, event);
+		if (ret) {
+			drm_vblank_put(plane->dev, vop->pipe);
+			mutex_unlock(&vop->vsync_mutex);
+			return ret;
+		}
+
+		vop->vsync_work_pending = true;
+	}
+	mutex_unlock(&vop->vsync_mutex);
+
+	spin_lock(&vop->reg_lock);
+
+	VOP_WIN_SET(vop, win, format, format);
+	VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride);
+	VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst);
+	if (is_yuv) {
+		VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride);
+		VOP_WIN_SET(vop, win, uv_mst, uv_mst);
 	}
 
 	if (win->phy->scl)
 		scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
-				    drm_rect_width(dest), drm_rect_height(dest),
+				    dest.x2 - dest.x1, dest.y2 - dest.y1,
 				    fb->pixel_format);
 
-	VOP_WIN_SET(vop, win, act_info, act_info);
-	VOP_WIN_SET(vop, win, dsp_info, dsp_info);
-	VOP_WIN_SET(vop, win, dsp_st, dsp_st);
+	val = (actual_h - 1) << 16;
+	val |= (actual_w - 1) & 0xffff;
+	VOP_WIN_SET(vop, win, act_info, val);
 
-	rb_swap = has_rb_swapped(fb->pixel_format);
+	val = (dest.y2 - dest.y1 - 1) << 16;
+	val |= (dest.x2 - dest.x1 - 1) & 0xffff;
+	VOP_WIN_SET(vop, win, dsp_info, val);
+	val = dsp_sty << 16;
+	val |= dsp_stx & 0xffff;
+	VOP_WIN_SET(vop, win, dsp_st, val);
 	VOP_WIN_SET(vop, win, rb_swap, rb_swap);
 
-	if (is_alpha_support(fb->pixel_format)) {
+	if (is_alpha) {
 		VOP_WIN_SET(vop, win, dst_alpha_ctl,
 			    DST_FACTOR_M0(ALPHA_SRC_INVERSE));
 		val = SRC_ALPHA_EN(1) | SRC_COLOR_M0(ALPHA_SRC_PRE_MUL) |
@@ -733,70 +979,86 @@
 	}
 
 	VOP_WIN_SET(vop, win, enable, 1);
+
+	vop_cfg_done(vop);
 	spin_unlock(&vop->reg_lock);
+
+	return 0;
 }
 
-static const struct drm_plane_helper_funcs plane_helper_funcs = {
-	.atomic_check = vop_plane_atomic_check,
-	.atomic_update = vop_plane_atomic_update,
-	.atomic_disable = vop_plane_atomic_disable,
-};
-
-void vop_atomic_plane_reset(struct drm_plane *plane)
+static int vop_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+			    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+			    unsigned int crtc_w, unsigned int crtc_h,
+			    uint32_t src_x, uint32_t src_y, uint32_t src_w,
+			    uint32_t src_h)
 {
-	struct vop_plane_state *vop_plane_state =
-					to_vop_plane_state(plane->state);
-
-	if (plane->state && plane->state->fb)
-		drm_framebuffer_unreference(plane->state->fb);
-
-	kfree(vop_plane_state);
-	vop_plane_state = kzalloc(sizeof(*vop_plane_state), GFP_KERNEL);
-	if (!vop_plane_state)
-		return;
-
-	plane->state = &vop_plane_state->base;
-	plane->state->plane = plane;
+	return vop_update_plane_event(plane, crtc, fb, crtc_x, crtc_y, crtc_w,
+				      crtc_h, src_x, src_y, src_w, src_h,
+				      NULL);
 }
 
-struct drm_plane_state *
-vop_atomic_plane_duplicate_state(struct drm_plane *plane)
+static int vop_update_primary_plane(struct drm_crtc *crtc,
+				    struct drm_pending_vblank_event *event)
 {
-	struct vop_plane_state *old_vop_plane_state;
-	struct vop_plane_state *vop_plane_state;
+	unsigned int crtc_w, crtc_h;
 
-	if (WARN_ON(!plane->state))
-		return NULL;
+	crtc_w = crtc->primary->fb->width - crtc->x;
+	crtc_h = crtc->primary->fb->height - crtc->y;
 
-	old_vop_plane_state = to_vop_plane_state(plane->state);
-	vop_plane_state = kmemdup(old_vop_plane_state,
-				  sizeof(*vop_plane_state), GFP_KERNEL);
-	if (!vop_plane_state)
-		return NULL;
-
-	__drm_atomic_helper_plane_duplicate_state(plane,
-						  &vop_plane_state->base);
-
-	return &vop_plane_state->base;
+	return vop_update_plane_event(crtc->primary, crtc, crtc->primary->fb,
+				      0, 0, crtc_w, crtc_h, crtc->x << 16,
+				      crtc->y << 16, crtc_w << 16,
+				      crtc_h << 16, event);
 }
 
-static void vop_atomic_plane_destroy_state(struct drm_plane *plane,
-					   struct drm_plane_state *state)
+static int vop_disable_plane(struct drm_plane *plane)
 {
-	struct vop_plane_state *vop_state = to_vop_plane_state(state);
+	struct vop_win *vop_win = to_vop_win(plane);
+	const struct vop_win_data *win = vop_win->data;
+	struct vop *vop;
+	int ret;
 
-	__drm_atomic_helper_plane_destroy_state(plane, state);
+	if (!plane->crtc)
+		return 0;
 
-	kfree(vop_state);
+	vop = to_vop(plane->crtc);
+
+	ret = drm_vblank_get(plane->dev, vop->pipe);
+	if (ret) {
+		DRM_ERROR("failed to get vblank, %d\n", ret);
+		return ret;
+	}
+
+	mutex_lock(&vop->vsync_mutex);
+
+	ret = vop_win_queue_fb(vop_win, NULL, 0, NULL);
+	if (ret) {
+		drm_vblank_put(plane->dev, vop->pipe);
+		mutex_unlock(&vop->vsync_mutex);
+		return ret;
+	}
+
+	vop->vsync_work_pending = true;
+	mutex_unlock(&vop->vsync_mutex);
+
+	spin_lock(&vop->reg_lock);
+	VOP_WIN_SET(vop, win, enable, 0);
+	vop_cfg_done(vop);
+	spin_unlock(&vop->reg_lock);
+
+	return 0;
+}
+
+static void vop_plane_destroy(struct drm_plane *plane)
+{
+	vop_disable_plane(plane);
+	drm_plane_cleanup(plane);
 }
 
 static const struct drm_plane_funcs vop_plane_funcs = {
-	.update_plane	= drm_atomic_helper_update_plane,
-	.disable_plane	= drm_atomic_helper_disable_plane,
+	.update_plane = vop_update_plane,
+	.disable_plane = vop_disable_plane,
 	.destroy = vop_plane_destroy,
-	.reset = vop_atomic_plane_reset,
-	.atomic_duplicate_state = vop_atomic_plane_duplicate_state,
-	.atomic_destroy_state = vop_atomic_plane_destroy_state,
 };
 
 int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc,
@@ -805,24 +1067,8 @@
 {
 	struct vop *vop = to_vop(crtc);
 
-	if (WARN_ON(!vop->is_enabled))
-		return -EINVAL;
-
-	switch (connector_type) {
-	case DRM_MODE_CONNECTOR_LVDS:
-		VOP_CTRL_SET(vop, rgb_en, 1);
-		break;
-	case DRM_MODE_CONNECTOR_eDP:
-		VOP_CTRL_SET(vop, edp_en, 1);
-		break;
-	case DRM_MODE_CONNECTOR_HDMIA:
-		VOP_CTRL_SET(vop, hdmi_en, 1);
-		break;
-	default:
-		DRM_ERROR("unsupport connector_type[%d]\n", connector_type);
-		return -EINVAL;
-	};
-	VOP_CTRL_SET(vop, out_mode, out_mode);
+	vop->connector_type = connector_type;
+	vop->connector_out_mode = out_mode;
 
 	return 0;
 }
@@ -833,12 +1079,12 @@
 	struct vop *vop = to_vop(crtc);
 	unsigned long flags;
 
-	if (WARN_ON(!vop->is_enabled))
+	if (!vop->is_enabled)
 		return -EPERM;
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
 
-	VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1);
+	vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(1));
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 
@@ -850,49 +1096,76 @@
 	struct vop *vop = to_vop(crtc);
 	unsigned long flags;
 
-	if (WARN_ON(!vop->is_enabled))
+	if (!vop->is_enabled)
 		return;
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
-
-	VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
-
+	vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(0));
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 }
 
-static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
-{
-	struct vop *vop = to_vop(crtc);
-
-	reinit_completion(&vop->wait_update_complete);
-	WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100));
-}
-
 static const struct rockchip_crtc_funcs private_crtc_funcs = {
 	.enable_vblank = vop_crtc_enable_vblank,
 	.disable_vblank = vop_crtc_disable_vblank,
-	.wait_for_update = vop_crtc_wait_for_update,
 };
 
+static void vop_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		vop_enable(crtc);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		vop_disable(crtc);
+		break;
+	default:
+		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+		break;
+	}
+}
+
+static void vop_crtc_prepare(struct drm_crtc *crtc)
+{
+	vop_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
 				const struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 {
-	struct vop *vop = to_vop(crtc);
-
 	if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
 		return false;
 
-	adjusted_mode->clock =
-		clk_round_rate(vop->dclk, mode->clock * 1000) / 1000;
-
 	return true;
 }
 
-static void vop_crtc_enable(struct drm_crtc *crtc)
+static int vop_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+				  struct drm_framebuffer *old_fb)
+{
+	int ret;
+
+	crtc->x = x;
+	crtc->y = y;
+
+	ret = vop_update_primary_plane(crtc, NULL);
+	if (ret < 0) {
+		DRM_ERROR("fail to update plane\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int vop_crtc_mode_set(struct drm_crtc *crtc,
+			     struct drm_display_mode *mode,
+			     struct drm_display_mode *adjusted_mode,
+			     int x, int y, struct drm_framebuffer *fb)
 {
 	struct vop *vop = to_vop(crtc);
-	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
 	u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
 	u16 hdisplay = adjusted_mode->hdisplay;
 	u16 htotal = adjusted_mode->htotal;
@@ -903,44 +1176,32 @@
 	u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start;
 	u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start;
 	u16 vact_end = vact_st + vdisplay;
+	int ret, ret_clk;
 	uint32_t val;
 
-	vop_enable(crtc);
 	/*
-	 * If dclk rate is zero, mean that scanout is stop,
-	 * we don't need wait any more.
+	 * disable dclk to stop frame scan, so that we can safe config mode and
+	 * enable iommu.
 	 */
-	if (clk_get_rate(vop->dclk)) {
-		/*
-		 * Rk3288 vop timing register is immediately, when configure
-		 * display timing on display time, may cause tearing.
-		 *
-		 * Vop standby will take effect at end of current frame,
-		 * if dsp hold valid irq happen, it means standby complete.
-		 *
-		 * mode set:
-		 *    standby and wait complete --> |----
-		 *                                  | display time
-		 *                                  |----
-		 *                                  |---> dsp hold irq
-		 *     configure display timing --> |
-		 *         standby exit             |
-		 *                                  | new frame start.
-		 */
+	clk_disable(vop->dclk);
 
-		reinit_completion(&vop->dsp_hold_completion);
-		vop_dsp_hold_valid_irq_enable(vop);
-
-		spin_lock(&vop->reg_lock);
-
-		VOP_CTRL_SET(vop, standby, 1);
-
-		spin_unlock(&vop->reg_lock);
-
-		wait_for_completion(&vop->dsp_hold_completion);
-
-		vop_dsp_hold_valid_irq_disable(vop);
-	}
+	switch (vop->connector_type) {
+	case DRM_MODE_CONNECTOR_LVDS:
+		VOP_CTRL_SET(vop, rgb_en, 1);
+		break;
+	case DRM_MODE_CONNECTOR_eDP:
+		VOP_CTRL_SET(vop, edp_en, 1);
+		break;
+	case DRM_MODE_CONNECTOR_HDMIA:
+		VOP_CTRL_SET(vop, hdmi_en, 1);
+		break;
+	default:
+		DRM_ERROR("unsupport connector_type[%d]\n",
+			  vop->connector_type);
+		ret = -EINVAL;
+		goto out;
+	};
+	VOP_CTRL_SET(vop, out_mode, vop->connector_out_mode);
 
 	val = 0x8;
 	val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
@@ -959,119 +1220,211 @@
 	VOP_CTRL_SET(vop, vact_st_end, val);
 	VOP_CTRL_SET(vop, vpost_st_end, val);
 
+	ret = vop_crtc_mode_set_base(crtc, x, y, fb);
+	if (ret)
+		goto out;
+
+	/*
+	 * reset dclk, take all mode config affect, so the clk would run in
+	 * correct frame.
+	 */
+	reset_control_assert(vop->dclk_rst);
+	usleep_range(10, 20);
+	reset_control_deassert(vop->dclk_rst);
+
 	clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
-
-	VOP_CTRL_SET(vop, standby, 0);
-}
-
-static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
-				  struct drm_crtc_state *old_crtc_state)
-{
-	struct vop *vop = to_vop(crtc);
-
-	if (WARN_ON(!vop->is_enabled))
-		return;
-
-	spin_lock(&vop->reg_lock);
-
-	vop_cfg_done(vop);
-
-	spin_unlock(&vop->reg_lock);
-}
-
-static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
-				  struct drm_crtc_state *old_crtc_state)
-{
-	struct vop *vop = to_vop(crtc);
-
-	if (crtc->state->event) {
-		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-
-		vop->event = crtc->state->event;
-		crtc->state->event = NULL;
+out:
+	ret_clk = clk_enable(vop->dclk);
+	if (ret_clk < 0) {
+		dev_err(vop->dev, "failed to enable dclk - %d\n", ret_clk);
+		return ret_clk;
 	}
+
+	return ret;
+}
+
+static void vop_crtc_commit(struct drm_crtc *crtc)
+{
 }
 
 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
-	.enable = vop_crtc_enable,
-	.disable = vop_crtc_disable,
+	.dpms = vop_crtc_dpms,
+	.prepare = vop_crtc_prepare,
 	.mode_fixup = vop_crtc_mode_fixup,
-	.atomic_flush = vop_crtc_atomic_flush,
-	.atomic_begin = vop_crtc_atomic_begin,
+	.mode_set = vop_crtc_mode_set,
+	.mode_set_base = vop_crtc_mode_set_base,
+	.commit = vop_crtc_commit,
 };
 
+static int vop_crtc_page_flip(struct drm_crtc *crtc,
+			      struct drm_framebuffer *fb,
+			      struct drm_pending_vblank_event *event,
+			      uint32_t page_flip_flags)
+{
+	struct vop *vop = to_vop(crtc);
+	struct drm_framebuffer *old_fb = crtc->primary->fb;
+	int ret;
+
+	/* when the page flip is requested, crtc should be on */
+	if (!vop->is_enabled) {
+		DRM_DEBUG("page flip request rejected because crtc is off.\n");
+		return 0;
+	}
+
+	crtc->primary->fb = fb;
+
+	ret = vop_update_primary_plane(crtc, event);
+	if (ret)
+		crtc->primary->fb = old_fb;
+
+	return ret;
+}
+
+static void vop_win_state_complete(struct vop_win *vop_win,
+				   struct vop_win_state *state)
+{
+	struct vop *vop = vop_win->vop;
+	struct drm_crtc *crtc = &vop->crtc;
+	struct drm_device *drm = crtc->dev;
+	unsigned long flags;
+
+	if (state->event) {
+		spin_lock_irqsave(&drm->event_lock, flags);
+		drm_crtc_send_vblank_event(crtc, state->event);
+		spin_unlock_irqrestore(&drm->event_lock, flags);
+	}
+
+	list_del(&state->head);
+	drm_vblank_put(crtc->dev, vop->pipe);
+}
+
 static void vop_crtc_destroy(struct drm_crtc *crtc)
 {
 	drm_crtc_cleanup(crtc);
 }
 
 static const struct drm_crtc_funcs vop_crtc_funcs = {
-	.set_config = drm_atomic_helper_set_config,
-	.page_flip = drm_atomic_helper_page_flip,
+	.set_config = drm_crtc_helper_set_config,
+	.page_flip = vop_crtc_page_flip,
 	.destroy = vop_crtc_destroy,
-	.reset = drm_atomic_helper_crtc_reset,
-	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
-static bool vop_win_pending_is_complete(struct vop_win *vop_win)
+static bool vop_win_state_is_active(struct vop_win *vop_win,
+				    struct vop_win_state *state)
 {
-	struct drm_plane *plane = &vop_win->base;
-	struct vop_plane_state *state = to_vop_plane_state(plane->state);
-	dma_addr_t yrgb_mst;
+	bool active = false;
 
-	if (!state->enable)
-		return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
+	if (state->fb) {
+		dma_addr_t yrgb_mst;
 
-	yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
+		/* check yrgb_mst to tell if pending_fb is now front */
+		yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
 
-	return yrgb_mst == state->yrgb_mst;
+		active = (yrgb_mst == state->yrgb_mst);
+	} else {
+		bool enabled;
+
+		/* if enable bit is clear, plane is now disabled */
+		enabled = VOP_WIN_GET(vop_win->vop, vop_win->data, enable);
+
+		active = (enabled == 0);
+	}
+
+	return active;
 }
 
-static void vop_handle_vblank(struct vop *vop)
+static void vop_win_state_destroy(struct vop_win_state *state)
 {
-	struct drm_device *drm = vop->drm_dev;
-	struct drm_crtc *crtc = &vop->crtc;
-	unsigned long flags;
-	int i;
+	struct drm_framebuffer *fb = state->fb;
 
-	for (i = 0; i < vop->data->win_size; i++) {
-		if (!vop_win_pending_is_complete(&vop->win[i]))
-			return;
+	if (fb)
+		drm_framebuffer_unreference(fb);
+
+	kfree(state);
+}
+
+static void vop_win_update_state(struct vop_win *vop_win)
+{
+	struct vop_win_state *state, *n, *new_active = NULL;
+
+	/* Check if any pending states are now active */
+	list_for_each_entry(state, &vop_win->pending, head)
+		if (vop_win_state_is_active(vop_win, state)) {
+			new_active = state;
+			break;
+		}
+
+	if (!new_active)
+		return;
+
+	/*
+	 * Destroy any 'skipped' pending states - states that were queued
+	 * before the newly active state.
+	 */
+	list_for_each_entry_safe(state, n, &vop_win->pending, head) {
+		if (state == new_active)
+			break;
+		vop_win_state_complete(vop_win, state);
+		vop_win_state_destroy(state);
 	}
 
-	if (vop->event) {
-		spin_lock_irqsave(&drm->event_lock, flags);
+	vop_win_state_complete(vop_win, new_active);
 
-		drm_crtc_send_vblank_event(crtc, vop->event);
-		drm_crtc_vblank_put(crtc);
-		vop->event = NULL;
+	if (vop_win->active)
+		vop_win_state_destroy(vop_win->active);
+	vop_win->active = new_active;
+}
 
-		spin_unlock_irqrestore(&drm->event_lock, flags);
+static bool vop_win_has_pending_state(struct vop_win *vop_win)
+{
+	return !list_empty(&vop_win->pending);
+}
+
+static irqreturn_t vop_isr_thread(int irq, void *data)
+{
+	struct vop *vop = data;
+	const struct vop_data *vop_data = vop->data;
+	unsigned int i;
+
+	mutex_lock(&vop->vsync_mutex);
+
+	if (!vop->vsync_work_pending)
+		goto done;
+
+	vop->vsync_work_pending = false;
+
+	for (i = 0; i < vop_data->win_size; i++) {
+		struct vop_win *vop_win = &vop->win[i];
+
+		vop_win_update_state(vop_win);
+		if (vop_win_has_pending_state(vop_win))
+			vop->vsync_work_pending = true;
 	}
-	if (!completion_done(&vop->wait_update_complete))
-		complete(&vop->wait_update_complete);
+
+done:
+	mutex_unlock(&vop->vsync_mutex);
+
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t vop_isr(int irq, void *data)
 {
 	struct vop *vop = data;
-	struct drm_crtc *crtc = &vop->crtc;
-	uint32_t active_irqs;
+	uint32_t intr0_reg, active_irqs;
 	unsigned long flags;
 	int ret = IRQ_NONE;
 
 	/*
-	 * interrupt register has interrupt status, enable and clear bits, we
+	 * INTR_CTRL0 register has interrupt status, enable and clear bits, we
 	 * must hold irq_lock to avoid a race with enable/disable_vblank().
 	*/
 	spin_lock_irqsave(&vop->irq_lock, flags);
-
-	active_irqs = VOP_INTR_GET_TYPE(vop, status, INTR_MASK);
+	intr0_reg = vop_readl(vop, INTR_CTRL0);
+	active_irqs = intr0_reg & INTR_MASK;
 	/* Clear all active interrupt sources */
 	if (active_irqs)
-		VOP_INTR_SET_TYPE(vop, clear, active_irqs, 1);
-
+		vop_writel(vop, INTR_CTRL0,
+			   intr0_reg | (active_irqs << INTR_CLR_SHIFT));
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 
 	/* This is expected for vop iommu irqs, since the irq is shared */
@@ -1085,10 +1438,9 @@
 	}
 
 	if (active_irqs & FS_INTR) {
-		drm_crtc_handle_vblank(crtc);
-		vop_handle_vblank(vop);
+		drm_handle_vblank(vop->drm_dev, vop->pipe);
 		active_irqs &= ~FS_INTR;
-		ret = IRQ_HANDLED;
+		ret = (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
 	}
 
 	/* Unhandled irqs are spurious. */
@@ -1133,7 +1485,6 @@
 		}
 
 		plane = &vop_win->base;
-		drm_plane_helper_add(plane, &plane_helper_funcs);
 		if (plane->type == DRM_PLANE_TYPE_PRIMARY)
 			primary = plane;
 		else if (plane->type == DRM_PLANE_TYPE_CURSOR)
@@ -1169,7 +1520,6 @@
 			DRM_ERROR("failed to initialize overlay plane\n");
 			goto err_cleanup_crtc;
 		}
-		drm_plane_helper_add(&vop_win->base, &plane_helper_funcs);
 	}
 
 	port = of_get_child_by_name(dev->of_node, "port");
@@ -1180,9 +1530,9 @@
 	}
 
 	init_completion(&vop->dsp_hold_completion);
-	init_completion(&vop->wait_update_complete);
 	crtc->port = port;
-	rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
+	vop->pipe = drm_crtc_index(crtc);
+	rockchip_register_crtc_funcs(drm_dev, &private_crtc_funcs, vop->pipe);
 
 	return 0;
 
@@ -1198,7 +1548,7 @@
 {
 	struct drm_crtc *crtc = &vop->crtc;
 
-	rockchip_unregister_crtc_funcs(crtc);
+	rockchip_unregister_crtc_funcs(vop->drm_dev, vop->pipe);
 	of_node_put(crtc->port);
 	drm_crtc_cleanup(crtc);
 }
@@ -1314,12 +1664,14 @@
 
 		vop_win->data = win_data;
 		vop_win->vop = vop;
+		INIT_LIST_HEAD(&vop_win->pending);
 	}
 }
 
 static int vop_bind(struct device *dev, struct device *master, void *data)
 {
 	struct platform_device *pdev = to_platform_device(dev);
+	const struct of_device_id *of_id;
 	const struct vop_data *vop_data;
 	struct drm_device *drm_dev = data;
 	struct vop *vop;
@@ -1327,7 +1679,8 @@
 	size_t alloc_size;
 	int ret, irq;
 
-	vop_data = of_device_get_match_data(dev);
+	of_id = of_match_device(vop_driver_dt_match, dev);
+	vop_data = of_id->data;
 	if (!vop_data)
 		return -ENODEV;
 
@@ -1372,8 +1725,8 @@
 
 	mutex_init(&vop->vsync_mutex);
 
-	ret = devm_request_irq(dev, vop->irq, vop_isr,
-			       IRQF_SHARED, dev_name(dev), vop);
+	ret = devm_request_threaded_irq(dev, vop->irq, vop_isr, vop_isr_thread,
+					IRQF_SHARED, dev_name(dev), vop);
 	if (ret)
 		return ret;
 
@@ -1396,8 +1749,42 @@
 	vop_destroy_crtc(vop);
 }
 
-const struct component_ops vop_component_ops = {
+static const struct component_ops vop_component_ops = {
 	.bind = vop_bind,
 	.unbind = vop_unbind,
 };
-EXPORT_SYMBOL_GPL(vop_component_ops);
+
+static int vop_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	if (!dev->of_node) {
+		dev_err(dev, "can't find vop devices\n");
+		return -ENODEV;
+	}
+
+	return component_add(dev, &vop_component_ops);
+}
+
+static int vop_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &vop_component_ops);
+
+	return 0;
+}
+
+struct platform_driver vop_platform_driver = {
+	.probe = vop_probe,
+	.remove = vop_remove,
+	.driver = {
+		.name = "rockchip-vop",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(vop_driver_dt_match),
+	},
+};
+
+module_platform_driver(vop_platform_driver);
+
+MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
+MODULE_DESCRIPTION("ROCKCHIP VOP Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 071ff0b..a2d4ddb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -15,125 +15,111 @@
 #ifndef _ROCKCHIP_DRM_VOP_H
 #define _ROCKCHIP_DRM_VOP_H
 
-enum vop_data_format {
-	VOP_FMT_ARGB8888 = 0,
-	VOP_FMT_RGB888,
-	VOP_FMT_RGB565,
-	VOP_FMT_YUV420SP = 4,
-	VOP_FMT_YUV422SP,
-	VOP_FMT_YUV444SP,
-};
-
-struct vop_reg_data {
-	uint32_t offset;
-	uint32_t value;
-};
-
-struct vop_reg {
-	uint32_t offset;
-	uint32_t shift;
-	uint32_t mask;
-};
-
-struct vop_ctrl {
-	struct vop_reg standby;
-	struct vop_reg data_blank;
-	struct vop_reg gate_en;
-	struct vop_reg mmu_en;
-	struct vop_reg rgb_en;
-	struct vop_reg edp_en;
-	struct vop_reg hdmi_en;
-	struct vop_reg mipi_en;
-	struct vop_reg out_mode;
-	struct vop_reg dither_down;
-	struct vop_reg dither_up;
-	struct vop_reg pin_pol;
-
-	struct vop_reg htotal_pw;
-	struct vop_reg hact_st_end;
-	struct vop_reg vtotal_pw;
-	struct vop_reg vact_st_end;
-	struct vop_reg hpost_st_end;
-	struct vop_reg vpost_st_end;
-
-	struct vop_reg cfg_done;
-};
-
-struct vop_intr {
-	const int *intrs;
-	uint32_t nintrs;
-	struct vop_reg enable;
-	struct vop_reg clear;
-	struct vop_reg status;
-};
-
-struct vop_scl_extension {
-	struct vop_reg cbcr_vsd_mode;
-	struct vop_reg cbcr_vsu_mode;
-	struct vop_reg cbcr_hsd_mode;
-	struct vop_reg cbcr_ver_scl_mode;
-	struct vop_reg cbcr_hor_scl_mode;
-	struct vop_reg yrgb_vsd_mode;
-	struct vop_reg yrgb_vsu_mode;
-	struct vop_reg yrgb_hsd_mode;
-	struct vop_reg yrgb_ver_scl_mode;
-	struct vop_reg yrgb_hor_scl_mode;
-	struct vop_reg line_load_mode;
-	struct vop_reg cbcr_axi_gather_num;
-	struct vop_reg yrgb_axi_gather_num;
-	struct vop_reg vsd_cbcr_gt2;
-	struct vop_reg vsd_cbcr_gt4;
-	struct vop_reg vsd_yrgb_gt2;
-	struct vop_reg vsd_yrgb_gt4;
-	struct vop_reg bic_coe_sel;
-	struct vop_reg cbcr_axi_gather_en;
-	struct vop_reg yrgb_axi_gather_en;
-	struct vop_reg lb_mode;
-};
-
-struct vop_scl_regs {
-	const struct vop_scl_extension *ext;
-
-	struct vop_reg scale_yrgb_x;
-	struct vop_reg scale_yrgb_y;
-	struct vop_reg scale_cbcr_x;
-	struct vop_reg scale_cbcr_y;
-};
-
-struct vop_win_phy {
-	const struct vop_scl_regs *scl;
-	const uint32_t *data_formats;
-	uint32_t nformats;
-
-	struct vop_reg enable;
-	struct vop_reg format;
-	struct vop_reg rb_swap;
-	struct vop_reg act_info;
-	struct vop_reg dsp_info;
-	struct vop_reg dsp_st;
-	struct vop_reg yrgb_mst;
-	struct vop_reg uv_mst;
-	struct vop_reg yrgb_vir;
-	struct vop_reg uv_vir;
-
-	struct vop_reg dst_alpha_ctl;
-	struct vop_reg src_alpha_ctl;
-};
-
-struct vop_win_data {
-	uint32_t base;
-	const struct vop_win_phy *phy;
-	enum drm_plane_type type;
-};
-
-struct vop_data {
-	const struct vop_reg_data *init_table;
-	unsigned int table_size;
-	const struct vop_ctrl *ctrl;
-	const struct vop_intr *intr;
-	const struct vop_win_data *win;
-	unsigned int win_size;
-};
+/* register definition */
+#define REG_CFG_DONE			0x0000
+#define VERSION_INFO			0x0004
+#define SYS_CTRL			0x0008
+#define SYS_CTRL1			0x000c
+#define DSP_CTRL0			0x0010
+#define DSP_CTRL1			0x0014
+#define DSP_BG				0x0018
+#define MCU_CTRL			0x001c
+#define INTR_CTRL0			0x0020
+#define INTR_CTRL1			0x0024
+#define WIN0_CTRL0			0x0030
+#define WIN0_CTRL1			0x0034
+#define WIN0_COLOR_KEY			0x0038
+#define WIN0_VIR			0x003c
+#define WIN0_YRGB_MST			0x0040
+#define WIN0_CBR_MST			0x0044
+#define WIN0_ACT_INFO			0x0048
+#define WIN0_DSP_INFO			0x004c
+#define WIN0_DSP_ST			0x0050
+#define WIN0_SCL_FACTOR_YRGB		0x0054
+#define WIN0_SCL_FACTOR_CBR		0x0058
+#define WIN0_SCL_OFFSET			0x005c
+#define WIN0_SRC_ALPHA_CTRL		0x0060
+#define WIN0_DST_ALPHA_CTRL		0x0064
+#define WIN0_FADING_CTRL		0x0068
+/* win1 register */
+#define WIN1_CTRL0			0x0070
+#define WIN1_CTRL1			0x0074
+#define WIN1_COLOR_KEY			0x0078
+#define WIN1_VIR			0x007c
+#define WIN1_YRGB_MST			0x0080
+#define WIN1_CBR_MST			0x0084
+#define WIN1_ACT_INFO			0x0088
+#define WIN1_DSP_INFO			0x008c
+#define WIN1_DSP_ST			0x0090
+#define WIN1_SCL_FACTOR_YRGB		0x0094
+#define WIN1_SCL_FACTOR_CBR		0x0098
+#define WIN1_SCL_OFFSET			0x009c
+#define WIN1_SRC_ALPHA_CTRL		0x00a0
+#define WIN1_DST_ALPHA_CTRL		0x00a4
+#define WIN1_FADING_CTRL		0x00a8
+/* win2 register */
+#define WIN2_CTRL0			0x00b0
+#define WIN2_CTRL1			0x00b4
+#define WIN2_VIR0_1			0x00b8
+#define WIN2_VIR2_3			0x00bc
+#define WIN2_MST0			0x00c0
+#define WIN2_DSP_INFO0			0x00c4
+#define WIN2_DSP_ST0			0x00c8
+#define WIN2_COLOR_KEY			0x00cc
+#define WIN2_MST1			0x00d0
+#define WIN2_DSP_INFO1			0x00d4
+#define WIN2_DSP_ST1			0x00d8
+#define WIN2_SRC_ALPHA_CTRL		0x00dc
+#define WIN2_MST2			0x00e0
+#define WIN2_DSP_INFO2			0x00e4
+#define WIN2_DSP_ST2			0x00e8
+#define WIN2_DST_ALPHA_CTRL		0x00ec
+#define WIN2_MST3			0x00f0
+#define WIN2_DSP_INFO3			0x00f4
+#define WIN2_DSP_ST3			0x00f8
+#define WIN2_FADING_CTRL		0x00fc
+/* win3 register */
+#define WIN3_CTRL0			0x0100
+#define WIN3_CTRL1			0x0104
+#define WIN3_VIR0_1			0x0108
+#define WIN3_VIR2_3			0x010c
+#define WIN3_MST0			0x0110
+#define WIN3_DSP_INFO0			0x0114
+#define WIN3_DSP_ST0			0x0118
+#define WIN3_COLOR_KEY			0x011c
+#define WIN3_MST1			0x0120
+#define WIN3_DSP_INFO1			0x0124
+#define WIN3_DSP_ST1			0x0128
+#define WIN3_SRC_ALPHA_CTRL		0x012c
+#define WIN3_MST2			0x0130
+#define WIN3_DSP_INFO2			0x0134
+#define WIN3_DSP_ST2			0x0138
+#define WIN3_DST_ALPHA_CTRL		0x013c
+#define WIN3_MST3			0x0140
+#define WIN3_DSP_INFO3			0x0144
+#define WIN3_DSP_ST3			0x0148
+#define WIN3_FADING_CTRL		0x014c
+/* hwc register */
+#define HWC_CTRL0			0x0150
+#define HWC_CTRL1			0x0154
+#define HWC_MST				0x0158
+#define HWC_DSP_ST			0x015c
+#define HWC_SRC_ALPHA_CTRL		0x0160
+#define HWC_DST_ALPHA_CTRL		0x0164
+#define HWC_FADING_CTRL			0x0168
+/* post process register */
+#define POST_DSP_HACT_INFO		0x0170
+#define POST_DSP_VACT_INFO		0x0174
+#define POST_SCL_FACTOR_YRGB		0x0178
+#define POST_SCL_CTRL			0x0180
+#define POST_DSP_VACT_INFO_F1		0x0184
+#define DSP_HTOTAL_HS_END		0x0188
+#define DSP_HACT_ST_END			0x018c
+#define DSP_VTOTAL_VS_END		0x0190
+#define DSP_VACT_ST_END			0x0194
+#define DSP_VS_ST_END_F1		0x0198
+#define DSP_VACT_ST_END_F1		0x019c
+/* register definition end */
 
 /* interrupt define */
 #define DSP_HOLD_VALID_INTR		(1 << 0)
@@ -247,11 +233,6 @@
 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
 }
 
-static inline uint16_t scl_cal_scale2(int src, int dst)
-{
-	return ((src - 1) << 12) / (dst - 1);
-}
-
 #define GET_SCL_FT_BILI_DN(src, dst)	scl_cal_scale(src, dst, 12)
 #define GET_SCL_FT_BILI_UP(src, dst)	scl_cal_scale(src, dst, 16)
 #define GET_SCL_FT_BIC(src, dst)	scl_cal_scale(src, dst, 16)
@@ -305,5 +286,4 @@
 	return lb_mode;
 }
 
-extern const struct component_ops vop_component_ops;
 #endif /* _ROCKCHIP_DRM_VOP_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
deleted file mode 100644
index 3166b46..0000000
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
- * Author:Mark Yao <mark.yao@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <drm/drmP.h>
-
-#include <linux/kernel.h>
-#include <linux/component.h>
-
-#include "rockchip_drm_vop.h"
-#include "rockchip_vop_reg.h"
-
-#define VOP_REG(off, _mask, s) \
-		{.offset = off, \
-		 .mask = _mask, \
-		 .shift = s,}
-
-static const uint32_t formats_win_full[] = {
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_RGB888,
-	DRM_FORMAT_BGR888,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_BGR565,
-	DRM_FORMAT_NV12,
-	DRM_FORMAT_NV16,
-	DRM_FORMAT_NV24,
-};
-
-static const uint32_t formats_win_lite[] = {
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_RGB888,
-	DRM_FORMAT_BGR888,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_BGR565,
-};
-
-static const struct vop_scl_extension rk3288_win_full_scl_ext = {
-	.cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
-	.cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
-	.cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
-	.cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
-	.cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
-	.yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
-	.yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
-	.yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
-	.yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
-	.yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
-	.line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
-	.cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
-	.yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
-	.vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
-	.vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
-	.vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
-	.vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
-	.bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
-	.cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
-	.yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
-	.lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
-};
-
-static const struct vop_scl_regs rk3288_win_full_scl = {
-	.ext = &rk3288_win_full_scl_ext,
-	.scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
-	.scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
-	.scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
-	.scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
-};
-
-static const struct vop_win_phy rk3288_win01_data = {
-	.scl = &rk3288_win_full_scl,
-	.data_formats = formats_win_full,
-	.nformats = ARRAY_SIZE(formats_win_full),
-	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
-	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
-	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
-	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
-	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
-	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
-	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
-	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
-	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
-	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
-	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
-	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
-};
-
-static const struct vop_win_phy rk3288_win23_data = {
-	.data_formats = formats_win_lite,
-	.nformats = ARRAY_SIZE(formats_win_lite),
-	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
-	.format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
-	.rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
-	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
-	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
-	.yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
-	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
-	.src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
-	.dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
-};
-
-static const struct vop_ctrl rk3288_ctrl_data = {
-	.standby = VOP_REG(RK3288_SYS_CTRL, 0x1, 22),
-	.gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
-	.mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
-	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
-	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
-	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
-	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
-	.dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1),
-	.dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
-	.data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
-	.out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
-	.pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
-	.htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
-	.hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
-	.vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
-	.vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
-	.hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
-	.vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
-	.cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0),
-};
-
-static const struct vop_reg_data rk3288_init_reg_table[] = {
-	{RK3288_SYS_CTRL, 0x00c00000},
-	{RK3288_DSP_CTRL0, 0x00000000},
-	{RK3288_WIN0_CTRL0, 0x00000080},
-	{RK3288_WIN1_CTRL0, 0x00000080},
-	/* TODO: Win2/3 support multiple area function, but we haven't found
-	 * a suitable way to use it yet, so let's just use them as other windows
-	 * with only area 0 enabled.
-	 */
-	{RK3288_WIN2_CTRL0, 0x00000010},
-	{RK3288_WIN3_CTRL0, 0x00000010},
-};
-
-/*
- * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
- * special support to get alpha blending working.  For now, just use overlay
- * window 3 for the drm cursor.
- *
- */
-static const struct vop_win_data rk3288_vop_win_data[] = {
-	{ .base = 0x00, .phy = &rk3288_win01_data,
-	  .type = DRM_PLANE_TYPE_PRIMARY },
-	{ .base = 0x40, .phy = &rk3288_win01_data,
-	  .type = DRM_PLANE_TYPE_OVERLAY },
-	{ .base = 0x00, .phy = &rk3288_win23_data,
-	  .type = DRM_PLANE_TYPE_OVERLAY },
-	{ .base = 0x50, .phy = &rk3288_win23_data,
-	  .type = DRM_PLANE_TYPE_CURSOR },
-};
-
-static const int rk3288_vop_intrs[] = {
-	DSP_HOLD_VALID_INTR,
-	FS_INTR,
-	LINE_FLAG_INTR,
-	BUS_ERROR_INTR,
-};
-
-static const struct vop_intr rk3288_vop_intr = {
-	.intrs = rk3288_vop_intrs,
-	.nintrs = ARRAY_SIZE(rk3288_vop_intrs),
-	.status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
-	.enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
-	.clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
-};
-
-static const struct vop_data rk3288_vop = {
-	.init_table = rk3288_init_reg_table,
-	.table_size = ARRAY_SIZE(rk3288_init_reg_table),
-	.intr = &rk3288_vop_intr,
-	.ctrl = &rk3288_ctrl_data,
-	.win = rk3288_vop_win_data,
-	.win_size = ARRAY_SIZE(rk3288_vop_win_data),
-};
-
-static const struct vop_scl_regs rk3066_win_scl = {
-	.scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
-	.scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
-	.scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
-	.scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
-};
-
-static const struct vop_win_phy rk3036_win0_data = {
-	.scl = &rk3066_win_scl,
-	.data_formats = formats_win_full,
-	.nformats = ARRAY_SIZE(formats_win_full),
-	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
-	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
-	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
-	.act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
-	.dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
-	.dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
-	.yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
-	.uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
-	.yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
-};
-
-static const struct vop_win_phy rk3036_win1_data = {
-	.data_formats = formats_win_lite,
-	.nformats = ARRAY_SIZE(formats_win_lite),
-	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
-	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
-	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
-	.act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
-	.dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
-	.dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
-	.yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
-	.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
-};
-
-static const struct vop_win_data rk3036_vop_win_data[] = {
-	{ .base = 0x00, .phy = &rk3036_win0_data,
-	  .type = DRM_PLANE_TYPE_PRIMARY },
-	{ .base = 0x00, .phy = &rk3036_win1_data,
-	  .type = DRM_PLANE_TYPE_CURSOR },
-};
-
-static const int rk3036_vop_intrs[] = {
-	DSP_HOLD_VALID_INTR,
-	FS_INTR,
-	LINE_FLAG_INTR,
-	BUS_ERROR_INTR,
-};
-
-static const struct vop_intr rk3036_intr = {
-	.intrs = rk3036_vop_intrs,
-	.nintrs = ARRAY_SIZE(rk3036_vop_intrs),
-	.status = VOP_REG(RK3036_INT_STATUS, 0xf, 0),
-	.enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4),
-	.clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8),
-};
-
-static const struct vop_ctrl rk3036_ctrl_data = {
-	.standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30),
-	.out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
-	.pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
-	.htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
-	.hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
-	.vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
-	.vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
-	.cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0),
-};
-
-static const struct vop_reg_data rk3036_vop_init_reg_table[] = {
-	{RK3036_DSP_CTRL1, 0x00000000},
-};
-
-static const struct vop_data rk3036_vop = {
-	.init_table = rk3036_vop_init_reg_table,
-	.table_size = ARRAY_SIZE(rk3036_vop_init_reg_table),
-	.ctrl = &rk3036_ctrl_data,
-	.intr = &rk3036_intr,
-	.win = rk3036_vop_win_data,
-	.win_size = ARRAY_SIZE(rk3036_vop_win_data),
-};
-
-static const struct of_device_id vop_driver_dt_match[] = {
-	{ .compatible = "rockchip,rk3288-vop",
-	  .data = &rk3288_vop },
-	{ .compatible = "rockchip,rk3036-vop",
-	  .data = &rk3036_vop },
-	{},
-};
-MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
-
-static int vop_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-
-	if (!dev->of_node) {
-		dev_err(dev, "can't find vop devices\n");
-		return -ENODEV;
-	}
-
-	return component_add(dev, &vop_component_ops);
-}
-
-static int vop_remove(struct platform_device *pdev)
-{
-	component_del(&pdev->dev, &vop_component_ops);
-
-	return 0;
-}
-
-struct platform_driver vop_platform_driver = {
-	.probe = vop_probe,
-	.remove = vop_remove,
-	.driver = {
-		.name = "rockchip-vop",
-		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(vop_driver_dt_match),
-	},
-};
-
-module_platform_driver(vop_platform_driver);
-
-MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
-MODULE_DESCRIPTION("ROCKCHIP VOP Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
deleted file mode 100644
index d4b46cb..0000000
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
- * Author:Mark Yao <mark.yao@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _ROCKCHIP_VOP_REG_H
-#define _ROCKCHIP_VOP_REG_H
-
-/* rk3288 register definition */
-#define RK3288_REG_CFG_DONE			0x0000
-#define RK3288_VERSION_INFO			0x0004
-#define RK3288_SYS_CTRL				0x0008
-#define RK3288_SYS_CTRL1			0x000c
-#define RK3288_DSP_CTRL0			0x0010
-#define RK3288_DSP_CTRL1			0x0014
-#define RK3288_DSP_BG				0x0018
-#define RK3288_MCU_CTRL				0x001c
-#define RK3288_INTR_CTRL0			0x0020
-#define RK3288_INTR_CTRL1			0x0024
-#define RK3288_WIN0_CTRL0			0x0030
-#define RK3288_WIN0_CTRL1			0x0034
-#define RK3288_WIN0_COLOR_KEY			0x0038
-#define RK3288_WIN0_VIR				0x003c
-#define RK3288_WIN0_YRGB_MST			0x0040
-#define RK3288_WIN0_CBR_MST			0x0044
-#define RK3288_WIN0_ACT_INFO			0x0048
-#define RK3288_WIN0_DSP_INFO			0x004c
-#define RK3288_WIN0_DSP_ST			0x0050
-#define RK3288_WIN0_SCL_FACTOR_YRGB		0x0054
-#define RK3288_WIN0_SCL_FACTOR_CBR		0x0058
-#define RK3288_WIN0_SCL_OFFSET			0x005c
-#define RK3288_WIN0_SRC_ALPHA_CTRL		0x0060
-#define RK3288_WIN0_DST_ALPHA_CTRL		0x0064
-#define RK3288_WIN0_FADING_CTRL			0x0068
-
-/* win1 register */
-#define RK3288_WIN1_CTRL0			0x0070
-#define RK3288_WIN1_CTRL1			0x0074
-#define RK3288_WIN1_COLOR_KEY			0x0078
-#define RK3288_WIN1_VIR				0x007c
-#define RK3288_WIN1_YRGB_MST			0x0080
-#define RK3288_WIN1_CBR_MST			0x0084
-#define RK3288_WIN1_ACT_INFO			0x0088
-#define RK3288_WIN1_DSP_INFO			0x008c
-#define RK3288_WIN1_DSP_ST			0x0090
-#define RK3288_WIN1_SCL_FACTOR_YRGB		0x0094
-#define RK3288_WIN1_SCL_FACTOR_CBR		0x0098
-#define RK3288_WIN1_SCL_OFFSET			0x009c
-#define RK3288_WIN1_SRC_ALPHA_CTRL		0x00a0
-#define RK3288_WIN1_DST_ALPHA_CTRL		0x00a4
-#define RK3288_WIN1_FADING_CTRL			0x00a8
-/* win2 register */
-#define RK3288_WIN2_CTRL0			0x00b0
-#define RK3288_WIN2_CTRL1			0x00b4
-#define RK3288_WIN2_VIR0_1			0x00b8
-#define RK3288_WIN2_VIR2_3			0x00bc
-#define RK3288_WIN2_MST0			0x00c0
-#define RK3288_WIN2_DSP_INFO0			0x00c4
-#define RK3288_WIN2_DSP_ST0			0x00c8
-#define RK3288_WIN2_COLOR_KEY			0x00cc
-#define RK3288_WIN2_MST1			0x00d0
-#define RK3288_WIN2_DSP_INFO1			0x00d4
-#define RK3288_WIN2_DSP_ST1			0x00d8
-#define RK3288_WIN2_SRC_ALPHA_CTRL		0x00dc
-#define RK3288_WIN2_MST2			0x00e0
-#define RK3288_WIN2_DSP_INFO2			0x00e4
-#define RK3288_WIN2_DSP_ST2			0x00e8
-#define RK3288_WIN2_DST_ALPHA_CTRL		0x00ec
-#define RK3288_WIN2_MST3			0x00f0
-#define RK3288_WIN2_DSP_INFO3			0x00f4
-#define RK3288_WIN2_DSP_ST3			0x00f8
-#define RK3288_WIN2_FADING_CTRL			0x00fc
-/* win3 register */
-#define RK3288_WIN3_CTRL0			0x0100
-#define RK3288_WIN3_CTRL1			0x0104
-#define RK3288_WIN3_VIR0_1			0x0108
-#define RK3288_WIN3_VIR2_3			0x010c
-#define RK3288_WIN3_MST0			0x0110
-#define RK3288_WIN3_DSP_INFO0			0x0114
-#define RK3288_WIN3_DSP_ST0			0x0118
-#define RK3288_WIN3_COLOR_KEY			0x011c
-#define RK3288_WIN3_MST1			0x0120
-#define RK3288_WIN3_DSP_INFO1			0x0124
-#define RK3288_WIN3_DSP_ST1			0x0128
-#define RK3288_WIN3_SRC_ALPHA_CTRL		0x012c
-#define RK3288_WIN3_MST2			0x0130
-#define RK3288_WIN3_DSP_INFO2			0x0134
-#define RK3288_WIN3_DSP_ST2			0x0138
-#define RK3288_WIN3_DST_ALPHA_CTRL		0x013c
-#define RK3288_WIN3_MST3			0x0140
-#define RK3288_WIN3_DSP_INFO3			0x0144
-#define RK3288_WIN3_DSP_ST3			0x0148
-#define RK3288_WIN3_FADING_CTRL			0x014c
-/* hwc register */
-#define RK3288_HWC_CTRL0			0x0150
-#define RK3288_HWC_CTRL1			0x0154
-#define RK3288_HWC_MST				0x0158
-#define RK3288_HWC_DSP_ST			0x015c
-#define RK3288_HWC_SRC_ALPHA_CTRL		0x0160
-#define RK3288_HWC_DST_ALPHA_CTRL		0x0164
-#define RK3288_HWC_FADING_CTRL			0x0168
-/* post process register */
-#define RK3288_POST_DSP_HACT_INFO		0x0170
-#define RK3288_POST_DSP_VACT_INFO		0x0174
-#define RK3288_POST_SCL_FACTOR_YRGB		0x0178
-#define RK3288_POST_SCL_CTRL			0x0180
-#define RK3288_POST_DSP_VACT_INFO_F1		0x0184
-#define RK3288_DSP_HTOTAL_HS_END		0x0188
-#define RK3288_DSP_HACT_ST_END			0x018c
-#define RK3288_DSP_VTOTAL_VS_END		0x0190
-#define RK3288_DSP_VACT_ST_END			0x0194
-#define RK3288_DSP_VS_ST_END_F1			0x0198
-#define RK3288_DSP_VACT_ST_END_F1		0x019c
-/* register definition end */
-
-/* rk3036 register definition */
-#define RK3036_SYS_CTRL			0x00
-#define RK3036_DSP_CTRL0		0x04
-#define RK3036_DSP_CTRL1		0x08
-#define RK3036_INT_STATUS		0x10
-#define RK3036_ALPHA_CTRL		0x14
-#define RK3036_WIN0_COLOR_KEY		0x18
-#define RK3036_WIN1_COLOR_KEY		0x1c
-#define RK3036_WIN0_YRGB_MST		0x20
-#define RK3036_WIN0_CBR_MST		0x24
-#define RK3036_WIN1_VIR			0x28
-#define RK3036_AXI_BUS_CTRL		0x2c
-#define RK3036_WIN0_VIR			0x30
-#define RK3036_WIN0_ACT_INFO		0x34
-#define RK3036_WIN0_DSP_INFO		0x38
-#define RK3036_WIN0_DSP_ST		0x3c
-#define RK3036_WIN0_SCL_FACTOR_YRGB	0x40
-#define RK3036_WIN0_SCL_FACTOR_CBR	0x44
-#define RK3036_WIN0_SCL_OFFSET		0x48
-#define RK3036_HWC_MST			0x58
-#define RK3036_HWC_DSP_ST		0x5c
-#define RK3036_DSP_HTOTAL_HS_END	0x6c
-#define RK3036_DSP_HACT_ST_END		0x70
-#define RK3036_DSP_VTOTAL_VS_END	0x74
-#define RK3036_DSP_VACT_ST_END		0x78
-#define RK3036_DSP_VS_ST_END_F1		0x7c
-#define RK3036_DSP_VACT_ST_END_F1	0x80
-#define RK3036_GATHER_TRANSFER		0x84
-#define RK3036_VERSION_INFO		0x94
-#define RK3036_REG_CFG_DONE		0x90
-#define RK3036_WIN1_MST			0xa0
-#define RK3036_WIN1_ACT_INFO		0xb4
-#define RK3036_WIN1_DSP_INFO		0xb8
-#define RK3036_WIN1_DSP_ST		0xbc
-#define RK3036_WIN1_SCL_FACTOR_YRGB	0xc0
-#define RK3036_WIN1_SCL_OFFSET		0xc8
-#define RK3036_BCSH_CTRL		0xd0
-#define RK3036_BCSH_COLOR_BAR		0xd4
-#define RK3036_BCSH_BCS			0xd8
-#define RK3036_BCSH_H			0xdc
-#define RK3036_WIN1_LUT_ADDR		0x400
-#define RK3036_HWC_LUT_ADDR		0x800
-/* rk3036 register definition end */
-
-#endif /* _ROCKCHIP_VOP_REG_H */
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index b80802f..e9272b0 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -613,7 +613,7 @@
 	encoder->possible_crtcs = 1;
 
 	ret = drm_encoder_init(sdev->ddev, encoder, &encoder_funcs,
-			       DRM_MODE_ENCODER_LVDS, NULL);
+			       DRM_MODE_ENCODER_LVDS);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c
index f2afcf5..c8a4c5d 100644
--- a/drivers/gpu/drm/sti/sti_tvout.c
+++ b/drivers/gpu/drm/sti/sti_tvout.c
@@ -512,8 +512,7 @@
 	drm_encoder->possible_clones = 1 << 0;
 
 	drm_encoder_init(dev, drm_encoder,
-			 &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_LVDS,
-			 NULL);
+			 &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_LVDS);
 
 	drm_encoder_helper_add(drm_encoder, &sti_dvo_encoder_helper_funcs);
 
@@ -565,7 +564,7 @@
 	drm_encoder->possible_clones = 1 << 0;
 
 	drm_encoder_init(dev, drm_encoder,
-			&sti_tvout_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL);
+			&sti_tvout_encoder_funcs, DRM_MODE_ENCODER_DAC);
 
 	drm_encoder_helper_add(drm_encoder, &sti_hda_encoder_helper_funcs);
 
@@ -614,7 +613,7 @@
 	drm_encoder->possible_clones = 1 << 1;
 
 	drm_encoder_init(dev, drm_encoder,
-			&sti_tvout_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL);
+			&sti_tvout_encoder_funcs, DRM_MODE_ENCODER_TMDS);
 
 	drm_encoder_helper_add(drm_encoder, &sti_hdmi_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 50d46ae..f0a138e 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -1023,7 +1023,7 @@
 
 		drm_encoder_init(drm, &dsi->output.encoder,
 				 &tegra_dsi_encoder_funcs,
-				 DRM_MODE_ENCODER_DSI, NULL);
+				 DRM_MODE_ENCODER_DSI);
 		drm_encoder_helper_add(&dsi->output.encoder,
 				       &tegra_dsi_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index b7ef492..52b32cb 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1320,7 +1320,7 @@
 	hdmi->output.connector.dpms = DRM_MODE_DPMS_OFF;
 
 	drm_encoder_init(drm, &hdmi->output.encoder, &tegra_hdmi_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(&hdmi->output.encoder,
 			       &tegra_hdmi_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
index e246334..bc9735b 100644
--- a/drivers/gpu/drm/tegra/rgb.c
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -287,7 +287,7 @@
 	output->connector.dpms = DRM_MODE_DPMS_OFF;
 
 	drm_encoder_init(drm, &output->encoder, &tegra_rgb_encoder_funcs,
-			 DRM_MODE_ENCODER_LVDS, NULL);
+			 DRM_MODE_ENCODER_LVDS);
 	drm_encoder_helper_add(&output->encoder,
 			       &tegra_rgb_encoder_helper_funcs);
 
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 3e012ee..3eff7cf 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -2178,7 +2178,7 @@
 	sor->output.connector.dpms = DRM_MODE_DPMS_OFF;
 
 	drm_encoder_init(drm, &sor->output.encoder, &tegra_sor_encoder_funcs,
-			 encoder, NULL);
+			 encoder);
 	drm_encoder_helper_add(&sor->output.encoder, helpers);
 
 	drm_mode_connector_attach_encoder(&sor->output.connector,
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
index 4dda6e2..0af8bed 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -128,7 +128,7 @@
 	encoder->possible_crtcs = 1;
 
 	ret = drm_encoder_init(dev, encoder, &panel_encoder_funcs,
-			DRM_MODE_ENCODER_LVDS, NULL);
+			DRM_MODE_ENCODER_LVDS);
 	if (ret < 0)
 		goto fail;
 
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
index 5052a8a..354c47c 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
@@ -138,7 +138,7 @@
 	encoder->possible_crtcs = 1;
 
 	ret = drm_encoder_init(dev, encoder, &tfp410_encoder_funcs,
-			DRM_MODE_ENCODER_TMDS, NULL);
+			DRM_MODE_ENCODER_TMDS);
 	if (ret < 0)
 		goto fail;
 
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 745e996..037c38b 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1004,9 +1004,9 @@
 	return ret;
 }
 
-static bool ttm_bo_mem_compat(struct ttm_placement *placement,
-			      struct ttm_mem_reg *mem,
-			      uint32_t *new_flags)
+bool ttm_bo_mem_compat(struct ttm_placement *placement,
+		       struct ttm_mem_reg *mem,
+		       uint32_t *new_flags)
 {
 	int i;
 
@@ -1038,6 +1038,7 @@
 
 	return false;
 }
+EXPORT_SYMBOL(ttm_bo_mem_compat);
 
 int ttm_bo_validate(struct ttm_buffer_object *bo,
 			struct ttm_placement *placement,
@@ -1620,7 +1621,6 @@
 	struct ttm_buffer_object *bo;
 	int ret = -EBUSY;
 	int put_count;
-	uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM);
 
 	spin_lock(&glob->lru_lock);
 	list_for_each_entry(bo, &glob->swap_lru, swap) {
@@ -1656,7 +1656,8 @@
 	if (unlikely(ret != 0))
 		goto out;
 
-	if ((bo->mem.placement & swap_placement) != swap_placement) {
+	if (bo->mem.mem_type != TTM_PL_SYSTEM ||
+	    bo->ttm->caching_state != tt_cached) {
 		struct ttm_mem_reg evict_mem;
 
 		evict_mem = bo->mem;
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 8fb7213..b753914 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -66,8 +66,11 @@
 		if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
 			goto out_unlock;
 
+		ttm_bo_reference(bo);
 		up_read(&vma->vm_mm->mmap_sem);
 		(void) ttm_bo_wait(bo, false, true, false);
+		ttm_bo_unreserve(bo);
+		ttm_bo_unref(&bo);
 		goto out_unlock;
 	}
 
@@ -114,8 +117,10 @@
 
 		if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
 			if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
+				ttm_bo_reference(bo);
 				up_read(&vma->vm_mm->mmap_sem);
 				(void) ttm_bo_wait_unreserved(bo);
+				ttm_bo_unref(&bo);
 			}
 
 			return VM_FAULT_RETRY;
@@ -160,6 +165,13 @@
 	ret = ttm_bo_vm_fault_idle(bo, vma, vmf);
 	if (unlikely(ret != 0)) {
 		retval = ret;
+
+		if (retval == VM_FAULT_RETRY &&
+		    !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
+			/* The BO has already been unreserved. */
+			return retval;
+		}
+
 		goto out_unlock;
 	}
 
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c
index 4f5fa8d..144367c 100644
--- a/drivers/gpu/drm/ttm/ttm_object.c
+++ b/drivers/gpu/drm/ttm/ttm_object.c
@@ -179,7 +179,7 @@
 	if (unlikely(ret != 0))
 		goto out_err0;
 
-	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
+	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
 	if (unlikely(ret != 0))
 		goto out_err1;
 
@@ -318,7 +318,8 @@
 
 int ttm_ref_object_add(struct ttm_object_file *tfile,
 		       struct ttm_base_object *base,
-		       enum ttm_ref_type ref_type, bool *existed)
+		       enum ttm_ref_type ref_type, bool *existed,
+		       bool require_existed)
 {
 	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
 	struct ttm_ref_object *ref;
@@ -345,6 +346,9 @@
 		}
 
 		rcu_read_unlock();
+		if (require_existed)
+			return -EPERM;
+
 		ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
 					   false, false);
 		if (unlikely(ret != 0))
@@ -635,7 +639,7 @@
 	prime = (struct ttm_prime_object *) dma_buf->priv;
 	base = &prime->base;
 	*handle = base->hash.key;
-	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
+	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
 
 	dma_buf_put(dma_buf);
 
diff --git a/drivers/gpu/drm/udl/udl_encoder.c b/drivers/gpu/drm/udl/udl_encoder.c
index a181a64..4052c46 100644
--- a/drivers/gpu/drm/udl/udl_encoder.c
+++ b/drivers/gpu/drm/udl/udl_encoder.c
@@ -73,8 +73,7 @@
 	if (!encoder)
 		return NULL;
 
-	drm_encoder_init(dev, encoder, &udl_enc_funcs, DRM_MODE_ENCODER_TMDS,
-			 NULL);
+	drm_encoder_init(dev, encoder, &udl_enc_funcs, DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &udl_helper_funcs);
 	encoder->possible_crtcs = 1;
 	return encoder;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c69c046..da9a36d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -519,7 +519,7 @@
 	WARN_ON_ONCE((HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE) == 0);
 
 	drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
 
 	hdmi->connector = vc4_hdmi_connector_init(drm, hdmi->encoder);
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index ba2a215..578fe0a 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -453,7 +453,7 @@
 	drm_connector_helper_add(connector, &virtio_gpu_conn_helper_funcs);
 
 	drm_encoder_init(dev, encoder, &virtio_gpu_enc_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
+			 DRM_MODE_ENCODER_VIRTUAL);
 	drm_encoder_helper_add(encoder, &virtio_gpu_enc_helper_funcs);
 	encoder->possible_crtcs = 1 << index;
 
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
index f300eba..1244cdf 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -81,8 +81,10 @@
 		return -ENOMEM;
 	size = roundup(size, PAGE_SIZE);
 	ret = drm_gem_object_init(vgdev->ddev, &bo->gem_base, size);
-	if (ret != 0)
+	if (ret != 0) {
+		kfree(bo);
 		return ret;
+	}
 	bo->dumb = false;
 	virtio_gpu_init_ttm_placement(bo, pinned);
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
index 13db8a2..1f013d4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
@@ -321,6 +321,7 @@
 	list_for_each_entry_safe(entry, next, &man->list, head)
 		vmw_cmdbuf_res_free(man, entry);
 
+	drm_ht_remove(&man->resources);
 	kfree(man);
 }
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
index 299925a..eadc981 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
@@ -49,6 +49,7 @@
 {
 	struct ttm_buffer_object *bo = &buf->base;
 	int ret;
+	uint32_t new_flags;
 
 	ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
 	if (unlikely(ret != 0))
@@ -60,7 +61,12 @@
 	if (unlikely(ret != 0))
 		goto err;
 
-	ret = ttm_bo_validate(bo, placement, interruptible, false);
+	if (buf->pin_count > 0)
+		ret = ttm_bo_mem_compat(placement, &bo->mem,
+					&new_flags) == true ? 0 : -EINVAL;
+	else
+		ret = ttm_bo_validate(bo, placement, interruptible, false);
+
 	if (!ret)
 		vmw_bo_pin_reserved(buf, true);
 
@@ -91,6 +97,7 @@
 {
 	struct ttm_buffer_object *bo = &buf->base;
 	int ret;
+	uint32_t new_flags;
 
 	ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
 	if (unlikely(ret != 0))
@@ -102,6 +109,12 @@
 	if (unlikely(ret != 0))
 		goto err;
 
+	if (buf->pin_count > 0) {
+		ret = ttm_bo_mem_compat(&vmw_vram_gmr_placement, &bo->mem,
+					&new_flags) == true ? 0 : -EINVAL;
+		goto out_unreserve;
+	}
+
 	ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, interruptible,
 			      false);
 	if (likely(ret == 0) || ret == -ERESTARTSYS)
@@ -161,6 +174,7 @@
 	struct ttm_placement placement;
 	struct ttm_place place;
 	int ret = 0;
+	uint32_t new_flags;
 
 	place = vmw_vram_placement.placement[0];
 	place.lpfn = bo->num_pages;
@@ -185,10 +199,15 @@
 	 */
 	if (bo->mem.mem_type == TTM_PL_VRAM &&
 	    bo->mem.start < bo->num_pages &&
-	    bo->mem.start > 0)
+	    bo->mem.start > 0 &&
+	    buf->pin_count == 0)
 		(void) ttm_bo_validate(bo, &vmw_sys_placement, false, false);
 
-	ret = ttm_bo_validate(bo, &placement, interruptible, false);
+	if (buf->pin_count > 0)
+		ret = ttm_bo_mem_compat(&placement, &bo->mem,
+					&new_flags) == true ? 0 : -EINVAL;
+	else
+		ret = ttm_bo_validate(bo, &placement, interruptible, false);
 
 	/* For some reason we didn't end up at the start of vram */
 	WARN_ON(ret == 0 && bo->offset != 0);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 24fb348..f3f31f9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -227,6 +227,7 @@
 static int vmw_restrict_iommu;
 static int vmw_force_coherent;
 static int vmw_restrict_dma_mask;
+static int vmw_assume_16bpp;
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
@@ -243,6 +244,8 @@
 module_param_named(force_coherent, vmw_force_coherent, int, 0600);
 MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU");
 module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600);
+MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");
+module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600);
 
 
 static void vmw_print_capabilities(uint32_t capabilities)
@@ -652,6 +655,8 @@
 	dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
 	dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
 
+	dev_priv->assume_16bpp = !!vmw_assume_16bpp;
+
 	dev_priv->enable_fb = enable_fbdev;
 
 	vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
@@ -698,6 +703,13 @@
 			vmw_read(dev_priv,
 				 SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB);
 
+		/*
+		 * Workaround for low memory 2D VMs to compensate for the
+		 * allocation taken by fbdev
+		 */
+		if (!(dev_priv->capabilities & SVGA_CAP_3D))
+			mem_size *= 2;
+
 		dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
 		dev_priv->prim_bb_mem =
 			vmw_read(dev_priv,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 469cdd5..2e94fe2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -387,6 +387,7 @@
 	spinlock_t hw_lock;
 	spinlock_t cap_lock;
 	bool has_dx;
+	bool assume_16bpp;
 
 	/*
 	 * VGA registers.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 5da5de0..ecf15cf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -3273,19 +3273,19 @@
 		    &vmw_cmd_dx_cid_check, true, false, true),
 	VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_QUERY, &vmw_cmd_dx_define_query,
 		    true, false, true),
-	VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_QUERY, &vmw_cmd_ok,
+	VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_QUERY, &vmw_cmd_dx_cid_check,
 		    true, false, true),
 	VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_QUERY, &vmw_cmd_dx_bind_query,
 		    true, false, true),
 	VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_QUERY_OFFSET,
-		    &vmw_cmd_ok, true, false, true),
-	VMW_CMD_DEF(SVGA_3D_CMD_DX_BEGIN_QUERY, &vmw_cmd_ok,
+		    &vmw_cmd_dx_cid_check, true, false, true),
+	VMW_CMD_DEF(SVGA_3D_CMD_DX_BEGIN_QUERY, &vmw_cmd_dx_cid_check,
 		    true, false, true),
-	VMW_CMD_DEF(SVGA_3D_CMD_DX_END_QUERY, &vmw_cmd_ok,
+	VMW_CMD_DEF(SVGA_3D_CMD_DX_END_QUERY, &vmw_cmd_dx_cid_check,
 		    true, false, true),
 	VMW_CMD_DEF(SVGA_3D_CMD_DX_READBACK_QUERY, &vmw_cmd_invalid,
 		    true, false, true),
-	VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_PREDICATION, &vmw_cmd_invalid,
+	VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_PREDICATION, &vmw_cmd_dx_cid_check,
 		    true, false, true),
 	VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_VIEWPORTS, &vmw_cmd_dx_cid_check,
 		    true, false, true),
@@ -3830,14 +3830,14 @@
 	int ret;
 
 	*header = NULL;
-	if (!dev_priv->cman || kernel_commands)
-		return kernel_commands;
-
 	if (command_size > SVGA_CB_MAX_SIZE) {
 		DRM_ERROR("Command buffer is too large.\n");
 		return ERR_PTR(-EINVAL);
 	}
 
+	if (!dev_priv->cman || kernel_commands)
+		return kernel_commands;
+
 	/* If possible, add a little space for fencing. */
 	cmdbuf_size = command_size + 512;
 	cmdbuf_size = min_t(size_t, cmdbuf_size, SVGA_CB_MAX_SIZE);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 3b1faf7..d2d9395 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -517,28 +517,6 @@
 
 	par->set_fb = &vfb->base;
 
-	if (!par->bo_ptr) {
-		/*
-		 * Pin before mapping. Since we don't know in what placement
-		 * to pin, call into KMS to do it for us.
-		 */
-		ret = vfb->pin(vfb);
-		if (ret) {
-			DRM_ERROR("Could not pin the fbdev framebuffer.\n");
-			return ret;
-		}
-
-		ret = ttm_bo_kmap(&par->vmw_bo->base, 0,
-				  par->vmw_bo->base.num_pages, &par->map);
-		if (ret) {
-			vfb->unpin(vfb);
-			DRM_ERROR("Could not map the fbdev framebuffer.\n");
-			return ret;
-		}
-
-		par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
-	}
-
 	return 0;
 }
 
@@ -573,9 +551,9 @@
 		mode = old_mode;
 		old_mode = NULL;
 	} else if (!vmw_kms_validate_mode_vram(vmw_priv,
-					       mode->hdisplay *
-					       (var->bits_per_pixel + 7) / 8,
-					       mode->vdisplay)) {
+					mode->hdisplay *
+					DIV_ROUND_UP(var->bits_per_pixel, 8),
+					mode->vdisplay)) {
 		drm_mode_destroy(vmw_priv->dev, mode);
 		return -EINVAL;
 	}
@@ -601,6 +579,31 @@
 	if (ret)
 		goto out_unlock;
 
+	if (!par->bo_ptr) {
+		struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(set.fb);
+
+		/*
+		 * Pin before mapping. Since we don't know in what placement
+		 * to pin, call into KMS to do it for us.
+		 */
+		ret = vfb->pin(vfb);
+		if (ret) {
+			DRM_ERROR("Could not pin the fbdev framebuffer.\n");
+			goto out_unlock;
+		}
+
+		ret = ttm_bo_kmap(&par->vmw_bo->base, 0,
+				  par->vmw_bo->base.num_pages, &par->map);
+		if (ret) {
+			vfb->unpin(vfb);
+			DRM_ERROR("Could not map the fbdev framebuffer.\n");
+			goto out_unlock;
+		}
+
+		par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
+	}
+
+
 	vmw_fb_dirty_mark(par, par->fb_x, par->fb_y,
 			  par->set_fb->width, par->set_fb->height);
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index 8e689b4..6c649f7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -539,7 +539,7 @@
 		     struct vmw_fence_obj **p_fence)
 {
 	struct vmw_fence_obj *fence;
-	int ret;
+ 	int ret;
 
 	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
 	if (unlikely(fence == NULL))
@@ -702,6 +702,41 @@
 }
 
 
+/**
+ * vmw_fence_obj_lookup - Look up a user-space fence object
+ *
+ * @tfile: A struct ttm_object_file identifying the caller.
+ * @handle: A handle identifying the fence object.
+ * @return: A struct vmw_user_fence base ttm object on success or
+ * an error pointer on failure.
+ *
+ * The fence object is looked up and type-checked. The caller needs
+ * to have opened the fence object first, but since that happens on
+ * creation and fence objects aren't shareable, that's not an
+ * issue currently.
+ */
+static struct ttm_base_object *
+vmw_fence_obj_lookup(struct ttm_object_file *tfile, u32 handle)
+{
+	struct ttm_base_object *base = ttm_base_object_lookup(tfile, handle);
+
+	if (!base) {
+		pr_err("Invalid fence object handle 0x%08lx.\n",
+		       (unsigned long)handle);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (base->refcount_release != vmw_user_fence_base_release) {
+		pr_err("Invalid fence object handle 0x%08lx.\n",
+		       (unsigned long)handle);
+		ttm_base_object_unref(&base);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return base;
+}
+
+
 int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
 			     struct drm_file *file_priv)
 {
@@ -727,13 +762,9 @@
 		arg->kernel_cookie = jiffies + wait_timeout;
 	}
 
-	base = ttm_base_object_lookup(tfile, arg->handle);
-	if (unlikely(base == NULL)) {
-		printk(KERN_ERR "Wait invalid fence object handle "
-		       "0x%08lx.\n",
-		       (unsigned long)arg->handle);
-		return -EINVAL;
-	}
+	base = vmw_fence_obj_lookup(tfile, arg->handle);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	fence = &(container_of(base, struct vmw_user_fence, base)->fence);
 
@@ -772,13 +803,9 @@
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
 	struct vmw_private *dev_priv = vmw_priv(dev);
 
-	base = ttm_base_object_lookup(tfile, arg->handle);
-	if (unlikely(base == NULL)) {
-		printk(KERN_ERR "Fence signaled invalid fence object handle "
-		       "0x%08lx.\n",
-		       (unsigned long)arg->handle);
-		return -EINVAL;
-	}
+	base = vmw_fence_obj_lookup(tfile, arg->handle);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	fence = &(container_of(base, struct vmw_user_fence, base)->fence);
 	fman = fman_from_fence(fence);
@@ -1093,6 +1120,7 @@
 		(struct drm_vmw_fence_event_arg *) data;
 	struct vmw_fence_obj *fence = NULL;
 	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+	struct ttm_object_file *tfile = vmw_fp->tfile;
 	struct drm_vmw_fence_rep __user *user_fence_rep =
 		(struct drm_vmw_fence_rep __user *)(unsigned long)
 		arg->fence_rep;
@@ -1106,24 +1134,18 @@
 	 */
 	if (arg->handle) {
 		struct ttm_base_object *base =
-			ttm_base_object_lookup_for_ref(dev_priv->tdev,
-						       arg->handle);
+			vmw_fence_obj_lookup(tfile, arg->handle);
 
-		if (unlikely(base == NULL)) {
-			DRM_ERROR("Fence event invalid fence object handle "
-				  "0x%08lx.\n",
-				  (unsigned long)arg->handle);
-			return -EINVAL;
-		}
+		if (IS_ERR(base))
+			return PTR_ERR(base);
+
 		fence = &(container_of(base, struct vmw_user_fence,
 				       base)->fence);
 		(void) vmw_fence_obj_reference(fence);
 
 		if (user_fence_rep != NULL) {
-			bool existed;
-
 			ret = ttm_ref_object_add(vmw_fp->tfile, base,
-						 TTM_REF_USAGE, &existed);
+						 TTM_REF_USAGE, NULL, false);
 			if (unlikely(ret != 0)) {
 				DRM_ERROR("Failed to reference a fence "
 					  "object.\n");
@@ -1166,8 +1188,7 @@
 	return 0;
 out_no_create:
 	if (user_fence_rep != NULL)
-		ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
-					  handle, TTM_REF_USAGE);
+		ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
 out_no_ref_obj:
 	vmw_fence_obj_unreference(&fence);
 	return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index b6a0806..a1c68e6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -368,6 +368,8 @@
 				return fifo_state->static_buffer;
 			else {
 				fifo_state->dynamic_buffer = vmalloc(bytes);
+				if (!fifo_state->dynamic_buffer)
+					goto out_err;
 				return fifo_state->dynamic_buffer;
 			}
 		}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index b8c6a03..5ec24fd 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -114,8 +114,6 @@
 		param->value = dev_priv->has_dx;
 		break;
 	default:
-		DRM_ERROR("Illegal vmwgfx get param request: %d\n",
-			  param->param);
 		return -EINVAL;
 	}
 
@@ -186,7 +184,7 @@
 	bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS);
 	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
 
-	if (unlikely(arg->pad64 != 0)) {
+	if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) {
 		DRM_ERROR("Illegal GET_3D_CAP argument.\n");
 		return -EINVAL;
 	}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 7c2e118..060e5c6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1538,14 +1538,10 @@
 		DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
 	};
 	int i;
-	u32 assumed_bpp = 2;
+	u32 assumed_bpp = 4;
 
-	/*
-	 * If using screen objects, then assume 32-bpp because that's what the
-	 * SVGA device is assuming
-	 */
-	if (dev_priv->active_display_unit == vmw_du_screen_object)
-		assumed_bpp = 4;
+	if (dev_priv->assume_16bpp)
+		assumed_bpp = 2;
 
 	if (dev_priv->active_display_unit == vmw_du_screen_target) {
 		max_width  = min(max_width,  dev_priv->stdu_max_width);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index a51e8c1..52caecb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -367,7 +367,7 @@
 	connector->status = vmw_du_connector_detect(connector, true);
 
 	drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
+			 DRM_MODE_ENCODER_VIRTUAL);
 	drm_mode_connector_attach_encoder(connector, encoder);
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index e57667c..dbca128 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -591,7 +591,7 @@
 		return ret;
 
 	ret = ttm_ref_object_add(tfile, &user_bo->prime.base,
-				 TTM_REF_SYNCCPU_WRITE, &existed);
+				 TTM_REF_SYNCCPU_WRITE, &existed, false);
 	if (ret != 0 || existed)
 		ttm_bo_synccpu_write_release(&user_bo->dma.base);
 
@@ -775,7 +775,7 @@
 
 	*handle = user_bo->prime.base.hash.key;
 	return ttm_ref_object_add(tfile, &user_bo->prime.base,
-				  TTM_REF_USAGE, NULL);
+				  TTM_REF_USAGE, NULL, false);
 }
 
 /*
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 6203909..13926ff 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -603,7 +603,7 @@
 	connector->status = vmw_du_connector_detect(connector, true);
 
 	drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
+			 DRM_MODE_ENCODER_VIRTUAL);
 	drm_mode_connector_attach_encoder(connector, encoder);
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 67a4a8a..f823fc3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1149,7 +1149,7 @@
 	connector->status = vmw_du_connector_detect(connector, false);
 
 	drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
+			 DRM_MODE_ENCODER_VIRTUAL);
 	drm_mode_connector_attach_encoder(connector, encoder);
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index 7d620e8..0279870 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -715,11 +715,14 @@
 			128;
 
 	num_sizes = 0;
-	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
+		if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS)
+			return -EINVAL;
 		num_sizes += req->mip_levels[i];
+	}
 
-	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES *
-	    DRM_VMW_MAX_MIP_LEVELS)
+	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS ||
+	    num_sizes == 0)
 		return -EINVAL;
 
 	size = vmw_user_surface_size + 128 +
@@ -904,17 +907,16 @@
 	uint32_t handle;
 	struct ttm_base_object *base;
 	int ret;
+	bool require_exist = false;
 
 	if (handle_type == DRM_VMW_HANDLE_PRIME) {
 		ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
 		if (unlikely(ret != 0))
 			return ret;
 	} else {
-		if (unlikely(drm_is_render_client(file_priv))) {
-			DRM_ERROR("Render client refused legacy "
-				  "surface reference.\n");
-			return -EACCES;
-		}
+		if (unlikely(drm_is_render_client(file_priv)))
+			require_exist = true;
+
 		if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) {
 			DRM_ERROR("Locked master refused legacy "
 				  "surface reference.\n");
@@ -942,17 +944,14 @@
 
 		/*
 		 * Make sure the surface creator has the same
-		 * authenticating master.
+		 * authenticating master, or is already registered with us.
 		 */
 		if (drm_is_primary_client(file_priv) &&
-		    user_srf->master != file_priv->master) {
-			DRM_ERROR("Trying to reference surface outside of"
-				  " master domain.\n");
-			ret = -EACCES;
-			goto out_bad_resource;
-		}
+		    user_srf->master != file_priv->master)
+			require_exist = true;
 
-		ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
+		ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL,
+					 require_exist);
 		if (unlikely(ret != 0)) {
 			DRM_ERROR("Could not add a reference to a surface.\n");
 			goto out_bad_resource;
@@ -1289,11 +1288,14 @@
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
 	int ret;
 	uint32_t size;
-	uint32_t backup_handle;
+	uint32_t backup_handle = 0;
 
 	if (req->multisample_count != 0)
 		return -EINVAL;
 
+	if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS)
+		return -EINVAL;
+
 	if (unlikely(vmw_user_surface_size == 0))
 		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
 			128;
@@ -1329,12 +1331,16 @@
 		ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
 					     &res->backup,
 					     &user_srf->backup_base);
-		if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE <
-		    res->backup_size) {
-			DRM_ERROR("Surface backup buffer is too small.\n");
-			vmw_dmabuf_unreference(&res->backup);
-			ret = -EINVAL;
-			goto out_unlock;
+		if (ret == 0) {
+			if (res->backup->base.num_pages * PAGE_SIZE <
+			    res->backup_size) {
+				DRM_ERROR("Surface backup buffer is too small.\n");
+				vmw_dmabuf_unreference(&res->backup);
+				ret = -EINVAL;
+				goto out_unlock;
+			} else {
+				backup_handle = req->buffer_handle;
+			}
 		}
 	} else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer)
 		ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 0585fd2..5030cba 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -997,7 +997,7 @@
 };
 
 /* These must be in the order of the corresponding device tree port nodes */
-static const struct ipu_platform_reg client_reg[] = {
+static struct ipu_platform_reg client_reg[] = {
 	{
 		.pdata = {
 			.csi = 0,
@@ -1048,7 +1048,7 @@
 	mutex_unlock(&ipu_client_id_mutex);
 
 	for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
-		const struct ipu_platform_reg *reg = &client_reg[i];
+		struct ipu_platform_reg *reg = &client_reg[i];
 		struct platform_device *pdev;
 		struct device_node *of_node;
 
@@ -1070,6 +1070,7 @@
 
 		pdev->dev.parent = dev;
 
+		reg->pdata.of_node = of_node;
 		ret = platform_device_add_data(pdev, &reg->pdata,
 					       sizeof(reg->pdata));
 		if (!ret)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index ec791e1..9369602 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1251,6 +1251,7 @@
 		/* Ignore report if ErrorRollOver */
 		if (!(field->flags & HID_MAIN_ITEM_VARIABLE) &&
 		    value[n] >= min && value[n] <= max &&
+		    value[n] - min < field->maxusage &&
 		    field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
 			goto exit;
 	}
@@ -1263,11 +1264,13 @@
 		}
 
 		if (field->value[n] >= min && field->value[n] <= max
+			&& field->value[n] - min < field->maxusage
 			&& field->usage[field->value[n] - min].hid
 			&& search(value, field->value[n], count))
 				hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
 
 		if (value[n] >= min && value[n] <= max
+			&& value[n] - min < field->maxusage
 			&& field->usage[value[n] - min].hid
 			&& search(field->value, value[n], count))
 				hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c
index bcefb9e..88be563 100644
--- a/drivers/hid/hid-corsair.c
+++ b/drivers/hid/hid-corsair.c
@@ -148,26 +148,36 @@
 	struct usb_interface *usbif = to_usb_interface(dev->parent);
 	struct usb_device *usbdev = interface_to_usbdev(usbif);
 	int brightness;
-	char data[8];
+	char *data;
+
+	data = kmalloc(8, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
 			      K90_REQUEST_STATUS,
 			      USB_DIR_IN | USB_TYPE_VENDOR |
 			      USB_RECIP_DEVICE, 0, 0, data, 8,
 			      USB_CTRL_SET_TIMEOUT);
-	if (ret < 0) {
+	if (ret < 5) {
 		dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
 			 ret);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 	brightness = data[4];
 	if (brightness < 0 || brightness > 3) {
 		dev_warn(dev,
 			 "Read invalid backlight brightness: %02hhx.\n",
 			 data[4]);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
-	return brightness;
+	ret = brightness;
+out:
+	kfree(data);
+
+	return ret;
 }
 
 static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev)
@@ -253,17 +263,22 @@
 	struct usb_interface *usbif = to_usb_interface(dev->parent);
 	struct usb_device *usbdev = interface_to_usbdev(usbif);
 	const char *macro_mode;
-	char data[8];
+	char *data;
+
+	data = kmalloc(2, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
 			      K90_REQUEST_GET_MODE,
 			      USB_DIR_IN | USB_TYPE_VENDOR |
 			      USB_RECIP_DEVICE, 0, 0, data, 2,
 			      USB_CTRL_SET_TIMEOUT);
-	if (ret < 0) {
+	if (ret < 1) {
 		dev_warn(dev, "Failed to get K90 initial mode (error %d).\n",
 			 ret);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
 	switch (data[0]) {
@@ -277,10 +292,15 @@
 	default:
 		dev_warn(dev, "K90 in unknown mode: %02hhx.\n",
 			 data[0]);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
-	return snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
+	ret = snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
+out:
+	kfree(data);
+
+	return ret;
 }
 
 static ssize_t k90_store_macro_mode(struct device *dev,
@@ -320,26 +340,36 @@
 	struct usb_interface *usbif = to_usb_interface(dev->parent);
 	struct usb_device *usbdev = interface_to_usbdev(usbif);
 	int current_profile;
-	char data[8];
+	char *data;
+
+	data = kmalloc(8, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
 			      K90_REQUEST_STATUS,
 			      USB_DIR_IN | USB_TYPE_VENDOR |
 			      USB_RECIP_DEVICE, 0, 0, data, 8,
 			      USB_CTRL_SET_TIMEOUT);
-	if (ret < 0) {
+	if (ret < 8) {
 		dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
 			 ret);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 	current_profile = data[7];
 	if (current_profile < 1 || current_profile > 3) {
 		dev_warn(dev, "Read invalid current profile: %02hhx.\n",
 			 data[7]);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
+out:
+	kfree(data);
+
+	return ret;
 }
 
 static ssize_t k90_store_current_profile(struct device *dev,
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c
index 1b764d1..1689568 100644
--- a/drivers/hid/hid-cypress.c
+++ b/drivers/hid/hid-cypress.c
@@ -39,6 +39,9 @@
 	if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
 		return rdesc;
 
+	if (*rsize < 4)
+		return rdesc;
+
 	for (i = 0; i < *rsize - 4; i++)
 		if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
 			rdesc[i] = 0x19;
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c
index aad8c16..0cd4f72 100644
--- a/drivers/hid/hid-elo.c
+++ b/drivers/hid/hid-elo.c
@@ -261,7 +261,7 @@
 	struct elo_priv *priv = hid_get_drvdata(hdev);
 
 	hid_hw_stop(hdev);
-	flush_workqueue(wq);
+	cancel_delayed_work_sync(&priv->work);
 	kfree(priv);
 }
 
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 909ab01..c7f8b70 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -168,6 +168,7 @@
 #define USB_DEVICE_ID_ATEN_4PORTKVM	0x2205
 #define USB_DEVICE_ID_ATEN_4PORTKVMC	0x2208
 #define USB_DEVICE_ID_ATEN_CS682	0x2213
+#define USB_DEVICE_ID_ATEN_CS692	0x8021
 
 #define USB_VENDOR_ID_ATMEL		0x03eb
 #define USB_DEVICE_ID_ATMEL_MULTITOUCH	0x211c
@@ -284,6 +285,9 @@
 #define USB_VENDOR_ID_DEALEXTREAME	0x10c5
 #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701	0x819a
 
+#define USB_VENDOR_ID_DELL				0x413c
+#define USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE	0x301a
+
 #define USB_VENDOR_ID_DELORME		0x1163
 #define USB_DEVICE_ID_DELORME_EARTHMATE	0x0100
 #define USB_DEVICE_ID_DELORME_EM_LT20	0x0200
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index c5ec4f9..f62a9d6 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -61,6 +61,7 @@
 #define MT_QUIRK_ALWAYS_VALID		(1 << 4)
 #define MT_QUIRK_VALID_IS_INRANGE	(1 << 5)
 #define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 6)
+#define MT_QUIRK_CONFIDENCE		(1 << 7)
 #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)
 #define MT_QUIRK_NO_AREA		(1 << 9)
 #define MT_QUIRK_IGNORE_DUPLICATES	(1 << 10)
@@ -78,6 +79,7 @@
 	__s32 contactid;	/* the device ContactID assigned to this slot */
 	bool touch_state;	/* is the touch valid? */
 	bool inrange_state;	/* is the finger in proximity of the sensor? */
+	bool confidence_state;  /* is the touch made by a finger? */
 };
 
 struct mt_class {
@@ -502,6 +504,9 @@
 			mt_store_field(usage, td, hi);
 			return 1;
 		case HID_DG_CONFIDENCE:
+			if (cls->name == MT_CLS_WIN_8 &&
+				field->application == HID_DG_TOUCHPAD)
+				cls->quirks |= MT_QUIRK_CONFIDENCE;
 			mt_store_field(usage, td, hi);
 			return 1;
 		case HID_DG_TIPSWITCH:
@@ -614,6 +619,7 @@
 		return;
 
 	if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
+		int active;
 		int slotnum = mt_compute_slot(td, input);
 		struct mt_slot *s = &td->curdata;
 		struct input_mt *mt = input->mt;
@@ -628,10 +634,14 @@
 				return;
 		}
 
+		if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE))
+			s->confidence_state = 1;
+		active = (s->touch_state || s->inrange_state) &&
+							s->confidence_state;
+
 		input_mt_slot(input, slotnum);
-		input_mt_report_slot_state(input, MT_TOOL_FINGER,
-			s->touch_state || s->inrange_state);
-		if (s->touch_state || s->inrange_state) {
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
+		if (active) {
 			/* this finger is in proximity of the sensor */
 			int wide = (s->w > s->h);
 			/* divided by two to match visual scale of touch */
@@ -696,6 +706,8 @@
 			td->curdata.touch_state = value;
 			break;
 		case HID_DG_CONFIDENCE:
+			if (quirks & MT_QUIRK_CONFIDENCE)
+				td->curdata.confidence_state = value;
 			if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
 				td->curvalid = value;
 			break;
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 774cd22..21febbb 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1418,8 +1418,10 @@
 	}
 
 	ret = hid_hw_output_report(hdev, buf, 1);
-	if (ret < 0)
-		hid_err(hdev, "can't set operational mode: step 3\n");
+	if (ret < 0) {
+		hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
+		ret = 0;
+	}
 
 out:
 	kfree(buf);
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 0b80633..d4d655a 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -364,6 +364,15 @@
 	if (ret)
 		return ret;
 
+	/*
+	 * The HID over I2C specification states that if a DEVICE needs time
+	 * after the PWR_ON request, it should utilise CLOCK stretching.
+	 * However, it has been observered that the Windows driver provides a
+	 * 1ms sleep between the PWR_ON and RESET requests and that some devices
+	 * rely on this.
+	 */
+	usleep_range(1000, 5000);
+
 	i2c_hid_dbg(ihid, "resetting...\n");
 
 	ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index e094c57..690a9f0 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -28,6 +28,8 @@
 #define UHID_NAME	"uhid"
 #define UHID_BUFSIZE	32
 
+static DEFINE_MUTEX(uhid_open_mutex);
+
 struct uhid_device {
 	struct mutex devlock;
 	bool running;
@@ -51,10 +53,26 @@
 	u32 report_id;
 	u32 report_type;
 	struct uhid_event report_buf;
+	struct work_struct worker;
 };
 
 static struct miscdevice uhid_misc;
 
+static void uhid_device_add_worker(struct work_struct *work)
+{
+	struct uhid_device *uhid = container_of(work, struct uhid_device, worker);
+	int ret;
+
+	ret = hid_add_device(uhid->hid);
+	if (ret) {
+		hid_err(uhid->hid, "Cannot register HID device: error %d\n", ret);
+
+		hid_destroy_device(uhid->hid);
+		uhid->hid = NULL;
+		uhid->running = false;
+	}
+}
+
 static void uhid_queue(struct uhid_device *uhid, struct uhid_event *ev)
 {
 	__u8 newhead;
@@ -126,15 +144,26 @@
 static int uhid_hid_open(struct hid_device *hid)
 {
 	struct uhid_device *uhid = hid->driver_data;
+	int retval = 0;
 
-	return uhid_queue_event(uhid, UHID_OPEN);
+	mutex_lock(&uhid_open_mutex);
+	if (!hid->open++) {
+		retval = uhid_queue_event(uhid, UHID_OPEN);
+		if (retval)
+			hid->open--;
+	}
+	mutex_unlock(&uhid_open_mutex);
+	return retval;
 }
 
 static void uhid_hid_close(struct hid_device *hid)
 {
 	struct uhid_device *uhid = hid->driver_data;
 
-	uhid_queue_event(uhid, UHID_CLOSE);
+	mutex_lock(&uhid_open_mutex);
+	if (!--hid->open)
+		uhid_queue_event(uhid, UHID_CLOSE);
+	mutex_unlock(&uhid_open_mutex);
 }
 
 static int uhid_hid_parse(struct hid_device *hid)
@@ -498,18 +527,14 @@
 	uhid->hid = hid;
 	uhid->running = true;
 
-	ret = hid_add_device(hid);
-	if (ret) {
-		hid_err(hid, "Cannot register HID device\n");
-		goto err_hid;
-	}
+	/* Adding of a HID device is done through a worker, to allow HID drivers
+	 * which use feature requests during .probe to work, without they would
+	 * be blocked on devlock, which is held by uhid_char_write.
+	 */
+	schedule_work(&uhid->worker);
 
 	return 0;
 
-err_hid:
-	hid_destroy_device(hid);
-	uhid->hid = NULL;
-	uhid->running = false;
 err_free:
 	kfree(uhid->rd_data);
 	uhid->rd_data = NULL;
@@ -550,6 +575,8 @@
 	uhid->running = false;
 	wake_up_interruptible(&uhid->report_wait);
 
+	cancel_work_sync(&uhid->worker);
+
 	hid_destroy_device(uhid->hid);
 	kfree(uhid->rd_data);
 
@@ -612,6 +639,7 @@
 	init_waitqueue_head(&uhid->waitq);
 	init_waitqueue_head(&uhid->report_wait);
 	uhid->running = false;
+	INIT_WORK(&uhid->worker, uhid_device_add_worker);
 
 	file->private_data = uhid;
 	nonseekable_open(inode, file);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index dc8e6ad..ce1543d 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -61,6 +61,7 @@
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET },
@@ -71,6 +72,7 @@
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
 	{ USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 2f1ddca..700145b 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -516,13 +516,13 @@
 					goto inval;
 			} else if (uref->usage_index >= field->report_count)
 				goto inval;
-
-			else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
-				 (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
-				  uref->usage_index + uref_multi->num_values > field->report_count))
-				goto inval;
 		}
 
+		if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+		    (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+		     uref->usage_index + uref_multi->num_values > field->report_count))
+			goto inval;
+
 		switch (cmd) {
 		case HIDIOCGUSAGE:
 			uref->value = field->value[uref->usage_index];
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 5c02d7b..b62c50d 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -148,19 +148,21 @@
 		wacom->id[0] = STYLUS_DEVICE_ID;
 	}
 
-	pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
-	if (features->pressure_max > 255)
-		pressure = (pressure << 1) | ((data[4] >> 6) & 1);
-	pressure += (features->pressure_max + 1) / 2;
+	if (prox) {
+		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
+		if (features->pressure_max > 255)
+			pressure = (pressure << 1) | ((data[4] >> 6) & 1);
+		pressure += (features->pressure_max + 1) / 2;
 
-	input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
-	input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
-	input_report_abs(input, ABS_PRESSURE, pressure);
+		input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
+		input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
+		input_report_abs(input, ABS_PRESSURE, pressure);
 
-	input_report_key(input, BTN_TOUCH, data[4] & 0x08);
-	input_report_key(input, BTN_STYLUS, data[4] & 0x10);
-	/* Only allow the stylus2 button to be reported for the pen tool. */
-	input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
+		input_report_key(input, BTN_TOUCH, data[4] & 0x08);
+		input_report_key(input, BTN_STYLUS, data[4] & 0x10);
+		/* Only allow the stylus2 button to be reported for the pen tool. */
+		input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
+	}
 
 	if (!prox)
 		wacom->id[0] = 0;
@@ -1438,37 +1440,38 @@
 {
 	unsigned char *data = wacom->data;
 
-	if (wacom->pen_input)
+	if (wacom->pen_input) {
 		dev_dbg(wacom->pen_input->dev.parent,
 			"%s: received report #%d\n", __func__, data[0]);
-	else if (wacom->touch_input)
+
+		if (len == WACOM_PKGLEN_PENABLED ||
+		    data[0] == WACOM_REPORT_PENABLED)
+			return wacom_tpc_pen(wacom);
+	}
+	else if (wacom->touch_input) {
 		dev_dbg(wacom->touch_input->dev.parent,
 			"%s: received report #%d\n", __func__, data[0]);
 
-	switch (len) {
-	case WACOM_PKGLEN_TPC1FG:
-		return wacom_tpc_single_touch(wacom, len);
-
-	case WACOM_PKGLEN_TPC2FG:
-		return wacom_tpc_mt_touch(wacom);
-
-	case WACOM_PKGLEN_PENABLED:
-		return wacom_tpc_pen(wacom);
-
-	default:
-		switch (data[0]) {
-		case WACOM_REPORT_TPC1FG:
-		case WACOM_REPORT_TPCHID:
-		case WACOM_REPORT_TPCST:
-		case WACOM_REPORT_TPC1FGE:
+		switch (len) {
+		case WACOM_PKGLEN_TPC1FG:
 			return wacom_tpc_single_touch(wacom, len);
 
-		case WACOM_REPORT_TPCMT:
-		case WACOM_REPORT_TPCMT2:
-			return wacom_mt_touch(wacom);
+		case WACOM_PKGLEN_TPC2FG:
+			return wacom_tpc_mt_touch(wacom);
 
-		case WACOM_REPORT_PENABLED:
-			return wacom_tpc_pen(wacom);
+		default:
+			switch (data[0]) {
+			case WACOM_REPORT_TPC1FG:
+			case WACOM_REPORT_TPCHID:
+			case WACOM_REPORT_TPCST:
+			case WACOM_REPORT_TPC1FGE:
+				return wacom_tpc_single_touch(wacom, len);
+
+			case WACOM_REPORT_TPCMT:
+			case WACOM_REPORT_TPCMT2:
+				return wacom_mt_touch(wacom);
+
+			}
 		}
 	}
 
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 9098f13..d037454 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/hyperv.h>
 #include <linux/uio.h>
+#include <linux/interrupt.h>
 
 #include "hyperv_vmbus.h"
 
@@ -72,7 +73,6 @@
 	void *in, *out;
 	unsigned long flags;
 	int ret, err = 0;
-	unsigned long t;
 	struct page *page;
 
 	spin_lock_irqsave(&newchannel->lock, flags);
@@ -182,11 +182,7 @@
 		goto error1;
 	}
 
-	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
-	if (t == 0) {
-		err = -ETIMEDOUT;
-		goto error1;
-	}
+	wait_for_completion(&open_info->waitevent);
 
 	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_del(&open_info->msglistentry);
@@ -374,7 +370,7 @@
 	struct vmbus_channel_gpadl_header *gpadlmsg;
 	struct vmbus_channel_gpadl_body *gpadl_body;
 	struct vmbus_channel_msginfo *msginfo = NULL;
-	struct vmbus_channel_msginfo *submsginfo;
+	struct vmbus_channel_msginfo *submsginfo, *tmp;
 	u32 msgcount;
 	struct list_head *curr;
 	u32 next_gpadl_handle;
@@ -436,6 +432,13 @@
 	list_del(&msginfo->msglistentry);
 	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
+	if (msgcount > 1) {
+		list_for_each_entry_safe(submsginfo, tmp, &msginfo->submsglist,
+			 msglistentry) {
+			kfree(submsginfo);
+		}
+	}
+
 	kfree(msginfo);
 	return ret;
 }
@@ -496,8 +499,21 @@
 static int vmbus_close_internal(struct vmbus_channel *channel)
 {
 	struct vmbus_channel_close_channel *msg;
+	struct tasklet_struct *tasklet;
 	int ret;
 
+	/*
+	 * process_chn_event(), running in the tasklet, can race
+	 * with vmbus_close_internal() in the case of SMP guest, e.g., when
+	 * the former is accessing channel->inbound.ring_buffer, the latter
+	 * could be freeing the ring_buffer pages.
+	 *
+	 * To resolve the race, we can serialize them by disabling the
+	 * tasklet when the latter is running here.
+	 */
+	tasklet = hv_context.event_dpc[channel->target_cpu];
+	tasklet_disable(tasklet);
+
 	channel->state = CHANNEL_OPEN_STATE;
 	channel->sc_creation_callback = NULL;
 	/* Stop callback and cancel the timer asap */
@@ -525,7 +541,7 @@
 		 * If we failed to post the close msg,
 		 * it is perhaps better to leak memory.
 		 */
-		return ret;
+		goto out;
 	}
 
 	/* Tear down the gpadl for the channel's ring buffer */
@@ -538,7 +554,7 @@
 			 * If we failed to teardown gpadl,
 			 * it is perhaps better to leak memory.
 			 */
-			return ret;
+			goto out;
 		}
 	}
 
@@ -549,12 +565,9 @@
 	free_pages((unsigned long)channel->ringbuffer_pages,
 		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
 
-	/*
-	 * If the channel has been rescinded; process device removal.
-	 */
-	if (channel->rescind)
-		hv_process_channel_removal(channel,
-					   channel->offermsg.child_relid);
+out:
+	tasklet_enable(tasklet);
+
 	return ret;
 }
 
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 652afd1..37238df 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -28,6 +28,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/completion.h>
+#include <linux/delay.h>
 #include <linux/hyperv.h>
 
 #include "hyperv_vmbus.h"
@@ -191,6 +192,8 @@
 	if (channel == NULL)
 		return;
 
+	BUG_ON(!channel->rescind);
+
 	if (channel->target_cpu != get_cpu()) {
 		put_cpu();
 		smp_call_function_single(channel->target_cpu,
@@ -230,9 +233,7 @@
 
 	list_for_each_entry_safe(channel, tmp, &vmbus_connection.chn_list,
 		listentry) {
-		/* if we don't set rescind to true, vmbus_close_internal()
-		 * won't invoke hv_process_channel_removal().
-		 */
+		/* hv_process_channel_removal() needs this */
 		channel->rescind = true;
 
 		vmbus_device_unregister(channel->device_obj);
@@ -459,6 +460,17 @@
 		    cpumask_of_node(primary->numa_node));
 
 	cur_cpu = -1;
+
+	/*
+	 * Normally Hyper-V host doesn't create more subchannels than there
+	 * are VCPUs on the node but it is possible when not all present VCPUs
+	 * on the node are initialized by guest. Clear the alloced_cpus_in_node
+	 * to start over.
+	 */
+	if (cpumask_equal(&primary->alloced_cpus_in_node,
+			  cpumask_of_node(primary->numa_node)))
+		cpumask_clear(&primary->alloced_cpus_in_node);
+
 	while (true) {
 		cur_cpu = cpumask_next(cur_cpu, &available_mask);
 		if (cur_cpu >= nr_cpu_ids) {
@@ -488,6 +500,40 @@
 	channel->target_vp = hv_context.vp_index[cur_cpu];
 }
 
+static void vmbus_wait_for_unload(void)
+{
+	int cpu = smp_processor_id();
+	void *page_addr = hv_context.synic_message_page[cpu];
+	struct hv_message *msg = (struct hv_message *)page_addr +
+				  VMBUS_MESSAGE_SINT;
+	struct vmbus_channel_message_header *hdr;
+	bool unloaded = false;
+
+	while (1) {
+		if (msg->header.message_type == HVMSG_NONE) {
+			mdelay(10);
+			continue;
+		}
+
+		hdr = (struct vmbus_channel_message_header *)msg->u.payload;
+		if (hdr->msgtype == CHANNELMSG_UNLOAD_RESPONSE)
+			unloaded = true;
+
+		msg->header.message_type = HVMSG_NONE;
+		/*
+		 * header.message_type needs to be written before we do
+		 * wrmsrl() below.
+		 */
+		mb();
+
+		if (msg->header.message_flags.msg_pending)
+			wrmsrl(HV_X64_MSR_EOM, 0);
+
+		if (unloaded)
+			break;
+	}
+}
+
 /*
  * vmbus_unload_response - Handler for the unload response.
  */
@@ -513,7 +559,14 @@
 	hdr.msgtype = CHANNELMSG_UNLOAD;
 	vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header));
 
-	wait_for_completion(&vmbus_connection.unload_event);
+	/*
+	 * vmbus_initiate_unload() is also called on crash and the crash can be
+	 * happening in an interrupt context, where scheduling is impossible.
+	 */
+	if (!in_interrupt())
+		wait_for_completion(&vmbus_connection.unload_event);
+	else
+		vmbus_wait_for_unload();
 }
 
 /*
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 4fc2e88..2bbc530 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -429,7 +429,7 @@
 	union hv_connection_id conn_id;
 	int ret = 0;
 	int retries = 0;
-	u32 msec = 1;
+	u32 usec = 1;
 
 	conn_id.asu32 = 0;
 	conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
@@ -462,9 +462,9 @@
 		}
 
 		retries++;
-		msleep(msec);
-		if (msec < 2048)
-			msec *= 2;
+		udelay(usec);
+		if (usec < 2048)
+			usec *= 2;
 	}
 	return ret;
 }
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 6341be8..8ce1f2e 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -219,7 +219,7 @@
 	/* See if the hypercall page is already set */
 	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
 
-	virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
+	virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
 
 	if (!virtaddr)
 		goto cleanup;
@@ -274,7 +274,7 @@
  *
  * This routine is called normally during driver unloading or exiting.
  */
-void hv_cleanup(void)
+void hv_cleanup(bool crash)
 {
 	union hv_x64_msr_hypercall_contents hypercall_msr;
 
@@ -284,7 +284,8 @@
 	if (hv_context.hypercall_page) {
 		hypercall_msr.as_uint64 = 0;
 		wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
-		vfree(hv_context.hypercall_page);
+		if (!crash)
+			vfree(hv_context.hypercall_page);
 		hv_context.hypercall_page = NULL;
 	}
 
@@ -293,13 +294,21 @@
 	 * Cleanup the TSC page based CS.
 	 */
 	if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
-		clocksource_change_rating(&hyperv_cs_tsc, 10);
-		clocksource_unregister(&hyperv_cs_tsc);
+		/*
+		 * Crash can happen in an interrupt context and unregistering
+		 * a clocksource is impossible and redundant in this case.
+		 */
+		if (!oops_in_progress) {
+			clocksource_change_rating(&hyperv_cs_tsc, 10);
+			clocksource_unregister(&hyperv_cs_tsc);
+		}
 
 		hypercall_msr.as_uint64 = 0;
 		wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
-		vfree(hv_context.tsc_page);
-		hv_context.tsc_page = NULL;
+		if (!crash) {
+			vfree(hv_context.tsc_page);
+			hv_context.tsc_page = NULL;
+		}
 	}
 #endif
 }
@@ -416,7 +425,7 @@
 		goto err;
 	}
 
-	for_each_online_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
 		if (hv_context.event_dpc[cpu] == NULL) {
 			pr_err("Unable to allocate event dpc\n");
@@ -455,6 +464,8 @@
 			pr_err("Unable to allocate post msg page\n");
 			goto err;
 		}
+
+		INIT_LIST_HEAD(&hv_context.percpu_list[cpu]);
 	}
 
 	return 0;
@@ -479,7 +490,7 @@
 	int cpu;
 
 	kfree(hv_context.hv_numa_map);
-	for_each_online_cpu(cpu)
+	for_each_present_cpu(cpu)
 		hv_synic_free_cpu(cpu);
 }
 
@@ -549,8 +560,6 @@
 	rdmsrl(HV_X64_MSR_VP_INDEX, vp_index);
 	hv_context.vp_index[cpu] = (u32)vp_index;
 
-	INIT_LIST_HEAD(&hv_context.percpu_list[cpu]);
-
 	/*
 	 * Register the per-cpu clockevent source.
 	 */
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index b853b4b..354da7f 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -430,16 +430,27 @@
  * currently hot added. We hot add in multiples of 128M
  * chunks; it is possible that we may not be able to bring
  * online all the pages in the region. The range
- * covered_end_pfn defines the pages that can
+ * covered_start_pfn:covered_end_pfn defines the pages that can
  * be brough online.
  */
 
 struct hv_hotadd_state {
 	struct list_head list;
 	unsigned long start_pfn;
+	unsigned long covered_start_pfn;
 	unsigned long covered_end_pfn;
 	unsigned long ha_end_pfn;
 	unsigned long end_pfn;
+	/*
+	 * A list of gaps.
+	 */
+	struct list_head gap_list;
+};
+
+struct hv_hotadd_gap {
+	struct list_head list;
+	unsigned long start_pfn;
+	unsigned long end_pfn;
 };
 
 struct balloon_state {
@@ -595,18 +606,46 @@
 	.priority = 0
 };
 
+/* Check if the particular page is backed and can be onlined and online it. */
+static void hv_page_online_one(struct hv_hotadd_state *has, struct page *pg)
+{
+	unsigned long cur_start_pgp;
+	unsigned long cur_end_pgp;
+	struct hv_hotadd_gap *gap;
 
-static void hv_bring_pgs_online(unsigned long start_pfn, unsigned long size)
+	cur_start_pgp = (unsigned long)pfn_to_page(has->covered_start_pfn);
+	cur_end_pgp = (unsigned long)pfn_to_page(has->covered_end_pfn);
+
+	/* The page is not backed. */
+	if (((unsigned long)pg < cur_start_pgp) ||
+	    ((unsigned long)pg >= cur_end_pgp))
+		return;
+
+	/* Check for gaps. */
+	list_for_each_entry(gap, &has->gap_list, list) {
+		cur_start_pgp = (unsigned long)
+			pfn_to_page(gap->start_pfn);
+		cur_end_pgp = (unsigned long)
+			pfn_to_page(gap->end_pfn);
+		if (((unsigned long)pg >= cur_start_pgp) &&
+		    ((unsigned long)pg < cur_end_pgp)) {
+			return;
+		}
+	}
+
+	/* This frame is currently backed; online the page. */
+	__online_page_set_limits(pg);
+	__online_page_increment_counters(pg);
+	__online_page_free(pg);
+}
+
+static void hv_bring_pgs_online(struct hv_hotadd_state *has,
+				unsigned long start_pfn, unsigned long size)
 {
 	int i;
 
-	for (i = 0; i < size; i++) {
-		struct page *pg;
-		pg = pfn_to_page(start_pfn + i);
-		__online_page_set_limits(pg);
-		__online_page_increment_counters(pg);
-		__online_page_free(pg);
-	}
+	for (i = 0; i < size; i++)
+		hv_page_online_one(has, pfn_to_page(start_pfn + i));
 }
 
 static void hv_mem_hot_add(unsigned long start, unsigned long size,
@@ -682,26 +721,25 @@
 
 	list_for_each(cur, &dm_device.ha_region_list) {
 		has = list_entry(cur, struct hv_hotadd_state, list);
-		cur_start_pgp = (unsigned long)pfn_to_page(has->start_pfn);
-		cur_end_pgp = (unsigned long)pfn_to_page(has->covered_end_pfn);
+		cur_start_pgp = (unsigned long)
+			pfn_to_page(has->start_pfn);
+		cur_end_pgp = (unsigned long)pfn_to_page(has->end_pfn);
 
-		if (((unsigned long)pg >= cur_start_pgp) &&
-			((unsigned long)pg < cur_end_pgp)) {
-			/*
-			 * This frame is currently backed; online the
-			 * page.
-			 */
-			__online_page_set_limits(pg);
-			__online_page_increment_counters(pg);
-			__online_page_free(pg);
-		}
+		/* The page belongs to a different HAS. */
+		if (((unsigned long)pg < cur_start_pgp) ||
+		    ((unsigned long)pg >= cur_end_pgp))
+			continue;
+
+		hv_page_online_one(has, pg);
+		break;
 	}
 }
 
-static bool pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt)
+static int pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt)
 {
 	struct list_head *cur;
 	struct hv_hotadd_state *has;
+	struct hv_hotadd_gap *gap;
 	unsigned long residual, new_inc;
 
 	if (list_empty(&dm_device.ha_region_list))
@@ -714,8 +752,26 @@
 		 * If the pfn range we are dealing with is not in the current
 		 * "hot add block", move on.
 		 */
-		if ((start_pfn >= has->end_pfn))
+		if (start_pfn < has->start_pfn || start_pfn >= has->end_pfn)
 			continue;
+
+		/*
+		 * If the current start pfn is not where the covered_end
+		 * is, create a gap and update covered_end_pfn.
+		 */
+		if (has->covered_end_pfn != start_pfn) {
+			gap = kzalloc(sizeof(struct hv_hotadd_gap), GFP_ATOMIC);
+			if (!gap)
+				return -ENOMEM;
+
+			INIT_LIST_HEAD(&gap->list);
+			gap->start_pfn = has->covered_end_pfn;
+			gap->end_pfn = start_pfn;
+			list_add_tail(&gap->list, &has->gap_list);
+
+			has->covered_end_pfn = start_pfn;
+		}
+
 		/*
 		 * If the current hot add-request extends beyond
 		 * our current limit; extend it.
@@ -732,19 +788,10 @@
 			has->end_pfn += new_inc;
 		}
 
-		/*
-		 * If the current start pfn is not where the covered_end
-		 * is, update it.
-		 */
-
-		if (has->covered_end_pfn != start_pfn)
-			has->covered_end_pfn = start_pfn;
-
-		return true;
-
+		return 1;
 	}
 
-	return false;
+	return 0;
 }
 
 static unsigned long handle_pg_range(unsigned long pg_start,
@@ -768,7 +815,7 @@
 		 * If the pfn range we are dealing with is not in the current
 		 * "hot add block", move on.
 		 */
-		if ((start_pfn >= has->end_pfn))
+		if (start_pfn < has->start_pfn || start_pfn >= has->end_pfn)
 			continue;
 
 		old_covered_state = has->covered_end_pfn;
@@ -783,6 +830,8 @@
 			if (pgs_ol > pfn_cnt)
 				pgs_ol = pfn_cnt;
 
+			has->covered_end_pfn +=  pgs_ol;
+			pfn_cnt -= pgs_ol;
 			/*
 			 * Check if the corresponding memory block is already
 			 * online by checking its last previously backed page.
@@ -791,10 +840,8 @@
 			 */
 			if (start_pfn > has->start_pfn &&
 			    !PageReserved(pfn_to_page(start_pfn - 1)))
-				hv_bring_pgs_online(start_pfn, pgs_ol);
+				hv_bring_pgs_online(has, start_pfn, pgs_ol);
 
-			has->covered_end_pfn +=  pgs_ol;
-			pfn_cnt -= pgs_ol;
 		}
 
 		if ((has->ha_end_pfn < has->end_pfn) && (pfn_cnt > 0)) {
@@ -832,13 +879,19 @@
 					unsigned long rg_size)
 {
 	struct hv_hotadd_state *ha_region = NULL;
+	int covered;
 
 	if (pfn_cnt == 0)
 		return 0;
 
-	if (!dm_device.host_specified_ha_region)
-		if (pfn_covered(pg_start, pfn_cnt))
+	if (!dm_device.host_specified_ha_region) {
+		covered = pfn_covered(pg_start, pfn_cnt);
+		if (covered < 0)
+			return 0;
+
+		if (covered)
 			goto do_pg_range;
+	}
 
 	/*
 	 * If the host has specified a hot-add range; deal with it first.
@@ -850,10 +903,12 @@
 			return 0;
 
 		INIT_LIST_HEAD(&ha_region->list);
+		INIT_LIST_HEAD(&ha_region->gap_list);
 
 		list_add_tail(&ha_region->list, &dm_device.ha_region_list);
 		ha_region->start_pfn = rg_start;
 		ha_region->ha_end_pfn = rg_start;
+		ha_region->covered_start_pfn = pg_start;
 		ha_region->covered_end_pfn = pg_start;
 		ha_region->end_pfn = rg_start + rg_size;
 	}
@@ -1581,6 +1636,7 @@
 	struct hv_dynmem_device *dm = hv_get_drvdata(dev);
 	struct list_head *cur, *tmp;
 	struct hv_hotadd_state *has;
+	struct hv_hotadd_gap *gap, *tmp_gap;
 
 	if (dm->num_pages_ballooned != 0)
 		pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned);
@@ -1597,6 +1653,10 @@
 #endif
 	list_for_each_safe(cur, tmp, &dm->ha_region_list) {
 		has = list_entry(cur, struct hv_hotadd_state, list);
+		list_for_each_entry_safe(gap, tmp_gap, &has->gap_list, list) {
+			list_del(&gap->list);
+			kfree(gap);
+		}
 		list_del(&has->list);
 		kfree(has);
 	}
diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c
index db4b887..1fb02dc 100644
--- a/drivers/hv/hv_fcopy.c
+++ b/drivers/hv/hv_fcopy.c
@@ -51,7 +51,6 @@
 	struct hv_fcopy_hdr  *fcopy_msg; /* current message */
 	struct vmbus_channel *recv_channel; /* chn we got the request */
 	u64 recv_req_id; /* request ID. */
-	void *fcopy_context; /* for the channel callback */
 } fcopy_transaction;
 
 static void fcopy_respond_to_host(int error);
@@ -62,11 +61,19 @@
 static const char fcopy_devname[] = "vmbus/hv_fcopy";
 static u8 *recv_buffer;
 static struct hvutil_transport *hvt;
+static struct completion release_event;
 /*
  * This state maintains the version number registered by the daemon.
  */
 static int dm_reg_value;
 
+static void fcopy_poll_wrapper(void *channel)
+{
+	/* Transaction is finished, reset the state here to avoid races. */
+	fcopy_transaction.state = HVUTIL_READY;
+	hv_fcopy_onchannelcallback(channel);
+}
+
 static void fcopy_timeout_func(struct work_struct *dummy)
 {
 	/*
@@ -74,13 +81,7 @@
 	 * process the pending transaction.
 	 */
 	fcopy_respond_to_host(HV_E_FAIL);
-
-	/* Transaction is finished, reset the state. */
-	if (fcopy_transaction.state > HVUTIL_READY)
-		fcopy_transaction.state = HVUTIL_READY;
-
-	hv_poll_channel(fcopy_transaction.fcopy_context,
-			hv_fcopy_onchannelcallback);
+	hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
 }
 
 static int fcopy_handle_handshake(u32 version)
@@ -108,9 +109,7 @@
 		return -EINVAL;
 	}
 	pr_debug("FCP: userspace daemon ver. %d registered\n", version);
-	fcopy_transaction.state = HVUTIL_READY;
-	hv_poll_channel(fcopy_transaction.fcopy_context,
-			hv_fcopy_onchannelcallback);
+	hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
 	return 0;
 }
 
@@ -227,15 +226,8 @@
 	int util_fw_version;
 	int fcopy_srv_version;
 
-	if (fcopy_transaction.state > HVUTIL_READY) {
-		/*
-		 * We will defer processing this callback once
-		 * the current transaction is complete.
-		 */
-		fcopy_transaction.fcopy_context = context;
+	if (fcopy_transaction.state > HVUTIL_READY)
 		return;
-	}
-	fcopy_transaction.fcopy_context = NULL;
 
 	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
 			 &requestid);
@@ -275,7 +267,8 @@
 		 * Send the information to the user-level daemon.
 		 */
 		schedule_work(&fcopy_send_work);
-		schedule_delayed_work(&fcopy_timeout_work, 5*HZ);
+		schedule_delayed_work(&fcopy_timeout_work,
+				      HV_UTIL_TIMEOUT * HZ);
 		return;
 	}
 	icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
@@ -304,9 +297,8 @@
 	if (cancel_delayed_work_sync(&fcopy_timeout_work)) {
 		fcopy_transaction.state = HVUTIL_USERSPACE_RECV;
 		fcopy_respond_to_host(*val);
-		fcopy_transaction.state = HVUTIL_READY;
-		hv_poll_channel(fcopy_transaction.fcopy_context,
-				hv_fcopy_onchannelcallback);
+		hv_poll_channel(fcopy_transaction.recv_channel,
+				fcopy_poll_wrapper);
 	}
 
 	return 0;
@@ -321,12 +313,14 @@
 
 	if (cancel_delayed_work_sync(&fcopy_timeout_work))
 		fcopy_respond_to_host(HV_E_FAIL);
+	complete(&release_event);
 }
 
 int hv_fcopy_init(struct hv_util_service *srv)
 {
 	recv_buffer = srv->recv_buffer;
 
+	init_completion(&release_event);
 	/*
 	 * When this driver loads, the user level daemon that
 	 * processes the host requests may not yet be running.
@@ -348,4 +342,5 @@
 	fcopy_transaction.state = HVUTIL_DEVICE_DYING;
 	cancel_delayed_work_sync(&fcopy_timeout_work);
 	hvutil_transport_destroy(hvt);
+	wait_for_completion(&release_event);
 }
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 74c38a9..ce4d3a9 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -66,7 +66,6 @@
 	struct hv_kvp_msg  *kvp_msg; /* current message */
 	struct vmbus_channel *recv_channel; /* chn we got the request */
 	u64 recv_req_id; /* request ID. */
-	void *kvp_context; /* for the channel callback */
 } kvp_transaction;
 
 /*
@@ -87,6 +86,7 @@
 static const char kvp_devname[] = "vmbus/hv_kvp";
 static u8 *recv_buffer;
 static struct hvutil_transport *hvt;
+static struct completion release_event;
 /*
  * Register the kernel component with the user-level daemon.
  * As part of this registration, pass the LIC version number.
@@ -94,6 +94,13 @@
  */
 #define HV_DRV_VERSION           "3.1"
 
+static void kvp_poll_wrapper(void *channel)
+{
+	/* Transaction is finished, reset the state here to avoid races. */
+	kvp_transaction.state = HVUTIL_READY;
+	hv_kvp_onchannelcallback(channel);
+}
+
 static void
 kvp_register(int reg_value)
 {
@@ -121,12 +128,7 @@
 	 */
 	kvp_respond_to_host(NULL, HV_E_FAIL);
 
-	/* Transaction is finished, reset the state. */
-	if (kvp_transaction.state > HVUTIL_READY)
-		kvp_transaction.state = HVUTIL_READY;
-
-	hv_poll_channel(kvp_transaction.kvp_context,
-			hv_kvp_onchannelcallback);
+	hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
 }
 
 static int kvp_handle_handshake(struct hv_kvp_msg *msg)
@@ -218,9 +220,7 @@
 	 */
 	if (cancel_delayed_work_sync(&kvp_timeout_work)) {
 		kvp_respond_to_host(message, error);
-		kvp_transaction.state = HVUTIL_READY;
-		hv_poll_channel(kvp_transaction.kvp_context,
-				hv_kvp_onchannelcallback);
+		hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
 	}
 
 	return 0;
@@ -596,15 +596,8 @@
 	int util_fw_version;
 	int kvp_srv_version;
 
-	if (kvp_transaction.state > HVUTIL_READY) {
-		/*
-		 * We will defer processing this callback once
-		 * the current transaction is complete.
-		 */
-		kvp_transaction.kvp_context = context;
+	if (kvp_transaction.state > HVUTIL_READY)
 		return;
-	}
-	kvp_transaction.kvp_context = NULL;
 
 	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 4, &recvlen,
 			 &requestid);
@@ -668,7 +661,8 @@
 			 * user-mode not responding.
 			 */
 			schedule_work(&kvp_sendkey_work);
-			schedule_delayed_work(&kvp_timeout_work, 5*HZ);
+			schedule_delayed_work(&kvp_timeout_work,
+					      HV_UTIL_TIMEOUT * HZ);
 
 			return;
 
@@ -689,6 +683,7 @@
 	if (cancel_delayed_work_sync(&kvp_timeout_work))
 		kvp_respond_to_host(NULL, HV_E_FAIL);
 	kvp_transaction.state = HVUTIL_DEVICE_INIT;
+	complete(&release_event);
 }
 
 int
@@ -696,6 +691,7 @@
 {
 	recv_buffer = srv->recv_buffer;
 
+	init_completion(&release_event);
 	/*
 	 * When this driver loads, the user level daemon that
 	 * processes the host requests may not yet be running.
@@ -718,4 +714,5 @@
 	cancel_delayed_work_sync(&kvp_timeout_work);
 	cancel_work_sync(&kvp_sendkey_work);
 	hvutil_transport_destroy(hvt);
+	wait_for_completion(&release_event);
 }
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 815405f..faad79a 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -53,7 +53,6 @@
 	struct vmbus_channel *recv_channel; /* chn we got the request */
 	u64 recv_req_id; /* request ID. */
 	struct hv_vss_msg  *msg; /* current message */
-	void *vss_context; /* for the channel callback */
 } vss_transaction;
 
 
@@ -67,6 +66,7 @@
 static const char vss_devname[] = "vmbus/hv_vss";
 static __u8 *recv_buffer;
 static struct hvutil_transport *hvt;
+static struct completion release_event;
 
 static void vss_send_op(struct work_struct *dummy);
 static void vss_timeout_func(struct work_struct *dummy);
@@ -74,6 +74,13 @@
 static DECLARE_DELAYED_WORK(vss_timeout_work, vss_timeout_func);
 static DECLARE_WORK(vss_send_op_work, vss_send_op);
 
+static void vss_poll_wrapper(void *channel)
+{
+	/* Transaction is finished, reset the state here to avoid races. */
+	vss_transaction.state = HVUTIL_READY;
+	hv_vss_onchannelcallback(channel);
+}
+
 /*
  * Callback when data is received from user mode.
  */
@@ -86,12 +93,7 @@
 	pr_warn("VSS: timeout waiting for daemon to reply\n");
 	vss_respond_to_host(HV_E_FAIL);
 
-	/* Transaction is finished, reset the state. */
-	if (vss_transaction.state > HVUTIL_READY)
-		vss_transaction.state = HVUTIL_READY;
-
-	hv_poll_channel(vss_transaction.vss_context,
-			hv_vss_onchannelcallback);
+	hv_poll_channel(vss_transaction.recv_channel, vss_poll_wrapper);
 }
 
 static int vss_handle_handshake(struct hv_vss_msg *vss_msg)
@@ -138,9 +140,8 @@
 		if (cancel_delayed_work_sync(&vss_timeout_work)) {
 			vss_respond_to_host(vss_msg->error);
 			/* Transaction is finished, reset the state. */
-			vss_transaction.state = HVUTIL_READY;
-			hv_poll_channel(vss_transaction.vss_context,
-					hv_vss_onchannelcallback);
+			hv_poll_channel(vss_transaction.recv_channel,
+					vss_poll_wrapper);
 		}
 	} else {
 		/* This is a spurious call! */
@@ -238,15 +239,8 @@
 	struct icmsg_hdr *icmsghdrp;
 	struct icmsg_negotiate *negop = NULL;
 
-	if (vss_transaction.state > HVUTIL_READY) {
-		/*
-		 * We will defer processing this callback once
-		 * the current transaction is complete.
-		 */
-		vss_transaction.vss_context = context;
+	if (vss_transaction.state > HVUTIL_READY)
 		return;
-	}
-	vss_transaction.vss_context = NULL;
 
 	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
 			 &requestid);
@@ -333,11 +327,18 @@
 	if (cancel_delayed_work_sync(&vss_timeout_work))
 		vss_respond_to_host(HV_E_FAIL);
 	vss_transaction.state = HVUTIL_DEVICE_INIT;
+	complete(&release_event);
 }
 
 int
 hv_vss_init(struct hv_util_service *srv)
 {
+	init_completion(&release_event);
+	if (vmbus_proto_version < VERSION_WIN8_1) {
+		pr_warn("Integration service 'Backup (volume snapshot)'"
+			" not supported on this host version.\n");
+		return -ENOTSUPP;
+	}
 	recv_buffer = srv->recv_buffer;
 
 	/*
@@ -362,4 +363,5 @@
 	cancel_delayed_work_sync(&vss_timeout_work);
 	cancel_work_sync(&vss_send_op_work);
 	hvutil_transport_destroy(hvt);
+	wait_for_completion(&release_event);
 }
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 7994ec2..41f5896 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -283,10 +283,14 @@
 	u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
 	struct icmsg_negotiate *negop = NULL;
 
-	vmbus_recvpacket(channel, hbeat_txf_buf,
-			 PAGE_SIZE, &recvlen, &requestid);
+	while (1) {
 
-	if (recvlen > 0) {
+		vmbus_recvpacket(channel, hbeat_txf_buf,
+				 PAGE_SIZE, &recvlen, &requestid);
+
+		if (!recvlen)
+			break;
+
 		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
 				sizeof(struct vmbuspipe_hdr)];
 
diff --git a/drivers/hv/hv_utils_transport.c b/drivers/hv/hv_utils_transport.c
index 6a9d80a..1505ee6 100644
--- a/drivers/hv/hv_utils_transport.c
+++ b/drivers/hv/hv_utils_transport.c
@@ -204,9 +204,12 @@
 		goto out_unlock;
 	}
 	hvt->outmsg = kzalloc(len, GFP_KERNEL);
-	memcpy(hvt->outmsg, msg, len);
-	hvt->outmsg_len = len;
-	wake_up_interruptible(&hvt->outmsg_q);
+	if (hvt->outmsg) {
+		memcpy(hvt->outmsg, msg, len);
+		hvt->outmsg_len = len;
+		wake_up_interruptible(&hvt->outmsg_q);
+	} else
+		ret = -ENOMEM;
 out_unlock:
 	mutex_unlock(&hvt->outmsg_lock);
 	return ret;
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 3782636..75e383e 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -31,6 +31,11 @@
 #include <linux/hyperv.h>
 
 /*
+ * Timeout for services such as KVP and fcopy.
+ */
+#define HV_UTIL_TIMEOUT 30
+
+/*
  * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
  * is set by CPUID(HVCPUID_VERSION_FEATURES).
  */
@@ -576,7 +581,7 @@
 
 extern int hv_init(void);
 
-extern void hv_cleanup(void);
+extern void hv_cleanup(bool crash);
 
 extern int hv_post_message(union hv_connection_id connection_id,
 			 enum hv_message_type message_type,
@@ -759,11 +764,7 @@
 	if (!channel)
 		return;
 
-	if (channel->target_cpu != smp_processor_id())
-		smp_call_function_single(channel->target_cpu,
-					 cb, channel, true);
-	else
-		cb(channel);
+	smp_call_function_single(channel->target_cpu, cb, channel, true);
 }
 
 enum hvutil_device_state {
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index f19b6f7..802dcb4 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -41,6 +41,7 @@
 #include <linux/ptrace.h>
 #include <linux/screen_info.h>
 #include <linux/kdebug.h>
+#include <linux/random.h>
 #include "hyperv_vmbus.h"
 
 static struct acpi_device  *hv_acpi_dev;
@@ -104,6 +105,7 @@
 };
 
 struct resource *hyperv_mmio;
+DEFINE_SEMAPHORE(hyperv_mmio_lock);
 
 static int vmbus_exists(void)
 {
@@ -602,23 +604,11 @@
 {
 	struct hv_driver *drv;
 	struct hv_device *dev = device_to_hv_device(child_device);
-	u32 relid = dev->channel->offermsg.child_relid;
 
 	if (child_device->driver) {
 		drv = drv_to_hv_drv(child_device->driver);
 		if (drv->remove)
 			drv->remove(dev);
-		else {
-			hv_process_channel_removal(dev->channel, relid);
-			pr_err("remove not set for driver %s\n",
-				dev_name(child_device));
-		}
-	} else {
-		/*
-		 * We don't have a driver for this device; deal with the
-		 * rescind message by removing the channel.
-		 */
-		hv_process_channel_removal(dev->channel, relid);
 	}
 
 	return 0;
@@ -653,7 +643,10 @@
 static void vmbus_device_release(struct device *device)
 {
 	struct hv_device *hv_dev = device_to_hv_device(device);
+	struct vmbus_channel *channel = hv_dev->channel;
 
+	hv_process_channel_removal(channel,
+				   channel->offermsg.child_relid);
 	kfree(hv_dev);
 
 }
@@ -826,6 +819,8 @@
 		else
 			tasklet_schedule(&msg_dpc);
 	}
+
+	add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
 }
 
 
@@ -867,7 +862,7 @@
 	on_each_cpu(hv_synic_init, NULL, 1);
 	ret = vmbus_connect();
 	if (ret)
-		goto err_alloc;
+		goto err_connect;
 
 	if (vmbus_proto_version > VERSION_WIN7)
 		cpu_hotplug_disable();
@@ -885,6 +880,8 @@
 
 	return 0;
 
+err_connect:
+	on_each_cpu(hv_synic_cleanup, NULL, 1);
 err_alloc:
 	hv_synic_free();
 	hv_remove_vmbus_irq();
@@ -892,7 +889,7 @@
 	bus_unregister(&hv_bus);
 
 err_cleanup:
-	hv_cleanup();
+	hv_cleanup(false);
 
 	return ret;
 }
@@ -1144,7 +1141,10 @@
 	resource_size_t range_min, range_max, start, local_min, local_max;
 	const char *dev_n = dev_name(&device_obj->device);
 	u32 fb_end = screen_info.lfb_base + (screen_info.lfb_size << 1);
-	int i;
+	int i, retval;
+
+	retval = -ENXIO;
+	down(&hyperv_mmio_lock);
 
 	for (iter = hyperv_mmio; iter; iter = iter->sibling) {
 		if ((iter->start >= max) || (iter->end <= min))
@@ -1181,13 +1181,17 @@
 			for (; start + size - 1 <= local_max; start += align) {
 				*new = request_mem_region_exclusive(start, size,
 								    dev_n);
-				if (*new)
-					return 0;
+				if (*new) {
+					retval = 0;
+					goto exit;
+				}
 			}
 		}
 	}
 
-	return -ENXIO;
+exit:
+	up(&hyperv_mmio_lock);
+	return retval;
 }
 EXPORT_SYMBOL_GPL(vmbus_allocate_mmio);
 
@@ -1250,7 +1254,7 @@
 	vmbus_initiate_unload();
 	for_each_online_cpu(cpu)
 		smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
-	hv_cleanup();
+	hv_cleanup(false);
 };
 
 static void hv_crash_handler(struct pt_regs *regs)
@@ -1262,7 +1266,7 @@
 	 * for kdump.
 	 */
 	hv_synic_cleanup(NULL);
-	hv_cleanup();
+	hv_cleanup(true);
 };
 
 static int __init hv_acpi_init(void)
@@ -1326,7 +1330,7 @@
 						 &hyperv_panic_block);
 	}
 	bus_unregister(&hv_bus);
-	hv_cleanup();
+	hv_cleanup(false);
 	for_each_online_cpu(cpu) {
 		tasklet_kill(hv_context.event_dpc[cpu]);
 		smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index 6c99ee7..ee396ff 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -120,6 +120,7 @@
 	unsigned int vref_mv = ADS7828_INT_VREF_MV;
 	bool diff_input = false;
 	bool ext_vref = false;
+	unsigned int regval;
 
 	data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
 	if (!data)
@@ -154,6 +155,15 @@
 	if (!diff_input)
 		data->cmd_byte |= ADS7828_CMD_SD_SE;
 
+	/*
+	 * Datasheet specifies internal reference voltage is disabled by
+	 * default. The internal reference voltage needs to be enabled and
+	 * voltage needs to settle before getting valid ADC data. So perform a
+	 * dummy read to enable the internal reference voltage.
+	 */
+	if (!ext_vref)
+		regmap_read(data->regmap, data->cmd_byte, &regval);
+
 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
 							   data,
 							   ads7828_groups);
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index 827c037..a7f8869 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -30,6 +30,7 @@
 
 #define ADT7411_REG_CFG1			0x18
 #define ADT7411_CFG1_START_MONITOR		(1 << 0)
+#define ADT7411_CFG1_RESERVED_BIT3		(1 << 3)
 
 #define ADT7411_REG_CFG2			0x19
 #define ADT7411_CFG2_DISABLE_AVG		(1 << 5)
@@ -296,8 +297,10 @@
 	mutex_init(&data->device_lock);
 	mutex_init(&data->update_lock);
 
+	/* According to the datasheet, we must only write 1 to bit 3 */
 	ret = adt7411_modify_bit(client, ADT7411_REG_CFG1,
-				 ADT7411_CFG1_START_MONITOR, 1);
+				 ADT7411_CFG1_RESERVED_BIT3
+				 | ADT7411_CFG1_START_MONITOR, 1);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
index 12e851a..46b4e35 100644
--- a/drivers/hwmon/amc6821.c
+++ b/drivers/hwmon/amc6821.c
@@ -188,8 +188,8 @@
 			!data->valid) {
 
 		for (i = 0; i < TEMP_IDX_LEN; i++)
-			data->temp[i] = i2c_smbus_read_byte_data(client,
-				temp_reg[i]);
+			data->temp[i] = (int8_t)i2c_smbus_read_byte_data(
+				client, temp_reg[i]);
 
 		data->stat1 = i2c_smbus_read_byte_data(client,
 			AMC6821_REG_STAT1);
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index c43318d..a9356a3 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -66,11 +66,13 @@
 
 static DEFINE_MUTEX(i8k_mutex);
 static char bios_version[4];
+static char bios_machineid[16];
 static struct device *i8k_hwmon_dev;
 static u32 i8k_hwmon_flags;
 static uint i8k_fan_mult = I8K_FAN_MULT;
 static uint i8k_pwm_mult;
 static uint i8k_fan_max = I8K_FAN_HIGH;
+static bool disallow_fan_type_call;
 
 #define I8K_HWMON_HAVE_TEMP1	(1 << 0)
 #define I8K_HWMON_HAVE_TEMP2	(1 << 1)
@@ -94,13 +96,13 @@
 MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
 
 #if IS_ENABLED(CONFIG_I8K)
-static bool restricted;
+static bool restricted = true;
 module_param(restricted, bool, 0);
-MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
+MODULE_PARM_DESC(restricted, "Restrict fan control and serial number to CAP_SYS_ADMIN (default: 1)");
 
 static bool power_status;
 module_param(power_status, bool, 0600);
-MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
+MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k (default: 0)");
 #endif
 
 static uint fan_mult;
@@ -235,14 +237,28 @@
 /*
  * Read the fan type.
  */
-static int i8k_get_fan_type(int fan)
+static int _i8k_get_fan_type(int fan)
 {
 	struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };
 
+	if (disallow_fan_type_call)
+		return -EINVAL;
+
 	regs.ebx = fan & 0xff;
 	return i8k_smm(&regs) ? : regs.eax & 0xff;
 }
 
+static int i8k_get_fan_type(int fan)
+{
+	/* I8K_SMM_GET_FAN_TYPE SMM call is expensive, so cache values */
+	static int types[2] = { INT_MIN, INT_MIN };
+
+	if (types[fan] == INT_MIN)
+		types[fan] = _i8k_get_fan_type(fan);
+
+	return types[fan];
+}
+
 /*
  * Read the fan nominal rpm for specific fan speed.
  */
@@ -392,9 +408,11 @@
 		break;
 
 	case I8K_MACHINE_ID:
-		memset(buff, 0, 16);
-		strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
-			sizeof(buff));
+		if (restricted && !capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		memset(buff, 0, sizeof(buff));
+		strlcpy(buff, bios_machineid, sizeof(buff));
 		break;
 
 	case I8K_FN_STATUS:
@@ -511,7 +529,7 @@
 	seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
 		   I8K_PROC_FMT,
 		   bios_version,
-		   i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+		   (restricted && !capable(CAP_SYS_ADMIN)) ? "-1" : bios_machineid,
 		   cpu_temp,
 		   left_fan, right_fan, left_speed, right_speed,
 		   ac_power, fn_key);
@@ -718,6 +736,9 @@
 static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
 			      int index)
 {
+	if (disallow_fan_type_call &&
+	    (index == 9 || index == 12))
+		return 0;
 	if (index >= 0 && index <= 1 &&
 	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
 		return 0;
@@ -767,13 +788,17 @@
 	if (err >= 0)
 		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
 
-	/* First fan attributes, if fan type is OK */
-	err = i8k_get_fan_type(0);
+	/* First fan attributes, if fan status or type is OK */
+	err = i8k_get_fan_status(0);
+	if (err < 0)
+		err = i8k_get_fan_type(0);
 	if (err >= 0)
 		i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;
 
-	/* Second fan attributes, if fan type is OK */
-	err = i8k_get_fan_type(1);
+	/* Second fan attributes, if fan status or type is OK */
+	err = i8k_get_fan_status(1);
+	if (err < 0)
+		err = i8k_get_fan_type(1);
 	if (err >= 0)
 		i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
 
@@ -929,12 +954,14 @@
 
 MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
 
-static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = {
+/*
+ * On some machines once I8K_SMM_GET_FAN_TYPE is issued then CPU fan speed
+ * randomly going up and down due to bug in Dell SMM or BIOS. Here is blacklist
+ * of affected Dell machines for which we disallow I8K_SMM_GET_FAN_TYPE call.
+ * See bug: https://bugzilla.kernel.org/show_bug.cgi?id=100121
+ */
+static struct dmi_system_id i8k_blacklist_fan_type_dmi_table[] __initdata = {
 	{
-		/*
-		 * CPU fan speed going up and down on Dell Studio XPS 8000
-		 * for unknown reasons.
-		 */
 		.ident = "Dell Studio XPS 8000",
 		.matches = {
 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -942,16 +969,19 @@
 		},
 	},
 	{
-		/*
-		 * CPU fan speed going up and down on Dell Studio XPS 8100
-		 * for unknown reasons.
-		 */
 		.ident = "Dell Studio XPS 8100",
 		.matches = {
 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8100"),
 		},
 	},
+	{
+		.ident = "Dell Inspiron 580",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Inspiron 580 "),
+		},
+	},
 	{ }
 };
 
@@ -966,8 +996,7 @@
 	/*
 	 * Get DMI information
 	 */
-	if (!dmi_check_system(i8k_dmi_table) ||
-	    dmi_check_system(i8k_blacklist_dmi_table)) {
+	if (!dmi_check_system(i8k_dmi_table)) {
 		if (!ignore_dmi && !force)
 			return -ENODEV;
 
@@ -978,8 +1007,13 @@
 			i8k_get_dmi_data(DMI_BIOS_VERSION));
 	}
 
+	if (dmi_check_system(i8k_blacklist_fan_type_dmi_table))
+		disallow_fan_type_call = true;
+
 	strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),
 		sizeof(bios_version));
+	strlcpy(bios_machineid, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+		sizeof(bios_machineid));
 
 	/*
 	 * Get SMM Dell signature
diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c
index edf550f..0043a4c 100644
--- a/drivers/hwmon/ds620.c
+++ b/drivers/hwmon/ds620.c
@@ -166,7 +166,7 @@
 	if (res)
 		return res;
 
-	val = (val * 10 / 625) * 8;
+	val = (clamp_val(val, -128000, 128000) * 10 / 625) * 8;
 
 	mutex_lock(&data->update_lock);
 	data->temp[attr->index] = val;
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index b96a2a9..628be9c 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -193,14 +193,17 @@
  * Convert fan RPM value from sysfs into count value for fan controller
  * register (FAN_SET_CNT).
  */
-static inline unsigned char cnt_from_rpm(u32 rpm, u32 clk_freq, u16 p,
+static inline unsigned char cnt_from_rpm(unsigned long rpm, u32 clk_freq, u16 p,
 					 u8 clk_div, u8 gear_mult)
 {
-	if (!rpm)         /* to stop the fan, set cnt to 255 */
+	unsigned long f1 = clk_freq * 30 * gear_mult;
+	unsigned long f2 = p * clk_div;
+
+	if (!rpm)	/* to stop the fan, set cnt to 255 */
 		return 0xff;
 
-	return clamp_val(((clk_freq * 30 * gear_mult) / (rpm * p * clk_div)),
-			 0, 255);
+	rpm = clamp_val(rpm, f1 / (255 * f2), ULONG_MAX / f2);
+	return DIV_ROUND_CLOSEST(f1, rpm * f2);
 }
 
 /* helper to grab and cache data, at most one time per second */
diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c
index 17ae2eb..d5c06f2 100644
--- a/drivers/hwmon/iio_hwmon.c
+++ b/drivers/hwmon/iio_hwmon.c
@@ -109,24 +109,24 @@
 
 		switch (type) {
 		case IIO_VOLTAGE:
-			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
-							  "in%d_input",
-							  in_i++);
+			a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
+							       "in%d_input",
+							       in_i++);
 			break;
 		case IIO_TEMP:
-			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
-							  "temp%d_input",
-							  temp_i++);
+			a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
+							       "temp%d_input",
+							       temp_i++);
 			break;
 		case IIO_CURRENT:
-			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
-							  "curr%d_input",
-							  curr_i++);
+			a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
+							       "curr%d_input",
+							       curr_i++);
 			break;
 		case IIO_HUMIDITYRELATIVE:
-			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
-							  "humidity%d_input",
-							  humidity_i++);
+			a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
+							       "humidity%d_input",
+							       humidity_i++);
 			break;
 		default:
 			ret = -EINVAL;
diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c
index 3ce33d2..12b94b0 100644
--- a/drivers/hwmon/nct7802.c
+++ b/drivers/hwmon/nct7802.c
@@ -259,13 +259,15 @@
 		ret = 0;
 	else if (ret)
 		ret = DIV_ROUND_CLOSEST(1350000U, ret);
+	else
+		ret = 1350000U;
 abort:
 	mutex_unlock(&data->access_lock);
 	return ret;
 }
 
 static int nct7802_write_fan_min(struct nct7802_data *data, u8 reg_fan_low,
-				 u8 reg_fan_high, unsigned int limit)
+				 u8 reg_fan_high, unsigned long limit)
 {
 	int err;
 
@@ -326,8 +328,8 @@
 	int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr];
 	int err;
 
+	voltage = clamp_val(voltage, 0, 0x3ff * nct7802_vmul[nr]);
 	voltage = DIV_ROUND_CLOSEST(voltage, nct7802_vmul[nr]);
-	voltage = clamp_val(voltage, 0, 0x3ff);
 
 	mutex_lock(&data->access_lock);
 	err = regmap_write(data->regmap,
@@ -402,7 +404,7 @@
 	if (err < 0)
 		return err;
 
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);
 
 	err = regmap_write(data->regmap, nr, val & 0xff);
 	return err ? : count;
diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c
index 7e20567..6827169 100644
--- a/drivers/hwmon/scpi-hwmon.c
+++ b/drivers/hwmon/scpi-hwmon.c
@@ -272,6 +272,7 @@
 	{.compatible = "arm,scpi-sensors"},
 	{},
 };
+MODULE_DEVICE_TABLE(of, scpi_of_match);
 
 static struct platform_driver scpi_hwmon_platdrv = {
 	.driver = {
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index 165d300..c6ec5c6 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -419,6 +419,38 @@
 	},
 };
 
+#ifdef CONFIG_MODULES
+static void __intel_th_request_hub_module(struct work_struct *work)
+{
+	struct intel_th *th = container_of(work, struct intel_th,
+					   request_module_work);
+
+	request_module("intel_th_%s", th->hub->name);
+}
+
+static int intel_th_request_hub_module(struct intel_th *th)
+{
+	INIT_WORK(&th->request_module_work, __intel_th_request_hub_module);
+	schedule_work(&th->request_module_work);
+
+	return 0;
+}
+
+static void intel_th_request_hub_module_flush(struct intel_th *th)
+{
+	flush_work(&th->request_module_work);
+}
+#else
+static inline int intel_th_request_hub_module(struct intel_th *th)
+{
+	return -EINVAL;
+}
+
+static inline void intel_th_request_hub_module_flush(struct intel_th *th)
+{
+}
+#endif /* CONFIG_MODULES */
+
 static int intel_th_populate(struct intel_th *th, struct resource *devres,
 			     unsigned int ndevres, int irq)
 {
@@ -488,7 +520,7 @@
 		/* need switch driver to be loaded to enumerate the rest */
 		if (subdev->type == INTEL_TH_SWITCH && !req) {
 			th->hub = thdev;
-			err = request_module("intel_th_%s", subdev->name);
+			err = intel_th_request_hub_module(th);
 			if (!err)
 				req++;
 		}
@@ -603,6 +635,7 @@
 {
 	int i;
 
+	intel_th_request_hub_module_flush(th);
 	for (i = 0; i < TH_SUBDEVICE_MAX; i++)
 		if (th->thdev[i] != th->hub)
 			intel_th_device_remove(th->thdev[i]);
diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h
index 57fd72b..d03a6cd 100644
--- a/drivers/hwtracing/intel_th/intel_th.h
+++ b/drivers/hwtracing/intel_th/intel_th.h
@@ -197,6 +197,9 @@
 
 	int			id;
 	int			major;
+#ifdef CONFIG_MODULES
+	struct work_struct	request_module_work;
+#endif /* CONFIG_MODULES */
 #ifdef CONFIG_INTEL_TH_DEBUG
 	struct dentry		*dbg;
 #endif
diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
index 641e879..d57a2f7 100644
--- a/drivers/hwtracing/intel_th/pci.c
+++ b/drivers/hwtracing/intel_th/pci.c
@@ -67,6 +67,11 @@
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa126),
 		.driver_data = (kernel_ulong_t)0,
 	},
+	{
+		/* Kaby Lake PCH-H */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6),
+		.driver_data = (kernel_ulong_t)0,
+	},
 	{ 0 },
 };
 
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 78fbee4..65dbde7 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -59,7 +59,6 @@
 
 config I2C_MUX
 	tristate "I2C bus multiplexing support"
-	depends on HAS_IOMEM
 	help
 	  Say Y here if you want the I2C core to support the ability to
 	  handle multiplexed I2C bus topologies, by presenting each
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
index a0d95ff..2d5ff863 100644
--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -215,7 +215,7 @@
 	msg->outsize = request_len;
 	msg->insize = response_len;
 
-	result = cros_ec_cmd_xfer(bus->ec, msg);
+	result = cros_ec_cmd_xfer_status(bus->ec, msg);
 	if (result < 0) {
 		dev_err(dev, "Error transferring EC i2c message %d\n", result);
 		goto exit;
diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c
index 8eff627..e253598 100644
--- a/drivers/i2c/busses/i2c-efm32.c
+++ b/drivers/i2c/busses/i2c-efm32.c
@@ -433,7 +433,7 @@
 	ret = request_irq(ddata->irq, efm32_i2c_irq, 0, DRIVER_NAME, ddata);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to request irq (%d)\n", ret);
-		return ret;
+		goto err_disable_clk;
 	}
 
 	ret = i2c_add_adapter(&ddata->adapter);
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index 76e699f..eef3aa6 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -773,13 +773,6 @@
 	/* Set the number of I2C channel instance */
 	adap_info->ch_num = id->driver_data;
 
-	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
-		  KBUILD_MODNAME, adap_info);
-	if (ret) {
-		pch_pci_err(pdev, "request_irq FAILED\n");
-		goto err_request_irq;
-	}
-
 	for (i = 0; i < adap_info->ch_num; i++) {
 		pch_adap = &adap_info->pch_data[i].pch_adapter;
 		adap_info->pch_i2c_suspended = false;
@@ -796,6 +789,17 @@
 		adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i;
 
 		pch_adap->dev.parent = &pdev->dev;
+	}
+
+	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
+		  KBUILD_MODNAME, adap_info);
+	if (ret) {
+		pch_pci_err(pdev, "request_irq FAILED\n");
+		goto err_request_irq;
+	}
+
+	for (i = 0; i < adap_info->ch_num; i++) {
+		pch_adap = &adap_info->pch_data[i].pch_adapter;
 
 		pch_i2c_init(&adap_info->pch_data[i]);
 
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 27fa0cb..85f39cc 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -244,6 +244,13 @@
 	struct platform_device *mux_pdev;
 #endif
 	struct platform_device *tco_pdev;
+
+	/*
+	 * If set to true the host controller registers are reserved for
+	 * ACPI AML use. Protected by acpi_lock.
+	 */
+	bool acpi_reserved;
+	struct mutex acpi_lock;
 };
 
 #define FEATURE_SMBUS_PEC	(1 << 0)
@@ -714,9 +721,15 @@
 {
 	int hwpec;
 	int block = 0;
-	int ret, xact = 0;
+	int ret = 0, xact = 0;
 	struct i801_priv *priv = i2c_get_adapdata(adap);
 
+	mutex_lock(&priv->acpi_lock);
+	if (priv->acpi_reserved) {
+		mutex_unlock(&priv->acpi_lock);
+		return -EBUSY;
+	}
+
 	hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
 		&& size != I2C_SMBUS_QUICK
 		&& size != I2C_SMBUS_I2C_BLOCK_DATA;
@@ -773,7 +786,8 @@
 	default:
 		dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
 			size);
-		return -EOPNOTSUPP;
+		ret = -EOPNOTSUPP;
+		goto out;
 	}
 
 	if (hwpec)	/* enable/disable hardware PEC */
@@ -796,11 +810,11 @@
 		       ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
 
 	if (block)
-		return ret;
+		goto out;
 	if (ret)
-		return ret;
+		goto out;
 	if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
-		return 0;
+		goto out;
 
 	switch (xact & 0x7f) {
 	case I801_BYTE:	/* Result put in SMBHSTDAT0 */
@@ -812,7 +826,10 @@
 			     (inb_p(SMBHSTDAT1(priv)) << 8);
 		break;
 	}
-	return 0;
+
+out:
+	mutex_unlock(&priv->acpi_lock);
+	return ret;
 }
 
 
@@ -1249,6 +1266,72 @@
 	priv->tco_pdev = pdev;
 }
 
+#ifdef CONFIG_ACPI
+static acpi_status
+i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
+		     u64 *value, void *handler_context, void *region_context)
+{
+	struct i801_priv *priv = handler_context;
+	struct pci_dev *pdev = priv->pci_dev;
+	acpi_status status;
+
+	/*
+	 * Once BIOS AML code touches the OpRegion we warn and inhibit any
+	 * further access from the driver itself. This device is now owned
+	 * by the system firmware.
+	 */
+	mutex_lock(&priv->acpi_lock);
+
+	if (!priv->acpi_reserved) {
+		priv->acpi_reserved = true;
+
+		dev_warn(&pdev->dev, "BIOS is accessing SMBus registers\n");
+		dev_warn(&pdev->dev, "Driver SMBus register access inhibited\n");
+	}
+
+	if ((function & ACPI_IO_MASK) == ACPI_READ)
+		status = acpi_os_read_port(address, (u32 *)value, bits);
+	else
+		status = acpi_os_write_port(address, (u32)*value, bits);
+
+	mutex_unlock(&priv->acpi_lock);
+
+	return status;
+}
+
+static int i801_acpi_probe(struct i801_priv *priv)
+{
+	struct acpi_device *adev;
+	acpi_status status;
+
+	adev = ACPI_COMPANION(&priv->pci_dev->dev);
+	if (adev) {
+		status = acpi_install_address_space_handler(adev->handle,
+				ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler,
+				NULL, priv);
+		if (ACPI_SUCCESS(status))
+			return 0;
+	}
+
+	return acpi_check_resource_conflict(&priv->pci_dev->resource[SMBBAR]);
+}
+
+static void i801_acpi_remove(struct i801_priv *priv)
+{
+	struct acpi_device *adev;
+
+	adev = ACPI_COMPANION(&priv->pci_dev->dev);
+	if (!adev)
+		return;
+
+	acpi_remove_address_space_handler(adev->handle,
+		ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler);
+}
+#else
+static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; }
+static inline void i801_acpi_remove(struct i801_priv *priv) { }
+#endif
+
 static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	unsigned char temp;
@@ -1266,6 +1349,7 @@
 	priv->adapter.dev.parent = &dev->dev;
 	ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&dev->dev));
 	priv->adapter.retries = 3;
+	mutex_init(&priv->acpi_lock);
 
 	priv->pci_dev = dev;
 	switch (dev->device) {
@@ -1328,10 +1412,8 @@
 		return -ENODEV;
 	}
 
-	err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
-	if (err) {
+	if (i801_acpi_probe(priv))
 		return -ENODEV;
-	}
 
 	err = pcim_iomap_regions(dev, 1 << SMBBAR,
 				 dev_driver_string(&dev->dev));
@@ -1340,6 +1422,7 @@
 			"Failed to request SMBus region 0x%lx-0x%Lx\n",
 			priv->smba,
 			(unsigned long long)pci_resource_end(dev, SMBBAR));
+		i801_acpi_remove(priv);
 		return err;
 	}
 
@@ -1404,6 +1487,7 @@
 	err = i2c_add_adapter(&priv->adapter);
 	if (err) {
 		dev_err(&dev->dev, "Failed to add SMBus adapter\n");
+		i801_acpi_remove(priv);
 		return err;
 	}
 
@@ -1422,6 +1506,7 @@
 
 	i801_del_mux(priv);
 	i2c_del_adapter(&priv->adapter);
+	i801_acpi_remove(priv);
 	pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
 
 	platform_device_unregister(priv->tco_pdev);
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 630bce6..b61db9d 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -54,7 +54,7 @@
 #define SMBSLVDAT	(0xC + piix4_smba)
 
 /* count for request_region */
-#define SMBIOSIZE	8
+#define SMBIOSIZE	9
 
 /* PCI Address Constants */
 #define SMBBA		0x090
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index fdcbdab..33b1156 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -727,7 +727,8 @@
 #ifdef CONFIG_PM_SLEEP
 static int qup_i2c_suspend(struct device *device)
 {
-	qup_i2c_pm_suspend_runtime(device);
+	if (!pm_runtime_suspended(device))
+		return qup_i2c_pm_suspend_runtime(device);
 	return 0;
 }
 
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c
index 0ed77ee..a2e3dd7 100644
--- a/drivers/i2c/busses/i2c-tiny-usb.c
+++ b/drivers/i2c/busses/i2c-tiny-usb.c
@@ -178,22 +178,39 @@
 		    int value, int index, void *data, int len)
 {
 	struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+	void *dmadata = kmalloc(len, GFP_KERNEL);
+	int ret;
+
+	if (!dmadata)
+		return -ENOMEM;
 
 	/* do control transfer */
-	return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
+	ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
 			       cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
-			       USB_DIR_IN, value, index, data, len, 2000);
+			       USB_DIR_IN, value, index, dmadata, len, 2000);
+
+	memcpy(data, dmadata, len);
+	kfree(dmadata);
+	return ret;
 }
 
 static int usb_write(struct i2c_adapter *adapter, int cmd,
 		     int value, int index, void *data, int len)
 {
 	struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+	void *dmadata = kmemdup(data, len, GFP_KERNEL);
+	int ret;
+
+	if (!dmadata)
+		return -ENOMEM;
 
 	/* do control transfer */
-	return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
+	ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
 			       cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-			       value, index, data, len, 2000);
+			       value, index, dmadata, len, 2000);
+
+	kfree(dmadata);
+	return ret;
 }
 
 static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c
index 4233f56..3c38029 100644
--- a/drivers/i2c/busses/i2c-xgene-slimpro.c
+++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
@@ -105,7 +105,7 @@
 	struct mbox_chan *mbox_chan;
 	struct mbox_client mbox_client;
 	struct completion rd_complete;
-	u8 dma_buffer[I2C_SMBUS_BLOCK_MAX];
+	u8 dma_buffer[I2C_SMBUS_BLOCK_MAX + 1]; /* dma_buffer[0] is used for length */
 	u32 *resp_msg;
 };
 
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index ba8eb08..e458741 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1400,7 +1400,7 @@
 
 	if (i2c_check_addr_validity(addr, info.flags)) {
 		dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
-			info.addr, node->full_name);
+			addr, node->full_name);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -1876,6 +1876,7 @@
 	/* add the driver to the list of i2c drivers in the driver core */
 	driver->driver.owner = owner;
 	driver->driver.bus = &i2c_bus_type;
+	INIT_LIST_HEAD(&driver->clients);
 
 	/* When registration returns, the driver core
 	 * will have called probe() for all matching-but-unbound devices.
@@ -1886,7 +1887,6 @@
 
 	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
 
-	INIT_LIST_HEAD(&driver->clients);
 	/* Walk the adapters that are already present */
 	i2c_for_each_dev(driver, __process_new_driver);
 
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 2413ec9..94c8370 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -329,7 +329,7 @@
 		unsigned long arg)
 {
 	struct i2c_smbus_ioctl_data data_arg;
-	union i2c_smbus_data temp;
+	union i2c_smbus_data temp = {};
 	int datasize, res;
 
 	if (copy_from_user(&data_arg,
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index f06b0e2..af2a63c 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -63,6 +63,7 @@
 
 config I2C_MUX_REG
 	tristate "Register-based I2C multiplexer"
+	depends on HAS_IOMEM
 	help
 	  If you say yes to this option, support will be included for a
 	  register based I2C multiplexer. This driver provides access to
diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index 5fbd5bd..49fc2c7 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -150,7 +150,7 @@
 		mux->data.idle_in_use = true;
 
 	/* map address from "reg" if exists */
-	if (of_address_to_resource(np, 0, &res)) {
+	if (of_address_to_resource(np, 0, &res) == 0) {
 		mux->data.reg_size = resource_size(&res);
 		mux->data.reg = devm_ioremap_resource(&pdev->dev, &res);
 		if (IS_ERR(mux->data.reg))
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 146eed70b..ba947df 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -716,6 +716,26 @@
 	{
 		.enter = NULL }
 };
+static struct cpuidle_state knl_cstates[] = {
+	{
+		.name = "C1-KNL",
+		.desc = "MWAIT 0x00",
+		.flags = MWAIT2flg(0x00),
+		.exit_latency = 1,
+		.target_residency = 2,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze },
+	{
+		.name = "C6-KNL",
+		.desc = "MWAIT 0x10",
+		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 120,
+		.target_residency = 500,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze },
+	{
+		.enter = NULL }
+};
 
 /**
  * intel_idle
@@ -890,6 +910,10 @@
 	.disable_promotion_to_c1e = true,
 };
 
+static const struct idle_cpu idle_cpu_knl = {
+	.state_table = knl_cstates,
+};
+
 #define ICPU(model, cpu) \
 	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
 
@@ -921,6 +945,7 @@
 	ICPU(0x56, idle_cpu_bdw),
 	ICPU(0x4e, idle_cpu_skl),
 	ICPU(0x5e, idle_cpu_skl),
+	ICPU(0x57, idle_cpu_knl),
 	{}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 291c61a..fa24d51 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -68,6 +68,9 @@
 #define BMC150_ACCEL_REG_PMU_BW		0x10
 #define BMC150_ACCEL_DEF_BW			125
 
+#define BMC150_ACCEL_REG_RESET			0x14
+#define BMC150_ACCEL_RESET_VAL			0xB6
+
 #define BMC150_ACCEL_REG_INT_MAP_0		0x19
 #define BMC150_ACCEL_INT_MAP_0_BIT_SLOPE	BIT(2)
 
@@ -1487,6 +1490,14 @@
 	int ret, i;
 	unsigned int val;
 
+	/*
+	 * Reset chip to get it in a known good state. A delay of 1.8ms after
+	 * reset is required according to the data sheets of supported chips.
+	 */
+	regmap_write(data->regmap, BMC150_ACCEL_REG_RESET,
+		     BMC150_ACCEL_RESET_VAL);
+	usleep_range(1800, 2500);
+
 	ret = regmap_read(data->regmap, BMC150_ACCEL_REG_CHIP_ID, &val);
 	if (ret < 0) {
 		dev_err(data->dev,
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 923f565..9d72d4b 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -81,7 +81,7 @@
 
 	mutex_lock(&st->buf_lock);
 	ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
-	if (ret)
+	if (ret < 0)
 		goto error_ret;
 	st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C);
 	st->tx[1] = (ret & ~KXSD9_FS_MASK) | i;
@@ -160,11 +160,13 @@
 		if (ret < 0)
 			goto error_ret;
 		*val = ret;
+		ret = IIO_VAL_INT;
 		break;
 	case IIO_CHAN_INFO_SCALE:
 		ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
-		if (ret)
+		if (ret < 0)
 			goto error_ret;
+		*val = 0;
 		*val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK];
 		ret = IIO_VAL_INT_PLUS_MICRO;
 		break;
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 1e7aded..bda6bbe 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -306,6 +306,7 @@
 config ROCKCHIP_SARADC
 	tristate "Rockchip SARADC driver"
 	depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST)
+	depends on RESET_CONTROLLER
 	help
 	  Say yes here to build support for the SARADC found in SoCs from
 	  Rockchip.
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 21e19b6..2123f0a 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -396,8 +396,8 @@
 
 	st = iio_priv(indio_dev);
 
-	st->reg = devm_regulator_get(&spi->dev, "vref");
-	if (!IS_ERR_OR_NULL(st->reg)) {
+	st->reg = devm_regulator_get_optional(&spi->dev, "vref");
+	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
 			return ret;
@@ -408,6 +408,9 @@
 
 		st->vref_mv = ret / 1000;
 	} else {
+		/* Any other error indicates that the regulator does exist */
+		if (PTR_ERR(st->reg) != -ENODEV)
+			return PTR_ERR(st->reg);
 		/* Use internal reference */
 		st->vref_mv = 2500;
 	}
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index 01d7158..ba82de2 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -533,6 +533,7 @@
 static const struct iio_info ad7991_info = {
 	.read_raw = &ad799x_read_raw,
 	.driver_module = THIS_MODULE,
+	.update_scan_mode = ad799x_update_scan_mode,
 };
 
 static const struct iio_info ad7993_4_7_8_noirq_info = {
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 7b40925..93986f0 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -381,8 +381,8 @@
 		st->ts_bufferedmeasure = false;
 		input_report_key(st->ts_input, BTN_TOUCH, 0);
 		input_sync(st->ts_input);
-	} else if (status & AT91_ADC_EOC(3)) {
-		/* Conversion finished */
+	} else if (status & AT91_ADC_EOC(3) && st->ts_input) {
+		/* Conversion finished and we've a touchscreen */
 		if (st->ts_bufferedmeasure) {
 			/*
 			 * Last measurement is always discarded, since it can
diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
index 9c311c1..dffff64 100644
--- a/drivers/iio/adc/rockchip_saradc.c
+++ b/drivers/iio/adc/rockchip_saradc.c
@@ -21,6 +21,8 @@
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/reset.h>
 #include <linux/regulator/consumer.h>
 #include <linux/iio/iio.h>
 
@@ -53,6 +55,7 @@
 	struct clk		*clk;
 	struct completion	completion;
 	struct regulator	*vref;
+	struct reset_control	*reset;
 	const struct rockchip_saradc_data *data;
 	u16			last_val;
 };
@@ -171,6 +174,16 @@
 };
 MODULE_DEVICE_TABLE(of, rockchip_saradc_match);
 
+/**
+ * Reset SARADC Controller.
+ */
+static void rockchip_saradc_reset_controller(struct reset_control *reset)
+{
+	reset_control_assert(reset);
+	usleep_range(10, 20);
+	reset_control_deassert(reset);
+}
+
 static int rockchip_saradc_probe(struct platform_device *pdev)
 {
 	struct rockchip_saradc *info = NULL;
@@ -199,6 +212,20 @@
 	if (IS_ERR(info->regs))
 		return PTR_ERR(info->regs);
 
+	/*
+	 * The reset should be an optional property, as it should work
+	 * with old devicetrees as well
+	 */
+	info->reset = devm_reset_control_get(&pdev->dev, "saradc-apb");
+	if (IS_ERR(info->reset)) {
+		ret = PTR_ERR(info->reset);
+		if (ret != -ENOENT)
+			return ret;
+
+		dev_dbg(&pdev->dev, "no reset control found\n");
+		info->reset = NULL;
+	}
+
 	init_completion(&info->completion);
 
 	irq = platform_get_irq(pdev, 0);
@@ -233,6 +260,9 @@
 		return PTR_ERR(info->vref);
 	}
 
+	if (info->reset)
+		rockchip_saradc_reset_controller(info->reset);
+
 	/*
 	 * Use a default value for the converter clock.
 	 * This may become user-configurable in the future.
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index c1e0553..9b68546 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -32,6 +32,7 @@
 
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
+	struct mutex fifo1_lock; /* to protect fifo access */
 	int channels;
 	u8 channel_line[8];
 	u8 channel_step[8];
@@ -150,7 +151,9 @@
 {
 	struct iio_dev *indio_dev = private;
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
-	unsigned int status, config;
+	unsigned int status, config, adc_fsm;
+	unsigned short count = 0;
+
 	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
 
 	/*
@@ -164,6 +167,15 @@
 		tiadc_writel(adc_dev, REG_CTRL, config);
 		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
 				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+
+		/* wait for idle state.
+		 * ADC needs to finish the current conversion
+		 * before disabling the module
+		 */
+		do {
+			adc_fsm = tiadc_readl(adc_dev, REG_ADCFSM);
+		} while (adc_fsm != 0x10 && count++ < 100);
+
 		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
 		return IRQ_HANDLED;
 	} else if (status & IRQENB_FIFO1THRES) {
@@ -360,6 +372,7 @@
 		int *val, int *val2, long mask)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int ret = IIO_VAL_INT;
 	int i, map_val;
 	unsigned int fifo1count, read, stepid;
 	bool found = false;
@@ -373,13 +386,14 @@
 	if (!step_en)
 		return -EINVAL;
 
+	mutex_lock(&adc_dev->fifo1_lock);
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
 	while (fifo1count--)
 		tiadc_readl(adc_dev, REG_FIFO1);
 
 	am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en);
 
-	timeout = jiffies + usecs_to_jiffies
+	timeout = jiffies + msecs_to_jiffies
 				(IDLE_TIMEOUT * adc_dev->channels);
 	/* Wait for Fifo threshold interrupt */
 	while (1) {
@@ -389,7 +403,8 @@
 
 		if (time_after(jiffies, timeout)) {
 			am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
-			return -EAGAIN;
+			ret = -EAGAIN;
+			goto err_unlock;
 		}
 	}
 	map_val = adc_dev->channel_step[chan->scan_index];
@@ -415,8 +430,11 @@
 	am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
 
 	if (found == false)
-		return -EBUSY;
-	return IIO_VAL_INT;
+		ret =  -EBUSY;
+
+err_unlock:
+	mutex_unlock(&adc_dev->fifo1_lock);
+	return ret;
 }
 
 static const struct iio_info tiadc_info = {
@@ -485,6 +503,7 @@
 
 	tiadc_step_config(indio_dev);
 	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
+	mutex_init(&adc_dev->fifo1_lock);
 
 	err = tiadc_channel_init(indio_dev, adc_dev->channels);
 	if (err < 0)
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
index e81f434..b5beea53 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -30,34 +30,34 @@
 	u32 usage_id;
 	int unit; /* 0 for default others from HID sensor spec */
 	int scale_val0; /* scale, whole number */
-	int scale_val1; /* scale, fraction in micros */
+	int scale_val1; /* scale, fraction in nanos */
 } unit_conversion[] = {
-	{HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650},
+	{HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650000},
 	{HID_USAGE_SENSOR_ACCEL_3D,
 		HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0},
 	{HID_USAGE_SENSOR_ACCEL_3D,
-		HID_USAGE_SENSOR_UNITS_G, 9, 806650},
+		HID_USAGE_SENSOR_UNITS_G, 9, 806650000},
 
-	{HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453},
+	{HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453293},
 	{HID_USAGE_SENSOR_GYRO_3D,
 		HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0},
 	{HID_USAGE_SENSOR_GYRO_3D,
-		HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453},
+		HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453293},
 
-	{HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000},
+	{HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000000},
 	{HID_USAGE_SENSOR_COMPASS_3D, HID_USAGE_SENSOR_UNITS_GAUSS, 1, 0},
 
-	{HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453},
+	{HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453293},
 	{HID_USAGE_SENSOR_INCLINOMETER_3D,
-		HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453},
+		HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453293},
 	{HID_USAGE_SENSOR_INCLINOMETER_3D,
 		HID_USAGE_SENSOR_UNITS_RADIANS, 1, 0},
 
 	{HID_USAGE_SENSOR_ALS, 0, 1, 0},
 	{HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 0},
 
-	{HID_USAGE_SENSOR_PRESSURE, 0, 100000, 0},
-	{HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 1, 0},
+	{HID_USAGE_SENSOR_PRESSURE, 0, 100, 0},
+	{HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 0, 1000000},
 };
 
 static int pow_10(unsigned power)
@@ -266,15 +266,15 @@
 /*
  * This fuction applies the unit exponent to the scale.
  * For example:
- * 9.806650 ->exp:2-> val0[980]val1[665000]
- * 9.000806 ->exp:2-> val0[900]val1[80600]
- * 0.174535 ->exp:2-> val0[17]val1[453500]
- * 1.001745 ->exp:0-> val0[1]val1[1745]
- * 1.001745 ->exp:2-> val0[100]val1[174500]
- * 1.001745 ->exp:4-> val0[10017]val1[450000]
- * 9.806650 ->exp:-2-> val0[0]val1[98066]
+ * 9.806650000 ->exp:2-> val0[980]val1[665000000]
+ * 9.000806000 ->exp:2-> val0[900]val1[80600000]
+ * 0.174535293 ->exp:2-> val0[17]val1[453529300]
+ * 1.001745329 ->exp:0-> val0[1]val1[1745329]
+ * 1.001745329 ->exp:2-> val0[100]val1[174532900]
+ * 1.001745329 ->exp:4-> val0[10017]val1[453290000]
+ * 9.806650000 ->exp:-2-> val0[0]val1[98066500]
  */
-static void adjust_exponent_micro(int *val0, int *val1, int scale0,
+static void adjust_exponent_nano(int *val0, int *val1, int scale0,
 				  int scale1, int exp)
 {
 	int i;
@@ -285,32 +285,32 @@
 	if (exp > 0) {
 		*val0 = scale0 * pow_10(exp);
 		res = 0;
-		if (exp > 6) {
+		if (exp > 9) {
 			*val1 = 0;
 			return;
 		}
 		for (i = 0; i < exp; ++i) {
-			x = scale1 / pow_10(5 - i);
+			x = scale1 / pow_10(8 - i);
 			res += (pow_10(exp - 1 - i) * x);
-			scale1 = scale1 % pow_10(5 - i);
+			scale1 = scale1 % pow_10(8 - i);
 		}
 		*val0 += res;
 			*val1 = scale1 * pow_10(exp);
 	} else if (exp < 0) {
 		exp = abs(exp);
-		if (exp > 6) {
+		if (exp > 9) {
 			*val0 = *val1 = 0;
 			return;
 		}
 		*val0 = scale0 / pow_10(exp);
 		rem = scale0 % pow_10(exp);
 		res = 0;
-		for (i = 0; i < (6 - exp); ++i) {
-			x = scale1 / pow_10(5 - i);
-			res += (pow_10(5 - exp - i) * x);
-			scale1 = scale1 % pow_10(5 - i);
+		for (i = 0; i < (9 - exp); ++i) {
+			x = scale1 / pow_10(8 - i);
+			res += (pow_10(8 - exp - i) * x);
+			scale1 = scale1 % pow_10(8 - i);
 		}
-		*val1 = rem * pow_10(6 - exp) + res;
+		*val1 = rem * pow_10(9 - exp) + res;
 	} else {
 		*val0 = scale0;
 		*val1 = scale1;
@@ -332,14 +332,14 @@
 			unit_conversion[i].unit == attr_info->units) {
 			exp  = hid_sensor_convert_exponent(
 						attr_info->unit_expo);
-			adjust_exponent_micro(val0, val1,
+			adjust_exponent_nano(val0, val1,
 					unit_conversion[i].scale_val0,
 					unit_conversion[i].scale_val1, exp);
 			break;
 		}
 	}
 
-	return IIO_VAL_INT_PLUS_MICRO;
+	return IIO_VAL_INT_PLUS_NANO;
 }
 EXPORT_SYMBOL(hid_sensor_format_scale);
 
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 5955110..0a86ef4 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -51,8 +51,6 @@
 			st->report_state.report_id,
 			st->report_state.index,
 			HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM);
-
-		poll_value = hid_sensor_read_poll_value(st);
 	} else {
 		int val;
 
@@ -89,7 +87,9 @@
 	sensor_hub_get_feature(st->hsdev, st->power_state.report_id,
 			       st->power_state.index,
 			       sizeof(state_val), &state_val);
-	if (state && poll_value)
+	if (state)
+		poll_value = hid_sensor_read_poll_value(st);
+	if (poll_value > 0)
 		msleep_interruptible(poll_value * 2);
 
 	return 0;
diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c
index e690dd1..4b0f942 100644
--- a/drivers/iio/dac/ad7303.c
+++ b/drivers/iio/dac/ad7303.c
@@ -184,9 +184,9 @@
 	.address = (chan),					\
 	.scan_type = {						\
 		.sign = 'u',					\
-		.realbits = '8',				\
-		.storagebits = '8',				\
-		.shift = '0',					\
+		.realbits = 8,					\
+		.storagebits = 8,				\
+		.shift = 0,					\
 	},							\
 	.ext_info = ad7303_ext_info,				\
 }
diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c
index acb3b30..90841ab 100644
--- a/drivers/iio/gyro/bmg160_core.c
+++ b/drivers/iio/gyro/bmg160_core.c
@@ -28,6 +28,7 @@
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/regmap.h>
+#include <linux/delay.h>
 #include "bmg160.h"
 
 #define BMG160_IRQ_NAME		"bmg160_event"
@@ -53,6 +54,9 @@
 #define BMG160_NO_FILTER		0
 #define BMG160_DEF_BW			100
 
+#define BMG160_GYRO_REG_RESET		0x14
+#define BMG160_GYRO_RESET_VAL		0xb6
+
 #define BMG160_REG_INT_MAP_0		0x17
 #define BMG160_INT_MAP_0_BIT_ANY	BIT(1)
 
@@ -186,6 +190,14 @@
 	int ret;
 	unsigned int val;
 
+	/*
+	 * Reset chip to get it in a known good state. A delay of 30ms after
+	 * reset is required according to the datasheet.
+	 */
+	regmap_write(data->regmap, BMG160_GYRO_REG_RESET,
+		     BMG160_GYRO_RESET_VAL);
+	usleep_range(30000, 30700);
+
 	ret = regmap_read(data->regmap, BMG160_REG_CHIP_ID, &val);
 	if (ret < 0) {
 		dev_err(data->dev, "Error reading reg_chip_id\n");
diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c
index a7f61e8..dc5e7e7 100644
--- a/drivers/iio/humidity/hdc100x.c
+++ b/drivers/iio/humidity/hdc100x.c
@@ -55,7 +55,7 @@
 	},
 	{ /* IIO_HUMIDITYRELATIVE channel */
 		.shift = 8,
-		.mask = 2,
+		.mask = 3,
 	},
 };
 
@@ -164,14 +164,14 @@
 		dev_err(&client->dev, "cannot read high byte measurement");
 		return ret;
 	}
-	val = ret << 6;
+	val = ret << 8;
 
 	ret = i2c_smbus_read_byte(client);
 	if (ret < 0) {
 		dev_err(&client->dev, "cannot read low byte measurement");
 		return ret;
 	}
-	val |= ret >> 2;
+	val |= ret;
 
 	return val;
 }
@@ -211,18 +211,18 @@
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_SCALE:
 		if (chan->type == IIO_TEMP) {
-			*val = 165;
-			*val2 = 65536 >> 2;
+			*val = 165000;
+			*val2 = 65536;
 			return IIO_VAL_FRACTIONAL;
 		} else {
-			*val = 0;
-			*val2 = 10000;
-			return IIO_VAL_INT_PLUS_MICRO;
+			*val = 100;
+			*val2 = 65536;
+			return IIO_VAL_FRACTIONAL;
 		}
 		break;
 	case IIO_CHAN_INFO_OFFSET:
-		*val = -3971;
-		*val2 = 879096;
+		*val = -15887;
+		*val2 = 515151;
 		return IIO_VAL_INT_PLUS_MICRO;
 	default:
 		return -EINVAL;
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 0f6f63b..32bb036 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -107,9 +107,10 @@
 {
 	struct iio_dev *indio_dev = filp->private_data;
 	struct iio_buffer *rb = indio_dev->buffer;
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	size_t datum_size;
 	size_t to_wait;
-	int ret;
+	int ret = 0;
 
 	if (!indio_dev->info)
 		return -ENODEV;
@@ -131,19 +132,29 @@
 	else
 		to_wait = min_t(size_t, n / datum_size, rb->watermark);
 
+	add_wait_queue(&rb->pollq, &wait);
 	do {
-		ret = wait_event_interruptible(rb->pollq,
-		      iio_buffer_ready(indio_dev, rb, to_wait, n / datum_size));
-		if (ret)
-			return ret;
+		if (!indio_dev->info) {
+			ret = -ENODEV;
+			break;
+		}
 
-		if (!indio_dev->info)
-			return -ENODEV;
+		if (!iio_buffer_ready(indio_dev, rb, to_wait, n / datum_size)) {
+			if (signal_pending(current)) {
+				ret = -ERESTARTSYS;
+				break;
+			}
+
+			wait_woken(&wait, TASK_INTERRUPTIBLE,
+				   MAX_SCHEDULE_TIMEOUT);
+			continue;
+		}
 
 		ret = rb->access->read_first_n(rb, n, buf);
 		if (ret == 0 && (filp->f_flags & O_NONBLOCK))
 			ret = -EAGAIN;
-	 } while (ret == 0);
+	} while (ret == 0);
+	remove_wait_queue(&rb->pollq, &wait);
 
 	return ret;
 }
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 159ede6..131b434 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -433,23 +433,21 @@
 		scale_db = true;
 	case IIO_VAL_INT_PLUS_MICRO:
 		if (vals[1] < 0)
-			return sprintf(buf, "-%ld.%06u%s\n", abs(vals[0]),
-					-vals[1],
-				scale_db ? " dB" : "");
+			return sprintf(buf, "-%d.%06u%s\n", abs(vals[0]),
+				       -vals[1], scale_db ? " dB" : "");
 		else
 			return sprintf(buf, "%d.%06u%s\n", vals[0], vals[1],
 				scale_db ? " dB" : "");
 	case IIO_VAL_INT_PLUS_NANO:
 		if (vals[1] < 0)
-			return sprintf(buf, "-%ld.%09u\n", abs(vals[0]),
-					-vals[1]);
+			return sprintf(buf, "-%d.%09u\n", abs(vals[0]),
+				       -vals[1]);
 		else
 			return sprintf(buf, "%d.%09u\n", vals[0], vals[1]);
 	case IIO_VAL_FRACTIONAL:
 		tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
-		vals[1] = do_div(tmp, 1000000000LL);
-		vals[0] = tmp;
-		return sprintf(buf, "%d.%09u\n", vals[0], vals[1]);
+		vals[0] = (int)div_s64_rem(tmp, 1000000000, &vals[1]);
+		return sprintf(buf, "%d.%09u\n", vals[0], abs(vals[1]));
 	case IIO_VAL_FRACTIONAL_LOG2:
 		tmp = (s64)vals[0] * 1000000000LL >> vals[1];
 		vals[1] = do_div(tmp, 1000000000LL);
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index ae2806a..0c52dfe 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -210,22 +210,35 @@
 
 	/* Prevent the module from being removed whilst attached to a trigger */
 	__module_get(pf->indio_dev->info->driver_module);
+
+	/* Get irq number */
 	pf->irq = iio_trigger_get_irq(trig);
+	if (pf->irq < 0)
+		goto out_put_module;
+
+	/* Request irq */
 	ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
 				   pf->type, pf->name,
 				   pf);
-	if (ret < 0) {
-		module_put(pf->indio_dev->info->driver_module);
-		return ret;
-	}
+	if (ret < 0)
+		goto out_put_irq;
 
+	/* Enable trigger in driver */
 	if (trig->ops && trig->ops->set_trigger_state && notinuse) {
 		ret = trig->ops->set_trigger_state(trig, true);
 		if (ret < 0)
-			module_put(pf->indio_dev->info->driver_module);
+			goto out_free_irq;
 	}
 
 	return ret;
+
+out_free_irq:
+	free_irq(pf->irq, pf);
+out_put_irq:
+	iio_trigger_put_irq(trig, pf->irq);
+out_put_module:
+	module_put(pf->indio_dev->info->driver_module);
+	return ret;
 }
 
 static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
index f6a07dc..4a6d967 100644
--- a/drivers/iio/light/apds9960.c
+++ b/drivers/iio/light/apds9960.c
@@ -1005,6 +1005,7 @@
 
 	iio_device_attach_buffer(indio_dev, buffer);
 
+	indio_dev->dev.parent = &client->dev;
 	indio_dev->info = &apds9960_info;
 	indio_dev->name = APDS9960_DRV_NAME;
 	indio_dev->channels = apds9960_channels;
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 6bf89d8..b9d1e5c 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -74,9 +74,9 @@
 static const struct reg_field reg_field_it =
 				REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4);
 static const struct reg_field reg_field_als_intr =
-				REG_FIELD(LTR501_INTR, 0, 0);
-static const struct reg_field reg_field_ps_intr =
 				REG_FIELD(LTR501_INTR, 1, 1);
+static const struct reg_field reg_field_ps_intr =
+				REG_FIELD(LTR501_INTR, 0, 0);
 static const struct reg_field reg_field_als_rate =
 				REG_FIELD(LTR501_ALS_MEAS_RATE, 0, 2);
 static const struct reg_field reg_field_ps_rate =
diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index b98b9d9..a97e802c 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -335,6 +335,7 @@
 	.id_table = hid_dev_rot_ids,
 	.driver = {
 		.name	= KBUILD_MODNAME,
+		.pm     = &hid_sensor_pm_ops,
 	},
 	.probe		= hid_dev_rot_probe,
 	.remove		= hid_dev_rot_remove,
diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c
index a0d7dee..3f90985 100644
--- a/drivers/iio/pressure/mpl115.c
+++ b/drivers/iio/pressure/mpl115.c
@@ -136,6 +136,7 @@
 	{
 		.type = IIO_TEMP,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type =
 			BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
 	},
 };
diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c
index 01b2e0b..0f5b876 100644
--- a/drivers/iio/pressure/mpl3115.c
+++ b/drivers/iio/pressure/mpl3115.c
@@ -182,7 +182,7 @@
 	{
 		.type = IIO_PRESSURE,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-			BIT(IIO_CHAN_INFO_SCALE),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.scan_index = 0,
 		.scan_type = {
 			.sign = 'u',
@@ -195,7 +195,7 @@
 	{
 		.type = IIO_TEMP,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-			BIT(IIO_CHAN_INFO_SCALE),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.scan_index = 1,
 		.scan_type = {
 			.sign = 's',
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index b39a2fb..5056bd6 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -28,15 +28,21 @@
 #include <linux/iio/common/st_sensors.h>
 #include "st_pressure.h"
 
+#define MCELSIUS_PER_CELSIUS			1000
+
+/* Default pressure sensitivity */
 #define ST_PRESS_LSB_PER_MBAR			4096UL
 #define ST_PRESS_KPASCAL_NANO_SCALE		(100000000UL / \
 						 ST_PRESS_LSB_PER_MBAR)
+
+/* Default temperature sensitivity */
 #define ST_PRESS_LSB_PER_CELSIUS		480UL
-#define ST_PRESS_CELSIUS_NANO_SCALE		(1000000000UL / \
-						 ST_PRESS_LSB_PER_CELSIUS)
+#define ST_PRESS_MILLI_CELSIUS_OFFSET		42500UL
+
 #define ST_PRESS_NUMBER_DATA_CHANNELS		1
 
 /* FULLSCALE */
+#define ST_PRESS_FS_AVL_1100MB			1100
 #define ST_PRESS_FS_AVL_1260MB			1260
 
 #define ST_PRESS_1_OUT_XL_ADDR			0x28
@@ -54,18 +60,20 @@
 #define ST_PRESS_LPS331AP_PW_MASK		0x80
 #define ST_PRESS_LPS331AP_FS_ADDR		0x23
 #define ST_PRESS_LPS331AP_FS_MASK		0x30
-#define ST_PRESS_LPS331AP_FS_AVL_1260_VAL	0x00
-#define ST_PRESS_LPS331AP_FS_AVL_1260_GAIN	ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN	ST_PRESS_CELSIUS_NANO_SCALE
 #define ST_PRESS_LPS331AP_BDU_ADDR		0x20
 #define ST_PRESS_LPS331AP_BDU_MASK		0x04
 #define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR		0x22
 #define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK	0x04
 #define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK	0x20
 #define ST_PRESS_LPS331AP_MULTIREAD_BIT		true
-#define ST_PRESS_LPS331AP_TEMP_OFFSET		42500
 
 /* CUSTOM VALUES FOR LPS001WP SENSOR */
+
+/* LPS001WP pressure resolution */
+#define ST_PRESS_LPS001WP_LSB_PER_MBAR		16UL
+/* LPS001WP temperature resolution */
+#define ST_PRESS_LPS001WP_LSB_PER_CELSIUS	64UL
+
 #define ST_PRESS_LPS001WP_WAI_EXP		0xba
 #define ST_PRESS_LPS001WP_ODR_ADDR		0x20
 #define ST_PRESS_LPS001WP_ODR_MASK		0x30
@@ -74,6 +82,8 @@
 #define ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL	0x03
 #define ST_PRESS_LPS001WP_PW_ADDR		0x20
 #define ST_PRESS_LPS001WP_PW_MASK		0x40
+#define ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN \
+	(100000000UL / ST_PRESS_LPS001WP_LSB_PER_MBAR)
 #define ST_PRESS_LPS001WP_BDU_ADDR		0x20
 #define ST_PRESS_LPS001WP_BDU_MASK		0x04
 #define ST_PRESS_LPS001WP_MULTIREAD_BIT		true
@@ -90,18 +100,12 @@
 #define ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL	0x04
 #define ST_PRESS_LPS25H_PW_ADDR			0x20
 #define ST_PRESS_LPS25H_PW_MASK			0x80
-#define ST_PRESS_LPS25H_FS_ADDR			0x00
-#define ST_PRESS_LPS25H_FS_MASK			0x00
-#define ST_PRESS_LPS25H_FS_AVL_1260_VAL		0x00
-#define ST_PRESS_LPS25H_FS_AVL_1260_GAIN	ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN	ST_PRESS_CELSIUS_NANO_SCALE
 #define ST_PRESS_LPS25H_BDU_ADDR		0x20
 #define ST_PRESS_LPS25H_BDU_MASK		0x04
 #define ST_PRESS_LPS25H_DRDY_IRQ_ADDR		0x23
 #define ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK	0x01
 #define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK	0x10
 #define ST_PRESS_LPS25H_MULTIREAD_BIT		true
-#define ST_PRESS_LPS25H_TEMP_OFFSET		42500
 #define ST_PRESS_LPS25H_OUT_XL_ADDR		0x28
 #define ST_TEMP_LPS25H_OUT_L_ADDR		0x2b
 
@@ -153,7 +157,9 @@
 			.storagebits = 16,
 			.endianness = IIO_LE,
 		},
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_separate =
+			BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.modified = 0,
 	},
 	{
@@ -169,7 +175,7 @@
 		},
 		.info_mask_separate =
 			BIT(IIO_CHAN_INFO_RAW) |
-			BIT(IIO_CHAN_INFO_OFFSET),
+			BIT(IIO_CHAN_INFO_SCALE),
 		.modified = 0,
 	},
 	IIO_CHAN_SOFT_TIMESTAMP(1)
@@ -204,11 +210,14 @@
 			.addr = ST_PRESS_LPS331AP_FS_ADDR,
 			.mask = ST_PRESS_LPS331AP_FS_MASK,
 			.fs_avl = {
+				/*
+				 * Pressure and temperature sensitivity values
+				 * as defined in table 3 of LPS331AP datasheet.
+				 */
 				[0] = {
 					.num = ST_PRESS_FS_AVL_1260MB,
-					.value = ST_PRESS_LPS331AP_FS_AVL_1260_VAL,
-					.gain = ST_PRESS_LPS331AP_FS_AVL_1260_GAIN,
-					.gain2 = ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN,
+					.gain = ST_PRESS_KPASCAL_NANO_SCALE,
+					.gain2 = ST_PRESS_LSB_PER_CELSIUS,
 				},
 			},
 		},
@@ -248,7 +257,17 @@
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
 		.fs = {
-			.addr = 0,
+			.fs_avl = {
+				/*
+				 * Pressure and temperature resolution values
+				 * as defined in table 3 of LPS001WP datasheet.
+				 */
+				[0] = {
+					.num = ST_PRESS_FS_AVL_1100MB,
+					.gain = ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN,
+					.gain2 = ST_PRESS_LPS001WP_LSB_PER_CELSIUS,
+				},
+			},
 		},
 		.bdu = {
 			.addr = ST_PRESS_LPS001WP_BDU_ADDR,
@@ -285,14 +304,15 @@
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
 		.fs = {
-			.addr = ST_PRESS_LPS25H_FS_ADDR,
-			.mask = ST_PRESS_LPS25H_FS_MASK,
 			.fs_avl = {
+				/*
+				 * Pressure and temperature sensitivity values
+				 * as defined in table 3 of LPS25H datasheet.
+				 */
 				[0] = {
 					.num = ST_PRESS_FS_AVL_1260MB,
-					.value = ST_PRESS_LPS25H_FS_AVL_1260_VAL,
-					.gain = ST_PRESS_LPS25H_FS_AVL_1260_GAIN,
-					.gain2 = ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN,
+					.gain = ST_PRESS_KPASCAL_NANO_SCALE,
+					.gain2 = ST_PRESS_LSB_PER_CELSIUS,
 				},
 			},
 		},
@@ -346,26 +366,26 @@
 
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		*val = 0;
-
 		switch (ch->type) {
 		case IIO_PRESSURE:
+			*val = 0;
 			*val2 = press_data->current_fullscale->gain;
-			break;
+			return IIO_VAL_INT_PLUS_NANO;
 		case IIO_TEMP:
+			*val = MCELSIUS_PER_CELSIUS;
 			*val2 = press_data->current_fullscale->gain2;
-			break;
+			return IIO_VAL_FRACTIONAL;
 		default:
 			err = -EINVAL;
 			goto read_error;
 		}
 
-		return IIO_VAL_INT_PLUS_NANO;
 	case IIO_CHAN_INFO_OFFSET:
 		switch (ch->type) {
 		case IIO_TEMP:
-			*val = 425;
-			*val2 = 10;
+			*val = ST_PRESS_MILLI_CELSIUS_OFFSET *
+			       press_data->current_fullscale->gain2;
+			*val2 = MCELSIUS_PER_CELSIUS;
 			break;
 		default:
 			err = -EINVAL;
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
index f4d29d5..4204789 100644
--- a/drivers/iio/proximity/as3935.c
+++ b/drivers/iio/proximity/as3935.c
@@ -40,9 +40,9 @@
 #define AS3935_AFE_PWR_BIT	BIT(0)
 
 #define AS3935_INT		0x03
-#define AS3935_INT_MASK		0x07
+#define AS3935_INT_MASK		0x0f
 #define AS3935_EVENT_INT	BIT(3)
-#define AS3935_NOISE_INT	BIT(1)
+#define AS3935_NOISE_INT	BIT(0)
 
 #define AS3935_DATA		0x07
 #define AS3935_DATA_MASK	0x3F
@@ -50,7 +50,6 @@
 #define AS3935_TUNE_CAP		0x08
 #define AS3935_CALIBRATE	0x3D
 
-#define AS3935_WRITE_DATA	BIT(15)
 #define AS3935_READ_DATA	BIT(14)
 #define AS3935_ADDRESS(x)	((x) << 8)
 
@@ -64,6 +63,7 @@
 	struct delayed_work work;
 
 	u32 tune_cap;
+	u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */
 	u8 buf[2] ____cacheline_aligned;
 };
 
@@ -72,7 +72,8 @@
 		.type           = IIO_PROXIMITY,
 		.info_mask_separate =
 			BIT(IIO_CHAN_INFO_RAW) |
-			BIT(IIO_CHAN_INFO_PROCESSED),
+			BIT(IIO_CHAN_INFO_PROCESSED) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.scan_index     = 0,
 		.scan_type = {
 			.sign           = 'u',
@@ -103,7 +104,7 @@
 {
 	u8 *buf = st->buf;
 
-	buf[0] = (AS3935_WRITE_DATA | AS3935_ADDRESS(reg)) >> 8;
+	buf[0] = AS3935_ADDRESS(reg) >> 8;
 	buf[1] = val;
 
 	return spi_write(st->spi, buf, 2);
@@ -181,7 +182,12 @@
 		/* storm out of range */
 		if (*val == AS3935_DATA_MASK)
 			return -EINVAL;
-		*val *= 1000;
+
+		if (m == IIO_CHAN_INFO_PROCESSED)
+			*val *= 1000;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 1000;
 		break;
 	default:
 		return -EINVAL;
@@ -206,10 +212,10 @@
 	ret = as3935_read(st, AS3935_DATA, &val);
 	if (ret)
 		goto err_read;
-	val &= AS3935_DATA_MASK;
-	val *= 1000;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, &val, pf->timestamp);
+	st->buffer[0] = val & AS3935_DATA_MASK;
+	iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,
+					   pf->timestamp);
 err_read:
 	iio_trigger_notify_done(indio_dev->trig);
 
@@ -257,8 +263,6 @@
 
 static void calibrate_as3935(struct as3935_state *st)
 {
-	mutex_lock(&st->lock);
-
 	/* mask disturber interrupt bit */
 	as3935_write(st, AS3935_INT, BIT(5));
 
@@ -268,8 +272,6 @@
 
 	mdelay(2);
 	as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV));
-
-	mutex_unlock(&st->lock);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -306,6 +308,8 @@
 	val &= ~AS3935_AFE_PWR_BIT;
 	ret = as3935_write(st, AS3935_AFE_GAIN, val);
 
+	calibrate_as3935(st);
+
 err_resume:
 	mutex_unlock(&st->lock);
 
@@ -385,7 +389,7 @@
 		return ret;
 	}
 
-	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+	ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time,
 		&as3935_trigger_handler, NULL);
 
 	if (ret) {
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 34b1ada..6a8024d 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -277,8 +277,8 @@
 	fl6.saddr = src_in->sin6_addr;
 	fl6.flowi6_oif = addr->bound_dev_if;
 
-	dst = ip6_route_output(addr->net, NULL, &fl6);
-	if ((ret = dst->error))
+	ret = ipv6_stub->ipv6_dst_lookup(addr->net, NULL, &dst, &fl6);
+	if (ret < 0)
 		goto put;
 
 	if (ipv6_addr_any(&fl6.saddr)) {
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index d6d2b35..941cd9b 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -80,6 +80,8 @@
 	__be32 random_id_operand;
 	struct list_head timewait_list;
 	struct workqueue_struct *wq;
+	/* Sync on cm change port state */
+	spinlock_t state_lock;
 } cm;
 
 /* Counter indexes ordered by attribute ID */
@@ -161,6 +163,8 @@
 	struct ib_mad_agent *mad_agent;
 	struct kobject port_obj;
 	u8 port_num;
+	struct list_head cm_priv_prim_list;
+	struct list_head cm_priv_altr_list;
 	struct cm_counter_group counter_group[CM_COUNTER_GROUPS];
 };
 
@@ -241,6 +245,12 @@
 	u8 service_timeout;
 	u8 target_ack_delay;
 
+	struct list_head prim_list;
+	struct list_head altr_list;
+	/* Indicates that the send port mad is registered and av is set */
+	int prim_send_port_not_ready;
+	int altr_send_port_not_ready;
+
 	struct list_head work_list;
 	atomic_t work_count;
 };
@@ -259,20 +269,47 @@
 	struct ib_mad_agent *mad_agent;
 	struct ib_mad_send_buf *m;
 	struct ib_ah *ah;
+	struct cm_av *av;
+	unsigned long flags, flags2;
+	int ret = 0;
 
+	/* don't let the port to be released till the agent is down */
+	spin_lock_irqsave(&cm.state_lock, flags2);
+	spin_lock_irqsave(&cm.lock, flags);
+	if (!cm_id_priv->prim_send_port_not_ready)
+		av = &cm_id_priv->av;
+	else if (!cm_id_priv->altr_send_port_not_ready &&
+		 (cm_id_priv->alt_av.port))
+		av = &cm_id_priv->alt_av;
+	else {
+		pr_info("%s: not valid CM id\n", __func__);
+		ret = -ENODEV;
+		spin_unlock_irqrestore(&cm.lock, flags);
+		goto out;
+	}
+	spin_unlock_irqrestore(&cm.lock, flags);
+	/* Make sure the port haven't released the mad yet */
 	mad_agent = cm_id_priv->av.port->mad_agent;
-	ah = ib_create_ah(mad_agent->qp->pd, &cm_id_priv->av.ah_attr);
-	if (IS_ERR(ah))
-		return PTR_ERR(ah);
+	if (!mad_agent) {
+		pr_info("%s: not a valid MAD agent\n", __func__);
+		ret = -ENODEV;
+		goto out;
+	}
+	ah = ib_create_ah(mad_agent->qp->pd, &av->ah_attr);
+	if (IS_ERR(ah)) {
+		ret = PTR_ERR(ah);
+		goto out;
+	}
 
 	m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn,
-			       cm_id_priv->av.pkey_index,
+			       av->pkey_index,
 			       0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
 			       GFP_ATOMIC,
 			       IB_MGMT_BASE_VERSION);
 	if (IS_ERR(m)) {
 		ib_destroy_ah(ah);
-		return PTR_ERR(m);
+		ret = PTR_ERR(m);
+		goto out;
 	}
 
 	/* Timeout set by caller if response is expected. */
@@ -282,7 +319,10 @@
 	atomic_inc(&cm_id_priv->refcount);
 	m->context[0] = cm_id_priv;
 	*msg = m;
-	return 0;
+
+out:
+	spin_unlock_irqrestore(&cm.state_lock, flags2);
+	return ret;
 }
 
 static int cm_alloc_response_msg(struct cm_port *port,
@@ -352,7 +392,8 @@
 			   grh, &av->ah_attr);
 }
 
-static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
+static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av,
+			      struct cm_id_private *cm_id_priv)
 {
 	struct cm_device *cm_dev;
 	struct cm_port *port = NULL;
@@ -387,7 +428,17 @@
 			     &av->ah_attr);
 	av->timeout = path->packet_life_time + 1;
 
-	return 0;
+	spin_lock_irqsave(&cm.lock, flags);
+	if (&cm_id_priv->av == av)
+		list_add_tail(&cm_id_priv->prim_list, &port->cm_priv_prim_list);
+	else if (&cm_id_priv->alt_av == av)
+		list_add_tail(&cm_id_priv->altr_list, &port->cm_priv_altr_list);
+	else
+		ret = -EINVAL;
+
+	spin_unlock_irqrestore(&cm.lock, flags);
+
+	return ret;
 }
 
 static int cm_alloc_id(struct cm_id_private *cm_id_priv)
@@ -677,6 +728,8 @@
 	spin_lock_init(&cm_id_priv->lock);
 	init_completion(&cm_id_priv->comp);
 	INIT_LIST_HEAD(&cm_id_priv->work_list);
+	INIT_LIST_HEAD(&cm_id_priv->prim_list);
+	INIT_LIST_HEAD(&cm_id_priv->altr_list);
 	atomic_set(&cm_id_priv->work_count, -1);
 	atomic_set(&cm_id_priv->refcount, 1);
 	return &cm_id_priv->id;
@@ -892,6 +945,15 @@
 		break;
 	}
 
+	spin_lock_irq(&cm.lock);
+	if (!list_empty(&cm_id_priv->altr_list) &&
+	    (!cm_id_priv->altr_send_port_not_ready))
+		list_del(&cm_id_priv->altr_list);
+	if (!list_empty(&cm_id_priv->prim_list) &&
+	    (!cm_id_priv->prim_send_port_not_ready))
+		list_del(&cm_id_priv->prim_list);
+	spin_unlock_irq(&cm.lock);
+
 	cm_free_id(cm_id->local_id);
 	cm_deref_id(cm_id_priv);
 	wait_for_completion(&cm_id_priv->comp);
@@ -1192,12 +1254,13 @@
 		goto out;
 	}
 
-	ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av);
+	ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av,
+				 cm_id_priv);
 	if (ret)
 		goto error1;
 	if (param->alternate_path) {
 		ret = cm_init_av_by_path(param->alternate_path,
-					 &cm_id_priv->alt_av);
+					 &cm_id_priv->alt_av, cm_id_priv);
 		if (ret)
 			goto error1;
 	}
@@ -1639,7 +1702,8 @@
 	cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
 
 	memcpy(work->path[0].dmac, cm_id_priv->av.ah_attr.dmac, ETH_ALEN);
-	ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
+	ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av,
+				 cm_id_priv);
 	if (ret) {
 		ib_get_cached_gid(work->port->cm_dev->ib_device,
 				  work->port->port_num, 0, &work->path[0].sgid,
@@ -1650,7 +1714,8 @@
 		goto rejected;
 	}
 	if (req_msg->alt_local_lid) {
-		ret = cm_init_av_by_path(&work->path[1], &cm_id_priv->alt_av);
+		ret = cm_init_av_by_path(&work->path[1], &cm_id_priv->alt_av,
+					 cm_id_priv);
 		if (ret) {
 			ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_ALT_GID,
 				       &work->path[0].sgid,
@@ -2705,7 +2770,8 @@
 		goto out;
 	}
 
-	ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av);
+	ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av,
+				 cm_id_priv);
 	if (ret)
 		goto out;
 	cm_id_priv->alt_av.timeout =
@@ -2817,7 +2883,8 @@
 	cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
 				work->mad_recv_wc->recv_buf.grh,
 				&cm_id_priv->av);
-	cm_init_av_by_path(param->alternate_path, &cm_id_priv->alt_av);
+	cm_init_av_by_path(param->alternate_path, &cm_id_priv->alt_av,
+			   cm_id_priv);
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -3009,7 +3076,7 @@
 		return -EINVAL;
 
 	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
-	ret = cm_init_av_by_path(param->path, &cm_id_priv->av);
+	ret = cm_init_av_by_path(param->path, &cm_id_priv->av, cm_id_priv);
 	if (ret)
 		goto out;
 
@@ -3430,14 +3497,14 @@
 	work->cm_event.event = IB_CM_USER_ESTABLISHED;
 
 	/* Check if the device started its remove_one */
-	spin_lock_irq(&cm.lock);
+	spin_lock_irqsave(&cm.lock, flags);
 	if (!cm_dev->going_down) {
 		queue_delayed_work(cm.wq, &work->work, 0);
 	} else {
 		kfree(work);
 		ret = -ENODEV;
 	}
-	spin_unlock_irq(&cm.lock);
+	spin_unlock_irqrestore(&cm.lock, flags);
 
 out:
 	return ret;
@@ -3446,7 +3513,9 @@
 static int cm_migrate(struct ib_cm_id *cm_id)
 {
 	struct cm_id_private *cm_id_priv;
+	struct cm_av tmp_av;
 	unsigned long flags;
+	int tmp_send_port_not_ready;
 	int ret = 0;
 
 	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
@@ -3455,7 +3524,14 @@
 	    (cm_id->lap_state == IB_CM_LAP_UNINIT ||
 	     cm_id->lap_state == IB_CM_LAP_IDLE)) {
 		cm_id->lap_state = IB_CM_LAP_IDLE;
+		/* Swap address vector */
+		tmp_av = cm_id_priv->av;
 		cm_id_priv->av = cm_id_priv->alt_av;
+		cm_id_priv->alt_av = tmp_av;
+		/* Swap port send ready state */
+		tmp_send_port_not_ready = cm_id_priv->prim_send_port_not_ready;
+		cm_id_priv->prim_send_port_not_ready = cm_id_priv->altr_send_port_not_ready;
+		cm_id_priv->altr_send_port_not_ready = tmp_send_port_not_ready;
 	} else
 		ret = -EINVAL;
 	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
@@ -3875,6 +3951,9 @@
 		port->cm_dev = cm_dev;
 		port->port_num = i;
 
+		INIT_LIST_HEAD(&port->cm_priv_prim_list);
+		INIT_LIST_HEAD(&port->cm_priv_altr_list);
+
 		ret = cm_create_port_fs(port);
 		if (ret)
 			goto error1;
@@ -3932,6 +4011,8 @@
 {
 	struct cm_device *cm_dev = client_data;
 	struct cm_port *port;
+	struct cm_id_private *cm_id_priv;
+	struct ib_mad_agent *cur_mad_agent;
 	struct ib_port_modify port_modify = {
 		.clr_port_cap_mask = IB_PORT_CM_SUP
 	};
@@ -3955,15 +4036,27 @@
 
 		port = cm_dev->port[i-1];
 		ib_modify_port(ib_device, port->port_num, 0, &port_modify);
+		/* Mark all the cm_id's as not valid */
+		spin_lock_irq(&cm.lock);
+		list_for_each_entry(cm_id_priv, &port->cm_priv_altr_list, altr_list)
+			cm_id_priv->altr_send_port_not_ready = 1;
+		list_for_each_entry(cm_id_priv, &port->cm_priv_prim_list, prim_list)
+			cm_id_priv->prim_send_port_not_ready = 1;
+		spin_unlock_irq(&cm.lock);
 		/*
 		 * We flush the queue here after the going_down set, this
 		 * verify that no new works will be queued in the recv handler,
 		 * after that we can call the unregister_mad_agent
 		 */
 		flush_workqueue(cm.wq);
-		ib_unregister_mad_agent(port->mad_agent);
+		spin_lock_irq(&cm.state_lock);
+		cur_mad_agent = port->mad_agent;
+		port->mad_agent = NULL;
+		spin_unlock_irq(&cm.state_lock);
+		ib_unregister_mad_agent(cur_mad_agent);
 		cm_remove_port_fs(port);
 	}
+
 	device_unregister(cm_dev->device);
 	kfree(cm_dev);
 }
@@ -3976,6 +4069,7 @@
 	INIT_LIST_HEAD(&cm.device_list);
 	rwlock_init(&cm.device_lock);
 	spin_lock_init(&cm.lock);
+	spin_lock_init(&cm.state_lock);
 	cm.listen_service_table = RB_ROOT;
 	cm.listen_service_id = be64_to_cpu(IB_CM_ASSIGN_SERVICE_ID);
 	cm.remote_id_table = RB_ROOT;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 17a15c5..3f5741a 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2578,7 +2578,8 @@
 	if (!src_addr || !src_addr->sa_family) {
 		src_addr = (struct sockaddr *) &id->route.addr.src_addr;
 		src_addr->sa_family = dst_addr->sa_family;
-		if (dst_addr->sa_family == AF_INET6) {
+		if (IS_ENABLED(CONFIG_IPV6) &&
+		    dst_addr->sa_family == AF_INET6) {
 			struct sockaddr_in6 *src_addr6 = (struct sockaddr_in6 *) src_addr;
 			struct sockaddr_in6 *dst_addr6 = (struct sockaddr_in6 *) dst_addr;
 			src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id;
@@ -3348,6 +3349,9 @@
 	struct iw_cm_conn_param iw_param;
 	int ret;
 
+	if (!conn_param)
+		return -EINVAL;
+
 	ret = cma_modify_qp_rtr(id_priv, conn_param);
 	if (ret)
 		return ret;
diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
index 5fb089e..fb43a24 100644
--- a/drivers/infiniband/core/iwpm_util.c
+++ b/drivers/infiniband/core/iwpm_util.c
@@ -634,6 +634,7 @@
 	if (!(ibnl_put_msg(skb, &nlh, 0, 0, nl_client,
 			   RDMA_NL_IWPM_MAPINFO, NLM_F_MULTI))) {
 		pr_warn("%s Unable to put NLMSG_DONE\n", __func__);
+		dev_kfree_skb(skb);
 		return -ENOMEM;
 	}
 	nlh->nlmsg_type = NLMSG_DONE;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 2281de1..8d84c56 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -1745,7 +1745,7 @@
 			if (!class)
 				goto out;
 			if (convert_mgmt_class(mad_hdr->mgmt_class) >=
-			    IB_MGMT_MAX_METHODS)
+			    ARRAY_SIZE(class->method_table))
 				goto out;
 			method = class->method_table[convert_mgmt_class(
 							mad_hdr->mgmt_class)];
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index bb6685f..2cd9797 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -106,7 +106,6 @@
 	atomic_t		refcount;
 	enum mcast_group_state	state;
 	struct ib_sa_query	*query;
-	int			query_id;
 	u16			pkey_index;
 	u8			leave_state;
 	int			retries;
@@ -339,11 +338,7 @@
 				       member->multicast.comp_mask,
 				       3000, GFP_KERNEL, join_handler, group,
 				       &group->query);
-	if (ret >= 0) {
-		group->query_id = ret;
-		ret = 0;
-	}
-	return ret;
+	return (ret > 0) ? 0 : ret;
 }
 
 static int send_leave(struct mcast_group *group, u8 leave_state)
@@ -363,11 +358,7 @@
 				       IB_SA_MCMEMBER_REC_JOIN_STATE,
 				       3000, GFP_KERNEL, leave_handler,
 				       group, &group->query);
-	if (ret >= 0) {
-		group->query_id = ret;
-		ret = 0;
-	}
-	return ret;
+	return (ret > 0) ? 0 : ret;
 }
 
 static void join_group(struct mcast_group *group, struct mcast_member *member,
@@ -526,8 +517,11 @@
 		process_join_error(group, status);
 	else {
 		int mgids_changed, is_mgid0;
-		ib_find_pkey(group->port->dev->device, group->port->port_num,
-			     be16_to_cpu(rec->pkey), &pkey_index);
+
+		if (ib_find_pkey(group->port->dev->device,
+				 group->port->port_num, be16_to_cpu(rec->pkey),
+				 &pkey_index))
+			pkey_index = MCAST_INVALID_PKEY_INDEX;
 
 		spin_lock_irq(&group->port->lock);
 		if (group->state == MCAST_BUSY &&
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index a95a32b..d3b7ecd 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -534,7 +534,7 @@
 	data = ibnl_put_msg(skb, &nlh, query->seq, 0, RDMA_NL_LS,
 			    RDMA_NL_LS_OP_RESOLVE, NLM_F_REQUEST);
 	if (!data) {
-		kfree_skb(skb);
+		nlmsg_free(skb);
 		return -EMSGSIZE;
 	}
 
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index b1f37d4..e76d52a 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -863,7 +863,7 @@
 	free_port_list_attributes(device);
 
 err_unregister:
-	device_unregister(class_dev);
+	device_del(class_dev);
 
 err:
 	return ret;
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 38acb3c..0ae337b 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -134,6 +134,7 @@
 		 IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_MW_BIND));
 
 	if (access & IB_ACCESS_ON_DEMAND) {
+		put_pid(umem->pid);
 		ret = ib_umem_odp_get(context, umem);
 		if (ret) {
 			kfree(umem);
@@ -149,6 +150,7 @@
 
 	page_list = (struct page **) __get_free_page(GFP_KERNEL);
 	if (!page_list) {
+		put_pid(umem->pid);
 		kfree(umem);
 		return ERR_PTR(-ENOMEM);
 	}
@@ -175,7 +177,7 @@
 
 	cur_base = addr & PAGE_MASK;
 
-	if (npages == 0) {
+	if (npages == 0 || npages > UINT_MAX) {
 		ret = -EINVAL;
 		goto out;
 	}
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 94bbd8c..a2d19d1 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -116,6 +116,7 @@
 struct ib_uverbs_file {
 	struct kref				ref;
 	struct mutex				mutex;
+	struct mutex                            cleanup_mutex; /* protect cleanup */
 	struct ib_uverbs_device		       *device;
 	struct ib_ucontext		       *ucontext;
 	struct ib_event_handler			event_handler;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 1c02dea..9eca4b4 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -2287,6 +2287,10 @@
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
+	if (cmd.port_num < rdma_start_port(ib_dev) ||
+	    cmd.port_num > rdma_end_port(ib_dev))
+		return -EINVAL;
+
 	INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
 		   out_len);
 
@@ -2827,6 +2831,10 @@
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
+	if (cmd.attr.port_num < rdma_start_port(ib_dev) ||
+	    cmd.attr.port_num > rdma_end_port(ib_dev))
+		return -EINVAL;
+
 	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
 	if (!uobj)
 		return -ENOMEM;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 24f3ca2..7becef2 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -244,12 +244,9 @@
 			container_of(uobj, struct ib_uqp_object, uevent.uobject);
 
 		idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
-		if (qp != qp->real_qp) {
-			ib_close_qp(qp);
-		} else {
+		if (qp == qp->real_qp)
 			ib_uverbs_detach_umcast(qp, uqp);
-			ib_destroy_qp(qp);
-		}
+		ib_destroy_qp(qp);
 		ib_uverbs_release_uevent(file, &uqp->uevent);
 		kfree(uqp);
 	}
@@ -922,6 +919,7 @@
 	file->async_file = NULL;
 	kref_init(&file->ref);
 	mutex_init(&file->mutex);
+	mutex_init(&file->cleanup_mutex);
 
 	filp->private_data = file;
 	kobject_get(&dev->kobj);
@@ -947,18 +945,20 @@
 {
 	struct ib_uverbs_file *file = filp->private_data;
 	struct ib_uverbs_device *dev = file->device;
-	struct ib_ucontext *ucontext = NULL;
+
+	mutex_lock(&file->cleanup_mutex);
+	if (file->ucontext) {
+		ib_uverbs_cleanup_ucontext(file, file->ucontext);
+		file->ucontext = NULL;
+	}
+	mutex_unlock(&file->cleanup_mutex);
 
 	mutex_lock(&file->device->lists_mutex);
-	ucontext = file->ucontext;
-	file->ucontext = NULL;
 	if (!file->is_closed) {
 		list_del(&file->list);
 		file->is_closed = 1;
 	}
 	mutex_unlock(&file->device->lists_mutex);
-	if (ucontext)
-		ib_uverbs_cleanup_ucontext(file, ucontext);
 
 	if (file->async_file)
 		kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
@@ -1172,22 +1172,30 @@
 	mutex_lock(&uverbs_dev->lists_mutex);
 	while (!list_empty(&uverbs_dev->uverbs_file_list)) {
 		struct ib_ucontext *ucontext;
-
 		file = list_first_entry(&uverbs_dev->uverbs_file_list,
 					struct ib_uverbs_file, list);
 		file->is_closed = 1;
-		ucontext = file->ucontext;
 		list_del(&file->list);
-		file->ucontext = NULL;
 		kref_get(&file->ref);
 		mutex_unlock(&uverbs_dev->lists_mutex);
-		/* We must release the mutex before going ahead and calling
-		 * disassociate_ucontext. disassociate_ucontext might end up
-		 * indirectly calling uverbs_close, for example due to freeing
-		 * the resources (e.g mmput).
-		 */
+
 		ib_uverbs_event_handler(&file->event_handler, &event);
+
+		mutex_lock(&file->cleanup_mutex);
+		ucontext = file->ucontext;
+		file->ucontext = NULL;
+		mutex_unlock(&file->cleanup_mutex);
+
+		/* At this point ib_uverbs_close cannot be running
+		 * ib_uverbs_cleanup_ucontext
+		 */
 		if (ucontext) {
+			/* We must release the mutex before going ahead and
+			 * calling disassociate_ucontext. disassociate_ucontext
+			 * might end up indirectly calling uverbs_close,
+			 * for example due to freeing the resources
+			 * (e.g mmput).
+			 */
 			ib_dev->disassociate_ucontext(ucontext);
 			ib_uverbs_cleanup_ucontext(file, ucontext);
 		}
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c
index 86af713..fc21bdb 100644
--- a/drivers/infiniband/hw/mlx4/ah.c
+++ b/drivers/infiniband/hw/mlx4/ah.c
@@ -47,6 +47,7 @@
 
 	ah->av.ib.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
 	ah->av.ib.g_slid  = ah_attr->src_path_bits;
+	ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
 	if (ah_attr->ah_flags & IB_AH_GRH) {
 		ah->av.ib.g_slid   |= 0x80;
 		ah->av.ib.gid_index = ah_attr->grh.sgid_index;
@@ -64,7 +65,6 @@
 		       !(1 << ah->av.ib.stat_rate & dev->caps.stat_rate_support))
 			--ah->av.ib.stat_rate;
 	}
-	ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
 
 	return &ah->ibah;
 }
@@ -102,7 +102,10 @@
 	if (vlan_tag < 0x1000)
 		vlan_tag |= (ah_attr->sl & 7) << 13;
 	ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
-	ah->av.eth.gid_index = mlx4_ib_gid_index_to_real_index(ibdev, ah_attr->port_num, ah_attr->grh.sgid_index);
+	ret = mlx4_ib_gid_index_to_real_index(ibdev, ah_attr->port_num, ah_attr->grh.sgid_index);
+	if (ret < 0)
+		return ERR_PTR(ret);
+	ah->av.eth.gid_index = ret;
 	ah->av.eth.vlan = cpu_to_be16(vlan_tag);
 	if (ah_attr->static_rate) {
 		ah->av.eth.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
@@ -110,7 +113,9 @@
 		       !(1 << ah->av.eth.stat_rate & dev->caps.stat_rate_support))
 			--ah->av.eth.stat_rate;
 	}
-
+	ah->av.eth.sl_tclass_flowlabel |=
+			cpu_to_be32((ah_attr->grh.traffic_class << 20) |
+				    ah_attr->grh.flow_label);
 	/*
 	 * HW requires multicast LID so we just choose one.
 	 */
@@ -118,7 +123,7 @@
 		ah->av.ib.dlid = cpu_to_be16(0xc000);
 
 	memcpy(ah->av.eth.dgid, ah_attr->grh.dgid.raw, 16);
-	ah->av.eth.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 29);
+	ah->av.eth.sl_tclass_flowlabel |= cpu_to_be32(ah_attr->sl << 29);
 
 	return &ah->ibah;
 }
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index b88fc8f..57e1a08 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -253,11 +253,14 @@
 	if (context)
 		if (ib_copy_to_udata(udata, &cq->mcq.cqn, sizeof (__u32))) {
 			err = -EFAULT;
-			goto err_dbmap;
+			goto err_cq_free;
 		}
 
 	return &cq->ibcq;
 
+err_cq_free:
+	mlx4_cq_free(dev->dev, &cq->mcq);
+
 err_dbmap:
 	if (context)
 		mlx4_ib_db_unmap_user(to_mucontext(context), &cq->db);
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 870e56b..d862b9b 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -526,7 +526,7 @@
 		tun_tx_ix = (++tun_qp->tx_ix_head) & (MLX4_NUM_TUNNEL_BUFS - 1);
 	spin_unlock(&tun_qp->tx_lock);
 	if (ret)
-		goto out;
+		goto end;
 
 	tun_mad = (struct mlx4_rcv_tunnel_mad *) (tun_qp->tx_ring[tun_tx_ix].buf.addr);
 	if (tun_qp->tx_ring[tun_tx_ix].ah)
@@ -595,9 +595,15 @@
 	wr.wr.send_flags = IB_SEND_SIGNALED;
 
 	ret = ib_post_send(src_qp, &wr.wr, &bad_wr);
-out:
-	if (ret)
-		ib_destroy_ah(ah);
+	if (!ret)
+		return 0;
+ out:
+	spin_lock(&tun_qp->tx_lock);
+	tun_qp->tx_ix_tail++;
+	spin_unlock(&tun_qp->tx_lock);
+	tun_qp->tx_ring[tun_tx_ix].ah = NULL;
+end:
+	ib_destroy_ah(ah);
 	return ret;
 }
 
@@ -1074,6 +1080,27 @@
 
 		/* Generate GUID changed event */
 		if (changed_attr & MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK) {
+			if (mlx4_is_master(dev->dev)) {
+				union ib_gid gid;
+				int err = 0;
+
+				if (!eqe->event.port_mgmt_change.params.port_info.gid_prefix)
+					err = __mlx4_ib_query_gid(&dev->ib_dev, port, 0, &gid, 1);
+				else
+					gid.global.subnet_prefix =
+						eqe->event.port_mgmt_change.params.port_info.gid_prefix;
+				if (err) {
+					pr_warn("Could not change QP1 subnet prefix for port %d: query_gid error (%d)\n",
+						port, err);
+				} else {
+					pr_debug("Changing QP1 subnet prefix for port %d. old=0x%llx. new=0x%llx\n",
+						 port,
+						 (u64)atomic64_read(&dev->sriov.demux[port - 1].subnet_prefix),
+						 be64_to_cpu(gid.global.subnet_prefix));
+					atomic64_set(&dev->sriov.demux[port - 1].subnet_prefix,
+						     be64_to_cpu(gid.global.subnet_prefix));
+				}
+			}
 			mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE);
 			/*if master, notify all slaves*/
 			if (mlx4_is_master(dev->dev))
@@ -1278,9 +1305,15 @@
 
 
 	ret = ib_post_send(send_qp, &wr.wr, &bad_wr);
+	if (!ret)
+		return 0;
+
+	spin_lock(&sqp->tx_lock);
+	sqp->tx_ix_tail++;
+	spin_unlock(&sqp->tx_lock);
+	sqp->tx_ring[wire_tx_ix].ah = NULL;
 out:
-	if (ret)
-		ib_destroy_ah(ah);
+	ib_destroy_ah(ah);
 	return ret;
 }
 
@@ -2142,6 +2175,8 @@
 		if (err)
 			goto demux_err;
 		dev->sriov.demux[i].guid_cache[0] = gid.global.interface_id;
+		atomic64_set(&dev->sriov.demux[i].subnet_prefix,
+			     be64_to_cpu(gid.global.subnet_prefix));
 		err = alloc_pv_object(dev, mlx4_master_func_num(dev->dev), i + 1,
 				      &dev->sriov.sqps[i]);
 		if (err)
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 97d6878..8763fb8 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -630,9 +630,11 @@
 	if (err)
 		goto out;
 
-	props->active_width	=  (((u8 *)mailbox->buf)[5] == 0x40) ?
-						IB_WIDTH_4X : IB_WIDTH_1X;
-	props->active_speed	= IB_SPEED_QDR;
+	props->active_width	=  (((u8 *)mailbox->buf)[5] == 0x40) ||
+				   (((u8 *)mailbox->buf)[5] == 0x20 /*56Gb*/) ?
+					   IB_WIDTH_4X : IB_WIDTH_1X;
+	props->active_speed	=  (((u8 *)mailbox->buf)[5] == 0x20 /*56Gb*/) ?
+					   IB_SPEED_FDR : IB_SPEED_QDR;
 	props->port_cap_flags	= IB_PORT_CM_SUP | IB_PORT_IP_BASED_GIDS;
 	props->gid_tbl_len	= mdev->dev->caps.gid_table_len[port];
 	props->max_msg_sz	= mdev->dev->caps.max_msg_sz;
@@ -2401,14 +2403,19 @@
 			goto err_steer_qp_release;
 		}
 
-		bitmap_zero(ibdev->ib_uc_qpns_bitmap, ibdev->steer_qpn_count);
-
-		err = mlx4_FLOW_STEERING_IB_UC_QP_RANGE(
-				dev, ibdev->steer_qpn_base,
-				ibdev->steer_qpn_base +
-				ibdev->steer_qpn_count - 1);
-		if (err)
-			goto err_steer_free_bitmap;
+		if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_DMFS_IPOIB) {
+			bitmap_zero(ibdev->ib_uc_qpns_bitmap,
+				    ibdev->steer_qpn_count);
+			err = mlx4_FLOW_STEERING_IB_UC_QP_RANGE(
+					dev, ibdev->steer_qpn_base,
+					ibdev->steer_qpn_base +
+					ibdev->steer_qpn_count - 1);
+			if (err)
+				goto err_steer_free_bitmap;
+		} else {
+			bitmap_fill(ibdev->ib_uc_qpns_bitmap,
+				    ibdev->steer_qpn_count);
+		}
 	}
 
 	for (j = 1; j <= ibdev->dev->caps.num_ports; j++)
@@ -2484,6 +2491,7 @@
 		mlx4_ib_delete_counters_table(ibdev, &ibdev->counters_table[i]);
 
 err_map:
+	mlx4_ib_free_eqs(dev, ibdev);
 	iounmap(ibdev->uar_map);
 
 err_uar:
diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c
index 99451d8..0b5bb0c 100644
--- a/drivers/infiniband/hw/mlx4/mcg.c
+++ b/drivers/infiniband/hw/mlx4/mcg.c
@@ -489,7 +489,7 @@
 		if (!group->members[i])
 			leave_state |= (1 << i);
 
-	return leave_state & (group->rec.scope_join_state & 7);
+	return leave_state & (group->rec.scope_join_state & 0xf);
 }
 
 static int join_group(struct mcast_group *group, int slave, u8 join_mask)
@@ -564,8 +564,8 @@
 		} else
 			mcg_warn_group(group, "DRIVER BUG\n");
 	} else if (group->state == MCAST_LEAVE_SENT) {
-		if (group->rec.scope_join_state & 7)
-			group->rec.scope_join_state &= 0xf8;
+		if (group->rec.scope_join_state & 0xf)
+			group->rec.scope_join_state &= 0xf0;
 		group->state = MCAST_IDLE;
 		mutex_unlock(&group->lock);
 		if (release_group(group, 1))
@@ -605,7 +605,7 @@
 static int handle_join_req(struct mcast_group *group, u8 join_mask,
 			   struct mcast_req *req)
 {
-	u8 group_join_state = group->rec.scope_join_state & 7;
+	u8 group_join_state = group->rec.scope_join_state & 0xf;
 	int ref = 0;
 	u16 status;
 	struct ib_sa_mcmember_data *sa_data = (struct ib_sa_mcmember_data *)req->sa_mad.data;
@@ -690,8 +690,8 @@
 			u8 cur_join_state;
 
 			resp_join_state = ((struct ib_sa_mcmember_data *)
-						group->response_sa_mad.data)->scope_join_state & 7;
-			cur_join_state = group->rec.scope_join_state & 7;
+						group->response_sa_mad.data)->scope_join_state & 0xf;
+			cur_join_state = group->rec.scope_join_state & 0xf;
 
 			if (method == IB_MGMT_METHOD_GET_RESP) {
 				/* successfull join */
@@ -710,7 +710,7 @@
 		req = list_first_entry(&group->pending_list, struct mcast_req,
 				       group_list);
 		sa_data = (struct ib_sa_mcmember_data *)req->sa_mad.data;
-		req_join_state = sa_data->scope_join_state & 0x7;
+		req_join_state = sa_data->scope_join_state & 0xf;
 
 		/* For a leave request, we will immediately answer the VF, and
 		 * update our internal counters. The actual leave will be sent
@@ -1105,7 +1105,8 @@
 	while ((p = rb_first(&ctx->mcg_table)) != NULL) {
 		group = rb_entry(p, struct mcast_group, node);
 		if (atomic_read(&group->refcount))
-			mcg_warn_group(group, "group refcount %d!!! (pointer %p)\n", atomic_read(&group->refcount), group);
+			mcg_debug_group(group, "group refcount %d!!! (pointer %p)\n",
+					atomic_read(&group->refcount), group);
 
 		force_clean_group(group);
 	}
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 1caa11e..78f29e9 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -441,7 +441,7 @@
 	struct workqueue_struct *wq;
 	struct workqueue_struct *ud_wq;
 	spinlock_t ud_lock;
-	__be64 subnet_prefix;
+	atomic64_t subnet_prefix;
 	__be64 guid_cache[128];
 	struct mlx4_ib_dev *dev;
 	/* the following lock protects both mcg_table and mcg_mgid0_list */
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 13eaaf4..1c8b7c2 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -357,7 +357,7 @@
 			sizeof (struct mlx4_wqe_raddr_seg);
 	case MLX4_IB_QPT_RC:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
-			sizeof (struct mlx4_wqe_atomic_seg) +
+			sizeof (struct mlx4_wqe_masked_atomic_seg) +
 			sizeof (struct mlx4_wqe_raddr_seg);
 	case MLX4_IB_QPT_SMI:
 	case MLX4_IB_QPT_GSI:
@@ -1162,8 +1162,10 @@
 	{
 		err = create_qp_common(to_mdev(pd->device), pd, init_attr,
 				       udata, 0, &qp, gfp);
-		if (err)
+		if (err) {
+			kfree(qp);
 			return ERR_PTR(err);
+		}
 
 		qp->ibqp.qp_num = qp->mqp.qpn;
 		qp->xrcdn = xrcdn;
@@ -1205,7 +1207,8 @@
 	if (is_qp0(dev, mqp))
 		mlx4_CLOSE_PORT(dev->dev, mqp->port);
 
-	if (dev->qp1_proxy[mqp->port - 1] == mqp) {
+	if (mqp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI &&
+	    dev->qp1_proxy[mqp->port - 1] == mqp) {
 		mutex_lock(&dev->qp1_proxy_lock[mqp->port - 1]);
 		dev->qp1_proxy[mqp->port - 1] = NULL;
 		mutex_unlock(&dev->qp1_proxy_lock[mqp->port - 1]);
@@ -2329,24 +2332,27 @@
 		sqp->ud_header.grh.flow_label    =
 			ah->av.ib.sl_tclass_flowlabel & cpu_to_be32(0xfffff);
 		sqp->ud_header.grh.hop_limit     = ah->av.ib.hop_limit;
-		if (is_eth)
+		if (is_eth) {
 			memcpy(sqp->ud_header.grh.source_gid.raw, sgid.raw, 16);
-		else {
-		if (mlx4_is_mfunc(to_mdev(ib_dev)->dev)) {
-			/* When multi-function is enabled, the ib_core gid
-			 * indexes don't necessarily match the hw ones, so
-			 * we must use our own cache */
-			sqp->ud_header.grh.source_gid.global.subnet_prefix =
-				to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
-						       subnet_prefix;
-			sqp->ud_header.grh.source_gid.global.interface_id =
-				to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
-					       guid_cache[ah->av.ib.gid_index];
-		} else
-			ib_get_cached_gid(ib_dev,
-					  be32_to_cpu(ah->av.ib.port_pd) >> 24,
-					  ah->av.ib.gid_index,
-					  &sqp->ud_header.grh.source_gid, NULL);
+		} else {
+			if (mlx4_is_mfunc(to_mdev(ib_dev)->dev)) {
+				/* When multi-function is enabled, the ib_core gid
+				 * indexes don't necessarily match the hw ones, so
+				 * we must use our own cache
+				 */
+				sqp->ud_header.grh.source_gid.global.subnet_prefix =
+					cpu_to_be64(atomic64_read(&(to_mdev(ib_dev)->sriov.
+								    demux[sqp->qp.port - 1].
+								    subnet_prefix)));
+				sqp->ud_header.grh.source_gid.global.interface_id =
+					to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
+						       guid_cache[ah->av.ib.gid_index];
+			} else {
+				ib_get_cached_gid(ib_dev,
+						  be32_to_cpu(ah->av.ib.port_pd) >> 24,
+						  ah->av.ib.gid_index,
+						  &sqp->ud_header.grh.source_gid, NULL);
+			}
 		}
 		memcpy(sqp->ud_header.grh.destination_gid.raw,
 		       ah->av.ib.dgid, 16);
diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c
index 92ddae1..02c8dea 100644
--- a/drivers/infiniband/hw/mlx5/cq.c
+++ b/drivers/infiniband/hw/mlx5/cq.c
@@ -763,7 +763,8 @@
 	if (attr->flags)
 		return ERR_PTR(-EINVAL);
 
-	if (entries < 0)
+	if (entries < 0 ||
+	    (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz))))
 		return ERR_PTR(-EINVAL);
 
 	entries = roundup_pow_of_two(entries + 1);
@@ -786,8 +787,7 @@
 		if (err)
 			goto err_create;
 	} else {
-		/* for now choose 64 bytes till we have a proper interface */
-		cqe_size = 64;
+		cqe_size = cache_line_size() == 128 ? 128 : 64;
 		err = create_cq_kernel(dev, cq, entries, cqe_size, &cqb,
 				       &index, &inlen);
 		if (err)
@@ -1094,11 +1094,16 @@
 		return -ENOSYS;
 	}
 
-	if (entries < 1)
+	if (entries < 1 ||
+	    entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz))) {
+		mlx5_ib_warn(dev, "wrong entries number %d, max %d\n",
+			     entries,
+			     1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz));
 		return -EINVAL;
+	}
 
 	entries = roundup_pow_of_two(entries + 1);
-	if (entries >  (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)) + 1)
+	if (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)) + 1)
 		return -EINVAL;
 
 	if (entries == ibcq->cqe + 1)
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 721d63f..2a1fdca 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -405,8 +405,8 @@
 	struct mlx5_ib_dev *dev = to_mdev(ibdev);
 	struct mlx5_core_dev *mdev = dev->mdev;
 	struct mlx5_hca_vport_context *rep;
-	int max_mtu;
-	int oper_mtu;
+	u16 max_mtu;
+	u16 oper_mtu;
 	int err;
 	u8 ib_link_width_oper;
 	u8 vl_hw_cap;
@@ -947,13 +947,13 @@
 {
 	struct mlx5_ib_dev *ibdev = (struct mlx5_ib_dev *)context;
 	struct ib_event ibev;
-
+	bool fatal = false;
 	u8 port = 0;
 
 	switch (event) {
 	case MLX5_DEV_EVENT_SYS_ERROR:
-		ibdev->ib_active = false;
 		ibev.event = IB_EVENT_DEVICE_FATAL;
+		fatal = true;
 		break;
 
 	case MLX5_DEV_EVENT_PORT_UP:
@@ -962,14 +962,11 @@
 		break;
 
 	case MLX5_DEV_EVENT_PORT_DOWN:
+	case MLX5_DEV_EVENT_PORT_INITIALIZED:
 		ibev.event = IB_EVENT_PORT_ERR;
 		port = (u8)param;
 		break;
 
-	case MLX5_DEV_EVENT_PORT_INITIALIZED:
-		/* not used by ULPs */
-		return;
-
 	case MLX5_DEV_EVENT_LID_CHANGE:
 		ibev.event = IB_EVENT_LID_CHANGE;
 		port = (u8)param;
@@ -1001,6 +998,9 @@
 
 	if (ibdev->ib_active)
 		ib_dispatch_event(&ibev);
+
+	if (fatal)
+		ibdev->ib_active = false;
 }
 
 static void get_ext_port_caps(struct mlx5_ib_dev *dev)
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 6000f7a..3399271 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -614,6 +614,33 @@
 	return 0;
 }
 
+static void wait_for_async_commands(struct mlx5_ib_dev *dev)
+{
+	struct mlx5_mr_cache *cache = &dev->cache;
+	struct mlx5_cache_ent *ent;
+	int total = 0;
+	int i;
+	int j;
+
+	for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
+		ent = &cache->ent[i];
+		for (j = 0 ; j < 1000; j++) {
+			if (!ent->pending)
+				break;
+			msleep(50);
+		}
+	}
+	for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
+		ent = &cache->ent[i];
+		total += ent->pending;
+	}
+
+	if (total)
+		mlx5_ib_warn(dev, "aborted while there are %d pending mr requests\n", total);
+	else
+		mlx5_ib_warn(dev, "done with all pending requests\n");
+}
+
 int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
 {
 	int i;
@@ -627,6 +654,7 @@
 		clean_keys(dev, i);
 
 	destroy_workqueue(dev->cache.wq);
+	wait_for_async_commands(dev);
 	del_timer_sync(&dev->delay_timer);
 
 	return 0;
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 307bdbc..cfcfbb6 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -226,6 +226,8 @@
 		qp->rq.max_gs = 0;
 		qp->rq.wqe_cnt = 0;
 		qp->rq.wqe_shift = 0;
+		cap->max_recv_wr = 0;
+		cap->max_recv_sge = 0;
 	} else {
 		if (ucmd) {
 			qp->rq.wqe_cnt = ucmd->rq_wqe_count;
@@ -2525,10 +2527,11 @@
 			return MLX5_FENCE_MODE_SMALL_AND_FENCE;
 		else
 			return fence;
-
-	} else {
-		return 0;
+	} else if (unlikely(wr->send_flags & IB_SEND_FENCE)) {
+		return MLX5_FENCE_MODE_FENCE;
 	}
+
+	return 0;
 }
 
 static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
@@ -3092,17 +3095,19 @@
 	qp_attr->cap.max_recv_sge    = qp->rq.max_gs;
 
 	if (!ibqp->uobject) {
-		qp_attr->cap.max_send_wr  = qp->sq.wqe_cnt;
+		qp_attr->cap.max_send_wr  = qp->sq.max_post;
 		qp_attr->cap.max_send_sge = qp->sq.max_gs;
+		qp_init_attr->qp_context = ibqp->qp_context;
 	} else {
 		qp_attr->cap.max_send_wr  = 0;
 		qp_attr->cap.max_send_sge = 0;
 	}
 
-	/* We don't support inline sends for kernel QPs (yet), and we
-	 * don't know what userspace's value should be.
-	 */
-	qp_attr->cap.max_inline_data = 0;
+	qp_init_attr->qp_type = ibqp->qp_type;
+	qp_init_attr->recv_cq = ibqp->recv_cq;
+	qp_init_attr->send_cq = ibqp->send_cq;
+	qp_init_attr->srq = ibqp->srq;
+	qp_attr->cap.max_inline_data = qp->max_inline_data;
 
 	qp_init_attr->cap	     = qp_attr->cap;
 
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index 3eff35c..2684605 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -41,13 +41,13 @@
 
 #include "qib.h"
 
-#define BITS_PER_PAGE           (PAGE_SIZE*BITS_PER_BYTE)
-#define BITS_PER_PAGE_MASK      (BITS_PER_PAGE-1)
+#define RVT_BITS_PER_PAGE           (PAGE_SIZE*BITS_PER_BYTE)
+#define RVT_BITS_PER_PAGE_MASK      (RVT_BITS_PER_PAGE-1)
 
 static inline unsigned mk_qpn(struct qib_qpn_table *qpt,
 			      struct qpn_map *map, unsigned off)
 {
-	return (map - qpt->map) * BITS_PER_PAGE + off;
+	return (map - qpt->map) * RVT_BITS_PER_PAGE + off;
 }
 
 static inline unsigned find_next_offset(struct qib_qpn_table *qpt,
@@ -59,7 +59,7 @@
 		if (((off & qpt->mask) >> 1) >= n)
 			off = (off | qpt->mask) + 2;
 	} else
-		off = find_next_zero_bit(map->page, BITS_PER_PAGE, off);
+		off = find_next_zero_bit(map->page, RVT_BITS_PER_PAGE, off);
 	return off;
 }
 
@@ -147,8 +147,8 @@
 		qpn = 2;
 	if (qpt->mask && ((qpn & qpt->mask) >> 1) >= dd->n_krcv_queues)
 		qpn = (qpn | qpt->mask) + 2;
-	offset = qpn & BITS_PER_PAGE_MASK;
-	map = &qpt->map[qpn / BITS_PER_PAGE];
+	offset = qpn & RVT_BITS_PER_PAGE_MASK;
+	map = &qpt->map[qpn / RVT_BITS_PER_PAGE];
 	max_scan = qpt->nmaps - !offset;
 	for (i = 0;;) {
 		if (unlikely(!map->page)) {
@@ -173,7 +173,7 @@
 			 * We just need to be sure we don't loop
 			 * forever.
 			 */
-		} while (offset < BITS_PER_PAGE && qpn < QPN_MAX);
+		} while (offset < RVT_BITS_PER_PAGE && qpn < QPN_MAX);
 		/*
 		 * In order to keep the number of pages allocated to a
 		 * minimum, we scan the all existing pages before increasing
@@ -204,9 +204,9 @@
 {
 	struct qpn_map *map;
 
-	map = qpt->map + qpn / BITS_PER_PAGE;
+	map = qpt->map + qpn / RVT_BITS_PER_PAGE;
 	if (map->page)
-		clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
+		clear_bit(qpn & RVT_BITS_PER_PAGE_MASK, map->page);
 }
 
 static inline unsigned qpn_hash(struct qib_ibdev *dev, u32 qpn)
diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c
index e6b7556..cbc4216 100644
--- a/drivers/infiniband/hw/qib/qib_rc.c
+++ b/drivers/infiniband/hw/qib/qib_rc.c
@@ -2088,8 +2088,10 @@
 		ret = qib_get_rwqe(qp, 1);
 		if (ret < 0)
 			goto nack_op_err;
-		if (!ret)
+		if (!ret) {
+			qib_put_ss(&qp->r_sge);
 			goto rnr_nak;
+		}
 		wc.ex.imm_data = ohdr->u.rc.imm_data;
 		hdrsize += 4;
 		wc.wc_flags = IB_WC_WITH_IMM;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 3ede103..07cfcc3 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -63,6 +63,8 @@
 
 enum {
 	IPOIB_ENCAP_LEN		  = 4,
+	IPOIB_PSEUDO_LEN	  = 20,
+	IPOIB_HARD_LEN		  = IPOIB_ENCAP_LEN + IPOIB_PSEUDO_LEN,
 
 	IPOIB_UD_HEAD_SIZE	  = IB_GRH_BYTES + IPOIB_ENCAP_LEN,
 	IPOIB_UD_RX_SG		  = 2, /* max buffer needed for 4K mtu */
@@ -131,15 +133,21 @@
 	u16	reserved;
 };
 
-struct ipoib_cb {
-	struct qdisc_skb_cb	qdisc_cb;
-	u8			hwaddr[INFINIBAND_ALEN];
+struct ipoib_pseudo_header {
+	u8	hwaddr[INFINIBAND_ALEN];
 };
 
-static inline struct ipoib_cb *ipoib_skb_cb(const struct sk_buff *skb)
+static inline void skb_add_pseudo_hdr(struct sk_buff *skb)
 {
-	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct ipoib_cb));
-	return (struct ipoib_cb *)skb->cb;
+	char *data = skb_push(skb, IPOIB_PSEUDO_LEN);
+
+	/*
+	 * only the ipoib header is present now, make room for a dummy
+	 * pseudo header and set skb field accordingly
+	 */
+	memset(data, 0, IPOIB_PSEUDO_LEN);
+	skb_reset_mac_header(skb);
+	skb_pull(skb, IPOIB_HARD_LEN);
 }
 
 /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
@@ -472,6 +480,7 @@
 		struct ipoib_ah *address, u32 qpn);
 void ipoib_reap_ah(struct work_struct *work);
 
+struct ipoib_path *__path_find(struct net_device *dev, void *gid);
 void ipoib_mark_paths_invalid(struct net_device *dev);
 void ipoib_flush_paths(struct net_device *dev);
 struct ipoib_dev_priv *ipoib_intf_alloc(const char *format);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 3ae9726..2018d24 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -63,6 +63,8 @@
 #define IPOIB_CM_RX_DELAY       (3 * 256 * HZ)
 #define IPOIB_CM_RX_UPDATE_MASK (0x3)
 
+#define IPOIB_CM_RX_RESERVE     (ALIGN(IPOIB_HARD_LEN, 16) - IPOIB_ENCAP_LEN)
+
 static struct ib_qp_attr ipoib_cm_err_attr = {
 	.qp_state = IB_QPS_ERR
 };
@@ -147,15 +149,15 @@
 	struct sk_buff *skb;
 	int i;
 
-	skb = dev_alloc_skb(IPOIB_CM_HEAD_SIZE + 12);
+	skb = dev_alloc_skb(ALIGN(IPOIB_CM_HEAD_SIZE + IPOIB_PSEUDO_LEN, 16));
 	if (unlikely(!skb))
 		return NULL;
 
 	/*
-	 * IPoIB adds a 4 byte header. So we need 12 more bytes to align the
+	 * IPoIB adds a IPOIB_ENCAP_LEN byte header, this will align the
 	 * IP header to a multiple of 16.
 	 */
-	skb_reserve(skb, 12);
+	skb_reserve(skb, IPOIB_CM_RX_RESERVE);
 
 	mapping[0] = ib_dma_map_single(priv->ca, skb->data, IPOIB_CM_HEAD_SIZE,
 				       DMA_FROM_DEVICE);
@@ -624,9 +626,9 @@
 	if (wc->byte_len < IPOIB_CM_COPYBREAK) {
 		int dlen = wc->byte_len;
 
-		small_skb = dev_alloc_skb(dlen + 12);
+		small_skb = dev_alloc_skb(dlen + IPOIB_CM_RX_RESERVE);
 		if (small_skb) {
-			skb_reserve(small_skb, 12);
+			skb_reserve(small_skb, IPOIB_CM_RX_RESERVE);
 			ib_dma_sync_single_for_cpu(priv->ca, rx_ring[wr_id].mapping[0],
 						   dlen, DMA_FROM_DEVICE);
 			skb_copy_from_linear_data(skb, small_skb->data, dlen);
@@ -663,8 +665,7 @@
 
 copied:
 	skb->protocol = ((struct ipoib_header *) skb->data)->proto;
-	skb_reset_mac_header(skb);
-	skb_pull(skb, IPOIB_ENCAP_LEN);
+	skb_add_pseudo_hdr(skb);
 
 	++dev->stats.rx_packets;
 	dev->stats.rx_bytes += skb->len;
@@ -1035,8 +1036,6 @@
 
 	tx_qp = ib_create_qp(priv->pd, &attr);
 	if (PTR_ERR(tx_qp) == -EINVAL) {
-		ipoib_warn(priv, "can't use GFP_NOIO for QPs on device %s, using GFP_KERNEL\n",
-			   priv->ca->name);
 		attr.create_flags &= ~IB_QP_CREATE_USE_GFP_NOIO;
 		tx_qp = ib_create_qp(priv->pd, &attr);
 	}
@@ -1299,6 +1298,8 @@
 	}
 }
 
+#define QPN_AND_OPTIONS_OFFSET	4
+
 static void ipoib_cm_tx_start(struct work_struct *work)
 {
 	struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
@@ -1307,6 +1308,7 @@
 	struct ipoib_neigh *neigh;
 	struct ipoib_cm_tx *p;
 	unsigned long flags;
+	struct ipoib_path *path;
 	int ret;
 
 	struct ib_sa_path_rec pathrec;
@@ -1319,7 +1321,19 @@
 		p = list_entry(priv->cm.start_list.next, typeof(*p), list);
 		list_del_init(&p->list);
 		neigh = p->neigh;
+
 		qpn = IPOIB_QPN(neigh->daddr);
+		/*
+		 * As long as the search is with these 2 locks,
+		 * path existence indicates its validity.
+		 */
+		path = __path_find(dev, neigh->daddr + QPN_AND_OPTIONS_OFFSET);
+		if (!path) {
+			pr_info("%s ignore not valid path %pI6\n",
+				__func__,
+				neigh->daddr + QPN_AND_OPTIONS_OFFSET);
+			goto free_neigh;
+		}
 		memcpy(&pathrec, &p->path->pathrec, sizeof pathrec);
 
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -1331,6 +1345,7 @@
 		spin_lock_irqsave(&priv->lock, flags);
 
 		if (ret) {
+free_neigh:
 			neigh = p->neigh;
 			if (neigh) {
 				neigh->cm = NULL;
@@ -1473,12 +1488,14 @@
 
 	ret = ipoib_set_mode(dev, buf);
 
-	rtnl_unlock();
+	/* The assumption is that the function ipoib_set_mode returned
+	 * with the rtnl held by it, if not the value -EBUSY returned,
+	 * then no need to rtnl_unlock
+	 */
+	if (ret != -EBUSY)
+		rtnl_unlock();
 
-	if (!ret)
-		return count;
-
-	return ret;
+	return (!ret || ret == -EBUSY) ? count : ret;
 }
 
 static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 6bd5740..09396bd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -281,8 +281,11 @@
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
+	WARN_ONCE(!priv->mcg_dentry, "null mcg debug file\n");
+	WARN_ONCE(!priv->path_dentry, "null path debug file\n");
 	debugfs_remove(priv->mcg_dentry);
 	debugfs_remove(priv->path_dentry);
+	priv->mcg_dentry = priv->path_dentry = NULL;
 }
 
 int ipoib_register_debugfs(void)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 5ea0c14..8f8c3af 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -130,16 +130,15 @@
 
 	buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
 
-	skb = dev_alloc_skb(buf_size + IPOIB_ENCAP_LEN);
+	skb = dev_alloc_skb(buf_size + IPOIB_HARD_LEN);
 	if (unlikely(!skb))
 		return NULL;
 
 	/*
-	 * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte
-	 * header.  So we need 4 more bytes to get to 48 and align the
-	 * IP header to a multiple of 16.
+	 * the IP header will be at IPOIP_HARD_LEN + IB_GRH_BYTES, that is
+	 * 64 bytes aligned
 	 */
-	skb_reserve(skb, 4);
+	skb_reserve(skb, sizeof(struct ipoib_pseudo_header));
 
 	mapping = priv->rx_ring[id].mapping;
 	mapping[0] = ib_dma_map_single(priv->ca, skb->data, buf_size,
@@ -242,10 +241,7 @@
 	skb_pull(skb, IB_GRH_BYTES);
 
 	skb->protocol = ((struct ipoib_header *) skb->data)->proto;
-	skb_reset_mac_header(skb);
-	skb_pull(skb, IPOIB_ENCAP_LEN);
-
-	skb->truesize = SKB_TRUESIZE(skb->len);
+	skb_add_pseudo_hdr(skb);
 
 	++dev->stats.rx_packets;
 	dev->stats.rx_bytes += skb->len;
@@ -1030,8 +1026,17 @@
 	}
 
 	if (level == IPOIB_FLUSH_LIGHT) {
+		int oper_up;
 		ipoib_mark_paths_invalid(dev);
+		/* Set IPoIB operation as down to prevent races between:
+		 * the flush flow which leaves MCG and on the fly joins
+		 * which can happen during that time. mcast restart task
+		 * should deal with join requests we missed.
+		 */
+		oper_up = test_and_clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
 		ipoib_mcast_dev_flush(dev);
+		if (oper_up)
+			set_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
 		ipoib_flush_ah(dev);
 	}
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 7d32818..6699ecd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -106,6 +106,33 @@
 	.get_net_dev_by_params = ipoib_get_net_dev_by_params,
 };
 
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+static int ipoib_netdev_event(struct notifier_block *this,
+			      unsigned long event, void *ptr)
+{
+	struct netdev_notifier_info *ni = ptr;
+	struct net_device *dev = ni->dev;
+
+	if (dev->netdev_ops->ndo_open != ipoib_open)
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_REGISTER:
+		ipoib_create_debug_files(dev);
+		break;
+	case NETDEV_CHANGENAME:
+		ipoib_delete_debug_files(dev);
+		ipoib_create_debug_files(dev);
+		break;
+	case NETDEV_UNREGISTER:
+		ipoib_delete_debug_files(dev);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+#endif
+
 int ipoib_open(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -464,8 +491,7 @@
 		priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM;
 
 		ipoib_flush_paths(dev);
-		rtnl_lock();
-		return 0;
+		return (!rtnl_trylock()) ? -EBUSY : 0;
 	}
 
 	if (!strcmp(buf, "datagram\n")) {
@@ -474,14 +500,13 @@
 		dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu));
 		rtnl_unlock();
 		ipoib_flush_paths(dev);
-		rtnl_lock();
-		return 0;
+		return (!rtnl_trylock()) ? -EBUSY : 0;
 	}
 
 	return -EINVAL;
 }
 
-static struct ipoib_path *__path_find(struct net_device *dev, void *gid)
+struct ipoib_path *__path_find(struct net_device *dev, void *gid)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct rb_node *n = priv->path_tree.rb_node;
@@ -628,6 +653,14 @@
 	spin_unlock_irq(&priv->lock);
 }
 
+static void push_pseudo_header(struct sk_buff *skb, const char *daddr)
+{
+	struct ipoib_pseudo_header *phdr;
+
+	phdr = (struct ipoib_pseudo_header *)skb_push(skb, sizeof(*phdr));
+	memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
+}
+
 void ipoib_flush_paths(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -850,9 +883,11 @@
 				ipoib_neigh_free(neigh);
 				goto err_drop;
 			}
-			if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE)
+			if (skb_queue_len(&neigh->queue) <
+			    IPOIB_MAX_PATH_REC_QUEUE) {
+				push_pseudo_header(skb, neigh->daddr);
 				__skb_queue_tail(&neigh->queue, skb);
-			else {
+			} else {
 				ipoib_warn(priv, "queue length limit %d. Packet drop.\n",
 					   skb_queue_len(&neigh->queue));
 				goto err_drop;
@@ -868,10 +903,12 @@
 
 		if (!path->query && path_rec_start(dev, path))
 			goto err_path;
-		if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE)
+		if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+			push_pseudo_header(skb, neigh->daddr);
 			__skb_queue_tail(&neigh->queue, skb);
-		else
+		} else {
 			goto err_drop;
+		}
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -889,7 +926,7 @@
 }
 
 static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
-			     struct ipoib_cb *cb)
+			     struct ipoib_pseudo_header *phdr)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_path *path;
@@ -897,16 +934,17 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	path = __path_find(dev, cb->hwaddr + 4);
+	path = __path_find(dev, phdr->hwaddr + 4);
 	if (!path || !path->valid) {
 		int new_path = 0;
 
 		if (!path) {
-			path = path_rec_create(dev, cb->hwaddr + 4);
+			path = path_rec_create(dev, phdr->hwaddr + 4);
 			new_path = 1;
 		}
 		if (path) {
 			if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+				push_pseudo_header(skb, phdr->hwaddr);
 				__skb_queue_tail(&path->queue, skb);
 			} else {
 				++dev->stats.tx_dropped;
@@ -934,10 +972,11 @@
 			  be16_to_cpu(path->pathrec.dlid));
 
 		spin_unlock_irqrestore(&priv->lock, flags);
-		ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr));
+		ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr));
 		return;
 	} else if ((path->query || !path_rec_start(dev, path)) &&
 		   skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+		push_pseudo_header(skb, phdr->hwaddr);
 		__skb_queue_tail(&path->queue, skb);
 	} else {
 		++dev->stats.tx_dropped;
@@ -951,13 +990,15 @@
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_neigh *neigh;
-	struct ipoib_cb *cb = ipoib_skb_cb(skb);
+	struct ipoib_pseudo_header *phdr;
 	struct ipoib_header *header;
 	unsigned long flags;
 
+	phdr = (struct ipoib_pseudo_header *) skb->data;
+	skb_pull(skb, sizeof(*phdr));
 	header = (struct ipoib_header *) skb->data;
 
-	if (unlikely(cb->hwaddr[4] == 0xff)) {
+	if (unlikely(phdr->hwaddr[4] == 0xff)) {
 		/* multicast, arrange "if" according to probability */
 		if ((header->proto != htons(ETH_P_IP)) &&
 		    (header->proto != htons(ETH_P_IPV6)) &&
@@ -970,13 +1011,13 @@
 			return NETDEV_TX_OK;
 		}
 		/* Add in the P_Key for multicast*/
-		cb->hwaddr[8] = (priv->pkey >> 8) & 0xff;
-		cb->hwaddr[9] = priv->pkey & 0xff;
+		phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff;
+		phdr->hwaddr[9] = priv->pkey & 0xff;
 
-		neigh = ipoib_neigh_get(dev, cb->hwaddr);
+		neigh = ipoib_neigh_get(dev, phdr->hwaddr);
 		if (likely(neigh))
 			goto send_using_neigh;
-		ipoib_mcast_send(dev, cb->hwaddr, skb);
+		ipoib_mcast_send(dev, phdr->hwaddr, skb);
 		return NETDEV_TX_OK;
 	}
 
@@ -985,16 +1026,16 @@
 	case htons(ETH_P_IP):
 	case htons(ETH_P_IPV6):
 	case htons(ETH_P_TIPC):
-		neigh = ipoib_neigh_get(dev, cb->hwaddr);
+		neigh = ipoib_neigh_get(dev, phdr->hwaddr);
 		if (unlikely(!neigh)) {
-			neigh_add_path(skb, cb->hwaddr, dev);
+			neigh_add_path(skb, phdr->hwaddr, dev);
 			return NETDEV_TX_OK;
 		}
 		break;
 	case htons(ETH_P_ARP):
 	case htons(ETH_P_RARP):
 		/* for unicast ARP and RARP should always perform path find */
-		unicast_arp_send(skb, dev, cb);
+		unicast_arp_send(skb, dev, phdr);
 		return NETDEV_TX_OK;
 	default:
 		/* ethertype not supported by IPoIB */
@@ -1011,11 +1052,12 @@
 			goto unref;
 		}
 	} else if (neigh->ah) {
-		ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(cb->hwaddr));
+		ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(phdr->hwaddr));
 		goto unref;
 	}
 
 	if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+		push_pseudo_header(skb, phdr->hwaddr);
 		spin_lock_irqsave(&priv->lock, flags);
 		__skb_queue_tail(&neigh->queue, skb);
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -1048,7 +1090,6 @@
 			     const void *daddr, const void *saddr, unsigned len)
 {
 	struct ipoib_header *header;
-	struct ipoib_cb *cb = ipoib_skb_cb(skb);
 
 	header = (struct ipoib_header *) skb_push(skb, sizeof *header);
 
@@ -1057,12 +1098,12 @@
 
 	/*
 	 * we don't rely on dst_entry structure,  always stuff the
-	 * destination address into skb->cb so we can figure out where
+	 * destination address into skb hard header so we can figure out where
 	 * to send the packet later.
 	 */
-	memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN);
+	push_pseudo_header(skb, daddr);
 
-	return sizeof *header;
+	return IPOIB_HARD_LEN;
 }
 
 static void ipoib_set_mcast_list(struct net_device *dev)
@@ -1131,7 +1172,9 @@
 				neigh = NULL;
 				goto out_unlock;
 			}
-			neigh->alive = jiffies;
+
+			if (likely(skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE))
+				neigh->alive = jiffies;
 			goto out_unlock;
 		}
 	}
@@ -1579,8 +1622,6 @@
 
 	ASSERT_RTNL();
 
-	ipoib_delete_debug_files(dev);
-
 	/* Delete any child interfaces first */
 	list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) {
 		/* Stop GC on child */
@@ -1636,7 +1677,7 @@
 
 	dev->flags		|= IFF_BROADCAST | IFF_MULTICAST;
 
-	dev->hard_header_len	 = IPOIB_ENCAP_LEN;
+	dev->hard_header_len	 = IPOIB_HARD_LEN;
 	dev->addr_len		 = INFINIBAND_ALEN;
 	dev->type		 = ARPHRD_INFINIBAND;
 	dev->tx_queue_len	 = ipoib_sendq_size * 2;
@@ -1892,8 +1933,6 @@
 		goto register_failed;
 	}
 
-	ipoib_create_debug_files(priv->dev);
-
 	if (ipoib_cm_add_mode_attr(priv->dev))
 		goto sysfs_failed;
 	if (ipoib_add_pkey_attr(priv->dev))
@@ -1908,7 +1947,6 @@
 	return priv->dev;
 
 sysfs_failed:
-	ipoib_delete_debug_files(priv->dev);
 	unregister_netdev(priv->dev);
 
 register_failed:
@@ -1990,6 +2028,12 @@
 	kfree(dev_list);
 }
 
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+static struct notifier_block ipoib_netdev_notifier = {
+	.notifier_call = ipoib_netdev_event,
+};
+#endif
+
 static int __init ipoib_init_module(void)
 {
 	int ret;
@@ -2041,6 +2085,9 @@
 	if (ret)
 		goto err_client;
 
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+	register_netdevice_notifier(&ipoib_netdev_notifier);
+#endif
 	return 0;
 
 err_client:
@@ -2058,6 +2105,9 @@
 
 static void __exit ipoib_cleanup_module(void)
 {
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+	unregister_netdevice_notifier(&ipoib_netdev_notifier);
+#endif
 	ipoib_netlink_fini();
 	ib_unregister_client(&ipoib_client);
 	ib_sa_unregister_client(&ipoib_sa_client);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 87799de..5580ab0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -563,8 +563,11 @@
 	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
 		return;
 
-	if (ib_query_port(priv->ca, priv->port, &port_attr) ||
-	    port_attr.state != IB_PORT_ACTIVE) {
+	if (ib_query_port(priv->ca, priv->port, &port_attr)) {
+		ipoib_dbg(priv, "ib_query_port() failed\n");
+		return;
+	}
+	if (port_attr.state != IB_PORT_ACTIVE) {
 		ipoib_dbg(priv, "port state is not ACTIVE (state = %d) suspending join task\n",
 			  port_attr.state);
 		return;
@@ -753,9 +756,11 @@
 			__ipoib_mcast_add(dev, mcast);
 			list_add_tail(&mcast->list, &priv->multicast_list);
 		}
-		if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE)
+		if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) {
+			/* put pseudoheader back on for next time */
+			skb_push(skb, sizeof(struct ipoib_pseudo_header));
 			skb_queue_tail(&mcast->pkt_queue, skb);
-		else {
+		} else {
 			++dev->stats.tx_dropped;
 			dev_kfree_skb_any(skb);
 		}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index fca1a88..57a34f8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -85,8 +85,6 @@
 		goto register_failed;
 	}
 
-	ipoib_create_debug_files(priv->dev);
-
 	/* RTNL childs don't need proprietary sysfs entries */
 	if (type == IPOIB_LEGACY_CHILD) {
 		if (ipoib_cm_add_mode_attr(priv->dev))
@@ -107,7 +105,6 @@
 
 sysfs_failed:
 	result = -ENOMEM;
-	ipoib_delete_debug_files(priv->dev);
 	unregister_netdevice(priv->dev);
 
 register_failed:
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 3db9a65..e397f1b 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1519,7 +1519,7 @@
 
 	if (dev->use_fast_reg) {
 		state.sg = idb_sg;
-		sg_set_buf(idb_sg, req->indirect_desc, idb_len);
+		sg_init_one(idb_sg, req->indirect_desc, idb_len);
 		idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
 #ifdef CONFIG_NEED_SG_DMA_LENGTH
 		idb_sg->dma_length = idb_sg->length;	      /* hack^2 */
@@ -1787,17 +1787,24 @@
 	if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
 		spin_lock_irqsave(&ch->lock, flags);
 		ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
+		if (rsp->tag == ch->tsk_mgmt_tag) {
+			ch->tsk_mgmt_status = -1;
+			if (be32_to_cpu(rsp->resp_data_len) >= 4)
+				ch->tsk_mgmt_status = rsp->data[3];
+			complete(&ch->tsk_mgmt_done);
+		} else {
+			shost_printk(KERN_ERR, target->scsi_host,
+				     "Received tsk mgmt response too late for tag %#llx\n",
+				     rsp->tag);
+		}
 		spin_unlock_irqrestore(&ch->lock, flags);
-
-		ch->tsk_mgmt_status = -1;
-		if (be32_to_cpu(rsp->resp_data_len) >= 4)
-			ch->tsk_mgmt_status = rsp->data[3];
-		complete(&ch->tsk_mgmt_done);
 	} else {
 		scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag);
-		if (scmnd) {
+		if (scmnd && scmnd->host_scribble) {
 			req = (void *)scmnd->host_scribble;
 			scmnd = srp_claim_req(ch, req, NULL, scmnd);
+		} else {
+			scmnd = NULL;
 		}
 		if (!scmnd) {
 			shost_printk(KERN_ERR, target->scsi_host,
@@ -2469,19 +2476,18 @@
 }
 
 static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
-			     u8 func)
+			     u8 func, u8 *status)
 {
 	struct srp_target_port *target = ch->target;
 	struct srp_rport *rport = target->rport;
 	struct ib_device *dev = target->srp_host->srp_dev->dev;
 	struct srp_iu *iu;
 	struct srp_tsk_mgmt *tsk_mgmt;
+	int res;
 
 	if (!ch->connected || target->qp_in_error)
 		return -1;
 
-	init_completion(&ch->tsk_mgmt_done);
-
 	/*
 	 * Lock the rport mutex to avoid that srp_create_ch_ib() is
 	 * invoked while a task management function is being sent.
@@ -2504,10 +2510,16 @@
 
 	tsk_mgmt->opcode 	= SRP_TSK_MGMT;
 	int_to_scsilun(lun, &tsk_mgmt->lun);
-	tsk_mgmt->tag		= req_tag | SRP_TAG_TSK_MGMT;
 	tsk_mgmt->tsk_mgmt_func = func;
 	tsk_mgmt->task_tag	= req_tag;
 
+	spin_lock_irq(&ch->lock);
+	ch->tsk_mgmt_tag = (ch->tsk_mgmt_tag + 1) | SRP_TAG_TSK_MGMT;
+	tsk_mgmt->tag = ch->tsk_mgmt_tag;
+	spin_unlock_irq(&ch->lock);
+
+	init_completion(&ch->tsk_mgmt_done);
+
 	ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
 				      DMA_TO_DEVICE);
 	if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) {
@@ -2516,13 +2528,15 @@
 
 		return -1;
 	}
+	res = wait_for_completion_timeout(&ch->tsk_mgmt_done,
+					msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS));
+	if (res > 0 && status)
+		*status = ch->tsk_mgmt_status;
 	mutex_unlock(&rport->mutex);
 
-	if (!wait_for_completion_timeout(&ch->tsk_mgmt_done,
-					 msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
-		return -1;
+	WARN_ON_ONCE(res < 0);
 
-	return 0;
+	return res > 0 ? 0 : -1;
 }
 
 static int srp_abort(struct scsi_cmnd *scmnd)
@@ -2548,7 +2562,7 @@
 	shost_printk(KERN_ERR, target->scsi_host,
 		     "Sending SRP abort for tag %#x\n", tag);
 	if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
-			      SRP_TSK_ABORT_TASK) == 0)
+			      SRP_TSK_ABORT_TASK, NULL) == 0)
 		ret = SUCCESS;
 	else if (target->rport->state == SRP_RPORT_LOST)
 		ret = FAST_IO_FAIL;
@@ -2566,14 +2580,15 @@
 	struct srp_target_port *target = host_to_target(scmnd->device->host);
 	struct srp_rdma_ch *ch;
 	int i;
+	u8 status;
 
 	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
 
 	ch = &target->ch[0];
 	if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun,
-			      SRP_TSK_LUN_RESET))
+			      SRP_TSK_LUN_RESET, &status))
 		return FAILED;
-	if (ch->tsk_mgmt_status)
+	if (status)
 		return FAILED;
 
 	for (i = 0; i < target->ch_count; i++) {
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index f6af531..109eea9 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -168,6 +168,7 @@
 	int			max_ti_iu_len;
 	int			comp_vector;
 
+	u64			tsk_mgmt_tag;
 	struct completion	tsk_mgmt_done;
 	u8			tsk_mgmt_status;
 	bool			connected;
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index d96aa27..db64adf 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -141,6 +141,9 @@
 
 	interface = intf->cur_altsetting;
 
+	if (interface->desc.bNumEndpoints < 2)
+		return -ENODEV;
+
 	epirq = &interface->endpoint[0].desc;
 	epout = &interface->endpoint[1].desc;
 
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index fd4100d..3258baf 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -189,6 +189,7 @@
 	{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
 	{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
 	{ 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 },
+	{ 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE },
 	{ 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 },
 	{ 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
 	{ 0x15e4, 0x3f10, "Batarang Xbox 360 controller", 0, XTYPE_XBOX360 },
@@ -310,6 +311,7 @@
 	XPAD_XBOX360_VENDOR(0x1689),		/* Razer Onza */
 	XPAD_XBOX360_VENDOR(0x24c6),		/* PowerA Controllers */
 	XPAD_XBOX360_VENDOR(0x1532),		/* Razer Sabertooth */
+	XPAD_XBOXONE_VENDOR(0x1532),		/* Razer Wildcat */
 	XPAD_XBOX360_VENDOR(0x15e4),		/* Numark X-Box 360 controllers */
 	XPAD_XBOX360_VENDOR(0x162e),		/* Joytech X-Box 360 controllers */
 	{ }
@@ -317,6 +319,19 @@
 
 MODULE_DEVICE_TABLE(usb, xpad_table);
 
+struct xpad_output_packet {
+	u8 data[XPAD_PKT_LEN];
+	u8 len;
+	bool pending;
+};
+
+#define XPAD_OUT_CMD_IDX	0
+#define XPAD_OUT_FF_IDX		1
+#define XPAD_OUT_LED_IDX	(1 + IS_ENABLED(CONFIG_JOYSTICK_XPAD_FF))
+#define XPAD_NUM_OUT_PACKETS	(1 + \
+				 IS_ENABLED(CONFIG_JOYSTICK_XPAD_FF) + \
+				 IS_ENABLED(CONFIG_JOYSTICK_XPAD_LEDS))
+
 struct usb_xpad {
 	struct input_dev *dev;		/* input device interface */
 	struct usb_device *udev;	/* usb device */
@@ -329,9 +344,13 @@
 	dma_addr_t idata_dma;
 
 	struct urb *irq_out;		/* urb for interrupt out report */
+	bool irq_out_active;		/* we must not use an active URB */
 	unsigned char *odata;		/* output data */
 	dma_addr_t odata_dma;
-	struct mutex odata_mutex;
+	spinlock_t odata_lock;
+
+	struct xpad_output_packet out_packets[XPAD_NUM_OUT_PACKETS];
+	int last_out_packet;
 
 #if defined(CONFIG_JOYSTICK_XPAD_LEDS)
 	struct xpad_led *led;
@@ -678,18 +697,71 @@
 			__func__, retval);
 }
 
+/* Callers must hold xpad->odata_lock spinlock */
+static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad)
+{
+	struct xpad_output_packet *pkt, *packet = NULL;
+	int i;
+
+	for (i = 0; i < XPAD_NUM_OUT_PACKETS; i++) {
+		if (++xpad->last_out_packet >= XPAD_NUM_OUT_PACKETS)
+			xpad->last_out_packet = 0;
+
+		pkt = &xpad->out_packets[xpad->last_out_packet];
+		if (pkt->pending) {
+			dev_dbg(&xpad->intf->dev,
+				"%s - found pending output packet %d\n",
+				__func__, xpad->last_out_packet);
+			packet = pkt;
+			break;
+		}
+	}
+
+	if (packet) {
+		memcpy(xpad->odata, packet->data, packet->len);
+		xpad->irq_out->transfer_buffer_length = packet->len;
+		packet->pending = false;
+		return true;
+	}
+
+	return false;
+}
+
+/* Callers must hold xpad->odata_lock spinlock */
+static int xpad_try_sending_next_out_packet(struct usb_xpad *xpad)
+{
+	int error;
+
+	if (!xpad->irq_out_active && xpad_prepare_next_out_packet(xpad)) {
+		error = usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+		if (error) {
+			dev_err(&xpad->intf->dev,
+				"%s - usb_submit_urb failed with result %d\n",
+				__func__, error);
+			return -EIO;
+		}
+
+		xpad->irq_out_active = true;
+	}
+
+	return 0;
+}
+
 static void xpad_irq_out(struct urb *urb)
 {
 	struct usb_xpad *xpad = urb->context;
 	struct device *dev = &xpad->intf->dev;
-	int retval, status;
+	int status = urb->status;
+	int error;
+	unsigned long flags;
 
-	status = urb->status;
+	spin_lock_irqsave(&xpad->odata_lock, flags);
 
 	switch (status) {
 	case 0:
 		/* success */
-		return;
+		xpad->irq_out_active = xpad_prepare_next_out_packet(xpad);
+		break;
 
 	case -ECONNRESET:
 	case -ENOENT:
@@ -697,19 +769,26 @@
 		/* this urb is terminated, clean up */
 		dev_dbg(dev, "%s - urb shutting down with status: %d\n",
 			__func__, status);
-		return;
+		xpad->irq_out_active = false;
+		break;
 
 	default:
 		dev_dbg(dev, "%s - nonzero urb status received: %d\n",
 			__func__, status);
-		goto exit;
+		break;
 	}
 
-exit:
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
-			__func__, retval);
+	if (xpad->irq_out_active) {
+		error = usb_submit_urb(urb, GFP_ATOMIC);
+		if (error) {
+			dev_err(dev,
+				"%s - usb_submit_urb failed with result %d\n",
+				__func__, error);
+			xpad->irq_out_active = false;
+		}
+	}
+
+	spin_unlock_irqrestore(&xpad->odata_lock, flags);
 }
 
 static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
@@ -728,7 +807,7 @@
 		goto fail1;
 	}
 
-	mutex_init(&xpad->odata_mutex);
+	spin_lock_init(&xpad->odata_lock);
 
 	xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
 	if (!xpad->irq_out) {
@@ -770,27 +849,57 @@
 
 static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
 {
+	struct xpad_output_packet *packet =
+			&xpad->out_packets[XPAD_OUT_CMD_IDX];
+	unsigned long flags;
 	int retval;
 
-	mutex_lock(&xpad->odata_mutex);
+	spin_lock_irqsave(&xpad->odata_lock, flags);
 
-	xpad->odata[0] = 0x08;
-	xpad->odata[1] = 0x00;
-	xpad->odata[2] = 0x0F;
-	xpad->odata[3] = 0xC0;
-	xpad->odata[4] = 0x00;
-	xpad->odata[5] = 0x00;
-	xpad->odata[6] = 0x00;
-	xpad->odata[7] = 0x00;
-	xpad->odata[8] = 0x00;
-	xpad->odata[9] = 0x00;
-	xpad->odata[10] = 0x00;
-	xpad->odata[11] = 0x00;
-	xpad->irq_out->transfer_buffer_length = 12;
+	packet->data[0] = 0x08;
+	packet->data[1] = 0x00;
+	packet->data[2] = 0x0F;
+	packet->data[3] = 0xC0;
+	packet->data[4] = 0x00;
+	packet->data[5] = 0x00;
+	packet->data[6] = 0x00;
+	packet->data[7] = 0x00;
+	packet->data[8] = 0x00;
+	packet->data[9] = 0x00;
+	packet->data[10] = 0x00;
+	packet->data[11] = 0x00;
+	packet->len = 12;
+	packet->pending = true;
 
-	retval = usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+	/* Reset the sequence so we send out presence first */
+	xpad->last_out_packet = -1;
+	retval = xpad_try_sending_next_out_packet(xpad);
 
-	mutex_unlock(&xpad->odata_mutex);
+	spin_unlock_irqrestore(&xpad->odata_lock, flags);
+
+	return retval;
+}
+
+static int xpad_start_xbox_one(struct usb_xpad *xpad)
+{
+	struct xpad_output_packet *packet =
+			&xpad->out_packets[XPAD_OUT_CMD_IDX];
+	unsigned long flags;
+	int retval;
+
+	spin_lock_irqsave(&xpad->odata_lock, flags);
+
+	/* Xbox one controller needs to be initialized. */
+	packet->data[0] = 0x05;
+	packet->data[1] = 0x20;
+	packet->len = 2;
+	packet->pending = true;
+
+	/* Reset the sequence so we send out start packet first */
+	xpad->last_out_packet = -1;
+	retval = xpad_try_sending_next_out_packet(xpad);
+
+	spin_unlock_irqrestore(&xpad->odata_lock, flags);
 
 	return retval;
 }
@@ -799,8 +908,11 @@
 static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
 {
 	struct usb_xpad *xpad = input_get_drvdata(dev);
+	struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_FF_IDX];
 	__u16 strong;
 	__u16 weak;
+	int retval;
+	unsigned long flags;
 
 	if (effect->type != FF_RUMBLE)
 		return 0;
@@ -808,69 +920,80 @@
 	strong = effect->u.rumble.strong_magnitude;
 	weak = effect->u.rumble.weak_magnitude;
 
+	spin_lock_irqsave(&xpad->odata_lock, flags);
+
 	switch (xpad->xtype) {
 	case XTYPE_XBOX:
-		xpad->odata[0] = 0x00;
-		xpad->odata[1] = 0x06;
-		xpad->odata[2] = 0x00;
-		xpad->odata[3] = strong / 256;	/* left actuator */
-		xpad->odata[4] = 0x00;
-		xpad->odata[5] = weak / 256;	/* right actuator */
-		xpad->irq_out->transfer_buffer_length = 6;
+		packet->data[0] = 0x00;
+		packet->data[1] = 0x06;
+		packet->data[2] = 0x00;
+		packet->data[3] = strong / 256;	/* left actuator */
+		packet->data[4] = 0x00;
+		packet->data[5] = weak / 256;	/* right actuator */
+		packet->len = 6;
+		packet->pending = true;
 		break;
 
 	case XTYPE_XBOX360:
-		xpad->odata[0] = 0x00;
-		xpad->odata[1] = 0x08;
-		xpad->odata[2] = 0x00;
-		xpad->odata[3] = strong / 256;  /* left actuator? */
-		xpad->odata[4] = weak / 256;	/* right actuator? */
-		xpad->odata[5] = 0x00;
-		xpad->odata[6] = 0x00;
-		xpad->odata[7] = 0x00;
-		xpad->irq_out->transfer_buffer_length = 8;
+		packet->data[0] = 0x00;
+		packet->data[1] = 0x08;
+		packet->data[2] = 0x00;
+		packet->data[3] = strong / 256;  /* left actuator? */
+		packet->data[4] = weak / 256;	/* right actuator? */
+		packet->data[5] = 0x00;
+		packet->data[6] = 0x00;
+		packet->data[7] = 0x00;
+		packet->len = 8;
+		packet->pending = true;
 		break;
 
 	case XTYPE_XBOX360W:
-		xpad->odata[0] = 0x00;
-		xpad->odata[1] = 0x01;
-		xpad->odata[2] = 0x0F;
-		xpad->odata[3] = 0xC0;
-		xpad->odata[4] = 0x00;
-		xpad->odata[5] = strong / 256;
-		xpad->odata[6] = weak / 256;
-		xpad->odata[7] = 0x00;
-		xpad->odata[8] = 0x00;
-		xpad->odata[9] = 0x00;
-		xpad->odata[10] = 0x00;
-		xpad->odata[11] = 0x00;
-		xpad->irq_out->transfer_buffer_length = 12;
+		packet->data[0] = 0x00;
+		packet->data[1] = 0x01;
+		packet->data[2] = 0x0F;
+		packet->data[3] = 0xC0;
+		packet->data[4] = 0x00;
+		packet->data[5] = strong / 256;
+		packet->data[6] = weak / 256;
+		packet->data[7] = 0x00;
+		packet->data[8] = 0x00;
+		packet->data[9] = 0x00;
+		packet->data[10] = 0x00;
+		packet->data[11] = 0x00;
+		packet->len = 12;
+		packet->pending = true;
 		break;
 
 	case XTYPE_XBOXONE:
-		xpad->odata[0] = 0x09; /* activate rumble */
-		xpad->odata[1] = 0x08;
-		xpad->odata[2] = 0x00;
-		xpad->odata[3] = 0x08; /* continuous effect */
-		xpad->odata[4] = 0x00; /* simple rumble mode */
-		xpad->odata[5] = 0x03; /* L and R actuator only */
-		xpad->odata[6] = 0x00; /* TODO: LT actuator */
-		xpad->odata[7] = 0x00; /* TODO: RT actuator */
-		xpad->odata[8] = strong / 256;	/* left actuator */
-		xpad->odata[9] = weak / 256;	/* right actuator */
-		xpad->odata[10] = 0x80;	/* length of pulse */
-		xpad->odata[11] = 0x00;	/* stop period of pulse */
-		xpad->irq_out->transfer_buffer_length = 12;
+		packet->data[0] = 0x09; /* activate rumble */
+		packet->data[1] = 0x08;
+		packet->data[2] = 0x00;
+		packet->data[3] = 0x08; /* continuous effect */
+		packet->data[4] = 0x00; /* simple rumble mode */
+		packet->data[5] = 0x03; /* L and R actuator only */
+		packet->data[6] = 0x00; /* TODO: LT actuator */
+		packet->data[7] = 0x00; /* TODO: RT actuator */
+		packet->data[8] = strong / 256;	/* left actuator */
+		packet->data[9] = weak / 256;	/* right actuator */
+		packet->data[10] = 0x80;	/* length of pulse */
+		packet->data[11] = 0x00;	/* stop period of pulse */
+		packet->len = 12;
+		packet->pending = true;
 		break;
 
 	default:
 		dev_dbg(&xpad->dev->dev,
 			"%s - rumble command sent to unsupported xpad type: %d\n",
 			__func__, xpad->xtype);
-		return -EINVAL;
+		retval = -EINVAL;
+		goto out;
 	}
 
-	return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+	retval = xpad_try_sending_next_out_packet(xpad);
+
+out:
+	spin_unlock_irqrestore(&xpad->odata_lock, flags);
+	return retval;
 }
 
 static int xpad_init_ff(struct usb_xpad *xpad)
@@ -921,36 +1044,44 @@
  */
 static void xpad_send_led_command(struct usb_xpad *xpad, int command)
 {
+	struct xpad_output_packet *packet =
+			&xpad->out_packets[XPAD_OUT_LED_IDX];
+	unsigned long flags;
+
 	command %= 16;
 
-	mutex_lock(&xpad->odata_mutex);
+	spin_lock_irqsave(&xpad->odata_lock, flags);
 
 	switch (xpad->xtype) {
 	case XTYPE_XBOX360:
-		xpad->odata[0] = 0x01;
-		xpad->odata[1] = 0x03;
-		xpad->odata[2] = command;
-		xpad->irq_out->transfer_buffer_length = 3;
+		packet->data[0] = 0x01;
+		packet->data[1] = 0x03;
+		packet->data[2] = command;
+		packet->len = 3;
+		packet->pending = true;
 		break;
+
 	case XTYPE_XBOX360W:
-		xpad->odata[0] = 0x00;
-		xpad->odata[1] = 0x00;
-		xpad->odata[2] = 0x08;
-		xpad->odata[3] = 0x40 + command;
-		xpad->odata[4] = 0x00;
-		xpad->odata[5] = 0x00;
-		xpad->odata[6] = 0x00;
-		xpad->odata[7] = 0x00;
-		xpad->odata[8] = 0x00;
-		xpad->odata[9] = 0x00;
-		xpad->odata[10] = 0x00;
-		xpad->odata[11] = 0x00;
-		xpad->irq_out->transfer_buffer_length = 12;
+		packet->data[0] = 0x00;
+		packet->data[1] = 0x00;
+		packet->data[2] = 0x08;
+		packet->data[3] = 0x40 + command;
+		packet->data[4] = 0x00;
+		packet->data[5] = 0x00;
+		packet->data[6] = 0x00;
+		packet->data[7] = 0x00;
+		packet->data[8] = 0x00;
+		packet->data[9] = 0x00;
+		packet->data[10] = 0x00;
+		packet->data[11] = 0x00;
+		packet->len = 12;
+		packet->pending = true;
 		break;
 	}
 
-	usb_submit_urb(xpad->irq_out, GFP_KERNEL);
-	mutex_unlock(&xpad->odata_mutex);
+	xpad_try_sending_next_out_packet(xpad);
+
+	spin_unlock_irqrestore(&xpad->odata_lock, flags);
 }
 
 /*
@@ -1048,13 +1179,8 @@
 	if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
 		return -EIO;
 
-	if (xpad->xtype == XTYPE_XBOXONE) {
-		/* Xbox one controller needs to be initialized. */
-		xpad->odata[0] = 0x05;
-		xpad->odata[1] = 0x20;
-		xpad->irq_out->transfer_buffer_length = 2;
-		return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
-	}
+	if (xpad->xtype == XTYPE_XBOXONE)
+		return xpad_start_xbox_one(xpad);
 
 	return 0;
 }
@@ -1114,6 +1240,12 @@
 	input_dev->name = xpad->name;
 	input_dev->phys = xpad->phys;
 	usb_to_input_id(xpad->udev, &input_dev->id);
+
+	if (xpad->xtype == XTYPE_XBOX360W) {
+		/* x360w controllers and the receiver have different ids */
+		input_dev->id.product = 0x02a1;
+	}
+
 	input_dev->dev.parent = &xpad->intf->dev;
 
 	input_set_drvdata(input_dev, xpad);
@@ -1200,22 +1332,15 @@
 	int ep_irq_in_idx;
 	int i, error;
 
+	if (intf->cur_altsetting->desc.bNumEndpoints != 2)
+		return -ENODEV;
+
 	for (i = 0; xpad_device[i].idVendor; i++) {
 		if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
 		    (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct))
 			break;
 	}
 
-	if (xpad_device[i].xtype == XTYPE_XBOXONE &&
-	    intf->cur_altsetting->desc.bInterfaceNumber != 0) {
-		/*
-		 * The Xbox One controller lists three interfaces all with the
-		 * same interface class, subclass and protocol. Differentiate by
-		 * interface number.
-		 */
-		return -ENODEV;
-	}
-
 	xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
 	if (!xpad)
 		return -ENOMEM;
@@ -1246,6 +1371,8 @@
 		if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
 			if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
 				xpad->xtype = XTYPE_XBOX360W;
+			else if (intf->cur_altsetting->desc.bInterfaceProtocol == 208)
+				xpad->xtype = XTYPE_XBOXONE;
 			else
 				xpad->xtype = XTYPE_XBOX360;
 		} else {
@@ -1260,6 +1387,17 @@
 			xpad->mapping |= MAP_STICKS_TO_NULL;
 	}
 
+	if (xpad->xtype == XTYPE_XBOXONE &&
+	    intf->cur_altsetting->desc.bInterfaceNumber != 0) {
+		/*
+		 * The Xbox One controller lists three interfaces all with the
+		 * same interface class, subclass and protocol. Differentiate by
+		 * interface number.
+		 */
+		error = -ENODEV;
+		goto err_free_in_urb;
+	}
+
 	error = xpad_init_output(intf, xpad);
 	if (error)
 		goto err_free_in_urb;
diff --git a/drivers/input/keyboard/goldfish_events.c b/drivers/input/keyboard/goldfish_events.c
index 907e4e2..c877e56 100644
--- a/drivers/input/keyboard/goldfish_events.c
+++ b/drivers/input/keyboard/goldfish_events.c
@@ -17,11 +17,15 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/acpi.h>
+
+#define GOLDFISH_MAX_FINGERS 5
 
 enum {
 	REG_READ        = 0x00,
@@ -51,7 +55,21 @@
 	value = __raw_readl(edev->addr + REG_READ);
 
 	input_event(edev->input, type, code, value);
-	input_sync(edev->input);
+	// Send an extra (EV_SYN, SYN_REPORT, 0x0) event
+	// if a key was pressed. Some keyboard device
+        // drivers may only send the EV_KEY event and
+        // not EV_SYN.
+        // Note that sending an extra SYN_REPORT is not
+        // necessary nor correct protocol with other
+        // devices such as touchscreens, which will send
+        // their own SYN_REPORT's when sufficient event
+        // information has been collected (e.g., for
+        // touchscreens, when pressure and X/Y coordinates
+	// have been received). Hence, we will only send
+	// this extra SYN_REPORT if type == EV_KEY.
+	if (type == EV_KEY) {
+		input_sync(edev->input);
+	}
 	return IRQ_HANDLED;
 }
 
@@ -153,6 +171,15 @@
 
 	input_dev->name = edev->name;
 	input_dev->id.bustype = BUS_HOST;
+	// Set the Goldfish Device to be multi-touch.
+	// In the Ranchu kernel, there is multi-touch-specific
+	// code for handling ABS_MT_SLOT events.
+	// See drivers/input/input.c:input_handle_abs_event.
+	// If we do not issue input_mt_init_slots,
+        // the kernel will filter out needed ABS_MT_SLOT
+        // events when we touch the screen in more than one place,
+        // preventing multi-touch with more than one finger from working.
+	input_mt_init_slots(input_dev, GOLDFISH_MAX_FINGERS, 0);
 
 	events_import_bits(edev, input_dev->evbit, EV_SYN, EV_MAX);
 	events_import_bits(edev, input_dev->keybit, EV_KEY, KEY_MAX);
@@ -178,10 +205,26 @@
 	return 0;
 }
 
+static const struct of_device_id goldfish_events_of_match[] = {
+	{ .compatible = "google,goldfish-events-keypad", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, goldfish_events_of_match);
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id goldfish_events_acpi_match[] = {
+	{ "GFSH0002", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, goldfish_events_acpi_match);
+#endif
+
 static struct platform_driver events_driver = {
 	.probe	= events_probe,
 	.driver	= {
 		.name	= "goldfish_events",
+		.of_match_table = goldfish_events_of_match,
+		.acpi_match_table = ACPI_PTR(goldfish_events_acpi_match),
 	},
 };
 
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index acc5394..29485bc 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -376,7 +376,7 @@
 	/* Reset the KBC controller to clear all previous status.*/
 	reset_control_assert(kbc->rst);
 	udelay(100);
-	reset_control_assert(kbc->rst);
+	reset_control_deassert(kbc->rst);
 	udelay(100);
 
 	tegra_kbc_config_pins(kbc);
diff --git a/drivers/input/keyreset.c b/drivers/input/keyreset.c
index 7fbf724..7e5222a 100644
--- a/drivers/input/keyreset.c
+++ b/drivers/input/keyreset.c
@@ -32,8 +32,7 @@
 
 static void do_restart(struct work_struct *unused)
 {
-	sys_sync();
-	kernel_restart(NULL);
+	orderly_reboot();
 }
 
 static void do_reset_fn(void *priv)
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
index 9365535..50a7faa 100644
--- a/drivers/input/misc/cm109.c
+++ b/drivers/input/misc/cm109.c
@@ -675,6 +675,10 @@
 	int error = -ENOMEM;
 
 	interface = intf->cur_altsetting;
+
+	if (interface->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	endpoint = &interface->endpoint[0].desc;
 
 	if (!usb_endpoint_is_int_in(endpoint))
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index 2adfd86c..930424e 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -592,7 +592,6 @@
 	}
 
 	haptics->input_dev->name = "drv260x:haptics";
-	haptics->input_dev->dev.parent = client->dev.parent;
 	haptics->input_dev->close = drv260x_close;
 	input_set_drvdata(haptics->input_dev, haptics);
 	input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 9c0ea36..f4e8fbe 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -1667,6 +1667,10 @@
 		return -EINVAL;
 
 	alt = pcu->ctrl_intf->cur_altsetting;
+
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	pcu->ep_ctrl = &alt->endpoint[0].desc;
 	pcu->max_ctrl_size = usb_endpoint_maxp(pcu->ep_ctrl);
 
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index a806ba3..8d6326d 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -255,12 +255,14 @@
 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	const struct max8997_platform_data *pdata =
 					dev_get_platdata(iodev->dev);
-	const struct max8997_haptic_platform_data *haptic_pdata =
-					pdata->haptic_pdata;
+	const struct max8997_haptic_platform_data *haptic_pdata = NULL;
 	struct max8997_haptic *chip;
 	struct input_dev *input_dev;
 	int error;
 
+	if (pdata)
+		haptic_pdata = pdata->haptic_pdata;
+
 	if (!haptic_pdata) {
 		dev_err(&pdev->dev, "no haptic platform data\n");
 		return -EINVAL;
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
index f2261ab..18663d4 100644
--- a/drivers/input/misc/pwm-beeper.c
+++ b/drivers/input/misc/pwm-beeper.c
@@ -20,21 +20,40 @@
 #include <linux/platform_device.h>
 #include <linux/pwm.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 
 struct pwm_beeper {
 	struct input_dev *input;
 	struct pwm_device *pwm;
+	struct work_struct work;
 	unsigned long period;
 };
 
 #define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
 
+static void __pwm_beeper_set(struct pwm_beeper *beeper)
+{
+	unsigned long period = beeper->period;
+
+	if (period) {
+		pwm_config(beeper->pwm, period / 2, period);
+		pwm_enable(beeper->pwm);
+	} else
+		pwm_disable(beeper->pwm);
+}
+
+static void pwm_beeper_work(struct work_struct *work)
+{
+	struct pwm_beeper *beeper =
+		container_of(work, struct pwm_beeper, work);
+
+	__pwm_beeper_set(beeper);
+}
+
 static int pwm_beeper_event(struct input_dev *input,
 			    unsigned int type, unsigned int code, int value)
 {
-	int ret = 0;
 	struct pwm_beeper *beeper = input_get_drvdata(input);
-	unsigned long period;
 
 	if (type != EV_SND || value < 0)
 		return -EINVAL;
@@ -49,22 +68,31 @@
 		return -EINVAL;
 	}
 
-	if (value == 0) {
-		pwm_disable(beeper->pwm);
-	} else {
-		period = HZ_TO_NANOSECONDS(value);
-		ret = pwm_config(beeper->pwm, period / 2, period);
-		if (ret)
-			return ret;
-		ret = pwm_enable(beeper->pwm);
-		if (ret)
-			return ret;
-		beeper->period = period;
-	}
+	if (value == 0)
+		beeper->period = 0;
+	else
+		beeper->period = HZ_TO_NANOSECONDS(value);
+
+	schedule_work(&beeper->work);
 
 	return 0;
 }
 
+static void pwm_beeper_stop(struct pwm_beeper *beeper)
+{
+	cancel_work_sync(&beeper->work);
+
+	if (beeper->period)
+		pwm_disable(beeper->pwm);
+}
+
+static void pwm_beeper_close(struct input_dev *input)
+{
+	struct pwm_beeper *beeper = input_get_drvdata(input);
+
+	pwm_beeper_stop(beeper);
+}
+
 static int pwm_beeper_probe(struct platform_device *pdev)
 {
 	unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev);
@@ -87,6 +115,8 @@
 		goto err_free;
 	}
 
+	INIT_WORK(&beeper->work, pwm_beeper_work);
+
 	beeper->input = input_allocate_device();
 	if (!beeper->input) {
 		dev_err(&pdev->dev, "Failed to allocate input device\n");
@@ -106,6 +136,7 @@
 	beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL);
 
 	beeper->input->event = pwm_beeper_event;
+	beeper->input->close = pwm_beeper_close;
 
 	input_set_drvdata(beeper->input, beeper);
 
@@ -135,7 +166,6 @@
 
 	input_unregister_device(beeper->input);
 
-	pwm_disable(beeper->pwm);
 	pwm_free(beeper->pwm);
 
 	kfree(beeper);
@@ -147,8 +177,7 @@
 {
 	struct pwm_beeper *beeper = dev_get_drvdata(dev);
 
-	if (beeper->period)
-		pwm_disable(beeper->pwm);
+	pwm_beeper_stop(beeper);
 
 	return 0;
 }
@@ -157,10 +186,8 @@
 {
 	struct pwm_beeper *beeper = dev_get_drvdata(dev);
 
-	if (beeper->period) {
-		pwm_config(beeper->pwm, beeper->period / 2, beeper->period);
-		pwm_enable(beeper->pwm);
-	}
+	if (beeper->period)
+		__pwm_beeper_set(beeper);
 
 	return 0;
 }
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 5adbced..2bb4c86 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -893,9 +893,15 @@
 }
 
 #ifdef CONFIG_COMPAT
+
+#define UI_SET_PHYS_COMPAT	_IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t)
+
 static long uinput_compat_ioctl(struct file *file,
 				unsigned int cmd, unsigned long arg)
 {
+	if (cmd == UI_SET_PHYS_COMPAT)
+		cmd = UI_SET_PHYS;
+
 	return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
 }
 #endif
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index 79c964c..6e7ff95 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -875,6 +875,10 @@
 	int ret, pipe, i;
 
 	interface = intf->cur_altsetting;
+
+	if (interface->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	endpoint = &interface->endpoint[0].desc;
 	if (!usb_endpoint_is_int_in(endpoint))
 		return -ENODEV;
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 2f58985..da5458d 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -4,7 +4,8 @@
  * Copyright (c) 2013 ELAN Microelectronics Corp.
  *
  * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
- * Version: 1.6.0
+ * Author: KT Liao <kt.liao@emc.com.tw>
+ * Version: 1.6.2
  *
  * Based on cyapa driver:
  * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
@@ -40,7 +41,7 @@
 #include "elan_i2c.h"
 
 #define DRIVER_NAME		"elan_i2c"
-#define ELAN_DRIVER_VERSION	"1.6.1"
+#define ELAN_DRIVER_VERSION	"1.6.2"
 #define ELAN_VENDOR_ID		0x04f3
 #define ETP_MAX_PRESSURE	255
 #define ETP_FWIDTH_REDUCE	90
@@ -199,9 +200,43 @@
 	return error;
 }
 
+static int elan_query_product(struct elan_tp_data *data)
+{
+	int error;
+
+	error = data->ops->get_product_id(data->client, &data->product_id);
+	if (error)
+		return error;
+
+	error = data->ops->get_sm_version(data->client, &data->ic_type,
+					  &data->sm_version);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+static int elan_check_ASUS_special_fw(struct elan_tp_data *data)
+{
+	if (data->ic_type == 0x0E) {
+		switch (data->product_id) {
+		case 0x05 ... 0x07:
+		case 0x09:
+		case 0x13:
+			return true;
+		}
+	} else if (data->ic_type == 0x08 && data->product_id == 0x26) {
+		/* ASUS EeeBook X205TA */
+		return true;
+	}
+
+	return false;
+}
+
 static int __elan_initialize(struct elan_tp_data *data)
 {
 	struct i2c_client *client = data->client;
+	bool woken_up = false;
 	int error;
 
 	error = data->ops->initialize(client);
@@ -210,6 +245,27 @@
 		return error;
 	}
 
+	error = elan_query_product(data);
+	if (error)
+		return error;
+
+	/*
+	 * Some ASUS devices were shipped with firmware that requires
+	 * touchpads to be woken up first, before attempting to switch
+	 * them into absolute reporting mode.
+	 */
+	if (elan_check_ASUS_special_fw(data)) {
+		error = data->ops->sleep_control(client, false);
+		if (error) {
+			dev_err(&client->dev,
+				"failed to wake device up: %d\n", error);
+			return error;
+		}
+
+		msleep(200);
+		woken_up = true;
+	}
+
 	data->mode |= ETP_ENABLE_ABS;
 	error = data->ops->set_mode(client, data->mode);
 	if (error) {
@@ -218,11 +274,13 @@
 		return error;
 	}
 
-	error = data->ops->sleep_control(client, false);
-	if (error) {
-		dev_err(&client->dev,
-			"failed to wake device up: %d\n", error);
-		return error;
+	if (!woken_up) {
+		error = data->ops->sleep_control(client, false);
+		if (error) {
+			dev_err(&client->dev,
+				"failed to wake device up: %d\n", error);
+			return error;
+		}
 	}
 
 	return 0;
@@ -248,10 +306,6 @@
 {
 	int error;
 
-	error = data->ops->get_product_id(data->client, &data->product_id);
-	if (error)
-		return error;
-
 	error = data->ops->get_version(data->client, false, &data->fw_version);
 	if (error)
 		return error;
@@ -261,11 +315,6 @@
 	if (error)
 		return error;
 
-	error = data->ops->get_sm_version(data->client, &data->ic_type,
-					  &data->sm_version);
-	if (error)
-		return error;
-
 	error = data->ops->get_version(data->client, true, &data->iap_version);
 	if (error)
 		return error;
@@ -1185,6 +1234,7 @@
 	{ "ELAN0000", 0 },
 	{ "ELAN0100", 0 },
 	{ "ELAN0600", 0 },
+	{ "ELAN0605", 0 },
 	{ "ELAN1000", 0 },
 	{ }
 };
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 78f93cf..6f4dc0f 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1122,7 +1122,10 @@
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
  * Fujitsu LIFEBOOK E544   0x470f00        d0, 12, 09      2 hw buttons
+ * Fujitsu LIFEBOOK E546   0x470f00        50, 12, 09      2 hw buttons
+ * Fujitsu LIFEBOOK E547   0x470f00        50, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E554   0x570f01        40, 14, 0c      2 hw buttons
+ * Fujitsu LIFEBOOK E557   0x570f01        40, 14, 0c      2 hw buttons
  * Fujitsu T725            0x470f01        05, 12, 09      2 hw buttons
  * Fujitsu H730            0x570f00        c0, 14, 0c      3 hw buttons (**)
  * Gigabyte U2442          0x450f01        58, 17, 0c      2 hw buttons
@@ -1163,6 +1166,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"),
 		},
 	},
+	{
+		/* Fujitsu H760 also has a middle button */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"),
+		},
+	},
 #endif
 	{ }
 };
@@ -1507,10 +1517,10 @@
 		},
 	},
 	{
-		/* Fujitsu LIFEBOOK E554  does not work with crc_enabled == 0 */
+		/* Fujitsu H760 does not work with crc_enabled == 0 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E554"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"),
 		},
 	},
 	{
@@ -1521,6 +1531,41 @@
 		},
 	},
 	{
+		/* Fujitsu LIFEBOOK E546  does not work with crc_enabled == 0 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E546"),
+		},
+	},
+	{
+		/* Fujitsu LIFEBOOK E547 does not work with crc_enabled == 0 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E547"),
+		},
+	},
+	{
+		/* Fujitsu LIFEBOOK E554  does not work with crc_enabled == 0 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E554"),
+		},
+	},
+	{
+		/* Fujitsu LIFEBOOK E556 does not work with crc_enabled == 0 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E556"),
+		},
+	},
+	{
+		/* Fujitsu LIFEBOOK E557 does not work with crc_enabled == 0 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E557"),
+		},
+	},
+	{
 		/* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
@@ -1568,13 +1613,7 @@
 		case 5:
 			etd->hw_version = 3;
 			break;
-		case 6:
-		case 7:
-		case 8:
-		case 9:
-		case 10:
-		case 13:
-		case 14:
+		case 6 ... 14:
 			etd->hw_version = 4;
 			break;
 		default:
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
index a3f0f5a..0f58678 100644
--- a/drivers/input/mouse/vmmouse.c
+++ b/drivers/input/mouse/vmmouse.c
@@ -355,18 +355,11 @@
 		return -ENXIO;
 	}
 
-	if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) {
-		psmouse_dbg(psmouse, "VMMouse port in use.\n");
-		return -EBUSY;
-	}
-
 	/* Check if the device is present */
 	response = ~VMMOUSE_PROTO_MAGIC;
 	VMMOUSE_CMD(GETVERSION, 0, version, response, dummy1, dummy2);
-	if (response != VMMOUSE_PROTO_MAGIC || version == 0xffffffffU) {
-		release_region(VMMOUSE_PROTO_PORT, 4);
+	if (response != VMMOUSE_PROTO_MAGIC || version == 0xffffffffU)
 		return -ENXIO;
-	}
 
 	if (set_properties) {
 		psmouse->vendor = VMMOUSE_VENDOR;
@@ -374,8 +367,6 @@
 		psmouse->model = version;
 	}
 
-	release_region(VMMOUSE_PROTO_PORT, 4);
-
 	return 0;
 }
 
@@ -394,7 +385,6 @@
 	psmouse_reset(psmouse);
 	input_unregister_device(priv->abs_dev);
 	kfree(priv);
-	release_region(VMMOUSE_PROTO_PORT, 4);
 }
 
 /**
@@ -438,15 +428,10 @@
 	struct input_dev *rel_dev = psmouse->dev, *abs_dev;
 	int error;
 
-	if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) {
-		psmouse_dbg(psmouse, "VMMouse port in use.\n");
-		return -EBUSY;
-	}
-
 	psmouse_reset(psmouse);
 	error = vmmouse_enable(psmouse);
 	if (error)
-		goto release_region;
+		return error;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	abs_dev = input_allocate_device();
@@ -502,8 +487,5 @@
 	kfree(priv);
 	psmouse->private = NULL;
 
-release_region:
-	release_region(VMMOUSE_PROTO_PORT, 4);
-
 	return error;
 }
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index a5eed2a..34da81c 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -81,7 +81,7 @@
 		return -EBUSY;
 #endif
 
-	i8042_reset = 1;
+	i8042_reset = I8042_RESET_ALWAYS;
 	return 0;
 }
 
diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h
index ee1ad27..08a1c10 100644
--- a/drivers/input/serio/i8042-ip22io.h
+++ b/drivers/input/serio/i8042-ip22io.h
@@ -61,7 +61,7 @@
 		return -EBUSY;
 #endif
 
-	i8042_reset = 1;
+	i8042_reset = I8042_RESET_ALWAYS;
 
 	return 0;
 }
diff --git a/drivers/input/serio/i8042-ppcio.h b/drivers/input/serio/i8042-ppcio.h
index f708c75..1aabea4 100644
--- a/drivers/input/serio/i8042-ppcio.h
+++ b/drivers/input/serio/i8042-ppcio.h
@@ -44,7 +44,7 @@
 
 static inline int i8042_platform_init(void)
 {
-	i8042_reset = 1;
+	i8042_reset = I8042_RESET_ALWAYS;
 	return 0;
 }
 
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index afcd1c1..6231d63 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -130,7 +130,7 @@
 		}
 	}
 
-	i8042_reset = 1;
+	i8042_reset = I8042_RESET_ALWAYS;
 
 	return 0;
 }
diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h
index 73f5cc1..4557475 100644
--- a/drivers/input/serio/i8042-unicore32io.h
+++ b/drivers/input/serio/i8042-unicore32io.h
@@ -61,7 +61,7 @@
 	if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042"))
 		return -EBUSY;
 
-	i8042_reset = 1;
+	i8042_reset = I8042_RESET_ALWAYS;
 	return 0;
 }
 
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 68f5f4a..5be14ad 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -120,6 +120,13 @@
 		},
 	},
 	{
+		/* Dell Embedded Box PC 3000 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Embedded Box PC 3000"),
+		},
+	},
+	{
 		/* OQO Model 01 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
@@ -211,6 +218,12 @@
 			DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
 		},
 	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
+		},
+	},
 	{ }
 };
 
@@ -510,6 +523,90 @@
 	{ }
 };
 
+/*
+ * On some Asus laptops, just running self tests cause problems.
+ */
+static const struct dmi_system_id i8042_dmi_noselftest_table[] = {
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "A455LD"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "K401LB"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "K501LB"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "K501LX"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "R409L"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "V502LX"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X302LA"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X450LD"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X455LAB"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X455LDB"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X455LF"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Z450LA"),
+		},
+	},
+	{ }
+};
 static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
 	{
 		/* MSI Wind U-100 */
@@ -588,6 +685,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
 		},
 	},
+	{
+		/* Clevo P650RS, 650RP6, Sager NP8152-S, and others */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"),
+		},
+	},
 	{ }
 };
 
@@ -684,6 +788,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
 		},
 	},
+	{
+		/* Fujitsu UH554 laptop */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"),
+		},
+	},
 	{ }
 };
 
@@ -793,6 +904,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
 		},
 	},
+	{
+		/* Schenker XMG C504 - Elantech touchpad */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "XMG"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "C504"),
+		},
+	},
 	{ }
 };
 
@@ -1072,12 +1190,18 @@
 		return retval;
 
 #if defined(__ia64__)
-        i8042_reset = true;
+        i8042_reset = I8042_RESET_ALWAYS;
 #endif
 
 #ifdef CONFIG_X86
-	if (dmi_check_system(i8042_dmi_reset_table))
-		i8042_reset = true;
+	/* Honor module parameter when value is not default */
+	if (i8042_reset == I8042_RESET_DEFAULT) {
+		if (dmi_check_system(i8042_dmi_reset_table))
+			i8042_reset = I8042_RESET_ALWAYS;
+
+		if (dmi_check_system(i8042_dmi_noselftest_table))
+			i8042_reset = I8042_RESET_NEVER;
+	}
 
 	if (dmi_check_system(i8042_dmi_noloop_table))
 		i8042_noloop = true;
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 4541957..89abfdb 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -48,9 +48,39 @@
 module_param_named(unlock, i8042_unlock, bool, 0);
 MODULE_PARM_DESC(unlock, "Ignore keyboard lock.");
 
-static bool i8042_reset;
-module_param_named(reset, i8042_reset, bool, 0);
-MODULE_PARM_DESC(reset, "Reset controller during init and cleanup.");
+enum i8042_controller_reset_mode {
+	I8042_RESET_NEVER,
+	I8042_RESET_ALWAYS,
+	I8042_RESET_ON_S2RAM,
+#define I8042_RESET_DEFAULT	I8042_RESET_ON_S2RAM
+};
+static enum i8042_controller_reset_mode i8042_reset = I8042_RESET_DEFAULT;
+static int i8042_set_reset(const char *val, const struct kernel_param *kp)
+{
+	enum i8042_controller_reset_mode *arg = kp->arg;
+	int error;
+	bool reset;
+
+	if (val) {
+		error = kstrtobool(val, &reset);
+		if (error)
+			return error;
+	} else {
+		reset = true;
+	}
+
+	*arg = reset ? I8042_RESET_ALWAYS : I8042_RESET_NEVER;
+	return 0;
+}
+
+static const struct kernel_param_ops param_ops_reset_param = {
+	.flags = KERNEL_PARAM_OPS_FL_NOARG,
+	.set = i8042_set_reset,
+};
+#define param_check_reset_param(name, p)	\
+	__param_check(name, p, enum i8042_controller_reset_mode)
+module_param_named(reset, i8042_reset, reset_param, 0);
+MODULE_PARM_DESC(reset, "Reset controller on resume, cleanup or both");
 
 static bool i8042_direct;
 module_param_named(direct, i8042_direct, bool, 0);
@@ -1019,7 +1049,7 @@
  * Reset the controller and reset CRT to the original value set by BIOS.
  */
 
-static void i8042_controller_reset(bool force_reset)
+static void i8042_controller_reset(bool s2r_wants_reset)
 {
 	i8042_flush();
 
@@ -1044,8 +1074,10 @@
  * Reset the controller if requested.
  */
 
-	if (i8042_reset || force_reset)
+	if (i8042_reset == I8042_RESET_ALWAYS ||
+	    (i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) {
 		i8042_controller_selftest();
+	}
 
 /*
  * Restore the original control register setting.
@@ -1110,7 +1142,7 @@
  * before suspending.
  */
 
-static int i8042_controller_resume(bool force_reset)
+static int i8042_controller_resume(bool s2r_wants_reset)
 {
 	int error;
 
@@ -1118,7 +1150,8 @@
 	if (error)
 		return error;
 
-	if (i8042_reset || force_reset) {
+	if (i8042_reset == I8042_RESET_ALWAYS ||
+	    (i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) {
 		error = i8042_controller_selftest();
 		if (error)
 			return error;
@@ -1195,7 +1228,7 @@
 
 static int i8042_pm_resume(struct device *dev)
 {
-	bool force_reset;
+	bool want_reset;
 	int i;
 
 	for (i = 0; i < I8042_NUM_PORTS; i++) {
@@ -1218,9 +1251,9 @@
 	 * off control to the platform firmware, otherwise we can simply restore
 	 * the mode.
 	 */
-	force_reset = pm_resume_via_firmware();
+	want_reset = pm_resume_via_firmware();
 
-	return i8042_controller_resume(force_reset);
+	return i8042_controller_resume(want_reset);
 }
 
 static int i8042_pm_thaw(struct device *dev)
@@ -1277,6 +1310,7 @@
 	serio->start		= i8042_start;
 	serio->stop		= i8042_stop;
 	serio->close		= i8042_port_close;
+	serio->ps2_cmd_mutex	= &i8042_mutex;
 	serio->port_data	= port;
 	serio->dev.parent	= &i8042_platform_device->dev;
 	strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
@@ -1304,6 +1338,7 @@
 	serio->write		= i8042_aux_write;
 	serio->start		= i8042_start;
 	serio->stop		= i8042_stop;
+	serio->ps2_cmd_mutex	= &i8042_mutex;
 	serio->port_data	= port;
 	serio->dev.parent	= &i8042_platform_device->dev;
 	if (idx < 0) {
@@ -1373,21 +1408,6 @@
 	}
 }
 
-/*
- * Checks whether port belongs to i8042 controller.
- */
-bool i8042_check_port_owner(const struct serio *port)
-{
-	int i;
-
-	for (i = 0; i < I8042_NUM_PORTS; i++)
-		if (i8042_ports[i].serio == port)
-			return true;
-
-	return false;
-}
-EXPORT_SYMBOL(i8042_check_port_owner);
-
 static void i8042_free_irqs(void)
 {
 	if (i8042_aux_irq_registered)
@@ -1495,7 +1515,7 @@
 
 	i8042_platform_device = dev;
 
-	if (i8042_reset) {
+	if (i8042_reset == I8042_RESET_ALWAYS) {
 		error = i8042_controller_selftest();
 		if (error)
 			return error;
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 316f2c8..83e9c66 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -56,19 +56,17 @@
 
 void ps2_begin_command(struct ps2dev *ps2dev)
 {
-	mutex_lock(&ps2dev->cmd_mutex);
+	struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
 
-	if (i8042_check_port_owner(ps2dev->serio))
-		i8042_lock_chip();
+	mutex_lock(m);
 }
 EXPORT_SYMBOL(ps2_begin_command);
 
 void ps2_end_command(struct ps2dev *ps2dev)
 {
-	if (i8042_check_port_owner(ps2dev->serio))
-		i8042_unlock_chip();
+	struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
 
-	mutex_unlock(&ps2dev->cmd_mutex);
+	mutex_unlock(m);
 }
 EXPORT_SYMBOL(ps2_end_command);
 
diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c
index cd85205..df4bea9 100644
--- a/drivers/input/tablet/hanwang.c
+++ b/drivers/input/tablet/hanwang.c
@@ -340,6 +340,9 @@
 	int error;
 	int i;
 
+	if (intf->cur_altsetting->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	hanwang = kzalloc(sizeof(struct hanwang), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!hanwang || !input_dev) {
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c
index d2ac7c2..2812f92 100644
--- a/drivers/input/tablet/kbtab.c
+++ b/drivers/input/tablet/kbtab.c
@@ -122,6 +122,9 @@
 	struct input_dev *input_dev;
 	int error = -ENOMEM;
 
+	if (intf->cur_altsetting->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!kbtab || !input_dev)
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index ac09855..486f8fe 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -905,9 +905,9 @@
 
 		case QUEUE_HEADER_NORMAL:
 			report_count = ts->buf[FW_HDR_COUNT];
-			if (report_count > 3) {
+			if (report_count == 0 || report_count > 3) {
 				dev_err(&client->dev,
-					"too large report count: %*ph\n",
+					"bad report count: %*ph\n",
 					HEADER_SIZE, ts->buf);
 				break;
 			}
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index d214f22..0146e2c 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -126,7 +126,7 @@
 #define VIDEO_PACKET_SIZE  16384
 
 /* polling interval (ms) */
-#define POLL_INTERVAL 4
+#define POLL_INTERVAL 1
 
 /* maximum number of contacts FIXME: this is a guess? */
 #define MAX_CONTACTS 64
@@ -441,7 +441,7 @@
 
 	/* return error if streaming was stopped in the meantime */
 	if (sur40->sequence == -1)
-		goto err_poll;
+		return;
 
 	/* mark as finished */
 	v4l2_get_timestamp(&new_buf->vb.timestamp);
@@ -500,6 +500,9 @@
 	if (iface_desc->desc.bInterfaceClass != 0xFF)
 		return -ENODEV;
 
+	if (iface_desc->desc.bNumEndpoints < 5)
+		return -ENODEV;
+
 	/* Use endpoint #4 (0x86). */
 	endpoint = &iface_desc->endpoint[4].desc;
 	if (endpoint->bEndpointAddress != TOUCH_ENDPOINT)
@@ -730,6 +733,7 @@
 static void sur40_stop_streaming(struct vb2_queue *vq)
 {
 	struct sur40_state *sur40 = vb2_get_drv_priv(vq);
+	vb2_wait_for_all_buffers(vq);
 	sur40->sequence = -1;
 
 	/* Release all active buffers */
diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c
index 7295c19..6fe55d5 100644
--- a/drivers/input/touchscreen/tsc2004.c
+++ b/drivers/input/touchscreen/tsc2004.c
@@ -22,6 +22,11 @@
 #include <linux/regmap.h>
 #include "tsc200x-core.h"
 
+static const struct input_id tsc2004_input_id = {
+	.bustype = BUS_I2C,
+	.product = 2004,
+};
+
 static int tsc2004_cmd(struct device *dev, u8 cmd)
 {
 	u8 tx = TSC200X_CMD | TSC200X_CMD_12BIT | cmd;
@@ -42,7 +47,7 @@
 			 const struct i2c_device_id *id)
 
 {
-	return tsc200x_probe(&i2c->dev, i2c->irq, BUS_I2C,
+	return tsc200x_probe(&i2c->dev, i2c->irq, &tsc2004_input_id,
 			     devm_regmap_init_i2c(i2c, &tsc200x_regmap_config),
 			     tsc2004_cmd);
 }
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
index b9f593d..f2c5f0e 100644
--- a/drivers/input/touchscreen/tsc2005.c
+++ b/drivers/input/touchscreen/tsc2005.c
@@ -24,6 +24,11 @@
 #include <linux/regmap.h>
 #include "tsc200x-core.h"
 
+static const struct input_id tsc2005_input_id = {
+	.bustype = BUS_SPI,
+	.product = 2005,
+};
+
 static int tsc2005_cmd(struct device *dev, u8 cmd)
 {
 	u8 tx = TSC200X_CMD | TSC200X_CMD_12BIT | cmd;
@@ -62,7 +67,7 @@
 	if (error)
 		return error;
 
-	return tsc200x_probe(&spi->dev, spi->irq, BUS_SPI,
+	return tsc200x_probe(&spi->dev, spi->irq, &tsc2005_input_id,
 			     devm_regmap_init_spi(spi, &tsc200x_regmap_config),
 			     tsc2005_cmd);
 }
diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c
index 15240c1..dfa7f1c 100644
--- a/drivers/input/touchscreen/tsc200x-core.c
+++ b/drivers/input/touchscreen/tsc200x-core.c
@@ -450,7 +450,7 @@
 	mutex_unlock(&ts->mutex);
 }
 
-int tsc200x_probe(struct device *dev, int irq, __u16 bustype,
+int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
 		  struct regmap *regmap,
 		  int (*tsc200x_cmd)(struct device *dev, u8 cmd))
 {
@@ -547,9 +547,18 @@
 	snprintf(ts->phys, sizeof(ts->phys),
 		 "%s/input-ts", dev_name(dev));
 
-	input_dev->name = "TSC200X touchscreen";
+	if (tsc_id->product == 2004) {
+		input_dev->name = "TSC200X touchscreen";
+	} else {
+		input_dev->name = devm_kasprintf(dev, GFP_KERNEL,
+						 "TSC%04d touchscreen",
+						 tsc_id->product);
+		if (!input_dev->name)
+			return -ENOMEM;
+	}
+
 	input_dev->phys = ts->phys;
-	input_dev->id.bustype = bustype;
+	input_dev->id = *tsc_id;
 	input_dev->dev.parent = dev;
 	input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
diff --git a/drivers/input/touchscreen/tsc200x-core.h b/drivers/input/touchscreen/tsc200x-core.h
index 7a482d1..49a63a3 100644
--- a/drivers/input/touchscreen/tsc200x-core.h
+++ b/drivers/input/touchscreen/tsc200x-core.h
@@ -70,7 +70,7 @@
 extern const struct regmap_config tsc200x_regmap_config;
 extern const struct dev_pm_ops tsc200x_pm_ops;
 
-int tsc200x_probe(struct device *dev, int irq, __u16 bustype,
+int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
 		  struct regmap *regmap,
 		  int (*tsc200x_cmd)(struct device *dev, u8 cmd));
 int tsc200x_remove(struct device *dev);
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 2792ca3..3ed0ce1 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -27,7 +27,7 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-#define W8001_MAX_LENGTH	11
+#define W8001_MAX_LENGTH	13
 #define W8001_LEAD_MASK		0x80
 #define W8001_LEAD_BYTE		0x80
 #define W8001_TAB_MASK		0x40
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index b9319b7..a0ef574 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -352,9 +352,11 @@
 	if (!domain)
 		goto out;
 
-	dma_domain = to_pdomain(domain)->priv;
+	if (to_pdomain(domain)->flags == PD_DMA_OPS_MASK) {
+		dma_domain = to_pdomain(domain)->priv;
+		init_unity_mappings_for_device(dev, dma_domain);
+	}
 
-	init_unity_mappings_for_device(dev, dma_domain);
 out:
 	iommu_group_put(group);
 }
@@ -924,7 +926,7 @@
 	next_tail = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
 	left      = (head - next_tail) % CMD_BUFFER_SIZE;
 
-	if (left <= 2) {
+	if (left <= 0x20) {
 		struct iommu_cmd sync_cmd;
 		volatile u64 sem = 0;
 		int ret;
@@ -1831,6 +1833,9 @@
 		kfree(dom->aperture[i]);
 	}
 
+	if (dom->domain.id)
+		domain_id_free(dom->domain.id);
+
 	kfree(dom);
 }
 
@@ -2322,8 +2327,15 @@
 {
 	struct iommu_dev_data *dev_data;
 
-	list_for_each_entry(dev_data, &domain->dev_list, list)
+	list_for_each_entry(dev_data, &domain->dev_list, list) {
 		set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
+
+		if (dev_data->devid == dev_data->alias)
+			continue;
+
+		/* There is an alias, update device table entry for it */
+		set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled);
+	}
 }
 
 static void update_domain(struct protection_domain *domain)
@@ -2970,9 +2982,7 @@
 static void amd_iommu_domain_free(struct iommu_domain *dom)
 {
 	struct protection_domain *domain;
-
-	if (!dom)
-		return;
+	struct dma_ops_domain *dma_dom;
 
 	domain = to_pdomain(dom);
 
@@ -2981,13 +2991,24 @@
 
 	BUG_ON(domain->dev_cnt != 0);
 
-	if (domain->mode != PAGE_MODE_NONE)
-		free_pagetable(domain);
+	if (!dom)
+		return;
 
-	if (domain->flags & PD_IOMMUV2_MASK)
-		free_gcr3_table(domain);
+	switch (dom->type) {
+	case IOMMU_DOMAIN_DMA:
+		dma_dom = domain->priv;
+		dma_ops_domain_free(dma_dom);
+		break;
+	default:
+		if (domain->mode != PAGE_MODE_NONE)
+			free_pagetable(domain);
 
-	protection_domain_free(domain);
+		if (domain->flags & PD_IOMMUV2_MASK)
+			free_gcr3_table(domain);
+
+		protection_domain_free(domain);
+		break;
+	}
 }
 
 static void amd_iommu_detach_device(struct iommu_domain *dom,
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index bf4959f..94f1bf7 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -1363,13 +1363,23 @@
 			break;
 	}
 
+	/*
+	 * Order is important here to make sure any unity map requirements are
+	 * fulfilled. The unity mappings are created and written to the device
+	 * table during the amd_iommu_init_api() call.
+	 *
+	 * After that we call init_device_table_dma() to make sure any
+	 * uninitialized DTE will block DMA, and in the end we flush the caches
+	 * of all IOMMUs to make sure the changes to the device table are
+	 * active.
+	 */
+	ret = amd_iommu_init_api();
+
 	init_device_table_dma();
 
 	for_each_iommu(iommu)
 		iommu_flush_all_caches(iommu);
 
-	ret = amd_iommu_init_api();
-
 	if (!ret)
 		print_iommu_info();
 
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 7caf2fa..22160e4 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -699,9 +699,9 @@
 
 out_unregister:
 	mmu_notifier_unregister(&pasid_state->mn, mm);
+	mmput(mm);
 
 out_free:
-	mmput(mm);
 	free_pasid_state(pasid_state);
 
 out:
@@ -809,8 +809,10 @@
 		goto out_free_domain;
 
 	group = iommu_group_get(&pdev->dev);
-	if (!group)
+	if (!group) {
+		ret = -EINVAL;
 		goto out_free_domain;
+	}
 
 	ret = iommu_attach_group(dev_state->domain, group);
 	if (ret != 0)
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4e5118a..00df383 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -870,7 +870,7 @@
 	 * We may have concurrent producers, so we need to be careful
 	 * not to touch any of the shadow cmdq state.
 	 */
-	queue_read(cmd, Q_ENT(q, idx), q->ent_dwords);
+	queue_read(cmd, Q_ENT(q, cons), q->ent_dwords);
 	dev_err(smmu->dev, "skipping command in error state:\n");
 	for (i = 0; i < ARRAY_SIZE(cmd); ++i)
 		dev_err(smmu->dev, "\t0x%016llx\n", (unsigned long long)cmd[i]);
@@ -881,7 +881,7 @@
 		return;
 	}
 
-	queue_write(cmd, Q_ENT(q, idx), q->ent_dwords);
+	queue_write(Q_ENT(q, cons), cmd, q->ent_dwords);
 }
 
 static void arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
@@ -1025,6 +1025,9 @@
 		case STRTAB_STE_0_CFG_S2_TRANS:
 			ste_live = true;
 			break;
+		case STRTAB_STE_0_CFG_ABORT:
+			if (disable_bypass)
+				break;
 		default:
 			BUG(); /* STE corruption */
 		}
@@ -1919,6 +1922,7 @@
 	.detach_dev		= arm_smmu_detach_dev,
 	.map			= arm_smmu_map,
 	.unmap			= arm_smmu_unmap,
+	.map_sg			= default_iommu_map_sg,
 	.iova_to_phys		= arm_smmu_iova_to_phys,
 	.add_device		= arm_smmu_add_device,
 	.remove_device		= arm_smmu_remove_device,
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 58f2fe6..347a3c1 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -68,7 +68,8 @@
 	if (!iovad)
 		return;
 
-	put_iova_domain(iovad);
+	if (iovad->granule)
+		put_iova_domain(iovad);
 	kfree(iovad);
 	domain->iova_cookie = NULL;
 }
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 3821c47..e913a93 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -326,7 +326,9 @@
 	struct pci_dev *pdev = to_pci_dev(data);
 	struct dmar_pci_notify_info *info;
 
-	/* Only care about add/remove events for physical functions */
+	/* Only care about add/remove events for physical functions.
+	 * For VFs we actually do the lookup based on the corresponding
+	 * PF in device_to_iommu() anyway. */
 	if (pdev->is_virtfn)
 		return NOTIFY_DONE;
 	if (action != BUS_NOTIFY_ADD_DEVICE &&
@@ -1858,10 +1860,11 @@
 	/*
 	 * All PCI devices managed by this unit should have been destroyed.
 	 */
-	if (!dmaru->include_all && dmaru->devices && dmaru->devices_cnt)
+	if (!dmaru->include_all && dmaru->devices && dmaru->devices_cnt) {
 		for_each_active_dev_scope(dmaru->devices,
 					  dmaru->devices_cnt, i, dev)
 			return -EBUSY;
+	}
 
 	ret = dmar_ir_hotplug(dmaru, false);
 	if (ret == 0)
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 97c41b8..29a31eb 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -647,6 +647,7 @@
 		.name		= "exynos-sysmmu",
 		.of_match_table	= sysmmu_of_match,
 		.pm		= &sysmmu_pm_ops,
+		.suppress_bind_attrs = true,
 	}
 };
 
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index a2e1b7f..f9711ac 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -885,7 +885,13 @@
 		return NULL;
 
 	if (dev_is_pci(dev)) {
+		struct pci_dev *pf_pdev;
+
 		pdev = to_pci_dev(dev);
+		/* VFs aren't listed in scope tables; we need to look up
+		 * the PF instead to find the IOMMU. */
+		pf_pdev = pci_physfn(pdev);
+		dev = &pf_pdev->dev;
 		segment = pci_domain_nr(pdev->bus);
 	} else if (has_acpi_companion(dev))
 		dev = &ACPI_COMPANION(dev)->dev;
@@ -898,6 +904,13 @@
 		for_each_active_dev_scope(drhd->devices,
 					  drhd->devices_cnt, i, tmp) {
 			if (tmp == dev) {
+				/* For a VF use its original BDF# not that of the PF
+				 * which we used for the IOMMU lookup. Strictly speaking
+				 * we could do this for all PCI devices; we only need to
+				 * get the BDF# from the scope table for ACPI matches. */
+				if (pdev && pdev->is_virtfn)
+					goto got_pdev;
+
 				*bus = drhd->devices[i].bus;
 				*devfn = drhd->devices[i].devfn;
 				goto out;
@@ -1124,7 +1137,7 @@
 		if (!dma_pte_present(pte) || dma_pte_superpage(pte))
 			goto next;
 
-		level_pfn = pfn & level_mask(level - 1);
+		level_pfn = pfn & level_mask(level);
 		level_pte = phys_to_virt(dma_pte_addr(pte));
 
 		if (level > 2)
@@ -1672,6 +1685,7 @@
 	if (!iommu->domains || !iommu->domain_ids)
 		return;
 
+again:
 	spin_lock_irqsave(&device_domain_lock, flags);
 	list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
 		struct dmar_domain *domain;
@@ -1684,10 +1698,19 @@
 
 		domain = info->domain;
 
-		dmar_remove_one_dev_info(domain, info->dev);
+		__dmar_remove_one_dev_info(info);
 
-		if (!domain_type_is_vm_or_si(domain))
+		if (!domain_type_is_vm_or_si(domain)) {
+			/*
+			 * The domain_exit() function  can't be called under
+			 * device_domain_lock, as it takes this lock itself.
+			 * So release the lock here and re-run the loop
+			 * afterwards.
+			 */
+			spin_unlock_irqrestore(&device_domain_lock, flags);
 			domain_exit(domain);
+			goto again;
+		}
 	}
 	spin_unlock_irqrestore(&device_domain_lock, flags);
 
@@ -1970,6 +1993,28 @@
 	if (context_present(context))
 		goto out_unlock;
 
+	/*
+	 * For kdump cases, old valid entries may be cached due to the
+	 * in-flight DMA and copied pgtable, but there is no unmapping
+	 * behaviour for them, thus we need an explicit cache flush for
+	 * the newly-mapped device. For kdump, at this point, the device
+	 * is supposed to finish reset at its driver probe stage, so no
+	 * in-flight DMA will exist, and we don't need to worry anymore
+	 * hereafter.
+	 */
+	if (context_copied(context)) {
+		u16 did_old = context_domain_id(context);
+
+		if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) {
+			iommu->flush.flush_context(iommu, did_old,
+						   (((u16)bus) << 8) | devfn,
+						   DMA_CCMD_MASK_NOBIT,
+						   DMA_CCMD_DEVICE_INVL);
+			iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
+						 DMA_TLB_DSI_FLUSH);
+		}
+	}
+
 	pgd = domain->pgd;
 
 	context_clear_entry(context);
@@ -2032,7 +2077,7 @@
 	spin_unlock(&iommu->lock);
 	spin_unlock_irqrestore(&device_domain_lock, flags);
 
-	return 0;
+	return ret;
 }
 
 struct domain_context_mapping_data {
@@ -3169,11 +3214,6 @@
 			}
 		}
 
-		iommu_flush_write_buffer(iommu);
-		iommu_set_root_entry(iommu);
-		iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
-		iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
-
 		if (!ecap_pass_through(iommu->ecap))
 			hw_pass_through = 0;
 #ifdef CONFIG_INTEL_IOMMU_SVM
@@ -3182,6 +3222,18 @@
 #endif
 	}
 
+	/*
+	 * Now that qi is enabled on all iommus, set the root entry and flush
+	 * caches. This is required on some Intel X58 chipsets, otherwise the
+	 * flush_context function will loop forever and the boot hangs.
+	 */
+	for_each_active_iommu(iommu, drhd) {
+		iommu_flush_write_buffer(iommu);
+		iommu_set_root_entry(iommu);
+		iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
+		iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
+	}
+
 	if (iommu_pass_through)
 		iommu_identity_mapping |= IDENTMAP_ALL;
 
@@ -3189,13 +3241,14 @@
 	iommu_identity_mapping |= IDENTMAP_GFX;
 #endif
 
+	check_tylersburg_isoch();
+
 	if (iommu_identity_mapping) {
 		ret = si_domain_init(hw_pass_through);
 		if (ret)
 			goto free_iommu;
 	}
 
-	check_tylersburg_isoch();
 
 	/*
 	 * If we copied translations from a previous kernel in the kdump
@@ -4175,10 +4228,11 @@
 	if (!atsru)
 		return 0;
 
-	if (!atsru->include_all && atsru->devices && atsru->devices_cnt)
+	if (!atsru->include_all && atsru->devices && atsru->devices_cnt) {
 		for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
 					  i, dev)
 			return -EBUSY;
+	}
 
 	return 0;
 }
@@ -4989,6 +5043,25 @@
 }
 
 #ifdef CONFIG_INTEL_IOMMU_SVM
+#define MAX_NR_PASID_BITS (20)
+static inline unsigned long intel_iommu_get_pts(struct intel_iommu *iommu)
+{
+	/*
+	 * Convert ecap_pss to extend context entry pts encoding, also
+	 * respect the soft pasid_max value set by the iommu.
+	 * - number of PASID bits = ecap_pss + 1
+	 * - number of PASID table entries = 2^(pts + 5)
+	 * Therefore, pts = ecap_pss - 4
+	 * e.g. KBL ecap_pss = 0x13, PASID has 20 bits, pts = 15
+	 */
+	if (ecap_pss(iommu->ecap) < 5)
+		return 0;
+
+	/* pasid_max is encoded as actual number of entries not the bits */
+	return find_first_bit((unsigned long *)&iommu->pasid_max,
+			MAX_NR_PASID_BITS) - 5;
+}
+
 int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
 {
 	struct device_domain_info *info;
@@ -5021,7 +5094,9 @@
 
 	if (!(ctx_lo & CONTEXT_PASIDE)) {
 		context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table);
-		context[1].lo = (u64)virt_to_phys(iommu->pasid_table) | ecap_pss(iommu->ecap);
+		context[1].lo = (u64)virt_to_phys(iommu->pasid_table) |
+			intel_iommu_get_pts(iommu);
+
 		wmb();
 		/* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both
 		 * extended to permit requests-with-PASID if the PASIDE bit
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index d9939fa..f929879 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -39,10 +39,18 @@
 	struct page *pages;
 	int order;
 
-	order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT;
-	if (order < 0)
-		order = 0;
+	/* Start at 2 because it's defined as 2^(1+PSS) */
+	iommu->pasid_max = 2 << ecap_pss(iommu->ecap);
 
+	/* Eventually I'm promised we will get a multi-level PASID table
+	 * and it won't have to be physically contiguous. Until then,
+	 * limit the size because 8MiB contiguous allocations can be hard
+	 * to come by. The limit of 0x20000, which is 1MiB for each of
+	 * the PASID and PASID-state tables, is somewhat arbitrary. */
+	if (iommu->pasid_max > 0x20000)
+		iommu->pasid_max = 0x20000;
+
+	order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max);
 	pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
 	if (!pages) {
 		pr_warn("IOMMU: %s: Failed to allocate PASID table\n",
@@ -53,6 +61,8 @@
 	pr_info("%s: Allocated order %d PASID table.\n", iommu->name, order);
 
 	if (ecap_dis(iommu->ecap)) {
+		/* Just making it explicit... */
+		BUILD_BUG_ON(sizeof(struct pasid_entry) != sizeof(struct pasid_state_entry));
 		pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
 		if (pages)
 			iommu->pasid_state_table = page_address(pages);
@@ -68,11 +78,7 @@
 
 int intel_svm_free_pasid_tables(struct intel_iommu *iommu)
 {
-	int order;
-
-	order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT;
-	if (order < 0)
-		order = 0;
+	int order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max);
 
 	if (iommu->pasid_table) {
 		free_pages((unsigned long)iommu->pasid_table, order);
@@ -371,8 +377,8 @@
 		}
 		svm->iommu = iommu;
 
-		if (pasid_max > 2 << ecap_pss(iommu->ecap))
-			pasid_max = 2 << ecap_pss(iommu->ecap);
+		if (pasid_max > iommu->pasid_max)
+			pasid_max = iommu->pasid_max;
 
 		/* Do not use PASID 0 in caching mode (virtualised IOMMU) */
 		ret = idr_alloc(&iommu->pasid_idr, svm,
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 515bb8b..a070fa3 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -391,36 +391,30 @@
 	device->dev = dev;
 
 	ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group");
-	if (ret) {
-		kfree(device);
-		return ret;
-	}
+	if (ret)
+		goto err_free_device;
 
 	device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj));
 rename:
 	if (!device->name) {
-		sysfs_remove_link(&dev->kobj, "iommu_group");
-		kfree(device);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_remove_link;
 	}
 
 	ret = sysfs_create_link_nowarn(group->devices_kobj,
 				       &dev->kobj, device->name);
 	if (ret) {
-		kfree(device->name);
 		if (ret == -EEXIST && i >= 0) {
 			/*
 			 * Account for the slim chance of collision
 			 * and append an instance to the name.
 			 */
+			kfree(device->name);
 			device->name = kasprintf(GFP_KERNEL, "%s.%d",
 						 kobject_name(&dev->kobj), i++);
 			goto rename;
 		}
-
-		sysfs_remove_link(&dev->kobj, "iommu_group");
-		kfree(device);
-		return ret;
+		goto err_free_name;
 	}
 
 	kobject_get(group->devices_kobj);
@@ -432,8 +426,10 @@
 	mutex_lock(&group->mutex);
 	list_add_tail(&device->list, &group->devices);
 	if (group->domain)
-		__iommu_attach_device(group->domain, dev);
+		ret = __iommu_attach_device(group->domain, dev);
 	mutex_unlock(&group->mutex);
+	if (ret)
+		goto err_put_group;
 
 	/* Notify any listeners about change to group. */
 	blocking_notifier_call_chain(&group->notifier,
@@ -444,6 +440,21 @@
 	pr_info("Adding device %s to group %d\n", dev_name(dev), group->id);
 
 	return 0;
+
+err_put_group:
+	mutex_lock(&group->mutex);
+	list_del(&device->list);
+	mutex_unlock(&group->mutex);
+	dev->iommu_group = NULL;
+	kobject_put(group->devices_kobj);
+err_free_name:
+	kfree(device->name);
+err_remove_link:
+	sysfs_remove_link(&dev->kobj, "iommu_group");
+err_free_device:
+	kfree(device);
+	pr_err("Failed to add device %s to group %d: %d\n", dev_name(dev), group->id, ret);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(iommu_group_add_device);
 
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index 8a0c7f2..981c395 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -176,6 +176,7 @@
 {
 	struct irq_domain_chip_generic *dgc = d->gc;
 	struct irq_chip_generic *gc;
+	unsigned long flags;
 	unsigned smr;
 	int idx;
 	int ret;
@@ -194,12 +195,12 @@
 
 	gc = dgc->gc[idx];
 
-	irq_gc_lock(gc);
+	irq_gc_lock_irqsave(gc, flags);
 	smr = irq_reg_readl(gc, AT91_AIC_SMR(*out_hwirq));
 	ret = aic_common_set_priority(intspec[2], &smr);
 	if (!ret)
 		irq_reg_writel(gc, smr, AT91_AIC_SMR(*out_hwirq));
-	irq_gc_unlock(gc);
+	irq_gc_unlock_irqrestore(gc, flags);
 
 	return ret;
 }
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
index 62bb840..7dee71b 100644
--- a/drivers/irqchip/irq-atmel-aic5.c
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -258,6 +258,7 @@
 				 unsigned int *out_type)
 {
 	struct irq_chip_generic *bgc = irq_get_domain_generic_chip(d, 0);
+	unsigned long flags;
 	unsigned smr;
 	int ret;
 
@@ -269,13 +270,13 @@
 	if (ret)
 		return ret;
 
-	irq_gc_lock(bgc);
+	irq_gc_lock_irqsave(bgc, flags);
 	irq_reg_writel(bgc, *out_hwirq, AT91_AIC5_SSR);
 	smr = irq_reg_readl(bgc, AT91_AIC5_SMR);
 	ret = aic_common_set_priority(intspec[2], &smr);
 	if (!ret)
 		irq_reg_writel(bgc, intspec[2] | smr, AT91_AIC5_SMR);
-	irq_gc_unlock(bgc);
+	irq_gc_unlock_irqrestore(bgc, flags);
 
 	return ret;
 }
diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c
index 0fea985..d7af885 100644
--- a/drivers/irqchip/irq-bcm7038-l1.c
+++ b/drivers/irqchip/irq-bcm7038-l1.c
@@ -216,6 +216,31 @@
 	return 0;
 }
 
+static void bcm7038_l1_cpu_offline(struct irq_data *d)
+{
+	struct cpumask *mask = irq_data_get_affinity_mask(d);
+	int cpu = smp_processor_id();
+	cpumask_t new_affinity;
+
+	/* This CPU was not on the affinity mask */
+	if (!cpumask_test_cpu(cpu, mask))
+		return;
+
+	if (cpumask_weight(mask) > 1) {
+		/*
+		 * Multiple CPU affinity, remove this CPU from the affinity
+		 * mask
+		 */
+		cpumask_copy(&new_affinity, mask);
+		cpumask_clear_cpu(cpu, &new_affinity);
+	} else {
+		/* Only CPU, put on the lowest online CPU */
+		cpumask_clear(&new_affinity);
+		cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
+	}
+	irq_set_affinity_locked(d, &new_affinity, false);
+}
+
 static int __init bcm7038_l1_init_one(struct device_node *dn,
 				      unsigned int idx,
 				      struct bcm7038_l1_chip *intc)
@@ -267,6 +292,7 @@
 	.irq_mask		= bcm7038_l1_mask,
 	.irq_unmask		= bcm7038_l1_unmask,
 	.irq_set_affinity	= bcm7038_l1_set_affinity,
+	.irq_cpu_offline	= bcm7038_l1_cpu_offline,
 };
 
 static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq,
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index a159529f..c5f1757 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -41,6 +41,7 @@
 
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING		(1ULL << 0)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_22375	(1ULL << 1)
+#define ITS_FLAGS_WORKAROUND_CAVIUM_23144	(1ULL << 2)
 
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING	(1 << 0)
 
@@ -71,6 +72,7 @@
 	struct list_head	its_device_list;
 	u64			flags;
 	u32			ite_size;
+	int			numa_node;
 };
 
 #define ITS_ITT_ALIGN		SZ_256
@@ -600,11 +602,23 @@
 static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 			    bool force)
 {
-	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
+	unsigned int cpu;
+	const struct cpumask *cpu_mask = cpu_online_mask;
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 	struct its_collection *target_col;
 	u32 id = its_get_event_id(d);
 
+       /* lpi cannot be routed to a redistributor that is on a foreign node */
+	if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
+		if (its_dev->its->numa_node >= 0) {
+			cpu_mask = cpumask_of_node(its_dev->its->numa_node);
+			if (!cpumask_intersects(mask_val, cpu_mask))
+				return -EINVAL;
+		}
+	}
+
+	cpu = cpumask_any_and(mask_val, cpu_mask);
+
 	if (cpu >= nr_cpu_ids)
 		return -EINVAL;
 
@@ -1081,6 +1095,16 @@
 	list_for_each_entry(its, &its_nodes, entry) {
 		u64 target;
 
+		/* avoid cross node collections and its mapping */
+		if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
+			struct device_node *cpu_node;
+
+			cpu_node = of_get_cpu_node(cpu, NULL);
+			if (its->numa_node != NUMA_NO_NODE &&
+				its->numa_node != of_node_to_nid(cpu_node))
+				continue;
+		}
+
 		/*
 		 * We now have to bind each collection to its target
 		 * redistributor.
@@ -1308,9 +1332,14 @@
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 	u32 event = its_get_event_id(d);
+	const struct cpumask *cpu_mask = cpu_online_mask;
+
+	/* get the cpu_mask of local node */
+	if (its_dev->its->numa_node >= 0)
+		cpu_mask = cpumask_of_node(its_dev->its->numa_node);
 
 	/* Bind the LPI to the first possible CPU */
-	its_dev->event_map.col_map[event] = cpumask_first(cpu_online_mask);
+	its_dev->event_map.col_map[event] = cpumask_first(cpu_mask);
 
 	/* Map the GIC IRQ and event to the device */
 	its_send_mapvi(its_dev, d->hwirq, event);
@@ -1400,6 +1429,13 @@
 	its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_22375;
 }
 
+static void __maybe_unused its_enable_quirk_cavium_23144(void *data)
+{
+	struct its_node *its = data;
+
+	its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_23144;
+}
+
 static const struct gic_quirk its_quirks[] = {
 #ifdef CONFIG_CAVIUM_ERRATUM_22375
 	{
@@ -1409,6 +1445,14 @@
 		.init	= its_enable_quirk_cavium_22375,
 	},
 #endif
+#ifdef CONFIG_CAVIUM_ERRATUM_23144
+	{
+		.desc	= "ITS: Cavium erratum 23144",
+		.iidr	= 0xa100034c,	/* ThunderX pass 1.x */
+		.mask	= 0xffff0fff,
+		.init	= its_enable_quirk_cavium_23144,
+	},
+#endif
 	{
 	}
 };
@@ -1470,6 +1514,7 @@
 	its->base = its_base;
 	its->phys_base = res.start;
 	its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
+	its->numa_node = of_node_to_nid(node);
 
 	its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
 	if (!its->cmd_base) {
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index d7be6dd..e33c729 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -142,7 +142,7 @@
 			return;	/* No PM support in this redistributor */
 	}
 
-	while (count--) {
+	while (--count) {
 		val = readl_relaxed(rbase + GICR_WAKER);
 		if (enable ^ (val & GICR_WAKER_ChildrenAsleep))
 			break;
@@ -361,6 +361,13 @@
 			if (static_key_true(&supports_deactivate))
 				gic_write_dir(irqnr);
 #ifdef CONFIG_SMP
+			/*
+			 * Unlike GICv2, we don't need an smp_rmb() here.
+			 * The control dependency from gic_read_iar to
+			 * the ISB in gic_write_eoir is enough to ensure
+			 * that any shared data read by handle_IPI will
+			 * be read after the ACK.
+			 */
 			handle_IPI(irqnr, regs);
 #else
 			WARN_ONCE(true, "Unexpected SGI received!\n");
@@ -380,6 +387,15 @@
 	writel_relaxed(0, base + GICD_CTLR);
 	gic_dist_wait_for_rwp();
 
+	/*
+	 * Configure SPIs as non-secure Group-1. This will only matter
+	 * if the GIC only has a single security state. This will not
+	 * do the right thing if the kernel is running in secure mode,
+	 * but that's not the intended use case anyway.
+	 */
+	for (i = 32; i < gic_data.irq_nr; i += 32)
+		writel_relaxed(~0, base + GICD_IGROUPR + i / 8);
+
 	gic_dist_config(base, gic_data.irq_nr, gic_dist_wait_for_rwp);
 
 	/* Enable distributor with ARE, Group1 */
@@ -494,6 +510,9 @@
 
 	rbase = gic_data_rdist_sgi_base();
 
+	/* Configure SGIs/PPIs as non-secure Group-1 */
+	writel_relaxed(~0, rbase + GICR_IGROUPR0);
+
 	gic_cpu_config(rbase, gic_redist_wait_for_rwp);
 
 	/* Give LPIs a spin */
@@ -525,7 +544,7 @@
 static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
 				   unsigned long cluster_id)
 {
-	int cpu = *base_cpu;
+	int next_cpu, cpu = *base_cpu;
 	unsigned long mpidr = cpu_logical_map(cpu);
 	u16 tlist = 0;
 
@@ -539,9 +558,10 @@
 
 		tlist |= 1 << (mpidr & 0xf);
 
-		cpu = cpumask_next(cpu, mask);
-		if (cpu >= nr_cpu_ids)
+		next_cpu = cpumask_next(cpu, mask);
+		if (next_cpu >= nr_cpu_ids)
 			goto out;
+		cpu = next_cpu;
 
 		mpidr = cpu_logical_map(cpu);
 
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index abf2ffa..cebd8ef 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -347,6 +347,14 @@
 			if (static_key_true(&supports_deactivate))
 				writel_relaxed(irqstat, cpu_base + GIC_CPU_DEACTIVATE);
 #ifdef CONFIG_SMP
+			/*
+			 * Ensure any shared data written by the CPU sending
+			 * the IPI is read after we've read the ACK register
+			 * on the GIC.
+			 *
+			 * Pairs with the write barrier in gic_raise_softirq
+			 */
+			smp_rmb();
 			handle_IPI(irqnr, regs);
 #endif
 			continue;
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index 15af9a9..2d203b4 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -230,6 +230,8 @@
 		return -ENOMEM;
 	}
 
+	raw_spin_lock_init(&cd->rlock);
+
 	cd->gpc_base = of_iomap(node, 0);
 	if (!cd->gpc_base) {
 		pr_err("fsl-gpcv2: unable to map gpc registers\n");
diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c
index bb3ac5f..72a391e 100644
--- a/drivers/irqchip/irq-xtensa-mx.c
+++ b/drivers/irqchip/irq-xtensa-mx.c
@@ -142,7 +142,7 @@
 int __init xtensa_mx_init_legacy(struct device_node *interrupt_parent)
 {
 	struct irq_domain *root_domain =
-		irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+		irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
 				&xtensa_mx_irq_domain_ops,
 				&xtensa_mx_irq_chip);
 	irq_set_default_host(root_domain);
diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c
index 472ae17..f728755 100644
--- a/drivers/irqchip/irq-xtensa-pic.c
+++ b/drivers/irqchip/irq-xtensa-pic.c
@@ -89,7 +89,7 @@
 int __init xtensa_pic_init_legacy(struct device_node *interrupt_parent)
 {
 	struct irq_domain *root_domain =
-		irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+		irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
 				&xtensa_irq_domain_ops, &xtensa_irq_chip);
 	irq_set_default_host(root_domain);
 	return 0;
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index aecec6d..7f1c625 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -2317,6 +2317,9 @@
 		return -ENODEV;
 	}
 
+	if (hostif->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	dev_info(&udev->dev,
 		 "%s: Device matched (Vendor: 0x%x, Product: 0x%x)\n",
 		 __func__, le16_to_cpu(udev->descriptor.idVendor),
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index 2a506fe..74bf1a1 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -762,8 +762,10 @@
 	driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
 				    GIGASET_MODULENAME, GIGASET_DEVNAME,
 				    &ops, THIS_MODULE);
-	if (!driver)
+	if (!driver) {
+		rc = -ENOMEM;
 		goto error;
+	}
 
 	rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc);
 	if (rc != 0) {
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
index d7c2866..7b4ddf0 100644
--- a/drivers/isdn/hardware/eicon/message.c
+++ b/drivers/isdn/hardware/eicon/message.c
@@ -11304,7 +11304,8 @@
 				((CAPI_MSG *) msg)->header.ncci = 0;
 				((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
 				((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
-				PUT_WORD(&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
+				((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
+				((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
 				((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
 				w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
 				if (w != _QUEUE_FULL)
diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c
index feca07b..1eb9fb3 100644
--- a/drivers/leds/leds-ktd2692.c
+++ b/drivers/leds/leds-ktd2692.c
@@ -296,15 +296,15 @@
 		return -ENXIO;
 
 	led->ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_ASIS);
-	if (IS_ERR(led->ctrl_gpio)) {
-		ret = PTR_ERR(led->ctrl_gpio);
+	ret = PTR_ERR_OR_ZERO(led->ctrl_gpio);
+	if (ret) {
 		dev_err(dev, "cannot get ctrl-gpios %d\n", ret);
 		return ret;
 	}
 
 	led->aux_gpio = devm_gpiod_get(dev, "aux", GPIOD_ASIS);
-	if (IS_ERR(led->aux_gpio)) {
-		ret = PTR_ERR(led->aux_gpio);
+	ret = PTR_ERR_OR_ZERO(led->aux_gpio);
+	if (ret) {
 		dev_err(dev, "cannot get aux-gpios %d\n", ret);
 		return ret;
 	}
diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
index a54b339..2a96ff6 100644
--- a/drivers/lightnvm/gennvm.c
+++ b/drivers/lightnvm/gennvm.c
@@ -89,6 +89,7 @@
 
 		list_move_tail(&blk->list, &lun->bb_list);
 		lun->vlun.nr_bad_blocks++;
+		lun->vlun.nr_free_blocks--;
 	}
 
 	return 0;
@@ -345,7 +346,7 @@
 static int gennvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
 {
 	if (!dev->ops->submit_io)
-		return 0;
+		return -ENODEV;
 
 	/* Convert address space */
 	gennvm_generic_to_addr_mode(dev, rqd);
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index 134e4fa..596347f 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -287,6 +287,10 @@
 	}
 
 	page = mempool_alloc(rrpc->page_pool, GFP_NOIO);
+	if (!page) {
+		bio_put(bio);
+		return -ENOMEM;
+	}
 
 	while ((slot = find_first_zero_bit(rblk->invalid_pages,
 					    nr_pgs_per_blk)) < nr_pgs_per_blk) {
@@ -427,7 +431,7 @@
 	if (nr_blocks_need < rrpc->nr_luns)
 		nr_blocks_need = rrpc->nr_luns;
 
-	spin_lock(&lun->lock);
+	spin_lock(&rlun->lock);
 	while (nr_blocks_need > lun->nr_free_blocks &&
 					!list_empty(&rlun->prio_list)) {
 		struct rrpc_block *rblock = block_prio_find_max(rlun);
@@ -436,16 +440,16 @@
 		if (!rblock->nr_invalid_pages)
 			break;
 
+		gcb = mempool_alloc(rrpc->gcb_pool, GFP_ATOMIC);
+		if (!gcb)
+			break;
+
 		list_del_init(&rblock->prio);
 
 		BUG_ON(!block_is_full(rrpc, rblock));
 
 		pr_debug("rrpc: selected block '%lu' for GC\n", block->id);
 
-		gcb = mempool_alloc(rrpc->gcb_pool, GFP_ATOMIC);
-		if (!gcb)
-			break;
-
 		gcb->rrpc = rrpc;
 		gcb->rblk = rblock;
 		INIT_WORK(&gcb->ws_gc, rrpc_block_gc);
@@ -454,7 +458,7 @@
 
 		nr_blocks_need--;
 	}
-	spin_unlock(&lun->lock);
+	spin_unlock(&rlun->lock);
 
 	/* TODO: Hint that request queue can be started again */
 }
@@ -650,11 +654,12 @@
 	if (bio_data_dir(rqd->bio) == WRITE)
 		rrpc_end_io_write(rrpc, rrqd, laddr, npages);
 
+	bio_put(rqd->bio);
+
 	if (rrqd->flags & NVM_IOTYPE_GC)
 		return 0;
 
 	rrpc_unlock_rq(rrpc, rqd);
-	bio_put(rqd->bio);
 
 	if (npages > 1)
 		nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list);
@@ -841,6 +846,13 @@
 	err = nvm_submit_io(rrpc->dev, rqd);
 	if (err) {
 		pr_err("rrpc: I/O submission failed: %d\n", err);
+		bio_put(bio);
+		if (!(flags & NVM_IOTYPE_GC)) {
+			rrpc_unlock_rq(rrpc, rqd);
+			if (rqd->nr_pages > 1)
+				nvm_dev_dma_free(rrpc->dev,
+			rqd->ppa_list, rqd->dma_ppa_list);
+		}
 		return NVM_IO_ERR;
 	}
 
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
index 0049269..b0155b0 100644
--- a/drivers/mcb/mcb-parse.c
+++ b/drivers/mcb/mcb-parse.c
@@ -57,7 +57,7 @@
 	mdev->id = GDD_DEV(reg1);
 	mdev->rev = GDD_REV(reg1);
 	mdev->var = GDD_VAR(reg1);
-	mdev->bar = GDD_BAR(reg1);
+	mdev->bar = GDD_BAR(reg2);
 	mdev->group = GDD_GRP(reg2);
 	mdev->inst = GDD_INS(reg2);
 
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index d8b0ab6..5649d1a 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -357,6 +357,7 @@
 config DM_RAID
        tristate "RAID 1/4/5/6/10 target"
        depends on BLK_DEV_DM
+       select MD_RAID0
        select MD_RAID1
        select MD_RAID10
        select MD_RAID456
@@ -458,6 +459,21 @@
 
 	  If unsure, say N.
 
+config DM_VERITY_HASH_PREFETCH_MIN_SIZE_128
+	bool "Prefetch size 128"
+
+config DM_VERITY_HASH_PREFETCH_MIN_SIZE
+	int "Verity hash prefetch minimum size"
+	depends on DM_VERITY
+	range 1 4096
+	default 128 if DM_VERITY_HASH_PREFETCH_MIN_SIZE_128
+	default 1
+	---help---
+	  This sets minimum number of hash blocks to prefetch for dm-verity.
+	  For devices like eMMC, having larger prefetch size like 128 can improve
+	  performance with increased memory consumption for keeping more hashes
+	  in RAM.
+
 config DM_VERITY_FEC
 	bool "Verity forward error correction support"
 	depends on DM_VERITY
@@ -500,4 +516,33 @@
 
 	  If unsure, say N.
 
+config DM_VERITY_AVB
+	tristate "Support AVB specific verity error behavior"
+	depends on DM_VERITY
+	---help---
+	  Enables Android Verified Boot platform-specific error
+	  behavior. In particular, it will modify the vbmeta partition
+	  specified on the kernel command-line when non-transient error
+	  occurs (followed by a panic).
+
+	  If unsure, say N.
+
+config DM_ANDROID_VERITY
+	bool "Android verity target support"
+	depends on DM_VERITY=y
+	depends on X509_CERTIFICATE_PARSER
+	depends on SYSTEM_TRUSTED_KEYRING
+	depends on PUBLIC_KEY_ALGO_RSA
+	depends on KEYS
+	depends on ASYMMETRIC_KEY_TYPE
+	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+	depends on MD_LINEAR=y
+	select DM_VERITY_HASH_PREFETCH_MIN_SIZE_128
+	---help---
+	  This device-mapper target is virtually a VERITY target. This
+	  target is setup by reading the metadata contents piggybacked
+	  to the actual data blocks in the block device. The signature
+	  of the metadata contents are verified against the key included
+	  in the system keyring. Upon success, the underlying verity
+	  target is setup.
 endif # MD
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 62a6576..c22cc74 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -60,6 +60,7 @@
 obj-$(CONFIG_DM_CACHE_CLEANER)	+= dm-cache-cleaner.o
 obj-$(CONFIG_DM_ERA)		+= dm-era.o
 obj-$(CONFIG_DM_LOG_WRITES)	+= dm-log-writes.o
+obj-$(CONFIG_DM_ANDROID_VERITY) += dm-android-verity.o
 
 ifeq ($(CONFIG_DM_UEVENT),y)
 dm-mod-objs			+= dm-uevent.o
@@ -68,3 +69,7 @@
 ifeq ($(CONFIG_DM_VERITY_FEC),y)
 dm-verity-objs			+= dm-verity-fec.o
 endif
+
+ifeq ($(CONFIG_DM_VERITY_AVB),y)
+dm-verity-objs			+= dm-verity-avb.o
+endif
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 6b420a5..c3ea03c 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -425,7 +425,7 @@
 	 * until a gc finishes - otherwise we could pointlessly burn a ton of
 	 * cpu
 	 */
-	unsigned		invalidate_needs_gc:1;
+	unsigned		invalidate_needs_gc;
 
 	bool			discard; /* Get rid of? */
 
@@ -593,8 +593,8 @@
 
 	/* Counts how many sectors bio_insert has added to the cache */
 	atomic_t		sectors_to_gc;
+	wait_queue_head_t	gc_wait;
 
-	wait_queue_head_t	moving_gc_wait;
 	struct keybuf		moving_gc_keys;
 	/* Number of moving GC bios in flight */
 	struct semaphore	moving_in_flight;
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 22b9e34..5b815e6 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -1762,33 +1762,34 @@
 	bch_moving_gc(c);
 }
 
-static int bch_gc_thread(void *arg)
+static bool gc_should_run(struct cache_set *c)
 {
-	struct cache_set *c = arg;
 	struct cache *ca;
 	unsigned i;
 
-	while (1) {
-again:
-		bch_btree_gc(c);
+	for_each_cache(ca, c, i)
+		if (ca->invalidate_needs_gc)
+			return true;
 
-		set_current_state(TASK_INTERRUPTIBLE);
+	if (atomic_read(&c->sectors_to_gc) < 0)
+		return true;
+
+	return false;
+}
+
+static int bch_gc_thread(void *arg)
+{
+	struct cache_set *c = arg;
+
+	while (1) {
+		wait_event_interruptible(c->gc_wait,
+			   kthread_should_stop() || gc_should_run(c));
+
 		if (kthread_should_stop())
 			break;
 
-		mutex_lock(&c->bucket_lock);
-
-		for_each_cache(ca, c, i)
-			if (ca->invalidate_needs_gc) {
-				mutex_unlock(&c->bucket_lock);
-				set_current_state(TASK_RUNNING);
-				goto again;
-			}
-
-		mutex_unlock(&c->bucket_lock);
-
-		try_to_freeze();
-		schedule();
+		set_gc_sectors(c);
+		bch_btree_gc(c);
 	}
 
 	return 0;
@@ -1796,11 +1797,10 @@
 
 int bch_gc_thread_start(struct cache_set *c)
 {
-	c->gc_thread = kthread_create(bch_gc_thread, c, "bcache_gc");
+	c->gc_thread = kthread_run(bch_gc_thread, c, "bcache_gc");
 	if (IS_ERR(c->gc_thread))
 		return PTR_ERR(c->gc_thread);
 
-	set_task_state(c->gc_thread, TASK_INTERRUPTIBLE);
 	return 0;
 }
 
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h
index 5c391fa..9b80417 100644
--- a/drivers/md/bcache/btree.h
+++ b/drivers/md/bcache/btree.h
@@ -260,8 +260,7 @@
 
 static inline void wake_up_gc(struct cache_set *c)
 {
-	if (c->gc_thread)
-		wake_up_process(c->gc_thread);
+	wake_up(&c->gc_wait);
 }
 
 #define MAP_DONE	0
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 25fa844..2410df1 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -196,10 +196,8 @@
 	struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
 	struct bio *bio = op->bio, *n;
 
-	if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0) {
-		set_gc_sectors(op->c);
+	if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0)
 		wake_up_gc(op->c);
-	}
 
 	if (op->bypass)
 		return bch_data_invalidate(cl);
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index a296425..7b5880b 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1489,6 +1489,7 @@
 	mutex_init(&c->bucket_lock);
 	init_waitqueue_head(&c->btree_cache_wait);
 	init_waitqueue_head(&c->bucket_wait);
+	init_waitqueue_head(&c->gc_wait);
 	sema_init(&c->uuid_write_mutex, 1);
 
 	spin_lock_init(&c->btree_gc_time.lock);
@@ -1547,6 +1548,7 @@
 
 	for_each_cache(ca, c, i)
 		c->nbuckets += ca->sb.nbuckets;
+	set_gc_sectors(c);
 
 	if (CACHE_SYNC(&c->sb)) {
 		LIST_HEAD(journal);
@@ -1818,7 +1820,7 @@
 	free = roundup_pow_of_two(ca->sb.nbuckets) >> 10;
 
 	if (!init_fifo(&ca->free[RESERVE_BTREE], 8, GFP_KERNEL) ||
-	    !init_fifo(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) ||
+	    !init_fifo_exact(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) ||
 	    !init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL) ||
 	    !init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) ||
 	    !init_fifo(&ca->free_inc,	free << 2, GFP_KERNEL) ||
diff --git a/drivers/md/dm-android-verity.c b/drivers/md/dm-android-verity.c
new file mode 100644
index 0000000..c3c9502
--- /dev/null
+++ b/drivers/md/dm-android-verity.c
@@ -0,0 +1,944 @@
+/*
+ * Copyright (C) 2015 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/buffer_head.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/device-mapper.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/key.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/of.h>
+#include <linux/reboot.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+
+#include <asm/setup.h>
+#include <crypto/hash.h>
+#include <crypto/public_key.h>
+#include <crypto/sha.h>
+#include <keys/asymmetric-type.h>
+#include <keys/system_keyring.h>
+
+#include "dm-verity.h"
+#include "dm-android-verity.h"
+
+static char verifiedbootstate[VERITY_COMMANDLINE_PARAM_LENGTH];
+static char veritymode[VERITY_COMMANDLINE_PARAM_LENGTH];
+static char veritykeyid[VERITY_DEFAULT_KEY_ID_LENGTH];
+static char buildvariant[BUILD_VARIANT];
+
+static bool target_added;
+static bool verity_enabled = true;
+struct dentry *debug_dir;
+static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv);
+
+static struct target_type android_verity_target = {
+	.name                   = "android-verity",
+	.version                = {1, 0, 0},
+	.module                 = THIS_MODULE,
+	.ctr                    = android_verity_ctr,
+	.dtr                    = verity_dtr,
+	.map                    = verity_map,
+	.status                 = verity_status,
+	.prepare_ioctl          = verity_prepare_ioctl,
+	.iterate_devices        = verity_iterate_devices,
+	.io_hints               = verity_io_hints,
+};
+
+static int __init verified_boot_state_param(char *line)
+{
+	strlcpy(verifiedbootstate, line, sizeof(verifiedbootstate));
+	return 1;
+}
+
+__setup("androidboot.verifiedbootstate=", verified_boot_state_param);
+
+static int __init verity_mode_param(char *line)
+{
+	strlcpy(veritymode, line, sizeof(veritymode));
+	return 1;
+}
+
+__setup("androidboot.veritymode=", verity_mode_param);
+
+static int __init verity_keyid_param(char *line)
+{
+	strlcpy(veritykeyid, line, sizeof(veritykeyid));
+	return 1;
+}
+
+__setup("veritykeyid=", verity_keyid_param);
+
+static int __init verity_buildvariant(char *line)
+{
+	strlcpy(buildvariant, line, sizeof(buildvariant));
+	return 1;
+}
+
+__setup("buildvariant=", verity_buildvariant);
+
+static inline bool default_verity_key_id(void)
+{
+	return veritykeyid[0] != '\0';
+}
+
+static inline bool is_eng(void)
+{
+	static const char typeeng[]  = "eng";
+
+	return !strncmp(buildvariant, typeeng, sizeof(typeeng));
+}
+
+static inline bool is_userdebug(void)
+{
+	static const char typeuserdebug[]  = "userdebug";
+
+	return !strncmp(buildvariant, typeuserdebug, sizeof(typeuserdebug));
+}
+
+static inline bool is_unlocked(void)
+{
+	static const char unlocked[] = "orange";
+
+	return !strncmp(verifiedbootstate, unlocked, sizeof(unlocked));
+}
+
+static int table_extract_mpi_array(struct public_key_signature *pks,
+				const void *data, size_t len)
+{
+	MPI mpi = mpi_read_raw_data(data, len);
+
+	if (!mpi) {
+		DMERR("Error while allocating mpi array");
+		return -ENOMEM;
+	}
+
+	pks->mpi[0] = mpi;
+	pks->nr_mpi = 1;
+	return 0;
+}
+
+static struct public_key_signature *table_make_digest(
+						enum hash_algo hash,
+						const void *table,
+						unsigned long table_len)
+{
+	struct public_key_signature *pks = NULL;
+	struct crypto_shash *tfm;
+	struct shash_desc *desc;
+	size_t digest_size, desc_size;
+	int ret;
+
+	/* Allocate the hashing algorithm we're going to need and find out how
+	 * big the hash operational data will be.
+	 */
+	tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0);
+	if (IS_ERR(tfm))
+		return ERR_CAST(tfm);
+
+	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+	digest_size = crypto_shash_digestsize(tfm);
+
+	/* We allocate the hash operational data storage on the end of out
+	 * context data and the digest output buffer on the end of that.
+	 */
+	ret = -ENOMEM;
+	pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL);
+	if (!pks)
+		goto error;
+
+	pks->pkey_hash_algo = hash;
+	pks->digest = (u8 *)pks + sizeof(*pks) + desc_size;
+	pks->digest_size = digest_size;
+
+	desc = (struct shash_desc *)(pks + 1);
+	desc->tfm = tfm;
+	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	ret = crypto_shash_init(desc);
+	if (ret < 0)
+		goto error;
+
+	ret = crypto_shash_finup(desc, table, table_len, pks->digest);
+	if (ret < 0)
+		goto error;
+
+	crypto_free_shash(tfm);
+	return pks;
+
+error:
+	kfree(pks);
+	crypto_free_shash(tfm);
+	return ERR_PTR(ret);
+}
+
+static int read_block_dev(struct bio_read *payload, struct block_device *bdev,
+		sector_t offset, int length)
+{
+	struct bio *bio;
+	int err = 0, i;
+
+	payload->number_of_pages = DIV_ROUND_UP(length, PAGE_SIZE);
+
+	bio = bio_alloc(GFP_KERNEL, payload->number_of_pages);
+	if (!bio) {
+		DMERR("Error while allocating bio");
+		return -ENOMEM;
+	}
+
+	bio->bi_bdev = bdev;
+	bio->bi_iter.bi_sector = offset;
+
+	payload->page_io = kzalloc(sizeof(struct page *) *
+		payload->number_of_pages, GFP_KERNEL);
+	if (!payload->page_io) {
+		DMERR("page_io array alloc failed");
+		err = -ENOMEM;
+		goto free_bio;
+	}
+
+	for (i = 0; i < payload->number_of_pages; i++) {
+		payload->page_io[i] = alloc_page(GFP_KERNEL);
+		if (!payload->page_io[i]) {
+			DMERR("alloc_page failed");
+			err = -ENOMEM;
+			goto free_pages;
+		}
+		if (!bio_add_page(bio, payload->page_io[i], PAGE_SIZE, 0)) {
+			DMERR("bio_add_page error");
+			err = -EIO;
+			goto free_pages;
+		}
+	}
+
+	if (!submit_bio_wait(READ, bio))
+		/* success */
+		goto free_bio;
+	DMERR("bio read failed");
+	err = -EIO;
+
+free_pages:
+	for (i = 0; i < payload->number_of_pages; i++)
+		if (payload->page_io[i])
+			__free_page(payload->page_io[i]);
+	kfree(payload->page_io);
+free_bio:
+	bio_put(bio);
+	return err;
+}
+
+static inline u64 fec_div_round_up(u64 x, u64 y)
+{
+	u64 remainder;
+
+	return div64_u64_rem(x, y, &remainder) +
+		(remainder > 0 ? 1 : 0);
+}
+
+static inline void populate_fec_metadata(struct fec_header *header,
+				struct fec_ecc_metadata *ecc)
+{
+	ecc->blocks = fec_div_round_up(le64_to_cpu(header->inp_size),
+			FEC_BLOCK_SIZE);
+	ecc->roots = le32_to_cpu(header->roots);
+	ecc->start = le64_to_cpu(header->inp_size);
+}
+
+static inline int validate_fec_header(struct fec_header *header, u64 offset)
+{
+	/* move offset to make the sanity check work for backup header
+	 * as well. */
+	offset -= offset % FEC_BLOCK_SIZE;
+	if (le32_to_cpu(header->magic) != FEC_MAGIC ||
+		le32_to_cpu(header->version) != FEC_VERSION ||
+		le32_to_cpu(header->size) != sizeof(struct fec_header) ||
+		le32_to_cpu(header->roots) == 0 ||
+		le32_to_cpu(header->roots) >= FEC_RSM)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int extract_fec_header(dev_t dev, struct fec_header *fec,
+				struct fec_ecc_metadata *ecc)
+{
+	u64 device_size;
+	struct bio_read payload;
+	int i, err = 0;
+	struct block_device *bdev;
+
+	bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
+
+	if (IS_ERR_OR_NULL(bdev)) {
+		DMERR("bdev get error");
+		return PTR_ERR(bdev);
+	}
+
+	device_size = i_size_read(bdev->bd_inode);
+
+	/* fec metadata size is a power of 2 and PAGE_SIZE
+	 * is a power of 2 as well.
+	 */
+	BUG_ON(FEC_BLOCK_SIZE > PAGE_SIZE);
+	/* 512 byte sector alignment */
+	BUG_ON(((device_size - FEC_BLOCK_SIZE) % (1 << SECTOR_SHIFT)) != 0);
+
+	err = read_block_dev(&payload, bdev, (device_size -
+		FEC_BLOCK_SIZE) / (1 << SECTOR_SHIFT), FEC_BLOCK_SIZE);
+	if (err) {
+		DMERR("Error while reading verity metadata");
+		goto error;
+	}
+
+	BUG_ON(sizeof(struct fec_header) > PAGE_SIZE);
+	memcpy(fec, page_address(payload.page_io[0]),
+			sizeof(*fec));
+
+	ecc->valid = true;
+	if (validate_fec_header(fec, device_size - FEC_BLOCK_SIZE)) {
+		/* Try the backup header */
+		memcpy(fec, page_address(payload.page_io[0]) + FEC_BLOCK_SIZE
+			- sizeof(*fec) ,
+			sizeof(*fec));
+		if (validate_fec_header(fec, device_size -
+			sizeof(struct fec_header)))
+			ecc->valid = false;
+	}
+
+	if (ecc->valid)
+		populate_fec_metadata(fec, ecc);
+
+	for (i = 0; i < payload.number_of_pages; i++)
+		__free_page(payload.page_io[i]);
+	kfree(payload.page_io);
+
+error:
+	blkdev_put(bdev, FMODE_READ);
+	return err;
+}
+static void find_metadata_offset(struct fec_header *fec,
+		struct block_device *bdev, u64 *metadata_offset)
+{
+	u64 device_size;
+
+	device_size = i_size_read(bdev->bd_inode);
+
+	if (le32_to_cpu(fec->magic) == FEC_MAGIC)
+		*metadata_offset = le64_to_cpu(fec->inp_size) -
+					VERITY_METADATA_SIZE;
+	else
+		*metadata_offset = device_size - VERITY_METADATA_SIZE;
+}
+
+static int find_size(dev_t dev, u64 *device_size)
+{
+	struct block_device *bdev;
+
+	bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
+	if (IS_ERR_OR_NULL(bdev)) {
+		DMERR("blkdev_get_by_dev failed");
+		return PTR_ERR(bdev);
+	}
+
+	*device_size = i_size_read(bdev->bd_inode);
+	*device_size >>= SECTOR_SHIFT;
+
+	DMINFO("blkdev size in sectors: %llu", *device_size);
+	blkdev_put(bdev, FMODE_READ);
+	return 0;
+}
+
+static int verify_header(struct android_metadata_header *header)
+{
+	int retval = -EINVAL;
+
+	if (is_userdebug() && le32_to_cpu(header->magic_number) ==
+			VERITY_METADATA_MAGIC_DISABLE)
+		return VERITY_STATE_DISABLE;
+
+	if (!(le32_to_cpu(header->magic_number) ==
+			VERITY_METADATA_MAGIC_NUMBER) ||
+			(le32_to_cpu(header->magic_number) ==
+			VERITY_METADATA_MAGIC_DISABLE)) {
+		DMERR("Incorrect magic number");
+		return retval;
+	}
+
+	if (le32_to_cpu(header->protocol_version) !=
+			VERITY_METADATA_VERSION) {
+		DMERR("Unsupported version %u",
+			le32_to_cpu(header->protocol_version));
+		return retval;
+	}
+
+	return 0;
+}
+
+static int extract_metadata(dev_t dev, struct fec_header *fec,
+				struct android_metadata **metadata,
+				bool *verity_enabled)
+{
+	struct block_device *bdev;
+	struct android_metadata_header *header;
+	int i;
+	u32 table_length, copy_length, offset;
+	u64 metadata_offset;
+	struct bio_read payload;
+	int err = 0;
+
+	bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
+
+	if (IS_ERR_OR_NULL(bdev)) {
+		DMERR("blkdev_get_by_dev failed");
+		return -ENODEV;
+	}
+
+	find_metadata_offset(fec, bdev, &metadata_offset);
+
+	/* Verity metadata size is a power of 2 and PAGE_SIZE
+	 * is a power of 2 as well.
+	 * PAGE_SIZE is also a multiple of 512 bytes.
+	*/
+	if (VERITY_METADATA_SIZE > PAGE_SIZE)
+		BUG_ON(VERITY_METADATA_SIZE % PAGE_SIZE != 0);
+	/* 512 byte sector alignment */
+	BUG_ON(metadata_offset % (1 << SECTOR_SHIFT) != 0);
+
+	err = read_block_dev(&payload, bdev, metadata_offset /
+		(1 << SECTOR_SHIFT), VERITY_METADATA_SIZE);
+	if (err) {
+		DMERR("Error while reading verity metadata");
+		goto blkdev_release;
+	}
+
+	header = kzalloc(sizeof(*header), GFP_KERNEL);
+	if (!header) {
+		DMERR("kzalloc failed for header");
+		err = -ENOMEM;
+		goto free_payload;
+	}
+
+	memcpy(header, page_address(payload.page_io[0]),
+		sizeof(*header));
+
+	DMINFO("bio magic_number:%u protocol_version:%d table_length:%u",
+		le32_to_cpu(header->magic_number),
+		le32_to_cpu(header->protocol_version),
+		le32_to_cpu(header->table_length));
+
+	err = verify_header(header);
+
+	if (err == VERITY_STATE_DISABLE) {
+		DMERR("Mounting root with verity disabled");
+		*verity_enabled = false;
+		/* we would still have to read the metadata to figure out
+		 * the data blocks size. Or may be could map the entire
+		 * partition similar to mounting the device.
+		 *
+		 * Reset error as well as the verity_enabled flag is changed.
+		 */
+		err = 0;
+	} else if (err)
+		goto free_header;
+
+	*metadata = kzalloc(sizeof(**metadata), GFP_KERNEL);
+	if (!*metadata) {
+		DMERR("kzalloc for metadata failed");
+		err = -ENOMEM;
+		goto free_header;
+	}
+
+	(*metadata)->header = header;
+	table_length = le32_to_cpu(header->table_length);
+
+	if (table_length == 0 ||
+		table_length > (VERITY_METADATA_SIZE -
+			sizeof(struct android_metadata_header))) {
+		DMERR("table_length too long");
+		err = -EINVAL;
+		goto free_metadata;
+	}
+
+	(*metadata)->verity_table = kzalloc(table_length + 1, GFP_KERNEL);
+
+	if (!(*metadata)->verity_table) {
+		DMERR("kzalloc verity_table failed");
+		err = -ENOMEM;
+		goto free_metadata;
+	}
+
+	if (sizeof(struct android_metadata_header) +
+			table_length <= PAGE_SIZE) {
+		memcpy((*metadata)->verity_table,
+			page_address(payload.page_io[0])
+			+ sizeof(struct android_metadata_header),
+			table_length);
+	} else {
+		copy_length = PAGE_SIZE -
+			sizeof(struct android_metadata_header);
+		memcpy((*metadata)->verity_table,
+			page_address(payload.page_io[0])
+			+ sizeof(struct android_metadata_header),
+			copy_length);
+		table_length -= copy_length;
+		offset = copy_length;
+		i = 1;
+		while (table_length != 0) {
+			if (table_length > PAGE_SIZE) {
+				memcpy((*metadata)->verity_table + offset,
+					page_address(payload.page_io[i]),
+					PAGE_SIZE);
+				offset += PAGE_SIZE;
+				table_length -= PAGE_SIZE;
+			} else {
+				memcpy((*metadata)->verity_table + offset,
+					page_address(payload.page_io[i]),
+					table_length);
+				table_length = 0;
+			}
+			i++;
+		}
+	}
+	(*metadata)->verity_table[table_length] = '\0';
+
+	DMINFO("verity_table: %s", (*metadata)->verity_table);
+	goto free_payload;
+
+free_metadata:
+	kfree(*metadata);
+free_header:
+	kfree(header);
+free_payload:
+	for (i = 0; i < payload.number_of_pages; i++)
+		if (payload.page_io[i])
+			__free_page(payload.page_io[i]);
+	kfree(payload.page_io);
+blkdev_release:
+	blkdev_put(bdev, FMODE_READ);
+	return err;
+}
+
+/* helper functions to extract properties from dts */
+const char *find_dt_value(const char *name)
+{
+	struct device_node *firmware;
+	const char *value;
+
+	firmware = of_find_node_by_path("/firmware/android");
+	if (!firmware)
+		return NULL;
+	value = of_get_property(firmware, name, NULL);
+	of_node_put(firmware);
+
+	return value;
+}
+
+static int verity_mode(void)
+{
+	static const char enforcing[] = "enforcing";
+	static const char verified_mode_prop[] = "veritymode";
+	const char *value;
+
+	value = find_dt_value(verified_mode_prop);
+	if (!value)
+		value = veritymode;
+	if (!strncmp(value, enforcing, sizeof(enforcing) - 1))
+		return DM_VERITY_MODE_RESTART;
+
+	return DM_VERITY_MODE_EIO;
+}
+
+static int verify_verity_signature(char *key_id,
+		struct android_metadata *metadata)
+{
+	key_ref_t key_ref;
+	struct key *key;
+	struct public_key_signature *pks = NULL;
+	int retval = -EINVAL;
+
+	key_ref = keyring_search(make_key_ref(system_trusted_keyring, 1),
+		&key_type_asymmetric, key_id);
+
+	if (IS_ERR(key_ref)) {
+		DMERR("keyring: key not found");
+		return -ENOKEY;
+	}
+
+	key = key_ref_to_ptr(key_ref);
+
+	pks = table_make_digest(HASH_ALGO_SHA256,
+			(const void *)metadata->verity_table,
+			le32_to_cpu(metadata->header->table_length));
+
+	if (IS_ERR(pks)) {
+		DMERR("hashing failed");
+		retval = PTR_ERR(pks);
+		pks = NULL;
+		goto error;
+	}
+
+	retval = table_extract_mpi_array(pks, &metadata->header->signature[0],
+				RSANUMBYTES);
+	if (retval < 0) {
+		DMERR("Error extracting mpi %d", retval);
+		goto error;
+	}
+
+	retval = verify_signature(key, pks);
+	mpi_free(pks->rsa.s);
+error:
+	kfree(pks);
+	key_put(key);
+
+	return retval;
+}
+
+static void handle_error(void)
+{
+	int mode = verity_mode();
+	if (mode == DM_VERITY_MODE_RESTART) {
+		DMERR("triggering restart");
+		kernel_restart("dm-verity device corrupted");
+	} else {
+		DMERR("Mounting verity root failed");
+	}
+}
+
+static inline bool test_mult_overflow(sector_t a, u32 b)
+{
+	sector_t r = (sector_t)~0ULL;
+
+	sector_div(r, b);
+	return a > r;
+}
+
+static int add_as_linear_device(struct dm_target *ti, char *dev)
+{
+	/*Move to linear mapping defines*/
+	char *linear_table_args[DM_LINEAR_ARGS] = {dev,
+					DM_LINEAR_TARGET_OFFSET};
+	int err = 0;
+
+	android_verity_target.dtr = dm_linear_dtr,
+	android_verity_target.map = dm_linear_map,
+	android_verity_target.status = dm_linear_status,
+	android_verity_target.prepare_ioctl = dm_linear_prepare_ioctl,
+	android_verity_target.iterate_devices = dm_linear_iterate_devices,
+	android_verity_target.io_hints = NULL;
+
+	err = dm_linear_ctr(ti, DM_LINEAR_ARGS, linear_table_args);
+
+	if (!err) {
+		DMINFO("Added android-verity as a linear target");
+		target_added = true;
+	} else
+		DMERR("Failed to add android-verity as linear target");
+
+	return err;
+}
+
+static int create_linear_device(struct dm_target *ti, dev_t dev,
+				char *target_device)
+{
+	u64 device_size = 0;
+	int err = find_size(dev, &device_size);
+
+	if (err) {
+		DMERR("error finding bdev size");
+		handle_error();
+		return err;
+	}
+
+	ti->len = device_size;
+	err = add_as_linear_device(ti, target_device);
+	if (err) {
+		handle_error();
+		return err;
+	}
+	verity_enabled = false;
+	return 0;
+}
+
+/*
+ * Target parameters:
+ *	<key id>	Key id of the public key in the system keyring.
+ *			Verity metadata's signature would be verified against
+ *			this. If the key id contains spaces, replace them
+ *			with '#'.
+ *	<block device>	The block device for which dm-verity is being setup.
+ */
+static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+	dev_t uninitialized_var(dev);
+	struct android_metadata *metadata = NULL;
+	int err = 0, i, mode;
+	char *key_id, *table_ptr, dummy, *target_device,
+	*verity_table_args[VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS];
+	/* One for specifying number of opt args and one for mode */
+	sector_t data_sectors;
+	u32 data_block_size;
+	unsigned int no_of_args = VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS;
+	struct fec_header uninitialized_var(fec);
+	struct fec_ecc_metadata uninitialized_var(ecc);
+	char buf[FEC_ARG_LENGTH], *buf_ptr;
+	unsigned long long tmpll;
+
+	if (argc == 1) {
+		/* Use the default keyid */
+		if (default_verity_key_id())
+			key_id = veritykeyid;
+		else if (!is_eng()) {
+			DMERR("veritykeyid= is not set");
+			handle_error();
+			return -EINVAL;
+		}
+	} else if (argc == 2)
+		key_id = argv[1];
+	else {
+		DMERR("Incorrect number of arguments");
+		handle_error();
+		return -EINVAL;
+	}
+
+	target_device = argv[0];
+
+	dev = name_to_dev_t(target_device);
+	if (!dev) {
+		DMERR("no dev found for %s", target_device);
+		handle_error();
+		return -EINVAL;
+	}
+
+	if (is_eng())
+		return create_linear_device(ti, dev, target_device);
+
+	strreplace(key_id, '#', ' ');
+
+	DMINFO("key:%s dev:%s", key_id, target_device);
+
+	if (extract_fec_header(dev, &fec, &ecc)) {
+		DMERR("Error while extracting fec header");
+		handle_error();
+		return -EINVAL;
+	}
+
+	err = extract_metadata(dev, &fec, &metadata, &verity_enabled);
+
+	if (err) {
+		/* Allow invalid metadata when the device is unlocked */
+		if (is_unlocked()) {
+			DMWARN("Allow invalid metadata when unlocked");
+			return create_linear_device(ti, dev, target_device);
+		}
+		DMERR("Error while extracting metadata");
+		handle_error();
+		goto free_metadata;
+	}
+
+	if (verity_enabled) {
+		err = verify_verity_signature(key_id, metadata);
+
+		if (err) {
+			DMERR("Signature verification failed");
+			handle_error();
+			goto free_metadata;
+		} else
+			DMINFO("Signature verification success");
+	}
+
+	table_ptr = metadata->verity_table;
+
+	for (i = 0; i < VERITY_TABLE_ARGS; i++) {
+		verity_table_args[i] = strsep(&table_ptr, " ");
+		if (verity_table_args[i] == NULL)
+			break;
+	}
+
+	if (i != VERITY_TABLE_ARGS) {
+		DMERR("Verity table not in the expected format");
+		err = -EINVAL;
+		handle_error();
+		goto free_metadata;
+	}
+
+	if (sscanf(verity_table_args[5], "%llu%c", &tmpll, &dummy)
+							!= 1) {
+		DMERR("Verity table not in the expected format");
+		handle_error();
+		err = -EINVAL;
+		goto free_metadata;
+	}
+
+	if (tmpll > ULONG_MAX) {
+		DMERR("<num_data_blocks> too large. Forgot to turn on CONFIG_LBDAF?");
+		handle_error();
+		err = -EINVAL;
+		goto free_metadata;
+	}
+
+	data_sectors = tmpll;
+
+	if (sscanf(verity_table_args[3], "%u%c", &data_block_size, &dummy)
+								!= 1) {
+		DMERR("Verity table not in the expected format");
+		handle_error();
+		err = -EINVAL;
+		goto free_metadata;
+	}
+
+	if (test_mult_overflow(data_sectors, data_block_size >>
+							SECTOR_SHIFT)) {
+		DMERR("data_sectors too large");
+		handle_error();
+		err = -EOVERFLOW;
+		goto free_metadata;
+	}
+
+	data_sectors *= data_block_size >> SECTOR_SHIFT;
+	DMINFO("Data sectors %llu", (unsigned long long)data_sectors);
+
+	/* update target length */
+	ti->len = data_sectors;
+
+	/* Setup linear target and free */
+	if (!verity_enabled) {
+		err = add_as_linear_device(ti, target_device);
+		goto free_metadata;
+	}
+
+	/*substitute data_dev and hash_dev*/
+	verity_table_args[1] = target_device;
+	verity_table_args[2] = target_device;
+
+	mode = verity_mode();
+
+	if (ecc.valid && IS_BUILTIN(CONFIG_DM_VERITY_FEC)) {
+		if (mode) {
+			err = snprintf(buf, FEC_ARG_LENGTH,
+				"%u %s " VERITY_TABLE_OPT_FEC_FORMAT,
+				1 + VERITY_TABLE_OPT_FEC_ARGS,
+				mode == DM_VERITY_MODE_RESTART ?
+					VERITY_TABLE_OPT_RESTART :
+					VERITY_TABLE_OPT_LOGGING,
+				target_device,
+				ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
+				ecc.roots);
+		} else {
+			err = snprintf(buf, FEC_ARG_LENGTH,
+				"%u " VERITY_TABLE_OPT_FEC_FORMAT,
+				VERITY_TABLE_OPT_FEC_ARGS, target_device,
+				ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
+				ecc.roots);
+		}
+	} else if (mode) {
+		err = snprintf(buf, FEC_ARG_LENGTH,
+			"2 " VERITY_TABLE_OPT_IGNZERO " %s",
+			mode == DM_VERITY_MODE_RESTART ?
+			VERITY_TABLE_OPT_RESTART : VERITY_TABLE_OPT_LOGGING);
+	} else {
+		err = snprintf(buf, FEC_ARG_LENGTH, "1 %s",
+				 "ignore_zero_blocks");
+	}
+
+	if (err < 0 || err >= FEC_ARG_LENGTH)
+		goto free_metadata;
+
+	buf_ptr = buf;
+
+	for (i = VERITY_TABLE_ARGS; i < (VERITY_TABLE_ARGS +
+		VERITY_TABLE_OPT_FEC_ARGS + 2); i++) {
+		verity_table_args[i] = strsep(&buf_ptr, " ");
+		if (verity_table_args[i] == NULL) {
+			no_of_args = i;
+			break;
+		}
+	}
+
+	err = verity_ctr(ti, no_of_args, verity_table_args);
+
+	if (err)
+		DMERR("android-verity failed to mount as verity target");
+	else {
+		target_added = true;
+		DMINFO("android-verity mounted as verity target");
+	}
+
+free_metadata:
+	if (metadata) {
+		kfree(metadata->header);
+		kfree(metadata->verity_table);
+	}
+	kfree(metadata);
+	return err;
+}
+
+static int __init dm_android_verity_init(void)
+{
+	int r;
+	struct dentry *file;
+
+	r = dm_register_target(&android_verity_target);
+	if (r < 0)
+		DMERR("register failed %d", r);
+
+	/* Tracks the status of the last added target */
+	debug_dir = debugfs_create_dir("android_verity", NULL);
+
+	if (IS_ERR_OR_NULL(debug_dir)) {
+		DMERR("Cannot create android_verity debugfs directory: %ld",
+			PTR_ERR(debug_dir));
+		goto end;
+	}
+
+	file = debugfs_create_bool("target_added", S_IRUGO, debug_dir,
+				&target_added);
+
+	if (IS_ERR_OR_NULL(file)) {
+		DMERR("Cannot create android_verity debugfs directory: %ld",
+			PTR_ERR(debug_dir));
+		debugfs_remove_recursive(debug_dir);
+		goto end;
+	}
+
+	file = debugfs_create_bool("verity_enabled", S_IRUGO, debug_dir,
+				&verity_enabled);
+
+	if (IS_ERR_OR_NULL(file)) {
+		DMERR("Cannot create android_verity debugfs directory: %ld",
+			PTR_ERR(debug_dir));
+		debugfs_remove_recursive(debug_dir);
+	}
+
+end:
+	return r;
+}
+
+static void __exit dm_android_verity_exit(void)
+{
+	if (!IS_ERR_OR_NULL(debug_dir))
+		debugfs_remove_recursive(debug_dir);
+
+	dm_unregister_target(&android_verity_target);
+}
+
+module_init(dm_android_verity_init);
+module_exit(dm_android_verity_exit);
diff --git a/drivers/md/dm-android-verity.h b/drivers/md/dm-android-verity.h
new file mode 100644
index 0000000..0c7ff6a
--- /dev/null
+++ b/drivers/md/dm-android-verity.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef DM_ANDROID_VERITY_H
+#define DM_ANDROID_VERITY_H
+
+#include <crypto/sha.h>
+
+#define RSANUMBYTES 256
+#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
+#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56
+#define VERITY_METADATA_VERSION 0
+#define VERITY_STATE_DISABLE 1
+#define DATA_BLOCK_SIZE (4 * 1024)
+#define VERITY_METADATA_SIZE (8 * DATA_BLOCK_SIZE)
+#define VERITY_TABLE_ARGS 10
+#define VERITY_COMMANDLINE_PARAM_LENGTH 20
+#define BUILD_VARIANT 20
+
+/*
+ * <subject>:<sha1-id> is the format for the identifier.
+ * subject can either be the Common Name(CN) + Organization Name(O) or
+ * just the CN if the it is prefixed with O
+ * From https://tools.ietf.org/html/rfc5280#appendix-A
+ * ub-organization-name-length INTEGER ::= 64
+ * ub-common-name-length INTEGER ::= 64
+ *
+ * http://lxr.free-electrons.com/source/crypto/asymmetric_keys/x509_cert_parser.c?v=3.9#L278
+ * ctx->o_size + 2 + ctx->cn_size + 1
+ * + 41 characters for ":" and sha1 id
+ * 64 + 2 + 64 + 1 + 1 + 40 (172)
+ * setting VERITY_DEFAULT_KEY_ID_LENGTH to 200 characters.
+ */
+#define VERITY_DEFAULT_KEY_ID_LENGTH 200
+
+#define FEC_MAGIC 0xFECFECFE
+#define FEC_BLOCK_SIZE (4 * 1024)
+#define FEC_VERSION 0
+#define FEC_RSM 255
+#define FEC_ARG_LENGTH 300
+
+#define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
+#define VERITY_TABLE_OPT_LOGGING "ignore_corruption"
+#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
+
+#define VERITY_TABLE_OPT_FEC_FORMAT \
+	"use_fec_from_device %s fec_start %llu fec_blocks %llu fec_roots %u ignore_zero_blocks"
+#define VERITY_TABLE_OPT_FEC_ARGS 9
+
+#define VERITY_DEBUG 0
+
+#define DM_MSG_PREFIX                   "android-verity"
+
+#define DM_LINEAR_ARGS 2
+#define DM_LINEAR_TARGET_OFFSET "0"
+
+/*
+ * There can be two formats.
+ * if fec is present
+ * <data_blocks> <verity_tree> <verity_metdata_32K><fec_data><fec_data_4K>
+ * if fec is not present
+ * <data_blocks> <verity_tree> <verity_metdata_32K>
+ */
+struct fec_header {
+	__le32 magic;
+	__le32 version;
+	__le32 size;
+	__le32 roots;
+	__le32 fec_size;
+	__le64 inp_size;
+	u8 hash[SHA256_DIGEST_SIZE];
+} __attribute__((packed));
+
+struct android_metadata_header {
+	__le32 magic_number;
+	__le32 protocol_version;
+	char signature[RSANUMBYTES];
+	__le32 table_length;
+};
+
+struct android_metadata {
+	struct android_metadata_header *header;
+	char *verity_table;
+};
+
+struct fec_ecc_metadata {
+	bool valid;
+	u32 roots;
+	u64 blocks;
+	u64 rounds;
+	u64 start;
+};
+
+struct bio_read {
+	struct page **page_io;
+	int number_of_pages;
+};
+
+extern struct target_type linear_target;
+
+extern void dm_linear_dtr(struct dm_target *ti);
+extern int dm_linear_map(struct dm_target *ti, struct bio *bio);
+extern void dm_linear_status(struct dm_target *ti, status_type_t type,
+			unsigned status_flags, char *result, unsigned maxlen);
+extern int dm_linear_prepare_ioctl(struct dm_target *ti,
+                struct block_device **bdev, fmode_t *mode);
+extern int dm_linear_iterate_devices(struct dm_target *ti,
+			iterate_devices_callout_fn fn, void *data);
+extern int dm_linear_ctr(struct dm_target *ti, unsigned int argc, char **argv);
+#endif /* DM_ANDROID_VERITY_H */
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 2dd3308..cdceefd 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -222,7 +222,7 @@
  * Buffers are freed after this timeout
  */
 static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
-static unsigned dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
+static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
 
 static unsigned long dm_bufio_peak_allocated;
 static unsigned long dm_bufio_allocated_kmem_cache;
@@ -914,10 +914,11 @@
 {
 	unsigned long buffers;
 
-	if (ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch) {
-		mutex_lock(&dm_bufio_clients_lock);
-		__cache_size_refresh();
-		mutex_unlock(&dm_bufio_clients_lock);
+	if (unlikely(ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch)) {
+		if (mutex_trylock(&dm_bufio_clients_lock)) {
+			__cache_size_refresh();
+			mutex_unlock(&dm_bufio_clients_lock);
+		}
 	}
 
 	buffers = dm_bufio_cache_size_per_client >>
@@ -1513,10 +1514,10 @@
 	return true;
 }
 
-static unsigned get_retain_buffers(struct dm_bufio_client *c)
+static unsigned long get_retain_buffers(struct dm_bufio_client *c)
 {
-        unsigned retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes);
-        return retain_bytes / c->block_size;
+        unsigned long retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes);
+        return retain_bytes >> (c->sectors_per_block_bits + SECTOR_SHIFT);
 }
 
 static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
@@ -1526,7 +1527,7 @@
 	struct dm_buffer *b, *tmp;
 	unsigned long freed = 0;
 	unsigned long count = nr_to_scan;
-	unsigned retain_target = get_retain_buffers(c);
+	unsigned long retain_target = get_retain_buffers(c);
 
 	for (l = 0; l < LIST_SIZE; l++) {
 		list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) {
@@ -1752,11 +1753,19 @@
 static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz)
 {
 	struct dm_buffer *b, *tmp;
-	unsigned retain_target = get_retain_buffers(c);
-	unsigned count;
+	unsigned long retain_target = get_retain_buffers(c);
+	unsigned long count;
+	LIST_HEAD(write_list);
 
 	dm_bufio_lock(c);
 
+	__check_watermark(c, &write_list);
+	if (unlikely(!list_empty(&write_list))) {
+		dm_bufio_unlock(c);
+		__flush_write_list(&write_list);
+		dm_bufio_lock(c);
+	}
+
 	count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
 	list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_CLEAN], lru_list) {
 		if (count <= retain_target)
@@ -1781,6 +1790,8 @@
 
 	mutex_lock(&dm_bufio_clients_lock);
 
+	__cache_size_refresh();
+
 	list_for_each_entry(c, &dm_bufio_all_clients, client_list)
 		__evict_old_buffers(c, max_age_hz);
 
@@ -1904,7 +1915,7 @@
 module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds");
 
-module_param_named(retain_bytes, dm_bufio_retain_bytes, uint, S_IRUGO | S_IWUSR);
+module_param_named(retain_bytes, dm_bufio_retain_bytes, ulong, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(retain_bytes, "Try to keep at least this many bytes cached in memory");
 
 module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR);
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index 3970cda..d3c55d7 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -1326,17 +1326,19 @@
 
 int dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown)
 {
-	int r;
+	int r = -EINVAL;
 	flags_mutator mutator = (clean_shutdown ? set_clean_shutdown :
 				 clear_clean_shutdown);
 
 	WRITE_LOCK(cmd);
+	if (cmd->fail_io)
+		goto out;
+
 	r = __commit_transaction(cmd, mutator);
 	if (r)
 		goto out;
 
 	r = __begin_transaction(cmd);
-
 out:
 	WRITE_UNLOCK(cmd);
 	return r;
@@ -1348,7 +1350,8 @@
 	int r = -EINVAL;
 
 	READ_LOCK(cmd);
-	r = dm_sm_get_nr_free(cmd->metadata_sm, result);
+	if (!cmd->fail_io)
+		r = dm_sm_get_nr_free(cmd->metadata_sm, result);
 	READ_UNLOCK(cmd);
 
 	return r;
@@ -1360,7 +1363,8 @@
 	int r = -EINVAL;
 
 	READ_LOCK(cmd);
-	r = dm_sm_get_nr_blocks(cmd->metadata_sm, result);
+	if (!cmd->fail_io)
+		r = dm_sm_get_nr_blocks(cmd->metadata_sm, result);
 	READ_UNLOCK(cmd);
 
 	return r;
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index bb9b92e..0da5efa 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -248,7 +248,7 @@
 	/*
 	 * Fields for converting from sectors to blocks.
 	 */
-	uint32_t sectors_per_block;
+	sector_t sectors_per_block;
 	int sectors_per_block_shift;
 
 	spinlock_t lock;
@@ -3544,11 +3544,11 @@
 
 		residency = policy_residency(cache->policy);
 
-		DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %lu ",
+		DMEMIT("%u %llu/%llu %llu %llu/%llu %u %u %u %u %u %u %lu ",
 		       (unsigned)DM_CACHE_METADATA_BLOCK_SIZE,
 		       (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
 		       (unsigned long long)nr_blocks_metadata,
-		       cache->sectors_per_block,
+		       (unsigned long long)cache->sectors_per_block,
 		       (unsigned long long) from_cblock(residency),
 		       (unsigned long long) from_cblock(cache->cache_size),
 		       (unsigned) atomic_read(&cache->stats.read_hit),
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index e85bcae..799b9a5 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -112,8 +112,7 @@
  * and encrypts / decrypts at the same time.
  */
 enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID,
-	     DM_CRYPT_SAME_CPU, DM_CRYPT_NO_OFFLOAD,
-	     DM_CRYPT_EXIT_THREAD};
+	     DM_CRYPT_SAME_CPU, DM_CRYPT_NO_OFFLOAD };
 
 /*
  * The fields in here must be read only after initialization.
@@ -1204,18 +1203,20 @@
 		if (!RB_EMPTY_ROOT(&cc->write_tree))
 			goto pop_from_list;
 
-		if (unlikely(test_bit(DM_CRYPT_EXIT_THREAD, &cc->flags))) {
-			spin_unlock_irq(&cc->write_thread_wait.lock);
-			break;
-		}
-
-		__set_current_state(TASK_INTERRUPTIBLE);
+		set_current_state(TASK_INTERRUPTIBLE);
 		__add_wait_queue(&cc->write_thread_wait, &wait);
 
 		spin_unlock_irq(&cc->write_thread_wait.lock);
 
+		if (unlikely(kthread_should_stop())) {
+			set_task_state(current, TASK_RUNNING);
+			remove_wait_queue(&cc->write_thread_wait, &wait);
+			break;
+		}
+
 		schedule();
 
+		set_task_state(current, TASK_RUNNING);
 		spin_lock_irq(&cc->write_thread_wait.lock);
 		__remove_wait_queue(&cc->write_thread_wait, &wait);
 		goto continue_locked;
@@ -1499,12 +1500,15 @@
 	if (!cc->key_size && strcmp(key, "-"))
 		goto out;
 
+	/* clear the flag since following operations may invalidate previously valid key */
+	clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
+
 	if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0)
 		goto out;
 
-	set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
-
 	r = crypt_setkey_allcpus(cc);
+	if (!r)
+		set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 
 out:
 	/* Hex key string not needed after here, so wipe it. */
@@ -1530,13 +1534,8 @@
 	if (!cc)
 		return;
 
-	if (cc->write_thread) {
-		spin_lock_irq(&cc->write_thread_wait.lock);
-		set_bit(DM_CRYPT_EXIT_THREAD, &cc->flags);
-		wake_up_locked(&cc->write_thread_wait);
-		spin_unlock_irq(&cc->write_thread_wait.lock);
+	if (cc->write_thread)
 		kthread_stop(cc->write_thread);
-	}
 
 	if (cc->io_queue)
 		destroy_workqueue(cc->io_queue);
@@ -1928,6 +1927,13 @@
 		return DM_MAPIO_REMAPPED;
 	}
 
+	/*
+	 * Check if bio is too large, split as needed.
+	 */
+	if (unlikely(bio->bi_iter.bi_size > (BIO_MAX_PAGES << PAGE_SHIFT)) &&
+	    bio_data_dir(bio) == WRITE)
+		dm_accept_partial_bio(bio, ((BIO_MAX_PAGES << PAGE_SHIFT) >> SECTOR_SHIFT));
+
 	io = dm_per_bio_data(bio, cc->per_bio_data_size);
 	crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
 	io->ctx.req = (struct ablkcipher_request *)(io + 1);
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index 665bf32..32e76c5 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -961,18 +961,18 @@
 		}
 	}
 
-	r = save_sm_root(md);
-	if (r) {
-		DMERR("%s: save_sm_root failed", __func__);
-		return r;
-	}
-
 	r = dm_tm_pre_commit(md->tm);
 	if (r) {
 		DMERR("%s: pre commit failed", __func__);
 		return r;
 	}
 
+	r = save_sm_root(md);
+	if (r) {
+		DMERR("%s: save_sm_root failed", __func__);
+		return r;
+	}
+
 	r = superblock_lock(md, &sblock);
 	if (r) {
 		DMERR("%s: superblock lock failed", __func__);
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 09e2afc..78f403b 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -200,11 +200,13 @@
 
 	if (!(fc->up_interval + fc->down_interval)) {
 		ti->error = "Total (up + down) interval is zero";
+		r = -EINVAL;
 		goto bad;
 	}
 
 	if (fc->up_interval + fc->down_interval < fc->up_interval) {
 		ti->error = "Interval overflow";
+		r = -EINVAL;
 		goto bad;
 	}
 
@@ -289,10 +291,14 @@
 		pb->bio_submitted = true;
 
 		/*
-		 * Map reads as normal.
+		 * Error reads if neither corrupt_bio_byte or drop_writes are set.
+		 * Otherwise, flakey_end_io() will decide if the reads should be modified.
 		 */
-		if (bio_data_dir(bio) == READ)
+		if (bio_data_dir(bio) == READ) {
+			if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags))
+				return -EIO;
 			goto map_bio;
+		}
 
 		/*
 		 * Drop writes?
@@ -328,14 +334,22 @@
 	struct flakey_c *fc = ti->private;
 	struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
 
-	/*
-	 * Corrupt successful READs while in down state.
-	 * If flags were specified, only corrupt those that match.
-	 */
-	if (fc->corrupt_bio_byte && !error && pb->bio_submitted &&
-	    (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) &&
-	    all_corrupt_bio_flags_match(bio, fc))
-		corrupt_bio_data(bio, fc);
+	if (!error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
+		if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
+		    all_corrupt_bio_flags_match(bio, fc)) {
+			/*
+			 * Corrupt successful matching READs while in down state.
+			 */
+			corrupt_bio_data(bio, fc);
+
+		} else if (!test_bit(DROP_WRITES, &fc->flags)) {
+			/*
+			 * Error read during the down_interval if drop_writes
+			 * wasn't configured.
+			 */
+			return -EIO;
+		}
+	}
 
 	return error;
 }
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index e0efc68..7baeeaf 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1843,7 +1843,7 @@
 	if (r)
 		goto out;
 
-	param->data_size = sizeof(*param);
+	param->data_size = offsetof(struct dm_ioctl, data);
 	r = fn(param, input_param_size);
 
 	if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) &&
@@ -1936,8 +1936,10 @@
 	int r = 0;
 	struct hash_cell *hc;
 
-	if (!md)
-		return -ENXIO;
+	if (!md) {
+		r = -ENXIO;
+		goto out;
+	}
 
 	/* The name and uuid can only be set once. */
 	mutex_lock(&dm_hash_cells_mutex);
@@ -1945,17 +1947,19 @@
 	mutex_unlock(&dm_hash_cells_mutex);
 	if (hc) {
 		DMERR("%s: already exported", dm_device_name(md));
-		return -ENXIO;
+		r = -ENXIO;
+		goto out;
 	}
 
 	r = dm_hash_insert(name, uuid, md);
 	if (r) {
 		DMERR("%s: could not bind to '%s'", dm_device_name(md), name);
-		return r;
+		goto out;
 	}
 
 	/* Let udev know we've changed. */
 	dm_kobject_uevent(md, KOBJ_CHANGE, dm_get_event_nr(md));
+out:
 	return r;
 }
 /**
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 05c35aa..2ff5f32 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -25,7 +25,7 @@
 /*
  * Construct a linear mapping: <dev_path> <offset>
  */
-static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+int dm_linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
 	struct linear_c *lc;
 	unsigned long long tmp;
@@ -66,14 +66,16 @@
 	kfree(lc);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(dm_linear_ctr);
 
-static void linear_dtr(struct dm_target *ti)
+void dm_linear_dtr(struct dm_target *ti)
 {
 	struct linear_c *lc = (struct linear_c *) ti->private;
 
 	dm_put_device(ti, lc->dev);
 	kfree(lc);
 }
+EXPORT_SYMBOL_GPL(dm_linear_dtr);
 
 static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector)
 {
@@ -92,14 +94,15 @@
 			linear_map_sector(ti, bio->bi_iter.bi_sector);
 }
 
-static int linear_map(struct dm_target *ti, struct bio *bio)
+int dm_linear_map(struct dm_target *ti, struct bio *bio)
 {
 	linear_map_bio(ti, bio);
 
 	return DM_MAPIO_REMAPPED;
 }
+EXPORT_SYMBOL_GPL(dm_linear_map);
 
-static void linear_status(struct dm_target *ti, status_type_t type,
+void dm_linear_status(struct dm_target *ti, status_type_t type,
 			  unsigned status_flags, char *result, unsigned maxlen)
 {
 	struct linear_c *lc = (struct linear_c *) ti->private;
@@ -115,8 +118,9 @@
 		break;
 	}
 }
+EXPORT_SYMBOL_GPL(dm_linear_status);
 
-static int linear_prepare_ioctl(struct dm_target *ti,
+int dm_linear_prepare_ioctl(struct dm_target *ti,
 		struct block_device **bdev, fmode_t *mode)
 {
 	struct linear_c *lc = (struct linear_c *) ti->private;
@@ -132,25 +136,27 @@
 		return 1;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(dm_linear_prepare_ioctl);
 
-static int linear_iterate_devices(struct dm_target *ti,
+int dm_linear_iterate_devices(struct dm_target *ti,
 				  iterate_devices_callout_fn fn, void *data)
 {
 	struct linear_c *lc = ti->private;
 
 	return fn(ti, lc->dev, lc->start, ti->len, data);
 }
+EXPORT_SYMBOL_GPL(dm_linear_iterate_devices);
 
 static struct target_type linear_target = {
 	.name   = "linear",
 	.version = {1, 2, 1},
 	.module = THIS_MODULE,
-	.ctr    = linear_ctr,
-	.dtr    = linear_dtr,
-	.map    = linear_map,
-	.status = linear_status,
-	.prepare_ioctl = linear_prepare_ioctl,
-	.iterate_devices = linear_iterate_devices,
+	.ctr    = dm_linear_ctr,
+	.dtr    = dm_linear_dtr,
+	.map    = dm_linear_map,
+	.status = dm_linear_status,
+	.prepare_ioctl  = dm_linear_prepare_ioctl,
+	.iterate_devices = dm_linear_iterate_devices,
 };
 
 int __init dm_linear_init(void)
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index 624589d..c8b513e 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -258,12 +258,12 @@
 		goto out;
 	sector++;
 
-	bio = bio_alloc(GFP_KERNEL, block->vec_cnt);
+	atomic_inc(&lc->io_blocks);
+	bio = bio_alloc(GFP_KERNEL, min(block->vec_cnt, BIO_MAX_PAGES));
 	if (!bio) {
 		DMERR("Couldn't alloc log bio");
 		goto error;
 	}
-	atomic_inc(&lc->io_blocks);
 	bio->bi_iter.bi_size = 0;
 	bio->bi_iter.bi_sector = sector;
 	bio->bi_bdev = lc->logdev->bdev;
@@ -280,7 +280,7 @@
 		if (ret != block->vecs[i].bv_len) {
 			atomic_inc(&lc->io_blocks);
 			submit_bio(WRITE, bio);
-			bio = bio_alloc(GFP_KERNEL, block->vec_cnt - i);
+			bio = bio_alloc(GFP_KERNEL, min(block->vec_cnt - i, BIO_MAX_PAGES));
 			if (!bio) {
 				DMERR("Couldn't alloc log bio");
 				goto error;
@@ -456,9 +456,9 @@
 		goto bad;
 	}
 
-	ret = -EINVAL;
 	lc->log_kthread = kthread_run(log_writes_kthread, lc, "log-write");
-	if (!lc->log_kthread) {
+	if (IS_ERR(lc->log_kthread)) {
+		ret = PTR_ERR(lc->log_kthread);
 		ti->error = "Couldn't alloc kthread";
 		dm_put_device(ti, lc->dev);
 		dm_put_device(ti, lc->logdev);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index cfa29f5..5b2ef96 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1220,10 +1220,10 @@
 {
 	struct pgpath *pgpath =
 		container_of(work, struct pgpath, activate_path.work);
+	struct request_queue *q = bdev_get_queue(pgpath->path.dev->bdev);
 
-	if (pgpath->is_active)
-		scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev),
-				 pg_init_done, pgpath);
+	if (pgpath->is_active && !blk_queue_dying(q))
+		scsi_dh_activate(q, pg_init_done, pgpath);
 	else
 		pg_init_done(pgpath, SCSI_DH_DEV_OFFLINED);
 }
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index f2a363a..115bd38 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1288,6 +1288,7 @@
 
 			dm_bio_restore(bd, bio);
 			bio_record->details.bi_bdev = NULL;
+			bio->bi_error = 0;
 
 			queue_bio(ms, bio, rw);
 			return DM_ENDIO_INCOMPLETE;
diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c
index 8289804..d5ea9f2 100644
--- a/drivers/md/dm-stats.c
+++ b/drivers/md/dm-stats.c
@@ -175,6 +175,7 @@
 	int cpu;
 	struct dm_stat *s = container_of(head, struct dm_stat, rcu_head);
 
+	kfree(s->histogram_boundaries);
 	kfree(s->program_id);
 	kfree(s->aux_data);
 	for_each_possible_cpu(cpu) {
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index cb5d0da..b3d78bb 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -11,6 +11,7 @@
 #include <linux/vmalloc.h>
 #include <linux/blkdev.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/slab.h>
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 911ada6..3b67afd 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -485,11 +485,11 @@
 	if (r < 0)
 		return r;
 
-	r = save_sm_roots(pmd);
+	r = dm_tm_pre_commit(pmd->tm);
 	if (r < 0)
 		return r;
 
-	r = dm_tm_pre_commit(pmd->tm);
+	r = save_sm_roots(pmd);
 	if (r < 0)
 		return r;
 
diff --git a/drivers/md/dm-verity-avb.c b/drivers/md/dm-verity-avb.c
new file mode 100644
index 0000000..727aacb
--- /dev/null
+++ b/drivers/md/dm-verity-avb.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2017 Google.
+ *
+ * This file is released under the GPLv2.
+ *
+ * Based on drivers/md/dm-verity-chromeos.c
+ */
+
+#include <linux/device-mapper.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+
+#define DM_MSG_PREFIX "verity-avb"
+
+/* Set via module parameters. */
+static char avb_vbmeta_device[64];
+static char avb_invalidate_on_error[4];
+
+static void invalidate_vbmeta_endio(struct bio *bio)
+{
+	if (bio->bi_error)
+		DMERR("invalidate_vbmeta_endio: error %d", bio->bi_error);
+	complete(bio->bi_private);
+}
+
+static int invalidate_vbmeta_submit(struct bio *bio,
+				    struct block_device *bdev,
+				    int rw, int access_last_sector,
+				    struct page *page)
+{
+	DECLARE_COMPLETION_ONSTACK(wait);
+
+	bio->bi_private = &wait;
+	bio->bi_end_io = invalidate_vbmeta_endio;
+	bio->bi_bdev = bdev;
+	bio->bi_rw = rw;
+
+	bio->bi_iter.bi_sector = 0;
+	if (access_last_sector) {
+		sector_t last_sector;
+
+		last_sector = (i_size_read(bdev->bd_inode)>>SECTOR_SHIFT) - 1;
+		bio->bi_iter.bi_sector = last_sector;
+	}
+	if (!bio_add_page(bio, page, PAGE_SIZE, 0)) {
+		DMERR("invalidate_vbmeta_submit: bio_add_page error");
+		return -EIO;
+	}
+
+	submit_bio(rw, bio);
+	/* Wait up to 2 seconds for completion or fail. */
+	if (!wait_for_completion_timeout(&wait, msecs_to_jiffies(2000)))
+		return -EIO;
+	return 0;
+}
+
+static int invalidate_vbmeta(dev_t vbmeta_devt)
+{
+	int ret = 0;
+	struct block_device *bdev;
+	struct bio *bio;
+	struct page *page;
+	fmode_t dev_mode;
+	/* Ensure we do synchronous unblocked I/O. We may also need
+	 * sync_bdev() on completion, but it really shouldn't.
+	 */
+	int rw = REQ_SYNC | REQ_SOFTBARRIER | REQ_NOIDLE;
+	int access_last_sector = 0;
+
+	DMINFO("invalidate_vbmeta: acting on device %d:%d",
+	       MAJOR(vbmeta_devt), MINOR(vbmeta_devt));
+
+	/* First we open the device for reading. */
+	dev_mode = FMODE_READ | FMODE_EXCL;
+	bdev = blkdev_get_by_dev(vbmeta_devt, dev_mode,
+				 invalidate_vbmeta);
+	if (IS_ERR(bdev)) {
+		DMERR("invalidate_kernel: could not open device for reading");
+		dev_mode = 0;
+		ret = -ENOENT;
+		goto failed_to_read;
+	}
+
+	bio = bio_alloc(GFP_NOIO, 1);
+	if (!bio) {
+		ret = -ENOMEM;
+		goto failed_bio_alloc;
+	}
+
+	page = alloc_page(GFP_NOIO);
+	if (!page) {
+		ret = -ENOMEM;
+		goto failed_to_alloc_page;
+	}
+
+	access_last_sector = 0;
+	ret = invalidate_vbmeta_submit(bio, bdev, rw, access_last_sector, page);
+	if (ret) {
+		DMERR("invalidate_vbmeta: error reading");
+		goto failed_to_submit_read;
+	}
+
+	/* We have a page. Let's make sure it looks right. */
+	if (memcmp("AVB0", page_address(page), 4) == 0) {
+		/* Stamp it. */
+		memcpy(page_address(page), "AVE0", 4);
+		DMINFO("invalidate_vbmeta: found vbmeta partition");
+	} else {
+		/* Could be this is on a AVB footer, check. Also, since the
+		 * AVB footer is in the last 64 bytes, adjust for the fact that
+		 * we're dealing with 512-byte sectors.
+		 */
+		size_t offset = (1<<SECTOR_SHIFT) - 64;
+
+		access_last_sector = 1;
+		ret = invalidate_vbmeta_submit(bio, bdev, rw,
+					       access_last_sector, page);
+		if (ret) {
+			DMERR("invalidate_vbmeta: error reading");
+			goto failed_to_submit_read;
+		}
+		if (memcmp("AVBf", page_address(page) + offset, 4) != 0) {
+			DMERR("invalidate_vbmeta on non-vbmeta partition");
+			ret = -EINVAL;
+			goto invalid_header;
+		}
+		/* Stamp it. */
+		memcpy(page_address(page) + offset, "AVE0", 4);
+		DMINFO("invalidate_vbmeta: found vbmeta footer partition");
+	}
+
+	/* Now rewrite the changed page - the block dev was being
+	 * changed on read. Let's reopen here.
+	 */
+	blkdev_put(bdev, dev_mode);
+	dev_mode = FMODE_WRITE | FMODE_EXCL;
+	bdev = blkdev_get_by_dev(vbmeta_devt, dev_mode,
+				 invalidate_vbmeta);
+	if (IS_ERR(bdev)) {
+		DMERR("invalidate_vbmeta: could not open device for writing");
+		dev_mode = 0;
+		ret = -ENOENT;
+		goto failed_to_write;
+	}
+
+	/* We re-use the same bio to do the write after the read. Need to reset
+	 * it to initialize bio->bi_remaining.
+	 */
+	bio_reset(bio);
+
+	rw |= REQ_WRITE;
+	ret = invalidate_vbmeta_submit(bio, bdev, rw, access_last_sector, page);
+	if (ret) {
+		DMERR("invalidate_vbmeta: error writing");
+		goto failed_to_submit_write;
+	}
+
+	DMERR("invalidate_vbmeta: completed.");
+	ret = 0;
+failed_to_submit_write:
+failed_to_write:
+invalid_header:
+	__free_page(page);
+failed_to_submit_read:
+	/* Technically, we'll leak a page with the pending bio, but
+	 * we're about to reboot anyway.
+	 */
+failed_to_alloc_page:
+	bio_put(bio);
+failed_bio_alloc:
+	if (dev_mode)
+		blkdev_put(bdev, dev_mode);
+failed_to_read:
+	return ret;
+}
+
+void dm_verity_avb_error_handler(void)
+{
+	dev_t dev;
+
+	DMINFO("AVB error handler called for %s", avb_vbmeta_device);
+
+	if (strcmp(avb_invalidate_on_error, "yes") != 0) {
+		DMINFO("Not configured to invalidate");
+		return;
+	}
+
+	if (avb_vbmeta_device[0] == '\0') {
+		DMERR("avb_vbmeta_device parameter not set");
+		goto fail_no_dev;
+	}
+
+	dev = name_to_dev_t(avb_vbmeta_device);
+	if (!dev) {
+		DMERR("No matching partition for device: %s",
+		      avb_vbmeta_device);
+		goto fail_no_dev;
+	}
+
+	invalidate_vbmeta(dev);
+
+fail_no_dev:
+	;
+}
+
+static int __init dm_verity_avb_init(void)
+{
+	DMINFO("AVB error handler initialized with vbmeta device: %s",
+	       avb_vbmeta_device);
+	return 0;
+}
+
+static void __exit dm_verity_avb_exit(void)
+{
+}
+
+module_init(dm_verity_avb_init);
+module_exit(dm_verity_avb_exit);
+
+MODULE_AUTHOR("David Zeuthen <zeuthen@google.com>");
+MODULE_DESCRIPTION("AVB-specific error handler for dm-verity");
+MODULE_LICENSE("GPL");
+
+/* Declare parameter with no module prefix */
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX	"androidboot.vbmeta."
+module_param_string(device, avb_vbmeta_device, sizeof(avb_vbmeta_device), 0);
+module_param_string(invalidate_on_error, avb_invalidate_on_error,
+		    sizeof(avb_invalidate_on_error), 0);
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index 5c5d30c..e34cf53 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -233,8 +233,12 @@
 	if (v->mode == DM_VERITY_MODE_LOGGING)
 		return 0;
 
-	if (v->mode == DM_VERITY_MODE_RESTART)
+	if (v->mode == DM_VERITY_MODE_RESTART) {
+#ifdef CONFIG_DM_VERITY_AVB
+		dm_verity_avb_error_handler();
+#endif
 		kernel_restart("dm-verity device corrupted");
+	}
 
 	return 1;
 }
@@ -501,6 +505,7 @@
 		container_of(work, struct dm_verity_prefetch_work, work);
 	struct dm_verity *v = pw->v;
 	int i;
+	sector_t prefetch_size;
 
 	for (i = v->levels - 2; i >= 0; i--) {
 		sector_t hash_block_start;
@@ -523,8 +528,14 @@
 				hash_block_end = v->hash_blocks - 1;
 		}
 no_prefetch_cluster:
+		// for emmc, it is more efficient to send bigger read
+		prefetch_size = max((sector_t)CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE,
+			hash_block_end - hash_block_start + 1);
+		if ((hash_block_start + prefetch_size) >= (v->hash_start + v->hash_blocks)) {
+			prefetch_size = hash_block_end - hash_block_start + 1;
+		}
 		dm_bufio_prefetch(v->bufio, hash_block_start,
-				  hash_block_end - hash_block_start + 1);
+				  prefetch_size);
 	}
 
 	kfree(pw);
@@ -551,7 +562,7 @@
  * Bio map function. It allocates dm_verity_io structure and bio vector and
  * fills them. Then it issues prefetches and the I/O.
  */
-static int verity_map(struct dm_target *ti, struct bio *bio)
+int verity_map(struct dm_target *ti, struct bio *bio)
 {
 	struct dm_verity *v = ti->private;
 	struct dm_verity_io *io;
@@ -592,11 +603,12 @@
 
 	return DM_MAPIO_SUBMITTED;
 }
+EXPORT_SYMBOL_GPL(verity_map);
 
 /*
  * Status: V (valid) or C (corruption found)
  */
-static void verity_status(struct dm_target *ti, status_type_t type,
+void verity_status(struct dm_target *ti, status_type_t type,
 			  unsigned status_flags, char *result, unsigned maxlen)
 {
 	struct dm_verity *v = ti->private;
@@ -655,8 +667,9 @@
 		break;
 	}
 }
+EXPORT_SYMBOL_GPL(verity_status);
 
-static int verity_prepare_ioctl(struct dm_target *ti,
+int verity_prepare_ioctl(struct dm_target *ti,
 		struct block_device **bdev, fmode_t *mode)
 {
 	struct dm_verity *v = ti->private;
@@ -668,16 +681,18 @@
 		return 1;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(verity_prepare_ioctl);
 
-static int verity_iterate_devices(struct dm_target *ti,
+int verity_iterate_devices(struct dm_target *ti,
 				  iterate_devices_callout_fn fn, void *data)
 {
 	struct dm_verity *v = ti->private;
 
 	return fn(ti, v->data_dev, v->data_start, ti->len, data);
 }
+EXPORT_SYMBOL_GPL(verity_iterate_devices);
 
-static void verity_io_hints(struct dm_target *ti, struct queue_limits *limits)
+void verity_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
 	struct dm_verity *v = ti->private;
 
@@ -689,8 +704,9 @@
 
 	blk_limits_io_min(limits, limits->logical_block_size);
 }
+EXPORT_SYMBOL_GPL(verity_io_hints);
 
-static void verity_dtr(struct dm_target *ti)
+void verity_dtr(struct dm_target *ti)
 {
 	struct dm_verity *v = ti->private;
 
@@ -719,6 +735,7 @@
 
 	kfree(v);
 }
+EXPORT_SYMBOL_GPL(verity_dtr);
 
 static int verity_alloc_zero_digest(struct dm_verity *v)
 {
@@ -817,7 +834,7 @@
  *	<digest>
  *	<salt>		Hex string or "-" if no salt.
  */
-static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
+int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
 {
 	struct dm_verity *v;
 	struct dm_arg_set as;
@@ -1053,6 +1070,7 @@
 
 	return r;
 }
+EXPORT_SYMBOL_GPL(verity_ctr);
 
 static struct target_type verity_target = {
 	.name		= "verity",
diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h
index fb419f4..a90d1d4 100644
--- a/drivers/md/dm-verity.h
+++ b/drivers/md/dm-verity.h
@@ -126,4 +126,15 @@
 extern int verity_hash_for_block(struct dm_verity *v, struct dm_verity_io *io,
 				 sector_t block, u8 *digest, bool *is_zero);
 
+extern void verity_status(struct dm_target *ti, status_type_t type,
+			unsigned status_flags, char *result, unsigned maxlen);
+extern int verity_prepare_ioctl(struct dm_target *ti,
+                struct block_device **bdev, fmode_t *mode);
+extern int verity_iterate_devices(struct dm_target *ti,
+				iterate_devices_callout_fn fn, void *data);
+extern void verity_io_hints(struct dm_target *ti, struct queue_limits *limits);
+extern void verity_dtr(struct dm_target *ti);
+extern int verity_ctr(struct dm_target *ti, unsigned argc, char **argv);
+extern int verity_map(struct dm_target *ti, struct bio *bio);
+extern void dm_verity_avb_error_handler(void);
 #endif /* DM_VERITY_H */
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index c338aeb..320eb3c 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1467,11 +1467,65 @@
 }
 EXPORT_SYMBOL_GPL(dm_accept_partial_bio);
 
+/*
+ * Flush current->bio_list when the target map method blocks.
+ * This fixes deadlocks in snapshot and possibly in other targets.
+ */
+struct dm_offload {
+	struct blk_plug plug;
+	struct blk_plug_cb cb;
+};
+
+static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule)
+{
+	struct dm_offload *o = container_of(cb, struct dm_offload, cb);
+	struct bio_list list;
+	struct bio *bio;
+	int i;
+
+	INIT_LIST_HEAD(&o->cb.list);
+
+	if (unlikely(!current->bio_list))
+		return;
+
+	for (i = 0; i < 2; i++) {
+		list = current->bio_list[i];
+		bio_list_init(&current->bio_list[i]);
+
+		while ((bio = bio_list_pop(&list))) {
+			struct bio_set *bs = bio->bi_pool;
+			if (unlikely(!bs) || bs == fs_bio_set) {
+				bio_list_add(&current->bio_list[i], bio);
+				continue;
+			}
+
+			spin_lock(&bs->rescue_lock);
+			bio_list_add(&bs->rescue_list, bio);
+			queue_work(bs->rescue_workqueue, &bs->rescue_work);
+			spin_unlock(&bs->rescue_lock);
+		}
+	}
+}
+
+static void dm_offload_start(struct dm_offload *o)
+{
+	blk_start_plug(&o->plug);
+	o->cb.callback = flush_current_bio_list;
+	list_add(&o->cb.list, &current->plug->cb_list);
+}
+
+static void dm_offload_end(struct dm_offload *o)
+{
+	list_del(&o->cb.list);
+	blk_finish_plug(&o->plug);
+}
+
 static void __map_bio(struct dm_target_io *tio)
 {
 	int r;
 	sector_t sector;
 	struct mapped_device *md;
+	struct dm_offload o;
 	struct bio *clone = &tio->clone;
 	struct dm_target *ti = tio->ti;
 
@@ -1484,7 +1538,11 @@
 	 */
 	atomic_inc(&tio->io->io_count);
 	sector = clone->bi_iter.bi_sector;
+
+	dm_offload_start(&o);
 	r = ti->type->map(ti, clone);
+	dm_offload_end(&o);
+
 	if (r == DM_MAPIO_REMAPPED) {
 		/* the bio has been remapped so dispatch it */
 
@@ -2260,8 +2318,6 @@
 	if (md->bs)
 		bioset_free(md->bs);
 
-	cleanup_srcu_struct(&md->io_barrier);
-
 	if (md->disk) {
 		spin_lock(&_minor_lock);
 		md->disk->private_data = NULL;
@@ -2273,6 +2329,8 @@
 	if (md->queue)
 		blk_cleanup_queue(md->queue);
 
+	cleanup_srcu_struct(&md->io_barrier);
+
 	if (md->bdev) {
 		bdput(md->bdev);
 		md->bdev = NULL;
@@ -2869,6 +2927,7 @@
 
 static void __dm_destroy(struct mapped_device *md, bool wait)
 {
+	struct request_queue *q = dm_get_md_queue(md);
 	struct dm_table *map;
 	int srcu_idx;
 
@@ -2879,6 +2938,10 @@
 	set_bit(DMF_FREEING, &md->flags);
 	spin_unlock(&_minor_lock);
 
+	spin_lock_irq(q->queue_lock);
+	queue_flag_set(QUEUE_FLAG_DYING, q);
+	spin_unlock_irq(q->queue_lock);
+
 	if (dm_request_based(md) && md->kworker_task)
 		flush_kthread_worker(&md->kworker);
 
@@ -3078,7 +3141,8 @@
  * Caller must hold md->suspend_lock
  */
 static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
-			unsigned suspend_flags, int interruptible)
+			unsigned suspend_flags, int interruptible,
+			int dmf_suspended_flag)
 {
 	bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
 	bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG;
@@ -3145,6 +3209,8 @@
 	 * to finish.
 	 */
 	r = dm_wait_for_completion(md, interruptible);
+	if (!r)
+		set_bit(dmf_suspended_flag, &md->flags);
 
 	if (noflush)
 		clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
@@ -3206,12 +3272,10 @@
 
 	map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
 
-	r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE);
+	r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE, DMF_SUSPENDED);
 	if (r)
 		goto out_unlock;
 
-	set_bit(DMF_SUSPENDED, &md->flags);
-
 	dm_table_postsuspend_targets(map);
 
 out_unlock:
@@ -3244,10 +3308,11 @@
 
 int dm_resume(struct mapped_device *md)
 {
-	int r = -EINVAL;
+	int r;
 	struct dm_table *map = NULL;
 
 retry:
+	r = -EINVAL;
 	mutex_lock_nested(&md->suspend_lock, SINGLE_DEPTH_NESTING);
 
 	if (!dm_suspended_md(md))
@@ -3271,8 +3336,6 @@
 		goto out;
 
 	clear_bit(DMF_SUSPENDED, &md->flags);
-
-	r = 0;
 out:
 	mutex_unlock(&md->suspend_lock);
 
@@ -3305,9 +3368,8 @@
 	 * would require changing .presuspend to return an error -- avoid this
 	 * until there is a need for more elaborate variants of internal suspend.
 	 */
-	(void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE);
-
-	set_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
+	(void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE,
+			    DMF_SUSPENDED_INTERNALLY);
 
 	dm_table_postsuspend_targets(map);
 }
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index f217004..7edcf97 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -78,6 +78,8 @@
 void dm_table_free_md_mempools(struct dm_table *t);
 struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t);
 
+void dm_lock_md_type(struct mapped_device *md);
+void dm_unlock_md_type(struct mapped_device *md);
 void dm_set_md_type(struct mapped_device *md, unsigned type);
 unsigned dm_get_md_type(struct mapped_device *md);
 struct target_type *dm_get_immutable_target_type(struct mapped_device *md);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index b7fe7e9..6ba3227 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -52,18 +52,26 @@
 	return conf->disks + lo;
 }
 
+/*
+ * In linear_congested() conf->raid_disks is used as a copy of
+ * mddev->raid_disks to iterate conf->disks[], because conf->raid_disks
+ * and conf->disks[] are created in linear_conf(), they are always
+ * consitent with each other, but mddev->raid_disks does not.
+ */
 static int linear_congested(struct mddev *mddev, int bits)
 {
 	struct linear_conf *conf;
 	int i, ret = 0;
 
-	conf = mddev->private;
+	rcu_read_lock();
+	conf = rcu_dereference(mddev->private);
 
-	for (i = 0; i < mddev->raid_disks && !ret ; i++) {
+	for (i = 0; i < conf->raid_disks && !ret ; i++) {
 		struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
 		ret |= bdi_congested(&q->backing_dev_info, bits);
 	}
 
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -143,6 +151,19 @@
 			conf->disks[i-1].end_sector +
 			conf->disks[i].rdev->sectors;
 
+	/*
+	 * conf->raid_disks is copy of mddev->raid_disks. The reason to
+	 * keep a copy of mddev->raid_disks in struct linear_conf is,
+	 * mddev->raid_disks may not be consistent with pointers number of
+	 * conf->disks[] when it is updated in linear_add() and used to
+	 * iterate old conf->disks[] earray in linear_congested().
+	 * Here conf->raid_disks is always consitent with number of
+	 * pointers in conf->disks[] array, and mddev->private is updated
+	 * with rcu_assign_pointer() in linear_addr(), such race can be
+	 * avoided.
+	 */
+	conf->raid_disks = raid_disks;
+
 	return conf;
 
 out:
@@ -195,15 +216,23 @@
 	if (!newconf)
 		return -ENOMEM;
 
+	/* newconf->raid_disks already keeps a copy of * the increased
+	 * value of mddev->raid_disks, WARN_ONCE() is just used to make
+	 * sure of this. It is possible that oldconf is still referenced
+	 * in linear_congested(), therefore kfree_rcu() is used to free
+	 * oldconf until no one uses it anymore.
+	 */
 	mddev_suspend(mddev);
-	oldconf = mddev->private;
+	oldconf = rcu_dereference(mddev->private);
 	mddev->raid_disks++;
-	mddev->private = newconf;
+	WARN_ONCE(mddev->raid_disks != newconf->raid_disks,
+		"copied raid_disks doesn't match mddev->raid_disks");
+	rcu_assign_pointer(mddev->private, newconf);
 	md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
 	set_capacity(mddev->gendisk, mddev->array_sectors);
 	mddev_resume(mddev);
 	revalidate_disk(mddev->gendisk);
-	kfree(oldconf);
+	kfree_rcu(oldconf, rcu);
 	return 0;
 }
 
diff --git a/drivers/md/linear.h b/drivers/md/linear.h
index b685ddd..8d392e6 100644
--- a/drivers/md/linear.h
+++ b/drivers/md/linear.h
@@ -10,6 +10,7 @@
 {
 	struct rcu_head		rcu;
 	sector_t		array_sectors;
+	int			raid_disks; /* a copy of mddev->raid_disks */
 	struct dev_info		disks[0];
 };
 #endif
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c57fdf8..0a856cb 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1866,7 +1866,7 @@
 	}
 	sb = page_address(rdev->sb_page);
 	sb->data_size = cpu_to_le64(num_sectors);
-	sb->super_offset = rdev->sb_start;
+	sb->super_offset = cpu_to_le64(rdev->sb_start);
 	sb->sb_csum = calc_sb_1_csum(sb);
 	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
 		       rdev->sb_page);
@@ -2273,7 +2273,7 @@
 	/* Check if any mddev parameters have changed */
 	if ((mddev->dev_sectors != le64_to_cpu(sb->size)) ||
 	    (mddev->reshape_position != le64_to_cpu(sb->reshape_position)) ||
-	    (mddev->layout != le64_to_cpu(sb->layout)) ||
+	    (mddev->layout != le32_to_cpu(sb->layout)) ||
 	    (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) ||
 	    (mddev->chunk_sectors != le32_to_cpu(sb->chunksize)))
 		return true;
@@ -6771,7 +6771,7 @@
 		/* need to ensure recovery thread has run */
 		wait_event_interruptible_timeout(mddev->sb_wait,
 						 !test_bit(MD_RECOVERY_NEEDED,
-							   &mddev->flags),
+							   &mddev->recovery),
 						 msecs_to_jiffies(5000));
 	if (cmd == STOP_ARRAY || cmd == STOP_ARRAY_RO) {
 		/* Need to flush page cache, and ensure no-one else opens
@@ -7572,16 +7572,12 @@
 
 int md_setup_cluster(struct mddev *mddev, int nodes)
 {
-	int err;
-
-	err = request_module("md-cluster");
-	if (err) {
-		pr_err("md-cluster module not found.\n");
-		return -ENOENT;
-	}
-
+	if (!md_cluster_ops)
+		request_module("md-cluster");
 	spin_lock(&pers_lock);
+	/* ensure module won't be unloaded */
 	if (!md_cluster_ops || !try_module_get(md_cluster_mod)) {
+		pr_err("can't find md-cluster module or get it's reference.\n");
 		spin_unlock(&pers_lock);
 		return -ENOENT;
 	}
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
index b1ced58..a1a6820 100644
--- a/drivers/md/persistent-data/dm-btree.c
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -887,8 +887,12 @@
 		else
 			*result_key = le64_to_cpu(ro_node(s)->keys[0]);
 
-		if (next_block || flags & INTERNAL_NODE)
-			block = value64(ro_node(s), i);
+		if (next_block || flags & INTERNAL_NODE) {
+			if (find_highest)
+				block = value64(ro_node(s), i);
+			else
+				block = value64(ro_node(s), 0);
+		}
 
 	} while (flags & INTERNAL_NODE);
 
diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c
index ebb280a..32adf6b 100644
--- a/drivers/md/persistent-data/dm-space-map-disk.c
+++ b/drivers/md/persistent-data/dm-space-map-disk.c
@@ -142,10 +142,23 @@
 
 static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b)
 {
+	int r;
+	uint32_t old_count;
 	enum allocation_event ev;
 	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
-	return sm_ll_dec(&smd->ll, b, &ev);
+	r = sm_ll_dec(&smd->ll, b, &ev);
+	if (!r && (ev == SM_FREE)) {
+		/*
+		 * It's only free if it's also free in the last
+		 * transaction.
+		 */
+		r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+		if (!r && !old_count)
+			smd->nr_allocated_this_transaction--;
+	}
+
+	return r;
 }
 
 static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c
index 7e44005..20557e2 100644
--- a/drivers/md/persistent-data/dm-space-map-metadata.c
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -775,16 +775,14 @@
 	memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
 
 	r = sm_ll_new_metadata(&smm->ll, tm);
-	if (r)
-		return r;
-
-	if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
-		nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
-	r = sm_ll_extend(&smm->ll, nr_blocks);
-	if (r)
-		return r;
-
+	if (!r) {
+		if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
+			nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
+		r = sm_ll_extend(&smm->ll, nr_blocks);
+	}
 	memcpy(&smm->sm, &ops, sizeof(smm->sm));
+	if (r)
+		return r;
 
 	/*
 	 * Now we need to update the newly created data structures with the
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 515554c..d81be5e 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -570,7 +570,7 @@
 			if (best_dist_disk < 0) {
 				if (is_badblock(rdev, this_sector, sectors,
 						&first_bad, &bad_sectors)) {
-					if (first_bad < this_sector)
+					if (first_bad <= this_sector)
 						/* Cannot use this */
 						continue;
 					best_good_sectors = first_bad - this_sector;
@@ -877,7 +877,8 @@
 				     ((conf->start_next_window <
 				       conf->next_resync + RESYNC_SECTORS) &&
 				      current->bio_list &&
-				      !bio_list_empty(current->bio_list))),
+				     (!bio_list_empty(&current->bio_list[0]) ||
+				      !bio_list_empty(&current->bio_list[1])))),
 				    conf->resync_lock);
 		conf->nr_waiting--;
 	}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index ebb0dd6..e5ee4e9 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -946,7 +946,8 @@
 				    !conf->barrier ||
 				    (conf->nr_pending &&
 				     current->bio_list &&
-				     !bio_list_empty(current->bio_list)),
+				     (!bio_list_empty(&current->bio_list[0]) ||
+				      !bio_list_empty(&current->bio_list[1]))),
 				    conf->resync_lock);
 		conf->nr_waiting--;
 	}
@@ -1072,6 +1073,8 @@
 	int max_sectors;
 	int sectors;
 
+	md_write_start(mddev, bio);
+
 	/*
 	 * Register the new request and wait if the reconstruction
 	 * thread has put up a bar for new requests.
@@ -1455,8 +1458,6 @@
 		return;
 	}
 
-	md_write_start(mddev, bio);
-
 	do {
 
 		/*
@@ -1477,7 +1478,25 @@
 			split = bio;
 		}
 
+		/*
+		 * If a bio is splitted, the first part of bio will pass
+		 * barrier but the bio is queued in current->bio_list (see
+		 * generic_make_request). If there is a raise_barrier() called
+		 * here, the second part of bio can't pass barrier. But since
+		 * the first part bio isn't dispatched to underlaying disks
+		 * yet, the barrier is never released, hence raise_barrier will
+		 * alays wait. We have a deadlock.
+		 * Note, this only happens in read path. For write path, the
+		 * first part of bio is dispatched in a schedule() call
+		 * (because of blk plug) or offloaded to raid10d.
+		 * Quitting from the function immediately can change the bio
+		 * order queued in bio_list and avoid the deadlock.
+		 */
 		__make_request(mddev, split);
+		if (split != bio && bio_data_dir(bio) == READ) {
+			generic_make_request(bio);
+			break;
+		}
 	} while (split != bio);
 
 	/* In case raid10d snuck in to freeze_array */
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 10ce885..4384b46 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2232,6 +2232,10 @@
 		err = -ENOMEM;
 
 	mutex_unlock(&conf->cache_size_mutex);
+
+	conf->slab_cache = sc;
+	conf->active_name = 1-conf->active_name;
+
 	/* Step 4, return new stripes to service */
 	while(!list_empty(&newstripes)) {
 		nsh = list_entry(newstripes.next, struct stripe_head, lru);
@@ -2249,8 +2253,6 @@
 	}
 	/* critical section pass, GFP_NOIO no longer needed */
 
-	conf->slab_cache = sc;
-	conf->active_name = 1-conf->active_name;
 	if (!err)
 		conf->pool_size = newsize;
 	return err;
@@ -6980,6 +6982,15 @@
 			stripe = (stripe | (stripe-1)) + 1;
 		mddev->queue->limits.discard_alignment = stripe;
 		mddev->queue->limits.discard_granularity = stripe;
+
+		/*
+		 * We use 16-bit counter of active stripes in bi_phys_segments
+		 * (minus one for over-loaded initialization)
+		 */
+		blk_queue_max_hw_sectors(mddev->queue, 0xfffe * STRIPE_SECTORS);
+		blk_queue_max_discard_sectors(mddev->queue,
+					      0xfffe * STRIPE_SECTORS);
+
 		/*
 		 * unaligned part of discard request will be ignored, so can't
 		 * guarantee discard_zeroes_data
diff --git a/drivers/media/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb-core/dvb_ringbuffer.c
index 1100e98..7df7fb3 100644
--- a/drivers/media/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb-core/dvb_ringbuffer.c
@@ -55,7 +55,13 @@
 
 int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
 {
-	return (rbuf->pread==rbuf->pwrite);
+	/* smp_load_acquire() to load write pointer on reader side
+	 * this pairs with smp_store_release() in dvb_ringbuffer_write(),
+	 * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
+	 *
+	 * for memory barriers also see Documentation/circular-buffers.txt
+	 */
+	return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
 }
 
 
@@ -64,7 +70,12 @@
 {
 	ssize_t free;
 
-	free = rbuf->pread - rbuf->pwrite;
+	/* ACCESS_ONCE() to load read pointer on writer side
+	 * this pairs with smp_store_release() in dvb_ringbuffer_read(),
+	 * dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(),
+	 * or dvb_ringbuffer_reset()
+	 */
+	free = ACCESS_ONCE(rbuf->pread) - rbuf->pwrite;
 	if (free <= 0)
 		free += rbuf->size;
 	return free-1;
@@ -76,7 +87,11 @@
 {
 	ssize_t avail;
 
-	avail = rbuf->pwrite - rbuf->pread;
+	/* smp_load_acquire() to load write pointer on reader side
+	 * this pairs with smp_store_release() in dvb_ringbuffer_write(),
+	 * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
+	 */
+	avail = smp_load_acquire(&rbuf->pwrite) - rbuf->pread;
 	if (avail < 0)
 		avail += rbuf->size;
 	return avail;
@@ -86,14 +101,25 @@
 
 void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
 {
-	rbuf->pread = rbuf->pwrite;
+	/* dvb_ringbuffer_flush() counts as read operation
+	 * smp_load_acquire() to load write pointer
+	 * smp_store_release() to update read pointer, this ensures that the
+	 * correct pointer is visible for subsequent dvb_ringbuffer_free()
+	 * calls on other cpu cores
+	 */
+	smp_store_release(&rbuf->pread, smp_load_acquire(&rbuf->pwrite));
 	rbuf->error = 0;
 }
 EXPORT_SYMBOL(dvb_ringbuffer_flush);
 
 void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
 {
-	rbuf->pread = rbuf->pwrite = 0;
+	/* dvb_ringbuffer_reset() counts as read and write operation
+	 * smp_store_release() to update read pointer
+	 */
+	smp_store_release(&rbuf->pread, 0);
+	/* smp_store_release() to update write pointer */
+	smp_store_release(&rbuf->pwrite, 0);
 	rbuf->error = 0;
 }
 
@@ -119,12 +145,17 @@
 			return -EFAULT;
 		buf += split;
 		todo -= split;
-		rbuf->pread = 0;
+		/* smp_store_release() for read pointer update to ensure
+		 * that buf is not overwritten until read is complete,
+		 * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
+		 */
+		smp_store_release(&rbuf->pread, 0);
 	}
 	if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
 		return -EFAULT;
 
-	rbuf->pread = (rbuf->pread + todo) % rbuf->size;
+	/* smp_store_release() to update read pointer, see above */
+	smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size);
 
 	return len;
 }
@@ -139,11 +170,16 @@
 		memcpy(buf, rbuf->data+rbuf->pread, split);
 		buf += split;
 		todo -= split;
-		rbuf->pread = 0;
+		/* smp_store_release() for read pointer update to ensure
+		 * that buf is not overwritten until read is complete,
+		 * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
+		 */
+		smp_store_release(&rbuf->pread, 0);
 	}
 	memcpy(buf, rbuf->data+rbuf->pread, todo);
 
-	rbuf->pread = (rbuf->pread + todo) % rbuf->size;
+	/* smp_store_release() to update read pointer, see above */
+	smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size);
 }
 
 
@@ -158,10 +194,16 @@
 		memcpy(rbuf->data+rbuf->pwrite, buf, split);
 		buf += split;
 		todo -= split;
-		rbuf->pwrite = 0;
+		/* smp_store_release() for write pointer update to ensure that
+		 * written data is visible on other cpu cores before the pointer
+		 * update, this pairs with smp_load_acquire() in
+		 * dvb_ringbuffer_empty() or dvb_ringbuffer_avail()
+		 */
+		smp_store_release(&rbuf->pwrite, 0);
 	}
 	memcpy(rbuf->data+rbuf->pwrite, buf, todo);
-	rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
+	/* smp_store_release() for write pointer update, see above */
+	smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size);
 
 	return len;
 }
@@ -181,12 +223,18 @@
 			return len - todo;
 		buf += split;
 		todo -= split;
-		rbuf->pwrite = 0;
+		/* smp_store_release() for write pointer update to ensure that
+		 * written data is visible on other cpu cores before the pointer
+		 * update, this pairs with smp_load_acquire() in
+		 * dvb_ringbuffer_empty() or dvb_ringbuffer_avail()
+		 */
+		smp_store_release(&rbuf->pwrite, 0);
 	}
 	status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo);
 	if (status)
 		return len - todo;
-	rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
+	/* smp_store_release() for write pointer update, see above */
+	smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size);
 
 	return len;
 }
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 292c947..310e4b8 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -264,7 +264,7 @@
 config DVB_TDA10071
 	tristate "NXP TDA10071"
 	depends on DVB_CORE && I2C
-	select REGMAP
+	select REGMAP_I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y when you want to support this frontend.
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c
index fdffb2f..107853b0 100644
--- a/drivers/media/dvb-frontends/cxd2841er.c
+++ b/drivers/media/dvb-frontends/cxd2841er.c
@@ -2678,7 +2678,9 @@
 			FE_CAN_MUTE_TS |
 			FE_CAN_2G_MODULATION,
 		.frequency_min = 42000000,
-		.frequency_max = 1002000000
+		.frequency_max = 1002000000,
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000
 	},
 	.init = cxd2841er_init_tc,
 	.sleep = cxd2841er_sleep_tc,
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c
index cfc005e..7fc72de 100644
--- a/drivers/media/dvb-frontends/mb86a20s.c
+++ b/drivers/media/dvb-frontends/mb86a20s.c
@@ -71,25 +71,27 @@
 };
 
 static struct regdata mb86a20s_init2[] = {
-	{ 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 },
+	{ 0x50, 0xd1 }, { 0x51, 0x22 },
+	{ 0x39, 0x01 },
+	{ 0x71, 0x00 },
 	{ 0x3b, 0x21 },
-	{ 0x3c, 0x38 },
+	{ 0x3c, 0x3a },
 	{ 0x01, 0x0d },
-	{ 0x04, 0x08 }, { 0x05, 0x03 },
+	{ 0x04, 0x08 }, { 0x05, 0x05 },
 	{ 0x04, 0x0e }, { 0x05, 0x00 },
-	{ 0x04, 0x0f }, { 0x05, 0x37 },
-	{ 0x04, 0x0b }, { 0x05, 0x78 },
+	{ 0x04, 0x0f }, { 0x05, 0x14 },
+	{ 0x04, 0x0b }, { 0x05, 0x8c },
 	{ 0x04, 0x00 }, { 0x05, 0x00 },
-	{ 0x04, 0x01 }, { 0x05, 0x1e },
-	{ 0x04, 0x02 }, { 0x05, 0x07 },
-	{ 0x04, 0x03 }, { 0x05, 0xd0 },
+	{ 0x04, 0x01 }, { 0x05, 0x07 },
+	{ 0x04, 0x02 }, { 0x05, 0x0f },
+	{ 0x04, 0x03 }, { 0x05, 0xa0 },
 	{ 0x04, 0x09 }, { 0x05, 0x00 },
 	{ 0x04, 0x0a }, { 0x05, 0xff },
-	{ 0x04, 0x27 }, { 0x05, 0x00 },
+	{ 0x04, 0x27 }, { 0x05, 0x64 },
 	{ 0x04, 0x28 }, { 0x05, 0x00 },
-	{ 0x04, 0x1e }, { 0x05, 0x00 },
-	{ 0x04, 0x29 }, { 0x05, 0x64 },
-	{ 0x04, 0x32 }, { 0x05, 0x02 },
+	{ 0x04, 0x1e }, { 0x05, 0xff },
+	{ 0x04, 0x29 }, { 0x05, 0x0a },
+	{ 0x04, 0x32 }, { 0x05, 0x0a },
 	{ 0x04, 0x14 }, { 0x05, 0x02 },
 	{ 0x04, 0x04 }, { 0x05, 0x00 },
 	{ 0x04, 0x05 }, { 0x05, 0x22 },
@@ -97,8 +99,6 @@
 	{ 0x04, 0x07 }, { 0x05, 0xd8 },
 	{ 0x04, 0x12 }, { 0x05, 0x00 },
 	{ 0x04, 0x13 }, { 0x05, 0xff },
-	{ 0x04, 0x15 }, { 0x05, 0x4e },
-	{ 0x04, 0x16 }, { 0x05, 0x20 },
 
 	/*
 	 * On this demod, when the bit count reaches the count below,
@@ -152,42 +152,36 @@
 	{ 0x50, 0x51 }, { 0x51, 0x04 },		/* MER symbol 4 */
 	{ 0x45, 0x04 },				/* CN symbol 4 */
 	{ 0x48, 0x04 },				/* CN manual mode */
-
+	{ 0x50, 0xd5 }, { 0x51, 0x01 },
 	{ 0x50, 0xd6 }, { 0x51, 0x1f },
 	{ 0x50, 0xd2 }, { 0x51, 0x03 },
-	{ 0x50, 0xd7 }, { 0x51, 0xbf },
-	{ 0x28, 0x74 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0xff },
-	{ 0x28, 0x46 }, { 0x29, 0x00 }, { 0x2a, 0x1a }, { 0x2b, 0x0c },
-
-	{ 0x04, 0x40 }, { 0x05, 0x00 },
-	{ 0x28, 0x00 }, { 0x2b, 0x08 },
-	{ 0x28, 0x05 }, { 0x2b, 0x00 },
+	{ 0x50, 0xd7 }, { 0x51, 0x3f },
 	{ 0x1c, 0x01 },
-	{ 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x1f },
-	{ 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x18 },
-	{ 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x12 },
-	{ 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x30 },
-	{ 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x37 },
-	{ 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
-	{ 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x09 },
-	{ 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x06 },
-	{ 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x7b },
-	{ 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x76 },
-	{ 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x7d },
-	{ 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x08 },
-	{ 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0b },
-	{ 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
-	{ 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xf2 },
-	{ 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xf3 },
-	{ 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x05 },
-	{ 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
-	{ 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
-	{ 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xef },
-	{ 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xd8 },
-	{ 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xf1 },
-	{ 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x3d },
-	{ 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x94 },
-	{ 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0xba },
+	{ 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 },
+	{ 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d },
+	{ 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
+	{ 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 },
+	{ 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 },
+	{ 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 },
+	{ 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
+	{ 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 },
+	{ 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e },
+	{ 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e },
+	{ 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 },
+	{ 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
+	{ 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 },
+	{ 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 },
+	{ 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe },
+	{ 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 },
+	{ 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee },
+	{ 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 },
+	{ 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f },
+	{ 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 },
+	{ 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 },
+	{ 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a },
+	{ 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc },
+	{ 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba },
+	{ 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 },
 	{ 0x50, 0x1e }, { 0x51, 0x5d },
 	{ 0x50, 0x22 }, { 0x51, 0x00 },
 	{ 0x50, 0x23 }, { 0x51, 0xc8 },
@@ -196,9 +190,7 @@
 	{ 0x50, 0x26 }, { 0x51, 0x00 },
 	{ 0x50, 0x27 }, { 0x51, 0xc3 },
 	{ 0x50, 0x39 }, { 0x51, 0x02 },
-	{ 0xec, 0x0f },
-	{ 0xeb, 0x1f },
-	{ 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
+	{ 0x50, 0xd5 }, { 0x51, 0x01 },
 	{ 0xd0, 0x00 },
 };
 
@@ -317,7 +309,11 @@
 	if (val >= 7)
 		*status |= FE_HAS_SYNC;
 
-	if (val >= 8)				/* Maybe 9? */
+	/*
+	 * Actually, on state S8, it starts receiving TS, but the TS
+	 * output is only on normal state after the transition to S9.
+	 */
+	if (val >= 9)
 		*status |= FE_HAS_LOCK;
 
 	dev_dbg(&state->i2c->dev, "%s: Status = 0x%02x (state = %d)\n",
@@ -2067,6 +2063,11 @@
 	kfree(state);
 }
 
+static int mb86a20s_get_frontend_algo(struct dvb_frontend *fe)
+{
+        return DVBFE_ALGO_HW;
+}
+
 static struct dvb_frontend_ops mb86a20s_ops;
 
 struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
@@ -2140,6 +2141,7 @@
 	.read_status = mb86a20s_read_status_and_stats,
 	.read_signal_strength = mb86a20s_read_signal_strength_from_cache,
 	.tune = mb86a20s_tune,
+	.get_frontend_algo = mb86a20s_get_frontend_algo,
 };
 
 MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware");
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 521bbf1..670240c 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -607,6 +607,7 @@
 config VIDEO_S5K4ECGX
         tristate "Samsung S5K4ECGX sensor support"
         depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	select CRC32
         ---help---
           This is a V4L2 sensor-level driver for Samsung S5K4ECGX 5M
           camera sensor with an embedded SoC image signal processor.
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index c4307ad..e543cbb 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -2168,11 +2168,12 @@
 		}
 		port->i2c_client_tuner = client_tuner;
 		break;
-	case CX23885_BOARD_HAUPPAUGE_HVR5525:
-		switch (port->nr) {
+	case CX23885_BOARD_HAUPPAUGE_HVR5525: {
 		struct m88rs6000t_config m88rs6000t_config;
 		struct a8293_platform_data a8293_pdata = {};
 
+		switch (port->nr) {
+
 		/* port b - satellite */
 		case 1:
 			/* attach frontend */
@@ -2267,6 +2268,7 @@
 			break;
 		}
 		break;
+	}
 	default:
 		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
 			" isn't supported yet\n",
diff --git a/drivers/media/pci/dm1105/Kconfig b/drivers/media/pci/dm1105/Kconfig
index 173daf0..14fa7e4 100644
--- a/drivers/media/pci/dm1105/Kconfig
+++ b/drivers/media/pci/dm1105/Kconfig
@@ -1,6 +1,6 @@
 config DVB_DM1105
 	tristate "SDMC DM1105 based PCI cards"
-	depends on DVB_CORE && PCI && I2C
+	depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT
 	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c
index 8ef6399..bc95752 100644
--- a/drivers/media/pci/saa7134/saa7134-i2c.c
+++ b/drivers/media/pci/saa7134/saa7134-i2c.c
@@ -355,12 +355,43 @@
 
 /* ----------------------------------------------------------- */
 
+/* On Medion 7134 reading EEPROM needs DVB-T demod i2c gate open */
+static void saa7134_i2c_eeprom_md7134_gate(struct saa7134_dev *dev)
+{
+	u8 subaddr = 0x7, dmdregval;
+	u8 data[2];
+	int ret;
+	struct i2c_msg i2cgatemsg_r[] = { {.addr = 0x08, .flags = 0,
+					   .buf = &subaddr, .len = 1},
+					  {.addr = 0x08,
+					   .flags = I2C_M_RD,
+					   .buf = &dmdregval, .len = 1}
+					};
+	struct i2c_msg i2cgatemsg_w[] = { {.addr = 0x08, .flags = 0,
+					   .buf = data, .len = 2} };
+
+	ret = i2c_transfer(&dev->i2c_adap, i2cgatemsg_r, 2);
+	if ((ret == 2) && (dmdregval & 0x2)) {
+		pr_debug("%s: DVB-T demod i2c gate was left closed\n",
+			 dev->name);
+
+		data[0] = subaddr;
+		data[1] = (dmdregval & ~0x2);
+		if (i2c_transfer(&dev->i2c_adap, i2cgatemsg_w, 1) != 1)
+			pr_err("%s: EEPROM i2c gate open failure\n",
+			  dev->name);
+	}
+}
+
 static int
 saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
 {
 	unsigned char buf;
 	int i,err;
 
+	if (dev->board == SAA7134_BOARD_MD7134)
+		saa7134_i2c_eeprom_md7134_gate(dev);
+
 	dev->i2c_client.addr = 0xa0 >> 1;
 	buf = 0;
 	if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index 4ab6586..f53e59e 100644
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -286,7 +286,10 @@
 static inline void solo_reg_write(struct solo_dev *solo_dev, int reg,
 				  u32 data)
 {
+	u16 val;
+
 	writel(data, solo_dev->reg_base + reg);
+	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
 }
 
 static inline void solo_irq_on(struct solo_dev *dev, u32 mask)
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index f0480d6..572bc04 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -1576,7 +1576,7 @@
 		return -EBUSY;
 	}
 
-	ret = vpfe_try_fmt(file, priv, &format);
+	ret = __vpfe_get_format(vpfe, &format, &bpp);
 	if (ret)
 		return ret;
 
@@ -1706,7 +1706,7 @@
 		sdinfo = &cfg->sub_devs[i];
 		client = v4l2_get_subdevdata(sdinfo->sd);
 		if (client->addr == curr_client->addr &&
-		    client->adapter->nr == client->adapter->nr) {
+		    client->adapter->nr == curr_client->adapter->nr) {
 			if (vpfe->current_input >= 1)
 				return -1;
 			*app_input_index = j + vpfe->current_input;
diff --git a/drivers/media/platform/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c
index cff63e5..b8f3d9f 100644
--- a/drivers/media/platform/blackfin/ppi.c
+++ b/drivers/media/platform/blackfin/ppi.c
@@ -214,6 +214,8 @@
 	if (params->dlen > 24 || params->dlen <= 0)
 		return -EINVAL;
 	pctrl = devm_pinctrl_get(ppi->dev);
+	if (IS_ERR(pctrl))
+		return PTR_ERR(pctrl);
 	pstate = pinctrl_lookup_state(pctrl,
 				      pin_state[(params->dlen + 7) / 8 - 1]);
 	if (pinctrl_select_state(pctrl, pstate))
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 3ffe2ec..7727789 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -173,6 +173,7 @@
 		}
 		s5p_mfc_clock_on();
 		ret = s5p_mfc_init_hw(dev);
+		s5p_mfc_clock_off();
 		if (ret)
 			mfc_err("Failed to reinit FW\n");
 	}
@@ -1029,6 +1030,11 @@
 	return !strcmp(dev_name(dev), (char *)data);
 }
 
+static void s5p_mfc_memdev_release(struct device *dev)
+{
+	dma_release_declared_memory(dev);
+}
+
 static void *mfc_get_drv_data(struct platform_device *pdev);
 
 static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
@@ -1041,6 +1047,9 @@
 		mfc_err("Not enough memory\n");
 		return -ENOMEM;
 	}
+
+	dev_set_name(dev->mem_dev_l, "%s", "s5p-mfc-l");
+	dev->mem_dev_l->release = s5p_mfc_memdev_release;
 	device_initialize(dev->mem_dev_l);
 	of_property_read_u32_array(dev->plat_dev->dev.of_node,
 			"samsung,mfc-l", mem_info, 2);
@@ -1058,6 +1067,9 @@
 		mfc_err("Not enough memory\n");
 		return -ENOMEM;
 	}
+
+	dev_set_name(dev->mem_dev_r, "%s", "s5p-mfc-r");
+	dev->mem_dev_r->release = s5p_mfc_memdev_release;
 	device_initialize(dev->mem_dev_r);
 	of_property_read_u32_array(dev->plat_dev->dev.of_node,
 			"samsung,mfc-r", mem_info, 2);
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 84fa6e9..67314c0 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -29,7 +29,7 @@
 #define RC5_BIT_START		(1 * RC5_UNIT)
 #define RC5_BIT_END		(1 * RC5_UNIT)
 #define RC5X_SPACE		(4 * RC5_UNIT)
-#define RC5_TRAILER		(10 * RC5_UNIT) /* In reality, approx 100 */
+#define RC5_TRAILER		(6 * RC5_UNIT) /* In reality, approx 100 */
 
 enum rc5_state {
 	STATE_INACTIVE,
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 0f30190..63165d3 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -263,6 +263,8 @@
 
 			if (allowance > ITE_RXDCR_MAX)
 				allowance = ITE_RXDCR_MAX;
+
+			use_demodulator = true;
 		}
 	}
 
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 2cdb740..f838d9c 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1321,8 +1321,8 @@
 			}
 		}
 	}
-	if (ep_in == NULL) {
-		dev_dbg(&intf->dev, "inbound and/or endpoint not found");
+	if (!ep_in || !ep_out) {
+		dev_dbg(&intf->dev, "required endpoints not found\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c
index 4e941f0..8d96a22 100644
--- a/drivers/media/tuners/tuner-xc2028.c
+++ b/drivers/media/tuners/tuner-xc2028.c
@@ -281,6 +281,14 @@
 	int i;
 	tuner_dbg("%s called\n", __func__);
 
+	/* free allocated f/w string */
+	if (priv->fname != firmware_name)
+		kfree(priv->fname);
+	priv->fname = NULL;
+
+	priv->state = XC2028_NO_FIRMWARE;
+	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+
 	if (!priv->firm)
 		return;
 
@@ -291,9 +299,6 @@
 
 	priv->firm = NULL;
 	priv->firm_size = 0;
-	priv->state = XC2028_NO_FIRMWARE;
-
-	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
 }
 
 static int load_all_firmwares(struct dvb_frontend *fe,
@@ -884,9 +889,8 @@
 	return 0;
 
 fail:
-	priv->state = XC2028_NO_FIRMWARE;
+	free_firmware(priv);
 
-	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
 	if (retry_count < 8) {
 		msleep(50);
 		retry_count++;
@@ -1332,11 +1336,8 @@
 	mutex_lock(&xc2028_list_mutex);
 
 	/* only perform final cleanup if this is the last instance */
-	if (hybrid_tuner_report_instance_count(priv) == 1) {
+	if (hybrid_tuner_report_instance_count(priv) == 1)
 		free_firmware(priv);
-		kfree(priv->ctrl.fname);
-		priv->ctrl.fname = NULL;
-	}
 
 	if (priv)
 		hybrid_tuner_release_state(priv);
@@ -1399,16 +1400,8 @@
 
 	/*
 	 * Copy the config data.
-	 * For the firmware name, keep a local copy of the string,
-	 * in order to avoid troubles during device release.
 	 */
-	kfree(priv->ctrl.fname);
 	memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
-	if (p->fname) {
-		priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
-		if (priv->ctrl.fname == NULL)
-			rc = -ENOMEM;
-	}
 
 	/*
 	 * If firmware name changed, frees firmware. As free_firmware will
@@ -1423,10 +1416,15 @@
 
 	if (priv->state == XC2028_NO_FIRMWARE) {
 		if (!firmware_name[0])
-			priv->fname = priv->ctrl.fname;
+			priv->fname = kstrdup(p->fname, GFP_KERNEL);
 		else
 			priv->fname = firmware_name;
 
+		if (!priv->fname) {
+			rc = -ENOMEM;
+			goto unlock;
+		}
+
 		rc = request_firmware_nowait(THIS_MODULE, 1,
 					     priv->fname,
 					     priv->i2c_props.adap->dev.parent,
@@ -1439,6 +1437,7 @@
 		} else
 			priv->state = XC2028_WAITING_FIRMWARE;
 	}
+unlock:
 	mutex_unlock(&priv->lock);
 
 	return rc;
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index 565a593..34b35eb 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -1073,7 +1073,7 @@
 	if (ret) {
 		dev_err(s->dev, "Failed to register as video device (%d)\n",
 				ret);
-		goto err_unregister_v4l2_dev;
+		goto err_free_controls;
 	}
 	dev_info(s->dev, "Registered as %s\n",
 			video_device_node_name(&s->vdev));
@@ -1082,7 +1082,6 @@
 
 err_free_controls:
 	v4l2_ctrl_handler_free(&s->hdl);
-err_unregister_v4l2_dev:
 	v4l2_device_unregister(&s->v4l2_dev);
 err_free_mem:
 	kfree(s);
diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c
index de4ae5e..10d8a08 100644
--- a/drivers/media/usb/cx231xx/cx231xx-audio.c
+++ b/drivers/media/usb/cx231xx/cx231xx-audio.c
@@ -671,10 +671,8 @@
 
 	spin_lock_init(&adev->slock);
 	err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm);
-	if (err < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if (err < 0)
+		goto err_free_card;
 
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 			&snd_cx231xx_pcm_capture);
@@ -688,10 +686,9 @@
 	INIT_WORK(&dev->wq_trigger, audio_trigger);
 
 	err = snd_card_register(card);
-	if (err < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if (err < 0)
+		goto err_free_card;
+
 	adev->sndcard = card;
 	adev->udev = dev->udev;
 
@@ -701,6 +698,11 @@
 					    hs_config_info[0].interface_info.
 					    audio_index + 1];
 
+	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) {
+		err = -ENODEV;
+		goto err_free_card;
+	}
+
 	adev->end_point_addr =
 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
 			bEndpointAddress;
@@ -710,13 +712,20 @@
 		"audio EndPoint Addr 0x%x, Alternate settings: %i\n",
 		adev->end_point_addr, adev->num_alt);
 	adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL);
-
-	if (adev->alt_max_pkt_size == NULL)
-		return -ENOMEM;
+	if (!adev->alt_max_pkt_size) {
+		err = -ENOMEM;
+		goto err_free_card;
+	}
 
 	for (i = 0; i < adev->num_alt; i++) {
-		u16 tmp =
-		    le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
+		u16 tmp;
+
+		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) {
+			err = -ENODEV;
+			goto err_free_pkt_size;
+		}
+
+		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
 				wMaxPacketSize);
 		adev->alt_max_pkt_size[i] =
 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
@@ -726,6 +735,13 @@
 	}
 
 	return 0;
+
+err_free_pkt_size:
+	kfree(adev->alt_max_pkt_size);
+err_free_card:
+	snd_card_free(card);
+
+	return err;
 }
 
 static int cx231xx_audio_fini(struct cx231xx *dev)
diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c
index 4919137..2f52d66 100644
--- a/drivers/media/usb/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c
@@ -1264,7 +1264,10 @@
 				   dev->board.agc_analog_digital_select_gpio,
 				   analog_or_digital);
 
-	return status;
+	if (status < 0)
+		return status;
+
+	return 0;
 }
 
 int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3)
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index 4a117a5..2c5f76d 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -486,7 +486,7 @@
 		.output_mode = OUT_MODE_VIP11,
 		.demod_xfer_mode = 0,
 		.ctl_pin_status_mask = 0xFFFFFFC4,
-		.agc_analog_digital_select_gpio = 0x00,	/* According with PV cxPolaris.inf file */
+		.agc_analog_digital_select_gpio = 0x1c,
 		.tuner_sif_gpio = -1,
 		.tuner_scl_gpio = -1,
 		.tuner_sda_gpio = -1,
@@ -1447,6 +1447,9 @@
 
 	uif = udev->actconfig->interface[idx];
 
+	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
+		return -ENODEV;
+
 	dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress;
 	dev->video_mode.num_alt = uif->num_altsetting;
 
@@ -1460,7 +1463,12 @@
 		return -ENOMEM;
 
 	for (i = 0; i < dev->video_mode.num_alt; i++) {
-		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
+		u16 tmp;
+
+		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
+			return -ENODEV;
+
+		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
 		dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
 		dev_dbg(dev->dev,
 			"Alternate setting %i, max size= %i\n", i,
@@ -1477,6 +1485,9 @@
 	}
 	uif = udev->actconfig->interface[idx];
 
+	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
+		return -ENODEV;
+
 	dev->vbi_mode.end_point_addr =
 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
 			bEndpointAddress;
@@ -1493,8 +1504,12 @@
 		return -ENOMEM;
 
 	for (i = 0; i < dev->vbi_mode.num_alt; i++) {
-		u16 tmp =
-		    le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+		u16 tmp;
+
+		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
+			return -ENODEV;
+
+		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
 				desc.wMaxPacketSize);
 		dev->vbi_mode.alt_max_pkt_size[i] =
 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
@@ -1514,6 +1529,9 @@
 	}
 	uif = udev->actconfig->interface[idx];
 
+	if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
+		return -ENODEV;
+
 	dev->sliced_cc_mode.end_point_addr =
 	    uif->altsetting[0].endpoint[isoc_pipe].desc.
 			bEndpointAddress;
@@ -1528,7 +1546,12 @@
 		return -ENOMEM;
 
 	for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
-		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+		u16 tmp;
+
+		if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
+			return -ENODEV;
+
+		tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
 				desc.wMaxPacketSize);
 		dev->sliced_cc_mode.alt_max_pkt_size[i] =
 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
@@ -1693,6 +1716,11 @@
 		}
 		uif = udev->actconfig->interface[idx];
 
+		if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) {
+			retval = -ENODEV;
+			goto err_video_alt;
+		}
+
 		dev->ts1_mode.end_point_addr =
 		    uif->altsetting[0].endpoint[isoc_pipe].
 				desc.bEndpointAddress;
@@ -1710,7 +1738,14 @@
 		}
 
 		for (i = 0; i < dev->ts1_mode.num_alt; i++) {
-			u16 tmp = le16_to_cpu(uif->altsetting[i].
+			u16 tmp;
+
+			if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) {
+				retval = -ENODEV;
+				goto err_video_alt;
+			}
+
+			tmp = le16_to_cpu(uif->altsetting[i].
 						endpoint[isoc_pipe].desc.
 						wMaxPacketSize);
 			dev->ts1_mode.alt_max_pkt_size[i] =
diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c
index a2fd49b..19b0293 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -712,6 +712,7 @@
 			break;
 		case CX231XX_BOARD_CNXT_RDE_253S:
 		case CX231XX_BOARD_CNXT_RDU_253S:
+		case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 			errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
 			break;
 		case CX231XX_BOARD_HAUPPAUGE_EXETER:
@@ -738,7 +739,7 @@
 		case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 		case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
 		case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
-		errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
+			errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
 			break;
 		default:
 			break;
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index f5df9ea..9757f35 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -1010,8 +1010,8 @@
 void dvb_usbv2_disconnect(struct usb_interface *intf)
 {
 	struct dvb_usb_device *d = usb_get_intfdata(intf);
-	const char *name = d->name;
-	struct device dev = d->udev->dev;
+	const char *devname = kstrdup(dev_name(&d->udev->dev), GFP_KERNEL);
+	const char *drvname = d->name;
 
 	dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__,
 			intf->cur_altsetting->desc.bInterfaceNumber);
@@ -1021,8 +1021,9 @@
 
 	dvb_usbv2_exit(d);
 
-	dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n",
-			KBUILD_MODNAME, name);
+	pr_info("%s: '%s:%s' successfully deinitialized and disconnected\n",
+		KBUILD_MODNAME, drvname, devname);
+	kfree(devname);
 }
 EXPORT_SYMBOL(dvb_usbv2_disconnect);
 
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
index 0d248ce..d1b4b72 100644
--- a/drivers/media/usb/dvb-usb/dib0700_core.c
+++ b/drivers/media/usb/dvb-usb/dib0700_core.c
@@ -677,7 +677,7 @@
 	struct dvb_usb_device *d = purb->context;
 	struct dib0700_rc_response *poll_reply;
 	enum rc_type protocol;
-	u32 uninitialized_var(keycode);
+	u32 keycode;
 	u8 toggle;
 
 	deb_info("%s()\n", __func__);
@@ -719,7 +719,8 @@
 		    poll_reply->nec.data       == 0x00 &&
 		    poll_reply->nec.not_data   == 0xff) {
 			poll_reply->data_state = 2;
-			break;
+			rc_repeat(d->rc_dev);
+			goto resubmit;
 		}
 
 		if ((poll_reply->nec.data ^ poll_reply->nec.not_data) != 0xff) {
@@ -782,6 +783,9 @@
 
 	/* Starting in firmware 1.20, the RC info is provided on a bulk pipe */
 
+	if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1)
+		return -ENODEV;
+
 	purb = usb_alloc_urb(0, GFP_KERNEL);
 	if (purb == NULL) {
 		err("rc usb alloc urb failed");
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
index 733a7ff..caad3b5 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
@@ -35,42 +35,51 @@
 
 int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type)
 {
-	struct hexline hx;
-	u8 reset;
-	int ret,pos=0;
+	struct hexline *hx;
+	u8 *buf;
+	int ret, pos = 0;
+	u16 cpu_cs_register = cypress[type].cpu_cs_register;
+
+	buf = kmalloc(sizeof(*hx), GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	hx = (struct hexline *)buf;
 
 	/* stop the CPU */
-	reset = 1;
-	if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
+	buf[0] = 1;
+	if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1)
 		err("could not stop the USB controller CPU.");
 
-	while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) {
-		deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk);
-		ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
+	while ((ret = dvb_usb_get_hexline(fw, hx, &pos)) > 0) {
+		deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n", hx->addr, hx->len, hx->chk);
+		ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len);
 
-		if (ret != hx.len) {
+		if (ret != hx->len) {
 			err("error while transferring firmware "
 				"(transferred size: %d, block size: %d)",
-				ret,hx.len);
+				ret, hx->len);
 			ret = -EINVAL;
 			break;
 		}
 	}
 	if (ret < 0) {
 		err("firmware download failed at %d with %d",pos,ret);
+		kfree(buf);
 		return ret;
 	}
 
 	if (ret == 0) {
 		/* restart the CPU */
-		reset = 0;
-		if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
+		buf[0] = 0;
+		if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) {
 			err("could not restart the USB controller CPU.");
 			ret = -EINVAL;
 		}
 	} else
 		ret = -EIO;
 
+	kfree(buf);
+
 	return ret;
 }
 EXPORT_SYMBOL(usb_cypress_load_firmware);
diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c
index f107173..dd93c2c 100644
--- a/drivers/media/usb/dvb-usb/ttusb2.c
+++ b/drivers/media/usb/dvb-usb/ttusb2.c
@@ -78,6 +78,9 @@
 	u8 *s, *r = NULL;
 	int ret = 0;
 
+	if (4 + rlen > 64)
+		return -EIO;
+
 	s = kzalloc(wlen+4, GFP_KERNEL);
 	if (!s)
 		return -ENOMEM;
@@ -381,6 +384,22 @@
 		write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
 		read = msg[i].flags & I2C_M_RD;
 
+		if (3 + msg[i].len > sizeof(obuf)) {
+			err("i2c wr len=%d too high", msg[i].len);
+			break;
+		}
+		if (write_read) {
+			if (3 + msg[i+1].len > sizeof(ibuf)) {
+				err("i2c rd len=%d too high", msg[i+1].len);
+				break;
+			}
+		} else if (read) {
+			if (3 + msg[i].len > sizeof(ibuf)) {
+				err("i2c rd len=%d too high", msg[i].len);
+				break;
+			}
+		}
+
 		obuf[0] = (msg[i].addr << 1) | (write_read | read);
 		if (read)
 			obuf[1] = 0;
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index a19b5c8..1a9e1e5 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -507,9 +507,8 @@
 	if (dev->disconnected)
 		return -ENODEV;
 
-	rc = rt_mutex_trylock(&dev->i2c_bus_lock);
-	if (rc < 0)
-		return rc;
+	if (!rt_mutex_trylock(&dev->i2c_bus_lock))
+		return -EAGAIN;
 
 	/* Switch I2C bus if needed */
 	if (bus != dev->cur_i2c_bus &&
diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c
index f23df4a..52b88e9 100644
--- a/drivers/media/usb/gspca/cpia1.c
+++ b/drivers/media/usb/gspca/cpia1.c
@@ -1624,7 +1624,7 @@
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
-	struct sd *sd = (struct sd *) gspca_dev;
+	struct sd *sd __maybe_unused = (struct sd *) gspca_dev;
 
 	command_pause(gspca_dev);
 
diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c
index 39c96bb..0f6d57f 100644
--- a/drivers/media/usb/gspca/konica.c
+++ b/drivers/media/usb/gspca/konica.c
@@ -188,6 +188,9 @@
 		return -EIO;
 	}
 
+	if (alt->desc.bNumEndpoints < 2)
+		return -ENODEV;
+
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 
 	n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
@@ -243,7 +246,7 @@
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
-	struct sd *sd = (struct sd *) gspca_dev;
+	struct sd *sd __maybe_unused = (struct sd *) gspca_dev;
 
 	konica_stream_off(gspca_dev);
 #if IS_ENABLED(CONFIG_INPUT)
diff --git a/drivers/media/usb/gspca/t613.c b/drivers/media/usb/gspca/t613.c
index e2cc4e5..bb52fc1 100644
--- a/drivers/media/usb/gspca/t613.c
+++ b/drivers/media/usb/gspca/t613.c
@@ -837,7 +837,7 @@
 			u8 *data,			/* isoc packet */
 			int len)			/* iso packet length */
 {
-	struct sd *sd = (struct sd *) gspca_dev;
+	struct sd *sd __maybe_unused = (struct sd *) gspca_dev;
 	int pkt_type;
 
 	if (data[0] == 0x5a) {
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
index e1907cd..7613d1f 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
@@ -123,15 +123,10 @@
 	memset(&tvdata,0,sizeof(tvdata));
 
 	eeprom = pvr2_eeprom_fetch(hdw);
-	if (!eeprom) return -EINVAL;
+	if (!eeprom)
+		return -EINVAL;
 
-	{
-		struct i2c_client fake_client;
-		/* Newer version expects a useless client interface */
-		fake_client.addr = hdw->eeprom_addr;
-		fake_client.adapter = &hdw->i2c_adap;
-		tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom);
-	}
+	tveeprom_hauppauge_analog(NULL, &tvdata, eeprom);
 
 	trace_eeprom("eeprom assumed v4l tveeprom module");
 	trace_eeprom("eeprom direct call results:");
diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
index c945e4c..ec30a00 100644
--- a/drivers/media/usb/siano/smsusb.c
+++ b/drivers/media/usb/siano/smsusb.c
@@ -200,22 +200,30 @@
 static int smsusb_sendrequest(void *context, void *buffer, size_t size)
 {
 	struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
-	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer;
-	int dummy;
+	struct sms_msg_hdr *phdr;
+	int dummy, ret;
 
 	if (dev->state != SMSUSB_ACTIVE) {
 		pr_debug("Device not active yet\n");
 		return -ENOENT;
 	}
 
+	phdr = kmalloc(size, GFP_KERNEL);
+	if (!phdr)
+		return -ENOMEM;
+	memcpy(phdr, buffer, size);
+
 	pr_debug("sending %s(%d) size: %d\n",
 		  smscore_translate_msg(phdr->msg_type), phdr->msg_type,
 		  phdr->msg_length);
 
 	smsendian_handle_tx_message((struct sms_msg_data *) phdr);
-	smsendian_handle_message_header((struct sms_msg_hdr *)buffer);
-	return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
-			    buffer, size, &dummy, 1000);
+	smsendian_handle_message_header((struct sms_msg_hdr *)phdr);
+	ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
+			    phdr, size, &dummy, 1000);
+
+	kfree(phdr);
+	return ret;
 }
 
 static char *smsusb1_fw_lkup[] = {
diff --git a/drivers/media/usb/usbtv/usbtv-audio.c b/drivers/media/usb/usbtv/usbtv-audio.c
index 78c12d2..5dab024 100644
--- a/drivers/media/usb/usbtv/usbtv-audio.c
+++ b/drivers/media/usb/usbtv/usbtv-audio.c
@@ -278,6 +278,9 @@
 {
 	struct usbtv *chip = container_of(work, struct usbtv, snd_trigger);
 
+	if (!chip->snd)
+		return;
+
 	if (atomic_read(&chip->snd_stream))
 		usbtv_audio_start(chip);
 	else
@@ -378,6 +381,8 @@
 
 void usbtv_audio_free(struct usbtv *usbtv)
 {
+	cancel_work_sync(&usbtv->snd_trigger);
+
 	if (usbtv->snd && usbtv->udev) {
 		snd_card_free(usbtv->snd);
 		usbtv->snd = NULL;
diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
index d1dc1a1..91d709e 100644
--- a/drivers/media/usb/usbvision/usbvision-video.c
+++ b/drivers/media/usb/usbvision/usbvision-video.c
@@ -1523,7 +1523,14 @@
 	}
 
 	for (i = 0; i < usbvision->num_alt; i++) {
-		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
+		u16 tmp;
+
+		if (uif->altsetting[i].desc.bNumEndpoints < 2) {
+			ret = -ENODEV;
+			goto err_pkt;
+		}
+
+		tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
 				      wMaxPacketSize);
 		usbvision->alt_max_pkt_size[i] =
 			(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index d11fd6a..885f689 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -148,6 +148,26 @@
 		.guid		= UVC_GUID_FORMAT_H264,
 		.fcc		= V4L2_PIX_FMT_H264,
 	},
+	{
+		.name		= "Greyscale 8 L/R (Y8I)",
+		.guid		= UVC_GUID_FORMAT_Y8I,
+		.fcc		= V4L2_PIX_FMT_Y8I,
+	},
+	{
+		.name		= "Greyscale 12 L/R (Y12I)",
+		.guid		= UVC_GUID_FORMAT_Y12I,
+		.fcc		= V4L2_PIX_FMT_Y12I,
+	},
+	{
+		.name		= "Depth data 16-bit (Z16)",
+		.guid		= UVC_GUID_FORMAT_Z16,
+		.fcc		= V4L2_PIX_FMT_Z16,
+	},
+	{
+		.name		= "Bayer 10-bit (SRGGB10P)",
+		.guid		= UVC_GUID_FORMAT_RW10,
+		.fcc		= V4L2_PIX_FMT_SRGGB10P,
+	},
 };
 
 /* ------------------------------------------------------------------------
@@ -1575,6 +1595,114 @@
 	return buffer;
 }
 
+static struct uvc_video_chain *uvc_alloc_chain(struct uvc_device *dev)
+{
+	struct uvc_video_chain *chain;
+
+	chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+	if (chain == NULL)
+		return NULL;
+
+	INIT_LIST_HEAD(&chain->entities);
+	mutex_init(&chain->ctrl_mutex);
+	chain->dev = dev;
+	v4l2_prio_init(&chain->prio);
+
+	return chain;
+}
+
+/*
+ * Fallback heuristic for devices that don't connect units and terminals in a
+ * valid chain.
+ *
+ * Some devices have invalid baSourceID references, causing uvc_scan_chain()
+ * to fail, but if we just take the entities we can find and put them together
+ * in the most sensible chain we can think of, turns out they do work anyway.
+ * Note: This heuristic assumes there is a single chain.
+ *
+ * At the time of writing, devices known to have such a broken chain are
+ *  - Acer Integrated Camera (5986:055a)
+ *  - Realtek rtl157a7 (0bda:57a7)
+ */
+static int uvc_scan_fallback(struct uvc_device *dev)
+{
+	struct uvc_video_chain *chain;
+	struct uvc_entity *iterm = NULL;
+	struct uvc_entity *oterm = NULL;
+	struct uvc_entity *entity;
+	struct uvc_entity *prev;
+
+	/*
+	 * Start by locating the input and output terminals. We only support
+	 * devices with exactly one of each for now.
+	 */
+	list_for_each_entry(entity, &dev->entities, list) {
+		if (UVC_ENTITY_IS_ITERM(entity)) {
+			if (iterm)
+				return -EINVAL;
+			iterm = entity;
+		}
+
+		if (UVC_ENTITY_IS_OTERM(entity)) {
+			if (oterm)
+				return -EINVAL;
+			oterm = entity;
+		}
+	}
+
+	if (iterm == NULL || oterm == NULL)
+		return -EINVAL;
+
+	/* Allocate the chain and fill it. */
+	chain = uvc_alloc_chain(dev);
+	if (chain == NULL)
+		return -ENOMEM;
+
+	if (uvc_scan_chain_entity(chain, oterm) < 0)
+		goto error;
+
+	prev = oterm;
+
+	/*
+	 * Add all Processing and Extension Units with two pads. The order
+	 * doesn't matter much, use reverse list traversal to connect units in
+	 * UVC descriptor order as we build the chain from output to input. This
+	 * leads to units appearing in the order meant by the manufacturer for
+	 * the cameras known to require this heuristic.
+	 */
+	list_for_each_entry_reverse(entity, &dev->entities, list) {
+		if (entity->type != UVC_VC_PROCESSING_UNIT &&
+		    entity->type != UVC_VC_EXTENSION_UNIT)
+			continue;
+
+		if (entity->num_pads != 2)
+			continue;
+
+		if (uvc_scan_chain_entity(chain, entity) < 0)
+			goto error;
+
+		prev->baSourceID[0] = entity->id;
+		prev = entity;
+	}
+
+	if (uvc_scan_chain_entity(chain, iterm) < 0)
+		goto error;
+
+	prev->baSourceID[0] = iterm->id;
+
+	list_add_tail(&chain->list, &dev->chains);
+
+	uvc_trace(UVC_TRACE_PROBE,
+		  "Found a video chain by fallback heuristic (%s).\n",
+		  uvc_print_chain(chain));
+
+	return 0;
+
+error:
+	kfree(chain);
+	return -EINVAL;
+}
+
 /*
  * Scan the device for video chains and register video devices.
  *
@@ -1597,15 +1725,10 @@
 		if (term->chain.next || term->chain.prev)
 			continue;
 
-		chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+		chain = uvc_alloc_chain(dev);
 		if (chain == NULL)
 			return -ENOMEM;
 
-		INIT_LIST_HEAD(&chain->entities);
-		mutex_init(&chain->ctrl_mutex);
-		chain->dev = dev;
-		v4l2_prio_init(&chain->prio);
-
 		term->flags |= UVC_ENTITY_FLAG_DEFAULT;
 
 		if (uvc_scan_chain(chain, term) < 0) {
@@ -1619,6 +1742,9 @@
 		list_add_tail(&chain->list, &dev->chains);
 	}
 
+	if (list_empty(&dev->chains))
+		uvc_scan_fallback(dev);
+
 	if (list_empty(&dev->chains)) {
 		uvc_printk(KERN_INFO, "No valid video chain found.\n");
 		return -1;
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index cfb868a..ff6feff 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -416,7 +416,7 @@
 		nextbuf = NULL;
 	spin_unlock_irqrestore(&queue->irqlock, flags);
 
-	buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
+	buf->state = buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
 	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
 	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
 
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 2764f43..0e7d16f 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -1388,47 +1388,44 @@
 static long uvc_v4l2_compat_ioctl32(struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
+	struct uvc_fh *handle = file->private_data;
 	union {
 		struct uvc_xu_control_mapping xmap;
 		struct uvc_xu_control_query xqry;
 	} karg;
 	void __user *up = compat_ptr(arg);
-	mm_segment_t old_fs;
 	long ret;
 
 	switch (cmd) {
 	case UVCIOC_CTRL_MAP32:
-		cmd = UVCIOC_CTRL_MAP;
 		ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up);
+		if (ret)
+			return ret;
+		ret = uvc_ioctl_ctrl_map(handle->chain, &karg.xmap);
+		if (ret)
+			return ret;
+		ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
+		if (ret)
+			return ret;
+
 		break;
 
 	case UVCIOC_CTRL_QUERY32:
-		cmd = UVCIOC_CTRL_QUERY;
 		ret = uvc_v4l2_get_xu_query(&karg.xqry, up);
+		if (ret)
+			return ret;
+		ret = uvc_xu_ctrl_query(handle->chain, &karg.xqry);
+		if (ret)
+			return ret;
+		ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
+		if (ret)
+			return ret;
 		break;
 
 	default:
 		return -ENOIOCTLCMD;
 	}
 
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = video_ioctl2(file, cmd, (unsigned long)&karg);
-	set_fs(old_fs);
-
-	if (ret < 0)
-		return ret;
-
-	switch (cmd) {
-	case UVCIOC_CTRL_MAP:
-		ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
-		break;
-
-	case UVCIOC_CTRL_QUERY:
-		ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
-		break;
-	}
-
 	return ret;
 }
 #endif
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index f0f2391..7e4d3ee 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -119,6 +119,18 @@
 #define UVC_GUID_FORMAT_H264 \
 	{ 'H',  '2',  '6',  '4', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y8I \
+	{ 'Y',  '8',  'I',  ' ', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y12I \
+	{ 'Y',  '1',  '2',  'I', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Z16 \
+	{ 'Z',  '1',  '6',  ' ', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_RW10 \
+	{ 'R',  'W',  '1',  '0', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 
 /* ------------------------------------------------------------------------
  * Driver specific constants.
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
index 7433ba5..fd6a3b3 100644
--- a/drivers/media/usb/zr364xx/zr364xx.c
+++ b/drivers/media/usb/zr364xx/zr364xx.c
@@ -604,6 +604,14 @@
 	ptr = pdest = frm->lpvbits;
 
 	if (frm->ulState == ZR364XX_READ_IDLE) {
+		if (purb->actual_length < 128) {
+			/* header incomplete */
+			dev_info(&cam->udev->dev,
+				 "%s: buffer (%d bytes) too small to hold jpeg header. Discarding.\n",
+				 __func__, purb->actual_length);
+			return -EINVAL;
+		}
+
 		frm->ulState = ZR364XX_READ_FRAME;
 		frm->cur_size = 0;
 
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index f38c076..109f687 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -280,7 +280,8 @@
 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
 {
 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
-	    copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)))
+	    copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
+	    copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
 		return -EFAULT;
 	return __put_v4l2_format32(&kp->format, &up->format);
 }
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 11f39791..3dc9ed2 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -793,7 +793,7 @@
  */
 void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
 {
-	if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
+	if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
 		return NULL;
 
 	return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv);
@@ -1505,7 +1505,7 @@
 			     void *pb, int nonblocking)
 {
 	unsigned long flags;
-	int ret;
+	int ret = 0;
 
 	/*
 	 * Wait for at least one buffer to become available on the done_list.
@@ -1521,10 +1521,12 @@
 	spin_lock_irqsave(&q->done_lock, flags);
 	*vb = list_first_entry(&q->done_list, struct vb2_buffer, done_entry);
 	/*
-	 * Only remove the buffer from done_list if v4l2_buffer can handle all
-	 * the planes.
+	 * Only remove the buffer from done_list if all planes can be
+	 * handled. Some cases such as V4L2 file I/O and DVB have pb
+	 * == NULL; skip the check then as there's nothing to verify.
 	 */
-	ret = call_bufop(q, verify_planes_array, *vb, pb);
+	if (pb)
+		ret = call_bufop(q, verify_planes_array, *vb, pb);
 	if (!ret)
 		list_del(&(*vb)->done_entry);
 	spin_unlock_irqrestore(&q->done_lock, flags);
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 6515dfc..55cba89 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -394,7 +394,7 @@
 	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
 			   GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
 	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
-			   GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
+			   GPMC_CONFIG4_WEEXTRADELAY, p->we_extra_delay);
 	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
 			   GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
 			   p->cycle2cyclesamecsen);
diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c
index 1105db2..83bfb16 100644
--- a/drivers/memstick/host/rtsx_usb_ms.c
+++ b/drivers/memstick/host/rtsx_usb_ms.c
@@ -524,6 +524,7 @@
 	int rc;
 
 	if (!host->req) {
+		pm_runtime_get_sync(ms_dev(host));
 		do {
 			rc = memstick_next_req(msh, &host->req);
 			dev_dbg(ms_dev(host), "next req %d\n", rc);
@@ -544,6 +545,7 @@
 						host->req->error);
 			}
 		} while (!rc);
+		pm_runtime_put(ms_dev(host));
 	}
 
 }
@@ -570,6 +572,7 @@
 	dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
 			__func__, param, value);
 
+	pm_runtime_get_sync(ms_dev(host));
 	mutex_lock(&ucr->dev_mutex);
 
 	err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_MS_CARD);
@@ -635,6 +638,7 @@
 	}
 out:
 	mutex_unlock(&ucr->dev_mutex);
+	pm_runtime_put(ms_dev(host));
 
 	/* power-on delay */
 	if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON)
@@ -681,6 +685,7 @@
 	int err;
 
 	for (;;) {
+		pm_runtime_get_sync(ms_dev(host));
 		mutex_lock(&ucr->dev_mutex);
 
 		/* Check pending MS card changes */
@@ -703,6 +708,7 @@
 		}
 
 poll_again:
+		pm_runtime_put(ms_dev(host));
 		if (host->eject)
 			break;
 
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 4d92df6..7398262 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1460,6 +1460,7 @@
 config MFD_WM8350_I2C
 	bool "Wolfson Microelectronics WM8350 with I2C"
 	select MFD_WM8350
+	select REGMAP_I2C
 	depends on I2C=y
 	help
 	  The WM8350 is an integrated audio and power management
diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c
index 06c2058..c216c3a 100644
--- a/drivers/mfd/atmel-hlcdc.c
+++ b/drivers/mfd/atmel-hlcdc.c
@@ -50,8 +50,9 @@
 	if (reg <= ATMEL_HLCDC_DIS) {
 		u32 status;
 
-		readl_poll_timeout(hregmap->regs + ATMEL_HLCDC_SR, status,
-				   !(status & ATMEL_HLCDC_SIP), 1, 100);
+		readl_poll_timeout_atomic(hregmap->regs + ATMEL_HLCDC_SR,
+					  status, !(status & ATMEL_HLCDC_SIP),
+					  1, 100);
 	}
 
 	writel(val, hregmap->regs + reg);
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index 68aa31ae..fe89e5e 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -33,6 +33,7 @@
 #define LPSS_DEV_SIZE		0x200
 #define LPSS_PRIV_OFFSET	0x200
 #define LPSS_PRIV_SIZE		0x100
+#define LPSS_PRIV_REG_COUNT	(LPSS_PRIV_SIZE / 4)
 #define LPSS_IDMA64_OFFSET	0x800
 #define LPSS_IDMA64_SIZE	0x800
 
@@ -75,6 +76,7 @@
 	const struct mfd_cell *cell;
 	struct device *dev;
 	void __iomem *priv;
+	u32 priv_ctx[LPSS_PRIV_REG_COUNT];
 	int devid;
 	u32 caps;
 	u32 active_ltr;
@@ -485,6 +487,13 @@
 
 int intel_lpss_suspend(struct device *dev)
 {
+	struct intel_lpss *lpss = dev_get_drvdata(dev);
+	unsigned int i;
+
+	/* Save device context */
+	for (i = 0; i < LPSS_PRIV_REG_COUNT; i++)
+		lpss->priv_ctx[i] = readl(lpss->priv + i * 4);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(intel_lpss_suspend);
@@ -492,8 +501,13 @@
 int intel_lpss_resume(struct device *dev)
 {
 	struct intel_lpss *lpss = dev_get_drvdata(dev);
+	unsigned int i;
 
-	intel_lpss_init_dev(lpss);
+	intel_lpss_deassert_reset(lpss);
+
+	/* Restore device context */
+	for (i = 0; i < LPSS_PRIV_REG_COUNT; i++)
+		writel(lpss->priv_ctx[i], lpss->priv + i * 4);
 
 	return 0;
 }
diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c
index d9e15cf..12d6ebb4 100644
--- a/drivers/mfd/intel_soc_pmic_core.c
+++ b/drivers/mfd/intel_soc_pmic_core.c
@@ -35,6 +35,7 @@
 	.table = {
 		/* Panel EN/DISABLE */
 		GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH),
+		{ },
 	},
 };
 
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 60b60dc..022c937 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -354,6 +354,8 @@
 					clones[i]);
 	}
 
+	put_device(dev);
+
 	return 0;
 }
 EXPORT_SYMBOL(mfd_clone_cell);
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index b7b3e8e..fe51e97 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -269,6 +269,8 @@
 
 		if (IS_ERR(tll->ch_clk[i]))
 			dev_dbg(dev, "can't get clock : %s\n", clkname);
+		else
+			clk_prepare(tll->ch_clk[i]);
 	}
 
 	pm_runtime_put_sync(dev);
@@ -301,9 +303,12 @@
 	tll_dev = NULL;
 	spin_unlock(&tll_lock);
 
-	for (i = 0; i < tll->nch; i++)
-		if (!IS_ERR(tll->ch_clk[i]))
+	for (i = 0; i < tll->nch; i++) {
+		if (!IS_ERR(tll->ch_clk[i])) {
+			clk_unprepare(tll->ch_clk[i]);
 			clk_put(tll->ch_clk[i]);
+		}
+	}
 
 	pm_runtime_disable(&pdev->dev);
 	return 0;
@@ -370,8 +375,8 @@
 				 * and use SDR Mode
 				 */
 				reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
-					| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
 					| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
+				reg |= OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF;
 			} else if (pdata->port_mode[i] ==
 					OMAP_EHCI_PORT_MODE_HSIC) {
 				/*
@@ -420,7 +425,7 @@
 			if (IS_ERR(tll->ch_clk[i]))
 				continue;
 
-			r = clk_prepare_enable(tll->ch_clk[i]);
+			r = clk_enable(tll->ch_clk[i]);
 			if (r) {
 				dev_err(tll_dev,
 				 "Error enabling ch %d clock: %d\n", i, r);
@@ -448,7 +453,7 @@
 	for (i = 0; i < tll->nch; i++) {
 		if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
 			if (!IS_ERR(tll->ch_clk[i]))
-				clk_disable_unprepare(tll->ch_clk[i]);
+				clk_disable(tll->ch_clk[i]);
 		}
 	}
 
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
index 207a3bd..a867cc9 100644
--- a/drivers/mfd/qcom_rpm.c
+++ b/drivers/mfd/qcom_rpm.c
@@ -34,7 +34,13 @@
 struct qcom_rpm_data {
 	u32 version;
 	const struct qcom_rpm_resource *resource_table;
-	unsigned n_resources;
+	unsigned int n_resources;
+	unsigned int req_ctx_off;
+	unsigned int req_sel_off;
+	unsigned int ack_ctx_off;
+	unsigned int ack_sel_off;
+	unsigned int req_sel_size;
+	unsigned int ack_sel_size;
 };
 
 struct qcom_rpm {
@@ -61,11 +67,7 @@
 
 #define RPM_REQUEST_TIMEOUT	(5 * HZ)
 
-#define RPM_REQUEST_CONTEXT	3
-#define RPM_REQ_SELECT		11
-#define RPM_ACK_CONTEXT		15
-#define RPM_ACK_SELECTOR	23
-#define RPM_SELECT_SIZE		7
+#define RPM_MAX_SEL_SIZE	7
 
 #define RPM_NOTIFICATION	BIT(30)
 #define RPM_REJECTED		BIT(31)
@@ -157,6 +159,12 @@
 	.version = 3,
 	.resource_table = apq8064_rpm_resource_table,
 	.n_resources = ARRAY_SIZE(apq8064_rpm_resource_table),
+	.req_ctx_off = 3,
+	.req_sel_off = 11,
+	.ack_ctx_off = 15,
+	.ack_sel_off = 23,
+	.req_sel_size = 4,
+	.ack_sel_size = 7,
 };
 
 static const struct qcom_rpm_resource msm8660_rpm_resource_table[] = {
@@ -240,6 +248,12 @@
 	.version = 2,
 	.resource_table = msm8660_rpm_resource_table,
 	.n_resources = ARRAY_SIZE(msm8660_rpm_resource_table),
+	.req_ctx_off = 3,
+	.req_sel_off = 11,
+	.ack_ctx_off = 19,
+	.ack_sel_off = 27,
+	.req_sel_size = 7,
+	.ack_sel_size = 7,
 };
 
 static const struct qcom_rpm_resource msm8960_rpm_resource_table[] = {
@@ -322,6 +336,12 @@
 	.version = 3,
 	.resource_table = msm8960_rpm_resource_table,
 	.n_resources = ARRAY_SIZE(msm8960_rpm_resource_table),
+	.req_ctx_off = 3,
+	.req_sel_off = 11,
+	.ack_ctx_off = 15,
+	.ack_sel_off = 23,
+	.req_sel_size = 4,
+	.ack_sel_size = 7,
 };
 
 static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = {
@@ -362,6 +382,12 @@
 	.version = 3,
 	.resource_table = ipq806x_rpm_resource_table,
 	.n_resources = ARRAY_SIZE(ipq806x_rpm_resource_table),
+	.req_ctx_off = 3,
+	.req_sel_off = 11,
+	.ack_ctx_off = 15,
+	.ack_sel_off = 23,
+	.req_sel_size = 4,
+	.ack_sel_size = 7,
 };
 
 static const struct of_device_id qcom_rpm_of_match[] = {
@@ -380,7 +406,7 @@
 {
 	const struct qcom_rpm_resource *res;
 	const struct qcom_rpm_data *data = rpm->data;
-	u32 sel_mask[RPM_SELECT_SIZE] = { 0 };
+	u32 sel_mask[RPM_MAX_SEL_SIZE] = { 0 };
 	int left;
 	int ret = 0;
 	int i;
@@ -398,12 +424,12 @@
 		writel_relaxed(buf[i], RPM_REQ_REG(rpm, res->target_id + i));
 
 	bitmap_set((unsigned long *)sel_mask, res->select_id, 1);
-	for (i = 0; i < ARRAY_SIZE(sel_mask); i++) {
+	for (i = 0; i < rpm->data->req_sel_size; i++) {
 		writel_relaxed(sel_mask[i],
-			       RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i));
+			       RPM_CTRL_REG(rpm, rpm->data->req_sel_off + i));
 	}
 
-	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
+	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, rpm->data->req_ctx_off));
 
 	reinit_completion(&rpm->ack);
 	regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit));
@@ -426,10 +452,11 @@
 	u32 ack;
 	int i;
 
-	ack = readl_relaxed(RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT));
-	for (i = 0; i < RPM_SELECT_SIZE; i++)
-		writel_relaxed(0, RPM_CTRL_REG(rpm, RPM_ACK_SELECTOR + i));
-	writel(0, RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT));
+	ack = readl_relaxed(RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off));
+	for (i = 0; i < rpm->data->ack_sel_size; i++)
+		writel_relaxed(0,
+			RPM_CTRL_REG(rpm, rpm->data->ack_sel_off + i));
+	writel(0, RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off));
 
 	if (ack & RPM_NOTIFICATION) {
 		dev_warn(rpm->dev, "ignoring notification!\n");
diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c
index dbd907d..691dab7 100644
--- a/drivers/mfd/rtsx_usb.c
+++ b/drivers/mfd/rtsx_usb.c
@@ -46,9 +46,6 @@
 
 	dev_dbg(&ucr->pusb_intf->dev, "%s: sg transfer timed out", __func__);
 	usb_sg_cancel(&ucr->current_sg);
-
-	/* we know the cancellation is caused by time-out */
-	ucr->current_sg.status = -ETIMEDOUT;
 }
 
 static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr,
@@ -67,12 +64,15 @@
 	ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout);
 	add_timer(&ucr->sg_timer);
 	usb_sg_wait(&ucr->current_sg);
-	del_timer_sync(&ucr->sg_timer);
+	if (!del_timer_sync(&ucr->sg_timer))
+		ret = -ETIMEDOUT;
+	else
+		ret = ucr->current_sg.status;
 
 	if (act_len)
 		*act_len = ucr->current_sg.bytes;
 
-	return ucr->current_sg.status;
+	return ret;
 }
 
 int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index ca74635..9e64999 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -525,11 +525,19 @@
 	  bus. System Configuration interface is one of the possible means
 	  of generating transactions on this bus.
 
-config UID_CPUTIME
-	bool "Per-UID cpu time statistics"
-	depends on PROFILING
+config UID_SYS_STATS
+	bool "Per-UID statistics"
+	depends on PROFILING && TASK_XACCT && TASK_IO_ACCOUNTING
 	help
 	  Per UID based cpu time statistics exported to /proc/uid_cputime
+	  Per UID based io statistics exported to /proc/uid_io
+	  Per UID based procstat control in /proc/uid_procstat
+
+config MEMORY_STATE_TIME
+	tristate "Memory freq/bandwidth time statistics"
+	depends on PROFILING
+	help
+	  Memory time statistics exported to /sys/kernel/memory_state_time
 
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e5142b8..9a3b402 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -56,4 +56,5 @@
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)		+= cxl/
-obj-$(CONFIG_UID_CPUTIME) += uid_cputime.o
+obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o
+obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o
diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c
index 5484301..3dc61ea 100644
--- a/drivers/misc/c2port/c2port-duramar2150.c
+++ b/drivers/misc/c2port/c2port-duramar2150.c
@@ -129,8 +129,8 @@
 
 	duramar2150_c2port_dev = c2port_device_register("uc",
 					&duramar2150_c2port_ops, NULL);
-	if (!duramar2150_c2port_dev) {
-		ret = -ENODEV;
+	if (IS_ERR(duramar2150_c2port_dev)) {
+		ret = PTR_ERR(duramar2150_c2port_dev);
 		goto free_region;
 	}
 
diff --git a/drivers/misc/cxl/Makefile b/drivers/misc/cxl/Makefile
index 6982f60..ab6f392 100644
--- a/drivers/misc/cxl/Makefile
+++ b/drivers/misc/cxl/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Werror -Wno-unused-const-variable
+ccflags-y := -Werror $(call cc-disable-warning, unused-const-variable)
 
 cxl-y				+= main.o file.o irq.o fault.o native.o
 cxl-y				+= context.o sysfs.o debugfs.o pci.o trace.o
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c
index 103baf0..ea3eeb7 100644
--- a/drivers/misc/cxl/api.c
+++ b/drivers/misc/cxl/api.c
@@ -25,7 +25,6 @@
 
 	afu = cxl_pci_to_afu(dev);
 
-	get_device(&afu->dev);
 	ctx = cxl_context_alloc();
 	if (IS_ERR(ctx)) {
 		rc = PTR_ERR(ctx);
@@ -61,7 +60,6 @@
 err_ctx:
 	kfree(ctx);
 err_dev:
-	put_device(&afu->dev);
 	return ERR_PTR(rc);
 }
 EXPORT_SYMBOL_GPL(cxl_dev_context_init);
@@ -87,8 +85,6 @@
 	if (ctx->status >= STARTED)
 		return -EBUSY;
 
-	put_device(&ctx->afu->dev);
-
 	cxl_context_free(ctx);
 
 	return 0;
@@ -176,7 +172,7 @@
 
 	if (task) {
 		ctx->pid = get_task_pid(task, PIDTYPE_PID);
-		get_pid(ctx->pid);
+		ctx->glpid = get_task_pid(task->group_leader, PIDTYPE_PID);
 		kernel = false;
 	}
 
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index 2faa127..262b88e 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -42,7 +42,7 @@
 	spin_lock_init(&ctx->sste_lock);
 	ctx->afu = afu;
 	ctx->master = master;
-	ctx->pid = NULL; /* Set in start work ioctl */
+	ctx->pid = ctx->glpid = NULL; /* Set in start work ioctl */
 	mutex_init(&ctx->mapping_lock);
 	ctx->mapping = mapping;
 
@@ -97,6 +97,12 @@
 	ctx->pe = i;
 	ctx->elem = &ctx->afu->spa[i];
 	ctx->pe_inserted = false;
+
+	/*
+	 * take a ref on the afu so that it stays alive at-least till
+	 * this context is reclaimed inside reclaim_ctx.
+	 */
+	cxl_afu_get(afu);
 	return 0;
 }
 
@@ -211,7 +217,11 @@
 	WARN_ON(cxl_detach_process(ctx) &&
 		cxl_adapter_link_ok(ctx->afu->adapter));
 	flush_work(&ctx->fault_work); /* Only needed for dedicated process */
+
+	/* release the reference to the group leader and mm handling pid */
 	put_pid(ctx->pid);
+	put_pid(ctx->glpid);
+
 	cxl_ctx_put();
 	return 0;
 }
@@ -278,6 +288,9 @@
 	if (ctx->irq_bitmap)
 		kfree(ctx->irq_bitmap);
 
+	/* Drop ref to the afu device taken during cxl_context_init */
+	cxl_afu_put(ctx->afu);
+
 	kfree(ctx);
 }
 
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 0cfb9c1..a521bc7 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -403,6 +403,18 @@
 	bool enabled;
 };
 
+/* AFU refcount management */
+static inline struct cxl_afu *cxl_afu_get(struct cxl_afu *afu)
+{
+
+	return (get_device(&afu->dev) == NULL) ? NULL : afu;
+}
+
+static inline void  cxl_afu_put(struct cxl_afu *afu)
+{
+	put_device(&afu->dev);
+}
+
 
 struct cxl_irq_name {
 	struct list_head list;
@@ -433,6 +445,9 @@
 	unsigned int sst_size, sst_lru;
 
 	wait_queue_head_t wq;
+	/* pid of the group leader associated with the pid */
+	struct pid *glpid;
+	/* use mm context associated with this pid for ds faults */
 	struct pid *pid;
 	spinlock_t lock; /* Protects pending_irq_mask, pending_fault and fault_addr */
 	/* Only used in PR mode */
diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c
index 25a5418..81c3f75 100644
--- a/drivers/misc/cxl/fault.c
+++ b/drivers/misc/cxl/fault.c
@@ -166,13 +166,92 @@
 	cxl_ack_irq(ctx, CXL_PSL_TFC_An_R, 0);
 }
 
+/*
+ * Returns the mm_struct corresponding to the context ctx via ctx->pid
+ * In case the task has exited we use the task group leader accessible
+ * via ctx->glpid to find the next task in the thread group that has a
+ * valid  mm_struct associated with it. If a task with valid mm_struct
+ * is found the ctx->pid is updated to use the task struct for subsequent
+ * translations. In case no valid mm_struct is found in the task group to
+ * service the fault a NULL is returned.
+ */
+static struct mm_struct *get_mem_context(struct cxl_context *ctx)
+{
+	struct task_struct *task = NULL;
+	struct mm_struct *mm = NULL;
+	struct pid *old_pid = ctx->pid;
+
+	if (old_pid == NULL) {
+		pr_warn("%s: Invalid context for pe=%d\n",
+			 __func__, ctx->pe);
+		return NULL;
+	}
+
+	task = get_pid_task(old_pid, PIDTYPE_PID);
+
+	/*
+	 * pid_alive may look racy but this saves us from costly
+	 * get_task_mm when the task is a zombie. In worst case
+	 * we may think a task is alive, which is about to die
+	 * but get_task_mm will return NULL.
+	 */
+	if (task != NULL && pid_alive(task))
+		mm = get_task_mm(task);
+
+	/* release the task struct that was taken earlier */
+	if (task)
+		put_task_struct(task);
+	else
+		pr_devel("%s: Context owning pid=%i for pe=%i dead\n",
+			__func__, pid_nr(old_pid), ctx->pe);
+
+	/*
+	 * If we couldn't find the mm context then use the group
+	 * leader to iterate over the task group and find a task
+	 * that gives us mm_struct.
+	 */
+	if (unlikely(mm == NULL && ctx->glpid != NULL)) {
+
+		rcu_read_lock();
+		task = pid_task(ctx->glpid, PIDTYPE_PID);
+		if (task)
+			do {
+				mm = get_task_mm(task);
+				if (mm) {
+					ctx->pid = get_task_pid(task,
+								PIDTYPE_PID);
+					break;
+				}
+				task = next_thread(task);
+			} while (task && !thread_group_leader(task));
+		rcu_read_unlock();
+
+		/* check if we switched pid */
+		if (ctx->pid != old_pid) {
+			if (mm)
+				pr_devel("%s:pe=%i switch pid %i->%i\n",
+					 __func__, ctx->pe, pid_nr(old_pid),
+					 pid_nr(ctx->pid));
+			else
+				pr_devel("%s:Cannot find mm for pid=%i\n",
+					 __func__, pid_nr(old_pid));
+
+			/* drop the reference to older pid */
+			put_pid(old_pid);
+		}
+	}
+
+	return mm;
+}
+
+
+
 void cxl_handle_fault(struct work_struct *fault_work)
 {
 	struct cxl_context *ctx =
 		container_of(fault_work, struct cxl_context, fault_work);
 	u64 dsisr = ctx->dsisr;
 	u64 dar = ctx->dar;
-	struct task_struct *task = NULL;
 	struct mm_struct *mm = NULL;
 
 	if (cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An) != dsisr ||
@@ -195,17 +274,17 @@
 		"DSISR: %#llx DAR: %#llx\n", ctx->pe, dsisr, dar);
 
 	if (!ctx->kernel) {
-		if (!(task = get_pid_task(ctx->pid, PIDTYPE_PID))) {
-			pr_devel("cxl_handle_fault unable to get task %i\n",
-				 pid_nr(ctx->pid));
+
+		mm = get_mem_context(ctx);
+		/* indicates all the thread in task group have exited */
+		if (mm == NULL) {
+			pr_devel("%s: unable to get mm for pe=%d pid=%i\n",
+				 __func__, ctx->pe, pid_nr(ctx->pid));
 			cxl_ack_ae(ctx);
 			return;
-		}
-		if (!(mm = get_task_mm(task))) {
-			pr_devel("cxl_handle_fault unable to get mm %i\n",
-				 pid_nr(ctx->pid));
-			cxl_ack_ae(ctx);
-			goto out;
+		} else {
+			pr_devel("Handling page fault for pe=%d pid=%i\n",
+				 ctx->pe, pid_nr(ctx->pid));
 		}
 	}
 
@@ -218,33 +297,22 @@
 
 	if (mm)
 		mmput(mm);
-out:
-	if (task)
-		put_task_struct(task);
 }
 
 static void cxl_prefault_one(struct cxl_context *ctx, u64 ea)
 {
-	int rc;
-	struct task_struct *task;
 	struct mm_struct *mm;
 
-	if (!(task = get_pid_task(ctx->pid, PIDTYPE_PID))) {
-		pr_devel("cxl_prefault_one unable to get task %i\n",
-			 pid_nr(ctx->pid));
-		return;
-	}
-	if (!(mm = get_task_mm(task))) {
+	mm = get_mem_context(ctx);
+	if (mm == NULL) {
 		pr_devel("cxl_prefault_one unable to get mm %i\n",
 			 pid_nr(ctx->pid));
-		put_task_struct(task);
 		return;
 	}
 
-	rc = cxl_fault_segment(ctx, mm, ea);
+	cxl_fault_segment(ctx, mm, ea);
 
 	mmput(mm);
-	put_task_struct(task);
 }
 
 static u64 next_segment(u64 ea, u64 vsid)
@@ -263,18 +331,13 @@
 	struct copro_slb slb;
 	struct vm_area_struct *vma;
 	int rc;
-	struct task_struct *task;
 	struct mm_struct *mm;
 
-	if (!(task = get_pid_task(ctx->pid, PIDTYPE_PID))) {
-		pr_devel("cxl_prefault_vma unable to get task %i\n",
-			 pid_nr(ctx->pid));
-		return;
-	}
-	if (!(mm = get_task_mm(task))) {
+	mm = get_mem_context(ctx);
+	if (mm == NULL) {
 		pr_devel("cxl_prefault_vm unable to get mm %i\n",
 			 pid_nr(ctx->pid));
-		goto out1;
+		return;
 	}
 
 	down_read(&mm->mmap_sem);
@@ -295,8 +358,6 @@
 	up_read(&mm->mmap_sem);
 
 	mmput(mm);
-out1:
-	put_task_struct(task);
 }
 
 void cxl_prefault(struct cxl_context *ctx, u64 wed)
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index 7ccd299..10a0293 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -67,7 +67,13 @@
 		spin_unlock(&adapter->afu_list_lock);
 		goto err_put_adapter;
 	}
-	get_device(&afu->dev);
+
+	/*
+	 * taking a ref to the afu so that it doesn't go away
+	 * for rest of the function. This ref is released before
+	 * we return.
+	 */
+	cxl_afu_get(afu);
 	spin_unlock(&adapter->afu_list_lock);
 
 	if (!afu->current_mode)
@@ -90,13 +96,12 @@
 	file->private_data = ctx;
 	cxl_ctx_get();
 
-	/* Our ref on the AFU will now hold the adapter */
-	put_device(&adapter->dev);
-
-	return 0;
+	/* indicate success */
+	rc = 0;
 
 err_put_afu:
-	put_device(&afu->dev);
+	/* release the ref taken earlier */
+	cxl_afu_put(afu);
 err_put_adapter:
 	put_device(&adapter->dev);
 	return rc;
@@ -131,8 +136,6 @@
 		mutex_unlock(&ctx->mapping_lock);
 	}
 
-	put_device(&ctx->afu->dev);
-
 	/*
 	 * At this this point all bottom halfs have finished and we should be
 	 * getting no more IRQs from the hardware for this context.  Once it's
@@ -155,11 +158,8 @@
 
 	/* Do this outside the status_mutex to avoid a circular dependency with
 	 * the locking in cxl_mmap_fault() */
-	if (copy_from_user(&work, uwork,
-			   sizeof(struct cxl_ioctl_start_work))) {
-		rc = -EFAULT;
-		goto out;
-	}
+	if (copy_from_user(&work, uwork, sizeof(work)))
+		return -EFAULT;
 
 	mutex_lock(&ctx->status_mutex);
 	if (ctx->status != OPENED) {
@@ -198,8 +198,12 @@
 	 * where a process (master, some daemon, etc) has opened the chardev on
 	 * behalf of another process, so the AFU's mm gets bound to the process
 	 * that performs this ioctl and not the process that opened the file.
+	 * Also we grab the PID of the group leader so that if the task that
+	 * has performed the attach operation exits the mm context of the
+	 * process is still accessible.
 	 */
-	ctx->pid = get_pid(get_task_pid(current, PIDTYPE_PID));
+	ctx->pid = get_task_pid(current, PIDTYPE_PID);
+	ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID);
 
 	trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr);
 
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index be2c8e24..0c6c17a1 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -138,6 +138,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0477), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x044b), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x04cf), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0601), },
 	{ PCI_DEVICE_CLASS(0x120000, ~0), },
 
 	{ }
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
index 222367c..524660510 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -352,17 +352,27 @@
 		if (copy_from_user(sgl->lpage, user_addr + user_size -
 				   sgl->lpage_size, sgl->lpage_size)) {
 			rc = -EFAULT;
-			goto err_out1;
+			goto err_out2;
 		}
 	}
 	return 0;
 
+ err_out2:
+	__genwqe_free_consistent(cd, PAGE_SIZE, sgl->lpage,
+				 sgl->lpage_dma_addr);
+	sgl->lpage = NULL;
+	sgl->lpage_dma_addr = 0;
  err_out1:
 	__genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage,
 				 sgl->fpage_dma_addr);
+	sgl->fpage = NULL;
+	sgl->fpage_dma_addr = 0;
  err_out:
 	__genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl,
 				 sgl->sgl_dma_addr);
+	sgl->sgl = NULL;
+	sgl->sgl_dma_addr = 0;
+	sgl->sgl_size = 0;
 	return -ENOMEM;
 }
 
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 11fdadc..2a6eaf1 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -103,6 +103,7 @@
 	CT_EXEC_USERSPACE,
 	CT_ACCESS_USERSPACE,
 	CT_WRITE_RO,
+	CT_WRITE_RO_AFTER_INIT,
 	CT_WRITE_KERN,
 };
 
@@ -140,6 +141,7 @@
 	"EXEC_USERSPACE",
 	"ACCESS_USERSPACE",
 	"WRITE_RO",
+	"WRITE_RO_AFTER_INIT",
 	"WRITE_KERN",
 };
 
@@ -162,6 +164,7 @@
 static u8 data_area[EXEC_SIZE];
 
 static const unsigned long rodata = 0xAA55AA55;
+static unsigned long ro_after_init __ro_after_init = 0x55AA5500;
 
 module_param(recur_count, int, 0644);
 MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test");
@@ -503,11 +506,28 @@
 		break;
 	}
 	case CT_WRITE_RO: {
-		unsigned long *ptr;
+		/* Explicitly cast away "const" for the test. */
+		unsigned long *ptr = (unsigned long *)&rodata;
 
-		ptr = (unsigned long *)&rodata;
+		pr_info("attempting bad rodata write at %p\n", ptr);
+		*ptr ^= 0xabcd1234;
 
-		pr_info("attempting bad write at %p\n", ptr);
+		break;
+	}
+	case CT_WRITE_RO_AFTER_INIT: {
+		unsigned long *ptr = &ro_after_init;
+
+		/*
+		 * Verify we were written to during init. Since an Oops
+		 * is considered a "success", a failure is to just skip the
+		 * real test.
+		 */
+		if ((*ptr & 0xAA) != 0xAA) {
+			pr_info("%p was NOT written during init!?\n", ptr);
+			break;
+		}
+
+		pr_info("attempting bad ro_after_init write at %p\n", ptr);
 		*ptr ^= 0xabcd1234;
 
 		break;
@@ -817,6 +837,9 @@
 	int n_debugfs_entries = 1; /* Assume only the direct entry */
 	int i;
 
+	/* Make sure we can write to __ro_after_init values during __init */
+	ro_after_init |= 0xAA;
+
 	/* Register debugfs interface */
 	lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
 	if (!lkdtm_debugfs_root) {
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index cd0403f..e79c037 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -417,8 +417,10 @@
 
 	dev = cl->dev;
 
-	if (dev->iamthif_state != MEI_IAMTHIF_READING)
+	if (dev->iamthif_state != MEI_IAMTHIF_READING) {
+		mei_irq_discard_msg(dev, mei_hdr);
 		return 0;
+	}
 
 	ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
 	if (ret)
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 020de59..bdc7fcd 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -151,7 +151,7 @@
 
 	ret = 0;
 	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
-	if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
+	if (bytes_recv < if_version_length) {
 		dev_err(bus->dev, "Could not read IF version\n");
 		ret = -EIO;
 		goto err;
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 1a173d0..be74a25 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -144,7 +144,7 @@
 		mutex_lock(&bus->device_lock);
 
 		if (!mei_cl_is_connected(cl)) {
-			rets = -EBUSY;
+			rets = -ENODEV;
 			goto out;
 		}
 	}
@@ -222,17 +222,23 @@
 static void mei_cl_bus_event_work(struct work_struct *work)
 {
 	struct mei_cl_device *cldev;
+	struct mei_device *bus;
 
 	cldev = container_of(work, struct mei_cl_device, event_work);
 
+	bus = cldev->bus;
+
 	if (cldev->event_cb)
 		cldev->event_cb(cldev, cldev->events, cldev->event_context);
 
 	cldev->events = 0;
 
 	/* Prepare for the next read */
-	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX))
+	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
+		mutex_lock(&bus->device_lock);
 		mei_cl_read_start(cldev->cl, 0, NULL);
+		mutex_unlock(&bus->device_lock);
+	}
 }
 
 /**
@@ -296,6 +302,7 @@
 				unsigned long events_mask,
 				mei_cldev_event_cb_t event_cb, void *context)
 {
+	struct mei_device *bus = cldev->bus;
 	int ret;
 
 	if (cldev->event_cb)
@@ -308,15 +315,17 @@
 	INIT_WORK(&cldev->event_work, mei_cl_bus_event_work);
 
 	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
+		mutex_lock(&bus->device_lock);
 		ret = mei_cl_read_start(cldev->cl, 0, NULL);
+		mutex_unlock(&bus->device_lock);
 		if (ret && ret != -EBUSY)
 			return ret;
 	}
 
 	if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) {
-		mutex_lock(&cldev->cl->dev->device_lock);
+		mutex_lock(&bus->device_lock);
 		ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0);
-		mutex_unlock(&cldev->cl->dev->device_lock);
+		mutex_unlock(&bus->device_lock);
 		if (ret)
 			return ret;
 	}
@@ -390,7 +399,7 @@
 EXPORT_SYMBOL_GPL(mei_cldev_enabled);
 
 /**
- * mei_cldev_enable_device - enable me client device
+ * mei_cldev_enable - enable me client device
  *     create connection with me client
  *
  * @cldev: me client device
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index a6c87c7..2ff39fb 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -698,7 +698,7 @@
 
 	pm_runtime_mark_last_busy(dev->dev);
 	dev_dbg(dev->dev, "rpm: autosuspend\n");
-	pm_runtime_autosuspend(dev->dev);
+	pm_request_autosuspend(dev->dev);
 }
 
 /**
@@ -1735,6 +1735,10 @@
 			wake_up(&cl->wait);
 
 		break;
+	case MEI_FOP_DISCONNECT_RSP:
+		mei_io_cb_free(cb);
+		mei_cl_set_disconnected(cl);
+		break;
 	default:
 		BUG_ON(0);
 	}
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index e7b7aad..fd8a9f0 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -873,8 +873,7 @@
 		cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT_RSP, NULL);
 		if (!cb)
 			return -ENOMEM;
-		cl_dbg(dev, cl, "add disconnect response as first\n");
-		list_add(&cb->list, &dev->ctrl_wr_list.list);
+		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 	}
 	return 0;
 }
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index a8a68ac..a266138 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -121,6 +121,10 @@
 #define MEI_DEV_ID_SPT_2      0x9D3B  /* Sunrise Point 2 */
 #define MEI_DEV_ID_SPT_H      0xA13A  /* Sunrise Point H */
 #define MEI_DEV_ID_SPT_H_2    0xA13B  /* Sunrise Point H 2 */
+
+#define MEI_DEV_ID_KBP        0xA2BA  /* Kaby Point */
+#define MEI_DEV_ID_KBP_2      0xA2BB  /* Kaby Point 2 */
+
 /*
  * MEI HW Section
  */
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 25b1997..3633375 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1258,8 +1258,14 @@
 static bool mei_me_fw_type_sps(struct pci_dev *pdev)
 {
 	u32 reg;
-	/* Read ME FW Status check for SPS Firmware */
-	pci_read_config_dword(pdev, PCI_CFG_HFS_1, &reg);
+	unsigned int devfn;
+
+	/*
+	 * Read ME FW Status register to check for SPS Firmware
+	 * The SPS FW is only signaled in pci function 0
+	 */
+	devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+	pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_1, &reg);
 	/* if bits [19:16] = 15, running SPS Firmware */
 	return (reg & 0xf0000) == 0xf0000;
 }
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index bae680c..396d75d 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -972,11 +972,13 @@
 	hisr = mei_txe_br_reg_read(hw, HISR_REG);
 
 	aliveness = mei_txe_aliveness_get(dev);
-	if (hhisr & IPC_HHIER_SEC && aliveness)
+	if (hhisr & IPC_HHIER_SEC && aliveness) {
 		ipc_isr = mei_txe_sec_reg_read_silent(hw,
 				SEC_IPC_HOST_INT_STATUS_REG);
-	else
+	} else {
 		ipc_isr = 0;
+		hhisr &= ~IPC_HHIER_SEC;
+	}
 
 	generated = generated ||
 		(hisr & HISR_INT_STS_MSK) ||
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 64b568a..d1df797 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -76,7 +76,6 @@
  * @dev: mei device
  * @hdr: message header
  */
-static inline
 void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
 {
 	/*
@@ -184,10 +183,7 @@
 		return -EMSGSIZE;
 
 	ret = mei_hbm_cl_disconnect_rsp(dev, cl);
-	mei_cl_set_disconnected(cl);
-	mei_io_cb_free(cb);
-	mei_me_cl_put(cl->me_cl);
-	cl->me_cl = NULL;
+	list_move_tail(&cb->list, &cmpl_list->list);
 
 	return ret;
 }
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 80f9afc..4ef189a 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -207,7 +207,7 @@
 
 		mutex_lock(&dev->device_lock);
 		if (!mei_cl_is_connected(cl)) {
-			rets = -EBUSY;
+			rets = -ENODEV;
 			goto out;
 		}
 	}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 4250555..1b06e2f 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -782,6 +782,8 @@
 
 bool mei_write_is_idle(struct mei_device *dev);
 
+void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr);
+
 #if IS_ENABLED(CONFIG_DEBUG_FS)
 int mei_dbgfs_register(struct mei_device *dev, const char *name);
 void mei_dbgfs_deregister(struct mei_device *dev);
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 27678d8..01e2038 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -84,8 +84,11 @@
 
 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT, mei_me_pch8_cfg)},
 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, mei_me_pch8_cfg)},
-	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_cfg)},
-	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_cfg)},
+	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_sps_cfg)},
+	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_sps_cfg)},
+
+	{MEI_PCI_DEVICE(MEI_DEV_ID_KBP, mei_me_pch8_cfg)},
+	{MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, mei_me_pch8_cfg)},
 
 	/* required last entry */
 	{0, }
diff --git a/drivers/misc/memory_state_time.c b/drivers/misc/memory_state_time.c
new file mode 100644
index 0000000..ba94dcf
--- /dev/null
+++ b/drivers/misc/memory_state_time.c
@@ -0,0 +1,462 @@
+/* drivers/misc/memory_state_time.c
+ *
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/hashtable.h>
+#include <linux/kconfig.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/memory-state-time.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/time.h>
+#include <linux/timekeeping.h>
+#include <linux/workqueue.h>
+
+#define KERNEL_ATTR_RO(_name) \
+static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
+
+#define KERNEL_ATTR_RW(_name) \
+static struct kobj_attribute _name##_attr = \
+	__ATTR(_name, 0644, _name##_show, _name##_store)
+
+#define FREQ_HASH_BITS 4
+DECLARE_HASHTABLE(freq_hash_table, FREQ_HASH_BITS);
+
+static DEFINE_MUTEX(mem_lock);
+
+#define TAG "memory_state_time"
+#define BW_NODE "/soc/memory-state-time"
+#define FREQ_TBL "freq-tbl"
+#define BW_TBL "bw-buckets"
+#define NUM_SOURCES "num-sources"
+
+#define LOWEST_FREQ 2
+
+static int curr_bw;
+static int curr_freq;
+static u32 *bw_buckets;
+static u32 *freq_buckets;
+static int num_freqs;
+static int num_buckets;
+static int registered_bw_sources;
+static u64 last_update;
+static bool init_success;
+static struct workqueue_struct *memory_wq;
+static u32 num_sources = 10;
+static int *bandwidths;
+
+struct freq_entry {
+	int freq;
+	u64 *buckets; /* Bandwidth buckets. */
+	struct hlist_node hash;
+};
+
+struct queue_container {
+	struct work_struct update_state;
+	int value;
+	u64 time_now;
+	int id;
+	struct mutex *lock;
+};
+
+static int find_bucket(int bw)
+{
+	int i;
+
+	if (bw_buckets != NULL) {
+		for (i = 0; i < num_buckets; i++) {
+			if (bw_buckets[i] > bw) {
+				pr_debug("Found bucket %d for bandwidth %d\n",
+					i, bw);
+				return i;
+			}
+		}
+		return num_buckets - 1;
+	}
+	return 0;
+}
+
+static u64 get_time_diff(u64 time_now)
+{
+	u64 ms;
+
+	ms = time_now - last_update;
+	last_update = time_now;
+	return ms;
+}
+
+static ssize_t show_stat_show(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	int i, j;
+	int len = 0;
+	struct freq_entry *freq_entry;
+
+	for (i = 0; i < num_freqs; i++) {
+		hash_for_each_possible(freq_hash_table, freq_entry, hash,
+				freq_buckets[i]) {
+			if (freq_entry->freq == freq_buckets[i]) {
+				len += scnprintf(buf + len, PAGE_SIZE - len,
+						"%d ", freq_buckets[i]);
+				if (len >= PAGE_SIZE)
+					break;
+				for (j = 0; j < num_buckets; j++) {
+					len += scnprintf(buf + len,
+							PAGE_SIZE - len,
+							"%llu ",
+							freq_entry->buckets[j]);
+				}
+				len += scnprintf(buf + len, PAGE_SIZE - len,
+						"\n");
+			}
+		}
+	}
+	pr_debug("Current Time: %llu\n", ktime_get_boot_ns());
+	return len;
+}
+KERNEL_ATTR_RO(show_stat);
+
+static void update_table(u64 time_now)
+{
+	struct freq_entry *freq_entry;
+
+	pr_debug("Last known bw %d freq %d\n", curr_bw, curr_freq);
+	hash_for_each_possible(freq_hash_table, freq_entry, hash, curr_freq) {
+		if (curr_freq == freq_entry->freq) {
+			freq_entry->buckets[find_bucket(curr_bw)]
+					+= get_time_diff(time_now);
+			break;
+		}
+	}
+}
+
+static bool freq_exists(int freq)
+{
+	int i;
+
+	for (i = 0; i < num_freqs; i++) {
+		if (freq == freq_buckets[i])
+			return true;
+	}
+	return false;
+}
+
+static int calculate_total_bw(int bw, int index)
+{
+	int i;
+	int total_bw = 0;
+
+	pr_debug("memory_state_time New bw %d for id %d\n", bw, index);
+	bandwidths[index] = bw;
+	for (i = 0; i < registered_bw_sources; i++)
+		total_bw += bandwidths[i];
+	return total_bw;
+}
+
+static void freq_update_do_work(struct work_struct *work)
+{
+	struct queue_container *freq_state_update
+			= container_of(work, struct queue_container,
+			update_state);
+	if (freq_state_update) {
+		mutex_lock(&mem_lock);
+		update_table(freq_state_update->time_now);
+		curr_freq = freq_state_update->value;
+		mutex_unlock(&mem_lock);
+		kfree(freq_state_update);
+	}
+}
+
+static void bw_update_do_work(struct work_struct *work)
+{
+	struct queue_container *bw_state_update
+			= container_of(work, struct queue_container,
+			update_state);
+	if (bw_state_update) {
+		mutex_lock(&mem_lock);
+		update_table(bw_state_update->time_now);
+		curr_bw = calculate_total_bw(bw_state_update->value,
+				bw_state_update->id);
+		mutex_unlock(&mem_lock);
+		kfree(bw_state_update);
+	}
+}
+
+static void memory_state_freq_update(struct memory_state_update_block *ub,
+		int value)
+{
+	if (IS_ENABLED(CONFIG_MEMORY_STATE_TIME)) {
+		if (freq_exists(value) && init_success) {
+			struct queue_container *freq_container
+				= kmalloc(sizeof(struct queue_container),
+				GFP_KERNEL);
+			if (!freq_container)
+				return;
+			INIT_WORK(&freq_container->update_state,
+					freq_update_do_work);
+			freq_container->time_now = ktime_get_boot_ns();
+			freq_container->value = value;
+			pr_debug("Scheduling freq update in work queue\n");
+			queue_work(memory_wq, &freq_container->update_state);
+		} else {
+			pr_debug("Freq does not exist.\n");
+		}
+	}
+}
+
+static void memory_state_bw_update(struct memory_state_update_block *ub,
+		int value)
+{
+	if (IS_ENABLED(CONFIG_MEMORY_STATE_TIME)) {
+		if (init_success) {
+			struct queue_container *bw_container
+				= kmalloc(sizeof(struct queue_container),
+				GFP_KERNEL);
+			if (!bw_container)
+				return;
+			INIT_WORK(&bw_container->update_state,
+					bw_update_do_work);
+			bw_container->time_now = ktime_get_boot_ns();
+			bw_container->value = value;
+			bw_container->id = ub->id;
+			pr_debug("Scheduling bandwidth update in work queue\n");
+			queue_work(memory_wq, &bw_container->update_state);
+		}
+	}
+}
+
+struct memory_state_update_block *memory_state_register_frequency_source(void)
+{
+	struct memory_state_update_block *block;
+
+	if (IS_ENABLED(CONFIG_MEMORY_STATE_TIME)) {
+		pr_debug("Allocating frequency source\n");
+		block = kmalloc(sizeof(struct memory_state_update_block),
+					GFP_KERNEL);
+		if (!block)
+			return NULL;
+		block->update_call = memory_state_freq_update;
+		return block;
+	}
+	pr_err("Config option disabled.\n");
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(memory_state_register_frequency_source);
+
+struct memory_state_update_block *memory_state_register_bandwidth_source(void)
+{
+	struct memory_state_update_block *block;
+
+	if (IS_ENABLED(CONFIG_MEMORY_STATE_TIME)) {
+		pr_debug("Allocating bandwidth source %d\n",
+				registered_bw_sources);
+		block = kmalloc(sizeof(struct memory_state_update_block),
+					GFP_KERNEL);
+		if (!block)
+			return NULL;
+		block->update_call = memory_state_bw_update;
+		if (registered_bw_sources < num_sources) {
+			block->id = registered_bw_sources++;
+		} else {
+			pr_err("Unable to allocate source; max number reached\n");
+			kfree(block);
+			return NULL;
+		}
+		return block;
+	}
+	pr_err("Config option disabled.\n");
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(memory_state_register_bandwidth_source);
+
+/* Buckets are designated by their maximum.
+ * Returns the buckets decided by the capability of the device.
+ */
+static int get_bw_buckets(struct device *dev)
+{
+	int ret, lenb;
+	struct device_node *node = dev->of_node;
+
+	of_property_read_u32(node, NUM_SOURCES, &num_sources);
+	if (!of_find_property(node, BW_TBL, &lenb)) {
+		pr_err("Missing %s property\n", BW_TBL);
+		return -ENODATA;
+	}
+
+	bandwidths = devm_kzalloc(dev,
+			sizeof(*bandwidths) * num_sources, GFP_KERNEL);
+	if (!bandwidths)
+		return -ENOMEM;
+	lenb /= sizeof(*bw_buckets);
+	bw_buckets = devm_kzalloc(dev, lenb * sizeof(*bw_buckets),
+			GFP_KERNEL);
+	if (!bw_buckets) {
+		devm_kfree(dev, bandwidths);
+		return -ENOMEM;
+	}
+	ret = of_property_read_u32_array(node, BW_TBL, bw_buckets,
+			lenb);
+	if (ret < 0) {
+		devm_kfree(dev, bandwidths);
+		devm_kfree(dev, bw_buckets);
+		pr_err("Unable to read bandwidth table from device tree.\n");
+		return ret;
+	}
+
+	curr_bw = 0;
+	num_buckets = lenb;
+	return 0;
+}
+
+/* Adds struct freq_entry nodes to the hashtable for each compatible frequency.
+ * Returns the supported number of frequencies.
+ */
+static int freq_buckets_init(struct device *dev)
+{
+	struct freq_entry *freq_entry;
+	int i;
+	int ret, lenf;
+	struct device_node *node = dev->of_node;
+
+	if (!of_find_property(node, FREQ_TBL, &lenf)) {
+		pr_err("Missing %s property\n", FREQ_TBL);
+		return -ENODATA;
+	}
+
+	lenf /= sizeof(*freq_buckets);
+	freq_buckets = devm_kzalloc(dev, lenf * sizeof(*freq_buckets),
+			GFP_KERNEL);
+	if (!freq_buckets)
+		return -ENOMEM;
+	pr_debug("freqs found len %d\n", lenf);
+	ret = of_property_read_u32_array(node, FREQ_TBL, freq_buckets,
+			lenf);
+	if (ret < 0) {
+		devm_kfree(dev, freq_buckets);
+		pr_err("Unable to read frequency table from device tree.\n");
+		return ret;
+	}
+	pr_debug("ret freq %d\n", ret);
+
+	num_freqs = lenf;
+	curr_freq = freq_buckets[LOWEST_FREQ];
+
+	for (i = 0; i < num_freqs; i++) {
+		freq_entry = devm_kzalloc(dev, sizeof(struct freq_entry),
+				GFP_KERNEL);
+		if (!freq_entry)
+			return -ENOMEM;
+		freq_entry->buckets = devm_kzalloc(dev, sizeof(u64)*num_buckets,
+				GFP_KERNEL);
+		if (!freq_entry->buckets) {
+			devm_kfree(dev, freq_entry);
+			return -ENOMEM;
+		}
+		pr_debug("memory_state_time Adding freq to ht %d\n",
+				freq_buckets[i]);
+		freq_entry->freq = freq_buckets[i];
+		hash_add(freq_hash_table, &freq_entry->hash, freq_buckets[i]);
+	}
+	return 0;
+}
+
+struct kobject *memory_kobj;
+EXPORT_SYMBOL_GPL(memory_kobj);
+
+static struct attribute *memory_attrs[] = {
+	&show_stat_attr.attr,
+	NULL
+};
+
+static struct attribute_group memory_attr_group = {
+	.attrs = memory_attrs,
+};
+
+static int memory_state_time_probe(struct platform_device *pdev)
+{
+	int error;
+
+	error = get_bw_buckets(&pdev->dev);
+	if (error)
+		return error;
+	error = freq_buckets_init(&pdev->dev);
+	if (error)
+		return error;
+	last_update = ktime_get_boot_ns();
+	init_success = true;
+
+	pr_debug("memory_state_time initialized with num_freqs %d\n",
+			num_freqs);
+	return 0;
+}
+
+static const struct of_device_id match_table[] = {
+	{ .compatible = "memory-state-time" },
+	{}
+};
+
+static struct platform_driver memory_state_time_driver = {
+	.probe = memory_state_time_probe,
+	.driver = {
+		.name = "memory-state-time",
+		.of_match_table = match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init memory_state_time_init(void)
+{
+	int error;
+
+	hash_init(freq_hash_table);
+	memory_wq = create_singlethread_workqueue("memory_wq");
+	if (!memory_wq) {
+		pr_err("Unable to create workqueue.\n");
+		return -EINVAL;
+	}
+	/*
+	 * Create sys/kernel directory for memory_state_time.
+	 */
+	memory_kobj = kobject_create_and_add(TAG, kernel_kobj);
+	if (!memory_kobj) {
+		pr_err("Unable to allocate memory_kobj for sysfs directory.\n");
+		error = -ENOMEM;
+		goto wq;
+	}
+	error = sysfs_create_group(memory_kobj, &memory_attr_group);
+	if (error) {
+		pr_err("Unable to create sysfs folder.\n");
+		goto kobj;
+	}
+
+	error = platform_driver_register(&memory_state_time_driver);
+	if (error) {
+		pr_err("Unable to register memory_state_time platform driver.\n");
+		goto group;
+	}
+	return 0;
+
+group:	sysfs_remove_group(memory_kobj, &memory_attr_group);
+kobj:	kobject_put(memory_kobj);
+wq:	destroy_workqueue(memory_wq);
+	return error;
+}
+module_init(memory_state_time_init);
diff --git a/drivers/misc/uid_cputime.c b/drivers/misc/uid_cputime.c
deleted file mode 100644
index c1ad524..0000000
--- a/drivers/misc/uid_cputime.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/* drivers/misc/uid_cputime.c
- *
- * Copyright (C) 2014 - 2015 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/atomic.h>
-#include <linux/err.h>
-#include <linux/hashtable.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/proc_fs.h>
-#include <linux/profile.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#define UID_HASH_BITS	10
-DECLARE_HASHTABLE(hash_table, UID_HASH_BITS);
-
-static DEFINE_MUTEX(uid_lock);
-static struct proc_dir_entry *parent;
-
-struct uid_entry {
-	uid_t uid;
-	cputime_t utime;
-	cputime_t stime;
-	cputime_t active_utime;
-	cputime_t active_stime;
-	struct hlist_node hash;
-};
-
-static struct uid_entry *find_uid_entry(uid_t uid)
-{
-	struct uid_entry *uid_entry;
-	hash_for_each_possible(hash_table, uid_entry, hash, uid) {
-		if (uid_entry->uid == uid)
-			return uid_entry;
-	}
-	return NULL;
-}
-
-static struct uid_entry *find_or_register_uid(uid_t uid)
-{
-	struct uid_entry *uid_entry;
-
-	uid_entry = find_uid_entry(uid);
-	if (uid_entry)
-		return uid_entry;
-
-	uid_entry = kzalloc(sizeof(struct uid_entry), GFP_ATOMIC);
-	if (!uid_entry)
-		return NULL;
-
-	uid_entry->uid = uid;
-
-	hash_add(hash_table, &uid_entry->hash, uid);
-
-	return uid_entry;
-}
-
-static int uid_stat_show(struct seq_file *m, void *v)
-{
-	struct uid_entry *uid_entry;
-	struct task_struct *task, *temp;
-	cputime_t utime;
-	cputime_t stime;
-	unsigned long bkt;
-
-	mutex_lock(&uid_lock);
-
-	hash_for_each(hash_table, bkt, uid_entry, hash) {
-		uid_entry->active_stime = 0;
-		uid_entry->active_utime = 0;
-	}
-
-	read_lock(&tasklist_lock);
-	do_each_thread(temp, task) {
-		uid_entry = find_or_register_uid(from_kuid_munged(
-			current_user_ns(), task_uid(task)));
-		if (!uid_entry) {
-			read_unlock(&tasklist_lock);
-			mutex_unlock(&uid_lock);
-			pr_err("%s: failed to find the uid_entry for uid %d\n",
-				__func__, from_kuid_munged(current_user_ns(),
-				task_uid(task)));
-			return -ENOMEM;
-		}
-		task_cputime_adjusted(task, &utime, &stime);
-		uid_entry->active_utime += utime;
-		uid_entry->active_stime += stime;
-	} while_each_thread(temp, task);
-	read_unlock(&tasklist_lock);
-
-	hash_for_each(hash_table, bkt, uid_entry, hash) {
-		cputime_t total_utime = uid_entry->utime +
-							uid_entry->active_utime;
-		cputime_t total_stime = uid_entry->stime +
-							uid_entry->active_stime;
-		seq_printf(m, "%d: %llu %llu\n", uid_entry->uid,
-			(unsigned long long)jiffies_to_msecs(
-				cputime_to_jiffies(total_utime)) * USEC_PER_MSEC,
-			(unsigned long long)jiffies_to_msecs(
-				cputime_to_jiffies(total_stime)) * USEC_PER_MSEC);
-	}
-
-	mutex_unlock(&uid_lock);
-	return 0;
-}
-
-static int uid_stat_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, uid_stat_show, PDE_DATA(inode));
-}
-
-static const struct file_operations uid_stat_fops = {
-	.open		= uid_stat_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int uid_remove_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, NULL, NULL);
-}
-
-static ssize_t uid_remove_write(struct file *file,
-			const char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct uid_entry *uid_entry;
-	struct hlist_node *tmp;
-	char uids[128];
-	char *start_uid, *end_uid = NULL;
-	long int uid_start = 0, uid_end = 0;
-
-	if (count >= sizeof(uids))
-		count = sizeof(uids) - 1;
-
-	if (copy_from_user(uids, buffer, count))
-		return -EFAULT;
-
-	uids[count] = '\0';
-	end_uid = uids;
-	start_uid = strsep(&end_uid, "-");
-
-	if (!start_uid || !end_uid)
-		return -EINVAL;
-
-	if (kstrtol(start_uid, 10, &uid_start) != 0 ||
-		kstrtol(end_uid, 10, &uid_end) != 0) {
-		return -EINVAL;
-	}
-	mutex_lock(&uid_lock);
-
-	for (; uid_start <= uid_end; uid_start++) {
-		hash_for_each_possible_safe(hash_table, uid_entry, tmp,
-							hash, (uid_t)uid_start) {
-			if (uid_start == uid_entry->uid) {
-				hash_del(&uid_entry->hash);
-				kfree(uid_entry);
-			}
-		}
-	}
-
-	mutex_unlock(&uid_lock);
-	return count;
-}
-
-static const struct file_operations uid_remove_fops = {
-	.open		= uid_remove_open,
-	.release	= single_release,
-	.write		= uid_remove_write,
-};
-
-static int process_notifier(struct notifier_block *self,
-			unsigned long cmd, void *v)
-{
-	struct task_struct *task = v;
-	struct uid_entry *uid_entry;
-	cputime_t utime, stime;
-	uid_t uid;
-
-	if (!task)
-		return NOTIFY_OK;
-
-	mutex_lock(&uid_lock);
-	uid = from_kuid_munged(current_user_ns(), task_uid(task));
-	uid_entry = find_or_register_uid(uid);
-	if (!uid_entry) {
-		pr_err("%s: failed to find uid %d\n", __func__, uid);
-		goto exit;
-	}
-
-	task_cputime_adjusted(task, &utime, &stime);
-	uid_entry->utime += utime;
-	uid_entry->stime += stime;
-
-exit:
-	mutex_unlock(&uid_lock);
-	return NOTIFY_OK;
-}
-
-static struct notifier_block process_notifier_block = {
-	.notifier_call	= process_notifier,
-};
-
-static int __init proc_uid_cputime_init(void)
-{
-	hash_init(hash_table);
-
-	parent = proc_mkdir("uid_cputime", NULL);
-	if (!parent) {
-		pr_err("%s: failed to create proc entry\n", __func__);
-		return -ENOMEM;
-	}
-
-	proc_create_data("remove_uid_range", S_IWUGO, parent, &uid_remove_fops,
-					NULL);
-
-	proc_create_data("show_uid_stat", S_IRUGO, parent, &uid_stat_fops,
-					NULL);
-
-	profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block);
-
-	return 0;
-}
-
-early_initcall(proc_uid_cputime_init);
diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c
new file mode 100644
index 0000000..3c9d311
--- /dev/null
+++ b/drivers/misc/uid_sys_stats.c
@@ -0,0 +1,484 @@
+/* drivers/misc/uid_cputime.c
+ *
+ * Copyright (C) 2014 - 2015 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/atomic.h>
+#include <linux/err.h>
+#include <linux/hashtable.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/profile.h>
+#include <linux/rtmutex.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#define UID_HASH_BITS	10
+DECLARE_HASHTABLE(hash_table, UID_HASH_BITS);
+
+static DEFINE_RT_MUTEX(uid_lock);
+static struct proc_dir_entry *cpu_parent;
+static struct proc_dir_entry *io_parent;
+static struct proc_dir_entry *proc_parent;
+
+struct io_stats {
+	u64 read_bytes;
+	u64 write_bytes;
+	u64 rchar;
+	u64 wchar;
+	u64 fsync;
+};
+
+#define UID_STATE_FOREGROUND	0
+#define UID_STATE_BACKGROUND	1
+#define UID_STATE_BUCKET_SIZE	2
+
+#define UID_STATE_TOTAL_CURR	2
+#define UID_STATE_TOTAL_LAST	3
+#define UID_STATE_DEAD_TASKS	4
+#define UID_STATE_SIZE		5
+
+struct uid_entry {
+	uid_t uid;
+	cputime_t utime;
+	cputime_t stime;
+	cputime_t active_utime;
+	cputime_t active_stime;
+	int state;
+	struct io_stats io[UID_STATE_SIZE];
+	struct hlist_node hash;
+};
+
+static struct uid_entry *find_uid_entry(uid_t uid)
+{
+	struct uid_entry *uid_entry;
+	hash_for_each_possible(hash_table, uid_entry, hash, uid) {
+		if (uid_entry->uid == uid)
+			return uid_entry;
+	}
+	return NULL;
+}
+
+static struct uid_entry *find_or_register_uid(uid_t uid)
+{
+	struct uid_entry *uid_entry;
+
+	uid_entry = find_uid_entry(uid);
+	if (uid_entry)
+		return uid_entry;
+
+	uid_entry = kzalloc(sizeof(struct uid_entry), GFP_ATOMIC);
+	if (!uid_entry)
+		return NULL;
+
+	uid_entry->uid = uid;
+
+	hash_add(hash_table, &uid_entry->hash, uid);
+
+	return uid_entry;
+}
+
+static int uid_cputime_show(struct seq_file *m, void *v)
+{
+	struct uid_entry *uid_entry = NULL;
+	struct task_struct *task, *temp;
+	struct user_namespace *user_ns = current_user_ns();
+	cputime_t utime;
+	cputime_t stime;
+	unsigned long bkt;
+	uid_t uid;
+
+	rt_mutex_lock(&uid_lock);
+
+	hash_for_each(hash_table, bkt, uid_entry, hash) {
+		uid_entry->active_stime = 0;
+		uid_entry->active_utime = 0;
+	}
+
+	read_lock(&tasklist_lock);
+	do_each_thread(temp, task) {
+		uid = from_kuid_munged(user_ns, task_uid(task));
+		if (!uid_entry || uid_entry->uid != uid)
+			uid_entry = find_or_register_uid(uid);
+		if (!uid_entry) {
+			read_unlock(&tasklist_lock);
+			rt_mutex_unlock(&uid_lock);
+			pr_err("%s: failed to find the uid_entry for uid %d\n",
+				__func__, uid);
+			return -ENOMEM;
+		}
+		task_cputime_adjusted(task, &utime, &stime);
+		uid_entry->active_utime += utime;
+		uid_entry->active_stime += stime;
+	} while_each_thread(temp, task);
+	read_unlock(&tasklist_lock);
+
+	hash_for_each(hash_table, bkt, uid_entry, hash) {
+		cputime_t total_utime = uid_entry->utime +
+							uid_entry->active_utime;
+		cputime_t total_stime = uid_entry->stime +
+							uid_entry->active_stime;
+		seq_printf(m, "%d: %llu %llu\n", uid_entry->uid,
+			(unsigned long long)jiffies_to_msecs(
+				cputime_to_jiffies(total_utime)) * USEC_PER_MSEC,
+			(unsigned long long)jiffies_to_msecs(
+				cputime_to_jiffies(total_stime)) * USEC_PER_MSEC);
+	}
+
+	rt_mutex_unlock(&uid_lock);
+	return 0;
+}
+
+static int uid_cputime_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, uid_cputime_show, PDE_DATA(inode));
+}
+
+static const struct file_operations uid_cputime_fops = {
+	.open		= uid_cputime_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int uid_remove_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, NULL, NULL);
+}
+
+static ssize_t uid_remove_write(struct file *file,
+			const char __user *buffer, size_t count, loff_t *ppos)
+{
+	struct uid_entry *uid_entry;
+	struct hlist_node *tmp;
+	char uids[128];
+	char *start_uid, *end_uid = NULL;
+	long int uid_start = 0, uid_end = 0;
+
+	if (count >= sizeof(uids))
+		count = sizeof(uids) - 1;
+
+	if (copy_from_user(uids, buffer, count))
+		return -EFAULT;
+
+	uids[count] = '\0';
+	end_uid = uids;
+	start_uid = strsep(&end_uid, "-");
+
+	if (!start_uid || !end_uid)
+		return -EINVAL;
+
+	if (kstrtol(start_uid, 10, &uid_start) != 0 ||
+		kstrtol(end_uid, 10, &uid_end) != 0) {
+		return -EINVAL;
+	}
+	rt_mutex_lock(&uid_lock);
+
+	for (; uid_start <= uid_end; uid_start++) {
+		hash_for_each_possible_safe(hash_table, uid_entry, tmp,
+							hash, (uid_t)uid_start) {
+			if (uid_start == uid_entry->uid) {
+				hash_del(&uid_entry->hash);
+				kfree(uid_entry);
+			}
+		}
+	}
+
+	rt_mutex_unlock(&uid_lock);
+	return count;
+}
+
+static const struct file_operations uid_remove_fops = {
+	.open		= uid_remove_open,
+	.release	= single_release,
+	.write		= uid_remove_write,
+};
+
+static u64 compute_write_bytes(struct task_struct *task)
+{
+	if (task->ioac.write_bytes <= task->ioac.cancelled_write_bytes)
+		return 0;
+
+	return task->ioac.write_bytes - task->ioac.cancelled_write_bytes;
+}
+
+static void add_uid_io_stats(struct uid_entry *uid_entry,
+			struct task_struct *task, int slot)
+{
+	struct io_stats *io_slot = &uid_entry->io[slot];
+
+	io_slot->read_bytes += task->ioac.read_bytes;
+	io_slot->write_bytes += compute_write_bytes(task);
+	io_slot->rchar += task->ioac.rchar;
+	io_slot->wchar += task->ioac.wchar;
+	io_slot->fsync += task->ioac.syscfs;
+}
+
+static void compute_uid_io_bucket_stats(struct io_stats *io_bucket,
+					struct io_stats *io_curr,
+					struct io_stats *io_last,
+					struct io_stats *io_dead)
+{
+	io_bucket->read_bytes += io_curr->read_bytes + io_dead->read_bytes -
+		io_last->read_bytes;
+	io_bucket->write_bytes += io_curr->write_bytes + io_dead->write_bytes -
+		io_last->write_bytes;
+	io_bucket->rchar += io_curr->rchar + io_dead->rchar - io_last->rchar;
+	io_bucket->wchar += io_curr->wchar + io_dead->wchar - io_last->wchar;
+	io_bucket->fsync += io_curr->fsync + io_dead->fsync - io_last->fsync;
+
+	io_last->read_bytes = io_curr->read_bytes;
+	io_last->write_bytes = io_curr->write_bytes;
+	io_last->rchar = io_curr->rchar;
+	io_last->wchar = io_curr->wchar;
+	io_last->fsync = io_curr->fsync;
+
+	memset(io_dead, 0, sizeof(struct io_stats));
+}
+
+static void update_io_stats_all_locked(void)
+{
+	struct uid_entry *uid_entry = NULL;
+	struct task_struct *task, *temp;
+	struct user_namespace *user_ns = current_user_ns();
+	unsigned long bkt;
+	uid_t uid;
+
+	hash_for_each(hash_table, bkt, uid_entry, hash)
+		memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0,
+			sizeof(struct io_stats));
+
+	rcu_read_lock();
+	do_each_thread(temp, task) {
+		uid = from_kuid_munged(user_ns, task_uid(task));
+		if (!uid_entry || uid_entry->uid != uid)
+			uid_entry = find_or_register_uid(uid);
+		if (!uid_entry)
+			continue;
+		add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR);
+	} while_each_thread(temp, task);
+	rcu_read_unlock();
+
+	hash_for_each(hash_table, bkt, uid_entry, hash) {
+		compute_uid_io_bucket_stats(&uid_entry->io[uid_entry->state],
+					&uid_entry->io[UID_STATE_TOTAL_CURR],
+					&uid_entry->io[UID_STATE_TOTAL_LAST],
+					&uid_entry->io[UID_STATE_DEAD_TASKS]);
+	}
+}
+
+static void update_io_stats_uid_locked(struct uid_entry *uid_entry)
+{
+	struct task_struct *task, *temp;
+	struct user_namespace *user_ns = current_user_ns();
+
+	memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0,
+		sizeof(struct io_stats));
+
+	rcu_read_lock();
+	do_each_thread(temp, task) {
+		if (from_kuid_munged(user_ns, task_uid(task)) != uid_entry->uid)
+			continue;
+		add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR);
+	} while_each_thread(temp, task);
+	rcu_read_unlock();
+
+	compute_uid_io_bucket_stats(&uid_entry->io[uid_entry->state],
+				&uid_entry->io[UID_STATE_TOTAL_CURR],
+				&uid_entry->io[UID_STATE_TOTAL_LAST],
+				&uid_entry->io[UID_STATE_DEAD_TASKS]);
+}
+
+static int uid_io_show(struct seq_file *m, void *v)
+{
+	struct uid_entry *uid_entry;
+	unsigned long bkt;
+
+	rt_mutex_lock(&uid_lock);
+
+	update_io_stats_all_locked();
+
+	hash_for_each(hash_table, bkt, uid_entry, hash) {
+		seq_printf(m, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
+			uid_entry->uid,
+			uid_entry->io[UID_STATE_FOREGROUND].rchar,
+			uid_entry->io[UID_STATE_FOREGROUND].wchar,
+			uid_entry->io[UID_STATE_FOREGROUND].read_bytes,
+			uid_entry->io[UID_STATE_FOREGROUND].write_bytes,
+			uid_entry->io[UID_STATE_BACKGROUND].rchar,
+			uid_entry->io[UID_STATE_BACKGROUND].wchar,
+			uid_entry->io[UID_STATE_BACKGROUND].read_bytes,
+			uid_entry->io[UID_STATE_BACKGROUND].write_bytes,
+			uid_entry->io[UID_STATE_FOREGROUND].fsync,
+			uid_entry->io[UID_STATE_BACKGROUND].fsync);
+	}
+
+	rt_mutex_unlock(&uid_lock);
+
+	return 0;
+}
+
+static int uid_io_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, uid_io_show, PDE_DATA(inode));
+}
+
+static const struct file_operations uid_io_fops = {
+	.open		= uid_io_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int uid_procstat_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, NULL, NULL);
+}
+
+static ssize_t uid_procstat_write(struct file *file,
+			const char __user *buffer, size_t count, loff_t *ppos)
+{
+	struct uid_entry *uid_entry;
+	uid_t uid;
+	int argc, state;
+	char input[128];
+
+	if (count >= sizeof(input))
+		return -EINVAL;
+
+	if (copy_from_user(input, buffer, count))
+		return -EFAULT;
+
+	input[count] = '\0';
+
+	argc = sscanf(input, "%u %d", &uid, &state);
+	if (argc != 2)
+		return -EINVAL;
+
+	if (state != UID_STATE_BACKGROUND && state != UID_STATE_FOREGROUND)
+		return -EINVAL;
+
+	rt_mutex_lock(&uid_lock);
+
+	uid_entry = find_or_register_uid(uid);
+	if (!uid_entry) {
+		rt_mutex_unlock(&uid_lock);
+		return -EINVAL;
+	}
+
+	if (uid_entry->state == state) {
+		rt_mutex_unlock(&uid_lock);
+		return count;
+	}
+
+	update_io_stats_uid_locked(uid_entry);
+
+	uid_entry->state = state;
+
+	rt_mutex_unlock(&uid_lock);
+
+	return count;
+}
+
+static const struct file_operations uid_procstat_fops = {
+	.open		= uid_procstat_open,
+	.release	= single_release,
+	.write		= uid_procstat_write,
+};
+
+static int process_notifier(struct notifier_block *self,
+			unsigned long cmd, void *v)
+{
+	struct task_struct *task = v;
+	struct uid_entry *uid_entry;
+	cputime_t utime, stime;
+	uid_t uid;
+
+	if (!task)
+		return NOTIFY_OK;
+
+	rt_mutex_lock(&uid_lock);
+	uid = from_kuid_munged(current_user_ns(), task_uid(task));
+	uid_entry = find_or_register_uid(uid);
+	if (!uid_entry) {
+		pr_err("%s: failed to find uid %d\n", __func__, uid);
+		goto exit;
+	}
+
+	task_cputime_adjusted(task, &utime, &stime);
+	uid_entry->utime += utime;
+	uid_entry->stime += stime;
+
+	add_uid_io_stats(uid_entry, task, UID_STATE_DEAD_TASKS);
+
+exit:
+	rt_mutex_unlock(&uid_lock);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block process_notifier_block = {
+	.notifier_call	= process_notifier,
+};
+
+static int __init proc_uid_sys_stats_init(void)
+{
+	hash_init(hash_table);
+
+	cpu_parent = proc_mkdir("uid_cputime", NULL);
+	if (!cpu_parent) {
+		pr_err("%s: failed to create uid_cputime proc entry\n",
+			__func__);
+		goto err;
+	}
+
+	proc_create_data("remove_uid_range", 0222, cpu_parent,
+		&uid_remove_fops, NULL);
+	proc_create_data("show_uid_stat", 0444, cpu_parent,
+		&uid_cputime_fops, NULL);
+
+	io_parent = proc_mkdir("uid_io", NULL);
+	if (!io_parent) {
+		pr_err("%s: failed to create uid_io proc entry\n",
+			__func__);
+		goto err;
+	}
+
+	proc_create_data("stats", 0444, io_parent,
+		&uid_io_fops, NULL);
+
+	proc_parent = proc_mkdir("uid_procstat", NULL);
+	if (!proc_parent) {
+		pr_err("%s: failed to create uid_procstat proc entry\n",
+			__func__);
+		goto err;
+	}
+
+	proc_create_data("set", 0222, proc_parent,
+		&uid_procstat_fops, NULL);
+
+	profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block);
+
+	return 0;
+
+err:
+	remove_proc_subtree("uid_cputime", NULL);
+	remove_proc_subtree("uid_io", NULL);
+	remove_proc_subtree("uid_procstat", NULL);
+	return -ENOMEM;
+}
+
+early_initcall(proc_uid_sys_stats_init);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index c15d3f3..8d169d5 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2017,7 +2017,7 @@
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_packed *packed = mqrq->packed;
 	bool do_rel_wr, do_data_tag;
-	u32 *packed_cmd_hdr;
+	__le32 *packed_cmd_hdr;
 	u8 hdr_blocks;
 	u8 i = 1;
 
@@ -2029,8 +2029,8 @@
 
 	packed_cmd_hdr = packed->cmd_hdr;
 	memset(packed_cmd_hdr, 0, sizeof(packed->cmd_hdr));
-	packed_cmd_hdr[0] = (packed->nr_entries << 16) |
-		(PACKED_CMD_WR << 8) | PACKED_CMD_VER;
+	packed_cmd_hdr[0] = cpu_to_le32((packed->nr_entries << 16) |
+		(PACKED_CMD_WR << 8) | PACKED_CMD_VER);
 	hdr_blocks = mmc_large_sector(card) ? 8 : 1;
 
 	/*
@@ -2044,14 +2044,14 @@
 			((brq->data.blocks * brq->data.blksz) >=
 			 card->ext_csd.data_tag_unit_size);
 		/* Argument of CMD23 */
-		packed_cmd_hdr[(i * 2)] =
+		packed_cmd_hdr[(i * 2)] = cpu_to_le32(
 			(do_rel_wr ? MMC_CMD23_ARG_REL_WR : 0) |
 			(do_data_tag ? MMC_CMD23_ARG_TAG_REQ : 0) |
-			blk_rq_sectors(prq);
+			blk_rq_sectors(prq));
 		/* Argument of CMD18 or CMD25 */
-		packed_cmd_hdr[((i * 2)) + 1] =
+		packed_cmd_hdr[((i * 2)) + 1] = cpu_to_le32(
 			mmc_card_blockaddr(card) ?
-			blk_rq_pos(prq) : blk_rq_pos(prq) << 9;
+			blk_rq_pos(prq) : blk_rq_pos(prq) << 9);
 		packed->blocks += blk_rq_sectors(prq);
 		i++;
 	}
@@ -2547,7 +2547,8 @@
 	set_capacity(md->disk, size);
 
 	if (mmc_host_cmd23(card->host)) {
-		if (mmc_card_mmc(card) ||
+		if ((mmc_card_mmc(card) &&
+		     card->csd.mmca_vsn >= CSD_SPEC_VER_3) ||
 		    (mmc_card_sd(card) &&
 		     card->scr.cmds & SD_SCR_CMD23_SUPPORT))
 			md->flags |= MMC_BLK_CMD23;
@@ -2816,11 +2817,12 @@
 		  MMC_QUIRK_BLK_NO_CMD23),
 
 	/*
-	 * Some Micron MMC cards needs longer data read timeout than
-	 * indicated in CSD.
+	 * Some MMC cards need longer data read timeout than indicated in CSD.
 	 */
 	MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
 		  MMC_QUIRK_LONG_READ_TIME),
+	MMC_FIXUP("008GE0", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_LONG_READ_TIME),
 
 	/*
 	 * On these Samsung MoviNAND parts, performing secure erase or
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 7fc9174..9a11aaa 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -791,7 +791,7 @@
 	struct mmc_async_req *cur_areq = &test_areq[0].areq;
 	struct mmc_async_req *other_areq = &test_areq[1].areq;
 	int i;
-	int ret;
+	int ret = RESULT_OK;
 
 	test_areq[0].test = test;
 	test_areq[1].test = test;
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index d890d88..1dc4c99 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -25,7 +25,7 @@
 
 struct mmc_packed {
 	struct list_head	list;
-	u32			cmd_hdr[1024];
+	__le32			cmd_hdr[1024];
 	unsigned int		blocks;
 	u8			nr_entries;
 	u8			retries;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9fab525..2986e27 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -183,6 +183,19 @@
 			pr_debug("%s:     %d bytes transferred: %d\n",
 				mmc_hostname(host),
 				mrq->data->bytes_xfered, mrq->data->error);
+#ifdef CONFIG_BLOCK
+			if (mrq->lat_hist_enabled) {
+				ktime_t completion;
+				u_int64_t delta_us;
+
+				completion = ktime_get();
+				delta_us = ktime_us_delta(completion,
+							  mrq->io_start);
+				blk_update_latency_hist(&host->io_lat_s,
+					(mrq->data->flags & MMC_DATA_READ),
+					delta_us);
+			}
+#endif
 			trace_mmc_blk_rw_end(cmd->opcode, cmd->arg, mrq->data);
 		}
 
@@ -627,6 +640,13 @@
 	}
 
 	if (!err && areq) {
+#ifdef CONFIG_BLOCK
+		if (host->latency_hist_enabled) {
+			areq->mrq->io_start = ktime_get();
+			areq->mrq->lat_hist_enabled = 1;
+		} else
+			areq->mrq->lat_hist_enabled = 0;
+#endif
 		trace_mmc_blk_rw_start(areq->mrq->cmd->opcode,
 				       areq->mrq->cmd->arg,
 				       areq->mrq->data);
@@ -887,11 +907,11 @@
 	/*
 	 * Some cards require longer data read timeout than indicated in CSD.
 	 * Address this by setting the read timeout to a "reasonably high"
-	 * value. For the cards tested, 300ms has proven enough. If necessary,
+	 * value. For the cards tested, 600ms has proven enough. If necessary,
 	 * this value can be increased if other problematic cards require this.
 	 */
 	if (mmc_card_long_read_time(card) && data->flags & MMC_DATA_READ) {
-		data->timeout_ns = 300000000;
+		data->timeout_ns = 600000000;
 		data->timeout_clks = 0;
 	}
 
@@ -1964,7 +1984,7 @@
 }
 
 static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
-				          unsigned int arg, unsigned int qty)
+					  unsigned int arg, unsigned int qty)
 {
 	unsigned int erase_timeout;
 
@@ -2907,6 +2927,56 @@
 	destroy_workqueue(workqueue);
 }
 
+#ifdef CONFIG_BLOCK
+static ssize_t
+latency_hist_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+
+	return blk_latency_hist_show(&host->io_lat_s, buf);
+}
+
+/*
+ * Values permitted 0, 1, 2.
+ * 0 -> Disable IO latency histograms (default)
+ * 1 -> Enable IO latency histograms
+ * 2 -> Zero out IO latency histograms
+ */
+static ssize_t
+latency_hist_store(struct device *dev, struct device_attribute *attr,
+		   const char *buf, size_t count)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+	long value;
+
+	if (kstrtol(buf, 0, &value))
+		return -EINVAL;
+	if (value == BLK_IO_LAT_HIST_ZERO)
+		blk_zero_latency_hist(&host->io_lat_s);
+	else if (value == BLK_IO_LAT_HIST_ENABLE ||
+		 value == BLK_IO_LAT_HIST_DISABLE)
+		host->latency_hist_enabled = value;
+	return count;
+}
+
+static DEVICE_ATTR(latency_hist, S_IRUGO | S_IWUSR,
+		   latency_hist_show, latency_hist_store);
+
+void
+mmc_latency_hist_sysfs_init(struct mmc_host *host)
+{
+	if (device_create_file(&host->class_dev, &dev_attr_latency_hist))
+		dev_err(&host->class_dev,
+			"Failed to create latency_hist sysfs entry\n");
+}
+
+void
+mmc_latency_hist_sysfs_exit(struct mmc_host *host)
+{
+	device_remove_file(&host->class_dev, &dev_attr_latency_hist);
+}
+#endif
+
 subsys_initcall(mmc_init);
 module_exit(mmc_exit);
 
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index da950c4..443fdfc 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -32,8 +32,6 @@
 #include "slot-gpio.h"
 #include "pwrseq.h"
 
-#define cls_dev_to_mmc_host(d)	container_of(d, struct mmc_host, class_dev)
-
 static DEFINE_IDR(mmc_host_idr);
 static DEFINE_SPINLOCK(mmc_host_lock);
 
@@ -394,8 +392,13 @@
 	mmc_add_host_debugfs(host);
 #endif
 
+#ifdef CONFIG_BLOCK
+	mmc_latency_hist_sysfs_init(host);
+#endif
+
 	mmc_start_host(host);
-	register_pm_notifier(&host->pm_notify);
+	if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
+		register_pm_notifier(&host->pm_notify);
 
 	return 0;
 }
@@ -412,13 +415,19 @@
  */
 void mmc_remove_host(struct mmc_host *host)
 {
-	unregister_pm_notifier(&host->pm_notify);
+	if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
+		unregister_pm_notifier(&host->pm_notify);
+
 	mmc_stop_host(host);
 
 #ifdef CONFIG_DEBUG_FS
 	mmc_remove_host_debugfs(host);
 #endif
 
+#ifdef CONFIG_BLOCK
+	mmc_latency_hist_sysfs_exit(host);
+#endif
+
 	device_del(&host->class_dev);
 
 	led_trigger_unregister_simple(host->led);
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
index 992bf53..bf38533 100644
--- a/drivers/mmc/core/host.h
+++ b/drivers/mmc/core/host.h
@@ -12,6 +12,8 @@
 #define _MMC_CORE_HOST_H
 #include <linux/mmc/host.h>
 
+#define cls_dev_to_mmc_host(d)	container_of(d, struct mmc_host, class_dev)
+
 int mmc_register_host_class(void);
 void mmc_unregister_host_class(void);
 
@@ -21,5 +23,8 @@
 void mmc_retune_release(struct mmc_host *host);
 int mmc_retune(struct mmc_host *host);
 
+void mmc_latency_hist_sysfs_init(struct mmc_host *host);
+void mmc_latency_hist_sysfs_exit(struct mmc_host *host);
+
 #endif
 
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 3d5087b..83b9bf8 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -333,6 +333,9 @@
 	}
 }
 
+/* Minimum partition switch timeout in milliseconds */
+#define MMC_MIN_PART_SWITCH_TIME	300
+
 /*
  * Decode extended CSD.
  */
@@ -397,6 +400,10 @@
 
 		/* EXT_CSD value is in units of 10ms, but we store in ms */
 		card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME];
+		/* Some eMMC set the value too low so set a minimum */
+		if (card->ext_csd.part_time &&
+		    card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME)
+			card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME;
 
 		/* Sleep / awake timeout in 100ns units */
 		if (sa_shift > 0 && sa_shift <= 0x17)
@@ -585,6 +592,12 @@
 		card->ext_csd.ffu_capable =
 			(ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) &&
 			!(ext_csd[EXT_CSD_FW_CONFIG] & 0x1);
+
+		card->ext_csd.pre_eol_info = ext_csd[EXT_CSD_PRE_EOL_INFO];
+		card->ext_csd.device_life_time_est_typ_a =
+			ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
+		card->ext_csd.device_life_time_est_typ_b =
+			ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
 	}
 out:
 	return err;
@@ -714,6 +727,11 @@
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv);
+MMC_DEV_ATTR(rev, "0x%x\n", card->ext_csd.rev);
+MMC_DEV_ATTR(pre_eol_info, "%02x\n", card->ext_csd.pre_eol_info);
+MMC_DEV_ATTR(life_time, "0x%02x 0x%02x\n",
+	card->ext_csd.device_life_time_est_typ_a,
+	card->ext_csd.device_life_time_est_typ_b);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
 MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
 		card->ext_csd.enhanced_area_offset);
@@ -750,6 +768,9 @@
 	&dev_attr_name.attr,
 	&dev_attr_oemid.attr,
 	&dev_attr_prv.attr,
+	&dev_attr_rev.attr,
+	&dev_attr_pre_eol_info.attr,
+	&dev_attr_life_time.attr,
 	&dev_attr_serial.attr,
 	&dev_attr_enhanced_area_offset.attr,
 	&dev_attr_enhanced_area_size.attr,
@@ -1574,10 +1595,10 @@
 		err = mmc_select_hs400(card);
 		if (err)
 			goto free_card;
-	} else if (mmc_card_hs(card)) {
+	} else {
 		/* Select the desired bus width optionally */
 		err = mmc_select_bus_width(card);
-		if (!IS_ERR_VALUE(err)) {
+		if (!IS_ERR_VALUE(err) && mmc_card_hs(card)) {
 			err = mmc_select_hs_ddr(card);
 			if (err)
 				goto free_card;
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index 78cb4d5..8fdeb07 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -384,6 +384,39 @@
 EXPORT_SYMBOL_GPL(sdio_readb);
 
 /**
+ *	sdio_readb_ext - read a single byte from a SDIO function
+ *	@func: SDIO function to access
+ *	@addr: address to read
+ *	@err_ret: optional status value from transfer
+ *	@in: value to add to argument
+ *
+ *	Reads a single byte from the address space of a given SDIO
+ *	function. If there is a problem reading the address, 0xff
+ *	is returned and @err_ret will contain the error code.
+ */
+unsigned char sdio_readb_ext(struct sdio_func *func, unsigned int addr,
+	int *err_ret, unsigned in)
+{
+	int ret;
+	unsigned char val;
+
+	BUG_ON(!func);
+
+	if (err_ret)
+		*err_ret = 0;
+
+	ret = mmc_io_rw_direct(func->card, 0, func->num, addr, (u8)in, &val);
+	if (ret) {
+		if (err_ret)
+			*err_ret = ret;
+		return 0xFF;
+	}
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(sdio_readb_ext);
+
+/**
  *	sdio_writeb - write a single byte to a SDIO function
  *	@func: SDIO function to access
  *	@b: byte to write
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1dee533..2e6d2ff 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -97,6 +97,7 @@
 config MMC_SDHCI_ACPI
 	tristate "SDHCI support for ACPI enumerated SDHCI controllers"
 	depends on MMC_SDHCI && ACPI
+	select IOSF_MBI if X86
 	help
 	  This selects support for ACPI enumerated SDHCI controllers,
 	  identified by ACPI Compatibility ID PNP0D40 or specific
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 7e1d13b..7dcfb1d 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -59,12 +59,13 @@
 	host->pdata = pdev->dev.platform_data;
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	/* Get registers' physical base address */
-	host->phy_regs = (void *)(regs->start);
 	host->regs = devm_ioremap_resource(&pdev->dev, regs);
 	if (IS_ERR(host->regs))
 		return PTR_ERR(host->regs);
 
+	/* Get registers' physical base address */
+	host->phy_regs = regs->start;
+
 	platform_set_drvdata(pdev, host);
 	return dw_mci_probe(host);
 }
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 7a6cedb..fb204ee 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -699,7 +699,7 @@
 	int ret = 0;
 
 	/* Set external dma config: burst size, burst width */
-	cfg.dst_addr = (dma_addr_t)(host->phy_regs + fifo_offset);
+	cfg.dst_addr = host->phy_regs + fifo_offset;
 	cfg.src_addr = cfg.dst_addr;
 	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index d839147..c8b8ac6 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -309,6 +309,9 @@
 	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
 	cmd1 = cmd->arg;
 
+	if (cmd->opcode == MMC_STOP_TRANSMISSION)
+		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
+
 	if (host->sdio_irq_en) {
 		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
 		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
@@ -417,8 +420,7 @@
 		       ssp->base + HW_SSP_BLOCK_SIZE);
 	}
 
-	if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
-	    (cmd->opcode == SD_IO_RW_EXTENDED))
+	if (cmd->opcode == SD_IO_RW_EXTENDED)
 		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
 
 	cmd1 = cmd->arg;
@@ -661,13 +663,13 @@
 
 	platform_set_drvdata(pdev, mmc);
 
+	spin_lock_init(&host->lock);
+
 	ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0,
 			       dev_name(&pdev->dev), host);
 	if (ret)
 		goto out_free_dma;
 
-	spin_lock_init(&host->lock);
-
 	ret = mmc_add_host(mmc);
 	if (ret)
 		goto out_free_dma;
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 28a057f..72bbb12 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -798,14 +798,16 @@
 		gpio_direction_output(gpio_power,
 				      host->pdata->gpio_power_invert);
 	}
-	if (gpio_is_valid(gpio_ro))
+	if (gpio_is_valid(gpio_ro)) {
 		ret = mmc_gpio_request_ro(mmc, gpio_ro);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro);
-		goto out;
-	} else {
-		mmc->caps2 |= host->pdata->gpio_card_ro_invert ?
-			0 : MMC_CAP2_RO_ACTIVE_HIGH;
+		if (ret) {
+			dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n",
+				gpio_ro);
+			goto out;
+		} else {
+			mmc->caps2 |= host->pdata->gpio_card_ro_invert ?
+				0 : MMC_CAP2_RO_ACTIVE_HIGH;
+		}
 	}
 
 	if (gpio_is_valid(gpio_cd))
diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c
index 6c71fc9..da9f71b 100644
--- a/drivers/mmc/host/rtsx_usb_sdmmc.c
+++ b/drivers/mmc/host/rtsx_usb_sdmmc.c
@@ -1138,11 +1138,6 @@
 	dev_dbg(sdmmc_dev(host), "%s\n", __func__);
 	mutex_lock(&ucr->dev_mutex);
 
-	if (rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD)) {
-		mutex_unlock(&ucr->dev_mutex);
-		return;
-	}
-
 	sd_set_power_mode(host, ios->power_mode);
 	sd_set_bus_width(host, ios->bus_width);
 	sd_set_timing(host, ios->timing, &host->ddr_mode);
@@ -1314,6 +1309,7 @@
 		container_of(work, struct rtsx_usb_sdmmc, led_work);
 	struct rtsx_ucr *ucr = host->ucr;
 
+	pm_runtime_get_sync(sdmmc_dev(host));
 	mutex_lock(&ucr->dev_mutex);
 
 	if (host->led.brightness == LED_OFF)
@@ -1322,6 +1318,7 @@
 		rtsx_usb_turn_on_led(ucr);
 
 	mutex_unlock(&ucr->dev_mutex);
+	pm_runtime_put(sdmmc_dev(host));
 }
 #endif
 
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index a5cda92..5a05bf4 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -41,6 +41,11 @@
 #include <linux/mmc/pm.h>
 #include <linux/mmc/slot-gpio.h>
 
+#ifdef CONFIG_X86
+#include <asm/cpu_device_id.h>
+#include <asm/iosf_mbi.h>
+#endif
+
 #include "sdhci.h"
 
 enum {
@@ -146,6 +151,75 @@
 	.ops = &sdhci_acpi_ops_int,
 };
 
+#ifdef CONFIG_X86
+
+static bool sdhci_acpi_byt(void)
+{
+	static const struct x86_cpu_id byt[] = {
+		{ X86_VENDOR_INTEL, 6, 0x37 },
+		{}
+	};
+
+	return x86_match_cpu(byt);
+}
+
+#define BYT_IOSF_SCCEP			0x63
+#define BYT_IOSF_OCP_NETCTRL0		0x1078
+#define BYT_IOSF_OCP_TIMEOUT_BASE	GENMASK(10, 8)
+
+static void sdhci_acpi_byt_setting(struct device *dev)
+{
+	u32 val = 0;
+
+	if (!sdhci_acpi_byt())
+		return;
+
+	if (iosf_mbi_read(BYT_IOSF_SCCEP, 0x06, BYT_IOSF_OCP_NETCTRL0,
+			  &val)) {
+		dev_err(dev, "%s read error\n", __func__);
+		return;
+	}
+
+	if (!(val & BYT_IOSF_OCP_TIMEOUT_BASE))
+		return;
+
+	val &= ~BYT_IOSF_OCP_TIMEOUT_BASE;
+
+	if (iosf_mbi_write(BYT_IOSF_SCCEP, 0x07, BYT_IOSF_OCP_NETCTRL0,
+			   val)) {
+		dev_err(dev, "%s write error\n", __func__);
+		return;
+	}
+
+	dev_dbg(dev, "%s completed\n", __func__);
+}
+
+static bool sdhci_acpi_byt_defer(struct device *dev)
+{
+	if (!sdhci_acpi_byt())
+		return false;
+
+	if (!iosf_mbi_available())
+		return true;
+
+	sdhci_acpi_byt_setting(dev);
+
+	return false;
+}
+
+#else
+
+static inline void sdhci_acpi_byt_setting(struct device *dev)
+{
+}
+
+static inline bool sdhci_acpi_byt_defer(struct device *dev)
+{
+	return false;
+}
+
+#endif
+
 static int bxt_get_cd(struct mmc_host *mmc)
 {
 	int gpio_cd = mmc_gpio_get_cd(mmc);
@@ -233,7 +307,7 @@
 	.chip    = &sdhci_acpi_chip_int,
 	.caps    = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
 		   MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
-		   MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
+		   MMC_CAP_WAIT_WHILE_BUSY,
 	.caps2   = MMC_CAP2_HC_ERASE_SZ,
 	.flags   = SDHCI_ACPI_RUNTIME_PM,
 	.quirks  = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
@@ -248,7 +322,7 @@
 		   SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
 	.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
 	.caps    = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD |
-		   MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
+		   MMC_CAP_WAIT_WHILE_BUSY,
 	.flags   = SDHCI_ACPI_RUNTIME_PM,
 	.pm_caps = MMC_PM_KEEP_POWER,
 	.probe_slot	= sdhci_acpi_sdio_probe_slot,
@@ -260,7 +334,7 @@
 	.quirks  = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
 	.quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
 		   SDHCI_QUIRK2_STOP_WITH_TC,
-	.caps    = MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
+	.caps    = MMC_CAP_WAIT_WHILE_BUSY,
 	.probe_slot	= sdhci_acpi_sd_probe_slot,
 };
 
@@ -337,6 +411,9 @@
 	if (acpi_bus_get_status(device) || !device->status.present)
 		return -ENODEV;
 
+	if (sdhci_acpi_byt_defer(dev))
+		return -EPROBE_DEFER;
+
 	hid = acpi_device_hid(device);
 	uid = device->pnp.unique_id;
 
@@ -460,6 +537,8 @@
 {
 	struct sdhci_acpi_host *c = dev_get_drvdata(dev);
 
+	sdhci_acpi_byt_setting(&c->pdev->dev);
+
 	return sdhci_resume_host(c->host);
 }
 
@@ -483,6 +562,8 @@
 {
 	struct sdhci_acpi_host *c = dev_get_drvdata(dev);
 
+	sdhci_acpi_byt_setting(&c->pdev->dev);
+
 	return sdhci_runtime_resume_host(c->host);
 }
 
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 1f1582f..8d83877 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -804,6 +804,7 @@
 
 	switch (uhs) {
 	case MMC_TIMING_UHS_SDR50:
+	case MMC_TIMING_UHS_DDR50:
 		pinctrl = imx_data->pins_100mhz;
 		break;
 	case MMC_TIMING_UHS_SDR104:
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c
index 3b423b0..f280744 100644
--- a/drivers/mmc/host/sdhci-iproc.c
+++ b/drivers/mmc/host/sdhci-iproc.c
@@ -156,7 +156,8 @@
 };
 
 static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = {
-	.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
+	.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+		  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
 	.quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
 	.ops = &sdhci_iproc_ops,
 };
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 6101548..5ebe6eb 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -361,7 +361,6 @@
 {
 	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
 				 MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
-				 MMC_CAP_BUS_WIDTH_TEST |
 				 MMC_CAP_WAIT_WHILE_BUSY;
 	slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
 	slot->hw_reset = sdhci_pci_int_hw_reset;
@@ -377,15 +376,13 @@
 static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
 	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
-				 MMC_CAP_BUS_WIDTH_TEST |
 				 MMC_CAP_WAIT_WHILE_BUSY;
 	return 0;
 }
 
 static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
 {
-	slot->host->mmc->caps |= MMC_CAP_BUS_WIDTH_TEST |
-				 MMC_CAP_WAIT_WHILE_BUSY;
+	slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
 	slot->cd_con_id = NULL;
 	slot->cd_idx = 0;
 	slot->cd_override_level = true;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 1a802af..62d37d2 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -492,7 +492,7 @@
 		host->align_buffer, host->align_buffer_sz, direction);
 	if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
 		goto fail;
-	BUG_ON(host->align_addr & host->align_mask);
+	BUG_ON(host->align_addr & SDHCI_ADMA2_MASK);
 
 	host->sg_count = sdhci_pre_dma_transfer(host, data);
 	if (host->sg_count < 0)
@@ -514,8 +514,8 @@
 		 * the (up to three) bytes that screw up the
 		 * alignment.
 		 */
-		offset = (host->align_sz - (addr & host->align_mask)) &
-			 host->align_mask;
+		offset = (SDHCI_ADMA2_ALIGN - (addr & SDHCI_ADMA2_MASK)) &
+			 SDHCI_ADMA2_MASK;
 		if (offset) {
 			if (data->flags & MMC_DATA_WRITE) {
 				buffer = sdhci_kmap_atomic(sg, &flags);
@@ -529,8 +529,8 @@
 
 			BUG_ON(offset > 65536);
 
-			align += host->align_sz;
-			align_addr += host->align_sz;
+			align += SDHCI_ADMA2_ALIGN;
+			align_addr += SDHCI_ADMA2_ALIGN;
 
 			desc += host->desc_sz;
 
@@ -611,7 +611,7 @@
 	/* Do a quick scan of the SG list for any unaligned mappings */
 	has_unaligned = false;
 	for_each_sg(data->sg, sg, host->sg_count, i)
-		if (sg_dma_address(sg) & host->align_mask) {
+		if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) {
 			has_unaligned = true;
 			break;
 		}
@@ -623,15 +623,15 @@
 		align = host->align_buffer;
 
 		for_each_sg(data->sg, sg, host->sg_count, i) {
-			if (sg_dma_address(sg) & host->align_mask) {
-				size = host->align_sz -
-				       (sg_dma_address(sg) & host->align_mask);
+			if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) {
+				size = SDHCI_ADMA2_ALIGN -
+				       (sg_dma_address(sg) & SDHCI_ADMA2_MASK);
 
 				buffer = sdhci_kmap_atomic(sg, &flags);
 				memcpy(buffer, align, size);
 				sdhci_kunmap_atomic(buffer, &flags);
 
-				align += host->align_sz;
+				align += SDHCI_ADMA2_ALIGN;
 			}
 		}
 	}
@@ -675,7 +675,7 @@
 			 * host->clock is in Hz.  target_timeout is in us.
 			 * Hence, us = 1000000 * cycles / Hz.  Round up.
 			 */
-			val = 1000000 * data->timeout_clks;
+			val = 1000000ULL * data->timeout_clks;
 			if (do_div(val, host->clock))
 				target_timeout++;
 			target_timeout += val;
@@ -1274,7 +1274,9 @@
 			return;
 		}
 		timeout--;
-		mdelay(1);
+		spin_unlock_irq(&host->lock);
+		usleep_range(900, 1100);
+		spin_lock_irq(&host->lock);
 	}
 
 	clk |= SDHCI_CLOCK_CARD_EN;
@@ -1315,7 +1317,9 @@
 			pwr = SDHCI_POWER_330;
 			break;
 		default:
-			BUG();
+			WARN(1, "%s: Invalid vdd %#x\n",
+			     mmc_hostname(host->mmc), vdd);
+			break;
 		}
 	}
 
@@ -2038,7 +2042,27 @@
 			ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
 			sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
+			sdhci_do_reset(host, SDHCI_RESET_CMD);
+			sdhci_do_reset(host, SDHCI_RESET_DATA);
+
 			err = -EIO;
+
+			if (cmd.opcode != MMC_SEND_TUNING_BLOCK_HS200)
+				goto out;
+
+			sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+			sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+
+			spin_unlock_irqrestore(&host->lock, flags);
+
+			memset(&cmd, 0, sizeof(cmd));
+			cmd.opcode = MMC_STOP_TRANSMISSION;
+			cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+			cmd.busy_timeout = 50;
+			mmc_wait_for_cmd(mmc, &cmd, 0);
+
+			spin_lock_irqsave(&host->lock, flags);
+
 			goto out;
 		}
 
@@ -2607,7 +2631,8 @@
 			pr_err("%s: Card is consuming too much power!\n",
 				mmc_hostname(host->mmc));
 
-		if (intmask & SDHCI_INT_CARD_INT) {
+		if ((intmask & SDHCI_INT_CARD_INT) &&
+		    (host->ier & SDHCI_INT_CARD_INT)) {
 			sdhci_enable_sdio_irq_nolock(host, false);
 			host->thread_isr |= SDHCI_INT_CARD_INT;
 			result = IRQ_WAKE_THREAD;
@@ -2983,24 +3008,17 @@
 		if (host->flags & SDHCI_USE_64_BIT_DMA) {
 			host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
 					      SDHCI_ADMA2_64_DESC_SZ;
-			host->align_buffer_sz = SDHCI_MAX_SEGS *
-						SDHCI_ADMA2_64_ALIGN;
 			host->desc_sz = SDHCI_ADMA2_64_DESC_SZ;
-			host->align_sz = SDHCI_ADMA2_64_ALIGN;
-			host->align_mask = SDHCI_ADMA2_64_ALIGN - 1;
 		} else {
 			host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
 					      SDHCI_ADMA2_32_DESC_SZ;
-			host->align_buffer_sz = SDHCI_MAX_SEGS *
-						SDHCI_ADMA2_32_ALIGN;
 			host->desc_sz = SDHCI_ADMA2_32_DESC_SZ;
-			host->align_sz = SDHCI_ADMA2_32_ALIGN;
-			host->align_mask = SDHCI_ADMA2_32_ALIGN - 1;
 		}
 		host->adma_table = dma_alloc_coherent(mmc_dev(mmc),
 						      host->adma_table_sz,
 						      &host->adma_addr,
 						      GFP_KERNEL);
+		host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN;
 		host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL);
 		if (!host->adma_table || !host->align_buffer) {
 			if (host->adma_table)
@@ -3014,7 +3032,7 @@
 			host->flags &= ~SDHCI_USE_ADMA;
 			host->adma_table = NULL;
 			host->align_buffer = NULL;
-		} else if (host->adma_addr & host->align_mask) {
+		} else if (host->adma_addr & (SDHCI_ADMA2_DESC_ALIGN - 1)) {
 			pr_warn("%s: unable to allocate aligned ADMA descriptor\n",
 				mmc_hostname(mmc));
 			host->flags &= ~SDHCI_USE_ADMA;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 9c331ac..0115e99 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -272,22 +272,27 @@
 /* ADMA2 32-bit DMA descriptor size */
 #define SDHCI_ADMA2_32_DESC_SZ	8
 
-/* ADMA2 32-bit DMA alignment */
-#define SDHCI_ADMA2_32_ALIGN	4
-
 /* ADMA2 32-bit descriptor */
 struct sdhci_adma2_32_desc {
 	__le16	cmd;
 	__le16	len;
 	__le32	addr;
-}  __packed __aligned(SDHCI_ADMA2_32_ALIGN);
+}  __packed __aligned(4);
+
+/* ADMA2 data alignment */
+#define SDHCI_ADMA2_ALIGN	4
+#define SDHCI_ADMA2_MASK	(SDHCI_ADMA2_ALIGN - 1)
+
+/*
+ * ADMA2 descriptor alignment.  Some controllers (e.g. Intel) require 8 byte
+ * alignment for the descriptor table even in 32-bit DMA mode.  Memory
+ * allocation is at least 8 byte aligned anyway, so just stipulate 8 always.
+ */
+#define SDHCI_ADMA2_DESC_ALIGN	8
 
 /* ADMA2 64-bit DMA descriptor size */
 #define SDHCI_ADMA2_64_DESC_SZ	12
 
-/* ADMA2 64-bit DMA alignment */
-#define SDHCI_ADMA2_64_ALIGN	8
-
 /*
  * ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte
  * aligned.
@@ -483,8 +488,6 @@
 	dma_addr_t align_addr;	/* Mapped bounce buffer */
 
 	unsigned int desc_sz;	/* ADMA descriptor size */
-	unsigned int align_sz;	/* ADMA alignment */
-	unsigned int align_mask;	/* ADMA alignment mask */
 
 	struct tasklet_struct finish_tasklet;	/* Tasklet structures */
 
diff --git a/drivers/mmc/host/ushc.c b/drivers/mmc/host/ushc.c
index d2c386f..1d84335 100644
--- a/drivers/mmc/host/ushc.c
+++ b/drivers/mmc/host/ushc.c
@@ -426,6 +426,9 @@
 	struct ushc_data *ushc;
 	int ret;
 
+	if (intf->cur_altsetting->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	mmc = mmc_alloc_host(sizeof(struct ushc_data), &intf->dev);
 	if (mmc == NULL)
 		return -ENOMEM;
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c
index c0720c1..9190057 100644
--- a/drivers/mtd/bcm47xxpart.c
+++ b/drivers/mtd/bcm47xxpart.c
@@ -66,11 +66,13 @@
 {
 	uint32_t buf;
 	size_t bytes_read;
+	int err;
 
-	if (mtd_read(master, offset, sizeof(buf), &bytes_read,
-		     (uint8_t *)&buf) < 0) {
-		pr_err("mtd_read error while parsing (offset: 0x%X)!\n",
-			offset);
+	err  = mtd_read(master, offset, sizeof(buf), &bytes_read,
+			(uint8_t *)&buf);
+	if (err && !mtd_is_bitflip(err)) {
+		pr_err("mtd_read error while parsing (offset: 0x%X): %d\n",
+			offset, err);
 		goto out_default;
 	}
 
@@ -95,6 +97,7 @@
 	int trx_part = -1;
 	int last_trx_part = -1;
 	int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, };
+	int err;
 
 	/*
 	 * Some really old flashes (like AT45DB*) had smaller erasesize-s, but
@@ -118,8 +121,8 @@
 	/* Parse block by block looking for magics */
 	for (offset = 0; offset <= master->size - blocksize;
 	     offset += blocksize) {
-		/* Nothing more in higher memory */
-		if (offset >= 0x2000000)
+		/* Nothing more in higher memory on BCM47XX (MIPS) */
+		if (config_enabled(CONFIG_BCM47XX) && offset >= 0x2000000)
 			break;
 
 		if (curr_part >= BCM47XXPART_MAX_PARTS) {
@@ -128,10 +131,11 @@
 		}
 
 		/* Read beginning of the block */
-		if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ,
-			     &bytes_read, (uint8_t *)buf) < 0) {
-			pr_err("mtd_read error while parsing (offset: 0x%X)!\n",
-			       offset);
+		err = mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ,
+			       &bytes_read, (uint8_t *)buf);
+		if (err && !mtd_is_bitflip(err)) {
+			pr_err("mtd_read error while parsing (offset: 0x%X): %d\n",
+			       offset, err);
 			continue;
 		}
 
@@ -225,12 +229,10 @@
 
 			last_trx_part = curr_part - 1;
 
-			/*
-			 * We have whole TRX scanned, skip to the next part. Use
-			 * roundown (not roundup), as the loop will increase
-			 * offset in next step.
-			 */
-			offset = rounddown(offset + trx->length, blocksize);
+			/* Jump to the end of TRX */
+			offset = roundup(offset + trx->length, blocksize);
+			/* Next loop iteration will increase the offset */
+			offset -= blocksize;
 			continue;
 		}
 
@@ -254,10 +256,11 @@
 		}
 
 		/* Read middle of the block */
-		if (mtd_read(master, offset + 0x8000, 0x4,
-			     &bytes_read, (uint8_t *)buf) < 0) {
-			pr_err("mtd_read error while parsing (offset: 0x%X)!\n",
-			       offset);
+		err = mtd_read(master, offset + 0x8000, 0x4, &bytes_read,
+			       (uint8_t *)buf);
+		if (err && !mtd_is_bitflip(err)) {
+			pr_err("mtd_read error while parsing (offset: 0x%X): %d\n",
+			       offset, err);
 			continue;
 		}
 
@@ -277,10 +280,11 @@
 		}
 
 		offset = master->size - possible_nvram_sizes[i];
-		if (mtd_read(master, offset, 0x4, &bytes_read,
-			     (uint8_t *)buf) < 0) {
-			pr_err("mtd_read error while reading at offset 0x%X!\n",
-			       offset);
+		err = mtd_read(master, offset, 0x4, &bytes_read,
+			       (uint8_t *)buf);
+		if (err && !mtd_is_bitflip(err)) {
+			pr_err("mtd_read error while reading (offset 0x%X): %d\n",
+			       offset, err);
 			continue;
 		}
 
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index 54479c4..8a25adc 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -111,6 +111,7 @@
 
 config MTD_MAP_BANK_WIDTH_32
 	bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY
+	select MTD_COMPLEX_MAPPINGS if HAS_IOMEM
 	default n
 	help
 	  If you wish to support CFI devices on a physical bus which is
diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c
index 744ca5c..2051f28 100644
--- a/drivers/mtd/maps/pmcmsp-flash.c
+++ b/drivers/mtd/maps/pmcmsp-flash.c
@@ -75,15 +75,15 @@
 
 	printk(KERN_NOTICE "Found %d PMC flash devices\n", fcnt);
 
-	msp_flash = kmalloc(fcnt * sizeof(struct map_info *), GFP_KERNEL);
+	msp_flash = kcalloc(fcnt, sizeof(*msp_flash), GFP_KERNEL);
 	if (!msp_flash)
 		return -ENOMEM;
 
-	msp_parts = kmalloc(fcnt * sizeof(struct mtd_partition *), GFP_KERNEL);
+	msp_parts = kcalloc(fcnt, sizeof(*msp_parts), GFP_KERNEL);
 	if (!msp_parts)
 		goto free_msp_flash;
 
-	msp_maps = kcalloc(fcnt, sizeof(struct mtd_info), GFP_KERNEL);
+	msp_maps = kcalloc(fcnt, sizeof(*msp_maps), GFP_KERNEL);
 	if (!msp_maps)
 		goto free_msp_parts;
 
@@ -139,15 +139,13 @@
 		}
 
 		msp_maps[i].bankwidth = 1;
-		msp_maps[i].name = kmalloc(7, GFP_KERNEL);
+		msp_maps[i].name = kstrndup(flash_name, 7, GFP_KERNEL);
 		if (!msp_maps[i].name) {
 			iounmap(msp_maps[i].virt);
 			kfree(msp_parts[i]);
 			goto cleanup_loop;
 		}
 
-		msp_maps[i].name = strncpy(msp_maps[i].name, flash_name, 7);
-
 		for (j = 0; j < pcnt; j++) {
 			part_name[5] = '0' + i;
 			part_name[7] = '0' + j;
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 142fc3d..784c6e1 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -230,8 +230,10 @@
 
 		info->mtd = mtd_concat_create(cdev, info->num_subdev,
 					      plat->name);
-		if (info->mtd == NULL)
+		if (info->mtd == NULL) {
 			ret = -ENXIO;
+			goto err;
+		}
 	}
 	info->mtd->dev.parent = &pdev->dev;
 
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 2896640..132d0d0 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,3 +1,10 @@
+config MTD_NAND_IDS
+	tristate "Include chip ids for known NAND devices."
+	depends on MTD
+	help
+	  Useful for NAND drivers that do not use the NAND subsystem but
+	  still like to take advantage of the known chip information.
+
 config MTD_NAND_ECC
 	tristate
 
@@ -108,9 +115,6 @@
 config MTD_NAND_OMAP_BCH_BUILD
 	def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH
 
-config MTD_NAND_IDS
-	tristate
-
 config MTD_NAND_RICOH
 	tristate "Ricoh xD card reader"
 	default n
@@ -527,7 +531,7 @@
 	  Flexible Static Memory Controller (FSMC)
 
 config MTD_NAND_XWAY
-	tristate "Support for NAND on Lantiq XWAY SoC"
+	bool "Support for NAND on Lantiq XWAY SoC"
 	depends on LANTIQ && SOC_TYPE_XWAY
 	select MTD_NAND_PLATFORM
 	help
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index c72313d..bc054a5 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -241,6 +241,9 @@
 	unsigned long flags;
 	u32 val;
 
+	/* Reset ECC hardware */
+	davinci_nand_readl(info, NAND_4BIT_ECC1_OFFSET);
+
 	spin_lock_irqsave(&davinci_nand_lock, flags);
 
 	/* Start 4-bit ECC calculation for read/write */
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ce7b2ca..54ab488 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2586,7 +2586,7 @@
 		int cached = writelen > bytes && page != blockmask;
 		uint8_t *wbuf = buf;
 		int use_bufpoi;
-		int part_pagewr = (column || writelen < (mtd->writesize - 1));
+		int part_pagewr = (column || writelen < mtd->writesize);
 
 		if (part_pagewr)
 			use_bufpoi = 1;
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 37e4135..64d6f05 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1057,6 +1057,13 @@
 		return -EINVAL;
 	}
 
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret) {
+		dev_err(nor->dev,
+			"timeout while writing configuration register\n");
+		return ret;
+	}
+
 	/* read back and check it */
 	ret = read_cr(nor);
 	if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 22fd19c..27de046 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -869,7 +869,7 @@
 	for (i = 0; i < UBI_MAX_DEVICES; i++) {
 		ubi = ubi_devices[i];
 		if (ubi && mtd->index == ubi->mtd->index) {
-			ubi_err(ubi, "mtd%d is already attached to ubi%d",
+			pr_err("ubi: mtd%d is already attached to ubi%d",
 				mtd->index, i);
 			return -EEXIST;
 		}
@@ -884,7 +884,7 @@
 	 * no sense to attach emulated MTD devices, so we prohibit this.
 	 */
 	if (mtd->type == MTD_UBIVOLUME) {
-		ubi_err(ubi, "refuse attaching mtd%d - it is already emulated on top of UBI",
+		pr_err("ubi: refuse attaching mtd%d - it is already emulated on top of UBI",
 			mtd->index);
 		return -EINVAL;
 	}
@@ -895,7 +895,7 @@
 			if (!ubi_devices[ubi_num])
 				break;
 		if (ubi_num == UBI_MAX_DEVICES) {
-			ubi_err(ubi, "only %d UBI devices may be created",
+			pr_err("ubi: only %d UBI devices may be created",
 				UBI_MAX_DEVICES);
 			return -ENFILE;
 		}
@@ -905,7 +905,7 @@
 
 		/* Make sure ubi_num is not busy */
 		if (ubi_devices[ubi_num]) {
-			ubi_err(ubi, "already exists");
+			pr_err("ubi: ubi%i already exists", ubi_num);
 			return -EEXIST;
 		}
 	}
@@ -987,6 +987,9 @@
 			goto out_detach;
 	}
 
+	/* Make device "available" before it becomes accessible via sysfs */
+	ubi_devices[ubi_num] = ubi;
+
 	err = uif_init(ubi, &ref);
 	if (err)
 		goto out_detach;
@@ -1031,7 +1034,6 @@
 	wake_up_process(ubi->bgt_thread);
 	spin_unlock(&ubi->wl_lock);
 
-	ubi_devices[ubi_num] = ubi;
 	ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
 	return ubi_num;
 
@@ -1042,6 +1044,7 @@
 	ubi_assert(ref);
 	uif_close(ubi);
 out_detach:
+	ubi_devices[ubi_num] = NULL;
 	ubi_wl_close(ubi);
 	ubi_free_internal_volumes(ubi);
 	vfree(ubi->vtbl);
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 5b9834c..4dd0391 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -426,8 +426,25 @@
 						 pnum, vol_id, lnum);
 					err = -EBADMSG;
 				} else {
-					err = -EINVAL;
-					ubi_ro_mode(ubi);
+					/*
+					 * Ending up here in the non-Fastmap case
+					 * is a clear bug as the VID header had to
+					 * be present at scan time to have it referenced.
+					 * With fastmap the story is more complicated.
+					 * Fastmap has the mapping info without the need
+					 * of a full scan. So the LEB could have been
+					 * unmapped, Fastmap cannot know this and keeps
+					 * the LEB referenced.
+					 * This is valid and works as the layer above UBI
+					 * has to do bookkeeping about used/referenced
+					 * LEBs in any case.
+					 */
+					if (ubi->fast_attach) {
+						err = -EBADMSG;
+					} else {
+						err = -EINVAL;
+						ubi_ro_mode(ubi);
+					}
 				}
 			}
 			goto out_free;
@@ -558,6 +575,7 @@
 	int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0;
 	struct ubi_volume *vol = ubi->volumes[idx];
 	struct ubi_vid_hdr *vid_hdr;
+	uint32_t crc;
 
 	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 	if (!vid_hdr)
@@ -582,14 +600,8 @@
 		goto out_put;
 	}
 
-	vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
-	err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
-	if (err) {
-		up_read(&ubi->fm_eba_sem);
-		goto write_error;
-	}
+	ubi_assert(vid_hdr->vol_type == UBI_VID_DYNAMIC);
 
-	data_size = offset + len;
 	mutex_lock(&ubi->buf_mutex);
 	memset(ubi->peb_buf + offset, 0xFF, len);
 
@@ -604,6 +616,19 @@
 
 	memcpy(ubi->peb_buf + offset, buf, len);
 
+	data_size = offset + len;
+	crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size);
+	vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+	vid_hdr->copy_flag = 1;
+	vid_hdr->data_size = cpu_to_be32(data_size);
+	vid_hdr->data_crc = cpu_to_be32(crc);
+	err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
+	if (err) {
+		mutex_unlock(&ubi->buf_mutex);
+		up_read(&ubi->fm_eba_sem);
+		goto write_error;
+	}
+
 	err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
 	if (err) {
 		mutex_unlock(&ubi->buf_mutex);
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 263b439..bba7dd1 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -513,10 +513,11 @@
 			unsigned long long ec = be64_to_cpu(ech->ec);
 			unmap_peb(ai, pnum);
 			dbg_bld("Adding PEB to free: %i", pnum);
+
 			if (err == UBI_IO_FF_BITFLIPS)
-				add_aeb(ai, free, pnum, ec, 1);
-			else
-				add_aeb(ai, free, pnum, ec, 0);
+				scrub = 1;
+
+			add_aeb(ai, free, pnum, ec, scrub);
 			continue;
 		} else if (err == 0 || err == UBI_IO_BITFLIPS) {
 			dbg_bld("Found non empty PEB:%i in pool", pnum);
@@ -748,11 +749,11 @@
 			     fmvhdr->vol_type,
 			     be32_to_cpu(fmvhdr->last_eb_bytes));
 
-		if (!av)
-			goto fail_bad;
-		if (PTR_ERR(av) == -EINVAL) {
-			ubi_err(ubi, "volume (ID %i) already exists",
-				fmvhdr->vol_id);
+		if (IS_ERR(av)) {
+			if (PTR_ERR(av) == -EEXIST)
+				ubi_err(ubi, "volume (ID %i) already exists",
+					fmvhdr->vol_id);
+
 			goto fail_bad;
 		}
 
@@ -1058,6 +1059,7 @@
 	ubi_msg(ubi, "fastmap WL pool size: %d",
 		ubi->fm_wl_pool.max_size);
 	ubi->fm_disabled = 0;
+	ubi->fast_attach = 1;
 
 	ubi_free_vid_hdr(ubi, vh);
 	kfree(ech);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 2974b67..de1ea2e 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -462,6 +462,7 @@
  * @fm_eba_sem: allows ubi_update_fastmap() to block EBA table changes
  * @fm_work: fastmap work queue
  * @fm_work_scheduled: non-zero if fastmap work was scheduled
+ * @fast_attach: non-zero if UBI was attached by fastmap
  *
  * @used: RB-tree of used physical eraseblocks
  * @erroneous: RB-tree of erroneous used physical eraseblocks
@@ -570,6 +571,7 @@
 	size_t fm_size;
 	struct work_struct fm_work;
 	int fm_work_scheduled;
+	int fast_attach;
 
 	/* Wear-leveling sub-system's stuff */
 	struct rb_root used;
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index 0134ba3..3971256 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -148,11 +148,11 @@
 			return err;
 	}
 
-	if (bytes == 0) {
-		err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
-		if (err)
-			return err;
+	err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
+	if (err)
+		return err;
 
+	if (bytes == 0) {
 		err = clear_update_marker(ubi, vol, 0);
 		if (err)
 			return err;
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 1ae17bb..3ea4c02 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -488,13 +488,6 @@
 		spin_unlock(&ubi->volumes_lock);
 	}
 
-	/* Change volume table record */
-	vtbl_rec = ubi->vtbl[vol_id];
-	vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
-	err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
-	if (err)
-		goto out_acc;
-
 	if (pebs < 0) {
 		for (i = 0; i < -pebs; i++) {
 			err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i);
@@ -512,6 +505,24 @@
 		spin_unlock(&ubi->volumes_lock);
 	}
 
+	/*
+	 * When we shrink a volume we have to flush all pending (erase) work.
+	 * Otherwise it can happen that upon next attach UBI finds a LEB with
+	 * lnum > highest_lnum and refuses to attach.
+	 */
+	if (pebs < 0) {
+		err = ubi_wl_flush(ubi, vol_id, UBI_ALL);
+		if (err)
+			goto out_acc;
+	}
+
+	/* Change volume table record */
+	vtbl_rec = ubi->vtbl[vol_id];
+	vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
+	err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
+	if (err)
+		goto out_acc;
+
 	vol->reserved_pebs = reserved_pebs;
 	if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
 		vol->used_ebs = reserved_pebs;
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 5606563..7528658 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -643,7 +643,7 @@
 				int shutdown)
 {
 	int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
-	int vol_id = -1, lnum = -1;
+	int erase = 0, keep = 0, vol_id = -1, lnum = -1;
 #ifdef CONFIG_MTD_UBI_FASTMAP
 	int anchor = wrk->anchor;
 #endif
@@ -777,6 +777,16 @@
 			       e1->pnum);
 			scrubbing = 1;
 			goto out_not_moved;
+		} else if (ubi->fast_attach && err == UBI_IO_BAD_HDR_EBADMSG) {
+			/*
+			 * While a full scan would detect interrupted erasures
+			 * at attach time we can face them here when attached from
+			 * Fastmap.
+			 */
+			dbg_wl("PEB %d has ECC errors, maybe from an interrupted erasure",
+			       e1->pnum);
+			erase = 1;
+			goto out_not_moved;
 		}
 
 		ubi_err(ubi, "error %d while reading VID header from PEB %d",
@@ -810,6 +820,7 @@
 			 * Target PEB had bit-flips or write error - torture it.
 			 */
 			torture = 1;
+			keep = 1;
 			goto out_not_moved;
 		}
 
@@ -895,7 +906,7 @@
 		ubi->erroneous_peb_count += 1;
 	} else if (scrubbing)
 		wl_tree_add(e1, &ubi->scrub);
-	else
+	else if (keep)
 		wl_tree_add(e1, &ubi->used);
 	ubi_assert(!ubi->move_to_put);
 	ubi->move_from = ubi->move_to = NULL;
@@ -907,6 +918,12 @@
 	if (err)
 		goto out_ro;
 
+	if (erase) {
+		err = do_sync_erase(ubi, e1, vol_id, lnum, 1);
+		if (err)
+			goto out_ro;
+	}
+
 	mutex_unlock(&ubi->move_mutex);
 	return 0;
 
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b3d70a7..5dca77e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1317,9 +1317,10 @@
 			    slave_dev->name);
 	}
 
-	/* already enslaved */
-	if (slave_dev->flags & IFF_SLAVE) {
-		netdev_dbg(bond_dev, "Error: Device was already enslaved\n");
+	/* already in-use? */
+	if (netdev_is_rx_handler_busy(slave_dev)) {
+		netdev_err(bond_dev,
+			   "Error: Device is in use and cannot be enslaved\n");
 		return -EBUSY;
 	}
 
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index db760e8..b8df0f5 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -446,7 +446,11 @@
 	if (err < 0)
 		return err;
 
-	return register_netdevice(bond_dev);
+	err = register_netdevice(bond_dev);
+
+	netif_carrier_off(bond_dev);
+
+	return err;
 }
 
 static size_t bond_get_size(const struct net_device *bond_dev)
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 8b3275d..8f5e93c 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -712,9 +712,10 @@
 
 	/* upper group completed, look again in lower */
 	if (priv->rx_next > get_mb_rx_low_last(priv) &&
-	    quota > 0 && mb > get_mb_rx_last(priv)) {
+	    mb > get_mb_rx_last(priv)) {
 		priv->rx_next = get_mb_rx_first(priv);
-		goto again;
+		if (quota > 0)
+			goto again;
 	}
 
 	return received;
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index f91b094..e3dccd3 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -332,9 +332,23 @@
 
 	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
 
-	for (i = 0; i < frame->can_dlc; i += 2) {
-		priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2,
-				frame->data[i] | (frame->data[i + 1] << 8));
+	if (priv->type == BOSCH_D_CAN) {
+		u32 data = 0, dreg = C_CAN_IFACE(DATA1_REG, iface);
+
+		for (i = 0; i < frame->can_dlc; i += 4, dreg += 2) {
+			data = (u32)frame->data[i];
+			data |= (u32)frame->data[i + 1] << 8;
+			data |= (u32)frame->data[i + 2] << 16;
+			data |= (u32)frame->data[i + 3] << 24;
+			priv->write_reg32(priv, dreg, data);
+		}
+	} else {
+		for (i = 0; i < frame->can_dlc; i += 2) {
+			priv->write_reg(priv,
+					C_CAN_IFACE(DATA1_REG, iface) + i / 2,
+					frame->data[i] |
+					(frame->data[i + 1] << 8));
+		}
 	}
 }
 
@@ -402,10 +416,20 @@
 	} else {
 		int i, dreg = C_CAN_IFACE(DATA1_REG, iface);
 
-		for (i = 0; i < frame->can_dlc; i += 2, dreg ++) {
-			data = priv->read_reg(priv, dreg);
-			frame->data[i] = data;
-			frame->data[i + 1] = data >> 8;
+		if (priv->type == BOSCH_D_CAN) {
+			for (i = 0; i < frame->can_dlc; i += 4, dreg += 2) {
+				data = priv->read_reg32(priv, dreg);
+				frame->data[i] = data;
+				frame->data[i + 1] = data >> 8;
+				frame->data[i + 2] = data >> 16;
+				frame->data[i + 3] = data >> 24;
+			}
+		} else {
+			for (i = 0; i < frame->can_dlc; i += 2, dreg++) {
+				data = priv->read_reg(priv, dreg);
+				frame->data[i] = data;
+				frame->data[i + 1] = data >> 8;
+			}
 		}
 	}
 
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index 7be393c..cf7c189 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -161,6 +161,7 @@
 
 	dev->irq = pdev->irq;
 	priv->base = addr;
+	priv->device = &pdev->dev;
 
 	if (!c_can_pci_data->freq) {
 		dev_err(&pdev->dev, "no clock frequency defined\n");
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 141c2a4..eab1327 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
+#include <linux/workqueue.h>
 #include <linux/can.h>
 #include <linux/can/dev.h>
 #include <linux/can/skb.h>
@@ -471,9 +472,8 @@
 /*
  * CAN device restart for bus-off recovery
  */
-static void can_restart(unsigned long data)
+static void can_restart(struct net_device *dev)
 {
-	struct net_device *dev = (struct net_device *)data;
 	struct can_priv *priv = netdev_priv(dev);
 	struct net_device_stats *stats = &dev->stats;
 	struct sk_buff *skb;
@@ -513,6 +513,14 @@
 		netdev_err(dev, "Error %d during restart", err);
 }
 
+static void can_restart_work(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct can_priv *priv = container_of(dwork, struct can_priv, restart_work);
+
+	can_restart(priv->dev);
+}
+
 int can_restart_now(struct net_device *dev)
 {
 	struct can_priv *priv = netdev_priv(dev);
@@ -526,8 +534,8 @@
 	if (priv->state != CAN_STATE_BUS_OFF)
 		return -EBUSY;
 
-	/* Runs as soon as possible in the timer context */
-	mod_timer(&priv->restart_timer, jiffies);
+	cancel_delayed_work_sync(&priv->restart_work);
+	can_restart(dev);
 
 	return 0;
 }
@@ -548,8 +556,8 @@
 	netif_carrier_off(dev);
 
 	if (priv->restart_ms)
-		mod_timer(&priv->restart_timer,
-			  jiffies + (priv->restart_ms * HZ) / 1000);
+		schedule_delayed_work(&priv->restart_work,
+				      msecs_to_jiffies(priv->restart_ms));
 }
 EXPORT_SYMBOL_GPL(can_bus_off);
 
@@ -658,6 +666,7 @@
 		return NULL;
 
 	priv = netdev_priv(dev);
+	priv->dev = dev;
 
 	if (echo_skb_max) {
 		priv->echo_skb_max = echo_skb_max;
@@ -667,7 +676,7 @@
 
 	priv->state = CAN_STATE_STOPPED;
 
-	init_timer(&priv->restart_timer);
+	INIT_DELAYED_WORK(&priv->restart_work, can_restart_work);
 
 	return dev;
 }
@@ -696,11 +705,17 @@
 	/* allow change of MTU according to the CANFD ability of the device */
 	switch (new_mtu) {
 	case CAN_MTU:
+		/* 'CANFD-only' controllers can not switch to CAN_MTU */
+		if (priv->ctrlmode_static & CAN_CTRLMODE_FD)
+			return -EINVAL;
+
 		priv->ctrlmode &= ~CAN_CTRLMODE_FD;
 		break;
 
 	case CANFD_MTU:
-		if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD))
+		/* check for potential CANFD ability */
+		if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD) &&
+		    !(priv->ctrlmode_static & CAN_CTRLMODE_FD))
 			return -EINVAL;
 
 		priv->ctrlmode |= CAN_CTRLMODE_FD;
@@ -742,8 +757,6 @@
 	if (!netif_carrier_ok(dev))
 		netif_carrier_on(dev);
 
-	setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev);
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(open_candev);
@@ -758,7 +771,7 @@
 {
 	struct can_priv *priv = netdev_priv(dev);
 
-	del_timer_sync(&priv->restart_timer);
+	cancel_delayed_work_sync(&priv->restart_work);
 	can_flush_echo_skb(dev);
 }
 EXPORT_SYMBOL_GPL(close_candev);
@@ -782,6 +795,38 @@
 				= { .len = sizeof(struct can_bittiming_const) },
 };
 
+static int can_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+	bool is_can_fd = false;
+
+	/* Make sure that valid CAN FD configurations always consist of
+	 * - nominal/arbitration bittiming
+	 * - data bittiming
+	 * - control mode with CAN_CTRLMODE_FD set
+	 */
+
+	if (!data)
+		return 0;
+
+	if (data[IFLA_CAN_CTRLMODE]) {
+		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+
+		is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
+	}
+
+	if (is_can_fd) {
+		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
+			return -EOPNOTSUPP;
+	}
+
+	if (data[IFLA_CAN_DATA_BITTIMING]) {
+		if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
+			return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
 static int can_changelink(struct net_device *dev,
 			  struct nlattr *tb[], struct nlattr *data[])
 {
@@ -813,19 +858,31 @@
 
 	if (data[IFLA_CAN_CTRLMODE]) {
 		struct can_ctrlmode *cm;
+		u32 ctrlstatic;
+		u32 maskedflags;
 
 		/* Do not allow changing controller mode while running */
 		if (dev->flags & IFF_UP)
 			return -EBUSY;
 		cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+		ctrlstatic = priv->ctrlmode_static;
+		maskedflags = cm->flags & cm->mask;
 
-		/* check whether changed bits are allowed to be modified */
-		if (cm->mask & ~priv->ctrlmode_supported)
+		/* check whether provided bits are allowed to be passed */
+		if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
+			return -EOPNOTSUPP;
+
+		/* do not check for static fd-non-iso if 'fd' is disabled */
+		if (!(maskedflags & CAN_CTRLMODE_FD))
+			ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
+
+		/* make sure static options are provided by configuration */
+		if ((maskedflags & ctrlstatic) != ctrlstatic)
 			return -EOPNOTSUPP;
 
 		/* clear bits to be modified and copy the flag values */
 		priv->ctrlmode &= ~cm->mask;
-		priv->ctrlmode |= (cm->flags & cm->mask);
+		priv->ctrlmode |= maskedflags;
 
 		/* CAN_CTRLMODE_FD can only be set when driver supports FD */
 		if (priv->ctrlmode & CAN_CTRLMODE_FD)
@@ -961,13 +1018,20 @@
 	return -EOPNOTSUPP;
 }
 
+static void can_dellink(struct net_device *dev, struct list_head *head)
+{
+	return;
+}
+
 static struct rtnl_link_ops can_link_ops __read_mostly = {
 	.kind		= "can",
 	.maxtype	= IFLA_CAN_MAX,
 	.policy		= can_policy,
 	.setup		= can_setup,
+	.validate	= can_validate,
 	.newlink	= can_newlink,
 	.changelink	= can_changelink,
+	.dellink	= can_dellink,
 	.get_size	= can_get_size,
 	.fill_info	= can_fill_info,
 	.get_xstats_size = can_get_xstats_size,
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 41c0fc9..16f7cad 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1268,11 +1268,10 @@
 	struct flexcan_priv *priv = netdev_priv(dev);
 	int err;
 
-	err = flexcan_chip_disable(priv);
-	if (err)
-		return err;
-
 	if (netif_running(dev)) {
+		err = flexcan_chip_disable(priv);
+		if (err)
+			return err;
 		netif_stop_queue(dev);
 		netif_device_detach(dev);
 	}
@@ -1285,13 +1284,17 @@
 {
 	struct net_device *dev = dev_get_drvdata(device);
 	struct flexcan_priv *priv = netdev_priv(dev);
+	int err;
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 	if (netif_running(dev)) {
 		netif_device_attach(dev);
 		netif_start_queue(dev);
+		err = flexcan_chip_enable(priv);
+		if (err)
+			return err;
 	}
-	return flexcan_chip_enable(priv);
+	return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(flexcan_pm_ops, flexcan_suspend, flexcan_resume);
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 39cf911..195f15e 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -955,7 +955,7 @@
 	priv->can.do_get_berr_counter = m_can_get_berr_counter;
 
 	/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.1 */
-	priv->can.ctrlmode = CAN_CTRLMODE_FD_NON_ISO;
+	can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
 
 	/* CAN_CTRLMODE_FD_NON_ISO can not be changed with M_CAN IP v3.0.1 */
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index 680d1ff..6749b18 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -948,7 +948,12 @@
 	netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll,
 		HECC_DEF_NAPI_WEIGHT);
 
-	clk_enable(priv->clk);
+	err = clk_prepare_enable(priv->clk);
+	if (err) {
+		dev_err(&pdev->dev, "clk_prepare_enable() failed\n");
+		goto probe_exit_clk;
+	}
+
 	err = register_candev(ndev);
 	if (err) {
 		dev_err(&pdev->dev, "register_candev() failed\n");
@@ -981,7 +986,7 @@
 	struct ti_hecc_priv *priv = netdev_priv(ndev);
 
 	unregister_candev(ndev);
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 	clk_put(priv->clk);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	iounmap(priv->base);
@@ -1006,7 +1011,7 @@
 	hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_PDR);
 	priv->can.state = CAN_STATE_SLEEPING;
 
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 
 	return 0;
 }
@@ -1015,8 +1020,11 @@
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
 	struct ti_hecc_priv *priv = netdev_priv(dev);
+	int err;
 
-	clk_enable(priv->clk);
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
 
 	hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_PDR);
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index cbc99d5..ae57093 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -246,6 +246,8 @@
 			     sizeof(*dm),
 			     1000);
 
+	kfree(dm);
+
 	return rc;
 }
 
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 5a2e341..91be457 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -872,23 +872,25 @@
 static void peak_usb_disconnect(struct usb_interface *intf)
 {
 	struct peak_usb_device *dev;
+	struct peak_usb_device *dev_prev_siblings;
 
 	/* unregister as many netdev devices as siblings */
-	for (dev = usb_get_intfdata(intf); dev; dev = dev->prev_siblings) {
+	for (dev = usb_get_intfdata(intf); dev; dev = dev_prev_siblings) {
 		struct net_device *netdev = dev->netdev;
 		char name[IFNAMSIZ];
 
+		dev_prev_siblings = dev->prev_siblings;
 		dev->state &= ~PCAN_USB_STATE_CONNECTED;
 		strncpy(name, netdev->name, IFNAMSIZ);
 
 		unregister_netdev(netdev);
-		free_candev(netdev);
 
 		kfree(dev->cmd_buf);
 		dev->next_siblings = NULL;
 		if (dev->adapter->dev_free)
 			dev->adapter->dev_free(dev);
 
+		free_candev(netdev);
 		dev_info(&intf->dev, "%s removed\n", name);
 	}
 
diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c
index a731720..449b2a4 100644
--- a/drivers/net/can/usb/usb_8dev.c
+++ b/drivers/net/can/usb/usb_8dev.c
@@ -954,8 +954,8 @@
 	for (i = 0; i < MAX_TX_URBS; i++)
 		priv->tx_contexts[i].echo_index = MAX_TX_URBS;
 
-	priv->cmd_msg_buffer = kzalloc(sizeof(struct usb_8dev_cmd_msg),
-				      GFP_KERNEL);
+	priv->cmd_msg_buffer = devm_kzalloc(&intf->dev, sizeof(struct usb_8dev_cmd_msg),
+					    GFP_KERNEL);
 	if (!priv->cmd_msg_buffer)
 		goto cleanup_candev;
 
@@ -969,7 +969,7 @@
 	if (err) {
 		netdev_err(netdev,
 			"couldn't register CAN device: %d\n", err);
-		goto cleanup_cmd_msg_buffer;
+		goto cleanup_candev;
 	}
 
 	err = usb_8dev_cmd_version(priv, &version);
@@ -990,9 +990,6 @@
 cleanup_unregister_candev:
 	unregister_netdev(priv->netdev);
 
-cleanup_cmd_msg_buffer:
-	kfree(priv->cmd_msg_buffer);
-
 cleanup_candev:
 	free_candev(netdev);
 
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 6f946fe..0864f05 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -1137,6 +1137,7 @@
 				   struct phy_device *phydev)
 {
 	struct bcm_sf2_priv *priv = ds_to_priv(ds);
+	struct ethtool_eee *p = &priv->port_sts[port].eee;
 	u32 id_mode_dis = 0, port_mode;
 	const char *str = NULL;
 	u32 reg;
@@ -1211,6 +1212,9 @@
 		reg |= DUPLX_MODE;
 
 	core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));
+
+	if (!phydev->is_pseudo_fixed_link)
+		p->eee_enabled = bcm_sf2_eee_init(ds, port, phydev);
 }
 
 static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h
index 6bba1c9..c7994e3 100644
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -187,8 +187,8 @@
 static inline void intrl2_##which##_mask_clear(struct bcm_sf2_priv *priv, \
 						u32 mask)		\
 {									\
-	intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR);	\
 	priv->irq##which##_mask &= ~(mask);				\
+	intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR);	\
 }									\
 static inline void intrl2_##which##_mask_set(struct bcm_sf2_priv *priv, \
 						u32 mask)		\
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index ac72882..f089fa9 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -1153,6 +1153,12 @@
 		if (skb == NULL)
 			break;
 		np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+		if (pci_dma_mapping_error(np->pci_dev,
+					  np->rx_info[i].mapping)) {
+			dev_kfree_skb(skb);
+			np->rx_info[i].skb = NULL;
+			break;
+		}
 		/* Grrr, we cannot offset to correctly align the IP header. */
 		np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
 	}
@@ -1183,8 +1189,9 @@
 {
 	struct netdev_private *np = netdev_priv(dev);
 	unsigned int entry;
+	unsigned int prev_tx;
 	u32 status;
-	int i;
+	int i, j;
 
 	/*
 	 * be cautious here, wrapping the queue has weird semantics
@@ -1202,6 +1209,7 @@
 	}
 #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
 
+	prev_tx = np->cur_tx;
 	entry = np->cur_tx % TX_RING_SIZE;
 	for (i = 0; i < skb_num_frags(skb); i++) {
 		int wrap_ring = 0;
@@ -1235,6 +1243,11 @@
 					       skb_frag_size(this_frag),
 					       PCI_DMA_TODEVICE);
 		}
+		if (pci_dma_mapping_error(np->pci_dev,
+					  np->tx_info[entry].mapping)) {
+			dev->stats.tx_dropped++;
+			goto err_out;
+		}
 
 		np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
 		np->tx_ring[entry].status = cpu_to_le32(status);
@@ -1269,8 +1282,30 @@
 		netif_stop_queue(dev);
 
 	return NETDEV_TX_OK;
-}
 
+err_out:
+	entry = prev_tx % TX_RING_SIZE;
+	np->tx_info[entry].skb = NULL;
+	if (i > 0) {
+		pci_unmap_single(np->pci_dev,
+				 np->tx_info[entry].mapping,
+				 skb_first_frag_len(skb),
+				 PCI_DMA_TODEVICE);
+		np->tx_info[entry].mapping = 0;
+		entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
+		for (j = 1; j < i; j++) {
+			pci_unmap_single(np->pci_dev,
+					 np->tx_info[entry].mapping,
+					 skb_frag_size(
+						&skb_shinfo(skb)->frags[j-1]),
+					 PCI_DMA_TODEVICE);
+			entry++;
+		}
+	}
+	dev_kfree_skb_any(skb);
+	np->cur_tx = prev_tx;
+	return NETDEV_TX_OK;
+}
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
@@ -1570,6 +1605,12 @@
 				break;	/* Better luck next round. */
 			np->rx_info[entry].mapping =
 				pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+			if (pci_dma_mapping_error(np->pci_dev,
+						np->rx_info[entry].mapping)) {
+				dev_kfree_skb(skb);
+				np->rx_info[entry].skb = NULL;
+				break;
+			}
 			np->rx_ring[entry].rxaddr =
 				cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
 		}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index b6fa891..66ba1e0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -913,8 +913,8 @@
 #define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH	1
 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX	1
 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH	1
-#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX	2
-#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH	1
+#define RX_PACKET_ATTRIBUTES_LAST_INDEX		2
+#define RX_PACKET_ATTRIBUTES_LAST_WIDTH		1
 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX	3
 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH	1
 #define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX	4
@@ -923,6 +923,8 @@
 #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH	1
 #define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX	6
 #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH	1
+#define RX_PACKET_ATTRIBUTES_FIRST_INDEX	7
+#define RX_PACKET_ATTRIBUTES_FIRST_WIDTH	1
 
 #define RX_NORMAL_DESC0_OVT_INDEX		0
 #define RX_NORMAL_DESC0_OVT_WIDTH		16
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index f6a7161..75e6e7e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1658,10 +1658,15 @@
 
 	/* Get the header length */
 	if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) {
+		XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+			       FIRST, 1);
 		rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2,
 						      RX_NORMAL_DESC2, HL);
 		if (rdata->rx.hdr_len)
 			pdata->ext_stats.rx_split_header_packets++;
+	} else {
+		XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+			       FIRST, 0);
 	}
 
 	/* Get the RSS hash */
@@ -1684,19 +1689,16 @@
 		}
 	}
 
-	/* Get the packet length */
-	rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
-
-	if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) {
-		/* Not all the data has been transferred for this packet */
-		XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
-			       INCOMPLETE, 1);
+	/* Not all the data has been transferred for this packet */
+	if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD))
 		return 0;
-	}
 
 	/* This is the last of the data for this packet */
 	XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
-		       INCOMPLETE, 0);
+		       LAST, 1);
+
+	/* Get the packet length */
+	rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
 
 	/* Set checksum done indicator as appropriate */
 	if (netdev->features & NETIF_F_RXCSUM)
@@ -2730,8 +2732,10 @@
 
 	/* Flush Tx queues */
 	ret = xgbe_flush_tx_queues(pdata);
-	if (ret)
+	if (ret) {
+		netdev_err(pdata->netdev, "error flushing TX queues\n");
 		return ret;
+	}
 
 	/*
 	 * Initialize DMA related features
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 53ce122..64034ff 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -877,7 +877,9 @@
 
 	DBGPR("-->xgbe_start\n");
 
-	hw_if->init(pdata);
+	ret = hw_if->init(pdata);
+	if (ret)
+		return ret;
 
 	ret = phy_if->phy_start(pdata);
 	if (ret)
@@ -1760,13 +1762,12 @@
 {
 	struct sk_buff *skb;
 	u8 *packet;
-	unsigned int copy_len;
 
 	skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len);
 	if (!skb)
 		return NULL;
 
-	/* Start with the header buffer which may contain just the header
+	/* Pull in the header buffer which may contain just the header
 	 * or the header plus data
 	 */
 	dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base,
@@ -1775,30 +1776,49 @@
 
 	packet = page_address(rdata->rx.hdr.pa.pages) +
 		 rdata->rx.hdr.pa.pages_offset;
-	copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : len;
-	copy_len = min(rdata->rx.hdr.dma_len, copy_len);
-	skb_copy_to_linear_data(skb, packet, copy_len);
-	skb_put(skb, copy_len);
-
-	len -= copy_len;
-	if (len) {
-		/* Add the remaining data as a frag */
-		dma_sync_single_range_for_cpu(pdata->dev,
-					      rdata->rx.buf.dma_base,
-					      rdata->rx.buf.dma_off,
-					      rdata->rx.buf.dma_len,
-					      DMA_FROM_DEVICE);
-
-		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
-				rdata->rx.buf.pa.pages,
-				rdata->rx.buf.pa.pages_offset,
-				len, rdata->rx.buf.dma_len);
-		rdata->rx.buf.pa.pages = NULL;
-	}
+	skb_copy_to_linear_data(skb, packet, len);
+	skb_put(skb, len);
 
 	return skb;
 }
 
+static unsigned int xgbe_rx_buf1_len(struct xgbe_ring_data *rdata,
+				     struct xgbe_packet_data *packet)
+{
+	/* Always zero if not the first descriptor */
+	if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, FIRST))
+		return 0;
+
+	/* First descriptor with split header, return header length */
+	if (rdata->rx.hdr_len)
+		return rdata->rx.hdr_len;
+
+	/* First descriptor but not the last descriptor and no split header,
+	 * so the full buffer was used
+	 */
+	if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST))
+		return rdata->rx.hdr.dma_len;
+
+	/* First descriptor and last descriptor and no split header, so
+	 * calculate how much of the buffer was used
+	 */
+	return min_t(unsigned int, rdata->rx.hdr.dma_len, rdata->rx.len);
+}
+
+static unsigned int xgbe_rx_buf2_len(struct xgbe_ring_data *rdata,
+				     struct xgbe_packet_data *packet,
+				     unsigned int len)
+{
+	/* Always the full buffer if not the last descriptor */
+	if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST))
+		return rdata->rx.buf.dma_len;
+
+	/* Last descriptor so calculate how much of the buffer was used
+	 * for the last bit of data
+	 */
+	return rdata->rx.len - len;
+}
+
 static int xgbe_tx_poll(struct xgbe_channel *channel)
 {
 	struct xgbe_prv_data *pdata = channel->pdata;
@@ -1881,8 +1901,8 @@
 	struct napi_struct *napi;
 	struct sk_buff *skb;
 	struct skb_shared_hwtstamps *hwtstamps;
-	unsigned int incomplete, error, context_next, context;
-	unsigned int len, rdesc_len, max_len;
+	unsigned int last, error, context_next, context;
+	unsigned int len, buf1_len, buf2_len, max_len;
 	unsigned int received = 0;
 	int packet_count = 0;
 
@@ -1892,7 +1912,7 @@
 	if (!ring)
 		return 0;
 
-	incomplete = 0;
+	last = 0;
 	context_next = 0;
 
 	napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi;
@@ -1926,9 +1946,8 @@
 		received++;
 		ring->cur++;
 
-		incomplete = XGMAC_GET_BITS(packet->attributes,
-					    RX_PACKET_ATTRIBUTES,
-					    INCOMPLETE);
+		last = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+				      LAST);
 		context_next = XGMAC_GET_BITS(packet->attributes,
 					      RX_PACKET_ATTRIBUTES,
 					      CONTEXT_NEXT);
@@ -1937,7 +1956,7 @@
 					 CONTEXT);
 
 		/* Earlier error, just drain the remaining data */
-		if ((incomplete || context_next) && error)
+		if ((!last || context_next) && error)
 			goto read_again;
 
 		if (error || packet->errors) {
@@ -1949,16 +1968,22 @@
 		}
 
 		if (!context) {
-			/* Length is cumulative, get this descriptor's length */
-			rdesc_len = rdata->rx.len - len;
-			len += rdesc_len;
+			/* Get the data length in the descriptor buffers */
+			buf1_len = xgbe_rx_buf1_len(rdata, packet);
+			len += buf1_len;
+			buf2_len = xgbe_rx_buf2_len(rdata, packet, len);
+			len += buf2_len;
 
-			if (rdesc_len && !skb) {
+			if (!skb) {
 				skb = xgbe_create_skb(pdata, napi, rdata,
-						      rdesc_len);
-				if (!skb)
+						      buf1_len);
+				if (!skb) {
 					error = 1;
-			} else if (rdesc_len) {
+					goto skip_data;
+				}
+			}
+
+			if (buf2_len) {
 				dma_sync_single_range_for_cpu(pdata->dev,
 							rdata->rx.buf.dma_base,
 							rdata->rx.buf.dma_off,
@@ -1968,13 +1993,14 @@
 				skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
 						rdata->rx.buf.pa.pages,
 						rdata->rx.buf.pa.pages_offset,
-						rdesc_len,
+						buf2_len,
 						rdata->rx.buf.dma_len);
 				rdata->rx.buf.pa.pages = NULL;
 			}
 		}
 
-		if (incomplete || context_next)
+skip_data:
+		if (!last || context_next)
 			goto read_again;
 
 		if (!skb)
@@ -2033,7 +2059,7 @@
 	}
 
 	/* Check if we need to save state before leaving */
-	if (received && (incomplete || context_next)) {
+	if (received && (!last || context_next)) {
 		rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
 		rdata->state_saved = 1;
 		rdata->state.skb = skb;
diff --git a/drivers/net/ethernet/arc/Kconfig b/drivers/net/ethernet/arc/Kconfig
index 6890451..52a6b16 100644
--- a/drivers/net/ethernet/arc/Kconfig
+++ b/drivers/net/ethernet/arc/Kconfig
@@ -34,9 +34,9 @@
 	select ARC_EMAC_CORE
 	depends on OF_IRQ && OF_NET && REGULATOR && HAS_DMA
 	---help---
-	  Support for Rockchip RK3036/RK3066/RK3188 EMAC ethernet controllers.
+	  Support for Rockchip RK3066/RK3188 EMAC ethernet controllers.
 	  This selects Rockchip SoC glue layer support for the
-	  emac device driver. This driver is used for RK3036/RK3066/RK3188
+	  emac device driver. This driver is used for RK3066/RK3188
 	  EMAC ethernet controller.
 
 endif # NET_VENDOR_ARC
diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c
index 85e821c..c31c740 100644
--- a/drivers/net/ethernet/arc/emac_rockchip.c
+++ b/drivers/net/ethernet/arc/emac_rockchip.c
@@ -25,13 +25,17 @@
 #include "emac.h"
 
 #define DRV_NAME        "rockchip_emac"
-#define DRV_VERSION     "1.1"
+#define DRV_VERSION     "1.0"
+
+#define GRF_MODE_MII		(1UL << 0)
+#define GRF_MODE_RMII		(0UL << 0)
+#define GRF_SPEED_10M		(0UL << 1)
+#define GRF_SPEED_100M		(1UL << 1)
+#define GRF_SPEED_ENABLE_BIT	(1UL << 17)
+#define GRF_MODE_ENABLE_BIT	(1UL << 16)
 
 struct emac_rockchip_soc_data {
-	unsigned int grf_offset;
-	unsigned int grf_mode_offset;
-	unsigned int grf_speed_offset;
-	bool need_div_macclk;
+	int grf_offset;
 };
 
 struct rockchip_priv_data {
@@ -40,22 +44,23 @@
 	const struct emac_rockchip_soc_data *soc_data;
 	struct regulator *regulator;
 	struct clk *refclk;
-	struct clk *macclk;
 };
 
 static void emac_rockchip_set_mac_speed(void *priv, unsigned int speed)
 {
 	struct rockchip_priv_data *emac = priv;
-	u32 speed_offset = emac->soc_data->grf_speed_offset;
 	u32 data;
 	int err = 0;
 
+	/* write-enable bits */
+	data = GRF_SPEED_ENABLE_BIT;
+
 	switch(speed) {
 	case 10:
-		data = (1 << (speed_offset + 16)) | (0 << speed_offset);
+		data |= GRF_SPEED_10M;
 		break;
 	case 100:
-		data = (1 << (speed_offset + 16)) | (1 << speed_offset);
+		data |= GRF_SPEED_100M;
 		break;
 	default:
 		pr_err("speed %u not supported\n", speed);
@@ -67,25 +72,14 @@
 		pr_err("unable to apply speed %u to grf (%d)\n", speed, err);
 }
 
-static const struct emac_rockchip_soc_data emac_rk3036_emac_data = {
-	.grf_offset = 0x140,   .grf_mode_offset = 8,
-	.grf_speed_offset = 9, .need_div_macclk = 1,
-};
-
-static const struct emac_rockchip_soc_data emac_rk3066_emac_data = {
-	.grf_offset = 0x154,   .grf_mode_offset = 0,
-	.grf_speed_offset = 1, .need_div_macclk = 0,
-};
-
-static const struct emac_rockchip_soc_data emac_rk3188_emac_data = {
-	.grf_offset = 0x0a4,   .grf_mode_offset = 0,
-	.grf_speed_offset = 1, .need_div_macclk = 0,
+static const struct emac_rockchip_soc_data emac_rockchip_dt_data[] = {
+	{ .grf_offset = 0x154 }, /* rk3066 */
+	{ .grf_offset = 0x0a4 }, /* rk3188 */
 };
 
 static const struct of_device_id emac_rockchip_dt_ids[] = {
-	{ .compatible = "rockchip,rk3036-emac", .data = &emac_rk3036_emac_data },
-	{ .compatible = "rockchip,rk3066-emac", .data = &emac_rk3066_emac_data },
-	{ .compatible = "rockchip,rk3188-emac", .data = &emac_rk3188_emac_data },
+	{ .compatible = "rockchip,rk3066-emac", .data = &emac_rockchip_dt_data[0] },
+	{ .compatible = "rockchip,rk3188-emac", .data = &emac_rockchip_dt_data[1] },
 	{ /* Sentinel */ }
 };
 
@@ -116,7 +110,7 @@
 
 	interface = of_get_phy_mode(dev->of_node);
 
-	/* RK3036/RK3066/RK3188 SoCs only support RMII */
+	/* RK3066 and RK3188 SoCs only support RMII */
 	if (interface != PHY_INTERFACE_MODE_RMII) {
 		dev_err(dev, "unsupported phy interface mode %d\n", interface);
 		err = -ENOTSUPP;
@@ -170,12 +164,15 @@
 		}
 	}
 
-	/* Set speed 100M */
-	data = (1 << (priv->soc_data->grf_speed_offset + 16)) |
-	       (1 << priv->soc_data->grf_speed_offset);
-	/* Set RMII mode */
-	data |= (1 << (priv->soc_data->grf_mode_offset + 16)) |
-		(0 << priv->soc_data->grf_mode_offset);
+	err = arc_emac_probe(ndev, interface);
+	if (err)
+		goto out_regulator_disable;
+
+	/* write-enable bits */
+	data = GRF_MODE_ENABLE_BIT | GRF_SPEED_ENABLE_BIT;
+
+	data |= GRF_SPEED_100M;
+	data |= GRF_MODE_RMII;
 
 	err = regmap_write(priv->grf, priv->soc_data->grf_offset, data);
 	if (err) {
@@ -187,33 +184,6 @@
 	err = clk_set_rate(priv->refclk, 50000000);
 	if (err)
 		dev_err(dev, "failed to change reference clock rate (%d)\n", err);
-
-	if (priv->soc_data->need_div_macclk) {
-		priv->macclk = devm_clk_get(dev, "macclk");
-		if (IS_ERR(priv->macclk)) {
-			dev_err(dev, "failed to retrieve mac clock (%ld)\n", PTR_ERR(priv->macclk));
-			err = PTR_ERR(priv->macclk);
-			goto out_regulator_disable;
-		}
-
-		err = clk_prepare_enable(priv->macclk);
-		if (err) {
-			dev_err(dev, "failed to enable mac clock (%d)\n", err);
-			goto out_regulator_disable;
-		}
-
-		/* RMII TX/RX needs always a rate of 25MHz */
-		err = clk_set_rate(priv->macclk, 25000000);
-		if (err)
-			dev_err(dev, "failed to change mac clock rate (%d)\n", err);
-	}
-
-	err = arc_emac_probe(ndev, interface);
-	if (err) {
-		dev_err(dev, "failed to probe arc emac (%d)\n", err);
-		goto out_regulator_disable;
-	}
-
 	return 0;
 
 out_regulator_disable:
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index bd377a6..df54475 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -86,9 +86,14 @@
 	while (!cur_buf->skb && next != rxq->read_idx) {
 		struct alx_rfd *rfd = &rxq->rfd[cur];
 
-		skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp);
+		skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size + 64, gfp);
 		if (!skb)
 			break;
+
+		/* Workround for the HW RX DMA overflow issue */
+		if (((unsigned long)skb->data & 0xfff) == 0xfc0)
+			skb_reserve(skb, 64);
+
 		dma = dma_map_single(&alx->hw.pdev->dev,
 				     skb->data, alx->rxbuf_size,
 				     DMA_FROM_DEVICE);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 8f76f45..2ff4658 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1412,7 +1412,7 @@
 
 	err = -EIO;
 
-	netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_RX;
+	netdev->hw_features = NETIF_F_HW_VLAN_CTAG_RX;
 	netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
 
 	/* Init PHY as early as possible due to power saving issue  */
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 8581063..8860e74 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -732,11 +732,8 @@
 	unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs;
 	unsigned int pkts_compl = 0, bytes_compl = 0;
 	struct bcm_sysport_cb *cb;
-	struct netdev_queue *txq;
 	u32 hw_ind;
 
-	txq = netdev_get_tx_queue(ndev, ring->index);
-
 	/* Compute how many descriptors have been processed since last call */
 	hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index));
 	c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK;
@@ -767,9 +764,6 @@
 
 	ring->c_index = c_index;
 
-	if (netif_tx_queue_stopped(txq) && pkts_compl)
-		netif_tx_wake_queue(txq);
-
 	netif_dbg(priv, tx_done, ndev,
 		  "ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n",
 		  ring->index, ring->c_index, pkts_compl, bytes_compl);
@@ -781,16 +775,33 @@
 static unsigned int bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
 					   struct bcm_sysport_tx_ring *ring)
 {
+	struct netdev_queue *txq;
 	unsigned int released;
 	unsigned long flags;
 
+	txq = netdev_get_tx_queue(priv->netdev, ring->index);
+
 	spin_lock_irqsave(&ring->lock, flags);
 	released = __bcm_sysport_tx_reclaim(priv, ring);
+	if (released)
+		netif_tx_wake_queue(txq);
+
 	spin_unlock_irqrestore(&ring->lock, flags);
 
 	return released;
 }
 
+/* Locked version of the per-ring TX reclaim, but does not wake the queue */
+static void bcm_sysport_tx_clean(struct bcm_sysport_priv *priv,
+				 struct bcm_sysport_tx_ring *ring)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ring->lock, flags);
+	__bcm_sysport_tx_reclaim(priv, ring);
+	spin_unlock_irqrestore(&ring->lock, flags);
+}
+
 static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
 {
 	struct bcm_sysport_tx_ring *ring =
@@ -1275,7 +1286,7 @@
 	napi_disable(&ring->napi);
 	netif_napi_del(&ring->napi);
 
-	bcm_sysport_tx_reclaim(priv, ring);
+	bcm_sysport_tx_clean(priv, ring);
 
 	kfree(ring->cbs);
 	ring->cbs = NULL;
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 28f7610..a5e4b4b 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -219,7 +219,7 @@
 	dma_unmap_single(dma_dev, slot->dma_addr, skb_headlen(skb),
 			 DMA_TO_DEVICE);
 
-	while (i > 0) {
+	while (i-- > 0) {
 		int index = (ring->end + i) % BGMAC_TX_RING_SLOTS;
 		struct bgmac_slot_info *slot = &ring->slots[index];
 		u32 ctl1 = le32_to_cpu(ring->cpu_base[index].ctl1);
@@ -255,15 +255,16 @@
 	while (ring->start != ring->end) {
 		int slot_idx = ring->start % BGMAC_TX_RING_SLOTS;
 		struct bgmac_slot_info *slot = &ring->slots[slot_idx];
-		u32 ctl1;
+		u32 ctl0, ctl1;
 		int len;
 
 		if (slot_idx == empty_slot)
 			break;
 
+		ctl0 = le32_to_cpu(ring->cpu_base[slot_idx].ctl0);
 		ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1);
 		len = ctl1 & BGMAC_DESC_CTL1_LEN;
-		if (ctl1 & BGMAC_DESC_CTL0_SOF)
+		if (ctl0 & BGMAC_DESC_CTL0_SOF)
 			/* Unmap no longer used buffer */
 			dma_unmap_single(dma_dev, slot->dma_addr, len,
 					 DMA_TO_DEVICE);
@@ -314,6 +315,10 @@
 	u32 ctl;
 
 	ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL);
+
+	/* preserve ONLY bits 16-17 from current hardware value */
+	ctl &= BGMAC_DMA_RX_ADDREXT_MASK;
+
 	if (bgmac->core->id.rev >= 4) {
 		ctl &= ~BGMAC_DMA_RX_BL_MASK;
 		ctl |= BGMAC_DMA_RX_BL_128 << BGMAC_DMA_RX_BL_SHIFT;
@@ -324,7 +329,6 @@
 		ctl &= ~BGMAC_DMA_RX_PT_MASK;
 		ctl |= BGMAC_DMA_RX_PT_1 << BGMAC_DMA_RX_PT_SHIFT;
 	}
-	ctl &= BGMAC_DMA_RX_ADDREXT_MASK;
 	ctl |= BGMAC_DMA_RX_ENABLE;
 	ctl |= BGMAC_DMA_RX_PARITY_DISABLE;
 	ctl |= BGMAC_DMA_RX_OVERFLOW_CONT;
@@ -466,6 +470,11 @@
 			len -= ETH_FCS_LEN;
 
 			skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE);
+			if (unlikely(!skb)) {
+				bgmac_err(bgmac, "build_skb failed\n");
+				put_page(virt_to_head_page(buf));
+				break;
+			}
 			skb_put(skb, BGMAC_RX_FRAME_OFFSET +
 				BGMAC_RX_BUF_OFFSET + len);
 			skb_pull(skb, BGMAC_RX_FRAME_OFFSET +
@@ -1299,7 +1308,8 @@
 
 	phy_start(bgmac->phy_dev);
 
-	netif_carrier_on(net_dev);
+	netif_start_queue(net_dev);
+
 	return 0;
 }
 
@@ -1573,6 +1583,11 @@
 		dev_warn(&core->dev, "Using random MAC: %pM\n", mac);
 	}
 
+	/* This (reset &) enable is not preset in specs or reference driver but
+	 * Broadcom does it in arch PCI code when enabling fake PCI device.
+	 */
+	bcma_core_enable(core, 0);
+
 	/* Allocation and references */
 	net_dev = alloc_etherdev(sizeof(*bgmac));
 	if (!net_dev)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index c82ab87..e5911cc 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1949,7 +1949,7 @@
 	}
 
 	/* select a non-FCoE queue */
-	return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
+	return fallback(dev, skb) % (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos);
 }
 
 void bnx2x_set_num_queues(struct bnx2x *bp)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 2e611dc..1c81238 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -14819,6 +14819,10 @@
 	}
 
 	offset = SHMEM2_RD(bp, fc_npiv_nvram_tbl_addr[BP_PORT(bp)]);
+	if (!offset) {
+		DP(BNX2X_MSG_MCP, "No FC-NPIV in NVRAM\n");
+		goto out;
+	}
 	DP(BNX2X_MSG_MCP, "Offset of FC-NPIV in NVRAM: %08x\n", offset);
 
 	/* Read the table contents from nvram */
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 07f5f23..4744919 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -2473,7 +2473,8 @@
 		INIT_HLIST_HEAD(&bp->ntp_fltr_hash_tbl[i]);
 
 	bp->ntp_fltr_count = 0;
-	bp->ntp_fltr_bmap = kzalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR),
+	bp->ntp_fltr_bmap = kcalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR),
+				    sizeof(long),
 				    GFP_KERNEL);
 
 	if (!bp->ntp_fltr_bmap)
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 0fb3f8d..f971d92 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1168,6 +1168,7 @@
 					  struct bcmgenet_tx_ring *ring)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct device *kdev = &priv->pdev->dev;
 	struct enet_cb *tx_cb_ptr;
 	struct netdev_queue *txq;
 	unsigned int pkts_compl = 0;
@@ -1195,7 +1196,7 @@
 			pkts_compl++;
 			dev->stats.tx_packets++;
 			dev->stats.tx_bytes += tx_cb_ptr->skb->len;
-			dma_unmap_single(&dev->dev,
+			dma_unmap_single(kdev,
 					 dma_unmap_addr(tx_cb_ptr, dma_addr),
 					 dma_unmap_len(tx_cb_ptr, dma_len),
 					 DMA_TO_DEVICE);
@@ -1203,7 +1204,7 @@
 		} else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) {
 			dev->stats.tx_bytes +=
 				dma_unmap_len(tx_cb_ptr, dma_len);
-			dma_unmap_page(&dev->dev,
+			dma_unmap_page(kdev,
 				       dma_unmap_addr(tx_cb_ptr, dma_addr),
 				       dma_unmap_len(tx_cb_ptr, dma_len),
 				       DMA_TO_DEVICE);
@@ -1754,6 +1755,7 @@
 
 static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)
 {
+	struct device *kdev = &priv->pdev->dev;
 	struct enet_cb *cb;
 	int i;
 
@@ -1761,7 +1763,7 @@
 		cb = &priv->rx_cbs[i];
 
 		if (dma_unmap_addr(cb, dma_addr)) {
-			dma_unmap_single(&priv->dev->dev,
+			dma_unmap_single(kdev,
 					 dma_unmap_addr(cb, dma_addr),
 					 priv->rx_buf_len, DMA_FROM_DEVICE);
 			dma_unmap_addr_set(cb, dma_addr, 0);
@@ -3493,7 +3495,8 @@
 
 	bcmgenet_netif_stop(dev);
 
-	phy_suspend(priv->phydev);
+	if (!device_may_wakeup(d))
+		phy_suspend(priv->phydev);
 
 	netif_device_detach(dev);
 
@@ -3590,7 +3593,8 @@
 
 	netif_device_attach(dev);
 
-	phy_resume(priv->phydev);
+	if (!device_may_wakeup(d))
+		phy_resume(priv->phydev);
 
 	if (priv->eee.eee_enabled)
 		bcmgenet_eee_enable_set(dev, true);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index 8bdfe53..e96d1f9 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -220,20 +220,6 @@
 	udelay(60);
 }
 
-static void bcmgenet_internal_phy_setup(struct net_device *dev)
-{
-	struct bcmgenet_priv *priv = netdev_priv(dev);
-	u32 reg;
-
-	/* Power up PHY */
-	bcmgenet_phy_power_set(dev, true);
-	/* enable APD */
-	reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
-	reg |= EXT_PWR_DN_EN_LD;
-	bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
-	bcmgenet_mii_reset(dev);
-}
-
 static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
 {
 	u32 reg;
@@ -281,7 +267,6 @@
 
 		if (priv->internal_phy) {
 			phy_name = "internal PHY";
-			bcmgenet_internal_phy_setup(dev);
 		} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
 			phy_name = "MoCA";
 			bcmgenet_moca_phy_setup(priv);
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index ca5ac5d..21e5b9e 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -12031,7 +12031,7 @@
 	int ret;
 	u32 offset, len, b_offset, odd_len;
 	u8 *buf;
-	__be32 start, end;
+	__be32 start = 0, end;
 
 	if (tg3_flag(tp, NO_NVRAM) ||
 	    eeprom->magic != TG3_EEPROM_MAGIC)
@@ -18142,14 +18142,14 @@
 
 	rtnl_lock();
 
-	/* We needn't recover from permanent error */
-	if (state == pci_channel_io_frozen)
-		tp->pcierr_recovery = true;
-
 	/* We probably don't have netdev yet */
 	if (!netdev || !netif_running(netdev))
 		goto done;
 
+	/* We needn't recover from permanent error */
+	if (state == pci_channel_io_frozen)
+		tp->pcierr_recovery = true;
+
 	tg3_phy_stop(tp);
 
 	tg3_netif_stop(tp);
@@ -18246,7 +18246,7 @@
 
 	rtnl_lock();
 
-	if (!netif_running(netdev))
+	if (!netdev || !netif_running(netdev))
 		goto done;
 
 	tg3_full_lock(tp, 0);
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 169059c..8d54e7b 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -2405,9 +2405,9 @@
 	if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII)
 		val = GEM_BIT(RGMII);
 	else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII &&
-		 (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII))
+		 (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
 		val = MACB_BIT(RMII);
-	else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII))
+	else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
 		val = MACB_BIT(MII);
 
 	if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN)
@@ -2738,7 +2738,7 @@
 }
 
 static const struct macb_config at91sam9260_config = {
-	.caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII,
+	.caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
 };
@@ -2751,21 +2751,22 @@
 };
 
 static const struct macb_config sama5d2_config = {
-	.caps = 0,
+	.caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
 	.dma_burst_length = 16,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
 };
 
 static const struct macb_config sama5d3_config = {
-	.caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
+	.caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE
+	      | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
 	.dma_burst_length = 16,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
 };
 
 static const struct macb_config sama5d4_config = {
-	.caps = 0,
+	.caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
 	.dma_burst_length = 4,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index d83b0db..3f385ab 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -398,7 +398,7 @@
 /* Capability mask bits */
 #define MACB_CAPS_ISR_CLEAR_ON_WRITE		0x00000001
 #define MACB_CAPS_USRIO_HAS_CLKEN		0x00000002
-#define MACB_CAPS_USRIO_DEFAULT_IS_MII		0x00000004
+#define MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII	0x00000004
 #define MACB_CAPS_NO_GIGABIT_HALF		0x00000008
 #define MACB_CAPS_FIFO_MODE			0x10000000
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE	0x20000000
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index b895044..cc17256 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2526,7 +2526,7 @@
 
 	octeon_swap_8B_data(&resp->timestamp, 1);
 
-	if (unlikely((skb_shinfo(skb)->tx_flags | SKBTX_IN_PROGRESS) != 0)) {
+	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) != 0)) {
 		struct skb_shared_hwtstamps ts;
 		u64 ns = resp->timestamp;
 
@@ -2823,7 +2823,7 @@
 		if (!g) {
 			netif_info(lio, tx_err, lio->netdev,
 				   "Transmit scatter gather: glist null!\n");
-			goto lio_xmit_failed;
+			goto lio_xmit_dma_failed;
 		}
 
 		cmdsetup.s.gather = 1;
@@ -2894,7 +2894,7 @@
 	else
 		status = octnet_send_nic_data_pkt(oct, &ndata, xmit_more);
 	if (status == IQ_SEND_FAILED)
-		goto lio_xmit_failed;
+		goto lio_xmit_dma_failed;
 
 	netif_info(lio, tx_queued, lio->netdev, "Transmit queued successfully\n");
 
@@ -2908,12 +2908,13 @@
 
 	return NETDEV_TX_OK;
 
+lio_xmit_dma_failed:
+	dma_unmap_single(&oct->pci_dev->dev, ndata.cmd.dptr,
+			 ndata.datasize, DMA_TO_DEVICE);
 lio_xmit_failed:
 	stats->tx_dropped++;
 	netif_info(lio, tx_err, lio->netdev, "IQ%d Transmit dropped:%llu\n",
 		   iq_no, stats->tx_dropped);
-	dma_unmap_single(&oct->pci_dev->dev, ndata.cmd.dptr,
-			 ndata.datasize, DMA_TO_DEVICE);
 	recv_buffer_free(skb);
 	return NETDEV_TX_OK;
 }
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 39ca674..22471d2 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -116,6 +116,15 @@
 #define NIC_PF_INTR_ID_MBOX0		8
 #define NIC_PF_INTR_ID_MBOX1		9
 
+/* Minimum FIFO level before all packets for the CQ are dropped
+ *
+ * This value ensures that once a packet has been "accepted"
+ * for reception it will not get dropped due to non-availability
+ * of CQ descriptor. An errata in HW mandates this value to be
+ * atleast 0x100.
+ */
+#define NICPF_CQM_MIN_DROP_LEVEL       0x100
+
 /* Global timer for CQ timer thresh interrupts
  * Calculated for SCLK of 700Mhz
  * value written should be a 1/16th of what is expected
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 5f24d11..16baaaf 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -309,6 +309,7 @@
 static void nic_init_hw(struct nicpf *nic)
 {
 	int i;
+	u64 cqm_cfg;
 
 	/* Enable NIC HW block */
 	nic_reg_write(nic, NIC_PF_CFG, 0x3);
@@ -345,6 +346,11 @@
 	/* Enable VLAN ethertype matching and stripping */
 	nic_reg_write(nic, NIC_PF_RX_ETYPE_0_7,
 		      (2 << 19) | (ETYPE_ALG_VLAN_STRIP << 16) | ETH_P_8021Q);
+
+	/* Check if HW expected value is higher (could be in future chips) */
+	cqm_cfg = nic_reg_read(nic, NIC_PF_CQM_CFG);
+	if (cqm_cfg < NICPF_CQM_MIN_DROP_LEVEL)
+		nic_reg_write(nic, NIC_PF_CQM_CFG, NICPF_CQM_MIN_DROP_LEVEL);
 }
 
 /* Channel parse index configuration */
diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h
index dd536be..fab35a5 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_reg.h
+++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h
@@ -21,7 +21,7 @@
 #define   NIC_PF_TCP_TIMER			(0x0060)
 #define   NIC_PF_BP_CFG				(0x0080)
 #define   NIC_PF_RRM_CFG			(0x0088)
-#define   NIC_PF_CQM_CF				(0x00A0)
+#define   NIC_PF_CQM_CFG			(0x00A0)
 #define   NIC_PF_CNM_CF				(0x00A8)
 #define   NIC_PF_CNM_STATUS			(0x00B0)
 #define   NIC_PF_CQ_AVG_CFG			(0x00C0)
@@ -170,7 +170,6 @@
 #define   NIC_QSET_SQ_0_7_DOOR			(0x010838)
 #define   NIC_QSET_SQ_0_7_STATUS		(0x010840)
 #define   NIC_QSET_SQ_0_7_DEBUG			(0x010848)
-#define   NIC_QSET_SQ_0_7_CNM_CHG		(0x010860)
 #define   NIC_QSET_SQ_0_7_STAT_0_1		(0x010900)
 
 #define   NIC_QSET_RBDR_0_1_CFG			(0x010C00)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
index a12b2e3..ff1d777 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
@@ -380,7 +380,10 @@
 		p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DOOR, q);
 		p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS, q);
 		p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DEBUG, q);
-		p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CNM_CHG, q);
+		/* Padding, was NIC_QSET_SQ_0_7_CNM_CHG, which
+		 * produces bus errors when read
+		 */
+		p[i++] = 0;
 		p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STAT_0_1, q);
 		reg_offset = NIC_QSET_SQ_0_7_STAT_0_1 | (1 << 3);
 		p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index dde8dc7..b7093b9 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -566,8 +566,7 @@
 
 static void nicvf_rcv_pkt_handler(struct net_device *netdev,
 				  struct napi_struct *napi,
-				  struct cmp_queue *cq,
-				  struct cqe_rx_t *cqe_rx, int cqe_type)
+				  struct cqe_rx_t *cqe_rx)
 {
 	struct sk_buff *skb;
 	struct nicvf *nic = netdev_priv(netdev);
@@ -583,7 +582,7 @@
 	}
 
 	/* Check for errors */
-	err = nicvf_check_cqe_rx_errs(nic, cq, cqe_rx);
+	err = nicvf_check_cqe_rx_errs(nic, cqe_rx);
 	if (err && !cqe_rx->rb_cnt)
 		return;
 
@@ -674,8 +673,7 @@
 			   cq_idx, cq_desc->cqe_type);
 		switch (cq_desc->cqe_type) {
 		case CQE_TYPE_RX:
-			nicvf_rcv_pkt_handler(netdev, napi, cq,
-					      cq_desc, CQE_TYPE_RX);
+			nicvf_rcv_pkt_handler(netdev, napi, cq_desc);
 			work_done++;
 		break;
 		case CQE_TYPE_SEND:
@@ -1117,7 +1115,6 @@
 
 	/* Clear multiqset info */
 	nic->pnicvf = nic;
-	nic->sqs_count = 0;
 
 	return 0;
 }
@@ -1346,6 +1343,9 @@
 	drv_stats->tx_frames_ok = stats->tx_ucast_frames_ok +
 				  stats->tx_bcast_frames_ok +
 				  stats->tx_mcast_frames_ok;
+	drv_stats->rx_frames_ok = stats->rx_ucast_frames +
+				  stats->rx_bcast_frames +
+				  stats->rx_mcast_frames;
 	drv_stats->rx_drops = stats->rx_drop_red +
 			      stats->rx_drop_overrun;
 	drv_stats->tx_drops = stats->tx_drops;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index 206b6a7..912ee28 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -550,6 +550,7 @@
 		nicvf_config_vlan_stripping(nic, nic->netdev->features);
 
 	/* Enable Receive queue */
+	memset(&rq_cfg, 0, sizeof(struct rq_cfg));
 	rq_cfg.ena = 1;
 	rq_cfg.tcp_ena = 0;
 	nicvf_queue_reg_write(nic, NIC_QSET_RQ_0_7_CFG, qidx, *(u64 *)&rq_cfg);
@@ -582,6 +583,7 @@
 			      qidx, (u64)(cq->dmem.phys_base));
 
 	/* Enable Completion queue */
+	memset(&cq_cfg, 0, sizeof(struct cq_cfg));
 	cq_cfg.ena = 1;
 	cq_cfg.reset = 0;
 	cq_cfg.caching = 0;
@@ -630,6 +632,7 @@
 			      qidx, (u64)(sq->dmem.phys_base));
 
 	/* Enable send queue  & set queue size */
+	memset(&sq_cfg, 0, sizeof(struct sq_cfg));
 	sq_cfg.ena = 1;
 	sq_cfg.reset = 0;
 	sq_cfg.ldwb = 0;
@@ -666,6 +669,7 @@
 
 	/* Enable RBDR  & set queue size */
 	/* Buffer size should be in multiples of 128 bytes */
+	memset(&rbdr_cfg, 0, sizeof(struct rbdr_cfg));
 	rbdr_cfg.ena = 1;
 	rbdr_cfg.reset = 0;
 	rbdr_cfg.ldwb = 0;
@@ -1410,16 +1414,12 @@
 }
 
 /* Check for errors in the receive cmp.queue entry */
-int nicvf_check_cqe_rx_errs(struct nicvf *nic,
-			    struct cmp_queue *cq, struct cqe_rx_t *cqe_rx)
+int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
 {
 	struct nicvf_hw_stats *stats = &nic->hw_stats;
-	struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
 
-	if (!cqe_rx->err_level && !cqe_rx->err_opcode) {
-		drv_stats->rx_frames_ok++;
+	if (!cqe_rx->err_level && !cqe_rx->err_opcode)
 		return 0;
-	}
 
 	if (netif_msg_rx_err(nic))
 		netdev_err(nic->netdev,
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
index 033e830..5652c61 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
@@ -344,8 +344,7 @@
 /* Stats */
 void nicvf_update_rq_stats(struct nicvf *nic, int rq_idx);
 void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx);
-int nicvf_check_cqe_rx_errs(struct nicvf *nic,
-			    struct cmp_queue *cq, struct cqe_rx_t *cqe_rx);
+int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx);
 int nicvf_check_cqe_tx_errs(struct nicvf *nic,
 			    struct cmp_queue *cq, struct cqe_send_t *cqe_tx);
 #endif /* NICVF_QUEUES_H */
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 9df26c2..42718cc 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -549,7 +549,9 @@
 	}
 
 	/* Clear rcvflt bit (latching high) and read it back */
-	bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS2, SPU_STATUS2_RCVFLT);
+	if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT)
+		bgx_reg_modify(bgx, lmacid,
+			       BGX_SPUX_STATUS2, SPU_STATUS2_RCVFLT);
 	if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) {
 		dev_err(&bgx->pdev->dev, "Receive fault, retry training\n");
 		if (bgx->use_training) {
@@ -568,13 +570,6 @@
 		return -1;
 	}
 
-	/* Wait for MAC RX to be ready */
-	if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_RX_CTL,
-			 SMU_RX_CTL_STATUS, true)) {
-		dev_err(&bgx->pdev->dev, "SMU RX link not okay\n");
-		return -1;
-	}
-
 	/* Wait for BGX RX to be idle */
 	if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_CTL, SMU_CTL_RX_IDLE, false)) {
 		dev_err(&bgx->pdev->dev, "SMU RX not idle\n");
@@ -587,29 +582,30 @@
 		return -1;
 	}
 
-	if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) {
-		dev_err(&bgx->pdev->dev, "Receive fault\n");
-		return -1;
-	}
-
-	/* Receive link is latching low. Force it high and verify it */
-	bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS1, SPU_STATUS1_RCV_LNK);
-	if (bgx_poll_reg(bgx, lmacid, BGX_SPUX_STATUS1,
-			 SPU_STATUS1_RCV_LNK, false)) {
-		dev_err(&bgx->pdev->dev, "SPU receive link down\n");
-		return -1;
-	}
-
+	/* Clear receive packet disable */
 	cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_MISC_CONTROL);
 	cfg &= ~SPU_MISC_CTL_RX_DIS;
 	bgx_reg_write(bgx, lmacid, BGX_SPUX_MISC_CONTROL, cfg);
-	return 0;
+
+	/* Check for MAC RX faults */
+	cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_RX_CTL);
+	/* 0 - Link is okay, 1 - Local fault, 2 - Remote fault */
+	cfg &= SMU_RX_CTL_STATUS;
+	if (!cfg)
+		return 0;
+
+	/* Rx local/remote fault seen.
+	 * Do lmac reinit to see if condition recovers
+	 */
+	bgx_lmac_xaui_init(bgx, lmacid, bgx->lmac_type);
+
+	return -1;
 }
 
 static void bgx_poll_for_link(struct work_struct *work)
 {
 	struct lmac *lmac;
-	u64 link;
+	u64 spu_link, smu_link;
 
 	lmac = container_of(work, struct lmac, dwork.work);
 
@@ -619,8 +615,11 @@
 	bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1,
 		     SPU_STATUS1_RCV_LNK, false);
 
-	link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1);
-	if (link & SPU_STATUS1_RCV_LNK) {
+	spu_link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1);
+	smu_link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SMUX_RX_CTL);
+
+	if ((spu_link & SPU_STATUS1_RCV_LNK) &&
+	    !(smu_link & SMU_RX_CTL_STATUS)) {
 		lmac->link_up = 1;
 		if (lmac->bgx->lmac_type == BGX_MODE_XLAUI)
 			lmac->last_speed = 40000;
@@ -634,9 +633,15 @@
 	}
 
 	if (lmac->last_link != lmac->link_up) {
+		if (lmac->link_up) {
+			if (bgx_xaui_check_link(lmac)) {
+				/* Errors, clear link_up state */
+				lmac->link_up = 0;
+				lmac->last_speed = SPEED_UNKNOWN;
+				lmac->last_duplex = DUPLEX_UNKNOWN;
+			}
+		}
 		lmac->last_link = lmac->link_up;
-		if (lmac->link_up)
-			bgx_xaui_check_link(lmac);
 	}
 
 	queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 2);
@@ -708,7 +713,7 @@
 static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid)
 {
 	struct lmac *lmac;
-	u64 cmrx_cfg;
+	u64 cfg;
 
 	lmac = &bgx->lmac[lmacid];
 	if (lmac->check_link) {
@@ -717,9 +722,33 @@
 		destroy_workqueue(lmac->check_link);
 	}
 
-	cmrx_cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
-	cmrx_cfg &= ~(1 << 15);
-	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cmrx_cfg);
+	/* Disable packet reception */
+	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
+	cfg &= ~CMR_PKT_RX_EN;
+	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
+
+	/* Give chance for Rx/Tx FIFO to get drained */
+	bgx_poll_reg(bgx, lmacid, BGX_CMRX_RX_FIFO_LEN, (u64)0x1FFF, true);
+	bgx_poll_reg(bgx, lmacid, BGX_CMRX_TX_FIFO_LEN, (u64)0x3FFF, true);
+
+	/* Disable packet transmission */
+	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
+	cfg &= ~CMR_PKT_TX_EN;
+	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
+
+	/* Disable serdes lanes */
+        if (!lmac->is_sgmii)
+                bgx_reg_modify(bgx, lmacid,
+                               BGX_SPUX_CONTROL1, SPU_CTL_LOW_POWER);
+        else
+                bgx_reg_modify(bgx, lmacid,
+                               BGX_GMP_PCS_MRX_CTL, PCS_MRX_CTL_PWR_DN);
+
+	/* Disable LMAC */
+	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
+	cfg &= ~CMR_EN;
+	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
+
 	bgx_flush_dmac_addrs(bgx, lmacid);
 
 	if ((bgx->lmac_type != BGX_MODE_XFI) &&
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index 149e179..42010d2 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -41,6 +41,7 @@
 #define BGX_CMRX_RX_STAT10		0xC0
 #define BGX_CMRX_RX_BP_DROP		0xC8
 #define BGX_CMRX_RX_DMAC_CTL		0x0E8
+#define BGX_CMRX_RX_FIFO_LEN		0x108
 #define BGX_CMR_RX_DMACX_CAM		0x200
 #define  RX_DMACX_CAM_EN			BIT_ULL(48)
 #define  RX_DMACX_CAM_LMACID(x)			(x << 49)
@@ -50,6 +51,7 @@
 #define BGX_CMR_CHAN_MSK_AND		0x450
 #define BGX_CMR_BIST_STATUS		0x460
 #define BGX_CMR_RX_LMACS		0x468
+#define BGX_CMRX_TX_FIFO_LEN		0x518
 #define BGX_CMRX_TX_STAT0		0x600
 #define BGX_CMRX_TX_STAT1		0x608
 #define BGX_CMRX_TX_STAT2		0x610
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 0d14761..090e006 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2714,10 +2714,14 @@
 		if (err)
 			goto irq_err;
 	}
+
+	mutex_lock(&uld_mutex);
 	enable_rx(adap);
 	t4_sge_start(adap);
 	t4_intr_enable(adap);
 	adap->flags |= FULL_INIT_DONE;
+	mutex_unlock(&uld_mutex);
+
 	notify_ulds(adap, CXGB4_STATE_UP);
 #if IS_ENABLED(CONFIG_IPV6)
 	update_clip(adap);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 1795c93..7b8638d 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1052,7 +1052,7 @@
 err:
 	spin_unlock_bh(&adapter->mcc_lock);
 
-	 if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
+	 if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST)
 		status = -EPERM;
 
 	return status;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 8a1d9ff..2625586 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5260,9 +5260,11 @@
 	struct be_adapter *adapter = netdev_priv(dev);
 	u8 l4_hdr = 0;
 
-	/* The code below restricts offload features for some tunneled packets.
+	/* The code below restricts offload features for some tunneled and
+	 * Q-in-Q packets.
 	 * Offload features for normal (non tunnel) packets are unchanged.
 	 */
+	features = vlan_features_check(skb, features);
 	if (!skb->encapsulation ||
 	    !(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS))
 		return features;
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index ff66549..52f2230 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -713,6 +713,8 @@
 	if (ret)
 		return ret;
 
+	napi_enable(&priv->napi);
+
 	ethoc_init_ring(priv, dev->mem_start);
 	ethoc_reset(priv);
 
@@ -725,7 +727,6 @@
 	}
 
 	phy_start(priv->phy);
-	napi_enable(&priv->napi);
 
 	if (netif_msg_ifup(priv)) {
 		dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n",
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index b2a3220..ab71604 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -944,11 +944,11 @@
 	 * enet-mac reset will reset mac address registers too,
 	 * so need to reconfigure it.
 	 */
-	if (fep->quirks & FEC_QUIRK_ENET_MAC) {
-		memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
-		writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
-		writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
-	}
+	memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
+	writel((__force u32)cpu_to_be32(temp_mac[0]),
+	       fep->hwp + FEC_ADDR_LOW);
+	writel((__force u32)cpu_to_be32(temp_mac[1]),
+	       fep->hwp + FEC_ADDR_HIGH);
 
 	/* Clear any outstanding interrupt. */
 	writel(0xffffffff, fep->hwp + FEC_IEVENT);
@@ -1557,9 +1557,15 @@
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
 	for_each_set_bit(queue_id, &fep->work_rx, FEC_ENET_MAX_RX_QS) {
-		clear_bit(queue_id, &fep->work_rx);
-		pkt_received += fec_enet_rx_queue(ndev,
+		int ret;
+
+		ret = fec_enet_rx_queue(ndev,
 					budget - pkt_received, queue_id);
+
+		if (ret < budget - pkt_received)
+			clear_bit(queue_id, &fep->work_rx);
+
+		pkt_received += ret;
 	}
 	return pkt_received;
 }
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 3e233d9..4cd2a7d 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -1999,8 +1999,8 @@
 		if (!rxb->page)
 			continue;
 
-		dma_unmap_single(rx_queue->dev, rxb->dma,
-				 PAGE_SIZE, DMA_FROM_DEVICE);
+		dma_unmap_page(rx_queue->dev, rxb->dma,
+			       PAGE_SIZE, DMA_FROM_DEVICE);
 		__free_page(rxb->page);
 
 		rxb->page = NULL;
@@ -2939,7 +2939,7 @@
 				size, GFAR_RXB_TRUESIZE);
 
 	/* try reuse page */
-	if (unlikely(page_count(page) != 1))
+	if (unlikely(page_count(page) != 1 || page_is_pfmemalloc(page)))
 		return false;
 
 	/* change offset to the other half */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
index bdbd804..9ff2881 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
@@ -900,9 +900,7 @@
 
 static inline void dsaf_write_reg(void __iomem *base, u32 reg, u32 value)
 {
-	u8 __iomem *reg_addr = ACCESS_ONCE(base);
-
-	writel(value, reg_addr + reg);
+	writel(value, base + reg);
 }
 
 #define dsaf_write_dev(a, reg, value) \
@@ -910,9 +908,7 @@
 
 static inline u32 dsaf_read_reg(u8 __iomem *base, u32 reg)
 {
-	u8 __iomem *reg_addr = ACCESS_ONCE(base);
-
-	return readl(reg_addr + reg);
+	return readl(base + reg);
 }
 
 #define dsaf_read_dev(a, reg) \
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 08cef0d..2fa54b0 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -105,8 +105,8 @@
 			struct hns_nic_ring_data *ring_data)
 {
 	struct hns_nic_priv *priv = netdev_priv(ndev);
-	struct device *dev = priv->dev;
 	struct hnae_ring *ring = ring_data->ring;
+	struct device *dev = ring_to_dev(ring);
 	struct netdev_queue *dev_queue;
 	struct skb_frag_struct *frag;
 	int buf_num;
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 7af870a..2f9b12c 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -58,7 +58,7 @@
 
 static const char ibmveth_driver_name[] = "ibmveth";
 static const char ibmveth_driver_string[] = "IBM Power Virtual Ethernet Driver";
-#define ibmveth_driver_version "1.05"
+#define ibmveth_driver_version "1.06"
 
 MODULE_AUTHOR("Santiago Leon <santil@linux.vnet.ibm.com>");
 MODULE_DESCRIPTION("IBM Power Virtual Ethernet Driver");
@@ -137,6 +137,11 @@
 	return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_OFF_MASK;
 }
 
+static inline int ibmveth_rxq_large_packet(struct ibmveth_adapter *adapter)
+{
+	return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_LRG_PKT;
+}
+
 static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter)
 {
 	return be32_to_cpu(adapter->rx_queue.queue_addr[adapter->rx_queue.index].length);
@@ -1172,6 +1177,53 @@
 	goto retry_bounce;
 }
 
+static void ibmveth_rx_mss_helper(struct sk_buff *skb, u16 mss, int lrg_pkt)
+{
+	struct tcphdr *tcph;
+	int offset = 0;
+	int hdr_len;
+
+	/* only TCP packets will be aggregated */
+	if (skb->protocol == htons(ETH_P_IP)) {
+		struct iphdr *iph = (struct iphdr *)skb->data;
+
+		if (iph->protocol == IPPROTO_TCP) {
+			offset = iph->ihl * 4;
+			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+		} else {
+			return;
+		}
+	} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		struct ipv6hdr *iph6 = (struct ipv6hdr *)skb->data;
+
+		if (iph6->nexthdr == IPPROTO_TCP) {
+			offset = sizeof(struct ipv6hdr);
+			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
+		} else {
+			return;
+		}
+	} else {
+		return;
+	}
+	/* if mss is not set through Large Packet bit/mss in rx buffer,
+	 * expect that the mss will be written to the tcp header checksum.
+	 */
+	tcph = (struct tcphdr *)(skb->data + offset);
+	if (lrg_pkt) {
+		skb_shinfo(skb)->gso_size = mss;
+	} else if (offset) {
+		skb_shinfo(skb)->gso_size = ntohs(tcph->check);
+		tcph->check = 0;
+	}
+
+	if (skb_shinfo(skb)->gso_size) {
+		hdr_len = offset + tcph->doff * 4;
+		skb_shinfo(skb)->gso_segs =
+				DIV_ROUND_UP(skb->len - hdr_len,
+					     skb_shinfo(skb)->gso_size);
+	}
+}
+
 static int ibmveth_poll(struct napi_struct *napi, int budget)
 {
 	struct ibmveth_adapter *adapter =
@@ -1180,6 +1232,7 @@
 	int frames_processed = 0;
 	unsigned long lpar_rc;
 	struct iphdr *iph;
+	u16 mss = 0;
 
 restart_poll:
 	while (frames_processed < budget) {
@@ -1197,9 +1250,21 @@
 			int length = ibmveth_rxq_frame_length(adapter);
 			int offset = ibmveth_rxq_frame_offset(adapter);
 			int csum_good = ibmveth_rxq_csum_good(adapter);
+			int lrg_pkt = ibmveth_rxq_large_packet(adapter);
 
 			skb = ibmveth_rxq_get_buffer(adapter);
 
+			/* if the large packet bit is set in the rx queue
+			 * descriptor, the mss will be written by PHYP eight
+			 * bytes from the start of the rx buffer, which is
+			 * skb->data at this stage
+			 */
+			if (lrg_pkt) {
+				__be64 *rxmss = (__be64 *)(skb->data + 8);
+
+				mss = (u16)be64_to_cpu(*rxmss);
+			}
+
 			new_skb = NULL;
 			if (length < rx_copybreak)
 				new_skb = netdev_alloc_skb(netdev, length);
@@ -1233,11 +1298,15 @@
 					if (iph->check == 0xffff) {
 						iph->check = 0;
 						iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-						adapter->rx_large_packets++;
 					}
 				}
 			}
 
+			if (length > netdev->mtu + ETH_HLEN) {
+				ibmveth_rx_mss_helper(skb, mss, lrg_pkt);
+				adapter->rx_large_packets++;
+			}
+
 			napi_gro_receive(napi, skb);	/* send it up */
 
 			netdev->stats.rx_packets++;
@@ -1533,8 +1602,11 @@
 	netdev->netdev_ops = &ibmveth_netdev_ops;
 	netdev->ethtool_ops = &netdev_ethtool_ops;
 	SET_NETDEV_DEV(netdev, &dev->dev);
-	netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev->hw_features = NETIF_F_SG;
+	if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL) {
+		netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+				       NETIF_F_RXCSUM;
+	}
 
 	netdev->features |= netdev->hw_features;
 
diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h
index 4eade67..7acda04 100644
--- a/drivers/net/ethernet/ibm/ibmveth.h
+++ b/drivers/net/ethernet/ibm/ibmveth.h
@@ -209,6 +209,7 @@
 #define IBMVETH_RXQ_TOGGLE		0x80000000
 #define IBMVETH_RXQ_TOGGLE_SHIFT	31
 #define IBMVETH_RXQ_VALID		0x40000000
+#define IBMVETH_RXQ_LRG_PKT		0x04000000
 #define IBMVETH_RXQ_NO_CSUM		0x02000000
 #define IBMVETH_RXQ_CSUM_GOOD		0x01000000
 #define IBMVETH_RXQ_OFF_MASK		0x0000FFFF
diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h
index 6970710..98fe5a2 100644
--- a/drivers/net/ethernet/intel/e1000/e1000.h
+++ b/drivers/net/ethernet/intel/e1000/e1000.h
@@ -213,8 +213,11 @@
 };
 
 #define E1000_DESC_UNUSED(R)						\
-	((((R)->next_to_clean > (R)->next_to_use)			\
-	  ? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1)
+({									\
+	unsigned int clean = smp_load_acquire(&(R)->next_to_clean);	\
+	unsigned int use = READ_ONCE((R)->next_to_use);			\
+	(clean > use ? 0 : (R)->count) + clean - use - 1;		\
+})
 
 #define E1000_RX_DESC_EXT(R, i)						\
 	(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index fd7be86..0680235 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -3876,7 +3876,10 @@
 		eop_desc = E1000_TX_DESC(*tx_ring, eop);
 	}
 
-	tx_ring->next_to_clean = i;
+	/* Synchronize with E1000_DESC_UNUSED called from e1000_xmit_frame,
+	 * which will reuse the cleaned buffers.
+	 */
+	smp_store_release(&tx_ring->next_to_clean, i);
 
 	netdev_completed_queue(netdev, pkts_compl, bytes_compl);
 
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 0a854a4..80ec587 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -1959,8 +1959,10 @@
 	 * previous interrupt.
 	 */
 	if (rx_ring->set_itr) {
-		writel(1000000000 / (rx_ring->itr_val * 256),
-		       rx_ring->itr_register);
+		u32 itr = rx_ring->itr_val ?
+			  1000000000 / (rx_ring->itr_val * 256) : 0;
+
+		writel(itr, rx_ring->itr_register);
 		rx_ring->set_itr = 0;
 	}
 
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h
index 1444020..48809e5 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k.h
@@ -33,7 +33,7 @@
 #include "fm10k_pf.h"
 #include "fm10k_vf.h"
 
-#define FM10K_MAX_JUMBO_FRAME_SIZE	15358	/* Maximum supported size 15K */
+#define FM10K_MAX_JUMBO_FRAME_SIZE	15342	/* Maximum supported size 15K */
 
 #define MAX_QUEUES	FM10K_MAX_QUEUES_PF
 
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index e76a44c..0928155 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -1428,6 +1428,10 @@
 	fm10k_for_each_ring(ring, q_vector->tx)
 		clean_complete &= fm10k_clean_tx_irq(q_vector, ring);
 
+	/* Handle case where we are called by netpoll with a budget of 0 */
+	if (budget <= 0)
+		return budget;
+
 	/* attempt to distribute budget to each queue fairly, but don't
 	 * allow the budget to go below 1 because we'll exit polling
 	 */
@@ -1966,8 +1970,10 @@
 
 	/* Allocate memory for queues */
 	err = fm10k_alloc_q_vectors(interface);
-	if (err)
+	if (err) {
+		fm10k_reset_msix_capability(interface);
 		return err;
+	}
 
 	/* Map rings to devices, and map devices to physical queues */
 	fm10k_assign_rings(interface);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index 74be792..7f3fb51 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -159,13 +159,30 @@
 
 	fm10k_mbx_free_irq(interface);
 
+	/* free interrupts */
+	fm10k_clear_queueing_scheme(interface);
+
 	/* delay any future reset requests */
 	interface->last_reset = jiffies + (10 * HZ);
 
 	/* reset and initialize the hardware so it is in a known state */
-	err = hw->mac.ops.reset_hw(hw) ? : hw->mac.ops.init_hw(hw);
-	if (err)
+	err = hw->mac.ops.reset_hw(hw);
+	if (err) {
+		dev_err(&interface->pdev->dev, "reset_hw failed: %d\n", err);
+		goto reinit_err;
+	}
+
+	err = hw->mac.ops.init_hw(hw);
+	if (err) {
 		dev_err(&interface->pdev->dev, "init_hw failed: %d\n", err);
+		goto reinit_err;
+	}
+
+	err = fm10k_init_queueing_scheme(interface);
+	if (err) {
+		dev_err(&interface->pdev->dev, "init_queueing_scheme failed: %d\n", err);
+		goto reinit_err;
+	}
 
 	/* reassociate interrupts */
 	fm10k_mbx_request_irq(interface);
@@ -193,6 +210,10 @@
 
 	fm10k_iov_resume(interface->pdev);
 
+reinit_err:
+	if (err)
+		netif_device_detach(netdev);
+
 	rtnl_unlock();
 
 	clear_bit(__FM10K_RESETTING, &interface->state);
@@ -1101,6 +1122,10 @@
 	struct fm10k_hw *hw = &interface->hw;
 	int itr_reg;
 
+	/* no mailbox IRQ to free if MSI-X is not enabled */
+	if (!interface->msix_entries)
+		return;
+
 	/* disconnect the mailbox */
 	hw->mbx.ops.disconnect(hw, &hw->mbx);
 
@@ -1423,10 +1448,15 @@
 		err = fm10k_mbx_request_irq_pf(interface);
 	else
 		err = fm10k_mbx_request_irq_vf(interface);
+	if (err)
+		return err;
 
 	/* connect mailbox */
-	if (!err)
-		err = hw->mbx.ops.connect(hw, &hw->mbx);
+	err = hw->mbx.ops.connect(hw, &hw->mbx);
+
+	/* if the mailbox failed to connect, then free IRQ */
+	if (err)
+		fm10k_mbx_free_irq(interface);
 
 	return err;
 }
@@ -1684,7 +1714,13 @@
 	interface->last_reset = jiffies + (10 * HZ);
 
 	/* reset and initialize the hardware so it is in a known state */
-	err = hw->mac.ops.reset_hw(hw) ? : hw->mac.ops.init_hw(hw);
+	err = hw->mac.ops.reset_hw(hw);
+	if (err) {
+		dev_err(&pdev->dev, "reset_hw failed: %d\n", err);
+		return err;
+	}
+
+	err = hw->mac.ops.init_hw(hw);
 	if (err) {
 		dev_err(&pdev->dev, "init_hw failed: %d\n", err);
 		return err;
@@ -2071,8 +2107,10 @@
 
 	/* reset hardware to known state */
 	err = hw->mac.ops.init_hw(&interface->hw);
-	if (err)
+	if (err) {
+		dev_err(&pdev->dev, "init_hw failed: %d\n", err);
 		return err;
+	}
 
 	/* reset statistics starting values */
 	hw->mac.ops.rebind_hw_stats(hw, &interface->stats);
@@ -2185,6 +2223,9 @@
 	if (netif_running(netdev))
 		fm10k_close(netdev);
 
+	/* free interrupts */
+	fm10k_clear_queueing_scheme(interface);
+
 	fm10k_mbx_free_irq(interface);
 
 	pci_disable_device(pdev);
@@ -2248,11 +2289,21 @@
 	int err = 0;
 
 	/* reset hardware to known state */
-	hw->mac.ops.init_hw(&interface->hw);
+	err = hw->mac.ops.init_hw(&interface->hw);
+	if (err) {
+		dev_err(&pdev->dev, "init_hw failed: %d\n", err);
+		return;
+	}
 
 	/* reset statistics starting values */
 	hw->mac.ops.rebind_hw_stats(hw, &interface->stats);
 
+	err = fm10k_init_queueing_scheme(interface);
+	if (err) {
+		dev_err(&interface->pdev->dev, "init_queueing_scheme failed: %d\n", err);
+		return;
+	}
+
 	/* reassociate interrupts */
 	fm10k_mbx_request_irq(interface);
 
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h
index 318a212..35afd71 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h
@@ -77,6 +77,7 @@
 #define FM10K_PCIE_SRIOV_CTRL_VFARI		0x10
 
 #define FM10K_ERR_PARAM				-2
+#define FM10K_ERR_NO_RESOURCES			-3
 #define FM10K_ERR_REQUESTS_PENDING		-4
 #define FM10K_ERR_RESET_REQUESTED		-5
 #define FM10K_ERR_DMA_PENDING			-6
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c
index 36c8b0a..d512575 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c
@@ -103,7 +103,14 @@
 	s32 err;
 	u16 i;
 
-	/* assume we always have at least 1 queue */
+	/* verify we have at least 1 queue */
+	if (!~fm10k_read_reg(hw, FM10K_TXQCTL(0)) ||
+	    !~fm10k_read_reg(hw, FM10K_RXQCTL(0))) {
+		err = FM10K_ERR_NO_RESOURCES;
+		goto reset_max_queues;
+	}
+
+	/* determine how many queues we have */
 	for (i = 1; tqdloc0 && (i < FM10K_MAX_QUEUES_POOL); i++) {
 		/* verify the Descriptor cache offsets are increasing */
 		tqdloc = ~fm10k_read_reg(hw, FM10K_TQDLOC(i));
@@ -119,7 +126,7 @@
 	/* shut down queues we own and reset DMA configuration */
 	err = fm10k_disable_queues_generic(hw, i);
 	if (err)
-		return err;
+		goto reset_max_queues;
 
 	/* record maximum queue count */
 	hw->mac.max_queues = i;
@@ -129,6 +136,11 @@
 			       FM10K_TXQCTL_VID_MASK) >> FM10K_TXQCTL_VID_SHIFT;
 
 	return 0;
+
+reset_max_queues:
+	hw->mac.max_queues = 0;
+
+	return err;
 }
 
 /* This structure defines the attibutes to be parsed below */
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 4dd3e26..7e258a8 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -767,6 +767,8 @@
 int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid);
 struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,
 					     bool is_vf, bool is_netdev);
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
+			  bool is_vf, bool is_netdev);
 bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
 struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
 				      bool is_vf, bool is_netdev);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index 2d74c6e..1cf715c7 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -302,13 +302,15 @@
 		   void *buffer, u16 buf_len)
 {
 	struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc;
-	u16 len = le16_to_cpu(aq_desc->datalen);
+	u16 len;
 	u8 *buf = (u8 *)buffer;
 	u16 i = 0;
 
 	if ((!(mask & hw->debug_mask)) || (desc == NULL))
 		return;
 
+	len = le16_to_cpu(aq_desc->datalen);
+
 	i40e_debug(hw, mask,
 		   "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
 		   le16_to_cpu(aq_desc->opcode),
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 3f385ff..488a50d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -2164,8 +2164,7 @@
 	case TCP_V4_FLOW:
 		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 		case 0:
-			hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
-			break;
+			return -EINVAL;
 		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
 			hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
 			break;
@@ -2176,8 +2175,7 @@
 	case TCP_V6_FLOW:
 		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 		case 0:
-			hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
-			break;
+			return -EINVAL;
 		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
 			hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
 			break;
@@ -2188,9 +2186,7 @@
 	case UDP_V4_FLOW:
 		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 		case 0:
-			hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
-				  BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
-			break;
+			return -EINVAL;
 		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
 			hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
 				 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
@@ -2202,9 +2198,7 @@
 	case UDP_V6_FLOW:
 		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 		case 0:
-			hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
-				  BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
-			break;
+			return -EINVAL;
 		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
 			hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
 				 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 4a9873ec..4edbab6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1317,6 +1317,42 @@
 }
 
 /**
+ * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS
+ * @vsi: the VSI to be searched
+ * @macaddr: the mac address to be removed
+ * @is_vf: true if it is a VF
+ * @is_netdev: true if it is a netdev
+ *
+ * Removes a given MAC address from a VSI, regardless of VLAN
+ *
+ * Returns 0 for success, or error
+ **/
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
+			  bool is_vf, bool is_netdev)
+{
+	struct i40e_mac_filter *f = NULL;
+	int changed = 0;
+
+	WARN(!spin_is_locked(&vsi->mac_filter_list_lock),
+	     "Missing mac_filter_list_lock\n");
+	list_for_each_entry(f, &vsi->mac_filter_list, list) {
+		if ((ether_addr_equal(macaddr, f->macaddr)) &&
+		    (is_vf == f->is_vf) &&
+		    (is_netdev == f->is_netdev)) {
+			f->counter--;
+			f->changed = true;
+			changed = 1;
+		}
+	}
+	if (changed) {
+		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
+		vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
+		return 0;
+	}
+	return -ENOENT;
+}
+
+/**
  * i40e_rm_default_mac_filter - Remove the default MAC filter set by NVM
  * @vsi: the PF Main VSI - inappropriate for any other VSI
  * @macaddr: the MAC address
@@ -1547,9 +1583,11 @@
 		spin_unlock_bh(&vsi->mac_filter_list_lock);
 	}
 
-	i40e_sync_vsi_filters(vsi, false);
 	ether_addr_copy(netdev->dev_addr, addr->sa_data);
-
+	/* schedule our worker thread which will take care of
+	 * applying the new filter changes
+	 */
+	i40e_service_event_schedule(vsi->back);
 	return 0;
 }
 
@@ -1935,11 +1973,13 @@
 
 	/* Now process 'del_list' outside the lock */
 	if (!list_empty(&tmp_del_list)) {
+		int del_list_size;
+
 		filter_list_len = pf->hw.aq.asq_buf_size /
 			    sizeof(struct i40e_aqc_remove_macvlan_element_data);
-		del_list = kcalloc(filter_list_len,
-			    sizeof(struct i40e_aqc_remove_macvlan_element_data),
-			    GFP_KERNEL);
+		del_list_size = filter_list_len *
+			    sizeof(struct i40e_aqc_remove_macvlan_element_data);
+		del_list = kzalloc(del_list_size, GFP_KERNEL);
 		if (!del_list) {
 			i40e_cleanup_add_list(&tmp_add_list);
 
@@ -1971,7 +2011,7 @@
 						  NULL);
 				aq_err = pf->hw.aq.asq_last_status;
 				num_del = 0;
-				memset(del_list, 0, sizeof(*del_list));
+				memset(del_list, 0, del_list_size);
 
 				if (ret && aq_err != I40E_AQ_RC_ENOENT)
 					dev_err(&pf->pdev->dev,
@@ -2004,13 +2044,14 @@
 	}
 
 	if (!list_empty(&tmp_add_list)) {
+		int add_list_size;
 
 		/* do all the adds now */
 		filter_list_len = pf->hw.aq.asq_buf_size /
 			       sizeof(struct i40e_aqc_add_macvlan_element_data),
-		add_list = kcalloc(filter_list_len,
-			       sizeof(struct i40e_aqc_add_macvlan_element_data),
-			       GFP_KERNEL);
+		add_list_size = filter_list_len *
+			       sizeof(struct i40e_aqc_add_macvlan_element_data);
+		add_list = kzalloc(add_list_size, GFP_KERNEL);
 		if (!add_list) {
 			/* Purge element from temporary lists */
 			i40e_cleanup_add_list(&tmp_add_list);
@@ -2048,7 +2089,7 @@
 
 				if (ret)
 					break;
-				memset(add_list, 0, sizeof(*add_list));
+				memset(add_list, 0, add_list_size);
 			}
 			/* Entries from tmp_add_list were cloned from MAC
 			 * filter list, hence clean those cloned entries
@@ -2112,12 +2153,7 @@
 			 */
 			if (pf->cur_promisc != cur_promisc) {
 				pf->cur_promisc = cur_promisc;
-				if (grab_rtnl)
-					i40e_do_reset_safe(pf,
-						BIT(__I40E_PF_RESET_REQUESTED));
-				else
-					i40e_do_reset(pf,
-						BIT(__I40E_PF_RESET_REQUESTED));
+				set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
 			}
 		} else {
 			ret = i40e_aq_set_vsi_unicast_promiscuous(
@@ -2377,16 +2413,13 @@
 		}
 	}
 
-	/* Make sure to release before sync_vsi_filter because that
-	 * function will lock/unlock as necessary
-	 */
 	spin_unlock_bh(&vsi->mac_filter_list_lock);
 
-	if (test_bit(__I40E_DOWN, &vsi->back->state) ||
-	    test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
-		return 0;
-
-	return i40e_sync_vsi_filters(vsi, false);
+	/* schedule our worker thread which will take care of
+	 * applying the new filter changes
+	 */
+	i40e_service_event_schedule(vsi->back);
+	return 0;
 }
 
 /**
@@ -2459,16 +2492,13 @@
 		}
 	}
 
-	/* Make sure to release before sync_vsi_filter because that
-	 * function with lock/unlock as necessary
-	 */
 	spin_unlock_bh(&vsi->mac_filter_list_lock);
 
-	if (test_bit(__I40E_DOWN, &vsi->back->state) ||
-	    test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
-		return 0;
-
-	return i40e_sync_vsi_filters(vsi, false);
+	/* schedule our worker thread which will take care of
+	 * applying the new filter changes
+	 */
+	i40e_service_event_schedule(vsi->back);
+	return 0;
 }
 
 /**
@@ -2711,6 +2741,11 @@
 		netif_set_xps_queue(ring->netdev, mask, ring->queue_index);
 		free_cpumask_var(mask);
 	}
+
+	/* schedule our worker thread which will take care of
+	 * applying the new filter changes
+	 */
+	i40e_service_event_schedule(vsi->back);
 }
 
 /**
@@ -6685,6 +6720,7 @@
 	struct i40e_hw *hw = &pf->hw;
 	u8 set_fc_aq_fail = 0;
 	i40e_status ret;
+	u32 val;
 	u32 v;
 
 	/* Now we wait for GRST to settle out.
@@ -6823,6 +6859,20 @@
 		}
 	}
 
+	/* Reconfigure hardware for allowing smaller MSS in the case
+	 * of TSO, so that we avoid the MDD being fired and causing
+	 * a reset in the case of small MSS+TSO.
+	 */
+#define I40E_REG_MSS          0x000E64DC
+#define I40E_REG_MSS_MIN_MASK 0x3FF0000
+#define I40E_64BYTE_MSS       0x400000
+	val = rd32(hw, I40E_REG_MSS);
+	if ((val & I40E_REG_MSS_MIN_MASK) > I40E_64BYTE_MSS) {
+		val &= ~I40E_REG_MSS_MIN_MASK;
+		val |= I40E_64BYTE_MSS;
+		wr32(hw, I40E_REG_MSS, val);
+	}
+
 	if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) ||
 	    (pf->hw.aq.fw_maj_ver < 4)) {
 		msleep(75);
@@ -8545,7 +8595,7 @@
 		return 0;
 
 	return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode,
-				       nlflags, 0, 0, filter_mask, NULL);
+				       0, 0, nlflags, filter_mask, NULL);
 }
 
 #define I40E_MAX_TUNNEL_HDR_LEN 80
@@ -10183,6 +10233,7 @@
 	u16 link_status;
 	int err;
 	u32 len;
+	u32 val;
 	u32 i;
 	u8 set_fc_aq_fail;
 
@@ -10493,6 +10544,17 @@
 			 i40e_stat_str(&pf->hw, err),
 			 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
 
+	/* Reconfigure hardware for allowing smaller MSS in the case
+	 * of TSO, so that we avoid the MDD being fired and causing
+	 * a reset in the case of small MSS+TSO.
+	 */
+	val = rd32(hw, I40E_REG_MSS);
+	if ((val & I40E_REG_MSS_MIN_MASK) > I40E_64BYTE_MSS) {
+		val &= ~I40E_REG_MSS_MIN_MASK;
+		val |= I40E_64BYTE_MSS;
+		wr32(hw, I40E_REG_MSS, val);
+	}
+
 	if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) ||
 	    (pf->hw.aq.fw_maj_ver < 4)) {
 		msleep(75);
@@ -10791,6 +10853,12 @@
 
 	dev_info(&pdev->dev, "%s: error %d\n", __func__, error);
 
+	if (!pf) {
+		dev_info(&pdev->dev,
+			 "Cannot recover - error happened during device probe\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
 	/* shutdown all operations */
 	if (!test_bit(__I40E_SUSPENDED, &pf->state)) {
 		rtnl_lock();
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 635b3ac..26c55bb 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -235,6 +235,9 @@
 				 "Filter deleted for PCTYPE %d loc = %d\n",
 				 fd_data->pctype, fd_data->fd_id);
 	}
+	if (err)
+		kfree(raw_packet);
+
 	return err ? -EOPNOTSUPP : 0;
 }
 
@@ -312,6 +315,9 @@
 				 fd_data->pctype, fd_data->fd_id);
 	}
 
+	if (err)
+		kfree(raw_packet);
+
 	return err ? -EOPNOTSUPP : 0;
 }
 
@@ -387,6 +393,9 @@
 		}
 	}
 
+	if (err)
+		kfree(raw_packet);
+
 	return err ? -EOPNOTSUPP : 0;
 }
 
@@ -526,11 +535,7 @@
 					    struct i40e_tx_buffer *tx_buffer)
 {
 	if (tx_buffer->skb) {
-		if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
-			kfree(tx_buffer->raw_buf);
-		else
-			dev_kfree_skb_any(tx_buffer->skb);
-
+		dev_kfree_skb_any(tx_buffer->skb);
 		if (dma_unmap_len(tx_buffer, len))
 			dma_unmap_single(ring->dev,
 					 dma_unmap_addr(tx_buffer, dma),
@@ -542,6 +547,10 @@
 			       dma_unmap_len(tx_buffer, len),
 			       DMA_TO_DEVICE);
 	}
+
+	if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
+		kfree(tx_buffer->raw_buf);
+
 	tx_buffer->next_to_watch = NULL;
 	tx_buffer->skb = NULL;
 	dma_unmap_len_set(tx_buffer, len, 0);
@@ -1416,31 +1425,12 @@
 }
 
 /**
- * i40e_rx_hash - returns the hash value from the Rx descriptor
- * @ring: descriptor ring
- * @rx_desc: specific descriptor
- **/
-static inline u32 i40e_rx_hash(struct i40e_ring *ring,
-			       union i40e_rx_desc *rx_desc)
-{
-	const __le64 rss_mask =
-		cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
-			    I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
-
-	if ((ring->netdev->features & NETIF_F_RXHASH) &&
-	    (rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask)
-		return le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
-	else
-		return 0;
-}
-
-/**
- * i40e_ptype_to_hash - get a hash type
+ * i40e_ptype_to_htype - get a hash type
  * @ptype: the ptype value from the descriptor
  *
  * Returns a hash type to be used by skb_set_hash
  **/
-static inline enum pkt_hash_types i40e_ptype_to_hash(u8 ptype)
+static inline enum pkt_hash_types i40e_ptype_to_htype(u8 ptype)
 {
 	struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype);
 
@@ -1458,6 +1448,30 @@
 }
 
 /**
+ * i40e_rx_hash - set the hash value in the skb
+ * @ring: descriptor ring
+ * @rx_desc: specific descriptor
+ **/
+static inline void i40e_rx_hash(struct i40e_ring *ring,
+				union i40e_rx_desc *rx_desc,
+				struct sk_buff *skb,
+				u8 rx_ptype)
+{
+	u32 hash;
+	const __le64 rss_mask  =
+		cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
+			    I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
+
+	if (ring->netdev->features & NETIF_F_RXHASH)
+		return;
+
+	if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
+		hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
+		skb_set_hash(skb, hash, i40e_ptype_to_htype(rx_ptype));
+	}
+}
+
+/**
  * i40e_clean_rx_irq_ps - Reclaim resources after receive; packet split
  * @rx_ring:  rx ring to clean
  * @budget:   how many cleans we're allowed
@@ -1606,8 +1620,8 @@
 			continue;
 		}
 
-		skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc),
-			     i40e_ptype_to_hash(rx_ptype));
+		i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype);
+
 		if (unlikely(rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK)) {
 			i40e_ptp_rx_hwtstamp(vsi->back, skb, (rx_status &
 					   I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
@@ -1736,8 +1750,7 @@
 			continue;
 		}
 
-		skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc),
-			     i40e_ptype_to_hash(rx_ptype));
+		i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype);
 		if (unlikely(rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK)) {
 			i40e_ptp_rx_hwtstamp(vsi->back, skb, (rx_status &
 					   I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 44462b4..e116d9a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -549,12 +549,15 @@
 			i40e_vsi_add_pvid(vsi, vf->port_vlan_id);
 
 		spin_lock_bh(&vsi->mac_filter_list_lock);
-		f = i40e_add_filter(vsi, vf->default_lan_addr.addr,
-				    vf->port_vlan_id ? vf->port_vlan_id : -1,
-				    true, false);
-		if (!f)
-			dev_info(&pf->pdev->dev,
-				 "Could not allocate VF MAC addr\n");
+		if (is_valid_ether_addr(vf->default_lan_addr.addr)) {
+			f = i40e_add_filter(vsi, vf->default_lan_addr.addr,
+				       vf->port_vlan_id ? vf->port_vlan_id : -1,
+				       true, false);
+			if (!f)
+				dev_info(&pf->pdev->dev,
+					 "Could not add MAC filter %pM for VF %d\n",
+					vf->default_lan_addr.addr, vf->vf_id);
+		}
 		f = i40e_add_filter(vsi, brdcast,
 				    vf->port_vlan_id ? vf->port_vlan_id : -1,
 				    true, false);
@@ -1680,8 +1683,12 @@
 	spin_lock_bh(&vsi->mac_filter_list_lock);
 	/* delete addresses from the list */
 	for (i = 0; i < al->num_elements; i++)
-		i40e_del_filter(vsi, al->list[i].addr,
-				I40E_VLAN_ANY, true, false);
+		if (i40e_del_mac_all_vlan(vsi, al->list[i].addr, true, false)) {
+			ret = I40E_ERR_INVALID_MAC_ADDR;
+			spin_unlock_bh(&vsi->mac_filter_list_lock);
+			goto error_param;
+		}
+
 	spin_unlock_bh(&vsi->mac_filter_list_lock);
 
 	/* program the updated filter list */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index 47e9a90..39db70a 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -51,11 +51,7 @@
 					    struct i40e_tx_buffer *tx_buffer)
 {
 	if (tx_buffer->skb) {
-		if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
-			kfree(tx_buffer->raw_buf);
-		else
-			dev_kfree_skb_any(tx_buffer->skb);
-
+		dev_kfree_skb_any(tx_buffer->skb);
 		if (dma_unmap_len(tx_buffer, len))
 			dma_unmap_single(ring->dev,
 					 dma_unmap_addr(tx_buffer, dma),
@@ -67,6 +63,10 @@
 			       dma_unmap_len(tx_buffer, len),
 			       DMA_TO_DEVICE);
 	}
+
+	if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
+		kfree(tx_buffer->raw_buf);
+
 	tx_buffer->next_to_watch = NULL;
 	tx_buffer->skb = NULL;
 	dma_unmap_len_set(tx_buffer, len, 0);
@@ -245,16 +245,6 @@
 	tx_ring->q_vector->tx.total_bytes += total_bytes;
 	tx_ring->q_vector->tx.total_packets += total_packets;
 
-	/* check to see if there are any non-cache aligned descriptors
-	 * waiting to be written back, and kick the hardware to force
-	 * them to be written back in case of napi polling
-	 */
-	if (budget &&
-	    !((i & WB_STRIDE) == WB_STRIDE) &&
-	    !test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
-	    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
-		tx_ring->arm_wb = true;
-
 	netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev,
 						      tx_ring->queue_index),
 				  total_packets, total_bytes);
@@ -889,31 +879,12 @@
 }
 
 /**
- * i40e_rx_hash - returns the hash value from the Rx descriptor
- * @ring: descriptor ring
- * @rx_desc: specific descriptor
- **/
-static inline u32 i40e_rx_hash(struct i40e_ring *ring,
-			       union i40e_rx_desc *rx_desc)
-{
-	const __le64 rss_mask =
-		cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
-			    I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
-
-	if ((ring->netdev->features & NETIF_F_RXHASH) &&
-	    (rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask)
-		return le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
-	else
-		return 0;
-}
-
-/**
- * i40e_ptype_to_hash - get a hash type
+ * i40e_ptype_to_htype - get a hash type
  * @ptype: the ptype value from the descriptor
  *
  * Returns a hash type to be used by skb_set_hash
  **/
-static inline enum pkt_hash_types i40e_ptype_to_hash(u8 ptype)
+static inline enum pkt_hash_types i40e_ptype_to_htype(u8 ptype)
 {
 	struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype);
 
@@ -931,6 +902,30 @@
 }
 
 /**
+ * i40e_rx_hash - set the hash value in the skb
+ * @ring: descriptor ring
+ * @rx_desc: specific descriptor
+ **/
+static inline void i40e_rx_hash(struct i40e_ring *ring,
+				union i40e_rx_desc *rx_desc,
+				struct sk_buff *skb,
+				u8 rx_ptype)
+{
+	u32 hash;
+	const __le64 rss_mask  =
+		cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
+			    I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
+
+	if (ring->netdev->features & NETIF_F_RXHASH)
+		return;
+
+	if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
+		hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
+		skb_set_hash(skb, hash, i40e_ptype_to_htype(rx_ptype));
+	}
+}
+
+/**
  * i40e_clean_rx_irq_ps - Reclaim resources after receive; packet split
  * @rx_ring:  rx ring to clean
  * @budget:   how many cleans we're allowed
@@ -1071,8 +1066,8 @@
 			continue;
 		}
 
-		skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc),
-			     i40e_ptype_to_hash(rx_ptype));
+		i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype);
+
 		/* probably a little skewed due to removing CRC */
 		total_rx_bytes += skb->len;
 		total_rx_packets++;
@@ -1189,8 +1184,7 @@
 			continue;
 		}
 
-		skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc),
-			     i40e_ptype_to_hash(rx_ptype));
+		i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype);
 		/* probably a little skewed due to removing CRC */
 		total_rx_bytes += skb->len;
 		total_rx_packets++;
@@ -1770,6 +1764,9 @@
 	u32 td_tag = 0;
 	dma_addr_t dma;
 	u16 gso_segs;
+	u16 desc_count = 0;
+	bool tail_bump = true;
+	bool do_rs = false;
 
 	if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
 		td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
@@ -1810,6 +1807,8 @@
 
 			tx_desc++;
 			i++;
+			desc_count++;
+
 			if (i == tx_ring->count) {
 				tx_desc = I40E_TX_DESC(tx_ring, 0);
 				i = 0;
@@ -1829,6 +1828,8 @@
 
 		tx_desc++;
 		i++;
+		desc_count++;
+
 		if (i == tx_ring->count) {
 			tx_desc = I40E_TX_DESC(tx_ring, 0);
 			i = 0;
@@ -1843,35 +1844,7 @@
 		tx_bi = &tx_ring->tx_bi[i];
 	}
 
-	/* Place RS bit on last descriptor of any packet that spans across the
-	 * 4th descriptor (WB_STRIDE aka 0x3) in a 64B cacheline.
-	 */
 #define WB_STRIDE 0x3
-	if (((i & WB_STRIDE) != WB_STRIDE) &&
-	    (first <= &tx_ring->tx_bi[i]) &&
-	    (first >= &tx_ring->tx_bi[i & ~WB_STRIDE])) {
-		tx_desc->cmd_type_offset_bsz =
-			build_ctob(td_cmd, td_offset, size, td_tag) |
-			cpu_to_le64((u64)I40E_TX_DESC_CMD_EOP <<
-					 I40E_TXD_QW1_CMD_SHIFT);
-	} else {
-		tx_desc->cmd_type_offset_bsz =
-			build_ctob(td_cmd, td_offset, size, td_tag) |
-			cpu_to_le64((u64)I40E_TXD_CMD <<
-					 I40E_TXD_QW1_CMD_SHIFT);
-	}
-
-	netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev,
-						 tx_ring->queue_index),
-			     first->bytecount);
-
-	/* Force memory writes to complete before letting h/w
-	 * know there are new descriptors to fetch.  (Only
-	 * applicable for weak-ordered memory model archs,
-	 * such as IA-64).
-	 */
-	wmb();
-
 	/* set next_to_watch value indicating a packet is present */
 	first->next_to_watch = tx_desc;
 
@@ -1881,15 +1854,78 @@
 
 	tx_ring->next_to_use = i;
 
+	netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev,
+						 tx_ring->queue_index),
+						 first->bytecount);
 	i40evf_maybe_stop_tx(tx_ring, DESC_NEEDED);
+
+	/* Algorithm to optimize tail and RS bit setting:
+	 * if xmit_more is supported
+	 *	if xmit_more is true
+	 *		do not update tail and do not mark RS bit.
+	 *	if xmit_more is false and last xmit_more was false
+	 *		if every packet spanned less than 4 desc
+	 *			then set RS bit on 4th packet and update tail
+	 *			on every packet
+	 *		else
+	 *			update tail and set RS bit on every packet.
+	 *	if xmit_more is false and last_xmit_more was true
+	 *		update tail and set RS bit.
+	 * else (kernel < 3.18)
+	 *	if every packet spanned less than 4 desc
+	 *		then set RS bit on 4th packet and update tail
+	 *		on every packet
+	 *	else
+	 *		set RS bit on EOP for every packet and update tail
+	 *
+	 * Optimization: wmb to be issued only in case of tail update.
+	 * Also optimize the Descriptor WB path for RS bit with the same
+	 * algorithm.
+	 *
+	 * Note: If there are less than 4 packets
+	 * pending and interrupts were disabled the service task will
+	 * trigger a force WB.
+	 */
+	if (skb->xmit_more  &&
+	    !netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
+						    tx_ring->queue_index))) {
+		tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
+		tail_bump = false;
+	} else if (!skb->xmit_more &&
+		   !netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
+						       tx_ring->queue_index)) &&
+		   (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) &&
+		   (tx_ring->packet_stride < WB_STRIDE) &&
+		   (desc_count < WB_STRIDE)) {
+		tx_ring->packet_stride++;
+	} else {
+		tx_ring->packet_stride = 0;
+		tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
+		do_rs = true;
+	}
+	if (do_rs)
+		tx_ring->packet_stride = 0;
+
+	tx_desc->cmd_type_offset_bsz =
+			build_ctob(td_cmd, td_offset, size, td_tag) |
+			cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD :
+						  I40E_TX_DESC_CMD_EOP) <<
+						  I40E_TXD_QW1_CMD_SHIFT);
+
 	/* notify HW of packet */
-	if (!skb->xmit_more ||
-	    netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
-						   tx_ring->queue_index)))
-		writel(i, tx_ring->tail);
-	else
+	if (!tail_bump)
 		prefetchw(tx_desc + 1);
 
+	if (tail_bump) {
+		/* Force memory writes to complete before letting h/w
+		 * know there are new descriptors to fetch.  (Only
+		 * applicable for weak-ordered memory model archs,
+		 * such as IA-64).
+		 */
+		wmb();
+		writel(i, tx_ring->tail);
+	}
+
 	return;
 
 dma_error:
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
index ebc1bf7..9989768 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
@@ -267,6 +267,8 @@
 
 	bool ring_active;		/* is ring online or not */
 	bool arm_wb;		/* do something to arm write back */
+	u8 packet_stride;
+#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)
 
 	u16 flags;
 #define I40E_TXR_FLAGS_WB_ON_ITR	BIT(0)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index 4790437..2ac62ef 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -477,54 +477,30 @@
 
 	switch (nfc->flow_type) {
 	case TCP_V4_FLOW:
-		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
-		case 0:
-			hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
-			break;
-		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+		if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3))
 			hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
-			break;
-		default:
+		else
 			return -EINVAL;
-		}
 		break;
 	case TCP_V6_FLOW:
-		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
-		case 0:
-			hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
-			break;
-		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+		if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3))
 			hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
-			break;
-		default:
+		else
 			return -EINVAL;
-		}
 		break;
 	case UDP_V4_FLOW:
-		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
-		case 0:
-			hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
-				  BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
-			break;
-		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+		if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 			hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
 				 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
-			break;
-		default:
+		} else {
 			return -EINVAL;
 		}
 		break;
 	case UDP_V6_FLOW:
-		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
-		case 0:
-			hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
-				  BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
-			break;
-		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+		if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 			hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
 				 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
-			break;
-		default:
+		} else {
 			return -EINVAL;
 		}
 		break;
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 99d2cff..5f03ab3 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -1864,6 +1864,9 @@
 {
 	int i;
 
+	if (!adapter->tx_rings)
+		return;
+
 	for (i = 0; i < adapter->num_active_queues; i++)
 		if (adapter->tx_rings[i]->desc)
 			i40evf_free_tx_resources(adapter->tx_rings[i]);
@@ -1932,6 +1935,9 @@
 {
 	int i;
 
+	if (!adapter->rx_rings)
+		return;
+
 	for (i = 0; i < adapter->num_active_queues; i++)
 		if (adapter->rx_rings[i]->desc)
 			i40evf_free_rx_resources(adapter->rx_rings[i]);
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
index 32e620e..5de3f52 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
@@ -391,6 +391,7 @@
 	struct i40e_virtchnl_ether_addr_list *veal;
 	int len, i = 0, count = 0;
 	struct i40evf_mac_filter *f;
+	bool more = false;
 
 	if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
 		/* bail because we already have a command pending */
@@ -415,7 +416,9 @@
 		count = (I40EVF_MAX_AQ_BUF_SIZE -
 			 sizeof(struct i40e_virtchnl_ether_addr_list)) /
 			sizeof(struct i40e_virtchnl_ether_addr);
-		len = I40EVF_MAX_AQ_BUF_SIZE;
+		len = sizeof(struct i40e_virtchnl_ether_addr_list) +
+		      (count * sizeof(struct i40e_virtchnl_ether_addr));
+		more = true;
 	}
 
 	veal = kzalloc(len, GFP_ATOMIC);
@@ -431,7 +434,8 @@
 			f->add = false;
 		}
 	}
-	adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+	if (!more)
+		adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
 	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
 			   (u8 *)veal, len);
 	kfree(veal);
@@ -450,6 +454,7 @@
 	struct i40e_virtchnl_ether_addr_list *veal;
 	struct i40evf_mac_filter *f, *ftmp;
 	int len, i = 0, count = 0;
+	bool more = false;
 
 	if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
 		/* bail because we already have a command pending */
@@ -474,7 +479,9 @@
 		count = (I40EVF_MAX_AQ_BUF_SIZE -
 			 sizeof(struct i40e_virtchnl_ether_addr_list)) /
 			sizeof(struct i40e_virtchnl_ether_addr);
-		len = I40EVF_MAX_AQ_BUF_SIZE;
+		len = sizeof(struct i40e_virtchnl_ether_addr_list) +
+		      (count * sizeof(struct i40e_virtchnl_ether_addr));
+		more = true;
 	}
 	veal = kzalloc(len, GFP_ATOMIC);
 	if (!veal)
@@ -490,7 +497,8 @@
 			kfree(f);
 		}
 	}
-	adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+	if (!more)
+		adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
 	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
 			   (u8 *)veal, len);
 	kfree(veal);
@@ -509,6 +517,7 @@
 	struct i40e_virtchnl_vlan_filter_list *vvfl;
 	int len, i = 0, count = 0;
 	struct i40evf_vlan_filter *f;
+	bool more = false;
 
 	if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
 		/* bail because we already have a command pending */
@@ -534,7 +543,9 @@
 		count = (I40EVF_MAX_AQ_BUF_SIZE -
 			 sizeof(struct i40e_virtchnl_vlan_filter_list)) /
 			sizeof(u16);
-		len = I40EVF_MAX_AQ_BUF_SIZE;
+		len = sizeof(struct i40e_virtchnl_vlan_filter_list) +
+		      (count * sizeof(u16));
+		more = true;
 	}
 	vvfl = kzalloc(len, GFP_ATOMIC);
 	if (!vvfl)
@@ -549,7 +560,8 @@
 			f->add = false;
 		}
 	}
-	adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+	if (!more)
+		adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
 	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
 	kfree(vvfl);
 }
@@ -567,6 +579,7 @@
 	struct i40e_virtchnl_vlan_filter_list *vvfl;
 	struct i40evf_vlan_filter *f, *ftmp;
 	int len, i = 0, count = 0;
+	bool more = false;
 
 	if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
 		/* bail because we already have a command pending */
@@ -592,7 +605,9 @@
 		count = (I40EVF_MAX_AQ_BUF_SIZE -
 			 sizeof(struct i40e_virtchnl_vlan_filter_list)) /
 			sizeof(u16);
-		len = I40EVF_MAX_AQ_BUF_SIZE;
+		len = sizeof(struct i40e_virtchnl_vlan_filter_list) +
+		      (count * sizeof(u16));
+		more = true;
 	}
 	vvfl = kzalloc(len, GFP_ATOMIC);
 	if (!vvfl)
@@ -608,7 +623,8 @@
 			kfree(f);
 		}
 	}
-	adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+	if (!more)
+		adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
 	i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
 	kfree(vvfl);
 }
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index 7a73510..97bf0c3 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -294,6 +294,7 @@
 	case I210_I_PHY_ID:
 		phy->type		= e1000_phy_i210;
 		phy->ops.check_polarity	= igb_check_polarity_m88;
+		phy->ops.get_cfg_done	= igb_get_cfg_done_i210;
 		phy->ops.get_phy_info	= igb_get_phy_info_m88;
 		phy->ops.get_cable_length = igb_get_cable_length_m88_gen2;
 		phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580;
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c
index 65d9316..29f59c7 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.c
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.c
@@ -900,3 +900,30 @@
 	wr32(E1000_MDICNFG, mdicnfg);
 	return ret_val;
 }
+
+/**
+ *  igb_get_cfg_done_i210 - Read config done bit
+ *  @hw: pointer to the HW structure
+ *
+ *  Read the management control register for the config done bit for
+ *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
+ *  to read the config done bit, so an error is *ONLY* logged and returns
+ *  0.  If we were to return with error, EEPROM-less silicon
+ *  would not be able to be reset or change link.
+ **/
+s32 igb_get_cfg_done_i210(struct e1000_hw *hw)
+{
+	s32 timeout = PHY_CFG_TIMEOUT;
+	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
+
+	while (timeout) {
+		if (rd32(E1000_EEMNGCTL_I210) & mask)
+			break;
+		usleep_range(1000, 2000);
+		timeout--;
+	}
+	if (!timeout)
+		hw_dbg("MNG configuration cycle has not completed.\n");
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h
index 3442b63..eaa68a5 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.h
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.h
@@ -34,6 +34,7 @@
 s32 igb_init_nvm_params_i210(struct e1000_hw *hw);
 bool igb_get_flash_presence_i210(struct e1000_hw *hw);
 s32 igb_pll_workaround_i210(struct e1000_hw *hw);
+s32 igb_get_cfg_done_i210(struct e1000_hw *hw);
 
 #define E1000_STM_OPCODE		0xDB00
 #define E1000_EEPROM_FLASH_SIZE_WORD	0x11
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
index 23ec28f..afaa98d 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -77,6 +77,10 @@
 	s32 ret_val = 0;
 	u16 phy_id;
 
+	/* ensure PHY page selection to fix misconfigured i210 */
+	if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211))
+		phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0);
+
 	ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
 	if (ret_val)
 		goto out;
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index 4af2870..0fdcd4d 100644
--- a/drivers/net/ethernet/intel/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -66,6 +66,7 @@
 #define E1000_PBA      0x01000  /* Packet Buffer Allocation - RW */
 #define E1000_PBS      0x01008  /* Packet Buffer Size */
 #define E1000_EEMNGCTL 0x01010  /* MNG EEprom Control */
+#define E1000_EEMNGCTL_I210 0x12030  /* MNG EEprom Control */
 #define E1000_EEARBC_I210 0x12024  /* EEPROM Auto Read Bus Control */
 #define E1000_EEWR     0x0102C  /* EEPROM Write Register - RW */
 #define E1000_I2CCMD   0x01028  /* SFPI2C Command Register - RW */
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 1a2f1cc..e3cb93b 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -389,6 +389,8 @@
 	u16 link_speed;
 	u16 link_duplex;
 
+	u8 __iomem *io_addr; /* Mainly for iounmap use */
+
 	struct work_struct reset_task;
 	struct work_struct watchdog_task;
 	bool fc_autoneg;
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index ea7b098..fa3b4cb 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2294,9 +2294,11 @@
 	adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
 	err = -EIO;
-	hw->hw_addr = pci_iomap(pdev, 0, 0);
-	if (!hw->hw_addr)
+	adapter->io_addr = pci_iomap(pdev, 0, 0);
+	if (!adapter->io_addr)
 		goto err_ioremap;
+	/* hw->hw_addr can be altered, we'll use adapter->io_addr for unmap */
+	hw->hw_addr = adapter->io_addr;
 
 	netdev->netdev_ops = &igb_netdev_ops;
 	igb_set_ethtool_ops(netdev);
@@ -2656,7 +2658,7 @@
 #ifdef CONFIG_PCI_IOV
 	igb_disable_sriov(pdev);
 #endif
-	pci_iounmap(pdev, hw->hw_addr);
+	pci_iounmap(pdev, adapter->io_addr);
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
@@ -2823,7 +2825,7 @@
 
 	igb_clear_interrupt_scheme(adapter);
 
-	pci_iounmap(pdev, hw->hw_addr);
+	pci_iounmap(pdev, adapter->io_addr);
 	if (hw->flash_address)
 		iounmap(hw->flash_address);
 	pci_release_selected_regions(pdev,
@@ -2856,6 +2858,13 @@
 	if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211))
 		return;
 
+	/* Of the below we really only want the effect of getting
+	 * IGB_FLAG_HAS_MSIX set (if available), without which
+	 * igb_enable_sriov() has no effect.
+	 */
+	igb_set_interrupt_capability(adapter, true);
+	igb_reset_interrupt_capability(adapter);
+
 	pci_sriov_set_totalvfs(pdev, 7);
 	igb_enable_sriov(pdev, max_vfs);
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index aed8d02..cd9b284 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -2786,7 +2786,8 @@
 	ixgbe_for_each_ring(ring, q_vector->tx)
 		clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring);
 
-	if (!ixgbe_qv_lock_napi(q_vector))
+	/* Exit if we are called by netpoll or busy polling is active */
+	if ((budget <= 0) || !ixgbe_qv_lock_napi(q_vector))
 		return budget;
 
 	/* attempt to distribute budget to each queue fairly, but don't allow
diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index d74f5f4..07eabf7 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -900,10 +900,10 @@
 				DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
 				&lp->rx_dma_regs->dmasm);
 
-	korina_free_ring(dev);
-
 	napi_disable(&lp->napi);
 
+	korina_free_ring(dev);
+
 	if (korina_init(dev) < 0) {
 		printk(KERN_ERR "%s: cannot restart device\n", dev->name);
 		return;
@@ -1064,12 +1064,12 @@
 	tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
 	writel(tmp, &lp->rx_dma_regs->dmasm);
 
-	korina_free_ring(dev);
-
 	napi_disable(&lp->napi);
 
 	cancel_work_sync(&lp->restart_task);
 
+	korina_free_ring(dev);
+
 	free_irq(lp->rx_irq, dev);
 	free_irq(lp->tx_irq, dev);
 	free_irq(lp->ovr_irq, dev);
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index a4ac6fe..15056f0 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -226,7 +226,7 @@
 /* Various constants */
 
 /* Coalescing */
-#define MVNETA_TXDONE_COAL_PKTS		1
+#define MVNETA_TXDONE_COAL_PKTS		0	/* interrupt per packet */
 #define MVNETA_RX_COAL_PKTS		32
 #define MVNETA_RX_COAL_USEC		100
 
@@ -2446,7 +2446,7 @@
 	mvneta_port_enable(pp);
 
 	/* Enable polling on the port */
-	for_each_present_cpu(cpu) {
+	for_each_online_cpu(cpu) {
 		struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
 
 		napi_enable(&port->napi);
@@ -2472,7 +2472,7 @@
 
 	phy_stop(pp->phy_dev);
 
-	for_each_present_cpu(cpu) {
+	for_each_online_cpu(cpu) {
 		struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
 
 		napi_disable(&port->napi);
@@ -2902,13 +2902,11 @@
 static int mvneta_stop(struct net_device *dev)
 {
 	struct mvneta_port *pp = netdev_priv(dev);
-	int cpu;
 
 	mvneta_stop_dev(pp);
 	mvneta_mdio_remove(pp);
 	unregister_cpu_notifier(&pp->cpu_notifier);
-	for_each_present_cpu(cpu)
-		smp_call_function_single(cpu, mvneta_percpu_disable, pp, true);
+	on_each_cpu(mvneta_percpu_disable, pp, true);
 	free_percpu_irq(dev->irq, pp->ports);
 	mvneta_cleanup_rxqs(pp);
 	mvneta_cleanup_txqs(pp);
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index a4beccf..0e67145 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -772,6 +772,17 @@
 	u32 reserved8;
 };
 
+struct mvpp2_txq_pcpu_buf {
+	/* Transmitted SKB */
+	struct sk_buff *skb;
+
+	/* Physical address of transmitted buffer */
+	dma_addr_t phys;
+
+	/* Size transmitted */
+	size_t size;
+};
+
 /* Per-CPU Tx queue control */
 struct mvpp2_txq_pcpu {
 	int cpu;
@@ -787,11 +798,8 @@
 	/* Number of Tx DMA descriptors reserved for each CPU */
 	int reserved_num;
 
-	/* Array of transmitted skb */
-	struct sk_buff **tx_skb;
-
-	/* Array of transmitted buffers' physical addresses */
-	dma_addr_t *tx_buffs;
+	/* Infos about transmitted buffers */
+	struct mvpp2_txq_pcpu_buf *buffs;
 
 	/* Index of last TX DMA descriptor that was inserted */
 	int txq_put_index;
@@ -981,10 +989,11 @@
 			      struct sk_buff *skb,
 			      struct mvpp2_tx_desc *tx_desc)
 {
-	txq_pcpu->tx_skb[txq_pcpu->txq_put_index] = skb;
-	if (skb)
-		txq_pcpu->tx_buffs[txq_pcpu->txq_put_index] =
-							 tx_desc->buf_phys_addr;
+	struct mvpp2_txq_pcpu_buf *tx_buf =
+		txq_pcpu->buffs + txq_pcpu->txq_put_index;
+	tx_buf->skb = skb;
+	tx_buf->size = tx_desc->data_size;
+	tx_buf->phys = tx_desc->buf_phys_addr + tx_desc->packet_offset;
 	txq_pcpu->txq_put_index++;
 	if (txq_pcpu->txq_put_index == txq_pcpu->size)
 		txq_pcpu->txq_put_index = 0;
@@ -4403,17 +4412,16 @@
 	int i;
 
 	for (i = 0; i < num; i++) {
-		dma_addr_t buf_phys_addr =
-				    txq_pcpu->tx_buffs[txq_pcpu->txq_get_index];
-		struct sk_buff *skb = txq_pcpu->tx_skb[txq_pcpu->txq_get_index];
+		struct mvpp2_txq_pcpu_buf *tx_buf =
+			txq_pcpu->buffs + txq_pcpu->txq_get_index;
 
 		mvpp2_txq_inc_get(txq_pcpu);
 
-		dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
-				 skb_headlen(skb), DMA_TO_DEVICE);
-		if (!skb)
+		dma_unmap_single(port->dev->dev.parent, tx_buf->phys,
+				 tx_buf->size, DMA_TO_DEVICE);
+		if (!tx_buf->skb)
 			continue;
-		dev_kfree_skb_any(skb);
+		dev_kfree_skb_any(tx_buf->skb);
 	}
 }
 
@@ -4664,15 +4672,10 @@
 	for_each_present_cpu(cpu) {
 		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
 		txq_pcpu->size = txq->size;
-		txq_pcpu->tx_skb = kmalloc(txq_pcpu->size *
-					   sizeof(*txq_pcpu->tx_skb),
-					   GFP_KERNEL);
-		if (!txq_pcpu->tx_skb)
-			goto error;
-
-		txq_pcpu->tx_buffs = kmalloc(txq_pcpu->size *
-					     sizeof(dma_addr_t), GFP_KERNEL);
-		if (!txq_pcpu->tx_buffs)
+		txq_pcpu->buffs = kmalloc(txq_pcpu->size *
+					  sizeof(struct mvpp2_txq_pcpu_buf),
+					  GFP_KERNEL);
+		if (!txq_pcpu->buffs)
 			goto error;
 
 		txq_pcpu->count = 0;
@@ -4686,8 +4689,7 @@
 error:
 	for_each_present_cpu(cpu) {
 		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
-		kfree(txq_pcpu->tx_skb);
-		kfree(txq_pcpu->tx_buffs);
+		kfree(txq_pcpu->buffs);
 	}
 
 	dma_free_coherent(port->dev->dev.parent,
@@ -4706,8 +4708,7 @@
 
 	for_each_present_cpu(cpu) {
 		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
-		kfree(txq_pcpu->tx_skb);
-		kfree(txq_pcpu->tx_buffs);
+		kfree(txq_pcpu->buffs);
 	}
 
 	if (txq->descs)
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 5606a04..4b62aa1 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -5220,6 +5220,19 @@
 
 static void sky2_shutdown(struct pci_dev *pdev)
 {
+	struct sky2_hw *hw = pci_get_drvdata(pdev);
+	int port;
+
+	for (port = 0; port < hw->ports; port++) {
+		struct net_device *ndev = hw->dev[port];
+
+		rtnl_lock();
+		if (netif_running(ndev)) {
+			dev_close(ndev);
+			netif_device_detach(ndev);
+		}
+		rtnl_unlock();
+	}
 	sky2_suspend(&pdev->dev);
 	pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev));
 	pci_set_power_state(pdev, PCI_D3hot);
diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c
index 715de8a..e203d0c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/catas.c
+++ b/drivers/net/ethernet/mellanox/mlx4/catas.c
@@ -158,7 +158,7 @@
 	return -ETIMEDOUT;
 }
 
-static int mlx4_comm_internal_err(u32 slave_read)
+int mlx4_comm_internal_err(u32 slave_read)
 {
 	return (u32)COMM_CHAN_EVENT_INTERNAL_ERR ==
 		(slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0;
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c
index 3348e64..6eba580 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
@@ -101,13 +101,19 @@
 {
 	struct mlx4_cq *cq;
 
+	rcu_read_lock();
 	cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree,
 			       cqn & (dev->caps.num_cqs - 1));
+	rcu_read_unlock();
+
 	if (!cq) {
 		mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn);
 		return;
 	}
 
+	/* Acessing the CQ outside of rcu_read_lock is safe, because
+	 * the CQ is freed only after interrupt handling is completed.
+	 */
 	++cq->arm_sn;
 
 	cq->comp(cq);
@@ -118,23 +124,19 @@
 	struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
 	struct mlx4_cq *cq;
 
-	spin_lock(&cq_table->lock);
-
+	rcu_read_lock();
 	cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1));
-	if (cq)
-		atomic_inc(&cq->refcount);
-
-	spin_unlock(&cq_table->lock);
+	rcu_read_unlock();
 
 	if (!cq) {
-		mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn);
+		mlx4_dbg(dev, "Async event for bogus CQ %08x\n", cqn);
 		return;
 	}
 
+	/* Acessing the CQ outside of rcu_read_lock is safe, because
+	 * the CQ is freed only after interrupt handling is completed.
+	 */
 	cq->event(cq, event_type);
-
-	if (atomic_dec_and_test(&cq->refcount))
-		complete(&cq->free);
 }
 
 static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
@@ -301,9 +303,9 @@
 	if (err)
 		return err;
 
-	spin_lock_irq(&cq_table->lock);
+	spin_lock(&cq_table->lock);
 	err = radix_tree_insert(&cq_table->tree, cq->cqn, cq);
-	spin_unlock_irq(&cq_table->lock);
+	spin_unlock(&cq_table->lock);
 	if (err)
 		goto err_icm;
 
@@ -347,9 +349,9 @@
 	return 0;
 
 err_radix:
-	spin_lock_irq(&cq_table->lock);
+	spin_lock(&cq_table->lock);
 	radix_tree_delete(&cq_table->tree, cq->cqn);
-	spin_unlock_irq(&cq_table->lock);
+	spin_unlock(&cq_table->lock);
 
 err_icm:
 	mlx4_cq_free_icm(dev, cq->cqn);
@@ -368,15 +370,15 @@
 	if (err)
 		mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn);
 
+	spin_lock(&cq_table->lock);
+	radix_tree_delete(&cq_table->tree, cq->cqn);
+	spin_unlock(&cq_table->lock);
+
 	synchronize_irq(priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq);
 	if (priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq !=
 	    priv->eq_table.eq[MLX4_EQ_ASYNC].irq)
 		synchronize_irq(priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
 
-	spin_lock_irq(&cq_table->lock);
-	radix_tree_delete(&cq_table->tree, cq->cqn);
-	spin_unlock_irq(&cq_table->lock);
-
 	if (atomic_dec_and_test(&cq->refcount))
 		complete(&cq->free);
 	wait_for_completion(&cq->free);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 67e9633..2321914 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2282,7 +2282,7 @@
 	struct mlx4_en_dev *mdev = en_priv->mdev;
 	u64 mac_u64 = mlx4_mac_to_u64(mac);
 
-	if (!is_valid_ether_addr(mac))
+	if (is_multicast_ether_addr(mac))
 		return -EINVAL;
 
 	return mlx4_set_vf_mac(mdev->dev, en_priv->port, queue, mac_u64);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index e7a5000..82bf1b5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -439,8 +439,14 @@
 		ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn;
 
 		ring->stride = stride;
-		if (ring->stride <= TXBB_SIZE)
+		if (ring->stride <= TXBB_SIZE) {
+			/* Stamp first unused send wqe */
+			__be32 *ptr = (__be32 *)ring->buf;
+			__be32 stamp = cpu_to_be32(1 << STAMP_SHIFT);
+			*ptr = stamp;
+			/* Move pointer to start of rx section */
 			ring->buf += TXBB_SIZE;
+		}
 
 		ring->log_stride = ffs(ring->stride) - 1;
 		ring->buf_size = ring->size * ring->stride;
@@ -502,8 +508,11 @@
 		return;
 
 	for (ring = 0; ring < priv->rx_ring_num; ring++) {
-		if (mlx4_en_is_ring_empty(priv->rx_ring[ring]))
+		if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) {
+			local_bh_disable();
 			napi_reschedule(&priv->rx_cq[ring]->napi);
+			local_bh_enable();
+		}
 	}
 }
 
@@ -704,7 +713,7 @@
 
 	if (ipv6h->nexthdr == IPPROTO_FRAGMENT || ipv6h->nexthdr == IPPROTO_HOPOPTS)
 		return -1;
-	hw_checksum = csum_add(hw_checksum, (__force __wsum)(ipv6h->nexthdr << 8));
+	hw_checksum = csum_add(hw_checksum, (__force __wsum)htons(ipv6h->nexthdr));
 
 	csum_pseudo_hdr = csum_partial(&ipv6h->saddr,
 				       sizeof(ipv6h->saddr) + sizeof(ipv6h->daddr), 0);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 4421bf5..e4019a8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -400,7 +400,6 @@
 	u32 packets = 0;
 	u32 bytes = 0;
 	int factor = priv->cqe_factor;
-	u64 timestamp = 0;
 	int done = 0;
 	int budget = priv->tx_work_limit;
 	u32 last_nr_txbb;
@@ -440,9 +439,12 @@
 		new_index = be16_to_cpu(cqe->wqe_index) & size_mask;
 
 		do {
+			u64 timestamp = 0;
+
 			txbbs_skipped += last_nr_txbb;
 			ring_index = (ring_index + last_nr_txbb) & size_mask;
-			if (ring->tx_info[ring_index].ts_requested)
+
+			if (unlikely(ring->tx_info[ring_index].ts_requested))
 				timestamp = mlx4_en_get_cqe_ts(cqe);
 
 			/* free next descriptor */
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 603d1c3..ff77b8b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -542,8 +542,9 @@
 			break;
 
 		case MLX4_EVENT_TYPE_SRQ_LIMIT:
-			mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n",
-				 __func__);
+			mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n",
+				 __func__, be32_to_cpu(eqe->event.srq.srqn),
+				 eq->eqn);
 		case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
 			if (mlx4_is_master(dev)) {
 				/* forward only to slave owning the SRQ */
@@ -558,15 +559,19 @@
 						  eq->eqn, eq->cons_index, ret);
 					break;
 				}
-				mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
-					  __func__, slave,
-					  be32_to_cpu(eqe->event.srq.srqn),
-					  eqe->type, eqe->subtype);
+				if (eqe->type ==
+				    MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+					mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
+						  __func__, slave,
+						  be32_to_cpu(eqe->event.srq.srqn),
+						  eqe->type, eqe->subtype);
 
 				if (!ret && slave != dev->caps.function) {
-					mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
-						  __func__, eqe->type,
-						  eqe->subtype, slave);
+					if (eqe->type ==
+					    MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+						mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
+							  __func__, eqe->type,
+							  eqe->subtype, slave);
 					mlx4_slave_event(dev, slave, eqe);
 					break;
 				}
diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c
index 0472941..1a134e0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/intf.c
+++ b/drivers/net/ethernet/mellanox/mlx4/intf.c
@@ -218,6 +218,18 @@
 	struct mlx4_interface *intf;
 
 	mlx4_stop_catas_poll(dev);
+	if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION &&
+	    mlx4_is_slave(dev)) {
+		/* In mlx4_remove_one on a VF */
+		u32 slave_read =
+			swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read));
+
+		if (mlx4_comm_internal_err(slave_read)) {
+			mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n",
+				 __func__);
+			mlx4_enter_error_state(dev->persist);
+		}
+	}
 	mutex_lock(&intf_mutex);
 
 	list_for_each_entry(intf, &intf_list, list)
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index e1cf903..f5fdbd5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -1205,6 +1205,7 @@
 void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
 
 void mlx4_enter_error_state(struct mlx4_dev_persistent *persist);
+int mlx4_comm_internal_err(u32 slave_read);
 
 int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
 		    enum mlx4_port_type *type);
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index d314d96..d1fc7fa 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -2955,6 +2955,9 @@
 		put_res(dev, slave, srqn, RES_SRQ);
 		qp->srq = srq;
 	}
+
+	/* Save param3 for dynamic changes from VST back to VGT */
+	qp->param3 = qpc->param3;
 	put_res(dev, slave, rcqn, RES_CQ);
 	put_res(dev, slave, mtt_base, RES_MTT);
 	res_end_move(dev, slave, RES_QP, qpn);
@@ -3747,7 +3750,6 @@
 	int qpn = vhcr->in_modifier & 0x7fffff;
 	struct res_qp *qp;
 	u8 orig_sched_queue;
-	__be32	orig_param3 = qpc->param3;
 	u8 orig_vlan_control = qpc->pri_path.vlan_control;
 	u8 orig_fvl_rx = qpc->pri_path.fvl_rx;
 	u8 orig_pri_path_fl = qpc->pri_path.fl;
@@ -3789,7 +3791,6 @@
 	 */
 	if (!err) {
 		qp->sched_queue = orig_sched_queue;
-		qp->param3	= orig_param3;
 		qp->vlan_control = orig_vlan_control;
 		qp->fvl_rx	=  orig_fvl_rx;
 		qp->pri_path_fl = orig_pri_path_fl;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 037fc4c..cc19906 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -143,13 +143,14 @@
 	return cmd->cmd_buf + (idx << cmd->log_stride);
 }
 
-static u8 xor8_buf(void *buf, int len)
+static u8 xor8_buf(void *buf, size_t offset, int len)
 {
 	u8 *ptr = buf;
 	u8 sum = 0;
 	int i;
+	int end = len + offset;
 
-	for (i = 0; i < len; i++)
+	for (i = offset; i < end; i++)
 		sum ^= ptr[i];
 
 	return sum;
@@ -157,41 +158,49 @@
 
 static int verify_block_sig(struct mlx5_cmd_prot_block *block)
 {
-	if (xor8_buf(block->rsvd0, sizeof(*block) - sizeof(block->data) - 1) != 0xff)
+	size_t rsvd0_off = offsetof(struct mlx5_cmd_prot_block, rsvd0);
+	int xor_len = sizeof(*block) - sizeof(block->data) - 1;
+
+	if (xor8_buf(block, rsvd0_off, xor_len) != 0xff)
 		return -EINVAL;
 
-	if (xor8_buf(block, sizeof(*block)) != 0xff)
+	if (xor8_buf(block, 0, sizeof(*block)) != 0xff)
 		return -EINVAL;
 
 	return 0;
 }
 
-static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token,
-			   int csum)
+static void calc_block_sig(struct mlx5_cmd_prot_block *block)
 {
-	block->token = token;
-	if (csum) {
-		block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) -
-					    sizeof(block->data) - 2);
-		block->sig = ~xor8_buf(block, sizeof(*block) - 1);
-	}
+	int ctrl_xor_len = sizeof(*block) - sizeof(block->data) - 2;
+	size_t rsvd0_off = offsetof(struct mlx5_cmd_prot_block, rsvd0);
+
+	block->ctrl_sig = ~xor8_buf(block, rsvd0_off, ctrl_xor_len);
+	block->sig = ~xor8_buf(block, 0, sizeof(*block) - 1);
 }
 
-static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token, int csum)
+static void calc_chain_sig(struct mlx5_cmd_msg *msg)
 {
 	struct mlx5_cmd_mailbox *next = msg->next;
+	int size = msg->len;
+	int blen = size - min_t(int, sizeof(msg->first.data), size);
+	int n = (blen + MLX5_CMD_DATA_BLOCK_SIZE - 1)
+		/ MLX5_CMD_DATA_BLOCK_SIZE;
+	int i = 0;
 
-	while (next) {
-		calc_block_sig(next->buf, token, csum);
+	for (i = 0; i < n && next; i++)  {
+		calc_block_sig(next->buf);
 		next = next->next;
 	}
 }
 
 static void set_signature(struct mlx5_cmd_work_ent *ent, int csum)
 {
-	ent->lay->sig = ~xor8_buf(ent->lay, sizeof(*ent->lay));
-	calc_chain_sig(ent->in, ent->token, csum);
-	calc_chain_sig(ent->out, ent->token, csum);
+	ent->lay->sig = ~xor8_buf(ent->lay, 0,  sizeof(*ent->lay));
+	if (csum) {
+		calc_chain_sig(ent->in);
+		calc_chain_sig(ent->out);
+	}
 }
 
 static void poll_timeout(struct mlx5_cmd_work_ent *ent)
@@ -222,12 +231,17 @@
 	struct mlx5_cmd_mailbox *next = ent->out->next;
 	int err;
 	u8 sig;
+	int size = ent->out->len;
+	int blen = size - min_t(int, sizeof(ent->out->first.data), size);
+	int n = (blen + MLX5_CMD_DATA_BLOCK_SIZE - 1)
+		/ MLX5_CMD_DATA_BLOCK_SIZE;
+	int i = 0;
 
-	sig = xor8_buf(ent->lay, sizeof(*ent->lay));
+	sig = xor8_buf(ent->lay, 0, sizeof(*ent->lay));
 	if (sig != 0xff)
 		return -EINVAL;
 
-	while (next) {
+	for (i = 0; i < n && next; i++) {
 		err = verify_block_sig(next->buf);
 		if (err)
 			return err;
@@ -641,7 +655,6 @@
 		spin_unlock_irqrestore(&cmd->alloc_lock, flags);
 	}
 
-	ent->token = alloc_token(cmd);
 	cmd->ent_arr[ent->idx] = ent;
 	lay = get_inst(cmd, ent->idx);
 	ent->lay = lay;
@@ -755,7 +768,8 @@
 static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
 			   struct mlx5_cmd_msg *out, void *uout, int uout_size,
 			   mlx5_cmd_cbk_t callback,
-			   void *context, int page_queue, u8 *status)
+			   void *context, int page_queue, u8 *status,
+			   u8 token)
 {
 	struct mlx5_cmd *cmd = &dev->cmd;
 	struct mlx5_cmd_work_ent *ent;
@@ -772,6 +786,8 @@
 	if (IS_ERR(ent))
 		return PTR_ERR(ent);
 
+	ent->token = token;
+
 	if (!callback)
 		init_completion(&ent->done);
 
@@ -844,7 +860,8 @@
 	.write	= dbg_write,
 };
 
-static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size)
+static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size,
+			    u8 token)
 {
 	struct mlx5_cmd_prot_block *block;
 	struct mlx5_cmd_mailbox *next;
@@ -870,6 +887,7 @@
 		memcpy(block->data, from, copy);
 		from += copy;
 		size -= copy;
+		block->token = token;
 		next = next->next;
 	}
 
@@ -939,7 +957,8 @@
 }
 
 static struct mlx5_cmd_msg *mlx5_alloc_cmd_msg(struct mlx5_core_dev *dev,
-					       gfp_t flags, int size)
+					       gfp_t flags, int size,
+					       u8 token)
 {
 	struct mlx5_cmd_mailbox *tmp, *head = NULL;
 	struct mlx5_cmd_prot_block *block;
@@ -968,6 +987,7 @@
 		tmp->next = head;
 		block->next = cpu_to_be64(tmp->next ? tmp->next->dma : 0);
 		block->block_num = cpu_to_be32(n - i - 1);
+		block->token = token;
 		head = tmp;
 	}
 	msg->next = head;
@@ -1351,7 +1371,7 @@
 	}
 
 	if (IS_ERR(msg))
-		msg = mlx5_alloc_cmd_msg(dev, gfp, in_size);
+		msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0);
 
 	return msg;
 }
@@ -1376,6 +1396,7 @@
 	int err;
 	u8 status = 0;
 	u32 drv_synd;
+	u8 token;
 
 	if (pci_channel_offline(dev->pdev) ||
 	    dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
@@ -1394,20 +1415,22 @@
 		return err;
 	}
 
-	err = mlx5_copy_to_msg(inb, in, in_size);
+	token = alloc_token(&dev->cmd);
+
+	err = mlx5_copy_to_msg(inb, in, in_size, token);
 	if (err) {
 		mlx5_core_warn(dev, "err %d\n", err);
 		goto out_in;
 	}
 
-	outb = mlx5_alloc_cmd_msg(dev, gfp, out_size);
+	outb = mlx5_alloc_cmd_msg(dev, gfp, out_size, token);
 	if (IS_ERR(outb)) {
 		err = PTR_ERR(outb);
 		goto out_in;
 	}
 
 	err = mlx5_cmd_invoke(dev, inb, outb, out, out_size, callback, context,
-			      pages_queue, &status);
+			      pages_queue, &status, token);
 	if (err)
 		goto out_out;
 
@@ -1475,7 +1498,7 @@
 	INIT_LIST_HEAD(&cmd->cache.med.head);
 
 	for (i = 0; i < NUM_LONG_LISTS; i++) {
-		msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE);
+		msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE, 0);
 		if (IS_ERR(msg)) {
 			err = PTR_ERR(msg);
 			goto ex_err;
@@ -1485,7 +1508,7 @@
 	}
 
 	for (i = 0; i < NUM_MED_LISTS; i++) {
-		msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE);
+		msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE, 0);
 		if (IS_ERR(msg)) {
 			err = PTR_ERR(msg);
 			goto ex_err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 2e022e9..7cc9df7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -399,6 +399,9 @@
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 
+	if (!MLX5_CAP_GEN(priv->mdev, cq_moderation))
+		return -ENOTSUPP;
+
 	coal->rx_coalesce_usecs       = priv->params.rx_cq_moderation_usec;
 	coal->rx_max_coalesced_frames = priv->params.rx_cq_moderation_pkts;
 	coal->tx_coalesce_usecs       = priv->params.tx_cq_moderation_usec;
@@ -416,11 +419,18 @@
 	int tc;
 	int i;
 
+	if (!MLX5_CAP_GEN(mdev, cq_moderation))
+		return -ENOTSUPP;
+
+	mutex_lock(&priv->state_lock);
 	priv->params.tx_cq_moderation_usec = coal->tx_coalesce_usecs;
 	priv->params.tx_cq_moderation_pkts = coal->tx_max_coalesced_frames;
 	priv->params.rx_cq_moderation_usec = coal->rx_coalesce_usecs;
 	priv->params.rx_cq_moderation_pkts = coal->rx_max_coalesced_frames;
 
+	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
+		goto out;
+
 	for (i = 0; i < priv->params.num_channels; ++i) {
 		c = priv->channel[i];
 
@@ -436,6 +446,8 @@
 					       coal->rx_max_coalesced_frames);
 	}
 
+out:
+	mutex_unlock(&priv->state_lock);
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 1203d89..90e876e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -863,12 +863,10 @@
 	if (err)
 		goto err_destroy_cq;
 
-	err = mlx5_core_modify_cq_moderation(mdev, &cq->mcq,
-					     moderation_usecs,
-					     moderation_frames);
-	if (err)
-		goto err_destroy_cq;
-
+	if (MLX5_CAP_GEN(mdev, cq_moderation))
+		mlx5_core_modify_cq_moderation(mdev, &cq->mcq,
+					       moderation_usecs,
+					       moderation_frames);
 	return 0;
 
 err_destroy_cq:
@@ -1372,7 +1370,7 @@
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 	struct mlx5_core_dev *mdev = priv->mdev;
-	int hw_mtu;
+	u16 hw_mtu;
 	int err;
 
 	err = mlx5_set_port_mtu(mdev, MLX5E_SW2HW_MTU(netdev->mtu), 1);
@@ -1891,22 +1889,27 @@
 	return err;
 }
 
+#define MXL5_HW_MIN_MTU 64
+#define MXL5E_MIN_MTU (MXL5_HW_MIN_MTU + ETH_FCS_LEN)
+
 static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 	struct mlx5_core_dev *mdev = priv->mdev;
 	bool was_opened;
-	int max_mtu;
+	u16 max_mtu;
+	u16 min_mtu;
 	int err = 0;
 
 	mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
 
 	max_mtu = MLX5E_HW2SW_MTU(max_mtu);
+	min_mtu = MLX5E_HW2SW_MTU(MXL5E_MIN_MTU);
 
-	if (new_mtu > max_mtu) {
+	if (new_mtu > max_mtu || new_mtu < min_mtu) {
 		netdev_err(netdev,
-			   "%s: Bad MTU (%d) > (%d) Max\n",
-			   __func__, new_mtu, max_mtu);
+			   "%s: Bad MTU (%d), valid range is: [%d..%d]\n",
+			   __func__, new_mtu, min_mtu, max_mtu);
 		return -EINVAL;
 	}
 
@@ -1958,6 +1961,8 @@
 	}
 	if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
 		mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
+	if (!MLX5_CAP_GEN(mdev, cq_moderation))
+		mlx5_core_warn(mdev, "CQ modiration is not supported\n");
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index cf00985..e9408f5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -197,6 +197,10 @@
 	if (lro_num_seg > 1) {
 		mlx5e_lro_update_hdr(skb, cqe);
 		skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg);
+		/* Subtract one since we already counted this as one
+		 * "regular" packet in mlx5e_complete_rx_cqe()
+		 */
+		rq->stats.packets += lro_num_seg - 1;
 		rq->stats.lro_packets++;
 		rq->stats.lro_bytes += cqe_bcnt;
 	}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 6cf6d93..f5c1f4a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -85,7 +85,7 @@
 	[2] = {
 		.mask		= MLX5_PROF_MASK_QP_SIZE |
 				  MLX5_PROF_MASK_MR_CACHE,
-		.log_max_qp	= 17,
+		.log_max_qp	= 18,
 		.mr_cache[0]	= {
 			.size	= 500,
 			.limit	= 250
@@ -153,8 +153,9 @@
 	},
 };
 
-#define FW_INIT_TIMEOUT_MILI	2000
-#define FW_INIT_WAIT_MS		2
+#define FW_INIT_TIMEOUT_MILI		2000
+#define FW_INIT_WAIT_MS			2
+#define FW_PRE_INIT_TIMEOUT_MILI	10000
 
 static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)
 {
@@ -432,6 +433,13 @@
 	MLX5_SET(cmd_hca_cap, set_hca_cap, pkey_table_size,
 		 to_fw_pkey_sz(128));
 
+	/* Check log_max_qp from HCA caps to set in current profile */
+	if (MLX5_CAP_GEN_MAX(dev, log_max_qp) < profile[prof_sel].log_max_qp) {
+		mlx5_core_warn(dev, "log_max_qp value in current profile is %d, changing it to HCA capability limit (%d)\n",
+			       profile[prof_sel].log_max_qp,
+			       MLX5_CAP_GEN_MAX(dev, log_max_qp));
+		profile[prof_sel].log_max_qp = MLX5_CAP_GEN_MAX(dev, log_max_qp);
+	}
 	if (prof->mask & MLX5_PROF_MASK_QP_SIZE)
 		MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_qp,
 			 prof->log_max_qp);
@@ -505,7 +513,6 @@
 	struct mlx5_priv *priv  = &mdev->priv;
 	struct msix_entry *msix = priv->msix_arr;
 	int irq                 = msix[i + MLX5_EQ_VEC_COMP_BASE].vector;
-	int numa_node           = priv->numa_node;
 	int err;
 
 	if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {
@@ -513,7 +520,7 @@
 		return -ENOMEM;
 	}
 
-	cpumask_set_cpu(cpumask_local_spread(i, numa_node),
+	cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
 			priv->irq_info[i].mask);
 
 	err = irq_set_affinity_hint(irq, priv->irq_info[i].mask);
@@ -928,6 +935,15 @@
 	 */
 	dev->state = MLX5_DEVICE_STATE_UP;
 
+	/* wait for firmware to accept initialization segments configurations
+	 */
+	err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI);
+	if (err) {
+		dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n",
+			FW_PRE_INIT_TIMEOUT_MILI);
+		goto out;
+	}
+
 	err = mlx5_cmd_init(dev);
 	if (err) {
 		dev_err(&pdev->dev, "Failed initializing command interface, aborting\n");
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index a87e773..53a793b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -246,8 +246,8 @@
 }
 EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
 
-static void mlx5_query_port_mtu(struct mlx5_core_dev *dev, int *admin_mtu,
-				int *max_mtu, int *oper_mtu, u8 port)
+static void mlx5_query_port_mtu(struct mlx5_core_dev *dev, u16 *admin_mtu,
+				u16 *max_mtu, u16 *oper_mtu, u8 port)
 {
 	u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
 	u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
@@ -267,7 +267,7 @@
 		*admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
 }
 
-int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu, u8 port)
+int mlx5_set_port_mtu(struct mlx5_core_dev *dev, u16 mtu, u8 port)
 {
 	u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
 	u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
@@ -282,14 +282,14 @@
 }
 EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
 
-void mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu,
+void mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, u16 *max_mtu,
 			     u8 port)
 {
 	mlx5_query_port_mtu(dev, NULL, max_mtu, NULL, port);
 }
 EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
 
-void mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu,
+void mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, u16 *oper_mtu,
 			      u8 port)
 {
 	mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu, port);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h
index 142f33d..a0fbe00 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h
@@ -206,21 +206,21 @@
 /* pci_eqe_cmd_token
  * Command completion event - token
  */
-MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16);
+MLXSW_ITEM32(pci, eqe, cmd_token, 0x00, 16, 16);
 
 /* pci_eqe_cmd_status
  * Command completion event - status
  */
-MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8);
+MLXSW_ITEM32(pci, eqe, cmd_status, 0x00, 0, 8);
 
 /* pci_eqe_cmd_out_param_h
  * Command completion event - output parameter - higher part
  */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32);
+MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x04, 0, 32);
 
 /* pci_eqe_cmd_out_param_l
  * Command completion event - output parameter - lower part
  */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32);
+MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x08, 0, 32);
 
 #endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 3be4a23..cb165c2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -390,6 +390,7 @@
 			dev_kfree_skb_any(skb_orig);
 			return NETDEV_TX_OK;
 		}
+		dev_consume_skb_any(skb_orig);
 	}
 
 	if (eth_skb_pad(skb)) {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index d85960c..fb2d9a8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -313,6 +313,7 @@
 			dev_kfree_skb_any(skb_orig);
 			return NETDEV_TX_OK;
 		}
+		dev_consume_skb_any(skb_orig);
 	}
 	mlxsw_sx_txhdr_construct(skb, &tx_info);
 	len = skb->len;
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index 50d5604..e0993eb 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -2223,8 +2223,6 @@
 	return IRQ_NONE;
 }
 
-#ifdef CONFIG_PCI_MSI
-
 static irqreturn_t vxge_tx_msix_handle(int irq, void *dev_id)
 {
 	struct vxge_fifo *fifo = (struct vxge_fifo *)dev_id;
@@ -2442,16 +2440,13 @@
 	if (vdev->config.intr_type == MSI_X)
 		pci_disable_msix(vdev->pdev);
 }
-#endif
 
 static void vxge_rem_isr(struct vxgedev *vdev)
 {
-#ifdef CONFIG_PCI_MSI
-	if (vdev->config.intr_type == MSI_X) {
+	if (IS_ENABLED(CONFIG_PCI_MSI) &&
+	    vdev->config.intr_type == MSI_X) {
 		vxge_rem_msix_isr(vdev);
-	} else
-#endif
-	if (vdev->config.intr_type == INTA) {
+	} else if (vdev->config.intr_type == INTA) {
 			synchronize_irq(vdev->pdev->irq);
 			free_irq(vdev->pdev->irq, vdev);
 	}
@@ -2460,11 +2455,10 @@
 static int vxge_add_isr(struct vxgedev *vdev)
 {
 	int ret = 0;
-#ifdef CONFIG_PCI_MSI
 	int vp_idx = 0, intr_idx = 0, intr_cnt = 0, msix_idx = 0, irq_req = 0;
 	int pci_fun = PCI_FUNC(vdev->pdev->devfn);
 
-	if (vdev->config.intr_type == MSI_X)
+	if (IS_ENABLED(CONFIG_PCI_MSI) && vdev->config.intr_type == MSI_X)
 		ret = vxge_enable_msix(vdev);
 
 	if (ret) {
@@ -2475,7 +2469,7 @@
 		vdev->config.intr_type = INTA;
 	}
 
-	if (vdev->config.intr_type == MSI_X) {
+	if (IS_ENABLED(CONFIG_PCI_MSI) && vdev->config.intr_type == MSI_X) {
 		for (intr_idx = 0;
 		     intr_idx < (vdev->no_of_vpath *
 			VXGE_HW_VPATH_MSIX_ACTIVE); intr_idx++) {
@@ -2576,9 +2570,8 @@
 		vdev->vxge_entries[intr_cnt].in_use = 1;
 		vdev->vxge_entries[intr_cnt].arg = &vdev->vpaths[0];
 	}
-INTA_MODE:
-#endif
 
+INTA_MODE:
 	if (vdev->config.intr_type == INTA) {
 		snprintf(vdev->desc[0], VXGE_INTR_STRLEN,
 			"%s:vxge:INTA", vdev->ndev->name);
@@ -3889,12 +3882,12 @@
 	if (max_mac_vpath > VXGE_MAX_MAC_ADDR_COUNT)
 		max_mac_vpath = VXGE_MAX_MAC_ADDR_COUNT;
 
-#ifndef CONFIG_PCI_MSI
-	vxge_debug_init(VXGE_ERR,
-		"%s: This Kernel does not support "
-		"MSI-X. Defaulting to INTA", VXGE_DRIVER_NAME);
-	*intr_type = INTA;
-#endif
+	if (!IS_ENABLED(CONFIG_PCI_MSI)) {
+		vxge_debug_init(VXGE_ERR,
+			"%s: This Kernel does not support "
+			"MSI-X. Defaulting to INTA", VXGE_DRIVER_NAME);
+		*intr_type = INTA;
+	}
 
 	/* Configure whether MSI-X or IRQL. */
 	switch (*intr_type) {
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index 3dd548a..40365cb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -794,13 +794,12 @@
 			 * in a bitmap and increasing the chain consumer only
 			 * for the first successive completed entries.
 			 */
-			bitmap_set(p_spq->p_comp_bitmap, pos, SPQ_RING_SIZE);
+			__set_bit(pos, p_spq->p_comp_bitmap);
 
 			while (test_bit(p_spq->comp_bitmap_idx,
 					p_spq->p_comp_bitmap)) {
-				bitmap_clear(p_spq->p_comp_bitmap,
-					     p_spq->comp_bitmap_idx,
-					     SPQ_RING_SIZE);
+				__clear_bit(p_spq->comp_bitmap_idx,
+					    p_spq->p_comp_bitmap);
 				p_spq->comp_bitmap_idx++;
 				qed_chain_return_produced(&p_spq->chain);
 			}
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 467d416..585e90f 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -171,6 +171,49 @@
 	.get_mdio_data = ravb_get_mdio_data,
 };
 
+/* Free TX skb function for AVB-IP */
+static int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only)
+{
+	struct ravb_private *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &priv->stats[q];
+	struct ravb_tx_desc *desc;
+	int free_num = 0;
+	int entry;
+	u32 size;
+
+	for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) {
+		bool txed;
+
+		entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] *
+					     NUM_TX_DESC);
+		desc = &priv->tx_ring[q][entry];
+		txed = desc->die_dt == DT_FEMPTY;
+		if (free_txed_only && !txed)
+			break;
+		/* Descriptor type must be checked before all other reads */
+		dma_rmb();
+		size = le16_to_cpu(desc->ds_tagl) & TX_DS;
+		/* Free the original skb. */
+		if (priv->tx_skb[q][entry / NUM_TX_DESC]) {
+			dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
+					 size, DMA_TO_DEVICE);
+			/* Last packet descriptor? */
+			if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) {
+				entry /= NUM_TX_DESC;
+				dev_kfree_skb_any(priv->tx_skb[q][entry]);
+				priv->tx_skb[q][entry] = NULL;
+				if (txed)
+					stats->tx_packets++;
+			}
+			free_num++;
+		}
+		if (txed)
+			stats->tx_bytes += size;
+		desc->die_dt = DT_EEMPTY;
+	}
+	return free_num;
+}
+
 /* Free skb's and DMA buffers for Ethernet AVB */
 static void ravb_ring_free(struct net_device *ndev, int q)
 {
@@ -178,6 +221,34 @@
 	int ring_size;
 	int i;
 
+	if (priv->rx_ring[q]) {
+		for (i = 0; i < priv->num_rx_ring[q]; i++) {
+			struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
+
+			if (!dma_mapping_error(ndev->dev.parent,
+					       le32_to_cpu(desc->dptr)))
+				dma_unmap_single(ndev->dev.parent,
+						 le32_to_cpu(desc->dptr),
+						 PKT_BUF_SZ,
+						 DMA_FROM_DEVICE);
+		}
+		ring_size = sizeof(struct ravb_ex_rx_desc) *
+			    (priv->num_rx_ring[q] + 1);
+		dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
+				  priv->rx_desc_dma[q]);
+		priv->rx_ring[q] = NULL;
+	}
+
+	if (priv->tx_ring[q]) {
+		ravb_tx_free(ndev, q, false);
+
+		ring_size = sizeof(struct ravb_tx_desc) *
+			    (priv->num_tx_ring[q] * NUM_TX_DESC + 1);
+		dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q],
+				  priv->tx_desc_dma[q]);
+		priv->tx_ring[q] = NULL;
+	}
+
 	/* Free RX skb ringbuffer */
 	if (priv->rx_skb[q]) {
 		for (i = 0; i < priv->num_rx_ring[q]; i++)
@@ -186,33 +257,15 @@
 	kfree(priv->rx_skb[q]);
 	priv->rx_skb[q] = NULL;
 
-	/* Free TX skb ringbuffer */
-	if (priv->tx_skb[q]) {
-		for (i = 0; i < priv->num_tx_ring[q]; i++)
-			dev_kfree_skb(priv->tx_skb[q][i]);
-	}
-	kfree(priv->tx_skb[q]);
-	priv->tx_skb[q] = NULL;
-
 	/* Free aligned TX buffers */
 	kfree(priv->tx_align[q]);
 	priv->tx_align[q] = NULL;
 
-	if (priv->rx_ring[q]) {
-		ring_size = sizeof(struct ravb_ex_rx_desc) *
-			    (priv->num_rx_ring[q] + 1);
-		dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
-				  priv->rx_desc_dma[q]);
-		priv->rx_ring[q] = NULL;
-	}
-
-	if (priv->tx_ring[q]) {
-		ring_size = sizeof(struct ravb_tx_desc) *
-			    (priv->num_tx_ring[q] * NUM_TX_DESC + 1);
-		dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q],
-				  priv->tx_desc_dma[q]);
-		priv->tx_ring[q] = NULL;
-	}
+	/* Free TX skb ringbuffer.
+	 * SKBs are freed by ravb_tx_free() call above.
+	 */
+	kfree(priv->tx_skb[q]);
+	priv->tx_skb[q] = NULL;
 }
 
 /* Format skb and descriptor buffer for Ethernet AVB */
@@ -420,44 +473,6 @@
 	return 0;
 }
 
-/* Free TX skb function for AVB-IP */
-static int ravb_tx_free(struct net_device *ndev, int q)
-{
-	struct ravb_private *priv = netdev_priv(ndev);
-	struct net_device_stats *stats = &priv->stats[q];
-	struct ravb_tx_desc *desc;
-	int free_num = 0;
-	int entry;
-	u32 size;
-
-	for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) {
-		entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] *
-					     NUM_TX_DESC);
-		desc = &priv->tx_ring[q][entry];
-		if (desc->die_dt != DT_FEMPTY)
-			break;
-		/* Descriptor type must be checked before all other reads */
-		dma_rmb();
-		size = le16_to_cpu(desc->ds_tagl) & TX_DS;
-		/* Free the original skb. */
-		if (priv->tx_skb[q][entry / NUM_TX_DESC]) {
-			dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
-					 size, DMA_TO_DEVICE);
-			/* Last packet descriptor? */
-			if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) {
-				entry /= NUM_TX_DESC;
-				dev_kfree_skb_any(priv->tx_skb[q][entry]);
-				priv->tx_skb[q][entry] = NULL;
-				stats->tx_packets++;
-			}
-			free_num++;
-		}
-		stats->tx_bytes += size;
-		desc->die_dt = DT_EEMPTY;
-	}
-	return free_num;
-}
-
 static void ravb_get_tx_tstamp(struct net_device *ndev)
 {
 	struct ravb_private *priv = netdev_priv(ndev);
@@ -797,7 +812,7 @@
 			spin_lock_irqsave(&priv->lock, flags);
 			/* Clear TX interrupt */
 			ravb_write(ndev, ~mask, TIS);
-			ravb_tx_free(ndev, q);
+			ravb_tx_free(ndev, q, true);
 			netif_wake_subqueue(ndev, q);
 			mmiowb();
 			spin_unlock_irqrestore(&priv->lock, flags);
@@ -1330,6 +1345,19 @@
 	buffer = PTR_ALIGN(priv->tx_align[q], DPTR_ALIGN) +
 		 entry / NUM_TX_DESC * DPTR_ALIGN;
 	len = PTR_ALIGN(skb->data, DPTR_ALIGN) - skb->data;
+	/* Zero length DMA descriptors are problematic as they seem to
+	 * terminate DMA transfers. Avoid them by simply using a length of
+	 * DPTR_ALIGN (4) when skb data is aligned to DPTR_ALIGN.
+	 *
+	 * As skb is guaranteed to have at least ETH_ZLEN (60) bytes of
+	 * data by the call to skb_put_padto() above this is safe with
+	 * respect to both the length of the first DMA descriptor (len)
+	 * overflowing the available data and the length of the second DMA
+	 * descriptor (skb->len - len) being negative.
+	 */
+	if (len == 0)
+		len = DPTR_ALIGN;
+
 	memcpy(buffer, skb->data, len);
 	dma_addr = dma_map_single(ndev->dev.parent, buffer, len, DMA_TO_DEVICE);
 	if (dma_mapping_error(ndev->dev.parent, dma_addr))
@@ -1380,7 +1408,8 @@
 
 	priv->cur_tx[q] += NUM_TX_DESC;
 	if (priv->cur_tx[q] - priv->dirty_tx[q] >
-	    (priv->num_tx_ring[q] - 1) * NUM_TX_DESC && !ravb_tx_free(ndev, q))
+	    (priv->num_tx_ring[q] - 1) * NUM_TX_DESC &&
+	    !ravb_tx_free(ndev, q, true))
 		netif_stop_subqueue(ndev, q);
 
 exit:
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 36fc942..480f3da 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -832,7 +832,7 @@
 
 	.ecsr_value	= ECSR_ICD,
 	.ecsipr_value	= ECSIPR_ICDIP,
-	.eesipr_value	= 0xff7f009f,
+	.eesipr_value	= 0xe77f009f,
 
 	.tx_check	= EESR_TC1 | EESR_FTC,
 	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index 2b34622..3920c3eb 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -4475,7 +4475,7 @@
 		fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
 		err = rocker_port_fib_ipv4(rocker_port, trans,
 					   htonl(fib4->dst), fib4->dst_len,
-					   &fib4->fi, fib4->tb_id, 0);
+					   fib4->fi, fib4->tb_id, 0);
 		break;
 	case SWITCHDEV_OBJ_ID_PORT_FDB:
 		err = rocker_port_fdb_add(rocker_port, trans,
@@ -4547,7 +4547,7 @@
 		fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
 		err = rocker_port_fib_ipv4(rocker_port, NULL,
 					   htonl(fib4->dst), fib4->dst_len,
-					   &fib4->fi, fib4->tb_id,
+					   fib4->fi, fib4->tb_id,
 					   ROCKER_OP_FLAG_REMOVE);
 		break;
 	case SWITCHDEV_OBJ_ID_PORT_FDB:
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index e6a084a..cbe9a33 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -619,6 +619,17 @@
 	return rc;
 }
 
+static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
+{
+	struct efx_channel *channel;
+	struct efx_tx_queue *tx_queue;
+
+	/* All our existing PIO buffers went away */
+	efx_for_each_channel(channel, efx)
+		efx_for_each_channel_tx_queue(tx_queue, channel)
+			tx_queue->piobuf = NULL;
+}
+
 #else /* !EFX_USE_PIO */
 
 static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
@@ -635,6 +646,10 @@
 {
 }
 
+static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
+{
+}
+
 #endif /* EFX_USE_PIO */
 
 static void efx_ef10_remove(struct efx_nic *efx)
@@ -1018,6 +1033,7 @@
 	nic_data->must_realloc_vis = true;
 	nic_data->must_restore_filters = true;
 	nic_data->must_restore_piobufs = true;
+	efx_ef10_forget_old_piobufs(efx);
 	nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID;
 
 	/* Driver-created vswitches and vports must be re-created */
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index d790cb8..8e832ba 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -2796,6 +2796,11 @@
 	.timer_period_max =  1 << FRF_AB_TC_TIMER_VAL_WIDTH,
 	.offload_features = NETIF_F_IP_CSUM,
 	.mcdi_max_ver = -1,
+#ifdef CONFIG_SFC_SRIOV
+	.vswitching_probe = efx_port_dummy_op_int,
+	.vswitching_restore = efx_port_dummy_op_int,
+	.vswitching_remove = efx_port_dummy_op_void,
+#endif
 };
 
 const struct efx_nic_type falcon_b0_nic_type = {
@@ -2897,4 +2902,9 @@
 	.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
 	.mcdi_max_ver = -1,
 	.max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS,
+#ifdef CONFIG_SFC_SRIOV
+	.vswitching_probe = efx_port_dummy_op_int,
+	.vswitching_restore = efx_port_dummy_op_int,
+	.vswitching_remove = efx_port_dummy_op_void,
+#endif
 };
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 0e2fc1a..23a0388 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -540,7 +540,7 @@
 #define smc_special_lock(lock, flags)		spin_lock_irqsave(lock, flags)
 #define smc_special_unlock(lock, flags) 	spin_unlock_irqrestore(lock, flags)
 #else
-#define smc_special_trylock(lock, flags)	(flags == flags)
+#define smc_special_trylock(lock, flags)	((void)flags, true)
 #define smc_special_lock(lock, flags)   	do { flags = 0; } while (0)
 #define smc_special_unlock(lock, flags)	do { flags = 0; } while (0)
 #endif
@@ -2269,6 +2269,13 @@
 	if (pd) {
 		memcpy(&lp->cfg, pd, sizeof(lp->cfg));
 		lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
+
+		if (!SMC_8BIT(lp) && !SMC_16BIT(lp)) {
+			dev_err(&pdev->dev,
+				"at least one of 8-bit or 16-bit access support is required.\n");
+			ret = -ENXIO;
+			goto out_free_netdev;
+		}
 	}
 
 #if IS_BUILTIN(CONFIG_OF)
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index a3c129e..29df046 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -37,6 +37,27 @@
 #include <linux/smc91x.h>
 
 /*
+ * Any 16-bit access is performed with two 8-bit accesses if the hardware
+ * can't do it directly. Most registers are 16-bit so those are mandatory.
+ */
+#define SMC_outw_b(x, a, r)						\
+	do {								\
+		unsigned int __val16 = (x);				\
+		unsigned int __reg = (r);				\
+		SMC_outb(__val16, a, __reg);				\
+		SMC_outb(__val16 >> 8, a, __reg + (1 << SMC_IO_SHIFT));	\
+	} while (0)
+
+#define SMC_inw_b(a, r)							\
+	({								\
+		unsigned int __val16;					\
+		unsigned int __reg = r;					\
+		__val16  = SMC_inb(a, __reg);				\
+		__val16 |= SMC_inb(a, __reg + (1 << SMC_IO_SHIFT)) << 8; \
+		__val16;						\
+	})
+
+/*
  * Define your architecture specific bus configuration parameters here.
  */
 
@@ -55,10 +76,30 @@
 #define SMC_IO_SHIFT		(lp->io_shift)
 
 #define SMC_inb(a, r)		readb((a) + (r))
-#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_inw(a, r)							\
+	({								\
+		unsigned int __smc_r = r;				\
+		SMC_16BIT(lp) ? readw((a) + __smc_r) :			\
+		SMC_8BIT(lp) ? SMC_inw_b(a, __smc_r) :			\
+		({ BUG(); 0; });					\
+	})
+
 #define SMC_inl(a, r)		readl((a) + (r))
 #define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)						\
+	do {								\
+		unsigned int __v = v, __smc_r = r;			\
+		if (SMC_16BIT(lp))					\
+			__SMC_outw(__v, a, __smc_r);			\
+		else if (SMC_8BIT(lp))					\
+			SMC_outw_b(__v, a, __smc_r);			\
+		else							\
+			BUG();						\
+	} while (0)
+
 #define SMC_outl(v, a, r)	writel(v, (a) + (r))
+#define SMC_insb(a, r, p, l)	readsb((a) + (r), p, l)
+#define SMC_outsb(a, r, p, l)	writesb((a) + (r), p, l)
 #define SMC_insw(a, r, p, l)	readsw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
 #define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
@@ -66,7 +107,7 @@
 #define SMC_IRQ_FLAGS		(-1)	/* from resource */
 
 /* We actually can't write halfwords properly if not word aligned */
-static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
+static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 {
 	if ((machine_is_mainstone() || machine_is_stargate2() ||
 	     machine_is_pxa_idp()) && reg & 2) {
@@ -405,24 +446,8 @@
 
 #if ! SMC_CAN_USE_16BIT
 
-/*
- * Any 16-bit access is performed with two 8-bit accesses if the hardware
- * can't do it directly. Most registers are 16-bit so those are mandatory.
- */
-#define SMC_outw(x, ioaddr, reg)					\
-	do {								\
-		unsigned int __val16 = (x);				\
-		SMC_outb( __val16, ioaddr, reg );			\
-		SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\
-	} while (0)
-#define SMC_inw(ioaddr, reg)						\
-	({								\
-		unsigned int __val16;					\
-		__val16 =  SMC_inb( ioaddr, reg );			\
-		__val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \
-		__val16;						\
-	})
-
+#define SMC_outw(x, ioaddr, reg)	SMC_outw_b(x, ioaddr, reg)
+#define SMC_inw(ioaddr, reg)		SMC_inw_b(ioaddr, reg)
 #define SMC_insw(a, r, p, l)		BUG()
 #define SMC_outsw(a, r, p, l)		BUG()
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a5b869e..4b100ef 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2939,12 +2939,6 @@
 	spin_lock_init(&priv->lock);
 	spin_lock_init(&priv->tx_lock);
 
-	ret = register_netdev(ndev);
-	if (ret) {
-		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
-		goto error_netdev_register;
-	}
-
 	/* If a specific clk_csr value is passed from the platform
 	 * this means that the CSR Clock Range selection cannot be
 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
@@ -2969,11 +2963,21 @@
 		}
 	}
 
-	return 0;
+	ret = register_netdev(ndev);
+	if (ret) {
+		netdev_err(priv->dev, "%s: ERROR %i registering the device\n",
+			   __func__, ret);
+		goto error_netdev_register;
+	}
 
-error_mdio_register:
-	unregister_netdev(ndev);
+	return ret;
+
 error_netdev_register:
+	if (priv->pcs != STMMAC_PCS_RGMII &&
+	    priv->pcs != STMMAC_PCS_TBI &&
+	    priv->pcs != STMMAC_PCS_RTBI)
+		stmmac_mdio_unregister(ndev);
+error_mdio_register:
 	netif_napi_del(&priv->napi);
 error_hw_init:
 	clk_disable_unprepare(priv->pclk);
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index 77d26fe..7e8bce4 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -549,7 +549,8 @@
 
 static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	int queue, len;
+	int queue;
+	unsigned int len;
 	struct cpmac_desc *desc;
 	struct cpmac_priv *priv = netdev_priv(dev);
 
@@ -559,7 +560,7 @@
 	if (unlikely(skb_padto(skb, ETH_ZLEN)))
 		return NETDEV_TX_OK;
 
-	len = max(skb->len, ETH_ZLEN);
+	len = max_t(unsigned int, skb->len, ETH_ZLEN);
 	queue = skb_get_queue_mapping(skb);
 	netif_stop_subqueue(dev, queue);
 
@@ -1236,7 +1237,7 @@
 		goto fail_alloc;
 	}
 
-#warning FIXME: unhardcode gpio&reset bits
+	/* FIXME: unhardcode gpio&reset bits */
 	ar7_gpio_disable(26);
 	ar7_gpio_disable(27);
 	ar7_device_reset(AR7_RESET_BIT_CPMAC_LO);
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index cf468c8..4cb8b85 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -100,6 +100,14 @@
 /* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
 #define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT)
 
+#ifdef __BIG_ENDIAN
+#define xemaclite_readl		ioread32be
+#define xemaclite_writel	iowrite32be
+#else
+#define xemaclite_readl		ioread32
+#define xemaclite_writel	iowrite32
+#endif
+
 /**
  * struct net_local - Our private per device data
  * @ndev:		instance of the network device
@@ -158,15 +166,15 @@
 	u32 reg_data;
 
 	/* Enable the Tx interrupts for the first Buffer */
-	reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
-	__raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
-		     drvdata->base_addr + XEL_TSR_OFFSET);
+	reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+	xemaclite_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
+			 drvdata->base_addr + XEL_TSR_OFFSET);
 
 	/* Enable the Rx interrupts for the first buffer */
-	__raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
+	xemaclite_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
 
 	/* Enable the Global Interrupt Enable */
-	__raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
+	xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
 }
 
 /**
@@ -181,17 +189,17 @@
 	u32 reg_data;
 
 	/* Disable the Global Interrupt Enable */
-	__raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
+	xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
 
 	/* Disable the Tx interrupts for the first buffer */
-	reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
-	__raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
-		     drvdata->base_addr + XEL_TSR_OFFSET);
+	reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+	xemaclite_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
+			 drvdata->base_addr + XEL_TSR_OFFSET);
 
 	/* Disable the Rx interrupts for the first buffer */
-	reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
-	__raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
-		     drvdata->base_addr + XEL_RSR_OFFSET);
+	reg_data = xemaclite_readl(drvdata->base_addr + XEL_RSR_OFFSET);
+	xemaclite_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
+			 drvdata->base_addr + XEL_RSR_OFFSET);
 }
 
 /**
@@ -323,7 +331,7 @@
 		byte_count = ETH_FRAME_LEN;
 
 	/* Check if the expected buffer is available */
-	reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+	reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
 	if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
 	     XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
 
@@ -336,7 +344,7 @@
 
 		addr = (void __iomem __force *)((u32 __force)addr ^
 						 XEL_BUFFER_OFFSET);
-		reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+		reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
 
 		if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
 		     XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
@@ -347,16 +355,16 @@
 	/* Write the frame to the buffer */
 	xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
 
-	__raw_writel((byte_count & XEL_TPLR_LENGTH_MASK),
-		     addr + XEL_TPLR_OFFSET);
+	xemaclite_writel((byte_count & XEL_TPLR_LENGTH_MASK),
+			 addr + XEL_TPLR_OFFSET);
 
 	/* Update the Tx Status Register to indicate that there is a
 	 * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
 	 * is used by the interrupt handler to check whether a frame
 	 * has been transmitted */
-	reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+	reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
 	reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
-	__raw_writel(reg_data, addr + XEL_TSR_OFFSET);
+	xemaclite_writel(reg_data, addr + XEL_TSR_OFFSET);
 
 	return 0;
 }
@@ -371,7 +379,7 @@
  *
  * Return:	Total number of bytes received
  */
-static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
+static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
 {
 	void __iomem *addr;
 	u16 length, proto_type;
@@ -381,7 +389,7 @@
 	addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use);
 
 	/* Verify which buffer has valid data */
-	reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
+	reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
 
 	if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
 		if (drvdata->rx_ping_pong != 0)
@@ -398,27 +406,28 @@
 			return 0;	/* No data was available */
 
 		/* Verify that buffer has valid data */
-		reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
+		reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
 		if ((reg_data & XEL_RSR_RECV_DONE_MASK) !=
 		     XEL_RSR_RECV_DONE_MASK)
 			return 0;	/* No data was available */
 	}
 
 	/* Get the protocol type of the ethernet frame that arrived */
-	proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET +
+	proto_type = ((ntohl(xemaclite_readl(addr + XEL_HEADER_OFFSET +
 			XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
 			XEL_RPLR_LENGTH_MASK);
 
 	/* Check if received ethernet frame is a raw ethernet frame
 	 * or an IP packet or an ARP packet */
-	if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
+	if (proto_type > ETH_DATA_LEN) {
 
 		if (proto_type == ETH_P_IP) {
-			length = ((ntohl(__raw_readl(addr +
+			length = ((ntohl(xemaclite_readl(addr +
 					XEL_HEADER_IP_LENGTH_OFFSET +
 					XEL_RXBUFF_OFFSET)) >>
 					XEL_HEADER_SHIFT) &
 					XEL_RPLR_LENGTH_MASK);
+			length = min_t(u16, length, ETH_DATA_LEN);
 			length += ETH_HLEN + ETH_FCS_LEN;
 
 		} else if (proto_type == ETH_P_ARP)
@@ -431,14 +440,17 @@
 		/* Use the length in the frame, plus the header and trailer */
 		length = proto_type + ETH_HLEN + ETH_FCS_LEN;
 
+	if (WARN_ON(length > maxlen))
+		length = maxlen;
+
 	/* Read from the EmacLite device */
 	xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
 				data, length);
 
 	/* Acknowledge the frame */
-	reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
+	reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
 	reg_data &= ~XEL_RSR_RECV_DONE_MASK;
-	__raw_writel(reg_data, addr + XEL_RSR_OFFSET);
+	xemaclite_writel(reg_data, addr + XEL_RSR_OFFSET);
 
 	return length;
 }
@@ -465,14 +477,14 @@
 
 	xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
 
-	__raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
+	xemaclite_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
 
 	/* Update the MAC address in the EmacLite */
-	reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
-	__raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
+	reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
+	xemaclite_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
 
 	/* Wait for EmacLite to finish with the MAC address update */
-	while ((__raw_readl(addr + XEL_TSR_OFFSET) &
+	while ((xemaclite_readl(addr + XEL_TSR_OFFSET) &
 		XEL_TSR_PROG_MAC_ADDR) != 0)
 		;
 }
@@ -605,7 +617,7 @@
 
 	skb_reserve(skb, 2);
 
-	len = xemaclite_recv_data(lp, (u8 *) skb->data);
+	len = xemaclite_recv_data(lp, (u8 *) skb->data, len);
 
 	if (!len) {
 		dev->stats.rx_errors++;
@@ -642,32 +654,32 @@
 	u32 tx_status;
 
 	/* Check if there is Rx Data available */
-	if ((__raw_readl(base_addr + XEL_RSR_OFFSET) &
+	if ((xemaclite_readl(base_addr + XEL_RSR_OFFSET) &
 			 XEL_RSR_RECV_DONE_MASK) ||
-	    (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
+	    (xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
 			 & XEL_RSR_RECV_DONE_MASK))
 
 		xemaclite_rx_handler(dev);
 
 	/* Check if the Transmission for the first buffer is completed */
-	tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET);
+	tx_status = xemaclite_readl(base_addr + XEL_TSR_OFFSET);
 	if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
 		(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
 
 		tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
-		__raw_writel(tx_status, base_addr + XEL_TSR_OFFSET);
+		xemaclite_writel(tx_status, base_addr + XEL_TSR_OFFSET);
 
 		tx_complete = true;
 	}
 
 	/* Check if the Transmission for the second buffer is completed */
-	tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+	tx_status = xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
 	if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
 		(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
 
 		tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
-		__raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
-			     XEL_TSR_OFFSET);
+		xemaclite_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
+				 XEL_TSR_OFFSET);
 
 		tx_complete = true;
 	}
@@ -700,7 +712,7 @@
 	/* wait for the MDIO interface to not be busy or timeout
 	   after some time.
 	*/
-	while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
+	while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
 			XEL_MDIOCTRL_MDIOSTS_MASK) {
 		if (time_before_eq(end, jiffies)) {
 			WARN_ON(1);
@@ -736,17 +748,17 @@
 	 * MDIO Address register. Set the Status bit in the MDIO Control
 	 * register to start a MDIO read transaction.
 	 */
-	ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
-	__raw_writel(XEL_MDIOADDR_OP_MASK |
-		     ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
-		     lp->base_addr + XEL_MDIOADDR_OFFSET);
-	__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
-		     lp->base_addr + XEL_MDIOCTRL_OFFSET);
+	ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+	xemaclite_writel(XEL_MDIOADDR_OP_MASK |
+			 ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+			 lp->base_addr + XEL_MDIOADDR_OFFSET);
+	xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+			 lp->base_addr + XEL_MDIOCTRL_OFFSET);
 
 	if (xemaclite_mdio_wait(lp))
 		return -ETIMEDOUT;
 
-	rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET);
+	rc = xemaclite_readl(lp->base_addr + XEL_MDIORD_OFFSET);
 
 	dev_dbg(&lp->ndev->dev,
 		"xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
@@ -783,13 +795,13 @@
 	 * Data register. Finally, set the Status bit in the MDIO Control
 	 * register to start a MDIO write transaction.
 	 */
-	ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
-	__raw_writel(~XEL_MDIOADDR_OP_MASK &
-		     ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
-		     lp->base_addr + XEL_MDIOADDR_OFFSET);
-	__raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
-	__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
-		     lp->base_addr + XEL_MDIOCTRL_OFFSET);
+	ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+	xemaclite_writel(~XEL_MDIOADDR_OP_MASK &
+			 ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+			 lp->base_addr + XEL_MDIOADDR_OFFSET);
+	xemaclite_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
+	xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+			 lp->base_addr + XEL_MDIOCTRL_OFFSET);
 
 	return 0;
 }
@@ -836,8 +848,8 @@
 	/* Enable the MDIO bus by asserting the enable bit in MDIO Control
 	 * register.
 	 */
-	__raw_writel(XEL_MDIOCTRL_MDIOEN_MASK,
-		     lp->base_addr + XEL_MDIOCTRL_OFFSET);
+	xemaclite_writel(XEL_MDIOCTRL_MDIOEN_MASK,
+			 lp->base_addr + XEL_MDIOCTRL_OFFSET);
 
 	bus = mdiobus_alloc();
 	if (!bus) {
@@ -1141,8 +1153,8 @@
 		dev_warn(dev, "No MAC address found\n");
 
 	/* Clear the Tx CSR's in case this is a restart */
-	__raw_writel(0, lp->base_addr + XEL_TSR_OFFSET);
-	__raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+	xemaclite_writel(0, lp->base_addr + XEL_TSR_OFFSET);
+	xemaclite_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
 
 	/* Set the MAC address in the EmacLite device */
 	xemaclite_update_address(lp, ndev->dev_addr);
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 58efdec..f0961cb 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -310,15 +310,15 @@
 
 	/* Need Geneve and inner Ethernet header to be present */
 	if (unlikely(!pskb_may_pull(skb, GENEVE_BASE_HLEN)))
-		goto error;
+		goto drop;
 
 	/* Return packets with reserved bits set */
 	geneveh = geneve_hdr(skb);
 	if (unlikely(geneveh->ver != GENEVE_VER))
-		goto error;
+		goto drop;
 
 	if (unlikely(geneveh->proto_type != htons(ETH_P_TEB)))
-		goto error;
+		goto drop;
 
 	opts_len = geneveh->opt_len * 4;
 	if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len,
@@ -336,10 +336,6 @@
 	/* Consume bad packet */
 	kfree_skb(skb);
 	return 0;
-
-error:
-	/* Let the UDP layer deal with the skb */
-	return 1;
 }
 
 static struct socket *geneve_create_sock(struct net *net, bool ipv6,
@@ -444,7 +440,7 @@
 
 	skb_gro_pull(skb, gh_len);
 	skb_gro_postpull_rcsum(skb, gh, gh_len);
-	pp = ptype->callbacks.gro_receive(head, skb);
+	pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
 
 out_unlock:
 	rcu_read_unlock();
@@ -819,7 +815,6 @@
 	struct geneve_dev *geneve = netdev_priv(dev);
 	struct geneve_sock *gs4 = geneve->sock4;
 	struct rtable *rt = NULL;
-	const struct iphdr *iip; /* interior IP header */
 	int err = -EINVAL;
 	struct flowi4 fl4;
 	__u8 tos, ttl;
@@ -846,8 +841,6 @@
 	sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
 	skb_reset_mac_header(skb);
 
-	iip = ip_hdr(skb);
-
 	if (info) {
 		const struct ip_tunnel_key *key = &info->key;
 		u8 *opts = NULL;
@@ -863,7 +856,7 @@
 		if (unlikely(err))
 			goto err;
 
-		tos = ip_tunnel_ecn_encap(key->tos, iip, skb);
+		tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
 		ttl = key->ttl;
 		df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
 	} else {
@@ -873,7 +866,7 @@
 		if (unlikely(err))
 			goto err;
 
-		tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb);
+		tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb);
 		ttl = geneve->ttl;
 		if (!ttl && IN_MULTICAST(ntohl(fl4.daddr)))
 			ttl = 1;
@@ -907,7 +900,6 @@
 	struct geneve_dev *geneve = netdev_priv(dev);
 	struct geneve_sock *gs6 = geneve->sock6;
 	struct dst_entry *dst = NULL;
-	const struct iphdr *iip; /* interior IP header */
 	int err = -EINVAL;
 	struct flowi6 fl6;
 	__u8 prio, ttl;
@@ -931,8 +923,6 @@
 	sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
 	skb_reset_mac_header(skb);
 
-	iip = ip_hdr(skb);
-
 	if (info) {
 		const struct ip_tunnel_key *key = &info->key;
 		u8 *opts = NULL;
@@ -949,7 +939,7 @@
 		if (unlikely(err))
 			goto err;
 
-		prio = ip_tunnel_ecn_encap(key->tos, iip, skb);
+		prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
 		ttl = key->ttl;
 	} else {
 		udp_csum = false;
@@ -958,7 +948,7 @@
 		if (unlikely(err))
 			goto err;
 
-		prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, iip, skb);
+		prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, ip_hdr(skb), skb);
 		ttl = geneve->ttl;
 		if (!ttl && ipv6_addr_is_multicast(&fl6.daddr))
 			ttl = 1;
@@ -998,6 +988,17 @@
 	return geneve_xmit_skb(skb, dev, info);
 }
 
+static int geneve_change_mtu(struct net_device *dev, int new_mtu)
+{
+	/* GENEVE overhead is not fixed, so we can't enforce a more
+	 * precise max MTU.
+	 */
+	if (new_mtu < 68 || new_mtu > IP_MAX_MTU)
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}
+
 static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 {
 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
@@ -1042,7 +1043,7 @@
 	.ndo_stop		= geneve_stop,
 	.ndo_start_xmit		= geneve_xmit,
 	.ndo_get_stats64	= ip_tunnel_get_stats64,
-	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_change_mtu		= geneve_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_fill_metadata_dst	= geneve_fill_metadata_dst,
@@ -1349,11 +1350,21 @@
 
 	err = geneve_configure(net, dev, &geneve_remote_unspec,
 			       0, 0, 0, htons(dst_port), true);
-	if (err) {
-		free_netdev(dev);
-		return ERR_PTR(err);
-	}
+	if (err)
+		goto err;
+
+	/* openvswitch users expect packet sizes to be unrestricted,
+	 * so set the largest MTU we can.
+	 */
+	err = geneve_change_mtu(dev, IP_MAX_MTU);
+	if (err)
+		goto err;
+
 	return dev;
+
+ err:
+	free_netdev(dev);
+	return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(geneve_dev_create_fb);
 
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 85828f1..0758d08 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -648,8 +648,8 @@
 {
 	/* Finish setting up the DEVICE info. */
 	dev->mtu             = AX_MTU;
-	dev->hard_header_len = 0;
-	dev->addr_len        = 0;
+	dev->hard_header_len = AX25_MAX_HEADER_LEN;
+	dev->addr_len        = AX25_ADDR_LEN;
 	dev->type            = ARPHRD_AX25;
 	dev->tx_queue_len    = 10;
 	dev->header_ops      = &ax25_header_ops;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 409b48e..c8a7802 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -40,6 +40,8 @@
 
 #include "hyperv_net.h"
 
+/* Restrict GSO size to account for NVGRE */
+#define NETVSC_GSO_MAX_SIZE	62768
 
 #define RING_SIZE_MIN 64
 static int ring_size = 128;
@@ -195,65 +197,6 @@
 	return ppi;
 }
 
-union sub_key {
-	u64 k;
-	struct {
-		u8 pad[3];
-		u8 kb;
-		u32 ka;
-	};
-};
-
-/* Toeplitz hash function
- * data: network byte order
- * return: host byte order
- */
-static u32 comp_hash(u8 *key, int klen, void *data, int dlen)
-{
-	union sub_key subk;
-	int k_next = 4;
-	u8 dt;
-	int i, j;
-	u32 ret = 0;
-
-	subk.k = 0;
-	subk.ka = ntohl(*(u32 *)key);
-
-	for (i = 0; i < dlen; i++) {
-		subk.kb = key[k_next];
-		k_next = (k_next + 1) % klen;
-		dt = ((u8 *)data)[i];
-		for (j = 0; j < 8; j++) {
-			if (dt & 0x80)
-				ret ^= subk.ka;
-			dt <<= 1;
-			subk.k <<= 1;
-		}
-	}
-
-	return ret;
-}
-
-static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb)
-{
-	struct flow_keys flow;
-	int data_len;
-
-	if (!skb_flow_dissect_flow_keys(skb, &flow, 0) ||
-	    !(flow.basic.n_proto == htons(ETH_P_IP) ||
-	      flow.basic.n_proto == htons(ETH_P_IPV6)))
-		return false;
-
-	if (flow.basic.ip_proto == IPPROTO_TCP)
-		data_len = 12;
-	else
-		data_len = 8;
-
-	*hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len);
-
-	return true;
-}
-
 static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
 			void *accel_priv, select_queue_fallback_t fallback)
 {
@@ -266,11 +209,9 @@
 	if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1)
 		return 0;
 
-	if (netvsc_set_hash(&hash, skb)) {
-		q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] %
-			ndev->real_num_tx_queues;
-		skb_set_hash(skb, hash, PKT_HASH_TYPE_L3);
-	}
+	hash = skb_get_hash(skb);
+	q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] %
+		ndev->real_num_tx_queues;
 
 	return q_idx;
 }
@@ -1139,6 +1080,7 @@
 	nvdev = hv_get_drvdata(dev);
 	netif_set_real_num_tx_queues(net, nvdev->num_chn);
 	netif_set_real_num_rx_queues(net, nvdev->num_chn);
+	netif_set_gso_max_size(net, NETVSC_GSO_MAX_SIZE);
 
 	ret = register_netdev(net);
 	if (ret != 0) {
diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c
index 199a94a..3a429f1 100644
--- a/drivers/net/ieee802154/atusb.c
+++ b/drivers/net/ieee802154/atusb.c
@@ -110,13 +110,26 @@
 {
 	struct usb_device *usb_dev = atusb->usb_dev;
 	int ret;
+	uint8_t *buffer;
 	uint8_t value;
 
+	buffer = kmalloc(1, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
 	dev_dbg(&usb_dev->dev, "atusb: reg = 0x%x\n", reg);
 	ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
 				ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
-				0, reg, &value, 1, 1000);
-	return ret >= 0 ? value : ret;
+				0, reg, buffer, 1, 1000);
+
+	if (ret >= 0) {
+		value = buffer[0];
+		kfree(buffer);
+		return value;
+	} else {
+		kfree(buffer);
+		return ret;
+	}
 }
 
 static int atusb_write_subreg(struct atusb *atusb, uint8_t reg, uint8_t mask,
@@ -517,9 +530,13 @@
 static int atusb_get_and_show_revision(struct atusb *atusb)
 {
 	struct usb_device *usb_dev = atusb->usb_dev;
-	unsigned char buffer[3];
+	unsigned char *buffer;
 	int ret;
 
+	buffer = kmalloc(3, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
 	/* Get a couple of the ATMega Firmware values */
 	ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
 				ATUSB_ID, ATUSB_REQ_FROM_DEV, 0, 0,
@@ -535,15 +552,20 @@
 		dev_info(&usb_dev->dev, "Please update to version 0.2 or newer");
 	}
 
+	kfree(buffer);
 	return ret;
 }
 
 static int atusb_get_and_show_build(struct atusb *atusb)
 {
 	struct usb_device *usb_dev = atusb->usb_dev;
-	char build[ATUSB_BUILD_SIZE + 1];
+	char *build;
 	int ret;
 
+	build = kmalloc(ATUSB_BUILD_SIZE + 1, GFP_KERNEL);
+	if (!build)
+		return -ENOMEM;
+
 	ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
 				ATUSB_BUILD, ATUSB_REQ_FROM_DEV, 0, 0,
 				build, ATUSB_BUILD_SIZE, 1000);
@@ -552,6 +574,7 @@
 		dev_info(&usb_dev->dev, "Firmware: build %s\n", build);
 	}
 
+	kfree(build);
 	return ret;
 }
 
diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
index 860d4ae..43617de 100644
--- a/drivers/net/ieee802154/fakelb.c
+++ b/drivers/net/ieee802154/fakelb.c
@@ -30,7 +30,7 @@
 static int numlbs = 2;
 
 static LIST_HEAD(fakelb_phys);
-static DEFINE_SPINLOCK(fakelb_phys_lock);
+static DEFINE_MUTEX(fakelb_phys_lock);
 
 static LIST_HEAD(fakelb_ifup_phys);
 static DEFINE_RWLOCK(fakelb_ifup_phys_lock);
@@ -180,9 +180,9 @@
 	if (err)
 		goto err_reg;
 
-	spin_lock(&fakelb_phys_lock);
+	mutex_lock(&fakelb_phys_lock);
 	list_add_tail(&phy->list, &fakelb_phys);
-	spin_unlock(&fakelb_phys_lock);
+	mutex_unlock(&fakelb_phys_lock);
 
 	return 0;
 
@@ -214,10 +214,10 @@
 	return 0;
 
 err_slave:
-	spin_lock(&fakelb_phys_lock);
+	mutex_lock(&fakelb_phys_lock);
 	list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)
 		fakelb_del(phy);
-	spin_unlock(&fakelb_phys_lock);
+	mutex_unlock(&fakelb_phys_lock);
 	return err;
 }
 
@@ -225,10 +225,10 @@
 {
 	struct fakelb_phy *phy, *tmp;
 
-	spin_lock(&fakelb_phys_lock);
+	mutex_lock(&fakelb_phys_lock);
 	list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)
 		fakelb_del(phy);
-	spin_unlock(&fakelb_phys_lock);
+	mutex_unlock(&fakelb_phys_lock);
 	return 0;
 }
 
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 25f2196..de2ea9f 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1077,7 +1077,7 @@
          * are "42101001.sb" or "42101002.sb"
          */
         sprintf(stir421x_fw_name, "4210%4X.sb",
-                self->usbdev->descriptor.bcdDevice);
+		le16_to_cpu(self->usbdev->descriptor.bcdDevice));
         ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev);
         if (ret < 0)
                 return ret;
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index dc7d970..effcdbf 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -164,6 +164,7 @@
 {
 	dev->mtu		= 64 * 1024;
 	dev->hard_header_len	= ETH_HLEN;	/* 14	*/
+	dev->min_header_len	= ETH_HLEN;	/* 14	*/
 	dev->addr_len		= ETH_ALEN;	/* 6	*/
 	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001*/
 	dev->flags		= IFF_LOOPBACK;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 06c8bfe..40cd866 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1110,6 +1110,7 @@
 static void macvlan_port_destroy(struct net_device *dev)
 {
 	struct macvlan_port *port = macvlan_port_get_rtnl(dev);
+	struct sk_buff *skb;
 
 	dev->priv_flags &= ~IFF_MACVLAN_PORT;
 	netdev_rx_handler_unregister(dev);
@@ -1118,7 +1119,15 @@
 	 * but we need to cancel it and purge left skbs if any.
 	 */
 	cancel_work_sync(&port->bc_work);
-	__skb_queue_purge(&port->bc_queue);
+
+	while ((skb = __skb_dequeue(&port->bc_queue))) {
+		const struct macvlan_dev *src = MACVLAN_SKB_CB(skb)->src;
+
+		if (src)
+			dev_put(src->dev);
+
+		kfree_skb(skb);
+	}
 
 	kfree_rcu(port, rcu);
 }
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 159a687..79de960 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -725,7 +725,7 @@
 	ssize_t n;
 
 	if (q->flags & IFF_VNET_HDR) {
-		vnet_hdr_len = q->vnet_hdr_sz;
+		vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
 
 		err = -EINVAL;
 		if (len < vnet_hdr_len)
@@ -865,7 +865,7 @@
 
 	if (q->flags & IFF_VNET_HDR) {
 		struct virtio_net_hdr vnet_hdr;
-		vnet_hdr_len = q->vnet_hdr_sz;
+		vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
 		if (iov_iter_count(iter) < vnet_hdr_len)
 			return -EINVAL;
 
diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c
index 86b2805..9b709f7 100644
--- a/drivers/net/phy/bcm63xx.c
+++ b/drivers/net/phy/bcm63xx.c
@@ -21,6 +21,23 @@
 MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
 MODULE_LICENSE("GPL");
 
+static int bcm63xx_config_intr(struct phy_device *phydev)
+{
+	int reg, err;
+
+	reg = phy_read(phydev, MII_BCM63XX_IR);
+	if (reg < 0)
+		return reg;
+
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+		reg &= ~MII_BCM63XX_IR_GMASK;
+	else
+		reg |= MII_BCM63XX_IR_GMASK;
+
+	err = phy_write(phydev, MII_BCM63XX_IR, reg);
+	return err;
+}
+
 static int bcm63xx_config_init(struct phy_device *phydev)
 {
 	int reg, err;
@@ -55,7 +72,7 @@
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm_phy_ack_intr,
-	.config_intr	= bcm_phy_config_intr,
+	.config_intr	= bcm63xx_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 }, {
 	/* same phy as above, with just a different OUI */
@@ -68,7 +85,7 @@
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm_phy_ack_intr,
-	.config_intr	= bcm_phy_config_intr,
+	.config_intr	= bcm63xx_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 } };
 
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index e6cefd0..84b9cca 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -1436,8 +1436,6 @@
 		skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
 		skb_queue_tail(&dp83640->rx_queue, skb);
 		schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
-	} else {
-		netif_rx_ni(skb);
 	}
 
 	return true;
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 0240552..ebec2dc 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -203,34 +203,6 @@
 {
 	int err;
 
-	/* The Marvell PHY has an errata which requires
-	 * that certain registers get written in order
-	 * to restart autonegotiation */
-	err = phy_write(phydev, MII_BMCR, BMCR_RESET);
-
-	if (err < 0)
-		return err;
-
-	err = phy_write(phydev, 0x1d, 0x1f);
-	if (err < 0)
-		return err;
-
-	err = phy_write(phydev, 0x1e, 0x200c);
-	if (err < 0)
-		return err;
-
-	err = phy_write(phydev, 0x1d, 0x5);
-	if (err < 0)
-		return err;
-
-	err = phy_write(phydev, 0x1e, 0);
-	if (err < 0)
-		return err;
-
-	err = phy_write(phydev, 0x1e, 0x100);
-	if (err < 0)
-		return err;
-
 	err = marvell_set_polarity(phydev, phydev->mdix);
 	if (err < 0)
 		return err;
@@ -264,6 +236,42 @@
 	return 0;
 }
 
+static int m88e1101_config_aneg(struct phy_device *phydev)
+{
+	int err;
+
+	/* This Marvell PHY has an errata which requires
+	 * that certain registers get written in order
+	 * to restart autonegotiation
+	 */
+	err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, 0x1d, 0x1f);
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, 0x1e, 0x200c);
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, 0x1d, 0x5);
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, 0x1e, 0);
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, 0x1e, 0x100);
+	if (err < 0)
+		return err;
+
+	return marvell_config_aneg(phydev);
+}
+
 #ifdef CONFIG_OF_MDIO
 /*
  * Set and/or override some configuration registers based on the
@@ -814,8 +822,6 @@
 		phydev->lp_advertising = mii_stat1000_to_ethtool_lpa_t(lpagb) |
 					 mii_lpa_to_ethtool_lpa_t(lpa);
 
-		lpa &= adv;
-
 		if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
 			phydev->duplex = DUPLEX_FULL;
 		else
@@ -993,7 +999,7 @@
 		.name = "Marvell 88E1101",
 		.features = PHY_GBIT_FEATURES,
 		.flags = PHY_HAS_INTERRUPT,
-		.config_aneg = &marvell_config_aneg,
+		.config_aneg = &m88e1101_config_aneg,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c
index c0b4e65..46fe1ae 100644
--- a/drivers/net/phy/mdio-bcm-iproc.c
+++ b/drivers/net/phy/mdio-bcm-iproc.c
@@ -81,8 +81,6 @@
 	if (rc)
 		return rc;
 
-	iproc_mdio_config_clk(priv->base);
-
 	/* Prepare the read operation */
 	cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
 		(reg << MII_DATA_RA_SHIFT) |
@@ -112,8 +110,6 @@
 	if (rc)
 		return rc;
 
-	iproc_mdio_config_clk(priv->base);
-
 	/* Prepare the write operation */
 	cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
 		(reg << MII_DATA_RA_SHIFT) |
@@ -163,6 +159,8 @@
 	bus->read = iproc_mdio_read;
 	bus->write = iproc_mdio_write;
 
+	iproc_mdio_config_clk(priv->base);
+
 	rc = of_mdiobus_register(bus, pdev->dev.of_node);
 	if (rc) {
 		dev_err(&pdev->dev, "MDIO bus registration failed\n");
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 47cd306..851c0e1 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -538,7 +538,7 @@
 	cancel_delayed_work_sync(&phydev->state_queue);
 
 	mutex_lock(&phydev->lock);
-	if (phydev->state > PHY_UP)
+	if (phydev->state > PHY_UP && phydev->state != PHY_HALTED)
 		phydev->state = PHY_UP;
 	mutex_unlock(&phydev->lock);
 }
@@ -640,8 +640,10 @@
 int phy_start_interrupts(struct phy_device *phydev)
 {
 	atomic_set(&phydev->irq_disable, 0);
-	if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt",
-			phydev) < 0) {
+	if (request_irq(phydev->irq, phy_interrupt,
+				IRQF_SHARED,
+				"phy_interrupt",
+				phydev) < 0) {
 		pr_warn("%s: Can't get IRQ %d (PHY)\n",
 			phydev->bus->name, phydev->irq);
 		phydev->irq = PHY_POLL;
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 174e06e..e5bb870 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -2390,8 +2390,6 @@
 	spin_lock_bh(&pn->all_channels_lock);
 	list_del(&pch->list);
 	spin_unlock_bh(&pn->all_channels_lock);
-	put_net(pch->chan_net);
-	pch->chan_net = NULL;
 
 	pch->file.dead = 1;
 	wake_up_interruptible(&pch->file.rwait);
@@ -2984,6 +2982,9 @@
  */
 static void ppp_destroy_channel(struct channel *pch)
 {
+	put_net(pch->chan_net);
+	pch->chan_net = NULL;
+
 	atomic_dec(&channel_count);
 
 	if (!pch->file.dead) {
diff --git a/drivers/net/ppp/pppolac.c b/drivers/net/ppp/pppolac.c
index 0184c96..3a45cf8 100644
--- a/drivers/net/ppp/pppolac.c
+++ b/drivers/net/ppp/pppolac.c
@@ -206,7 +206,9 @@
 	while ((skb = skb_dequeue(&delivery_queue))) {
 		struct sock *sk_udp = skb->sk;
 		struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
-		struct msghdr msg = { 0 };
+		struct msghdr msg = {
+			.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
+		};
 
 		iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1,
 			      skb->len);
diff --git a/drivers/net/ppp/pppopns.c b/drivers/net/ppp/pppopns.c
index d9e0603..cdb4fa1 100644
--- a/drivers/net/ppp/pppopns.c
+++ b/drivers/net/ppp/pppopns.c
@@ -189,7 +189,9 @@
 	while ((skb = skb_dequeue(&delivery_queue))) {
 		struct sock *sk_raw = skb->sk;
 		struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
-		struct msghdr msg = { 0 };
+		struct msghdr msg = {
+			.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
+		};
 
 		iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1,
 			      skb->len);
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 59fefca..a5f392a 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -969,7 +969,7 @@
 			    NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
 			    NETIF_F_HIGHDMA | NETIF_F_LRO)
 
-static void __team_compute_features(struct team *team)
+static void ___team_compute_features(struct team *team)
 {
 	struct team_port *port;
 	u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
@@ -993,15 +993,20 @@
 	team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
 	if (dst_release_flag == (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM))
 		team->dev->priv_flags |= IFF_XMIT_DST_RELEASE;
+}
 
+static void __team_compute_features(struct team *team)
+{
+	___team_compute_features(team);
 	netdev_change_features(team->dev);
 }
 
 static void team_compute_features(struct team *team)
 {
 	mutex_lock(&team->lock);
-	__team_compute_features(team);
+	___team_compute_features(team);
 	mutex_unlock(&team->lock);
+	netdev_change_features(team->dev);
 }
 
 static int team_port_enter(struct team *team, struct team_port *port)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 2d186bd..63778be 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -567,11 +567,13 @@
 	for (i = 0; i < n; i++) {
 		tfile = rtnl_dereference(tun->tfiles[i]);
 		BUG_ON(!tfile);
+		tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN;
 		tfile->socket.sk->sk_data_ready(tfile->socket.sk);
 		RCU_INIT_POINTER(tfile->tun, NULL);
 		--tun->numqueues;
 	}
 	list_for_each_entry(tfile, &tun->disabled, next) {
+		tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN;
 		tfile->socket.sk->sk_data_ready(tfile->socket.sk);
 		RCU_INIT_POINTER(tfile->tun, NULL);
 	}
@@ -627,6 +629,7 @@
 			goto out;
 	}
 	tfile->queue_index = tun->numqueues;
+	tfile->socket.sk->sk_shutdown &= ~RCV_SHUTDOWN;
 	rcu_assign_pointer(tfile->tun, tun);
 	rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
 	tun->numqueues++;
@@ -859,10 +862,7 @@
 	if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
 		goto drop;
 
-	if (skb->sk && sk_fullsock(skb->sk)) {
-		sock_tx_timestamp(skb->sk, &skb_shinfo(skb)->tx_flags);
-		sw_tx_timestamp(skb);
-	}
+	skb_tx_timestamp(skb);
 
 	/* Orphan the skb - required as we might hang on to it
 	 * for indefinite time.
@@ -1105,9 +1105,11 @@
 	}
 
 	if (tun->flags & IFF_VNET_HDR) {
-		if (len < tun->vnet_hdr_sz)
+		int vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz);
+
+		if (len < vnet_hdr_sz)
 			return -EINVAL;
-		len -= tun->vnet_hdr_sz;
+		len -= vnet_hdr_sz;
 
 		n = copy_from_iter(&gso, sizeof(gso), from);
 		if (n != sizeof(gso))
@@ -1119,7 +1121,7 @@
 
 		if (tun16_to_cpu(tun, gso.hdr_len) > len)
 			return -EINVAL;
-		iov_iter_advance(from, tun->vnet_hdr_sz - sizeof(gso));
+		iov_iter_advance(from, vnet_hdr_sz - sizeof(gso));
 	}
 
 	if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP) {
@@ -1298,7 +1300,7 @@
 		vlan_hlen = VLAN_HLEN;
 
 	if (tun->flags & IFF_VNET_HDR)
-		vnet_hdr_sz = tun->vnet_hdr_sz;
+		vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz);
 
 	total = skb->len + vlan_hlen + vnet_hdr_sz;
 
@@ -1408,9 +1410,6 @@
 	if (!iov_iter_count(to))
 		return 0;
 
-	if (tun->dev->reg_state != NETREG_REGISTERED)
-		return -EIO;
-
 	/* Read frames from queue */
 	skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0,
 				  &peeked, &off, &err);
@@ -1888,6 +1887,12 @@
 	int le;
 	int ret;
 
+#ifdef CONFIG_ANDROID_PARANOID_NETWORK
+	if (cmd != TUNGETIFF && !capable(CAP_NET_ADMIN)) {
+		return -EPERM;
+	}
+#endif
+
 	if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
 		if (copy_from_user(&ifr, argp, ifreq_len))
 			return -EFAULT;
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index bd9acff..7fbd8f04 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -66,7 +66,7 @@
 	 * buffer.
 	 */
 	if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
-		offset = ((rx->remaining + 1) & 0xfffe) + sizeof(u32);
+		offset = ((rx->remaining + 1) & 0xfffe);
 		rx->header = get_unaligned_le32(skb->data + offset);
 		offset = 0;
 
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 4e2b26a..2aa1a1d 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -777,7 +777,7 @@
 	struct net_device *netdev;
 	struct catc *catc;
 	u8 broadcast[ETH_ALEN];
-	int i, pktsz;
+	int pktsz, ret;
 
 	if (usb_set_interface(usbdev,
 			intf->altsetting->desc.bInterfaceNumber, 1)) {
@@ -812,12 +812,8 @@
 	if ((!catc->ctrl_urb) || (!catc->tx_urb) || 
 	    (!catc->rx_urb) || (!catc->irq_urb)) {
 		dev_err(&intf->dev, "No free urbs available.\n");
-		usb_free_urb(catc->ctrl_urb);
-		usb_free_urb(catc->tx_urb);
-		usb_free_urb(catc->rx_urb);
-		usb_free_urb(catc->irq_urb);
-		free_netdev(netdev);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto fail_free;
 	}
 
 	/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
@@ -845,15 +841,24 @@
                 catc->irq_buf, 2, catc_irq_done, catc, 1);
 
 	if (!catc->is_f5u011) {
+		u32 *buf;
+		int i;
+
 		dev_dbg(dev, "Checking memory size\n");
 
-		i = 0x12345678;
-		catc_write_mem(catc, 0x7a80, &i, 4);
-		i = 0x87654321;	
-		catc_write_mem(catc, 0xfa80, &i, 4);
-		catc_read_mem(catc, 0x7a80, &i, 4);
+		buf = kmalloc(4, GFP_KERNEL);
+		if (!buf) {
+			ret = -ENOMEM;
+			goto fail_free;
+		}
+
+		*buf = 0x12345678;
+		catc_write_mem(catc, 0x7a80, buf, 4);
+		*buf = 0x87654321;
+		catc_write_mem(catc, 0xfa80, buf, 4);
+		catc_read_mem(catc, 0x7a80, buf, 4);
 	  
-		switch (i) {
+		switch (*buf) {
 		case 0x12345678:
 			catc_set_reg(catc, TxBufCount, 8);
 			catc_set_reg(catc, RxBufCount, 32);
@@ -868,6 +873,8 @@
 			dev_dbg(dev, "32k Memory\n");
 			break;
 		}
+
+		kfree(buf);
 	  
 		dev_dbg(dev, "Getting MAC from SEEROM.\n");
 	  
@@ -914,16 +921,21 @@
 	usb_set_intfdata(intf, catc);
 
 	SET_NETDEV_DEV(netdev, &intf->dev);
-	if (register_netdev(netdev) != 0) {
-		usb_set_intfdata(intf, NULL);
-		usb_free_urb(catc->ctrl_urb);
-		usb_free_urb(catc->tx_urb);
-		usb_free_urb(catc->rx_urb);
-		usb_free_urb(catc->irq_urb);
-		free_netdev(netdev);
-		return -EIO;
-	}
+	ret = register_netdev(netdev);
+	if (ret)
+		goto fail_clear_intfdata;
+
 	return 0;
+
+fail_clear_intfdata:
+	usb_set_intfdata(intf, NULL);
+fail_free:
+	usb_free_urb(catc->ctrl_urb);
+	usb_free_urb(catc->tx_urb);
+	usb_free_urb(catc->rx_urb);
+	usb_free_urb(catc->irq_urb);
+	free_netdev(netdev);
+	return ret;
 }
 
 static void catc_disconnect(struct usb_interface *intf)
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 7cba2c3..8c408aa 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -462,6 +462,7 @@
 #define SAMSUNG_VENDOR_ID	0x04e8
 #define LENOVO_VENDOR_ID	0x17ef
 #define NVIDIA_VENDOR_ID	0x0955
+#define HP_VENDOR_ID		0x03f0
 
 static const struct usb_device_id	products[] = {
 /* BLACKLIST !!
@@ -608,6 +609,13 @@
 	.driver_info = 0,
 },
 
+/* HP lt2523 (Novatel E371) - handled by qmi_wwan */
+{
+	USB_DEVICE_AND_INTERFACE_INFO(HP_VENDOR_ID, 0x421d, USB_CLASS_COMM,
+				      USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+	.driver_info = 0,
+},
+
 /* AnyDATA ADU960S - handled by qmi_wwan */
 {
 	USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_CLASS_COMM,
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index bdd83d9..96a5028 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -617,8 +617,13 @@
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0bdb, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
 	  .driver_info = (unsigned long)&cdc_mbim_info,
 	},
-	/* Huawei E3372 fails unless NDP comes after the IP packets */
-	{ USB_DEVICE_AND_INTERFACE_INFO(0x12d1, 0x157d, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+
+	/* Some Huawei devices, ME906s-158 (12d1:15c1) and E3372
+	 * (12d1:157d), are known to fail unless the NDP is placed
+	 * after the IP packets.  Applying the quirk to all Huawei
+	 * devices is broader than necessary, but harmless.
+	 */
+	{ USB_VENDOR_AND_INTERFACE_INFO(0x12d1, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
 	  .driver_info = (unsigned long)&cdc_mbim_info_ndp_to_end,
 	},
 	/* default entry */
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index b11fe09..e0e94b8 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -809,6 +809,13 @@
 	if (cdc_ncm_init(dev))
 		goto error2;
 
+	/* Some firmwares need a pause here or they will silently fail
+	 * to set up the interface properly.  This value was decided
+	 * empirically on a Sierra Wireless MC7455 running 02.08.02.00
+	 * firmware.
+	 */
+	usleep_range(10000, 20000);
+
 	/* configure data interface */
 	temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
 	if (temp) {
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index f840802..17fac01 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -126,40 +126,61 @@
 
 static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
 {
+	u8 *buf;
 	int ret;
 
+	buf = kmalloc(size, GFP_NOIO);
+	if (!buf)
+		return -ENOMEM;
+
 	ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0),
 			      PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0,
-			      indx, data, size, 1000);
+			      indx, buf, size, 1000);
 	if (ret < 0)
 		netif_dbg(pegasus, drv, pegasus->net,
 			  "%s returned %d\n", __func__, ret);
+	else if (ret <= size)
+		memcpy(data, buf, ret);
+	kfree(buf);
 	return ret;
 }
 
-static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
+static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
+			 const void *data)
 {
+	u8 *buf;
 	int ret;
 
+	buf = kmemdup(data, size, GFP_NOIO);
+	if (!buf)
+		return -ENOMEM;
+
 	ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
 			      PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0,
-			      indx, data, size, 100);
+			      indx, buf, size, 100);
 	if (ret < 0)
 		netif_dbg(pegasus, drv, pegasus->net,
 			  "%s returned %d\n", __func__, ret);
+	kfree(buf);
 	return ret;
 }
 
 static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
 {
+	u8 *buf;
 	int ret;
 
+	buf = kmemdup(&data, 1, GFP_NOIO);
+	if (!buf)
+		return -ENOMEM;
+
 	ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
 			      PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data,
-			      indx, &data, 1, 1000);
+			      indx, buf, 1, 1000);
 	if (ret < 0)
 		netif_dbg(pegasus, drv, pegasus->net,
 			  "%s returned %d\n", __func__, ret);
+	kfree(buf);
 	return ret;
 }
 
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index a34f491..582d8f0 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -485,6 +485,13 @@
 					      USB_CDC_PROTO_NONE),
 		.driver_info        = (unsigned long)&qmi_wwan_info,
 	},
+	{	/* HP lt2523 (Novatel E371) */
+		USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d,
+					      USB_CLASS_COMM,
+					      USB_CDC_SUBCLASS_ETHERNET,
+					      USB_CDC_PROTO_NONE),
+		.driver_info        = (unsigned long)&qmi_wwan_info,
+	},
 	{	/* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
 		USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7),
 		.driver_info = (unsigned long)&qmi_wwan_info,
@@ -723,6 +730,8 @@
 	{QMI_FIXED_INTF(0x1199, 0x9071, 10)},	/* Sierra Wireless MC74xx */
 	{QMI_FIXED_INTF(0x1199, 0x9079, 8)},	/* Sierra Wireless EM74xx */
 	{QMI_FIXED_INTF(0x1199, 0x9079, 10)},	/* Sierra Wireless EM74xx */
+	{QMI_FIXED_INTF(0x1199, 0x907b, 8)},	/* Sierra Wireless EM74xx */
+	{QMI_FIXED_INTF(0x1199, 0x907b, 10)},	/* Sierra Wireless EM74xx */
 	{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},	/* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
 	{QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},	/* Alcatel L800MA */
 	{QMI_FIXED_INTF(0x2357, 0x0201, 4)},	/* TP-LINK HSUPA Modem MA180 */
@@ -747,6 +756,7 @@
 	{QMI_FIXED_INTF(0x413c, 0x81b1, 8)},	/* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
 	{QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)},	/* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
 	{QMI_FIXED_INTF(0x22de, 0x9061, 3)},	/* WeTelecom WPD-600N */
+	{QMI_FIXED_INTF(0x1e0e, 0x9001, 5)},	/* SIMCom 7230E */
 
 	/* 4. Gobi 1000 devices */
 	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 2fb637a..1c27e6f 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -1645,7 +1645,7 @@
 	u8 checksum = CHECKSUM_NONE;
 	u32 opts2, opts3;
 
-	if (tp->version == RTL_VER_01)
+	if (!(tp->netdev->features & NETIF_F_RXCSUM))
 		goto return_result;
 
 	opts2 = le32_to_cpu(rx_desc->opts2);
@@ -1851,6 +1851,9 @@
 		napi_complete(napi);
 		if (!list_empty(&tp->rx_done))
 			napi_schedule(napi);
+		else if (!skb_queue_empty(&tp->tx_queue) &&
+			 !list_empty(&tp->tx_free))
+			napi_schedule(napi);
 	}
 
 	return work_done;
@@ -2990,10 +2993,13 @@
 		if (!netif_carrier_ok(netdev)) {
 			tp->rtl_ops.enable(tp);
 			set_bit(RTL8152_SET_RX_MODE, &tp->flags);
+			netif_stop_queue(netdev);
 			napi_disable(&tp->napi);
 			netif_carrier_on(netdev);
 			rtl_start_rx(tp);
 			napi_enable(&tp->napi);
+			netif_wake_queue(netdev);
+			netif_info(tp, link, netdev, "carrier on\n");
 		}
 	} else {
 		if (netif_carrier_ok(netdev)) {
@@ -3001,6 +3007,7 @@
 			napi_disable(&tp->napi);
 			tp->rtl_ops.disable(tp);
 			napi_enable(&tp->napi);
+			netif_info(tp, link, netdev, "carrier off\n");
 		}
 	}
 }
@@ -3385,12 +3392,12 @@
 	if (!netif_running(netdev))
 		return 0;
 
+	netif_stop_queue(netdev);
 	napi_disable(&tp->napi);
 	clear_bit(WORK_ENABLE, &tp->flags);
 	usb_kill_urb(tp->intr_urb);
 	cancel_delayed_work_sync(&tp->schedule);
 	if (netif_carrier_ok(netdev)) {
-		netif_stop_queue(netdev);
 		mutex_lock(&tp->control);
 		tp->rtl_ops.disable(tp);
 		mutex_unlock(&tp->control);
@@ -3415,12 +3422,14 @@
 	if (netif_carrier_ok(netdev)) {
 		mutex_lock(&tp->control);
 		tp->rtl_ops.enable(tp);
+		rtl_start_rx(tp);
 		rtl8152_set_rx_mode(netdev);
 		mutex_unlock(&tp->control);
-		netif_wake_queue(netdev);
 	}
 
 	napi_enable(&tp->napi);
+	netif_wake_queue(netdev);
+	usb_submit_urb(tp->intr_urb, GFP_KERNEL);
 
 	return 0;
 }
@@ -3442,43 +3451,93 @@
 	 */
 	if (!sw_linking && tp->rtl_ops.in_nway(tp))
 		return true;
+	else if (!skb_queue_empty(&tp->tx_queue))
+		return true;
 	else
 		return false;
 }
 
-static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
+static int rtl8152_rumtime_suspend(struct r8152 *tp)
 {
-	struct r8152 *tp = usb_get_intfdata(intf);
 	struct net_device *netdev = tp->netdev;
 	int ret = 0;
 
-	mutex_lock(&tp->control);
+	if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
+		u32 rcr = 0;
 
-	if (PMSG_IS_AUTO(message)) {
-		if (netif_running(netdev) && delay_autosuspend(tp)) {
+		if (delay_autosuspend(tp)) {
 			ret = -EBUSY;
 			goto out1;
 		}
 
-		set_bit(SELECTIVE_SUSPEND, &tp->flags);
-	} else {
-		netif_device_detach(netdev);
+		if (netif_carrier_ok(netdev)) {
+			u32 ocp_data;
+
+			rcr = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
+			ocp_data = rcr & ~RCR_ACPT_ALL;
+			ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
+			rxdy_gated_en(tp, true);
+			ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA,
+						 PLA_OOB_CTRL);
+			if (!(ocp_data & RXFIFO_EMPTY)) {
+				rxdy_gated_en(tp, false);
+				ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
+				ret = -EBUSY;
+				goto out1;
+			}
+		}
+
+		clear_bit(WORK_ENABLE, &tp->flags);
+		usb_kill_urb(tp->intr_urb);
+
+		rtl_runtime_suspend_enable(tp, true);
+
+		if (netif_carrier_ok(netdev)) {
+			napi_disable(&tp->napi);
+			rtl_stop_rx(tp);
+			rxdy_gated_en(tp, false);
+			ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
+			napi_enable(&tp->napi);
+		}
 	}
 
+	set_bit(SELECTIVE_SUSPEND, &tp->flags);
+
+out1:
+	return ret;
+}
+
+static int rtl8152_system_suspend(struct r8152 *tp)
+{
+	struct net_device *netdev = tp->netdev;
+	int ret = 0;
+
+	netif_device_detach(netdev);
+
 	if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
 		clear_bit(WORK_ENABLE, &tp->flags);
 		usb_kill_urb(tp->intr_urb);
 		napi_disable(&tp->napi);
-		if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
-			rtl_stop_rx(tp);
-			rtl_runtime_suspend_enable(tp, true);
-		} else {
-			cancel_delayed_work_sync(&tp->schedule);
-			tp->rtl_ops.down(tp);
-		}
+		cancel_delayed_work_sync(&tp->schedule);
+		tp->rtl_ops.down(tp);
 		napi_enable(&tp->napi);
 	}
-out1:
+
+	return ret;
+}
+
+static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct r8152 *tp = usb_get_intfdata(intf);
+	int ret;
+
+	mutex_lock(&tp->control);
+
+	if (PMSG_IS_AUTO(message))
+		ret = rtl8152_rumtime_suspend(tp);
+	else
+		ret = rtl8152_system_suspend(tp);
+
 	mutex_unlock(&tp->control);
 
 	return ret;
@@ -4173,6 +4232,11 @@
 				NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
 				NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
 
+	if (tp->version == RTL_VER_01) {
+		netdev->features &= ~NETIF_F_RXCSUM;
+		netdev->hw_features &= ~NETIF_F_RXCSUM;
+	}
+
 	netdev->ethtool_ops = &ops;
 	netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
 
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index d37b7dc..3967298 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -155,16 +155,36 @@
 */
 static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
 {
-	return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-			       RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
-			       indx, 0, data, size, 500);
+	void *buf;
+	int ret;
+
+	buf = kmalloc(size, GFP_NOIO);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+			      RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
+			      indx, 0, buf, size, 500);
+	if (ret > 0 && ret <= size)
+		memcpy(data, buf, ret);
+	kfree(buf);
+	return ret;
 }
 
-static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
+static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data)
 {
-	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-			       RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
-			       indx, 0, data, size, 500);
+	void *buf;
+	int ret;
+
+	buf = kmemdup(data, size, GFP_NOIO);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+			      RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
+			      indx, 0, buf, size, 500);
+	kfree(buf);
+	return ret;
 }
 
 static void async_set_reg_cb(struct urb *urb)
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index a2515887..0b5a84c 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -73,8 +73,6 @@
 /* Private data structure */
 struct sierra_net_data {
 
-	u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */
-
 	u16 link_up;		/* air link up or down */
 	u8 tx_hdr_template[4];	/* part of HIP hdr for tx'd packets */
 
@@ -122,6 +120,7 @@
 
 /* LSI Protocol types */
 #define SIERRA_NET_PROTOCOL_UMTS      0x01
+#define SIERRA_NET_PROTOCOL_UMTS_DS   0x04
 /* LSI Coverage */
 #define SIERRA_NET_COVERAGE_NONE      0x00
 #define SIERRA_NET_COVERAGE_NOPACKET  0x01
@@ -129,7 +128,8 @@
 /* LSI Session */
 #define SIERRA_NET_SESSION_IDLE       0x00
 /* LSI Link types */
-#define SIERRA_NET_AS_LINK_TYPE_IPv4  0x00
+#define SIERRA_NET_AS_LINK_TYPE_IPV4  0x00
+#define SIERRA_NET_AS_LINK_TYPE_IPV6  0x02
 
 struct lsi_umts {
 	u8 protocol;
@@ -137,9 +137,14 @@
 	__be16 length;
 	/* eventually use a union for the rest - assume umts for now */
 	u8 coverage;
-	u8 unused2[41];
+	u8 network_len; /* network name len */
+	u8 network[40]; /* network name (UCS2, bigendian) */
 	u8 session_state;
 	u8 unused3[33];
+} __packed;
+
+struct lsi_umts_single {
+	struct lsi_umts lsi;
 	u8 link_type;
 	u8 pdp_addr_len; /* NW-supplied PDP address len */
 	u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */
@@ -158,10 +163,31 @@
 	u8 reserved[8];
 } __packed;
 
+struct lsi_umts_dual {
+	struct lsi_umts lsi;
+	u8 pdp_addr4_len; /* NW-supplied PDP IPv4 address len */
+	u8 pdp_addr4[4];  /* NW-supplied PDP IPv4 address (bigendian)) */
+	u8 pdp_addr6_len; /* NW-supplied PDP IPv6 address len */
+	u8 pdp_addr6[16]; /* NW-supplied PDP IPv6 address (bigendian)) */
+	u8 unused4[23];
+	u8 dns1_addr4_len; /* NW-supplied 1st DNS v4 address len (bigendian) */
+	u8 dns1_addr4[4];  /* NW-supplied 1st DNS v4 address */
+	u8 dns1_addr6_len; /* NW-supplied 1st DNS v6 address len */
+	u8 dns1_addr6[16]; /* NW-supplied 1st DNS v6 address (bigendian)*/
+	u8 dns2_addr4_len; /* NW-supplied 2nd DNS v4 address len (bigendian) */
+	u8 dns2_addr4[4];  /* NW-supplied 2nd DNS v4 address */
+	u8 dns2_addr6_len; /* NW-supplied 2nd DNS v6 address len */
+	u8 dns2_addr6[16]; /* NW-supplied 2nd DNS v6 address (bigendian)*/
+	u8 unused5[68];
+} __packed;
+
 #define SIERRA_NET_LSI_COMMON_LEN      4
-#define SIERRA_NET_LSI_UMTS_LEN        (sizeof(struct lsi_umts))
+#define SIERRA_NET_LSI_UMTS_LEN        (sizeof(struct lsi_umts_single))
 #define SIERRA_NET_LSI_UMTS_STATUS_LEN \
 	(SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN)
+#define SIERRA_NET_LSI_UMTS_DS_LEN     (sizeof(struct lsi_umts_dual))
+#define SIERRA_NET_LSI_UMTS_DS_STATUS_LEN \
+	(SIERRA_NET_LSI_UMTS_DS_LEN - SIERRA_NET_LSI_COMMON_LEN)
 
 /* Forward definitions */
 static void sierra_sync_timer(unsigned long syncdata);
@@ -191,10 +217,11 @@
 	dev->data[0] = (unsigned long)priv;
 }
 
-/* is packet IPv4 */
+/* is packet IPv4/IPv6 */
 static inline int is_ip(struct sk_buff *skb)
 {
-	return skb->protocol == cpu_to_be16(ETH_P_IP);
+	return skb->protocol == cpu_to_be16(ETH_P_IP) ||
+	       skb->protocol == cpu_to_be16(ETH_P_IPV6);
 }
 
 /*
@@ -350,46 +377,51 @@
 static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
 {
 	struct lsi_umts *lsi = (struct lsi_umts *)data;
+	u32 expected_length;
 
-	if (datalen < sizeof(struct lsi_umts)) {
-		netdev_err(dev->net, "%s: Data length %d, exp %Zu\n",
-				__func__, datalen,
-				sizeof(struct lsi_umts));
+	if (datalen < sizeof(struct lsi_umts_single)) {
+		netdev_err(dev->net, "%s: Data length %d, exp >= %Zu\n",
+			   __func__, datalen, sizeof(struct lsi_umts_single));
 		return -1;
 	}
 
-	if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) {
-		netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n",
-				__func__, be16_to_cpu(lsi->length),
-				(u32)SIERRA_NET_LSI_UMTS_STATUS_LEN);
-		return -1;
-	}
-
-	/* Validate the protocol  - only support UMTS for now */
-	if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) {
-		netdev_err(dev->net, "Protocol unsupported, 0x%02x\n",
-			lsi->protocol);
-		return -1;
-	}
-
-	/* Validate the link type */
-	if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) {
-		netdev_err(dev->net, "Link type unsupported: 0x%02x\n",
-			lsi->link_type);
-		return -1;
-	}
-
-	/* Validate the coverage */
-	if (lsi->coverage == SIERRA_NET_COVERAGE_NONE
-	   || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
-		netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage);
-		return 0;
-	}
-
 	/* Validate the session state */
 	if (lsi->session_state == SIERRA_NET_SESSION_IDLE) {
 		netdev_err(dev->net, "Session idle, 0x%02x\n",
-			lsi->session_state);
+			   lsi->session_state);
+		return 0;
+	}
+
+	/* Validate the protocol  - only support UMTS for now */
+	if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS) {
+		struct lsi_umts_single *single = (struct lsi_umts_single *)lsi;
+
+		/* Validate the link type */
+		if (single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV4 &&
+		    single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV6) {
+			netdev_err(dev->net, "Link type unsupported: 0x%02x\n",
+				   single->link_type);
+			return -1;
+		}
+		expected_length = SIERRA_NET_LSI_UMTS_STATUS_LEN;
+	} else if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS_DS) {
+		expected_length = SIERRA_NET_LSI_UMTS_DS_STATUS_LEN;
+	} else {
+		netdev_err(dev->net, "Protocol unsupported, 0x%02x\n",
+			   lsi->protocol);
+		return -1;
+	}
+
+	if (be16_to_cpu(lsi->length) != expected_length) {
+		netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n",
+			   __func__, be16_to_cpu(lsi->length), expected_length);
+		return -1;
+	}
+
+	/* Validate the coverage */
+	if (lsi->coverage == SIERRA_NET_COVERAGE_NONE ||
+	    lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
+		netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage);
 		return 0;
 	}
 
@@ -662,7 +694,6 @@
 	u8	numendpoints;
 	u16	fwattr = 0;
 	int	status;
-	struct ethhdr *eth;
 	struct sierra_net_data *priv;
 	static const u8 sync_tmplate[sizeof(priv->sync_msg)] = {
 		0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00};
@@ -700,11 +731,6 @@
 	dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter);
 	dev->net->dev_addr[ETH_ALEN-1] = ifacenum;
 
-	/* we will have to manufacture ethernet headers, prepare template */
-	eth = (struct ethhdr *)priv->ethr_hdr_tmpl;
-	memcpy(&eth->h_dest, dev->net->dev_addr, ETH_ALEN);
-	eth->h_proto = cpu_to_be16(ETH_P_IP);
-
 	/* prepare shutdown message template */
 	memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg));
 	/* set context index initially to 0 - prepares tx hdr template */
@@ -833,9 +859,14 @@
 
 		skb_pull(skb, hh.hdrlen);
 
-		/* We are going to accept this packet, prepare it */
-		memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl,
-			ETH_HLEN);
+		/* We are going to accept this packet, prepare it.
+		 * In case protocol is IPv6, keep it, otherwise force IPv4.
+		 */
+		skb_reset_mac_header(skb);
+		if (eth_hdr(skb)->h_proto != cpu_to_be16(ETH_P_IPV6))
+			eth_hdr(skb)->h_proto = cpu_to_be16(ETH_P_IP);
+		eth_zero_addr(eth_hdr(skb)->h_source);
+		memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
 
 		/* Last packet in batch handled by usbnet */
 		if (hh.payload_len.word == skb->len)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f94ab78..8dfc752 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -47,8 +47,16 @@
  */
 DECLARE_EWMA(pkt_len, 1, 64)
 
+/* With mergeable buffers we align buffer address and use the low bits to
+ * encode its true size. Buffer size is up to 1 page so we need to align to
+ * square root of page size to ensure we reserve enough bits to encode the true
+ * size.
+ */
+#define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2)
+
 /* Minimum alignment for mergeable packet buffers. */
-#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256)
+#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \
+				   1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT)
 
 #define VIRTNET_DRIVER_VERSION "1.0.0"
 
@@ -1415,6 +1423,7 @@
 #ifdef CONFIG_NET_RX_BUSY_POLL
 	.ndo_busy_poll		= virtnet_busy_poll,
 #endif
+	.ndo_features_check	= passthru_features_check,
 };
 
 static void virtnet_config_changed_work(struct work_struct *work)
@@ -1465,6 +1474,11 @@
 		netif_napi_del(&vi->rq[i].napi);
 	}
 
+	/* We called napi_hash_del() before netif_napi_del(),
+	 * we need to respect an RCU grace period before freeing vi->rq
+	 */
+	synchronize_net();
+
 	kfree(vi->rq);
 	kfree(vi->sq);
 }
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 903bda4..349aecb 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -301,7 +301,9 @@
 		.flowi4_tos = RT_TOS(ip4h->tos),
 		.flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_L3MDEV_SRC |
 				FLOWI_FLAG_SKIP_NH_OIF,
+		.flowi4_proto = ip4h->protocol,
 		.daddr = ip4h->daddr,
+		.saddr = ip4h->saddr,
 	};
 
 	if (vrf_send_v4_prep(skb, &fl4, vrf_dev))
@@ -343,6 +345,7 @@
 
 static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	int len = skb->len;
 	netdev_tx_t ret = is_ip_tx_frame(skb, dev);
 
 	if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
@@ -350,7 +353,7 @@
 
 		u64_stats_update_begin(&dstats->syncp);
 		dstats->tx_pkts++;
-		dstats->tx_bytes += skb->len;
+		dstats->tx_bytes += len;
 		u64_stats_update_end(&dstats->syncp);
 	} else {
 		this_cpu_inc(dev->dstats->tx_drps);
@@ -410,6 +413,8 @@
 	struct in6_addr *nexthop;
 	int ret;
 
+	nf_reset(skb);
+
 	skb->protocol = htons(ETH_P_IPV6);
 	skb->dev = dev;
 
@@ -521,6 +526,8 @@
 	u32 nexthop;
 	int ret = -EINVAL;
 
+	nf_reset(skb);
+
 	/* Be paranoid, rather than too clever. */
 	if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
 		struct sk_buff *skb2;
@@ -919,6 +926,8 @@
 		return -EINVAL;
 
 	vrf->tb_id = nla_get_u32(data[IFLA_VRF_TABLE]);
+	if (vrf->tb_id == RT_TABLE_UNSPEC)
+		return -EINVAL;
 
 	dev->priv_flags |= IFF_L3MDEV_MASTER;
 
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 3c0df70..dab3bf6 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -77,6 +77,8 @@
 
 static int vxlan_sock_add(struct vxlan_dev *vxlan);
 
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan);
+
 /* per-network namespace private data for this module */
 struct vxlan_net {
 	struct list_head  vxlan_list;
@@ -593,7 +595,7 @@
 		}
 	}
 
-	pp = eth_gro_receive(head, skb);
+	pp = call_gro_receive(eth_gro_receive, head, skb);
 
 out:
 	skb_gro_remcsum_cleanup(skb, &grc);
@@ -1052,6 +1054,8 @@
 
 static void vxlan_sock_release(struct vxlan_dev *vxlan)
 {
+	vxlan_vs_del_dev(vxlan);
+
 	__vxlan_sock_release(vxlan->vn4_sock);
 #if IS_ENABLED(CONFIG_IPV6)
 	__vxlan_sock_release(vxlan->vn6_sock);
@@ -1254,7 +1258,7 @@
 
 	/* Need Vxlan and inner Ethernet header to be present */
 	if (!pskb_may_pull(skb, VXLAN_HLEN))
-		goto error;
+		goto drop;
 
 	vxh = (struct vxlanhdr *)(udp_hdr(skb) + 1);
 	flags = ntohl(vxh->vx_flags);
@@ -1344,13 +1348,7 @@
 bad_flags:
 	netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
 		   ntohl(vxh->vx_flags), ntohl(vxh->vx_vni));
-
-error:
-	if (tun_dst)
-		dst_release((struct dst_entry *)tun_dst);
-
-	/* Return non vxlan pkt */
-	return 1;
+	goto drop;
 }
 
 static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
@@ -2242,7 +2240,7 @@
 				= container_of(p, struct vxlan_fdb, hlist);
 			unsigned long timeout;
 
-			if (f->state & NUD_PERMANENT)
+			if (f->state & (NUD_PERMANENT | NUD_NOARP))
 				continue;
 
 			timeout = f->used + vxlan->cfg.age_interval * HZ;
@@ -2261,6 +2259,15 @@
 	mod_timer(&vxlan->age_timer, next_timer);
 }
 
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan)
+{
+	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
+
+	spin_lock(&vn->sock_lock);
+	hlist_del_init_rcu(&vxlan->hlist);
+	spin_unlock(&vn->sock_lock);
+}
+
 static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
 {
 	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
@@ -2370,27 +2377,41 @@
 {
 }
 
+static int __vxlan_change_mtu(struct net_device *dev,
+			      struct net_device *lowerdev,
+			      struct vxlan_rdst *dst, int new_mtu, bool strict)
+{
+	int max_mtu = IP_MAX_MTU;
+
+	if (lowerdev)
+		max_mtu = lowerdev->mtu;
+
+	if (dst->remote_ip.sa.sa_family == AF_INET6)
+		max_mtu -= VXLAN6_HEADROOM;
+	else
+		max_mtu -= VXLAN_HEADROOM;
+
+	if (new_mtu < 68)
+		return -EINVAL;
+
+	if (new_mtu > max_mtu) {
+		if (strict)
+			return -EINVAL;
+
+		new_mtu = max_mtu;
+	}
+
+	dev->mtu = new_mtu;
+	return 0;
+}
+
 static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct vxlan_rdst *dst = &vxlan->default_dst;
-	struct net_device *lowerdev;
-	int max_mtu;
-
-	lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex);
-	if (lowerdev == NULL)
-		return eth_change_mtu(dev, new_mtu);
-
-	if (dst->remote_ip.sa.sa_family == AF_INET6)
-		max_mtu = lowerdev->mtu - VXLAN6_HEADROOM;
-	else
-		max_mtu = lowerdev->mtu - VXLAN_HEADROOM;
-
-	if (new_mtu < 68 || new_mtu > max_mtu)
-		return -EINVAL;
-
-	dev->mtu = new_mtu;
-	return 0;
+	struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
+							 dst->remote_ifindex);
+	return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true);
 }
 
 static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
@@ -2592,7 +2613,7 @@
 
 	if (data[IFLA_VXLAN_ID]) {
 		__u32 id = nla_get_u32(data[IFLA_VXLAN_ID]);
-		if (id >= VXLAN_VID_MASK)
+		if (id >= VXLAN_N_VID)
 			return -ERANGE;
 	}
 
@@ -2768,6 +2789,7 @@
 	int err;
 	bool use_ipv6 = false;
 	__be16 default_port = vxlan->cfg.dst_port;
+	struct net_device *lowerdev = NULL;
 
 	vxlan->net = src_net;
 
@@ -2788,9 +2810,7 @@
 	}
 
 	if (conf->remote_ifindex) {
-		struct net_device *lowerdev
-			 = __dev_get_by_index(src_net, conf->remote_ifindex);
-
+		lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex);
 		dst->remote_ifindex = conf->remote_ifindex;
 
 		if (!lowerdev) {
@@ -2814,6 +2834,12 @@
 		needed_headroom = lowerdev->hard_header_len;
 	}
 
+	if (conf->mtu) {
+		err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false);
+		if (err)
+			return err;
+	}
+
 	if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
 		needed_headroom += VXLAN6_HEADROOM;
 	else
@@ -2991,6 +3017,9 @@
 	if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL])
 		conf.flags |= VXLAN_F_REMCSUM_NOPARTIAL;
 
+	if (tb[IFLA_MTU])
+		conf.mtu = nla_get_u32(tb[IFLA_MTU]);
+
 	err = vxlan_dev_configure(src_net, dev, &conf);
 	switch (err) {
 	case -ENODEV:
@@ -3012,12 +3041,6 @@
 static void vxlan_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
-	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
-
-	spin_lock(&vn->sock_lock);
-	if (!hlist_unhashed(&vxlan->hlist))
-		hlist_del_rcu(&vxlan->hlist);
-	spin_unlock(&vn->sock_lock);
 
 	gro_cells_destroy(&vxlan->gro_cells);
 	list_del(&vxlan->next);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 37ab1a3..f9f9422 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -285,6 +285,5 @@
 source "drivers/net/wireless/mwifiex/Kconfig"
 source "drivers/net/wireless/cw1200/Kconfig"
 source "drivers/net/wireless/rsi/Kconfig"
-source "drivers/net/wireless/bcmdhd/Kconfig"
 
 endif # WLAN
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 9bbf4ed..740fdd3 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -60,5 +60,3 @@
 
 obj-$(CONFIG_CW1200)	+= cw1200/
 obj-$(CONFIG_RSI_91X)	+= rsi/
-
-obj-$(CONFIG_BCMDHD)	+= bcmdhd/
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 0947cc2..531de25 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1681,6 +1681,10 @@
 		goto err_hif_stop;
 	}
 
+	ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;
+
+	INIT_LIST_HEAD(&ar->arvifs);
+
 	/* we don't care about HTT in UTF mode */
 	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
 		status = ath10k_htt_setup(&ar->htt);
@@ -1694,10 +1698,6 @@
 	if (status)
 		goto err_hif_stop;
 
-	ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;
-
-	INIT_LIST_HEAD(&ar->arvifs);
-
 	return 0;
 
 err_hif_stop:
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 6cc1aa3..1a88a24 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1986,7 +1986,12 @@
 		goto out;
 	}
 
-	if (filter && (filter != ar->debug.pktlog_filter)) {
+	if (filter == ar->debug.pktlog_filter) {
+		ret = count;
+		goto out;
+	}
+
+	if (filter) {
 		ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
 		if (ret) {
 			ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 95a55405..6decf4a 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4456,7 +4456,10 @@
 		goto err_vdev_delete;
 	}
 
-	if (ar->cfg_tx_chainmask) {
+	/* Configuring number of spatial stream for monitor interface is causing
+	 * target assert in qca9888 and qca6174.
+	 */
+	if (ar->cfg_tx_chainmask && (vif->type != NL80211_IFTYPE_MONITOR)) {
 		u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
 
 		vdev_param = ar->wmi.vdev_param->nss;
@@ -6348,12 +6351,13 @@
 
 static int ath10k_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
-			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			       u8 buf_size, bool amsdu)
+			       struct ieee80211_ampdu_params *params)
 {
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
 
 	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
 		   arvif->vdev_id, sta->addr, tid, action);
@@ -6416,7 +6420,13 @@
 			def = &vifs[0].new_ctx->def;
 
 		ar->rx_channel = def->chan;
-	} else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) {
+	} else if ((ctx && ath10k_mac_num_chanctxs(ar) == 0) ||
+		   (ctx && (ar->state == ATH10K_STATE_RESTARTED))) {
+		/* During driver restart due to firmware assert, since mac80211
+		 * already has valid channel context for given radio, channel
+		 * context iteration return num_chanctx > 0. So fix rx_channel
+		 * when restart is in progress.
+		 */
 		ar->rx_channel = ctx->def.chan;
 	} else {
 		ar->rx_channel = NULL;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 930785a..907fd60 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -3050,7 +3050,7 @@
 		goto err_core_destroy;
 	}
 
-	if (QCA_REV_6174(ar))
+	if (QCA_REV_6174(ar) || QCA_REV_9377(ar))
 		ath10k_pci_override_ce_config(ar);
 
 	ret = ath10k_pci_alloc_pipes(ar);
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
index 4671cfb..a0e7eeb 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.c
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -338,7 +338,7 @@
 		} else {
 			res = -EINVAL;
 		}
-	} else if (strncmp("background", buf, 9) == 0) {
+	} else if (strncmp("background", buf, 10) == 0) {
 		res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
 	} else if (strncmp("manual", buf, 6) == 0) {
 		res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 803030f..6a2a168 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -77,7 +77,7 @@
 	/* HP Compaq CQ60-206US (ddreggors@jumptv.com) */
 	{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) },
 	/* HP Compaq C700 (nitrousnrg@gmail.com) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) },
+	{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 0) },
 	/* LiteOn AR5BXB63 (magooz@salug.it) */
 	{ ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) },
 	/* IBM-specific AR5212 (all others) */
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index dc44cfe..16e052d 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -502,8 +502,7 @@
 			break;
 		return -EOPNOTSUPP;
 	default:
-		WARN_ON(1);
-		return -EINVAL;
+		return -EOPNOTSUPP;
 	}
 
 	mutex_lock(&ah->lock);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 8b4561e..ef49327 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -4176,7 +4176,7 @@
 	if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9531(ah))
 		ar9003_hw_internal_regulator_apply(ah);
 	ar9003_hw_apply_tuning_caps(ah);
-	ar9003_hw_apply_minccapwr_thresh(ah, chan);
+	ar9003_hw_apply_minccapwr_thresh(ah, is2ghz);
 	ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
 	ar9003_hw_thermometer_apply(ah);
 	ar9003_hw_thermo_cal_apply(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
index 694ca2e..74670e0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
@@ -73,13 +73,13 @@
 #define AR9300_OTP_BASE \
 		((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000)
 #define AR9300_OTP_STATUS \
-		((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30018 : 0x15f18)
+		((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x31018 : 0x15f18)
 #define AR9300_OTP_STATUS_TYPE		0x7
 #define AR9300_OTP_STATUS_VALID		0x4
 #define AR9300_OTP_STATUS_ACCESS_BUSY	0x2
 #define AR9300_OTP_STATUS_SM_BUSY	0x1
 #define AR9300_OTP_READ_DATA \
-		((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3001c : 0x15f1c)
+		((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3101c : 0x15f1c)
 
 enum targetPowerHTRates {
 	HT_TARGET_RATE_0_8_16,
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index b42f4a9..a660e40 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -959,6 +959,7 @@
 	struct survey_info *cur_survey;
 	struct survey_info survey[ATH9K_NUM_CHANNELS];
 
+	spinlock_t intr_lock;
 	struct tasklet_struct intr_tq;
 	struct tasklet_struct bcon_tasklet;
 	struct ath_hw *sc_ah;
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c
index a876271..0394573 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.c
@@ -528,6 +528,9 @@
 	if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
 		return 0;
 
+	if (!spec_priv->rfs_chan_spec_scan)
+		return 1;
+
 	/* Output buffers are full, no need to process anything
 	 * since there is no space to put the result anyway
 	 */
@@ -1072,7 +1075,7 @@
 
 void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv)
 {
-	if (config_enabled(CONFIG_ATH9K_DEBUGFS)) {
+	if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) {
 		relay_close(spec_priv->rfs_chan_spec_scan);
 		spec_priv->rfs_chan_spec_scan = NULL;
 	}
@@ -1086,6 +1089,9 @@
 					    debugfs_phy,
 					    1024, 256, &rfs_spec_scan_cb,
 					    NULL);
+	if (!spec_priv->rfs_chan_spec_scan)
+		return;
+
 	debugfs_create_file("spectral_scan_ctl",
 			    S_IRUSR | S_IWUSR,
 			    debugfs_phy, spec_priv,
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 165dd20..c92564b 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -37,6 +37,7 @@
 	{ USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */
 	{ USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
 	{ USB_DEVICE(0x0471, 0x209e) }, /* Philips (or NXP) PTA01 */
+	{ USB_DEVICE(0x1eda, 0x2315) }, /* AirTies */
 
 	{ USB_DEVICE(0x0cf3, 0x7015),
 	  .driver_info = AR9287_USB },  /* Atheros */
@@ -1216,6 +1217,9 @@
 	u8 bulk_out_ep;
 	int r;
 
+	if (iface_desc->desc.bNumEndpoints < 2)
+		return -ENODEV;
+
 	/* Find bulk out endpoint */
 	for (r = 1; r >= 0; r--) {
 		endpoint = &iface_desc->endpoint[r].desc;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index a680a97..e428143 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1657,13 +1657,14 @@
 
 static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
-				  enum ieee80211_ampdu_mlme_action action,
-				  struct ieee80211_sta *sta,
-				  u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+				  struct ieee80211_ampdu_params *params)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath9k_htc_sta *ista;
 	int ret = 0;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
 
 	mutex_lock(&priv->mutex);
 	ath9k_htc_ps_wakeup(priv);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 2e2b92b..0f5672f 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -49,6 +49,10 @@
 module_param_named(blink, ath9k_led_blink, int, 0444);
 MODULE_PARM_DESC(blink, "Enable LED blink on activity");
 
+static int ath9k_led_active_high = -1;
+module_param_named(led_active_high, ath9k_led_active_high, int, 0444);
+MODULE_PARM_DESC(led_active_high, "Invert LED polarity");
+
 static int ath9k_btcoex_enable;
 module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
 MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
@@ -600,6 +604,9 @@
 	if (ret)
 		return ret;
 
+	if (ath9k_led_active_high != -1)
+		ah->config.led_active_high = ath9k_led_active_high == 1;
+
 	/*
 	 * Enable WLAN/BT RX Antenna diversity only when:
 	 *
@@ -612,6 +619,7 @@
 		common->bt_ant_diversity = 1;
 
 	spin_lock_init(&common->cc_lock);
+	spin_lock_init(&sc->intr_lock);
 	spin_lock_init(&sc->sc_serial_rw);
 	spin_lock_init(&sc->sc_pm_lock);
 	spin_lock_init(&sc->chan_lock);
@@ -862,8 +870,8 @@
 			hw->wiphy->interface_modes |=
 					BIT(NL80211_IFTYPE_P2P_DEVICE);
 
-			hw->wiphy->iface_combinations = if_comb;
-			hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
+		hw->wiphy->iface_combinations = if_comb;
+		hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
 	}
 
 	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index bba85d1..d937c39 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -805,21 +805,12 @@
 }
 EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
 
-void ath9k_hw_enable_interrupts(struct ath_hw *ah)
+static void __ath9k_hw_enable_interrupts(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 	u32 sync_default = AR_INTR_SYNC_DEFAULT;
 	u32 async_mask;
 
-	if (!(ah->imask & ATH9K_INT_GLOBAL))
-		return;
-
-	if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
-		ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
-			atomic_read(&ah->intr_ref_cnt));
-		return;
-	}
-
 	if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
 	    AR_SREV_9561(ah))
 		sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
@@ -841,6 +832,39 @@
 	ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
 		REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
 }
+
+void ath9k_hw_resume_interrupts(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!(ah->imask & ATH9K_INT_GLOBAL))
+		return;
+
+	if (atomic_read(&ah->intr_ref_cnt) != 0) {
+		ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
+			atomic_read(&ah->intr_ref_cnt));
+		return;
+	}
+
+	__ath9k_hw_enable_interrupts(ah);
+}
+EXPORT_SYMBOL(ath9k_hw_resume_interrupts);
+
+void ath9k_hw_enable_interrupts(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!(ah->imask & ATH9K_INT_GLOBAL))
+		return;
+
+	if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
+		ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
+			atomic_read(&ah->intr_ref_cnt));
+		return;
+	}
+
+	__ath9k_hw_enable_interrupts(ah);
+}
 EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
 
 void ath9k_hw_set_interrupts(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 7fbf7f9..1b63d26 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -748,6 +748,7 @@
 void ath9k_hw_enable_interrupts(struct ath_hw *ah);
 void ath9k_hw_disable_interrupts(struct ath_hw *ah);
 void ath9k_hw_kill_interrupts(struct ath_hw *ah);
+void ath9k_hw_resume_interrupts(struct ath_hw *ah);
 
 void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
 
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index d184e68..3abc645 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -373,21 +373,20 @@
 	struct ath_common *common = ath9k_hw_common(ah);
 	enum ath_reset_type type;
 	unsigned long flags;
-	u32 status = sc->intrstatus;
+	u32 status;
 	u32 rxmask;
 
+	spin_lock_irqsave(&sc->intr_lock, flags);
+	status = sc->intrstatus;
+	sc->intrstatus = 0;
+	spin_unlock_irqrestore(&sc->intr_lock, flags);
+
 	ath9k_ps_wakeup(sc);
 	spin_lock(&sc->sc_pcu_lock);
 
 	if (status & ATH9K_INT_FATAL) {
 		type = RESET_TYPE_FATAL_INT;
 		ath9k_queue_reset(sc, type);
-
-		/*
-		 * Increment the ref. counter here so that
-		 * interrupts are enabled in the reset routine.
-		 */
-		atomic_inc(&ah->intr_ref_cnt);
 		ath_dbg(common, RESET, "FATAL: Skipping interrupts\n");
 		goto out;
 	}
@@ -403,11 +402,6 @@
 			type = RESET_TYPE_BB_WATCHDOG;
 			ath9k_queue_reset(sc, type);
 
-			/*
-			 * Increment the ref. counter here so that
-			 * interrupts are enabled in the reset routine.
-			 */
-			atomic_inc(&ah->intr_ref_cnt);
 			ath_dbg(common, RESET,
 				"BB_WATCHDOG: Skipping interrupts\n");
 			goto out;
@@ -420,7 +414,6 @@
 		if ((sc->gtt_cnt >= MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) {
 			type = RESET_TYPE_TX_GTT;
 			ath9k_queue_reset(sc, type);
-			atomic_inc(&ah->intr_ref_cnt);
 			ath_dbg(common, RESET,
 				"GTT: Skipping interrupts\n");
 			goto out;
@@ -477,7 +470,7 @@
 	ath9k_btcoex_handle_interrupt(sc, status);
 
 	/* re-enable hardware interrupt */
-	ath9k_hw_enable_interrupts(ah);
+	ath9k_hw_resume_interrupts(ah);
 out:
 	spin_unlock(&sc->sc_pcu_lock);
 	ath9k_ps_restore(sc);
@@ -541,7 +534,9 @@
 		return IRQ_NONE;
 
 	/* Cache the status */
-	sc->intrstatus = status;
+	spin_lock(&sc->intr_lock);
+	sc->intrstatus |= status;
+	spin_unlock(&sc->intr_lock);
 
 	if (status & SCHED_INTR)
 		sched = true;
@@ -587,7 +582,7 @@
 
 	if (sched) {
 		/* turn off every interrupt */
-		ath9k_hw_disable_interrupts(ah);
+		ath9k_hw_kill_interrupts(ah);
 		tasklet_schedule(&sc->intr_tq);
 	}
 
@@ -1550,13 +1545,13 @@
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int ret = 0;
 
-	if (old_state == IEEE80211_STA_AUTH &&
-	    new_state == IEEE80211_STA_ASSOC) {
+	if (old_state == IEEE80211_STA_NOTEXIST &&
+	    new_state == IEEE80211_STA_NONE) {
 		ret = ath9k_sta_add(hw, vif, sta);
 		ath_dbg(common, CONFIG,
 			"Add station: %pM\n", sta->addr);
-	} else if (old_state == IEEE80211_STA_ASSOC &&
-		   new_state == IEEE80211_STA_AUTH) {
+	} else if (old_state == IEEE80211_STA_NONE &&
+		   new_state == IEEE80211_STA_NOTEXIST) {
 		ret = ath9k_sta_remove(hw, vif, sta);
 		ath_dbg(common, CONFIG,
 			"Remove station: %pM\n", sta->addr);
@@ -1860,14 +1855,16 @@
 
 static int ath9k_ampdu_action(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
-			      enum ieee80211_ampdu_mlme_action action,
-			      struct ieee80211_sta *sta,
-			      u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+			      struct ieee80211_ampdu_params *params)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	bool flush = false;
 	int ret = 0;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	mutex_lock(&sc->mutex);
 
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index e6fef1b..ea7b8c2 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -27,8 +27,17 @@
 	{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI   */
 	{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
 	{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI   */
+
+#ifdef CONFIG_ATH9K_PCOEM
+	/* Mini PCI AR9220 MB92 cards: Compex WLM200NX, Wistron DNMA-92 */
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x0029,
+			 PCI_VENDOR_ID_ATHEROS,
+			 0x2096),
+	  .driver_data = ATH9K_PCI_LED_ACT_HI },
+#endif
+
 	{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
-	{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
 
 #ifdef CONFIG_ATH9K_PCOEM
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
@@ -76,7 +85,11 @@
 			 0x10CF, /* Fujitsu */
 			 0x1536),
 	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+#endif
 
+	{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+
+#ifdef CONFIG_ATH9K_PCOEM
 	/* AR9285 card for Asus */
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
 			 0x002B,
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 19d3d64..4d1527a 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1413,10 +1413,12 @@
 
 static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
-				    enum ieee80211_ampdu_mlme_action action,
-				    struct ieee80211_sta *sta,
-				    u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+				    struct ieee80211_ampdu_params *params)
 {
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 	struct ar9170 *ar = hw->priv;
 	struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
 	struct carl9170_sta_tid *tid_info;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 7c169ab..a27279c 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -857,12 +857,14 @@
 
 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
 		    struct ieee80211_vif *vif,
-		    enum ieee80211_ampdu_mlme_action action,
-		    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-		    u8 buf_size, bool amsdu)
+		    struct ieee80211_ampdu_params *params)
 {
 	struct wcn36xx *wcn = hw->priv;
 	struct wcn36xx_sta *sta_priv = NULL;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
 		    action, tid);
diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig
deleted file mode 100755
index 8ecbfb2..0000000
--- a/drivers/net/wireless/bcmdhd/Kconfig
+++ /dev/null
@@ -1,44 +0,0 @@
-config BCMDHD
-	tristate "Broadcom FullMAC wireless cards support"
-	---help---
-	  This module adds support for wireless adapters based on
-	  Broadcom FullMAC chipset.
-
-	  If you choose to build a module, it'll be called dhd. Say M if
-	  unsure.
-
-config BCMDHD_SDIO
-	bool "SDIO bus interface support"
-	depends on BCMDHD && MMC
-
-config BCMDHD_PCIE
-	bool "PCIe bus interface support"
-	depends on BCMDHD && PCI && !BCMDHD_SDIO
-
-config BCMDHD_FW_PATH
-	depends on BCMDHD
-	string "Firmware path"
-	default "/system/vendor/firmware/fw_bcmdhd.bin"
-	---help---
-	  Path to the firmware file.
-
-config BCMDHD_NVRAM_PATH
-	depends on BCMDHD
-	string "NVRAM path"
-	default "/system/etc/wifi/bcmdhd.cal"
-	---help---
-	  Path to the calibration file.
-
-config DHD_USE_STATIC_BUF
-	bool "Enable memory preallocation"
-	depends on BCMDHD
-	default n
-	---help---
-	  Use memory preallocated in platform
-
-config DHD_USE_SCHED_SCAN
-	bool "Use CFG80211 sched scan"
-	depends on BCMDHD && CFG80211
-	default n
-	---help---
-	  Use CFG80211 sched scan
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
deleted file mode 100755
index 02baabf..0000000
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ /dev/null
@@ -1,89 +0,0 @@
-# bcmdhd
-#
-#
-#
-#
-#
-
-DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER               \
-	-DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE            \
-	-DDHDTHREAD -DDHD_DEBUG -DSHOW_EVENTS -DBCMDBG -DCUSTOMER_HW2 -DWLP2P \
-	-DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT                                \
-	-DKEEP_ALIVE -DGET_CUSTOM_MAC_ENABLE -DPKT_FILTER_SUPPORT             \
-	-DEMBEDDED_PLATFORM -DPNO_SUPPORT          \
-	-DDHD_USE_IDLECOUNT -DSET_RANDOM_MAC_SOFTAP -DROAM_ENABLE -DVSDB      \
-	-DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST                            \
-	-DESCAN_RESULT_PATCH -DSUPPORT_PM2_ONLY -DWLTDLS                      \
-	-DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DRXFRAME_THREAD       \
-	-DMIRACAST_AMPDU_SIZE=8	-DROAM_ENABLE	-DWL_IFACE_COMB_NUM_CHANNELS	\
-	-Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include   
-
-DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \
-	dhd_linux.o dhd_linux_platdev.o dhd_linux_sched.o dhd_pno.o \
-	dhd_common.o dhd_ip.o dhd_linux_wq.o dhd_custom_gpio.o \
-	bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o \
-	hnd_pktq.o hnd_pktpool.o
-
-obj-$(CONFIG_BCMDHD) += bcmdhd.o
-bcmdhd-objs += $(DHDOFILES)
-
-ifneq ($(CONFIG_CFG80211),)
-bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o dhd_cfg80211.o wl_cfg_btcoex.o
-DHDCFLAGS += -DWL_CFG80211 -DWL_CFG80211_STA_EVENT -DWL_ENABLE_P2P_IF
-DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65
-DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15
-DHDCFLAGS += -DCUSTOM_KEEP_ALIVE_SETTING=28000
-DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=7
-endif
-ifneq ($(CONFIG_DHD_USE_SCHED_SCAN),)
-DHDCFLAGS += -DWL_SCHED_SCAN
-endif
-EXTRA_CFLAGS = $(DHDCFLAGS)
-ifeq ($(CONFIG_BCMDHD),m)
-EXTRA_LDFLAGS += --strip-debug
-else
-DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD
-endif
-
-DHDCFLAGS += -DCONFIG_DTS
-
-#########################
-# Chip dependent feature
-#########################
-ifneq ($(CONFIG_BCM4339),)
-DHDCFLAGS += -DCUSTOM_GLOM_SETTING=8 -DCUSTOM_RXCHAIN=1
-DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128
-DHDCFLAGS += -DBCMSDIOH_TXGLOM -DCUSTOM_TXGLOM=1 -DBCMSDIOH_TXGLOM_HIGHSPEED
-DHDCFLAGS += -DCUSTOM_SDIO_F2_BLKSIZE=512
-DHDCFLAGS += -DDHDTCPACK_SUPPRESS
-DHDCFLAGS += -DUSE_WL_TXBF
-DHDCFLAGS += -DUSE_WL_FRAMEBURST
-DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=32
-DHDCFLAGS += -DPROP_TXSTATUS_VSDB
-DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32
-DHDCFLAGS += -DREPEAT_READFRAME
-DHDCFLAGS += -DROAM_AP_ENV_DETECTION
-endif
-
-bcmdhd-$(CONFIG_BCMDHD_SDIO) += \
-		bcmsdh.o \
-		bcmsdh_linux.o \
-		bcmsdh_sdmmc.o \
-		bcmsdh_sdmmc_linux.o \
-		dhd_sdio.o \
-		dhd_cdc.o \
-		dhd_wlfc.o
-bcmdhd-$(CONFIG_BCMDHD_PCIE) += \
-		dhd_pcie.o \
-		dhd_pcie_linux.o \
-		dhd_msgbuf.o \
-		dhd_log.o \
-		circularbuf.o \
-		pcie_core.o \
-		dhd_flowring.o
-ccflags-$(CONFIG_BCMDHD_SDIO) += \
-	-DSDTEST -DBDC -DDHD_BCMEVENTS -DPROP_TXSTATUS -DOOB_INTR_ONLY \
-	-DHW_OOB -DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DSDIO_CRC_ERROR_FIX \
-	-DCUSTOM_SDIO_F2_BLKSIZE=128 -DUSE_SDIOFIFO_IOVAR
-ccflags-$(CONFIG_BCMDHD_PCIE) += \
-	-DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1
diff --git a/drivers/net/wireless/bcmdhd/aiutils.c b/drivers/net/wireless/bcmdhd/aiutils.c
deleted file mode 100644
index 70b2b63..0000000
--- a/drivers/net/wireless/bcmdhd/aiutils.c
+++ /dev/null
@@ -1,1284 +0,0 @@
-/*
- * Misc utility routines for accessing chip-specific features
- * of the SiliconBackplane-based Broadcom chips.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: aiutils.c 607900 2015-12-22 13:38:53Z $
- */
-#include <bcm_cfg.h>
-#include <typedefs.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <hndsoc.h>
-#include <sbchipc.h>
-#include <pcicfg.h>
-
-#include "siutils_priv.h"
-
-#define BCM47162_DMP() (0)
-#define BCM5357_DMP() (0)
-#define BCM53573_DMP() (0)
-#define BCM4707_DMP() (0)
-#define PMU_DMP() (0)
-#define GCI_DMP() (0)
-#define remap_coreid(sih, coreid)	(coreid)
-#define remap_corerev(sih, corerev)	(corerev)
-
-/* EROM parsing */
-
-static uint32
-get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match)
-{
-	uint32 ent;
-	uint inv = 0, nom = 0;
-	uint32 size = 0;
-
-	while (TRUE) {
-		ent = R_REG(si_osh(sih), *eromptr);
-		(*eromptr)++;
-
-		if (mask == 0)
-			break;
-
-		if ((ent & ER_VALID) == 0) {
-			inv++;
-			continue;
-		}
-
-		if (ent == (ER_END | ER_VALID))
-			break;
-
-		if ((ent & mask) == match)
-			break;
-
-		/* escape condition related EROM size if it has invalid values */
-		size += sizeof(*eromptr);
-		if (size >= ER_SZ_MAX) {
-			SI_ERROR(("Failed to find end of EROM marker\n"));
-			break;
-		}
-
-		nom++;
-	}
-
-	SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent));
-	if (inv + nom) {
-		SI_VMSG(("  after %d invalid and %d non-matching entries\n", inv, nom));
-	}
-	return ent;
-}
-
-static uint32
-get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh,
-        uint32 *sizel, uint32 *sizeh)
-{
-	uint32 asd, sz, szd;
-
-	asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID);
-	if (((asd & ER_TAG1) != ER_ADD) ||
-	    (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) ||
-	    ((asd & AD_ST_MASK) != st)) {
-		/* This is not what we want, "push" it back */
-		(*eromptr)--;
-		return 0;
-	}
-	*addrl = asd & AD_ADDR_MASK;
-	if (asd & AD_AG32)
-		*addrh = get_erom_ent(sih, eromptr, 0, 0);
-	else
-		*addrh = 0;
-	*sizeh = 0;
-	sz = asd & AD_SZ_MASK;
-	if (sz == AD_SZ_SZD) {
-		szd = get_erom_ent(sih, eromptr, 0, 0);
-		*sizel = szd & SD_SZ_MASK;
-		if (szd & SD_SG32)
-			*sizeh = get_erom_ent(sih, eromptr, 0, 0);
-	} else
-		*sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
-
-	SI_VMSG(("  SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
-	        sp, ad, st, *sizeh, *sizel, *addrh, *addrl));
-
-	return asd;
-}
-
-static void
-ai_hwfixup(si_info_t *sii)
-{
-}
-
-
-/* parse the enumeration rom to identify all cores */
-void
-ai_scan(si_t *sih, void *regs, uint devid)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	chipcregs_t *cc = (chipcregs_t *)regs;
-	uint32 erombase, *eromptr, *eromlim;
-
-	erombase = R_REG(sii->osh, &cc->eromptr);
-
-	switch (BUSTYPE(sih->bustype)) {
-	case SI_BUS:
-		eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE);
-		break;
-
-	case PCI_BUS:
-		/* Set wrappers address */
-		sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE);
-
-		/* Now point the window at the erom */
-		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase);
-		eromptr = regs;
-		break;
-
-#ifdef BCMSDIO
-	case SPI_BUS:
-	case SDIO_BUS:
-		eromptr = (uint32 *)(uintptr)erombase;
-		break;
-#endif	/* BCMSDIO */
-
-	case PCMCIA_BUS:
-	default:
-		SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype));
-		ASSERT(0);
-		return;
-	}
-	eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32));
-
-	SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n",
-	         regs, erombase, eromptr, eromlim));
-	while (eromptr < eromlim) {
-		uint32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp;
-		uint32 mpd, asd, addrl, addrh, sizel, sizeh;
-		uint i, j, idx;
-		bool br;
-
-		br = FALSE;
-
-		/* Grok a component */
-		cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI);
-		if (cia == (ER_END | ER_VALID)) {
-			SI_VMSG(("Found END of erom after %d cores\n", sii->numcores));
-			ai_hwfixup(sii);
-			return;
-		}
-
-		cib = get_erom_ent(sih, &eromptr, 0, 0);
-
-		if ((cib & ER_TAG) != ER_CI) {
-			SI_ERROR(("CIA not followed by CIB\n"));
-			goto error;
-		}
-
-		cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT;
-		mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
-		crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
-		nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT;
-		nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT;
-		nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
-		nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
-
-#ifdef BCMDBG_SI
-		SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, "
-		         "nsw = %d, nmp = %d & nsp = %d\n",
-		         mfg, cid, crev, eromptr - 1, nmw, nsw, nmp, nsp));
-#else
-		BCM_REFERENCE(crev);
-#endif
-
-		if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0))
-			continue;
-		if ((nmw + nsw == 0)) {
-			/* A component which is not a core */
-			if (cid == OOB_ROUTER_CORE_ID) {
-				asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE,
-					&addrl, &addrh, &sizel, &sizeh);
-				if (asd != 0) {
-					sii->oob_router = addrl;
-				}
-			}
-			if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID &&
-				cid != PMU_CORE_ID && cid != GCI_CORE_ID)
-				continue;
-		}
-
-		idx = sii->numcores;
-
-		cores_info->cia[idx] = cia;
-		cores_info->cib[idx] = cib;
-		cores_info->coreid[idx] = remap_coreid(sih, cid);
-
-		for (i = 0; i < nmp; i++) {
-			mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
-			if ((mpd & ER_TAG) != ER_MP) {
-				SI_ERROR(("Not enough MP entries for component 0x%x\n", cid));
-				goto error;
-			}
-			SI_VMSG(("  Master port %d, mp: %d id: %d\n", i,
-			         (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT,
-			         (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT));
-		}
-
-		/* First Slave Address Descriptor should be port 0:
-		 * the main register space for the core
-		 */
-		asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
-		if (asd == 0) {
-			do {
-			/* Try again to see if it is a bridge */
-			asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
-			              &sizel, &sizeh);
-			if (asd != 0)
-				br = TRUE;
-			else {
-					if (br == TRUE) {
-						break;
-					}
-					else if ((addrh != 0) || (sizeh != 0) ||
-						(sizel != SI_CORE_SIZE)) {
-						SI_ERROR(("addrh = 0x%x\t sizeh = 0x%x\t size1 ="
-							"0x%x\n", addrh, sizeh, sizel));
-						SI_ERROR(("First Slave ASD for"
-							"core 0x%04x malformed "
-							"(0x%08x)\n", cid, asd));
-						goto error;
-					}
-				}
-			} while (1);
-		}
-		cores_info->coresba[idx] = addrl;
-		cores_info->coresba_size[idx] = sizel;
-		/* Get any more ASDs in port 0 */
-		j = 1;
-		do {
-			asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
-			              &sizel, &sizeh);
-			if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) {
-				cores_info->coresba2[idx] = addrl;
-				cores_info->coresba2_size[idx] = sizel;
-			}
-			j++;
-		} while (asd != 0);
-
-		/* Go through the ASDs for other slave ports */
-		for (i = 1; i < nsp; i++) {
-			j = 0;
-			do {
-				asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh,
-				              &sizel, &sizeh);
-
-				if (asd == 0)
-					break;
-				j++;
-			} while (1);
-			if (j == 0) {
-				SI_ERROR((" SP %d has no address descriptors\n", i));
-				goto error;
-			}
-		}
-
-		/* Now get master wrappers */
-		for (i = 0; i < nmw; i++) {
-			asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh,
-			              &sizel, &sizeh);
-			if (asd == 0) {
-				SI_ERROR(("Missing descriptor for MW %d\n", i));
-				goto error;
-			}
-			if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
-				SI_ERROR(("Master wrapper %d is not 4KB\n", i));
-				goto error;
-			}
-			if (i == 0)
-				cores_info->wrapba[idx] = addrl;
-			else if (i == 1)
-				cores_info->wrapba2[idx] = addrl;
-		}
-
-		/* And finally slave wrappers */
-		for (i = 0; i < nsw; i++) {
-			uint fwp = (nsp == 1) ? 0 : 1;
-			asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh,
-			              &sizel, &sizeh);
-
-			/* cache APB bridge wrapper address for set/clear timeout */
-			if ((mfg == MFGID_ARM) && (cid == APB_BRIDGE_ID)) {
-				ASSERT(sii->num_br < SI_MAXBR);
-				sii->br_wrapba[sii->num_br++] = addrl;
-			}
-			if (asd == 0) {
-				SI_ERROR(("Missing descriptor for SW %d\n", i));
-				goto error;
-			}
-			if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
-				SI_ERROR(("Slave wrapper %d is not 4KB\n", i));
-				goto error;
-			}
-			if ((nmw == 0) && (i == 0))
-				cores_info->wrapba[idx] = addrl;
-			else if ((nmw == 0) && (i == 1))
-				cores_info->wrapba2[idx] = addrl;
-		}
-
-
-		/* Don't record bridges */
-		if (br)
-			continue;
-
-		/* Done with core */
-		sii->numcores++;
-	}
-
-	SI_ERROR(("Reached end of erom without finding END"));
-
-error:
-	sii->numcores = 0;
-	return;
-}
-
-#define AI_SETCOREIDX_MAPSIZE(coreid) \
-	(((coreid) == NS_CCB_CORE_ID) ? 15 * SI_CORE_SIZE : SI_CORE_SIZE)
-
-/* This function changes the logical "focus" to the indicated core.
- * Return the current core's virtual address.
- */
-static void *
-_ai_setcoreidx(si_t *sih, uint coreidx, uint use_wrap2)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint32 addr, wrap, wrap2;
-	void *regs;
-
-	if (coreidx >= MIN(sii->numcores, SI_MAXCORES))
-		return (NULL);
-
-	addr = cores_info->coresba[coreidx];
-	wrap = cores_info->wrapba[coreidx];
-	wrap2 = cores_info->wrapba2[coreidx];
-
-	/*
-	 * If the user has provided an interrupt mask enabled function,
-	 * then assert interrupts are disabled before switching the core.
-	 */
-	ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg));
-
-	switch (BUSTYPE(sih->bustype)) {
-	case SI_BUS:
-		/* map new one */
-		if (!cores_info->regs[coreidx]) {
-			cores_info->regs[coreidx] = REG_MAP(addr,
-				AI_SETCOREIDX_MAPSIZE(cores_info->coreid[coreidx]));
-			ASSERT(GOODREGS(cores_info->regs[coreidx]));
-		}
-		sii->curmap = regs = cores_info->regs[coreidx];
-		if (!cores_info->wrappers[coreidx] && (wrap != 0)) {
-			cores_info->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
-			ASSERT(GOODREGS(cores_info->wrappers[coreidx]));
-		}
-		if (!cores_info->wrappers2[coreidx] && (wrap2 != 0)) {
-			cores_info->wrappers2[coreidx] = REG_MAP(wrap2, SI_CORE_SIZE);
-			ASSERT(GOODREGS(cores_info->wrappers2[coreidx]));
-		}
-		if (use_wrap2)
-			sii->curwrap = cores_info->wrappers2[coreidx];
-		else
-			sii->curwrap = cores_info->wrappers[coreidx];
-		break;
-
-	case PCI_BUS:
-		/* point bar0 window */
-		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, addr);
-		regs = sii->curmap;
-		/* point bar0 2nd 4KB window to the primary wrapper */
-		if (use_wrap2)
-			wrap = wrap2;
-		if (PCIE_GEN2(sii))
-			OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_WIN2, 4, wrap);
-		else
-			OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, wrap);
-		break;
-
-#ifdef BCMSDIO
-	case SPI_BUS:
-	case SDIO_BUS:
-		sii->curmap = regs = (void *)((uintptr)addr);
-		if (use_wrap2)
-			sii->curwrap = (void *)((uintptr)wrap2);
-		else
-			sii->curwrap = (void *)((uintptr)wrap);
-		break;
-#endif	/* BCMSDIO */
-
-	case PCMCIA_BUS:
-	default:
-		ASSERT(0);
-		regs = NULL;
-		break;
-	}
-
-	sii->curmap = regs;
-	sii->curidx = coreidx;
-
-	return regs;
-}
-
-void *
-ai_setcoreidx(si_t *sih, uint coreidx)
-{
-	return _ai_setcoreidx(sih, coreidx, 0);
-}
-
-void *
-ai_setcoreidx_2ndwrap(si_t *sih, uint coreidx)
-{
-	return _ai_setcoreidx(sih, coreidx, 1);
-}
-
-void
-ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	chipcregs_t *cc = NULL;
-	uint32 erombase, *eromptr, *eromlim;
-	uint i, j, cidx;
-	uint32 cia, cib, nmp, nsp;
-	uint32 asd, addrl, addrh, sizel, sizeh;
-
-	for (i = 0; i < sii->numcores; i++) {
-		if (cores_info->coreid[i] == CC_CORE_ID) {
-			cc = (chipcregs_t *)cores_info->regs[i];
-			break;
-		}
-	}
-	if (cc == NULL)
-		goto error;
-
-	erombase = R_REG(sii->osh, &cc->eromptr);
-	eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE);
-	eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32));
-
-	cidx = sii->curidx;
-	cia = cores_info->cia[cidx];
-	cib = cores_info->cib[cidx];
-
-	nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
-	nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
-
-	/* scan for cores */
-	while (eromptr < eromlim) {
-		if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) &&
-			(get_erom_ent(sih, &eromptr, 0, 0) == cib)) {
-			break;
-		}
-	}
-
-	/* skip master ports */
-	for (i = 0; i < nmp; i++)
-		get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
-
-	/* Skip ASDs in port 0 */
-	asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
-	if (asd == 0) {
-		/* Try again to see if it is a bridge */
-		asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
-		              &sizel, &sizeh);
-	}
-
-	j = 1;
-	do {
-		asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
-		              &sizel, &sizeh);
-		j++;
-	} while (asd != 0);
-
-	/* Go through the ASDs for other slave ports */
-	for (i = 1; i < nsp; i++) {
-		j = 0;
-		do {
-			asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh,
-				&sizel, &sizeh);
-			if (asd == 0)
-				break;
-
-			if (!asidx--) {
-				*addr = addrl;
-				*size = sizel;
-				return;
-			}
-			j++;
-		} while (1);
-
-		if (j == 0) {
-			SI_ERROR((" SP %d has no address descriptors\n", i));
-			break;
-		}
-	}
-
-error:
-	*size = 0;
-	return;
-}
-
-/* Return the number of address spaces in current core */
-int
-ai_numaddrspaces(si_t *sih)
-{
-	return 2;
-}
-
-/* Return the address of the nth address space in the current core */
-uint32
-ai_addrspace(si_t *sih, uint asidx)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint cidx;
-
-	cidx = sii->curidx;
-
-	if (asidx == 0)
-		return cores_info->coresba[cidx];
-	else if (asidx == 1)
-		return cores_info->coresba2[cidx];
-	else {
-		SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
-		          __FUNCTION__, asidx));
-		return 0;
-	}
-}
-
-/* Return the size of the nth address space in the current core */
-uint32
-ai_addrspacesize(si_t *sih, uint asidx)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint cidx;
-
-	cidx = sii->curidx;
-
-	if (asidx == 0)
-		return cores_info->coresba_size[cidx];
-	else if (asidx == 1)
-		return cores_info->coresba2_size[cidx];
-	else {
-		SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
-		          __FUNCTION__, asidx));
-		return 0;
-	}
-}
-
-uint
-ai_flag(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	aidmp_t *ai;
-
-	if (BCM47162_DMP()) {
-		SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
-		return sii->curidx;
-	}
-	if (BCM5357_DMP()) {
-		SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
-		return sii->curidx;
-	}
-	if (BCM4707_DMP()) {
-		SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
-			__FUNCTION__));
-		return sii->curidx;
-	}
-	if (BCM53573_DMP()) {
-		SI_ERROR(("%s: Attempting to read DMP registers on 53573\n", __FUNCTION__));
-		return sii->curidx;
-	}
-#ifdef REROUTE_OOBINT
-	if (PMU_DMP()) {
-		SI_ERROR(("%s: Attempting to read PMU DMP registers\n",
-			__FUNCTION__));
-		return PMU_OOB_BIT;
-	}
-#else
-	if (PMU_DMP()) {
-		uint idx, flag;
-		idx = sii->curidx;
-		ai_setcoreidx(sih, SI_CC_IDX);
-		flag = ai_flag_alt(sih);
-		ai_setcoreidx(sih, idx);
-		return flag;
-	}
-#endif /* REROUTE_OOBINT */
-
-	ai = sii->curwrap;
-	ASSERT(ai != NULL);
-
-	return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f);
-}
-
-uint
-ai_flag_alt(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	aidmp_t *ai;
-
-	if (BCM47162_DMP()) {
-		SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
-		return sii->curidx;
-	}
-	if (BCM5357_DMP()) {
-		SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
-		return sii->curidx;
-	}
-	if (BCM4707_DMP()) {
-		SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
-			__FUNCTION__));
-		return sii->curidx;
-	}
-#ifdef REROUTE_OOBINT
-	if (PMU_DMP()) {
-		SI_ERROR(("%s: Attempting to read PMU DMP registers\n",
-			__FUNCTION__));
-		return PMU_OOB_BIT;
-	}
-#endif /* REROUTE_OOBINT */
-
-	ai = sii->curwrap;
-
-	return ((R_REG(sii->osh, &ai->oobselouta30) >> AI_OOBSEL_1_SHIFT) & AI_OOBSEL_MASK);
-}
-
-void
-ai_setint(si_t *sih, int siflag)
-{
-}
-
-uint
-ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
-{
-	si_info_t *sii = SI_INFO(sih);
-	uint32 *map = (uint32 *) sii->curwrap;
-
-	if (mask || val) {
-		uint32 w = R_REG(sii->osh, map+(offset/4));
-		w &= ~mask;
-		w |= val;
-		W_REG(sii->osh, map+(offset/4), w);
-	}
-
-	return (R_REG(sii->osh, map+(offset/4)));
-}
-
-uint
-ai_corevendor(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint32 cia;
-
-	cia = cores_info->cia[sii->curidx];
-	return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT);
-}
-
-uint
-ai_corerev(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint32 cib;
-
-
-	cib = cores_info->cib[sii->curidx];
-	return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT);
-}
-
-bool
-ai_iscoreup(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	aidmp_t *ai;
-
-	ai = sii->curwrap;
-
-	return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) &&
-	        ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0));
-}
-
-/*
- * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
- * switch back to the original core, and return the new value.
- *
- * When using the silicon backplane, no fiddling with interrupts or core switches is needed.
- *
- * Also, when using pci/pcie, we can optimize away the core switching for pci registers
- * and (on newer pci cores) chipcommon registers.
- */
-uint
-ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
-{
-	uint origidx = 0;
-	uint32 *r = NULL;
-	uint w;
-	uint intr_val = 0;
-	bool fast = FALSE;
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-
-	ASSERT(GOODIDX(coreidx));
-	ASSERT(regoff < SI_CORE_SIZE);
-	ASSERT((val & ~mask) == 0);
-
-	if (coreidx >= SI_MAXCORES)
-		return 0;
-
-	if (BUSTYPE(sih->bustype) == SI_BUS) {
-		/* If internal bus, we can always get at everything */
-		fast = TRUE;
-		/* map if does not exist */
-		if (!cores_info->regs[coreidx]) {
-			cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
-			                            SI_CORE_SIZE);
-			ASSERT(GOODREGS(cores_info->regs[coreidx]));
-		}
-		r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
-	} else if (BUSTYPE(sih->bustype) == PCI_BUS) {
-		/* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
-
-		if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
-			/* Chipc registers are mapped at 12KB */
-
-			fast = TRUE;
-			r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
-		} else if (sii->pub.buscoreidx == coreidx) {
-			/* pci registers are at either in the last 2KB of an 8KB window
-			 * or, in pcie and pci rev 13 at 8KB
-			 */
-			fast = TRUE;
-			if (SI_FAST(sii))
-				r = (uint32 *)((char *)sii->curmap +
-				               PCI_16KB0_PCIREGS_OFFSET + regoff);
-			else
-				r = (uint32 *)((char *)sii->curmap +
-				               ((regoff >= SBCONFIGOFF) ?
-				                PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
-				               regoff);
-		}
-	}
-
-	if (!fast) {
-		INTR_OFF(sii, intr_val);
-
-		/* save current core index */
-		origidx = si_coreidx(&sii->pub);
-
-		/* switch core */
-		r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff);
-	}
-	ASSERT(r != NULL);
-
-	/* mask and set */
-	if (mask || val) {
-		w = (R_REG(sii->osh, r) & ~mask) | val;
-		W_REG(sii->osh, r, w);
-	}
-
-	/* readback */
-	w = R_REG(sii->osh, r);
-
-	if (!fast) {
-		/* restore core index */
-		if (origidx != coreidx)
-			ai_setcoreidx(&sii->pub, origidx);
-
-		INTR_RESTORE(sii, intr_val);
-	}
-
-	return (w);
-}
-
-/*
- * If there is no need for fiddling with interrupts or core switches (typically silicon
- * back plane registers, pci registers and chipcommon registers), this function
- * returns the register offset on this core to a mapped address. This address can
- * be used for W_REG/R_REG directly.
- *
- * For accessing registers that would need a core switch, this function will return
- * NULL.
- */
-uint32 *
-ai_corereg_addr(si_t *sih, uint coreidx, uint regoff)
-{
-	uint32 *r = NULL;
-	bool fast = FALSE;
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-
-	ASSERT(GOODIDX(coreidx));
-	ASSERT(regoff < SI_CORE_SIZE);
-
-	if (coreidx >= SI_MAXCORES)
-		return 0;
-
-	if (BUSTYPE(sih->bustype) == SI_BUS) {
-		/* If internal bus, we can always get at everything */
-		fast = TRUE;
-		/* map if does not exist */
-		if (!cores_info->regs[coreidx]) {
-			cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
-			                            SI_CORE_SIZE);
-			ASSERT(GOODREGS(cores_info->regs[coreidx]));
-		}
-		r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
-	} else if (BUSTYPE(sih->bustype) == PCI_BUS) {
-		/* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
-
-		if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
-			/* Chipc registers are mapped at 12KB */
-
-			fast = TRUE;
-			r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
-		} else if (sii->pub.buscoreidx == coreidx) {
-			/* pci registers are at either in the last 2KB of an 8KB window
-			 * or, in pcie and pci rev 13 at 8KB
-			 */
-			fast = TRUE;
-			if (SI_FAST(sii))
-				r = (uint32 *)((char *)sii->curmap +
-				               PCI_16KB0_PCIREGS_OFFSET + regoff);
-			else
-				r = (uint32 *)((char *)sii->curmap +
-				               ((regoff >= SBCONFIGOFF) ?
-				                PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
-				               regoff);
-		}
-	}
-
-	if (!fast) {
-		ASSERT(sii->curidx == coreidx);
-		r = (uint32*) ((uchar*)sii->curmap + regoff);
-	}
-
-	return (r);
-}
-
-void
-ai_core_disable(si_t *sih, uint32 bits)
-{
-	si_info_t *sii = SI_INFO(sih);
-	volatile uint32 dummy;
-	uint32 status;
-	aidmp_t *ai;
-
-
-	ASSERT(GOODREGS(sii->curwrap));
-	ai = sii->curwrap;
-
-	/* if core is already in reset, just return */
-	if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET)
-		return;
-
-	/* ensure there are no pending backplane operations */
-	SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
-
-	/* if pending backplane ops still, try waiting longer */
-	if (status != 0) {
-		/* 300usecs was sufficient to allow backplane ops to clear for big hammer */
-		/* during driver load we may need more time */
-		SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000);
-		/* if still pending ops, continue on and try disable anyway */
-		/* this is in big hammer path, so don't call wl_reinit in this case... */
-	}
-
-	W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
-	dummy = R_REG(sii->osh, &ai->resetctrl);
-	BCM_REFERENCE(dummy);
-	OSL_DELAY(1);
-
-	W_REG(sii->osh, &ai->ioctrl, bits);
-	dummy = R_REG(sii->osh, &ai->ioctrl);
-	BCM_REFERENCE(dummy);
-	OSL_DELAY(10);
-}
-
-/* reset and re-enable a core
- * inputs:
- * bits - core specific bits that are set during and after reset sequence
- * resetbits - core specific bits that are set only during reset sequence
- */
-static void
-_ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
-{
-	si_info_t *sii = SI_INFO(sih);
-	aidmp_t *ai;
-	volatile uint32 dummy;
-	uint loop_counter = 10;
-#ifdef CUSTOMER_HW4_DEBUG
-	printf("%s: bits: 0x%x, resetbits: 0x%x\n", __FUNCTION__, bits, resetbits);
-#endif
-
-	ASSERT(GOODREGS(sii->curwrap));
-	ai = sii->curwrap;
-
-	/* ensure there are no pending backplane operations */
-	SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
-#ifdef CUSTOMER_HW4_DEBUG
-	printf("%s: resetstatus: %p dummy: %x\n", __FUNCTION__, &ai->resetstatus, dummy);
-#endif
-
-
-	/* put core into reset state */
-#ifdef CUSTOMER_HW4_DEBUG
-	printf("%s: resetctrl: %p\n", __FUNCTION__, &ai->resetctrl);
-#endif
-	W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
-	OSL_DELAY(10);
-
-	/* ensure there are no pending backplane operations */
-	SPINWAIT((R_REG(sii->osh, &ai->resetstatus) != 0), 300);
-
-	W_REG(sii->osh, &ai->ioctrl, (bits | resetbits | SICF_FGC | SICF_CLOCK_EN));
-	dummy = R_REG(sii->osh, &ai->ioctrl);
-#ifdef CUSTOMER_HW4_DEBUG
-	printf("%s: ioctrl: %p dummy: 0x%x\n", __FUNCTION__, &ai->ioctrl, dummy);
-#endif
-	BCM_REFERENCE(dummy);
-
-	/* ensure there are no pending backplane operations */
-	SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
-
-
-	while (R_REG(sii->osh, &ai->resetctrl) != 0 && --loop_counter != 0) {
-		/* ensure there are no pending backplane operations */
-		SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
-
-
-		/* take core out of reset */
-		W_REG(sii->osh, &ai->resetctrl, 0);
-#ifdef CUSTOMER_HW4_DEBUG
-		printf("%s: loop_counter: %d resetstatus: %p resetctrl: %p\n",
-			__FUNCTION__, loop_counter, &ai->resetstatus, &ai->resetctrl);
-#endif
-
-		/* ensure there are no pending backplane operations */
-		SPINWAIT((R_REG(sii->osh, &ai->resetstatus) != 0), 300);
-	}
-
-
-	W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN));
-	dummy = R_REG(sii->osh, &ai->ioctrl);
-#ifdef CUSTOMER_HW4_DEBUG
-	printf("%s: ioctl: %p dummy: 0x%x\n", __FUNCTION__, &ai->ioctrl, dummy);
-#endif
-	BCM_REFERENCE(dummy);
-	OSL_DELAY(1);
-}
-
-void
-ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint idx = sii->curidx;
-
-	if (cores_info->wrapba2[idx] != 0) {
-		ai_setcoreidx_2ndwrap(sih, idx);
-		_ai_core_reset(sih, bits, resetbits);
-		ai_setcoreidx(sih, idx);
-	}
-
-	_ai_core_reset(sih, bits, resetbits);
-}
-
-void
-ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
-{
-	si_info_t *sii = SI_INFO(sih);
-	aidmp_t *ai;
-	uint32 w;
-
-
-	if (BCM47162_DMP()) {
-		SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
-		          __FUNCTION__));
-		return;
-	}
-	if (BCM5357_DMP()) {
-		SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
-		          __FUNCTION__));
-		return;
-	}
-	if (BCM4707_DMP()) {
-		SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
-			__FUNCTION__));
-		return;
-	}
-	if (PMU_DMP()) {
-		SI_ERROR(("%s: Accessing PMU DMP register (ioctrl)\n",
-			__FUNCTION__));
-		return;
-	}
-
-	ASSERT(GOODREGS(sii->curwrap));
-	ai = sii->curwrap;
-
-	ASSERT((val & ~mask) == 0);
-
-	if (mask || val) {
-		w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
-		W_REG(sii->osh, &ai->ioctrl, w);
-	}
-}
-
-uint32
-ai_core_cflags(si_t *sih, uint32 mask, uint32 val)
-{
-	si_info_t *sii = SI_INFO(sih);
-	aidmp_t *ai;
-	uint32 w;
-
-	if (BCM47162_DMP()) {
-		SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
-		          __FUNCTION__));
-		return 0;
-	}
-	if (BCM5357_DMP()) {
-		SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
-		          __FUNCTION__));
-		return 0;
-	}
-	if (BCM4707_DMP()) {
-		SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
-			__FUNCTION__));
-		return 0;
-	}
-
-	if (PMU_DMP()) {
-		SI_ERROR(("%s: Accessing PMU DMP register (ioctrl)\n",
-			__FUNCTION__));
-		return 0;
-	}
-	ASSERT(GOODREGS(sii->curwrap));
-	ai = sii->curwrap;
-
-	ASSERT((val & ~mask) == 0);
-
-	if (mask || val) {
-		w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
-		W_REG(sii->osh, &ai->ioctrl, w);
-	}
-
-	return R_REG(sii->osh, &ai->ioctrl);
-}
-
-uint32
-ai_core_sflags(si_t *sih, uint32 mask, uint32 val)
-{
-	si_info_t *sii = SI_INFO(sih);
-	aidmp_t *ai;
-	uint32 w;
-
-	if (BCM47162_DMP()) {
-		SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0",
-		          __FUNCTION__));
-		return 0;
-	}
-	if (BCM5357_DMP()) {
-		SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n",
-		          __FUNCTION__));
-		return 0;
-	}
-	if (BCM4707_DMP()) {
-		SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
-			__FUNCTION__));
-		return 0;
-	}
-	if (PMU_DMP()) {
-		SI_ERROR(("%s: Accessing PMU DMP register (ioctrl)\n",
-			__FUNCTION__));
-		return 0;
-	}
-
-	ASSERT(GOODREGS(sii->curwrap));
-	ai = sii->curwrap;
-
-	ASSERT((val & ~mask) == 0);
-	ASSERT((mask & ~SISF_CORE_BITS) == 0);
-
-	if (mask || val) {
-		w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val);
-		W_REG(sii->osh, &ai->iostatus, w);
-	}
-
-	return R_REG(sii->osh, &ai->iostatus);
-}
-
-#if defined(BCMDBG_PHYDUMP)
-/* print interesting aidmp registers */
-void
-ai_dumpregs(si_t *sih, struct bcmstrbuf *b)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	osl_t *osh;
-	aidmp_t *ai;
-	uint i;
-
-	osh = sii->osh;
-
-	for (i = 0; i < sii->numcores; i++) {
-		si_setcoreidx(&sii->pub, i);
-		ai = sii->curwrap;
-
-		bcm_bprintf(b, "core 0x%x: \n", cores_info->coreid[i]);
-		if (BCM47162_DMP()) {
-			bcm_bprintf(b, "Skipping mips74k in 47162a0\n");
-			continue;
-		}
-		if (BCM5357_DMP()) {
-			bcm_bprintf(b, "Skipping usb20h in 5357\n");
-			continue;
-		}
-		if (BCM4707_DMP()) {
-			bcm_bprintf(b, "Skipping chipcommonb in 4707\n");
-			continue;
-		}
-
-		if (PMU_DMP()) {
-			bcm_bprintf(b, "Skipping pmu core\n");
-			continue;
-		}
-
-		bcm_bprintf(b, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x"
-			    "ioctrlwidth 0x%x iostatuswidth 0x%x\n"
-			    "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x resetwriteid 0x%x\n"
-			    "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x"
-			    "errlogaddrlo 0x%x errlogaddrhi 0x%x\n"
-			    "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n"
-			    "intstatus 0x%x config 0x%x itcr 0x%x\n",
-			    R_REG(osh, &ai->ioctrlset),
-			    R_REG(osh, &ai->ioctrlclear),
-			    R_REG(osh, &ai->ioctrl),
-			    R_REG(osh, &ai->iostatus),
-			    R_REG(osh, &ai->ioctrlwidth),
-			    R_REG(osh, &ai->iostatuswidth),
-			    R_REG(osh, &ai->resetctrl),
-			    R_REG(osh, &ai->resetstatus),
-			    R_REG(osh, &ai->resetreadid),
-			    R_REG(osh, &ai->resetwriteid),
-			    R_REG(osh, &ai->errlogctrl),
-			    R_REG(osh, &ai->errlogdone),
-			    R_REG(osh, &ai->errlogstatus),
-			    R_REG(osh, &ai->errlogaddrlo),
-			    R_REG(osh, &ai->errlogaddrhi),
-			    R_REG(osh, &ai->errlogid),
-			    R_REG(osh, &ai->errloguser),
-			    R_REG(osh, &ai->errlogflags),
-			    R_REG(osh, &ai->intstatus),
-			    R_REG(osh, &ai->config),
-			    R_REG(osh, &ai->itcr));
-	}
-}
-#endif	
-
-
-void
-ai_enable_backplane_timeouts(si_t *sih)
-{
-#ifdef AXI_TIMEOUTS
-	si_info_t *sii = SI_INFO(sih);
-	aidmp_t *ai;
-	int i;
-
-	for (i = 0; i < sii->num_br; ++i) {
-		ai = (aidmp_t *) sii->br_wrapba[i];
-		W_REG(sii->osh, &ai->errlogctrl, (1 << AIELC_TO_ENAB_SHIFT) |
-		      ((AXI_TO_VAL << AIELC_TO_EXP_SHIFT) & AIELC_TO_EXP_MASK));
-	}
-#endif /* AXI_TIMEOUTS */
-}
-
-void
-ai_clear_backplane_to(si_t *sih)
-{
-#ifdef AXI_TIMEOUTS
-	si_info_t *sii = SI_INFO(sih);
-	aidmp_t *ai;
-	int i;
-	uint32 errlogstatus;
-
-	for (i = 0; i < sii->num_br; ++i) {
-		ai = (aidmp_t *) sii->br_wrapba[i];
-		/* check for backplane timeout & clear backplane hang */
-		errlogstatus = R_REG(sii->osh, &ai->errlogstatus);
-
-		if ((errlogstatus & AIELS_TIMEOUT_MASK) != 0) {
-			/* set ErrDone to clear the condition */
-			W_REG(sii->osh, &ai->errlogdone, AIELD_ERRDONE_MASK);
-
-			/* SPINWAIT on errlogstatus timeout status bits */
-			while (R_REG(sii->osh, &ai->errlogstatus) & AIELS_TIMEOUT_MASK)
-				;
-
-			/* only reset APB Bridge on timeout (not slave error, or dec error) */
-			switch (errlogstatus & AIELS_TIMEOUT_MASK) {
-			case 0x1:
-				printf("AXI slave error");
-				break;
-			case 0x2:
-				/* reset APB Bridge */
-				OR_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
-				/* sync write */
-				(void)R_REG(sii->osh, &ai->resetctrl);
-				/* clear Reset bit */
-				AND_REG(sii->osh, &ai->resetctrl, ~(AIRC_RESET));
-				/* sync write */
-				(void)R_REG(sii->osh, &ai->resetctrl);
-				printf("AXI timeout");
-				break;
-			case 0x3:
-				printf("AXI decode error");
-				break;
-			default:
-				;	/* should be impossible */
-			}
-			printf("; APB Bridge %d\n", i);
-			printf("\t errlog: lo 0x%08x, hi 0x%08x, id 0x%08x, flags 0x%08x",
-				R_REG(sii->osh, &ai->errlogaddrlo),
-				R_REG(sii->osh, &ai->errlogaddrhi),
-				R_REG(sii->osh, &ai->errlogid),
-				R_REG(sii->osh, &ai->errlogflags));
-			printf(", status 0x%08x\n", errlogstatus);
-		}
-	}
-#endif /* AXI_TIMEOUTS */
-}
diff --git a/drivers/net/wireless/bcmdhd/bcm_app_utils.c b/drivers/net/wireless/bcmdhd/bcm_app_utils.c
deleted file mode 100644
index d138849..0000000
--- a/drivers/net/wireless/bcmdhd/bcm_app_utils.c
+++ /dev/null
@@ -1,1012 +0,0 @@
-/*
- * Misc utility routines used by kernel or app-level.
- * Contents are wifi-specific, used by any kernel or app-level
- * software that might want wifi things as it grows.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcm_app_utils.c 547371 2015-04-08 12:51:39Z $
- */
-
-#include <typedefs.h>
-
-#ifdef BCMDRIVER
-#include <osl.h>
-#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
-#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
-#else /* BCMDRIVER */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#ifndef ASSERT
-#define ASSERT(exp)
-#endif
-#endif /* BCMDRIVER */
-#include <bcmwifi_channels.h>
-
-#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
-#include <bcmstdlib.h>	/* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
-#endif
-
-#include <bcmutils.h>
-#include <wlioctl.h>
-#include <wlioctl_utils.h>
-
-#ifndef BCMDRIVER
-/*	Take an array of measurments representing a single channel over time and return
-	a summary. Currently implemented as a simple average but could easily evolve
-	into more cpomplex alogrithms.
-*/
-cca_congest_channel_req_t *
-cca_per_chan_summary(cca_congest_channel_req_t *input, cca_congest_channel_req_t *avg, bool percent)
-{
-	int sec;
-	cca_congest_t totals;
-
-	totals.duration  = 0;
-	totals.congest_ibss  = 0;
-	totals.congest_obss  = 0;
-	totals.interference  = 0;
-	avg->num_secs = 0;
-
-	for (sec = 0; sec < input->num_secs; sec++) {
-		if (input->secs[sec].duration) {
-			totals.duration += input->secs[sec].duration;
-			totals.congest_ibss += input->secs[sec].congest_ibss;
-			totals.congest_obss += input->secs[sec].congest_obss;
-			totals.interference += input->secs[sec].interference;
-			avg->num_secs++;
-		}
-	}
-	avg->chanspec = input->chanspec;
-
-	if (!avg->num_secs || !totals.duration)
-		return (avg);
-
-	if (percent) {
-		avg->secs[0].duration = totals.duration / avg->num_secs;
-		avg->secs[0].congest_ibss = totals.congest_ibss * 100/totals.duration;
-		avg->secs[0].congest_obss = totals.congest_obss * 100/totals.duration;
-		avg->secs[0].interference = totals.interference * 100/totals.duration;
-	} else {
-		avg->secs[0].duration = totals.duration / avg->num_secs;
-		avg->secs[0].congest_ibss = totals.congest_ibss / avg->num_secs;
-		avg->secs[0].congest_obss = totals.congest_obss / avg->num_secs;
-		avg->secs[0].interference = totals.interference / avg->num_secs;
-	}
-
-	return (avg);
-}
-
-static void
-cca_info(uint8 *bitmap, int num_bits, int *left, int *bit_pos)
-{
-	int i;
-	for (*left = 0, i = 0; i < num_bits; i++) {
-		if (isset(bitmap, i)) {
-			(*left)++;
-			*bit_pos = i;
-		}
-	}
-}
-
-static uint8
-spec_to_chan(chanspec_t chspec)
-{
-	uint8 center_ch, edge, primary, sb;
-
-	center_ch = CHSPEC_CHANNEL(chspec);
-
-	if (CHSPEC_IS20(chspec)) {
-		return center_ch;
-	} else {
-		/* the lower edge of the wide channel is half the bw from
-		 * the center channel.
-		 */
-		if (CHSPEC_IS40(chspec)) {
-			edge = center_ch - CH_20MHZ_APART;
-		} else {
-			/* must be 80MHz (until we support more) */
-			ASSERT(CHSPEC_IS80(chspec));
-			edge = center_ch - CH_40MHZ_APART;
-		}
-
-		/* find the channel number of the lowest 20MHz primary channel */
-		primary = edge + CH_10MHZ_APART;
-
-		/* select the actual subband */
-		sb = (chspec & WL_CHANSPEC_CTL_SB_MASK) >> WL_CHANSPEC_CTL_SB_SHIFT;
-		primary = primary + sb * CH_20MHZ_APART;
-
-		return primary;
-	}
-}
-
-/*
-	Take an array of measumrements representing summaries of different channels.
-	Return a recomended channel.
-	Interference is evil, get rid of that first.
-	Then hunt for lowest Other bss traffic.
-	Don't forget that channels with low duration times may not have accurate readings.
-	For the moment, do not overwrite input array.
-*/
-int
-cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chanspec_t *answer)
-{
-	uint8 *bitmap = NULL;	/* 38 Max channels needs 5 bytes  = 40 */
-	int i, left, winner, ret_val = 0;
-	uint32 min_obss = 1 << 30;
-	uint bitmap_sz;
-
-	bitmap_sz = CEIL(num_chans, NBBY);
-	bitmap = (uint8 *)malloc(bitmap_sz);
-	if (bitmap == NULL) {
-		printf("unable to allocate memory\n");
-		return BCME_NOMEM;
-	}
-
-	memset(bitmap, 0, bitmap_sz);
-	/* Initially, all channels are up for consideration */
-	for (i = 0; i < num_chans; i++) {
-		if (input[i]->chanspec)
-			setbit(bitmap, i);
-	}
-	cca_info(bitmap, num_chans, &left, &i);
-	if (!left) {
-		ret_val = CCA_ERRNO_TOO_FEW;
-		goto f_exit;
-	}
-
-	/* Filter for 2.4 GHz Band */
-	if (flags & CCA_FLAG_2G_ONLY) {
-		for (i = 0; i < num_chans; i++) {
-			if (!CHSPEC_IS2G(input[i]->chanspec))
-				clrbit(bitmap, i);
-		}
-	}
-	cca_info(bitmap, num_chans, &left, &i);
-	if (!left) {
-		ret_val = CCA_ERRNO_BAND;
-		goto f_exit;
-	}
-
-	/* Filter for 5 GHz Band */
-	if (flags & CCA_FLAG_5G_ONLY) {
-		for (i = 0; i < num_chans; i++) {
-			if (!CHSPEC_IS5G(input[i]->chanspec))
-				clrbit(bitmap, i);
-		}
-	}
-	cca_info(bitmap, num_chans, &left, &i);
-	if (!left) {
-		ret_val = CCA_ERRNO_BAND;
-		goto f_exit;
-	}
-
-	/* Filter for Duration */
-	if (!(flags & CCA_FLAG_IGNORE_DURATION)) {
-		for (i = 0; i < num_chans; i++) {
-			if (input[i]->secs[0].duration < CCA_THRESH_MILLI)
-				clrbit(bitmap, i);
-		}
-	}
-	cca_info(bitmap, num_chans, &left, &i);
-	if (!left) {
-		ret_val = CCA_ERRNO_DURATION;
-		goto f_exit;
-	}
-
-	/* Filter for 1 6 11 on 2.4 Band */
-	if (flags &  CCA_FLAGS_PREFER_1_6_11) {
-		int tmp_channel = spec_to_chan(input[i]->chanspec);
-		int is2g = CHSPEC_IS2G(input[i]->chanspec);
-		for (i = 0; i < num_chans; i++) {
-			if (is2g && tmp_channel != 1 && tmp_channel != 6 && tmp_channel != 11)
-				clrbit(bitmap, i);
-		}
-	}
-	cca_info(bitmap, num_chans, &left, &i);
-	if (!left) {
-		ret_val = CCA_ERRNO_PREF_CHAN;
-		goto f_exit;
-	}
-
-	/* Toss high interference interference */
-	if (!(flags & CCA_FLAG_IGNORE_INTERFER)) {
-		for (i = 0; i < num_chans; i++) {
-			if (input[i]->secs[0].interference > CCA_THRESH_INTERFERE)
-				clrbit(bitmap, i);
-		}
-		cca_info(bitmap, num_chans, &left, &i);
-		if (!left) {
-			ret_val = CCA_ERRNO_INTERFER;
-			goto f_exit;
-		}
-	}
-
-	/* Now find lowest obss */
-	winner = 0;
-	for (i = 0; i < num_chans; i++) {
-		if (isset(bitmap, i) && input[i]->secs[0].congest_obss < min_obss) {
-			winner = i;
-			min_obss = input[i]->secs[0].congest_obss;
-		}
-	}
-	*answer = input[winner]->chanspec;
-	f_exit:
-	free(bitmap);	/* free the allocated memory for bitmap */
-	return ret_val;
-}
-#endif /* !BCMDRIVER */
-
-/* offset of cntmember by sizeof(uint32) from the first cnt variable, txframe. */
-#define IDX_IN_WL_CNT_VER_6_T(cntmember)		\
-	((OFFSETOF(wl_cnt_ver_6_t, cntmember) - OFFSETOF(wl_cnt_ver_6_t, txframe)) / sizeof(uint32))
-
-#define IDX_IN_WL_CNT_VER_11_T(cntmember)		\
-	((OFFSETOF(wl_cnt_ver_11_t, cntmember) - OFFSETOF(wl_cnt_ver_11_t, txframe))	\
-	/ sizeof(uint32))
-
-/* Exclude version and length fields */
-#define NUM_OF_CNT_IN_WL_CNT_VER_6_T	\
-	((sizeof(wl_cnt_ver_6_t) - 2 * sizeof(uint16)) / sizeof(uint32))
-/* Exclude macstat cnt variables. wl_cnt_ver_6_t only has 62 macstat cnt variables. */
-#define NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T			\
-	(NUM_OF_CNT_IN_WL_CNT_VER_6_T - (WL_CNT_MCST_VAR_NUM - 2))
-
-/* Exclude version and length fields */
-#define NUM_OF_CNT_IN_WL_CNT_VER_11_T	\
-	((sizeof(wl_cnt_ver_11_t) - 2 * sizeof(uint16)) / sizeof(uint32))
-/* Exclude 64 macstat cnt variables. */
-#define NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T		\
-	(NUM_OF_CNT_IN_WL_CNT_VER_11_T - WL_CNT_MCST_VAR_NUM)
-
-/* Index conversion table from wl_cnt_ver_6_t to wl_cnt_wlc_t */
-static const uint8 wlcntver6t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T] = {
-	IDX_IN_WL_CNT_VER_6_T(txframe),
-	IDX_IN_WL_CNT_VER_6_T(txbyte),
-	IDX_IN_WL_CNT_VER_6_T(txretrans),
-	IDX_IN_WL_CNT_VER_6_T(txerror),
-	IDX_IN_WL_CNT_VER_6_T(txctl),
-	IDX_IN_WL_CNT_VER_6_T(txprshort),
-	IDX_IN_WL_CNT_VER_6_T(txserr),
-	IDX_IN_WL_CNT_VER_6_T(txnobuf),
-	IDX_IN_WL_CNT_VER_6_T(txnoassoc),
-	IDX_IN_WL_CNT_VER_6_T(txrunt),
-	IDX_IN_WL_CNT_VER_6_T(txchit),
-	IDX_IN_WL_CNT_VER_6_T(txcmiss),
-	IDX_IN_WL_CNT_VER_6_T(txuflo),
-	IDX_IN_WL_CNT_VER_6_T(txphyerr),
-	IDX_IN_WL_CNT_VER_6_T(txphycrs),
-	IDX_IN_WL_CNT_VER_6_T(rxframe),
-	IDX_IN_WL_CNT_VER_6_T(rxbyte),
-	IDX_IN_WL_CNT_VER_6_T(rxerror),
-	IDX_IN_WL_CNT_VER_6_T(rxctl),
-	IDX_IN_WL_CNT_VER_6_T(rxnobuf),
-	IDX_IN_WL_CNT_VER_6_T(rxnondata),
-	IDX_IN_WL_CNT_VER_6_T(rxbadds),
-	IDX_IN_WL_CNT_VER_6_T(rxbadcm),
-	IDX_IN_WL_CNT_VER_6_T(rxfragerr),
-	IDX_IN_WL_CNT_VER_6_T(rxrunt),
-	IDX_IN_WL_CNT_VER_6_T(rxgiant),
-	IDX_IN_WL_CNT_VER_6_T(rxnoscb),
-	IDX_IN_WL_CNT_VER_6_T(rxbadproto),
-	IDX_IN_WL_CNT_VER_6_T(rxbadsrcmac),
-	IDX_IN_WL_CNT_VER_6_T(rxbadda),
-	IDX_IN_WL_CNT_VER_6_T(rxfilter),
-	IDX_IN_WL_CNT_VER_6_T(rxoflo),
-	IDX_IN_WL_CNT_VER_6_T(rxuflo),
-	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 1,
-	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 2,
-	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 3,
-	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 4,
-	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 5,
-	IDX_IN_WL_CNT_VER_6_T(d11cnt_txrts_off),
-	IDX_IN_WL_CNT_VER_6_T(d11cnt_rxcrc_off),
-	IDX_IN_WL_CNT_VER_6_T(d11cnt_txnocts_off),
-	IDX_IN_WL_CNT_VER_6_T(dmade),
-	IDX_IN_WL_CNT_VER_6_T(dmada),
-	IDX_IN_WL_CNT_VER_6_T(dmape),
-	IDX_IN_WL_CNT_VER_6_T(reset),
-	IDX_IN_WL_CNT_VER_6_T(tbtt),
-	IDX_IN_WL_CNT_VER_6_T(txdmawar),
-	IDX_IN_WL_CNT_VER_6_T(pkt_callback_reg_fail),
-	IDX_IN_WL_CNT_VER_6_T(txfrag),
-	IDX_IN_WL_CNT_VER_6_T(txmulti),
-	IDX_IN_WL_CNT_VER_6_T(txfail),
-	IDX_IN_WL_CNT_VER_6_T(txretry),
-	IDX_IN_WL_CNT_VER_6_T(txretrie),
-	IDX_IN_WL_CNT_VER_6_T(rxdup),
-	IDX_IN_WL_CNT_VER_6_T(txrts),
-	IDX_IN_WL_CNT_VER_6_T(txnocts),
-	IDX_IN_WL_CNT_VER_6_T(txnoack),
-	IDX_IN_WL_CNT_VER_6_T(rxfrag),
-	IDX_IN_WL_CNT_VER_6_T(rxmulti),
-	IDX_IN_WL_CNT_VER_6_T(rxcrc),
-	IDX_IN_WL_CNT_VER_6_T(txfrmsnt),
-	IDX_IN_WL_CNT_VER_6_T(rxundec),
-	IDX_IN_WL_CNT_VER_6_T(tkipmicfaill),
-	IDX_IN_WL_CNT_VER_6_T(tkipcntrmsr),
-	IDX_IN_WL_CNT_VER_6_T(tkipreplay),
-	IDX_IN_WL_CNT_VER_6_T(ccmpfmterr),
-	IDX_IN_WL_CNT_VER_6_T(ccmpreplay),
-	IDX_IN_WL_CNT_VER_6_T(ccmpundec),
-	IDX_IN_WL_CNT_VER_6_T(fourwayfail),
-	IDX_IN_WL_CNT_VER_6_T(wepundec),
-	IDX_IN_WL_CNT_VER_6_T(wepicverr),
-	IDX_IN_WL_CNT_VER_6_T(decsuccess),
-	IDX_IN_WL_CNT_VER_6_T(tkipicverr),
-	IDX_IN_WL_CNT_VER_6_T(wepexcluded),
-	IDX_IN_WL_CNT_VER_6_T(txchanrej),
-	IDX_IN_WL_CNT_VER_6_T(psmwds),
-	IDX_IN_WL_CNT_VER_6_T(phywatchdog),
-	IDX_IN_WL_CNT_VER_6_T(prq_entries_handled),
-	IDX_IN_WL_CNT_VER_6_T(prq_undirected_entries),
-	IDX_IN_WL_CNT_VER_6_T(prq_bad_entries),
-	IDX_IN_WL_CNT_VER_6_T(atim_suppress_count),
-	IDX_IN_WL_CNT_VER_6_T(bcn_template_not_ready),
-	IDX_IN_WL_CNT_VER_6_T(bcn_template_not_ready_done),
-	IDX_IN_WL_CNT_VER_6_T(late_tbtt_dpc),
-	IDX_IN_WL_CNT_VER_6_T(rx1mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx2mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx5mbps5),
-	IDX_IN_WL_CNT_VER_6_T(rx6mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx9mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx11mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx12mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx18mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx24mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx36mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx48mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx54mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx108mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx162mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx216mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx270mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx324mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx378mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx432mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx486mbps),
-	IDX_IN_WL_CNT_VER_6_T(rx540mbps),
-	IDX_IN_WL_CNT_VER_6_T(rfdisable),
-	IDX_IN_WL_CNT_VER_6_T(txexptime),
-	IDX_IN_WL_CNT_VER_6_T(txmpdu_sgi),
-	IDX_IN_WL_CNT_VER_6_T(rxmpdu_sgi),
-	IDX_IN_WL_CNT_VER_6_T(txmpdu_stbc),
-	IDX_IN_WL_CNT_VER_6_T(rxmpdu_stbc),
-	IDX_IN_WL_CNT_VER_6_T(rxundec_mcst),
-	IDX_IN_WL_CNT_VER_6_T(tkipmicfaill_mcst),
-	IDX_IN_WL_CNT_VER_6_T(tkipcntrmsr_mcst),
-	IDX_IN_WL_CNT_VER_6_T(tkipreplay_mcst),
-	IDX_IN_WL_CNT_VER_6_T(ccmpfmterr_mcst),
-	IDX_IN_WL_CNT_VER_6_T(ccmpreplay_mcst),
-	IDX_IN_WL_CNT_VER_6_T(ccmpundec_mcst),
-	IDX_IN_WL_CNT_VER_6_T(fourwayfail_mcst),
-	IDX_IN_WL_CNT_VER_6_T(wepundec_mcst),
-	IDX_IN_WL_CNT_VER_6_T(wepicverr_mcst),
-	IDX_IN_WL_CNT_VER_6_T(decsuccess_mcst),
-	IDX_IN_WL_CNT_VER_6_T(tkipicverr_mcst),
-	IDX_IN_WL_CNT_VER_6_T(wepexcluded_mcst)
-};
-
-/* Index conversion table from wl_cnt_ver_11_t to wl_cnt_wlc_t */
-static const uint8 wlcntver11t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T] = {
-	IDX_IN_WL_CNT_VER_11_T(txframe),
-	IDX_IN_WL_CNT_VER_11_T(txbyte),
-	IDX_IN_WL_CNT_VER_11_T(txretrans),
-	IDX_IN_WL_CNT_VER_11_T(txerror),
-	IDX_IN_WL_CNT_VER_11_T(txctl),
-	IDX_IN_WL_CNT_VER_11_T(txprshort),
-	IDX_IN_WL_CNT_VER_11_T(txserr),
-	IDX_IN_WL_CNT_VER_11_T(txnobuf),
-	IDX_IN_WL_CNT_VER_11_T(txnoassoc),
-	IDX_IN_WL_CNT_VER_11_T(txrunt),
-	IDX_IN_WL_CNT_VER_11_T(txchit),
-	IDX_IN_WL_CNT_VER_11_T(txcmiss),
-	IDX_IN_WL_CNT_VER_11_T(txuflo),
-	IDX_IN_WL_CNT_VER_11_T(txphyerr),
-	IDX_IN_WL_CNT_VER_11_T(txphycrs),
-	IDX_IN_WL_CNT_VER_11_T(rxframe),
-	IDX_IN_WL_CNT_VER_11_T(rxbyte),
-	IDX_IN_WL_CNT_VER_11_T(rxerror),
-	IDX_IN_WL_CNT_VER_11_T(rxctl),
-	IDX_IN_WL_CNT_VER_11_T(rxnobuf),
-	IDX_IN_WL_CNT_VER_11_T(rxnondata),
-	IDX_IN_WL_CNT_VER_11_T(rxbadds),
-	IDX_IN_WL_CNT_VER_11_T(rxbadcm),
-	IDX_IN_WL_CNT_VER_11_T(rxfragerr),
-	IDX_IN_WL_CNT_VER_11_T(rxrunt),
-	IDX_IN_WL_CNT_VER_11_T(rxgiant),
-	IDX_IN_WL_CNT_VER_11_T(rxnoscb),
-	IDX_IN_WL_CNT_VER_11_T(rxbadproto),
-	IDX_IN_WL_CNT_VER_11_T(rxbadsrcmac),
-	IDX_IN_WL_CNT_VER_11_T(rxbadda),
-	IDX_IN_WL_CNT_VER_11_T(rxfilter),
-	IDX_IN_WL_CNT_VER_11_T(rxoflo),
-	IDX_IN_WL_CNT_VER_11_T(rxuflo),
-	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 1,
-	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 2,
-	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 3,
-	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 4,
-	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 5,
-	IDX_IN_WL_CNT_VER_11_T(d11cnt_txrts_off),
-	IDX_IN_WL_CNT_VER_11_T(d11cnt_rxcrc_off),
-	IDX_IN_WL_CNT_VER_11_T(d11cnt_txnocts_off),
-	IDX_IN_WL_CNT_VER_11_T(dmade),
-	IDX_IN_WL_CNT_VER_11_T(dmada),
-	IDX_IN_WL_CNT_VER_11_T(dmape),
-	IDX_IN_WL_CNT_VER_11_T(reset),
-	IDX_IN_WL_CNT_VER_11_T(tbtt),
-	IDX_IN_WL_CNT_VER_11_T(txdmawar),
-	IDX_IN_WL_CNT_VER_11_T(pkt_callback_reg_fail),
-	IDX_IN_WL_CNT_VER_11_T(txfrag),
-	IDX_IN_WL_CNT_VER_11_T(txmulti),
-	IDX_IN_WL_CNT_VER_11_T(txfail),
-	IDX_IN_WL_CNT_VER_11_T(txretry),
-	IDX_IN_WL_CNT_VER_11_T(txretrie),
-	IDX_IN_WL_CNT_VER_11_T(rxdup),
-	IDX_IN_WL_CNT_VER_11_T(txrts),
-	IDX_IN_WL_CNT_VER_11_T(txnocts),
-	IDX_IN_WL_CNT_VER_11_T(txnoack),
-	IDX_IN_WL_CNT_VER_11_T(rxfrag),
-	IDX_IN_WL_CNT_VER_11_T(rxmulti),
-	IDX_IN_WL_CNT_VER_11_T(rxcrc),
-	IDX_IN_WL_CNT_VER_11_T(txfrmsnt),
-	IDX_IN_WL_CNT_VER_11_T(rxundec),
-	IDX_IN_WL_CNT_VER_11_T(tkipmicfaill),
-	IDX_IN_WL_CNT_VER_11_T(tkipcntrmsr),
-	IDX_IN_WL_CNT_VER_11_T(tkipreplay),
-	IDX_IN_WL_CNT_VER_11_T(ccmpfmterr),
-	IDX_IN_WL_CNT_VER_11_T(ccmpreplay),
-	IDX_IN_WL_CNT_VER_11_T(ccmpundec),
-	IDX_IN_WL_CNT_VER_11_T(fourwayfail),
-	IDX_IN_WL_CNT_VER_11_T(wepundec),
-	IDX_IN_WL_CNT_VER_11_T(wepicverr),
-	IDX_IN_WL_CNT_VER_11_T(decsuccess),
-	IDX_IN_WL_CNT_VER_11_T(tkipicverr),
-	IDX_IN_WL_CNT_VER_11_T(wepexcluded),
-	IDX_IN_WL_CNT_VER_11_T(txchanrej),
-	IDX_IN_WL_CNT_VER_11_T(psmwds),
-	IDX_IN_WL_CNT_VER_11_T(phywatchdog),
-	IDX_IN_WL_CNT_VER_11_T(prq_entries_handled),
-	IDX_IN_WL_CNT_VER_11_T(prq_undirected_entries),
-	IDX_IN_WL_CNT_VER_11_T(prq_bad_entries),
-	IDX_IN_WL_CNT_VER_11_T(atim_suppress_count),
-	IDX_IN_WL_CNT_VER_11_T(bcn_template_not_ready),
-	IDX_IN_WL_CNT_VER_11_T(bcn_template_not_ready_done),
-	IDX_IN_WL_CNT_VER_11_T(late_tbtt_dpc),
-	IDX_IN_WL_CNT_VER_11_T(rx1mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx2mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx5mbps5),
-	IDX_IN_WL_CNT_VER_11_T(rx6mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx9mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx11mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx12mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx18mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx24mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx36mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx48mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx54mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx108mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx162mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx216mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx270mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx324mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx378mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx432mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx486mbps),
-	IDX_IN_WL_CNT_VER_11_T(rx540mbps),
-	IDX_IN_WL_CNT_VER_11_T(rfdisable),
-	IDX_IN_WL_CNT_VER_11_T(txexptime),
-	IDX_IN_WL_CNT_VER_11_T(txmpdu_sgi),
-	IDX_IN_WL_CNT_VER_11_T(rxmpdu_sgi),
-	IDX_IN_WL_CNT_VER_11_T(txmpdu_stbc),
-	IDX_IN_WL_CNT_VER_11_T(rxmpdu_stbc),
-	IDX_IN_WL_CNT_VER_11_T(rxundec_mcst),
-	IDX_IN_WL_CNT_VER_11_T(tkipmicfaill_mcst),
-	IDX_IN_WL_CNT_VER_11_T(tkipcntrmsr_mcst),
-	IDX_IN_WL_CNT_VER_11_T(tkipreplay_mcst),
-	IDX_IN_WL_CNT_VER_11_T(ccmpfmterr_mcst),
-	IDX_IN_WL_CNT_VER_11_T(ccmpreplay_mcst),
-	IDX_IN_WL_CNT_VER_11_T(ccmpundec_mcst),
-	IDX_IN_WL_CNT_VER_11_T(fourwayfail_mcst),
-	IDX_IN_WL_CNT_VER_11_T(wepundec_mcst),
-	IDX_IN_WL_CNT_VER_11_T(wepicverr_mcst),
-	IDX_IN_WL_CNT_VER_11_T(decsuccess_mcst),
-	IDX_IN_WL_CNT_VER_11_T(tkipicverr_mcst),
-	IDX_IN_WL_CNT_VER_11_T(wepexcluded_mcst),
-	IDX_IN_WL_CNT_VER_11_T(dma_hang),
-	IDX_IN_WL_CNT_VER_11_T(reinit),
-	IDX_IN_WL_CNT_VER_11_T(pstatxucast),
-	IDX_IN_WL_CNT_VER_11_T(pstatxnoassoc),
-	IDX_IN_WL_CNT_VER_11_T(pstarxucast),
-	IDX_IN_WL_CNT_VER_11_T(pstarxbcmc),
-	IDX_IN_WL_CNT_VER_11_T(pstatxbcmc),
-	IDX_IN_WL_CNT_VER_11_T(cso_passthrough),
-	IDX_IN_WL_CNT_VER_11_T(cso_normal),
-	IDX_IN_WL_CNT_VER_11_T(chained),
-	IDX_IN_WL_CNT_VER_11_T(chainedsz1),
-	IDX_IN_WL_CNT_VER_11_T(unchained),
-	IDX_IN_WL_CNT_VER_11_T(maxchainsz),
-	IDX_IN_WL_CNT_VER_11_T(currchainsz),
-	IDX_IN_WL_CNT_VER_11_T(pciereset),
-	IDX_IN_WL_CNT_VER_11_T(cfgrestore),
-	IDX_IN_WL_CNT_VER_11_T(reinitreason),
-	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 1,
-	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 2,
-	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 3,
-	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 4,
-	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 5,
-	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 6,
-	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 7,
-	IDX_IN_WL_CNT_VER_11_T(rxrtry),
-	IDX_IN_WL_CNT_VER_11_T(rxmpdu_mu),
-	IDX_IN_WL_CNT_VER_11_T(txbar),
-	IDX_IN_WL_CNT_VER_11_T(rxbar),
-	IDX_IN_WL_CNT_VER_11_T(txpspoll),
-	IDX_IN_WL_CNT_VER_11_T(rxpspoll),
-	IDX_IN_WL_CNT_VER_11_T(txnull),
-	IDX_IN_WL_CNT_VER_11_T(rxnull),
-	IDX_IN_WL_CNT_VER_11_T(txqosnull),
-	IDX_IN_WL_CNT_VER_11_T(rxqosnull),
-	IDX_IN_WL_CNT_VER_11_T(txassocreq),
-	IDX_IN_WL_CNT_VER_11_T(rxassocreq),
-	IDX_IN_WL_CNT_VER_11_T(txreassocreq),
-	IDX_IN_WL_CNT_VER_11_T(rxreassocreq),
-	IDX_IN_WL_CNT_VER_11_T(txdisassoc),
-	IDX_IN_WL_CNT_VER_11_T(rxdisassoc),
-	IDX_IN_WL_CNT_VER_11_T(txassocrsp),
-	IDX_IN_WL_CNT_VER_11_T(rxassocrsp),
-	IDX_IN_WL_CNT_VER_11_T(txreassocrsp),
-	IDX_IN_WL_CNT_VER_11_T(rxreassocrsp),
-	IDX_IN_WL_CNT_VER_11_T(txauth),
-	IDX_IN_WL_CNT_VER_11_T(rxauth),
-	IDX_IN_WL_CNT_VER_11_T(txdeauth),
-	IDX_IN_WL_CNT_VER_11_T(rxdeauth),
-	IDX_IN_WL_CNT_VER_11_T(txprobereq),
-	IDX_IN_WL_CNT_VER_11_T(rxprobereq),
-	IDX_IN_WL_CNT_VER_11_T(txprobersp),
-	IDX_IN_WL_CNT_VER_11_T(rxprobersp),
-	IDX_IN_WL_CNT_VER_11_T(txaction),
-	IDX_IN_WL_CNT_VER_11_T(rxaction)
-};
-
-/* Index conversion table from wl_cnt_ver_11_t to
- * either wl_cnt_ge40mcst_v1_t or wl_cnt_lt40mcst_v1_t
- */
-static const uint8 wlcntver11t_to_wlcntXX40mcstv1t[WL_CNT_MCST_VAR_NUM] = {
-	IDX_IN_WL_CNT_VER_11_T(txallfrm),
-	IDX_IN_WL_CNT_VER_11_T(txrtsfrm),
-	IDX_IN_WL_CNT_VER_11_T(txctsfrm),
-	IDX_IN_WL_CNT_VER_11_T(txackfrm),
-	IDX_IN_WL_CNT_VER_11_T(txdnlfrm),
-	IDX_IN_WL_CNT_VER_11_T(txbcnfrm),
-	IDX_IN_WL_CNT_VER_11_T(txfunfl),
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 1,
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 2,
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 3,
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 4,
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 5,
-	IDX_IN_WL_CNT_VER_11_T(txfbw),
-	IDX_IN_WL_CNT_VER_11_T(txmpdu),
-	IDX_IN_WL_CNT_VER_11_T(txtplunfl),
-	IDX_IN_WL_CNT_VER_11_T(txphyerror),
-	IDX_IN_WL_CNT_VER_11_T(pktengrxducast),
-	IDX_IN_WL_CNT_VER_11_T(pktengrxdmcast),
-	IDX_IN_WL_CNT_VER_11_T(rxfrmtoolong),
-	IDX_IN_WL_CNT_VER_11_T(rxfrmtooshrt),
-	IDX_IN_WL_CNT_VER_11_T(rxinvmachdr),
-	IDX_IN_WL_CNT_VER_11_T(rxbadfcs),
-	IDX_IN_WL_CNT_VER_11_T(rxbadplcp),
-	IDX_IN_WL_CNT_VER_11_T(rxcrsglitch),
-	IDX_IN_WL_CNT_VER_11_T(rxstrt),
-	IDX_IN_WL_CNT_VER_11_T(rxdfrmucastmbss),
-	IDX_IN_WL_CNT_VER_11_T(rxmfrmucastmbss),
-	IDX_IN_WL_CNT_VER_11_T(rxcfrmucast),
-	IDX_IN_WL_CNT_VER_11_T(rxrtsucast),
-	IDX_IN_WL_CNT_VER_11_T(rxctsucast),
-	IDX_IN_WL_CNT_VER_11_T(rxackucast),
-	IDX_IN_WL_CNT_VER_11_T(rxdfrmocast),
-	IDX_IN_WL_CNT_VER_11_T(rxmfrmocast),
-	IDX_IN_WL_CNT_VER_11_T(rxcfrmocast),
-	IDX_IN_WL_CNT_VER_11_T(rxrtsocast),
-	IDX_IN_WL_CNT_VER_11_T(rxctsocast),
-	IDX_IN_WL_CNT_VER_11_T(rxdfrmmcast),
-	IDX_IN_WL_CNT_VER_11_T(rxmfrmmcast),
-	IDX_IN_WL_CNT_VER_11_T(rxcfrmmcast),
-	IDX_IN_WL_CNT_VER_11_T(rxbeaconmbss),
-	IDX_IN_WL_CNT_VER_11_T(rxdfrmucastobss),
-	IDX_IN_WL_CNT_VER_11_T(rxbeaconobss),
-	IDX_IN_WL_CNT_VER_11_T(rxrsptmout),
-	IDX_IN_WL_CNT_VER_11_T(bcntxcancl),
-	IDX_IN_WL_CNT_VER_11_T(rxnodelim),
-	IDX_IN_WL_CNT_VER_11_T(rxf0ovfl),
-	IDX_IN_WL_CNT_VER_11_T(rxf1ovfl),
-	IDX_IN_WL_CNT_VER_11_T(rxf2ovfl),
-	IDX_IN_WL_CNT_VER_11_T(txsfovfl),
-	IDX_IN_WL_CNT_VER_11_T(pmqovfl),
-	IDX_IN_WL_CNT_VER_11_T(rxcgprqfrm),
-	IDX_IN_WL_CNT_VER_11_T(rxcgprsqovfl),
-	IDX_IN_WL_CNT_VER_11_T(txcgprsfail),
-	IDX_IN_WL_CNT_VER_11_T(txcgprssuc),
-	IDX_IN_WL_CNT_VER_11_T(prs_timeout),
-	IDX_IN_WL_CNT_VER_11_T(rxnack),
-	IDX_IN_WL_CNT_VER_11_T(frmscons),
-	IDX_IN_WL_CNT_VER_11_T(txnack),
-	IDX_IN_WL_CNT_VER_11_T(rxback),
-	IDX_IN_WL_CNT_VER_11_T(txback),
-	IDX_IN_WL_CNT_VER_11_T(bphy_rxcrsglitch),
-	IDX_IN_WL_CNT_VER_11_T(rxdrop20s),
-	IDX_IN_WL_CNT_VER_11_T(rxtoolate),
-	IDX_IN_WL_CNT_VER_11_T(bphy_badplcp)
-};
-
-/* For mcst offsets that were not used. (2 Pads) */
-#define INVALID_MCST_IDX ((uint8)(-1))
-/* Index conversion table from wl_cnt_ver_11_t to wl_cnt_v_le10_mcst_t */
-static const uint8 wlcntver11t_to_wlcntvle10mcstt[WL_CNT_MCST_VAR_NUM] = {
-	IDX_IN_WL_CNT_VER_11_T(txallfrm),
-	IDX_IN_WL_CNT_VER_11_T(txrtsfrm),
-	IDX_IN_WL_CNT_VER_11_T(txctsfrm),
-	IDX_IN_WL_CNT_VER_11_T(txackfrm),
-	IDX_IN_WL_CNT_VER_11_T(txdnlfrm),
-	IDX_IN_WL_CNT_VER_11_T(txbcnfrm),
-	IDX_IN_WL_CNT_VER_11_T(txfunfl),
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 1,
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 2,
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 3,
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 4,
-	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 5,
-	IDX_IN_WL_CNT_VER_11_T(txfbw),
-	INVALID_MCST_IDX,
-	IDX_IN_WL_CNT_VER_11_T(txtplunfl),
-	IDX_IN_WL_CNT_VER_11_T(txphyerror),
-	IDX_IN_WL_CNT_VER_11_T(pktengrxducast),
-	IDX_IN_WL_CNT_VER_11_T(pktengrxdmcast),
-	IDX_IN_WL_CNT_VER_11_T(rxfrmtoolong),
-	IDX_IN_WL_CNT_VER_11_T(rxfrmtooshrt),
-	IDX_IN_WL_CNT_VER_11_T(rxinvmachdr),
-	IDX_IN_WL_CNT_VER_11_T(rxbadfcs),
-	IDX_IN_WL_CNT_VER_11_T(rxbadplcp),
-	IDX_IN_WL_CNT_VER_11_T(rxcrsglitch),
-	IDX_IN_WL_CNT_VER_11_T(rxstrt),
-	IDX_IN_WL_CNT_VER_11_T(rxdfrmucastmbss),
-	IDX_IN_WL_CNT_VER_11_T(rxmfrmucastmbss),
-	IDX_IN_WL_CNT_VER_11_T(rxcfrmucast),
-	IDX_IN_WL_CNT_VER_11_T(rxrtsucast),
-	IDX_IN_WL_CNT_VER_11_T(rxctsucast),
-	IDX_IN_WL_CNT_VER_11_T(rxackucast),
-	IDX_IN_WL_CNT_VER_11_T(rxdfrmocast),
-	IDX_IN_WL_CNT_VER_11_T(rxmfrmocast),
-	IDX_IN_WL_CNT_VER_11_T(rxcfrmocast),
-	IDX_IN_WL_CNT_VER_11_T(rxrtsocast),
-	IDX_IN_WL_CNT_VER_11_T(rxctsocast),
-	IDX_IN_WL_CNT_VER_11_T(rxdfrmmcast),
-	IDX_IN_WL_CNT_VER_11_T(rxmfrmmcast),
-	IDX_IN_WL_CNT_VER_11_T(rxcfrmmcast),
-	IDX_IN_WL_CNT_VER_11_T(rxbeaconmbss),
-	IDX_IN_WL_CNT_VER_11_T(rxdfrmucastobss),
-	IDX_IN_WL_CNT_VER_11_T(rxbeaconobss),
-	IDX_IN_WL_CNT_VER_11_T(rxrsptmout),
-	IDX_IN_WL_CNT_VER_11_T(bcntxcancl),
-	INVALID_MCST_IDX,
-	IDX_IN_WL_CNT_VER_11_T(rxf0ovfl),
-	IDX_IN_WL_CNT_VER_11_T(rxf1ovfl),
-	IDX_IN_WL_CNT_VER_11_T(rxf2ovfl),
-	IDX_IN_WL_CNT_VER_11_T(txsfovfl),
-	IDX_IN_WL_CNT_VER_11_T(pmqovfl),
-	IDX_IN_WL_CNT_VER_11_T(rxcgprqfrm),
-	IDX_IN_WL_CNT_VER_11_T(rxcgprsqovfl),
-	IDX_IN_WL_CNT_VER_11_T(txcgprsfail),
-	IDX_IN_WL_CNT_VER_11_T(txcgprssuc),
-	IDX_IN_WL_CNT_VER_11_T(prs_timeout),
-	IDX_IN_WL_CNT_VER_11_T(rxnack),
-	IDX_IN_WL_CNT_VER_11_T(frmscons),
-	IDX_IN_WL_CNT_VER_11_T(txnack),
-	IDX_IN_WL_CNT_VER_11_T(rxback),
-	IDX_IN_WL_CNT_VER_11_T(txback),
-	IDX_IN_WL_CNT_VER_11_T(bphy_rxcrsglitch),
-	IDX_IN_WL_CNT_VER_11_T(rxdrop20s),
-	IDX_IN_WL_CNT_VER_11_T(rxtoolate),
-	IDX_IN_WL_CNT_VER_11_T(bphy_badplcp)
-};
-
-
-/* Index conversion table from wl_cnt_ver_6_t to wl_cnt_v_le10_mcst_t */
-static const uint8 wlcntver6t_to_wlcntvle10mcstt[WL_CNT_MCST_VAR_NUM] = {
-	IDX_IN_WL_CNT_VER_6_T(txallfrm),
-	IDX_IN_WL_CNT_VER_6_T(txrtsfrm),
-	IDX_IN_WL_CNT_VER_6_T(txctsfrm),
-	IDX_IN_WL_CNT_VER_6_T(txackfrm),
-	IDX_IN_WL_CNT_VER_6_T(txdnlfrm),
-	IDX_IN_WL_CNT_VER_6_T(txbcnfrm),
-	IDX_IN_WL_CNT_VER_6_T(txfunfl),
-	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 1,
-	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 2,
-	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 3,
-	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 4,
-	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 5,
-	IDX_IN_WL_CNT_VER_6_T(txfbw),
-	INVALID_MCST_IDX,
-	IDX_IN_WL_CNT_VER_6_T(txtplunfl),
-	IDX_IN_WL_CNT_VER_6_T(txphyerror),
-	IDX_IN_WL_CNT_VER_6_T(pktengrxducast),
-	IDX_IN_WL_CNT_VER_6_T(pktengrxdmcast),
-	IDX_IN_WL_CNT_VER_6_T(rxfrmtoolong),
-	IDX_IN_WL_CNT_VER_6_T(rxfrmtooshrt),
-	IDX_IN_WL_CNT_VER_6_T(rxinvmachdr),
-	IDX_IN_WL_CNT_VER_6_T(rxbadfcs),
-	IDX_IN_WL_CNT_VER_6_T(rxbadplcp),
-	IDX_IN_WL_CNT_VER_6_T(rxcrsglitch),
-	IDX_IN_WL_CNT_VER_6_T(rxstrt),
-	IDX_IN_WL_CNT_VER_6_T(rxdfrmucastmbss),
-	IDX_IN_WL_CNT_VER_6_T(rxmfrmucastmbss),
-	IDX_IN_WL_CNT_VER_6_T(rxcfrmucast),
-	IDX_IN_WL_CNT_VER_6_T(rxrtsucast),
-	IDX_IN_WL_CNT_VER_6_T(rxctsucast),
-	IDX_IN_WL_CNT_VER_6_T(rxackucast),
-	IDX_IN_WL_CNT_VER_6_T(rxdfrmocast),
-	IDX_IN_WL_CNT_VER_6_T(rxmfrmocast),
-	IDX_IN_WL_CNT_VER_6_T(rxcfrmocast),
-	IDX_IN_WL_CNT_VER_6_T(rxrtsocast),
-	IDX_IN_WL_CNT_VER_6_T(rxctsocast),
-	IDX_IN_WL_CNT_VER_6_T(rxdfrmmcast),
-	IDX_IN_WL_CNT_VER_6_T(rxmfrmmcast),
-	IDX_IN_WL_CNT_VER_6_T(rxcfrmmcast),
-	IDX_IN_WL_CNT_VER_6_T(rxbeaconmbss),
-	IDX_IN_WL_CNT_VER_6_T(rxdfrmucastobss),
-	IDX_IN_WL_CNT_VER_6_T(rxbeaconobss),
-	IDX_IN_WL_CNT_VER_6_T(rxrsptmout),
-	IDX_IN_WL_CNT_VER_6_T(bcntxcancl),
-	INVALID_MCST_IDX,
-	IDX_IN_WL_CNT_VER_6_T(rxf0ovfl),
-	IDX_IN_WL_CNT_VER_6_T(rxf1ovfl),
-	IDX_IN_WL_CNT_VER_6_T(rxf2ovfl),
-	IDX_IN_WL_CNT_VER_6_T(txsfovfl),
-	IDX_IN_WL_CNT_VER_6_T(pmqovfl),
-	IDX_IN_WL_CNT_VER_6_T(rxcgprqfrm),
-	IDX_IN_WL_CNT_VER_6_T(rxcgprsqovfl),
-	IDX_IN_WL_CNT_VER_6_T(txcgprsfail),
-	IDX_IN_WL_CNT_VER_6_T(txcgprssuc),
-	IDX_IN_WL_CNT_VER_6_T(prs_timeout),
-	IDX_IN_WL_CNT_VER_6_T(rxnack),
-	IDX_IN_WL_CNT_VER_6_T(frmscons),
-	IDX_IN_WL_CNT_VER_6_T(txnack),
-	IDX_IN_WL_CNT_VER_6_T(rxback),
-	IDX_IN_WL_CNT_VER_6_T(txback),
-	IDX_IN_WL_CNT_VER_6_T(bphy_rxcrsglitch),
-	IDX_IN_WL_CNT_VER_6_T(rxdrop20s),
-	IDX_IN_WL_CNT_VER_6_T(rxtoolate),
-	IDX_IN_WL_CNT_VER_6_T(bphy_badplcp)
-};
-
-/* copy wlc layer counters from old type cntbuf to wl_cnt_wlc_t type. */
-static int
-wl_copy_wlccnt(uint16 cntver, uint32 *dst, uint32 *src, uint8 src_max_idx)
-{
-	uint i;
-	if (dst == NULL || src == NULL) {
-		return BCME_ERROR;
-	}
-
-	/* Init wlccnt with invalid value. Unchanged value will not be printed out */
-	for (i = 0; i < (sizeof(wl_cnt_wlc_t) / sizeof(uint32)); i++) {
-		dst[i] = INVALID_CNT_VAL;
-	}
-
-	if (cntver == WL_CNT_VERSION_6) {
-		for (i = 0; i < NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T; i++) {
-			if (wlcntver6t_to_wlcntwlct[i] >= src_max_idx) {
-			/* src buffer does not have counters from here */
-				break;
-			}
-			dst[i] = src[wlcntver6t_to_wlcntwlct[i]];
-		}
-	} else {
-		for (i = 0; i < NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T; i++) {
-			if (wlcntver11t_to_wlcntwlct[i] >= src_max_idx) {
-			/* src buffer does not have counters from here */
-				break;
-			}
-			dst[i] = src[wlcntver11t_to_wlcntwlct[i]];
-		}
-	}
-	return BCME_OK;
-}
-
-/* copy macstat counters from old type cntbuf to wl_cnt_v_le10_mcst_t type. */
-static int
-wl_copy_macstat_upto_ver10(uint16 cntver, uint32 *dst, uint32 *src)
-{
-	uint i;
-
-	if (dst == NULL || src == NULL) {
-		return BCME_ERROR;
-	}
-
-	if (cntver == WL_CNT_VERSION_6) {
-		for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
-			if (wlcntver6t_to_wlcntvle10mcstt[i] == INVALID_MCST_IDX) {
-				/* This mcst counter does not exist in wl_cnt_ver_6_t */
-				dst[i] = INVALID_CNT_VAL;
-			} else {
-				dst[i] = src[wlcntver6t_to_wlcntvle10mcstt[i]];
-			}
-		}
-	} else {
-		for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
-			if (wlcntver11t_to_wlcntvle10mcstt[i] == INVALID_MCST_IDX) {
-				/* This mcst counter does not exist in wl_cnt_ver_11_t */
-				dst[i] = INVALID_CNT_VAL;
-			} else {
-				dst[i] = src[wlcntver11t_to_wlcntvle10mcstt[i]];
-			}
-		}
-	}
-	return BCME_OK;
-}
-
-static int
-wl_copy_macstat_ver11(uint32 *dst, uint32 *src)
-{
-	uint i;
-
-	if (dst == NULL || src == NULL) {
-		return BCME_ERROR;
-	}
-
-	for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
-		dst[i] = src[wlcntver11t_to_wlcntXX40mcstv1t[i]];
-	}
-	return BCME_OK;
-}
-
-/**
- * Translate non-xtlv 'wl counters' IOVar buffer received by old driver/FW to xtlv format.
- * Parameters:
- *	cntbuf: pointer to non-xtlv 'wl counters' IOVar buffer received by old driver/FW.
- *		Newly translated xtlv format is written to this pointer.
- *	buflen: length of the "cntbuf" without any padding.
- *	corerev: chip core revision of the driver/FW.
- */
-int
-wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf, int buflen, uint32 corerev)
-{
-	wl_cnt_wlc_t *wlccnt = NULL;
-	uint32 *macstat = NULL;
-	xtlv_desc_t xtlv_desc[3];
-	uint16 mcst_xtlv_id;
-	int res = BCME_OK;
-	wl_cnt_info_t *cntinfo = cntbuf;
-	void *xtlvbuf_p = cntinfo->data;
-	uint16 ver = cntinfo->version;
-	uint16 xtlvbuflen = (uint16)buflen;
-	uint16 src_max_idx;
-#ifdef BCMDRIVER
-	osl_t *osh = ctx;
-#else
-	BCM_REFERENCE(ctx);
-#endif
-
-	if (ver == WL_CNT_T_VERSION) {
-		/* Already in xtlv format. */
-		goto exit;
-	}
-
-#ifdef BCMDRIVER
-	wlccnt = MALLOC(osh, sizeof(*wlccnt));
-	macstat = MALLOC(osh, WL_CNT_MCST_STRUCT_SZ);
-#else
-	wlccnt = (wl_cnt_wlc_t *)malloc(sizeof(*wlccnt));
-	macstat = (uint32 *)malloc(WL_CNT_MCST_STRUCT_SZ);
-#endif
-	if (!wlccnt) {
-		printf("wl_cntbuf_to_xtlv_format malloc fail!\n");
-		res = BCME_NOMEM;
-		goto exit;
-	}
-
-	/* Check if the max idx in the struct exceeds the boundary of uint8 */
-	if (NUM_OF_CNT_IN_WL_CNT_VER_6_T > ((uint8)(-1) + 1) ||
-		NUM_OF_CNT_IN_WL_CNT_VER_11_T > ((uint8)(-1) + 1)) {
-		printf("wlcntverXXt_to_wlcntwlct and src_max_idx need"
-			" to be of uint16 instead of uint8\n");
-		res = BCME_ERROR;
-		goto exit;
-	}
-
-	/* Exclude version and length fields in either wlc_cnt_ver_6_t or wlc_cnt_ver_11_t */
-	src_max_idx = (cntinfo->datalen - OFFSETOF(wl_cnt_info_t, data)) / sizeof(uint32);
-
-	if (src_max_idx > (uint8)(-1)) {
-		printf("wlcntverXXt_to_wlcntwlct and src_max_idx need"
-			" to be of uint16 instead of uint8\n"
-			"Try updating wl utility to the latest.\n");
-		res = BCME_ERROR;
-	}
-
-	/* Copy wlc layer counters to wl_cnt_wlc_t */
-	res = wl_copy_wlccnt(ver, (uint32 *)wlccnt, (uint32 *)cntinfo->data, (uint8)src_max_idx);
-	if (res != BCME_OK) {
-		printf("wl_copy_wlccnt fail!\n");
-		goto exit;
-	}
-
-	/* Copy macstat counters to wl_cnt_wlc_t */
-	if (ver == WL_CNT_VERSION_11) {
-		res = wl_copy_macstat_ver11(macstat, (uint32 *)cntinfo->data);
-		if (res != BCME_OK) {
-			printf("wl_copy_macstat_ver11 fail!\n");
-			goto exit;
-		}
-		if (corerev >= 40) {
-			mcst_xtlv_id = WL_CNT_XTLV_GE40_UCODE_V1;
-		} else {
-			mcst_xtlv_id = WL_CNT_XTLV_LT40_UCODE_V1;
-		}
-	} else {
-		res = wl_copy_macstat_upto_ver10(ver, macstat, (uint32 *)cntinfo->data);
-		if (res != BCME_OK) {
-			printf("wl_copy_macstat_upto_ver10 fail!\n");
-			goto exit;
-		}
-		mcst_xtlv_id = WL_CNT_XTLV_CNTV_LE10_UCODE;
-	}
-
-	xtlv_desc[0].type = WL_CNT_XTLV_WLC;
-	xtlv_desc[0].len = sizeof(*wlccnt);
-	xtlv_desc[0].ptr = wlccnt;
-
-	xtlv_desc[1].type = mcst_xtlv_id;
-	xtlv_desc[1].len = WL_CNT_MCST_STRUCT_SZ;
-	xtlv_desc[1].ptr = macstat;
-
-	xtlv_desc[2].type = 0;
-	xtlv_desc[2].len = 0;
-	xtlv_desc[2].ptr = NULL;
-
-	memset(cntbuf, 0, WL_CNTBUF_MAX_SIZE);
-
-	res = bcm_pack_xtlv_buf_from_mem(&xtlvbuf_p, &xtlvbuflen,
-		xtlv_desc, BCM_XTLV_OPTION_ALIGN32);
-	cntinfo->datalen = (buflen - xtlvbuflen);
-exit:
-#ifdef BCMDRIVER
-	if (wlccnt) {
-		MFREE(osh, wlccnt, sizeof(*wlccnt));
-	}
-	if (macstat) {
-		MFREE(osh, macstat, WL_CNT_MCST_STRUCT_SZ);
-	}
-#else
-	if (wlccnt) {
-		free(wlccnt);
-	}
-	if (macstat) {
-		free(macstat);
-	}
-#endif
-	return res;
-}
diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c
deleted file mode 100644
index 1746f47..0000000
--- a/drivers/net/wireless/bcmdhd/bcmevent.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * bcmevent read-only data shared by kernel or app layers
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmevent.c 530174 2015-01-29 09:47:55Z $
- */
-
-#include <typedefs.h>
-#include <bcmutils.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
-#include <proto/bcmeth.h>
-#include <proto/bcmevent.h>
-
-
-/* Table of event name strings for UIs and debugging dumps */
-typedef struct {
-	uint event;
-	const char *name;
-} bcmevent_name_str_t;
-
-/* Use the actual name for event tracing */
-#define BCMEVENT_NAME(_event) {(_event), #_event}
-
-static const bcmevent_name_str_t bcmevent_names[] = {
-	BCMEVENT_NAME(WLC_E_SET_SSID),
-	BCMEVENT_NAME(WLC_E_JOIN),
-	BCMEVENT_NAME(WLC_E_START),
-	BCMEVENT_NAME(WLC_E_AUTH),
-	BCMEVENT_NAME(WLC_E_AUTH_IND),
-	BCMEVENT_NAME(WLC_E_DEAUTH),
-	BCMEVENT_NAME(WLC_E_DEAUTH_IND),
-	BCMEVENT_NAME(WLC_E_ASSOC),
-	BCMEVENT_NAME(WLC_E_ASSOC_IND),
-	BCMEVENT_NAME(WLC_E_REASSOC),
-	BCMEVENT_NAME(WLC_E_REASSOC_IND),
-	BCMEVENT_NAME(WLC_E_DISASSOC),
-	BCMEVENT_NAME(WLC_E_DISASSOC_IND),
-	BCMEVENT_NAME(WLC_E_QUIET_START),
-	BCMEVENT_NAME(WLC_E_QUIET_END),
-	BCMEVENT_NAME(WLC_E_BEACON_RX),
-	BCMEVENT_NAME(WLC_E_LINK),
-	BCMEVENT_NAME(WLC_E_MIC_ERROR),
-	BCMEVENT_NAME(WLC_E_NDIS_LINK),
-	BCMEVENT_NAME(WLC_E_ROAM),
-	BCMEVENT_NAME(WLC_E_TXFAIL),
-	BCMEVENT_NAME(WLC_E_PMKID_CACHE),
-	BCMEVENT_NAME(WLC_E_RETROGRADE_TSF),
-	BCMEVENT_NAME(WLC_E_PRUNE),
-	BCMEVENT_NAME(WLC_E_AUTOAUTH),
-	BCMEVENT_NAME(WLC_E_EAPOL_MSG),
-	BCMEVENT_NAME(WLC_E_SCAN_COMPLETE),
-	BCMEVENT_NAME(WLC_E_ADDTS_IND),
-	BCMEVENT_NAME(WLC_E_DELTS_IND),
-	BCMEVENT_NAME(WLC_E_BCNSENT_IND),
-	BCMEVENT_NAME(WLC_E_BCNRX_MSG),
-	BCMEVENT_NAME(WLC_E_BCNLOST_MSG),
-	BCMEVENT_NAME(WLC_E_ROAM_PREP),
-	BCMEVENT_NAME(WLC_E_PFN_NET_FOUND),
-	BCMEVENT_NAME(WLC_E_PFN_SCAN_ALLGONE),
-	BCMEVENT_NAME(WLC_E_PFN_NET_LOST),
-#if defined(IBSS_PEER_DISCOVERY_EVENT)
-	BCMEVENT_NAME(WLC_E_IBSS_ASSOC),
-#endif /* defined(IBSS_PEER_DISCOVERY_EVENT) */
-	BCMEVENT_NAME(WLC_E_RADIO),
-	BCMEVENT_NAME(WLC_E_PSM_WATCHDOG),
-	BCMEVENT_NAME(WLC_E_PROBREQ_MSG),
-	BCMEVENT_NAME(WLC_E_SCAN_CONFIRM_IND),
-	BCMEVENT_NAME(WLC_E_PSK_SUP),
-	BCMEVENT_NAME(WLC_E_COUNTRY_CODE_CHANGED),
-	BCMEVENT_NAME(WLC_E_EXCEEDED_MEDIUM_TIME),
-	BCMEVENT_NAME(WLC_E_ICV_ERROR),
-	BCMEVENT_NAME(WLC_E_UNICAST_DECODE_ERROR),
-	BCMEVENT_NAME(WLC_E_MULTICAST_DECODE_ERROR),
-	BCMEVENT_NAME(WLC_E_TRACE),
-	BCMEVENT_NAME(WLC_E_IF),
-#ifdef WLP2P
-	BCMEVENT_NAME(WLC_E_P2P_DISC_LISTEN_COMPLETE),
-#endif
-	BCMEVENT_NAME(WLC_E_RSSI),
-	BCMEVENT_NAME(WLC_E_EXTLOG_MSG),
-	BCMEVENT_NAME(WLC_E_ACTION_FRAME),
-	BCMEVENT_NAME(WLC_E_ACTION_FRAME_RX),
-	BCMEVENT_NAME(WLC_E_ACTION_FRAME_COMPLETE),
-	BCMEVENT_NAME(WLC_E_ESCAN_RESULT),
-	BCMEVENT_NAME(WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE),
-#ifdef WLP2P
-	BCMEVENT_NAME(WLC_E_PROBRESP_MSG),
-	BCMEVENT_NAME(WLC_E_P2P_PROBREQ_MSG),
-#endif
-#ifdef PROP_TXSTATUS
-	BCMEVENT_NAME(WLC_E_FIFO_CREDIT_MAP),
-#endif
-	BCMEVENT_NAME(WLC_E_WAKE_EVENT),
-	BCMEVENT_NAME(WLC_E_DCS_REQUEST),
-	BCMEVENT_NAME(WLC_E_RM_COMPLETE),
-#ifdef WLMEDIA_HTSF
-	BCMEVENT_NAME(WLC_E_HTSFSYNC),
-#endif
-	BCMEVENT_NAME(WLC_E_OVERLAY_REQ),
-	BCMEVENT_NAME(WLC_E_CSA_COMPLETE_IND),
-	BCMEVENT_NAME(WLC_E_EXCESS_PM_WAKE_EVENT),
-	BCMEVENT_NAME(WLC_E_PFN_SCAN_NONE),
-	BCMEVENT_NAME(WLC_E_PFN_SCAN_ALLGONE),
-#ifdef SOFTAP
-	BCMEVENT_NAME(WLC_E_GTK_PLUMBED),
-#endif
-	BCMEVENT_NAME(WLC_E_ASSOC_REQ_IE),
-	BCMEVENT_NAME(WLC_E_ASSOC_RESP_IE),
-	BCMEVENT_NAME(WLC_E_BEACON_FRAME_RX),
-#ifdef WLTDLS
-	BCMEVENT_NAME(WLC_E_TDLS_PEER_EVENT),
-#endif /* WLTDLS */
-	BCMEVENT_NAME(WLC_E_NATIVE),
-#ifdef WLPKTDLYSTAT
-	BCMEVENT_NAME(WLC_E_PKTDELAY_IND),
-#endif /* WLPKTDLYSTAT */
-	BCMEVENT_NAME(WLC_E_SERVICE_FOUND),
-	BCMEVENT_NAME(WLC_E_GAS_FRAGMENT_RX),
-	BCMEVENT_NAME(WLC_E_GAS_COMPLETE),
-	BCMEVENT_NAME(WLC_E_P2PO_ADD_DEVICE),
-	BCMEVENT_NAME(WLC_E_P2PO_DEL_DEVICE),
-#ifdef WLWNM
-	BCMEVENT_NAME(WLC_E_WNM_STA_SLEEP),
-#endif /* WLWNM */
-#if defined(WL_PROXDETECT)
-	BCMEVENT_NAME(WLC_E_PROXD),
-#endif
-	BCMEVENT_NAME(WLC_E_CCA_CHAN_QUAL),
-	BCMEVENT_NAME(WLC_E_BSSID),
-#ifdef PROP_TXSTATUS
-	BCMEVENT_NAME(WLC_E_BCMC_CREDIT_SUPPORT),
-#endif
-	BCMEVENT_NAME(WLC_E_PSTA_PRIMARY_INTF_IND),
-	BCMEVENT_NAME(WLC_E_TXFAIL_THRESH),
-#ifdef GSCAN_SUPPORT
-	BCMEVENT_NAME(WLC_E_PFN_GSCAN_FULL_RESULT),
-	BCMEVENT_NAME(WLC_E_PFN_SWC),
-#endif /* GSCAN_SUPPORT */
-#ifdef WLBSSLOAD_REPORT
-	BCMEVENT_NAME(WLC_E_BSS_LOAD),
-#endif
-#if defined(BT_WIFI_HANDOVER) || defined(WL_TBOW)
-	BCMEVENT_NAME(WLC_E_BT_WIFI_HANDOVER_REQ),
-#endif
-	BCMEVENT_NAME(WLC_E_AUTHORIZED),
-	BCMEVENT_NAME(WLC_E_PROBREQ_MSG_RX),
-	BCMEVENT_NAME(WLC_E_CSA_START_IND),
-	BCMEVENT_NAME(WLC_E_CSA_DONE_IND),
-	BCMEVENT_NAME(WLC_E_CSA_FAILURE_IND),
-	BCMEVENT_NAME(WLC_E_RMC_EVENT),
-	BCMEVENT_NAME(WLC_E_DPSTA_INTF_IND),
-};
-
-
-const char *bcmevent_get_name(uint event_type)
-{
-	/* note:  first coded this as a static const but some
-	 * ROMs already have something called event_name so
-	 * changed it so we don't have a variable for the
-	 * 'unknown string
-	 */
-	const char *event_name = NULL;
-
-	uint idx;
-	for (idx = 0; idx < (uint)ARRAYSIZE(bcmevent_names); idx++) {
-
-		if (bcmevent_names[idx].event == event_type) {
-			event_name = bcmevent_names[idx].name;
-			break;
-		}
-	}
-
-	/* if we find an event name in the array, return it.
-	 * otherwise return unknown string.
-	 */
-	return ((event_name) ? event_name : "Unknown Event");
-}
-
-void
-wl_event_to_host_order(wl_event_msg_t * evt)
-{
-	/* Event struct members passed from dongle to host are stored in network
-	* byte order. Convert all members to host-order.
-	*/
-	evt->event_type = ntoh32(evt->event_type);
-	evt->flags = ntoh16(evt->flags);
-	evt->status = ntoh32(evt->status);
-	evt->reason = ntoh32(evt->reason);
-	evt->auth_type = ntoh32(evt->auth_type);
-	evt->datalen = ntoh32(evt->datalen);
-	evt->version = ntoh16(evt->version);
-}
-
-void
-wl_event_to_network_order(wl_event_msg_t * evt)
-{
-	/* Event struct members passed from dongle to host are stored in network
-	* byte order. Convert all members to host-order.
-	*/
-	evt->event_type = hton32(evt->event_type);
-	evt->flags = hton16(evt->flags);
-	evt->status = hton32(evt->status);
-	evt->reason = hton32(evt->reason);
-	evt->auth_type = hton32(evt->auth_type);
-	evt->datalen = hton32(evt->datalen);
-	evt->version = hton16(evt->version);
-}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh.c b/drivers/net/wireless/bcmdhd/bcmsdh.c
deleted file mode 100644
index 42b29bd..0000000
--- a/drivers/net/wireless/bcmdhd/bcmsdh.c
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- *  BCMSDH interface glue
- *  implement bcmsdh API for SDIOH driver
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsdh.c 514727 2014-11-12 03:02:48Z $
- */
-
-/**
- * @file bcmsdh.c
- */
-
-/* ****************** BCMSDH Interface Functions *************************** */
-
-#include <typedefs.h>
-#include <bcmdevs.h>
-#include <bcmendian.h>
-#include <bcmutils.h>
-#include <hndsoc.h>
-#include <siutils.h>
-#include <osl.h>
-
-#include <bcmsdh.h>	/* BRCM API for SDIO clients (such as wl, dhd) */
-#include <bcmsdbus.h>	/* common SDIO/controller interface */
-#include <sbsdio.h>	/* SDIO device core hardware definitions. */
-#include <sdio.h>	/* SDIO Device and Protocol Specs */
-
-#define SDIOH_API_ACCESS_RETRY_LIMIT	2
-const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
-
-/* local copy of bcm sd handler */
-bcmsdh_info_t * l_bcmsdh = NULL;
-
-
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-extern int
-sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
-
-void
-bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
-{
-	sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
-}
-#endif
-
-/* Attach BCMSDH layer to SDIO Host Controller Driver
- *
- * @param osh OSL Handle.
- * @param cfghdl Configuration Handle.
- * @param regsva Virtual address of controller registers.
- * @param irq Interrupt number of SDIO controller.
- *
- * @return bcmsdh_info_t Handle to BCMSDH context.
- */
-bcmsdh_info_t *
-bcmsdh_attach(osl_t *osh, void *sdioh, ulong *regsva)
-{
-	bcmsdh_info_t *bcmsdh;
-
-	if ((bcmsdh = (bcmsdh_info_t *)MALLOC(osh, sizeof(bcmsdh_info_t))) == NULL) {
-		BCMSDH_ERROR(("bcmsdh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh)));
-		return NULL;
-	}
-	bzero((char *)bcmsdh, sizeof(bcmsdh_info_t));
-	bcmsdh->sdioh = sdioh;
-	bcmsdh->osh = osh;
-	bcmsdh->init_success = TRUE;
-	*regsva = SI_ENUM_BASE;
-
-	/* Report the BAR, to fix if needed */
-	bcmsdh->sbwad = SI_ENUM_BASE;
-
-	/* save the handler locally */
-	l_bcmsdh = bcmsdh;
-
-	return bcmsdh;
-}
-
-int
-bcmsdh_detach(osl_t *osh, void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	if (bcmsdh != NULL) {
-		MFREE(osh, bcmsdh, sizeof(bcmsdh_info_t));
-	}
-
-	l_bcmsdh = NULL;
-
-	return 0;
-}
-
-int
-bcmsdh_iovar_op(void *sdh, const char *name,
-                void *params, int plen, void *arg, int len, bool set)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set);
-}
-
-bool
-bcmsdh_intr_query(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	bool on;
-
-	ASSERT(bcmsdh);
-	status = sdioh_interrupt_query(bcmsdh->sdioh, &on);
-	if (SDIOH_API_SUCCESS(status))
-		return FALSE;
-	else
-		return on;
-}
-
-int
-bcmsdh_intr_enable(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	ASSERT(bcmsdh);
-
-	status = sdioh_interrupt_set(bcmsdh->sdioh, TRUE);
-	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
-}
-
-int
-bcmsdh_intr_disable(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	ASSERT(bcmsdh);
-
-	status = sdioh_interrupt_set(bcmsdh->sdioh, FALSE);
-	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
-}
-
-int
-bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	ASSERT(bcmsdh);
-
-	status = sdioh_interrupt_register(bcmsdh->sdioh, fn, argh);
-	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
-}
-
-int
-bcmsdh_intr_dereg(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	ASSERT(bcmsdh);
-
-	status = sdioh_interrupt_deregister(bcmsdh->sdioh);
-	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
-}
-
-#if defined(DHD_DEBUG)
-bool
-bcmsdh_intr_pending(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	ASSERT(sdh);
-	return sdioh_interrupt_pending(bcmsdh->sdioh);
-}
-#endif
-
-
-int
-bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
-{
-	ASSERT(sdh);
-
-	/* don't support yet */
-	return BCME_UNSUPPORTED;
-}
-
-/**
- * Read from SDIO Configuration Space
- * @param sdh SDIO Host context.
- * @param func_num Function number to read from.
- * @param addr Address to read from.
- * @param err Error return.
- * @return value read from SDIO configuration space.
- */
-uint8
-bcmsdh_cfg_read(void *sdh, uint fnc_num, uint32 addr, int *err)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
-	int32 retry = 0;
-#endif
-	uint8 data = 0;
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
-
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
-	do {
-		if (retry)	/* wait for 1 ms till bus get settled down */
-			OSL_DELAY(1000);
-#endif
-	status = sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
-	} while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
-#endif
-	if (err)
-		*err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
-
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__,
-	            fnc_num, addr, data));
-
-	return data;
-}
-
-void
-bcmsdh_cfg_write(void *sdh, uint fnc_num, uint32 addr, uint8 data, int *err)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
-	int32 retry = 0;
-#endif
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
-
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
-	do {
-		if (retry)	/* wait for 1 ms till bus get settled down */
-			OSL_DELAY(1000);
-#endif
-	status = sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
-	} while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
-#endif
-	if (err)
-		*err = SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR;
-
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__,
-	            fnc_num, addr, data));
-}
-
-uint32
-bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	uint32 data = 0;
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
-
-	status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ, fnc_num,
-	                            addr, &data, 4);
-
-	if (err)
-		*err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
-
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__,
-	            fnc_num, addr, data));
-
-	return data;
-}
-
-void
-bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
-
-	status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, fnc_num,
-	                            addr, &data, 4);
-
-	if (err)
-		*err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
-
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__, fnc_num,
-	             addr, data));
-}
-
-
-int
-bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-
-	uint8 *tmp_buf, *tmp_ptr;
-	uint8 *ptr;
-	bool ascii = func & ~0xf;
-	func &= 0x7;
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
-	ASSERT(cis);
-	ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT);
-
-	status = sdioh_cis_read(bcmsdh->sdioh, func, cis, length);
-
-	if (ascii) {
-		/* Move binary bits to tmp and format them into the provided buffer. */
-		if ((tmp_buf = (uint8 *)MALLOC(bcmsdh->osh, length)) == NULL) {
-			BCMSDH_ERROR(("%s: out of memory\n", __FUNCTION__));
-			return BCME_NOMEM;
-		}
-		bcopy(cis, tmp_buf, length);
-		for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4); tmp_ptr++) {
-			ptr += snprintf((char*)ptr, (cis + length - ptr - 4),
-				"%.2x ", *tmp_ptr & 0xff);
-			if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
-				ptr += snprintf((char *)ptr, (cis + length - ptr -4), "\n");
-		}
-		MFREE(bcmsdh->osh, tmp_buf, length);
-	}
-
-	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
-}
-
-
-int
-bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set)
-{
-	int err = 0;
-	uint bar0 = address & ~SBSDIO_SB_OFT_ADDR_MASK;
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	if (bar0 != bcmsdh->sbwad || force_set) {
-		bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
-			(address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
-		if (!err)
-			bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
-				(address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
-		if (!err)
-			bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
-				(address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
-
-		if (!err)
-			bcmsdh->sbwad = bar0;
-		else
-			/* invalidate cached window var */
-			bcmsdh->sbwad = 0;
-
-	}
-
-	return err;
-}
-
-uint32
-bcmsdh_reg_read(void *sdh, uint32 addr, uint size)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	uint32 word = 0;
-
-	BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __FUNCTION__, addr));
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
-
-	if (bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE))
-		return 0xFFFFFFFF;
-
-	addr &= SBSDIO_SB_OFT_ADDR_MASK;
-	if (size == 4)
-		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-	status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
-		SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
-
-	bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
-
-	BCMSDH_INFO(("uint32data = 0x%x\n", word));
-
-	/* if ok, return appropriately masked word */
-	if (SDIOH_API_SUCCESS(status)) {
-		switch (size) {
-			case sizeof(uint8):
-				return (word & 0xff);
-			case sizeof(uint16):
-				return (word & 0xffff);
-			case sizeof(uint32):
-				return word;
-			default:
-				bcmsdh->regfail = TRUE;
-
-		}
-	}
-
-	/* otherwise, bad sdio access or invalid size */
-	BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __FUNCTION__, addr, size));
-	return 0xFFFFFFFF;
-}
-
-uint32
-bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	int err = 0;
-
-	BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
-	             __FUNCTION__, addr, size*8, data));
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
-
-	if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE)))
-		return err;
-
-	addr &= SBSDIO_SB_OFT_ADDR_MASK;
-	if (size == 4)
-		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-	status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, SDIO_FUNC_1,
-	                            addr, &data, size);
-	bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
-
-	if (SDIOH_API_SUCCESS(status))
-		return 0;
-
-	BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
-	              __FUNCTION__, data, addr, size));
-	return 0xFFFFFFFF;
-}
-
-bool
-bcmsdh_regfail(void *sdh)
-{
-	return ((bcmsdh_info_t *)sdh)->regfail;
-}
-
-int
-bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags,
-                uint8 *buf, uint nbytes, void *pkt,
-                bcmsdh_cmplt_fn_t complete_fn, void *handle)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	uint incr_fix;
-	uint width;
-	int err = 0;
-
-	ASSERT(bcmsdh);
-	ASSERT(bcmsdh->init_success);
-
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
-	             __FUNCTION__, fn, addr, nbytes));
-
-	/* Async not implemented yet */
-	ASSERT(!(flags & SDIO_REQ_ASYNC));
-	if (flags & SDIO_REQ_ASYNC)
-		return BCME_UNSUPPORTED;
-
-	if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE)))
-		return err;
-
-	addr &= SBSDIO_SB_OFT_ADDR_MASK;
-
-	incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
-	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-	if (width == 4)
-		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-	status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
-	                              SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
-
-	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
-}
-
-int
-bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags,
-                uint8 *buf, uint nbytes, void *pkt,
-                bcmsdh_cmplt_fn_t complete_fn, void *handle)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-	uint incr_fix;
-	uint width;
-	int err = 0;
-
-	ASSERT(bcmsdh);
-	ASSERT(bcmsdh->init_success);
-
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
-	            __FUNCTION__, fn, addr, nbytes));
-
-	/* Async not implemented yet */
-	ASSERT(!(flags & SDIO_REQ_ASYNC));
-	if (flags & SDIO_REQ_ASYNC)
-		return BCME_UNSUPPORTED;
-
-	if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE)))
-		return err;
-
-	addr &= SBSDIO_SB_OFT_ADDR_MASK;
-
-	incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
-	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-	if (width == 4)
-		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-	status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
-	                              SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
-
-	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
-}
-
-int
-bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	SDIOH_API_RC status;
-
-	ASSERT(bcmsdh);
-	ASSERT(bcmsdh->init_success);
-	ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0);
-
-	addr &= SBSDIO_SB_OFT_ADDR_MASK;
-	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-	status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC,
-	                              (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
-	                              addr, 4, nbytes, buf, NULL);
-
-	return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
-}
-
-int
-bcmsdh_abort(void *sdh, uint fn)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	return sdioh_abort(bcmsdh->sdioh, fn);
-}
-
-int
-bcmsdh_start(void *sdh, int stage)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	return sdioh_start(bcmsdh->sdioh, stage);
-}
-
-int
-bcmsdh_stop(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	return sdioh_stop(bcmsdh->sdioh);
-}
-
-int
-bcmsdh_waitlockfree(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	return sdioh_waitlockfree(bcmsdh->sdioh);
-}
-
-
-int
-bcmsdh_query_device(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	bcmsdh->vendevid = (VENDOR_BROADCOM << 16) | 0;
-	return (bcmsdh->vendevid);
-}
-
-uint
-bcmsdh_query_iofnum(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	return (sdioh_query_iofnum(bcmsdh->sdioh));
-}
-
-int
-bcmsdh_reset(bcmsdh_info_t *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	return sdioh_sdio_reset(bcmsdh->sdioh);
-}
-
-void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh)
-{
-	ASSERT(sdh);
-	return sdh->sdioh;
-}
-
-/* Function to pass device-status bits to DHD. */
-uint32
-bcmsdh_get_dstatus(void *sdh)
-{
-	return 0;
-}
-uint32
-bcmsdh_cur_sbwad(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	return (bcmsdh->sbwad);
-}
-
-void
-bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev)
-{
-	return;
-}
-
-
-int
-bcmsdh_sleep(void *sdh, bool enab)
-{
-#ifdef SDIOH_SLEEP_ENABLED
-	bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
-	sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
-
-	return sdioh_sleep(sd, enab);
-#else
-	return BCME_UNSUPPORTED;
-#endif
-}
-
-int
-bcmsdh_gpio_init(void *sdh)
-{
-	bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
-	sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
-
-	return sdioh_gpio_init(sd);
-}
-
-bool
-bcmsdh_gpioin(void *sdh, uint32 gpio)
-{
-	bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
-	sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
-
-	return sdioh_gpioin(sd, gpio);
-}
-
-int
-bcmsdh_gpioouten(void *sdh, uint32 gpio)
-{
-	bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
-	sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
-
-	return sdioh_gpioouten(sd, gpio);
-}
-
-int
-bcmsdh_gpioout(void *sdh, uint32 gpio, bool enab)
-{
-	bcmsdh_info_t *p = (bcmsdh_info_t *)sdh;
-	sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh);
-
-	return sdioh_gpioout(sd, gpio, enab);
-}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
deleted file mode 100644
index bf88261..0000000
--- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * SDIO access interface for drivers - linux specific (pci only)
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsdh_linux.c 514727 2014-11-12 03:02:48Z $
- */
-
-/**
- * @file bcmsdh_linux.c
- */
-
-#define __UNDEF_NO_VERSION__
-
-#include <typedefs.h>
-#include <linuxver.h>
-#include <linux/pci.h>
-#include <linux/completion.h>
-
-#include <osl.h>
-#include <pcicfg.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <linux/irq.h>
-extern void dhdsdio_isr(void * args);
-#include <bcmutils.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#if defined(CONFIG_ARCH_ODIN)
-#include <linux/platform_data/gpio-odin.h>
-#endif /* defined(CONFIG_ARCH_ODIN) */
-#include <dhd_linux.h>
-
-/* driver info, initialized when bcmsdh_register is called */
-static bcmsdh_driver_t drvinfo = {NULL, NULL, NULL, NULL};
-
-typedef enum {
-	DHD_INTR_INVALID = 0,
-	DHD_INTR_INBAND,
-	DHD_INTR_HWOOB,
-	DHD_INTR_SWOOB
-} DHD_HOST_INTR_TYPE;
-
-/* the BCMSDH module comprises the generic part (bcmsdh.c) and OS specific layer (e.g.
- * bcmsdh_linux.c). Put all OS specific variables (e.g. irq number and flags) here rather
- * than in the common structure bcmsdh_info. bcmsdh_info only keeps a handle (os_ctx) to this
- * structure.
- */
-typedef struct bcmsdh_os_info {
-	DHD_HOST_INTR_TYPE	intr_type;
-	int			oob_irq_num;	/* valid when hardware or software oob in use */
-	unsigned long		oob_irq_flags;	/* valid when hardware or software oob in use */
-	bool			oob_irq_registered;
-	bool			oob_irq_enabled;
-	bool			oob_irq_wake_enabled;
-	spinlock_t		oob_irq_spinlock;
-	bcmsdh_cb_fn_t		oob_irq_handler;
-	void			*oob_irq_handler_context;
-	void			*context;	/* context returned from upper layer */
-	void			*sdioh;		/* handle to lower layer (sdioh) */
-	void			*dev;		/* handle to the underlying device */
-	bool			dev_wake_enabled;
-} bcmsdh_os_info_t;
-
-/* debugging macros */
-#define SDLX_MSG(x)
-
-/**
- * Checks to see if vendor and device IDs match a supported SDIO Host Controller.
- */
-bool
-bcmsdh_chipmatch(uint16 vendor, uint16 device)
-{
-	/* Add other vendors and devices as required */
-
-#ifdef BCMSDIOH_STD
-	/* Check for Arasan host controller */
-	if (vendor == VENDOR_SI_IMAGE) {
-		return (TRUE);
-	}
-	/* Check for BRCM 27XX Standard host controller */
-	if (device == BCM27XX_SDIOH_ID && vendor == VENDOR_BROADCOM) {
-		return (TRUE);
-	}
-	/* Check for BRCM Standard host controller */
-	if (device == SDIOH_FPGA_ID && vendor == VENDOR_BROADCOM) {
-		return (TRUE);
-	}
-	/* Check for TI PCIxx21 Standard host controller */
-	if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI) {
-		return (TRUE);
-	}
-	if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI) {
-		return (TRUE);
-	}
-	/* Ricoh R5C822 Standard SDIO Host */
-	if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH) {
-		return (TRUE);
-	}
-	/* JMicron Standard SDIO Host */
-	if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON) {
-		return (TRUE);
-	}
-
-#endif /* BCMSDIOH_STD */
-#ifdef BCMSDIOH_SPI
-	/* This is the PciSpiHost. */
-	if (device == SPIH_FPGA_ID && vendor == VENDOR_BROADCOM) {
-		printf("Found PCI SPI Host Controller\n");
-		return (TRUE);
-	}
-
-#endif /* BCMSDIOH_SPI */
-
-	return (FALSE);
-}
-
-void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bus_type,
-	uint bus_num, uint slot_num)
-{
-	ulong regs;
-	bcmsdh_info_t *bcmsdh;
-	uint32 vendevid;
-	bcmsdh_os_info_t *bcmsdh_osinfo = NULL;
-
-	bcmsdh = bcmsdh_attach(osh, sdioh, &regs);
-	if (bcmsdh == NULL) {
-		SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
-		goto err;
-	}
-	bcmsdh_osinfo = MALLOC(osh, sizeof(bcmsdh_os_info_t));
-	if (bcmsdh_osinfo == NULL) {
-		SDLX_MSG(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__));
-		goto err;
-	}
-	bzero((char *)bcmsdh_osinfo, sizeof(bcmsdh_os_info_t));
-	bcmsdh->os_cxt = bcmsdh_osinfo;
-	bcmsdh_osinfo->sdioh = sdioh;
-	bcmsdh_osinfo->dev = dev;
-	osl_set_bus_handle(osh, bcmsdh);
-
-#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-	if (dev && device_init_wakeup(dev, true) == 0)
-		bcmsdh_osinfo->dev_wake_enabled = TRUE;
-#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
-
-#if defined(OOB_INTR_ONLY)
-	spin_lock_init(&bcmsdh_osinfo->oob_irq_spinlock);
-	/* Get customer specific OOB IRQ parametres: IRQ number as IRQ type */
-	bcmsdh_osinfo->oob_irq_num = wifi_platform_get_irq_number(adapter_info,
-		&bcmsdh_osinfo->oob_irq_flags);
-	if  (bcmsdh_osinfo->oob_irq_num < 0) {
-		SDLX_MSG(("%s: Host OOB irq is not defined\n", __FUNCTION__));
-		goto err;
-	}
-#endif /* defined(BCMLXSDMMC) */
-
-	/* Read the vendor/device ID from the CIS */
-	vendevid = bcmsdh_query_device(bcmsdh);
-	/* try to attach to the target device */
-	bcmsdh_osinfo->context = drvinfo.probe((vendevid >> 16), (vendevid & 0xFFFF), bus_num,
-		slot_num, 0, bus_type, (void *)regs, osh, bcmsdh);
-	if (bcmsdh_osinfo->context == NULL) {
-		SDLX_MSG(("%s: device attach failed\n", __FUNCTION__));
-		goto err;
-	}
-
-	return bcmsdh;
-
-	/* error handling */
-err:
-	if (bcmsdh != NULL)
-		bcmsdh_detach(osh, bcmsdh);
-	if (bcmsdh_osinfo != NULL)
-		MFREE(osh, bcmsdh_osinfo, sizeof(bcmsdh_os_info_t));
-	return NULL;
-}
-
-int bcmsdh_remove(bcmsdh_info_t *bcmsdh)
-{
-	bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
-
-#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-	if (bcmsdh_osinfo->dev)
-		device_init_wakeup(bcmsdh_osinfo->dev, false);
-	bcmsdh_osinfo->dev_wake_enabled = FALSE;
-#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
-
-	drvinfo.remove(bcmsdh_osinfo->context);
-	MFREE(bcmsdh->osh, bcmsdh->os_cxt, sizeof(bcmsdh_os_info_t));
-	bcmsdh_detach(bcmsdh->osh, bcmsdh);
-
-	return 0;
-}
-
-int bcmsdh_suspend(bcmsdh_info_t *bcmsdh)
-{
-	bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
-
-	if (drvinfo.suspend && drvinfo.suspend(bcmsdh_osinfo->context))
-		return -EBUSY;
-	return 0;
-}
-
-int bcmsdh_resume(bcmsdh_info_t *bcmsdh)
-{
-	bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
-
-	if (drvinfo.resume)
-		return drvinfo.resume(bcmsdh_osinfo->context);
-	return 0;
-}
-
-extern int bcmsdh_register_client_driver(void);
-extern void bcmsdh_unregister_client_driver(void);
-extern int sdio_func_reg_notify(void* semaphore);
-extern void sdio_func_unreg_notify(void);
-
-#if defined(BCMLXSDMMC)
-int bcmsdh_reg_sdio_notify(void* semaphore)
-{
-	return sdio_func_reg_notify(semaphore);
-}
-
-void bcmsdh_unreg_sdio_notify(void)
-{
-	sdio_func_unreg_notify();
-}
-#endif /* defined(BCMLXSDMMC) */
-
-int
-bcmsdh_register(bcmsdh_driver_t *driver)
-{
-	int error = 0;
-
-	drvinfo = *driver;
-	SDLX_MSG(("%s: register client driver\n", __FUNCTION__));
-	error = bcmsdh_register_client_driver();
-	if (error)
-		SDLX_MSG(("%s: failed %d\n", __FUNCTION__, error));
-
-	return error;
-}
-
-void
-bcmsdh_unregister(void)
-{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-		if (bcmsdh_pci_driver.node.next == NULL)
-			return;
-#endif
-
-	bcmsdh_unregister_client_driver();
-}
-
-void bcmsdh_dev_pm_stay_awake(bcmsdh_info_t *bcmsdh)
-{
-#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-	bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
-	pm_stay_awake(bcmsdh_osinfo->dev);
-#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
-}
-
-void bcmsdh_dev_relax(bcmsdh_info_t *bcmsdh)
-{
-#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-	bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
-	pm_relax(bcmsdh_osinfo->dev);
-#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
-}
-
-bool bcmsdh_dev_pm_enabled(bcmsdh_info_t *bcmsdh)
-{
-	bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
-
-	return bcmsdh_osinfo->dev_wake_enabled;
-}
-
-#if defined(OOB_INTR_ONLY)
-void bcmsdh_oob_intr_set(bcmsdh_info_t *bcmsdh, bool enable)
-{
-	unsigned long flags;
-	bcmsdh_os_info_t *bcmsdh_osinfo;
-
-	if (!bcmsdh)
-		return;
-
-	bcmsdh_osinfo = bcmsdh->os_cxt;
-	spin_lock_irqsave(&bcmsdh_osinfo->oob_irq_spinlock, flags);
-	if (bcmsdh_osinfo->oob_irq_enabled != enable) {
-		if (enable)
-			enable_irq(bcmsdh_osinfo->oob_irq_num);
-		else
-			disable_irq_nosync(bcmsdh_osinfo->oob_irq_num);
-		bcmsdh_osinfo->oob_irq_enabled = enable;
-	}
-	spin_unlock_irqrestore(&bcmsdh_osinfo->oob_irq_spinlock, flags);
-}
-
-static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)dev_id;
-	bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
-
-	bcmsdh_oob_intr_set(bcmsdh, FALSE);
-	bcmsdh_osinfo->oob_irq_handler(bcmsdh_osinfo->oob_irq_handler_context);
-
-	return IRQ_HANDLED;
-}
-
-int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handler,
-	void* oob_irq_handler_context)
-{
-	int err = 0;
-	bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
-
-	SDLX_MSG(("%s: Enter\n", __FUNCTION__));
-	if (bcmsdh_osinfo->oob_irq_registered) {
-		SDLX_MSG(("%s: irq is already registered\n", __FUNCTION__));
-		return -EBUSY;
-	}
-	SDLX_MSG(("%s OOB irq=%d flags=%X \n", __FUNCTION__,
-		(int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags));
-	bcmsdh_osinfo->oob_irq_handler = oob_irq_handler;
-	bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context;
-#if defined(CONFIG_ARCH_ODIN)
-	err = odin_gpio_sms_request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq,
-		bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh);
-#else
-	err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq,
-		bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh);
-#endif /* defined(CONFIG_ARCH_ODIN) */
-	if (err) {
-		SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err));
-		return err;
-	}
-
-		err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num);
-		if (!err)
-			bcmsdh_osinfo->oob_irq_wake_enabled = TRUE;
-	bcmsdh_osinfo->oob_irq_enabled = TRUE;
-	bcmsdh_osinfo->oob_irq_registered = TRUE;
-	return err;
-}
-
-void bcmsdh_oob_intr_unregister(bcmsdh_info_t *bcmsdh)
-{
-	int err = 0;
-	bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
-
-	SDLX_MSG(("%s: Enter\n", __FUNCTION__));
-	if (!bcmsdh_osinfo->oob_irq_registered) {
-		SDLX_MSG(("%s: irq is not registered\n", __FUNCTION__));
-		return;
-	}
-	if (bcmsdh_osinfo->oob_irq_wake_enabled) {
-			err = disable_irq_wake(bcmsdh_osinfo->oob_irq_num);
-			if (!err)
-				bcmsdh_osinfo->oob_irq_wake_enabled = FALSE;
-	}
-	if (bcmsdh_osinfo->oob_irq_enabled) {
-		disable_irq(bcmsdh_osinfo->oob_irq_num);
-		bcmsdh_osinfo->oob_irq_enabled = FALSE;
-	}
-	free_irq(bcmsdh_osinfo->oob_irq_num, bcmsdh);
-	bcmsdh_osinfo->oob_irq_registered = FALSE;
-}
-#endif 
-
-/* Module parameters specific to each host-controller driver */
-
-extern uint sd_msglevel;	/* Debug message level */
-module_param(sd_msglevel, uint, 0);
-
-extern uint sd_power;	/* 0 = SD Power OFF, 1 = SD Power ON. */
-module_param(sd_power, uint, 0);
-
-extern uint sd_clock;	/* SD Clock Control, 0 = SD Clock OFF, 1 = SD Clock ON */
-module_param(sd_clock, uint, 0);
-
-extern uint sd_divisor;	/* Divisor (-1 means external clock) */
-module_param(sd_divisor, uint, 0);
-
-extern uint sd_sdmode;	/* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */
-module_param(sd_sdmode, uint, 0);
-
-extern uint sd_hiok;	/* Ok to use hi-speed mode */
-module_param(sd_hiok, uint, 0);
-
-extern uint sd_f2_blocksize;
-module_param(sd_f2_blocksize, int, 0);
-
-#ifdef BCMSDIOH_STD
-extern int sd_uhsimode;
-module_param(sd_uhsimode, int, 0);
-extern uint sd_tuning_period;
-module_param(sd_tuning_period, uint, 0);
-extern int sd_delay_value;
-module_param(sd_delay_value, uint, 0);
-
-/* SDIO Drive Strength for UHSI mode specific to SDIO3.0 */
-extern char dhd_sdiod_uhsi_ds_override[2];
-module_param_string(dhd_sdiod_uhsi_ds_override, dhd_sdiod_uhsi_ds_override, 2, 0);
-
-#endif
-
-#ifdef BCMSDH_MODULE
-EXPORT_SYMBOL(bcmsdh_attach);
-EXPORT_SYMBOL(bcmsdh_detach);
-EXPORT_SYMBOL(bcmsdh_intr_query);
-EXPORT_SYMBOL(bcmsdh_intr_enable);
-EXPORT_SYMBOL(bcmsdh_intr_disable);
-EXPORT_SYMBOL(bcmsdh_intr_reg);
-EXPORT_SYMBOL(bcmsdh_intr_dereg);
-
-#if defined(DHD_DEBUG)
-EXPORT_SYMBOL(bcmsdh_intr_pending);
-#endif
-
-EXPORT_SYMBOL(bcmsdh_devremove_reg);
-EXPORT_SYMBOL(bcmsdh_cfg_read);
-EXPORT_SYMBOL(bcmsdh_cfg_write);
-EXPORT_SYMBOL(bcmsdh_cis_read);
-EXPORT_SYMBOL(bcmsdh_reg_read);
-EXPORT_SYMBOL(bcmsdh_reg_write);
-EXPORT_SYMBOL(bcmsdh_regfail);
-EXPORT_SYMBOL(bcmsdh_send_buf);
-EXPORT_SYMBOL(bcmsdh_recv_buf);
-
-EXPORT_SYMBOL(bcmsdh_rwdata);
-EXPORT_SYMBOL(bcmsdh_abort);
-EXPORT_SYMBOL(bcmsdh_query_device);
-EXPORT_SYMBOL(bcmsdh_query_iofnum);
-EXPORT_SYMBOL(bcmsdh_iovar_op);
-EXPORT_SYMBOL(bcmsdh_register);
-EXPORT_SYMBOL(bcmsdh_unregister);
-EXPORT_SYMBOL(bcmsdh_chipmatch);
-EXPORT_SYMBOL(bcmsdh_reset);
-EXPORT_SYMBOL(bcmsdh_waitlockfree);
-
-EXPORT_SYMBOL(bcmsdh_get_dstatus);
-EXPORT_SYMBOL(bcmsdh_cfg_read_word);
-EXPORT_SYMBOL(bcmsdh_cfg_write_word);
-EXPORT_SYMBOL(bcmsdh_cur_sbwad);
-EXPORT_SYMBOL(bcmsdh_chipinfo);
-
-#endif /* BCMSDH_MODULE */
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
deleted file mode 100644
index 199522e..0000000
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
+++ /dev/null
@@ -1,1472 +0,0 @@
-/*
- * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Proprietary,Open:>>
- *
- * $Id: bcmsdh_sdmmc.c 591104 2015-10-07 04:45:18Z $
- */
-#include <typedefs.h>
-
-#include <bcmdevs.h>
-#include <bcmendian.h>
-#include <bcmutils.h>
-#include <osl.h>
-#include <sdio.h>	/* SDIO Device and Protocol Specs */
-#include <sdioh.h>	/* Standard SDIO Host Controller Specification */
-#include <bcmsdbus.h>	/* bcmsdh to/from specific controller APIs */
-#include <sdiovar.h>	/* ioctl/iovars */
-
-#include <linux/mmc/core.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
-#include <linux/suspend.h>
-extern volatile bool dhd_mmc_suspend;
-#endif
-#include "bcmsdh_sdmmc.h"
-
-#ifndef BCMSDH_MODULE
-extern int sdio_function_init(void);
-extern void sdio_function_cleanup(void);
-#endif /* BCMSDH_MODULE */
-
-#if !defined(OOB_INTR_ONLY)
-static void IRQHandler(struct sdio_func *func);
-static void IRQHandlerF2(struct sdio_func *func);
-#endif /* !defined(OOB_INTR_ONLY) */
-static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
-extern int sdio_reset_comm(struct mmc_card *card);
-
-#define DEFAULT_SDIO_F2_BLKSIZE		512
-#ifndef CUSTOM_SDIO_F2_BLKSIZE
-#define CUSTOM_SDIO_F2_BLKSIZE		DEFAULT_SDIO_F2_BLKSIZE
-#endif
-
-#define MAX_IO_RW_EXTENDED_BLK		511
-
-uint sd_sdmode = SDIOH_MODE_SD4;	/* Use SD4 mode by default */
-uint sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE;
-uint sd_divisor = 2;			/* Default 48MHz/2 = 24MHz */
-
-uint sd_power = 1;		/* Default to SD Slot powered ON */
-uint sd_clock = 1;		/* Default to SD Clock turned ON */
-uint sd_hiok = FALSE;	/* Don't use hi-speed mode by default */
-uint sd_msglevel = 0x01;
-uint sd_use_dma = TRUE;
-
-#ifndef CUSTOM_RXCHAIN
-#define CUSTOM_RXCHAIN 0
-#endif
-
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
-
-#define DMA_ALIGN_MASK	0x03
-#define MMC_SDIO_ABORT_RETRY_LIMIT 5
-
-int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data);
-
-static int
-sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
-{
-	int err_ret;
-	uint32 fbraddr;
-	uint8 func;
-
-	sd_trace(("%s\n", __FUNCTION__));
-
-	/* Get the Card's common CIS address */
-	sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0);
-	sd->func_cis_ptr[0] = sd->com_cis_ptr;
-	sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
-
-	/* Get the Card's function CIS (for each function) */
-	for (fbraddr = SDIOD_FBR_STARTADDR, func = 1;
-	     func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
-		sd->func_cis_ptr[func] = sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr);
-		sd_info(("%s: Function %d CIS Ptr = 0x%x\n",
-		         __FUNCTION__, func, sd->func_cis_ptr[func]));
-	}
-
-	sd->func_cis_ptr[0] = sd->com_cis_ptr;
-	sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
-
-	/* Enable Function 1 */
-	sdio_claim_host(sd->func[1]);
-	err_ret = sdio_enable_func(sd->func[1]);
-	sdio_release_host(sd->func[1]);
-	if (err_ret) {
-		sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret));
-	}
-
-	return FALSE;
-}
-
-/*
- *	Public entry points & extern's
- */
-extern sdioh_info_t *
-sdioh_attach(osl_t *osh, struct sdio_func *func)
-{
-	sdioh_info_t *sd = NULL;
-	int err_ret;
-
-	sd_trace(("%s\n", __FUNCTION__));
-
-	if (func == NULL) {
-		sd_err(("%s: sdio function device is NULL\n", __FUNCTION__));
-		return NULL;
-	}
-
-	if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
-		sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh)));
-		return NULL;
-	}
-	bzero((char *)sd, sizeof(sdioh_info_t));
-	sd->osh = osh;
-	sd->fake_func0.num = 0;
-	sd->fake_func0.card = func->card;
-	sd->func[0] = &sd->fake_func0;
-	sd->func[1] = func->card->sdio_func[0];
-	sd->func[2] = func->card->sdio_func[1];
-	sd->num_funcs = 2;
-	sd->sd_blockmode = TRUE;
-	sd->use_client_ints = TRUE;
-	sd->client_block_size[0] = 64;
-	sd->use_rxchain = CUSTOM_RXCHAIN;
-	if (sd->func[1] == NULL || sd->func[2] == NULL) {
-		sd_err(("%s: func 1 or 2 is null \n", __FUNCTION__));
-		goto fail;
-	}
-	sdio_set_drvdata(sd->func[1], sd);
-
-	sdio_claim_host(sd->func[1]);
-	sd->client_block_size[1] = 64;
-	err_ret = sdio_set_block_size(sd->func[1], 64);
-	sdio_release_host(sd->func[1]);
-	if (err_ret) {
-		sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize(%d)\n", err_ret));
-		goto fail;
-	}
-
-	sdio_claim_host(sd->func[2]);
-	sd->client_block_size[2] = sd_f2_blocksize;
-	err_ret = sdio_set_block_size(sd->func[2], sd_f2_blocksize);
-	sdio_release_host(sd->func[2]);
-	if (err_ret) {
-		sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize to %d(%d)\n",
-			sd_f2_blocksize, err_ret));
-		goto fail;
-	}
-
-	sdioh_sdmmc_card_enablefuncs(sd);
-
-	sd_trace(("%s: Done\n", __FUNCTION__));
-	return sd;
-
-fail:
-	MFREE(sd->osh, sd, sizeof(sdioh_info_t));
-	return NULL;
-}
-
-
-extern SDIOH_API_RC
-sdioh_detach(osl_t *osh, sdioh_info_t *sd)
-{
-	sd_trace(("%s\n", __FUNCTION__));
-
-	if (sd) {
-
-		/* Disable Function 2 */
-		if (sd->func[2]) {
-			sdio_claim_host(sd->func[2]);
-			sdio_disable_func(sd->func[2]);
-			sdio_release_host(sd->func[2]);
-		}
-
-		/* Disable Function 1 */
-		if (sd->func[1]) {
-			sdio_claim_host(sd->func[1]);
-			sdio_disable_func(sd->func[1]);
-			sdio_release_host(sd->func[1]);
-		}
-
-		sd->func[1] = NULL;
-		sd->func[2] = NULL;
-
-		MFREE(sd->osh, sd, sizeof(sdioh_info_t));
-	}
-	return SDIOH_API_RC_SUCCESS;
-}
-
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-
-extern SDIOH_API_RC
-sdioh_enable_func_intr(sdioh_info_t *sd)
-{
-	uint8 reg;
-	int err;
-
-	if (sd->func[0] == NULL) {
-		sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__));
-		return SDIOH_API_RC_FAIL;
-	}
-
-	sdio_claim_host(sd->func[0]);
-	reg = sdio_readb(sd->func[0], SDIOD_CCCR_INTEN, &err);
-	if (err) {
-		sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
-		sdio_release_host(sd->func[0]);
-		return SDIOH_API_RC_FAIL;
-	}
-	/* Enable F1 and F2 interrupts, clear master enable */
-	reg &= ~INTR_CTL_MASTER_EN;
-	reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
-	sdio_writeb(sd->func[0], reg, SDIOD_CCCR_INTEN, &err);
-	sdio_release_host(sd->func[0]);
-
-	if (err) {
-		sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
-		return SDIOH_API_RC_FAIL;
-	}
-
-	return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_disable_func_intr(sdioh_info_t *sd)
-{
-	uint8 reg;
-	int err;
-
-	if (sd->func[0] == NULL) {
-		sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__));
-		return SDIOH_API_RC_FAIL;
-	}
-
-	sdio_claim_host(sd->func[0]);
-	reg = sdio_readb(sd->func[0], SDIOD_CCCR_INTEN, &err);
-	if (err) {
-		sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
-		sdio_release_host(sd->func[0]);
-		return SDIOH_API_RC_FAIL;
-	}
-	reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
-	/* Disable master interrupt with the last function interrupt */
-	if (!(reg & 0xFE))
-		reg = 0;
-	sdio_writeb(sd->func[0], reg, SDIOD_CCCR_INTEN, &err);
-	sdio_release_host(sd->func[0]);
-
-	if (err) {
-		sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
-		return SDIOH_API_RC_FAIL;
-	}
-
-	return SDIOH_API_RC_SUCCESS;
-}
-#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
-
-/* Configure callback to client when we recieve client interrupt */
-extern SDIOH_API_RC
-sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
-{
-	sd_trace(("%s: Entering\n", __FUNCTION__));
-	if (fn == NULL) {
-		sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__));
-		return SDIOH_API_RC_FAIL;
-	}
-#if !defined(OOB_INTR_ONLY)
-	sd->intr_handler = fn;
-	sd->intr_handler_arg = argh;
-	sd->intr_handler_valid = TRUE;
-
-	/* register and unmask irq */
-	if (sd->func[2]) {
-		sdio_claim_host(sd->func[2]);
-		sdio_claim_irq(sd->func[2], IRQHandlerF2);
-		sdio_release_host(sd->func[2]);
-	}
-
-	if (sd->func[1]) {
-		sdio_claim_host(sd->func[1]);
-		sdio_claim_irq(sd->func[1], IRQHandler);
-		sdio_release_host(sd->func[1]);
-	}
-#elif defined(HW_OOB)
-	sdioh_enable_func_intr(sd);
-#endif /* !defined(OOB_INTR_ONLY) */
-
-	return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_interrupt_deregister(sdioh_info_t *sd)
-{
-	sd_trace(("%s: Entering\n", __FUNCTION__));
-
-#if !defined(OOB_INTR_ONLY)
-	if (sd->func[1]) {
-		/* register and unmask irq */
-		sdio_claim_host(sd->func[1]);
-		sdio_release_irq(sd->func[1]);
-		sdio_release_host(sd->func[1]);
-	}
-
-	if (sd->func[2]) {
-		/* Claim host controller F2 */
-		sdio_claim_host(sd->func[2]);
-		sdio_release_irq(sd->func[2]);
-		/* Release host controller F2 */
-		sdio_release_host(sd->func[2]);
-	}
-
-	sd->intr_handler_valid = FALSE;
-	sd->intr_handler = NULL;
-	sd->intr_handler_arg = NULL;
-#elif defined(HW_OOB)
-	sdioh_disable_func_intr(sd);
-#endif /* !defined(OOB_INTR_ONLY) */
-	return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
-{
-	sd_trace(("%s: Entering\n", __FUNCTION__));
-	*onoff = sd->client_intr_enabled;
-	return SDIOH_API_RC_SUCCESS;
-}
-
-#if defined(DHD_DEBUG)
-extern bool
-sdioh_interrupt_pending(sdioh_info_t *sd)
-{
-	return (0);
-}
-#endif
-
-uint
-sdioh_query_iofnum(sdioh_info_t *sd)
-{
-	return sd->num_funcs;
-}
-
-/* IOVar table */
-enum {
-	IOV_MSGLEVEL = 1,
-	IOV_BLOCKMODE,
-	IOV_BLOCKSIZE,
-	IOV_DMA,
-	IOV_USEINTS,
-	IOV_NUMINTS,
-	IOV_NUMLOCALINTS,
-	IOV_HOSTREG,
-	IOV_DEVREG,
-	IOV_DIVISOR,
-	IOV_SDMODE,
-	IOV_HISPEED,
-	IOV_HCIREGS,
-	IOV_POWER,
-	IOV_CLOCK,
-	IOV_RXCHAIN
-};
-
-const bcm_iovar_t sdioh_iovars[] = {
-	{"sd_msglevel", IOV_MSGLEVEL,	0,	IOVT_UINT32,	0 },
-	{"sd_blockmode", IOV_BLOCKMODE, 0,	IOVT_BOOL,	0 },
-	{"sd_blocksize", IOV_BLOCKSIZE, 0,	IOVT_UINT32,	0 }, /* ((fn << 16) | size) */
-	{"sd_dma",	IOV_DMA,	0,	IOVT_BOOL,	0 },
-	{"sd_ints", 	IOV_USEINTS,	0,	IOVT_BOOL,	0 },
-	{"sd_numints",	IOV_NUMINTS,	0,	IOVT_UINT32,	0 },
-	{"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32,	0 },
-	{"sd_hostreg",	IOV_HOSTREG,	0,	IOVT_BUFFER,	sizeof(sdreg_t) },
-	{"sd_devreg",	IOV_DEVREG, 	0,	IOVT_BUFFER,	sizeof(sdreg_t) },
-	{"sd_divisor",	IOV_DIVISOR,	0,	IOVT_UINT32,	0 },
-	{"sd_power",	IOV_POWER,	0,	IOVT_UINT32,	0 },
-	{"sd_clock",	IOV_CLOCK,	0,	IOVT_UINT32,	0 },
-	{"sd_mode", 	IOV_SDMODE, 	0,	IOVT_UINT32,	100},
-	{"sd_highspeed", IOV_HISPEED,	0,	IOVT_UINT32,	0 },
-	{"sd_rxchain",  IOV_RXCHAIN,    0, 	IOVT_BOOL,	0 },
-	{NULL, 0, 0, 0, 0 }
-};
-
-int
-sdioh_iovar_op(sdioh_info_t *si, const char *name,
-                           void *params, int plen, void *arg, int len, bool set)
-{
-	const bcm_iovar_t *vi = NULL;
-	int bcmerror = 0;
-	int val_size;
-	int32 int_val = 0;
-	bool bool_val;
-	uint32 actionid;
-
-	ASSERT(name);
-	ASSERT(len >= 0);
-
-	/* Get must have return space; Set does not take qualifiers */
-	ASSERT(set || (arg && len));
-	ASSERT(!set || (!params && !plen));
-
-	sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
-
-	if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
-		bcmerror = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
-		goto exit;
-
-	/* Set up params so get and set can share the convenience variables */
-	if (params == NULL) {
-		params = arg;
-		plen = len;
-	}
-
-	if (vi->type == IOVT_VOID)
-		val_size = 0;
-	else if (vi->type == IOVT_BUFFER)
-		val_size = len;
-	else
-		val_size = sizeof(int);
-
-	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
-
-	bool_val = (int_val != 0) ? TRUE : FALSE;
-	BCM_REFERENCE(bool_val);
-
-	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
-	switch (actionid) {
-	case IOV_GVAL(IOV_MSGLEVEL):
-		int_val = (int32)sd_msglevel;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_MSGLEVEL):
-		sd_msglevel = int_val;
-		break;
-
-	case IOV_GVAL(IOV_BLOCKMODE):
-		int_val = (int32)si->sd_blockmode;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_BLOCKMODE):
-		si->sd_blockmode = (bool)int_val;
-		/* Haven't figured out how to make non-block mode with DMA */
-		break;
-
-	case IOV_GVAL(IOV_BLOCKSIZE):
-		if ((uint32)int_val > si->num_funcs) {
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		int_val = (int32)si->client_block_size[int_val];
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_BLOCKSIZE):
-	{
-		uint func = ((uint32)int_val >> 16);
-		uint blksize = (uint16)int_val;
-		uint maxsize;
-
-		if (func > si->num_funcs) {
-			bcmerror = BCME_BADARG;
-			break;
-		}
-
-		switch (func) {
-		case 0: maxsize = 32; break;
-		case 1: maxsize = BLOCK_SIZE_4318; break;
-		case 2: maxsize = BLOCK_SIZE_4328; break;
-		default: maxsize = 0;
-		}
-		if (blksize > maxsize) {
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		if (!blksize) {
-			blksize = maxsize;
-		}
-
-		/* Now set it */
-		si->client_block_size[func] = blksize;
-
-#ifdef USE_DYNAMIC_F2_BLKSIZE
-		if (si->func[func] == NULL) {
-			sd_err(("%s: SDIO Device not present\n", __FUNCTION__));
-			bcmerror = BCME_NORESOURCE;
-			break;
-		}
-		sdio_claim_host(si->func[func]);
-		bcmerror = sdio_set_block_size(si->func[func], blksize);
-		if (bcmerror)
-			sd_err(("%s: Failed to set F%d blocksize to %d(%d)\n",
-				__FUNCTION__, func, blksize, bcmerror));
-		sdio_release_host(si->func[func]);
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
-		break;
-	}
-
-	case IOV_GVAL(IOV_RXCHAIN):
-		int_val = (int32)si->use_rxchain;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_DMA):
-		int_val = (int32)si->sd_use_dma;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DMA):
-		si->sd_use_dma = (bool)int_val;
-		break;
-
-	case IOV_GVAL(IOV_USEINTS):
-		int_val = (int32)si->use_client_ints;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_USEINTS):
-		si->use_client_ints = (bool)int_val;
-		if (si->use_client_ints)
-			si->intmask |= CLIENT_INTR;
-		else
-			si->intmask &= ~CLIENT_INTR;
-
-		break;
-
-	case IOV_GVAL(IOV_DIVISOR):
-		int_val = (uint32)sd_divisor;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DIVISOR):
-		sd_divisor = int_val;
-		break;
-
-	case IOV_GVAL(IOV_POWER):
-		int_val = (uint32)sd_power;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_POWER):
-		sd_power = int_val;
-		break;
-
-	case IOV_GVAL(IOV_CLOCK):
-		int_val = (uint32)sd_clock;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_CLOCK):
-		sd_clock = int_val;
-		break;
-
-	case IOV_GVAL(IOV_SDMODE):
-		int_val = (uint32)sd_sdmode;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_SDMODE):
-		sd_sdmode = int_val;
-		break;
-
-	case IOV_GVAL(IOV_HISPEED):
-		int_val = (uint32)sd_hiok;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_HISPEED):
-		sd_hiok = int_val;
-		break;
-
-	case IOV_GVAL(IOV_NUMINTS):
-		int_val = (int32)si->intrcount;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_NUMLOCALINTS):
-		int_val = (int32)0;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_HOSTREG):
-	{
-		sdreg_t *sd_ptr = (sdreg_t *)params;
-
-		if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) {
-			sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-
-		sd_trace(("%s: rreg%d at offset %d\n", __FUNCTION__,
-		                  (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32),
-		                  sd_ptr->offset));
-		if (sd_ptr->offset & 1)
-			int_val = 8; /* sdioh_sdmmc_rreg8(si, sd_ptr->offset); */
-		else if (sd_ptr->offset & 2)
-			int_val = 16; /* sdioh_sdmmc_rreg16(si, sd_ptr->offset); */
-		else
-			int_val = 32; /* sdioh_sdmmc_rreg(si, sd_ptr->offset); */
-
-		bcopy(&int_val, arg, sizeof(int_val));
-		break;
-	}
-
-	case IOV_SVAL(IOV_HOSTREG):
-	{
-		sdreg_t *sd_ptr = (sdreg_t *)params;
-
-		if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) {
-			sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-
-		sd_trace(("%s: wreg%d value 0x%08x at offset %d\n", __FUNCTION__, sd_ptr->value,
-		                  (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32),
-		                  sd_ptr->offset));
-		break;
-	}
-
-	case IOV_GVAL(IOV_DEVREG):
-	{
-		sdreg_t *sd_ptr = (sdreg_t *)params;
-		uint8 data = 0;
-
-		if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) {
-			bcmerror = BCME_SDIO_ERROR;
-			break;
-		}
-
-		int_val = (int)data;
-		bcopy(&int_val, arg, sizeof(int_val));
-		break;
-	}
-
-	case IOV_SVAL(IOV_DEVREG):
-	{
-		sdreg_t *sd_ptr = (sdreg_t *)params;
-		uint8 data = (uint8)sd_ptr->value;
-
-		if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) {
-			bcmerror = BCME_SDIO_ERROR;
-			break;
-		}
-		break;
-	}
-
-	default:
-		bcmerror = BCME_UNSUPPORTED;
-		break;
-	}
-exit:
-
-	return bcmerror;
-}
-
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-
-SDIOH_API_RC
-sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
-{
-	SDIOH_API_RC status;
-	uint8 data;
-
-	if (enable)
-		data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE | SDIO_SEPINT_ACT_HI;
-	else
-		data = SDIO_SEPINT_ACT_HI;	/* disable hw oob interrupt */
-
-	status = sdioh_request_byte(sd, SDIOH_WRITE, 0, SDIOD_CCCR_BRCM_SEPINT, &data);
-	return status;
-}
-#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
-
-extern SDIOH_API_RC
-sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
-{
-	SDIOH_API_RC status;
-	/* No lock needed since sdioh_request_byte does locking */
-	status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
-	return status;
-}
-
-extern SDIOH_API_RC
-sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
-{
-	/* No lock needed since sdioh_request_byte does locking */
-	SDIOH_API_RC status;
-	status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
-	return status;
-}
-
-static int
-sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr)
-{
-	/* read 24 bits and return valid 17 bit addr */
-	int i;
-	uint32 scratch, regdata;
-	uint8 *ptr = (uint8 *)&scratch;
-	for (i = 0; i < 3; i++) {
-		if ((sdioh_sdmmc_card_regread (sd, 0, regaddr, 1, &regdata)) != SUCCESS)
-			sd_err(("%s: Can't read!\n", __FUNCTION__));
-
-		*ptr++ = (uint8) regdata;
-		regaddr++;
-	}
-
-	/* Only the lower 17-bits are valid */
-	scratch = ltoh32(scratch);
-	scratch &= 0x0001FFFF;
-	return (scratch);
-}
-
-extern SDIOH_API_RC
-sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
-{
-	uint32 count;
-	int offset;
-	uint32 foo;
-	uint8 *cis = cisd;
-
-	sd_trace(("%s: Func = %d\n", __FUNCTION__, func));
-
-	if (!sd->func_cis_ptr[func]) {
-		bzero(cis, length);
-		sd_err(("%s: no func_cis_ptr[%d]\n", __FUNCTION__, func));
-		return SDIOH_API_RC_FAIL;
-	}
-
-	sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__, func, sd->func_cis_ptr[func]));
-
-	for (count = 0; count < length; count++) {
-		offset =  sd->func_cis_ptr[func] + count;
-		if (sdioh_sdmmc_card_regread (sd, 0, offset, 1, &foo) < 0) {
-			sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
-			return SDIOH_API_RC_FAIL;
-		}
-
-		*cis = (uint8)(foo & 0xff);
-		cis++;
-	}
-
-	return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
-{
-	int err_ret = 0;
-#if defined(MMC_SDIO_ABORT)
-	int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT;
-#endif
-
-	sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr));
-
-	DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
-	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
-	if(rw) { /* CMD52 Write */
-		if (func == 0) {
-			/* Can only directly write to some F0 registers.  Handle F2 enable
-			 * as a special case.
-			 */
-			if (regaddr == SDIOD_CCCR_IOEN) {
-				if (sd->func[2]) {
-					sdio_claim_host(sd->func[2]);
-					if (*byte & SDIO_FUNC_ENABLE_2) {
-						/* Enable Function 2 */
-						err_ret = sdio_enable_func(sd->func[2]);
-						if (err_ret) {
-							sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
-								err_ret));
-						}
-					} else {
-						/* Disable Function 2 */
-						err_ret = sdio_disable_func(sd->func[2]);
-						if (err_ret) {
-							sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
-								err_ret));
-						}
-					}
-					sdio_release_host(sd->func[2]);
-				}
-			}
-#if defined(MMC_SDIO_ABORT)
-			/* to allow abort command through F1 */
-			else if (regaddr == SDIOD_CCCR_IOABORT) {
-				while (sdio_abort_retry--) {
-					if (sd->func[func]) {
-						sdio_claim_host(sd->func[func]);
-						/*
-						 * this sdio_f0_writeb() can be replaced with
-						 * another api depending upon MMC driver change.
-						 * As of this time, this is temporaray one
-						 */
-						sdio_writeb(sd->func[func],
-							*byte, regaddr, &err_ret);
-						sdio_release_host(sd->func[func]);
-					}
-					if (!err_ret)
-						break;
-				}
-			}
-#endif /* MMC_SDIO_ABORT */
-			else if (regaddr < 0xF0) {
-				sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
-			} else {
-				/* Claim host controller, perform F0 write, and release */
-				if (sd->func[func]) {
-					sdio_claim_host(sd->func[func]);
-					sdio_f0_writeb(sd->func[func],
-						*byte, regaddr, &err_ret);
-					sdio_release_host(sd->func[func]);
-				}
-			}
-		} else {
-			/* Claim host controller, perform Fn write, and release */
-			if (sd->func[func]) {
-				sdio_claim_host(sd->func[func]);
-				sdio_writeb(sd->func[func], *byte, regaddr, &err_ret);
-				sdio_release_host(sd->func[func]);
-			}
-		}
-	} else { /* CMD52 Read */
-		/* Claim host controller, perform Fn read, and release */
-		if (sd->func[func]) {
-			sdio_claim_host(sd->func[func]);
-			if (func == 0) {
-				*byte = sdio_f0_readb(sd->func[func], regaddr, &err_ret);
-			} else {
-				*byte = sdio_readb(sd->func[func], regaddr, &err_ret);
-			}
-			sdio_release_host(sd->func[func]);
-		}
-	}
-
-	if (err_ret) {
-		if ((regaddr == 0x1001F) && ((err_ret == -ETIMEDOUT) || (err_ret == -EILSEQ))) {
-		} else {
-			sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
-				rw ? "Write" : "Read", func, regaddr, *byte, err_ret));
-		}
-	}
-
-	return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
-}
-
-extern SDIOH_API_RC
-sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
-                                   uint32 *word, uint nbytes)
-{
-	int err_ret = SDIOH_API_RC_FAIL;
-#if defined(MMC_SDIO_ABORT)
-	int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT;
-#endif
-
-	if (func == 0) {
-		sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__));
-		return SDIOH_API_RC_FAIL;
-	}
-
-	sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
-	         __FUNCTION__, cmd_type, rw, func, addr, nbytes));
-
-	DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
-	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
-	/* Claim host controller */
-	sdio_claim_host(sd->func[func]);
-
-	if(rw) { /* CMD52 Write */
-		if (nbytes == 4) {
-			sdio_writel(sd->func[func], *word, addr, &err_ret);
-		} else if (nbytes == 2) {
-			sdio_writew(sd->func[func], (*word & 0xFFFF), addr, &err_ret);
-		} else {
-			sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
-		}
-	} else { /* CMD52 Read */
-		if (nbytes == 4) {
-			*word = sdio_readl(sd->func[func], addr, &err_ret);
-		} else if (nbytes == 2) {
-			*word = sdio_readw(sd->func[func], addr, &err_ret) & 0xFFFF;
-		} else {
-			sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
-		}
-	}
-
-	/* Release host controller */
-	sdio_release_host(sd->func[func]);
-
-	if (err_ret) {
-#if defined(MMC_SDIO_ABORT)
-		/* Any error on CMD53 transaction should abort that function using function 0. */
-		while (sdio_abort_retry--) {
-			if (sd->func[0]) {
-				sdio_claim_host(sd->func[0]);
-				/*
-				 * this sdio_f0_writeb() can be replaced with another api
-				 * depending upon MMC driver change.
-				 * As of this time, this is temporaray one
-				 */
-				sdio_writeb(sd->func[0],
-					func, SDIOD_CCCR_IOABORT, &err_ret);
-				sdio_release_host(sd->func[0]);
-			}
-			if (!err_ret)
-				break;
-		}
-		if (err_ret)
-#endif /* MMC_SDIO_ABORT */
-		{
-			sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
-				rw ? "Write" : "Read", err_ret));
-		}
-	}
-
-	return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
-}
-
-static SDIOH_API_RC
-sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
-                     uint addr, void *pkt)
-{
-	bool fifo = (fix_inc == SDIOH_DATA_FIX);
-	int err_ret = 0;
-	void *pnext;
-	uint ttl_len, pkt_offset;
-	uint blk_num;
-	uint blk_size;
-	uint max_blk_count;
-	uint max_req_size;
-	struct mmc_request mmc_req;
-	struct mmc_command mmc_cmd;
-	struct mmc_data mmc_dat;
-	uint32 sg_count;
-	struct sdio_func *sdio_func = sd->func[func];
-	struct mmc_host *host = sdio_func->card->host;
-
-	sd_trace(("%s: Enter\n", __FUNCTION__));
-	ASSERT(pkt);
-	DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
-	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
-
-	blk_size = sd->client_block_size[func];
-	max_blk_count = min(host->max_blk_count, (uint)MAX_IO_RW_EXTENDED_BLK);
-	max_req_size = min(max_blk_count * blk_size, host->max_req_size);
-
-	pkt_offset = 0;
-	pnext = pkt;
-
-	while (pnext != NULL) {
-		ttl_len = 0;
-		sg_count = 0;
-		memset(&mmc_req, 0, sizeof(struct mmc_request));
-		memset(&mmc_cmd, 0, sizeof(struct mmc_command));
-		memset(&mmc_dat, 0, sizeof(struct mmc_data));
-		sg_init_table(sd->sg_list, ARRAYSIZE(sd->sg_list));
-
-		/* Set up scatter-gather DMA descriptors. this loop is to find out the max
-		 * data we can transfer with one command 53. blocks per command is limited by
-		 * host max_req_size and 9-bit max block number. when the total length of this
-		 * packet chain is bigger than max_req_size, use multiple SD_IO_RW_EXTENDED
-		 * commands (each transfer is still block aligned)
-		 */
-		while (pnext != NULL && ttl_len < max_req_size) {
-			int pkt_len;
-			int sg_data_size;
-			uint8 *pdata = (uint8*)PKTDATA(sd->osh, pnext);
-
-			ASSERT(pdata != NULL);
-			pkt_len = PKTLEN(sd->osh, pnext);
-			sd_trace(("%s[%d] data=%p, len=%d\n", __FUNCTION__, write, pdata, pkt_len));
-			/* sg_count is unlikely larger than the array size, and this is
-			 * NOT something we can handle here, but in case it happens, PLEASE put
-			 * a restriction on max tx/glom count (based on host->max_segs).
-			 */
-			if (sg_count >= ARRAYSIZE(sd->sg_list)) {
-				sd_err(("%s: sg list entries exceed limit\n", __FUNCTION__));
-				return (SDIOH_API_RC_FAIL);
-			}
-			pdata += pkt_offset;
-
-			sg_data_size = pkt_len - pkt_offset;
-			if (sg_data_size > max_req_size - ttl_len)
-				sg_data_size = max_req_size - ttl_len;
-			/* some platforms put a restriction on the data size of each scatter-gather
-			 * DMA descriptor, use multiple sg buffers when xfer_size is bigger than
-			 * max_seg_size
-			 */
-			if (sg_data_size > host->max_seg_size)
-				sg_data_size = host->max_seg_size;
-			sg_set_buf(&sd->sg_list[sg_count++], pdata, sg_data_size);
-
-			ttl_len += sg_data_size;
-			pkt_offset += sg_data_size;
-			if (pkt_offset == pkt_len) {
-				pnext = PKTNEXT(sd->osh, pnext);
-				pkt_offset = 0;
-			}
-		}
-
-		if (ttl_len % blk_size != 0) {
-			sd_err(("%s, data length %d not aligned to block size %d\n",
-				__FUNCTION__,  ttl_len, blk_size));
-			return SDIOH_API_RC_FAIL;
-		}
-		blk_num = ttl_len / blk_size;
-		mmc_dat.sg = sd->sg_list;
-		mmc_dat.sg_len = sg_count;
-		mmc_dat.blksz = blk_size;
-		mmc_dat.blocks = blk_num;
-		mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
-		mmc_cmd.opcode = 53; /* SD_IO_RW_EXTENDED */
-		mmc_cmd.arg = write ? 1<<31 : 0;
-		mmc_cmd.arg |= (func & 0x7) << 28;
-		mmc_cmd.arg |= 1<<27;
-		mmc_cmd.arg |= fifo ? 0 : 1<<26;
-		mmc_cmd.arg |= (addr & 0x1FFFF) << 9;
-		mmc_cmd.arg |= blk_num & 0x1FF;
-		mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
-		mmc_req.cmd = &mmc_cmd;
-		mmc_req.data = &mmc_dat;
-		if (!fifo)
-			addr += ttl_len;
-
-		sdio_claim_host(sdio_func);
-		mmc_set_data_timeout(&mmc_dat, sdio_func->card);
-		mmc_wait_for_req(host, &mmc_req);
-		sdio_release_host(sdio_func);
-
-		err_ret = mmc_cmd.error? mmc_cmd.error : mmc_dat.error;
-		if (0 != err_ret) {
-			sd_err(("%s:CMD53 %s failed with code %d\n",
-				__FUNCTION__, write ? "write" : "read", err_ret));
-			return SDIOH_API_RC_FAIL;
-		}
-	}
-
-	sd_trace(("%s: Exit\n", __FUNCTION__));
-	return SDIOH_API_RC_SUCCESS;
-}
-
-static SDIOH_API_RC
-sdioh_buffer_tofrom_bus(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
-                     uint addr, uint8 *buf, uint len)
-{
-	bool fifo = (fix_inc == SDIOH_DATA_FIX);
-	int err_ret = 0;
-
-	sd_trace(("%s: Enter\n", __FUNCTION__));
-	ASSERT(buf);
-
-	/* NOTE:
-	 * For all writes, each packet length is aligned to 32 (or 4)
-	 * bytes in dhdsdio_txpkt_preprocess, and for glom the last packet length
-	 * is aligned to block boundary. If you want to align each packet to
-	 * a custom size, please do it in dhdsdio_txpkt_preprocess, NOT here
-	 *
-	 * For reads, the alignment is doen in sdioh_request_buffer.
-	 *
-	 */
-	sdio_claim_host(sd->func[func]);
-
-	if ((write) && (!fifo))
-		err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, len);
-	else if (write)
-		err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, len);
-	else if (fifo)
-		err_ret = sdio_readsb(sd->func[func], buf, addr, len);
-	else
-		err_ret = sdio_memcpy_fromio(sd->func[func], buf, addr, len);
-
-	sdio_release_host(sd->func[func]);
-
-	if (err_ret)
-		sd_err(("%s: %s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=%d\n", __FUNCTION__,
-		       (write) ? "TX" : "RX", buf, addr, len, err_ret));
-	else
-		sd_trace(("%s: %s xfr'd %p, addr=0x%05x, len=%d\n", __FUNCTION__,
-			(write) ? "TX" : "RX", buf, addr, len));
-
-	sd_trace(("%s: Exit\n", __FUNCTION__));
-	return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
-}
-
-
-/*
- * This function takes a buffer or packet, and fixes everything up so that in the
- * end, a DMA-able packet is created.
- *
- * A buffer does not have an associated packet pointer, and may or may not be aligned.
- * A packet may consist of a single packet, or a packet chain.  If it is a packet chain,
- * then all the packets in the chain must be properly aligned.  If the packet data is not
- * aligned, then there may only be one packet, and in this case, it is copied to a new
- * aligned packet.
- *
- */
-extern SDIOH_API_RC
-sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, uint func,
-	uint addr, uint reg_width, uint buf_len, uint8 *buffer, void *pkt)
-{
-	SDIOH_API_RC status;
-	void *tmppkt;
-
-	sd_trace(("%s: Enter\n", __FUNCTION__));
-	DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
-	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
-
-	if (pkt) {
-		/* packet chain, only used for tx/rx glom, all packets length
-		 * are aligned, total length is a block multiple
-		 */
-		if (PKTNEXT(sd->osh, pkt))
-			return sdioh_request_packet_chain(sd, fix_inc, write, func, addr, pkt);
-
-		/* non-glom mode, ignore the buffer parameter and use the packet pointer
-		 * (this shouldn't happen)
-		 */
-		buffer = PKTDATA(sd->osh, pkt);
-		buf_len = PKTLEN(sd->osh, pkt);
-	}
-
-	ASSERT(buffer);
-
-	/* buffer and length are aligned, use it directly so we can avoid memory copy */
-	if (((ulong)buffer & DMA_ALIGN_MASK) == 0 && (buf_len & DMA_ALIGN_MASK) == 0)
-		return sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr, buffer, buf_len);
-
-	sd_err(("%s: [%d] doing memory copy buf=%p, len=%d\n",
-		__FUNCTION__, write, buffer, buf_len));
-
-	/* otherwise, a memory copy is needed as the input buffer is not aligned */
-	tmppkt = PKTGET_STATIC(sd->osh, buf_len + DEFAULT_SDIO_F2_BLKSIZE, write ? TRUE : FALSE);
-	if (tmppkt == NULL) {
-		sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, buf_len));
-		return SDIOH_API_RC_FAIL;
-	}
-
-	if (write)
-		bcopy(buffer, PKTDATA(sd->osh, tmppkt), buf_len);
-
-	status = sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr,
-		PKTDATA(sd->osh, tmppkt), ROUNDUP(buf_len, (DMA_ALIGN_MASK+1)));
-
-	if (!write)
-		bcopy(PKTDATA(sd->osh, tmppkt), buffer, buf_len);
-
-	PKTFREE_STATIC(sd->osh, tmppkt, write ? TRUE : FALSE);
-
-	return status;
-}
-
-/* this function performs "abort" for both of host & device */
-extern int
-sdioh_abort(sdioh_info_t *sd, uint func)
-{
-#if defined(MMC_SDIO_ABORT)
-	char t_func = (char) func;
-#endif /* defined(MMC_SDIO_ABORT) */
-	sd_trace(("%s: Enter\n", __FUNCTION__));
-
-#if defined(MMC_SDIO_ABORT)
-	/* issue abort cmd52 command through F1 */
-	sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, &t_func);
-#endif /* defined(MMC_SDIO_ABORT) */
-
-	sd_trace(("%s: Exit\n", __FUNCTION__));
-	return SDIOH_API_RC_SUCCESS;
-}
-
-/* Reset and re-initialize the device */
-int sdioh_sdio_reset(sdioh_info_t *si)
-{
-	sd_trace(("%s: Enter\n", __FUNCTION__));
-	sd_trace(("%s: Exit\n", __FUNCTION__));
-	return SDIOH_API_RC_SUCCESS;
-}
-
-/* Disable device interrupt */
-void
-sdioh_sdmmc_devintr_off(sdioh_info_t *sd)
-{
-	sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
-	sd->intmask &= ~CLIENT_INTR;
-}
-
-/* Enable device interrupt */
-void
-sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
-{
-	sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
-	sd->intmask |= CLIENT_INTR;
-}
-
-/* Read client card reg */
-int
-sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
-{
-
-	if ((func == 0) || (regsize == 1)) {
-		uint8 temp = 0;
-
-		sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
-		*data = temp;
-		*data &= 0xff;
-		sd_data(("%s: byte read data=0x%02x\n",
-		         __FUNCTION__, *data));
-	} else {
-		sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, regsize);
-		if (regsize == 2)
-			*data &= 0xffff;
-
-		sd_data(("%s: word read data=0x%08x\n",
-		         __FUNCTION__, *data));
-	}
-
-	return SUCCESS;
-}
-
-#if !defined(OOB_INTR_ONLY)
-/* bcmsdh_sdmmc interrupt handler */
-static void IRQHandler(struct sdio_func *func)
-{
-	sdioh_info_t *sd;
-
-	sd = sdio_get_drvdata(func);
-
-	ASSERT(sd != NULL);
-	sdio_release_host(sd->func[0]);
-
-	if (sd->use_client_ints) {
-		sd->intrcount++;
-		ASSERT(sd->intr_handler);
-		ASSERT(sd->intr_handler_arg);
-		(sd->intr_handler)(sd->intr_handler_arg);
-	} else {
-		sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
-
-		sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
-		        __FUNCTION__, sd->client_intr_enabled, sd->intr_handler));
-	}
-
-	sdio_claim_host(sd->func[0]);
-}
-
-/* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
-static void IRQHandlerF2(struct sdio_func *func)
-{
-	sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
-}
-#endif /* !defined(OOB_INTR_ONLY) */
-
-#ifdef NOTUSED
-/* Write client card reg */
-static int
-sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
-{
-
-	if ((func == 0) || (regsize == 1)) {
-		uint8 temp;
-
-		temp = data & 0xff;
-		sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
-		sd_data(("%s: byte write data=0x%02x\n",
-		         __FUNCTION__, data));
-	} else {
-		if (regsize == 2)
-			data &= 0xffff;
-
-		sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data, regsize);
-
-		sd_data(("%s: word write data=0x%08x\n",
-		         __FUNCTION__, data));
-	}
-
-	return SUCCESS;
-}
-#endif /* NOTUSED */
-
-int
-sdioh_start(sdioh_info_t *sd, int stage)
-{
-	int ret;
-
-	if (!sd) {
-		sd_err(("%s Failed, sd is NULL\n", __FUNCTION__));
-		return (0);
-	}
-
-	/* Need to do this stages as we can't enable the interrupt till
-		downloading of the firmware is complete, other wise polling
-		sdio access will come in way
-	*/
-	if (sd->func[0]) {
-			if (stage == 0) {
-		/* Since the power to the chip is killed, we will have
-			re enumerate the device again. Set the block size
-			and enable the fucntion 1 for in preparation for
-			downloading the code
-		*/
-		/* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux
-		   2.6.27. The implementation prior to that is buggy, and needs broadcom's
-		   patch for it
-		*/
-		if ((ret = sdio_reset_comm(sd->func[0]->card))) {
-			sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret));
-			return ret;
-		}
-		else {
-			sd->num_funcs = 2;
-			sd->sd_blockmode = TRUE;
-			sd->use_client_ints = TRUE;
-			sd->client_block_size[0] = 64;
-
-			if (sd->func[1]) {
-				/* Claim host controller */
-				sdio_claim_host(sd->func[1]);
-
-				sd->client_block_size[1] = 64;
-				ret = sdio_set_block_size(sd->func[1], 64);
-				if (ret) {
-					sd_err(("bcmsdh_sdmmc: Failed to set F1 "
-						"blocksize(%d)\n", ret));
-				}
-
-				/* Release host controller F1 */
-				sdio_release_host(sd->func[1]);
-			}
-
-			if (sd->func[2]) {
-				/* Claim host controller F2 */
-				sdio_claim_host(sd->func[2]);
-
-				sd->client_block_size[2] = sd_f2_blocksize;
-				ret = sdio_set_block_size(sd->func[2], sd_f2_blocksize);
-				if (ret) {
-					sd_err(("bcmsdh_sdmmc: Failed to set F2 "
-						"blocksize to %d(%d)\n", sd_f2_blocksize, ret));
-				}
-
-				/* Release host controller F2 */
-				sdio_release_host(sd->func[2]);
-			}
-
-			sdioh_sdmmc_card_enablefuncs(sd);
-			}
-		} else {
-#if !defined(OOB_INTR_ONLY)
-			sdio_claim_host(sd->func[0]);
-			if (sd->func[2])
-				sdio_claim_irq(sd->func[2], IRQHandlerF2);
-			if (sd->func[1])
-				sdio_claim_irq(sd->func[1], IRQHandler);
-			sdio_release_host(sd->func[0]);
-#else /* defined(OOB_INTR_ONLY) */
-#if defined(HW_OOB)
-			sdioh_enable_func_intr(sd);
-#endif
-			bcmsdh_oob_intr_set(sd->bcmsdh, TRUE);
-#endif /* !defined(OOB_INTR_ONLY) */
-		}
-	}
-	else
-		sd_err(("%s Failed\n", __FUNCTION__));
-
-	return (0);
-}
-
-int
-sdioh_stop(sdioh_info_t *sd)
-{
-	/* MSM7201A Android sdio stack has bug with interrupt
-		So internaly within SDIO stack they are polling
-		which cause issue when device is turned off. So
-		unregister interrupt with SDIO stack to stop the
-		polling
-	*/
-	if (sd->func[0]) {
-#if !defined(OOB_INTR_ONLY)
-		sdio_claim_host(sd->func[0]);
-		if (sd->func[1])
-			sdio_release_irq(sd->func[1]);
-		if (sd->func[2])
-			sdio_release_irq(sd->func[2]);
-		sdio_release_host(sd->func[0]);
-#else /* defined(OOB_INTR_ONLY) */
-#if defined(HW_OOB)
-		sdioh_disable_func_intr(sd);
-#endif
-		bcmsdh_oob_intr_set(sd->bcmsdh, FALSE);
-#endif /* !defined(OOB_INTR_ONLY) */
-	}
-	else
-		sd_err(("%s Failed\n", __FUNCTION__));
-	return (0);
-}
-
-int
-sdioh_waitlockfree(sdioh_info_t *sd)
-{
-	return (1);
-}
-
-
-SDIOH_API_RC
-sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio)
-{
-	return SDIOH_API_RC_FAIL;
-}
-
-SDIOH_API_RC
-sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab)
-{
-	return SDIOH_API_RC_FAIL;
-}
-
-bool
-sdioh_gpioin(sdioh_info_t *sd, uint32 gpio)
-{
-	return FALSE;
-}
-
-SDIOH_API_RC
-sdioh_gpio_init(sdioh_info_t *sd)
-{
-	return SDIOH_API_RC_FAIL;
-}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
deleted file mode 100644
index db41c59..0000000
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Proprietary,Open:>>
- *
- * $Id: bcmsdh_sdmmc_linux.c 591173 2015-10-07 06:24:22Z $
- */
-
-#include <typedefs.h>
-#include <bcmutils.h>
-#include <sdio.h>	/* SDIO Device and Protocol Specs */
-#include <bcmsdbus.h>	/* bcmsdh to/from specific controller APIs */
-#include <sdiovar.h>	/* to get msglevel bit values */
-
-#include <linux/sched.h>	/* request_irq() */
-
-#include <linux/mmc/core.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-#include <dhd_linux.h>
-#include <bcmsdh_sdmmc.h>
-#include <dhd_dbg.h>
-
-#if !defined(SDIO_VENDOR_ID_BROADCOM)
-#define SDIO_VENDOR_ID_BROADCOM		0x02d0
-#endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */
-
-#define SDIO_DEVICE_ID_BROADCOM_DEFAULT	0x0000
-
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)
-#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB	0x0492	/* BCM94325SDGWB */
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325)
-#define SDIO_DEVICE_ID_BROADCOM_4325	0x0493
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4329)
-#define SDIO_DEVICE_ID_BROADCOM_4329	0x4329
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4319)
-#define SDIO_DEVICE_ID_BROADCOM_4319	0x4319
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4319) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4330)
-#define SDIO_DEVICE_ID_BROADCOM_4330	0x4330
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4330) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4334)
-#define SDIO_DEVICE_ID_BROADCOM_4334    0x4334
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4334) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4324)
-#define SDIO_DEVICE_ID_BROADCOM_4324    0x4324
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4324) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_43239)
-#define SDIO_DEVICE_ID_BROADCOM_43239    43239
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_43239) */
-
-extern void wl_cfg80211_set_parent_dev(void *dev);
-extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
-extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
-extern void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bus_type,
-	uint bus_num, uint slot_num);
-extern int bcmsdh_remove(bcmsdh_info_t *bcmsdh);
-
-int sdio_function_init(void);
-void sdio_function_cleanup(void);
-
-#define DESCRIPTION "bcmsdh_sdmmc Driver"
-#define AUTHOR "Broadcom Corporation"
-
-/* module param defaults */
-static int clockoverride = 0;
-
-module_param(clockoverride, int, 0644);
-MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
-
-/* Maximum number of bcmsdh_sdmmc devices supported by driver */
-#define BCMSDH_SDMMC_MAX_DEVICES 1
-
-extern volatile bool dhd_mmc_suspend;
-
-static int sdioh_probe(struct sdio_func *func)
-{
-	int host_idx = func->card->host->index;
-	uint32 rca = func->card->rca;
-	wifi_adapter_info_t *adapter;
-	osl_t *osh = NULL;
-	sdioh_info_t *sdioh = NULL;
-
-	sd_err(("bus num (host idx)=%d, slot num (rca)=%d\n", host_idx, rca));
-	adapter = dhd_wifi_platform_get_adapter(SDIO_BUS, host_idx, rca);
-	if (adapter  != NULL)
-		sd_err(("found adapter info '%s'\n", adapter->name));
-	else
-		sd_err(("can't find adapter info for this chip\n"));
-
-#ifdef WL_CFG80211
-	wl_cfg80211_set_parent_dev(&func->dev);
-#endif
-
-	 /* allocate SDIO Host Controller state info */
-	 osh = osl_attach(&func->dev, SDIO_BUS, TRUE);
-	 if (osh == NULL) {
-		 sd_err(("%s: osl_attach failed\n", __FUNCTION__));
-		 goto fail;
-	 }
-	 osl_static_mem_init(osh, adapter);
-	 sdioh = sdioh_attach(osh, func);
-	 if (sdioh == NULL) {
-		 sd_err(("%s: sdioh_attach failed\n", __FUNCTION__));
-		 goto fail;
-	 }
-	 sdioh->bcmsdh = bcmsdh_probe(osh, &func->dev, sdioh, adapter, SDIO_BUS, host_idx, rca);
-	 if (sdioh->bcmsdh == NULL) {
-		 sd_err(("%s: bcmsdh_probe failed\n", __FUNCTION__));
-		 goto fail;
-	 }
-
-	sdio_set_drvdata(func, sdioh);
-	return 0;
-
-fail:
-	if (sdioh != NULL)
-		sdioh_detach(osh, sdioh);
-	if (osh != NULL)
-		osl_detach(osh);
-	return -ENOMEM;
-}
-
-static void sdioh_remove(struct sdio_func *func)
-{
-	sdioh_info_t *sdioh;
-	osl_t *osh;
-
-	sdioh = sdio_get_drvdata(func);
-	if (sdioh == NULL) {
-		sd_err(("%s: error, no sdioh handler found\n", __FUNCTION__));
-		return;
-	}
-
-	osh = sdioh->osh;
-	bcmsdh_remove(sdioh->bcmsdh);
-	sdioh_detach(osh, sdioh);
-	osl_detach(osh);
-}
-
-static int bcmsdh_sdmmc_probe(struct sdio_func *func,
-                              const struct sdio_device_id *id)
-{
-	int ret = 0;
-
-	if (func == NULL)
-		return -EINVAL;
-
-	sd_err(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
-	sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
-	sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
-	sd_info(("sdio_device: 0x%04x\n", func->device));
-	sd_info(("Function#: 0x%04x\n", func->num));
-
-	/* 4318 doesn't have function 2 */
-	if ((func->num == 2) || (func->num == 1 && func->device == 0x4))
-		ret = sdioh_probe(func);
-
-	return ret;
-}
-
-static void bcmsdh_sdmmc_remove(struct sdio_func *func)
-{
-	if (func == NULL) {
-		sd_err(("%s is called with NULL SDIO function pointer\n", __FUNCTION__));
-		return;
-	}
-
-	sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
-	sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
-	sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
-	sd_info(("sdio_device: 0x%04x\n", func->device));
-	sd_info(("Function#: 0x%04x\n", func->num));
-
-	if ((func->num == 2) || (func->num == 1 && func->device == 0x4))
-		sdioh_remove(func);
-}
-
-/* devices we support, null terminated */
-static const struct sdio_device_id bcmsdh_sdmmc_ids[] = {
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT) },
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) },
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325) },
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329) },
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319) },
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330) },
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334) },
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4324) },
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43239) },
-	{ SDIO_DEVICE_CLASS(SDIO_CLASS_NONE)		},
-	{ /* end: all zeroes */				},
-};
-
-MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids);
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM)
-static int bcmsdh_sdmmc_suspend(struct device *pdev)
-{
-	int err;
-	sdioh_info_t *sdioh;
-	struct sdio_func *func = dev_to_sdio_func(pdev);
-	mmc_pm_flag_t sdio_flags;
-
-	sd_err(("%s Enter\n", __FUNCTION__));
-	if (func->num != 2)
-		return 0;
-
-	dhd_mmc_suspend = TRUE;
-	sdioh = sdio_get_drvdata(func);
-	err = bcmsdh_suspend(sdioh->bcmsdh);
-	if (err) {
-		dhd_mmc_suspend = FALSE;
-		return err;
-	}
-
-	sdio_flags = sdio_get_host_pm_caps(func);
-	if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
-		sd_err(("%s: can't keep power while host is suspended\n", __FUNCTION__));
-		dhd_mmc_suspend = FALSE;
-		return  -EINVAL;
-	}
-
-	/* keep power while host suspended */
-	err = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
-	if (err) {
-		sd_err(("%s: error while trying to keep power\n", __FUNCTION__));
-		dhd_mmc_suspend = FALSE;
-		return err;
-	}
-	smp_mb();
-
-	return 0;
-}
-
-static int bcmsdh_sdmmc_resume(struct device *pdev)
-{
-	sdioh_info_t *sdioh;
-	struct sdio_func *func = dev_to_sdio_func(pdev);
-
-	sd_err(("%s Enter\n", __FUNCTION__));
-	if (func->num != 2)
-		return 0;
-
-	sdioh = sdio_get_drvdata(func);
-	dhd_mmc_suspend = FALSE;
-
-	smp_mb();
-	return 0;
-}
-
-static const struct dev_pm_ops bcmsdh_sdmmc_pm_ops = {
-	.suspend	= bcmsdh_sdmmc_suspend,
-	.resume		= bcmsdh_sdmmc_resume,
-};
-#endif  /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */
-
-#if defined(BCMLXSDMMC)
-static struct semaphore *notify_semaphore = NULL;
-
-static int dummy_probe(struct sdio_func *func,
-                              const struct sdio_device_id *id)
-{
-	if (func && (func->num != 2)) {
-		return 0;
-	}
-
-	if (notify_semaphore)
-		up(notify_semaphore);
-	return 0;
-}
-
-static void dummy_remove(struct sdio_func *func)
-{
-}
-
-static struct sdio_driver dummy_sdmmc_driver = {
-	.probe		= dummy_probe,
-	.remove		= dummy_remove,
-	.name		= "dummy_sdmmc",
-	.id_table	= bcmsdh_sdmmc_ids,
-	};
-
-int sdio_func_reg_notify(void* semaphore)
-{
-	notify_semaphore = semaphore;
-	return sdio_register_driver(&dummy_sdmmc_driver);
-}
-
-void sdio_func_unreg_notify(void)
-{
-	OSL_SLEEP(15);
-	sdio_unregister_driver(&dummy_sdmmc_driver);
-}
-
-#endif /* defined(BCMLXSDMMC) */
-
-static struct sdio_driver bcmsdh_sdmmc_driver = {
-	.probe		= bcmsdh_sdmmc_probe,
-	.remove		= bcmsdh_sdmmc_remove,
-	.name		= "bcmsdh_sdmmc",
-	.id_table	= bcmsdh_sdmmc_ids,
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM)
-	.drv = {
-	.pm	= &bcmsdh_sdmmc_pm_ops,
-	},
-#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */
-	};
-
-struct sdos_info {
-	sdioh_info_t *sd;
-	spinlock_t lock;
-};
-
-/* Interrupt enable/disable */
-SDIOH_API_RC
-sdioh_interrupt_set(sdioh_info_t *sd, bool enable)
-{
-	if (!sd)
-		return BCME_BADARG;
-
-	sd_trace(("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling"));
-	return SDIOH_API_RC_SUCCESS;
-}
-
-#ifdef BCMSDH_MODULE
-static int __init
-bcmsdh_module_init(void)
-{
-	int error = 0;
-	error = sdio_function_init();
-	return error;
-}
-
-static void __exit
-bcmsdh_module_cleanup(void)
-{
-	sdio_function_cleanup();
-}
-
-module_init(bcmsdh_module_init);
-module_exit(bcmsdh_module_cleanup);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION(DESCRIPTION);
-MODULE_AUTHOR(AUTHOR);
-
-#endif /* BCMSDH_MODULE */
-/*
- * module init
-*/
-int bcmsdh_register_client_driver(void)
-{
-	return sdio_register_driver(&bcmsdh_sdmmc_driver);
-}
-
-/*
- * module cleanup
-*/
-void bcmsdh_unregister_client_driver(void)
-{
-	sdio_unregister_driver(&bcmsdh_sdmmc_driver);
-}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c
deleted file mode 100644
index 139288e..0000000
--- a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Broadcom SPI Host Controller Driver - Linux Per-port
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsdspi_linux.c 514727 2014-11-12 03:02:48Z $
- */
-
-#include <typedefs.h>
-#include <bcmutils.h>
-
-#include <bcmsdbus.h>		/* bcmsdh to/from specific controller APIs */
-#include <sdiovar.h>		/* to get msglevel bit values */
-
-#include <pcicfg.h>
-#include <sdio.h>		/* SDIO Device and Protocol Specs */
-#include <linux/sched.h>	/* request_irq(), free_irq() */
-#include <bcmsdspi.h>
-#include <bcmspi.h>
-
-extern uint sd_crc;
-module_param(sd_crc, uint, 0);
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-#define KERNEL26
-#endif
-
-struct sdos_info {
-	sdioh_info_t *sd;
-	spinlock_t lock;
-	wait_queue_head_t intr_wait_queue;
-};
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-#define BLOCKABLE()	(!in_atomic())
-#else
-#define BLOCKABLE()	(!in_interrupt())
-#endif
-
-/* Interrupt handler */
-static irqreturn_t
-sdspi_isr(int irq, void *dev_id
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
-, struct pt_regs *ptregs
-#endif
-)
-{
-	sdioh_info_t *sd;
-	struct sdos_info *sdos;
-	bool ours;
-
-	sd = (sdioh_info_t *)dev_id;
-	sd->local_intrcount++;
-
-	if (!sd->card_init_done) {
-		sd_err(("%s: Hey Bogus intr...not even initted: irq %d\n", __FUNCTION__, irq));
-		return IRQ_RETVAL(FALSE);
-	} else {
-		ours = spi_check_client_intr(sd, NULL);
-
-		/* For local interrupts, wake the waiting process */
-		if (ours && sd->got_hcint) {
-			sdos = (struct sdos_info *)sd->sdos_info;
-			wake_up_interruptible(&sdos->intr_wait_queue);
-		}
-
-		return IRQ_RETVAL(ours);
-	}
-}
-
-
-/* Register with Linux for interrupts */
-int
-spi_register_irq(sdioh_info_t *sd, uint irq)
-{
-	sd_trace(("Entering %s: irq == %d\n", __FUNCTION__, irq));
-	if (request_irq(irq, sdspi_isr, IRQF_SHARED, "bcmsdspi", sd) < 0) {
-		sd_err(("%s: request_irq() failed\n", __FUNCTION__));
-		return ERROR;
-	}
-	return SUCCESS;
-}
-
-/* Free Linux irq */
-void
-spi_free_irq(uint irq, sdioh_info_t *sd)
-{
-	free_irq(irq, sd);
-}
-
-/* Map Host controller registers */
-uint32 *
-spi_reg_map(osl_t *osh, uintptr addr, int size)
-{
-	return (uint32 *)REG_MAP(addr, size);
-}
-
-void
-spi_reg_unmap(osl_t *osh, uintptr addr, int size)
-{
-	REG_UNMAP((void*)(uintptr)addr);
-}
-
-int
-spi_osinit(sdioh_info_t *sd)
-{
-	struct sdos_info *sdos;
-
-	sdos = (struct sdos_info*)MALLOC(sd->osh, sizeof(struct sdos_info));
-	sd->sdos_info = (void*)sdos;
-	if (sdos == NULL)
-		return BCME_NOMEM;
-
-	sdos->sd = sd;
-	spin_lock_init(&sdos->lock);
-	init_waitqueue_head(&sdos->intr_wait_queue);
-	return BCME_OK;
-}
-
-void
-spi_osfree(sdioh_info_t *sd)
-{
-	struct sdos_info *sdos;
-	ASSERT(sd && sd->sdos_info);
-
-	sdos = (struct sdos_info *)sd->sdos_info;
-	MFREE(sd->osh, sdos, sizeof(struct sdos_info));
-}
-
-/* Interrupt enable/disable */
-SDIOH_API_RC
-sdioh_interrupt_set(sdioh_info_t *sd, bool enable)
-{
-	ulong flags;
-	struct sdos_info *sdos;
-
-	sd_trace(("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling"));
-
-	sdos = (struct sdos_info *)sd->sdos_info;
-	ASSERT(sdos);
-
-	if (!(sd->host_init_done && sd->card_init_done)) {
-		sd_err(("%s: Card & Host are not initted - bailing\n", __FUNCTION__));
-		return SDIOH_API_RC_FAIL;
-	}
-
-	if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
-		sd_err(("%s: no handler registered, will not enable\n", __FUNCTION__));
-		return SDIOH_API_RC_FAIL;
-	}
-
-	/* Ensure atomicity for enable/disable calls */
-	spin_lock_irqsave(&sdos->lock, flags);
-
-	sd->client_intr_enabled = enable;
-	if (enable && !sd->lockcount)
-		spi_devintr_on(sd);
-	else
-		spi_devintr_off(sd);
-
-	spin_unlock_irqrestore(&sdos->lock, flags);
-
-	return SDIOH_API_RC_SUCCESS;
-}
-
-/* Protect against reentrancy (disable device interrupts while executing) */
-void
-spi_lock(sdioh_info_t *sd)
-{
-	ulong flags;
-	struct sdos_info *sdos;
-
-	sdos = (struct sdos_info *)sd->sdos_info;
-	ASSERT(sdos);
-
-	sd_trace(("%s: %d\n", __FUNCTION__, sd->lockcount));
-
-	spin_lock_irqsave(&sdos->lock, flags);
-	if (sd->lockcount) {
-		sd_err(("%s: Already locked!\n", __FUNCTION__));
-		ASSERT(sd->lockcount == 0);
-	}
-	spi_devintr_off(sd);
-	sd->lockcount++;
-	spin_unlock_irqrestore(&sdos->lock, flags);
-}
-
-/* Enable client interrupt */
-void
-spi_unlock(sdioh_info_t *sd)
-{
-	ulong flags;
-	struct sdos_info *sdos;
-
-	sd_trace(("%s: %d, %d\n", __FUNCTION__, sd->lockcount, sd->client_intr_enabled));
-	ASSERT(sd->lockcount > 0);
-
-	sdos = (struct sdos_info *)sd->sdos_info;
-	ASSERT(sdos);
-
-	spin_lock_irqsave(&sdos->lock, flags);
-	if (--sd->lockcount == 0 && sd->client_intr_enabled) {
-		spi_devintr_on(sd);
-	}
-	spin_unlock_irqrestore(&sdos->lock, flags);
-}
-
-void spi_waitbits(sdioh_info_t *sd, bool yield)
-{
-#ifndef BCMSDYIELD
-	ASSERT(!yield);
-#endif
-	sd_trace(("%s: yield %d canblock %d\n",
-	          __FUNCTION__, yield, BLOCKABLE()));
-
-	/* Clear the "interrupt happened" flag and last intrstatus */
-	sd->got_hcint = FALSE;
-
-#ifdef BCMSDYIELD
-	if (yield && BLOCKABLE()) {
-		struct sdos_info *sdos;
-		sdos = (struct sdos_info *)sd->sdos_info;
-		/* Wait for the indication, the interrupt will be masked when the ISR fires. */
-		wait_event_interruptible(sdos->intr_wait_queue, (sd->got_hcint));
-	} else
-#endif /* BCMSDYIELD */
-	{
-		spi_spinbits(sd);
-	}
-
-}
diff --git a/drivers/net/wireless/bcmdhd/bcmspibrcm.c b/drivers/net/wireless/bcmdhd/bcmspibrcm.c
deleted file mode 100644
index 10d982e..0000000
--- a/drivers/net/wireless/bcmdhd/bcmspibrcm.c
+++ /dev/null
@@ -1,1819 +0,0 @@
-/*
- * Broadcom BCMSDH to gSPI Protocol Conversion Layer
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmspibrcm.c 591086 2015-10-07 02:51:01Z $
- */
-
-#define HSMODE
-
-#include <typedefs.h>
-
-#include <bcmdevs.h>
-#include <bcmendian.h>
-#include <bcmutils.h>
-#include <osl.h>
-#include <hndsoc.h>
-#include <siutils.h>
-#include <sbchipc.h>
-#include <sbsdio.h>	/* SDIO device core hardware definitions. */
-#include <spid.h>
-
-#include <bcmsdbus.h>	/* bcmsdh to/from specific controller APIs */
-#include <sdiovar.h>	/* ioctl/iovars */
-#include <sdio.h>	/* SDIO Device and Protocol Specs */
-
-#include <pcicfg.h>
-
-
-#include <bcmspibrcm.h>
-#include <bcmspi.h>
-
-/* these are for the older cores... for newer cores we have control for each of them */
-#define F0_RESPONSE_DELAY	16
-#define F1_RESPONSE_DELAY	16
-#define F2_RESPONSE_DELAY	F0_RESPONSE_DELAY
-
-
-#define GSPI_F0_RESP_DELAY		0
-#define GSPI_F1_RESP_DELAY		F1_RESPONSE_DELAY
-#define GSPI_F2_RESP_DELAY		0
-#define GSPI_F3_RESP_DELAY		0
-
-#define CMDLEN		4
-
-#define DWORDMODE_ON (sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 2) && (sd->dwordmode == TRUE)
-
-/* Globals */
-#if defined(DHD_DEBUG)
-uint sd_msglevel = SDH_ERROR_VAL;
-#else
-uint sd_msglevel = 0;
-#endif 
-
-uint sd_hiok = FALSE;		/* Use hi-speed mode if available? */
-uint sd_sdmode = SDIOH_MODE_SPI;		/* Use SD4 mode by default */
-uint sd_f2_blocksize = 64;		/* Default blocksize */
-
-
-uint sd_divisor = 2;
-uint sd_power = 1;		/* Default to SD Slot powered ON */
-uint sd_clock = 1;		/* Default to SD Clock turned ON */
-uint sd_crc = 0;		/* Default to SPI CRC Check turned OFF */
-uint sd_pci_slot = 0xFFFFffff; /* Used to force selection of a particular PCI slot */
-
-uint8	spi_outbuf[SPI_MAX_PKT_LEN];
-uint8	spi_inbuf[SPI_MAX_PKT_LEN];
-
-/* 128bytes buffer is enough to clear data-not-available and program response-delay F0 bits
- * assuming we will not exceed F0 response delay > 100 bytes at 48MHz.
- */
-#define BUF2_PKT_LEN	128
-uint8	spi_outbuf2[BUF2_PKT_LEN];
-uint8	spi_inbuf2[BUF2_PKT_LEN];
-
-#define SPISWAP_WD4(x) bcmswap32(x);
-#define SPISWAP_WD2(x) (bcmswap16(x & 0xffff)) | \
-						(bcmswap16((x & 0xffff0000) >> 16) << 16);
-
-/* Prototypes */
-static bool bcmspi_test_card(sdioh_info_t *sd);
-static bool bcmspi_host_device_init_adapt(sdioh_info_t *sd);
-static int bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode);
-static int bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
-                           uint32 *data, uint32 datalen);
-static int bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr,
-                              int regsize, uint32 *data);
-static int bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr,
-                               int regsize, uint32 data);
-static int bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr,
-                               uint8 *data);
-static int bcmspi_driver_init(sdioh_info_t *sd);
-static int bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
-                          uint32 addr, int nbytes, uint32 *data);
-static int bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize,
-                                 uint32 *data);
-static void bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer);
-static int bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg);
-
-/*
- *  Public entry points & extern's
- */
-extern sdioh_info_t *
-sdioh_attach(osl_t *osh, void *bar0, uint irq)
-{
-	sdioh_info_t *sd;
-
-	sd_trace(("%s\n", __FUNCTION__));
-	if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
-		sd_err(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh)));
-		return NULL;
-	}
-	bzero((char *)sd, sizeof(sdioh_info_t));
-	sd->osh = osh;
-	if (spi_osinit(sd) != 0) {
-		sd_err(("%s: spi_osinit() failed\n", __FUNCTION__));
-		MFREE(sd->osh, sd, sizeof(sdioh_info_t));
-		return NULL;
-	}
-
-	sd->bar0 = bar0;
-	sd->irq = irq;
-	sd->intr_handler = NULL;
-	sd->intr_handler_arg = NULL;
-	sd->intr_handler_valid = FALSE;
-
-	/* Set defaults */
-	sd->use_client_ints = TRUE;
-	sd->sd_use_dma = FALSE;	/* DMA Not supported */
-
-	/* Spi device default is 16bit mode, change to 4 when device is changed to 32bit
-	 * mode
-	 */
-	sd->wordlen = 2;
-
-
-	if (!spi_hw_attach(sd)) {
-		sd_err(("%s: spi_hw_attach() failed\n", __FUNCTION__));
-		spi_osfree(sd);
-		MFREE(sd->osh, sd, sizeof(sdioh_info_t));
-		return (NULL);
-	}
-
-	if (bcmspi_driver_init(sd) != SUCCESS) {
-		sd_err(("%s: bcmspi_driver_init() failed()\n", __FUNCTION__));
-		spi_hw_detach(sd);
-		spi_osfree(sd);
-		MFREE(sd->osh, sd, sizeof(sdioh_info_t));
-		return (NULL);
-	}
-
-	if (spi_register_irq(sd, irq) != SUCCESS) {
-		sd_err(("%s: spi_register_irq() failed for irq = %d\n", __FUNCTION__, irq));
-		spi_hw_detach(sd);
-		spi_osfree(sd);
-		MFREE(sd->osh, sd, sizeof(sdioh_info_t));
-		return (NULL);
-	}
-
-	sd_trace(("%s: Done\n", __FUNCTION__));
-
-	return sd;
-}
-
-extern SDIOH_API_RC
-sdioh_detach(osl_t *osh, sdioh_info_t *sd)
-{
-	sd_trace(("%s\n", __FUNCTION__));
-	if (sd) {
-		sd_err(("%s: detaching from hardware\n", __FUNCTION__));
-		spi_free_irq(sd->irq, sd);
-		spi_hw_detach(sd);
-		spi_osfree(sd);
-		MFREE(sd->osh, sd, sizeof(sdioh_info_t));
-	}
-	return SDIOH_API_RC_SUCCESS;
-}
-
-/* Configure callback to client when we recieve client interrupt */
-extern SDIOH_API_RC
-sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
-{
-	sd_trace(("%s: Entering\n", __FUNCTION__));
-#if !defined(OOB_INTR_ONLY)
-	sd->intr_handler = fn;
-	sd->intr_handler_arg = argh;
-	sd->intr_handler_valid = TRUE;
-#endif /* !defined(OOB_INTR_ONLY) */
-	return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_interrupt_deregister(sdioh_info_t *sd)
-{
-	sd_trace(("%s: Entering\n", __FUNCTION__));
-#if !defined(OOB_INTR_ONLY)
-	sd->intr_handler_valid = FALSE;
-	sd->intr_handler = NULL;
-	sd->intr_handler_arg = NULL;
-#endif /* !defined(OOB_INTR_ONLY) */
-	return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
-{
-	sd_trace(("%s: Entering\n", __FUNCTION__));
-	*onoff = sd->client_intr_enabled;
-	return SDIOH_API_RC_SUCCESS;
-}
-
-#if defined(DHD_DEBUG)
-extern bool
-sdioh_interrupt_pending(sdioh_info_t *sd)
-{
-	return 0;
-}
-#endif
-
-extern SDIOH_API_RC
-sdioh_query_device(sdioh_info_t *sd)
-{
-	/* Return a BRCM ID appropriate to the dongle class */
-	return (sd->num_funcs > 1) ? BCM4329_D11N_ID : BCM4318_D11G_ID;
-}
-
-/* Provide dstatus bits of spi-transaction for dhd layers. */
-extern uint32
-sdioh_get_dstatus(sdioh_info_t *sd)
-{
-	return sd->card_dstatus;
-}
-
-extern void
-sdioh_chipinfo(sdioh_info_t *sd, uint32 chip, uint32 chiprev)
-{
-	sd->chip = chip;
-	sd->chiprev = chiprev;
-}
-
-extern void
-sdioh_dwordmode(sdioh_info_t *sd, bool set)
-{
-	uint8 reg = 0;
-	int status;
-
-	if ((status = sdioh_request_byte(sd, SDIOH_READ, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
-	     SUCCESS) {
-		sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
-		return;
-	}
-
-	if (set) {
-		reg |= DWORD_PKT_LEN_EN;
-		sd->dwordmode = TRUE;
-		sd->client_block_size[SPI_FUNC_2] = 4096; /* h2spi's limit is 4KB, we support 8KB */
-	} else {
-		reg &= ~DWORD_PKT_LEN_EN;
-		sd->dwordmode = FALSE;
-		sd->client_block_size[SPI_FUNC_2] = 2048;
-	}
-
-	if ((status = sdioh_request_byte(sd, SDIOH_WRITE, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
-	     SUCCESS) {
-		sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
-		return;
-	}
-}
-
-
-uint
-sdioh_query_iofnum(sdioh_info_t *sd)
-{
-	return sd->num_funcs;
-}
-
-/* IOVar table */
-enum {
-	IOV_MSGLEVEL = 1,
-	IOV_BLOCKMODE,
-	IOV_BLOCKSIZE,
-	IOV_DMA,
-	IOV_USEINTS,
-	IOV_NUMINTS,
-	IOV_NUMLOCALINTS,
-	IOV_HOSTREG,
-	IOV_DEVREG,
-	IOV_DIVISOR,
-	IOV_SDMODE,
-	IOV_HISPEED,
-	IOV_HCIREGS,
-	IOV_POWER,
-	IOV_CLOCK,
-	IOV_SPIERRSTATS,
-	IOV_RESP_DELAY_ALL
-};
-
-const bcm_iovar_t sdioh_iovars[] = {
-	{"sd_msglevel",	IOV_MSGLEVEL, 	0,	IOVT_UINT32,	0 },
-	{"sd_blocksize", IOV_BLOCKSIZE, 0,	IOVT_UINT32,	0 }, /* ((fn << 16) | size) */
-	{"sd_dma",	IOV_DMA,	0,	IOVT_BOOL,	0 },
-	{"sd_ints",	IOV_USEINTS,	0,	IOVT_BOOL,	0 },
-	{"sd_numints",	IOV_NUMINTS,	0,	IOVT_UINT32,	0 },
-	{"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32,	0 },
-	{"sd_hostreg",	IOV_HOSTREG,	0,	IOVT_BUFFER,	sizeof(sdreg_t) },
-	{"sd_devreg",	IOV_DEVREG,	0,	IOVT_BUFFER,	sizeof(sdreg_t)	},
-	{"sd_divisor",	IOV_DIVISOR,	0,	IOVT_UINT32,	0 },
-	{"sd_power",	IOV_POWER,	0,	IOVT_UINT32,	0 },
-	{"sd_clock",	IOV_CLOCK,	0,	IOVT_UINT32,	0 },
-	{"sd_mode",	IOV_SDMODE,	0,	IOVT_UINT32,	100},
-	{"sd_highspeed",	IOV_HISPEED,	0,	IOVT_UINT32,	0},
-	{"spi_errstats", IOV_SPIERRSTATS, 0, IOVT_BUFFER, sizeof(struct spierrstats_t) },
-	{"spi_respdelay",	IOV_RESP_DELAY_ALL,	0,	IOVT_BOOL,	0 },
-	{NULL, 0, 0, 0, 0 }
-};
-
-int
-sdioh_iovar_op(sdioh_info_t *si, const char *name,
-               void *params, int plen, void *arg, int len, bool set)
-{
-	const bcm_iovar_t *vi = NULL;
-	int bcmerror = 0;
-	int val_size;
-	int32 int_val = 0;
-	bool bool_val;
-	uint32 actionid;
-/*
-	sdioh_regs_t *regs;
-*/
-
-	ASSERT(name);
-	ASSERT(len >= 0);
-
-	/* Get must have return space; Set does not take qualifiers */
-	ASSERT(set || (arg && len));
-	ASSERT(!set || (!params && !plen));
-
-	sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
-
-	if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
-		bcmerror = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
-		goto exit;
-
-	/* Set up params so get and set can share the convenience variables */
-	if (params == NULL) {
-		params = arg;
-		plen = len;
-	}
-
-	if (vi->type == IOVT_VOID)
-		val_size = 0;
-	else if (vi->type == IOVT_BUFFER)
-		val_size = len;
-	else
-		val_size = sizeof(int);
-
-	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
-
-	bool_val = (int_val != 0) ? TRUE : FALSE;
-
-	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
-	switch (actionid) {
-	case IOV_GVAL(IOV_MSGLEVEL):
-		int_val = (int32)sd_msglevel;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_MSGLEVEL):
-		sd_msglevel = int_val;
-		break;
-
-	case IOV_GVAL(IOV_BLOCKSIZE):
-		if ((uint32)int_val > si->num_funcs) {
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		int_val = (int32)si->client_block_size[int_val];
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_DMA):
-		int_val = (int32)si->sd_use_dma;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DMA):
-		si->sd_use_dma = (bool)int_val;
-		break;
-
-	case IOV_GVAL(IOV_USEINTS):
-		int_val = (int32)si->use_client_ints;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_USEINTS):
-		break;
-
-	case IOV_GVAL(IOV_DIVISOR):
-		int_val = (uint32)sd_divisor;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DIVISOR):
-		sd_divisor = int_val;
-		if (!spi_start_clock(si, (uint16)sd_divisor)) {
-			sd_err(("%s: set clock failed\n", __FUNCTION__));
-			bcmerror = BCME_ERROR;
-		}
-		break;
-
-	case IOV_GVAL(IOV_POWER):
-		int_val = (uint32)sd_power;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_POWER):
-		sd_power = int_val;
-		break;
-
-	case IOV_GVAL(IOV_CLOCK):
-		int_val = (uint32)sd_clock;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_CLOCK):
-		sd_clock = int_val;
-		break;
-
-	case IOV_GVAL(IOV_SDMODE):
-		int_val = (uint32)sd_sdmode;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_SDMODE):
-		sd_sdmode = int_val;
-		break;
-
-	case IOV_GVAL(IOV_HISPEED):
-		int_val = (uint32)sd_hiok;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_HISPEED):
-		sd_hiok = int_val;
-
-		if (!bcmspi_set_highspeed_mode(si, (bool)sd_hiok)) {
-			sd_err(("%s: Failed changing highspeed mode to %d.\n",
-			        __FUNCTION__, sd_hiok));
-			bcmerror = BCME_ERROR;
-			return ERROR;
-		}
-		break;
-
-	case IOV_GVAL(IOV_NUMINTS):
-		int_val = (int32)si->intrcount;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_NUMLOCALINTS):
-		int_val = (int32)si->local_intrcount;
-		bcopy(&int_val, arg, val_size);
-		break;
-	case IOV_GVAL(IOV_DEVREG):
-	{
-		sdreg_t *sd_ptr = (sdreg_t *)params;
-		uint8 data;
-
-		if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) {
-			bcmerror = BCME_SDIO_ERROR;
-			break;
-		}
-
-		int_val = (int)data;
-		bcopy(&int_val, arg, sizeof(int_val));
-		break;
-	}
-
-	case IOV_SVAL(IOV_DEVREG):
-	{
-		sdreg_t *sd_ptr = (sdreg_t *)params;
-		uint8 data = (uint8)sd_ptr->value;
-
-		if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) {
-			bcmerror = BCME_SDIO_ERROR;
-			break;
-		}
-		break;
-	}
-
-
-	case IOV_GVAL(IOV_SPIERRSTATS):
-	{
-		bcopy(&si->spierrstats, arg, sizeof(struct spierrstats_t));
-		break;
-	}
-
-	case IOV_SVAL(IOV_SPIERRSTATS):
-	{
-		bzero(&si->spierrstats, sizeof(struct spierrstats_t));
-		break;
-	}
-
-	case IOV_GVAL(IOV_RESP_DELAY_ALL):
-		int_val = (int32)si->resp_delay_all;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_RESP_DELAY_ALL):
-		si->resp_delay_all = (bool)int_val;
-		int_val = STATUS_ENABLE|INTR_WITH_STATUS;
-		if (si->resp_delay_all)
-			int_val |= RESP_DELAY_ALL;
-		else {
-			if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_RESPONSE_DELAY, 1,
-			     F1_RESPONSE_DELAY) != SUCCESS) {
-				sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
-				bcmerror = BCME_SDIO_ERROR;
-				break;
-			}
-		}
-
-		if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_STATUS_ENABLE, 1, int_val)
-		     != SUCCESS) {
-			sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
-			bcmerror = BCME_SDIO_ERROR;
-			break;
-		}
-		break;
-
-	default:
-		bcmerror = BCME_UNSUPPORTED;
-		break;
-	}
-exit:
-
-	return bcmerror;
-}
-
-extern SDIOH_API_RC
-sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
-{
-	SDIOH_API_RC status;
-	/* No lock needed since sdioh_request_byte does locking */
-	status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
-	return status;
-}
-
-extern SDIOH_API_RC
-sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
-{
-	/* No lock needed since sdioh_request_byte does locking */
-	SDIOH_API_RC status;
-
-	if ((fnc_num == SPI_FUNC_1) && (addr == SBSDIO_FUNC1_FRAMECTRL)) {
-		uint8 dummy_data;
-		status = sdioh_cfg_read(sd, fnc_num, addr, &dummy_data);
-		if (status) {
-			sd_err(("sdioh_cfg_read() failed.\n"));
-			return status;
-		}
-	}
-
-	status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
-	return status;
-}
-
-extern SDIOH_API_RC
-sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
-{
-	uint32 count;
-	int offset;
-	uint32 cis_byte;
-	uint16 *cis = (uint16 *)cisd;
-	uint bar0 = SI_ENUM_BASE;
-	int status;
-	uint8 data;
-
-	sd_trace(("%s: Func %d\n", __FUNCTION__, func));
-
-	spi_lock(sd);
-
-	/* Set sb window address to 0x18000000 */
-	data = (bar0 >> 8) & SBSDIO_SBADDRLOW_MASK;
-	status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, &data);
-	if (status == SUCCESS) {
-		data = (bar0 >> 16) & SBSDIO_SBADDRMID_MASK;
-		status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, &data);
-	} else {
-		sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
-		spi_unlock(sd);
-		return (BCME_ERROR);
-	}
-	if (status == SUCCESS) {
-		data = (bar0 >> 24) & SBSDIO_SBADDRHIGH_MASK;
-		status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, &data);
-	} else {
-		sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
-		spi_unlock(sd);
-		return (BCME_ERROR);
-	}
-
-	offset =  CC_SROM_OTP; /* OTP offset in chipcommon. */
-	for (count = 0; count < length/2; count++) {
-		if (bcmspi_card_regread (sd, SDIO_FUNC_1, offset, 2, &cis_byte) < 0) {
-			sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
-			spi_unlock(sd);
-			return (BCME_ERROR);
-		}
-
-		*cis = (uint16)cis_byte;
-		cis++;
-		offset += 2;
-	}
-
-	spi_unlock(sd);
-
-	return (BCME_OK);
-}
-
-extern SDIOH_API_RC
-sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
-{
-	int status;
-	uint32 cmd_arg;
-	uint32 dstatus;
-	uint32 data = (uint32)(*byte);
-
-	spi_lock(sd);
-
-	cmd_arg = 0;
-	cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
-	cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);	/* Incremental access */
-	cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
-	cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, rw == SDIOH_READ ? 0 : 1);
-	cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
-
-	if (rw == SDIOH_READ) {
-		sd_trace(("%s: RD cmd_arg=0x%x func=%d regaddr=0x%x\n",
-		          __FUNCTION__, cmd_arg, func, regaddr));
-	} else {
-		sd_trace(("%s: WR cmd_arg=0x%x func=%d regaddr=0x%x data=0x%x\n",
-		          __FUNCTION__, cmd_arg, func, regaddr, data));
-	}
-
-	if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, 1)) != SUCCESS) {
-		spi_unlock(sd);
-		return status;
-	}
-
-	if (rw == SDIOH_READ) {
-		*byte = (uint8)data;
-		sd_trace(("%s: RD result=0x%x\n", __FUNCTION__, *byte));
-	}
-
-	bcmspi_cmd_getdstatus(sd, &dstatus);
-	if (dstatus)
-		sd_trace(("dstatus=0x%x\n", dstatus));
-
-	spi_unlock(sd);
-	return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
-                   uint32 *word, uint nbytes)
-{
-	int status;
-
-	spi_lock(sd);
-
-	if (rw == SDIOH_READ)
-		status = bcmspi_card_regread(sd, func, addr, nbytes, word);
-	else
-		status = bcmspi_card_regwrite(sd, func, addr, nbytes, *word);
-
-	spi_unlock(sd);
-	return (status == SUCCESS ?  SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
-}
-
-extern SDIOH_API_RC
-sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint func,
-                     uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt)
-{
-	int len;
-	int buflen = (int)buflen_u;
-	bool fifo = (fix_inc == SDIOH_DATA_FIX);
-
-	spi_lock(sd);
-
-	ASSERT(reg_width == 4);
-	ASSERT(buflen_u < (1 << 30));
-	ASSERT(sd->client_block_size[func]);
-
-	sd_data(("%s: %c len %d r_cnt %d t_cnt %d, pkt @0x%p\n",
-	         __FUNCTION__, rw == SDIOH_READ ? 'R' : 'W',
-	         buflen_u, sd->r_cnt, sd->t_cnt, pkt));
-
-	/* Break buffer down into blocksize chunks. */
-	while (buflen > 0) {
-		len = MIN(sd->client_block_size[func], buflen);
-		if (bcmspi_card_buf(sd, rw, func, fifo, addr, len, (uint32 *)buffer) != SUCCESS) {
-			sd_err(("%s: bcmspi_card_buf %s failed\n",
-				__FUNCTION__, rw == SDIOH_READ ? "Read" : "Write"));
-			spi_unlock(sd);
-			return SDIOH_API_RC_FAIL;
-		}
-		buffer += len;
-		buflen -= len;
-		if (!fifo)
-			addr += len;
-	}
-	spi_unlock(sd);
-	return SDIOH_API_RC_SUCCESS;
-}
-
-/* This function allows write to gspi bus when another rd/wr function is deep down the call stack.
- * Its main aim is to have simpler spi writes rather than recursive writes.
- * e.g. When there is a need to program response delay on the fly after detecting the SPI-func
- * this call will allow to program the response delay.
- */
-static int
-bcmspi_card_byterewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 byte)
-{
-	uint32 cmd_arg;
-	uint32 datalen = 1;
-	uint32 hostlen;
-
-	cmd_arg = 0;
-
-	cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
-	cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);	/* Incremental access */
-	cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
-	cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
-	cmd_arg = SFIELD(cmd_arg, SPI_LEN, datalen);
-
-	sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
-
-
-	/* Set up and issue the SPI command.  MSByte goes out on bus first.  Increase datalen
-	 * according to the wordlen mode(16/32bit) the device is in.
-	 */
-	ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
-	datalen = ROUNDUP(datalen, sd->wordlen);
-
-	/* Start by copying command in the spi-outbuffer */
-	if (sd->wordlen == 4) { /* 32bit spid */
-		*(uint32 *)spi_outbuf2 = SPISWAP_WD4(cmd_arg);
-		if (datalen & 0x3)
-			datalen += (4 - (datalen & 0x3));
-	} else if (sd->wordlen == 2) { /* 16bit spid */
-		*(uint32 *)spi_outbuf2 = SPISWAP_WD2(cmd_arg);
-		if (datalen & 0x1)
-			datalen++;
-	} else {
-		sd_err(("%s: Host is %d bit spid, could not create SPI command.\n",
-		        __FUNCTION__, 8 * sd->wordlen));
-		return ERROR;
-	}
-
-	/* for Write, put the data into the output buffer  */
-	if (datalen != 0) {
-			if (sd->wordlen == 4) { /* 32bit spid */
-				*(uint32 *)&spi_outbuf2[CMDLEN] = SPISWAP_WD4(byte);
-			} else if (sd->wordlen == 2) { /* 16bit spid */
-				*(uint32 *)&spi_outbuf2[CMDLEN] = SPISWAP_WD2(byte);
-			}
-	}
-
-	/* +4 for cmd, +4 for dstatus */
-	hostlen = datalen + 8;
-	hostlen += (4 - (hostlen & 0x3));
-	spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, hostlen);
-
-	/* Last 4bytes are dstatus.  Device is configured to return status bits. */
-	if (sd->wordlen == 4) { /* 32bit spid */
-		sd->card_dstatus = SPISWAP_WD4(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
-	} else if (sd->wordlen == 2) { /* 16bit spid */
-		sd->card_dstatus = SPISWAP_WD2(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
-	} else {
-		sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
-		        __FUNCTION__, 8 * sd->wordlen));
-		return ERROR;
-	}
-
-	if (sd->card_dstatus)
-		sd_trace(("dstatus after byte rewrite = 0x%x\n", sd->card_dstatus));
-
-	return (BCME_OK);
-}
-
-/* Program the response delay corresponding to the spi function */
-static int
-bcmspi_prog_resp_delay(sdioh_info_t *sd, int func, uint8 resp_delay)
-{
-	if (sd->resp_delay_all == FALSE)
-		return (BCME_OK);
-
-	if (sd->prev_fun == func)
-		return (BCME_OK);
-
-	if (F0_RESPONSE_DELAY == F1_RESPONSE_DELAY)
-		return (BCME_OK);
-
-	bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_RESPONSE_DELAY, resp_delay);
-
-	/* Remember function for which to avoid reprogramming resp-delay in next iteration */
-	sd->prev_fun = func;
-
-	return (BCME_OK);
-
-}
-
-#define GSPI_RESYNC_PATTERN	0x0
-
-/* A resync pattern is a 32bit MOSI line with all zeros. Its a special command in gSPI.
- * It resets the spi-bkplane logic so that all F1 related ping-pong buffer logic is
- * synchronised and all queued resuests are cancelled.
- */
-static int
-bcmspi_resync_f1(sdioh_info_t *sd)
-{
-	uint32 cmd_arg = GSPI_RESYNC_PATTERN, data = 0, datalen = 0;
-
-
-	/* Set up and issue the SPI command.  MSByte goes out on bus first.  Increase datalen
-	 * according to the wordlen mode(16/32bit) the device is in.
-	 */
-	ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
-	datalen = ROUNDUP(datalen, sd->wordlen);
-
-	/* Start by copying command in the spi-outbuffer */
-	*(uint32 *)spi_outbuf2 = cmd_arg;
-
-	/* for Write, put the data into the output buffer  */
-	*(uint32 *)&spi_outbuf2[CMDLEN] = data;
-
-	/* +4 for cmd, +4 for dstatus */
-	spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, datalen + 8);
-
-	/* Last 4bytes are dstatus.  Device is configured to return status bits. */
-	if (sd->wordlen == 4) { /* 32bit spid */
-		sd->card_dstatus = SPISWAP_WD4(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
-	} else if (sd->wordlen == 2) { /* 16bit spid */
-		sd->card_dstatus = SPISWAP_WD2(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
-	} else {
-		sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
-		        __FUNCTION__, 8 * sd->wordlen));
-		return ERROR;
-	}
-
-	if (sd->card_dstatus)
-		sd_trace(("dstatus after resync pattern write = 0x%x\n", sd->card_dstatus));
-
-	return (BCME_OK);
-}
-
-uint32 dstatus_count = 0;
-
-static int
-bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg)
-{
-	uint32 dstatus = sd->card_dstatus;
-	struct spierrstats_t *spierrstats = &sd->spierrstats;
-	int err = SUCCESS;
-
-	sd_trace(("cmd = 0x%x, dstatus = 0x%x\n", cmd_arg, dstatus));
-
-	/* Store dstatus of last few gSPI transactions */
-	spierrstats->dstatus[dstatus_count % NUM_PREV_TRANSACTIONS] = dstatus;
-	spierrstats->spicmd[dstatus_count % NUM_PREV_TRANSACTIONS] = cmd_arg;
-	dstatus_count++;
-
-	if (sd->card_init_done == FALSE)
-		return err;
-
-	if (dstatus & STATUS_DATA_NOT_AVAILABLE) {
-		spierrstats->dna++;
-		sd_trace(("Read data not available on F1 addr = 0x%x\n",
-		        GFIELD(cmd_arg, SPI_REG_ADDR)));
-		/* Clear dna bit */
-		bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, DATA_UNAVAILABLE);
-	}
-
-	if (dstatus & STATUS_UNDERFLOW) {
-		spierrstats->rdunderflow++;
-		sd_err(("FIFO underflow happened due to current F2 read command.\n"));
-	}
-
-	if (dstatus & STATUS_OVERFLOW) {
-		spierrstats->wroverflow++;
-		sd_err(("FIFO overflow happened due to current (F1/F2) write command.\n"));
-		bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, F1_OVERFLOW);
-		bcmspi_resync_f1(sd);
-		sd_err(("Recovering from F1 FIFO overflow.\n"));
-	}
-
-	if (dstatus & STATUS_F2_INTR) {
-		spierrstats->f2interrupt++;
-		sd_trace(("Interrupt from F2.  SW should clear corresponding IntStatus bits\n"));
-	}
-
-	if (dstatus & STATUS_F3_INTR) {
-		spierrstats->f3interrupt++;
-		sd_err(("Interrupt from F3.  SW should clear corresponding IntStatus bits\n"));
-	}
-
-	if (dstatus & STATUS_HOST_CMD_DATA_ERR) {
-		spierrstats->hostcmddataerr++;
-		sd_err(("Error in CMD or Host data, detected by CRC/Checksum (optional)\n"));
-	}
-
-	if (dstatus & STATUS_F2_PKT_AVAILABLE) {
-		spierrstats->f2pktavailable++;
-		sd_trace(("Packet is available/ready in F2 TX FIFO\n"));
-		sd_trace(("Packet length = %d\n", sd->dwordmode ?
-		         ((dstatus & STATUS_F2_PKT_LEN_MASK) >> (STATUS_F2_PKT_LEN_SHIFT - 2)) :
-		         ((dstatus & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT)));
-	}
-
-	if (dstatus & STATUS_F3_PKT_AVAILABLE) {
-		spierrstats->f3pktavailable++;
-		sd_err(("Packet is available/ready in F3 TX FIFO\n"));
-		sd_err(("Packet length = %d\n",
-		        (dstatus & STATUS_F3_PKT_LEN_MASK) >> STATUS_F3_PKT_LEN_SHIFT));
-	}
-
-	return err;
-}
-
-extern int
-sdioh_abort(sdioh_info_t *sd, uint func)
-{
-	return 0;
-}
-
-int
-sdioh_start(sdioh_info_t *sd, int stage)
-{
-	return SUCCESS;
-}
-
-int
-sdioh_stop(sdioh_info_t *sd)
-{
-	return SUCCESS;
-}
-
-int
-sdioh_waitlockfree(sdioh_info_t *sd)
-{
-	return SUCCESS;
-}
-
-
-/*
- * Private/Static work routines
- */
-static int
-bcmspi_host_init(sdioh_info_t *sd)
-{
-
-	/* Default power on mode */
-	sd->sd_mode = SDIOH_MODE_SPI;
-	sd->polled_mode = TRUE;
-	sd->host_init_done = TRUE;
-	sd->card_init_done = FALSE;
-	sd->adapter_slot = 1;
-
-	return (SUCCESS);
-}
-
-static int
-get_client_blocksize(sdioh_info_t *sd)
-{
-	uint32 regdata[2];
-	int status;
-
-	/* Find F1/F2/F3 max packet size */
-	if ((status = bcmspi_card_regread(sd, 0, SPID_F1_INFO_REG,
-	                                 8, regdata)) != SUCCESS) {
-		return status;
-	}
-
-	sd_trace(("pkt_size regdata[0] = 0x%x, regdata[1] = 0x%x\n",
-	        regdata[0], regdata[1]));
-
-	sd->client_block_size[1] = (regdata[0] & F1_MAX_PKT_SIZE) >> 2;
-	sd_trace(("Func1 blocksize = %d\n", sd->client_block_size[1]));
-	ASSERT(sd->client_block_size[1] == BLOCK_SIZE_F1);
-
-	sd->client_block_size[2] = ((regdata[0] >> 16) & F2_MAX_PKT_SIZE) >> 2;
-	sd_trace(("Func2 blocksize = %d\n", sd->client_block_size[2]));
-	ASSERT(sd->client_block_size[2] == BLOCK_SIZE_F2);
-
-	sd->client_block_size[3] = (regdata[1] & F3_MAX_PKT_SIZE) >> 2;
-	sd_trace(("Func3 blocksize = %d\n", sd->client_block_size[3]));
-	ASSERT(sd->client_block_size[3] == BLOCK_SIZE_F3);
-
-	return 0;
-}
-
-static int
-bcmspi_client_init(sdioh_info_t *sd)
-{
-	uint32	status_en_reg = 0;
-	sd_trace(("%s: Powering up slot %d\n", __FUNCTION__, sd->adapter_slot));
-
-#ifdef HSMODE
-	if (!spi_start_clock(sd, (uint16)sd_divisor)) {
-		sd_err(("spi_start_clock failed\n"));
-		return ERROR;
-	}
-#else
-	/* Start at ~400KHz clock rate for initialization */
-	if (!spi_start_clock(sd, 128)) {
-		sd_err(("spi_start_clock failed\n"));
-		return ERROR;
-	}
-#endif /* HSMODE */
-
-	if (!bcmspi_host_device_init_adapt(sd)) {
-		sd_err(("bcmspi_host_device_init_adapt failed\n"));
-		return ERROR;
-	}
-
-	if (!bcmspi_test_card(sd)) {
-		sd_err(("bcmspi_test_card failed\n"));
-		return ERROR;
-	}
-
-	sd->num_funcs = SPI_MAX_IOFUNCS;
-
-	get_client_blocksize(sd);
-
-	/* Apply resync pattern cmd with all zeros to reset spi-bkplane F1 logic */
-	bcmspi_resync_f1(sd);
-
-	sd->dwordmode = FALSE;
-
-	bcmspi_card_regread(sd, 0, SPID_STATUS_ENABLE, 1, &status_en_reg);
-
-	sd_trace(("%s: Enabling interrupt with dstatus \n", __FUNCTION__));
-	status_en_reg |= INTR_WITH_STATUS;
-
-	if (bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_STATUS_ENABLE, 1,
-	    status_en_reg & 0xff) != SUCCESS) {
-		sd_err(("%s: Unable to set response delay for all fun's.\n", __FUNCTION__));
-		return ERROR;
-	}
-
-#ifndef HSMODE
-	/* After configuring for High-Speed mode, set the desired clock rate. */
-	if (!spi_start_clock(sd, 4)) {
-		sd_err(("spi_start_clock failed\n"));
-		return ERROR;
-	}
-#endif /* HSMODE */
-
-	/* check to see if the response delay needs to be programmed properly */
-	{
-		uint32 f1_respdelay = 0;
-		bcmspi_card_regread(sd, 0, SPID_RESP_DELAY_F1, 1, &f1_respdelay);
-		if ((f1_respdelay == 0) || (f1_respdelay == 0xFF)) {
-			/* older sdiodevice core and has no separte resp delay for each of */
-			sd_err(("older corerev < 4 so use the same resp delay for all funcs\n"));
-			sd->resp_delay_new = FALSE;
-		}
-		else {
-			/* older sdiodevice core and has no separte resp delay for each of */
-			int ret_val;
-			sd->resp_delay_new = TRUE;
-			sd_err(("new corerev >= 4 so set the resp delay for each of the funcs\n"));
-			sd_trace(("resp delay for funcs f0(%d), f1(%d), f2(%d), f3(%d)\n",
-				GSPI_F0_RESP_DELAY, GSPI_F1_RESP_DELAY,
-				GSPI_F2_RESP_DELAY, GSPI_F3_RESP_DELAY));
-			ret_val = bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_RESP_DELAY_F0, 1,
-				GSPI_F0_RESP_DELAY);
-			if (ret_val != SUCCESS) {
-				sd_err(("%s: Unable to set response delay for F0\n", __FUNCTION__));
-				return ERROR;
-			}
-			ret_val = bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_RESP_DELAY_F1, 1,
-				GSPI_F1_RESP_DELAY);
-			if (ret_val != SUCCESS) {
-				sd_err(("%s: Unable to set response delay for F1\n", __FUNCTION__));
-				return ERROR;
-			}
-			ret_val = bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_RESP_DELAY_F2, 1,
-				GSPI_F2_RESP_DELAY);
-			if (ret_val != SUCCESS) {
-				sd_err(("%s: Unable to set response delay for F2\n", __FUNCTION__));
-				return ERROR;
-			}
-			ret_val = bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_RESP_DELAY_F3, 1,
-				GSPI_F3_RESP_DELAY);
-			if (ret_val != SUCCESS) {
-				sd_err(("%s: Unable to set response delay for F2\n", __FUNCTION__));
-				return ERROR;
-			}
-		}
-	}
-
-
-	sd->card_init_done = TRUE;
-
-	/* get the device rev to program the prop respdelays */
-
-	return SUCCESS;
-}
-
-static int
-bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode)
-{
-	uint32 regdata;
-	int status;
-
-	if ((status = bcmspi_card_regread(sd, 0, SPID_CONFIG,
-	                                 4, &regdata)) != SUCCESS)
-		return status;
-
-	sd_trace(("In %s spih-ctrl = 0x%x \n", __FUNCTION__, regdata));
-
-
-	if (hsmode == TRUE) {
-		sd_trace(("Attempting to enable High-Speed mode.\n"));
-
-		if (regdata & HIGH_SPEED_MODE) {
-			sd_trace(("Device is already in High-Speed mode.\n"));
-			return status;
-		} else {
-			regdata |= HIGH_SPEED_MODE;
-			sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
-			if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
-			                                  4, regdata)) != SUCCESS) {
-				return status;
-			}
-		}
-	} else {
-		sd_trace(("Attempting to disable High-Speed mode.\n"));
-
-		if (regdata & HIGH_SPEED_MODE) {
-			regdata &= ~HIGH_SPEED_MODE;
-			sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
-			if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
-			                                  4, regdata)) != SUCCESS)
-				return status;
-		}
-		 else {
-			sd_trace(("Device is already in Low-Speed mode.\n"));
-			return status;
-		}
-	}
-	spi_controller_highspeed_mode(sd, hsmode);
-
-	return TRUE;
-}
-
-#define bcmspi_find_curr_mode(sd) { \
-	sd->wordlen = 2; \
-	status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
-	regdata &= 0xff; \
-	if ((regdata == 0xad) || (regdata == 0x5b) || \
-	    (regdata == 0x5d) || (regdata == 0x5a)) \
-		break; \
-	sd->wordlen = 4; \
-	status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
-	regdata &= 0xff; \
-	if ((regdata == 0xad) || (regdata == 0x5b) || \
-	    (regdata == 0x5d) || (regdata == 0x5a)) \
-		break; \
-	sd_trace(("Silicon testability issue: regdata = 0x%x." \
-		" Expected 0xad, 0x5a, 0x5b or 0x5d.\n", regdata)); \
-	OSL_DELAY(100000); \
-}
-
-#define INIT_ADAPT_LOOP		100
-
-/* Adapt clock-phase-speed-bitwidth between host and device */
-static bool
-bcmspi_host_device_init_adapt(sdioh_info_t *sd)
-{
-	uint32 wrregdata, regdata = 0;
-	int status;
-	int i;
-
-	/* Due to a silicon testability issue, the first command from the Host
-	 * to the device will get corrupted (first bit will be lost). So the
-	 * Host should poll the device with a safe read request. ie: The Host
-	 * should try to read F0 addr 0x14 using the Fixed address mode
-	 * (This will prevent a unintended write command to be detected by device)
-	 */
-	for (i = 0; i < INIT_ADAPT_LOOP; i++) {
-	/* If device was not power-cycled it will stay in 32bit mode with
-	 * response-delay-all bit set.  Alternate the iteration so that
-	 * read either with or without response-delay for F0 to succeed.
-	 */
-		bcmspi_find_curr_mode(sd);
-		sd->resp_delay_all = (i & 0x1) ? TRUE : FALSE;
-
-		bcmspi_find_curr_mode(sd);
-		sd->dwordmode = TRUE;
-
-		bcmspi_find_curr_mode(sd);
-		sd->dwordmode = FALSE;
-	}
-
-	/* Bail out, device not detected */
-	if (i == INIT_ADAPT_LOOP)
-		return FALSE;
-
-	/* Softreset the spid logic */
-	if ((sd->dwordmode) || (sd->wordlen == 4)) {
-		bcmspi_card_regwrite(sd, 0, SPID_RESET_BP, 1, RESET_ON_WLAN_BP_RESET|RESET_SPI);
-		bcmspi_card_regread(sd, 0, SPID_RESET_BP, 1, &regdata);
-		sd_trace(("reset reg read = 0x%x\n", regdata));
-		sd_trace(("dwordmode = %d, wordlen = %d, resp_delay_all = %d\n", sd->dwordmode,
-		       sd->wordlen, sd->resp_delay_all));
-		/* Restore default state after softreset */
-		sd->wordlen = 2;
-		sd->dwordmode = FALSE;
-	}
-
-	if (sd->wordlen == 4) {
-		if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) !=
-		     SUCCESS)
-				return FALSE;
-		if (regdata == TEST_RO_DATA_32BIT_LE) {
-			sd_trace(("Spid is already in 32bit LE mode. Value read = 0x%x\n",
-			          regdata));
-			sd_trace(("Spid power was left on.\n"));
-		} else {
-			sd_err(("Spid power was left on but signature read failed."
-			        " Value read = 0x%x\n", regdata));
-			return FALSE;
-		}
-	} else {
-		sd->wordlen = 2;
-
-#define CTRL_REG_DEFAULT	0x00010430 /* according to the host m/c */
-
-		wrregdata = (CTRL_REG_DEFAULT);
-
-		if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
-			return FALSE;
-		sd_trace(("(we are still in 16bit mode) 32bit READ LE regdata = 0x%x\n", regdata));
-
-#ifndef HSMODE
-		wrregdata |= (CLOCK_PHASE | CLOCK_POLARITY);
-		wrregdata &= ~HIGH_SPEED_MODE;
-		bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
-#endif /* HSMODE */
-
-		for (i = 0; i < INIT_ADAPT_LOOP; i++) {
-			if ((regdata == 0xfdda7d5b) || (regdata == 0xfdda7d5a)) {
-				sd_trace(("0xfeedbead was leftshifted by 1-bit.\n"));
-				if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4,
-				     &regdata)) != SUCCESS)
-					return FALSE;
-			}
-			OSL_DELAY(1000);
-		}
-
-#if defined(CHANGE_SPI_INTR_POLARITY_ACTIVE_HIGH)
-		/* Change to host controller intr-polarity of active-high */
-		wrregdata |= INTR_POLARITY;
-#else
-		/* Change to host controller intr-polarity of active-low */
-		wrregdata &= ~INTR_POLARITY;
-#endif /* CHANGE_SPI_INTR_POLARITY_ACTIVE_HIGH */
-
-		sd_trace(("(we are still in 16bit mode) 32bit Write LE reg-ctrl-data = 0x%x\n",
-		        wrregdata));
-		/* Change to 32bit mode */
-		wrregdata |= WORD_LENGTH_32;
-		bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
-
-		/* Change command/data packaging in 32bit LE mode */
-		sd->wordlen = 4;
-
-		if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
-			return FALSE;
-
-		if (regdata == TEST_RO_DATA_32BIT_LE) {
-			sd_trace(("Read spid passed. Value read = 0x%x\n", regdata));
-			sd_trace(("Spid had power-on cycle OR spi was soft-resetted \n"));
-		} else {
-			sd_err(("Stale spid reg values read as it was kept powered. Value read ="
-			  "0x%x\n", regdata));
-			return FALSE;
-		}
-	}
-
-
-	return TRUE;
-}
-
-static bool
-bcmspi_test_card(sdioh_info_t *sd)
-{
-	uint32 regdata;
-	int status;
-
-	if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
-		return FALSE;
-
-	if (regdata == (TEST_RO_DATA_32BIT_LE))
-		sd_trace(("32bit LE regdata = 0x%x\n", regdata));
-	else {
-		sd_trace(("Incorrect 32bit LE regdata = 0x%x\n", regdata));
-		return FALSE;
-	}
-
-
-#define RW_PATTERN1	0xA0A1A2A3
-#define RW_PATTERN2	0x4B5B6B7B
-
-	regdata = RW_PATTERN1;
-	if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
-		return FALSE;
-	regdata = 0;
-	if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
-		return FALSE;
-	if (regdata != RW_PATTERN1) {
-		sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
-			RW_PATTERN1, regdata));
-		return FALSE;
-	} else
-		sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
-
-	regdata = RW_PATTERN2;
-	if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
-		return FALSE;
-	regdata = 0;
-	if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
-		return FALSE;
-	if (regdata != RW_PATTERN2) {
-		sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
-			RW_PATTERN2, regdata));
-		return FALSE;
-	} else
-		sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
-
-	return TRUE;
-}
-
-static int
-bcmspi_driver_init(sdioh_info_t *sd)
-{
-	sd_trace(("%s\n", __FUNCTION__));
-	if ((bcmspi_host_init(sd)) != SUCCESS) {
-		return ERROR;
-	}
-
-	if (bcmspi_client_init(sd) != SUCCESS) {
-		return ERROR;
-	}
-
-	return SUCCESS;
-}
-
-/* Read device reg */
-static int
-bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
-{
-	int status;
-	uint32 cmd_arg, dstatus;
-
-	ASSERT(regsize);
-
-	if (func == 2)
-		sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
-
-	cmd_arg = 0;
-	cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
-	cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);	/* Incremental access */
-	cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
-	cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
-	cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
-
-	sd_trace(("%s: RD cmd_arg=0x%x func=%d regaddr=0x%x regsize=%d\n",
-	          __FUNCTION__, cmd_arg, func, regaddr, regsize));
-
-	if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize)) != SUCCESS)
-		return status;
-
-	bcmspi_cmd_getdstatus(sd, &dstatus);
-	if (dstatus)
-		sd_trace(("dstatus =0x%x\n", dstatus));
-
-	return SUCCESS;
-}
-
-static int
-bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
-{
-
-	int status;
-	uint32 cmd_arg;
-	uint32 dstatus;
-
-	ASSERT(regsize);
-
-	if (func == 2)
-		sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
-
-	cmd_arg = 0;
-	cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
-	cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0);	/* Fixed access */
-	cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
-	cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
-	cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize);
-
-	sd_trace(("%s: RD cmd_arg=0x%x func=%d regaddr=0x%x regsize=%d\n",
-	          __FUNCTION__, cmd_arg, func, regaddr, regsize));
-
-	if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize)) != SUCCESS)
-		return status;
-
-	sd_trace(("%s: RD result=0x%x\n", __FUNCTION__, *data));
-
-	bcmspi_cmd_getdstatus(sd, &dstatus);
-	sd_trace(("dstatus =0x%x\n", dstatus));
-	return SUCCESS;
-}
-
-/* write a device register */
-static int
-bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
-{
-	int status;
-	uint32 cmd_arg, dstatus;
-
-	ASSERT(regsize);
-
-	cmd_arg = 0;
-
-	cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
-	cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);	/* Incremental access */
-	cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
-	cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
-	cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
-
-	sd_trace(("%s: WR cmd_arg=0x%x func=%d regaddr=0x%x regsize=%d data=0x%x\n",
-	          __FUNCTION__, cmd_arg, func, regaddr, regsize, data));
-
-	if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, regsize)) != SUCCESS)
-		return status;
-
-	bcmspi_cmd_getdstatus(sd, &dstatus);
-	if (dstatus)
-		sd_trace(("dstatus=0x%x\n", dstatus));
-
-	return SUCCESS;
-}
-
-/* write a device register - 1 byte */
-static int
-bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 *byte)
-{
-	int status;
-	uint32 cmd_arg;
-	uint32 dstatus;
-	uint32 data = (uint32)(*byte);
-
-	cmd_arg = 0;
-	cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
-	cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);	/* Incremental access */
-	cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
-	cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
-	cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
-
-	sd_trace(("%s: WR cmd_arg=0x%x func=%d regaddr=0x%x data=0x%x\n",
-	          __FUNCTION__, cmd_arg, func, regaddr, data));
-
-	if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, 1)) != SUCCESS)
-		return status;
-
-	bcmspi_cmd_getdstatus(sd, &dstatus);
-	if (dstatus)
-		sd_trace(("dstatus =0x%x\n", dstatus));
-
-	return SUCCESS;
-}
-
-void
-bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer)
-{
-	*dstatus_buffer = sd->card_dstatus;
-}
-
-/* 'data' is of type uint32 whereas other buffers are of type uint8 */
-static int
-bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
-                uint32 *data, uint32 datalen)
-{
-	uint32	i, j;
-	uint8	resp_delay = 0;
-	int	err = SUCCESS;
-	uint32	hostlen;
-	uint32 spilen = 0;
-	uint32 dstatus_idx = 0;
-	uint16 templen, buslen, len, *ptr = NULL;
-
-	sd_trace(("spi cmd = 0x%x\n", cmd_arg));
-
-	if (DWORDMODE_ON) {
-		spilen = GFIELD(cmd_arg, SPI_LEN);
-		if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_0) ||
-		    (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_1))
-			dstatus_idx = spilen * 3;
-
-		if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
-		    (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
-			spilen = spilen << 2;
-			dstatus_idx = (spilen % 16) ? (16 - (spilen % 16)) : 0;
-			/* convert len to mod16 size */
-			spilen = ROUNDUP(spilen, 16);
-			cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
-		}
-	}
-
-	/* Set up and issue the SPI command.  MSByte goes out on bus first.  Increase datalen
-	 * according to the wordlen mode(16/32bit) the device is in.
-	 */
-	if (sd->wordlen == 4) { /* 32bit spid */
-		*(uint32 *)spi_outbuf = SPISWAP_WD4(cmd_arg);
-		if (datalen & 0x3)
-			datalen += (4 - (datalen & 0x3));
-	} else if (sd->wordlen == 2) { /* 16bit spid */
-		*(uint32 *)spi_outbuf = SPISWAP_WD2(cmd_arg);
-		if (datalen & 0x1)
-			datalen++;
-		if (datalen < 4)
-			datalen = ROUNDUP(datalen, 4);
-	} else {
-		sd_err(("Host is %d bit spid, could not create SPI command.\n",
-			8 * sd->wordlen));
-		return ERROR;
-	}
-
-	/* for Write, put the data into the output buffer */
-	if (GFIELD(cmd_arg, SPI_RW_FLAG) == 1) {
-		/* We send len field of hw-header always a mod16 size, both from host and dongle */
-		if (DWORDMODE_ON) {
-			if (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) {
-				ptr = (uint16 *)&data[0];
-				templen = *ptr;
-				/* ASSERT(*ptr == ~*(ptr + 1)); */
-				templen = ROUNDUP(templen, 16);
-				*ptr = templen;
-				sd_trace(("actual tx len = %d\n", (uint16)(~*(ptr+1))));
-			}
-		}
-
-		if (datalen != 0) {
-			for (i = 0; i < datalen/4; i++) {
-				if (sd->wordlen == 4) { /* 32bit spid */
-					*(uint32 *)&spi_outbuf[i * 4 + CMDLEN] =
-						SPISWAP_WD4(data[i]);
-				} else if (sd->wordlen == 2) { /* 16bit spid */
-					*(uint32 *)&spi_outbuf[i * 4 + CMDLEN] =
-						SPISWAP_WD2(data[i]);
-				}
-			}
-		}
-	}
-
-	/* Append resp-delay number of bytes and clock them out for F0/1/2 reads. */
-	if ((GFIELD(cmd_arg, SPI_RW_FLAG) == 0)) {
-		int func = GFIELD(cmd_arg, SPI_FUNCTION);
-		switch (func) {
-			case 0:
-				if (sd->resp_delay_new)
-					resp_delay = GSPI_F0_RESP_DELAY;
-				else
-					resp_delay = sd->resp_delay_all ? F0_RESPONSE_DELAY : 0;
-				break;
-			case 1:
-				if (sd->resp_delay_new)
-					resp_delay = GSPI_F1_RESP_DELAY;
-				else
-					resp_delay = F1_RESPONSE_DELAY;
-				break;
-			case 2:
-				if (sd->resp_delay_new)
-					resp_delay = GSPI_F2_RESP_DELAY;
-				else
-					resp_delay = sd->resp_delay_all ? F2_RESPONSE_DELAY : 0;
-				break;
-			default:
-				ASSERT(0);
-				break;
-		}
-		/* Program response delay */
-		if (sd->resp_delay_new == FALSE)
-			bcmspi_prog_resp_delay(sd, func, resp_delay);
-	}
-
-	/* +4 for cmd and +4 for dstatus */
-	hostlen = datalen + 8 + resp_delay;
-	hostlen += dstatus_idx;
-	hostlen += (4 - (hostlen & 0x3));
-	spi_sendrecv(sd, spi_outbuf, spi_inbuf, hostlen);
-
-	/* for Read, get the data into the input buffer */
-	if (datalen != 0) {
-		if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) { /* if read cmd */
-			for (j = 0; j < datalen/4; j++) {
-				if (sd->wordlen == 4) { /* 32bit spid */
-					data[j] = SPISWAP_WD4(*(uint32 *)&spi_inbuf[j * 4 +
-					            CMDLEN + resp_delay]);
-				} else if (sd->wordlen == 2) { /* 16bit spid */
-					data[j] = SPISWAP_WD2(*(uint32 *)&spi_inbuf[j * 4 +
-					            CMDLEN + resp_delay]);
-				}
-			}
-
-			if ((DWORDMODE_ON) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
-				ptr = (uint16 *)&data[0];
-				templen = *ptr;
-				buslen = len = ~(*(ptr + 1));
-				buslen = ROUNDUP(buslen, 16);
-				/* populate actual len in hw-header */
-				if (templen == buslen)
-					*ptr = len;
-			}
-		}
-	}
-
-	/* Restore back the len field of the hw header */
-	if (DWORDMODE_ON) {
-		if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
-		    (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
-			ptr = (uint16 *)&data[0];
-			*ptr = (uint16)(~*(ptr+1));
-		}
-	}
-
-	dstatus_idx += (datalen + CMDLEN + resp_delay);
-	/* Last 4bytes are dstatus.  Device is configured to return status bits. */
-	if (sd->wordlen == 4) { /* 32bit spid */
-		sd->card_dstatus = SPISWAP_WD4(*(uint32 *)&spi_inbuf[dstatus_idx]);
-	} else if (sd->wordlen == 2) { /* 16bit spid */
-		sd->card_dstatus = SPISWAP_WD2(*(uint32 *)&spi_inbuf[dstatus_idx]);
-	} else {
-		sd_err(("Host is %d bit machine, could not read SPI dstatus.\n",
-			8 * sd->wordlen));
-		return ERROR;
-	}
-	if (sd->card_dstatus == 0xffffffff) {
-		sd_err(("looks like not a GSPI device or device is not powered.\n"));
-	}
-
-	err = bcmspi_update_stats(sd, cmd_arg);
-
-	return err;
-
-}
-
-static int
-bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
-                uint32 addr, int nbytes, uint32 *data)
-{
-	int status;
-	uint32 cmd_arg;
-	bool write = rw == SDIOH_READ ? 0 : 1;
-	uint retries = 0;
-
-	bool enable;
-	uint32	spilen;
-
-	cmd_arg = 0;
-
-	ASSERT(nbytes);
-	ASSERT(nbytes <= sd->client_block_size[func]);
-
-	if (write) sd->t_cnt++; else sd->r_cnt++;
-
-	if (func == 2) {
-		/* Frame len check limited by gSPI. */
-		if ((nbytes > 2000) && write) {
-			sd_trace((">2KB write: F2 wr of %d bytes\n", nbytes));
-		}
-		/* ASSERT(nbytes <= 2048); Fix bigger len gspi issue and uncomment. */
-		/* If F2 fifo on device is not ready to receive data, don't do F2 transfer */
-		if (write) {
-			uint32 dstatus;
-			/* check F2 ready with cached one */
-			bcmspi_cmd_getdstatus(sd, &dstatus);
-			if ((dstatus & STATUS_F2_RX_READY) == 0) {
-				retries = WAIT_F2RXFIFORDY;
-				enable = 0;
-				while (retries-- && !enable) {
-					OSL_DELAY(WAIT_F2RXFIFORDY_DELAY * 1000);
-					bcmspi_card_regread(sd, SPI_FUNC_0, SPID_STATUS_REG, 4,
-					                   &dstatus);
-					if (dstatus & STATUS_F2_RX_READY)
-						enable = TRUE;
-				}
-				if (!enable) {
-					struct spierrstats_t *spierrstats = &sd->spierrstats;
-					spierrstats->f2rxnotready++;
-					sd_err(("F2 FIFO is not ready to receive data.\n"));
-					return ERROR;
-				}
-				sd_trace(("No of retries on F2 ready %d\n",
-					(WAIT_F2RXFIFORDY - retries)));
-			}
-		}
-	}
-
-	/* F2 transfers happen on 0 addr */
-	addr = (func == 2) ? 0 : addr;
-
-	/* In pio mode buffer is read using fixed address fifo in func 1 */
-	if ((func == 1) && (fifo))
-		cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0);
-	else
-		cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);
-
-	cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
-	cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, addr);
-	cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, write);
-	spilen = sd->data_xfer_count = MIN(sd->client_block_size[func], nbytes);
-	if ((sd->dwordmode == TRUE) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
-		/* convert len to mod4 size */
-		spilen = spilen + ((spilen & 0x3) ? (4 - (spilen & 0x3)): 0);
-		cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
-	} else
-		cmd_arg = SFIELD(cmd_arg, SPI_LEN, spilen);
-
-	if ((func == 2) && (fifo == 1)) {
-		sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
-		          __FUNCTION__, write ? "Wr" : "Rd", func, "INCR",
-		          addr, nbytes, sd->r_cnt, sd->t_cnt));
-	}
-
-	sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
-	sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
-	         __FUNCTION__, write ? "Wd" : "Rd", func, "INCR",
-	         addr, nbytes, sd->r_cnt, sd->t_cnt));
-
-
-	if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, nbytes)) != SUCCESS) {
-		sd_err(("%s: cmd_issue failed for %s\n", __FUNCTION__,
-			(write ? "write" : "read")));
-		return status;
-	}
-
-	/* gSPI expects that hw-header-len is equal to spi-command-len */
-	if ((func == 2) && (rw == SDIOH_WRITE) && (sd->dwordmode == FALSE)) {
-		ASSERT((uint16)sd->data_xfer_count == (uint16)(*data & 0xffff));
-		ASSERT((uint16)sd->data_xfer_count == (uint16)(~((*data & 0xffff0000) >> 16)));
-	}
-
-	if ((nbytes > 2000) && !write) {
-		sd_trace((">2KB read: F2 rd of %d bytes\n", nbytes));
-	}
-
-	return SUCCESS;
-}
-
-/* Reset and re-initialize the device */
-int
-sdioh_sdio_reset(sdioh_info_t *si)
-{
-	si->card_init_done = FALSE;
-	return bcmspi_client_init(si);
-}
-
-SDIOH_API_RC
-sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio)
-{
-	return SDIOH_API_RC_FAIL;
-}
-
-SDIOH_API_RC
-sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab)
-{
-	return SDIOH_API_RC_FAIL;
-}
-
-bool
-sdioh_gpioin(sdioh_info_t *sd, uint32 gpio)
-{
-	return FALSE;
-}
-
-SDIOH_API_RC
-sdioh_gpio_init(sdioh_info_t *sd)
-{
-	return SDIOH_API_RC_FAIL;
-}
diff --git a/drivers/net/wireless/bcmdhd/bcmutils.c b/drivers/net/wireless/bcmdhd/bcmutils.c
deleted file mode 100644
index a4f1f25..0000000
--- a/drivers/net/wireless/bcmdhd/bcmutils.c
+++ /dev/null
@@ -1,3545 +0,0 @@
-/*
- * Driver O/S-independent utility routines
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmutils.c 591286 2015-10-07 11:59:26Z $
- */
-
-#include <bcm_cfg.h>
-#include <typedefs.h>
-#include <bcmdefs.h>
-#include <stdarg.h>
-#ifdef BCMDRIVER
-
-#include <osl.h>
-#include <bcmutils.h>
-
-#else /* !BCMDRIVER */
-
-#include <stdio.h>
-#include <string.h>
-#include <bcmutils.h>
-
-#if defined(BCMEXTSUP)
-#include <bcm_osl.h>
-#endif
-
-#ifndef ASSERT
-#define ASSERT(exp)
-#endif
-
-#endif /* !BCMDRIVER */
-
-#include <bcmendian.h>
-#include <bcmdevs.h>
-#include <proto/ethernet.h>
-#include <proto/vlan.h>
-#include <proto/bcmip.h>
-#include <proto/802.1d.h>
-#include <proto/802.11.h>
-
-
-void *_bcmutils_dummy_fn = NULL;
-
-
-
-
-#ifdef BCMDRIVER
-
-
-
-/* copy a pkt buffer chain into a buffer */
-uint
-pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
-{
-	uint n, ret = 0;
-
-	if (len < 0)
-		len = 4096;	/* "infinite" */
-
-	/* skip 'offset' bytes */
-	for (; p && offset; p = PKTNEXT(osh, p)) {
-		if (offset < (uint)PKTLEN(osh, p))
-			break;
-		offset -= PKTLEN(osh, p);
-	}
-
-	if (!p)
-		return 0;
-
-	/* copy the data */
-	for (; p && len; p = PKTNEXT(osh, p)) {
-		n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
-		bcopy(PKTDATA(osh, p) + offset, buf, n);
-		buf += n;
-		len -= n;
-		ret += n;
-		offset = 0;
-	}
-
-	return ret;
-}
-
-/* copy a buffer into a pkt buffer chain */
-uint
-pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf)
-{
-	uint n, ret = 0;
-
-
-	/* skip 'offset' bytes */
-	for (; p && offset; p = PKTNEXT(osh, p)) {
-		if (offset < (uint)PKTLEN(osh, p))
-			break;
-		offset -= PKTLEN(osh, p);
-	}
-
-	if (!p)
-		return 0;
-
-	/* copy the data */
-	for (; p && len; p = PKTNEXT(osh, p)) {
-		n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
-		bcopy(buf, PKTDATA(osh, p) + offset, n);
-		buf += n;
-		len -= n;
-		ret += n;
-		offset = 0;
-	}
-
-	return ret;
-}
-
-
-
-/* return total length of buffer chain */
-uint BCMFASTPATH
-pkttotlen(osl_t *osh, void *p)
-{
-	uint total;
-	int len;
-
-	total = 0;
-	for (; p; p = PKTNEXT(osh, p)) {
-		len = PKTLEN(osh, p);
-		total += len;
-#ifdef BCMLFRAG
-		if (BCMLFRAG_ENAB()) {
-			if (PKTISFRAG(osh, p)) {
-				total += PKTFRAGTOTLEN(osh, p);
-			}
-		}
-#endif
-	}
-
-	return (total);
-}
-
-/* return the last buffer of chained pkt */
-void *
-pktlast(osl_t *osh, void *p)
-{
-	for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p))
-		;
-
-	return (p);
-}
-
-/* count segments of a chained packet */
-uint BCMFASTPATH
-pktsegcnt(osl_t *osh, void *p)
-{
-	uint cnt;
-
-	for (cnt = 0; p; p = PKTNEXT(osh, p)) {
-		cnt++;
-#ifdef BCMLFRAG
-		if (BCMLFRAG_ENAB()) {
-			if (PKTISFRAG(osh, p)) {
-				cnt += PKTFRAGTOTNUM(osh, p);
-			}
-		}
-#endif
-	}
-
-	return cnt;
-}
-
-
-/* count segments of a chained packet */
-uint BCMFASTPATH
-pktsegcnt_war(osl_t *osh, void *p)
-{
-	uint cnt;
-	uint8 *pktdata;
-	uint len, remain, align64;
-
-	for (cnt = 0; p; p = PKTNEXT(osh, p)) {
-		cnt++;
-		len = PKTLEN(osh, p);
-		if (len > 128) {
-			pktdata = (uint8 *)PKTDATA(osh, p);	/* starting address of data */
-			/* Check for page boundary straddle (2048B) */
-			if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff))
-				cnt++;
-
-			align64 = (uint)((uintptr)pktdata & 0x3f);	/* aligned to 64B */
-			align64 = (64 - align64) & 0x3f;
-			len -= align64;		/* bytes from aligned 64B to end */
-			/* if aligned to 128B, check for MOD 128 between 1 to 4B */
-			remain = len % 128;
-			if (remain > 0 && remain <= 4)
-				cnt++;		/* add extra seg */
-		}
-	}
-
-	return cnt;
-}
-
-uint8 * BCMFASTPATH
-pktdataoffset(osl_t *osh, void *p,  uint offset)
-{
-	uint total = pkttotlen(osh, p);
-	uint pkt_off = 0, len = 0;
-	uint8 *pdata = (uint8 *) PKTDATA(osh, p);
-
-	if (offset > total)
-		return NULL;
-
-	for (; p; p = PKTNEXT(osh, p)) {
-		pdata = (uint8 *) PKTDATA(osh, p);
-		pkt_off = offset - len;
-		len += PKTLEN(osh, p);
-		if (len > offset)
-			break;
-	}
-	return (uint8*) (pdata+pkt_off);
-}
-
-
-/* given a offset in pdata, find the pkt seg hdr */
-void *
-pktoffset(osl_t *osh, void *p,  uint offset)
-{
-	uint total = pkttotlen(osh, p);
-	uint len = 0;
-
-	if (offset > total)
-		return NULL;
-
-	for (; p; p = PKTNEXT(osh, p)) {
-		len += PKTLEN(osh, p);
-		if (len > offset)
-			break;
-	}
-	return p;
-}
-
-#endif /* BCMDRIVER */
-
-#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
-const unsigned char bcm_ctype[] = {
-
-	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 0-7 */
-	_BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C,
-	_BCM_C,	/* 8-15 */
-	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 16-23 */
-	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 24-31 */
-	_BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,		/* 32-39 */
-	_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,			/* 40-47 */
-	_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,			/* 48-55 */
-	_BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,			/* 56-63 */
-	_BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X,
-	_BCM_U|_BCM_X, _BCM_U, /* 64-71 */
-	_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,			/* 72-79 */
-	_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,			/* 80-87 */
-	_BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,			/* 88-95 */
-	_BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X,
-	_BCM_L|_BCM_X, _BCM_L, /* 96-103 */
-	_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
-	_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
-	_BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		/* 128-143 */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		/* 144-159 */
-	_BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
-	_BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,	/* 160-175 */
-	_BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
-	_BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,	/* 176-191 */
-	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
-	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,	/* 192-207 */
-	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U,
-	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L,	/* 208-223 */
-	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
-	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,	/* 224-239 */
-	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L,
-	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */
-};
-
-ulong
-bcm_strtoul(const char *cp, char **endp, uint base)
-{
-	ulong result, last_result = 0, value;
-	bool minus;
-
-	minus = FALSE;
-
-	while (bcm_isspace(*cp))
-		cp++;
-
-	if (cp[0] == '+')
-		cp++;
-	else if (cp[0] == '-') {
-		minus = TRUE;
-		cp++;
-	}
-
-	if (base == 0) {
-		if (cp[0] == '0') {
-			if ((cp[1] == 'x') || (cp[1] == 'X')) {
-				base = 16;
-				cp = &cp[2];
-			} else {
-				base = 8;
-				cp = &cp[1];
-			}
-		} else
-			base = 10;
-	} else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
-		cp = &cp[2];
-	}
-
-	result = 0;
-
-	while (bcm_isxdigit(*cp) &&
-	       (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
-		result = result*base + value;
-		/* Detected overflow */
-		if (result < last_result && !minus)
-			return (ulong)-1;
-		last_result = result;
-		cp++;
-	}
-
-	if (minus)
-		result = (ulong)(-(long)result);
-
-	if (endp)
-		*endp = DISCARD_QUAL(cp, char);
-
-	return (result);
-}
-
-int
-bcm_atoi(const char *s)
-{
-	return (int)bcm_strtoul(s, NULL, 10);
-}
-
-/* return pointer to location of substring 'needle' in 'haystack' */
-char *
-bcmstrstr(const char *haystack, const char *needle)
-{
-	int len, nlen;
-	int i;
-
-	if ((haystack == NULL) || (needle == NULL))
-		return DISCARD_QUAL(haystack, char);
-
-	nlen = (int)strlen(needle);
-	len = (int)strlen(haystack) - nlen + 1;
-
-	for (i = 0; i < len; i++)
-		if (memcmp(needle, &haystack[i], nlen) == 0)
-			return DISCARD_QUAL(&haystack[i], char);
-	return (NULL);
-}
-
-char *
-bcmstrnstr(const char *s, uint s_len, const char *substr, uint substr_len)
-{
-	for (; s_len >= substr_len; s++, s_len--)
-		if (strncmp(s, substr, substr_len) == 0)
-			return DISCARD_QUAL(s, char);
-
-	return NULL;
-}
-
-char *
-bcmstrcat(char *dest, const char *src)
-{
-	char *p;
-
-	p = dest + strlen(dest);
-
-	while ((*p++ = *src++) != '\0')
-		;
-
-	return (dest);
-}
-
-char *
-bcmstrncat(char *dest, const char *src, uint size)
-{
-	char *endp;
-	char *p;
-
-	p = dest + strlen(dest);
-	endp = p + size;
-
-	while (p != endp && (*p++ = *src++) != '\0')
-		;
-
-	return (dest);
-}
-
-
-/****************************************************************************
-* Function:   bcmstrtok
-*
-* Purpose:
-*  Tokenizes a string. This function is conceptually similiar to ANSI C strtok(),
-*  but allows strToken() to be used by different strings or callers at the same
-*  time. Each call modifies '*string' by substituting a NULL character for the
-*  first delimiter that is encountered, and updates 'string' to point to the char
-*  after the delimiter. Leading delimiters are skipped.
-*
-* Parameters:
-*  string      (mod) Ptr to string ptr, updated by token.
-*  delimiters  (in)  Set of delimiter characters.
-*  tokdelim    (out) Character that delimits the returned token. (May
-*                    be set to NULL if token delimiter is not required).
-*
-* Returns:  Pointer to the next token found. NULL when no more tokens are found.
-*****************************************************************************
-*/
-char *
-bcmstrtok(char **string, const char *delimiters, char *tokdelim)
-{
-	unsigned char *str;
-	unsigned long map[8];
-	int count;
-	char *nextoken;
-
-	if (tokdelim != NULL) {
-		/* Prime the token delimiter */
-		*tokdelim = '\0';
-	}
-
-	/* Clear control map */
-	for (count = 0; count < 8; count++) {
-		map[count] = 0;
-	}
-
-	/* Set bits in delimiter table */
-	do {
-		map[*delimiters >> 5] |= (1 << (*delimiters & 31));
-	}
-	while (*delimiters++);
-
-	str = (unsigned char*)*string;
-
-	/* Find beginning of token (skip over leading delimiters). Note that
-	 * there is no token iff this loop sets str to point to the terminal
-	 * null (*str == '\0')
-	 */
-	while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) {
-		str++;
-	}
-
-	nextoken = (char*)str;
-
-	/* Find the end of the token. If it is not the end of the string,
-	 * put a null there.
-	 */
-	for (; *str; str++) {
-		if (map[*str >> 5] & (1 << (*str & 31))) {
-			if (tokdelim != NULL) {
-				*tokdelim = *str;
-			}
-
-			*str++ = '\0';
-			break;
-		}
-	}
-
-	*string = (char*)str;
-
-	/* Determine if a token has been found. */
-	if (nextoken == (char *) str) {
-		return NULL;
-	}
-	else {
-		return nextoken;
-	}
-}
-
-
-#define xToLower(C) \
-	((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C)
-
-
-/****************************************************************************
-* Function:   bcmstricmp
-*
-* Purpose:    Compare to strings case insensitively.
-*
-* Parameters: s1 (in) First string to compare.
-*             s2 (in) Second string to compare.
-*
-* Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
-*             t1 > t2, when ignoring case sensitivity.
-*****************************************************************************
-*/
-int
-bcmstricmp(const char *s1, const char *s2)
-{
-	char dc, sc;
-
-	while (*s2 && *s1) {
-		dc = xToLower(*s1);
-		sc = xToLower(*s2);
-		if (dc < sc) return -1;
-		if (dc > sc) return 1;
-		s1++;
-		s2++;
-	}
-
-	if (*s1 && !*s2) return 1;
-	if (!*s1 && *s2) return -1;
-	return 0;
-}
-
-
-/****************************************************************************
-* Function:   bcmstrnicmp
-*
-* Purpose:    Compare to strings case insensitively, upto a max of 'cnt'
-*             characters.
-*
-* Parameters: s1  (in) First string to compare.
-*             s2  (in) Second string to compare.
-*             cnt (in) Max characters to compare.
-*
-* Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
-*             t1 > t2, when ignoring case sensitivity.
-*****************************************************************************
-*/
-int
-bcmstrnicmp(const char* s1, const char* s2, int cnt)
-{
-	char dc, sc;
-
-	while (*s2 && *s1 && cnt) {
-		dc = xToLower(*s1);
-		sc = xToLower(*s2);
-		if (dc < sc) return -1;
-		if (dc > sc) return 1;
-		s1++;
-		s2++;
-		cnt--;
-	}
-
-	if (!cnt) return 0;
-	if (*s1 && !*s2) return 1;
-	if (!*s1 && *s2) return -1;
-	return 0;
-}
-
-/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
-int
-bcm_ether_atoe(const char *p, struct ether_addr *ea)
-{
-	int i = 0;
-	char *ep;
-
-	for (;;) {
-		ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16);
-		p = ep;
-		if (!*p++ || i == 6)
-			break;
-	}
-
-	return (i == 6);
-}
-
-int
-bcm_atoipv4(const char *p, struct ipv4_addr *ip)
-{
-
-	int i = 0;
-	char *c;
-	for (;;) {
-		ip->addr[i++] = (uint8)bcm_strtoul(p, &c, 0);
-		if (*c++ != '.' || i == IPV4_ADDR_LEN)
-			break;
-		p = c;
-	}
-	return (i == IPV4_ADDR_LEN);
-}
-#endif	/* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
-
-
-#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
-/* registry routine buffer preparation utility functions:
- * parameter order is like strncpy, but returns count
- * of bytes copied. Minimum bytes copied is null char(1)/wchar(2)
- */
-ulong
-wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen)
-{
-	ulong copyct = 1;
-	ushort i;
-
-	if (abuflen == 0)
-		return 0;
-
-	/* wbuflen is in bytes */
-	wbuflen /= sizeof(ushort);
-
-	for (i = 0; i < wbuflen; ++i) {
-		if (--abuflen == 0)
-			break;
-		*abuf++ = (char) *wbuf++;
-		++copyct;
-	}
-	*abuf = '\0';
-
-	return copyct;
-}
-#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */
-
-char *
-bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
-{
-	static const char hex[] =
-	  {
-		  '0', '1', '2', '3', '4', '5', '6', '7',
-		  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
-	  };
-	const uint8 *octet = ea->octet;
-	char *p = buf;
-	int i;
-
-	for (i = 0; i < 6; i++, octet++) {
-		*p++ = hex[(*octet >> 4) & 0xf];
-		*p++ = hex[*octet & 0xf];
-		*p++ = ':';
-	}
-
-	*(p-1) = '\0';
-
-	return (buf);
-}
-
-char *
-bcm_ip_ntoa(struct ipv4_addr *ia, char *buf)
-{
-	snprintf(buf, 16, "%d.%d.%d.%d",
-	         ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]);
-	return (buf);
-}
-
-char *
-bcm_ipv6_ntoa(void *ipv6, char *buf)
-{
-	/* Implementing RFC 5952 Sections 4 + 5 */
-	/* Not thoroughly tested */
-	uint16 tmp[8];
-	uint16 *a = &tmp[0];
-	char *p = buf;
-	int i, i_max = -1, cnt = 0, cnt_max = 1;
-	uint8 *a4 = NULL;
-	memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN);
-
-	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
-		if (a[i]) {
-			if (cnt > cnt_max) {
-				cnt_max = cnt;
-				i_max = i - cnt;
-			}
-			cnt = 0;
-		} else
-			cnt++;
-	}
-	if (cnt > cnt_max) {
-		cnt_max = cnt;
-		i_max = i - cnt;
-	}
-	if (i_max == 0 &&
-		/* IPv4-translated: ::ffff:0:a.b.c.d */
-		((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
-		/* IPv4-mapped: ::ffff:a.b.c.d */
-		(cnt_max == 5 && a[5] == 0xffff)))
-		a4 = (uint8*) (a + 6);
-
-	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
-		if ((uint8*) (a + i) == a4) {
-			snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
-			break;
-		} else if (i == i_max) {
-			*p++ = ':';
-			i += cnt_max - 1;
-			p[0] = ':';
-			p[1] = '\0';
-		} else {
-			if (i)
-				*p++ = ':';
-			p += snprintf(p, 8, "%x", ntoh16(a[i]));
-		}
-	}
-
-	return buf;
-}
-#ifdef BCMDRIVER
-
-void
-bcm_mdelay(uint ms)
-{
-	uint i;
-
-	for (i = 0; i < ms; i++) {
-		OSL_DELAY(1000);
-	}
-}
-
-
-
-
-
-#if defined(DHD_DEBUG)
-/* pretty hex print a pkt buffer chain */
-void
-prpkt(const char *msg, osl_t *osh, void *p0)
-{
-	void *p;
-
-	if (msg && (msg[0] != '\0'))
-		printf("%s:\n", msg);
-
-	for (p = p0; p; p = PKTNEXT(osh, p))
-		prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p));
-}
-#endif	
-
-/* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
- * Also updates the inplace vlan tag if requested.
- * For debugging, it returns an indication of what it did.
- */
-uint BCMFASTPATH
-pktsetprio(void *pkt, bool update_vtag)
-{
-	struct ether_header *eh;
-	struct ethervlan_header *evh;
-	uint8 *pktdata;
-	int priority = 0;
-	int rc = 0;
-
-	pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
-	ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
-
-	eh = (struct ether_header *) pktdata;
-
-	if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) {
-		uint16 vlan_tag;
-		int vlan_prio, dscp_prio = 0;
-
-		evh = (struct ethervlan_header *)eh;
-
-		vlan_tag = ntoh16(evh->vlan_tag);
-		vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
-
-		if ((evh->ether_type == hton16(ETHER_TYPE_IP)) ||
-			(evh->ether_type == hton16(ETHER_TYPE_IPV6))) {
-			uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
-			uint8 tos_tc = IP_TOS46(ip_body);
-			dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
-		}
-
-		/* DSCP priority gets precedence over 802.1P (vlan tag) */
-		if (dscp_prio != 0) {
-			priority = dscp_prio;
-			rc |= PKTPRIO_VDSCP;
-		} else {
-			priority = vlan_prio;
-			rc |= PKTPRIO_VLAN;
-		}
-		/*
-		 * If the DSCP priority is not the same as the VLAN priority,
-		 * then overwrite the priority field in the vlan tag, with the
-		 * DSCP priority value. This is required for Linux APs because
-		 * the VLAN driver on Linux, overwrites the skb->priority field
-		 * with the priority value in the vlan tag
-		 */
-		if (update_vtag && (priority != vlan_prio)) {
-			vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
-			vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
-			evh->vlan_tag = hton16(vlan_tag);
-			rc |= PKTPRIO_UPD;
-		}
-#ifdef DHD_LOSSLESS_ROAMING
-	} else if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
-		priority = PRIO_8021D_NC;
-		rc = PKTPRIO_DSCP;
-#endif /* DHD_LOSSLESS_ROAMING */
-	} else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) ||
-		(eh->ether_type == hton16(ETHER_TYPE_IPV6))) {
-		uint8 *ip_body = pktdata + sizeof(struct ether_header);
-		uint8 tos_tc = IP_TOS46(ip_body);
-		uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT;
-		switch (dscp) {
-		case DSCP_EF:
-			priority = PRIO_8021D_VO;
-			break;
-		case DSCP_AF31:
-		case DSCP_AF32:
-		case DSCP_AF33:
-			priority = PRIO_8021D_CL;
-			break;
-		case DSCP_AF21:
-		case DSCP_AF22:
-		case DSCP_AF23:
-		case DSCP_AF11:
-		case DSCP_AF12:
-		case DSCP_AF13:
-			priority = PRIO_8021D_EE;
-			break;
-		default:
-			priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
-			break;
-		}
-
-		rc |= PKTPRIO_DSCP;
-	}
-
-	ASSERT(priority >= 0 && priority <= MAXPRIO);
-	PKTSETPRIO(pkt, priority);
-	return (rc | priority);
-}
-
-/* lookup user priority for specified DSCP */
-static uint8
-dscp2up(uint8 *up_table, uint8 dscp)
-{
-	uint8 user_priority = 255;
-
-	/* lookup up from table if parameters valid */
-	if (up_table != NULL && dscp < UP_TABLE_MAX) {
-		user_priority = up_table[dscp];
-	}
-
-	/* 255 is unused value so return up from dscp */
-	if (user_priority == 255) {
-		user_priority = dscp >> (IPV4_TOS_PREC_SHIFT - IPV4_TOS_DSCP_SHIFT);
-	}
-
-	return user_priority;
-}
-
-/* set user priority by QoS Map Set table (UP table), table size is UP_TABLE_MAX */
-uint BCMFASTPATH
-pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag)
-{
-	if (up_table) {
-		uint8 *pktdata;
-		uint pktlen;
-		uint8 dscp;
-		uint user_priority = 0;
-		uint rc = 0;
-
-		pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
-		pktlen = PKTLEN(OSH_NULL, pkt);
-
-		if (pktgetdscp(pktdata, pktlen, &dscp)) {
-			rc = PKTPRIO_DSCP;
-			user_priority = dscp2up(up_table, dscp);
-			PKTSETPRIO(pkt, user_priority);
-		}
-
-		return (rc | user_priority);
-	} else {
-		return pktsetprio(pkt, update_vtag);
-	}
-}
-
-/* Returns TRUE and DSCP if IP header found, FALSE otherwise.
- */
-bool BCMFASTPATH
-pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp)
-{
-	struct ether_header *eh;
-	struct ethervlan_header *evh;
-	uint8 *ip_body;
-	bool rc = FALSE;
-
-	/* minimum length is ether header and IP header */
-	if (pktlen < sizeof(struct ether_header) + IPV4_MIN_HEADER_LEN)
-		return FALSE;
-
-	eh = (struct ether_header *) pktdata;
-
-	if (eh->ether_type == HTON16(ETHER_TYPE_IP)) {
-		ip_body = pktdata + sizeof(struct ether_header);
-		*dscp = IP_DSCP46(ip_body);
-		rc = TRUE;
-	}
-	else if (eh->ether_type == HTON16(ETHER_TYPE_8021Q)) {
-		evh = (struct ethervlan_header *)eh;
-
-		/* minimum length is ethervlan header and IP header */
-		if (pktlen >= sizeof(struct ethervlan_header) + IPV4_MIN_HEADER_LEN &&
-			evh->ether_type == HTON16(ETHER_TYPE_IP)) {
-			ip_body = pktdata + sizeof(struct ethervlan_header);
-			*dscp = IP_DSCP46(ip_body);
-			rc = TRUE;
-		}
-	}
-
-	return rc;
-}
-
-/* The 0.5KB string table is not removed by compiler even though it's unused */
-
-static char bcm_undeferrstr[32];
-static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
-
-/* Convert the error codes into related error strings  */
-const char *
-bcmerrorstr(int bcmerror)
-{
-	/* check if someone added a bcmerror code but forgot to add errorstring */
-	ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
-
-	if (bcmerror > 0 || bcmerror < BCME_LAST) {
-		snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror);
-		return bcm_undeferrstr;
-	}
-
-	ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
-
-	return bcmerrorstrtable[-bcmerror];
-}
-
-
-
-/* iovar table lookup */
-/* could mandate sorted tables and do a binary search */
-const bcm_iovar_t*
-bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
-{
-	const bcm_iovar_t *vi;
-	const char *lookup_name;
-
-	/* skip any ':' delimited option prefixes */
-	lookup_name = strrchr(name, ':');
-	if (lookup_name != NULL)
-		lookup_name++;
-	else
-		lookup_name = name;
-
-	ASSERT(table != NULL);
-
-	for (vi = table; vi->name; vi++) {
-		if (!strcmp(vi->name, lookup_name))
-			return vi;
-	}
-	/* ran to end of table */
-
-	return NULL; /* var name not found */
-}
-
-int
-bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
-{
-	int bcmerror = 0;
-
-	/* length check on io buf */
-	switch (vi->type) {
-	case IOVT_BOOL:
-	case IOVT_INT8:
-	case IOVT_INT16:
-	case IOVT_INT32:
-	case IOVT_UINT8:
-	case IOVT_UINT16:
-	case IOVT_UINT32:
-		/* all integers are int32 sized args at the ioctl interface */
-		if (len < (int)sizeof(int)) {
-			bcmerror = BCME_BUFTOOSHORT;
-		}
-		break;
-
-	case IOVT_BUFFER:
-		/* buffer must meet minimum length requirement */
-		if (len < vi->minlen) {
-			bcmerror = BCME_BUFTOOSHORT;
-		}
-		break;
-
-	case IOVT_VOID:
-		if (!set) {
-			/* Cannot return nil... */
-			bcmerror = BCME_UNSUPPORTED;
-		} else if (len) {
-			/* Set is an action w/o parameters */
-			bcmerror = BCME_BUFTOOLONG;
-		}
-		break;
-
-	default:
-		/* unknown type for length check in iovar info */
-		ASSERT(0);
-		bcmerror = BCME_UNSUPPORTED;
-	}
-
-	return bcmerror;
-}
-
-#endif	/* BCMDRIVER */
-
-#ifdef BCM_OBJECT_TRACE
-
-#define BCM_OBJECT_MERGE_SAME_OBJ	0
-
-/* some place may add / remove the object to trace list for Linux: */
-/* add:    osl_alloc_skb dev_alloc_skb skb_realloc_headroom dhd_start_xmit */
-/* remove: osl_pktfree dev_kfree_skb netif_rx */
-
-#define BCM_OBJDBG_COUNT          (1024 * 100)
-static spinlock_t dbgobj_lock;
-#define	BCM_OBJDBG_LOCK_INIT()    spin_lock_init(&dbgobj_lock)
-#define	BCM_OBJDBG_LOCK_DESTROY()
-#define	BCM_OBJDBG_LOCK           spin_lock_irqsave
-#define	BCM_OBJDBG_UNLOCK         spin_unlock_irqrestore
-
-#define BCM_OBJDBG_ADDTOHEAD      0
-#define BCM_OBJDBG_ADDTOTAIL      1
-
-#define BCM_OBJDBG_CALLER_LEN     32
-struct bcm_dbgobj {
-	struct bcm_dbgobj *prior;
-	struct bcm_dbgobj *next;
-	uint32 flag;
-	void   *obj;
-	uint32 obj_sn;
-	uint32 obj_state;
-	uint32 line;
-	char   caller[BCM_OBJDBG_CALLER_LEN];
-};
-
-static struct bcm_dbgobj *dbgobj_freehead = NULL;
-static struct bcm_dbgobj *dbgobj_freetail = NULL;
-static struct bcm_dbgobj *dbgobj_objhead = NULL;
-static struct bcm_dbgobj *dbgobj_objtail = NULL;
-
-static uint32 dbgobj_sn = 0;
-static int dbgobj_count = 0;
-static struct bcm_dbgobj bcm_dbg_objs[BCM_OBJDBG_COUNT];
-
-void
-bcm_object_trace_init(void)
-{
-	int i = 0;
-	BCM_OBJDBG_LOCK_INIT();
-	memset(&bcm_dbg_objs, 0x00, sizeof(struct bcm_dbgobj) * BCM_OBJDBG_COUNT);
-	dbgobj_freehead = &bcm_dbg_objs[0];
-	dbgobj_freetail = &bcm_dbg_objs[BCM_OBJDBG_COUNT - 1];
-
-	for (i = 0; i < BCM_OBJDBG_COUNT; ++i) {
-		bcm_dbg_objs[i].next = (i == (BCM_OBJDBG_COUNT - 1)) ?
-			dbgobj_freehead : &bcm_dbg_objs[i + 1];
-		bcm_dbg_objs[i].prior = (i == 0) ?
-			dbgobj_freetail : &bcm_dbg_objs[i - 1];
-	}
-}
-
-void
-bcm_object_trace_deinit(void)
-{
-	if (dbgobj_objhead || dbgobj_objtail) {
-		printf("%s: not all objects are released\n", __FUNCTION__);
-		ASSERT(0);
-	}
-	BCM_OBJDBG_LOCK_DESTROY();
-}
-
-static void
-bcm_object_rm_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
-	struct bcm_dbgobj *dbgobj)
-{
-	if ((dbgobj == *head) && (dbgobj == *tail)) {
-		*head = NULL;
-		*tail = NULL;
-	} else if (dbgobj == *head) {
-		*head = (*head)->next;
-	} else if (dbgobj == *tail) {
-		*tail = (*tail)->prior;
-	}
-	dbgobj->next->prior = dbgobj->prior;
-	dbgobj->prior->next = dbgobj->next;
-}
-
-static void
-bcm_object_add_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
-	struct bcm_dbgobj *dbgobj, int addtotail)
-{
-	if (!(*head) && !(*tail)) {
-		*head = dbgobj;
-		*tail = dbgobj;
-		dbgobj->next = dbgobj;
-		dbgobj->prior = dbgobj;
-	} else if ((*head) && (*tail)) {
-		(*tail)->next = dbgobj;
-		(*head)->prior = dbgobj;
-		dbgobj->next = *head;
-		dbgobj->prior = *tail;
-		if (addtotail == BCM_OBJDBG_ADDTOTAIL)
-			*tail = dbgobj;
-		else
-			*head = dbgobj;
-	} else {
-		ASSERT(0); /* can't be this case */
-	}
-}
-
-static INLINE void
-bcm_object_movetoend(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
-	struct bcm_dbgobj *dbgobj, int movetotail)
-{
-	if ((*head) && (*tail)) {
-		if (movetotail == BCM_OBJDBG_ADDTOTAIL) {
-			if (dbgobj != (*tail)) {
-				bcm_object_rm_list(head, tail, dbgobj);
-				bcm_object_add_list(head, tail, dbgobj, movetotail);
-			}
-		} else {
-			if (dbgobj != (*head)) {
-				bcm_object_rm_list(head, tail, dbgobj);
-				bcm_object_add_list(head, tail, dbgobj, movetotail);
-			}
-		}
-	} else {
-		ASSERT(0); /* can't be this case */
-	}
-}
-
-void
-bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line)
-{
-	struct bcm_dbgobj *dbgobj;
-	unsigned long flags;
-
-	BCM_REFERENCE(flags);
-	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
-
-	if (opt == BCM_OBJDBG_ADD_PKT ||
-		opt == BCM_OBJDBG_ADD) {
-		dbgobj = dbgobj_objtail;
-		while (dbgobj) {
-			if (dbgobj->obj == obj) {
-				printf("%s: obj %p allocated from %s(%d),"
-					" allocate again from %s(%d)\n",
-					__FUNCTION__, dbgobj->obj,
-					dbgobj->caller, dbgobj->line,
-					caller, line);
-				ASSERT(0);
-				goto EXIT;
-			}
-			dbgobj = dbgobj->prior;
-			if (dbgobj == dbgobj_objtail)
-				break;
-		}
-
-#if BCM_OBJECT_MERGE_SAME_OBJ
-		dbgobj = dbgobj_freetail;
-		while (dbgobj) {
-			if (dbgobj->obj == obj) {
-				goto FREED_ENTRY_FOUND;
-			}
-			dbgobj = dbgobj->prior;
-			if (dbgobj == dbgobj_freetail)
-				break;
-		}
-#endif /* BCM_OBJECT_MERGE_SAME_OBJ */
-
-		dbgobj = dbgobj_freehead;
-#if BCM_OBJECT_MERGE_SAME_OBJ
-FREED_ENTRY_FOUND:
-#endif /* BCM_OBJECT_MERGE_SAME_OBJ */
-		if (!dbgobj) {
-			printf("%s: already got %d objects ?????????????????????\n",
-				__FUNCTION__, BCM_OBJDBG_COUNT);
-			ASSERT(0);
-			goto EXIT;
-		}
-
-		bcm_object_rm_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj);
-		dbgobj->obj = obj;
-		strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
-		dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
-		dbgobj->line = line;
-		dbgobj->flag = 0;
-		if (opt == BCM_OBJDBG_ADD_PKT) {
-			dbgobj->obj_sn = dbgobj_sn++;
-			dbgobj->obj_state = 0;
-			/* first 4 bytes is pkt sn */
-			if (((unsigned long)PKTTAG(obj)) & 0x3)
-				printf("pkt tag address not aligned by 4: %p\n", PKTTAG(obj));
-			*(uint32*)PKTTAG(obj) = dbgobj->obj_sn;
-		}
-		bcm_object_add_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj,
-			BCM_OBJDBG_ADDTOTAIL);
-
-		dbgobj_count++;
-
-	} else if (opt == BCM_OBJDBG_REMOVE) {
-		dbgobj = dbgobj_objtail;
-		while (dbgobj) {
-			if (dbgobj->obj == obj) {
-				if (dbgobj->flag) {
-					printf("%s: rm flagged obj %p flag 0x%08x from %s(%d)\n",
-						__FUNCTION__, obj, dbgobj->flag, caller, line);
-				}
-				bcm_object_rm_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj);
-				memset(dbgobj->caller, 0x00, BCM_OBJDBG_CALLER_LEN);
-				strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
-				dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
-				dbgobj->line = line;
-				bcm_object_add_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj,
-					BCM_OBJDBG_ADDTOTAIL);
-				dbgobj_count--;
-				goto EXIT;
-			}
-			dbgobj = dbgobj->prior;
-			if (dbgobj == dbgobj_objtail)
-				break;
-		}
-
-		dbgobj = dbgobj_freetail;
-		while (dbgobj && dbgobj->obj) {
-			if (dbgobj->obj == obj) {
-				printf("%s: obj %p already freed from from %s(%d),"
-					" try free again from %s(%d)\n",
-					__FUNCTION__, obj,
-					dbgobj->caller, dbgobj->line,
-					caller, line);
-				//ASSERT(0); /* release same obj more than one time? */
-				goto EXIT;
-			}
-			dbgobj = dbgobj->prior;
-			if (dbgobj == dbgobj_freetail)
-				break;
-		}
-
-		printf("%s: ################### release none-existing obj %p from %s(%d)\n",
-			__FUNCTION__, obj, caller, line);
-		//ASSERT(0); /* release same obj more than one time? */
-
-	}
-
-EXIT:
-	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
-	return;
-}
-
-void
-bcm_object_trace_upd(void *obj, void *obj_new)
-{
-	struct bcm_dbgobj *dbgobj;
-	unsigned long flags;
-
-	BCM_REFERENCE(flags);
-	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
-
-	dbgobj = dbgobj_objtail;
-	while (dbgobj) {
-		if (dbgobj->obj == obj) {
-			dbgobj->obj = obj_new;
-			if (dbgobj != dbgobj_objtail) {
-				bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
-					dbgobj, BCM_OBJDBG_ADDTOTAIL);
-			}
-			goto EXIT;
-		}
-		dbgobj = dbgobj->prior;
-		if (dbgobj == dbgobj_objtail)
-			break;
-	}
-
-EXIT:
-	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
-	return;
-}
-
-void
-bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn,
-	const char *caller, int line)
-{
-	struct bcm_dbgobj *dbgobj;
-	unsigned long flags;
-
-	BCM_REFERENCE(flags);
-	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
-
-	dbgobj = dbgobj_objtail;
-	while (dbgobj) {
-		if ((dbgobj->obj == obj) &&
-			((!chksn) || (dbgobj->obj_sn == sn))) {
-			if (dbgobj != dbgobj_objtail) {
-				bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
-					dbgobj, BCM_OBJDBG_ADDTOTAIL);
-			}
-			goto EXIT;
-		}
-		dbgobj = dbgobj->prior;
-		if (dbgobj == dbgobj_objtail)
-			break;
-	}
-
-	dbgobj = dbgobj_freetail;
-	while (dbgobj) {
-		if ((dbgobj->obj == obj) &&
-			((!chksn) || (dbgobj->obj_sn == sn))) {
-			printf("%s: (%s:%d) obj %p (sn %d state %d) was freed from %s(%d)\n",
-				__FUNCTION__, caller, line,
-				dbgobj->obj, dbgobj->obj_sn, dbgobj->obj_state,
-				dbgobj->caller, dbgobj->line);
-			goto EXIT;
-		}
-		else if (dbgobj->obj == NULL) {
-			break;
-		}
-		dbgobj = dbgobj->prior;
-		if (dbgobj == dbgobj_freetail)
-			break;
-	}
-
-	printf("%s: obj %p not found, check from %s(%d), chksn %s, sn %d\n",
-		__FUNCTION__, obj, caller, line, chksn ? "yes" : "no", sn);
-	dbgobj = dbgobj_objtail;
-	while (dbgobj) {
-		printf("%s: (%s:%d) obj %p sn %d was allocated from %s(%d)\n",
-				__FUNCTION__, caller, line,
-				dbgobj->obj, dbgobj->obj_sn, dbgobj->caller, dbgobj->line);
-		dbgobj = dbgobj->prior;
-		if (dbgobj == dbgobj_objtail)
-			break;
-	}
-
-EXIT:
-	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
-	return;
-}
-
-void
-bcm_object_feature_set(void *obj, uint32 type, uint32 value)
-{
-	struct bcm_dbgobj *dbgobj;
-	unsigned long flags;
-
-	BCM_REFERENCE(flags);
-	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
-
-	dbgobj = dbgobj_objtail;
-	while (dbgobj) {
-		if (dbgobj->obj == obj) {
-			if (type == BCM_OBJECT_FEATURE_FLAG) {
-				if (value & BCM_OBJECT_FEATURE_CLEAR)
-					dbgobj->flag &= ~(value);
-				else
-					dbgobj->flag |= (value);
-			} else if (type == BCM_OBJECT_FEATURE_PKT_STATE) {
-				dbgobj->obj_state = value;
-			}
-			if (dbgobj != dbgobj_objtail) {
-				bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
-					dbgobj, BCM_OBJDBG_ADDTOTAIL);
-			}
-			goto EXIT;
-		}
-		dbgobj = dbgobj->prior;
-		if (dbgobj == dbgobj_objtail)
-			break;
-	}
-
-	printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
-	ASSERT(0);
-
-EXIT:
-	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
-	return;
-}
-
-int
-bcm_object_feature_get(void *obj, uint32 type, uint32 value)
-{
-	int rtn = 0;
-	struct bcm_dbgobj *dbgobj;
-	unsigned long flags;
-
-	BCM_REFERENCE(flags);
-	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
-
-	dbgobj = dbgobj_objtail;
-	while (dbgobj) {
-		if (dbgobj->obj == obj) {
-			if (type == BCM_OBJECT_FEATURE_FLAG) {
-				rtn = (dbgobj->flag & value) & (~BCM_OBJECT_FEATURE_CLEAR);
-			}
-			if (dbgobj != dbgobj_objtail) {
-				bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
-					dbgobj, BCM_OBJDBG_ADDTOTAIL);
-			}
-			goto EXIT;
-		}
-		dbgobj = dbgobj->prior;
-		if (dbgobj == dbgobj_objtail)
-			break;
-	}
-
-	printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
-	ASSERT(0);
-
-EXIT:
-	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
-	return rtn;
-}
-
-#endif /* BCM_OBJECT_TRACE */
-
-uint8 *
-bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst)
-{
-	uint8 *new_dst = dst;
-	bcm_tlv_t *dst_tlv = (bcm_tlv_t *)dst;
-
-	/* dst buffer should always be valid */
-	ASSERT(dst);
-
-	/* data len must be within valid range */
-	ASSERT((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE));
-
-	/* source data buffer pointer should be valid, unless datalen is 0
-	 * meaning no data with this TLV
-	 */
-	ASSERT((data != NULL) || (datalen == 0));
-
-	/* only do work if the inputs are valid
-	 * - must have a dst to write to AND
-	 * - datalen must be within range AND
-	 * - the source data pointer must be non-NULL if datalen is non-zero
-	 * (this last condition detects datalen > 0 with a NULL data pointer)
-	 */
-	if ((dst != NULL) &&
-	    ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) &&
-	    ((data != NULL) || (datalen == 0))) {
-
-	        /* write type, len fields */
-		dst_tlv->id = (uint8)type;
-	        dst_tlv->len = (uint8)datalen;
-
-		/* if data is present, copy to the output buffer and update
-		 * pointer to output buffer
-		 */
-		if (datalen > 0) {
-
-			memcpy(dst_tlv->data, data, datalen);
-		}
-
-		/* update the output destination poitner to point past
-		 * the TLV written
-		 */
-		new_dst = dst + BCM_TLV_HDR_SIZE + datalen;
-	}
-
-	return (new_dst);
-}
-
-uint8 *
-bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, int dst_maxlen)
-{
-	uint8 *new_dst = dst;
-
-	if ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) {
-
-		/* if len + tlv hdr len is more than destlen, don't do anything
-		 * just return the buffer untouched
-		 */
-		if ((int)(datalen + BCM_TLV_HDR_SIZE) <= dst_maxlen) {
-
-			new_dst = bcm_write_tlv(type, data, datalen, dst);
-		}
-	}
-
-	return (new_dst);
-}
-
-uint8 *
-bcm_copy_tlv(const void *src, uint8 *dst)
-{
-	uint8 *new_dst = dst;
-	const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
-	uint totlen;
-
-	ASSERT(dst && src);
-	if (dst && src) {
-
-		totlen = BCM_TLV_HDR_SIZE + src_tlv->len;
-		memcpy(dst, src_tlv, totlen);
-		new_dst = dst + totlen;
-	}
-
-	return (new_dst);
-}
-
-
-uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen)
-{
-	uint8 *new_dst = dst;
-	const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
-
-	ASSERT(src);
-	if (src) {
-		if (bcm_valid_tlv(src_tlv, dst_maxlen)) {
-			new_dst = bcm_copy_tlv(src, dst);
-		}
-	}
-
-	return (new_dst);
-}
-
-
-#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
-/*******************************************************************************
- * crc8
- *
- * Computes a crc8 over the input data using the polynomial:
- *
- *       x^8 + x^7 +x^6 + x^4 + x^2 + 1
- *
- * The caller provides the initial value (either CRC8_INIT_VALUE
- * or the previous returned value) to allow for processing of
- * discontiguous blocks of data.  When generating the CRC the
- * caller is responsible for complementing the final return value
- * and inserting it into the byte stream.  When checking, a final
- * return value of CRC8_GOOD_VALUE indicates a valid CRC.
- *
- * Reference: Dallas Semiconductor Application Note 27
- *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
- *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
- *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
- *
- * ****************************************************************************
- */
-
-static const uint8 crc8_table[256] = {
-    0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
-    0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
-    0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
-    0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
-    0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
-    0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
-    0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
-    0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
-    0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
-    0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
-    0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
-    0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
-    0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
-    0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
-    0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
-    0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
-    0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
-    0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
-    0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
-    0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
-    0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
-    0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
-    0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
-    0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
-    0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
-    0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
-    0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
-    0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
-    0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
-    0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
-    0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
-    0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
-};
-
-#define CRC_INNER_LOOP(n, c, x) \
-	(c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
-
-uint8
-hndcrc8(
-	uint8 *pdata,	/* pointer to array of data to process */
-	uint  nbytes,	/* number of input data bytes to process */
-	uint8 crc	/* either CRC8_INIT_VALUE or previous return value */
-)
-{
-	/* hard code the crc loop instead of using CRC_INNER_LOOP macro
-	 * to avoid the undefined and unnecessary (uint8 >> 8) operation.
-	 */
-	while (nbytes-- > 0)
-		crc = crc8_table[(crc ^ *pdata++) & 0xff];
-
-	return crc;
-}
-
-/*******************************************************************************
- * crc16
- *
- * Computes a crc16 over the input data using the polynomial:
- *
- *       x^16 + x^12 +x^5 + 1
- *
- * The caller provides the initial value (either CRC16_INIT_VALUE
- * or the previous returned value) to allow for processing of
- * discontiguous blocks of data.  When generating the CRC the
- * caller is responsible for complementing the final return value
- * and inserting it into the byte stream.  When checking, a final
- * return value of CRC16_GOOD_VALUE indicates a valid CRC.
- *
- * Reference: Dallas Semiconductor Application Note 27
- *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
- *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
- *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
- *
- * ****************************************************************************
- */
-
-static const uint16 crc16_table[256] = {
-    0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
-    0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
-    0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
-    0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
-    0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
-    0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
-    0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
-    0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
-    0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
-    0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
-    0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
-    0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
-    0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
-    0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
-    0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
-    0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
-    0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
-    0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
-    0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
-    0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
-    0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
-    0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
-    0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
-    0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
-    0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
-    0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
-    0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
-    0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
-    0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
-    0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
-    0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
-    0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
-};
-
-uint16
-hndcrc16(
-    uint8 *pdata,  /* pointer to array of data to process */
-    uint nbytes, /* number of input data bytes to process */
-    uint16 crc     /* either CRC16_INIT_VALUE or previous return value */
-)
-{
-	while (nbytes-- > 0)
-		CRC_INNER_LOOP(16, crc, *pdata++);
-	return crc;
-}
-
-static const uint32 crc32_table[256] = {
-    0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
-    0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
-    0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
-    0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
-    0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
-    0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
-    0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
-    0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
-    0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
-    0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
-    0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
-    0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
-    0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
-    0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
-    0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
-    0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
-    0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
-    0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
-    0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
-    0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
-    0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
-    0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
-    0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
-    0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
-    0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
-    0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
-    0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
-    0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
-    0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
-    0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
-    0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
-    0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
-    0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
-    0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
-    0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
-    0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
-    0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
-    0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
-    0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
-    0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
-    0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
-    0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
-    0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
-    0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
-    0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
-    0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
-    0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
-    0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
-    0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
-    0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
-    0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
-    0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
-    0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
-    0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
-    0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
-    0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
-    0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
-    0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
-    0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
-    0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
-    0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
-    0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
-    0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
-    0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
-};
-
-/*
- * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if
- * accumulating over multiple pieces.
- */
-uint32
-hndcrc32(uint8 *pdata, uint nbytes, uint32 crc)
-{
-	uint8 *pend;
-	pend = pdata + nbytes;
-	while (pdata < pend)
-		CRC_INNER_LOOP(32, crc, *pdata++);
-
-	return crc;
-}
-
-#ifdef notdef
-#define CLEN 	1499 	/*  CRC Length */
-#define CBUFSIZ 	(CLEN+4)
-#define CNBUFS		5 /* # of bufs */
-
-void
-testcrc32(void)
-{
-	uint j, k, l;
-	uint8 *buf;
-	uint len[CNBUFS];
-	uint32 crcr;
-	uint32 crc32tv[CNBUFS] =
-		{0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110};
-
-	ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL);
-
-	/* step through all possible alignments */
-	for (l = 0; l <= 4; l++) {
-		for (j = 0; j < CNBUFS; j++) {
-			len[j] = CLEN;
-			for (k = 0; k < len[j]; k++)
-				*(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff;
-		}
-
-		for (j = 0; j < CNBUFS; j++) {
-			crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE);
-			ASSERT(crcr == crc32tv[j]);
-		}
-	}
-
-	MFREE(buf, CBUFSIZ*CNBUFS);
-	return;
-}
-#endif /* notdef */
-
-/*
- * Advance from the current 1-byte tag/1-byte length/variable-length value
- * triple, to the next, returning a pointer to the next.
- * If the current or next TLV is invalid (does not fit in given buffer length),
- * NULL is returned.
- * *buflen is not modified if the TLV elt parameter is invalid, or is decremented
- * by the TLV parameter's length if it is valid.
- */
-bcm_tlv_t *
-bcm_next_tlv(bcm_tlv_t *elt, int *buflen)
-{
-	int len;
-
-	/* validate current elt */
-	if (!bcm_valid_tlv(elt, *buflen)) {
-		return NULL;
-	}
-
-	/* advance to next elt */
-	len = elt->len;
-	elt = (bcm_tlv_t*)(elt->data + len);
-	*buflen -= (TLV_HDR_LEN + len);
-
-	/* validate next elt */
-	if (!bcm_valid_tlv(elt, *buflen)) {
-		return NULL;
-	}
-
-	return elt;
-}
-
-/*
- * Traverse a string of 1-byte tag/1-byte length/variable-length value
- * triples, returning a pointer to the substring whose first element
- * matches tag
- */
-bcm_tlv_t *
-bcm_parse_tlvs(void *buf, int buflen, uint key)
-{
-	bcm_tlv_t *elt;
-	int totlen;
-
-	if ((elt = (bcm_tlv_t*)buf) == NULL) {
-		return NULL;
-	}
-	totlen = buflen;
-
-	/* find tagged parameter */
-	while (totlen >= TLV_HDR_LEN) {
-		int len = elt->len;
-
-		/* validate remaining totlen */
-		if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
-
-			return (elt);
-		}
-
-		elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
-		totlen -= (len + TLV_HDR_LEN);
-	}
-
-	return NULL;
-}
-
-/*
- * Traverse a string of 1-byte tag/1-byte length/variable-length value
- * triples, returning a pointer to the substring whose first element
- * matches tag
- * return NULL if not found or length field < min_varlen
- */
-bcm_tlv_t *
-bcm_parse_tlvs_min_bodylen(void *buf, int buflen, uint key, int min_bodylen)
-{
-	bcm_tlv_t * ret = bcm_parse_tlvs(buf, buflen, key);
-	if (ret == NULL || ret->len < min_bodylen) {
-		return NULL;
-	}
-	return ret;
-}
-
-/*
- * Traverse a string of 1-byte tag/1-byte length/variable-length value
- * triples, returning a pointer to the substring whose first element
- * matches tag.  Stop parsing when we see an element whose ID is greater
- * than the target key.
- */
-bcm_tlv_t *
-bcm_parse_ordered_tlvs(void *buf, int buflen, uint key)
-{
-	bcm_tlv_t *elt;
-	int totlen;
-
-	elt = (bcm_tlv_t*)buf;
-	totlen = buflen;
-
-	/* find tagged parameter */
-	while (totlen >= TLV_HDR_LEN) {
-		uint id = elt->id;
-		int len = elt->len;
-
-		/* Punt if we start seeing IDs > than target key */
-		if (id > key) {
-			return (NULL);
-		}
-
-		/* validate remaining totlen */
-		if ((id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
-			return (elt);
-		}
-
-		elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
-		totlen -= (len + TLV_HDR_LEN);
-	}
-	return NULL;
-}
-#endif	/* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
-
-#if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \
-	defined(DHD_DEBUG)
-int
-bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len)
-{
-	int i, slen = 0;
-	uint32 bit, mask;
-	const char *name;
-	mask = bd->mask;
-	if (len < 2 || !buf)
-		return 0;
-
-	buf[0] = '\0';
-
-	for (i = 0;  (name = bd->bitfield[i].name) != NULL; i++) {
-		bit = bd->bitfield[i].bit;
-		if ((flags & mask) == bit) {
-			if (len > (int)strlen(name)) {
-				slen = strlen(name);
-				strncpy(buf, name, slen+1);
-			}
-			break;
-		}
-	}
-	return slen;
-}
-
-int
-bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len)
-{
-	int i;
-	char* p = buf;
-	char hexstr[16];
-	int slen = 0, nlen = 0;
-	uint32 bit;
-	const char* name;
-
-	if (len < 2 || !buf)
-		return 0;
-
-	buf[0] = '\0';
-
-	for (i = 0; flags != 0; i++) {
-		bit = bd[i].bit;
-		name = bd[i].name;
-		if (bit == 0 && flags != 0) {
-			/* print any unnamed bits */
-			snprintf(hexstr, 16, "0x%X", flags);
-			name = hexstr;
-			flags = 0;	/* exit loop */
-		} else if ((flags & bit) == 0)
-			continue;
-		flags &= ~bit;
-		nlen = strlen(name);
-		slen += nlen;
-		/* count btwn flag space */
-		if (flags != 0)
-			slen += 1;
-		/* need NULL char as well */
-		if (len <= slen)
-			break;
-		/* copy NULL char but don't count it */
-		strncpy(p, name, nlen + 1);
-		p += nlen;
-		/* copy btwn flag space and NULL char */
-		if (flags != 0)
-			p += snprintf(p, 2, " ");
-	}
-
-	/* indicate the str was too short */
-	if (flags != 0) {
-		p += snprintf(p, 2, ">");
-	}
-
-	return (int)(p - buf);
-}
-#endif 
-
-/* print bytes formatted as hex to a string. return the resulting string length */
-int
-bcm_format_hex(char *str, const void *bytes, int len)
-{
-	int i;
-	char *p = str;
-	const uint8 *src = (const uint8*)bytes;
-
-	for (i = 0; i < len; i++) {
-		p += snprintf(p, 3, "%02X", *src);
-		src++;
-	}
-	return (int)(p - str);
-}
-
-/* pretty hex print a contiguous buffer */
-void
-prhex(const char *msg, uchar *buf, uint nbytes)
-{
-	char line[128], *p;
-	int len = sizeof(line);
-	int nchar;
-	uint i;
-
-	if (msg && (msg[0] != '\0'))
-		printf("%s:\n", msg);
-
-	p = line;
-	for (i = 0; i < nbytes; i++) {
-		if (i % 16 == 0) {
-			nchar = snprintf(p, len, "  %04x: ", i);	/* line prefix */
-			p += nchar;
-			len -= nchar;
-		}
-		if (len > 0) {
-			nchar = snprintf(p, len, "%02x ", buf[i]);
-			p += nchar;
-			len -= nchar;
-		}
-
-		if (i % 16 == 15) {
-			printf("%s\n", line);		/* flush line */
-			p = line;
-			len = sizeof(line);
-		}
-	}
-
-	/* flush last partial line */
-	if (p != line)
-		printf("%s\n", line);
-}
-
-static const char *crypto_algo_names[] = {
-	"NONE",
-	"WEP1",
-	"TKIP",
-	"WEP128",
-	"AES_CCM",
-	"AES_OCB_MSDU",
-	"AES_OCB_MPDU",
-	"NALG",
-	"UNDEF",
-	"UNDEF",
-	"UNDEF",
-	"UNDEF"
-	"PMK",
-	"BIP",
-	"AES_GCM",
-	"AES_CCM256",
-	"AES_GCM256",
-	"BIP_CMAC256",
-	"BIP_GMAC",
-	"BIP_GMAC256",
-	"UNDEF"
-};
-
-const char *
-bcm_crypto_algo_name(uint algo)
-{
-	return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR";
-}
-
-
-char *
-bcm_chipname(uint chipid, char *buf, uint len)
-{
-	const char *fmt;
-
-	fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
-	snprintf(buf, len, fmt, chipid);
-	return buf;
-}
-
-/* Produce a human-readable string for boardrev */
-char *
-bcm_brev_str(uint32 brev, char *buf)
-{
-	if (brev < 0x100)
-		snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
-	else
-		snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff);
-
-	return (buf);
-}
-
-#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */
-
-/* dump large strings to console */
-void
-printbig(char *buf)
-{
-	uint len, max_len;
-	char c;
-
-	len = (uint)strlen(buf);
-
-	max_len = BUFSIZE_TODUMP_ATONCE;
-
-	while (len > max_len) {
-		c = buf[max_len];
-		buf[max_len] = '\0';
-		printf("%s", buf);
-		buf[max_len] = c;
-
-		buf += max_len;
-		len -= max_len;
-	}
-	/* print the remaining string */
-	printf("%s\n", buf);
-	return;
-}
-
-/* routine to dump fields in a fileddesc structure */
-uint
-bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array,
-	char *buf, uint32 bufsize)
-{
-	uint  filled_len;
-	int len;
-	struct fielddesc *cur_ptr;
-
-	filled_len = 0;
-	cur_ptr = fielddesc_array;
-
-	while (bufsize > 1) {
-		if (cur_ptr->nameandfmt == NULL)
-			break;
-		len = snprintf(buf, bufsize, cur_ptr->nameandfmt,
-		               read_rtn(arg0, arg1, cur_ptr->offset));
-		/* check for snprintf overflow or error */
-		if (len < 0 || (uint32)len >= bufsize)
-			len = bufsize - 1;
-		buf += len;
-		bufsize -= len;
-		filled_len += len;
-		cur_ptr++;
-	}
-	return filled_len;
-}
-
-uint
-bcm_mkiovar(const char *name, char *data, uint datalen, char *buf, uint buflen)
-{
-	uint len;
-
-	len = (uint)strlen(name) + 1;
-
-	if ((len + datalen) > buflen)
-		return 0;
-
-	strncpy(buf, name, buflen);
-
-	/* append data onto the end of the name string */
-	memcpy(&buf[len], data, datalen);
-	len += datalen;
-
-	return len;
-}
-
-/* Quarter dBm units to mW
- * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
- * Table is offset so the last entry is largest mW value that fits in
- * a uint16.
- */
-
-#define QDBM_OFFSET 153		/* Offset for first entry */
-#define QDBM_TABLE_LEN 40	/* Table size */
-
-/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
- * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
- */
-#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
-
-/* Largest mW value that will round down to the last table entry,
- * QDBM_OFFSET + QDBM_TABLE_LEN-1.
- * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
- */
-#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
-
-static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
-/* qdBm: 	+0 	+1 	+2 	+3 	+4 	+5 	+6 	+7 */
-/* 153: */      6683,	7079,	7499,	7943,	8414,	8913,	9441,	10000,
-/* 161: */      10593,	11220,	11885,	12589,	13335,	14125,	14962,	15849,
-/* 169: */      16788,	17783,	18836,	19953,	21135,	22387,	23714,	25119,
-/* 177: */      26607,	28184,	29854,	31623,	33497,	35481,	37584,	39811,
-/* 185: */      42170,	44668,	47315,	50119,	53088,	56234,	59566,	63096
-};
-
-uint16
-bcm_qdbm_to_mw(uint8 qdbm)
-{
-	uint factor = 1;
-	int idx = qdbm - QDBM_OFFSET;
-
-	if (idx >= QDBM_TABLE_LEN) {
-		/* clamp to max uint16 mW value */
-		return 0xFFFF;
-	}
-
-	/* scale the qdBm index up to the range of the table 0-40
-	 * where an offset of 40 qdBm equals a factor of 10 mW.
-	 */
-	while (idx < 0) {
-		idx += 40;
-		factor *= 10;
-	}
-
-	/* return the mW value scaled down to the correct factor of 10,
-	 * adding in factor/2 to get proper rounding.
-	 */
-	return ((nqdBm_to_mW_map[idx] + factor/2) / factor);
-}
-
-uint8
-bcm_mw_to_qdbm(uint16 mw)
-{
-	uint8 qdbm;
-	int offset;
-	uint mw_uint = mw;
-	uint boundary;
-
-	/* handle boundary case */
-	if (mw_uint <= 1)
-		return 0;
-
-	offset = QDBM_OFFSET;
-
-	/* move mw into the range of the table */
-	while (mw_uint < QDBM_TABLE_LOW_BOUND) {
-		mw_uint *= 10;
-		offset -= 40;
-	}
-
-	for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
-		boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] -
-		                                    nqdBm_to_mW_map[qdbm])/2;
-		if (mw_uint < boundary) break;
-	}
-
-	qdbm += (uint8)offset;
-
-	return (qdbm);
-}
-
-
-uint
-bcm_bitcount(uint8 *bitmap, uint length)
-{
-	uint bitcount = 0, i;
-	uint8 tmp;
-	for (i = 0; i < length; i++) {
-		tmp = bitmap[i];
-		while (tmp) {
-			bitcount++;
-			tmp &= (tmp - 1);
-		}
-	}
-	return bitcount;
-}
-
-#if defined(BCMDRIVER) || defined(WL_UNITTEST)
-
-/* triggers bcm_bprintf to print to kernel log */
-bool bcm_bprintf_bypass = FALSE;
-
-/* Initialization of bcmstrbuf structure */
-void
-bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
-{
-	b->origsize = b->size = size;
-	b->origbuf = b->buf = buf;
-}
-
-/* Buffer sprintf wrapper to guard against buffer overflow */
-int
-bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
-{
-	va_list ap;
-	int r;
-
-	va_start(ap, fmt);
-
-	r = vsnprintf(b->buf, b->size, fmt, ap);
-	if (bcm_bprintf_bypass == TRUE) {
-		printf(b->buf);
-		goto exit;
-	}
-
-	/* Non Ansi C99 compliant returns -1,
-	 * Ansi compliant return r >= b->size,
-	 * bcmstdlib returns 0, handle all
-	 */
-	/* r == 0 is also the case when strlen(fmt) is zero.
-	 * typically the case when "" is passed as argument.
-	 */
-	if ((r == -1) || (r >= (int)b->size)) {
-		b->size = 0;
-	} else {
-		b->size -= r;
-		b->buf += r;
-	}
-
-exit:
-	va_end(ap);
-
-	return r;
-}
-
-void
-bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, const uint8 *buf, int len)
-{
-	int i;
-
-	if (msg != NULL && msg[0] != '\0')
-		bcm_bprintf(b, "%s", msg);
-	for (i = 0; i < len; i ++)
-		bcm_bprintf(b, "%02X", buf[i]);
-	if (newline)
-		bcm_bprintf(b, "\n");
-}
-
-void
-bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount)
-{
-	int i;
-
-	for (i = 0; i < num_bytes; i++) {
-		num[i] += amount;
-		if (num[i] >= amount)
-			break;
-		amount = 1;
-	}
-}
-
-int
-bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes)
-{
-	int i;
-
-	for (i = nbytes - 1; i >= 0; i--) {
-		if (arg1[i] != arg2[i])
-			return (arg1[i] - arg2[i]);
-	}
-	return 0;
-}
-
-void
-bcm_print_bytes(const char *name, const uchar *data, int len)
-{
-	int i;
-	int per_line = 0;
-
-	printf("%s: %d \n", name ? name : "", len);
-	for (i = 0; i < len; i++) {
-		printf("%02x ", *data++);
-		per_line++;
-		if (per_line == 16) {
-			per_line = 0;
-			printf("\n");
-		}
-	}
-	printf("\n");
-}
-
-/* Look for vendor-specific IE with specified OUI and optional type */
-bcm_tlv_t *
-bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len)
-{
-	bcm_tlv_t *ie;
-	uint8 ie_len;
-
-	ie = (bcm_tlv_t*)tlvs;
-
-	/* make sure we are looking at a valid IE */
-	if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) {
-		return NULL;
-	}
-
-	/* Walk through the IEs looking for an OUI match */
-	do {
-		ie_len = ie->len;
-		if ((ie->id == DOT11_MNG_PROPR_ID) &&
-		    (ie_len >= (DOT11_OUI_LEN + type_len)) &&
-		    !bcmp(ie->data, voui, DOT11_OUI_LEN))
-		{
-			/* compare optional type */
-			if (type_len == 0 ||
-			    !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) {
-				return (ie);		/* a match */
-			}
-		}
-	} while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL);
-
-	return NULL;
-}
-
-#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
-	defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
-#define SSID_FMT_BUF_LEN	((4 * DOT11_MAX_SSID_LEN) + 1)
-
-int
-bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len)
-{
-	uint i, c;
-	char *p = buf;
-	char *endp = buf + SSID_FMT_BUF_LEN;
-
-	if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN;
-
-	for (i = 0; i < ssid_len; i++) {
-		c = (uint)ssid[i];
-		if (c == '\\') {
-			*p++ = '\\';
-			*p++ = '\\';
-		} else if (bcm_isprint((uchar)c)) {
-			*p++ = (char)c;
-		} else {
-			p += snprintf(p, (endp - p), "\\x%02X", c);
-		}
-	}
-	*p = '\0';
-	ASSERT(p < endp);
-
-	return (int)(p - buf);
-}
-#endif 
-
-#endif /* BCMDRIVER || WL_UNITTEST */
-
-/*
- * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
- * also accepts nvram files which are already in the format of <var1>=<value>\0\<var2>=<value2>\0
- * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs.
- * Shortens buffer as needed and pads with NULs.  End of buffer is marked by two NULs.
-*/
-
-unsigned int
-process_nvram_vars(char *varbuf, unsigned int len)
-{
-	char *dp;
-	bool findNewline;
-	int column;
-	unsigned int buf_len, n;
-	unsigned int pad = 0;
-
-	dp = varbuf;
-
-	findNewline = FALSE;
-	column = 0;
-
-	for (n = 0; n < len; n++) {
-		if (varbuf[n] == '\r')
-			continue;
-		if (findNewline && varbuf[n] != '\n')
-			continue;
-		findNewline = FALSE;
-		if (varbuf[n] == '#') {
-			findNewline = TRUE;
-			continue;
-		}
-		if (varbuf[n] == '\n') {
-			if (column == 0)
-				continue;
-			*dp++ = 0;
-			column = 0;
-			continue;
-		}
-		*dp++ = varbuf[n];
-		column++;
-	}
-	buf_len = (unsigned int)(dp - varbuf);
-	if (buf_len % 4) {
-		pad = 4 - buf_len % 4;
-		if (pad && (buf_len + pad <= len)) {
-			buf_len += pad;
-		}
-	}
-
-	while (dp < varbuf + n)
-		*dp++ = 0;
-
-	return buf_len;
-}
-
-/* calculate a * b + c */
-void
-bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c)
-{
-#define FORMALIZE(var) {cc += (var & 0x80000000) ? 1 : 0; var &= 0x7fffffff;}
-	uint32 r1, r0;
-	uint32 a1, a0, b1, b0, t, cc = 0;
-
-	a1 = a >> 16;
-	a0 = a & 0xffff;
-	b1 = b >> 16;
-	b0 = b & 0xffff;
-
-	r0 = a0 * b0;
-	FORMALIZE(r0);
-
-	t = (a1 * b0) << 16;
-	FORMALIZE(t);
-
-	r0 += t;
-	FORMALIZE(r0);
-
-	t = (a0 * b1) << 16;
-	FORMALIZE(t);
-
-	r0 += t;
-	FORMALIZE(r0);
-
-	FORMALIZE(c);
-
-	r0 += c;
-	FORMALIZE(r0);
-
-	r0 |= (cc % 2) ? 0x80000000 : 0;
-	r1 = a1 * b1 + ((a1 * b0) >> 16) + ((b1 * a0) >> 16) + (cc / 2);
-
-	*r_high = r1;
-	*r_low = r0;
-}
-
-/* calculate a / b */
-void
-bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
-{
-	uint32 a1 = a_high, a0 = a_low, r0 = 0;
-
-	if (b < 2)
-		return;
-
-	while (a1 != 0) {
-		r0 += (0xffffffff / b) * a1;
-		bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0);
-	}
-
-	r0 += a0 / b;
-	*r = r0;
-}
-
-#ifndef setbit /* As in the header file */
-#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
-/* Set bit in byte array. */
-void
-setbit(void *array, uint bit)
-{
-	((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY);
-}
-
-/* Clear bit in byte array. */
-void
-clrbit(void *array, uint bit)
-{
-	((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY));
-}
-
-/* Test if bit is set in byte array. */
-bool
-isset(const void *array, uint bit)
-{
-	return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY)));
-}
-
-/* Test if bit is clear in byte array. */
-bool
-isclr(const void *array, uint bit)
-{
-	return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0);
-}
-#endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */
-#endif /* setbit */
-
-void
-set_bitrange(void *array, uint start, uint end, uint maxbit)
-{
-	uint startbyte = start/NBBY;
-	uint endbyte = end/NBBY;
-	uint i, startbytelastbit, endbytestartbit;
-
-	if (end >= start) {
-		if (endbyte - startbyte > 1)
-		{
-			startbytelastbit = (startbyte+1)*NBBY - 1;
-			endbytestartbit = endbyte*NBBY;
-			for (i = startbyte+1; i < endbyte; i++)
-				((uint8 *)array)[i] = 0xFF;
-			for (i = start; i <= startbytelastbit; i++)
-				setbit(array, i);
-			for (i = endbytestartbit; i <= end; i++)
-				setbit(array, i);
-		} else {
-			for (i = start; i <= end; i++)
-				setbit(array, i);
-		}
-	}
-	else {
-		set_bitrange(array, start, maxbit, maxbit);
-		set_bitrange(array, 0, end, maxbit);
-	}
-}
-
-void
-bcm_bitprint32(const uint32 u32arg)
-{
-	int i;
-	for (i = NBITS(uint32) - 1; i >= 0; i--) {
-		isbitset(u32arg, i) ? printf("1") : printf("0");
-		if ((i % NBBY) == 0) printf(" ");
-	}
-	printf("\n");
-}
-
-/* calculate checksum for ip header, tcp / udp header / data */
-uint16
-bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum)
-{
-	while (len > 1) {
-		sum += (buf[0] << 8) | buf[1];
-		buf += 2;
-		len -= 2;
-	}
-
-	if (len > 0) {
-		sum += (*buf) << 8;
-	}
-
-	while (sum >> 16) {
-		sum = (sum & 0xffff) + (sum >> 16);
-	}
-
-	return ((uint16)~sum);
-}
-#if defined(BCMDRIVER) && !defined(_CFEZ_)
-/*
- * Hierarchical Multiword bitmap based small id allocator.
- *
- * Multilevel hierarchy bitmap. (maximum 2 levels)
- * First hierarchy uses a multiword bitmap to identify 32bit words in the
- * second hierarchy that have at least a single bit set. Each bit in a word of
- * the second hierarchy represents a unique ID that may be allocated.
- *
- * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed.
- * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word
- * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs.
- * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non
- *                       non-zero bitmap word carrying at least one free ID.
- * BCM_MWBMAP_SHIFT_OP:  Used in MOD, DIV and MUL operations.
- * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID
- *
- * Design Notes:
- * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many
- * bits are computed each time on allocation and deallocation, requiring 4
- * array indexed access and 3 arithmetic operations. When not defined, a runtime
- * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed.
- * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation.
- * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may
- * be used by defining BCM_MWBMAP_USE_CNTSETBITS.
- *
- * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array
- * size is fixed. No intention to support larger than 4K indice allocation. ID
- * allocators for ranges smaller than 4K will have a wastage of only 12Bytes
- * with savings in not having to use an indirect access, had it been dynamically
- * allocated.
- */
-#define BCM_MWBMAP_ITEMS_MAX    (64 * 1024)  /* May increase to 64K */
-
-#define BCM_MWBMAP_BITS_WORD    (NBITS(uint32))
-#define BCM_MWBMAP_WORDS_MAX    (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD)
-#define BCM_MWBMAP_WDMAP_MAX    (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD)
-#define BCM_MWBMAP_SHIFT_OP     (5)
-#define BCM_MWBMAP_MODOP(ix)    ((ix) & (BCM_MWBMAP_BITS_WORD - 1))
-#define BCM_MWBMAP_DIVOP(ix)    ((ix) >> BCM_MWBMAP_SHIFT_OP)
-#define BCM_MWBMAP_MULOP(ix)    ((ix) << BCM_MWBMAP_SHIFT_OP)
-
-/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */
-#define BCM_MWBMAP_PTR(hdl)		((struct bcm_mwbmap *)(hdl))
-#define BCM_MWBMAP_HDL(ptr)		((void *)(ptr))
-
-#if defined(BCM_MWBMAP_DEBUG)
-#define BCM_MWBMAP_AUDIT(mwb) \
-	do { \
-		ASSERT((mwb != NULL) && \
-		       (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \
-		bcm_mwbmap_audit(mwb); \
-	} while (0)
-#define MWBMAP_ASSERT(exp)		ASSERT(exp)
-#define MWBMAP_DBG(x)           printf x
-#else   /* !BCM_MWBMAP_DEBUG */
-#define BCM_MWBMAP_AUDIT(mwb)   do {} while (0)
-#define MWBMAP_ASSERT(exp)		do {} while (0)
-#define MWBMAP_DBG(x)
-#endif  /* !BCM_MWBMAP_DEBUG */
-
-
-typedef struct bcm_mwbmap {     /* Hierarchical multiword bitmap allocator    */
-	uint16 wmaps;               /* Total number of words in free wd bitmap    */
-	uint16 imaps;               /* Total number of words in free id bitmap    */
-	int32  ifree;               /* Count of free indices. Used only in audits */
-	uint16 total;               /* Total indices managed by multiword bitmap  */
-
-	void * magic;               /* Audit handle parameter from user           */
-
-	uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of            */
-#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
-	int8   wd_count[BCM_MWBMAP_WORDS_MAX];  /* free id running count, 1st lvl */
-#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
-
-	uint32 id_bitmap[0];        /* Second level bitmap                        */
-} bcm_mwbmap_t;
-
-/* Incarnate a hierarchical multiword bitmap based small index allocator. */
-struct bcm_mwbmap *
-bcm_mwbmap_init(osl_t *osh, uint32 items_max)
-{
-	struct bcm_mwbmap * mwbmap_p;
-	uint32 wordix, size, words, extra;
-
-	/* Implementation Constraint: Uses 32bit word bitmap */
-	MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U);
-	MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U);
-	MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX));
-	MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U);
-
-	ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX);
-
-	/* Determine the number of words needed in the multiword bitmap */
-	extra = BCM_MWBMAP_MODOP(items_max);
-	words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U);
-
-	/* Allocate runtime state of multiword bitmap */
-	/* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */
-	size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words);
-	mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size);
-	if (mwbmap_p == (bcm_mwbmap_t *)NULL) {
-		ASSERT(0);
-		goto error1;
-	}
-	memset(mwbmap_p, 0, size);
-
-	/* Initialize runtime multiword bitmap state */
-	mwbmap_p->imaps = (uint16)words;
-	mwbmap_p->ifree = (int32)items_max;
-	mwbmap_p->total = (uint16)items_max;
-
-	/* Setup magic, for use in audit of handle */
-	mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p);
-
-	/* Setup the second level bitmap of free indices */
-	/* Mark all indices as available */
-	for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) {
-		mwbmap_p->id_bitmap[wordix] = (uint32)(~0U);
-#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
-		mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD;
-#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
-	}
-
-	/* Ensure that extra indices are tagged as un-available */
-	if (extra) { /* fixup the free ids in last bitmap and wd_count */
-		uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1];
-		*bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
-#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
-		mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */
-#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
-	}
-
-	/* Setup the first level bitmap hierarchy */
-	extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps);
-	words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U);
-
-	mwbmap_p->wmaps = (uint16)words;
-
-	for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++)
-		mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U);
-	if (extra) {
-		uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1];
-		*bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
-	}
-
-	return mwbmap_p;
-
-error1:
-	return BCM_MWBMAP_INVALID_HDL;
-}
-
-/* Release resources used by multiword bitmap based small index allocator. */
-void
-bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl)
-{
-	bcm_mwbmap_t * mwbmap_p;
-
-	BCM_MWBMAP_AUDIT(mwbmap_hdl);
-	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
-
-	MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap)
-	                     + (sizeof(uint32) * mwbmap_p->imaps));
-	return;
-}
-
-/* Allocate a unique small index using a multiword bitmap index allocator.    */
-uint32 BCMFASTPATH
-bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl)
-{
-	bcm_mwbmap_t * mwbmap_p;
-	uint32 wordix, bitmap;
-
-	BCM_MWBMAP_AUDIT(mwbmap_hdl);
-	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
-
-	/* Start with the first hierarchy */
-	for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) {
-
-		bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */
-
-		if (bitmap != 0U) {
-
-			uint32 count, bitix, *bitmap_p;
-
-			bitmap_p = &mwbmap_p->wd_bitmap[wordix];
-
-			/* clear all except trailing 1 */
-			bitmap   = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
-			MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
-			              bcm_count_leading_zeros(bitmap));
-			bitix    = (BCM_MWBMAP_BITS_WORD - 1)
-			         - bcm_count_leading_zeros(bitmap); /* use asm clz */
-			wordix   = BCM_MWBMAP_MULOP(wordix) + bitix;
-
-			/* Clear bit if wd count is 0, without conditional branch */
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
-			count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1;
-#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
-			mwbmap_p->wd_count[wordix]--;
-			count = mwbmap_p->wd_count[wordix];
-			MWBMAP_ASSERT(count ==
-			              (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1));
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
-			MWBMAP_ASSERT(count >= 0);
-
-			/* clear wd_bitmap bit if id_map count is 0 */
-			bitmap = (count == 0) << bitix;
-
-			MWBMAP_DBG((
-			    "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
-			    bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count));
-
-			*bitmap_p ^= bitmap;
-
-			/* Use bitix in the second hierarchy */
-			bitmap_p = &mwbmap_p->id_bitmap[wordix];
-
-			bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */
-			MWBMAP_ASSERT(bitmap != 0U);
-
-			/* clear all except trailing 1 */
-			bitmap   = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
-			MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
-			              bcm_count_leading_zeros(bitmap));
-			bitix    = BCM_MWBMAP_MULOP(wordix)
-			         + (BCM_MWBMAP_BITS_WORD - 1)
-			         - bcm_count_leading_zeros(bitmap); /* use asm clz */
-
-			mwbmap_p->ifree--; /* decrement system wide free count */
-			MWBMAP_ASSERT(mwbmap_p->ifree >= 0);
-
-			MWBMAP_DBG((
-			    "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d",
-			    bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
-			    mwbmap_p->ifree));
-
-			*bitmap_p ^= bitmap; /* mark as allocated = 1b0 */
-
-			return bitix;
-		}
-	}
-
-	ASSERT(mwbmap_p->ifree == 0);
-
-	return BCM_MWBMAP_INVALID_IDX;
-}
-
-/* Force an index at a specified position to be in use */
-void
-bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
-{
-	bcm_mwbmap_t * mwbmap_p;
-	uint32 count, wordix, bitmap, *bitmap_p;
-
-	BCM_MWBMAP_AUDIT(mwbmap_hdl);
-	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
-
-	ASSERT(bitix < mwbmap_p->total);
-
-	/* Start with second hierarchy */
-	wordix   = BCM_MWBMAP_DIVOP(bitix);
-	bitmap   = (uint32)(1U << BCM_MWBMAP_MODOP(bitix));
-	bitmap_p = &mwbmap_p->id_bitmap[wordix];
-
-	ASSERT((*bitmap_p & bitmap) == bitmap);
-
-	mwbmap_p->ifree--; /* update free count */
-	ASSERT(mwbmap_p->ifree >= 0);
-
-	MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d",
-	           bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
-	           mwbmap_p->ifree));
-
-	*bitmap_p ^= bitmap; /* mark as in use */
-
-	/* Update first hierarchy */
-	bitix    = wordix;
-
-	wordix   = BCM_MWBMAP_DIVOP(bitix);
-	bitmap_p = &mwbmap_p->wd_bitmap[wordix];
-
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
-	count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
-#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
-	mwbmap_p->wd_count[bitix]--;
-	count = mwbmap_p->wd_count[bitix];
-	MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
-	MWBMAP_ASSERT(count >= 0);
-
-	bitmap   = (count == 0) << BCM_MWBMAP_MODOP(bitix);
-
-	MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
-	           BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap,
-	           (*bitmap_p) ^ bitmap, count));
-
-	*bitmap_p ^= bitmap; /* mark as in use */
-
-	return;
-}
-
-/* Free a previously allocated index back into the multiword bitmap allocator */
-void BCMFASTPATH
-bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
-{
-	bcm_mwbmap_t * mwbmap_p;
-	uint32 wordix, bitmap, *bitmap_p;
-
-	BCM_MWBMAP_AUDIT(mwbmap_hdl);
-	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
-
-	ASSERT(bitix < mwbmap_p->total);
-
-	/* Start with second level hierarchy */
-	wordix   = BCM_MWBMAP_DIVOP(bitix);
-	bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
-	bitmap_p = &mwbmap_p->id_bitmap[wordix];
-
-	ASSERT((*bitmap_p & bitmap) == 0U);	/* ASSERT not a double free */
-
-	mwbmap_p->ifree++; /* update free count */
-	ASSERT(mwbmap_p->ifree <= mwbmap_p->total);
-
-	MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d",
-	           bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap,
-	           mwbmap_p->ifree));
-
-	*bitmap_p |= bitmap; /* mark as available */
-
-	/* Now update first level hierarchy */
-
-	bitix    = wordix;
-
-	wordix   = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */
-	bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
-	bitmap_p = &mwbmap_p->wd_bitmap[wordix];
-
-#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
-	mwbmap_p->wd_count[bitix]++;
-#endif
-
-#if defined(BCM_MWBMAP_DEBUG)
-	{
-		uint32 count;
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
-		count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
-#else  /*  ! BCM_MWBMAP_USE_CNTSETBITS */
-		count = mwbmap_p->wd_count[bitix];
-		MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
-#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
-
-		MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD);
-
-		MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d",
-		            bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count));
-	}
-#endif /* BCM_MWBMAP_DEBUG */
-
-	*bitmap_p |= bitmap;
-
-	return;
-}
-
-/* Fetch the toal number of free indices in the multiword bitmap allocator */
-uint32
-bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl)
-{
-	bcm_mwbmap_t * mwbmap_p;
-
-	BCM_MWBMAP_AUDIT(mwbmap_hdl);
-	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
-
-	ASSERT(mwbmap_p->ifree >= 0);
-
-	return mwbmap_p->ifree;
-}
-
-/* Determine whether an index is inuse or free */
-bool
-bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
-{
-	bcm_mwbmap_t * mwbmap_p;
-	uint32 wordix, bitmap;
-
-	BCM_MWBMAP_AUDIT(mwbmap_hdl);
-	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
-
-	ASSERT(bitix < mwbmap_p->total);
-
-	wordix   = BCM_MWBMAP_DIVOP(bitix);
-	bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
-
-	return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U);
-}
-
-/* Debug dump a multiword bitmap allocator */
-void
-bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl)
-{
-	uint32 ix, count;
-	bcm_mwbmap_t * mwbmap_p;
-
-	BCM_MWBMAP_AUDIT(mwbmap_hdl);
-	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
-
-	printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n", mwbmap_p,
-	       mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total);
-	for (ix = 0U; ix < mwbmap_p->wmaps; ix++) {
-		printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]);
-		bcm_bitprint32(mwbmap_p->wd_bitmap[ix]);
-		printf("\n");
-	}
-	for (ix = 0U; ix < mwbmap_p->imaps; ix++) {
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
-		count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]);
-#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
-		count = mwbmap_p->wd_count[ix];
-		MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix]));
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
-		printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count);
-		bcm_bitprint32(mwbmap_p->id_bitmap[ix]);
-		printf("\n");
-	}
-
-	return;
-}
-
-/* Audit a hierarchical multiword bitmap */
-void
-bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl)
-{
-	bcm_mwbmap_t * mwbmap_p;
-	uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p;
-
-	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
-
-	for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) {
-
-		bitmap_p = &mwbmap_p->wd_bitmap[wordix];
-
-		for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) {
-			if ((*bitmap_p) & (1 << bitix)) {
-				idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix;
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
-				count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]);
-#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
-				count = mwbmap_p->wd_count[idmap_ix];
-				ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]));
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
-				ASSERT(count != 0U);
-				free_cnt += count;
-			}
-		}
-	}
-
-	ASSERT((int)free_cnt == mwbmap_p->ifree);
-}
-/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */
-
-/* Simple 16bit Id allocator using a stack implementation. */
-typedef struct id16_map {
-	uint32  failures;  /* count of failures */
-	void    *dbg;      /* debug placeholder */
-	uint16  total;     /* total number of ids managed by allocator */
-	uint16  start;     /* start value of 16bit ids to be managed */
-	int     stack_idx; /* index into stack of available ids */
-	uint16  stack[0];  /* stack of 16 bit ids */
-} id16_map_t;
-
-#define ID16_MAP_SZ(items)      (sizeof(id16_map_t) + \
-	                             (sizeof(uint16) * (items)))
-
-#if defined(BCM_DBG)
-
-/* Uncomment BCM_DBG_ID16 to debug double free */
-/* #define BCM_DBG_ID16 */
-
-typedef struct id16_map_dbg {
-	uint16  total;
-	bool    avail[0];
-} id16_map_dbg_t;
-#define ID16_MAP_DBG_SZ(items)  (sizeof(id16_map_dbg_t) + \
-	                             (sizeof(bool) * (items)))
-#define ID16_MAP_MSG(x)         print x
-#else
-#define ID16_MAP_MSG(x)
-#endif /* BCM_DBG */
-
-void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */
-id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16)
-{
-	uint16 idx, val16;
-	id16_map_t * id16_map;
-
-	ASSERT(total_ids > 0);
-
-	/* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
-	 * with random values.
-	 */
-	ASSERT((start_val16 == ID16_UNDEFINED) ||
-	       (start_val16 + total_ids) < ID16_INVALID);
-
-	id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids));
-	if (id16_map == NULL) {
-		return NULL;
-	}
-
-	id16_map->total = total_ids;
-	id16_map->start = start_val16;
-	id16_map->failures = 0;
-	id16_map->dbg = NULL;
-
-	/*
-	 * Populate stack with 16bit id values, commencing with start_val16.
-	 * if start_val16 is ID16_UNDEFINED, then do not populate the id16 map.
-	 */
-	id16_map->stack_idx = -1;
-
-	if (id16_map->start != ID16_UNDEFINED) {
-		val16 = start_val16;
-
-		for (idx = 0; idx < total_ids; idx++, val16++) {
-			id16_map->stack_idx = idx;
-			id16_map->stack[id16_map->stack_idx] = val16;
-		}
-	}
-
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
-	if (id16_map->start != ID16_UNDEFINED) {
-		id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids));
-
-		if (id16_map->dbg) {
-			id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
-
-			id16_map_dbg->total = total_ids;
-			for (idx = 0; idx < total_ids; idx++) {
-				id16_map_dbg->avail[idx] = TRUE;
-			}
-		}
-	}
-#endif /* BCM_DBG && BCM_DBG_ID16 */
-
-	return (void *)id16_map;
-}
-
-void * /* Destruct an id16 allocator instance */
-id16_map_fini(osl_t *osh, void * id16_map_hndl)
-{
-	uint16 total_ids;
-	id16_map_t * id16_map;
-
-	if (id16_map_hndl == NULL)
-		return NULL;
-
-	id16_map = (id16_map_t *)id16_map_hndl;
-
-	total_ids = id16_map->total;
-	ASSERT(total_ids > 0);
-
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
-	if (id16_map->dbg) {
-		MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids));
-		id16_map->dbg = NULL;
-	}
-#endif /* BCM_DBG && BCM_DBG_ID16 */
-
-	id16_map->total = 0;
-	MFREE(osh, id16_map, ID16_MAP_SZ(total_ids));
-
-	return NULL;
-}
-
-void
-id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16)
-{
-	uint16 idx, val16;
-	id16_map_t * id16_map;
-
-	ASSERT(total_ids > 0);
-	/* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
-	 * with random values.
-	 */
-	ASSERT((start_val16 == ID16_UNDEFINED) ||
-	       (start_val16 + total_ids) < ID16_INVALID);
-
-	id16_map = (id16_map_t *)id16_map_hndl;
-	if (id16_map == NULL) {
-		return;
-	}
-
-	id16_map->total = total_ids;
-	id16_map->start = start_val16;
-	id16_map->failures = 0;
-
-	/* Populate stack with 16bit id values, commencing with start_val16 */
-	id16_map->stack_idx = -1;
-
-	if (id16_map->start != ID16_UNDEFINED) {
-		val16 = start_val16;
-
-		for (idx = 0; idx < total_ids; idx++, val16++) {
-			id16_map->stack_idx = idx;
-			id16_map->stack[id16_map->stack_idx] = val16;
-		}
-	}
-
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
-	if (id16_map->start != ID16_UNDEFINED) {
-		if (id16_map->dbg) {
-			id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
-
-			id16_map_dbg->total = total_ids;
-			for (idx = 0; idx < total_ids; idx++) {
-				id16_map_dbg->avail[idx] = TRUE;
-			}
-		}
-	}
-#endif /* BCM_DBG && BCM_DBG_ID16 */
-}
-
-uint16 BCMFASTPATH /* Allocate a unique 16bit id */
-id16_map_alloc(void * id16_map_hndl)
-{
-	uint16 val16;
-	id16_map_t * id16_map;
-
-	ASSERT(id16_map_hndl != NULL);
-
-	id16_map = (id16_map_t *)id16_map_hndl;
-
-	ASSERT(id16_map->total > 0);
-
-	if (id16_map->stack_idx < 0) {
-		id16_map->failures++;
-		return ID16_INVALID;
-	}
-
-	val16 = id16_map->stack[id16_map->stack_idx];
-	id16_map->stack_idx--;
-
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
-	ASSERT((id16_map->start == ID16_UNDEFINED) ||
-	       (val16 < (id16_map->start + id16_map->total)));
-
-	if (id16_map->dbg) { /* Validate val16 */
-		id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
-
-		ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE);
-		id16_map_dbg->avail[val16 - id16_map->start] = FALSE;
-	}
-#endif /* BCM_DBG && BCM_DBG_ID16 */
-
-	return val16;
-}
-
-
-void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */
-id16_map_free(void * id16_map_hndl, uint16 val16)
-{
-	id16_map_t * id16_map;
-
-	ASSERT(id16_map_hndl != NULL);
-
-	id16_map = (id16_map_t *)id16_map_hndl;
-
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
-	ASSERT((id16_map->start == ID16_UNDEFINED) ||
-	       (val16 < (id16_map->start + id16_map->total)));
-
-	if (id16_map->dbg) { /* Validate val16 */
-		id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
-
-		ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE);
-		id16_map_dbg->avail[val16 - id16_map->start] = TRUE;
-	}
-#endif /* BCM_DBG && BCM_DBG_ID16 */
-
-	id16_map->stack_idx++;
-	id16_map->stack[id16_map->stack_idx] = val16;
-}
-
-uint32 /* Returns number of failures to allocate an unique id16 */
-id16_map_failures(void * id16_map_hndl)
-{
-	ASSERT(id16_map_hndl != NULL);
-	return ((id16_map_t *)id16_map_hndl)->failures;
-}
-
-bool
-id16_map_audit(void * id16_map_hndl)
-{
-	int idx;
-	int insane = 0;
-	id16_map_t * id16_map;
-
-	ASSERT(id16_map_hndl != NULL);
-
-	id16_map = (id16_map_t *)id16_map_hndl;
-
-	ASSERT(id16_map->stack_idx >= -1);
-	ASSERT(id16_map->stack_idx < (int)id16_map->total);
-
-	if (id16_map->start == ID16_UNDEFINED)
-		goto done;
-
-	for (idx = 0; idx <= id16_map->stack_idx; idx++) {
-		ASSERT(id16_map->stack[idx] >= id16_map->start);
-		ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total));
-
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
-		if (id16_map->dbg) {
-			uint16 val16 = id16_map->stack[idx];
-			if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) {
-				insane |= 1;
-				ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n",
-					id16_map_hndl, idx, val16));
-			}
-		}
-#endif /* BCM_DBG && BCM_DBG_ID16 */
-	}
-
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
-	if (id16_map->dbg) {
-		uint16 avail = 0; /* Audit available ids counts */
-		for (idx = 0; idx < id16_map_dbg->total; idx++) {
-			if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE)
-				avail++;
-		}
-		if (avail && (avail != (id16_map->stack_idx + 1))) {
-			insane |= 1;
-			ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n",
-				id16_map_hndl, avail, id16_map->stack_idx));
-		}
-	}
-#endif /* BCM_DBG && BCM_DBG_ID16 */
-
-done:
-	/* invoke any other system audits */
-	return (!!insane);
-}
-/* END: Simple id16 allocator */
-
-
-#endif 
-
-/* calculate a >> b; and returns only lower 32 bits */
-void
-bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
-{
-	uint32 a1 = a_high, a0 = a_low, r0 = 0;
-
-	if (b == 0) {
-		r0 = a_low;
-		*r = r0;
-		return;
-	}
-
-	if (b < 32) {
-		a0 = a0 >> b;
-		a1 = a1 & ((1 << b) - 1);
-		a1 = a1 << (32 - b);
-		r0 = a0 | a1;
-		*r = r0;
-		return;
-	} else {
-		r0 = a1 >> (b - 32);
-		*r = r0;
-		return;
-	}
-
-}
-
-/* calculate a + b where a is a 64 bit number and b is a 32 bit number */
-void
-bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset)
-{
-	uint32 r1_lo = *r_lo;
-	(*r_lo) += offset;
-	if (*r_lo < r1_lo)
-		(*r_hi) ++;
-}
-
-/* calculate a - b where a is a 64 bit number and b is a 32 bit number */
-void
-bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset)
-{
-	uint32 r1_lo = *r_lo;
-	(*r_lo) -= offset;
-	if (*r_lo > r1_lo)
-		(*r_hi) --;
-}
-
-#ifdef DEBUG_COUNTER
-#if (OSL_SYSUPTIME_SUPPORT == TRUE)
-void counter_printlog(counter_tbl_t *ctr_tbl)
-{
-	uint32 now;
-
-	if (!ctr_tbl->enabled)
-		return;
-
-	now = OSL_SYSUPTIME();
-
-	if (now - ctr_tbl->prev_log_print > ctr_tbl->log_print_interval) {
-		uint8 i = 0;
-		printf("counter_print(%s %d):", ctr_tbl->name, now - ctr_tbl->prev_log_print);
-
-		for (i = 0; i < ctr_tbl->needed_cnt; i++) {
-			printf(" %u", ctr_tbl->cnt[i]);
-		}
-		printf("\n");
-
-		ctr_tbl->prev_log_print = now;
-		bzero(ctr_tbl->cnt, CNTR_TBL_MAX * sizeof(uint));
-	}
-}
-#else
-/* OSL_SYSUPTIME is not supported so no way to get time */
-#define counter_printlog(a) do {} while (0)
-#endif /* OSL_SYSUPTIME_SUPPORT == TRUE */
-#endif /* DEBUG_COUNTER */
-
-#if defined(BCMDRIVER) && !defined(_CFEZ_)
-void
-dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size)
-{
-	uint32 mem_size;
-	mem_size = sizeof(dll_pool_t) + (elems_max * elem_size);
-	if (pool)
-		MFREE(osh, pool, mem_size);
-}
-dll_pool_t *
-dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size)
-{
-	uint32 mem_size, i;
-	dll_pool_t * dll_pool_p;
-	dll_t * elem_p;
-
-	ASSERT(elem_size > sizeof(dll_t));
-
-	mem_size = sizeof(dll_pool_t) + (elems_max * elem_size);
-
-	if ((dll_pool_p = (dll_pool_t *)MALLOCZ(osh, mem_size)) == NULL) {
-		printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n",
-			elems_max, elem_size);
-		ASSERT(0);
-		return dll_pool_p;
-	}
-
-	dll_init(&dll_pool_p->free_list);
-	dll_pool_p->elems_max = elems_max;
-	dll_pool_p->elem_size = elem_size;
-
-	elem_p = dll_pool_p->elements;
-	for (i = 0; i < elems_max; i++) {
-		dll_append(&dll_pool_p->free_list, elem_p);
-		elem_p = (dll_t *)((uintptr)elem_p + elem_size);
-	}
-
-	dll_pool_p->free_count = elems_max;
-
-	return dll_pool_p;
-}
-
-
-void *
-dll_pool_alloc(dll_pool_t * dll_pool_p)
-{
-	dll_t * elem_p;
-
-	if (dll_pool_p->free_count == 0) {
-		ASSERT(dll_empty(&dll_pool_p->free_list));
-		return NULL;
-	}
-
-	elem_p = dll_head_p(&dll_pool_p->free_list);
-	dll_delete(elem_p);
-	dll_pool_p->free_count -= 1;
-
-	return (void *)elem_p;
-}
-
-void
-dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p)
-{
-	dll_t * node_p = (dll_t *)elem_p;
-	dll_prepend(&dll_pool_p->free_list, node_p);
-	dll_pool_p->free_count += 1;
-}
-
-
-void
-dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p)
-{
-	dll_t * node_p = (dll_t *)elem_p;
-	dll_append(&dll_pool_p->free_list, node_p);
-	dll_pool_p->free_count += 1;
-}
-
-#endif 
diff --git a/drivers/net/wireless/bcmdhd/bcmwifi_channels.c b/drivers/net/wireless/bcmdhd/bcmwifi_channels.c
deleted file mode 100644
index be884cc..0000000
--- a/drivers/net/wireless/bcmdhd/bcmwifi_channels.c
+++ /dev/null
@@ -1,1253 +0,0 @@
-/*
- * Misc utility routines used by kernel or app-level.
- * Contents are wifi-specific, used by any kernel or app-level
- * software that might want wifi things as it grows.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmwifi_channels.c 591285 2015-10-07 11:56:29Z $
- */
-
-#include <bcm_cfg.h>
-#include <typedefs.h>
-#include <bcmutils.h>
-
-#ifdef BCMDRIVER
-#include <osl.h>
-#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
-#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#ifndef ASSERT
-#define ASSERT(exp)
-#endif
-#endif /* BCMDRIVER */
-
-#include <bcmwifi_channels.h>
-
-#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
-#include <bcmstdlib.h> 	/* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
-#endif
-
-/* Definitions for D11AC capable Chanspec type */
-
-/* Chanspec ASCII representation with 802.11ac capability:
- * [<band> 'g'] <channel> ['/'<bandwidth> [<ctl-sideband>]['/'<1st80channel>'-'<2nd80channel>]]
- *
- * <band>:
- *      (optional) 2, 3, 4, 5 for 2.4GHz, 3GHz, 4GHz, and 5GHz respectively.
- *      Default value is 2g if channel <= 14, otherwise 5g.
- * <channel>:
- *      channel number of the 5MHz, 10MHz, 20MHz channel,
- *      or primary channel of 40MHz, 80MHz, 160MHz, or 80+80MHz channel.
- * <bandwidth>:
- *      (optional) 5, 10, 20, 40, 80, 160, or 80+80. Default value is 20.
- * <primary-sideband>:
- *      (only for 2.4GHz band 40MHz) U for upper sideband primary, L for lower.
- *
- *      For 2.4GHz band 40MHz channels, the same primary channel may be the
- *      upper sideband for one 40MHz channel, and the lower sideband for an
- *      overlapping 40MHz channel.  The U/L disambiguates which 40MHz channel
- *      is being specified.
- *
- *      For 40MHz in the 5GHz band and all channel bandwidths greater than
- *      40MHz, the U/L specificaion is not allowed since the channels are
- *      non-overlapping and the primary sub-band is derived from its
- *      position in the wide bandwidth channel.
- *
- * <1st80Channel>:
- * <2nd80Channel>:
- *      Required for 80+80, otherwise not allowed.
- *      Specifies the center channel of the first and second 80MHz band.
- *
- * In its simplest form, it is a 20MHz channel number, with the implied band
- * of 2.4GHz if channel number <= 14, and 5GHz otherwise.
- *
- * To allow for backward compatibility with scripts, the old form for
- * 40MHz channels is also allowed: <channel><ctl-sideband>
- *
- * <channel>:
- *	primary channel of 40MHz, channel <= 14 is 2GHz, otherwise 5GHz
- * <ctl-sideband>:
- * 	"U" for upper, "L" for lower (or lower case "u" "l")
- *
- * 5 GHz Examples:
- *      Chanspec        BW        Center Ch  Channel Range  Primary Ch
- *      5g8             20MHz     8          -              -
- *      52              20MHz     52         -              -
- *      52/40           40MHz     54         52-56          52
- *      56/40           40MHz     54         52-56          56
- *      52/80           80MHz     58         52-64          52
- *      56/80           80MHz     58         52-64          56
- *      60/80           80MHz     58         52-64          60
- *      64/80           80MHz     58         52-64          64
- *      52/160          160MHz    50         36-64          52
- *      36/160          160MGz    50         36-64          36
- *      36/80+80/42-106 80+80MHz  42,106     36-48,100-112  36
- *
- * 2 GHz Examples:
- *      Chanspec        BW        Center Ch  Channel Range  Primary Ch
- *      2g8             20MHz     8          -              -
- *      8               20MHz     8          -              -
- *      6               20MHz     6          -              -
- *      6/40l           40MHz     8          6-10           6
- *      6l              40MHz     8          6-10           6
- *      6/40u           40MHz     4          2-6            6
- *      6u              40MHz     4          2-6            6
- */
-
-/* bandwidth ASCII string */
-static const char *wf_chspec_bw_str[] =
-{
-	"5",
-	"10",
-	"20",
-	"40",
-	"80",
-	"160",
-	"80+80",
-#ifdef WL11ULB
-	"2.5"
-#else /* WL11ULB */
-	"na"
-#endif /* WL11ULB */
-};
-
-static const uint8 wf_chspec_bw_mhz[] =
-{5, 10, 20, 40, 80, 160, 160};
-
-#define WF_NUM_BW \
-	(sizeof(wf_chspec_bw_mhz)/sizeof(uint8))
-
-/* 40MHz channels in 5GHz band */
-static const uint8 wf_5g_40m_chans[] =
-{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159};
-#define WF_NUM_5G_40M_CHANS \
-	(sizeof(wf_5g_40m_chans)/sizeof(uint8))
-
-/* 80MHz channels in 5GHz band */
-static const uint8 wf_5g_80m_chans[] =
-{42, 58, 106, 122, 138, 155};
-#define WF_NUM_5G_80M_CHANS \
-	(sizeof(wf_5g_80m_chans)/sizeof(uint8))
-
-/* 160MHz channels in 5GHz band */
-static const uint8 wf_5g_160m_chans[] =
-{50, 114};
-#define WF_NUM_5G_160M_CHANS \
-	(sizeof(wf_5g_160m_chans)/sizeof(uint8))
-
-
-/* convert bandwidth from chanspec to MHz */
-static uint
-bw_chspec_to_mhz(chanspec_t chspec)
-{
-	uint bw;
-
-	bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT;
-	return (bw >= WF_NUM_BW ? 0 : wf_chspec_bw_mhz[bw]);
-}
-
-/* bw in MHz, return the channel count from the center channel to the
- * the channel at the edge of the band
- */
-static uint8
-center_chan_to_edge(uint bw)
-{
-	/* edge channels separated by BW - 10MHz on each side
-	 * delta from cf to edge is half of that,
-	 * MHz to channel num conversion is 5MHz/channel
-	 */
-	return (uint8)(((bw - 20) / 2) / 5);
-}
-
-/* return channel number of the low edge of the band
- * given the center channel and BW
- */
-static uint8
-channel_low_edge(uint center_ch, uint bw)
-{
-	return (uint8)(center_ch - center_chan_to_edge(bw));
-}
-
-/* return side band number given center channel and control channel
- * return -1 on error
- */
-static int
-channel_to_sb(uint center_ch, uint ctl_ch, uint bw)
-{
-	uint lowest = channel_low_edge(center_ch, bw);
-	uint sb;
-
-	if ((ctl_ch - lowest) % 4) {
-		/* bad ctl channel, not mult 4 */
-		return -1;
-	}
-
-	sb = ((ctl_ch - lowest) / 4);
-
-	/* sb must be a index to a 20MHz channel in range */
-	if (sb >= (bw / 20)) {
-		/* ctl_ch must have been too high for the center_ch */
-		return -1;
-	}
-
-	return sb;
-}
-
-/* return control channel given center channel and side band */
-static uint8
-channel_to_ctl_chan(uint center_ch, uint bw, uint sb)
-{
-	return (uint8)(channel_low_edge(center_ch, bw) + sb * 4);
-}
-
-/* return index of 80MHz channel from channel number
- * return -1 on error
- */
-static int
-channel_80mhz_to_id(uint ch)
-{
-	uint i;
-	for (i = 0; i < WF_NUM_5G_80M_CHANS; i ++) {
-		if (ch == wf_5g_80m_chans[i])
-			return i;
-	}
-
-	return -1;
-}
-
-/* wrapper function for wf_chspec_ntoa. In case of an error it puts
- * the original chanspec in the output buffer, prepended with "invalid".
- * Can be directly used in print routines as it takes care of null
- */
-char *
-wf_chspec_ntoa_ex(chanspec_t chspec, char *buf)
-{
-	if (wf_chspec_ntoa(chspec, buf) == NULL)
-		snprintf(buf, CHANSPEC_STR_LEN, "invalid 0x%04x", chspec);
-	return buf;
-}
-
-/* given a chanspec and a string buffer, format the chanspec as a
- * string, and return the original pointer a.
- * Min buffer length must be CHANSPEC_STR_LEN.
- * On error return NULL
- */
-char *
-wf_chspec_ntoa(chanspec_t chspec, char *buf)
-{
-	const char *band;
-	uint ctl_chan;
-
-	if (wf_chspec_malformed(chspec))
-		return NULL;
-
-	band = "";
-
-	/* check for non-default band spec */
-	if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) ||
-	    (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL))
-		band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g";
-
-	/* ctl channel */
-	ctl_chan = wf_chspec_ctlchan(chspec);
-
-	/* bandwidth and ctl sideband */
-	if (CHSPEC_IS20(chspec)) {
-		snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan);
-	} else if (!CHSPEC_IS8080(chspec)) {
-		const char *bw;
-		const char *sb = "";
-
-		bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT];
-
-#ifdef CHANSPEC_NEW_40MHZ_FORMAT
-		/* ctl sideband string if needed for 2g 40MHz */
-		if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) {
-			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
-		}
-
-		snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb);
-#else
-		/* ctl sideband string instead of BW for 40MHz */
-		if (CHSPEC_IS40(chspec)) {
-			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
-			snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb);
-		} else {
-			snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw);
-		}
-#endif /* CHANSPEC_NEW_40MHZ_FORMAT */
-
-	} else {
-		/* 80+80 */
-		uint chan1 = (chspec & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT;
-		uint chan2 = (chspec & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT;
-
-		/* convert to channel number */
-		chan1 = (chan1 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan1] : 0;
-		chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0;
-
-		/* Outputs a max of CHANSPEC_STR_LEN chars including '\0'  */
-		snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2);
-	}
-
-	return (buf);
-}
-
-static int
-read_uint(const char **p, unsigned int *num)
-{
-	unsigned long val;
-	char *endp = NULL;
-
-	val = strtoul(*p, &endp, 10);
-	/* if endp is the initial pointer value, then a number was not read */
-	if (endp == *p)
-		return 0;
-
-	/* advance the buffer pointer to the end of the integer string */
-	*p = endp;
-	/* return the parsed integer */
-	*num = (unsigned int)val;
-
-	return 1;
-}
-
-/* given a chanspec string, convert to a chanspec.
- * On error return 0
- */
-chanspec_t
-wf_chspec_aton(const char *a)
-{
-	chanspec_t chspec;
-	uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb;
-	uint num, ctl_ch;
-	uint ch1, ch2;
-	char c, sb_ul = '\0';
-	int i;
-
-	bw = 20;
-	chspec_sb = 0;
-	chspec_ch = ch1 = ch2 = 0;
-
-	/* parse channel num or band */
-	if (!read_uint(&a, &num))
-		return 0;
-	/* if we are looking at a 'g', then the first number was a band */
-	c = tolower((int)a[0]);
-	if (c == 'g') {
-		a++; /* consume the char */
-
-		/* band must be "2" or "5" */
-		if (num == 2)
-			chspec_band = WL_CHANSPEC_BAND_2G;
-		else if (num == 5)
-			chspec_band = WL_CHANSPEC_BAND_5G;
-		else
-			return 0;
-
-		/* read the channel number */
-		if (!read_uint(&a, &ctl_ch))
-			return 0;
-
-		c = tolower((int)a[0]);
-	}
-	else {
-		/* first number is channel, use default for band */
-		ctl_ch = num;
-		chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ?
-		               WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
-	}
-
-	if (c == '\0') {
-		/* default BW of 20MHz */
-		chspec_bw = WL_CHANSPEC_BW_20;
-		goto done_read;
-	}
-
-	a ++; /* consume the 'u','l', or '/' */
-
-	/* check 'u'/'l' */
-	if (c == 'u' || c == 'l') {
-		sb_ul = c;
-		chspec_bw = WL_CHANSPEC_BW_40;
-		goto done_read;
-	}
-
-	/* next letter must be '/' */
-	if (c != '/')
-		return 0;
-
-	/* read bandwidth */
-	if (!read_uint(&a, &bw))
-		return 0;
-
-	/* convert to chspec value */
-	if (bw == 2) {
-		chspec_bw = WL_CHANSPEC_BW_2P5;
-	} else if (bw == 5) {
-		chspec_bw = WL_CHANSPEC_BW_5;
-	} else if (bw == 10) {
-		chspec_bw = WL_CHANSPEC_BW_10;
-	} else if (bw == 20) {
-		chspec_bw = WL_CHANSPEC_BW_20;
-	} else if (bw == 40) {
-		chspec_bw = WL_CHANSPEC_BW_40;
-	} else if (bw == 80) {
-		chspec_bw = WL_CHANSPEC_BW_80;
-	} else if (bw == 160) {
-		chspec_bw = WL_CHANSPEC_BW_160;
-	} else {
-		return 0;
-	}
-
-	/* So far we have <band>g<chan>/<bw>
-	 * Can now be followed by u/l if bw = 40,
-	 * or '+80' if bw = 80, to make '80+80' bw,
-	 * or '.5' if bw = 2.5 to make '2.5' bw .
-	 */
-
-	c = tolower((int)a[0]);
-
-	/* if we have a 2g/40 channel, we should have a l/u spec now */
-	if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) {
-		if (c == 'u' || c == 'l') {
-			a ++; /* consume the u/l char */
-			sb_ul = c;
-			goto done_read;
-		}
-	}
-
-	/* check for 80+80 */
-	if (c == '+') {
-		/* 80+80 */
-		const char plus80[] = "80/";
-
-		/* must be looking at '+80/'
-		 * check and consume this string.
-		 */
-		chspec_bw = WL_CHANSPEC_BW_8080;
-
-		a ++; /* consume the char '+' */
-
-		/* consume the '80/' string */
-		for (i = 0; i < 3; i++) {
-			if (*a++ != plus80[i]) {
-				return 0;
-			}
-		}
-
-		/* read primary 80MHz channel */
-		if (!read_uint(&a, &ch1))
-			return 0;
-
-		/* must followed by '-' */
-		if (a[0] != '-')
-			return 0;
-		a ++; /* consume the char */
-
-		/* read secondary 80MHz channel */
-		if (!read_uint(&a, &ch2))
-			return 0;
-	} else if (c == '.') {
-		/* 2.5 */
-		/* must be looking at '.5'
-		 * check and consume this string.
-		 */
-		chspec_bw = WL_CHANSPEC_BW_2P5;
-
-		a ++; /* consume the char '.' */
-
-		/* consume the '5' string */
-		if (*a++ != '5') {
-			return 0;
-		}
-	}
-
-done_read:
-	/* skip trailing white space */
-	while (a[0] == ' ') {
-		a ++;
-	}
-
-	/* must be end of string */
-	if (a[0] != '\0')
-		return 0;
-
-	/* Now have all the chanspec string parts read;
-	 * chspec_band, ctl_ch, chspec_bw, sb_ul, ch1, ch2.
-	 * chspec_band and chspec_bw are chanspec values.
-	 * Need to convert ctl_ch, sb_ul, and ch1,ch2 into
-	 * a center channel (or two) and sideband.
-	 */
-
-	/* if a sb u/l string was given, just use that,
-	 * guaranteed to be bw = 40 by sting parse.
-	 */
-	if (sb_ul != '\0') {
-		if (sb_ul == 'l') {
-			chspec_ch = UPPER_20_SB(ctl_ch);
-			chspec_sb = WL_CHANSPEC_CTL_SB_LLL;
-		} else if (sb_ul == 'u') {
-			chspec_ch = LOWER_20_SB(ctl_ch);
-			chspec_sb = WL_CHANSPEC_CTL_SB_LLU;
-		}
-	}
-	/* if the bw is 20, center and sideband are trivial */
-	else if (BW_LE20(chspec_bw)) {
-		chspec_ch = ctl_ch;
-		chspec_sb = WL_CHANSPEC_CTL_SB_NONE;
-	}
-	/* if the bw is 40/80/160, not 80+80, a single method
-	 * can be used to to find the center and sideband
-	 */
-	else if (chspec_bw != WL_CHANSPEC_BW_8080) {
-		/* figure out ctl sideband based on ctl channel and bandwidth */
-		const uint8 *center_ch = NULL;
-		int num_ch = 0;
-		int sb = -1;
-
-		if (chspec_bw == WL_CHANSPEC_BW_40) {
-			center_ch = wf_5g_40m_chans;
-			num_ch = WF_NUM_5G_40M_CHANS;
-		} else if (chspec_bw == WL_CHANSPEC_BW_80) {
-			center_ch = wf_5g_80m_chans;
-			num_ch = WF_NUM_5G_80M_CHANS;
-		} else if (chspec_bw == WL_CHANSPEC_BW_160) {
-			center_ch = wf_5g_160m_chans;
-			num_ch = WF_NUM_5G_160M_CHANS;
-		} else {
-			return 0;
-		}
-
-		for (i = 0; i < num_ch; i ++) {
-			sb = channel_to_sb(center_ch[i], ctl_ch, bw);
-			if (sb >= 0) {
-				chspec_ch = center_ch[i];
-				chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
-				break;
-			}
-		}
-
-		/* check for no matching sb/center */
-		if (sb < 0) {
-			return 0;
-		}
-	}
-	/* Otherwise, bw is 80+80. Figure out channel pair and sb */
-	else {
-		int ch1_id = 0, ch2_id = 0;
-		int sb;
-
-		/* look up the channel ID for the specified channel numbers */
-		ch1_id = channel_80mhz_to_id(ch1);
-		ch2_id = channel_80mhz_to_id(ch2);
-
-		/* validate channels */
-		if (ch1_id < 0 || ch2_id < 0)
-			return 0;
-
-		/* combine 2 channel IDs in channel field of chspec */
-		chspec_ch = (((uint)ch1_id << WL_CHANSPEC_CHAN1_SHIFT) |
-		             ((uint)ch2_id << WL_CHANSPEC_CHAN2_SHIFT));
-
-		/* figure out primary 20 MHz sideband */
-
-		/* is the primary channel contained in the 1st 80MHz channel? */
-		sb = channel_to_sb(ch1, ctl_ch, bw);
-		if (sb < 0) {
-			/* no match for primary channel 'ctl_ch' in segment0 80MHz channel */
-			return 0;
-		}
-
-		chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
-	}
-
-	chspec = (chspec_ch | chspec_band | chspec_bw | chspec_sb);
-
-	if (wf_chspec_malformed(chspec))
-		return 0;
-
-	return chspec;
-}
-
-/*
- * Verify the chanspec is using a legal set of parameters, i.e. that the
- * chanspec specified a band, bw, ctl_sb and channel and that the
- * combination could be legal given any set of circumstances.
- * RETURNS: TRUE is the chanspec is malformed, false if it looks good.
- */
-bool
-wf_chspec_malformed(chanspec_t chanspec)
-{
-	uint chspec_bw = CHSPEC_BW(chanspec);
-	uint chspec_ch = CHSPEC_CHANNEL(chanspec);
-
-	/* must be 2G or 5G band */
-	if (CHSPEC_IS2G(chanspec)) {
-		/* must be valid bandwidth */
-		if (!BW_LE40(chspec_bw)) {
-			return TRUE;
-		}
-	} else if (CHSPEC_IS5G(chanspec)) {
-		if (chspec_bw == WL_CHANSPEC_BW_8080) {
-			uint ch1_id, ch2_id;
-
-			/* channel IDs in 80+80 must be in range */
-			ch1_id = CHSPEC_CHAN1(chanspec);
-			ch2_id = CHSPEC_CHAN2(chanspec);
-			if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS)
-				return TRUE;
-
-		} else if (BW_LE160(chspec_bw)) {
-			if (chspec_ch > MAXCHANNEL) {
-				return TRUE;
-			}
-		} else {
-			/* invalid bandwidth */
-			return TRUE;
-		}
-	} else {
-		/* must be 2G or 5G band */
-		return TRUE;
-	}
-
-	/* side band needs to be consistent with bandwidth */
-	if (BW_LE20(chspec_bw)) {
-		if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL)
-			return TRUE;
-	} else if (chspec_bw == WL_CHANSPEC_BW_40) {
-		if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LLU)
-			return TRUE;
-	} else if (chspec_bw == WL_CHANSPEC_BW_80 ||
-	           chspec_bw == WL_CHANSPEC_BW_8080) {
-		if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU)
-			return TRUE;
-	}
-	else if (chspec_bw == WL_CHANSPEC_BW_160) {
-		ASSERT(CHSPEC_CTL_SB(chanspec) <= WL_CHANSPEC_CTL_SB_UUU);
-	}
-	return FALSE;
-}
-
-/*
- * Verify the chanspec specifies a valid channel according to 802.11.
- * RETURNS: TRUE if the chanspec is a valid 802.11 channel
- */
-bool
-wf_chspec_valid(chanspec_t chanspec)
-{
-	uint chspec_bw = CHSPEC_BW(chanspec);
-	uint chspec_ch = CHSPEC_CHANNEL(chanspec);
-
-	if (wf_chspec_malformed(chanspec))
-		return FALSE;
-
-	if (CHSPEC_IS2G(chanspec)) {
-		/* must be valid bandwidth and channel range */
-		if (BW_LE20(chspec_bw)) {
-			if (chspec_ch >= 1 && chspec_ch <= 14)
-				return TRUE;
-		} else if (chspec_bw == WL_CHANSPEC_BW_40) {
-			if (chspec_ch >= 3 && chspec_ch <= 11)
-				return TRUE;
-		}
-	} else if (CHSPEC_IS5G(chanspec)) {
-		if (chspec_bw == WL_CHANSPEC_BW_8080) {
-			uint16 ch1, ch2;
-
-			ch1 = wf_5g_80m_chans[CHSPEC_CHAN1(chanspec)];
-			ch2 = wf_5g_80m_chans[CHSPEC_CHAN2(chanspec)];
-
-			/* the two channels must be separated by more than 80MHz by VHT req */
-			if ((ch2 > ch1 + CH_80MHZ_APART) ||
-			    (ch1 > ch2 + CH_80MHZ_APART))
-				return TRUE;
-		} else {
-			const uint8 *center_ch;
-			uint num_ch, i;
-
-			if (BW_LE40(chspec_bw)) {
-				center_ch = wf_5g_40m_chans;
-				num_ch = WF_NUM_5G_40M_CHANS;
-			} else if (chspec_bw == WL_CHANSPEC_BW_80) {
-				center_ch = wf_5g_80m_chans;
-				num_ch = WF_NUM_5G_80M_CHANS;
-			} else if (chspec_bw == WL_CHANSPEC_BW_160) {
-				center_ch = wf_5g_160m_chans;
-				num_ch = WF_NUM_5G_160M_CHANS;
-			} else {
-				/* invalid bandwidth */
-				return FALSE;
-			}
-
-			/* check for a valid center channel */
-			if (BW_LE20(chspec_bw)) {
-				/* We don't have an array of legal 20MHz 5G channels, but they are
-				 * each side of the legal 40MHz channels.  Check the chanspec
-				 * channel against either side of the 40MHz channels.
-				 */
-				for (i = 0; i < num_ch; i ++) {
-					if (chspec_ch == (uint)LOWER_20_SB(center_ch[i]) ||
-					    chspec_ch == (uint)UPPER_20_SB(center_ch[i]))
-						break; /* match found */
-				}
-
-				if (i == num_ch) {
-					/* check for channel 165 which is not the side band
-					 * of 40MHz 5G channel
-					 */
-					if (chspec_ch == 165)
-						i = 0;
-
-					/* check for legacy JP channels on failure */
-					if (chspec_ch == 34 || chspec_ch == 38 ||
-					    chspec_ch == 42 || chspec_ch == 46)
-						i = 0;
-				}
-			} else {
-				/* check the chanspec channel to each legal channel */
-				for (i = 0; i < num_ch; i ++) {
-					if (chspec_ch == center_ch[i])
-						break; /* match found */
-				}
-			}
-
-			if (i < num_ch) {
-				/* match found */
-				return TRUE;
-			}
-		}
-	}
-
-	return FALSE;
-}
-
-/*
- * This function returns the channel number that control traffic is being sent on, for 20MHz
- * channels this is just the channel number, for 40MHZ, 80MHz, 160MHz channels it is the 20MHZ
- * sideband depending on the chanspec selected
- */
-uint8
-wf_chspec_ctlchan(chanspec_t chspec)
-{
-	uint center_chan;
-	uint bw_mhz;
-	uint sb;
-
-	ASSERT(!wf_chspec_malformed(chspec));
-
-	/* Is there a sideband ? */
-	if (CHSPEC_BW_LE20(chspec)) {
-		return CHSPEC_CHANNEL(chspec);
-	} else {
-		sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
-
-		if (CHSPEC_IS8080(chspec)) {
-			/* For an 80+80 MHz channel, the sideband 'sb' field is an 80 MHz sideband
-			 * (LL, LU, UL, LU) for the 80 MHz frequency segment 0.
-			 */
-			uint chan_id = CHSPEC_CHAN1(chspec);
-
-			bw_mhz = 80;
-
-			/* convert from channel index to channel number */
-			center_chan = wf_5g_80m_chans[chan_id];
-		}
-		else {
-			bw_mhz = bw_chspec_to_mhz(chspec);
-			center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT;
-		}
-
-		return (channel_to_ctl_chan(center_chan, bw_mhz, sb));
-	}
-}
-
-/* given a chanspec, return the bandwidth string */
-char *
-wf_chspec_to_bw_str(chanspec_t chspec)
-{
-		return (char *)wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)];
-}
-
-/*
- * This function returns the chanspec of the control channel of a given chanspec
- */
-chanspec_t
-wf_chspec_ctlchspec(chanspec_t chspec)
-{
-	chanspec_t ctl_chspec = chspec;
-	uint8 ctl_chan;
-
-	ASSERT(!wf_chspec_malformed(chspec));
-
-	/* Is there a sideband ? */
-	if (!CHSPEC_BW_LE20(chspec)) {
-		ctl_chan = wf_chspec_ctlchan(chspec);
-		ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20;
-		ctl_chspec |= CHSPEC_BAND(chspec);
-	}
-	return ctl_chspec;
-}
-
-/* return chanspec given control channel and bandwidth
- * return 0 on error
- */
-uint16
-wf_channel2chspec(uint ctl_ch, uint bw)
-{
-	uint16 chspec;
-	const uint8 *center_ch = NULL;
-	int num_ch = 0;
-	int sb = -1;
-	int i = 0;
-
-	chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
-
-	chspec |= bw;
-
-	if (bw == WL_CHANSPEC_BW_40) {
-		center_ch = wf_5g_40m_chans;
-		num_ch = WF_NUM_5G_40M_CHANS;
-		bw = 40;
-	} else if (bw == WL_CHANSPEC_BW_80) {
-		center_ch = wf_5g_80m_chans;
-		num_ch = WF_NUM_5G_80M_CHANS;
-		bw = 80;
-	} else if (bw == WL_CHANSPEC_BW_160) {
-		center_ch = wf_5g_160m_chans;
-		num_ch = WF_NUM_5G_160M_CHANS;
-		bw = 160;
-	} else if (BW_LE20(bw)) {
-		chspec |= ctl_ch;
-		return chspec;
-	} else {
-		return 0;
-	}
-
-	for (i = 0; i < num_ch; i ++) {
-		sb = channel_to_sb(center_ch[i], ctl_ch, bw);
-		if (sb >= 0) {
-			chspec |= center_ch[i];
-			chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT);
-			break;
-		}
-	}
-
-	/* check for no matching sb/center */
-	if (sb < 0) {
-		return 0;
-	}
-
-	return chspec;
-}
-
-/*
- * This function returns the chanspec for the primary 40MHz of an 80MHz channel.
- * The control sideband specifies the same 20MHz channel that the 80MHz channel is using
- * as the primary 20MHz channel.
- */
-extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec)
-{
-	chanspec_t chspec40 = chspec;
-	uint center_chan;
-	uint sb;
-
-	ASSERT(!wf_chspec_malformed(chspec));
-
-	/* if the chanspec is > 80MHz, use the helper routine to find the primary 80 MHz channel */
-	if (CHSPEC_IS8080(chspec) || CHSPEC_IS160(chspec)) {
-		chspec = wf_chspec_primary80_chspec(chspec);
-	}
-
-	/* determine primary 40 MHz sub-channel of an 80 MHz chanspec */
-	if (CHSPEC_IS80(chspec)) {
-		center_chan = CHSPEC_CHANNEL(chspec);
-		sb = CHSPEC_CTL_SB(chspec);
-
-		if (sb < WL_CHANSPEC_CTL_SB_UL) {
-			/* Primary 40MHz is on lower side */
-			center_chan -= CH_20MHZ_APART;
-			/* sideband bits are the same for LL/LU and L/U */
-		} else {
-			/* Primary 40MHz is on upper side */
-			center_chan += CH_20MHZ_APART;
-			/* sideband bits need to be adjusted by UL offset */
-			sb -= WL_CHANSPEC_CTL_SB_UL;
-		}
-
-		/* Create primary 40MHz chanspec */
-		chspec40 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 |
-		            sb | center_chan);
-	}
-
-	return chspec40;
-}
-
-/*
- * Return the channel number for a given frequency and base frequency.
- * The returned channel number is relative to the given base frequency.
- * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
- * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
- *
- * Frequency is specified in MHz.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- *
- * The returned channel will be in the range [1, 14] in the 2.4 GHz band
- * and [0, 200] otherwise.
- * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
- * frequency is not a 2.4 GHz channel, or if the frequency is not and even
- * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-int
-wf_mhz2channel(uint freq, uint start_factor)
-{
-	int ch = -1;
-	uint base;
-	int offset;
-
-	/* take the default channel start frequency */
-	if (start_factor == 0) {
-		if (freq >= 2400 && freq <= 2500)
-			start_factor = WF_CHAN_FACTOR_2_4_G;
-		else if (freq >= 5000 && freq <= 6000)
-			start_factor = WF_CHAN_FACTOR_5_G;
-	}
-
-	if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G)
-		return 14;
-
-	base = start_factor / 2;
-
-	/* check that the frequency is in 1GHz range of the base */
-	if ((freq < base) || (freq > base + 1000))
-		return -1;
-
-	offset = freq - base;
-	ch = offset / 5;
-
-	/* check that frequency is a 5MHz multiple from the base */
-	if (offset != (ch * 5))
-		return -1;
-
-	/* restricted channel range check for 2.4G */
-	if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13))
-		return -1;
-
-	return ch;
-}
-
-/*
- * Return the center frequency in MHz of the given channel and base frequency.
- * The channel number is interpreted relative to the given base frequency.
- *
- * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_4_G, and WF_CHAN_FACTOR_5_G
- * are defined for 2.4 GHz, 4 GHz, and 5 GHz bands.
- * The channel range of [1, 14] is only checked for a start_factor of
- * WF_CHAN_FACTOR_2_4_G (4814 = 2407 * 2).
- * Odd start_factors produce channels on .5 MHz boundaries, in which case
- * the answer is rounded down to an integral MHz.
- * -1 is returned for an out of range channel.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-int
-wf_channel2mhz(uint ch, uint start_factor)
-{
-	int freq;
-
-	if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) ||
-	    (ch > 200))
-		freq = -1;
-	else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14))
-		freq = 2484;
-	else
-		freq = ch * 5 + start_factor / 2;
-
-	return freq;
-}
-
-static const uint16 sidebands[] = {
-	WL_CHANSPEC_CTL_SB_LLL, WL_CHANSPEC_CTL_SB_LLU,
-	WL_CHANSPEC_CTL_SB_LUL, WL_CHANSPEC_CTL_SB_LUU,
-	WL_CHANSPEC_CTL_SB_ULL, WL_CHANSPEC_CTL_SB_ULU,
-	WL_CHANSPEC_CTL_SB_UUL, WL_CHANSPEC_CTL_SB_UUU
-};
-
-/*
- * Returns the chanspec 80Mhz channel corresponding to the following input
- * parameters
- *
- *	primary_channel - primary 20Mhz channel
- *	center_channel   - center frequecny of the 80Mhz channel
- *
- * The center_channel can be one of {42, 58, 106, 122, 138, 155}
- *
- * returns INVCHANSPEC in case of error
- */
-chanspec_t
-wf_chspec_80(uint8 center_channel, uint8 primary_channel)
-{
-
-	chanspec_t chanspec = INVCHANSPEC;
-	chanspec_t chanspec_cur;
-	uint i;
-
-	for (i = 0; i < WF_NUM_SIDEBANDS_80MHZ; i++) {
-		chanspec_cur = CH80MHZ_CHSPEC(center_channel, sidebands[i]);
-		if (primary_channel == wf_chspec_ctlchan(chanspec_cur)) {
-			chanspec = chanspec_cur;
-			break;
-		}
-	}
-	/* If the loop ended early, we are good, otherwise we did not
-	* find a 80MHz chanspec with the given center_channel that had a primary channel
-	*matching the given primary_channel.
-	*/
-	return chanspec;
-}
-
-/*
- * Returns the 80+80 chanspec corresponding to the following input parameters
- *
- *    primary_20mhz - Primary 20 MHz channel
- *    chan0 - center channel number of one frequency segment
- *    chan1 - center channel number of the other frequency segment
- *
- * Parameters chan0 and chan1 are channel numbers in {42, 58, 106, 122, 138, 155}.
- * The primary channel must be contained in one of the 80MHz channels. This routine
- * will determine which frequency segment is the primary 80 MHz segment.
- *
- * Returns INVCHANSPEC in case of error.
- *
- * Refer to IEEE802.11ac section 22.3.14 "Channelization".
- */
-chanspec_t
-wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan0, uint8 chan1)
-{
-	int sb = 0;
-	uint16 chanspec = 0;
-	int chan0_id = 0, chan1_id = 0;
-	int seg0, seg1;
-
-	chan0_id = channel_80mhz_to_id(chan0);
-	chan1_id = channel_80mhz_to_id(chan1);
-
-	/* make sure the channel numbers were valid */
-	if (chan0_id == -1 || chan1_id == -1)
-		return INVCHANSPEC;
-
-	/* does the primary channel fit with the 1st 80MHz channel ? */
-	sb = channel_to_sb(chan0, primary_20mhz, 80);
-	if (sb >= 0) {
-		/* yes, so chan0 is frequency segment 0, and chan1 is seg 1 */
-		seg0 = chan0_id;
-		seg1 = chan1_id;
-	} else {
-		/* no, so does the primary channel fit with the 2nd 80MHz channel ? */
-		sb = channel_to_sb(chan1, primary_20mhz, 80);
-		if (sb < 0) {
-			/* no match for ctl_ch to either 80MHz center channel */
-			return INVCHANSPEC;
-		}
-		/* swapped, so chan1 is frequency segment 0, and chan0 is seg 1 */
-		seg0 = chan1_id;
-		seg1 = chan0_id;
-	}
-
-	chanspec = ((seg0 << WL_CHANSPEC_CHAN1_SHIFT) |
-	            (seg1 << WL_CHANSPEC_CHAN2_SHIFT) |
-	            (sb << WL_CHANSPEC_CTL_SB_SHIFT) |
-	            WL_CHANSPEC_BW_8080 |
-	            WL_CHANSPEC_BAND_5G);
-
-	return chanspec;
-}
-
-/*
- * This function returns the 80Mhz channel for the given id.
- */
-static uint8
-wf_chspec_get80Mhz_ch(uint8 chan_80Mhz_id)
-{
-	if (chan_80Mhz_id < WF_NUM_5G_80M_CHANS)
-		return wf_5g_80m_chans[chan_80Mhz_id];
-
-	return 0;
-}
-
-/*
- * Returns the primary 80 Mhz channel for the provided chanspec
- *
- *    chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
- *
- *  returns -1 in case the provided channel is 20/40 Mhz chanspec
- */
-
-uint8
-wf_chspec_primary80_channel(chanspec_t chanspec)
-{
-	uint8 primary80_chan;
-
-	if (CHSPEC_IS80(chanspec))	{
-		primary80_chan = CHSPEC_CHANNEL(chanspec);
-	}
-	else if (CHSPEC_IS8080(chanspec)) {
-		/* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */
-		primary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec));
-	}
-	else if (CHSPEC_IS160(chanspec)) {
-		uint8 center_chan = CHSPEC_CHANNEL(chanspec);
-		uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
-
-		/* based on the sb value primary 80 channel can be retrieved
-		 * if sb is in range 0 to 3 the lower band is the 80Mhz primary band
-		 */
-		if (sb < 4) {
-			primary80_chan = center_chan - CH_40MHZ_APART;
-		}
-		/* if sb is in range 4 to 7 the upper band is the 80Mhz primary band */
-		else
-		{
-			primary80_chan = center_chan + CH_40MHZ_APART;
-		}
-	}
-	else {
-		/* for 20 and 40 Mhz */
-		primary80_chan = -1;
-	}
-	return primary80_chan;
-}
-
-/*
- * Returns the secondary 80 Mhz channel for the provided chanspec
- *
- *    chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
- *
- *  returns -1 in case the provided channel is 20/40/80 Mhz chanspec
- */
-uint8
-wf_chspec_secondary80_channel(chanspec_t chanspec)
-{
-	uint8 secondary80_chan;
-
-	if (CHSPEC_IS8080(chanspec)) {
-		secondary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec));
-	}
-	else if (CHSPEC_IS160(chanspec)) {
-		uint8 center_chan = CHSPEC_CHANNEL(chanspec);
-		uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
-
-		/* based on the sb value  secondary 80 channel can be retrieved
-		 * if sb is in range 0 to 3 upper band is the secondary 80Mhz band
-		 */
-		if (sb < 4) {
-			secondary80_chan = center_chan + CH_40MHZ_APART;
-		}
-		/* if sb is in range 4 to 7 the lower band is the secondary 80Mhz band */
-		else
-		{
-			secondary80_chan = center_chan - CH_40MHZ_APART;
-		}
-	}
-	else {
-		/* for 20, 40, and 80 Mhz */
-		secondary80_chan = -1;
-	}
-	return secondary80_chan;
-}
-
-/*
- * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
- *
- *    chanspec - Input chanspec for which the primary 80Mhz chanspec has to be retreived
- *
- *  returns the input chanspec in case the provided chanspec is an 80 MHz chanspec
- *  returns INVCHANSPEC in case the provided channel is 20/40 MHz chanspec
- */
-chanspec_t
-wf_chspec_primary80_chspec(chanspec_t chspec)
-{
-	chanspec_t chspec80;
-	uint center_chan;
-	uint sb;
-
-	ASSERT(!wf_chspec_malformed(chspec));
-	if (CHSPEC_IS80(chspec)) {
-		chspec80 = chspec;
-	}
-	else if (CHSPEC_IS8080(chspec)) {
-
-		/* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */
-		center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
-
-		sb = CHSPEC_CTL_SB(chspec);
-
-		/* Create primary 80MHz chanspec */
-		chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
-	}
-	else if (CHSPEC_IS160(chspec)) {
-		center_chan = CHSPEC_CHANNEL(chspec);
-		sb = CHSPEC_CTL_SB(chspec);
-
-		if (sb < WL_CHANSPEC_CTL_SB_ULL) {
-			/* Primary 80MHz is on lower side */
-			center_chan -= CH_40MHZ_APART;
-		}
-		else {
-			/* Primary 80MHz is on upper side */
-			center_chan += CH_40MHZ_APART;
-			sb -= WL_CHANSPEC_CTL_SB_ULL;
-		}
-		/* Create primary 80MHz chanspec */
-		chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
-	}
-	else {
-		chspec80 = INVCHANSPEC;
-	}
-
-	return chspec80;
-}
-
-#ifdef WL11AC_80P80
-uint8
-wf_chspec_channel(chanspec_t chspec)
-{
-	if (CHSPEC_IS8080(chspec)) {
-		return wf_chspec_primary80_channel(chspec);
-	}
-	else {
-		return ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK));
-	}
-}
-#endif /* WL11AC_80P80 */
diff --git a/drivers/net/wireless/bcmdhd/bcmwifi_channels.h b/drivers/net/wireless/bcmdhd/bcmwifi_channels.h
deleted file mode 100644
index 186c0e1..0000000
--- a/drivers/net/wireless/bcmdhd/bcmwifi_channels.h
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * Misc utility routines for WL and Apps
- * This header file housing the define and function prototype use by
- * both the wl driver, tools & Apps.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmwifi_channels.h 591285 2015-10-07 11:56:29Z $
- */
-
-#ifndef	_bcmwifi_channels_h_
-#define	_bcmwifi_channels_h_
-
-
-/* A chanspec holds the channel number, band, bandwidth and control sideband */
-typedef uint16 chanspec_t;
-
-/* channel defines */
-#define CH_UPPER_SB			0x01
-#define CH_LOWER_SB			0x02
-#define CH_EWA_VALID			0x04
-#define CH_80MHZ_APART			16
-#define CH_40MHZ_APART			8
-#define CH_20MHZ_APART			4
-#define CH_10MHZ_APART			2
-#define CH_5MHZ_APART			1	/* 2G band channels are 5 Mhz apart */
-#define CH_MAX_2G_CHANNEL		14	/* Max channel in 2G band */
-
-/* maximum # channels the s/w supports */
-#define MAXCHANNEL		224	/* max # supported channels. The max channel no is above,
-					 * this is that + 1 rounded up to a multiple of NBBY (8).
-					 * DO NOT MAKE it > 255: channels are uint8's all over
-					 */
-#define MAXCHANNEL_NUM	(MAXCHANNEL - 1)	/* max channel number */
-
-/* channel bitvec */
-typedef struct {
-	uint8   vec[MAXCHANNEL/8];   /* bitvec of channels */
-} chanvec_t;
-
-/* make sure channel num is within valid range */
-#define CH_NUM_VALID_RANGE(ch_num) ((ch_num) > 0 && (ch_num) <= MAXCHANNEL_NUM)
-
-#define CHSPEC_CTLOVLP(sp1, sp2, sep)	\
-	(ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep))
-
-/* All builds use the new 11ac ratespec/chanspec */
-#undef  D11AC_IOTYPES
-#define D11AC_IOTYPES
-
-#define WL_CHANSPEC_CHAN_MASK		0x00ff
-#define WL_CHANSPEC_CHAN_SHIFT		0
-#define WL_CHANSPEC_CHAN1_MASK		0x000f
-#define WL_CHANSPEC_CHAN1_SHIFT		0
-#define WL_CHANSPEC_CHAN2_MASK		0x00f0
-#define WL_CHANSPEC_CHAN2_SHIFT		4
-
-#define WL_CHANSPEC_CTL_SB_MASK		0x0700
-#define WL_CHANSPEC_CTL_SB_SHIFT	8
-#define WL_CHANSPEC_CTL_SB_LLL		0x0000
-#define WL_CHANSPEC_CTL_SB_LLU		0x0100
-#define WL_CHANSPEC_CTL_SB_LUL		0x0200
-#define WL_CHANSPEC_CTL_SB_LUU		0x0300
-#define WL_CHANSPEC_CTL_SB_ULL		0x0400
-#define WL_CHANSPEC_CTL_SB_ULU		0x0500
-#define WL_CHANSPEC_CTL_SB_UUL		0x0600
-#define WL_CHANSPEC_CTL_SB_UUU		0x0700
-#define WL_CHANSPEC_CTL_SB_LL		WL_CHANSPEC_CTL_SB_LLL
-#define WL_CHANSPEC_CTL_SB_LU		WL_CHANSPEC_CTL_SB_LLU
-#define WL_CHANSPEC_CTL_SB_UL		WL_CHANSPEC_CTL_SB_LUL
-#define WL_CHANSPEC_CTL_SB_UU		WL_CHANSPEC_CTL_SB_LUU
-#define WL_CHANSPEC_CTL_SB_L		WL_CHANSPEC_CTL_SB_LLL
-#define WL_CHANSPEC_CTL_SB_U		WL_CHANSPEC_CTL_SB_LLU
-#define WL_CHANSPEC_CTL_SB_LOWER	WL_CHANSPEC_CTL_SB_LLL
-#define WL_CHANSPEC_CTL_SB_UPPER	WL_CHANSPEC_CTL_SB_LLU
-#define WL_CHANSPEC_CTL_SB_NONE		WL_CHANSPEC_CTL_SB_LLL
-
-#define WL_CHANSPEC_BW_MASK		0x3800
-#define WL_CHANSPEC_BW_SHIFT		11
-#define WL_CHANSPEC_BW_5		0x0000
-#define WL_CHANSPEC_BW_10		0x0800
-#define WL_CHANSPEC_BW_20		0x1000
-#define WL_CHANSPEC_BW_40		0x1800
-#define WL_CHANSPEC_BW_80		0x2000
-#define WL_CHANSPEC_BW_160		0x2800
-#define WL_CHANSPEC_BW_8080		0x3000
-#define WL_CHANSPEC_BW_2P5		0x3800
-
-#define WL_CHANSPEC_BAND_MASK		0xc000
-#define WL_CHANSPEC_BAND_SHIFT		14
-#define WL_CHANSPEC_BAND_2G		0x0000
-#define WL_CHANSPEC_BAND_3G		0x4000
-#define WL_CHANSPEC_BAND_4G		0x8000
-#define WL_CHANSPEC_BAND_5G		0xc000
-#define INVCHANSPEC			255
-#define MAX_CHANSPEC				0xFFFF
-
-/* channel defines */
-#define LOWER_20_SB(channel)		(((channel) > CH_10MHZ_APART) ? \
-					((channel) - CH_10MHZ_APART) : 0)
-#define UPPER_20_SB(channel)		(((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
-					((channel) + CH_10MHZ_APART) : 0)
-
-#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0)
-#define UU_20_SB(channel) 	(((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \
-				((channel) + 3 * CH_10MHZ_APART) : 0)
-#define LU_20_SB(channel) LOWER_20_SB(channel)
-#define UL_20_SB(channel) UPPER_20_SB(channel)
-
-#define LOWER_40_SB(channel)		((channel) - CH_20MHZ_APART)
-#define UPPER_40_SB(channel)		((channel) + CH_20MHZ_APART)
-#define CHSPEC_WLCBANDUNIT(chspec)	(CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX)
-#define CH20MHZ_CHSPEC(channel)		(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
-					(((channel) <= CH_MAX_2G_CHANNEL) ? \
-					WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define CH2P5MHZ_CHSPEC(channel)	(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_2P5 | \
-						(((channel) <= CH_MAX_2G_CHANNEL) ? \
-						WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define CH5MHZ_CHSPEC(channel)		(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_5 | \
-						(((channel) <= CH_MAX_2G_CHANNEL) ? \
-						WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define CH10MHZ_CHSPEC(channel)		(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_10 | \
-						(((channel) <= CH_MAX_2G_CHANNEL) ? \
-						WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define NEXT_20MHZ_CHAN(channel)	(((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
-					((channel) + CH_20MHZ_APART) : 0)
-#define CH40MHZ_CHSPEC(channel, ctlsb)	(chanspec_t) \
-					((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
-					((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
-					WL_CHANSPEC_BAND_5G))
-#define CH80MHZ_CHSPEC(channel, ctlsb)	(chanspec_t) \
-					((channel) | (ctlsb) | \
-					 WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G)
-#define CH160MHZ_CHSPEC(channel, ctlsb)	(chanspec_t) \
-					((channel) | (ctlsb) | \
-					 WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G)
-#define CHBW_CHSPEC(bw, channel)	(chanspec_t)((chanspec_t)(channel) | (bw) | \
-							(((channel) <= CH_MAX_2G_CHANNEL) ? \
-							WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-
-/* simple MACROs to get different fields of chanspec */
-#ifdef WL11AC_80P80
-#define CHSPEC_CHANNEL(chspec)	wf_chspec_channel(chspec)
-#else
-#define CHSPEC_CHANNEL(chspec)	((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK))
-#endif
-#define CHSPEC_CHAN1(chspec)	((chspec) & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT
-#define CHSPEC_CHAN2(chspec)	((chspec) & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT
-#define CHSPEC_BAND(chspec)		((chspec) & WL_CHANSPEC_BAND_MASK)
-#define CHSPEC_CTL_SB(chspec)	((chspec) & WL_CHANSPEC_CTL_SB_MASK)
-#define CHSPEC_BW(chspec)		((chspec) & WL_CHANSPEC_BW_MASK)
-
-#ifdef WL11N_20MHZONLY
-
-#define CHSPEC_IS2P5(chspec)	0
-#define CHSPEC_IS5(chspec)	0
-#define CHSPEC_IS10(chspec)	0
-#define CHSPEC_IS20(chspec)	1
-#ifndef CHSPEC_IS40
-#define CHSPEC_IS40(chspec)	0
-#endif
-#ifndef CHSPEC_IS80
-#define CHSPEC_IS80(chspec)	0
-#endif
-#ifndef CHSPEC_IS160
-#define CHSPEC_IS160(chspec)	0
-#endif
-#ifndef CHSPEC_IS8080
-#define CHSPEC_IS8080(chspec)	0
-#endif
-#define BW_LE20(bw)		TRUE
-#define CHSPEC_ISLE20(chspec)	TRUE
-#else /* !WL11N_20MHZONLY */
-
-#define CHSPEC_IS2P5(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_2P5)
-#define CHSPEC_IS5(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_5)
-#define CHSPEC_IS10(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
-#define CHSPEC_IS20(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
-#ifndef CHSPEC_IS40
-#define CHSPEC_IS40(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
-#endif
-#ifndef CHSPEC_IS80
-#define CHSPEC_IS80(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80)
-#endif
-#ifndef CHSPEC_IS160
-#define CHSPEC_IS160(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160)
-#endif
-#ifndef CHSPEC_IS8080
-#define CHSPEC_IS8080(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080)
-#endif
-
-#ifdef WL11ULB
-#define BW_LT20(bw)		(((bw) == WL_CHANSPEC_BW_2P5) || \
-				((bw) == WL_CHANSPEC_BW_5) || \
-				((bw) == WL_CHANSPEC_BW_10))
-#define CHSPEC_BW_LT20(chspec)	(BW_LT20(CHSPEC_BW(chspec)))
-/* This MACRO is strictly to avoid abandons in existing code with ULB feature and is in no way
- * optimial to use. Should be replaced with CHSPEC_BW_LE() instead
- */
-#define BW_LE20(bw)		(((bw) == WL_CHANSPEC_BW_2P5) || \
-				((bw) == WL_CHANSPEC_BW_5) || \
-				((bw) == WL_CHANSPEC_BW_10) || \
-				((bw) == WL_CHANSPEC_BW_20))
-#define CHSPEC_ISLE20(chspec)	(BW_LE20(CHSPEC_BW(chspec)))
-
-#else /* WL11ULB */
-#define BW_LE20(bw)		((bw) == WL_CHANSPEC_BW_20)
-#define CHSPEC_ISLE20(chspec)	(CHSPEC_IS20(chspec))
-#endif /* WL11ULB */
-#endif /* !WL11N_20MHZONLY */
-
-#define BW_LE40(bw)		(BW_LE20(bw) || ((bw) == WL_CHANSPEC_BW_40))
-#define BW_LE80(bw)		(BW_LE40(bw) || ((bw) == WL_CHANSPEC_BW_80))
-#define BW_LE160(bw)		(BW_LE80(bw) || ((bw) == WL_CHANSPEC_BW_160))
-#define CHSPEC_BW_LE20(chspec)	(BW_LE20(CHSPEC_BW(chspec)))
-#define CHSPEC_IS5G(chspec)	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
-#define CHSPEC_IS2G(chspec)	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
-#define CHSPEC_SB_UPPER(chspec)	\
-	((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \
-	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
-#define CHSPEC_SB_LOWER(chspec)	\
-	((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \
-	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
-#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G)
-
-/**
- * Number of chars needed for wf_chspec_ntoa() destination character buffer.
- */
-#define CHANSPEC_STR_LEN    20
-
-
-#define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\
-	CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080)
-
-/* BW inequality comparisons, LE (<=), GE (>=), LT (<), GT (>), comparisons can be made
-* as simple numeric comparisons, with the exception that 160 is the same BW as 80+80,
-* but have different numeric values; (WL_CHANSPEC_BW_160 < WL_CHANSPEC_BW_8080).
-*
-* The LT/LE/GT/GE macros check first checks whether both chspec bandwidth and bw are 160 wide.
-* If both chspec bandwidth and bw is not 160 wide, then the comparison is made.
-*/
-#ifdef WL11ULB
-#define CHSPEC_BW_GE(chspec, bw) \
-	(((CHSPEC_IS_BW_160_WIDE(chspec) &&\
-	((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
-	(CHSPEC_BW(chspec) >= (bw))) && \
-	(!(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5)))
-#else /* WL11ULB */
-#define CHSPEC_BW_GE(chspec, bw) \
-		((CHSPEC_IS_BW_160_WIDE(chspec) &&\
-		((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
-		(CHSPEC_BW(chspec) >= (bw)))
-#endif /* WL11ULB */
-
-#ifdef WL11ULB
-#define CHSPEC_BW_LE(chspec, bw) \
-	(((CHSPEC_IS_BW_160_WIDE(chspec) &&\
-	((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
-	(CHSPEC_BW(chspec) <= (bw))) || \
-	(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5))
-#else /* WL11ULB */
-#define CHSPEC_BW_LE(chspec, bw) \
-		((CHSPEC_IS_BW_160_WIDE(chspec) &&\
-		((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
-		(CHSPEC_BW(chspec) <= (bw)))
-#endif /* WL11ULB */
-
-#ifdef WL11ULB
-#define CHSPEC_BW_GT(chspec, bw) \
-	((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
-	((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
-	(CHSPEC_BW(chspec) > (bw))) && \
-	(CHSPEC_BW(chspec) != WL_CHANSPEC_BW_2P5))
-#else /* WL11ULB */
-#define CHSPEC_BW_GT(chspec, bw) \
-		(!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
-		((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
-		(CHSPEC_BW(chspec) > (bw)))
-#endif /* WL11ULB */
-
-#ifdef WL11ULB
-#define CHSPEC_BW_LT(chspec, bw) \
-	((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
-	((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
-	(CHSPEC_BW(chspec) < (bw))) || \
-	((CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5)))
-#else /* WL11ULB */
-#define CHSPEC_BW_LT(chspec, bw) \
-		(!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
-		((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
-		(CHSPEC_BW(chspec) < (bw)))
-#endif /* WL11ULB */
-
-/* Legacy Chanspec defines
- * These are the defines for the previous format of the chanspec_t
- */
-#define WL_LCHANSPEC_CHAN_MASK		0x00ff
-#define WL_LCHANSPEC_CHAN_SHIFT		     0
-
-#define WL_LCHANSPEC_CTL_SB_MASK	0x0300
-#define WL_LCHANSPEC_CTL_SB_SHIFT	     8
-#define WL_LCHANSPEC_CTL_SB_LOWER	0x0100
-#define WL_LCHANSPEC_CTL_SB_UPPER	0x0200
-#define WL_LCHANSPEC_CTL_SB_NONE	0x0300
-
-#define WL_LCHANSPEC_BW_MASK		0x0C00
-#define WL_LCHANSPEC_BW_SHIFT		    10
-#define WL_LCHANSPEC_BW_10		0x0400
-#define WL_LCHANSPEC_BW_20		0x0800
-#define WL_LCHANSPEC_BW_40		0x0C00
-
-#define WL_LCHANSPEC_BAND_MASK		0xf000
-#define WL_LCHANSPEC_BAND_SHIFT		    12
-#define WL_LCHANSPEC_BAND_5G		0x1000
-#define WL_LCHANSPEC_BAND_2G		0x2000
-
-#define LCHSPEC_CHANNEL(chspec)	((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK))
-#define LCHSPEC_BAND(chspec)	((chspec) & WL_LCHANSPEC_BAND_MASK)
-#define LCHSPEC_CTL_SB(chspec)	((chspec) & WL_LCHANSPEC_CTL_SB_MASK)
-#define LCHSPEC_BW(chspec)	((chspec) & WL_LCHANSPEC_BW_MASK)
-#define LCHSPEC_IS10(chspec)	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10)
-#define LCHSPEC_IS20(chspec)	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20)
-#define LCHSPEC_IS40(chspec)	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)
-#define LCHSPEC_IS5G(chspec)	(((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G)
-#define LCHSPEC_IS2G(chspec)	(((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G)
-
-#define LCHSPEC_SB_UPPER(chspec)	\
-	((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \
-	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
-#define LCHSPEC_SB_LOWER(chspec)	\
-	((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \
-	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
-
-#define LCHSPEC_CREATE(chan, band, bw, sb)  ((uint16)((chan) | (sb) | (bw) | (band)))
-
-#define CH20MHZ_LCHSPEC(channel) \
-	(chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \
-	WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
-	WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G))
-
-/*
- * WF_CHAN_FACTOR_* constants are used to calculate channel frequency
- * given a channel number.
- * chan_freq = chan_factor * 500Mhz + chan_number * 5
- */
-
-/**
- * Channel Factor for the starting frequence of 2.4 GHz channels.
- * The value corresponds to 2407 MHz.
- */
-#define WF_CHAN_FACTOR_2_4_G		4814	/* 2.4 GHz band, 2407 MHz */
-
-/**
- * Channel Factor for the starting frequence of 5 GHz channels.
- * The value corresponds to 5000 MHz.
- */
-#define WF_CHAN_FACTOR_5_G		10000	/* 5   GHz band, 5000 MHz */
-
-/**
- * Channel Factor for the starting frequence of 4.9 GHz channels.
- * The value corresponds to 4000 MHz.
- */
-#define WF_CHAN_FACTOR_4_G		8000	/* 4.9 GHz band for Japan */
-
-#define WLC_2G_25MHZ_OFFSET		5	/* 2.4GHz band channel offset */
-
-/**
- *  No of sub-band vlaue of the specified Mhz chanspec
- */
-#define WF_NUM_SIDEBANDS_40MHZ   2
-#define WF_NUM_SIDEBANDS_80MHZ   4
-#define WF_NUM_SIDEBANDS_8080MHZ 4
-#define WF_NUM_SIDEBANDS_160MHZ  8
-
-/**
- * Convert chanspec to ascii string
- *
- * @param	chspec		chanspec format
- * @param	buf		ascii string of chanspec
- *
- * @return	pointer to buf with room for at least CHANSPEC_STR_LEN bytes
- *		Original chanspec in case of error
- *
- * @see		CHANSPEC_STR_LEN
- */
-extern char * wf_chspec_ntoa_ex(chanspec_t chspec, char *buf);
-
-/**
- * Convert chanspec to ascii string
- *
- * @param	chspec		chanspec format
- * @param	buf		ascii string of chanspec
- *
- * @return	pointer to buf with room for at least CHANSPEC_STR_LEN bytes
- *		NULL in case of error
- *
- * @see		CHANSPEC_STR_LEN
- */
-extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf);
-
-/**
- * Convert ascii string to chanspec
- *
- * @param	a     pointer to input string
- *
- * @return	>= 0 if successful or 0 otherwise
- */
-extern chanspec_t wf_chspec_aton(const char *a);
-
-/**
- * Verify the chanspec fields are valid.
- *
- * Verify the chanspec is using a legal set field values, i.e. that the chanspec
- * specified a band, bw, ctl_sb and channel and that the combination could be
- * legal given some set of circumstances.
- *
- * @param	chanspec   input chanspec to verify
- *
- * @return TRUE if the chanspec is malformed, FALSE if it looks good.
- */
-extern bool wf_chspec_malformed(chanspec_t chanspec);
-
-/**
- * Verify the chanspec specifies a valid channel according to 802.11.
- *
- * @param	chanspec   input chanspec to verify
- *
- * @return TRUE if the chanspec is a valid 802.11 channel
- */
-extern bool wf_chspec_valid(chanspec_t chanspec);
-
-/**
- * Return the primary (control) channel.
- *
- * This function returns the channel number of the primary 20MHz channel. For
- * 20MHz channels this is just the channel number. For 40MHz or wider channels
- * it is the primary 20MHz channel specified by the chanspec.
- *
- * @param	chspec    input chanspec
- *
- * @return Returns the channel number of the primary 20MHz channel
- */
-extern uint8 wf_chspec_ctlchan(chanspec_t chspec);
-
-/*
- * Return the bandwidth string.
- *
- * This function returns the bandwidth string for the passed chanspec.
- *
- * @param	chspec    input chanspec
- *
- * @return Returns the bandwidth string
- */
-extern char * wf_chspec_to_bw_str(chanspec_t chspec);
-
-/**
- * Return the primary (control) chanspec.
- *
- * This function returns the chanspec of the primary 20MHz channel. For 20MHz
- * channels this is just the chanspec. For 40MHz or wider channels it is the
- * chanspec of the primary 20MHZ channel specified by the chanspec.
- *
- * @param	chspec    input chanspec
- *
- * @return Returns the chanspec of the primary 20MHz channel
- */
-extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec);
-
-/**
- * Return a channel number corresponding to a frequency.
- *
- * This function returns the chanspec for the primary 40MHz of an 80MHz channel.
- * The control sideband specifies the same 20MHz channel that the 80MHz channel is using
- * as the primary 20MHz channel.
- */
-extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec);
-
-/*
- * Return the channel number for a given frequency and base frequency.
- * The returned channel number is relative to the given base frequency.
- * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
- * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
- *
- * Frequency is specified in MHz.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- *
- * The returned channel will be in the range [1, 14] in the 2.4 GHz band
- * and [0, 200] otherwise.
- * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
- * frequency is not a 2.4 GHz channel, or if the frequency is not and even
- * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- *
- * @param	freq          frequency in MHz
- * @param	start_factor  base frequency in 500 kHz units, e.g. 10000 for 5 GHz
- *
- * @return Returns a channel number
- *
- * @see  WF_CHAN_FACTOR_2_4_G
- * @see  WF_CHAN_FACTOR_5_G
- */
-extern int wf_mhz2channel(uint freq, uint start_factor);
-
-/**
- * Return the center frequency in MHz of the given channel and base frequency.
- *
- * Return the center frequency in MHz of the given channel and base frequency.
- * The channel number is interpreted relative to the given base frequency.
- *
- * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- * The channel range of [1, 14] is only checked for a start_factor of
- * WF_CHAN_FACTOR_2_4_G (4814).
- * Odd start_factors produce channels on .5 MHz boundaries, in which case
- * the answer is rounded down to an integral MHz.
- * -1 is returned for an out of range channel.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- *
- * @param	channel       input channel number
- * @param	start_factor  base frequency in 500 kHz units, e.g. 10000 for 5 GHz
- *
- * @return Returns a frequency in MHz
- *
- * @see  WF_CHAN_FACTOR_2_4_G
- * @see  WF_CHAN_FACTOR_5_G
- */
-extern int wf_channel2mhz(uint channel, uint start_factor);
-
-/**
- * Returns the chanspec 80Mhz channel corresponding to the following input
- * parameters
- *
- *	primary_channel - primary 20Mhz channel
- *	center_channel   - center frequecny of the 80Mhz channel
- *
- * The center_channel can be one of {42, 58, 106, 122, 138, 155}
- *
- * returns INVCHANSPEC in case of error
- */
-extern chanspec_t wf_chspec_80(uint8 center_channel, uint8 primary_channel);
-
-/**
- * Convert ctl chan and bw to chanspec
- *
- * @param	ctl_ch		channel
- * @param	bw	        bandwidth
- *
- * @return	> 0 if successful or 0 otherwise
- *
- */
-extern uint16 wf_channel2chspec(uint ctl_ch, uint bw);
-
-extern uint wf_channel2freq(uint channel);
-extern uint wf_freq2channel(uint freq);
-
-/*
- * Returns the 80+80 MHz chanspec corresponding to the following input parameters
- *
- *    primary_20mhz - Primary 20 MHz channel
- *    chan0_80MHz - center channel number of one frequency segment
- *    chan1_80MHz - center channel number of the other frequency segment
- *
- * Parameters chan0_80MHz and chan1_80MHz are channel numbers in {42, 58, 106, 122, 138, 155}.
- * The primary channel must be contained in one of the 80MHz channels. This routine
- * will determine which frequency segment is the primary 80 MHz segment.
- *
- * Returns INVCHANSPEC in case of error.
- *
- * Refer to IEEE802.11ac section 22.3.14 "Channelization".
- */
-extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz,
-	uint8 chan0_80Mhz, uint8 chan1_80Mhz);
-
-/*
- * Returns the primary 80 Mhz channel for the provided chanspec
- *
- *    chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
- *
- *  returns -1 in case the provided channel is 20/40 Mhz chanspec
- */
-extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec);
-
-/*
- * Returns the secondary 80 Mhz channel for the provided chanspec
- *
- *    chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
- *
- *  returns -1 in case the provided channel is 20/40 Mhz chanspec
- */
-extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec);
-
-/*
- * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
- */
-extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec);
-
-#ifdef WL11AC_80P80
-/*
- * This function returns the centre chanel for the given chanspec.
- * In case of 80+80 chanspec it returns the primary 80 Mhz centre channel
- */
-extern uint8 wf_chspec_channel(chanspec_t chspec);
-#endif
-#endif	/* _bcmwifi_channels_h_ */
diff --git a/drivers/net/wireless/bcmdhd/bcmwifi_rates.h b/drivers/net/wireless/bcmdhd/bcmwifi_rates.h
deleted file mode 100644
index 1329e9b..0000000
--- a/drivers/net/wireless/bcmdhd/bcmwifi_rates.h
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmwifi_rates.h 591285 2015-10-07 11:56:29Z $
- */
-
-#ifndef _bcmwifi_rates_h_
-#define _bcmwifi_rates_h_
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define WL_RATESET_SZ_DSSS		4
-#define WL_RATESET_SZ_OFDM		8
-#define WL_RATESET_SZ_VHT_MCS	10
-#define WL_RATESET_SZ_VHT_MCS_P	12
-
-#if defined(WLPROPRIETARY_11N_RATES)
-#define WL_RATESET_SZ_HT_MCS	WL_RATESET_SZ_VHT_MCS
-#else
-#define WL_RATESET_SZ_HT_MCS	8
-#endif
-
-#define WL_RATESET_SZ_HT_IOCTL	8	/* MAC histogram, compatibility with wl utility */
-
-#define WL_TX_CHAINS_MAX		4
-
-#define WL_RATE_DISABLED		(-128) /* Power value corresponding to unsupported rate */
-
-/* Transmit channel bandwidths */
-typedef enum wl_tx_bw {
-	WL_TX_BW_20,
-	WL_TX_BW_40,
-	WL_TX_BW_80,
-	WL_TX_BW_20IN40,
-	WL_TX_BW_20IN80,
-	WL_TX_BW_40IN80,
-	WL_TX_BW_160,
-	WL_TX_BW_20IN160,
-	WL_TX_BW_40IN160,
-	WL_TX_BW_80IN160,
-	WL_TX_BW_ALL,
-	WL_TX_BW_8080,
-	WL_TX_BW_8080CHAN2,
-	WL_TX_BW_20IN8080,
-	WL_TX_BW_40IN8080,
-	WL_TX_BW_80IN8080,
-	WL_TX_BW_2P5,
-	WL_TX_BW_5,
-	WL_TX_BW_10
-} wl_tx_bw_t;
-
-
-/*
- * Transmit modes.
- * Not all modes are listed here, only those required for disambiguation. e.g. SPEXP is not listed
- */
-typedef enum wl_tx_mode {
-	WL_TX_MODE_NONE,
-	WL_TX_MODE_STBC,
-	WL_TX_MODE_CDD,
-	WL_TX_MODE_TXBF,
-	WL_NUM_TX_MODES
-} wl_tx_mode_t;
-
-
-/* Number of transmit chains */
-typedef enum wl_tx_chains {
-	WL_TX_CHAINS_1 = 1,
-	WL_TX_CHAINS_2,
-	WL_TX_CHAINS_3,
-	WL_TX_CHAINS_4
-} wl_tx_chains_t;
-
-
-/* Number of transmit streams */
-typedef enum wl_tx_nss {
-	WL_TX_NSS_1 = 1,
-	WL_TX_NSS_2,
-	WL_TX_NSS_3,
-	WL_TX_NSS_4
-} wl_tx_nss_t;
-
-
-/* This enum maps each rate to a CLM index */
-
-typedef enum clm_rates {
-	/************
-	* 1 chain  *
-	************
-	*/
-
-	/* 1 Stream */
-	WL_RATE_1X1_DSSS_1            = 0,
-	WL_RATE_1X1_DSSS_2            = 1,
-	WL_RATE_1X1_DSSS_5_5          = 2,
-	WL_RATE_1X1_DSSS_11           = 3,
-
-	WL_RATE_1X1_OFDM_6            = 4,
-	WL_RATE_1X1_OFDM_9            = 5,
-	WL_RATE_1X1_OFDM_12           = 6,
-	WL_RATE_1X1_OFDM_18           = 7,
-	WL_RATE_1X1_OFDM_24           = 8,
-	WL_RATE_1X1_OFDM_36           = 9,
-	WL_RATE_1X1_OFDM_48           = 10,
-	WL_RATE_1X1_OFDM_54           = 11,
-
-	WL_RATE_1X1_MCS0              = 12,
-	WL_RATE_1X1_MCS1              = 13,
-	WL_RATE_1X1_MCS2              = 14,
-	WL_RATE_1X1_MCS3              = 15,
-	WL_RATE_1X1_MCS4              = 16,
-	WL_RATE_1X1_MCS5              = 17,
-	WL_RATE_1X1_MCS6              = 18,
-	WL_RATE_1X1_MCS7              = 19,
-	WL_RATE_P_1X1_MCS87           = 20,
-	WL_RATE_P_1X1_MCS88           = 21,
-
-	WL_RATE_1X1_VHT0SS1           = 12,
-	WL_RATE_1X1_VHT1SS1           = 13,
-	WL_RATE_1X1_VHT2SS1           = 14,
-	WL_RATE_1X1_VHT3SS1           = 15,
-	WL_RATE_1X1_VHT4SS1           = 16,
-	WL_RATE_1X1_VHT5SS1           = 17,
-	WL_RATE_1X1_VHT6SS1           = 18,
-	WL_RATE_1X1_VHT7SS1           = 19,
-	WL_RATE_1X1_VHT8SS1           = 20,
-	WL_RATE_1X1_VHT9SS1           = 21,
-	WL_RATE_P_1X1_VHT10SS1        = 22,
-	WL_RATE_P_1X1_VHT11SS1        = 23,
-
-
-	/************
-	* 2 chains *
-	************
-	*/
-
-	/* 1 Stream expanded + 1 */
-	WL_RATE_1X2_DSSS_1            = 24,
-	WL_RATE_1X2_DSSS_2            = 25,
-	WL_RATE_1X2_DSSS_5_5          = 26,
-	WL_RATE_1X2_DSSS_11           = 27,
-
-	WL_RATE_1X2_CDD_OFDM_6        = 28,
-	WL_RATE_1X2_CDD_OFDM_9        = 29,
-	WL_RATE_1X2_CDD_OFDM_12       = 30,
-	WL_RATE_1X2_CDD_OFDM_18       = 31,
-	WL_RATE_1X2_CDD_OFDM_24       = 32,
-	WL_RATE_1X2_CDD_OFDM_36       = 33,
-	WL_RATE_1X2_CDD_OFDM_48       = 34,
-	WL_RATE_1X2_CDD_OFDM_54       = 35,
-
-	WL_RATE_1X2_CDD_MCS0          = 36,
-	WL_RATE_1X2_CDD_MCS1          = 37,
-	WL_RATE_1X2_CDD_MCS2          = 38,
-	WL_RATE_1X2_CDD_MCS3          = 39,
-	WL_RATE_1X2_CDD_MCS4          = 40,
-	WL_RATE_1X2_CDD_MCS5          = 41,
-	WL_RATE_1X2_CDD_MCS6          = 42,
-	WL_RATE_1X2_CDD_MCS7          = 43,
-	WL_RATE_P_1X2_CDD_MCS87       = 44,
-	WL_RATE_P_1X2_CDD_MCS88       = 45,
-
-	WL_RATE_1X2_VHT0SS1           = 36,
-	WL_RATE_1X2_VHT1SS1           = 37,
-	WL_RATE_1X2_VHT2SS1           = 38,
-	WL_RATE_1X2_VHT3SS1           = 39,
-	WL_RATE_1X2_VHT4SS1           = 40,
-	WL_RATE_1X2_VHT5SS1           = 41,
-	WL_RATE_1X2_VHT6SS1           = 42,
-	WL_RATE_1X2_VHT7SS1           = 43,
-	WL_RATE_1X2_VHT8SS1           = 44,
-	WL_RATE_1X2_VHT9SS1           = 45,
-	WL_RATE_P_1X2_VHT10SS1        = 46,
-	WL_RATE_P_1X2_VHT11SS1        = 47,
-
-	/* 2 Streams */
-	WL_RATE_2X2_STBC_MCS0         = 48,
-	WL_RATE_2X2_STBC_MCS1         = 49,
-	WL_RATE_2X2_STBC_MCS2         = 50,
-	WL_RATE_2X2_STBC_MCS3         = 51,
-	WL_RATE_2X2_STBC_MCS4         = 52,
-	WL_RATE_2X2_STBC_MCS5         = 53,
-	WL_RATE_2X2_STBC_MCS6         = 54,
-	WL_RATE_2X2_STBC_MCS7         = 55,
-	WL_RATE_P_2X2_STBC_MCS87      = 56,
-	WL_RATE_P_2X2_STBC_MCS88      = 57,
-
-	WL_RATE_2X2_STBC_VHT0SS1      = 48,
-	WL_RATE_2X2_STBC_VHT1SS1      = 49,
-	WL_RATE_2X2_STBC_VHT2SS1      = 50,
-	WL_RATE_2X2_STBC_VHT3SS1      = 51,
-	WL_RATE_2X2_STBC_VHT4SS1      = 52,
-	WL_RATE_2X2_STBC_VHT5SS1      = 53,
-	WL_RATE_2X2_STBC_VHT6SS1      = 54,
-	WL_RATE_2X2_STBC_VHT7SS1      = 55,
-	WL_RATE_2X2_STBC_VHT8SS1      = 56,
-	WL_RATE_2X2_STBC_VHT9SS1      = 57,
-	WL_RATE_P_2X2_STBC_VHT10SS1   = 58,
-	WL_RATE_P_2X2_STBC_VHT11SS1   = 59,
-
-	WL_RATE_2X2_SDM_MCS8          = 60,
-	WL_RATE_2X2_SDM_MCS9          = 61,
-	WL_RATE_2X2_SDM_MCS10         = 62,
-	WL_RATE_2X2_SDM_MCS11         = 63,
-	WL_RATE_2X2_SDM_MCS12         = 64,
-	WL_RATE_2X2_SDM_MCS13         = 65,
-	WL_RATE_2X2_SDM_MCS14         = 66,
-	WL_RATE_2X2_SDM_MCS15         = 67,
-	WL_RATE_P_2X2_SDM_MCS99       = 68,
-	WL_RATE_P_2X2_SDM_MCS100      = 69,
-
-	WL_RATE_2X2_VHT0SS2           = 60,
-	WL_RATE_2X2_VHT1SS2           = 61,
-	WL_RATE_2X2_VHT2SS2           = 62,
-	WL_RATE_2X2_VHT3SS2           = 63,
-	WL_RATE_2X2_VHT4SS2           = 64,
-	WL_RATE_2X2_VHT5SS2           = 65,
-	WL_RATE_2X2_VHT6SS2           = 66,
-	WL_RATE_2X2_VHT7SS2           = 67,
-	WL_RATE_2X2_VHT8SS2           = 68,
-	WL_RATE_2X2_VHT9SS2           = 69,
-	WL_RATE_P_2X2_VHT10SS2        = 70,
-	WL_RATE_P_2X2_VHT11SS2        = 71,
-
-	/****************************
-	 * TX Beamforming, 2 chains *
-	 ****************************
-	 */
-
-	/* 1 Stream expanded + 1 */
-	WL_RATE_1X2_TXBF_OFDM_6       = 72,
-	WL_RATE_1X2_TXBF_OFDM_9       = 73,
-	WL_RATE_1X2_TXBF_OFDM_12      = 74,
-	WL_RATE_1X2_TXBF_OFDM_18      = 75,
-	WL_RATE_1X2_TXBF_OFDM_24      = 76,
-	WL_RATE_1X2_TXBF_OFDM_36      = 77,
-	WL_RATE_1X2_TXBF_OFDM_48      = 78,
-	WL_RATE_1X2_TXBF_OFDM_54      = 79,
-
-	WL_RATE_1X2_TXBF_MCS0         = 80,
-	WL_RATE_1X2_TXBF_MCS1         = 81,
-	WL_RATE_1X2_TXBF_MCS2         = 82,
-	WL_RATE_1X2_TXBF_MCS3         = 83,
-	WL_RATE_1X2_TXBF_MCS4         = 84,
-	WL_RATE_1X2_TXBF_MCS5         = 85,
-	WL_RATE_1X2_TXBF_MCS6         = 86,
-	WL_RATE_1X2_TXBF_MCS7         = 87,
-	WL_RATE_P_1X2_TXBF_MCS87      = 88,
-	WL_RATE_P_1X2_TXBF_MCS88      = 89,
-
-	WL_RATE_1X2_TXBF_VHT0SS1      = 80,
-	WL_RATE_1X2_TXBF_VHT1SS1      = 81,
-	WL_RATE_1X2_TXBF_VHT2SS1      = 82,
-	WL_RATE_1X2_TXBF_VHT3SS1      = 83,
-	WL_RATE_1X2_TXBF_VHT4SS1      = 84,
-	WL_RATE_1X2_TXBF_VHT5SS1      = 85,
-	WL_RATE_1X2_TXBF_VHT6SS1      = 86,
-	WL_RATE_1X2_TXBF_VHT7SS1      = 87,
-	WL_RATE_1X2_TXBF_VHT8SS1      = 88,
-	WL_RATE_1X2_TXBF_VHT9SS1      = 89,
-	WL_RATE_P_1X2_TXBF_VHT10SS1   = 90,
-	WL_RATE_P_1X2_TXBF_VHT11SS1   = 91,
-
-	/* 2 Streams */
-	WL_RATE_2X2_TXBF_SDM_MCS8     = 92,
-	WL_RATE_2X2_TXBF_SDM_MCS9     = 93,
-	WL_RATE_2X2_TXBF_SDM_MCS10    = 94,
-	WL_RATE_2X2_TXBF_SDM_MCS11    = 95,
-	WL_RATE_2X2_TXBF_SDM_MCS12    = 96,
-	WL_RATE_2X2_TXBF_SDM_MCS13    = 97,
-	WL_RATE_2X2_TXBF_SDM_MCS14    = 98,
-	WL_RATE_2X2_TXBF_SDM_MCS15    = 99,
-	WL_RATE_P_2X2_TXBF_SDM_MCS99  = 100,
-	WL_RATE_P_2X2_TXBF_SDM_MCS100 = 101,
-
-	WL_RATE_2X2_TXBF_VHT0SS2      = 92,
-	WL_RATE_2X2_TXBF_VHT1SS2      = 93,
-	WL_RATE_2X2_TXBF_VHT2SS2      = 94,
-	WL_RATE_2X2_TXBF_VHT3SS2      = 95,
-	WL_RATE_2X2_TXBF_VHT4SS2      = 96,
-	WL_RATE_2X2_TXBF_VHT5SS2      = 97,
-	WL_RATE_2X2_TXBF_VHT6SS2      = 98,
-	WL_RATE_2X2_TXBF_VHT7SS2      = 99,
-	WL_RATE_2X2_TXBF_VHT8SS2      = 100,
-	WL_RATE_2X2_TXBF_VHT9SS2      = 101,
-	WL_RATE_P_2X2_TXBF_VHT10SS2   = 102,
-	WL_RATE_P_2X2_TXBF_VHT11SS2   = 103,
-
-
-	/************
-	* 3 chains *
-	************
-	*/
-
-	/* 1 Stream expanded + 2 */
-	WL_RATE_1X3_DSSS_1            = 104,
-	WL_RATE_1X3_DSSS_2            = 105,
-	WL_RATE_1X3_DSSS_5_5          = 106,
-	WL_RATE_1X3_DSSS_11           = 107,
-
-	WL_RATE_1X3_CDD_OFDM_6        = 108,
-	WL_RATE_1X3_CDD_OFDM_9        = 109,
-	WL_RATE_1X3_CDD_OFDM_12       = 110,
-	WL_RATE_1X3_CDD_OFDM_18       = 111,
-	WL_RATE_1X3_CDD_OFDM_24       = 112,
-	WL_RATE_1X3_CDD_OFDM_36       = 113,
-	WL_RATE_1X3_CDD_OFDM_48       = 114,
-	WL_RATE_1X3_CDD_OFDM_54       = 115,
-
-	WL_RATE_1X3_CDD_MCS0          = 116,
-	WL_RATE_1X3_CDD_MCS1          = 117,
-	WL_RATE_1X3_CDD_MCS2          = 118,
-	WL_RATE_1X3_CDD_MCS3          = 119,
-	WL_RATE_1X3_CDD_MCS4          = 120,
-	WL_RATE_1X3_CDD_MCS5          = 121,
-	WL_RATE_1X3_CDD_MCS6          = 122,
-	WL_RATE_1X3_CDD_MCS7          = 123,
-	WL_RATE_P_1X3_CDD_MCS87       = 124,
-	WL_RATE_P_1X3_CDD_MCS88       = 125,
-
-	WL_RATE_1X3_VHT0SS1           = 116,
-	WL_RATE_1X3_VHT1SS1           = 117,
-	WL_RATE_1X3_VHT2SS1           = 118,
-	WL_RATE_1X3_VHT3SS1           = 119,
-	WL_RATE_1X3_VHT4SS1           = 120,
-	WL_RATE_1X3_VHT5SS1           = 121,
-	WL_RATE_1X3_VHT6SS1           = 122,
-	WL_RATE_1X3_VHT7SS1           = 123,
-	WL_RATE_1X3_VHT8SS1           = 124,
-	WL_RATE_1X3_VHT9SS1           = 125,
-	WL_RATE_P_1X3_VHT10SS1        = 126,
-	WL_RATE_P_1X3_VHT11SS1        = 127,
-
-	/* 2 Streams expanded + 1 */
-	WL_RATE_2X3_STBC_MCS0         = 128,
-	WL_RATE_2X3_STBC_MCS1         = 129,
-	WL_RATE_2X3_STBC_MCS2         = 130,
-	WL_RATE_2X3_STBC_MCS3         = 131,
-	WL_RATE_2X3_STBC_MCS4         = 132,
-	WL_RATE_2X3_STBC_MCS5         = 133,
-	WL_RATE_2X3_STBC_MCS6         = 134,
-	WL_RATE_2X3_STBC_MCS7         = 135,
-	WL_RATE_P_2X3_STBC_MCS87      = 136,
-	WL_RATE_P_2X3_STBC_MCS88      = 137,
-
-	WL_RATE_2X3_STBC_VHT0SS1      = 128,
-	WL_RATE_2X3_STBC_VHT1SS1      = 129,
-	WL_RATE_2X3_STBC_VHT2SS1      = 130,
-	WL_RATE_2X3_STBC_VHT3SS1      = 131,
-	WL_RATE_2X3_STBC_VHT4SS1      = 132,
-	WL_RATE_2X3_STBC_VHT5SS1      = 133,
-	WL_RATE_2X3_STBC_VHT6SS1      = 134,
-	WL_RATE_2X3_STBC_VHT7SS1      = 135,
-	WL_RATE_2X3_STBC_VHT8SS1      = 136,
-	WL_RATE_2X3_STBC_VHT9SS1      = 137,
-	WL_RATE_P_2X3_STBC_VHT10SS1   = 138,
-	WL_RATE_P_2X3_STBC_VHT11SS1   = 139,
-
-	WL_RATE_2X3_SDM_MCS8          = 140,
-	WL_RATE_2X3_SDM_MCS9          = 141,
-	WL_RATE_2X3_SDM_MCS10         = 142,
-	WL_RATE_2X3_SDM_MCS11         = 143,
-	WL_RATE_2X3_SDM_MCS12         = 144,
-	WL_RATE_2X3_SDM_MCS13         = 145,
-	WL_RATE_2X3_SDM_MCS14         = 146,
-	WL_RATE_2X3_SDM_MCS15         = 147,
-	WL_RATE_P_2X3_SDM_MCS99       = 148,
-	WL_RATE_P_2X3_SDM_MCS100      = 149,
-
-	WL_RATE_2X3_VHT0SS2           = 140,
-	WL_RATE_2X3_VHT1SS2           = 141,
-	WL_RATE_2X3_VHT2SS2           = 142,
-	WL_RATE_2X3_VHT3SS2           = 143,
-	WL_RATE_2X3_VHT4SS2           = 144,
-	WL_RATE_2X3_VHT5SS2           = 145,
-	WL_RATE_2X3_VHT6SS2           = 146,
-	WL_RATE_2X3_VHT7SS2           = 147,
-	WL_RATE_2X3_VHT8SS2           = 148,
-	WL_RATE_2X3_VHT9SS2           = 149,
-	WL_RATE_P_2X3_VHT10SS2        = 150,
-	WL_RATE_P_2X3_VHT11SS2        = 151,
-
-	/* 3 Streams */
-	WL_RATE_3X3_SDM_MCS16         = 152,
-	WL_RATE_3X3_SDM_MCS17         = 153,
-	WL_RATE_3X3_SDM_MCS18         = 154,
-	WL_RATE_3X3_SDM_MCS19         = 155,
-	WL_RATE_3X3_SDM_MCS20         = 156,
-	WL_RATE_3X3_SDM_MCS21         = 157,
-	WL_RATE_3X3_SDM_MCS22         = 158,
-	WL_RATE_3X3_SDM_MCS23         = 159,
-	WL_RATE_P_3X3_SDM_MCS101      = 160,
-	WL_RATE_P_3X3_SDM_MCS102      = 161,
-
-	WL_RATE_3X3_VHT0SS3           = 152,
-	WL_RATE_3X3_VHT1SS3           = 153,
-	WL_RATE_3X3_VHT2SS3           = 154,
-	WL_RATE_3X3_VHT3SS3           = 155,
-	WL_RATE_3X3_VHT4SS3           = 156,
-	WL_RATE_3X3_VHT5SS3           = 157,
-	WL_RATE_3X3_VHT6SS3           = 158,
-	WL_RATE_3X3_VHT7SS3           = 159,
-	WL_RATE_3X3_VHT8SS3           = 160,
-	WL_RATE_3X3_VHT9SS3           = 161,
-	WL_RATE_P_3X3_VHT10SS3        = 162,
-	WL_RATE_P_3X3_VHT11SS3        = 163,
-
-
-	/****************************
-	 * TX Beamforming, 3 chains *
-	 ****************************
-	 */
-
-	/* 1 Stream expanded + 2 */
-	WL_RATE_1X3_TXBF_OFDM_6       = 164,
-	WL_RATE_1X3_TXBF_OFDM_9       = 165,
-	WL_RATE_1X3_TXBF_OFDM_12      = 166,
-	WL_RATE_1X3_TXBF_OFDM_18      = 167,
-	WL_RATE_1X3_TXBF_OFDM_24      = 168,
-	WL_RATE_1X3_TXBF_OFDM_36      = 169,
-	WL_RATE_1X3_TXBF_OFDM_48      = 170,
-	WL_RATE_1X3_TXBF_OFDM_54      = 171,
-
-	WL_RATE_1X3_TXBF_MCS0         = 172,
-	WL_RATE_1X3_TXBF_MCS1         = 173,
-	WL_RATE_1X3_TXBF_MCS2         = 174,
-	WL_RATE_1X3_TXBF_MCS3         = 175,
-	WL_RATE_1X3_TXBF_MCS4         = 176,
-	WL_RATE_1X3_TXBF_MCS5         = 177,
-	WL_RATE_1X3_TXBF_MCS6         = 178,
-	WL_RATE_1X3_TXBF_MCS7         = 179,
-	WL_RATE_P_1X3_TXBF_MCS87      = 180,
-	WL_RATE_P_1X3_TXBF_MCS88      = 181,
-
-	WL_RATE_1X3_TXBF_VHT0SS1      = 172,
-	WL_RATE_1X3_TXBF_VHT1SS1      = 173,
-	WL_RATE_1X3_TXBF_VHT2SS1      = 174,
-	WL_RATE_1X3_TXBF_VHT3SS1      = 175,
-	WL_RATE_1X3_TXBF_VHT4SS1      = 176,
-	WL_RATE_1X3_TXBF_VHT5SS1      = 177,
-	WL_RATE_1X3_TXBF_VHT6SS1      = 178,
-	WL_RATE_1X3_TXBF_VHT7SS1      = 179,
-	WL_RATE_1X3_TXBF_VHT8SS1      = 180,
-	WL_RATE_1X3_TXBF_VHT9SS1      = 181,
-	WL_RATE_P_1X3_TXBF_VHT10SS1   = 182,
-	WL_RATE_P_1X3_TXBF_VHT11SS1   = 183,
-
-	/* 2 Streams expanded + 1 */
-	WL_RATE_2X3_TXBF_SDM_MCS8     = 184,
-	WL_RATE_2X3_TXBF_SDM_MCS9     = 185,
-	WL_RATE_2X3_TXBF_SDM_MCS10    = 186,
-	WL_RATE_2X3_TXBF_SDM_MCS11    = 187,
-	WL_RATE_2X3_TXBF_SDM_MCS12    = 188,
-	WL_RATE_2X3_TXBF_SDM_MCS13    = 189,
-	WL_RATE_2X3_TXBF_SDM_MCS14    = 190,
-	WL_RATE_2X3_TXBF_SDM_MCS15    = 191,
-	WL_RATE_P_2X3_TXBF_SDM_MCS99  = 192,
-	WL_RATE_P_2X3_TXBF_SDM_MCS100 = 193,
-
-	WL_RATE_2X3_TXBF_VHT0SS2      = 184,
-	WL_RATE_2X3_TXBF_VHT1SS2      = 185,
-	WL_RATE_2X3_TXBF_VHT2SS2      = 186,
-	WL_RATE_2X3_TXBF_VHT3SS2      = 187,
-	WL_RATE_2X3_TXBF_VHT4SS2      = 188,
-	WL_RATE_2X3_TXBF_VHT5SS2      = 189,
-	WL_RATE_2X3_TXBF_VHT6SS2      = 190,
-	WL_RATE_2X3_TXBF_VHT7SS2      = 191,
-	WL_RATE_2X3_TXBF_VHT8SS2      = 192,
-	WL_RATE_2X3_TXBF_VHT9SS2      = 193,
-	WL_RATE_P_2X3_TXBF_VHT10SS2   = 194,
-	WL_RATE_P_2X3_TXBF_VHT11SS2   = 195,
-
-	/* 3 Streams */
-	WL_RATE_3X3_TXBF_SDM_MCS16    = 196,
-	WL_RATE_3X3_TXBF_SDM_MCS17    = 197,
-	WL_RATE_3X3_TXBF_SDM_MCS18    = 198,
-	WL_RATE_3X3_TXBF_SDM_MCS19    = 199,
-	WL_RATE_3X3_TXBF_SDM_MCS20    = 200,
-	WL_RATE_3X3_TXBF_SDM_MCS21    = 201,
-	WL_RATE_3X3_TXBF_SDM_MCS22    = 202,
-	WL_RATE_3X3_TXBF_SDM_MCS23    = 203,
-	WL_RATE_P_3X3_TXBF_SDM_MCS101 = 204,
-	WL_RATE_P_3X3_TXBF_SDM_MCS102 = 205,
-
-	WL_RATE_3X3_TXBF_VHT0SS3      = 196,
-	WL_RATE_3X3_TXBF_VHT1SS3      = 197,
-	WL_RATE_3X3_TXBF_VHT2SS3      = 198,
-	WL_RATE_3X3_TXBF_VHT3SS3      = 199,
-	WL_RATE_3X3_TXBF_VHT4SS3      = 200,
-	WL_RATE_3X3_TXBF_VHT5SS3      = 201,
-	WL_RATE_3X3_TXBF_VHT6SS3      = 202,
-	WL_RATE_3X3_TXBF_VHT7SS3      = 203,
-	WL_RATE_3X3_TXBF_VHT8SS3      = 204,
-	WL_RATE_3X3_TXBF_VHT9SS3      = 205,
-	WL_RATE_P_3X3_TXBF_VHT10SS3   = 206,
-	WL_RATE_P_3X3_TXBF_VHT11SS3   = 207,
-
-
-	/************
-	* 4 chains *
-	************
-	*/
-
-	/* 1 Stream expanded + 3 */
-	WL_RATE_1X4_DSSS_1            = 208,
-	WL_RATE_1X4_DSSS_2            = 209,
-	WL_RATE_1X4_DSSS_5_5          = 210,
-	WL_RATE_1X4_DSSS_11           = 211,
-
-	WL_RATE_1X4_CDD_OFDM_6        = 212,
-	WL_RATE_1X4_CDD_OFDM_9        = 213,
-	WL_RATE_1X4_CDD_OFDM_12       = 214,
-	WL_RATE_1X4_CDD_OFDM_18       = 215,
-	WL_RATE_1X4_CDD_OFDM_24       = 216,
-	WL_RATE_1X4_CDD_OFDM_36       = 217,
-	WL_RATE_1X4_CDD_OFDM_48       = 218,
-	WL_RATE_1X4_CDD_OFDM_54       = 219,
-
-	WL_RATE_1X4_CDD_MCS0          = 220,
-	WL_RATE_1X4_CDD_MCS1          = 221,
-	WL_RATE_1X4_CDD_MCS2          = 222,
-	WL_RATE_1X4_CDD_MCS3          = 223,
-	WL_RATE_1X4_CDD_MCS4          = 224,
-	WL_RATE_1X4_CDD_MCS5          = 225,
-	WL_RATE_1X4_CDD_MCS6          = 226,
-	WL_RATE_1X4_CDD_MCS7          = 227,
-	WL_RATE_P_1X4_CDD_MCS87       = 228,
-	WL_RATE_P_1X4_CDD_MCS88       = 229,
-
-	WL_RATE_1X4_VHT0SS1           = 220,
-	WL_RATE_1X4_VHT1SS1           = 221,
-	WL_RATE_1X4_VHT2SS1           = 222,
-	WL_RATE_1X4_VHT3SS1           = 223,
-	WL_RATE_1X4_VHT4SS1           = 224,
-	WL_RATE_1X4_VHT5SS1           = 225,
-	WL_RATE_1X4_VHT6SS1           = 226,
-	WL_RATE_1X4_VHT7SS1           = 227,
-	WL_RATE_1X4_VHT8SS1           = 228,
-	WL_RATE_1X4_VHT9SS1           = 229,
-	WL_RATE_P_1X4_VHT10SS1        = 230,
-	WL_RATE_P_1X4_VHT11SS1        = 231,
-
-	/* 2 Streams expanded + 2 */
-	WL_RATE_2X4_STBC_MCS0         = 232,
-	WL_RATE_2X4_STBC_MCS1         = 233,
-	WL_RATE_2X4_STBC_MCS2         = 234,
-	WL_RATE_2X4_STBC_MCS3         = 235,
-	WL_RATE_2X4_STBC_MCS4         = 236,
-	WL_RATE_2X4_STBC_MCS5         = 237,
-	WL_RATE_2X4_STBC_MCS6         = 238,
-	WL_RATE_2X4_STBC_MCS7         = 239,
-	WL_RATE_P_2X4_STBC_MCS87      = 240,
-	WL_RATE_P_2X4_STBC_MCS88      = 241,
-
-	WL_RATE_2X4_STBC_VHT0SS1      = 232,
-	WL_RATE_2X4_STBC_VHT1SS1      = 233,
-	WL_RATE_2X4_STBC_VHT2SS1      = 234,
-	WL_RATE_2X4_STBC_VHT3SS1      = 235,
-	WL_RATE_2X4_STBC_VHT4SS1      = 236,
-	WL_RATE_2X4_STBC_VHT5SS1      = 237,
-	WL_RATE_2X4_STBC_VHT6SS1      = 238,
-	WL_RATE_2X4_STBC_VHT7SS1      = 239,
-	WL_RATE_2X4_STBC_VHT8SS1      = 240,
-	WL_RATE_2X4_STBC_VHT9SS1      = 241,
-	WL_RATE_P_2X4_STBC_VHT10SS1   = 242,
-	WL_RATE_P_2X4_STBC_VHT11SS1   = 243,
-
-	WL_RATE_2X4_SDM_MCS8          = 244,
-	WL_RATE_2X4_SDM_MCS9          = 245,
-	WL_RATE_2X4_SDM_MCS10         = 246,
-	WL_RATE_2X4_SDM_MCS11         = 247,
-	WL_RATE_2X4_SDM_MCS12         = 248,
-	WL_RATE_2X4_SDM_MCS13         = 249,
-	WL_RATE_2X4_SDM_MCS14         = 250,
-	WL_RATE_2X4_SDM_MCS15         = 251,
-	WL_RATE_P_2X4_SDM_MCS99       = 252,
-	WL_RATE_P_2X4_SDM_MCS100      = 253,
-
-	WL_RATE_2X4_VHT0SS2           = 244,
-	WL_RATE_2X4_VHT1SS2           = 245,
-	WL_RATE_2X4_VHT2SS2           = 246,
-	WL_RATE_2X4_VHT3SS2           = 247,
-	WL_RATE_2X4_VHT4SS2           = 248,
-	WL_RATE_2X4_VHT5SS2           = 249,
-	WL_RATE_2X4_VHT6SS2           = 250,
-	WL_RATE_2X4_VHT7SS2           = 251,
-	WL_RATE_2X4_VHT8SS2           = 252,
-	WL_RATE_2X4_VHT9SS2           = 253,
-	WL_RATE_P_2X4_VHT10SS2        = 254,
-	WL_RATE_P_2X4_VHT11SS2        = 255,
-
-	/* 3 Streams expanded + 1 */
-	WL_RATE_3X4_SDM_MCS16         = 256,
-	WL_RATE_3X4_SDM_MCS17         = 257,
-	WL_RATE_3X4_SDM_MCS18         = 258,
-	WL_RATE_3X4_SDM_MCS19         = 259,
-	WL_RATE_3X4_SDM_MCS20         = 260,
-	WL_RATE_3X4_SDM_MCS21         = 261,
-	WL_RATE_3X4_SDM_MCS22         = 262,
-	WL_RATE_3X4_SDM_MCS23         = 263,
-	WL_RATE_P_3X4_SDM_MCS101      = 264,
-	WL_RATE_P_3X4_SDM_MCS102      = 265,
-
-	WL_RATE_3X4_VHT0SS3           = 256,
-	WL_RATE_3X4_VHT1SS3           = 257,
-	WL_RATE_3X4_VHT2SS3           = 258,
-	WL_RATE_3X4_VHT3SS3           = 259,
-	WL_RATE_3X4_VHT4SS3           = 260,
-	WL_RATE_3X4_VHT5SS3           = 261,
-	WL_RATE_3X4_VHT6SS3           = 262,
-	WL_RATE_3X4_VHT7SS3           = 263,
-	WL_RATE_3X4_VHT8SS3           = 264,
-	WL_RATE_3X4_VHT9SS3           = 265,
-	WL_RATE_P_3X4_VHT10SS3        = 266,
-	WL_RATE_P_3X4_VHT11SS3        = 267,
-
-
-	/* 4 Streams */
-	WL_RATE_4X4_SDM_MCS24         = 268,
-	WL_RATE_4X4_SDM_MCS25         = 269,
-	WL_RATE_4X4_SDM_MCS26         = 270,
-	WL_RATE_4X4_SDM_MCS27         = 271,
-	WL_RATE_4X4_SDM_MCS28         = 272,
-	WL_RATE_4X4_SDM_MCS29         = 273,
-	WL_RATE_4X4_SDM_MCS30         = 274,
-	WL_RATE_4X4_SDM_MCS31         = 275,
-	WL_RATE_P_4X4_SDM_MCS103      = 276,
-	WL_RATE_P_4X4_SDM_MCS104      = 277,
-
-	WL_RATE_4X4_VHT0SS4           = 268,
-	WL_RATE_4X4_VHT1SS4           = 269,
-	WL_RATE_4X4_VHT2SS4           = 270,
-	WL_RATE_4X4_VHT3SS4           = 271,
-	WL_RATE_4X4_VHT4SS4           = 272,
-	WL_RATE_4X4_VHT5SS4           = 273,
-	WL_RATE_4X4_VHT6SS4           = 274,
-	WL_RATE_4X4_VHT7SS4           = 275,
-	WL_RATE_4X4_VHT8SS4           = 276,
-	WL_RATE_4X4_VHT9SS4           = 277,
-	WL_RATE_P_4X4_VHT10SS4        = 278,
-	WL_RATE_P_4X4_VHT11SS4        = 279,
-
-
-	/****************************
-	 * TX Beamforming, 4 chains *
-	 ****************************
-	 */
-
-	/* 1 Stream expanded + 3 */
-	WL_RATE_1X4_TXBF_OFDM_6       = 280,
-	WL_RATE_1X4_TXBF_OFDM_9       = 281,
-	WL_RATE_1X4_TXBF_OFDM_12      = 282,
-	WL_RATE_1X4_TXBF_OFDM_18      = 283,
-	WL_RATE_1X4_TXBF_OFDM_24      = 284,
-	WL_RATE_1X4_TXBF_OFDM_36      = 285,
-	WL_RATE_1X4_TXBF_OFDM_48      = 286,
-	WL_RATE_1X4_TXBF_OFDM_54      = 287,
-
-	WL_RATE_1X4_TXBF_MCS0         = 288,
-	WL_RATE_1X4_TXBF_MCS1         = 289,
-	WL_RATE_1X4_TXBF_MCS2         = 290,
-	WL_RATE_1X4_TXBF_MCS3         = 291,
-	WL_RATE_1X4_TXBF_MCS4         = 292,
-	WL_RATE_1X4_TXBF_MCS5         = 293,
-	WL_RATE_1X4_TXBF_MCS6         = 294,
-	WL_RATE_1X4_TXBF_MCS7         = 295,
-	WL_RATE_P_1X4_TXBF_MCS87      = 296,
-	WL_RATE_P_1X4_TXBF_MCS88      = 297,
-
-	WL_RATE_1X4_TXBF_VHT0SS1      = 288,
-	WL_RATE_1X4_TXBF_VHT1SS1      = 289,
-	WL_RATE_1X4_TXBF_VHT2SS1      = 290,
-	WL_RATE_1X4_TXBF_VHT3SS1      = 291,
-	WL_RATE_1X4_TXBF_VHT4SS1      = 292,
-	WL_RATE_1X4_TXBF_VHT5SS1      = 293,
-	WL_RATE_1X4_TXBF_VHT6SS1      = 294,
-	WL_RATE_1X4_TXBF_VHT7SS1      = 295,
-	WL_RATE_1X4_TXBF_VHT8SS1      = 296,
-	WL_RATE_1X4_TXBF_VHT9SS1      = 297,
-	WL_RATE_P_1X4_TXBF_VHT10SS1   = 298,
-	WL_RATE_P_1X4_TXBF_VHT11SS1   = 299,
-
-	/* 2 Streams expanded + 2 */
-	WL_RATE_2X4_TXBF_SDM_MCS8     = 300,
-	WL_RATE_2X4_TXBF_SDM_MCS9     = 301,
-	WL_RATE_2X4_TXBF_SDM_MCS10    = 302,
-	WL_RATE_2X4_TXBF_SDM_MCS11    = 303,
-	WL_RATE_2X4_TXBF_SDM_MCS12    = 304,
-	WL_RATE_2X4_TXBF_SDM_MCS13    = 305,
-	WL_RATE_2X4_TXBF_SDM_MCS14    = 306,
-	WL_RATE_2X4_TXBF_SDM_MCS15    = 307,
-	WL_RATE_P_2X4_TXBF_SDM_MCS99  = 308,
-	WL_RATE_P_2X4_TXBF_SDM_MCS100 = 309,
-
-	WL_RATE_2X4_TXBF_VHT0SS2      = 300,
-	WL_RATE_2X4_TXBF_VHT1SS2      = 301,
-	WL_RATE_2X4_TXBF_VHT2SS2      = 302,
-	WL_RATE_2X4_TXBF_VHT3SS2      = 303,
-	WL_RATE_2X4_TXBF_VHT4SS2      = 304,
-	WL_RATE_2X4_TXBF_VHT5SS2      = 305,
-	WL_RATE_2X4_TXBF_VHT6SS2      = 306,
-	WL_RATE_2X4_TXBF_VHT7SS2      = 307,
-	WL_RATE_2X4_TXBF_VHT8SS2      = 308,
-	WL_RATE_2X4_TXBF_VHT9SS2      = 309,
-	WL_RATE_P_2X4_TXBF_VHT10SS2   = 310,
-	WL_RATE_P_2X4_TXBF_VHT11SS2   = 311,
-
-	/* 3 Streams expanded + 1 */
-	WL_RATE_3X4_TXBF_SDM_MCS16    = 312,
-	WL_RATE_3X4_TXBF_SDM_MCS17    = 313,
-	WL_RATE_3X4_TXBF_SDM_MCS18    = 314,
-	WL_RATE_3X4_TXBF_SDM_MCS19    = 315,
-	WL_RATE_3X4_TXBF_SDM_MCS20    = 316,
-	WL_RATE_3X4_TXBF_SDM_MCS21    = 317,
-	WL_RATE_3X4_TXBF_SDM_MCS22    = 318,
-	WL_RATE_3X4_TXBF_SDM_MCS23    = 319,
-	WL_RATE_P_3X4_TXBF_SDM_MCS101 = 320,
-	WL_RATE_P_3X4_TXBF_SDM_MCS102 = 321,
-
-	WL_RATE_3X4_TXBF_VHT0SS3      = 312,
-	WL_RATE_3X4_TXBF_VHT1SS3      = 313,
-	WL_RATE_3X4_TXBF_VHT2SS3      = 314,
-	WL_RATE_3X4_TXBF_VHT3SS3      = 315,
-	WL_RATE_3X4_TXBF_VHT4SS3      = 316,
-	WL_RATE_3X4_TXBF_VHT5SS3      = 317,
-	WL_RATE_3X4_TXBF_VHT6SS3      = 318,
-	WL_RATE_3X4_TXBF_VHT7SS3      = 319,
-	WL_RATE_P_3X4_TXBF_VHT8SS3    = 320,
-	WL_RATE_P_3X4_TXBF_VHT9SS3    = 321,
-	WL_RATE_P_3X4_TXBF_VHT10SS3   = 322,
-	WL_RATE_P_3X4_TXBF_VHT11SS3   = 323,
-
-	/* 4 Streams */
-	WL_RATE_4X4_TXBF_SDM_MCS24    = 324,
-	WL_RATE_4X4_TXBF_SDM_MCS25    = 325,
-	WL_RATE_4X4_TXBF_SDM_MCS26    = 326,
-	WL_RATE_4X4_TXBF_SDM_MCS27    = 327,
-	WL_RATE_4X4_TXBF_SDM_MCS28    = 328,
-	WL_RATE_4X4_TXBF_SDM_MCS29    = 329,
-	WL_RATE_4X4_TXBF_SDM_MCS30    = 330,
-	WL_RATE_4X4_TXBF_SDM_MCS31    = 331,
-	WL_RATE_P_4X4_TXBF_SDM_MCS103 = 332,
-	WL_RATE_P_4X4_TXBF_SDM_MCS104 = 333,
-
-	WL_RATE_4X4_TXBF_VHT0SS4      = 324,
-	WL_RATE_4X4_TXBF_VHT1SS4      = 325,
-	WL_RATE_4X4_TXBF_VHT2SS4      = 326,
-	WL_RATE_4X4_TXBF_VHT3SS4      = 327,
-	WL_RATE_4X4_TXBF_VHT4SS4      = 328,
-	WL_RATE_4X4_TXBF_VHT5SS4      = 329,
-	WL_RATE_4X4_TXBF_VHT6SS4      = 330,
-	WL_RATE_4X4_TXBF_VHT7SS4      = 331,
-	WL_RATE_P_4X4_TXBF_VHT8SS4    = 332,
-	WL_RATE_P_4X4_TXBF_VHT9SS4    = 333,
-	WL_RATE_P_4X4_TXBF_VHT10SS4   = 334,
-	WL_RATE_P_4X4_TXBF_VHT11SS4   = 335
-
-} clm_rates_t;
-
-/* Number of rate codes */
-#define WL_NUMRATES 336
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* _bcmwifi_rates_h_ */
diff --git a/drivers/net/wireless/bcmdhd/bcmxtlv.c b/drivers/net/wireless/bcmdhd/bcmxtlv.c
deleted file mode 100644
index 26cfb9a..0000000
--- a/drivers/net/wireless/bcmdhd/bcmxtlv.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Driver O/S-independent utility routines
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmxtlv.c 527361 2015-01-17 01:48:34Z $
- */
-
-#include <bcm_cfg.h>
-
-#include <typedefs.h>
-#include <bcmdefs.h>
-
-#include <stdarg.h>
-
-#ifdef BCMDRIVER
-#include <osl.h>
-#else /* !BCMDRIVER */
-	#include <stdlib.h> /* AS!!! */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#ifndef ASSERT
-#define ASSERT(exp)
-#endif
-INLINE void* MALLOCZ(void *o, size_t s) { BCM_REFERENCE(o); return calloc(1, s); }
-INLINE void MFREE(void *o, void *p, size_t s) { BCM_REFERENCE(o); BCM_REFERENCE(s); free(p); }
-#endif /* !BCMDRIVER */
-
-#include <bcmendian.h>
-#include <bcmutils.h>
-
-static INLINE int bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts)
-{
-	return ((opts & BCM_XTLV_OPTION_ALIGN32) ? ALIGN_SIZE(dlen + BCM_XTLV_HDR_SIZE, 4)
-		: (dlen + BCM_XTLV_HDR_SIZE));
-}
-
-bcm_xtlv_t *
-bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts)
-{
-	int sz;
-	/* advance to next elt */
-	sz = BCM_XTLV_SIZE(elt, opts);
-	elt = (bcm_xtlv_t*)((uint8 *)elt + sz);
-	*buflen -= sz;
-
-	/* validate next elt */
-	if (!bcm_valid_xtlv(elt, *buflen, opts))
-		return NULL;
-
-	return elt;
-}
-
-int
-bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len, bcm_xtlv_opts_t opts)
-{
-	if (!tlv_buf || !buf || !len)
-		return BCME_BADARG;
-
-	tlv_buf->opts = opts;
-	tlv_buf->size = len;
-	tlv_buf->head = buf;
-	tlv_buf->buf  = buf;
-	return BCME_OK;
-}
-
-uint16
-bcm_xtlv_buf_len(bcm_xtlvbuf_t *tbuf)
-{
-	if (tbuf == NULL) return 0;
-	return (uint16)(tbuf->buf - tbuf->head);
-}
-uint16
-bcm_xtlv_buf_rlen(bcm_xtlvbuf_t *tbuf)
-{
-	if (tbuf == NULL) return 0;
-	return tbuf->size - bcm_xtlv_buf_len(tbuf);
-}
-uint8 *
-bcm_xtlv_buf(bcm_xtlvbuf_t *tbuf)
-{
-	if (tbuf == NULL) return NULL;
-	return tbuf->buf;
-}
-uint8 *
-bcm_xtlv_head(bcm_xtlvbuf_t *tbuf)
-{
-	if (tbuf == NULL) return NULL;
-	return tbuf->head;
-}
-int
-bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const void *data, uint16 dlen)
-{
-	bcm_xtlv_t *xtlv;
-	int size;
-
-	if (tbuf == NULL)
-		return BCME_BADARG;
-	size = bcm_xtlv_size_for_data(dlen, tbuf->opts);
-	if (bcm_xtlv_buf_rlen(tbuf) < size)
-		return BCME_NOMEM;
-	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
-	xtlv->id = htol16(type);
-	xtlv->len = htol16(dlen);
-	memcpy(xtlv->data, data, dlen);
-	tbuf->buf += size;
-	return BCME_OK;
-}
-int
-bcm_xtlv_put_8(bcm_xtlvbuf_t *tbuf, uint16 type, const int8 data)
-{
-	bcm_xtlv_t *xtlv;
-	int size;
-
-	if (tbuf == NULL)
-		return BCME_BADARG;
-	size = bcm_xtlv_size_for_data(1, tbuf->opts);
-	if (bcm_xtlv_buf_rlen(tbuf) < size)
-		return BCME_NOMEM;
-	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
-	xtlv->id = htol16(type);
-	xtlv->len = htol16(sizeof(data));
-	xtlv->data[0] = data;
-	tbuf->buf += size;
-	return BCME_OK;
-}
-int
-bcm_xtlv_put_16(bcm_xtlvbuf_t *tbuf, uint16 type, const int16 data)
-{
-	bcm_xtlv_t *xtlv;
-	int size;
-
-	if (tbuf == NULL)
-		return BCME_BADARG;
-	size = bcm_xtlv_size_for_data(2, tbuf->opts);
-	if (bcm_xtlv_buf_rlen(tbuf) < size)
-		return BCME_NOMEM;
-
-	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
-	xtlv->id = htol16(type);
-	xtlv->len = htol16(sizeof(data));
-	htol16_ua_store(data, xtlv->data);
-	tbuf->buf += size;
-	return BCME_OK;
-}
-int
-bcm_xtlv_put_32(bcm_xtlvbuf_t *tbuf, uint16 type, const int32 data)
-{
-	bcm_xtlv_t *xtlv;
-	int size;
-
-	if (tbuf == NULL)
-		return BCME_BADARG;
-	size = bcm_xtlv_size_for_data(4, tbuf->opts);
-	if (bcm_xtlv_buf_rlen(tbuf) < size)
-		return BCME_NOMEM;
-	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
-	xtlv->id = htol16(type);
-	xtlv->len = htol16(sizeof(data));
-	htol32_ua_store(data, xtlv->data);
-	tbuf->buf += size;
-	return BCME_OK;
-}
-
-/*
- *  upacks xtlv record from buf checks the type
- *  copies data to callers buffer
- *  advances tlv pointer to next record
- *  caller's resposible for dst space check
- */
-int
-bcm_unpack_xtlv_entry(uint8 **tlv_buf, uint16 xpct_type, uint16 xpct_len, void *dst,
-	bcm_xtlv_opts_t opts)
-{
-	bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf;
-	uint16 len;
-	uint16 type;
-
-	ASSERT(ptlv);
-	/* tlv headr is always packed in LE order */
-	len = ltoh16(ptlv->len);
-	type = ltoh16(ptlv->id);
-	if	(len == 0) {
-		/* z-len tlv headers: allow, but don't process */
-		printf("z-len, skip unpack\n");
-	} else  {
-		if ((type != xpct_type) ||
-			(len > xpct_len)) {
-			printf("xtlv_unpack Error: found[type:%d,len:%d] != xpct[type:%d,len:%d]\n",
-				type, len, xpct_type, xpct_len);
-			return BCME_BADARG;
-		}
-		/* copy tlv record to caller's buffer */
-		memcpy(dst, ptlv->data, ptlv->len);
-	}
-	*tlv_buf += BCM_XTLV_SIZE(ptlv, opts);
-	return BCME_OK;
-}
-
-/*
- *  packs user data into tlv record
- *  advances tlv pointer to next xtlv slot
- *  buflen is used for tlv_buf space check
- */
-int
-bcm_pack_xtlv_entry(uint8 **tlv_buf, uint16 *buflen, uint16 type, uint16 len, void *src,
-	bcm_xtlv_opts_t opts)
-{
-	bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf;
-	int size;
-
-	ASSERT(ptlv);
-	ASSERT(src);
-
-	size = bcm_xtlv_size_for_data(len, opts);
-
-	/* copy data from tlv buffer to dst provided by user */
-	if (size > *buflen) {
-		printf("bcm_pack_xtlv_entry: no space tlv_buf: requested:%d, available:%d\n",
-			size, *buflen);
-		return BCME_BADLEN;
-	}
-	ptlv->id = htol16(type);
-	ptlv->len = htol16(len);
-
-	/* copy callers data */
-	memcpy(ptlv->data, src, len);
-
-	/* advance callers pointer to tlv buff */
-	*tlv_buf += size;
-	/* decrement the len */
-	*buflen -= (uint16)size;
-	return BCME_OK;
-}
-
-/*
- *  unpack all xtlv records from the issue a callback
- *  to set function one call per found tlv record
- */
-int
-bcm_unpack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
-	bcm_xtlv_unpack_cbfn_t *cbfn)
-{
-	uint16 len;
-	uint16 type;
-	int res = BCME_OK;
-	int size;
-	bcm_xtlv_t *ptlv;
-	int sbuflen = buflen;
-
-	ASSERT(!buflen || tlv_buf);
-	ASSERT(!buflen || cbfn);
-
-	while (sbuflen >= (int)BCM_XTLV_HDR_SIZE) {
-		ptlv = (bcm_xtlv_t *)tlv_buf;
-
-		/* tlv header is always packed in LE order */
-		len = ltoh16(ptlv->len);
-		type = ltoh16(ptlv->id);
-
-		size = bcm_xtlv_size_for_data(len, opts);
-
-		sbuflen -= size;
-		/* check for possible buffer overrun */
-		if (sbuflen < 0)
-			break;
-
-		if ((res = cbfn(ctx, ptlv->data, type, len)) != BCME_OK)
-			break;
-		tlv_buf += size;
-	}
-	return res;
-}
-
-int
-bcm_pack_xtlv_buf(void *ctx, void *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
-	bcm_pack_xtlv_next_info_cbfn_t get_next, bcm_pack_xtlv_pack_next_cbfn_t pack_next,
-	int *outlen)
-{
-	int res = BCME_OK;
-	uint16 tlv_id;
-	uint16 tlv_len;
-	uint8 *startp;
-	uint8 *endp;
-	uint8 *buf;
-	bool more;
-	int size;
-
-	ASSERT(get_next && pack_next);
-
-	buf = (uint8 *)tlv_buf;
-	startp = buf;
-	endp = (uint8 *)buf + buflen;
-	more = TRUE;
-	while (more && (buf < endp)) {
-		more = get_next(ctx, &tlv_id, &tlv_len);
-		size = bcm_xtlv_size_for_data(tlv_len, opts);
-		if ((buf + size) >= endp) {
-			res = BCME_BUFTOOSHORT;
-			goto done;
-		}
-
-		htol16_ua_store(tlv_id, buf);
-		htol16_ua_store(tlv_len, buf + sizeof(tlv_id));
-		pack_next(ctx, tlv_id, tlv_len, buf + BCM_XTLV_HDR_SIZE);
-		buf += size;
-	}
-
-	if (more)
-		res = BCME_BUFTOOSHORT;
-
-done:
-	if (outlen) {
-		*outlen = (int)(buf - startp);
-	}
-	return res;
-}
-
-/*
- *  pack xtlv buffer from memory according to xtlv_desc_t
- */
-int
-bcm_pack_xtlv_buf_from_mem(void **tlv_buf, uint16 *buflen, xtlv_desc_t *items,
-	bcm_xtlv_opts_t opts)
-{
-	int res = BCME_OK;
-	uint8 *ptlv = (uint8 *)*tlv_buf;
-
-	while (items->type != 0) {
-		if ((res = bcm_pack_xtlv_entry(&ptlv,
-			buflen, items->type,
-			items->len, items->ptr, opts) != BCME_OK)) {
-			break;
-		}
-		items++;
-	}
-	*tlv_buf = ptlv; /* update the external pointer */
-	return res;
-}
-
-/*
- *  unpack xtlv buffer to memory according to xtlv_desc_t
- *
- */
-int
-bcm_unpack_xtlv_buf_to_mem(void *tlv_buf, int *buflen, xtlv_desc_t *items, bcm_xtlv_opts_t opts)
-{
-	int res = BCME_OK;
-	bcm_xtlv_t *elt;
-
-	elt =  bcm_valid_xtlv((bcm_xtlv_t *)tlv_buf, *buflen, opts) ? (bcm_xtlv_t *)tlv_buf : NULL;
-	if (!elt || !items) {
-		res = BCME_BADARG;
-		return res;
-	}
-
-	for (; elt != NULL && res == BCME_OK; elt = bcm_next_xtlv(elt, buflen, opts)) {
-		/*  find matches in desc_t items  */
-		xtlv_desc_t *dst_desc = items;
-		uint16 len = ltoh16(elt->len);
-
-		while (dst_desc->type != 0) {
-			if (ltoh16(elt->id) == dst_desc->type) {
-				if (len != dst_desc->len) {
-					res = BCME_BADLEN;
-				} else {
-					memcpy(dst_desc->ptr, elt->data, len);
-				}
-				break;
-			}
-			dst_desc++;
-		}
-	}
-
-	if (res == BCME_OK && *buflen != 0)
-		res =  BCME_BUFTOOSHORT;
-
-	return res;
-}
-
-/*
- * return data pointer of a given ID from xtlv buffer.
- * If the specified xTLV ID is found, on return *data_len_out will contain
- * the the data length of the xTLV ID.
- */
-void *
-bcm_get_data_from_xtlv_buf(uint8 *tlv_buf, uint16 buflen, uint16 id,
-	uint16 *datalen_out, bcm_xtlv_opts_t opts)
-{
-	void *retptr = NULL;
-	uint16 type, len;
-	int size;
-	bcm_xtlv_t *ptlv;
-	int sbuflen = buflen;
-
-	while (sbuflen >= (int)BCM_XTLV_HDR_SIZE) {
-		ptlv = (bcm_xtlv_t *)tlv_buf;
-
-		/* tlv header is always packed in LE order */
-		type = ltoh16(ptlv->id);
-		len = ltoh16(ptlv->len);
-		size = bcm_xtlv_size_for_data(len, opts);
-
-		sbuflen -= size;
-		/* check for possible buffer overrun */
-		if (sbuflen < 0) {
-			printf("%s %d: Invalid sbuflen %d\n",
-				__FUNCTION__, __LINE__, sbuflen);
-			break;
-		}
-
-		if (id == type) {
-			retptr = ptlv->data;
-			if (datalen_out) {
-				*datalen_out = len;
-			}
-			break;
-		}
-		tlv_buf += size;
-	}
-
-	return retptr;
-}
-
-int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
-{
-	int size; /* entire size of the XTLV including header, data, and optional padding */
-	int len; /* XTLV's value real length wthout padding */
-
-	len = BCM_XTLV_LEN(elt);
-
-	size = bcm_xtlv_size_for_data(len, opts);
-
-	return size;
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
deleted file mode 100644
index fbc6269..0000000
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ /dev/null
@@ -1,1607 +0,0 @@
-/*
- * Header file describing the internal (inter-module) DHD interfaces.
- *
- * Provides type definitions and function prototypes used to link the
- * DHD OS, bus, and protocol modules.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd.h 610267 2016-01-06 16:03:53Z $
- */
-
-/****************
- * Common types *
- */
-
-#ifndef _dhd_h_
-#define _dhd_h_
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
-#include <linux/wakelock.h>
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
-#include <dhd_buzzz.h>
-/* The kernel threading is sdio-specific */
-struct task_struct;
-struct sched_param;
-int setScheduler(struct task_struct *p, int policy, struct sched_param *param);
-int get_scheduler_policy(struct task_struct *p);
-#define MAX_EVENT	16
-
-#define ALL_INTERFACES	0xff
-
-#include <wlioctl.h>
-#include <wlfc_proto.h>
-
-#if defined(BCMWDF)
-#include <wdf.h>
-#include <WdfMiniport.h>
-#endif /* (BCMWDF)  */
-
-#ifdef DEBUG_DPC_THREAD_WATCHDOG
-#define MAX_RESCHED_CNT 600
-#endif /* DEBUG_DPC_THREAD_WATCHDOG */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) && LINUX_VERSION_CODE < \
-	KERNEL_VERSION(3, 18, 0) || defined(CONFIG_BCMDHD_VENDOR_EXT))
-#define WL_VENDOR_EXT_SUPPORT
-#endif /* 3.13.0 <= LINUX_KERNEL_VERSION < 3.18.0 || CONFIG_BCMDHD_VENDOR_EXT */
-#if defined(CONFIG_ANDROID) && defined(WL_VENDOR_EXT_SUPPORT)
-#if !defined(GSCAN_SUPPORT)
-#define GSCAN_SUPPORT
-#endif
-#endif /* CONFIG_ANDROID && WL_VENDOR_EXT_SUPPORT */
-
-#if defined(KEEP_ALIVE)
-/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */
-#define KEEP_ALIVE_PERIOD 55000
-#define NULL_PKT_STR	"null_pkt"
-#endif /* KEEP_ALIVE */
-
-/* Forward decls */
-struct dhd_bus;
-struct dhd_prot;
-struct dhd_info;
-struct dhd_ioctl;
-
-/* The level of bus communication with the dongle */
-enum dhd_bus_state {
-	DHD_BUS_DOWN,		/* Not ready for frame transfers */
-	DHD_BUS_LOAD,		/* Download access only (CPU reset) */
-	DHD_BUS_DATA,		/* Ready for frame transfers */
-	DHD_BUS_SUSPEND,	/* Bus has been suspended */
-	DHD_BUS_DOWN_IN_PROGRESS,	/* Bus going Down */
-};
-
-/*
- * Bit fields to Indicate clean up process that wait till they are finished.
- * Future synchronizable processes can add their bit filed below and update
- * their functionalities accordingly
- */
-#define DHD_BUS_BUSY_IN_TX                   0x01
-#define DHD_BUS_BUSY_IN_SEND_PKT             0x02
-#define DHD_BUS_BUSY_IN_DPC                  0x04
-#define DHD_BUS_BUSY_IN_WD                   0x08
-#define DHD_BUS_BUSY_IN_IOVAR                0x10
-#define DHD_BUS_BUSY_IN_DHD_IOVAR            0x20
-#define DHD_BUS_BUSY_IN_SUSPEND              0x40
-#define DHD_BUS_BUSY_IN_RESUME               0x80
-#define DHD_BUS_BUSY_RPM_SUSPEND_IN_PROGRESS 0x100
-#define DHD_BUS_BUSY_RPM_SUSPEND_DONE        0x200
-#define DHD_BUS_BUSY_RPM_RESUME_IN_PROGRESS  0x400
-#define DHD_BUS_BUSY_RPM_ALL                 (DHD_BUS_BUSY_RPM_SUSPEND_DONE | \
-		DHD_BUS_BUSY_RPM_SUSPEND_IN_PROGRESS | \
-		DHD_BUS_BUSY_RPM_RESUME_IN_PROGRESS)
-
-/* Download Types */
-typedef enum download_type {
-	FW,
-	NVRAM
-} download_type_t;
-
-
-/* For supporting multiple interfaces */
-#define DHD_MAX_IFS	16
-#define DHD_DEL_IF	-0xE
-#define DHD_BAD_IF	-0xF
-
-enum dhd_op_flags {
-/* Firmware requested operation mode */
-	DHD_FLAG_STA_MODE				= (1 << (0)), /* STA only */
-	DHD_FLAG_HOSTAP_MODE				= (1 << (1)), /* SOFTAP only */
-	DHD_FLAG_P2P_MODE				= (1 << (2)), /* P2P Only */
-	/* STA + P2P */
-	DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE),
-	DHD_FLAG_CONCURR_MULTI_CHAN_MODE		= (1 << (4)), /* STA + P2P */
-	/* Current P2P mode for P2P connection */
-	DHD_FLAG_P2P_GC_MODE				= (1 << (5)),
-	DHD_FLAG_P2P_GO_MODE				= (1 << (6)),
-	DHD_FLAG_MBSS_MODE				= (1 << (7)), /* MBSS in future */
-	DHD_FLAG_IBSS_MODE				= (1 << (8)),
-	DHD_FLAG_MFG_MODE				= (1 << (9)),
-	DHD_FLAG_RSDB_MODE				= (1 << (10)),
-	DHD_FLAG_MP2P_MODE				= (1 << (11))
-};
-
-#define DHD_OPMODE_SUPPORTED(dhd, opmode_flag) \
-	(dhd ? ((((dhd_pub_t *)dhd)->op_mode)  &  opmode_flag) : -1)
-
-/* Max sequential TX/RX Control timeouts to set HANG event */
-#ifndef MAX_CNTL_TX_TIMEOUT
-#define MAX_CNTL_TX_TIMEOUT 2
-#endif /* MAX_CNTL_TX_TIMEOUT */
-#ifndef MAX_CNTL_RX_TIMEOUT
-#define MAX_CNTL_RX_TIMEOUT 1
-#endif /* MAX_CNTL_RX_TIMEOUT */
-
-#define DHD_SCAN_ASSOC_ACTIVE_TIME	40 /* ms: Embedded default Active setting from DHD */
-#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */
-#define DHD_SCAN_PASSIVE_TIME		130 /* ms: Embedded default Passive setting from DHD */
-
-#ifndef POWERUP_MAX_RETRY
-#define POWERUP_MAX_RETRY	3 /* how many times we retry to power up the chip */
-#endif
-#ifndef POWERUP_WAIT_MS
-#define POWERUP_WAIT_MS		2000 /* ms: time out in waiting wifi to come up */
-#endif
-#define MAX_NVRAMBUF_SIZE	(16 * 1024) /* max nvram buf size */
-#ifdef DHD_DEBUG
-#define DHD_JOIN_MAX_TIME_DEFAULT 10000 /* ms: Max time out for joining AP */
-#define DHD_SCAN_DEF_TIMEOUT 10000 /* ms: Max time out for scan in progress */
-#endif
-
-#define FW_VER_STR_LEN	128
-
-enum dhd_bus_wake_state {
-	WAKE_LOCK_OFF,
-	WAKE_LOCK_PRIV,
-	WAKE_LOCK_DPC,
-	WAKE_LOCK_IOCTL,
-	WAKE_LOCK_DOWNLOAD,
-	WAKE_LOCK_TMOUT,
-	WAKE_LOCK_WATCHDOG,
-	WAKE_LOCK_LINK_DOWN_TMOUT,
-	WAKE_LOCK_PNO_FIND_TMOUT,
-	WAKE_LOCK_SOFTAP_SET,
-	WAKE_LOCK_SOFTAP_STOP,
-	WAKE_LOCK_SOFTAP_START,
-	WAKE_LOCK_SOFTAP_THREAD
-};
-
-enum dhd_prealloc_index {
-	DHD_PREALLOC_PROT = 0,
-	DHD_PREALLOC_RXBUF,
-	DHD_PREALLOC_DATABUF,
-	DHD_PREALLOC_OSL_BUF,
-#if defined(STATIC_WL_PRIV_STRUCT)
-	DHD_PREALLOC_WIPHY_ESCAN0 = 5,
-#endif /* STATIC_WL_PRIV_STRUCT */
-	DHD_PREALLOC_DHD_INFO = 7,
-	DHD_PREALLOC_DHD_WLFC_INFO = 8,
-	DHD_PREALLOC_IF_FLOW_LKUP = 9,
-	DHD_PREALLOC_MEMDUMP_BUF = 10,
-	DHD_PREALLOC_MEMDUMP_RAM = 11,
-	DHD_PREALLOC_DHD_WLFC_HANGER = 12,
-	DHD_PREALLOC_PKTID_MAP = 13,
-	DHD_PREALLOC_PKTID_MAP_IOCTL = 14,
-	DHD_PREALLOC_DHD_LOG_DUMP_BUF = 15
-};
-
-enum dhd_dongledump_mode {
-	DUMP_DISABLED = 0,
-	DUMP_MEMONLY,
-	DUMP_MEMFILE,
-	DUMP_MEMFILE_BUGON,
-	DUMP_MEMFILE_MAX
-};
-
-enum dhd_dongledump_type {
-	DUMP_TYPE_RESUMED_ON_TIMEOUT = 1,
-	DUMP_TYPE_D3_ACK_TIMEOUT,
-	DUMP_TYPE_DONGLE_TRAP,
-	DUMP_TYPE_MEMORY_CORRUPTION,
-	DUMP_TYPE_PKTID_AUDIT_FAILURE,
-	DUMP_TYPE_SCAN_TIMEOUT,
-	DUMP_TYPE_SCAN_BUSY,
-	DUMP_TYPE_BY_SYSDUMP,
-	DUMP_TYPE_BY_LIVELOCK,
-	DUMP_TYPE_AP_LINKUP_FAILURE
-};
-
-enum dhd_hang_reason {
-	HANG_REASON_MASK = 0x8000,
-	HANG_REASON_IOCTL_RESP_TIMEOUT = 0x8001,
-	HANG_REASON_DONGLE_TRAP = 0x8002,
-	HANG_REASON_D3_ACK_TIMEOUT = 0x8003,
-	HANG_REASON_BUS_DOWN = 0x8004,
-	HANG_REASON_PCIE_LINK_DOWN = 0x8005,
-	HANG_REASON_MSGBUF_LIVELOCK = 0x8006,
-	HANG_REASON_P2P_IFACE_DEL_FAILURE = 0x8007,
-	HANG_REASON_HT_AVAIL_ERROR = 0x8008,
-	HANG_REASON_PCIE_RC_LINK_UP_FAIL = 0x8009,
-	HANG_REASON_MAX = 0x800a
-};
-
-enum dhd_rsdb_scan_features {
-	/* Downgraded scan feature for AP active */
-	RSDB_SCAN_DOWNGRADED_AP_SCAN = 0x01,
-	/* Downgraded scan feature for P2P Discovery */
-	RSDB_SCAN_DOWNGRADED_P2P_DISC_SCAN = 0x02,
-	/* Enable channel pruning for ROAM SCAN */
-	RSDB_SCAN_DOWNGRADED_CH_PRUNE_ROAM = 0x10,
-	/* Enable channel pruning for any SCAN */
-	RSDB_SCAN_DOWNGRADED_CH_PRUNE_ALL  = 0x20
-};
-
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN	32
-#endif
-
-/**
- * DMA-able buffer parameters
- * - dmaaddr_t is 32bits on a 32bit host.
- *   dhd_dma_buf::pa may not be used as a sh_addr_t, bcm_addr64_t or uintptr
- * - dhd_dma_buf::_alloced is ONLY for freeing a DMA-able buffer.
- */
-typedef struct dhd_dma_buf {
-	void      *va;      /* virtual address of buffer */
-	uint32    len;      /* user requested buffer length */
-	dmaaddr_t pa;       /* physical address of buffer */
-	void      *dmah;    /* dma mapper handle */
-	void      *secdma;  /* secure dma sec_cma_info handle */
-	uint32    _alloced; /* actual size of buffer allocated with align and pad */
-} dhd_dma_buf_t;
-
-/* host reordering packts logic */
-/* followed the structure to hold the reorder buffers (void **p) */
-typedef struct reorder_info {
-	void **p;
-	uint8 flow_id;
-	uint8 cur_idx;
-	uint8 exp_idx;
-	uint8 max_idx;
-	uint8 pend_pkts;
-} reorder_info_t;
-
-#ifdef DHDTCPACK_SUPPRESS
-
-enum {
-	/* TCPACK suppress off */
-	TCPACK_SUP_OFF,
-	/* Replace TCPACK in txq when new coming one has higher ACK number. */
-	TCPACK_SUP_REPLACE,
-	/* TCPACK_SUP_REPLACE + delayed TCPACK TX unless ACK to PSH DATA.
-	 * This will give benefits to Half-Duplex bus interface(e.g. SDIO) that
-	 * 1. we are able to read TCP DATA packets first from the bus
-	 * 2. TCPACKs that don't need to hurry delivered remains longer in TXQ so can be suppressed.
-	 */
-	TCPACK_SUP_DELAYTX,
-	TCPACK_SUP_HOLD,
-	TCPACK_SUP_LAST_MODE
-};
-#endif /* DHDTCPACK_SUPPRESS */
-
-
-/*
- * Accumulating the queue lengths of all flowring queues in a parent object,
- * to assert flow control, when the cummulative queue length crosses an upper
- * threshold defined on a parent object. Upper threshold may be maintained
- * at a station level, at an interface level, or at a dhd instance.
- *
- * cumm_ctr_t abstraction:
- * cumm_ctr_t abstraction may be enhanced to use an object with a hysterisis
- * pause on/off threshold callback.
- * All macros use the address of the cummulative length in the parent objects.
- *
- * BCM_GMAC3 builds use a single perimeter lock, as opposed to a per queue lock.
- * Cummulative counters in parent objects may be updated without spinlocks.
- *
- * In non BCM_GMAC3, if a cummulative queue length is desired across all flows
- * belonging to either of (a station, or an interface or a dhd instance), then
- * an atomic operation is required using an atomic_t cummulative counters or
- * using a spinlock. BCM_ROUTER_DHD uses the Linux atomic_t construct.
- */
-
-/* Cummulative length not supported. */
-typedef uint32 cumm_ctr_t;
-#define DHD_CUMM_CTR_PTR(clen)     ((cumm_ctr_t*)(clen))
-#define DHD_CUMM_CTR(clen)         *(DHD_CUMM_CTR_PTR(clen)) /* accessor */
-#define DHD_CUMM_CTR_READ(clen)    DHD_CUMM_CTR(clen) /* read access */
-#define DHD_CUMM_CTR_INIT(clen)                                                \
-	ASSERT(DHD_CUMM_CTR_PTR(clen) != DHD_CUMM_CTR_PTR(NULL));
-#define DHD_CUMM_CTR_INCR(clen)                                                \
-	ASSERT(DHD_CUMM_CTR_PTR(clen) != DHD_CUMM_CTR_PTR(NULL));
-#define DHD_CUMM_CTR_DECR(clen)                                                \
-	ASSERT(DHD_CUMM_CTR_PTR(clen) != DHD_CUMM_CTR_PTR(NULL));
-
-/* DMA'ing r/w indices for rings supported */
-#ifdef BCM_INDX_TCM /* FW gets r/w indices in TCM */
-#define DMA_INDX_ENAB(dma_indxsup)	0
-#elif defined BCM_INDX_DMA  /* FW gets r/w indices from Host memory */
-#define DMA_INDX_ENAB(dma_indxsup)	1
-#else	/* r/w indices in TCM or host memory based on FW/Host agreement */
-#define DMA_INDX_ENAB(dma_indxsup)	dma_indxsup
-#endif	/* BCM_INDX_TCM */
-
-#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE)
-struct tdls_peer_node {
-	uint8 addr[ETHER_ADDR_LEN];
-	struct tdls_peer_node *next;
-};
-typedef struct tdls_peer_node tdls_peer_node_t;
-typedef struct {
-	tdls_peer_node_t *node;
-	uint8 tdls_peer_count;
-} tdls_peer_tbl_t;
-#endif /* defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */
-
-#ifdef DHD_LOG_DUMP
-/* below structure describe ring buffer. */
-struct dhd_log_dump_buf
-{
-	spinlock_t lock;
-	unsigned int wraparound;
-	unsigned long max;
-	unsigned int remain;
-	char* present;
-	char* front;
-	char* buffer;
-};
-
-#define DHD_LOG_DUMP_BUFFER_SIZE	(1024 * 1024)
-#define DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE 256
-
-extern void dhd_log_dump_print(const char *fmt, ...);
-extern char *dhd_log_dump_get_timestamp(void);
-#endif /* DHD_LOG_DUMP */
-#define DHD_COMMON_DUMP_PATH	"/data/misc/wifi/log/"
-
-/* Common structure for module and instance linkage */
-typedef struct dhd_pub {
-	/* Linkage ponters */
-	osl_t *osh;		/* OSL handle */
-	struct dhd_bus *bus;	/* Bus module handle */
-	struct dhd_prot *prot;	/* Protocol module handle */
-	struct dhd_info  *info; /* Info module handle */
-
-	/* to NDIS developer, the structure dhd_common is redundant,
-	 * please do NOT merge it back from other branches !!!
-	 */
-
-
-	/* Internal dhd items */
-	bool up;		/* Driver up/down (to OS) */
-	bool txoff;		/* Transmit flow-controlled */
-	bool dongle_reset;  /* TRUE = DEVRESET put dongle into reset */
-	enum dhd_bus_state busstate;
-	uint dhd_bus_busy_state;	/* Bus busy state */
-	uint hdrlen;		/* Total DHD header length (proto + bus) */
-	uint maxctl;		/* Max size rxctl request from proto to bus */
-	uint rxsz;		/* Rx buffer size bus module should use */
-	uint8 wme_dp;	/* wme discard priority */
-
-	/* Dongle media info */
-	bool iswl;		/* Dongle-resident driver is wl */
-	ulong drv_version;	/* Version of dongle-resident driver */
-	struct ether_addr mac;	/* MAC address obtained from dongle */
-	dngl_stats_t dstats;	/* Stats for dongle-based data */
-
-	/* Additional stats for the bus level */
-	ulong tx_packets;	/* Data packets sent to dongle */
-	ulong tx_dropped;	/* Data packets dropped in dhd */
-	ulong tx_multicast;	/* Multicast data packets sent to dongle */
-	ulong tx_errors;	/* Errors in sending data to dongle */
-	ulong tx_ctlpkts;	/* Control packets sent to dongle */
-	ulong tx_ctlerrs;	/* Errors sending control frames to dongle */
-	ulong rx_packets;	/* Packets sent up the network interface */
-	ulong rx_multicast;	/* Multicast packets sent up the network interface */
-	ulong rx_errors;	/* Errors processing rx data packets */
-	ulong rx_ctlpkts;	/* Control frames processed from dongle */
-	ulong rx_ctlerrs;	/* Errors in processing rx control frames */
-	ulong rx_dropped;	/* Packets dropped locally (no memory) */
-	ulong rx_flushed;  /* Packets flushed due to unscheduled sendup thread */
-	ulong wd_dpc_sched;   /* Number of times dhd dpc scheduled by watchdog timer */
-	ulong rx_pktgetfail; /* Number of PKTGET failures in DHD on RX */
-	ulong tx_pktgetfail; /* Number of PKTGET failures in DHD on TX */
-	ulong rx_readahead_cnt;	/* Number of packets where header read-ahead was used. */
-	ulong tx_realloc;	/* Number of tx packets we had to realloc for headroom */
-	ulong fc_packets;       /* Number of flow control pkts recvd */
-
-	/* Last error return */
-	int bcmerror;
-	uint tickcnt;
-
-	/* Last error from dongle */
-	int dongle_error;
-
-	uint8 country_code[WLC_CNTRY_BUF_SZ];
-
-	/* Suspend disable flag and "in suspend" flag */
-	int suspend_disable_flag; /* "1" to disable all extra powersaving during suspend */
-	int in_suspend;			/* flag set to 1 when early suspend called */
-#ifdef PNO_SUPPORT
-	int pno_enable;			/* pno status : "1" is pno enable */
-	int pno_suspend;		/* pno suspend status : "1" is pno suspended */
-#endif /* PNO_SUPPORT */
-	/* DTIM skip value, default 0(or 1) means wake each DTIM
-	 * 3 means skip 2 DTIMs and wake up 3rd DTIM(9th beacon when AP DTIM is 3)
-	 */
-	int suspend_bcn_li_dtim;         /* bcn_li_dtim value in suspend mode */
-#ifdef PKT_FILTER_SUPPORT
-	int early_suspended;	/* Early suspend status */
-	int dhcp_in_progress;	/* DHCP period */
-#endif
-
-	/* Pkt filter defination */
-	char * pktfilter[100];
-	int pktfilter_count;
-
-	wl_country_t dhd_cspec;		/* Current Locale info */
-#ifdef CUSTOM_COUNTRY_CODE
-	u32 dhd_cflags;
-#endif /* CUSTOM_COUNTRY_CODE */
-	bool force_country_change;
-	char eventmask[WL_EVENTING_MASK_LEN];
-	int	op_mode;				/* STA, HostAPD, WFD, SoftAP */
-
-/* Set this to 1 to use a seperate interface (p2p0) for p2p operations.
- *  For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework
- *  see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile
- */
-/* #define WL_ENABLE_P2P_IF		1 */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	struct mutex 	wl_start_stop_lock; /* lock/unlock for Android start/stop */
-	struct mutex 	wl_softap_lock;		 /* lock/unlock for any SoftAP/STA settings */
-#endif 
-
-#ifdef PROP_TXSTATUS
-	bool	wlfc_enabled;
-	int	wlfc_mode;
-	void*	wlfc_state;
-	/*
-	Mode in which the dhd flow control shall operate. Must be set before
-	traffic starts to the device.
-	0 - Do not do any proptxtstatus flow control
-	1 - Use implied credit from a packet status
-	2 - Use explicit credit
-	3 - Only AMPDU hostreorder used. no wlfc.
-	*/
-	uint8	proptxstatus_mode;
-	bool	proptxstatus_txoff;
-	bool	proptxstatus_module_ignore;
-	bool	proptxstatus_credit_ignore;
-	bool	proptxstatus_txstatus_ignore;
-
-	bool	wlfc_rxpkt_chk;
-	/*
-	 * implement below functions in each platform if needed.
-	 */
-	/* platform specific function whether to skip flow control */
-	bool (*skip_fc)(void);
-	/* platform specific function for wlfc_enable and wlfc_deinit */
-	void (*plat_init)(void *dhd);
-	void (*plat_deinit)(void *dhd);
-#ifdef DHD_WLFC_THREAD
-	bool                wlfc_thread_go;
-	struct task_struct* wlfc_thread;
-	wait_queue_head_t   wlfc_wqhead;
-#endif /* DHD_WLFC_THREAD */
-#endif /* PROP_TXSTATUS */
-#ifdef PNO_SUPPORT
-	void *pno_state;
-#endif
-#ifdef RTT_SUPPORT
-	void *rtt_state;
-#endif
-	bool	dongle_isolation;
-	bool	dongle_trap_occured;	/* flag for sending HANG event to upper layer */
-	int   hang_was_sent;
-	int   rxcnt_timeout;		/* counter rxcnt timeout to send HANG */
-	int   txcnt_timeout;		/* counter txcnt timeout to send HANG */
-#ifdef BCMPCIE
-	int   d3ackcnt_timeout;		/* counter d3ack timeout to send HANG */
-#endif /* BCMPCIE */
-	bool hang_report;		/* enable hang report by default */
-	uint16 hang_reason;		/* reason codes for HANG event */
-#ifdef WLMEDIA_HTSF
-	uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */
-#endif
-#ifdef WLTDLS
-	bool tdls_enable;
-#endif
-	struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS];
-	#define WLC_IOCTL_MAXBUF_FWCAP	512
-	char  fw_capabilities[WLC_IOCTL_MAXBUF_FWCAP];
-	#define MAXSKBPEND 1024
-	void *skbbuf[MAXSKBPEND];
-	uint32 store_idx;
-	uint32 sent_idx;
-#ifdef DHDTCPACK_SUPPRESS
-	uint8 tcpack_sup_mode;		/* TCPACK suppress mode */
-	void *tcpack_sup_module;	/* TCPACK suppress module */
-	uint32 tcpack_sup_ratio;
-	uint32 tcpack_sup_delay;
-#endif /* DHDTCPACK_SUPPRESS */
-#if defined(ARP_OFFLOAD_SUPPORT)
-	uint32 arp_version;
-#endif
-#ifdef DEBUG_DPC_THREAD_WATCHDOG
-	bool dhd_bug_on;
-#endif /* DEBUG_DPC_THREAD_WATCHDOG */
-#ifdef CUSTOM_SET_CPUCORE
-	struct task_struct * current_dpc;
-	struct task_struct * current_rxf;
-	int chan_isvht80;
-#endif /* CUSTOM_SET_CPUCORE */
-
-
-	void    *sta_pool;          /* pre-allocated pool of sta objects */
-	void    *staid_allocator;   /* allocator of sta indexes */
-#ifdef PCIE_FULL_DONGLE
-	bool	flow_rings_inited;	/* set this flag after initializing flow rings */
-#endif /* PCIE_FULL_DONGLE */
-	void    *flowid_allocator;  /* unique flowid allocator */
-	void	*flow_ring_table;   /* flow ring table, include prot and bus info */
-	void	*if_flow_lkup;      /* per interface flowid lkup hash table */
-	void    *flowid_lock;       /* per os lock for flowid info protection */
-	void    *flowring_list_lock;       /* per os lock for flowring list protection */
-	uint32  num_flow_rings;
-	cumm_ctr_t cumm_ctr;        /* cumm queue length placeholder  */
-	uint32 d2h_sync_mode;       /* D2H DMA completion sync mode */
-	uint8  flow_prio_map[NUMPRIO];
-	uint8	flow_prio_map_type;
-	char enable_log[MAX_EVENT];
-	bool dma_d2h_ring_upd_support;
-	bool dma_h2d_ring_upd_support;
-
-#ifdef DHD_WMF
-	bool wmf_ucast_igmp;
-#ifdef DHD_IGMP_UCQUERY
-	bool wmf_ucast_igmp_query;
-#endif
-#ifdef DHD_UCAST_UPNP
-	bool wmf_ucast_upnp;
-#endif
-#endif /* DHD_WMF */
-#ifdef DHD_L2_FILTER
-	unsigned long l2_filter_cnt;	/* for L2_FILTER ARP table timeout */
-#endif /* DHD_L2_FILTER */
-	uint8 *soc_ram;
-	uint32 soc_ram_length;
-	uint32 memdump_type;
-#ifdef DHD_FW_COREDUMP
-	uint32 memdump_enabled;
-#endif /* DHD_FW_COREDUMP */
-#ifdef PCIE_FULL_DONGLE
-#ifdef WLTDLS
-	tdls_peer_tbl_t peer_tbl;
-#endif /* WLTDLS */
-#endif /* PCIE_FULL_DONGLE */
-#ifdef CACHE_FW_IMAGES
-	char	*cached_fw;
-	int	cached_fw_length;
-	char	*cached_nvram;
-	int	cached_nvram_length;
-#endif
-#ifdef WLTDLS
-	uint32 tdls_mode;
-#endif
-#ifdef DHD_LOSSLESS_ROAMING
-	uint8 dequeue_prec_map;
-#endif
-	struct mutex wl_up_lock;
-	bool is_fw_download_done;
-#ifdef DHD_LOG_DUMP
-	struct dhd_log_dump_buf dld_buf;
-	unsigned int dld_enable;
-#endif /* DHD_LOG_DUMP */
-} dhd_pub_t;
-
-#if defined(PCIE_FULL_DONGLE)
-
-/* Packet Tag for PCIE Full Dongle DHD */
-typedef struct dhd_pkttag_fd {
-	uint16    flowid;   /* Flowring Id */
-	uint16    dataoff;  /* start of packet */
-	uint16    dma_len;  /* pkt len for DMA_MAP/UNMAP */
-	dmaaddr_t pa;       /* physical address */
-	void      *dmah;    /* dma mapper handle */
-	void      *secdma; /* secure dma sec_cma_info handle */
-} dhd_pkttag_fd_t;
-
-/* Packet Tag for DHD PCIE Full Dongle */
-#define DHD_PKTTAG_FD(pkt)          ((dhd_pkttag_fd_t *)(PKTTAG(pkt)))
-
-#define DHD_PKT_GET_FLOWID(pkt)     ((DHD_PKTTAG_FD(pkt))->flowid)
-#define DHD_PKT_SET_FLOWID(pkt, pkt_flowid) \
-	DHD_PKTTAG_FD(pkt)->flowid = (uint16)(pkt_flowid)
-
-#define DHD_PKT_GET_DATAOFF(pkt)    ((DHD_PKTTAG_FD(pkt))->dataoff)
-#define DHD_PKT_SET_DATAOFF(pkt, pkt_dataoff) \
-	DHD_PKTTAG_FD(pkt)->dataoff = (uint16)(pkt_dataoff)
-
-#define DHD_PKT_GET_DMA_LEN(pkt)    ((DHD_PKTTAG_FD(pkt))->dma_len)
-#define DHD_PKT_SET_DMA_LEN(pkt, pkt_dma_len) \
-	DHD_PKTTAG_FD(pkt)->dma_len = (uint16)(pkt_dma_len)
-
-#define DHD_PKT_GET_PA(pkt)         ((DHD_PKTTAG_FD(pkt))->pa)
-#define DHD_PKT_SET_PA(pkt, pkt_pa) \
-	DHD_PKTTAG_FD(pkt)->pa = (dmaaddr_t)(pkt_pa)
-
-#define DHD_PKT_GET_DMAH(pkt)       ((DHD_PKTTAG_FD(pkt))->dmah)
-#define DHD_PKT_SET_DMAH(pkt, pkt_dmah) \
-	DHD_PKTTAG_FD(pkt)->dmah = (void *)(pkt_dmah)
-
-#define DHD_PKT_GET_SECDMA(pkt)    ((DHD_PKTTAG_FD(pkt))->secdma)
-#define DHD_PKT_SET_SECDMA(pkt, pkt_secdma) \
-	DHD_PKTTAG_FD(pkt)->secdma = (void *)(pkt_secdma)
-#endif /* PCIE_FULL_DONGLE */
-
-#if defined(BCMWDF)
-typedef struct {
-	dhd_pub_t *dhd_pub;
-} dhd_workitem_context_t;
-
-WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(dhd_workitem_context_t, dhd_get_dhd_workitem_context)
-#endif /* (BCMWDF)  */
-
-	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
-
-	#define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-	#define _DHD_PM_RESUME_WAIT(a, b) do {\
-			int retry = 0; \
-			SMP_RD_BARRIER_DEPENDS(); \
-			while (dhd_mmc_suspend && retry++ != b) { \
-				SMP_RD_BARRIER_DEPENDS(); \
-				wait_event_interruptible_timeout(a, !dhd_mmc_suspend, 1); \
-			} \
-		} 	while (0)
-	#define DHD_PM_RESUME_WAIT(a) 		_DHD_PM_RESUME_WAIT(a, 200)
-	#define DHD_PM_RESUME_WAIT_FOREVER(a) 	_DHD_PM_RESUME_WAIT(a, ~0)
-	#define DHD_PM_RESUME_RETURN_ERROR(a)   do { \
-			if (dhd_mmc_suspend) { \
-				printf("%s[%d]: mmc is still in suspend state!!!\n", \
-					__FUNCTION__, __LINE__); \
-				return a; \
-			} \
-		} while (0)
-	#define DHD_PM_RESUME_RETURN		do { if (dhd_mmc_suspend) return; } while (0)
-
-	#define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-	#define SPINWAIT_SLEEP(a, exp, us) do { \
-		uint countdown = (us) + 9999; \
-		while ((exp) && (countdown >= 10000)) { \
-			wait_event_interruptible_timeout(a, FALSE, 1); \
-			countdown -= 10000; \
-		} \
-	} while (0)
-
-	#else
-
-	#define DHD_PM_RESUME_WAIT_INIT(a)
-	#define DHD_PM_RESUME_WAIT(a)
-	#define DHD_PM_RESUME_WAIT_FOREVER(a)
-	#define DHD_PM_RESUME_RETURN_ERROR(a)
-	#define DHD_PM_RESUME_RETURN
-
-	#define DHD_SPINWAIT_SLEEP_INIT(a)
-	#define SPINWAIT_SLEEP(a, exp, us)  do { \
-		uint countdown = (us) + 9; \
-		while ((exp) && (countdown >= 10)) { \
-			OSL_DELAY(10);  \
-			countdown -= 10;  \
-		} \
-	} while (0)
-
-	#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
-
-#ifndef OSL_SLEEP
-#define OSL_SLEEP(ms)		OSL_DELAY(ms*1000)
-#endif /* OSL_SLEEP */
-
-#define DHD_IF_VIF	0x01	/* Virtual IF (Hidden from user) */
-
-#ifdef PNO_SUPPORT
-int dhd_pno_clean(dhd_pub_t *dhd);
-#endif /* PNO_SUPPORT */
-/*
- *  Wake locks are an Android power management concept. They are used by applications and services
- *  to request CPU resources.
- */
-extern int dhd_os_wake_lock(dhd_pub_t *pub);
-extern int dhd_os_wake_unlock(dhd_pub_t *pub);
-extern int dhd_event_wake_lock(dhd_pub_t *pub);
-extern int dhd_event_wake_unlock(dhd_pub_t *pub);
-extern int dhd_os_wake_lock_waive(dhd_pub_t *pub);
-extern int dhd_os_wake_lock_restore(dhd_pub_t *pub);
-extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub);
-extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val);
-extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val);
-extern int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub);
-extern int dhd_os_wd_wake_lock(dhd_pub_t *pub);
-extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub);
-extern void dhd_os_wake_lock_init(struct dhd_info *dhd);
-extern void dhd_os_wake_lock_destroy(struct dhd_info *dhd);
-#ifdef BCMPCIE_OOB_HOST_WAKE
-extern void dhd_os_oob_irq_wake_lock_timeout(dhd_pub_t *pub, int val);
-extern void dhd_os_oob_irq_wake_unlock(dhd_pub_t *pub);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-#ifdef DHD_USE_SCAN_WAKELOCK
-extern void dhd_os_scan_wake_lock_timeout(dhd_pub_t *pub, int val);
-extern void dhd_os_scan_wake_unlock(dhd_pub_t *pub);
-#endif /* BCMPCIE_SCAN_WAKELOCK */
-
-inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	mutex_init(&dhdp->wl_softap_lock);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-}
-
-inline static void MUTEX_LOCK_SOFTAP_SET(dhd_pub_t * dhdp)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	mutex_lock(&dhdp->wl_softap_lock);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-}
-
-inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	mutex_unlock(&dhdp->wl_softap_lock);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-}
-
-#define DHD_OS_WAKE_LOCK(pub)			dhd_os_wake_lock(pub)
-#define DHD_OS_WAKE_UNLOCK(pub)		dhd_os_wake_unlock(pub)
-#define DHD_EVENT_WAKE_LOCK(pub)			dhd_event_wake_lock(pub)
-#define DHD_EVENT_WAKE_UNLOCK(pub)		dhd_event_wake_unlock(pub)
-#define DHD_OS_WAKE_LOCK_TIMEOUT(pub)		dhd_os_wake_lock_timeout(pub)
-#define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) \
-	dhd_os_wake_lock_rx_timeout_enable(pub, val)
-#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) \
-	dhd_os_wake_lock_ctrl_timeout_enable(pub, val)
-#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL(pub) \
-	dhd_os_wake_lock_ctrl_timeout_cancel(pub)
-#define DHD_OS_WAKE_LOCK_WAIVE(pub)			dhd_os_wake_lock_waive(pub)
-#define DHD_OS_WAKE_LOCK_RESTORE(pub)		dhd_os_wake_lock_restore(pub)
-#define DHD_OS_WAKE_LOCK_INIT(dhd)		dhd_os_wake_lock_init(dhd);
-#define DHD_OS_WAKE_LOCK_DESTROY(dhd)		dhd_os_wake_lock_destroy(dhd);
-
-#define DHD_OS_WD_WAKE_LOCK(pub)		dhd_os_wd_wake_lock(pub)
-#define DHD_OS_WD_WAKE_UNLOCK(pub)		dhd_os_wd_wake_unlock(pub)
-
-#ifdef BCMPCIE_OOB_HOST_WAKE
-#define OOB_WAKE_LOCK_TIMEOUT 500
-#define DHD_OS_OOB_IRQ_WAKE_LOCK_TIMEOUT(pub, val)	dhd_os_oob_irq_wake_lock_timeout(pub, val)
-#define DHD_OS_OOB_IRQ_WAKE_UNLOCK(pub)			dhd_os_oob_irq_wake_unlock(pub)
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-#ifdef DHD_USE_SCAN_WAKELOCK
-#ifdef DHD_DEBUG_SCAN_WAKELOCK
-#define DHD_OS_SCAN_WAKE_LOCK_TIMEOUT(pub, val) \
-	do { \
-		printf("call wake_lock_scan: %s %d\n", \
-			__FUNCTION__, __LINE__); \
-		dhd_os_scan_wake_lock_timeout(pub, val); \
-	} while (0)
-#define DHD_OS_SCAN_WAKE_UNLOCK(pub) \
-	do { \
-		printf("call wake_unlock_scan: %s %d\n", \
-			__FUNCTION__, __LINE__); \
-		dhd_os_scan_wake_unlock(pub); \
-	} while (0)
-#else
-#define DHD_OS_SCAN_WAKE_LOCK_TIMEOUT(pub, val)		dhd_os_scan_wake_lock_timeout(pub, val)
-#define DHD_OS_SCAN_WAKE_UNLOCK(pub)			dhd_os_scan_wake_unlock(pub)
-#endif /* DHD_DEBUG_SCAN_WAKELOCK */
-#else
-#define DHD_OS_SCAN_WAKE_LOCK_TIMEOUT(pub, val)
-#define DHD_OS_SCAN_WAKE_UNLOCK(pub)
-#endif /* DHD_USE_SCAN_WAKELOCK */
-#define DHD_PACKET_TIMEOUT_MS	500
-#define DHD_EVENT_TIMEOUT_MS	1500
-#define SCAN_WAKE_LOCK_TIMEOUT	10000
-
-/* Enum for IOCTL recieved status */
-typedef enum dhd_ioctl_recieved_status
-{
-	IOCTL_WAIT = 0,
-	IOCTL_RETURN_ON_SUCCESS,
-	IOCTL_RETURN_ON_TRAP,
-	IOCTL_RETURN_ON_BUS_STOP
-} dhd_ioctl_recieved_status_t;
-
-/* interface operations (register, remove) should be atomic, use this lock to prevent race
- * condition among wifi on/off and interface operation functions
- */
-void dhd_net_if_lock(struct net_device *dev);
-void dhd_net_if_unlock(struct net_device *dev);
-
-
-typedef enum dhd_attach_states
-{
-	DHD_ATTACH_STATE_INIT = 0x0,
-	DHD_ATTACH_STATE_NET_ALLOC = 0x1,
-	DHD_ATTACH_STATE_DHD_ALLOC = 0x2,
-	DHD_ATTACH_STATE_ADD_IF = 0x4,
-	DHD_ATTACH_STATE_PROT_ATTACH = 0x8,
-	DHD_ATTACH_STATE_WL_ATTACH = 0x10,
-	DHD_ATTACH_STATE_THREADS_CREATED = 0x20,
-	DHD_ATTACH_STATE_WAKELOCKS_INIT = 0x40,
-	DHD_ATTACH_STATE_CFG80211 = 0x80,
-	DHD_ATTACH_STATE_EARLYSUSPEND_DONE = 0x100,
-	DHD_ATTACH_STATE_DONE = 0x200
-} dhd_attach_states_t;
-
-/* Value -1 means we are unsuccessful in creating the kthread. */
-#define DHD_PID_KT_INVALID 	-1
-/* Value -2 means we are unsuccessful in both creating the kthread and tasklet */
-#define DHD_PID_KT_TL_INVALID	-2
-
-/*
- * Exported from dhd OS modules (dhd_linux/dhd_ndis)
- */
-
-/* Indication from bus module regarding presence/insertion of dongle.
- * Return dhd_pub_t pointer, used as handle to OS module in later calls.
- * Returned structure should have bus and prot pointers filled in.
- * bus_hdrlen specifies required headroom for bus module header.
- */
-extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen);
-#if defined(WLP2P) && defined(WL_CFG80211)
-/* To allow attach/detach calls corresponding to p2p0 interface  */
-extern int dhd_attach_p2p(dhd_pub_t *);
-extern int dhd_detach_p2p(dhd_pub_t *);
-#endif /* WLP2P && WL_CFG80211 */
-extern int dhd_register_if(dhd_pub_t *dhdp, int idx, bool need_rtnl_lock);
-
-/* Indication from bus module regarding removal/absence of dongle */
-extern void dhd_detach(dhd_pub_t *dhdp);
-extern void dhd_free(dhd_pub_t *dhdp);
-extern void dhd_clear(dhd_pub_t *dhdp);
-
-/* Indication from bus module to change flow-control state */
-extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on);
-
-/* Store the status of a connection attempt for later retrieval by an iovar */
-extern void dhd_store_conn_status(uint32 event, uint32 status, uint32 reason);
-
-extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec);
-
-/* Receive frame for delivery to OS.  Callee disposes of rxp. */
-extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *rxp, int numpkt, uint8 chan);
-
-/* Return pointer to interface name */
-extern char *dhd_ifname(dhd_pub_t *dhdp, int idx);
-
-/* Request scheduling of the bus dpc */
-extern void dhd_sched_dpc(dhd_pub_t *dhdp);
-
-/* Notify tx completion */
-extern void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success);
-extern void dhd_dpc_enable(dhd_pub_t *dhdp);
-
-#define WIFI_FEATURE_INFRA              0x0001      /* Basic infrastructure mode        */
-#define WIFI_FEATURE_INFRA_5G           0x0002      /* Support for 5 GHz Band           */
-#define WIFI_FEATURE_HOTSPOT            0x0004      /* Support for GAS/ANQP             */
-#define WIFI_FEATURE_P2P                0x0008      /* Wifi-Direct                      */
-#define WIFI_FEATURE_SOFT_AP            0x0010      /* Soft AP                          */
-#define WIFI_FEATURE_GSCAN              0x0020      /* Google-Scan APIs                 */
-#define WIFI_FEATURE_NAN                0x0040      /* Neighbor Awareness Networking    */
-#define WIFI_FEATURE_D2D_RTT            0x0080      /* Device-to-device RTT             */
-#define WIFI_FEATURE_D2AP_RTT           0x0100      /* Device-to-AP RTT                 */
-#define WIFI_FEATURE_BATCH_SCAN         0x0200      /* Batched Scan (legacy)            */
-#define WIFI_FEATURE_PNO                0x0400      /* Preferred network offload        */
-#define WIFI_FEATURE_ADDITIONAL_STA     0x0800      /* Support for two STAs             */
-#define WIFI_FEATURE_TDLS               0x1000      /* Tunnel directed link setup       */
-#define WIFI_FEATURE_TDLS_OFFCHANNEL    0x2000      /* Support for TDLS off channel     */
-#define WIFI_FEATURE_EPR                0x4000      /* Enhanced power reporting         */
-#define WIFI_FEATURE_AP_STA             0x8000      /* Support for AP STA Concurrency   */
-#define WIFI_FEATURE_LINKSTAT           0x10000     /* Support for Linkstats            */
-
-#define MAX_FEATURE_SET_CONCURRRENT_GROUPS  3
-
-extern int dhd_dev_get_feature_set(struct net_device *dev);
-extern int *dhd_dev_get_feature_set_matrix(struct net_device *dev,      int *num);
-#ifdef CUSTOM_FORCE_NODFS_FLAG
-extern int dhd_dev_set_nodfs(struct net_device *dev, uint nodfs);
-#endif /* CUSTOM_FORCE_NODFS_FLAG */
-/* OS independent layer functions */
-extern void dhd_os_dhdiovar_lock(dhd_pub_t *pub);
-extern void dhd_os_dhdiovar_unlock(dhd_pub_t *pub);
-extern int dhd_os_proto_block(dhd_pub_t * pub);
-extern int dhd_os_proto_unblock(dhd_pub_t * pub);
-extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition);
-extern int dhd_os_ioctl_resp_wake(dhd_pub_t * pub);
-extern unsigned int dhd_os_get_ioctl_resp_timeout(void);
-extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
-extern void dhd_os_ioctl_resp_lock(dhd_pub_t * pub);
-extern void dhd_os_ioctl_resp_unlock(dhd_pub_t * pub);
-extern int dhd_wakeup_ioctl_event(dhd_pub_t *pub, dhd_ioctl_recieved_status_t reason);
-
-#define DHD_OS_IOCTL_RESP_LOCK(x)
-#define DHD_OS_IOCTL_RESP_UNLOCK(x)
-
-
-extern int dhd_os_get_image_block(char * buf, int len, void * image);
-extern void * dhd_os_open_image(char * filename);
-extern void dhd_os_close_image(void * image);
-extern void dhd_os_wd_timer(void *bus, uint wdtick);
-#ifdef DHD_PCIE_RUNTIMEPM
-extern void dhd_os_runtimepm_timer(void *bus, uint tick);
-#endif /* DHD_PCIE_RUNTIMEPM */
-extern void dhd_os_sdlock(dhd_pub_t * pub);
-extern void dhd_os_sdunlock(dhd_pub_t * pub);
-extern void dhd_os_sdlock_txq(dhd_pub_t * pub);
-extern void dhd_os_sdunlock_txq(dhd_pub_t * pub);
-extern void dhd_os_sdlock_rxq(dhd_pub_t * pub);
-extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub);
-extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub);
-#ifdef DHDTCPACK_SUPPRESS
-extern unsigned long dhd_os_tcpacklock(dhd_pub_t *pub);
-extern void dhd_os_tcpackunlock(dhd_pub_t *pub, unsigned long flags);
-#endif /* DHDTCPACK_SUPPRESS */
-
-extern int dhd_customer_oob_irq_map(void *adapter, unsigned long *irq_flags_ptr);
-extern int dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff);
-extern int dhd_custom_get_mac_address(void *adapter, unsigned char *buf);
-#ifdef CUSTOM_COUNTRY_CODE
-extern void get_customized_country_code(void *adapter, char *country_iso_code,
-wl_country_t *cspec, u32 flags);
-#else
-extern void get_customized_country_code(void *adapter, char *country_iso_code, wl_country_t *cspec);
-#endif /* CUSTOM_COUNTRY_CODE */
-extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub);
-extern void dhd_os_sdlock_eventq(dhd_pub_t * pub);
-extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub);
-extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret);
-extern int dhd_os_send_hang_message(dhd_pub_t *dhdp);
-extern void dhd_set_version_info(dhd_pub_t *pub, char *fw);
-extern bool dhd_os_check_if_up(dhd_pub_t *pub);
-extern int dhd_os_check_wakelock(dhd_pub_t *pub);
-extern int dhd_os_check_wakelock_all(dhd_pub_t *pub);
-extern int dhd_get_instance(dhd_pub_t *pub);
-#ifdef CUSTOM_SET_CPUCORE
-extern void dhd_set_cpucore(dhd_pub_t *dhd, int set);
-#endif /* CUSTOM_SET_CPUCORE */
-
-#if defined(KEEP_ALIVE)
-extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
-#endif /* KEEP_ALIVE */
-
-#ifdef SUPPORT_AP_POWERSAVE
-extern int dhd_set_ap_powersave(dhd_pub_t *dhdp, int ifidx, int enable);
-#endif
-
-#if defined(DHD_FW_COREDUMP)
-void dhd_schedule_memdump(dhd_pub_t *dhdp, uint8 *buf, uint32 size);
-#endif /* DHD_FW_COREDUMP */
-
-#ifdef SUPPORT_AP_POWERSAVE
-extern int dhd_set_ap_powersave(dhd_pub_t *dhdp, int ifidx, int enable);
-#endif /* SUPPORT_AP_POWERSAVE */
-
-
-#ifdef PKT_FILTER_SUPPORT
-#define DHD_UNICAST_FILTER_NUM		0
-#define DHD_BROADCAST_FILTER_NUM	1
-#define DHD_MULTICAST4_FILTER_NUM	2
-#define DHD_MULTICAST6_FILTER_NUM	3
-#define DHD_MDNS_FILTER_NUM		4
-#define DHD_ARP_FILTER_NUM		5
-extern int 	dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val);
-extern void dhd_enable_packet_filter(int value, dhd_pub_t *dhd);
-extern int net_os_enable_packet_filter(struct net_device *dev, int val);
-extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num);
-#endif /* PKT_FILTER_SUPPORT */
-
-extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd);
-extern bool dhd_support_sta_mode(dhd_pub_t *dhd);
-
-extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size);
-
-typedef struct {
-	uint32 limit;		/* Expiration time (usec) */
-	uint32 increment;	/* Current expiration increment (usec) */
-	uint32 elapsed;		/* Current elapsed time (usec) */
-	uint32 tick;		/* O/S tick time (usec) */
-} dhd_timeout_t;
-
-#ifdef SHOW_LOGTRACE
-typedef struct {
-	int  num_fmts;
-	char **fmts;
-	char *raw_fmts;
-	char *raw_sstr;
-	uint32 ramstart;
-	uint32 rodata_start;
-	uint32 rodata_end;
-	char *rom_raw_sstr;
-	uint32 rom_ramstart;
-	uint32 rom_rodata_start;
-	uint32 rom_rodata_end;
-} dhd_event_log_t;
-#endif /* SHOW_LOGTRACE */
-
-extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec);
-extern int dhd_timeout_expired(dhd_timeout_t *tmo);
-
-extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
-extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net);
-extern struct net_device * dhd_idx2net(void *pub, int ifidx);
-extern int net_os_send_hang_message(struct net_device *dev);
-extern int net_os_send_hang_message_reason(struct net_device *dev, const char *string_num);
-extern bool dhd_wowl_cap(void *bus);
-
-extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, size_t pktlen,
-                         wl_event_msg_t *, void **data_ptr,  void *);
-extern void wl_event_to_host_order(wl_event_msg_t * evt);
-extern int wl_host_event_get_data(void *pktdata, wl_event_msg_t *event, void **data_ptr);
-
-extern int dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len);
-extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set,
-                            int ifindex);
-extern int dhd_wl_ioctl_get_intiovar(dhd_pub_t *dhd_pub, char *name, uint *pval,
-	int cmd, uint8 set, int ifidx);
-extern int dhd_wl_ioctl_set_intiovar(dhd_pub_t *dhd_pub, char *name, uint val,
-	int cmd, uint8 set, int ifidx);
-extern void dhd_common_init(osl_t *osh);
-
-extern int dhd_do_driver_init(struct net_device *net);
-extern int dhd_event_ifadd(struct dhd_info *dhd, struct wl_event_data_if *ifevent,
-	char *name, uint8 *mac);
-extern int dhd_event_ifdel(struct dhd_info *dhd, struct wl_event_data_if *ifevent,
-	char *name, uint8 *mac);
-extern struct net_device* dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, char *name,
-	uint8 *mac, uint8 bssidx, bool need_rtnl_lock, char *dngl_name);
-extern int dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock);
-extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char * name);
-extern void dhd_vif_del(struct dhd_info *dhd, int ifidx);
-extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx);
-extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len);
-
-/* Send packet to dongle via data channel */
-extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt);
-
-/* send up locally generated event */
-extern void dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data);
-/* Send event to host */
-extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data);
-#ifdef LOG_INTO_TCPDUMP
-extern void dhd_sendup_log(dhd_pub_t *dhdp, void *data, int len);
-#endif /* LOG_INTO_TCPDUMP */
-extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag);
-extern uint dhd_bus_status(dhd_pub_t *dhdp);
-extern int  dhd_bus_start(dhd_pub_t *dhdp);
-extern int dhd_bus_suspend(dhd_pub_t *dhdpub);
-extern int dhd_bus_resume(dhd_pub_t *dhdpub, int stage);
-extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size);
-extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line);
-extern bool dhd_is_associated(dhd_pub_t *dhd, uint8 ifidx, int *retval);
-#if defined(BCMSDIO) || defined(BCMPCIE)
-extern uint dhd_bus_chip_id(dhd_pub_t *dhdp);
-extern uint dhd_bus_chiprev_id(dhd_pub_t *dhdp);
-extern uint dhd_bus_chippkg_id(dhd_pub_t *dhdp);
-#endif /* defined(BCMSDIO) || defined(BCMPCIE) */
-
-#if defined(KEEP_ALIVE)
-extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
-#endif /* KEEP_ALIVE */
-
-/* OS spin lock API */
-extern void *dhd_os_spin_lock_init(osl_t *osh);
-extern void dhd_os_spin_lock_deinit(osl_t *osh, void *lock);
-extern unsigned long dhd_os_spin_lock(void *lock);
-void dhd_os_spin_unlock(void *lock, unsigned long flags);
-
-/*
- * Manage sta objects in an interface. Interface is identified by an ifindex and
- * sta(s) within an interfaces are managed using a MacAddress of the sta.
- */
-struct dhd_sta;
-extern struct dhd_sta *dhd_findadd_sta(void *pub, int ifidx, void *ea);
-extern void dhd_del_sta(void *pub, int ifidx, void *ea);
-extern int dhd_get_ap_isolate(dhd_pub_t *dhdp, uint32 idx);
-extern int dhd_set_ap_isolate(dhd_pub_t *dhdp, uint32 idx, int val);
-#if defined(BCM_GMAC3)
-extern int dhd_set_dev_def(dhd_pub_t *dhdp, uint32 idx, int val);
-#endif
-extern int dhd_bssidx2idx(dhd_pub_t *dhdp, uint32 bssidx);
-extern int dhd_os_d3ack_wait(dhd_pub_t * pub, uint * condition);
-extern int dhd_os_d3ack_wake(dhd_pub_t * pub);
-extern int dhd_os_busbusy_wait_negation(dhd_pub_t * pub, uint * condition);
-extern int dhd_os_busbusy_wake(dhd_pub_t * pub);
-
-extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd);
-extern int dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set);
-typedef enum cust_gpio_modes {
-	WLAN_RESET_ON,
-	WLAN_RESET_OFF,
-	WLAN_POWER_ON,
-	WLAN_POWER_OFF
-} cust_gpio_modes_t;
-
-extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
-extern int wl_iw_send_priv_event(struct net_device *dev, char *flag);
-/*
- * Insmod parameters for debug/test
- */
-
-/* Watchdog timer interval */
-extern uint dhd_watchdog_ms;
-
-#ifdef DHD_PCIE_RUNTIMEPM
-extern uint dhd_runtimepm_ms;
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-#if defined(DHD_DEBUG)
-/* Console output poll interval */
-extern uint dhd_console_ms;
-extern uint wl_msg_level;
-#endif /* defined(DHD_DEBUG) */
-
-extern uint dhd_slpauto;
-
-/* Use interrupts */
-extern uint dhd_intr;
-
-/* Use polling */
-extern uint dhd_poll;
-
-/* ARP offload agent mode */
-extern uint dhd_arp_mode;
-
-/* ARP offload enable */
-extern uint dhd_arp_enable;
-
-/* Pkt filte enable control */
-extern uint dhd_pkt_filter_enable;
-
-/*  Pkt filter init setup */
-extern uint dhd_pkt_filter_init;
-
-/* Pkt filter mode control */
-extern uint dhd_master_mode;
-
-/* Roaming mode control */
-extern uint dhd_roam_disable;
-
-/* Roaming mode control */
-extern uint dhd_radio_up;
-
-/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
-extern int dhd_idletime;
-#ifdef DHD_USE_IDLECOUNT
-#define DHD_IDLETIME_TICKS 5
-#else
-#define DHD_IDLETIME_TICKS 1
-#endif /* DHD_USE_IDLECOUNT */
-
-/* SDIO Drive Strength */
-extern uint dhd_sdiod_drive_strength;
-
-/* triggers bcm_bprintf to print to kernel log */
-extern bool bcm_bprintf_bypass;
-
-/* Override to force tx queueing all the time */
-extern uint dhd_force_tx_queueing;
-/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */
-#define DEFAULT_KEEP_ALIVE_VALUE 	55000 /* msec */
-#ifndef CUSTOM_KEEP_ALIVE_SETTING
-#define CUSTOM_KEEP_ALIVE_SETTING 	DEFAULT_KEEP_ALIVE_VALUE
-#endif /* DEFAULT_KEEP_ALIVE_VALUE */
-
-#define NULL_PKT_STR	"null_pkt"
-
-/* hooks for custom glom setting option via Makefile */
-#define DEFAULT_GLOM_VALUE 	-1
-#ifndef CUSTOM_GLOM_SETTING
-#define CUSTOM_GLOM_SETTING 	DEFAULT_GLOM_VALUE
-#endif
-#define WL_AUTO_ROAM_TRIGGER -75
-/* hooks for custom Roaming Trigger  setting via Makefile */
-#define DEFAULT_ROAM_TRIGGER_VALUE -75 /* dBm default roam trigger all band */
-#define DEFAULT_ROAM_TRIGGER_SETTING 	-1
-#ifndef CUSTOM_ROAM_TRIGGER_SETTING
-#define CUSTOM_ROAM_TRIGGER_SETTING 	DEFAULT_ROAM_TRIGGER_VALUE
-#endif
-
-/* hooks for custom Roaming Romaing  setting via Makefile */
-#define DEFAULT_ROAM_DELTA_VALUE  10 /* dBm default roam delta all band */
-#define DEFAULT_ROAM_DELTA_SETTING 	-1
-#ifndef CUSTOM_ROAM_DELTA_SETTING
-#define CUSTOM_ROAM_DELTA_SETTING 	DEFAULT_ROAM_DELTA_VALUE
-#endif
-
-/* hooks for custom PNO Event wake lock to guarantee enough time
-	for the Platform to detect Event before system suspended
-*/
-#define DEFAULT_PNO_EVENT_LOCK_xTIME 	2 	/* multiplay of DHD_PACKET_TIMEOUT_MS */
-#ifndef CUSTOM_PNO_EVENT_LOCK_xTIME
-#define CUSTOM_PNO_EVENT_LOCK_xTIME	 DEFAULT_PNO_EVENT_LOCK_xTIME
-#endif
-/* hooks for custom dhd_dpc_prio setting option via Makefile */
-#define DEFAULT_DHP_DPC_PRIO  1
-#ifndef CUSTOM_DPC_PRIO_SETTING
-#define CUSTOM_DPC_PRIO_SETTING 	DEFAULT_DHP_DPC_PRIO
-#endif
-
-#ifndef CUSTOM_LISTEN_INTERVAL
-#define CUSTOM_LISTEN_INTERVAL 		LISTEN_INTERVAL
-#endif /* CUSTOM_LISTEN_INTERVAL */
-
-#define DEFAULT_SUSPEND_BCN_LI_DTIM		3
-#ifndef CUSTOM_SUSPEND_BCN_LI_DTIM
-#define CUSTOM_SUSPEND_BCN_LI_DTIM		DEFAULT_SUSPEND_BCN_LI_DTIM
-#endif
-
-#ifndef CUSTOM_RXF_PRIO_SETTING
-#define CUSTOM_RXF_PRIO_SETTING		MAX((CUSTOM_DPC_PRIO_SETTING - 1), 1)
-#endif
-
-#define DEFAULT_WIFI_TURNOFF_DELAY		0
-#define WIFI_TURNOFF_DELAY		DEFAULT_WIFI_TURNOFF_DELAY
-
-#define DEFAULT_WIFI_TURNON_DELAY		200
-#ifndef WIFI_TURNON_DELAY
-#define WIFI_TURNON_DELAY		DEFAULT_WIFI_TURNON_DELAY
-#endif /* WIFI_TURNON_DELAY */
-
-#define DEFAULT_DHD_WATCHDOG_INTERVAL_MS	10 /* msec */
-#ifndef CUSTOM_DHD_WATCHDOG_MS
-#define CUSTOM_DHD_WATCHDOG_MS			DEFAULT_DHD_WATCHDOG_INTERVAL_MS
-#endif /* DEFAULT_DHD_WATCHDOG_INTERVAL_MS */
-
-#define DEFAULT_ASSOC_RETRY_MAX			3
-#ifndef CUSTOM_ASSOC_RETRY_MAX
-#define CUSTOM_ASSOC_RETRY_MAX			DEFAULT_ASSOC_RETRY_MAX
-#endif /* DEFAULT_ASSOC_RETRY_MAX */
-
-
-#ifdef WLTDLS
-#ifndef CUSTOM_TDLS_IDLE_MODE_SETTING
-#define CUSTOM_TDLS_IDLE_MODE_SETTING  60000 /* 60sec to tear down TDLS of not active */
-#endif
-#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_HIGH
-#define CUSTOM_TDLS_RSSI_THRESHOLD_HIGH -70 /* rssi threshold for establishing TDLS link */
-#endif
-#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_LOW
-#define CUSTOM_TDLS_RSSI_THRESHOLD_LOW -80 /* rssi threshold for tearing down TDLS link */
-#endif
-#endif /* WLTDLS */
-
-#define DEFAULT_BCN_TIMEOUT		8
-#ifndef CUSTOM_BCN_TIMEOUT
-#define CUSTOM_BCN_TIMEOUT		DEFAULT_BCN_TIMEOUT
-#endif
-
-#define MAX_DTIM_SKIP_BEACON_INTERVAL	100 /* max allowed associated AP beacon for DTIM skip */
-#ifndef MAX_DTIM_ALLOWED_INTERVAL
-#define MAX_DTIM_ALLOWED_INTERVAL 600 /* max allowed total beacon interval for DTIM skip */
-#endif
-#define NO_DTIM_SKIP 1
-#ifdef SDTEST
-/* Echo packet generator (SDIO), pkts/s */
-extern uint dhd_pktgen;
-
-/* Echo packet len (0 => sawtooth, max 1800) */
-extern uint dhd_pktgen_len;
-#define MAX_PKTGEN_LEN 1800
-#endif
-
-
-/* optionally set by a module_param_string() */
-#define MOD_PARAM_PATHLEN	2048
-#define MOD_PARAM_INFOLEN	512
-
-#ifdef SOFTAP
-extern char fw_path2[MOD_PARAM_PATHLEN];
-#endif
-
-/* Flag to indicate if we should download firmware on driver load */
-extern uint dhd_download_fw_on_driverload;
-extern int allow_delay_fwdl;
-
-
-extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
-extern void dhd_wait_event_wakeup(dhd_pub_t*dhd);
-
-#define IFLOCK_INIT(lock)       *lock = 0
-#define IFLOCK(lock)    while (InterlockedCompareExchange((lock), 1, 0))	\
-	NdisStallExecution(1);
-#define IFUNLOCK(lock)  InterlockedExchange((lock), 0)
-#define IFLOCK_FREE(lock)
-#define FW_SUPPORTED(dhd, capa) ((strstr(dhd->fw_capabilities, " " #capa " ") != NULL))
-#ifdef ARP_OFFLOAD_SUPPORT
-#define MAX_IPV4_ENTRIES	8
-void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode);
-void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable);
-
-/* dhd_commn arp offload wrapers */
-void dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx);
-void dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx);
-int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx);
-void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx);
-#endif /* ARP_OFFLOAD_SUPPORT */
-#ifdef WLTDLS
-int dhd_tdls_enable(struct net_device *dev, bool tdls_on, bool auto_on, struct ether_addr *mac);
-int dhd_tdls_set_mode(dhd_pub_t *dhd, bool wfd_mode);
-#ifdef PCIE_FULL_DONGLE
-void dhd_tdls_update_peer_info(struct net_device *dev, bool connect_disconnect, uint8 *addr);
-#endif /* PCIE_FULL_DONGLE */
-#endif /* WLTDLS */
-/* Neighbor Discovery Offload Support */
-extern int dhd_ndo_enable(dhd_pub_t * dhd, int ndo_enable);
-int dhd_ndo_add_ip(dhd_pub_t *dhd, char* ipaddr, int idx);
-int dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx);
-/* ioctl processing for nl80211 */
-int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc, void *data_buf);
-
-void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path);
-void dhd_set_bus_state(void *bus, uint32 state);
-
-/* Remove proper pkts(either one no-frag pkt or whole fragmented pkts) */
-typedef int (*f_droppkt_t)(dhd_pub_t *dhdp, int prec, void* p, bool bPktInQ);
-extern bool dhd_prec_drop_pkts(dhd_pub_t *dhdp, struct pktq *pq, int prec, f_droppkt_t fn);
-
-#ifdef PROP_TXSTATUS
-int dhd_os_wlfc_block(dhd_pub_t *pub);
-int dhd_os_wlfc_unblock(dhd_pub_t *pub);
-extern const uint8 prio2fifo[];
-#endif /* PROP_TXSTATUS */
-
-uint8* dhd_os_prealloc(dhd_pub_t *dhdpub, int section, uint size, bool kmalloc_if_fail);
-void dhd_os_prefree(dhd_pub_t *dhdpub, void *addr, uint size);
-
-int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost);
-
-#if defined(CONFIG_DHD_USE_STATIC_BUF)
-#define DHD_OS_PREALLOC(dhdpub, section, size) dhd_os_prealloc(dhdpub, section, size, FALSE)
-#define DHD_OS_PREFREE(dhdpub, addr, size) dhd_os_prefree(dhdpub, addr, size)
-#else
-#define DHD_OS_PREALLOC(dhdpub, section, size) MALLOC(dhdpub->osh, size)
-#define DHD_OS_PREFREE(dhdpub, addr, size) MFREE(dhdpub->osh, addr, size)
-#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */
-
-#ifdef USE_WFA_CERT_CONF
-enum {
-	SET_PARAM_BUS_TXGLOM_MODE,
-	SET_PARAM_ROAMOFF,
-#ifdef USE_WL_FRAMEBURST
-	SET_PARAM_FRAMEBURST,
-#endif /* USE_WL_FRAMEBURST */
-#ifdef USE_WL_TXBF
-	SET_PARAM_TXBF,
-#endif /* USE_WL_TXBF */
-#ifdef PROP_TXSTATUS
-	SET_PARAM_PROPTX,
-	SET_PARAM_PROPTXMODE,
-#endif /* PROP_TXSTATUS */
-	PARAM_LAST_VALUE
-};
-extern int sec_get_param_wfa_cert(dhd_pub_t *dhd, int mode, uint* read_val);
-#endif /* USE_WFA_CERT_CONF */
-
-#define dhd_add_flowid(pub, ifidx, ac_prio, ea, flowid)  do {} while (0)
-#define dhd_del_flowid(pub, ifidx, flowid)               do {} while (0)
-
-extern unsigned long dhd_os_general_spin_lock(dhd_pub_t *pub);
-extern void dhd_os_general_spin_unlock(dhd_pub_t *pub, unsigned long flags);
-
-/** Miscellaenous DHD Spin Locks */
-
-/* Disable router 3GMAC bypass path perimeter lock */
-#define DHD_PERIM_LOCK(dhdp)              do {} while (0)
-#define DHD_PERIM_UNLOCK(dhdp)            do {} while (0)
-#define DHD_PERIM_LOCK_ALL(processor_id)    do {} while (0)
-#define DHD_PERIM_UNLOCK_ALL(processor_id)  do {} while (0)
-
-/* Enable DHD general spin lock/unlock */
-#define DHD_GENERAL_LOCK(dhdp, flags) \
-	(flags) = dhd_os_general_spin_lock(dhdp)
-#define DHD_GENERAL_UNLOCK(dhdp, flags) \
-	dhd_os_general_spin_unlock((dhdp), (flags))
-
-/* Enable DHD flowring spin lock/unlock */
-#define DHD_FLOWRING_LOCK(lock, flags)     (flags) = dhd_os_spin_lock(lock)
-#define DHD_FLOWRING_UNLOCK(lock, flags)   dhd_os_spin_unlock((lock), (flags))
-
-/* Enable DHD common flowring info spin lock/unlock */
-#define DHD_FLOWID_LOCK(lock, flags)       (flags) = dhd_os_spin_lock(lock)
-#define DHD_FLOWID_UNLOCK(lock, flags)     dhd_os_spin_unlock((lock), (flags))
-
-/* Enable DHD common flowring list spin lock/unlock */
-#define DHD_FLOWRING_LIST_LOCK(lock, flags)       (flags) = dhd_os_spin_lock(lock)
-#define DHD_FLOWRING_LIST_UNLOCK(lock, flags)     dhd_os_spin_unlock((lock), (flags))
-
-extern void dhd_dump_to_kernelog(dhd_pub_t *dhdp);
-
-
-#ifdef DHD_L2_FILTER
-extern int dhd_get_parp_status(dhd_pub_t *dhdp, uint32 idx);
-extern int dhd_set_parp_status(dhd_pub_t *dhdp, uint32 idx, int val);
-extern int dhd_get_dhcp_unicast_status(dhd_pub_t *dhdp, uint32 idx);
-extern int dhd_set_dhcp_unicast_status(dhd_pub_t *dhdp, uint32 idx, int val);
-extern int dhd_get_block_ping_status(dhd_pub_t *dhdp, uint32 idx);
-extern int dhd_set_block_ping_status(dhd_pub_t *dhdp, uint32 idx, int val);
-extern int dhd_get_grat_arp_status(dhd_pub_t *dhdp, uint32 idx);
-extern int dhd_set_grat_arp_status(dhd_pub_t *dhdp, uint32 idx, int val);
-#endif /* DHD_L2_FILTER */
-
-typedef struct wl_io_pport {
-	dhd_pub_t *dhd_pub;
-	uint ifidx;
-} wl_io_pport_t;
-
-typedef struct wl_evt_pport {
-	dhd_pub_t *dhd_pub;
-	int *ifidx;
-	void *pktdata;
-	void **data_ptr;
-	void *raw_event;
-} wl_evt_pport_t;
-
-extern void *dhd_pub_shim(dhd_pub_t *dhd_pub);
-#ifdef DHD_FW_COREDUMP
-void dhd_save_fwdump(dhd_pub_t *dhd_pub, void * buffer, uint32 length);
-#endif /* DHD_FW_COREDUMP */
-
-#if defined(SET_RPS_CPUS)
-int dhd_rps_cpus_enable(struct net_device *net, int enable);
-int custom_rps_map_set(struct netdev_rx_queue *queue, char *buf, size_t len);
-void custom_rps_map_clear(struct netdev_rx_queue *queue);
-#define PRIMARY_INF 0
-#define VIRTUAL_INF 1
-#if defined(CONFIG_MACH_UNIVERSAL5433) || defined(CONFIG_MACH_UNIVERSAL7420) || \
-	defined(CONFIG_SOC_EXYNOS8890)
-#define RPS_CPUS_MASK "10"
-#define RPS_CPUS_MASK_P2P "10"
-#define RPS_CPUS_MASK_IBSS "10"
-#define RPS_CPUS_WLAN_CORE_ID 4
-#else
-#define RPS_CPUS_MASK "6"
-#define RPS_CPUS_MASK_P2P "6"
-#define RPS_CPUS_MASK_IBSS "6"
-#endif /* CONFIG_MACH_UNIVERSAL5433 || CONFIG_MACH_UNIVERSAL7420 || CONFIG_SOC_EXYNOS8890 */
-#endif 
-
-int dhd_get_download_buffer(dhd_pub_t	*dhd, char *file_path, download_type_t component,
-	char ** buffer, int *length);
-
-void dhd_free_download_buffer(dhd_pub_t	*dhd, void *buffer, int length);
-
-#define dhd_is_device_removed(x) FALSE
-#define dhd_os_ind_firmware_stall(x)
-
-#ifdef DHD_FW_COREDUMP
-extern void dhd_get_memdump_info(dhd_pub_t *dhd);
-#endif /* DHD_FW_COREDUMP */
-#ifdef BCMASSERT_LOG
-extern void dhd_get_assert_info(dhd_pub_t *dhd);
-#endif /* BCMASSERT_LOG */
-
-
-#if defined(DHD_LB_STATS)
-#include <bcmutils.h>
-extern void dhd_lb_stats_init(dhd_pub_t *dhd);
-extern void dhd_lb_stats_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
-extern void dhd_lb_stats_update_napi_histo(dhd_pub_t *dhdp, uint32 count);
-extern void dhd_lb_stats_update_txc_histo(dhd_pub_t *dhdp, uint32 count);
-extern void dhd_lb_stats_update_rxc_histo(dhd_pub_t *dhdp, uint32 count);
-extern void dhd_lb_stats_txc_percpu_cnt_incr(dhd_pub_t *dhdp);
-extern void dhd_lb_stats_rxc_percpu_cnt_incr(dhd_pub_t *dhdp);
-#define DHD_LB_STATS_INIT(dhdp) dhd_lb_stats_init(dhdp)
-/* Reset is called from common layer so it takes dhd_pub_t as argument */
-#define DHD_LB_STATS_RESET(dhdp) dhd_lb_stats_init(dhdp)
-#define DHD_LB_STATS_CLR(x)     (x) = 0U
-#define DHD_LB_STATS_INCR(x)    (x) = (x) + 1
-#define DHD_LB_STATS_ADD(x, c)  (x) = (x) + (c)
-#define DHD_LB_STATS_PERCPU_ARR_INCR(x) \
-	{ \
-		int cpu = get_cpu(); put_cpu(); \
-		DHD_LB_STATS_INCR(x[cpu]); \
-	}
-#define DHD_LB_STATS_UPDATE_NAPI_HISTO(dhdp, x) dhd_lb_stats_update_napi_histo(dhdp, x)
-#define DHD_LB_STATS_UPDATE_TXC_HISTO(dhdp, x)  dhd_lb_stats_update_txc_histo(dhdp, x)
-#define DHD_LB_STATS_UPDATE_RXC_HISTO(dhdp, x)  dhd_lb_stats_update_rxc_histo(dhdp, x)
-#define DHD_LB_STATS_TXC_PERCPU_CNT_INCR(dhdp)  dhd_lb_stats_txc_percpu_cnt_incr(dhdp)
-#define DHD_LB_STATS_RXC_PERCPU_CNT_INCR(dhdp)  dhd_lb_stats_rxc_percpu_cnt_incr(dhdp)
-#else /* !DHD_LB_STATS */
-#define DHD_LB_STATS_NOOP       do { /* noop */ } while (0)
-#define DHD_LB_STATS_INIT(dhdp)  DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_RESET(dhdp) DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_CLR(x)      DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_INCR(x)     DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_ADD(x, c)   DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_PERCPU_ARR_INCR(x)  DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_UPDATE_NAPI_HISTO(dhd, x) DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_UPDATE_TXC_HISTO(dhd, x) DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_UPDATE_RXC_HISTO(dhd, x) DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_TXC_PERCPU_CNT_INCR(dhdp) DHD_LB_STATS_NOOP
-#define DHD_LB_STATS_RXC_PERCPU_CNT_INCR(dhdp) DHD_LB_STATS_NOOP
-#endif /* !DHD_LB_STATS */
-
-#ifdef DHD_PCIE_RUNTIMEPM
-extern bool dhd_runtimepm_state(dhd_pub_t *dhd);
-extern bool dhd_runtime_bus_wake(struct dhd_bus *bus, bool wait, void *func_addr);
-extern bool dhdpcie_runtime_bus_wake(dhd_pub_t *dhdp, bool wait, void *func_addr);
-extern void dhdpcie_block_runtime_pm(dhd_pub_t *dhdp);
-extern bool dhdpcie_is_resume_done(dhd_pub_t *dhdp);
-extern void dhd_runtime_pm_disable(dhd_pub_t *dhdp);
-extern void dhd_runtime_pm_enable(dhd_pub_t *dhdp);
-/* Disable the Runtime PM and wake up if the bus is already in suspend */
-#define DHD_DISABLE_RUNTIME_PM(dhdp) \
-do { \
-	dhd_runtime_pm_disable(dhdp); \
-} while (0);
-
-/* Enable the Runtime PM */
-#define DHD_ENABLE_RUNTIME_PM(dhdp) \
-do { \
-	dhd_runtime_pm_enable(dhdp); \
-} while (0);
-#else
-#define DHD_DISABLE_RUNTIME_PM(dhdp)
-#define DHD_ENABLE_RUNTIME_PM(dhdp)
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-extern void dhd_memdump_work_schedule(dhd_pub_t *dhdp, unsigned long msecs);
-
-/*
- * Enable this macro if you want to track the calls to wake lock
- * This records can be printed using the following command
- * cat /sys/bcm-dhd/wklock_trace
- * DHD_TRACE_WAKE_LOCK supports over linux 2.6.0 version
- */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-#undef DHD_TRACE_WAKE_LOCK
-#endif /* KERNEL_VER < KERNEL_VERSION(2, 6, 0) */
-
-#if defined(DHD_TRACE_WAKE_LOCK)
-void dhd_wk_lock_stats_dump(dhd_pub_t *dhdp);
-#endif
-
-extern int dhd_prot_debug_info_print(dhd_pub_t *dhd);
-
-#ifdef ENABLE_TEMP_THROTTLING
-#define TEMP_THROTTLE_CONTROL_BIT 0xf   //Enable all feature.
-#endif /* ENABLE_TEMP_THROTTLING */
-
-#ifdef DHD_PKTID_AUDIT_ENABLED
-void dhd_pktid_audit_fail_cb(dhd_pub_t *dhdp);
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-#endif /* _dhd_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_bta.c b/drivers/net/wireless/bcmdhd/dhd_bta.c
deleted file mode 100644
index dc24edb..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_bta.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * BT-AMP support routines
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_bta.c 514727 2014-11-12 03:02:48Z $
- */
-#error "WLBTAMP is not defined"
-
-#include <typedefs.h>
-#include <osl.h>
-#include <bcmcdc.h>
-#include <bcmutils.h>
-#include <bcmendian.h>
-#include <proto/802.11.h>
-#include <proto/802.11_bta.h>
-#include <proto/bt_amp_hci.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhdioctl.h>
-#include <dhd_dbg.h>
-
-#include <dhd_bta.h>
-
-
-#ifdef SEND_HCI_CMD_VIA_IOCTL
-#define BTA_HCI_CMD_MAX_LEN HCI_CMD_PREAMBLE_SIZE + HCI_CMD_DATA_SIZE
-
-/* Send HCI cmd via wl iovar HCI_cmd to the dongle. */
-int
-dhd_bta_docmd(dhd_pub_t *pub, void *cmd_buf, uint cmd_len)
-{
-	amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)cmd_buf;
-	uint8 buf[BTA_HCI_CMD_MAX_LEN + 16];
-	uint len = sizeof(buf);
-	wl_ioctl_t ioc;
-
-	if (cmd_len < HCI_CMD_PREAMBLE_SIZE)
-		return BCME_BADLEN;
-
-	if ((uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE > cmd_len)
-		return BCME_BADLEN;
-
-	len = bcm_mkiovar("HCI_cmd",
-		(char *)cmd, (uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE, (char *)buf, len);
-
-
-	memset(&ioc, 0, sizeof(ioc));
-
-	ioc.cmd = WLC_SET_VAR;
-	ioc.buf = buf;
-	ioc.len = len;
-	ioc.set = TRUE;
-
-	return dhd_wl_ioctl(pub, &ioc, ioc.buf, ioc.len);
-}
-#else /* !SEND_HCI_CMD_VIA_IOCTL */
-
-static void
-dhd_bta_flush_hcidata(dhd_pub_t *pub, uint16 llh)
-{
-	int prec;
-	struct pktq *q;
-	uint count = 0;
-
-	q = dhd_bus_txq(pub->bus);
-	if (q == NULL)
-		return;
-
-	DHD_BTA(("dhd: flushing HCI ACL data for logical link %u...\n", llh));
-
-	dhd_os_sdlock_txq(pub);
-
-	/* Walk through the txq and toss all HCI ACL data packets */
-	PKTQ_PREC_ITER(q, prec) {
-		void *head_pkt = NULL;
-
-		while (pktq_ppeek(q, prec) != head_pkt) {
-			void *pkt = pktq_pdeq(q, prec);
-			int ifidx;
-
-			dhd_prot_hdrpull(pub, &ifidx, pkt, NULL, NULL);
-
-			if (PKTLEN(pub->osh, pkt) >= RFC1042_HDR_LEN) {
-				struct ether_header *eh =
-				        (struct ether_header *)PKTDATA(pub->osh, pkt);
-
-				if (ntoh16(eh->ether_type) < ETHER_TYPE_MIN) {
-					struct dot11_llc_snap_header *lsh =
-					        (struct dot11_llc_snap_header *)&eh[1];
-
-					if (bcmp(lsh, BT_SIG_SNAP_MPROT,
-					         DOT11_LLC_SNAP_HDR_LEN - 2) == 0 &&
-					    ntoh16(lsh->type) == BTA_PROT_L2CAP) {
-						amp_hci_ACL_data_t *ACL_data =
-						        (amp_hci_ACL_data_t *)&lsh[1];
-						uint16 handle = ltoh16(ACL_data->handle);
-
-						if (HCI_ACL_DATA_HANDLE(handle) == llh) {
-							PKTFREE(pub->osh, pkt, TRUE);
-							count ++;
-							continue;
-						}
-					}
-				}
-			}
-
-			dhd_prot_hdrpush(pub, ifidx, pkt);
-
-			if (head_pkt == NULL)
-				head_pkt = pkt;
-			pktq_penq(q, prec, pkt);
-		}
-	}
-
-	dhd_os_sdunlock_txq(pub);
-
-	DHD_BTA(("dhd: flushed %u packet(s) for logical link %u...\n", count, llh));
-}
-
-/* Handle HCI cmd locally.
- * Return 0: continue to send the cmd across SDIO
- *        < 0: stop, fail
- *        > 0: stop, succuess
- */
-static int
-_dhd_bta_docmd(dhd_pub_t *pub, amp_hci_cmd_t *cmd)
-{
-	int status = 0;
-
-	switch (ltoh16_ua((uint8 *)&cmd->opcode)) {
-	case HCI_Enhanced_Flush: {
-		eflush_cmd_parms_t *cmdparms = (eflush_cmd_parms_t *)cmd->parms;
-		dhd_bta_flush_hcidata(pub, ltoh16_ua(cmdparms->llh));
-		break;
-	}
-	default:
-		break;
-	}
-
-	return status;
-}
-
-/* Send HCI cmd encapsulated in BT-SIG frame via data channel to the dongle. */
-int
-dhd_bta_docmd(dhd_pub_t *pub, void *cmd_buf, uint cmd_len)
-{
-	amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)cmd_buf;
-	struct ether_header *eh;
-	struct dot11_llc_snap_header *lsh;
-	osl_t *osh = pub->osh;
-	uint len;
-	void *p;
-	int status;
-
-	if (cmd_len < HCI_CMD_PREAMBLE_SIZE) {
-		DHD_ERROR(("dhd_bta_docmd: short command, cmd_len %u\n", cmd_len));
-		return BCME_BADLEN;
-	}
-
-	if ((len = (uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE) > cmd_len) {
-		DHD_ERROR(("dhd_bta_docmd: malformed command, len %u cmd_len %u\n",
-		           len, cmd_len));
-		/* return BCME_BADLEN; */
-	}
-
-	p = PKTGET(osh, pub->hdrlen + RFC1042_HDR_LEN + len, TRUE);
-	if (p == NULL) {
-		DHD_ERROR(("dhd_bta_docmd: out of memory\n"));
-		return BCME_NOMEM;
-	}
-
-
-	/* intercept and handle the HCI cmd locally */
-	if ((status = _dhd_bta_docmd(pub, cmd)) > 0)
-		return 0;
-	else if (status < 0)
-		return status;
-
-	/* copy in HCI cmd */
-	PKTPULL(osh, p, pub->hdrlen + RFC1042_HDR_LEN);
-	bcopy(cmd, PKTDATA(osh, p), len);
-
-	/* copy in partial Ethernet header with BT-SIG LLC/SNAP header */
-	PKTPUSH(osh, p, RFC1042_HDR_LEN);
-	eh = (struct ether_header *)PKTDATA(osh, p);
-	bzero(eh->ether_dhost, ETHER_ADDR_LEN);
-	ETHER_SET_LOCALADDR(eh->ether_dhost);
-	bcopy(&pub->mac, eh->ether_shost, ETHER_ADDR_LEN);
-	eh->ether_type = hton16(len + DOT11_LLC_SNAP_HDR_LEN);
-	lsh = (struct dot11_llc_snap_header *)&eh[1];
-	bcopy(BT_SIG_SNAP_MPROT, lsh, DOT11_LLC_SNAP_HDR_LEN - 2);
-	lsh->type = 0;
-
-	return dhd_sendpkt(pub, 0, p);
-}
-#endif /* !SEND_HCI_CMD_VIA_IOCTL */
-
-/* Send HCI ACL data to dongle via data channel */
-int
-dhd_bta_tx_hcidata(dhd_pub_t *pub, void *data_buf, uint data_len)
-{
-	amp_hci_ACL_data_t *data = (amp_hci_ACL_data_t *)data_buf;
-	struct ether_header *eh;
-	struct dot11_llc_snap_header *lsh;
-	osl_t *osh = pub->osh;
-	uint len;
-	void *p;
-
-	if (data_len < HCI_ACL_DATA_PREAMBLE_SIZE) {
-		DHD_ERROR(("dhd_bta_tx_hcidata: short data_buf, data_len %u\n", data_len));
-		return BCME_BADLEN;
-	}
-
-	if ((len = (uint)ltoh16(data->dlen) + HCI_ACL_DATA_PREAMBLE_SIZE) > data_len) {
-		DHD_ERROR(("dhd_bta_tx_hcidata: malformed hci data, len %u data_len %u\n",
-		           len, data_len));
-		/* return BCME_BADLEN; */
-	}
-
-	p = PKTGET(osh, pub->hdrlen + RFC1042_HDR_LEN + len, TRUE);
-	if (p == NULL) {
-		DHD_ERROR(("dhd_bta_tx_hcidata: out of memory\n"));
-		return BCME_NOMEM;
-	}
-
-
-	/* copy in HCI ACL data header and HCI ACL data */
-	PKTPULL(osh, p, pub->hdrlen + RFC1042_HDR_LEN);
-	bcopy(data, PKTDATA(osh, p), len);
-
-	/* copy in partial Ethernet header with BT-SIG LLC/SNAP header */
-	PKTPUSH(osh, p, RFC1042_HDR_LEN);
-	eh = (struct ether_header *)PKTDATA(osh, p);
-	bzero(eh->ether_dhost, ETHER_ADDR_LEN);
-	bcopy(&pub->mac, eh->ether_shost, ETHER_ADDR_LEN);
-	eh->ether_type = hton16(len + DOT11_LLC_SNAP_HDR_LEN);
-	lsh = (struct dot11_llc_snap_header *)&eh[1];
-	bcopy(BT_SIG_SNAP_MPROT, lsh, DOT11_LLC_SNAP_HDR_LEN - 2);
-	lsh->type = HTON16(BTA_PROT_L2CAP);
-
-	return dhd_sendpkt(pub, 0, p);
-}
-
-/* txcomplete callback */
-void
-dhd_bta_tx_hcidata_complete(dhd_pub_t *dhdp, void *txp, bool success)
-{
-	uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, txp);
-	amp_hci_ACL_data_t *ACL_data = (amp_hci_ACL_data_t *)(pktdata + RFC1042_HDR_LEN);
-	uint16 handle = ltoh16(ACL_data->handle);
-	uint16 llh = HCI_ACL_DATA_HANDLE(handle);
-
-	wl_event_msg_t event;
-	uint8 data[HCI_EVT_PREAMBLE_SIZE + sizeof(num_completed_data_blocks_evt_parms_t)];
-	amp_hci_event_t *evt;
-	num_completed_data_blocks_evt_parms_t *parms;
-
-	uint16 len = HCI_EVT_PREAMBLE_SIZE + sizeof(num_completed_data_blocks_evt_parms_t);
-
-	/* update the event struct */
-	memset(&event, 0, sizeof(event));
-	event.version = hton16(BCM_EVENT_MSG_VERSION);
-	event.event_type = hton32(WLC_E_BTA_HCI_EVENT);
-	event.status = 0;
-	event.reason = 0;
-	event.auth_type = 0;
-	event.datalen = hton32(len);
-	event.flags = 0;
-
-	/* generate Number of Completed Blocks event */
-	evt = (amp_hci_event_t *)data;
-	evt->ecode = HCI_Number_of_Completed_Data_Blocks;
-	evt->plen = sizeof(num_completed_data_blocks_evt_parms_t);
-
-	parms = (num_completed_data_blocks_evt_parms_t *)evt->parms;
-	htol16_ua_store(dhdp->maxdatablks, (uint8 *)&parms->num_blocks);
-	parms->num_handles = 1;
-	htol16_ua_store(llh, (uint8 *)&parms->completed[0].handle);
-	parms->completed[0].pkts = 1;
-	parms->completed[0].blocks = 1;
-
-	dhd_sendup_event_common(dhdp, &event, data);
-}
-
-/* event callback */
-void
-dhd_bta_doevt(dhd_pub_t *dhdp, void *data_buf, uint data_len)
-{
-	amp_hci_event_t *evt = (amp_hci_event_t *)data_buf;
-
-	ASSERT(dhdp);
-	ASSERT(evt);
-
-	switch (evt->ecode) {
-	case HCI_Command_Complete: {
-		cmd_complete_parms_t *parms = (cmd_complete_parms_t *)evt->parms;
-		switch (ltoh16_ua((uint8 *)&parms->opcode)) {
-		case HCI_Read_Data_Block_Size: {
-			read_data_block_size_evt_parms_t *parms2 =
-			        (read_data_block_size_evt_parms_t *)parms->parms;
-			dhdp->maxdatablks = ltoh16_ua((uint8 *)&parms2->data_block_num);
-			break;
-		}
-		}
-		break;
-	}
-
-	case HCI_Flush_Occurred: {
-		flush_occurred_evt_parms_t *evt_parms = (flush_occurred_evt_parms_t *)evt->parms;
-		dhd_bta_flush_hcidata(dhdp, ltoh16_ua((uint8 *)&evt_parms->handle));
-		break;
-	}
-	default:
-		break;
-	}
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd_bta.h b/drivers/net/wireless/bcmdhd/dhd_bta.h
deleted file mode 100644
index df9d1f9..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_bta.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * BT-AMP support routines
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_bta.h 514727 2014-11-12 03:02:48Z $
- */
-#ifndef __dhd_bta_h__
-#define __dhd_bta_h__
-
-struct dhd_pub;
-
-extern int dhd_bta_docmd(struct dhd_pub *pub, void *cmd_buf, uint cmd_len);
-
-extern void dhd_bta_doevt(struct dhd_pub *pub, void *data_buf, uint data_len);
-
-extern int dhd_bta_tx_hcidata(struct dhd_pub *pub, void *data_buf, uint data_len);
-extern void dhd_bta_tx_hcidata_complete(struct dhd_pub *dhdp, void *txp, bool success);
-
-
-#endif /* __dhd_bta_h__ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_bus.h b/drivers/net/wireless/bcmdhd/dhd_bus.h
deleted file mode 100644
index 05ac034..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_bus.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Header file describing the internal (inter-module) DHD interfaces.
- *
- * Provides type definitions and function prototypes used to link the
- * DHD OS, bus, and protocol modules.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_bus.h 602721 2015-11-27 10:32:48Z $
- */
-
-#ifndef _dhd_bus_h_
-#define _dhd_bus_h_
-
-/*
- * Exported from dhd bus module (dhd_usb, dhd_sdio)
- */
-
-/* Indicate (dis)interest in finding dongles. */
-extern int dhd_bus_register(void);
-extern void dhd_bus_unregister(void);
-
-/* Download firmware image and nvram image */
-extern int dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, char *fw_path, char *nv_path);
-
-/* Stop bus module: clear pending frames, disable data flow */
-extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);
-
-/* Initialize bus module: prepare for communication w/dongle */
-extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex);
-
-/* Get the Bus Idle Time */
-extern void dhd_bus_getidletime(dhd_pub_t *dhdp, int *idletime);
-
-/* Set the Bus Idle Time */
-extern void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time);
-
-/* Send a data frame to the dongle.  Callee disposes of txp. */
-#ifdef BCMPCIE
-extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp, uint8 ifidx);
-#else
-extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp);
-#endif
-
-
-/* Send/receive a control message to/from the dongle.
- * Expects caller to enforce a single outstanding transaction.
- */
-extern int dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen);
-extern int dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen);
-
-/* Watchdog timer function */
-extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
-
-extern int dhd_bus_oob_intr_register(dhd_pub_t *dhdp);
-extern void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp);
-extern void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable);
-extern void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub);
-extern void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub);
-extern bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub);
-
-#if defined(DHD_DEBUG)
-/* Device console input function */
-extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen);
-#endif /* defined(DHD_DEBUG) */
-
-/* Deferred processing for the bus, return TRUE requests reschedule */
-extern bool dhd_bus_dpc(struct dhd_bus *bus);
-extern void dhd_bus_isr(bool * InterruptRecognized, bool * QueueMiniportHandleInterrupt, void *arg);
-
-
-/* Check for and handle local prot-specific iovar commands */
-extern int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
-                            void *params, int plen, void *arg, int len, bool set);
-
-/* Add bus dump output to a buffer */
-extern void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
-
-/* Clear any bus counters */
-extern void dhd_bus_clearcounts(dhd_pub_t *dhdp);
-
-/* return the dongle chipid */
-extern uint dhd_bus_chip(struct dhd_bus *bus);
-
-/* return the dongle chiprev */
-extern uint dhd_bus_chiprev(struct dhd_bus *bus);
-
-/* Set user-specified nvram parameters. */
-extern void dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params);
-
-extern void *dhd_bus_pub(struct dhd_bus *bus);
-extern void *dhd_bus_txq(struct dhd_bus *bus);
-extern void *dhd_bus_sih(struct dhd_bus *bus);
-extern uint dhd_bus_hdrlen(struct dhd_bus *bus);
-#ifdef BCMSDIO
-extern void dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val);
-/* return sdio io status */
-extern uint8 dhd_bus_is_ioready(struct dhd_bus *bus);
-#else
-#define dhd_bus_set_dotxinrx(a, b) do {} while (0)
-#endif
-
-#define DHD_SET_BUS_STATE_DOWN(_bus)  do { \
-	(_bus)->dhd->busstate = DHD_BUS_DOWN; \
-} while (0)
-
-/* Register a dummy SDIO client driver in order to be notified of new SDIO device */
-extern int dhd_bus_reg_sdio_notify(void* semaphore);
-extern void dhd_bus_unreg_sdio_notify(void);
-extern void dhd_txglom_enable(dhd_pub_t *dhdp, bool enable);
-extern int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num,
-	uint32 *slot_num);
-
-#ifdef BCMPCIE
-enum {
-	/* Scratch buffer confiuguration update */
-	D2H_DMA_SCRATCH_BUF,
-	D2H_DMA_SCRATCH_BUF_LEN,
-
-	/* DMA Indices array buffers for: H2D WR and RD, and D2H WR and RD */
-	H2D_DMA_INDX_WR_BUF, /* update H2D WR dma indices buf base addr to dongle */
-	H2D_DMA_INDX_RD_BUF, /* update H2D RD dma indices buf base addr to dongle */
-	D2H_DMA_INDX_WR_BUF, /* update D2H WR dma indices buf base addr to dongle */
-	D2H_DMA_INDX_RD_BUF, /* update D2H RD dma indices buf base addr to dongle */
-
-	/* DHD sets/gets WR or RD index, in host's H2D and D2H DMA indices buffer */
-	H2D_DMA_INDX_WR_UPD, /* update H2D WR index in H2D WR dma indices buf */
-	H2D_DMA_INDX_RD_UPD, /* update H2D RD index in H2D RD dma indices buf */
-	D2H_DMA_INDX_WR_UPD, /* update D2H WR index in D2H WR dma indices buf */
-	D2H_DMA_INDX_RD_UPD, /* update D2H RD index in D2H RD dma indices buf */
-
-	/* H2D and D2H Mailbox data update */
-	H2D_MB_DATA,
-	D2H_MB_DATA,
-
-	/* (Common) MsgBuf Ring configuration update */
-	RING_BUF_ADDR,       /* update ring base address to dongle */
-	RING_ITEM_LEN,       /* update ring item size to dongle */
-	RING_MAX_ITEMS,      /* update ring max items to dongle */
-
-	/* Update of WR or RD index, for a MsgBuf Ring */
-	RING_RD_UPD,         /* update ring read index from/to dongle */
-	RING_WR_UPD,         /* update ring write index from/to dongle */
-
-	TOTAL_LFRAG_PACKET_CNT,
-	MAX_HOST_RXBUFS
-};
-
-typedef void (*dhd_mb_ring_t) (struct dhd_bus *, uint32);
-extern void dhd_bus_cmn_writeshared(struct dhd_bus *bus, void * data, uint32 len, uint8 type,
-	uint16 ringid);
-extern void dhd_bus_ringbell(struct dhd_bus *bus, uint32 value);
-extern void dhd_bus_cmn_readshared(struct dhd_bus *bus, void* data, uint8 type, uint16 ringid);
-extern uint32 dhd_bus_get_sharedflags(struct dhd_bus *bus);
-extern void dhd_bus_rx_frame(struct dhd_bus *bus, void* pkt, int ifidx, uint pkt_count);
-extern void dhd_bus_start_queue(struct dhd_bus *bus);
-extern void dhd_bus_stop_queue(struct dhd_bus *bus);
-
-extern dhd_mb_ring_t dhd_bus_get_mbintr_fn(struct dhd_bus *bus);
-extern void dhd_bus_write_flow_ring_states(struct dhd_bus *bus,
-	void * data, uint16 flowid);
-extern void dhd_bus_read_flow_ring_states(struct dhd_bus *bus,
-	void * data, uint8 flowid);
-extern int dhd_bus_flow_ring_create_request(struct dhd_bus *bus, void *flow_ring_node);
-extern void dhd_bus_clean_flow_ring(struct dhd_bus *bus, void *flow_ring_node);
-extern void dhd_bus_flow_ring_create_response(struct dhd_bus *bus, uint16 flow_id, int32 status);
-extern int dhd_bus_flow_ring_delete_request(struct dhd_bus *bus, void *flow_ring_node);
-extern void dhd_bus_flow_ring_delete_response(struct dhd_bus *bus, uint16 flowid, uint32 status);
-extern int dhd_bus_flow_ring_flush_request(struct dhd_bus *bus, void *flow_ring_node);
-extern void dhd_bus_flow_ring_flush_response(struct dhd_bus *bus, uint16 flowid, uint32 status);
-extern uint32 dhd_bus_max_h2d_queues(struct dhd_bus *bus);
-extern int dhd_bus_schedule_queue(struct dhd_bus *bus, uint16 flow_id, bool txs);
-extern void dhd_bus_set_linkdown(dhd_pub_t *dhdp, bool val);
-
-
-extern int dhdpcie_bus_clock_start(struct dhd_bus *bus);
-extern int dhdpcie_bus_clock_stop(struct dhd_bus *bus);
-extern int dhdpcie_bus_enable_device(struct dhd_bus *bus);
-extern int dhdpcie_bus_disable_device(struct dhd_bus *bus);
-extern int dhdpcie_bus_alloc_resource(struct dhd_bus *bus);
-extern void dhdpcie_bus_free_resource(struct dhd_bus *bus);
-extern bool dhdpcie_bus_dongle_attach(struct dhd_bus *bus);
-extern int dhd_bus_release_dongle(struct dhd_bus *bus);
-extern int dhd_bus_request_irq(struct dhd_bus *bus);
-
-
-#ifdef DHD_FW_COREDUMP
-extern int dhd_bus_mem_dump(dhd_pub_t *dhd);
-#endif /* DHD_FW_COREDUMP */
-
-#endif /* BCMPCIE */
-#endif /* _dhd_bus_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_buzzz.h b/drivers/net/wireless/bcmdhd/dhd_buzzz.h
deleted file mode 100644
index a5422d5..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_buzzz.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _DHD_BUZZZ_H_INCLUDED_
-#define _DHD_BUZZZ_H_INCLUDED_
-
-/*
- * Broadcom logging system - Empty implementaiton
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_buzzz.h 591283 2015-10-07 11:52:00Z $
- */
-
-#define dhd_buzzz_attach()              do { /* noop */ } while (0)
-#define dhd_buzzz_detach()              do { /* noop */ } while (0)
-#define dhd_buzzz_panic(x)              do { /* noop */ } while (0)
-#define BUZZZ_LOG(ID, N, ARG...)    do { /* noop */ } while (0)
-
-#endif /* _DHD_BUZZZ_H_INCLUDED_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c
deleted file mode 100644
index 66a3110..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_cdc.c
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * DHD Protocol Module for CDC and BDC.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_cdc.c 596022 2015-10-29 11:02:47Z $
- *
- * BDC is like CDC, except it includes a header for data packets to convey
- * packet priority over the bus, and flags (e.g. to indicate checksum status
- * for dongle offload.)
- */
-
-#include <typedefs.h>
-#include <osl.h>
-
-#include <bcmutils.h>
-#include <bcmcdc.h>
-#include <bcmendian.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_proto.h>
-#include <dhd_bus.h>
-#include <dhd_dbg.h>
-
-
-#ifdef PROP_TXSTATUS
-#include <wlfc_proto.h>
-#include <dhd_wlfc.h>
-#endif
-
-
-#define RETRIES 2		/* # of retries to retrieve matching ioctl response */
-#define BUS_HEADER_LEN	(24+DHD_SDALIGN)	/* Must be at least SDPCM_RESERVE
-				 * defined in dhd_sdio.c (amount of header tha might be added)
-				 * plus any space that might be needed for alignment padding.
-				 */
-#define ROUND_UP_MARGIN	2048	/* Biggest SDIO block size possible for
-				 * round off at the end of buffer
-				 */
-
-typedef struct dhd_prot {
-	uint16 reqid;
-	uint8 pending;
-	uint32 lastcmd;
-	uint8 bus_header[BUS_HEADER_LEN];
-	cdc_ioctl_t msg;
-	unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN];
-} dhd_prot_t;
-
-
-static int
-dhdcdc_msg(dhd_pub_t *dhd)
-{
-	int err = 0;
-	dhd_prot_t *prot = dhd->prot;
-	int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t);
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	DHD_OS_WAKE_LOCK(dhd);
-
-	/* NOTE : cdc->msg.len holds the desired length of the buffer to be
-	 *        returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
-	 *	  is actually sent to the dongle
-	 */
-	if (len > CDC_MAX_MSG_SIZE)
-		len = CDC_MAX_MSG_SIZE;
-
-	/* Send request */
-	err = dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len);
-
-	DHD_OS_WAKE_UNLOCK(dhd);
-	return err;
-}
-
-static int
-dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len)
-{
-	int ret;
-	int cdc_len = len + sizeof(cdc_ioctl_t);
-	dhd_prot_t *prot = dhd->prot;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	do {
-		ret = dhd_bus_rxctl(dhd->bus, (uchar*)&prot->msg, cdc_len);
-		if (ret < 0)
-			break;
-	} while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id);
-
-	return ret;
-}
-
-static int
-dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
-{
-	dhd_prot_t *prot = dhd->prot;
-	cdc_ioctl_t *msg = &prot->msg;
-	int ret = 0, retries = 0;
-	uint32 id, flags = 0;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-	DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len));
-
-
-	/* Respond "bcmerror" and "bcmerrorstr" with local cache */
-	if (cmd == WLC_GET_VAR && buf)
-	{
-		if (!strcmp((char *)buf, "bcmerrorstr"))
-		{
-			strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN);
-			goto done;
-		}
-		else if (!strcmp((char *)buf, "bcmerror"))
-		{
-			*(int *)buf = dhd->dongle_error;
-			goto done;
-		}
-	}
-
-	memset(msg, 0, sizeof(cdc_ioctl_t));
-
-	msg->cmd = htol32(cmd);
-	msg->len = htol32(len);
-	msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
-	CDC_SET_IF_IDX(msg, ifidx);
-	/* add additional action bits */
-	action &= WL_IOCTL_ACTION_MASK;
-	msg->flags |= (action << CDCF_IOC_ACTION_SHIFT);
-	msg->flags = htol32(msg->flags);
-
-	if (buf)
-		memcpy(prot->buf, buf, len);
-
-	if ((ret = dhdcdc_msg(dhd)) < 0) {
-		if (!dhd->hang_was_sent)
-		DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret));
-		goto done;
-	}
-
-retry:
-	/* wait for interrupt and get first fragment */
-	if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0)
-		goto done;
-
-	flags = ltoh32(msg->flags);
-	id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
-
-	if ((id < prot->reqid) && (++retries < RETRIES))
-		goto retry;
-	if (id != prot->reqid) {
-		DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
-		           dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid));
-		ret = -EINVAL;
-		goto done;
-	}
-
-	/* Copy info buffer */
-	if (buf)
-	{
-		if (ret < (int)len)
-			len = ret;
-		memcpy(buf, (void*) prot->buf, len);
-	}
-
-	/* Check the ERROR flag */
-	if (flags & CDCF_IOC_ERROR)
-	{
-		ret = ltoh32(msg->status);
-		/* Cache error from dongle */
-		dhd->dongle_error = ret;
-	}
-
-done:
-	return ret;
-}
-
-
-static int
-dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
-{
-	dhd_prot_t *prot = dhd->prot;
-	cdc_ioctl_t *msg = &prot->msg;
-	int ret = 0;
-	uint32 flags, id;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-	DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len));
-
-	if (dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
-		return -EIO;
-	}
-
-	/* don't talk to the dongle if fw is about to be reloaded */
-	if (dhd->hang_was_sent) {
-		DHD_ERROR(("%s: HANG was sent up earlier. Not talking to the chip\n",
-			__FUNCTION__));
-		return -EIO;
-	}
-
-	if (cmd == WLC_SET_PM) {
-		DHD_TRACE_HW4(("%s: SET PM to %d\n", __FUNCTION__, *(char *)buf));
-	}
-
-	memset(msg, 0, sizeof(cdc_ioctl_t));
-
-	msg->cmd = htol32(cmd);
-	msg->len = htol32(len);
-	msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
-	CDC_SET_IF_IDX(msg, ifidx);
-	/* add additional action bits */
-	action &= WL_IOCTL_ACTION_MASK;
-	msg->flags |= (action << CDCF_IOC_ACTION_SHIFT) | CDCF_IOC_SET;
-	msg->flags = htol32(msg->flags);
-
-	if (buf)
-		memcpy(prot->buf, buf, len);
-
-	if ((ret = dhdcdc_msg(dhd)) < 0) {
-		DHD_ERROR(("%s: dhdcdc_msg failed w/status %d\n", __FUNCTION__, ret));
-		goto done;
-	}
-
-	if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0)
-		goto done;
-
-	flags = ltoh32(msg->flags);
-	id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
-
-	if (id != prot->reqid) {
-		DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
-		           dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid));
-		ret = -EINVAL;
-		goto done;
-	}
-
-	/* Check the ERROR flag */
-	if (flags & CDCF_IOC_ERROR)
-	{
-		ret = ltoh32(msg->status);
-		/* Cache error from dongle */
-		dhd->dongle_error = ret;
-	}
-
-done:
-	return ret;
-}
-
-
-int
-dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
-{
-	dhd_prot_t *prot = dhd->prot;
-	int ret = -1;
-	uint8 action;
-
-	if ((dhd->busstate == DHD_BUS_DOWN) || dhd->hang_was_sent) {
-		DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
-		goto done;
-	}
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	ASSERT(len <= WLC_IOCTL_MAXLEN);
-
-	if (len > WLC_IOCTL_MAXLEN)
-		goto done;
-
-	if (prot->pending == TRUE) {
-		DHD_ERROR(("CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n",
-			ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
-			(unsigned long)prot->lastcmd));
-		if ((ioc->cmd == WLC_SET_VAR) || (ioc->cmd == WLC_GET_VAR)) {
-			DHD_TRACE(("iovar cmd=%s\n", (char*)buf));
-		}
-		goto done;
-	}
-
-	prot->pending = TRUE;
-	prot->lastcmd = ioc->cmd;
-	action = ioc->set;
-	if (action & WL_IOCTL_ACTION_SET)
-		ret = dhdcdc_set_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
-	else {
-		ret = dhdcdc_query_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
-		if (ret > 0)
-			ioc->used = ret - sizeof(cdc_ioctl_t);
-	}
-
-	/* Too many programs assume ioctl() returns 0 on success */
-	if (ret >= 0)
-		ret = 0;
-	else {
-		cdc_ioctl_t *msg = &prot->msg;
-		ioc->needed = ltoh32(msg->len); /* len == needed when set/query fails from dongle */
-	}
-
-	/* Intercept the wme_dp ioctl here */
-	if ((!ret) && (ioc->cmd == WLC_SET_VAR) && (!strcmp(buf, "wme_dp"))) {
-		int slen, val = 0;
-
-		slen = strlen("wme_dp") + 1;
-		if (len >= (int)(slen + sizeof(int)))
-			bcopy(((char *)buf + slen), &val, sizeof(int));
-		dhd->wme_dp = (uint8) ltoh32(val);
-	}
-
-	prot->pending = FALSE;
-
-done:
-
-	return ret;
-}
-
-int
-dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
-                  void *params, int plen, void *arg, int len, bool set)
-{
-	return BCME_UNSUPPORTED;
-}
-
-void
-dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
-{
-	if (!dhdp || !dhdp->prot)
-		return;
-	bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid);
-#ifdef PROP_TXSTATUS
-	dhd_wlfc_dump(dhdp, strbuf);
-#endif
-}
-
-/*	The FreeBSD PKTPUSH could change the packet buf pinter
-	so we need to make it changable
-*/
-#define PKTBUF pktbuf
-void
-dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *PKTBUF)
-{
-#ifdef BDC
-	struct bdc_header *h;
-#endif /* BDC */
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-#ifdef BDC
-	/* Push BDC header used to convey priority for buses that don't */
-
-	PKTPUSH(dhd->osh, PKTBUF, BDC_HEADER_LEN);
-
-	h = (struct bdc_header *)PKTDATA(dhd->osh, PKTBUF);
-
-	h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
-	if (PKTSUMNEEDED(PKTBUF))
-		h->flags |= BDC_FLAG_SUM_NEEDED;
-
-
-	h->priority = (PKTPRIO(PKTBUF) & BDC_PRIORITY_MASK);
-	h->flags2 = 0;
-	h->dataOffset = 0;
-#endif /* BDC */
-	BDC_SET_IF_IDX(h, ifidx);
-}
-#undef PKTBUF	/* Only defined in the above routine */
-
-uint
-dhd_prot_hdrlen(dhd_pub_t *dhd, void *PKTBUF)
-{
-	uint hdrlen = 0;
-#ifdef BDC
-	/* Length of BDC(+WLFC) headers pushed */
-	hdrlen = BDC_HEADER_LEN + (((struct bdc_header *)PKTBUF)->dataOffset * 4);
-#endif
-	return hdrlen;
-}
-
-int
-dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_info,
-	uint *reorder_info_len)
-{
-#ifdef BDC
-	struct bdc_header *h;
-#endif
-	uint8 data_offset = 0;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-#ifdef BDC
-	if (reorder_info_len)
-		*reorder_info_len = 0;
-	/* Pop BDC header used to convey priority for buses that don't */
-
-	if (PKTLEN(dhd->osh, pktbuf) < BDC_HEADER_LEN) {
-		DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__,
-		           PKTLEN(dhd->osh, pktbuf), BDC_HEADER_LEN));
-		return BCME_ERROR;
-	}
-
-	h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf);
-
-	if (!ifidx) {
-		/* for tx packet, skip the analysis */
-		data_offset = h->dataOffset;
-		PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN);
-		goto exit;
-	}
-
-	*ifidx = BDC_GET_IF_IDX(h);
-
-	if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != BDC_PROTO_VER) {
-		DHD_ERROR(("%s: non-BDC packet received, flags = 0x%x\n",
-		           dhd_ifname(dhd, *ifidx), h->flags));
-		if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) == BDC_PROTO_VER_1)
-			h->dataOffset = 0;
-		else
-		return BCME_ERROR;
-	}
-
-	if (h->flags & BDC_FLAG_SUM_GOOD) {
-		DHD_INFO(("%s: BDC packet received with good rx-csum, flags 0x%x\n",
-		          dhd_ifname(dhd, *ifidx), h->flags));
-		PKTSETSUMGOOD(pktbuf, TRUE);
-	}
-
-	PKTSETPRIO(pktbuf, (h->priority & BDC_PRIORITY_MASK));
-	data_offset = h->dataOffset;
-	PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN);
-#endif /* BDC */
-
-
-#ifdef PROP_TXSTATUS
-	if (!DHD_PKTTAG_PKTDIR(PKTTAG(pktbuf))) {
-		/*
-		- parse txstatus only for packets that came from the firmware
-		*/
-		dhd_wlfc_parse_header_info(dhd, pktbuf, (data_offset << 2),
-			reorder_buf_info, reorder_info_len);
-
-	}
-#endif /* PROP_TXSTATUS */
-
-exit:
-	PKTPULL(dhd->osh, pktbuf, (data_offset << 2));
-	return 0;
-}
-
-
-int
-dhd_prot_attach(dhd_pub_t *dhd)
-{
-	dhd_prot_t *cdc;
-
-	if (!(cdc = (dhd_prot_t *)DHD_OS_PREALLOC(dhd, DHD_PREALLOC_PROT, sizeof(dhd_prot_t)))) {
-		DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
-		goto fail;
-	}
-	memset(cdc, 0, sizeof(dhd_prot_t));
-
-	/* ensure that the msg buf directly follows the cdc msg struct */
-	if ((uintptr)(&cdc->msg + 1) != (uintptr)cdc->buf) {
-		DHD_ERROR(("dhd_prot_t is not correctly defined\n"));
-		goto fail;
-	}
-
-	dhd->prot = cdc;
-#ifdef BDC
-	dhd->hdrlen += BDC_HEADER_LEN;
-#endif
-	dhd->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN;
-	return 0;
-
-fail:
-	if (cdc != NULL)
-		DHD_OS_PREFREE(dhd, cdc, sizeof(dhd_prot_t));
-	return BCME_NOMEM;
-}
-
-/* ~NOTE~ What if another thread is waiting on the semaphore?  Holding it? */
-void
-dhd_prot_detach(dhd_pub_t *dhd)
-{
-#ifdef PROP_TXSTATUS
-	dhd_wlfc_deinit(dhd);
-#endif
-	DHD_OS_PREFREE(dhd, dhd->prot, sizeof(dhd_prot_t));
-	dhd->prot = NULL;
-}
-
-void
-dhd_prot_dstats(dhd_pub_t *dhd)
-{
-	/*  copy bus stats */
-
-	dhd->dstats.tx_packets = dhd->tx_packets;
-	dhd->dstats.tx_errors = dhd->tx_errors;
-	dhd->dstats.rx_packets = dhd->rx_packets;
-	dhd->dstats.rx_errors = dhd->rx_errors;
-	dhd->dstats.rx_dropped = dhd->rx_dropped;
-	dhd->dstats.multicast = dhd->rx_multicast;
-	return;
-}
-
-int
-dhd_sync_with_dongle(dhd_pub_t *dhd)
-{
-	int ret = 0;
-	wlc_rev_info_t revinfo;
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-#ifdef BCMASSERT_LOG
-	dhd_get_assert_info(dhd);
-#endif /* BCMASSERT_LOG */
-
-	/* Get the device rev info */
-	memset(&revinfo, 0, sizeof(revinfo));
-	ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0);
-	if (ret < 0)
-		goto done;
-
-
-	dhd_process_cid_mac(dhd, TRUE);
-
-	ret = dhd_preinit_ioctls(dhd);
-
-	if (!ret)
-		dhd_process_cid_mac(dhd, FALSE);
-
-	/* Always assumes wl for now */
-	dhd->iswl = TRUE;
-
-done:
-	return ret;
-}
-
-int dhd_prot_init(dhd_pub_t *dhd)
-{
-	return BCME_OK;
-}
-
-void
-dhd_prot_stop(dhd_pub_t *dhd)
-{
-/* Nothing to do for CDC */
-}
-
-
-static void
-dhd_get_hostreorder_pkts(void *osh, struct reorder_info *ptr, void **pkt,
-	uint32 *pkt_count, void **pplast, uint8 start, uint8 end)
-{
-	void *plast = NULL, *p;
-	uint32 pkt_cnt = 0;
-
-	if (ptr->pend_pkts == 0) {
-		DHD_REORDER(("%s: no packets in reorder queue \n", __FUNCTION__));
-		*pplast = NULL;
-		*pkt_count = 0;
-		*pkt = NULL;
-		return;
-	}
-	do {
-		p = (void *)(ptr->p[start]);
-		ptr->p[start] = NULL;
-
-		if (p != NULL) {
-			if (plast == NULL)
-				*pkt = p;
-			else
-				PKTSETNEXT(osh, plast, p);
-
-			plast = p;
-			pkt_cnt++;
-		}
-		start++;
-		if (start > ptr->max_idx)
-			start = 0;
-	} while (start != end);
-	*pplast = plast;
-	*pkt_count = pkt_cnt;
-	ptr->pend_pkts -= (uint8)pkt_cnt;
-}
-
-int
-dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len,
-	void **pkt, uint32 *pkt_count)
-{
-	uint8 flow_id, max_idx, cur_idx, exp_idx;
-	struct reorder_info *ptr;
-	uint8 flags;
-	void *cur_pkt, *plast = NULL;
-	uint32 cnt = 0;
-
-	if (pkt == NULL) {
-		if (pkt_count != NULL)
-			*pkt_count = 0;
-		return 0;
-	}
-
-	flow_id = reorder_info_buf[WLHOST_REORDERDATA_FLOWID_OFFSET];
-	flags = reorder_info_buf[WLHOST_REORDERDATA_FLAGS_OFFSET];
-
-	DHD_REORDER(("flow_id %d, flags 0x%02x, idx(%d, %d, %d)\n", flow_id, flags,
-		reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET],
-		reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET],
-		reorder_info_buf[WLHOST_REORDERDATA_MAXIDX_OFFSET]));
-
-	/* validate flags and flow id */
-	if (flags == 0xFF) {
-		DHD_ERROR(("%s: invalid flags...so ignore this packet\n", __FUNCTION__));
-		*pkt_count = 1;
-		return 0;
-	}
-
-	cur_pkt = *pkt;
-	*pkt = NULL;
-
-	ptr = dhd->reorder_bufs[flow_id];
-	if (flags & WLHOST_REORDERDATA_DEL_FLOW) {
-		uint32 buf_size = sizeof(struct reorder_info);
-
-		DHD_REORDER(("%s: Flags indicating to delete a flow id %d\n",
-			__FUNCTION__, flow_id));
-
-		if (ptr == NULL) {
-			DHD_REORDER(("%s: received flags to cleanup, but no flow (%d) yet\n",
-				__FUNCTION__, flow_id));
-			*pkt_count = 1;
-			*pkt = cur_pkt;
-			return 0;
-		}
-
-		dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
-			ptr->exp_idx, ptr->exp_idx);
-		/* set it to the last packet */
-		if (plast) {
-			PKTSETNEXT(dhd->osh, plast, cur_pkt);
-			cnt++;
-		}
-		else {
-			if (cnt != 0) {
-				DHD_ERROR(("%s: del flow: something fishy, pending packets %d\n",
-					__FUNCTION__, cnt));
-			}
-			*pkt = cur_pkt;
-			cnt = 1;
-		}
-		buf_size += ((ptr->max_idx + 1) * sizeof(void *));
-		MFREE(dhd->osh, ptr, buf_size);
-		dhd->reorder_bufs[flow_id] = NULL;
-		*pkt_count = cnt;
-		return 0;
-	}
-	/* all the other cases depend on the existance of the reorder struct for that flow id */
-	if (ptr == NULL) {
-		uint32 buf_size_alloc = sizeof(reorder_info_t);
-		max_idx = reorder_info_buf[WLHOST_REORDERDATA_MAXIDX_OFFSET];
-
-		buf_size_alloc += ((max_idx + 1) * sizeof(void*));
-		/* allocate space to hold the buffers, index etc */
-
-		DHD_REORDER(("%s: alloc buffer of size %d size, reorder info id %d, maxidx %d\n",
-			__FUNCTION__, buf_size_alloc, flow_id, max_idx));
-		ptr = (struct reorder_info *)MALLOC(dhd->osh, buf_size_alloc);
-		if (ptr == NULL) {
-			DHD_ERROR(("%s: Malloc failed to alloc buffer\n", __FUNCTION__));
-			*pkt_count = 1;
-			return 0;
-		}
-		bzero(ptr, buf_size_alloc);
-		dhd->reorder_bufs[flow_id] = ptr;
-		ptr->p = (void *)(ptr+1);
-		ptr->max_idx = max_idx;
-	}
-	if (flags & WLHOST_REORDERDATA_NEW_HOLE)  {
-		DHD_REORDER(("%s: new hole, so cleanup pending buffers\n", __FUNCTION__));
-		if (ptr->pend_pkts) {
-			dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
-				ptr->exp_idx, ptr->exp_idx);
-			ptr->pend_pkts = 0;
-		}
-		ptr->cur_idx = reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET];
-		ptr->exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET];
-		ptr->max_idx = reorder_info_buf[WLHOST_REORDERDATA_MAXIDX_OFFSET];
-		ptr->p[ptr->cur_idx] = cur_pkt;
-		ptr->pend_pkts++;
-		*pkt_count = cnt;
-	}
-	else if (flags & WLHOST_REORDERDATA_CURIDX_VALID) {
-		cur_idx = reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET];
-		exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET];
-
-
-		if ((exp_idx == ptr->exp_idx) && (cur_idx != ptr->exp_idx)) {
-			/* still in the current hole */
-			/* enqueue the current on the buffer chain */
-			if (ptr->p[cur_idx] != NULL) {
-				DHD_REORDER(("%s: HOLE: ERROR buffer pending..free it\n",
-					__FUNCTION__));
-				PKTFREE(dhd->osh, ptr->p[cur_idx], TRUE);
-				ptr->p[cur_idx] = NULL;
-			}
-			ptr->p[cur_idx] = cur_pkt;
-			ptr->pend_pkts++;
-			ptr->cur_idx = cur_idx;
-			DHD_REORDER(("%s: fill up a hole..pending packets is %d\n",
-				__FUNCTION__, ptr->pend_pkts));
-			*pkt_count = 0;
-			*pkt = NULL;
-		}
-		else if (ptr->exp_idx == cur_idx) {
-			/* got the right one ..flush from cur to exp and update exp */
-			DHD_REORDER(("%s: got the right one now, cur_idx is %d\n",
-				__FUNCTION__, cur_idx));
-			if (ptr->p[cur_idx] != NULL) {
-				DHD_REORDER(("%s: Error buffer pending..free it\n",
-					__FUNCTION__));
-				PKTFREE(dhd->osh, ptr->p[cur_idx], TRUE);
-				ptr->p[cur_idx] = NULL;
-			}
-			ptr->p[cur_idx] = cur_pkt;
-			ptr->pend_pkts++;
-
-			ptr->cur_idx = cur_idx;
-			ptr->exp_idx = exp_idx;
-
-			dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
-				cur_idx, exp_idx);
-			*pkt_count = cnt;
-			DHD_REORDER(("%s: freeing up buffers %d, still pending %d\n",
-				__FUNCTION__, cnt, ptr->pend_pkts));
-		}
-		else {
-			uint8 end_idx;
-			bool flush_current = FALSE;
-			/* both cur and exp are moved now .. */
-			DHD_REORDER(("%s:, flow %d, both moved, cur %d(%d), exp %d(%d)\n",
-				__FUNCTION__, flow_id, ptr->cur_idx, cur_idx,
-				ptr->exp_idx, exp_idx));
-			if (flags & WLHOST_REORDERDATA_FLUSH_ALL)
-				end_idx = ptr->exp_idx;
-			else
-				end_idx = exp_idx;
-
-			/* flush pkts first */
-			dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
-				ptr->exp_idx, end_idx);
-
-			if (cur_idx == ptr->max_idx) {
-				if (exp_idx == 0)
-					flush_current = TRUE;
-			} else {
-				if (exp_idx == cur_idx + 1)
-					flush_current = TRUE;
-			}
-			if (flush_current) {
-				if (plast)
-					PKTSETNEXT(dhd->osh, plast, cur_pkt);
-				else
-					*pkt = cur_pkt;
-				cnt++;
-			}
-			else {
-				ptr->p[cur_idx] = cur_pkt;
-				ptr->pend_pkts++;
-			}
-			ptr->exp_idx = exp_idx;
-			ptr->cur_idx = cur_idx;
-			*pkt_count = cnt;
-		}
-	}
-	else {
-		uint8 end_idx;
-		/* no real packet but update to exp_seq...that means explicit window move */
-		exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET];
-
-		DHD_REORDER(("%s: move the window, cur_idx is %d, exp is %d, new exp is %d\n",
-			__FUNCTION__, ptr->cur_idx, ptr->exp_idx, exp_idx));
-		if (flags & WLHOST_REORDERDATA_FLUSH_ALL)
-			end_idx =  ptr->exp_idx;
-		else
-			end_idx =  exp_idx;
-
-		dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast, ptr->exp_idx, end_idx);
-		if (plast)
-			PKTSETNEXT(dhd->osh, plast, cur_pkt);
-		else
-			*pkt = cur_pkt;
-		cnt++;
-		*pkt_count = cnt;
-		/* set the new expected idx */
-		ptr->exp_idx = exp_idx;
-	}
-	return 0;
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
deleted file mode 100644
index 390747f..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Linux cfg80211 driver - Dongle Host Driver (DHD) related
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_cfg80211.c 591285 2015-10-07 11:56:29Z $
- */
-
-#include <linux/vmalloc.h>
-#include <net/rtnetlink.h>
-
-#include <bcmutils.h>
-#include <wldev_common.h>
-#include <wl_cfg80211.h>
-#include <dhd_cfg80211.h>
-
-#ifdef PKT_FILTER_SUPPORT
-#include <dngl_stats.h>
-#include <dhd.h>
-#endif
-
-extern struct bcm_cfg80211 *g_bcm_cfg;
-
-#ifdef PKT_FILTER_SUPPORT
-extern uint dhd_pkt_filter_enable;
-extern uint dhd_master_mode;
-extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
-#endif
-
-static int dhd_dongle_up = FALSE;
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhdioctl.h>
-#include <wlioctl.h>
-#include <brcm_nl80211.h>
-#include <dhd_cfg80211.h>
-
-static s32 wl_dongle_up(struct net_device *ndev);
-static s32 wl_dongle_down(struct net_device *ndev);
-
-/**
- * Function implementations
- */
-
-s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg)
-{
-	dhd_dongle_up = FALSE;
-	return 0;
-}
-
-s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg)
-{
-	dhd_dongle_up = FALSE;
-	return 0;
-}
-
-s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg)
-{
-	struct net_device *ndev;
-	s32 err = 0;
-
-	WL_TRACE(("In\n"));
-	if (!dhd_dongle_up) {
-		WL_ERR(("Dongle is already down\n"));
-		return err;
-	}
-
-	ndev = bcmcfg_to_prmry_ndev(cfg);
-	wl_dongle_down(ndev);
-	dhd_dongle_up = FALSE;
-	return 0;
-}
-
-s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val)
-{
-	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
-	dhd->op_mode |= val;
-	WL_ERR(("Set : op_mode=0x%04x\n", dhd->op_mode));
-#ifdef ARP_OFFLOAD_SUPPORT
-	if (dhd->arp_version == 1) {
-		/* IF P2P is enabled, disable arpoe */
-		dhd_arp_offload_set(dhd, 0);
-		dhd_arp_offload_enable(dhd, false);
-	}
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-	return 0;
-}
-
-s32 dhd_cfg80211_clean_p2p_info(struct bcm_cfg80211 *cfg)
-{
-	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
-	dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE);
-	WL_ERR(("Clean : op_mode=0x%04x\n", dhd->op_mode));
-
-#ifdef ARP_OFFLOAD_SUPPORT
-	if (dhd->arp_version == 1) {
-		/* IF P2P is disabled, enable arpoe back for STA mode. */
-		dhd_arp_offload_set(dhd, dhd_arp_mode);
-		dhd_arp_offload_enable(dhd, true);
-	}
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-	return 0;
-}
-
-struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, char *name,
-	uint8 *mac, uint8 bssidx, char *dngl_name)
-{
-	return dhd_allocate_if(cfg->pub, ifidx, name, mac, bssidx, FALSE, dngl_name);
-}
-
-int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
-{
-	return dhd_register_if(cfg->pub, ifidx, FALSE);
-}
-
-int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
-{
-	return dhd_remove_if(cfg->pub, ifidx, FALSE);
-}
-
-struct net_device * dhd_cfg80211_netdev_free(struct net_device *ndev)
-{
-	if (ndev) {
-		if (ndev->ieee80211_ptr) {
-			kfree(ndev->ieee80211_ptr);
-			ndev->ieee80211_ptr = NULL;
-		}
-		free_netdev(ndev);
-		return NULL;
-	}
-
-	return ndev;
-}
-
-void dhd_netdev_free(struct net_device *ndev)
-{
-#ifdef WL_CFG80211
-	ndev = dhd_cfg80211_netdev_free(ndev);
-#endif
-	if (ndev)
-		free_netdev(ndev);
-}
-
-static s32
-wl_dongle_up(struct net_device *ndev)
-{
-	s32 err = 0;
-	u32 up = 0;
-
-	err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true);
-	if (unlikely(err)) {
-		WL_ERR(("WLC_UP error (%d)\n", err));
-	}
-	return err;
-}
-
-static s32
-wl_dongle_down(struct net_device *ndev)
-{
-	s32 err = 0;
-	u32 down = 0;
-
-	err = wldev_ioctl(ndev, WLC_DOWN, &down, sizeof(down), true);
-	if (unlikely(err)) {
-		WL_ERR(("WLC_DOWN error (%d)\n", err));
-	}
-	return err;
-}
-
-
-s32 dhd_config_dongle(struct bcm_cfg80211 *cfg)
-{
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN	32
-#endif
-	struct net_device *ndev;
-	s32 err = 0;
-
-	WL_TRACE(("In\n"));
-	if (dhd_dongle_up) {
-		WL_ERR(("Dongle is already up\n"));
-		return err;
-	}
-
-	ndev = bcmcfg_to_prmry_ndev(cfg);
-
-	err = wl_dongle_up(ndev);
-	if (unlikely(err)) {
-		WL_ERR(("wl_dongle_up failed\n"));
-		goto default_conf_out;
-	}
-	dhd_dongle_up = true;
-
-default_conf_out:
-
-	return err;
-
-}
-
-int dhd_cfgvendor_priv_string_handler(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev,
-	const struct bcm_nlmsg_hdr *nlioc, void *buf)
-{
-	struct net_device *ndev = NULL;
-	dhd_pub_t *dhd;
-	dhd_ioctl_t ioc = { 0 };
-	int ret = 0;
-	int8 index;
-
-	WL_TRACE(("entry: cmd = %d\n", nlioc->cmd));
-
-	dhd = cfg->pub;
-	DHD_OS_WAKE_LOCK(dhd);
-
-	/* send to dongle only if we are not waiting for reload already */
-	if (dhd->hang_was_sent) {
-		WL_ERR(("HANG was sent up earlier\n"));
-		DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
-		DHD_OS_WAKE_UNLOCK(dhd);
-		return OSL_ERROR(BCME_DONGLE_DOWN);
-	}
-
-	ndev = wdev_to_wlc_ndev(wdev, cfg);
-	index = dhd_net2idx(dhd->info, ndev);
-	if (index == DHD_BAD_IF) {
-		WL_ERR(("Bad ifidx from wdev:%p\n", wdev));
-		ret = BCME_ERROR;
-		goto done;
-	}
-
-	ioc.cmd = nlioc->cmd;
-	ioc.len = nlioc->len;
-	ioc.set = nlioc->set;
-	ioc.driver = nlioc->magic;
-	ret = dhd_ioctl_process(dhd, index, &ioc, buf);
-	if (ret) {
-		WL_TRACE(("dhd_ioctl_process return err %d\n", ret));
-		ret = OSL_ERROR(ret);
-		goto done;
-	}
-
-done:
-	DHD_OS_WAKE_UNLOCK(dhd);
-	return ret;
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h
deleted file mode 100644
index cae7cc9..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Linux cfg80211 driver - Dongle Host Driver (DHD) related
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_cfg80211.h 591285 2015-10-07 11:56:29Z $
- */
-
-
-#ifndef __DHD_CFG80211__
-#define __DHD_CFG80211__
-
-#include <wl_cfg80211.h>
-#include <wl_cfgp2p.h>
-#include <brcm_nl80211.h>
-
-#ifndef WL_ERR
-#define WL_ERR CFG80211_ERR
-#endif
-#ifndef WL_TRACE
-#define WL_TRACE CFG80211_TRACE
-#endif
-
-s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg);
-s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg);
-s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg);
-s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val);
-s32 dhd_cfg80211_clean_p2p_info(struct bcm_cfg80211 *cfg);
-s32 dhd_config_dongle(struct bcm_cfg80211 *cfg);
-int dhd_cfgvendor_priv_string_handler(struct bcm_cfg80211 *cfg,
-	struct wireless_dev *wdev, const struct bcm_nlmsg_hdr *nlioc, void  *data);
-
-#endif /* __DHD_CFG80211__ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg_vendor.c b/drivers/net/wireless/bcmdhd/dhd_cfg_vendor.c
deleted file mode 100644
index c72f829..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_cfg_vendor.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Linux cfg80211 vendor command/event handlers of DHD
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_cfg_vendor.c 525516 2015-01-09 23:12:53Z $
- */
-
-#include <linux/vmalloc.h>
-#include <linuxver.h>
-#include <net/cfg80211.h>
-#include <net/netlink.h>
-
-#include <bcmutils.h>
-#include <wl_cfg80211.h>
-#include <wl_cfgvendor.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_dbg.h>
-#include <dhdioctl.h>
-#include <brcm_nl80211.h>
-
-#ifdef VENDOR_EXT_SUPPORT
-static int dhd_cfgvendor_priv_string_handler(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	const struct bcm_nlmsg_hdr *nlioc = data;
-	struct net_device *ndev = NULL;
-	struct bcm_cfg80211 *cfg;
-	struct sk_buff *reply;
-	void *buf = NULL, *cur;
-	dhd_pub_t *dhd;
-	dhd_ioctl_t ioc = { 0 };
-	int ret = 0, ret_len, payload, msglen;
-	int maxmsglen = PAGE_SIZE - 0x100;
-	int8 index;
-
-	WL_TRACE(("entry: cmd = %d\n", nlioc->cmd));
-	DHD_ERROR(("entry: cmd = %d\n", nlioc->cmd));
-
-	cfg = wiphy_priv(wiphy);
-	dhd = cfg->pub;
-
-	DHD_OS_WAKE_LOCK(dhd);
-
-	/* send to dongle only if we are not waiting for reload already */
-	if (dhd->hang_was_sent) {
-		WL_ERR(("HANG was sent up earlier\n"));
-		DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
-		DHD_OS_WAKE_UNLOCK(dhd);
-		return OSL_ERROR(BCME_DONGLE_DOWN);
-	}
-
-	len -= sizeof(struct bcm_nlmsg_hdr);
-	ret_len = nlioc->len;
-	if (ret_len > 0 || len > 0) {
-		if (len > DHD_IOCTL_MAXLEN) {
-			WL_ERR(("oversize input buffer %d\n", len));
-			len = DHD_IOCTL_MAXLEN;
-		}
-		if (ret_len > DHD_IOCTL_MAXLEN) {
-			WL_ERR(("oversize return buffer %d\n", ret_len));
-			ret_len = DHD_IOCTL_MAXLEN;
-		}
-		payload = max(ret_len, len) + 1;
-		buf = vzalloc(payload);
-		if (!buf) {
-			DHD_OS_WAKE_UNLOCK(dhd);
-			return -ENOMEM;
-		}
-		memcpy(buf, (void *)nlioc + nlioc->offset, len);
-		*(char *)(buf + len) = '\0';
-	}
-
-	ndev = wdev_to_wlc_ndev(wdev, cfg);
-	index = dhd_net2idx(dhd->info, ndev);
-	if (index == DHD_BAD_IF) {
-		WL_ERR(("Bad ifidx from wdev:%p\n", wdev));
-		ret = BCME_ERROR;
-		goto done;
-	}
-
-	ioc.cmd = nlioc->cmd;
-	ioc.len = nlioc->len;
-	ioc.set = nlioc->set;
-	ioc.driver = nlioc->magic;
-	ret = dhd_ioctl_process(dhd, index, &ioc, buf);
-	if (ret) {
-		WL_TRACE(("dhd_ioctl_process return err %d\n", ret));
-		ret = OSL_ERROR(ret);
-		goto done;
-	}
-
-	cur = buf;
-	while (ret_len > 0) {
-		msglen = nlioc->len > maxmsglen ? maxmsglen : ret_len;
-		ret_len -= msglen;
-		payload = msglen + sizeof(msglen);
-		reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
-		if (!reply) {
-			WL_ERR(("Failed to allocate reply msg\n"));
-			ret = -ENOMEM;
-			break;
-		}
-
-		if (nla_put(reply, BCM_NLATTR_DATA, msglen, cur) ||
-			nla_put_u16(reply, BCM_NLATTR_LEN, msglen)) {
-			kfree_skb(reply);
-			ret = -ENOBUFS;
-			break;
-		}
-
-		ret = cfg80211_vendor_cmd_reply(reply);
-		if (ret) {
-			WL_ERR(("testmode reply failed:%d\n", ret));
-			break;
-		}
-		cur += msglen;
-	}
-
-done:
-	vfree(buf);
-	DHD_OS_WAKE_UNLOCK(dhd);
-	return ret;
-}
-
-const struct wiphy_vendor_command dhd_cfgvendor_cmds [] = {
-	{
-		{
-			.vendor_id = OUI_BRCM,
-			.subcmd = BRCM_VENDOR_SCMD_PRIV_STR
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = dhd_cfgvendor_priv_string_handler
-	},
-};
-
-int cfgvendor_attach(struct wiphy *wiphy)
-{
-	wiphy->vendor_commands	= dhd_cfgvendor_cmds;
-	wiphy->n_vendor_commands = ARRAY_SIZE(dhd_cfgvendor_cmds);
-
-	return 0;
-}
-
-int cfgvendor_detach(struct wiphy *wiphy)
-{
-	wiphy->vendor_commands  = NULL;
-	wiphy->n_vendor_commands = 0;
-
-	return 0;
-}
-#endif /* VENDOR_EXT_SUPPORT */
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
deleted file mode 100644
index 55bc9eb..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ /dev/null
@@ -1,3557 +0,0 @@
-/*
- * Broadcom Dongle Host Driver (DHD), common DHD core.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_common.c 609263 2015-12-31 16:21:33Z $
- */
-#include <typedefs.h>
-#include <osl.h>
-
-#include <epivers.h>
-#include <bcmutils.h>
-
-#include <bcmendian.h>
-#include <dngl_stats.h>
-#include <wlioctl.h>
-#include <dhd.h>
-#include <dhd_ip.h>
-#include <proto/bcmevent.h>
-
-#ifdef SHOW_LOGTRACE
-#include <event_log.h>
-#endif /* SHOW_LOGTRACE */
-
-#ifdef BCMPCIE
-#include <dhd_flowring.h>
-#endif
-
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#include <msgtrace.h>
-
-#ifdef WL_CFG80211
-#include <wl_cfg80211.h>
-#endif
-#ifdef PNO_SUPPORT
-#include <dhd_pno.h>
-#endif
-
-#define htod32(i) (i)
-#define htod16(i) (i)
-#define dtoh32(i) (i)
-#define dtoh16(i) (i)
-#define htodchanspec(i) (i)
-#define dtohchanspec(i) (i)
-
-#ifdef PROP_TXSTATUS
-#include <wlfc_proto.h>
-#include <dhd_wlfc.h>
-#endif
-
-#ifdef DHD_WMF
-#include <dhd_linux.h>
-#include <dhd_wmf_linux.h>
-#endif /* DHD_WMF */
-
-#ifdef DHD_L2_FILTER
-#include <dhd_l2_filter.h>
-#endif /* DHD_L2_FILTER */
-
-#ifdef DHD_PSTA
-#include <dhd_psta.h>
-#endif /* DHD_PSTA */
-
-
-#ifdef WLMEDIA_HTSF
-extern void htsf_update(struct dhd_info *dhd, void *data);
-#endif
-
-#ifdef DHD_LOG_DUMP
-int dhd_msg_level = DHD_ERROR_VAL | DHD_MSGTRACE_VAL | DHD_FWLOG_VAL | DHD_EVENT_VAL;
-#else
-int dhd_msg_level = DHD_ERROR_VAL | DHD_MSGTRACE_VAL | DHD_FWLOG_VAL;
-#endif /* DHD_LOG_DUMP */
-
-
-#if defined(WL_WLC_SHIM)
-#include <wl_shim.h>
-#else
-#endif /* WL_WLC_SHIM */
-
-#include <wl_iw.h>
-
-#ifdef SOFTAP
-char fw_path2[MOD_PARAM_PATHLEN];
-extern bool softap_enabled;
-#endif
-
-/* Last connection success/failure status */
-uint32 dhd_conn_event;
-uint32 dhd_conn_status;
-uint32 dhd_conn_reason;
-
-#if defined(SHOW_EVENTS) && defined(SHOW_LOGTRACE)
-static int check_event_log_sequence_number(uint32 seq_no);
-#endif /* defined(SHOW_EVENTS) && defined(SHOW_LOGTRACE) */
-extern int dhd_iscan_request(void * dhdp, uint16 action);
-extern void dhd_ind_scan_confirm(void *h, bool status);
-extern int dhd_iscan_in_progress(void *h);
-void dhd_iscan_lock(void);
-void dhd_iscan_unlock(void);
-extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx);
-#if !defined(AP) && defined(WLP2P)
-extern int dhd_get_concurrent_capabilites(dhd_pub_t *dhd);
-#endif
-
-extern int dhd_socram_dump(struct dhd_bus *bus);
-
-bool ap_cfg_running = FALSE;
-bool ap_fw_loaded = FALSE;
-
-/* Version string to report */
-#ifdef DHD_DEBUG
-#ifndef SRCBASE
-#define SRCBASE        "drivers/net/wireless/bcmdhd"
-#endif
-#define DHD_COMPILED "\nCompiled in " SRCBASE
-#endif /* DHD_DEBUG */
-
-#if defined(DHD_DEBUG)
-const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR;
-#else
-const char dhd_version[] = "\nDongle Host Driver, version " EPI_VERSION_STR "\nCompiled from ";
-#endif 
-char fw_version[FW_VER_STR_LEN] = "\0";
-
-void dhd_set_timer(void *bus, uint wdtick);
-
-
-
-/* IOVar table */
-enum {
-	IOV_VERSION = 1,
-	IOV_MSGLEVEL,
-	IOV_BCMERRORSTR,
-	IOV_BCMERROR,
-	IOV_WDTICK,
-	IOV_DUMP,
-	IOV_CLEARCOUNTS,
-	IOV_LOGDUMP,
-	IOV_LOGCAL,
-	IOV_LOGSTAMP,
-	IOV_GPIOOB,
-	IOV_IOCTLTIMEOUT,
-#if defined(DHD_DEBUG)
-	IOV_CONS,
-	IOV_DCONSOLE_POLL,
-	IOV_DHD_JOIN_TIMEOUT_DBG,
-	IOV_SCAN_TIMEOUT,
-#endif /* defined(DHD_DEBUG) */
-#ifdef PROP_TXSTATUS
-	IOV_PROPTXSTATUS_ENABLE,
-	IOV_PROPTXSTATUS_MODE,
-	IOV_PROPTXSTATUS_OPT,
-	IOV_PROPTXSTATUS_MODULE_IGNORE,
-	IOV_PROPTXSTATUS_CREDIT_IGNORE,
-	IOV_PROPTXSTATUS_TXSTATUS_IGNORE,
-	IOV_PROPTXSTATUS_RXPKT_CHK,
-#endif /* PROP_TXSTATUS */
-	IOV_BUS_TYPE,
-#ifdef WLMEDIA_HTSF
-	IOV_WLPKTDLYSTAT_SZ,
-#endif
-	IOV_CHANGEMTU,
-	IOV_HOSTREORDER_FLOWS,
-#ifdef DHDTCPACK_SUPPRESS
-	IOV_TCPACK_SUPPRESS,
-#endif /* DHDTCPACK_SUPPRESS */
-#ifdef DHD_WMF
-	IOV_WMF_BSS_ENAB,
-	IOV_WMF_UCAST_IGMP,
-	IOV_WMF_MCAST_DATA_SENDUP,
-#ifdef WL_IGMP_UCQUERY
-	IOV_WMF_UCAST_IGMP_QUERY,
-#endif /* WL_IGMP_UCQUERY */
-#ifdef DHD_UCAST_UPNP
-	IOV_WMF_UCAST_UPNP,
-#endif /* DHD_UCAST_UPNP */
-#endif /* DHD_WMF */
-	IOV_AP_ISOLATE,
-#ifdef DHD_L2_FILTER
-	IOV_DHCP_UNICAST,
-	IOV_BLOCK_PING,
-	IOV_PROXY_ARP,
-	IOV_GRAT_ARP,
-#endif /* DHD_L2_FILTER */
-#ifdef DHD_PSTA
-	IOV_PSTA,
-#endif /* DHD_PSTA */
-	IOV_CFG80211_OPMODE,
-	IOV_ASSERT_TYPE,
-	IOV_LMTEST,
-	IOV_LAST
-};
-
-const bcm_iovar_t dhd_iovars[] = {
-	{"version",	IOV_VERSION,	0,	IOVT_BUFFER,	sizeof(dhd_version) },
-#ifdef DHD_DEBUG
-	{"msglevel",	IOV_MSGLEVEL,	0,	IOVT_UINT32,	0 },
-#endif /* DHD_DEBUG */
-	{"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER,	BCME_STRLEN },
-	{"bcmerror",	IOV_BCMERROR,	0,	IOVT_INT8,	0 },
-	{"wdtick",	IOV_WDTICK, 0,	IOVT_UINT32,	0 },
-	{"dump",	IOV_DUMP,	0,	IOVT_BUFFER,	DHD_IOCTL_MAXLEN },
-#ifdef DHD_DEBUG
-	{"cons",	IOV_CONS,	0,	IOVT_BUFFER,	0 },
-	{"dconpoll",	IOV_DCONSOLE_POLL, 0,	IOVT_UINT32,	0 },
-#endif
-	{"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID,	0 },
-	{"gpioob",	IOV_GPIOOB,	0,	IOVT_UINT32,	0 },
-	{"ioctl_timeout",	IOV_IOCTLTIMEOUT,	0,	IOVT_UINT32,	0 },
-#ifdef PROP_TXSTATUS
-	{"proptx",	IOV_PROPTXSTATUS_ENABLE,	0,	IOVT_BOOL,	0 },
-	/*
-	set the proptxtstatus operation mode:
-	0 - Do not do any proptxtstatus flow control
-	1 - Use implied credit from a packet status
-	2 - Use explicit credit
-	*/
-	{"ptxmode",	IOV_PROPTXSTATUS_MODE,	0,	IOVT_UINT32,	0 },
-	{"proptx_opt", IOV_PROPTXSTATUS_OPT,	0,	IOVT_UINT32,	0 },
-	{"pmodule_ignore", IOV_PROPTXSTATUS_MODULE_IGNORE, 0, IOVT_BOOL, 0 },
-	{"pcredit_ignore", IOV_PROPTXSTATUS_CREDIT_IGNORE, 0, IOVT_BOOL, 0 },
-	{"ptxstatus_ignore", IOV_PROPTXSTATUS_TXSTATUS_IGNORE, 0, IOVT_BOOL, 0 },
-	{"rxpkt_chk", IOV_PROPTXSTATUS_RXPKT_CHK, 0, IOVT_BOOL, 0 },
-#endif /* PROP_TXSTATUS */
-	{"bustype", IOV_BUS_TYPE, 0, IOVT_UINT32, 0},
-#ifdef WLMEDIA_HTSF
-	{"pktdlystatsz", IOV_WLPKTDLYSTAT_SZ, 0, IOVT_UINT8, 0 },
-#endif
-	{"changemtu", IOV_CHANGEMTU, 0, IOVT_UINT32, 0 },
-	{"host_reorder_flows", IOV_HOSTREORDER_FLOWS, 0, IOVT_BUFFER,
-	(WLHOST_REORDERDATA_MAXFLOWS + 1) },
-#ifdef DHDTCPACK_SUPPRESS
-	{"tcpack_suppress",	IOV_TCPACK_SUPPRESS,	0,	IOVT_UINT8,	0 },
-#endif /* DHDTCPACK_SUPPRESS */
-#ifdef DHD_WMF
-	{"wmf_bss_enable", IOV_WMF_BSS_ENAB,	0,	IOVT_BOOL,	0 },
-	{"wmf_ucast_igmp", IOV_WMF_UCAST_IGMP,	0,	IOVT_BOOL,	0 },
-	{"wmf_mcast_data_sendup", IOV_WMF_MCAST_DATA_SENDUP,	0,	IOVT_BOOL,	0 },
-#ifdef WL_IGMP_UCQUERY
-	{"wmf_ucast_igmp_query", IOV_WMF_UCAST_IGMP_QUERY, (0), IOVT_BOOL, 0 },
-#endif /* WL_IGMP_UCQUERY */
-#ifdef DHD_UCAST_UPNP
-	{"wmf_ucast_upnp", IOV_WMF_UCAST_UPNP, (0), IOVT_BOOL, 0 },
-#endif /* DHD_UCAST_UPNP */
-#endif /* DHD_WMF */
-#ifdef DHD_L2_FILTER
-	{"dhcp_unicast", IOV_DHCP_UNICAST, (0), IOVT_BOOL, 0 },
-#endif /* DHD_L2_FILTER */
-	{"ap_isolate", IOV_AP_ISOLATE, (0), IOVT_BOOL, 0},
-#ifdef DHD_L2_FILTER
-	{"block_ping", IOV_BLOCK_PING, (0), IOVT_BOOL, 0},
-	{"proxy_arp", IOV_PROXY_ARP, (0), IOVT_BOOL, 0},
-	{"grat_arp", IOV_GRAT_ARP, (0), IOVT_BOOL, 0},
-#endif /* DHD_L2_FILTER */
-#ifdef DHD_PSTA
-	/* PSTA/PSR Mode configuration. 0: DIABLED 1: PSTA 2: PSR */
-	{"psta", IOV_PSTA, 0, IOVT_UINT32, 0},
-#endif /* DHD PSTA */
-	{"op_mode",	IOV_CFG80211_OPMODE,	0,	IOVT_UINT32,	0 },
-	{"assert_type", IOV_ASSERT_TYPE, (0), IOVT_UINT32, 0},
-	{"lmtest", IOV_LMTEST,	0,	IOVT_UINT32,	0 },
-	{NULL, 0, 0, 0, 0 }
-};
-
-#define DHD_IOVAR_BUF_SIZE	128
-
-#ifdef DHD_FW_COREDUMP
-void dhd_save_fwdump(dhd_pub_t *dhd_pub, void * buffer, uint32 length)
-{
-	if (dhd_pub->soc_ram) {
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP)
-		DHD_OS_PREFREE(dhd_pub, dhd_pub->soc_ram, dhd_pub->soc_ram_length);
-#else
-		MFREE(dhd_pub->osh, dhd_pub->soc_ram, dhd_pub->soc_ram_length);
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */
-		dhd_pub->soc_ram = NULL;
-		dhd_pub->soc_ram_length = 0;
-	}
-
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP)
-	dhd_pub->soc_ram = (uint8*)DHD_OS_PREALLOC(dhd_pub,
-		DHD_PREALLOC_MEMDUMP_RAM, length);
-	memset(dhd_pub->soc_ram, 0, length);
-#else
-	dhd_pub->soc_ram = (uint8*) MALLOCZ(dhd_pub->osh, length);
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */
-	if (dhd_pub->soc_ram == NULL) {
-		DHD_ERROR(("%s: Failed to allocate memory for fw crash snap shot.\n",
-			__FUNCTION__));
-		return;
-	}
-
-	dhd_pub->soc_ram_length = length;
-	memcpy(dhd_pub->soc_ram, buffer, length);
-}
-#endif /* DHD_FW_COREDUMP */
-
-/* to NDIS developer, the structure dhd_common is redundant,
- * please do NOT merge it back from other branches !!!
- */
-
-static int
-dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen)
-{
-	char eabuf[ETHER_ADDR_STR_LEN];
-
-	struct bcmstrbuf b;
-	struct bcmstrbuf *strbuf = &b;
-	if (!dhdp || !dhdp->prot || !buf)
-		return BCME_ERROR;
-
-	bcm_binit(strbuf, buf, buflen);
-
-	/* Base DHD info */
-	bcm_bprintf(strbuf, "%s\n", dhd_version);
-	bcm_bprintf(strbuf, "\n");
-	bcm_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
-	            dhdp->up, dhdp->txoff, dhdp->busstate);
-	bcm_bprintf(strbuf, "pub.hdrlen %u pub.maxctl %u pub.rxsz %u\n",
-	            dhdp->hdrlen, dhdp->maxctl, dhdp->rxsz);
-	bcm_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %s\n",
-	            dhdp->iswl, dhdp->drv_version, bcm_ether_ntoa(&dhdp->mac, eabuf));
-	bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %u\n", dhdp->bcmerror, dhdp->tickcnt);
-
-	bcm_bprintf(strbuf, "dongle stats:\n");
-	bcm_bprintf(strbuf, "tx_packets %lu tx_bytes %lu tx_errors %lu tx_dropped %lu\n",
-	            dhdp->dstats.tx_packets, dhdp->dstats.tx_bytes,
-	            dhdp->dstats.tx_errors, dhdp->dstats.tx_dropped);
-	bcm_bprintf(strbuf, "rx_packets %lu rx_bytes %lu rx_errors %lu rx_dropped %lu\n",
-	            dhdp->dstats.rx_packets, dhdp->dstats.rx_bytes,
-	            dhdp->dstats.rx_errors, dhdp->dstats.rx_dropped);
-	bcm_bprintf(strbuf, "multicast %lu\n", dhdp->dstats.multicast);
-
-	bcm_bprintf(strbuf, "bus stats:\n");
-	bcm_bprintf(strbuf, "tx_packets %lu  tx_dropped %lu tx_multicast %lu tx_errors %lu\n",
-	            dhdp->tx_packets, dhdp->tx_dropped, dhdp->tx_multicast, dhdp->tx_errors);
-	bcm_bprintf(strbuf, "tx_ctlpkts %lu tx_ctlerrs %lu\n",
-	            dhdp->tx_ctlpkts, dhdp->tx_ctlerrs);
-	bcm_bprintf(strbuf, "rx_packets %lu rx_multicast %lu rx_errors %lu \n",
-	            dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors);
-	bcm_bprintf(strbuf, "rx_ctlpkts %lu rx_ctlerrs %lu rx_dropped %lu\n",
-	            dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped);
-	bcm_bprintf(strbuf, "rx_readahead_cnt %lu tx_realloc %lu\n",
-	            dhdp->rx_readahead_cnt, dhdp->tx_realloc);
-	bcm_bprintf(strbuf, "tx_pktgetfail %lu rx_pktgetfail %lu\n",
-	            dhdp->tx_pktgetfail, dhdp->rx_pktgetfail);
-	bcm_bprintf(strbuf, "\n");
-
-	/* Add any prot info */
-	dhd_prot_dump(dhdp, strbuf);
-	bcm_bprintf(strbuf, "\n");
-
-	/* Add any bus info */
-	dhd_bus_dump(dhdp, strbuf);
-
-
-#if defined(DHD_LB_STATS)
-	dhd_lb_stats_dump(dhdp, strbuf);
-#endif /* DHD_LB_STATS */
-
-	return (!strbuf->size ? BCME_BUFTOOSHORT : 0);
-}
-
-void
-dhd_dump_to_kernelog(dhd_pub_t *dhdp)
-{
-	char buf[512];
-
-	DHD_ERROR(("F/W version: %s\n", fw_version));
-	bcm_bprintf_bypass = TRUE;
-	dhd_dump(dhdp, buf, sizeof(buf));
-	bcm_bprintf_bypass = FALSE;
-}
-
-int
-dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, int ifidx)
-{
-	wl_ioctl_t ioc;
-
-	ioc.cmd = cmd;
-	ioc.buf = arg;
-	ioc.len = len;
-	ioc.set = set;
-
-	return dhd_wl_ioctl(dhd_pub, ifidx, &ioc, arg, len);
-}
-
-int
-dhd_wl_ioctl_get_intiovar(dhd_pub_t *dhd_pub, char *name, uint *pval,
-	int cmd, uint8 set, int ifidx)
-{
-	char iovbuf[WLC_IOCTL_SMLEN];
-	int ret = -1;
-
-	/* memset(iovbuf, 0, sizeof(iovbuf)); */
-	if (bcm_mkiovar(name, NULL, 0, iovbuf, sizeof(iovbuf))) {
-		ret = dhd_wl_ioctl_cmd(dhd_pub, cmd, iovbuf, sizeof(iovbuf), set, ifidx);
-		if (!ret) {
-			*pval = ltoh32(*((uint*)iovbuf));
-		} else {
-			DHD_ERROR(("%s: get int iovar %s failed, ERR %d\n",
-				__FUNCTION__, name, ret));
-		}
-	} else {
-		DHD_ERROR(("%s: mkiovar %s failed\n",
-			__FUNCTION__, name));
-	}
-
-	return ret;
-}
-
-int
-dhd_wl_ioctl_set_intiovar(dhd_pub_t *dhd_pub, char *name, uint val,
-	int cmd, uint8 set, int ifidx)
-{
-	char iovbuf[WLC_IOCTL_SMLEN];
-	int ret = -1;
-	int lval = htol32(val);
-
-	/* memset(iovbuf, 0, sizeof(iovbuf)); */
-	if (bcm_mkiovar(name, (char*)&lval, sizeof(lval), iovbuf, sizeof(iovbuf))) {
-		ret = dhd_wl_ioctl_cmd(dhd_pub, cmd, iovbuf, sizeof(iovbuf), set, ifidx);
-		if (ret) {
-			DHD_ERROR(("%s: set int iovar %s failed, ERR %d\n",
-				__FUNCTION__, name, ret));
-		}
-	} else {
-		DHD_ERROR(("%s: mkiovar %s failed\n",
-			__FUNCTION__, name));
-	}
-
-	return ret;
-}
-
-int
-dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len)
-{
-	int ret = BCME_ERROR;
-	unsigned long flags;
-
-	if (dhd_os_proto_block(dhd_pub))
-	{
-#ifdef DHD_LOG_DUMP
-		int slen, i, val, rem;
-		long int lval;
-		char *pval, *pos, *msg;
-		char tmp[64];
-#endif /* DHD_LOG_DUMP */
-		DHD_GENERAL_LOCK(dhd_pub, flags);
-		if (dhd_pub->busstate == DHD_BUS_DOWN ||
-				dhd_pub->busstate == DHD_BUS_DOWN_IN_PROGRESS) {
-			DHD_ERROR(("%s: returning as busstate=%d\n",
-				__FUNCTION__, dhd_pub->busstate));
-			DHD_GENERAL_UNLOCK(dhd_pub, flags);
-			dhd_os_proto_unblock(dhd_pub);
-			return -ENODEV;
-		}
-		dhd_pub->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_IOVAR;
-		DHD_GENERAL_UNLOCK(dhd_pub, flags);
-
-#ifdef DHD_LOG_DUMP
-		/* WLC_GET_VAR */
-		if (ioc->cmd == WLC_GET_VAR) {
-			memset(tmp, 0, sizeof(tmp));
-			bcopy(ioc->buf, tmp, strlen(ioc->buf) + 1);
-		}
-#endif /* DHD_LOG_DUMP */
-#ifdef DHD_PCIE_RUNTIMEPM
-		dhdpcie_runtime_bus_wake(dhd_pub, TRUE, dhd_wl_ioctl);
-#endif /* DHD_PCIE_RUNTIMEPM */
-#if defined(WL_WLC_SHIM)
-		{
-			struct wl_shim_node *shim = dhd_pub_shim(dhd_pub);
-
-			wl_io_pport_t io_pport;
-			io_pport.dhd_pub = dhd_pub;
-			io_pport.ifidx = ifidx;
-
-			ret = wl_shim_ioctl(shim, ioc, len, &io_pport);
-			if (ret != BCME_OK) {
-				DHD_TRACE(("%s: wl_shim_ioctl(%d) ERR %d\n",
-					__FUNCTION__, ioc->cmd, ret));
-			}
-		}
-#else
-		ret = dhd_prot_ioctl(dhd_pub, ifidx, ioc, buf, len);
-#endif /* defined(WL_WLC_SHIM) */
-
-		if (ret && dhd_pub->up) {
-			/* Send hang event only if dhd_open() was success */
-			dhd_os_check_hang(dhd_pub, ifidx, ret);
-		}
-
-		if (ret == -ETIMEDOUT && !dhd_pub->up) {
-			DHD_ERROR(("%s: 'resumed on timeout' error is "
-				"occurred before the interface does not"
-				" bring up\n", __FUNCTION__));
-			dhd_pub->busstate = DHD_BUS_DOWN;
-		}
-
-		DHD_GENERAL_LOCK(dhd_pub, flags);
-		dhd_pub->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_IOVAR;
-		dhd_os_busbusy_wake(dhd_pub);
-		DHD_GENERAL_UNLOCK(dhd_pub, flags);
-
-		dhd_os_proto_unblock(dhd_pub);
-
-#ifdef DHD_LOG_DUMP
-		if (ioc->cmd == WLC_GET_VAR || ioc->cmd == WLC_SET_VAR) {
-			lval = 0;
-			slen = strlen(ioc->buf) + 1;
-			msg = (char*)ioc->buf;
-			if (ioc->cmd == WLC_GET_VAR) {
-				bcopy(msg, &lval, sizeof(long int));
-				msg = tmp;
-			} else {
-				bcopy((msg + slen), &lval, sizeof(long int));
-			}
-			DHD_ERROR_EX(("%s: cmd: %d, msg: %s, val: 0x%lx, len: %d, set: %d\n",
-				ioc->cmd == WLC_GET_VAR ? "WLC_GET_VAR" : "WLC_SET_VAR",
-				ioc->cmd, msg, lval, ioc->len, ioc->set));
-		} else {
-			slen = ioc->len;
-			if (ioc->buf != NULL) {
-				val = *(int*)ioc->buf;
-				pval = (char*)ioc->buf;
-				pos = tmp;
-				rem = sizeof(tmp);
-				memset(tmp, 0, sizeof(tmp));
-				for (i = 0; i < slen; i++) {
-					pos += snprintf(pos, rem, "%02x ", pval[i]);
-					rem = sizeof(tmp) - (int)(pos - tmp);
-					if (rem <= 0) {
-						break;
-					}
-				}
-				DHD_ERROR_EX(("WLC_IOCTL: cmd: %d, val: %d(%s), len: %d, set: %d\n",
-				ioc->cmd, val, tmp, ioc->len, ioc->set));
-			} else {
-				DHD_ERROR_EX(("WLC_IOCTL: cmd: %d, buf is NULL\n", ioc->cmd));
-			}
-		}
-#endif /* DHD_LOG_DUMP */
-	}
-
-	return ret;
-}
-
-uint wl_get_port_num(wl_io_pport_t *io_pport)
-{
-	return 0;
-}
-
-/* Get bssidx from iovar params
- * Input:   dhd_pub - pointer to dhd_pub_t
- *	    params  - IOVAR params
- * Output:  idx	    - BSS index
- *	    val	    - ponter to the IOVAR arguments
- */
-static int
-dhd_iovar_parse_bssidx(dhd_pub_t *dhd_pub, char *params, int *idx, char **val)
-{
-	char *prefix = "bsscfg:";
-	uint32	bssidx;
-
-	if (!(strncmp(params, prefix, strlen(prefix)))) {
-		/* per bss setting should be prefixed with 'bsscfg:' */
-		char *p = (char *)params + strlen(prefix);
-
-		/* Skip Name */
-		while (*p != '\0')
-			p++;
-		/* consider null */
-		p = p + 1;
-		bcopy(p, &bssidx, sizeof(uint32));
-		/* Get corresponding dhd index */
-		bssidx = dhd_bssidx2idx(dhd_pub, htod32(bssidx));
-
-		if (bssidx >= DHD_MAX_IFS) {
-			DHD_ERROR(("%s Wrong bssidx provided\n", __FUNCTION__));
-			return BCME_ERROR;
-		}
-
-		/* skip bss idx */
-		p += sizeof(uint32);
-		*val = p;
-		*idx = bssidx;
-	} else {
-		DHD_ERROR(("%s: bad parameter for per bss iovar\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	return BCME_OK;
-}
-
-#if defined(DHD_DEBUG) && defined(BCMDHDUSB)
-/* USB Device console input function */
-int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen)
-{
-	DHD_TRACE(("%s \n", __FUNCTION__));
-
-	return dhd_iovar(dhd, 0, "cons", msg, msglen, 1);
-
-}
-#endif /* DHD_DEBUG && BCMDHDUSB  */
-
-static int
-dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const char *name,
-            void *params, int plen, void *arg, int len, int val_size)
-{
-	int bcmerror = 0;
-	int32 int_val = 0;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-	DHD_TRACE(("%s: actionid = %d; name %s\n", __FUNCTION__, actionid, name));
-
-	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
-		goto exit;
-
-	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
-
-	switch (actionid) {
-	case IOV_GVAL(IOV_VERSION):
-		/* Need to have checked buffer length */
-		bcm_strncpy_s((char*)arg, len, dhd_version, len);
-		break;
-
-	case IOV_GVAL(IOV_MSGLEVEL):
-		int_val = (int32)dhd_msg_level;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_MSGLEVEL):
-#ifdef WL_CFG80211
-		/* Enable DHD and WL logs in oneshot */
-		if (int_val & DHD_WL_VAL2)
-			wl_cfg80211_enable_trace(TRUE, int_val & (~DHD_WL_VAL2));
-		else if (int_val & DHD_WL_VAL)
-			wl_cfg80211_enable_trace(FALSE, WL_DBG_DBG);
-		if (!(int_val & DHD_WL_VAL2))
-#endif /* WL_CFG80211 */
-		dhd_msg_level = int_val;
-		break;
-	case IOV_GVAL(IOV_BCMERRORSTR):
-		bcm_strncpy_s((char *)arg, len, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN);
-		((char *)arg)[BCME_STRLEN - 1] = 0x00;
-		break;
-
-	case IOV_GVAL(IOV_BCMERROR):
-		int_val = (int32)dhd_pub->bcmerror;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_WDTICK):
-		int_val = (int32)dhd_watchdog_ms;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_WDTICK):
-		if (!dhd_pub->up) {
-			bcmerror = BCME_NOTUP;
-			break;
-		}
-
-		if (CUSTOM_DHD_WATCHDOG_MS == 0 && int_val == 0) {
-			dhd_watchdog_ms = (uint)int_val;
-		}
-
-		dhd_os_wd_timer(dhd_pub, (uint)int_val);
-		break;
-
-	case IOV_GVAL(IOV_DUMP):
-		bcmerror = dhd_dump(dhd_pub, arg, len);
-		break;
-
-#ifdef DHD_DEBUG
-	case IOV_GVAL(IOV_DCONSOLE_POLL):
-		int_val = (int32)dhd_console_ms;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DCONSOLE_POLL):
-		dhd_console_ms = (uint)int_val;
-		break;
-
-	case IOV_SVAL(IOV_CONS):
-		if (len > 0)
-			bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
-		break;
-#endif /* DHD_DEBUG */
-
-	case IOV_SVAL(IOV_CLEARCOUNTS):
-		dhd_pub->tx_packets = dhd_pub->rx_packets = 0;
-		dhd_pub->tx_errors = dhd_pub->rx_errors = 0;
-		dhd_pub->tx_ctlpkts = dhd_pub->rx_ctlpkts = 0;
-		dhd_pub->tx_ctlerrs = dhd_pub->rx_ctlerrs = 0;
-		dhd_pub->tx_dropped = 0;
-		dhd_pub->rx_dropped = 0;
-		dhd_pub->tx_pktgetfail = 0;
-		dhd_pub->rx_pktgetfail = 0;
-		dhd_pub->rx_readahead_cnt = 0;
-		dhd_pub->tx_realloc = 0;
-		dhd_pub->wd_dpc_sched = 0;
-		memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats));
-		dhd_bus_clearcounts(dhd_pub);
-#ifdef PROP_TXSTATUS
-		/* clear proptxstatus related counters */
-		dhd_wlfc_clear_counts(dhd_pub);
-#endif /* PROP_TXSTATUS */
-		DHD_LB_STATS_RESET(dhd_pub);
-		break;
-
-
-	case IOV_GVAL(IOV_IOCTLTIMEOUT): {
-		int_val = (int32)dhd_os_get_ioctl_resp_timeout();
-		bcopy(&int_val, arg, sizeof(int_val));
-		break;
-	}
-
-	case IOV_SVAL(IOV_IOCTLTIMEOUT): {
-		if (int_val <= 0)
-			bcmerror = BCME_BADARG;
-		else
-			dhd_os_set_ioctl_resp_timeout((unsigned int)int_val);
-		break;
-	}
-
-
-#ifdef PROP_TXSTATUS
-	case IOV_GVAL(IOV_PROPTXSTATUS_ENABLE): {
-		bool wlfc_enab = FALSE;
-		bcmerror = dhd_wlfc_get_enable(dhd_pub, &wlfc_enab);
-		if (bcmerror != BCME_OK)
-			goto exit;
-		int_val = wlfc_enab ? 1 : 0;
-		bcopy(&int_val, arg, val_size);
-		break;
-	}
-	case IOV_SVAL(IOV_PROPTXSTATUS_ENABLE): {
-		bool wlfc_enab = FALSE;
-		bcmerror = dhd_wlfc_get_enable(dhd_pub, &wlfc_enab);
-		if (bcmerror != BCME_OK)
-			goto exit;
-
-		/* wlfc is already set as desired */
-		if (wlfc_enab == (int_val == 0 ? FALSE : TRUE))
-			goto exit;
-
-		if (int_val == TRUE)
-			bcmerror = dhd_wlfc_init(dhd_pub);
-		else
-			bcmerror = dhd_wlfc_deinit(dhd_pub);
-
-		break;
-	}
-	case IOV_GVAL(IOV_PROPTXSTATUS_MODE):
-		bcmerror = dhd_wlfc_get_mode(dhd_pub, &int_val);
-		if (bcmerror != BCME_OK)
-			goto exit;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_PROPTXSTATUS_MODE):
-		dhd_wlfc_set_mode(dhd_pub, int_val);
-		break;
-
-	case IOV_GVAL(IOV_PROPTXSTATUS_MODULE_IGNORE):
-		bcmerror = dhd_wlfc_get_module_ignore(dhd_pub, &int_val);
-		if (bcmerror != BCME_OK)
-			goto exit;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_PROPTXSTATUS_MODULE_IGNORE):
-		dhd_wlfc_set_module_ignore(dhd_pub, int_val);
-		break;
-
-	case IOV_GVAL(IOV_PROPTXSTATUS_CREDIT_IGNORE):
-		bcmerror = dhd_wlfc_get_credit_ignore(dhd_pub, &int_val);
-		if (bcmerror != BCME_OK)
-			goto exit;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_PROPTXSTATUS_CREDIT_IGNORE):
-		dhd_wlfc_set_credit_ignore(dhd_pub, int_val);
-		break;
-
-	case IOV_GVAL(IOV_PROPTXSTATUS_TXSTATUS_IGNORE):
-		bcmerror = dhd_wlfc_get_txstatus_ignore(dhd_pub, &int_val);
-		if (bcmerror != BCME_OK)
-			goto exit;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_PROPTXSTATUS_TXSTATUS_IGNORE):
-		dhd_wlfc_set_txstatus_ignore(dhd_pub, int_val);
-		break;
-
-	case IOV_GVAL(IOV_PROPTXSTATUS_RXPKT_CHK):
-		bcmerror = dhd_wlfc_get_rxpkt_chk(dhd_pub, &int_val);
-		if (bcmerror != BCME_OK)
-			goto exit;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_PROPTXSTATUS_RXPKT_CHK):
-		dhd_wlfc_set_rxpkt_chk(dhd_pub, int_val);
-		break;
-
-#endif /* PROP_TXSTATUS */
-
-	case IOV_GVAL(IOV_BUS_TYPE):
-		/* The dhd application queries the driver to check if its usb or sdio.  */
-#ifdef BCMDHDUSB
-		int_val = BUS_TYPE_USB;
-#endif
-#ifdef BCMSDIO
-		int_val = BUS_TYPE_SDIO;
-#endif
-#ifdef PCIE_FULL_DONGLE
-		int_val = BUS_TYPE_PCIE;
-#endif
-		bcopy(&int_val, arg, val_size);
-		break;
-
-
-#ifdef WLMEDIA_HTSF
-	case IOV_GVAL(IOV_WLPKTDLYSTAT_SZ):
-		int_val = dhd_pub->htsfdlystat_sz;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_WLPKTDLYSTAT_SZ):
-		dhd_pub->htsfdlystat_sz = int_val & 0xff;
-		printf("Setting tsfdlystat_sz:%d\n", dhd_pub->htsfdlystat_sz);
-		break;
-#endif
-	case IOV_SVAL(IOV_CHANGEMTU):
-		int_val &= 0xffff;
-		bcmerror = dhd_change_mtu(dhd_pub, int_val, 0);
-		break;
-
-	case IOV_GVAL(IOV_HOSTREORDER_FLOWS):
-	{
-		uint i = 0;
-		uint8 *ptr = (uint8 *)arg;
-		uint8 count = 0;
-
-		ptr++;
-		for (i = 0; i < WLHOST_REORDERDATA_MAXFLOWS; i++) {
-			if (dhd_pub->reorder_bufs[i] != NULL) {
-				*ptr = dhd_pub->reorder_bufs[i]->flow_id;
-				ptr++;
-				count++;
-			}
-		}
-		ptr = (uint8 *)arg;
-		*ptr = count;
-		break;
-	}
-#ifdef DHDTCPACK_SUPPRESS
-	case IOV_GVAL(IOV_TCPACK_SUPPRESS): {
-		int_val = (uint32)dhd_pub->tcpack_sup_mode;
-		bcopy(&int_val, arg, val_size);
-		break;
-	}
-	case IOV_SVAL(IOV_TCPACK_SUPPRESS): {
-		bcmerror = dhd_tcpack_suppress_set(dhd_pub, (uint8)int_val);
-		break;
-	}
-#endif /* DHDTCPACK_SUPPRESS */
-#ifdef DHD_WMF
-	case IOV_GVAL(IOV_WMF_BSS_ENAB): {
-		uint32	bssidx;
-		dhd_wmf_t *wmf;
-		char *val;
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: wmf_bss_enable: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-
-		wmf = dhd_wmf_conf(dhd_pub, bssidx);
-		int_val = wmf->wmf_enable ? 1 :0;
-		bcopy(&int_val, arg, val_size);
-		break;
-	}
-	case IOV_SVAL(IOV_WMF_BSS_ENAB): {
-		/* Enable/Disable WMF */
-		uint32	bssidx;
-		dhd_wmf_t *wmf;
-		char *val;
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: wmf_bss_enable: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-
-		ASSERT(val);
-		bcopy(val, &int_val, sizeof(uint32));
-		wmf = dhd_wmf_conf(dhd_pub, bssidx);
-		if (wmf->wmf_enable == int_val)
-			break;
-		if (int_val) {
-			/* Enable WMF */
-			if (dhd_wmf_instance_add(dhd_pub, bssidx) != BCME_OK) {
-				DHD_ERROR(("%s: Error in creating WMF instance\n",
-				__FUNCTION__));
-				break;
-			}
-			if (dhd_wmf_start(dhd_pub, bssidx) != BCME_OK) {
-				DHD_ERROR(("%s: Failed to start WMF\n", __FUNCTION__));
-				break;
-			}
-			wmf->wmf_enable = TRUE;
-		} else {
-			/* Disable WMF */
-			wmf->wmf_enable = FALSE;
-			dhd_wmf_stop(dhd_pub, bssidx);
-			dhd_wmf_instance_del(dhd_pub, bssidx);
-		}
-		break;
-	}
-	case IOV_GVAL(IOV_WMF_UCAST_IGMP):
-		int_val = dhd_pub->wmf_ucast_igmp ? 1 : 0;
-		bcopy(&int_val, arg, val_size);
-		break;
-	case IOV_SVAL(IOV_WMF_UCAST_IGMP):
-		if (dhd_pub->wmf_ucast_igmp == int_val)
-			break;
-
-		if (int_val >= OFF && int_val <= ON)
-			dhd_pub->wmf_ucast_igmp = int_val;
-		else
-			bcmerror = BCME_RANGE;
-		break;
-	case IOV_GVAL(IOV_WMF_MCAST_DATA_SENDUP):
-		int_val = dhd_wmf_mcast_data_sendup(dhd_pub, 0, FALSE, FALSE);
-		bcopy(&int_val, arg, val_size);
-		break;
-	case IOV_SVAL(IOV_WMF_MCAST_DATA_SENDUP):
-		dhd_wmf_mcast_data_sendup(dhd_pub, 0, TRUE, int_val);
-		break;
-
-#ifdef WL_IGMP_UCQUERY
-	case IOV_GVAL(IOV_WMF_UCAST_IGMP_QUERY):
-		int_val = dhd_pub->wmf_ucast_igmp_query ? 1 : 0;
-		bcopy(&int_val, arg, val_size);
-		break;
-	case IOV_SVAL(IOV_WMF_UCAST_IGMP_QUERY):
-		if (dhd_pub->wmf_ucast_igmp_query == int_val)
-			break;
-
-		if (int_val >= OFF && int_val <= ON)
-			dhd_pub->wmf_ucast_igmp_query = int_val;
-		else
-			bcmerror = BCME_RANGE;
-		break;
-#endif /* WL_IGMP_UCQUERY */
-#ifdef DHD_UCAST_UPNP
-	case IOV_GVAL(IOV_WMF_UCAST_UPNP):
-		int_val = dhd_pub->wmf_ucast_upnp ? 1 : 0;
-		bcopy(&int_val, arg, val_size);
-		break;
-	case IOV_SVAL(IOV_WMF_UCAST_UPNP):
-		if (dhd_pub->wmf_ucast_upnp == int_val)
-			break;
-
-		if (int_val >= OFF && int_val <= ON)
-			dhd_pub->wmf_ucast_upnp = int_val;
-		else
-			bcmerror = BCME_RANGE;
-		break;
-#endif /* DHD_UCAST_UPNP */
-#endif /* DHD_WMF */
-
-
-#ifdef DHD_L2_FILTER
-	case IOV_GVAL(IOV_DHCP_UNICAST): {
-		uint32 bssidx;
-		char *val;
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: IOV_DHCP_UNICAST: bad parameterand name = %s\n",
-				__FUNCTION__, name));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		int_val = dhd_get_dhcp_unicast_status(dhd_pub, bssidx);
-		memcpy(arg, &int_val, val_size);
-		break;
-	}
-	case IOV_SVAL(IOV_DHCP_UNICAST): {
-		uint32	bssidx;
-		char *val;
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: IOV_DHCP_UNICAST: bad parameterand name = %s\n",
-				__FUNCTION__, name));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		memcpy(&int_val, val, sizeof(int_val));
-		bcmerror = dhd_set_dhcp_unicast_status(dhd_pub, bssidx, int_val ? 1 : 0);
-		break;
-	}
-	case IOV_GVAL(IOV_BLOCK_PING): {
-		uint32 bssidx;
-		char *val;
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: IOV_BLOCK_PING: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		int_val = dhd_get_block_ping_status(dhd_pub, bssidx);
-		memcpy(arg, &int_val, val_size);
-		break;
-	}
-	case IOV_SVAL(IOV_BLOCK_PING): {
-		uint32	bssidx;
-		char *val;
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: IOV_BLOCK_PING: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		memcpy(&int_val, val, sizeof(int_val));
-		bcmerror = dhd_set_block_ping_status(dhd_pub, bssidx, int_val ? 1 : 0);
-		break;
-	}
-	case IOV_GVAL(IOV_PROXY_ARP): {
-		uint32	bssidx;
-		char *val;
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: IOV_PROXY_ARP: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		int_val = dhd_get_parp_status(dhd_pub, bssidx);
-		bcopy(&int_val, arg, val_size);
-		break;
-	}
-	case IOV_SVAL(IOV_PROXY_ARP): {
-		uint32	bssidx;
-		char *val;
-		char iobuf[32];
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: IOV_PROXY_ARP: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		bcopy(val, &int_val, sizeof(int_val));
-
-		/* Issue a iovar request to WL to update the proxy arp capability bit
-		 * in the Extended Capability IE of beacons/probe responses.
-		 */
-		bcm_mkiovar("proxy_arp_advertise", val, sizeof(int_val), iobuf,
-			sizeof(iobuf));
-		bcmerror =  dhd_wl_ioctl_cmd(dhd_pub, WLC_SET_VAR, iobuf,
-			sizeof(iobuf),	TRUE, bssidx);
-
-		if (bcmerror == BCME_OK) {
-			dhd_set_parp_status(dhd_pub, bssidx, int_val ? 1 : 0);
-		}
-		break;
-	}
-	case IOV_GVAL(IOV_GRAT_ARP): {
-		uint32 bssidx;
-		char *val;
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: IOV_GRAT_ARP: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		int_val = dhd_get_grat_arp_status(dhd_pub, bssidx);
-		memcpy(arg, &int_val, val_size);
-		break;
-	}
-	case IOV_SVAL(IOV_GRAT_ARP): {
-		uint32	bssidx;
-		char *val;
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: IOV_GRAT_ARP: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-		memcpy(&int_val, val, sizeof(int_val));
-		bcmerror = dhd_set_grat_arp_status(dhd_pub, bssidx, int_val ? 1 : 0);
-		break;
-	}
-#endif /* DHD_L2_FILTER */
-	case IOV_GVAL(IOV_AP_ISOLATE): {
-		uint32	bssidx;
-		char *val;
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: ap isoalate: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-
-		int_val = dhd_get_ap_isolate(dhd_pub, bssidx);
-		bcopy(&int_val, arg, val_size);
-		break;
-	}
-	case IOV_SVAL(IOV_AP_ISOLATE): {
-		uint32	bssidx;
-		char *val;
-
-		if (dhd_iovar_parse_bssidx(dhd_pub, (char *)name, &bssidx, &val) != BCME_OK) {
-			DHD_ERROR(("%s: ap isolate: bad parameter\n", __FUNCTION__));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-
-		ASSERT(val);
-		bcopy(val, &int_val, sizeof(uint32));
-		dhd_set_ap_isolate(dhd_pub, bssidx, int_val);
-		break;
-	}
-#ifdef DHD_PSTA
-	case IOV_GVAL(IOV_PSTA): {
-		int_val = dhd_get_psta_mode(dhd_pub);
-		bcopy(&int_val, arg, val_size);
-		break;
-		}
-	case IOV_SVAL(IOV_PSTA): {
-		if (int_val >= DHD_MODE_PSTA_DISABLED && int_val <= DHD_MODE_PSR) {
-			dhd_set_psta_mode(dhd_pub, int_val);
-		} else {
-			bcmerror = BCME_RANGE;
-		}
-		break;
-		}
-#endif /* DHD_PSTA */
-	case IOV_GVAL(IOV_CFG80211_OPMODE): {
-		int_val = (int32)dhd_pub->op_mode;
-		bcopy(&int_val, arg, sizeof(int_val));
-		break;
-		}
-	case IOV_SVAL(IOV_CFG80211_OPMODE): {
-		if (int_val <= 0)
-			bcmerror = BCME_BADARG;
-		else
-			dhd_pub->op_mode = int_val;
-		break;
-	}
-
-	case IOV_GVAL(IOV_ASSERT_TYPE):
-		int_val = g_assert_type;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_ASSERT_TYPE):
-		g_assert_type = (uint32)int_val;
-		break;
-
-
-	case IOV_GVAL(IOV_LMTEST): {
-		*(uint32 *)arg = (uint32)lmtest;
-		break;
-	}
-
-	case IOV_SVAL(IOV_LMTEST): {
-		uint32 val = *(uint32 *)arg;
-		if (val > 50)
-			bcmerror = BCME_BADARG;
-		else {
-			lmtest = (uint)val;
-			DHD_ERROR(("%s: lmtest %s\n",
-				__FUNCTION__, (lmtest == FALSE)? "OFF" : "ON"));
-		}
-		break;
-	}
-
-	default:
-		bcmerror = BCME_UNSUPPORTED;
-		break;
-	}
-
-exit:
-	DHD_TRACE(("%s: actionid %d, bcmerror %d\n", __FUNCTION__, actionid, bcmerror));
-	return bcmerror;
-}
-
-/* Store the status of a connection attempt for later retrieval by an iovar */
-void
-dhd_store_conn_status(uint32 event, uint32 status, uint32 reason)
-{
-	/* Do not overwrite a WLC_E_PRUNE with a WLC_E_SET_SSID
-	 * because an encryption/rsn mismatch results in both events, and
-	 * the important information is in the WLC_E_PRUNE.
-	 */
-	if (!(event == WLC_E_SET_SSID && status == WLC_E_STATUS_FAIL &&
-	      dhd_conn_event == WLC_E_PRUNE)) {
-		dhd_conn_event = event;
-		dhd_conn_status = status;
-		dhd_conn_reason = reason;
-	}
-}
-
-bool
-dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec)
-{
-	void *p;
-	int eprec = -1;		/* precedence to evict from */
-	bool discard_oldest;
-
-	/* Fast case, precedence queue is not full and we are also not
-	 * exceeding total queue length
-	 */
-	if (!pktq_pfull(q, prec) && !pktq_full(q)) {
-		pktq_penq(q, prec, pkt);
-		return TRUE;
-	}
-
-	/* Determine precedence from which to evict packet, if any */
-	if (pktq_pfull(q, prec))
-		eprec = prec;
-	else if (pktq_full(q)) {
-		p = pktq_peek_tail(q, &eprec);
-		ASSERT(p);
-		if (eprec > prec || eprec < 0)
-			return FALSE;
-	}
-
-	/* Evict if needed */
-	if (eprec >= 0) {
-		/* Detect queueing to unconfigured precedence */
-		ASSERT(!pktq_pempty(q, eprec));
-		discard_oldest = AC_BITMAP_TST(dhdp->wme_dp, eprec);
-		if (eprec == prec && !discard_oldest)
-			return FALSE;		/* refuse newer (incoming) packet */
-		/* Evict packet according to discard policy */
-		p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q, eprec);
-		ASSERT(p);
-#ifdef DHDTCPACK_SUPPRESS
-		if (dhd_tcpack_check_xmit(dhdp, p) == BCME_ERROR) {
-			DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
-				__FUNCTION__, __LINE__));
-			dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF);
-		}
-#endif /* DHDTCPACK_SUPPRESS */
-		PKTFREE(dhdp->osh, p, TRUE);
-	}
-
-	/* Enqueue */
-	p = pktq_penq(q, prec, pkt);
-	ASSERT(p);
-
-	return TRUE;
-}
-
-/*
- * Functions to drop proper pkts from queue:
- *	If one pkt in queue is non-fragmented, drop first non-fragmented pkt only
- *	If all pkts in queue are all fragmented, find and drop one whole set fragmented pkts
- *	If can't find pkts matching upper 2 cases, drop first pkt anyway
- */
-bool
-dhd_prec_drop_pkts(dhd_pub_t *dhdp, struct pktq *pq, int prec, f_droppkt_t fn)
-{
-	struct pktq_prec *q = NULL;
-	void *p, *prev = NULL, *next = NULL, *first = NULL, *last = NULL, *prev_first = NULL;
-	pkt_frag_t frag_info;
-
-	ASSERT(dhdp && pq);
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	q = &pq->q[prec];
-	p = q->head;
-
-	if (p == NULL)
-		return FALSE;
-
-	while (p) {
-		frag_info = pkt_frag_info(dhdp->osh, p);
-		if (frag_info == DHD_PKT_FRAG_NONE) {
-			break;
-		} else if (frag_info == DHD_PKT_FRAG_FIRST) {
-			if (first) {
-				/* No last frag pkt, use prev as last */
-				last = prev;
-				break;
-			} else {
-				first = p;
-				prev_first = prev;
-			}
-		} else if (frag_info == DHD_PKT_FRAG_LAST) {
-			if (first) {
-				last = p;
-				break;
-			}
-		}
-
-		prev = p;
-		p = PKTLINK(p);
-	}
-
-	if ((p == NULL) || ((frag_info != DHD_PKT_FRAG_NONE) && !(first && last))) {
-		/* Not found matching pkts, use oldest */
-		prev = NULL;
-		p = q->head;
-		frag_info = 0;
-	}
-
-	if (frag_info == DHD_PKT_FRAG_NONE) {
-		first = last = p;
-		prev_first = prev;
-	}
-
-	p = first;
-	while (p) {
-		next = PKTLINK(p);
-		q->len--;
-		pq->len--;
-
-		PKTSETLINK(p, NULL);
-
-		if (fn)
-			fn(dhdp, prec, p, TRUE);
-
-		if (p == last)
-			break;
-
-		p = next;
-	}
-
-	if (prev_first == NULL) {
-		if ((q->head = next) == NULL)
-			q->tail = NULL;
-	} else {
-		PKTSETLINK(prev_first, next);
-		if (!next)
-			q->tail = prev_first;
-	}
-
-	return TRUE;
-}
-
-static int
-dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name,
-	void *params, int plen, void *arg, int len, bool set)
-{
-	int bcmerror = 0;
-	int val_size;
-	const bcm_iovar_t *vi = NULL;
-	uint32 actionid;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	ASSERT(name);
-	ASSERT(len >= 0);
-
-	/* Get MUST have return space */
-	ASSERT(set || (arg && len));
-
-	/* Set does NOT take qualifiers */
-	ASSERT(!set || (!params && !plen));
-
-	if ((vi = bcm_iovar_lookup(dhd_iovars, name)) == NULL) {
-		bcmerror = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-	DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
-		name, (set ? "set" : "get"), len, plen));
-
-	/* set up 'params' pointer in case this is a set command so that
-	 * the convenience int and bool code can be common to set and get
-	 */
-	if (params == NULL) {
-		params = arg;
-		plen = len;
-	}
-
-	if (vi->type == IOVT_VOID)
-		val_size = 0;
-	else if (vi->type == IOVT_BUFFER)
-		val_size = len;
-	else
-		/* all other types are integer sized */
-		val_size = sizeof(int);
-
-	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
-
-	bcmerror = dhd_doiovar(dhd_pub, vi, actionid, name, params, plen, arg, len, val_size);
-
-exit:
-	return bcmerror;
-}
-
-int
-dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen)
-{
-	int bcmerror = 0;
-	unsigned long flags;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (!buf) {
-		return BCME_BADARG;
-	}
-
-	dhd_os_dhdiovar_lock(dhd_pub);
-	switch (ioc->cmd) {
-		case DHD_GET_MAGIC:
-			if (buflen < sizeof(int))
-				bcmerror = BCME_BUFTOOSHORT;
-			else
-				*(int*)buf = DHD_IOCTL_MAGIC;
-			break;
-
-		case DHD_GET_VERSION:
-			if (buflen < sizeof(int))
-				bcmerror = BCME_BUFTOOSHORT;
-			else
-				*(int*)buf = DHD_IOCTL_VERSION;
-			break;
-
-		case DHD_GET_VAR:
-		case DHD_SET_VAR:
-			{
-				char *arg;
-				uint arglen;
-
-				DHD_GENERAL_LOCK(dhd_pub, flags);
-				if (dhd_pub->busstate == DHD_BUS_DOWN ||
-						dhd_pub->busstate == DHD_BUS_DOWN_IN_PROGRESS) {
-					/* In platforms like FC19, the FW download is done via IOCTL
-					 * and should not return error for IOCTLs fired before FW
-					 * Download is done
-					 */
-					if (dhd_pub->is_fw_download_done) {
-						DHD_ERROR(("%s: returning as busstate=%d\n",
-								__FUNCTION__, dhd_pub->busstate));
-						DHD_GENERAL_UNLOCK(dhd_pub, flags);
-						dhd_os_dhdiovar_unlock(dhd_pub);
-						return -ENODEV;
-					}
-				}
-				dhd_pub->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_DHD_IOVAR;
-				DHD_GENERAL_UNLOCK(dhd_pub, flags);
-#ifdef DHD_PCIE_RUNTIMEPM
-				dhdpcie_runtime_bus_wake(dhd_pub, TRUE, dhd_ioctl);
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-				/* scan past the name to any arguments */
-				for (arg = buf, arglen = buflen; *arg && arglen; arg++, arglen--)
-					;
-
-				if (*arg) {
-					bcmerror = BCME_BUFTOOSHORT;
-					goto unlock_exit;
-				}
-
-				/* account for the NUL terminator */
-				arg++, arglen--;
-
-				/* call with the appropriate arguments */
-				if (ioc->cmd == DHD_GET_VAR) {
-					bcmerror = dhd_iovar_op(dhd_pub, buf, arg, arglen,
-							buf, buflen, IOV_GET);
-				} else {
-					bcmerror = dhd_iovar_op(dhd_pub, buf, NULL, 0,
-							arg, arglen, IOV_SET);
-				}
-				if (bcmerror != BCME_UNSUPPORTED) {
-					goto unlock_exit;
-				}
-
-				/* not in generic table, try protocol module */
-				if (ioc->cmd == DHD_GET_VAR) {
-					bcmerror = dhd_prot_iovar_op(dhd_pub, buf, arg,
-							arglen, buf, buflen, IOV_GET);
-				} else {
-					bcmerror = dhd_prot_iovar_op(dhd_pub, buf,
-							NULL, 0, arg, arglen, IOV_SET);
-				}
-				if (bcmerror != BCME_UNSUPPORTED) {
-					goto unlock_exit;
-				}
-
-				/* if still not found, try bus module */
-				if (ioc->cmd == DHD_GET_VAR) {
-					bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
-							arg, arglen, buf, buflen, IOV_GET);
-				} else {
-					bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
-							NULL, 0, arg, arglen, IOV_SET);
-				}
-			}
-			goto unlock_exit;
-
-		default:
-			bcmerror = BCME_UNSUPPORTED;
-	}
-	dhd_os_dhdiovar_unlock(dhd_pub);
-	return bcmerror;
-
-unlock_exit:
-	DHD_GENERAL_LOCK(dhd_pub, flags);
-	dhd_pub->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_DHD_IOVAR;
-	dhd_os_busbusy_wake(dhd_pub);
-	DHD_GENERAL_UNLOCK(dhd_pub, flags);
-	dhd_os_dhdiovar_unlock(dhd_pub);
-	return bcmerror;
-}
-
-#ifdef SHOW_EVENTS
-#ifdef SHOW_LOGTRACE
-
-#define MAX_NO_OF_ARG	16
-
-#define FMTSTR_SIZE	132
-#define SIZE_LOC_STR	50
-#define MIN_DLEN	4
-#define TAG_BYTES	12
-#define TAG_WORDS	3
-#define ROMSTR_SIZE	200
-
-
-static int
-check_event_log_sequence_number(uint32 seq_no)
-{
-	int32 diff;
-	uint32 ret;
-	static uint32 logtrace_seqnum_prev = 0;
-
-	diff = ntoh32(seq_no)-logtrace_seqnum_prev;
-	switch (diff)
-	{
-		case 0:
-			ret = -1; /* duplicate packet . drop */
-			break;
-
-		case 1:
-			ret =0; /* in order */
-			break;
-
-		default:
-			if ((ntoh32(seq_no) == 0) &&
-				(logtrace_seqnum_prev == 0xFFFFFFFF) ) { /* in-order - Roll over */
-					ret = 0;
-			} else {
-
-				if (diff > 0) {
-					DHD_EVENT(("WLC_E_TRACE:"
-						"Event lost (log) seqnum %d nblost %d\n",
-						ntoh32(seq_no), (diff-1)));
-				} else {
-					DHD_EVENT(("WLC_E_TRACE:"
-						"Event Packets coming out of order!!\n"));
-				}
-				ret = 0;
-			}
-	}
-
-	logtrace_seqnum_prev = ntoh32(seq_no);
-
-	return ret;
-}
-
-static void
-dhd_eventmsg_print(dhd_pub_t *dhd_pub, void *event_data, void *raw_event_ptr,
-		uint datalen, const char *event_name)
-{
-	msgtrace_hdr_t hdr;
-	uint32 nblost;
-	uint8 count;
-	char *s, *p;
-	static uint32 seqnum_prev = 0;
-	uint32 *log_ptr =  NULL;
-	uchar *buf;
-	event_log_hdr_t event_hdr;
-	uint32 i;
-	int32 j;
-
-	dhd_event_log_t *raw_event = (dhd_event_log_t *) raw_event_ptr;
-
-	char fmtstr_loc_buf[FMTSTR_SIZE] = {0};
-	char (*str_buf)[SIZE_LOC_STR] = NULL;
-	char * str_tmpptr = NULL;
-	uint32 addr = 0;
-	uint32 **hdr_ptr = NULL;
-	uint32 h_i = 0;
-	uint32 hdr_ptr_len = 0;
-
-	typedef union {
-		uint32 val;
-		char * addr;
-	} u_arg;
-	u_arg arg[MAX_NO_OF_ARG] = {{0}};
-	char *c_ptr = NULL;
-	char rom_log_str[ROMSTR_SIZE] = {0};
-	uint32 rom_str_len = 0;
-
-	BCM_REFERENCE(arg);
-
-	if (!DHD_FWLOG_ON())
-		return;
-
-	buf = (uchar *) event_data;
-	memcpy(&hdr, buf, MSGTRACE_HDRLEN);
-
-	if (hdr.version != MSGTRACE_VERSION) {
-		DHD_EVENT(("\nMACEVENT: %s [unsupported version --> "
-			"dhd version:%d dongle version:%d]\n",
-			event_name, MSGTRACE_VERSION, hdr.version));
-		/* Reset datalen to avoid display below */
-		datalen = 0;
-		return;
-	}
-
-	if (hdr.trace_type == MSGTRACE_HDR_TYPE_MSG) {
-		/* There are 2 bytes available at the end of data */
-		buf[MSGTRACE_HDRLEN + ntoh16(hdr.len)] = '\0';
-
-		if (ntoh32(hdr.discarded_bytes) || ntoh32(hdr.discarded_printf)) {
-			DHD_FWLOG(("WLC_E_TRACE: [Discarded traces in dongle -->"
-				"discarded_bytes %d discarded_printf %d]\n",
-				ntoh32(hdr.discarded_bytes),
-				ntoh32(hdr.discarded_printf)));
-		}
-
-		nblost = ntoh32(hdr.seqnum) - seqnum_prev - 1;
-		if (nblost > 0) {
-			DHD_FWLOG(("WLC_E_TRACE:"
-				"[Event lost (msg) --> seqnum %d nblost %d\n",
-				ntoh32(hdr.seqnum), nblost));
-		}
-		seqnum_prev = ntoh32(hdr.seqnum);
-
-		/* Display the trace buffer. Advance from
-		 * \n to \n to avoid display big
-		 * printf (issue with Linux printk )
-		 */
-		p = (char *)&buf[MSGTRACE_HDRLEN];
-		while (*p != '\0' && (s = strstr(p, "\n")) != NULL) {
-			*s = '\0';
-			DHD_FWLOG(("[FWLOG] %s\n", p));
-			p = s+1;
-		}
-		if (*p)
-			DHD_FWLOG(("[FWLOG] %s", p));
-
-		/* Reset datalen to avoid display below */
-		datalen = 0;
-
-	} else if (hdr.trace_type == MSGTRACE_HDR_TYPE_LOG) {
-		/* Let the standard event printing work for now */
-		uint32 timestamp, seq, pktlen;
-
-		if (check_event_log_sequence_number(hdr.seqnum)) {
-
-			DHD_EVENT(("%s: WLC_E_TRACE:"
-				"[Event duplicate (log) %d] dropping!!\n",
-				__FUNCTION__, hdr.seqnum));
-			return; /* drop duplicate events */
-		}
-
-		p = (char *)&buf[MSGTRACE_HDRLEN];
-		datalen -= MSGTRACE_HDRLEN;
-		pktlen = ltoh16(*((uint16 *)p));
-		seq = ltoh16(*((uint16 *)(p + 2)));
-		p += MIN_DLEN;
-		datalen -= MIN_DLEN;
-		timestamp = ltoh32(*((uint32 *)p));
-		BCM_REFERENCE(pktlen);
-		BCM_REFERENCE(seq);
-		BCM_REFERENCE(timestamp);
-
-		/*
-		* Allocating max possible number of event TAGs in the received buffer
-		* considering  that  each event requires minimum of TAG_BYTES.
-		*/
-		hdr_ptr_len = ((datalen/TAG_BYTES)+1) * sizeof(uint32*);
-
-		if ((raw_event->fmts)) {
-			if (!(str_buf = MALLOCZ(dhd_pub->osh, (MAX_NO_OF_ARG * SIZE_LOC_STR)))) {
-				DHD_ERROR(("%s: malloc failed str_buf \n", __FUNCTION__));
-			}
-		}
-
-		if (!(hdr_ptr = MALLOCZ(dhd_pub->osh, hdr_ptr_len))) {
-			DHD_ERROR(("%s: malloc failed hdr_ptr \n", __FUNCTION__));
-		}
-
-
-		DHD_MSGTRACE_LOG(("EVENT_LOG_HDR[No.%d]: timestamp 0x%08x length = %d\n",
-				seq, timestamp, pktlen));
-
-		/* (raw_event->fmts) has value */
-
-		log_ptr = (uint32 *) (p + datalen);
-
-		/* Store all hdr pointer while parsing from last of the log buffer
-		* sample format of
-		* 001d3c54 00000064 00000064 001d3c54 001dba08 035d6ce1 0c540639
-		* 001d3c54 00000064 00000064 035d6d89 0c580439
-		* in above example 0c580439 -- 39 is tag , 04 is count, 580c is format number
-		* all these uint32 values comes in reverse order as group as EL data
-		* while decoding we can parse only from last to first
-		*/
-
-		while (datalen > MIN_DLEN) {
-			log_ptr--;
-			datalen -= MIN_DLEN;
-			event_hdr.t = *log_ptr;
-			/*
-			 * Check for partially overriten entries
-			 */
-			if (log_ptr - (uint32 *) p < event_hdr.count) {
-				break;
-			}
-			/*
-			 * Check argument count (only when format is valid)
-			 */
-			if ((event_hdr.count > MAX_NO_OF_ARG) &&
-			    (event_hdr.fmt_num != 0xffff)) {
-				break;
-			}
-			/*
-			 * Check for end of the Frame.
-			 */
-			if (event_hdr.tag ==  EVENT_LOG_TAG_NULL) {
-				continue;
-			}
-			log_ptr[0] = event_hdr.t;
-			if (h_i < (hdr_ptr_len / sizeof(uint32*))) {
-				hdr_ptr[h_i++] = log_ptr;
-			}
-
-			/* Now place the header at the front
-			 * and copy back.
-			 */
-			log_ptr -= event_hdr.count;
-
-			c_ptr = NULL;
-			datalen = datalen - (event_hdr.count * MIN_DLEN);
-		}
-		datalen = 0;
-
-		/* print all log using stored hdr pointer in reverse order of EL data
-		 * which is actually print older log first and then other in order
-		 */
-
-		for (j = (h_i-1); j >= 0; j--) {
-			if (!(hdr_ptr[j])) {
-				break;
-			}
-
-			event_hdr.t = *hdr_ptr[j];
-
-			log_ptr = hdr_ptr[j];
-
-			/* Now place the header at the front
-			* and copy back.
-			*/
-			log_ptr -= event_hdr.count;
-
-			if (event_hdr.tag == EVENT_LOG_TAG_ROM_PRINTF) {
-
-				rom_str_len = ((event_hdr.count)-1) * sizeof(uint32);
-
-				if (rom_str_len >= (ROMSTR_SIZE -1)) {
-					rom_str_len = ROMSTR_SIZE - 1;
-				}
-
-				/* copy all ascii data for ROM printf to local string */
-				memcpy(rom_log_str, log_ptr, rom_str_len);
-				/* add end of line at last */
-				rom_log_str[rom_str_len] = '\0';
-
-				DHD_MSGTRACE_LOG(("EVENT_LOG_ROM[0x%08x]: %s",
-					log_ptr[event_hdr.count - 1], rom_log_str));
-
-				/* Add newline if missing */
-				if (rom_log_str[strlen(rom_log_str) - 1] != '\n') {
-					DHD_EVENT(("\n"));
-				}
-
-				memset(rom_log_str, 0, ROMSTR_SIZE);
-
-				continue;
-			}
-
-			/*
-			 * Check For Special Time Stamp Packet
-			 */
-			if (event_hdr.tag == EVENT_LOG_TAG_TS) {
-				DHD_MSGTRACE_LOG(("EVENT_LOG_TS[0x%08x]: SYS:%08x CPU:%08x\n",
-					log_ptr[event_hdr.count-1], log_ptr[0], log_ptr[1]));
-				continue;
-			}
-
-			/* Simply print out event dump buffer (fmt_num = 0xffff) */
-			if (!str_buf || event_hdr.fmt_num == 0xffff) {
-				/*
-				 * Print out raw value if unable to interpret
-				 */
-#ifdef DHD_LOG_DUMP
-				char buf[256];
-				char *pos = buf;
-				memset(buf, 0, sizeof(buf));
-				pos += snprintf(pos, 256,
-#else
-				DHD_MSGTRACE_LOG((
-#endif /* DHD_LOG_DUMP */
-					"EVENT_LOG_BUF[0x%08x]: tag=%d len=%d fmt=%04x",
-					log_ptr[event_hdr.count-1], event_hdr.tag,
-					event_hdr.count, event_hdr.fmt_num
-#ifdef DHD_LOG_DUMP
-);
-#else
-));
-#endif /* DHD_LOG_DUMP */
-
-				for (count = 0; count < (event_hdr.count-1); count++) {
-#ifdef DHD_LOG_DUMP
-					if (strlen(buf) >= (256 - 1)) {
-						DHD_MSGTRACE_LOG(("%s\n", buf));
-						memset(buf, 0, sizeof(buf));
-						pos = buf;
-					}
-					pos += snprintf(pos, (256 - (int)(pos-buf)),
-						" %08x", log_ptr[count]);
-#else
-					if (count % 8 == 0)
-						DHD_MSGTRACE_LOG(("\n\t%08x", log_ptr[count]));
-					else
-						DHD_MSGTRACE_LOG((" %08x", log_ptr[count]));
-#endif /* DHD_LOG_DUMP */
-				}
-#ifdef DHD_LOG_DUMP
-				DHD_MSGTRACE_LOG(("%s\n", buf));
-#else
-				DHD_MSGTRACE_LOG(("\n"));
-#endif /* DHD_LOG_DUMP */
-				continue;
-			}
-
-			/* Copy the format string to parse %s and add "EVENT_LOG:  */
-			if ((event_hdr.fmt_num >> 2) < raw_event->num_fmts) {
-				snprintf(fmtstr_loc_buf, FMTSTR_SIZE,
-					"EVENT_LOG[0x%08x]: %s", log_ptr[event_hdr.count-1],
-					raw_event->fmts[event_hdr.fmt_num >> 2]);
-				c_ptr = fmtstr_loc_buf;
-			} else {
-				DHD_ERROR(("%s: fmt number out of range \n", __FUNCTION__));
-				continue;
-			}
-
-			for (count = 0; count < (event_hdr.count-1); count++) {
-				if (c_ptr != NULL) {
-					if ((c_ptr = strstr(c_ptr, "%")) != NULL) {
-						c_ptr++;
-					}
-				}
-
-				if ((c_ptr != NULL) && (*c_ptr == 's')) {
-					if ((raw_event->raw_sstr) &&
-						((log_ptr[count] > raw_event->rodata_start) &&
-						(log_ptr[count] < raw_event->rodata_end))) {
-						/* ram static string */
-						addr = log_ptr[count] - raw_event->rodata_start;
-						str_tmpptr = raw_event->raw_sstr + addr;
-						memcpy(str_buf[count], str_tmpptr, SIZE_LOC_STR);
-						str_buf[count][SIZE_LOC_STR-1] = '\0';
-						arg[count].addr = str_buf[count];
-					} else if ((raw_event->rom_raw_sstr) &&
-							((log_ptr[count] >
-							raw_event->rom_rodata_start) &&
-							(log_ptr[count] <
-							raw_event->rom_rodata_end))) {
-						/* rom static string */
-						addr = log_ptr[count] - raw_event->rom_rodata_start;
-						str_tmpptr = raw_event->rom_raw_sstr + addr;
-						memcpy(str_buf[count], str_tmpptr, SIZE_LOC_STR);
-						str_buf[count][SIZE_LOC_STR-1] = '\0';
-						arg[count].addr = str_buf[count];
-					} else {
-						/*
-						*  Dynamic string OR
-						* No data for static string.
-						* So store all string's address as string.
-						*/
-						snprintf(str_buf[count], SIZE_LOC_STR, "(s)0x%x",
-							log_ptr[count]);
-							arg[count].addr = str_buf[count];
-					}
-				} else {
-					/* Other than string */
-					arg[count].val = log_ptr[count];
-				}
-			}
-
-			DHD_MSGTRACE_LOG((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
-				arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
-				arg[11], arg[12], arg[13], arg[14], arg[15]));
-
-			if (fmtstr_loc_buf[strlen(fmtstr_loc_buf) - 1] != '\n') {
-				/* Add newline if missing */
-				DHD_MSGTRACE_LOG(("\n"));
-			}
-
-			memset(fmtstr_loc_buf, 0, FMTSTR_SIZE);
-
-			for (i = 0; i < MAX_NO_OF_ARG; i++) {
-				arg[i].addr = 0;
-			}
-			for (i = 0; i < MAX_NO_OF_ARG; i++) {
-				memset(str_buf[i], 0, SIZE_LOC_STR);
-			}
-
-		}
-		DHD_MSGTRACE_LOG(("\n"));
-
-		if (str_buf) {
-			MFREE(dhd_pub->osh, str_buf, (MAX_NO_OF_ARG * SIZE_LOC_STR));
-		}
-
-		if (hdr_ptr) {
-			MFREE(dhd_pub->osh, hdr_ptr, hdr_ptr_len);
-		}
-	}
-}
-
-#endif /* SHOW_LOGTRACE */
-
-static void
-wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data,
-	void *raw_event_ptr, char *eventmask)
-{
-	uint i, status, reason;
-	bool group = FALSE, flush_txq = FALSE, link = FALSE;
-	bool host_data = FALSE; /* prints  event data after the case  when set */
-	const char *auth_str;
-	const char *event_name;
-	uchar *buf;
-	char err_msg[256], eabuf[ETHER_ADDR_STR_LEN];
-	uint event_type, flags, auth_type, datalen;
-
-	event_type = ntoh32(event->event_type);
-	flags = ntoh16(event->flags);
-	status = ntoh32(event->status);
-	reason = ntoh32(event->reason);
-	BCM_REFERENCE(reason);
-	auth_type = ntoh32(event->auth_type);
-	datalen = ntoh32(event->datalen);
-
-	/* debug dump of event messages */
-	snprintf(eabuf, sizeof(eabuf), "%02x:%02x:%02x:%02x:%02x:%02x",
-	        (uchar)event->addr.octet[0]&0xff,
-	        (uchar)event->addr.octet[1]&0xff,
-	        (uchar)event->addr.octet[2]&0xff,
-	        (uchar)event->addr.octet[3]&0xff,
-	        (uchar)event->addr.octet[4]&0xff,
-	        (uchar)event->addr.octet[5]&0xff);
-
-	event_name = bcmevent_get_name(event_type);
-	BCM_REFERENCE(event_name);
-
-	if (flags & WLC_EVENT_MSG_LINK)
-		link = TRUE;
-	if (flags & WLC_EVENT_MSG_GROUP)
-		group = TRUE;
-	if (flags & WLC_EVENT_MSG_FLUSHTXQ)
-		flush_txq = TRUE;
-
-	switch (event_type) {
-	case WLC_E_START:
-	case WLC_E_DEAUTH:
-	case WLC_E_DISASSOC:
-		DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
-		break;
-
-	case WLC_E_ASSOC_IND:
-	case WLC_E_REASSOC_IND:
-
-		DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
-		break;
-
-	case WLC_E_ASSOC:
-	case WLC_E_REASSOC:
-		if (status == WLC_E_STATUS_SUCCESS) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n", event_name, eabuf));
-		} else if (status == WLC_E_STATUS_TIMEOUT) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n", event_name, eabuf));
-		} else if (status == WLC_E_STATUS_FAIL) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
-			       event_name, eabuf, (int)reason));
-		} else {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, unexpected status %d\n",
-			       event_name, eabuf, (int)status));
-		}
-		break;
-
-	case WLC_E_DEAUTH_IND:
-	case WLC_E_DISASSOC_IND:
-		DHD_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name, eabuf, (int)reason));
-		break;
-
-	case WLC_E_AUTH:
-	case WLC_E_AUTH_IND:
-		if (auth_type == DOT11_OPEN_SYSTEM)
-			auth_str = "Open System";
-		else if (auth_type == DOT11_SHARED_KEY)
-			auth_str = "Shared Key";
-		else {
-			snprintf(err_msg, sizeof(err_msg), "AUTH unknown: %d", (int)auth_type);
-			auth_str = err_msg;
-		}
-		if (event_type == WLC_E_AUTH_IND) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name, eabuf, auth_str));
-		} else if (status == WLC_E_STATUS_SUCCESS) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
-				event_name, eabuf, auth_str));
-		} else if (status == WLC_E_STATUS_TIMEOUT) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
-				event_name, eabuf, auth_str));
-		} else if (status == WLC_E_STATUS_FAIL) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n",
-			       event_name, eabuf, auth_str, (int)reason));
-		}
-		BCM_REFERENCE(auth_str);
-
-		break;
-
-	case WLC_E_JOIN:
-	case WLC_E_ROAM:
-	case WLC_E_SET_SSID:
-		if (status == WLC_E_STATUS_SUCCESS) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
-		} else if (status == WLC_E_STATUS_FAIL) {
-			DHD_EVENT(("MACEVENT: %s, failed\n", event_name));
-		} else if (status == WLC_E_STATUS_NO_NETWORKS) {
-			DHD_EVENT(("MACEVENT: %s, no networks found\n", event_name));
-		} else {
-			DHD_EVENT(("MACEVENT: %s, unexpected status %d\n",
-				event_name, (int)status));
-		}
-		break;
-
-	case WLC_E_BEACON_RX:
-		if (status == WLC_E_STATUS_SUCCESS) {
-			DHD_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
-		} else if (status == WLC_E_STATUS_FAIL) {
-			DHD_EVENT(("MACEVENT: %s, FAIL\n", event_name));
-		} else {
-			DHD_EVENT(("MACEVENT: %s, status %d\n", event_name, status));
-		}
-		break;
-
-	case WLC_E_LINK:
-		DHD_EVENT(("MACEVENT: %s %s\n", event_name, link?"UP":"DOWN"));
-		BCM_REFERENCE(link);
-		break;
-
-	case WLC_E_MIC_ERROR:
-		DHD_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
-		       event_name, eabuf, group, flush_txq));
-		BCM_REFERENCE(group);
-		BCM_REFERENCE(flush_txq);
-		break;
-
-	case WLC_E_ICV_ERROR:
-	case WLC_E_UNICAST_DECODE_ERROR:
-	case WLC_E_MULTICAST_DECODE_ERROR:
-		DHD_EVENT(("MACEVENT: %s, MAC %s\n",
-		       event_name, eabuf));
-		break;
-
-	case WLC_E_TXFAIL:
-		DHD_EVENT(("MACEVENT: %s, RA %s status %d\n", event_name, eabuf, status));
-		break;
-
-	case WLC_E_ASSOC_REQ_IE:
-	case WLC_E_ASSOC_RESP_IE:
-	case WLC_E_PMKID_CACHE:
-	case WLC_E_SCAN_COMPLETE:
-		DHD_EVENT(("MACEVENT: %s\n", event_name));
-		break;
-
-	case WLC_E_PFN_NET_FOUND:
-	case WLC_E_PFN_NET_LOST:
-	case WLC_E_PFN_SCAN_NONE:
-	case WLC_E_PFN_SCAN_ALLGONE:
-	case WLC_E_PFN_GSCAN_FULL_RESULT:
-	case WLC_E_PFN_SWC:
-		DHD_EVENT(("PNOEVENT: %s\n", event_name));
-		break;
-
-	case WLC_E_PSK_SUP:
-	case WLC_E_PRUNE:
-		DHD_EVENT(("MACEVENT: %s, status %d, reason %d\n",
-		           event_name, (int)status, (int)reason));
-		break;
-
-#ifdef WIFI_ACT_FRAME
-	case WLC_E_ACTION_FRAME:
-		DHD_TRACE(("MACEVENT: %s Bssid %s\n", event_name, eabuf));
-		break;
-#endif /* WIFI_ACT_FRAME */
-
-#ifdef SHOW_LOGTRACE
-	case WLC_E_TRACE:
-	{
-		dhd_eventmsg_print(dhd_pub, event_data, raw_event_ptr, datalen, event_name);
-		break;
-	}
-#endif /* SHOW_LOGTRACE */
-
-	case WLC_E_RSSI:
-		DHD_EVENT(("MACEVENT: %s %d\n", event_name, ntoh32(*((int *)event_data))));
-		break;
-
-	case WLC_E_SERVICE_FOUND:
-	case WLC_E_P2PO_ADD_DEVICE:
-	case WLC_E_P2PO_DEL_DEVICE:
-		DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
-		break;
-
-#ifdef BT_WIFI_HANDOBER
-	case WLC_E_BT_WIFI_HANDOVER_REQ:
-		DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
-		break;
-#endif
-
-	case WLC_E_CCA_CHAN_QUAL:
-		if (datalen) {
-			buf = (uchar *) event_data;
-			DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d, "
-				"channel 0x%02x \n", event_name, event_type, eabuf, (int)status,
-				(int)reason, (int)auth_type, *(buf + 4)));
-		}
-		break;
-	case WLC_E_ESCAN_RESULT:
-	{
-#ifndef DHD_IFDEBUG
-		DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d \n",
-		       event_name, event_type, eabuf, (int)status));
-#endif
-	}
-		break;
-	default:
-		DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n",
-		       event_name, event_type, eabuf, (int)status, (int)reason,
-		       (int)auth_type));
-		break;
-	}
-
-	/* show any appended data if message level is set to bytes or host_data is set */
-	if ((DHD_BYTES_ON() || (host_data == TRUE)) && DHD_EVENT_ON() && datalen) {
-		buf = (uchar *) event_data;
-		BCM_REFERENCE(buf);
-		DHD_EVENT((" data (%d) : ", datalen));
-		for (i = 0; i < datalen; i++)
-			DHD_EVENT((" 0x%02x ", *buf++));
-		DHD_EVENT(("\n"));
-	}
-}
-#endif /* SHOW_EVENTS */
-
-/* Stub for now. Will become real function as soon as shim
- * is being integrated to Android, Linux etc.
- */
-int
-wl_event_process_default(wl_event_msg_t *event, struct wl_evt_pport *evt_pport)
-{
-	return BCME_OK;
-}
-
-int
-wl_event_process(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, void **data_ptr, void *raw_event)
-{
-	wl_evt_pport_t evt_pport;
-	wl_event_msg_t event;
-
-	/* make sure it is a BRCM event pkt and record event data */
-	int ret = wl_host_event_get_data(pktdata, &event, data_ptr);
-	if (ret != BCME_OK) {
-		return ret;
-	}
-
-	/* convert event from network order to host order */
-	wl_event_to_host_order(&event);
-
-	/* record event params to evt_pport */
-	evt_pport.dhd_pub = dhd_pub;
-	evt_pport.ifidx = ifidx;
-	evt_pport.pktdata = pktdata;
-	evt_pport.data_ptr = data_ptr;
-	evt_pport.raw_event = raw_event;
-
-#if defined(WL_WLC_SHIM) && defined(WL_WLC_SHIM_EVENTS)
-	{
-		struct wl_shim_node *shim = dhd_pub_shim(dhd_pub);
-		ASSERT(shim);
-		ret = wl_shim_event_process(shim, &event, &evt_pport);
-	}
-#else
-	ret = wl_event_process_default(&event, &evt_pport);
-#endif
-
-	return ret;
-}
-
-/* Check whether packet is a BRCM event pkt. If it is, record event data. */
-int
-wl_host_event_get_data(void *pktdata, wl_event_msg_t *event, void **data_ptr)
-{
-	bcm_event_t *pvt_data = (bcm_event_t *)pktdata;
-
-	if (bcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) {
-		DHD_ERROR(("%s: mismatched OUI, bailing\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	/* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
-	if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) != BCMILCP_BCM_SUBTYPE_EVENT) {
-		DHD_ERROR(("%s: mismatched subtype, bailing\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	*data_ptr = &pvt_data[1];
-
-	/* memcpy since BRCM event pkt may be unaligned. */
-	memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t));
-
-	return BCME_OK;
-}
-
-int
-wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, size_t pktlen,
-	wl_event_msg_t *event, void **data_ptr, void *raw_event)
-{
-	bcm_event_t *pvt_data;
-	uint8 *event_data;
-	uint32 type, status, datalen;
-	uint16 flags;
-	int evlen;
-
-	/* make sure it is a BRCM event pkt and record event data */
-	int ret = wl_host_event_get_data(pktdata, event, data_ptr);
-	if (ret != BCME_OK) {
-		return ret;
-	}
-
-	if (pktlen < sizeof(bcm_event_t))
-		return (BCME_ERROR);
-
-	pvt_data = (bcm_event_t *)pktdata;
-	event_data = *data_ptr;
-
-	type = ntoh32_ua((void *)&event->event_type);
-	flags = ntoh16_ua((void *)&event->flags);
-	status = ntoh32_ua((void *)&event->status);
-
-	datalen = ntoh32_ua((void *)&event->datalen);
-	if (datalen > pktlen)
-		return (BCME_ERROR);
-
-	evlen = datalen + sizeof(bcm_event_t);
-	if (evlen > pktlen) {
-		return (BCME_ERROR);
-	}
-
-	switch (type) {
-#ifdef PROP_TXSTATUS
-	case WLC_E_FIFO_CREDIT_MAP:
-		dhd_wlfc_enable(dhd_pub);
-		dhd_wlfc_FIFOcreditmap_event(dhd_pub, event_data);
-		WLFC_DBGMESG(("WLC_E_FIFO_CREDIT_MAP:(AC0,AC1,AC2,AC3),(BC_MC),(OTHER): "
-			"(%d,%d,%d,%d),(%d),(%d)\n", event_data[0], event_data[1],
-			event_data[2],
-			event_data[3], event_data[4], event_data[5]));
-		break;
-
-	case WLC_E_BCMC_CREDIT_SUPPORT:
-		dhd_wlfc_BCMCCredit_support_event(dhd_pub);
-		break;
-#endif
-
-	case WLC_E_IF:
-		{
-		struct wl_event_data_if *ifevent = (struct wl_event_data_if *)event_data;
-
-		/* Ignore the event if NOIF is set */
-		if (ifevent->reserved & WLC_E_IF_FLAGS_BSSCFG_NOIF) {
-			DHD_ERROR(("WLC_E_IF: NO_IF set, event Ignored\r\n"));
-			return (BCME_UNSUPPORTED);
-		}
-#ifdef PCIE_FULL_DONGLE
-		dhd_update_interface_flow_info(dhd_pub, ifevent->ifidx,
-			ifevent->opcode, ifevent->role);
-#endif
-#ifdef PROP_TXSTATUS
-		{
-			uint8* ea = pvt_data->eth.ether_dhost;
-			WLFC_DBGMESG(("WLC_E_IF: idx:%d, action:%s, iftype:%s, "
-			              "[%02x:%02x:%02x:%02x:%02x:%02x]\n",
-			              ifevent->ifidx,
-			              ((ifevent->opcode == WLC_E_IF_ADD) ? "ADD":"DEL"),
-			              ((ifevent->role == 0) ? "STA":"AP "),
-			              ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]));
-			(void)ea;
-
-			if (ifevent->opcode == WLC_E_IF_CHANGE)
-				dhd_wlfc_interface_event(dhd_pub,
-					eWLFC_MAC_ENTRY_ACTION_UPDATE,
-					ifevent->ifidx, ifevent->role, ea);
-			else
-				dhd_wlfc_interface_event(dhd_pub,
-					((ifevent->opcode == WLC_E_IF_ADD) ?
-					eWLFC_MAC_ENTRY_ACTION_ADD : eWLFC_MAC_ENTRY_ACTION_DEL),
-					ifevent->ifidx, ifevent->role, ea);
-
-			/* dhd already has created an interface by default, for 0 */
-			if (ifevent->ifidx == 0)
-				break;
-		}
-#endif /* PROP_TXSTATUS */
-
-		if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) {
-			if (ifevent->opcode == WLC_E_IF_ADD) {
-				if (dhd_event_ifadd(dhd_pub->info, ifevent, event->ifname,
-					event->addr.octet)) {
-
-					DHD_ERROR(("%s: dhd_event_ifadd failed ifidx: %d  %s\n",
-						__FUNCTION__, ifevent->ifidx, event->ifname));
-					return (BCME_ERROR);
-				}
-			} else if (ifevent->opcode == WLC_E_IF_DEL) {
-				dhd_event_ifdel(dhd_pub->info, ifevent, event->ifname,
-					event->addr.octet);
-			} else if (ifevent->opcode == WLC_E_IF_CHANGE) {
-#ifdef WL_CFG80211
-				wl_cfg80211_notify_ifchange(ifevent->ifidx,
-					event->ifname, event->addr.octet, ifevent->bssidx);
-#endif /* WL_CFG80211 */
-			}
-		} else {
-#if !defined(PROP_TXSTATUS) && !defined(PCIE_FULL_DONGLE) && defined(WL_CFG80211)
-			DHD_ERROR(("%s: Invalid ifidx %d for %s\n",
-			           __FUNCTION__, ifevent->ifidx, event->ifname));
-#endif /* !PROP_TXSTATUS && !PCIE_FULL_DONGLE && WL_CFG80211 */
-		}
-			/* send up the if event: btamp user needs it */
-			*ifidx = dhd_ifname2idx(dhd_pub->info, event->ifname);
-			/* push up to external supp/auth */
-			dhd_event(dhd_pub->info, (char *)pvt_data, evlen, *ifidx);
-		break;
-	}
-
-#ifdef WLMEDIA_HTSF
-	case WLC_E_HTSFSYNC:
-		htsf_update(dhd_pub->info, event_data);
-		break;
-#endif /* WLMEDIA_HTSF */
-	case WLC_E_NDIS_LINK:
-		break;
-	case WLC_E_PFN_NET_FOUND:
-	case WLC_E_PFN_SCAN_ALLGONE: /* share with WLC_E_PFN_BSSID_NET_LOST */
-	case WLC_E_PFN_NET_LOST:
-		break;
-#if defined(PNO_SUPPORT)
-	case WLC_E_PFN_BSSID_NET_FOUND:
-	case WLC_E_PFN_BEST_BATCHING:
-		dhd_pno_event_handler(dhd_pub, event, (void *)event_data);
-		break;
-#endif 
-		/* These are what external supplicant/authenticator wants */
-	case WLC_E_ASSOC_IND:
-	case WLC_E_AUTH_IND:
-	case WLC_E_REASSOC_IND:
-		dhd_findadd_sta(dhd_pub,
-			dhd_ifname2idx(dhd_pub->info, event->ifname),
-			&event->addr.octet);
-		break;
-#if defined(DHD_FW_COREDUMP)
-	case WLC_E_PSM_WATCHDOG:
-		DHD_ERROR(("%s: WLC_E_PSM_WATCHDOG event received : \n", __FUNCTION__));
-		if (dhd_socram_dump(dhd_pub->bus) != BCME_OK) {
-			DHD_ERROR(("%s: socram dump ERROR : \n", __FUNCTION__));
-		}
-	break;
-#endif
-	case WLC_E_LINK:
-#ifdef PCIE_FULL_DONGLE
-		if (dhd_update_interface_link_status(dhd_pub, (uint8)dhd_ifname2idx(dhd_pub->info,
-			event->ifname), (uint8)flags) != BCME_OK)
-			break;
-		if (!flags) {
-			dhd_flow_rings_delete(dhd_pub, (uint8)dhd_ifname2idx(dhd_pub->info,
-				event->ifname));
-		}
-		/* fall through */
-#endif
-	case WLC_E_DEAUTH:
-	case WLC_E_DEAUTH_IND:
-	case WLC_E_DISASSOC:
-	case WLC_E_DISASSOC_IND:
-		DHD_EVENT(("%s: Link event %d, flags %x, status %x\n",
-		           __FUNCTION__, type, flags, status));
-#ifdef PCIE_FULL_DONGLE
-		if (type != WLC_E_LINK) {
-			uint8 ifindex = (uint8)dhd_ifname2idx(dhd_pub->info, event->ifname);
-			uint8 role = dhd_flow_rings_ifindex2role(dhd_pub, ifindex);
-			uint8 del_sta = TRUE;
-#ifdef WL_CFG80211
-			if (role == WLC_E_IF_ROLE_STA && !wl_cfg80211_is_roam_offload() &&
-				!wl_cfg80211_is_event_from_connected_bssid(event, *ifidx)) {
-				del_sta = FALSE;
-			}
-#endif /* WL_CFG80211 */
-
-			if (del_sta) {
-				dhd_del_sta(dhd_pub, dhd_ifname2idx(dhd_pub->info,
-					event->ifname), &event->addr.octet);
-				if (role == WLC_E_IF_ROLE_STA) {
-					dhd_flow_rings_delete(dhd_pub, ifindex);
-				} else {
-					dhd_flow_rings_delete_for_peer(dhd_pub, ifindex,
-						&event->addr.octet[0]);
-				}
-			}
-		}
-#endif /* PCIE_FULL_DONGLE */
-		/* fall through */
-	default:
-		*ifidx = dhd_ifname2idx(dhd_pub->info, event->ifname);
-		/* push up to external supp/auth */
-		dhd_event(dhd_pub->info, (char *)pvt_data, evlen, *ifidx);
-		DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n",
-		           __FUNCTION__, type, flags, status));
-		BCM_REFERENCE(flags);
-		BCM_REFERENCE(status);
-
-		break;
-	}
-
-#ifdef SHOW_EVENTS
-	if (DHD_FWLOG_ON() || DHD_EVENT_ON()) {
-		wl_show_host_event(dhd_pub, event,
-			(void *)event_data, raw_event, dhd_pub->enable_log);
-	}
-#endif /* SHOW_EVENTS */
-
-	return (BCME_OK);
-}
-
-void
-dhd_print_buf(void *pbuf, int len, int bytes_per_line)
-{
-#ifdef DHD_DEBUG
-	int i, j = 0;
-	unsigned char *buf = pbuf;
-
-	if (bytes_per_line == 0) {
-		bytes_per_line = len;
-	}
-
-	for (i = 0; i < len; i++) {
-		printf("%2.2x", *buf++);
-		j++;
-		if (j == bytes_per_line) {
-			printf("\n");
-			j = 0;
-		} else {
-			printf(":");
-		}
-	}
-	printf("\n");
-#endif /* DHD_DEBUG */
-}
-#ifndef strtoul
-#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
-#endif
-
-#ifdef PKT_FILTER_SUPPORT
-/* Convert user's input in hex pattern to byte-size mask */
-static int
-wl_pattern_atoh(char *src, char *dst)
-{
-	int i;
-	if (strncmp(src, "0x", 2) != 0 &&
-	    strncmp(src, "0X", 2) != 0) {
-		DHD_ERROR(("Mask invalid format. Needs to start with 0x\n"));
-		return -1;
-	}
-	src = src + 2; /* Skip past 0x */
-	if (strlen(src) % 2 != 0) {
-		DHD_ERROR(("Mask invalid format. Needs to be of even length\n"));
-		return -1;
-	}
-	for (i = 0; *src != '\0'; i++) {
-		char num[3];
-		bcm_strncpy_s(num, sizeof(num), src, 2);
-		num[2] = '\0';
-		dst[i] = (uint8)strtoul(num, NULL, 16);
-		src += 2;
-	}
-	return i;
-}
-
-void
-dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode)
-{
-	char				*argv[8];
-	int					i = 0;
-	const char			*str;
-	int					buf_len;
-	int					str_len;
-	char				*arg_save = 0, *arg_org = 0;
-	int					rc;
-	char				buf[32] = {0};
-	wl_pkt_filter_enable_t	enable_parm;
-	wl_pkt_filter_enable_t	* pkt_filterp;
-
-	if (!arg)
-		return;
-
-	if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
-		DHD_ERROR(("%s: malloc failed\n", __FUNCTION__));
-		goto fail;
-	}
-	arg_org = arg_save;
-	memcpy(arg_save, arg, strlen(arg) + 1);
-
-	argv[i] = bcmstrtok(&arg_save, " ", 0);
-
-	i = 0;
-	if (argv[i] == NULL) {
-		DHD_ERROR(("No args provided\n"));
-		goto fail;
-	}
-
-	str = "pkt_filter_enable";
-	str_len = strlen(str);
-	bcm_strncpy_s(buf, sizeof(buf) - 1, str, sizeof(buf) - 1);
-	buf[ sizeof(buf) - 1 ] = '\0';
-	buf_len = str_len + 1;
-
-	pkt_filterp = (wl_pkt_filter_enable_t *)(buf + str_len + 1);
-
-	/* Parse packet filter id. */
-	enable_parm.id = htod32(strtoul(argv[i], NULL, 0));
-
-	/* Parse enable/disable value. */
-	enable_parm.enable = htod32(enable);
-
-	buf_len += sizeof(enable_parm);
-	memcpy((char *)pkt_filterp,
-	       &enable_parm,
-	       sizeof(enable_parm));
-
-	/* Enable/disable the specified filter. */
-	rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
-	rc = rc >= 0 ? 0 : rc;
-	if (rc)
-		DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
-		__FUNCTION__, arg, rc));
-	else
-		DHD_TRACE(("%s: successfully added pktfilter %s\n",
-		__FUNCTION__, arg));
-
-	/* Contorl the master mode */
-	rc = dhd_wl_ioctl_set_intiovar(dhd, "pkt_filter_mode",
-		master_mode, WLC_SET_VAR, TRUE, 0);
-	rc = rc >= 0 ? 0 : rc;
-	if (rc)
-		DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
-		__FUNCTION__, arg, rc));
-
-fail:
-	if (arg_org)
-		MFREE(dhd->osh, arg_org, strlen(arg) + 1);
-}
-
-void
-dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg)
-{
-	const char 			*str;
-	wl_pkt_filter_t		pkt_filter;
-	wl_pkt_filter_t		*pkt_filterp;
-	int					buf_len;
-	int					str_len;
-	int 				rc;
-	uint32				mask_size;
-	uint32				pattern_size;
-	char				*argv[8], * buf = 0;
-	int					i = 0;
-	char				*arg_save = 0, *arg_org = 0;
-#define BUF_SIZE		2048
-
-	if (!arg)
-		return;
-
-	if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
-		DHD_ERROR(("%s: malloc failed\n", __FUNCTION__));
-		goto fail;
-	}
-
-	arg_org = arg_save;
-
-	if (!(buf = MALLOC(dhd->osh, BUF_SIZE))) {
-		DHD_ERROR(("%s: malloc failed\n", __FUNCTION__));
-		goto fail;
-	}
-
-	memcpy(arg_save, arg, strlen(arg) + 1);
-
-	if (strlen(arg) > BUF_SIZE) {
-		DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg), (int)sizeof(buf)));
-		goto fail;
-	}
-
-	argv[i] = bcmstrtok(&arg_save, " ", 0);
-	while (argv[i++])
-		argv[i] = bcmstrtok(&arg_save, " ", 0);
-
-	i = 0;
-	if (argv[i] == NULL) {
-		DHD_ERROR(("No args provided\n"));
-		goto fail;
-	}
-
-	str = "pkt_filter_add";
-	str_len = strlen(str);
-	bcm_strncpy_s(buf, BUF_SIZE, str, str_len);
-	buf[ str_len ] = '\0';
-	buf_len = str_len + 1;
-
-	pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
-
-	/* Parse packet filter id. */
-	pkt_filter.id = htod32(strtoul(argv[i], NULL, 0));
-
-	if (argv[++i] == NULL) {
-		DHD_ERROR(("Polarity not provided\n"));
-		goto fail;
-	}
-
-	/* Parse filter polarity. */
-	pkt_filter.negate_match = htod32(strtoul(argv[i], NULL, 0));
-
-	if (argv[++i] == NULL) {
-		DHD_ERROR(("Filter type not provided\n"));
-		goto fail;
-	}
-
-	/* Parse filter type. */
-	pkt_filter.type = htod32(strtoul(argv[i], NULL, 0));
-
-	if (argv[++i] == NULL) {
-		DHD_ERROR(("Offset not provided\n"));
-		goto fail;
-	}
-
-	/* Parse pattern filter offset. */
-	pkt_filter.u.pattern.offset = htod32(strtoul(argv[i], NULL, 0));
-
-	if (argv[++i] == NULL) {
-		DHD_ERROR(("Bitmask not provided\n"));
-		goto fail;
-	}
-
-	/* Parse pattern filter mask. */
-	mask_size =
-		htod32(wl_pattern_atoh(argv[i], (char *) pkt_filterp->u.pattern.mask_and_pattern));
-
-	if (argv[++i] == NULL) {
-		DHD_ERROR(("Pattern not provided\n"));
-		goto fail;
-	}
-
-	/* Parse pattern filter pattern. */
-	pattern_size =
-		htod32(wl_pattern_atoh(argv[i],
-	         (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
-
-	if (mask_size != pattern_size) {
-		DHD_ERROR(("Mask and pattern not the same size\n"));
-		goto fail;
-	}
-
-	pkt_filter.u.pattern.size_bytes = mask_size;
-	buf_len += WL_PKT_FILTER_FIXED_LEN;
-	buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
-
-	/* Keep-alive attributes are set in local	variable (keep_alive_pkt), and
-	** then memcpy'ed into buffer (keep_alive_pktp) since there is no
-	** guarantee that the buffer is properly aligned.
-	*/
-	memcpy((char *)pkt_filterp,
-	       &pkt_filter,
-	       WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
-
-	rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
-	rc = rc >= 0 ? 0 : rc;
-
-	if (rc)
-		DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
-		__FUNCTION__, arg, rc));
-	else
-		DHD_TRACE(("%s: successfully added pktfilter %s\n",
-		__FUNCTION__, arg));
-
-fail:
-	if (arg_org)
-		MFREE(dhd->osh, arg_org, strlen(arg) + 1);
-
-	if (buf)
-		MFREE(dhd->osh, buf, BUF_SIZE);
-}
-
-void dhd_pktfilter_offload_delete(dhd_pub_t *dhd, int id)
-{
-	int ret;
-
-	ret = dhd_wl_ioctl_set_intiovar(dhd, "pkt_filter_delete",
-		id, WLC_SET_VAR, TRUE, 0);
-	if (ret < 0) {
-		DHD_ERROR(("%s: Failed to delete filter ID:%d, ret=%d\n",
-			__FUNCTION__, id, ret));
-	}
-}
-#endif /* PKT_FILTER_SUPPORT */
-
-/* ========================== */
-/* ==== ARP OFFLOAD SUPPORT = */
-/* ========================== */
-#ifdef ARP_OFFLOAD_SUPPORT
-void
-dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode)
-{
-	int retcode;
-
-	retcode = dhd_wl_ioctl_set_intiovar(dhd, "arp_ol",
-		arp_mode, WLC_SET_VAR, TRUE, 0);
-
-	retcode = retcode >= 0 ? 0 : retcode;
-	if (retcode)
-		DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, retcode = %d\n",
-			__FUNCTION__, arp_mode, retcode));
-	else
-		DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
-			__FUNCTION__, arp_mode));
-}
-
-void
-dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
-{
-	int retcode;
-
-	retcode = dhd_wl_ioctl_set_intiovar(dhd, "arpoe",
-		arp_enable, WLC_SET_VAR, TRUE, 0);
-
-	retcode = retcode >= 0 ? 0 : retcode;
-	if (retcode)
-		DHD_TRACE(("%s: failed to enabe ARP offload to %d, retcode = %d\n",
-			__FUNCTION__, arp_enable, retcode));
-	else
-		DHD_TRACE(("%s: successfully enabed ARP offload to %d\n",
-			__FUNCTION__, arp_enable));
-	if (arp_enable) {
-		uint32 version;
-		retcode = dhd_wl_ioctl_get_intiovar(dhd, "arp_version",
-			&version, WLC_GET_VAR, FALSE, 0);
-		if (retcode) {
-			DHD_INFO(("%s: fail to get version (maybe version 1:retcode = %d\n",
-				__FUNCTION__, retcode));
-			dhd->arp_version = 1;
-		}
-		else {
-			DHD_INFO(("%s: ARP Version= %x\n", __FUNCTION__, version));
-			dhd->arp_version = version;
-		}
-	}
-}
-
-void
-dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx)
-{
-	int ret = 0;
-	int iov_len = 0;
-	char iovbuf[DHD_IOVAR_BUF_SIZE];
-
-	if (dhd == NULL) return;
-	if (dhd->arp_version == 1)
-		idx = 0;
-
-	iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf));
-	if (!iov_len) {
-		DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
-			__FUNCTION__, sizeof(iovbuf)));
-		return;
-	}
-	if ((ret  = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx)) < 0)
-		DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
-}
-
-void
-dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx)
-{
-	int ret = 0;
-	int iov_len = 0;
-	char iovbuf[DHD_IOVAR_BUF_SIZE];
-
-	if (dhd == NULL) return;
-	if (dhd->arp_version == 1)
-		idx = 0;
-
-	iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf));
-	if (!iov_len) {
-		DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
-			__FUNCTION__, sizeof(iovbuf)));
-		return;
-	}
-	if ((ret  = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx)) < 0)
-		DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
-}
-
-void
-dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx)
-{
-	int iov_len = 0;
-	char iovbuf[DHD_IOVAR_BUF_SIZE];
-	int retcode;
-
-
-	if (dhd == NULL) return;
-	if (dhd->arp_version == 1)
-		idx = 0;
-	iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr,
-		sizeof(ipaddr), iovbuf, sizeof(iovbuf));
-	if (!iov_len) {
-		DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
-			__FUNCTION__, sizeof(iovbuf)));
-		return;
-	}
-	retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx);
-
-	if (retcode)
-		DHD_TRACE(("%s: ARP ip addr add failed, retcode = %d\n",
-		__FUNCTION__, retcode));
-	else
-		DHD_TRACE(("%s: sARP H ipaddr entry added \n",
-		__FUNCTION__));
-}
-
-int
-dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx)
-{
-	int retcode, i;
-	int iov_len;
-	uint32 *ptr32 = buf;
-	bool clr_bottom = FALSE;
-
-	if (!buf)
-		return -1;
-	if (dhd == NULL) return -1;
-	if (dhd->arp_version == 1)
-		idx = 0;
-
-	iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen);
-	BCM_REFERENCE(iov_len);
-	retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, buflen, FALSE, idx);
-
-	if (retcode) {
-		DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n",
-		__FUNCTION__, retcode));
-
-		return -1;
-	}
-
-	/* clean up the buf, ascii reminder */
-	for (i = 0; i < MAX_IPV4_ENTRIES; i++) {
-		if (!clr_bottom) {
-			if (*ptr32 == 0)
-				clr_bottom = TRUE;
-		} else {
-			*ptr32 = 0;
-		}
-		ptr32++;
-	}
-
-	return 0;
-}
-#endif /* ARP_OFFLOAD_SUPPORT  */
-
-/*
- * Neighbor Discovery Offload: enable NDO feature
- * Called  by ipv6 event handler when interface comes up/goes down
- */
-int
-dhd_ndo_enable(dhd_pub_t * dhd, int ndo_enable)
-{
-	int retcode;
-
-	if (dhd == NULL)
-		return -1;
-
-	retcode = dhd_wl_ioctl_set_intiovar(dhd, "ndoe",
-		ndo_enable, WLC_SET_VAR, TRUE, 0);
-	if (retcode)
-		DHD_ERROR(("%s: failed to enabe ndo to %d, retcode = %d\n",
-			__FUNCTION__, ndo_enable, retcode));
-	else
-		DHD_TRACE(("%s: successfully enabed ndo offload to %d\n",
-			__FUNCTION__, ndo_enable));
-
-	return retcode;
-}
-
-/*
- * Neighbor Discover Offload: enable NDO feature
- * Called  by ipv6 event handler when interface comes up
- */
-int
-dhd_ndo_add_ip(dhd_pub_t *dhd, char* ipv6addr, int idx)
-{
-	int iov_len = 0;
-	char iovbuf[DHD_IOVAR_BUF_SIZE];
-	int retcode;
-
-	if (dhd == NULL)
-		return -1;
-
-	iov_len = bcm_mkiovar("nd_hostip", (char *)ipv6addr,
-		IPV6_ADDR_LEN, iovbuf, sizeof(iovbuf));
-	if (!iov_len) {
-		DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
-			__FUNCTION__, sizeof(iovbuf)));
-		return -1;
-	}
-	retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx);
-
-	if (retcode)
-		DHD_ERROR(("%s: ndo ip addr add failed, retcode = %d\n",
-		__FUNCTION__, retcode));
-	else
-		DHD_TRACE(("%s: ndo ipaddr entry added \n",
-		__FUNCTION__));
-
-	return retcode;
-}
-/*
- * Neighbor Discover Offload: enable NDO feature
- * Called  by ipv6 event handler when interface goes down
- */
-int
-dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx)
-{
-	int iov_len = 0;
-	char iovbuf[DHD_IOVAR_BUF_SIZE];
-	int retcode;
-
-	if (dhd == NULL)
-		return -1;
-
-	iov_len = bcm_mkiovar("nd_hostip_clear", NULL,
-		0, iovbuf, sizeof(iovbuf));
-	if (!iov_len) {
-		DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n",
-			__FUNCTION__, sizeof(iovbuf)));
-		return -1;
-	}
-	retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx);
-
-	if (retcode)
-		DHD_ERROR(("%s: ndo ip addr remove failed, retcode = %d\n",
-		__FUNCTION__, retcode));
-	else
-		DHD_TRACE(("%s: ndo ipaddr entry removed \n",
-		__FUNCTION__));
-
-	return retcode;
-}
-
-
-
-/*
- * returns = TRUE if associated, FALSE if not associated
- */
-bool dhd_is_associated(dhd_pub_t *dhd, uint8 ifidx, int *retval)
-{
-	char bssid[6], zbuf[6];
-	int ret = -1;
-
-	bzero(bssid, 6);
-	bzero(zbuf, 6);
-
-	ret  = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, (char *)&bssid,
-		ETHER_ADDR_LEN, FALSE, ifidx);
-	DHD_TRACE((" %s WLC_GET_BSSID ioctl res = %d\n", __FUNCTION__, ret));
-
-	if (ret == BCME_NOTASSOCIATED) {
-		DHD_TRACE(("%s: not associated! res:%d\n", __FUNCTION__, ret));
-	}
-
-	if (retval)
-		*retval = ret;
-
-	if (ret < 0)
-		return FALSE;
-
-	if ((memcmp(bssid, zbuf, ETHER_ADDR_LEN) == 0)) {
-		DHD_TRACE(("%s: WLC_GET_BSSID ioctl returned zero bssid\n", __FUNCTION__));
-		return FALSE;
-	}
-	return TRUE;
-}
-
-/* Function to estimate possible DTIM_SKIP value */
-int
-dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd)
-{
-	int bcn_li_dtim = 1; /* deafult no dtim skip setting */
-	int ret = -1;
-	int dtim_period = 0;
-	int ap_beacon = 0;
-#ifndef ENABLE_MAX_DTIM_IN_SUSPEND
-	int allowed_skip_dtim_cnt = 0;
-#endif /* !ENABLE_MAX_DTIM_IN_SUSPEND */
-	/* Check if associated */
-	if (dhd_is_associated(dhd, 0, NULL) == FALSE) {
-		DHD_TRACE(("%s NOT assoc ret %d\n", __FUNCTION__, ret));
-		goto exit;
-	}
-
-	/* read associated AP beacon interval */
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BCNPRD,
-		&ap_beacon, sizeof(ap_beacon), FALSE, 0)) < 0) {
-		DHD_ERROR(("%s get beacon failed code %d\n", __FUNCTION__, ret));
-		goto exit;
-	}
-
-	/* read associated ap's dtim setup */
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_DTIMPRD,
-		&dtim_period, sizeof(dtim_period), FALSE, 0)) < 0) {
-		DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
-		goto exit;
-	}
-
-	/* if not assocated just eixt */
-	if (dtim_period == 0) {
-		goto exit;
-	}
-
-#ifdef ENABLE_MAX_DTIM_IN_SUSPEND
-	bcn_li_dtim = (int) (MAX_DTIM_ALLOWED_INTERVAL / (ap_beacon * dtim_period));
-	if (bcn_li_dtim == 0) {
-		bcn_li_dtim = 1;
-	}
-#else /* ENABLE_MAX_DTIM_IN_SUSPEND */
-	/* attemp to use platform defined dtim skip interval */
-	bcn_li_dtim = dhd->suspend_bcn_li_dtim;
-
-	/* check if sta listen interval fits into AP dtim */
-	if (dtim_period > CUSTOM_LISTEN_INTERVAL) {
-		/* AP DTIM to big for our Listen Interval : no dtim skiping */
-		bcn_li_dtim = NO_DTIM_SKIP;
-		DHD_ERROR(("%s DTIM=%d > Listen=%d : too big ...\n",
-			__FUNCTION__, dtim_period, CUSTOM_LISTEN_INTERVAL));
-		goto exit;
-	}
-
-	if ((dtim_period * ap_beacon * bcn_li_dtim) > MAX_DTIM_ALLOWED_INTERVAL) {
-		 allowed_skip_dtim_cnt = MAX_DTIM_ALLOWED_INTERVAL / (dtim_period * ap_beacon);
-		 bcn_li_dtim = (allowed_skip_dtim_cnt != 0) ? allowed_skip_dtim_cnt : NO_DTIM_SKIP;
-	}
-
-	if ((bcn_li_dtim * dtim_period) > CUSTOM_LISTEN_INTERVAL) {
-		/* Round up dtim_skip to fit into STAs Listen Interval */
-		bcn_li_dtim = (int)(CUSTOM_LISTEN_INTERVAL / dtim_period);
-		DHD_TRACE(("%s agjust dtim_skip as %d\n", __FUNCTION__, bcn_li_dtim));
-	}
-#endif /* ENABLE_MAX_DTIM_IN_SUSPEND */
-
-	DHD_ERROR(("%s beacon=%d bcn_li_dtim=%d DTIM=%d Listen=%d\n",
-		__FUNCTION__, ap_beacon, bcn_li_dtim, dtim_period, CUSTOM_LISTEN_INTERVAL));
-
-exit:
-	return bcn_li_dtim;
-}
-
-/* Check if the mode supports STA MODE */
-bool dhd_support_sta_mode(dhd_pub_t *dhd)
-{
-
-#ifdef  WL_CFG80211
-	if (!(dhd->op_mode & DHD_FLAG_STA_MODE))
-		return FALSE;
-	else
-#endif /* WL_CFG80211 */
-		return TRUE;
-}
-
-#if defined(KEEP_ALIVE)
-int dhd_keep_alive_onoff(dhd_pub_t *dhd)
-{
-	char				buf[32] = {0};
-	const char			*str;
-	wl_mkeep_alive_pkt_t	mkeep_alive_pkt = {0};
-	wl_mkeep_alive_pkt_t	*mkeep_alive_pktp;
-	int					buf_len;
-	int					str_len;
-	int res					= -1;
-
-	if (!dhd_support_sta_mode(dhd))
-		return res;
-
-	DHD_TRACE(("%s execution\n", __FUNCTION__));
-
-	str = "mkeep_alive";
-	str_len = strlen(str);
-	strncpy(buf, str, sizeof(buf) - 1);
-	buf[ sizeof(buf) - 1 ] = '\0';
-	mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1);
-	mkeep_alive_pkt.period_msec = CUSTOM_KEEP_ALIVE_SETTING;
-	buf_len = str_len + 1;
-	mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION);
-	mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
-	/* Setup keep alive zero for null packet generation */
-	mkeep_alive_pkt.keep_alive_id = 0;
-	mkeep_alive_pkt.len_bytes = 0;
-	buf_len += WL_MKEEP_ALIVE_FIXED_LEN;
-	bzero(mkeep_alive_pkt.data, sizeof(mkeep_alive_pkt.data));
-	/* Keep-alive attributes are set in local	variable (mkeep_alive_pkt), and
-	 * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no
-	 * guarantee that the buffer is properly aligned.
-	 */
-	memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN);
-
-	res = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
-
-	return res;
-}
-#endif /* defined(KEEP_ALIVE) */
-/* Android ComboSCAN support */
-
-/*
- *  data parsing from ComboScan tlv list
-*/
-int
-wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token,
-                     int input_size, int *bytes_left)
-{
-	char* str;
-	uint16 short_temp;
-	uint32 int_temp;
-
-	if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) {
-		DHD_ERROR(("%s error paramters\n", __FUNCTION__));
-		return -1;
-	}
-	str = *list_str;
-
-	/* Clean all dest bytes */
-	memset(dst, 0, dst_size);
-	while (*bytes_left > 0) {
-
-		if (str[0] != token) {
-			DHD_TRACE(("%s NOT Type=%d get=%d left_parse=%d \n",
-				__FUNCTION__, token, str[0], *bytes_left));
-			return -1;
-		}
-
-		*bytes_left -= 1;
-		str += 1;
-
-		if (input_size == 1) {
-			memcpy(dst, str, input_size);
-		}
-		else if (input_size == 2) {
-			memcpy(dst, (char *)htod16(memcpy(&short_temp, str, input_size)),
-				input_size);
-		}
-		else if (input_size == 4) {
-			memcpy(dst, (char *)htod32(memcpy(&int_temp, str, input_size)),
-				input_size);
-		}
-
-		*bytes_left -= input_size;
-		str += input_size;
-		*list_str = str;
-		return 1;
-	}
-	return 1;
-}
-
-/*
- *  channel list parsing from cscan tlv list
-*/
-int
-wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list,
-                             int channel_num, int *bytes_left)
-{
-	char* str;
-	int idx = 0;
-
-	if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) {
-		DHD_ERROR(("%s error paramters\n", __FUNCTION__));
-		return -1;
-	}
-	str = *list_str;
-
-	while (*bytes_left > 0) {
-
-		if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) {
-			*list_str = str;
-			DHD_TRACE(("End channel=%d left_parse=%d %d\n", idx, *bytes_left, str[0]));
-			return idx;
-		}
-		/* Get proper CSCAN_TLV_TYPE_CHANNEL_IE */
-		*bytes_left -= 1;
-		str += 1;
-
-		if (str[0] == 0) {
-			/* All channels */
-			channel_list[idx] = 0x0;
-		}
-		else {
-			channel_list[idx] = (uint16)str[0];
-			DHD_TRACE(("%s channel=%d \n", __FUNCTION__,  channel_list[idx]));
-		}
-		*bytes_left -= 1;
-		str += 1;
-
-		if (idx++ > 255) {
-			DHD_ERROR(("%s Too many channels \n", __FUNCTION__));
-			return -1;
-		}
-	}
-
-	*list_str = str;
-	return idx;
-}
-
-/*
- *  SSIDs list parsing from cscan tlv list
- */
-int
-wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_ext_t* ssid, int max, int *bytes_left)
-{
-	char* str;
-	int idx = 0;
-
-	if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) {
-		DHD_ERROR(("%s error paramters\n", __FUNCTION__));
-		return -1;
-	}
-	str = *list_str;
-	while (*bytes_left > 0) {
-
-		if (str[0] != CSCAN_TLV_TYPE_SSID_IE) {
-			*list_str = str;
-			DHD_TRACE(("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0]));
-			return idx;
-		}
-
-		/* Get proper CSCAN_TLV_TYPE_SSID_IE */
-		*bytes_left -= 1;
-		str += 1;
-
-		if (str[0] == 0) {
-			/* Broadcast SSID */
-			ssid[idx].SSID_len = 0;
-			memset((char*)ssid[idx].SSID, 0x0, DOT11_MAX_SSID_LEN);
-			*bytes_left -= 1;
-			str += 1;
-
-			DHD_TRACE(("BROADCAST SCAN  left=%d\n", *bytes_left));
-		}
-		else if (str[0] <= DOT11_MAX_SSID_LEN) {
-			/* Get proper SSID size */
-			ssid[idx].SSID_len = str[0];
-			*bytes_left -= 1;
-			str += 1;
-
-			/* Get SSID */
-			if (ssid[idx].SSID_len > *bytes_left) {
-				DHD_ERROR(("%s out of memory range len=%d but left=%d\n",
-				__FUNCTION__, ssid[idx].SSID_len, *bytes_left));
-				return -1;
-			}
-
-			memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len);
-
-			*bytes_left -= ssid[idx].SSID_len;
-			str += ssid[idx].SSID_len;
-			ssid[idx].hidden = TRUE;
-
-			DHD_TRACE(("%s :size=%d left=%d\n",
-				(char*)ssid[idx].SSID, ssid[idx].SSID_len, *bytes_left));
-		}
-		else {
-			DHD_ERROR(("### SSID size more that %d\n", str[0]));
-			return -1;
-		}
-
-		if (idx++ >  max) {
-			DHD_ERROR(("%s number of SSIDs more that %d\n", __FUNCTION__, idx));
-			return -1;
-		}
-	}
-
-	*list_str = str;
-	return idx;
-}
-
-/* Parse a comma-separated list from list_str into ssid array, starting
- * at index idx.  Max specifies size of the ssid array.  Parses ssids
- * and returns updated idx; if idx >= max not all fit, the excess have
- * not been copied.  Returns -1 on empty string, or on ssid too long.
- */
-int
-wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max)
-{
-	char* str, *ptr;
-
-	if ((list_str == NULL) || (*list_str == NULL))
-		return -1;
-
-	for (str = *list_str; str != NULL; str = ptr) {
-
-		/* check for next TAG */
-		if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) {
-			*list_str	 = str + strlen(GET_CHANNEL);
-			return idx;
-		}
-
-		if ((ptr = strchr(str, ',')) != NULL) {
-			*ptr++ = '\0';
-		}
-
-		if (strlen(str) > DOT11_MAX_SSID_LEN) {
-			DHD_ERROR(("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN));
-			return -1;
-		}
-
-		if (strlen(str) == 0)
-			ssid[idx].SSID_len = 0;
-
-		if (idx < max) {
-			bzero(ssid[idx].SSID, sizeof(ssid[idx].SSID));
-			strncpy((char*)ssid[idx].SSID, str, sizeof(ssid[idx].SSID) - 1);
-			ssid[idx].SSID_len = strlen(str);
-		}
-		idx++;
-	}
-	return idx;
-}
-
-/*
- * Parse channel list from iwpriv CSCAN
- */
-int
-wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num)
-{
-	int num;
-	int val;
-	char* str;
-	char* endptr = NULL;
-
-	if ((list_str == NULL)||(*list_str == NULL))
-		return -1;
-
-	str = *list_str;
-	num = 0;
-	while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) {
-		val = (int)strtoul(str, &endptr, 0);
-		if (endptr == str) {
-			printf("could not parse channel number starting at"
-				" substring \"%s\" in list:\n%s\n",
-				str, *list_str);
-			return -1;
-		}
-		str = endptr + strspn(endptr, " ,");
-
-		if (num == channel_num) {
-			DHD_ERROR(("too many channels (more than %d) in channel list:\n%s\n",
-				channel_num, *list_str));
-			return -1;
-		}
-
-		channel_list[num++] = (uint16)val;
-	}
-	*list_str = str;
-	return num;
-}
-
-
-/* Given filename and download type,  returns a buffer pointer and length
- * for download to f/w. Type can be FW or NVRAM.
- *
- */
-int dhd_get_download_buffer(dhd_pub_t	*dhd, char *file_path, download_type_t component,
-	char ** buffer, int *length)
-
-{
-	int ret = BCME_ERROR;
-	int len = 0;
-	int file_len;
-	void *image = NULL;
-	uint8 *buf = NULL;
-
-	/* Point to cache if available. */
-#ifdef CACHE_FW_IMAGES
-	if (component == FW) {
-		if (dhd->cached_fw_length) {
-			len = dhd->cached_fw_length;
-			buf = dhd->cached_fw;
-		}
-	} else if (component == NVRAM) {
-		if (dhd->cached_nvram_length) {
-			len = dhd->cached_nvram_length;
-			buf = dhd->cached_nvram;
-		}
-	} else {
-		return ret;
-	}
-#endif
-	/* No Valid cache found on this call */
-	if (!len) {
-		file_len = *length;
-		*length = 0;
-
-		if (file_path) {
-			image = dhd_os_open_image(file_path);
-			if (image == NULL) {
-				goto err;
-			}
-		}
-
-		buf = MALLOCZ(dhd->osh, file_len);
-		if (buf == NULL) {
-			DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
-				__FUNCTION__, file_len));
-			goto err;
-		}
-
-		/* Download image */
-		len = dhd_os_get_image_block(buf, file_len, image);
-		if ((len <= 0 || len > file_len)) {
-			MFREE(dhd->osh, buf, file_len);
-			goto err;
-		}
-	}
-
-	ret = BCME_OK;
-	*length = len;
-	*buffer = buf;
-
-	/* Cache if first call. */
-#ifdef CACHE_FW_IMAGES
-	if (component == FW) {
-		if (!dhd->cached_fw_length) {
-			dhd->cached_fw = buf;
-			dhd->cached_fw_length = len;
-		}
-	} else if (component == NVRAM) {
-		if (!dhd->cached_nvram_length) {
-			dhd->cached_nvram = buf;
-			dhd->cached_nvram_length = len;
-		}
-	}
-#endif
-
-err:
-	if (image)
-		dhd_os_close_image(image);
-
-	return ret;
-}
-
-void dhd_free_download_buffer(dhd_pub_t	*dhd, void *buffer, int length)
-{
-#ifdef CACHE_FW_IMAGES
-	return;
-#endif
-	MFREE(dhd->osh, buffer, length);
-}
-/* Parse EAPOL 4 way handshake messages */
-void
-dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction)
-{
-	unsigned char type;
-	int pair, ack, mic, kerr, req, sec, install;
-	unsigned short us_tmp;
-	type = dump_data[18];
-	if (type == 2 || type == 254) {
-		us_tmp = (dump_data[19] << 8) | dump_data[20];
-		pair =  0 != (us_tmp & 0x08);
-		ack = 0  != (us_tmp & 0x80);
-		mic = 0  != (us_tmp & 0x100);
-		kerr =  0 != (us_tmp & 0x400);
-		req = 0  != (us_tmp & 0x800);
-		sec = 0  != (us_tmp & 0x200);
-		install  = 0 != (us_tmp & 0x40);
-		if (!sec && !mic && ack && !install && pair && !kerr && !req) {
-			DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s] : M1 of 4way\n",
-				ifname, direction ? "TX" : "RX"));
-		} else if (pair && !install && !ack && mic && !sec && !kerr && !req) {
-			DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s] : M2 of 4way\n",
-				ifname, direction ? "TX" : "RX"));
-		} else if (pair && ack && mic && sec && !kerr && !req) {
-			DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s] : M3 of 4way\n",
-				ifname, direction ? "TX" : "RX"));
-		} else if (pair && !install && !ack && mic && sec && !req && !kerr) {
-			DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s] : M4 of 4way\n",
-				ifname, direction ? "TX" : "RX"));
-		} else {
-			DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s]: ver %d, type %d, replay %d\n",
-				ifname, direction ? "TX" : "RX",
-				dump_data[14], dump_data[15], dump_data[30]));
-		}
-	} else {
-		DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s]: ver %d, type %d, replay %d\n",
-			ifname, direction ? "TX" : "RX",
-			dump_data[14], dump_data[15], dump_data[30]));
-	}
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
deleted file mode 100644
index 43a7140..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Customer code to add GPIO control during WLAN start/stop
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_custom_gpio.c 591129 2015-10-07 05:22:14Z $
- */
-
-#include <typedefs.h>
-#include <linuxver.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_linux.h>
-
-#include <wlioctl.h>
-#if defined(WL_WIRELESS_EXT)
-#include <wl_iw.h>
-#endif
-
-#define WL_ERROR(x) printf x
-#define WL_TRACE(x)
-
-#if defined(OOB_INTR_ONLY)
-
-#if defined(BCMLXSDMMC)
-extern int sdioh_mmc_irq(int irq);
-#endif /* (BCMLXSDMMC)  */
-
-/* Customer specific Host GPIO defintion  */
-static int dhd_oob_gpio_num = -1;
-
-module_param(dhd_oob_gpio_num, int, 0644);
-MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
-
-/* This function will return:
- *  1) return :  Host gpio interrupt number per customer platform
- *  2) irq_flags_ptr : Type of Host interrupt as Level or Edge
- *
- *  NOTE :
- *  Customer should check his platform definitions
- *  and his Host Interrupt spec
- *  to figure out the proper setting for his platform.
- *  Broadcom provides just reference settings as example.
- *
- */
-int dhd_customer_oob_irq_map(void *adapter, unsigned long *irq_flags_ptr)
-{
-	int  host_oob_irq = 0;
-
-#if defined(CUSTOMER_HW2)
-	host_oob_irq = wifi_platform_get_irq_number(adapter, irq_flags_ptr);
-
-#else
-#if defined(CUSTOM_OOB_GPIO_NUM)
-	if (dhd_oob_gpio_num < 0) {
-		dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
-	}
-#endif /* CUSTOMER_OOB_GPIO_NUM */
-
-	if (dhd_oob_gpio_num < 0) {
-		WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
-		__FUNCTION__));
-		return (dhd_oob_gpio_num);
-	}
-
-	WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n",
-	         __FUNCTION__, dhd_oob_gpio_num));
-
-#endif 
-
-	return (host_oob_irq);
-}
-#endif 
-
-/* Customer function to control hw specific wlan gpios */
-int
-dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff)
-{
-	int err = 0;
-
-	return err;
-}
-
-#ifdef GET_CUSTOM_MAC_ENABLE
-/* Function to get custom MAC address */
-int
-dhd_custom_get_mac_address(void *adapter, unsigned char *buf)
-{
-	int ret = 0;
-
-	WL_TRACE(("%s Enter\n", __FUNCTION__));
-	if (!buf)
-		return -EINVAL;
-
-	/* Customer access to MAC address stored outside of DHD driver */
-#if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
-	ret = wifi_platform_get_mac_addr(adapter, buf);
-#endif
-
-#ifdef EXAMPLE_GET_MAC
-	/* EXAMPLE code */
-	{
-		struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
-		bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
-	}
-#endif /* EXAMPLE_GET_MAC */
-
-	return ret;
-}
-#endif /* GET_CUSTOM_MAC_ENABLE */
-
-#if !defined(WL_WIRELESS_EXT)
-struct cntry_locales_custom {
-	char iso_abbrev[WLC_CNTRY_BUF_SZ];	/* ISO 3166-1 country abbreviation */
-	char custom_locale[WLC_CNTRY_BUF_SZ];	/* Custom firmware locale */
-	int32 custom_locale_rev;		/* Custom local revisin default -1 */
-};
-#endif /* WL_WIRELESS_EXT */
-
-/* Customized Locale table : OPTIONAL feature */
-const struct cntry_locales_custom translate_custom_table[] = {
-/* Table should be filled out based on custom platform regulatory requirement */
-#ifdef EXAMPLE_TABLE
-	{"",   "XY", 4},  /* Universal if Country code is unknown or empty */
-	{"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
-	{"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
-	{"EU", "EU", 5},  /* European union countries to : EU regrev 05 */
-	{"AT", "EU", 5},
-	{"BE", "EU", 5},
-	{"BG", "EU", 5},
-	{"CY", "EU", 5},
-	{"CZ", "EU", 5},
-	{"DK", "EU", 5},
-	{"EE", "EU", 5},
-	{"FI", "EU", 5},
-	{"FR", "EU", 5},
-	{"DE", "EU", 5},
-	{"GR", "EU", 5},
-	{"HU", "EU", 5},
-	{"IE", "EU", 5},
-	{"IT", "EU", 5},
-	{"LV", "EU", 5},
-	{"LI", "EU", 5},
-	{"LT", "EU", 5},
-	{"LU", "EU", 5},
-	{"MT", "EU", 5},
-	{"NL", "EU", 5},
-	{"PL", "EU", 5},
-	{"PT", "EU", 5},
-	{"RO", "EU", 5},
-	{"SK", "EU", 5},
-	{"SI", "EU", 5},
-	{"ES", "EU", 5},
-	{"SE", "EU", 5},
-	{"GB", "EU", 5},
-	{"KR", "XY", 3},
-	{"AU", "XY", 3},
-	{"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */
-	{"TW", "XY", 3},
-	{"AR", "XY", 3},
-	{"MX", "XY", 3},
-	{"IL", "IL", 0},
-	{"CH", "CH", 0},
-	{"TR", "TR", 0},
-	{"NO", "NO", 0},
-#endif /* EXMAPLE_TABLE */
-#if defined(CUSTOMER_HW2)
-#if defined(BCM4335_CHIP)
-	{"",   "XZ", 11},  /* Universal if Country code is unknown or empty */
-#endif
-	{"AE", "AE", 1},
-	{"AR", "AR", 1},
-	{"AT", "AT", 1},
-	{"AU", "AU", 2},
-	{"BE", "BE", 1},
-	{"BG", "BG", 1},
-	{"BN", "BN", 1},
-	{"CA", "CA", 2},
-	{"CH", "CH", 1},
-	{"CY", "CY", 1},
-	{"CZ", "CZ", 1},
-	{"DE", "DE", 3},
-	{"DK", "DK", 1},
-	{"EE", "EE", 1},
-	{"ES", "ES", 1},
-	{"FI", "FI", 1},
-	{"FR", "FR", 1},
-	{"GB", "GB", 1},
-	{"GR", "GR", 1},
-	{"HR", "HR", 1},
-	{"HU", "HU", 1},
-	{"IE", "IE", 1},
-	{"IS", "IS", 1},
-	{"IT", "IT", 1},
-	{"ID", "ID", 1},
-	{"JP", "JP", 8},
-	{"KR", "KR", 24},
-	{"KW", "KW", 1},
-	{"LI", "LI", 1},
-	{"LT", "LT", 1},
-	{"LU", "LU", 1},
-	{"LV", "LV", 1},
-	{"MA", "MA", 1},
-	{"MT", "MT", 1},
-	{"MX", "MX", 1},
-	{"NL", "NL", 1},
-	{"NO", "NO", 1},
-	{"PL", "PL", 1},
-	{"PT", "PT", 1},
-	{"PY", "PY", 1},
-	{"RO", "RO", 1},
-	{"SE", "SE", 1},
-	{"SI", "SI", 1},
-	{"SK", "SK", 1},
-	{"TR", "TR", 7},
-	{"TW", "TW", 1},
-	{"IR", "XZ", 11},	/* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */
-	{"SD", "XZ", 11},	/* Universal if Country code is SUDAN */
-	{"SY", "XZ", 11},	/* Universal if Country code is SYRIAN ARAB REPUBLIC */
-	{"GL", "XZ", 11},	/* Universal if Country code is GREENLAND */
-	{"PS", "XZ", 11},	/* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */
-	{"TL", "XZ", 11},	/* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */
-	{"MH", "XZ", 11},	/* Universal if Country code is MARSHALL ISLANDS */
-#ifdef BCM4330_CHIP
-	{"RU", "RU", 1},
-	{"US", "US", 5}
-#endif
-#endif 
-};
-
-
-/* Customized Locale convertor
-*  input : ISO 3166-1 country abbreviation
-*  output: customized cspec
-*/
-#ifdef CUSTOM_COUNTRY_CODE
-void get_customized_country_code(void *adapter, char *country_iso_code,
-  wl_country_t *cspec, u32 flags)
-#else
-void get_customized_country_code(void *adapter, char *country_iso_code, wl_country_t *cspec)
-#endif /* CUSTOM_COUNTRY_CODE */
-{
-#if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
-
-	struct cntry_locales_custom *cloc_ptr;
-
-	if (!cspec)
-		return;
-#ifdef CUSTOM_COUNTRY_CODE
-	cloc_ptr = wifi_platform_get_country_code(adapter, country_iso_code,
-	           flags);
-#else
-	cloc_ptr = wifi_platform_get_country_code(adapter, country_iso_code);
-#endif /* CUSTOM_COUNTRY_CODE */
-	if (cloc_ptr) {
-		strlcpy(cspec->ccode, cloc_ptr->custom_locale, WLC_CNTRY_BUF_SZ);
-		cspec->rev = cloc_ptr->custom_locale_rev;
-	}
-	return;
-#else
-	int size, i;
-
-	size = ARRAYSIZE(translate_custom_table);
-
-	if (cspec == 0)
-		 return;
-
-	if (size == 0)
-		 return;
-
-	for (i = 0; i < size; i++) {
-		if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
-			memcpy(cspec->ccode,
-				translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
-			cspec->rev = translate_custom_table[i].custom_locale_rev;
-			return;
-		}
-	}
-#ifdef EXAMPLE_TABLE
-	/* if no country code matched return first universal code from translate_custom_table */
-	memcpy(cspec->ccode, translate_custom_table[0].custom_locale, WLC_CNTRY_BUF_SZ);
-	cspec->rev = translate_custom_table[0].custom_locale_rev;
-#endif /* EXMAPLE_TABLE */
-	return;
-#endif /* defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) */
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd_dbg.h b/drivers/net/wireless/bcmdhd/dhd_dbg.h
deleted file mode 100644
index 4489981..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_dbg.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Debug/trace/assert driver definitions for Dongle Host Driver.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_dbg.h 598059 2015-11-07 07:31:52Z $
- */
-
-#ifndef _dhd_dbg_
-#define _dhd_dbg_
-
-#if defined(DHD_DEBUG)
-#ifdef DHD_LOG_DUMP
-extern void dhd_log_dump_print(const char *fmt, ...);
-extern char *dhd_log_dump_get_timestamp(void);
-#define DHD_ERROR(args)	\
-do {	\
-	if (dhd_msg_level & DHD_ERROR_VAL) {	\
-		printf args;	\
-		dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__);	\
-		dhd_log_dump_print args;	\
-	}	\
-} while (0)
-#else
-#define DHD_ERROR(args)		do {if (dhd_msg_level & DHD_ERROR_VAL) printf args;} while (0)
-#endif /* DHD_LOG_DUMP */
-#define DHD_TRACE(args)		do {if (dhd_msg_level & DHD_TRACE_VAL) printf args;} while (0)
-#define DHD_INFO(args)		do {if (dhd_msg_level & DHD_INFO_VAL) printf args;} while (0)
-#define DHD_DATA(args)		do {if (dhd_msg_level & DHD_DATA_VAL) printf args;} while (0)
-#define DHD_CTL(args)		do {if (dhd_msg_level & DHD_CTL_VAL) printf args;} while (0)
-#define DHD_TIMER(args)		do {if (dhd_msg_level & DHD_TIMER_VAL) printf args;} while (0)
-#define DHD_HDRS(args)		do {if (dhd_msg_level & DHD_HDRS_VAL) printf args;} while (0)
-#define DHD_BYTES(args)		do {if (dhd_msg_level & DHD_BYTES_VAL) printf args;} while (0)
-#define DHD_INTR(args)		do {if (dhd_msg_level & DHD_INTR_VAL) printf args;} while (0)
-#define DHD_GLOM(args)		do {if (dhd_msg_level & DHD_GLOM_VAL) printf args;} while (0)
-#ifdef DHD_LOG_DUMP
-#define DHD_EVENT(args) \
-do {	\
-	if (dhd_msg_level & DHD_EVENT_VAL) {	\
-		printf args;	\
-		dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__);	\
-		dhd_log_dump_print args;	\
-	}	\
-} while (0)
-#else
-#define DHD_EVENT(args)		do {if (dhd_msg_level & DHD_EVENT_VAL) printf args;} while (0)
-#endif /* DHD_LOG_DUMP */
-#define DHD_BTA(args)		do {if (dhd_msg_level & DHD_BTA_VAL) printf args;} while (0)
-#define DHD_ISCAN(args)		do {if (dhd_msg_level & DHD_ISCAN_VAL) printf args;} while (0)
-#define DHD_ARPOE(args)		do {if (dhd_msg_level & DHD_ARPOE_VAL) printf args;} while (0)
-#define DHD_REORDER(args)	do {if (dhd_msg_level & DHD_REORDER_VAL) printf args;} while (0)
-#define DHD_PNO(args)		do {if (dhd_msg_level & DHD_PNO_VAL) printf args;} while (0)
-#ifdef DHD_LOG_DUMP
-#define DHD_MSGTRACE_LOG(args)	\
-do {	\
-	if (dhd_msg_level & DHD_MSGTRACE_VAL) {	\
-		printf args;	\
-		dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__);	\
-		dhd_log_dump_print args;	\
-	}   \
-} while (0)
-#else
-#define DHD_MSGTRACE_LOG(args)  do {if (dhd_msg_level & DHD_MSGTRACE_VAL) printf args;} while (0)
-#endif /* DHD_LOG_DUMP */
-#define DHD_FWLOG(args)		do {if (dhd_msg_level & DHD_FWLOG_VAL) printf args;} while (0)
-#define DHD_RTT(args)		do {if (dhd_msg_level & DHD_RTT_VAL) printf args;} while (0)
-#define DHD_IOV_INFO(args)	do {if (dhd_msg_level & DHD_IOV_INFO_VAL) printf args;} while (0)
-
-#ifdef DHD_LOG_DUMP
-#define DHD_ERROR_EX(args)                  \
-do {                                        \
-	if (dhd_msg_level & DHD_ERROR_VAL) {    \
-		dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__);	\
-		dhd_log_dump_print args;	\
-	}	\
-} while (0)
-#else
-#define DHD_ERROR_EX(args) DHD_ERROR(args)
-#endif /* DHD_LOG_DUMP */
-
-#ifdef CUSTOMER_HW4_DEBUG
-#define DHD_TRACE_HW4	DHD_ERROR
-#define DHD_INFO_HW4	DHD_ERROR
-#else
-#define DHD_TRACE_HW4	DHD_TRACE
-#define DHD_INFO_HW4	DHD_INFO
-#endif /* CUSTOMER_HW4_DEBUG */
-
-#define DHD_ERROR_ON()		(dhd_msg_level & DHD_ERROR_VAL)
-#define DHD_TRACE_ON()		(dhd_msg_level & DHD_TRACE_VAL)
-#define DHD_INFO_ON()		(dhd_msg_level & DHD_INFO_VAL)
-#define DHD_DATA_ON()		(dhd_msg_level & DHD_DATA_VAL)
-#define DHD_CTL_ON()		(dhd_msg_level & DHD_CTL_VAL)
-#define DHD_TIMER_ON()		(dhd_msg_level & DHD_TIMER_VAL)
-#define DHD_HDRS_ON()		(dhd_msg_level & DHD_HDRS_VAL)
-#define DHD_BYTES_ON()		(dhd_msg_level & DHD_BYTES_VAL)
-#define DHD_INTR_ON()		(dhd_msg_level & DHD_INTR_VAL)
-#define DHD_GLOM_ON()		(dhd_msg_level & DHD_GLOM_VAL)
-#define DHD_EVENT_ON()		(dhd_msg_level & DHD_EVENT_VAL)
-#define DHD_BTA_ON()		(dhd_msg_level & DHD_BTA_VAL)
-#define DHD_ISCAN_ON()		(dhd_msg_level & DHD_ISCAN_VAL)
-#define DHD_ARPOE_ON()		(dhd_msg_level & DHD_ARPOE_VAL)
-#define DHD_REORDER_ON()	(dhd_msg_level & DHD_REORDER_VAL)
-#define DHD_NOCHECKDIED_ON()	(dhd_msg_level & DHD_NOCHECKDIED_VAL)
-#define DHD_PNO_ON()		(dhd_msg_level & DHD_PNO_VAL)
-#define DHD_FWLOG_ON()		(dhd_msg_level & DHD_FWLOG_VAL)
-#define DHD_IOV_INFO_ON()	(dhd_msg_level & DHD_IOV_INFO_VAL)
-
-#else /* defined(BCMDBG) || defined(DHD_DEBUG) */
-
-#define DHD_ERROR(args)		do {printf args;} while (0)
-#define DHD_TRACE(args)
-#define DHD_INFO(args)
-#define DHD_DATA(args)
-#define DHD_CTL(args)
-#define DHD_TIMER(args)
-#define DHD_HDRS(args)
-#define DHD_BYTES(args)
-#define DHD_INTR(args)
-#define DHD_GLOM(args)
-#define DHD_EVENT(args)
-#define DHD_BTA(args)
-#define DHD_ISCAN(args)
-#define DHD_ARPOE(args)
-#define DHD_REORDER(args)
-#define DHD_PNO(args)
-#define DHD_MSGTRACE_LOG(args)
-#define DHD_FWLOG(args)
-#define DHD_IOV_INFO(args)
-#define DHD_ERROR_EX(args) DHD_ERROR(args)
-
-#ifdef CUSTOMER_HW4_DEBUG
-#define DHD_TRACE_HW4	DHD_ERROR
-#define DHD_INFO_HW4	DHD_ERROR
-#else
-#define DHD_TRACE_HW4	DHD_TRACE
-#define DHD_INFO_HW4	DHD_INFO
-#endif /* CUSTOMER_HW4_DEBUG */
-
-#define DHD_ERROR_ON()		0
-#define DHD_TRACE_ON()		0
-#define DHD_INFO_ON()		0
-#define DHD_DATA_ON()		0
-#define DHD_CTL_ON()		0
-#define DHD_TIMER_ON()		0
-#define DHD_HDRS_ON()		0
-#define DHD_BYTES_ON()		0
-#define DHD_INTR_ON()		0
-#define DHD_GLOM_ON()		0
-#define DHD_EVENT_ON()		0
-#define DHD_BTA_ON()		0
-#define DHD_ISCAN_ON()		0
-#define DHD_ARPOE_ON()		0
-#define DHD_REORDER_ON()	0
-#define DHD_NOCHECKDIED_ON()	0
-#define DHD_PNO_ON()		0
-#define DHD_FWLOG_ON()		0
-#define DHD_IOV_INFO_ON()	0
-
-#endif 
-
-#define DHD_LOG(args)
-
-#define DHD_BLOG(cp, size)
-
-#define DHD_NONE(args)
-extern int dhd_msg_level;
-
-/* Defines msg bits */
-#include <dhdioctl.h>
-
-#endif /* _dhd_dbg_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_flowring.c b/drivers/net/wireless/bcmdhd/dhd_flowring.c
deleted file mode 100644
index 759dd0e..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_flowring.c
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
- * @file Broadcom Dongle Host Driver (DHD), Flow ring specific code at top level
- *
- * Flow rings are transmit traffic (=propagating towards antenna) related entities
- *
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_flowring.c 591285 2015-10-07 11:56:29Z $
- */
-
-
-#include <typedefs.h>
-#include <bcmutils.h>
-#include <bcmendian.h>
-#include <bcmdevs.h>
-
-#include <proto/ethernet.h>
-#include <proto/bcmevent.h>
-#include <dngl_stats.h>
-
-#include <dhd.h>
-
-#include <dhd_flowring.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#include <proto/802.1d.h>
-#include <pcie_core.h>
-#include <bcmmsgbuf.h>
-#include <dhd_pcie.h>
-
-
-static INLINE int dhd_flow_queue_throttle(flow_queue_t *queue);
-
-static INLINE uint16 dhd_flowid_find(dhd_pub_t *dhdp, uint8 ifindex,
-                                     uint8 prio, char *sa, char *da);
-
-static INLINE uint16 dhd_flowid_alloc(dhd_pub_t *dhdp, uint8 ifindex,
-                                      uint8 prio, char *sa, char *da);
-
-static INLINE int dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex,
-                                uint8 prio, char *sa, char *da, uint16 *flowid);
-int BCMFASTPATH dhd_flow_queue_overflow(flow_queue_t *queue, void *pkt);
-
-#define FLOW_QUEUE_PKT_NEXT(p)          PKTLINK(p)
-#define FLOW_QUEUE_PKT_SETNEXT(p, x)    PKTSETLINK((p), (x))
-
-#ifdef DHD_LOSSLESS_ROAMING
-const uint8 prio2ac[8] = { 0, 1, 1, 0, 2, 2, 3, 7 };
-#else
-const uint8 prio2ac[8] = { 0, 1, 1, 0, 2, 2, 3, 3 };
-#endif
-const uint8 prio2tid[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
-
-/** Queue overflow throttle. Return value: TRUE if throttle needs to be applied */
-static INLINE int
-dhd_flow_queue_throttle(flow_queue_t *queue)
-{
-	return DHD_FLOW_QUEUE_FULL(queue);
-}
-
-int BCMFASTPATH
-dhd_flow_queue_overflow(flow_queue_t *queue, void *pkt)
-{
-	return BCME_NORESOURCE;
-}
-
-/** Returns flow ring given a flowid */
-flow_ring_node_t *
-dhd_flow_ring_node(dhd_pub_t *dhdp, uint16 flowid)
-{
-	flow_ring_node_t * flow_ring_node;
-
-	ASSERT(dhdp != (dhd_pub_t*)NULL);
-	ASSERT(flowid < dhdp->num_flow_rings);
-
-	flow_ring_node = &(((flow_ring_node_t*)(dhdp->flow_ring_table))[flowid]);
-
-	ASSERT(flow_ring_node->flowid == flowid);
-	return flow_ring_node;
-}
-
-/** Returns 'backup' queue given a flowid */
-flow_queue_t *
-dhd_flow_queue(dhd_pub_t *dhdp, uint16 flowid)
-{
-	flow_ring_node_t * flow_ring_node;
-
-	flow_ring_node = dhd_flow_ring_node(dhdp, flowid);
-	return &flow_ring_node->queue;
-}
-
-/* Flow ring's queue management functions */
-
-/** Initialize a flow ring's queue, called on driver initialization. */
-void
-dhd_flow_queue_init(dhd_pub_t *dhdp, flow_queue_t *queue, int max)
-{
-	ASSERT((queue != NULL) && (max > 0));
-
-	dll_init(&queue->list);
-	queue->head = queue->tail = NULL;
-	queue->len = 0;
-
-	/* Set queue's threshold and queue's parent cummulative length counter */
-	ASSERT(max > 1);
-	DHD_FLOW_QUEUE_SET_MAX(queue, max);
-	DHD_FLOW_QUEUE_SET_THRESHOLD(queue, max);
-	DHD_FLOW_QUEUE_SET_CLEN(queue, &dhdp->cumm_ctr);
-
-	queue->failures = 0U;
-	queue->cb = &dhd_flow_queue_overflow;
-}
-
-/** Register an enqueue overflow callback handler */
-void
-dhd_flow_queue_register(flow_queue_t *queue, flow_queue_cb_t cb)
-{
-	ASSERT(queue != NULL);
-	queue->cb = cb;
-}
-
-/**
- * Enqueue an 802.3 packet at the back of a flow ring's queue. From there, it will travel later on
- * to the flow ring itself.
- */
-int BCMFASTPATH
-dhd_flow_queue_enqueue(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt)
-{
-	int ret = BCME_OK;
-
-	ASSERT(queue != NULL);
-
-	if (dhd_flow_queue_throttle(queue)) {
-		queue->failures++;
-		ret = (*queue->cb)(queue, pkt);
-		goto done;
-	}
-
-	if (queue->head) {
-		FLOW_QUEUE_PKT_SETNEXT(queue->tail, pkt);
-	} else {
-		queue->head = pkt;
-	}
-
-	FLOW_QUEUE_PKT_SETNEXT(pkt, NULL);
-
-	queue->tail = pkt; /* at tail */
-
-	queue->len++;
-	/* increment parent's cummulative length */
-	DHD_CUMM_CTR_INCR(DHD_FLOW_QUEUE_CLEN_PTR(queue));
-
-done:
-	return ret;
-}
-
-/** Dequeue an 802.3 packet from a flow ring's queue, from head (FIFO) */
-void * BCMFASTPATH
-dhd_flow_queue_dequeue(dhd_pub_t *dhdp, flow_queue_t *queue)
-{
-	void * pkt;
-
-	ASSERT(queue != NULL);
-
-	pkt = queue->head; /* from head */
-
-	if (pkt == NULL) {
-		ASSERT((queue->len == 0) && (queue->tail == NULL));
-		goto done;
-	}
-
-	queue->head = FLOW_QUEUE_PKT_NEXT(pkt);
-	if (queue->head == NULL)
-		queue->tail = NULL;
-
-	queue->len--;
-	/* decrement parent's cummulative length */
-	DHD_CUMM_CTR_DECR(DHD_FLOW_QUEUE_CLEN_PTR(queue));
-
-	FLOW_QUEUE_PKT_SETNEXT(pkt, NULL); /* dettach packet from queue */
-
-done:
-	return pkt;
-}
-
-/** Reinsert a dequeued 802.3 packet back at the head */
-void BCMFASTPATH
-dhd_flow_queue_reinsert(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt)
-{
-	if (queue->head == NULL) {
-		queue->tail = pkt;
-	}
-
-	FLOW_QUEUE_PKT_SETNEXT(pkt, queue->head);
-	queue->head = pkt;
-	queue->len++;
-	/* increment parent's cummulative length */
-	DHD_CUMM_CTR_INCR(DHD_FLOW_QUEUE_CLEN_PTR(queue));
-}
-
-/** Fetch the backup queue for a flowring, and assign flow control thresholds */
-void
-dhd_flow_ring_config_thresholds(dhd_pub_t *dhdp, uint16 flowid,
-                     int queue_budget, int cumm_threshold, void *cumm_ctr)
-{
-	flow_queue_t * queue;
-
-	ASSERT(dhdp != (dhd_pub_t*)NULL);
-	ASSERT(queue_budget > 1);
-	ASSERT(cumm_threshold > 1);
-	ASSERT(cumm_ctr != (void*)NULL);
-
-	queue = dhd_flow_queue(dhdp, flowid);
-
-	DHD_FLOW_QUEUE_SET_MAX(queue, queue_budget); /* Max queue length */
-
-	/* Set the queue's parent threshold and cummulative counter */
-	DHD_FLOW_QUEUE_SET_THRESHOLD(queue, cumm_threshold);
-	DHD_FLOW_QUEUE_SET_CLEN(queue, cumm_ctr);
-}
-
-/** Initializes data structures of multiple flow rings */
-int
-dhd_flow_rings_init(dhd_pub_t *dhdp, uint32 num_flow_rings)
-{
-	uint32 idx;
-	uint32 flow_ring_table_sz;
-	uint32 if_flow_lkup_sz = 0;
-	void * flowid_allocator;
-	flow_ring_table_t *flow_ring_table = NULL;
-	if_flow_lkup_t *if_flow_lkup = NULL;
-	void *lock = NULL;
-	void *list_lock = NULL;
-	unsigned long flags;
-
-	DHD_INFO(("%s\n", __FUNCTION__));
-
-	/* Construct a 16bit flowid allocator */
-	flowid_allocator = id16_map_init(dhdp->osh,
-	                       num_flow_rings - FLOW_RING_COMMON, FLOWID_RESERVED);
-	if (flowid_allocator == NULL) {
-		DHD_ERROR(("%s: flowid allocator init failure\n", __FUNCTION__));
-		return BCME_NOMEM;
-	}
-
-	/* Allocate a flow ring table, comprising of requested number of rings */
-	flow_ring_table_sz = (num_flow_rings * sizeof(flow_ring_node_t));
-	flow_ring_table = (flow_ring_table_t *)MALLOCZ(dhdp->osh, flow_ring_table_sz);
-	if (flow_ring_table == NULL) {
-		DHD_ERROR(("%s: flow ring table alloc failure\n", __FUNCTION__));
-		goto fail;
-	}
-
-	/* Initialize flow ring table state */
-	DHD_CUMM_CTR_INIT(&dhdp->cumm_ctr);
-	bzero((uchar *)flow_ring_table, flow_ring_table_sz);
-	for (idx = 0; idx < num_flow_rings; idx++) {
-		flow_ring_table[idx].status = FLOW_RING_STATUS_CLOSED;
-		flow_ring_table[idx].flowid = (uint16)idx;
-		flow_ring_table[idx].lock = dhd_os_spin_lock_init(dhdp->osh);
-		if (flow_ring_table[idx].lock == NULL) {
-			DHD_ERROR(("%s: Failed to init spinlock for queue!\n", __FUNCTION__));
-			goto fail;
-		}
-
-		dll_init(&flow_ring_table[idx].list);
-
-		/* Initialize the per flow ring backup queue */
-		dhd_flow_queue_init(dhdp, &flow_ring_table[idx].queue,
-		                    FLOW_RING_QUEUE_THRESHOLD);
-	}
-
-	/* Allocate per interface hash table (for fast lookup from interface to flow ring) */
-	if_flow_lkup_sz = sizeof(if_flow_lkup_t) * DHD_MAX_IFS;
-	if_flow_lkup = (if_flow_lkup_t *)DHD_OS_PREALLOC(dhdp,
-		DHD_PREALLOC_IF_FLOW_LKUP, if_flow_lkup_sz);
-	if (if_flow_lkup == NULL) {
-		DHD_ERROR(("%s: if flow lkup alloc failure\n", __FUNCTION__));
-		goto fail;
-	}
-
-	/* Initialize per interface hash table */
-	for (idx = 0; idx < DHD_MAX_IFS; idx++) {
-		int hash_ix;
-		if_flow_lkup[idx].status = 0;
-		if_flow_lkup[idx].role = 0;
-		for (hash_ix = 0; hash_ix < DHD_FLOWRING_HASH_SIZE; hash_ix++)
-			if_flow_lkup[idx].fl_hash[hash_ix] = NULL;
-	}
-
-	lock = dhd_os_spin_lock_init(dhdp->osh);
-	if (lock == NULL)
-		goto fail;
-
-	list_lock = dhd_os_spin_lock_init(dhdp->osh);
-	if (list_lock == NULL)
-		goto lock_fail;
-
-	dhdp->flow_prio_map_type = DHD_FLOW_PRIO_AC_MAP;
-	bcopy(prio2ac, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO);
-#ifdef DHD_LOSSLESS_ROAMING
-	dhdp->dequeue_prec_map = ALLPRIO;
-#endif
-	/* Now populate into dhd pub */
-	DHD_FLOWID_LOCK(lock, flags);
-	dhdp->num_flow_rings = num_flow_rings;
-	dhdp->flowid_allocator = (void *)flowid_allocator;
-	dhdp->flow_ring_table = (void *)flow_ring_table;
-	dhdp->if_flow_lkup = (void *)if_flow_lkup;
-	dhdp->flowid_lock = lock;
-	dhdp->flow_rings_inited = TRUE;
-	dhdp->flowring_list_lock = list_lock;
-	DHD_FLOWID_UNLOCK(lock, flags);
-
-	DHD_INFO(("%s done\n", __FUNCTION__));
-	return BCME_OK;
-
-lock_fail:
-	/* deinit the spinlock */
-	dhd_os_spin_lock_deinit(dhdp->osh, lock);
-
-fail:
-	/* Destruct the per interface flow lkup table */
-	if (if_flow_lkup != NULL) {
-		DHD_OS_PREFREE(dhdp, if_flow_lkup, if_flow_lkup_sz);
-	}
-	if (flow_ring_table != NULL) {
-		for (idx = 0; idx < num_flow_rings; idx++) {
-			if (flow_ring_table[idx].lock != NULL)
-				dhd_os_spin_lock_deinit(dhdp->osh, flow_ring_table[idx].lock);
-		}
-		MFREE(dhdp->osh, flow_ring_table, flow_ring_table_sz);
-	}
-	id16_map_fini(dhdp->osh, flowid_allocator);
-
-	return BCME_NOMEM;
-}
-
-/** Deinit Flow Ring specific data structures */
-void dhd_flow_rings_deinit(dhd_pub_t *dhdp)
-{
-	uint16 idx;
-	uint32 flow_ring_table_sz;
-	uint32 if_flow_lkup_sz;
-	flow_ring_table_t *flow_ring_table;
-	unsigned long flags;
-	void *lock;
-
-	DHD_INFO(("dhd_flow_rings_deinit\n"));
-
-	if (!(dhdp->flow_rings_inited)) {
-		DHD_ERROR(("dhd_flow_rings not initialized!\n"));
-		return;
-	}
-
-	if (dhdp->flow_ring_table != NULL) {
-
-		ASSERT(dhdp->num_flow_rings > 0);
-
-		DHD_FLOWID_LOCK(dhdp->flowid_lock, flags);
-		flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table;
-		dhdp->flow_ring_table = NULL;
-		DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-		for (idx = 0; idx < dhdp->num_flow_rings; idx++) {
-			if (flow_ring_table[idx].active) {
-				dhd_bus_clean_flow_ring(dhdp->bus, &flow_ring_table[idx]);
-			}
-			ASSERT(DHD_FLOW_QUEUE_EMPTY(&flow_ring_table[idx].queue));
-
-			/* Deinit flow ring queue locks before destroying flow ring table */
-			dhd_os_spin_lock_deinit(dhdp->osh, flow_ring_table[idx].lock);
-			flow_ring_table[idx].lock = NULL;
-
-		}
-
-		/* Destruct the flow ring table */
-		flow_ring_table_sz = dhdp->num_flow_rings * sizeof(flow_ring_table_t);
-		MFREE(dhdp->osh, flow_ring_table, flow_ring_table_sz);
-	}
-
-	DHD_FLOWID_LOCK(dhdp->flowid_lock, flags);
-
-	/* Destruct the per interface flow lkup table */
-	if (dhdp->if_flow_lkup != NULL) {
-		if_flow_lkup_sz = sizeof(if_flow_lkup_t) * DHD_MAX_IFS;
-		bzero((uchar *)dhdp->if_flow_lkup, if_flow_lkup_sz);
-		DHD_OS_PREFREE(dhdp, dhdp->if_flow_lkup, if_flow_lkup_sz);
-		dhdp->if_flow_lkup = NULL;
-	}
-
-	/* Destruct the flowid allocator */
-	if (dhdp->flowid_allocator != NULL)
-		dhdp->flowid_allocator = id16_map_fini(dhdp->osh, dhdp->flowid_allocator);
-
-	dhdp->num_flow_rings = 0U;
-	bzero(dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO);
-
-	lock = dhdp->flowid_lock;
-	dhdp->flowid_lock = NULL;
-
-	DHD_FLOWID_UNLOCK(lock, flags);
-	dhd_os_spin_lock_deinit(dhdp->osh, lock);
-
-	dhd_os_spin_lock_deinit(dhdp->osh, dhdp->flowring_list_lock);
-	dhdp->flowring_list_lock = NULL;
-
-	ASSERT(dhdp->if_flow_lkup == NULL);
-	ASSERT(dhdp->flowid_allocator == NULL);
-	ASSERT(dhdp->flow_ring_table == NULL);
-	dhdp->flow_rings_inited = FALSE;
-}
-
-/** Uses hash table to quickly map from ifindex to a flow ring 'role' (STA/AP) */
-uint8
-dhd_flow_rings_ifindex2role(dhd_pub_t *dhdp, uint8 ifindex)
-{
-	if_flow_lkup_t *if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup;
-	ASSERT(if_flow_lkup);
-	return if_flow_lkup[ifindex].role;
-}
-
-#ifdef WLTDLS
-bool is_tdls_destination(dhd_pub_t *dhdp, uint8 *da)
-{
-	tdls_peer_node_t *cur = dhdp->peer_tbl.node;
-	while (cur != NULL) {
-		if (!memcmp(da, cur->addr, ETHER_ADDR_LEN)) {
-			return TRUE;
-		}
-		cur = cur->next;
-	}
-	return FALSE;
-}
-#endif /* WLTDLS */
-
-/** Uses hash table to quickly map from ifindex+prio+da to a flow ring id */
-static INLINE uint16
-dhd_flowid_find(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, char *sa, char *da)
-{
-	int hash;
-	bool ismcast = FALSE;
-	flow_hash_info_t *cur;
-	if_flow_lkup_t *if_flow_lkup;
-	unsigned long flags;
-
-	DHD_FLOWID_LOCK(dhdp->flowid_lock, flags);
-	if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup;
-
-	ASSERT(if_flow_lkup);
-
-	if (if_flow_lkup[ifindex].role == WLC_E_IF_ROLE_STA) {
-#ifdef WLTDLS
-		if (dhdp->peer_tbl.tdls_peer_count && !(ETHER_ISMULTI(da)) &&
-			is_tdls_destination(dhdp, da)) {
-			hash = DHD_FLOWRING_HASHINDEX(da, prio);
-			cur = if_flow_lkup[ifindex].fl_hash[hash];
-			while (cur != NULL) {
-				if (!memcmp(cur->flow_info.da, da, ETHER_ADDR_LEN)) {
-					DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-					return cur->flowid;
-				}
-				cur = cur->next;
-			}
-			DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-			return FLOWID_INVALID;
-		}
-#endif /* WLTDLS */
-		cur = if_flow_lkup[ifindex].fl_hash[prio];
-		if (cur) {
-			DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-			return cur->flowid;
-		}
-	} else {
-
-		if (ETHER_ISMULTI(da)) {
-			ismcast = TRUE;
-			hash = 0;
-		} else {
-			hash = DHD_FLOWRING_HASHINDEX(da, prio);
-		}
-
-		cur = if_flow_lkup[ifindex].fl_hash[hash];
-
-		while (cur) {
-			if ((ismcast && ETHER_ISMULTI(cur->flow_info.da)) ||
-				(!memcmp(cur->flow_info.da, da, ETHER_ADDR_LEN) &&
-				(cur->flow_info.tid == prio))) {
-				DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-				return cur->flowid;
-			}
-			cur = cur->next;
-		}
-	}
-	DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-
-	DHD_INFO(("%s: cannot find flowid\n", __FUNCTION__));
-	return FLOWID_INVALID;
-} /* dhd_flowid_find */
-
-/** Create unique Flow ID, called when a flow ring is created. */
-static INLINE uint16
-dhd_flowid_alloc(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, char *sa, char *da)
-{
-	flow_hash_info_t *fl_hash_node, *cur;
-	if_flow_lkup_t *if_flow_lkup;
-	int hash;
-	uint16 flowid;
-	unsigned long flags;
-
-	fl_hash_node = (flow_hash_info_t *) MALLOC(dhdp->osh, sizeof(flow_hash_info_t));
-	memcpy(fl_hash_node->flow_info.da, da, sizeof(fl_hash_node->flow_info.da));
-
-	DHD_FLOWID_LOCK(dhdp->flowid_lock, flags);
-	ASSERT(dhdp->flowid_allocator != NULL);
-	flowid = id16_map_alloc(dhdp->flowid_allocator);
-	DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-
-	if (flowid == FLOWID_INVALID) {
-		MFREE(dhdp->osh, fl_hash_node,  sizeof(flow_hash_info_t));
-		DHD_ERROR(("%s: cannot get free flowid \n", __FUNCTION__));
-		return FLOWID_INVALID;
-	}
-
-	fl_hash_node->flowid = flowid;
-	fl_hash_node->flow_info.tid = prio;
-	fl_hash_node->flow_info.ifindex = ifindex;
-	fl_hash_node->next = NULL;
-
-	DHD_FLOWID_LOCK(dhdp->flowid_lock, flags);
-	if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup;
-
-	if (if_flow_lkup[ifindex].role == WLC_E_IF_ROLE_STA) {
-		/* For STA non TDLS dest we allocate entry based on prio only */
-#ifdef WLTDLS
-		if (dhdp->peer_tbl.tdls_peer_count &&
-			(is_tdls_destination(dhdp, da))) {
-			hash = DHD_FLOWRING_HASHINDEX(da, prio);
-			cur = if_flow_lkup[ifindex].fl_hash[hash];
-			if (cur) {
-				while (cur->next) {
-					cur = cur->next;
-				}
-				cur->next = fl_hash_node;
-			} else {
-				if_flow_lkup[ifindex].fl_hash[hash] = fl_hash_node;
-			}
-		} else
-#endif /* WLTDLS */
-			if_flow_lkup[ifindex].fl_hash[prio] = fl_hash_node;
-	} else {
-
-		/* For bcast/mcast assign first slot in in interface */
-		hash = ETHER_ISMULTI(da) ? 0 : DHD_FLOWRING_HASHINDEX(da, prio);
-		cur = if_flow_lkup[ifindex].fl_hash[hash];
-		if (cur) {
-			while (cur->next) {
-				cur = cur->next;
-			}
-			cur->next = fl_hash_node;
-		} else
-			if_flow_lkup[ifindex].fl_hash[hash] = fl_hash_node;
-	}
-	DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-
-	DHD_INFO(("%s: allocated flowid %d\n", __FUNCTION__, fl_hash_node->flowid));
-
-	return fl_hash_node->flowid;
-} /* dhd_flowid_alloc */
-
-/** Get flow ring ID, if not present try to create one */
-static INLINE int
-dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex,
-                  uint8 prio, char *sa, char *da, uint16 *flowid)
-{
-	uint16 id;
-	flow_ring_node_t *flow_ring_node;
-	flow_ring_table_t *flow_ring_table;
-	unsigned long flags;
-	int ret;
-
-	DHD_INFO(("%s\n", __FUNCTION__));
-
-	if (!dhdp->flow_ring_table) {
-		return BCME_ERROR;
-	}
-
-	flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table;
-
-	id = dhd_flowid_find(dhdp, ifindex, prio, sa, da);
-
-	if (id == FLOWID_INVALID) {
-
-		if_flow_lkup_t *if_flow_lkup;
-		if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup;
-
-		if (!if_flow_lkup[ifindex].status)
-			return BCME_ERROR;
-
-
-		id = dhd_flowid_alloc(dhdp, ifindex, prio, sa, da);
-		if (id == FLOWID_INVALID) {
-			DHD_ERROR(("%s: alloc flowid ifindex %u status %u\n",
-			           __FUNCTION__, ifindex, if_flow_lkup[ifindex].status));
-			return BCME_ERROR;
-		}
-
-		/* register this flowid in dhd_pub */
-		dhd_add_flowid(dhdp, ifindex, prio, da, id);
-
-		ASSERT(id < dhdp->num_flow_rings);
-
-		flow_ring_node = (flow_ring_node_t *) &flow_ring_table[id];
-
-		DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-
-		/* Init Flow info */
-		memcpy(flow_ring_node->flow_info.sa, sa, sizeof(flow_ring_node->flow_info.sa));
-		memcpy(flow_ring_node->flow_info.da, da, sizeof(flow_ring_node->flow_info.da));
-		flow_ring_node->flow_info.tid = prio;
-		flow_ring_node->flow_info.ifindex = ifindex;
-		flow_ring_node->active = TRUE;
-		flow_ring_node->status = FLOW_RING_STATUS_PENDING;
-		DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-
-		/* Create and inform device about the new flow */
-		if (dhd_bus_flow_ring_create_request(dhdp->bus, (void *)flow_ring_node)
-				!= BCME_OK) {
-			DHD_ERROR(("%s: create error %d\n", __FUNCTION__, id));
-			return BCME_ERROR;
-		}
-
-		*flowid = id;
-		return BCME_OK;
-	} else {
-		/* if the Flow id was found in the hash */
-		ASSERT(id < dhdp->num_flow_rings);
-
-		flow_ring_node = (flow_ring_node_t *) &flow_ring_table[id];
-		DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-
-		/*
-		 * If the flow_ring_node is in Open State or Status pending state then
-		 * we can return the Flow id to the caller.If the flow_ring_node is in
-		 * FLOW_RING_STATUS_PENDING this means the creation is in progress and
-		 * hence the packets should be queued.
-		 *
-		 * If the flow_ring_node is in FLOW_RING_STATUS_DELETE_PENDING Or
-		 * FLOW_RING_STATUS_CLOSED, then we should return Error.
-		 * Note that if the flowing is being deleted we would mark it as
-		 * FLOW_RING_STATUS_DELETE_PENDING.  Now before Dongle could respond and
-		 * before we mark it as FLOW_RING_STATUS_CLOSED we could get tx packets.
-		 * We should drop the packets in that case.
-		 * The decission to return OK should NOT be based on 'active' variable, beause
-		 * active is made TRUE when a flow_ring_node gets allocated and is made
-		 * FALSE when the flow ring gets removed and does not reflect the True state
-		 * of the Flow ring.
-		 */
-		if (flow_ring_node->status == FLOW_RING_STATUS_OPEN ||
-			flow_ring_node->status == FLOW_RING_STATUS_PENDING) {
-			*flowid = id;
-			ret = BCME_OK;
-		} else {
-			*flowid = FLOWID_INVALID;
-			ret = BCME_ERROR;
-		}
-
-		DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-		return ret;
-
-	} /* Flow Id found in the hash */
-} /* dhd_flowid_lookup */
-
-/**
- * Assign existing or newly created flowid to an 802.3 packet. This flowid is later on used to
- * select the flowring to send the packet to the dongle.
- */
-int BCMFASTPATH
-dhd_flowid_update(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, void *pktbuf)
-{
-	uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf);
-	struct ether_header *eh = (struct ether_header *)pktdata;
-	uint16 flowid;
-
-	ASSERT(ifindex < DHD_MAX_IFS);
-
-	if (ifindex >= DHD_MAX_IFS) {
-		return BCME_BADARG;
-	}
-
-	if (!dhdp->flowid_allocator) {
-		DHD_ERROR(("%s: Flow ring not intited yet  \n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	if (dhd_flowid_lookup(dhdp, ifindex, prio, eh->ether_shost, eh->ether_dhost,
-		&flowid) != BCME_OK) {
-		return BCME_ERROR;
-	}
-
-	DHD_INFO(("%s: prio %d flowid %d\n", __FUNCTION__, prio, flowid));
-
-	/* Tag the packet with flowid */
-	DHD_PKT_SET_FLOWID(pktbuf, flowid);
-	return BCME_OK;
-}
-
-void
-dhd_flowid_free(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid)
-{
-	int hashix;
-	bool found = FALSE;
-	flow_hash_info_t *cur, *prev;
-	if_flow_lkup_t *if_flow_lkup;
-	unsigned long flags;
-
-	DHD_FLOWID_LOCK(dhdp->flowid_lock, flags);
-	if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup;
-
-	for (hashix = 0; hashix < DHD_FLOWRING_HASH_SIZE; hashix++) {
-
-		cur = if_flow_lkup[ifindex].fl_hash[hashix];
-
-		if (cur) {
-			if (cur->flowid == flowid) {
-				found = TRUE;
-			}
-
-			prev = NULL;
-			while (!found && cur) {
-				if (cur->flowid == flowid) {
-					found = TRUE;
-					break;
-				}
-				prev = cur;
-				cur = cur->next;
-			}
-			if (found) {
-				if (!prev) {
-					if_flow_lkup[ifindex].fl_hash[hashix] = cur->next;
-				} else {
-					prev->next = cur->next;
-				}
-
-				/* deregister flowid from dhd_pub. */
-				dhd_del_flowid(dhdp, ifindex, flowid);
-
-				id16_map_free(dhdp->flowid_allocator, flowid);
-				DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-				MFREE(dhdp->osh, cur, sizeof(flow_hash_info_t));
-
-				return;
-			}
-		}
-	}
-
-	DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-	DHD_ERROR(("%s: could not free flow ring hash entry flowid %d\n",
-	           __FUNCTION__, flowid));
-} /* dhd_flowid_free */
-
-/**
- * Delete all Flow rings associated with the given interface. Is called when e.g. the dongle
- * indicates that a wireless link has gone down.
- */
-void
-dhd_flow_rings_delete(dhd_pub_t *dhdp, uint8 ifindex)
-{
-	uint32 id;
-	flow_ring_table_t *flow_ring_table;
-
-	DHD_INFO(("%s: ifindex %u\n", __FUNCTION__, ifindex));
-
-	ASSERT(ifindex < DHD_MAX_IFS);
-	if (ifindex >= DHD_MAX_IFS)
-		return;
-
-	if (!dhdp->flow_ring_table)
-		return;
-
-	flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table;
-	for (id = 0; id < dhdp->num_flow_rings; id++) {
-		if (flow_ring_table[id].active &&
-		    (flow_ring_table[id].flow_info.ifindex == ifindex)) {
-			dhd_bus_flow_ring_delete_request(dhdp->bus,
-			                                 (void *) &flow_ring_table[id]);
-		}
-	}
-}
-
-/** Delete flow ring(s) for given peer address. Related to AP/AWDL/TDLS functionality. */
-void
-dhd_flow_rings_delete_for_peer(dhd_pub_t *dhdp, uint8 ifindex, char *addr)
-{
-	uint32 id;
-	flow_ring_table_t *flow_ring_table;
-
-	DHD_ERROR(("%s: ifindex %u\n", __FUNCTION__, ifindex));
-
-	ASSERT(ifindex < DHD_MAX_IFS);
-	if (ifindex >= DHD_MAX_IFS)
-		return;
-
-	if (!dhdp->flow_ring_table)
-		return;
-
-	flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table;
-	for (id = 0; id < dhdp->num_flow_rings; id++) {
-		if (flow_ring_table[id].active &&
-			(flow_ring_table[id].flow_info.ifindex == ifindex) &&
-			(!memcmp(flow_ring_table[id].flow_info.da, addr, ETHER_ADDR_LEN)) &&
-			(flow_ring_table[id].status != FLOW_RING_STATUS_DELETE_PENDING)) {
-			DHD_INFO(("%s: deleting flowid %d\n",
-				__FUNCTION__, flow_ring_table[id].flowid));
-			dhd_bus_flow_ring_delete_request(dhdp->bus,
-				(void *) &flow_ring_table[id]);
-		}
-	}
-}
-
-/** Handles interface ADD, CHANGE, DEL indications from the dongle */
-void
-dhd_update_interface_flow_info(dhd_pub_t *dhdp, uint8 ifindex,
-                               uint8 op, uint8 role)
-{
-	if_flow_lkup_t *if_flow_lkup;
-	unsigned long flags;
-
-	ASSERT(ifindex < DHD_MAX_IFS);
-	if (ifindex >= DHD_MAX_IFS)
-		return;
-
-	DHD_INFO(("%s: ifindex %u op %u role is %u \n",
-	          __FUNCTION__, ifindex, op, role));
-	if (!dhdp->flowid_allocator) {
-		DHD_ERROR(("%s: Flow ring not intited yet  \n", __FUNCTION__));
-		return;
-	}
-
-	DHD_FLOWID_LOCK(dhdp->flowid_lock, flags);
-	if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup;
-
-	if (op == WLC_E_IF_ADD || op == WLC_E_IF_CHANGE) {
-
-		if_flow_lkup[ifindex].role = role;
-
-		if (role != WLC_E_IF_ROLE_STA) {
-			if_flow_lkup[ifindex].status = TRUE;
-			DHD_INFO(("%s: Mcast Flow ring for ifindex %d role is %d \n",
-			          __FUNCTION__, ifindex, role));
-			/* Create Mcast Flow */
-		}
-	} else	if (op == WLC_E_IF_DEL) {
-		if_flow_lkup[ifindex].status = FALSE;
-		DHD_INFO(("%s: cleanup all Flow rings for ifindex %d role is %d \n",
-		          __FUNCTION__, ifindex, role));
-	}
-	DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-}
-
-/** Handles a STA 'link' indication from the dongle */
-int
-dhd_update_interface_link_status(dhd_pub_t *dhdp, uint8 ifindex, uint8 status)
-{
-	if_flow_lkup_t *if_flow_lkup;
-	unsigned long flags;
-
-	ASSERT(ifindex < DHD_MAX_IFS);
-	if (ifindex >= DHD_MAX_IFS)
-		return BCME_BADARG;
-
-	DHD_INFO(("%s: ifindex %d status %d\n", __FUNCTION__, ifindex, status));
-
-	DHD_FLOWID_LOCK(dhdp->flowid_lock, flags);
-	if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup;
-
-	if (if_flow_lkup[ifindex].role == WLC_E_IF_ROLE_STA) {
-		if (status)
-			if_flow_lkup[ifindex].status = TRUE;
-		else
-			if_flow_lkup[ifindex].status = FALSE;
-	}
-	DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags);
-
-	return BCME_OK;
-}
-
-/** Update flow priority mapping, called on IOVAR */
-int dhd_update_flow_prio_map(dhd_pub_t *dhdp, uint8 map)
-{
-	uint16 flowid;
-	flow_ring_node_t *flow_ring_node;
-
-	if (map > DHD_FLOW_PRIO_LLR_MAP)
-		return BCME_BADOPTION;
-
-	/* Check if we need to change prio map */
-	if (map == dhdp->flow_prio_map_type)
-		return BCME_OK;
-
-	/* If any ring is active we cannot change priority mapping for flow rings */
-	for (flowid = 0; flowid < dhdp->num_flow_rings; flowid++) {
-		flow_ring_node = DHD_FLOW_RING(dhdp, flowid);
-		if (flow_ring_node->active)
-			return BCME_EPERM;
-	}
-
-	/* Inform firmware about new mapping type */
-	if (BCME_OK != dhd_flow_prio_map(dhdp, &map, TRUE))
-		return BCME_ERROR;
-
-	/* update internal structures */
-	dhdp->flow_prio_map_type = map;
-	if (dhdp->flow_prio_map_type == DHD_FLOW_PRIO_TID_MAP)
-		bcopy(prio2tid, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO);
-	else
-		bcopy(prio2ac, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO);
-
-	return BCME_OK;
-}
-
-/** Inform firmware on updated flow priority mapping, called on IOVAR */
-int dhd_flow_prio_map(dhd_pub_t *dhd, uint8 *map, bool set)
-{
-	uint8 iovbuf[24];
-	if (!set) {
-		bcm_mkiovar("bus:fl_prio_map", NULL, 0, (char*)iovbuf, sizeof(iovbuf));
-		if (dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0) < 0) {
-			DHD_ERROR(("%s: failed to get fl_prio_map\n", __FUNCTION__));
-			return BCME_ERROR;
-		}
-		*map = iovbuf[0];
-		return BCME_OK;
-	}
-	bcm_mkiovar("bus:fl_prio_map", (char *)map, 4, (char*)iovbuf, sizeof(iovbuf));
-	if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) {
-		DHD_ERROR(("%s: failed to set fl_prio_map \n",
-			__FUNCTION__));
-		return BCME_ERROR;
-	}
-	return BCME_OK;
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd_flowring.h b/drivers/net/wireless/bcmdhd/dhd_flowring.h
deleted file mode 100644
index 7c36de5..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_flowring.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * @file Header file describing the flow rings DHD interfaces.
- *
- * Flow rings are transmit traffic (=propagating towards antenna) related entities.
- *
- * Provides type definitions and function prototypes used to create, delete and manage flow rings at
- * high level.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_flowring.h 591285 2015-10-07 11:56:29Z $
- */
-
-
-/****************
- * Common types *
- */
-
-#ifndef _dhd_flowrings_h_
-#define _dhd_flowrings_h_
-
-/* Max pkts held in a flow ring's backup queue */
-#define FLOW_RING_QUEUE_THRESHOLD       (2048)
-
-/* Number of H2D common rings */
-#define FLOW_RING_COMMON                BCMPCIE_H2D_COMMON_MSGRINGS
-
-#define FLOWID_INVALID                  (ID16_INVALID)
-#define FLOWID_RESERVED                 (FLOW_RING_COMMON)
-
-#define FLOW_RING_STATUS_OPEN           0
-#define FLOW_RING_STATUS_PENDING        1
-#define FLOW_RING_STATUS_CLOSED         2
-#define FLOW_RING_STATUS_DELETE_PENDING 3
-#define FLOW_RING_STATUS_FLUSH_PENDING  4
-#define FLOW_RING_STATUS_STA_FREEING    5
-
-#define DHD_FLOWRING_RX_BUFPOST_PKTSZ	2048
-
-#define DHD_FLOW_PRIO_AC_MAP		0
-#define DHD_FLOW_PRIO_TID_MAP		1
-#define DHD_FLOW_PRIO_LLR_MAP		2
-
-/* Pkttag not compatible with PROP_TXSTATUS or WLFC */
-typedef struct dhd_pkttag_fr {
-	uint16  flowid;
-	uint16  ifid;
-	int     dataoff;
-	dmaaddr_t physaddr;
-	uint32 pa_len;
-
-} dhd_pkttag_fr_t;
-
-#define DHD_PKTTAG_SET_FLOWID(tag, flow)    ((tag)->flowid = (uint16)(flow))
-#define DHD_PKTTAG_SET_IFID(tag, idx)       ((tag)->ifid = (uint16)(idx))
-#define DHD_PKTTAG_SET_DATAOFF(tag, offset) ((tag)->dataoff = (int)(offset))
-#define DHD_PKTTAG_SET_PA(tag, pa)          ((tag)->physaddr = (pa))
-#define DHD_PKTTAG_SET_PA_LEN(tag, palen)   ((tag)->pa_len = (palen))
-
-#define DHD_PKTTAG_FLOWID(tag)              ((tag)->flowid)
-#define DHD_PKTTAG_IFID(tag)                ((tag)->ifid)
-#define DHD_PKTTAG_DATAOFF(tag)             ((tag)->dataoff)
-#define DHD_PKTTAG_PA(tag)                  ((tag)->physaddr)
-#define DHD_PKTTAG_PA_LEN(tag)              ((tag)->pa_len)
-
-/* Hashing a MacAddress for lkup into a per interface flow hash table */
-#define DHD_FLOWRING_HASH_SIZE    256
-#define	DHD_FLOWRING_HASHINDEX(ea, prio) \
-	       ((((uint8 *)(ea))[3] ^ ((uint8 *)(ea))[4] ^ ((uint8 *)(ea))[5] ^ ((uint8)(prio))) \
-		% DHD_FLOWRING_HASH_SIZE)
-
-#define DHD_IF_ROLE(pub, idx)		(((if_flow_lkup_t *)(pub)->if_flow_lkup)[idx].role)
-#define DHD_IF_ROLE_AP(pub, idx)	(DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_AP)
-#define DHD_IF_ROLE_STA(pub, idx)	(DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_STA)
-#define DHD_IF_ROLE_P2PGO(pub, idx)	(DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_P2P_GO)
-#define DHD_FLOW_RING(dhdp, flowid) \
-	(flow_ring_node_t *)&(((flow_ring_node_t *)((dhdp)->flow_ring_table))[flowid])
-
-struct flow_queue;
-
-/* Flow Ring Queue Enqueue overflow callback */
-typedef int (*flow_queue_cb_t)(struct flow_queue * queue, void * pkt);
-
-/**
- * Each flow ring has an associated (tx flow controlled) queue. 802.3 packets are transferred
- * between queue and ring. A packet from the host stack is first added to the queue, and in a later
- * stage transferred to the flow ring. Packets in the queue are dhd owned, whereas packets in the
- * flow ring are device owned.
- */
-typedef struct flow_queue {
-	dll_t  list;                /* manage a flowring queue in a double linked list */
-	void * head;                /* first packet in the queue */
-	void * tail;                /* last packet in the queue */
-	uint16 len;                 /* number of packets in the queue */
-	uint16 max;                 /* maximum or min budget (used in cumm) */
-	uint32 threshold;           /* parent's cummulative length threshold */
-	void * clen_ptr;            /* parent's cummulative length counter */
-	uint32 failures;            /* enqueue failures due to queue overflow */
-	flow_queue_cb_t cb;         /* callback invoked on threshold crossing */
-} flow_queue_t;
-
-#define DHD_FLOW_QUEUE_LEN(queue)       ((int)(queue)->len)
-#define DHD_FLOW_QUEUE_MAX(queue)       ((int)(queue)->max)
-#define DHD_FLOW_QUEUE_THRESHOLD(queue) ((int)(queue)->threshold)
-#define DHD_FLOW_QUEUE_EMPTY(queue)     ((queue)->len == 0)
-#define DHD_FLOW_QUEUE_FAILURES(queue)  ((queue)->failures)
-
-#define DHD_FLOW_QUEUE_AVAIL(queue)     ((int)((queue)->max - (queue)->len))
-#define DHD_FLOW_QUEUE_FULL(queue)      ((queue)->len >= (queue)->max)
-
-#define DHD_FLOW_QUEUE_OVFL(queue, budget)  \
-	(((queue)->len) > budget)
-
-#define DHD_FLOW_QUEUE_SET_MAX(queue, budget) \
-	((queue)->max) = ((budget) - 1)
-
-/* Queue's cummulative threshold. */
-#define DHD_FLOW_QUEUE_SET_THRESHOLD(queue, cumm_threshold) \
-	((queue)->threshold) = ((cumm_threshold) - 1)
-
-/* Queue's cummulative length object accessor. */
-#define DHD_FLOW_QUEUE_CLEN_PTR(queue)  ((queue)->clen_ptr)
-
-/* Set a queue's cumm_len point to a parent's cumm_ctr_t cummulative length */
-#define DHD_FLOW_QUEUE_SET_CLEN(queue, parent_clen_ptr)  \
-	((queue)->clen_ptr) = (void *)(parent_clen_ptr)
-
-/*  see wlfc_proto.h for tx status details */
-#define DHD_FLOWRING_MAXSTATUS_MSGS	5
-#define DHD_FLOWRING_TXSTATUS_CNT_UPDATE(bus, flowid, txstatus)
-/** each flow ring is dedicated to a tid/sa/da combination */
-typedef struct flow_info {
-	uint8		tid;
-	uint8		ifindex;
-	char		sa[ETHER_ADDR_LEN];
-	char		da[ETHER_ADDR_LEN];
-} flow_info_t;
-
-/** a flow ring is used for outbound (towards antenna) 802.3 packets */
-typedef struct flow_ring_node {
-	dll_t		list;  /* manage a constructed flowring in a dll, must be at first place */
-	flow_queue_t	queue; /* queues packets before they enter the flow ring, flow control */
-	bool		active;
-	uint8		status;
-	/*
-	 * flowid: unique ID of a flow ring, which can either be unicast or broadcast/multicast. For
-	 * unicast flow rings, the flow id accelerates ARM 802.3->802.11 header translation.
-	 */
-	uint16		flowid;
-	flow_info_t	flow_info;
-	void		*prot_info;
-	void		*lock; /* lock for flowring access protection */
-} flow_ring_node_t;
-
-typedef flow_ring_node_t flow_ring_table_t;
-
-typedef struct flow_hash_info {
-	uint16			flowid;
-	flow_info_t		flow_info;
-	struct flow_hash_info	*next;
-} flow_hash_info_t;
-
-typedef struct if_flow_lkup {
-	bool		status;
-	uint8		role; /* Interface role: STA/AP */
-	flow_hash_info_t *fl_hash[DHD_FLOWRING_HASH_SIZE]; /* Lkup Hash table */
-} if_flow_lkup_t;
-
-static INLINE flow_ring_node_t *
-dhd_constlist_to_flowring(dll_t *item)
-{
-	return ((flow_ring_node_t *)item);
-}
-
-/* Exported API */
-
-/* Flow ring's queue management functions */
-extern flow_ring_node_t * dhd_flow_ring_node(dhd_pub_t *dhdp, uint16 flowid);
-extern flow_queue_t * dhd_flow_queue(dhd_pub_t *dhdp, uint16 flowid);
-
-extern void dhd_flow_queue_init(dhd_pub_t *dhdp, flow_queue_t *queue, int max);
-extern void dhd_flow_queue_register(flow_queue_t *queue, flow_queue_cb_t cb);
-extern int  dhd_flow_queue_enqueue(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt);
-extern void * dhd_flow_queue_dequeue(dhd_pub_t *dhdp, flow_queue_t *queue);
-extern void dhd_flow_queue_reinsert(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt);
-
-extern void dhd_flow_ring_config_thresholds(dhd_pub_t *dhdp, uint16 flowid,
-                          int queue_budget, int cumm_threshold, void *cumm_ctr);
-extern int  dhd_flow_rings_init(dhd_pub_t *dhdp, uint32 num_flow_rings);
-
-extern void dhd_flow_rings_deinit(dhd_pub_t *dhdp);
-
-extern int dhd_flowid_update(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio,
-                void *pktbuf);
-
-extern void dhd_flowid_free(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid);
-
-extern void dhd_flow_rings_delete(dhd_pub_t *dhdp, uint8 ifindex);
-
-extern void dhd_flow_rings_delete_for_peer(dhd_pub_t *dhdp, uint8 ifindex,
-                char *addr);
-
-/* Handle Interface ADD, DEL operations */
-extern void dhd_update_interface_flow_info(dhd_pub_t *dhdp, uint8 ifindex,
-                uint8 op, uint8 role);
-
-/* Handle a STA interface link status update */
-extern int dhd_update_interface_link_status(dhd_pub_t *dhdp, uint8 ifindex,
-                uint8 status);
-extern int dhd_flow_prio_map(dhd_pub_t *dhd, uint8 *map, bool set);
-extern int dhd_update_flow_prio_map(dhd_pub_t *dhdp, uint8 map);
-
-extern uint8 dhd_flow_rings_ifindex2role(dhd_pub_t *dhdp, uint8 ifindex);
-#endif /* _dhd_flowrings_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_ip.c b/drivers/net/wireless/bcmdhd/dhd_ip.c
deleted file mode 100644
index 971e4ca..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_ip.c
+++ /dev/null
@@ -1,1275 +0,0 @@
-/*
- * IP Packet Parser Module.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_ip.c 569132 2015-07-07 09:09:33Z $
- */
-#include <typedefs.h>
-#include <osl.h>
-
-#include <proto/ethernet.h>
-#include <proto/vlan.h>
-#include <proto/802.3.h>
-#include <proto/bcmip.h>
-#include <bcmendian.h>
-
-#include <dhd_dbg.h>
-
-#include <dhd_ip.h>
-
-#ifdef DHDTCPACK_SUPPRESS
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <proto/bcmtcp.h>
-#endif /* DHDTCPACK_SUPPRESS */
-
-/* special values */
-/* 802.3 llc/snap header */
-static const uint8 llc_snap_hdr[SNAP_HDR_LEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
-
-pkt_frag_t pkt_frag_info(osl_t *osh, void *p)
-{
-	uint8 *frame;
-	int length;
-	uint8 *pt;			/* Pointer to type field */
-	uint16 ethertype;
-	struct ipv4_hdr *iph;		/* IP frame pointer */
-	int ipl;			/* IP frame length */
-	uint16 iph_frag;
-
-	ASSERT(osh && p);
-
-	frame = PKTDATA(osh, p);
-	length = PKTLEN(osh, p);
-
-	/* Process Ethernet II or SNAP-encapsulated 802.3 frames */
-	if (length < ETHER_HDR_LEN) {
-		DHD_INFO(("%s: short eth frame (%d)\n", __FUNCTION__, length));
-		return DHD_PKT_FRAG_NONE;
-	} else if (ntoh16(*(uint16 *)(frame + ETHER_TYPE_OFFSET)) >= ETHER_TYPE_MIN) {
-		/* Frame is Ethernet II */
-		pt = frame + ETHER_TYPE_OFFSET;
-	} else if (length >= ETHER_HDR_LEN + SNAP_HDR_LEN + ETHER_TYPE_LEN &&
-	           !bcmp(llc_snap_hdr, frame + ETHER_HDR_LEN, SNAP_HDR_LEN)) {
-		pt = frame + ETHER_HDR_LEN + SNAP_HDR_LEN;
-	} else {
-		DHD_INFO(("%s: non-SNAP 802.3 frame\n", __FUNCTION__));
-		return DHD_PKT_FRAG_NONE;
-	}
-
-	ethertype = ntoh16(*(uint16 *)pt);
-
-	/* Skip VLAN tag, if any */
-	if (ethertype == ETHER_TYPE_8021Q) {
-		pt += VLAN_TAG_LEN;
-
-		if (pt + ETHER_TYPE_LEN > frame + length) {
-			DHD_INFO(("%s: short VLAN frame (%d)\n", __FUNCTION__, length));
-			return DHD_PKT_FRAG_NONE;
-		}
-
-		ethertype = ntoh16(*(uint16 *)pt);
-	}
-
-	if (ethertype != ETHER_TYPE_IP) {
-		DHD_INFO(("%s: non-IP frame (ethertype 0x%x, length %d)\n",
-			__FUNCTION__, ethertype, length));
-		return DHD_PKT_FRAG_NONE;
-	}
-
-	iph = (struct ipv4_hdr *)(pt + ETHER_TYPE_LEN);
-	ipl = (uint)(length - (pt + ETHER_TYPE_LEN - frame));
-
-	/* We support IPv4 only */
-	if ((ipl < IPV4_OPTIONS_OFFSET) || (IP_VER(iph) != IP_VER_4)) {
-		DHD_INFO(("%s: short frame (%d) or non-IPv4\n", __FUNCTION__, ipl));
-		return DHD_PKT_FRAG_NONE;
-	}
-
-	iph_frag = ntoh16(iph->frag);
-
-	if (iph_frag & IPV4_FRAG_DONT) {
-		return DHD_PKT_FRAG_NONE;
-	} else if ((iph_frag & IPV4_FRAG_MORE) == 0) {
-		return DHD_PKT_FRAG_LAST;
-	} else {
-		return (iph_frag & IPV4_FRAG_OFFSET_MASK)? DHD_PKT_FRAG_CONT : DHD_PKT_FRAG_FIRST;
-	}
-}
-
-#ifdef DHDTCPACK_SUPPRESS
-
-typedef struct {
-	void *pkt_in_q;		/* TCP ACK packet that is already in txq or DelayQ */
-	void *pkt_ether_hdr;	/* Ethernet header pointer of pkt_in_q */
-	int ifidx;
-	uint8 supp_cnt;
-	dhd_pub_t *dhdp;
-	struct timer_list timer;
-} tcpack_info_t;
-
-typedef struct _tdata_psh_info_t {
-	uint32 end_seq;			/* end seq# of a received TCP PSH DATA pkt */
-	struct _tdata_psh_info_t *next;	/* next pointer of the link chain */
-} tdata_psh_info_t;
-
-typedef struct {
-	struct {
-		uint8 src[IPV4_ADDR_LEN];	/* SRC ip addrs of this TCP stream */
-		uint8 dst[IPV4_ADDR_LEN];	/* DST ip addrs of this TCP stream */
-	} ip_addr;
-	struct {
-		uint8 src[TCP_PORT_LEN];	/* SRC tcp ports of this TCP stream */
-		uint8 dst[TCP_PORT_LEN];	/* DST tcp ports of this TCP stream */
-	} tcp_port;
-	tdata_psh_info_t *tdata_psh_info_head;	/* Head of received TCP PSH DATA chain */
-	tdata_psh_info_t *tdata_psh_info_tail;	/* Tail of received TCP PSH DATA chain */
-	uint32 last_used_time;	/* The last time this tcpdata_info was used(in ms) */
-} tcpdata_info_t;
-
-/* TCPACK SUPPRESS module */
-typedef struct {
-	int tcpack_info_cnt;
-	tcpack_info_t tcpack_info_tbl[TCPACK_INFO_MAXNUM];	/* Info of TCP ACK to send */
-	int tcpdata_info_cnt;
-	tcpdata_info_t tcpdata_info_tbl[TCPDATA_INFO_MAXNUM];	/* Info of received TCP DATA */
-	tdata_psh_info_t *tdata_psh_info_pool;	/* Pointer to tdata_psh_info elements pool */
-	tdata_psh_info_t *tdata_psh_info_free;	/* free tdata_psh_info elements chain in pool */
-#ifdef DHDTCPACK_SUP_DBG
-	int psh_info_enq_num;	/* Number of free TCP PSH DATA info elements in pool */
-#endif /* DHDTCPACK_SUP_DBG */
-} tcpack_sup_module_t;
-
-#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
-counter_tbl_t tack_tbl = {"tcpACK", 0, 1000, 10, {0, }, 1};
-#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
-
-static void
-_tdata_psh_info_pool_enq(tcpack_sup_module_t *tcpack_sup_mod,
-	tdata_psh_info_t *tdata_psh_info)
-{
-	if ((tcpack_sup_mod == NULL) || (tdata_psh_info == NULL)) {
-		DHD_ERROR(("%s %d: ERROR %p %p\n", __FUNCTION__, __LINE__,
-			tcpack_sup_mod, tdata_psh_info));
-		return;
-	}
-
-	ASSERT(tdata_psh_info->next == NULL);
-	tdata_psh_info->next = tcpack_sup_mod->tdata_psh_info_free;
-	tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info;
-#ifdef DHDTCPACK_SUP_DBG
-	tcpack_sup_mod->psh_info_enq_num++;
-#endif
-}
-
-static tdata_psh_info_t*
-_tdata_psh_info_pool_deq(tcpack_sup_module_t *tcpack_sup_mod)
-{
-	tdata_psh_info_t *tdata_psh_info = NULL;
-
-	if (tcpack_sup_mod == NULL) {
-		DHD_ERROR(("%s %d: ERROR %p\n", __FUNCTION__, __LINE__,
-			tcpack_sup_mod));
-		return NULL;
-	}
-
-	tdata_psh_info = tcpack_sup_mod->tdata_psh_info_free;
-	if (tdata_psh_info == NULL)
-		DHD_ERROR(("%s %d: Out of tdata_disc_grp\n", __FUNCTION__, __LINE__));
-	else {
-		tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info->next;
-		tdata_psh_info->next = NULL;
-#ifdef DHDTCPACK_SUP_DBG
-		tcpack_sup_mod->psh_info_enq_num--;
-#endif /* DHDTCPACK_SUP_DBG */
-	}
-
-	return tdata_psh_info;
-}
-
-#ifdef BCMSDIO
-static int _tdata_psh_info_pool_init(dhd_pub_t *dhdp,
-	tcpack_sup_module_t *tcpack_sup_mod)
-{
-	tdata_psh_info_t *tdata_psh_info_pool = NULL;
-	uint i;
-
-	DHD_TRACE(("%s %d: Enter\n", __FUNCTION__, __LINE__));
-
-	if (tcpack_sup_mod == NULL)
-		return BCME_ERROR;
-
-	ASSERT(tcpack_sup_mod->tdata_psh_info_pool == NULL);
-	ASSERT(tcpack_sup_mod->tdata_psh_info_free == NULL);
-
-	tdata_psh_info_pool =
-		MALLOC(dhdp->osh, sizeof(tdata_psh_info_t) * TCPDATA_PSH_INFO_MAXNUM);
-
-	if (tdata_psh_info_pool == NULL)
-		return BCME_NOMEM;
-	bzero(tdata_psh_info_pool, sizeof(tdata_psh_info_t) * TCPDATA_PSH_INFO_MAXNUM);
-#ifdef DHDTCPACK_SUP_DBG
-	tcpack_sup_mod->psh_info_enq_num = 0;
-#endif /* DHDTCPACK_SUP_DBG */
-
-	/* Enqueue newly allocated tcpdata psh info elements to the pool */
-	for (i = 0; i < TCPDATA_PSH_INFO_MAXNUM; i++)
-		_tdata_psh_info_pool_enq(tcpack_sup_mod, &tdata_psh_info_pool[i]);
-
-	ASSERT(tcpack_sup_mod->tdata_psh_info_free != NULL);
-	tcpack_sup_mod->tdata_psh_info_pool = tdata_psh_info_pool;
-
-	return BCME_OK;
-}
-
-static void _tdata_psh_info_pool_deinit(dhd_pub_t *dhdp,
-	tcpack_sup_module_t *tcpack_sup_mod)
-{
-	uint i;
-	tdata_psh_info_t *tdata_psh_info;
-
-	DHD_TRACE(("%s %d: Enter\n", __FUNCTION__, __LINE__));
-
-	if (tcpack_sup_mod == NULL) {
-		DHD_ERROR(("%s %d: ERROR tcpack_sup_mod NULL!\n",
-			__FUNCTION__, __LINE__));
-		return;
-	}
-
-	for (i = 0; i < tcpack_sup_mod->tcpdata_info_cnt; i++) {
-		tcpdata_info_t *tcpdata_info = &tcpack_sup_mod->tcpdata_info_tbl[i];
-		/* Return tdata_psh_info elements allocated to each tcpdata_info to the pool */
-		while ((tdata_psh_info = tcpdata_info->tdata_psh_info_head)) {
-			tcpdata_info->tdata_psh_info_head = tdata_psh_info->next;
-			tdata_psh_info->next = NULL;
-			_tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info);
-		}
-		tcpdata_info->tdata_psh_info_tail = NULL;
-	}
-#ifdef DHDTCPACK_SUP_DBG
-	DHD_ERROR(("%s %d: PSH INFO ENQ %d\n",
-		__FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
-#endif /* DHDTCPACK_SUP_DBG */
-
-	i = 0;
-	/* Be sure we recollected all tdata_psh_info elements */
-	while ((tdata_psh_info = tcpack_sup_mod->tdata_psh_info_free)) {
-		tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info->next;
-		tdata_psh_info->next = NULL;
-		i++;
-	}
-	ASSERT(i == TCPDATA_PSH_INFO_MAXNUM);
-	MFREE(dhdp->osh, tcpack_sup_mod->tdata_psh_info_pool,
-		sizeof(tdata_psh_info_t) * TCPDATA_PSH_INFO_MAXNUM);
-	tcpack_sup_mod->tdata_psh_info_pool = NULL;
-
-	return;
-}
-#endif /* BCMSDIO */
-
-static void dhd_tcpack_send(ulong data)
-{
-	tcpack_sup_module_t *tcpack_sup_mod;
-	tcpack_info_t *cur_tbl = (tcpack_info_t *)data;
-	dhd_pub_t *dhdp;
-	int ifidx;
-	void* pkt;
-	unsigned long flags;
-
-	if (!cur_tbl) {
-		return;
-	}
-
-	dhdp = cur_tbl->dhdp;
-	if (!dhdp) {
-		return;
-	}
-
-	flags = dhd_os_tcpacklock(dhdp);
-
-	tcpack_sup_mod = dhdp->tcpack_sup_module;
-	if (!tcpack_sup_mod) {
-		DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n",
-			__FUNCTION__, __LINE__));
-		dhd_os_tcpackunlock(dhdp, flags);
-		return;
-	}
-	pkt = cur_tbl->pkt_in_q;
-	ifidx = cur_tbl->ifidx;
-	if (!pkt) {
-		dhd_os_tcpackunlock(dhdp, flags);
-		return;
-	}
-	cur_tbl->pkt_in_q = NULL;
-	cur_tbl->pkt_ether_hdr = NULL;
-	cur_tbl->ifidx = 0;
-	cur_tbl->supp_cnt = 0;
-	if (--tcpack_sup_mod->tcpack_info_cnt < 0) {
-		DHD_ERROR(("%s %d: ERROR!!! tcp_ack_info_cnt %d\n",
-			__FUNCTION__, __LINE__, tcpack_sup_mod->tcpack_info_cnt));
-	}
-
-	dhd_os_tcpackunlock(dhdp, flags);
-
-	dhd_sendpkt(dhdp, ifidx, pkt);
-}
-
-int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode)
-{
-	int ret = BCME_OK;
-	unsigned long flags;
-
-	flags = dhd_os_tcpacklock(dhdp);
-
-	if (dhdp->tcpack_sup_mode == mode) {
-		DHD_ERROR(("%s %d: already set to %d\n", __FUNCTION__, __LINE__, mode));
-		goto exit;
-	}
-
-	if (mode >= TCPACK_SUP_LAST_MODE ||
-#ifndef BCMSDIO
-		mode == TCPACK_SUP_DELAYTX ||
-#endif /* !BCMSDIO */
-		FALSE) {
-		DHD_ERROR(("%s %d: Invalid mode %d\n", __FUNCTION__, __LINE__, mode));
-		ret = BCME_BADARG;
-		goto exit;
-	}
-
-	DHD_TRACE(("%s: %d -> %d\n",
-		__FUNCTION__, dhdp->tcpack_sup_mode, mode));
-
-#ifdef BCMSDIO
-	/* Old tcpack_sup_mode is TCPACK_SUP_DELAYTX */
-	if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX) {
-		tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module;
-		/* We won't need tdata_psh_info pool and tcpddata_info_tbl anymore */
-		_tdata_psh_info_pool_deinit(dhdp, tcpack_sup_mod);
-		tcpack_sup_mod->tcpdata_info_cnt = 0;
-		bzero(tcpack_sup_mod->tcpdata_info_tbl,
-			sizeof(tcpdata_info_t) * TCPDATA_INFO_MAXNUM);
-		/* For half duplex bus interface, tx precedes rx by default */
-		if (dhdp->bus)
-			dhd_bus_set_dotxinrx(dhdp->bus, TRUE);
-	}
-#endif /* BCMSDIO */
-	dhdp->tcpack_sup_mode = mode;
-
-	if (mode == TCPACK_SUP_OFF) {
-		ASSERT(dhdp->tcpack_sup_module != NULL);
-		/* Clean up timer/data structure for any remaining/pending packet or timer. */
-		dhd_tcpack_info_tbl_clean(dhdp);
-		MFREE(dhdp->osh, dhdp->tcpack_sup_module, sizeof(tcpack_sup_module_t));
-		dhdp->tcpack_sup_module = NULL;
-		goto exit;
-	}
-
-	if (dhdp->tcpack_sup_module == NULL) {
-		tcpack_sup_module_t *tcpack_sup_mod =
-			MALLOC(dhdp->osh, sizeof(tcpack_sup_module_t));
-		if (tcpack_sup_mod == NULL) {
-			DHD_ERROR(("%s %d: No MEM\n", __FUNCTION__, __LINE__));
-			dhdp->tcpack_sup_mode = TCPACK_SUP_OFF;
-			ret = BCME_NOMEM;
-			goto exit;
-		}
-		bzero(tcpack_sup_mod, sizeof(tcpack_sup_module_t));
-		dhdp->tcpack_sup_module = tcpack_sup_mod;
-	}
-
-#ifdef BCMSDIO
-	if (mode == TCPACK_SUP_DELAYTX) {
-		ret = _tdata_psh_info_pool_init(dhdp, dhdp->tcpack_sup_module);
-		if (ret != BCME_OK)
-			DHD_ERROR(("%s %d: pool init fail with %d\n", __FUNCTION__, __LINE__, ret));
-		else if (dhdp->bus)
-			dhd_bus_set_dotxinrx(dhdp->bus, FALSE);
-	}
-#endif /* BCMSDIO */
-
-	if (mode == TCPACK_SUP_HOLD) {
-		int i;
-		tcpack_sup_module_t *tcpack_sup_mod =
-			(tcpack_sup_module_t *)dhdp->tcpack_sup_module;
-		dhdp->tcpack_sup_ratio = CUSTOM_TCPACK_SUPP_RATIO;
-		dhdp->tcpack_sup_delay = CUSTOM_TCPACK_DELAY_TIME;
-		for (i = 0; i < TCPACK_INFO_MAXNUM; i++)
-		{
-			tcpack_sup_mod->tcpack_info_tbl[i].dhdp = dhdp;
-			init_timer(&tcpack_sup_mod->tcpack_info_tbl[i].timer);
-			tcpack_sup_mod->tcpack_info_tbl[i].timer.data =
-				(ulong)&tcpack_sup_mod->tcpack_info_tbl[i];
-			tcpack_sup_mod->tcpack_info_tbl[i].timer.function = dhd_tcpack_send;
-		}
-	}
-
-exit:
-	dhd_os_tcpackunlock(dhdp, flags);
-	return ret;
-}
-
-void
-dhd_tcpack_info_tbl_clean(dhd_pub_t *dhdp)
-{
-	tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module;
-	int i;
-	unsigned long flags;
-
-	if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF)
-		goto exit;
-
-	flags = dhd_os_tcpacklock(dhdp);
-
-	if (!tcpack_sup_mod) {
-		DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n",
-			__FUNCTION__, __LINE__));
-		dhd_os_tcpackunlock(dhdp, flags);
-		goto exit;
-	}
-
-	if (dhdp->tcpack_sup_mode == TCPACK_SUP_HOLD) {
-		for (i = 0; i < TCPACK_INFO_MAXNUM; i++) {
-			if (tcpack_sup_mod->tcpack_info_tbl[i].pkt_in_q) {
-				PKTFREE(dhdp->osh, tcpack_sup_mod->tcpack_info_tbl[i].pkt_in_q,
-					TRUE);
-				tcpack_sup_mod->tcpack_info_tbl[i].pkt_in_q = NULL;
-				tcpack_sup_mod->tcpack_info_tbl[i].pkt_ether_hdr = NULL;
-				tcpack_sup_mod->tcpack_info_tbl[i].ifidx = 0;
-				tcpack_sup_mod->tcpack_info_tbl[i].supp_cnt = 0;
-			}
-		}
-	} else {
-		tcpack_sup_mod->tcpack_info_cnt = 0;
-		bzero(tcpack_sup_mod->tcpack_info_tbl, sizeof(tcpack_info_t) * TCPACK_INFO_MAXNUM);
-	}
-
-	dhd_os_tcpackunlock(dhdp, flags);
-
-	if (dhdp->tcpack_sup_mode == TCPACK_SUP_HOLD) {
-		for (i = 0; i < TCPACK_INFO_MAXNUM; i++) {
-			del_timer_sync(&tcpack_sup_mod->tcpack_info_tbl[i].timer);
-		}
-	}
-
-exit:
-	return;
-}
-
-inline int dhd_tcpack_check_xmit(dhd_pub_t *dhdp, void *pkt)
-{
-	uint8 i;
-	tcpack_sup_module_t *tcpack_sup_mod;
-	tcpack_info_t *tcpack_info_tbl;
-	int tbl_cnt;
-	int ret = BCME_OK;
-	void *pdata;
-	uint32 pktlen;
-	unsigned long flags;
-
-	if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF)
-		goto exit;
-
-	pdata = PKTDATA(dhdp->osh, pkt);
-	pktlen = PKTLEN(dhdp->osh, pkt) - dhd_prot_hdrlen(dhdp, pdata);
-
-	if (pktlen < TCPACKSZMIN || pktlen > TCPACKSZMAX) {
-		DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n",
-			__FUNCTION__, __LINE__, pktlen));
-		goto exit;
-	}
-
-	flags = dhd_os_tcpacklock(dhdp);
-	tcpack_sup_mod = dhdp->tcpack_sup_module;
-
-	if (!tcpack_sup_mod) {
-		DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
-		ret = BCME_ERROR;
-		dhd_os_tcpackunlock(dhdp, flags);
-		goto exit;
-	}
-	tbl_cnt = tcpack_sup_mod->tcpack_info_cnt;
-	tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl;
-
-	ASSERT(tbl_cnt <= TCPACK_INFO_MAXNUM);
-
-	for (i = 0; i < tbl_cnt; i++) {
-		if (tcpack_info_tbl[i].pkt_in_q == pkt) {
-			DHD_TRACE(("%s %d: pkt %p sent out. idx %d, tbl_cnt %d\n",
-				__FUNCTION__, __LINE__, pkt, i, tbl_cnt));
-			/* This pkt is being transmitted so remove the tcp_ack_info of it. */
-			if (i < tbl_cnt - 1) {
-				bcopy(&tcpack_info_tbl[tbl_cnt - 1],
-					&tcpack_info_tbl[i], sizeof(tcpack_info_t));
-			}
-			bzero(&tcpack_info_tbl[tbl_cnt - 1], sizeof(tcpack_info_t));
-			if (--tcpack_sup_mod->tcpack_info_cnt < 0) {
-				DHD_ERROR(("%s %d: ERROR!!! tcp_ack_info_cnt %d\n",
-					__FUNCTION__, __LINE__, tcpack_sup_mod->tcpack_info_cnt));
-				ret = BCME_ERROR;
-			}
-			break;
-		}
-	}
-	dhd_os_tcpackunlock(dhdp, flags);
-
-exit:
-	return ret;
-}
-
-static INLINE bool dhd_tcpdata_psh_acked(dhd_pub_t *dhdp, uint8 *ip_hdr,
-	uint8 *tcp_hdr, uint32 tcp_ack_num)
-{
-	tcpack_sup_module_t *tcpack_sup_mod;
-	int i;
-	tcpdata_info_t *tcpdata_info = NULL;
-	tdata_psh_info_t *tdata_psh_info = NULL;
-	bool ret = FALSE;
-
-	if (dhdp->tcpack_sup_mode != TCPACK_SUP_DELAYTX)
-		goto exit;
-
-	tcpack_sup_mod = dhdp->tcpack_sup_module;
-
-	if (!tcpack_sup_mod) {
-		DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
-		goto exit;
-	}
-
-	DHD_TRACE(("%s %d: IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
-		" TCP port %d %d, ack %u\n", __FUNCTION__, __LINE__,
-		IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
-		IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
-		ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
-		ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]),
-		tcp_ack_num));
-
-	for (i = 0; i < tcpack_sup_mod->tcpdata_info_cnt; i++) {
-		tcpdata_info_t *tcpdata_info_tmp = &tcpack_sup_mod->tcpdata_info_tbl[i];
-		DHD_TRACE(("%s %d: data info[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
-			" TCP port %d %d\n", __FUNCTION__, __LINE__, i,
-			IPV4_ADDR_TO_STR(ntoh32_ua(tcpdata_info_tmp->ip_addr.src)),
-			IPV4_ADDR_TO_STR(ntoh32_ua(tcpdata_info_tmp->ip_addr.dst)),
-			ntoh16_ua(tcpdata_info_tmp->tcp_port.src),
-			ntoh16_ua(tcpdata_info_tmp->tcp_port.dst)));
-
-		/* If either IP address or TCP port number does not match, skip. */
-		if (memcmp(&ip_hdr[IPV4_SRC_IP_OFFSET],
-			tcpdata_info_tmp->ip_addr.dst, IPV4_ADDR_LEN) == 0 &&
-			memcmp(&ip_hdr[IPV4_DEST_IP_OFFSET],
-			tcpdata_info_tmp->ip_addr.src, IPV4_ADDR_LEN) == 0 &&
-			memcmp(&tcp_hdr[TCP_SRC_PORT_OFFSET],
-			tcpdata_info_tmp->tcp_port.dst, TCP_PORT_LEN) == 0 &&
-			memcmp(&tcp_hdr[TCP_DEST_PORT_OFFSET],
-			tcpdata_info_tmp->tcp_port.src, TCP_PORT_LEN) == 0) {
-			tcpdata_info = tcpdata_info_tmp;
-			break;
-		}
-	}
-
-	if (tcpdata_info == NULL) {
-		DHD_TRACE(("%s %d: no tcpdata_info!\n", __FUNCTION__, __LINE__));
-		goto exit;
-	}
-
-	if (tcpdata_info->tdata_psh_info_head == NULL) {
-		DHD_TRACE(("%s %d: No PSH DATA to be acked!\n", __FUNCTION__, __LINE__));
-	}
-
-	while ((tdata_psh_info = tcpdata_info->tdata_psh_info_head)) {
-		if (IS_TCPSEQ_GE(tcp_ack_num, tdata_psh_info->end_seq)) {
-			DHD_TRACE(("%s %d: PSH ACKED! %u >= %u\n",
-				__FUNCTION__, __LINE__, tcp_ack_num, tdata_psh_info->end_seq));
-			tcpdata_info->tdata_psh_info_head = tdata_psh_info->next;
-			tdata_psh_info->next = NULL;
-			_tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info);
-			ret = TRUE;
-		} else
-			break;
-	}
-	if (tdata_psh_info == NULL)
-		tcpdata_info->tdata_psh_info_tail = NULL;
-
-#ifdef DHDTCPACK_SUP_DBG
-	DHD_TRACE(("%s %d: PSH INFO ENQ %d\n",
-		__FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
-#endif /* DHDTCPACK_SUP_DBG */
-
-exit:
-	return ret;
-}
-
-bool
-dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt)
-{
-	uint8 *new_ether_hdr;	/* Ethernet header of the new packet */
-	uint16 new_ether_type;	/* Ethernet type of the new packet */
-	uint8 *new_ip_hdr;		/* IP header of the new packet */
-	uint8 *new_tcp_hdr;		/* TCP header of the new packet */
-	uint32 new_ip_hdr_len;	/* IP header length of the new packet */
-	uint32 cur_framelen;
-	uint32 new_tcp_ack_num;		/* TCP acknowledge number of the new packet */
-	uint16 new_ip_total_len;	/* Total length of IP packet for the new packet */
-	uint32 new_tcp_hdr_len;		/* TCP header length of the new packet */
-	tcpack_sup_module_t *tcpack_sup_mod;
-	tcpack_info_t *tcpack_info_tbl;
-	int i;
-	bool ret = FALSE;
-	bool set_dotxinrx = TRUE;
-	unsigned long flags;
-
-
-	if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF)
-		goto exit;
-
-	new_ether_hdr = PKTDATA(dhdp->osh, pkt);
-	cur_framelen = PKTLEN(dhdp->osh, pkt);
-
-	if (cur_framelen < TCPACKSZMIN || cur_framelen > TCPACKSZMAX) {
-		DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n",
-			__FUNCTION__, __LINE__, cur_framelen));
-		goto exit;
-	}
-
-	new_ether_type = new_ether_hdr[12] << 8 | new_ether_hdr[13];
-
-	if (new_ether_type != ETHER_TYPE_IP) {
-		DHD_TRACE(("%s %d: Not a IP packet 0x%x\n",
-			__FUNCTION__, __LINE__, new_ether_type));
-		goto exit;
-	}
-
-	DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, new_ether_type));
-
-	new_ip_hdr = new_ether_hdr + ETHER_HDR_LEN;
-	cur_framelen -= ETHER_HDR_LEN;
-
-	ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN);
-
-	new_ip_hdr_len = IPV4_HLEN(new_ip_hdr);
-	if (IP_VER(new_ip_hdr) != IP_VER_4 || IPV4_PROT(new_ip_hdr) != IP_PROT_TCP) {
-		DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n",
-			__FUNCTION__, __LINE__, IP_VER(new_ip_hdr), IPV4_PROT(new_ip_hdr)));
-		goto exit;
-	}
-
-	new_tcp_hdr = new_ip_hdr + new_ip_hdr_len;
-	cur_framelen -= new_ip_hdr_len;
-
-	ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN);
-
-	DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__));
-
-	/* is it an ack ? Allow only ACK flag, not to suppress others. */
-	if (new_tcp_hdr[TCP_FLAGS_OFFSET] != TCP_FLAG_ACK) {
-		DHD_TRACE(("%s %d: Do not touch TCP flag 0x%x\n",
-			__FUNCTION__, __LINE__, new_tcp_hdr[TCP_FLAGS_OFFSET]));
-		goto exit;
-	}
-
-	new_ip_total_len = ntoh16_ua(&new_ip_hdr[IPV4_PKTLEN_OFFSET]);
-	new_tcp_hdr_len = 4 * TCP_HDRLEN(new_tcp_hdr[TCP_HLEN_OFFSET]);
-
-	/* This packet has TCP data, so just send */
-	if (new_ip_total_len > new_ip_hdr_len + new_tcp_hdr_len) {
-		DHD_TRACE(("%s %d: Do nothing for TCP DATA\n", __FUNCTION__, __LINE__));
-		goto exit;
-	}
-
-	ASSERT(new_ip_total_len == new_ip_hdr_len + new_tcp_hdr_len);
-
-	new_tcp_ack_num = ntoh32_ua(&new_tcp_hdr[TCP_ACK_NUM_OFFSET]);
-
-	DHD_TRACE(("%s %d: TCP ACK with zero DATA length"
-		" IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n",
-		__FUNCTION__, __LINE__,
-		IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_SRC_IP_OFFSET])),
-		IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_DEST_IP_OFFSET])),
-		ntoh16_ua(&new_tcp_hdr[TCP_SRC_PORT_OFFSET]),
-		ntoh16_ua(&new_tcp_hdr[TCP_DEST_PORT_OFFSET])));
-
-	/* Look for tcp_ack_info that has the same ip src/dst addrs and tcp src/dst ports */
-	flags = dhd_os_tcpacklock(dhdp);
-#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
-	counter_printlog(&tack_tbl);
-	tack_tbl.cnt[0]++;
-#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
-
-	tcpack_sup_mod = dhdp->tcpack_sup_module;
-	tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl;
-
-	if (!tcpack_sup_mod) {
-		DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
-		ret = BCME_ERROR;
-		dhd_os_tcpackunlock(dhdp, flags);
-		goto exit;
-	}
-
-	if (dhd_tcpdata_psh_acked(dhdp, new_ip_hdr, new_tcp_hdr, new_tcp_ack_num)) {
-		/* This TCPACK is ACK to TCPDATA PSH pkt, so keep set_dotxinrx TRUE */
-#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
-		tack_tbl.cnt[5]++;
-#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
-	} else
-		set_dotxinrx = FALSE;
-
-	for (i = 0; i < tcpack_sup_mod->tcpack_info_cnt; i++) {
-		void *oldpkt;	/* TCPACK packet that is already in txq or DelayQ */
-		uint8 *old_ether_hdr, *old_ip_hdr, *old_tcp_hdr;
-		uint32 old_ip_hdr_len, old_tcp_hdr_len;
-		uint32 old_tcpack_num;	/* TCP ACK number of old TCPACK packet in Q */
-
-		if ((oldpkt = tcpack_info_tbl[i].pkt_in_q) == NULL) {
-			DHD_ERROR(("%s %d: Unexpected error!! cur idx %d, ttl cnt %d\n",
-				__FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpack_info_cnt));
-			break;
-		}
-
-		if (PKTDATA(dhdp->osh, oldpkt) == NULL) {
-			DHD_ERROR(("%s %d: oldpkt data NULL!! cur idx %d, ttl cnt %d\n",
-				__FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpack_info_cnt));
-			break;
-		}
-
-		old_ether_hdr = tcpack_info_tbl[i].pkt_ether_hdr;
-		old_ip_hdr = old_ether_hdr + ETHER_HDR_LEN;
-		old_ip_hdr_len = IPV4_HLEN(old_ip_hdr);
-		old_tcp_hdr = old_ip_hdr + old_ip_hdr_len;
-		old_tcp_hdr_len = 4 * TCP_HDRLEN(old_tcp_hdr[TCP_HLEN_OFFSET]);
-
-		DHD_TRACE(("%s %d: oldpkt %p[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
-			" TCP port %d %d\n", __FUNCTION__, __LINE__, oldpkt, i,
-			IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_SRC_IP_OFFSET])),
-			IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_DEST_IP_OFFSET])),
-			ntoh16_ua(&old_tcp_hdr[TCP_SRC_PORT_OFFSET]),
-			ntoh16_ua(&old_tcp_hdr[TCP_DEST_PORT_OFFSET])));
-
-		/* If either of IP address or TCP port number does not match, skip.
-		 * Note that src/dst addr fields in ip header are contiguous being 8 bytes in total.
-		 * Also, src/dst port fields in TCP header are contiguous being 4 bytes in total.
-		 */
-		if (memcmp(&new_ip_hdr[IPV4_SRC_IP_OFFSET],
-			&old_ip_hdr[IPV4_SRC_IP_OFFSET], IPV4_ADDR_LEN * 2) ||
-			memcmp(&new_tcp_hdr[TCP_SRC_PORT_OFFSET],
-			&old_tcp_hdr[TCP_SRC_PORT_OFFSET], TCP_PORT_LEN * 2))
-			continue;
-
-		old_tcpack_num = ntoh32_ua(&old_tcp_hdr[TCP_ACK_NUM_OFFSET]);
-
-		if (IS_TCPSEQ_GT(new_tcp_ack_num, old_tcpack_num)) {
-			/* New packet has higher TCP ACK number, so it replaces the old packet */
-			if (new_ip_hdr_len == old_ip_hdr_len &&
-				new_tcp_hdr_len == old_tcp_hdr_len) {
-				ASSERT(memcmp(new_ether_hdr, old_ether_hdr, ETHER_HDR_LEN) == 0);
-				bcopy(new_ip_hdr, old_ip_hdr, new_ip_total_len);
-				PKTFREE(dhdp->osh, pkt, FALSE);
-				DHD_TRACE(("%s %d: TCP ACK replace %u -> %u\n",
-					__FUNCTION__, __LINE__, old_tcpack_num, new_tcp_ack_num));
-#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
-				tack_tbl.cnt[2]++;
-#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
-				ret = TRUE;
-			} else {
-#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
-				tack_tbl.cnt[6]++;
-#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
-				DHD_TRACE(("%s %d: lenth mismatch %d != %d || %d != %d"
-					" ACK %u -> %u\n", __FUNCTION__, __LINE__,
-					new_ip_hdr_len, old_ip_hdr_len,
-					new_tcp_hdr_len, old_tcp_hdr_len,
-					old_tcpack_num, new_tcp_ack_num));
-			}
-		} else if (new_tcp_ack_num == old_tcpack_num) {
-			set_dotxinrx = TRUE;
-			/* TCPACK retransmission */
-#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
-			tack_tbl.cnt[3]++;
-#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
-		} else {
-			DHD_TRACE(("%s %d: ACK number reverse old %u(0x%p) new %u(0x%p)\n",
-				__FUNCTION__, __LINE__, old_tcpack_num, oldpkt,
-				new_tcp_ack_num, pkt));
-		}
-		dhd_os_tcpackunlock(dhdp, flags);
-		goto exit;
-	}
-
-	if (i == tcpack_sup_mod->tcpack_info_cnt && i < TCPACK_INFO_MAXNUM) {
-		/* No TCPACK packet with the same IP addr and TCP port is found
-		 * in tcp_ack_info_tbl. So add this packet to the table.
-		 */
-		DHD_TRACE(("%s %d: Add pkt 0x%p(ether_hdr 0x%p) to tbl[%d]\n",
-			__FUNCTION__, __LINE__, pkt, new_ether_hdr,
-			tcpack_sup_mod->tcpack_info_cnt));
-
-		tcpack_info_tbl[tcpack_sup_mod->tcpack_info_cnt].pkt_in_q = pkt;
-		tcpack_info_tbl[tcpack_sup_mod->tcpack_info_cnt].pkt_ether_hdr = new_ether_hdr;
-		tcpack_sup_mod->tcpack_info_cnt++;
-#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
-		tack_tbl.cnt[1]++;
-#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
-	} else {
-		ASSERT(i == tcpack_sup_mod->tcpack_info_cnt);
-		DHD_TRACE(("%s %d: No empty tcp ack info tbl\n",
-			__FUNCTION__, __LINE__));
-	}
-	dhd_os_tcpackunlock(dhdp, flags);
-
-exit:
-	/* Unless TCPACK_SUP_DELAYTX, dotxinrx is alwasy TRUE, so no need to set here */
-	if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX && set_dotxinrx)
-		dhd_bus_set_dotxinrx(dhdp->bus, TRUE);
-
-	return ret;
-}
-
-bool
-dhd_tcpdata_info_get(dhd_pub_t *dhdp, void *pkt)
-{
-	uint8 *ether_hdr;	/* Ethernet header of the new packet */
-	uint16 ether_type;	/* Ethernet type of the new packet */
-	uint8 *ip_hdr;		/* IP header of the new packet */
-	uint8 *tcp_hdr;		/* TCP header of the new packet */
-	uint32 ip_hdr_len;	/* IP header length of the new packet */
-	uint32 cur_framelen;
-	uint16 ip_total_len;	/* Total length of IP packet for the new packet */
-	uint32 tcp_hdr_len;		/* TCP header length of the new packet */
-	uint32 tcp_seq_num;		/* TCP sequence number of the new packet */
-	uint16 tcp_data_len;	/* TCP DATA length that excludes IP and TCP headers */
-	uint32 end_tcp_seq_num;	/* TCP seq number of the last byte in the new packet */
-	tcpack_sup_module_t *tcpack_sup_mod;
-	tcpdata_info_t *tcpdata_info = NULL;
-	tdata_psh_info_t *tdata_psh_info;
-
-	int i;
-	bool ret = FALSE;
-	unsigned long flags;
-
-	if (dhdp->tcpack_sup_mode != TCPACK_SUP_DELAYTX)
-		goto exit;
-
-	ether_hdr = PKTDATA(dhdp->osh, pkt);
-	cur_framelen = PKTLEN(dhdp->osh, pkt);
-
-	ether_type = ether_hdr[12] << 8 | ether_hdr[13];
-
-	if (ether_type != ETHER_TYPE_IP) {
-		DHD_TRACE(("%s %d: Not a IP packet 0x%x\n",
-			__FUNCTION__, __LINE__, ether_type));
-		goto exit;
-	}
-
-	DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, ether_type));
-
-	ip_hdr = ether_hdr + ETHER_HDR_LEN;
-	cur_framelen -= ETHER_HDR_LEN;
-
-	ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN);
-
-	ip_hdr_len = IPV4_HLEN(ip_hdr);
-	if (IP_VER(ip_hdr) != IP_VER_4 || IPV4_PROT(ip_hdr) != IP_PROT_TCP) {
-		DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n",
-			__FUNCTION__, __LINE__, IP_VER(ip_hdr), IPV4_PROT(ip_hdr)));
-		goto exit;
-	}
-
-	tcp_hdr = ip_hdr + ip_hdr_len;
-	cur_framelen -= ip_hdr_len;
-
-	ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN);
-
-	DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__));
-
-	ip_total_len = ntoh16_ua(&ip_hdr[IPV4_PKTLEN_OFFSET]);
-	tcp_hdr_len = 4 * TCP_HDRLEN(tcp_hdr[TCP_HLEN_OFFSET]);
-
-	/* This packet is mere TCP ACK, so do nothing */
-	if (ip_total_len == ip_hdr_len + tcp_hdr_len) {
-		DHD_TRACE(("%s %d: Do nothing for no data TCP ACK\n", __FUNCTION__, __LINE__));
-		goto exit;
-	}
-
-	ASSERT(ip_total_len > ip_hdr_len + tcp_hdr_len);
-
-	if ((tcp_hdr[TCP_FLAGS_OFFSET] & TCP_FLAG_PSH) == 0) {
-		DHD_TRACE(("%s %d: Not interested TCP DATA packet\n", __FUNCTION__, __LINE__));
-		goto exit;
-	}
-
-	DHD_TRACE(("%s %d: TCP DATA with nonzero DATA length"
-		" IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d, flag 0x%x\n",
-		__FUNCTION__, __LINE__,
-		IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
-		IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
-		ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
-		ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]),
-		tcp_hdr[TCP_FLAGS_OFFSET]));
-
-	flags = dhd_os_tcpacklock(dhdp);
-	tcpack_sup_mod = dhdp->tcpack_sup_module;
-
-	if (!tcpack_sup_mod) {
-		DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
-		ret = BCME_ERROR;
-		dhd_os_tcpackunlock(dhdp, flags);
-		goto exit;
-	}
-
-	/* Look for tcpdata_info that has the same ip src/dst addrs and tcp src/dst ports */
-	i = 0;
-	while (i < tcpack_sup_mod->tcpdata_info_cnt) {
-		tcpdata_info_t *tdata_info_tmp = &tcpack_sup_mod->tcpdata_info_tbl[i];
-		uint32 now_in_ms = OSL_SYSUPTIME();
-		DHD_TRACE(("%s %d: data info[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
-			" TCP port %d %d\n", __FUNCTION__, __LINE__, i,
-			IPV4_ADDR_TO_STR(ntoh32_ua(tdata_info_tmp->ip_addr.src)),
-			IPV4_ADDR_TO_STR(ntoh32_ua(tdata_info_tmp->ip_addr.dst)),
-			ntoh16_ua(tdata_info_tmp->tcp_port.src),
-			ntoh16_ua(tdata_info_tmp->tcp_port.dst)));
-
-		/* If both IP address and TCP port number match, we found it so break.
-		 * Note that src/dst addr fields in ip header are contiguous being 8 bytes in total.
-		 * Also, src/dst port fields in TCP header are contiguous being 4 bytes in total.
-		 */
-		if (memcmp(&ip_hdr[IPV4_SRC_IP_OFFSET],
-			(void *)&tdata_info_tmp->ip_addr, IPV4_ADDR_LEN * 2) == 0 &&
-			memcmp(&tcp_hdr[TCP_SRC_PORT_OFFSET],
-			(void *)&tdata_info_tmp->tcp_port, TCP_PORT_LEN * 2) == 0) {
-			tcpdata_info = tdata_info_tmp;
-			tcpdata_info->last_used_time = now_in_ms;
-			break;
-		}
-
-		if (now_in_ms - tdata_info_tmp->last_used_time > TCPDATA_INFO_TIMEOUT) {
-			tdata_psh_info_t *tdata_psh_info_tmp;
-			tcpdata_info_t *last_tdata_info;
-
-			while ((tdata_psh_info_tmp = tdata_info_tmp->tdata_psh_info_head)) {
-				tdata_info_tmp->tdata_psh_info_head = tdata_psh_info_tmp->next;
-				tdata_psh_info_tmp->next = NULL;
-				DHD_TRACE(("%s %d: Clean tdata_psh_info(end_seq %u)!\n",
-					__FUNCTION__, __LINE__, tdata_psh_info_tmp->end_seq));
-				_tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info_tmp);
-			}
-#ifdef DHDTCPACK_SUP_DBG
-			DHD_ERROR(("%s %d: PSH INFO ENQ %d\n",
-				__FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
-#endif /* DHDTCPACK_SUP_DBG */
-			tcpack_sup_mod->tcpdata_info_cnt--;
-			ASSERT(tcpack_sup_mod->tcpdata_info_cnt >= 0);
-
-			last_tdata_info =
-				&tcpack_sup_mod->tcpdata_info_tbl[tcpack_sup_mod->tcpdata_info_cnt];
-			if (i < tcpack_sup_mod->tcpdata_info_cnt) {
-				ASSERT(last_tdata_info != tdata_info_tmp);
-				bcopy(last_tdata_info, tdata_info_tmp, sizeof(tcpdata_info_t));
-			}
-			bzero(last_tdata_info, sizeof(tcpdata_info_t));
-			DHD_INFO(("%s %d: tcpdata_info(idx %d) is aged out. ttl cnt is now %d\n",
-				__FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpdata_info_cnt));
-			/* Don't increase "i" here, so that the prev last tcpdata_info is checked */
-		} else
-			 i++;
-	}
-
-	tcp_seq_num = ntoh32_ua(&tcp_hdr[TCP_SEQ_NUM_OFFSET]);
-	tcp_data_len = ip_total_len - ip_hdr_len - tcp_hdr_len;
-	end_tcp_seq_num = tcp_seq_num + tcp_data_len;
-
-	if (tcpdata_info == NULL) {
-		ASSERT(i == tcpack_sup_mod->tcpdata_info_cnt);
-		if (i >= TCPDATA_INFO_MAXNUM) {
-			DHD_TRACE(("%s %d: tcp_data_info_tbl FULL! %d %d"
-				" IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n",
-				__FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpdata_info_cnt,
-				IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
-				IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
-				ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
-				ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET])));
-			dhd_os_tcpackunlock(dhdp, flags);
-			goto exit;
-		}
-		tcpdata_info = &tcpack_sup_mod->tcpdata_info_tbl[i];
-
-		/* No TCP flow with the same IP addr and TCP port is found
-		 * in tcp_data_info_tbl. So add this flow to the table.
-		 */
-		DHD_INFO(("%s %d: Add data info to tbl[%d]: IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
-			" TCP port %d %d\n",
-			__FUNCTION__, __LINE__, tcpack_sup_mod->tcpdata_info_cnt,
-			IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
-			IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
-			ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
-			ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET])));
-		/* Note that src/dst addr fields in ip header are contiguous being 8 bytes in total.
-		 * Also, src/dst port fields in TCP header are contiguous being 4 bytes in total.
-		 */
-		bcopy(&ip_hdr[IPV4_SRC_IP_OFFSET], (void *)&tcpdata_info->ip_addr,
-			IPV4_ADDR_LEN * 2);
-		bcopy(&tcp_hdr[TCP_SRC_PORT_OFFSET], (void *)&tcpdata_info->tcp_port,
-			TCP_PORT_LEN * 2);
-
-		tcpdata_info->last_used_time = OSL_SYSUPTIME();
-		tcpack_sup_mod->tcpdata_info_cnt++;
-	}
-
-	ASSERT(tcpdata_info != NULL);
-
-	tdata_psh_info = _tdata_psh_info_pool_deq(tcpack_sup_mod);
-#ifdef DHDTCPACK_SUP_DBG
-	DHD_TRACE(("%s %d: PSH INFO ENQ %d\n",
-		__FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
-#endif /* DHDTCPACK_SUP_DBG */
-
-	if (tdata_psh_info == NULL) {
-		DHD_ERROR(("%s %d: No more free tdata_psh_info!!\n", __FUNCTION__, __LINE__));
-		ret = BCME_ERROR;
-		dhd_os_tcpackunlock(dhdp, flags);
-		goto exit;
-	}
-	tdata_psh_info->end_seq = end_tcp_seq_num;
-
-#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
-	tack_tbl.cnt[4]++;
-#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
-
-	DHD_TRACE(("%s %d: TCP PSH DATA recvd! end seq %u\n",
-		__FUNCTION__, __LINE__, tdata_psh_info->end_seq));
-
-	ASSERT(tdata_psh_info->next == NULL);
-
-	if (tcpdata_info->tdata_psh_info_head == NULL)
-		tcpdata_info->tdata_psh_info_head = tdata_psh_info;
-	else {
-		ASSERT(tcpdata_info->tdata_psh_info_tail);
-		tcpdata_info->tdata_psh_info_tail->next = tdata_psh_info;
-	}
-	tcpdata_info->tdata_psh_info_tail = tdata_psh_info;
-
-	dhd_os_tcpackunlock(dhdp, flags);
-
-exit:
-	return ret;
-}
-
-bool
-dhd_tcpack_hold(dhd_pub_t *dhdp, void *pkt, int ifidx)
-{
-	uint8 *new_ether_hdr;	/* Ethernet header of the new packet */
-	uint16 new_ether_type;	/* Ethernet type of the new packet */
-	uint8 *new_ip_hdr;		/* IP header of the new packet */
-	uint8 *new_tcp_hdr;		/* TCP header of the new packet */
-	uint32 new_ip_hdr_len;	/* IP header length of the new packet */
-	uint32 cur_framelen;
-	uint32 new_tcp_ack_num;		/* TCP acknowledge number of the new packet */
-	uint16 new_ip_total_len;	/* Total length of IP packet for the new packet */
-	uint32 new_tcp_hdr_len;		/* TCP header length of the new packet */
-	tcpack_sup_module_t *tcpack_sup_mod;
-	tcpack_info_t *tcpack_info_tbl;
-	int i, free_slot = TCPACK_INFO_MAXNUM;
-	bool hold = FALSE;
-	unsigned long flags;
-
-	if (dhdp->tcpack_sup_mode != TCPACK_SUP_HOLD) {
-		goto exit;
-	}
-
-	if (dhdp->tcpack_sup_ratio == 1) {
-		goto exit;
-	}
-
-	new_ether_hdr = PKTDATA(dhdp->osh, pkt);
-	cur_framelen = PKTLEN(dhdp->osh, pkt);
-
-	if (cur_framelen < TCPACKSZMIN || cur_framelen > TCPACKSZMAX) {
-		DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n",
-			__FUNCTION__, __LINE__, cur_framelen));
-		goto exit;
-	}
-
-	new_ether_type = new_ether_hdr[12] << 8 | new_ether_hdr[13];
-
-	if (new_ether_type != ETHER_TYPE_IP) {
-		DHD_TRACE(("%s %d: Not a IP packet 0x%x\n",
-			__FUNCTION__, __LINE__, new_ether_type));
-		goto exit;
-	}
-
-	DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, new_ether_type));
-
-	new_ip_hdr = new_ether_hdr + ETHER_HDR_LEN;
-	cur_framelen -= ETHER_HDR_LEN;
-
-	ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN);
-
-	new_ip_hdr_len = IPV4_HLEN(new_ip_hdr);
-	if (IP_VER(new_ip_hdr) != IP_VER_4 || IPV4_PROT(new_ip_hdr) != IP_PROT_TCP) {
-		DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n",
-			__FUNCTION__, __LINE__, IP_VER(new_ip_hdr), IPV4_PROT(new_ip_hdr)));
-		goto exit;
-	}
-
-	new_tcp_hdr = new_ip_hdr + new_ip_hdr_len;
-	cur_framelen -= new_ip_hdr_len;
-
-	ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN);
-
-	DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__));
-
-	/* is it an ack ? Allow only ACK flag, not to suppress others. */
-	if (new_tcp_hdr[TCP_FLAGS_OFFSET] != TCP_FLAG_ACK) {
-		DHD_TRACE(("%s %d: Do not touch TCP flag 0x%x\n",
-			__FUNCTION__, __LINE__, new_tcp_hdr[TCP_FLAGS_OFFSET]));
-		goto exit;
-	}
-
-	new_ip_total_len = ntoh16_ua(&new_ip_hdr[IPV4_PKTLEN_OFFSET]);
-	new_tcp_hdr_len = 4 * TCP_HDRLEN(new_tcp_hdr[TCP_HLEN_OFFSET]);
-
-	/* This packet has TCP data, so just send */
-	if (new_ip_total_len > new_ip_hdr_len + new_tcp_hdr_len) {
-		DHD_TRACE(("%s %d: Do nothing for TCP DATA\n", __FUNCTION__, __LINE__));
-		goto exit;
-	}
-
-	ASSERT(new_ip_total_len == new_ip_hdr_len + new_tcp_hdr_len);
-
-	new_tcp_ack_num = ntoh32_ua(&new_tcp_hdr[TCP_ACK_NUM_OFFSET]);
-
-	DHD_TRACE(("%s %d: TCP ACK with zero DATA length"
-		" IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n",
-		__FUNCTION__, __LINE__,
-		IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_SRC_IP_OFFSET])),
-		IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_DEST_IP_OFFSET])),
-		ntoh16_ua(&new_tcp_hdr[TCP_SRC_PORT_OFFSET]),
-		ntoh16_ua(&new_tcp_hdr[TCP_DEST_PORT_OFFSET])));
-
-	/* Look for tcp_ack_info that has the same ip src/dst addrs and tcp src/dst ports */
-	flags = dhd_os_tcpacklock(dhdp);
-
-	tcpack_sup_mod = dhdp->tcpack_sup_module;
-	tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl;
-
-	if (!tcpack_sup_mod) {
-		DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
-		dhd_os_tcpackunlock(dhdp, flags);
-		goto exit;
-	}
-
-	hold = TRUE;
-
-	for (i = 0; i < TCPACK_INFO_MAXNUM; i++) {
-		void *oldpkt;	/* TCPACK packet that is already in txq or DelayQ */
-		uint8 *old_ether_hdr, *old_ip_hdr, *old_tcp_hdr;
-		uint32 old_ip_hdr_len, old_tcp_hdr_len;
-		uint32 old_tcpack_num;	/* TCP ACK number of old TCPACK packet in Q */
-
-		if ((oldpkt = tcpack_info_tbl[i].pkt_in_q) == NULL) {
-			if (free_slot == TCPACK_INFO_MAXNUM) {
-				free_slot = i;
-			}
-			continue;
-		}
-
-		if (PKTDATA(dhdp->osh, oldpkt) == NULL) {
-			DHD_ERROR(("%s %d: oldpkt data NULL!! cur idx %d\n",
-				__FUNCTION__, __LINE__, i));
-			hold = FALSE;
-			dhd_os_tcpackunlock(dhdp, flags);
-			goto exit;
-		}
-
-		old_ether_hdr = tcpack_info_tbl[i].pkt_ether_hdr;
-		old_ip_hdr = old_ether_hdr + ETHER_HDR_LEN;
-		old_ip_hdr_len = IPV4_HLEN(old_ip_hdr);
-		old_tcp_hdr = old_ip_hdr + old_ip_hdr_len;
-		old_tcp_hdr_len = 4 * TCP_HDRLEN(old_tcp_hdr[TCP_HLEN_OFFSET]);
-
-		DHD_TRACE(("%s %d: oldpkt %p[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
-			" TCP port %d %d\n", __FUNCTION__, __LINE__, oldpkt, i,
-			IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_SRC_IP_OFFSET])),
-			IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_DEST_IP_OFFSET])),
-			ntoh16_ua(&old_tcp_hdr[TCP_SRC_PORT_OFFSET]),
-			ntoh16_ua(&old_tcp_hdr[TCP_DEST_PORT_OFFSET])));
-
-		/* If either of IP address or TCP port number does not match, skip. */
-		if (memcmp(&new_ip_hdr[IPV4_SRC_IP_OFFSET],
-			&old_ip_hdr[IPV4_SRC_IP_OFFSET], IPV4_ADDR_LEN * 2) ||
-			memcmp(&new_tcp_hdr[TCP_SRC_PORT_OFFSET],
-			&old_tcp_hdr[TCP_SRC_PORT_OFFSET], TCP_PORT_LEN * 2)) {
-			continue;
-		}
-
-		old_tcpack_num = ntoh32_ua(&old_tcp_hdr[TCP_ACK_NUM_OFFSET]);
-
-		if (IS_TCPSEQ_GE(new_tcp_ack_num, old_tcpack_num)) {
-			tcpack_info_tbl[i].supp_cnt++;
-			if (tcpack_info_tbl[i].supp_cnt >= dhdp->tcpack_sup_ratio) {
-				tcpack_info_tbl[i].pkt_in_q = NULL;
-				tcpack_info_tbl[i].pkt_ether_hdr = NULL;
-				tcpack_info_tbl[i].ifidx = 0;
-				tcpack_info_tbl[i].supp_cnt = 0;
-				hold = FALSE;
-			} else {
-				tcpack_info_tbl[i].pkt_in_q = pkt;
-				tcpack_info_tbl[i].pkt_ether_hdr = new_ether_hdr;
-				tcpack_info_tbl[i].ifidx = ifidx;
-			}
-			PKTFREE(dhdp->osh, oldpkt, TRUE);
-		} else {
-			PKTFREE(dhdp->osh, pkt, TRUE);
-		}
-		dhd_os_tcpackunlock(dhdp, flags);
-
-		if (!hold) {
-			del_timer_sync(&tcpack_info_tbl[i].timer);
-		}
-		goto exit;
-	}
-
-	if (free_slot < TCPACK_INFO_MAXNUM) {
-		/* No TCPACK packet with the same IP addr and TCP port is found
-		 * in tcp_ack_info_tbl. So add this packet to the table.
-		 */
-		DHD_TRACE(("%s %d: Add pkt 0x%p(ether_hdr 0x%p) to tbl[%d]\n",
-			__FUNCTION__, __LINE__, pkt, new_ether_hdr,
-			free_slot));
-
-		tcpack_info_tbl[free_slot].pkt_in_q = pkt;
-		tcpack_info_tbl[free_slot].pkt_ether_hdr = new_ether_hdr;
-		tcpack_info_tbl[free_slot].ifidx = ifidx;
-		tcpack_info_tbl[free_slot].supp_cnt = 1;
-		mod_timer(&tcpack_sup_mod->tcpack_info_tbl[free_slot].timer,
-			jiffies + msecs_to_jiffies(dhdp->tcpack_sup_delay));
-		tcpack_sup_mod->tcpack_info_cnt++;
-	} else {
-		DHD_TRACE(("%s %d: No empty tcp ack info tbl\n",
-			__FUNCTION__, __LINE__));
-	}
-	dhd_os_tcpackunlock(dhdp, flags);
-
-exit:
-	return hold;
-}
-#endif /* DHDTCPACK_SUPPRESS */
diff --git a/drivers/net/wireless/bcmdhd/dhd_ip.h b/drivers/net/wireless/bcmdhd/dhd_ip.h
deleted file mode 100644
index a72976b..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_ip.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Header file describing the common ip parser function.
- *
- * Provides type definitions and function prototypes used to parse ip packet.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_ip.h 537119 2015-02-25 04:24:14Z $
- */
-
-#ifndef _dhd_ip_h_
-#define _dhd_ip_h_
-
-#ifdef DHDTCPACK_SUPPRESS
-#include <dngl_stats.h>
-#include <bcmutils.h>
-#include <dhd.h>
-#endif /* DHDTCPACK_SUPPRESS */
-
-typedef enum pkt_frag
-{
-	DHD_PKT_FRAG_NONE = 0,
-	DHD_PKT_FRAG_FIRST,
-	DHD_PKT_FRAG_CONT,
-	DHD_PKT_FRAG_LAST
-} pkt_frag_t;
-
-extern pkt_frag_t pkt_frag_info(osl_t *osh, void *p);
-
-#ifdef DHDTCPACK_SUPPRESS
-#define	TCPACKSZMIN	(ETHER_HDR_LEN + IPV4_MIN_HEADER_LEN + TCP_MIN_HEADER_LEN)
-/* Size of MAX possible TCP ACK packet. Extra bytes for IP/TCP option fields */
-#define	TCPACKSZMAX	(TCPACKSZMIN + 100)
-
-/* Max number of TCP streams that have own src/dst IP addrs and TCP ports */
-#define TCPACK_INFO_MAXNUM 4
-#define TCPDATA_INFO_MAXNUM 4
-#define TCPDATA_PSH_INFO_MAXNUM (8 * TCPDATA_INFO_MAXNUM)
-
-#define TCPDATA_INFO_TIMEOUT 5000	/* Remove tcpdata_info if inactive for this time (in ms) */
-
-#define DEFAULT_TCPACK_SUPP_RATIO 3
-#ifndef CUSTOM_TCPACK_SUPP_RATIO
-#define CUSTOM_TCPACK_SUPP_RATIO DEFAULT_TCPACK_SUPP_RATIO
-#endif /* CUSTOM_TCPACK_SUPP_RATIO */
-
-#define DEFAULT_TCPACK_DELAY_TIME 10 /* ms */
-#ifndef CUSTOM_TCPACK_DELAY_TIME
-#define CUSTOM_TCPACK_DELAY_TIME DEFAULT_TCPACK_DELAY_TIME
-#endif /* CUSTOM_TCPACK_DELAY_TIME */
-
-extern int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 on);
-extern void dhd_tcpack_info_tbl_clean(dhd_pub_t *dhdp);
-extern int dhd_tcpack_check_xmit(dhd_pub_t *dhdp, void *pkt);
-extern bool dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt);
-extern bool dhd_tcpdata_info_get(dhd_pub_t *dhdp, void *pkt);
-extern bool dhd_tcpack_hold(dhd_pub_t *dhdp, void *pkt, int ifidx);
-/* #define DHDTCPACK_SUP_DBG */
-#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
-extern counter_tbl_t tack_tbl;
-#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
-#endif /* DHDTCPACK_SUPPRESS */
-
-#endif /* _dhd_ip_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
deleted file mode 100644
index 495a0b8..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ /dev/null
@@ -1,13638 +0,0 @@
-/*
- * Broadcom Dongle Host Driver (DHD), Linux-specific network interface
- * Basically selected code segments from usb-cdc.c and usb-rndis.c
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_linux.c 609723 2016-01-05 08:40:45Z $
- */
-
-#include <typedefs.h>
-#include <linuxver.h>
-#include <osl.h>
-#ifdef SHOW_LOGTRACE
-#include <linux/syscalls.h>
-#include <event_log.h>
-#endif /* SHOW_LOGTRACE */
-
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/rtnetlink.h>
-#include <linux/etherdevice.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/fcntl.h>
-#include <linux/fs.h>
-#include <linux/ip.h>
-#include <linux/reboot.h>
-#include <linux/notifier.h>
-#include <net/addrconf.h>
-#ifdef ENABLE_ADAPTIVE_SCHED
-#include <linux/cpufreq.h>
-#endif /* ENABLE_ADAPTIVE_SCHED */
-
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
-
-#include <epivers.h>
-#include <bcmutils.h>
-#include <bcmendian.h>
-#include <bcmdevs.h>
-
-#include <proto/ethernet.h>
-#include <proto/bcmevent.h>
-#include <proto/vlan.h>
-#include <proto/802.3.h>
-
-#include <dngl_stats.h>
-#include <dhd_linux_wq.h>
-#include <dhd.h>
-#include <dhd_linux.h>
-#ifdef PCIE_FULL_DONGLE
-#include <dhd_flowring.h>
-#endif
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
-#ifdef WL_CFG80211
-#include <wl_cfg80211.h>
-#endif
-#ifdef PNO_SUPPORT
-#include <dhd_pno.h>
-#endif
-#ifdef RTT_SUPPORT
-#include <dhd_rtt.h>
-#endif
-
-#ifdef CONFIG_COMPAT
-#include <linux/compat.h>
-#endif
-
-#ifdef DHD_WMF
-#include <dhd_wmf_linux.h>
-#endif /* DHD_WMF */
-
-#ifdef DHD_L2_FILTER
-#include <proto/bcmicmp.h>
-#include <bcm_l2_filter.h>
-#include <dhd_l2_filter.h>
-#endif /* DHD_L2_FILTER */
-
-#ifdef DHD_PSTA
-#include <dhd_psta.h>
-#endif /* DHD_PSTA */
-
-
-#ifdef DHDTCPACK_SUPPRESS
-#include <dhd_ip.h>
-#endif /* DHDTCPACK_SUPPRESS */
-
-#ifdef DHD_DEBUG_PAGEALLOC
-typedef void (*page_corrupt_cb_t)(void *handle, void *addr_corrupt, size_t len);
-void dhd_page_corrupt_cb(void *handle, void *addr_corrupt, size_t len);
-extern void register_page_corrupt_cb(page_corrupt_cb_t cb, void* handle);
-#endif /* DHD_DEBUG_PAGEALLOC */
-
-
-#if defined(DHD_LB)
-/* Dynamic CPU selection for load balancing */
-#include <linux/cpu.h>
-#include <linux/cpumask.h>
-#include <linux/notifier.h>
-#include <linux/workqueue.h>
-#include <asm/atomic.h>
-
-#if !defined(DHD_LB_PRIMARY_CPUS)
-#define DHD_LB_PRIMARY_CPUS     0x0 /* Big CPU coreids mask */
-#endif
-
-#if !defined(DHD_LB_SECONDARY_CPUS)
-#define DHD_LB_SECONDARY_CPUS   0xFE /* Little CPU coreids mask */
-#endif
-
-#define HIST_BIN_SIZE	8
-
-#if defined(DHD_LB_RXP)
-static void dhd_rx_napi_dispatcher_fn(struct work_struct * work);
-#endif /* DHD_LB_RXP */
-
-#endif /* DHD_LB */
-
-#ifdef WLMEDIA_HTSF
-#include <linux/time.h>
-#include <htsf.h>
-
-#define HTSF_MINLEN 200    /* min. packet length to timestamp */
-#define HTSF_BUS_DELAY 150 /* assume a fix propagation in us  */
-#define TSMAX  1000        /* max no. of timing record kept   */
-#define NUMBIN 34
-
-static uint32 tsidx = 0;
-static uint32 htsf_seqnum = 0;
-uint32 tsfsync;
-struct timeval tsync;
-static uint32 tsport = 5010;
-
-typedef struct histo_ {
-	uint32 bin[NUMBIN];
-} histo_t;
-
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
-#endif
-
-static histo_t vi_d1, vi_d2, vi_d3, vi_d4;
-#endif /* WLMEDIA_HTSF */
-
-#ifdef STBLINUX
-#ifdef quote_str
-#undef quote_str
-#endif /* quote_str */
-#ifdef to_str
-#undef to_str
-#endif /* quote_str */
-#define to_str(s) #s
-#define quote_str(s) to_str(s)
-
-static char *driver_target = "driver_target: "quote_str(BRCM_DRIVER_TARGET);
-#endif /* STBLINUX */
-
-
-#if defined(SOFTAP)
-extern bool ap_cfg_running;
-extern bool ap_fw_loaded;
-#endif
-extern void dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction);
-
-#ifdef FIX_CPU_MIN_CLOCK
-#include <linux/pm_qos.h>
-#endif /* FIX_CPU_MIN_CLOCK */
-#ifdef SET_RANDOM_MAC_SOFTAP
-#ifndef CONFIG_DHD_SET_RANDOM_MAC_VAL
-#define CONFIG_DHD_SET_RANDOM_MAC_VAL	0x001A11
-#endif
-static u32 vendor_oui = CONFIG_DHD_SET_RANDOM_MAC_VAL;
-#endif /* SET_RANDOM_MAC_SOFTAP */
-#ifdef ENABLE_ADAPTIVE_SCHED
-#define DEFAULT_CPUFREQ_THRESH		1000000	/* threshold frequency : 1000000 = 1GHz */
-#ifndef CUSTOM_CPUFREQ_THRESH
-#define CUSTOM_CPUFREQ_THRESH	DEFAULT_CPUFREQ_THRESH
-#endif /* CUSTOM_CPUFREQ_THRESH */
-#endif /* ENABLE_ADAPTIVE_SCHED */
-
-/* enable HOSTIP cache update from the host side when an eth0:N is up */
-#define AOE_IP_ALIAS_SUPPORT 1
-
-#ifdef BCM_FD_AGGR
-#include <bcm_rpc.h>
-#include <bcm_rpc_tp.h>
-#endif
-#ifdef PROP_TXSTATUS
-#include <wlfc_proto.h>
-#include <dhd_wlfc.h>
-#endif
-
-#include <wl_android.h>
-
-/* Maximum STA per radio */
-#define DHD_MAX_STA     32
-
-
-
-const uint8 wme_fifo2ac[] = { 0, 1, 2, 3, 1, 1 };
-const uint8 prio2fifo[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
-#define WME_PRIO2AC(prio)  wme_fifo2ac[prio2fifo[(prio)]]
-
-#ifdef ARP_OFFLOAD_SUPPORT
-void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx);
-static int dhd_inetaddr_notifier_call(struct notifier_block *this,
-	unsigned long event, void *ptr);
-static struct notifier_block dhd_inetaddr_notifier = {
-	.notifier_call = dhd_inetaddr_notifier_call
-};
-/* to make sure we won't register the same notifier twice, otherwise a loop is likely to be
- * created in kernel notifier link list (with 'next' pointing to itself)
- */
-static bool dhd_inetaddr_notifier_registered = FALSE;
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT)
-static int dhd_inet6addr_notifier_call(struct notifier_block *this,
-	unsigned long event, void *ptr);
-static struct notifier_block dhd_inet6addr_notifier = {
-	.notifier_call = dhd_inet6addr_notifier_call
-};
-/* to make sure we won't register the same notifier twice, otherwise a loop is likely to be
- * created in kernel notifier link list (with 'next' pointing to itself)
- */
-static bool dhd_inet6addr_notifier_registered = FALSE;
-#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
-#include <linux/suspend.h>
-volatile bool dhd_mmc_suspend = FALSE;
-DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
-
-#if defined(OOB_INTR_ONLY)
-extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable);
-#endif 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-static void dhd_hang_process(void *dhd_info, void *event_data, u8 event);
-#endif 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-MODULE_LICENSE("GPL and additional rights");
-#endif /* LinuxVer */
-
-#include <dhd_bus.h>
-
-#ifdef BCM_FD_AGGR
-#define DBUS_RX_BUFFER_SIZE_DHD(net)	(BCM_RPC_TP_DNGL_AGG_MAX_BYTE)
-#else
-#ifndef PROP_TXSTATUS
-#define DBUS_RX_BUFFER_SIZE_DHD(net)	(net->mtu + net->hard_header_len + dhd->pub.hdrlen)
-#else
-#define DBUS_RX_BUFFER_SIZE_DHD(net)	(net->mtu + net->hard_header_len + dhd->pub.hdrlen + 128)
-#endif
-#endif /* BCM_FD_AGGR */
-
-#ifdef PROP_TXSTATUS
-extern bool dhd_wlfc_skip_fc(void);
-extern void dhd_wlfc_plat_init(void *dhd);
-extern void dhd_wlfc_plat_deinit(void *dhd);
-#endif /* PROP_TXSTATUS */
-#ifdef USE_DYNAMIC_F2_BLKSIZE
-extern uint sd_f2_blocksize;
-extern int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size);
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
-
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15)
-const char *
-print_tainted()
-{
-	return "";
-}
-#endif	/* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */
-
-/* Linux wireless extension support */
-#if defined(WL_WIRELESS_EXT)
-#include <wl_iw.h>
-extern wl_iw_extra_params_t  g_wl_iw_params;
-#endif /* defined(WL_WIRELESS_EXT) */
-
-#ifdef CONFIG_PARTIALSUSPEND_SLP
-#include <linux/partialsuspend_slp.h>
-#define CONFIG_HAS_EARLYSUSPEND
-#define DHD_USE_EARLYSUSPEND
-#define register_early_suspend		register_pre_suspend
-#define unregister_early_suspend	unregister_pre_suspend
-#define early_suspend				pre_suspend
-#define EARLY_SUSPEND_LEVEL_BLANK_SCREEN		50
-#else
-#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */
-#endif /* CONFIG_PARTIALSUSPEND_SLP */
-
-extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd);
-
-#ifdef PKT_FILTER_SUPPORT
-extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg);
-extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
-extern void dhd_pktfilter_offload_delete(dhd_pub_t *dhd, int id);
-#endif
-
-
-#ifdef READ_MACADDR
-extern int dhd_read_macaddr(struct dhd_info *dhd);
-#else
-static inline int dhd_read_macaddr(struct dhd_info *dhd) { return 0; }
-#endif
-#ifdef WRITE_MACADDR
-extern int dhd_write_macaddr(struct ether_addr *mac);
-#else
-static inline int dhd_write_macaddr(struct ether_addr *mac) { return 0; }
-#endif
-
-
-
-
-
-#ifdef DHD_FW_COREDUMP
-static void dhd_mem_dump(void *dhd_info, void *event_info, u8 event);
-#endif /* DHD_FW_COREDUMP */
-#ifdef DHD_LOG_DUMP
-static void dhd_log_dump_init(dhd_pub_t *dhd);
-static void dhd_log_dump_deinit(dhd_pub_t *dhd);
-static void dhd_log_dump(void *handle, void *event_info, u8 event);
-void dhd_schedule_log_dump(dhd_pub_t *dhdp);
-static int do_dhd_log_dump(dhd_pub_t *dhdp);
-#endif /* DHD_LOG_DUMP */
-
-static int dhd_reboot_callback(struct notifier_block *this, unsigned long code, void *unused);
-static struct notifier_block dhd_reboot_notifier = {
-	.notifier_call = dhd_reboot_callback,
-	.priority = 1,
-};
-
-#ifdef BCMPCIE
-static int is_reboot = 0;
-#endif /* BCMPCIE */
-
-typedef struct dhd_if_event {
-	struct list_head	list;
-	wl_event_data_if_t	event;
-	char			name[IFNAMSIZ+1];
-	uint8			mac[ETHER_ADDR_LEN];
-} dhd_if_event_t;
-
-/* Interface control information */
-typedef struct dhd_if {
-	struct dhd_info *info;			/* back pointer to dhd_info */
-	/* OS/stack specifics */
-	struct net_device *net;
-	int				idx;			/* iface idx in dongle */
-	uint			subunit;		/* subunit */
-	uint8			mac_addr[ETHER_ADDR_LEN];	/* assigned MAC address */
-	bool			set_macaddress;
-	bool			set_multicast;
-	uint8			bssidx;			/* bsscfg index for the interface */
-	bool			attached;		/* Delayed attachment when unset */
-	bool			txflowcontrol;	/* Per interface flow control indicator */
-	char			name[IFNAMSIZ+1]; /* linux interface name */
-	char			dngl_name[IFNAMSIZ+1]; /* corresponding dongle interface name */
-	struct net_device_stats stats;
-#ifdef DHD_WMF
-	dhd_wmf_t		wmf;		/* per bsscfg wmf setting */
-#endif /* DHD_WMF */
-#ifdef PCIE_FULL_DONGLE
-	struct list_head sta_list;		/* sll of associated stations */
-#if !defined(BCM_GMAC3)
-	spinlock_t	sta_list_lock;		/* lock for manipulating sll */
-#endif /* ! BCM_GMAC3 */
-#endif /* PCIE_FULL_DONGLE */
-	uint32  ap_isolate;			/* ap-isolation settings */
-#ifdef DHD_L2_FILTER
-	bool parp_enable;
-	bool parp_discard;
-	bool parp_allnode;
-	arp_table_t *phnd_arp_table;
-/* for Per BSS modification */
-	bool dhcp_unicast;
-	bool block_ping;
-	bool grat_arp;
-#endif /* DHD_L2_FILTER */
-} dhd_if_t;
-
-#ifdef WLMEDIA_HTSF
-typedef struct {
-	uint32 low;
-	uint32 high;
-} tsf_t;
-
-typedef struct {
-	uint32 last_cycle;
-	uint32 last_sec;
-	uint32 last_tsf;
-	uint32 coef;     /* scaling factor */
-	uint32 coefdec1; /* first decimal  */
-	uint32 coefdec2; /* second decimal */
-} htsf_t;
-
-typedef struct {
-	uint32 t1;
-	uint32 t2;
-	uint32 t3;
-	uint32 t4;
-} tstamp_t;
-
-static tstamp_t ts[TSMAX];
-static tstamp_t maxdelayts;
-static uint32 maxdelay = 0, tspktcnt = 0, maxdelaypktno = 0;
-
-#endif  /* WLMEDIA_HTSF */
-
-struct ipv6_work_info_t {
-	uint8			if_idx;
-	char			ipv6_addr[16];
-	unsigned long		event;
-};
-
-#ifdef DHD_DEBUG
-typedef struct dhd_dump {
-	uint8 *buf;
-	int bufsize;
-} dhd_dump_t;
-#endif /* DHD_DEBUG */
-
-/* When Perimeter locks are deployed, any blocking calls must be preceeded
- * with a PERIM UNLOCK and followed by a PERIM LOCK.
- * Examples of blocking calls are: schedule_timeout(), down_interruptible(),
- * wait_event_timeout().
- */
-
-/* Local private structure (extension of pub) */
-typedef struct dhd_info {
-#if defined(WL_WIRELESS_EXT)
-	wl_iw_t		iw;		/* wireless extensions state (must be first) */
-#endif /* defined(WL_WIRELESS_EXT) */
-	dhd_pub_t pub;
-	dhd_if_t *iflist[DHD_MAX_IFS]; /* for supporting multiple interfaces */
-
-	void *adapter;			/* adapter information, interrupt, fw path etc. */
-	char fw_path[PATH_MAX];		/* path to firmware image */
-	char nv_path[PATH_MAX];		/* path to nvram vars file */
-
-	/* serialize dhd iovars */
-	struct mutex dhd_iovar_mutex;
-
-	struct semaphore proto_sem;
-#ifdef PROP_TXSTATUS
-	spinlock_t	wlfc_spinlock;
-
-#endif /* PROP_TXSTATUS */
-#ifdef WLMEDIA_HTSF
-	htsf_t  htsf;
-#endif
-	wait_queue_head_t ioctl_resp_wait;
-	wait_queue_head_t d3ack_wait;
-	wait_queue_head_t dhd_bus_busy_state_wait;
-	uint32	default_wd_interval;
-
-	struct timer_list timer;
-	bool wd_timer_valid;
-#ifdef DHD_PCIE_RUNTIMEPM
-	struct timer_list rpm_timer;
-	bool rpm_timer_valid;
-	tsk_ctl_t	  thr_rpm_ctl;
-#endif /* DHD_PCIE_RUNTIMEPM */
-	struct tasklet_struct tasklet;
-	spinlock_t	sdlock;
-	spinlock_t	txqlock;
-	spinlock_t	dhd_lock;
-
-	struct semaphore sdsem;
-	tsk_ctl_t	thr_dpc_ctl;
-	tsk_ctl_t	thr_wdt_ctl;
-
-	tsk_ctl_t	thr_rxf_ctl;
-	spinlock_t	rxf_lock;
-	bool		rxthread_enabled;
-
-	/* Wakelocks */
-#if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-	struct wake_lock wl_wifi;   /* Wifi wakelock */
-	struct wake_lock wl_rxwake; /* Wifi rx wakelock */
-	struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */
-	struct wake_lock wl_wdwake; /* Wifi wd wakelock */
-	struct wake_lock wl_evtwake; /* Wifi event wakelock */
-#ifdef BCMPCIE_OOB_HOST_WAKE
-	struct wake_lock wl_intrwake; /* Host wakeup wakelock */
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-#ifdef DHD_USE_SCAN_WAKELOCK
-	struct wake_lock wl_scanwake;  /* Wifi scan wakelock */
-#endif /* DHD_USE_SCAN_WAKELOCK */
-#endif /* CONFIG_HAS_WAKELOCK && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	/* net_device interface lock, prevent race conditions among net_dev interface
-	 * calls and wifi_on or wifi_off
-	 */
-	struct mutex dhd_net_if_mutex;
-	struct mutex dhd_suspend_mutex;
-#endif
-	spinlock_t wakelock_spinlock;
-	spinlock_t wakelock_evt_spinlock;
-	uint32 wakelock_event_counter;
-	uint32 wakelock_counter;
-	int wakelock_wd_counter;
-	int wakelock_rx_timeout_enable;
-	int wakelock_ctrl_timeout_enable;
-	bool waive_wakelock;
-	uint32 wakelock_before_waive;
-
-	/* Thread to issue ioctl for multicast */
-	wait_queue_head_t ctrl_wait;
-	atomic_t pend_8021x_cnt;
-	dhd_attach_states_t dhd_state;
-#ifdef SHOW_LOGTRACE
-	dhd_event_log_t event_data;
-#endif /* SHOW_LOGTRACE */
-
-#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
-	struct early_suspend early_suspend;
-#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
-
-#ifdef ARP_OFFLOAD_SUPPORT
-	u32 pend_ipaddr;
-#endif /* ARP_OFFLOAD_SUPPORT */
-#ifdef BCM_FD_AGGR
-	void *rpc_th;
-	void *rpc_osh;
-	struct timer_list rpcth_timer;
-	bool rpcth_timer_active;
-	uint8 fdaggr;
-#endif
-#ifdef DHDTCPACK_SUPPRESS
-	spinlock_t	tcpack_lock;
-#endif /* DHDTCPACK_SUPPRESS */
-#ifdef FIX_CPU_MIN_CLOCK
-	bool cpufreq_fix_status;
-	struct mutex cpufreq_fix;
-	struct pm_qos_request dhd_cpu_qos;
-#ifdef FIX_BUS_MIN_CLOCK
-	struct pm_qos_request dhd_bus_qos;
-#endif /* FIX_BUS_MIN_CLOCK */
-#endif /* FIX_CPU_MIN_CLOCK */
-	void			*dhd_deferred_wq;
-#ifdef DEBUG_CPU_FREQ
-	struct notifier_block freq_trans;
-	int __percpu *new_freq;
-#endif
-	unsigned int unit;
-	struct notifier_block pm_notifier;
-#ifdef DHD_PSTA
-	uint32	psta_mode;	/* PSTA or PSR */
-#endif /* DHD_PSTA */
-#ifdef DHD_DEBUG
-	dhd_dump_t *dump;
-	struct timer_list join_timer;
-	u32 join_timeout_val;
-	bool join_timer_active;
-	uint scan_time_count;
-	struct timer_list scan_timer;
-	bool scan_timer_active;
-#endif
-#if defined(DHD_LB)
-	/* CPU Load Balance dynamic CPU selection */
-
-	/* Variable that tracks the currect CPUs available for candidacy */
-	cpumask_var_t cpumask_curr_avail;
-
-	/* Primary and secondary CPU mask */
-	cpumask_var_t cpumask_primary, cpumask_secondary; /* configuration */
-	cpumask_var_t cpumask_primary_new, cpumask_secondary_new; /* temp */
-
-	struct notifier_block cpu_notifier;
-
-	/* Tasklet to handle Tx Completion packet freeing */
-	struct tasklet_struct tx_compl_tasklet;
-	atomic_t	tx_compl_cpu;
-
-
-	/* Tasklet to handle RxBuf Post during Rx completion */
-	struct tasklet_struct rx_compl_tasklet;
-	atomic_t	rx_compl_cpu;
-
-	/* Napi struct for handling rx packet sendup. Packets are removed from
-	 * H2D RxCompl ring and placed into rx_pend_queue. rx_pend_queue is then
-	 * appended to rx_napi_queue (w/ lock) and the rx_napi_struct is scheduled
-	 * to run to rx_napi_cpu.
-	 */
-	struct sk_buff_head   rx_pend_queue  ____cacheline_aligned;
-	struct sk_buff_head   rx_napi_queue  ____cacheline_aligned;
-	struct napi_struct    rx_napi_struct ____cacheline_aligned;
-	atomic_t	rx_napi_cpu; /* cpu on which the napi is dispatched */
-	struct net_device    *rx_napi_netdev; /* netdev of primary interface */
-
-	struct work_struct    rx_napi_dispatcher_work;
-	struct work_struct    tx_compl_dispatcher_work;
-	struct work_struct    rx_compl_dispatcher_work;
-	/* Number of times DPC Tasklet ran */
-	uint32	dhd_dpc_cnt;
-
-	/* Number of times NAPI processing got scheduled */
-	uint32	napi_sched_cnt;
-
-	/* Number of times NAPI processing ran on each available core */
-	uint32	napi_percpu_run_cnt[NR_CPUS];
-
-	/* Number of times RX Completions got scheduled */
-	uint32	rxc_sched_cnt;
-	/* Number of times RX Completion ran on each available core */
-	uint32	rxc_percpu_run_cnt[NR_CPUS];
-
-	/* Number of times TX Completions got scheduled */
-	uint32	txc_sched_cnt;
-	/* Number of times TX Completions ran on each available core */
-	uint32	txc_percpu_run_cnt[NR_CPUS];
-
-	/* CPU status */
-	/* Number of times each CPU came online */
-	uint32	cpu_online_cnt[NR_CPUS];
-
-	/* Number of times each CPU went offline */
-	uint32	cpu_offline_cnt[NR_CPUS];
-
-	/*
-	 * Consumer Histogram - NAPI RX Packet processing
-	 * -----------------------------------------------
-	 * On Each CPU, when the NAPI RX Packet processing call back was invoked
-	 * how many packets were processed is captured in this data structure.
-	 * Now its difficult to capture the "exact" number of packets processed.
-	 * So considering the packet counter to be a 32 bit one, we have a
-	 * bucket with 8 bins (2^1, 2^2 ... 2^8). The "number" of packets
-	 * processed is rounded off to the next power of 2 and put in the
-	 * approriate "bin" the value in the bin gets incremented.
-	 * For example, assume that in CPU 1 if NAPI Rx runs 3 times
-	 * and the packet count processed is as follows (assume the bin counters are 0)
-	 * iteration 1 - 10 (the bin counter 2^4 increments to 1)
-	 * iteration 2 - 30 (the bin counter 2^5 increments to 1)
-	 * iteration 3 - 15 (the bin counter 2^4 increments by 1 to become 2)
-	 */
-	uint32 napi_rx_hist[NR_CPUS][HIST_BIN_SIZE];
-	uint32 txc_hist[NR_CPUS][HIST_BIN_SIZE];
-	uint32 rxc_hist[NR_CPUS][HIST_BIN_SIZE];
-#endif /* DHD_LB */
-
-#if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW)
-#endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */
-
-	struct kobject dhd_kobj;
-#ifdef SUPPORT_SENSORHUB
-	uint32 shub_enable;
-#endif /* SUPPORT_SENSORHUB */
-
-	struct delayed_work dhd_memdump_work;
-} dhd_info_t;
-
-#define DHDIF_FWDER(dhdif)      FALSE
-
-/* Flag to indicate if we should download firmware on driver load */
-uint dhd_download_fw_on_driverload = TRUE;
-
-/* Flag to indicate if driver is initialized */
-uint dhd_driver_init_done = FALSE;
-
-/* Definitions to provide path to the firmware and nvram
- * example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt"
- */
-char firmware_path[MOD_PARAM_PATHLEN];
-char nvram_path[MOD_PARAM_PATHLEN];
-
-/* backup buffer for firmware and nvram path */
-char fw_bak_path[MOD_PARAM_PATHLEN];
-char nv_bak_path[MOD_PARAM_PATHLEN];
-
-/* information string to keep firmware, chio, cheip version info visiable from log */
-char info_string[MOD_PARAM_INFOLEN];
-module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444);
-int op_mode = 0;
-int disable_proptx = 0;
-module_param(op_mode, int, 0644);
-
-#if defined(DHD_LB_RXP)
-static int dhd_napi_weight = 32;
-module_param(dhd_napi_weight, int, 0644);
-#endif /* DHD_LB_RXP */
-
-extern int wl_control_wl_start(struct net_device *dev);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(BCMLXSDMMC)
-struct semaphore dhd_registration_sem;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-
-/* deferred handlers */
-static void dhd_ifadd_event_handler(void *handle, void *event_info, u8 event);
-static void dhd_ifdel_event_handler(void *handle, void *event_info, u8 event);
-static void dhd_set_mac_addr_handler(void *handle, void *event_info, u8 event);
-static void dhd_set_mcast_list_handler(void *handle, void *event_info, u8 event);
-#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT)
-static void dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event);
-#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */
-#ifdef WL_CFG80211
-extern void dhd_netdev_free(struct net_device *ndev);
-#endif /* WL_CFG80211 */
-
-/* Error bits */
-module_param(dhd_msg_level, int, 0);
-
-#ifdef ARP_OFFLOAD_SUPPORT
-/* ARP offload enable */
-uint dhd_arp_enable = TRUE;
-module_param(dhd_arp_enable, uint, 0);
-
-/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */
-
-#ifdef ENABLE_ARP_SNOOP_MODE
-uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY | ARP_OL_SNOOP;
-#else
-uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY;
-#endif	/* ENABLE_ARP_SNOOP_MODE */
-
-module_param(dhd_arp_mode, uint, 0);
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-/* Disable Prop tx */
-module_param(disable_proptx, int, 0644);
-/* load firmware and/or nvram values from the filesystem */
-module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660);
-module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0660);
-
-/* Watchdog interval */
-
-/* extend watchdog expiration to 2 seconds when DPC is running */
-#define WATCHDOG_EXTEND_INTERVAL (2000)
-
-uint dhd_watchdog_ms = CUSTOM_DHD_WATCHDOG_MS;
-module_param(dhd_watchdog_ms, uint, 0);
-
-#ifdef DHD_PCIE_RUNTIMEPM
-uint dhd_runtimepm_ms = CUSTOM_DHD_RUNTIME_MS;
-#endif /* DHD_PCIE_RUNTIMEPMT */
-#if defined(DHD_DEBUG)
-/* Console poll interval */
-uint dhd_console_ms = 0;
-module_param(dhd_console_ms, uint, 0644);
-#endif /* defined(DHD_DEBUG) */
-
-
-uint dhd_slpauto = TRUE;
-module_param(dhd_slpauto, uint, 0);
-
-#ifdef PKT_FILTER_SUPPORT
-/* Global Pkt filter enable control */
-uint dhd_pkt_filter_enable = TRUE;
-module_param(dhd_pkt_filter_enable, uint, 0);
-#endif
-
-/* Pkt filter init setup */
-uint dhd_pkt_filter_init = 0;
-module_param(dhd_pkt_filter_init, uint, 0);
-
-/* Pkt filter mode control */
-#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER
-uint dhd_master_mode = FALSE;
-#else
-uint dhd_master_mode = TRUE;
-#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */
-module_param(dhd_master_mode, uint, 0);
-
-int dhd_watchdog_prio = 0;
-module_param(dhd_watchdog_prio, int, 0);
-
-/* DPC thread priority */
-int dhd_dpc_prio = CUSTOM_DPC_PRIO_SETTING;
-module_param(dhd_dpc_prio, int, 0);
-
-/* RX frame thread priority */
-int dhd_rxf_prio = CUSTOM_RXF_PRIO_SETTING;
-module_param(dhd_rxf_prio, int, 0);
-
-int passive_channel_skip = 0;
-module_param(passive_channel_skip, int, (S_IRUSR|S_IWUSR));
-
-#if !defined(BCMDHDUSB)
-extern int dhd_dongle_ramsize;
-module_param(dhd_dongle_ramsize, int, 0);
-#endif /* BCMDHDUSB */
-
-/* Keep track of number of instances */
-static int dhd_found = 0;
-static int instance_base = 0; /* Starting instance number */
-module_param(instance_base, int, 0644);
-
-/* Functions to manage sysfs interface for dhd */
-static int dhd_sysfs_init(dhd_info_t *dhd);
-static void dhd_sysfs_exit(dhd_info_t *dhd);
-
-#if defined(DHD_LB)
-
-static void
-dhd_lb_set_default_cpus(dhd_info_t *dhd)
-{
-	/* Default CPU allocation for the jobs */
-	atomic_set(&dhd->rx_napi_cpu, 1);
-	atomic_set(&dhd->rx_compl_cpu, 2);
-	atomic_set(&dhd->tx_compl_cpu, 2);
-}
-
-static void
-dhd_cpumasks_deinit(dhd_info_t *dhd)
-{
-	free_cpumask_var(dhd->cpumask_curr_avail);
-	free_cpumask_var(dhd->cpumask_primary);
-	free_cpumask_var(dhd->cpumask_primary_new);
-	free_cpumask_var(dhd->cpumask_secondary);
-	free_cpumask_var(dhd->cpumask_secondary_new);
-}
-
-static int
-dhd_cpumasks_init(dhd_info_t *dhd)
-{
-	int id;
-	uint32 cpus;
-	int ret = 0;
-
-	if (!alloc_cpumask_var(&dhd->cpumask_curr_avail, GFP_KERNEL) ||
-		!alloc_cpumask_var(&dhd->cpumask_primary, GFP_KERNEL) ||
-		!alloc_cpumask_var(&dhd->cpumask_primary_new, GFP_KERNEL) ||
-		!alloc_cpumask_var(&dhd->cpumask_secondary, GFP_KERNEL) ||
-		!alloc_cpumask_var(&dhd->cpumask_secondary_new, GFP_KERNEL)) {
-		DHD_ERROR(("%s Failed to init cpumasks\n", __FUNCTION__));
-		ret = -ENOMEM;
-		goto fail;
-	}
-
-	cpumask_copy(dhd->cpumask_curr_avail, cpu_online_mask);
-	cpumask_clear(dhd->cpumask_primary);
-	cpumask_clear(dhd->cpumask_secondary);
-
-	cpus = DHD_LB_PRIMARY_CPUS;
-	for (id = 0; id < NR_CPUS; id++) {
-		if (isset(&cpus, id))
-			cpumask_set_cpu(id, dhd->cpumask_primary);
-	}
-
-	cpus = DHD_LB_SECONDARY_CPUS;
-	for (id = 0; id < NR_CPUS; id++) {
-		if (isset(&cpus, id))
-			cpumask_set_cpu(id, dhd->cpumask_secondary);
-	}
-
-	return ret;
-fail:
-	dhd_cpumasks_deinit(dhd);
-	return ret;
-}
-
-/*
- * The CPU Candidacy Algorithm
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * The available CPUs for selection are divided into two groups
- *  Primary Set - A CPU mask that carries the First Choice CPUs
- *  Secondary Set - A CPU mask that carries the Second Choice CPUs.
- *
- * There are two types of Job, that needs to be assigned to
- * the CPUs, from one of the above mentioned CPU group. The Jobs are
- * 1) Rx Packet Processing - napi_cpu
- * 2) Completion Processiong (Tx, RX) - compl_cpu
- *
- * To begin with both napi_cpu and compl_cpu are on CPU0. Whenever a CPU goes
- * on-line/off-line the CPU candidacy algorithm is triggerd. The candidacy
- * algo tries to pickup the first available non boot CPU (CPU0) for napi_cpu.
- * If there are more processors free, it assigns one to compl_cpu.
- * It also tries to ensure that both napi_cpu and compl_cpu are not on the same
- * CPU, as much as possible.
- *
- * By design, both Tx and Rx completion jobs are run on the same CPU core, as it
- * would allow Tx completion skb's to be released into a local free pool from
- * which the rx buffer posts could have been serviced. it is important to note
- * that a Tx packet may not have a large enough buffer for rx posting.
- */
-void dhd_select_cpu_candidacy(dhd_info_t *dhd)
-{
-	uint32 primary_available_cpus; /* count of primary available cpus */
-	uint32 secondary_available_cpus; /* count of secondary available cpus */
-	uint32 napi_cpu = 0; /* cpu selected for napi rx processing */
-	uint32 compl_cpu = 0; /* cpu selected for completion jobs */
-
-	cpumask_clear(dhd->cpumask_primary_new);
-	cpumask_clear(dhd->cpumask_secondary_new);
-
-	/*
-	 * Now select from the primary mask. Even if a Job is
-	 * already running on a CPU in secondary group, we still move
-	 * to primary CPU. So no conditional checks.
-	 */
-	cpumask_and(dhd->cpumask_primary_new, dhd->cpumask_primary,
-		dhd->cpumask_curr_avail);
-
-	cpumask_and(dhd->cpumask_secondary_new, dhd->cpumask_secondary,
-		dhd->cpumask_curr_avail);
-
-	primary_available_cpus = cpumask_weight(dhd->cpumask_primary_new);
-
-	if (primary_available_cpus > 0) {
-		napi_cpu = cpumask_first(dhd->cpumask_primary_new);
-
-		/* If no further CPU is available,
-		 * cpumask_next returns >= nr_cpu_ids
-		 */
-		compl_cpu = cpumask_next(napi_cpu, dhd->cpumask_primary_new);
-		if (compl_cpu >= nr_cpu_ids)
-			compl_cpu = 0;
-	}
-
-	DHD_INFO(("%s After primary CPU check napi_cpu %d compl_cpu %d\n",
-		__FUNCTION__, napi_cpu, compl_cpu));
-
-	/* -- Now check for the CPUs from the secondary mask -- */
-	secondary_available_cpus = cpumask_weight(dhd->cpumask_secondary_new);
-
-	DHD_INFO(("%s Available secondary cpus %d nr_cpu_ids %d\n",
-		__FUNCTION__, secondary_available_cpus, nr_cpu_ids));
-
-	if (secondary_available_cpus > 0) {
-		/* At this point if napi_cpu is unassigned it means no CPU
-		 * is online from Primary Group
-		 */
-		if (napi_cpu == 0) {
-			napi_cpu = cpumask_first(dhd->cpumask_secondary_new);
-			compl_cpu = cpumask_next(napi_cpu, dhd->cpumask_secondary_new);
-		} else if (compl_cpu == 0) {
-			compl_cpu = cpumask_first(dhd->cpumask_secondary_new);
-		}
-
-		/* If no CPU was available for completion, choose CPU 0 */
-		if (compl_cpu >= nr_cpu_ids)
-			compl_cpu = 0;
-	}
-	if ((primary_available_cpus == 0) &&
-		(secondary_available_cpus == 0)) {
-		/* No CPUs available from primary or secondary mask */
-		napi_cpu = 0;
-		compl_cpu = 0;
-	}
-
-	DHD_INFO(("%s After secondary CPU check napi_cpu %d compl_cpu %d\n",
-		__FUNCTION__, napi_cpu, compl_cpu));
-	ASSERT(napi_cpu < nr_cpu_ids);
-	ASSERT(compl_cpu < nr_cpu_ids);
-
-	atomic_set(&dhd->rx_napi_cpu, napi_cpu);
-	atomic_set(&dhd->tx_compl_cpu, compl_cpu);
-	atomic_set(&dhd->rx_compl_cpu, compl_cpu);
-	return;
-}
-
-/*
- * Function to handle CPU Hotplug notifications.
- * One of the task it does is to trigger the CPU Candidacy algorithm
- * for load balancing.
- */
-int
-dhd_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned int)(long)hcpu;
-
-	dhd_info_t *dhd = container_of(nfb, dhd_info_t, cpu_notifier);
-
-	switch (action)
-	{
-		case CPU_ONLINE:
-			DHD_LB_STATS_INCR(dhd->cpu_online_cnt[cpu]);
-			cpumask_set_cpu(cpu, dhd->cpumask_curr_avail);
-			dhd_select_cpu_candidacy(dhd);
-			break;
-
-		case CPU_DOWN_PREPARE:
-		case CPU_DOWN_PREPARE_FROZEN:
-			DHD_LB_STATS_INCR(dhd->cpu_offline_cnt[cpu]);
-			cpumask_clear_cpu(cpu, dhd->cpumask_curr_avail);
-			dhd_select_cpu_candidacy(dhd);
-			break;
-		default:
-			break;
-	}
-
-	return NOTIFY_OK;
-}
-
-#if defined(DHD_LB_STATS)
-void dhd_lb_stats_init(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd;
-	int i, j;
-
-	if (dhdp == NULL) {
-		DHD_ERROR(("%s(): Invalid argument dhdp is NULL \n",
-			__FUNCTION__));
-		return;
-	}
-
-	dhd = dhdp->info;
-	if (dhd == NULL) {
-		DHD_ERROR(("%s(): DHD pointer is NULL \n", __FUNCTION__));
-		return;
-	}
-
-	DHD_LB_STATS_CLR(dhd->dhd_dpc_cnt);
-	DHD_LB_STATS_CLR(dhd->napi_sched_cnt);
-	DHD_LB_STATS_CLR(dhd->rxc_sched_cnt);
-	DHD_LB_STATS_CLR(dhd->txc_sched_cnt);
-
-	for (i = 0; i < NR_CPUS; i++) {
-		DHD_LB_STATS_CLR(dhd->napi_percpu_run_cnt[i]);
-		DHD_LB_STATS_CLR(dhd->rxc_percpu_run_cnt[i]);
-		DHD_LB_STATS_CLR(dhd->txc_percpu_run_cnt[i]);
-
-		DHD_LB_STATS_CLR(dhd->cpu_online_cnt[i]);
-		DHD_LB_STATS_CLR(dhd->cpu_offline_cnt[i]);
-	}
-
-	for (i = 0; i < NR_CPUS; i++) {
-		for (j = 0; j < HIST_BIN_SIZE; j++) {
-			DHD_LB_STATS_CLR(dhd->napi_rx_hist[i][j]);
-			DHD_LB_STATS_CLR(dhd->txc_hist[i][j]);
-			DHD_LB_STATS_CLR(dhd->rxc_hist[i][j]);
-		}
-	}
-
-	return;
-}
-
-static void dhd_lb_stats_dump_histo(
-	struct bcmstrbuf *strbuf, uint32 (*hist)[HIST_BIN_SIZE])
-{
-	int i, j;
-	uint32 per_cpu_total[NR_CPUS] = {0};
-	uint32 total = 0;
-
-	bcm_bprintf(strbuf, "CPU: \t\t");
-	for (i = 0; i < num_possible_cpus(); i++)
-		bcm_bprintf(strbuf, "%d\t", i);
-	bcm_bprintf(strbuf, "\nBin\n");
-
-	for (i = 0; i < HIST_BIN_SIZE; i++) {
-		bcm_bprintf(strbuf, "%d:\t\t", 1<<(i+1));
-		for (j = 0; j < num_possible_cpus(); j++) {
-			bcm_bprintf(strbuf, "%d\t", hist[j][i]);
-		}
-		bcm_bprintf(strbuf, "\n");
-	}
-	bcm_bprintf(strbuf, "Per CPU Total \t");
-	total = 0;
-	for (i = 0; i < num_possible_cpus(); i++) {
-		for (j = 0; j < HIST_BIN_SIZE; j++) {
-			per_cpu_total[i] += (hist[i][j] * (1<<(j+1)));
-		}
-		bcm_bprintf(strbuf, "%d\t", per_cpu_total[i]);
-		total += per_cpu_total[i];
-	}
-	bcm_bprintf(strbuf, "\nTotal\t\t%d \n", total);
-
-	return;
-}
-
-static inline void dhd_lb_stats_dump_cpu_array(struct bcmstrbuf *strbuf, uint32 *p)
-{
-	int i;
-
-	bcm_bprintf(strbuf, "CPU: \t");
-	for (i = 0; i < num_possible_cpus(); i++)
-		bcm_bprintf(strbuf, "%d\t", i);
-	bcm_bprintf(strbuf, "\n");
-
-	bcm_bprintf(strbuf, "Val: \t");
-	for (i = 0; i < num_possible_cpus(); i++)
-		bcm_bprintf(strbuf, "%u\t", *(p+i));
-	bcm_bprintf(strbuf, "\n");
-	return;
-}
-
-void dhd_lb_stats_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
-{
-	dhd_info_t *dhd;
-
-	if (dhdp == NULL || strbuf == NULL) {
-		DHD_ERROR(("%s(): Invalid argument dhdp %p strbuf %p \n",
-			__FUNCTION__, dhdp, strbuf));
-		return;
-	}
-
-	dhd = dhdp->info;
-	if (dhd == NULL) {
-		DHD_ERROR(("%s(): DHD pointer is NULL \n", __FUNCTION__));
-		return;
-	}
-
-	bcm_bprintf(strbuf, "\ncpu_online_cnt:\n");
-	dhd_lb_stats_dump_cpu_array(strbuf, dhd->cpu_online_cnt);
-
-	bcm_bprintf(strbuf, "cpu_offline_cnt:\n");
-	dhd_lb_stats_dump_cpu_array(strbuf, dhd->cpu_offline_cnt);
-
-	bcm_bprintf(strbuf, "\nsched_cnt: dhd_dpc %u napi %u rxc %u txc %u\n",
-		dhd->dhd_dpc_cnt, dhd->napi_sched_cnt, dhd->rxc_sched_cnt,
-		dhd->txc_sched_cnt);
-#ifdef DHD_LB_RXP
-	bcm_bprintf(strbuf, "napi_percpu_run_cnt:\n");
-	dhd_lb_stats_dump_cpu_array(strbuf, dhd->napi_percpu_run_cnt);
-	bcm_bprintf(strbuf, "\nNAPI Packets Received Histogram:\n");
-	dhd_lb_stats_dump_histo(strbuf, dhd->napi_rx_hist);
-#endif /* DHD_LB_RXP */
-
-#ifdef DHD_LB_RXC
-	bcm_bprintf(strbuf, "rxc_percpu_run_cnt:\n");
-	dhd_lb_stats_dump_cpu_array(strbuf, dhd->rxc_percpu_run_cnt);
-	bcm_bprintf(strbuf, "\nRX Completions (Buffer Post) Histogram:\n");
-	dhd_lb_stats_dump_histo(strbuf, dhd->rxc_hist);
-#endif /* DHD_LB_RXC */
-
-
-#ifdef DHD_LB_TXC
-	bcm_bprintf(strbuf, "txc_percpu_run_cnt:\n");
-	dhd_lb_stats_dump_cpu_array(strbuf, dhd->txc_percpu_run_cnt);
-	bcm_bprintf(strbuf, "\nTX Completions (Buffer Free) Histogram:\n");
-	dhd_lb_stats_dump_histo(strbuf, dhd->txc_hist);
-#endif /* DHD_LB_TXC */
-}
-
-static void dhd_lb_stats_update_histo(uint32 *bin, uint32 count)
-{
-	uint32 bin_power;
-	uint32 *p = NULL;
-
-	bin_power = next_larger_power2(count);
-
-	switch (bin_power) {
-		case   0: break;
-		case   1: /* Fall through intentionally */
-		case   2: p = bin + 0; break;
-		case   4: p = bin + 1; break;
-		case   8: p = bin + 2; break;
-		case  16: p = bin + 3; break;
-		case  32: p = bin + 4; break;
-		case  64: p = bin + 5; break;
-		case 128: p = bin + 6; break;
-		default : p = bin + 7; break;
-	}
-	if (p)
-		*p = *p + 1;
-	return;
-}
-
-extern void dhd_lb_stats_update_napi_histo(dhd_pub_t *dhdp, uint32 count)
-{
-	int cpu;
-	dhd_info_t *dhd = dhdp->info;
-
-	cpu = get_cpu();
-	put_cpu();
-	dhd_lb_stats_update_histo(&dhd->napi_rx_hist[cpu][0], count);
-
-	return;
-}
-
-extern void dhd_lb_stats_update_txc_histo(dhd_pub_t *dhdp, uint32 count)
-{
-	int cpu;
-	dhd_info_t *dhd = dhdp->info;
-
-	cpu = get_cpu();
-	put_cpu();
-	dhd_lb_stats_update_histo(&dhd->txc_hist[cpu][0], count);
-
-	return;
-}
-
-extern void dhd_lb_stats_update_rxc_histo(dhd_pub_t *dhdp, uint32 count)
-{
-	int cpu;
-	dhd_info_t *dhd = dhdp->info;
-
-	cpu = get_cpu();
-	put_cpu();
-	dhd_lb_stats_update_histo(&dhd->rxc_hist[cpu][0], count);
-
-	return;
-}
-
-extern void dhd_lb_stats_txc_percpu_cnt_incr(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd = dhdp->info;
-	DHD_LB_STATS_PERCPU_ARR_INCR(dhd->txc_percpu_run_cnt);
-}
-
-extern void dhd_lb_stats_rxc_percpu_cnt_incr(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd = dhdp->info;
-	DHD_LB_STATS_PERCPU_ARR_INCR(dhd->rxc_percpu_run_cnt);
-}
-
-#endif /* DHD_LB_STATS */
-#endif /* DHD_LB */
-
-
-#if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
-int g_frameburst = 1;
-#endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
-
-static int dhd_get_pend_8021x_cnt(dhd_info_t *dhd);
-
-/* DHD Perimiter lock only used in router with bypass forwarding. */
-#define DHD_PERIM_RADIO_INIT()              do { /* noop */ } while (0)
-#define DHD_PERIM_LOCK_TRY(unit, flag)      do { /* noop */ } while (0)
-#define DHD_PERIM_UNLOCK_TRY(unit, flag)    do { /* noop */ } while (0)
-
-#ifdef PCIE_FULL_DONGLE
-#if defined(BCM_GMAC3)
-#define DHD_IF_STA_LIST_LOCK_INIT(ifp)      do { /* noop */ } while (0)
-#define DHD_IF_STA_LIST_LOCK(ifp, flags)    ({ BCM_REFERENCE(flags); })
-#define DHD_IF_STA_LIST_UNLOCK(ifp, flags)  ({ BCM_REFERENCE(flags); })
-
-#if defined(DHD_IGMP_UCQUERY) || defined(DHD_UCAST_UPNP)
-#define DHD_IF_WMF_UCFORWARD_LOCK(dhd, ifp, slist) ({ BCM_REFERENCE(slist); &(ifp)->sta_list; })
-#define DHD_IF_WMF_UCFORWARD_UNLOCK(dhd, slist) ({ BCM_REFERENCE(slist); })
-#endif /* DHD_IGMP_UCQUERY || DHD_UCAST_UPNP */
-
-#else /* ! BCM_GMAC3 */
-#define DHD_IF_STA_LIST_LOCK_INIT(ifp) spin_lock_init(&(ifp)->sta_list_lock)
-#define DHD_IF_STA_LIST_LOCK(ifp, flags) \
-	spin_lock_irqsave(&(ifp)->sta_list_lock, (flags))
-#define DHD_IF_STA_LIST_UNLOCK(ifp, flags) \
-	spin_unlock_irqrestore(&(ifp)->sta_list_lock, (flags))
-
-#if defined(DHD_IGMP_UCQUERY) || defined(DHD_UCAST_UPNP)
-static struct list_head * dhd_sta_list_snapshot(dhd_info_t *dhd, dhd_if_t *ifp,
-	struct list_head *snapshot_list);
-static void dhd_sta_list_snapshot_free(dhd_info_t *dhd, struct list_head *snapshot_list);
-#define DHD_IF_WMF_UCFORWARD_LOCK(dhd, ifp, slist) ({ dhd_sta_list_snapshot(dhd, ifp, slist); })
-#define DHD_IF_WMF_UCFORWARD_UNLOCK(dhd, slist) ({ dhd_sta_list_snapshot_free(dhd, slist); })
-#endif /* DHD_IGMP_UCQUERY || DHD_UCAST_UPNP */
-
-#endif /* ! BCM_GMAC3 */
-#endif /* PCIE_FULL_DONGLE */
-
-/* Control fw roaming */
-uint dhd_roam_disable = 0;
-
-#ifdef BCMDBGFS
-extern int dhd_dbg_init(dhd_pub_t *dhdp);
-extern void dhd_dbg_remove(void);
-#endif
-
-/* Control radio state */
-uint dhd_radio_up = 1;
-
-/* Network inteface name */
-char iface_name[IFNAMSIZ] = {'\0'};
-module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
-
-/* The following are specific to the SDIO dongle */
-
-/* IOCTL response timeout */
-int dhd_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
-
-/* Idle timeout for backplane clock */
-int dhd_idletime = DHD_IDLETIME_TICKS;
-module_param(dhd_idletime, int, 0);
-
-/* Use polling */
-uint dhd_poll = FALSE;
-module_param(dhd_poll, uint, 0);
-
-/* Use interrupts */
-uint dhd_intr = TRUE;
-module_param(dhd_intr, uint, 0);
-
-/* SDIO Drive Strength (in milliamps) */
-uint dhd_sdiod_drive_strength = 6;
-module_param(dhd_sdiod_drive_strength, uint, 0);
-
-#ifdef BCMSDIO
-/* Tx/Rx bounds */
-extern uint dhd_txbound;
-extern uint dhd_rxbound;
-module_param(dhd_txbound, uint, 0);
-module_param(dhd_rxbound, uint, 0);
-
-/* Deferred transmits */
-extern uint dhd_deferred_tx;
-module_param(dhd_deferred_tx, uint, 0);
-
-#endif /* BCMSDIO */
-
-
-#ifdef SDTEST
-/* Echo packet generator (pkts/s) */
-uint dhd_pktgen = 0;
-module_param(dhd_pktgen, uint, 0);
-
-/* Echo packet len (0 => sawtooth, max 2040) */
-uint dhd_pktgen_len = 0;
-module_param(dhd_pktgen_len, uint, 0);
-#endif /* SDTEST */
-
-
-
-/* Allow delayed firmware download for debug purpose */
-int allow_delay_fwdl = FALSE;
-module_param(allow_delay_fwdl, int, 0);
-
-extern char dhd_version[];
-extern char fw_version[];
-
-int dhd_net_bus_devreset(struct net_device *dev, uint8 flag);
-static void dhd_net_if_lock_local(dhd_info_t *dhd);
-static void dhd_net_if_unlock_local(dhd_info_t *dhd);
-static void dhd_suspend_lock(dhd_pub_t *dhdp);
-static void dhd_suspend_unlock(dhd_pub_t *dhdp);
-
-#ifdef WLMEDIA_HTSF
-void htsf_update(dhd_info_t *dhd, void *data);
-tsf_t prev_tsf, cur_tsf;
-
-uint32 dhd_get_htsf(dhd_info_t *dhd, int ifidx);
-static int dhd_ioctl_htsf_get(dhd_info_t *dhd, int ifidx);
-static void dhd_dump_latency(void);
-static void dhd_htsf_addtxts(dhd_pub_t *dhdp, void *pktbuf);
-static void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf);
-static void dhd_dump_htsfhisto(histo_t *his, char *s);
-#endif /* WLMEDIA_HTSF */
-
-/* Monitor interface */
-int dhd_monitor_init(void *dhd_pub);
-int dhd_monitor_uninit(void);
-
-
-#if defined(WL_WIRELESS_EXT)
-struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
-#endif /* defined(WL_WIRELESS_EXT) */
-
-static void dhd_dpc(ulong data);
-/* forward decl */
-extern int dhd_wait_pend8021x(struct net_device *dev);
-void dhd_os_wd_timer_extend(void *bus, bool extend);
-
-#ifdef TOE
-#ifndef BDC
-#error TOE requires BDC
-#endif /* !BDC */
-static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol);
-static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol);
-#endif /* TOE */
-
-static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, size_t pktlen,
-                             wl_event_msg_t *event_ptr, void **data_ptr);
-
-#if defined(CONFIG_PM_SLEEP)
-static int dhd_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored)
-{
-	int ret = NOTIFY_DONE;
-	bool suspend = FALSE;
-	dhd_info_t *dhdinfo = (dhd_info_t*)container_of(nfb, struct dhd_info, pm_notifier);
-
-	BCM_REFERENCE(dhdinfo);
-
-	switch (action) {
-	case PM_HIBERNATION_PREPARE:
-	case PM_SUSPEND_PREPARE:
-		suspend = TRUE;
-		break;
-
-	case PM_POST_HIBERNATION:
-	case PM_POST_SUSPEND:
-		suspend = FALSE;
-		break;
-	}
-
-#if defined(SUPPORT_P2P_GO_PS)
-#ifdef PROP_TXSTATUS
-	if (suspend) {
-		DHD_OS_WAKE_LOCK_WAIVE(&dhdinfo->pub);
-		dhd_wlfc_suspend(&dhdinfo->pub);
-		DHD_OS_WAKE_LOCK_RESTORE(&dhdinfo->pub);
-	} else
-		dhd_wlfc_resume(&dhdinfo->pub);
-#endif /* PROP_TXSTATUS */
-#endif /* defined(SUPPORT_P2P_GO_PS) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
-	KERNEL_VERSION(2, 6, 39))
-	dhd_mmc_suspend = suspend;
-	smp_mb();
-#endif
-
-	return ret;
-}
-
-/* to make sure we won't register the same notifier twice, otherwise a loop is likely to be
- * created in kernel notifier link list (with 'next' pointing to itself)
- */
-static bool dhd_pm_notifier_registered = FALSE;
-
-extern int register_pm_notifier(struct notifier_block *nb);
-extern int unregister_pm_notifier(struct notifier_block *nb);
-#endif /* CONFIG_PM_SLEEP */
-
-/* Request scheduling of the bus rx frame */
-static void dhd_sched_rxf(dhd_pub_t *dhdp, void *skb);
-static void dhd_os_rxflock(dhd_pub_t *pub);
-static void dhd_os_rxfunlock(dhd_pub_t *pub);
-
-/** priv_link is the link between netdev and the dhdif and dhd_info structs. */
-typedef struct dhd_dev_priv {
-	dhd_info_t * dhd; /* cached pointer to dhd_info in netdevice priv */
-	dhd_if_t   * ifp; /* cached pointer to dhd_if in netdevice priv */
-	int          ifidx; /* interface index */
-} dhd_dev_priv_t;
-
-#define DHD_DEV_PRIV_SIZE       (sizeof(dhd_dev_priv_t))
-#define DHD_DEV_PRIV(dev)       ((dhd_dev_priv_t *)DEV_PRIV(dev))
-#define DHD_DEV_INFO(dev)       (((dhd_dev_priv_t *)DEV_PRIV(dev))->dhd)
-#define DHD_DEV_IFP(dev)        (((dhd_dev_priv_t *)DEV_PRIV(dev))->ifp)
-#define DHD_DEV_IFIDX(dev)      (((dhd_dev_priv_t *)DEV_PRIV(dev))->ifidx)
-
-/** Clear the dhd net_device's private structure. */
-static inline void
-dhd_dev_priv_clear(struct net_device * dev)
-{
-	dhd_dev_priv_t * dev_priv;
-	ASSERT(dev != (struct net_device *)NULL);
-	dev_priv = DHD_DEV_PRIV(dev);
-	dev_priv->dhd = (dhd_info_t *)NULL;
-	dev_priv->ifp = (dhd_if_t *)NULL;
-	dev_priv->ifidx = DHD_BAD_IF;
-}
-
-/** Setup the dhd net_device's private structure. */
-static inline void
-dhd_dev_priv_save(struct net_device * dev, dhd_info_t * dhd, dhd_if_t * ifp,
-                  int ifidx)
-{
-	dhd_dev_priv_t * dev_priv;
-	ASSERT(dev != (struct net_device *)NULL);
-	dev_priv = DHD_DEV_PRIV(dev);
-	dev_priv->dhd = dhd;
-	dev_priv->ifp = ifp;
-	dev_priv->ifidx = ifidx;
-}
-
-#ifdef PCIE_FULL_DONGLE
-
-/** Dummy objects are defined with state representing bad|down.
- * Performance gains from reducing branch conditionals, instruction parallelism,
- * dual issue, reducing load shadows, avail of larger pipelines.
- * Use DHD_XXX_NULL instead of (dhd_xxx_t *)NULL, whenever an object pointer
- * is accessed via the dhd_sta_t.
- */
-
-/* Dummy dhd_info object */
-dhd_info_t dhd_info_null = {
-#if defined(BCM_GMAC3)
-	.fwdh = FWDER_NULL,
-#endif
-	.pub = {
-	         .info = &dhd_info_null,
-#ifdef DHDTCPACK_SUPPRESS
-	         .tcpack_sup_mode = TCPACK_SUP_REPLACE,
-#endif /* DHDTCPACK_SUPPRESS */
-	         .up = FALSE,
-	         .busstate = DHD_BUS_DOWN
-	}
-};
-#define DHD_INFO_NULL (&dhd_info_null)
-#define DHD_PUB_NULL  (&dhd_info_null.pub)
-
-/* Dummy netdevice object */
-struct net_device dhd_net_dev_null = {
-	.reg_state = NETREG_UNREGISTERED
-};
-#define DHD_NET_DEV_NULL (&dhd_net_dev_null)
-
-/* Dummy dhd_if object */
-dhd_if_t dhd_if_null = {
-#if defined(BCM_GMAC3)
-	.fwdh = FWDER_NULL,
-#endif
-#ifdef WMF
-	.wmf = { .wmf_enable = TRUE },
-#endif
-	.info = DHD_INFO_NULL,
-	.net = DHD_NET_DEV_NULL,
-	.idx = DHD_BAD_IF
-};
-#define DHD_IF_NULL  (&dhd_if_null)
-
-#define DHD_STA_NULL ((dhd_sta_t *)NULL)
-
-/** Interface STA list management. */
-
-/** Fetch the dhd_if object, given the interface index in the dhd. */
-static inline dhd_if_t *dhd_get_ifp(dhd_pub_t *dhdp, uint32 ifidx);
-
-/** Alloc/Free a dhd_sta object from the dhd instances' sta_pool. */
-static void dhd_sta_free(dhd_pub_t *pub, dhd_sta_t *sta);
-static dhd_sta_t * dhd_sta_alloc(dhd_pub_t * dhdp);
-
-/* Delete a dhd_sta or flush all dhd_sta in an interface's sta_list. */
-static void dhd_if_del_sta_list(dhd_if_t * ifp);
-static void	dhd_if_flush_sta(dhd_if_t * ifp);
-
-/* Construct/Destruct a sta pool. */
-static int dhd_sta_pool_init(dhd_pub_t *dhdp, int max_sta);
-static void dhd_sta_pool_fini(dhd_pub_t *dhdp, int max_sta);
-/* Clear the pool of dhd_sta_t objects for built-in type driver */
-static void dhd_sta_pool_clear(dhd_pub_t *dhdp, int max_sta);
-
-
-/* Return interface pointer */
-static inline dhd_if_t *dhd_get_ifp(dhd_pub_t *dhdp, uint32 ifidx)
-{
-	ASSERT(ifidx < DHD_MAX_IFS);
-
-	if (ifidx >= DHD_MAX_IFS)
-		return NULL;
-
-	return dhdp->info->iflist[ifidx];
-}
-
-/** Reset a dhd_sta object and free into the dhd pool. */
-static void
-dhd_sta_free(dhd_pub_t * dhdp, dhd_sta_t * sta)
-{
-	int prio;
-
-	ASSERT((sta != DHD_STA_NULL) && (sta->idx != ID16_INVALID));
-
-	ASSERT((dhdp->staid_allocator != NULL) && (dhdp->sta_pool != NULL));
-
-	/*
-	 * Flush and free all packets in all flowring's queues belonging to sta.
-	 * Packets in flow ring will be flushed later.
-	 */
-	for (prio = 0; prio < (int)NUMPRIO; prio++) {
-		uint16 flowid = sta->flowid[prio];
-
-		if (flowid != FLOWID_INVALID) {
-			unsigned long flags;
-			flow_queue_t * queue = dhd_flow_queue(dhdp, flowid);
-			flow_ring_node_t * flow_ring_node;
-
-#ifdef DHDTCPACK_SUPPRESS
-			/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
-			 * when there is a newly coming packet from network stack.
-			 */
-			dhd_tcpack_info_tbl_clean(dhdp);
-#endif /* DHDTCPACK_SUPPRESS */
-
-			flow_ring_node = dhd_flow_ring_node(dhdp, flowid);
-			DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-			flow_ring_node->status = FLOW_RING_STATUS_STA_FREEING;
-
-			if (!DHD_FLOW_QUEUE_EMPTY(queue)) {
-				void * pkt;
-				while ((pkt = dhd_flow_queue_dequeue(dhdp, queue)) != NULL) {
-					PKTFREE(dhdp->osh, pkt, TRUE);
-				}
-			}
-
-			DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-			ASSERT(DHD_FLOW_QUEUE_EMPTY(queue));
-		}
-
-		sta->flowid[prio] = FLOWID_INVALID;
-	}
-
-	id16_map_free(dhdp->staid_allocator, sta->idx);
-	DHD_CUMM_CTR_INIT(&sta->cumm_ctr);
-	sta->ifp = DHD_IF_NULL; /* dummy dhd_if object */
-	sta->ifidx = DHD_BAD_IF;
-	bzero(sta->ea.octet, ETHER_ADDR_LEN);
-	INIT_LIST_HEAD(&sta->list);
-	sta->idx = ID16_INVALID; /* implying free */
-}
-
-/** Allocate a dhd_sta object from the dhd pool. */
-static dhd_sta_t *
-dhd_sta_alloc(dhd_pub_t * dhdp)
-{
-	uint16 idx;
-	dhd_sta_t * sta;
-	dhd_sta_pool_t * sta_pool;
-
-	ASSERT((dhdp->staid_allocator != NULL) && (dhdp->sta_pool != NULL));
-
-	idx = id16_map_alloc(dhdp->staid_allocator);
-	if (idx == ID16_INVALID) {
-		DHD_ERROR(("%s: cannot get free staid\n", __FUNCTION__));
-		return DHD_STA_NULL;
-	}
-
-	sta_pool = (dhd_sta_pool_t *)(dhdp->sta_pool);
-	sta = &sta_pool[idx];
-
-	ASSERT((sta->idx == ID16_INVALID) &&
-	       (sta->ifp == DHD_IF_NULL) && (sta->ifidx == DHD_BAD_IF));
-
-	DHD_CUMM_CTR_INIT(&sta->cumm_ctr);
-
-	sta->idx = idx; /* implying allocated */
-
-	return sta;
-}
-
-/** Delete all STAs in an interface's STA list. */
-static void
-dhd_if_del_sta_list(dhd_if_t *ifp)
-{
-	dhd_sta_t *sta, *next;
-	unsigned long flags;
-
-	DHD_IF_STA_LIST_LOCK(ifp, flags);
-
-	list_for_each_entry_safe(sta, next, &ifp->sta_list, list) {
-#if defined(BCM_GMAC3)
-		if (ifp->fwdh) {
-			/* Remove sta from WOFA forwarder. */
-			fwder_deassoc(ifp->fwdh, (uint16 *)(sta->ea.octet), (wofa_t)sta);
-		}
-#endif /* BCM_GMAC3 */
-		list_del(&sta->list);
-		dhd_sta_free(&ifp->info->pub, sta);
-	}
-
-	DHD_IF_STA_LIST_UNLOCK(ifp, flags);
-
-	return;
-}
-
-/** Router/GMAC3: Flush all station entries in the forwarder's WOFA database. */
-static void
-dhd_if_flush_sta(dhd_if_t * ifp)
-{
-#if defined(BCM_GMAC3)
-
-	if (ifp && (ifp->fwdh != FWDER_NULL)) {
-		dhd_sta_t *sta, *next;
-		unsigned long flags;
-
-		DHD_IF_STA_LIST_LOCK(ifp, flags);
-
-		list_for_each_entry_safe(sta, next, &ifp->sta_list, list) {
-			/* Remove any sta entry from WOFA forwarder. */
-			fwder_flush(ifp->fwdh, (wofa_t)sta);
-		}
-
-		DHD_IF_STA_LIST_UNLOCK(ifp, flags);
-	}
-#endif /* BCM_GMAC3 */
-}
-
-/** Construct a pool of dhd_sta_t objects to be used by interfaces. */
-static int
-dhd_sta_pool_init(dhd_pub_t *dhdp, int max_sta)
-{
-	int idx, prio, sta_pool_memsz;
-	dhd_sta_t * sta;
-	dhd_sta_pool_t * sta_pool;
-	void * staid_allocator;
-
-	ASSERT(dhdp != (dhd_pub_t *)NULL);
-	ASSERT((dhdp->staid_allocator == NULL) && (dhdp->sta_pool == NULL));
-
-	/* dhd_sta objects per radio are managed in a table. id#0 reserved. */
-	staid_allocator = id16_map_init(dhdp->osh, max_sta, 1);
-	if (staid_allocator == NULL) {
-		DHD_ERROR(("%s: sta id allocator init failure\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	/* Pre allocate a pool of dhd_sta objects (one extra). */
-	sta_pool_memsz = ((max_sta + 1) * sizeof(dhd_sta_t)); /* skip idx 0 */
-	sta_pool = (dhd_sta_pool_t *)MALLOC(dhdp->osh, sta_pool_memsz);
-	if (sta_pool == NULL) {
-		DHD_ERROR(("%s: sta table alloc failure\n", __FUNCTION__));
-		id16_map_fini(dhdp->osh, staid_allocator);
-		return BCME_ERROR;
-	}
-
-	dhdp->sta_pool = sta_pool;
-	dhdp->staid_allocator = staid_allocator;
-
-	/* Initialize all sta(s) for the pre-allocated free pool. */
-	bzero((uchar *)sta_pool, sta_pool_memsz);
-	for (idx = max_sta; idx >= 1; idx--) { /* skip sta_pool[0] */
-		sta = &sta_pool[idx];
-		sta->idx = id16_map_alloc(staid_allocator);
-		ASSERT(sta->idx <= max_sta);
-	}
-	/* Now place them into the pre-allocated free pool. */
-	for (idx = 1; idx <= max_sta; idx++) {
-		sta = &sta_pool[idx];
-		for (prio = 0; prio < (int)NUMPRIO; prio++) {
-			sta->flowid[prio] = FLOWID_INVALID; /* Flow rings do not exist */
-		}
-		dhd_sta_free(dhdp, sta);
-	}
-
-	return BCME_OK;
-}
-
-/** Destruct the pool of dhd_sta_t objects.
- * Caller must ensure that no STA objects are currently associated with an if.
- */
-static void
-dhd_sta_pool_fini(dhd_pub_t *dhdp, int max_sta)
-{
-	dhd_sta_pool_t * sta_pool = (dhd_sta_pool_t *)dhdp->sta_pool;
-
-	if (sta_pool) {
-		int idx;
-		int sta_pool_memsz = ((max_sta + 1) * sizeof(dhd_sta_t));
-		for (idx = 1; idx <= max_sta; idx++) {
-			ASSERT(sta_pool[idx].ifp == DHD_IF_NULL);
-			ASSERT(sta_pool[idx].idx == ID16_INVALID);
-		}
-		MFREE(dhdp->osh, dhdp->sta_pool, sta_pool_memsz);
-		dhdp->sta_pool = NULL;
-	}
-
-	id16_map_fini(dhdp->osh, dhdp->staid_allocator);
-	dhdp->staid_allocator = NULL;
-}
-
-/* Clear the pool of dhd_sta_t objects for built-in type driver */
-static void
-dhd_sta_pool_clear(dhd_pub_t *dhdp, int max_sta)
-{
-	int idx, prio, sta_pool_memsz;
-	dhd_sta_t * sta;
-	dhd_sta_pool_t * sta_pool;
-	void *staid_allocator;
-
-	if (!dhdp) {
-		DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	sta_pool = (dhd_sta_pool_t *)dhdp->sta_pool;
-	staid_allocator = dhdp->staid_allocator;
-
-	if (!sta_pool) {
-		DHD_ERROR(("%s: sta_pool is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	if (!staid_allocator) {
-		DHD_ERROR(("%s: staid_allocator is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	/* clear free pool */
-	sta_pool_memsz = ((max_sta + 1) * sizeof(dhd_sta_t));
-	bzero((uchar *)sta_pool, sta_pool_memsz);
-
-	/* dhd_sta objects per radio are managed in a table. id#0 reserved. */
-	id16_map_clear(staid_allocator, max_sta, 1);
-
-	/* Initialize all sta(s) for the pre-allocated free pool. */
-	for (idx = max_sta; idx >= 1; idx--) { /* skip sta_pool[0] */
-		sta = &sta_pool[idx];
-		sta->idx = id16_map_alloc(staid_allocator);
-		ASSERT(sta->idx <= max_sta);
-	}
-	/* Now place them into the pre-allocated free pool. */
-	for (idx = 1; idx <= max_sta; idx++) {
-		sta = &sta_pool[idx];
-		for (prio = 0; prio < (int)NUMPRIO; prio++) {
-			sta->flowid[prio] = FLOWID_INVALID; /* Flow rings do not exist */
-		}
-		dhd_sta_free(dhdp, sta);
-	}
-}
-
-/** Find STA with MAC address ea in an interface's STA list. */
-dhd_sta_t *
-dhd_find_sta(void *pub, int ifidx, void *ea)
-{
-	dhd_sta_t *sta;
-	dhd_if_t *ifp;
-	unsigned long flags;
-
-	ASSERT(ea != NULL);
-	ifp = dhd_get_ifp((dhd_pub_t *)pub, ifidx);
-	if (ifp == NULL)
-		return DHD_STA_NULL;
-
-	DHD_IF_STA_LIST_LOCK(ifp, flags);
-
-	list_for_each_entry(sta, &ifp->sta_list, list) {
-		if (!memcmp(sta->ea.octet, ea, ETHER_ADDR_LEN)) {
-			DHD_IF_STA_LIST_UNLOCK(ifp, flags);
-			return sta;
-		}
-	}
-
-	DHD_IF_STA_LIST_UNLOCK(ifp, flags);
-
-	return DHD_STA_NULL;
-}
-
-/** Add STA into the interface's STA list. */
-dhd_sta_t *
-dhd_add_sta(void *pub, int ifidx, void *ea)
-{
-	dhd_sta_t *sta;
-	dhd_if_t *ifp;
-	unsigned long flags;
-
-	ASSERT(ea != NULL);
-	ifp = dhd_get_ifp((dhd_pub_t *)pub, ifidx);
-	if (ifp == NULL)
-		return DHD_STA_NULL;
-
-	sta = dhd_sta_alloc((dhd_pub_t *)pub);
-	if (sta == DHD_STA_NULL) {
-		DHD_ERROR(("%s: Alloc failed\n", __FUNCTION__));
-		return DHD_STA_NULL;
-	}
-
-	memcpy(sta->ea.octet, ea, ETHER_ADDR_LEN);
-
-	/* link the sta and the dhd interface */
-	sta->ifp = ifp;
-	sta->ifidx = ifidx;
-	INIT_LIST_HEAD(&sta->list);
-
-	DHD_IF_STA_LIST_LOCK(ifp, flags);
-
-	list_add_tail(&sta->list, &ifp->sta_list);
-
-#if defined(BCM_GMAC3)
-	if (ifp->fwdh) {
-		ASSERT(ISALIGNED(ea, 2));
-		/* Add sta to WOFA forwarder. */
-		fwder_reassoc(ifp->fwdh, (uint16 *)ea, (wofa_t)sta);
-	}
-#endif /* BCM_GMAC3 */
-
-	DHD_IF_STA_LIST_UNLOCK(ifp, flags);
-
-	return sta;
-}
-
-/** Delete STA from the interface's STA list. */
-void
-dhd_del_sta(void *pub, int ifidx, void *ea)
-{
-	dhd_sta_t *sta, *next;
-	dhd_if_t *ifp;
-	unsigned long flags;
-
-	ASSERT(ea != NULL);
-	ifp = dhd_get_ifp((dhd_pub_t *)pub, ifidx);
-	if (ifp == NULL)
-		return;
-
-	DHD_IF_STA_LIST_LOCK(ifp, flags);
-
-	list_for_each_entry_safe(sta, next, &ifp->sta_list, list) {
-		if (!memcmp(sta->ea.octet, ea, ETHER_ADDR_LEN)) {
-#if defined(BCM_GMAC3)
-			if (ifp->fwdh) { /* Found a sta, remove from WOFA forwarder. */
-				ASSERT(ISALIGNED(ea, 2));
-				fwder_deassoc(ifp->fwdh, (uint16 *)ea, (wofa_t)sta);
-			}
-#endif /* BCM_GMAC3 */
-			list_del(&sta->list);
-			dhd_sta_free(&ifp->info->pub, sta);
-		}
-	}
-
-	DHD_IF_STA_LIST_UNLOCK(ifp, flags);
-#ifdef DHD_L2_FILTER
-	if (ifp->parp_enable) {
-		/* clear Proxy ARP cache of specific Ethernet Address */
-		bcm_l2_filter_arp_table_update(((dhd_pub_t*)pub)->osh, ifp->phnd_arp_table, FALSE,
-			ea, FALSE, ((dhd_pub_t*)pub)->tickcnt);
-	}
-#endif /* DHD_L2_FILTER */
-	return;
-}
-
-/** Add STA if it doesn't exist. Not reentrant. */
-dhd_sta_t*
-dhd_findadd_sta(void *pub, int ifidx, void *ea)
-{
-	dhd_sta_t *sta;
-
-	sta = dhd_find_sta(pub, ifidx, ea);
-
-	if (!sta) {
-		/* Add entry */
-		sta = dhd_add_sta(pub, ifidx, ea);
-	}
-
-	return sta;
-}
-
-#if defined(DHD_IGMP_UCQUERY) || defined(DHD_UCAST_UPNP)
-#if !defined(BCM_GMAC3)
-static struct list_head *
-dhd_sta_list_snapshot(dhd_info_t *dhd, dhd_if_t *ifp, struct list_head *snapshot_list)
-{
-	unsigned long flags;
-	dhd_sta_t *sta, *snapshot;
-
-	INIT_LIST_HEAD(snapshot_list);
-
-	DHD_IF_STA_LIST_LOCK(ifp, flags);
-
-	list_for_each_entry(sta, &ifp->sta_list, list) {
-		/* allocate one and add to snapshot */
-		snapshot = (dhd_sta_t *)MALLOC(dhd->pub.osh, sizeof(dhd_sta_t));
-		if (snapshot == NULL) {
-			DHD_ERROR(("%s: Cannot allocate memory\n", __FUNCTION__));
-			continue;
-		}
-
-		memcpy(snapshot->ea.octet, sta->ea.octet, ETHER_ADDR_LEN);
-
-		INIT_LIST_HEAD(&snapshot->list);
-		list_add_tail(&snapshot->list, snapshot_list);
-	}
-
-	DHD_IF_STA_LIST_UNLOCK(ifp, flags);
-
-	return snapshot_list;
-}
-
-static void
-dhd_sta_list_snapshot_free(dhd_info_t *dhd, struct list_head *snapshot_list)
-{
-	dhd_sta_t *sta, *next;
-
-	list_for_each_entry_safe(sta, next, snapshot_list, list) {
-		list_del(&sta->list);
-		MFREE(dhd->pub.osh, sta, sizeof(dhd_sta_t));
-	}
-}
-#endif /* !BCM_GMAC3 */
-#endif /* DHD_IGMP_UCQUERY || DHD_UCAST_UPNP */
-
-#else
-static inline void dhd_if_flush_sta(dhd_if_t * ifp) { }
-static inline void dhd_if_del_sta_list(dhd_if_t *ifp) {}
-static inline int dhd_sta_pool_init(dhd_pub_t *dhdp, int max_sta) { return BCME_OK; }
-static inline void dhd_sta_pool_fini(dhd_pub_t *dhdp, int max_sta) {}
-static inline void dhd_sta_pool_clear(dhd_pub_t *dhdp, int max_sta) {}
-dhd_sta_t *dhd_findadd_sta(void *pub, int ifidx, void *ea) { return NULL; }
-void dhd_del_sta(void *pub, int ifidx, void *ea) {}
-#endif /* PCIE_FULL_DONGLE */
-
-
-#if defined(DHD_LB)
-
-#if defined(DHD_LB_TXC) || defined(DHD_LB_RXC)
-/**
- * dhd_tasklet_schedule - Function that runs in IPI context of the destination
- * CPU and schedules a tasklet.
- * @tasklet: opaque pointer to the tasklet
- */
-static INLINE void
-dhd_tasklet_schedule(void *tasklet)
-{
-	tasklet_schedule((struct tasklet_struct *)tasklet);
-}
-
-/**
- * dhd_tasklet_schedule_on - Executes the passed takslet in a given CPU
- * @tasklet: tasklet to be scheduled
- * @on_cpu: cpu core id
- *
- * If the requested cpu is online, then an IPI is sent to this cpu via the
- * smp_call_function_single with no wait and the tasklet_schedule function
- * will be invoked to schedule the specified tasklet on the requested CPU.
- */
-static void
-dhd_tasklet_schedule_on(struct tasklet_struct *tasklet, int on_cpu)
-{
-	const int wait = 0;
-	smp_call_function_single(on_cpu,
-		dhd_tasklet_schedule, (void *)tasklet, wait);
-}
-#endif /* DHD_LB_TXC || DHD_LB_RXC */
-
-
-#if defined(DHD_LB_TXC)
-/**
- * dhd_lb_tx_compl_dispatch - load balance by dispatching the tx_compl_tasklet
- * on another cpu. The tx_compl_tasklet will take care of DMA unmapping and
- * freeing the packets placed in the tx_compl workq
- */
-void
-dhd_lb_tx_compl_dispatch(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd = dhdp->info;
-	int curr_cpu, on_cpu;
-
-	if (dhd->rx_napi_netdev == NULL) {
-		DHD_ERROR(("%s: dhd->rx_napi_netdev is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	DHD_LB_STATS_INCR(dhd->txc_sched_cnt);
-	/*
-	 * If the destination CPU is NOT online or is same as current CPU
-	 * no need to schedule the work
-	 */
-	curr_cpu = get_cpu();
-	put_cpu();
-
-	on_cpu = atomic_read(&dhd->tx_compl_cpu);
-
-	if ((on_cpu == curr_cpu) || (!cpu_online(on_cpu))) {
-		dhd_tasklet_schedule(&dhd->tx_compl_tasklet);
-	} else {
-		schedule_work(&dhd->tx_compl_dispatcher_work);
-	}
-}
-
-static void dhd_tx_compl_dispatcher_fn(struct work_struct * work)
-{
-	struct dhd_info *dhd =
-		container_of(work, struct dhd_info, tx_compl_dispatcher_work);
-	int cpu;
-
-	get_online_cpus();
-	cpu = atomic_read(&dhd->tx_compl_cpu);
-	if (!cpu_online(cpu))
-		dhd_tasklet_schedule(&dhd->tx_compl_tasklet);
-	else
-		dhd_tasklet_schedule_on(&dhd->tx_compl_tasklet, cpu);
-	put_online_cpus();
-}
-
-#endif /* DHD_LB_TXC */
-
-
-#if defined(DHD_LB_RXC)
-/**
- * dhd_lb_rx_compl_dispatch - load balance by dispatching the rx_compl_tasklet
- * on another cpu. The rx_compl_tasklet will take care of reposting rx buffers
- * in the H2D RxBuffer Post common ring, by using the recycled pktids that were
- * placed in the rx_compl workq.
- *
- * @dhdp: pointer to dhd_pub object
- */
-void
-dhd_lb_rx_compl_dispatch(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd = dhdp->info;
-	int curr_cpu, on_cpu;
-
-	if (dhd->rx_napi_netdev == NULL) {
-		DHD_ERROR(("%s: dhd->rx_napi_netdev is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	DHD_LB_STATS_INCR(dhd->rxc_sched_cnt);
-	/*
-	 * If the destination CPU is NOT online or is same as current CPU
-	 * no need to schedule the work
-	 */
-	curr_cpu = get_cpu();
-	put_cpu();
-
-	on_cpu = atomic_read(&dhd->rx_compl_cpu);
-
-	if ((on_cpu == curr_cpu) || (!cpu_online(on_cpu))) {
-		dhd_tasklet_schedule(&dhd->rx_compl_tasklet);
-	} else {
-		schedule_work(&dhd->rx_compl_dispatcher_work);
-	}
-}
-
-static void dhd_rx_compl_dispatcher_fn(struct work_struct * work)
-{
-	struct dhd_info *dhd =
-		container_of(work, struct dhd_info, rx_compl_dispatcher_work);
-	int cpu;
-
-	get_online_cpus();
-	cpu = atomic_read(&dhd->tx_compl_cpu);
-	if (!cpu_online(cpu))
-		dhd_tasklet_schedule(&dhd->rx_compl_tasklet);
-	else
-		dhd_tasklet_schedule_on(&dhd->rx_compl_tasklet, cpu);
-	put_online_cpus();
-}
-
-#endif /* DHD_LB_RXC */
-
-
-#if defined(DHD_LB_RXP)
-/**
- * dhd_napi_poll - Load balance napi poll function to process received
- * packets and send up the network stack using netif_receive_skb()
- *
- * @napi: napi object in which context this poll function is invoked
- * @budget: number of packets to be processed.
- *
- * Fetch the dhd_info given the rx_napi_struct. Move all packets from the
- * rx_napi_queue into a local rx_process_queue (lock and queue move and unlock).
- * Dequeue each packet from head of rx_process_queue, fetch the ifid from the
- * packet tag and sendup.
- */
-static int
-dhd_napi_poll(struct napi_struct *napi, int budget)
-{
-	int ifid;
-	const int pkt_count = 1;
-	const int chan = 0;
-	struct sk_buff * skb;
-	unsigned long flags;
-	struct dhd_info *dhd;
-	int processed = 0;
-	struct sk_buff_head rx_process_queue;
-
-	dhd = container_of(napi, struct dhd_info, rx_napi_struct);
-	DHD_INFO(("%s napi_queue<%d> budget<%d>\n",
-		__FUNCTION__, skb_queue_len(&dhd->rx_napi_queue), budget));
-
-	__skb_queue_head_init(&rx_process_queue);
-
-	/* extract the entire rx_napi_queue into local rx_process_queue */
-	spin_lock_irqsave(&dhd->rx_napi_queue.lock, flags);
-	skb_queue_splice_tail_init(&dhd->rx_napi_queue, &rx_process_queue);
-	spin_unlock_irqrestore(&dhd->rx_napi_queue.lock, flags);
-
-	while ((skb = __skb_dequeue(&rx_process_queue)) != NULL) {
-		OSL_PREFETCH(skb->data);
-
-		ifid = DHD_PKTTAG_IFID((dhd_pkttag_fr_t *)PKTTAG(skb));
-
-		DHD_INFO(("%s dhd_rx_frame pkt<%p> ifid<%d>\n",
-			__FUNCTION__, skb, ifid));
-
-		dhd_rx_frame(&dhd->pub, ifid, skb, pkt_count, chan);
-		processed++;
-	}
-
-	DHD_LB_STATS_UPDATE_NAPI_HISTO(&dhd->pub, processed);
-
-	DHD_INFO(("%s processed %d\n", __FUNCTION__, processed));
-	napi_complete(napi);
-
-	return budget - 1;
-}
-
-/**
- * dhd_napi_schedule - Place the napi struct into the current cpus softnet napi
- * poll list. This function may be invoked via the smp_call_function_single
- * from a remote CPU.
- *
- * This function will essentially invoke __raise_softirq_irqoff(NET_RX_SOFTIRQ)
- * after the napi_struct is added to the softnet data's poll_list
- *
- * @info: pointer to a dhd_info struct
- */
-static void
-dhd_napi_schedule(void *info)
-{
-	dhd_info_t *dhd = (dhd_info_t *)info;
-
-	DHD_INFO(("%s rx_napi_struct<%p> on cpu<%d>\n",
-		__FUNCTION__, &dhd->rx_napi_struct, atomic_read(&dhd->rx_napi_cpu)));
-
-	/* add napi_struct to softnet data poll list and raise NET_RX_SOFTIRQ */
-	if (napi_schedule_prep(&dhd->rx_napi_struct)) {
-		__napi_schedule(&dhd->rx_napi_struct);
-		DHD_LB_STATS_PERCPU_ARR_INCR(dhd->napi_percpu_run_cnt);
-	}
-
-	/*
-	 * If the rx_napi_struct was already running, then we let it complete
-	 * processing all its packets. The rx_napi_struct may only run on one
-	 * core at a time, to avoid out-of-order handling.
-	 */
-}
-
-/**
- * dhd_napi_schedule_on - API to schedule on a desired CPU core a NET_RX_SOFTIRQ
- * action after placing the dhd's rx_process napi object in the the remote CPU's
- * softnet data's poll_list.
- *
- * @dhd: dhd_info which has the rx_process napi object
- * @on_cpu: desired remote CPU id
- */
-static INLINE int
-dhd_napi_schedule_on(dhd_info_t *dhd, int on_cpu)
-{
-	int wait = 0; /* asynchronous IPI */
-
-	DHD_INFO(("%s dhd<%p> napi<%p> on_cpu<%d>\n",
-		__FUNCTION__, dhd, &dhd->rx_napi_struct, on_cpu));
-
-	if (smp_call_function_single(on_cpu, dhd_napi_schedule, dhd, wait)) {
-		DHD_ERROR(("%s smp_call_function_single on_cpu<%d> failed\n",
-			__FUNCTION__, on_cpu));
-	}
-
-	DHD_LB_STATS_INCR(dhd->napi_sched_cnt);
-
-	return 0;
-}
-
-/*
- * Call get_online_cpus/put_online_cpus around dhd_napi_schedule_on
- * Why should we do this?
- * The candidacy algorithm is run from the call back function
- * registered to CPU hotplug notifier. This call back happens from Worker
- * context. The dhd_napi_schedule_on is also from worker context.
- * Note that both of this can run on two different CPUs at the same time.
- * So we can possibly have a window where a given CPUn is being brought
- * down from CPUm while we try to run a function on CPUn.
- * To prevent this its better have the whole code to execute an SMP
- * function under get_online_cpus.
- * This function call ensures that hotplug mechanism does not kick-in
- * until we are done dealing with online CPUs
- * If the hotplug worker is already running, no worries because the
- * candidacy algo would then reflect the same in dhd->rx_napi_cpu.
- *
- * The below mentioned code structure is proposed in
- * https://www.kernel.org/doc/Documentation/cpu-hotplug.txt
- * for the question
- * Q: I need to ensure that a particular cpu is not removed when there is some
- *    work specific to this cpu is in progress
- *
- * According to the documentation calling get_online_cpus is NOT required, if
- * we are running from tasklet context. Since dhd_rx_napi_dispatcher_fn can
- * run from Work Queue context we have to call these functions
- */
-static void dhd_rx_napi_dispatcher_fn(struct work_struct * work)
-{
-	struct dhd_info *dhd =
-		container_of(work, struct dhd_info, rx_napi_dispatcher_work);
-	int cpu;
-
-	get_online_cpus();
-	cpu = atomic_read(&dhd->rx_napi_cpu);
-	if (!cpu_online(cpu))
-		dhd_napi_schedule(dhd);
-	else
-		dhd_napi_schedule_on(dhd, cpu);
-	put_online_cpus();
-}
-
-/**
- * dhd_lb_rx_napi_dispatch - load balance by dispatching the rx_napi_struct
- * to run on another CPU. The rx_napi_struct's poll function will retrieve all
- * the packets enqueued into the rx_napi_queue and sendup.
- * The producer's rx packet queue is appended to the rx_napi_queue before
- * dispatching the rx_napi_struct.
- */
-void
-dhd_lb_rx_napi_dispatch(dhd_pub_t *dhdp)
-{
-	unsigned long flags;
-	dhd_info_t *dhd = dhdp->info;
-	int curr_cpu;
-	int on_cpu;
-
-	if (dhd->rx_napi_netdev == NULL) {
-		DHD_ERROR(("%s: dhd->rx_napi_netdev is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	DHD_INFO(("%s append napi_queue<%d> pend_queue<%d>\n", __FUNCTION__,
-		skb_queue_len(&dhd->rx_napi_queue), skb_queue_len(&dhd->rx_pend_queue)));
-
-	/* append the producer's queue of packets to the napi's rx process queue */
-	spin_lock_irqsave(&dhd->rx_napi_queue.lock, flags);
-	skb_queue_splice_tail_init(&dhd->rx_pend_queue, &dhd->rx_napi_queue);
-	spin_unlock_irqrestore(&dhd->rx_napi_queue.lock, flags);
-
-	/*
-	 * If the destination CPU is NOT online or is same as current CPU
-	 * no need to schedule the work
-	 */
-	curr_cpu = get_cpu();
-	put_cpu();
-
-	on_cpu = atomic_read(&dhd->rx_napi_cpu);
-
-	if ((on_cpu == curr_cpu) || (!cpu_online(on_cpu))) {
-		dhd_napi_schedule(dhd);
-	} else {
-		schedule_work(&dhd->rx_napi_dispatcher_work);
-	}
-}
-
-/**
- * dhd_lb_rx_pkt_enqueue - Enqueue the packet into the producer's queue
- */
-void
-dhd_lb_rx_pkt_enqueue(dhd_pub_t *dhdp, void *pkt, int ifidx)
-{
-	dhd_info_t *dhd = dhdp->info;
-
-	DHD_INFO(("%s enqueue pkt<%p> ifidx<%d> pend_queue<%d>\n", __FUNCTION__,
-		pkt, ifidx, skb_queue_len(&dhd->rx_pend_queue)));
-	DHD_PKTTAG_SET_IFID((dhd_pkttag_fr_t *)PKTTAG(pkt), ifidx);
-	__skb_queue_tail(&dhd->rx_pend_queue, pkt);
-}
-#endif /* DHD_LB_RXP */
-
-#endif /* DHD_LB */
-
-static void dhd_memdump_work_handler(struct work_struct * work)
-{
-	struct dhd_info *dhd =
-		container_of(work, struct dhd_info, dhd_memdump_work.work);
-
-	BCM_REFERENCE(dhd);
-#ifdef BCMPCIE
-	dhd_prot_collect_memdump(&dhd->pub);
-#endif
-}
-
-
-/** Returns dhd iflist index corresponding the the bssidx provided by apps */
-int dhd_bssidx2idx(dhd_pub_t *dhdp, uint32 bssidx)
-{
-	dhd_if_t *ifp;
-	dhd_info_t *dhd = dhdp->info;
-	int i;
-
-	ASSERT(bssidx < DHD_MAX_IFS);
-	ASSERT(dhdp);
-
-	for (i = 0; i < DHD_MAX_IFS; i++) {
-		ifp = dhd->iflist[i];
-		if (ifp && (ifp->bssidx == bssidx)) {
-			DHD_TRACE(("Index manipulated for %s from %d to %d\n",
-				ifp->name, bssidx, i));
-			break;
-		}
-	}
-	return i;
-}
-
-static inline int dhd_rxf_enqueue(dhd_pub_t *dhdp, void* skb)
-{
-	uint32 store_idx;
-	uint32 sent_idx;
-
-	if (!skb) {
-		DHD_ERROR(("dhd_rxf_enqueue: NULL skb!!!\n"));
-		return BCME_ERROR;
-	}
-
-	dhd_os_rxflock(dhdp);
-	store_idx = dhdp->store_idx;
-	sent_idx = dhdp->sent_idx;
-	if (dhdp->skbbuf[store_idx] != NULL) {
-		/* Make sure the previous packets are processed */
-		dhd_os_rxfunlock(dhdp);
-#ifdef RXF_DEQUEUE_ON_BUSY
-		DHD_TRACE(("dhd_rxf_enqueue: pktbuf not consumed %p, store idx %d sent idx %d\n",
-			skb, store_idx, sent_idx));
-		return BCME_BUSY;
-#else /* RXF_DEQUEUE_ON_BUSY */
-		DHD_ERROR(("dhd_rxf_enqueue: pktbuf not consumed %p, store idx %d sent idx %d\n",
-			skb, store_idx, sent_idx));
-		/* removed msleep here, should use wait_event_timeout if we
-		 * want to give rx frame thread a chance to run
-		 */
-#if defined(WAIT_DEQUEUE)
-		OSL_SLEEP(1);
-#endif
-		return BCME_ERROR;
-#endif /* RXF_DEQUEUE_ON_BUSY */
-	}
-	DHD_TRACE(("dhd_rxf_enqueue: Store SKB %p. idx %d -> %d\n",
-		skb, store_idx, (store_idx + 1) & (MAXSKBPEND - 1)));
-	dhdp->skbbuf[store_idx] = skb;
-	dhdp->store_idx = (store_idx + 1) & (MAXSKBPEND - 1);
-	dhd_os_rxfunlock(dhdp);
-
-	return BCME_OK;
-}
-
-static inline void* dhd_rxf_dequeue(dhd_pub_t *dhdp)
-{
-	uint32 store_idx;
-	uint32 sent_idx;
-	void *skb;
-
-	dhd_os_rxflock(dhdp);
-
-	store_idx = dhdp->store_idx;
-	sent_idx = dhdp->sent_idx;
-	skb = dhdp->skbbuf[sent_idx];
-
-	if (skb == NULL) {
-		dhd_os_rxfunlock(dhdp);
-		DHD_ERROR(("dhd_rxf_dequeue: Dequeued packet is NULL, store idx %d sent idx %d\n",
-			store_idx, sent_idx));
-		return NULL;
-	}
-
-	dhdp->skbbuf[sent_idx] = NULL;
-	dhdp->sent_idx = (sent_idx + 1) & (MAXSKBPEND - 1);
-
-	DHD_TRACE(("dhd_rxf_dequeue: netif_rx_ni(%p), sent idx %d\n",
-		skb, sent_idx));
-
-	dhd_os_rxfunlock(dhdp);
-
-	return skb;
-}
-
-int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost)
-{
-	dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
-
-	if (prepost) { /* pre process */
-		dhd_read_macaddr(dhd);
-	} else { /* post process */
-		dhd_write_macaddr(&dhd->pub.mac);
-	}
-
-	return 0;
-}
-
-#if defined(PKT_FILTER_SUPPORT) && !defined(GAN_LITE_NAT_KEEPALIVE_FILTER)
-static bool
-_turn_on_arp_filter(dhd_pub_t *dhd, int op_mode)
-{
-	bool _apply = FALSE;
-	/* In case of IBSS mode, apply arp pkt filter */
-	if (op_mode & DHD_FLAG_IBSS_MODE) {
-		_apply = TRUE;
-		goto exit;
-	}
-	/* In case of P2P GO or GC, apply pkt filter to pass arp pkt to host */
-	if ((dhd->arp_version == 1) &&
-		(op_mode & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE))) {
-		_apply = TRUE;
-		goto exit;
-	}
-
-exit:
-	return _apply;
-}
-#endif /* PKT_FILTER_SUPPORT && !GAN_LITE_NAT_KEEPALIVE_FILTER */
-
-void dhd_set_packet_filter(dhd_pub_t *dhd)
-{
-#ifdef PKT_FILTER_SUPPORT
-	int i;
-
-	DHD_TRACE(("%s: enter\n", __FUNCTION__));
-	if (dhd_pkt_filter_enable) {
-		for (i = 0; i < dhd->pktfilter_count; i++) {
-			dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
-		}
-	}
-#endif /* PKT_FILTER_SUPPORT */
-}
-
-void dhd_enable_packet_filter(int value, dhd_pub_t *dhd)
-{
-#ifdef PKT_FILTER_SUPPORT
-	int i;
-
-	DHD_ERROR(("%s: enter, value = %d\n", __FUNCTION__, value));
-
-	if ((dhd->op_mode & DHD_FLAG_HOSTAP_MODE) && value) {
-		DHD_ERROR(("%s: DHD_FLAG_HOSTAP_MODE\n", __FUNCTION__));
-		return;
-	}
-	/* 1 - Enable packet filter, only allow unicast packet to send up */
-	/* 0 - Disable packet filter */
-	if (dhd_pkt_filter_enable && (!value ||
-	    (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress)))
-	    {
-		for (i = 0; i < dhd->pktfilter_count; i++) {
-#ifndef GAN_LITE_NAT_KEEPALIVE_FILTER
-			if (value && (i == DHD_ARP_FILTER_NUM) &&
-				!_turn_on_arp_filter(dhd, dhd->op_mode)) {
-				DHD_TRACE(("Do not turn on ARP white list pkt filter:"
-					"val %d, cnt %d, op_mode 0x%x\n",
-					value, i, dhd->op_mode));
-				continue;
-			}
-#endif /* !GAN_LITE_NAT_KEEPALIVE_FILTER */
-			dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
-				value, dhd_master_mode);
-		}
-	}
-#endif /* PKT_FILTER_SUPPORT */
-}
-
-static int dhd_set_suspend(int value, dhd_pub_t *dhd)
-{
-#ifndef SUPPORT_PM2_ONLY
-	int power_mode = PM_MAX;
-#endif /* SUPPORT_PM2_ONLY */
-#ifdef SUPPORT_SENSORHUB
-	uint32 shub_msreq;
-#endif /* SUPPORT_SENSORHUB */
-	/* wl_pkt_filter_enable_t	enable_parm; */
-	char iovbuf[32];
-	int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */
-#ifdef DHD_USE_EARLYSUSPEND
-#ifdef CUSTOM_BCN_TIMEOUT_IN_SUSPEND
-	int bcn_timeout = 0;
-#endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND */
-#ifdef CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND
-	int roam_time_thresh = 0;	/* (ms) */
-#endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */
-#ifndef ENABLE_FW_ROAM_SUSPEND
-	uint roamvar = 1;
-#endif /* ENABLE_FW_ROAM_SUSPEND */
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
-	int bcn_li_bcn;
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
-	uint nd_ra_filter = 0;
-	int ret = 0;
-#endif /* DHD_USE_EARLYSUSPEND */
-#ifdef PASS_ALL_MCAST_PKTS
-	struct dhd_info *dhdinfo;
-	uint32 allmulti;
-	uint i;
-#endif /* PASS_ALL_MCAST_PKTS */
-#ifdef DYNAMIC_SWOOB_DURATION
-#ifndef CUSTOM_INTR_WIDTH
-#define CUSTOM_INTR_WIDTH 100
-	int intr_width = 0;
-#endif /* CUSTOM_INTR_WIDTH */
-#endif /* DYNAMIC_SWOOB_DURATION */
-	if (!dhd)
-		return -ENODEV;
-
-#ifdef PASS_ALL_MCAST_PKTS
-	dhdinfo = dhd->info;
-#endif /* PASS_ALL_MCAST_PKTS */
-
-	DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n",
-		__FUNCTION__, value, dhd->in_suspend));
-
-	dhd_suspend_lock(dhd);
-
-#ifdef CUSTOM_SET_CPUCORE
-	DHD_TRACE(("%s set cpucore(suspend%d)\n", __FUNCTION__, value));
-	/* set specific cpucore */
-	dhd_set_cpucore(dhd, TRUE);
-#endif /* CUSTOM_SET_CPUCORE */
-	if (dhd->up) {
-		if (value && dhd->in_suspend) {
-#ifdef PKT_FILTER_SUPPORT
-				dhd->early_suspended = 1;
-#endif
-				/* Kernel suspended */
-				DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__));
-
-#ifdef SUPPORT_SENSORHUB
-			shub_msreq = 1;
-			if (dhd->info->shub_enable == 1) {
-				bcm_mkiovar("shub_msreq", (char *)&shub_msreq, 4,
-					iovbuf, sizeof(iovbuf));
-				if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
-					iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-					DHD_ERROR(("%s Sensor Hub move/stop start: failed %d\n",
-						__FUNCTION__, ret));
-				}
-			}
-#endif /* SUPPORT_SENSORHUB */
-
-#ifndef SUPPORT_PM2_ONLY
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
-				                 sizeof(power_mode), TRUE, 0);
-#endif /* SUPPORT_PM2_ONLY */
-
-#ifdef PKT_FILTER_SUPPORT
-				/* Enable packet filter,
-				 * only allow unicast packet to send up
-				 */
-				dhd_enable_packet_filter(1, dhd);
-#endif /* PKT_FILTER_SUPPORT */
-
-#ifdef PASS_ALL_MCAST_PKTS
-				allmulti = 0;
-				bcm_mkiovar("allmulti", (char *)&allmulti, 4,
-					iovbuf, sizeof(iovbuf));
-				for (i = 0; i < DHD_MAX_IFS; i++) {
-					if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net)
-						dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-							sizeof(iovbuf), TRUE, i);
-				}
-#endif /* PASS_ALL_MCAST_PKTS */
-
-				/* If DTIM skip is set up as default, force it to wake
-				 * each third DTIM for better power savings.  Note that
-				 * one side effect is a chance to miss BC/MC packet.
-				 */
-#ifdef WLTDLS
-				/* Do not set bcn_li_ditm on WFD mode */
-				if (dhd->tdls_mode) {
-					bcn_li_dtim = 0;
-				} else
-#endif /* WLTDLS */
-				bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd);
-				bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
-					4, iovbuf, sizeof(iovbuf));
-				if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf),
-					TRUE, 0) < 0)
-					DHD_ERROR(("%s: set dtim failed\n", __FUNCTION__));
-
-#ifdef DHD_USE_EARLYSUSPEND
-#ifdef CUSTOM_BCN_TIMEOUT_IN_SUSPEND
-				bcn_timeout = CUSTOM_BCN_TIMEOUT_IN_SUSPEND;
-				bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout,
-					4, iovbuf, sizeof(iovbuf));
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND */
-#ifdef CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND
-				roam_time_thresh = CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND;
-				bcm_mkiovar("roam_time_thresh", (char *)&roam_time_thresh,
-					4, iovbuf, sizeof(iovbuf));
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */
-#ifndef ENABLE_FW_ROAM_SUSPEND
-				/* Disable firmware roaming during suspend */
-				bcm_mkiovar("roam_off", (char *)&roamvar, 4,
-					iovbuf, sizeof(iovbuf));
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* ENABLE_FW_ROAM_SUSPEND */
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
-				bcn_li_bcn = 0;
-				bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn,
-					4, iovbuf, sizeof(iovbuf));
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
-				if (FW_SUPPORTED(dhd, ndoe)) {
-					/* enable IPv6 RA filter in  firmware during suspend */
-					nd_ra_filter = 1;
-					bcm_mkiovar("nd_ra_filter_enable", (char *)&nd_ra_filter, 4,
-						iovbuf, sizeof(iovbuf));
-					if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-						sizeof(iovbuf), TRUE, 0)) < 0)
-						DHD_ERROR(("failed to set nd_ra_filter (%d)\n",
-							ret));
-				}
-#ifdef DYNAMIC_SWOOB_DURATION
-				intr_width = CUSTOM_INTR_WIDTH;
-				bcm_mkiovar("bus:intr_width", (char *)&intr_width, 4,
-					iovbuf, sizeof(iovbuf));
-				if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-						sizeof(iovbuf), TRUE, 0)) < 0) {
-					DHD_ERROR(("failed to set intr_width (%d)\n", ret));
-				}
-#endif /* DYNAMIC_SWOOB_DURATION */
-#endif /* DHD_USE_EARLYSUSPEND */
-			} else {
-#ifdef PKT_FILTER_SUPPORT
-				dhd->early_suspended = 0;
-#endif
-				/* Kernel resumed  */
-				DHD_ERROR(("%s: Remove extra suspend setting \n", __FUNCTION__));
-
-#ifdef SUPPORT_SENSORHUB
-				shub_msreq = 0;
-				if (dhd->info->shub_enable == 1) {
-					bcm_mkiovar("shub_msreq", (char *)&shub_msreq,
-						4, iovbuf, sizeof(iovbuf));
-					if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
-						iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-							DHD_ERROR(("%s Sensor Hub move/stop stop:"
-								"failed %d\n", __FUNCTION__, ret));
-		}
-	}
-#endif /* SUPPORT_SENSORHUB */
-
-
-#ifdef DYNAMIC_SWOOB_DURATION
-				intr_width = 0;
-				bcm_mkiovar("bus:intr_width", (char *)&intr_width, 4,
-					iovbuf, sizeof(iovbuf));
-				if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-						sizeof(iovbuf), TRUE, 0)) < 0) {
-					DHD_ERROR(("failed to set intr_width (%d)\n", ret));
-				}
-#endif /* DYNAMIC_SWOOB_DURATION */
-#ifndef SUPPORT_PM2_ONLY
-				power_mode = PM_FAST;
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
-				                 sizeof(power_mode), TRUE, 0);
-#endif /* SUPPORT_PM2_ONLY */
-#ifdef PKT_FILTER_SUPPORT
-				/* disable pkt filter */
-				dhd_enable_packet_filter(0, dhd);
-#endif /* PKT_FILTER_SUPPORT */
-#ifdef PASS_ALL_MCAST_PKTS
-				allmulti = 1;
-				bcm_mkiovar("allmulti", (char *)&allmulti, 4,
-					iovbuf, sizeof(iovbuf));
-				for (i = 0; i < DHD_MAX_IFS; i++) {
-					if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net)
-						dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-							sizeof(iovbuf), TRUE, i);
-				}
-#endif /* PASS_ALL_MCAST_PKTS */
-
-				/* restore pre-suspend setting for dtim_skip */
-				bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
-					4, iovbuf, sizeof(iovbuf));
-
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#ifdef DHD_USE_EARLYSUSPEND
-#ifdef CUSTOM_BCN_TIMEOUT_IN_SUSPEND
-				bcn_timeout = CUSTOM_BCN_TIMEOUT;
-				bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout,
-					4, iovbuf, sizeof(iovbuf));
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND */
-#ifdef CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND
-				roam_time_thresh = 2000;
-				bcm_mkiovar("roam_time_thresh", (char *)&roam_time_thresh,
-					4, iovbuf, sizeof(iovbuf));
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */
-#ifndef ENABLE_FW_ROAM_SUSPEND
-				roamvar = dhd_roam_disable;
-				bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf,
-					sizeof(iovbuf));
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* ENABLE_FW_ROAM_SUSPEND */
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
-				bcn_li_bcn = 1;
-				bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn,
-					4, iovbuf, sizeof(iovbuf));
-				dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
-				if (FW_SUPPORTED(dhd, ndoe)) {
-					/* disable IPv6 RA filter in  firmware during suspend */
-					nd_ra_filter = 0;
-					bcm_mkiovar("nd_ra_filter_enable", (char *)&nd_ra_filter, 4,
-						iovbuf, sizeof(iovbuf));
-					if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-						sizeof(iovbuf), TRUE, 0)) < 0)
-						DHD_ERROR(("failed to set nd_ra_filter (%d)\n",
-							ret));
-				}
-#endif /* DHD_USE_EARLYSUSPEND */
-			}
-	}
-	dhd_suspend_unlock(dhd);
-
-	return 0;
-}
-
-static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force)
-{
-	dhd_pub_t *dhdp = &dhd->pub;
-	int ret = 0;
-
-	DHD_OS_WAKE_LOCK(dhdp);
-	DHD_PERIM_LOCK(dhdp);
-
-	/* Set flag when early suspend was called */
-	dhdp->in_suspend = val;
-	if ((force || !dhdp->suspend_disable_flag) &&
-		dhd_support_sta_mode(dhdp))
-	{
-		ret = dhd_set_suspend(val, dhdp);
-	}
-
-	DHD_PERIM_UNLOCK(dhdp);
-	DHD_OS_WAKE_UNLOCK(dhdp);
-	return ret;
-}
-
-#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
-static void dhd_early_suspend(struct early_suspend *h)
-{
-	struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
-	DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__));
-
-	if (dhd)
-		dhd_suspend_resume_helper(dhd, 1, 0);
-}
-
-static void dhd_late_resume(struct early_suspend *h)
-{
-	struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
-	DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__));
-
-	if (dhd)
-		dhd_suspend_resume_helper(dhd, 0, 0);
-}
-#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
-
-/*
- * Generalized timeout mechanism.  Uses spin sleep with exponential back-off until
- * the sleep time reaches one jiffy, then switches over to task delay.  Usage:
- *
- *      dhd_timeout_start(&tmo, usec);
- *      while (!dhd_timeout_expired(&tmo))
- *              if (poll_something())
- *                      break;
- *      if (dhd_timeout_expired(&tmo))
- *              fatal();
- */
-
-void
-dhd_timeout_start(dhd_timeout_t *tmo, uint usec)
-{
-	tmo->limit = usec;
-	tmo->increment = 0;
-	tmo->elapsed = 0;
-	tmo->tick = jiffies_to_usecs(1);
-}
-
-int
-dhd_timeout_expired(dhd_timeout_t *tmo)
-{
-	/* Does nothing the first call */
-	if (tmo->increment == 0) {
-		tmo->increment = 1;
-		return 0;
-	}
-
-	if (tmo->elapsed >= tmo->limit)
-		return 1;
-
-	/* Add the delay that's about to take place */
-	tmo->elapsed += tmo->increment;
-
-	if ((!CAN_SLEEP()) || tmo->increment < tmo->tick) {
-		OSL_DELAY(tmo->increment);
-		tmo->increment *= 2;
-		if (tmo->increment > tmo->tick)
-			tmo->increment = tmo->tick;
-	} else {
-		wait_queue_head_t delay_wait;
-		DECLARE_WAITQUEUE(wait, current);
-		init_waitqueue_head(&delay_wait);
-		add_wait_queue(&delay_wait, &wait);
-		set_current_state(TASK_INTERRUPTIBLE);
-		(void)schedule_timeout(1);
-		remove_wait_queue(&delay_wait, &wait);
-		set_current_state(TASK_RUNNING);
-	}
-
-	return 0;
-}
-
-int
-dhd_net2idx(dhd_info_t *dhd, struct net_device *net)
-{
-	int i = 0;
-
-	if (!dhd) {
-		DHD_ERROR(("%s : DHD_BAD_IF return\n", __FUNCTION__));
-		return DHD_BAD_IF;
-	}
-
-	while (i < DHD_MAX_IFS) {
-		if (dhd->iflist[i] && dhd->iflist[i]->net && (dhd->iflist[i]->net == net))
-			return i;
-		i++;
-	}
-
-	return DHD_BAD_IF;
-}
-
-struct net_device * dhd_idx2net(void *pub, int ifidx)
-{
-	struct dhd_pub *dhd_pub = (struct dhd_pub *)pub;
-	struct dhd_info *dhd_info;
-
-	if (!dhd_pub || ifidx < 0 || ifidx >= DHD_MAX_IFS)
-		return NULL;
-	dhd_info = dhd_pub->info;
-	if (dhd_info && dhd_info->iflist[ifidx])
-		return dhd_info->iflist[ifidx]->net;
-	return NULL;
-}
-
-int
-dhd_ifname2idx(dhd_info_t *dhd, char *name)
-{
-	int i = DHD_MAX_IFS;
-
-	ASSERT(dhd);
-
-	if (name == NULL || *name == '\0')
-		return 0;
-
-	while (--i > 0)
-		if (dhd->iflist[i] && !strncmp(dhd->iflist[i]->dngl_name, name, IFNAMSIZ))
-				break;
-
-	DHD_TRACE(("%s: return idx %d for \"%s\"\n", __FUNCTION__, i, name));
-
-	return i;	/* default - the primary interface */
-}
-
-char *
-dhd_ifname(dhd_pub_t *dhdp, int ifidx)
-{
-	dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
-
-	ASSERT(dhd);
-
-	if (ifidx < 0 || ifidx >= DHD_MAX_IFS) {
-		DHD_ERROR(("%s: ifidx %d out of range\n", __FUNCTION__, ifidx));
-		return "<if_bad>";
-	}
-
-	if (dhd->iflist[ifidx] == NULL) {
-		DHD_ERROR(("%s: null i/f %d\n", __FUNCTION__, ifidx));
-		return "<if_null>";
-	}
-
-	if (dhd->iflist[ifidx]->net)
-		return dhd->iflist[ifidx]->net->name;
-
-	return "<if_none>";
-}
-
-uint8 *
-dhd_bssidx2bssid(dhd_pub_t *dhdp, int idx)
-{
-	int i;
-	dhd_info_t *dhd = (dhd_info_t *)dhdp;
-
-	ASSERT(dhd);
-	for (i = 0; i < DHD_MAX_IFS; i++)
-	if (dhd->iflist[i] && dhd->iflist[i]->bssidx == idx)
-		return dhd->iflist[i]->mac_addr;
-
-	return NULL;
-}
-
-
-static void
-_dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
-{
-	struct net_device *dev;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
-	struct netdev_hw_addr *ha;
-#else
-	struct dev_mc_list *mclist;
-#endif
-	uint32 allmulti, cnt;
-
-	wl_ioctl_t ioc;
-	char *buf, *bufp;
-	uint buflen;
-	int ret;
-
-	if (!dhd->iflist[ifidx]) {
-		DHD_ERROR(("%s : dhd->iflist[%d] was NULL\n", __FUNCTION__, ifidx));
-		return;
-	}
-	dev = dhd->iflist[ifidx]->net;
-	if (!dev)
-		return;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-	netif_addr_lock_bh(dev);
-#endif /* LINUX >= 2.6.27 */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
-	cnt = netdev_mc_count(dev);
-#else
-	cnt = dev->mc_count;
-#endif /* LINUX >= 2.6.35 */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-	netif_addr_unlock_bh(dev);
-#endif /* LINUX >= 2.6.27 */
-
-	/* Determine initial value of allmulti flag */
-	allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE;
-
-#ifdef PASS_ALL_MCAST_PKTS
-#ifdef PKT_FILTER_SUPPORT
-	if (!dhd->pub.early_suspended)
-#endif /* PKT_FILTER_SUPPORT */
-		allmulti = TRUE;
-#endif /* PASS_ALL_MCAST_PKTS */
-
-	/* Send down the multicast list first. */
-
-
-	buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETHER_ADDR_LEN);
-	if (!(bufp = buf = MALLOC(dhd->pub.osh, buflen))) {
-		DHD_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
-		           dhd_ifname(&dhd->pub, ifidx), cnt));
-		return;
-	}
-
-	strncpy(bufp, "mcast_list", buflen - 1);
-	bufp[buflen - 1] = '\0';
-	bufp += strlen("mcast_list") + 1;
-
-	cnt = htol32(cnt);
-	memcpy(bufp, &cnt, sizeof(cnt));
-	bufp += sizeof(cnt);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-	netif_addr_lock_bh(dev);
-#endif /* LINUX >= 2.6.27 */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
-	netdev_for_each_mc_addr(ha, dev) {
-		if (!cnt)
-			break;
-		memcpy(bufp, ha->addr, ETHER_ADDR_LEN);
-		bufp += ETHER_ADDR_LEN;
-		cnt--;
-	}
-#else /* LINUX < 2.6.35 */
-	for (mclist = dev->mc_list; (mclist && (cnt > 0));
-		cnt--, mclist = mclist->next) {
-		memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN);
-		bufp += ETHER_ADDR_LEN;
-	}
-#endif /* LINUX >= 2.6.35 */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-	netif_addr_unlock_bh(dev);
-#endif /* LINUX >= 2.6.27 */
-
-	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = WLC_SET_VAR;
-	ioc.buf = buf;
-	ioc.len = buflen;
-	ioc.set = TRUE;
-
-	ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
-	if (ret < 0) {
-		DHD_ERROR(("%s: set mcast_list failed, cnt %d\n",
-			dhd_ifname(&dhd->pub, ifidx), cnt));
-		allmulti = cnt ? TRUE : allmulti;
-	}
-
-	MFREE(dhd->pub.osh, buf, buflen);
-
-	/* Now send the allmulti setting.  This is based on the setting in the
-	 * net_device flags, but might be modified above to be turned on if we
-	 * were trying to set some addresses and dongle rejected it...
-	 */
-
-	buflen = sizeof("allmulti") + sizeof(allmulti);
-	if (!(buf = MALLOC(dhd->pub.osh, buflen))) {
-		DHD_ERROR(("%s: out of memory for allmulti\n", dhd_ifname(&dhd->pub, ifidx)));
-		return;
-	}
-	allmulti = htol32(allmulti);
-
-	if (!bcm_mkiovar("allmulti", (void*)&allmulti, sizeof(allmulti), buf, buflen)) {
-		DHD_ERROR(("%s: mkiovar failed for allmulti, datalen %d buflen %u\n",
-		           dhd_ifname(&dhd->pub, ifidx), (int)sizeof(allmulti), buflen));
-		MFREE(dhd->pub.osh, buf, buflen);
-		return;
-	}
-
-
-	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = WLC_SET_VAR;
-	ioc.buf = buf;
-	ioc.len = buflen;
-	ioc.set = TRUE;
-
-	ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
-	if (ret < 0) {
-		DHD_ERROR(("%s: set allmulti %d failed\n",
-		           dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)));
-	}
-
-	MFREE(dhd->pub.osh, buf, buflen);
-
-	/* Finally, pick up the PROMISC flag as well, like the NIC driver does */
-
-	allmulti = (dev->flags & IFF_PROMISC) ? TRUE : FALSE;
-
-	allmulti = htol32(allmulti);
-
-	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = WLC_SET_PROMISC;
-	ioc.buf = &allmulti;
-	ioc.len = sizeof(allmulti);
-	ioc.set = TRUE;
-
-	ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
-	if (ret < 0) {
-		DHD_ERROR(("%s: set promisc %d failed\n",
-		           dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)));
-	}
-}
-
-int
-_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, uint8 *addr)
-{
-	char buf[32];
-	wl_ioctl_t ioc;
-	int ret;
-
-	if (!bcm_mkiovar("cur_etheraddr", (char*)addr, ETHER_ADDR_LEN, buf, 32)) {
-		DHD_ERROR(("%s: mkiovar failed for cur_etheraddr\n", dhd_ifname(&dhd->pub, ifidx)));
-		return -1;
-	}
-	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = WLC_SET_VAR;
-	ioc.buf = buf;
-	ioc.len = 32;
-	ioc.set = TRUE;
-
-	ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
-	if (ret < 0) {
-		DHD_ERROR(("%s: set cur_etheraddr failed\n", dhd_ifname(&dhd->pub, ifidx)));
-	} else {
-		memcpy(dhd->iflist[ifidx]->net->dev_addr, addr, ETHER_ADDR_LEN);
-		if (ifidx == 0)
-			memcpy(dhd->pub.mac.octet, addr, ETHER_ADDR_LEN);
-	}
-
-	return ret;
-}
-
-#ifdef SOFTAP
-extern struct net_device *ap_net_dev;
-extern tsk_ctl_t ap_eth_ctl; /* ap netdev heper thread ctl */
-#endif
-
-#ifdef DHD_PSTA
-/* Get psta/psr configuration configuration */
-int dhd_get_psta_mode(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd = dhdp->info;
-	return (int)dhd->psta_mode;
-}
-/* Set psta/psr configuration configuration */
-int dhd_set_psta_mode(dhd_pub_t *dhdp, uint32 val)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd->psta_mode = val;
-	return 0;
-}
-#endif /* DHD_PSTA */
-
-static void
-dhd_ifadd_event_handler(void *handle, void *event_info, u8 event)
-{
-	dhd_info_t *dhd = handle;
-	dhd_if_event_t *if_event = event_info;
-	struct net_device *ndev;
-	int ifidx, bssidx;
-	int ret;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
-	struct wireless_dev *vwdev, *primary_wdev;
-	struct net_device *primary_ndev;
-#endif /* OEM_ANDROID && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */
-
-	if (event != DHD_WQ_WORK_IF_ADD) {
-		DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
-		return;
-	}
-
-	if (!dhd) {
-		DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__));
-		return;
-	}
-
-	if (!if_event) {
-		DHD_ERROR(("%s: event data is null \n", __FUNCTION__));
-		return;
-	}
-
-	dhd_net_if_lock_local(dhd);
-	DHD_OS_WAKE_LOCK(&dhd->pub);
-	DHD_PERIM_LOCK(&dhd->pub);
-
-	ifidx = if_event->event.ifidx;
-	bssidx = if_event->event.bssidx;
-	DHD_TRACE(("%s: registering if with ifidx %d\n", __FUNCTION__, ifidx));
-
-	/* This path is for non-android case */
-	/* The interface name in host and in event msg are same */
-	/* if name in event msg is used to create dongle if list on host */
-	ndev = dhd_allocate_if(&dhd->pub, ifidx, if_event->name,
-		if_event->mac, bssidx, TRUE, if_event->name);
-	if (!ndev) {
-		DHD_ERROR(("%s: net device alloc failed  \n", __FUNCTION__));
-		goto done;
-	}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
-	vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
-	if (unlikely(!vwdev)) {
-		DHD_ERROR(("Could not allocate wireless device\n"));
-		goto done;
-	}
-	primary_ndev = dhd->pub.info->iflist[0]->net;
-	primary_wdev = ndev_to_wdev(primary_ndev);
-	vwdev->wiphy = primary_wdev->wiphy;
-	vwdev->iftype = if_event->event.role;
-	vwdev->netdev = ndev;
-	ndev->ieee80211_ptr = vwdev;
-	SET_NETDEV_DEV(ndev, wiphy_dev(vwdev->wiphy));
-	DHD_ERROR(("virtual interface(%s) is created\n", if_event->name));
-#endif /* OEM_ANDROID && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */
-
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	ret = dhd_register_if(&dhd->pub, ifidx, TRUE);
-	DHD_PERIM_LOCK(&dhd->pub);
-	if (ret != BCME_OK) {
-		DHD_ERROR(("%s: dhd_register_if failed\n", __FUNCTION__));
-		dhd_remove_if(&dhd->pub, ifidx, TRUE);
-		goto done;
-	}
-#ifdef PCIE_FULL_DONGLE
-	/* Turn on AP isolation in the firmware for interfaces operating in AP mode */
-	if (FW_SUPPORTED((&dhd->pub), ap) && (if_event->event.role != WLC_E_IF_ROLE_STA)) {
-		char iovbuf[WLC_IOCTL_SMLEN];
-		uint32 var_int =  1;
-
-		memset(iovbuf, 0, sizeof(iovbuf));
-		bcm_mkiovar("ap_isolate", (char *)&var_int, 4, iovbuf, sizeof(iovbuf));
-		ret = dhd_wl_ioctl_cmd(&dhd->pub, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, ifidx);
-
-		if (ret != BCME_OK) {
-			DHD_ERROR(("%s: Failed to set ap_isolate to dongle\n", __FUNCTION__));
-			dhd_remove_if(&dhd->pub, ifidx, TRUE);
-		}
-	}
-#endif /* PCIE_FULL_DONGLE */
-
-done:
-	MFREE(dhd->pub.osh, if_event, sizeof(dhd_if_event_t));
-
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	DHD_OS_WAKE_UNLOCK(&dhd->pub);
-	dhd_net_if_unlock_local(dhd);
-}
-
-static void
-dhd_ifdel_event_handler(void *handle, void *event_info, u8 event)
-{
-	dhd_info_t *dhd = handle;
-	int ifidx;
-	dhd_if_event_t *if_event = event_info;
-
-
-	if (event != DHD_WQ_WORK_IF_DEL) {
-		DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
-		return;
-	}
-
-	if (!dhd) {
-		DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__));
-		return;
-	}
-
-	if (!if_event) {
-		DHD_ERROR(("%s: event data is null \n", __FUNCTION__));
-		return;
-	}
-
-	dhd_net_if_lock_local(dhd);
-	DHD_OS_WAKE_LOCK(&dhd->pub);
-	DHD_PERIM_LOCK(&dhd->pub);
-
-	ifidx = if_event->event.ifidx;
-	DHD_TRACE(("Removing interface with idx %d\n", ifidx));
-
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	dhd_remove_if(&dhd->pub, ifidx, TRUE);
-	DHD_PERIM_LOCK(&dhd->pub);
-
-	MFREE(dhd->pub.osh, if_event, sizeof(dhd_if_event_t));
-
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	DHD_OS_WAKE_UNLOCK(&dhd->pub);
-	dhd_net_if_unlock_local(dhd);
-}
-
-static void
-dhd_set_mac_addr_handler(void *handle, void *event_info, u8 event)
-{
-	dhd_info_t *dhd = handle;
-	dhd_if_t *ifp = event_info;
-
-	if (event != DHD_WQ_WORK_SET_MAC) {
-		DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
-	}
-
-	if (!dhd) {
-		DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__));
-		return;
-	}
-
-	dhd_net_if_lock_local(dhd);
-	DHD_OS_WAKE_LOCK(&dhd->pub);
-	DHD_PERIM_LOCK(&dhd->pub);
-
-#ifdef SOFTAP
-	{
-		unsigned long flags;
-		bool in_ap = FALSE;
-		DHD_GENERAL_LOCK(&dhd->pub, flags);
-		in_ap = (ap_net_dev != NULL);
-		DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-
-		if (in_ap)  {
-			DHD_ERROR(("attempt to set MAC for %s in AP Mode, blocked. \n",
-			           ifp->net->name));
-			goto done;
-		}
-	}
-#endif /* SOFTAP */
-
-	if (ifp == NULL || !dhd->pub.up) {
-		DHD_ERROR(("%s: interface info not available/down \n", __FUNCTION__));
-		goto done;
-	}
-
-	DHD_ERROR(("%s: MACID is overwritten\n", __FUNCTION__));
-	ifp->set_macaddress = FALSE;
-	if (_dhd_set_mac_address(dhd, ifp->idx, ifp->mac_addr) == 0)
-		DHD_INFO(("%s: MACID is overwritten\n",	__FUNCTION__));
-	else
-		DHD_ERROR(("%s: _dhd_set_mac_address() failed\n", __FUNCTION__));
-
-done:
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	DHD_OS_WAKE_UNLOCK(&dhd->pub);
-	dhd_net_if_unlock_local(dhd);
-}
-
-static void
-dhd_set_mcast_list_handler(void *handle, void *event_info, u8 event)
-{
-	dhd_info_t *dhd = handle;
-	dhd_if_t *ifp = event_info;
-	int ifidx;
-
-	if (event != DHD_WQ_WORK_SET_MCAST_LIST) {
-		DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
-		return;
-	}
-
-	if (!dhd) {
-		DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__));
-		return;
-	}
-
-	dhd_net_if_lock_local(dhd);
-	DHD_OS_WAKE_LOCK(&dhd->pub);
-	DHD_PERIM_LOCK(&dhd->pub);
-
-#ifdef SOFTAP
-	{
-		bool in_ap = FALSE;
-		unsigned long flags;
-		DHD_GENERAL_LOCK(&dhd->pub, flags);
-		in_ap = (ap_net_dev != NULL);
-		DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-
-		if (in_ap)  {
-			DHD_ERROR(("set MULTICAST list for %s in AP Mode, blocked. \n",
-			           ifp->net->name));
-			ifp->set_multicast = FALSE;
-			goto done;
-		}
-	}
-#endif /* SOFTAP */
-
-	if (ifp == NULL || !dhd->pub.up) {
-		DHD_ERROR(("%s: interface info not available/down \n", __FUNCTION__));
-		goto done;
-	}
-
-	ifidx = ifp->idx;
-
-
-	_dhd_set_multicast_list(dhd, ifidx);
-	DHD_INFO(("%s: set multicast list for if %d\n", __FUNCTION__, ifidx));
-
-done:
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	DHD_OS_WAKE_UNLOCK(&dhd->pub);
-	dhd_net_if_unlock_local(dhd);
-}
-
-static int
-dhd_set_mac_address(struct net_device *dev, void *addr)
-{
-	int ret = 0;
-
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	struct sockaddr *sa = (struct sockaddr *)addr;
-	int ifidx;
-	dhd_if_t *dhdif;
-
-	ifidx = dhd_net2idx(dhd, dev);
-	if (ifidx == DHD_BAD_IF)
-		return -1;
-
-	dhdif = dhd->iflist[ifidx];
-
-	dhd_net_if_lock_local(dhd);
-	memcpy(dhdif->mac_addr, sa->sa_data, ETHER_ADDR_LEN);
-	dhdif->set_macaddress = TRUE;
-	dhd_net_if_unlock_local(dhd);
-	dhd_deferred_schedule_work(dhd->dhd_deferred_wq, (void *)dhdif, DHD_WQ_WORK_SET_MAC,
-		dhd_set_mac_addr_handler, DHD_WORK_PRIORITY_LOW);
-	return ret;
-}
-
-static void
-dhd_set_multicast_list(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ifidx;
-
-	ifidx = dhd_net2idx(dhd, dev);
-	if (ifidx == DHD_BAD_IF)
-		return;
-
-	dhd->iflist[ifidx]->set_multicast = TRUE;
-	dhd_deferred_schedule_work(dhd->dhd_deferred_wq, (void *)dhd->iflist[ifidx],
-		DHD_WQ_WORK_SET_MCAST_LIST, dhd_set_mcast_list_handler, DHD_WORK_PRIORITY_LOW);
-}
-
-#ifdef PROP_TXSTATUS
-int
-dhd_os_wlfc_block(dhd_pub_t *pub)
-{
-	dhd_info_t *di = (dhd_info_t *)(pub->info);
-	ASSERT(di != NULL);
-	spin_lock_bh(&di->wlfc_spinlock);
-	return 1;
-}
-
-int
-dhd_os_wlfc_unblock(dhd_pub_t *pub)
-{
-	dhd_info_t *di = (dhd_info_t *)(pub->info);
-
-	ASSERT(di != NULL);
-	spin_unlock_bh(&di->wlfc_spinlock);
-	return 1;
-}
-
-#endif /* PROP_TXSTATUS */
-
-#if defined(DHD_8021X_DUMP)
-void
-dhd_tx_dump(struct net_device *ndev, osl_t *osh, void *pkt)
-{
-	uint8 *dump_data;
-	uint16 protocol;
-	char *ifname;
-
-	dump_data = PKTDATA(osh, pkt);
-	protocol = (dump_data[12] << 8) | dump_data[13];
-	ifname = ndev ? ndev->name : "N/A";
-
-	if (protocol == ETHER_TYPE_802_1X) {
-		dhd_dump_eapol_4way_message(ifname, dump_data, TRUE);
-	}
-}
-#endif /* DHD_8021X_DUMP */
-
-/*  This routine do not support Packet chain feature, Currently tested for
- *  proxy arp feature
- */
-int dhd_sendup(dhd_pub_t *dhdp, int ifidx, void *p)
-{
-	struct sk_buff *skb;
-	void *skbhead = NULL;
-	void *skbprev = NULL;
-	dhd_if_t *ifp;
-	ASSERT(!PKTISCHAINED(p));
-	skb = PKTTONATIVE(dhdp->osh, p);
-
-	ifp = dhdp->info->iflist[ifidx];
-	skb->dev = ifp->net;
-#if defined(BCM_GMAC3)
-	/* Forwarder capable interfaces use WOFA based forwarding */
-	if (ifp->fwdh) {
-		struct ether_header *eh = (struct ether_header *)PKTDATA(dhdp->osh, p);
-		uint16 * da = (uint16 *)(eh->ether_dhost);
-		wofa_t wofa;
-		ASSERT(ISALIGNED(da, 2));
-
-		wofa = fwder_lookup(ifp->fwdh->mate, da, ifp->idx);
-		if (wofa == FWDER_WOFA_INVALID) { /* Unknown MAC address */
-			if (fwder_transmit(ifp->fwdh, skb, 1, skb->dev) == FWDER_SUCCESS) {
-				return BCME_OK;
-			}
-		}
-		PKTFRMNATIVE(dhdp->osh, p);
-		PKTFREE(dhdp->osh, p, FALSE);
-		return BCME_OK;
-	}
-#endif /* BCM_GMAC3 */
-
-	skb->protocol = eth_type_trans(skb, skb->dev);
-
-	if (in_interrupt()) {
-		bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE,
-			__FUNCTION__, __LINE__);
-		netif_rx(skb);
-	} else {
-		if (dhdp->info->rxthread_enabled) {
-			if (!skbhead) {
-				skbhead = skb;
-			} else {
-				PKTSETNEXT(dhdp->osh, skbprev, skb);
-			}
-			skbprev = skb;
-		} else {
-			/* If the receive is not processed inside an ISR,
-			 * the softirqd must be woken explicitly to service
-			 * the NET_RX_SOFTIRQ.	In 2.6 kernels, this is handled
-			 * by netif_rx_ni(), but in earlier kernels, we need
-			 * to do it manually.
-			 */
-			bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE,
-				__FUNCTION__, __LINE__);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-			netif_rx_ni(skb);
-#else
-			ulong flags;
-			netif_rx(skb);
-			local_irq_save(flags);
-			RAISE_RX_SOFTIRQ();
-			local_irq_restore(flags);
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
-		}
-	}
-
-	if (dhdp->info->rxthread_enabled && skbhead)
-		dhd_sched_rxf(dhdp, skbhead);
-
-	return BCME_OK;
-}
-
-int BCMFASTPATH
-__dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
-{
-	int ret = BCME_OK;
-	dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
-	struct ether_header *eh = NULL;
-#ifdef DHD_L2_FILTER
-	dhd_if_t *ifp = dhd_get_ifp(dhdp, ifidx);
-#endif
-#ifdef DHD_8021X_DUMP
-	struct net_device *ndev;
-#endif /* DHD_8021X_DUMP */
-
-	/* Reject if down */
-	if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN)) {
-		/* free the packet here since the caller won't */
-		PKTCFREE(dhdp->osh, pktbuf, TRUE);
-		return -ENODEV;
-	}
-
-#ifdef PCIE_FULL_DONGLE
-	if (dhdp->busstate == DHD_BUS_SUSPEND) {
-		DHD_ERROR(("%s : pcie is still in suspend state!!\n", __FUNCTION__));
-		PKTFREE(dhdp->osh, pktbuf, TRUE);
-		return -EBUSY;
-	}
-#endif /* PCIE_FULL_DONGLE */
-
-#ifdef DHD_L2_FILTER
-	/* if dhcp_unicast is enabled, we need to convert the */
-	/* broadcast DHCP ACK/REPLY packets to Unicast. */
-	if (ifp->dhcp_unicast) {
-	    uint8* mac_addr;
-	    uint8* ehptr = NULL;
-	    int ret;
-	    ret = bcm_l2_filter_get_mac_addr_dhcp_pkt(dhdp->osh, pktbuf, ifidx, &mac_addr);
-	    if (ret == BCME_OK) {
-		/*  if given mac address having valid entry in sta list
-		 *  copy the given mac address, and return with BCME_OK
-		*/
-		if (dhd_find_sta(dhdp, ifidx, mac_addr)) {
-		    ehptr = PKTDATA(dhdp->osh, pktbuf);
-		    bcopy(mac_addr, ehptr + ETHER_DEST_OFFSET, ETHER_ADDR_LEN);
-		}
-	    }
-	}
-
-	if (ifp->grat_arp && DHD_IF_ROLE_AP(dhdp, ifidx)) {
-	    if (bcm_l2_filter_gratuitous_arp(dhdp->osh, pktbuf) == BCME_OK) {
-			PKTCFREE(dhdp->osh, pktbuf, TRUE);
-			return BCME_ERROR;
-	    }
-	}
-
-	if (ifp->parp_enable && DHD_IF_ROLE_AP(dhdp, ifidx)) {
-		ret = dhd_l2_filter_pkt_handle(dhdp, ifidx, pktbuf, TRUE);
-
-		/* Drop the packets if l2 filter has processed it already
-		 * otherwise continue with the normal path
-		 */
-		if (ret == BCME_OK) {
-			PKTCFREE(dhdp->osh, pktbuf, TRUE);
-			return BCME_ERROR;
-		}
-	}
-#endif /* DHD_L2_FILTER */
-	/* Update multicast statistic */
-	if (PKTLEN(dhdp->osh, pktbuf) >= ETHER_HDR_LEN) {
-		uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf);
-		eh = (struct ether_header *)pktdata;
-
-		if (ETHER_ISMULTI(eh->ether_dhost))
-			dhdp->tx_multicast++;
-		if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X)
-			atomic_inc(&dhd->pend_8021x_cnt);
-#ifdef DHD_DHCP_DUMP
-		if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) {
-			uint16 dump_hex;
-			uint16 source_port;
-			uint16 dest_port;
-			uint16 udp_port_pos;
-			uint8 *ptr8 = (uint8 *)&pktdata[ETHER_HDR_LEN];
-			uint8 ip_header_len = (*ptr8 & 0x0f)<<2;
-			struct net_device *net;
-			char *ifname;
-
-			net = dhd_idx2net(dhdp, ifidx);
-			ifname = net ? net->name : "N/A";
-			udp_port_pos = ETHER_HDR_LEN + ip_header_len;
-			source_port = (pktdata[udp_port_pos] << 8) | pktdata[udp_port_pos+1];
-			dest_port = (pktdata[udp_port_pos+2] << 8) | pktdata[udp_port_pos+3];
-			if (source_port == 0x0044 || dest_port == 0x0044) {
-				dump_hex = (pktdata[udp_port_pos+249] << 8) |
-					pktdata[udp_port_pos+250];
-				if (dump_hex == 0x0101) {
-					DHD_ERROR(("DHCP[%s] - DISCOVER [TX]", ifname));
-				} else if (dump_hex == 0x0102) {
-					DHD_ERROR(("DHCP[%s] - OFFER [TX]", ifname));
-				} else if (dump_hex == 0x0103) {
-					DHD_ERROR(("DHCP[%s] - REQUEST [TX]", ifname));
-				} else if (dump_hex == 0x0105) {
-					DHD_ERROR(("DHCP[%s] - ACK [TX]", ifname));
-				} else {
-					DHD_ERROR(("DHCP[%s] - 0x%X [TX]", ifname, dump_hex));
-				}
-#ifdef DHD_LOSSLESS_ROAMING
-				if (dhdp->dequeue_prec_map != (uint8)ALLPRIO) {
-					DHD_ERROR(("/%d", dhdp->dequeue_prec_map));
-				}
-#endif /* DHD_LOSSLESS_ROAMING */
-				DHD_ERROR(("\n"));
-			} else if (source_port == 0x0043 || dest_port == 0x0043) {
-				DHD_ERROR(("DHCP[%s] - BOOTP [RX]\n", ifname));
-			}
-		}
-#endif /* DHD_DHCP_DUMP */
-	} else {
-			PKTCFREE(dhdp->osh, pktbuf, TRUE);
-			return BCME_ERROR;
-	}
-
-	/* Look into the packet and update the packet priority */
-#ifndef PKTPRIO_OVERRIDE
-	if (PKTPRIO(pktbuf) == 0)
-#endif /* !PKTPRIO_OVERRIDE */
-	{
-#ifdef QOS_MAP_SET
-		pktsetprio_qms(pktbuf, wl_get_up_table(), FALSE);
-#else
-		pktsetprio(pktbuf, FALSE);
-#endif /* QOS_MAP_SET */
-	}
-
-
-#ifdef PCIE_FULL_DONGLE
-	/*
-	 * Lkup the per interface hash table, for a matching flowring. If one is not
-	 * available, allocate a unique flowid and add a flowring entry.
-	 * The found or newly created flowid is placed into the pktbuf's tag.
-	 */
-	ret = dhd_flowid_update(dhdp, ifidx, dhdp->flow_prio_map[(PKTPRIO(pktbuf))], pktbuf);
-	if (ret != BCME_OK) {
-		PKTCFREE(dhd->pub.osh, pktbuf, TRUE);
-		return ret;
-	}
-#endif
-
-#ifdef PROP_TXSTATUS
-	if (dhd_wlfc_is_supported(dhdp)) {
-		/* store the interface ID */
-		DHD_PKTTAG_SETIF(PKTTAG(pktbuf), ifidx);
-
-		/* store destination MAC in the tag as well */
-		DHD_PKTTAG_SETDSTN(PKTTAG(pktbuf), eh->ether_dhost);
-
-		/* decide which FIFO this packet belongs to */
-		if (ETHER_ISMULTI(eh->ether_dhost))
-			/* one additional queue index (highest AC + 1) is used for bc/mc queue */
-			DHD_PKTTAG_SETFIFO(PKTTAG(pktbuf), AC_COUNT);
-		else
-			DHD_PKTTAG_SETFIFO(PKTTAG(pktbuf), WME_PRIO2AC(PKTPRIO(pktbuf)));
-	} else
-#endif /* PROP_TXSTATUS */
-	{
-		/* If the protocol uses a data header, apply it */
-		dhd_prot_hdrpush(dhdp, ifidx, pktbuf);
-	}
-
-	/* Use bus module to send data frame */
-#ifdef WLMEDIA_HTSF
-	dhd_htsf_addtxts(dhdp, pktbuf);
-#endif
-#if defined(DHD_8021X_DUMP)
-	ndev = dhd_idx2net(dhdp, ifidx);
-	dhd_tx_dump(ndev, dhdp->osh, pktbuf);
-#endif
-#ifdef PROP_TXSTATUS
-	{
-		if (dhd_wlfc_commit_packets(dhdp, (f_commitpkt_t)dhd_bus_txdata,
-			dhdp->bus, pktbuf, TRUE) == WLFC_UNSUPPORTED) {
-			/* non-proptxstatus way */
-#ifdef BCMPCIE
-			ret = dhd_bus_txdata(dhdp->bus, pktbuf, (uint8)ifidx);
-#else
-			ret = dhd_bus_txdata(dhdp->bus, pktbuf);
-#endif /* BCMPCIE */
-		}
-	}
-#else
-#ifdef BCMPCIE
-	ret = dhd_bus_txdata(dhdp->bus, pktbuf, (uint8)ifidx);
-#else
-	ret = dhd_bus_txdata(dhdp->bus, pktbuf);
-#endif /* BCMPCIE */
-#endif /* PROP_TXSTATUS */
-
-	return ret;
-}
-
-int BCMFASTPATH
-dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	DHD_GENERAL_LOCK(dhdp, flags);
-	if (dhdp->busstate == DHD_BUS_DOWN ||
-			dhdp->busstate == DHD_BUS_DOWN_IN_PROGRESS) {
-		DHD_ERROR(("%s: returning as busstate=%d\n",
-			__FUNCTION__, dhdp->busstate));
-		DHD_GENERAL_UNLOCK(dhdp, flags);
-		PKTCFREE(dhdp->osh, pktbuf, TRUE);
-		return -ENODEV;
-	}
-	dhdp->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_SEND_PKT;
-	DHD_GENERAL_UNLOCK(dhdp, flags);
-
-#ifdef DHD_PCIE_RUNTIMEPM
-	if (dhdpcie_runtime_bus_wake(dhdp, FALSE, __builtin_return_address(0))) {
-		DHD_ERROR(("%s : pcie is still in suspend state!!\n", __FUNCTION__));
-		PKTCFREE(dhdp->osh, pktbuf, TRUE);
-		ret = -EBUSY;
-		goto exit;
-	}
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-	ret = __dhd_sendpkt(dhdp, ifidx, pktbuf);
-
-#ifdef DHD_PCIE_RUNTIMEPM
-exit:
-#endif
-	DHD_GENERAL_LOCK(dhdp, flags);
-	dhdp->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_SEND_PKT;
-	DHD_GENERAL_UNLOCK(dhdp, flags);
-	return ret;
-}
-
-int BCMFASTPATH
-dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
-{
-	int ret;
-	uint datalen;
-	void *pktbuf;
-	dhd_info_t *dhd = DHD_DEV_INFO(net);
-	dhd_if_t *ifp = NULL;
-	int ifidx;
-	unsigned long flags;
-#ifdef WLMEDIA_HTSF
-	uint8 htsfdlystat_sz = dhd->pub.htsfdlystat_sz;
-#else
-	uint8 htsfdlystat_sz = 0;
-#endif 
-#ifdef DHD_WMF
-	struct ether_header *eh;
-	uint8 *iph;
-#endif /* DHD_WMF */
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-
-#ifdef PCIE_FULL_DONGLE
-	DHD_GENERAL_LOCK(&dhd->pub, flags);
-	dhd->pub.dhd_bus_busy_state |= DHD_BUS_BUSY_IN_TX;
-	DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-#endif /* PCIE_FULL_DONGLE */
-
-#ifdef DHD_PCIE_RUNTIMEPM
-	if (dhdpcie_runtime_bus_wake(&dhd->pub, FALSE, dhd_start_xmit)) {
-		/* In order to avoid pkt loss. Return NETDEV_TX_BUSY until run-time resumed. */
-		/* stop the network queue temporarily until resume done */
-		DHD_GENERAL_LOCK(&dhd->pub, flags);
-		if (!dhdpcie_is_resume_done(&dhd->pub)) {
-			dhd_bus_stop_queue(dhd->pub.bus);
-		}
-		dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX;
-		dhd_os_busbusy_wake(&dhd->pub);
-		DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
-		return -ENODEV;
-#else
-		return NETDEV_TX_BUSY;
-#endif
-	}
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-	DHD_GENERAL_LOCK(&dhd->pub, flags);
-#ifdef PCIE_FULL_DONGLE
-	if (dhd->pub.busstate == DHD_BUS_SUSPEND) {
-		dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX;
-		dhd_os_busbusy_wake(&dhd->pub);
-		DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
-		return -ENODEV;
-#else
-		return NETDEV_TX_BUSY;
-#endif
-	}
-#endif /* PCIE_FULL_DONGLE */
-
-	DHD_OS_WAKE_LOCK(&dhd->pub);
-	DHD_PERIM_LOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken);
-
-	/* Reject if down */
-	if (dhd->pub.hang_was_sent || dhd->pub.busstate == DHD_BUS_DOWN ||
-		dhd->pub.busstate == DHD_BUS_DOWN_IN_PROGRESS) {
-		DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d \n",
-			__FUNCTION__, dhd->pub.up, dhd->pub.busstate));
-		netif_stop_queue(net);
-		/* Send Event when bus down detected during data session */
-		if (dhd->pub.up && !dhd->pub.hang_was_sent) {
-			DHD_ERROR(("%s: Event HANG sent up\n", __FUNCTION__));
-			dhd->pub.hang_reason = HANG_REASON_BUS_DOWN;
-			net_os_send_hang_message(net);
-		}
-#ifdef PCIE_FULL_DONGLE
-		dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX;
-		dhd_os_busbusy_wake(&dhd->pub);
-		DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-#endif /* PCIE_FULL_DONGLE */
-		DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken);
-		DHD_OS_WAKE_UNLOCK(&dhd->pub);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
-		return -ENODEV;
-#else
-		return NETDEV_TX_BUSY;
-#endif
-	}
-
-	ifp = DHD_DEV_IFP(net);
-	ifidx = DHD_DEV_IFIDX(net);
-	BUZZZ_LOG(START_XMIT_BGN, 2, (uint32)ifidx, (uintptr)skb);
-
-	if (ifidx == DHD_BAD_IF) {
-		DHD_ERROR(("%s: bad ifidx %d\n", __FUNCTION__, ifidx));
-		netif_stop_queue(net);
-#ifdef PCIE_FULL_DONGLE
-		dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX;
-		dhd_os_busbusy_wake(&dhd->pub);
-		DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-#endif /* PCIE_FULL_DONGLE */
-		DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken);
-		DHD_OS_WAKE_UNLOCK(&dhd->pub);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
-		return -ENODEV;
-#else
-		return NETDEV_TX_BUSY;
-#endif
-	}
-	DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-
-	ASSERT(ifidx == dhd_net2idx(dhd, net));
-	ASSERT((ifp != NULL) && ((ifidx < DHD_MAX_IFS) && (ifp == dhd->iflist[ifidx])));
-
-	bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, __FUNCTION__, __LINE__);
-
-	/* re-align socket buffer if "skb->data" is odd address */
-	if (((unsigned long)(skb->data)) & 0x1) {
-		unsigned char *data = skb->data;
-		uint32 length = skb->len;
-		PKTPUSH(dhd->pub.osh, skb, 1);
-		memmove(skb->data, data, length);
-		PKTSETLEN(dhd->pub.osh, skb, length);
-	}
-
-	datalen  = PKTLEN(dhd->pub.osh, skb);
-
-	/* Make sure there's enough room for any header */
-	if (skb_headroom(skb) < dhd->pub.hdrlen + htsfdlystat_sz) {
-		struct sk_buff *skb2;
-
-		DHD_INFO(("%s: insufficient headroom\n",
-		          dhd_ifname(&dhd->pub, ifidx)));
-		dhd->pub.tx_realloc++;
-
-		bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, __FUNCTION__, __LINE__);
-		skb2 = skb_realloc_headroom(skb, dhd->pub.hdrlen + htsfdlystat_sz);
-
-		dev_kfree_skb(skb);
-		if ((skb = skb2) == NULL) {
-			DHD_ERROR(("%s: skb_realloc_headroom failed\n",
-			           dhd_ifname(&dhd->pub, ifidx)));
-			ret = -ENOMEM;
-			goto done;
-		}
-		bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, __FUNCTION__, __LINE__);
-	}
-
-	/* Convert to packet */
-	if (!(pktbuf = PKTFRMNATIVE(dhd->pub.osh, skb))) {
-		DHD_ERROR(("%s: PKTFRMNATIVE failed\n",
-		           dhd_ifname(&dhd->pub, ifidx)));
-		bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, __FUNCTION__, __LINE__);
-		dev_kfree_skb_any(skb);
-		ret = -ENOMEM;
-		goto done;
-	}
-
-#if defined(WLMEDIA_HTSF)
-	if (htsfdlystat_sz && PKTLEN(dhd->pub.osh, pktbuf) >= ETHER_ADDR_LEN) {
-		uint8 *pktdata = (uint8 *)PKTDATA(dhd->pub.osh, pktbuf);
-		struct ether_header *eh = (struct ether_header *)pktdata;
-
-		if (!ETHER_ISMULTI(eh->ether_dhost) &&
-			(ntoh16(eh->ether_type) == ETHER_TYPE_IP)) {
-			eh->ether_type = hton16(ETHER_TYPE_BRCM_PKTDLYSTATS);
-		}
-	}
-#endif 
-
-#ifdef DHD_WMF
-	eh = (struct ether_header *)PKTDATA(dhd->pub.osh, pktbuf);
-	iph = (uint8 *)eh + ETHER_HDR_LEN;
-
-	/* WMF processing for multicast packets
-	 * Only IPv4 packets are handled
-	 */
-	if (ifp->wmf.wmf_enable && (ntoh16(eh->ether_type) == ETHER_TYPE_IP) &&
-		(IP_VER(iph) == IP_VER_4) && (ETHER_ISMULTI(eh->ether_dhost) ||
-		((IPV4_PROT(iph) == IP_PROT_IGMP) && dhd->pub.wmf_ucast_igmp))) {
-#if defined(DHD_IGMP_UCQUERY) || defined(DHD_UCAST_UPNP)
-		void *sdu_clone;
-		bool ucast_convert = FALSE;
-#ifdef DHD_UCAST_UPNP
-		uint32 dest_ip;
-
-		dest_ip = ntoh32(*((uint32 *)(iph + IPV4_DEST_IP_OFFSET)));
-		ucast_convert = dhd->pub.wmf_ucast_upnp && MCAST_ADDR_UPNP_SSDP(dest_ip);
-#endif /* DHD_UCAST_UPNP */
-#ifdef DHD_IGMP_UCQUERY
-		ucast_convert |= dhd->pub.wmf_ucast_igmp_query &&
-			(IPV4_PROT(iph) == IP_PROT_IGMP) &&
-			(*(iph + IPV4_HLEN(iph)) == IGMPV2_HOST_MEMBERSHIP_QUERY);
-#endif /* DHD_IGMP_UCQUERY */
-		if (ucast_convert) {
-			dhd_sta_t *sta;
-#ifdef PCIE_FULL_DONGLE
-			unsigned long flags;
-#endif
-			struct list_head snapshot_list;
-			struct list_head *wmf_ucforward_list;
-
-			ret = NETDEV_TX_OK;
-
-			/* For non BCM_GMAC3 platform we need a snapshot sta_list to
-			 * resolve double DHD_IF_STA_LIST_LOCK call deadlock issue.
-			 */
-			wmf_ucforward_list = DHD_IF_WMF_UCFORWARD_LOCK(dhd, ifp, &snapshot_list);
-
-			/* Convert upnp/igmp query to unicast for each assoc STA */
-			list_for_each_entry(sta, wmf_ucforward_list, list) {
-				if ((sdu_clone = PKTDUP(dhd->pub.osh, pktbuf)) == NULL) {
-					ret = WMF_NOP;
-					break;
-				}
-				dhd_wmf_forward(ifp->wmf.wmfh, sdu_clone, 0, sta, 1);
-			}
-			DHD_IF_WMF_UCFORWARD_UNLOCK(dhd, wmf_ucforward_list);
-
-#ifdef PCIE_FULL_DONGLE
-			DHD_GENERAL_LOCK(&dhd->pub, flags);
-			dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX;
-			dhd_os_busbusy_wake(&dhd->pub);
-			DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-#endif /* PCIE_FULL_DONGLE */
-			DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken);
-			DHD_OS_WAKE_UNLOCK(&dhd->pub);
-
-			if (ret == NETDEV_TX_OK)
-				PKTFREE(dhd->pub.osh, pktbuf, TRUE);
-
-			return ret;
-		} else
-#endif /* defined(DHD_IGMP_UCQUERY) || defined(DHD_UCAST_UPNP) */
-		{
-			/* There will be no STA info if the packet is coming from LAN host
-			 * Pass as NULL
-			 */
-			ret = dhd_wmf_packets_handle(&dhd->pub, pktbuf, NULL, ifidx, 0);
-			switch (ret) {
-			case WMF_TAKEN:
-			case WMF_DROP:
-				/* Either taken by WMF or we should drop it.
-				 * Exiting send path
-				 */
-#ifdef PCIE_FULL_DONGLE
-				DHD_GENERAL_LOCK(&dhd->pub, flags);
-				dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX;
-				dhd_os_busbusy_wake(&dhd->pub);
-				DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-#endif /* PCIE_FULL_DONGLE */
-				DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken);
-				DHD_OS_WAKE_UNLOCK(&dhd->pub);
-				return NETDEV_TX_OK;
-			default:
-				/* Continue the transmit path */
-				break;
-			}
-		}
-	}
-#endif /* DHD_WMF */
-#ifdef DHD_PSTA
-	/* PSR related packet proto manipulation should be done in DHD
-	 * since dongle doesn't have complete payload
-	 */
-	if (PSR_ENABLED(&dhd->pub) && (dhd_psta_proc(&dhd->pub,
-		ifidx, &pktbuf, TRUE) < 0)) {
-			DHD_ERROR(("%s:%s: psta send proc failed\n", __FUNCTION__,
-				dhd_ifname(&dhd->pub, ifidx)));
-	}
-#endif /* DHD_PSTA */
-
-#ifdef DHDTCPACK_SUPPRESS
-	if (dhd->pub.tcpack_sup_mode == TCPACK_SUP_HOLD) {
-		/* If this packet has been hold or got freed, just return */
-		if (dhd_tcpack_hold(&dhd->pub, pktbuf, ifidx)) {
-			ret = 0;
-			goto done;
-		}
-	} else {
-		/* If this packet has replaced another packet and got freed, just return */
-		if (dhd_tcpack_suppress(&dhd->pub, pktbuf)) {
-			ret = 0;
-			goto done;
-		}
-	}
-#endif /* DHDTCPACK_SUPPRESS */
-
-	/* segmented SKB support (Kernel-3.18.y) */
-	if ((PKTLINK(skb) != NULL) && (PKTLINK(skb) == skb)) {
-		PKTSETLINK(skb, NULL);
-	}
-
-	ret = __dhd_sendpkt(&dhd->pub, ifidx, pktbuf);
-
-done:
-	if (ret) {
-		ifp->stats.tx_dropped++;
-		dhd->pub.tx_dropped++;
-	} else {
-
-#ifdef PROP_TXSTATUS
-		/* tx_packets counter can counted only when wlfc is disabled */
-		if (!dhd_wlfc_is_supported(&dhd->pub))
-#endif
-		{
-			dhd->pub.tx_packets++;
-			ifp->stats.tx_packets++;
-			ifp->stats.tx_bytes += datalen;
-		}
-	}
-
-#ifdef PCIE_FULL_DONGLE
-	DHD_GENERAL_LOCK(&dhd->pub, flags);
-	dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX;
-	dhd_os_busbusy_wake(&dhd->pub);
-	DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-#endif /* PCIE_FULL_DONGLE */
-
-	DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken);
-	DHD_OS_WAKE_UNLOCK(&dhd->pub);
-	BUZZZ_LOG(START_XMIT_END, 0);
-
-	/* Return ok: we always eat the packet */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
-	return 0;
-#else
-	return NETDEV_TX_OK;
-#endif
-}
-
-
-void
-dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state)
-{
-	struct net_device *net;
-	dhd_info_t *dhd = dhdp->info;
-	int i;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	ASSERT(dhd);
-
-#ifdef DHD_LOSSLESS_ROAMING
-	/* block flowcontrol during roaming */
-	if ((dhdp->dequeue_prec_map == 1 << PRIO_8021D_NC) && state == ON) {
-		return;
-	}
-#endif
-
-	if (ifidx == ALL_INTERFACES) {
-		/* Flow control on all active interfaces */
-		dhdp->txoff = state;
-		for (i = 0; i < DHD_MAX_IFS; i++) {
-			if (dhd->iflist[i]) {
-				net = dhd->iflist[i]->net;
-				if (state == ON)
-					netif_stop_queue(net);
-				else
-					netif_wake_queue(net);
-			}
-		}
-	} else {
-		if (dhd->iflist[ifidx]) {
-			net = dhd->iflist[ifidx]->net;
-			if (state == ON)
-				netif_stop_queue(net);
-			else
-				netif_wake_queue(net);
-		}
-	}
-}
-
-#ifdef DHD_RX_DUMP
-typedef struct {
-	uint16 type;
-	const char *str;
-} PKTTYPE_INFO;
-
-static const PKTTYPE_INFO packet_type_info[] =
-{
-	{ ETHER_TYPE_IP, "IP" },
-	{ ETHER_TYPE_ARP, "ARP" },
-	{ ETHER_TYPE_BRCM, "BRCM" },
-	{ ETHER_TYPE_802_1X, "802.1X" },
-	{ 0, ""}
-};
-
-static const char *_get_packet_type_str(uint16 type)
-{
-	int i;
-	int n = sizeof(packet_type_info)/sizeof(packet_type_info[1]) - 1;
-
-	for (i = 0; i < n; i++) {
-		if (packet_type_info[i].type == type)
-			return packet_type_info[i].str;
-	}
-
-	return packet_type_info[n].str;
-}
-#endif /* DHD_RX_DUMP */
-
-
-#ifdef DHD_WMF
-bool
-dhd_is_rxthread_enabled(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd = dhdp->info;
-
-	return dhd->rxthread_enabled;
-}
-#endif /* DHD_WMF */
-
-/** Called when a frame is received by the dongle on interface 'ifidx' */
-void
-dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
-{
-	dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
-	struct sk_buff *skb;
-	uchar *eth;
-	uint len;
-	void *data, *pnext = NULL;
-	int i;
-	dhd_if_t *ifp;
-	wl_event_msg_t event;
-	int tout_rx = 0;
-	int tout_ctrl = 0;
-	void *skbhead = NULL;
-	void *skbprev = NULL;
-#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP) || defined(DHD_DHCP_DUMP)
-	char *dump_data;
-	uint16 protocol;
-	char *ifname;
-#endif /* DHD_RX_DUMP || DHD_8021X_DUMP || DHD_DHCP_DUMP */
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) {
-		struct ether_header *eh;
-
-		pnext = PKTNEXT(dhdp->osh, pktbuf);
-		PKTSETNEXT(dhdp->osh, pktbuf, NULL);
-
-		ifp = dhd->iflist[ifidx];
-		if (ifp == NULL) {
-			DHD_ERROR(("%s: ifp is NULL. drop packet\n",
-				__FUNCTION__));
-			PKTCFREE(dhdp->osh, pktbuf, FALSE);
-			continue;
-		}
-
-		eh = (struct ether_header *)PKTDATA(dhdp->osh, pktbuf);
-
-		/* Dropping only data packets before registering net device to avoid kernel panic */
-#ifndef PROP_TXSTATUS_VSDB
-		if ((!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) &&
-			(ntoh16(eh->ether_type) != ETHER_TYPE_BRCM)) {
-#else
-		if ((!ifp->net || ifp->net->reg_state != NETREG_REGISTERED || !dhd->pub.up) &&
-			(ntoh16(eh->ether_type) != ETHER_TYPE_BRCM)) {
-#endif /* PROP_TXSTATUS_VSDB */
-			DHD_ERROR(("%s: net device is NOT registered yet. drop packet\n",
-			__FUNCTION__));
-			PKTCFREE(dhdp->osh, pktbuf, FALSE);
-			continue;
-		}
-
-
-#ifdef PROP_TXSTATUS
-		if (dhd_wlfc_is_header_only_pkt(dhdp, pktbuf)) {
-			/* WLFC may send header only packet when
-			there is an urgent message but no packet to
-			piggy-back on
-			*/
-			PKTCFREE(dhdp->osh, pktbuf, FALSE);
-			continue;
-		}
-#endif
-#ifdef DHD_L2_FILTER
-		/* If block_ping is enabled drop the ping packet */
-		if (ifp->block_ping) {
-			if (bcm_l2_filter_block_ping(dhdp->osh, pktbuf) == BCME_OK) {
-				PKTCFREE(dhdp->osh, pktbuf, FALSE);
-				continue;
-			}
-		}
-		if (ifp->grat_arp && DHD_IF_ROLE_STA(dhdp, ifidx)) {
-		    if (bcm_l2_filter_gratuitous_arp(dhdp->osh, pktbuf) == BCME_OK) {
-				PKTCFREE(dhdp->osh, pktbuf, FALSE);
-				continue;
-		    }
-		}
-		if (ifp->parp_enable && DHD_IF_ROLE_AP(dhdp, ifidx)) {
-			int ret = dhd_l2_filter_pkt_handle(dhdp, ifidx, pktbuf, FALSE);
-
-			/* Drop the packets if l2 filter has processed it already
-			 * otherwise continue with the normal path
-			 */
-			if (ret == BCME_OK) {
-				PKTCFREE(dhdp->osh, pktbuf, TRUE);
-				continue;
-			}
-		}
-#endif /* DHD_L2_FILTER */
-#ifdef DHD_WMF
-		/* WMF processing for multicast packets */
-		if (ifp->wmf.wmf_enable && (ETHER_ISMULTI(eh->ether_dhost))) {
-			dhd_sta_t *sta;
-			int ret;
-
-			sta = dhd_find_sta(dhdp, ifidx, (void *)eh->ether_shost);
-			ret = dhd_wmf_packets_handle(dhdp, pktbuf, sta, ifidx, 1);
-			switch (ret) {
-				case WMF_TAKEN:
-					/* The packet is taken by WMF. Continue to next iteration */
-					continue;
-				case WMF_DROP:
-					/* Packet DROP decision by WMF. Toss it */
-					DHD_ERROR(("%s: WMF decides to drop packet\n",
-						__FUNCTION__));
-					PKTCFREE(dhdp->osh, pktbuf, FALSE);
-					continue;
-				default:
-					/* Continue the transmit path */
-					break;
-			}
-		}
-#endif /* DHD_WMF */
-
-#ifdef DHDTCPACK_SUPPRESS
-		dhd_tcpdata_info_get(dhdp, pktbuf);
-#endif
-		skb = PKTTONATIVE(dhdp->osh, pktbuf);
-
-		ASSERT(ifp);
-		skb->dev = ifp->net;
-
-#ifdef DHD_PSTA
-		if (PSR_ENABLED(dhdp) && (dhd_psta_proc(dhdp, ifidx, &pktbuf, FALSE) < 0)) {
-				DHD_ERROR(("%s:%s: psta recv proc failed\n", __FUNCTION__,
-					dhd_ifname(dhdp, ifidx)));
-		}
-#endif /* DHD_PSTA */
-
-#ifdef PCIE_FULL_DONGLE
-		if ((DHD_IF_ROLE_AP(dhdp, ifidx) || DHD_IF_ROLE_P2PGO(dhdp, ifidx)) &&
-			(!ifp->ap_isolate)) {
-			eh = (struct ether_header *)PKTDATA(dhdp->osh, pktbuf);
-			if (ETHER_ISUCAST(eh->ether_dhost)) {
-				if (dhd_find_sta(dhdp, ifidx, (void *)eh->ether_dhost)) {
-					dhd_sendpkt(dhdp, ifidx, pktbuf);
-					continue;
-				}
-			} else {
-				void *npktbuf = PKTDUP(dhdp->osh, pktbuf);
-				if (npktbuf)
-					dhd_sendpkt(dhdp, ifidx, npktbuf);
-			}
-		}
-#endif /* PCIE_FULL_DONGLE */
-
-		/* Get the protocol, maintain skb around eth_type_trans()
-		 * The main reason for this hack is for the limitation of
-		 * Linux 2.4 where 'eth_type_trans' uses the 'net->hard_header_len'
-		 * to perform skb_pull inside vs ETH_HLEN. Since to avoid
-		 * coping of the packet coming from the network stack to add
-		 * BDC, Hardware header etc, during network interface registration
-		 * we set the 'net->hard_header_len' to ETH_HLEN + extra space required
-		 * for BDC, Hardware header etc. and not just the ETH_HLEN
-		 */
-		eth = skb->data;
-		len = skb->len;
-
-#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP) || defined(DHD_DHCP_DUMP)
-		dump_data = skb->data;
-		protocol = (dump_data[12] << 8) | dump_data[13];
-		ifname = skb->dev ? skb->dev->name : "N/A";
-#endif /* DHD_RX_DUMP || DHD_8021X_DUMP || DHD_DHCP_DUMP */
-#ifdef DHD_8021X_DUMP
-		if (protocol == ETHER_TYPE_802_1X) {
-			dhd_dump_eapol_4way_message(ifname, dump_data, FALSE);
-		}
-#endif /* DHD_8021X_DUMP */
-#ifdef DHD_DHCP_DUMP
-		if (protocol != ETHER_TYPE_BRCM && protocol == ETHER_TYPE_IP) {
-			uint16 dump_hex;
-			uint16 source_port;
-			uint16 dest_port;
-			uint16 udp_port_pos;
-			uint8 *ptr8 = (uint8 *)&dump_data[ETHER_HDR_LEN];
-			uint8 ip_header_len = (*ptr8 & 0x0f)<<2;
-
-			udp_port_pos = ETHER_HDR_LEN + ip_header_len;
-			source_port = (dump_data[udp_port_pos] << 8) | dump_data[udp_port_pos+1];
-			dest_port = (dump_data[udp_port_pos+2] << 8) | dump_data[udp_port_pos+3];
-			if (source_port == 0x0044 || dest_port == 0x0044) {
-				dump_hex = (dump_data[udp_port_pos+249] << 8) |
-					dump_data[udp_port_pos+250];
-				if (dump_hex == 0x0101) {
-					DHD_ERROR(("DHCP[%s] - DISCOVER [RX]\n", ifname));
-				} else if (dump_hex == 0x0102) {
-					DHD_ERROR(("DHCP[%s] - OFFER [RX]\n", ifname));
-				} else if (dump_hex == 0x0103) {
-					DHD_ERROR(("DHCP[%s] - REQUEST [RX]\n", ifname));
-				} else if (dump_hex == 0x0105) {
-					DHD_ERROR(("DHCP[%s] - ACK [RX]\n", ifname));
-				} else {
-					DHD_ERROR(("DHCP[%s] - 0x%X [RX]\n", ifname, dump_hex));
-				}
-			} else if (source_port == 0x0043 || dest_port == 0x0043) {
-				DHD_ERROR(("DHCP[%s] - BOOTP [RX]\n", ifname));
-			}
-		}
-#endif /* DHD_DHCP_DUMP */
-#if defined(DHD_RX_DUMP)
-		DHD_ERROR(("RX DUMP[%s] - %s\n", ifname, _get_packet_type_str(protocol)));
-		if (protocol != ETHER_TYPE_BRCM) {
-			if (dump_data[0] == 0xFF) {
-				DHD_ERROR(("%s: BROADCAST\n", __FUNCTION__));
-
-				if ((dump_data[12] == 8) &&
-					(dump_data[13] == 6)) {
-					DHD_ERROR(("%s: ARP %d\n",
-						__FUNCTION__, dump_data[0x15]));
-				}
-			} else if (dump_data[0] & 1) {
-				DHD_ERROR(("%s: MULTICAST: " MACDBG "\n",
-					__FUNCTION__, MAC2STRDBG(dump_data)));
-			}
-#ifdef DHD_RX_FULL_DUMP
-			{
-				int k;
-				for (k = 0; k < skb->len; k++) {
-					DHD_ERROR(("%02X ", dump_data[k]));
-					if ((k & 15) == 15)
-						DHD_ERROR(("\n"));
-				}
-				DHD_ERROR(("\n"));
-			}
-#endif /* DHD_RX_FULL_DUMP */
-		}
-#endif /* DHD_RX_DUMP */
-
-		skb->protocol = eth_type_trans(skb, skb->dev);
-
-		if (skb->pkt_type == PACKET_MULTICAST) {
-			dhd->pub.rx_multicast++;
-			ifp->stats.multicast++;
-		}
-
-		skb->data = eth;
-		skb->len = len;
-
-#ifdef WLMEDIA_HTSF
-		dhd_htsf_addrxts(dhdp, pktbuf);
-#endif
-		/* Strip header, count, deliver upward */
-		skb_pull(skb, ETH_HLEN);
-
-		/* Process special event packets and then discard them */
-		memset(&event, 0, sizeof(event));
-		if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) {
-			dhd_wl_host_event(dhd, &ifidx,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
-			skb_mac_header(skb),
-#else
-			skb->mac.raw,
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) */
-			len - 2,
-			&event,
-			&data);
-
-			wl_event_to_host_order(&event);
-			if (!tout_ctrl)
-				tout_ctrl = DHD_PACKET_TIMEOUT_MS;
-
-#if defined(PNO_SUPPORT)
-			if (event.event_type == WLC_E_PFN_NET_FOUND) {
-				/* enforce custom wake lock to garantee that Kernel not suspended */
-				tout_ctrl = CUSTOM_PNO_EVENT_LOCK_xTIME * DHD_PACKET_TIMEOUT_MS;
-			}
-#endif /* PNO_SUPPORT */
-
-#ifdef DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT
-#ifdef DHD_USE_STATIC_CTRLBUF
-			PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE);
-#else
-			PKTFREE(dhdp->osh, pktbuf, FALSE);
-#endif /* DHD_USE_STATIC_CTRLBUF */
-			continue;
-#endif /* DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT */
-		} else {
-			tout_rx = DHD_PACKET_TIMEOUT_MS;
-
-#ifdef PROP_TXSTATUS
-			dhd_wlfc_save_rxpath_ac_time(dhdp, (uint8)PKTPRIO(skb));
-#endif /* PROP_TXSTATUS */
-		}
-
-		ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
-		ifp = dhd->iflist[ifidx];
-
-		if (ifp->net)
-			ifp->net->last_rx = jiffies;
-
-		if (ntoh16(skb->protocol) != ETHER_TYPE_BRCM) {
-			dhdp->dstats.rx_bytes += skb->len;
-			dhdp->rx_packets++; /* Local count */
-			ifp->stats.rx_bytes += skb->len;
-			ifp->stats.rx_packets++;
-		}
-
-		if (in_interrupt()) {
-			bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE,
-				__FUNCTION__, __LINE__);
-			DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT));
-#if defined(DHD_LB) && defined(DHD_LB_RXP)
-			netif_receive_skb(skb);
-#else
-			netif_rx(skb);
-#endif /* !defined(DHD_LB) && !defined(DHD_LB_RXP) */
-			DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT));
-		} else {
-			if (dhd->rxthread_enabled) {
-				if (!skbhead)
-					skbhead = skb;
-				else
-					PKTSETNEXT(dhdp->osh, skbprev, skb);
-				skbprev = skb;
-			} else {
-
-				/* If the receive is not processed inside an ISR,
-				 * the softirqd must be woken explicitly to service
-				 * the NET_RX_SOFTIRQ.	In 2.6 kernels, this is handled
-				 * by netif_rx_ni(), but in earlier kernels, we need
-				 * to do it manually.
-				 */
-				bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE,
-					__FUNCTION__, __LINE__);
-
-#if defined(DHD_LB) && defined(DHD_LB_RXP)
-				DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT));
-				netif_receive_skb(skb);
-				DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT));
-#else
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-				DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT));
-				netif_rx_ni(skb);
-				DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT));
-#else
-				ulong flags;
-				DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT));
-				netif_rx(skb);
-				DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT));
-				local_irq_save(flags);
-				RAISE_RX_SOFTIRQ();
-				local_irq_restore(flags);
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
-#endif /* !defined(DHD_LB) && !defined(DHD_LB_RXP) */
-			}
-		}
-	}
-
-	if (dhd->rxthread_enabled && skbhead)
-		dhd_sched_rxf(dhdp, skbhead);
-
-	DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx);
-	DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl);
-	DHD_OS_WAKE_LOCK_TIMEOUT(dhdp);
-}
-
-void
-dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx)
-{
-	/* Linux version has nothing to do */
-	return;
-}
-
-void
-dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
-	struct ether_header *eh;
-	uint16 type;
-
-	dhd_prot_hdrpull(dhdp, NULL, txp, NULL, NULL);
-
-	eh = (struct ether_header *)PKTDATA(dhdp->osh, txp);
-	type  = ntoh16(eh->ether_type);
-
-	if ((type == ETHER_TYPE_802_1X) && (dhd_get_pend_8021x_cnt(dhd) > 0))
-		atomic_dec(&dhd->pend_8021x_cnt);
-
-#ifdef PROP_TXSTATUS
-	if (dhdp->wlfc_state && (dhdp->proptxstatus_mode != WLFC_FCMODE_NONE)) {
-		dhd_if_t *ifp = dhd->iflist[DHD_PKTTAG_IF(PKTTAG(txp))];
-		uint datalen  = PKTLEN(dhd->pub.osh, txp);
-		if (ifp != NULL) {
-			if (success) {
-				dhd->pub.tx_packets++;
-				ifp->stats.tx_packets++;
-				ifp->stats.tx_bytes += datalen;
-			} else {
-				ifp->stats.tx_dropped++;
-			}
-		}
-	}
-#endif
-}
-
-static struct net_device_stats *
-dhd_get_stats(struct net_device *net)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(net);
-	dhd_if_t *ifp;
-	int ifidx;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	ifidx = dhd_net2idx(dhd, net);
-	if (ifidx == DHD_BAD_IF) {
-		DHD_ERROR(("%s: BAD_IF\n", __FUNCTION__));
-
-		memset(&net->stats, 0, sizeof(net->stats));
-		return &net->stats;
-	}
-
-	ifp = dhd->iflist[ifidx];
-	ASSERT(dhd && ifp);
-
-	if (dhd->pub.up) {
-		/* Use the protocol to get dongle stats */
-		dhd_prot_dstats(&dhd->pub);
-	}
-	return &ifp->stats;
-}
-
-static int
-dhd_watchdog_thread(void *data)
-{
-	tsk_ctl_t *tsk = (tsk_ctl_t *)data;
-	dhd_info_t *dhd = (dhd_info_t *)tsk->parent;
-	/* This thread doesn't need any user-level access,
-	 * so get rid of all our resources
-	 */
-	if (dhd_watchdog_prio > 0) {
-		struct sched_param param;
-		param.sched_priority = (dhd_watchdog_prio < MAX_RT_PRIO)?
-			dhd_watchdog_prio:(MAX_RT_PRIO-1);
-		setScheduler(current, SCHED_FIFO, &param);
-	}
-
-	while (1) {
-		if (down_interruptible (&tsk->sema) == 0) {
-			unsigned long flags;
-			unsigned long jiffies_at_start = jiffies;
-			unsigned long time_lapse;
-
-			DHD_OS_WD_WAKE_LOCK(&dhd->pub);
-			SMP_RD_BARRIER_DEPENDS();
-			if (tsk->terminated) {
-				break;
-			}
-
-			if (dhd->pub.dongle_reset == FALSE) {
-				DHD_TIMER(("%s:\n", __FUNCTION__));
-				dhd_bus_watchdog(&dhd->pub);
-
-				DHD_GENERAL_LOCK(&dhd->pub, flags);
-				/* Count the tick for reference */
-				dhd->pub.tickcnt++;
-#ifdef DHD_L2_FILTER
-				dhd_l2_filter_watchdog(&dhd->pub);
-#endif /* DHD_L2_FILTER */
-				time_lapse = jiffies - jiffies_at_start;
-
-				/* Reschedule the watchdog */
-				if (dhd->wd_timer_valid) {
-					mod_timer(&dhd->timer,
-					    jiffies +
-					    msecs_to_jiffies(dhd_watchdog_ms) -
-					    min(msecs_to_jiffies(dhd_watchdog_ms), time_lapse));
-				}
-				DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-			}
-			DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
-		} else {
-			break;
-		}
-	}
-
-	complete_and_exit(&tsk->completed, 0);
-}
-
-static void dhd_watchdog(ulong data)
-{
-	dhd_info_t *dhd = (dhd_info_t *)data;
-	unsigned long flags;
-
-	if (dhd->pub.dongle_reset) {
-		return;
-	}
-
-	if (dhd->pub.busstate == DHD_BUS_SUSPEND) {
-		DHD_ERROR(("%s wd while suspend in progress \n", __FUNCTION__));
-		return;
-	}
-
-	if (dhd->thr_wdt_ctl.thr_pid >= 0) {
-		up(&dhd->thr_wdt_ctl.sema);
-		return;
-	}
-
-	DHD_OS_WD_WAKE_LOCK(&dhd->pub);
-	/* Call the bus module watchdog */
-	dhd_bus_watchdog(&dhd->pub);
-	DHD_GENERAL_LOCK(&dhd->pub, flags);
-	/* Count the tick for reference */
-	dhd->pub.tickcnt++;
-
-#ifdef DHD_L2_FILTER
-	dhd_l2_filter_watchdog(&dhd->pub);
-#endif /* DHD_L2_FILTER */
-	/* Reschedule the watchdog */
-	if (dhd->wd_timer_valid)
-		mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms));
-	DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-	DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
-}
-
-#ifdef DHD_PCIE_RUNTIMEPM
-static int
-dhd_rpm_state_thread(void *data)
-{
-	tsk_ctl_t *tsk = (tsk_ctl_t *)data;
-	dhd_info_t *dhd = (dhd_info_t *)tsk->parent;
-
-	while (1) {
-		if (down_interruptible (&tsk->sema) == 0) {
-			unsigned long flags;
-			unsigned long jiffies_at_start = jiffies;
-			unsigned long time_lapse;
-
-			SMP_RD_BARRIER_DEPENDS();
-			if (tsk->terminated) {
-				break;
-			}
-
-			if (dhd->pub.dongle_reset == FALSE) {
-				DHD_TIMER(("%s:\n", __FUNCTION__));
-				if (dhd->pub.up) {
-					dhd_runtimepm_state(&dhd->pub);
-				}
-
-				DHD_GENERAL_LOCK(&dhd->pub, flags);
-				time_lapse = jiffies - jiffies_at_start;
-
-				/* Reschedule the watchdog */
-				if (dhd->rpm_timer_valid) {
-					mod_timer(&dhd->rpm_timer,
-						jiffies +
-						msecs_to_jiffies(dhd_runtimepm_ms) -
-						min(msecs_to_jiffies(dhd_runtimepm_ms),
-							time_lapse));
-				}
-				DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-			}
-		} else {
-			break;
-		}
-	}
-
-	complete_and_exit(&tsk->completed, 0);
-}
-
-static void dhd_runtimepm(ulong data)
-{
-	dhd_info_t *dhd = (dhd_info_t *)data;
-
-	if (dhd->pub.dongle_reset) {
-		return;
-	}
-
-	if (dhd->thr_rpm_ctl.thr_pid >= 0) {
-		up(&dhd->thr_rpm_ctl.sema);
-		return;
-	}
-}
-
-void dhd_runtime_pm_disable(dhd_pub_t *dhdp)
-{
-	dhd_os_runtimepm_timer(dhdp, 0);
-	dhdpcie_runtime_bus_wake(dhdp, TRUE, __builtin_return_address(0));
-	DHD_ERROR(("DHD Runtime PM Disabled \n"));
-}
-
-void dhd_runtime_pm_enable(dhd_pub_t *dhdp)
-{
-	dhd_os_runtimepm_timer(dhdp, dhd_runtimepm_ms);
-	DHD_ERROR(("DHD Runtime PM Enabled \n"));
-}
-
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-
-#ifdef ENABLE_ADAPTIVE_SCHED
-static void
-dhd_sched_policy(int prio)
-{
-	struct sched_param param;
-	if (cpufreq_quick_get(0) <= CUSTOM_CPUFREQ_THRESH) {
-		param.sched_priority = 0;
-		setScheduler(current, SCHED_NORMAL, &param);
-	} else {
-		if (get_scheduler_policy(current) != SCHED_FIFO) {
-			param.sched_priority = (prio < MAX_RT_PRIO)? prio : (MAX_RT_PRIO-1);
-			setScheduler(current, SCHED_FIFO, &param);
-		}
-	}
-}
-#endif /* ENABLE_ADAPTIVE_SCHED */
-#ifdef DEBUG_CPU_FREQ
-static int dhd_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
-{
-	dhd_info_t *dhd = container_of(nb, struct dhd_info, freq_trans);
-	struct cpufreq_freqs *freq = data;
-	if (dhd) {
-		if (!dhd->new_freq)
-			goto exit;
-		if (val == CPUFREQ_POSTCHANGE) {
-			DHD_ERROR(("cpu freq is changed to %u kHZ on CPU %d\n",
-				freq->new, freq->cpu));
-			*per_cpu_ptr(dhd->new_freq, freq->cpu) = freq->new;
-		}
-	}
-exit:
-	return 0;
-}
-#endif /* DEBUG_CPU_FREQ */
-static int
-dhd_dpc_thread(void *data)
-{
-	tsk_ctl_t *tsk = (tsk_ctl_t *)data;
-	dhd_info_t *dhd = (dhd_info_t *)tsk->parent;
-
-	/* This thread doesn't need any user-level access,
-	 * so get rid of all our resources
-	 */
-	if (dhd_dpc_prio > 0)
-	{
-		struct sched_param param;
-		param.sched_priority = (dhd_dpc_prio < MAX_RT_PRIO)?dhd_dpc_prio:(MAX_RT_PRIO-1);
-		setScheduler(current, SCHED_FIFO, &param);
-	}
-
-#ifdef CUSTOM_DPC_CPUCORE
-	set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_DPC_CPUCORE));
-#endif
-#ifdef CUSTOM_SET_CPUCORE
-	dhd->pub.current_dpc = current;
-#endif /* CUSTOM_SET_CPUCORE */
-	/* Run until signal received */
-	while (1) {
-		if (!binary_sema_down(tsk)) {
-#ifdef ENABLE_ADAPTIVE_SCHED
-			dhd_sched_policy(dhd_dpc_prio);
-#endif /* ENABLE_ADAPTIVE_SCHED */
-			SMP_RD_BARRIER_DEPENDS();
-			if (tsk->terminated) {
-				break;
-			}
-
-			/* Call bus dpc unless it indicated down (then clean stop) */
-			if (dhd->pub.busstate != DHD_BUS_DOWN) {
-#ifdef DEBUG_DPC_THREAD_WATCHDOG
-				int resched_cnt = 0;
-#endif /* DEBUG_DPC_THREAD_WATCHDOG */
-				dhd_os_wd_timer_extend(&dhd->pub, TRUE);
-				while (dhd_bus_dpc(dhd->pub.bus)) {
-					/* process all data */
-#ifdef DEBUG_DPC_THREAD_WATCHDOG
-					resched_cnt++;
-					if (resched_cnt > MAX_RESCHED_CNT) {
-						DHD_INFO(("%s Calling msleep to"
-							"let other processes run. \n",
-							__FUNCTION__));
-						dhd->pub.dhd_bug_on = true;
-						resched_cnt = 0;
-						OSL_SLEEP(1);
-					}
-#endif /* DEBUG_DPC_THREAD_WATCHDOG */
-				}
-				dhd_os_wd_timer_extend(&dhd->pub, FALSE);
-				DHD_OS_WAKE_UNLOCK(&dhd->pub);
-			} else {
-				if (dhd->pub.up)
-					dhd_bus_stop(dhd->pub.bus, TRUE);
-				DHD_OS_WAKE_UNLOCK(&dhd->pub);
-			}
-		} else {
-			break;
-		}
-	}
-	complete_and_exit(&tsk->completed, 0);
-}
-
-static int
-dhd_rxf_thread(void *data)
-{
-	tsk_ctl_t *tsk = (tsk_ctl_t *)data;
-	dhd_info_t *dhd = (dhd_info_t *)tsk->parent;
-#if defined(WAIT_DEQUEUE)
-#define RXF_WATCHDOG_TIME 250 /* BARK_TIME(1000) /  */
-	ulong watchdogTime = OSL_SYSUPTIME(); /* msec */
-#endif
-	dhd_pub_t *pub = &dhd->pub;
-
-	/* This thread doesn't need any user-level access,
-	 * so get rid of all our resources
-	 */
-	if (dhd_rxf_prio > 0)
-	{
-		struct sched_param param;
-		param.sched_priority = (dhd_rxf_prio < MAX_RT_PRIO)?dhd_rxf_prio:(MAX_RT_PRIO-1);
-		setScheduler(current, SCHED_FIFO, &param);
-	}
-
-	DAEMONIZE("dhd_rxf");
-	/* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below  */
-
-	/*  signal: thread has started */
-	complete(&tsk->completed);
-#ifdef CUSTOM_SET_CPUCORE
-	dhd->pub.current_rxf = current;
-#endif /* CUSTOM_SET_CPUCORE */
-	/* Run until signal received */
-	while (1) {
-		if (down_interruptible(&tsk->sema) == 0) {
-			void *skb;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
-			ulong flags;
-#endif
-#ifdef ENABLE_ADAPTIVE_SCHED
-			dhd_sched_policy(dhd_rxf_prio);
-#endif /* ENABLE_ADAPTIVE_SCHED */
-
-			SMP_RD_BARRIER_DEPENDS();
-
-			if (tsk->terminated) {
-				break;
-			}
-			skb = dhd_rxf_dequeue(pub);
-
-			if (skb == NULL) {
-				continue;
-			}
-			while (skb) {
-				void *skbnext = PKTNEXT(pub->osh, skb);
-				PKTSETNEXT(pub->osh, skb, NULL);
-				bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE,
-					__FUNCTION__, __LINE__);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-				netif_rx_ni(skb);
-#else
-				netif_rx(skb);
-				local_irq_save(flags);
-				RAISE_RX_SOFTIRQ();
-				local_irq_restore(flags);
-
-#endif
-				skb = skbnext;
-			}
-#if defined(WAIT_DEQUEUE)
-			if (OSL_SYSUPTIME() - watchdogTime > RXF_WATCHDOG_TIME) {
-				OSL_SLEEP(1);
-				watchdogTime = OSL_SYSUPTIME();
-			}
-#endif
-
-			DHD_OS_WAKE_UNLOCK(pub);
-		} else {
-			break;
-		}
-	}
-	complete_and_exit(&tsk->completed, 0);
-}
-
-#ifdef BCMPCIE
-void dhd_dpc_enable(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd;
-
-	if (!dhdp || !dhdp->info)
-		return;
-	dhd = dhdp->info;
-
-#ifdef DHD_LB
-#ifdef DHD_LB_RXP
-	__skb_queue_head_init(&dhd->rx_pend_queue);
-#endif /* DHD_LB_RXP */
-#ifdef DHD_LB_TXC
-	if (atomic_read(&dhd->tx_compl_tasklet.count) == 1)
-		tasklet_enable(&dhd->tx_compl_tasklet);
-#endif /* DHD_LB_TXC */
-#ifdef DHD_LB_RXC
-	if (atomic_read(&dhd->rx_compl_tasklet.count) == 1)
-		tasklet_enable(&dhd->rx_compl_tasklet);
-#endif /* DHD_LB_RXC */
-#endif /* DHD_LB */
-	if (atomic_read(&dhd->tasklet.count) ==  1)
-		tasklet_enable(&dhd->tasklet);
-}
-#endif /* BCMPCIE */
-
-
-#ifdef BCMPCIE
-void
-dhd_dpc_kill(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd;
-
-	if (!dhdp) {
-		return;
-	}
-
-	dhd = dhdp->info;
-
-	if (!dhd) {
-		return;
-	}
-
-	if (dhd->thr_dpc_ctl.thr_pid < 0) {
-		tasklet_disable(&dhd->tasklet);
-		tasklet_kill(&dhd->tasklet);
-		DHD_ERROR(("%s: tasklet disabled\n", __FUNCTION__));
-	}
-#if defined(DHD_LB)
-#ifdef DHD_LB_RXP
-	__skb_queue_purge(&dhd->rx_pend_queue);
-#endif /* DHD_LB_RXP */
-	/* Kill the Load Balancing Tasklets */
-#if defined(DHD_LB_TXC)
-	tasklet_disable(&dhd->tx_compl_tasklet);
-	tasklet_kill(&dhd->tx_compl_tasklet);
-#endif /* DHD_LB_TXC */
-#if defined(DHD_LB_RXC)
-	tasklet_disable(&dhd->rx_compl_tasklet);
-	tasklet_kill(&dhd->rx_compl_tasklet);
-#endif /* DHD_LB_RXC */
-#endif /* DHD_LB */
-}
-#endif /* BCMPCIE */
-
-static void
-dhd_dpc(ulong data)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *)data;
-
-	/* this (tasklet) can be scheduled in dhd_sched_dpc[dhd_linux.c]
-	 * down below , wake lock is set,
-	 * the tasklet is initialized in dhd_attach()
-	 */
-	/* Call bus dpc unless it indicated down (then clean stop) */
-	if (dhd->pub.busstate != DHD_BUS_DOWN) {
-		if (dhd_bus_dpc(dhd->pub.bus)) {
-			DHD_LB_STATS_INCR(dhd->dhd_dpc_cnt);
-			tasklet_schedule(&dhd->tasklet);
-		}
-	} else {
-		dhd_bus_stop(dhd->pub.bus, TRUE);
-	}
-}
-
-void
-dhd_sched_dpc(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
-
-	if (dhd->thr_dpc_ctl.thr_pid >= 0) {
-		DHD_OS_WAKE_LOCK(dhdp);
-		/* If the semaphore does not get up,
-		* wake unlock should be done here
-		*/
-		if (!binary_sema_up(&dhd->thr_dpc_ctl)) {
-			DHD_OS_WAKE_UNLOCK(dhdp);
-		}
-		return;
-	} else {
-		tasklet_schedule(&dhd->tasklet);
-	}
-}
-
-static void
-dhd_sched_rxf(dhd_pub_t *dhdp, void *skb)
-{
-	dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
-#ifdef RXF_DEQUEUE_ON_BUSY
-	int ret = BCME_OK;
-	int retry = 2;
-#endif /* RXF_DEQUEUE_ON_BUSY */
-
-	DHD_OS_WAKE_LOCK(dhdp);
-
-	DHD_TRACE(("dhd_sched_rxf: Enter\n"));
-#ifdef RXF_DEQUEUE_ON_BUSY
-	do {
-		ret = dhd_rxf_enqueue(dhdp, skb);
-		if (ret == BCME_OK || ret == BCME_ERROR)
-			break;
-		else
-			OSL_SLEEP(50); /* waiting for dequeueing */
-	} while (retry-- > 0);
-
-	if (retry <= 0 && ret == BCME_BUSY) {
-		void *skbp = skb;
-
-		while (skbp) {
-			void *skbnext = PKTNEXT(dhdp->osh, skbp);
-			PKTSETNEXT(dhdp->osh, skbp, NULL);
-			bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE,
-				__FUNCTION__, __LINE__);
-			netif_rx_ni(skbp);
-			skbp = skbnext;
-		}
-		DHD_ERROR(("send skb to kernel backlog without rxf_thread\n"));
-	} else {
-		if (dhd->thr_rxf_ctl.thr_pid >= 0) {
-			up(&dhd->thr_rxf_ctl.sema);
-		}
-	}
-#else /* RXF_DEQUEUE_ON_BUSY */
-	do {
-		if (dhd_rxf_enqueue(dhdp, skb) == BCME_OK)
-			break;
-	} while (1);
-	if (dhd->thr_rxf_ctl.thr_pid >= 0) {
-		up(&dhd->thr_rxf_ctl.sema);
-	}
-	return;
-#endif /* RXF_DEQUEUE_ON_BUSY */
-}
-
-#if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW)
-#endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */
-
-#ifdef TOE
-/* Retrieve current toe component enables, which are kept as a bitmap in toe_ol iovar */
-static int
-dhd_toe_get(dhd_info_t *dhd, int ifidx, uint32 *toe_ol)
-{
-	wl_ioctl_t ioc;
-	char buf[32];
-	int ret;
-
-	memset(&ioc, 0, sizeof(ioc));
-
-	ioc.cmd = WLC_GET_VAR;
-	ioc.buf = buf;
-	ioc.len = (uint)sizeof(buf);
-	ioc.set = FALSE;
-
-	strncpy(buf, "toe_ol", sizeof(buf) - 1);
-	buf[sizeof(buf) - 1] = '\0';
-	if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) {
-		/* Check for older dongle image that doesn't support toe_ol */
-		if (ret == -EIO) {
-			DHD_ERROR(("%s: toe not supported by device\n",
-				dhd_ifname(&dhd->pub, ifidx)));
-			return -EOPNOTSUPP;
-		}
-
-		DHD_INFO(("%s: could not get toe_ol: ret=%d\n", dhd_ifname(&dhd->pub, ifidx), ret));
-		return ret;
-	}
-
-	memcpy(toe_ol, buf, sizeof(uint32));
-	return 0;
-}
-
-/* Set current toe component enables in toe_ol iovar, and set toe global enable iovar */
-static int
-dhd_toe_set(dhd_info_t *dhd, int ifidx, uint32 toe_ol)
-{
-	wl_ioctl_t ioc;
-	char buf[32];
-	int toe, ret;
-
-	memset(&ioc, 0, sizeof(ioc));
-
-	ioc.cmd = WLC_SET_VAR;
-	ioc.buf = buf;
-	ioc.len = (uint)sizeof(buf);
-	ioc.set = TRUE;
-
-	/* Set toe_ol as requested */
-
-	strncpy(buf, "toe_ol", sizeof(buf) - 1);
-	buf[sizeof(buf) - 1] = '\0';
-	memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(uint32));
-
-	if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) {
-		DHD_ERROR(("%s: could not set toe_ol: ret=%d\n",
-			dhd_ifname(&dhd->pub, ifidx), ret));
-		return ret;
-	}
-
-	/* Enable toe globally only if any components are enabled. */
-
-	toe = (toe_ol != 0);
-
-	strcpy(buf, "toe");
-	memcpy(&buf[sizeof("toe")], &toe, sizeof(uint32));
-
-	if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) {
-		DHD_ERROR(("%s: could not set toe: ret=%d\n", dhd_ifname(&dhd->pub, ifidx), ret));
-		return ret;
-	}
-
-	return 0;
-}
-#endif /* TOE */
-
-#if defined(WL_CFG80211) && defined(NUM_SCB_MAX_PROBE)
-void dhd_set_scb_probe(dhd_pub_t *dhd)
-{
-	int ret = 0;
-	wl_scb_probe_t scb_probe;
-	char iovbuf[WL_EVENTING_MASK_LEN + sizeof(wl_scb_probe_t)];
-
-	memset(&scb_probe, 0, sizeof(wl_scb_probe_t));
-
-	if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
-		return;
-	}
-
-	bcm_mkiovar("scb_probe", NULL, 0, iovbuf, sizeof(iovbuf));
-
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {
-		DHD_ERROR(("%s: GET max_scb_probe failed\n", __FUNCTION__));
-	}
-
-	memcpy(&scb_probe, iovbuf, sizeof(wl_scb_probe_t));
-
-	scb_probe.scb_max_probe = NUM_SCB_MAX_PROBE;
-
-	bcm_mkiovar("scb_probe", (char *)&scb_probe,
-		sizeof(wl_scb_probe_t), iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s: max_scb_probe setting failed\n", __FUNCTION__));
-		return;
-	}
-}
-#endif /* WL_CFG80211 && NUM_SCB_MAX_PROBE */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
-static void
-dhd_ethtool_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(net);
-
-	snprintf(info->driver, sizeof(info->driver), "wl");
-	snprintf(info->version, sizeof(info->version), "%lu", dhd->pub.drv_version);
-}
-
-struct ethtool_ops dhd_ethtool_ops = {
-	.get_drvinfo = dhd_ethtool_get_drvinfo
-};
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
-
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2)
-static int
-dhd_ethtool(dhd_info_t *dhd, void *uaddr)
-{
-	struct ethtool_drvinfo info;
-	char drvname[sizeof(info.driver)];
-	uint32 cmd;
-#ifdef TOE
-	struct ethtool_value edata;
-	uint32 toe_cmpnt, csum_dir;
-	int ret;
-#endif
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	/* all ethtool calls start with a cmd word */
-	if (copy_from_user(&cmd, uaddr, sizeof (uint32)))
-		return -EFAULT;
-
-	switch (cmd) {
-	case ETHTOOL_GDRVINFO:
-		/* Copy out any request driver name */
-		if (copy_from_user(&info, uaddr, sizeof(info)))
-			return -EFAULT;
-		strncpy(drvname, info.driver, sizeof(info.driver));
-		drvname[sizeof(info.driver)-1] = '\0';
-
-		/* clear struct for return */
-		memset(&info, 0, sizeof(info));
-		info.cmd = cmd;
-
-		/* if dhd requested, identify ourselves */
-		if (strcmp(drvname, "?dhd") == 0) {
-			snprintf(info.driver, sizeof(info.driver), "dhd");
-			strncpy(info.version, EPI_VERSION_STR, sizeof(info.version) - 1);
-			info.version[sizeof(info.version) - 1] = '\0';
-		}
-
-		/* otherwise, require dongle to be up */
-		else if (!dhd->pub.up) {
-			DHD_ERROR(("%s: dongle is not up\n", __FUNCTION__));
-			return -ENODEV;
-		}
-
-		/* finally, report dongle driver type */
-		else if (dhd->pub.iswl)
-			snprintf(info.driver, sizeof(info.driver), "wl");
-		else
-			snprintf(info.driver, sizeof(info.driver), "xx");
-
-		snprintf(info.version, sizeof(info.version), "%lu", dhd->pub.drv_version);
-		if (copy_to_user(uaddr, &info, sizeof(info)))
-			return -EFAULT;
-		DHD_CTL(("%s: given %*s, returning %s\n", __FUNCTION__,
-		         (int)sizeof(drvname), drvname, info.driver));
-		break;
-
-#ifdef TOE
-	/* Get toe offload components from dongle */
-	case ETHTOOL_GRXCSUM:
-	case ETHTOOL_GTXCSUM:
-		if ((ret = dhd_toe_get(dhd, 0, &toe_cmpnt)) < 0)
-			return ret;
-
-		csum_dir = (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
-
-		edata.cmd = cmd;
-		edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
-
-		if (copy_to_user(uaddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		break;
-
-	/* Set toe offload components in dongle */
-	case ETHTOOL_SRXCSUM:
-	case ETHTOOL_STXCSUM:
-		if (copy_from_user(&edata, uaddr, sizeof(edata)))
-			return -EFAULT;
-
-		/* Read the current settings, update and write back */
-		if ((ret = dhd_toe_get(dhd, 0, &toe_cmpnt)) < 0)
-			return ret;
-
-		csum_dir = (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
-
-		if (edata.data != 0)
-			toe_cmpnt |= csum_dir;
-		else
-			toe_cmpnt &= ~csum_dir;
-
-		if ((ret = dhd_toe_set(dhd, 0, toe_cmpnt)) < 0)
-			return ret;
-
-		/* If setting TX checksum mode, tell Linux the new mode */
-		if (cmd == ETHTOOL_STXCSUM) {
-			if (edata.data)
-				dhd->iflist[0]->net->features |= NETIF_F_IP_CSUM;
-			else
-				dhd->iflist[0]->net->features &= ~NETIF_F_IP_CSUM;
-		}
-
-		break;
-#endif /* TOE */
-
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return 0;
-}
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
-
-static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error)
-{
-	dhd_info_t *dhd;
-
-	if (!dhdp) {
-		DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
-		return FALSE;
-	}
-
-	if (!dhdp->up)
-		return FALSE;
-
-	dhd = (dhd_info_t *)dhdp->info;
-#if !defined(BCMPCIE)
-	if (dhd->thr_dpc_ctl.thr_pid < 0) {
-		DHD_ERROR(("%s : skipped due to negative pid - unloading?\n", __FUNCTION__));
-		return FALSE;
-	}
-#endif 
-
-	if ((error == -ETIMEDOUT) || (error == -EREMOTEIO) ||
-		((dhdp->busstate == DHD_BUS_DOWN) && (!dhdp->dongle_reset))) {
-#ifdef BCMPCIE
-		DHD_ERROR(("%s: Event HANG send up due to  re=%d te=%d d3acke=%d e=%d s=%d\n",
-			__FUNCTION__, dhdp->rxcnt_timeout, dhdp->txcnt_timeout,
-			dhdp->d3ackcnt_timeout, error, dhdp->busstate));
-#else
-		DHD_ERROR(("%s: Event HANG send up due to  re=%d te=%d e=%d s=%d\n", __FUNCTION__,
-			dhdp->rxcnt_timeout, dhdp->txcnt_timeout, error, dhdp->busstate));
-#endif /* BCMPCIE */
-		if (dhdp->hang_reason == 0) {
-			if (dhdp->dongle_trap_occured) {
-				dhdp->hang_reason = HANG_REASON_DONGLE_TRAP;
-#ifdef BCMPCIE
-			} else if (dhdp->d3ackcnt_timeout) {
-				dhdp->hang_reason = HANG_REASON_D3_ACK_TIMEOUT;
-#endif /* BCMPCIE */
-			} else {
-				dhdp->hang_reason = HANG_REASON_IOCTL_RESP_TIMEOUT;
-			}
-		}
-		net_os_send_hang_message(net);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, dhd_ioctl_t *ioc, void *data_buf)
-{
-	int bcmerror = BCME_OK;
-	int buflen = 0;
-	struct net_device *net;
-
-	net = dhd_idx2net(pub, ifidx);
-	if (!net) {
-		bcmerror = BCME_BADARG;
-		goto done;
-	}
-
-	if (data_buf)
-		buflen = MIN(ioc->len, DHD_IOCTL_MAXLEN);
-
-	/* check for local dhd ioctl and handle it */
-	if (ioc->driver == DHD_IOCTL_MAGIC) {
-		bcmerror = dhd_ioctl((void *)pub, ioc, data_buf, buflen);
-		if (bcmerror)
-			pub->bcmerror = bcmerror;
-		goto done;
-	}
-
-	/* send to dongle (must be up, and wl). */
-	if (pub->busstate == DHD_BUS_DOWN || pub->busstate == DHD_BUS_LOAD) {
-		if (allow_delay_fwdl) {
-			int ret = dhd_bus_start(pub);
-			if (ret != 0) {
-				DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
-				bcmerror = BCME_DONGLE_DOWN;
-				goto done;
-			}
-		} else {
-			bcmerror = BCME_DONGLE_DOWN;
-			goto done;
-		}
-	}
-
-	if (!pub->iswl) {
-		bcmerror = BCME_DONGLE_DOWN;
-		goto done;
-	}
-
-	/*
-	 * Flush the TX queue if required for proper message serialization:
-	 * Intercept WLC_SET_KEY IOCTL - serialize M4 send and set key IOCTL to
-	 * prevent M4 encryption and
-	 * intercept WLC_DISASSOC IOCTL - serialize WPS-DONE and WLC_DISASSOC IOCTL to
-	 * prevent disassoc frame being sent before WPS-DONE frame.
-	 */
-	if (ioc->cmd == WLC_SET_KEY ||
-	    (ioc->cmd == WLC_SET_VAR && data_buf != NULL &&
-	     strncmp("wsec_key", data_buf, 9) == 0) ||
-	    (ioc->cmd == WLC_SET_VAR && data_buf != NULL &&
-	     strncmp("bsscfg:wsec_key", data_buf, 15) == 0) ||
-	    ioc->cmd == WLC_DISASSOC)
-		dhd_wait_pend8021x(net);
-
-#ifdef WLMEDIA_HTSF
-	if (data_buf) {
-		/*  short cut wl ioctl calls here  */
-		if (strcmp("htsf", data_buf) == 0) {
-			dhd_ioctl_htsf_get(dhd, 0);
-			return BCME_OK;
-		}
-
-		if (strcmp("htsflate", data_buf) == 0) {
-			if (ioc->set) {
-				memset(ts, 0, sizeof(tstamp_t)*TSMAX);
-				memset(&maxdelayts, 0, sizeof(tstamp_t));
-				maxdelay = 0;
-				tspktcnt = 0;
-				maxdelaypktno = 0;
-				memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN);
-				memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN);
-				memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN);
-				memset(&vi_d4.bin, 0, sizeof(uint32)*NUMBIN);
-			} else {
-				dhd_dump_latency();
-			}
-			return BCME_OK;
-		}
-		if (strcmp("htsfclear", data_buf) == 0) {
-			memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN);
-			memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN);
-			memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN);
-			memset(&vi_d4.bin, 0, sizeof(uint32)*NUMBIN);
-			htsf_seqnum = 0;
-			return BCME_OK;
-		}
-		if (strcmp("htsfhis", data_buf) == 0) {
-			dhd_dump_htsfhisto(&vi_d1, "H to D");
-			dhd_dump_htsfhisto(&vi_d2, "D to D");
-			dhd_dump_htsfhisto(&vi_d3, "D to H");
-			dhd_dump_htsfhisto(&vi_d4, "H to H");
-			return BCME_OK;
-		}
-		if (strcmp("tsport", data_buf) == 0) {
-			if (ioc->set) {
-				memcpy(&tsport, data_buf + 7, 4);
-			} else {
-				DHD_ERROR(("current timestamp port: %d \n", tsport));
-			}
-			return BCME_OK;
-		}
-	}
-#endif /* WLMEDIA_HTSF */
-
-	if ((ioc->cmd == WLC_SET_VAR || ioc->cmd == WLC_GET_VAR) &&
-		data_buf != NULL && strncmp("rpc_", data_buf, 4) == 0) {
-#ifdef BCM_FD_AGGR
-		bcmerror = dhd_fdaggr_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, data_buf, buflen);
-#else
-		bcmerror = BCME_UNSUPPORTED;
-#endif
-		goto done;
-	}
-
-#ifdef DHD_DEBUG
-	if (ioc->cmd != WLC_GET_MAGIC && ioc->cmd != WLC_GET_VERSION) {
-		if (ioc->cmd == WLC_SET_VAR || ioc->cmd == WLC_GET_VAR) {
-			/* Print  IOVAR Information */
-			DHD_IOV_INFO(("%s: IOVAR_INFO name = %s set = %d\n",
-				__FUNCTION__, (char *)data_buf, ioc->set));
-			if ((dhd_msg_level & DHD_IOV_INFO_VAL) && ioc->set && data_buf) {
-				prhex(NULL, data_buf + strlen(data_buf) + 1,
-					buflen - strlen(data_buf) - 1);
-			}
-		} else {
-			/* Print  IOCTL Information */
-			DHD_IOV_INFO(("%s: IOCTL_INFO cmd = %d set = %d\n",
-				__FUNCTION__, ioc->cmd, ioc->set));
-			if ((dhd_msg_level & DHD_IOV_INFO_VAL) && ioc->set && data_buf) {
-				prhex(NULL, data_buf, buflen);
-			}
-		}
-	}
-#endif /* DHD_DEBUG */
-
-	bcmerror = dhd_wl_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, data_buf, buflen);
-
-done:
-	dhd_check_hang(net, pub, bcmerror);
-
-	return bcmerror;
-}
-
-static int
-dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(net);
-	dhd_ioctl_t ioc;
-	int ifidx;
-	int ret;
-	void *local_buf = NULL;
-	u16 buflen = 0;
-
-	DHD_OS_WAKE_LOCK(&dhd->pub);
-	DHD_PERIM_LOCK(&dhd->pub);
-
-	/* Interface up check for built-in type */
-	if (!dhd_download_fw_on_driverload && dhd->pub.up == FALSE) {
-		DHD_TRACE(("%s: Interface is down \n", __FUNCTION__));
-		ret = BCME_NOTUP;
-		goto exit;
-	}
-
-	/* send to dongle only if we are not waiting for reload already */
-	if (dhd->pub.hang_was_sent) {
-		DHD_TRACE(("%s: HANG was sent up earlier\n", __FUNCTION__));
-		DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS);
-		ret = BCME_DONGLE_DOWN;
-		goto exit;
-	}
-
-	ifidx = dhd_net2idx(dhd, net);
-	DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd));
-
-	if (ifidx == DHD_BAD_IF) {
-		DHD_ERROR(("%s: BAD IF\n", __FUNCTION__));
-		ret = -1;
-		goto exit;
-	}
-
-#if defined(WL_WIRELESS_EXT)
-	/* linux wireless extensions */
-	if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
-		/* may recurse, do NOT lock */
-		ret = wl_iw_ioctl(net, ifr, cmd);
-		goto exit;
-	}
-#endif /* defined(WL_WIRELESS_EXT) */
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2)
-	if (cmd == SIOCETHTOOL) {
-		ret = dhd_ethtool(dhd, (void*)ifr->ifr_data);
-		goto exit;
-	}
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
-
-	if (cmd == SIOCDEVPRIVATE+1) {
-		ret = wl_android_priv_cmd(net, ifr, cmd);
-		dhd_check_hang(net, &dhd->pub, ret);
-		goto exit;
-	}
-
-	if (cmd != SIOCDEVPRIVATE) {
-		ret = -EOPNOTSUPP;
-		goto exit;
-	}
-
-	memset(&ioc, 0, sizeof(ioc));
-
-#ifdef CONFIG_COMPAT
-	if (is_compat_task()) {
-		compat_wl_ioctl_t compat_ioc;
-		if (copy_from_user(&compat_ioc, ifr->ifr_data, sizeof(compat_wl_ioctl_t))) {
-			ret = BCME_BADADDR;
-			goto done;
-		}
-		ioc.cmd = compat_ioc.cmd;
-		ioc.buf = compat_ptr(compat_ioc.buf);
-		ioc.len = compat_ioc.len;
-		ioc.set = compat_ioc.set;
-		ioc.used = compat_ioc.used;
-		ioc.needed = compat_ioc.needed;
-		/* To differentiate between wl and dhd read 4 more byes */
-		if ((copy_from_user(&ioc.driver, (char *)ifr->ifr_data + sizeof(compat_wl_ioctl_t),
-			sizeof(uint)) != 0)) {
-			ret = BCME_BADADDR;
-			goto done;
-		}
-	} else
-#endif /* CONFIG_COMPAT */
-	{
-		/* Copy the ioc control structure part of ioctl request */
-		if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) {
-			ret = BCME_BADADDR;
-			goto done;
-		}
-
-		/* To differentiate between wl and dhd read 4 more byes */
-		if ((copy_from_user(&ioc.driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t),
-			sizeof(uint)) != 0)) {
-			ret = BCME_BADADDR;
-			goto done;
-		}
-	}
-
-	if (!capable(CAP_NET_ADMIN)) {
-		ret = BCME_EPERM;
-		goto done;
-	}
-
-	if (ioc.len > 0) {
-		buflen = MIN(ioc.len, DHD_IOCTL_MAXLEN);
-		if (!(local_buf = MALLOC(dhd->pub.osh, buflen+1))) {
-			ret = BCME_NOMEM;
-			goto done;
-		}
-
-		DHD_PERIM_UNLOCK(&dhd->pub);
-		if (copy_from_user(local_buf, ioc.buf, buflen)) {
-			DHD_PERIM_LOCK(&dhd->pub);
-			ret = BCME_BADADDR;
-			goto done;
-		}
-		DHD_PERIM_LOCK(&dhd->pub);
-
-		*(char *)(local_buf + buflen) = '\0';
-	}
-
-	ret = dhd_ioctl_process(&dhd->pub, ifidx, &ioc, local_buf);
-
-	if (!ret && buflen && local_buf && ioc.buf) {
-		DHD_PERIM_UNLOCK(&dhd->pub);
-		if (copy_to_user(ioc.buf, local_buf, buflen))
-			ret = -EFAULT;
-		DHD_PERIM_LOCK(&dhd->pub);
-	}
-
-done:
-	if (local_buf)
-		MFREE(dhd->pub.osh, local_buf, buflen+1);
-
-exit:
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	DHD_OS_WAKE_UNLOCK(&dhd->pub);
-
-	return OSL_ERROR(ret);
-}
-
-
-#ifdef FIX_CPU_MIN_CLOCK
-static int dhd_init_cpufreq_fix(dhd_info_t *dhd)
-{
-	if (dhd) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-		mutex_init(&dhd->cpufreq_fix);
-#endif
-		dhd->cpufreq_fix_status = FALSE;
-	}
-	return 0;
-}
-
-static void dhd_fix_cpu_freq(dhd_info_t *dhd)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	mutex_lock(&dhd->cpufreq_fix);
-#endif
-	if (dhd && !dhd->cpufreq_fix_status) {
-		pm_qos_add_request(&dhd->dhd_cpu_qos, PM_QOS_CPU_FREQ_MIN, 300000);
-#ifdef FIX_BUS_MIN_CLOCK
-		pm_qos_add_request(&dhd->dhd_bus_qos, PM_QOS_BUS_THROUGHPUT, 400000);
-#endif /* FIX_BUS_MIN_CLOCK */
-		DHD_ERROR(("pm_qos_add_requests called\n"));
-
-		dhd->cpufreq_fix_status = TRUE;
-	}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	mutex_unlock(&dhd->cpufreq_fix);
-#endif
-}
-
-static void dhd_rollback_cpu_freq(dhd_info_t *dhd)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	mutex_lock(&dhd ->cpufreq_fix);
-#endif
-	if (dhd && dhd->cpufreq_fix_status != TRUE) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-		mutex_unlock(&dhd->cpufreq_fix);
-#endif
-		return;
-	}
-
-	pm_qos_remove_request(&dhd->dhd_cpu_qos);
-#ifdef FIX_BUS_MIN_CLOCK
-	pm_qos_remove_request(&dhd->dhd_bus_qos);
-#endif /* FIX_BUS_MIN_CLOCK */
-	DHD_ERROR(("pm_qos_add_requests called\n"));
-
-	dhd->cpufreq_fix_status = FALSE;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	mutex_unlock(&dhd->cpufreq_fix);
-#endif
-}
-#endif /* FIX_CPU_MIN_CLOCK */
-
-static int
-dhd_stop(struct net_device *net)
-{
-	int ifidx = 0;
-	dhd_info_t *dhd = DHD_DEV_INFO(net);
-	DHD_OS_WAKE_LOCK(&dhd->pub);
-	DHD_PERIM_LOCK(&dhd->pub);
-	DHD_TRACE(("%s: Enter %p\n", __FUNCTION__, net));
-	dhd->pub.rxcnt_timeout = 0;
-	dhd->pub.txcnt_timeout = 0;
-
-#ifdef BCMPCIE
-	dhd->pub.d3ackcnt_timeout = 0;
-#endif /* BCMPCIE */
-
-	if (dhd->pub.up == 0) {
-		goto exit;
-	}
-
-	dhd_if_flush_sta(DHD_DEV_IFP(net));
-
-	/* Disable Runtime PM before interface down */
-	DHD_DISABLE_RUNTIME_PM(&dhd->pub);
-
-#ifdef FIX_CPU_MIN_CLOCK
-	if (dhd_get_fw_mode(dhd) == DHD_FLAG_HOSTAP_MODE)
-		dhd_rollback_cpu_freq(dhd);
-#endif /* FIX_CPU_MIN_CLOCK */
-
-	ifidx = dhd_net2idx(dhd, net);
-	BCM_REFERENCE(ifidx);
-
-	/* Set state and stop OS transmissions */
-	netif_stop_queue(net);
-	dhd->pub.up = 0;
-
-#ifdef WL_CFG80211
-	if (ifidx == 0) {
-		dhd_if_t *ifp;
-		wl_cfg80211_down(NULL);
-
-		ifp = dhd->iflist[0];
-		ASSERT(ifp && ifp->net);
-		/*
-		 * For CFG80211: Clean up all the left over virtual interfaces
-		 * when the primary Interface is brought down. [ifconfig wlan0 down]
-		 */
-		if (!dhd_download_fw_on_driverload) {
-			if ((dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) &&
-				(dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) {
-				int i;
-
-#ifdef WL_CFG80211_P2P_DEV_IF
-				wl_cfg80211_del_p2p_wdev();
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-				dhd_net_if_lock_local(dhd);
-				for (i = 1; i < DHD_MAX_IFS; i++)
-					dhd_remove_if(&dhd->pub, i, FALSE);
-
-				if (ifp && ifp->net) {
-					dhd_if_del_sta_list(ifp);
-				}
-
-#ifdef ARP_OFFLOAD_SUPPORT
-				if (dhd_inetaddr_notifier_registered) {
-					dhd_inetaddr_notifier_registered = FALSE;
-					unregister_inetaddr_notifier(&dhd_inetaddr_notifier);
-				}
-#endif /* ARP_OFFLOAD_SUPPORT */
-#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT)
-				if (dhd_inet6addr_notifier_registered) {
-					dhd_inet6addr_notifier_registered = FALSE;
-					unregister_inet6addr_notifier(&dhd_inet6addr_notifier);
-				}
-#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */
-				dhd_net_if_unlock_local(dhd);
-			}
-			cancel_work_sync(dhd->dhd_deferred_wq);
-#if defined(DHD_LB) && defined(DHD_LB_RXP)
-			__skb_queue_purge(&dhd->rx_pend_queue);
-#endif /* DHD_LB && DHD_LB_RXP */
-		}
-
-#if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS)
-		dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF);
-#endif /* BCMPCIE && DHDTCPACK_SUPPRESS */
-#if defined(DHD_LB) && defined(DHD_LB_RXP)
-		if (ifp->net == dhd->rx_napi_netdev) {
-			DHD_INFO(("%s napi<%p> disabled ifp->net<%p,%s>\n",
-				__FUNCTION__, &dhd->rx_napi_struct, net, net->name));
-			skb_queue_purge(&dhd->rx_napi_queue);
-			napi_disable(&dhd->rx_napi_struct);
-			netif_napi_del(&dhd->rx_napi_struct);
-			dhd->rx_napi_netdev = NULL;
-		}
-#endif /* DHD_LB && DHD_LB_RXP */
-
-	}
-#endif /* WL_CFG80211 */
-
-#ifdef PROP_TXSTATUS
-	dhd_wlfc_cleanup(&dhd->pub, NULL, 0);
-#endif
-	/* Stop the protocol module */
-	dhd_prot_stop(&dhd->pub);
-
-	OLD_MOD_DEC_USE_COUNT;
-exit:
-#if defined(WL_CFG80211)
-	if (ifidx == 0 && !dhd_download_fw_on_driverload)
-			wl_android_wifi_off(net, TRUE);
-#endif 
-	dhd->pub.hang_was_sent = 0;
-
-	/* Clear country spec for for built-in type driver */
-	if (!dhd_download_fw_on_driverload) {
-		dhd->pub.dhd_cspec.country_abbrev[0] = 0x00;
-		dhd->pub.dhd_cspec.rev = 0;
-		dhd->pub.dhd_cspec.ccode[0] = 0x00;
-	}
-
-#ifdef BCMDBGFS
-	dhd_dbg_remove();
-#endif
-
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	DHD_OS_WAKE_UNLOCK(&dhd->pub);
-
-	/* Destroy wakelock */
-	if (!dhd_download_fw_on_driverload &&
-		(dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) {
-		DHD_OS_WAKE_LOCK_DESTROY(dhd);
-		dhd->dhd_state &= ~DHD_ATTACH_STATE_WAKELOCKS_INIT;
-	}
-
-	return 0;
-}
-
-#if defined(WL_CFG80211) && defined(USE_INITIAL_SHORT_DWELL_TIME)
-extern bool g_first_broadcast_scan;
-#endif 
-
-#ifdef WL11U
-static int dhd_interworking_enable(dhd_pub_t *dhd)
-{
-	char iovbuf[WLC_IOCTL_SMLEN];
-	uint32 enable = true;
-	int ret = BCME_OK;
-
-	bcm_mkiovar("interworking", (char *)&enable, sizeof(enable), iovbuf, sizeof(iovbuf));
-	ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-	if (ret < 0) {
-		DHD_ERROR(("%s: enableing interworking failed, ret=%d\n", __FUNCTION__, ret));
-	}
-
-	if (ret == BCME_OK) {
-		/* basic capabilities for HS20 REL2 */
-		uint32 cap = WL_WNM_BSSTRANS | WL_WNM_NOTIF;
-		bcm_mkiovar("wnm", (char *)&cap, sizeof(cap), iovbuf, sizeof(iovbuf));
-		ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-		if (ret < 0) {
-			DHD_ERROR(("%s: set wnm returned (%d)\n", __FUNCTION__, ret));
-		}
-	}
-
-	return ret;
-}
-#endif /* WL11u */
-
-static int
-dhd_open(struct net_device *net)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(net);
-#ifdef TOE
-	uint32 toe_ol;
-#endif
-#ifdef BCM_FD_AGGR
-	char iovbuf[WLC_IOCTL_SMLEN];
-	dbus_config_t config;
-	uint32 agglimit = 0;
-	uint32 rpc_agg = BCM_RPC_TP_DNGL_AGG_DPC; /* host aggr not enabled yet */
-#endif /* BCM_FD_AGGR */
-	int ifidx;
-	int32 ret = 0;
-
-	if (!dhd_download_fw_on_driverload && !dhd_driver_init_done) {
-		DHD_ERROR(("%s: WLAN driver is not initialized\n", __FUNCTION__));
-		return -1;
-	}
-
-	/* Init wakelock */
-	if (!dhd_download_fw_on_driverload &&
-		!(dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) {
-		DHD_OS_WAKE_LOCK_INIT(dhd);
-		dhd->dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT;
-	}
-
-#ifdef PREVENT_REOPEN_DURING_HANG
-	/* WAR : to prevent calling dhd_open abnormally in quick succession after hang event */
-	if (dhd->pub.hang_was_sent == 1) {
-		DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__));
-		/* Force to bring down WLAN interface in case dhd_stop() is not called
-		 * from the upper layer when HANG event is triggered.
-		 */
-		if (!dhd_download_fw_on_driverload && dhd->pub.up == 1) {
-			DHD_ERROR(("%s: WLAN interface is not brought down\n", __FUNCTION__));
-			dhd_stop(net);
-		} else {
-			return -1;
-		}
-	}
-#endif /* PREVENT_REOPEN_DURING_HANG */
-
-
-	DHD_OS_WAKE_LOCK(&dhd->pub);
-	DHD_PERIM_LOCK(&dhd->pub);
-	dhd->pub.dongle_trap_occured = 0;
-	dhd->pub.hang_was_sent = 0;
-	dhd->pub.hang_reason = 0;
-#ifdef DHD_LOSSLESS_ROAMING
-	dhd->pub.dequeue_prec_map = ALLPRIO;
-#endif
-#if !defined(WL_CFG80211)
-	/*
-	 * Force start if ifconfig_up gets called before START command
-	 *  We keep WEXT's wl_control_wl_start to provide backward compatibility
-	 *  This should be removed in the future
-	 */
-	ret = wl_control_wl_start(net);
-	if (ret != 0) {
-		DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
-		ret = -1;
-		goto exit;
-	}
-
-#endif 
-
-	ifidx = dhd_net2idx(dhd, net);
-	DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
-
-	if (ifidx < 0) {
-		DHD_ERROR(("%s: Error: called with invalid IF\n", __FUNCTION__));
-		ret = -1;
-		goto exit;
-	}
-
-	if (!dhd->iflist[ifidx]) {
-		DHD_ERROR(("%s: Error: called when IF already deleted\n", __FUNCTION__));
-		ret = -1;
-		goto exit;
-	}
-
-	if (ifidx == 0) {
-		atomic_set(&dhd->pend_8021x_cnt, 0);
-#if defined(WL_CFG80211)
-		if (!dhd_download_fw_on_driverload) {
-			DHD_ERROR(("\n%s\n", dhd_version));
-#if defined(USE_INITIAL_SHORT_DWELL_TIME)
-			g_first_broadcast_scan = TRUE;
-#endif 
-			ret = wl_android_wifi_on(net);
-			if (ret != 0) {
-				DHD_ERROR(("%s : wl_android_wifi_on failed (%d)\n",
-					__FUNCTION__, ret));
-				ret = -1;
-				goto exit;
-			}
-		}
-#ifdef FIX_CPU_MIN_CLOCK
-		if (dhd_get_fw_mode(dhd) == DHD_FLAG_HOSTAP_MODE) {
-			dhd_init_cpufreq_fix(dhd);
-			dhd_fix_cpu_freq(dhd);
-		}
-#endif /* FIX_CPU_MIN_CLOCK */
-#endif 
-
-		if (dhd->pub.busstate != DHD_BUS_DATA) {
-
-			/* try to bring up bus */
-			DHD_PERIM_UNLOCK(&dhd->pub);
-			ret = dhd_bus_start(&dhd->pub);
-			DHD_PERIM_LOCK(&dhd->pub);
-			if (ret) {
-				DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
-				ret = -1;
-				goto exit;
-			}
-
-		}
-
-#ifdef BCM_FD_AGGR
-		config.config_id = DBUS_CONFIG_ID_AGGR_LIMIT;
-
-
-		memset(iovbuf, 0, sizeof(iovbuf));
-		bcm_mkiovar("rpc_dngl_agglimit", (char *)&agglimit, 4,
-			iovbuf, sizeof(iovbuf));
-
-		if (!dhd_wl_ioctl_cmd(&dhd->pub, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) {
-			agglimit = *(uint32 *)iovbuf;
-			config.aggr_param.maxrxsf = agglimit >> BCM_RPC_TP_AGG_SF_SHIFT;
-			config.aggr_param.maxrxsize = agglimit & BCM_RPC_TP_AGG_BYTES_MASK;
-			DHD_ERROR(("rpc_dngl_agglimit %x : sf_limit %d bytes_limit %d\n",
-				agglimit, config.aggr_param.maxrxsf, config.aggr_param.maxrxsize));
-			if (bcm_rpc_tp_set_config(dhd->pub.info->rpc_th, &config)) {
-				DHD_ERROR(("set tx/rx queue size and buffersize failed\n"));
-			}
-		} else {
-			DHD_ERROR(("get rpc_dngl_agglimit failed\n"));
-			rpc_agg &= ~BCM_RPC_TP_DNGL_AGG_DPC;
-		}
-
-		/* Set aggregation for TX */
-		bcm_rpc_tp_agg_set(dhd->pub.info->rpc_th, BCM_RPC_TP_HOST_AGG_MASK,
-			rpc_agg & BCM_RPC_TP_HOST_AGG_MASK);
-
-		/* Set aggregation for RX */
-		memset(iovbuf, 0, sizeof(iovbuf));
-		bcm_mkiovar("rpc_agg", (char *)&rpc_agg, sizeof(rpc_agg), iovbuf, sizeof(iovbuf));
-		if (!dhd_wl_ioctl_cmd(&dhd->pub, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) {
-			dhd->pub.info->fdaggr = 0;
-			if (rpc_agg & BCM_RPC_TP_HOST_AGG_MASK)
-				dhd->pub.info->fdaggr |= BCM_FDAGGR_H2D_ENABLED;
-			if (rpc_agg & BCM_RPC_TP_DNGL_AGG_MASK)
-				dhd->pub.info->fdaggr |= BCM_FDAGGR_D2H_ENABLED;
-		} else {
-			DHD_ERROR(("%s(): Setting RX aggregation failed %d\n", __FUNCTION__, ret));
-		}
-#endif /* BCM_FD_AGGR */
-
-		/* dhd_sync_with_dongle has been called in dhd_bus_start or wl_android_wifi_on */
-		memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN);
-
-#ifdef TOE
-		/* Get current TOE mode from dongle */
-		if (dhd_toe_get(dhd, ifidx, &toe_ol) >= 0 && (toe_ol & TOE_TX_CSUM_OL) != 0) {
-			dhd->iflist[ifidx]->net->features |= NETIF_F_IP_CSUM;
-		} else {
-			dhd->iflist[ifidx]->net->features &= ~NETIF_F_IP_CSUM;
-		}
-#endif /* TOE */
-
-#if defined(WL_CFG80211)
-		if (unlikely(wl_cfg80211_up(NULL))) {
-			DHD_ERROR(("%s: failed to bring up cfg80211\n", __FUNCTION__));
-			ret = -1;
-			goto exit;
-		}
-		if (!dhd_download_fw_on_driverload) {
-#ifdef ARP_OFFLOAD_SUPPORT
-			dhd->pend_ipaddr = 0;
-			if (!dhd_inetaddr_notifier_registered) {
-				dhd_inetaddr_notifier_registered = TRUE;
-				register_inetaddr_notifier(&dhd_inetaddr_notifier);
-			}
-#endif /* ARP_OFFLOAD_SUPPORT */
-#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT)
-			if (!dhd_inet6addr_notifier_registered) {
-				dhd_inet6addr_notifier_registered = TRUE;
-				register_inet6addr_notifier(&dhd_inet6addr_notifier);
-			}
-#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */
-#ifdef DHD_LB
-			DHD_LB_STATS_INIT(&dhd->pub);
-#ifdef DHD_LB_RXP
-			__skb_queue_head_init(&dhd->rx_pend_queue);
-#endif /* DHD_LB_RXP */
-#endif /* DHD_LB */
-		}
-
-#if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS)
-#if defined(SET_RPS_CPUS)
-		dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF);
-#else
-		dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_HOLD);
-#endif 
-#endif /* BCMPCIE && DHDTCPACK_SUPPRESS */
-#if defined(DHD_LB) && defined(DHD_LB_RXP)
-		if (dhd->rx_napi_netdev == NULL) {
-			dhd->rx_napi_netdev = dhd->iflist[ifidx]->net;
-			memset(&dhd->rx_napi_struct, 0, sizeof(struct napi_struct));
-			netif_napi_add(dhd->rx_napi_netdev, &dhd->rx_napi_struct,
-					dhd_napi_poll, dhd_napi_weight);
-			DHD_INFO(("%s napi<%p> enabled ifp->net<%p,%s>\n",
-					__FUNCTION__, &dhd->rx_napi_struct, net, net->name));
-			napi_enable(&dhd->rx_napi_struct);
-			DHD_INFO(("%s load balance init rx_napi_struct\n", __FUNCTION__));
-			skb_queue_head_init(&dhd->rx_napi_queue);
-		}
-#endif /* DHD_LB && DHD_LB_RXP */
-#if defined(NUM_SCB_MAX_PROBE)
-		dhd_set_scb_probe(&dhd->pub);
-#endif /* NUM_SCB_MAX_PROBE */
-#endif /* WL_CFG80211 */
-	}
-
-	/* Allow transmit calls */
-	netif_start_queue(net);
-	dhd->pub.up = 1;
-
-	OLD_MOD_INC_USE_COUNT;
-
-#ifdef BCMDBGFS
-	dhd_dbg_init(&dhd->pub);
-#endif
-
-exit:
-	if (ret) {
-		dhd_stop(net);
-	}
-
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	DHD_OS_WAKE_UNLOCK(&dhd->pub);
-
-
-	return ret;
-}
-
-int dhd_do_driver_init(struct net_device *net)
-{
-	dhd_info_t *dhd = NULL;
-
-	if (!net) {
-		DHD_ERROR(("Primary Interface not initialized \n"));
-		return -EINVAL;
-	}
-
-
-	/*  && defined(OEM_ANDROID) && defined(BCMSDIO) */
-	dhd = DHD_DEV_INFO(net);
-
-	/* If driver is already initialized, do nothing
-	 */
-	if (dhd->pub.busstate == DHD_BUS_DATA) {
-		DHD_TRACE(("Driver already Inititalized. Nothing to do"));
-		return 0;
-	}
-
-	if (dhd_open(net) < 0) {
-		DHD_ERROR(("Driver Init Failed \n"));
-		return -1;
-	}
-
-	return 0;
-}
-
-int
-dhd_event_ifadd(dhd_info_t *dhdinfo, wl_event_data_if_t *ifevent, char *name, uint8 *mac)
-{
-
-#ifdef WL_CFG80211
-	if (wl_cfg80211_notify_ifadd(ifevent->ifidx, name, mac, ifevent->bssidx) == BCME_OK)
-		return BCME_OK;
-#endif
-
-	/* handle IF event caused by wl commands, SoftAP, WEXT and
-	 * anything else. This has to be done asynchronously otherwise
-	 * DPC will be blocked (and iovars will timeout as DPC has no chance
-	 * to read the response back)
-	 */
-	if (ifevent->ifidx > 0) {
-		dhd_if_event_t *if_event = MALLOC(dhdinfo->pub.osh, sizeof(dhd_if_event_t));
-		if (if_event == NULL) {
-			DHD_ERROR(("dhd_event_ifadd: Failed MALLOC, malloced %d bytes",
-				MALLOCED(dhdinfo->pub.osh)));
-			return BCME_NOMEM;
-		}
-
-		memcpy(&if_event->event, ifevent, sizeof(if_event->event));
-		memcpy(if_event->mac, mac, ETHER_ADDR_LEN);
-		strncpy(if_event->name, name, IFNAMSIZ);
-		if_event->name[IFNAMSIZ - 1] = '\0';
-		dhd_deferred_schedule_work(dhdinfo->dhd_deferred_wq, (void *)if_event,
-			DHD_WQ_WORK_IF_ADD, dhd_ifadd_event_handler, DHD_WORK_PRIORITY_LOW);
-	}
-
-	return BCME_OK;
-}
-
-int
-dhd_event_ifdel(dhd_info_t *dhdinfo, wl_event_data_if_t *ifevent, char *name, uint8 *mac)
-{
-	dhd_if_event_t *if_event;
-
-#ifdef WL_CFG80211
-	if (wl_cfg80211_notify_ifdel(ifevent->ifidx, name, mac, ifevent->bssidx) == BCME_OK)
-		return BCME_OK;
-#endif /* WL_CFG80211 */
-
-	/* handle IF event caused by wl commands, SoftAP, WEXT and
-	 * anything else
-	 */
-	if_event = MALLOC(dhdinfo->pub.osh, sizeof(dhd_if_event_t));
-	if (if_event == NULL) {
-		DHD_ERROR(("dhd_event_ifdel: malloc failed for if_event, malloced %d bytes",
-			MALLOCED(dhdinfo->pub.osh)));
-		return BCME_NOMEM;
-	}
-	memcpy(&if_event->event, ifevent, sizeof(if_event->event));
-	memcpy(if_event->mac, mac, ETHER_ADDR_LEN);
-	strncpy(if_event->name, name, IFNAMSIZ);
-	if_event->name[IFNAMSIZ - 1] = '\0';
-	dhd_deferred_schedule_work(dhdinfo->dhd_deferred_wq, (void *)if_event, DHD_WQ_WORK_IF_DEL,
-		dhd_ifdel_event_handler, DHD_WORK_PRIORITY_LOW);
-
-	return BCME_OK;
-}
-
-/* unregister and free the existing net_device interface (if any) in iflist and
- * allocate a new one. the slot is reused. this function does NOT register the
- * new interface to linux kernel. dhd_register_if does the job
- */
-struct net_device*
-dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, char *name,
-	uint8 *mac, uint8 bssidx, bool need_rtnl_lock, char *dngl_name)
-{
-	dhd_info_t *dhdinfo = (dhd_info_t *)dhdpub->info;
-	dhd_if_t *ifp;
-
-	ASSERT(dhdinfo && (ifidx < DHD_MAX_IFS));
-	ifp = dhdinfo->iflist[ifidx];
-
-	if (ifp != NULL) {
-		if (ifp->net != NULL) {
-			DHD_ERROR(("%s: free existing IF %s\n", __FUNCTION__, ifp->net->name));
-
-			dhd_dev_priv_clear(ifp->net); /* clear net_device private */
-
-			/* in unregister_netdev case, the interface gets freed by net->destructor
-			 * (which is set to free_netdev)
-			 */
-			if (ifp->net->reg_state == NETREG_UNINITIALIZED) {
-				free_netdev(ifp->net);
-			} else {
-				netif_stop_queue(ifp->net);
-				if (need_rtnl_lock)
-					unregister_netdev(ifp->net);
-				else
-					unregister_netdevice(ifp->net);
-			}
-			ifp->net = NULL;
-		}
-	} else {
-		ifp = MALLOC(dhdinfo->pub.osh, sizeof(dhd_if_t));
-		if (ifp == NULL) {
-			DHD_ERROR(("%s: OOM - dhd_if_t(%zu)\n", __FUNCTION__, sizeof(dhd_if_t)));
-			return NULL;
-		}
-	}
-
-	memset(ifp, 0, sizeof(dhd_if_t));
-	ifp->info = dhdinfo;
-	ifp->idx = ifidx;
-	ifp->bssidx = bssidx;
-	if (mac != NULL)
-		memcpy(&ifp->mac_addr, mac, ETHER_ADDR_LEN);
-
-	/* Allocate etherdev, including space for private structure */
-	ifp->net = alloc_etherdev(DHD_DEV_PRIV_SIZE);
-	if (ifp->net == NULL) {
-		DHD_ERROR(("%s: OOM - alloc_etherdev(%zu)\n", __FUNCTION__, sizeof(dhdinfo)));
-		goto fail;
-	}
-
-	/* Setup the dhd interface's netdevice private structure. */
-	dhd_dev_priv_save(ifp->net, dhdinfo, ifp, ifidx);
-
-	if (name && name[0]) {
-		strncpy(ifp->net->name, name, IFNAMSIZ);
-		ifp->net->name[IFNAMSIZ - 1] = '\0';
-	}
-
-#ifdef WL_CFG80211
-	if (ifidx == 0)
-		ifp->net->destructor = free_netdev;
-	else
-		ifp->net->destructor = dhd_netdev_free;
-#else
-	ifp->net->destructor = free_netdev;
-#endif /* WL_CFG80211 */
-	strncpy(ifp->name, ifp->net->name, IFNAMSIZ);
-	ifp->name[IFNAMSIZ - 1] = '\0';
-	dhdinfo->iflist[ifidx] = ifp;
-
-/* initialize the dongle provided if name */
-	if (dngl_name)
-		strncpy(ifp->dngl_name, dngl_name, IFNAMSIZ);
-	else
-		strncpy(ifp->dngl_name, name, IFNAMSIZ);
-
-#ifdef PCIE_FULL_DONGLE
-	/* Initialize STA info list */
-	INIT_LIST_HEAD(&ifp->sta_list);
-	DHD_IF_STA_LIST_LOCK_INIT(ifp);
-#endif /* PCIE_FULL_DONGLE */
-
-#ifdef DHD_L2_FILTER
-	ifp->phnd_arp_table = init_l2_filter_arp_table(dhdpub->osh);
-	ifp->parp_allnode = TRUE;
-#endif
-	return ifp->net;
-
-fail:
-
-	if (ifp != NULL) {
-		if (ifp->net != NULL) {
-			dhd_dev_priv_clear(ifp->net);
-			free_netdev(ifp->net);
-			ifp->net = NULL;
-		}
-		MFREE(dhdinfo->pub.osh, ifp, sizeof(*ifp));
-		ifp = NULL;
-	}
-
-	dhdinfo->iflist[ifidx] = NULL;
-	return NULL;
-}
-
-/* unregister and free the the net_device interface associated with the indexed
- * slot, also free the slot memory and set the slot pointer to NULL
- */
-int
-dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock)
-{
-	dhd_info_t *dhdinfo = (dhd_info_t *)dhdpub->info;
-	dhd_if_t *ifp;
-
-	ifp = dhdinfo->iflist[ifidx];
-
-	if (ifp != NULL) {
-		if (ifp->net != NULL) {
-			DHD_ERROR(("deleting interface '%s' idx %d\n", ifp->net->name, ifp->idx));
-
-			/* in unregister_netdev case, the interface gets freed by net->destructor
-			 * (which is set to free_netdev)
-			 */
-			if (ifp->net->reg_state == NETREG_UNINITIALIZED) {
-				free_netdev(ifp->net);
-			} else {
-				netif_tx_disable(ifp->net);
-
-
-
-#if defined(SET_RPS_CPUS)
-				custom_rps_map_clear(ifp->net->_rx);
-#endif /* SET_RPS_CPUS */
-#if defined(SET_RPS_CPUS)
-#if (defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE))
-				dhd_tcpack_suppress_set(dhdpub, TCPACK_SUP_OFF);
-#endif /* DHDTCPACK_SUPPRESS && BCMPCIE */
-#endif 
-				if (need_rtnl_lock)
-					unregister_netdev(ifp->net);
-				else
-					unregister_netdevice(ifp->net);
-			}
-			ifp->net = NULL;
-			dhdinfo->iflist[ifidx] = NULL;
-		}
-#ifdef DHD_WMF
-		dhd_wmf_cleanup(dhdpub, ifidx);
-#endif /* DHD_WMF */
-#ifdef DHD_L2_FILTER
-		bcm_l2_filter_arp_table_update(dhdpub->osh, ifp->phnd_arp_table, TRUE,
-			NULL, FALSE, dhdpub->tickcnt);
-		deinit_l2_filter_arp_table(dhdpub->osh, ifp->phnd_arp_table);
-		ifp->phnd_arp_table = NULL;
-#endif /* DHD_L2_FILTER */
-
-		dhd_if_del_sta_list(ifp);
-
-		MFREE(dhdinfo->pub.osh, ifp, sizeof(*ifp));
-
-	}
-
-	return BCME_OK;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
-static struct net_device_ops dhd_ops_pri = {
-	.ndo_open = dhd_open,
-	.ndo_stop = dhd_stop,
-	.ndo_get_stats = dhd_get_stats,
-	.ndo_do_ioctl = dhd_ioctl_entry,
-	.ndo_start_xmit = dhd_start_xmit,
-	.ndo_set_mac_address = dhd_set_mac_address,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
-	.ndo_set_rx_mode = dhd_set_multicast_list,
-#else
-	.ndo_set_multicast_list = dhd_set_multicast_list,
-#endif
-};
-
-static struct net_device_ops dhd_ops_virt = {
-	.ndo_get_stats = dhd_get_stats,
-	.ndo_do_ioctl = dhd_ioctl_entry,
-	.ndo_start_xmit = dhd_start_xmit,
-	.ndo_set_mac_address = dhd_set_mac_address,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
-	.ndo_set_rx_mode = dhd_set_multicast_list,
-#else
-	.ndo_set_multicast_list = dhd_set_multicast_list,
-#endif
-};
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */
-
-#ifdef DEBUGGER
-extern void debugger_init(void *bus_handle);
-#endif
-
-
-#ifdef SHOW_LOGTRACE
-static char *logstrs_path = "/root/logstrs.bin";
-static char *st_str_file_path = "/root/rtecdc.bin";
-static char *map_file_path = "/root/rtecdc.map";
-static char *rom_st_str_file_path = "/root/roml.bin";
-static char *rom_map_file_path = "/root/roml.map";
-
-#define BYTES_AHEAD_NUM		11	/* address in map file is before these many bytes */
-#define READ_NUM_BYTES		1000 /* read map file each time this No. of bytes */
-#define GO_BACK_FILE_POS_NUM_BYTES	100 /* set file pos back to cur pos */
-static char *ramstart_str = "text_start"; /* string in mapfile has addr ramstart */
-static char *rodata_start_str = "rodata_start"; /* string in mapfile has addr rodata start */
-static char *rodata_end_str = "rodata_end"; /* string in mapfile has addr rodata end */
-static char *ram_file_str = "rtecdc";
-static char *rom_file_str = "roml";
-#define RAMSTART_BIT	0x01
-#define RDSTART_BIT		0x02
-#define RDEND_BIT		0x04
-#define ALL_MAP_VAL		(RAMSTART_BIT | RDSTART_BIT | RDEND_BIT)
-
-module_param(logstrs_path, charp, S_IRUGO);
-module_param(st_str_file_path, charp, S_IRUGO);
-module_param(map_file_path, charp, S_IRUGO);
-module_param(rom_st_str_file_path, charp, S_IRUGO);
-module_param(rom_map_file_path, charp, S_IRUGO);
-
-static void
-dhd_init_logstrs_array(dhd_event_log_t *temp)
-{
-	struct file *filep = NULL;
-	struct kstat stat;
-	mm_segment_t fs;
-	char *raw_fmts =  NULL;
-	int logstrs_size = 0;
-
-	logstr_header_t *hdr = NULL;
-	uint32 *lognums = NULL;
-	char *logstrs = NULL;
-	int ram_index = 0;
-	char **fmts;
-	int num_fmts = 0;
-	uint32 i = 0;
-	int error = 0;
-
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	filep = filp_open(logstrs_path, O_RDONLY, 0);
-
-	if (IS_ERR(filep)) {
-		DHD_ERROR(("%s: Failed to open the file %s \n", __FUNCTION__, logstrs_path));
-		goto fail;
-	}
-	error = vfs_stat(logstrs_path, &stat);
-	if (error) {
-		DHD_ERROR(("%s: Failed to stat file %s \n", __FUNCTION__, logstrs_path));
-		goto fail;
-	}
-	logstrs_size = (int) stat.size;
-
-	raw_fmts = kmalloc(logstrs_size, GFP_KERNEL);
-	if (raw_fmts == NULL) {
-		DHD_ERROR(("%s: Failed to allocate memory \n", __FUNCTION__));
-		goto fail;
-	}
-	if (vfs_read(filep, raw_fmts, logstrs_size, &filep->f_pos) !=	logstrs_size) {
-		DHD_ERROR(("%s: Failed to read file %s", __FUNCTION__, logstrs_path));
-		goto fail;
-	}
-
-	/* Remember header from the logstrs.bin file */
-	hdr = (logstr_header_t *) (raw_fmts + logstrs_size -
-		sizeof(logstr_header_t));
-
-	if (hdr->log_magic == LOGSTRS_MAGIC) {
-		/*
-		* logstrs.bin start with header.
-		*/
-		num_fmts =	hdr->rom_logstrs_offset / sizeof(uint32);
-		ram_index = (hdr->ram_lognums_offset -
-			hdr->rom_lognums_offset) / sizeof(uint32);
-		lognums = (uint32 *) &raw_fmts[hdr->rom_lognums_offset];
-		logstrs = (char *)	 &raw_fmts[hdr->rom_logstrs_offset];
-	} else {
-		/*
-		 * Legacy logstrs.bin format without header.
-		 */
-		num_fmts = *((uint32 *) (raw_fmts)) / sizeof(uint32);
-		if (num_fmts == 0) {
-			/* Legacy ROM/RAM logstrs.bin format:
-			  *  - ROM 'lognums' section
-			  *   - RAM 'lognums' section
-			  *   - ROM 'logstrs' section.
-			  *   - RAM 'logstrs' section.
-			  *
-			  * 'lognums' is an array of indexes for the strings in the
-			  * 'logstrs' section. The first uint32 is 0 (index of first
-			  * string in ROM 'logstrs' section).
-			  *
-			  * The 4324b5 is the only ROM that uses this legacy format. Use the
-			  * fixed number of ROM fmtnums to find the start of the RAM
-			  * 'lognums' section. Use the fixed first ROM string ("Con\n") to
-			  * find the ROM 'logstrs' section.
-			  */
-			#define NUM_4324B5_ROM_FMTS	186
-			#define FIRST_4324B5_ROM_LOGSTR "Con\n"
-			ram_index = NUM_4324B5_ROM_FMTS;
-			lognums = (uint32 *) raw_fmts;
-			num_fmts =	ram_index;
-			logstrs = (char *) &raw_fmts[num_fmts << 2];
-			while (strncmp(FIRST_4324B5_ROM_LOGSTR, logstrs, 4)) {
-				num_fmts++;
-				logstrs = (char *) &raw_fmts[num_fmts << 2];
-			}
-		} else {
-				/* Legacy RAM-only logstrs.bin format:
-				 *	  - RAM 'lognums' section
-				 *	  - RAM 'logstrs' section.
-				 *
-				 * 'lognums' is an array of indexes for the strings in the
-				 * 'logstrs' section. The first uint32 is an index to the
-				 * start of 'logstrs'. Therefore, if this index is divided
-				 * by 'sizeof(uint32)' it provides the number of logstr
-				 *	entries.
-				 */
-				ram_index = 0;
-				lognums = (uint32 *) raw_fmts;
-				logstrs = (char *)	&raw_fmts[num_fmts << 2];
-			}
-	}
-	fmts = kmalloc(num_fmts  * sizeof(char *), GFP_KERNEL);
-	if (fmts == NULL) {
-		DHD_ERROR(("Failed to allocate fmts memory"));
-		goto fail;
-	}
-
-	for (i = 0; i < num_fmts; i++) {
-		/* ROM lognums index into logstrs using 'rom_logstrs_offset' as a base
-		* (they are 0-indexed relative to 'rom_logstrs_offset').
-		*
-		* RAM lognums are already indexed to point to the correct RAM logstrs (they
-		* are 0-indexed relative to the start of the logstrs.bin file).
-		*/
-		if (i == ram_index) {
-			logstrs = raw_fmts;
-		}
-		fmts[i] = &logstrs[lognums[i]];
-	}
-	temp->fmts = fmts;
-	temp->raw_fmts = raw_fmts;
-	temp->num_fmts = num_fmts;
-	filp_close(filep, NULL);
-	set_fs(fs);
-	return;
-fail:
-	if (raw_fmts) {
-		kfree(raw_fmts);
-		raw_fmts = NULL;
-	}
-	if (!IS_ERR(filep))
-		filp_close(filep, NULL);
-	set_fs(fs);
-	temp->fmts = NULL;
-	return;
-}
-
-static int
-dhd_read_map(char *fname, uint32 *ramstart, uint32 *rodata_start,
-	uint32 *rodata_end)
-{
-	struct file *filep = NULL;
-	mm_segment_t fs;
-	char *raw_fmts =  NULL;
-	uint32 read_size = READ_NUM_BYTES;
-	int error = 0;
-	char * cptr = NULL;
-	char c;
-	uint8 count = 0;
-
-	*ramstart = 0;
-	*rodata_start = 0;
-	*rodata_end = 0;
-
-	if (fname == NULL) {
-		DHD_ERROR(("%s: ERROR fname is NULL \n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	filep = filp_open(fname, O_RDONLY, 0);
-	if (IS_ERR(filep)) {
-		DHD_ERROR(("%s: Failed to open %s \n",  __FUNCTION__, fname));
-		goto fail;
-	}
-
-	/* Allocate 1 byte more than read_size to terminate it with NULL */
-	raw_fmts = kmalloc(read_size + 1, GFP_KERNEL);
-	if (raw_fmts == NULL) {
-		DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__));
-		goto fail;
-	}
-
-	/* read ram start, rodata_start and rodata_end values from map  file */
-
-	while (count != ALL_MAP_VAL)
-	{
-		error = vfs_read(filep, raw_fmts, read_size, (&filep->f_pos));
-		if (error < 0) {
-			DHD_ERROR(("%s: read failed %s err:%d \n", __FUNCTION__,
-				map_file_path, error));
-			goto fail;
-		}
-
-		if (error < read_size) {
-			/*
-			* since we reset file pos back to earlier pos by
-			* GO_BACK_FILE_POS_NUM_BYTES bytes we won't reach EOF.
-			* So if ret value is less than read_size, reached EOF don't read further
-			*/
-			break;
-		}
-		/* End raw_fmts with NULL as strstr expects NULL terminated strings */
-		raw_fmts[read_size] = '\0';
-
-		/* Get ramstart address */
-		if ((cptr = strstr(raw_fmts, ramstart_str))) {
-			cptr = cptr - BYTES_AHEAD_NUM;
-			sscanf(cptr, "%x %c text_start", ramstart, &c);
-			count |= RAMSTART_BIT;
-		}
-
-		/* Get ram rodata start address */
-		if ((cptr = strstr(raw_fmts, rodata_start_str))) {
-			cptr = cptr - BYTES_AHEAD_NUM;
-			sscanf(cptr, "%x %c rodata_start", rodata_start, &c);
-			count |= RDSTART_BIT;
-		}
-
-		/* Get ram rodata end address */
-		if ((cptr = strstr(raw_fmts, rodata_end_str))) {
-			cptr = cptr - BYTES_AHEAD_NUM;
-			sscanf(cptr, "%x %c rodata_end", rodata_end, &c);
-			count |= RDEND_BIT;
-		}
-		memset(raw_fmts, 0, read_size);
-		/*
-		* go back to predefined NUM of bytes so that we won't miss
-		* the string and  addr even if it comes as splited in next read.
-		*/
-		filep->f_pos = filep->f_pos - GO_BACK_FILE_POS_NUM_BYTES;
-	}
-
-	DHD_ERROR(("---ramstart: 0x%x, rodata_start: 0x%x, rodata_end:0x%x\n",
-		*ramstart, *rodata_start, *rodata_end));
-
-	DHD_ERROR(("readmap over \n"));
-
-fail:
-	if (raw_fmts) {
-		kfree(raw_fmts);
-		raw_fmts = NULL;
-	}
-	if (!IS_ERR(filep))
-		filp_close(filep, NULL);
-
-	set_fs(fs);
-	if (count == ALL_MAP_VAL) {
-		return BCME_OK;
-	}
-	DHD_ERROR(("readmap error 0X%x \n", count));
-	return BCME_ERROR;
-}
-
-static void
-dhd_init_static_strs_array(dhd_event_log_t *temp, char *str_file, char *map_file)
-{
-	struct file *filep = NULL;
-	mm_segment_t fs;
-	char *raw_fmts =  NULL;
-	uint32 logstrs_size = 0;
-
-	int error = 0;
-	uint32 ramstart = 0;
-	uint32 rodata_start = 0;
-	uint32 rodata_end = 0;
-	uint32 logfilebase = 0;
-
-	error = dhd_read_map(map_file, &ramstart, &rodata_start, &rodata_end);
-	if (error == BCME_ERROR) {
-		DHD_ERROR(("readmap Error!! \n"));
-		/* don't do event log parsing in actual case */
-		temp->raw_sstr = NULL;
-		return;
-	}
-	DHD_ERROR(("ramstart: 0x%x, rodata_start: 0x%x, rodata_end:0x%x\n",
-		ramstart, rodata_start, rodata_end));
-
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	filep = filp_open(str_file, O_RDONLY, 0);
-	if (IS_ERR(filep)) {
-		DHD_ERROR(("%s: Failed to open the file %s \n",  __FUNCTION__, str_file));
-		goto fail;
-	}
-
-	/* Full file size is huge. Just read required part */
-	logstrs_size = rodata_end - rodata_start;
-
-	raw_fmts = kmalloc(logstrs_size, GFP_KERNEL);
-	if (raw_fmts == NULL) {
-		DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__));
-		goto fail;
-	}
-
-	logfilebase = rodata_start - ramstart;
-
-	error = generic_file_llseek(filep, logfilebase, SEEK_SET);
-	if (error < 0) {
-		DHD_ERROR(("%s: %s llseek failed %d \n", __FUNCTION__, str_file, error));
-		goto fail;
-	}
-
-	error = vfs_read(filep, raw_fmts, logstrs_size, (&filep->f_pos));
-	if (error != logstrs_size) {
-		DHD_ERROR(("%s: %s read failed %d \n", __FUNCTION__, str_file, error));
-		goto fail;
-	}
-
-	if (strstr(str_file, ram_file_str) != NULL) {
-		temp->raw_sstr = raw_fmts;
-		temp->ramstart = ramstart;
-		temp->rodata_start = rodata_start;
-		temp->rodata_end = rodata_end;
-	} else if (strstr(str_file, rom_file_str) != NULL) {
-		temp->rom_raw_sstr = raw_fmts;
-		temp->rom_ramstart = ramstart;
-		temp->rom_rodata_start = rodata_start;
-		temp->rom_rodata_end = rodata_end;
-	}
-
-	filp_close(filep, NULL);
-	set_fs(fs);
-
-	return;
-fail:
-	if (raw_fmts) {
-		kfree(raw_fmts);
-		raw_fmts = NULL;
-	}
-	if (!IS_ERR(filep))
-		filp_close(filep, NULL);
-	set_fs(fs);
-	if (strstr(str_file, ram_file_str) != NULL) {
-		temp->raw_sstr = NULL;
-	} else if (strstr(str_file, rom_file_str) != NULL) {
-		temp->rom_raw_sstr = NULL;
-	}
-	return;
-}
-
-#endif /* SHOW_LOGTRACE */
-
-
-dhd_pub_t *
-dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
-{
-	dhd_info_t *dhd = NULL;
-	struct net_device *net = NULL;
-	char if_name[IFNAMSIZ] = {'\0'};
-	uint32 bus_type = -1;
-	uint32 bus_num = -1;
-	uint32 slot_num = -1;
-	wifi_adapter_info_t *adapter = NULL;
-
-	dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT;
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-#ifdef STBLINUX
-	DHD_ERROR(("%s\n", driver_target));
-#endif /* STBLINUX */
-	/* will implement get_ids for DBUS later */
-#if defined(BCMSDIO)
-	dhd_bus_get_ids(bus, &bus_type, &bus_num, &slot_num);
-#endif 
-	adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
-
-	/* Allocate primary dhd_info */
-	dhd = wifi_platform_prealloc(adapter, DHD_PREALLOC_DHD_INFO, sizeof(dhd_info_t));
-	if (dhd == NULL) {
-		dhd = MALLOC(osh, sizeof(dhd_info_t));
-		if (dhd == NULL) {
-			DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__));
-			goto fail;
-		}
-	}
-	memset(dhd, 0, sizeof(dhd_info_t));
-	dhd_state |= DHD_ATTACH_STATE_DHD_ALLOC;
-
-	dhd->unit = dhd_found + instance_base; /* do not increment dhd_found, yet */
-
-	dhd->pub.osh = osh;
-	dhd->adapter = adapter;
-
-#ifdef GET_CUSTOM_MAC_ENABLE
-	wifi_platform_get_mac_addr(dhd->adapter, dhd->pub.mac.octet);
-#endif /* GET_CUSTOM_MAC_ENABLE */
-#ifdef CUSTOM_FORCE_NODFS_FLAG
-	dhd->pub.dhd_cflags |= WLAN_PLAT_NODFS_FLAG;
-	dhd->pub.force_country_change = TRUE;
-#endif /* CUSTOM_FORCE_NODFS_FLAG */
-#ifdef CUSTOM_COUNTRY_CODE
-	get_customized_country_code(dhd->adapter,
-		dhd->pub.dhd_cspec.country_abbrev, &dhd->pub.dhd_cspec,
-		dhd->pub.dhd_cflags);
-#endif /* CUSTOM_COUNTRY_CODE */
-	dhd->thr_dpc_ctl.thr_pid = DHD_PID_KT_TL_INVALID;
-	dhd->thr_wdt_ctl.thr_pid = DHD_PID_KT_INVALID;
-
-	/* Initialize thread based operation and lock */
-	sema_init(&dhd->sdsem, 1);
-
-	/* Some DHD modules (e.g. cfg80211) configures operation mode based on firmware name.
-	 * This is indeed a hack but we have to make it work properly before we have a better
-	 * solution
-	 */
-	dhd_update_fw_nv_path(dhd);
-
-	/* Link to info module */
-	dhd->pub.info = dhd;
-
-
-	/* Link to bus module */
-	dhd->pub.bus = bus;
-	dhd->pub.hdrlen = bus_hdrlen;
-
-	/* Set network interface name if it was provided as module parameter */
-	if (iface_name[0]) {
-		int len;
-		char ch;
-		strncpy(if_name, iface_name, IFNAMSIZ);
-		if_name[IFNAMSIZ - 1] = 0;
-		len = strlen(if_name);
-		ch = if_name[len - 1];
-		if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
-			strcat(if_name, "%d");
-	}
-
-	/* Passing NULL to dngl_name to ensure host gets if_name in dngl_name member */
-	net = dhd_allocate_if(&dhd->pub, 0, if_name, NULL, 0, TRUE, NULL);
-	if (net == NULL) {
-		goto fail;
-	}
-
-
-	dhd_state |= DHD_ATTACH_STATE_ADD_IF;
-#ifdef DHD_L2_FILTER
-	/* initialize the l2_filter_cnt */
-	dhd->pub.l2_filter_cnt = 0;
-#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
-	net->open = NULL;
-#else
-	net->netdev_ops = NULL;
-#endif
-
-	mutex_init(&dhd->dhd_iovar_mutex);
-	sema_init(&dhd->proto_sem, 1);
-
-#ifdef PROP_TXSTATUS
-	spin_lock_init(&dhd->wlfc_spinlock);
-
-	dhd->pub.skip_fc = dhd_wlfc_skip_fc;
-	dhd->pub.plat_init = dhd_wlfc_plat_init;
-	dhd->pub.plat_deinit = dhd_wlfc_plat_deinit;
-
-#ifdef DHD_WLFC_THREAD
-	init_waitqueue_head(&dhd->pub.wlfc_wqhead);
-	dhd->pub.wlfc_thread = kthread_create(dhd_wlfc_transfer_packets, &dhd->pub, "wlfc-thread");
-	if (IS_ERR(dhd->pub.wlfc_thread)) {
-		DHD_ERROR(("create wlfc thread failed\n"));
-		goto fail;
-	} else {
-		wake_up_process(dhd->pub.wlfc_thread);
-	}
-#endif /* DHD_WLFC_THREAD */
-#endif /* PROP_TXSTATUS */
-
-	/* Initialize other structure content */
-	init_waitqueue_head(&dhd->ioctl_resp_wait);
-	init_waitqueue_head(&dhd->d3ack_wait);
-	init_waitqueue_head(&dhd->ctrl_wait);
-	init_waitqueue_head(&dhd->dhd_bus_busy_state_wait);
-	dhd->pub.dhd_bus_busy_state = 0;
-
-	/* Initialize the spinlocks */
-	spin_lock_init(&dhd->sdlock);
-	spin_lock_init(&dhd->txqlock);
-	spin_lock_init(&dhd->dhd_lock);
-	spin_lock_init(&dhd->rxf_lock);
-#if defined(RXFRAME_THREAD)
-	dhd->rxthread_enabled = TRUE;
-#endif /* defined(RXFRAME_THREAD) */
-
-#ifdef DHDTCPACK_SUPPRESS
-	spin_lock_init(&dhd->tcpack_lock);
-#endif /* DHDTCPACK_SUPPRESS */
-
-	/* Initialize Wakelock stuff */
-	spin_lock_init(&dhd->wakelock_spinlock);
-	spin_lock_init(&dhd->wakelock_evt_spinlock);
-	DHD_OS_WAKE_LOCK_INIT(dhd);
-	dhd->wakelock_wd_counter = 0;
-#ifdef CONFIG_HAS_WAKELOCK
-	wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake");
-#endif /* CONFIG_HAS_WAKELOCK */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	mutex_init(&dhd->dhd_net_if_mutex);
-	mutex_init(&dhd->dhd_suspend_mutex);
-#endif
-	dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT;
-
-	/* Attach and link in the protocol */
-	if (dhd_prot_attach(&dhd->pub) != 0) {
-		DHD_ERROR(("dhd_prot_attach failed\n"));
-		goto fail;
-	}
-	dhd_state |= DHD_ATTACH_STATE_PROT_ATTACH;
-
-#ifdef WL_CFG80211
-	/* Attach and link in the cfg80211 */
-	if (unlikely(wl_cfg80211_attach(net, &dhd->pub))) {
-		DHD_ERROR(("wl_cfg80211_attach failed\n"));
-		goto fail;
-	}
-
-	dhd_monitor_init(&dhd->pub);
-	dhd_state |= DHD_ATTACH_STATE_CFG80211;
-#endif
-#ifdef DHD_LOG_DUMP
-	dhd_log_dump_init(&dhd->pub);
-#endif /* DHD_LOG_DUMP */
-#if defined(WL_WIRELESS_EXT)
-	/* Attach and link in the iw */
-	if (!(dhd_state &  DHD_ATTACH_STATE_CFG80211)) {
-		if (wl_iw_attach(net, (void *)&dhd->pub) != 0) {
-		DHD_ERROR(("wl_iw_attach failed\n"));
-		goto fail;
-	}
-	dhd_state |= DHD_ATTACH_STATE_WL_ATTACH;
-	}
-#endif /* defined(WL_WIRELESS_EXT) */
-
-#ifdef SHOW_LOGTRACE
-	dhd_init_logstrs_array(&dhd->event_data);
-	dhd_init_static_strs_array(&dhd->event_data, st_str_file_path, map_file_path);
-	dhd_init_static_strs_array(&dhd->event_data, rom_st_str_file_path, rom_map_file_path);
-#endif /* SHOW_LOGTRACE */
-
-	if (dhd_sta_pool_init(&dhd->pub, DHD_MAX_STA) != BCME_OK) {
-		DHD_ERROR(("%s: Initializing %u sta\n", __FUNCTION__, DHD_MAX_STA));
-		goto fail;
-	}
-
-
-
-	/* Set up the watchdog timer */
-	init_timer(&dhd->timer);
-	dhd->timer.data = (ulong)dhd;
-	dhd->timer.function = dhd_watchdog;
-	dhd->default_wd_interval = dhd_watchdog_ms;
-
-	if (dhd_watchdog_prio >= 0) {
-		/* Initialize watchdog thread */
-		PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread");
-		if (dhd->thr_wdt_ctl.thr_pid < 0) {
-			goto fail;
-		}
-
-	} else {
-		dhd->thr_wdt_ctl.thr_pid = -1;
-	}
-
-#ifdef DHD_PCIE_RUNTIMEPM
-	/* Setup up the runtime PM Idlecount timer */
-	init_timer(&dhd->rpm_timer);
-	dhd->rpm_timer.data = (ulong)dhd;
-	dhd->rpm_timer.function = dhd_runtimepm;
-	dhd->rpm_timer_valid = FALSE;
-
-	dhd->thr_rpm_ctl.thr_pid = DHD_PID_KT_INVALID;
-	PROC_START(dhd_rpm_state_thread, dhd, &dhd->thr_rpm_ctl, 0, "dhd_rpm_state_thread");
-	if (dhd->thr_rpm_ctl.thr_pid < 0) {
-		goto fail;
-	}
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-#ifdef DEBUGGER
-	debugger_init((void *) bus);
-#endif
-
-	/* Set up the bottom half handler */
-	if (dhd_dpc_prio >= 0) {
-		/* Initialize DPC thread */
-		PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc");
-		if (dhd->thr_dpc_ctl.thr_pid < 0) {
-			goto fail;
-		}
-	} else {
-		/*  use tasklet for dpc */
-		tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd);
-		dhd->thr_dpc_ctl.thr_pid = -1;
-	}
-
-	if (dhd->rxthread_enabled) {
-		bzero(&dhd->pub.skbbuf[0], sizeof(void *) * MAXSKBPEND);
-		/* Initialize RXF thread */
-		PROC_START(dhd_rxf_thread, dhd, &dhd->thr_rxf_ctl, 0, "dhd_rxf");
-		if (dhd->thr_rxf_ctl.thr_pid < 0) {
-			goto fail;
-		}
-	}
-
-	dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED;
-
-#if defined(CONFIG_PM_SLEEP)
-	if (!dhd_pm_notifier_registered) {
-		dhd_pm_notifier_registered = TRUE;
-		dhd->pm_notifier.notifier_call = dhd_pm_callback;
-		dhd->pm_notifier.priority = 10;
-		register_pm_notifier(&dhd->pm_notifier);
-	}
-
-#endif /* CONFIG_PM_SLEEP */
-
-#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
-	dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
-	dhd->early_suspend.suspend = dhd_early_suspend;
-	dhd->early_suspend.resume = dhd_late_resume;
-	register_early_suspend(&dhd->early_suspend);
-	dhd_state |= DHD_ATTACH_STATE_EARLYSUSPEND_DONE;
-#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
-
-#ifdef ARP_OFFLOAD_SUPPORT
-	dhd->pend_ipaddr = 0;
-	if (!dhd_inetaddr_notifier_registered) {
-		dhd_inetaddr_notifier_registered = TRUE;
-		register_inetaddr_notifier(&dhd_inetaddr_notifier);
-	}
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT)
-	if (!dhd_inet6addr_notifier_registered) {
-		dhd_inet6addr_notifier_registered = TRUE;
-		register_inet6addr_notifier(&dhd_inet6addr_notifier);
-	}
-#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */
-	dhd->dhd_deferred_wq = dhd_deferred_work_init((void *)dhd);
-#ifdef DEBUG_CPU_FREQ
-	dhd->new_freq = alloc_percpu(int);
-	dhd->freq_trans.notifier_call = dhd_cpufreq_notifier;
-	cpufreq_register_notifier(&dhd->freq_trans, CPUFREQ_TRANSITION_NOTIFIER);
-#endif
-#ifdef DHDTCPACK_SUPPRESS
-#ifdef BCMSDIO
-	dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_DELAYTX);
-#elif defined(BCMPCIE)
-	dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_HOLD);
-#else
-	dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF);
-#endif /* BCMSDIO */
-#endif /* DHDTCPACK_SUPPRESS */
-
-#if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW)
-#endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */
-
-	dhd_state |= DHD_ATTACH_STATE_DONE;
-	dhd->dhd_state = dhd_state;
-
-	dhd_found++;
-#ifdef DHD_DEBUG_PAGEALLOC
-	register_page_corrupt_cb(dhd_page_corrupt_cb, &dhd->pub);
-#endif /* DHD_DEBUG_PAGEALLOC */
-
-#if defined(DHD_LB)
-	DHD_ERROR(("DHD LOAD BALANCING Enabled\n"));
-
-	dhd_lb_set_default_cpus(dhd);
-
-	/* Initialize the CPU Masks */
-	if (dhd_cpumasks_init(dhd) ==  0) {
-
-		/* Now we have the current CPU maps, run through candidacy */
-		dhd_select_cpu_candidacy(dhd);
-
-		/*
-		 * If we are able to initialize CPU masks, lets register to the
-		 * CPU Hotplug framework to change the CPU for each job dynamically
-		 * using candidacy algorithm.
-		 */
-		dhd->cpu_notifier.notifier_call = dhd_cpu_callback;
-		register_cpu_notifier(&dhd->cpu_notifier); /* Register a callback */
-	} else {
-		/*
-		 * We are unable to initialize CPU masks, so candidacy algorithm
-		 * won't run, but still Load Balancing will be honoured based
-		 * on the CPUs allocated for a given job statically during init
-		 */
-		dhd->cpu_notifier.notifier_call = NULL;
-		DHD_ERROR(("%s(): dhd_cpumasks_init failed CPUs for JOB would be static\n",
-			__FUNCTION__));
-	}
-
-
-	DHD_LB_STATS_INIT(&dhd->pub);
-
-	/* Initialize the Load Balancing Tasklets and Napi object */
-#if defined(DHD_LB_TXC)
-	tasklet_init(&dhd->tx_compl_tasklet,
-		dhd_lb_tx_compl_handler, (ulong)(&dhd->pub));
-	INIT_WORK(&dhd->tx_compl_dispatcher_work, dhd_tx_compl_dispatcher_fn);
-	DHD_INFO(("%s load balance init tx_compl_tasklet\n", __FUNCTION__));
-#endif /* DHD_LB_TXC */
-
-#if defined(DHD_LB_RXC)
-	tasklet_init(&dhd->rx_compl_tasklet,
-		dhd_lb_rx_compl_handler, (ulong)(&dhd->pub));
-	INIT_WORK(&dhd->rx_compl_dispatcher_work, dhd_rx_compl_dispatcher_fn);
-	DHD_INFO(("%s load balance init rx_compl_tasklet\n", __FUNCTION__));
-#endif /* DHD_LB_RXC */
-
-#if defined(DHD_LB_RXP)
-	 __skb_queue_head_init(&dhd->rx_pend_queue);
-	skb_queue_head_init(&dhd->rx_napi_queue);
-
-	/* Initialize the work that dispatches NAPI job to a given core */
-	INIT_WORK(&dhd->rx_napi_dispatcher_work, dhd_rx_napi_dispatcher_fn);
-	DHD_INFO(("%s load balance init rx_napi_queue\n", __FUNCTION__));
-#endif /* DHD_LB_RXP */
-
-#endif /* DHD_LB */
-
-	INIT_DELAYED_WORK(&dhd->dhd_memdump_work, dhd_memdump_work_handler);
-
-	(void)dhd_sysfs_init(dhd);
-
-	return &dhd->pub;
-
-fail:
-	if (dhd_state >= DHD_ATTACH_STATE_DHD_ALLOC) {
-		DHD_TRACE(("%s: Calling dhd_detach dhd_state 0x%x &dhd->pub %p\n",
-			__FUNCTION__, dhd_state, &dhd->pub));
-		dhd->dhd_state = dhd_state;
-		dhd_detach(&dhd->pub);
-		dhd_free(&dhd->pub);
-	}
-
-	return NULL;
-}
-
-#include <linux/delay.h>
-
-void dhd_memdump_work_schedule(dhd_pub_t *dhdp, unsigned long msecs)
-{
-	dhd_info_t *dhd = (dhd_info_t*)dhdp->info;
-
-	schedule_delayed_work(&dhd->dhd_memdump_work, msecs_to_jiffies(msecs));
-}
-
-int dhd_get_fw_mode(dhd_info_t *dhdinfo)
-{
-	if (strstr(dhdinfo->fw_path, "_apsta") != NULL)
-		return DHD_FLAG_HOSTAP_MODE;
-	if (strstr(dhdinfo->fw_path, "_p2p") != NULL)
-		return DHD_FLAG_P2P_MODE;
-	if (strstr(dhdinfo->fw_path, "_ibss") != NULL)
-		return DHD_FLAG_IBSS_MODE;
-	if (strstr(dhdinfo->fw_path, "_mfg") != NULL)
-		return DHD_FLAG_MFG_MODE;
-
-	return DHD_FLAG_STA_MODE;
-}
-
-bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
-{
-	int fw_len;
-	int nv_len;
-	const char *fw = NULL;
-	const char *nv = NULL;
-	wifi_adapter_info_t *adapter = dhdinfo->adapter;
-
-
-	/* Update firmware and nvram path. The path may be from adapter info or module parameter
-	 * The path from adapter info is used for initialization only (as it won't change).
-	 *
-	 * The firmware_path/nvram_path module parameter may be changed by the system at run
-	 * time. When it changes we need to copy it to dhdinfo->fw_path. Also Android private
-	 * command may change dhdinfo->fw_path. As such we need to clear the path info in
-	 * module parameter after it is copied. We won't update the path until the module parameter
-	 * is changed again (first character is not '\0')
-	 */
-
-	/* set default firmware and nvram path for built-in type driver */
-	if (!dhd_download_fw_on_driverload) {
-#ifdef CONFIG_BCMDHD_FW_PATH
-		fw = CONFIG_BCMDHD_FW_PATH;
-#endif /* CONFIG_BCMDHD_FW_PATH */
-#ifdef CONFIG_BCMDHD_NVRAM_PATH
-		nv = CONFIG_BCMDHD_NVRAM_PATH;
-#endif /* CONFIG_BCMDHD_NVRAM_PATH */
-	}
-
-	/* check if we need to initialize the path */
-	if (dhdinfo->fw_path[0] == '\0') {
-		if (adapter && adapter->fw_path && adapter->fw_path[0] != '\0')
-			fw = adapter->fw_path;
-
-	}
-	if (dhdinfo->nv_path[0] == '\0') {
-		if (adapter && adapter->nv_path && adapter->nv_path[0] != '\0')
-			nv = adapter->nv_path;
-	}
-
-	/* Use module parameter if it is valid, EVEN IF the path has not been initialized
-	 *
-	 * TODO: need a solution for multi-chip, can't use the same firmware for all chips
-	 */
-	if (firmware_path[0] != '\0')
-		fw = firmware_path;
-	if (nvram_path[0] != '\0')
-		nv = nvram_path;
-
-	if (fw && fw[0] != '\0') {
-		fw_len = strlen(fw);
-		if (fw_len >= sizeof(dhdinfo->fw_path)) {
-			DHD_ERROR(("fw path len exceeds max len of dhdinfo->fw_path\n"));
-			return FALSE;
-		}
-		strncpy(dhdinfo->fw_path, fw, sizeof(dhdinfo->fw_path));
-		if (dhdinfo->fw_path[fw_len-1] == '\n')
-		       dhdinfo->fw_path[fw_len-1] = '\0';
-	}
-	if (nv && nv[0] != '\0') {
-		nv_len = strlen(nv);
-		if (nv_len >= sizeof(dhdinfo->nv_path)) {
-			DHD_ERROR(("nvram path len exceeds max len of dhdinfo->nv_path\n"));
-			return FALSE;
-		}
-		strncpy(dhdinfo->nv_path, nv, sizeof(dhdinfo->nv_path));
-		if (dhdinfo->nv_path[nv_len-1] == '\n')
-		       dhdinfo->nv_path[nv_len-1] = '\0';
-	}
-
-	/* clear the path in module parameter */
-	if (dhd_download_fw_on_driverload) {
-		firmware_path[0] = '\0';
-		nvram_path[0] = '\0';
-	}
-#ifndef BCMEMBEDIMAGE
-	/* fw_path and nv_path are not mandatory for BCMEMBEDIMAGE */
-	if (dhdinfo->fw_path[0] == '\0') {
-		DHD_ERROR(("firmware path not found\n"));
-		return FALSE;
-	}
-	if (dhdinfo->nv_path[0] == '\0') {
-		DHD_ERROR(("nvram path not found\n"));
-		return FALSE;
-	}
-#endif /* BCMEMBEDIMAGE */
-
-	return TRUE;
-}
-
-#ifdef CUSTOMER_HW4_DEBUG
-bool dhd_validate_chipid(dhd_pub_t *dhdp)
-{
-	uint chipid = dhd_bus_chip_id(dhdp);
-	uint config_chipid;
-
-#ifdef BCM4359_CHIP
-	config_chipid = BCM4359_CHIP_ID;
-#elif defined(BCM4358_CHIP)
-	config_chipid = BCM4358_CHIP_ID;
-#elif defined(BCM4354_CHIP)
-	config_chipid = BCM4354_CHIP_ID;
-#elif defined(BCM4356_CHIP)
-	config_chipid = BCM4356_CHIP_ID;
-#elif defined(BCM4339_CHIP)
-	config_chipid = BCM4339_CHIP_ID;
-#elif defined(BCM43349_CHIP)
-	config_chipid = BCM43349_CHIP_ID;
-#elif defined(BCM4335_CHIP)
-	config_chipid = BCM4335_CHIP_ID;
-#elif defined(BCM43241_CHIP)
-	config_chipid = BCM4324_CHIP_ID;
-#elif defined(BCM4330_CHIP)
-	config_chipid = BCM4330_CHIP_ID;
-#elif defined(BCM43430_CHIP)
-	config_chipid = BCM43430_CHIP_ID;
-#elif defined(BCM4334W_CHIP)
-	config_chipid = BCM43342_CHIP_ID;
-#elif defined(BCM43455_CHIP)
-	config_chipid = BCM4345_CHIP_ID;
-#else
-	DHD_ERROR(("%s: Unknown chip id, if you use new chipset,"
-		" please add CONFIG_BCMXXXX into the Kernel and"
-		" BCMXXXX_CHIP definition into the DHD driver\n",
-		__FUNCTION__));
-	config_chipid = 0;
-
-	return FALSE;
-#endif /* BCM4354_CHIP */
-
-#if defined(BCM4359_CHIP)
-	if (chipid == BCM4355_CHIP_ID && config_chipid == BCM4359_CHIP_ID) {
-		return TRUE;
-	}
-#endif /* BCM4359_CHIP */
-
-	return config_chipid == chipid;
-}
-#endif /* CUSTOMER_HW4_DEBUG */
-
-int
-dhd_bus_start(dhd_pub_t *dhdp)
-{
-	int ret = -1;
-	dhd_info_t *dhd = (dhd_info_t*)dhdp->info;
-	unsigned long flags;
-
-	ASSERT(dhd);
-
-	DHD_TRACE(("Enter %s:\n", __FUNCTION__));
-
-	DHD_PERIM_LOCK(dhdp);
-
-	/* try to download image and nvram to the dongle */
-	if  (dhd->pub.busstate == DHD_BUS_DOWN && dhd_update_fw_nv_path(dhd)) {
-		/* Indicate FW Download has not yet done */
-		dhd->pub.is_fw_download_done = FALSE;
-		DHD_INFO(("%s download fw %s, nv %s\n", __FUNCTION__, dhd->fw_path, dhd->nv_path));
-		ret = dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
-		                                dhd->fw_path, dhd->nv_path);
-		if (ret < 0) {
-			DHD_ERROR(("%s: failed to download firmware %s\n",
-			          __FUNCTION__, dhd->fw_path));
-			DHD_PERIM_UNLOCK(dhdp);
-			return ret;
-		}
-		/* Indicate FW Download has succeeded */
-		dhd->pub.is_fw_download_done = TRUE;
-	}
-	if (dhd->pub.busstate != DHD_BUS_LOAD) {
-		DHD_PERIM_UNLOCK(dhdp);
-		return -ENETDOWN;
-	}
-
-	dhd_os_sdlock(dhdp);
-
-	/* Start the watchdog timer */
-	dhd->pub.tickcnt = 0;
-	dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
-	DHD_ENABLE_RUNTIME_PM(&dhd->pub);
-
-	/* Bring up the bus */
-	if ((ret = dhd_bus_init(&dhd->pub, FALSE)) != 0) {
-
-		DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret));
-		dhd_os_sdunlock(dhdp);
-		DHD_PERIM_UNLOCK(dhdp);
-		return ret;
-	}
-#if defined(OOB_INTR_ONLY) || defined(BCMPCIE_OOB_HOST_WAKE)
-#if defined(BCMPCIE_OOB_HOST_WAKE)
-	dhd_os_sdunlock(dhdp);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-	/* Host registration for OOB interrupt */
-	if (dhd_bus_oob_intr_register(dhdp)) {
-		/* deactivate timer and wait for the handler to finish */
-#if !defined(BCMPCIE_OOB_HOST_WAKE)
-		DHD_GENERAL_LOCK(&dhd->pub, flags);
-		dhd->wd_timer_valid = FALSE;
-		DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-		del_timer_sync(&dhd->timer);
-
-		dhd_os_sdunlock(dhdp);
-#endif /* !BCMPCIE_OOB_HOST_WAKE */
-		DHD_DISABLE_RUNTIME_PM(&dhd->pub);
-		DHD_PERIM_UNLOCK(dhdp);
-		DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
-		DHD_ERROR(("%s Host failed to register for OOB\n", __FUNCTION__));
-		return -ENODEV;
-	}
-
-#if defined(BCMPCIE_OOB_HOST_WAKE)
-	dhd_os_sdlock(dhdp);
-	dhd_bus_oob_intr_set(dhdp, TRUE);
-#else
-	/* Enable oob at firmware */
-	dhd_enable_oob_intr(dhd->pub.bus, TRUE);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-#endif 
-#ifdef PCIE_FULL_DONGLE
-	{
-		/* max_h2d_rings includes H2D common rings */
-		uint32 max_h2d_rings = dhd_bus_max_h2d_queues(dhd->pub.bus);
-
-		DHD_ERROR(("%s: Initializing %u h2drings\n", __FUNCTION__,
-			max_h2d_rings));
-		if ((ret = dhd_flow_rings_init(&dhd->pub, max_h2d_rings)) != BCME_OK) {
-			dhd_os_sdunlock(dhdp);
-			DHD_PERIM_UNLOCK(dhdp);
-			return ret;
-		}
-	}
-#endif /* PCIE_FULL_DONGLE */
-
-	/* Do protocol initialization necessary for IOCTL/IOVAR */
-#ifdef PCIE_FULL_DONGLE
-	dhd_os_sdunlock(dhdp);
-#endif /* PCIE_FULL_DONGLE */
-	ret = dhd_prot_init(&dhd->pub);
-	if (unlikely(ret) != BCME_OK) {
-		DHD_PERIM_UNLOCK(dhdp);
-		DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
-		return ret;
-	}
-#ifdef PCIE_FULL_DONGLE
-	dhd_os_sdlock(dhdp);
-#endif /* PCIE_FULL_DONGLE */
-
-	/* If bus is not ready, can't come up */
-	if (dhd->pub.busstate != DHD_BUS_DATA) {
-		DHD_GENERAL_LOCK(&dhd->pub, flags);
-		dhd->wd_timer_valid = FALSE;
-		DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-		del_timer_sync(&dhd->timer);
-		DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__));
-		DHD_DISABLE_RUNTIME_PM(&dhd->pub);
-		dhd_os_sdunlock(dhdp);
-		DHD_PERIM_UNLOCK(dhdp);
-		DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
-		return -ENODEV;
-	}
-
-	dhd_os_sdunlock(dhdp);
-
-	/* Bus is ready, query any dongle information */
-	if ((ret = dhd_sync_with_dongle(&dhd->pub)) < 0) {
-		DHD_GENERAL_LOCK(&dhd->pub, flags);
-		dhd->wd_timer_valid = FALSE;
-		DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-		del_timer_sync(&dhd->timer);
-		DHD_ERROR(("%s failed to sync with dongle\n", __FUNCTION__));
-		DHD_DISABLE_RUNTIME_PM(&dhd->pub);
-		DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
-		DHD_PERIM_UNLOCK(dhdp);
-		return ret;
-	}
-
-#ifdef ARP_OFFLOAD_SUPPORT
-	if (dhd->pend_ipaddr) {
-#ifdef AOE_IP_ALIAS_SUPPORT
-		aoe_update_host_ipv4_table(&dhd->pub, dhd->pend_ipaddr, TRUE, 0);
-#endif /* AOE_IP_ALIAS_SUPPORT */
-		dhd->pend_ipaddr = 0;
-	}
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-	DHD_PERIM_UNLOCK(dhdp);
-	return 0;
-}
-#ifdef WLTDLS
-int _dhd_tdls_enable(dhd_pub_t *dhd, bool tdls_on, bool auto_on, struct ether_addr *mac)
-{
-	char iovbuf[WLC_IOCTL_SMLEN];
-	uint32 tdls = tdls_on;
-	int ret = 0;
-	uint32 tdls_auto_op = 0;
-	uint32 tdls_idle_time = CUSTOM_TDLS_IDLE_MODE_SETTING;
-	int32 tdls_rssi_high = CUSTOM_TDLS_RSSI_THRESHOLD_HIGH;
-	int32 tdls_rssi_low = CUSTOM_TDLS_RSSI_THRESHOLD_LOW;
-	BCM_REFERENCE(mac);
-	if (!FW_SUPPORTED(dhd, tdls))
-		return BCME_ERROR;
-
-	if (dhd->tdls_enable == tdls_on)
-		goto auto_mode;
-	bcm_mkiovar("tdls_enable", (char *)&tdls, sizeof(tdls), iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s: tdls %d failed %d\n", __FUNCTION__, tdls, ret));
-		goto exit;
-	}
-	dhd->tdls_enable = tdls_on;
-auto_mode:
-
-	tdls_auto_op = auto_on;
-	bcm_mkiovar("tdls_auto_op", (char *)&tdls_auto_op, sizeof(tdls_auto_op),
-		iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-		sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s: tdls_auto_op failed %d\n", __FUNCTION__, ret));
-		goto exit;
-	}
-
-	if (tdls_auto_op) {
-		bcm_mkiovar("tdls_idle_time", (char *)&tdls_idle_time,
-			sizeof(tdls_idle_time),	iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-			sizeof(iovbuf), TRUE, 0)) < 0) {
-			DHD_ERROR(("%s: tdls_idle_time failed %d\n", __FUNCTION__, ret));
-			goto exit;
-		}
-		bcm_mkiovar("tdls_rssi_high", (char *)&tdls_rssi_high, 4, iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-			sizeof(iovbuf), TRUE, 0)) < 0) {
-			DHD_ERROR(("%s: tdls_rssi_high failed %d\n", __FUNCTION__, ret));
-			goto exit;
-		}
-		bcm_mkiovar("tdls_rssi_low", (char *)&tdls_rssi_low, 4, iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-			sizeof(iovbuf), TRUE, 0)) < 0) {
-			DHD_ERROR(("%s: tdls_rssi_low failed %d\n", __FUNCTION__, ret));
-			goto exit;
-		}
-	}
-
-exit:
-	return ret;
-}
-int dhd_tdls_enable(struct net_device *dev, bool tdls_on, bool auto_on, struct ether_addr *mac)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ret = 0;
-	if (dhd)
-		ret = _dhd_tdls_enable(&dhd->pub, tdls_on, auto_on, mac);
-	else
-		ret = BCME_ERROR;
-	return ret;
-}
-int
-dhd_tdls_set_mode(dhd_pub_t *dhd, bool wfd_mode)
-{
-	char iovbuf[WLC_IOCTL_SMLEN];
-	int ret = 0;
-	bool auto_on = false;
-	uint32 mode =  wfd_mode;
-
-#ifdef ENABLE_TDLS_AUTO_MODE
-	if (wfd_mode) {
-		auto_on = false;
-	} else {
-		auto_on = true;
-	}
-#else
-	auto_on = false;
-#endif /* ENABLE_TDLS_AUTO_MODE */
-	ret = _dhd_tdls_enable(dhd, false, auto_on, NULL);
-	if (ret < 0) {
-		DHD_ERROR(("Disable tdls_auto_op failed. %d\n", ret));
-		return ret;
-	}
-
-
-	bcm_mkiovar("tdls_wfd_mode", (char *)&mode, sizeof(mode),
-			iovbuf, sizeof(iovbuf));
-	if (((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-			sizeof(iovbuf), TRUE, 0)) < 0) &&
-			(ret != BCME_UNSUPPORTED)) {
-		DHD_ERROR(("%s: tdls_wfd_mode faile_wfd_mode %d\n", __FUNCTION__, ret));
-		return ret;
-	}
-
-	ret = _dhd_tdls_enable(dhd, true, auto_on, NULL);
-	if (ret < 0) {
-		DHD_ERROR(("enable tdls_auto_op failed. %d\n", ret));
-		return ret;
-	}
-
-	dhd->tdls_mode = mode;
-	return ret;
-}
-#ifdef PCIE_FULL_DONGLE
-void dhd_tdls_update_peer_info(struct net_device *dev, bool connect, uint8 *da)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	dhd_pub_t *dhdp =  (dhd_pub_t *)&dhd->pub;
-	tdls_peer_node_t *cur = dhdp->peer_tbl.node;
-	tdls_peer_node_t *new = NULL, *prev = NULL;
-	dhd_if_t *dhdif;
-	uint8 sa[ETHER_ADDR_LEN];
-	int ifidx = dhd_net2idx(dhd, dev);
-
-	if (ifidx == DHD_BAD_IF)
-		return;
-
-	dhdif = dhd->iflist[ifidx];
-	memcpy(sa, dhdif->mac_addr, ETHER_ADDR_LEN);
-
-	if (connect) {
-		while (cur != NULL) {
-			if (!memcmp(da, cur->addr, ETHER_ADDR_LEN)) {
-				DHD_ERROR(("%s: TDLS Peer exist already %d\n",
-					__FUNCTION__, __LINE__));
-				return;
-			}
-			cur = cur->next;
-		}
-
-		new = MALLOC(dhdp->osh, sizeof(tdls_peer_node_t));
-		if (new == NULL) {
-			DHD_ERROR(("%s: Failed to allocate memory\n", __FUNCTION__));
-			return;
-		}
-		memcpy(new->addr, da, ETHER_ADDR_LEN);
-		new->next = dhdp->peer_tbl.node;
-		dhdp->peer_tbl.node = new;
-		dhdp->peer_tbl.tdls_peer_count++;
-
-	} else {
-		while (cur != NULL) {
-			if (!memcmp(da, cur->addr, ETHER_ADDR_LEN)) {
-				dhd_flow_rings_delete_for_peer(dhdp, ifidx, da);
-				if (prev)
-					prev->next = cur->next;
-				else
-					dhdp->peer_tbl.node = cur->next;
-				MFREE(dhdp->osh, cur, sizeof(tdls_peer_node_t));
-				dhdp->peer_tbl.tdls_peer_count--;
-				return;
-			}
-			prev = cur;
-			cur = cur->next;
-		}
-		DHD_ERROR(("%s: TDLS Peer Entry Not found\n", __FUNCTION__));
-	}
-}
-#endif /* PCIE_FULL_DONGLE */
-#endif 
-
-bool dhd_is_concurrent_mode(dhd_pub_t *dhd)
-{
-	if (!dhd)
-		return FALSE;
-
-	if (dhd->op_mode & DHD_FLAG_CONCURR_MULTI_CHAN_MODE)
-		return TRUE;
-	else if ((dhd->op_mode & DHD_FLAG_CONCURR_SINGLE_CHAN_MODE) ==
-		DHD_FLAG_CONCURR_SINGLE_CHAN_MODE)
-		return TRUE;
-	else
-		return FALSE;
-}
-#if !defined(AP) && defined(WLP2P)
-/* From Android JerryBean release, the concurrent mode is enabled by default and the firmware
- * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA
- * firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware
- * would still be named as fw_bcmdhd_apsta.
- */
-uint32
-dhd_get_concurrent_capabilites(dhd_pub_t *dhd)
-{
-	int32 ret = 0;
-	char buf[WLC_IOCTL_SMLEN];
-	bool mchan_supported = FALSE;
-	/* if dhd->op_mode is already set for HOSTAP and Manufacturing
-	 * test mode, that means we only will use the mode as it is
-	 */
-	if (dhd->op_mode & (DHD_FLAG_HOSTAP_MODE | DHD_FLAG_MFG_MODE))
-		return 0;
-	if (FW_SUPPORTED(dhd, vsdb)) {
-		mchan_supported = TRUE;
-	}
-	if (!FW_SUPPORTED(dhd, p2p)) {
-		DHD_TRACE(("Chip does not support p2p\n"));
-		return 0;
-	} else {
-		/* Chip supports p2p but ensure that p2p is really implemented in firmware or not */
-		memset(buf, 0, sizeof(buf));
-		bcm_mkiovar("p2p", 0, 0, buf, sizeof(buf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
-			FALSE, 0)) < 0) {
-			DHD_ERROR(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret));
-			return 0;
-		} else {
-			if (buf[0] == 1) {
-				/* By default, chip supports single chan concurrency,
-				* now lets check for mchan
-				*/
-				ret = DHD_FLAG_CONCURR_SINGLE_CHAN_MODE;
-				if (mchan_supported)
-					ret |= DHD_FLAG_CONCURR_MULTI_CHAN_MODE;
-				if (FW_SUPPORTED(dhd, rsdb)) {
-					ret |= DHD_FLAG_RSDB_MODE;
-				}
-				if (FW_SUPPORTED(dhd, mp2p)) {
-					ret |= DHD_FLAG_MP2P_MODE;
-				}
-#if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
-				return ret;
-#else
-				return 0;
-#endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
-			}
-		}
-	}
-	return 0;
-}
-#endif 
-
-#ifdef SUPPORT_AP_POWERSAVE
-#define RXCHAIN_PWRSAVE_PPS			10
-#define RXCHAIN_PWRSAVE_QUIET_TIME		10
-#define RXCHAIN_PWRSAVE_STAS_ASSOC_CHECK	0
-int dhd_set_ap_powersave(dhd_pub_t *dhdp, int ifidx, int enable)
-{
-	char iovbuf[128];
-	int32 pps = RXCHAIN_PWRSAVE_PPS;
-	int32 quiet_time = RXCHAIN_PWRSAVE_QUIET_TIME;
-	int32 stas_assoc_check = RXCHAIN_PWRSAVE_STAS_ASSOC_CHECK;
-
-	if (enable) {
-		bcm_mkiovar("rxchain_pwrsave_enable", (char *)&enable, 4, iovbuf, sizeof(iovbuf));
-		if (dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR,
-		    iovbuf, sizeof(iovbuf), TRUE, 0) != BCME_OK) {
-			DHD_ERROR(("Failed to enable AP power save"));
-		}
-		bcm_mkiovar("rxchain_pwrsave_pps", (char *)&pps, 4, iovbuf, sizeof(iovbuf));
-		if (dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR,
-		    iovbuf, sizeof(iovbuf), TRUE, 0) != BCME_OK) {
-			DHD_ERROR(("Failed to set pps"));
-		}
-		bcm_mkiovar("rxchain_pwrsave_quiet_time", (char *)&quiet_time,
-		4, iovbuf, sizeof(iovbuf));
-		if (dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR,
-		    iovbuf, sizeof(iovbuf), TRUE, 0) != BCME_OK) {
-			DHD_ERROR(("Failed to set quiet time"));
-		}
-		bcm_mkiovar("rxchain_pwrsave_stas_assoc_check", (char *)&stas_assoc_check,
-		4, iovbuf, sizeof(iovbuf));
-		if (dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR,
-		    iovbuf, sizeof(iovbuf), TRUE, 0) != BCME_OK) {
-			DHD_ERROR(("Failed to set stas assoc check"));
-		}
-	} else {
-		bcm_mkiovar("rxchain_pwrsave_enable", (char *)&enable, 4, iovbuf, sizeof(iovbuf));
-		if (dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR,
-		    iovbuf, sizeof(iovbuf), TRUE, 0) != BCME_OK) {
-			DHD_ERROR(("Failed to disable AP power save"));
-		}
-	}
-
-	return 0;
-}
-#endif /* SUPPORT_AP_POWERSAVE */
-
-
-int
-dhd_preinit_ioctls(dhd_pub_t *dhd)
-{
-	int ret = 0;
-	char eventmask[WL_EVENTING_MASK_LEN];
-	char iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" + '\0' + bitvec  */
-	uint32 buf_key_b4_m4 = 1;
-	uint8 msglen;
-	eventmsgs_ext_t *eventmask_msg = NULL;
-	char* iov_buf = NULL;
-	int ret2 = 0;
-#if defined(CUSTOM_AMPDU_BA_WSIZE)
-	uint32 ampdu_ba_wsize = 0;
-#endif 
-#if defined(CUSTOM_AMPDU_MPDU)
-	int32 ampdu_mpdu = 0;
-#endif
-#if defined(CUSTOM_AMPDU_RELEASE)
-	int32 ampdu_release = 0;
-#endif
-#if defined(CUSTOM_AMSDU_AGGSF)
-	int32 amsdu_aggsf = 0;
-#endif
-#ifdef SUPPORT_SENSORHUB
-	int32 shub_enable = 0;
-#endif /* SUPPORT_SENSORHUB */
-#if defined(BCMSDIO)
-#ifdef PROP_TXSTATUS
-	int wlfc_enable = TRUE;
-#ifndef DISABLE_11N
-	uint32 hostreorder = 1;
-#endif /* DISABLE_11N */
-#endif /* PROP_TXSTATUS */
-#endif 
-#ifdef PCIE_FULL_DONGLE
-	uint32 wl_ap_isolate;
-#endif /* PCIE_FULL_DONGLE */
-
-#if defined(BCMSDIO)
-	/* by default frame burst is enabled for PCIe and disabled for SDIO dongles */
-	uint32 frameburst = 0;
-#else
-	uint32 frameburst = 1;
-#endif /* BCMSDIO */
-
-#ifdef DHD_ENABLE_LPC
-	uint32 lpc = 1;
-#endif /* DHD_ENABLE_LPC */
-	uint power_mode = PM_FAST;
-#if defined(BCMSDIO)
-	uint32 dongle_align = DHD_SDALIGN;
-	uint32 glom = CUSTOM_GLOM_SETTING;
-#endif /* defined(BCMSDIO) */
-#if defined(CUSTOMER_HW2) && defined(USE_WL_CREDALL)
-	uint32 credall = 1;
-#endif
-#if defined(VSDB) || defined(ROAM_ENABLE)
-	uint bcn_timeout = CUSTOM_BCN_TIMEOUT;
-#else
-	uint bcn_timeout = 4;
-#endif /* VSDB || ROAM_ENABLE */
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
-	uint32 bcn_li_bcn = 1;
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
-	uint retry_max = CUSTOM_ASSOC_RETRY_MAX;
-#if defined(ARP_OFFLOAD_SUPPORT)
-	int arpoe = 1;
-#endif
-	int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME;
-	int scan_unassoc_time = DHD_SCAN_UNASSOC_ACTIVE_TIME;
-	int scan_passive_time = DHD_SCAN_PASSIVE_TIME;
-	char buf[WLC_IOCTL_SMLEN];
-	char *ptr;
-	uint32 listen_interval = CUSTOM_LISTEN_INTERVAL; /* Default Listen Interval in Beacons */
-#ifdef ROAM_ENABLE
-	uint roamvar = 0;
-	int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL};
-	int roam_scan_period[2] = {10, WLC_BAND_ALL};
-	int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL};
-#ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC
-	int roam_fullscan_period = 60;
-#else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
-	int roam_fullscan_period = 120;
-#endif /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
-#else
-#ifdef DISABLE_BUILTIN_ROAM
-	uint roamvar = 1;
-#endif /* DISABLE_BUILTIN_ROAM */
-#endif /* ROAM_ENABLE */
-
-#if defined(SOFTAP)
-	uint dtim = 1;
-#endif
-#if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211))
-	uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */
-	struct ether_addr p2p_ea;
-#endif
-#ifdef SOFTAP_UAPSD_OFF
-	uint32 wme_apsd = 0;
-#endif /* SOFTAP_UAPSD_OFF */
-#if (defined(AP) || defined(WLP2P)) && !defined(SOFTAP_AND_GC)
-	uint32 apsta = 1; /* Enable APSTA mode */
-#elif defined(SOFTAP_AND_GC)
-	uint32 apsta = 0;
-	int ap_mode = 1;
-#endif /* (defined(AP) || defined(WLP2P)) && !defined(SOFTAP_AND_GC) */
-#ifdef GET_CUSTOM_MAC_ENABLE
-	struct ether_addr ea_addr;
-#endif /* GET_CUSTOM_MAC_ENABLE */
-
-#ifdef DISABLE_11N
-	uint32 nmode = 0;
-#endif /* DISABLE_11N */
-
-#ifdef USE_WL_TXBF
-	uint32 txbf = 1;
-#endif /* USE_WL_TXBF */
-#if defined(PROP_TXSTATUS)
-#ifdef USE_WFA_CERT_CONF
-	uint32 proptx = 0;
-#endif /* USE_WFA_CERT_CONF */
-#endif /* PROP_TXSTATUS */
-#ifdef CUSTOM_PSPRETEND_THR
-	uint32 pspretend_thr = CUSTOM_PSPRETEND_THR;
-#endif
-	uint32 rsdb_mode = 0;
-#ifdef ENABLE_TEMP_THROTTLING
-	wl_temp_control_t temp_control;
-#endif /* ENABLE_TEMP_THROTTLING */
-#ifdef DISABLE_PRUNED_SCAN
-	uint32 scan_features = 0;
-#endif /* DISABLE_PRUNED_SCAN */
-#ifdef CUSTOM_EVENT_PM_WAKE
-	uint32 pm_awake_thresh = CUSTOM_EVENT_PM_WAKE;
-#endif /* CUSTOM_EVENT_PM_WAKE */
-#ifdef PKT_FILTER_SUPPORT
-	dhd_pkt_filter_enable = TRUE;
-#endif /* PKT_FILTER_SUPPORT */
-#ifdef WLTDLS
-	dhd->tdls_enable = FALSE;
-	dhd_tdls_set_mode(dhd, false);
-#endif /* WLTDLS */
-	dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM;
-	DHD_TRACE(("Enter %s\n", __FUNCTION__));
-	dhd->op_mode = 0;
-#ifdef CUSTOMER_HW4_DEBUG
-	if (!dhd_validate_chipid(dhd)) {
-		DHD_ERROR(("%s: CONFIG_BCMXXX and CHIP ID(%x) is mismatched\n",
-			__FUNCTION__, dhd_bus_chip_id(dhd)));
-#ifndef SUPPORT_MULTIPLE_CHIPS
-		ret = BCME_BADARG;
-		goto done;
-#endif /* !SUPPORT_MULTIPLE_CHIPS */
-	}
-#endif /* CUSTOMER_HW4_DEBUG */
-	if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) ||
-		(op_mode == DHD_FLAG_MFG_MODE)) {
-#ifdef DHD_PCIE_RUNTIMEPM
-		/* Disable RuntimePM in mfg mode */
-		DHD_DISABLE_RUNTIME_PM(dhd);
-		DHD_ERROR(("%s : Disable RuntimePM in Manufactring Firmware\n", __FUNCTION__));
-#endif /* DHD_PCIE_RUNTIME_PM */
-		/* Check and adjust IOCTL response timeout for Manufactring firmware */
-		dhd_os_set_ioctl_resp_timeout(MFG_IOCTL_RESP_TIMEOUT);
-		DHD_ERROR(("%s : Set IOCTL response time for Manufactring Firmware\n",
-			__FUNCTION__));
-	} else {
-		dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT);
-		DHD_INFO(("%s : Set IOCTL response time.\n", __FUNCTION__));
-	}
-#ifdef GET_CUSTOM_MAC_ENABLE
-	ret = wifi_platform_get_mac_addr(dhd->info->adapter, ea_addr.octet);
-	if (!ret) {
-		memset(buf, 0, sizeof(buf));
-		bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf));
-		ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
-		if (ret < 0) {
-			DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
-			ret = BCME_NOTUP;
-			goto done;
-		}
-		memcpy(dhd->mac.octet, ea_addr.octet, ETHER_ADDR_LEN);
-	} else {
-#endif /* GET_CUSTOM_MAC_ENABLE */
-		/* Get the default device MAC address directly from firmware */
-		memset(buf, 0, sizeof(buf));
-		bcm_mkiovar("cur_etheraddr", 0, 0, buf, sizeof(buf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
-			FALSE, 0)) < 0) {
-			DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
-			ret = BCME_NOTUP;
-			goto done;
-		}
-		/* Update public MAC address after reading from Firmware */
-		memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
-
-#ifdef GET_CUSTOM_MAC_ENABLE
-	}
-#endif /* GET_CUSTOM_MAC_ENABLE */
-
-	/* get a capabilities from firmware */
-	{
-		uint32 cap_buf_size = sizeof(dhd->fw_capabilities);
-		memset(dhd->fw_capabilities, 0, cap_buf_size);
-		bcm_mkiovar("cap", 0, 0, dhd->fw_capabilities, cap_buf_size - 1);
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, dhd->fw_capabilities,
-			(cap_buf_size - 1), FALSE, 0)) < 0)
-		{
-			DHD_ERROR(("%s: Get Capability failed (error=%d)\n",
-				__FUNCTION__, ret));
-			return 0;
-		}
-
-		memmove(&dhd->fw_capabilities[1], dhd->fw_capabilities, (cap_buf_size - 1));
-		dhd->fw_capabilities[0] = ' ';
-		dhd->fw_capabilities[cap_buf_size - 2] = ' ';
-		dhd->fw_capabilities[cap_buf_size - 1] = '\0';
-	}
-
-	if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) ||
-		(op_mode == DHD_FLAG_HOSTAP_MODE)) {
-#ifdef SET_RANDOM_MAC_SOFTAP
-		uint rand_mac;
-#endif /* SET_RANDOM_MAC_SOFTAP */
-		dhd->op_mode = DHD_FLAG_HOSTAP_MODE;
-#if defined(ARP_OFFLOAD_SUPPORT)
-			arpoe = 0;
-#endif
-#ifdef PKT_FILTER_SUPPORT
-			dhd_pkt_filter_enable = FALSE;
-#endif
-#ifdef SET_RANDOM_MAC_SOFTAP
-		SRANDOM32((uint)jiffies);
-		rand_mac = RANDOM32();
-		iovbuf[0] = (unsigned char)(vendor_oui >> 16) | 0x02;	/* local admin bit */
-		iovbuf[1] = (unsigned char)(vendor_oui >> 8);
-		iovbuf[2] = (unsigned char)vendor_oui;
-		iovbuf[3] = (unsigned char)(rand_mac & 0x0F) | 0xF0;
-		iovbuf[4] = (unsigned char)(rand_mac >> 8);
-		iovbuf[5] = (unsigned char)(rand_mac >> 16);
-
-		bcm_mkiovar("cur_etheraddr", (void *)iovbuf, ETHER_ADDR_LEN, buf, sizeof(buf));
-		ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
-		if (ret < 0) {
-			DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
-		} else
-			memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
-#endif /* SET_RANDOM_MAC_SOFTAP */
-#if !defined(AP) && defined(WL_CFG80211)
-		/* Turn off MPC in AP mode */
-		bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-			sizeof(iovbuf), TRUE, 0)) < 0) {
-			DHD_ERROR(("%s mpc for HostAPD failed  %d\n", __FUNCTION__, ret));
-		}
-#endif
-#ifdef USE_DYNAMIC_F2_BLKSIZE
-		dhdsdio_func_blocksize(dhd, 2, DYNAMIC_F2_BLKSIZE_FOR_NONLEGACY);
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
-#ifdef SUPPORT_AP_POWERSAVE
-		dhd_set_ap_powersave(dhd, 0, TRUE);
-#endif /* SUPPORT_AP_POWERSAVE */
-#ifdef SOFTAP_UAPSD_OFF
-		bcm_mkiovar("wme_apsd", (char *)&wme_apsd, 4, iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-			sizeof(iovbuf), TRUE, 0)) < 0) {
-			DHD_ERROR(("%s: set wme_apsd 0 fail (error=%d)\n",
-				__FUNCTION__, ret));
-		}
-#endif /* SOFTAP_UAPSD_OFF */
-	} else if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) ||
-		(op_mode == DHD_FLAG_MFG_MODE)) {
-#if defined(ARP_OFFLOAD_SUPPORT)
-		arpoe = 0;
-#endif /* ARP_OFFLOAD_SUPPORT */
-#ifdef PKT_FILTER_SUPPORT
-		dhd_pkt_filter_enable = FALSE;
-#endif /* PKT_FILTER_SUPPORT */
-		dhd->op_mode = DHD_FLAG_MFG_MODE;
-#ifdef USE_DYNAMIC_F2_BLKSIZE
-		dhdsdio_func_blocksize(dhd, 2, DYNAMIC_F2_BLKSIZE_FOR_NONLEGACY);
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
-		if (FW_SUPPORTED(dhd, rsdb)) {
-			rsdb_mode = 0;
-			bcm_mkiovar("rsdb_mode", (char *)&rsdb_mode, 4, iovbuf, sizeof(iovbuf));
-			if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
-				iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-				DHD_ERROR(("%s Disable rsdb_mode is failed ret= %d\n",
-					__FUNCTION__, ret));
-			}
-		}
-	} else {
-		uint32 concurrent_mode = 0;
-		if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_P2P_MODE) ||
-			(op_mode == DHD_FLAG_P2P_MODE)) {
-#if defined(ARP_OFFLOAD_SUPPORT)
-			arpoe = 0;
-#endif
-#ifdef PKT_FILTER_SUPPORT
-			dhd_pkt_filter_enable = FALSE;
-#endif
-			dhd->op_mode = DHD_FLAG_P2P_MODE;
-		} else if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_IBSS_MODE) ||
-			(op_mode == DHD_FLAG_IBSS_MODE)) {
-			dhd->op_mode = DHD_FLAG_IBSS_MODE;
-		} else
-			dhd->op_mode = DHD_FLAG_STA_MODE;
-#if !defined(AP) && defined(WLP2P)
-		if (dhd->op_mode != DHD_FLAG_IBSS_MODE &&
-			(concurrent_mode = dhd_get_concurrent_capabilites(dhd))) {
-#if defined(ARP_OFFLOAD_SUPPORT)
-			arpoe = 1;
-#endif
-			dhd->op_mode |= concurrent_mode;
-		}
-
-		/* Check if we are enabling p2p */
-		if (dhd->op_mode & DHD_FLAG_P2P_MODE) {
-			bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
-			if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
-				iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-				DHD_ERROR(("%s APSTA for P2P failed ret= %d\n", __FUNCTION__, ret));
-			}
-
-#if defined(SOFTAP_AND_GC)
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_AP,
-			(char *)&ap_mode, sizeof(ap_mode), TRUE, 0)) < 0) {
-				DHD_ERROR(("%s WLC_SET_AP failed %d\n", __FUNCTION__, ret));
-		}
-#endif
-			memcpy(&p2p_ea, &dhd->mac, ETHER_ADDR_LEN);
-			ETHER_SET_LOCALADDR(&p2p_ea);
-			bcm_mkiovar("p2p_da_override", (char *)&p2p_ea,
-				ETHER_ADDR_LEN, iovbuf, sizeof(iovbuf));
-			if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
-				iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-				DHD_ERROR(("%s p2p_da_override ret= %d\n", __FUNCTION__, ret));
-			} else {
-				DHD_INFO(("dhd_preinit_ioctls: p2p_da_override succeeded\n"));
-			}
-		}
-#else
-	(void)concurrent_mode;
-#endif 
-	}
-
-#ifdef RSDB_MODE_FROM_FILE
-	(void)dhd_rsdb_mode_from_file(dhd);
-#endif /* RSDB_MODE_FROM_FILE */
-
-#ifdef DISABLE_PRUNED_SCAN
-	if (FW_SUPPORTED(dhd, rsdb)) {
-		memset(iovbuf, 0, sizeof(iovbuf));
-		bcm_mkiovar("scan_features", (char *)&scan_features,
-			4, iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR,
-			iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {
-			DHD_ERROR(("%s get scan_features is failed ret=%d\n",
-				__FUNCTION__, ret));
-		} else {
-			memcpy(&scan_features, iovbuf, 4);
-			scan_features &= ~RSDB_SCAN_DOWNGRADED_CH_PRUNE_ROAM;
-			memset(iovbuf, 0, sizeof(iovbuf));
-			bcm_mkiovar("scan_features", (char *)&scan_features,
-				4, iovbuf, sizeof(iovbuf));
-			if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
-				iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-				DHD_ERROR(("%s set scan_features is failed ret=%d\n",
-					__FUNCTION__, ret));
-			}
-		}
-	}
-#endif /* DISABLE_PRUNED_SCAN */
-
-	DHD_ERROR(("Firmware up: op_mode=0x%04x, MAC="MACDBG"\n",
-		dhd->op_mode, MAC2STRDBG(dhd->mac.octet)));
-	#if defined(RXFRAME_THREAD) && defined(RXTHREAD_ONLYSTA)
-	if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE)
-		dhd->info->rxthread_enabled = FALSE;
-	else
-		dhd->info->rxthread_enabled = TRUE;
-	#endif
-	/* Set Country code  */
-	if (dhd->dhd_cspec.ccode[0] != 0) {
-		bcm_mkiovar("country", (char *)&dhd->dhd_cspec,
-			sizeof(wl_country_t), iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
-			DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
-	}
-
-
-	/* Set Listen Interval */
-	bcm_mkiovar("assoc_listen", (char *)&listen_interval, 4, iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
-		DHD_ERROR(("%s assoc_listen failed %d\n", __FUNCTION__, ret));
-
-#if defined(ROAM_ENABLE) || defined(DISABLE_BUILTIN_ROAM)
-#ifdef USE_WFA_CERT_CONF
-	if (sec_get_param_wfa_cert(dhd, SET_PARAM_ROAMOFF, &roamvar) == BCME_OK) {
-		DHD_ERROR(("%s: read roam_off param =%d\n", __FUNCTION__, roamvar));
-	}
-#endif /* USE_WFA_CERT_CONF */
-	/* Disable built-in roaming to allowed ext supplicant to take care of roaming */
-	bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */
-#if defined(ROAM_ENABLE)
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger,
-		sizeof(roam_trigger), TRUE, 0)) < 0)
-		DHD_ERROR(("%s: roam trigger set failed %d\n", __FUNCTION__, ret));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_SCAN_PERIOD, roam_scan_period,
-		sizeof(roam_scan_period), TRUE, 0)) < 0)
-		DHD_ERROR(("%s: roam scan period set failed %d\n", __FUNCTION__, ret));
-	if ((dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta,
-		sizeof(roam_delta), TRUE, 0)) < 0)
-		DHD_ERROR(("%s: roam delta set failed %d\n", __FUNCTION__, ret));
-	bcm_mkiovar("fullroamperiod", (char *)&roam_fullscan_period, 4, iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
-		DHD_ERROR(("%s: roam fullscan period set failed %d\n", __FUNCTION__, ret));
-#endif /* ROAM_ENABLE */
-
-#ifdef CUSTOM_EVENT_PM_WAKE
-	bcm_mkiovar("const_awake_thresh", (char *)&pm_awake_thresh, 4, iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s set const_awake_thresh failed %d\n", __FUNCTION__, ret));
-	}
-#endif /* CUSTOM_EVENT_PM_WAKE */
-#ifdef WLTDLS
-#ifdef ENABLE_TDLS_AUTO_MODE
-	/* by default TDLS on and auto mode on */
-	_dhd_tdls_enable(dhd, true, true, NULL);
-#else
-	/* by default TDLS on and auto mode off */
-	_dhd_tdls_enable(dhd, true, false, NULL);
-#endif /* ENABLE_TDLS_AUTO_MODE */
-#endif /* WLTDLS */
-
-#ifdef DHD_ENABLE_LPC
-	/* Set lpc 1 */
-	bcm_mkiovar("lpc", (char *)&lpc, 4, iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-		sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s Set lpc failed  %d\n", __FUNCTION__, ret));
-
-		if (ret == BCME_NOTDOWN) {
-			uint wl_down = 1;
-			ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN,
-				(char *)&wl_down, sizeof(wl_down), TRUE, 0);
-			DHD_ERROR(("%s lpc fail WL_DOWN : %d, lpc = %d\n", __FUNCTION__, ret, lpc));
-
-			bcm_mkiovar("lpc", (char *)&lpc, 4, iovbuf, sizeof(iovbuf));
-			ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-			DHD_ERROR(("%s Set lpc ret --> %d\n", __FUNCTION__, ret));
-		}
-	}
-#endif /* DHD_ENABLE_LPC */
-
-	/* Set PowerSave mode */
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
-
-#if defined(BCMSDIO)
-	/* Match Host and Dongle rx alignment */
-	bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-
-#if defined(CUSTOMER_HW2) && defined(USE_WL_CREDALL)
-	/* enable credall to reduce the chance of no bus credit happened. */
-	bcm_mkiovar("bus:credall", (char *)&credall, 4, iovbuf, sizeof(iovbuf));
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif
-
-#ifdef USE_WFA_CERT_CONF
-	if (sec_get_param_wfa_cert(dhd, SET_PARAM_BUS_TXGLOM_MODE, &glom) == BCME_OK) {
-		DHD_ERROR(("%s, read txglom param =%d\n", __FUNCTION__, glom));
-	}
-#endif /* USE_WFA_CERT_CONF */
-	if (glom != DEFAULT_GLOM_VALUE) {
-		DHD_INFO(("%s set glom=0x%X\n", __FUNCTION__, glom));
-		bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
-		dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-	}
-#endif /* defined(BCMSDIO) */
-
-	/* Setup timeout if Beacons are lost and roam is off to report link down */
-	bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-	/* Setup assoc_retry_max count to reconnect target AP in dongle */
-	bcm_mkiovar("assoc_retry_max", (char *)&retry_max, 4, iovbuf, sizeof(iovbuf));
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#if defined(AP) && !defined(WLP2P)
-	/* Turn off MPC in AP mode */
-	bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-	bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* defined(AP) && !defined(WLP2P) */
-
-#ifdef MIMO_ANT_SETTING
-	dhd_sel_ant_from_file(dhd);
-#endif /* MIMO_ANT_SETTING */
-
-#if defined(SOFTAP)
-	if (ap_fw_loaded == TRUE) {
-		dhd_wl_ioctl_cmd(dhd, WLC_SET_DTIMPRD, (char *)&dtim, sizeof(dtim), TRUE, 0);
-	}
-#endif 
-
-#if defined(KEEP_ALIVE)
-	{
-	/* Set Keep Alive : be sure to use FW with -keepalive */
-	int res;
-
-#if defined(SOFTAP)
-	if (ap_fw_loaded == FALSE)
-#endif 
-		if (!(dhd->op_mode &
-			(DHD_FLAG_HOSTAP_MODE | DHD_FLAG_MFG_MODE))) {
-			if ((res = dhd_keep_alive_onoff(dhd)) < 0)
-				DHD_ERROR(("%s set keeplive failed %d\n",
-				__FUNCTION__, res));
-		}
-	}
-#endif /* defined(KEEP_ALIVE) */
-
-#ifdef USE_WL_TXBF
-	bcm_mkiovar("txbf", (char *)&txbf, 4, iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-		sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s Set txbf returned (%d)\n", __FUNCTION__, ret));
-	}
-#endif /* USE_WL_TXBF */
-
-#ifdef USE_WFA_CERT_CONF
-#ifdef USE_WL_FRAMEBURST
-	 if (sec_get_param_wfa_cert(dhd, SET_PARAM_FRAMEBURST, &frameburst) == BCME_OK) {
-		DHD_ERROR(("%s, read frameburst param=%d\n", __FUNCTION__, frameburst));
-	 }
-#endif /* USE_WL_FRAMEBURST */
-#ifdef DISABLE_FRAMEBURST_VSDB
-	g_frameburst = frameburst;
-#endif /* DISABLE_FRAMEBURST_VSDB */
-#endif /* USE_WFA_CERT_CONF */
-#ifdef DISABLE_WL_FRAMEBURST_SOFTAP
-	/* Disable Framebursting for SofAP */
-	if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
-		frameburst = 0;
-	}
-#endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
-	/* Set frameburst to value */
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_FAKEFRAG, (char *)&frameburst,
-		sizeof(frameburst), TRUE, 0)) < 0) {
-		DHD_INFO(("%s frameburst not supported  %d\n", __FUNCTION__, ret));
-	}
-#if defined(CUSTOM_AMPDU_BA_WSIZE)
-	/* Set ampdu ba wsize to 64 or 16 */
-#ifdef CUSTOM_AMPDU_BA_WSIZE
-	ampdu_ba_wsize = CUSTOM_AMPDU_BA_WSIZE;
-#endif
-	if (ampdu_ba_wsize != 0) {
-		bcm_mkiovar("ampdu_ba_wsize", (char *)&ampdu_ba_wsize, 4, iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-			sizeof(iovbuf), TRUE, 0)) < 0) {
-			DHD_ERROR(("%s Set ampdu_ba_wsize to %d failed  %d\n",
-				__FUNCTION__, ampdu_ba_wsize, ret));
-		}
-	}
-#endif 
-
-	iov_buf = (char*)kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
-	if (iov_buf == NULL) {
-		DHD_ERROR(("failed to allocate %d bytes for iov_buf\n", WLC_IOCTL_SMLEN));
-		ret = BCME_NOMEM;
-		goto done;
-	}
-#ifdef ENABLE_TEMP_THROTTLING
-	if (dhd->op_mode & DHD_FLAG_STA_MODE) {
-		memset(&temp_control, 0, sizeof(temp_control));
-		temp_control.enable = 1;
-		temp_control.control_bit = TEMP_THROTTLE_CONTROL_BIT;
-		bcm_mkiovar("temp_throttle_control", (char *)&temp_control,
-				sizeof(wl_temp_control_t), iov_buf, WLC_IOCTL_SMLEN);
-		ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iov_buf, WLC_IOCTL_SMLEN, TRUE, 0);
-		if (ret < 0) {
-			DHD_ERROR(("%s Set temp_throttle_control to %d failed \n",
-				__FUNCTION__, ret));
-		}
-	}
-#endif /* ENABLE_TEMP_THROTTLING */
-#if defined(CUSTOM_AMPDU_MPDU)
-	ampdu_mpdu = CUSTOM_AMPDU_MPDU;
-	if (ampdu_mpdu != 0 && (ampdu_mpdu <= ampdu_ba_wsize)) {
-		bcm_mkiovar("ampdu_mpdu", (char *)&ampdu_mpdu, 4, iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-			sizeof(iovbuf), TRUE, 0)) < 0) {
-			DHD_ERROR(("%s Set ampdu_mpdu to %d failed  %d\n",
-				__FUNCTION__, CUSTOM_AMPDU_MPDU, ret));
-		}
-	}
-#endif /* CUSTOM_AMPDU_MPDU */
-
-#if defined(CUSTOM_AMPDU_RELEASE)
-	ampdu_release = CUSTOM_AMPDU_RELEASE;
-	if (ampdu_release != 0 && (ampdu_release <= ampdu_ba_wsize)) {
-		bcm_mkiovar("ampdu_release", (char *)&ampdu_release, 4, iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-			sizeof(iovbuf), TRUE, 0)) < 0) {
-			DHD_ERROR(("%s Set ampdu_release to %d failed  %d\n",
-				__FUNCTION__, CUSTOM_AMPDU_RELEASE, ret));
-		}
-	}
-#endif /* CUSTOM_AMPDU_RELEASE */
-
-#if defined(CUSTOM_AMSDU_AGGSF)
-	amsdu_aggsf = CUSTOM_AMSDU_AGGSF;
-	if (amsdu_aggsf != 0) {
-		bcm_mkiovar("amsdu_aggsf", (char *)&amsdu_aggsf, 4, iovbuf, sizeof(iovbuf));
-		ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-		if (ret < 0) {
-			DHD_ERROR(("%s Set amsdu_aggsf to %d failed %d\n",
-				__FUNCTION__, CUSTOM_AMSDU_AGGSF, ret));
-		}
-	}
-#endif /* CUSTOM_AMSDU_AGGSF */
-
-#ifdef CUSTOM_PSPRETEND_THR
-	/* Turn off MPC in AP mode */
-	bcm_mkiovar("pspretend_threshold", (char *)&pspretend_thr, 4,
-		iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-		sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s pspretend_threshold for HostAPD failed  %d\n",
-			__FUNCTION__, ret));
-	}
-#endif
-
-	bcm_mkiovar("buf_key_b4_m4", (char *)&buf_key_b4_m4, 4, iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
-		sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s buf_key_b4_m4 set failed %d\n", __FUNCTION__, ret));
-	}
-
-	/* Read event_msgs mask */
-	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
-	if ((ret  = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {
-		DHD_ERROR(("%s read Event mask failed %d\n", __FUNCTION__, ret));
-		goto done;
-	}
-	bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
-
-	/* Setup event_msgs */
-	setbit(eventmask, WLC_E_SET_SSID);
-	setbit(eventmask, WLC_E_PRUNE);
-	setbit(eventmask, WLC_E_AUTH);
-	setbit(eventmask, WLC_E_AUTH_IND);
-	setbit(eventmask, WLC_E_ASSOC);
-	setbit(eventmask, WLC_E_REASSOC);
-	setbit(eventmask, WLC_E_REASSOC_IND);
-	if (!(dhd->op_mode & DHD_FLAG_IBSS_MODE))
-		setbit(eventmask, WLC_E_DEAUTH);
-	setbit(eventmask, WLC_E_DEAUTH_IND);
-	setbit(eventmask, WLC_E_DISASSOC_IND);
-	setbit(eventmask, WLC_E_DISASSOC);
-	setbit(eventmask, WLC_E_JOIN);
-	setbit(eventmask, WLC_E_START);
-	setbit(eventmask, WLC_E_ASSOC_IND);
-	setbit(eventmask, WLC_E_PSK_SUP);
-	setbit(eventmask, WLC_E_LINK);
-	setbit(eventmask, WLC_E_MIC_ERROR);
-	setbit(eventmask, WLC_E_ASSOC_REQ_IE);
-	setbit(eventmask, WLC_E_ASSOC_RESP_IE);
-#ifndef WL_CFG80211
-	setbit(eventmask, WLC_E_PMKID_CACHE);
-	setbit(eventmask, WLC_E_TXFAIL);
-#endif
-	setbit(eventmask, WLC_E_JOIN_START);
-	setbit(eventmask, WLC_E_SCAN_COMPLETE);
-#ifdef DHD_DEBUG
-	setbit(eventmask, WLC_E_SCAN_CONFIRM_IND);
-#endif
-#ifdef WLMEDIA_HTSF
-	setbit(eventmask, WLC_E_HTSFSYNC);
-#endif /* WLMEDIA_HTSF */
-#ifdef PNO_SUPPORT
-	setbit(eventmask, WLC_E_PFN_NET_FOUND);
-	setbit(eventmask, WLC_E_PFN_BEST_BATCHING);
-	setbit(eventmask, WLC_E_PFN_BSSID_NET_FOUND);
-	setbit(eventmask, WLC_E_PFN_BSSID_NET_LOST);
-#endif /* PNO_SUPPORT */
-	/* enable dongle roaming event */
-	setbit(eventmask, WLC_E_ROAM);
-	setbit(eventmask, WLC_E_BSSID);
-#ifdef WLTDLS
-	setbit(eventmask, WLC_E_TDLS_PEER_EVENT);
-#endif /* WLTDLS */
-#ifdef WL_CFG80211
-	setbit(eventmask, WLC_E_ESCAN_RESULT);
-	setbit(eventmask, WLC_E_AP_STARTED);
-	if (dhd->op_mode & DHD_FLAG_P2P_MODE) {
-		setbit(eventmask, WLC_E_ACTION_FRAME_RX);
-		setbit(eventmask, WLC_E_P2P_DISC_LISTEN_COMPLETE);
-	}
-#endif /* WL_CFG80211 */
-
-#if defined(SHOW_LOGTRACE) && defined(LOGTRACE_FROM_FILE)
-	if (dhd_logtrace_from_file(dhd)) {
-		setbit(eventmask, WLC_E_TRACE);
-	} else {
-		clrbit(eventmask, WLC_E_TRACE);
-	}
-#elif defined(SHOW_LOGTRACE)
-	setbit(eventmask, WLC_E_TRACE);
-#else
-	clrbit(eventmask, WLC_E_TRACE);
-#endif /* defined(SHOW_LOGTRACE) && defined(LOGTRACE_FROM_FILE) */
-
-	setbit(eventmask, WLC_E_CSA_COMPLETE_IND);
-#ifdef DHD_LOSSLESS_ROAMING
-	setbit(eventmask, WLC_E_ROAM_PREP);
-#endif
-#ifdef CUSTOM_EVENT_PM_WAKE
-	setbit(eventmask, WLC_E_EXCESS_PM_WAKE_EVENT);
-#endif /* CUSTOM_EVENT_PM_WAKE */
-#if defined(PCIE_FULL_DONGLE) && defined(DHD_LOSSLESS_ROAMING)
-	dhd_update_flow_prio_map(dhd, DHD_FLOW_PRIO_LLR_MAP);
-#endif /* defined(PCIE_FULL_DONGLE) && defined(DHD_LOSSLESS_ROAMING) */
-
-	/* Write updated Event mask */
-	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s Set Event mask failed %d\n", __FUNCTION__, ret));
-		goto done;
-	}
-
-	/* make up event mask ext message iovar for event larger than 128 */
-	msglen = ROUNDUP(WLC_E_LAST, NBBY)/NBBY + EVENTMSGS_EXT_STRUCT_SIZE;
-	eventmask_msg = (eventmsgs_ext_t*)kmalloc(msglen, GFP_KERNEL);
-	if (eventmask_msg == NULL) {
-		DHD_ERROR(("failed to allocate %d bytes for event_msg_ext\n", msglen));
-		ret = BCME_NOMEM;
-		goto done;
-	}
-	bzero(eventmask_msg, msglen);
-	eventmask_msg->ver = EVENTMSGS_VER;
-	eventmask_msg->len = ROUNDUP(WLC_E_LAST, NBBY)/NBBY;
-
-	/* Read event_msgs_ext mask */
-	bcm_mkiovar("event_msgs_ext", (char *)eventmask_msg, msglen, iov_buf, WLC_IOCTL_SMLEN);
-	ret2  = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iov_buf, WLC_IOCTL_SMLEN, FALSE, 0);
-	if (ret2 == 0) { /* event_msgs_ext must be supported */
-		bcopy(iov_buf, eventmask_msg, msglen);
-#ifdef GSCAN_SUPPORT
-		setbit(eventmask_msg->mask, WLC_E_PFN_GSCAN_FULL_RESULT);
-		setbit(eventmask_msg->mask, WLC_E_PFN_SCAN_COMPLETE);
-		setbit(eventmask_msg->mask, WLC_E_PFN_SWC);
-#endif /* GSCAN_SUPPORT */
-#ifdef BT_WIFI_HANDOVER
-		setbit(eventmask_msg->mask, WLC_E_BT_WIFI_HANDOVER_REQ);
-#endif /* BT_WIFI_HANDOVER */
-
-		/* Write updated Event mask */
-		eventmask_msg->ver = EVENTMSGS_VER;
-		eventmask_msg->command = EVENTMSGS_SET_MASK;
-		eventmask_msg->len = ROUNDUP(WLC_E_LAST, NBBY)/NBBY;
-		bcm_mkiovar("event_msgs_ext", (char *)eventmask_msg,
-			msglen, iov_buf, WLC_IOCTL_SMLEN);
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
-			iov_buf, WLC_IOCTL_SMLEN, TRUE, 0)) < 0) {
-			DHD_ERROR(("%s write event mask ext failed %d\n", __FUNCTION__, ret));
-			goto done;
-		}
-	} else if (ret2 == BCME_UNSUPPORTED || ret2 == BCME_VERSION) {
-		/* Skip for BCME_UNSUPPORTED or BCME_VERSION */
-		DHD_ERROR(("%s event_msgs_ext not support or version mismatch %d\n",
-			__FUNCTION__, ret2));
-	} else {
-		DHD_ERROR(("%s read event mask ext failed %d\n", __FUNCTION__, ret2));
-		ret = ret2;
-		goto done;
-	}
-
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time,
-		sizeof(scan_assoc_time), TRUE, 0);
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
-		sizeof(scan_unassoc_time), TRUE, 0);
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_PASSIVE_TIME, (char *)&scan_passive_time,
-		sizeof(scan_passive_time), TRUE, 0);
-
-#ifdef ARP_OFFLOAD_SUPPORT
-	/* Set and enable ARP offload feature for STA only  */
-#if defined(SOFTAP)
-	if (arpoe && !ap_fw_loaded) {
-#else
-	if (arpoe) {
-#endif 
-		dhd_arp_offload_enable(dhd, TRUE);
-		dhd_arp_offload_set(dhd, dhd_arp_mode);
-	} else {
-		dhd_arp_offload_enable(dhd, FALSE);
-		dhd_arp_offload_set(dhd, 0);
-	}
-	dhd_arp_enable = arpoe;
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-#ifdef PKT_FILTER_SUPPORT
-	/* Setup default defintions for pktfilter , enable in suspend */
-	dhd->pktfilter_count = 6;
-	dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = NULL;
-	dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = NULL;
-	dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL;
-	/* apply APP pktfilter */
-	dhd->pktfilter[DHD_ARP_FILTER_NUM] = "105 0 0 12 0xFFFF 0x0806";
-
-	/* Setup filter to allow only unicast */
-	dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0x01 0x00";
-
-	/* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */
-	dhd->pktfilter[DHD_MDNS_FILTER_NUM] = NULL;
-
-#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER
-	dhd->pktfilter_count = 4;
-	/* Setup filter to block broadcast and NAT Keepalive packets */
-	/* discard all broadcast packets */
-	dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0xffffff 0xffffff";
-	/* discard NAT Keepalive packets */
-	dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = "102 0 0 36 0xffffffff 0x11940009";
-	/* discard NAT Keepalive packets */
-	dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = "104 0 0 38 0xffffffff 0x11940009";
-	dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL;
-#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */
-
-#if defined(SOFTAP)
-	if (ap_fw_loaded) {
-		dhd_enable_packet_filter(0, dhd);
-	}
-#endif /* defined(SOFTAP) */
-	dhd_set_packet_filter(dhd);
-#endif /* PKT_FILTER_SUPPORT */
-#ifdef DISABLE_11N
-	bcm_mkiovar("nmode", (char *)&nmode, 4, iovbuf, sizeof(iovbuf));
-	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
-		DHD_ERROR(("%s wl nmode 0 failed %d\n", __FUNCTION__, ret));
-#endif /* DISABLE_11N */
-
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
-	bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, 4, iovbuf, sizeof(iovbuf));
-	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
-	/* query for 'ver' to get version info from firmware */
-	memset(buf, 0, sizeof(buf));
-	ptr = buf;
-	bcm_mkiovar("ver", (char *)&buf, 4, buf, sizeof(buf));
-	if ((ret  = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0)
-		DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
-	else {
-		bcmstrtok(&ptr, "\n", 0);
-		/* Print fw version info */
-		DHD_ERROR(("Firmware version = %s\n", buf));
-		strncpy(fw_version, buf, FW_VER_STR_LEN);
-#if defined(BCMSDIO)
-		dhd_set_version_info(dhd, buf);
-#endif /* defined(BCMSDIO) */
-#ifdef WRITE_WLANINFO
-		sec_save_wlinfo(buf, EPI_VERSION_STR, dhd->info->nv_path);
-#endif /* WRITE_WLANINFO */
-	}
-
-#if defined(BCMSDIO)
-	dhd_txglom_enable(dhd, TRUE);
-#endif /* defined(BCMSDIO) */
-
-#if defined(BCMSDIO)
-#ifdef PROP_TXSTATUS
-	if (disable_proptx ||
-#ifdef PROP_TXSTATUS_VSDB
-		/* enable WLFC only if the firmware is VSDB when it is in STA mode */
-		(dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
-		 dhd->op_mode != DHD_FLAG_IBSS_MODE) ||
-#endif /* PROP_TXSTATUS_VSDB */
-		FALSE) {
-		wlfc_enable = FALSE;
-	}
-
-#ifdef USE_WFA_CERT_CONF
-	if (sec_get_param_wfa_cert(dhd, SET_PARAM_PROPTX, &proptx) == BCME_OK) {
-		DHD_ERROR(("%s , read proptx param=%d\n", __FUNCTION__, proptx));
-		wlfc_enable = proptx;
-	}
-#endif /* USE_WFA_CERT_CONF */
-
-#ifndef DISABLE_11N
-	bcm_mkiovar("ampdu_hostreorder", (char *)&hostreorder, 4, iovbuf, sizeof(iovbuf));
-	if ((ret2 = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
-		DHD_ERROR(("%s wl ampdu_hostreorder failed %d\n", __FUNCTION__, ret2));
-		if (ret2 != BCME_UNSUPPORTED)
-			ret = ret2;
-
-		if (ret == BCME_NOTDOWN) {
-			uint wl_down = 1;
-			ret2 = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, (char *)&wl_down,
-				sizeof(wl_down), TRUE, 0);
-			DHD_ERROR(("%s ampdu_hostreorder fail WL_DOWN : %d, hostreorder :%d\n",
-				__FUNCTION__, ret2, hostreorder));
-
-			bcm_mkiovar("ampdu_hostreorder", (char *)&hostreorder, 4,
-				iovbuf, sizeof(iovbuf));
-			ret2 = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-			DHD_ERROR(("%s wl ampdu_hostreorder. ret --> %d\n", __FUNCTION__, ret2));
-			if (ret2 != BCME_UNSUPPORTED)
-					ret = ret2;
-		}
-		if (ret2 != BCME_OK)
-			hostreorder = 0;
-	}
-#endif /* DISABLE_11N */
-
-
-	if (wlfc_enable)
-		dhd_wlfc_init(dhd);
-#ifndef DISABLE_11N
-	else if (hostreorder)
-		dhd_wlfc_hostreorder_init(dhd);
-#endif /* DISABLE_11N */
-
-#endif /* PROP_TXSTATUS */
-#endif /* BCMSDIO || BCMBUS */
-#ifdef PCIE_FULL_DONGLE
-	/* For FD we need all the packets at DHD to handle intra-BSS forwarding */
-	if (FW_SUPPORTED(dhd, ap)) {
-		wl_ap_isolate = AP_ISOLATE_SENDUP_ALL;
-		bcm_mkiovar("ap_isolate", (char *)&wl_ap_isolate, 4, iovbuf, sizeof(iovbuf));
-		if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
-			DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
-	}
-#endif /* PCIE_FULL_DONGLE */
-#ifdef PNO_SUPPORT
-	if (!dhd->pno_state) {
-		dhd_pno_init(dhd);
-	}
-#endif
-#ifdef WL11U
-	dhd_interworking_enable(dhd);
-#endif /* WL11U */
-
-#ifdef SUPPORT_SENSORHUB
-	bcm_mkiovar("shub", (char *)&shub_enable, 4, iovbuf, sizeof(iovbuf));
-	if ((dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf),
-		FALSE, 0)) < 0) {
-		DHD_ERROR(("%s failed to get shub hub enable information %d\n",
-			__FUNCTION__, ret));
-		dhd->info->shub_enable = 0;
-	} else {
-		memcpy(&shub_enable, iovbuf, sizeof(uint32));
-		dhd->info->shub_enable = shub_enable;
-		DHD_ERROR(("%s: checking sensorhub enable %d\n",
-			__FUNCTION__, dhd->info->shub_enable));
-	}
-#endif /* SUPPORT_SENSORHUB */
-done:
-
-	if (eventmask_msg)
-		kfree(eventmask_msg);
-	if (iov_buf)
-		kfree(iov_buf);
-
-	return ret;
-}
-
-
-int
-dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set)
-{
-	char buf[strlen(name) + 1 + cmd_len];
-	int len = sizeof(buf);
-	wl_ioctl_t ioc;
-	int ret;
-
-	len = bcm_mkiovar(name, cmd_buf, cmd_len, buf, len);
-
-	memset(&ioc, 0, sizeof(ioc));
-
-	ioc.cmd = set? WLC_SET_VAR : WLC_GET_VAR;
-	ioc.buf = buf;
-	ioc.len = len;
-	ioc.set = set;
-
-	ret = dhd_wl_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len);
-	if (!set && ret >= 0)
-		memcpy(cmd_buf, buf, cmd_len);
-
-	return ret;
-}
-
-int dhd_change_mtu(dhd_pub_t *dhdp, int new_mtu, int ifidx)
-{
-	struct dhd_info *dhd = dhdp->info;
-	struct net_device *dev = NULL;
-
-	ASSERT(dhd && dhd->iflist[ifidx]);
-	dev = dhd->iflist[ifidx]->net;
-	ASSERT(dev);
-
-	if (netif_running(dev)) {
-		DHD_ERROR(("%s: Must be down to change its MTU", dev->name));
-		return BCME_NOTDOWN;
-	}
-
-#define DHD_MIN_MTU 1500
-#define DHD_MAX_MTU 1752
-
-	if ((new_mtu < DHD_MIN_MTU) || (new_mtu > DHD_MAX_MTU)) {
-		DHD_ERROR(("%s: MTU size %d is invalid.\n", __FUNCTION__, new_mtu));
-		return BCME_BADARG;
-	}
-
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-#ifdef ARP_OFFLOAD_SUPPORT
-/* add or remove AOE host ip(s) (up to 8 IPs on the interface)  */
-void
-aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx)
-{
-	u32 ipv4_buf[MAX_IPV4_ENTRIES]; /* temp save for AOE host_ip table */
-	int i;
-	int ret;
-
-	bzero(ipv4_buf, sizeof(ipv4_buf));
-
-	/* display what we've got */
-	ret = dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx);
-	DHD_ARPOE(("%s: hostip table read from Dongle:\n", __FUNCTION__));
-#ifdef AOE_DBG
-	dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */
-#endif
-	/* now we saved hoste_ip table, clr it in the dongle AOE */
-	dhd_aoe_hostip_clr(dhd_pub, idx);
-
-	if (ret) {
-		DHD_ERROR(("%s failed\n", __FUNCTION__));
-		return;
-	}
-
-	for (i = 0; i < MAX_IPV4_ENTRIES; i++) {
-		if (add && (ipv4_buf[i] == 0)) {
-				ipv4_buf[i] = ipa;
-				add = FALSE; /* added ipa to local table  */
-				DHD_ARPOE(("%s: Saved new IP in temp arp_hostip[%d]\n",
-				__FUNCTION__, i));
-		} else if (ipv4_buf[i] == ipa) {
-			ipv4_buf[i]	= 0;
-			DHD_ARPOE(("%s: removed IP:%x from temp table %d\n",
-				__FUNCTION__, ipa, i));
-		}
-
-		if (ipv4_buf[i] != 0) {
-			/* add back host_ip entries from our local cache */
-			dhd_arp_offload_add_ip(dhd_pub, ipv4_buf[i], idx);
-			DHD_ARPOE(("%s: added IP:%x to dongle arp_hostip[%d]\n\n",
-				__FUNCTION__, ipv4_buf[i], i));
-		}
-	}
-#ifdef AOE_DBG
-	/* see the resulting hostip table */
-	dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx);
-	DHD_ARPOE(("%s: read back arp_hostip table:\n", __FUNCTION__));
-	dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */
-#endif
-}
-
-/*
- * Notification mechanism from kernel to our driver. This function is called by the Linux kernel
- * whenever there is an event related to an IP address.
- * ptr : kernel provided pointer to IP address that has changed
- */
-static int dhd_inetaddr_notifier_call(struct notifier_block *this,
-	unsigned long event,
-	void *ptr)
-{
-	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
-
-	dhd_info_t *dhd;
-	dhd_pub_t *dhd_pub;
-	int idx;
-
-	if (!dhd_arp_enable)
-		return NOTIFY_DONE;
-	if (!ifa || !(ifa->ifa_dev->dev))
-		return NOTIFY_DONE;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
-	/* Filter notifications meant for non Broadcom devices */
-	if ((ifa->ifa_dev->dev->netdev_ops != &dhd_ops_pri) &&
-	    (ifa->ifa_dev->dev->netdev_ops != &dhd_ops_virt)) {
-#if defined(WL_ENABLE_P2P_IF)
-		if (!wl_cfgp2p_is_ifops(ifa->ifa_dev->dev->netdev_ops))
-#endif /* WL_ENABLE_P2P_IF */
-			return NOTIFY_DONE;
-	}
-#endif /* LINUX_VERSION_CODE */
-
-	dhd = DHD_DEV_INFO(ifa->ifa_dev->dev);
-	if (!dhd)
-		return NOTIFY_DONE;
-
-	dhd_pub = &dhd->pub;
-
-	if (dhd_pub->arp_version == 1) {
-		idx = 0;
-	} else {
-		for (idx = 0; idx < DHD_MAX_IFS; idx++) {
-			if (dhd->iflist[idx] && dhd->iflist[idx]->net == ifa->ifa_dev->dev)
-			break;
-		}
-		if (idx < DHD_MAX_IFS) {
-			DHD_TRACE(("ifidx : %p %s %d\n", dhd->iflist[idx]->net,
-				dhd->iflist[idx]->name, dhd->iflist[idx]->idx));
-		} else {
-			DHD_ERROR(("Cannot find ifidx for(%s) set to 0\n", ifa->ifa_label));
-			idx = 0;
-		}
-	}
-
-	switch (event) {
-		case NETDEV_UP:
-			DHD_ARPOE(("%s: [%s] Up IP: 0x%x\n",
-				__FUNCTION__, ifa->ifa_label, ifa->ifa_address));
-
-			if (dhd->pub.busstate != DHD_BUS_DATA) {
-				DHD_ERROR(("%s: bus not ready, exit\n", __FUNCTION__));
-				if (dhd->pend_ipaddr) {
-					DHD_ERROR(("%s: overwrite pending ipaddr: 0x%x\n",
-						__FUNCTION__, dhd->pend_ipaddr));
-				}
-				dhd->pend_ipaddr = ifa->ifa_address;
-				break;
-			}
-
-#ifdef AOE_IP_ALIAS_SUPPORT
-			DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n",
-				__FUNCTION__));
-			aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE, idx);
-#endif /* AOE_IP_ALIAS_SUPPORT */
-			break;
-
-		case NETDEV_DOWN:
-			DHD_ARPOE(("%s: [%s] Down IP: 0x%x\n",
-				__FUNCTION__, ifa->ifa_label, ifa->ifa_address));
-			dhd->pend_ipaddr = 0;
-#ifdef AOE_IP_ALIAS_SUPPORT
-			DHD_ARPOE(("%s:interface is down, AOE clr all for this if\n",
-				__FUNCTION__));
-			aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE, idx);
-#else
-			dhd_aoe_hostip_clr(&dhd->pub, idx);
-			dhd_aoe_arp_clr(&dhd->pub, idx);
-#endif /* AOE_IP_ALIAS_SUPPORT */
-			break;
-
-		default:
-			DHD_ARPOE(("%s: do noting for [%s] Event: %lu\n",
-				__func__, ifa->ifa_label, event));
-			break;
-	}
-	return NOTIFY_DONE;
-}
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT)
-/* Neighbor Discovery Offload: defered handler */
-static void
-dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event)
-{
-	struct ipv6_work_info_t *ndo_work = (struct ipv6_work_info_t *)event_data;
-	dhd_pub_t	*pub = &((dhd_info_t *)dhd_info)->pub;
-	int		ret;
-
-	if (event != DHD_WQ_WORK_IPV6_NDO) {
-		DHD_ERROR(("%s: unexpected event \n", __FUNCTION__));
-		return;
-	}
-
-	if (!ndo_work) {
-		DHD_ERROR(("%s: ipv6 work info is not initialized \n", __FUNCTION__));
-		return;
-	}
-
-	if (!pub) {
-		DHD_ERROR(("%s: dhd pub is not initialized \n", __FUNCTION__));
-		return;
-	}
-
-	if (ndo_work->if_idx) {
-		DHD_ERROR(("%s: idx %d \n", __FUNCTION__, ndo_work->if_idx));
-		return;
-	}
-
-	switch (ndo_work->event) {
-		case NETDEV_UP:
-			DHD_TRACE(("%s: Enable NDO and add ipv6 into table \n ", __FUNCTION__));
-			ret = dhd_ndo_enable(pub, TRUE);
-			if (ret < 0) {
-				DHD_ERROR(("%s: Enabling NDO Failed %d\n", __FUNCTION__, ret));
-			}
-
-			ret = dhd_ndo_add_ip(pub, &ndo_work->ipv6_addr[0], ndo_work->if_idx);
-			if (ret < 0) {
-				DHD_ERROR(("%s: Adding host ip for NDO failed %d\n",
-					__FUNCTION__, ret));
-			}
-			break;
-		case NETDEV_DOWN:
-			DHD_TRACE(("%s: clear ipv6 table \n", __FUNCTION__));
-			ret = dhd_ndo_remove_ip(pub, ndo_work->if_idx);
-			if (ret < 0) {
-				DHD_ERROR(("%s: Removing host ip for NDO failed %d\n",
-					__FUNCTION__, ret));
-				goto done;
-			}
-
-			ret = dhd_ndo_enable(pub, FALSE);
-			if (ret < 0) {
-				DHD_ERROR(("%s: disabling NDO Failed %d\n", __FUNCTION__, ret));
-				goto done;
-			}
-			break;
-		default:
-			DHD_ERROR(("%s: unknown notifier event \n", __FUNCTION__));
-			break;
-	}
-done:
-	/* free ndo_work. alloced while scheduling the work */
-	kfree(ndo_work);
-
-	return;
-}
-
-/*
- * Neighbor Discovery Offload: Called when an interface
- * is assigned with ipv6 address.
- * Handles only primary interface
- */
-static int dhd_inet6addr_notifier_call(struct notifier_block *this,
-	unsigned long event,
-	void *ptr)
-{
-	dhd_info_t *dhd;
-	dhd_pub_t *dhd_pub;
-	struct inet6_ifaddr *inet6_ifa = ptr;
-	struct in6_addr *ipv6_addr = &inet6_ifa->addr;
-	struct ipv6_work_info_t *ndo_info;
-	int idx = 0; /* REVISIT */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
-	/* Filter notifications meant for non Broadcom devices */
-	if (inet6_ifa->idev->dev->netdev_ops != &dhd_ops_pri) {
-			return NOTIFY_DONE;
-	}
-#endif /* LINUX_VERSION_CODE */
-
-	dhd = DHD_DEV_INFO(inet6_ifa->idev->dev);
-	if (!dhd)
-		return NOTIFY_DONE;
-
-	if (dhd->iflist[idx] && dhd->iflist[idx]->net != inet6_ifa->idev->dev)
-		return NOTIFY_DONE;
-	dhd_pub = &dhd->pub;
-
-	if (!FW_SUPPORTED(dhd_pub, ndoe))
-		return NOTIFY_DONE;
-
-	ndo_info = (struct ipv6_work_info_t *)kzalloc(sizeof(struct ipv6_work_info_t), GFP_ATOMIC);
-	if (!ndo_info) {
-		DHD_ERROR(("%s: ipv6 work alloc failed\n", __FUNCTION__));
-		return NOTIFY_DONE;
-	}
-
-	ndo_info->event = event;
-	ndo_info->if_idx = idx;
-	memcpy(&ndo_info->ipv6_addr[0], ipv6_addr, IPV6_ADDR_LEN);
-
-	/* defer the work to thread as it may block kernel */
-	dhd_deferred_schedule_work(dhd->dhd_deferred_wq, (void *)ndo_info, DHD_WQ_WORK_IPV6_NDO,
-		dhd_inet6_work_handler, DHD_WORK_PRIORITY_LOW);
-	return NOTIFY_DONE;
-}
-#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */
-
-int
-dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock)
-{
-	dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
-	dhd_if_t *ifp;
-	struct net_device *net = NULL;
-	int err = 0;
-	uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 };
-
-	DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
-
-	ASSERT(dhd && dhd->iflist[ifidx]);
-	ifp = dhd->iflist[ifidx];
-	net = ifp->net;
-	ASSERT(net && (ifp->idx == ifidx));
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
-	ASSERT(!net->open);
-	net->get_stats = dhd_get_stats;
-	net->do_ioctl = dhd_ioctl_entry;
-	net->hard_start_xmit = dhd_start_xmit;
-	net->set_mac_address = dhd_set_mac_address;
-	net->set_multicast_list = dhd_set_multicast_list;
-	net->open = net->stop = NULL;
-#else
-	ASSERT(!net->netdev_ops);
-	net->netdev_ops = &dhd_ops_virt;
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
-
-	/* Ok, link into the network layer... */
-	if (ifidx == 0) {
-		/*
-		 * device functions for the primary interface only
-		 */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
-		net->open = dhd_open;
-		net->stop = dhd_stop;
-#else
-		net->netdev_ops = &dhd_ops_pri;
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
-		if (!ETHER_ISNULLADDR(dhd->pub.mac.octet))
-			memcpy(temp_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN);
-	} else {
-		/*
-		 * We have to use the primary MAC for virtual interfaces
-		 */
-		memcpy(temp_addr, ifp->mac_addr, ETHER_ADDR_LEN);
-		/*
-		 * Android sets the locally administered bit to indicate that this is a
-		 * portable hotspot.  This will not work in simultaneous AP/STA mode,
-		 * nor with P2P.  Need to set the Donlge's MAC address, and then use that.
-		 */
-		if (!memcmp(temp_addr, dhd->iflist[0]->mac_addr,
-			ETHER_ADDR_LEN)) {
-			DHD_ERROR(("%s interface [%s]: set locally administered bit in MAC\n",
-			__func__, net->name));
-			temp_addr[0] |= 0x02;
-		}
-	}
-
-	net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
-	net->ethtool_ops = &dhd_ethtool_ops;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
-
-#if defined(WL_WIRELESS_EXT)
-#if WIRELESS_EXT < 19
-	net->get_wireless_stats = dhd_get_wireless_stats;
-#endif /* WIRELESS_EXT < 19 */
-#if WIRELESS_EXT > 12
-	net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def;
-#endif /* WIRELESS_EXT > 12 */
-#endif /* defined(WL_WIRELESS_EXT) */
-
-	dhd->pub.rxsz = DBUS_RX_BUFFER_SIZE_DHD(net);
-
-	memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
-
-	if (ifidx == 0)
-		printf("%s\n", dhd_version);
-
-	if (need_rtnl_lock)
-		err = register_netdev(net);
-	else
-		err = register_netdevice(net);
-
-	if (err != 0) {
-		DHD_ERROR(("couldn't register the net device [%s], err %d\n", net->name, err));
-		goto fail;
-	}
-
-
-
-	printf("Register interface [%s]  MAC: "MACDBG"\n\n", net->name,
-#if defined(CUSTOMER_HW4_DEBUG)
-		MAC2STRDBG(dhd->pub.mac.octet));
-#else
-		MAC2STRDBG(net->dev_addr));
-#endif /* CUSTOMER_HW4_DEBUG */
-
-#if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211)
-		wl_iw_iscan_set_scan_broadcast_prep(net, 1);
-#endif
-
-#if (defined(BCMPCIE) || (defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= \
-	KERNEL_VERSION(2, 6, 27))))
-	if (ifidx == 0) {
-#ifdef BCMLXSDMMC
-		up(&dhd_registration_sem);
-#endif /* BCMLXSDMMC */
-		if (!dhd_download_fw_on_driverload) {
-#ifdef WL_CFG80211
-			wl_terminate_event_handler();
-#endif /* WL_CFG80211 */
-#if defined(DHD_LB) && defined(DHD_LB_RXP)
-			__skb_queue_purge(&dhd->rx_pend_queue);
-#endif /* DHD_LB && DHD_LB_RXP */
-#if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS)
-			dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF);
-#endif /* BCMPCIE && DHDTCPACK_SUPPRESS */
-			dhd_net_bus_devreset(net, TRUE);
-#ifdef BCMLXSDMMC
-			dhd_net_bus_suspend(net);
-#endif /* BCMLXSDMMC */
-			wifi_platform_set_power(dhdp->info->adapter, FALSE, WIFI_TURNOFF_DELAY);
-		}
-	}
-#endif /* OEM_ANDROID && (BCMPCIE || (BCMLXSDMMC && KERNEL_VERSION >= 2.6.27)) */
-	return 0;
-
-fail:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
-	net->open = NULL;
-#else
-	net->netdev_ops = NULL;
-#endif
-	return err;
-}
-
-void
-dhd_bus_detach(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (dhdp) {
-		dhd = (dhd_info_t *)dhdp->info;
-		if (dhd) {
-
-			/*
-			 * In case of Android cfg80211 driver, the bus is down in dhd_stop,
-			 *  calling stop again will cuase SD read/write errors.
-			 */
-			if (dhd->pub.busstate != DHD_BUS_DOWN) {
-				/* Stop the protocol module */
-				dhd_prot_stop(&dhd->pub);
-
-				/* Stop the bus module */
-				dhd_bus_stop(dhd->pub.bus, TRUE);
-			}
-
-#if defined(OOB_INTR_ONLY) || defined(BCMPCIE_OOB_HOST_WAKE)
-			dhd_bus_oob_intr_unregister(dhdp);
-#endif 
-		}
-	}
-}
-
-
-void dhd_detach(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd;
-	unsigned long flags;
-	int timer_valid = FALSE;
-	struct net_device *dev;
-
-	if (!dhdp)
-		return;
-
-	dhd = (dhd_info_t *)dhdp->info;
-	if (!dhd)
-		return;
-
-	dev = dhd->iflist[0]->net;
-
-	if (dev) {
-		rtnl_lock();
-		if (dev->flags & IFF_UP) {
-			/* If IFF_UP is still up, it indicates that
-			 * "ifconfig wlan0 down" hasn't been called.
-			 * So invoke dev_close explicitly here to
-			 * bring down the interface.
-			 */
-			DHD_TRACE(("IFF_UP flag is up. Enforcing dev_close from detach \n"));
-			dev_close(dev);
-		}
-		rtnl_unlock();
-	}
-
-	DHD_TRACE(("%s: Enter state 0x%x\n", __FUNCTION__, dhd->dhd_state));
-
-	dhd->pub.up = 0;
-	if (!(dhd->dhd_state & DHD_ATTACH_STATE_DONE)) {
-		/* Give sufficient time for threads to start running in case
-		 * dhd_attach() has failed
-		 */
-		OSL_SLEEP(100);
-	}
-
-#if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW)
-#endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */
-
-#ifdef PROP_TXSTATUS
-#ifdef DHD_WLFC_THREAD
-	if (dhd->pub.wlfc_thread) {
-		kthread_stop(dhd->pub.wlfc_thread);
-		dhdp->wlfc_thread_go = TRUE;
-		wake_up_interruptible(&dhdp->wlfc_wqhead);
-	}
-	dhd->pub.wlfc_thread = NULL;
-#endif /* DHD_WLFC_THREAD */
-#endif /* PROP_TXSTATUS */
-
-	if (dhd->dhd_state & DHD_ATTACH_STATE_PROT_ATTACH) {
-
-		dhd_bus_detach(dhdp);
-#ifdef BCMPCIE
-		if (is_reboot == SYS_RESTART) {
-			extern bcmdhd_wifi_platdata_t *dhd_wifi_platdata;
-			if (dhd_wifi_platdata && !dhdp->dongle_reset) {
-				dhdpcie_bus_clock_stop(dhdp->bus);
-				wifi_platform_set_power(dhd_wifi_platdata->adapters,
-					FALSE, WIFI_TURNOFF_DELAY);
-			}
-		}
-#endif /* BCMPCIE */
-#ifndef PCIE_FULL_DONGLE
-		if (dhdp->prot)
-			dhd_prot_detach(dhdp);
-#endif
-	}
-
-#ifdef ARP_OFFLOAD_SUPPORT
-	if (dhd_inetaddr_notifier_registered) {
-		dhd_inetaddr_notifier_registered = FALSE;
-		unregister_inetaddr_notifier(&dhd_inetaddr_notifier);
-	}
-#endif /* ARP_OFFLOAD_SUPPORT */
-#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT)
-	if (dhd_inet6addr_notifier_registered) {
-		dhd_inet6addr_notifier_registered = FALSE;
-		unregister_inet6addr_notifier(&dhd_inet6addr_notifier);
-	}
-#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */
-#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
-	if (dhd->dhd_state & DHD_ATTACH_STATE_EARLYSUSPEND_DONE) {
-		if (dhd->early_suspend.suspend)
-			unregister_early_suspend(&dhd->early_suspend);
-	}
-#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
-
-#if defined(WL_WIRELESS_EXT)
-	if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) {
-		/* Detatch and unlink in the iw */
-		wl_iw_detach();
-	}
-#endif /* defined(WL_WIRELESS_EXT) */
-
-	/* delete all interfaces, start with virtual  */
-	if (dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) {
-		int i = 1;
-		dhd_if_t *ifp;
-
-		/* Cleanup virtual interfaces */
-		dhd_net_if_lock_local(dhd);
-		for (i = 1; i < DHD_MAX_IFS; i++) {
-			if (dhd->iflist[i])
-				dhd_remove_if(&dhd->pub, i, TRUE);
-		}
-		dhd_net_if_unlock_local(dhd);
-
-		/*  delete primary interface 0 */
-		ifp = dhd->iflist[0];
-		ASSERT(ifp);
-		ASSERT(ifp->net);
-		if (ifp && ifp->net) {
-
-
-
-			/* in unregister_netdev case, the interface gets freed by net->destructor
-			 * (which is set to free_netdev)
-			 */
-			if (ifp->net->reg_state == NETREG_UNINITIALIZED) {
-				free_netdev(ifp->net);
-			} else {
-#ifdef SET_RPS_CPUS
-				custom_rps_map_clear(ifp->net->_rx);
-#endif /* SET_RPS_CPUS */
-				netif_tx_disable(ifp->net);
-				unregister_netdev(ifp->net);
-			}
-			ifp->net = NULL;
-#ifdef DHD_WMF
-			dhd_wmf_cleanup(dhdp, 0);
-#endif /* DHD_WMF */
-#ifdef DHD_L2_FILTER
-			bcm_l2_filter_arp_table_update(dhdp->osh, ifp->phnd_arp_table, TRUE,
-				NULL, FALSE, dhdp->tickcnt);
-			deinit_l2_filter_arp_table(dhdp->osh, ifp->phnd_arp_table);
-			ifp->phnd_arp_table = NULL;
-#endif /* DHD_L2_FILTER */
-
-			dhd_if_del_sta_list(ifp);
-
-			MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
-			dhd->iflist[0] = NULL;
-		}
-	}
-
-	/* Clear the watchdog timer */
-	DHD_GENERAL_LOCK(&dhd->pub, flags);
-	timer_valid = dhd->wd_timer_valid;
-	dhd->wd_timer_valid = FALSE;
-	DHD_GENERAL_UNLOCK(&dhd->pub, flags);
-	if (timer_valid)
-		del_timer_sync(&dhd->timer);
-	DHD_DISABLE_RUNTIME_PM(&dhd->pub);
-
-	if (dhd->dhd_state & DHD_ATTACH_STATE_THREADS_CREATED) {
-#ifdef DHD_PCIE_RUNTIMEPM
-		if (dhd->thr_rpm_ctl.thr_pid >= 0) {
-			PROC_STOP(&dhd->thr_rpm_ctl);
-		}
-#endif /* DHD_PCIE_RUNTIMEPM */
-		if (dhd->thr_wdt_ctl.thr_pid >= 0) {
-			PROC_STOP(&dhd->thr_wdt_ctl);
-		}
-
-		if (dhd->rxthread_enabled && dhd->thr_rxf_ctl.thr_pid >= 0) {
-			PROC_STOP(&dhd->thr_rxf_ctl);
-		}
-
-		if (dhd->thr_dpc_ctl.thr_pid >= 0) {
-			PROC_STOP(&dhd->thr_dpc_ctl);
-		} else {
-			tasklet_kill(&dhd->tasklet);
-#ifdef DHD_LB_RXP
-			__skb_queue_purge(&dhd->rx_pend_queue);
-#endif /* DHD_LB_RXP */
-		}
-	}
-
-#if defined(DHD_LB)
-	/* Kill the Load Balancing Tasklets */
-#if defined(DHD_LB_TXC)
-	tasklet_disable(&dhd->tx_compl_tasklet);
-	tasklet_kill(&dhd->tx_compl_tasklet);
-#endif /* DHD_LB_TXC */
-#if defined(DHD_LB_RXC)
-	tasklet_disable(&dhd->rx_compl_tasklet);
-	tasklet_kill(&dhd->rx_compl_tasklet);
-#endif /* DHD_LB_RXC */
-	if (dhd->cpu_notifier.notifier_call != NULL)
-		unregister_cpu_notifier(&dhd->cpu_notifier);
-	dhd_cpumasks_deinit(dhd);
-#endif /* DHD_LB */
-
-#ifdef DHD_LOG_DUMP
-	dhd_log_dump_deinit(&dhd->pub);
-#endif /* DHD_LOG_DUMP */
-#ifdef WL_CFG80211
-	if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
-		wl_cfg80211_detach(NULL);
-		dhd_monitor_uninit();
-	}
-#endif
-	/* free deferred work queue */
-	dhd_deferred_work_deinit(dhd->dhd_deferred_wq);
-	dhd->dhd_deferred_wq = NULL;
-
-#ifdef SHOW_LOGTRACE
-	if (dhd->event_data.fmts)
-		kfree(dhd->event_data.fmts);
-	if (dhd->event_data.raw_fmts)
-		kfree(dhd->event_data.raw_fmts);
-	if (dhd->event_data.raw_sstr)
-		kfree(dhd->event_data.raw_sstr);
-#endif /* SHOW_LOGTRACE */
-
-#ifdef PNO_SUPPORT
-	if (dhdp->pno_state)
-		dhd_pno_deinit(dhdp);
-#endif
-#if defined(CONFIG_PM_SLEEP)
-	if (dhd_pm_notifier_registered) {
-		unregister_pm_notifier(&dhd->pm_notifier);
-		dhd_pm_notifier_registered = FALSE;
-	}
-#endif /* CONFIG_PM_SLEEP */
-
-#ifdef DEBUG_CPU_FREQ
-		if (dhd->new_freq)
-			free_percpu(dhd->new_freq);
-		dhd->new_freq = NULL;
-		cpufreq_unregister_notifier(&dhd->freq_trans, CPUFREQ_TRANSITION_NOTIFIER);
-#endif
-	if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) {
-		DHD_TRACE(("wd wakelock count:%d\n", dhd->wakelock_wd_counter));
-#ifdef CONFIG_HAS_WAKELOCK
-		dhd->wakelock_wd_counter = 0;
-		wake_lock_destroy(&dhd->wl_wdwake);
-#endif /* CONFIG_HAS_WAKELOCK */
-		DHD_OS_WAKE_LOCK_DESTROY(dhd);
-	}
-
-
-
-#ifdef DHDTCPACK_SUPPRESS
-	/* This will free all MEM allocated for TCPACK SUPPRESS */
-	dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF);
-#endif /* DHDTCPACK_SUPPRESS */
-
-#ifdef PCIE_FULL_DONGLE
-		dhd_flow_rings_deinit(dhdp);
-		if (dhdp->prot)
-			dhd_prot_detach(dhdp);
-#endif
-
-
-	dhd_sysfs_exit(dhd);
-	dhd->pub.is_fw_download_done = FALSE;
-}
-
-
-void
-dhd_free(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd;
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (dhdp) {
-		int i;
-		for (i = 0; i < ARRAYSIZE(dhdp->reorder_bufs); i++) {
-			if (dhdp->reorder_bufs[i]) {
-				reorder_info_t *ptr;
-				uint32 buf_size = sizeof(struct reorder_info);
-
-				ptr = dhdp->reorder_bufs[i];
-
-				buf_size += ((ptr->max_idx + 1) * sizeof(void*));
-				DHD_REORDER(("free flow id buf %d, maxidx is %d, buf_size %d\n",
-					i, ptr->max_idx, buf_size));
-
-				MFREE(dhdp->osh, dhdp->reorder_bufs[i], buf_size);
-				dhdp->reorder_bufs[i] = NULL;
-			}
-		}
-
-		dhd_sta_pool_fini(dhdp, DHD_MAX_STA);
-
-		dhd = (dhd_info_t *)dhdp->info;
-		if (dhdp->soc_ram) {
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP)
-			DHD_OS_PREFREE(dhdp, dhdp->soc_ram, dhdp->soc_ram_length);
-#else
-			MFREE(dhdp->osh, dhdp->soc_ram, dhdp->soc_ram_length);
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */
-			dhdp->soc_ram = NULL;
-		}
-#ifdef CACHE_FW_IMAGES
-		if (dhdp->cached_fw) {
-			MFREE(dhdp->osh, dhdp->cached_fw, dhdp->bus->ramsize);
-			dhdp->cached_fw = NULL;
-		}
-
-		if (dhdp->cached_nvram) {
-			MFREE(dhdp->osh, dhdp->cached_nvram, MAX_NVRAMBUF_SIZE);
-			dhdp->cached_nvram = NULL;
-		}
-#endif
-		/* If pointer is allocated by dhd_os_prealloc then avoid MFREE */
-		if (dhd &&
-			dhd != (dhd_info_t *)dhd_os_prealloc(dhdp, DHD_PREALLOC_DHD_INFO, 0, FALSE))
-			MFREE(dhd->pub.osh, dhd, sizeof(*dhd));
-		dhd = NULL;
-	}
-}
-
-void
-dhd_clear(dhd_pub_t *dhdp)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (dhdp) {
-		int i;
-#ifdef DHDTCPACK_SUPPRESS
-		/* Clean up timer/data structure for any remaining/pending packet or timer. */
-		dhd_tcpack_info_tbl_clean(dhdp);
-#endif /* DHDTCPACK_SUPPRESS */
-		for (i = 0; i < ARRAYSIZE(dhdp->reorder_bufs); i++) {
-			if (dhdp->reorder_bufs[i]) {
-				reorder_info_t *ptr;
-				uint32 buf_size = sizeof(struct reorder_info);
-
-				ptr = dhdp->reorder_bufs[i];
-
-				buf_size += ((ptr->max_idx + 1) * sizeof(void*));
-				DHD_REORDER(("free flow id buf %d, maxidx is %d, buf_size %d\n",
-					i, ptr->max_idx, buf_size));
-
-				MFREE(dhdp->osh, dhdp->reorder_bufs[i], buf_size);
-				dhdp->reorder_bufs[i] = NULL;
-			}
-		}
-
-		dhd_sta_pool_clear(dhdp, DHD_MAX_STA);
-
-		if (dhdp->soc_ram) {
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP)
-			DHD_OS_PREFREE(dhdp, dhdp->soc_ram, dhdp->soc_ram_length);
-#else
-			MFREE(dhdp->osh, dhdp->soc_ram, dhdp->soc_ram_length);
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */
-			dhdp->soc_ram = NULL;
-		}
-	}
-}
-
-static void
-dhd_module_cleanup(void)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	dhd_bus_unregister();
-
-	wl_android_exit();
-
-	dhd_wifi_platform_unregister_drv();
-}
-
-static void __exit
-dhd_module_exit(void)
-{
-	dhd_buzzz_detach();
-	dhd_module_cleanup();
-	unregister_reboot_notifier(&dhd_reboot_notifier);
-}
-
-static int __init
-dhd_module_init(void)
-{
-	int err;
-	int retry = POWERUP_MAX_RETRY;
-
-	DHD_ERROR(("%s in\n", __FUNCTION__));
-
-	dhd_buzzz_attach();
-
-	DHD_PERIM_RADIO_INIT();
-
-
-	if (firmware_path[0] != '\0') {
-		strncpy(fw_bak_path, firmware_path, MOD_PARAM_PATHLEN);
-		fw_bak_path[MOD_PARAM_PATHLEN-1] = '\0';
-	}
-
-	if (nvram_path[0] != '\0') {
-		strncpy(nv_bak_path, nvram_path, MOD_PARAM_PATHLEN);
-		nv_bak_path[MOD_PARAM_PATHLEN-1] = '\0';
-	}
-
-	do {
-		err = dhd_wifi_platform_register_drv();
-		if (!err) {
-			register_reboot_notifier(&dhd_reboot_notifier);
-			break;
-		}
-		else {
-			DHD_ERROR(("%s: Failed to load the driver, try cnt %d\n",
-				__FUNCTION__, retry));
-			strncpy(firmware_path, fw_bak_path, MOD_PARAM_PATHLEN);
-			firmware_path[MOD_PARAM_PATHLEN-1] = '\0';
-			strncpy(nvram_path, nv_bak_path, MOD_PARAM_PATHLEN);
-			nvram_path[MOD_PARAM_PATHLEN-1] = '\0';
-		}
-	} while (retry--);
-
-	if (err) {
-		DHD_ERROR(("%s: Failed to load driver max retry reached**\n", __FUNCTION__));
-	} else {
-		if (!dhd_download_fw_on_driverload) {
-			dhd_driver_init_done = TRUE;
-		}
-	}
-
-	DHD_ERROR(("%s out\n", __FUNCTION__));
-
-	return err;
-}
-
-static int
-dhd_reboot_callback(struct notifier_block *this, unsigned long code, void *unused)
-{
-	DHD_TRACE(("%s: code = %ld\n", __FUNCTION__, code));
-	if (code == SYS_RESTART) {
-#ifdef BCMPCIE
-		is_reboot = code;
-#endif /* BCMPCIE */
-	}
-	return NOTIFY_DONE;
-}
-
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-#if defined(CONFIG_DEFERRED_INITCALLS)
-#if defined(CONFIG_MACH_UNIVERSAL7420) || defined(CONFIG_SOC_EXYNOS8890) || \
-	defined(CONFIG_ARCH_MSM8996)
-deferred_module_init_sync(dhd_module_init);
-#else
-deferred_module_init(dhd_module_init);
-#endif /* CONFIG_MACH_UNIVERSAL7420 || CONFIG_SOC_EXYNOS8890 ||
-	* CONFIG_ARCH_MSM8996
-	*/
-#elif defined(USE_LATE_INITCALL_SYNC)
-late_initcall_sync(dhd_module_init);
-#else
-late_initcall(dhd_module_init);
-#endif /* USE_LATE_INITCALL_SYNC */
-#else
-module_init(dhd_module_init);
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
-
-module_exit(dhd_module_exit);
-
-/*
- * OS specific functions required to implement DHD driver in OS independent way
- */
-int
-dhd_os_proto_block(dhd_pub_t *pub)
-{
-	dhd_info_t * dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-		DHD_PERIM_UNLOCK(pub);
-
-		down(&dhd->proto_sem);
-
-		DHD_PERIM_LOCK(pub);
-		return 1;
-	}
-
-	return 0;
-}
-
-int
-dhd_os_proto_unblock(dhd_pub_t *pub)
-{
-	dhd_info_t * dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-		up(&dhd->proto_sem);
-		return 1;
-	}
-
-	return 0;
-}
-
-void
-dhd_os_dhdiovar_lock(dhd_pub_t *pub)
-{
-	dhd_info_t * dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-		mutex_lock(&dhd->dhd_iovar_mutex);
-	}
-}
-
-void
-dhd_os_dhdiovar_unlock(dhd_pub_t *pub)
-{
-	dhd_info_t * dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-		mutex_unlock(&dhd->dhd_iovar_mutex);
-	}
-}
-
-unsigned int
-dhd_os_get_ioctl_resp_timeout(void)
-{
-	return ((unsigned int)dhd_ioctl_timeout_msec);
-}
-
-void
-dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
-{
-	dhd_ioctl_timeout_msec = (int)timeout_msec;
-}
-
-int
-dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition)
-{
-	dhd_info_t * dhd = (dhd_info_t *)(pub->info);
-	int timeout;
-
-	/* Convert timeout in millsecond to jiffies */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-	timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec);
-#else
-	timeout = dhd_ioctl_timeout_msec * HZ / 1000;
-#endif
-
-	DHD_PERIM_UNLOCK(pub);
-
-	timeout = wait_event_timeout(dhd->ioctl_resp_wait, (*condition), timeout);
-
-	DHD_PERIM_LOCK(pub);
-
-	return timeout;
-}
-
-int
-dhd_os_ioctl_resp_wake(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-
-	wake_up(&dhd->ioctl_resp_wait);
-	return 0;
-}
-
-int
-dhd_os_d3ack_wait(dhd_pub_t *pub, uint *condition)
-{
-	dhd_info_t * dhd = (dhd_info_t *)(pub->info);
-	int timeout;
-
-	/* Convert timeout in millsecond to jiffies */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-	timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec);
-#else
-	timeout = dhd_ioctl_timeout_msec * HZ / 1000;
-#endif
-
-	DHD_PERIM_UNLOCK(pub);
-
-	timeout = wait_event_timeout(dhd->d3ack_wait, (*condition), timeout);
-
-	DHD_PERIM_LOCK(pub);
-
-	return timeout;
-}
-
-int
-dhd_os_d3ack_wake(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-
-	wake_up(&dhd->d3ack_wait);
-	return 0;
-}
-
-int
-dhd_os_busbusy_wait_negation(dhd_pub_t *pub, uint *condition)
-{
-	dhd_info_t * dhd = (dhd_info_t *)(pub->info);
-	int timeout;
-
-	/* Wait for bus usage contexts to gracefully exit within some timeout value
-	 * Set time out to little higher than dhd_ioctl_timeout_msec,
-	 * so that IOCTL timeout should not get affected.
-	 */
-	/* Convert timeout in millsecond to jiffies */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-	timeout = msecs_to_jiffies(DHD_BUS_BUSY_TIMEOUT);
-#else
-	timeout = DHD_BUS_BUSY_TIMEOUT * HZ / 1000;
-#endif
-
-	timeout = wait_event_timeout(dhd->dhd_bus_busy_state_wait, !(*condition), timeout);
-
-	return timeout;
-}
-
-int INLINE
-dhd_os_busbusy_wake(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	/* Call wmb() to make sure before waking up the other event value gets updated */
-	OSL_SMP_WMB();
-	wake_up(&dhd->dhd_bus_busy_state_wait);
-	return 0;
-}
-
-void
-dhd_os_wd_timer_extend(void *bus, bool extend)
-{
-	dhd_pub_t *pub = bus;
-	dhd_info_t *dhd = (dhd_info_t *)pub->info;
-
-	if (extend)
-		dhd_os_wd_timer(bus, WATCHDOG_EXTEND_INTERVAL);
-	else
-		dhd_os_wd_timer(bus, dhd->default_wd_interval);
-}
-
-
-void
-dhd_os_wd_timer(void *bus, uint wdtick)
-{
-	dhd_pub_t *pub = bus;
-	dhd_info_t *dhd = (dhd_info_t *)pub->info;
-	unsigned long flags;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (!dhd) {
-		DHD_ERROR(("%s: dhd NULL\n", __FUNCTION__));
-		return;
-	}
-
-	DHD_OS_WD_WAKE_LOCK(pub);
-	DHD_GENERAL_LOCK(pub, flags);
-
-	/* don't start the wd until fw is loaded */
-	if (pub->busstate == DHD_BUS_DOWN) {
-		DHD_GENERAL_UNLOCK(pub, flags);
-		if (!wdtick)
-			DHD_OS_WD_WAKE_UNLOCK(pub);
-		return;
-	}
-
-	/* Totally stop the timer */
-	if (!wdtick && dhd->wd_timer_valid == TRUE) {
-		dhd->wd_timer_valid = FALSE;
-		DHD_GENERAL_UNLOCK(pub, flags);
-		del_timer_sync(&dhd->timer);
-		DHD_OS_WD_WAKE_UNLOCK(pub);
-		return;
-	}
-
-	if (wdtick) {
-		DHD_OS_WD_WAKE_LOCK(pub);
-		dhd_watchdog_ms = (uint)wdtick;
-		/* Re arm the timer, at last watchdog period */
-		mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms));
-		dhd->wd_timer_valid = TRUE;
-	}
-	DHD_GENERAL_UNLOCK(pub, flags);
-	DHD_OS_WD_WAKE_UNLOCK(pub);
-}
-
-#ifdef DHD_PCIE_RUNTIMEPM
-void
-dhd_os_runtimepm_timer(void *bus, uint tick)
-{
-	dhd_pub_t *pub = bus;
-	dhd_info_t *dhd = (dhd_info_t *)pub->info;
-	unsigned long flags;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (!dhd) {
-		DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	DHD_GENERAL_LOCK(pub, flags);
-
-	/* don't start the RPM until fw is loaded */
-	if (pub->busstate == DHD_BUS_DOWN ||
-			pub->busstate == DHD_BUS_DOWN_IN_PROGRESS) {
-		DHD_GENERAL_UNLOCK(pub, flags);
-		return;
-	}
-
-	/* If tick is non-zero, the request is to start the timer */
-	if (tick) {
-		/* Start the timer only if its not already running */
-		if (dhd->rpm_timer_valid == FALSE) {
-			mod_timer(&dhd->rpm_timer, jiffies + msecs_to_jiffies(dhd_runtimepm_ms));
-			dhd->rpm_timer_valid = TRUE;
-		}
-	} else {
-		/* tick is zero, we have to stop the timer */
-		/* Stop the timer only if its running, otherwise we don't have to do anything */
-		if (dhd->rpm_timer_valid == TRUE) {
-			dhd->rpm_timer_valid = FALSE;
-			DHD_GENERAL_UNLOCK(pub, flags);
-			del_timer_sync(&dhd->rpm_timer);
-			/* we have already released the lock, so just go to exit */
-			goto exit;
-		}
-	}
-
-	DHD_GENERAL_UNLOCK(pub, flags);
-exit:
-	return;
-
-}
-
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-void *
-dhd_os_open_image(char *filename)
-{
-	struct file *fp;
-	int size;
-
-	fp = filp_open(filename, O_RDONLY, 0);
-	/*
-	 * 2.6.11 (FC4) supports filp_open() but later revs don't?
-	 * Alternative:
-	 * fp = open_namei(AT_FDCWD, filename, O_RD, 0);
-	 * ???
-	 */
-	 if (IS_ERR(fp)) {
-		 fp = NULL;
-		 goto err;
-	 }
-
-	 if (!S_ISREG(file_inode(fp)->i_mode)) {
-		 DHD_ERROR(("%s: %s is not regular file\n", __FUNCTION__, filename));
-		 fp = NULL;
-		 goto err;
-	 }
-
-	 size = i_size_read(file_inode(fp));
-	 if (size <= 0) {
-		 DHD_ERROR(("%s: %s file size invalid %d\n", __FUNCTION__, filename, size));
-		 fp = NULL;
-		 goto err;
-	 }
-
-	 DHD_ERROR(("%s: %s (%d bytes) open success\n", __FUNCTION__, filename, size));
-
-err:
-	 return fp;
-}
-
-int
-dhd_os_get_image_block(char *buf, int len, void *image)
-{
-	struct file *fp = (struct file *)image;
-	int rdlen;
-	int size;
-
-	if (!image)
-		return 0;
-
-	size = i_size_read(file_inode(fp));
-	rdlen = kernel_read(fp, fp->f_pos, buf, MIN(len, size));
-
-	if (len >= size && size != rdlen) {
-		return -EIO;
-	}
-
-	if (rdlen > 0)
-		fp->f_pos += rdlen;
-
-	return rdlen;
-}
-
-void
-dhd_os_close_image(void *image)
-{
-	if (image)
-		filp_close((struct file *)image, NULL);
-}
-
-void
-dhd_os_sdlock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd_dpc_prio >= 0)
-		down(&dhd->sdsem);
-	else
-		spin_lock_bh(&dhd->sdlock);
-}
-
-void
-dhd_os_sdunlock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd_dpc_prio >= 0)
-		up(&dhd->sdsem);
-	else
-		spin_unlock_bh(&dhd->sdlock);
-}
-
-void
-dhd_os_sdlock_txq(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *)(pub->info);
-	spin_lock_bh(&dhd->txqlock);
-}
-
-void
-dhd_os_sdunlock_txq(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *)(pub->info);
-	spin_unlock_bh(&dhd->txqlock);
-}
-
-void
-dhd_os_sdlock_rxq(dhd_pub_t *pub)
-{
-}
-
-void
-dhd_os_sdunlock_rxq(dhd_pub_t *pub)
-{
-}
-
-static void
-dhd_os_rxflock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *)(pub->info);
-	spin_lock_bh(&dhd->rxf_lock);
-
-}
-
-static void
-dhd_os_rxfunlock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *)(pub->info);
-	spin_unlock_bh(&dhd->rxf_lock);
-}
-
-#ifdef DHDTCPACK_SUPPRESS
-unsigned long
-dhd_os_tcpacklock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-	unsigned long flags = 0;
-
-	dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-#ifdef BCMSDIO
-		spin_lock_bh(&dhd->tcpack_lock);
-#else
-		spin_lock_irqsave(&dhd->tcpack_lock, flags);
-#endif /* BCMSDIO */
-	}
-
-	return flags;
-}
-
-void
-dhd_os_tcpackunlock(dhd_pub_t *pub, unsigned long flags)
-{
-	dhd_info_t *dhd;
-
-#ifdef BCMSDIO
-	BCM_REFERENCE(flags);
-#endif /* BCMSDIO */
-
-	dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-#ifdef BCMSDIO
-		spin_lock_bh(&dhd->tcpack_lock);
-#else
-		spin_unlock_irqrestore(&dhd->tcpack_lock, flags);
-#endif /* BCMSDIO */
-	}
-}
-#endif /* DHDTCPACK_SUPPRESS */
-
-uint8* dhd_os_prealloc(dhd_pub_t *dhdpub, int section, uint size, bool kmalloc_if_fail)
-{
-	uint8* buf;
-	gfp_t flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
-
-	buf = (uint8*)wifi_platform_prealloc(dhdpub->info->adapter, section, size);
-	if (buf == NULL && kmalloc_if_fail)
-		buf = kmalloc(size, flags);
-
-	return buf;
-}
-
-void dhd_os_prefree(dhd_pub_t *dhdpub, void *addr, uint size)
-{
-}
-
-#if defined(WL_WIRELESS_EXT)
-struct iw_statistics *
-dhd_get_wireless_stats(struct net_device *dev)
-{
-	int res = 0;
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	if (!dhd->pub.up) {
-		return NULL;
-	}
-
-	res = wl_iw_get_wireless_stats(dev, &dhd->iw.wstats);
-
-	if (res == 0)
-		return &dhd->iw.wstats;
-	else
-		return NULL;
-}
-#endif /* defined(WL_WIRELESS_EXT) */
-
-static int
-dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, size_t pktlen,
-	wl_event_msg_t *event, void **data)
-{
-	int bcmerror = 0;
-	ASSERT(dhd != NULL);
-
-#ifdef SHOW_LOGTRACE
-		bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, pktlen, event, data, &dhd->event_data);
-#else
-		bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, pktlen, event, data, NULL);
-#endif /* SHOW_LOGTRACE */
-
-	if (bcmerror != BCME_OK)
-		return (bcmerror);
-
-#if defined(WL_WIRELESS_EXT)
-	if (event->bsscfgidx == 0) {
-		/*
-		 * Wireless ext is on primary interface only
-		 */
-
-	ASSERT(dhd->iflist[*ifidx] != NULL);
-	ASSERT(dhd->iflist[*ifidx]->net != NULL);
-
-		if (dhd->iflist[*ifidx]->net) {
-		wl_iw_event(dhd->iflist[*ifidx]->net, event, *data);
-		}
-	}
-#endif /* defined(WL_WIRELESS_EXT)  */
-
-#ifdef WL_CFG80211
-	ASSERT(dhd->iflist[*ifidx] != NULL);
-	ASSERT(dhd->iflist[*ifidx]->net != NULL);
-	if (dhd->iflist[*ifidx]->net)
-		wl_cfg80211_event(dhd->iflist[*ifidx]->net, event, *data);
-#endif /* defined(WL_CFG80211) */
-
-	return (bcmerror);
-}
-
-/* send up locally generated event */
-void
-dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
-{
-	switch (ntoh32(event->event_type)) {
-
-	default:
-		break;
-	}
-}
-
-#ifdef LOG_INTO_TCPDUMP
-void
-dhd_sendup_log(dhd_pub_t *dhdp, void *data, int data_len)
-{
-	struct sk_buff *p, *skb;
-	uint32 pktlen;
-	int len;
-	dhd_if_t *ifp;
-	dhd_info_t *dhd;
-	uchar *skb_data;
-	int ifidx = 0;
-	struct ether_header eth;
-
-	pktlen = sizeof(eth) + data_len;
-	dhd = dhdp->info;
-
-	if ((p = PKTGET(dhdp->osh, pktlen, FALSE))) {
-		ASSERT(ISALIGNED((uintptr)PKTDATA(dhdp->osh, p), sizeof(uint32)));
-
-		bcopy(&dhdp->mac, &eth.ether_dhost, ETHER_ADDR_LEN);
-		bcopy(&dhdp->mac, &eth.ether_shost, ETHER_ADDR_LEN);
-		ETHER_TOGGLE_LOCALADDR(&eth.ether_shost);
-		eth.ether_type = hton16(ETHER_TYPE_BRCM);
-
-		bcopy((void *)&eth, PKTDATA(dhdp->osh, p), sizeof(eth));
-		bcopy(data, PKTDATA(dhdp->osh, p) + sizeof(eth), data_len);
-		skb = PKTTONATIVE(dhdp->osh, p);
-		skb_data = skb->data;
-		len = skb->len;
-
-		ifidx = dhd_ifname2idx(dhd, "wlan0");
-		ifp = dhd->iflist[ifidx];
-		if (ifp == NULL)
-			 ifp = dhd->iflist[0];
-
-		ASSERT(ifp);
-		skb->dev = ifp->net;
-		skb->protocol = eth_type_trans(skb, skb->dev);
-		skb->data = skb_data;
-		skb->len = len;
-
-		/* Strip header, count, deliver upward */
-		skb_pull(skb, ETH_HLEN);
-
-		bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE,
-			__FUNCTION__, __LINE__);
-		/* Send the packet */
-		if (in_interrupt()) {
-			netif_rx(skb);
-		} else {
-			netif_rx_ni(skb);
-		}
-	}
-	else {
-		/* Could not allocate a sk_buf */
-		DHD_ERROR(("%s: unable to alloc sk_buf", __FUNCTION__));
-	}
-}
-#endif /* LOG_INTO_TCPDUMP */
-
-void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar)
-{
-#if defined(BCMSDIO) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-	struct dhd_info *dhdinfo =  dhd->info;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-	int timeout = msecs_to_jiffies(IOCTL_RESP_TIMEOUT);
-#else
-	int timeout = (IOCTL_RESP_TIMEOUT / 1000) * HZ;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-
-	dhd_os_sdunlock(dhd);
-	wait_event_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), timeout);
-	dhd_os_sdlock(dhd);
-#endif /* defined(BCMSDIO) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */
-	return;
-}
-
-void dhd_wait_event_wakeup(dhd_pub_t *dhd)
-{
-#if defined(BCMSDIO) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-	struct dhd_info *dhdinfo =  dhd->info;
-	if (waitqueue_active(&dhdinfo->ctrl_wait))
-		wake_up(&dhdinfo->ctrl_wait);
-#endif
-	return;
-}
-
-#if defined(BCMSDIO) || defined(BCMPCIE)
-int
-dhd_net_bus_devreset(struct net_device *dev, uint8 flag)
-{
-	int ret;
-
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	if (flag == TRUE) {
-		/* Issue wl down command before resetting the chip */
-		if (dhd_wl_ioctl_cmd(&dhd->pub, WLC_DOWN, NULL, 0, TRUE, 0) < 0) {
-			DHD_TRACE(("%s: wl down failed\n", __FUNCTION__));
-		}
-#ifdef PROP_TXSTATUS
-		if (dhd->pub.wlfc_enabled)
-			dhd_wlfc_deinit(&dhd->pub);
-#endif /* PROP_TXSTATUS */
-#ifdef PNO_SUPPORT
-	if (dhd->pub.pno_state)
-		dhd_pno_deinit(&dhd->pub);
-#endif
-	}
-
-#ifdef BCMSDIO
-	if (!flag) {
-		dhd_update_fw_nv_path(dhd);
-		/* update firmware and nvram path to sdio bus */
-		dhd_bus_update_fw_nv_path(dhd->pub.bus,
-			dhd->fw_path, dhd->nv_path);
-	}
-#endif /* BCMSDIO */
-
-	ret = dhd_bus_devreset(&dhd->pub, flag);
-	if (ret) {
-		DHD_ERROR(("%s: dhd_bus_devreset: %d\n", __FUNCTION__, ret));
-		return ret;
-	}
-
-	return ret;
-}
-
-#ifdef BCMSDIO
-int
-dhd_net_bus_suspend(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	return dhd_bus_suspend(&dhd->pub);
-}
-
-int
-dhd_net_bus_resume(struct net_device *dev, uint8 stage)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	return dhd_bus_resume(&dhd->pub, stage);
-}
-
-#endif /* BCMSDIO */
-#endif /* BCMSDIO || BCMPCIE */
-
-int net_os_set_suspend_disable(struct net_device *dev, int val)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ret = 0;
-
-	if (dhd) {
-		ret = dhd->pub.suspend_disable_flag;
-		dhd->pub.suspend_disable_flag = val;
-	}
-	return ret;
-}
-
-int net_os_set_suspend(struct net_device *dev, int val, int force)
-{
-	int ret = 0;
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	if (dhd) {
-#ifdef CONFIG_MACH_UNIVERSAL7420
-#endif /* CONFIG_MACH_UNIVERSAL7420 */
-#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
-		ret = dhd_set_suspend(val, &dhd->pub);
-#else
-		ret = dhd_suspend_resume_helper(dhd, val, force);
-#endif
-#ifdef WL_CFG80211
-		wl_cfg80211_update_power_mode(dev);
-#endif
-	}
-	return ret;
-}
-
-int net_os_set_suspend_bcn_li_dtim(struct net_device *dev, int val)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	if (dhd)
-		dhd->pub.suspend_bcn_li_dtim = val;
-
-	return 0;
-}
-
-#ifdef PKT_FILTER_SUPPORT
-int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num)
-{
-#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER
-	return 0;
-#else
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	char *filterp = NULL;
-	int filter_id = 0;
-	int ret = 0;
-
-	DHD_ERROR(("%s: add_remove = %d, num = %d\n", __FUNCTION__, add_remove, num));
-	if (!dhd || (num == DHD_UNICAST_FILTER_NUM))
-		return ret;
-	if (num >= dhd->pub.pktfilter_count)
-		return -EINVAL;
-	switch (num) {
-		case DHD_BROADCAST_FILTER_NUM:
-			filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF";
-			filter_id = 101;
-			break;
-		case DHD_MULTICAST4_FILTER_NUM:
-			filterp = "102 0 0 0 0xFFFFFF 0x01005E";
-			filter_id = 102;
-			break;
-		case DHD_MULTICAST6_FILTER_NUM:
-			filterp = "103 0 0 0 0xFFFF 0x3333";
-			filter_id = 103;
-			break;
-		case DHD_MDNS_FILTER_NUM:
-			filterp = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB";
-			filter_id = 104;
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	/* Add filter */
-	if (add_remove) {
-		dhd->pub.pktfilter[num] = filterp;
-		dhd_pktfilter_offload_set(&dhd->pub, dhd->pub.pktfilter[num]);
-	} else { /* Delete filter */
-		if (dhd->pub.pktfilter[num] != NULL) {
-			dhd_pktfilter_offload_delete(&dhd->pub, filter_id);
-			dhd->pub.pktfilter[num] = NULL;
-		}
-	}
-	return ret;
-#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */
-}
-
-int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val)
-
-{
-	int ret = 0;
-
-	/* Packet filtering is set only if we still in early-suspend and
-	 * we need either to turn it ON or turn it OFF
-	 * We can always turn it OFF in case of early-suspend, but we turn it
-	 * back ON only if suspend_disable_flag was not set
-	*/
-	if (dhdp && dhdp->up) {
-		if (dhdp->in_suspend) {
-			if (!val || (val && !dhdp->suspend_disable_flag))
-				dhd_enable_packet_filter(val, dhdp);
-		}
-	}
-	return ret;
-}
-
-/* function to enable/disable packet for Network device */
-int net_os_enable_packet_filter(struct net_device *dev, int val)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	DHD_ERROR(("%s: val = %d\n", __FUNCTION__, val));
-	return dhd_os_enable_packet_filter(&dhd->pub, val);
-}
-#endif /* PKT_FILTER_SUPPORT */
-
-int
-dhd_dev_init_ioctl(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ret;
-
-	if ((ret = dhd_sync_with_dongle(&dhd->pub)) < 0)
-		goto done;
-
-done:
-	return ret;
-}
-
-int
-dhd_dev_get_feature_set(struct net_device *dev)
-{
-	dhd_info_t *ptr = *(dhd_info_t **)netdev_priv(dev);
-	dhd_pub_t *dhd = (&ptr->pub);
-	int feature_set = 0;
-
-#ifdef DYNAMIC_SWOOB_DURATION
-#ifndef CUSTOM_INTR_WIDTH
-#define CUSTOM_INTR_WIDTH 100
-	int intr_width = 0;
-#endif /* CUSTOM_INTR_WIDTH */
-#endif /* DYNAMIC_SWOOB_DURATION */
-	if (!dhd)
-		return feature_set;
-
-	if (FW_SUPPORTED(dhd, sta))
-		feature_set |= WIFI_FEATURE_INFRA;
-	if (FW_SUPPORTED(dhd, dualband))
-		feature_set |= WIFI_FEATURE_INFRA_5G;
-	if (FW_SUPPORTED(dhd, p2p))
-		feature_set |= WIFI_FEATURE_P2P;
-	if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE)
-		feature_set |= WIFI_FEATURE_SOFT_AP;
-	if (FW_SUPPORTED(dhd, tdls))
-		feature_set |= WIFI_FEATURE_TDLS;
-	if (FW_SUPPORTED(dhd, vsdb))
-		feature_set |= WIFI_FEATURE_TDLS_OFFCHANNEL;
-	if (FW_SUPPORTED(dhd, nan)) {
-		feature_set |= WIFI_FEATURE_NAN;
-		/* NAN is essentail for d2d rtt */
-		if (FW_SUPPORTED(dhd, rttd2d))
-			feature_set |= WIFI_FEATURE_D2D_RTT;
-	}
-#ifdef RTT_SUPPORT
-	feature_set |= WIFI_FEATURE_D2AP_RTT;
-#endif /* RTT_SUPPORT */
-#ifdef LINKSTAT_SUPPORT
-	feature_set |= WIFI_FEATURE_LINKSTAT;
-#endif /* LINKSTAT_SUPPORT */
-	/* Supports STA + STA always */
-	feature_set |= WIFI_FEATURE_ADDITIONAL_STA;
-#ifdef PNO_SUPPORT
-	if (dhd_is_pno_supported(dhd)) {
-		feature_set |= WIFI_FEATURE_PNO;
-		feature_set |= WIFI_FEATURE_BATCH_SCAN;
-#ifdef GSCAN_SUPPORT
-		feature_set |= WIFI_FEATURE_GSCAN;
-#endif /* GSCAN_SUPPORT */
-	}
-#endif /* PNO_SUPPORT */
-#ifdef WL11U
-	feature_set |= WIFI_FEATURE_HOTSPOT;
-#endif /* WL11U */
-	return feature_set;
-}
-
-
-int *dhd_dev_get_feature_set_matrix(struct net_device *dev, int *num)
-{
-	int feature_set_full, mem_needed;
-	int *ret;
-
-	*num = 0;
-	mem_needed = sizeof(int) * MAX_FEATURE_SET_CONCURRRENT_GROUPS;
-	ret = (int *) kmalloc(mem_needed, GFP_KERNEL);
-	if (!ret) {
-		DHD_ERROR(("%s: failed to allocate %d bytes\n", __FUNCTION__,
-			mem_needed));
-		return ret;
-	}
-
-	feature_set_full = dhd_dev_get_feature_set(dev);
-
-	ret[0] = (feature_set_full & WIFI_FEATURE_INFRA) |
-	         (feature_set_full & WIFI_FEATURE_INFRA_5G) |
-	         (feature_set_full & WIFI_FEATURE_NAN) |
-	         (feature_set_full & WIFI_FEATURE_D2D_RTT) |
-	         (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
-	         (feature_set_full & WIFI_FEATURE_PNO) |
-	         (feature_set_full & WIFI_FEATURE_BATCH_SCAN) |
-	         (feature_set_full & WIFI_FEATURE_GSCAN) |
-	         (feature_set_full & WIFI_FEATURE_HOTSPOT) |
-	         (feature_set_full & WIFI_FEATURE_ADDITIONAL_STA) |
-	         (feature_set_full & WIFI_FEATURE_EPR);
-
-	ret[1] = (feature_set_full & WIFI_FEATURE_INFRA) |
-	         (feature_set_full & WIFI_FEATURE_INFRA_5G) |
-	         /* Not yet verified NAN with P2P */
-	         /* (feature_set_full & WIFI_FEATURE_NAN) | */
-	         (feature_set_full & WIFI_FEATURE_P2P) |
-	         (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
-	         (feature_set_full & WIFI_FEATURE_D2D_RTT) |
-	         (feature_set_full & WIFI_FEATURE_EPR);
-
-	ret[2] = (feature_set_full & WIFI_FEATURE_INFRA) |
-	         (feature_set_full & WIFI_FEATURE_INFRA_5G) |
-	         (feature_set_full & WIFI_FEATURE_NAN) |
-	         (feature_set_full & WIFI_FEATURE_D2D_RTT) |
-	         (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
-	         (feature_set_full & WIFI_FEATURE_TDLS) |
-	         (feature_set_full & WIFI_FEATURE_TDLS_OFFCHANNEL) |
-	         (feature_set_full & WIFI_FEATURE_EPR);
-	*num = MAX_FEATURE_SET_CONCURRRENT_GROUPS;
-
-	return ret;
-}
-#ifdef CUSTOM_FORCE_NODFS_FLAG
-int
-dhd_dev_set_nodfs(struct net_device *dev, u32 nodfs)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	if (nodfs)
-		dhd->pub.dhd_cflags |= WLAN_PLAT_NODFS_FLAG;
-	else
-		dhd->pub.dhd_cflags &= ~WLAN_PLAT_NODFS_FLAG;
-	dhd->pub.force_country_change = TRUE;
-	return 0;
-}
-#endif /* CUSTOM_FORCE_NODFS_FLAG */
-#ifdef PNO_SUPPORT
-/* Linux wrapper to call common dhd_pno_stop_for_ssid */
-int
-dhd_dev_pno_stop_for_ssid(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	return (dhd_pno_stop_for_ssid(&dhd->pub));
-}
-/* Linux wrapper to call common dhd_pno_set_for_ssid */
-int
-dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_ext_t* ssids_local, int nssid,
-	uint16  scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	return (dhd_pno_set_for_ssid(&dhd->pub, ssids_local, nssid, scan_fr,
-		pno_repeat, pno_freq_expo_max, channel_list, nchan));
-}
-
-/* Linux wrapper to call common dhd_pno_enable */
-int
-dhd_dev_pno_enable(struct net_device *dev, int enable)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	return (dhd_pno_enable(&dhd->pub, enable));
-}
-
-/* Linux wrapper to call common dhd_pno_set_for_hotlist */
-int
-dhd_dev_pno_set_for_hotlist(struct net_device *dev, wl_pfn_bssid_t *p_pfn_bssid,
-	struct dhd_pno_hotlist_params *hotlist_params)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	return (dhd_pno_set_for_hotlist(&dhd->pub, p_pfn_bssid, hotlist_params));
-}
-/* Linux wrapper to call common dhd_dev_pno_stop_for_batch */
-int
-dhd_dev_pno_stop_for_batch(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	return (dhd_pno_stop_for_batch(&dhd->pub));
-}
-/* Linux wrapper to call common dhd_dev_pno_set_for_batch */
-int
-dhd_dev_pno_set_for_batch(struct net_device *dev, struct dhd_pno_batch_params *batch_params)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	return (dhd_pno_set_for_batch(&dhd->pub, batch_params));
-}
-/* Linux wrapper to call common dhd_dev_pno_get_for_batch */
-int
-dhd_dev_pno_get_for_batch(struct net_device *dev, char *buf, int bufsize)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	return (dhd_pno_get_for_batch(&dhd->pub, buf, bufsize, PNO_STATUS_NORMAL));
-}
-/* Linux wrapper to call common dhd_pno_set_mac_oui */
-int
-dhd_dev_pno_set_mac_oui(struct net_device *dev, uint8 *oui)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	return (dhd_pno_set_mac_oui(&dhd->pub, oui));
-}
-#endif /* PNO_SUPPORT */
-
-#if defined(PNO_SUPPORT)
-#ifdef GSCAN_SUPPORT
-/* Linux wrapper to call common dhd_pno_set_cfg_gscan */
-int
-dhd_dev_pno_set_cfg_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type,
- void *buf, uint8 flush)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_pno_set_cfg_gscan(&dhd->pub, type, buf, flush));
-}
-
-/* Linux wrapper to call common dhd_pno_get_gscan */
-void *
-dhd_dev_pno_get_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type,
-                      void *info, uint32 *len)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_pno_get_gscan(&dhd->pub, type, info, len));
-}
-
-/* Linux wrapper to call common dhd_wait_batch_results_complete */
-void
-dhd_dev_wait_batch_results_complete(struct net_device *dev)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_wait_batch_results_complete(&dhd->pub));
-}
-
-/* Linux wrapper to call common dhd_pno_lock_batch_results */
-void
-dhd_dev_pno_lock_access_batch_results(struct net_device *dev)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_pno_lock_batch_results(&dhd->pub));
-}
-/* Linux wrapper to call common dhd_pno_unlock_batch_results */
-void
-dhd_dev_pno_unlock_access_batch_results(struct net_device *dev)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_pno_unlock_batch_results(&dhd->pub));
-}
-
-/* Linux wrapper to call common dhd_pno_initiate_gscan_request */
-int
-dhd_dev_pno_run_gscan(struct net_device *dev, bool run, bool flush)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_pno_initiate_gscan_request(&dhd->pub, run, flush));
-}
-
-/* Linux wrapper to call common dhd_pno_enable_full_scan_result */
-int
-dhd_dev_pno_enable_full_scan_result(struct net_device *dev, bool real_time_flag)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_pno_enable_full_scan_result(&dhd->pub, real_time_flag));
-}
-
-/* Linux wrapper to call common dhd_handle_swc_evt */
-void *
-dhd_dev_swc_scan_event(struct net_device *dev, const void  *data, int *send_evt_bytes)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_handle_swc_evt(&dhd->pub, data, send_evt_bytes));
-}
-
-/* Linux wrapper to call common dhd_handle_hotlist_scan_evt */
-void *
-dhd_dev_hotlist_scan_event(struct net_device *dev,
-      const void  *data, int *send_evt_bytes, hotlist_type_t type)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_handle_hotlist_scan_evt(&dhd->pub, data, send_evt_bytes, type));
-}
-
-/* Linux wrapper to call common dhd_process_full_gscan_result */
-void *
-dhd_dev_process_full_gscan_result(struct net_device *dev,
-const void  *data, int *send_evt_bytes)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_process_full_gscan_result(&dhd->pub, data, send_evt_bytes));
-}
-
-void
-dhd_dev_gscan_hotlist_cache_cleanup(struct net_device *dev, hotlist_type_t type)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	dhd_gscan_hotlist_cache_cleanup(&dhd->pub, type);
-
-	return;
-}
-
-int
-dhd_dev_gscan_batch_cache_cleanup(struct net_device *dev)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_gscan_batch_cache_cleanup(&dhd->pub));
-}
-
-/* Linux wrapper to call common dhd_retreive_batch_scan_results */
-int
-dhd_dev_retrieve_batch_scan(struct net_device *dev)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_retreive_batch_scan_results(&dhd->pub));
-}
-#endif /* GSCAN_SUPPORT */
-#endif 
-#ifdef RTT_SUPPORT
-/* Linux wrapper to call common dhd_pno_set_cfg_gscan */
-int
-dhd_dev_rtt_set_cfg(struct net_device *dev, void *buf)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_rtt_set_cfg(&dhd->pub, buf));
-}
-int
-dhd_dev_rtt_cancel_cfg(struct net_device *dev, struct ether_addr *mac_list, int mac_cnt)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_rtt_stop(&dhd->pub, mac_list, mac_cnt));
-}
-int
-dhd_dev_rtt_register_noti_callback(struct net_device *dev, void *ctx, dhd_rtt_compl_noti_fn noti_fn)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_rtt_register_noti_callback(&dhd->pub, ctx, noti_fn));
-}
-int
-dhd_dev_rtt_unregister_noti_callback(struct net_device *dev, dhd_rtt_compl_noti_fn noti_fn)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_rtt_unregister_noti_callback(&dhd->pub, noti_fn));
-}
-
-int
-dhd_dev_rtt_capability(struct net_device *dev, rtt_capabilities_t *capa)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return (dhd_rtt_capability(&dhd->pub, capa));
-}
-
-#endif /* RTT_SUPPORT */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-static void dhd_hang_process(void *dhd_info, void *event_info, u8 event)
-{
-	dhd_info_t *dhd;
-	struct net_device *dev;
-
-	dhd = (dhd_info_t *)dhd_info;
-	dev = dhd->iflist[0]->net;
-
-	if (dev) {
-#if defined(WL_WIRELESS_EXT)
-		wl_iw_send_priv_event(dev, "HANG");
-#endif
-#if defined(WL_CFG80211)
-		wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED);
-#endif
-	}
-}
-
-#ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY
-extern dhd_pub_t *link_recovery;
-void dhd_host_recover_link(void)
-{
-	DHD_ERROR(("****** %s ******\n", __FUNCTION__));
-	link_recovery->hang_reason = HANG_REASON_PCIE_LINK_DOWN;
-	dhd_bus_set_linkdown(link_recovery, TRUE);
-	dhd_os_send_hang_message(link_recovery);
-}
-EXPORT_SYMBOL(dhd_host_recover_link);
-#endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */
-
-int dhd_os_send_hang_message(dhd_pub_t *dhdp)
-{
-	int ret = 0;
-	if (dhdp) {
-		if (!dhdp->hang_was_sent) {
-			dhdp->hang_was_sent = 1;
-			dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, (void *)dhdp,
-				DHD_WQ_WORK_HANG_MSG, dhd_hang_process, DHD_WORK_PRIORITY_HIGH);
-		}
-	}
-	return ret;
-}
-
-int net_os_send_hang_message(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ret = 0;
-
-	if (dhd) {
-		/* Report FW problem when enabled */
-		if (dhd->pub.hang_report) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-			ret = dhd_os_send_hang_message(&dhd->pub);
-#else
-			ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED);
-#endif
-		} else {
-			DHD_ERROR(("%s: FW HANG ignored (for testing purpose) and not sent up\n",
-				__FUNCTION__));
-			/* Enforce bus down to stop any future traffic */
-			dhd->pub.busstate = DHD_BUS_DOWN;
-		}
-	}
-	return ret;
-}
-
-int net_os_send_hang_message_reason(struct net_device *dev, const char *string_num)
-{
-	dhd_info_t *dhd = NULL;
-	dhd_pub_t *dhdp = NULL;
-	int reason;
-
-	dhd = DHD_DEV_INFO(dev);
-	if (dhd) {
-		dhdp = &dhd->pub;
-	}
-
-	if (!dhd || !dhdp) {
-		return 0;
-	}
-
-	reason = bcm_strtoul(string_num, NULL, 0);
-	DHD_INFO(("%s: Enter, reason=0x%x\n", __FUNCTION__, reason));
-
-	if ((reason <= HANG_REASON_MASK) || (reason >= HANG_REASON_MAX)) {
-		reason = 0;
-	}
-
-	dhdp->hang_reason = reason;
-
-	return net_os_send_hang_message(dev);
-}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */
-
-
-int dhd_net_wifi_platform_set_power(struct net_device *dev, bool on, unsigned long delay_msec)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	return wifi_platform_set_power(dhd->adapter, on, delay_msec);
-}
-
-bool dhd_force_country_change(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	if (dhd && dhd->pub.up)
-		return dhd->pub.force_country_change;
-	return FALSE;
-}
-void dhd_get_customized_country_code(struct net_device *dev, char *country_iso_code,
-	wl_country_t *cspec)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-#ifdef CUSTOM_COUNTRY_CODE
-	get_customized_country_code(dhd->adapter, country_iso_code, cspec,
-			dhd->pub.dhd_cflags);
-#else
-	get_customized_country_code(dhd->adapter, country_iso_code, cspec);
-#endif /* CUSTOM_COUNTRY_CODE */
-}
-void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	if (dhd && dhd->pub.up) {
-		memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t));
-#ifdef WL_CFG80211
-		wl_update_wiphybands(NULL, notify);
-#endif
-	}
-}
-
-void dhd_bus_band_set(struct net_device *dev, uint band)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	if (dhd && dhd->pub.up) {
-#ifdef WL_CFG80211
-		wl_update_wiphybands(NULL, true);
-#endif
-	}
-}
-
-int dhd_net_set_fw_path(struct net_device *dev, char *fw)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-
-	if (!fw || fw[0] == '\0')
-		return -EINVAL;
-
-	strncpy(dhd->fw_path, fw, sizeof(dhd->fw_path) - 1);
-	dhd->fw_path[sizeof(dhd->fw_path)-1] = '\0';
-
-#if defined(SOFTAP)
-	if (strstr(fw, "apsta") != NULL) {
-		DHD_INFO(("GOT APSTA FIRMWARE\n"));
-		ap_fw_loaded = TRUE;
-	} else {
-		DHD_INFO(("GOT STA FIRMWARE\n"));
-		ap_fw_loaded = FALSE;
-	}
-#endif 
-	return 0;
-}
-
-void dhd_net_if_lock(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	dhd_net_if_lock_local(dhd);
-}
-
-void dhd_net_if_unlock(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	dhd_net_if_unlock_local(dhd);
-}
-
-static void dhd_net_if_lock_local(dhd_info_t *dhd)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	if (dhd)
-		mutex_lock(&dhd->dhd_net_if_mutex);
-#endif
-}
-
-static void dhd_net_if_unlock_local(dhd_info_t *dhd)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	if (dhd)
-		mutex_unlock(&dhd->dhd_net_if_mutex);
-#endif
-}
-
-static void dhd_suspend_lock(dhd_pub_t *pub)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	if (dhd)
-		mutex_lock(&dhd->dhd_suspend_mutex);
-#endif
-}
-
-static void dhd_suspend_unlock(dhd_pub_t *pub)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	if (dhd)
-		mutex_unlock(&dhd->dhd_suspend_mutex);
-#endif
-}
-
-unsigned long dhd_os_general_spin_lock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags = 0;
-
-	if (dhd)
-		spin_lock_irqsave(&dhd->dhd_lock, flags);
-
-	return flags;
-}
-
-void dhd_os_general_spin_unlock(dhd_pub_t *pub, unsigned long flags)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd)
-		spin_unlock_irqrestore(&dhd->dhd_lock, flags);
-}
-
-/* Linux specific multipurpose spinlock API */
-void *
-dhd_os_spin_lock_init(osl_t *osh)
-{
-	/* Adding 4 bytes since the sizeof(spinlock_t) could be 0 */
-	/* if CONFIG_SMP and CONFIG_DEBUG_SPINLOCK are not defined */
-	/* and this results in kernel asserts in internal builds */
-	spinlock_t * lock = MALLOC(osh, sizeof(spinlock_t) + 4);
-	if (lock)
-		spin_lock_init(lock);
-	return ((void *)lock);
-}
-void
-dhd_os_spin_lock_deinit(osl_t *osh, void *lock)
-{
-	if (lock)
-		MFREE(osh, lock, sizeof(spinlock_t) + 4);
-}
-unsigned long
-dhd_os_spin_lock(void *lock)
-{
-	unsigned long flags = 0;
-
-	if (lock)
-		spin_lock_irqsave((spinlock_t *)lock, flags);
-
-	return flags;
-}
-void
-dhd_os_spin_unlock(void *lock, unsigned long flags)
-{
-	if (lock)
-		spin_unlock_irqrestore((spinlock_t *)lock, flags);
-}
-
-static int
-dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
-{
-	return (atomic_read(&dhd->pend_8021x_cnt));
-}
-
-#define MAX_WAIT_FOR_8021X_TX	100
-
-int
-dhd_wait_pend8021x(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int timeout = msecs_to_jiffies(10);
-	int ntimes = MAX_WAIT_FOR_8021X_TX;
-	int pend = dhd_get_pend_8021x_cnt(dhd);
-
-	while (ntimes && pend) {
-		if (pend) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			DHD_PERIM_UNLOCK(&dhd->pub);
-			schedule_timeout(timeout);
-			DHD_PERIM_LOCK(&dhd->pub);
-			set_current_state(TASK_RUNNING);
-			ntimes--;
-		}
-		pend = dhd_get_pend_8021x_cnt(dhd);
-	}
-	if (ntimes == 0)
-	{
-		atomic_set(&dhd->pend_8021x_cnt, 0);
-		DHD_ERROR(("%s: TIMEOUT\n", __FUNCTION__));
-	}
-	return pend;
-}
-
-#ifdef DHD_DEBUG
-static void
-dhd_convert_memdump_type_to_str(uint32 type, char *buf)
-{
-	char *type_str = NULL;
-
-	switch (type) {
-		case DUMP_TYPE_RESUMED_ON_TIMEOUT:
-			type_str = "resumed_on_timeout";
-			break;
-		case DUMP_TYPE_D3_ACK_TIMEOUT:
-			type_str = "D3_ACK_timeout";
-			break;
-		case DUMP_TYPE_DONGLE_TRAP:
-			type_str = "Dongle_Trap";
-			break;
-		case DUMP_TYPE_MEMORY_CORRUPTION:
-			type_str = "Memory_Corruption";
-			break;
-		case DUMP_TYPE_PKTID_AUDIT_FAILURE:
-			type_str = "PKTID_AUDIT_Fail";
-			break;
-		case DUMP_TYPE_SCAN_TIMEOUT:
-			type_str = "SCAN_timeout";
-			break;
-		case DUMP_TYPE_SCAN_BUSY:
-			type_str = "SCAN_Busy";
-			break;
-		case DUMP_TYPE_BY_SYSDUMP:
-			type_str = "BY_SYSDUMP";
-			break;
-		case DUMP_TYPE_BY_LIVELOCK:
-			type_str = "BY_LIVELOCK";
-			break;
-		case DUMP_TYPE_AP_LINKUP_FAILURE:
-			type_str = "BY_AP_LINK_FAILURE";
-			break;
-		default:
-			type_str = "Unknown_type";
-			break;
-	}
-
-	strncpy(buf, type_str, strlen(type_str));
-	buf[strlen(type_str)] = 0;
-}
-
-int
-write_to_file(dhd_pub_t *dhd, uint8 *buf, int size)
-{
-	int ret = 0;
-	struct file *fp = NULL;
-	mm_segment_t old_fs;
-	loff_t pos = 0;
-	char memdump_path[128];
-	char memdump_type[32];
-	struct timeval curtime;
-	uint32 file_mode;
-
-	/* change to KERNEL_DS address limit */
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	/* Init file name */
-	memset(memdump_path, 0, sizeof(memdump_path));
-	memset(memdump_type, 0, sizeof(memdump_type));
-	do_gettimeofday(&curtime);
-	dhd_convert_memdump_type_to_str(dhd->memdump_type, memdump_type);
-#ifdef CUSTOMER_HW4_DEBUG
-	snprintf(memdump_path, sizeof(memdump_path), "%s_%s_%ld.%ld",
-		DHD_COMMON_DUMP_PATH "mem_dump", memdump_type,
-		(unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec);
-	file_mode = O_CREAT | O_WRONLY | O_SYNC;
-#elif defined(CUSTOMER_HW2)
-	snprintf(memdump_path, sizeof(memdump_path), "%s_%s_%ld.%ld",
-		"/data/misc/wifi/mem_dump", memdump_type,
-		(unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec);
-	file_mode = O_CREAT | O_WRONLY | O_SYNC;
-#else
-	snprintf(memdump_path, sizeof(memdump_path), "%s_%s_%ld.%ld",
-		"/installmedia/mem_dump", memdump_type,
-		(unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec);
-	/* Extra flags O_DIRECT and O_SYNC are required for Brix Android, as we are
-	 * calling BUG_ON immediately after collecting the socram dump.
-	 * So the file write operation should directly write the contents into the
-	 * file instead of caching it. O_TRUNC flag ensures that file will be re-written
-	 * instead of appending.
-	 */
-	file_mode = O_CREAT | O_WRONLY | O_DIRECT | O_SYNC | O_TRUNC;
-#endif /* CUSTOMER_HW4_DEBUG */
-
-	/* print SOCRAM dump file path */
-	DHD_ERROR(("%s: memdump_path = %s\n", __FUNCTION__, memdump_path));
-
-	/* open file to write */
-	fp = filp_open(memdump_path, file_mode, 0644);
-	if (IS_ERR(fp)) {
-		ret = PTR_ERR(fp);
-		printf("%s: open file error, err = %d\n", __FUNCTION__, ret);
-		goto exit;
-	}
-
-	/* Write buf to file */
-	fp->f_op->write(fp, buf, size, &pos);
-
-exit:
-	/* close file before return */
-	if (!ret)
-		filp_close(fp, current->files);
-
-	/* restore previous address limit */
-	set_fs(old_fs);
-
-	/* free buf before return */
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP)
-	DHD_OS_PREFREE(dhd, buf, size);
-#else
-	MFREE(dhd->osh, buf, size);
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */
-
-	return ret;
-}
-#endif /* DHD_DEBUG */
-
-int dhd_os_wake_lock_timeout(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-	int ret = 0;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-		ret = dhd->wakelock_rx_timeout_enable > dhd->wakelock_ctrl_timeout_enable ?
-			dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable;
-#ifdef CONFIG_HAS_WAKELOCK
-		if (dhd->wakelock_rx_timeout_enable)
-			wake_lock_timeout(&dhd->wl_rxwake,
-				msecs_to_jiffies(dhd->wakelock_rx_timeout_enable));
-		if (dhd->wakelock_ctrl_timeout_enable)
-			wake_lock_timeout(&dhd->wl_ctrlwake,
-				msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable));
-#endif
-		dhd->wakelock_rx_timeout_enable = 0;
-		dhd->wakelock_ctrl_timeout_enable = 0;
-		spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	}
-	return ret;
-}
-
-int net_os_wake_lock_timeout(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ret = 0;
-
-	if (dhd)
-		ret = dhd_os_wake_lock_timeout(&dhd->pub);
-	return ret;
-}
-
-int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-		if (val > dhd->wakelock_rx_timeout_enable)
-			dhd->wakelock_rx_timeout_enable = val;
-		spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	}
-	return 0;
-}
-
-int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-		if (val > dhd->wakelock_ctrl_timeout_enable)
-			dhd->wakelock_ctrl_timeout_enable = val;
-		spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	}
-	return 0;
-}
-
-int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-		dhd->wakelock_ctrl_timeout_enable = 0;
-#ifdef CONFIG_HAS_WAKELOCK
-		if (wake_lock_active(&dhd->wl_ctrlwake))
-			wake_unlock(&dhd->wl_ctrlwake);
-#endif
-		spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	}
-	return 0;
-}
-
-int net_os_wake_lock_rx_timeout_enable(struct net_device *dev, int val)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ret = 0;
-
-	if (dhd)
-		ret = dhd_os_wake_lock_rx_timeout_enable(&dhd->pub, val);
-	return ret;
-}
-
-int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ret = 0;
-
-	if (dhd)
-		ret = dhd_os_wake_lock_ctrl_timeout_enable(&dhd->pub, val);
-	return ret;
-}
-
-
-#if defined(DHD_TRACE_WAKE_LOCK)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-#include <linux/hashtable.h>
-#else
-#include <linux/hash.h>
-#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */
-
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-/* Define 2^5 = 32 bucket size hash table */
-DEFINE_HASHTABLE(wklock_history, 5);
-#else
-/* Define 2^5 = 32 bucket size hash table */
-struct hlist_head wklock_history[32] = { [0 ... 31] = HLIST_HEAD_INIT };
-#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */
-
-int trace_wklock_onoff = 1;
-
-typedef enum dhd_wklock_type {
-	DHD_WAKE_LOCK,
-	DHD_WAKE_UNLOCK,
-	DHD_WAIVE_LOCK,
-	DHD_RESTORE_LOCK
-} dhd_wklock_t;
-
-struct wk_trace_record {
-	unsigned long addr;	            /* Address of the instruction */
-	dhd_wklock_t lock_type;         /* lock_type */
-	unsigned long long counter;		/* counter information */
-	struct hlist_node wklock_node;  /* hash node */
-};
-
-
-static struct wk_trace_record *find_wklock_entry(unsigned long addr)
-{
-	struct wk_trace_record *wklock_info;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-	hash_for_each_possible(wklock_history, wklock_info, wklock_node, addr)
-#else
-	struct hlist_node *entry;
-	int index = hash_long(addr, ilog2(ARRAY_SIZE(wklock_history)));
-	hlist_for_each_entry(wklock_info, entry, &wklock_history[index], wklock_node)
-#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */
-	{
-		if (wklock_info->addr == addr) {
-			return wklock_info;
-		}
-	}
-	return NULL;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-#define HASH_ADD(hashtable, node, key) \
-	do { \
-		hash_add(hashtable, node, key); \
-	} while (0);
-#else
-#define HASH_ADD(hashtable, node, key) \
-	do { \
-		int index = hash_long(key, ilog2(ARRAY_SIZE(hashtable))); \
-		hlist_add_head(node, &hashtable[index]); \
-	} while (0);
-#endif /* KERNEL_VER < KERNEL_VERSION(3, 7, 0) */
-
-#define STORE_WKLOCK_RECORD(wklock_type) \
-	do { \
-		struct wk_trace_record *wklock_info = NULL; \
-		unsigned long func_addr = (unsigned long)__builtin_return_address(0); \
-		wklock_info = find_wklock_entry(func_addr); \
-		if (wklock_info) { \
-			if (wklock_type == DHD_WAIVE_LOCK || wklock_type == DHD_RESTORE_LOCK) { \
-				wklock_info->counter = dhd->wakelock_counter; \
-			} else { \
-				wklock_info->counter++; \
-			} \
-		} else { \
-			wklock_info = kzalloc(sizeof(*wklock_info), GFP_ATOMIC); \
-			if (!wklock_info) {\
-				printk("Can't allocate wk_trace_record \n"); \
-			} else { \
-				wklock_info->addr = func_addr; \
-				wklock_info->lock_type = wklock_type; \
-				if (wklock_type == DHD_WAIVE_LOCK || \
-						wklock_type == DHD_RESTORE_LOCK) { \
-					wklock_info->counter = dhd->wakelock_counter; \
-				} else { \
-					wklock_info->counter++; \
-				} \
-				HASH_ADD(wklock_history, &wklock_info->wklock_node, func_addr); \
-			} \
-		} \
-	} while (0);
-
-static inline void dhd_wk_lock_rec_dump(void)
-{
-	int bkt;
-	struct wk_trace_record *wklock_info;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-	hash_for_each(wklock_history, bkt, wklock_info, wklock_node)
-#else
-	struct hlist_node *entry = NULL;
-	int max_index = ARRAY_SIZE(wklock_history);
-	for (bkt = 0; bkt < max_index; bkt++)
-		hlist_for_each_entry(wklock_info, entry, &wklock_history[bkt], wklock_node)
-#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */
-		{
-			switch (wklock_info->lock_type) {
-				case DHD_WAKE_LOCK:
-					DHD_ERROR(("wakelock lock : %pS  lock_counter : %llu\n",
-						(void *)wklock_info->addr, wklock_info->counter));
-					break;
-				case DHD_WAKE_UNLOCK:
-					DHD_ERROR(("wakelock unlock : %pS, unlock_counter : %llu\n",
-						(void *)wklock_info->addr, wklock_info->counter));
-					break;
-				case DHD_WAIVE_LOCK:
-					DHD_ERROR(("wakelock waive : %pS  before_waive : %llu\n",
-						(void *)wklock_info->addr, wklock_info->counter));
-					break;
-				case DHD_RESTORE_LOCK:
-					DHD_ERROR(("wakelock restore : %pS, after_waive : %llu\n",
-						(void *)wklock_info->addr, wklock_info->counter));
-					break;
-			}
-		}
-}
-
-static void dhd_wk_lock_trace_init(struct dhd_info *dhd)
-{
-	unsigned long flags;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
-	int i;
-#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */
-
-	spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-	hash_init(wklock_history);
-#else
-	for (i = 0; i < ARRAY_SIZE(wklock_history); i++)
-		INIT_HLIST_HEAD(&wklock_history[i]);
-#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */
-	spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-}
-
-static void dhd_wk_lock_trace_deinit(struct dhd_info *dhd)
-{
-	int bkt;
-	struct wk_trace_record *wklock_info;
-	struct hlist_node *tmp;
-	unsigned long flags;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
-	struct hlist_node *entry = NULL;
-	int max_index = ARRAY_SIZE(wklock_history);
-#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */
-
-	spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-	hash_for_each_safe(wklock_history, bkt, tmp, wklock_info, wklock_node)
-#else
-	for (bkt = 0; bkt < max_index; bkt++)
-		hlist_for_each_entry_safe(wklock_info, entry, tmp,
-			&wklock_history[bkt], wklock_node)
-#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0)) */
-		{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-			hash_del(&wklock_info->wklock_node);
-#else
-			hlist_del_init(&wklock_info->wklock_node);
-#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0)) */
-			kfree(wklock_info);
-		}
-	spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-}
-
-void dhd_wk_lock_stats_dump(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
-	unsigned long flags;
-
-	DHD_ERROR((KERN_ERR"DHD Printing wl_wake Lock/Unlock Record \r\n"));
-	spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-	dhd_wk_lock_rec_dump();
-	spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	DHD_ERROR((KERN_ERR"Event wakelock counter %u\n", dhd->wakelock_event_counter));
-}
-#else
-#define STORE_WKLOCK_RECORD(wklock_type)
-#endif /* ! DHD_TRACE_WAKE_LOCK */
-
-int dhd_os_wake_lock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-	int ret = 0;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-		if (dhd->wakelock_counter == 0 && !dhd->waive_wakelock) {
-#ifdef CONFIG_HAS_WAKELOCK
-			wake_lock(&dhd->wl_wifi);
-#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-			dhd_bus_dev_pm_stay_awake(pub);
-#endif
-		}
-#ifdef DHD_TRACE_WAKE_LOCK
-		if (trace_wklock_onoff) {
-			STORE_WKLOCK_RECORD(DHD_WAKE_LOCK);
-		}
-#endif /* DHD_TRACE_WAKE_LOCK */
-		dhd->wakelock_counter++;
-		ret = dhd->wakelock_counter;
-		spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	}
-
-	return ret;
-}
-
-int dhd_event_wake_lock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-	int ret = 0;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_evt_spinlock, flags);
-		if (dhd->wakelock_event_counter == 0) {
-#ifdef CONFIG_HAS_WAKELOCK
-			wake_lock(&dhd->wl_evtwake);
-#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-			dhd_bus_dev_pm_stay_awake(pub);
-#endif
-		}
-		dhd->wakelock_event_counter++;
-		ret = dhd->wakelock_event_counter;
-		spin_unlock_irqrestore(&dhd->wakelock_evt_spinlock, flags);
-	}
-
-	return ret;
-}
-
-int net_os_wake_lock(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ret = 0;
-
-	if (dhd)
-		ret = dhd_os_wake_lock(&dhd->pub);
-	return ret;
-}
-
-int dhd_os_wake_unlock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-	int ret = 0;
-
-	dhd_os_wake_lock_timeout(pub);
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-
-		if (dhd->wakelock_counter > 0) {
-			dhd->wakelock_counter--;
-#ifdef DHD_TRACE_WAKE_LOCK
-			if (trace_wklock_onoff) {
-				STORE_WKLOCK_RECORD(DHD_WAKE_UNLOCK);
-			}
-#endif /* DHD_TRACE_WAKE_LOCK */
-			if (dhd->wakelock_counter == 0 && !dhd->waive_wakelock) {
-#ifdef CONFIG_HAS_WAKELOCK
-				wake_unlock(&dhd->wl_wifi);
-#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-				dhd_bus_dev_pm_relax(pub);
-#endif
-			}
-			ret = dhd->wakelock_counter;
-		}
-		spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	}
-	return ret;
-}
-
-int dhd_event_wake_unlock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-	int ret = 0;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_evt_spinlock, flags);
-
-		if (dhd->wakelock_event_counter > 0) {
-			dhd->wakelock_event_counter--;
-			if (dhd->wakelock_event_counter == 0) {
-#ifdef CONFIG_HAS_WAKELOCK
-				wake_unlock(&dhd->wl_evtwake);
-#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-				dhd_bus_dev_pm_relax(pub);
-#endif
-			}
-			ret = dhd->wakelock_event_counter;
-		}
-		spin_unlock_irqrestore(&dhd->wakelock_evt_spinlock, flags);
-	}
-	return ret;
-}
-
-int dhd_os_check_wakelock(dhd_pub_t *pub)
-{
-#if defined(CONFIG_HAS_WAKELOCK) || (defined(BCMSDIO) && (LINUX_VERSION_CODE > \
-	KERNEL_VERSION(2, 6, 36)))
-	dhd_info_t *dhd;
-
-	if (!pub)
-		return 0;
-	dhd = (dhd_info_t *)(pub->info);
-#endif /* CONFIG_HAS_WAKELOCK || BCMSDIO */
-
-#ifdef CONFIG_HAS_WAKELOCK
-	/* Indicate to the SD Host to avoid going to suspend if internal locks are up */
-	if (dhd && (wake_lock_active(&dhd->wl_wifi) ||
-		(wake_lock_active(&dhd->wl_wdwake))))
-		return 1;
-#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-	if (dhd && (dhd->wakelock_counter > 0) && dhd_bus_dev_pm_enabled(pub))
-		return 1;
-#endif
-	return 0;
-}
-
-int
-dhd_os_check_wakelock_all(dhd_pub_t *pub)
-{
-#ifdef CONFIG_HAS_WAKELOCK
-	int l1, l2, l3, l4, l7;
-	int l5 = 0, l6 = 0;
-	int c, lock_active;
-#endif /* CONFIG_HAS_WAKELOCK */
-#if defined(CONFIG_HAS_WAKELOCK) || (defined(BCMSDIO) && (LINUX_VERSION_CODE > \
-	KERNEL_VERSION(2, 6, 36)))
-	dhd_info_t *dhd;
-
-	if (!pub) {
-		return 0;
-	}
-	dhd = (dhd_info_t *)(pub->info);
-	if (!dhd) {
-		return 0;
-	}
-#endif /* CONFIG_HAS_WAKELOCK || BCMSDIO */
-
-#ifdef CONFIG_HAS_WAKELOCK
-	c = dhd->wakelock_counter;
-	l1 = wake_lock_active(&dhd->wl_wifi);
-	l2 = wake_lock_active(&dhd->wl_wdwake);
-	l3 = wake_lock_active(&dhd->wl_rxwake);
-	l4 = wake_lock_active(&dhd->wl_ctrlwake);
-#ifdef BCMPCIE_OOB_HOST_WAKE
-	l5 = wake_lock_active(&dhd->wl_intrwake);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-#ifdef DHD_USE_SCAN_WAKELOCK
-	l6 = wake_lock_active(&dhd->wl_scanwake);
-#endif /* DHD_USE_SCAN_WAKELOCK */
-	l7 = wake_lock_active(&dhd->wl_evtwake);
-	lock_active = (l1 || l2 || l3 || l4 || l5 || l6 || l7);
-
-	/* Indicate to the Host to avoid going to suspend if internal locks are up */
-	if (dhd && lock_active) {
-		DHD_ERROR(("%s wakelock c-%d wl-%d wd-%d rx-%d "
-			"ctl-%d intr-%d scan-%d evt-%d\n",
-			__FUNCTION__, c, l1, l2, l3, l4, l5, l6, l7));
-		return 1;
-	}
-#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-	if (dhd && (dhd->wakelock_counter > 0) && dhd_bus_dev_pm_enabled(pub)) {
-		return 1;
-	}
-#endif /* CONFIG_HAS_WAKELOCK */
-	return 0;
-}
-
-int net_os_wake_unlock(struct net_device *dev)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(dev);
-	int ret = 0;
-
-	if (dhd)
-		ret = dhd_os_wake_unlock(&dhd->pub);
-	return ret;
-}
-
-int dhd_os_wd_wake_lock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-	int ret = 0;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-#ifdef CONFIG_HAS_WAKELOCK
-		/* if wakelock_wd_counter was never used : lock it at once */
-		if (!dhd->wakelock_wd_counter)
-			wake_lock(&dhd->wl_wdwake);
-#endif
-		dhd->wakelock_wd_counter++;
-		ret = dhd->wakelock_wd_counter;
-		spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	}
-	return ret;
-}
-
-int dhd_os_wd_wake_unlock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-	int ret = 0;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-		if (dhd->wakelock_wd_counter) {
-			dhd->wakelock_wd_counter = 0;
-#ifdef CONFIG_HAS_WAKELOCK
-			wake_unlock(&dhd->wl_wdwake);
-#endif
-		}
-		spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	}
-	return ret;
-}
-
-#ifdef BCMPCIE_OOB_HOST_WAKE
-void
-dhd_os_oob_irq_wake_lock_timeout(dhd_pub_t *pub, int val)
-{
-#ifdef CONFIG_HAS_WAKELOCK
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-		wake_lock_timeout(&dhd->wl_intrwake, msecs_to_jiffies(val));
-	}
-#endif /* CONFIG_HAS_WAKELOCK */
-}
-
-void
-dhd_os_oob_irq_wake_unlock(dhd_pub_t *pub)
-{
-#ifdef CONFIG_HAS_WAKELOCK
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-		/* if wl_intrwake is active, unlock it */
-		if (wake_lock_active(&dhd->wl_intrwake)) {
-			wake_unlock(&dhd->wl_intrwake);
-		}
-	}
-#endif /* CONFIG_HAS_WAKELOCK */
-}
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-
-#ifdef DHD_USE_SCAN_WAKELOCK
-void
-dhd_os_scan_wake_lock_timeout(dhd_pub_t *pub, int val)
-{
-#ifdef CONFIG_HAS_WAKELOCK
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-		wake_lock_timeout(&dhd->wl_scanwake, msecs_to_jiffies(val));
-	}
-#endif /* CONFIG_HAS_WAKELOCK */
-}
-
-void
-dhd_os_scan_wake_unlock(dhd_pub_t *pub)
-{
-#ifdef CONFIG_HAS_WAKELOCK
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-
-	if (dhd) {
-		/* if wl_scanwake is active, unlock it */
-		if (wake_lock_active(&dhd->wl_scanwake)) {
-			wake_unlock(&dhd->wl_scanwake);
-		}
-	}
-#endif /* CONFIG_HAS_WAKELOCK */
-}
-#endif /* DHD_USE_SCAN_WAKELOCK */
-
-/* waive wakelocks for operations such as IOVARs in suspend function, must be closed
- * by a paired function call to dhd_wakelock_restore. returns current wakelock counter
- */
-int dhd_os_wake_lock_waive(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-	int ret = 0;
-
-	if (dhd) {
-		spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-
-		/* dhd_wakelock_waive/dhd_wakelock_restore must be paired */
-		if (dhd->waive_wakelock == FALSE) {
-#ifdef DHD_TRACE_WAKE_LOCK
-			if (trace_wklock_onoff) {
-				STORE_WKLOCK_RECORD(DHD_WAIVE_LOCK);
-			}
-#endif /* DHD_TRACE_WAKE_LOCK */
-			/* record current lock status */
-			dhd->wakelock_before_waive = dhd->wakelock_counter;
-			dhd->waive_wakelock = TRUE;
-		}
-		ret = dhd->wakelock_wd_counter;
-		spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	}
-	return ret;
-}
-
-int dhd_os_wake_lock_restore(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-	unsigned long flags;
-	int ret = 0;
-
-	if (!dhd)
-		return 0;
-
-	spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-
-	/* dhd_wakelock_waive/dhd_wakelock_restore must be paired */
-	if (!dhd->waive_wakelock)
-		goto exit;
-
-	dhd->waive_wakelock = FALSE;
-	/* if somebody else acquires wakelock between dhd_wakelock_waive/dhd_wakelock_restore,
-	 * we need to make it up by calling wake_lock or pm_stay_awake. or if somebody releases
-	 * the lock in between, do the same by calling wake_unlock or pm_relax
-	 */
-#ifdef DHD_TRACE_WAKE_LOCK
-	if (trace_wklock_onoff) {
-		STORE_WKLOCK_RECORD(DHD_RESTORE_LOCK);
-	}
-#endif /* DHD_TRACE_WAKE_LOCK */
-
-	if (dhd->wakelock_before_waive == 0 && dhd->wakelock_counter > 0) {
-#ifdef CONFIG_HAS_WAKELOCK
-		wake_lock(&dhd->wl_wifi);
-#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-		dhd_bus_dev_pm_stay_awake(&dhd->pub);
-#endif
-	} else if (dhd->wakelock_before_waive > 0 && dhd->wakelock_counter == 0) {
-#ifdef CONFIG_HAS_WAKELOCK
-		wake_unlock(&dhd->wl_wifi);
-#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
-		dhd_bus_dev_pm_relax(&dhd->pub);
-#endif
-	}
-	dhd->wakelock_before_waive = 0;
-exit:
-	ret = dhd->wakelock_wd_counter;
-	spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	return ret;
-}
-
-void dhd_os_wake_lock_init(struct dhd_info *dhd)
-{
-	DHD_TRACE(("%s: initialize wake_lock_counters\n", __FUNCTION__));
-	dhd->wakelock_event_counter = 0;
-	dhd->wakelock_counter = 0;
-	dhd->wakelock_rx_timeout_enable = 0;
-	dhd->wakelock_ctrl_timeout_enable = 0;
-#ifdef CONFIG_HAS_WAKELOCK
-	wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
-	wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake");
-	wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake");
-	wake_lock_init(&dhd->wl_evtwake, WAKE_LOCK_SUSPEND, "wlan_evt_wake");
-#ifdef BCMPCIE_OOB_HOST_WAKE
-	wake_lock_init(&dhd->wl_intrwake, WAKE_LOCK_SUSPEND, "wlan_oob_irq_wake");
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-#ifdef DHD_USE_SCAN_WAKELOCK
-	wake_lock_init(&dhd->wl_scanwake, WAKE_LOCK_SUSPEND, "wlan_scan_wake");
-#endif /* DHD_USE_SCAN_WAKELOCK */
-#endif /* CONFIG_HAS_WAKELOCK */
-#ifdef DHD_TRACE_WAKE_LOCK
-	dhd_wk_lock_trace_init(dhd);
-#endif /* DHD_TRACE_WAKE_LOCK */
-}
-
-void dhd_os_wake_lock_destroy(struct dhd_info *dhd)
-{
-	DHD_TRACE(("%s: deinit wake_lock_counters\n", __FUNCTION__));
-#ifdef CONFIG_HAS_WAKELOCK
-	dhd->wakelock_event_counter = 0;
-	dhd->wakelock_counter = 0;
-	dhd->wakelock_rx_timeout_enable = 0;
-	dhd->wakelock_ctrl_timeout_enable = 0;
-	wake_lock_destroy(&dhd->wl_wifi);
-	wake_lock_destroy(&dhd->wl_rxwake);
-	wake_lock_destroy(&dhd->wl_ctrlwake);
-	wake_lock_destroy(&dhd->wl_evtwake);
-#ifdef BCMPCIE_OOB_HOST_WAKE
-	wake_lock_destroy(&dhd->wl_intrwake);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-#ifdef DHD_USE_SCAN_WAKELOCK
-	wake_lock_destroy(&dhd->wl_scanwake);
-#endif /* DHD_USE_SCAN_WAKELOCK */
-#ifdef DHD_TRACE_WAKE_LOCK
-	dhd_wk_lock_trace_deinit(dhd);
-#endif /* DHD_TRACE_WAKE_LOCK */
-#endif /* CONFIG_HAS_WAKELOCK */
-}
-
-bool dhd_os_check_if_up(dhd_pub_t *pub)
-{
-	if (!pub)
-		return FALSE;
-	return pub->up;
-}
-
-#if defined(BCMSDIO)
-/* function to collect firmware, chip id and chip version info */
-void dhd_set_version_info(dhd_pub_t *dhdp, char *fw)
-{
-	int i;
-
-	i = snprintf(info_string, sizeof(info_string),
-		"  Driver: %s\n  Firmware: %s ", EPI_VERSION_STR, fw);
-
-	if (!dhdp)
-		return;
-
-	i = snprintf(&info_string[i], sizeof(info_string) - i,
-		"\n  Chip: %x Rev %x Pkg %x", dhd_bus_chip_id(dhdp),
-		dhd_bus_chiprev_id(dhdp), dhd_bus_chippkg_id(dhdp));
-}
-#endif /* defined(BCMSDIO) */
-int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd)
-{
-	int ifidx;
-	int ret = 0;
-	dhd_info_t *dhd = NULL;
-
-	if (!net || !DEV_PRIV(net)) {
-		DHD_ERROR(("%s invalid parameter\n", __FUNCTION__));
-		return -EINVAL;
-	}
-
-	dhd = DHD_DEV_INFO(net);
-	if (!dhd)
-		return -EINVAL;
-
-	ifidx = dhd_net2idx(dhd, net);
-	if (ifidx == DHD_BAD_IF) {
-		DHD_ERROR(("%s bad ifidx\n", __FUNCTION__));
-		return -ENODEV;
-	}
-
-	DHD_OS_WAKE_LOCK(&dhd->pub);
-	DHD_PERIM_LOCK(&dhd->pub);
-
-	ret = dhd_wl_ioctl(&dhd->pub, ifidx, ioc, ioc->buf, ioc->len);
-	dhd_check_hang(net, &dhd->pub, ret);
-
-	DHD_PERIM_UNLOCK(&dhd->pub);
-	DHD_OS_WAKE_UNLOCK(&dhd->pub);
-
-	return ret;
-}
-
-bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret)
-{
-	struct net_device *net;
-
-	net = dhd_idx2net(dhdp, ifidx);
-	if (!net) {
-		DHD_ERROR(("%s : Invalid index : %d\n", __FUNCTION__, ifidx));
-		return -EINVAL;
-	}
-
-	return dhd_check_hang(net, dhdp, ret);
-}
-
-/* Return instance */
-int dhd_get_instance(dhd_pub_t *dhdp)
-{
-	return dhdp->info->unit;
-}
-
-
-#ifdef PROP_TXSTATUS
-
-void dhd_wlfc_plat_init(void *dhd)
-{
-#ifdef USE_DYNAMIC_F2_BLKSIZE
-	dhdsdio_func_blocksize((dhd_pub_t *)dhd, 2, DYNAMIC_F2_BLKSIZE_FOR_NONLEGACY);
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
-	return;
-}
-
-void dhd_wlfc_plat_deinit(void *dhd)
-{
-#ifdef USE_DYNAMIC_F2_BLKSIZE
-	dhdsdio_func_blocksize((dhd_pub_t *)dhd, 2, sd_f2_blocksize);
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
-	return;
-}
-
-bool dhd_wlfc_skip_fc(void)
-{
-#ifdef SKIP_WLFC_ON_CONCURRENT
-#ifdef WL_CFG80211
-
-	/* enable flow control in vsdb mode */
-	return !(wl_cfg80211_is_concurrent_mode());
-#else
-	return TRUE; /* skip flow control */
-#endif /* WL_CFG80211 */
-
-#else
-	return FALSE;
-#endif /* SKIP_WLFC_ON_CONCURRENT */
-}
-#endif /* PROP_TXSTATUS */
-
-#ifdef BCMDBGFS
-#include <linux/debugfs.h>
-
-typedef struct dhd_dbgfs {
-	struct dentry	*debugfs_dir;
-	struct dentry	*debugfs_mem;
-	dhd_pub_t	*dhdp;
-	uint32		size;
-} dhd_dbgfs_t;
-
-dhd_dbgfs_t g_dbgfs;
-
-extern uint32 dhd_readregl(void *bp, uint32 addr);
-extern uint32 dhd_writeregl(void *bp, uint32 addr, uint32 data);
-
-static int
-dhd_dbg_state_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static ssize_t
-dhd_dbg_state_read(struct file *file, char __user *ubuf,
-                       size_t count, loff_t *ppos)
-{
-	ssize_t rval;
-	uint32 tmp;
-	loff_t pos = *ppos;
-	size_t ret;
-
-	if (pos < 0)
-		return -EINVAL;
-	if (pos >= g_dbgfs.size || !count)
-		return 0;
-	if (count > g_dbgfs.size - pos)
-		count = g_dbgfs.size - pos;
-
-	/* Basically enforce aligned 4 byte reads. It's up to the user to work out the details */
-	tmp = dhd_readregl(g_dbgfs.dhdp->bus, file->f_pos & (~3));
-
-	ret = copy_to_user(ubuf, &tmp, 4);
-	if (ret == count)
-		return -EFAULT;
-
-	count -= ret;
-	*ppos = pos + count;
-	rval = count;
-
-	return rval;
-}
-
-
-static ssize_t
-dhd_debugfs_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos)
-{
-	loff_t pos = *ppos;
-	size_t ret;
-	uint32 buf;
-
-	if (pos < 0)
-		return -EINVAL;
-	if (pos >= g_dbgfs.size || !count)
-		return 0;
-	if (count > g_dbgfs.size - pos)
-		count = g_dbgfs.size - pos;
-
-	ret = copy_from_user(&buf, ubuf, sizeof(uint32));
-	if (ret == count)
-		return -EFAULT;
-
-	/* Basically enforce aligned 4 byte writes. It's up to the user to work out the details */
-	dhd_writeregl(g_dbgfs.dhdp->bus, file->f_pos & (~3), buf);
-
-	return count;
-}
-
-
-loff_t
-dhd_debugfs_lseek(struct file *file, loff_t off, int whence)
-{
-	loff_t pos = -1;
-
-	switch (whence) {
-		case 0:
-			pos = off;
-			break;
-		case 1:
-			pos = file->f_pos + off;
-			break;
-		case 2:
-			pos = g_dbgfs.size - off;
-	}
-	return (pos < 0 || pos > g_dbgfs.size) ? -EINVAL : (file->f_pos = pos);
-}
-
-static const struct file_operations dhd_dbg_state_ops = {
-	.read   = dhd_dbg_state_read,
-	.write	= dhd_debugfs_write,
-	.open   = dhd_dbg_state_open,
-	.llseek	= dhd_debugfs_lseek
-};
-
-static void dhd_dbg_create(void)
-{
-	if (g_dbgfs.debugfs_dir) {
-		g_dbgfs.debugfs_mem = debugfs_create_file("mem", 0644, g_dbgfs.debugfs_dir,
-			NULL, &dhd_dbg_state_ops);
-	}
-}
-
-void dhd_dbg_init(dhd_pub_t *dhdp)
-{
-	g_dbgfs.dhdp = dhdp;
-	g_dbgfs.size = 0x20000000; /* Allow access to various cores regs */
-
-	g_dbgfs.debugfs_dir = debugfs_create_dir("dhd", 0);
-	if (IS_ERR(g_dbgfs.debugfs_dir)) {
-		g_dbgfs.debugfs_dir = NULL;
-		return;
-	}
-
-	dhd_dbg_create();
-
-	return;
-}
-
-void dhd_dbg_remove(void)
-{
-	debugfs_remove(g_dbgfs.debugfs_mem);
-	debugfs_remove(g_dbgfs.debugfs_dir);
-
-	bzero((unsigned char *) &g_dbgfs, sizeof(g_dbgfs));
-}
-#endif /* BCMDBGFS */
-
-#ifdef WLMEDIA_HTSF
-
-static
-void dhd_htsf_addtxts(dhd_pub_t *dhdp, void *pktbuf)
-{
-	dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
-	struct sk_buff *skb;
-	uint32 htsf = 0;
-	uint16 dport = 0, oldmagic = 0xACAC;
-	char *p1;
-	htsfts_t ts;
-
-	/*  timestamp packet  */
-
-	p1 = (char*) PKTDATA(dhdp->osh, pktbuf);
-
-	if (PKTLEN(dhdp->osh, pktbuf) > HTSF_MINLEN) {
-/*		memcpy(&proto, p1+26, 4);  	*/
-		memcpy(&dport, p1+40, 2);
-/* 	proto = ((ntoh32(proto))>> 16) & 0xFF;  */
-		dport = ntoh16(dport);
-	}
-
-	/* timestamp only if  icmp or udb iperf with port 5555 */
-/*	if (proto == 17 && dport == tsport) { */
-	if (dport >= tsport && dport <= tsport + 20) {
-
-		skb = (struct sk_buff *) pktbuf;
-
-		htsf = dhd_get_htsf(dhd, 0);
-		memset(skb->data + 44, 0, 2); /* clear checksum */
-		memcpy(skb->data+82, &oldmagic, 2);
-		memcpy(skb->data+84, &htsf, 4);
-
-		memset(&ts, 0, sizeof(htsfts_t));
-		ts.magic  = HTSFMAGIC;
-		ts.prio   = PKTPRIO(pktbuf);
-		ts.seqnum = htsf_seqnum++;
-		ts.c10    = get_cycles();
-		ts.t10    = htsf;
-		ts.endmagic = HTSFENDMAGIC;
-
-		memcpy(skb->data + HTSF_HOSTOFFSET, &ts, sizeof(ts));
-	}
-}
-
-static void dhd_dump_htsfhisto(histo_t *his, char *s)
-{
-	int pktcnt = 0, curval = 0, i;
-	for (i = 0; i < (NUMBIN-2); i++) {
-		curval += 500;
-		printf("%d ",  his->bin[i]);
-		pktcnt += his->bin[i];
-	}
-	printf(" max: %d TotPkt: %d neg: %d [%s]\n", his->bin[NUMBIN-2], pktcnt,
-		his->bin[NUMBIN-1], s);
-}
-
-static
-void sorttobin(int value, histo_t *histo)
-{
-	int i, binval = 0;
-
-	if (value < 0) {
-		histo->bin[NUMBIN-1]++;
-		return;
-	}
-	if (value > histo->bin[NUMBIN-2])  /* store the max value  */
-		histo->bin[NUMBIN-2] = value;
-
-	for (i = 0; i < (NUMBIN-2); i++) {
-		binval += 500; /* 500m s bins */
-		if (value <= binval) {
-			histo->bin[i]++;
-			return;
-		}
-	}
-	histo->bin[NUMBIN-3]++;
-}
-
-static
-void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf)
-{
-	dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
-	struct sk_buff *skb;
-	char *p1;
-	uint16 old_magic;
-	int d1, d2, d3, end2end;
-	htsfts_t *htsf_ts;
-	uint32 htsf;
-
-	skb = PKTTONATIVE(dhdp->osh, pktbuf);
-	p1 = (char*)PKTDATA(dhdp->osh, pktbuf);
-
-	if (PKTLEN(osh, pktbuf) > HTSF_MINLEN) {
-		memcpy(&old_magic, p1+78, 2);
-		htsf_ts = (htsfts_t*) (p1 + HTSF_HOSTOFFSET - 4);
-	} else {
-		return;
-	}
-	if (htsf_ts->magic == HTSFMAGIC) {
-		htsf_ts->tE0 = dhd_get_htsf(dhd, 0);
-		htsf_ts->cE0 = get_cycles();
-	}
-
-	if (old_magic == 0xACAC) {
-
-		tspktcnt++;
-		htsf = dhd_get_htsf(dhd, 0);
-		memcpy(skb->data+92, &htsf, sizeof(uint32));
-
-		memcpy(&ts[tsidx].t1, skb->data+80, 16);
-
-		d1 = ts[tsidx].t2 - ts[tsidx].t1;
-		d2 = ts[tsidx].t3 - ts[tsidx].t2;
-		d3 = ts[tsidx].t4 - ts[tsidx].t3;
-		end2end = ts[tsidx].t4 - ts[tsidx].t1;
-
-		sorttobin(d1, &vi_d1);
-		sorttobin(d2, &vi_d2);
-		sorttobin(d3, &vi_d3);
-		sorttobin(end2end, &vi_d4);
-
-		if (end2end > 0 && end2end >  maxdelay) {
-			maxdelay = end2end;
-			maxdelaypktno = tspktcnt;
-			memcpy(&maxdelayts, &ts[tsidx], 16);
-		}
-		if (++tsidx >= TSMAX)
-			tsidx = 0;
-	}
-}
-
-uint32 dhd_get_htsf(dhd_info_t *dhd, int ifidx)
-{
-	uint32 htsf = 0, cur_cycle, delta, delta_us;
-	uint32    factor, baseval, baseval2;
-	cycles_t t;
-
-	t = get_cycles();
-	cur_cycle = t;
-
-	if (cur_cycle >  dhd->htsf.last_cycle) {
-		delta = cur_cycle -  dhd->htsf.last_cycle;
-	} else {
-		delta = cur_cycle + (0xFFFFFFFF -  dhd->htsf.last_cycle);
-	}
-
-	delta = delta >> 4;
-
-	if (dhd->htsf.coef) {
-		/* times ten to get the first digit */
-	        factor = (dhd->htsf.coef*10 + dhd->htsf.coefdec1);
-		baseval  = (delta*10)/factor;
-		baseval2 = (delta*10)/(factor+1);
-		delta_us  = (baseval -  (((baseval - baseval2) * dhd->htsf.coefdec2)) / 10);
-		htsf = (delta_us << 4) +  dhd->htsf.last_tsf + HTSF_BUS_DELAY;
-	} else {
-		DHD_ERROR(("-------dhd->htsf.coef = 0 -------\n"));
-	}
-
-	return htsf;
-}
-
-static void dhd_dump_latency(void)
-{
-	int i, max = 0;
-	int d1, d2, d3, d4, d5;
-
-	printf("T1       T2       T3       T4           d1  d2   t4-t1     i    \n");
-	for (i = 0; i < TSMAX; i++) {
-		d1 = ts[i].t2 - ts[i].t1;
-		d2 = ts[i].t3 - ts[i].t2;
-		d3 = ts[i].t4 - ts[i].t3;
-		d4 = ts[i].t4 - ts[i].t1;
-		d5 = ts[max].t4-ts[max].t1;
-		if (d4 > d5 && d4 > 0)  {
-			max = i;
-		}
-		printf("%08X %08X %08X %08X \t%d %d %d   %d i=%d\n",
-			ts[i].t1, ts[i].t2, ts[i].t3, ts[i].t4,
-			d1, d2, d3, d4, i);
-	}
-
-	printf("current idx = %d \n", tsidx);
-
-	printf("Highest latency %d pkt no.%d total=%d\n", maxdelay, maxdelaypktno, tspktcnt);
-	printf("%08X %08X %08X %08X \t%d %d %d   %d\n",
-	maxdelayts.t1, maxdelayts.t2, maxdelayts.t3, maxdelayts.t4,
-	maxdelayts.t2 - maxdelayts.t1,
-	maxdelayts.t3 - maxdelayts.t2,
-	maxdelayts.t4 - maxdelayts.t3,
-	maxdelayts.t4 - maxdelayts.t1);
-}
-
-
-static int
-dhd_ioctl_htsf_get(dhd_info_t *dhd, int ifidx)
-{
-	wl_ioctl_t ioc;
-	char buf[32];
-	int ret;
-	uint32 s1, s2;
-
-	struct tsf {
-		uint32 low;
-		uint32 high;
-	} tsf_buf;
-
-	memset(&ioc, 0, sizeof(ioc));
-	memset(&tsf_buf, 0, sizeof(tsf_buf));
-
-	ioc.cmd = WLC_GET_VAR;
-	ioc.buf = buf;
-	ioc.len = (uint)sizeof(buf);
-	ioc.set = FALSE;
-
-	strncpy(buf, "tsf", sizeof(buf) - 1);
-	buf[sizeof(buf) - 1] = '\0';
-	s1 = dhd_get_htsf(dhd, 0);
-	if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) {
-		if (ret == -EIO) {
-			DHD_ERROR(("%s: tsf is not supported by device\n",
-				dhd_ifname(&dhd->pub, ifidx)));
-			return -EOPNOTSUPP;
-		}
-		return ret;
-	}
-	s2 = dhd_get_htsf(dhd, 0);
-
-	memcpy(&tsf_buf, buf, sizeof(tsf_buf));
-	printf(" TSF_h=%04X lo=%08X Calc:htsf=%08X, coef=%d.%d%d delta=%d ",
-		tsf_buf.high, tsf_buf.low, s2, dhd->htsf.coef, dhd->htsf.coefdec1,
-		dhd->htsf.coefdec2, s2-tsf_buf.low);
-	printf("lasttsf=%08X lastcycle=%08X\n", dhd->htsf.last_tsf, dhd->htsf.last_cycle);
-	return 0;
-}
-
-void htsf_update(dhd_info_t *dhd, void *data)
-{
-	static ulong  cur_cycle = 0, prev_cycle = 0;
-	uint32 htsf, tsf_delta = 0;
-	uint32 hfactor = 0, cyc_delta, dec1 = 0, dec2, dec3, tmp;
-	ulong b, a;
-	cycles_t t;
-
-	/* cycles_t in inlcude/mips/timex.h */
-
-	t = get_cycles();
-
-	prev_cycle = cur_cycle;
-	cur_cycle = t;
-
-	if (cur_cycle > prev_cycle)
-		cyc_delta = cur_cycle - prev_cycle;
-	else {
-		b = cur_cycle;
-		a = prev_cycle;
-		cyc_delta = cur_cycle + (0xFFFFFFFF - prev_cycle);
-	}
-
-	if (data == NULL)
-		printf(" tsf update ata point er is null \n");
-
-	memcpy(&prev_tsf, &cur_tsf, sizeof(tsf_t));
-	memcpy(&cur_tsf, data, sizeof(tsf_t));
-
-	if (cur_tsf.low == 0) {
-		DHD_INFO((" ---- 0 TSF, do not update, return\n"));
-		return;
-	}
-
-	if (cur_tsf.low > prev_tsf.low)
-		tsf_delta = (cur_tsf.low - prev_tsf.low);
-	else {
-		DHD_INFO((" ---- tsf low is smaller cur_tsf= %08X, prev_tsf=%08X, \n",
-		 cur_tsf.low, prev_tsf.low));
-		if (cur_tsf.high > prev_tsf.high) {
-			tsf_delta = cur_tsf.low + (0xFFFFFFFF - prev_tsf.low);
-			DHD_INFO((" ---- Wrap around tsf coutner  adjusted TSF=%08X\n", tsf_delta));
-		} else {
-			return; /* do not update */
-		}
-	}
-
-	if (tsf_delta)  {
-		hfactor = cyc_delta / tsf_delta;
-		tmp  = 	(cyc_delta - (hfactor * tsf_delta))*10;
-		dec1 =  tmp/tsf_delta;
-		dec2 =  ((tmp - dec1*tsf_delta)*10) / tsf_delta;
-		tmp  = 	(tmp   - (dec1*tsf_delta))*10;
-		dec3 =  ((tmp - dec2*tsf_delta)*10) / tsf_delta;
-
-		if (dec3 > 4) {
-			if (dec2 == 9) {
-				dec2 = 0;
-				if (dec1 == 9) {
-					dec1 = 0;
-					hfactor++;
-				} else {
-					dec1++;
-				}
-			} else {
-				dec2++;
-			}
-		}
-	}
-
-	if (hfactor) {
-		htsf = ((cyc_delta * 10)  / (hfactor*10+dec1)) + prev_tsf.low;
-		dhd->htsf.coef = hfactor;
-		dhd->htsf.last_cycle = cur_cycle;
-		dhd->htsf.last_tsf = cur_tsf.low;
-		dhd->htsf.coefdec1 = dec1;
-		dhd->htsf.coefdec2 = dec2;
-	} else {
-		htsf = prev_tsf.low;
-	}
-}
-
-#endif /* WLMEDIA_HTSF */
-
-#ifdef CUSTOM_SET_CPUCORE
-void dhd_set_cpucore(dhd_pub_t *dhd, int set)
-{
-	int e_dpc = 0, e_rxf = 0, retry_set = 0;
-
-	if (!(dhd->chan_isvht80)) {
-		DHD_ERROR(("%s: chan_status(%d) cpucore!!!\n", __FUNCTION__, dhd->chan_isvht80));
-		return;
-	}
-
-	if (DPC_CPUCORE) {
-		do {
-			if (set == TRUE) {
-				e_dpc = set_cpus_allowed_ptr(dhd->current_dpc,
-					cpumask_of(DPC_CPUCORE));
-			} else {
-				e_dpc = set_cpus_allowed_ptr(dhd->current_dpc,
-					cpumask_of(PRIMARY_CPUCORE));
-			}
-			if (retry_set++ > MAX_RETRY_SET_CPUCORE) {
-				DHD_ERROR(("%s: dpc(%d) invalid cpu!\n", __FUNCTION__, e_dpc));
-				return;
-			}
-			if (e_dpc < 0)
-				OSL_SLEEP(1);
-		} while (e_dpc < 0);
-	}
-	if (RXF_CPUCORE) {
-		do {
-			if (set == TRUE) {
-				e_rxf = set_cpus_allowed_ptr(dhd->current_rxf,
-					cpumask_of(RXF_CPUCORE));
-			} else {
-				e_rxf = set_cpus_allowed_ptr(dhd->current_rxf,
-					cpumask_of(PRIMARY_CPUCORE));
-			}
-			if (retry_set++ > MAX_RETRY_SET_CPUCORE) {
-				DHD_ERROR(("%s: rxf(%d) invalid cpu!\n", __FUNCTION__, e_rxf));
-				return;
-			}
-			if (e_rxf < 0)
-				OSL_SLEEP(1);
-		} while (e_rxf < 0);
-	}
-#ifdef DHD_OF_SUPPORT
-	interrupt_set_cpucore(set);
-#endif /* DHD_OF_SUPPORT */
-	DHD_TRACE(("%s: set(%d) cpucore success!\n", __FUNCTION__, set));
-
-	return;
-}
-#endif /* CUSTOM_SET_CPUCORE */
-
-/* Get interface specific ap_isolate configuration */
-int dhd_get_ap_isolate(dhd_pub_t *dhdp, uint32 idx)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(idx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[idx];
-
-	return ifp->ap_isolate;
-}
-
-/* Set interface specific ap_isolate configuration */
-int dhd_set_ap_isolate(dhd_pub_t *dhdp, uint32 idx, int val)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(idx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[idx];
-
-	ifp->ap_isolate = val;
-
-	return 0;
-}
-
-#ifdef DHD_FW_COREDUMP
-
-
-#ifdef CUSTOMER_HW4_DEBUG
-#ifdef PLATFORM_SLP
-#define MEMDUMPINFO "/opt/etc/.memdump.info"
-#else
-#define MEMDUMPINFO "/data/.memdump.info"
-#endif /* PLATFORM_SLP */
-#elif defined(CUSTOMER_HW2)
-#define MEMDUMPINFO "/data/misc/wifi/.memdump.info"
-#else
-#define MEMDUMPINFO "/installmedia/.memdump.info"
-#endif /* CUSTOMER_HW4_DEBUG */
-
-void dhd_get_memdump_info(dhd_pub_t *dhd)
-{
-	struct file *fp = NULL;
-	uint32 mem_val = DUMP_MEMFILE_MAX;
-	int ret = 0;
-	char *filepath = MEMDUMPINFO;
-
-	/* Read memdump info from the file */
-	fp = filp_open(filepath, O_RDONLY, 0);
-	if (IS_ERR(fp)) {
-		DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
-		goto done;
-	} else {
-		ret = kernel_read(fp, 0, (char *)&mem_val, 4);
-		if (ret < 0) {
-			DHD_ERROR(("%s: File read error, ret=%d\n", __FUNCTION__, ret));
-			filp_close(fp, NULL);
-			goto done;
-		}
-
-		mem_val = bcm_atoi((char *)&mem_val);
-
-		DHD_ERROR(("%s: MEMDUMP ENABLED = %d\n", __FUNCTION__, mem_val));
-		filp_close(fp, NULL);
-	}
-
-done:
-#ifdef CUSTOMER_HW4_DEBUG
-	dhd->memdump_enabled = (mem_val < DUMP_MEMFILE_MAX) ? mem_val : DUMP_DISABLED;
-#else
-	dhd->memdump_enabled = (mem_val < DUMP_MEMFILE_MAX) ? mem_val : DUMP_MEMFILE_BUGON;
-#endif /* CUSTOMER_HW4_DEBUG */
-}
-
-
-void dhd_schedule_memdump(dhd_pub_t *dhdp, uint8 *buf, uint32 size)
-{
-	dhd_dump_t *dump = NULL;
-	dump = (dhd_dump_t *)MALLOC(dhdp->osh, sizeof(dhd_dump_t));
-	if (dump == NULL) {
-		DHD_ERROR(("%s: dhd dump memory allocation failed\n", __FUNCTION__));
-		return;
-	}
-	dump->buf = buf;
-	dump->bufsize = size;
-
-#if defined(CONFIG_ARM64)
-	DHD_ERROR(("%s: buf(va)=%llx, buf(pa)=%llx, bufsize=%d\n", __FUNCTION__,
-		(uint64)buf, (uint64)__virt_to_phys((ulong)buf), size));
-#elif defined(__ARM_ARCH_7A__)
-	DHD_ERROR(("%s: buf(va)=%x, buf(pa)=%x, bufsize=%d\n", __FUNCTION__,
-		(uint32)buf, (uint32)__virt_to_phys((ulong)buf), size));
-#endif /* __ARM_ARCH_7A__ */
-	if (dhdp->memdump_enabled == DUMP_MEMONLY) {
-		BUG_ON(1);
-	}
-
-#ifdef DHD_LOG_DUMP
-	if (dhdp->memdump_type != DUMP_TYPE_BY_SYSDUMP) {
-		dhd_schedule_log_dump(dhdp);
-	}
-#endif /* DHD_LOG_DUMP */
-	dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, (void *)dump,
-		DHD_WQ_WORK_SOC_RAM_DUMP, dhd_mem_dump, DHD_WORK_PRIORITY_HIGH);
-}
-static void
-dhd_mem_dump(void *handle, void *event_info, u8 event)
-{
-	dhd_info_t *dhd = handle;
-	dhd_dump_t *dump = event_info;
-
-	if (!dhd) {
-		DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	if (!dump) {
-		DHD_ERROR(("%s: dump is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	if (write_to_file(&dhd->pub, dump->buf, dump->bufsize)) {
-		DHD_ERROR(("%s: writing SoC_RAM dump to the file failed\n", __FUNCTION__));
-	}
-
-	if (dhd->pub.memdump_enabled == DUMP_MEMFILE_BUGON &&
-#ifdef DHD_LOG_DUMP
-		dhd->pub.memdump_type != DUMP_TYPE_BY_SYSDUMP &&
-#endif
-		TRUE) {
-		BUG_ON(1);
-	}
-	MFREE(dhd->pub.osh, dump, sizeof(dhd_dump_t));
-}
-#endif /* DHD_FW_COREDUMP */
-
-#ifdef DHD_LOG_DUMP
-static void
-dhd_log_dump(void *handle, void *event_info, u8 event)
-{
-	dhd_info_t *dhd = handle;
-
-	if (!dhd) {
-		DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	if (do_dhd_log_dump(&dhd->pub)) {
-		DHD_ERROR(("%s: writing debug dump to the file failed\n", __FUNCTION__));
-		return;
-	}
-}
-
-void dhd_schedule_log_dump(dhd_pub_t *dhdp)
-{
-	dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq,
-		(void*)NULL, DHD_WQ_WORK_DHD_LOG_DUMP,
-		dhd_log_dump, DHD_WORK_PRIORITY_HIGH);
-}
-
-static int
-do_dhd_log_dump(dhd_pub_t *dhdp)
-{
-	int ret = 0;
-	struct file *fp = NULL;
-	mm_segment_t old_fs;
-	loff_t pos = 0;
-	char dump_path[128];
-	char common_info[1024];
-	struct timeval curtime;
-	uint32 file_mode;
-	unsigned long flags = 0;
-
-	if (!dhdp) {
-		return -1;
-	}
-
-	/* Building the additional information like DHD, F/W version */
-	memset(common_info, 0, sizeof(common_info));
-	snprintf(common_info, sizeof(common_info),
-		"---------- Common information ----------\n"
-		"DHD version: %s\n"
-		"F/W version: %s\n"
-		"----------------------------------------\n",
-		dhd_version, fw_version);
-
-	/* change to KERNEL_DS address limit */
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	/* Init file name */
-	memset(dump_path, 0, sizeof(dump_path));
-	do_gettimeofday(&curtime);
-	snprintf(dump_path, sizeof(dump_path), "%s_%ld.%ld",
-		DHD_COMMON_DUMP_PATH "debug_dump",
-		(unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec);
-	file_mode = O_CREAT | O_WRONLY | O_SYNC;
-
-	DHD_ERROR(("debug_dump_path = %s\n", dump_path));
-	fp = filp_open(dump_path, file_mode, 0644);
-	if (IS_ERR(fp)) {
-		ret = PTR_ERR(fp);
-		DHD_ERROR(("open file error, err = %d\n", ret));
-		ret = -1;
-		goto exit;
-	}
-
-	fp->f_op->write(fp, common_info, strlen(common_info), &pos);
-	if (dhdp->dld_buf.wraparound) {
-		fp->f_op->write(fp, dhdp->dld_buf.buffer, DHD_LOG_DUMP_BUFFER_SIZE, &pos);
-	} else {
-		fp->f_op->write(fp, dhdp->dld_buf.buffer,
-			(int)(dhdp->dld_buf.present - dhdp->dld_buf.front), &pos);
-	}
-
-	/* re-init dhd_log_dump_buf structure */
-	spin_lock_irqsave(&dhdp->dld_buf.lock, flags);
-	dhdp->dld_buf.wraparound = 0;
-	dhdp->dld_buf.present = dhdp->dld_buf.front;
-	dhdp->dld_buf.remain = DHD_LOG_DUMP_BUFFER_SIZE;
-	bzero(dhdp->dld_buf.buffer, DHD_LOG_DUMP_BUFFER_SIZE);
-	spin_unlock_irqrestore(&dhdp->dld_buf.lock, flags);
-exit:
-	if (!ret) {
-		filp_close(fp, NULL);
-	}
-	set_fs(old_fs);
-
-	return ret;
-}
-#endif /* DHD_LOG_DUMP */
-
-#ifdef BCMASSERT_LOG
-#ifdef CUSTOMER_HW4_DEBUG
-#ifdef PLATFORM_SLP
-#define ASSERTINFO "/opt/etc/.assert.info"
-#else
-#define ASSERTINFO "/data/.assert.info"
-#endif /* PLATFORM_SLP */
-#elif defined(CUSTOMER_HW2)
-#define ASSERTINFO "/data/misc/wifi/.assert.info"
-#else
-#define ASSERTINFO "/installmedia/.assert.info"
-#endif /* CUSTOMER_HW4_DEBUG */
-void dhd_get_assert_info(dhd_pub_t *dhd)
-{
-	struct file *fp = NULL;
-	char *filepath = ASSERTINFO;
-
-	/*
-	 * Read assert info from the file
-	 * 0: Trigger Kernel crash by panic()
-	 * 1: Print out the logs and don't trigger Kernel panic. (default)
-	 * 2: Trigger Kernel crash by BUG()
-	 * File doesn't exist: Keep default value (1).
-	 */
-	fp = filp_open(filepath, O_RDONLY, 0);
-	if (IS_ERR(fp)) {
-		DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
-	} else {
-		int mem_val = 0;
-		int ret = kernel_read(fp, 0, (char *)&mem_val, 4);
-		if (ret < 0) {
-			DHD_ERROR(("%s: File read error, ret=%d\n", __FUNCTION__, ret));
-		} else {
-			mem_val = bcm_atoi((char *)&mem_val);
-			DHD_ERROR(("%s: ASSERT ENABLED = %d\n", __FUNCTION__, mem_val));
-			g_assert_type = mem_val;
-		}
-		filp_close(fp, NULL);
-	}
-}
-#endif /* BCMASSERT_LOG */
-
-
-#ifdef DHD_WMF
-/* Returns interface specific WMF configuration */
-dhd_wmf_t* dhd_wmf_conf(dhd_pub_t *dhdp, uint32 idx)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(idx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[idx];
-	return &ifp->wmf;
-}
-#endif /* DHD_WMF */
-
-
-#if defined(DHD_L2_FILTER)
-bool dhd_sta_associated(dhd_pub_t *dhdp, uint32 bssidx, uint8 *mac)
-{
-	return dhd_find_sta(dhdp, bssidx, mac) ? TRUE : FALSE;
-}
-#endif 
-
-#ifdef DHD_L2_FILTER
-arp_table_t*
-dhd_get_ifp_arp_table_handle(dhd_pub_t *dhdp, uint32 bssidx)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(bssidx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[bssidx];
-	return ifp->phnd_arp_table;
-}
-
-int dhd_get_parp_status(dhd_pub_t *dhdp, uint32 idx)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(idx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[idx];
-
-	if (ifp)
-		return ifp->parp_enable;
-	else
-		return FALSE;
-}
-
-/* Set interface specific proxy arp configuration */
-int dhd_set_parp_status(dhd_pub_t *dhdp, uint32 idx, int val)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-	ASSERT(idx < DHD_MAX_IFS);
-	ifp = dhd->iflist[idx];
-
-	if (!ifp)
-	    return BCME_ERROR;
-
-	/* At present all 3 variables are being
-	 * handled at once
-	 */
-	ifp->parp_enable = val;
-	ifp->parp_discard = val;
-	ifp->parp_allnode = !val;
-
-	/* Flush ARP entries when disabled */
-	if (val == FALSE) {
-		bcm_l2_filter_arp_table_update(dhdp->osh, ifp->phnd_arp_table, TRUE, NULL,
-			FALSE, dhdp->tickcnt);
-	}
-	return BCME_OK;
-}
-
-bool dhd_parp_discard_is_enabled(dhd_pub_t *dhdp, uint32 idx)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(idx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[idx];
-
-	ASSERT(ifp);
-	return ifp->parp_discard;
-}
-
-bool
-dhd_parp_allnode_is_enabled(dhd_pub_t *dhdp, uint32 idx)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(idx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[idx];
-
-	ASSERT(ifp);
-
-	return ifp->parp_allnode;
-}
-
-int dhd_get_dhcp_unicast_status(dhd_pub_t *dhdp, uint32 idx)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(idx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[idx];
-
-	ASSERT(ifp);
-
-	return ifp->dhcp_unicast;
-}
-
-int dhd_set_dhcp_unicast_status(dhd_pub_t *dhdp, uint32 idx, int val)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-	ASSERT(idx < DHD_MAX_IFS);
-	ifp = dhd->iflist[idx];
-
-	ASSERT(ifp);
-
-	ifp->dhcp_unicast = val;
-	return BCME_OK;
-}
-
-int dhd_get_block_ping_status(dhd_pub_t *dhdp, uint32 idx)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(idx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[idx];
-
-	ASSERT(ifp);
-
-	return ifp->block_ping;
-}
-
-int dhd_set_block_ping_status(dhd_pub_t *dhdp, uint32 idx, int val)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-	ASSERT(idx < DHD_MAX_IFS);
-	ifp = dhd->iflist[idx];
-
-	ASSERT(ifp);
-
-	ifp->block_ping = val;
-
-	return BCME_OK;
-}
-
-int dhd_get_grat_arp_status(dhd_pub_t *dhdp, uint32 idx)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-
-	ASSERT(idx < DHD_MAX_IFS);
-
-	ifp = dhd->iflist[idx];
-
-	ASSERT(ifp);
-
-	return ifp->grat_arp;
-}
-
-int dhd_set_grat_arp_status(dhd_pub_t *dhdp, uint32 idx, int val)
-{
-	dhd_info_t *dhd = dhdp->info;
-	dhd_if_t *ifp;
-	ASSERT(idx < DHD_MAX_IFS);
-	ifp = dhd->iflist[idx];
-
-	ASSERT(ifp);
-
-	ifp->grat_arp = val;
-
-	return BCME_OK;
-}
-#endif /* DHD_L2_FILTER */
-
-
-#if defined(SET_RPS_CPUS)
-int dhd_rps_cpus_enable(struct net_device *net, int enable)
-{
-	dhd_info_t *dhd = DHD_DEV_INFO(net);
-	dhd_if_t *ifp;
-	int ifidx;
-	char * RPS_CPU_SETBUF;
-
-	ifidx = dhd_net2idx(dhd, net);
-	if (ifidx == DHD_BAD_IF) {
-		DHD_ERROR(("%s bad ifidx\n", __FUNCTION__));
-		return -ENODEV;
-	}
-
-	if (ifidx == PRIMARY_INF) {
-		if (dhd->pub.op_mode == DHD_FLAG_IBSS_MODE) {
-			DHD_INFO(("%s : set for IBSS.\n", __FUNCTION__));
-			RPS_CPU_SETBUF = RPS_CPUS_MASK_IBSS;
-		} else {
-			DHD_INFO(("%s : set for BSS.\n", __FUNCTION__));
-			RPS_CPU_SETBUF = RPS_CPUS_MASK;
-		}
-	} else if (ifidx == VIRTUAL_INF) {
-		DHD_INFO(("%s : set for P2P.\n", __FUNCTION__));
-		RPS_CPU_SETBUF = RPS_CPUS_MASK_P2P;
-	} else {
-		DHD_ERROR(("%s : Invalid index : %d.\n", __FUNCTION__, ifidx));
-		return -EINVAL;
-	}
-
-	ifp = dhd->iflist[ifidx];
-	if (ifp) {
-		if (enable) {
-			DHD_INFO(("%s : set rps_cpus as [%s]\n", __FUNCTION__, RPS_CPU_SETBUF));
-			custom_rps_map_set(ifp->net->_rx, RPS_CPU_SETBUF, strlen(RPS_CPU_SETBUF));
-		} else {
-			custom_rps_map_clear(ifp->net->_rx);
-		}
-	} else {
-		DHD_ERROR(("%s : ifp is NULL!!\n", __FUNCTION__));
-		return -ENODEV;
-	}
-	return BCME_OK;
-}
-
-int custom_rps_map_set(struct netdev_rx_queue *queue, char *buf, size_t len)
-{
-	struct rps_map *old_map, *map;
-	cpumask_var_t mask;
-	int err, cpu, i;
-	static DEFINE_SPINLOCK(rps_map_lock);
-
-	DHD_INFO(("%s : Entered.\n", __FUNCTION__));
-
-	if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
-		DHD_ERROR(("%s : alloc_cpumask_var fail.\n", __FUNCTION__));
-		return -ENOMEM;
-	}
-
-	err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits);
-	if (err) {
-		free_cpumask_var(mask);
-		DHD_ERROR(("%s : bitmap_parse fail.\n", __FUNCTION__));
-		return err;
-	}
-
-	map = kzalloc(max_t(unsigned int,
-		RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES),
-		GFP_KERNEL);
-	if (!map) {
-		free_cpumask_var(mask);
-		DHD_ERROR(("%s : map malloc fail.\n", __FUNCTION__));
-		return -ENOMEM;
-	}
-
-	i = 0;
-	for_each_cpu(cpu, mask) {
-		map->cpus[i++] = cpu;
-	}
-
-	if (i) {
-		map->len = i;
-	} else {
-		kfree(map);
-		map = NULL;
-		free_cpumask_var(mask);
-		DHD_ERROR(("%s : mapping cpu fail.\n", __FUNCTION__));
-		return -1;
-	}
-
-	spin_lock(&rps_map_lock);
-	old_map = rcu_dereference_protected(queue->rps_map,
-		lockdep_is_held(&rps_map_lock));
-	rcu_assign_pointer(queue->rps_map, map);
-	spin_unlock(&rps_map_lock);
-
-	if (map) {
-		static_key_slow_inc(&rps_needed);
-	}
-	if (old_map) {
-		kfree_rcu(old_map, rcu);
-		static_key_slow_dec(&rps_needed);
-	}
-	free_cpumask_var(mask);
-
-	DHD_INFO(("%s : Done. mapping cpu nummber : %d\n", __FUNCTION__, map->len));
-	return map->len;
-}
-
-void custom_rps_map_clear(struct netdev_rx_queue *queue)
-{
-	struct rps_map *map;
-
-	DHD_INFO(("%s : Entered.\n", __FUNCTION__));
-
-	map = rcu_dereference_protected(queue->rps_map, 1);
-	if (map) {
-		RCU_INIT_POINTER(queue->rps_map, NULL);
-		kfree_rcu(map, rcu);
-		DHD_INFO(("%s : rps_cpus map clear.\n", __FUNCTION__));
-	}
-}
-#endif 
-
-
-
-#ifdef DHD_DEBUG_PAGEALLOC
-
-void
-dhd_page_corrupt_cb(void *handle, void *addr_corrupt, size_t len)
-{
-	dhd_pub_t *dhdp = (dhd_pub_t *)handle;
-
-	DHD_ERROR(("%s: Got dhd_page_corrupt_cb 0x%p %d\n",
-		__FUNCTION__, addr_corrupt, (uint32)len));
-
-	DHD_OS_WAKE_LOCK(dhdp);
-	prhex("Page Corruption:", addr_corrupt, len);
-	dhd_dump_to_kernelog(dhdp);
-#if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
-	/* Load the dongle side dump to host memory and then BUG_ON() */
-	dhdp->memdump_enabled = DUMP_MEMONLY;
-	dhdp->memdump_type = DUMP_TYPE_MEMORY_CORRUPTION;
-	dhd_bus_mem_dump(dhdp);
-#endif /* BCMPCIE && DHD_FW_COREDUMP */
-	DHD_OS_WAKE_UNLOCK(dhdp);
-}
-EXPORT_SYMBOL(dhd_page_corrupt_cb);
-#endif /* DHD_DEBUG_PAGEALLOC */
-
-#ifdef DHD_PKTID_AUDIT_ENABLED
-void
-dhd_pktid_audit_fail_cb(dhd_pub_t *dhdp)
-{
-	DHD_ERROR(("%s: Got Pkt Id Audit failure \n", __FUNCTION__));
-	DHD_OS_WAKE_LOCK(dhdp);
-	dhd_dump_to_kernelog(dhdp);
-#if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
-	/* Load the dongle side dump to host memory and then BUG_ON() */
-	dhdp->memdump_enabled = DUMP_MEMFILE_BUGON;
-	dhdp->memdump_type = DUMP_TYPE_PKTID_AUDIT_FAILURE;
-	dhd_bus_mem_dump(dhdp);
-#endif /* BCMPCIE && DHD_FW_COREDUMP */
-	DHD_OS_WAKE_UNLOCK(dhdp);
-}
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-/* ----------------------------------------------------------------------------
- * Infrastructure code for sysfs interface support for DHD
- *
- * What is sysfs interface?
- * https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt
- *
- * Why sysfs interface?
- * This is the Linux standard way of changing/configuring Run Time parameters
- * for a driver. We can use this interface to control "linux" specific driver
- * parameters.
- *
- * -----------------------------------------------------------------------------
- */
-
-#include <linux/sysfs.h>
-#include <linux/kobject.h>
-
-#if defined(DHD_TRACE_WAKE_LOCK)
-
-/* Function to show the history buffer */
-static ssize_t
-show_wklock_trace(struct dhd_info *dev, char *buf)
-{
-	ssize_t ret = 0;
-	dhd_info_t *dhd = (dhd_info_t *)dev;
-
-	buf[ret] = '\n';
-	buf[ret+1] = 0;
-
-	dhd_wk_lock_stats_dump(&dhd->pub);
-	return ret+1;
-}
-
-/* Function to enable/disable wakelock trace */
-static ssize_t
-wklock_trace_onoff(struct dhd_info *dev, const char *buf, size_t count)
-{
-	unsigned long onoff;
-	unsigned long flags;
-	dhd_info_t *dhd = (dhd_info_t *)dev;
-
-	onoff = bcm_strtoul(buf, NULL, 10);
-	if (onoff != 0 && onoff != 1) {
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
-	trace_wklock_onoff = onoff;
-	spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
-	if (trace_wklock_onoff) {
-		printk("ENABLE WAKLOCK TRACE\n");
-	} else {
-		printk("DISABLE WAKELOCK TRACE\n");
-	}
-
-	return (ssize_t)(onoff+1);
-}
-#endif /* DHD_TRACE_WAKE_LOCK */
-
-/*
- * Generic Attribute Structure for DHD.
- * If we have to add a new sysfs entry under /sys/bcm-dhd/, we have
- * to instantiate an object of type dhd_attr,  populate it with
- * the required show/store functions (ex:- dhd_attr_cpumask_primary)
- * and add the object to default_attrs[] array, that gets registered
- * to the kobject of dhd (named bcm-dhd).
- */
-
-struct dhd_attr {
-	struct attribute attr;
-	ssize_t(*show)(struct dhd_info *, char *);
-	ssize_t(*store)(struct dhd_info *, const char *, size_t count);
-};
-
-#if defined(DHD_TRACE_WAKE_LOCK)
-static struct dhd_attr dhd_attr_wklock =
-	__ATTR(wklock_trace, 0660, show_wklock_trace, wklock_trace_onoff);
-#endif /* defined(DHD_TRACE_WAKE_LOCK */
-
-/* Attribute object that gets registered with "bcm-dhd" kobject tree */
-static struct attribute *default_attrs[] = {
-#if defined(DHD_TRACE_WAKE_LOCK)
-	&dhd_attr_wklock.attr,
-#endif
-	NULL
-};
-
-#define to_dhd(k) container_of(k, struct dhd_info, dhd_kobj)
-#define to_attr(a) container_of(a, struct dhd_attr, attr)
-
-/*
- * bcm-dhd kobject show function, the "attr" attribute specifices to which
- * node under "bcm-dhd" the show function is called.
- */
-static ssize_t dhd_show(struct kobject *kobj, struct attribute *attr, char *buf)
-{
-	dhd_info_t *dhd = to_dhd(kobj);
-	struct dhd_attr *d_attr = to_attr(attr);
-	int ret;
-
-	if (d_attr->show)
-		ret = d_attr->show(dhd, buf);
-	else
-		ret = -EIO;
-
-	return ret;
-}
-
-
-/*
- * bcm-dhd kobject show function, the "attr" attribute specifices to which
- * node under "bcm-dhd" the store function is called.
- */
-static ssize_t dhd_store(struct kobject *kobj, struct attribute *attr,
-	const char *buf, size_t count)
-{
-	dhd_info_t *dhd = to_dhd(kobj);
-	struct dhd_attr *d_attr = to_attr(attr);
-	int ret;
-
-	if (d_attr->store)
-		ret = d_attr->store(dhd, buf, count);
-	else
-		ret = -EIO;
-
-	return ret;
-
-}
-
-static struct sysfs_ops dhd_sysfs_ops = {
-	.show = dhd_show,
-	.store = dhd_store,
-};
-
-static struct kobj_type dhd_ktype = {
-	.sysfs_ops = &dhd_sysfs_ops,
-	.default_attrs = default_attrs,
-};
-
-/* Create a kobject and attach to sysfs interface */
-static int dhd_sysfs_init(dhd_info_t *dhd)
-{
-	int ret = -1;
-
-	if (dhd == NULL) {
-		DHD_ERROR(("%s(): dhd is NULL \r\n", __FUNCTION__));
-		return ret;
-	}
-
-	/* Initialize the kobject */
-	ret = kobject_init_and_add(&dhd->dhd_kobj, &dhd_ktype, NULL, "bcm-dhd");
-	if (ret) {
-		kobject_put(&dhd->dhd_kobj);
-		DHD_ERROR(("%s(): Unable to allocate kobject \r\n", __FUNCTION__));
-		return ret;
-	}
-
-	/*
-	 * We are always responsible for sending the uevent that the kobject
-	 * was added to the system.
-	 */
-	kobject_uevent(&dhd->dhd_kobj, KOBJ_ADD);
-
-	return ret;
-}
-
-/* Done with the kobject and detach the sysfs interface */
-static void dhd_sysfs_exit(dhd_info_t *dhd)
-{
-	if (dhd == NULL) {
-		DHD_ERROR(("%s(): dhd is NULL \r\n", __FUNCTION__));
-		return;
-	}
-
-	/* Releae the kobject */
-	kobject_put(&dhd->dhd_kobj);
-}
-
-#ifdef DHD_LOG_DUMP
-void
-dhd_log_dump_init(dhd_pub_t *dhd)
-{
-	spin_lock_init(&dhd->dld_buf.lock);
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP)
-	dhd->dld_buf.buffer = DHD_OS_PREALLOC(dhd,
-		DHD_PREALLOC_DHD_LOG_DUMP_BUF, DHD_LOG_DUMP_BUFFER_SIZE);
-#else
-	dhd->dld_buf.buffer = kmalloc(DHD_LOG_DUMP_BUFFER_SIZE, GFP_KERNEL);
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */
-
-	if (!dhd->dld_buf.buffer) {
-		dhd->dld_buf.buffer = kmalloc(DHD_LOG_DUMP_BUFFER_SIZE, GFP_KERNEL);
-		DHD_ERROR(("Try to allocate memory using kmalloc().\n"));
-
-		if (!dhd->dld_buf.buffer) {
-			DHD_ERROR(("Failed to allocate memory for dld_buf.\n"));
-			return;
-		}
-	}
-
-	dhd->dld_buf.wraparound = 0;
-	dhd->dld_buf.max = (unsigned long)dhd->dld_buf.buffer + DHD_LOG_DUMP_BUFFER_SIZE;
-	dhd->dld_buf.present = dhd->dld_buf.buffer;
-	dhd->dld_buf.front = dhd->dld_buf.buffer;
-	dhd->dld_buf.remain = DHD_LOG_DUMP_BUFFER_SIZE;
-	dhd->dld_enable = 1;
-}
-
-void
-dhd_log_dump_deinit(dhd_pub_t *dhd)
-{
-	dhd->dld_enable = 0;
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP)
-	DHD_OS_PREFREE(dhd,
-		dhd->dld_buf.buffer, DHD_LOG_DUMP_BUFFER_SIZE);
-#else
-	kfree(dhd->dld_buf.buffer);
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */
-}
-
-void
-dhd_log_dump_print(const char *fmt, ...)
-{
-	int len = 0;
-	char tmp_buf[DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE] = {0, };
-	va_list args;
-	dhd_pub_t *dhd = NULL;
-	unsigned long flags = 0;
-
-	if (wl_get_bcm_cfg80211_ptr()) {
-		dhd = (dhd_pub_t*)(wl_get_bcm_cfg80211_ptr()->pub);
-	}
-
-	if (!dhd || dhd->dld_enable != 1) {
-		return;
-	}
-
-	va_start(args, fmt);
-
-	len = vsnprintf(tmp_buf, DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE, fmt, args);
-	if (len < 0) {
-		return;
-	}
-
-	/* make a critical section to eliminate race conditions */
-	spin_lock_irqsave(&dhd->dld_buf.lock, flags);
-	if (dhd->dld_buf.remain < len) {
-		dhd->dld_buf.wraparound = 1;
-		dhd->dld_buf.present = dhd->dld_buf.front;
-		dhd->dld_buf.remain = DHD_LOG_DUMP_BUFFER_SIZE;
-	}
-
-	strncpy(dhd->dld_buf.present, tmp_buf, len);
-	dhd->dld_buf.remain -= len;
-	dhd->dld_buf.present += len;
-	spin_unlock_irqrestore(&dhd->dld_buf.lock, flags);
-
-	/* double check invalid memory operation */
-	ASSERT((unsigned long)dhd->dld_buf.present <= dhd->dld_buf.max);
-	va_end(args);
-}
-
-char*
-dhd_log_dump_get_timestamp(void)
-{
-	static char buf[16];
-	u64 ts_nsec;
-	unsigned long rem_nsec;
-
-	ts_nsec = local_clock();
-	rem_nsec = do_div(ts_nsec, 1000000000);
-	snprintf(buf, sizeof(buf), "%5lu.%06lu",
-		(unsigned long)ts_nsec, rem_nsec / 1000);
-
-	return buf;
-}
-
-#endif /* DHD_LOG_DUMP */
-
-/* ---------------------------- End of sysfs implementation ------------------------------------- */
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.h b/drivers/net/wireless/bcmdhd/dhd_linux.h
deleted file mode 100644
index dd33977..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_linux.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * DHD Linux header file (dhd_linux exports for cfg80211 and other components)
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_linux.h 591285 2015-10-07 11:56:29Z $
- */
-
-/* wifi platform functions for power, interrupt and pre-alloc, either
- * from Android-like platform device data, or Broadcom wifi platform
- * device data.
- *
- */
-#ifndef __DHD_LINUX_H__
-#define __DHD_LINUX_H__
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#ifdef DHD_WMF
-#include <dhd_wmf_linux.h>
-#endif
-/* Linux wireless extension support */
-#if defined(WL_WIRELESS_EXT)
-#include <wl_iw.h>
-#endif /* defined(WL_WIRELESS_EXT) */
-#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */
-
-#if defined(CONFIG_WIFI_CONTROL_FUNC)
-#include <linux/wlan_plat.h>
-#endif
-
-#if !defined(CONFIG_WIFI_CONTROL_FUNC)
-#define WLAN_PLAT_NODFS_FLAG    0x01
-struct wifi_platform_data {
-	int (*set_power)(int val);
-	int (*set_reset)(int val);
-	int (*set_carddetect)(int val);
-	void *(*mem_prealloc)(int section, unsigned long size);
-	int (*get_mac_addr)(unsigned char *buf);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58)) || defined(CUSTOM_COUNTRY_CODE)
-	void *(*get_country_code)(char *ccode, u32 flags);
-#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58)) || defined (CUSTOM_COUNTRY_CODE) */
-	void *(*get_country_code)(char *ccode);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58)) */
- };
-#endif /* CONFIG_WIFI_CONTROL_FUNC */
-#define DHD_REGISTRATION_TIMEOUT  12000  /* msec : allowed time to finished dhd registration */
-
-typedef struct wifi_adapter_info {
-	const char	*name;
-	uint		irq_num;
-	uint		intr_flags;
-	const char	*fw_path;
-	const char	*nv_path;
-	void		*wifi_plat_data;	/* wifi ctrl func, for backward compatibility */
-	uint		bus_type;
-	uint		bus_num;
-	uint		slot_num;
-} wifi_adapter_info_t;
-
-typedef struct bcmdhd_wifi_platdata {
-	uint				num_adapters;
-	wifi_adapter_info_t	*adapters;
-} bcmdhd_wifi_platdata_t;
-
-/** Per STA params. A list of dhd_sta objects are managed in dhd_if */
-typedef struct dhd_sta {
-	cumm_ctr_t cumm_ctr;    /* cummulative queue length of child flowrings */
-	uint16 flowid[NUMPRIO]; /* allocated flow ring ids (by priority) */
-	void * ifp;             /* associated dhd_if */
-	struct ether_addr ea;   /* stations ethernet mac address */
-	struct list_head list;  /* link into dhd_if::sta_list */
-	int idx;                /* index of self in dhd_pub::sta_pool[] */
-	int ifidx;              /* index of interface in dhd */
-} dhd_sta_t;
-typedef dhd_sta_t dhd_sta_pool_t;
-
-int dhd_wifi_platform_register_drv(void);
-void dhd_wifi_platform_unregister_drv(void);
-wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_num,
-	uint32 slot_num);
-int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec);
-int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present);
-int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *irq_flags_ptr);
-int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf);
-#ifdef CUSTOM_COUNTRY_CODE
-void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode,
-   u32 flags);
-#else
-void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode);
-#endif /* CUSTOM_COUNTRY_CODE */
-void* wifi_platform_prealloc(wifi_adapter_info_t *adapter, int section, unsigned long size);
-void* wifi_platform_get_prealloc_func_ptr(wifi_adapter_info_t *adapter);
-
-int dhd_get_fw_mode(struct dhd_info *dhdinfo);
-bool dhd_update_fw_nv_path(struct dhd_info *dhdinfo);
-
-#ifdef DHD_WMF
-dhd_wmf_t* dhd_wmf_conf(dhd_pub_t *dhdp, uint32 idx);
-#endif /* DHD_WMF */
-#endif /* __DHD_LINUX_H__ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_platdev.c b/drivers/net/wireless/bcmdhd/dhd_linux_platdev.c
deleted file mode 100644
index f7696d8..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_linux_platdev.c
+++ /dev/null
@@ -1,823 +0,0 @@
-/*
- * Linux platform device for DHD WLAN adapter
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_linux_platdev.c 591285 2015-10-07 11:56:29Z $
- */
-#include <typedefs.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <bcmutils.h>
-#include <linux_osl.h>
-#include <dhd_dbg.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_linux.h>
-#include <wl_android.h>
-#if defined(CONFIG_WIFI_CONTROL_FUNC)
-#include <linux/wlan_plat.h>
-#endif
-#ifdef CONFIG_DTS
-#include<linux/regulator/consumer.h>
-#include<linux/of_gpio.h>
-#endif /* CONFIG_DTS */
-
-
-#define WIFI_PLAT_NAME		"bcmdhd_wlan"
-#define WIFI_PLAT_NAME2		"bcm4329_wlan"
-#define WIFI_PLAT_EXT		"bcmdhd_wifi_platform"
-
-#ifdef CONFIG_DTS
-struct regulator *wifi_regulator = NULL;
-#endif /* CONFIG_DTS */
-
-bool cfg_multichip = FALSE;
-bcmdhd_wifi_platdata_t *dhd_wifi_platdata = NULL;
-static int wifi_plat_dev_probe_ret = 0;
-static bool is_power_on = FALSE;
-#if !defined(CONFIG_DTS)
-#if defined(DHD_OF_SUPPORT)
-static bool dts_enabled = TRUE;
-extern struct resource dhd_wlan_resources;
-extern struct wifi_platform_data dhd_wlan_control;
-#else
-static bool dts_enabled = FALSE;
-struct resource dhd_wlan_resources = {0};
-struct wifi_platform_data dhd_wlan_control = {0};
-#endif /* CONFIG_OF && !defined(CONFIG_ARCH_MSM) */
-#endif /* !defind(CONFIG_DTS) */
-
-static int dhd_wifi_platform_load(void);
-
-extern void* wl_cfg80211_get_dhdp(void);
-
-#ifdef ENABLE_4335BT_WAR
-extern int bcm_bt_lock(int cookie);
-extern void bcm_bt_unlock(int cookie);
-static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24;	/* cookie is "WiFi" */
-#endif /* ENABLE_4335BT_WAR */
-
-wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_num, uint32 slot_num)
-{
-	int i;
-
-	if (dhd_wifi_platdata == NULL)
-		return NULL;
-
-	for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
-		wifi_adapter_info_t *adapter = &dhd_wifi_platdata->adapters[i];
-		if ((adapter->bus_type == -1 || adapter->bus_type == bus_type) &&
-			(adapter->bus_num == -1 || adapter->bus_num == bus_num) &&
-			(adapter->slot_num == -1 || adapter->slot_num == slot_num)) {
-			DHD_TRACE(("found adapter info '%s'\n", adapter->name));
-			return adapter;
-		}
-	}
-	return NULL;
-}
-
-void* wifi_platform_prealloc(wifi_adapter_info_t *adapter, int section, unsigned long size)
-{
-	void *alloc_ptr = NULL;
-	struct wifi_platform_data *plat_data;
-
-	if (!adapter || !adapter->wifi_plat_data)
-		return NULL;
-	plat_data = adapter->wifi_plat_data;
-	if (plat_data->mem_prealloc) {
-		alloc_ptr = plat_data->mem_prealloc(section, size);
-		if (alloc_ptr) {
-			DHD_INFO(("success alloc section %d\n", section));
-			if (size != 0L)
-				bzero(alloc_ptr, size);
-			return alloc_ptr;
-		}
-	}
-
-	DHD_ERROR(("%s: failed to alloc static mem section %d\n", __FUNCTION__, section));
-	return NULL;
-}
-
-void* wifi_platform_get_prealloc_func_ptr(wifi_adapter_info_t *adapter)
-{
-	struct wifi_platform_data *plat_data;
-
-	if (!adapter || !adapter->wifi_plat_data)
-		return NULL;
-	plat_data = adapter->wifi_plat_data;
-	return plat_data->mem_prealloc;
-}
-
-int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *irq_flags_ptr)
-{
-	if (adapter == NULL)
-		return -1;
-	if (irq_flags_ptr)
-		*irq_flags_ptr = adapter->intr_flags;
-	return adapter->irq_num;
-}
-
-int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec)
-{
-	int err = 0;
-#ifdef CONFIG_DTS
-	if (on) {
-	//	err = regulator_enable(wifi_regulator);
-		is_power_on = TRUE;
-	}
-	else {
-	//	err = regulator_disable(wifi_regulator);
-		is_power_on = FALSE;
-	}
-	if (err < 0)
-		DHD_ERROR(("%s: regulator enable/disable failed", __FUNCTION__));
-#else
-	struct wifi_platform_data *plat_data;
-
-	if (!adapter || !adapter->wifi_plat_data)
-		return -EINVAL;
-	plat_data = adapter->wifi_plat_data;
-
-	DHD_ERROR(("%s = %d\n", __FUNCTION__, on));
-	if (plat_data->set_power) {
-#ifdef ENABLE_4335BT_WAR
-		if (on) {
-			printk("WiFi: trying to acquire BT lock\n");
-			if (bcm_bt_lock(lock_cookie_wifi) != 0)
-				printk("** WiFi: timeout in acquiring bt lock**\n");
-			printk("%s: btlock acquired\n", __FUNCTION__);
-		}
-		else {
-			/* For a exceptional case, release btlock */
-			bcm_bt_unlock(lock_cookie_wifi);
-		}
-#endif /* ENABLE_4335BT_WAR */
-
-		err = plat_data->set_power(on);
-	}
-
-	if (msec && !err)
-		OSL_SLEEP(msec);
-
-	if (on && !err)
-		is_power_on = TRUE;
-	else
-		is_power_on = FALSE;
-
-#endif /* CONFIG_DTS */
-
-	return err;
-}
-
-int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present)
-{
-	int err = 0;
-	struct wifi_platform_data *plat_data;
-
-	if (!adapter || !adapter->wifi_plat_data)
-		return -EINVAL;
-	plat_data = adapter->wifi_plat_data;
-
-	DHD_ERROR(("%s device present %d\n", __FUNCTION__, device_present));
-	if (plat_data->set_carddetect) {
-		err = plat_data->set_carddetect(device_present);
-	}
-	return err;
-
-}
-
-int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf)
-{
-	struct wifi_platform_data *plat_data;
-
-	DHD_ERROR(("%s\n", __FUNCTION__));
-	if (!buf || !adapter || !adapter->wifi_plat_data)
-		return -EINVAL;
-	plat_data = adapter->wifi_plat_data;
-	if (plat_data->get_mac_addr) {
-		return plat_data->get_mac_addr(buf);
-	}
-	return -EOPNOTSUPP;
-}
-#ifdef CUSTOM_COUNTRY_CODE
-void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode, u32 flags)
-#else
-void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode)
-#endif /* CUSTOM_COUNTRY_CODE */
-{
-	/* get_country_code was added after 2.6.39 */
-#if	(LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
-	struct wifi_platform_data *plat_data;
-
-	if (!ccode || !adapter || !adapter->wifi_plat_data)
-		return NULL;
-	plat_data = adapter->wifi_plat_data;
-
-	DHD_TRACE(("%s\n", __FUNCTION__));
-	if (plat_data->get_country_code) {
-#if     (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58))
-		return plat_data->get_country_code(ccode, WLAN_PLAT_NODFS_FLAG);
-#else
-#ifdef CUSTOM_COUNTRY_CODE
-		return plat_data->get_country_code(ccode, flags);
-#else
-		return plat_data->get_country_code(ccode);
-#endif /* CUSTOM_COUNTRY_CODE */
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58)) */
-	}
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
-
-	return NULL;
-}
-
-static int wifi_plat_dev_drv_probe(struct platform_device *pdev)
-{
-	struct resource *resource;
-	wifi_adapter_info_t *adapter;
-#ifdef CONFIG_DTS
-	int irq, gpio;
-#endif /* CONFIG_DTS */
-
-	/* Android style wifi platform data device ("bcmdhd_wlan" or "bcm4329_wlan")
-	 * is kept for backward compatibility and supports only 1 adapter
-	 */
-	ASSERT(dhd_wifi_platdata != NULL);
-	ASSERT(dhd_wifi_platdata->num_adapters == 1);
-	adapter = &dhd_wifi_platdata->adapters[0];
-	adapter->wifi_plat_data = (struct wifi_platform_data *)(pdev->dev.platform_data);
-
-	resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
-	if (resource == NULL)
-		resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq");
-	if (resource) {
-		adapter->irq_num = resource->start;
-		adapter->intr_flags = resource->flags & IRQF_TRIGGER_MASK;
-	}
-
-#ifdef CONFIG_DTS
-	wifi_regulator = regulator_get(&pdev->dev, "wlreg_on");
-	if (wifi_regulator == NULL) {
-		DHD_ERROR(("%s regulator is null\n", __FUNCTION__));
-		return -1;
-	}
-
-	/* This is to get the irq for the OOB */
-	gpio = of_get_gpio(pdev->dev.of_node, 0);
-
-	if (gpio < 0) {
-		DHD_ERROR(("%s gpio information is incorrect\n", __FUNCTION__));
-		return -1;
-	}
-	irq = gpio_to_irq(gpio);
-	if (irq < 0) {
-		DHD_ERROR(("%s irq information is incorrect\n", __FUNCTION__));
-		return -1;
-	}
-	adapter->irq_num = irq;
-
-	/* need to change the flags according to our requirement */
-	adapter->intr_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
-		IORESOURCE_IRQ_SHAREABLE;
-#endif /* CONFIG_DTS */
-
-	wifi_plat_dev_probe_ret = dhd_wifi_platform_load();
-	return wifi_plat_dev_probe_ret;
-}
-
-static int wifi_plat_dev_drv_remove(struct platform_device *pdev)
-{
-	wifi_adapter_info_t *adapter;
-
-	/* Android style wifi platform data device ("bcmdhd_wlan" or "bcm4329_wlan")
-	 * is kept for backward compatibility and supports only 1 adapter
-	 */
-	ASSERT(dhd_wifi_platdata != NULL);
-	ASSERT(dhd_wifi_platdata->num_adapters == 1);
-	adapter = &dhd_wifi_platdata->adapters[0];
-	if (is_power_on) {
-#ifdef BCMPCIE
-		wifi_platform_bus_enumerate(adapter, FALSE);
-		wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
-#else
-		wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
-		wifi_platform_bus_enumerate(adapter, FALSE);
-#endif /* BCMPCIE */
-	}
-
-#ifdef CONFIG_DTS
-	regulator_put(wifi_regulator);
-#endif /* CONFIG_DTS */
-	return 0;
-}
-
-static int wifi_plat_dev_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	DHD_TRACE(("##> %s\n", __FUNCTION__));
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && \
-	defined(BCMSDIO)
-	bcmsdh_oob_intr_set(0);
-#endif /* (OOB_INTR_ONLY) */
-	return 0;
-}
-
-static int wifi_plat_dev_drv_resume(struct platform_device *pdev)
-{
-	DHD_TRACE(("##> %s\n", __FUNCTION__));
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && \
-	defined(BCMSDIO)
-	if (dhd_os_check_if_up(wl_cfg80211_get_dhdp()))
-		bcmsdh_oob_intr_set(1);
-#endif /* (OOB_INTR_ONLY) */
-	return 0;
-}
-
-#ifdef CONFIG_DTS
-static const struct of_device_id wifi_device_dt_match[] = {
-	{ .compatible = "android,bcmdhd_wlan", },
-	{},
-};
-#endif /* CONFIG_DTS */
-static struct platform_driver wifi_platform_dev_driver = {
-	.probe          = wifi_plat_dev_drv_probe,
-	.remove         = wifi_plat_dev_drv_remove,
-	.suspend        = wifi_plat_dev_drv_suspend,
-	.resume         = wifi_plat_dev_drv_resume,
-	.driver         = {
-	.name   = WIFI_PLAT_NAME,
-#ifdef CONFIG_DTS
-	.of_match_table = wifi_device_dt_match,
-#endif /* CONFIG_DTS */
-	}
-};
-
-static struct platform_driver wifi_platform_dev_driver_legacy = {
-	.probe          = wifi_plat_dev_drv_probe,
-	.remove         = wifi_plat_dev_drv_remove,
-	.suspend        = wifi_plat_dev_drv_suspend,
-	.resume         = wifi_plat_dev_drv_resume,
-	.driver         = {
-	.name	= WIFI_PLAT_NAME2,
-	}
-};
-
-static int wifi_platdev_match(struct device *dev, void *data)
-{
-	char *name = (char*)data;
-	struct platform_device *pdev = to_platform_device(dev);
-
-	if (strcmp(pdev->name, name) == 0) {
-		DHD_ERROR(("found wifi platform device %s\n", name));
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static int wifi_ctrlfunc_register_drv(void)
-{
-	int err = 0;
-	struct device *dev1, *dev2;
-	wifi_adapter_info_t *adapter;
-
-	dev1 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME, wifi_platdev_match);
-	dev2 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME2, wifi_platdev_match);
-
-#if !defined(CONFIG_DTS)
-	if (!dts_enabled) {
-		if (dev1 == NULL && dev2 == NULL) {
-			DHD_ERROR(("no wifi platform data, skip\n"));
-			return -ENXIO;
-		}
-	}
-#endif /* !defined(CONFIG_DTS) */
-
-	/* multi-chip support not enabled, build one adapter information for
-	 * DHD (either SDIO, USB or PCIe)
-	 */
-	adapter = kzalloc(sizeof(wifi_adapter_info_t), GFP_KERNEL);
-	if (adapter == NULL) {
-		DHD_ERROR(("%s:adapter alloc failed", __FUNCTION__));
-		return ENOMEM;
-	}
-	adapter->name = "DHD generic adapter";
-	adapter->bus_type = -1;
-	adapter->bus_num = -1;
-	adapter->slot_num = -1;
-	adapter->irq_num = -1;
-	is_power_on = FALSE;
-	wifi_plat_dev_probe_ret = 0;
-	dhd_wifi_platdata = kzalloc(sizeof(bcmdhd_wifi_platdata_t), GFP_KERNEL);
-	dhd_wifi_platdata->num_adapters = 1;
-	dhd_wifi_platdata->adapters = adapter;
-
-	if (dev1) {
-		err = platform_driver_register(&wifi_platform_dev_driver);
-		if (err) {
-			DHD_ERROR(("%s: failed to register wifi ctrl func driver\n",
-				__FUNCTION__));
-			return err;
-		}
-	}
-	if (dev2) {
-		err = platform_driver_register(&wifi_platform_dev_driver_legacy);
-		if (err) {
-			DHD_ERROR(("%s: failed to register wifi ctrl func legacy driver\n",
-				__FUNCTION__));
-			return err;
-		}
-	}
-
-#if !defined(CONFIG_DTS)
-	if (dts_enabled) {
-		struct resource *resource;
-		adapter->wifi_plat_data = (void *)&dhd_wlan_control;
-		resource = &dhd_wlan_resources;
-		adapter->irq_num = resource->start;
-		adapter->intr_flags = resource->flags & IRQF_TRIGGER_MASK;
-		wifi_plat_dev_probe_ret = dhd_wifi_platform_load();
-	}
-#endif /* !defined(CONFIG_DTS) */
-
-
-#ifdef CONFIG_DTS
-	wifi_plat_dev_probe_ret = platform_driver_register(&wifi_platform_dev_driver);
-#endif /* CONFIG_DTS */
-
-	/* return probe function's return value if registeration succeeded */
-	return wifi_plat_dev_probe_ret;
-}
-
-void wifi_ctrlfunc_unregister_drv(void)
-{
-
-#ifdef CONFIG_DTS
-	DHD_ERROR(("unregister wifi platform drivers\n"));
-	platform_driver_unregister(&wifi_platform_dev_driver);
-#else
-	struct device *dev1, *dev2;
-	dev1 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME, wifi_platdev_match);
-	dev2 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME2, wifi_platdev_match);
-	if (!dts_enabled)
-		if (dev1 == NULL && dev2 == NULL)
-			return;
-
-	DHD_ERROR(("unregister wifi platform drivers\n"));
-	if (dev1)
-		platform_driver_unregister(&wifi_platform_dev_driver);
-	if (dev2)
-		platform_driver_unregister(&wifi_platform_dev_driver_legacy);
-	if (dts_enabled) {
-		wifi_adapter_info_t *adapter;
-		adapter = &dhd_wifi_platdata->adapters[0];
-		if (is_power_on) {
-			wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
-			wifi_platform_bus_enumerate(adapter, FALSE);
-		}
-	}
-#endif /* !defined(CONFIG_DTS) */
-
-	kfree(dhd_wifi_platdata->adapters);
-	dhd_wifi_platdata->adapters = NULL;
-	dhd_wifi_platdata->num_adapters = 0;
-	kfree(dhd_wifi_platdata);
-	dhd_wifi_platdata = NULL;
-}
-
-static int bcmdhd_wifi_plat_dev_drv_probe(struct platform_device *pdev)
-{
-	dhd_wifi_platdata = (bcmdhd_wifi_platdata_t *)(pdev->dev.platform_data);
-
-	return dhd_wifi_platform_load();
-}
-
-static int bcmdhd_wifi_plat_dev_drv_remove(struct platform_device *pdev)
-{
-	int i;
-	wifi_adapter_info_t *adapter;
-	ASSERT(dhd_wifi_platdata != NULL);
-
-	/* power down all adapters */
-	for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
-		adapter = &dhd_wifi_platdata->adapters[i];
-		wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
-		wifi_platform_bus_enumerate(adapter, FALSE);
-	}
-	return 0;
-}
-
-static struct platform_driver dhd_wifi_platform_dev_driver = {
-	.probe          = bcmdhd_wifi_plat_dev_drv_probe,
-	.remove         = bcmdhd_wifi_plat_dev_drv_remove,
-	.driver         = {
-	.name   = WIFI_PLAT_EXT,
-	}
-};
-
-int dhd_wifi_platform_register_drv(void)
-{
-	int err = 0;
-	struct device *dev;
-
-	/* register Broadcom wifi platform data driver if multi-chip is enabled,
-	 * otherwise use Android style wifi platform data (aka wifi control function)
-	 * if it exists
-	 *
-	 * to support multi-chip DHD, Broadcom wifi platform data device must
-	 * be added in kernel early boot (e.g. board config file).
-	 */
-	if (cfg_multichip) {
-		dev = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_EXT, wifi_platdev_match);
-		if (dev == NULL) {
-			DHD_ERROR(("bcmdhd wifi platform data device not found!!\n"));
-			return -ENXIO;
-		}
-		err = platform_driver_register(&dhd_wifi_platform_dev_driver);
-	} else {
-		err = wifi_ctrlfunc_register_drv();
-
-		/* no wifi ctrl func either, load bus directly and ignore this error */
-		if (err) {
-			if (err == -ENXIO) {
-				/* wifi ctrl function does not exist */
-				err = dhd_wifi_platform_load();
-			} else {
-				/* unregister driver due to initialization failure */
-				wifi_ctrlfunc_unregister_drv();
-			}
-		}
-	}
-
-	return err;
-}
-
-#ifdef BCMPCIE
-static int dhd_wifi_platform_load_pcie(void)
-{
-	int err = 0;
-	int i;
-	wifi_adapter_info_t *adapter;
-
-	BCM_REFERENCE(i);
-	BCM_REFERENCE(adapter);
-
-	if (dhd_wifi_platdata == NULL) {
-		err = dhd_bus_register();
-	} else {
-		if (dhd_download_fw_on_driverload) {
-			/* power up all adapters */
-			for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
-				int retry = POWERUP_MAX_RETRY;
-				adapter = &dhd_wifi_platdata->adapters[i];
-
-				DHD_ERROR(("Power-up adapter '%s'\n", adapter->name));
-				DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
-					adapter->irq_num, adapter->intr_flags, adapter->fw_path,
-					adapter->nv_path));
-				DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
-					adapter->bus_type, adapter->bus_num, adapter->slot_num));
-
-				do {
-					err = wifi_platform_set_power(adapter,
-						TRUE, WIFI_TURNON_DELAY);
-					if (err) {
-						DHD_ERROR(("failed to power up %s,"
-							" %d retry left\n",
-							adapter->name, retry));
-						/* WL_REG_ON state unknown, Power off forcely */
-						wifi_platform_set_power(adapter,
-							FALSE, WIFI_TURNOFF_DELAY);
-						continue;
-					} else {
-						err = wifi_platform_bus_enumerate(adapter, TRUE);
-						if (err) {
-							DHD_ERROR(("failed to enumerate bus %s, "
-								"%d retry left\n",
-								adapter->name, retry));
-							wifi_platform_set_power(adapter, FALSE,
-								WIFI_TURNOFF_DELAY);
-						} else {
-							break;
-						}
-					}
-				} while (retry--);
-
-				if (!retry) {
-					DHD_ERROR(("failed to power up %s, max retry reached**\n",
-						adapter->name));
-					return -ENODEV;
-				}
-			}
-		}
-
-		err = dhd_bus_register();
-
-		if (err) {
-			DHD_ERROR(("%s: pcie_register_driver failed\n", __FUNCTION__));
-			if (dhd_download_fw_on_driverload) {
-				/* power down all adapters */
-				for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
-					adapter = &dhd_wifi_platdata->adapters[i];
-					wifi_platform_bus_enumerate(adapter, FALSE);
-					wifi_platform_set_power(adapter,
-						FALSE, WIFI_TURNOFF_DELAY);
-				}
-			}
-		}
-	}
-
-	return err;
-}
-#else
-static int dhd_wifi_platform_load_pcie(void)
-{
-	return 0;
-}
-#endif /* BCMPCIE  */
-
-
-void dhd_wifi_platform_unregister_drv(void)
-{
-	if (cfg_multichip)
-		platform_driver_unregister(&dhd_wifi_platform_dev_driver);
-	else
-		wifi_ctrlfunc_unregister_drv();
-}
-
-extern int dhd_watchdog_prio;
-extern int dhd_dpc_prio;
-extern uint dhd_deferred_tx;
-#if defined(BCMLXSDMMC)
-extern struct semaphore dhd_registration_sem;
-#endif 
-
-#ifdef BCMSDIO
-static int dhd_wifi_platform_load_sdio(void)
-{
-	int i;
-	int err = 0;
-	wifi_adapter_info_t *adapter;
-
-	BCM_REFERENCE(i);
-	BCM_REFERENCE(adapter);
-	/* Sanity check on the module parameters
-	 * - Both watchdog and DPC as tasklets are ok
-	 * - If both watchdog and DPC are threads, TX must be deferred
-	 */
-	if (!(dhd_watchdog_prio < 0 && dhd_dpc_prio < 0) &&
-		!(dhd_watchdog_prio >= 0 && dhd_dpc_prio >= 0 && dhd_deferred_tx))
-		return -EINVAL;
-
-#if defined(BCMLXSDMMC)
-	if (dhd_wifi_platdata == NULL) {
-		DHD_ERROR(("DHD wifi platform data is required for Android build\n"));
-		return -EINVAL;
-	}
-
-	sema_init(&dhd_registration_sem, 0);
-	/* power up all adapters */
-	for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
-		bool chip_up = FALSE;
-		int retry = POWERUP_MAX_RETRY;
-		struct semaphore dhd_chipup_sem;
-
-		adapter = &dhd_wifi_platdata->adapters[i];
-
-		DHD_ERROR(("Power-up adapter '%s'\n", adapter->name));
-		DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
-			adapter->irq_num, adapter->intr_flags, adapter->fw_path, adapter->nv_path));
-		DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
-			adapter->bus_type, adapter->bus_num, adapter->slot_num));
-
-		do {
-			sema_init(&dhd_chipup_sem, 0);
-			err = dhd_bus_reg_sdio_notify(&dhd_chipup_sem);
-			if (err) {
-				DHD_ERROR(("%s dhd_bus_reg_sdio_notify fail(%d)\n\n",
-					__FUNCTION__, err));
-				return err;
-			}
-			err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY);
-			if (err) {
-				/* WL_REG_ON state unknown, Power off forcely */
-				wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
-				continue;
-			} else {
-				wifi_platform_bus_enumerate(adapter, TRUE);
-				err = 0;
-			}
-
-			if (down_timeout(&dhd_chipup_sem, msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) {
-				dhd_bus_unreg_sdio_notify();
-				chip_up = TRUE;
-				break;
-			}
-
-			DHD_ERROR(("failed to power up %s, %d retry left\n", adapter->name, retry));
-			dhd_bus_unreg_sdio_notify();
-			wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
-			wifi_platform_bus_enumerate(adapter, FALSE);
-		} while (retry--);
-
-		if (!chip_up) {
-			DHD_ERROR(("failed to power up %s, max retry reached**\n", adapter->name));
-			return -ENODEV;
-		}
-
-	}
-
-	err = dhd_bus_register();
-
-	if (err) {
-		DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__));
-		goto fail;
-	}
-
-
-	/*
-	 * Wait till MMC sdio_register_driver callback called and made driver attach.
-	 * It's needed to make sync up exit from dhd insmod  and
-	 * Kernel MMC sdio device callback registration
-	 */
-	err = down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT));
-	if (err) {
-		DHD_ERROR(("%s: sdio_register_driver timeout or error \n", __FUNCTION__));
-		dhd_bus_unregister();
-		goto fail;
-	}
-
-	return err;
-
-fail:
-	/* power down all adapters */
-	for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
-		adapter = &dhd_wifi_platdata->adapters[i];
-		wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
-		wifi_platform_bus_enumerate(adapter, FALSE);
-	}
-#else
-
-	/* x86 bring-up PC needs no power-up operations */
-	err = dhd_bus_register();
-
-#endif 
-
-	return err;
-}
-#else /* BCMSDIO */
-static int dhd_wifi_platform_load_sdio(void)
-{
-	return 0;
-}
-#endif /* BCMSDIO */
-
-static int dhd_wifi_platform_load_usb(void)
-{
-	return 0;
-}
-
-static int dhd_wifi_platform_load()
-{
-	int err = 0;
-
-		wl_android_init();
-
-	if ((err = dhd_wifi_platform_load_usb()))
-		goto end;
-	else if ((err = dhd_wifi_platform_load_sdio()))
-		goto end;
-	else
-		err = dhd_wifi_platform_load_pcie();
-
-end:
-	if (err)
-		wl_android_exit();
-	else
-		wl_android_post_init();
-
-	return err;
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_sched.c b/drivers/net/wireless/bcmdhd/dhd_linux_sched.c
deleted file mode 100644
index 66eb894..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_linux_sched.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Expose some of the kernel scheduler routines
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_linux_sched.c 514727 2014-11-12 03:02:48Z $
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <typedefs.h>
-#include <linuxver.h>
-
-int setScheduler(struct task_struct *p, int policy, struct sched_param *param)
-{
-	int rc = 0;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-	rc = sched_setscheduler(p, policy, param);
-#endif /* LinuxVer */
-	return rc;
-}
-
-int get_scheduler_policy(struct task_struct *p)
-{
-	int rc = SCHED_NORMAL;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-	rc = p->policy;
-#endif /* LinuxVer */
-	return rc;
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_wq.c b/drivers/net/wireless/bcmdhd/dhd_linux_wq.c
deleted file mode 100644
index d2513cc..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_linux_wq.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Broadcom Dongle Host Driver (DHD), Generic work queue framework
- * Generic interface to handle dhd deferred work events
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_linux_wq.c 514727 2014-11-12 03:02:48Z $
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/fcntl.h>
-#include <linux/fs.h>
-#include <linux/ip.h>
-#include <linux/kfifo.h>
-
-#include <linuxver.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <bcmendian.h>
-#include <bcmdevs.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_dbg.h>
-#include <dhd_linux_wq.h>
-
-struct dhd_deferred_event_t {
-	u8	event; /* holds the event */
-	void	*event_data; /* Holds event specific data */
-	event_handler_t event_handler;
-};
-#define DEFRD_EVT_SIZE	sizeof(struct dhd_deferred_event_t)
-
-struct dhd_deferred_wq {
-	struct work_struct	deferred_work; /* should be the first member */
-
-	/*
-	 * work events may occur simultaneously.
-	 * Can hold upto 64 low priority events and 4 high priority events
-	 */
-#define DHD_PRIO_WORK_FIFO_SIZE	(4 * sizeof(struct dhd_deferred_event_t))
-#define DHD_WORK_FIFO_SIZE	(64 * sizeof(struct dhd_deferred_event_t))
-	struct kfifo			*prio_fifo;
-	struct kfifo			*work_fifo;
-	u8				*prio_fifo_buf;
-	u8				*work_fifo_buf;
-	spinlock_t			work_lock;
-	void				*dhd_info; /* review: does it require */
-};
-
-static inline struct kfifo*
-dhd_kfifo_init(u8 *buf, int size, spinlock_t *lock)
-{
-	struct kfifo *fifo;
-	gfp_t flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC;
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
-	fifo = kfifo_init(buf, size, flags, lock);
-#else
-	fifo = (struct kfifo *)kzalloc(sizeof(struct kfifo), flags);
-	if (!fifo) {
-		return NULL;
-	}
-	kfifo_init(fifo, buf, size);
-#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) */
-	return fifo;
-}
-
-static inline void
-dhd_kfifo_free(struct kfifo *fifo)
-{
-	kfifo_free(fifo);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
-	/* FC11 releases the fifo memory */
-	kfree(fifo);
-#endif
-}
-
-/* deferred work functions */
-static void dhd_deferred_work_handler(struct work_struct *data);
-
-void*
-dhd_deferred_work_init(void *dhd_info)
-{
-	struct dhd_deferred_wq	*work = NULL;
-	u8*	buf;
-	unsigned long	fifo_size = 0;
-	gfp_t	flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC;
-
-	if (!dhd_info) {
-		DHD_ERROR(("%s: dhd info not initialized\n", __FUNCTION__));
-		goto return_null;
-	}
-
-	work = (struct dhd_deferred_wq *)kzalloc(sizeof(struct dhd_deferred_wq),
-		flags);
-
-	if (!work) {
-		DHD_ERROR(("%s: work queue creation failed \n", __FUNCTION__));
-		goto return_null;
-	}
-
-	INIT_WORK((struct work_struct *)work, dhd_deferred_work_handler);
-
-	/* initialize event fifo */
-	spin_lock_init(&work->work_lock);
-
-	/* allocate buffer to hold prio events */
-	fifo_size = DHD_PRIO_WORK_FIFO_SIZE;
-	fifo_size = is_power_of_2(fifo_size)? fifo_size : roundup_pow_of_two(fifo_size);
-	buf = (u8*)kzalloc(fifo_size, flags);
-	if (!buf) {
-		DHD_ERROR(("%s: prio work fifo allocation failed \n", __FUNCTION__));
-		goto return_null;
-	}
-
-	/* Initialize prio event fifo */
-	work->prio_fifo = dhd_kfifo_init(buf, fifo_size, &work->work_lock);
-	if (!work->prio_fifo) {
-		kfree(buf);
-		goto return_null;
-	}
-
-	/* allocate buffer to hold work events */
-	fifo_size = DHD_WORK_FIFO_SIZE;
-	fifo_size = is_power_of_2(fifo_size)? fifo_size : roundup_pow_of_two(fifo_size);
-	buf = (u8*)kzalloc(fifo_size, flags);
-	if (!buf) {
-		DHD_ERROR(("%s: work fifo allocation failed \n", __FUNCTION__));
-		goto return_null;
-	}
-
-	/* Initialize event fifo */
-	work->work_fifo = dhd_kfifo_init(buf, fifo_size, &work->work_lock);
-	if (!work->work_fifo) {
-		kfree(buf);
-		goto return_null;
-	}
-
-	work->dhd_info = dhd_info;
-	DHD_ERROR(("%s: work queue initialized \n", __FUNCTION__));
-	return work;
-
-return_null:
-
-	if (work)
-		dhd_deferred_work_deinit(work);
-
-	return NULL;
-}
-
-void
-dhd_deferred_work_deinit(void *work)
-{
-	struct dhd_deferred_wq *deferred_work = work;
-
-
-	if (!deferred_work) {
-		DHD_ERROR(("%s: deferred work has been freed alread \n", __FUNCTION__));
-		return;
-	}
-
-	/* cancel the deferred work handling */
-	cancel_work_sync((struct work_struct *)deferred_work);
-
-	/*
-	 * free work event fifo.
-	 * kfifo_free frees locally allocated fifo buffer
-	 */
-	if (deferred_work->prio_fifo)
-		dhd_kfifo_free(deferred_work->prio_fifo);
-
-	if (deferred_work->work_fifo)
-		dhd_kfifo_free(deferred_work->work_fifo);
-
-	kfree(deferred_work);
-}
-
-/*
- *	Prepares event to be queued
- *	Schedules the event
- */
-int
-dhd_deferred_schedule_work(void *workq, void *event_data, u8 event,
-	event_handler_t event_handler, u8 priority)
-{
-	struct dhd_deferred_wq *deferred_wq = (struct dhd_deferred_wq *) workq;
-	struct	dhd_deferred_event_t	deferred_event;
-	int	status;
-
-	if (!deferred_wq) {
-		DHD_ERROR(("%s: work queue not initialized \n", __FUNCTION__));
-		ASSERT(0);
-		return DHD_WQ_STS_UNINITIALIZED;
-	}
-
-	if (!event || (event >= DHD_MAX_WQ_EVENTS)) {
-		DHD_ERROR(("%s: Unknown event \n", __FUNCTION__));
-		return DHD_WQ_STS_UNKNOWN_EVENT;
-	}
-
-	/*
-	 * default element size is 1, which can be changed
-	 * using kfifo_esize(). Older kernel(FC11) doesn't support
-	 * changing element size. For compatibility changing
-	 * element size is not prefered
-	 */
-	ASSERT(kfifo_esize(deferred_wq->prio_fifo) == 1);
-	ASSERT(kfifo_esize(deferred_wq->work_fifo) == 1);
-
-	deferred_event.event = event;
-	deferred_event.event_data = event_data;
-	deferred_event.event_handler = event_handler;
-
-	if (priority == DHD_WORK_PRIORITY_HIGH) {
-		status = kfifo_in_spinlocked(deferred_wq->prio_fifo, &deferred_event,
-			DEFRD_EVT_SIZE, &deferred_wq->work_lock);
-	} else {
-		status = kfifo_in_spinlocked(deferred_wq->work_fifo, &deferred_event,
-			DEFRD_EVT_SIZE, &deferred_wq->work_lock);
-	}
-
-	if (!status) {
-		return DHD_WQ_STS_SCHED_FAILED;
-	}
-	schedule_work((struct work_struct *)deferred_wq);
-	return DHD_WQ_STS_OK;
-}
-
-static int
-dhd_get_scheduled_work(struct dhd_deferred_wq *deferred_wq, struct dhd_deferred_event_t *event)
-{
-	int	status = 0;
-
-	if (!deferred_wq) {
-		DHD_ERROR(("%s: work queue not initialized \n", __FUNCTION__));
-		return DHD_WQ_STS_UNINITIALIZED;
-	}
-
-	/*
-	 * default element size is 1 byte, which can be changed
-	 * using kfifo_esize(). Older kernel(FC11) doesn't support
-	 * changing element size. For compatibility changing
-	 * element size is not prefered
-	 */
-	ASSERT(kfifo_esize(deferred_wq->prio_fifo) == 1);
-	ASSERT(kfifo_esize(deferred_wq->work_fifo) == 1);
-
-	/* first read  priorit event fifo */
-	status = kfifo_out_spinlocked(deferred_wq->prio_fifo, event,
-		DEFRD_EVT_SIZE, &deferred_wq->work_lock);
-
-	if (!status) {
-		/* priority fifo is empty. Now read low prio work fifo */
-		status = kfifo_out_spinlocked(deferred_wq->work_fifo, event,
-			DEFRD_EVT_SIZE, &deferred_wq->work_lock);
-	}
-
-	return status;
-}
-
-/*
- *	Called when work is scheduled
- */
-static void
-dhd_deferred_work_handler(struct work_struct *work)
-{
-	struct dhd_deferred_wq		*deferred_work = (struct dhd_deferred_wq *)work;
-	struct dhd_deferred_event_t	work_event;
-	int				status;
-
-	if (!deferred_work) {
-		DHD_ERROR(("%s: work queue not initialized\n", __FUNCTION__));
-		return;
-	}
-
-	do {
-		status = dhd_get_scheduled_work(deferred_work, &work_event);
-		DHD_TRACE(("%s: event to handle %d \n", __FUNCTION__, status));
-		if (!status) {
-			DHD_TRACE(("%s: No event to handle %d \n", __FUNCTION__, status));
-			break;
-		}
-
-		if (work_event.event > DHD_MAX_WQ_EVENTS) {
-			DHD_TRACE(("%s: Unknown event %d \n", __FUNCTION__, work_event.event));
-			break;
-		}
-
-		if (work_event.event_handler) {
-			work_event.event_handler(deferred_work->dhd_info,
-				work_event.event_data, work_event.event);
-		} else {
-			DHD_ERROR(("%s: event not defined %d\n", __FUNCTION__, work_event.event));
-		}
-	} while (1);
-	return;
-}
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_wq.h b/drivers/net/wireless/bcmdhd/dhd_linux_wq.h
deleted file mode 100644
index e6197b2..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_linux_wq.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Broadcom Dongle Host Driver (DHD), Generic work queue framework
- * Generic interface to handle dhd deferred work events
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_linux_wq.h 597512 2015-11-05 11:37:36Z $
- */
-#ifndef _dhd_linux_wq_h_
-#define _dhd_linux_wq_h_
-/*
- *	Work event definitions
- */
-enum _wq_event {
-	DHD_WQ_WORK_IF_ADD = 1,
-	DHD_WQ_WORK_IF_DEL,
-	DHD_WQ_WORK_SET_MAC,
-	DHD_WQ_WORK_SET_MCAST_LIST,
-	DHD_WQ_WORK_IPV6_NDO,
-	DHD_WQ_WORK_HANG_MSG,
-	DHD_WQ_WORK_SOC_RAM_DUMP,
-	DHD_WQ_WORK_DHD_LOG_DUMP,
-
-	DHD_MAX_WQ_EVENTS
-};
-
-/*
- *	Work event priority
- */
-#define DHD_WORK_PRIORITY_LOW	0
-#define DHD_WORK_PRIORITY_HIGH	1
-
-/*
- *	Error definitions
- */
-#define DHD_WQ_STS_OK			 0
-#define DHD_WQ_STS_FAILED		-1	/* General failure */
-#define DHD_WQ_STS_UNINITIALIZED	-2
-#define DHD_WQ_STS_SCHED_FAILED		-3
-#define DHD_WQ_STS_UNKNOWN_EVENT	-4
-
-typedef void (*event_handler_t)(void *handle, void *event_data, u8 event);
-
-void *dhd_deferred_work_init(void *dhd);
-void dhd_deferred_work_deinit(void *workq);
-int dhd_deferred_schedule_work(void *workq, void *event_data, u8 event,
-	event_handler_t evt_handler, u8 priority);
-#endif /* _dhd_linux_wq_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c
deleted file mode 100644
index 3bd9a45..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c
+++ /dev/null
@@ -1,6413 +0,0 @@
-/**
- * @file definition of host message ring functionality
- * Provides type definitions and function prototypes used to link the
- * DHD OS, bus, and protocol modules.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_msgbuf.c 605475 2015-12-10 12:49:49Z $
- */
-
-
-#include <typedefs.h>
-#include <osl.h>
-
-#include <bcmutils.h>
-#include <bcmmsgbuf.h>
-#include <bcmendian.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_proto.h>
-
-#include <dhd_bus.h>
-
-#include <dhd_dbg.h>
-#include <siutils.h>
-
-
-#include <dhd_flowring.h>
-
-#include <pcie_core.h>
-#include <bcmpcie.h>
-#include <dhd_pcie.h>
-
-#if defined(DHD_LB)
-#include <linux/cpu.h>
-#include <bcm_ring.h>
-#define DHD_LB_WORKQ_SZ                            (8192)
-#define DHD_LB_WORKQ_SYNC           (16)
-#define DHD_LB_WORK_SCHED           (DHD_LB_WORKQ_SYNC * 2)
-#endif /* DHD_LB */
-
-
-/**
- * Host configures a soft doorbell for d2h rings, by specifying a 32bit host
- * address where a value must be written. Host may also interrupt coalescing
- * on this soft doorbell.
- * Use Case: Hosts with network processors, may register with the dongle the
- * network processor's thread wakeup register and a value corresponding to the
- * core/thread context. Dongle will issue a write transaction <address,value>
- * to the PCIE RC which will need to be routed to the mapped register space, by
- * the host.
- */
-/* #define DHD_D2H_SOFT_DOORBELL_SUPPORT */
-
-/* Dependency Check */
-#if defined(IOCTLRESP_USE_CONSTMEM) && defined(DHD_USE_STATIC_CTRLBUF)
-#error "DHD_USE_STATIC_CTRLBUF is NOT working with DHD_USE_OSLPKT_FOR_RESPBUF"
-#endif /* IOCTLRESP_USE_CONSTMEM && DHD_USE_STATIC_CTRLBUF */
-
-#define RETRIES 2		/* # of retries to retrieve matching ioctl response */
-
-#define DEFAULT_RX_BUFFERS_TO_POST	256
-#define RXBUFPOST_THRESHOLD			32
-#define RX_BUF_BURST				32 /* Rx buffers for MSDU Data */
-
-#define DHD_STOP_QUEUE_THRESHOLD	200
-#define DHD_START_QUEUE_THRESHOLD	100
-
-#define RX_DMA_OFFSET		8 /* Mem2mem DMA inserts an extra 8 */
-#define IOCT_RETBUF_SIZE	(RX_DMA_OFFSET + WLC_IOCTL_MAXLEN)
-#define FLOWRING_SIZE		(H2DRING_TXPOST_MAX_ITEM * H2DRING_TXPOST_ITEMSIZE)
-
-/* flags for ioctl pending status */
-#define MSGBUF_IOCTL_ACK_PENDING	(1<<0)
-#define MSGBUF_IOCTL_RESP_PENDING	(1<<1)
-
-#define DMA_ALIGN_LEN		4
-
-#define DMA_D2H_SCRATCH_BUF_LEN	8
-#define DMA_XFER_LEN_LIMIT	0x400000
-
-#define DHD_FLOWRING_IOCTL_BUFPOST_PKTSZ		8192
-
-#define DHD_FLOWRING_MAX_EVENTBUF_POST			8
-#define DHD_FLOWRING_MAX_IOCTLRESPBUF_POST		8
-
-#define DHD_PROT_FUNCS	37
-
-/* Length of buffer in host for bus throughput measurement */
-#define DHD_BUS_TPUT_BUF_LEN 2048
-
-#define TXP_FLUSH_NITEMS
-
-/* optimization to write "n" tx items at a time to ring */
-#define TXP_FLUSH_MAX_ITEMS_FLUSH_CNT	48
-
-#define RING_NAME_MAX_LENGTH		24
-
-
-struct msgbuf_ring; /* ring context for common and flow rings */
-
-/**
- * PCIE D2H DMA Complete Sync Modes
- *
- * Firmware may interrupt the host, prior to the D2H Mem2Mem DMA completes into
- * Host system memory. A WAR using one of 3 approaches is needed:
- * 1. Dongle places a modulo-253 seqnum in last word of each D2H message
- * 2. XOR Checksum, with epoch# in each work item. Dongle builds an XOR checksum
- *    writes in the last word of each work item. Each work item has a seqnum
- *    number = sequence num % 253.
- *
- * 3. Read Barrier: Dongle does a host memory read access prior to posting an
- *    interrupt, ensuring that D2H data transfer indeed completed.
- * 4. Dongle DMA's all indices after producing items in the D2H ring, flushing
- *    ring contents before the indices.
- *
- * Host does not sync for DMA to complete with option #3 or #4, and a noop sync
- * callback (see dhd_prot_d2h_sync_none) may be bound.
- *
- * Dongle advertizes host side sync mechanism requirements.
- */
-#define PCIE_D2H_SYNC
-
-#if defined(PCIE_D2H_SYNC)
-#define PCIE_D2H_SYNC_WAIT_TRIES    (512UL)
-#define PCIE_D2H_SYNC_NUM_OF_STEPS	(3UL)
-#define PCIE_D2H_SYNC_DELAY			(50UL)	/* in terms of usecs */
-
-/**
- * Custom callback attached based upon D2H DMA Sync mode advertized by dongle.
- *
- * On success: return cmn_msg_hdr_t::msg_type
- * On failure: return 0 (invalid msg_type)
- */
-typedef uint8 (* d2h_sync_cb_t)(dhd_pub_t *dhd, struct msgbuf_ring *ring,
-                                volatile cmn_msg_hdr_t *msg, int msglen);
-#endif /* PCIE_D2H_SYNC */
-
-
-/*
- * +----------------------------------------------------------------------------
- *
- * RingIds and FlowId are not equivalent as ringids include D2H rings whereas
- * flowids do not.
- *
- * Dongle advertizes the max H2D rings, as max_sub_queues = 'N' which includes
- * the H2D common rings as well as the (N-BCMPCIE_H2D_COMMON_MSGRINGS) flowrings
- *
- * Here is a sample mapping for (based on PCIE Full Dongle Rev5) where,
- *  BCMPCIE_H2D_COMMON_MSGRINGS = 2, i.e. 2 H2D common rings,
- *  BCMPCIE_COMMON_MSGRINGS     = 5, i.e. include 3 D2H common rings.
- *
- *  H2D Control  Submit   RingId = 0        FlowId = 0 reserved never allocated
- *  H2D RxPost   Submit   RingId = 1        FlowId = 1 reserved never allocated
- *
- *  D2H Control  Complete RingId = 2
- *  D2H Transmit Complete RingId = 3
- *  D2H Receive  Complete RingId = 4
- *
- *  H2D TxPost   FLOWRING RingId = 5         FlowId = 2     (1st flowring)
- *  H2D TxPost   FLOWRING RingId = 6         FlowId = 3     (2nd flowring)
- *  H2D TxPost   FLOWRING RingId = 5 + (N-1) FlowId = (N-1) (Nth flowring)
- *
- * When TxPost FlowId(s) are allocated, the FlowIds [0..FLOWID_RESERVED) are
- * unused, where FLOWID_RESERVED is BCMPCIE_H2D_COMMON_MSGRINGS.
- *
- * Example: when a system supports 4 bc/mc and 128 uc flowrings, with
- * BCMPCIE_H2D_COMMON_MSGRINGS = 2, and BCMPCIE_H2D_COMMON_MSGRINGS = 5, and the
- * FlowId values would be in the range [2..133] and the corresponding
- * RingId values would be in the range [5..136].
- *
- * The flowId allocator, may chose to, allocate Flowids:
- *   bc/mc (per virtual interface) in one consecutive range [2..(2+VIFS))
- *   X# of uc flowids in consecutive ranges (per station Id), where X is the
- *   packet's access category (e.g. 4 uc flowids per station).
- *
- * CAUTION:
- * When DMA indices array feature is used, RingId=5, corresponding to the 0th
- * FLOWRING, will actually use the FlowId as index into the H2D DMA index,
- * since the FlowId truly represents the index in the H2D DMA indices array.
- *
- * Likewise, in the D2H direction, the RingId - BCMPCIE_H2D_COMMON_MSGRINGS,
- * will represent the index in the D2H DMA indices array.
- *
- * +----------------------------------------------------------------------------
- */
-
-/* First TxPost Flowring Id */
-#define DHD_FLOWRING_START_FLOWID   BCMPCIE_H2D_COMMON_MSGRINGS
-
-/* Determine whether a ringid belongs to a TxPost flowring */
-#define DHD_IS_FLOWRING(ringid) \
-	((ringid) >= BCMPCIE_COMMON_MSGRINGS)
-
-/* Convert a H2D TxPost FlowId to a MsgBuf RingId */
-#define DHD_FLOWID_TO_RINGID(flowid) \
-	(BCMPCIE_COMMON_MSGRINGS + ((flowid) - BCMPCIE_H2D_COMMON_MSGRINGS))
-
-/* Convert a MsgBuf RingId to a H2D TxPost FlowId */
-#define DHD_RINGID_TO_FLOWID(ringid) \
-	(BCMPCIE_H2D_COMMON_MSGRINGS + ((ringid) - BCMPCIE_COMMON_MSGRINGS))
-
-/* Convert a H2D MsgBuf RingId to an offset index into the H2D DMA indices array
- * This may be used for the H2D DMA WR index array or H2D DMA RD index array or
- * any array of H2D rings.
- */
-#define DHD_H2D_RING_OFFSET(ringid) \
-	((DHD_IS_FLOWRING(ringid)) ? DHD_RINGID_TO_FLOWID(ringid) : (ringid))
-
-/* Convert a D2H MsgBuf RingId to an offset index into the D2H DMA indices array
- * This may be used for the D2H DMA WR index array or D2H DMA RD index array or
- * any array of D2H rings.
- */
-#define DHD_D2H_RING_OFFSET(ringid) \
-	((ringid) - BCMPCIE_H2D_COMMON_MSGRINGS)
-
-/* Convert a D2H DMA Indices Offset to a RingId */
-#define DHD_D2H_RINGID(offset) \
-	((offset) + BCMPCIE_H2D_COMMON_MSGRINGS)
-
-
-#define DHD_DMAH_NULL      ((void*)NULL)
-
-/*
- * Pad a DMA-able buffer by an additional cachline. If the end of the DMA-able
- * buffer does not occupy the entire cacheline, and another object is placed
- * following the DMA-able buffer, data corruption may occur if the DMA-able
- * buffer is used to DMAing into (e.g. D2H direction), when HW cache coherency
- * is not available.
- */
-#if defined(L1_CACHE_BYTES)
-#define DHD_DMA_PAD        (L1_CACHE_BYTES)
-#else
-#define DHD_DMA_PAD        (128)
-#endif
-
-/* Used in loopback tests */
-typedef struct dhd_dmaxfer {
-	dhd_dma_buf_t srcmem;
-	dhd_dma_buf_t dstmem;
-	uint32        srcdelay;
-	uint32        destdelay;
-	uint32        len;
-	bool          in_progress;
-} dhd_dmaxfer_t;
-
-/**
- * msgbuf_ring : This object manages the host side ring that includes a DMA-able
- * buffer, the WR and RD indices, ring parameters such as max number of items
- * an length of each items, and other miscellaneous runtime state.
- * A msgbuf_ring may be used to represent a H2D or D2H common ring or a
- * H2D TxPost ring as specified in the PCIE FullDongle Spec.
- * Ring parameters are conveyed to the dongle, which maintains its own peer end
- * ring state. Depending on whether the DMA Indices feature is supported, the
- * host will update the WR/RD index in the DMA indices array in host memory or
- * directly in dongle memory.
- */
-typedef struct msgbuf_ring {
-	bool           inited;
-	uint16         idx;       /* ring id */
-	uint16         rd;        /* read index */
-	uint16         curr_rd;   /* read index for debug */
-	uint16         wr;        /* write index */
-	uint16         max_items; /* maximum number of items in ring */
-	uint16         item_len;  /* length of each item in the ring */
-	sh_addr_t      base_addr; /* LITTLE ENDIAN formatted: base address */
-	dhd_dma_buf_t  dma_buf;   /* DMA-able buffer: pa, va, len, dmah, secdma */
-	uint32         seqnum;    /* next expected item's sequence number */
-#ifdef TXP_FLUSH_NITEMS
-	void           *start_addr;
-	/* # of messages on ring not yet announced to dongle */
-	uint16         pend_items_count;
-#endif /* TXP_FLUSH_NITEMS */
-	uchar		name[RING_NAME_MAX_LENGTH];
-} msgbuf_ring_t;
-
-#define DHD_RING_BGN_VA(ring)           ((ring)->dma_buf.va)
-#define DHD_RING_END_VA(ring) \
-	((uint8 *)(DHD_RING_BGN_VA((ring))) + \
-	 (((ring)->max_items - 1) * (ring)->item_len))
-
-
-
-/** DHD protocol handle. Is an opaque type to other DHD software layers. */
-typedef struct dhd_prot {
-	osl_t *osh;		/* OSL handle */
-	uint16 rxbufpost;
-	uint16 max_rxbufpost;
-	uint16 max_eventbufpost;
-	uint16 max_ioctlrespbufpost;
-	uint16 cur_event_bufs_posted;
-	uint16 cur_ioctlresp_bufs_posted;
-
-	/* Flow control mechanism based on active transmits pending */
-	uint16 active_tx_count; /* increments on every packet tx, and decrements on tx_status */
-	uint16 max_tx_count;
-	uint16 txp_threshold;  /* optimization to write "n" tx items at a time to ring */
-
-	/* MsgBuf Ring info: has a dhd_dma_buf that is dynamically allocated */
-	msgbuf_ring_t h2dring_ctrl_subn; /* H2D ctrl message submission ring */
-	msgbuf_ring_t h2dring_rxp_subn; /* H2D RxBuf post ring */
-	msgbuf_ring_t d2hring_ctrl_cpln; /* D2H ctrl completion ring */
-	msgbuf_ring_t d2hring_tx_cpln; /* D2H Tx complete message ring */
-	msgbuf_ring_t d2hring_rx_cpln; /* D2H Rx complete message ring */
-
-	msgbuf_ring_t *h2d_flowrings_pool; /* Pool of preallocated flowings */
-	dhd_dma_buf_t flowrings_dma_buf; /* Contiguous DMA buffer for flowrings */
-	uint16        h2d_rings_total; /* total H2D (common rings + flowrings) */
-
-	uint32		rx_dataoffset;
-
-	dhd_mb_ring_t	mb_ring_fn;	/* called when dongle needs to be notified of new msg */
-
-	/* ioctl related resources */
-	uint8 ioctl_state;
-	int16 ioctl_status;		/* status returned from dongle */
-	uint16 ioctl_resplen;
-	dhd_ioctl_recieved_status_t ioctl_received;
-	uint curr_ioctl_cmd;
-	dhd_dma_buf_t	retbuf;		/* For holding ioctl response */
-	dhd_dma_buf_t	ioctbuf;	/* For holding ioctl request */
-
-	dhd_dma_buf_t	d2h_dma_scratch_buf;	/* For holding d2h scratch */
-
-	/* DMA-able arrays for holding WR and RD indices */
-	uint32          rw_index_sz; /* Size of a RD or WR index in dongle */
-	dhd_dma_buf_t   h2d_dma_indx_wr_buf;	/* Array of H2D WR indices */
-	dhd_dma_buf_t	h2d_dma_indx_rd_buf;	/* Array of H2D RD indices */
-	dhd_dma_buf_t	d2h_dma_indx_wr_buf;	/* Array of D2H WR indices */
-	dhd_dma_buf_t	d2h_dma_indx_rd_buf;	/* Array of D2H RD indices */
-
-	dhd_dma_buf_t	host_bus_throughput_buf; /* bus throughput measure buffer */
-
-	dhd_dma_buf_t   *flowring_buf;    /* pool of flow ring buf */
-	uint32			flowring_num;
-
-#if defined(PCIE_D2H_SYNC)
-	d2h_sync_cb_t d2h_sync_cb; /* Sync on D2H DMA done: SEQNUM or XORCSUM */
-	ulong d2h_sync_wait_max; /* max number of wait loops to receive one msg */
-	ulong d2h_sync_wait_tot; /* total wait loops */
-#endif  /* PCIE_D2H_SYNC */
-
-	dhd_dmaxfer_t	dmaxfer; /* for test/DMA loopback */
-
-	uint16		ioctl_seq_no;
-	uint16		data_seq_no;
-	uint16		ioctl_trans_id;
-	void		*pktid_map_handle; /* a pktid maps to a packet and its metadata */
-	bool		metadata_dbg;
-	void		*pktid_map_handle_ioctl;
-
-	/* Applications/utilities can read tx and rx metadata using IOVARs */
-	uint16		rx_metadata_offset;
-	uint16		tx_metadata_offset;
-
-
-#if defined(DHD_D2H_SOFT_DOORBELL_SUPPORT)
-	/* Host's soft doorbell configuration */
-	bcmpcie_soft_doorbell_t soft_doorbell[BCMPCIE_D2H_COMMON_MSGRINGS];
-#endif /* DHD_D2H_SOFT_DOORBELL_SUPPORT */
-#if defined(DHD_LB)
-	/* Work Queues to be used by the producer and the consumer, and threshold
-	 * when the WRITE index must be synced to consumer's workq
-	 */
-#if defined(DHD_LB_TXC)
-	uint32 tx_compl_prod_sync ____cacheline_aligned;
-	bcm_workq_t tx_compl_prod, tx_compl_cons;
-#endif /* DHD_LB_TXC */
-#if defined(DHD_LB_RXC)
-	uint32 rx_compl_prod_sync ____cacheline_aligned;
-	bcm_workq_t rx_compl_prod, rx_compl_cons;
-#endif /* DHD_LB_RXC */
-#endif /* DHD_LB */
-} dhd_prot_t;
-
-/* Convert a dmaaddr_t to a base_addr with htol operations */
-static INLINE void dhd_base_addr_htolpa(sh_addr_t *base_addr, dmaaddr_t pa);
-
-/* APIs for managing a DMA-able buffer */
-static int  dhd_dma_buf_audit(dhd_pub_t *dhd, dhd_dma_buf_t *dma_buf);
-static int  dhd_dma_buf_alloc(dhd_pub_t *dhd, dhd_dma_buf_t *dma_buf, uint32 buf_len);
-static void dhd_dma_buf_reset(dhd_pub_t *dhd, dhd_dma_buf_t *dma_buf);
-static void dhd_dma_buf_free(dhd_pub_t *dhd, dhd_dma_buf_t *dma_buf);
-
-/* msgbuf ring management */
-static int dhd_prot_ring_attach(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-	const char *name, uint16 max_items, uint16 len_item, uint16 ringid);
-static void dhd_prot_ring_init(dhd_pub_t *dhd, msgbuf_ring_t *ring);
-static void dhd_prot_ring_reset(dhd_pub_t *dhd, msgbuf_ring_t *ring);
-static void dhd_prot_ring_detach(dhd_pub_t *dhd, msgbuf_ring_t *ring);
-
-/* Pool of pre-allocated msgbuf_ring_t with DMA-able buffers for Flowrings */
-static int  dhd_prot_flowrings_pool_attach(dhd_pub_t *dhd);
-static void dhd_prot_flowrings_pool_reset(dhd_pub_t *dhd);
-static void dhd_prot_flowrings_pool_detach(dhd_pub_t *dhd);
-
-/* Fetch and Release a flowring msgbuf_ring from flowring  pool */
-static msgbuf_ring_t *dhd_prot_flowrings_pool_fetch(dhd_pub_t *dhd,
-	uint16 flowid);
-/* see also dhd_prot_flowrings_pool_release() in dhd_prot.h */
-
-/* Producer: Allocate space in a msgbuf ring */
-static void* dhd_prot_alloc_ring_space(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-	uint16 nitems, uint16 *alloced, bool exactly_nitems);
-static void* dhd_prot_get_ring_space(msgbuf_ring_t *ring, uint16 nitems,
-	uint16 *alloced, bool exactly_nitems);
-
-/* Consumer: Determine the location where the next message may be consumed */
-static uint8* dhd_prot_get_read_addr(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-	uint32 *available_len);
-
-/* Producer (WR index update) or Consumer (RD index update) indication */
-static void dhd_prot_ring_write_complete(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-	void *p, uint16 len);
-static void dhd_prot_upd_read_idx(dhd_pub_t *dhd, msgbuf_ring_t *ring);
-
-/* Allocate DMA-able memory for saving H2D/D2H WR/RD indices */
-static INLINE int dhd_prot_dma_indx_alloc(dhd_pub_t *dhd, uint8 type,
-	dhd_dma_buf_t *dma_buf, uint32 bufsz);
-
-/* Set/Get a RD or WR index in the array of indices */
-/* See also: dhd_prot_dma_indx_init() */
-static void dhd_prot_dma_indx_set(dhd_pub_t *dhd, uint16 new_index, uint8 type,
-	uint16 ringid);
-static uint16 dhd_prot_dma_indx_get(dhd_pub_t *dhd, uint8 type, uint16 ringid);
-
-/* Locate a packet given a pktid */
-static INLINE void *dhd_prot_packet_get(dhd_pub_t *dhd, uint32 pktid, uint8 pkttype,
-	bool free_pktid);
-/* Locate a packet given a PktId and free it. */
-static INLINE void dhd_prot_packet_free(dhd_pub_t *dhd, void *pkt, uint8 pkttype, bool send);
-
-static int dhd_msgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd,
-	void *buf, uint len, uint8 action);
-static int dhd_msgbuf_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd,
-	void *buf, uint len, uint8 action);
-static int dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf);
-static int dhd_fillup_ioct_reqst(dhd_pub_t *dhd, uint16 len, uint cmd,
-	void *buf, int ifidx);
-
-/* Post buffers for Rx, control ioctl response and events */
-static uint16 dhd_msgbuf_rxbuf_post_ctrlpath(dhd_pub_t *dhd, bool event_buf, uint32 max_to_post);
-static void dhd_msgbuf_rxbuf_post_ioctlresp_bufs(dhd_pub_t *pub);
-static void dhd_msgbuf_rxbuf_post_event_bufs(dhd_pub_t *pub);
-static void dhd_msgbuf_rxbuf_post(dhd_pub_t *dhd, bool use_rsv_pktid);
-static int dhd_prot_rxbuf_post(dhd_pub_t *dhd, uint16 count, bool use_rsv_pktid);
-
-static void dhd_prot_return_rxbuf(dhd_pub_t *dhd, uint32 pktid, uint32 rxcnt);
-
-/* D2H Message handling */
-static int dhd_prot_process_msgtype(dhd_pub_t *dhd, msgbuf_ring_t *ring, uint8 *buf, uint32 len);
-
-/* D2H Message handlers */
-static void dhd_prot_noop(dhd_pub_t *dhd, void *msg);
-static void dhd_prot_txstatus_process(dhd_pub_t *dhd, void *msg);
-static void dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg);
-static void dhd_prot_ioctack_process(dhd_pub_t *dhd, void *msg);
-static void dhd_prot_ringstatus_process(dhd_pub_t *dhd, void *msg);
-static void dhd_prot_genstatus_process(dhd_pub_t *dhd, void *msg);
-static void dhd_prot_rxcmplt_process(dhd_pub_t *dhd, void *msg);
-static void dhd_prot_event_process(dhd_pub_t *dhd, void *msg);
-
-/* Loopback test with dongle */
-static void dmaxfer_free_dmaaddr(dhd_pub_t *dhd, dhd_dmaxfer_t *dma);
-static int dmaxfer_prepare_dmaaddr(dhd_pub_t *dhd, uint len, uint srcdelay,
-	uint destdelay, dhd_dmaxfer_t *dma);
-static void dhd_msgbuf_dmaxfer_process(dhd_pub_t *dhd, void *msg);
-
-/* Flowring management communication with dongle */
-static void dhd_prot_flow_ring_create_response_process(dhd_pub_t *dhd, void *msg);
-static void dhd_prot_flow_ring_delete_response_process(dhd_pub_t *dhd, void *msg);
-static void dhd_prot_flow_ring_flush_response_process(dhd_pub_t *dhd, void *msg);
-
-/* Configure a soft doorbell per D2H ring */
-static void dhd_msgbuf_ring_config_d2h_soft_doorbell(dhd_pub_t *dhd);
-static void dhd_prot_d2h_ring_config_cmplt_process(dhd_pub_t *dhd, void *msg);
-
-typedef void (*dhd_msgbuf_func_t)(dhd_pub_t *dhd, void *msg);
-
-/** callback functions for messages generated by the dongle */
-#define MSG_TYPE_INVALID 0
-
-static dhd_msgbuf_func_t table_lookup[DHD_PROT_FUNCS] = {
-	dhd_prot_noop, /* 0 is MSG_TYPE_INVALID */
-	dhd_prot_genstatus_process, /* MSG_TYPE_GEN_STATUS */
-	dhd_prot_ringstatus_process, /* MSG_TYPE_RING_STATUS */
-	NULL,
-	dhd_prot_flow_ring_create_response_process, /* MSG_TYPE_FLOW_RING_CREATE_CMPLT */
-	NULL,
-	dhd_prot_flow_ring_delete_response_process, /* MSG_TYPE_FLOW_RING_DELETE_CMPLT */
-	NULL,
-	dhd_prot_flow_ring_flush_response_process, /* MSG_TYPE_FLOW_RING_FLUSH_CMPLT */
-	NULL,
-	dhd_prot_ioctack_process, /* MSG_TYPE_IOCTLPTR_REQ_ACK */
-	NULL,
-	dhd_prot_ioctcmplt_process, /* MSG_TYPE_IOCTL_CMPLT */
-	NULL,
-	dhd_prot_event_process, /* MSG_TYPE_WL_EVENT */
-	NULL,
-	dhd_prot_txstatus_process, /* MSG_TYPE_TX_STATUS */
-	NULL,
-	dhd_prot_rxcmplt_process, /* MSG_TYPE_RX_CMPLT */
-	NULL,
-	dhd_msgbuf_dmaxfer_process, /* MSG_TYPE_LPBK_DMAXFER_CMPLT */
-	NULL, /* MSG_TYPE_FLOW_RING_RESUME */
-	NULL, /* MSG_TYPE_FLOW_RING_RESUME_CMPLT */
-	NULL, /* MSG_TYPE_FLOW_RING_SUSPEND */
-	NULL, /* MSG_TYPE_FLOW_RING_SUSPEND_CMPLT */
-	NULL, /* MSG_TYPE_INFO_BUF_POST */
-	NULL, /* MSG_TYPE_INFO_BUF_CMPLT */
-	NULL, /* MSG_TYPE_H2D_RING_CREATE */
-	NULL, /* MSG_TYPE_D2H_RING_CREATE */
-	NULL, /* MSG_TYPE_H2D_RING_CREATE_CMPLT */
-	NULL, /* MSG_TYPE_D2H_RING_CREATE_CMPLT */
-	NULL, /* MSG_TYPE_H2D_RING_CONFIG */
-	NULL, /* MSG_TYPE_D2H_RING_CONFIG */
-	NULL, /* MSG_TYPE_H2D_RING_CONFIG_CMPLT */
-	dhd_prot_d2h_ring_config_cmplt_process, /* MSG_TYPE_D2H_RING_CONFIG_CMPLT */
-	NULL, /* MSG_TYPE_H2D_MAILBOX_DATA */
-	NULL, /* MSG_TYPE_D2H_MAILBOX_DATA */
-};
-
-
-#ifdef DHD_RX_CHAINING
-
-#define PKT_CTF_CHAINABLE(dhd, ifidx, evh, prio, h_sa, h_da, h_prio) \
-	(!ETHER_ISNULLDEST(((struct ether_header *)(evh))->ether_dhost) && \
-	 !ETHER_ISMULTI(((struct ether_header *)(evh))->ether_dhost) && \
-	 !eacmp((h_da), ((struct ether_header *)(evh))->ether_dhost) && \
-	 !eacmp((h_sa), ((struct ether_header *)(evh))->ether_shost) && \
-	 ((h_prio) == (prio)) && (dhd_ctf_hotbrc_check((dhd), (evh), (ifidx))) && \
-	 ((((struct ether_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IP)) || \
-	 (((struct ether_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IPV6))) && \
-	 dhd_l2_filter_chainable((dhd), (evh), (ifidx)))
-
-static INLINE void BCMFASTPATH dhd_rxchain_reset(rxchain_info_t *rxchain);
-static void BCMFASTPATH dhd_rxchain_frame(dhd_pub_t *dhd, void *pkt, uint ifidx);
-static void BCMFASTPATH dhd_rxchain_commit(dhd_pub_t *dhd);
-
-#define DHD_PKT_CTF_MAX_CHAIN_LEN	64
-
-#endif /* DHD_RX_CHAINING */
-
-static void dhd_prot_h2d_sync_init(dhd_pub_t *dhd);
-
-#if defined(PCIE_D2H_SYNC) /* avoids problems related to host CPU cache */
-
-/**
- * D2H DMA to completion callback handlers. Based on the mode advertised by the
- * dongle through the PCIE shared region, the appropriate callback will be
- * registered in the proto layer to be invoked prior to precessing any message
- * from a D2H DMA ring. If the dongle uses a read barrier or another mode that
- * does not require host participation, then a noop callback handler will be
- * bound that simply returns the msg_type.
- */
-static void dhd_prot_d2h_sync_livelock(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-                                       uint32 tries, uchar *msg, int msglen);
-static uint8 dhd_prot_d2h_sync_seqnum(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-                                      volatile cmn_msg_hdr_t *msg, int msglen);
-static uint8 dhd_prot_d2h_sync_xorcsum(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-                                       volatile cmn_msg_hdr_t *msg, int msglen);
-static uint8 dhd_prot_d2h_sync_none(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-                                    volatile cmn_msg_hdr_t *msg, int msglen);
-static void dhd_prot_d2h_sync_init(dhd_pub_t *dhd);
-
-void dhd_prot_collect_memdump(dhd_pub_t *dhd)
-{
-	DHD_ERROR(("%s(): Collecting mem dump now \r\n", __FUNCTION__));
-#ifdef DHD_FW_COREDUMP
-	if (dhd->memdump_enabled) {
-		/* collect core dump */
-		dhd->memdump_type = DUMP_TYPE_BY_LIVELOCK;
-		dhd_bus_mem_dump(dhd);
-	}
-#endif /* DHD_FW_COREDUMP */
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#ifdef CONFIG_ARCH_MSM
-	dhd->bus->no_cfg_restore = 1;
-#endif /* CONFIG_ARCH_MSM */
-	dhd->hang_reason = HANG_REASON_MSGBUF_LIVELOCK;
-	dhd_os_send_hang_message(dhd);
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-}
-
-/**
- * dhd_prot_d2h_sync_livelock - when the host determines that a DMA transfer has
- * not completed, a livelock condition occurs. Host will avert this livelock by
- * dropping this message and moving to the next. This dropped message can lead
- * to a packet leak, or even something disastrous in the case the dropped
- * message happens to be a control response.
- * Here we will log this condition. One may choose to reboot the dongle.
- *
- */
-static void
-dhd_prot_d2h_sync_livelock(dhd_pub_t *dhd, msgbuf_ring_t *ring, uint32 tries,
-                           uchar *msg, int msglen)
-{
-	uint32 seqnum = ring->seqnum;
-
-	DHD_ERROR(("LIVELOCK DHD<%p> name<%s> seqnum<%u:%u> tries<%u> max<%lu> tot<%lu>"
-		"dma_buf va<%p> msg<%p> curr_rd<%d>\n",
-		dhd, ring->name, seqnum, seqnum% D2H_EPOCH_MODULO, tries,
-		dhd->prot->d2h_sync_wait_max, dhd->prot->d2h_sync_wait_tot,
-		ring->dma_buf.va, msg, ring->curr_rd));
-	prhex("D2H MsgBuf Failure", (uchar *)msg, msglen);
-	dhd_dump_to_kernelog(dhd);
-
-#ifdef DHD_FW_COREDUMP
-	if (dhd->memdump_enabled) {
-		/* collect core dump */
-		dhd->memdump_type = DUMP_TYPE_BY_LIVELOCK;
-		dhd_bus_mem_dump(dhd);
-	}
-#endif /* DHD_FW_COREDUMP */
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#ifdef CONFIG_ARCH_MSM
-	dhd->bus->no_cfg_restore = 1;
-#endif /* CONFIG_ARCH_MSM */
-	dhd->hang_reason = HANG_REASON_MSGBUF_LIVELOCK;
-	dhd_os_send_hang_message(dhd);
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-}
-
-/**
- * dhd_prot_d2h_sync_seqnum - Sync on a D2H DMA completion using the SEQNUM
- * mode. Sequence number is always in the last word of a message.
- */
-static uint8 BCMFASTPATH
-dhd_prot_d2h_sync_seqnum(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-                         volatile cmn_msg_hdr_t *msg, int msglen)
-{
-	uint32 tries;
-	uint32 ring_seqnum = ring->seqnum % D2H_EPOCH_MODULO;
-	int num_words = msglen / sizeof(uint32); /* num of 32bit words */
-	volatile uint32 *marker = (uint32 *)msg + (num_words - 1); /* last word */
-	dhd_prot_t *prot = dhd->prot;
-	uint32 step = 0;
-	uint32 delay = PCIE_D2H_SYNC_DELAY;
-	uint32 total_tries = 0;
-
-	ASSERT(msglen == ring->item_len);
-
-	BCM_REFERENCE(delay);
-	/*
-	 * For retries we have to make some sort of stepper algorithm.
-	 * We see that every time when the Dongle comes out of the D3
-	 * Cold state, the first D2H mem2mem DMA takes more time to
-	 * complete, leading to livelock issues.
-	 *
-	 * Case 1 - Apart from Host CPU some other bus master is
-	 * accessing the DDR port, probably page close to the ring
-	 * so, PCIE does not get a change to update the memory.
-	 * Solution - Increase the number of tries.
-	 *
-	 * Case 2 - The 50usec delay given by the Host CPU is not
-	 * sufficient for the PCIe RC to start its work.
-	 * In this case the breathing time of 50usec given by
-	 * the Host CPU is not sufficient.
-	 * Solution: Increase the delay in a stepper fashion.
-	 * This is done to ensure that there are no
-	 * unwanted extra delay introdcued in normal conditions.
-	 */
-	for (step = 1; step <= PCIE_D2H_SYNC_NUM_OF_STEPS; step++) {
-		for (tries = 1; tries <= PCIE_D2H_SYNC_WAIT_TRIES; tries++) {
-			uint32 msg_seqnum = *marker;
-			if (ltoh32(msg_seqnum) == ring_seqnum) { /* dma upto last word done */
-				ring->seqnum++; /* next expected sequence number */
-				goto dma_completed;
-			}
-
-			total_tries = ((step-1) * PCIE_D2H_SYNC_WAIT_TRIES) + tries;
-
-			if (total_tries > prot->d2h_sync_wait_max)
-				prot->d2h_sync_wait_max = total_tries;
-
-			OSL_CACHE_INV(msg, msglen); /* invalidate and try again */
-			OSL_CPU_RELAX(); /* CPU relax for msg_seqnum  value to update */
-#if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_SOC_EXYNOS8890)
-			/* For ARM there is no pause in cpu_relax, so add extra delay */
-			OSL_DELAY(delay * step);
-#endif /* defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_SOC_EXYNOS8890) */
-		} /* for PCIE_D2H_SYNC_WAIT_TRIES */
-	} /* for number of steps */
-
-	dhd_prot_d2h_sync_livelock(dhd, ring, total_tries, (uchar *)msg, msglen);
-
-	ring->seqnum++; /* skip this message ... leak of a pktid */
-	return MSG_TYPE_INVALID; /* invalid msg_type 0 -> noop callback */
-
-dma_completed:
-
-	prot->d2h_sync_wait_tot += total_tries;
-	return msg->msg_type;
-}
-
-/**
- * dhd_prot_d2h_sync_xorcsum - Sync on a D2H DMA completion using the XORCSUM
- * mode. The xorcsum is placed in the last word of a message. Dongle will also
- * place a seqnum in the epoch field of the cmn_msg_hdr.
- */
-static uint8 BCMFASTPATH
-dhd_prot_d2h_sync_xorcsum(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-                          volatile cmn_msg_hdr_t *msg, int msglen)
-{
-	uint32 tries;
-	uint32 prot_checksum = 0; /* computed checksum */
-	int num_words = msglen / sizeof(uint32); /* num of 32bit words */
-	uint8 ring_seqnum = ring->seqnum % D2H_EPOCH_MODULO;
-	dhd_prot_t *prot = dhd->prot;
-	uint32 step = 0;
-	uint32 delay = PCIE_D2H_SYNC_DELAY;
-	uint32 total_tries = 0;
-
-	ASSERT(msglen == ring->item_len);
-
-	BCM_REFERENCE(delay);
-
-	/*
-	 * For retries we have to make some sort of stepper algorithm.
-	 * We see that every time when the Dongle comes out of the D3
-	 * Cold state, the first D2H mem2mem DMA takes more time to
-	 * complete, leading to livelock issues.
-	 *
-	 * Case 1 - Apart from Host CPU some other bus master is
-	 * accessing the DDR port, probably page close to the ring
-	 * so, PCIE does not get a change to update the memory.
-	 * Solution - Increase the number of tries.
-	 *
-	 * Case 2 - The 50usec delay given by the Host CPU is not
-	 * sufficient for the PCIe RC to start its work.
-	 * In this case the breathing time of 50usec given by
-	 * the Host CPU is not sufficient.
-	 * Solution: Increase the delay in a stepper fashion.
-	 * This is done to ensure that there are no
-	 * unwanted extra delay introdcued in normal conditions.
-	 */
-	for (step = 1; step <= PCIE_D2H_SYNC_NUM_OF_STEPS; step++) {
-		for (tries = 1; tries <= PCIE_D2H_SYNC_WAIT_TRIES; tries++) {
-			prot_checksum = bcm_compute_xor32((volatile uint32 *)msg, num_words);
-			if (prot_checksum == 0U) { /* checksum is OK */
-				if (msg->epoch == ring_seqnum) {
-					ring->seqnum++; /* next expected sequence number */
-					goto dma_completed;
-				}
-			}
-
-			total_tries = ((step-1) * PCIE_D2H_SYNC_WAIT_TRIES) + tries;
-
-			if (total_tries > prot->d2h_sync_wait_max)
-				prot->d2h_sync_wait_max = total_tries;
-
-			OSL_CACHE_INV(msg, msglen); /* invalidate and try again */
-			OSL_CPU_RELAX(); /* CPU relax for msg_seqnum  value to update */
-#if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_SOC_EXYNOS8890)
-			/* For ARM there is no pause in cpu_relax, so add extra delay */
-			OSL_DELAY(delay * step);
-#endif /* defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_SOC_EXYNOS8890) */
-
-		} /* for PCIE_D2H_SYNC_WAIT_TRIES */
-	} /* for number of steps */
-
-	dhd_prot_d2h_sync_livelock(dhd, ring, total_tries, (uchar *)msg, msglen);
-
-	ring->seqnum++; /* skip this message ... leak of a pktid */
-	return MSG_TYPE_INVALID; /* invalid msg_type 0 -> noop callback */
-
-dma_completed:
-
-	prot->d2h_sync_wait_tot += total_tries;
-	return msg->msg_type;
-}
-
-/**
- * dhd_prot_d2h_sync_none - Dongle ensure that the DMA will complete and host
- * need to try to sync. This noop sync handler will be bound when the dongle
- * advertises that neither the SEQNUM nor XORCSUM mode of DMA sync is required.
- */
-static uint8 BCMFASTPATH
-dhd_prot_d2h_sync_none(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-                       volatile cmn_msg_hdr_t *msg, int msglen)
-{
-	return msg->msg_type;
-}
-
-/**
- * dhd_prot_d2h_sync_init - Setup the host side DMA sync mode based on what
- * dongle advertizes.
- */
-static void
-dhd_prot_d2h_sync_init(dhd_pub_t *dhd)
-{
-	dhd_prot_t *prot = dhd->prot;
-	prot->d2h_sync_wait_max = 0UL;
-	prot->d2h_sync_wait_tot = 0UL;
-
-	prot->d2hring_ctrl_cpln.seqnum = D2H_EPOCH_INIT_VAL;
-	prot->d2hring_tx_cpln.seqnum = D2H_EPOCH_INIT_VAL;
-	prot->d2hring_rx_cpln.seqnum = D2H_EPOCH_INIT_VAL;
-
-	if (dhd->d2h_sync_mode & PCIE_SHARED_D2H_SYNC_SEQNUM) {
-		prot->d2h_sync_cb = dhd_prot_d2h_sync_seqnum;
-	} else if (dhd->d2h_sync_mode & PCIE_SHARED_D2H_SYNC_XORCSUM) {
-		prot->d2h_sync_cb = dhd_prot_d2h_sync_xorcsum;
-	} else {
-		prot->d2h_sync_cb = dhd_prot_d2h_sync_none;
-	}
-}
-
-#endif /* PCIE_D2H_SYNC */
-
-int INLINE
-dhd_wakeup_ioctl_event(dhd_pub_t *dhd, dhd_ioctl_recieved_status_t reason)
-{
-	/* To synchronize with the previous memory operations call wmb() */
-	OSL_SMP_WMB();
-	dhd->prot->ioctl_received = reason;
-	/* Call another wmb() to make sure before waking up the other event value gets updated */
-	OSL_SMP_WMB();
-	dhd_os_ioctl_resp_wake(dhd);
-	return 0;
-}
-
-/**
- * dhd_prot_h2d_sync_init - Per H2D common ring, setup the msgbuf ring seqnum
- */
-static void
-dhd_prot_h2d_sync_init(dhd_pub_t *dhd)
-{
-	dhd_prot_t *prot = dhd->prot;
-	prot->h2dring_rxp_subn.seqnum = H2D_EPOCH_INIT_VAL;
-	prot->h2dring_ctrl_subn.seqnum = H2D_EPOCH_INIT_VAL;
-}
-
-/* +-----------------  End of PCIE DHD H2D DMA SYNC ------------------------+ */
-
-
-/*
- * +---------------------------------------------------------------------------+
- * PCIE DMA-able buffer. Sets up a dhd_dma_buf_t object, which includes the
- * virtual and physical address, the buffer lenght and the DMA handler.
- * A secdma handler is also included in the dhd_dma_buf object.
- * +---------------------------------------------------------------------------+
- */
-
-static INLINE void
-dhd_base_addr_htolpa(sh_addr_t *base_addr, dmaaddr_t pa)
-{
-	base_addr->low_addr = htol32(PHYSADDRLO(pa));
-	base_addr->high_addr = htol32(PHYSADDRHI(pa));
-}
-
-
-/**
- * dhd_dma_buf_audit - Any audits on a DHD DMA Buffer.
- */
-static int
-dhd_dma_buf_audit(dhd_pub_t *dhd, dhd_dma_buf_t *dma_buf)
-{
-	uint32 base, end; /* dongle uses 32bit ptr arithmetic */
-
-	ASSERT(dma_buf);
-	base = PHYSADDRLO(dma_buf->pa);
-	ASSERT(base);
-	ASSERT(ISALIGNED(base, DMA_ALIGN_LEN));
-	ASSERT(dma_buf->len != 0);
-
-	/* test 32bit offset arithmetic over dma buffer for loss of carry-over */
-	end = (base + dma_buf->len); /* end address */
-
-	if ((end & 0xFFFFFFFF) < (base & 0xFFFFFFFF)) { /* exclude carryover */
-		DHD_ERROR(("%s: dma_buf %x len %d spans dongle 32bit ptr arithmetic\n",
-			__FUNCTION__, base, dma_buf->len));
-		return BCME_ERROR;
-	}
-
-	return BCME_OK;
-}
-
-/**
- * dhd_dma_buf_alloc - Allocate a cache coherent DMA-able buffer.
- * returns BCME_OK=0 on success
- * returns non-zero negative error value on failure.
- */
-static int
-dhd_dma_buf_alloc(dhd_pub_t *dhd, dhd_dma_buf_t *dma_buf, uint32 buf_len)
-{
-	uint32 dma_pad = 0;
-	osl_t *osh = dhd->osh;
-
-	ASSERT(dma_buf != NULL);
-	ASSERT(dma_buf->va == NULL);
-	ASSERT(dma_buf->len == 0);
-
-	/* Pad the buffer length by one extra cacheline size.
-	 * Required for D2H direction.
-	 */
-	dma_pad = (buf_len % DHD_DMA_PAD) ? DHD_DMA_PAD : 0;
-	dma_buf->va = DMA_ALLOC_CONSISTENT(osh, buf_len + dma_pad,
-		DMA_ALIGN_LEN, &dma_buf->_alloced, &dma_buf->pa, &dma_buf->dmah);
-
-	if (dma_buf->va == NULL) {
-		DHD_ERROR(("%s: buf_len %d, no memory available\n",
-			__FUNCTION__, buf_len));
-		return BCME_NOMEM;
-	}
-
-	dma_buf->len = buf_len; /* not including padded len */
-
-	if (dhd_dma_buf_audit(dhd, dma_buf) != BCME_OK) { /* audit dma buf */
-		dhd_dma_buf_free(dhd, dma_buf);
-		return BCME_ERROR;
-	}
-
-	dhd_dma_buf_reset(dhd, dma_buf); /* zero out and cache flush */
-
-	return BCME_OK;
-}
-
-/**
- * dhd_dma_buf_reset - Reset a cache coherent DMA-able buffer.
- */
-static void
-dhd_dma_buf_reset(dhd_pub_t *dhd, dhd_dma_buf_t *dma_buf)
-{
-	if ((dma_buf == NULL) || (dma_buf->va == NULL)) {
-		return;
-	}
-
-	(void)dhd_dma_buf_audit(dhd, dma_buf);
-
-	/* Zero out the entire buffer and cache flush */
-	memset((void*)dma_buf->va, 0, dma_buf->len);
-	OSL_CACHE_FLUSH((void *)dma_buf->va, dma_buf->len);
-}
-
-/**
- * dhd_dma_buf_free - Free a DMA-able buffer that was previously allocated using
- * dhd_dma_buf_alloc().
- */
-static void
-dhd_dma_buf_free(dhd_pub_t *dhd, dhd_dma_buf_t *dma_buf)
-{
-	osl_t *osh = dhd->osh;
-
-	ASSERT(dma_buf);
-
-	if (dma_buf->va == NULL) {
-		return; /* Allow for free invocation, when alloc failed */
-	}
-
-	/* DEBUG: dhd_dma_buf_reset(dhd, dma_buf) */
-	(void)dhd_dma_buf_audit(dhd, dma_buf);
-
-	/* dma buffer may have been padded at allocation */
-	DMA_FREE_CONSISTENT(osh, dma_buf->va, dma_buf->_alloced,
-		dma_buf->pa, dma_buf->dmah);
-
-	memset(dma_buf, 0, sizeof(dhd_dma_buf_t));
-}
-
-/**
- * dhd_dma_buf_init - Initialize a dhd_dma_buf with speicifed values.
- * Do not use dhd_dma_buf_init to zero out a dhd_dma_buf_t object. Use memset 0.
- */
-void
-dhd_dma_buf_init(dhd_pub_t *dhd, void *dhd_dma_buf,
-	void *va, uint32 len, dmaaddr_t pa, void *dmah, void *secdma)
-{
-	dhd_dma_buf_t *dma_buf;
-	ASSERT(dhd_dma_buf);
-	dma_buf = (dhd_dma_buf_t *)dhd_dma_buf;
-	dma_buf->va = va;
-	dma_buf->len = len;
-	dma_buf->pa = pa;
-	dma_buf->dmah = dmah;
-	dma_buf->secdma = secdma;
-
-	/* Audit user defined configuration */
-	(void)dhd_dma_buf_audit(dhd, dma_buf);
-}
-
-/* +------------------  End of PCIE DHD DMA BUF ADT ------------------------+ */
-
-/*
- * +---------------------------------------------------------------------------+
- * PktId Map: Provides a native packet pointer to unique 32bit PktId mapping.
- * Main purpose is to save memory on the dongle, has other purposes as well.
- * The packet id map, also includes storage for some packet parameters that
- * may be saved. A native packet pointer along with the parameters may be saved
- * and a unique 32bit pkt id will be returned. Later, the saved packet pointer
- * and the metadata may be retrieved using the previously allocated packet id.
- * +---------------------------------------------------------------------------+
- */
-#define DHD_PCIE_PKTID
-#define MAX_PKTID_ITEMS     (3072) /* Maximum number of pktids supported */
-
-/* On Router, the pktptr serves as a pktid. */
-
-
-#if defined(PROP_TXSTATUS) && !defined(DHD_PCIE_PKTID)
-#error "PKTIDMAP must be supported with PROP_TXSTATUS/WLFC"
-#endif
-
-/* Enum for marking the buffer color based on usage */
-typedef enum dhd_pkttype {
-	PKTTYPE_DATA_TX = 0,
-	PKTTYPE_DATA_RX,
-	PKTTYPE_IOCTL_RX,
-	PKTTYPE_EVENT_RX,
-	/* dhd_prot_pkt_free no check, if pktid reserved and no space avail case */
-	PKTTYPE_NO_CHECK
-} dhd_pkttype_t;
-
-#define DHD_PKTID_INVALID               (0U)
-#define DHD_IOCTL_REQ_PKTID             (0xFFFE)
-#define DHD_FAKE_PKTID                  (0xFACE)
-
-#define DHD_PKTID_FREE_LOCKER           (FALSE)
-#define DHD_PKTID_RSV_LOCKER            (TRUE)
-
-typedef void * dhd_pktid_map_handle_t; /* opaque handle to a pktid map */
-
-/* Construct a packet id mapping table, returning an opaque map handle */
-static dhd_pktid_map_handle_t *dhd_pktid_map_init(dhd_pub_t *dhd, uint32 num_items, uint32 index);
-
-/* Destroy a packet id mapping table, freeing all packets active in the table */
-static void dhd_pktid_map_fini(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map);
-
-#define PKTID_MAP_HANDLE	(0)
-#define PKTID_MAP_HANDLE_IOCTL	(1)
-
-#define DHD_NATIVE_TO_PKTID_INIT(dhd, items, index) dhd_pktid_map_init((dhd), (items), (index))
-#define DHD_NATIVE_TO_PKTID_FINI(dhd, map)   dhd_pktid_map_fini((dhd), (map))
-
-#if defined(DHD_PCIE_PKTID)
-
-
-/* Determine number of pktids that are available */
-static INLINE uint32 dhd_pktid_map_avail_cnt(dhd_pktid_map_handle_t *handle);
-
-/* Allocate a unique pktid against which a pkt and some metadata is saved */
-static INLINE uint32 dhd_pktid_map_reserve(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle,
-	void *pkt);
-static INLINE void dhd_pktid_map_save(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle,
-	void *pkt, uint32 nkey, dmaaddr_t pa, uint32 len, uint8 dma,
-	void *dmah, void *secdma, dhd_pkttype_t pkttype);
-static uint32 dhd_pktid_map_alloc(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map,
-	void *pkt, dmaaddr_t pa, uint32 len, uint8 dma,
-	void *dmah, void *secdma, dhd_pkttype_t pkttype);
-
-/* Return an allocated pktid, retrieving previously saved pkt and metadata */
-static void *dhd_pktid_map_free(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map,
-	uint32 id, dmaaddr_t *pa, uint32 *len, void **dmah,
-	void **secdma, dhd_pkttype_t pkttype, bool rsv_locker);
-
-/*
- * DHD_PKTID_AUDIT_ENABLED: Audit of PktIds in DHD for duplicate alloc and frees
- *
- * DHD_PKTID_AUDIT_MAP: Audit the LIFO or FIFO PktIdMap allocator
- * DHD_PKTID_AUDIT_RING: Audit the pktid during producer/consumer ring operation
- *
- * CAUTION: When DHD_PKTID_AUDIT_ENABLED is defined,
- *    either DHD_PKTID_AUDIT_MAP or DHD_PKTID_AUDIT_RING may be selected.
- */
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-#define USE_DHD_PKTID_AUDIT_LOCK 1
-/* Audit the pktidmap allocator */
-/* #define DHD_PKTID_AUDIT_MAP */
-
-/* Audit the pktid during production/consumption of workitems */
-#define DHD_PKTID_AUDIT_RING
-
-#if defined(DHD_PKTID_AUDIT_MAP) && defined(DHD_PKTID_AUDIT_RING)
-#error "May only enabled audit of MAP or RING, at a time."
-#endif /* DHD_PKTID_AUDIT_MAP && DHD_PKTID_AUDIT_RING */
-
-#define DHD_DUPLICATE_ALLOC     1
-#define DHD_DUPLICATE_FREE      2
-#define DHD_TEST_IS_ALLOC       3
-#define DHD_TEST_IS_FREE        4
-
-#ifdef USE_DHD_PKTID_AUDIT_LOCK
-#define DHD_PKTID_AUDIT_LOCK_INIT(osh)          dhd_os_spin_lock_init(osh)
-#define DHD_PKTID_AUDIT_LOCK_DEINIT(osh, lock)  dhd_os_spin_lock_deinit(osh, lock)
-#define DHD_PKTID_AUDIT_LOCK(lock)              dhd_os_spin_lock(lock)
-#define DHD_PKTID_AUDIT_UNLOCK(lock, flags)     dhd_os_spin_unlock(lock, flags)
-#else
-#define DHD_PKTID_AUDIT_LOCK_INIT(osh)          (void *)(1)
-#define DHD_PKTID_AUDIT_LOCK_DEINIT(osh, lock)  do { /* noop */ } while (0)
-#define DHD_PKTID_AUDIT_LOCK(lock)              0
-#define DHD_PKTID_AUDIT_UNLOCK(lock, flags)     do { /* noop */ } while (0)
-#endif /* !USE_DHD_PKTID_AUDIT_LOCK */
-
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-/* #define USE_DHD_PKTID_LOCK   1 */
-
-#ifdef USE_DHD_PKTID_LOCK
-#define DHD_PKTID_LOCK_INIT(osh)                dhd_os_spin_lock_init(osh)
-#define DHD_PKTID_LOCK_DEINIT(osh, lock)        dhd_os_spin_lock_deinit(osh, lock)
-#define DHD_PKTID_LOCK(lock)                    dhd_os_spin_lock(lock)
-#define DHD_PKTID_UNLOCK(lock, flags)           dhd_os_spin_unlock(lock, flags)
-#else
-#define DHD_PKTID_LOCK_INIT(osh)                (void *)(1)
-#define DHD_PKTID_LOCK_DEINIT(osh, lock)	\
-	do { \
-		BCM_REFERENCE(osh); \
-		BCM_REFERENCE(lock); \
-	} while (0)
-#define DHD_PKTID_LOCK(lock)                    0
-#define DHD_PKTID_UNLOCK(lock, flags)           \
-	do { \
-		BCM_REFERENCE(lock); \
-		BCM_REFERENCE(flags); \
-	} while (0)
-#endif /* !USE_DHD_PKTID_LOCK */
-
-/* Packet metadata saved in packet id mapper */
-
-/* The Locker can be 3 states
- * LOCKER_IS_FREE - Locker is free and can be allocated
- * LOCKER_IS_BUSY - Locker is assigned and is being used, values in the
- *                  locker (buffer address, len, phy addr etc) are populated
- *		    with valid values
- * LOCKER_IS_RSVD - The locker is reserved for future use, but the values
- *                  in the locker are not valid. Especially pkt should be
- *                  NULL in this state. When the user wants to re-use the
- *                  locker dhd_pktid_map_free can be called with a flag
- *                  to reserve the pktid for future use, which will clear
- *                  the contents of the locker. When the user calls
- *                  dhd_pktid_map_save the locker would move to LOCKER_IS_BUSY
- */
-typedef enum dhd_locker_state {
-	LOCKER_IS_FREE,
-	LOCKER_IS_BUSY,
-	LOCKER_IS_RSVD
-} dhd_locker_state_t;
-
-typedef struct dhd_pktid_item {
-	dhd_locker_state_t state;  /* tag a locker to be free, busy or reserved */
-	uint8         dir;      /* dma map direction (Tx=flush or Rx=invalidate) */
-	dhd_pkttype_t pkttype;  /* pktlists are maintained based on pkttype */
-	uint16        len;      /* length of mapped packet's buffer */
-	void          *pkt;     /* opaque native pointer to a packet */
-	dmaaddr_t     pa;       /* physical address of mapped packet's buffer */
-	void          *dmah;    /* handle to OS specific DMA map */
-	void          *secdma;
-} dhd_pktid_item_t;
-
-typedef struct dhd_pktid_map {
-	uint32      items;    /* total items in map */
-	uint32      avail;    /* total available items */
-	int         failures; /* lockers unavailable count */
-	/* Spinlock to protect dhd_pktid_map in process/tasklet context */
-	void        *pktid_lock; /* Used when USE_DHD_PKTID_LOCK is defined */
-
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-	void	    *pktid_audit_lock;
-	struct bcm_mwbmap *pktid_audit; /* multi word bitmap based audit */
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-	uint32      keys[MAX_PKTID_ITEMS + 1]; /* stack of unique pkt ids */
-	dhd_pktid_item_t lockers[0];           /* metadata storage */
-} dhd_pktid_map_t;
-
-/*
- * PktId (Locker) #0 is never allocated and is considered invalid.
- *
- * On request for a pktid, a value DHD_PKTID_INVALID must be treated as a
- * depleted pktid pool and must not be used by the caller.
- *
- * Likewise, a caller must never free a pktid of value DHD_PKTID_INVALID.
- */
-
-#define DHD_PKTID_ITEM_SZ               (sizeof(dhd_pktid_item_t))
-#define DHD_PKIDMAP_ITEMS(items)        (items)
-#define DHD_PKTID_MAP_SZ(items)         (sizeof(dhd_pktid_map_t) + \
-					(DHD_PKTID_ITEM_SZ * ((items) + 1)))
-
-#define DHD_NATIVE_TO_PKTID_FINI_IOCTL(dhd, map)  dhd_pktid_map_fini_ioctl((dhd), (map))
-
-/* Convert a packet to a pktid, and save pkt pointer in busy locker */
-#define DHD_NATIVE_TO_PKTID_RSV(dhd, map, pkt)    dhd_pktid_map_reserve((dhd), (map), (pkt))
-
-/* Reuse a previously reserved locker to save packet params */
-#define DHD_NATIVE_TO_PKTID_SAVE(dhd, map, pkt, nkey, pa, len, dir, dmah, secdma, pkttype) \
-	dhd_pktid_map_save((dhd), (map), (void *)(pkt), (nkey), (pa), (uint32)(len), \
-	                   (uint8)(dir), (void *)(dmah), (void *)(secdma), \
-			   (dhd_pkttype_t)(pkttype))
-
-/* Convert a packet to a pktid, and save packet params in locker */
-#define DHD_NATIVE_TO_PKTID(dhd, map, pkt, pa, len, dir, dmah, secdma, pkttype) \
-	dhd_pktid_map_alloc((dhd), (map), (void *)(pkt), (pa), (uint32)(len), \
-	                    (uint8)(dir), (void *)(dmah), (void *)(secdma), \
-			    (dhd_pkttype_t)(pkttype))
-
-/* Convert pktid to a packet, and free the locker */
-#define DHD_PKTID_TO_NATIVE(dhd, map, pktid, pa, len, dmah, secdma, pkttype) \
-	dhd_pktid_map_free((dhd), (map), (uint32)(pktid), \
-	(dmaaddr_t *)&(pa), (uint32 *)&(len), (void **)&(dmah), \
-	(void **) &secdma, (dhd_pkttype_t)(pkttype), DHD_PKTID_FREE_LOCKER)
-
-/* Convert the pktid to a packet, empty locker, but keep it reserved */
-#define DHD_PKTID_TO_NATIVE_RSV(dhd, map, pktid, pa, len, dmah, secdma, pkttype) \
-	dhd_pktid_map_free((dhd), (map), (uint32)(pktid), \
-	(dmaaddr_t *)&(pa), (uint32 *)&(len), (void **)&(dmah), \
-	(void **) &secdma, (dhd_pkttype_t)(pkttype), DHD_PKTID_RSV_LOCKER)
-
-#define DHD_PKTID_AVAIL(map)                 dhd_pktid_map_avail_cnt(map)
-
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-
-static int dhd_pktid_audit(dhd_pub_t *dhd, dhd_pktid_map_t *pktid_map, uint32 pktid,
-	const int test_for, const char *errmsg);
-
-/**
-* dhd_pktid_audit - Use the mwbmap to audit validity of a pktid.
-*/
-static int
-dhd_pktid_audit(dhd_pub_t *dhd, dhd_pktid_map_t *pktid_map, uint32 pktid,
-	const int test_for, const char *errmsg)
-{
-#define DHD_PKT_AUDIT_STR "ERROR: %16s Host PktId Audit: "
-
-	const uint32 max_pktid_items = (MAX_PKTID_ITEMS);
-	struct bcm_mwbmap *handle;
-	uint32	flags;
-	bool ignore_audit;
-
-	if (pktid_map == (dhd_pktid_map_t *)NULL) {
-		DHD_ERROR((DHD_PKT_AUDIT_STR "Pkt id map NULL\n", errmsg));
-		return BCME_OK;
-	}
-
-	flags = DHD_PKTID_AUDIT_LOCK(pktid_map->pktid_audit_lock);
-
-	handle = pktid_map->pktid_audit;
-	if (handle == (struct bcm_mwbmap *)NULL) {
-		DHD_ERROR((DHD_PKT_AUDIT_STR "Handle NULL\n", errmsg));
-		DHD_PKTID_AUDIT_UNLOCK(pktid_map->pktid_audit_lock, flags);
-		return BCME_OK;
-	}
-
-	/* Exclude special pktids from audit */
-	ignore_audit = (pktid == DHD_IOCTL_REQ_PKTID) | (pktid == DHD_FAKE_PKTID);
-	if (ignore_audit) {
-		DHD_PKTID_AUDIT_UNLOCK(pktid_map->pktid_audit_lock, flags);
-		return BCME_OK;
-	}
-
-	if ((pktid == DHD_PKTID_INVALID) || (pktid > max_pktid_items)) {
-		DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> invalid\n", errmsg, pktid));
-		/* lock is released in "error" */
-		goto error;
-	}
-
-	/* Perform audit */
-	switch (test_for) {
-		case DHD_DUPLICATE_ALLOC:
-			if (!bcm_mwbmap_isfree(handle, pktid)) {
-				DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> alloc duplicate\n",
-				           errmsg, pktid));
-				goto error;
-			}
-			bcm_mwbmap_force(handle, pktid);
-			break;
-
-		case DHD_DUPLICATE_FREE:
-			if (bcm_mwbmap_isfree(handle, pktid)) {
-				DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> free duplicate\n",
-				           errmsg, pktid));
-				goto error;
-			}
-			bcm_mwbmap_free(handle, pktid);
-			break;
-
-		case DHD_TEST_IS_ALLOC:
-			if (bcm_mwbmap_isfree(handle, pktid)) {
-				DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> is not allocated\n",
-				           errmsg, pktid));
-				goto error;
-			}
-			break;
-
-		case DHD_TEST_IS_FREE:
-			if (!bcm_mwbmap_isfree(handle, pktid)) {
-				DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> is not free",
-				           errmsg, pktid));
-				goto error;
-			}
-			break;
-
-		default:
-			goto error;
-	}
-
-	DHD_PKTID_AUDIT_UNLOCK(pktid_map->pktid_audit_lock, flags);
-	return BCME_OK;
-
-error:
-
-	DHD_PKTID_AUDIT_UNLOCK(pktid_map->pktid_audit_lock, flags);
-	/* May insert any trap mechanism here ! */
-	dhd_pktid_audit_fail_cb(dhd);
-
-	return BCME_ERROR;
-}
-
-#define DHD_PKTID_AUDIT(dhdp, map, pktid, test_for) \
-	dhd_pktid_audit((dhdp), (dhd_pktid_map_t *)(map), (pktid), (test_for), __FUNCTION__)
-
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-/* +------------------  End of PCIE DHD PKTID AUDIT ------------------------+ */
-
-
-/**
- * +---------------------------------------------------------------------------+
- * Packet to Packet Id mapper using a <numbered_key, locker> paradigm.
- *
- * dhd_pktid_map manages a set of unique Packet Ids range[1..MAX_PKTID_ITEMS].
- *
- * dhd_pktid_map_alloc() may be used to save some packet metadata, and a unique
- * packet id is returned. This unique packet id may be used to retrieve the
- * previously saved packet metadata, using dhd_pktid_map_free(). On invocation
- * of dhd_pktid_map_free(), the unique packet id is essentially freed. A
- * subsequent call to dhd_pktid_map_alloc() may reuse this packet id.
- *
- * Implementation Note:
- * Convert this into a <key,locker> abstraction and place into bcmutils !
- * Locker abstraction should treat contents as opaque storage, and a
- * callback should be registered to handle busy lockers on destructor.
- *
- * +---------------------------------------------------------------------------+
- */
-
-/** Allocate and initialize a mapper of num_items <numbered_key, locker> */
-
-static dhd_pktid_map_handle_t *
-dhd_pktid_map_init(dhd_pub_t *dhd, uint32 num_items, uint32 index)
-{
-	void *osh;
-	uint32 nkey;
-	dhd_pktid_map_t *map;
-	uint32 dhd_pktid_map_sz;
-	uint32 map_items;
-#ifdef DHD_USE_STATIC_PKTIDMAP
-	uint32 section;
-#endif /* DHD_USE_STATIC_PKTIDMAP */
-	osh = dhd->osh;
-
-	ASSERT((num_items >= 1) && (num_items <= MAX_PKTID_ITEMS));
-	dhd_pktid_map_sz = DHD_PKTID_MAP_SZ(num_items);
-
-#ifdef DHD_USE_STATIC_PKTIDMAP
-	if (index == PKTID_MAP_HANDLE) {
-		section = DHD_PREALLOC_PKTID_MAP;
-	} else {
-		section = DHD_PREALLOC_PKTID_MAP_IOCTL;
-	}
-
-	map = (dhd_pktid_map_t *)DHD_OS_PREALLOC(dhd, section, dhd_pktid_map_sz);
-#else
-	map = (dhd_pktid_map_t *)MALLOC(osh, dhd_pktid_map_sz);
-#endif /* DHD_USE_STATIC_PKTIDMAP */
-
-	if (map == NULL) {
-		DHD_ERROR(("%s:%d: MALLOC failed for size %d\n",
-			__FUNCTION__, __LINE__, dhd_pktid_map_sz));
-		goto error;
-	}
-
-	bzero(map, dhd_pktid_map_sz);
-
-	/* Initialize the lock that protects this structure */
-	map->pktid_lock = DHD_PKTID_LOCK_INIT(osh);
-	if (map->pktid_lock == NULL) {
-		DHD_ERROR(("%s:%d: Lock init failed \r\n", __FUNCTION__, __LINE__));
-		goto error;
-	}
-
-	map->items = num_items;
-	map->avail = num_items;
-
-	map_items = DHD_PKIDMAP_ITEMS(map->items);
-
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-	/* Incarnate a hierarchical multiword bitmap for auditing pktid allocator */
-	map->pktid_audit = bcm_mwbmap_init(osh, map_items + 1);
-	if (map->pktid_audit == (struct bcm_mwbmap *)NULL) {
-		DHD_ERROR(("%s:%d: pktid_audit init failed\r\n", __FUNCTION__, __LINE__));
-		goto error;
-	} else {
-		DHD_ERROR(("%s:%d: pktid_audit init succeeded %d\n",
-			__FUNCTION__, __LINE__, map_items + 1));
-	}
-
-	map->pktid_audit_lock = DHD_PKTID_AUDIT_LOCK_INIT(osh);
-
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-	for (nkey = 1; nkey <= map_items; nkey++) { /* locker #0 is reserved */
-		map->keys[nkey] = nkey; /* populate with unique keys */
-		map->lockers[nkey].state = LOCKER_IS_FREE;
-		map->lockers[nkey].pkt   = NULL; /* bzero: redundant */
-		map->lockers[nkey].len   = 0;
-	}
-
-	/* Reserve pktid #0, i.e. DHD_PKTID_INVALID to be busy */
-	map->lockers[DHD_PKTID_INVALID].state = LOCKER_IS_BUSY;
-	map->lockers[DHD_PKTID_INVALID].pkt   = NULL; /* bzero: redundant */
-	map->lockers[DHD_PKTID_INVALID].len   = 0;
-
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-	/* do not use dhd_pktid_audit() here, use bcm_mwbmap_force directly */
-	bcm_mwbmap_force(map->pktid_audit, DHD_PKTID_INVALID);
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-	return (dhd_pktid_map_handle_t *)map; /* opaque handle */
-
-error:
-
-	if (map) {
-
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-		if (map->pktid_audit != (struct bcm_mwbmap *)NULL) {
-			bcm_mwbmap_fini(osh, map->pktid_audit); /* Destruct pktid_audit */
-			map->pktid_audit = (struct bcm_mwbmap *)NULL;
-			if (map->pktid_audit_lock)
-				DHD_PKTID_AUDIT_LOCK_DEINIT(osh, map->pktid_audit_lock);
-		}
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-		if (map->pktid_lock)
-			DHD_PKTID_LOCK_DEINIT(osh, map->pktid_lock);
-
-		MFREE(osh, map, dhd_pktid_map_sz);
-	}
-
-	return (dhd_pktid_map_handle_t *)NULL;
-}
-
-/**
- * Retrieve all allocated keys and free all <numbered_key, locker>.
- * Freeing implies: unmapping the buffers and freeing the native packet
- * This could have been a callback registered with the pktid mapper.
- */
-
-static void
-dhd_pktid_map_fini(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle)
-{
-	void *osh;
-	uint32 nkey;
-	dhd_pktid_map_t *map;
-	uint32 dhd_pktid_map_sz;
-	dhd_pktid_item_t *locker;
-	uint32 map_items;
-	uint32 flags;
-
-	if (handle == NULL) {
-		return;
-	}
-
-	map = (dhd_pktid_map_t *)handle;
-	flags =  DHD_PKTID_LOCK(map->pktid_lock);
-	osh = dhd->osh;
-
-	dhd_pktid_map_sz = DHD_PKTID_MAP_SZ(map->items);
-
-	nkey = 1; /* skip reserved KEY #0, and start from 1 */
-	locker = &map->lockers[nkey];
-
-	map_items = DHD_PKIDMAP_ITEMS(map->items);
-
-	for (; nkey <= map_items; nkey++, locker++) {
-
-		if (locker->state == LOCKER_IS_BUSY) { /* numbered key still in use */
-
-			locker->state = LOCKER_IS_FREE; /* force open the locker */
-
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-			DHD_PKTID_AUDIT(dhd, map, nkey, DHD_DUPLICATE_FREE); /* duplicate frees */
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-			{   /* This could be a callback registered with dhd_pktid_map */
-				DMA_UNMAP(osh, locker->pa, locker->len,
-					locker->dir, 0, DHD_DMAH_NULL);
-				dhd_prot_packet_free(dhd, (ulong*)locker->pkt,
-					locker->pkttype, TRUE);
-			}
-		}
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-		else {
-			DHD_PKTID_AUDIT(dhd, map, nkey, DHD_TEST_IS_FREE);
-		}
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-		locker->pkt = NULL; /* clear saved pkt */
-		locker->len = 0;
-	}
-
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-	if (map->pktid_audit != (struct bcm_mwbmap *)NULL) {
-		bcm_mwbmap_fini(osh, map->pktid_audit); /* Destruct pktid_audit */
-		map->pktid_audit = (struct bcm_mwbmap *)NULL;
-		if (map->pktid_audit_lock) {
-			DHD_PKTID_AUDIT_LOCK_DEINIT(osh, map->pktid_audit_lock);
-		}
-	}
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-	DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-	DHD_PKTID_LOCK_DEINIT(osh, map->pktid_lock);
-
-#ifdef DHD_USE_STATIC_PKTIDMAP
-	DHD_OS_PREFREE(dhd, handle, dhd_pktid_map_sz);
-#else
-	MFREE(osh, handle, dhd_pktid_map_sz);
-#endif /* DHD_USE_STATIC_PKTIDMAP */
-}
-
-#ifdef IOCTLRESP_USE_CONSTMEM
-/** Called in detach scenario. Releasing IOCTL buffers. */
-static void
-dhd_pktid_map_fini_ioctl(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle)
-{
-	uint32 nkey;
-	dhd_pktid_map_t *map;
-	uint32 dhd_pktid_map_sz;
-	dhd_pktid_item_t *locker;
-	uint32 map_items;
-	uint32 flags;
-	osl_t *osh = dhd->osh;
-
-	if (handle == NULL) {
-		return;
-	}
-
-	map = (dhd_pktid_map_t *)handle;
-	flags = DHD_PKTID_LOCK(map->pktid_lock);
-
-	dhd_pktid_map_sz = DHD_PKTID_MAP_SZ(map->items);
-
-	nkey = 1; /* skip reserved KEY #0, and start from 1 */
-	locker = &map->lockers[nkey];
-
-	map_items = DHD_PKIDMAP_ITEMS(map->items);
-
-	for (; nkey <= map_items; nkey++, locker++) {
-
-		if (locker->state == LOCKER_IS_BUSY) { /* numbered key still in use */
-
-			locker->state = LOCKER_IS_FREE; /* force open the locker */
-
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-			DHD_PKTID_AUDIT(dhd, map, nkey, DHD_DUPLICATE_FREE); /* duplicate frees */
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-			{
-				dhd_dma_buf_t retbuf;
-				retbuf.va = locker->pkt;
-				retbuf.len = locker->len;
-				retbuf.pa = locker->pa;
-				retbuf.dmah = locker->dmah;
-				retbuf.secdma = locker->secdma;
-
-				/* This could be a callback registered with dhd_pktid_map */
-				DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-				free_ioctl_return_buffer(dhd, &retbuf);
-				flags = DHD_PKTID_LOCK(map->pktid_lock);
-			}
-		}
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-		else {
-			DHD_PKTID_AUDIT(dhd, map, nkey, DHD_TEST_IS_FREE);
-		}
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-		locker->pkt = NULL; /* clear saved pkt */
-		locker->len = 0;
-	}
-
-#if defined(DHD_PKTID_AUDIT_ENABLED)
-	if (map->pktid_audit != (struct bcm_mwbmap *)NULL) {
-		bcm_mwbmap_fini(osh, map->pktid_audit); /* Destruct pktid_audit */
-		map->pktid_audit = (struct bcm_mwbmap *)NULL;
-		if (map->pktid_audit_lock) {
-			DHD_PKTID_AUDIT_LOCK_DEINIT(osh, map->pktid_audit_lock);
-		}
-	}
-#endif /* DHD_PKTID_AUDIT_ENABLED */
-
-	DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-	DHD_PKTID_LOCK_DEINIT(osh, map->pktid_lock);
-
-#ifdef DHD_USE_STATIC_PKTIDMAP
-	DHD_OS_PREFREE(dhd, handle, dhd_pktid_map_sz);
-#else
-	MFREE(osh, handle, dhd_pktid_map_sz);
-#endif /* DHD_USE_STATIC_PKTIDMAP */
-}
-#endif /* IOCTLRESP_USE_CONSTMEM */
-
-/** Get the pktid free count */
-static INLINE uint32 BCMFASTPATH
-dhd_pktid_map_avail_cnt(dhd_pktid_map_handle_t *handle)
-{
-	dhd_pktid_map_t *map;
-	uint32	flags;
-	uint32	avail;
-
-	ASSERT(handle != NULL);
-	map = (dhd_pktid_map_t *)handle;
-
-	flags = DHD_PKTID_LOCK(map->pktid_lock);
-	avail = map->avail;
-	DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-
-	return avail;
-}
-
-/**
- * Allocate locker, save pkt contents, and return the locker's numbered key.
- * dhd_pktid_map_alloc() is not reentrant, and is the caller's responsibility.
- * Caller must treat a returned value DHD_PKTID_INVALID as a failure case,
- * implying a depleted pool of pktids.
- */
-
-static INLINE uint32
-__dhd_pktid_map_reserve(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, void *pkt)
-{
-	uint32 nkey;
-	dhd_pktid_map_t *map;
-	dhd_pktid_item_t *locker;
-
-	ASSERT(handle != NULL);
-	map = (dhd_pktid_map_t *)handle;
-
-	if (map->avail <= 0) { /* no more pktids to allocate */
-		map->failures++;
-		DHD_INFO(("%s:%d: failed, no free keys\n", __FUNCTION__, __LINE__));
-		return DHD_PKTID_INVALID; /* failed alloc request */
-	}
-
-	ASSERT(map->avail <= map->items);
-	nkey = map->keys[map->avail]; /* fetch a free locker, pop stack */
-	locker = &map->lockers[nkey]; /* save packet metadata in locker */
-	map->avail--;
-	locker->pkt = pkt; /* pkt is saved, other params not yet saved. */
-	locker->len = 0;
-	locker->state = LOCKER_IS_BUSY; /* reserve this locker */
-
-#if defined(DHD_PKTID_AUDIT_MAP)
-	DHD_PKTID_AUDIT(dhd, map, nkey, DHD_DUPLICATE_ALLOC); /* Audit duplicate alloc */
-#endif /* DHD_PKTID_AUDIT_MAP */
-
-	ASSERT(nkey != DHD_PKTID_INVALID);
-	return nkey; /* return locker's numbered key */
-}
-
-
-/**
- * dhd_pktid_map_reserve - reserve a unique numbered key. Reserved locker is not
- * yet populated. Invoke the pktid save api to populate the packet parameters
- * into the locker.
- * Wrapper that takes the required lock when called directly.
- */
-static INLINE uint32
-dhd_pktid_map_reserve(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, void *pkt)
-{
-	dhd_pktid_map_t *map;
-	uint32 flags;
-	uint32 ret;
-
-	ASSERT(handle != NULL);
-	map = (dhd_pktid_map_t *)handle;
-	flags = DHD_PKTID_LOCK(map->pktid_lock);
-	ret = __dhd_pktid_map_reserve(dhd, handle, pkt);
-	DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-
-	return ret;
-}
-
-static INLINE void
-__dhd_pktid_map_save(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, void *pkt,
-	uint32 nkey, dmaaddr_t pa, uint32 len, uint8 dir, void *dmah, void *secdma,
-	dhd_pkttype_t pkttype)
-{
-	dhd_pktid_map_t *map;
-	dhd_pktid_item_t *locker;
-
-	ASSERT(handle != NULL);
-	map = (dhd_pktid_map_t *)handle;
-
-	ASSERT((nkey != DHD_PKTID_INVALID) && (nkey <= DHD_PKIDMAP_ITEMS(map->items)));
-
-	locker = &map->lockers[nkey];
-
-	ASSERT(((locker->state == LOCKER_IS_BUSY) && (locker->pkt == pkt)) ||
-		((locker->state == LOCKER_IS_RSVD) && (locker->pkt == NULL)));
-
-#if defined(DHD_PKTID_AUDIT_MAP)
-	DHD_PKTID_AUDIT(dhd, map, nkey, DHD_TEST_IS_ALLOC); /* apriori, reservation */
-#endif /* DHD_PKTID_AUDIT_MAP */
-
-	/* store contents in locker */
-	locker->dir = dir;
-	locker->pa = pa;
-	locker->len = (uint16)len; /* 16bit len */
-	locker->dmah = dmah; /* 16bit len */
-	locker->secdma = secdma;
-	locker->pkttype = pkttype;
-	locker->pkt = pkt;
-	locker->state = LOCKER_IS_BUSY; /* make this locker busy */
-}
-
-/**
- * dhd_pktid_map_save - Save a packet's parameters into a locker corresponding
- * to a previously reserved unique numbered key.
- * Wrapper that takes the required lock when called directly.
- */
-static INLINE void
-dhd_pktid_map_save(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, void *pkt,
-	uint32 nkey, dmaaddr_t pa, uint32 len, uint8 dir, void *dmah, void *secdma,
-	dhd_pkttype_t pkttype)
-{
-	dhd_pktid_map_t *map;
-	uint32 flags;
-
-	ASSERT(handle != NULL);
-	map = (dhd_pktid_map_t *)handle;
-	flags = DHD_PKTID_LOCK(map->pktid_lock);
-	__dhd_pktid_map_save(dhd, handle, pkt, nkey, pa, len,
-		dir, dmah, secdma, pkttype);
-	DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-}
-
-/**
- * dhd_pktid_map_alloc - Allocate a unique numbered key and save the packet
- * contents into the corresponding locker. Return the numbered key.
- */
-static uint32 BCMFASTPATH
-dhd_pktid_map_alloc(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, void *pkt,
-	dmaaddr_t pa, uint32 len, uint8 dir, void *dmah, void *secdma,
-	dhd_pkttype_t pkttype)
-{
-	uint32 nkey;
-	uint32 flags;
-	dhd_pktid_map_t *map;
-
-	ASSERT(handle != NULL);
-	map = (dhd_pktid_map_t *)handle;
-
-	flags = DHD_PKTID_LOCK(map->pktid_lock);
-
-	nkey = __dhd_pktid_map_reserve(dhd, handle, pkt);
-	if (nkey != DHD_PKTID_INVALID) {
-		__dhd_pktid_map_save(dhd, handle, pkt, nkey, pa,
-			len, dir, dmah, secdma, pkttype);
-#if defined(DHD_PKTID_AUDIT_MAP)
-		DHD_PKTID_AUDIT(dhd, map, nkey, DHD_TEST_IS_ALLOC); /* apriori, reservation */
-#endif /* DHD_PKTID_AUDIT_MAP */
-	}
-
-	DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-
-	return nkey;
-}
-
-/**
- * dhd_pktid_map_free - Given a numbered key, return the locker contents.
- * dhd_pktid_map_free() is not reentrant, and is the caller's responsibility.
- * Caller may not free a pktid value DHD_PKTID_INVALID or an arbitrary pktid
- * value. Only a previously allocated pktid may be freed.
- */
-static void * BCMFASTPATH
-dhd_pktid_map_free(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, uint32 nkey,
-	dmaaddr_t *pa, uint32 *len, void **dmah, void **secdma,
-	dhd_pkttype_t pkttype, bool rsv_locker)
-{
-	dhd_pktid_map_t *map;
-	dhd_pktid_item_t *locker;
-	void * pkt;
-	uint32 flags;
-
-	ASSERT(handle != NULL);
-
-	map = (dhd_pktid_map_t *)handle;
-
-	flags = DHD_PKTID_LOCK(map->pktid_lock);
-
-	ASSERT((nkey != DHD_PKTID_INVALID) && (nkey <= DHD_PKIDMAP_ITEMS(map->items)));
-
-	locker = &map->lockers[nkey];
-
-#if defined(DHD_PKTID_AUDIT_MAP)
-	DHD_PKTID_AUDIT(dhd, map, nkey, DHD_DUPLICATE_FREE); /* Audit duplicate FREE */
-#endif /* DHD_PKTID_AUDIT_MAP */
-
-	if (locker->state == LOCKER_IS_FREE) { /* Debug check for cloned numbered key */
-		DHD_ERROR(("%s:%d: Error! freeing invalid pktid<%u>\n",
-			__FUNCTION__, __LINE__, nkey));
-		ASSERT(locker->state != LOCKER_IS_FREE);
-
-		DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-		return NULL;
-	}
-
-	/* Check for the colour of the buffer i.e The buffer posted for TX,
-	 * should be freed for TX completion. Similarly the buffer posted for
-	 * IOCTL should be freed for IOCT completion etc.
-	 */
-	if ((pkttype != PKTTYPE_NO_CHECK) && (locker->pkttype != pkttype)) {
-
-		DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-
-		DHD_ERROR(("%s:%d: Error! Invalid Buffer Free for pktid<%u> \n",
-			__FUNCTION__, __LINE__, nkey));
-		ASSERT(locker->pkttype == pkttype);
-
-		return NULL;
-	}
-
-	if (rsv_locker == DHD_PKTID_FREE_LOCKER) {
-		map->avail++;
-		map->keys[map->avail] = nkey; /* make this numbered key available */
-		locker->state = LOCKER_IS_FREE; /* open and free Locker */
-	} else {
-		/* pktid will be reused, but the locker does not have a valid pkt */
-		locker->state = LOCKER_IS_RSVD;
-	}
-
-#if defined(DHD_PKTID_AUDIT_MAP)
-	DHD_PKTID_AUDIT(dhd, map, nkey, DHD_TEST_IS_FREE);
-#endif /* DHD_PKTID_AUDIT_MAP */
-
-	*pa = locker->pa; /* return contents of locker */
-	*len = (uint32)locker->len;
-	*dmah = locker->dmah;
-	*secdma = locker->secdma;
-
-	pkt = locker->pkt;
-	locker->pkt = NULL; /* Clear pkt */
-	locker->len = 0;
-
-	DHD_PKTID_UNLOCK(map->pktid_lock, flags);
-	return pkt;
-}
-
-#else /* ! DHD_PCIE_PKTID */
-
-
-typedef struct pktlist {
-	PKT_LIST *tx_pkt_list;		/* list for tx packets */
-	PKT_LIST *rx_pkt_list;		/* list for rx packets */
-	PKT_LIST *ctrl_pkt_list;	/* list for ioctl/event buf post */
-} pktlists_t;
-
-/*
- * Given that each workitem only uses a 32bit pktid, only 32bit hosts may avail
- * of a one to one mapping 32bit pktptr and a 32bit pktid.
- *
- * - When PKTIDMAP is not used, DHD_NATIVE_TO_PKTID variants will never fail.
- * - Neither DHD_NATIVE_TO_PKTID nor DHD_PKTID_TO_NATIVE need to be protected by
- *   a lock.
- * - Hence DHD_PKTID_INVALID is not defined when DHD_PCIE_PKTID is undefined.
- */
-#define DHD_PKTID32(pktptr32)	((uint32)(pktptr32))
-#define DHD_PKTPTR32(pktid32)	((void *)(pktid32))
-
-
-static INLINE uint32 dhd_native_to_pktid(dhd_pktid_map_handle_t *map, void *pktptr32,
-	dmaaddr_t pa, uint32 dma_len, void *dmah, void *secdma,
-	dhd_pkttype_t pkttype);
-static INLINE void * dhd_pktid_to_native(dhd_pktid_map_handle_t *map, uint32 pktid32,
-	dmaaddr_t *pa, uint32 *dma_len, void **dmah, void **secdma,
-	dhd_pkttype_t pkttype);
-
-static dhd_pktid_map_handle_t *
-dhd_pktid_map_init(dhd_pub_t *dhd, uint32 num_items, uint32 index)
-{
-	osl_t *osh = dhd->osh;
-	pktlists_t *handle = NULL;
-
-	if ((handle = (pktlists_t *) MALLOCZ(osh, sizeof(pktlists_t))) == NULL) {
-		DHD_ERROR(("%s:%d: MALLOC failed for lists allocation, size=%d\n",
-		           __FUNCTION__, __LINE__, sizeof(pktlists_t)));
-		goto error_done;
-	}
-
-	if ((handle->tx_pkt_list = (PKT_LIST *) MALLOC(osh, sizeof(PKT_LIST))) == NULL) {
-		DHD_ERROR(("%s:%d: MALLOC failed for list allocation, size=%d\n",
-		           __FUNCTION__, __LINE__, sizeof(PKT_LIST)));
-		goto error;
-	}
-
-	if ((handle->rx_pkt_list = (PKT_LIST *) MALLOC(osh, sizeof(PKT_LIST))) == NULL) {
-		DHD_ERROR(("%s:%d: MALLOC failed for list allocation, size=%d\n",
-		           __FUNCTION__, __LINE__, sizeof(PKT_LIST)));
-		goto error;
-	}
-
-	if ((handle->ctrl_pkt_list = (PKT_LIST *) MALLOC(osh, sizeof(PKT_LIST))) == NULL) {
-		DHD_ERROR(("%s:%d: MALLOC failed for list allocation, size=%d\n",
-		           __FUNCTION__, __LINE__, sizeof(PKT_LIST)));
-		goto error;
-	}
-
-	PKTLIST_INIT(handle->tx_pkt_list);
-	PKTLIST_INIT(handle->rx_pkt_list);
-	PKTLIST_INIT(handle->ctrl_pkt_list);
-
-	return (dhd_pktid_map_handle_t *) handle;
-
-error:
-	if (handle->ctrl_pkt_list) {
-		MFREE(osh, handle->ctrl_pkt_list, sizeof(PKT_LIST));
-	}
-
-	if (handle->rx_pkt_list) {
-		MFREE(osh, handle->rx_pkt_list, sizeof(PKT_LIST));
-	}
-
-	if (handle->tx_pkt_list) {
-		MFREE(osh, handle->tx_pkt_list, sizeof(PKT_LIST));
-	}
-
-	if (handle) {
-		MFREE(osh, handle, sizeof(pktlists_t));
-	}
-
-error_done:
-	return (dhd_pktid_map_handle_t *)NULL;
-}
-
-static void
-dhd_pktid_map_fini(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map)
-{
-	osl_t *osh = dhd->osh;
-	pktlists_t *handle = (pktlists_t *) map;
-
-	ASSERT(handle != NULL);
-	if (handle == (pktlists_t *)NULL) {
-		return;
-	}
-
-	if (handle->ctrl_pkt_list) {
-		PKTLIST_FINI(handle->ctrl_pkt_list);
-		MFREE(osh, handle->ctrl_pkt_list, sizeof(PKT_LIST));
-	}
-
-	if (handle->rx_pkt_list) {
-		PKTLIST_FINI(handle->rx_pkt_list);
-		MFREE(osh, handle->rx_pkt_list, sizeof(PKT_LIST));
-	}
-
-	if (handle->tx_pkt_list) {
-		PKTLIST_FINI(handle->tx_pkt_list);
-		MFREE(osh, handle->tx_pkt_list, sizeof(PKT_LIST));
-	}
-
-	if (handle) {
-		MFREE(osh, handle, sizeof(pktlists_t));
-	}
-}
-
-/** Save dma parameters into the packet's pkttag and convert a pktptr to pktid */
-static INLINE uint32
-dhd_native_to_pktid(dhd_pktid_map_handle_t *map, void *pktptr32,
-	dmaaddr_t pa, uint32 dma_len, void *dmah, void *secdma,
-	dhd_pkttype_t pkttype)
-{
-	pktlists_t *handle = (pktlists_t *) map;
-	ASSERT(pktptr32 != NULL);
-	DHD_PKT_SET_DMA_LEN(pktptr32, dma_len);
-	DHD_PKT_SET_DMAH(pktptr32, dmah);
-	DHD_PKT_SET_PA(pktptr32, pa);
-	DHD_PKT_SET_SECDMA(pktptr32, secdma);
-
-	if (pkttype == PKTTYPE_DATA_TX) {
-		PKTLIST_ENQ(handle->tx_pkt_list,  pktptr32);
-	} else if (pkttype == PKTTYPE_DATA_RX) {
-		PKTLIST_ENQ(handle->rx_pkt_list,  pktptr32);
-	} else {
-		PKTLIST_ENQ(handle->ctrl_pkt_list,  pktptr32);
-	}
-
-	return DHD_PKTID32(pktptr32);
-}
-
-/** Convert a pktid to pktptr and retrieve saved dma parameters from packet */
-static INLINE void *
-dhd_pktid_to_native(dhd_pktid_map_handle_t *map, uint32 pktid32,
-	dmaaddr_t *pa, uint32 *dma_len, void **dmah, void **secdma,
-	dhd_pkttype_t pkttype)
-{
-	pktlists_t *handle = (pktlists_t *) map;
-	void *pktptr32;
-
-	ASSERT(pktid32 != 0U);
-	pktptr32 = DHD_PKTPTR32(pktid32);
-	*dma_len = DHD_PKT_GET_DMA_LEN(pktptr32);
-	*dmah = DHD_PKT_GET_DMAH(pktptr32);
-	*pa = DHD_PKT_GET_PA(pktptr32);
-	*secdma = DHD_PKT_GET_SECDMA(pktptr32);
-
-	if (pkttype == PKTTYPE_DATA_TX) {
-		PKTLIST_UNLINK(handle->tx_pkt_list,  pktptr32);
-	} else if (pkttype == PKTTYPE_DATA_RX) {
-		PKTLIST_UNLINK(handle->rx_pkt_list,  pktptr32);
-	} else {
-		PKTLIST_UNLINK(handle->ctrl_pkt_list,  pktptr32);
-	}
-
-	return pktptr32;
-}
-
-#define DHD_NATIVE_TO_PKTID_RSV(dhd, map, pkt)  DHD_PKTID32(pkt)
-
-#define DHD_NATIVE_TO_PKTID_SAVE(dhd, map, pkt, nkey, pa, len, dma_dir, dmah, secdma, pkttype) \
-	({ BCM_REFERENCE(dhd); BCM_REFERENCE(nkey); BCM_REFERENCE(dma_dir); \
-	   dhd_native_to_pktid((dhd_pktid_map_handle_t *) map, (pkt), (pa), (len), \
-			   (dmah), (secdma), (dhd_pkttype_t)(pkttype)); \
-	})
-
-#define DHD_NATIVE_TO_PKTID(dhd, map, pkt, pa, len, dma_dir, dmah, secdma, pkttype) \
-	({ BCM_REFERENCE(dhd); BCM_REFERENCE(dma_dir); \
-	   dhd_native_to_pktid((dhd_pktid_map_handle_t *) map, (pkt), (pa), (len), \
-			   (dmah), (secdma), (dhd_pkttype_t)(pkttype)); \
-	})
-
-#define DHD_PKTID_TO_NATIVE(dhd, map, pktid, pa, len, dmah, secdma, pkttype) \
-	({ BCM_REFERENCE(dhd); BCM_REFERENCE(pkttype);	\
-		dhd_pktid_to_native((dhd_pktid_map_handle_t *) map, (uint32)(pktid), \
-				(dmaaddr_t *)&(pa), (uint32 *)&(len), (void **)&(dmah), \
-				(void **)&secdma, (dhd_pkttype_t)(pkttype)); \
-	})
-
-#define DHD_PKTID_AVAIL(map)  (~0)
-
-#endif /* ! DHD_PCIE_PKTID */
-
-/* +------------------ End of PCIE DHD PKTID MAPPER  -----------------------+ */
-
-
-/**
- * The PCIE FD protocol layer is constructed in two phases:
- *    Phase 1. dhd_prot_attach()
- *    Phase 2. dhd_prot_init()
- *
- * dhd_prot_attach() - Allocates a dhd_prot_t object and resets all its fields.
- * All Common rings are allose attached (msgbuf_ring_t objects are allocated
- * with DMA-able buffers).
- * All dhd_dma_buf_t objects are also allocated here.
- *
- * As dhd_prot_attach is invoked prior to the pcie_shared object is read, any
- * initialization of objects that requires information advertized by the dongle
- * may not be performed here.
- * E.g. the number of TxPost flowrings is not know at this point, neither do
- * we know shich form of D2H DMA sync mechanism is advertized by the dongle, or
- * whether the dongle supports DMA-ing of WR/RD indices for the H2D and/or D2H
- * rings (common + flow).
- *
- * dhd_prot_init() is invoked after the bus layer has fetched the information
- * advertized by the dongle in the pcie_shared_t.
- */
-int
-dhd_prot_attach(dhd_pub_t *dhd)
-{
-	osl_t *osh = dhd->osh;
-	dhd_prot_t *prot;
-
-	/* Allocate prot structure */
-	if (!(prot = (dhd_prot_t *)DHD_OS_PREALLOC(dhd, DHD_PREALLOC_PROT,
-		sizeof(dhd_prot_t)))) {
-		DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
-		goto fail;
-	}
-	memset(prot, 0, sizeof(*prot));
-
-	prot->osh = osh;
-	dhd->prot = prot;
-
-	/* DMAing ring completes supported? FALSE by default  */
-	dhd->dma_d2h_ring_upd_support = FALSE;
-	dhd->dma_h2d_ring_upd_support = FALSE;
-
-	/* Common Ring Allocations */
-
-	/* Ring  0: H2D Control Submission */
-	if (dhd_prot_ring_attach(dhd, &prot->h2dring_ctrl_subn, "h2dctrl",
-	        H2DRING_CTRL_SUB_MAX_ITEM, H2DRING_CTRL_SUB_ITEMSIZE,
-	        BCMPCIE_H2D_MSGRING_CONTROL_SUBMIT) != BCME_OK) {
-		DHD_ERROR(("%s: dhd_prot_ring_attach H2D Ctrl Submission failed\n",
-			__FUNCTION__));
-		goto fail;
-	}
-
-	/* Ring  1: H2D Receive Buffer Post */
-	if (dhd_prot_ring_attach(dhd, &prot->h2dring_rxp_subn, "h2drxp",
-	        H2DRING_RXPOST_MAX_ITEM, H2DRING_RXPOST_ITEMSIZE,
-	        BCMPCIE_H2D_MSGRING_RXPOST_SUBMIT) != BCME_OK) {
-		DHD_ERROR(("%s: dhd_prot_ring_attach H2D RxPost failed\n",
-			__FUNCTION__));
-		goto fail;
-	}
-
-	/* Ring  2: D2H Control Completion */
-	if (dhd_prot_ring_attach(dhd, &prot->d2hring_ctrl_cpln, "d2hctrl",
-	        D2HRING_CTRL_CMPLT_MAX_ITEM, D2HRING_CTRL_CMPLT_ITEMSIZE,
-	        BCMPCIE_D2H_MSGRING_CONTROL_COMPLETE) != BCME_OK) {
-		DHD_ERROR(("%s: dhd_prot_ring_attach D2H Ctrl Completion failed\n",
-			__FUNCTION__));
-		goto fail;
-	}
-
-	/* Ring  3: D2H Transmit Complete */
-	if (dhd_prot_ring_attach(dhd, &prot->d2hring_tx_cpln, "d2htxcpl",
-	        D2HRING_TXCMPLT_MAX_ITEM, D2HRING_TXCMPLT_ITEMSIZE,
-	        BCMPCIE_D2H_MSGRING_TX_COMPLETE) != BCME_OK) {
-		DHD_ERROR(("%s: dhd_prot_ring_attach D2H Tx Completion failed\n",
-			__FUNCTION__));
-		goto fail;
-
-	}
-
-	/* Ring  4: D2H Receive Complete */
-	if (dhd_prot_ring_attach(dhd, &prot->d2hring_rx_cpln, "d2hrxcpl",
-	        D2HRING_RXCMPLT_MAX_ITEM, D2HRING_RXCMPLT_ITEMSIZE,
-	        BCMPCIE_D2H_MSGRING_RX_COMPLETE) != BCME_OK) {
-		DHD_ERROR(("%s: dhd_prot_ring_attach D2H Rx Completion failed\n",
-			__FUNCTION__));
-		goto fail;
-
-	}
-
-	/*
-	 * Max number of flowrings is not yet known. msgbuf_ring_t with DMA-able
-	 * buffers for flowrings will be instantiated, in dhd_prot_init() .
-	 * See dhd_prot_flowrings_pool_attach()
-	 */
-	/* ioctl response buffer */
-	if (dhd_dma_buf_alloc(dhd, &prot->retbuf, IOCT_RETBUF_SIZE)) {
-		goto fail;
-	}
-
-	/* IOCTL request buffer */
-	if (dhd_dma_buf_alloc(dhd, &prot->ioctbuf, IOCT_RETBUF_SIZE)) {
-		goto fail;
-	}
-
-	/* Scratch buffer for dma rx offset */
-	if (dhd_dma_buf_alloc(dhd, &prot->d2h_dma_scratch_buf, DMA_D2H_SCRATCH_BUF_LEN)) {
-		goto fail;
-	}
-
-	/* scratch buffer bus throughput measurement */
-	if (dhd_dma_buf_alloc(dhd, &prot->host_bus_throughput_buf, DHD_BUS_TPUT_BUF_LEN)) {
-		goto fail;
-	}
-
-#ifdef DHD_RX_CHAINING
-	dhd_rxchain_reset(&prot->rxchain);
-#endif
-
-#if defined(DHD_LB)
-
-	   /* Initialize the work queues to be used by the Load Balancing logic */
-#if defined(DHD_LB_TXC)
-	{
-		void *buffer;
-		buffer = MALLOC(dhd->osh, sizeof(void*) * DHD_LB_WORKQ_SZ);
-		bcm_workq_init(&prot->tx_compl_prod, &prot->tx_compl_cons,
-			buffer, DHD_LB_WORKQ_SZ);
-		prot->tx_compl_prod_sync = 0;
-		DHD_INFO(("%s: created tx_compl_workq <%p,%d>\n",
-			__FUNCTION__, buffer, DHD_LB_WORKQ_SZ));
-	}
-#endif /* DHD_LB_TXC */
-
-#if defined(DHD_LB_RXC)
-	{
-		void *buffer;
-		buffer = MALLOC(dhd->osh, sizeof(uint32) * DHD_LB_WORKQ_SZ);
-		bcm_workq_init(&prot->rx_compl_prod, &prot->rx_compl_cons,
-			buffer, DHD_LB_WORKQ_SZ);
-		prot->rx_compl_prod_sync = 0;
-		DHD_INFO(("%s: created rx_compl_workq <%p,%d>\n",
-			__FUNCTION__, buffer, DHD_LB_WORKQ_SZ));
-	}
-#endif /* DHD_LB_RXC */
-
-#endif /* DHD_LB */
-
-	return BCME_OK;
-
-fail:
-
-#ifndef CONFIG_DHD_USE_STATIC_BUF
-	if (prot != NULL) {
-		dhd_prot_detach(dhd);
-	}
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-
-	return BCME_NOMEM;
-} /* dhd_prot_attach */
-
-
-/**
- * dhd_prot_init - second stage of dhd_prot_attach. Now that the dongle has
- * completed it's initialization of the pcie_shared structure, we may now fetch
- * the dongle advertized features and adjust the protocol layer accordingly.
- *
- * dhd_prot_init() may be invoked again after a dhd_prot_reset().
- */
-int
-dhd_prot_init(dhd_pub_t *dhd)
-{
-	sh_addr_t base_addr;
-	dhd_prot_t *prot = dhd->prot;
-
-	/* PKTID handle INIT */
-	if (prot->pktid_map_handle != NULL) {
-		DHD_ERROR(("%s: pktid_map_handle already set!\n", __FUNCTION__));
-		ASSERT(0);
-		return BCME_ERROR;
-	}
-
-#ifdef IOCTLRESP_USE_CONSTMEM
-	if (prot->pktid_map_handle_ioctl != NULL) {
-		DHD_ERROR(("%s: pktid_map_handle_ioctl already set!\n", __FUNCTION__));
-		ASSERT(0);
-		return BCME_ERROR;
-	}
-#endif /* IOCTLRESP_USE_CONSTMEM */
-
-	prot->pktid_map_handle = DHD_NATIVE_TO_PKTID_INIT(dhd, MAX_PKTID_ITEMS, PKTID_MAP_HANDLE);
-	if (prot->pktid_map_handle == NULL) {
-		DHD_ERROR(("%s: Unable to map packet id's\n", __FUNCTION__));
-		ASSERT(0);
-		return BCME_NOMEM;
-	}
-
-#ifdef IOCTLRESP_USE_CONSTMEM
-	prot->pktid_map_handle_ioctl = DHD_NATIVE_TO_PKTID_INIT(dhd,
-		DHD_FLOWRING_MAX_IOCTLRESPBUF_POST, PKTID_MAP_HANDLE_IOCTL);
-	if (prot->pktid_map_handle_ioctl == NULL) {
-		DHD_ERROR(("%s: Unable to map ioctl response buffers\n", __FUNCTION__));
-		ASSERT(0);
-		return BCME_NOMEM;
-	}
-#endif /* IOCTLRESP_USE_CONSTMEM */
-
-	/* Max pkts in ring */
-	prot->max_tx_count = H2DRING_TXPOST_MAX_ITEM;
-
-	DHD_INFO(("%s:%d: MAX_TX_COUNT = %d\n", __FUNCTION__, __LINE__, prot->max_tx_count));
-
-	/* Read max rx packets supported by dongle */
-	dhd_bus_cmn_readshared(dhd->bus, &prot->max_rxbufpost, MAX_HOST_RXBUFS, 0);
-	if (prot->max_rxbufpost == 0) {
-		/* This would happen if the dongle firmware is not */
-		/* using the latest shared structure template */
-		prot->max_rxbufpost = DEFAULT_RX_BUFFERS_TO_POST;
-	}
-	DHD_INFO(("%s:%d: MAX_RXBUFPOST = %d\n", __FUNCTION__, __LINE__, prot->max_rxbufpost));
-
-	/* Initialize.  bzero() would blow away the dma pointers. */
-	prot->max_eventbufpost = DHD_FLOWRING_MAX_EVENTBUF_POST;
-	prot->max_ioctlrespbufpost = DHD_FLOWRING_MAX_IOCTLRESPBUF_POST;
-
-	prot->cur_ioctlresp_bufs_posted = 0;
-	prot->active_tx_count = 0;
-	prot->data_seq_no = 0;
-	prot->ioctl_seq_no = 0;
-	prot->rxbufpost = 0;
-	prot->cur_event_bufs_posted = 0;
-	prot->ioctl_state = 0;
-	prot->curr_ioctl_cmd = 0;
-	prot->ioctl_received = IOCTL_WAIT;
-
-	prot->dmaxfer.srcmem.va = NULL;
-	prot->dmaxfer.dstmem.va = NULL;
-	prot->dmaxfer.in_progress = FALSE;
-
-	prot->metadata_dbg = FALSE;
-	prot->rx_metadata_offset = 0;
-	prot->tx_metadata_offset = 0;
-	prot->txp_threshold = TXP_FLUSH_MAX_ITEMS_FLUSH_CNT;
-
-	prot->ioctl_trans_id = 0;
-
-	/* Register the interrupt function upfront */
-	/* remove corerev checks in data path */
-	prot->mb_ring_fn = dhd_bus_get_mbintr_fn(dhd->bus);
-
-	/* Initialize Common MsgBuf Rings */
-
-	dhd_prot_ring_init(dhd, &prot->h2dring_ctrl_subn);
-	dhd_prot_ring_init(dhd, &prot->h2dring_rxp_subn);
-	dhd_prot_ring_init(dhd, &prot->d2hring_ctrl_cpln);
-	dhd_prot_ring_init(dhd, &prot->d2hring_tx_cpln);
-	dhd_prot_ring_init(dhd, &prot->d2hring_rx_cpln);
-
-#if defined(PCIE_D2H_SYNC)
-	dhd_prot_d2h_sync_init(dhd);
-#endif /* PCIE_D2H_SYNC */
-
-	dhd_prot_h2d_sync_init(dhd);
-
-	/* init the scratch buffer */
-	dhd_base_addr_htolpa(&base_addr, prot->d2h_dma_scratch_buf.pa);
-	dhd_bus_cmn_writeshared(dhd->bus, &base_addr, sizeof(base_addr),
-		D2H_DMA_SCRATCH_BUF, 0);
-	dhd_bus_cmn_writeshared(dhd->bus, &prot->d2h_dma_scratch_buf.len,
-		sizeof(prot->d2h_dma_scratch_buf.len), D2H_DMA_SCRATCH_BUF_LEN, 0);
-
-	/* If supported by the host, indicate the memory block
-	 * for completion writes / submission reads to shared space
-	 */
-	if (DMA_INDX_ENAB(dhd->dma_d2h_ring_upd_support)) {
-		dhd_base_addr_htolpa(&base_addr, prot->d2h_dma_indx_wr_buf.pa);
-		dhd_bus_cmn_writeshared(dhd->bus, &base_addr, sizeof(base_addr),
-			D2H_DMA_INDX_WR_BUF, 0);
-		dhd_base_addr_htolpa(&base_addr, prot->h2d_dma_indx_rd_buf.pa);
-		dhd_bus_cmn_writeshared(dhd->bus, &base_addr, sizeof(base_addr),
-			H2D_DMA_INDX_RD_BUF, 0);
-	}
-
-	if (DMA_INDX_ENAB(dhd->dma_h2d_ring_upd_support)) {
-		dhd_base_addr_htolpa(&base_addr, prot->h2d_dma_indx_wr_buf.pa);
-		dhd_bus_cmn_writeshared(dhd->bus, &base_addr, sizeof(base_addr),
-			H2D_DMA_INDX_WR_BUF, 0);
-		dhd_base_addr_htolpa(&base_addr, prot->d2h_dma_indx_rd_buf.pa);
-		dhd_bus_cmn_writeshared(dhd->bus, &base_addr, sizeof(base_addr),
-			D2H_DMA_INDX_RD_BUF, 0);
-	}
-
-	/*
-	 * If the DMA-able buffers for flowring needs to come from a specific
-	 * contiguous memory region, then setup prot->flowrings_dma_buf here.
-	 * dhd_prot_flowrings_pool_attach() will carve out DMA-able buffers from
-	 * this contiguous memory region, for each of the flowrings.
-	 */
-
-	/* Pre-allocate pool of msgbuf_ring for flowrings */
-	if (dhd_prot_flowrings_pool_attach(dhd) != BCME_OK) {
-		return BCME_ERROR;
-	}
-
-	/* Host should configure soft doorbells if needed ... here */
-
-	/* Post to dongle host configured soft doorbells */
-	dhd_msgbuf_ring_config_d2h_soft_doorbell(dhd);
-
-	/* Post buffers for packet reception and ioctl/event responses */
-	dhd_msgbuf_rxbuf_post(dhd, FALSE); /* alloc pkt ids */
-	dhd_msgbuf_rxbuf_post_ioctlresp_bufs(dhd);
-	dhd_msgbuf_rxbuf_post_event_bufs(dhd);
-
-	return BCME_OK;
-} /* dhd_prot_init */
-
-
-/**
- * dhd_prot_detach - PCIE FD protocol layer destructor.
- * Unlink, frees allocated protocol memory (including dhd_prot)
- */
-void
-dhd_prot_detach(dhd_pub_t *dhd)
-{
-	dhd_prot_t *prot = dhd->prot;
-
-	/* Stop the protocol module */
-	if (prot) {
-
-		/* free up all DMA-able buffers allocated during prot attach/init */
-
-		dhd_dma_buf_free(dhd, &prot->d2h_dma_scratch_buf);
-		dhd_dma_buf_free(dhd, &prot->retbuf); /* ioctl return buffer */
-		dhd_dma_buf_free(dhd, &prot->ioctbuf);
-		dhd_dma_buf_free(dhd, &prot->host_bus_throughput_buf);
-
-		/* DMA-able buffers for DMAing H2D/D2H WR/RD indices */
-		dhd_dma_buf_free(dhd, &prot->h2d_dma_indx_wr_buf);
-		dhd_dma_buf_free(dhd, &prot->h2d_dma_indx_rd_buf);
-		dhd_dma_buf_free(dhd, &prot->d2h_dma_indx_wr_buf);
-		dhd_dma_buf_free(dhd, &prot->d2h_dma_indx_rd_buf);
-
-		/* Common MsgBuf Rings */
-		dhd_prot_ring_detach(dhd, &prot->h2dring_ctrl_subn);
-		dhd_prot_ring_detach(dhd, &prot->h2dring_rxp_subn);
-		dhd_prot_ring_detach(dhd, &prot->d2hring_ctrl_cpln);
-		dhd_prot_ring_detach(dhd, &prot->d2hring_tx_cpln);
-		dhd_prot_ring_detach(dhd, &prot->d2hring_rx_cpln);
-
-		/* Detach each DMA-able buffer and free the pool of msgbuf_ring_t */
-		dhd_prot_flowrings_pool_detach(dhd);
-
-		DHD_NATIVE_TO_PKTID_FINI(dhd, dhd->prot->pktid_map_handle);
-
-#ifndef CONFIG_DHD_USE_STATIC_BUF
-		MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t));
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-
-#if defined(DHD_LB)
-#if defined(DHD_LB_TXC)
-		if (prot->tx_compl_prod.buffer) {
-			MFREE(dhd->osh, prot->tx_compl_prod.buffer,
-				sizeof(void*) * DHD_LB_WORKQ_SZ);
-		}
-#endif /* DHD_LB_TXC */
-#if defined(DHD_LB_RXC)
-		if (prot->rx_compl_prod.buffer) {
-			MFREE(dhd->osh, prot->rx_compl_prod.buffer,
-				sizeof(void*) * DHD_LB_WORKQ_SZ);
-		}
-#endif /* DHD_LB_RXC */
-#endif /* DHD_LB */
-
-		dhd->prot = NULL;
-	}
-} /* dhd_prot_detach */
-
-
-/**
- * dhd_prot_reset - Reset the protocol layer without freeing any objects. This
- * may be invoked to soft reboot the dongle, without having to detach and attach
- * the entire protocol layer.
- *
- * After dhd_prot_reset(), dhd_prot_init() may be invoked without going through
- * a dhd_prot_attach() phase.
- */
-void
-dhd_prot_reset(dhd_pub_t *dhd)
-{
-	struct dhd_prot *prot = dhd->prot;
-
-	DHD_TRACE(("%s\n", __FUNCTION__));
-
-	if (prot == NULL) {
-		return;
-	}
-
-	dhd_prot_flowrings_pool_reset(dhd);
-
-	dhd_prot_ring_reset(dhd, &prot->h2dring_ctrl_subn);
-	dhd_prot_ring_reset(dhd, &prot->h2dring_rxp_subn);
-	dhd_prot_ring_reset(dhd, &prot->d2hring_ctrl_cpln);
-	dhd_prot_ring_reset(dhd, &prot->d2hring_tx_cpln);
-	dhd_prot_ring_reset(dhd, &prot->d2hring_rx_cpln);
-
-	dhd_dma_buf_reset(dhd, &prot->retbuf);
-	dhd_dma_buf_reset(dhd, &prot->ioctbuf);
-	dhd_dma_buf_reset(dhd, &prot->d2h_dma_scratch_buf);
-	dhd_dma_buf_reset(dhd, &prot->h2d_dma_indx_rd_buf);
-	dhd_dma_buf_reset(dhd, &prot->h2d_dma_indx_wr_buf);
-	dhd_dma_buf_reset(dhd, &prot->d2h_dma_indx_rd_buf);
-	dhd_dma_buf_reset(dhd, &prot->d2h_dma_indx_wr_buf);
-
-
-	prot->rx_metadata_offset = 0;
-	prot->tx_metadata_offset = 0;
-
-	prot->rxbufpost = 0;
-	prot->cur_event_bufs_posted = 0;
-	prot->cur_ioctlresp_bufs_posted = 0;
-
-	prot->active_tx_count = 0;
-	prot->data_seq_no = 0;
-	prot->ioctl_seq_no = 0;
-	prot->ioctl_state = 0;
-	prot->curr_ioctl_cmd = 0;
-	prot->ioctl_received = IOCTL_WAIT;
-	prot->ioctl_trans_id = 0;
-
-	/* dhd_flow_rings_init is located at dhd_bus_start,
-	 * so when stopping bus, flowrings shall be deleted
-	 */
-	if (dhd->flow_rings_inited) {
-		dhd_flow_rings_deinit(dhd);
-	}
-
-	if (prot->pktid_map_handle) {
-		DHD_NATIVE_TO_PKTID_FINI(dhd, prot->pktid_map_handle);
-		prot->pktid_map_handle = NULL;
-	}
-
-#ifdef IOCTLRESP_USE_CONSTMEM
-	if (prot->pktid_map_handle_ioctl) {
-		DHD_NATIVE_TO_PKTID_FINI_IOCTL(dhd, prot->pktid_map_handle_ioctl);
-		prot->pktid_map_handle_ioctl = NULL;
-	}
-#endif /* IOCTLRESP_USE_CONSTMEM */
-} /* dhd_prot_reset */
-
-
-void
-dhd_prot_rx_dataoffset(dhd_pub_t *dhd, uint32 rx_offset)
-{
-	dhd_prot_t *prot = dhd->prot;
-	prot->rx_dataoffset = rx_offset;
-}
-
-/**
- * Initialize protocol: sync w/dongle state.
- * Sets dongle media info (iswl, drv_version, mac address).
- */
-int
-dhd_sync_with_dongle(dhd_pub_t *dhd)
-{
-	int ret = 0;
-	wlc_rev_info_t revinfo;
-
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT);
-
-
-
-#ifdef DHD_FW_COREDUMP
-	/* Check the memdump capability */
-	dhd_get_memdump_info(dhd);
-#endif /* DHD_FW_COREDUMP */
-#ifdef BCMASSERT_LOG
-	dhd_get_assert_info(dhd);
-#endif /* BCMASSERT_LOG */
-
-	/* Get the device rev info */
-	memset(&revinfo, 0, sizeof(revinfo));
-	ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0);
-	if (ret < 0) {
-		DHD_ERROR(("%s: GET revinfo FAILED\n", __FUNCTION__));
-		goto done;
-	}
-	DHD_ERROR(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__,
-		revinfo.deviceid, revinfo.vendorid, revinfo.chipnum));
-
-	dhd_process_cid_mac(dhd, TRUE);
-
-	ret = dhd_preinit_ioctls(dhd);
-
-	if (!ret) {
-		dhd_process_cid_mac(dhd, FALSE);
-	}
-
-	/* Always assumes wl for now */
-	dhd->iswl = TRUE;
-done:
-	return ret;
-} /* dhd_sync_with_dongle */
-
-#if defined(DHD_LB)
-
-/* DHD load balancing: deferral of work to another online CPU */
-
-/* DHD_LB_TXC DHD_LB_RXC DHD_LB_RXP dispatchers, in dhd_linux.c */
-extern void dhd_lb_tx_compl_dispatch(dhd_pub_t *dhdp);
-extern void dhd_lb_rx_compl_dispatch(dhd_pub_t *dhdp);
-extern void dhd_lb_rx_napi_dispatch(dhd_pub_t *dhdp);
-
-extern void dhd_lb_rx_pkt_enqueue(dhd_pub_t *dhdp, void *pkt, int ifidx);
-
-/**
- * dhd_lb_dispatch - load balance by dispatch work to other CPU cores
- * Note: rx_compl_tasklet is dispatched explicitly.
- */
-static INLINE void
-dhd_lb_dispatch(dhd_pub_t *dhdp, uint16 ring_idx)
-{
-	switch (ring_idx) {
-
-#if defined(DHD_LB_TXC)
-		case BCMPCIE_D2H_MSGRING_TX_COMPLETE:
-			bcm_workq_prod_sync(&dhdp->prot->tx_compl_prod); /* flush WR index */
-			dhd_lb_tx_compl_dispatch(dhdp); /* dispatch tx_compl_tasklet */
-			break;
-#endif /* DHD_LB_TXC */
-
-		case BCMPCIE_D2H_MSGRING_RX_COMPLETE:
-		{
-#if defined(DHD_LB_RXC)
-			dhd_prot_t *prot = dhdp->prot;
-			/* Schedule the takslet only if we have to */
-			if (prot->rxbufpost <= (prot->max_rxbufpost - RXBUFPOST_THRESHOLD)) {
-				/* flush WR index */
-				bcm_workq_prod_sync(&dhdp->prot->rx_compl_prod);
-				dhd_lb_rx_compl_dispatch(dhdp); /* dispatch rx_compl_tasklet */
-			}
-#endif /* DHD_LB_RXC */
-#if defined(DHD_LB_RXP)
-			dhd_lb_rx_napi_dispatch(dhdp); /* dispatch rx_process_napi */
-#endif /* DHD_LB_RXP */
-			break;
-		}
-		default:
-			break;
-	}
-}
-
-
-#if defined(DHD_LB_TXC)
-/**
- * DHD load balanced tx completion tasklet handler, that will perform the
- * freeing of packets on the selected CPU. Packet pointers are delivered to
- * this tasklet via the tx complete workq.
- */
-void
-dhd_lb_tx_compl_handler(unsigned long data)
-{
-	int elem_ix;
-	void *pkt, **elem;
-	dmaaddr_t pa;
-	uint32 pa_len;
-	dhd_pub_t *dhd = (dhd_pub_t *)data;
-	dhd_prot_t *prot = dhd->prot;
-	bcm_workq_t *workq = &prot->tx_compl_cons;
-	uint32 count = 0;
-
-	DHD_LB_STATS_TXC_PERCPU_CNT_INCR(dhd);
-
-	while (1) {
-		elem_ix = bcm_ring_cons(WORKQ_RING(workq), DHD_LB_WORKQ_SZ);
-
-		if (elem_ix == BCM_RING_EMPTY) {
-			break;
-		}
-
-		elem = WORKQ_ELEMENT(void *, workq, elem_ix);
-		pkt = *elem;
-
-		DHD_INFO(("%s: tx_compl_cons pkt<%p>\n", __FUNCTION__, pkt));
-
-		OSL_PREFETCH(PKTTAG(pkt));
-		OSL_PREFETCH(pkt);
-
-		pa = DHD_PKTTAG_PA((dhd_pkttag_fr_t *)PKTTAG(pkt));
-		pa_len = DHD_PKTTAG_PA_LEN((dhd_pkttag_fr_t *)PKTTAG(pkt));
-
-		DMA_UNMAP(dhd->osh, pa, pa_len, DMA_RX, 0, 0);
-
-#if defined(BCMPCIE)
-		dhd_txcomplete(dhd, pkt, true);
-#endif 
-
-		PKTFREE(dhd->osh, pkt, TRUE);
-		count++;
-	}
-
-	/* smp_wmb(); */
-	bcm_workq_cons_sync(workq);
-	DHD_LB_STATS_UPDATE_TXC_HISTO(dhd, count);
-}
-#endif /* DHD_LB_TXC */
-
-#if defined(DHD_LB_RXC)
-void
-dhd_lb_rx_compl_handler(unsigned long data)
-{
-	dhd_pub_t *dhd = (dhd_pub_t *)data;
-	bcm_workq_t *workq = &dhd->prot->rx_compl_cons;
-
-	DHD_LB_STATS_RXC_PERCPU_CNT_INCR(dhd);
-
-	dhd_msgbuf_rxbuf_post(dhd, TRUE); /* re-use pktids */
-	bcm_workq_cons_sync(workq);
-}
-#endif /* DHD_LB_RXC */
-
-#endif /* DHD_LB */
-
-#define DHD_DBG_SHOW_METADATA	0
-
-#if DHD_DBG_SHOW_METADATA
-static void BCMFASTPATH
-dhd_prot_print_metadata(dhd_pub_t *dhd, void *ptr, int len)
-{
-	uint8 tlv_t;
-	uint8 tlv_l;
-	uint8 *tlv_v = (uint8 *)ptr;
-
-	if (len <= BCMPCIE_D2H_METADATA_HDRLEN)
-		return;
-
-	len -= BCMPCIE_D2H_METADATA_HDRLEN;
-	tlv_v += BCMPCIE_D2H_METADATA_HDRLEN;
-
-	while (len > TLV_HDR_LEN) {
-		tlv_t = tlv_v[TLV_TAG_OFF];
-		tlv_l = tlv_v[TLV_LEN_OFF];
-
-		len -= TLV_HDR_LEN;
-		tlv_v += TLV_HDR_LEN;
-		if (len < tlv_l)
-			break;
-		if ((tlv_t == 0) || (tlv_t == WLFC_CTL_TYPE_FILLER))
-			break;
-
-		switch (tlv_t) {
-		case WLFC_CTL_TYPE_TXSTATUS: {
-			uint32 txs;
-			memcpy(&txs, tlv_v, sizeof(uint32));
-			if (tlv_l < (sizeof(wl_txstatus_additional_info_t) + sizeof(uint32))) {
-				printf("METADATA TX_STATUS: %08x\n", txs);
-			} else {
-				wl_txstatus_additional_info_t tx_add_info;
-				memcpy(&tx_add_info, tlv_v + sizeof(uint32),
-					sizeof(wl_txstatus_additional_info_t));
-				printf("METADATA TX_STATUS: %08x WLFCTS[%04x | %08x - %08x - %08x]"
-					" rate = %08x tries = %d - %d\n", txs,
-					tx_add_info.seq, tx_add_info.entry_ts,
-					tx_add_info.enq_ts, tx_add_info.last_ts,
-					tx_add_info.rspec, tx_add_info.rts_cnt,
-					tx_add_info.tx_cnt);
-			}
-			} break;
-
-		case WLFC_CTL_TYPE_RSSI: {
-			if (tlv_l == 1)
-				printf("METADATA RX_RSSI: rssi = %d\n", *tlv_v);
-			else
-				printf("METADATA RX_RSSI[%04x]: rssi = %d snr = %d\n",
-					(*(tlv_v + 3) << 8) | *(tlv_v + 2),
-					(int8)(*tlv_v), *(tlv_v + 1));
-			} break;
-
-		case WLFC_CTL_TYPE_FIFO_CREDITBACK:
-			bcm_print_bytes("METADATA FIFO_CREDITBACK", tlv_v, tlv_l);
-			break;
-
-		case WLFC_CTL_TYPE_TX_ENTRY_STAMP:
-			bcm_print_bytes("METADATA TX_ENTRY", tlv_v, tlv_l);
-			break;
-
-		case WLFC_CTL_TYPE_RX_STAMP: {
-			struct {
-				uint32 rspec;
-				uint32 bus_time;
-				uint32 wlan_time;
-			} rx_tmstamp;
-			memcpy(&rx_tmstamp, tlv_v, sizeof(rx_tmstamp));
-			printf("METADATA RX TIMESTMAP: WLFCTS[%08x - %08x] rate = %08x\n",
-				rx_tmstamp.wlan_time, rx_tmstamp.bus_time, rx_tmstamp.rspec);
-			} break;
-
-		case WLFC_CTL_TYPE_TRANS_ID:
-			bcm_print_bytes("METADATA TRANS_ID", tlv_v, tlv_l);
-			break;
-
-		case WLFC_CTL_TYPE_COMP_TXSTATUS:
-			bcm_print_bytes("METADATA COMP_TXSTATUS", tlv_v, tlv_l);
-			break;
-
-		default:
-			bcm_print_bytes("METADATA UNKNOWN", tlv_v, tlv_l);
-			break;
-		}
-
-		len -= tlv_l;
-		tlv_v += tlv_l;
-	}
-}
-#endif /* DHD_DBG_SHOW_METADATA */
-
-static INLINE void BCMFASTPATH
-dhd_prot_packet_free(dhd_pub_t *dhd, void *pkt, uint8 pkttype, bool send)
-{
-	if (pkt) {
-		if (pkttype == PKTTYPE_IOCTL_RX ||
-			pkttype == PKTTYPE_EVENT_RX) {
-#ifdef DHD_USE_STATIC_CTRLBUF
-			PKTFREE_STATIC(dhd->osh, pkt, send);
-#else
-			PKTFREE(dhd->osh, pkt, send);
-#endif /* DHD_USE_STATIC_CTRLBUF */
-		} else {
-			PKTFREE(dhd->osh, pkt, send);
-		}
-	}
-}
-
-static INLINE void * BCMFASTPATH
-dhd_prot_packet_get(dhd_pub_t *dhd, uint32 pktid, uint8 pkttype, bool free_pktid)
-{
-	void *PKTBUF;
-	dmaaddr_t pa;
-	uint32 len;
-	void *dmah;
-	void *secdma;
-
-#ifdef DHD_PCIE_PKTID
-	if (free_pktid) {
-		PKTBUF = DHD_PKTID_TO_NATIVE(dhd, dhd->prot->pktid_map_handle,
-			pktid, pa, len, dmah, secdma, pkttype);
-	} else {
-		PKTBUF = DHD_PKTID_TO_NATIVE_RSV(dhd, dhd->prot->pktid_map_handle,
-			pktid, pa, len, dmah, secdma, pkttype);
-	}
-#else
-	PKTBUF = DHD_PKTID_TO_NATIVE(dhd, dhd->prot->pktid_map_handle, pktid, pa,
-		len, dmah, secdma, pkttype);
-#endif /* DHD_PCIE_PKTID */
-
-	if (PKTBUF) {
-		{
-			if (SECURE_DMA_ENAB(dhd->osh)) {
-				SECURE_DMA_UNMAP(dhd->osh, pa, (uint) len, DMA_RX, 0, dmah,
-					secdma, 0);
-			} else {
-				DMA_UNMAP(dhd->osh, pa, (uint) len, DMA_RX, 0, dmah);
-			}
-		}
-	}
-
-	return PKTBUF;
-}
-
-#ifdef IOCTLRESP_USE_CONSTMEM
-static INLINE void BCMFASTPATH
-dhd_prot_ioctl_ret_buffer_get(dhd_pub_t *dhd, uint32 pktid, dhd_dma_buf_t *retbuf)
-{
-	memset(retbuf, 0, sizeof(dhd_dma_buf_t));
-	retbuf->va = DHD_PKTID_TO_NATIVE(dhd, dhd->prot->pktid_map_handle_ioctl, pktid,
-		retbuf->pa, retbuf->len, retbuf->dmah, retbuf->secdma, PKTTYPE_IOCTL_RX);
-
-	return;
-}
-#endif /* IOCTLRESP_USE_CONSTMEM */
-
-static void BCMFASTPATH
-dhd_msgbuf_rxbuf_post(dhd_pub_t *dhd, bool use_rsv_pktid)
-{
-	dhd_prot_t *prot = dhd->prot;
-	int16 fillbufs;
-	uint16 cnt = 256;
-	int retcount = 0;
-
-	fillbufs = prot->max_rxbufpost - prot->rxbufpost;
-	while (fillbufs >= RX_BUF_BURST) {
-		cnt--;
-		if (cnt == 0) {
-			/* find a better way to reschedule rx buf post if space not available */
-			DHD_ERROR(("h2d rx post ring not available to post host buffers \n"));
-			DHD_ERROR(("Current posted host buf count %d \n", prot->rxbufpost));
-			break;
-		}
-
-		/* Post in a burst of 32 buffers at a time */
-		fillbufs = MIN(fillbufs, RX_BUF_BURST);
-
-		/* Post buffers */
-		retcount = dhd_prot_rxbuf_post(dhd, fillbufs, use_rsv_pktid);
-
-		if (retcount >= 0) {
-			prot->rxbufpost += (uint16)retcount;
-#ifdef DHD_LB_RXC
-			/* dhd_prot_rxbuf_post returns the number of buffers posted */
-			DHD_LB_STATS_UPDATE_RXC_HISTO(dhd, retcount);
-#endif /* DHD_LB_RXC */
-			/* how many more to post */
-			fillbufs = prot->max_rxbufpost - prot->rxbufpost;
-		} else {
-			/* Make sure we don't run loop any further */
-			fillbufs = 0;
-		}
-	}
-}
-
-/** Post 'count' no of rx buffers to dongle */
-static int BCMFASTPATH
-dhd_prot_rxbuf_post(dhd_pub_t *dhd, uint16 count, bool use_rsv_pktid)
-{
-	void *p;
-	uint16 pktsz = DHD_FLOWRING_RX_BUFPOST_PKTSZ;
-	uint8 *rxbuf_post_tmp;
-	host_rxbuf_post_t *rxbuf_post;
-	void *msg_start;
-	dmaaddr_t pa;
-	uint32 pktlen;
-	uint8 i = 0;
-	uint16 alloced = 0;
-	unsigned long flags;
-	uint32 pktid;
-	dhd_prot_t *prot = dhd->prot;
-	msgbuf_ring_t *ring = &prot->h2dring_rxp_subn;
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	/* Claim space for exactly 'count' no of messages, for mitigation purpose */
-	msg_start = (void *)
-		dhd_prot_alloc_ring_space(dhd, ring, count, &alloced, TRUE);
-
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	if (msg_start == NULL) {
-		DHD_INFO(("%s:%d: Rxbufpost Msgbuf Not available\n", __FUNCTION__, __LINE__));
-		return -1;
-	}
-	/* if msg_start !=  NULL, we should have alloced space for atleast 1 item */
-	ASSERT(alloced > 0);
-
-	rxbuf_post_tmp = (uint8*)msg_start;
-
-	/* loop through each allocated message in the rxbuf post msgbuf_ring */
-	for (i = 0; i < alloced; i++) {
-		rxbuf_post = (host_rxbuf_post_t *)rxbuf_post_tmp;
-		/* Create a rx buffer */
-		if ((p = PKTGET(dhd->osh, pktsz, FALSE)) == NULL) {
-			DHD_ERROR(("%s:%d: PKTGET for rxbuf failed\n", __FUNCTION__, __LINE__));
-			dhd->rx_pktgetfail++;
-			break;
-		}
-
-		pktlen = PKTLEN(dhd->osh, p);
-		if (SECURE_DMA_ENAB(dhd->osh)) {
-			DHD_GENERAL_LOCK(dhd, flags);
-			pa = SECURE_DMA_MAP(dhd->osh, PKTDATA(dhd->osh, p), pktlen,
-				DMA_RX, p, 0, ring->dma_buf.secdma, 0);
-			DHD_GENERAL_UNLOCK(dhd, flags);
-		} else {
-			pa = DMA_MAP(dhd->osh, PKTDATA(dhd->osh, p), pktlen, DMA_RX, p, 0);
-		}
-
-		if (PHYSADDRISZERO(pa)) {
-			if (SECURE_DMA_ENAB(dhd->osh)) {
-				DHD_GENERAL_LOCK(dhd, flags);
-				SECURE_DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL,
-				    ring->dma_buf.secdma, 0);
-				DHD_GENERAL_UNLOCK(dhd, flags);
-			} else {
-				DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL);
-			}
-
-			PKTFREE(dhd->osh, p, FALSE);
-			DHD_ERROR(("Invalid phyaddr 0\n"));
-			ASSERT(0);
-			break;
-		}
-
-		PKTPULL(dhd->osh, p, prot->rx_metadata_offset);
-		pktlen = PKTLEN(dhd->osh, p);
-
-		/* Common msg header */
-		rxbuf_post->cmn_hdr.msg_type = MSG_TYPE_RXBUF_POST;
-		rxbuf_post->cmn_hdr.if_id = 0;
-		rxbuf_post->cmn_hdr.epoch = ring->seqnum % H2D_EPOCH_MODULO;
-		ring->seqnum++;
-
-#if defined(DHD_LB_RXC)
-		if (use_rsv_pktid == TRUE) {
-			bcm_workq_t *workq = &prot->rx_compl_cons;
-			int elem_ix = bcm_ring_cons(WORKQ_RING(workq), DHD_LB_WORKQ_SZ);
-			if (elem_ix == BCM_RING_EMPTY) {
-				DHD_ERROR(("%s rx_compl_cons ring is empty\n", __FUNCTION__));
-				pktid = DHD_PKTID_INVALID;
-				goto alloc_pkt_id;
-			} else {
-				uint32 *elem = WORKQ_ELEMENT(uint32, workq, elem_ix);
-				pktid = *elem;
-			}
-
-			/* Now populate the previous locker with valid information */
-			if (pktid != DHD_PKTID_INVALID) {
-				rxbuf_post->cmn_hdr.request_id = htol32(pktid);
-				DHD_NATIVE_TO_PKTID_SAVE(dhd, dhd->prot->pktid_map_handle, p, pktid,
-					pa, pktlen, DMA_RX, NULL, ring->dma_buf.secdma,
-					PKTTYPE_DATA_RX);
-			}
-		} else
-#endif /* DHD_LB_RXC */
-		{
-#if defined(DHD_LB_RXC)
-alloc_pkt_id:
-#endif
-#if defined(DHD_PCIE_PKTID)
-		/* get the lock before calling DHD_NATIVE_TO_PKTID */
-		DHD_GENERAL_LOCK(dhd, flags);
-#endif
-		pktid = DHD_NATIVE_TO_PKTID(dhd, dhd->prot->pktid_map_handle, p, pa,
-			pktlen, DMA_RX, NULL, ring->dma_buf.secdma, PKTTYPE_DATA_RX);
-
-#if defined(DHD_PCIE_PKTID)
-		/* free lock */
-		DHD_GENERAL_UNLOCK(dhd, flags);
-
-		if (pktid == DHD_PKTID_INVALID) {
-
-			if (SECURE_DMA_ENAB(dhd->osh)) {
-				DHD_GENERAL_LOCK(dhd, flags);
-				SECURE_DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL,
-				    ring->dma_buf.secdma, 0);
-				DHD_GENERAL_UNLOCK(dhd, flags);
-			} else {
-				DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL);
-			}
-
-			PKTFREE(dhd->osh, p, FALSE);
-			DHD_ERROR(("Pktid pool depleted.\n"));
-			break;
-		}
-#endif /* DHD_PCIE_PKTID */
-		}
-
-		rxbuf_post->data_buf_len = htol16((uint16)pktlen);
-		rxbuf_post->data_buf_addr.high_addr = htol32(PHYSADDRHI(pa));
-		rxbuf_post->data_buf_addr.low_addr =
-			htol32(PHYSADDRLO(pa) + prot->rx_metadata_offset);
-
-		if (prot->rx_metadata_offset) {
-			rxbuf_post->metadata_buf_len = prot->rx_metadata_offset;
-			rxbuf_post->metadata_buf_addr.high_addr = htol32(PHYSADDRHI(pa));
-			rxbuf_post->metadata_buf_addr.low_addr  = htol32(PHYSADDRLO(pa));
-		} else {
-			rxbuf_post->metadata_buf_len = 0;
-			rxbuf_post->metadata_buf_addr.high_addr = 0;
-			rxbuf_post->metadata_buf_addr.low_addr  = 0;
-		}
-
-#if defined(DHD_PKTID_AUDIT_RING)
-		DHD_PKTID_AUDIT(dhd, prot->pktid_map_handle, pktid, DHD_DUPLICATE_ALLOC);
-#endif /* DHD_PKTID_AUDIT_RING */
-
-		rxbuf_post->cmn_hdr.request_id = htol32(pktid);
-
-		/* Move rxbuf_post_tmp to next item */
-		rxbuf_post_tmp = rxbuf_post_tmp + ring->item_len;
-	}
-
-	if (i < alloced) {
-		if (ring->wr < (alloced - i)) {
-			ring->wr = ring->max_items - (alloced - i);
-		} else {
-			ring->wr -= (alloced - i);
-		}
-
-		alloced = i;
-	}
-
-	/* Update ring's WR index and ring doorbell to dongle */
-	if (alloced > 0) {
-		dhd_prot_ring_write_complete(dhd, ring, msg_start, alloced);
-	}
-
-	return alloced;
-} /* dhd_prot_rxbuf_post */
-
-#ifdef IOCTLRESP_USE_CONSTMEM
-static int
-alloc_ioctl_return_buffer(dhd_pub_t *dhd, dhd_dma_buf_t *retbuf)
-{
-	int err;
-	memset(retbuf, 0, sizeof(dhd_dma_buf_t));
-
-	if ((err = dhd_dma_buf_alloc(dhd, retbuf, IOCT_RETBUF_SIZE)) != BCME_OK) {
-		DHD_ERROR(("%s: dhd_dma_buf_alloc err %d\n", __FUNCTION__, err));
-		ASSERT(0);
-		return BCME_NOMEM;
-	}
-
-	return BCME_OK;
-}
-
-static void
-free_ioctl_return_buffer(dhd_pub_t *dhd, dhd_dma_buf_t *retbuf)
-{
-	/* retbuf (declared on stack) not fully populated ...  */
-	if (retbuf->va) {
-		uint32 dma_pad;
-		dma_pad = (IOCT_RETBUF_SIZE % DHD_DMA_PAD) ? DHD_DMA_PAD : 0;
-		retbuf->len = IOCT_RETBUF_SIZE;
-		retbuf->_alloced = retbuf->len + dma_pad;
-		/* JIRA:SWWLAN-70021 The pa value would be overwritten by the dongle.
-		 * Need to reassign before free to pass the check in dhd_dma_buf_audit().
-		 */
-		retbuf->pa = DMA_MAP(dhd->osh, retbuf->va, retbuf->len, DMA_RX, NULL, NULL);
-	}
-
-	dhd_dma_buf_free(dhd, retbuf);
-	return;
-}
-#endif /* IOCTLRESP_USE_CONSTMEM */
-
-static int
-dhd_prot_rxbufpost_ctrl(dhd_pub_t *dhd, bool event_buf)
-{
-	void *p;
-	uint16 pktsz;
-	ioctl_resp_evt_buf_post_msg_t *rxbuf_post;
-	dmaaddr_t pa;
-	uint32 pktlen;
-	dhd_prot_t *prot = dhd->prot;
-	uint16 alloced = 0;
-	unsigned long flags;
-	dhd_dma_buf_t retbuf;
-	void *dmah = NULL;
-	uint32 pktid;
-	void *map_handle;
-	msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn;
-
-	if (dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s: bus is already down.\n", __FUNCTION__));
-		return -1;
-	}
-
-	memset(&retbuf, 0, sizeof(dhd_dma_buf_t));
-
-	if (event_buf) {
-		/* Allocate packet for event buffer post */
-		pktsz = DHD_FLOWRING_RX_BUFPOST_PKTSZ;
-	} else {
-		/* Allocate packet for ctrl/ioctl buffer post */
-		pktsz = DHD_FLOWRING_IOCTL_BUFPOST_PKTSZ;
-	}
-
-#ifdef IOCTLRESP_USE_CONSTMEM
-	if (!event_buf) {
-		if (alloc_ioctl_return_buffer(dhd, &retbuf) != BCME_OK) {
-			DHD_ERROR(("Could not allocate IOCTL response buffer\n"));
-			return -1;
-		}
-		ASSERT(retbuf.len == IOCT_RETBUF_SIZE);
-		p = retbuf.va;
-		pktlen = retbuf.len;
-		pa = retbuf.pa;
-		dmah = retbuf.dmah;
-	} else
-#endif /* IOCTLRESP_USE_CONSTMEM */
-	{
-#ifdef DHD_USE_STATIC_CTRLBUF
-		p = PKTGET_STATIC(dhd->osh, pktsz, FALSE);
-#else
-		p = PKTGET(dhd->osh, pktsz, FALSE);
-#endif /* DHD_USE_STATIC_CTRLBUF */
-		if (p == NULL) {
-			DHD_ERROR(("%s:%d: PKTGET for %s buf failed\n",
-				__FUNCTION__, __LINE__, event_buf ?
-				"EVENT" : "IOCTL RESP"));
-			dhd->rx_pktgetfail++;
-			return -1;
-		}
-
-		pktlen = PKTLEN(dhd->osh, p);
-
-		if (SECURE_DMA_ENAB(dhd->osh)) {
-			DHD_GENERAL_LOCK(dhd, flags);
-			pa = SECURE_DMA_MAP(dhd->osh, PKTDATA(dhd->osh, p), pktlen,
-				DMA_RX, p, 0, ring->dma_buf.secdma, 0);
-			DHD_GENERAL_UNLOCK(dhd, flags);
-		} else {
-			pa = DMA_MAP(dhd->osh, PKTDATA(dhd->osh, p), pktlen, DMA_RX, p, 0);
-		}
-
-		if (PHYSADDRISZERO(pa)) {
-			DHD_ERROR(("Invalid physaddr 0\n"));
-			ASSERT(0);
-			goto free_pkt_return;
-		}
-	}
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	rxbuf_post = (ioctl_resp_evt_buf_post_msg_t *)
-		dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE);
-
-	if (rxbuf_post == NULL) {
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		DHD_ERROR(("%s:%d: Ctrl submit Msgbuf Not available to post buffer \n",
-			__FUNCTION__, __LINE__));
-
-#ifdef IOCTLRESP_USE_CONSTMEM
-		if (event_buf)
-#endif /* IOCTLRESP_USE_CONSTMEM */
-		{
-			if (SECURE_DMA_ENAB(dhd->osh)) {
-				DHD_GENERAL_LOCK(dhd, flags);
-				SECURE_DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL,
-					ring->dma_buf.secdma, 0);
-				DHD_GENERAL_UNLOCK(dhd, flags);
-			} else {
-				DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL);
-			}
-		}
-		goto free_pkt_return;
-	}
-
-	/* CMN msg header */
-	if (event_buf) {
-		rxbuf_post->cmn_hdr.msg_type = MSG_TYPE_EVENT_BUF_POST;
-	} else {
-		rxbuf_post->cmn_hdr.msg_type = MSG_TYPE_IOCTLRESP_BUF_POST;
-	}
-
-#ifdef IOCTLRESP_USE_CONSTMEM
-	if (!event_buf) {
-		map_handle = dhd->prot->pktid_map_handle_ioctl;
-		pktid =	DHD_NATIVE_TO_PKTID(dhd, map_handle, p, pa, pktlen,
-			DMA_RX, dmah, ring->dma_buf.secdma, PKTTYPE_IOCTL_RX);
-	} else
-#endif /* IOCTLRESP_USE_CONSTMEM */
-	{
-		map_handle = dhd->prot->pktid_map_handle;
-		pktid =	DHD_NATIVE_TO_PKTID(dhd, map_handle,
-			p, pa, pktlen, DMA_RX, dmah, ring->dma_buf.secdma,
-			event_buf ? PKTTYPE_EVENT_RX : PKTTYPE_IOCTL_RX);
-	}
-
-	if (pktid == DHD_PKTID_INVALID) {
-		if (ring->wr == 0) {
-			ring->wr = ring->max_items - 1;
-		} else {
-			ring->wr--;
-		}
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL);
-		goto free_pkt_return;
-	}
-
-#if defined(DHD_PKTID_AUDIT_RING)
-	DHD_PKTID_AUDIT(dhd, map_handle, pktid, DHD_DUPLICATE_ALLOC);
-#endif /* DHD_PKTID_AUDIT_RING */
-
-	rxbuf_post->cmn_hdr.request_id = htol32(pktid);
-	rxbuf_post->cmn_hdr.if_id = 0;
-	rxbuf_post->cmn_hdr.epoch = ring->seqnum % H2D_EPOCH_MODULO;
-	ring->seqnum++;
-
-#if defined(DHD_PCIE_PKTID)
-	if (rxbuf_post->cmn_hdr.request_id == DHD_PKTID_INVALID) {
-		if (ring->wr == 0) {
-			ring->wr = ring->max_items - 1;
-		} else {
-			ring->wr--;
-		}
-		DHD_GENERAL_UNLOCK(dhd, flags);
-#ifdef IOCTLRESP_USE_CONSTMEM
-		if (event_buf)
-#endif /* IOCTLRESP_USE_CONSTMEM */
-		{
-			if (SECURE_DMA_ENAB(dhd->osh)) {
-				DHD_GENERAL_LOCK(dhd, flags);
-				SECURE_DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL,
-					ring->dma_buf.secdma, 0);
-				DHD_GENERAL_UNLOCK(dhd, flags);
-			} else {
-				DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL);
-			}
-		}
-		goto free_pkt_return;
-	}
-#endif /* DHD_PCIE_PKTID */
-
-	rxbuf_post->cmn_hdr.flags = 0;
-#ifndef IOCTLRESP_USE_CONSTMEM
-	rxbuf_post->host_buf_len = htol16((uint16)PKTLEN(dhd->osh, p));
-#else
-	rxbuf_post->host_buf_len = htol16((uint16)pktlen);
-#endif /* IOCTLRESP_USE_CONSTMEM */
-	rxbuf_post->host_buf_addr.high_addr = htol32(PHYSADDRHI(pa));
-	rxbuf_post->host_buf_addr.low_addr  = htol32(PHYSADDRLO(pa));
-
-	/* update ring's WR index and ring doorbell to dongle */
-	dhd_prot_ring_write_complete(dhd, ring, rxbuf_post, 1);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return 1;
-
-free_pkt_return:
-#ifdef IOCTLRESP_USE_CONSTMEM
-	if (!event_buf) {
-		free_ioctl_return_buffer(dhd, &retbuf);
-	} else
-#endif /* IOCTLRESP_USE_CONSTMEM */
-	{
-		dhd_prot_packet_free(dhd, p,
-			event_buf ? PKTTYPE_EVENT_RX : PKTTYPE_IOCTL_RX,
-			FALSE);
-	}
-
-	return -1;
-} /* dhd_prot_rxbufpost_ctrl */
-
-static uint16
-dhd_msgbuf_rxbuf_post_ctrlpath(dhd_pub_t *dhd, bool event_buf, uint32 max_to_post)
-{
-	uint32 i = 0;
-	int32 ret_val;
-
-	DHD_INFO(("max to post %d, event %d \n", max_to_post, event_buf));
-
-	if (dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s: bus is already down.\n", __FUNCTION__));
-		return 0;
-	}
-
-	while (i < max_to_post) {
-		ret_val  = dhd_prot_rxbufpost_ctrl(dhd, event_buf);
-		if (ret_val < 0) {
-			break;
-		}
-		i++;
-	}
-	DHD_INFO(("posted %d buffers to event_pool/ioctl_resp_pool %d\n", i, event_buf));
-	return (uint16)i;
-}
-
-static void
-dhd_msgbuf_rxbuf_post_ioctlresp_bufs(dhd_pub_t *dhd)
-{
-	dhd_prot_t *prot = dhd->prot;
-	int max_to_post;
-
-	DHD_INFO(("ioctl resp buf post\n"));
-	max_to_post = prot->max_ioctlrespbufpost - prot->cur_ioctlresp_bufs_posted;
-	if (max_to_post <= 0) {
-		DHD_INFO(("%s: Cannot post more than max IOCTL resp buffers\n",
-			__FUNCTION__));
-		return;
-	}
-	prot->cur_ioctlresp_bufs_posted += dhd_msgbuf_rxbuf_post_ctrlpath(dhd,
-		FALSE, max_to_post);
-}
-
-static void
-dhd_msgbuf_rxbuf_post_event_bufs(dhd_pub_t *dhd)
-{
-	dhd_prot_t *prot = dhd->prot;
-	int max_to_post;
-
-	max_to_post = prot->max_eventbufpost - prot->cur_event_bufs_posted;
-	if (max_to_post <= 0) {
-		DHD_INFO(("%s: Cannot post more than max event buffers\n",
-			__FUNCTION__));
-		return;
-	}
-	prot->cur_event_bufs_posted += dhd_msgbuf_rxbuf_post_ctrlpath(dhd,
-		TRUE, max_to_post);
-}
-
-/** called when DHD needs to check for 'receive complete' messages from the dongle */
-bool BCMFASTPATH
-dhd_prot_process_msgbuf_rxcpl(dhd_pub_t *dhd, uint bound)
-{
-	bool more = TRUE;
-	uint n = 0;
-	msgbuf_ring_t *ring = &dhd->prot->d2hring_rx_cpln;
-
-	/* Process all the messages - DTOH direction */
-	while (!dhd_is_device_removed(dhd)) {
-		uint8 *msg_addr;
-		uint32 msg_len;
-
-		if (dhd->hang_was_sent) {
-			more = FALSE;
-			break;
-		}
-
-		/* Get the address of the next message to be read from ring */
-		msg_addr = dhd_prot_get_read_addr(dhd, ring, &msg_len);
-		if (msg_addr == NULL) {
-			more = FALSE;
-			break;
-		}
-
-		/* Prefetch data to populate the cache */
-		OSL_PREFETCH(msg_addr);
-
-		if (dhd_prot_process_msgtype(dhd, ring, msg_addr, msg_len) != BCME_OK) {
-			DHD_ERROR(("%s: process %s msg addr %p len %d\n",
-				__FUNCTION__, ring->name, msg_addr, msg_len));
-		}
-
-		/* Update read pointer */
-		dhd_prot_upd_read_idx(dhd, ring);
-
-		/* After batch processing, check RX bound */
-		n += msg_len / ring->item_len;
-		if (n >= bound) {
-			break;
-		}
-	}
-
-	return more;
-}
-
-/**
- * Hands transmit packets (with a caller provided flow_id) over to dongle territory (the flow ring)
- */
-void
-dhd_prot_update_txflowring(dhd_pub_t *dhd, uint16 flowid, void *msgring)
-{
-	msgbuf_ring_t *ring = (msgbuf_ring_t *)msgring;
-
-	/* Update read pointer */
-	if (DMA_INDX_ENAB(dhd->dma_d2h_ring_upd_support)) {
-		ring->rd = dhd_prot_dma_indx_get(dhd, H2D_DMA_INDX_RD_UPD, ring->idx);
-	}
-
-	DHD_TRACE(("ringid %d flowid %d write %d read %d \n\n",
-		ring->idx, flowid, ring->wr, ring->rd));
-
-	/* Need more logic here, but for now use it directly */
-	dhd_bus_schedule_queue(dhd->bus, flowid, TRUE); /* from queue to flowring */
-}
-
-/** called when DHD needs to check for 'transmit complete' messages from the dongle */
-bool BCMFASTPATH
-dhd_prot_process_msgbuf_txcpl(dhd_pub_t *dhd, uint bound)
-{
-	bool more = TRUE;
-	uint n = 0;
-	msgbuf_ring_t *ring = &dhd->prot->d2hring_tx_cpln;
-
-	/* Process all the messages - DTOH direction */
-	while (!dhd_is_device_removed(dhd)) {
-		uint8 *msg_addr;
-		uint32 msg_len;
-
-		if (dhd->hang_was_sent) {
-			more = FALSE;
-			break;
-		}
-
-		/* Get the address of the next message to be read from ring */
-		msg_addr = dhd_prot_get_read_addr(dhd, ring, &msg_len);
-		if (msg_addr == NULL) {
-			more = FALSE;
-			break;
-		}
-
-		/* Prefetch data to populate the cache */
-		OSL_PREFETCH(msg_addr);
-
-		if (dhd_prot_process_msgtype(dhd, ring, msg_addr, msg_len) != BCME_OK) {
-			DHD_ERROR(("%s: process %s msg addr %p len %d\n",
-				__FUNCTION__, ring->name, msg_addr, msg_len));
-		}
-
-		/* Write to dngl rd ptr */
-		dhd_prot_upd_read_idx(dhd, ring);
-
-		/* After batch processing, check bound */
-		n += msg_len / ring->item_len;
-		if (n >= bound) {
-			break;
-		}
-	}
-
-	return more;
-}
-
-/** called when DHD needs to check for 'ioctl complete' messages from the dongle */
-int BCMFASTPATH
-dhd_prot_process_ctrlbuf(dhd_pub_t *dhd)
-{
-	dhd_prot_t *prot = dhd->prot;
-	msgbuf_ring_t *ring = &prot->d2hring_ctrl_cpln;
-
-	/* Process all the messages - DTOH direction */
-	while (!dhd_is_device_removed(dhd)) {
-		uint8 *msg_addr;
-		uint32 msg_len;
-
-		if (dhd->hang_was_sent) {
-			break;
-		}
-
-		/* Get the address of the next message to be read from ring */
-		msg_addr = dhd_prot_get_read_addr(dhd, ring, &msg_len);
-		if (msg_addr == NULL) {
-			break;
-		}
-
-		/* Prefetch data to populate the cache */
-		OSL_PREFETCH(msg_addr);
-
-		if (dhd_prot_process_msgtype(dhd, ring, msg_addr, msg_len) != BCME_OK) {
-			DHD_ERROR(("%s: process %s msg addr %p len %d\n",
-				__FUNCTION__, ring->name, msg_addr, msg_len));
-		}
-
-		/* Write to dngl rd ptr */
-		dhd_prot_upd_read_idx(dhd, ring);
-	}
-
-	return 0;
-}
-
-/**
- * Consume messages out of the D2H ring. Ensure that the message's DMA to host
- * memory has completed, before invoking the message handler via a table lookup
- * of the cmn_msg_hdr::msg_type.
- */
-static int BCMFASTPATH
-dhd_prot_process_msgtype(dhd_pub_t *dhd, msgbuf_ring_t *ring, uint8 *buf, uint32 len)
-{
-	int buf_len = len;
-	uint16 item_len;
-	uint8 msg_type;
-	cmn_msg_hdr_t *msg = NULL;
-	int ret = BCME_OK;
-
-	ASSERT(ring);
-	item_len = ring->item_len;
-	if (item_len == 0) {
-		DHD_ERROR(("%s: ringidx %d item_len %d buf_len %d\n",
-			__FUNCTION__, ring->idx, item_len, buf_len));
-		return BCME_ERROR;
-	}
-
-	while (buf_len > 0) {
-		if (dhd->hang_was_sent) {
-			ret = BCME_ERROR;
-			goto done;
-		}
-
-		msg = (cmn_msg_hdr_t *)buf;
-
-		/*
-		 * Update the curr_rd to the current index in the ring, from where
-		 * the work item is fetched. This way if the fetched work item
-		 * fails in LIVELOCK, we can print the exact read index in the ring
-		 * that shows up the corrupted work item.
-		 */
-		if ((ring->curr_rd + 1) >= ring->max_items) {
-			ring->curr_rd = 0;
-		} else {
-			ring->curr_rd += 1;
-		}
-
-#if defined(PCIE_D2H_SYNC)
-		/* Wait until DMA completes, then fetch msg_type */
-		msg_type = dhd->prot->d2h_sync_cb(dhd, ring, msg, item_len);
-#else
-		msg_type = msg->msg_type;
-#endif /* !PCIE_D2H_SYNC */
-
-		/* Prefetch data to populate the cache */
-		OSL_PREFETCH(buf + item_len);
-
-		DHD_INFO(("msg_type %d item_len %d buf_len %d\n",
-			msg_type, item_len, buf_len));
-
-		if (msg_type == MSG_TYPE_LOOPBACK) {
-			bcm_print_bytes("LPBK RESP: ", (uint8 *)msg, item_len);
-			DHD_ERROR((" MSG_TYPE_LOOPBACK, len %d\n", item_len));
-		}
-
-		ASSERT(msg_type < DHD_PROT_FUNCS);
-		if (msg_type >= DHD_PROT_FUNCS) {
-			DHD_ERROR(("%s: msg_type %d item_len %d buf_len %d\n",
-				__FUNCTION__, msg_type, item_len, buf_len));
-			ret = BCME_ERROR;
-			goto done;
-		}
-
-		if (table_lookup[msg_type]) {
-			table_lookup[msg_type](dhd, buf);
-		}
-
-		if (buf_len < item_len) {
-			ret = BCME_ERROR;
-			goto done;
-		}
-		buf_len = buf_len - item_len;
-		buf = buf + item_len;
-	}
-
-done:
-
-#ifdef DHD_RX_CHAINING
-	dhd_rxchain_commit(dhd);
-#endif
-#if defined(DHD_LB)
-	dhd_lb_dispatch(dhd, ring->idx);
-#endif
-	return ret;
-} /* dhd_prot_process_msgtype */
-
-static void
-dhd_prot_noop(dhd_pub_t *dhd, void *msg)
-{
-	return;
-}
-
-/** called on MSG_TYPE_RING_STATUS message received from dongle */
-static void
-dhd_prot_ringstatus_process(dhd_pub_t *dhd, void *msg)
-{
-	pcie_ring_status_t *ring_status = (pcie_ring_status_t *)msg;
-	DHD_ERROR(("ring status: request_id %d, status 0x%04x, flow ring %d, write_idx %d \n",
-		ring_status->cmn_hdr.request_id, ring_status->compl_hdr.status,
-		ring_status->compl_hdr.flow_ring_id, ring_status->write_idx));
-	/* How do we track this to pair it with ??? */
-	return;
-}
-
-/** called on MSG_TYPE_GEN_STATUS ('general status') message received from dongle */
-static void
-dhd_prot_genstatus_process(dhd_pub_t *dhd, void *msg)
-{
-	pcie_gen_status_t *gen_status = (pcie_gen_status_t *)msg;
-	DHD_ERROR(("ERROR: gen status: request_id %d, STATUS 0x%04x, flow ring %d \n",
-		gen_status->cmn_hdr.request_id, gen_status->compl_hdr.status,
-		gen_status->compl_hdr.flow_ring_id));
-
-	/* How do we track this to pair it with ??? */
-	return;
-}
-
-/**
- * Called on MSG_TYPE_IOCTLPTR_REQ_ACK ('ioctl ack') message received from dongle, meaning that the
- * dongle received the ioctl message in dongle memory.
- */
-static void
-dhd_prot_ioctack_process(dhd_pub_t *dhd, void *msg)
-{
-	uint32 pktid;
-	ioctl_req_ack_msg_t *ioct_ack = (ioctl_req_ack_msg_t *)msg;
-	unsigned long flags;
-
-	pktid = ltoh32(ioct_ack->cmn_hdr.request_id);
-
-#if defined(DHD_PKTID_AUDIT_RING)
-	/* Skip DHD_IOCTL_REQ_PKTID = 0xFFFE */
-	if (pktid != DHD_IOCTL_REQ_PKTID) {
-		if (DHD_PKTID_AUDIT(dhd, dhd->prot->pktid_map_handle, pktid,
-			DHD_TEST_IS_ALLOC) == BCME_ERROR) {
-			prhex("dhd_prot_ioctack_process:",
-				(uchar *)msg, D2HRING_CTRL_CMPLT_ITEMSIZE);
-		}
-	}
-#endif /* DHD_PKTID_AUDIT_RING */
-
-	DHD_GENERAL_LOCK(dhd, flags);
-	if ((dhd->prot->ioctl_state & MSGBUF_IOCTL_ACK_PENDING) &&
-		(dhd->prot->ioctl_state & MSGBUF_IOCTL_RESP_PENDING)) {
-		dhd->prot->ioctl_state &= ~MSGBUF_IOCTL_ACK_PENDING;
-	} else {
-		DHD_ERROR(("%s: received ioctl ACK with state %02x trans_id = %d\n",
-			__FUNCTION__, dhd->prot->ioctl_state, dhd->prot->ioctl_trans_id));
-		prhex("dhd_prot_ioctack_process:",
-			(uchar *)msg, D2HRING_CTRL_CMPLT_ITEMSIZE);
-	}
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	DHD_CTL(("ioctl req ack: request_id %d, status 0x%04x, flow ring %d \n",
-		ioct_ack->cmn_hdr.request_id, ioct_ack->compl_hdr.status,
-		ioct_ack->compl_hdr.flow_ring_id));
-	if (ioct_ack->compl_hdr.status != 0)  {
-		DHD_ERROR(("got an error status for the ioctl request...need to handle that\n"));
-	}
-}
-
-/** called on MSG_TYPE_IOCTL_CMPLT message received from dongle */
-static void
-dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg)
-{
-	dhd_prot_t *prot = dhd->prot;
-	uint32 pkt_id, xt_id;
-	ioctl_comp_resp_msg_t *ioct_resp = (ioctl_comp_resp_msg_t *)msg;
-	void *pkt;
-	unsigned long flags;
-	dhd_dma_buf_t retbuf;
-
-	memset(&retbuf, 0, sizeof(dhd_dma_buf_t));
-
-	pkt_id = ltoh32(ioct_resp->cmn_hdr.request_id);
-
-#if defined(DHD_PKTID_AUDIT_RING)
-	{
-		int ret;
-#ifndef IOCTLRESP_USE_CONSTMEM
-		ret = DHD_PKTID_AUDIT(dhd, prot->pktid_map_handle, pkt_id,
-			DHD_DUPLICATE_FREE);
-#else
-		ret = DHD_PKTID_AUDIT(dhd, prot->pktid_map_handle_ioctl, pkt_id,
-			DHD_DUPLICATE_FREE);
-#endif /* !IOCTLRESP_USE_CONSTMEM */
-		if (ret == BCME_ERROR) {
-			prhex("dhd_prot_ioctcmplt_process:",
-				(uchar *)msg, D2HRING_CTRL_CMPLT_ITEMSIZE);
-		}
-	}
-#endif /* DHD_PKTID_AUDIT_RING */
-
-	DHD_GENERAL_LOCK(dhd, flags);
-	if ((prot->ioctl_state & MSGBUF_IOCTL_ACK_PENDING) ||
-		!(prot->ioctl_state & MSGBUF_IOCTL_RESP_PENDING)) {
-		DHD_ERROR(("%s: received ioctl response with state %02x trans_id = %d\n",
-			__FUNCTION__, dhd->prot->ioctl_state, dhd->prot->ioctl_trans_id));
-		prhex("dhd_prot_ioctcmplt_process:",
-				(uchar *)msg, D2HRING_CTRL_CMPLT_ITEMSIZE);
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return;
-	}
-#ifndef IOCTLRESP_USE_CONSTMEM
-	pkt = dhd_prot_packet_get(dhd, pkt_id, PKTTYPE_IOCTL_RX, TRUE);
-#else
-	dhd_prot_ioctl_ret_buffer_get(dhd, pkt_id, &retbuf);
-	pkt = retbuf.va;
-#endif /* !IOCTLRESP_USE_CONSTMEM */
-	if (!pkt) {
-		prot->ioctl_state = 0;
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		DHD_ERROR(("%s: received ioctl response with NULL pkt\n", __FUNCTION__));
-		return;
-	}
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	prot->ioctl_resplen = ltoh16(ioct_resp->resp_len);
-	prot->ioctl_status = ltoh16(ioct_resp->compl_hdr.status);
-	xt_id = ltoh16(ioct_resp->trans_id);
-	if (xt_id != prot->ioctl_trans_id) {
-		ASSERT(0);
-		goto exit;
-	}
-
-	DHD_CTL(("IOCTL_COMPLETE: req_id %x transid %d status %x resplen %d\n",
-		pkt_id, xt_id, prot->ioctl_status, prot->ioctl_resplen));
-
-	if (prot->ioctl_resplen > 0) {
-#ifndef IOCTLRESP_USE_CONSTMEM
-		bcopy(PKTDATA(dhd->osh, pkt), prot->retbuf.va, prot->ioctl_resplen);
-#else
-		bcopy(pkt, prot->retbuf.va, prot->ioctl_resplen);
-#endif /* !IOCTLRESP_USE_CONSTMEM */
-	}
-
-	/* wake up any dhd_os_ioctl_resp_wait() */
-	dhd_wakeup_ioctl_event(dhd, IOCTL_RETURN_ON_SUCCESS);
-
-exit:
-#ifndef IOCTLRESP_USE_CONSTMEM
-	dhd_prot_packet_free(dhd, pkt,
-		PKTTYPE_IOCTL_RX, FALSE);
-#else
-	free_ioctl_return_buffer(dhd, &retbuf);
-#endif /* !IOCTLRESP_USE_CONSTMEM */
-}
-
-/** called on MSG_TYPE_TX_STATUS message received from dongle */
-static void BCMFASTPATH
-dhd_prot_txstatus_process(dhd_pub_t *dhd, void *msg)
-{
-	dhd_prot_t *prot = dhd->prot;
-	host_txbuf_cmpl_t * txstatus;
-	unsigned long flags;
-	uint32 pktid;
-	void *pkt = NULL;
-	dmaaddr_t pa;
-	uint32 len;
-	void *dmah;
-	void *secdma;
-
-	/* locks required to protect circular buffer accesses */
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	txstatus = (host_txbuf_cmpl_t *)msg;
-	pktid = ltoh32(txstatus->cmn_hdr.request_id);
-
-#if defined(DHD_PKTID_AUDIT_RING)
-	if (DHD_PKTID_AUDIT(dhd, dhd->prot->pktid_map_handle, pktid,
-		DHD_DUPLICATE_FREE) == BCME_ERROR) {
-			prhex("dhd_prot_txstatus_process:",
-				(uchar *)msg, D2HRING_TXCMPLT_ITEMSIZE);
-	}
-#endif /* DHD_PKTID_AUDIT_RING */
-
-	DHD_INFO(("txstatus for pktid 0x%04x\n", pktid));
-	if (prot->active_tx_count) {
-		prot->active_tx_count--;
-
-		/* Release the Lock when no more tx packets are pending */
-		if (prot->active_tx_count == 0)
-			 DHD_OS_WAKE_UNLOCK(dhd);
-
-	} else {
-		DHD_ERROR(("Extra packets are freed\n"));
-	}
-
-	ASSERT(pktid != 0);
-
-#if defined(DHD_LB_TXC) && !defined(BCM_SECURE_DMA)
-	{
-		int elem_ix;
-		void **elem;
-		bcm_workq_t *workq;
-
-		pkt = DHD_PKTID_TO_NATIVE(dhd, dhd->prot->pktid_map_handle,
-			pktid, pa, len, dmah, secdma, PKTTYPE_DATA_TX);
-
-		workq = &prot->tx_compl_prod;
-		/*
-		 * Produce the packet into the tx_compl workq for the tx compl tasklet
-		 * to consume.
-		 */
-		OSL_PREFETCH(PKTTAG(pkt));
-
-		/* fetch next available slot in workq */
-		elem_ix = bcm_ring_prod(WORKQ_RING(workq), DHD_LB_WORKQ_SZ);
-
-		DHD_PKTTAG_SET_PA((dhd_pkttag_fr_t *)PKTTAG(pkt), pa);
-		DHD_PKTTAG_SET_PA_LEN((dhd_pkttag_fr_t *)PKTTAG(pkt), len);
-
-		if (elem_ix == BCM_RING_FULL) {
-			DHD_ERROR(("tx_compl_prod BCM_RING_FULL\n"));
-			goto workq_ring_full;
-		}
-
-		elem = WORKQ_ELEMENT(void *, &prot->tx_compl_prod, elem_ix);
-		*elem = pkt;
-
-		smp_wmb();
-
-		/* Sync WR index to consumer if the SYNC threshold has been reached */
-		if (++prot->tx_compl_prod_sync >= DHD_LB_WORKQ_SYNC) {
-			bcm_workq_prod_sync(workq);
-			prot->tx_compl_prod_sync = 0;
-		}
-
-		DHD_INFO(("%s: tx_compl_prod pkt<%p> sync<%d>\n",
-		__FUNCTION__, pkt, prot->tx_compl_prod_sync));
-
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return;
-	   }
-
-workq_ring_full:
-
-#endif /* !DHD_LB_TXC */
-
-	/*
-	 * We can come here if no DHD_LB_TXC is enabled and in case where DHD_LB_TXC is
-	 * defined but the tx_compl queue is full.
-	 */
-	if (pkt == NULL) {
-		pkt = DHD_PKTID_TO_NATIVE(dhd, dhd->prot->pktid_map_handle,
-			pktid, pa, len, dmah, secdma, PKTTYPE_DATA_TX);
-	}
-
-	if (pkt) {
-		if (SECURE_DMA_ENAB(dhd->osh)) {
-			int offset = 0;
-			BCM_REFERENCE(offset);
-
-			if (dhd->prot->tx_metadata_offset)
-				offset = dhd->prot->tx_metadata_offset + ETHER_HDR_LEN;
-			SECURE_DMA_UNMAP(dhd->osh, (uint) pa,
-				(uint) dhd->prot->tx_metadata_offset, DMA_RX, 0, dmah,
-				secdma, offset);
-		} else {
-			DMA_UNMAP(dhd->osh, pa, (uint) len, DMA_RX, 0, dmah);
-		}
-#if defined(BCMPCIE)
-		dhd_txcomplete(dhd, pkt, true);
-#endif 
-
-#if DHD_DBG_SHOW_METADATA
-		if (dhd->prot->metadata_dbg &&
-		    dhd->prot->tx_metadata_offset && txstatus->metadata_len) {
-			uchar *ptr;
-			/* The Ethernet header of TX frame was copied and removed.
-			 * Here, move the data pointer forward by Ethernet header size.
-			 */
-			PKTPULL(dhd->osh, pkt, ETHER_HDR_LEN);
-			ptr = PKTDATA(dhd->osh, pkt)  - (dhd->prot->tx_metadata_offset);
-			bcm_print_bytes("txmetadata", ptr, txstatus->metadata_len);
-			dhd_prot_print_metadata(dhd, ptr, txstatus->metadata_len);
-		}
-#endif /* DHD_DBG_SHOW_METADATA */
-		PKTFREE(dhd->osh, pkt, TRUE);
-		DHD_FLOWRING_TXSTATUS_CNT_UPDATE(dhd->bus, txstatus->compl_hdr.flow_ring_id,
-		txstatus->tx_status);
-	}
-
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return;
-} /* dhd_prot_txstatus_process */
-
-/** called on MSG_TYPE_WL_EVENT message received from dongle */
-static void
-dhd_prot_event_process(dhd_pub_t *dhd, void *msg)
-{
-	wlevent_req_msg_t *evnt;
-	uint32 bufid;
-	uint16 buflen;
-	int ifidx = 0;
-	void* pkt;
-	unsigned long flags;
-	dhd_prot_t *prot = dhd->prot;
-
-	/* Event complete header */
-	evnt = (wlevent_req_msg_t *)msg;
-	bufid = ltoh32(evnt->cmn_hdr.request_id);
-
-#if defined(DHD_PKTID_AUDIT_RING)
-	if (DHD_PKTID_AUDIT(dhd, dhd->prot->pktid_map_handle, bufid,
-		DHD_DUPLICATE_FREE) == BCME_ERROR) {
-			prhex("dhd_prot_event_process:",
-				(uchar *)msg, D2HRING_CTRL_CMPLT_ITEMSIZE);
-	}
-#endif /* DHD_PKTID_AUDIT_RING */
-
-	buflen = ltoh16(evnt->event_data_len);
-
-	ifidx = BCMMSGBUF_API_IFIDX(&evnt->cmn_hdr);
-
-	/* Post another rxbuf to the device */
-	if (prot->cur_event_bufs_posted) {
-		prot->cur_event_bufs_posted--;
-	}
-	dhd_msgbuf_rxbuf_post_event_bufs(dhd);
-
-	/* locks required to protect pktid_map */
-	DHD_GENERAL_LOCK(dhd, flags);
-	pkt = dhd_prot_packet_get(dhd, bufid, PKTTYPE_EVENT_RX, TRUE);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	if (!pkt) {
-		return;
-	}
-
-	/* DMA RX offset updated through shared area */
-	if (dhd->prot->rx_dataoffset) {
-		PKTPULL(dhd->osh, pkt, dhd->prot->rx_dataoffset);
-	}
-
-	PKTSETLEN(dhd->osh, pkt, buflen);
-
-	dhd_bus_rx_frame(dhd->bus, pkt, ifidx, 1);
-}
-
-/** called on MSG_TYPE_RX_CMPLT message received from dongle */
-static void BCMFASTPATH
-dhd_prot_rxcmplt_process(dhd_pub_t *dhd, void *msg)
-{
-	host_rxbuf_cmpl_t *rxcmplt_h;
-	uint16 data_offset;             /* offset at which data starts */
-	void *pkt;
-	unsigned long flags;
-	uint ifidx;
-	uint32 pktid;
-#if defined(DHD_LB_RXC)
-	const bool free_pktid = FALSE;
-#else
-	const bool free_pktid = TRUE;
-#endif /* DHD_LB_RXC */
-
-	/* RXCMPLT HDR */
-	rxcmplt_h = (host_rxbuf_cmpl_t *)msg;
-
-	/* offset from which data starts is populated in rxstatus0 */
-	data_offset = ltoh16(rxcmplt_h->data_offset);
-
-	pktid = ltoh32(rxcmplt_h->cmn_hdr.request_id);
-
-#if defined(DHD_PKTID_AUDIT_RING)
-	if (DHD_PKTID_AUDIT(dhd, dhd->prot->pktid_map_handle, pktid,
-		DHD_DUPLICATE_FREE) == BCME_ERROR) {
-			prhex("dhd_prot_rxcmplt_process:",
-				(uchar *)msg, D2HRING_RXCMPLT_ITEMSIZE);
-		}
-#endif /* DHD_PKTID_AUDIT_RING */
-
-	DHD_GENERAL_LOCK(dhd, flags);
-	pkt = dhd_prot_packet_get(dhd, pktid, PKTTYPE_DATA_RX, free_pktid);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	if (!pkt) {
-		return;
-	}
-
-	/* Post another set of rxbufs to the device */
-	dhd_prot_return_rxbuf(dhd, pktid, 1);
-
-	DHD_INFO(("id 0x%04x, offset %d, len %d, idx %d, phase 0x%02x, pktdata %p, metalen %d\n",
-		ltoh32(rxcmplt_h->cmn_hdr.request_id), data_offset, ltoh16(rxcmplt_h->data_len),
-		rxcmplt_h->cmn_hdr.if_id, rxcmplt_h->cmn_hdr.flags, PKTDATA(dhd->osh, pkt),
-		ltoh16(rxcmplt_h->metadata_len)));
-#if DHD_DBG_SHOW_METADATA
-	if (dhd->prot->metadata_dbg &&
-	    dhd->prot->rx_metadata_offset && rxcmplt_h->metadata_len) {
-		uchar *ptr;
-		ptr = PKTDATA(dhd->osh, pkt) - (dhd->prot->rx_metadata_offset);
-		/* header followed by data */
-		bcm_print_bytes("rxmetadata", ptr, rxcmplt_h->metadata_len);
-		dhd_prot_print_metadata(dhd, ptr, rxcmplt_h->metadata_len);
-	}
-#endif /* DHD_DBG_SHOW_METADATA */
-
-	if (rxcmplt_h->flags & BCMPCIE_PKT_FLAGS_FRAME_802_11) {
-		DHD_INFO(("D11 frame rxed \n"));
-	}
-
-	/* data_offset from buf start */
-	if (data_offset) {
-		/* data offset given from dongle after split rx */
-		PKTPULL(dhd->osh, pkt, data_offset); /* data offset */
-	} else {
-		/* DMA RX offset updated through shared area */
-		if (dhd->prot->rx_dataoffset) {
-			PKTPULL(dhd->osh, pkt, dhd->prot->rx_dataoffset);
-		}
-	}
-	/* Actual length of the packet */
-	PKTSETLEN(dhd->osh, pkt, ltoh16(rxcmplt_h->data_len));
-
-	ifidx = rxcmplt_h->cmn_hdr.if_id;
-
-#if defined(DHD_LB_RXP)
-	dhd_lb_rx_pkt_enqueue(dhd, pkt, ifidx);
-#else  /* ! DHD_LB_RXP */
-#ifdef DHD_RX_CHAINING
-	/* Chain the packets */
-	dhd_rxchain_frame(dhd, pkt, ifidx);
-#else /* ! DHD_RX_CHAINING */
-	/* offset from which data starts is populated in rxstatus0 */
-	dhd_bus_rx_frame(dhd->bus, pkt, ifidx, 1);
-#endif /* ! DHD_RX_CHAINING */
-#endif /* ! DHD_LB_RXP */
-} /* dhd_prot_rxcmplt_process */
-
-/** Stop protocol: sync w/dongle state. */
-void dhd_prot_stop(dhd_pub_t *dhd)
-{
-	ASSERT(dhd);
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-}
-
-/* Add any protocol-specific data header.
- * Caller must reserve prot_hdrlen prepend space.
- */
-void BCMFASTPATH
-dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *PKTBUF)
-{
-	return;
-}
-
-uint
-dhd_prot_hdrlen(dhd_pub_t *dhd, void *PKTBUF)
-{
-	return 0;
-}
-
-
-#define PKTBUF pktbuf
-
-/**
- * Called when a tx ethernet packet has been dequeued from a flow queue, and has to be inserted in
- * the corresponding flow ring.
- */
-int BCMFASTPATH
-dhd_prot_txdata(dhd_pub_t *dhd, void *PKTBUF, uint8 ifidx)
-{
-	unsigned long flags;
-	dhd_prot_t *prot = dhd->prot;
-	host_txbuf_post_t *txdesc = NULL;
-	dmaaddr_t pa, meta_pa;
-	uint8 *pktdata;
-	uint32 pktlen;
-	uint32 pktid;
-	uint8	prio;
-	uint16 flowid = 0;
-	uint16 alloced = 0;
-	uint16	headroom;
-	msgbuf_ring_t *ring;
-	flow_ring_table_t *flow_ring_table;
-	flow_ring_node_t *flow_ring_node;
-
-	if (dhd->flow_ring_table == NULL) {
-		return BCME_NORESOURCE;
-	}
-
-	flowid = DHD_PKT_GET_FLOWID(PKTBUF);
-
-	flow_ring_table = (flow_ring_table_t *)dhd->flow_ring_table;
-	flow_ring_node = (flow_ring_node_t *)&flow_ring_table[flowid];
-
-	ring = (msgbuf_ring_t *)flow_ring_node->prot_info;
-
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	/* Create a unique 32-bit packet id */
-	pktid = DHD_NATIVE_TO_PKTID_RSV(dhd, dhd->prot->pktid_map_handle, PKTBUF);
-#if defined(DHD_PCIE_PKTID)
-	if (pktid == DHD_PKTID_INVALID) {
-		DHD_ERROR(("Pktid pool depleted.\n"));
-		/*
-		 * If we return error here, the caller would queue the packet
-		 * again. So we'll just free the skb allocated in DMA Zone.
-		 * Since we have not freed the original SKB yet the caller would
-		 * requeue the same.
-		 */
-		goto err_no_res_pktfree;
-	}
-#endif /* DHD_PCIE_PKTID */
-
-	/* Reserve space in the circular buffer */
-	txdesc = (host_txbuf_post_t *)
-		dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE);
-	if (txdesc == NULL) {
-#if defined(DHD_PCIE_PKTID)
-		void *dmah;
-		void *secdma;
-		/* Free up the PKTID. physaddr and pktlen will be garbage. */
-		DHD_PKTID_TO_NATIVE(dhd, dhd->prot->pktid_map_handle, pktid,
-			pa, pktlen, dmah, secdma, PKTTYPE_NO_CHECK);
-#endif /* DHD_PCIE_PKTID */
-		DHD_INFO(("%s:%d: HTOD Msgbuf Not available TxCount = %d\n",
-			__FUNCTION__, __LINE__, prot->active_tx_count));
-		goto err_no_res_pktfree;
-	}
-
-	/* Extract the data pointer and length information */
-	pktdata = PKTDATA(dhd->osh, PKTBUF);
-	pktlen  = PKTLEN(dhd->osh, PKTBUF);
-
-	/* Ethernet header: Copy before we cache flush packet using DMA_MAP */
-	bcopy(pktdata, txdesc->txhdr, ETHER_HDR_LEN);
-
-	/* Extract the ethernet header and adjust the data pointer and length */
-	pktdata = PKTPULL(dhd->osh, PKTBUF, ETHER_HDR_LEN);
-	pktlen -= ETHER_HDR_LEN;
-
-	/* Map the data pointer to a DMA-able address */
-	if (SECURE_DMA_ENAB(dhd->osh)) {
-		int offset = 0;
-		BCM_REFERENCE(offset);
-
-		if (prot->tx_metadata_offset) {
-			offset = prot->tx_metadata_offset + ETHER_HDR_LEN;
-		}
-
-		pa = SECURE_DMA_MAP(dhd->osh, PKTDATA(dhd->osh, PKTBUF), pktlen,
-			DMA_TX, PKTBUF, 0, ring->dma_buf.secdma, offset);
-	} else {
-		pa = DMA_MAP(dhd->osh, PKTDATA(dhd->osh, PKTBUF), pktlen, DMA_TX, PKTBUF, 0);
-	}
-
-	if ((PHYSADDRHI(pa) == 0) && (PHYSADDRLO(pa) == 0)) {
-		DHD_ERROR(("Something really bad, unless 0 is a valid phyaddr\n"));
-		ASSERT(0);
-	}
-
-	/* No need to lock. Save the rest of the packet's metadata */
-	DHD_NATIVE_TO_PKTID_SAVE(dhd, dhd->prot->pktid_map_handle, PKTBUF, pktid,
-	    pa, pktlen, DMA_TX, NULL, ring->dma_buf.secdma, PKTTYPE_DATA_TX);
-
-#ifdef TXP_FLUSH_NITEMS
-	if (ring->pend_items_count == 0) {
-		ring->start_addr = (void *)txdesc;
-	}
-	ring->pend_items_count++;
-#endif
-
-	/* Form the Tx descriptor message buffer */
-
-	/* Common message hdr */
-	txdesc->cmn_hdr.msg_type = MSG_TYPE_TX_POST;
-	txdesc->cmn_hdr.if_id = ifidx;
-
-	txdesc->flags = BCMPCIE_PKT_FLAGS_FRAME_802_3;
-	prio = (uint8)PKTPRIO(PKTBUF);
-
-
-	txdesc->flags |= (prio & 0x7) << BCMPCIE_PKT_FLAGS_PRIO_SHIFT;
-	txdesc->seg_cnt = 1;
-
-	txdesc->data_len = htol16((uint16) pktlen);
-	txdesc->data_buf_addr.high_addr = htol32(PHYSADDRHI(pa));
-	txdesc->data_buf_addr.low_addr  = htol32(PHYSADDRLO(pa));
-
-	/* Move data pointer to keep ether header in local PKTBUF for later reference */
-	PKTPUSH(dhd->osh, PKTBUF, ETHER_HDR_LEN);
-
-	/* Handle Tx metadata */
-	headroom = (uint16)PKTHEADROOM(dhd->osh, PKTBUF);
-	if (prot->tx_metadata_offset && (headroom < prot->tx_metadata_offset)) {
-		DHD_ERROR(("No headroom for Metadata tx %d %d\n",
-		prot->tx_metadata_offset, headroom));
-	}
-
-	if (prot->tx_metadata_offset && (headroom >= prot->tx_metadata_offset)) {
-		DHD_TRACE(("Metadata in tx %d\n", prot->tx_metadata_offset));
-
-		/* Adjust the data pointer to account for meta data in DMA_MAP */
-		PKTPUSH(dhd->osh, PKTBUF, prot->tx_metadata_offset);
-
-		if (SECURE_DMA_ENAB(dhd->osh)) {
-			meta_pa = SECURE_DMA_MAP_TXMETA(dhd->osh, PKTDATA(dhd->osh, PKTBUF),
-				prot->tx_metadata_offset + ETHER_HDR_LEN, DMA_RX, PKTBUF,
-				0, ring->dma_buf.secdma);
-		} else {
-			meta_pa = DMA_MAP(dhd->osh, PKTDATA(dhd->osh, PKTBUF),
-				prot->tx_metadata_offset, DMA_RX, PKTBUF, 0);
-		}
-
-		if (PHYSADDRISZERO(meta_pa)) {
-			DHD_ERROR(("Something really bad, unless 0 is a valid phyaddr\n"));
-			ASSERT(0);
-		}
-
-		/* Adjust the data pointer back to original value */
-		PKTPULL(dhd->osh, PKTBUF, prot->tx_metadata_offset);
-
-		txdesc->metadata_buf_len = prot->tx_metadata_offset;
-		txdesc->metadata_buf_addr.high_addr = htol32(PHYSADDRHI(meta_pa));
-		txdesc->metadata_buf_addr.low_addr = htol32(PHYSADDRLO(meta_pa));
-	} else {
-		txdesc->metadata_buf_len = htol16(0);
-		txdesc->metadata_buf_addr.high_addr = 0;
-		txdesc->metadata_buf_addr.low_addr = 0;
-	}
-
-#if defined(DHD_PKTID_AUDIT_RING)
-	DHD_PKTID_AUDIT(dhd, prot->pktid_map_handle, pktid,
-		DHD_DUPLICATE_ALLOC);
-#endif /* DHD_PKTID_AUDIT_RING */
-
-	txdesc->cmn_hdr.request_id = htol32(pktid);
-
-	DHD_TRACE(("txpost: data_len %d, pktid 0x%04x\n", txdesc->data_len,
-		txdesc->cmn_hdr.request_id));
-
-	/* Update the write pointer in TCM & ring bell */
-#ifdef TXP_FLUSH_NITEMS
-	/* Flush if we have either hit the txp_threshold or if this msg is */
-	/* occupying the last slot in the flow_ring - before wrap around.  */
-	if ((ring->pend_items_count == prot->txp_threshold) ||
-		((uint8 *) txdesc == (uint8 *) DHD_RING_END_VA(ring))) {
-		dhd_prot_txdata_write_flush(dhd, flowid, TRUE);
-	}
-#else
-	/* update ring's WR index and ring doorbell to dongle */
-	dhd_prot_ring_write_complete(dhd, ring, txdesc, 1);
-#endif
-
-	prot->active_tx_count++;
-
-	/*
-	 * Take a wake lock, do not sleep if we have atleast one packet
-	 * to finish.
-	 */
-	if (prot->active_tx_count == 1)
-		DHD_OS_WAKE_LOCK(dhd);
-
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return BCME_OK;
-
-err_no_res_pktfree:
-
-
-
-	DHD_GENERAL_UNLOCK(dhd, flags);
-	return BCME_NORESOURCE;
-} /* dhd_prot_txdata */
-
-/* called with a lock */
-/** optimization to write "n" tx items at a time to ring */
-void BCMFASTPATH
-dhd_prot_txdata_write_flush(dhd_pub_t *dhd, uint16 flowid, bool in_lock)
-{
-#ifdef TXP_FLUSH_NITEMS
-	unsigned long flags = 0;
-	flow_ring_table_t *flow_ring_table;
-	flow_ring_node_t *flow_ring_node;
-	msgbuf_ring_t *ring;
-
-	if (dhd->flow_ring_table == NULL) {
-		return;
-	}
-
-	if (!in_lock) {
-		DHD_GENERAL_LOCK(dhd, flags);
-	}
-
-	flow_ring_table = (flow_ring_table_t *)dhd->flow_ring_table;
-	flow_ring_node = (flow_ring_node_t *)&flow_ring_table[flowid];
-	ring = (msgbuf_ring_t *)flow_ring_node->prot_info;
-
-	if (ring->pend_items_count) {
-		/* update ring's WR index and ring doorbell to dongle */
-		dhd_prot_ring_write_complete(dhd, ring, ring->start_addr,
-			ring->pend_items_count);
-		ring->pend_items_count = 0;
-		ring->start_addr = NULL;
-	}
-
-	if (!in_lock) {
-		DHD_GENERAL_UNLOCK(dhd, flags);
-	}
-#endif /* TXP_FLUSH_NITEMS */
-}
-
-#undef PKTBUF	/* Only defined in the above routine */
-
-int BCMFASTPATH
-dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pkt, uchar *buf, uint *len)
-{
-	return 0;
-}
-
-/** post a set of receive buffers to the dongle */
-static void BCMFASTPATH
-dhd_prot_return_rxbuf(dhd_pub_t *dhd, uint32 pktid, uint32 rxcnt)
-{
-	dhd_prot_t *prot = dhd->prot;
-#if defined(DHD_LB_RXC)
-	int elem_ix;
-	uint32 *elem;
-	bcm_workq_t *workq;
-
-	workq = &prot->rx_compl_prod;
-
-	/* Produce the work item */
-	elem_ix = bcm_ring_prod(WORKQ_RING(workq), DHD_LB_WORKQ_SZ);
-	if (elem_ix == BCM_RING_FULL) {
-		DHD_ERROR(("%s LB RxCompl workQ is full\n", __FUNCTION__));
-		ASSERT(0);
-		return;
-	}
-
-	elem = WORKQ_ELEMENT(uint32, workq, elem_ix);
-	*elem = pktid;
-
-	smp_wmb();
-
-	/* Sync WR index to consumer if the SYNC threshold has been reached */
-	if (++prot->rx_compl_prod_sync >= DHD_LB_WORKQ_SYNC) {
-		bcm_workq_prod_sync(workq);
-		prot->rx_compl_prod_sync = 0;
-	}
-
-	DHD_INFO(("%s: rx_compl_prod pktid<%u> sync<%d>\n",
-		__FUNCTION__, pktid, prot->rx_compl_prod_sync));
-
-#endif /* DHD_LB_RXC */
-
-
-	if (prot->rxbufpost >= rxcnt) {
-		prot->rxbufpost -= rxcnt;
-	} else {
-		/* ASSERT(0); */
-		prot->rxbufpost = 0;
-	}
-
-#if !defined(DHD_LB_RXC)
-	if (prot->rxbufpost <= (prot->max_rxbufpost - RXBUFPOST_THRESHOLD)) {
-		dhd_msgbuf_rxbuf_post(dhd, FALSE); /* alloc pkt ids */
-	}
-#endif /* !DHD_LB_RXC */
-}
-
-/* called before an ioctl is sent to the dongle */
-static void
-dhd_prot_wlioctl_intercept(dhd_pub_t *dhd, wl_ioctl_t * ioc, void * buf)
-{
-	dhd_prot_t *prot = dhd->prot;
-
-	if (ioc->cmd == WLC_SET_VAR && buf != NULL && !strcmp(buf, "pcie_bus_tput")) {
-		int slen = 0;
-		pcie_bus_tput_params_t *tput_params;
-
-		slen = strlen("pcie_bus_tput") + 1;
-		tput_params = (pcie_bus_tput_params_t*)((char *)buf + slen);
-		bcopy(&prot->host_bus_throughput_buf.pa, &tput_params->host_buf_addr,
-			sizeof(tput_params->host_buf_addr));
-		tput_params->host_buf_len = DHD_BUS_TPUT_BUF_LEN;
-	}
-}
-
-
-/** Use protocol to issue ioctl to dongle. Only one ioctl may be in transit. */
-int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
-{
-	int ret = -1;
-	uint8 action;
-
-	if ((dhd->busstate == DHD_BUS_DOWN) || dhd->hang_was_sent) {
-		DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
-		goto done;
-	}
-
-	if (dhd->busstate == DHD_BUS_SUSPEND) {
-		DHD_ERROR(("%s : bus is suspended\n", __FUNCTION__));
-		goto done;
-	}
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (ioc->cmd == WLC_SET_PM) {
-		DHD_TRACE_HW4(("%s: SET PM to %d\n", __FUNCTION__, *(char *)buf));
-	}
-
-	ASSERT(len <= WLC_IOCTL_MAXLEN);
-
-	if (len > WLC_IOCTL_MAXLEN) {
-		goto done;
-	}
-
-	action = ioc->set;
-
-	dhd_prot_wlioctl_intercept(dhd, ioc, buf);
-
-	if (action & WL_IOCTL_ACTION_SET) {
-		ret = dhd_msgbuf_set_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
-	} else {
-		ret = dhd_msgbuf_query_ioctl(dhd, ifidx, ioc->cmd, buf, len, action);
-		if (ret > 0) {
-			ioc->used = ret;
-		}
-	}
-
-	/* Too many programs assume ioctl() returns 0 on success */
-	if (ret >= 0) {
-		ret = 0;
-	} else {
-		DHD_ERROR(("%s: status ret value is %d \n", __FUNCTION__, ret));
-		dhd->dongle_error = ret;
-	}
-
-	if (!ret && ioc->cmd == WLC_SET_VAR && buf != NULL) {
-		/* Intercept the wme_dp ioctl here */
-		if (!strcmp(buf, "wme_dp")) {
-			int slen, val = 0;
-
-			slen = strlen("wme_dp") + 1;
-			if (len >= (int)(slen + sizeof(int))) {
-				bcopy(((char *)buf + slen), &val, sizeof(int));
-			}
-			dhd->wme_dp = (uint8) ltoh32(val);
-		}
-
-	}
-
-done:
-	return ret;
-
-} /* dhd_prot_ioctl */
-
-/** test / loopback */
-
-int
-dhdmsgbuf_lpbk_req(dhd_pub_t *dhd, uint len)
-{
-	unsigned long flags;
-	dhd_prot_t *prot = dhd->prot;
-	uint16 alloced = 0;
-
-	ioct_reqst_hdr_t *ioct_rqst;
-
-	uint16 hdrlen = sizeof(ioct_reqst_hdr_t);
-	uint16 msglen = len + hdrlen;
-	msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn;
-
-	msglen = ALIGN_SIZE(msglen, DMA_ALIGN_LEN);
-	msglen = LIMIT_TO_MAX(msglen, MSGBUF_MAX_MSG_SIZE);
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	ioct_rqst = (ioct_reqst_hdr_t *)
-		dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE);
-
-	if (ioct_rqst == NULL) {
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return 0;
-	}
-
-	{
-		uint8 *ptr;
-		uint16 i;
-
-		ptr = (uint8 *)ioct_rqst;
-		for (i = 0; i < msglen; i++) {
-			ptr[i] = i % 256;
-		}
-	}
-
-	/* Common msg buf hdr */
-	ioct_rqst->msg.epoch = ring->seqnum % H2D_EPOCH_MODULO;
-	ring->seqnum++;
-
-	ioct_rqst->msg.msg_type = MSG_TYPE_LOOPBACK;
-	ioct_rqst->msg.if_id = 0;
-
-	bcm_print_bytes("LPBK REQ: ", (uint8 *)ioct_rqst, msglen);
-
-	/* update ring's WR index and ring doorbell to dongle */
-	dhd_prot_ring_write_complete(dhd, ring, ioct_rqst, 1);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return 0;
-}
-
-/** test / loopback */
-void dmaxfer_free_dmaaddr(dhd_pub_t *dhd, dhd_dmaxfer_t *dmaxfer)
-{
-	if (dmaxfer == NULL) {
-		return;
-	}
-
-	dhd_dma_buf_free(dhd, &dmaxfer->srcmem);
-	dhd_dma_buf_free(dhd, &dmaxfer->dstmem);
-}
-
-/** test / loopback */
-int dmaxfer_prepare_dmaaddr(dhd_pub_t *dhd, uint len,
-	uint srcdelay, uint destdelay, dhd_dmaxfer_t *dmaxfer)
-{
-	uint i;
-	if (!dmaxfer) {
-		return BCME_ERROR;
-	}
-
-	/* First free up existing buffers */
-	dmaxfer_free_dmaaddr(dhd, dmaxfer);
-
-	if (dhd_dma_buf_alloc(dhd, &dmaxfer->srcmem, len)) {
-		return BCME_NOMEM;
-	}
-
-	if (dhd_dma_buf_alloc(dhd, &dmaxfer->dstmem, len + 8)) {
-		dhd_dma_buf_free(dhd, &dmaxfer->srcmem);
-		return BCME_NOMEM;
-	}
-
-	dmaxfer->len = len;
-
-	/* Populate source with a pattern */
-	for (i = 0; i < dmaxfer->len; i++) {
-		((uint8*)dmaxfer->srcmem.va)[i] = i % 256;
-	}
-	OSL_CACHE_FLUSH(dmaxfer->srcmem.va, dmaxfer->len);
-
-	dmaxfer->srcdelay = srcdelay;
-	dmaxfer->destdelay = destdelay;
-
-	return BCME_OK;
-} /* dmaxfer_prepare_dmaaddr */
-
-static void
-dhd_msgbuf_dmaxfer_process(dhd_pub_t *dhd, void *msg)
-{
-	dhd_prot_t *prot = dhd->prot;
-
-	OSL_CACHE_INV(prot->dmaxfer.dstmem.va, prot->dmaxfer.len);
-	if (prot->dmaxfer.srcmem.va && prot->dmaxfer.dstmem.va) {
-		if (memcmp(prot->dmaxfer.srcmem.va,
-		        prot->dmaxfer.dstmem.va, prot->dmaxfer.len)) {
-			bcm_print_bytes("XFER SRC: ",
-			    prot->dmaxfer.srcmem.va, prot->dmaxfer.len);
-			bcm_print_bytes("XFER DST: ",
-			    prot->dmaxfer.dstmem.va, prot->dmaxfer.len);
-		} else {
-			DHD_INFO(("DMA successful\n"));
-		}
-	}
-	dmaxfer_free_dmaaddr(dhd, &prot->dmaxfer);
-	dhd->prot->dmaxfer.in_progress = FALSE;
-}
-
-/** Test functionality.
- * Transfers bytes from host to dongle and to host again using DMA
- * This function is not reentrant, as prot->dmaxfer.in_progress is not protected
- * by a spinlock.
- */
-int
-dhdmsgbuf_dmaxfer_req(dhd_pub_t *dhd, uint len, uint srcdelay, uint destdelay)
-{
-	unsigned long flags;
-	int ret = BCME_OK;
-	dhd_prot_t *prot = dhd->prot;
-	pcie_dma_xfer_params_t *dmap;
-	uint32 xferlen = LIMIT_TO_MAX(len, DMA_XFER_LEN_LIMIT);
-	uint16 alloced = 0;
-	msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn;
-
-	if (prot->dmaxfer.in_progress) {
-		DHD_ERROR(("DMA is in progress...\n"));
-		return ret;
-	}
-
-	prot->dmaxfer.in_progress = TRUE;
-	if ((ret = dmaxfer_prepare_dmaaddr(dhd, xferlen, srcdelay, destdelay,
-	        &prot->dmaxfer)) != BCME_OK) {
-		prot->dmaxfer.in_progress = FALSE;
-		return ret;
-	}
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	dmap = (pcie_dma_xfer_params_t *)
-		dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE);
-
-	if (dmap == NULL) {
-		dmaxfer_free_dmaaddr(dhd, &prot->dmaxfer);
-		prot->dmaxfer.in_progress = FALSE;
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return BCME_NOMEM;
-	}
-
-	/* Common msg buf hdr */
-	dmap->cmn_hdr.msg_type = MSG_TYPE_LPBK_DMAXFER;
-	dmap->cmn_hdr.request_id = htol32(DHD_FAKE_PKTID);
-	dmap->cmn_hdr.epoch = ring->seqnum % H2D_EPOCH_MODULO;
-	ring->seqnum++;
-
-	dmap->host_input_buf_addr.high = htol32(PHYSADDRHI(prot->dmaxfer.srcmem.pa));
-	dmap->host_input_buf_addr.low = htol32(PHYSADDRLO(prot->dmaxfer.srcmem.pa));
-	dmap->host_ouput_buf_addr.high = htol32(PHYSADDRHI(prot->dmaxfer.dstmem.pa));
-	dmap->host_ouput_buf_addr.low = htol32(PHYSADDRLO(prot->dmaxfer.dstmem.pa));
-	dmap->xfer_len = htol32(prot->dmaxfer.len);
-	dmap->srcdelay = htol32(prot->dmaxfer.srcdelay);
-	dmap->destdelay = htol32(prot->dmaxfer.destdelay);
-
-	/* update ring's WR index and ring doorbell to dongle */
-	dhd_prot_ring_write_complete(dhd, ring, dmap, 1);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	DHD_ERROR(("DMA Started...\n"));
-
-	return BCME_OK;
-} /* dhdmsgbuf_dmaxfer_req */
-
-/** Called in the process of submitting an ioctl to the dongle */
-static int
-dhd_msgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
-{
-	int ret = 0;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	/* Respond "bcmerror" and "bcmerrorstr" with local cache */
-	if (cmd == WLC_GET_VAR && buf)
-	{
-		if (!strcmp((char *)buf, "bcmerrorstr"))
-		{
-			strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN);
-			goto done;
-		}
-		else if (!strcmp((char *)buf, "bcmerror"))
-		{
-			*(int *)buf = dhd->dongle_error;
-			goto done;
-		}
-	}
-
-	ret = dhd_fillup_ioct_reqst(dhd, (uint16)len, cmd, buf, ifidx);
-
-	DHD_CTL(("query_ioctl: ACTION %d ifdix %d cmd %d len %d \n",
-		action, ifidx, cmd, len));
-
-	/* wait for IOCTL completion message from dongle and get first fragment */
-	ret = dhd_msgbuf_wait_ioctl_cmplt(dhd, len, buf);
-
-done:
-	return ret;
-}
-
-/**
- * Waits for IOCTL completion message from the dongle, copies this into caller
- * provided parameter 'buf'.
- */
-static int
-dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf)
-{
-	dhd_prot_t *prot = dhd->prot;
-	int timeleft;
-	unsigned long flags;
-	int ret = 0;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (dhd->dongle_reset) {
-		ret = -EIO;
-		goto out;
-	}
-
-	if (prot->cur_ioctlresp_bufs_posted) {
-		prot->cur_ioctlresp_bufs_posted--;
-	}
-
-	dhd_msgbuf_rxbuf_post_ioctlresp_bufs(dhd);
-
-	timeleft = dhd_os_ioctl_resp_wait(dhd, &prot->ioctl_received);
-	if (timeleft == 0) {
-		dhd->rxcnt_timeout++;
-		dhd->rx_ctlerrs++;
-		DHD_ERROR(("%s: resumed on timeout rxcnt_timeout %d ioctl_cmd %d "
-			"trans_id %d state %d busstate=%d ioctl_received=%d\n",
-			__FUNCTION__, dhd->rxcnt_timeout, prot->curr_ioctl_cmd,
-			prot->ioctl_trans_id, prot->ioctl_state,
-			dhd->busstate, prot->ioctl_received));
-
-		dhd_prot_debug_info_print(dhd);
-
-#ifdef DHD_FW_COREDUMP
-		/* As soon as FW TRAP occurs, FW dump will be collected from dhdpcie_checkdied */
-		if (dhd->memdump_enabled && !dhd->dongle_trap_occured) {
-			/* collect core dump */
-			dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT;
-			dhd_bus_mem_dump(dhd);
-		}
-#endif /* DHD_FW_COREDUMP */
-		if (dhd->rxcnt_timeout >= MAX_CNTL_RX_TIMEOUT) {
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#ifdef CONFIG_ARCH_MSM
-			dhd->bus->no_cfg_restore = 1;
-#endif /* CONFIG_ARCH_MSM */
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-			DHD_ERROR(("%s: timeout > MAX_CNTL_TX_TIMEOUT\n", __FUNCTION__));
-		}
-		ret = -ETIMEDOUT;
-		goto out;
-	} else {
-		if (prot->ioctl_received != IOCTL_RETURN_ON_SUCCESS) {
-			DHD_ERROR(("%s: IOCTL failure due to ioctl_received = %d\n",
-				__FUNCTION__, prot->ioctl_received));
-			ret = -ECONNABORTED;
-			goto out;
-		}
-		dhd->rxcnt_timeout = 0;
-		dhd->rx_ctlpkts++;
-		DHD_CTL(("%s: ioctl resp resumed, got %d\n",
-			__FUNCTION__, prot->ioctl_resplen));
-	}
-
-	if (dhd->dongle_trap_occured) {
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#ifdef CONFIG_ARCH_MSM
-		dhd->bus->no_cfg_restore = 1;
-#endif /* CONFIG_ARCH_MSM */
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-		DHD_ERROR(("%s: TRAP occurred!!\n", __FUNCTION__));
-		ret = -EREMOTEIO;
-		goto out;
-	}
-
-	if (dhd->prot->ioctl_resplen > len) {
-		dhd->prot->ioctl_resplen = (uint16)len;
-	}
-	if (buf) {
-		bcopy(dhd->prot->retbuf.va, buf, dhd->prot->ioctl_resplen);
-	}
-
-	ret = (int)(dhd->prot->ioctl_status);
-out:
-	DHD_GENERAL_LOCK(dhd, flags);
-	dhd->prot->ioctl_state = 0;
-	dhd->prot->ioctl_resplen = 0;
-	dhd->prot->ioctl_received = IOCTL_WAIT;
-	dhd->prot->curr_ioctl_cmd = 0;
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return ret;
-} /* dhd_msgbuf_wait_ioctl_cmplt */
-
-static int
-dhd_msgbuf_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
-{
-	int ret = 0;
-
-	DHD_TRACE(("%s: Enter \n", __FUNCTION__));
-
-	if (dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
-		return -EIO;
-	}
-
-	/* don't talk to the dongle if fw is about to be reloaded */
-	if (dhd->hang_was_sent) {
-		DHD_ERROR(("%s: HANG was sent up earlier. Not talking to the chip\n",
-			__FUNCTION__));
-		return -EIO;
-	}
-
-	/* Fill up msgbuf for ioctl req */
-	ret = dhd_fillup_ioct_reqst(dhd, (uint16)len, cmd, buf, ifidx);
-
-	DHD_CTL(("ACTION %d ifdix %d cmd %d len %d \n",
-		action, ifidx, cmd, len));
-
-	ret = dhd_msgbuf_wait_ioctl_cmplt(dhd, len, buf);
-
-	return ret;
-}
-
-/** Called by upper DHD layer. Handles a protocol control response asynchronously. */
-int dhd_prot_ctl_complete(dhd_pub_t *dhd)
-{
-	return 0;
-}
-
-/** Called by upper DHD layer. Check for and handle local prot-specific iovar commands */
-int dhd_prot_iovar_op(dhd_pub_t *dhd, const char *name,
-	void *params, int plen, void *arg, int len, bool set)
-{
-	return BCME_UNSUPPORTED;
-}
-
-/** Add prot dump output to a buffer */
-void dhd_prot_dump(dhd_pub_t *dhd, struct bcmstrbuf *b)
-{
-
-#if defined(PCIE_D2H_SYNC)
-	if (dhd->d2h_sync_mode & PCIE_SHARED_D2H_SYNC_SEQNUM)
-		bcm_bprintf(b, "\nd2h_sync: SEQNUM:");
-	else if (dhd->d2h_sync_mode & PCIE_SHARED_D2H_SYNC_XORCSUM)
-		bcm_bprintf(b, "\nd2h_sync: XORCSUM:");
-	else
-		bcm_bprintf(b, "\nd2h_sync: NONE:");
-	bcm_bprintf(b, " d2h_sync_wait max<%lu> tot<%lu>\n",
-		dhd->prot->d2h_sync_wait_max, dhd->prot->d2h_sync_wait_tot);
-#endif  /* PCIE_D2H_SYNC */
-
-	bcm_bprintf(b, "\nDongle DMA Indices: h2d %d  d2h %d index size %d bytes\n",
-		DMA_INDX_ENAB(dhd->dma_h2d_ring_upd_support),
-		DMA_INDX_ENAB(dhd->dma_d2h_ring_upd_support),
-		dhd->prot->rw_index_sz);
-}
-
-/* Update local copy of dongle statistics */
-void dhd_prot_dstats(dhd_pub_t *dhd)
-{
-	return;
-}
-
-/** Called by upper DHD layer */
-int dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf,
-	uint reorder_info_len, void **pkt, uint32 *free_buf_count)
-{
-	return 0;
-}
-
-/** Debug related, post a dummy message to interrupt dongle. Used to process cons commands. */
-int
-dhd_post_dummy_msg(dhd_pub_t *dhd)
-{
-	unsigned long flags;
-	hostevent_hdr_t *hevent = NULL;
-	uint16 alloced = 0;
-
-	dhd_prot_t *prot = dhd->prot;
-	msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn;
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	hevent = (hostevent_hdr_t *)
-		dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE);
-
-	if (hevent == NULL) {
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return -1;
-	}
-
-	/* CMN msg header */
-	hevent->msg.epoch = ring->seqnum % H2D_EPOCH_MODULO;
-	ring->seqnum++;
-	hevent->msg.msg_type = MSG_TYPE_HOST_EVNT;
-	hevent->msg.if_id = 0;
-
-	/* Event payload */
-	hevent->evnt_pyld = htol32(HOST_EVENT_CONS_CMD);
-
-	/* Since, we are filling the data directly into the bufptr obtained
-	 * from the msgbuf, we can directly call the write_complete
-	 */
-	dhd_prot_ring_write_complete(dhd, ring, hevent, 1);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return 0;
-}
-
-/**
- * If exactly_nitems is true, this function will allocate space for nitems or fail
- * If exactly_nitems is false, this function will allocate space for nitems or less
- */
-static void * BCMFASTPATH
-dhd_prot_alloc_ring_space(dhd_pub_t *dhd, msgbuf_ring_t *ring,
-	uint16 nitems, uint16 * alloced, bool exactly_nitems)
-{
-	void * ret_buf;
-
-	/* Alloc space for nitems in the ring */
-	ret_buf = dhd_prot_get_ring_space(ring, nitems, alloced, exactly_nitems);
-
-	if (ret_buf == NULL) {
-		/* if alloc failed , invalidate cached read ptr */
-		if (DMA_INDX_ENAB(dhd->dma_d2h_ring_upd_support)) {
-			ring->rd = dhd_prot_dma_indx_get(dhd, H2D_DMA_INDX_RD_UPD, ring->idx);
-		} else {
-			dhd_bus_cmn_readshared(dhd->bus, &(ring->rd), RING_RD_UPD, ring->idx);
-		}
-
-		/* Try allocating once more */
-		ret_buf = dhd_prot_get_ring_space(ring, nitems, alloced, exactly_nitems);
-
-		if (ret_buf == NULL) {
-			DHD_INFO(("%s: Ring space not available  \n", ring->name));
-			return NULL;
-		}
-	}
-
-	/* Return alloced space */
-	return ret_buf;
-}
-
-/**
- * Non inline ioct request.
- * Form a ioctl request first as per ioctptr_reqst_hdr_t header in the circular buffer
- * Form a separate request buffer where a 4 byte cmn header is added in the front
- * buf contents from parent function is copied to remaining section of this buffer
- */
-static int
-dhd_fillup_ioct_reqst(dhd_pub_t *dhd, uint16 len, uint cmd, void* buf, int ifidx)
-{
-	dhd_prot_t *prot = dhd->prot;
-	ioctl_req_msg_t *ioct_rqst;
-	void * ioct_buf;	/* For ioctl payload */
-	uint16  rqstlen, resplen;
-	unsigned long flags;
-	uint16 alloced = 0;
-	msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn;
-
-	rqstlen = len;
-	resplen = len;
-
-	/* Limit ioct request to MSGBUF_MAX_MSG_SIZE bytes including hdrs */
-	/* 8K allocation of dongle buffer fails */
-	/* dhd doesnt give separate input & output buf lens */
-	/* so making the assumption that input length can never be more than 1.5k */
-	rqstlen = MIN(rqstlen, MSGBUF_MAX_MSG_SIZE);
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	if (prot->ioctl_state) {
-		DHD_ERROR(("%s: pending ioctl %02x\n", __FUNCTION__, prot->ioctl_state));
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return BCME_BUSY;
-	} else {
-		prot->ioctl_state = MSGBUF_IOCTL_ACK_PENDING | MSGBUF_IOCTL_RESP_PENDING;
-	}
-
-	/* Request for cbuf space */
-	ioct_rqst = (ioctl_req_msg_t*)
-		dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE);
-	if (ioct_rqst == NULL) {
-		DHD_ERROR(("couldn't allocate space on msgring to send ioctl request\n"));
-		prot->ioctl_state = 0;
-		prot->curr_ioctl_cmd = 0;
-		prot->ioctl_received = IOCTL_WAIT;
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return -1;
-	}
-
-	/* Common msg buf hdr */
-	ioct_rqst->cmn_hdr.msg_type = MSG_TYPE_IOCTLPTR_REQ;
-	ioct_rqst->cmn_hdr.if_id = (uint8)ifidx;
-	ioct_rqst->cmn_hdr.flags = 0;
-	ioct_rqst->cmn_hdr.request_id = htol32(DHD_IOCTL_REQ_PKTID);
-	ioct_rqst->cmn_hdr.epoch = ring->seqnum % H2D_EPOCH_MODULO;
-	ring->seqnum++;
-
-	ioct_rqst->cmd = htol32(cmd);
-	prot->curr_ioctl_cmd = cmd;
-	ioct_rqst->output_buf_len = htol16(resplen);
-	prot->ioctl_trans_id++;
-	ioct_rqst->trans_id = prot->ioctl_trans_id;
-
-	/* populate ioctl buffer info */
-	ioct_rqst->input_buf_len = htol16(rqstlen);
-	ioct_rqst->host_input_buf_addr.high = htol32(PHYSADDRHI(prot->ioctbuf.pa));
-	ioct_rqst->host_input_buf_addr.low = htol32(PHYSADDRLO(prot->ioctbuf.pa));
-	/* copy ioct payload */
-	ioct_buf = (void *) prot->ioctbuf.va;
-
-	if (buf) {
-		memcpy(ioct_buf, buf, len);
-	}
-
-	OSL_CACHE_FLUSH((void *) prot->ioctbuf.va, len);
-
-	if (!ISALIGNED(ioct_buf, DMA_ALIGN_LEN)) {
-		DHD_ERROR(("host ioct address unaligned !!!!! \n"));
-	}
-
-	DHD_CTL(("submitted IOCTL request request_id %d, cmd %d, output_buf_len %d, tx_id %d\n",
-		ioct_rqst->cmn_hdr.request_id, cmd, ioct_rqst->output_buf_len,
-		ioct_rqst->trans_id));
-
-	/* update ring's WR index and ring doorbell to dongle */
-	dhd_prot_ring_write_complete(dhd, ring, ioct_rqst, 1);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return 0;
-} /* dhd_fillup_ioct_reqst */
-
-
-/**
- * dhd_prot_ring_attach - Initialize the msgbuf_ring object and attach a
- * DMA-able buffer to it. The ring is NOT tagged as inited until all the ring
- * information is posted to the dongle.
- *
- * Invoked in dhd_prot_attach for the common rings, and in dhd_prot_init for
- * each flowring in pool of flowrings.
- *
- * returns BCME_OK=0 on success
- * returns non-zero negative error value on failure.
- */
-static int
-dhd_prot_ring_attach(dhd_pub_t *dhd, msgbuf_ring_t *ring, const char *name,
-	uint16 max_items, uint16 item_len, uint16 ringid)
-{
-	int dma_buf_alloced = BCME_NOMEM;
-	uint32 dma_buf_len = max_items * item_len;
-	dhd_prot_t *prot = dhd->prot;
-
-	ASSERT(ring);
-	ASSERT(name);
-	ASSERT((max_items < 0xFFFF) && (item_len < 0xFFFF) && (ringid < 0xFFFF));
-
-	/* Init name */
-	strncpy(ring->name, name, RING_NAME_MAX_LENGTH);
-	ring->name[RING_NAME_MAX_LENGTH - 1] = '\0';
-
-	ring->idx = ringid;
-
-	ring->max_items = max_items;
-	ring->item_len = item_len;
-
-	/* A contiguous space may be reserved for all flowrings */
-	if (DHD_IS_FLOWRING(ringid) && (prot->flowrings_dma_buf.va)) {
-		/* Carve out from the contiguous DMA-able flowring buffer */
-		uint16 flowid;
-		uint32 base_offset;
-
-		dhd_dma_buf_t *dma_buf = &ring->dma_buf;
-		dhd_dma_buf_t *rsv_buf = &prot->flowrings_dma_buf;
-
-		flowid = DHD_RINGID_TO_FLOWID(ringid);
-		base_offset = (flowid - BCMPCIE_H2D_COMMON_MSGRINGS) * dma_buf_len;
-
-		ASSERT(base_offset + dma_buf_len <= rsv_buf->len);
-
-		dma_buf->len = dma_buf_len;
-		dma_buf->va = (void *)((uintptr)rsv_buf->va + base_offset);
-		PHYSADDRHISET(dma_buf->pa, PHYSADDRHI(rsv_buf->pa));
-		PHYSADDRLOSET(dma_buf->pa, PHYSADDRLO(rsv_buf->pa) + base_offset);
-
-		/* On 64bit, contiguous space may not span across 0x00000000FFFFFFFF */
-		ASSERT(PHYSADDRLO(dma_buf->pa) >= PHYSADDRLO(rsv_buf->pa));
-
-		dma_buf->dmah   = rsv_buf->dmah;
-		dma_buf->secdma = rsv_buf->secdma;
-
-		(void)dhd_dma_buf_audit(dhd, &ring->dma_buf);
-	} else {
-		/* Allocate a dhd_dma_buf */
-		dma_buf_alloced = dhd_dma_buf_alloc(dhd, &ring->dma_buf, dma_buf_len);
-		if (dma_buf_alloced != BCME_OK) {
-			return BCME_NOMEM;
-		}
-	}
-
-	/* CAUTION: Save ring::base_addr in little endian format! */
-	dhd_base_addr_htolpa(&ring->base_addr, ring->dma_buf.pa);
-
-#ifdef BCM_SECURE_DMA
-	if (SECURE_DMA_ENAB(prot->osh)) {
-		ring->dma_buf.secdma = MALLOCZ(prot->osh, sizeof(sec_cma_info_t));
-		if (ring->dma_buf.secdma == NULL) {
-			goto free_dma_buf;
-		}
-	}
-#endif /* BCM_SECURE_DMA */
-
-	DHD_INFO(("RING_ATTACH : %s Max item %d len item %d total size %d "
-		"ring start %p buf phys addr  %x:%x \n",
-		ring->name, ring->max_items, ring->item_len,
-		dma_buf_len, ring->dma_buf.va, ltoh32(ring->base_addr.high_addr),
-		ltoh32(ring->base_addr.low_addr)));
-
-	return BCME_OK;
-
-#ifdef BCM_SECURE_DMA
-free_dma_buf:
-	if (dma_buf_alloced == BCME_OK) {
-		dhd_dma_buf_free(dhd, &ring->dma_buf);
-	}
-#endif /* BCM_SECURE_DMA */
-
-	return BCME_NOMEM;
-
-} /* dhd_prot_ring_attach */
-
-
-/**
- * dhd_prot_ring_init - Post the common ring information to dongle.
- *
- * Used only for common rings.
- *
- * The flowrings information is passed via the create flowring control message
- * (tx_flowring_create_request_t) sent over the H2D control submission common
- * ring.
- */
-static void
-dhd_prot_ring_init(dhd_pub_t *dhd, msgbuf_ring_t *ring)
-{
-	ring->wr = 0;
-	ring->rd = 0;
-	ring->curr_rd = 0;
-
-	/* CAUTION: ring::base_addr already in Little Endian */
-	dhd_bus_cmn_writeshared(dhd->bus, &ring->base_addr,
-		sizeof(sh_addr_t), RING_BUF_ADDR, ring->idx);
-	dhd_bus_cmn_writeshared(dhd->bus, &ring->max_items,
-		sizeof(uint16), RING_MAX_ITEMS, ring->idx);
-	dhd_bus_cmn_writeshared(dhd->bus, &ring->item_len,
-		sizeof(uint16), RING_ITEM_LEN, ring->idx);
-
-	dhd_bus_cmn_writeshared(dhd->bus, &(ring->wr),
-		sizeof(uint16), RING_WR_UPD, ring->idx);
-	dhd_bus_cmn_writeshared(dhd->bus, &(ring->rd),
-		sizeof(uint16), RING_RD_UPD, ring->idx);
-
-	/* ring inited */
-	ring->inited = TRUE;
-
-} /* dhd_prot_ring_init */
-
-
-/**
- * dhd_prot_ring_reset - bzero a ring's DMA-ble buffer and cache flush
- * Reset WR and RD indices to 0.
- */
-static void
-dhd_prot_ring_reset(dhd_pub_t *dhd, msgbuf_ring_t *ring)
-{
-	DHD_TRACE(("%s\n", __FUNCTION__));
-
-	dhd_dma_buf_reset(dhd, &ring->dma_buf);
-
-	ring->rd = ring->wr = 0;
-	ring->curr_rd = 0;
-}
-
-
-/**
- * dhd_prot_ring_detach - Detach the DMA-able buffer and any other objects
- * hanging off the msgbuf_ring.
- */
-static void
-dhd_prot_ring_detach(dhd_pub_t *dhd, msgbuf_ring_t *ring)
-{
-	dhd_prot_t *prot = dhd->prot;
-	ASSERT(ring);
-
-	ring->inited = FALSE;
-	/* rd = ~0, wr = ring->rd - 1, max_items = 0, len_item = ~0 */
-
-#ifdef BCM_SECURE_DMA
-	if (SECURE_DMA_ENAB(prot->osh)) {
-		SECURE_DMA_UNMAP_ALL(prot->osh, ring->dma_buf.secdma);
-		if (ring->dma_buf.secdma) {
-			MFREE(prot->osh, ring->dma_buf.secdma, sizeof(sec_cma_info_t));
-		}
-		ring->dma_buf.secdma = NULL;
-	}
-#endif /* BCM_SECURE_DMA */
-
-	/* If the DMA-able buffer was carved out of a pre-reserved contiguous
-	 * memory, then simply stop using it.
-	 */
-	if (DHD_IS_FLOWRING(ring->idx) && (prot->flowrings_dma_buf.va)) {
-		(void)dhd_dma_buf_audit(dhd, &ring->dma_buf);
-		memset(&ring->dma_buf, 0, sizeof(dhd_dma_buf_t));
-	} else {
-		dhd_dma_buf_free(dhd, &ring->dma_buf);
-	}
-
-} /* dhd_prot_ring_detach */
-
-
-/*
- * +----------------------------------------------------------------------------
- * Flowring Pool
- *
- * Unlike common rings, which are attached very early on (dhd_prot_attach),
- * flowrings are dynamically instantiated. Moreover, flowrings may require a
- * larger DMA-able buffer. To avoid issues with fragmented cache coherent
- * DMA-able memory, a pre-allocated pool of msgbuf_ring_t is allocated once.
- * The DMA-able buffers are attached to these pre-allocated msgbuf_ring.
- *
- * Each DMA-able buffer may be allocated independently, or may be carved out
- * of a single large contiguous region that is registered with the protocol
- * layer into flowrings_dma_buf. On a 64bit platform, this contiguous region
- * may not span 0x00000000FFFFFFFF (avoid dongle side 64bit ptr arithmetic).
- *
- * No flowring pool action is performed in dhd_prot_attach(), as the number
- * of h2d rings is not yet known.
- *
- * In dhd_prot_init(), the dongle advertized number of h2d rings is used to
- * determine the number of flowrings required, and a pool of msgbuf_rings are
- * allocated and a DMA-able buffer (carved or allocated) is attached.
- * See: dhd_prot_flowrings_pool_attach()
- *
- * A flowring msgbuf_ring object may be fetched from this pool during flowring
- * creation, using the flowid. Likewise, flowrings may be freed back into the
- * pool on flowring deletion.
- * See: dhd_prot_flowrings_pool_fetch(), dhd_prot_flowrings_pool_release()
- *
- * In dhd_prot_detach(), the flowring pool is detached. The DMA-able buffers
- * are detached (returned back to the carved region or freed), and the pool of
- * msgbuf_ring and any objects allocated against it are freed.
- * See: dhd_prot_flowrings_pool_detach()
- *
- * In dhd_prot_reset(), the flowring pool is simply reset by returning it to a
- * state as-if upon an attach. All DMA-able buffers are retained.
- * Following a dhd_prot_reset(), in a subsequent dhd_prot_init(), the flowring
- * pool attach will notice that the pool persists and continue to use it. This
- * will avoid the case of a fragmented DMA-able region.
- *
- * +----------------------------------------------------------------------------
- */
-
-/* Fetch number of H2D flowrings given the total number of h2d rings */
-#define DHD_FLOWRINGS_POOL_TOTAL(h2d_rings_total) \
-	((h2d_rings_total) - BCMPCIE_H2D_COMMON_MSGRINGS)
-
-/* Conversion of a flowid to a flowring pool index */
-#define DHD_FLOWRINGS_POOL_OFFSET(flowid) \
-	((flowid) - BCMPCIE_H2D_COMMON_MSGRINGS)
-
-/* Fetch the msgbuf_ring_t from the flowring pool given a flowid */
-#define DHD_RING_IN_FLOWRINGS_POOL(prot, flowid) \
-	(msgbuf_ring_t*)((prot)->h2d_flowrings_pool) + DHD_FLOWRINGS_POOL_OFFSET(flowid)
-
-/* Traverse each flowring in the flowring pool, assigning ring and flowid */
-#define FOREACH_RING_IN_FLOWRINGS_POOL(prot, ring, flowid) \
-	for ((flowid) = DHD_FLOWRING_START_FLOWID, \
-		 (ring) = DHD_RING_IN_FLOWRINGS_POOL(prot, flowid); \
-		 (flowid) < (prot)->h2d_rings_total; \
-		 (flowid)++, (ring)++)
-
-/**
- * dhd_prot_flowrings_pool_attach - Initialize a pool of flowring msgbuf_ring_t.
- *
- * Allocate a pool of msgbuf_ring along with DMA-able buffers for flowrings.
- * Dongle includes common rings when it advertizes the number of H2D rings.
- * Allocates a pool of msgbuf_ring_t and invokes dhd_prot_ring_attach to
- * allocate the DMA-able buffer and initialize each msgbuf_ring_t object.
- *
- * dhd_prot_ring_attach is invoked to perform the actual initialization and
- * attaching the DMA-able buffer.
- *
- * Later dhd_prot_flowrings_pool_fetch() may be used to fetch a preallocated and
- * initialized msgbuf_ring_t object.
- *
- * returns BCME_OK=0 on success
- * returns non-zero negative error value on failure.
- */
-static int
-dhd_prot_flowrings_pool_attach(dhd_pub_t *dhd)
-{
-	uint16 flowid;
-	msgbuf_ring_t *ring;
-	uint16 h2d_flowrings_total; /* exclude H2D common rings */
-	dhd_prot_t *prot = dhd->prot;
-	char ring_name[RING_NAME_MAX_LENGTH];
-
-	if (prot->h2d_flowrings_pool != NULL) {
-		return BCME_OK; /* dhd_prot_init rentry after a dhd_prot_reset */
-	}
-
-	ASSERT(prot->h2d_rings_total == 0);
-
-	/* h2d_rings_total includes H2D common rings: ctrl and rxbuf subn */
-	prot->h2d_rings_total = (uint16)dhd_bus_max_h2d_queues(dhd->bus);
-
-	if (prot->h2d_rings_total < BCMPCIE_H2D_COMMON_MSGRINGS) {
-		DHD_ERROR(("%s: h2d_rings_total advertized as %u\n",
-			__FUNCTION__, prot->h2d_rings_total));
-		return BCME_ERROR;
-	}
-
-	/* Subtract number of H2D common rings, to determine number of flowrings */
-	h2d_flowrings_total = DHD_FLOWRINGS_POOL_TOTAL(prot->h2d_rings_total);
-
-	DHD_ERROR(("Attach flowrings pool for %d rings\n", h2d_flowrings_total));
-
-	/* Allocate pool of msgbuf_ring_t objects for all flowrings */
-	prot->h2d_flowrings_pool = (msgbuf_ring_t *)MALLOCZ(prot->osh,
-		(h2d_flowrings_total * sizeof(msgbuf_ring_t)));
-
-	if (prot->h2d_flowrings_pool == NULL) {
-		DHD_ERROR(("%s: flowrings pool for %d flowrings, alloc failure\n",
-			__FUNCTION__, h2d_flowrings_total));
-		goto fail;
-	}
-
-	/* Setup & Attach a DMA-able buffer to each flowring in the flowring pool */
-	FOREACH_RING_IN_FLOWRINGS_POOL(prot, ring, flowid) {
-		snprintf(ring_name, sizeof(ring_name), "h2dflr_%03u", flowid);
-		ring_name[RING_NAME_MAX_LENGTH - 1] = '\0';
-		if (dhd_prot_ring_attach(dhd, ring, ring_name,
-		        H2DRING_TXPOST_MAX_ITEM, H2DRING_TXPOST_ITEMSIZE,
-		        DHD_FLOWID_TO_RINGID(flowid)) != BCME_OK) {
-			goto attach_fail;
-		}
-	}
-
-	return BCME_OK;
-
-attach_fail:
-	dhd_prot_flowrings_pool_detach(dhd); /* Free entire pool of flowrings */
-
-fail:
-	prot->h2d_rings_total = 0;
-	return BCME_NOMEM;
-
-} /* dhd_prot_flowrings_pool_attach */
-
-
-/**
- * dhd_prot_flowrings_pool_reset - Reset all msgbuf_ring_t objects in the pool.
- * Invokes dhd_prot_ring_reset to perform the actual reset.
- *
- * The DMA-able buffer is not freed during reset and neither is the flowring
- * pool freed.
- *
- * dhd_prot_flowrings_pool_reset will be invoked in dhd_prot_reset. Following
- * the dhd_prot_reset, dhd_prot_init will be re-invoked, and the flowring pool
- * from a previous flowring pool instantiation will be reused.
- *
- * This will avoid a fragmented DMA-able memory condition, if multiple
- * dhd_prot_reset were invoked to reboot the dongle without a full detach/attach
- * cycle.
- */
-static void
-dhd_prot_flowrings_pool_reset(dhd_pub_t *dhd)
-{
-	uint16 flowid;
-	msgbuf_ring_t *ring;
-	dhd_prot_t *prot = dhd->prot;
-
-	if (prot->h2d_flowrings_pool == NULL) {
-		ASSERT(prot->h2d_rings_total == 0);
-		return;
-	}
-
-	/* Reset each flowring in the flowring pool */
-	FOREACH_RING_IN_FLOWRINGS_POOL(prot, ring, flowid) {
-		dhd_prot_ring_reset(dhd, ring);
-		ring->inited = FALSE;
-	}
-
-	/* Flowring pool state must be as-if dhd_prot_flowrings_pool_attach */
-}
-
-
-/**
- * dhd_prot_flowrings_pool_detach - Free pool of msgbuf_ring along with
- * DMA-able buffers for flowrings.
- * dhd_prot_ring_detach is invoked to free the DMA-able buffer and perform any
- * de-initialization of each msgbuf_ring_t.
- */
-static void
-dhd_prot_flowrings_pool_detach(dhd_pub_t *dhd)
-{
-	int flowid;
-	msgbuf_ring_t *ring;
-	int h2d_flowrings_total; /* exclude H2D common rings */
-	dhd_prot_t *prot = dhd->prot;
-
-	if (prot->h2d_flowrings_pool == NULL) {
-		ASSERT(prot->h2d_rings_total == 0);
-		return;
-	}
-
-	/* Detach the DMA-able buffer for each flowring in the flowring pool */
-	FOREACH_RING_IN_FLOWRINGS_POOL(prot, ring, flowid) {
-		dhd_prot_ring_detach(dhd, ring);
-	}
-
-	h2d_flowrings_total = DHD_FLOWRINGS_POOL_TOTAL(prot->h2d_rings_total);
-
-	MFREE(prot->osh, prot->h2d_flowrings_pool,
-		(h2d_flowrings_total * sizeof(msgbuf_ring_t)));
-
-	prot->h2d_flowrings_pool = (msgbuf_ring_t*)NULL;
-	prot->h2d_rings_total = 0;
-
-} /* dhd_prot_flowrings_pool_detach */
-
-
-/**
- * dhd_prot_flowrings_pool_fetch - Fetch a preallocated and initialized
- * msgbuf_ring from the flowring pool, and assign it.
- *
- * Unlike common rings, which uses a dhd_prot_ring_init() to pass the common
- * ring information to the dongle, a flowring's information is passed via a
- * flowring create control message.
- *
- * Only the ring state (WR, RD) index are initialized.
- */
-static msgbuf_ring_t *
-dhd_prot_flowrings_pool_fetch(dhd_pub_t *dhd, uint16 flowid)
-{
-	msgbuf_ring_t *ring;
-	dhd_prot_t *prot = dhd->prot;
-
-	ASSERT(flowid >= DHD_FLOWRING_START_FLOWID);
-	ASSERT(flowid < prot->h2d_rings_total);
-	ASSERT(prot->h2d_flowrings_pool != NULL);
-
-	ring = DHD_RING_IN_FLOWRINGS_POOL(prot, flowid);
-
-	/* ASSERT flow_ring->inited == FALSE */
-
-	ring->wr = 0;
-	ring->rd = 0;
-	ring->curr_rd = 0;
-	ring->inited = TRUE;
-
-	return ring;
-}
-
-
-/**
- * dhd_prot_flowrings_pool_release - release a previously fetched flowring's
- * msgbuf_ring back to the flow_ring pool.
- */
-void
-dhd_prot_flowrings_pool_release(dhd_pub_t *dhd, uint16 flowid, void *flow_ring)
-{
-	msgbuf_ring_t *ring;
-	dhd_prot_t *prot = dhd->prot;
-
-	ASSERT(flowid >= DHD_FLOWRING_START_FLOWID);
-	ASSERT(flowid < prot->h2d_rings_total);
-	ASSERT(prot->h2d_flowrings_pool != NULL);
-
-	ring = DHD_RING_IN_FLOWRINGS_POOL(prot, flowid);
-
-	ASSERT(ring == (msgbuf_ring_t*)flow_ring);
-	/* ASSERT flow_ring->inited == TRUE */
-
-	(void)dhd_dma_buf_audit(dhd, &ring->dma_buf);
-
-	ring->wr = 0;
-	ring->rd = 0;
-	ring->inited = FALSE;
-
-	ring->curr_rd = 0;
-}
-
-
-/* Assumes only one index is updated at a time */
-/* If exactly_nitems is true, this function will allocate space for nitems or fail */
-/*    Exception: when wrap around is encountered, to prevent hangup (last nitems of ring buffer) */
-/* If exactly_nitems is false, this function will allocate space for nitems or less */
-static void *BCMFASTPATH
-dhd_prot_get_ring_space(msgbuf_ring_t *ring, uint16 nitems, uint16 * alloced,
-	bool exactly_nitems)
-{
-	void *ret_ptr = NULL;
-	uint16 ring_avail_cnt;
-
-	ASSERT(nitems <= ring->max_items);
-
-	ring_avail_cnt = CHECK_WRITE_SPACE(ring->rd, ring->wr, ring->max_items);
-
-	if ((ring_avail_cnt == 0) ||
-	       (exactly_nitems && (ring_avail_cnt < nitems) &&
-	       ((ring->max_items - ring->wr) >= nitems))) {
-		DHD_INFO(("Space not available: ring %s items %d write %d read %d\n",
-			ring->name, nitems, ring->wr, ring->rd));
-		return NULL;
-	}
-	*alloced = MIN(nitems, ring_avail_cnt);
-
-	/* Return next available space */
-	ret_ptr = (char *)DHD_RING_BGN_VA(ring) + (ring->wr * ring->item_len);
-
-	/* Update write index */
-	if ((ring->wr + *alloced) == ring->max_items) {
-		ring->wr = 0;
-	} else if ((ring->wr + *alloced) < ring->max_items) {
-		ring->wr += *alloced;
-	} else {
-		/* Should never hit this */
-		ASSERT(0);
-		return NULL;
-	}
-
-	return ret_ptr;
-} /* dhd_prot_get_ring_space */
-
-
-/**
- * dhd_prot_ring_write_complete - Host updates the new WR index on producing
- * new messages in a H2D ring. The messages are flushed from cache prior to
- * posting the new WR index. The new WR index will be updated in the DMA index
- * array or directly in the dongle's ring state memory.
- * A PCIE doorbell will be generated to wake up the dongle.
- */
-static void BCMFASTPATH
-dhd_prot_ring_write_complete(dhd_pub_t *dhd, msgbuf_ring_t * ring, void* p,
-	uint16 nitems)
-{
-	dhd_prot_t *prot = dhd->prot;
-
-	/* cache flush */
-	OSL_CACHE_FLUSH(p, ring->item_len * nitems);
-
-	if (DMA_INDX_ENAB(dhd->dma_h2d_ring_upd_support)) {
-		dhd_prot_dma_indx_set(dhd, ring->wr,
-			H2D_DMA_INDX_WR_UPD, ring->idx);
-	} else {
-		dhd_bus_cmn_writeshared(dhd->bus, &(ring->wr),
-			sizeof(uint16), RING_WR_UPD, ring->idx);
-	}
-
-	/* raise h2d interrupt */
-	prot->mb_ring_fn(dhd->bus, ring->wr);
-}
-
-
-/**
- * dhd_prot_upd_read_idx - Host updates the new RD index on consuming messages
- * from a D2H ring. The new RD index will be updated in the DMA Index array or
- * directly in dongle's ring state memory.
- */
-static void
-dhd_prot_upd_read_idx(dhd_pub_t *dhd, msgbuf_ring_t * ring)
-{
-	/* update read index */
-	/* If dma'ing h2d indices supported
-	 * update the r -indices in the
-	 * host memory o/w in TCM
-	 */
-	if (DMA_INDX_ENAB(dhd->dma_h2d_ring_upd_support)) {
-		dhd_prot_dma_indx_set(dhd, ring->rd,
-			D2H_DMA_INDX_RD_UPD, ring->idx);
-	} else {
-		dhd_bus_cmn_writeshared(dhd->bus, &(ring->rd),
-			sizeof(uint16), RING_RD_UPD, ring->idx);
-	}
-}
-
-
-/**
- * dhd_prot_dma_indx_set - set a new WR or RD index in the DMA index array.
- * Dongle will DMA the entire array (if DMA_INDX feature is enabled).
- * See dhd_prot_dma_indx_init()
- */
-static void
-dhd_prot_dma_indx_set(dhd_pub_t *dhd, uint16 new_index, uint8 type, uint16 ringid)
-{
-	uint8 *ptr;
-	uint16 offset;
-	dhd_prot_t *prot = dhd->prot;
-
-	switch (type) {
-		case H2D_DMA_INDX_WR_UPD:
-			ptr = (uint8 *)(prot->h2d_dma_indx_wr_buf.va);
-			offset = DHD_H2D_RING_OFFSET(ringid);
-			break;
-
-		case D2H_DMA_INDX_RD_UPD:
-			ptr = (uint8 *)(prot->d2h_dma_indx_rd_buf.va);
-			offset = DHD_D2H_RING_OFFSET(ringid);
-			break;
-
-		default:
-			DHD_ERROR(("%s: Invalid option for DMAing read/write index\n",
-				__FUNCTION__));
-			return;
-	}
-
-	ASSERT(prot->rw_index_sz != 0);
-	ptr += offset * prot->rw_index_sz;
-
-	*(uint16*)ptr = htol16(new_index);
-
-	OSL_CACHE_FLUSH((void *)ptr, prot->rw_index_sz);
-
-	DHD_TRACE(("%s: data %d type %d ringid %d ptr 0x%p offset %d\n",
-		__FUNCTION__, new_index, type, ringid, ptr, offset));
-
-} /* dhd_prot_dma_indx_set */
-
-
-/**
- * dhd_prot_dma_indx_get - Fetch a WR or RD index from the dongle DMA-ed index
- * array.
- * Dongle DMAes an entire array to host memory (if the feature is enabled).
- * See dhd_prot_dma_indx_init()
- */
-static uint16
-dhd_prot_dma_indx_get(dhd_pub_t *dhd, uint8 type, uint16 ringid)
-{
-	uint8 *ptr;
-	uint16 data;
-	uint16 offset;
-	dhd_prot_t *prot = dhd->prot;
-
-	switch (type) {
-		case H2D_DMA_INDX_WR_UPD:
-			ptr = (uint8 *)(prot->h2d_dma_indx_wr_buf.va);
-			offset = DHD_H2D_RING_OFFSET(ringid);
-			break;
-
-		case H2D_DMA_INDX_RD_UPD:
-			ptr = (uint8 *)(prot->h2d_dma_indx_rd_buf.va);
-			offset = DHD_H2D_RING_OFFSET(ringid);
-			break;
-
-		case D2H_DMA_INDX_WR_UPD:
-			ptr = (uint8 *)(prot->d2h_dma_indx_wr_buf.va);
-			offset = DHD_D2H_RING_OFFSET(ringid);
-			break;
-
-		case D2H_DMA_INDX_RD_UPD:
-			ptr = (uint8 *)(prot->d2h_dma_indx_rd_buf.va);
-			offset = DHD_D2H_RING_OFFSET(ringid);
-			break;
-
-		default:
-			DHD_ERROR(("%s: Invalid option for DMAing read/write index\n",
-				__FUNCTION__));
-			return 0;
-	}
-
-	ASSERT(prot->rw_index_sz != 0);
-	ptr += offset * prot->rw_index_sz;
-
-	OSL_CACHE_INV((void *)ptr, prot->rw_index_sz);
-
-	data = LTOH16(*((uint16*)ptr));
-
-	DHD_TRACE(("%s: data %d type %d ringid %d ptr 0x%p offset %d\n",
-		__FUNCTION__, data, type, ringid, ptr, offset));
-
-	return (data);
-
-} /* dhd_prot_dma_indx_get */
-
-/**
- * An array of DMA read/write indices, containing information about host rings, can be maintained
- * either in host memory or in device memory, dependent on preprocessor options. This function is,
- * dependent on these options, called during driver initialization. It reserves and initializes
- * blocks of DMA'able host memory containing an array of DMA read or DMA write indices. The physical
- * address of these host memory blocks are communicated to the dongle later on. By reading this host
- * memory, the dongle learns about the state of the host rings.
- */
-
-static INLINE int
-dhd_prot_dma_indx_alloc(dhd_pub_t *dhd, uint8 type,
-	dhd_dma_buf_t *dma_buf, uint32 bufsz)
-{
-	int rc;
-
-	if ((dma_buf->len == bufsz) || (dma_buf->va != NULL))
-		return BCME_OK;
-
-	rc = dhd_dma_buf_alloc(dhd, dma_buf, bufsz);
-
-	return rc;
-}
-
-int
-dhd_prot_dma_indx_init(dhd_pub_t *dhd, uint32 rw_index_sz, uint8 type, uint32 length)
-{
-	uint32 bufsz;
-	dhd_prot_t *prot = dhd->prot;
-	dhd_dma_buf_t *dma_buf;
-
-	if (prot == NULL) {
-		DHD_ERROR(("prot is not inited\n"));
-		return BCME_ERROR;
-	}
-
-	/* Dongle advertizes 2B or 4B RW index size */
-	ASSERT(rw_index_sz != 0);
-	prot->rw_index_sz = rw_index_sz;
-
-	bufsz = rw_index_sz * length;
-
-	switch (type) {
-		case H2D_DMA_INDX_WR_BUF:
-			dma_buf = &prot->h2d_dma_indx_wr_buf;
-			if (dhd_prot_dma_indx_alloc(dhd, type, dma_buf, bufsz)) {
-				goto ret_no_mem;
-			}
-			DHD_ERROR(("H2D DMA WR INDX : array size %d = %d * %d\n",
-				dma_buf->len, rw_index_sz, length));
-			break;
-
-		case H2D_DMA_INDX_RD_BUF:
-			dma_buf = &prot->h2d_dma_indx_rd_buf;
-			if (dhd_prot_dma_indx_alloc(dhd, type, dma_buf, bufsz)) {
-				goto ret_no_mem;
-			}
-			DHD_ERROR(("H2D DMA RD INDX : array size %d = %d * %d\n",
-				dma_buf->len, rw_index_sz, length));
-			break;
-
-		case D2H_DMA_INDX_WR_BUF:
-			dma_buf = &prot->d2h_dma_indx_wr_buf;
-			if (dhd_prot_dma_indx_alloc(dhd, type, dma_buf, bufsz)) {
-				goto ret_no_mem;
-			}
-			DHD_ERROR(("D2H DMA WR INDX : array size %d = %d * %d\n",
-				dma_buf->len, rw_index_sz, length));
-			break;
-
-		case D2H_DMA_INDX_RD_BUF:
-			dma_buf = &prot->d2h_dma_indx_rd_buf;
-			if (dhd_prot_dma_indx_alloc(dhd, type, dma_buf, bufsz)) {
-				goto ret_no_mem;
-			}
-			DHD_ERROR(("D2H DMA RD INDX : array size %d = %d * %d\n",
-				dma_buf->len, rw_index_sz, length));
-			break;
-
-		default:
-			DHD_ERROR(("%s: Unexpected option\n", __FUNCTION__));
-			return BCME_BADOPTION;
-	}
-
-	return BCME_OK;
-
-ret_no_mem:
-	DHD_ERROR(("%s: dhd_prot_dma_indx_alloc type %d buf_sz %d failure\n",
-		__FUNCTION__, type, bufsz));
-	return BCME_NOMEM;
-
-} /* dhd_prot_dma_indx_init */
-
-
-/**
- * Called on checking for 'completion' messages from the dongle. Returns next host buffer to read
- * from, or NULL if there are no more messages to read.
- */
-static uint8*
-dhd_prot_get_read_addr(dhd_pub_t *dhd, msgbuf_ring_t *ring, uint32 *available_len)
-{
-	uint16 wr;
-	uint16 rd;
-	uint16 depth;
-	uint16 items;
-	void  *read_addr = NULL; /* address of next msg to be read in ring */
-	uint16 d2h_wr = 0;
-
-	DHD_TRACE(("%s: d2h_dma_indx_rd_buf %p, d2h_dma_indx_wr_buf %p\n",
-		__FUNCTION__, (uint32 *)(dhd->prot->d2h_dma_indx_rd_buf.va),
-		(uint32 *)(dhd->prot->d2h_dma_indx_wr_buf.va)));
-
-	/* Remember the read index in a variable.
-	 * This is becuase ring->rd gets updated in the end of this function
-	 * So if we have to print the exact read index from which the
-	 * message is read its not possible.
-	 */
-	ring->curr_rd = ring->rd;
-
-	/* update write pointer */
-	if (DMA_INDX_ENAB(dhd->dma_d2h_ring_upd_support)) {
-		/* DMAing write/read indices supported */
-		d2h_wr = dhd_prot_dma_indx_get(dhd, D2H_DMA_INDX_WR_UPD, ring->idx);
-		ring->wr = d2h_wr;
-	} else {
-		dhd_bus_cmn_readshared(dhd->bus, &(ring->wr), RING_WR_UPD, ring->idx);
-	}
-
-	wr = ring->wr;
-	rd = ring->rd;
-	depth = ring->max_items;
-
-	/* check for avail space, in number of ring items */
-	items = READ_AVAIL_SPACE(wr, rd, depth);
-	if (items == 0) {
-		return NULL;
-	}
-
-	ASSERT(items < ring->max_items);
-
-	/*
-	 * Note that there are builds where Assert translates to just printk
-	 * so, even if we had hit this condition we would never halt. Now
-	 * dhd_prot_process_msgtype can get into an big loop if this
-	 * happens.
-	 */
-	if (items >= ring->max_items) {
-		DHD_ERROR(("\r\n======================= \r\n"));
-		DHD_ERROR(("%s(): ring %p, ring->name %s, ring->max_items %d, items %d \r\n",
-			__FUNCTION__, ring, ring->name, ring->max_items, items));
-		DHD_ERROR(("wr: %d,  rd: %d,  depth: %d  \r\n", wr, rd, depth));
-		DHD_ERROR(("dhd->busstate %d bus->suspended %d bus->wait_for_d3_ack %d \r\n",
-			dhd->busstate, dhd->bus->suspended, dhd->bus->wait_for_d3_ack));
-		DHD_ERROR(("\r\n======================= \r\n"));
-
-		*available_len = 0;
-		return NULL;
-	}
-
-	/* if space is available, calculate address to be read */
-	read_addr = (char*)ring->dma_buf.va + (rd * ring->item_len);
-
-	/* update read pointer */
-	if ((ring->rd + items) >= ring->max_items) {
-		ring->rd = 0;
-	} else {
-		ring->rd += items;
-	}
-
-	ASSERT(ring->rd < ring->max_items);
-
-	/* convert items to bytes : available_len must be 32bits */
-	*available_len = (uint32)(items * ring->item_len);
-
-	OSL_CACHE_INV(read_addr, *available_len);
-
-	/* return read address */
-	return read_addr;
-
-} /* dhd_prot_get_read_addr */
-
-/** Creates a flow ring and informs dongle of this event */
-int
-dhd_prot_flow_ring_create(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node)
-{
-	tx_flowring_create_request_t *flow_create_rqst;
-	msgbuf_ring_t *flow_ring;
-	dhd_prot_t *prot = dhd->prot;
-	unsigned long flags;
-	uint16 alloced = 0;
-	msgbuf_ring_t *ctrl_ring = &prot->h2dring_ctrl_subn;
-
-	/* Fetch a pre-initialized msgbuf_ring from the flowring pool */
-	flow_ring = dhd_prot_flowrings_pool_fetch(dhd, flow_ring_node->flowid);
-	if (flow_ring == NULL) {
-		DHD_ERROR(("%s: dhd_prot_flowrings_pool_fetch TX Flowid %d failed\n",
-			__FUNCTION__, flow_ring_node->flowid));
-		return BCME_NOMEM;
-	}
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	/* Request for ctrl_ring buffer space */
-	flow_create_rqst = (tx_flowring_create_request_t *)
-		dhd_prot_alloc_ring_space(dhd, ctrl_ring, 1, &alloced, FALSE);
-
-	if (flow_create_rqst == NULL) {
-		dhd_prot_flowrings_pool_release(dhd, flow_ring_node->flowid, flow_ring);
-		DHD_ERROR(("%s: Flow Create Req flowid %d - failure ring space\n",
-			__FUNCTION__, flow_ring_node->flowid));
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return BCME_NOMEM;
-	}
-
-	flow_ring_node->prot_info = (void *)flow_ring;
-
-	/* Common msg buf hdr */
-	flow_create_rqst->msg.msg_type = MSG_TYPE_FLOW_RING_CREATE;
-	flow_create_rqst->msg.if_id = (uint8)flow_ring_node->flow_info.ifindex;
-	flow_create_rqst->msg.request_id = htol32(0); /* TBD */
-
-	flow_create_rqst->msg.epoch = ctrl_ring->seqnum % H2D_EPOCH_MODULO;
-	ctrl_ring->seqnum++;
-
-	/* Update flow create message */
-	flow_create_rqst->tid = flow_ring_node->flow_info.tid;
-	flow_create_rqst->flow_ring_id = htol16((uint16)flow_ring_node->flowid);
-	memcpy(flow_create_rqst->sa, flow_ring_node->flow_info.sa, sizeof(flow_create_rqst->sa));
-	memcpy(flow_create_rqst->da, flow_ring_node->flow_info.da, sizeof(flow_create_rqst->da));
-	/* CAUTION: ring::base_addr already in Little Endian */
-	flow_create_rqst->flow_ring_ptr.low_addr = flow_ring->base_addr.low_addr;
-	flow_create_rqst->flow_ring_ptr.high_addr = flow_ring->base_addr.high_addr;
-	flow_create_rqst->max_items = htol16(H2DRING_TXPOST_MAX_ITEM);
-	flow_create_rqst->len_item = htol16(H2DRING_TXPOST_ITEMSIZE);
-	DHD_ERROR(("%s: Send Flow Create Req flow ID %d for peer " MACDBG
-		" prio %d ifindex %d\n", __FUNCTION__, flow_ring_node->flowid,
-		MAC2STRDBG(flow_ring_node->flow_info.da), flow_ring_node->flow_info.tid,
-		flow_ring_node->flow_info.ifindex));
-
-	/* Update the flow_ring's WRITE index */
-	if (DMA_INDX_ENAB(dhd->dma_h2d_ring_upd_support)) {
-		dhd_prot_dma_indx_set(dhd, flow_ring->wr,
-			H2D_DMA_INDX_WR_UPD, flow_ring->idx);
-	} else {
-		dhd_bus_cmn_writeshared(dhd->bus, &(flow_ring->wr),
-			sizeof(uint16), RING_WR_UPD, flow_ring->idx);
-	}
-
-	/* update control subn ring's WR index and ring doorbell to dongle */
-	dhd_prot_ring_write_complete(dhd, ctrl_ring, flow_create_rqst, 1);
-
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return BCME_OK;
-} /* dhd_prot_flow_ring_create */
-
-/** called on receiving MSG_TYPE_FLOW_RING_CREATE_CMPLT message from dongle */
-static void
-dhd_prot_flow_ring_create_response_process(dhd_pub_t *dhd, void *msg)
-{
-	tx_flowring_create_response_t *flow_create_resp = (tx_flowring_create_response_t *)msg;
-
-	DHD_ERROR(("%s: Flow Create Response status = %d Flow %d\n", __FUNCTION__,
-		ltoh16(flow_create_resp->cmplt.status),
-		ltoh16(flow_create_resp->cmplt.flow_ring_id)));
-
-	dhd_bus_flow_ring_create_response(dhd->bus,
-		ltoh16(flow_create_resp->cmplt.flow_ring_id),
-		ltoh16(flow_create_resp->cmplt.status));
-}
-
-/** called on e.g. flow ring delete */
-void dhd_prot_clean_flow_ring(dhd_pub_t *dhd, void *msgbuf_flow_info)
-{
-	msgbuf_ring_t *flow_ring = (msgbuf_ring_t *)msgbuf_flow_info;
-	dhd_prot_ring_detach(dhd, flow_ring);
-	DHD_INFO(("%s Cleaning up Flow \n", __FUNCTION__));
-}
-
-void dhd_prot_print_flow_ring(dhd_pub_t *dhd, void *msgbuf_flow_info,
-	struct bcmstrbuf *strbuf, const char * fmt)
-{
-	const char *default_fmt = "RD %d WR %d BASE(VA) %p BASE(PA) %x:%x SIZE %d\n";
-	msgbuf_ring_t *flow_ring = (msgbuf_ring_t *)msgbuf_flow_info;
-	uint16 rd, wr;
-	uint32 dma_buf_len = flow_ring->max_items * flow_ring->item_len;
-
-	if (fmt == NULL) {
-		fmt = default_fmt;
-	}
-	dhd_bus_cmn_readshared(dhd->bus, &rd, RING_RD_UPD, flow_ring->idx);
-	dhd_bus_cmn_readshared(dhd->bus, &wr, RING_WR_UPD, flow_ring->idx);
-	bcm_bprintf(strbuf, fmt, rd, wr, flow_ring->dma_buf.va,
-		ltoh32(flow_ring->base_addr.high_addr),
-		ltoh32(flow_ring->base_addr.low_addr), dma_buf_len);
-}
-
-void dhd_prot_print_info(dhd_pub_t *dhd, struct bcmstrbuf *strbuf)
-{
-	dhd_prot_t *prot = dhd->prot;
-	bcm_bprintf(strbuf, "CtrlPost: ");
-	dhd_prot_print_flow_ring(dhd, &prot->h2dring_ctrl_subn, strbuf, NULL);
-	bcm_bprintf(strbuf, "CtrlCpl: ");
-	dhd_prot_print_flow_ring(dhd, &prot->d2hring_ctrl_cpln, strbuf, NULL);
-
-	bcm_bprintf(strbuf, "RxPost: ");
-	bcm_bprintf(strbuf, "RBP %d ", prot->rxbufpost);
-	dhd_prot_print_flow_ring(dhd, &prot->h2dring_rxp_subn, strbuf, NULL);
-	bcm_bprintf(strbuf, "RxCpl: ");
-	dhd_prot_print_flow_ring(dhd, &prot->d2hring_rx_cpln, strbuf, NULL);
-
-	bcm_bprintf(strbuf, "TxCpl: ");
-	dhd_prot_print_flow_ring(dhd, &prot->d2hring_tx_cpln, strbuf, NULL);
-	bcm_bprintf(strbuf, "active_tx_count %d	 pktidmap_avail %d\n",
-		dhd->prot->active_tx_count,
-		DHD_PKTID_AVAIL(dhd->prot->pktid_map_handle));
-}
-
-int
-dhd_prot_flow_ring_delete(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node)
-{
-	tx_flowring_delete_request_t *flow_delete_rqst;
-	dhd_prot_t *prot = dhd->prot;
-	unsigned long flags;
-	uint16 alloced = 0;
-	msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn;
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	/* Request for ring buffer space */
-	flow_delete_rqst = (tx_flowring_delete_request_t *)
-		dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE);
-
-	if (flow_delete_rqst == NULL) {
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		DHD_ERROR(("%s: Flow Delete Req - failure ring space\n", __FUNCTION__));
-		return BCME_NOMEM;
-	}
-
-	/* Common msg buf hdr */
-	flow_delete_rqst->msg.msg_type = MSG_TYPE_FLOW_RING_DELETE;
-	flow_delete_rqst->msg.if_id = (uint8)flow_ring_node->flow_info.ifindex;
-	flow_delete_rqst->msg.request_id = htol32(0); /* TBD */
-
-	flow_delete_rqst->msg.epoch = ring->seqnum % H2D_EPOCH_MODULO;
-	ring->seqnum++;
-
-	/* Update Delete info */
-	flow_delete_rqst->flow_ring_id = htol16((uint16)flow_ring_node->flowid);
-	flow_delete_rqst->reason = htol16(BCME_OK);
-
-	DHD_ERROR(("%s: Send Flow Delete Req RING ID %d for peer " MACDBG
-		" prio %d ifindex %d\n", __FUNCTION__, flow_ring_node->flowid,
-		MAC2STRDBG(flow_ring_node->flow_info.da), flow_ring_node->flow_info.tid,
-		flow_ring_node->flow_info.ifindex));
-
-	/* update ring's WR index and ring doorbell to dongle */
-	dhd_prot_ring_write_complete(dhd, ring, flow_delete_rqst, 1);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return BCME_OK;
-}
-
-static void
-dhd_prot_flow_ring_delete_response_process(dhd_pub_t *dhd, void *msg)
-{
-	tx_flowring_delete_response_t *flow_delete_resp = (tx_flowring_delete_response_t *)msg;
-
-	DHD_ERROR(("%s: Flow Delete Response status = %d Flow %d\n", __FUNCTION__,
-		flow_delete_resp->cmplt.status, flow_delete_resp->cmplt.flow_ring_id));
-
-	dhd_bus_flow_ring_delete_response(dhd->bus, flow_delete_resp->cmplt.flow_ring_id,
-		flow_delete_resp->cmplt.status);
-}
-
-int
-dhd_prot_flow_ring_flush(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node)
-{
-	tx_flowring_flush_request_t *flow_flush_rqst;
-	dhd_prot_t *prot = dhd->prot;
-	unsigned long flags;
-	uint16 alloced = 0;
-	msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn;
-
-	DHD_GENERAL_LOCK(dhd, flags);
-
-	/* Request for ring buffer space */
-	flow_flush_rqst = (tx_flowring_flush_request_t *)
-		dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE);
-	if (flow_flush_rqst == NULL) {
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		DHD_ERROR(("%s: Flow Flush Req - failure ring space\n", __FUNCTION__));
-		return BCME_NOMEM;
-	}
-
-	/* Common msg buf hdr */
-	flow_flush_rqst->msg.msg_type = MSG_TYPE_FLOW_RING_FLUSH;
-	flow_flush_rqst->msg.if_id = (uint8)flow_ring_node->flow_info.ifindex;
-	flow_flush_rqst->msg.request_id = htol32(0); /* TBD */
-
-	flow_flush_rqst->msg.epoch = ring->seqnum % H2D_EPOCH_MODULO;
-	ring->seqnum++;
-
-	flow_flush_rqst->flow_ring_id = htol16((uint16)flow_ring_node->flowid);
-	flow_flush_rqst->reason = htol16(BCME_OK);
-
-	DHD_INFO(("%s: Send Flow Flush Req\n", __FUNCTION__));
-
-	/* update ring's WR index and ring doorbell to dongle */
-	dhd_prot_ring_write_complete(dhd, ring, flow_flush_rqst, 1);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return BCME_OK;
-} /* dhd_prot_flow_ring_flush */
-
-static void
-dhd_prot_flow_ring_flush_response_process(dhd_pub_t *dhd, void *msg)
-{
-	tx_flowring_flush_response_t *flow_flush_resp = (tx_flowring_flush_response_t *)msg;
-
-	DHD_INFO(("%s: Flow Flush Response status = %d\n", __FUNCTION__,
-		flow_flush_resp->cmplt.status));
-
-	dhd_bus_flow_ring_flush_response(dhd->bus, flow_flush_resp->cmplt.flow_ring_id,
-		flow_flush_resp->cmplt.status);
-}
-
-/**
- * Request dongle to configure soft doorbells for D2H rings. Host populated soft
- * doorbell information is transferred to dongle via the d2h ring config control
- * message.
- */
-void
-dhd_msgbuf_ring_config_d2h_soft_doorbell(dhd_pub_t *dhd)
-{
-#if defined(DHD_D2H_SOFT_DOORBELL_SUPPORT)
-	uint16 ring_idx;
-	uint8 *msg_next;
-	void *msg_start;
-	uint16 alloced = 0;
-	unsigned long flags;
-	dhd_prot_t *prot = dhd->prot;
-	ring_config_req_t *ring_config_req;
-	bcmpcie_soft_doorbell_t *soft_doorbell;
-	msgbuf_ring_t *ctrl_ring = &prot->h2dring_ctrl_subn;
-	const uint16 d2h_rings = BCMPCIE_D2H_COMMON_MSGRINGS;
-
-	/* Claim space for d2h_ring number of d2h_ring_config_req_t messages */
-	DHD_GENERAL_LOCK(dhd, flags);
-	msg_start = dhd_prot_alloc_ring_space(dhd, ctrl_ring, d2h_rings, &alloced, TRUE);
-
-	if (msg_start == NULL) {
-		DHD_ERROR(("%s Msgbuf no space for %d D2H ring config soft doorbells\n",
-			__FUNCTION__, d2h_rings));
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return;
-	}
-
-	msg_next = (uint8*)msg_start;
-
-	for (ring_idx = 0; ring_idx < d2h_rings; ring_idx++) {
-
-		/* position the ring_config_req into the ctrl subm ring */
-		ring_config_req = (ring_config_req_t *)msg_next;
-
-		/* Common msg header */
-		ring_config_req->msg.msg_type = MSG_TYPE_D2H_RING_CONFIG;
-		ring_config_req->msg.if_id = 0;
-		ring_config_req->msg.flags = 0;
-
-		ring_config_req->msg.epoch = ctrl_ring->seqnum % H2D_EPOCH_MODULO;
-		ctrl_ring->seqnum++;
-
-		ring_config_req->msg.request_id = htol32(DHD_FAKE_PKTID); /* unused */
-
-		/* Ring Config subtype and d2h ring_id */
-		ring_config_req->subtype = htol16(D2H_RING_CONFIG_SUBTYPE_SOFT_DOORBELL);
-		ring_config_req->ring_id = htol16(DHD_D2H_RINGID(ring_idx));
-
-		/* Host soft doorbell configuration */
-		soft_doorbell = &prot->soft_doorbell[ring_idx];
-
-		ring_config_req->soft_doorbell.value = htol32(soft_doorbell->value);
-		ring_config_req->soft_doorbell.haddr.high =
-			htol32(soft_doorbell->haddr.high);
-		ring_config_req->soft_doorbell.haddr.low =
-			htol32(soft_doorbell->haddr.low);
-		ring_config_req->soft_doorbell.items = htol16(soft_doorbell->items);
-		ring_config_req->soft_doorbell.msecs = htol16(soft_doorbell->msecs);
-
-		DHD_INFO(("%s: Soft doorbell haddr 0x%08x 0x%08x value 0x%08x\n",
-			__FUNCTION__, ring_config_req->soft_doorbell.haddr.high,
-			ring_config_req->soft_doorbell.haddr.low,
-			ring_config_req->soft_doorbell.value));
-
-		msg_next = msg_next + ctrl_ring->item_len;
-	}
-
-	/* update control subn ring's WR index and ring doorbell to dongle */
-	dhd_prot_ring_write_complete(dhd, ctrl_ring, msg_start, d2h_rings);
-	DHD_GENERAL_UNLOCK(dhd, flags);
-#endif /* DHD_D2H_SOFT_DOORBELL_SUPPORT */
-}
-
-static void
-dhd_prot_d2h_ring_config_cmplt_process(dhd_pub_t *dhd, void *msg)
-{
-	DHD_INFO(("%s: Ring Config Response - status %d ringid %d\n",
-		__FUNCTION__, ltoh16(((ring_config_resp_t *)msg)->compl_hdr.status),
-		ltoh16(((ring_config_resp_t *)msg)->compl_hdr.flow_ring_id)));
-}
-
-int
-dhd_prot_debug_info_print(dhd_pub_t *dhd)
-{
-	dhd_prot_t *prot = dhd->prot;
-	msgbuf_ring_t *ring;
-	uint16 rd, wr;
-	uint32 intstatus = 0;
-	uint32 intmask = 0;
-	uint32 mbintstatus = 0;
-	uint32 d2h_mb_data = 0;
-	uint32 dma_buf_len;
-
-	DHD_ERROR(("\n ------- DUMPING IOCTL RING RD WR Pointers ------- \r\n"));
-
-	ring = &prot->h2dring_ctrl_subn;
-	dma_buf_len = ring->max_items * ring->item_len;
-	DHD_ERROR(("CtrlPost: Mem Info: BASE(VA) %p BASE(PA) %x:%x SIZE %d \r\n",
-		ring->dma_buf.va, ltoh32(ring->base_addr.high_addr),
-		ltoh32(ring->base_addr.low_addr), dma_buf_len));
-	DHD_ERROR(("CtrlPost: From Host mem: RD: %d WR %d \r\n", ring->rd, ring->wr));
-	dhd_bus_cmn_readshared(dhd->bus, &rd, RING_RD_UPD, ring->idx);
-	dhd_bus_cmn_readshared(dhd->bus, &wr, RING_WR_UPD, ring->idx);
-	DHD_ERROR(("CtrlPost: From Shared Mem: RD: %d WR %d \r\n", rd, wr));
-
-	ring = &prot->d2hring_ctrl_cpln;
-	dma_buf_len = ring->max_items * ring->item_len;
-	DHD_ERROR(("CtrlCpl: Mem Info: BASE(VA) %p BASE(PA) %x:%x SIZE %d \r\n",
-		ring->dma_buf.va, ltoh32(ring->base_addr.high_addr),
-		ltoh32(ring->base_addr.low_addr), dma_buf_len));
-	DHD_ERROR(("CtrlCpl: From Host mem: RD: %d WR %d \r\n", ring->rd, ring->wr));
-	dhd_bus_cmn_readshared(dhd->bus, &rd, RING_RD_UPD, ring->idx);
-	dhd_bus_cmn_readshared(dhd->bus, &wr, RING_WR_UPD, ring->idx);
-	DHD_ERROR(("CtrlCpl: From Shared Mem: RD: %d WR %d \r\n", rd, wr));
-	DHD_ERROR(("CtrlCpl: Expected seq num: %d \r\n", ring->seqnum));
-
-	intstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCIMailBoxInt, 0, 0);
-	intmask = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCIMailBoxMask, 0, 0);
-	mbintstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCID2H_MailBox, 0, 0);
-	dhd_bus_cmn_readshared(dhd->bus, &d2h_mb_data, D2H_MB_DATA, 0);
-
-	DHD_ERROR(("\n ------- DUMPING INTR Status and Masks ------- \r\n"));
-	DHD_ERROR(("intstatus=0x%x intmask=0x%x mbintstatus=0x%x\n,",
-		intstatus, intmask, mbintstatus));
-	DHD_ERROR(("d2h_mb_data=0x%x def_intmask=0x%x \r\n", d2h_mb_data, dhd->bus->def_intmask));
-
-	return 0;
-}
-
-int
-dhd_prot_ringupd_dump(dhd_pub_t *dhd, struct bcmstrbuf *b)
-{
-	uint32 *ptr;
-	uint32 value;
-	uint32 i;
-	uint32 max_h2d_queues = dhd_bus_max_h2d_queues(dhd->bus);
-
-	OSL_CACHE_INV((void *)dhd->prot->d2h_dma_indx_wr_buf.va,
-		dhd->prot->d2h_dma_indx_wr_buf.len);
-
-	ptr = (uint32 *)(dhd->prot->d2h_dma_indx_wr_buf.va);
-
-	bcm_bprintf(b, "\n max_tx_queues %d\n", max_h2d_queues);
-
-	bcm_bprintf(b, "\nRPTR block H2D common rings, 0x%04x\n", ptr);
-	value = ltoh32(*ptr);
-	bcm_bprintf(b, "\tH2D CTRL: value 0x%04x\n", value);
-	ptr++;
-	value = ltoh32(*ptr);
-	bcm_bprintf(b, "\tH2D RXPOST: value 0x%04x\n", value);
-
-	ptr++;
-	bcm_bprintf(b, "RPTR block Flow rings , 0x%04x\n", ptr);
-	for (i = BCMPCIE_H2D_COMMON_MSGRINGS; i < max_h2d_queues; i++) {
-		value = ltoh32(*ptr);
-		bcm_bprintf(b, "\tflowring ID %d: value 0x%04x\n", i, value);
-		ptr++;
-	}
-
-	OSL_CACHE_INV((void *)dhd->prot->h2d_dma_indx_rd_buf.va,
-		dhd->prot->h2d_dma_indx_rd_buf.len);
-
-	ptr = (uint32 *)(dhd->prot->h2d_dma_indx_rd_buf.va);
-
-	bcm_bprintf(b, "\nWPTR block D2H common rings, 0x%04x\n", ptr);
-	value = ltoh32(*ptr);
-	bcm_bprintf(b, "\tD2H CTRLCPLT: value 0x%04x\n", value);
-	ptr++;
-	value = ltoh32(*ptr);
-	bcm_bprintf(b, "\tD2H TXCPLT: value 0x%04x\n", value);
-	ptr++;
-	value = ltoh32(*ptr);
-	bcm_bprintf(b, "\tD2H RXCPLT: value 0x%04x\n", value);
-
-	return 0;
-}
-
-uint32
-dhd_prot_metadata_dbg_set(dhd_pub_t *dhd, bool val)
-{
-	dhd_prot_t *prot = dhd->prot;
-#if DHD_DBG_SHOW_METADATA
-	prot->metadata_dbg = val;
-#endif
-	return (uint32)prot->metadata_dbg;
-}
-
-uint32
-dhd_prot_metadata_dbg_get(dhd_pub_t *dhd)
-{
-	dhd_prot_t *prot = dhd->prot;
-	return (uint32)prot->metadata_dbg;
-}
-
-uint32
-dhd_prot_metadatalen_set(dhd_pub_t *dhd, uint32 val, bool rx)
-{
-	dhd_prot_t *prot = dhd->prot;
-	if (rx)
-		prot->rx_metadata_offset = (uint16)val;
-	else
-		prot->tx_metadata_offset = (uint16)val;
-	return dhd_prot_metadatalen_get(dhd, rx);
-}
-
-uint32
-dhd_prot_metadatalen_get(dhd_pub_t *dhd, bool rx)
-{
-	dhd_prot_t *prot = dhd->prot;
-	if (rx)
-		return prot->rx_metadata_offset;
-	else
-		return prot->tx_metadata_offset;
-}
-
-/** optimization to write "n" tx items at a time to ring */
-uint32
-dhd_prot_txp_threshold(dhd_pub_t *dhd, bool set, uint32 val)
-{
-	dhd_prot_t *prot = dhd->prot;
-	if (set)
-		prot->txp_threshold = (uint16)val;
-	val = prot->txp_threshold;
-	return val;
-}
-
-#ifdef DHD_RX_CHAINING
-
-static INLINE void BCMFASTPATH
-dhd_rxchain_reset(rxchain_info_t *rxchain)
-{
-	rxchain->pkt_count = 0;
-}
-
-static void BCMFASTPATH
-dhd_rxchain_frame(dhd_pub_t *dhd, void *pkt, uint ifidx)
-{
-	uint8 *eh;
-	uint8 prio;
-	dhd_prot_t *prot = dhd->prot;
-	rxchain_info_t *rxchain = &prot->rxchain;
-
-	ASSERT(!PKTISCHAINED(pkt));
-	ASSERT(PKTCLINK(pkt) == NULL);
-	ASSERT(PKTCGETATTR(pkt) == 0);
-
-	eh = PKTDATA(dhd->osh, pkt);
-	prio = IP_TOS46(eh + ETHER_HDR_LEN) >> IPV4_TOS_PREC_SHIFT;
-
-	if (rxchain->pkt_count && !(PKT_CTF_CHAINABLE(dhd, ifidx, eh, prio, rxchain->h_sa,
-		rxchain->h_da, rxchain->h_prio))) {
-		/* Different flow - First release the existing chain */
-		dhd_rxchain_commit(dhd);
-	}
-
-	/* For routers, with HNDCTF, link the packets using PKTSETCLINK, */
-	/* so that the chain can be handed off to CTF bridge as is. */
-	if (rxchain->pkt_count == 0) {
-		/* First packet in chain */
-		rxchain->pkthead = rxchain->pkttail = pkt;
-
-		/* Keep a copy of ptr to ether_da, ether_sa and prio */
-		rxchain->h_da = ((struct ether_header *)eh)->ether_dhost;
-		rxchain->h_sa = ((struct ether_header *)eh)->ether_shost;
-		rxchain->h_prio = prio;
-		rxchain->ifidx = ifidx;
-		rxchain->pkt_count++;
-	} else {
-		/* Same flow - keep chaining */
-		PKTSETCLINK(rxchain->pkttail, pkt);
-		rxchain->pkttail = pkt;
-		rxchain->pkt_count++;
-	}
-
-	if ((!ETHER_ISMULTI(rxchain->h_da)) &&
-		((((struct ether_header *)eh)->ether_type == HTON16(ETHER_TYPE_IP)) ||
-		(((struct ether_header *)eh)->ether_type == HTON16(ETHER_TYPE_IPV6)))) {
-		PKTSETCHAINED(dhd->osh, pkt);
-		PKTCINCRCNT(rxchain->pkthead);
-		PKTCADDLEN(rxchain->pkthead, PKTLEN(dhd->osh, pkt));
-	} else {
-		dhd_rxchain_commit(dhd);
-		return;
-	}
-
-	/* If we have hit the max chain length, dispatch the chain and reset */
-	if (rxchain->pkt_count >= DHD_PKT_CTF_MAX_CHAIN_LEN) {
-		dhd_rxchain_commit(dhd);
-	}
-}
-
-static void BCMFASTPATH
-dhd_rxchain_commit(dhd_pub_t *dhd)
-{
-	dhd_prot_t *prot = dhd->prot;
-	rxchain_info_t *rxchain = &prot->rxchain;
-
-	if (rxchain->pkt_count == 0)
-		return;
-
-	/* Release the packets to dhd_linux */
-	dhd_bus_rx_frame(dhd->bus, rxchain->pkthead, rxchain->ifidx, rxchain->pkt_count);
-
-	/* Reset the chain */
-	dhd_rxchain_reset(rxchain);
-}
-
-#endif /* DHD_RX_CHAINING */
diff --git a/drivers/net/wireless/bcmdhd/dhd_pcie.c b/drivers/net/wireless/bcmdhd/dhd_pcie.c
deleted file mode 100644
index 7577b8e..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_pcie.c
+++ /dev/null
@@ -1,5699 +0,0 @@
-/*
- * DHD Bus Module for PCIE
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_pcie.c 609007 2015-12-30 07:44:52Z $
- */
-
-
-/* include files */
-#include <typedefs.h>
-#include <bcmutils.h>
-#include <bcmdevs.h>
-#include <siutils.h>
-#include <hndsoc.h>
-#include <hndpmu.h>
-#include <sbchipc.h>
-#include <hnd_armtrap.h>
-#if defined(DHD_DEBUG)
-#include <hnd_cons.h>
-#endif /* defined(DHD_DEBUG) */
-#include <dngl_stats.h>
-#include <pcie_core.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_flowring.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#include <dhdioctl.h>
-#include <sdiovar.h>
-#include <bcmmsgbuf.h>
-#include <pcicfg.h>
-#include <dhd_pcie.h>
-#include <bcmpcie.h>
-#include <bcmendian.h>
-#ifdef DHDTCPACK_SUPPRESS
-#include <dhd_ip.h>
-#endif /* DHDTCPACK_SUPPRESS */
-
-#ifdef BCMEMBEDIMAGE
-#include BCMEMBEDIMAGE
-#endif /* BCMEMBEDIMAGE */
-
-#ifdef PCIE_OOB
-#include "ftdi_sio_external.h"
-#endif /* PCIE_OOB */
-
-#define MEMBLOCK	2048		/* Block size used for downloading of dongle image */
-#define MAX_WKLK_IDLE_CHECK	3	/* times wake_lock checked before deciding not to suspend */
-
-#define ARMCR4REG_BANKIDX	(0x40/sizeof(uint32))
-#define ARMCR4REG_BANKPDA	(0x4C/sizeof(uint32))
-/* Temporary war to fix precommit till sync issue between trunk & precommit branch is resolved */
-
-#if defined(SUPPORT_MULTIPLE_BOARD_REV)
-	extern unsigned int system_rev;
-#endif /* SUPPORT_MULTIPLE_BOARD_REV */
-
-int dhd_dongle_memsize;
-int dhd_dongle_ramsize;
-static int dhdpcie_checkdied(dhd_bus_t *bus, char *data, uint size);
-#ifdef DHD_DEBUG
-static int dhdpcie_bus_readconsole(dhd_bus_t *bus);
-#endif /* DHD_DEBUG */
-#if defined(DHD_FW_COREDUMP)
-static int dhdpcie_mem_dump(dhd_bus_t *bus);
-#endif /* DHD_FW_COREDUMP */
-
-static int dhdpcie_bus_membytes(dhd_bus_t *bus, bool write, ulong address, uint8 *data, uint size);
-static int dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid,
-	const char *name, void *params,
-	int plen, void *arg, int len, int val_size);
-static int dhdpcie_bus_lpback_req(struct  dhd_bus *bus, uint32 intval);
-static int dhdpcie_bus_dmaxfer_req(struct  dhd_bus *bus,
-	uint32 len, uint32 srcdelay, uint32 destdelay);
-static int dhdpcie_bus_download_state(dhd_bus_t *bus, bool enter);
-static int _dhdpcie_download_firmware(struct dhd_bus *bus);
-static int dhdpcie_download_firmware(dhd_bus_t *bus, osl_t *osh);
-static int dhdpcie_bus_write_vars(dhd_bus_t *bus);
-static bool dhdpcie_bus_process_mailbox_intr(dhd_bus_t *bus, uint32 intstatus);
-static bool dhdpci_bus_read_frames(dhd_bus_t *bus);
-static int dhdpcie_readshared(dhd_bus_t *bus);
-static void dhdpcie_init_shared_addr(dhd_bus_t *bus);
-static bool dhdpcie_dongle_attach(dhd_bus_t *bus);
-static void dhdpcie_bus_dongle_setmemsize(dhd_bus_t *bus, int mem_size);
-static void dhdpcie_bus_release_dongle(dhd_bus_t *bus, osl_t *osh,
-	bool dongle_isolation, bool reset_flag);
-static void dhdpcie_bus_release_malloc(dhd_bus_t *bus, osl_t *osh);
-static int dhdpcie_downloadvars(dhd_bus_t *bus, void *arg, int len);
-static uint8 dhdpcie_bus_rtcm8(dhd_bus_t *bus, ulong offset);
-static void dhdpcie_bus_wtcm8(dhd_bus_t *bus, ulong offset, uint8 data);
-static void dhdpcie_bus_wtcm16(dhd_bus_t *bus, ulong offset, uint16 data);
-static uint16 dhdpcie_bus_rtcm16(dhd_bus_t *bus, ulong offset);
-static void dhdpcie_bus_wtcm32(dhd_bus_t *bus, ulong offset, uint32 data);
-static uint32 dhdpcie_bus_rtcm32(dhd_bus_t *bus, ulong offset);
-static void dhdpcie_bus_wtcm64(dhd_bus_t *bus, ulong offset, uint64 data);
-static uint64 dhdpcie_bus_rtcm64(dhd_bus_t *bus, ulong offset);
-static void dhdpcie_bus_cfg_set_bar0_win(dhd_bus_t *bus, uint32 data);
-static void dhdpcie_bus_reg_unmap(osl_t *osh, ulong addr, int size);
-static int dhdpcie_cc_nvmshadow(dhd_bus_t *bus, struct bcmstrbuf *b);
-static void dhdpcie_send_mb_data(dhd_bus_t *bus, uint32 h2d_mb_data);
-static void dhd_fillup_ring_sharedptr_info(dhd_bus_t *bus, ring_info_t *ring_info);
-extern void dhd_dpc_kill(dhd_pub_t *dhdp);
-
-#ifdef BCMEMBEDIMAGE
-static int dhdpcie_download_code_array(dhd_bus_t *bus);
-#endif /* BCMEMBEDIMAGE */
-
-
-#ifdef EXYNOS_PCIE_DEBUG
-extern void exynos_pcie_register_dump(int ch_num);
-#endif /* EXYNOS_PCIE_DEBUG */
-
-#define     PCI_VENDOR_ID_BROADCOM          0x14e4
-
-static void dhd_bus_set_device_wake(struct dhd_bus *bus, bool val);
-extern void wl_nddbg_wpp_log(const char *format, ...);
-#ifdef PCIE_OOB
-static void dhd_bus_doorbell_timeout_reset(struct dhd_bus *bus);
-
-#define DHD_DEFAULT_DOORBELL_TIMEOUT 200	/* ms */
-static uint dhd_doorbell_timeout = DHD_DEFAULT_DOORBELL_TIMEOUT;
-
-#define HOST_WAKE 4   /* GPIO_0 (HOST_WAKE) - Output from WLAN */
-#define DEVICE_WAKE 5  /* GPIO_1 (DEVICE_WAKE) - Input to WLAN */
-#define BIT_WL_REG_ON 6
-#define BIT_BT_REG_ON 7
-
-int gpio_handle_val = 0;
-unsigned char gpio_port = 0;
-unsigned char gpio_direction = 0;
-#define OOB_PORT "ttyUSB0"
-#endif /* PCIE_OOB */
-static bool dhdpcie_check_firmware_compatible(uint32 f_api_version, uint32 h_api_version);
-
-/* IOVar table */
-enum {
-	IOV_INTR = 1,
-	IOV_MEMBYTES,
-	IOV_MEMSIZE,
-	IOV_SET_DOWNLOAD_STATE,
-	IOV_DEVRESET,
-	IOV_VARS,
-	IOV_MSI_SIM,
-	IOV_PCIE_LPBK,
-	IOV_CC_NVMSHADOW,
-	IOV_RAMSIZE,
-	IOV_RAMSTART,
-	IOV_SLEEP_ALLOWED,
-	IOV_PCIE_DMAXFER,
-	IOV_PCIE_SUSPEND,
-	IOV_PCIEREG,
-	IOV_PCIECFGREG,
-	IOV_PCIECOREREG,
-	IOV_PCIESERDESREG,
-	IOV_BAR0_SECWIN_REG,
-	IOV_SBREG,
-	IOV_DONGLEISOLATION,
-	IOV_LTRSLEEPON_UNLOOAD,
-	IOV_METADATA_DBG,
-	IOV_RX_METADATALEN,
-	IOV_TX_METADATALEN,
-	IOV_TXP_THRESHOLD,
-	IOV_BUZZZ_DUMP,
-	IOV_DUMP_RINGUPD_BLOCK,
-	IOV_DMA_RINGINDICES,
-	IOV_DB1_FOR_MB,
-	IOV_FLOW_PRIO_MAP,
-#ifdef DHD_PCIE_RUNTIMEPM
-	IOV_IDLETIME,
-#endif /* DHD_PCIE_RUNTIMEPM */
-	IOV_RXBOUND,
-	IOV_TXBOUND,
-	IOV_HANGREPORT,
-#ifdef PCIE_OOB
-	IOV_OOB_BT_REG_ON,
-	IOV_OOB_ENABLE
-#endif /* PCIE_OOB */
-};
-
-
-const bcm_iovar_t dhdpcie_iovars[] = {
-	{"intr",	IOV_INTR,	0,	IOVT_BOOL,	0 },
-	{"membytes",	IOV_MEMBYTES,	0,	IOVT_BUFFER,	2 * sizeof(int) },
-	{"memsize",	IOV_MEMSIZE,	0,	IOVT_UINT32,	0 },
-	{"dwnldstate",	IOV_SET_DOWNLOAD_STATE,	0,	IOVT_BOOL,	0 },
-	{"vars",	IOV_VARS,	0,	IOVT_BUFFER,	0 },
-	{"devreset",	IOV_DEVRESET,	0,	IOVT_BOOL,	0 },
-	{"pcie_lpbk",	IOV_PCIE_LPBK,	0,	IOVT_UINT32,	0 },
-	{"cc_nvmshadow", IOV_CC_NVMSHADOW, 0, IOVT_BUFFER, 0 },
-	{"ramsize",	IOV_RAMSIZE,	0,	IOVT_UINT32,	0 },
-	{"ramstart",	IOV_RAMSTART,	0,	IOVT_UINT32,	0 },
-	{"pciereg",	IOV_PCIEREG,	0,	IOVT_BUFFER,	2 * sizeof(int32) },
-	{"pciecfgreg",	IOV_PCIECFGREG,	0,	IOVT_BUFFER,	2 * sizeof(int32) },
-	{"pciecorereg",	IOV_PCIECOREREG,	0,	IOVT_BUFFER,	2 * sizeof(int32) },
-	{"pcieserdesreg",	IOV_PCIESERDESREG,	0,	IOVT_BUFFER,	3 * sizeof(int32) },
-	{"bar0secwinreg",	IOV_BAR0_SECWIN_REG,	0,	IOVT_BUFFER,	sizeof(sdreg_t) },
-	{"sbreg",	IOV_SBREG,	0,	IOVT_BUFFER,	sizeof(sdreg_t) },
-	{"pcie_dmaxfer",	IOV_PCIE_DMAXFER,	0,	IOVT_BUFFER,	3 * sizeof(int32) },
-	{"pcie_suspend", IOV_PCIE_SUSPEND,	0,	IOVT_UINT32,	0 },
-#ifdef PCIE_OOB
-	{"oob_bt_reg_on", IOV_OOB_BT_REG_ON,    0,  IOVT_UINT32,    0 },
-	{"oob_enable",   IOV_OOB_ENABLE,    0,  IOVT_UINT32,    0 },
-#endif /* PCIE_OOB */
-	{"sleep_allowed",	IOV_SLEEP_ALLOWED,	0,	IOVT_BOOL,	0 },
-	{"dngl_isolation", IOV_DONGLEISOLATION,	0,	IOVT_UINT32,	0 },
-	{"ltrsleep_on_unload", IOV_LTRSLEEPON_UNLOOAD,	0,	IOVT_UINT32,	0 },
-	{"dump_ringupdblk", IOV_DUMP_RINGUPD_BLOCK,	0,	IOVT_BUFFER,	0 },
-	{"dma_ring_indices", IOV_DMA_RINGINDICES,	0,	IOVT_UINT32,	0},
-	{"metadata_dbg", IOV_METADATA_DBG,	0,	IOVT_BOOL,	0 },
-	{"rx_metadata_len", IOV_RX_METADATALEN,	0,	IOVT_UINT32,	0 },
-	{"tx_metadata_len", IOV_TX_METADATALEN,	0,	IOVT_UINT32,	0 },
-	{"db1_for_mb", IOV_DB1_FOR_MB,	0,	IOVT_UINT32,	0 },
-	{"txp_thresh", IOV_TXP_THRESHOLD,	0,	IOVT_UINT32,	0 },
-	{"buzzz_dump", IOV_BUZZZ_DUMP,		0,	IOVT_UINT32,	0 },
-	{"flow_prio_map", IOV_FLOW_PRIO_MAP,	0,	IOVT_UINT32,	0 },
-#ifdef DHD_PCIE_RUNTIMEPM
-	{"idletime",    IOV_IDLETIME,   0,      IOVT_INT32,     0 },
-#endif /* DHD_PCIE_RUNTIMEPM */
-	{"rxbound",     IOV_RXBOUND,    0,      IOVT_UINT32,    0 },
-	{"txbound",     IOV_TXBOUND,    0,      IOVT_UINT32,    0 },
-	{"fw_hang_report", IOV_HANGREPORT,	0,	IOVT_BOOL,	0 },
-	{NULL, 0, 0, 0, 0 }
-};
-
-
-#define MAX_READ_TIMEOUT	5 * 1000 * 1000
-
-#ifndef DHD_RXBOUND
-#define DHD_RXBOUND		64
-#endif
-#ifndef DHD_TXBOUND
-#define DHD_TXBOUND		64
-#endif
-uint dhd_rxbound = DHD_RXBOUND;
-uint dhd_txbound = DHD_TXBOUND;
-
-/* Register/Unregister functions are called by the main DHD entry
- * point (e.g. module insertion) to link with the bus driver, in
- * order to look for or await the device.
- */
-
-int
-dhd_bus_register(void)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	return dhdpcie_bus_register();
-}
-
-void
-dhd_bus_unregister(void)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	dhdpcie_bus_unregister();
-	return;
-}
-
-
-/** returns a host virtual address */
-uint32 *
-dhdpcie_bus_reg_map(osl_t *osh, ulong addr, int size)
-{
-	return (uint32 *)REG_MAP(addr, size);
-}
-
-void
-dhdpcie_bus_reg_unmap(osl_t *osh, ulong addr, int size)
-{
-	REG_UNMAP((void*)(uintptr)addr);
-	return;
-}
-
-/**
- * 'regs' is the host virtual address that maps to the start of the PCIe BAR0 window. The first 4096
- * bytes in this window are mapped to the backplane address in the PCIEBAR0Window register. The
- * precondition is that the PCIEBAR0Window register 'points' at the PCIe core.
- *
- * 'tcm' is the *host* virtual address at which tcm is mapped.
- */
-dhd_bus_t* dhdpcie_bus_attach(osl_t *osh,
-	volatile char *regs, volatile char *tcm, void *pci_dev)
-{
-	dhd_bus_t *bus;
-
-	DHD_TRACE(("%s: ENTER\n", __FUNCTION__));
-
-	do {
-		if (!(bus = MALLOCZ(osh, sizeof(dhd_bus_t)))) {
-			DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
-			break;
-		}
-
-		bus->regs = regs;
-		bus->tcm = tcm;
-		bus->osh = osh;
-		/* Save pci_dev into dhd_bus, as it may be needed in dhd_attach */
-		bus->dev = (struct pci_dev *)pci_dev;
-
-		dll_init(&bus->const_flowring);
-
-		/* Attach pcie shared structure */
-		if (!(bus->pcie_sh = MALLOCZ(osh, sizeof(pciedev_shared_t)))) {
-			DHD_ERROR(("%s: MALLOC of bus->pcie_sh failed\n", __FUNCTION__));
-			break;
-		}
-
-		/* dhd_common_init(osh); */
-
-		if (dhdpcie_dongle_attach(bus)) {
-			DHD_ERROR(("%s: dhdpcie_probe_attach failed\n", __FUNCTION__));
-			break;
-		}
-
-		/* software resources */
-		if (!(bus->dhd = dhd_attach(osh, bus, PCMSGBUF_HDRLEN))) {
-			DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
-
-			break;
-		}
-		bus->dhd->busstate = DHD_BUS_DOWN;
-		bus->db1_for_mb = TRUE;
-		bus->dhd->hang_report = TRUE;
-		bus->irq_registered = FALSE;
-
-		bus->d3_ack_war_cnt = 0;
-
-		DHD_TRACE(("%s: EXIT SUCCESS\n",
-			__FUNCTION__));
-
-		return bus;
-	} while (0);
-
-	DHD_TRACE(("%s: EXIT FAILURE\n", __FUNCTION__));
-
-	if (bus && bus->pcie_sh) {
-		MFREE(osh, bus->pcie_sh, sizeof(pciedev_shared_t));
-	}
-
-	if (bus) {
-		MFREE(osh, bus, sizeof(dhd_bus_t));
-	}
-	return NULL;
-}
-
-uint
-dhd_bus_chip(struct dhd_bus *bus)
-{
-	ASSERT(bus->sih != NULL);
-	return bus->sih->chip;
-}
-
-uint
-dhd_bus_chiprev(struct dhd_bus *bus)
-{
-	ASSERT(bus);
-	ASSERT(bus->sih != NULL);
-	return bus->sih->chiprev;
-}
-
-void *
-dhd_bus_pub(struct dhd_bus *bus)
-{
-	return bus->dhd;
-}
-
-void *
-dhd_bus_sih(struct dhd_bus *bus)
-{
-	return (void *)bus->sih;
-}
-
-void *
-dhd_bus_txq(struct dhd_bus *bus)
-{
-	return &bus->txq;
-}
-
-/** Get Chip ID version */
-uint dhd_bus_chip_id(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	return  bus->sih->chip;
-}
-
-/** Get Chip Rev ID version */
-uint dhd_bus_chiprev_id(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	return bus->sih->chiprev;
-}
-
-/** Get Chip Pkg ID version */
-uint dhd_bus_chippkg_id(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	return bus->sih->chippkg;
-}
-
-/** Read and clear intstatus. This should be called with interupts disabled or inside isr */
-uint32
-dhdpcie_bus_intstatus(dhd_bus_t *bus)
-{
-	uint32 intstatus = 0;
-	uint32 intmask = 0;
-
-	if ((bus->sih->buscorerev == 6) || (bus->sih->buscorerev == 4) ||
-		(bus->sih->buscorerev == 2)) {
-		intstatus = dhdpcie_bus_cfg_read_dword(bus, PCIIntstatus, 4);
-		dhdpcie_bus_cfg_write_dword(bus, PCIIntstatus, 4, intstatus);
-		intstatus &= I_MB;
-	} else {
-		/* this is a PCIE core register..not a config register... */
-		intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, 0, 0);
-
-		/* this is a PCIE core register..not a config register... */
-		intmask = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask, 0, 0);
-
-		/*
-		 * The fourth argument to si_corereg is the "mask" fields of the register to update
-		 * and the fifth field is the "value" to update. Now if we are interested in only
-		 * few fields of the "mask" bit map, we should not be writing back what we read
-		 * By doing so, we might clear/ack interrupts that are not handled yet.
-		 */
-		si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, bus->def_intmask,
-			intstatus);
-
-		intstatus &= intmask;
-
-		/* Is device removed. intstatus & intmask read 0xffffffff */
-		if (intstatus == (uint32)-1) {
-			DHD_ERROR(("%s: !!!!!!Device Removed or dead chip.\n", __FUNCTION__));
-			intstatus = 0;
-#ifdef CUSTOMER_HW4_DEBUG
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-			bus->dhd->hang_reason = HANG_REASON_PCIE_LINK_DOWN;
-			dhd_os_send_hang_message(bus->dhd);
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */
-#endif /* CUSTOMER_HW4_DEBUG */
-		}
-
-		intstatus &= bus->def_intmask;
-	}
-
-	return intstatus;
-}
-
-/**
- * Name:  dhdpcie_bus_isr
- * Parameters:
- * 1: IN int irq   -- interrupt vector
- * 2: IN void *arg      -- handle to private data structure
- * Return value:
- * Status (TRUE or FALSE)
- *
- * Description:
- * Interrupt Service routine checks for the status register,
- * disable interrupt and queue DPC if mail box interrupts are raised.
- */
-int32
-dhdpcie_bus_isr(dhd_bus_t *bus)
-{
-	uint32 intstatus = 0;
-
-	do {
-		DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-		/* verify argument */
-		if (!bus) {
-			DHD_ERROR(("%s : bus is null pointer, exit \n", __FUNCTION__));
-			break;
-		}
-
-		if (bus->dhd->dongle_reset) {
-			break;
-		}
-
-		if (bus->dhd->busstate == DHD_BUS_DOWN) {
-			DHD_ERROR(("%s: BUS is down, not processing the interrupt \r\n",
-				__FUNCTION__));
-			break;
-		}
-
-		intstatus = dhdpcie_bus_intstatus(bus);
-
-		/* Check if the interrupt is ours or not */
-		if (intstatus == 0) {
-			break;
-		}
-
-		/* save the intstatus */
-		bus->intstatus = intstatus;
-
-		/*  Overall operation:
-		 *    - Mask further interrupts
-		 *    - Read/ack intstatus
-		 *    - Take action based on bits and state
-		 *    - Reenable interrupts (as per state)
-		 */
-
-		/* Count the interrupt call */
-		bus->intrcount++;
-
-		/* read interrupt status register!! Status bits will be cleared in DPC !! */
-		bus->ipend = TRUE;
-		dhdpcie_bus_intr_disable(bus); /* Disable interrupt!! */
-		bus->intdis = TRUE;
-
-#if defined(PCIE_ISR_THREAD)
-
-		DHD_TRACE(("Calling dhd_bus_dpc() from %s\n", __FUNCTION__));
-		DHD_OS_WAKE_LOCK(bus->dhd);
-		while (dhd_bus_dpc(bus));
-		DHD_OS_WAKE_UNLOCK(bus->dhd);
-#else
-		bus->dpc_sched = TRUE;
-		dhd_sched_dpc(bus->dhd);     /* queue DPC now!! */
-#endif /* defined(SDIO_ISR_THREAD) */
-
-		DHD_TRACE(("%s: Exit Success DPC Queued\n", __FUNCTION__));
-		return TRUE;
-
-	} while (0);
-
-	DHD_TRACE(("%s: Exit Failure\n", __FUNCTION__));
-	return FALSE;
-}
-
-#ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY
-dhd_pub_t *link_recovery = NULL;
-#endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */
-static bool
-dhdpcie_dongle_attach(dhd_bus_t *bus)
-{
-
-	osl_t *osh = bus->osh;
-	void *regsva = (void*)bus->regs;
-	uint16 devid = bus->cl_devid;
-	uint32 val;
-	sbpcieregs_t *sbpcieregs;
-
-	DHD_TRACE(("%s: ENTER\n", __FUNCTION__));
-
-#ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY
-	link_recovery = bus->dhd;
-#endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */
-
-	bus->alp_only = TRUE;
-	bus->sih = NULL;
-
-	/* Set bar0 window to si_enum_base */
-	dhdpcie_bus_cfg_set_bar0_win(bus, SI_ENUM_BASE);
-
-	/* Checking PCIe bus status with reading configuration space */
-	val = OSL_PCI_READ_CONFIG(osh, PCI_CFG_VID, sizeof(uint32));
-	if ((val & 0xFFFF) != VENDOR_BROADCOM) {
-		DHD_ERROR(("%s : failed to read PCI configuration space!\n", __FUNCTION__));
-		goto fail;
-	}
-
-	/* si_attach() will provide an SI handle and scan the backplane */
-	if (!(bus->sih = si_attach((uint)devid, osh, regsva, PCI_BUS, bus,
-	                           &bus->vars, &bus->varsz))) {
-		DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__));
-		goto fail;
-	}
-
-
-	si_setcore(bus->sih, PCIE2_CORE_ID, 0);
-	sbpcieregs = (sbpcieregs_t*)(bus->regs);
-
-	/* WAR where the BAR1 window may not be sized properly */
-	W_REG(osh, &sbpcieregs->configaddr, 0x4e0);
-	val = R_REG(osh, &sbpcieregs->configdata);
-	W_REG(osh, &sbpcieregs->configdata, val);
-
-	/* Get info on the ARM and SOCRAM cores... */
-	/* Should really be qualified by device id */
-	if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) ||
-	    (si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) ||
-	    (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) ||
-	    (si_setcore(bus->sih, ARMCA7_CORE_ID, 0))) {
-		bus->armrev = si_corerev(bus->sih);
-	} else {
-		DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__));
-		goto fail;
-	}
-
-	if (si_setcore(bus->sih, SYSMEM_CORE_ID, 0)) {
-		if (!(bus->orig_ramsize = si_sysmem_size(bus->sih))) {
-			DHD_ERROR(("%s: failed to find SYSMEM memory!\n", __FUNCTION__));
-			goto fail;
-		}
-		/* also populate base address */
-		bus->dongle_ram_base = CA7_4365_RAM_BASE;
-	} else if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
-		if (!(bus->orig_ramsize = si_socram_size(bus->sih))) {
-			DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__));
-			goto fail;
-		}
-	} else {
-		/* cr4 has a different way to find the RAM size from TCM's */
-		if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) {
-			DHD_ERROR(("%s: failed to find CR4-TCM memory!\n", __FUNCTION__));
-			goto fail;
-		}
-		/* also populate base address */
-		switch ((uint16)bus->sih->chip) {
-		case BCM4339_CHIP_ID:
-		case BCM4335_CHIP_ID:
-			bus->dongle_ram_base = CR4_4335_RAM_BASE;
-			break;
-		case BCM4358_CHIP_ID:
-		case BCM4356_CHIP_ID:
-		case BCM4354_CHIP_ID:
-		case BCM43567_CHIP_ID:
-		case BCM43569_CHIP_ID:
-		case BCM4350_CHIP_ID:
-		case BCM43570_CHIP_ID:
-			bus->dongle_ram_base = CR4_4350_RAM_BASE;
-			break;
-		case BCM4360_CHIP_ID:
-			bus->dongle_ram_base = CR4_4360_RAM_BASE;
-			break;
-		CASE_BCM4345_CHIP:
-			bus->dongle_ram_base = (bus->sih->chiprev < 6)  /* changed at 4345C0 */
-				? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
-			break;
-		CASE_BCM43602_CHIP:
-			bus->dongle_ram_base = CR4_43602_RAM_BASE;
-			break;
-		case BCM4349_CHIP_GRPID:
-			/* RAM base changed from 4349c0(revid=9) onwards */
-			bus->dongle_ram_base = ((bus->sih->chiprev < 9) ?
-			CR4_4349_RAM_BASE : CR4_4349_RAM_BASE_FROM_REV_9);
-			break;
-		default:
-			bus->dongle_ram_base = 0;
-			DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n",
-			           __FUNCTION__, bus->dongle_ram_base));
-		}
-	}
-	bus->ramsize = bus->orig_ramsize;
-	if (dhd_dongle_memsize)
-		dhdpcie_bus_dongle_setmemsize(bus, dhd_dongle_memsize);
-
-	DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n",
-	           bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base));
-
-	bus->srmemsize = si_socram_srmem_size(bus->sih);
-
-
-	bus->def_intmask = PCIE_MB_D2H_MB_MASK | PCIE_MB_TOPCIE_FN0_0 | PCIE_MB_TOPCIE_FN0_1;
-
-	/* Set the poll and/or interrupt flags */
-	bus->intr = (bool)dhd_intr;
-
-	bus->wait_for_d3_ack = 1;
-	bus->suspended = FALSE;
-
-#ifdef PCIE_OOB
-	gpio_handle_val = get_handle(OOB_PORT);
-	if (gpio_handle_val < 0)
-	{
-		DHD_ERROR(("%s: Could not get GPIO handle.\n", __FUNCTION__));
-		ASSERT(FALSE);
-	}
-
-	gpio_direction = 0;
-	ftdi_set_bitmode(gpio_handle_val, 0, BITMODE_BITBANG);
-
-	/* Note BT core is also enabled here */
-	gpio_port = 1 << BIT_WL_REG_ON | 1 << BIT_BT_REG_ON | 1 << DEVICE_WAKE;
-	gpio_write_port(gpio_handle_val, gpio_port);
-
-	gpio_direction = 1 << BIT_WL_REG_ON | 1 << BIT_BT_REG_ON | 1 << DEVICE_WAKE;
-	ftdi_set_bitmode(gpio_handle_val, gpio_direction, BITMODE_BITBANG);
-
-	bus->oob_enabled = TRUE;
-
-	/* drive the Device_Wake GPIO low on startup */
-	bus->device_wake_state = TRUE;
-	dhd_bus_set_device_wake(bus, FALSE);
-	dhd_bus_doorbell_timeout_reset(bus);
-#endif /* PCIE_OOB */
-
-	DHD_TRACE(("%s: EXIT: SUCCESS\n", __FUNCTION__));
-	return 0;
-
-fail:
-	if (bus->sih != NULL) {
-		si_detach(bus->sih);
-		bus->sih = NULL;
-	}
-	DHD_TRACE(("%s: EXIT: FAILURE\n", __FUNCTION__));
-	return -1;
-}
-
-int
-dhpcie_bus_unmask_interrupt(dhd_bus_t *bus)
-{
-	dhdpcie_bus_cfg_write_dword(bus, PCIIntmask, 4, I_MB);
-	return 0;
-}
-int
-dhpcie_bus_mask_interrupt(dhd_bus_t *bus)
-{
-	dhdpcie_bus_cfg_write_dword(bus, PCIIntmask, 4, 0x0);
-	return 0;
-}
-
-void
-dhdpcie_bus_intr_enable(dhd_bus_t *bus)
-{
-	DHD_TRACE(("enable interrupts\n"));
-	if (bus && bus->sih && !bus->is_linkdown) {
-		if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
-			(bus->sih->buscorerev == 4)) {
-			dhpcie_bus_unmask_interrupt(bus);
-		} else {
-		si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask,
-			bus->def_intmask, bus->def_intmask);
-		}
-	} else {
-		DHD_ERROR(("****** %s: failed ******\n", __FUNCTION__));
-		DHD_ERROR(("bus: %p sih: %p bus->is_linkdown %d\n",
-				bus, bus ? bus->sih : NULL, bus ? bus->is_linkdown: -1));
-	}
-}
-
-void
-dhdpcie_bus_intr_disable(dhd_bus_t *bus)
-{
-
-	DHD_TRACE(("%s Enter\n", __FUNCTION__));
-
-	if (bus && bus->sih && !bus->is_linkdown) {
-		if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
-			(bus->sih->buscorerev == 4)) {
-			dhpcie_bus_mask_interrupt(bus);
-		} else {
-			si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask,
-				bus->def_intmask, 0);
-		}
-	} else {
-		DHD_ERROR(("****** %s: failed ******\n", __FUNCTION__));
-		DHD_ERROR(("bus: %p sih: %p bus->is_linkdown %d\n",
-				bus, bus ? bus->sih : NULL, bus ? bus->is_linkdown: -1));
-	}
-
-	DHD_TRACE(("%s Exit\n", __FUNCTION__));
-}
-
-/*
- *  dhdpcie_advertise_bus_cleanup advertises that clean up is under progress
- * to other bus user contexts like Tx, Rx, IOVAR, WD etc and it waits for other contexts
- * to gracefully exit. All the bus usage contexts before marking busstate as busy, will check for
- * whether the busstate is DHD_BUS_DOWN or DHD_BUS_DOWN_IN_PROGRESS, if so
- * they will exit from there itself without marking dhd_bus_busy_state as BUSY.
- */
-static void
-dhdpcie_advertise_bus_cleanup(dhd_pub_t	 *dhdp)
-{
-	unsigned long flags;
-	int timeleft;
-
-	DHD_GENERAL_LOCK(dhdp, flags);
-	dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS;
-	DHD_GENERAL_UNLOCK(dhdp, flags);
-
-	timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
-	if (timeleft == 0) {
-		DHD_ERROR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
-				__FUNCTION__, dhdp->dhd_bus_busy_state));
-		BUG_ON(1);
-	}
-
-	return;
-}
-
-static void
-dhdpcie_bus_remove_prep(dhd_bus_t *bus)
-{
-	unsigned long flags;
-	DHD_TRACE(("%s Enter\n", __FUNCTION__));
-
-	DHD_GENERAL_LOCK(bus->dhd, flags);
-	bus->dhd->busstate = DHD_BUS_DOWN;
-	DHD_GENERAL_UNLOCK(bus->dhd, flags);
-
-	dhd_os_sdlock(bus->dhd);
-
-	dhdpcie_bus_intr_disable(bus);
-	if (!bus->dhd->dongle_isolation) {
-		pcie_watchdog_reset(bus->osh, bus->sih, (sbpcieregs_t *)(bus->regs));
-	}
-
-	dhd_os_sdunlock(bus->dhd);
-
-	DHD_TRACE(("%s Exit\n", __FUNCTION__));
-}
-
-/** Detach and free everything */
-void
-dhdpcie_bus_release(dhd_bus_t *bus)
-{
-	bool dongle_isolation = FALSE;
-	osl_t *osh = NULL;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (bus) {
-
-		osh = bus->osh;
-		ASSERT(osh);
-
-		if (bus->dhd) {
-			dhdpcie_advertise_bus_cleanup(bus->dhd);
-			dongle_isolation = bus->dhd->dongle_isolation;
-			dhdpcie_bus_remove_prep(bus);
-
-			if (bus->intr) {
-				dhdpcie_bus_intr_disable(bus);
-				dhdpcie_free_irq(bus);
-			}
-			dhdpcie_bus_release_dongle(bus, osh, dongle_isolation, TRUE);
-			dhd_detach(bus->dhd);
-			dhd_free(bus->dhd);
-			bus->dhd = NULL;
-		}
-
-		/* unmap the regs and tcm here!! */
-		if (bus->regs) {
-			dhdpcie_bus_reg_unmap(osh, (ulong)bus->regs, DONGLE_REG_MAP_SIZE);
-			bus->regs = NULL;
-		}
-		if (bus->tcm) {
-			dhdpcie_bus_reg_unmap(osh, (ulong)bus->tcm, DONGLE_TCM_MAP_SIZE);
-			bus->tcm = NULL;
-		}
-
-		dhdpcie_bus_release_malloc(bus, osh);
-		/* Detach pcie shared structure */
-		if (bus->pcie_sh) {
-			MFREE(osh, bus->pcie_sh, sizeof(pciedev_shared_t));
-			bus->pcie_sh = NULL;
-		}
-
-#ifdef DHD_DEBUG
-
-		if (bus->console.buf != NULL)
-			MFREE(osh, bus->console.buf, bus->console.bufsize);
-#endif
-
-
-		/* Finally free bus info */
-		MFREE(osh, bus, sizeof(dhd_bus_t));
-
-	}
-
-	DHD_TRACE(("%s: Exit\n", __FUNCTION__));
-} /* dhdpcie_bus_release */
-
-
-void
-dhdpcie_bus_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
-{
-	DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
-		bus->dhd, bus->dhd->dongle_reset));
-
-	if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag) {
-		DHD_TRACE(("%s Exit\n", __FUNCTION__));
-		return;
-	}
-
-	if (bus->sih) {
-
-		if (!dongle_isolation)
-			pcie_watchdog_reset(bus->osh, bus->sih, (sbpcieregs_t *)(bus->regs));
-
-		if (bus->ltrsleep_on_unload) {
-			si_corereg(bus->sih, bus->sih->buscoreidx,
-				OFFSETOF(sbpcieregs_t, u.pcie2.ltr_state), ~0, 0);
-		}
-
-		if (bus->sih->buscorerev == 13)
-			 pcie_serdes_iddqdisable(bus->osh, bus->sih, (sbpcieregs_t *)(bus->regs));
-
-		if (bus->sih != NULL) {
-			si_detach(bus->sih);
-			bus->sih = NULL;
-		}
-		if (bus->vars && bus->varsz)
-			MFREE(osh, bus->vars, bus->varsz);
-		bus->vars = NULL;
-	}
-
-	DHD_TRACE(("%s Exit\n", __FUNCTION__));
-}
-
-uint32
-dhdpcie_bus_cfg_read_dword(dhd_bus_t *bus, uint32 addr, uint32 size)
-{
-	uint32 data = OSL_PCI_READ_CONFIG(bus->osh, addr, size);
-	return data;
-}
-
-/** 32 bit config write */
-void
-dhdpcie_bus_cfg_write_dword(dhd_bus_t *bus, uint32 addr, uint32 size, uint32 data)
-{
-	OSL_PCI_WRITE_CONFIG(bus->osh, addr, size, data);
-}
-
-void
-dhdpcie_bus_cfg_set_bar0_win(dhd_bus_t *bus, uint32 data)
-{
-	OSL_PCI_WRITE_CONFIG(bus->osh, PCI_BAR0_WIN, 4, data);
-}
-
-void
-dhdpcie_bus_dongle_setmemsize(struct dhd_bus *bus, int mem_size)
-{
-	int32 min_size =  DONGLE_MIN_MEMSIZE;
-	/* Restrict the memsize to user specified limit */
-	DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
-		dhd_dongle_memsize, min_size));
-	if ((dhd_dongle_memsize > min_size) &&
-		(dhd_dongle_memsize < (int32)bus->orig_ramsize))
-		bus->ramsize = dhd_dongle_memsize;
-}
-
-void
-dhdpcie_bus_release_malloc(dhd_bus_t *bus, osl_t *osh)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (bus->dhd && bus->dhd->dongle_reset)
-		return;
-
-	if (bus->vars && bus->varsz) {
-		MFREE(osh, bus->vars, bus->varsz);
-		bus->vars = NULL;
-	}
-
-	DHD_TRACE(("%s: Exit\n", __FUNCTION__));
-	return;
-
-}
-
-/** Stop bus module: clear pending frames, disable data flow */
-void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
-{
-	uint32 status;
-	unsigned long flags;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (!bus->dhd)
-		return;
-
-	if (bus->dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s: already down by net_dev_reset\n", __FUNCTION__));
-		goto done;
-	}
-
-	DHD_DISABLE_RUNTIME_PM(bus->dhd);
-
-	DHD_GENERAL_LOCK(bus->dhd, flags);
-	bus->dhd->busstate = DHD_BUS_DOWN;
-	DHD_GENERAL_UNLOCK(bus->dhd, flags);
-
-	dhdpcie_bus_intr_disable(bus);
-	status =  dhdpcie_bus_cfg_read_dword(bus, PCIIntstatus, 4);
-	dhdpcie_bus_cfg_write_dword(bus, PCIIntstatus, 4, status);
-
-	if (!dhd_download_fw_on_driverload) {
-		dhd_dpc_kill(bus->dhd);
-	}
-
-	/* Clear rx control and wake any waiters */
-	dhd_os_set_ioctl_resp_timeout(IOCTL_DISABLE_TIMEOUT);
-	dhd_wakeup_ioctl_event(bus->dhd, IOCTL_RETURN_ON_BUS_STOP);
-
-done:
-	return;
-}
-
-/** Watchdog timer function */
-bool dhd_bus_watchdog(dhd_pub_t *dhd)
-{
-	unsigned long flags;
-#ifdef DHD_DEBUG
-	dhd_bus_t *bus;
-	bus = dhd->bus;
-
-	DHD_GENERAL_LOCK(dhd, flags);
-	if (dhd->busstate == DHD_BUS_DOWN ||
-			dhd->busstate == DHD_BUS_DOWN_IN_PROGRESS) {
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		return FALSE;
-	}
-	dhd->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_WD;
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-#ifdef DHD_PCIE_RUNTIMEPM
-	dhdpcie_runtime_bus_wake(dhd, TRUE, __builtin_return_address(0));
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-
-
-	/* Poll for console output periodically */
-	if (dhd->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
-		bus->console.count += dhd_watchdog_ms;
-		if (bus->console.count >= dhd_console_ms) {
-			bus->console.count -= dhd_console_ms;
-			/* Make sure backplane clock is on */
-			if (dhdpcie_bus_readconsole(bus) < 0)
-				dhd_console_ms = 0;	/* On error, stop trying */
-		}
-	}
-#endif /* DHD_DEBUG */
-
-#ifdef PCIE_OOB
-	/* If haven't communicated with device for a while, deassert the Device_Wake GPIO */
-	if (dhd_doorbell_timeout != 0 && !(bus->dhd->busstate == DHD_BUS_SUSPEND) &&
-		dhd_timeout_expired(&bus->doorbell_timer)) {
-		dhd_bus_set_device_wake(bus, FALSE);
-	}
-#endif /* PCIE_OOB */
-
-	DHD_GENERAL_LOCK(dhd, flags);
-	dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_WD;
-	DHD_GENERAL_UNLOCK(dhd, flags);
-
-	return TRUE;
-} /* dhd_bus_watchdog */
-
-
-#define DEADBEEF_PATTERN 0xADDEADDE	// "DeadDead"
-#define MEMCHECKINFO "/data/.memcheck.info"
-
-static int
-dhd_get_memcheck_info(void)
-{
-	struct file *fp = NULL;
-	uint32 mem_val = 0;
-	int ret = 0;
-	char *filepath = MEMCHECKINFO;
-
-	fp = filp_open(filepath, O_RDONLY, 0);
-	if (IS_ERR(fp)) {
-		DHD_ERROR(("[WIFI_SEC] %s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
-		goto done;
-	} else {
-		ret = kernel_read(fp, 0, (char *)&mem_val, 4);
-		if (ret < 0) {
-			DHD_ERROR(("[WIFI_SEC] %s: File read error, ret=%d\n", __FUNCTION__, ret));
-			filp_close(fp, NULL);
-			goto done;
-		}
-
-		mem_val = bcm_atoi((char *)&mem_val);
-
-		DHD_ERROR(("[WIFI_SEC]%s: MEMCHECK ENABLED = %d\n", __FUNCTION__, mem_val));
-		filp_close(fp, NULL);
-	}
-done:
-	return mem_val;
-}
-
-static int
-dhdpcie_mem_check(struct dhd_bus *bus)
-{
-	int bcmerror = BCME_OK;
-	int offset = 0;
-	int len = 0;
-	uint8 *memblock = NULL, *memptr;
-	int size = bus->ramsize;
-	int i;
-	uint32 memcheck_enabled;
-
-	/* Read memcheck info from the file */
-	/* 0 : Disable */
-	/* 1 : "Dead Beef" pattern write */
-	/* 2 : "Dead Beef" pattern write and checking the pattern value */
-
-	memcheck_enabled = dhd_get_memcheck_info();
-
-	DHD_ERROR(("%s: memcheck_enabled: %d \n", __FUNCTION__, memcheck_enabled));
-
-	if (memcheck_enabled == 0) {
-		return bcmerror;
-	}
-
-	memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
-	if (memblock == NULL) {
-		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
-		goto err;
-	}
-
-	if ((ulong)memblock % DHD_SDALIGN) {
-		memptr += (DHD_SDALIGN - ((ulong)memblock % DHD_SDALIGN));
-	}
-
-	for (i = 0; i < MEMBLOCK; i = i + 4) {
-		*(ulong*)(memptr + i) = DEADBEEF_PATTERN;
-	}
-
-	if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0) ||
-			si_setcore(bus->sih, ARMCA7_CORE_ID, 0)) {
-		if (offset == 0) {
-			/* Add start of RAM address to the address given by user */
-			offset += bus->dongle_ram_base;
-		}
-	}
-
-	/* Write  "DeadBeef" pattern with MEMBLOCK size */
-	while (size) {
-		len = MIN(MEMBLOCK, size);
-
-		bcmerror = dhdpcie_bus_membytes(bus, TRUE, offset, (uint8 *)memptr, len);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
-				__FUNCTION__, bcmerror, MEMBLOCK, offset));
-			goto err;
-		}
-
-		if (memcheck_enabled == 2) {
-			bcmerror = dhdpcie_bus_membytes(bus, FALSE, offset, (uint8 *)memptr, len);
-			if (bcmerror) {
-				DHD_ERROR(("%s: error %d on read %d membytes at 0x%08x\n",
-					__FUNCTION__, bcmerror, MEMBLOCK, offset));
-				goto err;
-			} else {
-				for (i = 0; i < len; i = i+4) {
-					if ((*(uint32*)(memptr + i)) != DEADBEEF_PATTERN) {
-						DHD_ERROR(("%s: error on reading pattern at "
-							"0x%08x\n", __FUNCTION__, (offset + i)));
-						bcmerror = BCME_ERROR;
-						goto err;
-					}
-				}
-			}
-		}
-		offset += MEMBLOCK;
-		size -= MEMBLOCK;
-	}
-
-	DHD_ERROR(("%s: Writing the Dead Beef pattern is Done \n", __FUNCTION__));
-
-err:
-	if (memblock) {
-		MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN);
-	}
-
-	return bcmerror;
-}
-
-/* Download firmware image and nvram image */
-int
-dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
-                          char *pfw_path, char *pnv_path)
-{
-	int ret;
-
-	bus->fw_path = pfw_path;
-	bus->nv_path = pnv_path;
-
-	DHD_ERROR(("%s: firmware path=%s, nvram path=%s\n",
-		__FUNCTION__, bus->fw_path, bus->nv_path));
-
-	dhdpcie_mem_check(bus);
-
-	ret = dhdpcie_download_firmware(bus, osh);
-
-	return ret;
-}
-
-static int
-dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh)
-{
-	int ret = 0;
-#if defined(BCM_REQUEST_FW)
-	uint chipid = bus->sih->chip;
-	uint revid = bus->sih->chiprev;
-	char fw_path[64] = "/lib/firmware/brcm/bcm";	/* path to firmware image */
-	char nv_path[64];		/* path to nvram vars file */
-	bus->fw_path = fw_path;
-	bus->nv_path = nv_path;
-	switch (chipid) {
-	case BCM43570_CHIP_ID:
-		bcmstrncat(fw_path, "43570", 5);
-		switch (revid) {
-		case 0:
-			bcmstrncat(fw_path, "a0", 2);
-			break;
-		case 2:
-			bcmstrncat(fw_path, "a2", 2);
-			break;
-		default:
-			DHD_ERROR(("%s: revid is not found %x\n", __FUNCTION__,
-			revid));
-			break;
-		}
-		break;
-	default:
-		DHD_ERROR(("%s: unsupported device %x\n", __FUNCTION__,
-		chipid));
-		return 0;
-	}
-	/* load board specific nvram file */
-	snprintf(bus->nv_path, sizeof(nv_path), "%s.nvm", fw_path);
-	/* load firmware */
-	snprintf(bus->fw_path, sizeof(fw_path), "%s-firmware.bin", fw_path);
-#endif /* BCM_REQUEST_FW */
-
-	DHD_OS_WAKE_LOCK(bus->dhd);
-
-	ret = _dhdpcie_download_firmware(bus);
-
-	DHD_OS_WAKE_UNLOCK(bus->dhd);
-	return ret;
-}
-
-static int
-dhdpcie_download_code_file(struct dhd_bus *bus, char *pfw_path)
-{
-	int bcmerror = BCME_ERROR;
-	int offset = 0;
-	int len = 0;
-	char *imgbuf = NULL;
-	uint8 *memblock = NULL, *memptr;
-
-	int offset_end = bus->ramsize;
-
-	DHD_ERROR(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
-
-	/* Should succeed in opening image if it is actually given through registry
-	 * entry or in module param.
-	 */
-	imgbuf = dhd_os_open_image(pfw_path);
-	if (imgbuf == NULL)
-		goto err;
-
-	memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
-	if (memblock == NULL) {
-		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
-		goto err;
-	}
-	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
-		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
-
-	DHD_INFO_HW4(("%s: dongle_ram_base: 0x%x ramsize: 0x%x tcm: %p\n",
-			__FUNCTION__, bus->dongle_ram_base, bus->ramsize, bus->tcm));
-	/* Download image with MEMBLOCK size */
-	while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, imgbuf))) {
-		if (len < 0) {
-			DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
-			bcmerror = BCME_ERROR;
-			goto err;
-		}
-		/* check if CR4/CA7 */
-		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0) ||
-			si_setcore(bus->sih, ARMCA7_CORE_ID, 0)) {
-			/* if address is 0, store the reset instruction to be written in 0 */
-			if (offset == 0) {
-				bus->resetinstr = *(((uint32*)memptr));
-				/* Add start of RAM address to the address given by user */
-				offset += bus->dongle_ram_base;
-				offset_end += offset;
-			}
-		}
-		bcmerror = dhdpcie_bus_membytes(bus, TRUE, offset, (uint8 *)memptr, len);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
-				__FUNCTION__, bcmerror, MEMBLOCK, offset));
-			goto err;
-		}
-		offset += MEMBLOCK;
-
-		if (offset >= offset_end) {
-			DHD_ERROR(("%s: invalid address access to %x (offset end: %x)\n",
-				__FUNCTION__, offset, offset_end));
-			bcmerror = BCME_ERROR;
-			goto err;
-		}
-	}
-
-err:
-	if (memblock)
-		MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN);
-
-	if (imgbuf)
-		dhd_os_close_image(imgbuf);
-
-	return bcmerror;
-} /* dhdpcie_download_code_file */
-
-#ifdef CUSTOMER_HW4_DEBUG
-#define MIN_NVRAMVARS_SIZE 128
-#endif /* CUSTOMER_HW4_DEBUG */
-
-static int
-dhdpcie_download_nvram(struct dhd_bus *bus)
-{
-	int bcmerror = BCME_ERROR;
-	uint len;
-	char * memblock = NULL;
-	char *bufp;
-	char *pnv_path;
-	bool nvram_file_exists;
-	bool nvram_uefi_exists = FALSE;
-	bool local_alloc = FALSE;
-	pnv_path = bus->nv_path;
-
-	nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
-
-	/* First try UEFI */
-	len = MAX_NVRAMBUF_SIZE;
-	dhd_get_download_buffer(bus->dhd, NULL, NVRAM, &memblock, &len);
-
-	/* If UEFI empty, then read from file system */
-	if ((len == 0) || (memblock[0] == '\0')) {
-
-		if (nvram_file_exists) {
-			len = MAX_NVRAMBUF_SIZE;
-			dhd_get_download_buffer(bus->dhd, pnv_path, NVRAM, &memblock, &len);
-			if ((len <= 0 || len > MAX_NVRAMBUF_SIZE)) {
-				goto err;
-			}
-		}
-		else {
-			/* For SROM OTP no external file or UEFI required */
-			bcmerror = BCME_OK;
-		}
-	} else {
-		nvram_uefi_exists = TRUE;
-	}
-
-	DHD_ERROR(("%s: dhd_get_download_buffer len %d\n", __FUNCTION__, len));
-
-	if (len > 0 && len <= MAX_NVRAMBUF_SIZE) {
-		bufp = (char *) memblock;
-
-#ifdef CACHE_FW_IMAGES
-		if (bus->processed_nvram_params_len) {
-			len = bus->processed_nvram_params_len;
-		}
-
-		if (!bus->processed_nvram_params_len) {
-			bufp[len] = 0;
-			if (nvram_uefi_exists || nvram_file_exists) {
-				len = process_nvram_vars(bufp, len);
-				bus->processed_nvram_params_len = len;
-			}
-		} else
-#else
-		{
-			bufp[len] = 0;
-			if (nvram_uefi_exists || nvram_file_exists) {
-				len = process_nvram_vars(bufp, len);
-			}
-		}
-#endif /* CACHE_FW_IMAGES */
-
-		DHD_ERROR(("%s: process_nvram_vars len %d\n", __FUNCTION__, len));
-#ifdef CUSTOMER_HW4_DEBUG
-		if (len < MIN_NVRAMVARS_SIZE) {
-			DHD_ERROR(("%s: invalid nvram size in process_nvram_vars \n",
-				__FUNCTION__));
-			bcmerror = BCME_ERROR;
-			goto err;
-		}
-#endif /* CUSTOMER_HW4_DEBUG */
-
-		if (len % 4) {
-			len += 4 - (len % 4);
-		}
-		bufp += len;
-		*bufp++ = 0;
-		if (len)
-			bcmerror = dhdpcie_downloadvars(bus, memblock, len + 1);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error downloading vars: %d\n",
-				__FUNCTION__, bcmerror));
-		}
-	}
-
-
-err:
-	if (memblock) {
-		if (local_alloc) {
-			MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE);
-		} else {
-			dhd_free_download_buffer(bus->dhd, memblock, MAX_NVRAMBUF_SIZE);
-		}
-	}
-
-	return bcmerror;
-}
-
-
-#ifdef BCMEMBEDIMAGE
-int
-dhdpcie_download_code_array(struct dhd_bus *bus)
-{
-	int bcmerror = -1;
-	int offset = 0;
-	unsigned char *p_dlarray  = NULL;
-	unsigned int dlarray_size = 0;
-	unsigned int downloded_len, remaining_len, len;
-	char *p_dlimagename, *p_dlimagever, *p_dlimagedate;
-	uint8 *memblock = NULL, *memptr;
-
-	downloded_len = 0;
-	remaining_len = 0;
-	len = 0;
-
-	p_dlarray = dlarray;
-	dlarray_size = sizeof(dlarray);
-	p_dlimagename = dlimagename;
-	p_dlimagever  = dlimagever;
-	p_dlimagedate = dlimagedate;
-
-	if ((p_dlarray == 0) ||	(dlarray_size == 0) ||(dlarray_size > bus->ramsize) ||
-		(p_dlimagename == 0) ||	(p_dlimagever  == 0) ||	(p_dlimagedate == 0))
-		goto err;
-
-	memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
-	if (memblock == NULL) {
-		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
-		goto err;
-	}
-	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
-		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
-
-	while (downloded_len  < dlarray_size) {
-		remaining_len = dlarray_size - downloded_len;
-		if (remaining_len >= MEMBLOCK)
-			len = MEMBLOCK;
-		else
-			len = remaining_len;
-
-		memcpy(memptr, (p_dlarray + downloded_len), len);
-		/* check if CR4/CA7 */
-		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0) ||
-			si_setcore(bus->sih, SYSMEM_CORE_ID, 0)) {
-			/* if address is 0, store the reset instruction to be written in 0 */
-			if (offset == 0) {
-				bus->resetinstr = *(((uint32*)memptr));
-				/* Add start of RAM address to the address given by user */
-				offset += bus->dongle_ram_base;
-			}
-		}
-		bcmerror = dhdpcie_bus_membytes(bus, TRUE, offset, (uint8 *)memptr, len);
-		downloded_len += len;
-		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
-				__FUNCTION__, bcmerror, MEMBLOCK, offset));
-			goto err;
-		}
-		offset += MEMBLOCK;
-	}
-
-#ifdef DHD_DEBUG
-	/* Upload and compare the downloaded code */
-	{
-		unsigned char *ularray = NULL;
-		unsigned int uploded_len;
-		uploded_len = 0;
-		bcmerror = -1;
-		ularray = MALLOC(bus->dhd->osh, dlarray_size);
-		if (ularray == NULL)
-			goto upload_err;
-		/* Upload image to verify downloaded contents. */
-		offset = bus->dongle_ram_base;
-		memset(ularray, 0xaa, dlarray_size);
-		while (uploded_len  < dlarray_size) {
-			remaining_len = dlarray_size - uploded_len;
-			if (remaining_len >= MEMBLOCK)
-				len = MEMBLOCK;
-			else
-				len = remaining_len;
-			bcmerror = dhdpcie_bus_membytes(bus, FALSE, offset,
-				(uint8 *)(ularray + uploded_len), len);
-			if (bcmerror) {
-				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
-					__FUNCTION__, bcmerror, MEMBLOCK, offset));
-				goto upload_err;
-			}
-
-			uploded_len += len;
-			offset += MEMBLOCK;
-		}
-
-		if (memcmp(p_dlarray, ularray, dlarray_size)) {
-			DHD_ERROR(("%s: Downloaded image is corrupted (%s, %s, %s).\n",
-				__FUNCTION__, p_dlimagename, p_dlimagever, p_dlimagedate));
-			goto upload_err;
-
-		} else
-			DHD_ERROR(("%s: Download, Upload and compare succeeded (%s, %s, %s).\n",
-				__FUNCTION__, p_dlimagename, p_dlimagever, p_dlimagedate));
-upload_err:
-		if (ularray)
-			MFREE(bus->dhd->osh, ularray, dlarray_size);
-	}
-#endif /* DHD_DEBUG */
-err:
-
-	if (memblock)
-		MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN);
-
-	return bcmerror;
-} /* dhdpcie_download_code_array */
-#endif /* BCMEMBEDIMAGE */
-
-
-static int
-_dhdpcie_download_firmware(struct dhd_bus *bus)
-{
-	int bcmerror = -1;
-
-	bool embed = FALSE;	/* download embedded firmware */
-	bool dlok = FALSE;	/* download firmware succeeded */
-
-	/* Out immediately if no image to download */
-	if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
-#ifdef BCMEMBEDIMAGE
-		embed = TRUE;
-#else
-		DHD_ERROR(("%s: no fimrware file\n", __FUNCTION__));
-		return 0;
-#endif
-	}
-
-	/* Keep arm in reset */
-	if (dhdpcie_bus_download_state(bus, TRUE)) {
-		DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__));
-		goto err;
-	}
-
-	/* External image takes precedence if specified */
-	if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
-		if (dhdpcie_download_code_file(bus, bus->fw_path)) {
-			DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
-#ifdef BCMEMBEDIMAGE
-			embed = TRUE;
-#else
-			goto err;
-#endif
-		} else {
-			embed = FALSE;
-			dlok = TRUE;
-		}
-	}
-
-#ifdef BCMEMBEDIMAGE
-	if (embed) {
-		if (dhdpcie_download_code_array(bus)) {
-			DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__));
-			goto err;
-		} else {
-			dlok = TRUE;
-		}
-	}
-#else
-	BCM_REFERENCE(embed);
-#endif
-	if (!dlok) {
-		DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
-		goto err;
-	}
-
-	/* EXAMPLE: nvram_array */
-	/* If a valid nvram_arry is specified as above, it can be passed down to dongle */
-	/* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
-
-
-	/* External nvram takes precedence if specified */
-	if (dhdpcie_download_nvram(bus)) {
-		DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
-		goto err;
-	}
-
-	/* Take arm out of reset */
-	if (dhdpcie_bus_download_state(bus, FALSE)) {
-		DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__));
-		goto err;
-	}
-
-	bcmerror = 0;
-
-err:
-	return bcmerror;
-} /* _dhdpcie_download_firmware */
-
-#define CONSOLE_LINE_MAX	192
-
-#ifdef DHD_DEBUG
-static int
-dhdpcie_bus_readconsole(dhd_bus_t *bus)
-{
-	dhd_console_t *c = &bus->console;
-	uint8 line[CONSOLE_LINE_MAX], ch;
-	uint32 n, idx, addr;
-	int rv;
-
-	/* Don't do anything until FWREADY updates console address */
-	if (bus->console_addr == 0)
-		return -1;
-
-	/* Read console log struct */
-	addr = bus->console_addr + OFFSETOF(hnd_cons_t, log);
-
-	if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
-		return rv;
-
-	/* Allocate console buffer (one time only) */
-	if (c->buf == NULL) {
-		c->bufsize = ltoh32(c->log.buf_size);
-		if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
-			return BCME_NOMEM;
-	}
-	idx = ltoh32(c->log.idx);
-
-	/* Protect against corrupt value */
-	if (idx > c->bufsize)
-		return BCME_ERROR;
-
-	/* Skip reading the console buffer if the index pointer has not moved */
-	if (idx == c->last)
-		return BCME_OK;
-
-	/* Read the console buffer */
-	addr = ltoh32(c->log.buf);
-	if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
-		return rv;
-
-	while (c->last != idx) {
-		for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
-			if (c->last == idx) {
-				/* This would output a partial line.  Instead, back up
-				 * the buffer pointer and output this line next time around.
-				 */
-				if (c->last >= n)
-					c->last -= n;
-				else
-					c->last = c->bufsize - n;
-				goto break2;
-			}
-			ch = c->buf[c->last];
-			c->last = (c->last + 1) % c->bufsize;
-			if (ch == '\n')
-				break;
-			line[n] = ch;
-		}
-
-		if (n > 0) {
-			if (line[n - 1] == '\r')
-				n--;
-			line[n] = 0;
-			printf("CONSOLE: %s\n", line);
-
-		}
-	}
-break2:
-
-	return BCME_OK;
-} /* dhdpcie_bus_readconsole */
-#endif /* DHD_DEBUG */
-
-static int
-dhdpcie_checkdied(dhd_bus_t *bus, char *data, uint size)
-{
-	int bcmerror = 0;
-	uint msize = 512;
-	char *mbuffer = NULL;
-	char *console_buffer = NULL;
-	uint maxstrlen = 256;
-	char *str = NULL;
-	trap_t tr;
-	pciedev_shared_t *pciedev_shared = bus->pcie_sh;
-	struct bcmstrbuf strbuf;
-	uint32 console_ptr, console_size, console_index;
-	uint8 line[CONSOLE_LINE_MAX], ch;
-	uint32 n, i, addr;
-	int rv;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (DHD_NOCHECKDIED_ON()) {
-		return 0;
-	}
-
-	if (data == NULL) {
-		/*
-		 * Called after a rx ctrl timeout. "data" is NULL.
-		 * allocate memory to trace the trap or assert.
-		 */
-		size = msize;
-		mbuffer = data = MALLOC(bus->dhd->osh, msize);
-
-		if (mbuffer == NULL) {
-			DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize));
-			bcmerror = BCME_NOMEM;
-			goto done;
-		}
-	}
-
-	if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) {
-		DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen));
-		bcmerror = BCME_NOMEM;
-		goto done;
-	}
-
-	if ((bcmerror = dhdpcie_readshared(bus)) < 0) {
-		goto done;
-	}
-
-	bcm_binit(&strbuf, data, size);
-
-	bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address  : 0x%08X\n",
-	            pciedev_shared->msgtrace_addr, pciedev_shared->console_addr);
-
-	if ((pciedev_shared->flags & PCIE_SHARED_ASSERT_BUILT) == 0) {
-		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
-		 * (Avoids conflict with real asserts for programmatic parsing of output.)
-		 */
-		bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
-	}
-
-	if ((bus->pcie_sh->flags & (PCIE_SHARED_ASSERT|PCIE_SHARED_TRAP)) == 0) {
-		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
-		 * (Avoids conflict with real asserts for programmatic parsing of output.)
-		 */
-		bcm_bprintf(&strbuf, "No trap%s in dongle",
-		          (bus->pcie_sh->flags & PCIE_SHARED_ASSERT_BUILT)
-		          ?"/assrt" :"");
-	} else {
-		if (bus->pcie_sh->flags & PCIE_SHARED_ASSERT) {
-			/* Download assert */
-			bcm_bprintf(&strbuf, "Dongle assert");
-			if (bus->pcie_sh->assert_exp_addr != 0) {
-				str[0] = '\0';
-				if ((bcmerror = dhdpcie_bus_membytes(bus, FALSE,
-					bus->pcie_sh->assert_exp_addr,
-					(uint8 *)str, maxstrlen)) < 0) {
-					goto done;
-				}
-
-				str[maxstrlen - 1] = '\0';
-				bcm_bprintf(&strbuf, " expr \"%s\"", str);
-			}
-
-			if (bus->pcie_sh->assert_file_addr != 0) {
-				str[0] = '\0';
-				if ((bcmerror = dhdpcie_bus_membytes(bus, FALSE,
-					bus->pcie_sh->assert_file_addr,
-					(uint8 *)str, maxstrlen)) < 0) {
-					goto done;
-				}
-
-				str[maxstrlen - 1] = '\0';
-				bcm_bprintf(&strbuf, " file \"%s\"", str);
-			}
-
-			bcm_bprintf(&strbuf, " line %d ",  bus->pcie_sh->assert_line);
-		}
-
-		if (bus->pcie_sh->flags & PCIE_SHARED_TRAP) {
-			bus->dhd->dongle_trap_occured = TRUE;
-			if ((bcmerror = dhdpcie_bus_membytes(bus, FALSE,
-				bus->pcie_sh->trap_addr, (uint8*)&tr, sizeof(trap_t))) < 0) {
-				goto done;
-			}
-
-			bcm_bprintf(&strbuf,
-			"\nTRAP type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
-			" lp 0x%x, rpc 0x%x"
-			"\nTrap offset 0x%x, r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, "
-			"r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
-			ltoh32(tr.type), ltoh32(tr.epc), ltoh32(tr.cpsr), ltoh32(tr.spsr),
-			ltoh32(tr.r13), ltoh32(tr.r14), ltoh32(tr.pc),
-			ltoh32(bus->pcie_sh->trap_addr),
-			ltoh32(tr.r0), ltoh32(tr.r1), ltoh32(tr.r2), ltoh32(tr.r3),
-			ltoh32(tr.r4), ltoh32(tr.r5), ltoh32(tr.r6), ltoh32(tr.r7));
-
-			addr =  bus->pcie_sh->console_addr + OFFSETOF(hnd_cons_t, log);
-			if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr,
-				(uint8 *)&console_ptr, sizeof(console_ptr))) < 0) {
-				goto printbuf;
-			}
-
-			addr =  bus->pcie_sh->console_addr + OFFSETOF(hnd_cons_t, log.buf_size);
-			if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr,
-				(uint8 *)&console_size, sizeof(console_size))) < 0) {
-				goto printbuf;
-			}
-
-			addr =  bus->pcie_sh->console_addr + OFFSETOF(hnd_cons_t, log.idx);
-			if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr,
-				(uint8 *)&console_index, sizeof(console_index))) < 0) {
-				goto printbuf;
-			}
-
-			console_ptr = ltoh32(console_ptr);
-			console_size = ltoh32(console_size);
-			console_index = ltoh32(console_index);
-
-			if (console_size > CONSOLE_BUFFER_MAX ||
-				!(console_buffer = MALLOC(bus->dhd->osh, console_size))) {
-				goto printbuf;
-			}
-
-			if ((rv = dhdpcie_bus_membytes(bus, FALSE, console_ptr,
-				(uint8 *)console_buffer, console_size)) < 0) {
-				goto printbuf;
-			}
-
-			for (i = 0, n = 0; i < console_size; i += n + 1) {
-				for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
-					ch = console_buffer[(console_index + i + n) % console_size];
-					if (ch == '\n')
-						break;
-					line[n] = ch;
-				}
-
-
-				if (n > 0) {
-					if (line[n - 1] == '\r')
-						n--;
-					line[n] = 0;
-					/* Don't use DHD_ERROR macro since we print
-					 * a lot of information quickly. The macro
-					 * will truncate a lot of the printfs
-					 */
-
-					printf("CONSOLE: %s\n", line);
-				}
-			}
-		}
-	}
-
-printbuf:
-	if (bus->pcie_sh->flags & (PCIE_SHARED_ASSERT | PCIE_SHARED_TRAP)) {
-		printf("%s: %s\n", __FUNCTION__, strbuf.origbuf);
-
-		/* wake up IOCTL wait event */
-		dhd_wakeup_ioctl_event(bus->dhd, IOCTL_RETURN_ON_TRAP);
-
-#if defined(DHD_FW_COREDUMP)
-		/* save core dump or write to a file */
-		if (bus->dhd->memdump_enabled) {
-			bus->dhd->memdump_type = DUMP_TYPE_DONGLE_TRAP;
-			dhdpcie_mem_dump(bus);
-		}
-#endif /* DHD_FW_COREDUMP */
-
-
-	}
-
-done:
-	if (mbuffer)
-		MFREE(bus->dhd->osh, mbuffer, msize);
-	if (str)
-		MFREE(bus->dhd->osh, str, maxstrlen);
-
-	if (console_buffer)
-		MFREE(bus->dhd->osh, console_buffer, console_size);
-
-	return bcmerror;
-} /* dhdpcie_checkdied */
-
-
-/* Custom copy of dhdpcie_mem_dump() that can be called at interrupt level */
-void dhdpcie_mem_dump_bugcheck(dhd_bus_t *bus, uint8 *buf)
-{
-	int ret = 0;
-	int size; /* Full mem size */
-	int start; /* Start address */
-	int read_size = 0; /* Read size of each iteration */
-	uint8 *databuf = buf;
-
-	if (bus == NULL) {
-		return;
-	}
-
-	start = bus->dongle_ram_base;
-	/* Get full mem size */
-	size = bus->ramsize;
-	/* Read mem content */
-	while (size)
-	{
-		read_size = MIN(MEMBLOCK, size);
-		if ((ret = dhdpcie_bus_membytes(bus, FALSE, start, databuf, read_size))) {
-			return;
-		}
-
-		/* Decrement size and increment start address */
-		size -= read_size;
-		start += read_size;
-		databuf += read_size;
-	}
-	bus->dhd->soc_ram = buf;
-	bus->dhd->soc_ram_length = bus->ramsize;
-	return;
-}
-
-
-#if defined(DHD_FW_COREDUMP)
-static int
-dhdpcie_mem_dump(dhd_bus_t *bus)
-{
-	int ret = 0;
-	int size; /* Full mem size */
-	int start = bus->dongle_ram_base; /* Start address */
-	int read_size = 0; /* Read size of each iteration */
-	uint8 *buf = NULL, *databuf = NULL;
-
-#ifdef EXYNOS_PCIE_DEBUG
-	exynos_pcie_register_dump(1);
-#endif /* EXYNOS_PCIE_DEBUG */
-
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-	if (bus->is_linkdown) {
-		DHD_ERROR(("%s: PCIe link was down so skip\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-
-	/* Get full mem size */
-	size = bus->ramsize;
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP)
-	buf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_MEMDUMP_BUF, size);
-	bzero(buf, size);
-#else
-	buf = MALLOC(bus->dhd->osh, size);
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */
-	if (!buf) {
-		DHD_ERROR(("%s: Out of memory (%d bytes)\n", __FUNCTION__, size));
-		return BCME_ERROR;
-	}
-
-	/* Read mem content */
-	DHD_TRACE_HW4(("Dump dongle memory"));
-	databuf = buf;
-	while (size)
-	{
-		read_size = MIN(MEMBLOCK, size);
-		if ((ret = dhdpcie_bus_membytes(bus, FALSE, start, databuf, read_size)))
-		{
-			DHD_ERROR(("%s: Error membytes %d\n", __FUNCTION__, ret));
-			if (buf) {
-				MFREE(bus->dhd->osh, buf, size);
-			}
-			return BCME_ERROR;
-		}
-		DHD_TRACE(("."));
-
-		/* Decrement size and increment start address */
-		size -= read_size;
-		start += read_size;
-		databuf += read_size;
-	}
-
-	DHD_TRACE_HW4(("%s FUNC: Copy fw image to the embedded buffer \n", __FUNCTION__));
-
-	dhd_save_fwdump(bus->dhd, buf, bus->ramsize);
-	dhd_schedule_memdump(bus->dhd, buf, bus->ramsize);
-
-	return ret;
-}
-
-int
-dhd_bus_mem_dump(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-
-	if (bus->suspended) {
-		DHD_ERROR(("%s: Bus is suspend so skip\n", __FUNCTION__));
-		return 0;
-	}
-
-	return dhdpcie_mem_dump(bus);
-}
-#endif /* DHD_FW_COREDUMP */
-
-int
-dhd_socram_dump(dhd_bus_t *bus)
-{
-#if defined(DHD_FW_COREDUMP)
-	return (dhdpcie_mem_dump(bus));
-#else
-	return -1;
-#endif
-}
-
-/**
- * Transfers bytes from host to dongle using pio mode.
- * Parameter 'address' is a backplane address.
- */
-static int
-dhdpcie_bus_membytes(dhd_bus_t *bus, bool write, ulong address, uint8 *data, uint size)
-{
-	uint dsize;
-	int detect_endian_flag = 0x01;
-	bool little_endian;
-
-	if (write && bus->is_linkdown) {
-		DHD_ERROR(("%s: PCIe link was down\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	/* Detect endianness. */
-	little_endian = *(char *)&detect_endian_flag;
-
-	/* In remap mode, adjust address beyond socram and redirect
-	 * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize
-	 * is not backplane accessible
-	 */
-
-	/* Determine initial transfer parameters */
-	dsize = sizeof(uint64);
-
-	/* Do the transfer(s) */
-	if (write) {
-		while (size) {
-			if (size >= sizeof(uint64) && little_endian &&
-#ifdef CONFIG_64BIT
-				!(address % 8) &&
-#endif /* CONFIG_64BIT */
-				1) {
-				dhdpcie_bus_wtcm64(bus, address, *((uint64 *)data));
-			} else {
-				dsize = sizeof(uint8);
-				dhdpcie_bus_wtcm8(bus, address, *data);
-			}
-
-			/* Adjust for next transfer (if any) */
-			if ((size -= dsize)) {
-				data += dsize;
-				address += dsize;
-			}
-		}
-	} else {
-		while (size) {
-			if (size >= sizeof(uint64) && little_endian &&
-#ifdef CONFIG_64BIT
-				!(address % 8) &&
-#endif /* CONFIG_64BIT */
-				1) {
-				*(uint64 *)data = dhdpcie_bus_rtcm64(bus, address);
-			} else {
-				dsize = sizeof(uint8);
-				*data = dhdpcie_bus_rtcm8(bus, address);
-			}
-
-			/* Adjust for next transfer (if any) */
-			if ((size -= dsize) > 0) {
-				data += dsize;
-				address += dsize;
-			}
-		}
-	}
-	return BCME_OK;
-} /* dhdpcie_bus_membytes */
-
-/**
- * Transfers one transmit (ethernet) packet that was queued in the (flow controlled) flow ring queue
- * to the (non flow controlled) flow ring.
- */
-int BCMFASTPATH
-dhd_bus_schedule_queue(struct dhd_bus  *bus, uint16 flow_id, bool txs)
-{
-	flow_ring_node_t *flow_ring_node;
-	int ret = BCME_OK;
-#ifdef DHD_LOSSLESS_ROAMING
-	dhd_pub_t *dhdp = bus->dhd;
-#endif
-	DHD_INFO(("%s: flow_id is %d\n", __FUNCTION__, flow_id));
-
-	/* ASSERT on flow_id */
-	if (flow_id >= bus->max_sub_queues) {
-		DHD_ERROR(("%s: flow_id is invalid %d, max %d\n", __FUNCTION__,
-			flow_id, bus->max_sub_queues));
-		return 0;
-	}
-
-	flow_ring_node = DHD_FLOW_RING(bus->dhd, flow_id);
-
-#ifdef DHD_LOSSLESS_ROAMING
-	if ((dhdp->dequeue_prec_map & (1 << flow_ring_node->flow_info.tid)) == 0) {
-		DHD_INFO(("%s: tid %d is not in precedence map. block scheduling\n",
-			__FUNCTION__, flow_ring_node->flow_info.tid));
-		return BCME_OK;
-	}
-#endif /* DHD_LOSSLESS_ROAMING */
-
-	{
-		unsigned long flags;
-		void *txp = NULL;
-		flow_queue_t *queue;
-#ifdef DHD_LOSSLESS_ROAMING
-		struct ether_header *eh;
-		uint8 *pktdata;
-#endif /* DHD_LOSSLESS_ROAMING */
-
-		queue = &flow_ring_node->queue; /* queue associated with flow ring */
-
-		DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-
-		if (flow_ring_node->status != FLOW_RING_STATUS_OPEN) {
-			DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-			return BCME_NOTREADY;
-		}
-
-		while ((txp = dhd_flow_queue_dequeue(bus->dhd, queue)) != NULL) {
-			PKTORPHAN(txp);
-
-			/*
-			 * Modifying the packet length caused P2P cert failures.
-			 * Specifically on test cases where a packet of size 52 bytes
-			 * was injected, the sniffer capture showed 62 bytes because of
-			 * which the cert tests failed. So making the below change
-			 * only Router specific.
-			 */
-
-#ifdef DHDTCPACK_SUPPRESS
-			if (bus->dhd->tcpack_sup_mode != TCPACK_SUP_HOLD) {
-				ret = dhd_tcpack_check_xmit(bus->dhd, txp);
-				if (ret != BCME_OK) {
-					DHD_ERROR(("%s: dhd_tcpack_check_xmit() error.\n",
-						__FUNCTION__));
-				}
-			}
-#endif /* DHDTCPACK_SUPPRESS */
-#ifdef DHD_LOSSLESS_ROAMING
-			pktdata = (uint8 *)PKTDATA(OSH_NULL, txp);
-			eh = (struct ether_header *) pktdata;
-			if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
-				uint8 prio = (uint8)PKTPRIO(txp);
-
-				/* Restore to original priority for 802.1X packet */
-				if (prio == PRIO_8021D_NC) {
-					PKTSETPRIO(txp, PRIO_8021D_BE);
-				}
-			}
-#endif /* DHD_LOSSLESS_ROAMING */
-
-			/* Attempt to transfer packet over flow ring */
-			ret = dhd_prot_txdata(bus->dhd, txp, flow_ring_node->flow_info.ifindex);
-			if (ret != BCME_OK) { /* may not have resources in flow ring */
-				DHD_INFO(("%s: Reinserrt %d\n", __FUNCTION__, ret));
-				dhd_prot_txdata_write_flush(bus->dhd, flow_id, FALSE);
-				/* reinsert at head */
-				dhd_flow_queue_reinsert(bus->dhd, queue, txp);
-				DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-
-				/* If we are able to requeue back, return success */
-				return BCME_OK;
-			}
-		}
-
-		dhd_prot_txdata_write_flush(bus->dhd, flow_id, FALSE);
-
-		DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-	}
-
-	return ret;
-} /* dhd_bus_schedule_queue */
-
-/** Sends an (ethernet) data frame (in 'txp') to the dongle. Callee disposes of txp. */
-int BCMFASTPATH
-dhd_bus_txdata(struct dhd_bus *bus, void *txp, uint8 ifidx)
-{
-	uint16 flowid;
-	flow_queue_t *queue;
-	flow_ring_node_t *flow_ring_node;
-	unsigned long flags;
-	int ret = BCME_OK;
-	void *txp_pend = NULL;
-
-	if (!bus->dhd->flowid_allocator) {
-		DHD_ERROR(("%s: Flow ring not intited yet  \n", __FUNCTION__));
-		goto toss;
-	}
-
-	flowid = DHD_PKT_GET_FLOWID(txp);
-
-	flow_ring_node = DHD_FLOW_RING(bus->dhd, flowid);
-
-	DHD_TRACE(("%s: pkt flowid %d, status %d active %d\n",
-		__FUNCTION__, flowid, flow_ring_node->status,
-		flow_ring_node->active));
-
-	DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-	if ((flowid >= bus->dhd->num_flow_rings) ||
-		(!flow_ring_node->active) ||
-		(flow_ring_node->status == FLOW_RING_STATUS_DELETE_PENDING) ||
-		(flow_ring_node->status == FLOW_RING_STATUS_STA_FREEING)) {
-		DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-		DHD_INFO(("%s: Dropping pkt flowid %d, status %d active %d\n",
-			__FUNCTION__, flowid, flow_ring_node->status,
-			flow_ring_node->active));
-		ret = BCME_ERROR;
-		goto toss;
-	}
-
-	queue = &flow_ring_node->queue; /* queue associated with flow ring */
-
-	if ((ret = dhd_flow_queue_enqueue(bus->dhd, queue, txp)) != BCME_OK) {
-		txp_pend = txp;
-	}
-
-	DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-
-	if (flow_ring_node->status) {
-		DHD_INFO(("%s: Enq pkt flowid %d, status %d active %d\n",
-			__FUNCTION__, flowid, flow_ring_node->status,
-			flow_ring_node->active));
-		if (txp_pend) {
-			txp = txp_pend;
-			goto toss;
-		}
-		return BCME_OK;
-	}
-	ret = dhd_bus_schedule_queue(bus, flowid, FALSE); /* from queue to flowring */
-
-	/* If we have anything pending, try to push into q */
-	if (txp_pend) {
-		DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-
-		if ((ret = dhd_flow_queue_enqueue(bus->dhd, queue, txp_pend)) != BCME_OK) {
-			DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-			txp = txp_pend;
-			goto toss;
-		}
-
-		DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-	}
-
-	return ret;
-
-toss:
-	DHD_INFO(("%s: Toss %d\n", __FUNCTION__, ret));
-	PKTCFREE(bus->dhd->osh, txp, TRUE);
-	return ret;
-} /* dhd_bus_txdata */
-
-
-void
-dhd_bus_stop_queue(struct dhd_bus *bus)
-{
-	dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
-	bus->bus_flowctrl = TRUE;
-}
-
-void
-dhd_bus_start_queue(struct dhd_bus *bus)
-{
-	dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
-	bus->bus_flowctrl = TRUE;
-}
-
-#if defined(DHD_DEBUG)
-/* Device console input function */
-int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen)
-{
-	dhd_bus_t *bus = dhd->bus;
-	uint32 addr, val;
-	int rv;
-	/* Address could be zero if CONSOLE := 0 in dongle Makefile */
-	if (bus->console_addr == 0)
-		return BCME_UNSUPPORTED;
-
-	/* Don't allow input if dongle is in reset */
-	if (bus->dhd->dongle_reset) {
-		dhd_os_sdunlock(bus->dhd);
-		return BCME_NOTREADY;
-	}
-
-	/* Zero cbuf_index */
-	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf_idx);
-	val = htol32(0);
-	if ((rv = dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
-		goto done;
-
-	/* Write message into cbuf */
-	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf);
-	if ((rv = dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
-		goto done;
-
-	/* Write length into vcons_in */
-	addr = bus->console_addr + OFFSETOF(hnd_cons_t, vcons_in);
-	val = htol32(msglen);
-	if ((rv = dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
-		goto done;
-
-	/* generate an interrupt to dongle to indicate that it needs to process cons command */
-	dhdpcie_send_mb_data(bus, H2D_HOST_CONS_INT);
-done:
-	return rv;
-} /* dhd_bus_console_in */
-#endif /* defined(DHD_DEBUG) */
-
-/**
- * Called on frame reception, the frame was received from the dongle on interface 'ifidx' and is
- * contained in 'pkt'. Processes rx frame, forwards up the layer to netif.
- */
-void BCMFASTPATH
-dhd_bus_rx_frame(struct dhd_bus *bus, void* pkt, int ifidx, uint pkt_count)
-{
-	dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, 0);
-}
-
-/** 'offset' is a backplane address */
-void
-dhdpcie_bus_wtcm8(dhd_bus_t *bus, ulong offset, uint8 data)
-{
-	*(volatile uint8 *)(bus->tcm + offset) = (uint8)data;
-}
-
-uint8
-dhdpcie_bus_rtcm8(dhd_bus_t *bus, ulong offset)
-{
-	volatile uint8 data;
-
-		data = *(volatile uint8 *)(bus->tcm + offset);
-
-	return data;
-}
-
-void
-dhdpcie_bus_wtcm32(dhd_bus_t *bus, ulong offset, uint32 data)
-{
-	*(volatile uint32 *)(bus->tcm + offset) = (uint32)data;
-}
-void
-dhdpcie_bus_wtcm16(dhd_bus_t *bus, ulong offset, uint16 data)
-{
-	*(volatile uint16 *)(bus->tcm + offset) = (uint16)data;
-}
-void
-dhdpcie_bus_wtcm64(dhd_bus_t *bus, ulong offset, uint64 data)
-{
-	*(volatile uint64 *)(bus->tcm + offset) = (uint64)data;
-}
-
-uint16
-dhdpcie_bus_rtcm16(dhd_bus_t *bus, ulong offset)
-{
-	volatile uint16 data;
-
-		data = *(volatile uint16 *)(bus->tcm + offset);
-
-	return data;
-}
-
-uint32
-dhdpcie_bus_rtcm32(dhd_bus_t *bus, ulong offset)
-{
-	volatile uint32 data;
-
-		data = *(volatile uint32 *)(bus->tcm + offset);
-
-	return data;
-}
-
-uint64
-dhdpcie_bus_rtcm64(dhd_bus_t *bus, ulong offset)
-{
-	volatile uint64 data;
-
-		data = *(volatile uint64 *)(bus->tcm + offset);
-
-	return data;
-}
-
-/** A snippet of dongle memory is shared between host and dongle */
-void
-dhd_bus_cmn_writeshared(dhd_bus_t *bus, void *data, uint32 len, uint8 type, uint16 ringid)
-{
-	uint64 long_data;
-	ulong tcm_offset;
-
-	DHD_INFO(("%s: writing to dongle type %d len %d\n", __FUNCTION__, type, len));
-
-	if (bus->is_linkdown) {
-		DHD_ERROR(("%s: PCIe link was down\n", __FUNCTION__));
-		return;
-	}
-
-	switch (type) {
-		case D2H_DMA_SCRATCH_BUF:
-		{
-			pciedev_shared_t *sh = (pciedev_shared_t*)bus->shared_addr;
-			long_data = HTOL64(*(uint64 *)data);
-			tcm_offset = (ulong)&(sh->host_dma_scratch_buffer);
-			dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8*) &long_data, len);
-			prhex(__FUNCTION__, data, len);
-			break;
-		}
-
-		case D2H_DMA_SCRATCH_BUF_LEN:
-		{
-			pciedev_shared_t *sh = (pciedev_shared_t*)bus->shared_addr;
-			tcm_offset = (ulong)&(sh->host_dma_scratch_buffer_len);
-			dhdpcie_bus_wtcm32(bus, tcm_offset, (uint32) HTOL32(*(uint32 *)data));
-			prhex(__FUNCTION__, data, len);
-			break;
-		}
-
-		case H2D_DMA_INDX_WR_BUF:
-		{
-			pciedev_shared_t *shmem = (pciedev_shared_t *)bus->pcie_sh;
-
-			long_data = HTOL64(*(uint64 *)data);
-			tcm_offset = (ulong)shmem->rings_info_ptr;
-			tcm_offset += OFFSETOF(ring_info_t, h2d_w_idx_hostaddr);
-			dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8*) &long_data, len);
-			prhex(__FUNCTION__, data, len);
-			break;
-		}
-
-		case H2D_DMA_INDX_RD_BUF:
-		{
-			pciedev_shared_t *shmem = (pciedev_shared_t *)bus->pcie_sh;
-			long_data = HTOL64(*(uint64 *)data);
-			tcm_offset = (ulong)shmem->rings_info_ptr;
-			tcm_offset += OFFSETOF(ring_info_t, h2d_r_idx_hostaddr);
-			dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8*) &long_data, len);
-			prhex(__FUNCTION__, data, len);
-			break;
-		}
-
-		case D2H_DMA_INDX_WR_BUF:
-		{
-			pciedev_shared_t *shmem = (pciedev_shared_t *)bus->pcie_sh;
-			long_data = HTOL64(*(uint64 *)data);
-			tcm_offset = (ulong)shmem->rings_info_ptr;
-			tcm_offset += OFFSETOF(ring_info_t, d2h_w_idx_hostaddr);
-			dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8*) &long_data, len);
-			prhex(__FUNCTION__, data, len);
-			break;
-		}
-
-		case D2H_DMA_INDX_RD_BUF:
-		{
-			pciedev_shared_t *shmem = (pciedev_shared_t *)bus->pcie_sh;
-			long_data = HTOL64(*(uint64 *)data);
-			tcm_offset = (ulong)shmem->rings_info_ptr;
-			tcm_offset += OFFSETOF(ring_info_t, d2h_r_idx_hostaddr);
-			dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8*) &long_data, len);
-			prhex(__FUNCTION__, data, len);
-			break;
-		}
-
-		case RING_ITEM_LEN:
-			tcm_offset = bus->ring_sh[ringid].ring_mem_addr;
-			tcm_offset += OFFSETOF(ring_mem_t, len_items);
-			dhdpcie_bus_wtcm16(bus, tcm_offset, (uint16) HTOL16(*(uint16 *)data));
-			break;
-
-		case RING_MAX_ITEMS:
-			tcm_offset = bus->ring_sh[ringid].ring_mem_addr;
-			tcm_offset += OFFSETOF(ring_mem_t, max_item);
-			dhdpcie_bus_wtcm16(bus, tcm_offset, (uint16) HTOL16(*(uint16 *)data));
-			break;
-
-		case RING_BUF_ADDR:
-			long_data = HTOL64(*(uint64 *)data);
-			tcm_offset = bus->ring_sh[ringid].ring_mem_addr;
-			tcm_offset += OFFSETOF(ring_mem_t, base_addr);
-			dhdpcie_bus_membytes(bus, TRUE, tcm_offset, (uint8 *) &long_data, len);
-			prhex(__FUNCTION__, data, len);
-			break;
-
-		case RING_WR_UPD:
-			tcm_offset = bus->ring_sh[ringid].ring_state_w;
-			dhdpcie_bus_wtcm16(bus, tcm_offset, (uint16) HTOL16(*(uint16 *)data));
-			break;
-
-		case RING_RD_UPD:
-			tcm_offset = bus->ring_sh[ringid].ring_state_r;
-			dhdpcie_bus_wtcm16(bus, tcm_offset, (uint16) HTOL16(*(uint16 *)data));
-			break;
-
-		case D2H_MB_DATA:
-			dhdpcie_bus_wtcm32(bus, bus->d2h_mb_data_ptr_addr,
-				(uint32) HTOL32(*(uint32 *)data));
-			break;
-
-		case H2D_MB_DATA:
-			dhdpcie_bus_wtcm32(bus, bus->h2d_mb_data_ptr_addr,
-				(uint32) HTOL32(*(uint32 *)data));
-			break;
-
-		default:
-			break;
-	}
-} /* dhd_bus_cmn_writeshared */
-
-/** A snippet of dongle memory is shared between host and dongle */
-void
-dhd_bus_cmn_readshared(dhd_bus_t *bus, void* data, uint8 type, uint16 ringid)
-{
-	ulong tcm_offset;
-
-	switch (type) {
-		case RING_WR_UPD:
-			tcm_offset = bus->ring_sh[ringid].ring_state_w;
-			*(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, tcm_offset));
-			break;
-		case RING_RD_UPD:
-			tcm_offset = bus->ring_sh[ringid].ring_state_r;
-			*(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, tcm_offset));
-			break;
-		case TOTAL_LFRAG_PACKET_CNT:
-		{
-			pciedev_shared_t *sh = (pciedev_shared_t*)bus->shared_addr;
-			*(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus,
-				(ulong) &sh->total_lfrag_pkt_cnt));
-			break;
-		}
-		case H2D_MB_DATA:
-			*(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, bus->h2d_mb_data_ptr_addr));
-			break;
-		case D2H_MB_DATA:
-			*(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, bus->d2h_mb_data_ptr_addr));
-			break;
-		case MAX_HOST_RXBUFS:
-		{
-			pciedev_shared_t *sh = (pciedev_shared_t*)bus->shared_addr;
-			*(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus,
-				(ulong) &sh->max_host_rxbufs));
-			break;
-		}
-		default :
-			break;
-	}
-}
-
-uint32 dhd_bus_get_sharedflags(dhd_bus_t *bus)
-{
-	return ((pciedev_shared_t*)bus->pcie_sh)->flags;
-}
-
-void
-dhd_bus_clearcounts(dhd_pub_t *dhdp)
-{
-}
-
-int
-dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
-                 void *params, int plen, void *arg, int len, bool set)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	const bcm_iovar_t *vi = NULL;
-	int bcmerror = 0;
-	int val_size;
-	uint32 actionid;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	ASSERT(name);
-	ASSERT(len >= 0);
-
-	/* Get MUST have return space */
-	ASSERT(set || (arg && len));
-
-	/* Set does NOT take qualifiers */
-	ASSERT(!set || (!params && !plen));
-
-	DHD_INFO(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
-	         name, (set ? "set" : "get"), len, plen));
-
-	/* Look up var locally; if not found pass to host driver */
-	if ((vi = bcm_iovar_lookup(dhdpcie_iovars, name)) == NULL) {
-		goto exit;
-	}
-
-
-	/* set up 'params' pointer in case this is a set command so that
-	 * the convenience int and bool code can be common to set and get
-	 */
-	if (params == NULL) {
-		params = arg;
-		plen = len;
-	}
-
-	if (vi->type == IOVT_VOID)
-		val_size = 0;
-	else if (vi->type == IOVT_BUFFER)
-		val_size = len;
-	else
-		/* all other types are integer sized */
-		val_size = sizeof(int);
-
-	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
-	bcmerror = dhdpcie_bus_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
-
-exit:
-	return bcmerror;
-} /* dhd_bus_iovar_op */
-
-#ifdef BCM_BUZZZ
-#include <bcm_buzzz.h>
-
-int
-dhd_buzzz_dump_cntrs(char *p, uint32 *core, uint32 *log,
-	const int num_counters)
-{
-	int bytes = 0;
-	uint32 ctr;
-	uint32 curr[BCM_BUZZZ_COUNTERS_MAX], prev[BCM_BUZZZ_COUNTERS_MAX];
-	uint32 delta[BCM_BUZZZ_COUNTERS_MAX];
-
-	/* Compute elapsed counter values per counter event type */
-	for (ctr = 0U; ctr < num_counters; ctr++) {
-		prev[ctr] = core[ctr];
-		curr[ctr] = *log++;
-		core[ctr] = curr[ctr];  /* saved for next log */
-
-		if (curr[ctr] < prev[ctr])
-			delta[ctr] = curr[ctr] + (~0U - prev[ctr]);
-		else
-			delta[ctr] = (curr[ctr] - prev[ctr]);
-
-		bytes += sprintf(p + bytes, "%12u ", delta[ctr]);
-	}
-
-	return bytes;
-}
-
-typedef union cm3_cnts { /* export this in bcm_buzzz.h */
-	uint32 u32;
-	uint8  u8[4];
-	struct {
-		uint8 cpicnt;
-		uint8 exccnt;
-		uint8 sleepcnt;
-		uint8 lsucnt;
-	};
-} cm3_cnts_t;
-
-int
-dhd_bcm_buzzz_dump_cntrs6(char *p, uint32 *core, uint32 *log)
-{
-	int bytes = 0;
-
-	uint32 cyccnt, instrcnt;
-	cm3_cnts_t cm3_cnts;
-	uint8 foldcnt;
-
-	{   /* 32bit cyccnt */
-		uint32 curr, prev, delta;
-		prev = core[0]; curr = *log++; core[0] = curr;
-		if (curr < prev)
-			delta = curr + (~0U - prev);
-		else
-			delta = (curr - prev);
-
-		bytes += sprintf(p + bytes, "%12u ", delta);
-		cyccnt = delta;
-	}
-
-	{	/* Extract the 4 cnts: cpi, exc, sleep and lsu */
-		int i;
-		uint8 max8 = ~0;
-		cm3_cnts_t curr, prev, delta;
-		prev.u32 = core[1]; curr.u32 = * log++; core[1] = curr.u32;
-		for (i = 0; i < 4; i++) {
-			if (curr.u8[i] < prev.u8[i])
-				delta.u8[i] = curr.u8[i] + (max8 - prev.u8[i]);
-			else
-				delta.u8[i] = (curr.u8[i] - prev.u8[i]);
-			bytes += sprintf(p + bytes, "%4u ", delta.u8[i]);
-		}
-		cm3_cnts.u32 = delta.u32;
-	}
-
-	{   /* Extract the foldcnt from arg0 */
-		uint8 curr, prev, delta, max8 = ~0;
-		bcm_buzzz_arg0_t arg0; arg0.u32 = *log;
-		prev = core[2]; curr = arg0.klog.cnt; core[2] = curr;
-		if (curr < prev)
-			delta = curr + (max8 - prev);
-		else
-			delta = (curr - prev);
-		bytes += sprintf(p + bytes, "%4u ", delta);
-		foldcnt = delta;
-	}
-
-	instrcnt = cyccnt - (cm3_cnts.u8[0] + cm3_cnts.u8[1] + cm3_cnts.u8[2]
-		                 + cm3_cnts.u8[3]) + foldcnt;
-	if (instrcnt > 0xFFFFFF00)
-		bytes += sprintf(p + bytes, "[%10s] ", "~");
-	else
-		bytes += sprintf(p + bytes, "[%10u] ", instrcnt);
-	return bytes;
-}
-
-int
-dhd_buzzz_dump_log(char *p, uint32 *core, uint32 *log, bcm_buzzz_t *buzzz)
-{
-	int bytes = 0;
-	bcm_buzzz_arg0_t arg0;
-	static uint8 * fmt[] = BCM_BUZZZ_FMT_STRINGS;
-
-	if (buzzz->counters == 6) {
-		bytes += dhd_bcm_buzzz_dump_cntrs6(p, core, log);
-		log += 2; /* 32bit cyccnt + (4 x 8bit) CM3 */
-	} else {
-		bytes += dhd_buzzz_dump_cntrs(p, core, log, buzzz->counters);
-		log += buzzz->counters; /* (N x 32bit) CR4=3, CA7=4 */
-	}
-
-	/* Dump the logged arguments using the registered formats */
-	arg0.u32 = *log++;
-
-	switch (arg0.klog.args) {
-		case 0:
-			bytes += sprintf(p + bytes, fmt[arg0.klog.id]);
-			break;
-		case 1:
-		{
-			uint32 arg1 = *log++;
-			bytes += sprintf(p + bytes, fmt[arg0.klog.id], arg1);
-			break;
-		}
-		case 2:
-		{
-			uint32 arg1, arg2;
-			arg1 = *log++; arg2 = *log++;
-			bytes += sprintf(p + bytes, fmt[arg0.klog.id], arg1, arg2);
-			break;
-		}
-		case 3:
-		{
-			uint32 arg1, arg2, arg3;
-			arg1 = *log++; arg2 = *log++; arg3 = *log++;
-			bytes += sprintf(p + bytes, fmt[arg0.klog.id], arg1, arg2, arg3);
-			break;
-		}
-		case 4:
-		{
-			uint32 arg1, arg2, arg3, arg4;
-			arg1 = *log++; arg2 = *log++;
-			arg3 = *log++; arg4 = *log++;
-			bytes += sprintf(p + bytes, fmt[arg0.klog.id], arg1, arg2, arg3, arg4);
-			break;
-		}
-		default:
-			printf("Maximum one argument supported\n");
-			break;
-	}
-
-	bytes += sprintf(p + bytes, "\n");
-
-	return bytes;
-}
-
-void dhd_buzzz_dump(bcm_buzzz_t *buzzz_p, void *buffer_p, char *p)
-{
-	int i;
-	uint32 total, part1, part2, log_sz, core[BCM_BUZZZ_COUNTERS_MAX];
-	void * log;
-
-	for (i = 0; i < BCM_BUZZZ_COUNTERS_MAX; i++) {
-		core[i] = 0;
-	}
-
-	log_sz = buzzz_p->log_sz;
-
-	part1 = ((uint32)buzzz_p->cur - (uint32)buzzz_p->log) / log_sz;
-
-	if (buzzz_p->wrap == TRUE) {
-		part2 = ((uint32)buzzz_p->end - (uint32)buzzz_p->cur) / log_sz;
-		total = (buzzz_p->buffer_sz - BCM_BUZZZ_LOGENTRY_MAXSZ) / log_sz;
-	} else {
-		part2 = 0U;
-		total = buzzz_p->count;
-	}
-
-	if (total == 0U) {
-		printf("bcm_buzzz_dump total<%u> done\n", total);
-		return;
-	} else {
-		printf("bcm_buzzz_dump total<%u> : part2<%u> + part1<%u>\n",
-		       total, part2, part1);
-	}
-
-	if (part2) {   /* with wrap */
-		log = (void*)((size_t)buffer_p + (buzzz_p->cur - buzzz_p->log));
-		while (part2--) {   /* from cur to end : part2 */
-			p[0] = '\0';
-			dhd_buzzz_dump_log(p, core, (uint32 *)log, buzzz_p);
-			printf("%s", p);
-			log = (void*)((size_t)log + buzzz_p->log_sz);
-		}
-	}
-
-	log = (void*)buffer_p;
-	while (part1--) {
-		p[0] = '\0';
-		dhd_buzzz_dump_log(p, core, (uint32 *)log, buzzz_p);
-		printf("%s", p);
-		log = (void*)((size_t)log + buzzz_p->log_sz);
-	}
-
-	printf("bcm_buzzz_dump done.\n");
-}
-
-int dhd_buzzz_dump_dngl(dhd_bus_t *bus)
-{
-	bcm_buzzz_t * buzzz_p = NULL;
-	void * buffer_p = NULL;
-	char * page_p = NULL;
-	pciedev_shared_t *sh;
-	int ret = 0;
-
-	if (bus->dhd->busstate != DHD_BUS_DATA) {
-		return BCME_UNSUPPORTED;
-	}
-	if ((page_p = (char *)MALLOC(bus->dhd->osh, 4096)) == NULL) {
-		printf("Page memory allocation failure\n");
-		goto done;
-	}
-	if ((buzzz_p = MALLOC(bus->dhd->osh, sizeof(bcm_buzzz_t))) == NULL) {
-		printf("BCM BUZZZ memory allocation failure\n");
-		goto done;
-	}
-
-	ret = dhdpcie_readshared(bus);
-	if (ret < 0) {
-		DHD_ERROR(("%s :Shared area read failed \n", __FUNCTION__));
-		goto done;
-	}
-
-	sh = bus->pcie_sh;
-
-	DHD_INFO(("%s buzzz:%08x\n", __FUNCTION__, sh->buzzz));
-
-	if (sh->buzzz != 0U) {	/* Fetch and display dongle BUZZZ Trace */
-
-		dhdpcie_bus_membytes(bus, FALSE, (ulong)sh->buzzz,
-		                     (uint8 *)buzzz_p, sizeof(bcm_buzzz_t));
-
-		printf("BUZZZ[0x%08x]: log<0x%08x> cur<0x%08x> end<0x%08x> "
-			"count<%u> status<%u> wrap<%u>\n"
-			"cpu<0x%02X> counters<%u> group<%u> buffer_sz<%u> log_sz<%u>\n",
-			(int)sh->buzzz,
-			(int)buzzz_p->log, (int)buzzz_p->cur, (int)buzzz_p->end,
-			buzzz_p->count, buzzz_p->status, buzzz_p->wrap,
-			buzzz_p->cpu_idcode, buzzz_p->counters, buzzz_p->group,
-			buzzz_p->buffer_sz, buzzz_p->log_sz);
-
-		if (buzzz_p->count == 0) {
-			printf("Empty dongle BUZZZ trace\n\n");
-			goto done;
-		}
-
-		/* Allocate memory for trace buffer and format strings */
-		buffer_p = MALLOC(bus->dhd->osh, buzzz_p->buffer_sz);
-		if (buffer_p == NULL) {
-			printf("Buffer memory allocation failure\n");
-			goto done;
-		}
-
-		/* Fetch the trace. format strings are exported via bcm_buzzz.h */
-		dhdpcie_bus_membytes(bus, FALSE, (uint32)buzzz_p->log,   /* Trace */
-		                     (uint8 *)buffer_p, buzzz_p->buffer_sz);
-
-		/* Process and display the trace using formatted output */
-
-		{
-			int ctr;
-			for (ctr = 0; ctr < buzzz_p->counters; ctr++) {
-				printf("<Evt[%02X]> ", buzzz_p->eventid[ctr]);
-			}
-			printf("<code execution point>\n");
-		}
-
-		dhd_buzzz_dump(buzzz_p, buffer_p, page_p);
-
-		printf("----- End of dongle BCM BUZZZ Trace -----\n\n");
-
-		MFREE(bus->dhd->osh, buffer_p, buzzz_p->buffer_sz); buffer_p = NULL;
-	}
-
-done:
-
-	if (page_p)   MFREE(bus->dhd->osh, page_p, 4096);
-	if (buzzz_p)  MFREE(bus->dhd->osh, buzzz_p, sizeof(bcm_buzzz_t));
-	if (buffer_p) MFREE(bus->dhd->osh, buffer_p, buzzz_p->buffer_sz);
-
-	return BCME_OK;
-}
-#endif /* BCM_BUZZZ */
-
-#define PCIE_GEN2(sih) ((BUSTYPE((sih)->bustype) == PCI_BUS) &&	\
-	((sih)->buscoretype == PCIE2_CORE_ID))
-
-static bool
-pcie2_mdiosetblock(dhd_bus_t *bus, uint blk)
-{
-	uint mdiodata, mdioctrl, i = 0;
-	uint pcie_serdes_spinwait = 200;
-
-	mdioctrl = MDIOCTL2_DIVISOR_VAL | (0x1F << MDIOCTL2_REGADDR_SHF);
-	mdiodata = (blk << MDIODATA2_DEVADDR_SHF) | MDIODATA2_DONE;
-
-	si_corereg(bus->sih, bus->sih->buscoreidx, PCIE2_MDIO_CONTROL, ~0, mdioctrl);
-	si_corereg(bus->sih, bus->sih->buscoreidx, PCIE2_MDIO_WR_DATA, ~0, mdiodata);
-
-	OSL_DELAY(10);
-	/* retry till the transaction is complete */
-	while (i < pcie_serdes_spinwait) {
-		uint mdioctrl_read = si_corereg(bus->sih, bus->sih->buscoreidx, PCIE2_MDIO_WR_DATA,
-			0, 0);
-		if (!(mdioctrl_read & MDIODATA2_DONE)) {
-			break;
-		}
-		OSL_DELAY(1000);
-		i++;
-	}
-
-	if (i >= pcie_serdes_spinwait) {
-		DHD_ERROR(("pcie_mdiosetblock: timed out\n"));
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-
-int
-dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	int bcmerror = 0;
-	unsigned long flags;
-#ifdef CONFIG_ARCH_MSM
-	int retry = POWERUP_MAX_RETRY;
-#endif /* CONFIG_ARCH_MSM */
-
-	if (dhd_download_fw_on_driverload) {
-		bcmerror = dhd_bus_start(dhdp);
-	} else {
-		if (flag == TRUE) { /* Turn off WLAN */
-			/* Removing Power */
-			DHD_ERROR(("%s: == Power OFF ==\n", __FUNCTION__));
-
-			bus->dhd->up = FALSE;
-
-			if (bus->dhd->busstate != DHD_BUS_DOWN) {
-				dhdpcie_advertise_bus_cleanup(bus->dhd);
-				if (bus->intr) {
-					dhdpcie_bus_intr_disable(bus);
-					dhdpcie_free_irq(bus);
-				}
-#ifdef BCMPCIE_OOB_HOST_WAKE
-				/* Clean up any pending host wake IRQ */
-				dhd_bus_oob_intr_set(bus->dhd, FALSE);
-				dhd_bus_oob_intr_unregister(bus->dhd);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-				dhd_os_wd_timer(dhdp, 0);
-				dhd_bus_stop(bus, TRUE);
-				dhd_prot_reset(dhdp);
-				dhd_clear(dhdp);
-				dhd_bus_release_dongle(bus);
-				dhdpcie_bus_free_resource(bus);
-				bcmerror = dhdpcie_bus_disable_device(bus);
-				if (bcmerror) {
-					DHD_ERROR(("%s: dhdpcie_bus_disable_device: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-#ifdef CONFIG_ARCH_MSM
-				bcmerror = dhdpcie_bus_clock_stop(bus);
-				if (bcmerror) {
-					DHD_ERROR(("%s: host clock stop failed: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-#endif /* CONFIG_ARCH_MSM */
-				DHD_GENERAL_LOCK(bus->dhd, flags);
-				bus->dhd->busstate = DHD_BUS_DOWN;
-				DHD_GENERAL_UNLOCK(bus->dhd, flags);
-			} else {
-				if (bus->intr) {
-					dhdpcie_free_irq(bus);
-				}
-#ifdef BCMPCIE_OOB_HOST_WAKE
-				/* Clean up any pending host wake IRQ */
-				dhd_bus_oob_intr_set(bus->dhd, FALSE);
-				dhd_bus_oob_intr_unregister(bus->dhd);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-				dhd_prot_reset(dhdp);
-				dhd_clear(dhdp);
-				dhd_bus_release_dongle(bus);
-				dhdpcie_bus_free_resource(bus);
-				bcmerror = dhdpcie_bus_disable_device(bus);
-				if (bcmerror) {
-					DHD_ERROR(("%s: dhdpcie_bus_disable_device: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-
-#ifdef CONFIG_ARCH_MSM
-				bcmerror = dhdpcie_bus_clock_stop(bus);
-				if (bcmerror) {
-					DHD_ERROR(("%s: host clock stop failed: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-#endif  /* CONFIG_ARCH_MSM */
-			}
-
-			bus->dhd->dongle_reset = TRUE;
-			DHD_ERROR(("%s:  WLAN OFF Done\n", __FUNCTION__));
-
-		} else { /* Turn on WLAN */
-			if (bus->dhd->busstate == DHD_BUS_DOWN) {
-				/* Powering On */
-				DHD_ERROR(("%s: == Power ON ==\n", __FUNCTION__));
-#ifdef CONFIG_ARCH_MSM
-				while (--retry) {
-					bcmerror = dhdpcie_bus_clock_start(bus);
-					if (!bcmerror) {
-						DHD_ERROR(("%s: dhdpcie_bus_clock_start OK\n",
-							__FUNCTION__));
-						break;
-					} else {
-						OSL_SLEEP(10);
-					}
-				}
-
-				if (bcmerror && !retry) {
-					DHD_ERROR(("%s: host pcie clock enable failed: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-#endif /* CONFIG_ARCH_MSM */
-				bus->is_linkdown = 0;
-				bus->pci_d3hot_done = 0;
-				bcmerror = dhdpcie_bus_enable_device(bus);
-				if (bcmerror) {
-					DHD_ERROR(("%s: host configuration restore failed: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-
-				bcmerror = dhdpcie_bus_alloc_resource(bus);
-				if (bcmerror) {
-					DHD_ERROR(("%s: dhdpcie_bus_resource_alloc failed: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-
-				bcmerror = dhdpcie_bus_dongle_attach(bus);
-				if (bcmerror) {
-					DHD_ERROR(("%s: dhdpcie_bus_dongle_attach failed: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-
-				bcmerror = dhd_bus_request_irq(bus);
-				if (bcmerror) {
-					DHD_ERROR(("%s: dhd_bus_request_irq failed: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-
-				bus->dhd->dongle_reset = FALSE;
-
-				bcmerror = dhd_bus_start(dhdp);
-				if (bcmerror) {
-					DHD_ERROR(("%s: dhd_bus_start: %d\n",
-						__FUNCTION__, bcmerror));
-					goto done;
-				}
-
-				bus->dhd->up = TRUE;
-				DHD_ERROR(("%s: WLAN Power On Done\n", __FUNCTION__));
-			} else {
-				DHD_ERROR(("%s: what should we do here\n", __FUNCTION__));
-				goto done;
-			}
-		}
-	}
-
-done:
-	if (bcmerror) {
-		DHD_GENERAL_LOCK(bus->dhd, flags);
-		bus->dhd->busstate = DHD_BUS_DOWN;
-		DHD_GENERAL_UNLOCK(bus->dhd, flags);
-	}
-
-	return bcmerror;
-}
-
-static int
-pcie2_mdioop(dhd_bus_t *bus, uint physmedia, uint regaddr, bool write, uint *val,
-	bool slave_bypass)
-{
-	uint pcie_serdes_spinwait = 200, i = 0, mdio_ctrl;
-	uint32 reg32;
-
-	pcie2_mdiosetblock(bus, physmedia);
-
-	/* enable mdio access to SERDES */
-	mdio_ctrl = MDIOCTL2_DIVISOR_VAL;
-	mdio_ctrl |= (regaddr << MDIOCTL2_REGADDR_SHF);
-
-	if (slave_bypass)
-		mdio_ctrl |= MDIOCTL2_SLAVE_BYPASS;
-
-	if (!write)
-		mdio_ctrl |= MDIOCTL2_READ;
-
-	si_corereg(bus->sih, bus->sih->buscoreidx, PCIE2_MDIO_CONTROL, ~0, mdio_ctrl);
-
-	if (write) {
-		reg32 =  PCIE2_MDIO_WR_DATA;
-		si_corereg(bus->sih, bus->sih->buscoreidx, PCIE2_MDIO_WR_DATA, ~0,
-			*val | MDIODATA2_DONE);
-	} else
-		reg32 =  PCIE2_MDIO_RD_DATA;
-
-	/* retry till the transaction is complete */
-	while (i < pcie_serdes_spinwait) {
-		uint done_val =  si_corereg(bus->sih, bus->sih->buscoreidx, reg32, 0, 0);
-		if (!(done_val & MDIODATA2_DONE)) {
-			if (!write) {
-				*val = si_corereg(bus->sih, bus->sih->buscoreidx,
-					PCIE2_MDIO_RD_DATA, 0, 0);
-				*val = *val & MDIODATA2_MASK;
-			}
-			return 0;
-		}
-		OSL_DELAY(1000);
-		i++;
-	}
-	return -1;
-}
-
-static int
-dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
-                void *params, int plen, void *arg, int len, int val_size)
-{
-	int bcmerror = 0;
-	int32 int_val = 0;
-	int32 int_val2 = 0;
-	int32 int_val3 = 0;
-	bool bool_val = 0;
-
-	DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
-	           __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
-
-	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
-		goto exit;
-
-	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
-
-	if (plen >= (int)sizeof(int_val) * 2)
-		bcopy((void*)((uintptr)params + sizeof(int_val)), &int_val2, sizeof(int_val2));
-
-	if (plen >= (int)sizeof(int_val) * 3)
-		bcopy((void*)((uintptr)params + 2 * sizeof(int_val)), &int_val3, sizeof(int_val3));
-
-	bool_val = (int_val != 0) ? TRUE : FALSE;
-
-	/* Check if dongle is in reset. If so, only allow DEVRESET iovars */
-	if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
-	                                actionid == IOV_GVAL(IOV_DEVRESET))) {
-		bcmerror = BCME_NOTREADY;
-		goto exit;
-	}
-
-	switch (actionid) {
-
-
-	case IOV_SVAL(IOV_VARS):
-		bcmerror = dhdpcie_downloadvars(bus, arg, len);
-		break;
-
-	case IOV_SVAL(IOV_PCIEREG):
-		si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configaddr), ~0,
-			int_val);
-		si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configdata), ~0,
-			int_val2);
-		break;
-
-	case IOV_GVAL(IOV_PCIEREG):
-		si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configaddr), ~0,
-			int_val);
-		int_val = si_corereg(bus->sih, bus->sih->buscoreidx,
-			OFFSETOF(sbpcieregs_t, configdata), 0, 0);
-		bcopy(&int_val, arg, sizeof(int_val));
-		break;
-
-	case IOV_SVAL(IOV_PCIECOREREG):
-		si_corereg(bus->sih, bus->sih->buscoreidx, int_val, ~0, int_val2);
-		break;
-	case IOV_GVAL(IOV_BAR0_SECWIN_REG):
-	{
-		sdreg_t sdreg;
-		uint32 addr, size;
-
-		bcopy(params, &sdreg, sizeof(sdreg));
-
-		addr = sdreg.offset;
-		size = sdreg.func;
-
-		if (si_backplane_access(bus->sih, addr, size, &int_val, TRUE) != BCME_OK) {
-			DHD_ERROR(("Invalid size/addr combination \n"));
-			bcmerror = BCME_ERROR;
-			break;
-		}
-		bcopy(&int_val, arg, sizeof(int32));
-		break;
-	}
-
-	case IOV_SVAL(IOV_BAR0_SECWIN_REG):
-	{
-		sdreg_t sdreg;
-		uint32 addr, size;
-
-		bcopy(params, &sdreg, sizeof(sdreg));
-
-		addr = sdreg.offset;
-		size = sdreg.func;
-		if (si_backplane_access(bus->sih, addr, size, &sdreg.value, FALSE) != BCME_OK) {
-			DHD_ERROR(("Invalid size/addr combination \n"));
-			bcmerror = BCME_ERROR;
-		}
-		break;
-	}
-
-	case IOV_GVAL(IOV_SBREG):
-	{
-		sdreg_t sdreg;
-		uint32 addr, size;
-
-		bcopy(params, &sdreg, sizeof(sdreg));
-
-		addr = sdreg.offset | SI_ENUM_BASE;
-		size = sdreg.func;
-
-		if (si_backplane_access(bus->sih, addr, size, &int_val, TRUE) != BCME_OK) {
-			DHD_ERROR(("Invalid size/addr combination \n"));
-			bcmerror = BCME_ERROR;
-			break;
-		}
-		bcopy(&int_val, arg, sizeof(int32));
-		break;
-	}
-
-	case IOV_SVAL(IOV_SBREG):
-	{
-		sdreg_t sdreg;
-		uint32 addr, size;
-
-		bcopy(params, &sdreg, sizeof(sdreg));
-
-		addr = sdreg.offset | SI_ENUM_BASE;
-		size = sdreg.func;
-		if (si_backplane_access(bus->sih, addr, size, &sdreg.value, FALSE) != BCME_OK) {
-			DHD_ERROR(("Invalid size/addr combination \n"));
-			bcmerror = BCME_ERROR;
-		}
-		break;
-	}
-
-	case IOV_GVAL(IOV_PCIESERDESREG):
-	{
-		uint val;
-		if (!PCIE_GEN2(bus->sih)) {
-			DHD_ERROR(("supported only in pcie gen2\n"));
-			bcmerror = BCME_ERROR;
-			break;
-		}
-
-		if (!pcie2_mdioop(bus, int_val, int_val2, FALSE, &val, FALSE)) {
-			bcopy(&val, arg, sizeof(int32));
-		} else {
-			DHD_ERROR(("pcie2_mdioop failed.\n"));
-			bcmerror = BCME_ERROR;
-		}
-		break;
-	}
-
-	case IOV_SVAL(IOV_PCIESERDESREG):
-		if (!PCIE_GEN2(bus->sih)) {
-			DHD_ERROR(("supported only in pcie gen2\n"));
-			bcmerror = BCME_ERROR;
-			break;
-		}
-		if (pcie2_mdioop(bus, int_val, int_val2, TRUE, &int_val3, FALSE)) {
-			DHD_ERROR(("pcie2_mdioop failed.\n"));
-			bcmerror = BCME_ERROR;
-		}
-		break;
-	case IOV_GVAL(IOV_PCIECOREREG):
-		int_val = si_corereg(bus->sih, bus->sih->buscoreidx, int_val, 0, 0);
-		bcopy(&int_val, arg, sizeof(int_val));
-		break;
-
-	case IOV_SVAL(IOV_PCIECFGREG):
-		OSL_PCI_WRITE_CONFIG(bus->osh, int_val, 4, int_val2);
-		break;
-
-	case IOV_GVAL(IOV_PCIECFGREG):
-		int_val = OSL_PCI_READ_CONFIG(bus->osh, int_val, 4);
-		bcopy(&int_val, arg, sizeof(int_val));
-		break;
-
-	case IOV_SVAL(IOV_PCIE_LPBK):
-		bcmerror = dhdpcie_bus_lpback_req(bus, int_val);
-		break;
-
-	case IOV_SVAL(IOV_PCIE_DMAXFER):
-		bcmerror = dhdpcie_bus_dmaxfer_req(bus, int_val, int_val2, int_val3);
-		break;
-
-	case IOV_GVAL(IOV_PCIE_SUSPEND):
-		int_val = (bus->dhd->busstate == DHD_BUS_SUSPEND) ? 1 : 0;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_PCIE_SUSPEND):
-		dhdpcie_bus_suspend(bus, bool_val);
-		break;
-
-	case IOV_GVAL(IOV_MEMSIZE):
-		int_val = (int32)bus->ramsize;
-		bcopy(&int_val, arg, val_size);
-		break;
-	case IOV_SVAL(IOV_MEMBYTES):
-	case IOV_GVAL(IOV_MEMBYTES):
-	{
-		uint32 address;		/* absolute backplane address */
-		uint size, dsize;
-		uint8 *data;
-
-		bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
-
-		ASSERT(plen >= 2*sizeof(int));
-
-		address = (uint32)int_val;
-		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
-		size = (uint)int_val;
-
-		/* Do some validation */
-		dsize = set ? plen - (2 * sizeof(int)) : len;
-		if (dsize < size) {
-			DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
-			           __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-
-		DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n dsize %d ", __FUNCTION__,
-		          (set ? "write" : "read"), size, address, dsize));
-
-		/* check if CR4 */
-		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0) ||
-		    si_setcore(bus->sih, SYSMEM_CORE_ID, 0)) {
-			/* if address is 0, store the reset instruction to be written in 0 */
-			if (set && address == bus->dongle_ram_base) {
-				bus->resetinstr = *(((uint32*)params) + 2);
-			}
-		} else {
-		/* If we know about SOCRAM, check for a fit */
-		if ((bus->orig_ramsize) &&
-		    ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize)))
-		{
-			uint8 enable, protect, remap;
-			si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
-			if (!enable || protect) {
-				DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n",
-					__FUNCTION__, bus->orig_ramsize, size, address));
-				DHD_ERROR(("%s: socram enable %d, protect %d\n",
-					__FUNCTION__, enable, protect));
-				bcmerror = BCME_BADARG;
-				break;
-			}
-
-			if (!REMAP_ENAB(bus) && (address >= SOCDEVRAM_ARM_ADDR)) {
-				uint32 devramsize = si_socdevram_size(bus->sih);
-				if ((address < SOCDEVRAM_ARM_ADDR) ||
-					(address + size > (SOCDEVRAM_ARM_ADDR + devramsize))) {
-					DHD_ERROR(("%s: bad address 0x%08x, size 0x%08x\n",
-						__FUNCTION__, address, size));
-					DHD_ERROR(("%s: socram range 0x%08x,size 0x%08x\n",
-						__FUNCTION__, SOCDEVRAM_ARM_ADDR, devramsize));
-					bcmerror = BCME_BADARG;
-					break;
-				}
-				/* move it such that address is real now */
-				address -= SOCDEVRAM_ARM_ADDR;
-				address += SOCDEVRAM_BP_ADDR;
-				DHD_INFO(("%s: Request to %s %d bytes @ Mapped address 0x%08x\n",
-					__FUNCTION__, (set ? "write" : "read"), size, address));
-			} else if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address) && remap) {
-				/* Can not access remap region while devram remap bit is set
-				 * ROM content would be returned in this case
-				 */
-				DHD_ERROR(("%s: Need to disable remap for address 0x%08x\n",
-					__FUNCTION__, address));
-				bcmerror = BCME_ERROR;
-				break;
-			}
-		}
-		}
-
-		/* Generate the actual data pointer */
-		data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
-
-		/* Call to do the transfer */
-		bcmerror = dhdpcie_bus_membytes(bus, set, address, data, size);
-
-		break;
-	}
-
-#ifdef BCM_BUZZZ
-	/* Dump dongle side buzzz trace to console */
-	case IOV_GVAL(IOV_BUZZZ_DUMP):
-		bcmerror = dhd_buzzz_dump_dngl(bus);
-		break;
-#endif /* BCM_BUZZZ */
-
-	case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):
-		bcmerror = dhdpcie_bus_download_state(bus, bool_val);
-		break;
-
-	case IOV_GVAL(IOV_RAMSIZE):
-		int_val = (int32)bus->ramsize;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_RAMSTART):
-		int_val = (int32)bus->dongle_ram_base;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_CC_NVMSHADOW):
-	{
-		struct bcmstrbuf dump_b;
-
-		bcm_binit(&dump_b, arg, len);
-		bcmerror = dhdpcie_cc_nvmshadow(bus, &dump_b);
-		break;
-	}
-
-	case IOV_GVAL(IOV_SLEEP_ALLOWED):
-		bool_val = bus->sleep_allowed;
-		bcopy(&bool_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_SLEEP_ALLOWED):
-		bus->sleep_allowed = bool_val;
-		break;
-
-	case IOV_GVAL(IOV_DONGLEISOLATION):
-		int_val = bus->dhd->dongle_isolation;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DONGLEISOLATION):
-		bus->dhd->dongle_isolation = bool_val;
-		break;
-
-	case IOV_GVAL(IOV_LTRSLEEPON_UNLOOAD):
-		int_val = bus->ltrsleep_on_unload;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_LTRSLEEPON_UNLOOAD):
-		bus->ltrsleep_on_unload = bool_val;
-		break;
-
-	case IOV_GVAL(IOV_DUMP_RINGUPD_BLOCK):
-	{
-		struct bcmstrbuf dump_b;
-		bcm_binit(&dump_b, arg, len);
-		bcmerror = dhd_prot_ringupd_dump(bus->dhd, &dump_b);
-		break;
-	}
-	case IOV_GVAL(IOV_DMA_RINGINDICES):
-	{	int h2d_support, d2h_support;
-
-		d2h_support = DMA_INDX_ENAB(bus->dhd->dma_d2h_ring_upd_support) ? 1 : 0;
-		h2d_support = DMA_INDX_ENAB(bus->dhd->dma_h2d_ring_upd_support) ? 1 : 0;
-		int_val = d2h_support | (h2d_support << 1);
-		bcopy(&int_val, arg, sizeof(int_val));
-		break;
-	}
-	case IOV_SVAL(IOV_DMA_RINGINDICES):
-		/* Can change it only during initialization/FW download */
-		if (bus->dhd->busstate == DHD_BUS_DOWN) {
-			if ((int_val > 3) || (int_val < 0)) {
-				DHD_ERROR(("Bad argument. Possible values: 0, 1, 2 & 3\n"));
-				bcmerror = BCME_BADARG;
-			} else {
-				bus->dhd->dma_d2h_ring_upd_support = (int_val & 1) ? TRUE : FALSE;
-				bus->dhd->dma_h2d_ring_upd_support = (int_val & 2) ? TRUE : FALSE;
-			}
-		} else {
-			DHD_ERROR(("%s: Can change only when bus down (before FW download)\n",
-				__FUNCTION__));
-			bcmerror = BCME_NOTDOWN;
-		}
-		break;
-
-	case IOV_GVAL(IOV_METADATA_DBG):
-		int_val = dhd_prot_metadata_dbg_get(bus->dhd);
-		bcopy(&int_val, arg, val_size);
-		break;
-	case IOV_SVAL(IOV_METADATA_DBG):
-		dhd_prot_metadata_dbg_set(bus->dhd, (int_val != 0));
-		break;
-
-	case IOV_GVAL(IOV_RX_METADATALEN):
-		int_val = dhd_prot_metadatalen_get(bus->dhd, TRUE);
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_RX_METADATALEN):
-		if (int_val > 64) {
-			bcmerror = BCME_BUFTOOLONG;
-			break;
-		}
-		dhd_prot_metadatalen_set(bus->dhd, int_val, TRUE);
-		break;
-
-	case IOV_SVAL(IOV_TXP_THRESHOLD):
-		dhd_prot_txp_threshold(bus->dhd, TRUE, int_val);
-		break;
-
-	case IOV_GVAL(IOV_TXP_THRESHOLD):
-		int_val = dhd_prot_txp_threshold(bus->dhd, FALSE, int_val);
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DB1_FOR_MB):
-		if (int_val)
-			bus->db1_for_mb = TRUE;
-		else
-			bus->db1_for_mb = FALSE;
-		break;
-
-	case IOV_GVAL(IOV_DB1_FOR_MB):
-		if (bus->db1_for_mb)
-			int_val = 1;
-		else
-			int_val = 0;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_TX_METADATALEN):
-		int_val = dhd_prot_metadatalen_get(bus->dhd, FALSE);
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_TX_METADATALEN):
-		if (int_val > 64) {
-			bcmerror = BCME_BUFTOOLONG;
-			break;
-		}
-		dhd_prot_metadatalen_set(bus->dhd, int_val, FALSE);
-		break;
-
-	case IOV_SVAL(IOV_DEVRESET):
-		dhd_bus_devreset(bus->dhd, (uint8)bool_val);
-		break;
-
-	case IOV_GVAL(IOV_FLOW_PRIO_MAP):
-		int_val = bus->dhd->flow_prio_map_type;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_FLOW_PRIO_MAP):
-		int_val = (int32)dhd_update_flow_prio_map(bus->dhd, (uint8)int_val);
-		bcopy(&int_val, arg, val_size);
-		break;
-
-#ifdef DHD_PCIE_RUNTIMEPM
-	case IOV_GVAL(IOV_IDLETIME):
-		int_val = bus->idletime;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_IDLETIME):
-		if (int_val < 0) {
-			bcmerror = BCME_BADARG;
-		} else {
-			bus->idletime = int_val;
-		}
-		break;
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-	case IOV_GVAL(IOV_TXBOUND):
-		int_val = (int32)dhd_txbound;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_TXBOUND):
-		dhd_txbound = (uint)int_val;
-		break;
-
-	case IOV_GVAL(IOV_RXBOUND):
-		int_val = (int32)dhd_rxbound;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_RXBOUND):
-		dhd_rxbound = (uint)int_val;
-		break;
-
-	case IOV_SVAL(IOV_HANGREPORT):
-		bus->dhd->hang_report = bool_val;
-		DHD_ERROR(("%s: Set hang_report as %d\n",
-			__FUNCTION__, bus->dhd->hang_report));
-		break;
-
-	case IOV_GVAL(IOV_HANGREPORT):
-		int_val = (int32)bus->dhd->hang_report;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	default:
-		bcmerror = BCME_UNSUPPORTED;
-		break;
-	}
-
-exit:
-	return bcmerror;
-} /* dhdpcie_bus_doiovar */
-
-/** Transfers bytes from host to dongle using pio mode */
-static int
-dhdpcie_bus_lpback_req(struct  dhd_bus *bus, uint32 len)
-{
-	if (bus->dhd == NULL) {
-		DHD_ERROR(("bus not inited\n"));
-		return 0;
-	}
-	if (bus->dhd->prot == NULL) {
-		DHD_ERROR(("prot is not inited\n"));
-		return 0;
-	}
-	if (bus->dhd->busstate != DHD_BUS_DATA) {
-		DHD_ERROR(("not in a readystate to LPBK  is not inited\n"));
-		return 0;
-	}
-	dhdmsgbuf_lpbk_req(bus->dhd, len);
-	return 0;
-}
-
-int
-dhdpcie_bus_suspend(struct dhd_bus *bus, bool state)
-{
-	int timeleft;
-	unsigned long flags;
-	int rc = 0;
-
-	if (bus->dhd == NULL) {
-		DHD_ERROR(("bus not inited\n"));
-		return BCME_ERROR;
-	}
-	if (bus->dhd->prot == NULL) {
-		DHD_ERROR(("prot is not inited\n"));
-		return BCME_ERROR;
-	}
-	DHD_GENERAL_LOCK(bus->dhd, flags);
-	if (bus->dhd->busstate != DHD_BUS_DATA && bus->dhd->busstate != DHD_BUS_SUSPEND) {
-		DHD_ERROR(("not in a readystate to LPBK  is not inited\n"));
-		DHD_GENERAL_UNLOCK(bus->dhd, flags);
-		return BCME_ERROR;
-	}
-	DHD_GENERAL_UNLOCK(bus->dhd, flags);
-	if (bus->dhd->dongle_reset) {
-		DHD_ERROR(("Dongle is in reset state.\n"));
-		return -EIO;
-	}
-
-	if (bus->suspended == state) { /* Set to same state */
-		DHD_ERROR(("Bus is already in SUSPEND state.\n"));
-		return BCME_OK;
-	}
-
-	if (state) {
-		int idle_retry = 0;
-		int active;
-
-		if (bus->is_linkdown) {
-			DHD_ERROR(("%s: PCIe link was down, state=%d\n",
-				__FUNCTION__, state));
-			return BCME_ERROR;
-		}
-
-		/* Suspend */
-		DHD_ERROR(("%s: Entering suspend state\n", __FUNCTION__));
-		bus->wait_for_d3_ack = 0;
-		bus->suspended = TRUE;
-
-
-		DHD_GENERAL_LOCK(bus->dhd, flags);
-		/* stop all interface network queue. */
-		dhd_bus_stop_queue(bus);
-		bus->dhd->busstate = DHD_BUS_SUSPEND;
-		if (bus->dhd->dhd_bus_busy_state & DHD_BUS_BUSY_IN_TX) {
-			DHD_ERROR(("Tx Request is not ended\n"));
-			bus->dhd->busstate = DHD_BUS_DATA;
-			/* resume all interface network queue. */
-			dhd_bus_start_queue(bus);
-			DHD_GENERAL_UNLOCK(bus->dhd, flags);
-			bus->suspended = FALSE;
-			return -EBUSY;
-		}
-
-		bus->dhd->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_SUSPEND;
-		DHD_GENERAL_UNLOCK(bus->dhd, flags);
-
-		DHD_OS_WAKE_LOCK_WAIVE(bus->dhd);
-		dhd_os_set_ioctl_resp_timeout(D3_ACK_RESP_TIMEOUT);
-		dhdpcie_send_mb_data(bus, H2D_HOST_D3_INFORM);
-		timeleft = dhd_os_d3ack_wait(bus->dhd, &bus->wait_for_d3_ack);
-		dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT);
-		DHD_OS_WAKE_LOCK_RESTORE(bus->dhd);
-
-		{
-			uint32 d2h_mb_data = 0;
-			uint32 zero = 0;
-
-			/* If wait_for_d3_ack was not updated because D2H MB was not received */
-			if (bus->wait_for_d3_ack == 0) {
-				/* Read the Mb data to see if the Dongle has actually sent D3 ACK */
-				dhd_bus_cmn_readshared(bus, &d2h_mb_data, D2H_MB_DATA, 0);
-
-				if (d2h_mb_data & D2H_DEV_D3_ACK) {
-					DHD_ERROR(("*** D3 WAR for missing interrupt ***\r\n"));
-					/* Clear the MB Data */
-					dhd_bus_cmn_writeshared(bus, &zero, sizeof(uint32),
-						D2H_MB_DATA, 0);
-
-					/* Consider that D3 ACK is received */
-					bus->wait_for_d3_ack = 1;
-					bus->d3_ack_war_cnt++;
-
-				} /* d2h_mb_data & D2H_DEV_D3_ACK */
-			} /* bus->wait_for_d3_ack was 0 */
-		}
-
-		/* To allow threads that got pre-empted to complete.
-		 */
-		while ((active = dhd_os_check_wakelock_all(bus->dhd)) &&
-			(idle_retry < MAX_WKLK_IDLE_CHECK)) {
-			msleep(1);
-			idle_retry++;
-		}
-
-		if (bus->wait_for_d3_ack) {
-			DHD_ERROR(("%s: Got D3 Ack \n", __FUNCTION__));
-			/* Got D3 Ack. Suspend the bus */
-			if (active) {
-				DHD_ERROR(("%s():Suspend failed because of wakelock restoring "
-					"Dongle to D0\n", __FUNCTION__));
-
-				/*
-				 * Dongle still thinks that it has to be in D3 state
-				 * until gets a D0 Inform, but we are backing off from suspend.
-				 * Ensure that Dongle is brought back to D0.
-				 *
-				 * Bringing back Dongle from D3 Ack state to D0 state
-				 * is a 2 step process. Dongle would want to know that D0 Inform
-				 * would be sent as a MB interrupt
-				 * to bring it out of D3 Ack state to D0 state.
-				 * So we have to send both this message.
-				 */
-				DHD_OS_WAKE_LOCK_WAIVE(bus->dhd);
-				dhdpcie_send_mb_data(bus,
-					(H2D_HOST_D0_INFORM_IN_USE | H2D_HOST_D0_INFORM));
-				DHD_OS_WAKE_LOCK_RESTORE(bus->dhd);
-
-				bus->suspended = FALSE;
-				DHD_GENERAL_LOCK(bus->dhd, flags);
-				bus->dhd->busstate = DHD_BUS_DATA;
-				/* resume all interface network queue. */
-				dhd_bus_start_queue(bus);
-				DHD_GENERAL_UNLOCK(bus->dhd, flags);
-				rc = BCME_ERROR;
-			} else {
-				DHD_OS_WAKE_LOCK_WAIVE(bus->dhd);
-				dhdpcie_send_mb_data(bus, (H2D_HOST_D0_INFORM_IN_USE));
-				DHD_OS_WAKE_LOCK_RESTORE(bus->dhd);
-				dhdpcie_bus_intr_disable(bus);
-				rc = dhdpcie_pci_suspend_resume(bus, state);
-				dhd_bus_set_device_wake(bus, FALSE);
-			}
-			bus->dhd->d3ackcnt_timeout = 0;
-#if defined(BCMPCIE_OOB_HOST_WAKE)
-			dhdpcie_oob_intr_set(bus, TRUE);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-		} else if (timeleft == 0) {
-			bus->dhd->d3ackcnt_timeout++;
-			DHD_ERROR(("%s: resumed on timeout for D3 ACK d3_inform_cnt %d \n",
-				__FUNCTION__, bus->dhd->d3ackcnt_timeout));
-			dhd_prot_debug_info_print(bus->dhd);
-#ifdef DHD_FW_COREDUMP
-			if (bus->dhd->memdump_enabled) {
-				/* write core dump to file */
-				bus->dhd->memdump_type = DUMP_TYPE_D3_ACK_TIMEOUT;
-				dhdpcie_mem_dump(bus);
-			}
-#endif /* DHD_FW_COREDUMP */
-			bus->suspended = FALSE;
-			DHD_GENERAL_LOCK(bus->dhd, flags);
-			bus->dhd->busstate = DHD_BUS_DATA;
-			/* resume all interface network queue. */
-			dhd_bus_start_queue(bus);
-			DHD_GENERAL_UNLOCK(bus->dhd, flags);
-			if (bus->dhd->d3ackcnt_timeout >= MAX_CNTL_D3ACK_TIMEOUT) {
-				DHD_ERROR(("%s: Event HANG send up "
-					"due to PCIe linkdown\n", __FUNCTION__));
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#ifdef CONFIG_ARCH_MSM
-				bus->no_cfg_restore = 1;
-#endif /* CONFIG_ARCH_MSM */
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-				dhd_os_check_hang(bus->dhd, 0, -ETIMEDOUT);
-			}
-			rc = -ETIMEDOUT;
-
-		}
-
-		bus->wait_for_d3_ack = 1;
-		DHD_GENERAL_LOCK(bus->dhd, flags);
-		bus->dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_SUSPEND;
-		dhd_os_busbusy_wake(bus->dhd);
-		DHD_GENERAL_UNLOCK(bus->dhd, flags);
-	} else {
-		/* Resume */
-#if defined(BCMPCIE_OOB_HOST_WAKE)
-		DHD_OS_OOB_IRQ_WAKE_UNLOCK(bus->dhd);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-		DHD_GENERAL_LOCK(bus->dhd, flags);
-		bus->dhd->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_RESUME;
-		DHD_GENERAL_UNLOCK(bus->dhd, flags);
-		rc = dhdpcie_pci_suspend_resume(bus, state);
-		if (bus->dhd->busstate == DHD_BUS_SUSPEND) {
-			DHD_OS_WAKE_LOCK_WAIVE(bus->dhd);
-			dhdpcie_send_mb_data(bus, (H2D_HOST_D0_INFORM));
-			DHD_OS_WAKE_LOCK_RESTORE(bus->dhd);
-			dhd_bus_set_device_wake(bus, TRUE);
-		}
-		bus->suspended = FALSE;
-		DHD_GENERAL_LOCK(bus->dhd, flags);
-		bus->dhd->busstate = DHD_BUS_DATA;
-		bus->dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_RESUME;
-#ifdef DHD_PCIE_RUNTIMEPM
-		if (bus->dhd->dhd_bus_busy_state & DHD_BUS_BUSY_RPM_SUSPEND_DONE) {
-			bus->bus_wake = 1;
-			OSL_SMP_WMB();
-			wake_up_interruptible(&bus->rpm_queue);
-		}
-#endif /* DHD_PCIE_RUNTIMEPM */
-		/* resume all interface network queue. */
-		dhd_bus_start_queue(bus);
-		dhd_os_busbusy_wake(bus->dhd);
-		DHD_GENERAL_UNLOCK(bus->dhd, flags);
-		dhdpcie_bus_intr_enable(bus);
-	}
-	return rc;
-}
-
-/** Transfers bytes from host to dongle and to host again using DMA */
-static int
-dhdpcie_bus_dmaxfer_req(struct  dhd_bus *bus, uint32 len, uint32 srcdelay, uint32 destdelay)
-{
-	if (bus->dhd == NULL) {
-		DHD_ERROR(("bus not inited\n"));
-		return BCME_ERROR;
-	}
-	if (bus->dhd->prot == NULL) {
-		DHD_ERROR(("prot is not inited\n"));
-		return BCME_ERROR;
-	}
-	if (bus->dhd->busstate != DHD_BUS_DATA) {
-		DHD_ERROR(("not in a readystate to LPBK  is not inited\n"));
-		return BCME_ERROR;
-	}
-
-	if (len < 5 || len > 4194296) {
-		DHD_ERROR(("len is too small or too large\n"));
-		return BCME_ERROR;
-	}
-	return dhdmsgbuf_dmaxfer_req(bus->dhd, len, srcdelay, destdelay);
-}
-
-
-
-static int
-dhdpcie_bus_download_state(dhd_bus_t *bus, bool enter)
-{
-	int bcmerror = 0;
-	uint32 *cr4_regs;
-
-	if (!bus->sih) {
-		DHD_ERROR(("%s: NULL sih!!\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-	/* To enter download state, disable ARM and reset SOCRAM.
-	 * To exit download state, simply reset ARM (default is RAM boot).
-	 */
-	if (enter) {
-		bus->alp_only = TRUE;
-
-		/* some chips (e.g. 43602) have two ARM cores, the CR4 is receives the firmware. */
-		cr4_regs = si_setcore(bus->sih, ARMCR4_CORE_ID, 0);
-
-		if (cr4_regs == NULL && !(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
-		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) &&
-		    !(si_setcore(bus->sih, ARMCA7_CORE_ID, 0))) {
-			DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
-			bcmerror = BCME_ERROR;
-			goto fail;
-		}
-
-		if (si_setcore(bus->sih, ARMCA7_CORE_ID, 0)) {
-			/* Halt ARM & remove reset */
-			si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT);
-			if (!(si_setcore(bus->sih, SYSMEM_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find SYSMEM core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-			si_core_reset(bus->sih, 0, 0);
-			/* reset last 4 bytes of RAM address. to be used for shared area */
-			dhdpcie_init_shared_addr(bus);
-		} else if (cr4_regs == NULL) { /* no CR4 present on chip */
-			si_core_disable(bus->sih, 0);
-
-			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-
-			si_core_reset(bus->sih, 0, 0);
-
-			/* Clear the top bit of memory */
-			if (bus->ramsize) {
-				uint32 zeros = 0;
-				if (dhdpcie_bus_membytes(bus, TRUE, bus->ramsize - 4,
-				                     (uint8*)&zeros, 4) < 0) {
-					bcmerror = BCME_ERROR;
-					goto fail;
-				}
-			}
-		} else {
-			/* For CR4,
-			 * Halt ARM
-			 * Remove ARM reset
-			 * Read RAM base address [0x18_0000]
-			 * [next] Download firmware
-			 * [done at else] Populate the reset vector
-			 * [done at else] Remove ARM halt
-			*/
-			/* Halt ARM & remove reset */
-			si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT);
-			if (BCM43602_CHIP(bus->sih->chip)) {
-				W_REG(bus->pcie_mb_intr_osh, cr4_regs + ARMCR4REG_BANKIDX, 5);
-				W_REG(bus->pcie_mb_intr_osh, cr4_regs + ARMCR4REG_BANKPDA, 0);
-				W_REG(bus->pcie_mb_intr_osh, cr4_regs + ARMCR4REG_BANKIDX, 7);
-				W_REG(bus->pcie_mb_intr_osh, cr4_regs + ARMCR4REG_BANKPDA, 0);
-			}
-			/* reset last 4 bytes of RAM address. to be used for shared area */
-			dhdpcie_init_shared_addr(bus);
-		}
-	} else {
-		if (si_setcore(bus->sih, ARMCA7_CORE_ID, 0)) {
-			/* write vars */
-			if ((bcmerror = dhdpcie_bus_write_vars(bus))) {
-				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
-				goto fail;
-			}
-			/* switch back to arm core again */
-			if (!(si_setcore(bus->sih, ARMCA7_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find ARM CA7 core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-			/* write address 0 with reset instruction */
-			bcmerror = dhdpcie_bus_membytes(bus, TRUE, 0,
-				(uint8 *)&bus->resetinstr, sizeof(bus->resetinstr));
-			/* now remove reset and halt and continue to run CA7 */
-		} else if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
-			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-
-			if (!si_iscoreup(bus->sih)) {
-				DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-
-			/* Enable remap before ARM reset but after vars.
-			 * No backplane access in remap mode
-			 */
-			if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
-			    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
-				DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-
-
-			if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
-			    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-		} else {
-			if (BCM43602_CHIP(bus->sih->chip)) {
-				/* Firmware crashes on SOCSRAM access when core is in reset */
-				if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
-					DHD_ERROR(("%s: Failed to find SOCRAM core!\n",
-						__FUNCTION__));
-					bcmerror = BCME_ERROR;
-					goto fail;
-				}
-				si_core_reset(bus->sih, 0, 0);
-				si_setcore(bus->sih, ARMCR4_CORE_ID, 0);
-			}
-
-			/* write vars */
-			if ((bcmerror = dhdpcie_bus_write_vars(bus))) {
-				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
-				goto fail;
-			}
-
-			/* switch back to arm core again */
-			if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find ARM CR4 core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-
-			/* write address 0 with reset instruction */
-			bcmerror = dhdpcie_bus_membytes(bus, TRUE, 0,
-				(uint8 *)&bus->resetinstr, sizeof(bus->resetinstr));
-
-			if (bcmerror == BCME_OK) {
-				uint32 tmp;
-
-				bcmerror = dhdpcie_bus_membytes(bus, FALSE, 0,
-				                                (uint8 *)&tmp, sizeof(tmp));
-
-				if (bcmerror == BCME_OK && tmp != bus->resetinstr) {
-					DHD_ERROR(("%s: Failed to write 0x%08x to addr 0\n",
-					          __FUNCTION__, bus->resetinstr));
-					DHD_ERROR(("%s: contents of addr 0 is 0x%08x\n",
-					          __FUNCTION__, tmp));
-					bcmerror = BCME_ERROR;
-					goto fail;
-				}
-			}
-
-			/* now remove reset and halt and continue to run CR4 */
-		}
-
-		si_core_reset(bus->sih, 0, 0);
-
-		/* Allow HT Clock now that the ARM is running. */
-		bus->alp_only = FALSE;
-
-		bus->dhd->busstate = DHD_BUS_LOAD;
-	}
-
-fail:
-	/* Always return to PCIE core */
-	si_setcore(bus->sih, PCIE2_CORE_ID, 0);
-
-	return bcmerror;
-} /* dhdpcie_bus_download_state */
-
-static int
-dhdpcie_bus_write_vars(dhd_bus_t *bus)
-{
-	int bcmerror = 0;
-	uint32 varsize, phys_size;
-	uint32 varaddr;
-	uint8 *vbuffer;
-	uint32 varsizew;
-#ifdef DHD_DEBUG
-	uint8 *nvram_ularray;
-#endif /* DHD_DEBUG */
-
-	/* Even if there are no vars are to be written, we still need to set the ramsize. */
-	varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
-	varaddr = (bus->ramsize - 4) - varsize;
-
-	varaddr += bus->dongle_ram_base;
-
-	if (bus->vars) {
-
-		vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
-		if (!vbuffer)
-			return BCME_NOMEM;
-
-		bzero(vbuffer, varsize);
-		bcopy(bus->vars, vbuffer, bus->varsz);
-		/* Write the vars list */
-		DHD_INFO_HW4(("%s: tcm: %p varaddr: 0x%x varsize: %d\n",
-			__FUNCTION__, bus->tcm, varaddr, varsize));
-		bcmerror = dhdpcie_bus_membytes(bus, TRUE, varaddr, vbuffer, varsize);
-
-		/* Implement read back and verify later */
-#ifdef DHD_DEBUG
-		/* Verify NVRAM bytes */
-		DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
-		nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize);
-		if (!nvram_ularray)
-			return BCME_NOMEM;
-
-		/* Upload image to verify downloaded contents. */
-		memset(nvram_ularray, 0xaa, varsize);
-
-		/* Read the vars list to temp buffer for comparison */
-		bcmerror = dhdpcie_bus_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
-		if (bcmerror) {
-				DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
-					__FUNCTION__, bcmerror, varsize, varaddr));
-		}
-
-		/* Compare the org NVRAM with the one read from RAM */
-		if (memcmp(vbuffer, nvram_ularray, varsize)) {
-			DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
-		} else
-			DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
-			__FUNCTION__));
-
-		MFREE(bus->dhd->osh, nvram_ularray, varsize);
-#endif /* DHD_DEBUG */
-
-		MFREE(bus->dhd->osh, vbuffer, varsize);
-	}
-
-	phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize;
-
-	phys_size += bus->dongle_ram_base;
-
-	/* adjust to the user specified RAM */
-	DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
-		phys_size, bus->ramsize));
-	DHD_INFO(("Vars are at %d, orig varsize is %d\n",
-		varaddr, varsize));
-	varsize = ((phys_size - 4) - varaddr);
-
-	/*
-	 * Determine the length token:
-	 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
-	 */
-	if (bcmerror) {
-		varsizew = 0;
-		bus->nvram_csm = varsizew;
-	} else {
-		varsizew = varsize / 4;
-		varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
-		bus->nvram_csm = varsizew;
-		varsizew = htol32(varsizew);
-	}
-
-	DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
-
-	/* Write the length token to the last word */
-	DHD_INFO_HW4(("%s: tcm: %p phys_size: 0x%x varsizew: %x\n",
-			__FUNCTION__, bus->tcm, phys_size, varsizew));
-	bcmerror = dhdpcie_bus_membytes(bus, TRUE, (phys_size - 4),
-		(uint8*)&varsizew, 4);
-
-	return bcmerror;
-} /* dhdpcie_bus_write_vars */
-
-int
-dhdpcie_downloadvars(dhd_bus_t *bus, void *arg, int len)
-{
-	int bcmerror = BCME_OK;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	/* Basic sanity checks */
-	if (bus->dhd->up) {
-		bcmerror = BCME_NOTDOWN;
-		goto err;
-	}
-	if (!len) {
-		bcmerror = BCME_BUFTOOSHORT;
-		goto err;
-	}
-
-	/* Free the old ones and replace with passed variables */
-	if (bus->vars)
-		MFREE(bus->dhd->osh, bus->vars, bus->varsz);
-
-	bus->vars = MALLOC(bus->dhd->osh, len);
-	bus->varsz = bus->vars ? len : 0;
-	if (bus->vars == NULL) {
-		bcmerror = BCME_NOMEM;
-		goto err;
-	}
-
-	/* Copy the passed variables, which should include the terminating double-null */
-	bcopy(arg, bus->vars, bus->varsz);
-
-
-err:
-	return bcmerror;
-}
-
-#ifndef BCMPCIE_OOB_HOST_WAKE
-/* loop through the capability list and see if the pcie capabilty exists */
-uint8
-dhdpcie_find_pci_capability(osl_t *osh, uint8 req_cap_id)
-{
-	uint8 cap_id;
-	uint8 cap_ptr = 0;
-	uint8 byte_val;
-
-	/* check for Header type 0 */
-	byte_val = read_pci_cfg_byte(PCI_CFG_HDR);
-	if ((byte_val & 0x7f) != PCI_HEADER_NORMAL) {
-		DHD_ERROR(("%s : PCI config header not normal.\n", __FUNCTION__));
-		goto end;
-	}
-
-	/* check if the capability pointer field exists */
-	byte_val = read_pci_cfg_byte(PCI_CFG_STAT);
-	if (!(byte_val & PCI_CAPPTR_PRESENT)) {
-		DHD_ERROR(("%s : PCI CAP pointer not present.\n", __FUNCTION__));
-		goto end;
-	}
-
-	cap_ptr = read_pci_cfg_byte(PCI_CFG_CAPPTR);
-	/* check if the capability pointer is 0x00 */
-	if (cap_ptr == 0x00) {
-		DHD_ERROR(("%s : PCI CAP pointer is 0x00.\n", __FUNCTION__));
-		goto end;
-	}
-
-	/* loop thr'u the capability list and see if the pcie capabilty exists */
-
-	cap_id = read_pci_cfg_byte(cap_ptr);
-
-	while (cap_id != req_cap_id) {
-		cap_ptr = read_pci_cfg_byte((cap_ptr + 1));
-		if (cap_ptr == 0x00) break;
-		cap_id = read_pci_cfg_byte(cap_ptr);
-	}
-
-end:
-	return cap_ptr;
-}
-
-void
-dhdpcie_pme_active(osl_t *osh, bool enable)
-{
-	uint8 cap_ptr;
-	uint32 pme_csr;
-
-	cap_ptr = dhdpcie_find_pci_capability(osh, PCI_CAP_POWERMGMTCAP_ID);
-
-	if (!cap_ptr) {
-		DHD_ERROR(("%s : Power Management Capability not present\n", __FUNCTION__));
-		return;
-	}
-
-	pme_csr = OSL_PCI_READ_CONFIG(osh, cap_ptr + PME_CSR_OFFSET, sizeof(uint32));
-	DHD_ERROR(("%s : pme_sts_ctrl 0x%x\n", __FUNCTION__, pme_csr));
-
-	pme_csr |= PME_CSR_PME_STAT;
-	if (enable) {
-		pme_csr |= PME_CSR_PME_EN;
-	} else {
-		pme_csr &= ~PME_CSR_PME_EN;
-	}
-
-	OSL_PCI_WRITE_CONFIG(osh, cap_ptr + PME_CSR_OFFSET, sizeof(uint32), pme_csr);
-}
-
-bool
-dhdpcie_pme_cap(osl_t *osh)
-{
-	uint8 cap_ptr;
-	uint32 pme_cap;
-
-	cap_ptr = dhdpcie_find_pci_capability(osh, PCI_CAP_POWERMGMTCAP_ID);
-
-	if (!cap_ptr) {
-		DHD_ERROR(("%s : Power Management Capability not present\n", __FUNCTION__));
-		return FALSE;
-	}
-
-	pme_cap = OSL_PCI_READ_CONFIG(osh, cap_ptr, sizeof(uint32));
-
-	DHD_ERROR(("%s : pme_cap 0x%x\n", __FUNCTION__, pme_cap));
-
-	return ((pme_cap & PME_CAP_PM_STATES) != 0);
-}
-#endif /* !BCMPCIE_OOB_HOST_WAKE */
-
-void dhd_dump_intr_registers(dhd_pub_t *dhd, struct bcmstrbuf *strbuf)
-{
-	uint32 intstatus = 0;
-	uint32 intmask = 0;
-	uint32 mbintstatus = 0;
-	uint32 d2h_mb_data = 0;
-
-	intstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCIMailBoxInt, 0, 0);
-	intmask = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCIMailBoxMask, 0, 0);
-	mbintstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCID2H_MailBox, 0, 0);
-	dhd_bus_cmn_readshared(dhd->bus, &d2h_mb_data, D2H_MB_DATA, 0);
-
-	bcm_bprintf(strbuf, "intstatus=0x%x intmask=0x%x mbintstatus=0x%x\n",
-		intstatus, intmask, mbintstatus);
-	bcm_bprintf(strbuf, "d2h_mb_data=0x%x def_intmask=0x%x\n",
-		d2h_mb_data, dhd->bus->def_intmask);
-}
-
-/** Add bus dump output to a buffer */
-void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
-{
-	uint16 flowid;
-	int ix = 0;
-	flow_ring_node_t *flow_ring_node;
-	flow_info_t *flow_info;
-	char eabuf[ETHER_ADDR_STR_LEN];
-
-	if (dhdp->busstate != DHD_BUS_DATA)
-		return;
-
-	dhd_prot_print_info(dhdp, strbuf);
-	dhd_dump_intr_registers(dhdp, strbuf);
-	bcm_bprintf(strbuf, "h2d_mb_data_ptr_addr 0x%x, d2h_mb_data_ptr_addr 0x%x\n",
-		dhdp->bus->h2d_mb_data_ptr_addr, dhdp->bus->d2h_mb_data_ptr_addr);
-	bcm_bprintf(strbuf, "dhd cumm_ctr %d\n", DHD_CUMM_CTR_READ(&dhdp->cumm_ctr));
-	bcm_bprintf(strbuf,
-		"%s %4s %2s %4s %17s %4s %4s %10s %4s %4s ",
-		"Num:", "Flow", "If", "Prio", ":Dest_MacAddress:", "Qlen", "CLen",
-		"Overflows", "RD", "WR");
-	bcm_bprintf(strbuf, "%5s %6s %5s \n", "Acked", "tossed", "noack");
-
-	for (flowid = 0; flowid < dhdp->num_flow_rings; flowid++) {
-		flow_ring_node = DHD_FLOW_RING(dhdp, flowid);
-		if (flow_ring_node->active) {
-			flow_info = &flow_ring_node->flow_info;
-			bcm_bprintf(strbuf,
-				"%3d. %4d %2d %4d %17s %4d %4d %10u ", ix++,
-				flow_ring_node->flowid, flow_info->ifindex, flow_info->tid,
-				bcm_ether_ntoa((struct ether_addr *)&flow_info->da, eabuf),
-				DHD_FLOW_QUEUE_LEN(&flow_ring_node->queue),
-				DHD_CUMM_CTR_READ(DHD_FLOW_QUEUE_CLEN_PTR(&flow_ring_node->queue)),
-				DHD_FLOW_QUEUE_FAILURES(&flow_ring_node->queue));
-			dhd_prot_print_flow_ring(dhdp, flow_ring_node->prot_info, strbuf,
-				"%4d %4d ");
-			bcm_bprintf(strbuf,
-				"%5s %6s %5s\n", "NA", "NA", "NA");
-		}
-	}
-	bcm_bprintf(strbuf, "D3 inform cnt %d\n", dhdp->bus->d3_inform_cnt);
-	bcm_bprintf(strbuf, "D0 inform cnt %d\n", dhdp->bus->d0_inform_cnt);
-	bcm_bprintf(strbuf, "D0 inform in use cnt %d\n", dhdp->bus->d0_inform_in_use_cnt);
-	bcm_bprintf(strbuf, "D3 Ack WAR cnt %d\n", dhdp->bus->d3_ack_war_cnt);
-}
-
-/**
- * Brings transmit packets on all flow rings closer to the dongle, by moving (a subset) from their
- * flow queue to their flow ring.
- */
-static void
-dhd_update_txflowrings(dhd_pub_t *dhd)
-{
-	unsigned long flags;
-	dll_t *item, *next;
-	flow_ring_node_t *flow_ring_node;
-	struct dhd_bus *bus = dhd->bus;
-
-	DHD_FLOWRING_LIST_LOCK(bus->dhd->flowring_list_lock, flags);
-	for (item = dll_head_p(&bus->const_flowring);
-		(!dhd_is_device_removed(dhd) && !dll_end(&bus->const_flowring, item));
-		item = next) {
-		if (dhd->hang_was_sent) {
-			break;
-		}
-
-		next = dll_next_p(item);
-		flow_ring_node = dhd_constlist_to_flowring(item);
-
-		/* Ensure that flow_ring_node in the list is Not Null */
-		ASSERT(flow_ring_node != NULL);
-
-		/* Ensure that the flowring node has valid contents */
-		ASSERT(flow_ring_node->prot_info != NULL);
-
-		dhd_prot_update_txflowring(dhd, flow_ring_node->flowid, flow_ring_node->prot_info);
-	}
-	DHD_FLOWRING_LIST_UNLOCK(bus->dhd->flowring_list_lock, flags);
-}
-
-/** Mailbox ringbell Function */
-static void
-dhd_bus_gen_devmb_intr(struct dhd_bus *bus)
-{
-	if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
-		(bus->sih->buscorerev == 4)) {
-		DHD_ERROR(("mailbox communication not supported\n"));
-		return;
-	}
-	if (bus->db1_for_mb)  {
-		/* this is a pcie core register, not the config register */
-		DHD_INFO(("writing a mail box interrupt to the device, through doorbell 1\n"));
-		si_corereg(bus->sih, bus->sih->buscoreidx, PCIH2D_DB1, ~0, 0x12345678);
-	} else {
-		DHD_INFO(("writing a mail box interrupt to the device, through config space\n"));
-		dhdpcie_bus_cfg_write_dword(bus, PCISBMbx, 4, (1 << 0));
-		dhdpcie_bus_cfg_write_dword(bus, PCISBMbx, 4, (1 << 0));
-	}
-}
-
-static void
-dhd_bus_set_device_wake(struct dhd_bus *bus, bool val)
-{
-	if (bus->device_wake_state != val)
-	{
-		DHD_INFO(("Set Device_Wake to %d\n", val));
-#ifdef PCIE_OOB
-		if (bus->oob_enabled)
-		{
-			if (val)
-			{
-				gpio_port = gpio_port | (1 << DEVICE_WAKE);
-				gpio_write_port_non_block(gpio_handle_val, gpio_port);
-			} else {
-				gpio_port = gpio_port & (0xff ^ (1 << DEVICE_WAKE));
-				gpio_write_port_non_block(gpio_handle_val, gpio_port);
-			}
-		}
-#endif /* PCIE_OOB */
-		bus->device_wake_state = val;
-	}
-}
-
-#ifdef PCIE_OOB
-void
-dhd_oob_set_bt_reg_on(struct dhd_bus *bus, bool val)
-{
-	DHD_INFO(("Set Device_Wake to %d\n", val));
-	if (val)
-	{
-		gpio_port = gpio_port | (1 << BIT_BT_REG_ON);
-		gpio_write_port(gpio_handle_val, gpio_port);
-	} else {
-		gpio_port = gpio_port & (0xff ^ (1 << BIT_BT_REG_ON));
-		gpio_write_port(gpio_handle_val, gpio_port);
-	}
-}
-
-int
-dhd_oob_get_bt_reg_on(struct dhd_bus *bus)
-{
-	int ret;
-	uint8 val;
-	ret = gpio_read_port(gpio_handle_val, &val);
-
-	if (ret < 0) {
-		DHD_ERROR(("gpio_read_port returns %d\n", ret));
-		return ret;
-	}
-
-	if (val & (1 << BIT_BT_REG_ON))
-	{
-		ret = 1;
-	} else {
-		ret = 0;
-	}
-
-	return ret;
-}
-
-static void
-dhd_bus_doorbell_timeout_reset(struct dhd_bus *bus)
-{
-	if (dhd_doorbell_timeout)
-		dhd_timeout_start(&bus->doorbell_timer,
-			(dhd_doorbell_timeout * 1000) / dhd_watchdog_ms);
-	else if (!(bus->dhd->busstate == DHD_BUS_SUSPEND))
-		dhd_bus_set_device_wake(bus, FALSE);
-}
-#endif /* PCIE_OOB */
-
-/** mailbox doorbell ring function */
-void
-dhd_bus_ringbell(struct dhd_bus *bus, uint32 value)
-{
-	if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
-		(bus->sih->buscorerev == 4)) {
-		si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, PCIE_INTB, PCIE_INTB);
-	} else {
-		/* this is a pcie core register, not the config regsiter */
-		DHD_INFO(("writing a door bell to the device\n"));
-		si_corereg(bus->sih, bus->sih->buscoreidx, PCIH2D_MailBox, ~0, 0x12345678);
-	}
-}
-
-void
-dhdpcie_bus_ringbell_fast(struct dhd_bus *bus, uint32 value)
-{
-#ifdef PCIE_OOB
-	dhd_bus_set_device_wake(bus, TRUE);
-	dhd_bus_doorbell_timeout_reset(bus);
-#endif
-	W_REG(bus->pcie_mb_intr_osh, bus->pcie_mb_intr_addr, value);
-}
-
-static void
-dhd_bus_ringbell_oldpcie(struct dhd_bus *bus, uint32 value)
-{
-	uint32 w;
-	w = (R_REG(bus->pcie_mb_intr_osh, bus->pcie_mb_intr_addr) & ~PCIE_INTB) | PCIE_INTB;
-	W_REG(bus->pcie_mb_intr_osh, bus->pcie_mb_intr_addr, w);
-}
-
-dhd_mb_ring_t
-dhd_bus_get_mbintr_fn(struct dhd_bus *bus)
-{
-	if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
-		(bus->sih->buscorerev == 4)) {
-		bus->pcie_mb_intr_addr = si_corereg_addr(bus->sih, bus->sih->buscoreidx,
-			PCIMailBoxInt);
-		if (bus->pcie_mb_intr_addr) {
-			bus->pcie_mb_intr_osh = si_osh(bus->sih);
-			return dhd_bus_ringbell_oldpcie;
-		}
-	} else {
-		bus->pcie_mb_intr_addr = si_corereg_addr(bus->sih, bus->sih->buscoreidx,
-			PCIH2D_MailBox);
-		if (bus->pcie_mb_intr_addr) {
-			bus->pcie_mb_intr_osh = si_osh(bus->sih);
-			return dhdpcie_bus_ringbell_fast;
-		}
-	}
-	return dhd_bus_ringbell;
-}
-
-bool BCMFASTPATH
-dhd_bus_dpc(struct dhd_bus *bus)
-{
-	bool resched = FALSE;	  /* Flag indicating resched wanted */
-	unsigned long flags;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	DHD_GENERAL_LOCK(bus->dhd, flags);
-	/* Check for only DHD_BUS_DOWN and not for DHD_BUS_DOWN_IN_PROGRESS
-	 * to avoid IOCTL Resumed On timeout when ioctl is waiting for response
-	 * and rmmod is fired in parallel, which will make DHD_BUS_DOWN_IN_PROGRESS
-	 * and if we return from here, then IOCTL response will never be handled
-	 */
-	if (bus->dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
-		bus->intstatus = 0;
-		DHD_GENERAL_UNLOCK(bus->dhd, flags);
-		return 0;
-	}
-	bus->dhd->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_DPC;
-	DHD_GENERAL_UNLOCK(bus->dhd, flags);
-
-	resched = dhdpcie_bus_process_mailbox_intr(bus, bus->intstatus);
-	if (!resched) {
-		bus->intstatus = 0;
-		if (!bus->pci_d3hot_done) {
-			dhdpcie_bus_intr_enable(bus);
-		} else {
-			DHD_ERROR(("%s: dhdpcie_bus_intr_enable skip in pci D3hot state \n",
-					__FUNCTION__));
-		}
-	}
-
-	DHD_GENERAL_LOCK(bus->dhd, flags);
-	bus->dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_DPC;
-	dhd_os_busbusy_wake(bus->dhd);
-	DHD_GENERAL_UNLOCK(bus->dhd, flags);
-
-	return resched;
-
-}
-
-
-static void
-dhdpcie_send_mb_data(dhd_bus_t *bus, uint32 h2d_mb_data)
-{
-	uint32 cur_h2d_mb_data = 0;
-
-	DHD_INFO_HW4(("%s: H2D_MB_DATA: 0x%08X\n", __FUNCTION__, h2d_mb_data));
-
-	if (bus->is_linkdown) {
-		DHD_ERROR(("%s: PCIe link was down\n", __FUNCTION__));
-		return;
-	}
-
-	dhd_bus_cmn_readshared(bus, &cur_h2d_mb_data, H2D_MB_DATA, 0);
-
-	if (cur_h2d_mb_data != 0) {
-		uint32 i = 0;
-		DHD_INFO(("GRRRRRRR: MB transaction is already pending 0x%04x\n", cur_h2d_mb_data));
-		while ((i++ < 100) && cur_h2d_mb_data) {
-			OSL_DELAY(10);
-			dhd_bus_cmn_readshared(bus, &cur_h2d_mb_data, H2D_MB_DATA, 0);
-		}
-		if (i >= 100) {
-			DHD_ERROR(("%s : waited 1ms for the dngl "
-				"to ack the previous mb transaction\n", __FUNCTION__));
-			DHD_ERROR(("%s : MB transaction is still pending 0x%04x\n",
-				__FUNCTION__, cur_h2d_mb_data));
-		}
-	}
-
-	dhd_bus_cmn_writeshared(bus, &h2d_mb_data, sizeof(uint32), H2D_MB_DATA, 0);
-	dhd_bus_gen_devmb_intr(bus);
-
-	if (h2d_mb_data == H2D_HOST_D3_INFORM) {
-		DHD_INFO_HW4(("%s: send H2D_HOST_D3_INFORM to dongle\n", __FUNCTION__));
-		bus->d3_inform_cnt++;
-	}
-	if (h2d_mb_data == H2D_HOST_D0_INFORM_IN_USE) {
-		DHD_INFO_HW4(("%s: send H2D_HOST_D0_INFORM_IN_USE to dongle\n", __FUNCTION__));
-		bus->d0_inform_in_use_cnt++;
-	}
-	if (h2d_mb_data == H2D_HOST_D0_INFORM) {
-		DHD_INFO_HW4(("%s: send H2D_HOST_D0_INFORM to dongle\n", __FUNCTION__));
-		bus->d0_inform_cnt++;
-	}
-}
-
-static void
-dhdpcie_handle_mb_data(dhd_bus_t *bus)
-{
-	uint32 d2h_mb_data = 0;
-	uint32 zero = 0;
-	dhd_bus_cmn_readshared(bus, &d2h_mb_data, D2H_MB_DATA, 0);
-	if (!d2h_mb_data) {
-		DHD_INFO_HW4(("%s: Invalid D2H_MB_DATA: 0x%08x\n",
-			__FUNCTION__, d2h_mb_data));
-		return;
-	}
-
-	dhd_bus_cmn_writeshared(bus, &zero, sizeof(uint32), D2H_MB_DATA, 0);
-
-	DHD_INFO_HW4(("D2H_MB_DATA: 0x%08x\n", d2h_mb_data));
-	if (d2h_mb_data & D2H_DEV_FWHALT)  {
-		DHD_ERROR(("FW trap has happened\n"));
-		dhdpcie_checkdied(bus, NULL, 0);
-		/* not ready yet dhd_os_ind_firmware_stall(bus->dhd); */
-		bus->dhd->busstate = DHD_BUS_DOWN;
-		return;
-	}
-	if (d2h_mb_data & D2H_DEV_DS_ENTER_REQ)  {
-		/* what should we do */
-		DHD_INFO(("D2H_MB_DATA: DEEP SLEEP REQ\n"));
-		dhdpcie_send_mb_data(bus, H2D_HOST_DS_ACK);
-		DHD_INFO(("D2H_MB_DATA: sent DEEP SLEEP ACK\n"));
-	}
-	if (d2h_mb_data & D2H_DEV_DS_EXIT_NOTE)  {
-		/* what should we do */
-		DHD_INFO(("D2H_MB_DATA: DEEP SLEEP EXIT\n"));
-	}
-	if (d2h_mb_data & D2H_DEV_D3_ACK)  {
-		/* what should we do */
-		DHD_INFO_HW4(("D2H_MB_DATA: D3 ACK\n"));
-		if (!bus->wait_for_d3_ack) {
-			bus->wait_for_d3_ack = 1;
-			dhd_os_d3ack_wake(bus->dhd);
-		}
-	}
-}
-
-/* Inform Dongle to print HW Registers for Livelock Debug */
-void dhdpcie_bus_dongle_print_hwregs(struct dhd_bus *bus)
-{
-	dhdpcie_send_mb_data(bus, H2D_FW_TRAP);
-}
-
-static bool
-dhdpcie_bus_process_mailbox_intr(dhd_bus_t *bus, uint32 intstatus)
-{
-	bool resched = FALSE;
-
-	if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) ||
-		(bus->sih->buscorerev == 4)) {
-		/* Msg stream interrupt */
-		if (intstatus & I_BIT1) {
-			resched = dhdpci_bus_read_frames(bus);
-		} else if (intstatus & I_BIT0) {
-			/* do nothing for Now */
-		}
-	} else {
-		if (intstatus & (PCIE_MB_TOPCIE_FN0_0 | PCIE_MB_TOPCIE_FN0_1))
-			dhdpcie_handle_mb_data(bus);
-
-		if (bus->dhd->busstate == DHD_BUS_SUSPEND) {
-			goto exit;
-		}
-
-		if (intstatus & PCIE_MB_D2H_MB_MASK) {
-			resched = dhdpci_bus_read_frames(bus);
-		}
-	}
-
-exit:
-	return resched;
-}
-
-static bool
-dhdpci_bus_read_frames(dhd_bus_t *bus)
-{
-	bool more = FALSE;
-
-	/* There may be frames in both ctrl buf and data buf; check ctrl buf first */
-	DHD_PERIM_LOCK_ALL((bus->dhd->fwder_unit % FWDER_MAX_UNIT));
-	dhd_prot_process_ctrlbuf(bus->dhd);
-	/* Unlock to give chance for resp to be handled */
-	DHD_PERIM_UNLOCK_ALL((bus->dhd->fwder_unit % FWDER_MAX_UNIT));
-
-	DHD_PERIM_LOCK_ALL((bus->dhd->fwder_unit % FWDER_MAX_UNIT));
-	/* update the flow ring cpls */
-	dhd_update_txflowrings(bus->dhd);
-
-	/* With heavy TX traffic, we could get a lot of TxStatus
-	 * so add bound
-	 */
-	more |= dhd_prot_process_msgbuf_txcpl(bus->dhd, dhd_txbound);
-
-	/* With heavy RX traffic, this routine potentially could spend some time
-	 * processing RX frames without RX bound
-	 */
-	more |= dhd_prot_process_msgbuf_rxcpl(bus->dhd, dhd_rxbound);
-
-	/* don't talk to the dongle if fw is about to be reloaded */
-	if (bus->dhd->hang_was_sent) {
-		more = FALSE;
-	}
-	DHD_PERIM_UNLOCK_ALL((bus->dhd->fwder_unit % FWDER_MAX_UNIT));
-
-	return more;
-}
-
-bool
-dhdpcie_tcm_valid(dhd_bus_t *bus)
-{
-	uint32 addr = 0;
-	int rv;
-	uint32 shaddr = 0;
-	pciedev_shared_t sh;
-
-	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
-
-	/* Read last word in memory to determine address of pciedev_shared structure */
-	addr = LTOH32(dhdpcie_bus_rtcm32(bus, shaddr));
-
-	if ((addr == 0) || (addr == bus->nvram_csm) || (addr < bus->dongle_ram_base) ||
-		(addr > shaddr)) {
-		DHD_ERROR(("%s: address (0x%08x) of pciedev_shared invalid addr\n",
-			__FUNCTION__, addr));
-		return FALSE;
-	}
-
-	/* Read hndrte_shared structure */
-	if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr, (uint8 *)&sh,
-		sizeof(pciedev_shared_t))) < 0) {
-		DHD_ERROR(("Failed to read PCIe shared struct with %d\n", rv));
-		return FALSE;
-	}
-
-	/* Compare any field in pciedev_shared_t */
-	if (sh.console_addr != bus->pcie_sh->console_addr) {
-		DHD_ERROR(("Contents of pciedev_shared_t structure are not matching.\n"));
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static bool
-dhdpcie_check_firmware_compatible(uint32 firmware_api_version, uint32 host_api_version)
-{
-	DHD_INFO(("firmware api revision %d, host api revision %d\n",
-		firmware_api_version, host_api_version));
-	if (firmware_api_version <= host_api_version)
-		return TRUE;
-	if ((firmware_api_version == 6) && (host_api_version == 5))
-		return TRUE;
-	if ((firmware_api_version == 5) && (host_api_version == 6))
-		return TRUE;
-	return FALSE;
-}
-
-static int
-dhdpcie_readshared(dhd_bus_t *bus)
-{
-	uint32 addr = 0;
-	int rv, dma_indx_wr_buf, dma_indx_rd_buf;
-	uint32 shaddr = 0;
-	pciedev_shared_t *sh = bus->pcie_sh;
-	dhd_timeout_t tmo;
-
-	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
-
-	DHD_INFO_HW4(("%s: ram_base: 0x%x ramsize 0x%x tcm: %p shaddr: 0x%x nvram_csm: 0x%x\n",
-		__FUNCTION__, bus->dongle_ram_base, bus->ramsize,
-		bus->tcm, shaddr, bus->nvram_csm));
-	/* start a timer for 5 seconds */
-	dhd_timeout_start(&tmo, MAX_READ_TIMEOUT);
-
-	while (((addr == 0) || (addr == bus->nvram_csm)) && !dhd_timeout_expired(&tmo)) {
-		/* Read last word in memory to determine address of pciedev_shared structure */
-		addr = LTOH32(dhdpcie_bus_rtcm32(bus, shaddr));
-	}
-
-	if ((addr == 0) || (addr == bus->nvram_csm) || (addr < bus->dongle_ram_base) ||
-		(addr > shaddr)) {
-		DHD_ERROR(("%s: address (0x%08x) of pciedev_shared invalid\n",
-			__FUNCTION__, addr));
-		DHD_ERROR(("Waited %u usec, dongle is not ready\n", tmo.elapsed));
-		return BCME_ERROR;
-	} else {
-		bus->shared_addr = (ulong)addr;
-		DHD_ERROR(("PCIe shared addr (0x%08x) read took %u usec "
-			"before dongle is ready\n", addr, tmo.elapsed));
-	}
-
-	/* Read hndrte_shared structure */
-	if ((rv = dhdpcie_bus_membytes(bus, FALSE, addr, (uint8 *)sh,
-		sizeof(pciedev_shared_t))) < 0) {
-		DHD_ERROR(("Failed to read PCIe shared struct with %d\n", rv));
-		return rv;
-	}
-
-	/* Endianness */
-	sh->flags = ltoh32(sh->flags);
-	sh->trap_addr = ltoh32(sh->trap_addr);
-	sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
-	sh->assert_file_addr = ltoh32(sh->assert_file_addr);
-	sh->assert_line = ltoh32(sh->assert_line);
-	sh->console_addr = ltoh32(sh->console_addr);
-	sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
-	sh->dma_rxoffset = ltoh32(sh->dma_rxoffset);
-	sh->rings_info_ptr = ltoh32(sh->rings_info_ptr);
-
-#ifdef DHD_DEBUG
-	/* load bus console address */
-	bus->console_addr = sh->console_addr;
-#endif
-
-	/* Read the dma rx offset */
-	bus->dma_rxoffset = bus->pcie_sh->dma_rxoffset;
-	dhd_prot_rx_dataoffset(bus->dhd, bus->dma_rxoffset);
-
-	DHD_ERROR(("DMA RX offset from shared Area %d\n", bus->dma_rxoffset));
-
-	if (!(dhdpcie_check_firmware_compatible(sh->flags & PCIE_SHARED_VERSION_MASK,
-		PCIE_SHARED_VERSION)))
-	{
-		DHD_ERROR(("%s: pcie_shared version %d in dhd "
-		           "is older than pciedev_shared version %d in dongle\n",
-		           __FUNCTION__, PCIE_SHARED_VERSION,
-		           sh->flags & PCIE_SHARED_VERSION_MASK));
-		return BCME_ERROR;
-	}
-
-	bus->rw_index_sz = (sh->flags & PCIE_SHARED_2BYTE_INDICES) ?
-		sizeof(uint16) : sizeof(uint32);
-	DHD_ERROR(("%s: Dongle advertizes %d size indices\n",
-		__FUNCTION__, bus->rw_index_sz));
-
-	/* Does the FW support DMA'ing r/w indices */
-	if (sh->flags & PCIE_SHARED_DMA_INDEX) {
-
-
-		DHD_ERROR(("%s: Host support DMAing indices: H2D:%d - D2H:%d. FW supports it\n",
-			__FUNCTION__,
-			(DMA_INDX_ENAB(bus->dhd->dma_h2d_ring_upd_support) ? 1 : 0),
-			(DMA_INDX_ENAB(bus->dhd->dma_d2h_ring_upd_support) ? 1 : 0)));
-
-	} else if (DMA_INDX_ENAB(bus->dhd->dma_d2h_ring_upd_support) ||
-	           DMA_INDX_ENAB(bus->dhd->dma_h2d_ring_upd_support)) {
-
-#ifdef BCM_INDX_DMA
-		DHD_ERROR(("%s: Incompatible FW. FW does not support DMAing indices\n",
-			__FUNCTION__));
-		return BCME_ERROR;
-#endif
-		DHD_ERROR(("%s: Host supports DMAing indices but FW does not\n",
-			__FUNCTION__));
-		bus->dhd->dma_d2h_ring_upd_support = FALSE;
-		bus->dhd->dma_h2d_ring_upd_support = FALSE;
-	}
-
-
-	/* get ring_info, ring_state and mb data ptrs and store the addresses in bus structure */
-	{
-		ring_info_t  ring_info;
-
-		if ((rv = dhdpcie_bus_membytes(bus, FALSE, sh->rings_info_ptr,
-			(uint8 *)&ring_info, sizeof(ring_info_t))) < 0)
-			return rv;
-
-		bus->h2d_mb_data_ptr_addr = ltoh32(sh->h2d_mb_data_ptr);
-		bus->d2h_mb_data_ptr_addr = ltoh32(sh->d2h_mb_data_ptr);
-
-
-		bus->max_sub_queues = ltoh16(ring_info.max_sub_queues);
-
-		/* If both FW and Host support DMA'ing indices, allocate memory and notify FW
-		 * The max_sub_queues is read from FW initialized ring_info
-		 */
-		if (DMA_INDX_ENAB(bus->dhd->dma_h2d_ring_upd_support)) {
-			dma_indx_wr_buf = dhd_prot_dma_indx_init(bus->dhd, bus->rw_index_sz,
-				H2D_DMA_INDX_WR_BUF, bus->max_sub_queues);
-			dma_indx_rd_buf = dhd_prot_dma_indx_init(bus->dhd, bus->rw_index_sz,
-				D2H_DMA_INDX_RD_BUF, BCMPCIE_D2H_COMMON_MSGRINGS);
-
-			if ((dma_indx_wr_buf != BCME_OK) || (dma_indx_rd_buf != BCME_OK)) {
-				DHD_ERROR(("%s: Failed to allocate memory for dma'ing h2d indices"
-					"Host will use w/r indices in TCM\n",
-					__FUNCTION__));
-				bus->dhd->dma_h2d_ring_upd_support = FALSE;
-			}
-		}
-
-		if (DMA_INDX_ENAB(bus->dhd->dma_d2h_ring_upd_support)) {
-			dma_indx_wr_buf = dhd_prot_dma_indx_init(bus->dhd, bus->rw_index_sz,
-				D2H_DMA_INDX_WR_BUF, BCMPCIE_D2H_COMMON_MSGRINGS);
-			dma_indx_rd_buf = dhd_prot_dma_indx_init(bus->dhd, bus->rw_index_sz,
-				H2D_DMA_INDX_RD_BUF, bus->max_sub_queues);
-
-			if ((dma_indx_wr_buf != BCME_OK) || (dma_indx_rd_buf != BCME_OK)) {
-				DHD_ERROR(("%s: Failed to allocate memory for dma'ing d2h indices"
-					"Host will use w/r indices in TCM\n",
-					__FUNCTION__));
-				bus->dhd->dma_d2h_ring_upd_support = FALSE;
-			}
-		}
-
-		/* read ringmem and ringstate ptrs from shared area and store in host variables */
-		dhd_fillup_ring_sharedptr_info(bus, &ring_info);
-
-		bcm_print_bytes("ring_info_raw", (uchar *)&ring_info, sizeof(ring_info_t));
-		DHD_INFO(("ring_info\n"));
-
-		DHD_ERROR(("%s: max H2D queues %d\n",
-			__FUNCTION__, ltoh16(ring_info.max_sub_queues)));
-
-		DHD_INFO(("mail box address\n"));
-		DHD_INFO(("%s: h2d_mb_data_ptr_addr 0x%04x\n",
-			__FUNCTION__, bus->h2d_mb_data_ptr_addr));
-		DHD_INFO(("%s: d2h_mb_data_ptr_addr 0x%04x\n",
-			__FUNCTION__, bus->d2h_mb_data_ptr_addr));
-	}
-
-	bus->dhd->d2h_sync_mode = sh->flags & PCIE_SHARED_D2H_SYNC_MODE_MASK;
-	DHD_INFO(("%s: d2h_sync_mode 0x%08x\n",
-		__FUNCTION__, bus->dhd->d2h_sync_mode));
-
-	return BCME_OK;
-} /* dhdpcie_readshared */
-
-/** Read ring mem and ring state ptr info from shared memory area in device memory */
-static void
-dhd_fillup_ring_sharedptr_info(dhd_bus_t *bus, ring_info_t *ring_info)
-{
-	uint16 i = 0;
-	uint16 j = 0;
-	uint32 tcm_memloc;
-	uint32	d2h_w_idx_ptr, d2h_r_idx_ptr, h2d_w_idx_ptr, h2d_r_idx_ptr;
-
-	/* Ring mem ptr info */
-	/* Alloated in the order
-		H2D_MSGRING_CONTROL_SUBMIT              0
-		H2D_MSGRING_RXPOST_SUBMIT               1
-		D2H_MSGRING_CONTROL_COMPLETE            2
-		D2H_MSGRING_TX_COMPLETE                 3
-		D2H_MSGRING_RX_COMPLETE                 4
-	*/
-
-	{
-		/* ringmemptr holds start of the mem block address space */
-		tcm_memloc = ltoh32(ring_info->ringmem_ptr);
-
-		/* Find out ringmem ptr for each ring common  ring */
-		for (i = 0; i <= BCMPCIE_COMMON_MSGRING_MAX_ID; i++) {
-			bus->ring_sh[i].ring_mem_addr = tcm_memloc;
-			/* Update mem block */
-			tcm_memloc = tcm_memloc + sizeof(ring_mem_t);
-			DHD_INFO(("ring id %d ring mem addr 0x%04x \n",
-				i, bus->ring_sh[i].ring_mem_addr));
-		}
-	}
-
-	/* Ring state mem ptr info */
-	{
-		d2h_w_idx_ptr = ltoh32(ring_info->d2h_w_idx_ptr);
-		d2h_r_idx_ptr = ltoh32(ring_info->d2h_r_idx_ptr);
-		h2d_w_idx_ptr = ltoh32(ring_info->h2d_w_idx_ptr);
-		h2d_r_idx_ptr = ltoh32(ring_info->h2d_r_idx_ptr);
-
-		/* Store h2d common ring write/read pointers */
-		for (i = 0; i < BCMPCIE_H2D_COMMON_MSGRINGS; i++) {
-			bus->ring_sh[i].ring_state_w = h2d_w_idx_ptr;
-			bus->ring_sh[i].ring_state_r = h2d_r_idx_ptr;
-
-			/* update mem block */
-			h2d_w_idx_ptr = h2d_w_idx_ptr + bus->rw_index_sz;
-			h2d_r_idx_ptr = h2d_r_idx_ptr + bus->rw_index_sz;
-
-			DHD_INFO(("h2d w/r : idx %d write %x read %x \n", i,
-				bus->ring_sh[i].ring_state_w, bus->ring_sh[i].ring_state_r));
-		}
-
-		/* Store d2h common ring write/read pointers */
-		for (j = 0; j < BCMPCIE_D2H_COMMON_MSGRINGS; j++, i++) {
-			bus->ring_sh[i].ring_state_w = d2h_w_idx_ptr;
-			bus->ring_sh[i].ring_state_r = d2h_r_idx_ptr;
-
-			/* update mem block */
-			d2h_w_idx_ptr = d2h_w_idx_ptr + bus->rw_index_sz;
-			d2h_r_idx_ptr = d2h_r_idx_ptr + bus->rw_index_sz;
-
-			DHD_INFO(("d2h w/r : idx %d write %x read %x \n", i,
-				bus->ring_sh[i].ring_state_w, bus->ring_sh[i].ring_state_r));
-		}
-
-		/* Store txflow ring write/read pointers */
-		for (j = 0; j < (bus->max_sub_queues - BCMPCIE_H2D_COMMON_MSGRINGS);
-			i++, j++)
-		{
-			bus->ring_sh[i].ring_state_w = h2d_w_idx_ptr;
-			bus->ring_sh[i].ring_state_r = h2d_r_idx_ptr;
-
-			/* update mem block */
-			h2d_w_idx_ptr = h2d_w_idx_ptr + bus->rw_index_sz;
-			h2d_r_idx_ptr = h2d_r_idx_ptr + bus->rw_index_sz;
-
-			DHD_INFO(("FLOW Rings h2d w/r : idx %d write %x read %x \n", i,
-				bus->ring_sh[i].ring_state_w,
-				bus->ring_sh[i].ring_state_r));
-		}
-	}
-} /* dhd_fillup_ring_sharedptr_info */
-
-/**
- * Initialize bus module: prepare for communication with the dongle. Called after downloading
- * firmware into the dongle.
- */
-int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	int  ret = 0;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	ASSERT(bus->dhd);
-	if (!bus->dhd)
-		return 0;
-
-	/* Make sure we're talking to the core. */
-	bus->reg = si_setcore(bus->sih, PCIE2_CORE_ID, 0);
-	ASSERT(bus->reg != NULL);
-
-	/* before opening up bus for data transfer, check if shared are is intact */
-	ret = dhdpcie_readshared(bus);
-	if (ret < 0) {
-		DHD_ERROR(("%s :Shared area read failed \n", __FUNCTION__));
-		return ret;
-	}
-
-	/* Make sure we're talking to the core. */
-	bus->reg = si_setcore(bus->sih, PCIE2_CORE_ID, 0);
-	ASSERT(bus->reg != NULL);
-
-	/* Set bus state according to enable result */
-	dhdp->busstate = DHD_BUS_DATA;
-
-	if (!dhd_download_fw_on_driverload)
-		dhd_dpc_enable(bus->dhd);
-
-	/* Enable the interrupt after device is up */
-	dhdpcie_bus_intr_enable(bus);
-
-	/* bcmsdh_intr_unmask(bus->sdh); */
-
-#ifdef DHD_PCIE_RUNTIMEPM
-	bus->idlecount = 0;
-	bus->idletime = (int32)MAX_IDLE_COUNT;
-	init_waitqueue_head(&bus->rpm_queue);
-	mutex_init(&bus->pm_lock);
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-	bus->d3_ack_war_cnt = 0;
-
-	return ret;
-}
-
-static void
-dhdpcie_init_shared_addr(dhd_bus_t *bus)
-{
-	uint32 addr = 0;
-	uint32 val = 0;
-	addr = bus->dongle_ram_base + bus->ramsize - 4;
-#ifdef DHD_PCIE_RUNTIMEPM
-	dhdpcie_runtime_bus_wake(bus->dhd, TRUE, __builtin_return_address(0));
-#endif /* DHD_PCIE_RUNTIMEPM */
-	DHD_INFO_HW4(("%s: tcm: %p, addr: 0x%x val: 0x%x\n", __FUNCTION__, bus->tcm, addr, val));
-	dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val));
-}
-
-
-bool
-dhdpcie_chipmatch(uint16 vendor, uint16 device)
-{
-	if (vendor != PCI_VENDOR_ID_BROADCOM) {
-		DHD_ERROR(("%s: Unsupported vendor %x device %x\n", __FUNCTION__,
-			vendor, device));
-		return (-ENODEV);
-	}
-
-	if ((device == BCM4350_D11AC_ID) || (device == BCM4350_D11AC2G_ID) ||
-		(device == BCM4350_D11AC5G_ID) || (device == BCM4350_CHIP_ID) ||
-		(device == BCM43569_CHIP_ID))
-		return 0;
-
-	if ((device == BCM4354_D11AC_ID) || (device == BCM4354_D11AC2G_ID) ||
-		(device == BCM4354_D11AC5G_ID) || (device == BCM4354_CHIP_ID))
-		return 0;
-
-	if ((device == BCM4356_D11AC_ID) || (device == BCM4356_D11AC2G_ID) ||
-		(device == BCM4356_D11AC5G_ID) || (device == BCM4356_CHIP_ID))
-		return 0;
-
-	if ((device == BCM4345_D11AC_ID) || (device == BCM4345_D11AC2G_ID) ||
-		(device == BCM4345_D11AC5G_ID) || BCM4345_CHIP(device))
-		return 0;
-
-	if ((device == BCM4335_D11AC_ID) || (device == BCM4335_D11AC2G_ID) ||
-		(device == BCM4335_D11AC5G_ID) || (device == BCM4335_CHIP_ID))
-		return 0;
-
-	if ((device == BCM43602_D11AC_ID) || (device == BCM43602_D11AC2G_ID) ||
-		(device == BCM43602_D11AC5G_ID) || (device == BCM43602_CHIP_ID))
-		return 0;
-
-	if ((device == BCM43569_D11AC_ID) || (device == BCM43569_D11AC2G_ID) ||
-		(device == BCM43569_D11AC5G_ID) || (device == BCM43569_CHIP_ID))
-		return 0;
-
-	if ((device == BCM4358_D11AC_ID) || (device == BCM4358_D11AC2G_ID) ||
-		(device == BCM4358_D11AC5G_ID))
-		return 0;
-
-	if ((device == BCM4349_D11AC_ID) || (device == BCM4349_D11AC2G_ID) ||
-		(device == BCM4349_D11AC5G_ID) || (device == BCM4349_CHIP_ID))
-		return 0;
-
-	if ((device == BCM4355_D11AC_ID) || (device == BCM4355_D11AC2G_ID) ||
-		(device == BCM4355_D11AC5G_ID) || (device == BCM4355_CHIP_ID))
-		return 0;
-
-	if ((device == BCM4359_D11AC_ID) || (device == BCM4359_D11AC2G_ID) ||
-		(device == BCM4359_D11AC5G_ID))
-		return 0;
-
-	if ((device == BCM43596_D11AC_ID) || (device == BCM43596_D11AC2G_ID) ||
-		(device == BCM43596_D11AC5G_ID))
-		return 0;
-
-
-	if ((device == BCM4365_D11AC_ID) || (device == BCM4365_D11AC2G_ID) ||
-		(device == BCM4365_D11AC5G_ID) || (device == BCM4365_CHIP_ID))
-		return 0;
-
-	if ((device == BCM4366_D11AC_ID) || (device == BCM4366_D11AC2G_ID) ||
-		(device == BCM4366_D11AC5G_ID) || (device == BCM4366_CHIP_ID))
-		return 0;
-
-	DHD_ERROR(("%s: Unsupported vendor %x device %x\n", __FUNCTION__, vendor, device));
-	return (-ENODEV);
-} /* dhdpcie_chipmatch */
-
-/**
- * Name:  dhdpcie_cc_nvmshadow
- *
- * Description:
- * A shadow of OTP/SPROM exists in ChipCommon Region
- * betw. 0x800 and 0xBFF (Backplane Addr. 0x1800_0800 and 0x1800_0BFF).
- * Strapping option (SPROM vs. OTP), presence of OTP/SPROM and its size
- * can also be read from ChipCommon Registers.
- */
-static int
-dhdpcie_cc_nvmshadow(dhd_bus_t *bus, struct bcmstrbuf *b)
-{
-	uint16 dump_offset = 0;
-	uint32 dump_size = 0, otp_size = 0, sprom_size = 0;
-
-	/* Table for 65nm OTP Size (in bits) */
-	int  otp_size_65nm[8] = {0, 2048, 4096, 8192, 4096, 6144, 512, 1024};
-
-	volatile uint16 *nvm_shadow;
-
-	uint cur_coreid;
-	uint chipc_corerev;
-	chipcregs_t *chipcregs;
-
-	/* Save the current core */
-	cur_coreid = si_coreid(bus->sih);
-	/* Switch to ChipC */
-	chipcregs = (chipcregs_t *)si_setcore(bus->sih, CC_CORE_ID, 0);
-	ASSERT(chipcregs != NULL);
-
-	chipc_corerev = si_corerev(bus->sih);
-
-	/* Check ChipcommonCore Rev */
-	if (chipc_corerev < 44) {
-		DHD_ERROR(("%s: ChipcommonCore Rev %d < 44\n", __FUNCTION__, chipc_corerev));
-		return BCME_UNSUPPORTED;
-	}
-
-	/* Check ChipID */
-	if (((uint16)bus->sih->chip != BCM4350_CHIP_ID) && !BCM4345_CHIP((uint16)bus->sih->chip)) {
-		DHD_ERROR(("%s: cc_nvmdump cmd. supported for 4350/4345 only\n",
-			__FUNCTION__));
-		return BCME_UNSUPPORTED;
-	}
-
-	/* Check if SRC_PRESENT in SpromCtrl(0x190 in ChipCommon Regs) is set */
-	if (chipcregs->sromcontrol & SRC_PRESENT) {
-		/* SPROM Size: 1Kbits (0x0), 4Kbits (0x1), 16Kbits(0x2) */
-		sprom_size = (1 << (2 * ((chipcregs->sromcontrol & SRC_SIZE_MASK)
-					>> SRC_SIZE_SHIFT))) * 1024;
-		bcm_bprintf(b, "\nSPROM Present (Size %d bits)\n", sprom_size);
-	}
-
-	if (chipcregs->sromcontrol & SRC_OTPPRESENT) {
-		bcm_bprintf(b, "\nOTP Present");
-
-		if (((chipcregs->otplayout & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT)
-			== OTPL_WRAP_TYPE_40NM) {
-			/* 40nm OTP: Size = (OtpSize + 1) * 1024 bits */
-			otp_size =  (((chipcregs->capabilities & CC_CAP_OTPSIZE)
-				        >> CC_CAP_OTPSIZE_SHIFT) + 1) * 1024;
-			bcm_bprintf(b, "(Size %d bits)\n", otp_size);
-		} else {
-			/* This part is untested since newer chips have 40nm OTP */
-			otp_size = otp_size_65nm[(chipcregs->capabilities & CC_CAP_OTPSIZE)
-				        >> CC_CAP_OTPSIZE_SHIFT];
-			bcm_bprintf(b, "(Size %d bits)\n", otp_size);
-			DHD_INFO(("%s: 65nm/130nm OTP Size not tested. \n",
-				__FUNCTION__));
-		}
-	}
-
-	if (((chipcregs->sromcontrol & SRC_PRESENT) == 0) &&
-		((chipcregs->capabilities & CC_CAP_OTPSIZE) == 0)) {
-		DHD_ERROR(("%s: SPROM and OTP could not be found \n",
-			__FUNCTION__));
-		return BCME_NOTFOUND;
-	}
-
-	/* Check the strapping option in SpromCtrl: Set = OTP otherwise SPROM */
-	if ((chipcregs->sromcontrol & SRC_OTPSEL) &&
-		(chipcregs->sromcontrol & SRC_OTPPRESENT)) {
-
-		bcm_bprintf(b, "OTP Strap selected.\n"
-		               "\nOTP Shadow in ChipCommon:\n");
-
-		dump_size = otp_size / 16 ; /* 16bit words */
-
-	} else if (((chipcregs->sromcontrol & SRC_OTPSEL) == 0) &&
-		(chipcregs->sromcontrol & SRC_PRESENT)) {
-
-		bcm_bprintf(b, "SPROM Strap selected\n"
-				"\nSPROM Shadow in ChipCommon:\n");
-
-		/* If SPROM > 8K only 8Kbits is mapped to ChipCommon (0x800 - 0xBFF) */
-		/* dump_size in 16bit words */
-		dump_size = sprom_size > 8 ? (8 * 1024) / 16 : sprom_size / 16;
-	} else {
-		DHD_ERROR(("%s: NVM Shadow does not exist in ChipCommon\n",
-			__FUNCTION__));
-		return BCME_NOTFOUND;
-	}
-
-	if (bus->regs == NULL) {
-		DHD_ERROR(("ChipCommon Regs. not initialized\n"));
-		return BCME_NOTREADY;
-	} else {
-	    bcm_bprintf(b, "\n OffSet:");
-
-	    /* Point to the SPROM/OTP shadow in ChipCommon */
-	    nvm_shadow = chipcregs->sromotp;
-
-	   /*
-	    * Read 16 bits / iteration.
-	    * dump_size & dump_offset in 16-bit words
-	    */
-	    while (dump_offset < dump_size) {
-		if (dump_offset % 2 == 0)
-			/* Print the offset in the shadow space in Bytes */
-			bcm_bprintf(b, "\n 0x%04x", dump_offset * 2);
-
-		bcm_bprintf(b, "\t0x%04x", *(nvm_shadow + dump_offset));
-		dump_offset += 0x1;
-	    }
-	}
-
-	/* Switch back to the original core */
-	si_setcore(bus->sih, cur_coreid, 0);
-
-	return BCME_OK;
-} /* dhdpcie_cc_nvmshadow */
-
-/** Flow rings are dynamically created and destroyed */
-void dhd_bus_clean_flow_ring(dhd_bus_t *bus, void *node)
-{
-	void *pkt;
-	flow_queue_t *queue;
-	flow_ring_node_t *flow_ring_node = (flow_ring_node_t *)node;
-	unsigned long flags;
-
-	queue = &flow_ring_node->queue;
-
-#ifdef DHDTCPACK_SUPPRESS
-	/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
-	 * when there is a newly coming packet from network stack.
-	 */
-	dhd_tcpack_info_tbl_clean(bus->dhd);
-#endif /* DHDTCPACK_SUPPRESS */
-
-	/* clean up BUS level info */
-	DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-
-	/* Flush all pending packets in the queue, if any */
-	while ((pkt = dhd_flow_queue_dequeue(bus->dhd, queue)) != NULL) {
-		PKTFREE(bus->dhd->osh, pkt, TRUE);
-	}
-	ASSERT(DHD_FLOW_QUEUE_EMPTY(queue));
-
-	flow_ring_node->status = FLOW_RING_STATUS_CLOSED;
-	flow_ring_node->active = FALSE;
-
-	DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-
-	DHD_FLOWRING_LIST_LOCK(bus->dhd->flowring_list_lock, flags);
-	dll_delete(&flow_ring_node->list);
-	DHD_FLOWRING_LIST_UNLOCK(bus->dhd->flowring_list_lock, flags);
-
-	/* Release the flowring object back into the pool */
-	dhd_prot_flowrings_pool_release(bus->dhd,
-		flow_ring_node->flowid, flow_ring_node->prot_info);
-
-	/* Free the flowid back to the flowid allocator */
-	dhd_flowid_free(bus->dhd, flow_ring_node->flow_info.ifindex,
-		flow_ring_node->flowid);
-}
-
-/**
- * Allocate a Flow ring buffer,
- * Init Ring buffer, send Msg to device about flow ring creation
-*/
-int
-dhd_bus_flow_ring_create_request(dhd_bus_t *bus, void *arg)
-{
-	flow_ring_node_t *flow_ring_node = (flow_ring_node_t *)arg;
-
-	DHD_INFO(("%s :Flow create\n", __FUNCTION__));
-
-	/* Send Msg to device about flow ring creation */
-	if (dhd_prot_flow_ring_create(bus->dhd, flow_ring_node) != BCME_OK)
-		return BCME_NOMEM;
-
-	return BCME_OK;
-}
-
-/** Handle response from dongle on a 'flow ring create' request */
-void
-dhd_bus_flow_ring_create_response(dhd_bus_t *bus, uint16 flowid, int32 status)
-{
-	flow_ring_node_t *flow_ring_node;
-	unsigned long flags;
-
-	DHD_INFO(("%s :Flow Response %d \n", __FUNCTION__, flowid));
-
-	flow_ring_node = DHD_FLOW_RING(bus->dhd, flowid);
-	ASSERT(flow_ring_node->flowid == flowid);
-
-	if (status != BCME_OK) {
-		DHD_ERROR(("%s Flow create Response failure error status = %d \n",
-		     __FUNCTION__, status));
-		/* Call Flow clean up */
-		dhd_bus_clean_flow_ring(bus, flow_ring_node);
-		return;
-	}
-
-	DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-	flow_ring_node->status = FLOW_RING_STATUS_OPEN;
-	DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-
-	/* Now add the Flow ring node into the active list
-	 * Note that this code to add the newly created node to the active
-	 * list was living in dhd_flowid_lookup. But note that after
-	 * adding the node to the active list the contents of node is being
-	 * filled in dhd_prot_flow_ring_create.
-	 * If there is a D2H interrupt after the node gets added to the
-	 * active list and before the node gets populated with values
-	 * from the Bottom half dhd_update_txflowrings would be called.
-	 * which will then try to walk through the active flow ring list,
-	 * pickup the nodes and operate on them. Now note that since
-	 * the function dhd_prot_flow_ring_create is not finished yet
-	 * the contents of flow_ring_node can still be NULL leading to
-	 * crashes. Hence the flow_ring_node should be added to the
-	 * active list only after its truely created, which is after
-	 * receiving the create response message from the Host.
-	 */
-
-	DHD_FLOWRING_LIST_LOCK(bus->dhd->flowring_list_lock, flags);
-	dll_prepend(&bus->const_flowring, &flow_ring_node->list);
-	DHD_FLOWRING_LIST_UNLOCK(bus->dhd->flowring_list_lock, flags);
-
-	dhd_bus_schedule_queue(bus, flowid, FALSE); /* from queue to flowring */
-
-	return;
-}
-
-int
-dhd_bus_flow_ring_delete_request(dhd_bus_t *bus, void *arg)
-{
-	void * pkt;
-	flow_queue_t *queue;
-	flow_ring_node_t *flow_ring_node;
-	unsigned long flags;
-
-	DHD_INFO(("%s :Flow Delete\n", __FUNCTION__));
-
-	flow_ring_node = (flow_ring_node_t *)arg;
-
-	DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-	if (flow_ring_node->status == FLOW_RING_STATUS_DELETE_PENDING) {
-		DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-		DHD_ERROR(("%s :Delete Pending Flow %d\n",
-			__FUNCTION__, flow_ring_node->flowid));
-		return BCME_ERROR;
-	}
-	flow_ring_node->status = FLOW_RING_STATUS_DELETE_PENDING;
-
-	queue = &flow_ring_node->queue; /* queue associated with flow ring */
-
-#ifdef DHDTCPACK_SUPPRESS
-	/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
-	 * when there is a newly coming packet from network stack.
-	 */
-	dhd_tcpack_info_tbl_clean(bus->dhd);
-#endif /* DHDTCPACK_SUPPRESS */
-	/* Flush all pending packets in the queue, if any */
-	while ((pkt = dhd_flow_queue_dequeue(bus->dhd, queue)) != NULL) {
-		PKTFREE(bus->dhd->osh, pkt, TRUE);
-	}
-	ASSERT(DHD_FLOW_QUEUE_EMPTY(queue));
-
-	DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-
-	/* Send Msg to device about flow ring deletion */
-	dhd_prot_flow_ring_delete(bus->dhd, flow_ring_node);
-
-	return BCME_OK;
-}
-
-void
-dhd_bus_flow_ring_delete_response(dhd_bus_t *bus, uint16 flowid, uint32 status)
-{
-	flow_ring_node_t *flow_ring_node;
-
-	DHD_INFO(("%s :Flow Delete Response %d \n", __FUNCTION__, flowid));
-
-	flow_ring_node = DHD_FLOW_RING(bus->dhd, flowid);
-	ASSERT(flow_ring_node->flowid == flowid);
-
-	if (status != BCME_OK) {
-		DHD_ERROR(("%s Flow Delete Response failure error status = %d \n",
-		    __FUNCTION__, status));
-		return;
-	}
-	/* Call Flow clean up */
-	dhd_bus_clean_flow_ring(bus, flow_ring_node);
-
-	return;
-
-}
-
-/** This function is not called. Obsolete ? */
-int dhd_bus_flow_ring_flush_request(dhd_bus_t *bus, void *arg)
-{
-	void *pkt;
-	flow_queue_t *queue;
-	flow_ring_node_t *flow_ring_node;
-	unsigned long flags;
-
-	DHD_INFO(("%s :Flow Delete\n", __FUNCTION__));
-
-	flow_ring_node = (flow_ring_node_t *)arg;
-	queue = &flow_ring_node->queue; /* queue associated with flow ring */
-
-	DHD_FLOWRING_LOCK(flow_ring_node->lock, flags);
-
-#ifdef DHDTCPACK_SUPPRESS
-	/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
-	 * when there is a newly coming packet from network stack.
-	 */
-	dhd_tcpack_info_tbl_clean(bus->dhd);
-#endif /* DHDTCPACK_SUPPRESS */
-
-	/* Flush all pending packets in the queue, if any */
-	while ((pkt = dhd_flow_queue_dequeue(bus->dhd, queue)) != NULL) {
-		PKTFREE(bus->dhd->osh, pkt, TRUE);
-	}
-	ASSERT(DHD_FLOW_QUEUE_EMPTY(queue));
-
-	DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
-
-	/* Send Msg to device about flow ring flush */
-	dhd_prot_flow_ring_flush(bus->dhd, flow_ring_node);
-
-	flow_ring_node->status = FLOW_RING_STATUS_FLUSH_PENDING;
-	return BCME_OK;
-}
-
-void
-dhd_bus_flow_ring_flush_response(dhd_bus_t *bus, uint16 flowid, uint32 status)
-{
-	flow_ring_node_t *flow_ring_node;
-
-	if (status != BCME_OK) {
-		DHD_ERROR(("%s Flow flush Response failure error status = %d \n",
-		    __FUNCTION__, status));
-		return;
-	}
-
-	flow_ring_node = DHD_FLOW_RING(bus->dhd, flowid);
-	ASSERT(flow_ring_node->flowid == flowid);
-
-	flow_ring_node->status = FLOW_RING_STATUS_OPEN;
-	return;
-}
-
-uint32
-dhd_bus_max_h2d_queues(struct dhd_bus *bus)
-{
-	return bus->max_sub_queues;
-}
-
-/* To be symmetric with SDIO */
-void
-dhd_bus_pktq_flush(dhd_pub_t *dhdp)
-{
-	return;
-}
-
-void
-dhd_bus_set_linkdown(dhd_pub_t *dhdp, bool val)
-{
-	dhdp->bus->is_linkdown = val;
-}
-
-int
-dhdpcie_bus_clock_start(struct dhd_bus *bus)
-{
-	return dhdpcie_start_host_pcieclock(bus);
-}
-
-int
-dhdpcie_bus_clock_stop(struct dhd_bus *bus)
-{
-	return dhdpcie_stop_host_pcieclock(bus);
-}
-
-int
-dhdpcie_bus_disable_device(struct dhd_bus *bus)
-{
-	return dhdpcie_disable_device(bus);
-}
-
-int
-dhdpcie_bus_enable_device(struct dhd_bus *bus)
-{
-	return dhdpcie_enable_device(bus);
-}
-
-int
-dhdpcie_bus_alloc_resource(struct dhd_bus *bus)
-{
-	return dhdpcie_alloc_resource(bus);
-}
-
-void
-dhdpcie_bus_free_resource(struct dhd_bus *bus)
-{
-	dhdpcie_free_resource(bus);
-}
-
-int
-dhd_bus_request_irq(struct dhd_bus *bus)
-{
-	return dhdpcie_bus_request_irq(bus);
-}
-
-bool
-dhdpcie_bus_dongle_attach(struct dhd_bus *bus)
-{
-	return dhdpcie_dongle_attach(bus);
-}
-
-int
-dhd_bus_release_dongle(struct dhd_bus *bus)
-{
-	bool dongle_isolation;
-	osl_t *osh;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (bus) {
-		osh = bus->osh;
-		ASSERT(osh);
-
-		if (bus->dhd) {
-			dongle_isolation = bus->dhd->dongle_isolation;
-			dhdpcie_bus_release_dongle(bus, osh, dongle_isolation, TRUE);
-		}
-	}
-
-	return 0;
-}
-
-#ifdef BCMPCIE_OOB_HOST_WAKE
-int
-dhd_bus_oob_intr_register(dhd_pub_t *dhdp)
-{
-	return dhdpcie_oob_intr_register(dhdp->bus);
-}
-
-void
-dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp)
-{
-	dhdpcie_oob_intr_unregister(dhdp->bus);
-}
-
-void
-dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable)
-{
-	dhdpcie_oob_intr_set(dhdp->bus, enable);
-}
-#endif /* BCMPCIE_OOB_HOST_WAKE */
diff --git a/drivers/net/wireless/bcmdhd/dhd_pcie.h b/drivers/net/wireless/bcmdhd/dhd_pcie.h
deleted file mode 100644
index 511d00e..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_pcie.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Linux DHD Bus Module for PCIE
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_pcie.h 607608 2015-12-21 13:14:19Z $
- */
-
-
-#ifndef dhd_pcie_h
-#define dhd_pcie_h
-
-#include <bcmpcie.h>
-#include <hnd_cons.h>
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#ifdef CONFIG_ARCH_MSM
-#ifdef CONFIG_PCI_MSM
-#include <linux/msm_pcie.h>
-#else
-#include <mach/msm_pcie.h>
-#endif /* CONFIG_PCI_MSM */
-#endif /* CONFIG_ARCH_MSM */
-#ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY
-#ifdef CONFIG_SOC_EXYNOS8890
-#include <linux/exynos-pci-noti.h>
-extern int exynos_pcie_register_event(struct exynos_pcie_register_event *reg);
-extern int exynos_pcie_deregister_event(struct exynos_pcie_register_event *reg);
-#endif /* CONFIG_SOC_EXYNOS8890 */
-#endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-
-#ifdef DHD_PCIE_RUNTIMEPM
-#include <linux/mutex.h>
-#include <linux/wait.h>
-
-#define DEFAULT_DHD_RUNTIME_MS 100
-#ifndef CUSTOM_DHD_RUNTIME_MS
-#define CUSTOM_DHD_RUNTIME_MS DEFAULT_DHD_RUNTIME_MS
-#endif /* CUSTOM_DHD_RUNTIME_MS */
-
-
-#ifndef MAX_IDLE_COUNT
-#define MAX_IDLE_COUNT 16
-#endif /* MAX_IDLE_COUNT */
-
-#ifndef MAX_RESUME_WAIT
-#define MAX_RESUME_WAIT 100
-#endif /* MAX_RESUME_WAIT */
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-/* defines */
-
-#define PCMSGBUF_HDRLEN 0
-#define DONGLE_REG_MAP_SIZE (32 * 1024)
-#define DONGLE_TCM_MAP_SIZE (4096 * 1024)
-#define DONGLE_MIN_MEMSIZE (128 *1024)
-#ifdef DHD_DEBUG
-#define DHD_PCIE_SUCCESS 0
-#define DHD_PCIE_FAILURE 1
-#endif /* DHD_DEBUG */
-#define	REMAP_ENAB(bus)			((bus)->remap)
-#define	REMAP_ISADDR(bus, a)		(((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize)))
-
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#ifdef CONFIG_ARCH_MSM
-#define struct_pcie_notify		struct msm_pcie_notify
-#define struct_pcie_register_event	struct msm_pcie_register_event
-#endif /* CONFIG_ARCH_MSM */
-#ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY
-#ifdef CONFIG_SOC_EXYNOS8890
-#define struct_pcie_notify		struct exynos_pcie_notify
-#define struct_pcie_register_event	struct exynos_pcie_register_event
-#endif /* CONFIG_SOC_EXYNOS8890 */
-#endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-
-/*
- * Router with 4366 can have 128 stations and 16 BSS,
- * hence (128 stations x 4 access categories for ucast) + 16 bc/mc flowrings
- */
-#define MAX_DHD_TX_FLOWS	320
-
-/* user defined data structures */
-/* Device console log buffer state */
-#define CONSOLE_LINE_MAX	192
-#define CONSOLE_BUFFER_MAX	(8 * 1024)
-
-#ifndef MAX_CNTL_D3ACK_TIMEOUT
-#define MAX_CNTL_D3ACK_TIMEOUT 2
-#endif /* MAX_CNTL_D3ACK_TIMEOUT */
-
-#ifdef DHD_DEBUG
-
-typedef struct dhd_console {
-	 uint		count;	/* Poll interval msec counter */
-	 uint		log_addr;		 /* Log struct address (fixed) */
-	 hnd_log_t	 log;			 /* Log struct (host copy) */
-	 uint		 bufsize;		 /* Size of log buffer */
-	 uint8		 *buf;			 /* Log buffer (host copy) */
-	 uint		 last;			 /* Last buffer read index */
-} dhd_console_t;
-#endif /* DHD_DEBUG */
-typedef struct ring_sh_info {
-	uint32 ring_mem_addr;
-	uint32 ring_state_w;
-	uint32 ring_state_r;
-} ring_sh_info_t;
-
-typedef struct dhd_bus {
-	dhd_pub_t	*dhd;
-	struct pci_dev  *dev;		/* pci device handle */
-	dll_t       const_flowring; /* constructed list of tx flowring queues */
-
-	si_t		*sih;			/* Handle for SI calls */
-	char		*vars;			/* Variables (from CIS and/or other) */
-	uint		varsz;			/* Size of variables buffer */
-	uint32		sbaddr;			/* Current SB window pointer (-1, invalid) */
-	sbpcieregs_t	*reg;			/* Registers for PCIE core */
-
-	uint		armrev;			/* CPU core revision */
-	uint		ramrev;			/* SOCRAM core revision */
-	uint32		ramsize;		/* Size of RAM in SOCRAM (bytes) */
-	uint32		orig_ramsize;		/* Size of RAM in SOCRAM (bytes) */
-	uint32		srmemsize;		/* Size of SRMEM */
-
-	uint32		bus;			/* gSPI or SDIO bus */
-	uint32		intstatus;		/* Intstatus bits (events) pending */
-	bool		dpc_sched;		/* Indicates DPC schedule (intrpt rcvd) */
-	bool		fcstate;		/* State of dongle flow-control */
-
-	uint16		cl_devid;		/* cached devid for dhdsdio_probe_attach() */
-	char		*fw_path;		/* module_param: path to firmware image */
-	char		*nv_path;		/* module_param: path to nvram vars file */
-#ifdef CACHE_FW_IMAGES
-	int			processed_nvram_params_len;	/* Modified len of NVRAM info */
-#endif
-
-
-	struct pktq	txq;			/* Queue length used for flow-control */
-
-	bool		intr;			/* Use interrupts */
-	bool		ipend;			/* Device interrupt is pending */
-	bool		intdis;			/* Interrupts disabled by isr */
-	uint		intrcount;		/* Count of device interrupt callbacks */
-	uint		lastintrs;		/* Count as of last watchdog timer */
-
-#ifdef DHD_DEBUG
-	dhd_console_t	console;		/* Console output polling support */
-	uint		console_addr;		/* Console address from shared struct */
-#endif /* DHD_DEBUG */
-
-	bool		alp_only;		/* Don't use HT clock (ALP only) */
-
-	bool		remap;		/* Contiguous 1MB RAM: 512K socram + 512K devram
-					 * Available with socram rev 16
-					 * Remap region not DMA-able
-					 */
-	uint32		resetinstr;
-	uint32		dongle_ram_base;
-
-	ulong		shared_addr;
-	pciedev_shared_t	*pcie_sh;
-	bool bus_flowctrl;
-	uint32		dma_rxoffset;
-	volatile char	*regs;		/* pci device memory va */
-	volatile char	*tcm;		/* pci device memory va */
-	osl_t		*osh;
-	uint32		nvram_csm;	/* Nvram checksum */
-	uint16		pollrate;
-	uint16  polltick;
-
-	uint32  *pcie_mb_intr_addr;
-	void    *pcie_mb_intr_osh;
-	bool	sleep_allowed;
-
-	/* version 3 shared struct related info start */
-	ring_sh_info_t	ring_sh[BCMPCIE_COMMON_MSGRINGS + MAX_DHD_TX_FLOWS];
-	uint8	h2d_ring_count;
-	uint8	d2h_ring_count;
-	uint32  ringmem_ptr;
-	uint32  ring_state_ptr;
-
-	uint32 d2h_dma_scratch_buffer_mem_addr;
-
-	uint32 h2d_mb_data_ptr_addr;
-	uint32 d2h_mb_data_ptr_addr;
-	/* version 3 shared struct related info end */
-
-	uint32 def_intmask;
-	bool	ltrsleep_on_unload;
-	uint	wait_for_d3_ack;
-	uint32 max_sub_queues;
-	uint32	rw_index_sz;
-	bool	db1_for_mb;
-	bool	suspended;
-
-	dhd_timeout_t doorbell_timer;
-	bool	device_wake_state;
-	bool	irq_registered;
-#ifdef PCIE_OOB
-	bool	oob_enabled;
-#endif /* PCIE_OOB */
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#if defined(CONFIG_ARCH_MSM) || (defined(EXYNOS_PCIE_LINKDOWN_RECOVERY) && \
-	defined(CONFIG_SOC_EXYNOS8890))
-#ifdef CONFIG_ARCH_MSM
-	uint8 no_cfg_restore;
-#endif /* CONFIG_ARCH_MSM */
-	struct_pcie_register_event pcie_event;
-#endif /* CONFIG_ARCH_MSM || (EXYNOS_PCIE_LINKDOWN_RECOVERY && CONFIG_SOC_EXYNOS8890) */
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-#ifdef DHD_PCIE_RUNTIMEPM
-	int32 idlecount;                /* Activity timeout counter */
-	int32 idletime;                 /* Control for activity timeout */
-	int32 bus_wake;                 /* For wake up the bus */
-	bool runtime_resume_done;       /* For check runtime suspend end */
-	struct mutex pm_lock;            /* Synchronize for system PM & runtime PM */
-	wait_queue_head_t rpm_queue;    /* wait-queue for bus wake up */
-#endif /* DHD_PCIE_RUNTIMEPM */
-	uint32 d3_inform_cnt;
-	uint32 d0_inform_cnt;
-	uint32 d0_inform_in_use_cnt;
-	uint8 force_suspend;
-	uint32 d3_ack_war_cnt;
-	uint8 is_linkdown;
-	uint32 pci_d3hot_done;
-} dhd_bus_t;
-
-/* function declarations */
-
-extern uint32* dhdpcie_bus_reg_map(osl_t *osh, ulong addr, int size);
-extern int dhdpcie_bus_register(void);
-extern void dhdpcie_bus_unregister(void);
-extern bool dhdpcie_chipmatch(uint16 vendor, uint16 device);
-
-extern struct dhd_bus* dhdpcie_bus_attach(osl_t *osh,
-	volatile char *regs, volatile char *tcm, void *pci_dev);
-extern uint32 dhdpcie_bus_cfg_read_dword(struct dhd_bus *bus, uint32 addr, uint32 size);
-extern void dhdpcie_bus_cfg_write_dword(struct dhd_bus *bus, uint32 addr, uint32 size, uint32 data);
-extern void dhdpcie_bus_intr_enable(struct dhd_bus *bus);
-extern void dhdpcie_bus_intr_disable(struct dhd_bus *bus);
-extern void dhdpcie_bus_release(struct dhd_bus *bus);
-extern int32 dhdpcie_bus_isr(struct dhd_bus *bus);
-extern void dhdpcie_free_irq(dhd_bus_t *bus);
-extern void dhdpcie_bus_ringbell_fast(struct dhd_bus *bus, uint32 value);
-extern int dhdpcie_bus_suspend(struct  dhd_bus *bus, bool state);
-extern int dhdpcie_pci_suspend_resume(struct  dhd_bus *bus, bool state);
-extern bool dhdpcie_tcm_valid(dhd_bus_t *bus);
-extern void dhdpcie_bus_dongle_print_hwregs(struct dhd_bus *bus);
-#ifndef BCMPCIE_OOB_HOST_WAKE
-extern void dhdpcie_pme_active(osl_t *osh, bool enable);
-#endif /* !BCMPCIE_OOB_HOST_WAKE */
-extern bool dhdpcie_pme_cap(osl_t *osh);
-extern int dhdpcie_start_host_pcieclock(dhd_bus_t *bus);
-extern int dhdpcie_stop_host_pcieclock(dhd_bus_t *bus);
-extern int dhdpcie_disable_device(dhd_bus_t *bus);
-extern int dhdpcie_enable_device(dhd_bus_t *bus);
-extern int dhdpcie_alloc_resource(dhd_bus_t *bus);
-extern void dhdpcie_free_resource(dhd_bus_t *bus);
-extern int dhdpcie_bus_request_irq(struct dhd_bus *bus);
-#ifdef BCMPCIE_OOB_HOST_WAKE
-extern int dhdpcie_oob_intr_register(dhd_bus_t *bus);
-extern void dhdpcie_oob_intr_unregister(dhd_bus_t *bus);
-extern void dhdpcie_oob_intr_set(dhd_bus_t *bus, bool enable);
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-#ifdef PCIE_OOB
-extern void dhd_oob_set_bt_reg_on(struct dhd_bus *bus, bool val);
-extern int dhd_oob_get_bt_reg_on(struct dhd_bus *bus);
-#endif /* PCIE_OOB */
-
-#ifdef USE_EXYNOS_PCIE_RC_PMPATCH
-#if defined(CONFIG_MACH_UNIVERSAL5433)
-#define SAMSUNG_PCIE_DEVICE_ID 0xa5e3
-#define SAMSUNG_PCIE_CH_NUM
-#elif defined(CONFIG_MACH_UNIVERSAL7420)
-#define SAMSUNG_PCIE_DEVICE_ID 0xa575
-#define SAMSUNG_PCIE_CH_NUM 1
-#elif defined(CONFIG_SOC_EXYNOS8890)
-#define SAMSUNG_PCIE_DEVICE_ID 0xa544
-#define SAMSUNG_PCIE_CH_NUM 0
-#else
-#error "Not supported platform"
-#endif
-#ifdef CONFIG_MACH_UNIVERSAL5433
-extern int exynos_pcie_pm_suspend(void);
-extern int exynos_pcie_pm_resume(void);
-#else
-extern int exynos_pcie_pm_suspend(int ch_num);
-extern int exynos_pcie_pm_resume(int ch_num);
-#endif /* CONFIG_MACH_UNIVERSAL5433 */
-#endif /* USE_EXYNOS_PCIE_RC_PMPATCH */
-
-extern int dhd_buzzz_dump_dngl(dhd_bus_t *bus);
-#endif /* dhd_pcie_h */
diff --git a/drivers/net/wireless/bcmdhd/dhd_pcie_linux.c b/drivers/net/wireless/bcmdhd/dhd_pcie_linux.c
deleted file mode 100644
index e9814d2..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_pcie_linux.c
+++ /dev/null
@@ -1,1562 +0,0 @@
-/*
- * Linux DHD Bus Module for PCIE
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_pcie_linux.c 610267 2016-01-06 16:03:53Z $
- */
-
-
-/* include files */
-#include <typedefs.h>
-#include <bcmutils.h>
-#include <bcmdevs.h>
-#include <siutils.h>
-#include <hndsoc.h>
-#include <hndpmu.h>
-#include <sbchipc.h>
-#if defined(DHD_DEBUG)
-#include <hnd_armtrap.h>
-#include <hnd_cons.h>
-#endif /* defined(DHD_DEBUG) */
-#include <dngl_stats.h>
-#include <pcie_core.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#include <dhdioctl.h>
-#include <bcmmsgbuf.h>
-#include <pcicfg.h>
-#include <dhd_pcie.h>
-#include <dhd_linux.h>
-#ifdef CONFIG_ARCH_MSM
-#ifdef CONFIG_PCI_MSM
-#include <linux/msm_pcie.h>
-#else
-#include <mach/msm_pcie.h>
-#endif /* CONFIG_PCI_MSM */
-#endif /* CONFIG_ARCH_MSM */
-
-#define PCI_CFG_RETRY		10
-#define OS_HANDLE_MAGIC		0x1234abcd	/* Magic # to recognize osh */
-#define BCM_MEM_FILENAME_LEN 	24		/* Mem. filename length */
-
-#define OSL_PKTTAG_CLEAR(p) \
-do { \
-	struct sk_buff *s = (struct sk_buff *)(p); \
-	ASSERT(OSL_PKTTAG_SZ == 32); \
-	*(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \
-	*(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \
-	*(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \
-	*(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \
-} while (0)
-
-
-/* user defined data structures  */
-
-typedef struct dhd_pc_res {
-	uint32 bar0_size;
-	void* bar0_addr;
-	uint32 bar1_size;
-	void* bar1_addr;
-} pci_config_res, *pPci_config_res;
-
-typedef bool (*dhdpcie_cb_fn_t)(void *);
-
-typedef struct dhdpcie_info
-{
-	dhd_bus_t	*bus;
-	osl_t 			*osh;
-	struct pci_dev  *dev;		/* pci device handle */
-	volatile char 	*regs;		/* pci device memory va */
-	volatile char 	*tcm;		/* pci device memory va */
-	uint32			tcm_size;	/* pci device memory size */
-	struct pcos_info *pcos_info;
-	uint16		last_intrstatus;	/* to cache intrstatus */
-	int	irq;
-	char pciname[32];
-	struct pci_saved_state* default_state;
-	struct pci_saved_state* state;
-#ifdef BCMPCIE_OOB_HOST_WAKE
-	void *os_cxt;			/* Pointer to per-OS private data */
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-} dhdpcie_info_t;
-
-
-struct pcos_info {
-	dhdpcie_info_t *pc;
-	spinlock_t lock;
-	wait_queue_head_t intr_wait_queue;
-	struct timer_list tuning_timer;
-	int tuning_timer_exp;
-	atomic_t timer_enab;
-	struct tasklet_struct tuning_tasklet;
-};
-
-#ifdef BCMPCIE_OOB_HOST_WAKE
-typedef struct dhdpcie_os_info {
-	int			oob_irq_num;	/* valid when hardware or software oob in use */
-	unsigned long		oob_irq_flags;	/* valid when hardware or software oob in use */
-	bool			oob_irq_registered;
-	bool			oob_irq_enabled;
-	bool			oob_irq_wake_enabled;
-	spinlock_t		oob_irq_spinlock;
-	void			*dev;		/* handle to the underlying device */
-} dhdpcie_os_info_t;
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-
-/* function declarations */
-static int __devinit
-dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void __devexit
-dhdpcie_pci_remove(struct pci_dev *pdev);
-static int dhdpcie_init(struct pci_dev *pdev);
-static irqreturn_t dhdpcie_isr(int irq, void *arg);
-/* OS Routine functions for PCI suspend/resume */
-
-static int dhdpcie_set_suspend_resume(struct pci_dev *dev, bool state);
-static int dhdpcie_resume_host_dev(dhd_bus_t *bus);
-static int dhdpcie_suspend_host_dev(dhd_bus_t *bus);
-static int dhdpcie_resume_dev(struct pci_dev *dev);
-static int dhdpcie_suspend_dev(struct pci_dev *dev);
-#ifdef DHD_PCIE_RUNTIMEPM
-static int dhdpcie_pm_suspend(struct device *dev);
-static int dhdpcie_pm_prepare(struct device *dev);
-static int dhdpcie_pm_resume(struct device *dev);
-static void dhdpcie_pm_complete(struct device *dev);
-#else
-static int dhdpcie_pci_suspend(struct pci_dev *dev, pm_message_t state);
-static int dhdpcie_pci_resume(struct pci_dev *dev);
-#endif /* DHD_PCIE_RUNTIMEPM */
-static struct pci_device_id dhdpcie_pci_devid[] __devinitdata = {
-	{ vendor: 0x14e4,
-	device: PCI_ANY_ID,
-	subvendor: PCI_ANY_ID,
-	subdevice: PCI_ANY_ID,
-	class: PCI_CLASS_NETWORK_OTHER << 8,
-	class_mask: 0xffff00,
-	driver_data: 0,
-	},
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, dhdpcie_pci_devid);
-
-/* Power Management Hooks */
-#ifdef DHD_PCIE_RUNTIMEPM
-static const struct dev_pm_ops dhd_pcie_pm_ops = {
-	.prepare = dhdpcie_pm_prepare,
-	.suspend = dhdpcie_pm_suspend,
-	.resume = dhdpcie_pm_resume,
-	.complete = dhdpcie_pm_complete,
-};
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-static struct pci_driver dhdpcie_driver = {
-	node:		{},
-	name:		"pcieh",
-	id_table:	dhdpcie_pci_devid,
-	probe:		dhdpcie_pci_probe,
-	remove:		dhdpcie_pci_remove,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-	save_state:	NULL,
-#endif
-#ifdef DHD_PCIE_RUNTIMEPM
-	.driver.pm = &dhd_pcie_pm_ops,
-#else
-	suspend:	dhdpcie_pci_suspend,
-	resume:		dhdpcie_pci_resume,
-#endif /* DHD_PCIE_RUNTIMEPM */
-};
-
-int dhdpcie_init_succeeded = FALSE;
-
-#ifdef DHD_PCIE_RUNTIMEPM
-static int dhdpcie_pm_suspend(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	return dhdpcie_set_suspend_resume(pdev, TRUE);
-}
-
-static int dhdpcie_pm_prepare(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	dhdpcie_info_t *pch = pci_get_drvdata(pdev);
-	dhd_bus_t *bus = NULL;
-
-	if (pch) {
-		bus = pch->bus;
-		DHD_DISABLE_RUNTIME_PM(bus->dhd);
-	}
-
-	return 0;
-}
-
-static int dhdpcie_pm_resume(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	return dhdpcie_set_suspend_resume(pdev, FALSE);
-}
-
-static void dhdpcie_pm_complete(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	dhdpcie_info_t *pch = pci_get_drvdata(pdev);
-	dhd_bus_t *bus = NULL;
-
-	if (pch) {
-		bus = pch->bus;
-		DHD_ENABLE_RUNTIME_PM(bus->dhd);
-	}
-
-	return;
-}
-#else
-static int dhdpcie_pci_suspend(struct pci_dev * pdev, pm_message_t state)
-{
-	BCM_REFERENCE(state);
-	return dhdpcie_set_suspend_resume(pdev, TRUE);
-}
-
-static int dhdpcie_pci_resume(struct pci_dev *pdev)
-{
-	return dhdpcie_set_suspend_resume(pdev, FALSE);
-}
-
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-static int dhdpcie_set_suspend_resume(struct pci_dev *pdev, bool state)
-{
-	int ret = 0;
-	dhdpcie_info_t *pch = pci_get_drvdata(pdev);
-	dhd_bus_t *bus = NULL;
-
-	if (pch) {
-		bus = pch->bus;
-	}
-
-#ifdef DHD_PCIE_RUNTIMEPM
-	if (bus && !bus->dhd->dongle_reset) {
-		/* if wakelock is held during suspend, return failed */
-		if (state == TRUE && dhd_os_check_wakelock_all(bus->dhd)) {
-			return -EBUSY;
-		}
-
-		mutex_lock(&bus->pm_lock);
-	}
-#endif /* DHD_PCIE_RUNTIMEPM */
-
-	/* When firmware is not loaded do the PCI bus */
-	/* suspend/resume only */
-	if (bus && (bus->dhd->busstate == DHD_BUS_DOWN) &&
-		!bus->dhd->dongle_reset) {
-		ret = dhdpcie_pci_suspend_resume(bus, state);
-#ifdef DHD_PCIE_RUNTIMEPM
-		mutex_unlock(&bus->pm_lock);
-#endif /* DHD_PCIE_RUNTIMEPM */
-		return ret;
-	}
-
-	if (bus && ((bus->dhd->busstate == DHD_BUS_SUSPEND)||
-		(bus->dhd->busstate == DHD_BUS_DATA)) &&
-		(bus->suspended != state)) {
-		ret = dhdpcie_bus_suspend(bus, state);
-	}
-
-#ifdef DHD_PCIE_RUNTIMEPM
-	if (bus && !bus->dhd->dongle_reset) {
-		mutex_unlock(&bus->pm_lock);
-	}
-#endif /* DHD_PCIE_RUNTIMEPM */
-	return ret;
-}
-
-static int dhdpcie_suspend_dev(struct pci_dev *dev)
-{
-	int ret;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-	dhdpcie_info_t *pch = pci_get_drvdata(dev);
-	dhd_bus_t *bus = pch->bus;
-
-	if (bus->is_linkdown) {
-		DHD_ERROR(("%s: PCIe link is down\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-#endif /* OEM_ANDROID && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
-	DHD_TRACE_HW4(("%s: Enter\n", __FUNCTION__));
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-	bus->pci_d3hot_done = 1;
-#endif /* OEM_ANDROID && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
-	pci_save_state(dev);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-	pch->state = pci_store_saved_state(dev);
-#endif /* OEM_ANDROID && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
-	pci_enable_wake(dev, PCI_D0, TRUE);
-	if (pci_is_enabled(dev)) {
-		pci_disable_device(dev);
-	}
-	ret = pci_set_power_state(dev, PCI_D3hot);
-	if (ret) {
-		DHD_ERROR(("%s: pci_set_power_state error %d\n",
-			__FUNCTION__, ret));
-	}
-	disable_irq(dev->irq);
-	return ret;
-}
-
-static int dhdpcie_resume_dev(struct pci_dev *dev)
-{
-	int err = 0;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-	dhdpcie_info_t *pch = pci_get_drvdata(dev);
-	dhd_bus_t *bus = pch->bus;
-	pci_load_and_free_saved_state(dev, &pch->state);
-#endif /* OEM_ANDROID && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
-	DHD_TRACE_HW4(("%s: Enter\n", __FUNCTION__));
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-	bus->pci_d3hot_done = 0;
-#endif /* OEM_ANDROID && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
-	pci_restore_state(dev);
-	err = pci_enable_device(dev);
-	if (err) {
-		printf("%s:pci_enable_device error %d \n", __FUNCTION__, err);
-		goto out;
-	}
-	pci_set_master(dev);
-	err = pci_set_power_state(dev, PCI_D0);
-	if (err) {
-		printf("%s:pci_set_power_state error %d \n", __FUNCTION__, err);
-		goto out;
-	}
-
-out:
-	enable_irq(dev->irq);
-	return err;
-}
-
-static int dhdpcie_resume_host_dev(dhd_bus_t *bus)
-{
-	int bcmerror = 0;
-#ifdef USE_EXYNOS_PCIE_RC_PMPATCH
-	bcmerror = exynos_pcie_pm_resume(SAMSUNG_PCIE_CH_NUM);
-#endif /* USE_EXYNOS_PCIE_RC_PMPATCH */
-#ifdef CONFIG_ARCH_MSM
-	bcmerror = dhdpcie_start_host_pcieclock(bus);
-#endif /* CONFIG_ARCH_MSM */
-	if (bcmerror < 0) {
-		DHD_ERROR(("%s: PCIe RC resume failed!!! (%d)\n",
-			__FUNCTION__, bcmerror));
-		bus->is_linkdown = 1;
-#ifdef CONFIG_ARCH_MSM
-		bus->no_cfg_restore = 1;
-#endif /* CONFIG_ARCH_MSM */
-	}
-
-	return bcmerror;
-}
-
-static int dhdpcie_suspend_host_dev(dhd_bus_t *bus)
-{
-	int bcmerror = 0;
-#ifdef USE_EXYNOS_PCIE_RC_PMPATCH
-	struct pci_dev *rc_pci_dev;
-	rc_pci_dev = pci_get_device(0x144d, SAMSUNG_PCIE_DEVICE_ID, NULL);
-	if (rc_pci_dev) {
-		pci_save_state(rc_pci_dev);
-	}
-	exynos_pcie_pm_suspend(SAMSUNG_PCIE_CH_NUM);
-#endif	/* USE_EXYNOS_PCIE_RC_PMPATCH */
-#ifdef CONFIG_ARCH_MSM
-	bcmerror = dhdpcie_stop_host_pcieclock(bus);
-#endif	/* CONFIG_ARCH_MSM */
-	return bcmerror;
-}
-
-int dhdpcie_pci_suspend_resume(dhd_bus_t *bus, bool state)
-{
-	int rc;
-
-	struct pci_dev *dev = bus->dev;
-
-	if (state) {
-		if (bus->is_linkdown) {
-			DHD_ERROR(("%s: PCIe link was down\n", __FUNCTION__));
-			return BCME_ERROR;
-		}
-#ifndef BCMPCIE_OOB_HOST_WAKE
-		dhdpcie_pme_active(bus->osh, state);
-#endif /* !BCMPCIE_OOB_HOST_WAKE */
-		rc = dhdpcie_suspend_dev(dev);
-		if (!rc) {
-			dhdpcie_suspend_host_dev(bus);
-		}
-	} else {
-		dhdpcie_resume_host_dev(bus);
-		rc = dhdpcie_resume_dev(dev);
-#ifndef	BCMPCIE_OOB_HOST_WAKE
-		dhdpcie_pme_active(bus->osh, state);
-#endif /* !BCMPCIE_OOB_HOST_WAKE */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-		if (bus->is_linkdown) {
-			bus->dhd->hang_reason = HANG_REASON_PCIE_RC_LINK_UP_FAIL;
-			dhd_os_send_hang_message(bus->dhd);
-		}
-#endif 
-	}
-	return rc;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-static int dhdpcie_device_scan(struct device *dev, void *data)
-{
-	struct pci_dev *pcidev;
-	int *cnt = data;
-
-	pcidev = container_of(dev, struct pci_dev, dev);
-	if (pcidev->vendor != 0x14e4)
-		return 0;
-
-	DHD_INFO(("Found Broadcom PCI device 0x%04x\n", pcidev->device));
-	*cnt += 1;
-	if (pcidev->driver && strcmp(pcidev->driver->name, dhdpcie_driver.name))
-		DHD_ERROR(("Broadcom PCI Device 0x%04x has allocated with driver %s\n",
-			pcidev->device, pcidev->driver->name));
-
-	return 0;
-}
-#endif /* LINUX_VERSION >= 2.6.0 */
-
-int
-dhdpcie_bus_register(void)
-{
-	int error = 0;
-
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-	if (!(error = pci_module_init(&dhdpcie_driver)))
-		return 0;
-
-	DHD_ERROR(("%s: pci_module_init failed 0x%x\n", __FUNCTION__, error));
-#else
-	if (!(error = pci_register_driver(&dhdpcie_driver))) {
-		bus_for_each_dev(dhdpcie_driver.driver.bus, NULL, &error, dhdpcie_device_scan);
-		if (!error) {
-			DHD_ERROR(("No Broadcom PCI device enumerated!\n"));
-		} else if (!dhdpcie_init_succeeded) {
-			DHD_ERROR(("%s: dhdpcie initialize failed.\n", __FUNCTION__));
-		} else {
-			return 0;
-		}
-
-		pci_unregister_driver(&dhdpcie_driver);
-		error = BCME_ERROR;
-	}
-#endif /* LINUX_VERSION < 2.6.0 */
-
-	return error;
-}
-
-
-void
-dhdpcie_bus_unregister(void)
-{
-	pci_unregister_driver(&dhdpcie_driver);
-}
-
-int __devinit
-dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-
-	if (dhdpcie_chipmatch (pdev->vendor, pdev->device)) {
-		DHD_ERROR(("%s: chipmatch failed!!\n", __FUNCTION__));
-			return -ENODEV;
-	}
-	printf("PCI_PROBE:  bus %X, slot %X,vendor %X, device %X"
-		"(good PCI location)\n", pdev->bus->number,
-		PCI_SLOT(pdev->devfn), pdev->vendor, pdev->device);
-
-	if (dhdpcie_init (pdev)) {
-		DHD_ERROR(("%s: PCIe Enumeration failed\n", __FUNCTION__));
-		return -ENODEV;
-	}
-
-#ifdef BCMPCIE_DISABLE_ASYNC_SUSPEND
-	/* disable async suspend */
-	device_disable_async_suspend(&pdev->dev);
-#endif /* BCMPCIE_DISABLE_ASYNC_SUSPEND */
-
-	DHD_TRACE(("%s: PCIe Enumeration done!!\n", __FUNCTION__));
-	return 0;
-}
-
-int
-dhdpcie_detach(dhdpcie_info_t *pch)
-{
-	if (pch) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-		if (!dhd_download_fw_on_driverload) {
-			pci_load_and_free_saved_state(pch->dev, &pch->default_state);
-		}
-#endif /* OEM_ANDROID && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
-		MFREE(pch->osh, pch, sizeof(dhdpcie_info_t));
-	}
-	return 0;
-}
-
-
-void __devexit
-dhdpcie_pci_remove(struct pci_dev *pdev)
-{
-	osl_t *osh = NULL;
-	dhdpcie_info_t *pch = NULL;
-	dhd_bus_t *bus = NULL;
-
-	DHD_TRACE(("%s Enter\n", __FUNCTION__));
-	pch = pci_get_drvdata(pdev);
-	bus = pch->bus;
-	osh = pch->osh;
-
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-	if (bus) {
-#ifdef CONFIG_ARCH_MSM
-		msm_pcie_deregister_event(&bus->pcie_event);
-#endif /* CONFIG_ARCH_MSM */
-#ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY
-#ifdef CONFIG_SOC_EXYNOS8890
-		exynos_pcie_deregister_event(&bus->pcie_event);
-#endif /* CONFIG_SOC_EXYNOS8890 */
-#endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */
-	}
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-	dhdpcie_bus_release(bus);
-	pci_disable_device(pdev);
-#ifdef BCMPCIE_OOB_HOST_WAKE
-	/* pcie os info detach */
-	MFREE(osh, pch->os_cxt, sizeof(dhdpcie_os_info_t));
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-	/* pcie info detach */
-	dhdpcie_detach(pch);
-	/* osl detach */
-	osl_detach(osh);
-
-	dhdpcie_init_succeeded = FALSE;
-
-	DHD_TRACE(("%s Exit\n", __FUNCTION__));
-
-	return;
-}
-
-/* Free Linux irq */
-int
-dhdpcie_request_irq(dhdpcie_info_t *dhdpcie_info)
-{
-	dhd_bus_t *bus = dhdpcie_info->bus;
-	struct pci_dev *pdev = dhdpcie_info->bus->dev;
-
-	if (!bus->irq_registered) {
-		snprintf(dhdpcie_info->pciname, sizeof(dhdpcie_info->pciname),
-		    "dhdpcie:%s", pci_name(pdev));
-		if (request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED,
-			dhdpcie_info->pciname, bus) < 0) {
-			DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__));
-			return -1;
-		} else {
-			bus->irq_registered = TRUE;
-		}
-	} else {
-		DHD_ERROR(("%s: PCI IRQ is already registered\n", __FUNCTION__));
-	}
-
-	DHD_TRACE(("%s %s\n", __FUNCTION__, dhdpcie_info->pciname));
-
-
-	return 0; /* SUCCESS */
-}
-
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
-#define PRINTF_RESOURCE	"0x%016llx"
-#else
-#define PRINTF_RESOURCE	"0x%08x"
-#endif
-
-/*
-
-Name:  osl_pci_get_resource
-
-Parametrs:
-
-1: struct pci_dev *pdev   -- pci device structure
-2: pci_res                       -- structure containing pci configuration space values
-
-
-Return value:
-
-int   - Status (TRUE or FALSE)
-
-Description:
-Access PCI configuration space, retrieve  PCI allocated resources , updates in resource structure.
-
- */
-int dhdpcie_get_resource(dhdpcie_info_t *dhdpcie_info)
-{
-	phys_addr_t  bar0_addr, bar1_addr;
-	ulong bar1_size;
-	struct pci_dev *pdev = NULL;
-	pdev = dhdpcie_info->dev;
-	do {
-		if (pci_enable_device(pdev)) {
-			printf("%s: Cannot enable PCI device\n", __FUNCTION__);
-			break;
-		}
-		pci_set_master(pdev);
-		bar0_addr = pci_resource_start(pdev, 0);	/* Bar-0 mapped address */
-		bar1_addr = pci_resource_start(pdev, 2);	/* Bar-1 mapped address */
-
-		/* read Bar-1 mapped memory range */
-		bar1_size = pci_resource_len(pdev, 2);
-
-		if ((bar1_size == 0) || (bar1_addr == 0)) {
-			printf("%s: BAR1 Not enabled for this device  size(%ld),"
-				" addr(0x"PRINTF_RESOURCE")\n",
-				__FUNCTION__, bar1_size, bar1_addr);
-			goto err;
-		}
-
-		dhdpcie_info->regs = (volatile char *) REG_MAP(bar0_addr, DONGLE_REG_MAP_SIZE);
-		dhdpcie_info->tcm = (volatile char *) REG_MAP(bar1_addr, DONGLE_TCM_MAP_SIZE);
-		dhdpcie_info->tcm_size = DONGLE_TCM_MAP_SIZE;
-
-		if (!dhdpcie_info->regs || !dhdpcie_info->tcm) {
-			DHD_ERROR(("%s:ioremap() failed\n", __FUNCTION__));
-			break;
-		}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-		if (!dhd_download_fw_on_driverload) {
-			/* Backup PCIe configuration so as to use Wi-Fi on/off process
-			 * in case of built in driver
-			 */
-			pci_save_state(pdev);
-			dhdpcie_info->default_state = pci_store_saved_state(pdev);
-
-			if (dhdpcie_info->default_state == NULL) {
-				DHD_ERROR(("%s pci_store_saved_state returns NULL\n",
-					__FUNCTION__));
-				REG_UNMAP(dhdpcie_info->regs);
-				REG_UNMAP(dhdpcie_info->tcm);
-				pci_disable_device(pdev);
-				break;
-			}
-		}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
-
-		DHD_TRACE(("%s:Phys addr : reg space = %p base addr 0x"PRINTF_RESOURCE" \n",
-			__FUNCTION__, dhdpcie_info->regs, bar0_addr));
-		DHD_TRACE(("%s:Phys addr : tcm_space = %p base addr 0x"PRINTF_RESOURCE" \n",
-			__FUNCTION__, dhdpcie_info->tcm, bar1_addr));
-
-		return 0; /* SUCCESS  */
-	} while (0);
-err:
-	return -1;  /* FAILURE */
-}
-
-int dhdpcie_scan_resource(dhdpcie_info_t *dhdpcie_info)
-{
-
-	DHD_TRACE(("%s: ENTER\n", __FUNCTION__));
-
-	do {
-		/* define it here only!! */
-		if (dhdpcie_get_resource (dhdpcie_info)) {
-			DHD_ERROR(("%s: Failed to get PCI resources\n", __FUNCTION__));
-			break;
-		}
-		DHD_TRACE(("%s:Exit - SUCCESS \n",
-			__FUNCTION__));
-
-		return 0; /* SUCCESS */
-
-	} while (0);
-
-	DHD_TRACE(("%s:Exit - FAILURE \n", __FUNCTION__));
-
-	return -1; /* FAILURE */
-
-}
-
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#if defined(CONFIG_ARCH_MSM) || (defined(EXYNOS_PCIE_LINKDOWN_RECOVERY) && \
-	defined(CONFIG_SOC_EXYNOS8890))
-void dhdpcie_linkdown_cb(struct_pcie_notify *noti)
-{
-	struct pci_dev *pdev = (struct pci_dev *)noti->user;
-	dhdpcie_info_t *pch = NULL;
-
-	if (pdev) {
-		pch = pci_get_drvdata(pdev);
-		if (pch) {
-			dhd_bus_t *bus = pch->bus;
-			if (bus) {
-				dhd_pub_t *dhd = bus->dhd;
-				if (dhd) {
-					DHD_ERROR(("%s: Event HANG send up "
-						"due to PCIe linkdown\n",
-						__FUNCTION__));
-#ifdef CONFIG_ARCH_MSM
-					bus->no_cfg_restore = 1;
-#endif /* CONFIG_ARCH_MSM */
-					bus->is_linkdown = 1;
-					DHD_OS_WAKE_LOCK(dhd);
-					dhd->hang_reason = HANG_REASON_PCIE_LINK_DOWN;
-					dhd_os_send_hang_message(dhd);
-				}
-			}
-		}
-	}
-
-}
-#endif /* CONFIG_ARCH_MSM || (EXYNOS_PCIE_LINKDOWN_RECOVERY && CONFIG_SOC_EXYNOS8890) */
-#endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */
-
-int dhdpcie_init(struct pci_dev *pdev)
-{
-
-	osl_t 				*osh = NULL;
-	dhd_bus_t 			*bus = NULL;
-	dhdpcie_info_t		*dhdpcie_info =  NULL;
-	wifi_adapter_info_t	*adapter = NULL;
-#ifdef BCMPCIE_OOB_HOST_WAKE
-	dhdpcie_os_info_t	*dhdpcie_osinfo = NULL;
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-
-	do {
-		/* osl attach */
-		if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) {
-			DHD_ERROR(("%s: osl_attach failed\n", __FUNCTION__));
-			break;
-		}
-
-		/* initialize static buffer */
-		adapter = dhd_wifi_platform_get_adapter(PCI_BUS, pdev->bus->number,
-			PCI_SLOT(pdev->devfn));
-		if (adapter != NULL)
-			DHD_ERROR(("%s: found adapter info '%s'\n", __FUNCTION__, adapter->name));
-		else
-			DHD_ERROR(("%s: can't find adapter info for this chip\n", __FUNCTION__));
-		osl_static_mem_init(osh, adapter);
-
-		/* Set ACP coherence flag */
-		if (OSL_ACP_WAR_ENAB() || OSL_ARCH_IS_COHERENT())
-			osl_flag_set(osh, OSL_ACP_COHERENCE);
-
-		/*  allocate linux spcific pcie structure here */
-		if (!(dhdpcie_info = MALLOC(osh, sizeof(dhdpcie_info_t)))) {
-			DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
-			break;
-		}
-		bzero(dhdpcie_info, sizeof(dhdpcie_info_t));
-		dhdpcie_info->osh = osh;
-		dhdpcie_info->dev = pdev;
-
-#ifdef BCMPCIE_OOB_HOST_WAKE
-		/* allocate OS speicific structure */
-		dhdpcie_osinfo = MALLOC(osh, sizeof(dhdpcie_os_info_t));
-		if (dhdpcie_osinfo == NULL) {
-			DHD_ERROR(("%s: MALLOC of dhdpcie_os_info_t failed\n",
-				__FUNCTION__));
-			break;
-		}
-		bzero(dhdpcie_osinfo, sizeof(dhdpcie_os_info_t));
-		dhdpcie_info->os_cxt = (void *)dhdpcie_osinfo;
-
-		/* Initialize host wake IRQ */
-		spin_lock_init(&dhdpcie_osinfo->oob_irq_spinlock);
-		/* Get customer specific host wake IRQ parametres: IRQ number as IRQ type */
-		dhdpcie_osinfo->oob_irq_num = wifi_platform_get_irq_number(adapter,
-			&dhdpcie_osinfo->oob_irq_flags);
-		if (dhdpcie_osinfo->oob_irq_num < 0) {
-			DHD_ERROR(("%s: Host OOB irq is not defined\n", __FUNCTION__));
-		}
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-
-		/* Find the PCI resources, verify the  */
-		/* vendor and device ID, map BAR regions and irq,  update in structures */
-		if (dhdpcie_scan_resource(dhdpcie_info)) {
-			DHD_ERROR(("%s: dhd_Scan_PCI_Res failed\n", __FUNCTION__));
-
-			break;
-		}
-
-		/* Bus initialization */
-		bus = dhdpcie_bus_attach(osh, dhdpcie_info->regs, dhdpcie_info->tcm, pdev);
-		if (!bus) {
-			DHD_ERROR(("%s:dhdpcie_bus_attach() failed\n", __FUNCTION__));
-			break;
-		}
-
-		dhdpcie_info->bus = bus;
-		bus->is_linkdown = 0;
-		bus->pci_d3hot_done = 0;
-#ifdef DONGLE_ENABLE_ISOLATION
-		bus->dhd->dongle_isolation = TRUE;
-#endif /* DONGLE_ENABLE_ISOLATION */
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-#ifdef CONFIG_ARCH_MSM
-		bus->pcie_event.events = MSM_PCIE_EVENT_LINKDOWN;
-		bus->pcie_event.user = pdev;
-		bus->pcie_event.mode = MSM_PCIE_TRIGGER_CALLBACK;
-		bus->pcie_event.callback = dhdpcie_linkdown_cb;
-		bus->pcie_event.options = MSM_PCIE_CONFIG_NO_RECOVERY;
-		msm_pcie_register_event(&bus->pcie_event);
-		bus->no_cfg_restore = 0;
-#endif /* CONFIG_ARCH_MSM */
-#ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY
-#ifdef CONFIG_SOC_EXYNOS8890
-		bus->pcie_event.events = EXYNOS_PCIE_EVENT_LINKDOWN;
-		bus->pcie_event.user = pdev;
-		bus->pcie_event.mode = EXYNOS_PCIE_TRIGGER_CALLBACK;
-		bus->pcie_event.callback = dhdpcie_linkdown_cb;
-		exynos_pcie_register_event(&bus->pcie_event);
-#endif /* CONFIG_SOC_EXYNOS8890 */
-#endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-
-		if (bus->intr) {
-			/* Register interrupt callback, but mask it (not operational yet). */
-			DHD_INTR(("%s: Registering and masking interrupts\n", __FUNCTION__));
-			dhdpcie_bus_intr_disable(bus);
-
-			if (dhdpcie_request_irq(dhdpcie_info)) {
-				DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__));
-				break;
-			}
-		} else {
-			bus->pollrate = 1;
-			DHD_INFO(("%s: PCIe interrupt function is NOT registered "
-				"due to polling mode\n", __FUNCTION__));
-		}
-
-#if defined(BCM_REQUEST_FW)
-		if (dhd_bus_download_firmware(bus, osh, NULL, NULL) < 0) {
-		DHD_ERROR(("%s: failed to download firmware\n", __FUNCTION__));
-		}
-		bus->nv_path = NULL;
-		bus->fw_path = NULL;
-#endif /* BCM_REQUEST_FW */
-
-		/* set private data for pci_dev */
-		pci_set_drvdata(pdev, dhdpcie_info);
-
-		if (dhd_download_fw_on_driverload) {
-			if (dhd_bus_start(bus->dhd)) {
-				DHD_ERROR(("%s: dhd_bud_start() failed\n", __FUNCTION__));
-				if (!allow_delay_fwdl)
-					break;
-			}
-		} else {
-			/* Set ramdom MAC address during boot time */
-			get_random_bytes(&bus->dhd->mac.octet[3], 3);
-			/* Adding BRCM OUI */
-			bus->dhd->mac.octet[0] = 0;
-			bus->dhd->mac.octet[1] = 0x90;
-			bus->dhd->mac.octet[2] = 0x4C;
-		}
-
-		/* Attach to the OS network interface */
-		DHD_TRACE(("%s(): Calling dhd_register_if() \n", __FUNCTION__));
-		if (dhd_register_if(bus->dhd, 0, TRUE)) {
-			DHD_ERROR(("%s(): ERROR.. dhd_register_if() failed\n", __FUNCTION__));
-			break;
-		}
-
-		dhdpcie_init_succeeded = TRUE;
-
-		DHD_TRACE(("%s:Exit - SUCCESS \n", __FUNCTION__));
-		return 0;  /* return  SUCCESS  */
-
-	} while (0);
-	/* reverse the initialization in order in case of error */
-
-	if (bus)
-		dhdpcie_bus_release(bus);
-
-#ifdef BCMPCIE_OOB_HOST_WAKE
-	if (dhdpcie_osinfo) {
-		MFREE(osh, dhdpcie_osinfo, sizeof(dhdpcie_os_info_t));
-	}
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-
-	if (dhdpcie_info)
-		dhdpcie_detach(dhdpcie_info);
-	pci_disable_device(pdev);
-	if (osh)
-		osl_detach(osh);
-
-	dhdpcie_init_succeeded = FALSE;
-
-	DHD_TRACE(("%s:Exit - FAILURE \n", __FUNCTION__));
-
-	return -1; /* return FAILURE  */
-}
-
-/* Free Linux irq */
-void
-dhdpcie_free_irq(dhd_bus_t *bus)
-{
-	struct pci_dev *pdev = NULL;
-
-	DHD_TRACE(("%s: freeing up the IRQ\n", __FUNCTION__));
-	if (!bus) {
-		return;
-	}
-
-	if (bus->irq_registered) {
-		pdev = bus->dev;
-		free_irq(pdev->irq, bus);
-		bus->irq_registered = FALSE;
-	} else {
-		DHD_ERROR(("%s: PCIe IRQ is not registered\n", __FUNCTION__));
-	}
-	DHD_TRACE(("%s: Exit\n", __FUNCTION__));
-	return;
-}
-
-/*
-
-Name:  dhdpcie_isr
-
-Parametrs:
-
-1: IN int irq   -- interrupt vector
-2: IN void *arg      -- handle to private data structure
-
-Return value:
-
-Status (TRUE or FALSE)
-
-Description:
-Interrupt Service routine checks for the status register,
-disable interrupt and queue DPC if mail box interrupts are raised.
-*/
-
-
-irqreturn_t
-dhdpcie_isr(int irq, void *arg)
-{
-	dhd_bus_t *bus = (dhd_bus_t*)arg;
-	if (dhdpcie_bus_isr(bus))
-		return TRUE;
-	else
-		return FALSE;
-}
-
-int
-dhdpcie_start_host_pcieclock(dhd_bus_t *bus)
-{
-	int ret = 0;
-#ifdef CONFIG_ARCH_MSM
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-	int options = 0;
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-#endif /* CONFIG_ARCH_MSM */
-	DHD_TRACE(("%s Enter:\n", __FUNCTION__));
-
-	if (bus == NULL) {
-		return BCME_ERROR;
-	}
-
-	if (bus->dev == NULL) {
-		return BCME_ERROR;
-	}
-
-#ifdef CONFIG_ARCH_MSM
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-	if (bus->no_cfg_restore) {
-		options = MSM_PCIE_CONFIG_NO_CFG_RESTORE;
-	}
-	ret = msm_pcie_pm_control(MSM_PCIE_RESUME, bus->dev->bus->number,
-		bus->dev, NULL, options);
-	if (bus->no_cfg_restore && !ret) {
-		msm_pcie_recover_config(bus->dev);
-		bus->no_cfg_restore = 0;
-	}
-#else
-	ret = msm_pcie_pm_control(MSM_PCIE_RESUME, bus->dev->bus->number,
-		bus->dev, NULL, 0);
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-	if (ret) {
-		DHD_ERROR(("%s Failed to bring up PCIe link\n", __FUNCTION__));
-		goto done;
-	}
-
-done:
-#endif /* CONFIG_ARCH_MSM */
-	DHD_TRACE(("%s Exit:\n", __FUNCTION__));
-	return ret;
-}
-
-int
-dhdpcie_stop_host_pcieclock(dhd_bus_t *bus)
-{
-	int ret = 0;
-#ifdef CONFIG_ARCH_MSM
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-	int options = 0;
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-#endif /* CONFIG_ARCH_MSM */
-
-	DHD_TRACE(("%s Enter:\n", __FUNCTION__));
-
-	if (bus == NULL) {
-		return BCME_ERROR;
-	}
-
-	if (bus->dev == NULL) {
-		return BCME_ERROR;
-	}
-
-#ifdef CONFIG_ARCH_MSM
-#ifdef SUPPORT_LINKDOWN_RECOVERY
-	if (bus->no_cfg_restore) {
-		options = MSM_PCIE_CONFIG_NO_CFG_RESTORE | MSM_PCIE_CONFIG_LINKDOWN;
-	}
-
-	ret = msm_pcie_pm_control(MSM_PCIE_SUSPEND, bus->dev->bus->number,
-		bus->dev, NULL, options);
-#else
-	ret = msm_pcie_pm_control(MSM_PCIE_SUSPEND, bus->dev->bus->number,
-		bus->dev, NULL, 0);
-#endif /* SUPPORT_LINKDOWN_RECOVERY */
-	if (ret) {
-		DHD_ERROR(("Failed to stop PCIe link\n"));
-		goto done;
-	}
-done:
-#endif /* CONFIG_ARCH_MSM */
-	DHD_TRACE(("%s Exit:\n", __FUNCTION__));
-	return ret;
-}
-
-int
-dhdpcie_disable_device(dhd_bus_t *bus)
-{
-	DHD_TRACE(("%s Enter:\n", __FUNCTION__));
-
-	if (bus == NULL) {
-		return BCME_ERROR;
-	}
-
-	if (bus->dev == NULL) {
-		return BCME_ERROR;
-	}
-
-	pci_disable_device(bus->dev);
-
-	return 0;
-}
-
-int
-dhdpcie_enable_device(dhd_bus_t *bus)
-{
-	int ret = BCME_ERROR;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-	dhdpcie_info_t *pch;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
-
-	DHD_TRACE(("%s Enter:\n", __FUNCTION__));
-
-	if (bus == NULL) {
-		return BCME_ERROR;
-	}
-
-	if (bus->dev == NULL) {
-		return BCME_ERROR;
-	}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-	pch = pci_get_drvdata(bus->dev);
-	if (pch == NULL) {
-		return BCME_ERROR;
-	}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) && !defined(CONFIG_SOC_EXYNOS8890)
-	/* Updated with pci_load_and_free_saved_state to compatible
-	 * with kernel 3.14 or higher
-	 */
-	pci_load_and_free_saved_state(bus->dev, &pch->default_state);
-	pch->default_state = pci_store_saved_state(bus->dev);
-#else
-	pci_load_saved_state(bus->dev, pch->default_state);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) && !CONFIG_SOC_EXYNOS8890 */
-
-	pci_restore_state(bus->dev);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) */
-
-	ret = pci_enable_device(bus->dev);
-	if (ret) {
-		pci_disable_device(bus->dev);
-	} else {
-		pci_set_master(bus->dev);
-	}
-
-	return ret;
-}
-
-int
-dhdpcie_alloc_resource(dhd_bus_t *bus)
-{
-	dhdpcie_info_t *dhdpcie_info;
-	phys_addr_t bar0_addr, bar1_addr;
-	ulong bar1_size;
-
-	do {
-		if (bus == NULL) {
-			DHD_ERROR(("%s: bus is NULL\n", __FUNCTION__));
-			break;
-		}
-
-		if (bus->dev == NULL) {
-			DHD_ERROR(("%s: bus->dev is NULL\n", __FUNCTION__));
-			break;
-		}
-
-		dhdpcie_info = pci_get_drvdata(bus->dev);
-		if (dhdpcie_info == NULL) {
-			DHD_ERROR(("%s: dhdpcie_info is NULL\n", __FUNCTION__));
-			break;
-		}
-
-		bar0_addr = pci_resource_start(bus->dev, 0);	/* Bar-0 mapped address */
-		bar1_addr = pci_resource_start(bus->dev, 2);	/* Bar-1 mapped address */
-
-		/* read Bar-1 mapped memory range */
-		bar1_size = pci_resource_len(bus->dev, 2);
-
-		if ((bar1_size == 0) || (bar1_addr == 0)) {
-			printf("%s: BAR1 Not enabled for this device size(%ld),"
-				" addr(0x"PRINTF_RESOURCE")\n",
-				__FUNCTION__, bar1_size, bar1_addr);
-			break;
-		}
-
-		dhdpcie_info->regs = (volatile char *) REG_MAP(bar0_addr, DONGLE_REG_MAP_SIZE);
-		if (!dhdpcie_info->regs) {
-			DHD_ERROR(("%s: ioremap() for regs is failed\n", __FUNCTION__));
-			break;
-		}
-
-		bus->regs = dhdpcie_info->regs;
-		dhdpcie_info->tcm = (volatile char *) REG_MAP(bar1_addr, DONGLE_TCM_MAP_SIZE);
-		dhdpcie_info->tcm_size = DONGLE_TCM_MAP_SIZE;
-		if (!dhdpcie_info->tcm) {
-			DHD_ERROR(("%s: ioremap() for regs is failed\n", __FUNCTION__));
-			REG_UNMAP(dhdpcie_info->regs);
-			bus->regs = NULL;
-			break;
-		}
-
-		bus->tcm = dhdpcie_info->tcm;
-
-		DHD_TRACE(("%s:Phys addr : reg space = %p base addr 0x"PRINTF_RESOURCE" \n",
-			__FUNCTION__, dhdpcie_info->regs, bar0_addr));
-		DHD_TRACE(("%s:Phys addr : tcm_space = %p base addr 0x"PRINTF_RESOURCE" \n",
-			__FUNCTION__, dhdpcie_info->tcm, bar1_addr));
-
-		return 0;
-	} while (0);
-
-	return BCME_ERROR;
-}
-
-void
-dhdpcie_free_resource(dhd_bus_t *bus)
-{
-	dhdpcie_info_t *dhdpcie_info;
-
-	if (bus == NULL) {
-		DHD_ERROR(("%s: bus is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	if (bus->dev == NULL) {
-		DHD_ERROR(("%s: bus->dev is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	dhdpcie_info = pci_get_drvdata(bus->dev);
-	if (dhdpcie_info == NULL) {
-		DHD_ERROR(("%s: dhdpcie_info is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	if (bus->regs) {
-		REG_UNMAP(dhdpcie_info->regs);
-		bus->regs = NULL;
-	}
-
-	if (bus->tcm) {
-		REG_UNMAP(dhdpcie_info->tcm);
-		bus->tcm = NULL;
-	}
-}
-
-int
-dhdpcie_bus_request_irq(struct dhd_bus *bus)
-{
-	dhdpcie_info_t *dhdpcie_info;
-	int ret = 0;
-
-	if (bus == NULL) {
-		DHD_ERROR(("%s: bus is NULL\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	if (bus->dev == NULL) {
-		DHD_ERROR(("%s: bus->dev is NULL\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	dhdpcie_info = pci_get_drvdata(bus->dev);
-	if (dhdpcie_info == NULL) {
-		DHD_ERROR(("%s: dhdpcie_info is NULL\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	if (bus->intr) {
-		/* Register interrupt callback, but mask it (not operational yet). */
-		DHD_INTR(("%s: Registering and masking interrupts\n", __FUNCTION__));
-		dhdpcie_bus_intr_disable(bus);
-		ret = dhdpcie_request_irq(dhdpcie_info);
-		if (ret) {
-			DHD_ERROR(("%s: request_irq() failed, ret=%d\n",
-				__FUNCTION__, ret));
-			return ret;
-		}
-	}
-
-	return ret;
-}
-
-#ifdef BCMPCIE_OOB_HOST_WAKE
-void dhdpcie_oob_intr_set(dhd_bus_t *bus, bool enable)
-{
-	unsigned long flags;
-	dhdpcie_info_t *pch;
-	dhdpcie_os_info_t *dhdpcie_osinfo;
-
-	if (bus == NULL) {
-		DHD_ERROR(("%s: bus is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	if (bus->dev == NULL) {
-		DHD_ERROR(("%s: bus->dev is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	pch = pci_get_drvdata(bus->dev);
-	if (pch == NULL) {
-		DHD_ERROR(("%s: pch is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	dhdpcie_osinfo = (dhdpcie_os_info_t *)pch->os_cxt;
-	spin_lock_irqsave(&dhdpcie_osinfo->oob_irq_spinlock, flags);
-	if ((dhdpcie_osinfo->oob_irq_enabled != enable) &&
-		(dhdpcie_osinfo->oob_irq_num > 0)) {
-		if (enable) {
-			enable_irq(dhdpcie_osinfo->oob_irq_num);
-		} else {
-			disable_irq_nosync(dhdpcie_osinfo->oob_irq_num);
-		}
-		dhdpcie_osinfo->oob_irq_enabled = enable;
-	}
-	spin_unlock_irqrestore(&dhdpcie_osinfo->oob_irq_spinlock, flags);
-}
-
-static irqreturn_t wlan_oob_irq(int irq, void *data)
-{
-	dhd_bus_t *bus;
-	DHD_TRACE(("%s: IRQ Triggered\n", __FUNCTION__));
-	bus = (dhd_bus_t *)data;
-	dhdpcie_oob_intr_set(bus, FALSE);
-#ifdef DHD_PCIE_RUNTIMEPM
-	dhdpcie_runtime_bus_wake(bus->dhd, FALSE, wlan_oob_irq);
-#endif /* DHD_PCIE_RUNTIMPM */
-	if (bus->dhd->up && bus->suspended) {
-		DHD_OS_OOB_IRQ_WAKE_LOCK_TIMEOUT(bus->dhd, OOB_WAKE_LOCK_TIMEOUT);
-	}
-	return IRQ_HANDLED;
-}
-
-int dhdpcie_oob_intr_register(dhd_bus_t *bus)
-{
-	int err = 0;
-	dhdpcie_info_t *pch;
-	dhdpcie_os_info_t *dhdpcie_osinfo;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-	if (bus == NULL) {
-		DHD_ERROR(("%s: bus is NULL\n", __FUNCTION__));
-		return -EINVAL;
-	}
-
-	if (bus->dev == NULL) {
-		DHD_ERROR(("%s: bus->dev is NULL\n", __FUNCTION__));
-		return -EINVAL;
-	}
-
-	pch = pci_get_drvdata(bus->dev);
-	if (pch == NULL) {
-		DHD_ERROR(("%s: pch is NULL\n", __FUNCTION__));
-		return -EINVAL;
-	}
-
-	dhdpcie_osinfo = (dhdpcie_os_info_t *)pch->os_cxt;
-	if (dhdpcie_osinfo->oob_irq_registered) {
-		DHD_ERROR(("%s: irq is already registered\n", __FUNCTION__));
-		return -EBUSY;
-	}
-
-	if (dhdpcie_osinfo->oob_irq_num > 0) {
-		DHD_INFO_HW4(("%s OOB irq=%d flags=%X \n", __FUNCTION__,
-			(int)dhdpcie_osinfo->oob_irq_num,
-			(int)dhdpcie_osinfo->oob_irq_flags));
-		err = request_irq(dhdpcie_osinfo->oob_irq_num, wlan_oob_irq,
-			dhdpcie_osinfo->oob_irq_flags, "dhdpcie_host_wake",
-			bus);
-		if (err) {
-			DHD_ERROR(("%s: request_irq failed with %d\n",
-				__FUNCTION__, err));
-			return err;
-		}
-		err = enable_irq_wake(dhdpcie_osinfo->oob_irq_num);
-		if (!err) {
-			dhdpcie_osinfo->oob_irq_wake_enabled = TRUE;
-		}
-		dhdpcie_osinfo->oob_irq_enabled = TRUE;
-	}
-
-	dhdpcie_osinfo->oob_irq_registered = TRUE;
-
-	return err;
-}
-
-void dhdpcie_oob_intr_unregister(dhd_bus_t *bus)
-{
-	int err = 0;
-	dhdpcie_info_t *pch;
-	dhdpcie_os_info_t *dhdpcie_osinfo;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-	if (bus == NULL) {
-		DHD_ERROR(("%s: bus is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	if (bus->dev == NULL) {
-		DHD_ERROR(("%s: bus->dev is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	pch = pci_get_drvdata(bus->dev);
-	if (pch == NULL) {
-		DHD_ERROR(("%s: pch is NULL\n", __FUNCTION__));
-		return;
-	}
-
-	dhdpcie_osinfo = (dhdpcie_os_info_t *)pch->os_cxt;
-	if (!dhdpcie_osinfo->oob_irq_registered) {
-		DHD_ERROR(("%s: irq is not registered\n", __FUNCTION__));
-		return;
-	}
-	if (dhdpcie_osinfo->oob_irq_num > 0) {
-		if (dhdpcie_osinfo->oob_irq_wake_enabled) {
-			err = disable_irq_wake(dhdpcie_osinfo->oob_irq_num);
-			if (!err) {
-				dhdpcie_osinfo->oob_irq_wake_enabled = FALSE;
-			}
-		}
-		if (dhdpcie_osinfo->oob_irq_enabled) {
-			disable_irq(dhdpcie_osinfo->oob_irq_num);
-			dhdpcie_osinfo->oob_irq_enabled = FALSE;
-		}
-		free_irq(dhdpcie_osinfo->oob_irq_num, bus);
-	}
-	dhdpcie_osinfo->oob_irq_registered = FALSE;
-}
-#endif /* BCMPCIE_OOB_HOST_WAKE */
-
-#ifdef DHD_PCIE_RUNTIMEPM
-bool dhd_runtimepm_state(dhd_pub_t *dhd)
-{
-	dhd_bus_t *bus;
-	unsigned long flags;
-	bus = dhd->bus;
-
-	DHD_GENERAL_LOCK(dhd, flags);
-	if (bus->suspended == TRUE) {
-		DHD_GENERAL_UNLOCK(dhd, flags);
-		DHD_INFO(("Bus is already suspended system PM: %d\n", bus->suspended));
-		return FALSE;
-	}
-
-	bus->idlecount++;
-
-	DHD_TRACE(("%s : Enter \n", __FUNCTION__));
-	if ((bus->idletime > 0) && (bus->idlecount >= bus->idletime)) {
-		bus->idlecount = 0;
-		if (dhd->dhd_bus_busy_state == 0 && dhd->busstate != DHD_BUS_DOWN &&
-				dhd->busstate != DHD_BUS_DOWN_IN_PROGRESS) {
-			bus->bus_wake = 0;
-			dhd->dhd_bus_busy_state |= DHD_BUS_BUSY_RPM_SUSPEND_IN_PROGRESS;
-			bus->runtime_resume_done = FALSE;
-			/* stop all interface network queue. */
-			dhd_bus_stop_queue(bus);
-			DHD_GENERAL_UNLOCK(dhd, flags);
-			DHD_ERROR(("%s: DHD Idle state!! -  idletime :%d, wdtick :%d \n",
-					__FUNCTION__, bus->idletime, dhd_runtimepm_ms));
-			/* RPM suspend is failed, return FALSE then re-trying */
-			if (dhdpcie_set_suspend_resume(bus->dev, TRUE)) {
-				DHD_ERROR(("%s: exit with wakelock \n", __FUNCTION__));
-				DHD_GENERAL_LOCK(dhd, flags);
-				dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_RPM_SUSPEND_IN_PROGRESS;
-				bus->runtime_resume_done = TRUE;
-				/* It can make stuck NET TX Queue without below */
-				dhd_bus_start_queue(bus);
-				DHD_GENERAL_UNLOCK(dhd, flags);
-				smp_wmb();
-				wake_up_interruptible(&bus->rpm_queue);
-				return FALSE;
-			}
-
-			DHD_GENERAL_LOCK(dhd, flags);
-			dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_RPM_SUSPEND_IN_PROGRESS;
-			dhd->dhd_bus_busy_state |= DHD_BUS_BUSY_RPM_SUSPEND_DONE;
-			/* For making sure NET TX Queue active  */
-			dhd_bus_start_queue(bus);
-			DHD_GENERAL_UNLOCK(dhd, flags);
-
-			wait_event_interruptible(bus->rpm_queue, bus->bus_wake);
-
-			DHD_GENERAL_LOCK(dhd, flags);
-			dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_RPM_SUSPEND_DONE;
-			dhd->dhd_bus_busy_state |= DHD_BUS_BUSY_RPM_RESUME_IN_PROGRESS;
-			DHD_GENERAL_UNLOCK(dhd, flags);
-
-			dhdpcie_set_suspend_resume(bus->dev, FALSE);
-
-			DHD_GENERAL_LOCK(dhd, flags);
-			dhd->dhd_bus_busy_state &= ~DHD_BUS_BUSY_RPM_RESUME_IN_PROGRESS;
-			/* Inform the wake up context that Resume is over */
-			bus->runtime_resume_done = TRUE;
-			/* For making sure NET TX Queue active  */
-			dhd_bus_start_queue(bus);
-			DHD_GENERAL_UNLOCK(dhd, flags);
-
-			smp_wmb();
-			wake_up_interruptible(&bus->rpm_queue);
-			DHD_ERROR(("%s : runtime resume ended\n", __FUNCTION__));
-			return TRUE;
-		} else {
-			DHD_GENERAL_UNLOCK(dhd, flags);
-			/* Since one of the contexts are busy (TX, IOVAR or RX)
-			 * we should not suspend
-			 */
-			DHD_ERROR(("%s : bus is active with dhd_bus_busy_state = 0x%x\n",
-				__FUNCTION__, dhd->dhd_bus_busy_state));
-			return FALSE;
-		}
-	}
-
-	DHD_GENERAL_UNLOCK(dhd, flags);
-	return FALSE;
-} /* dhd_runtimepm_state */
-
-/*
- * dhd_runtime_bus_wake
- *  TRUE - related with runtime pm context
- *  FALSE - It isn't invloved in runtime pm context
- */
-bool dhd_runtime_bus_wake(dhd_bus_t *bus, bool wait, void *func_addr)
-{
-	unsigned long flags;
-	bus->idlecount = 0;
-	DHD_TRACE(("%s : enter\n", __FUNCTION__));
-	if (bus->dhd->up == FALSE) {
-		DHD_INFO(("%s : dhd is not up\n", __FUNCTION__));
-		return FALSE;
-	}
-
-	DHD_GENERAL_LOCK(bus->dhd, flags);
-	if (bus->dhd->dhd_bus_busy_state & DHD_BUS_BUSY_RPM_ALL) {
-		/* Wake up RPM state thread if it is suspend in progress or suspended */
-		if (bus->dhd->dhd_bus_busy_state & DHD_BUS_BUSY_RPM_SUSPEND_IN_PROGRESS ||
-				bus->dhd->dhd_bus_busy_state & DHD_BUS_BUSY_RPM_SUSPEND_DONE) {
-			bus->bus_wake = 1;
-
-			DHD_GENERAL_UNLOCK(bus->dhd, flags);
-
-			DHD_ERROR(("Runtime Resume is called in %pf\n", func_addr));
-			smp_wmb();
-			wake_up_interruptible(&bus->rpm_queue);
-		/* No need to wake up the RPM state thread */
-		} else if (bus->dhd->dhd_bus_busy_state & DHD_BUS_BUSY_RPM_RESUME_IN_PROGRESS) {
-			DHD_GENERAL_UNLOCK(bus->dhd, flags);
-		}
-
-		/* If wait is TRUE, function with wait = TRUE will be wait in here  */
-		if (wait) {
-			wait_event_interruptible(bus->rpm_queue, bus->runtime_resume_done);
-		} else {
-			DHD_INFO(("%s: bus wakeup but no wait until resume done\n", __FUNCTION__));
-		}
-		/* If it is called from RPM context, it returns TRUE */
-		return TRUE;
-	}
-
-	DHD_GENERAL_UNLOCK(bus->dhd, flags);
-
-	return FALSE;
-}
-
-bool dhdpcie_runtime_bus_wake(dhd_pub_t *dhdp, bool wait, void* func_addr)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	return dhd_runtime_bus_wake(bus, wait, func_addr);
-}
-
-void dhdpcie_block_runtime_pm(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	bus->idletime = 0;
-}
-
-bool dhdpcie_is_resume_done(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	return bus->runtime_resume_done;
-}
-#endif /* DHD_PCIE_RUNTIMEPM */
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c
deleted file mode 100644
index 90e6877..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_pno.c
+++ /dev/null
@@ -1,3889 +0,0 @@
-/*
- * Broadcom Dongle Host Driver (DHD)
- * Prefered Network Offload and Wi-Fi Location Service(WLS) code.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_pno.c 606280 2015-12-15 05:28:25Z $
- */
-
-#if defined(GSCAN_SUPPORT) && !defined(PNO_SUPPORT)
-#error "GSCAN needs PNO to be enabled!"
-#endif
-
-#ifdef PNO_SUPPORT
-#include <typedefs.h>
-#include <osl.h>
-
-#include <epivers.h>
-#include <bcmutils.h>
-
-#include <bcmendian.h>
-#include <linuxver.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/sort.h>
-#include <dngl_stats.h>
-#include <wlioctl.h>
-
-#include <proto/bcmevent.h>
-#include <dhd.h>
-#include <dhd_pno.h>
-#include <dhd_dbg.h>
-#ifdef GSCAN_SUPPORT
-#include <linux/gcd.h>
-#endif /* GSCAN_SUPPORT */
-
-#ifdef __BIG_ENDIAN
-#include <bcmendian.h>
-#define htod32(i) (bcmswap32(i))
-#define htod16(i) (bcmswap16(i))
-#define dtoh32(i) (bcmswap32(i))
-#define dtoh16(i) (bcmswap16(i))
-#define htodchanspec(i) htod16(i)
-#define dtohchanspec(i) dtoh16(i)
-#else
-#define htod32(i) (i)
-#define htod16(i) (i)
-#define dtoh32(i) (i)
-#define dtoh16(i) (i)
-#define htodchanspec(i) (i)
-#define dtohchanspec(i) (i)
-#endif /* IL_BIGENDINA */
-
-#define NULL_CHECK(p, s, err)  \
-			do { \
-				if (!(p)) { \
-					printf("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \
-					err = BCME_ERROR; \
-					return err; \
-				} \
-			} while (0)
-#define PNO_GET_PNOSTATE(dhd) ((dhd_pno_status_info_t *)dhd->pno_state)
-#define PNO_BESTNET_LEN 1024
-#define PNO_ON 1
-#define PNO_OFF 0
-#define CHANNEL_2G_MAX 14
-#define CHANNEL_5G_MAX 165
-#define MAX_NODE_CNT 5
-#define WLS_SUPPORTED(pno_state) (pno_state->wls_supported == TRUE)
-#define TIME_DIFF(timestamp1, timestamp2) (abs((uint32)(timestamp1/1000)  \
-						- (uint32)(timestamp2/1000)))
-#define TIME_DIFF_MS(timestamp1, timestamp2) (abs((uint32)(timestamp1)  \
-						- (uint32)(timestamp2)))
-#define TIMESPEC_TO_US(ts)  (((uint64)(ts).tv_sec * USEC_PER_SEC) + \
-							(ts).tv_nsec / NSEC_PER_USEC)
-
-#define ENTRY_OVERHEAD strlen("bssid=\nssid=\nfreq=\nlevel=\nage=\ndist=\ndistSd=\n====")
-#define TIME_MIN_DIFF 5
-static wlc_ssid_ext_t * dhd_pno_get_legacy_pno_ssid(dhd_pub_t *dhd,
-        dhd_pno_status_info_t *pno_state);
-#ifdef GSCAN_SUPPORT
-static wl_pfn_gscan_channel_bucket_t *
-dhd_pno_gscan_create_channel_list(dhd_pub_t *dhd, dhd_pno_status_info_t *pno_state,
-uint16 *chan_list, uint32 *num_buckets, uint32 *num_buckets_to_fw);
-#endif /* GSCAN_SUPPORT */
-
-static inline bool
-is_dfs(uint16 channel)
-{
-	if (channel >= 52 && channel <= 64)			/* class 2 */
-		return TRUE;
-	else if (channel >= 100 && channel <= 140)	/* class 4 */
-		return TRUE;
-	else
-		return FALSE;
-}
-int
-dhd_pno_clean(dhd_pub_t *dhd)
-{
-	int pfn = 0;
-	int err;
-	dhd_pno_status_info_t *_pno_state;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	/* Disable PNO */
-	err = dhd_iovar(dhd, 0, "pfn", (char *)&pfn, sizeof(pfn), 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to execute pfn(error : %d)\n",
-			__FUNCTION__, err));
-		goto exit;
-	}
-	_pno_state->pno_status = DHD_PNO_DISABLED;
-	err = dhd_iovar(dhd, 0, "pfnclear", NULL, 0, 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to execute pfnclear(error : %d)\n",
-			__FUNCTION__, err));
-	}
-exit:
-	return err;
-}
-
-bool
-dhd_is_pno_supported(dhd_pub_t *dhd)
-{
-	dhd_pno_status_info_t *_pno_state;
-
-	if (!dhd || !dhd->pno_state) {
-		DHD_ERROR(("NULL POINTER : %s\n",
-			__FUNCTION__));
-		return FALSE;
-	}
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	return WLS_SUPPORTED(_pno_state);
-}
-
-int
-dhd_pno_set_mac_oui(dhd_pub_t *dhd, uint8 *oui)
-{
-	int err = BCME_OK;
-	dhd_pno_status_info_t *_pno_state;
-
-	if (!dhd || !dhd->pno_state) {
-		DHD_ERROR(("NULL POINTER : %s\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	if (ETHER_ISMULTI(oui)) {
-		DHD_ERROR(("Expected unicast OUI\n"));
-		err = BCME_ERROR;
-	} else {
-		memcpy(_pno_state->pno_oui, oui, DOT11_OUI_LEN);
-		DHD_PNO(("PNO mac oui to be used - %02x:%02x:%02x\n", _pno_state->pno_oui[0],
-		    _pno_state->pno_oui[1], _pno_state->pno_oui[2]));
-	}
-
-	return err;
-}
-
-#ifdef GSCAN_SUPPORT
-static uint64
-convert_fw_rel_time_to_systime(uint32 fw_ts_ms)
-{
-	struct timespec ts;
-
-	get_monotonic_boottime(&ts);
-	return ((uint64)(TIMESPEC_TO_US(ts)) - (uint64)(fw_ts_ms * 1000));
-}
-
-static int
-_dhd_pno_gscan_cfg(dhd_pub_t *dhd, wl_pfn_gscan_cfg_t *pfncfg_gscan_param, int size)
-{
-	int err = BCME_OK;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	err = dhd_iovar(dhd, 0, "pfn_gscan_cfg", (char *)pfncfg_gscan_param, size, 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to execute pfncfg_gscan_param\n", __FUNCTION__));
-		goto exit;
-	}
-exit:
-	return err;
-}
-
-static bool
-is_batch_retrieval_complete(struct dhd_pno_gscan_params *gscan_params)
-{
-	smp_rmb();
-	return (gscan_params->get_batch_flag == GSCAN_BATCH_RETRIEVAL_COMPLETE);
-}
-#endif /* GSCAN_SUPPORT */
-
-static int
-dhd_pno_set_mac_addr(dhd_pub_t *dhd, struct ether_addr *macaddr)
-{
-	int err;
-	wl_pfn_macaddr_cfg_t cfg;
-
-	cfg.version = WL_PFN_MACADDR_CFG_VER;
-	if (ETHER_ISNULLADDR(macaddr)) {
-		cfg.flags = 0;
-	} else {
-		cfg.flags = (WL_PFN_MAC_OUI_ONLY_MASK | WL_PFN_SET_MAC_UNASSOC_MASK);
-	}
-	memcpy(&cfg.macaddr, macaddr, ETHER_ADDR_LEN);
-
-	err = dhd_iovar(dhd, 0, "pfn_macaddr", (char *)&cfg, sizeof(cfg), 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to execute pfn_macaddr\n", __FUNCTION__));
-	}
-
-	return err;
-}
-
-static int
-_dhd_pno_suspend(dhd_pub_t *dhd)
-{
-	int err;
-	int suspend = 1;
-	dhd_pno_status_info_t *_pno_state;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	err = dhd_iovar(dhd, 0, "pfn_suspend", (char *)&suspend, sizeof(suspend), 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to suspend pfn(error :%d)\n", __FUNCTION__, err));
-		goto exit;
-
-	}
-	_pno_state->pno_status = DHD_PNO_SUSPEND;
-exit:
-	return err;
-}
-static int
-_dhd_pno_enable(dhd_pub_t *dhd, int enable)
-{
-	int err = BCME_OK;
-	dhd_pno_status_info_t *_pno_state;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	if (enable & 0xfffe) {
-		DHD_ERROR(("%s invalid value\n", __FUNCTION__));
-		err = BCME_BADARG;
-		goto exit;
-	}
-	if (!dhd_support_sta_mode(dhd)) {
-		DHD_ERROR(("PNO is not allowed for non-STA mode"));
-		err = BCME_BADOPTION;
-		goto exit;
-	}
-	if (enable) {
-		if ((_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) &&
-			dhd_is_associated(dhd, 0, NULL)) {
-			DHD_ERROR(("%s Legacy PNO mode cannot be enabled "
-				"in assoc mode , ignore it\n", __FUNCTION__));
-			err = BCME_BADOPTION;
-			goto exit;
-		}
-	}
-	/* Enable/Disable PNO */
-	err = dhd_iovar(dhd, 0, "pfn", (char *)&enable, sizeof(enable), 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to execute pfn_set - %d\n", __FUNCTION__, err));
-		goto exit;
-	}
-	_pno_state->pno_status = (enable)?
-		DHD_PNO_ENABLED : DHD_PNO_DISABLED;
-	if (!enable)
-		_pno_state->pno_mode = DHD_PNO_NONE_MODE;
-
-	DHD_PNO(("%s set pno as %s\n",
-		__FUNCTION__, enable ? "Enable" : "Disable"));
-exit:
-	return err;
-}
-
-static int
-_dhd_pno_set(dhd_pub_t *dhd, const dhd_pno_params_t *pno_params, dhd_pno_mode_t mode)
-{
-	int err = BCME_OK;
-	wl_pfn_param_t pfn_param;
-	dhd_pno_params_t *_params;
-	dhd_pno_status_info_t *_pno_state;
-	bool combined_scan = FALSE;
-	struct ether_addr macaddr;
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-
-	memset(&pfn_param, 0, sizeof(pfn_param));
-
-	/* set pfn parameters */
-	pfn_param.version = htod32(PFN_VERSION);
-	pfn_param.flags = ((PFN_LIST_ORDER << SORT_CRITERIA_BIT) |
-		(ENABLE << IMMEDIATE_SCAN_BIT) | (ENABLE << REPORT_SEPERATELY_BIT));
-	if (mode == DHD_PNO_LEGACY_MODE) {
-		/* check and set extra pno params */
-		if ((pno_params->params_legacy.pno_repeat != 0) ||
-			(pno_params->params_legacy.pno_freq_expo_max != 0)) {
-			pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT);
-			pfn_param.repeat = (uchar) (pno_params->params_legacy.pno_repeat);
-			pfn_param.exp = (uchar) (pno_params->params_legacy.pno_freq_expo_max);
-		}
-		/* set up pno scan fr */
-		if (pno_params->params_legacy.scan_fr != 0)
-			pfn_param.scan_freq = htod32(pno_params->params_legacy.scan_fr);
-		if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
-			DHD_PNO(("will enable combined scan with BATCHIG SCAN MODE\n"));
-			mode |= DHD_PNO_BATCH_MODE;
-			combined_scan = TRUE;
-		} else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
-			DHD_PNO(("will enable combined scan with HOTLIST SCAN MODE\n"));
-			mode |= DHD_PNO_HOTLIST_MODE;
-			combined_scan = TRUE;
-		}
-#ifdef GSCAN_SUPPORT
-		else if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
-			DHD_PNO(("will enable combined scan with GSCAN SCAN MODE\n"));
-			mode |= DHD_PNO_GSCAN_MODE;
-		}
-#endif /* GSCAN_SUPPORT */
-	}
-	if (mode & (DHD_PNO_BATCH_MODE | DHD_PNO_HOTLIST_MODE)) {
-		/* Scan frequency of 30 sec */
-		pfn_param.scan_freq = htod32(30);
-		/* slow adapt scan is off by default */
-		pfn_param.slow_freq = htod32(0);
-		/* RSSI margin of 30 dBm */
-		pfn_param.rssi_margin = htod16(PNO_RSSI_MARGIN_DBM);
-		/* Network timeout 60 sec */
-		pfn_param.lost_network_timeout = htod32(60);
-		/* best n = 2 by default */
-		pfn_param.bestn = DEFAULT_BESTN;
-		/* mscan m=0 by default, so not record best networks by default */
-		pfn_param.mscan = DEFAULT_MSCAN;
-		/*  default repeat = 10 */
-		pfn_param.repeat = DEFAULT_REPEAT;
-		/* by default, maximum scan interval = 2^2
-		 * scan_freq when adaptive scan is turned on
-		 */
-		pfn_param.exp = DEFAULT_EXP;
-		if (mode == DHD_PNO_BATCH_MODE) {
-			/* In case of BATCH SCAN */
-			if (pno_params->params_batch.bestn)
-				pfn_param.bestn = pno_params->params_batch.bestn;
-			if (pno_params->params_batch.scan_fr)
-				pfn_param.scan_freq = htod32(pno_params->params_batch.scan_fr);
-			if (pno_params->params_batch.mscan)
-				pfn_param.mscan = pno_params->params_batch.mscan;
-			/* enable broadcast scan */
-			pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT);
-		} else if (mode == DHD_PNO_HOTLIST_MODE) {
-			/* In case of HOTLIST SCAN */
-			if (pno_params->params_hotlist.scan_fr)
-				pfn_param.scan_freq = htod32(pno_params->params_hotlist.scan_fr);
-			pfn_param.bestn = 0;
-			pfn_param.repeat = 0;
-			/* enable broadcast scan */
-			pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT);
-		}
-		if (combined_scan) {
-			/* Disable Adaptive Scan */
-			pfn_param.flags &= ~(htod16(ENABLE << ENABLE_ADAPTSCAN_BIT));
-			pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT);
-			pfn_param.repeat = 0;
-			pfn_param.exp = 0;
-			if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
-				/* In case of Legacy PNO + BATCH SCAN */
-				_params = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]);
-				if (_params->params_batch.bestn)
-					pfn_param.bestn = _params->params_batch.bestn;
-				if (_params->params_batch.scan_fr)
-					pfn_param.scan_freq = htod32(_params->params_batch.scan_fr);
-				if (_params->params_batch.mscan)
-					pfn_param.mscan = _params->params_batch.mscan;
-			} else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
-				/* In case of Legacy PNO + HOTLIST SCAN */
-				_params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
-				if (_params->params_hotlist.scan_fr)
-				pfn_param.scan_freq = htod32(_params->params_hotlist.scan_fr);
-				pfn_param.bestn = 0;
-				pfn_param.repeat = 0;
-			}
-		}
-	}
-#ifdef GSCAN_SUPPORT
-	if (mode & DHD_PNO_GSCAN_MODE) {
-		uint32 lost_network_timeout;
-
-		pfn_param.scan_freq = htod32(pno_params->params_gscan.scan_fr);
-		if (pno_params->params_gscan.mscan) {
-			pfn_param.bestn = pno_params->params_gscan.bestn;
-			pfn_param.mscan =  pno_params->params_gscan.mscan;
-			pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT);
-		}
-		/* RSSI margin of 30 dBm */
-		pfn_param.rssi_margin = htod16(PNO_RSSI_MARGIN_DBM);
-		/* ADAPTIVE turned off */
-		pfn_param.flags &= ~(htod16(ENABLE << ENABLE_ADAPTSCAN_BIT));
-		pfn_param.repeat = 0;
-		pfn_param.exp = 0;
-		pfn_param.slow_freq = 0;
-
-		if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
-			dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
-			dhd_pno_params_t *_params;
-
-			_params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
-
-			pfn_param.scan_freq = htod32(MIN(pno_params->params_gscan.scan_fr,
-			_params->params_legacy.scan_fr));
-		}
-
-		lost_network_timeout = (pno_params->params_gscan.max_ch_bucket_freq *
-		                        pfn_param.scan_freq *
-		                        pno_params->params_gscan.lost_ap_window);
-		if (lost_network_timeout) {
-			pfn_param.lost_network_timeout = htod32(MIN(lost_network_timeout,
-			                                 GSCAN_MIN_BSSID_TIMEOUT));
-		} else {
-			pfn_param.lost_network_timeout = htod32(GSCAN_MIN_BSSID_TIMEOUT);
-		}
-	} else
-#endif /* GSCAN_SUPPORT */
-	{
-		if (pfn_param.scan_freq < htod32(PNO_SCAN_MIN_FW_SEC) ||
-			pfn_param.scan_freq > htod32(PNO_SCAN_MAX_FW_SEC)) {
-			DHD_ERROR(("%s pno freq(%d sec) is not valid \n",
-				__FUNCTION__, PNO_SCAN_MIN_FW_SEC));
-			err = BCME_BADARG;
-			goto exit;
-		}
-	}
-
-	memset(&macaddr, 0, ETHER_ADDR_LEN);
-	memcpy(&macaddr, _pno_state->pno_oui, DOT11_OUI_LEN);
-
-	DHD_PNO(("Setting mac oui to FW - %02x:%02x:%02x\n", _pno_state->pno_oui[0],
-	    _pno_state->pno_oui[1], _pno_state->pno_oui[2]));
-	err = dhd_pno_set_mac_addr(dhd, &macaddr);
-	if (err < 0) {
-	DHD_ERROR(("%s : failed to set pno mac address, error - %d\n", __FUNCTION__, err));
-		goto exit;
-	}
-
-
-#ifdef GSCAN_SUPPORT
-			if (mode == DHD_PNO_BATCH_MODE ||
-				((mode & DHD_PNO_GSCAN_MODE) && pno_params->params_gscan.mscan)) {
-#else
-			if (mode == DHD_PNO_BATCH_MODE) {
-#endif /* GSCAN_SUPPORT */
-
-		int _tmp = pfn_param.bestn;
-		/* set bestn to calculate the max mscan which firmware supports */
-		err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 1);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to set pfnmem\n", __FUNCTION__));
-			goto exit;
-		}
-		/* get max mscan which the firmware supports */
-		err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 0);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to get pfnmem\n", __FUNCTION__));
-			goto exit;
-		}
-		DHD_PNO((" returned mscan : %d, set bestn : %d\n", _tmp, pfn_param.bestn));
-		pfn_param.mscan = MIN(pfn_param.mscan, _tmp);
-	}
-	err = dhd_iovar(dhd, 0, "pfn_set", (char *)&pfn_param, sizeof(pfn_param), 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to execute pfn_set %d\n", __FUNCTION__, err));
-		goto exit;
-	}
-	/* need to return mscan if this is for batch scan instead of err */
-	err = (mode == DHD_PNO_BATCH_MODE)? pfn_param.mscan : err;
-exit:
-	return err;
-}
-static int
-_dhd_pno_add_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssids_list, int nssid)
-{
-	int err = BCME_OK;
-	int i = 0;
-	wl_pfn_t pfn_element;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	if (nssid) {
-		NULL_CHECK(ssids_list, "ssid list is NULL", err);
-	}
-	memset(&pfn_element, 0, sizeof(pfn_element));
-	{
-		int j;
-		for (j = 0; j < nssid; j++) {
-			DHD_PNO(("%d: scan  for  %s size = %d hidden = %d\n", j,
-				ssids_list[j].SSID, ssids_list[j].SSID_len, ssids_list[j].hidden));
-		}
-	}
-	/* Check for broadcast ssid */
-	for (i = 0; i < nssid; i++) {
-		if (!ssids_list[i].SSID_len) {
-			DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", i));
-			err = BCME_ERROR;
-			goto exit;
-		}
-	}
-	/* set all pfn ssid */
-	for (i = 0; i < nssid; i++) {
-		pfn_element.infra = htod32(DOT11_BSSTYPE_INFRASTRUCTURE);
-		pfn_element.auth = (DOT11_OPEN_SYSTEM);
-		pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
-		pfn_element.wsec = htod32(0);
-		pfn_element.infra = htod32(1);
-		if (ssids_list[i].hidden) {
-			pfn_element.flags = htod32(ENABLE << WL_PFN_HIDDEN_BIT);
-		} else {
-			pfn_element.flags = 0;
-		}
-		memcpy((char *)pfn_element.ssid.SSID, ssids_list[i].SSID,
-			ssids_list[i].SSID_len);
-		pfn_element.ssid.SSID_len = ssids_list[i].SSID_len;
-		err = dhd_iovar(dhd, 0, "pfn_add", (char *)&pfn_element,
-			sizeof(pfn_element), 1);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to execute pfn_add\n", __FUNCTION__));
-			goto exit;
-		}
-	}
-exit:
-	return err;
-}
-/* qsort compare function */
-static int
-_dhd_pno_cmpfunc(const void *a, const void *b)
-{
-	return (*(uint16*)a - *(uint16*)b);
-}
-static int
-_dhd_pno_chan_merge(uint16 *d_chan_list, int *nchan,
-	uint16 *chan_list1, int nchan1, uint16 *chan_list2, int nchan2)
-{
-	int err = BCME_OK;
-	int i = 0, j = 0, k = 0;
-	uint16 tmp;
-	NULL_CHECK(d_chan_list, "d_chan_list is NULL", err);
-	NULL_CHECK(nchan, "nchan is NULL", err);
-	NULL_CHECK(chan_list1, "chan_list1 is NULL", err);
-	NULL_CHECK(chan_list2, "chan_list2 is NULL", err);
-	/* chan_list1 and chan_list2 should be sorted at first */
-	while (i < nchan1 && j < nchan2) {
-		tmp = chan_list1[i] < chan_list2[j]?
-			chan_list1[i++] : chan_list2[j++];
-		for (; i < nchan1 && chan_list1[i] == tmp; i++);
-		for (; j < nchan2 && chan_list2[j] == tmp; j++);
-		d_chan_list[k++] = tmp;
-	}
-
-	while (i < nchan1) {
-		tmp = chan_list1[i++];
-		for (; i < nchan1 && chan_list1[i] == tmp; i++);
-		d_chan_list[k++] = tmp;
-	}
-
-	while (j < nchan2) {
-		tmp = chan_list2[j++];
-		for (; j < nchan2 && chan_list2[j] == tmp; j++);
-		d_chan_list[k++] = tmp;
-
-	}
-	*nchan = k;
-	return err;
-}
-static int
-_dhd_pno_get_channels(dhd_pub_t *dhd, uint16 *d_chan_list,
-	int *nchan, uint8 band, bool skip_dfs)
-{
-	int err = BCME_OK;
-	int i, j;
-	uint32 chan_buf[WL_NUMCHANNELS + 1];
-	wl_uint32_list_t *list;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	if (*nchan) {
-		NULL_CHECK(d_chan_list, "d_chan_list is NULL", err);
-	}
-	list = (wl_uint32_list_t *) (void *)chan_buf;
-	list->count = htod32(WL_NUMCHANNELS);
-	err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, chan_buf, sizeof(chan_buf), FALSE, 0);
-	if (err < 0) {
-		DHD_ERROR(("failed to get channel list (err: %d)\n", err));
-		goto exit;
-	}
-	for (i = 0, j = 0; i < dtoh32(list->count) && i < *nchan; i++) {
-		if (band == WLC_BAND_2G) {
-			if (dtoh32(list->element[i]) > CHANNEL_2G_MAX)
-				continue;
-		} else if (band == WLC_BAND_5G) {
-			if (dtoh32(list->element[i]) <= CHANNEL_2G_MAX)
-				continue;
-			if (skip_dfs && is_dfs(dtoh32(list->element[i])))
-				continue;
-
-
-	} else if (band == WLC_BAND_AUTO) {
-		if (skip_dfs || !is_dfs(dtoh32(list->element[i])))
-				continue;
-		 } else { /* All channels */
-		if (skip_dfs && is_dfs(dtoh32(list->element[i])))
-				continue;
-		}
-			if (dtoh32(list->element[i]) <= CHANNEL_5G_MAX) {
-			d_chan_list[j++] = (uint16) dtoh32(list->element[i]);
-		} else {
-			err = BCME_BADCHAN;
-			goto exit;
-		}
-	}
-	*nchan = j;
-exit:
-	return err;
-}
-static int
-_dhd_pno_convert_format(dhd_pub_t *dhd, struct dhd_pno_batch_params *params_batch,
-	char *buf, int nbufsize)
-{
-	int err = BCME_OK;
-	int bytes_written = 0, nreadsize = 0;
-	int t_delta = 0;
-	int nleftsize = nbufsize;
-	uint8 cnt = 0;
-	char *bp = buf;
-	char eabuf[ETHER_ADDR_STR_LEN];
-#ifdef PNO_DEBUG
-	char *_base_bp;
-	char msg[150];
-#endif
-	dhd_pno_bestnet_entry_t *iter, *next;
-	dhd_pno_scan_results_t *siter, *snext;
-	dhd_pno_best_header_t *phead, *pprev;
-	NULL_CHECK(params_batch, "params_batch is NULL", err);
-	if (nbufsize > 0)
-		NULL_CHECK(buf, "buf is NULL", err);
-	/* initialize the buffer */
-	memset(buf, 0, nbufsize);
-	DHD_PNO(("%s enter \n", __FUNCTION__));
-	/* # of scans */
-	if (!params_batch->get_batch.batch_started) {
-		bp += nreadsize = sprintf(bp, "scancount=%d\n",
-			params_batch->get_batch.expired_tot_scan_cnt);
-		nleftsize -= nreadsize;
-		params_batch->get_batch.batch_started = TRUE;
-	}
-	DHD_PNO(("%s scancount %d\n", __FUNCTION__, params_batch->get_batch.expired_tot_scan_cnt));
-	/* preestimate scan count until which scan result this report is going to end */
-	list_for_each_entry_safe(siter, snext,
-		&params_batch->get_batch.expired_scan_results_list, list) {
-		phead = siter->bestnetheader;
-		while (phead != NULL) {
-			/* if left_size is less than bestheader total size , stop this */
-			if (nleftsize <=
-				(phead->tot_size + phead->tot_cnt * ENTRY_OVERHEAD))
-				goto exit;
-			/* increase scan count */
-			cnt++;
-			/* # best of each scan */
-			DHD_PNO(("\n<loop : %d, apcount %d>\n", cnt - 1, phead->tot_cnt));
-			/* attribute of the scan */
-			if (phead->reason & PNO_STATUS_ABORT_MASK) {
-				bp += nreadsize = sprintf(bp, "trunc\n");
-				nleftsize -= nreadsize;
-			}
-			list_for_each_entry_safe(iter, next,
-				&phead->entry_list, list) {
-				t_delta = jiffies_to_msecs(jiffies - iter->recorded_time);
-#ifdef PNO_DEBUG
-				_base_bp = bp;
-				memset(msg, 0, sizeof(msg));
-#endif
-				/* BSSID info */
-				bp += nreadsize = sprintf(bp, "bssid=%s\n",
-				bcm_ether_ntoa((const struct ether_addr *)&iter->BSSID, eabuf));
-				nleftsize -= nreadsize;
-				/* SSID */
-				bp += nreadsize = sprintf(bp, "ssid=%s\n", iter->SSID);
-				nleftsize -= nreadsize;
-				/* channel */
-				bp += nreadsize = sprintf(bp, "freq=%d\n",
-				wf_channel2mhz(iter->channel,
-				iter->channel <= CH_MAX_2G_CHANNEL?
-				WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
-				nleftsize -= nreadsize;
-				/* RSSI */
-				bp += nreadsize = sprintf(bp, "level=%d\n", iter->RSSI);
-				nleftsize -= nreadsize;
-				/* add the time consumed in Driver to the timestamp of firmware */
-				iter->timestamp += t_delta;
-				bp += nreadsize = sprintf(bp, "age=%d\n", iter->timestamp);
-				nleftsize -= nreadsize;
-				/* RTT0 */
-				bp += nreadsize = sprintf(bp, "dist=%d\n",
-				(iter->rtt0 == 0)? -1 : iter->rtt0);
-				nleftsize -= nreadsize;
-				/* RTT1 */
-				bp += nreadsize = sprintf(bp, "distSd=%d\n",
-				(iter->rtt0 == 0)? -1 : iter->rtt1);
-				nleftsize -= nreadsize;
-				bp += nreadsize = sprintf(bp, "%s", AP_END_MARKER);
-				nleftsize -= nreadsize;
-				list_del(&iter->list);
-				MFREE(dhd->osh, iter, BESTNET_ENTRY_SIZE);
-#ifdef PNO_DEBUG
-				memcpy(msg, _base_bp, bp - _base_bp);
-				DHD_PNO(("Entry : \n%s", msg));
-#endif
-			}
-			bp += nreadsize = sprintf(bp, "%s", SCAN_END_MARKER);
-			DHD_PNO(("%s", SCAN_END_MARKER));
-			nleftsize -= nreadsize;
-			pprev = phead;
-			/* reset the header */
-			siter->bestnetheader = phead = phead->next;
-			MFREE(dhd->osh, pprev, BEST_HEADER_SIZE);
-
-			siter->cnt_header--;
-		}
-		if (phead == NULL) {
-			/* we store all entry in this scan , so it is ok to delete */
-			list_del(&siter->list);
-			MFREE(dhd->osh, siter, SCAN_RESULTS_SIZE);
-		}
-	}
-exit:
-	if (cnt < params_batch->get_batch.expired_tot_scan_cnt) {
-		DHD_ERROR(("Buffer size is small to save all batch entry,"
-			" cnt : %d (remained_scan_cnt): %d\n",
-			cnt, params_batch->get_batch.expired_tot_scan_cnt - cnt));
-	}
-	params_batch->get_batch.expired_tot_scan_cnt -= cnt;
-	/* set FALSE only if the link list  is empty after returning the data */
-	if (list_empty(&params_batch->get_batch.expired_scan_results_list)) {
-		params_batch->get_batch.batch_started = FALSE;
-		bp += sprintf(bp, "%s", RESULTS_END_MARKER);
-		DHD_PNO(("%s", RESULTS_END_MARKER));
-		DHD_PNO(("%s : Getting the batching data is complete\n", __FUNCTION__));
-	}
-	/* return used memory in buffer */
-	bytes_written = (int32)(bp - buf);
-	return bytes_written;
-}
-static int
-_dhd_pno_clear_all_batch_results(dhd_pub_t *dhd, struct list_head *head, bool only_last)
-{
-	int err = BCME_OK;
-	int removed_scan_cnt = 0;
-	dhd_pno_scan_results_t *siter, *snext;
-	dhd_pno_best_header_t *phead, *pprev;
-	dhd_pno_bestnet_entry_t *iter, *next;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(head, "head is NULL", err);
-	NULL_CHECK(head->next, "head->next is NULL", err);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	list_for_each_entry_safe(siter, snext,
-		head, list) {
-		if (only_last) {
-			/* in case that we need to delete only last one */
-			if (!list_is_last(&siter->list, head)) {
-				/* skip if the one is not last */
-				continue;
-			}
-		}
-		/* delete all data belong if the one is last */
-		phead = siter->bestnetheader;
-		while (phead != NULL) {
-			removed_scan_cnt++;
-			list_for_each_entry_safe(iter, next,
-			&phead->entry_list, list) {
-				list_del(&iter->list);
-				MFREE(dhd->osh, iter, BESTNET_ENTRY_SIZE);
-			}
-			pprev = phead;
-			phead = phead->next;
-			MFREE(dhd->osh, pprev, BEST_HEADER_SIZE);
-		}
-		if (phead == NULL) {
-			/* it is ok to delete top node */
-			list_del(&siter->list);
-			MFREE(dhd->osh, siter, SCAN_RESULTS_SIZE);
-		}
-	}
-	return removed_scan_cnt;
-}
-
-static int
-_dhd_pno_cfg(dhd_pub_t *dhd, uint16 *channel_list, int nchan)
-{
-	int err = BCME_OK;
-	int i = 0;
-	wl_pfn_cfg_t pfncfg_param;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	if (nchan) {
-		NULL_CHECK(channel_list, "nchan is NULL", err);
-	}
-	DHD_PNO(("%s enter :  nchan : %d\n", __FUNCTION__, nchan));
-	memset(&pfncfg_param, 0, sizeof(wl_pfn_cfg_t));
-	/* Setup default values */
-	pfncfg_param.reporttype = htod32(WL_PFN_REPORT_ALLNET);
-	pfncfg_param.channel_num = htod32(0);
-
-	for (i = 0; i < nchan && nchan < WL_NUMCHANNELS; i++)
-		pfncfg_param.channel_list[i] = channel_list[i];
-
-	pfncfg_param.channel_num = htod32(nchan);
-	err = dhd_iovar(dhd, 0, "pfn_cfg", (char *)&pfncfg_param, sizeof(pfncfg_param), 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to execute pfn_cfg\n", __FUNCTION__));
-		goto exit;
-	}
-exit:
-	return err;
-}
-static int
-_dhd_pno_reinitialize_prof(dhd_pub_t *dhd, dhd_pno_params_t *params, dhd_pno_mode_t mode)
-{
-	int err = BCME_OK;
-	dhd_pno_status_info_t *_pno_state;
-	NULL_CHECK(dhd, "dhd is NULL\n", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL\n", err);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	mutex_lock(&_pno_state->pno_mutex);
-	switch (mode) {
-	case DHD_PNO_LEGACY_MODE: {
-		struct dhd_pno_ssid *iter, *next;
-		if (params->params_legacy.nssid > 0) {
-			list_for_each_entry_safe(iter, next,
-				&params->params_legacy.ssid_list, list) {
-				list_del(&iter->list);
-				kfree(iter);
-			}
-		}
-		params->params_legacy.nssid = 0;
-		params->params_legacy.scan_fr = 0;
-		params->params_legacy.pno_freq_expo_max = 0;
-		params->params_legacy.pno_repeat = 0;
-		params->params_legacy.nchan = 0;
-		memset(params->params_legacy.chan_list, 0,
-			sizeof(params->params_legacy.chan_list));
-		break;
-	}
-	case DHD_PNO_BATCH_MODE: {
-		params->params_batch.scan_fr = 0;
-		params->params_batch.mscan = 0;
-		params->params_batch.nchan = 0;
-		params->params_batch.rtt = 0;
-		params->params_batch.bestn = 0;
-		params->params_batch.nchan = 0;
-		params->params_batch.band = WLC_BAND_AUTO;
-		memset(params->params_batch.chan_list, 0,
-			sizeof(params->params_batch.chan_list));
-		params->params_batch.get_batch.batch_started = FALSE;
-		params->params_batch.get_batch.buf = NULL;
-		params->params_batch.get_batch.bufsize = 0;
-		params->params_batch.get_batch.reason = 0;
-		_dhd_pno_clear_all_batch_results(dhd,
-			&params->params_batch.get_batch.scan_results_list, FALSE);
-		_dhd_pno_clear_all_batch_results(dhd,
-			&params->params_batch.get_batch.expired_scan_results_list, FALSE);
-		params->params_batch.get_batch.tot_scan_cnt = 0;
-		params->params_batch.get_batch.expired_tot_scan_cnt = 0;
-		params->params_batch.get_batch.top_node_cnt = 0;
-		INIT_LIST_HEAD(&params->params_batch.get_batch.scan_results_list);
-		INIT_LIST_HEAD(&params->params_batch.get_batch.expired_scan_results_list);
-		break;
-	}
-	case DHD_PNO_HOTLIST_MODE: {
-		struct dhd_pno_bssid *iter, *next;
-		if (params->params_hotlist.nbssid > 0) {
-			list_for_each_entry_safe(iter, next,
-				&params->params_hotlist.bssid_list, list) {
-				list_del(&iter->list);
-				kfree(iter);
-			}
-		}
-		params->params_hotlist.scan_fr = 0;
-		params->params_hotlist.nbssid = 0;
-		params->params_hotlist.nchan = 0;
-		params->params_batch.band = WLC_BAND_AUTO;
-		memset(params->params_hotlist.chan_list, 0,
-			sizeof(params->params_hotlist.chan_list));
-		break;
-	}
-	default:
-		DHD_ERROR(("%s : unknown mode : %d\n", __FUNCTION__, mode));
-		break;
-	}
-	mutex_unlock(&_pno_state->pno_mutex);
-	return err;
-}
-static int
-_dhd_pno_add_bssid(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, int nbssid)
-{
-	int err = BCME_OK;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	if (nbssid) {
-		NULL_CHECK(p_pfn_bssid, "bssid list is NULL", err);
-	}
-	err = dhd_iovar(dhd, 0, "pfn_add_bssid", (char *)p_pfn_bssid,
-		sizeof(wl_pfn_bssid_t) * nbssid, 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to execute pfn_cfg\n", __FUNCTION__));
-		goto exit;
-	}
-exit:
-	return err;
-}
-
-#ifdef GSCAN_SUPPORT
-static int
-_dhd_pno_add_significant_bssid(dhd_pub_t *dhd,
-   wl_pfn_significant_bssid_t *p_pfn_significant_bssid, int nbssid)
-{
-	int err = BCME_OK;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-
-	if (!nbssid) {
-		err = BCME_ERROR;
-		goto exit;
-	}
-
-	NULL_CHECK(p_pfn_significant_bssid, "bssid list is NULL", err);
-
-	err = dhd_iovar(dhd, 0, "pfn_add_swc_bssid", (char *)p_pfn_significant_bssid,
-		sizeof(wl_pfn_significant_bssid_t) * nbssid, 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to execute pfn_significant_bssid %d\n", __FUNCTION__, err));
-		goto exit;
-	}
-exit:
-	return err;
-}
-#endif /* GSCAN_SUPPORT */
-
-int
-dhd_pno_stop_for_ssid(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	uint32 mode = 0;
-	dhd_pno_status_info_t *_pno_state;
-	dhd_pno_params_t *_params;
-	wl_pfn_bssid_t *p_pfn_bssid = NULL;
-	NULL_CHECK(dhd, "dev is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	if (!(_pno_state->pno_mode & DHD_PNO_LEGACY_MODE)) {
-		DHD_ERROR(("%s : LEGACY PNO MODE is not enabled\n", __FUNCTION__));
-		goto exit;
-	}
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	_pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
-#ifdef GSCAN_SUPPORT
-	if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
-		struct dhd_pno_gscan_params *gscan_params;
-
-		_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-		gscan_params = &_params->params_gscan;
-
-		if (gscan_params->mscan)
-			dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
-			/* save current pno_mode before calling dhd_pno_clean */
-		mode = _pno_state->pno_mode;
-		err = dhd_pno_clean(dhd);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-		/* restore previous pno_mode */
-		_pno_state->pno_mode = mode;
-		/* Restart gscan */
-		err = dhd_pno_initiate_gscan_request(dhd, 1, 0);
-		goto exit;
-	}
-#endif /* GSCAN_SUPPORT */
-	/* restart Batch mode  if the batch mode is on */
-	if (_pno_state->pno_mode & (DHD_PNO_BATCH_MODE | DHD_PNO_HOTLIST_MODE)) {
-		/* retrieve the batching data from firmware into host */
-		dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
-		/* save current pno_mode before calling dhd_pno_clean */
-		mode = _pno_state->pno_mode;
-		dhd_pno_clean(dhd);
-		/* restore previous pno_mode */
-		_pno_state->pno_mode = mode;
-		if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
-			_params = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]);
-			/* restart BATCH SCAN */
-			err = dhd_pno_set_for_batch(dhd, &_params->params_batch);
-			if (err < 0) {
-				_pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
-				DHD_ERROR(("%s : failed to restart batch scan(err: %d)\n",
-					__FUNCTION__, err));
-				goto exit;
-			}
-		} else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
-			/* restart HOTLIST SCAN */
-			struct dhd_pno_bssid *iter, *next;
-			_params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
-			p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) *
-			_params->params_hotlist.nbssid, GFP_KERNEL);
-			if (p_pfn_bssid == NULL) {
-				DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array"
-				" (count: %d)",
-					__FUNCTION__, _params->params_hotlist.nbssid));
-				err = BCME_ERROR;
-				_pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
-				goto exit;
-			}
-			/* convert dhd_pno_bssid to wl_pfn_bssid */
-			list_for_each_entry_safe(iter, next,
-			&_params->params_hotlist.bssid_list, list) {
-				memcpy(&p_pfn_bssid->macaddr,
-				&iter->macaddr, ETHER_ADDR_LEN);
-				p_pfn_bssid->flags = iter->flags;
-				p_pfn_bssid++;
-			}
-			err = dhd_pno_set_for_hotlist(dhd, p_pfn_bssid, &_params->params_hotlist);
-			if (err < 0) {
-				_pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
-				DHD_ERROR(("%s : failed to restart hotlist scan(err: %d)\n",
-					__FUNCTION__, err));
-				goto exit;
-			}
-		}
-	} else {
-		err = dhd_pno_clean(dhd);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-	}
-exit:
-	kfree(p_pfn_bssid);
-	return err;
-}
-
-int
-dhd_pno_enable(dhd_pub_t *dhd, int enable)
-{
-	int err = BCME_OK;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	return (_dhd_pno_enable(dhd, enable));
-}
-
-static wlc_ssid_ext_t *
-dhd_pno_get_legacy_pno_ssid(dhd_pub_t *dhd, dhd_pno_status_info_t *pno_state)
-{
-	int err = BCME_OK;
-	int i;
-	struct dhd_pno_ssid *iter, *next;
-	dhd_pno_params_t	*_params1 = &pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
-	wlc_ssid_ext_t *p_ssid_list;
-
-	p_ssid_list = kzalloc(sizeof(wlc_ssid_ext_t) *
-	                   _params1->params_legacy.nssid, GFP_KERNEL);
-	if (p_ssid_list == NULL) {
-		DHD_ERROR(("%s : failed to allocate wlc_ssid_ext_t array (count: %d)",
-			__FUNCTION__, _params1->params_legacy.nssid));
-		err = BCME_ERROR;
-		pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
-		goto exit;
-	}
-	i = 0;
-	/* convert dhd_pno_ssid to wlc_ssid_ext_t */
-	list_for_each_entry_safe(iter, next, &_params1->params_legacy.ssid_list, list) {
-		p_ssid_list[i].SSID_len = iter->SSID_len;
-		p_ssid_list[i].hidden = iter->hidden;
-		memcpy(p_ssid_list[i].SSID, iter->SSID, p_ssid_list[i].SSID_len);
-		i++;
-	}
-exit:
-	return p_ssid_list;
-}
-
-static int
-dhd_pno_add_to_ssid_list(dhd_pno_params_t *params, wlc_ssid_ext_t *ssid_list,
-    int nssid)
-{
-	int ret = 0;
-	int i;
-	struct dhd_pno_ssid *_pno_ssid;
-
-	for (i = 0; i < nssid; i++) {
-		if (ssid_list[i].SSID_len > DOT11_MAX_SSID_LEN) {
-			DHD_ERROR(("%s : Invalid SSID length %d\n",
-				__FUNCTION__, ssid_list[i].SSID_len));
-			ret = BCME_ERROR;
-			goto exit;
-		}
-		_pno_ssid = kzalloc(sizeof(struct dhd_pno_ssid), GFP_KERNEL);
-		if (_pno_ssid == NULL) {
-			DHD_ERROR(("%s : failed to allocate struct dhd_pno_ssid\n",
-				__FUNCTION__));
-			ret = BCME_ERROR;
-			goto exit;
-		}
-		_pno_ssid->SSID_len = ssid_list[i].SSID_len;
-		_pno_ssid->hidden = ssid_list[i].hidden;
-		memcpy(_pno_ssid->SSID, ssid_list[i].SSID, _pno_ssid->SSID_len);
-		list_add_tail(&_pno_ssid->list, &params->params_legacy.ssid_list);
-	}
-
-exit:
-	return ret;
-}
-
-int
-dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssid_list, int nssid,
-	uint16  scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan)
-{
-	dhd_pno_params_t *_params;
-	dhd_pno_params_t *_params2;
-	dhd_pno_status_info_t *_pno_state;
-	uint16 _chan_list[WL_NUMCHANNELS];
-	int32 tot_nchan = 0;
-	int err = BCME_OK;
-	int i;
-	int mode = 0;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-
-	if (!dhd_support_sta_mode(dhd)) {
-		err = BCME_BADOPTION;
-		goto exit_no_clear;
-	}
-	DHD_PNO(("%s enter : scan_fr :%d, pno_repeat :%d,"
-			"pno_freq_expo_max: %d, nchan :%d\n", __FUNCTION__,
-			scan_fr, pno_repeat, pno_freq_expo_max, nchan));
-
-	_params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
-	/* If GSCAN is also ON will handle this down below */
-#ifdef GSCAN_SUPPORT
-	if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE &&
-		!(_pno_state->pno_mode & DHD_PNO_GSCAN_MODE)) {
-#else
-		if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
-#endif /* GSCAN_SUPPORT */
-		DHD_ERROR(("%s : Legacy PNO mode was already started, "
-			"will disable previous one to start new one\n", __FUNCTION__));
-		err = dhd_pno_stop_for_ssid(dhd);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to stop legacy PNO (err %d)\n",
-				__FUNCTION__, err));
-			goto exit_no_clear;
-		}
-	}
-	_pno_state->pno_mode |= DHD_PNO_LEGACY_MODE;
-	err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to reinitialize profile (err %d)\n",
-			__FUNCTION__, err));
-		goto exit_no_clear;
-	}
-	memset(_chan_list, 0, sizeof(_chan_list));
-	tot_nchan = MIN(nchan, WL_NUMCHANNELS);
-	if (tot_nchan > 0 && channel_list) {
-		for (i = 0; i < tot_nchan; i++)
-		_params->params_legacy.chan_list[i] = _chan_list[i] = channel_list[i];
-	}
-#ifdef GSCAN_SUPPORT
-	else {
-		tot_nchan = WL_NUMCHANNELS;
-		err = _dhd_pno_get_channels(dhd, _chan_list, &tot_nchan,
-				(WLC_BAND_2G | WLC_BAND_5G), TRUE);
-		if (err < 0) {
-			tot_nchan = 0;
-			DHD_PNO(("Could not get channel list for PNO SSID\n"));
-		} else {
-			for (i = 0; i < tot_nchan; i++)
-			_params->params_legacy.chan_list[i] = _chan_list[i];
-		}
-	}
-#endif /* GSCAN_SUPPORT */
-
-	if (_pno_state->pno_mode & (DHD_PNO_BATCH_MODE | DHD_PNO_HOTLIST_MODE)) {
-		DHD_PNO(("BATCH SCAN is on progress in firmware\n"));
-		/* retrieve the batching data from firmware into host */
-		dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
-		/* store current pno_mode before disabling pno */
-		mode = _pno_state->pno_mode;
-		err = _dhd_pno_enable(dhd, PNO_OFF);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to disable PNO\n", __FUNCTION__));
-			goto exit_no_clear;
-		}
-		/* restore the previous mode */
-		_pno_state->pno_mode = mode;
-		/* use superset of channel list between two mode */
-		if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
-			_params2 = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]);
-			if (_params2->params_batch.nchan > 0 && tot_nchan > 0) {
-				err = _dhd_pno_chan_merge(_chan_list, &tot_nchan,
-					&_params2->params_batch.chan_list[0],
-					_params2->params_batch.nchan,
-					&channel_list[0], tot_nchan);
-				if (err < 0) {
-					DHD_ERROR(("%s : failed to merge channel list"
-					" between legacy and batch\n",
-						__FUNCTION__));
-					goto exit_no_clear;
-				}
-			}  else {
-				DHD_PNO(("superset channel will use"
-				" all channels in firmware\n"));
-			}
-		} else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
-			_params2 = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
-			if (_params2->params_hotlist.nchan > 0 && tot_nchan > 0) {
-				err = _dhd_pno_chan_merge(_chan_list, &tot_nchan,
-					&_params2->params_hotlist.chan_list[0],
-					_params2->params_hotlist.nchan,
-					&channel_list[0], tot_nchan);
-				if (err < 0) {
-					DHD_ERROR(("%s : failed to merge channel list"
-					" between legacy and hotlist\n",
-						__FUNCTION__));
-					goto exit_no_clear;
-				}
-			}
-		}
-	}
-	_params->params_legacy.scan_fr = scan_fr;
-	_params->params_legacy.pno_repeat = pno_repeat;
-	_params->params_legacy.pno_freq_expo_max = pno_freq_expo_max;
-	_params->params_legacy.nchan = tot_nchan;
-	_params->params_legacy.nssid = nssid;
-	INIT_LIST_HEAD(&_params->params_legacy.ssid_list);
-#ifdef GSCAN_SUPPORT
-	/* dhd_pno_initiate_gscan_request will handle simultaneous Legacy PNO and GSCAN */
-	if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
-		if (dhd_pno_add_to_ssid_list(_params, ssid_list, nssid) < 0) {
-			err = BCME_ERROR;
-			goto exit;
-		}
-		DHD_PNO(("GSCAN mode is ON! Will restart GSCAN+Legacy PNO\n"));
-		err = dhd_pno_initiate_gscan_request(dhd, 1, 0);
-		goto exit;
-	}
-#endif /* GSCAN_SUPPORT */
-	if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_LEGACY_MODE)) < 0) {
-		DHD_ERROR(("failed to set call pno_set (err %d) in firmware\n", err));
-		goto exit;
-	}
-	if ((err = _dhd_pno_add_ssid(dhd, ssid_list, nssid)) < 0) {
-		DHD_ERROR(("failed to add ssid list(err %d), %d in firmware\n", err, nssid));
-		goto exit;
-	}
-	if (dhd_pno_add_to_ssid_list(_params, ssid_list, nssid) < 0) {
-		err = BCME_ERROR;
-		goto exit;
-	}
-	if (tot_nchan > 0) {
-		if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) {
-			DHD_ERROR(("%s : failed to set call pno_cfg (err %d) in firmware\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-	}
-	if (_pno_state->pno_status == DHD_PNO_DISABLED) {
-		if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0)
-			DHD_ERROR(("%s : failed to enable PNO\n", __FUNCTION__));
-	}
-exit:
-	if (err < 0) {
-		_dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
-	}
-exit_no_clear:
-	/* clear mode in case of error */
-	if (err < 0) {
-		int ret = dhd_pno_clean(dhd);
-
-		if (ret < 0) {
-			DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
-				__FUNCTION__, ret));
-		} else {
-			_pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
-		}
-	}
-	return err;
-}
-int
-dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params)
-{
-	int err = BCME_OK;
-	uint16 _chan_list[WL_NUMCHANNELS];
-	int rem_nchan = 0, tot_nchan = 0;
-	int mode = 0, mscan = 0;
-	dhd_pno_params_t *_params;
-	dhd_pno_params_t *_params2;
-	dhd_pno_status_info_t *_pno_state;
-	wlc_ssid_ext_t *p_ssid_list = NULL;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	NULL_CHECK(batch_params, "batch_params is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	if (!dhd_support_sta_mode(dhd)) {
-		err = BCME_BADOPTION;
-		goto exit;
-	}
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-	_params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
-	if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
-		_pno_state->pno_mode |= DHD_PNO_BATCH_MODE;
-		err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to call _dhd_pno_reinitialize_prof\n",
-				__FUNCTION__));
-			goto exit;
-		}
-	} else {
-		/* batch mode is already started */
-		return -EBUSY;
-	}
-	_params->params_batch.scan_fr = batch_params->scan_fr;
-	_params->params_batch.bestn = batch_params->bestn;
-	_params->params_batch.mscan = (batch_params->mscan)?
-		batch_params->mscan : DEFAULT_BATCH_MSCAN;
-	_params->params_batch.nchan = batch_params->nchan;
-	memcpy(_params->params_batch.chan_list, batch_params->chan_list,
-		sizeof(_params->params_batch.chan_list));
-
-	memset(_chan_list, 0, sizeof(_chan_list));
-
-	rem_nchan = ARRAYSIZE(batch_params->chan_list) - batch_params->nchan;
-	if (batch_params->band == WLC_BAND_2G || batch_params->band == WLC_BAND_5G) {
-		/* get a valid channel list based on band B or A */
-		err = _dhd_pno_get_channels(dhd,
-		&_params->params_batch.chan_list[batch_params->nchan],
-		&rem_nchan, batch_params->band, FALSE);
-		if (err < 0) {
-			DHD_ERROR(("%s: failed to get valid channel list(band : %d)\n",
-				__FUNCTION__, batch_params->band));
-			goto exit;
-		}
-		/* now we need to update nchan because rem_chan has valid channel count */
-		_params->params_batch.nchan += rem_nchan;
-		/* need to sort channel list */
-		sort(_params->params_batch.chan_list, _params->params_batch.nchan,
-			sizeof(_params->params_batch.chan_list[0]), _dhd_pno_cmpfunc, NULL);
-	}
-#ifdef PNO_DEBUG
-{
-		DHD_PNO(("Channel list : "));
-		for (i = 0; i < _params->params_batch.nchan; i++) {
-			DHD_PNO(("%d ", _params->params_batch.chan_list[i]));
-		}
-		DHD_PNO(("\n"));
-}
-#endif
-	if (_params->params_batch.nchan) {
-		/* copy the channel list into local array */
-		memcpy(_chan_list, _params->params_batch.chan_list, sizeof(_chan_list));
-		tot_nchan = _params->params_batch.nchan;
-	}
-	if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
-		DHD_PNO(("PNO SSID is on progress in firmware\n"));
-		/* store current pno_mode before disabling pno */
-		mode = _pno_state->pno_mode;
-		err = _dhd_pno_enable(dhd, PNO_OFF);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to disable PNO\n", __FUNCTION__));
-			goto exit;
-		}
-		/* restore the previous mode */
-		_pno_state->pno_mode = mode;
-		/* Use the superset for channelist between two mode */
-		_params2 = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
-		if (_params2->params_legacy.nchan > 0 && _params->params_batch.nchan > 0) {
-			err = _dhd_pno_chan_merge(_chan_list, &tot_nchan,
-				&_params2->params_legacy.chan_list[0],
-				_params2->params_legacy.nchan,
-				&_params->params_batch.chan_list[0], _params->params_batch.nchan);
-			if (err < 0) {
-				DHD_ERROR(("%s : failed to merge channel list"
-				" between legacy and batch\n",
-					__FUNCTION__));
-				goto exit;
-			}
-		} else {
-			DHD_PNO(("superset channel will use all channels in firmware\n"));
-		}
-		p_ssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
-		if (!p_ssid_list) {
-			err = BCME_NOMEM;
-			DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
-			goto exit;
-		}
-		if ((err = _dhd_pno_add_ssid(dhd, p_ssid_list,
-			_params2->params_legacy.nssid)) < 0) {
-			DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err));
-			goto exit;
-		}
-	}
-	if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_BATCH_MODE)) < 0) {
-		DHD_ERROR(("%s : failed to set call pno_set (err %d) in firmware\n",
-			__FUNCTION__, err));
-		goto exit;
-	} else {
-		/* we need to return mscan */
-		mscan = err;
-	}
-	if (tot_nchan > 0) {
-		if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) {
-			DHD_ERROR(("%s : failed to set call pno_cfg (err %d) in firmware\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-	}
-	if (_pno_state->pno_status == DHD_PNO_DISABLED) {
-		if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0)
-			DHD_ERROR(("%s : failed to enable PNO\n", __FUNCTION__));
-	}
-exit:
-	/* clear mode in case of error */
-	if (err < 0)
-		_pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
-	else {
-		/* return #max scan firmware can do */
-		err = mscan;
-	}
-	if (p_ssid_list)
-		kfree(p_ssid_list);
-	return err;
-}
-
-
-#ifdef GSCAN_SUPPORT
-static void
-dhd_pno_reset_cfg_gscan(dhd_pno_params_t *_params,
-            dhd_pno_status_info_t *_pno_state, uint8 flags)
-{
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	if (flags & GSCAN_FLUSH_SCAN_CFG) {
-		_params->params_gscan.bestn = 0;
-		_params->params_gscan.mscan = 0;
-		_params->params_gscan.buffer_threshold = GSCAN_BATCH_NO_THR_SET;
-		_params->params_gscan.scan_fr = 0;
-		_params->params_gscan.send_all_results_flag = 0;
-		memset(_params->params_gscan.channel_bucket, 0,
-		_params->params_gscan.nchannel_buckets *
-		 sizeof(struct dhd_pno_gscan_channel_bucket));
-		_params->params_gscan.nchannel_buckets = 0;
-		DHD_PNO(("Flush Scan config\n"));
-	}
-	if (flags & GSCAN_FLUSH_HOTLIST_CFG) {
-		struct dhd_pno_bssid *iter, *next;
-		if (_params->params_gscan.nbssid_hotlist > 0) {
-			list_for_each_entry_safe(iter, next,
-				&_params->params_gscan.hotlist_bssid_list, list) {
-				list_del(&iter->list);
-				kfree(iter);
-			}
-		}
-		_params->params_gscan.nbssid_hotlist = 0;
-		DHD_PNO(("Flush Hotlist Config\n"));
-	}
-	if (flags & GSCAN_FLUSH_SIGNIFICANT_CFG) {
-		dhd_pno_significant_bssid_t *iter, *next;
-
-		if (_params->params_gscan.nbssid_significant_change > 0) {
-			list_for_each_entry_safe(iter, next,
-				&_params->params_gscan.significant_bssid_list, list) {
-				list_del(&iter->list);
-				kfree(iter);
-			}
-		}
-		_params->params_gscan.nbssid_significant_change = 0;
-		DHD_PNO(("Flush Significant Change Config\n"));
-	}
-
-	return;
-}
-
-void
-dhd_pno_lock_batch_results(dhd_pub_t *dhd)
-{
-	dhd_pno_status_info_t *_pno_state;
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	mutex_lock(&_pno_state->pno_mutex);
-	return;
-}
-
-void
-dhd_pno_unlock_batch_results(dhd_pub_t *dhd)
-{
-	dhd_pno_status_info_t *_pno_state;
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	mutex_unlock(&_pno_state->pno_mutex);
-	return;
-}
-
-void
-dhd_wait_batch_results_complete(dhd_pub_t *dhd)
-{
-	dhd_pno_status_info_t *_pno_state;
-	dhd_pno_params_t *_params;
-
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-
-	/* Has the workqueue finished its job already?? */
-	if (_params->params_gscan.get_batch_flag == GSCAN_BATCH_RETRIEVAL_IN_PROGRESS) {
-		DHD_PNO(("%s: Waiting to complete retrieval..\n", __FUNCTION__));
-		wait_event_interruptible_timeout(_pno_state->batch_get_wait,
-		     is_batch_retrieval_complete(&_params->params_gscan),
-		     msecs_to_jiffies(GSCAN_BATCH_GET_MAX_WAIT));
-	} else { /* GSCAN_BATCH_RETRIEVAL_COMPLETE */
-		gscan_results_cache_t *iter;
-		uint16 num_results = 0;
-		int err;
-
-		mutex_lock(&_pno_state->pno_mutex);
-		iter = _params->params_gscan.gscan_batch_cache;
-		while (iter) {
-			num_results += iter->tot_count - iter->tot_consumed;
-			iter = iter->next;
-		}
-		mutex_unlock(&_pno_state->pno_mutex);
-
-		/* All results consumed/No results cached??
-		 * Get fresh results from FW
-		 */
-		if (!num_results) {
-			DHD_PNO(("%s: No results cached, getting from FW..\n", __FUNCTION__));
-			err = dhd_retreive_batch_scan_results(dhd);
-			if (err == BCME_OK) {
-				wait_event_interruptible_timeout(_pno_state->batch_get_wait,
-				  is_batch_retrieval_complete(&_params->params_gscan),
-				  msecs_to_jiffies(GSCAN_BATCH_GET_MAX_WAIT));
-			}
-		}
-	}
-	DHD_PNO(("%s: Wait complete\n", __FUNCTION__));
-
-	return;
-}
-
-static void *
-dhd_get_gscan_batch_results(dhd_pub_t *dhd, uint32 *len)
-{
-	gscan_results_cache_t *iter, *results;
-	dhd_pno_status_info_t *_pno_state;
-	dhd_pno_params_t *_params;
-	uint16 num_scan_ids = 0, num_results = 0;
-
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-
-	iter = results = _params->params_gscan.gscan_batch_cache;
-	while (iter) {
-		num_results += iter->tot_count - iter->tot_consumed;
-		num_scan_ids++;
-		iter = iter->next;
-	}
-
-	*len = ((num_results << 16) | (num_scan_ids));
-	return results;
-}
-
-void *
-dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type,
-         void *info, uint32 *len)
-{
-	void *ret = NULL;
-	dhd_pno_gscan_capabilities_t *ptr;
-
-	if (!len) {
-		DHD_ERROR(("%s: len is NULL\n", __FUNCTION__));
-		return ret;
-	}
-
-	switch (type) {
-		case DHD_PNO_GET_CAPABILITIES:
-			ptr = (dhd_pno_gscan_capabilities_t *)
-			kmalloc(sizeof(dhd_pno_gscan_capabilities_t), GFP_KERNEL);
-			if (!ptr)
-				break;
-			/* Hardcoding these values for now, need to get
-			 * these values from FW, will change in a later check-in
-			 */
-			ptr->max_scan_cache_size = 12;
-			ptr->max_scan_buckets = GSCAN_MAX_CH_BUCKETS;
-			ptr->max_ap_cache_per_scan = 16;
-			ptr->max_rssi_sample_size = PFN_SWC_RSSI_WINDOW_MAX;
-			ptr->max_scan_reporting_threshold = 100;
-			ptr->max_hotlist_aps = PFN_HOTLIST_MAX_NUM_APS;
-			ptr->max_significant_wifi_change_aps = PFN_SWC_MAX_NUM_APS;
-			ret = (void *)ptr;
-			*len = sizeof(dhd_pno_gscan_capabilities_t);
-			break;
-
-		case DHD_PNO_GET_BATCH_RESULTS:
-			ret = dhd_get_gscan_batch_results(dhd, len);
-			break;
-		case DHD_PNO_GET_CHANNEL_LIST:
-			if (info) {
-				uint16 ch_list[WL_NUMCHANNELS];
-				uint32 *ptr, mem_needed, i;
-				int32 err, nchan = WL_NUMCHANNELS;
-				uint32 *gscan_band = (uint32 *) info;
-				uint8 band = 0;
-
-				/* No band specified?, nothing to do */
-				if ((*gscan_band & GSCAN_BAND_MASK) == 0) {
-					DHD_PNO(("No band specified\n"));
-					*len = 0;
-					break;
-				}
-
-				/* HAL and DHD use different bits for 2.4G and
-				 * 5G in bitmap. Hence translating it here...
-				 */
-				if (*gscan_band & GSCAN_BG_BAND_MASK) {
-					band |= WLC_BAND_2G;
-				}
-				if (*gscan_band & GSCAN_A_BAND_MASK) {
-					band |= WLC_BAND_5G;
-				}
-
-				err = _dhd_pno_get_channels(dhd, ch_list, &nchan,
-				                          (band & GSCAN_ABG_BAND_MASK),
-				                          !(*gscan_band & GSCAN_DFS_MASK));
-
-				if (err < 0) {
-					DHD_ERROR(("%s: failed to get valid channel list\n",
-						__FUNCTION__));
-					*len = 0;
-				} else {
-					mem_needed = sizeof(uint32) * nchan;
-					ptr = (uint32 *) kmalloc(mem_needed, GFP_KERNEL);
-					if (!ptr) {
-						DHD_ERROR(("%s: Unable to malloc %d bytes\n",
-							__FUNCTION__, mem_needed));
-						break;
-					}
-					for (i = 0; i < nchan; i++) {
-						ptr[i] = wf_channel2mhz(ch_list[i],
-							(ch_list[i] <= CH_MAX_2G_CHANNEL?
-							WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
-					}
-					ret = ptr;
-					*len = mem_needed;
-				}
-			} else {
-				*len = 0;
-				DHD_ERROR(("%s: info buffer is NULL\n", __FUNCTION__));
-			}
-			break;
-
-		default:
-			DHD_ERROR(("%s: Unrecognized cmd type - %d\n", __FUNCTION__, type));
-			break;
-	}
-
-	return ret;
-
-}
-
-int
-dhd_pno_set_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type,
-    void *buf, uint8 flush)
-{
-	int err = BCME_OK;
-	dhd_pno_params_t *_params;
-	int i;
-	dhd_pno_status_info_t *_pno_state;
-
-	NULL_CHECK(dhd, "dhd is NULL", err);
-
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-	mutex_lock(&_pno_state->pno_mutex);
-
-	switch (type) {
-		case DHD_PNO_BATCH_SCAN_CFG_ID:
-		{
-			gscan_batch_params_t *ptr = (gscan_batch_params_t *)buf;
-			_params->params_gscan.bestn = ptr->bestn;
-			_params->params_gscan.mscan = ptr->mscan;
-			_params->params_gscan.buffer_threshold = ptr->buffer_threshold;
-			break;
-		}
-		case DHD_PNO_GEOFENCE_SCAN_CFG_ID:
-		{
-			gscan_hotlist_scan_params_t *ptr = (gscan_hotlist_scan_params_t *)buf;
-			struct dhd_pno_bssid *_pno_bssid;
-			struct bssid_t *bssid_ptr;
-			int8 flags;
-
-			if (flush) {
-				dhd_pno_reset_cfg_gscan(_params, _pno_state,
-				    GSCAN_FLUSH_HOTLIST_CFG);
-			}
-
-			if (!ptr->nbssid) {
-				break;
-			}
-			if (!_params->params_gscan.nbssid_hotlist) {
-				INIT_LIST_HEAD(&_params->params_gscan.hotlist_bssid_list);
-			}
-			if ((_params->params_gscan.nbssid_hotlist +
-			          ptr->nbssid) > PFN_SWC_MAX_NUM_APS) {
-				DHD_ERROR(("Excessive number of hotlist APs programmed %d\n",
-				     (_params->params_gscan.nbssid_hotlist +
-				      ptr->nbssid)));
-				err = BCME_RANGE;
-				goto exit;
-			}
-
-			for (i = 0, bssid_ptr = ptr->bssid; i < ptr->nbssid; i++, bssid_ptr++) {
-				_pno_bssid = kzalloc(sizeof(struct dhd_pno_bssid), GFP_KERNEL);
-
-				if (!_pno_bssid) {
-					DHD_ERROR(("_pno_bssid is NULL, cannot kalloc %zd bytes",
-					       sizeof(struct dhd_pno_bssid)));
-					err = BCME_NOMEM;
-					goto exit;
-				}
-				memcpy(&_pno_bssid->macaddr, &bssid_ptr->macaddr, ETHER_ADDR_LEN);
-
-				flags = (int8) bssid_ptr->rssi_reporting_threshold;
-				_pno_bssid->flags = flags  << WL_PFN_RSSI_SHIFT;
-				list_add_tail(&_pno_bssid->list,
-				   &_params->params_gscan.hotlist_bssid_list);
-			}
-
-			_params->params_gscan.nbssid_hotlist += ptr->nbssid;
-			_params->params_gscan.lost_ap_window = ptr->lost_ap_window;
-			break;
-		}
-		case DHD_PNO_SIGNIFICANT_SCAN_CFG_ID:
-		{
-			gscan_swc_params_t *ptr = (gscan_swc_params_t *)buf;
-			dhd_pno_significant_bssid_t *_pno_significant_change_bssid;
-			wl_pfn_significant_bssid_t *significant_bssid_ptr;
-
-			if (flush) {
-				dhd_pno_reset_cfg_gscan(_params, _pno_state,
-				   GSCAN_FLUSH_SIGNIFICANT_CFG);
-			}
-
-			if (!ptr->nbssid) {
-				break;
-			}
-			if (!_params->params_gscan.nbssid_significant_change) {
-				INIT_LIST_HEAD(&_params->params_gscan.significant_bssid_list);
-			}
-			if ((_params->params_gscan.nbssid_significant_change +
-			          ptr->nbssid) > PFN_SWC_MAX_NUM_APS) {
-				DHD_ERROR(("Excessive number of SWC APs programmed %d\n",
-				     (_params->params_gscan.nbssid_significant_change +
-				      ptr->nbssid)));
-				err = BCME_RANGE;
-				goto exit;
-			}
-
-			for (i = 0, significant_bssid_ptr = ptr->bssid_elem_list;
-			     i < ptr->nbssid; i++, significant_bssid_ptr++) {
-				_pno_significant_change_bssid =
-				      kzalloc(sizeof(dhd_pno_significant_bssid_t),
-				      GFP_KERNEL);
-
-				if (!_pno_significant_change_bssid) {
-					DHD_ERROR(("SWC bssidptr is NULL, cannot kalloc %zd bytes",
-					sizeof(dhd_pno_significant_bssid_t)));
-					err = BCME_NOMEM;
-					goto exit;
-				}
-				memcpy(&_pno_significant_change_bssid->BSSID,
-				    &significant_bssid_ptr->macaddr, ETHER_ADDR_LEN);
-				_pno_significant_change_bssid->rssi_low_threshold =
-				    significant_bssid_ptr->rssi_low_threshold;
-				_pno_significant_change_bssid->rssi_high_threshold =
-				    significant_bssid_ptr->rssi_high_threshold;
-				list_add_tail(&_pno_significant_change_bssid->list,
-				    &_params->params_gscan.significant_bssid_list);
-			}
-
-			_params->params_gscan.swc_nbssid_threshold = ptr->swc_threshold;
-			_params->params_gscan.swc_rssi_window_size = ptr->rssi_window;
-			_params->params_gscan.lost_ap_window = ptr->lost_ap_window;
-			_params->params_gscan.nbssid_significant_change += ptr->nbssid;
-			break;
-		}
-		case DHD_PNO_SCAN_CFG_ID:
-		{
-			int i, k, valid = 0;
-			uint16 band, min;
-			gscan_scan_params_t *ptr = (gscan_scan_params_t *)buf;
-			struct dhd_pno_gscan_channel_bucket *ch_bucket;
-
-			if (ptr->nchannel_buckets <= GSCAN_MAX_CH_BUCKETS) {
-				_params->params_gscan.nchannel_buckets = ptr->nchannel_buckets;
-
-				memcpy(_params->params_gscan.channel_bucket, ptr->channel_bucket,
-				    _params->params_gscan.nchannel_buckets *
-				    sizeof(struct dhd_pno_gscan_channel_bucket));
-				min = ptr->channel_bucket[0].bucket_freq_multiple;
-				ch_bucket = _params->params_gscan.channel_bucket;
-
-				for (i = 0; i < ptr->nchannel_buckets; i++) {
-					band = ch_bucket[i].band;
-					for (k = 0; k < ptr->channel_bucket[i].num_channels; k++)  {
-						ch_bucket[i].chan_list[k] =
-						wf_mhz2channel(ptr->channel_bucket[i].chan_list[k],
-							0);
-					}
-					ch_bucket[i].band = 0;
-					/* HAL and DHD use different bits for 2.4G and
-					 * 5G in bitmap. Hence translating it here...
-					 */
-					if (band & GSCAN_BG_BAND_MASK)
-						ch_bucket[i].band |= WLC_BAND_2G;
-
-					if (band & GSCAN_A_BAND_MASK)
-						ch_bucket[i].band |= WLC_BAND_5G;
-
-					if (band & GSCAN_DFS_MASK)
-						ch_bucket[i].band |= GSCAN_DFS_MASK;
-					if (ptr->scan_fr ==
-					    ptr->channel_bucket[i].bucket_freq_multiple) {
-						valid = 1;
-					}
-					if (ptr->channel_bucket[i].bucket_freq_multiple < min)
-						min = ptr->channel_bucket[i].bucket_freq_multiple;
-
-					DHD_PNO(("band %d report_flag %d\n", ch_bucket[i].band,
-					          ch_bucket[i].report_flag));
-				}
-				if (!valid)
-					ptr->scan_fr = min;
-
-				for (i = 0; i < ptr->nchannel_buckets; i++) {
-					ch_bucket[i].bucket_freq_multiple =
-					ch_bucket[i].bucket_freq_multiple/ptr->scan_fr;
-				}
-				_params->params_gscan.scan_fr = ptr->scan_fr;
-
-				DHD_PNO(("num_buckets %d scan_fr %d\n", ptr->nchannel_buckets,
-				        _params->params_gscan.scan_fr));
-			} else {
-				err = BCME_BADARG;
-			}
-			break;
-		}
-		default:
-			err = BCME_BADARG;
-			DHD_ERROR(("%s: Unrecognized cmd type - %d\n", __FUNCTION__, type));
-			break;
-	}
-exit:
-	mutex_unlock(&_pno_state->pno_mutex);
-	return err;
-
-}
-
-
-static bool
-validate_gscan_params(struct dhd_pno_gscan_params *gscan_params)
-{
-	unsigned int i, k;
-
-	if (!gscan_params->scan_fr || !gscan_params->nchannel_buckets) {
-		DHD_ERROR(("%s : Scan freq - %d or number of channel buckets - %d is empty\n",
-		 __FUNCTION__, gscan_params->scan_fr, gscan_params->nchannel_buckets));
-		return false;
-	}
-
-	for (i = 0; i < gscan_params->nchannel_buckets; i++) {
-		if (!gscan_params->channel_bucket[i].band) {
-			for (k = 0; k < gscan_params->channel_bucket[i].num_channels; k++) {
-				if (gscan_params->channel_bucket[i].chan_list[k] > CHANNEL_5G_MAX) {
-					DHD_ERROR(("%s : Unknown channel %d\n", __FUNCTION__,
-					 gscan_params->channel_bucket[i].chan_list[k]));
-					return false;
-				}
-			}
-		}
-	}
-
-	return true;
-}
-
-static int
-dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params)
-{
-	int err = BCME_OK;
-	int mode, i = 0, k;
-	uint16 _chan_list[WL_NUMCHANNELS];
-	int tot_nchan = 0;
-	int num_buckets_to_fw, tot_num_buckets, gscan_param_size;
-	dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
-	wl_pfn_gscan_channel_bucket_t *ch_bucket = NULL;
-	wl_pfn_gscan_cfg_t *pfn_gscan_cfg_t = NULL;
-	wl_pfn_significant_bssid_t *p_pfn_significant_bssid = NULL;
-	wl_pfn_bssid_t *p_pfn_bssid = NULL;
-	wlc_ssid_ext_t *pssid_list = NULL;
-	dhd_pno_params_t	*params_legacy;
-	dhd_pno_params_t	*_params;
-
-	params_legacy = &_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
-	_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	NULL_CHECK(gscan_params, "gscan_params is NULL", err);
-
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	if (!dhd_support_sta_mode(dhd)) {
-		err = BCME_BADOPTION;
-		goto exit;
-	}
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-	if (!validate_gscan_params(gscan_params)) {
-		DHD_ERROR(("%s : Cannot start gscan - bad params\n", __FUNCTION__));
-		err = BCME_BADARG;
-		goto exit;
-	}
-	/* Create channel list based on channel buckets */
-	if (!(ch_bucket = dhd_pno_gscan_create_channel_list(dhd, _pno_state,
-	    _chan_list, &tot_num_buckets, &num_buckets_to_fw))) {
-		goto exit;
-	}
-
-	if (_pno_state->pno_mode & (DHD_PNO_GSCAN_MODE | DHD_PNO_LEGACY_MODE)) {
-		/* store current pno_mode before disabling pno */
-		mode = _pno_state->pno_mode;
-		err = dhd_pno_clean(dhd);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to disable PNO\n", __FUNCTION__));
-			goto exit;
-		}
-		/* restore the previous mode */
-		_pno_state->pno_mode = mode;
-	}
-
-	_pno_state->pno_mode |= DHD_PNO_GSCAN_MODE;
-
-	if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
-		pssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
-
-		if (!pssid_list) {
-			err = BCME_NOMEM;
-			DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
-			goto exit;
-		}
-
-		if ((err = _dhd_pno_add_ssid(dhd, pssid_list,
-			params_legacy->params_legacy.nssid)) < 0) {
-			DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err));
-			goto exit;
-		}
-	}
-
-	if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_GSCAN_MODE)) < 0) {
-		DHD_ERROR(("failed to set call pno_set (err %d) in firmware\n", err));
-		goto exit;
-	}
-
-	gscan_param_size = sizeof(wl_pfn_gscan_cfg_t) +
-	          (num_buckets_to_fw - 1) * sizeof(wl_pfn_gscan_channel_bucket_t);
-	pfn_gscan_cfg_t = (wl_pfn_gscan_cfg_t *) MALLOC(dhd->osh, gscan_param_size);
-
-	if (!pfn_gscan_cfg_t) {
-		DHD_ERROR(("%s: failed to malloc memory of size %d\n",
-		   __FUNCTION__, gscan_param_size));
-		err = BCME_NOMEM;
-		goto exit;
-	}
-
-
-	if (gscan_params->mscan) {
-		pfn_gscan_cfg_t->buffer_threshold = gscan_params->buffer_threshold;
-	} else {
-		pfn_gscan_cfg_t->buffer_threshold = GSCAN_BATCH_NO_THR_SET;
-	}
-	if (gscan_params->nbssid_significant_change) {
-		pfn_gscan_cfg_t->swc_nbssid_threshold = gscan_params->swc_nbssid_threshold;
-		pfn_gscan_cfg_t->swc_rssi_window_size = gscan_params->swc_rssi_window_size;
-		pfn_gscan_cfg_t->lost_ap_window	= gscan_params->lost_ap_window;
-	} else {
-		pfn_gscan_cfg_t->swc_nbssid_threshold = 0;
-		pfn_gscan_cfg_t->swc_rssi_window_size = 0;
-		pfn_gscan_cfg_t->lost_ap_window	= 0;
-	}
-
-	pfn_gscan_cfg_t->flags =
-	         (gscan_params->send_all_results_flag & GSCAN_SEND_ALL_RESULTS_MASK);
-	pfn_gscan_cfg_t->count_of_channel_buckets = num_buckets_to_fw;
-
-
-	for (i = 0, k = 0; i < tot_num_buckets; i++) {
-		if (ch_bucket[i].bucket_end_index  != CHANNEL_BUCKET_EMPTY_INDEX) {
-			pfn_gscan_cfg_t->channel_bucket[k].bucket_end_index =
-			           ch_bucket[i].bucket_end_index;
-			pfn_gscan_cfg_t->channel_bucket[k].bucket_freq_multiple =
-			           ch_bucket[i].bucket_freq_multiple;
-			pfn_gscan_cfg_t->channel_bucket[k].report_flag =
-				ch_bucket[i].report_flag;
-			k++;
-		}
-	}
-
-	tot_nchan = pfn_gscan_cfg_t->channel_bucket[num_buckets_to_fw - 1].bucket_end_index + 1;
-	DHD_PNO(("Total channel num %d total ch_buckets  %d ch_buckets_to_fw %d \n", tot_nchan,
-	      tot_num_buckets, num_buckets_to_fw));
-
-	if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) {
-		DHD_ERROR(("%s : failed to set call pno_cfg (err %d) in firmware\n",
-			__FUNCTION__, err));
-		goto exit;
-	}
-
-	if ((err = _dhd_pno_gscan_cfg(dhd, pfn_gscan_cfg_t, gscan_param_size)) < 0) {
-		DHD_ERROR(("%s : failed to set call pno_gscan_cfg (err %d) in firmware\n",
-			__FUNCTION__, err));
-		goto exit;
-	}
-	if (gscan_params->nbssid_significant_change) {
-		dhd_pno_significant_bssid_t *iter, *next;
-
-
-		p_pfn_significant_bssid = kzalloc(sizeof(wl_pfn_significant_bssid_t) *
-		                   gscan_params->nbssid_significant_change, GFP_KERNEL);
-		if (p_pfn_significant_bssid == NULL) {
-			DHD_ERROR(("%s : failed to allocate memory %zd\n",
-				__FUNCTION__,
-				sizeof(wl_pfn_significant_bssid_t) *
-				gscan_params->nbssid_significant_change));
-			err = BCME_NOMEM;
-			goto exit;
-		}
-		i = 0;
-		/* convert dhd_pno_significant_bssid_t to wl_pfn_significant_bssid_t */
-		list_for_each_entry_safe(iter, next, &gscan_params->significant_bssid_list, list) {
-			p_pfn_significant_bssid[i].rssi_low_threshold = iter->rssi_low_threshold;
-			p_pfn_significant_bssid[i].rssi_high_threshold = iter->rssi_high_threshold;
-			memcpy(&p_pfn_significant_bssid[i].macaddr, &iter->BSSID, ETHER_ADDR_LEN);
-			i++;
-		}
-		DHD_PNO(("nbssid_significant_change %d \n",
-				gscan_params->nbssid_significant_change));
-		err = _dhd_pno_add_significant_bssid(dhd, p_pfn_significant_bssid,
-		                     gscan_params->nbssid_significant_change);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to call _dhd_pno_add_significant_bssid(err :%d)\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-	}
-
-	if (gscan_params->nbssid_hotlist) {
-		struct dhd_pno_bssid *iter, *next;
-		wl_pfn_bssid_t *ptr;
-		p_pfn_bssid = (wl_pfn_bssid_t *)kzalloc(sizeof(wl_pfn_bssid_t) *
-		       gscan_params->nbssid_hotlist, GFP_KERNEL);
-		if (p_pfn_bssid == NULL) {
-			DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array"
-			" (count: %d)",
-				__FUNCTION__, _params->params_hotlist.nbssid));
-			err = BCME_NOMEM;
-			_pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
-			goto exit;
-		}
-		ptr = p_pfn_bssid;
-		/* convert dhd_pno_bssid to wl_pfn_bssid */
-		DHD_PNO(("nhotlist %d\n", gscan_params->nbssid_hotlist));
-		list_for_each_entry_safe(iter, next,
-		          &gscan_params->hotlist_bssid_list, list) {
-			memcpy(&ptr->macaddr,
-			&iter->macaddr, ETHER_ADDR_LEN);
-			ptr->flags = iter->flags;
-			ptr++;
-		}
-
-		err = _dhd_pno_add_bssid(dhd, p_pfn_bssid, gscan_params->nbssid_hotlist);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to call _dhd_pno_add_bssid(err :%d)\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-	}
-
-	if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0) {
-		DHD_ERROR(("%s : failed to enable PNO err %d\n", __FUNCTION__, err));
-	}
-
-exit:
-	/* clear mode in case of error */
-	if (err < 0) {
-		int ret = dhd_pno_clean(dhd);
-
-		if (ret < 0) {
-			DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
-				__FUNCTION__, ret));
-		} else {
-			_pno_state->pno_mode &= ~DHD_PNO_GSCAN_MODE;
-		}
-	}
-	kfree(pssid_list);
-	kfree(p_pfn_significant_bssid);
-	kfree(p_pfn_bssid);
-	if (pfn_gscan_cfg_t) {
-		MFREE(dhd->osh, pfn_gscan_cfg_t, gscan_param_size);
-	}
-	if (ch_bucket) {
-		MFREE(dhd->osh, ch_bucket,
-		(tot_num_buckets * sizeof(wl_pfn_gscan_channel_bucket_t)));
-	}
-	return err;
-
-}
-
-
-static void
-dhd_pno_merge_gscan_pno_channels(dhd_pno_status_info_t *pno_state,
-                                uint16 *chan_list,
-                                uint8 *ch_scratch_pad,
-                                wl_pfn_gscan_channel_bucket_t *ch_bucket,
-                                uint32 *num_buckets_to_fw,
-                                int num_channels)
-{
-	uint16 chan_buf[WL_NUMCHANNELS];
-	int i, j = 0, ch_bucket_idx = 0;
-	dhd_pno_params_t *_params = &pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-	dhd_pno_params_t *_params1 = &pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
-	uint16 *legacy_chan_list = _params1->params_legacy.chan_list;
-	bool is_legacy_scan_freq_higher;
-	uint8 report_flag = CH_BUCKET_REPORT_REGULAR;
-
-	if (!_params1->params_legacy.scan_fr)
-		_params1->params_legacy.scan_fr = PNO_SCAN_MIN_FW_SEC;
-
-	is_legacy_scan_freq_higher =
-	     _params->params_gscan.scan_fr < _params1->params_legacy.scan_fr;
-
-	/* Calculate new Legacy scan multiple of base scan_freq
-	* The legacy PNO channel bucket is added at the end of the
-	* channel bucket list.
-	*/
-	if (is_legacy_scan_freq_higher) {
-		ch_bucket[_params->params_gscan.nchannel_buckets].bucket_freq_multiple =
-		_params1->params_legacy.scan_fr/_params->params_gscan.scan_fr;
-
-	} else {
-		uint16 max = 0;
-
-		/* Calculate new multiple of base scan_freq for gscan buckets */
-		ch_bucket[_params->params_gscan.nchannel_buckets].bucket_freq_multiple = 1;
-		for (i = 0; i < _params->params_gscan.nchannel_buckets; i++) {
-			ch_bucket[i].bucket_freq_multiple *= _params->params_gscan.scan_fr;
-			ch_bucket[i].bucket_freq_multiple /= _params1->params_legacy.scan_fr;
-			if (max < ch_bucket[i].bucket_freq_multiple)
-				max = ch_bucket[i].bucket_freq_multiple;
-		}
-		_params->params_gscan.max_ch_bucket_freq =  max;
-	}
-
-	/* Off to remove duplicates!!
-	 * Find channels that are already being serviced by gscan before legacy bucket
-	 * These have to be removed from legacy bucket.
-	 *  !!Assuming chan_list channels are validated list of channels!!
-	 * ch_scratch_pad is 1 at gscan bucket locations see dhd_pno_gscan_create_channel_list()
-	 */
-	for (i = 0; i < _params1->params_legacy.nchan; i++)
-		ch_scratch_pad[legacy_chan_list[i]] += 2;
-
-	ch_bucket_idx = 0;
-	memcpy(chan_buf, chan_list, num_channels * sizeof(uint16));
-
-	/* Finally create channel list and bucket
-	 * At this point ch_scratch_pad can have 4 values:
-	 * 0 - Channel not present in either Gscan or Legacy PNO bucket
-	 * 1 - Channel present only in Gscan bucket
-	 * 2 - Channel present only in Legacy PNO bucket
-	 * 3 - Channel present in both Gscan and Legacy PNO buckets
-	 * Thus Gscan buckets can have values 1 or 3 and Legacy 2 or 3
-	 * For channel buckets with scan_freq < legacy accept all
-	 * channels i.e. ch_scratch_pad = 1 and 3
-	 * else accept only ch_scratch_pad = 1 and mark rejects as
-	 * ch_scratch_pad = 4 so that they go in legacy
-	 */
-	for (i = 0; i < _params->params_gscan.nchannel_buckets; i++) {
-		if (ch_bucket[i].bucket_freq_multiple <=
-		ch_bucket[_params->params_gscan.nchannel_buckets].bucket_freq_multiple) {
-			for (; ch_bucket_idx <= ch_bucket[i].bucket_end_index; ch_bucket_idx++, j++)
-				chan_list[j] = chan_buf[ch_bucket_idx];
-
-			ch_bucket[i].bucket_end_index = j - 1;
-		} else {
-			num_channels = 0;
-			for (; ch_bucket_idx <= ch_bucket[i].bucket_end_index; ch_bucket_idx++) {
-				if (ch_scratch_pad[chan_buf[ch_bucket_idx]] == 1) {
-					chan_list[j] = chan_buf[ch_bucket_idx];
-					j++;
-					num_channels++;
-				} else {
-					ch_scratch_pad[chan_buf[ch_bucket_idx]] = 4;
-					/* If Gscan channel is merged off to legacy bucket and
-					 * if the gscan channel bucket has a report flag > 0
-					 * use the same for legacy
-					 */
-					if (report_flag < ch_bucket[i].report_flag)
-						report_flag = ch_bucket[i].report_flag;
-				}
-			}
-
-			if (num_channels) {
-				ch_bucket[i].bucket_end_index = j - 1;
-			} else {
-				ch_bucket[i].bucket_end_index = CHANNEL_BUCKET_EMPTY_INDEX;
-				*num_buckets_to_fw = *num_buckets_to_fw - 1;
-			}
-		}
-
-	}
-
-	num_channels = 0;
-	ch_bucket[_params->params_gscan.nchannel_buckets].report_flag = report_flag;
-	/* Now add channels to the legacy scan bucket
-	 * ch_scratch_pad = 0 to 4 at this point, for legacy -> 2,3,4. 2 means exclusively
-	 * Legacy so add to bucket. 4 means it is a reject of gscan bucket and must
-	 * be added to Legacy bucket,reject 3
-	 */
-	for (i = 0; i < _params1->params_legacy.nchan; i++) {
-		if (ch_scratch_pad[legacy_chan_list[i]] != 3) {
-			chan_list[j] = legacy_chan_list[i];
-			j++;
-			num_channels++;
-		}
-	}
-	if (num_channels) {
-		ch_bucket[_params->params_gscan.nchannel_buckets].bucket_end_index = j - 1;
-	}
-	else {
-		ch_bucket[_params->params_gscan.nchannel_buckets].bucket_end_index =
-		            CHANNEL_BUCKET_EMPTY_INDEX;
-		*num_buckets_to_fw = *num_buckets_to_fw - 1;
-	}
-
-	return;
-}
-static wl_pfn_gscan_channel_bucket_t *
-dhd_pno_gscan_create_channel_list(dhd_pub_t *dhd,
-                                  dhd_pno_status_info_t *_pno_state,
-                                  uint16 *chan_list,
-                                  uint32 *num_buckets,
-                                  uint32 *num_buckets_to_fw)
-{
-	int i, num_channels, err, nchan = WL_NUMCHANNELS;
-	uint16 *ptr = chan_list, max;
-	uint8 *ch_scratch_pad;
-	wl_pfn_gscan_channel_bucket_t *ch_bucket;
-	dhd_pno_params_t *_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-	bool is_pno_legacy_running = _pno_state->pno_mode & DHD_PNO_LEGACY_MODE;
-	dhd_pno_gscan_channel_bucket_t *gscan_buckets = _params->params_gscan.channel_bucket;
-
-	if (is_pno_legacy_running)
-		*num_buckets = _params->params_gscan.nchannel_buckets + 1;
-	 else
-		*num_buckets = _params->params_gscan.nchannel_buckets;
-
-
-	*num_buckets_to_fw = *num_buckets;
-
-
-	ch_bucket = (wl_pfn_gscan_channel_bucket_t *) MALLOC(dhd->osh,
-		((*num_buckets) * sizeof(wl_pfn_gscan_channel_bucket_t)));
-
-	if (!ch_bucket) {
-		DHD_ERROR(("%s: failed to malloc memory of size %zd\n",
-			__FUNCTION__, (*num_buckets) * sizeof(wl_pfn_gscan_channel_bucket_t)));
-		*num_buckets_to_fw = *num_buckets = 0;
-		return NULL;
-	}
-
-	max = gscan_buckets[0].bucket_freq_multiple;
-	num_channels = 0;
-	for (i = 0; i < _params->params_gscan.nchannel_buckets; i++) {
-		if (!gscan_buckets[i].band) {
-			num_channels += gscan_buckets[i].num_channels;
-			memcpy(ptr, gscan_buckets[i].chan_list,
-			    gscan_buckets[i].num_channels * sizeof(uint16));
-			ptr = ptr + gscan_buckets[i].num_channels;
-		} else {
-			/* get a valid channel list based on band B or A */
-			err = _dhd_pno_get_channels(dhd, ptr,
-			        &nchan, (gscan_buckets[i].band & GSCAN_ABG_BAND_MASK),
-			        !(gscan_buckets[i].band & GSCAN_DFS_MASK));
-
-			if (err < 0) {
-				DHD_ERROR(("%s: failed to get valid channel list(band : %d)\n",
-					__FUNCTION__, gscan_buckets[i].band));
-				MFREE(dhd->osh, ch_bucket,
-				      ((*num_buckets) * sizeof(wl_pfn_gscan_channel_bucket_t)));
-				*num_buckets_to_fw = *num_buckets = 0;
-				return NULL;
-			}
-
-			num_channels += nchan;
-			ptr = ptr + nchan;
-		}
-
-		ch_bucket[i].bucket_end_index = num_channels - 1;
-		ch_bucket[i].bucket_freq_multiple = gscan_buckets[i].bucket_freq_multiple;
-		ch_bucket[i].report_flag = gscan_buckets[i].report_flag;
-		if (max < gscan_buckets[i].bucket_freq_multiple)
-			max = gscan_buckets[i].bucket_freq_multiple;
-		nchan = WL_NUMCHANNELS - num_channels;
-		DHD_PNO(("end_idx  %d freq_mult - %d\n",
-		ch_bucket[i].bucket_end_index, ch_bucket[i].bucket_freq_multiple));
-	}
-
-	ch_scratch_pad = (uint8 *) kzalloc(CHANNEL_5G_MAX, GFP_KERNEL);
-	if (!ch_scratch_pad) {
-		DHD_ERROR(("%s: failed to malloc memory of size %d\n",
-			__FUNCTION__, CHANNEL_5G_MAX));
-		MFREE(dhd->osh, ch_bucket,
-		      ((*num_buckets) * sizeof(wl_pfn_gscan_channel_bucket_t)));
-		*num_buckets_to_fw = *num_buckets = 0;
-		return NULL;
-	}
-
-	/* Need to look for duplicates in gscan buckets if the framework programmed
-	 * the gscan buckets badly, for now return error if there are duplicates.
-	 * Plus as an added bonus, we get all channels in Gscan bucket
-	 * set to 1 for dhd_pno_merge_gscan_pno_channels()
-	 */
-	for (i = 0; i < num_channels; i++) {
-		if (!ch_scratch_pad[chan_list[i]]) {
-			ch_scratch_pad[chan_list[i]] = 1;
-		} else {
-			DHD_ERROR(("%s: Duplicate channel - %d programmed in channel bucket\n",
-				__FUNCTION__, chan_list[i]));
-			MFREE(dhd->osh, ch_bucket, ((*num_buckets) *
-			     sizeof(wl_pfn_gscan_channel_bucket_t)));
-			*num_buckets_to_fw = *num_buckets = 0;
-			kfree(ch_scratch_pad);
-			return NULL;
-		}
-	}
-	_params->params_gscan.max_ch_bucket_freq = max;
-	/* Legacy PNO maybe running, which means we need to create a legacy PNO bucket
-	 * Plus need to remove duplicates as the legacy PNO chan_list may have common channels
-	 * If channel is to be scanned more frequently as per gscan requirements
-	 * remove from legacy PNO ch_bucket. Similarly, if legacy wants a channel scanned
-	 * more often, it is removed from the Gscan channel bucket.
-	 * In the end both are satisfied.
-	 */
-	if (is_pno_legacy_running)
-		dhd_pno_merge_gscan_pno_channels(_pno_state, chan_list,
-		    ch_scratch_pad, ch_bucket, num_buckets_to_fw, num_channels);
-
-	kfree(ch_scratch_pad);
-	return ch_bucket;
-}
-
-static int
-dhd_pno_stop_for_gscan(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	int mode;
-	wlc_ssid_ext_t *pssid_list = NULL;
-	dhd_pno_status_info_t *_pno_state;
-
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	if (!dhd_support_sta_mode(dhd)) {
-		err = BCME_BADOPTION;
-		goto exit;
-	}
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n",
-			__FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-	if (!(_pno_state->pno_mode & DHD_PNO_GSCAN_MODE)) {
-		DHD_ERROR(("%s : GSCAN is not enabled\n", __FUNCTION__));
-		goto exit;
-	}
-	mutex_lock(&_pno_state->pno_mutex);
-	mode = _pno_state->pno_mode & ~DHD_PNO_GSCAN_MODE;
-	err = dhd_pno_clean(dhd);
-	if (err < 0) {
-
-		DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
-			__FUNCTION__, err));
-		mutex_unlock(&_pno_state->pno_mutex);
-		return err;
-	}
-	_pno_state->pno_mode = mode;
-	mutex_unlock(&_pno_state->pno_mutex);
-
-	/* Reprogram Legacy PNO if it was running */
-	if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
-		struct dhd_pno_legacy_params *params_legacy;
-		uint16 chan_list[WL_NUMCHANNELS];
-
-		params_legacy = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
-		_pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
-		pssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
-		if (!pssid_list) {
-			err = BCME_NOMEM;
-			DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
-			goto exit;
-		}
-
-		DHD_PNO(("Restarting Legacy PNO SSID scan...\n"));
-		memcpy(chan_list, params_legacy->chan_list,
-		    (params_legacy->nchan * sizeof(uint16)));
-		err = dhd_pno_set_for_ssid(dhd, pssid_list, params_legacy->nssid,
-			params_legacy->scan_fr, params_legacy->pno_repeat,
-			params_legacy->pno_freq_expo_max, chan_list,
-			params_legacy->nchan);
-		if (err < 0) {
-			_pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
-			DHD_ERROR(("%s : failed to restart legacy PNO scan(err: %d)\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-
-	}
-
-exit:
-	kfree(pssid_list);
-	return err;
-}
-
-int
-dhd_pno_initiate_gscan_request(dhd_pub_t *dhd, bool run, bool flush)
-{
-	int err = BCME_OK;
-	dhd_pno_params_t *params;
-	dhd_pno_status_info_t *_pno_state;
-	struct dhd_pno_gscan_params *gscan_params;
-
-	NULL_CHECK(dhd, "dhd is NULL\n", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-
-	DHD_PNO(("%s enter - run %d flush %d\n", __FUNCTION__, run, flush));
-	params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-	gscan_params = &params->params_gscan;
-
-	if (run) {
-		err = dhd_pno_set_for_gscan(dhd, gscan_params);
-	} else {
-		if (flush) {
-			mutex_lock(&_pno_state->pno_mutex);
-			dhd_pno_reset_cfg_gscan(params, _pno_state, GSCAN_FLUSH_ALL_CFG);
-			mutex_unlock(&_pno_state->pno_mutex);
-		}
-		/* Need to stop all gscan */
-		err = dhd_pno_stop_for_gscan(dhd);
-	}
-
-	return err;
-}
-
-int
-dhd_pno_enable_full_scan_result(dhd_pub_t *dhd, bool real_time_flag)
-{
-	int err = BCME_OK;
-	dhd_pno_params_t *params;
-	dhd_pno_status_info_t *_pno_state;
-	struct dhd_pno_gscan_params *gscan_params;
-	uint8 old_flag;
-
-	NULL_CHECK(dhd, "dhd is NULL\n", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-	params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-	gscan_params = &params->params_gscan;
-
-	mutex_lock(&_pno_state->pno_mutex);
-
-	old_flag = gscan_params->send_all_results_flag;
-	gscan_params->send_all_results_flag = (uint8) real_time_flag;
-	if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
-	    if (old_flag != gscan_params->send_all_results_flag) {
-			wl_pfn_gscan_cfg_t gscan_cfg;
-			gscan_cfg.flags = (gscan_params->send_all_results_flag &
-				GSCAN_SEND_ALL_RESULTS_MASK);
-			gscan_cfg.flags |= GSCAN_CFG_FLAGS_ONLY_MASK;
-
-			if ((err = _dhd_pno_gscan_cfg(dhd, &gscan_cfg,
-				sizeof(wl_pfn_gscan_cfg_t))) < 0) {
-				DHD_ERROR(("%s : pno_gscan_cfg failed (err %d) in firmware\n",
-					__FUNCTION__, err));
-				goto exit_mutex_unlock;
-			}
-		} else {
-			DHD_PNO(("No change in flag - %d\n", old_flag));
-		}
-	} else {
-		DHD_PNO(("Gscan not started\n"));
-	}
-exit_mutex_unlock:
-	mutex_unlock(&_pno_state->pno_mutex);
-exit:
-	return err;
-}
-
-int dhd_gscan_batch_cache_cleanup(dhd_pub_t *dhd)
-{
-	int ret = 0;
-	dhd_pno_params_t *params;
-	struct dhd_pno_gscan_params *gscan_params;
-	dhd_pno_status_info_t *_pno_state;
-	gscan_results_cache_t *iter, *tmp;
-
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-	gscan_params = &params->params_gscan;
-	iter = gscan_params->gscan_batch_cache;
-
-	while (iter) {
-		if (iter->tot_consumed == iter->tot_count) {
-			tmp = iter->next;
-			kfree(iter);
-			iter = tmp;
-		} else
-			break;
-}
-	gscan_params->gscan_batch_cache = iter;
-	ret = (iter == NULL);
-	return ret;
-}
-
-static int
-_dhd_pno_get_gscan_batch_from_fw(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	uint32 timestamp = 0, ts = 0, i, j, timediff;
-	dhd_pno_params_t *params;
-	dhd_pno_status_info_t *_pno_state;
-	wl_pfn_lnet_info_t *plnetinfo;
-	struct dhd_pno_gscan_params *gscan_params;
-	wl_pfn_lscanresults_t *plbestnet = NULL;
-	gscan_results_cache_t *iter, *tail;
-	wifi_gscan_result_t *result;
-	uint8 *nAPs_per_scan = NULL;
-	uint8 num_scans_in_cur_iter;
-	uint16 count, scan_id = 0;
-
-	NULL_CHECK(dhd, "dhd is NULL\n", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-	gscan_params = &params->params_gscan;
-	nAPs_per_scan = (uint8 *) MALLOC(dhd->osh, gscan_params->mscan);
-
-	if (!nAPs_per_scan) {
-		DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n", __FUNCTION__,
-		gscan_params->mscan));
-		err = BCME_NOMEM;
-		goto exit;
-	}
-
-	plbestnet = (wl_pfn_lscanresults_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN);
-
-	mutex_lock(&_pno_state->pno_mutex);
-	iter = gscan_params->gscan_batch_cache;
-	/* If a cache has not been consumed , just delete it */
-	while (iter) {
-		iter->tot_consumed = iter->tot_count;
-		iter = iter->next;
-	}
-	dhd_gscan_batch_cache_cleanup(dhd);
-
-	if (!(_pno_state->pno_mode & DHD_PNO_GSCAN_MODE)) {
-		DHD_ERROR(("%s : GSCAN is not enabled\n", __FUNCTION__));
-		goto exit_mutex_unlock;
-	}
-
-	timediff = gscan_params->scan_fr * 1000;
-	timediff = timediff >> 1;
-
-	/* Ok, now lets start getting results from the FW */
-	plbestnet->status = PFN_INCOMPLETE;
-	tail = gscan_params->gscan_batch_cache;
-	while (plbestnet->status != PFN_COMPLETE) {
-		memset(plbestnet, 0, PNO_BESTNET_LEN);
-		err = dhd_iovar(dhd, 0, "pfnlbest", (char *)plbestnet, PNO_BESTNET_LEN, 0);
-		if (err < 0) {
-			DHD_ERROR(("%s : Cannot get all the batch results, err :%d\n",
-				__FUNCTION__, err));
-			goto exit_mutex_unlock;
-		}
-		DHD_PNO(("ver %d, status : %d, count %d\n", plbestnet->version,
-			plbestnet->status, plbestnet->count));
-		if (plbestnet->version != PFN_SCANRESULT_VERSION) {
-			err = BCME_VERSION;
-			DHD_ERROR(("bestnet version(%d) is mismatch with Driver version(%d)\n",
-				plbestnet->version, PFN_SCANRESULT_VERSION));
-			goto exit_mutex_unlock;
-		}
-
-		num_scans_in_cur_iter = 0;
-		timestamp = plbestnet->netinfo[0].timestamp;
-		/* find out how many scans' results did we get in this batch of FW results */
-		for (i = 0, count = 0; i < plbestnet->count; i++, count++) {
-			plnetinfo = &plbestnet->netinfo[i];
-			/* Unlikely to happen, but just in case the results from
-			 * FW doesnt make sense..... Assume its part of one single scan
-			 */
-			if (num_scans_in_cur_iter > gscan_params->mscan) {
-				num_scans_in_cur_iter = 0;
-				count = plbestnet->count;
-				break;
-			}
-			if (TIME_DIFF_MS(timestamp, plnetinfo->timestamp) > timediff) {
-				nAPs_per_scan[num_scans_in_cur_iter] = count;
-				count = 0;
-				num_scans_in_cur_iter++;
-			}
-			timestamp = plnetinfo->timestamp;
-		}
-		nAPs_per_scan[num_scans_in_cur_iter] = count;
-		num_scans_in_cur_iter++;
-
-		DHD_PNO(("num_scans_in_cur_iter %d\n", num_scans_in_cur_iter));
-		plnetinfo = &plbestnet->netinfo[0];
-
-		for (i = 0; i < num_scans_in_cur_iter; i++) {
-			iter = (gscan_results_cache_t *)
-			kzalloc(((nAPs_per_scan[i] - 1) * sizeof(wifi_gscan_result_t)) +
-			              sizeof(gscan_results_cache_t), GFP_KERNEL);
-			if (!iter) {
-				DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n",
-				 __FUNCTION__, gscan_params->mscan));
-				err = BCME_NOMEM;
-				goto exit_mutex_unlock;
-			}
-			/* Need this check because the new set of results from FW
-			 * maybe a continuation of previous sets' scan results
-			 */
-			if (TIME_DIFF_MS(ts, plnetinfo->timestamp) > timediff) {
-				iter->scan_id = ++scan_id;
-			} else {
-				iter->scan_id = scan_id;
-			}
-			DHD_PNO(("scan_id %d tot_count %d\n", scan_id, nAPs_per_scan[i]));
-			iter->tot_count = nAPs_per_scan[i];
-			iter->tot_consumed = 0;
-
-			if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) {
-				DHD_PNO(("This scan is aborted\n"));
-				iter->flag = (ENABLE << PNO_STATUS_ABORT);
-			} else if (gscan_params->reason) {
-				iter->flag = (ENABLE << gscan_params->reason);
-			}
-
-			if (!tail) {
-				gscan_params->gscan_batch_cache = iter;
-			} else {
-				tail->next = iter;
-			}
-			tail = iter;
-			iter->next = NULL;
-			for (j = 0; j < nAPs_per_scan[i]; j++, plnetinfo++) {
-				result = &iter->results[j];
-
-				result->channel = wf_channel2mhz(plnetinfo->pfnsubnet.channel,
-					(plnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL?
-					WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
-				result->rssi = (int32) plnetinfo->RSSI;
-				/* Info not available & not expected */
-				result->beacon_period = 0;
-				result->capability = 0;
-				result->ie_length = 0;
-				result->rtt = (uint64) plnetinfo->rtt0;
-				result->rtt_sd = (uint64) plnetinfo->rtt1;
-				result->ts = convert_fw_rel_time_to_systime(plnetinfo->timestamp);
-				ts = plnetinfo->timestamp;
-				if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
-					DHD_ERROR(("%s: Invalid SSID length %d\n",
-					      __FUNCTION__, plnetinfo->pfnsubnet.SSID_len));
-					plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
-				}
-				memcpy(result->ssid, plnetinfo->pfnsubnet.SSID,
-					plnetinfo->pfnsubnet.SSID_len);
-				result->ssid[plnetinfo->pfnsubnet.SSID_len] = '\0';
-				memcpy(&result->macaddr, &plnetinfo->pfnsubnet.BSSID,
-				    ETHER_ADDR_LEN);
-
-				DHD_PNO(("\tSSID : "));
-				DHD_PNO(("\n"));
-					DHD_PNO(("\tBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",
-					result->macaddr.octet[0],
-					result->macaddr.octet[1],
-					result->macaddr.octet[2],
-					result->macaddr.octet[3],
-					result->macaddr.octet[4],
-					result->macaddr.octet[5]));
-				DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n",
-					plnetinfo->pfnsubnet.channel,
-					plnetinfo->RSSI, plnetinfo->timestamp));
-				DHD_PNO(("\tRTT0 : %d, RTT1: %d\n",
-				    plnetinfo->rtt0, plnetinfo->rtt1));
-
-			}
-		}
-	}
-exit_mutex_unlock:
-	mutex_unlock(&_pno_state->pno_mutex);
-exit:
-	params->params_gscan.get_batch_flag = GSCAN_BATCH_RETRIEVAL_COMPLETE;
-	smp_wmb();
-	wake_up_interruptible(&_pno_state->batch_get_wait);
-	if (nAPs_per_scan) {
-		MFREE(dhd->osh, nAPs_per_scan, gscan_params->mscan);
-	}
-	if (plbestnet) {
-		MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN);
-	}
-	DHD_PNO(("Batch retrieval done!\n"));
-	return err;
-}
-#endif /* GSCAN_SUPPORT */
-
-static int
-_dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
-{
-	int err = BCME_OK;
-	int i, j;
-	uint32 timestamp = 0;
-	dhd_pno_params_t *_params = NULL;
-	dhd_pno_status_info_t *_pno_state = NULL;
-	wl_pfn_lscanresults_t *plbestnet = NULL;
-	wl_pfn_lnet_info_t *plnetinfo;
-	dhd_pno_bestnet_entry_t *pbestnet_entry;
-	dhd_pno_best_header_t *pbestnetheader = NULL;
-	dhd_pno_scan_results_t *pscan_results = NULL, *siter, *snext;
-	bool allocate_header = FALSE;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	if (!dhd_support_sta_mode(dhd)) {
-		err = BCME_BADOPTION;
-		goto exit_no_unlock;
-	}
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit_no_unlock;
-	}
-#ifdef GSCAN_SUPPORT
-	if (!(_pno_state->pno_mode & (DHD_PNO_BATCH_MODE | DHD_PNO_GSCAN_MODE))) {
-#else
-	if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
-#endif /* GSCAN_SUPPORT */
-		DHD_ERROR(("%s: Batching SCAN mode is not enabled\n", __FUNCTION__));
-		goto exit_no_unlock;
-	}
-	mutex_lock(&_pno_state->pno_mutex);
-	_params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
-	if (buf && bufsize) {
-		if (!list_empty(&_params->params_batch.get_batch.expired_scan_results_list)) {
-			/* need to check whether we have cashed data or not */
-			DHD_PNO(("%s: have cashed batching data in Driver\n",
-				__FUNCTION__));
-			/* convert to results format */
-			goto convert_format;
-		} else {
-			/* this is a first try to get batching results */
-			if (!list_empty(&_params->params_batch.get_batch.scan_results_list)) {
-				/* move the scan_results_list to expired_scan_results_lists */
-				list_for_each_entry_safe(siter, snext,
-					&_params->params_batch.get_batch.scan_results_list, list) {
-					list_move_tail(&siter->list,
-					&_params->params_batch.get_batch.expired_scan_results_list);
-				}
-				_params->params_batch.get_batch.top_node_cnt = 0;
-				_params->params_batch.get_batch.expired_tot_scan_cnt =
-					_params->params_batch.get_batch.tot_scan_cnt;
-				_params->params_batch.get_batch.tot_scan_cnt = 0;
-				goto convert_format;
-			}
-		}
-	}
-	/* create dhd_pno_scan_results_t whenever we got event WLC_E_PFN_BEST_BATCHING */
-	pscan_results = (dhd_pno_scan_results_t *)MALLOC(dhd->osh, SCAN_RESULTS_SIZE);
-	if (pscan_results == NULL) {
-		err = BCME_NOMEM;
-		DHD_ERROR(("failed to allocate dhd_pno_scan_results_t\n"));
-		goto exit;
-	}
-	pscan_results->bestnetheader = NULL;
-	pscan_results->cnt_header = 0;
-	/* add the element into list unless total node cnt is less than MAX_NODE_ CNT */
-	if (_params->params_batch.get_batch.top_node_cnt < MAX_NODE_CNT) {
-		list_add(&pscan_results->list, &_params->params_batch.get_batch.scan_results_list);
-		_params->params_batch.get_batch.top_node_cnt++;
-	} else {
-		int _removed_scan_cnt;
-		/* remove oldest one and add new one */
-		DHD_PNO(("%s : Remove oldest node and add new one\n", __FUNCTION__));
-		_removed_scan_cnt = _dhd_pno_clear_all_batch_results(dhd,
-			&_params->params_batch.get_batch.scan_results_list, TRUE);
-		_params->params_batch.get_batch.tot_scan_cnt -= _removed_scan_cnt;
-		list_add(&pscan_results->list, &_params->params_batch.get_batch.scan_results_list);
-
-	}
-	plbestnet = (wl_pfn_lscanresults_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN);
-	NULL_CHECK(plbestnet, "failed to allocate buffer for bestnet", err);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	memset(plbestnet, 0, PNO_BESTNET_LEN);
-	while (plbestnet->status != PFN_COMPLETE) {
-		memset(plbestnet, 0, PNO_BESTNET_LEN);
-		err = dhd_iovar(dhd, 0, "pfnlbest", (char *)plbestnet, PNO_BESTNET_LEN, 0);
-		if (err < 0) {
-			if (err == BCME_EPERM) {
-				DHD_ERROR(("we cannot get the batching data "
-					"during scanning in firmware, try again\n,"));
-				msleep(500);
-				continue;
-			} else {
-				DHD_ERROR(("%s : failed to execute pfnlbest (err :%d)\n",
-					__FUNCTION__, err));
-				goto exit;
-			}
-		}
-		DHD_PNO(("ver %d, status : %d, count %d\n", plbestnet->version,
-			plbestnet->status, plbestnet->count));
-		if (plbestnet->version != PFN_SCANRESULT_VERSION) {
-			err = BCME_VERSION;
-			DHD_ERROR(("bestnet version(%d) is mismatch with Driver version(%d)\n",
-				plbestnet->version, PFN_SCANRESULT_VERSION));
-			goto exit;
-		}
-		plnetinfo = plbestnet->netinfo;
-		for (i = 0; i < plbestnet->count; i++) {
-			pbestnet_entry = (dhd_pno_bestnet_entry_t *)
-			MALLOC(dhd->osh, BESTNET_ENTRY_SIZE);
-			if (pbestnet_entry == NULL) {
-				err = BCME_NOMEM;
-				DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n"));
-				goto exit;
-			}
-			memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE);
-			pbestnet_entry->recorded_time = jiffies; /* record the current time */
-			/* create header for the first entry */
-			allocate_header = (i == 0)? TRUE : FALSE;
-			/* check whether the new generation is started or not */
-			if (timestamp && (TIME_DIFF(timestamp, plnetinfo->timestamp)
-				> TIME_MIN_DIFF))
-				allocate_header = TRUE;
-			timestamp = plnetinfo->timestamp;
-			if (allocate_header) {
-				pbestnetheader = (dhd_pno_best_header_t *)
-				MALLOC(dhd->osh, BEST_HEADER_SIZE);
-				if (pbestnetheader == NULL) {
-					err = BCME_NOMEM;
-					if (pbestnet_entry)
-						MFREE(dhd->osh, pbestnet_entry,
-						BESTNET_ENTRY_SIZE);
-					DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n"));
-					goto exit;
-				}
-				/* increase total cnt of bestnet header */
-				pscan_results->cnt_header++;
-				/* need to record the reason to call dhd_pno_get_for_bach */
-				if (reason)
-					pbestnetheader->reason = (ENABLE << reason);
-				memset(pbestnetheader, 0, BEST_HEADER_SIZE);
-				/* initialize the head of linked list */
-				INIT_LIST_HEAD(&(pbestnetheader->entry_list));
-				/* link the pbestnet heaer into existed list */
-				if (pscan_results->bestnetheader == NULL)
-					/* In case of header */
-					pscan_results->bestnetheader = pbestnetheader;
-				else {
-					dhd_pno_best_header_t *head = pscan_results->bestnetheader;
-					pscan_results->bestnetheader = pbestnetheader;
-					pbestnetheader->next = head;
-				}
-			}
-			/* fills the best network info */
-			pbestnet_entry->channel = plnetinfo->pfnsubnet.channel;
-			pbestnet_entry->RSSI = plnetinfo->RSSI;
-			if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) {
-				/* if RSSI is positive value, we assume that
-				 * this scan is aborted by other scan
-				 */
-				DHD_PNO(("This scan is aborted\n"));
-				pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT);
-			}
-			pbestnet_entry->rtt0 = plnetinfo->rtt0;
-			pbestnet_entry->rtt1 = plnetinfo->rtt1;
-			pbestnet_entry->timestamp = plnetinfo->timestamp;
-			if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
-				DHD_ERROR(("%s: Invalid SSID length %d: trimming it to max\n",
-				      __FUNCTION__, plnetinfo->pfnsubnet.SSID_len));
-				plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
-			}
-			pbestnet_entry->SSID_len = plnetinfo->pfnsubnet.SSID_len;
-			memcpy(pbestnet_entry->SSID, plnetinfo->pfnsubnet.SSID,
-				pbestnet_entry->SSID_len);
-			memcpy(&pbestnet_entry->BSSID, &plnetinfo->pfnsubnet.BSSID, ETHER_ADDR_LEN);
-			/* add the element into list */
-			list_add_tail(&pbestnet_entry->list, &pbestnetheader->entry_list);
-			/* increase best entry count */
-			pbestnetheader->tot_cnt++;
-			pbestnetheader->tot_size += BESTNET_ENTRY_SIZE;
-			DHD_PNO(("Header %d\n", pscan_results->cnt_header - 1));
-			DHD_PNO(("\tSSID : "));
-			for (j = 0; j < plnetinfo->pfnsubnet.SSID_len; j++)
-				DHD_PNO(("%c", plnetinfo->pfnsubnet.SSID[j]));
-			DHD_PNO(("\n"));
-			DHD_PNO(("\tBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",
-				plnetinfo->pfnsubnet.BSSID.octet[0],
-				plnetinfo->pfnsubnet.BSSID.octet[1],
-				plnetinfo->pfnsubnet.BSSID.octet[2],
-				plnetinfo->pfnsubnet.BSSID.octet[3],
-				plnetinfo->pfnsubnet.BSSID.octet[4],
-				plnetinfo->pfnsubnet.BSSID.octet[5]));
-			DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n",
-				plnetinfo->pfnsubnet.channel,
-				plnetinfo->RSSI, plnetinfo->timestamp));
-			DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", plnetinfo->rtt0, plnetinfo->rtt1));
-			plnetinfo++;
-		}
-	}
-	if (pscan_results->cnt_header == 0) {
-		/* In case that we didn't get any data from the firmware
-		 * Remove the current scan_result list from get_bach.scan_results_list.
-		 */
-		DHD_PNO(("NO BATCH DATA from Firmware, Delete current SCAN RESULT LIST\n"));
-		list_del(&pscan_results->list);
-		MFREE(dhd->osh, pscan_results, SCAN_RESULTS_SIZE);
-		_params->params_batch.get_batch.top_node_cnt--;
-	}
-	/* increase total scan count using current scan count */
-	_params->params_batch.get_batch.tot_scan_cnt += pscan_results->cnt_header;
-
-	if (buf && bufsize) {
-		/* This is a first try to get batching results */
-		if (!list_empty(&_params->params_batch.get_batch.scan_results_list)) {
-			/* move the scan_results_list to expired_scan_results_lists */
-			list_for_each_entry_safe(siter, snext,
-				&_params->params_batch.get_batch.scan_results_list, list) {
-				list_move_tail(&siter->list,
-					&_params->params_batch.get_batch.expired_scan_results_list);
-			}
-			/* reset gloval values after  moving to expired list */
-			_params->params_batch.get_batch.top_node_cnt = 0;
-			_params->params_batch.get_batch.expired_tot_scan_cnt =
-				_params->params_batch.get_batch.tot_scan_cnt;
-			_params->params_batch.get_batch.tot_scan_cnt = 0;
-		}
-convert_format:
-		err = _dhd_pno_convert_format(dhd, &_params->params_batch, buf, bufsize);
-		if (err < 0) {
-			DHD_ERROR(("failed to convert the data into upper layer format\n"));
-			goto exit;
-		}
-	}
-exit:
-	if (plbestnet)
-		MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN);
-	if (_params) {
-		_params->params_batch.get_batch.buf = NULL;
-		_params->params_batch.get_batch.bufsize = 0;
-		_params->params_batch.get_batch.bytes_written = err;
-	}
-	mutex_unlock(&_pno_state->pno_mutex);
-exit_no_unlock:
-	if (waitqueue_active(&_pno_state->get_batch_done.wait))
-		complete(&_pno_state->get_batch_done);
-	return err;
-}
-static void
-_dhd_pno_get_batch_handler(struct work_struct *work)
-{
-	dhd_pno_status_info_t *_pno_state;
-	dhd_pub_t *dhd;
-	struct dhd_pno_batch_params *params_batch;
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	_pno_state = container_of(work, struct dhd_pno_status_info, work);
-	dhd = _pno_state->dhd;
-	if (dhd == NULL) {
-		DHD_ERROR(("%s : dhd is NULL\n", __FUNCTION__));
-		return;
-	}
-
-#ifdef GSCAN_SUPPORT
-	if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
-		_dhd_pno_get_gscan_batch_from_fw(dhd);
-		return;
-	} else
-#endif /* GSCAN_SUPPORT */
-	{
-		params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
-
-		_dhd_pno_get_for_batch(dhd, params_batch->get_batch.buf,
-			params_batch->get_batch.bufsize, params_batch->get_batch.reason);
-	}
-
-}
-
-int
-dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
-{
-	int err = BCME_OK;
-	char *pbuf = buf;
-	dhd_pno_status_info_t *_pno_state;
-	struct dhd_pno_batch_params *params_batch;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	if (!dhd_support_sta_mode(dhd)) {
-		err = BCME_BADOPTION;
-		goto exit;
-	}
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-	params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
-#ifdef GSCAN_SUPPORT
-	if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
-		struct dhd_pno_gscan_params *gscan_params;
-		gscan_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan;
-		gscan_params->reason = reason;
-		err = dhd_retreive_batch_scan_results(dhd);
-		if (err == BCME_OK) {
-			wait_event_interruptible_timeout(_pno_state->batch_get_wait,
-			     is_batch_retrieval_complete(gscan_params),
-			     msecs_to_jiffies(GSCAN_BATCH_GET_MAX_WAIT));
-		}
-	} else
-#endif
-	{
-		if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
-			DHD_ERROR(("%s: Batching SCAN mode is not enabled\n", __FUNCTION__));
-			memset(pbuf, 0, bufsize);
-			pbuf += sprintf(pbuf, "scancount=%d\n", 0);
-			sprintf(pbuf, "%s", RESULTS_END_MARKER);
-			err = strlen(buf);
-			goto exit;
-		}
-		params_batch->get_batch.buf = buf;
-		params_batch->get_batch.bufsize = bufsize;
-		params_batch->get_batch.reason = reason;
-		params_batch->get_batch.bytes_written = 0;
-		schedule_work(&_pno_state->work);
-		wait_for_completion(&_pno_state->get_batch_done);
-	}
-
-#ifdef GSCAN_SUPPORT
-	if (!(_pno_state->pno_mode & DHD_PNO_GSCAN_MODE))
-#endif
-	err = params_batch->get_batch.bytes_written;
-exit:
-	return err;
-}
-
-int
-dhd_pno_stop_for_batch(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	int mode = 0;
-	int i = 0;
-	dhd_pno_status_info_t *_pno_state;
-	dhd_pno_params_t *_params;
-	wl_pfn_bssid_t *p_pfn_bssid = NULL;
-	wlc_ssid_ext_t *p_ssid_list = NULL;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	if (!dhd_support_sta_mode(dhd)) {
-		err = BCME_BADOPTION;
-		goto exit;
-	}
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n",
-			__FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-#ifdef GSCAN_SUPPORT
-	if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
-		DHD_PNO(("Gscan is ongoing, nothing to stop here\n"));
-		return err;
-	}
-#endif
-
-	if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
-		DHD_ERROR(("%s : PNO BATCH MODE is not enabled\n", __FUNCTION__));
-		goto exit;
-	}
-	_pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
-	if (_pno_state->pno_mode & (DHD_PNO_LEGACY_MODE | DHD_PNO_HOTLIST_MODE)) {
-		mode = _pno_state->pno_mode;
-		dhd_pno_clean(dhd);
-		_pno_state->pno_mode = mode;
-		/* restart Legacy PNO if the Legacy PNO is on */
-		if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
-			struct dhd_pno_legacy_params *_params_legacy;
-			_params_legacy =
-				&(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
-			p_ssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
-			if (!p_ssid_list) {
-				err = BCME_NOMEM;
-				DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
-				goto exit;
-			}
-			err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid,
-				_params_legacy->scan_fr, _params_legacy->pno_repeat,
-				_params_legacy->pno_freq_expo_max, _params_legacy->chan_list,
-				_params_legacy->nchan);
-			if (err < 0) {
-				_pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
-				DHD_ERROR(("%s : failed to restart legacy PNO scan(err: %d)\n",
-					__FUNCTION__, err));
-				goto exit;
-			}
-		} else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) {
-			struct dhd_pno_bssid *iter, *next;
-			_params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]);
-			p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) *
-				_params->params_hotlist.nbssid, GFP_KERNEL);
-			if (p_pfn_bssid == NULL) {
-				DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array"
-					" (count: %d)",
-					__FUNCTION__, _params->params_hotlist.nbssid));
-				err = BCME_ERROR;
-				_pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
-				goto exit;
-			}
-			i = 0;
-			/* convert dhd_pno_bssid to wl_pfn_bssid */
-			list_for_each_entry_safe(iter, next,
-				&_params->params_hotlist.bssid_list, list) {
-				memcpy(&p_pfn_bssid[i].macaddr, &iter->macaddr, ETHER_ADDR_LEN);
-				p_pfn_bssid[i].flags = iter->flags;
-				i++;
-			}
-			err = dhd_pno_set_for_hotlist(dhd, p_pfn_bssid, &_params->params_hotlist);
-			if (err < 0) {
-				_pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
-				DHD_ERROR(("%s : failed to restart hotlist scan(err: %d)\n",
-					__FUNCTION__, err));
-				goto exit;
-			}
-		}
-	} else {
-		err = dhd_pno_clean(dhd);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-	}
-exit:
-	_params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
-	_dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE);
-	kfree(p_ssid_list);
-	kfree(p_pfn_bssid);
-	return err;
-}
-
-int
-dhd_pno_set_for_hotlist(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid,
-	struct dhd_pno_hotlist_params *hotlist_params)
-{
-	int err = BCME_OK;
-	int i;
-	uint16 _chan_list[WL_NUMCHANNELS];
-	int rem_nchan = 0;
-	int tot_nchan = 0;
-	int mode = 0;
-	dhd_pno_params_t *_params;
-	dhd_pno_params_t *_params2;
-	struct dhd_pno_bssid *_pno_bssid;
-	dhd_pno_status_info_t *_pno_state;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	NULL_CHECK(hotlist_params, "hotlist_params is NULL", err);
-	NULL_CHECK(p_pfn_bssid, "p_pfn_bssid is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-
-	if (!dhd_support_sta_mode(dhd)) {
-		err = BCME_BADOPTION;
-		goto exit;
-	}
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-	_params = &_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS];
-	if (!(_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE)) {
-		_pno_state->pno_mode |= DHD_PNO_HOTLIST_MODE;
-		err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_HOTLIST_MODE);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to call _dhd_pno_reinitialize_prof\n",
-				__FUNCTION__));
-			goto exit;
-		}
-	}
-	_params->params_batch.nchan = hotlist_params->nchan;
-	_params->params_batch.scan_fr = hotlist_params->scan_fr;
-	if (hotlist_params->nchan)
-		memcpy(_params->params_hotlist.chan_list, hotlist_params->chan_list,
-			sizeof(_params->params_hotlist.chan_list));
-	memset(_chan_list, 0, sizeof(_chan_list));
-
-	rem_nchan = ARRAYSIZE(hotlist_params->chan_list) - hotlist_params->nchan;
-	if (hotlist_params->band == WLC_BAND_2G || hotlist_params->band == WLC_BAND_5G) {
-		/* get a valid channel list based on band B or A */
-		err = _dhd_pno_get_channels(dhd,
-		&_params->params_hotlist.chan_list[hotlist_params->nchan],
-		&rem_nchan, hotlist_params->band, FALSE);
-		if (err < 0) {
-			DHD_ERROR(("%s: failed to get valid channel list(band : %d)\n",
-				__FUNCTION__, hotlist_params->band));
-			goto exit;
-		}
-		/* now we need to update nchan because rem_chan has valid channel count */
-		_params->params_hotlist.nchan += rem_nchan;
-		/* need to sort channel list */
-		sort(_params->params_hotlist.chan_list, _params->params_hotlist.nchan,
-			sizeof(_params->params_hotlist.chan_list[0]), _dhd_pno_cmpfunc, NULL);
-	}
-#ifdef PNO_DEBUG
-{
-		int i;
-		DHD_PNO(("Channel list : "));
-		for (i = 0; i < _params->params_batch.nchan; i++) {
-			DHD_PNO(("%d ", _params->params_batch.chan_list[i]));
-		}
-		DHD_PNO(("\n"));
-}
-#endif
-	if (_params->params_hotlist.nchan) {
-		/* copy the channel list into local array */
-		memcpy(_chan_list, _params->params_hotlist.chan_list,
-			sizeof(_chan_list));
-		tot_nchan = _params->params_hotlist.nchan;
-	}
-	if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
-			DHD_PNO(("PNO SSID is on progress in firmware\n"));
-			/* store current pno_mode before disabling pno */
-			mode = _pno_state->pno_mode;
-			err = _dhd_pno_enable(dhd, PNO_OFF);
-			if (err < 0) {
-				DHD_ERROR(("%s : failed to disable PNO\n", __FUNCTION__));
-				goto exit;
-			}
-			/* restore the previous mode */
-			_pno_state->pno_mode = mode;
-			/* Use the superset for channelist between two mode */
-			_params2 = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
-			if (_params2->params_legacy.nchan > 0 &&
-				_params->params_hotlist.nchan > 0) {
-				err = _dhd_pno_chan_merge(_chan_list, &tot_nchan,
-					&_params2->params_legacy.chan_list[0],
-					_params2->params_legacy.nchan,
-					&_params->params_hotlist.chan_list[0],
-					_params->params_hotlist.nchan);
-				if (err < 0) {
-					DHD_ERROR(("%s : failed to merge channel list"
-						"between legacy and hotlist\n",
-						__FUNCTION__));
-					goto exit;
-				}
-			}
-
-	}
-
-	INIT_LIST_HEAD(&(_params->params_hotlist.bssid_list));
-
-	err = _dhd_pno_add_bssid(dhd, p_pfn_bssid, hotlist_params->nbssid);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to call _dhd_pno_add_bssid(err :%d)\n",
-			__FUNCTION__, err));
-		goto exit;
-	}
-	if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_HOTLIST_MODE)) < 0) {
-		DHD_ERROR(("%s : failed to set call pno_set (err %d) in firmware\n",
-			__FUNCTION__, err));
-		goto exit;
-	}
-	if (tot_nchan > 0) {
-		if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) {
-			DHD_ERROR(("%s : failed to set call pno_cfg (err %d) in firmware\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-	}
-	for (i = 0; i < hotlist_params->nbssid; i++) {
-		_pno_bssid = kzalloc(sizeof(struct dhd_pno_bssid), GFP_KERNEL);
-		NULL_CHECK(_pno_bssid, "_pfn_bssid is NULL", err);
-		memcpy(&_pno_bssid->macaddr, &p_pfn_bssid[i].macaddr, ETHER_ADDR_LEN);
-		_pno_bssid->flags = p_pfn_bssid[i].flags;
-		list_add_tail(&_pno_bssid->list, &_params->params_hotlist.bssid_list);
-	}
-	_params->params_hotlist.nbssid = hotlist_params->nbssid;
-	if (_pno_state->pno_status == DHD_PNO_DISABLED) {
-		if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0)
-			DHD_ERROR(("%s : failed to enable PNO\n", __FUNCTION__));
-	}
-exit:
-	/* clear mode in case of error */
-	if (err < 0)
-		_pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE;
-	return err;
-}
-
-int
-dhd_pno_stop_for_hotlist(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	uint32 mode = 0;
-	dhd_pno_status_info_t *_pno_state;
-	dhd_pno_params_t *_params;
-	wlc_ssid_ext_t *p_ssid_list = NULL;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n",
-			__FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-	if (!(_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE)) {
-		DHD_ERROR(("%s : Hotlist MODE is not enabled\n",
-			__FUNCTION__));
-		goto exit;
-	}
-	_pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
-
-	if (_pno_state->pno_mode & (DHD_PNO_LEGACY_MODE | DHD_PNO_BATCH_MODE)) {
-		/* retrieve the batching data from firmware into host */
-		dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
-		/* save current pno_mode before calling dhd_pno_clean */
-		mode = _pno_state->pno_mode;
-		err = dhd_pno_clean(dhd);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-		/* restore previos pno mode */
-		_pno_state->pno_mode = mode;
-		if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
-			/* restart Legacy PNO Scan */
-			struct dhd_pno_legacy_params *_params_legacy;
-			_params_legacy =
-			&(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
-			p_ssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
-			if (!p_ssid_list) {
-				err = BCME_NOMEM;
-				DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
-				goto exit;
-			}
-			err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid,
-				_params_legacy->scan_fr, _params_legacy->pno_repeat,
-				_params_legacy->pno_freq_expo_max, _params_legacy->chan_list,
-				_params_legacy->nchan);
-			if (err < 0) {
-				_pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
-				DHD_ERROR(("%s : failed to restart legacy PNO scan(err: %d)\n",
-					__FUNCTION__, err));
-				goto exit;
-			}
-		} else if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
-			/* restart Batching Scan */
-			_params = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]);
-			/* restart BATCH SCAN */
-			err = dhd_pno_set_for_batch(dhd, &_params->params_batch);
-			if (err < 0) {
-				_pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
-				DHD_ERROR(("%s : failed to restart batch scan(err: %d)\n",
-					__FUNCTION__,  err));
-				goto exit;
-			}
-		}
-	} else {
-		err = dhd_pno_clean(dhd);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
-				__FUNCTION__, err));
-			goto exit;
-		}
-	}
-exit:
-	kfree(p_ssid_list);
-	return err;
-}
-
-#ifdef GSCAN_SUPPORT
-int
-dhd_retreive_batch_scan_results(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	dhd_pno_status_info_t *_pno_state;
-	dhd_pno_params_t *_params;
-	struct dhd_pno_batch_params *params_batch;
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-
-	params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
-	if (_params->params_gscan.get_batch_flag == GSCAN_BATCH_RETRIEVAL_COMPLETE) {
-		DHD_PNO(("Retreive batch results\n"));
-		params_batch->get_batch.buf = NULL;
-		params_batch->get_batch.bufsize = 0;
-		params_batch->get_batch.reason = PNO_STATUS_EVENT;
-		_params->params_gscan.get_batch_flag = GSCAN_BATCH_RETRIEVAL_IN_PROGRESS;
-		schedule_work(&_pno_state->work);
-	} else {
-		DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING retrieval"
-			"already in progress, will skip\n", __FUNCTION__));
-		err = BCME_ERROR;
-	}
-
-	return err;
-}
-
-/* Handle Significant WiFi Change (SWC) event from FW
- * Send event to HAL when all results arrive from FW
- */
-void *
-dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_bytes)
-{
-	void *ptr = NULL;
-	dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
-	struct dhd_pno_gscan_params *gscan_params;
-	struct dhd_pno_swc_evt_param *params;
-	wl_pfn_swc_results_t *results = (wl_pfn_swc_results_t *)event_data;
-	wl_pfn_significant_net_t *change_array;
-	int i;
-
-
-	gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan);
-	params = &(gscan_params->param_significant);
-
-	if (!results->total_count) {
-		*send_evt_bytes = 0;
-		return ptr;
-	}
-
-	if (!params->results_rxed_so_far) {
-		if (!params->change_array) {
-			params->change_array = (wl_pfn_significant_net_t *)
-			kmalloc(sizeof(wl_pfn_significant_net_t) * results->total_count,
-			GFP_KERNEL);
-
-			if (!params->change_array) {
-				DHD_ERROR(("%s Cannot Malloc %zd bytes!!\n", __FUNCTION__,
-				sizeof(wl_pfn_significant_net_t) * results->total_count));
-				*send_evt_bytes = 0;
-				return ptr;
-			}
-		} else {
-			DHD_ERROR(("RX'ed WLC_E_PFN_SWC evt from FW, previous evt not complete!!"));
-			*send_evt_bytes = 0;
-			return ptr;
-		}
-
-	}
-
-	DHD_PNO(("%s: pkt_count %d total_count %d\n", __FUNCTION__,
-	results->pkt_count, results->total_count));
-
-	for (i = 0; i < results->pkt_count; i++) {
-		DHD_PNO(("\t %02x:%02x:%02x:%02x:%02x:%02x\n",
-		results->list[i].BSSID.octet[0],
-		results->list[i].BSSID.octet[1],
-		results->list[i].BSSID.octet[2],
-		results->list[i].BSSID.octet[3],
-		results->list[i].BSSID.octet[4],
-		results->list[i].BSSID.octet[5]));
-	}
-
-	change_array = &params->change_array[params->results_rxed_so_far];
-	memcpy(change_array, results->list, sizeof(wl_pfn_significant_net_t) * results->pkt_count);
-	params->results_rxed_so_far += results->pkt_count;
-
-	if (params->results_rxed_so_far == results->total_count) {
-		params->results_rxed_so_far = 0;
-		*send_evt_bytes = sizeof(wl_pfn_significant_net_t) * results->total_count;
-		/* Pack up change buffer to send up and reset
-		 * results_rxed_so_far, after its done.
-		 */
-		ptr = (void *) params->change_array;
-		/* expecting the callee to free this mem chunk */
-		params->change_array = NULL;
-	}
-	 else {
-		*send_evt_bytes = 0;
-	}
-
-	return ptr;
-}
-
-void
-dhd_gscan_hotlist_cache_cleanup(dhd_pub_t *dhd, hotlist_type_t type)
-{
-	dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
-	struct dhd_pno_gscan_params *gscan_params;
-	gscan_results_cache_t *iter, *tmp;
-
-	if (!_pno_state) {
-		return;
-	}
-	gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan);
-
-	if (type == HOTLIST_FOUND) {
-		iter = gscan_params->gscan_hotlist_found;
-		gscan_params->gscan_hotlist_found = NULL;
-	} else {
-		iter = gscan_params->gscan_hotlist_lost;
-		gscan_params->gscan_hotlist_lost = NULL;
-	}
-
-	while (iter) {
-		tmp = iter->next;
-		kfree(iter);
-		iter = tmp;
-	}
-
-	return;
-}
-
-void *
-dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, int *size)
-{
-	wl_bss_info_t *bi = NULL;
-	wl_gscan_result_t *gscan_result;
-	wifi_gscan_result_t *result = NULL;
-	u32 bi_length = 0;
-	uint8 channel;
-	uint32 mem_needed;
-
-	struct timespec ts;
-
-	*size = 0;
-
-	gscan_result = (wl_gscan_result_t *)data;
-
-	if (!gscan_result) {
-		DHD_ERROR(("Invalid gscan result (NULL pointer)\n"));
-		goto exit;
-	}
-	if (!gscan_result->bss_info) {
-		DHD_ERROR(("Invalid gscan bss info (NULL pointer)\n"));
-		goto exit;
-	}
-	bi = &gscan_result->bss_info[0].info;
-	bi_length = dtoh32(bi->length);
-	if (bi_length != (dtoh32(gscan_result->buflen) -
-		WL_GSCAN_RESULTS_FIXED_SIZE - WL_GSCAN_INFO_FIXED_FIELD_SIZE)) {
-		DHD_ERROR(("Invalid bss_info length %d: ignoring\n", bi_length));
-		goto exit;
-	}
-	if (bi->SSID_len > DOT11_MAX_SSID_LEN) {
-		DHD_ERROR(("Invalid SSID length %d: trimming it to max\n", bi->SSID_len));
-		bi->SSID_len = DOT11_MAX_SSID_LEN;
-	}
-
-	mem_needed = OFFSETOF(wifi_gscan_result_t, ie_data) + bi->ie_length;
-	result = kmalloc(mem_needed, GFP_KERNEL);
-
-	if (!result) {
-		DHD_ERROR(("%s Cannot malloc scan result buffer %d bytes\n",
-		 __FUNCTION__, mem_needed));
-		goto exit;
-	}
-
-	memcpy(result->ssid, bi->SSID, bi->SSID_len);
-	result->ssid[bi->SSID_len] = '\0';
-	channel = wf_chspec_ctlchan(bi->chanspec);
-	result->channel = wf_channel2mhz(channel,
-		(channel <= CH_MAX_2G_CHANNEL?
-		WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
-	result->rssi = (int32) bi->RSSI;
-	result->rtt = 0;
-	result->rtt_sd = 0;
-	get_monotonic_boottime(&ts);
-	result->ts = (uint64) TIMESPEC_TO_US(ts);
-	result->beacon_period = dtoh16(bi->beacon_period);
-	result->capability = dtoh16(bi->capability);
-	result->ie_length = dtoh32(bi->ie_length);
-	memcpy(&result->macaddr, &bi->BSSID, ETHER_ADDR_LEN);
-	memcpy(result->ie_data, ((uint8 *)bi + bi->ie_offset), bi->ie_length);
-	*size = mem_needed;
-exit:
-	return result;
-}
-
-void *
-dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data,
-        int *send_evt_bytes, hotlist_type_t type)
-{
-	void *ptr = NULL;
-	dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
-	struct dhd_pno_gscan_params *gscan_params;
-	wl_pfn_scanresults_t *results = (wl_pfn_scanresults_t *)event_data;
-	wifi_gscan_result_t *hotlist_found_array;
-	wl_pfn_net_info_t *plnetinfo;
-	gscan_results_cache_t *gscan_hotlist_cache;
-	int malloc_size = 0, i, total = 0;
-
-	gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan);
-
-	if (!results->count) {
-		*send_evt_bytes = 0;
-		return ptr;
-	}
-
-	malloc_size = sizeof(gscan_results_cache_t) +
-	((results->count - 1) * sizeof(wifi_gscan_result_t));
-	gscan_hotlist_cache = (gscan_results_cache_t *) kmalloc(malloc_size, GFP_KERNEL);
-
-	if (!gscan_hotlist_cache) {
-		DHD_ERROR(("%s Cannot Malloc %d bytes!!\n", __FUNCTION__, malloc_size));
-		*send_evt_bytes = 0;
-		return ptr;
-	}
-
-	if (type == HOTLIST_FOUND) {
-		gscan_hotlist_cache->next = gscan_params->gscan_hotlist_found;
-		gscan_params->gscan_hotlist_found = gscan_hotlist_cache;
-		DHD_PNO(("%s enter, FOUND results count %d\n", __FUNCTION__, results->count));
-	} else {
-		gscan_hotlist_cache->next = gscan_params->gscan_hotlist_lost;
-		gscan_params->gscan_hotlist_lost = gscan_hotlist_cache;
-		DHD_PNO(("%s enter, LOST results count %d\n", __FUNCTION__, results->count));
-	}
-
-	gscan_hotlist_cache->tot_count = results->count;
-	gscan_hotlist_cache->tot_consumed = 0;
-	plnetinfo = results->netinfo;
-
-	for (i = 0; i < results->count; i++, plnetinfo++) {
-		hotlist_found_array = &gscan_hotlist_cache->results[i];
-		hotlist_found_array->channel = wf_channel2mhz(plnetinfo->pfnsubnet.channel,
-			(plnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL?
-			WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G));
-		hotlist_found_array->rssi = (int32) plnetinfo->RSSI;
-		/* Info not available & not expected */
-		hotlist_found_array->beacon_period = 0;
-		hotlist_found_array->capability = 0;
-		hotlist_found_array->ie_length = 0;
-
-		hotlist_found_array->ts = convert_fw_rel_time_to_systime(plnetinfo->timestamp);
-		if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
-			DHD_ERROR(("Invalid SSID length %d: trimming it to max\n",
-			          plnetinfo->pfnsubnet.SSID_len));
-			plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
-		}
-		memcpy(hotlist_found_array->ssid, plnetinfo->pfnsubnet.SSID,
-			plnetinfo->pfnsubnet.SSID_len);
-		hotlist_found_array->ssid[plnetinfo->pfnsubnet.SSID_len] = '\0';
-
-		memcpy(&hotlist_found_array->macaddr, &plnetinfo->pfnsubnet.BSSID, ETHER_ADDR_LEN);
-	DHD_PNO(("\t%s %02x:%02x:%02x:%02x:%02x:%02x rssi %d\n", hotlist_found_array->ssid,
-		hotlist_found_array->macaddr.octet[0],
-		hotlist_found_array->macaddr.octet[1],
-		hotlist_found_array->macaddr.octet[2],
-		hotlist_found_array->macaddr.octet[3],
-		hotlist_found_array->macaddr.octet[4],
-		hotlist_found_array->macaddr.octet[5],
-		hotlist_found_array->rssi));
-	}
-
-
-	if (results->status == PFN_COMPLETE) {
-		ptr = (void *) gscan_hotlist_cache;
-		while (gscan_hotlist_cache) {
-			total += gscan_hotlist_cache->tot_count;
-			gscan_hotlist_cache = gscan_hotlist_cache->next;
-		}
-		*send_evt_bytes =  total * sizeof(wifi_gscan_result_t);
-	}
-
-	return ptr;
-}
-#endif /* GSCAN_SUPPORT */
-int
-dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data)
-{
-	int err = BCME_OK;
-	uint status, event_type, flags, datalen;
-	dhd_pno_status_info_t *_pno_state;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	if (!WLS_SUPPORTED(_pno_state)) {
-		DHD_ERROR(("%s : wifi location service is not supported\n", __FUNCTION__));
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-	event_type = ntoh32(event->event_type);
-	flags = ntoh16(event->flags);
-	status = ntoh32(event->status);
-	datalen = ntoh32(event->datalen);
-	DHD_PNO(("%s enter : event_type :%d\n", __FUNCTION__, event_type));
-	switch (event_type) {
-	case WLC_E_PFN_BSSID_NET_FOUND:
-	case WLC_E_PFN_BSSID_NET_LOST:
-		/* TODO : need to implement event logic using generic netlink */
-		break;
-	case WLC_E_PFN_BEST_BATCHING:
-#ifndef GSCAN_SUPPORT
-	{
-		struct dhd_pno_batch_params *params_batch;
-		params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
-		if (!waitqueue_active(&_pno_state->get_batch_done.wait)) {
-			DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING\n", __FUNCTION__));
-			params_batch->get_batch.buf = NULL;
-			params_batch->get_batch.bufsize = 0;
-			params_batch->get_batch.reason = PNO_STATUS_EVENT;
-			schedule_work(&_pno_state->work);
-		} else
-			DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING"
-				"will skip this event\n", __FUNCTION__));
-		break;
-	}
-#else
-		break;
-#endif /* !GSCAN_SUPPORT */
-	default:
-		DHD_ERROR(("unknown event : %d\n", event_type));
-	}
-exit:
-	return err;
-}
-
-int dhd_pno_init(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	dhd_pno_status_info_t *_pno_state;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	UNUSED_PARAMETER(_dhd_pno_suspend);
-	if (dhd->pno_state)
-		goto exit;
-	dhd->pno_state = MALLOC(dhd->osh, sizeof(dhd_pno_status_info_t));
-	NULL_CHECK(dhd->pno_state, "failed to create dhd_pno_state", err);
-	memset(dhd->pno_state, 0, sizeof(dhd_pno_status_info_t));
-	/* need to check whether current firmware support batching and hotlist scan */
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	_pno_state->wls_supported = TRUE;
-	_pno_state->dhd = dhd;
-	mutex_init(&_pno_state->pno_mutex);
-	INIT_WORK(&_pno_state->work, _dhd_pno_get_batch_handler);
-	init_completion(&_pno_state->get_batch_done);
-#ifdef GSCAN_SUPPORT
-	init_waitqueue_head(&_pno_state->batch_get_wait);
-#endif /* GSCAN_SUPPORT */
-	err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, 0);
-	if (err == BCME_UNSUPPORTED) {
-		_pno_state->wls_supported = FALSE;
-		DHD_INFO(("Current firmware doesn't support"
-			" Android Location Service\n"));
-	} else {
-		DHD_ERROR(("%s: Support Android Location Service\n",
-			__FUNCTION__));
-	}
-exit:
-	return err;
-}
-
-int dhd_pno_deinit(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	dhd_pno_status_info_t *_pno_state;
-	dhd_pno_params_t *_params;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-
-	DHD_PNO(("%s enter\n", __FUNCTION__));
-	_pno_state = PNO_GET_PNOSTATE(dhd);
-	NULL_CHECK(_pno_state, "pno_state is NULL", err);
-	/* may need to free legacy ssid_list */
-	if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
-		_params = &_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
-		_dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
-	}
-
-#ifdef GSCAN_SUPPORT
-	if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) {
-		_params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS];
-		mutex_lock(&_pno_state->pno_mutex);
-		dhd_pno_reset_cfg_gscan(_params, _pno_state, GSCAN_FLUSH_ALL_CFG);
-		mutex_unlock(&_pno_state->pno_mutex);
-	}
-#endif /* GSCAN_SUPPORT */
-
-	if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
-		_params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
-		/* clear resource if the BATCH MODE is on */
-		_dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE);
-	}
-	cancel_work_sync(&_pno_state->work);
-	MFREE(dhd->osh, _pno_state, sizeof(dhd_pno_status_info_t));
-	dhd->pno_state = NULL;
-	return err;
-}
-#endif /* PNO_SUPPORT */
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.h b/drivers/net/wireless/bcmdhd/dhd_pno.h
deleted file mode 100644
index 990ec6c..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_pno.h
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Header file of Broadcom Dongle Host Driver (DHD)
- * Prefered Network Offload code and Wi-Fi Location Service(WLS) code.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_pno.h 591285 2015-10-07 11:56:29Z $
- */
-
-#ifndef __DHD_PNO_H__
-#define __DHD_PNO_H__
-
-#if defined(PNO_SUPPORT)
-#define PNO_TLV_PREFIX			'S'
-#define PNO_TLV_VERSION			'1'
-#define PNO_TLV_SUBTYPE_LEGACY_PNO '2'
-#define PNO_TLV_RESERVED		'0'
-#define PNO_BATCHING_SET "SET"
-#define PNO_BATCHING_GET "GET"
-#define PNO_BATCHING_STOP "STOP"
-#define PNO_PARAMS_DELIMETER " "
-#define PNO_PARAM_CHANNEL_DELIMETER ","
-#define PNO_PARAM_VALUE_DELLIMETER '='
-#define PNO_PARAM_SCANFREQ "SCANFREQ"
-#define PNO_PARAM_BESTN	"BESTN"
-#define PNO_PARAM_MSCAN "MSCAN"
-#define PNO_PARAM_CHANNEL "CHANNEL"
-#define PNO_PARAM_RTT "RTT"
-
-#define PNO_TLV_TYPE_SSID_IE		'S'
-#define PNO_TLV_TYPE_TIME		'T'
-#define PNO_TLV_FREQ_REPEAT		'R'
-#define PNO_TLV_FREQ_EXPO_MAX		'M'
-
-#define MAXNUM_SSID_PER_ADD	16
-#define MAXNUM_PNO_PARAMS 2
-#define PNO_TLV_COMMON_LENGTH	1
-#define DEFAULT_BATCH_MSCAN 16
-
-#define RESULTS_END_MARKER "----\n"
-#define SCAN_END_MARKER "####\n"
-#define AP_END_MARKER "====\n"
-#define PNO_RSSI_MARGIN_DBM          30
-
-#ifdef GSCAN_SUPPORT
-
-#define GSCAN_MAX_CH_BUCKETS         8
-#define GSCAN_BG_BAND_MASK             (1 << 0)
-#define GSCAN_A_BAND_MASK              (1 << 1)
-#define GSCAN_DFS_MASK                 (1 << 2)
-#define GSCAN_ABG_BAND_MASK            (GSCAN_A_BAND_MASK | GSCAN_BG_BAND_MASK)
-#define GSCAN_BAND_MASK                (GSCAN_ABG_BAND_MASK | GSCAN_DFS_MASK)
-
-#define GSCAN_FLUSH_HOTLIST_CFG      (1 << 0)
-#define GSCAN_FLUSH_SIGNIFICANT_CFG  (1 << 1)
-#define GSCAN_FLUSH_SCAN_CFG         (1 << 2)
-#define GSCAN_FLUSH_ALL_CFG     (GSCAN_FLUSH_SCAN_CFG | \
-								GSCAN_FLUSH_SIGNIFICANT_CFG | \
-								GSCAN_FLUSH_HOTLIST_CFG)
-/* Do not change GSCAN_BATCH_RETRIEVAL_COMPLETE */
-#define GSCAN_BATCH_RETRIEVAL_COMPLETE      0
-#define GSCAN_BATCH_RETRIEVAL_IN_PROGRESS   1
-#define GSCAN_BATCH_NO_THR_SET              101
-#define GSCAN_LOST_AP_WINDOW_DEFAULT        4
-#define GSCAN_MIN_BSSID_TIMEOUT             90
-#define GSCAN_BATCH_GET_MAX_WAIT            500
-#define CHANNEL_BUCKET_EMPTY_INDEX                      0xFFFF
-#define GSCAN_RETRY_THRESHOLD              3
-#endif /* GSCAN_SUPPORT */
-
-enum scan_status {
-	/* SCAN ABORT by other scan */
-	PNO_STATUS_ABORT,
-	/* RTT is presence or not */
-	PNO_STATUS_RTT_PRESENCE,
-	/* Disable PNO by Driver */
-	PNO_STATUS_DISABLE,
-	/* NORMAL BATCHING GET */
-	PNO_STATUS_NORMAL,
-	/* WLC_E_PFN_BEST_BATCHING */
-	PNO_STATUS_EVENT,
-	PNO_STATUS_MAX
-};
-#define PNO_STATUS_ABORT_MASK 0x0001
-#define PNO_STATUS_RTT_MASK 0x0002
-#define PNO_STATUS_DISABLE_MASK 0x0004
-#define PNO_STATUS_OOM_MASK 0x0010
-
-enum index_mode {
-	INDEX_OF_LEGACY_PARAMS,
-	INDEX_OF_BATCH_PARAMS,
-	INDEX_OF_HOTLIST_PARAMS,
-	/* GSCAN includes hotlist scan and they do not run
-	 * independent of each other
-	 */
-#ifdef GSCAN_SUPPORT
-	INDEX_OF_GSCAN_PARAMS = INDEX_OF_HOTLIST_PARAMS,
-#endif /* GSCAN_SUPPORT */
-	INDEX_MODE_MAX
-};
-enum dhd_pno_status {
-	DHD_PNO_DISABLED,
-	DHD_PNO_ENABLED,
-	DHD_PNO_SUSPEND
-};
-typedef struct cmd_tlv {
-	char prefix;
-	char version;
-	char subtype;
-	char reserved;
-} cmd_tlv_t;
-#ifdef GSCAN_SUPPORT
-typedef enum {
-    WIFI_BAND_UNSPECIFIED,
-    WIFI_BAND_BG = 1,                       /* 2.4 GHz                   */
-    WIFI_BAND_A = 2,                        /* 5 GHz without DFS         */
-    WIFI_BAND_A_DFS = 4,                    /* 5 GHz DFS only            */
-    WIFI_BAND_A_WITH_DFS = 6,               /* 5 GHz with DFS            */
-    WIFI_BAND_ABG = 3,                      /* 2.4 GHz + 5 GHz; no DFS   */
-    WIFI_BAND_ABG_WITH_DFS = 7,             /* 2.4 GHz + 5 GHz with DFS  */
-} gscan_wifi_band_t;
-
-typedef enum {
-	HOTLIST_LOST,
-	HOTLIST_FOUND
-} hotlist_type_t;
-
-typedef enum dhd_pno_gscan_cmd_cfg {
-	DHD_PNO_BATCH_SCAN_CFG_ID,
-	DHD_PNO_GEOFENCE_SCAN_CFG_ID,
-	DHD_PNO_SIGNIFICANT_SCAN_CFG_ID,
-	DHD_PNO_SCAN_CFG_ID,
-	DHD_PNO_GET_CAPABILITIES,
-	DHD_PNO_GET_BATCH_RESULTS,
-	DHD_PNO_GET_CHANNEL_LIST
-} dhd_pno_gscan_cmd_cfg_t;
-
-typedef enum dhd_pno_mode {
-	/* Wi-Fi Legacy PNO Mode */
-	DHD_PNO_NONE_MODE   = 0,
-	DHD_PNO_LEGACY_MODE = (1 << (0)),
-	/* Wi-Fi Android BATCH SCAN Mode */
-	DHD_PNO_BATCH_MODE = (1 << (1)),
-	/* Wi-Fi Android Hotlist SCAN Mode */
-	DHD_PNO_HOTLIST_MODE = (1 << (2)),
-	/* Wi-Fi Google Android SCAN Mode */
-	DHD_PNO_GSCAN_MODE = (1 << (3))
-} dhd_pno_mode_t;
-#else
-typedef enum dhd_pno_mode {
-	/* Wi-Fi Legacy PNO Mode */
-	DHD_PNO_NONE_MODE   = 0,
-	DHD_PNO_LEGACY_MODE = (1 << (0)),
-	/* Wi-Fi Android BATCH SCAN Mode */
-	DHD_PNO_BATCH_MODE = (1 << (1)),
-	/* Wi-Fi Android Hotlist SCAN Mode */
-	DHD_PNO_HOTLIST_MODE = (1 << (2))
-} dhd_pno_mode_t;
-#endif /* GSCAN_SUPPORT */
-struct dhd_pno_ssid {
-	bool		hidden;
-	uint32		SSID_len;
-	uchar		SSID[DOT11_MAX_SSID_LEN];
-	struct list_head list;
-};
-struct dhd_pno_bssid {
-	struct ether_addr	macaddr;
-	/* Bit4: suppress_lost, Bit3: suppress_found */
-	uint16			flags;
-	struct list_head list;
-};
-typedef struct dhd_pno_bestnet_entry {
-	struct ether_addr BSSID;
-	uint8	SSID_len;
-	uint8	SSID[DOT11_MAX_SSID_LEN];
-	int8	RSSI;
-	uint8	channel;
-	uint32	timestamp;
-	uint16	rtt0; /* distance_cm based on RTT */
-	uint16	rtt1; /* distance_cm based on sample standard deviation */
-	unsigned long recorded_time;
-	struct list_head list;
-} dhd_pno_bestnet_entry_t;
-#define BESTNET_ENTRY_SIZE (sizeof(dhd_pno_bestnet_entry_t))
-
-typedef struct dhd_pno_bestnet_header {
-	struct dhd_pno_bestnet_header *next;
-	uint8 reason;
-	uint32 tot_cnt;
-	uint32 tot_size;
-	struct list_head entry_list;
-} dhd_pno_best_header_t;
-#define BEST_HEADER_SIZE (sizeof(dhd_pno_best_header_t))
-
-typedef struct dhd_pno_scan_results {
-	dhd_pno_best_header_t *bestnetheader;
-	uint8 cnt_header;
-	struct list_head list;
-} dhd_pno_scan_results_t;
-#define SCAN_RESULTS_SIZE (sizeof(dhd_pno_scan_results_t))
-
-struct dhd_pno_get_batch_info {
-	/* info related to get batch */
-	char *buf;
-	bool batch_started;
-	uint32 tot_scan_cnt;
-	uint32 expired_tot_scan_cnt;
-	uint32 top_node_cnt;
-	uint32 bufsize;
-	uint32 bytes_written;
-	int reason;
-	struct list_head scan_results_list;
-	struct list_head expired_scan_results_list;
-};
-struct dhd_pno_legacy_params {
-	uint16 scan_fr;
-	uint16 chan_list[WL_NUMCHANNELS];
-	uint16 nchan;
-	int pno_repeat;
-	int pno_freq_expo_max;
-	int nssid;
-	struct list_head ssid_list;
-};
-struct dhd_pno_batch_params {
-	int32 scan_fr;
-	uint8 bestn;
-	uint8 mscan;
-	uint8 band;
-	uint16 chan_list[WL_NUMCHANNELS];
-	uint16 nchan;
-	uint16 rtt;
-	struct dhd_pno_get_batch_info get_batch;
-};
-struct dhd_pno_hotlist_params {
-	uint8 band;
-	int32 scan_fr;
-	uint16 chan_list[WL_NUMCHANNELS];
-	uint16 nchan;
-	uint16 nbssid;
-	struct list_head bssid_list;
-};
-#ifdef GSCAN_SUPPORT
-typedef struct dhd_pno_gscan_channel_bucket {
-	uint16 bucket_freq_multiple;
-	/* band = 1 All bg band channels,
-	 * band = 2 All a band channels,
-	 * band = 0 chan_list channels
-	 */
-	uint16 band;
-	uint8 report_flag;
-	uint8 num_channels;
-	uint16 chan_list[GSCAN_MAX_CH_BUCKETS];
-} dhd_pno_gscan_channel_bucket_t;
-
-typedef struct dhd_pno_swc_evt_param {
-	uint16 results_rxed_so_far;
-	wl_pfn_significant_net_t *change_array;
-} dhd_pno_swc_evt_param_t;
-
-typedef struct wifi_gscan_result {
-	uint64 ts;                           /* Time of discovery           */
-	char ssid[DOT11_MAX_SSID_LEN+1];     /* null terminated             */
-	struct ether_addr	macaddr;         /* BSSID                      */
-	uint32 channel;                      /* channel frequency in MHz    */
-	int32 rssi;                          /* in db                       */
-	uint64 rtt;                          /* in nanoseconds              */
-	uint64 rtt_sd;                       /* standard deviation in rtt   */
-	uint16 beacon_period;                /* units are Kusec             */
-	uint16 capability;                   /* Capability information       */
-	uint32 ie_length;                    /* byte length of Information Elements */
-	char  ie_data[1];                    /* IE data to follow       */
-} wifi_gscan_result_t;
-
-typedef struct gscan_results_cache {
-	struct gscan_results_cache *next;
-	uint8  scan_id;
-	uint8  flag;
-	uint8  tot_count;
-	uint8  tot_consumed;
-	wifi_gscan_result_t results[1];
-} gscan_results_cache_t;
-
-typedef struct dhd_pno_gscan_capabilities {
-	int max_scan_cache_size;
-	int max_scan_buckets;
-	int max_ap_cache_per_scan;
-	int max_rssi_sample_size;
-	int max_scan_reporting_threshold;
-	int max_hotlist_aps;
-	int max_significant_wifi_change_aps;
-} dhd_pno_gscan_capabilities_t;
-
-struct dhd_pno_gscan_params {
-	int32 scan_fr;
-	uint8 bestn;
-	uint8 mscan;
-	uint8 buffer_threshold;
-	uint8 swc_nbssid_threshold;
-	uint8 swc_rssi_window_size;
-	uint8 lost_ap_window;
-	uint8 nchannel_buckets;
-	uint8 reason;
-	uint8 get_batch_flag;
-	uint8 send_all_results_flag;
-	uint16 max_ch_bucket_freq;
-	gscan_results_cache_t *gscan_batch_cache;
-	gscan_results_cache_t *gscan_hotlist_found;
-	gscan_results_cache_t *gscan_hotlist_lost;
-	uint16 nbssid_significant_change;
-	uint16 nbssid_hotlist;
-	struct dhd_pno_swc_evt_param param_significant;
-	struct dhd_pno_gscan_channel_bucket channel_bucket[GSCAN_MAX_CH_BUCKETS];
-	struct list_head hotlist_bssid_list;
-	struct list_head significant_bssid_list;
-};
-
-typedef struct gscan_scan_params {
-	int32 scan_fr;
-	uint16 nchannel_buckets;
-	struct dhd_pno_gscan_channel_bucket channel_bucket[GSCAN_MAX_CH_BUCKETS];
-} gscan_scan_params_t;
-
-typedef struct gscan_batch_params {
-	uint8 bestn;
-	uint8 mscan;
-	uint8 buffer_threshold;
-} gscan_batch_params_t;
-
-struct bssid_t {
-	struct ether_addr	macaddr;
-	int16 rssi_reporting_threshold;  /* 0 -> no reporting threshold */
-};
-
-typedef struct gscan_hotlist_scan_params {
-	uint16 lost_ap_window; /* number of scans to declare LOST */
-	uint16 nbssid;   /* number of bssids  */
-	struct bssid_t bssid[1];  /* n bssids to follow */
-} gscan_hotlist_scan_params_t;
-
-/* SWC (Significant WiFi Change) params */
-typedef struct gscan_swc_params {
-	/* Rssi averaging window size */
-	uint8 rssi_window;
-	/* Number of scans that the AP has to be absent before
-	 * being declared LOST
-	 */
-	uint8 lost_ap_window;
-	/* if x  Aps have a significant change generate an event. */
-	uint8 swc_threshold;
-	uint8 nbssid;
-	wl_pfn_significant_bssid_t bssid_elem_list[1];
-} gscan_swc_params_t;
-
-typedef struct dhd_pno_significant_bssid {
-	struct ether_addr BSSID;
-	int8 rssi_low_threshold;
-	int8 rssi_high_threshold;
-	struct list_head list;
-} dhd_pno_significant_bssid_t;
-#endif /* GSCAN_SUPPORT */
-typedef union dhd_pno_params {
-	struct dhd_pno_legacy_params params_legacy;
-	struct dhd_pno_batch_params params_batch;
-	struct dhd_pno_hotlist_params params_hotlist;
-#ifdef GSCAN_SUPPORT
-	struct dhd_pno_gscan_params params_gscan;
-#endif /* GSCAN_SUPPORT */
-} dhd_pno_params_t;
-typedef struct dhd_pno_status_info {
-	uint8 pno_oui[DOT11_OUI_LEN];
-	dhd_pub_t *dhd;
-	struct work_struct work;
-	struct mutex pno_mutex;
-#ifdef GSCAN_SUPPORT
-	wait_queue_head_t batch_get_wait;
-#endif /* GSCAN_SUPPORT */
-	struct completion get_batch_done;
-	bool wls_supported; /* wifi location service supported or not */
-	enum dhd_pno_status pno_status;
-	enum dhd_pno_mode pno_mode;
-	dhd_pno_params_t pno_params_arr[INDEX_MODE_MAX];
-	struct list_head head_list;
-} dhd_pno_status_info_t;
-
-/* wrapper functions */
-extern int
-dhd_dev_pno_enable(struct net_device *dev, int enable);
-
-extern int
-dhd_dev_pno_stop_for_ssid(struct net_device *dev);
-
-extern int
-dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_ext_t* ssids_local, int nssid,
-	uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan);
-
-extern int
-dhd_dev_pno_set_for_batch(struct net_device *dev,
-	struct dhd_pno_batch_params *batch_params);
-
-extern int
-dhd_dev_pno_get_for_batch(struct net_device *dev, char *buf, int bufsize);
-
-extern int
-dhd_dev_pno_stop_for_batch(struct net_device *dev);
-
-extern int
-dhd_dev_pno_set_for_hotlist(struct net_device *dev, wl_pfn_bssid_t *p_pfn_bssid,
-	struct dhd_pno_hotlist_params *hotlist_params);
-extern int dhd_dev_pno_set_mac_oui(struct net_device *dev, uint8 *oui);
-#ifdef GSCAN_SUPPORT
-extern int
-dhd_dev_pno_set_cfg_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type,
-              void *buf, uint8 flush);
-extern void *
-dhd_dev_pno_get_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type, void *info,
-        uint32 *len);
-void dhd_dev_pno_lock_access_batch_results(struct net_device *dev);
-void dhd_dev_pno_unlock_access_batch_results(struct net_device *dev);
-extern int dhd_dev_pno_run_gscan(struct net_device *dev, bool run, bool flush);
-extern int dhd_dev_pno_enable_full_scan_result(struct net_device *dev, bool real_time);
-extern void * dhd_dev_swc_scan_event(struct net_device *dev, const void  *data,
-              int *send_evt_bytes);
-int dhd_retreive_batch_scan_results(dhd_pub_t *dhd);
-extern void * dhd_dev_hotlist_scan_event(struct net_device *dev,
-            const void  *data, int *send_evt_bytes, hotlist_type_t type);
-void * dhd_dev_process_full_gscan_result(struct net_device *dev,
-            const void  *data, int *send_evt_bytes);
-extern int dhd_dev_gscan_batch_cache_cleanup(struct net_device *dev);
-extern void dhd_dev_gscan_hotlist_cache_cleanup(struct net_device *dev, hotlist_type_t type);
-extern void dhd_dev_wait_batch_results_complete(struct net_device *dev);
-#endif /* GSCAN_SUPPORT */
-/* dhd pno fuctions */
-extern int dhd_pno_stop_for_ssid(dhd_pub_t *dhd);
-extern int dhd_pno_enable(dhd_pub_t *dhd, int enable);
-extern int dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssid_list, int nssid,
-	uint16  scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan);
-
-extern int dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params);
-
-extern int dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason);
-
-
-extern int dhd_pno_stop_for_batch(dhd_pub_t *dhd);
-
-extern int dhd_pno_set_for_hotlist(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid,
-	struct dhd_pno_hotlist_params *hotlist_params);
-
-extern int dhd_pno_stop_for_hotlist(dhd_pub_t *dhd);
-
-extern int dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data);
-extern int dhd_pno_init(dhd_pub_t *dhd);
-extern int dhd_pno_deinit(dhd_pub_t *dhd);
-extern bool dhd_is_pno_supported(dhd_pub_t *dhd);
-extern int dhd_pno_set_mac_oui(dhd_pub_t *dhd, uint8 *oui);
-#ifdef GSCAN_SUPPORT
-extern int dhd_pno_set_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type,
-                       void *buf, uint8 flush);
-extern void * dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, void *info,
-                       uint32 *len);
-extern void dhd_pno_lock_batch_results(dhd_pub_t *dhd);
-extern void dhd_pno_unlock_batch_results(dhd_pub_t *dhd);
-extern int dhd_pno_initiate_gscan_request(dhd_pub_t *dhd, bool run, bool flush);
-extern int dhd_pno_enable_full_scan_result(dhd_pub_t *dhd, bool real_time_flag);
-extern int dhd_pno_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, void *buf);
-extern int dhd_dev_retrieve_batch_scan(struct net_device *dev);
-extern void *dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_bytes);
-extern void *dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data,
-                       int *send_evt_bytes, hotlist_type_t type);
-extern void *dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *event_data,
-                       int *send_evt_bytes);
-extern int dhd_gscan_batch_cache_cleanup(dhd_pub_t *dhd);
-extern void dhd_gscan_hotlist_cache_cleanup(dhd_pub_t *dhd, hotlist_type_t type);
-extern void dhd_wait_batch_results_complete(dhd_pub_t *dhd);
-#endif /* GSCAN_SUPPORT */
-#endif 
-
-#endif /* __DHD_PNO_H__ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_proto.h b/drivers/net/wireless/bcmdhd/dhd_proto.h
deleted file mode 100644
index 6dcb563..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_proto.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Header file describing the internal (inter-module) DHD interfaces.
- *
- * Provides type definitions and function prototypes used to link the
- * DHD OS, bus, and protocol modules.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_proto.h 604483 2015-12-07 14:47:36Z $
- */
-
-#ifndef _dhd_proto_h_
-#define _dhd_proto_h_
-
-#include <dhdioctl.h>
-#include <wlioctl.h>
-#ifdef BCMPCIE
-#include <dhd_flowring.h>
-#endif
-
-#define DEFAULT_IOCTL_RESP_TIMEOUT	2000
-#ifndef IOCTL_RESP_TIMEOUT
-/* In milli second default value for Production FW */
-#define IOCTL_RESP_TIMEOUT  DEFAULT_IOCTL_RESP_TIMEOUT
-#endif /* IOCTL_RESP_TIMEOUT */
-
-#ifndef MFG_IOCTL_RESP_TIMEOUT
-#define MFG_IOCTL_RESP_TIMEOUT  20000  /* In milli second default value for MFG FW */
-#endif /* MFG_IOCTL_RESP_TIMEOUT */
-
-#define DEFAULT_D3_ACK_RESP_TIMEOUT	4000
-#ifndef D3_ACK_RESP_TIMEOUT
-#define D3_ACK_RESP_TIMEOUT		DEFAULT_D3_ACK_RESP_TIMEOUT
-#endif /* D3_ACK_RESP_TIMEOUT */
-
-#define DEFAULT_DHD_BUS_BUSY_TIMEOUT	(IOCTL_RESP_TIMEOUT + 1000)
-#ifndef DHD_BUS_BUSY_TIMEOUT
-#define DHD_BUS_BUSY_TIMEOUT	DEFAULT_DHD_BUS_BUSY_TIMEOUT
-#endif /* DEFAULT_DHD_BUS_BUSY_TIMEOUT */
-
-#define IOCTL_DISABLE_TIMEOUT 0
-/*
- * Exported from the dhd protocol module (dhd_cdc, dhd_rndis)
- */
-
-/* Linkage, sets prot link and updates hdrlen in pub */
-extern int dhd_prot_attach(dhd_pub_t *dhdp);
-
-/* Initilizes the index block for dma'ing indices */
-extern int dhd_prot_dma_indx_init(dhd_pub_t *dhdp, uint32 rw_index_sz,
-	uint8 type, uint32 length);
-
-/* Unlink, frees allocated protocol memory (including dhd_prot) */
-extern void dhd_prot_detach(dhd_pub_t *dhdp);
-
-/* Initialize protocol: sync w/dongle state.
- * Sets dongle media info (iswl, drv_version, mac address).
- */
-extern int dhd_sync_with_dongle(dhd_pub_t *dhdp);
-
-/* Protocol initialization needed for IOCTL/IOVAR path */
-extern int dhd_prot_init(dhd_pub_t *dhd);
-
-/* Stop protocol: sync w/dongle state. */
-extern void dhd_prot_stop(dhd_pub_t *dhdp);
-
-/* Add any protocol-specific data header.
- * Caller must reserve prot_hdrlen prepend space.
- */
-extern void dhd_prot_hdrpush(dhd_pub_t *, int ifidx, void *txp);
-extern uint dhd_prot_hdrlen(dhd_pub_t *, void *txp);
-
-/* Remove any protocol-specific data header. */
-extern int dhd_prot_hdrpull(dhd_pub_t *, int *ifidx, void *rxp, uchar *buf, uint *len);
-
-/* Use protocol to issue ioctl to dongle */
-extern int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len);
-
-/* Handles a protocol control response asynchronously */
-extern int dhd_prot_ctl_complete(dhd_pub_t *dhd);
-
-/* Check for and handle local prot-specific iovar commands */
-extern int dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
-                             void *params, int plen, void *arg, int len, bool set);
-
-/* Add prot dump output to a buffer */
-extern void dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
-
-/* Update local copy of dongle statistics */
-extern void dhd_prot_dstats(dhd_pub_t *dhdp);
-
-extern int dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen);
-
-extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
-
-extern int dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf,
-	uint reorder_info_len, void **pkt, uint32 *free_buf_count);
-
-#ifdef BCMPCIE
-extern bool dhd_prot_process_msgbuf_txcpl(dhd_pub_t *dhd, uint bound);
-extern bool dhd_prot_process_msgbuf_rxcpl(dhd_pub_t *dhd, uint bound);
-extern int dhd_prot_process_ctrlbuf(dhd_pub_t * dhd);
-extern bool dhd_prot_dtohsplit(dhd_pub_t * dhd);
-extern int dhd_post_dummy_msg(dhd_pub_t *dhd);
-extern int dhdmsgbuf_lpbk_req(dhd_pub_t *dhd, uint len);
-extern void dhd_prot_rx_dataoffset(dhd_pub_t *dhd, uint32 offset);
-extern int dhd_prot_txdata(dhd_pub_t *dhd, void *p, uint8 ifidx);
-extern int dhdmsgbuf_dmaxfer_req(dhd_pub_t *dhd, uint len, uint srcdelay, uint destdelay);
-
-extern void dhd_dma_buf_init(dhd_pub_t *dhd, void *dma_buf,
-	void *va, uint32 len, dmaaddr_t pa, void *dmah, void *secdma);
-extern void dhd_prot_flowrings_pool_release(dhd_pub_t *dhd,
-	uint16 flowid, void *msgbuf_ring);
-extern int dhd_prot_flow_ring_create(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node);
-extern int dhd_post_tx_ring_item(dhd_pub_t *dhd, void *PKTBUF, uint8 ifindex);
-extern int dhd_prot_flow_ring_delete(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node);
-extern int dhd_prot_flow_ring_flush(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node);
-extern int dhd_prot_ringupd_dump(dhd_pub_t *dhd, struct bcmstrbuf *b);
-extern uint32 dhd_prot_metadata_dbg_set(dhd_pub_t *dhd, bool val);
-extern uint32 dhd_prot_metadata_dbg_get(dhd_pub_t *dhd);
-extern uint32 dhd_prot_metadatalen_set(dhd_pub_t *dhd, uint32 val, bool rx);
-extern uint32 dhd_prot_metadatalen_get(dhd_pub_t *dhd, bool rx);
-extern void dhd_prot_print_flow_ring(dhd_pub_t *dhd, void *msgbuf_flow_info,
-	struct bcmstrbuf *strbuf, const char * fmt);
-extern void dhd_prot_print_info(dhd_pub_t *dhd, struct bcmstrbuf *strbuf);
-extern void dhd_prot_update_txflowring(dhd_pub_t *dhdp, uint16 flow_id, void *msgring_info);
-extern void dhd_prot_txdata_write_flush(dhd_pub_t *dhd, uint16 flow_id, bool in_lock);
-extern uint32 dhd_prot_txp_threshold(dhd_pub_t *dhd, bool set, uint32 val);
-extern void dhd_prot_reset(dhd_pub_t *dhd);
-#ifdef DHD_LB
-extern void dhd_lb_tx_compl_handler(unsigned long data);
-extern void dhd_lb_rx_compl_handler(unsigned long data);
-extern void dhd_lb_rx_process_handler(unsigned long data);
-#endif /* DHD_LB */
-void dhd_prot_collect_memdump(dhd_pub_t *dhd);
-#endif /* BCMPCIE */
-/********************************
- * For version-string expansion *
- */
-#if defined(BDC)
-#define DHD_PROTOCOL "bdc"
-#elif defined(CDC)
-#define DHD_PROTOCOL "cdc"
-#else
-#define DHD_PROTOCOL "unknown"
-#endif /* proto */
-
-#endif /* _dhd_proto_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_rtt.c b/drivers/net/wireless/bcmdhd/dhd_rtt.c
deleted file mode 100644
index cc0ebb2..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_rtt.c
+++ /dev/null
@@ -1,731 +0,0 @@
-/*
- * Broadcom Dongle Host Driver (DHD), RTT
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- * $Id: dhd_rtt.c 606280 2015-12-15 05:28:25Z $
- */
-#ifdef RTT_SUPPORT
-#include <typedefs.h>
-#include <osl.h>
-
-#include <epivers.h>
-#include <bcmutils.h>
-
-#include <bcmendian.h>
-#include <linuxver.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/sort.h>
-#include <dngl_stats.h>
-#include <wlioctl.h>
-
-#include <proto/bcmevent.h>
-#include <dhd.h>
-#include <dhd_rtt.h>
-#include <dhd_dbg.h>
-#define GET_RTTSTATE(dhd) ((rtt_status_info_t *)dhd->rtt_state)
-static DEFINE_SPINLOCK(noti_list_lock);
-#define NULL_CHECK(p, s, err)  \
-			do { \
-				if (!(p)) { \
-					printf("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \
-					err = BCME_ERROR; \
-					return err; \
-				} \
-			} while (0)
-
-#define RTT_TWO_SIDED(capability) \
-			do { \
-				if ((capability & RTT_CAP_ONE_WAY) == (uint8) (RTT_CAP_ONE_WAY)) \
-					return FALSE; \
-				else \
-					return TRUE; \
-			} while (0)
-#define TIMESPEC_TO_US(ts)  (((uint64)(ts).tv_sec * USEC_PER_SEC) + \
-							(ts).tv_nsec / NSEC_PER_USEC)
-struct rtt_noti_callback {
-	struct list_head list;
-	void *ctx;
-	dhd_rtt_compl_noti_fn noti_fn;
-};
-
-typedef struct rtt_status_info {
-	dhd_pub_t *dhd;
-	int8 status;   /* current status for the current entry */
-	int8 cur_idx; /* current entry to do RTT */
-	int32 capability; /* rtt capability */
-	struct mutex rtt_mutex;
-	rtt_config_params_t rtt_config;
-	struct work_struct work;
-	struct list_head noti_fn_list;
-	struct list_head rtt_results_cache; /* store results for RTT */
-} rtt_status_info_t;
-
-static int dhd_rtt_start(dhd_pub_t *dhd);
-
-chanspec_t
-dhd_rtt_convert_to_chspec(wifi_channel_info_t channel)
-{
-	int bw;
-	/* set witdh to 20MHZ for 2.4G HZ */
-	if (channel.center_freq >= 2400 && channel.center_freq <= 2500) {
-		channel.width = WIFI_CHAN_WIDTH_20;
-	}
-	switch (channel.width) {
-	case WIFI_CHAN_WIDTH_20:
-		bw = WL_CHANSPEC_BW_20;
-		break;
-	case WIFI_CHAN_WIDTH_40:
-		bw = WL_CHANSPEC_BW_40;
-		break;
-	case WIFI_CHAN_WIDTH_80:
-		bw = WL_CHANSPEC_BW_80;
-		break;
-	case WIFI_CHAN_WIDTH_160:
-		bw = WL_CHANSPEC_BW_160;
-		break;
-	default:
-		DHD_ERROR(("doesn't support this bandwith : %d", channel.width));
-		bw = -1;
-		break;
-	}
-	return wf_channel2chspec(wf_mhz2channel(channel.center_freq, 0), bw);
-}
-
-int
-dhd_rtt_set_cfg(dhd_pub_t *dhd, rtt_config_params_t *params)
-{
-	int err = BCME_OK;
-	int idx;
-	rtt_status_info_t *rtt_status;
-	NULL_CHECK(params, "params is NULL", err);
-
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	rtt_status = GET_RTTSTATE(dhd);
-	NULL_CHECK(rtt_status, "rtt_status is NULL", err);
-	if (rtt_status->capability == RTT_CAP_NONE) {
-		DHD_ERROR(("doesn't support RTT \n"));
-		return BCME_ERROR;
-	}
-	if (rtt_status->status == RTT_STARTED) {
-		DHD_ERROR(("rtt is already started\n"));
-		return BCME_BUSY;
-	}
-	DHD_RTT(("%s enter\n", __FUNCTION__));
-	bcopy(params, &rtt_status->rtt_config, sizeof(rtt_config_params_t));
-	rtt_status->status = RTT_STARTED;
-	/* start to measure RTT from 1th device */
-	/* find next target to trigger RTT */
-	for (idx = rtt_status->cur_idx; idx < rtt_status->rtt_config.rtt_target_cnt; idx++) {
-		/* skip the disabled device */
-		if (rtt_status->rtt_config.target_info[idx].disable) {
-			continue;
-		} else {
-			/* set the idx to cur_idx */
-			rtt_status->cur_idx = idx;
-			break;
-		}
-	}
-	if (idx < rtt_status->rtt_config.rtt_target_cnt) {
-		DHD_RTT(("rtt_status->cur_idx : %d\n", rtt_status->cur_idx));
-		schedule_work(&rtt_status->work);
-	}
-	return err;
-}
-
-int
-dhd_rtt_stop(dhd_pub_t *dhd, struct ether_addr *mac_list, int mac_cnt)
-{
-	int err = BCME_OK;
-	int i = 0, j = 0;
-	rtt_status_info_t *rtt_status;
-
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	rtt_status = GET_RTTSTATE(dhd);
-	NULL_CHECK(rtt_status, "rtt_status is NULL", err);
-	if (rtt_status->status == RTT_STOPPED) {
-		DHD_ERROR(("rtt is not started\n"));
-		return BCME_OK;
-	}
-	DHD_RTT(("%s enter\n", __FUNCTION__));
-	mutex_lock(&rtt_status->rtt_mutex);
-	for (i = 0; i < mac_cnt; i++) {
-		for (j = 0; j < rtt_status->rtt_config.rtt_target_cnt; j++) {
-			if (!bcmp(&mac_list[i], &rtt_status->rtt_config.target_info[j].addr,
-				ETHER_ADDR_LEN)) {
-				rtt_status->rtt_config.target_info[j].disable = TRUE;
-			}
-		}
-	}
-	mutex_unlock(&rtt_status->rtt_mutex);
-	return err;
-}
-
-static int
-dhd_rtt_start(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	int mpc = 0;
-	int nss, mcs, bw;
-	uint32 rspec = 0;
-	int8 eabuf[ETHER_ADDR_STR_LEN];
-	int8 chanbuf[CHANSPEC_STR_LEN];
-	bool set_mpc = FALSE;
-	wl_proxd_iovar_t proxd_iovar;
-	wl_proxd_params_iovar_t proxd_params;
-	wl_proxd_params_iovar_t proxd_tune;
-	wl_proxd_params_tof_method_t *tof_params = &proxd_params.u.tof_params;
-	rtt_status_info_t *rtt_status;
-	rtt_target_info_t *rtt_target;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-
-	rtt_status = GET_RTTSTATE(dhd);
-	NULL_CHECK(rtt_status, "rtt_status is NULL", err);
-	/* turn off mpc in case of non-associted */
-	if (!dhd_is_associated(dhd, 0, NULL)) {
-		err = dhd_iovar(dhd, 0, "mpc", (char *)&mpc, sizeof(mpc), 1);
-		if (err < 0) {
-			DHD_ERROR(("%s : failed to set proxd_tune\n", __FUNCTION__));
-			goto exit;
-		}
-		set_mpc = TRUE;
-	}
-
-	if (rtt_status->cur_idx >= rtt_status->rtt_config.rtt_target_cnt) {
-		err = BCME_RANGE;
-		goto exit;
-	}
-	DHD_RTT(("%s enter\n", __FUNCTION__));
-	bzero(&proxd_tune, sizeof(proxd_tune));
-	bzero(&proxd_params, sizeof(proxd_params));
-	mutex_lock(&rtt_status->rtt_mutex);
-	/* Get a target information */
-	rtt_target = &rtt_status->rtt_config.target_info[rtt_status->cur_idx];
-	mutex_unlock(&rtt_status->rtt_mutex);
-	/* set role */
-	proxd_iovar.method = PROXD_TOF_METHOD;
-	proxd_iovar.mode = WL_PROXD_MODE_INITIATOR;
-
-	/* make sure that proxd is stop */
-	/* dhd_iovar(dhd, 0, "proxd_stop", (char *)NULL, 0, 1); */
-
-	err = dhd_iovar(dhd, 0, "proxd", (char *)&proxd_iovar, sizeof(proxd_iovar), 1);
-	if (err < 0 && err != BCME_BUSY) {
-		DHD_ERROR(("%s : failed to set proxd %d\n", __FUNCTION__, err));
-		goto exit;
-	}
-	if (err == BCME_BUSY) {
-		DHD_RTT(("BCME_BUSY occurred\n"));
-	}
-	/* mac address */
-	bcopy(&rtt_target->addr, &tof_params->tgt_mac, ETHER_ADDR_LEN);
-	/* frame count */
-	if (rtt_target->ftm_cnt > RTT_MAX_FRAME_CNT) {
-		rtt_target->ftm_cnt = RTT_MAX_FRAME_CNT;
-	}
-
-	if (rtt_target->ftm_cnt) {
-		tof_params->ftm_cnt = htol16(rtt_target->ftm_cnt);
-	} else {
-		tof_params->ftm_cnt = htol16(DEFAULT_FTM_CNT);
-	}
-
-	if (rtt_target->retry_cnt > RTT_MAX_RETRY_CNT) {
-		rtt_target->retry_cnt = RTT_MAX_RETRY_CNT;
-	}
-
-	/* retry count */
-	if (rtt_target->retry_cnt) {
-		tof_params->retry_cnt = htol16(rtt_target->retry_cnt);
-	} else {
-		tof_params->retry_cnt = htol16(DEFAULT_RETRY_CNT);
-	}
-
-	/* chanspec */
-	tof_params->chanspec = htol16(rtt_target->chanspec);
-	/* set parameter */
-	DHD_RTT(("Target addr(Idx %d) %s, Channel : %s for RTT (ftm_cnt %d, rety_cnt : %d)\n",
-		rtt_status->cur_idx,
-		bcm_ether_ntoa((const struct ether_addr *)&rtt_target->addr, eabuf),
-		wf_chspec_ntoa(rtt_target->chanspec, chanbuf), rtt_target->ftm_cnt,
-		rtt_target->retry_cnt));
-
-	if (rtt_target->type == RTT_ONE_WAY) {
-		proxd_tune.u.tof_tune.flags = htol32(WL_PROXD_FLAG_ONEWAY);
-		/* report RTT results for initiator */
-		proxd_tune.u.tof_tune.flags |= htol32(WL_PROXD_FLAG_INITIATOR_RPTRTT);
-		proxd_tune.u.tof_tune.vhtack = 0;
-		tof_params->tx_rate = htol16(WL_RATE_6M);
-		tof_params->vht_rate = htol16((WL_RATE_6M >> 16));
-	} else { /* RTT TWO WAY */
-		/* initiator will send the rtt result to the target  */
-		proxd_tune.u.tof_tune.flags = htol32(WL_PROXD_FLAG_INITIATOR_REPORT);
-		tof_params->timeout = 10; /* 10ms for timeout */
-		rspec = WL_RSPEC_ENCODE_VHT;	/* 11ac VHT */
-		nss = 1; /* default Nss = 1 */
-		mcs = 0; /* default MCS 0 */
-		rspec |= (nss << WL_RSPEC_VHT_NSS_SHIFT) | mcs;
-		bw = 0;
-		switch (CHSPEC_BW(rtt_target->chanspec)) {
-		case WL_CHANSPEC_BW_20:
-			bw = WL_RSPEC_BW_20MHZ;
-			break;
-		case WL_CHANSPEC_BW_40:
-			bw = WL_RSPEC_BW_40MHZ;
-			break;
-		case WL_CHANSPEC_BW_80:
-			bw = WL_RSPEC_BW_80MHZ;
-			break;
-		case WL_CHANSPEC_BW_160:
-			bw = WL_RSPEC_BW_160MHZ;
-			break;
-		default:
-			DHD_ERROR(("CHSPEC_BW not supported : %d",
-				CHSPEC_BW(rtt_target->chanspec)));
-			goto exit;
-		}
-		rspec |= bw;
-		tof_params->tx_rate = htol16(rspec & 0xffff);
-		tof_params->vht_rate = htol16(rspec >> 16);
-	}
-
-	/* Set Method to TOF */
-	proxd_tune.method = PROXD_TOF_METHOD;
-	err = dhd_iovar(dhd, 0, "proxd_tune", (char *)&proxd_tune, sizeof(proxd_tune), 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to set proxd_tune %d\n", __FUNCTION__, err));
-		goto exit;
-	}
-
-	/* Set Method to TOF */
-	proxd_params.method = PROXD_TOF_METHOD;
-	err = dhd_iovar(dhd, 0, "proxd_params", (char *)&proxd_params, sizeof(proxd_params), 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to set proxd_params %d\n", __FUNCTION__, err));
-		goto exit;
-	}
-	err = dhd_iovar(dhd, 0, "proxd_find", (char *)NULL, 0, 1);
-	if (err < 0) {
-		DHD_ERROR(("%s : failed to set proxd_find %d\n", __FUNCTION__, err));
-		goto exit;
-	}
-exit:
-	if (err < 0) {
-		rtt_status->status = RTT_STOPPED;
-		if (set_mpc) {
-			/* enable mpc again in case of error */
-			mpc = 1;
-			err = dhd_iovar(dhd, 0, "mpc", (char *)&mpc, sizeof(mpc), 1);
-		}
-	}
-	return err;
-}
-
-int
-dhd_rtt_register_noti_callback(dhd_pub_t *dhd, void *ctx, dhd_rtt_compl_noti_fn noti_fn)
-{
-	int err = BCME_OK;
-	struct rtt_noti_callback *cb = NULL, *iter;
-	rtt_status_info_t *rtt_status;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(noti_fn, "noti_fn is NULL", err);
-
-	rtt_status = GET_RTTSTATE(dhd);
-	NULL_CHECK(rtt_status, "rtt_status is NULL", err);
-	spin_lock_bh(&noti_list_lock);
-	list_for_each_entry(iter, &rtt_status->noti_fn_list, list) {
-		if (iter->noti_fn == noti_fn) {
-			goto exit;
-		}
-	}
-	cb = kmalloc(sizeof(struct rtt_noti_callback), GFP_ATOMIC);
-	if (!cb) {
-		err = -ENOMEM;
-		goto exit;
-	}
-	cb->noti_fn = noti_fn;
-	cb->ctx = ctx;
-	list_add(&cb->list, &rtt_status->noti_fn_list);
-exit:
-	spin_unlock_bh(&noti_list_lock);
-	return err;
-}
-
-int
-dhd_rtt_unregister_noti_callback(dhd_pub_t *dhd, dhd_rtt_compl_noti_fn noti_fn)
-{
-	int err = BCME_OK;
-	struct rtt_noti_callback *cb = NULL, *iter;
-	rtt_status_info_t *rtt_status;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	NULL_CHECK(noti_fn, "noti_fn is NULL", err);
-	rtt_status = GET_RTTSTATE(dhd);
-	NULL_CHECK(rtt_status, "rtt_status is NULL", err);
-	spin_lock_bh(&noti_list_lock);
-	list_for_each_entry(iter, &rtt_status->noti_fn_list, list) {
-		if (iter->noti_fn == noti_fn) {
-			cb = iter;
-			list_del(&cb->list);
-			break;
-		}
-	}
-	spin_unlock_bh(&noti_list_lock);
-	if (cb) {
-		kfree(cb);
-	}
-	return err;
-}
-
-static int
-dhd_rtt_convert_to_host(rtt_result_t *rtt_results, const wl_proxd_event_data_t* evp)
-{
-	int err = BCME_OK;
-	int i;
-	char eabuf[ETHER_ADDR_STR_LEN];
-	char diststr[40];
-	struct timespec ts;
-	NULL_CHECK(rtt_results, "rtt_results is NULL", err);
-	NULL_CHECK(evp, "evp is NULL", err);
-	DHD_RTT(("%s enter\n", __FUNCTION__));
-	rtt_results->distance = ntoh32(evp->distance);
-	rtt_results->sdrtt = ntoh32(evp->sdrtt);
-	rtt_results->ftm_cnt = ntoh16(evp->ftm_cnt);
-	rtt_results->avg_rssi = ntoh16(evp->avg_rssi);
-	rtt_results->validfrmcnt = ntoh16(evp->validfrmcnt);
-	rtt_results->meanrtt = ntoh32(evp->meanrtt);
-	rtt_results->modertt = ntoh32(evp->modertt);
-	rtt_results->medianrtt = ntoh32(evp->medianrtt);
-	rtt_results->err_code = evp->err_code;
-	rtt_results->tx_rate.preamble = (evp->OFDM_frame_type == TOF_FRAME_RATE_VHT)? 3 : 0;
-	rtt_results->tx_rate.nss = 0; /* 1 x 1 */
-	rtt_results->tx_rate.bw =
-		(evp->bandwidth == TOF_BW_80MHZ)? 2 : (evp->bandwidth == TOF_BW_40MHZ)? 1 : 0;
-	rtt_results->TOF_type = evp->TOF_type;
-	if (evp->TOF_type == TOF_TYPE_ONE_WAY) {
-		/* convert to 100kbps unit */
-		rtt_results->tx_rate.bitrate = WL_RATE_6M * 5;
-		rtt_results->tx_rate.rateMcsIdx = WL_RATE_6M;
-	} else {
-		rtt_results->tx_rate.bitrate = WL_RATE_6M * 5;
-		rtt_results->tx_rate.rateMcsIdx = 0; /* MCS 0 */
-	}
-	memset(diststr, 0, sizeof(diststr));
-	if (rtt_results->distance == 0xffffffff || rtt_results->distance == 0) {
-		sprintf(diststr, "distance=-1m\n");
-	} else {
-		sprintf(diststr, "distance=%d.%d m\n",
-			rtt_results->distance >> 4, ((rtt_results->distance & 0xf) * 125) >> 1);
-	}
-
-	if (ntoh32(evp->mode) == WL_PROXD_MODE_INITIATOR) {
-		DHD_RTT(("Target:(%s) %s;\n", bcm_ether_ntoa((&evp->peer_mac), eabuf), diststr));
-		DHD_RTT(("RTT : mean %d mode %d median %d\n", rtt_results->meanrtt,
-			rtt_results->modertt, rtt_results->medianrtt));
-	} else {
-		DHD_RTT(("Initiator:(%s) %s; ", bcm_ether_ntoa((&evp->peer_mac), eabuf), diststr));
-	}
-	if (rtt_results->sdrtt > 0) {
-		DHD_RTT(("sigma:%d.%d\n", rtt_results->sdrtt/10, rtt_results->sdrtt % 10));
-	} else {
-		DHD_RTT(("sigma:0\n"));
-	}
-
-	DHD_RTT(("rssi:%d validfrmcnt %d, err_code : %d\n", rtt_results->avg_rssi,
-		rtt_results->validfrmcnt, evp->err_code));
-
-	switch (evp->err_code) {
-	case TOF_REASON_OK:
-		rtt_results->err_code = RTT_REASON_SUCCESS;
-		break;
-	case TOF_REASON_TIMEOUT:
-		rtt_results->err_code = RTT_REASON_TIMEOUT;
-		break;
-	case TOF_REASON_NOACK:
-		rtt_results->err_code = RTT_REASON_NO_RSP;
-		break;
-	case TOF_REASON_ABORT:
-		rtt_results->err_code = RTT_REASON_ABORT;
-		break;
-	default:
-		rtt_results->err_code = RTT_REASON_FAILURE;
-		break;
-	}
-	rtt_results->peer_mac = evp->peer_mac;
-	/* get the time elapsed from boot time */
-	get_monotonic_boottime(&ts);
-	rtt_results->ts = (uint64) TIMESPEC_TO_US(ts);
-
-	for (i = 0; i < rtt_results->ftm_cnt; i++) {
-		rtt_results->ftm_buff[i].value = ltoh32(evp->ftm_buff[i].value);
-		rtt_results->ftm_buff[i].rssi = ltoh32(evp->ftm_buff[i].rssi);
-	}
-	return err;
-}
-
-int
-dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data)
-{
-	int err = BCME_OK;
-	int len = 0;
-	int idx;
-	uint status, event_type, flags, reason, ftm_cnt;
-	rtt_status_info_t *rtt_status;
-	wl_proxd_event_data_t* evp;
-	struct rtt_noti_callback *iter;
-	rtt_result_t *rtt_result, *entry, *next;
-	gfp_t kflags;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	rtt_status = GET_RTTSTATE(dhd);
-	NULL_CHECK(rtt_status, "rtt_status is NULL", err);
-	event_type = ntoh32_ua((void *)&event->event_type);
-	flags = ntoh16_ua((void *)&event->flags);
-	status = ntoh32_ua((void *)&event->status);
-	reason = ntoh32_ua((void *)&event->reason);
-
-	if (event_type != WLC_E_PROXD) {
-		goto exit;
-	}
-	kflags = in_softirq()? GFP_ATOMIC : GFP_KERNEL;
-	evp = (wl_proxd_event_data_t*)event_data;
-	DHD_RTT(("%s enter : mode: %s, reason :%d \n", __FUNCTION__,
-		(ntoh16(evp->mode) == WL_PROXD_MODE_INITIATOR)?
-		"initiator":"target", reason));
-	switch (reason) {
-	case WLC_E_PROXD_STOP:
-		DHD_RTT(("WLC_E_PROXD_STOP\n"));
-		break;
-	case WLC_E_PROXD_ERROR:
-	case WLC_E_PROXD_COMPLETED:
-		if (reason == WLC_E_PROXD_ERROR) {
-			DHD_RTT(("WLC_E_PROXD_ERROR\n"));
-		} else {
-			DHD_RTT(("WLC_E_PROXD_COMPLETED\n"));
-		}
-
-		if (!in_atomic()) {
-			mutex_lock(&rtt_status->rtt_mutex);
-		}
-		ftm_cnt = ntoh16(evp->ftm_cnt);
-
-		if (ftm_cnt > 0) {
-			len = OFFSETOF(rtt_result_t, ftm_buff);
-		} else {
-			len = sizeof(rtt_result_t);
-		}
-		/* check whether the results is already reported or not */
-		list_for_each_entry(entry, &rtt_status->rtt_results_cache, list) {
-			if (!memcmp(&entry->peer_mac, &evp->peer_mac, ETHER_ADDR_LEN))	{
-				if (!in_atomic()) {
-					mutex_unlock(&rtt_status->rtt_mutex);
-				}
-				goto exit;
-			}
-		}
-		rtt_result = kzalloc(len + sizeof(ftm_sample_t) * ftm_cnt, kflags);
-		if (!rtt_result) {
-			if (!in_atomic()) {
-				mutex_unlock(&rtt_status->rtt_mutex);
-			}
-			err = -ENOMEM;
-			goto exit;
-		}
-		/* point to target_info in status struct and increase pointer */
-		rtt_result->target_info = &rtt_status->rtt_config.target_info[rtt_status->cur_idx];
-		/* find next target to trigger RTT */
-		for (idx = (rtt_status->cur_idx + 1);
-			idx < rtt_status->rtt_config.rtt_target_cnt; idx++) {
-			/* skip the disabled device */
-			if (rtt_status->rtt_config.target_info[idx].disable) {
-				continue;
-			} else {
-				/* set the idx to cur_idx */
-				rtt_status->cur_idx = idx;
-				break;
-			}
-		}
-		/* convert the event results to host format */
-		dhd_rtt_convert_to_host(rtt_result, evp);
-		list_add_tail(&rtt_result->list, &rtt_status->rtt_results_cache);
-		if (idx < rtt_status->rtt_config.rtt_target_cnt) {
-			/* restart to measure RTT from next device */
-			schedule_work(&rtt_status->work);
-		} else {
-			DHD_RTT(("RTT_STOPPED\n"));
-			rtt_status->status = RTT_STOPPED;
-			/* to turn on mpc mode */
-			schedule_work(&rtt_status->work);
-			/* notify the completed information to others */
-			list_for_each_entry(iter, &rtt_status->noti_fn_list, list) {
-				iter->noti_fn(iter->ctx, &rtt_status->rtt_results_cache);
-			}
-			/* remove the rtt results in cache */
-			list_for_each_entry_safe(rtt_result, next,
-				&rtt_status->rtt_results_cache, list) {
-				list_del(&rtt_result->list);
-				kfree(rtt_result);
-			}
-			/* reinit the HEAD */
-			INIT_LIST_HEAD(&rtt_status->rtt_results_cache);
-			/* clear information for rtt_config */
-			bzero(&rtt_status->rtt_config, sizeof(rtt_status->rtt_config));
-			rtt_status->cur_idx = 0;
-		}
-		if (!in_atomic()) {
-			mutex_unlock(&rtt_status->rtt_mutex);
-		}
-
-		break;
-	case WLC_E_PROXD_GONE:
-		DHD_RTT(("WLC_E_PROXD_GONE\n"));
-		break;
-	case WLC_E_PROXD_START:
-		/* event for targets / accesspoints  */
-		DHD_RTT(("WLC_E_PROXD_START\n"));
-		break;
-	case WLC_E_PROXD_COLLECT_START:
-		DHD_RTT(("WLC_E_PROXD_COLLECT_START\n"));
-		break;
-	case WLC_E_PROXD_COLLECT_STOP:
-		DHD_RTT(("WLC_E_PROXD_COLLECT_STOP\n"));
-		break;
-	case WLC_E_PROXD_COLLECT_COMPLETED:
-		DHD_RTT(("WLC_E_PROXD_COLLECT_COMPLETED\n"));
-		break;
-	case WLC_E_PROXD_COLLECT_ERROR:
-		DHD_RTT(("WLC_E_PROXD_COLLECT_ERROR; "));
-		break;
-	default:
-		DHD_ERROR(("WLC_E_PROXD: supported EVENT reason code:%d\n", reason));
-		break;
-	}
-
-exit:
-	return err;
-}
-
-static void
-dhd_rtt_work(struct work_struct *work)
-{
-	rtt_status_info_t *rtt_status;
-	dhd_pub_t *dhd;
-	rtt_status = container_of(work, rtt_status_info_t, work);
-	if (rtt_status == NULL) {
-		DHD_ERROR(("%s : rtt_status is NULL\n", __FUNCTION__));
-		return;
-	}
-	dhd = rtt_status->dhd;
-	if (dhd == NULL) {
-		DHD_ERROR(("%s : dhd is NULL\n", __FUNCTION__));
-		return;
-	}
-	(void) dhd_rtt_start(dhd);
-}
-
-int
-dhd_rtt_capability(dhd_pub_t *dhd, rtt_capabilities_t *capa)
-{
-	rtt_status_info_t *rtt_status;
-	int err = BCME_OK;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	rtt_status = GET_RTTSTATE(dhd);
-	NULL_CHECK(rtt_status, "rtt_status is NULL", err);
-	NULL_CHECK(capa, "capa is NULL", err);
-	bzero(capa, sizeof(rtt_capabilities_t));
-
-	if (rtt_status->capability & RTT_CAP_ONE_WAY) {
-		capa->rtt_one_sided_supported = 1;
-	}
-	if (rtt_status->capability & RTT_CAP_11V_WAY) {
-		capa->rtt_11v_supported = 1;
-	}
-	if (rtt_status->capability & RTT_CAP_11MC_WAY) {
-		capa->rtt_ftm_supported = 1;
-	}
-	if (rtt_status->capability & RTT_CAP_VS_WAY) {
-		capa->rtt_vs_supported = 1;
-	}
-
-	return err;
-}
-
-int
-dhd_rtt_init(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	rtt_status_info_t *rtt_status;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	if (dhd->rtt_state) {
-		goto exit;
-	}
-	dhd->rtt_state = MALLOC(dhd->osh, sizeof(rtt_status_info_t));
-	if (dhd->rtt_state == NULL) {
-		DHD_ERROR(("failed to create rtt_state\n"));
-		goto exit;
-	}
-	bzero(dhd->rtt_state, sizeof(rtt_status_info_t));
-	rtt_status = GET_RTTSTATE(dhd);
-	rtt_status->dhd = dhd;
-	err = dhd_iovar(dhd, 0, "proxd_params", NULL, 0, 1);
-	if (err != BCME_UNSUPPORTED) {
-		rtt_status->capability |= RTT_CAP_ONE_WAY;
-		rtt_status->capability |= RTT_CAP_VS_WAY;
-		DHD_ERROR(("%s: Support RTT Service\n", __FUNCTION__));
-	}
-	mutex_init(&rtt_status->rtt_mutex);
-	INIT_LIST_HEAD(&rtt_status->noti_fn_list);
-	INIT_LIST_HEAD(&rtt_status->rtt_results_cache);
-	INIT_WORK(&rtt_status->work, dhd_rtt_work);
-exit:
-	return err;
-}
-
-int
-dhd_rtt_deinit(dhd_pub_t *dhd)
-{
-	int err = BCME_OK;
-	rtt_status_info_t *rtt_status;
-	rtt_result_t *rtt_result, *next;
-	struct rtt_noti_callback *iter, *iter2;
-	NULL_CHECK(dhd, "dhd is NULL", err);
-	rtt_status = GET_RTTSTATE(dhd);
-	NULL_CHECK(rtt_status, "rtt_status is NULL", err);
-	rtt_status->status = RTT_STOPPED;
-	/* clear evt callback list */
-	if (!list_empty(&rtt_status->noti_fn_list)) {
-		list_for_each_entry_safe(iter, iter2, &rtt_status->noti_fn_list, list) {
-			list_del(&iter->list);
-			kfree(iter);
-		}
-	}
-	/* remove the rtt results */
-	if (!list_empty(&rtt_status->rtt_results_cache)) {
-		list_for_each_entry_safe(rtt_result, next, &rtt_status->rtt_results_cache, list) {
-			list_del(&rtt_result->list);
-			kfree(rtt_result);
-		}
-	}
-	MFREE(dhd->osh, dhd->rtt_state, sizeof(rtt_status_info_t));
-	dhd->rtt_state = NULL;
-	return err;
-}
-#endif /* RTT_SUPPORT */
diff --git a/drivers/net/wireless/bcmdhd/dhd_rtt.h b/drivers/net/wireless/bcmdhd/dhd_rtt.h
deleted file mode 100644
index 2fbb9c9..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_rtt.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Broadcom Dongle Host Driver (DHD), RTT
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- * $Id: dhd_rtt.h 558438 2015-05-22 06:05:11Z $
- */
-#ifndef __DHD_RTT_H__
-#define __DHD_RTT_H__
-
-#include "dngl_stats.h"
-
-#define RTT_MAX_TARGET_CNT	10
-#define RTT_MAX_FRAME_CNT	25
-#define RTT_MAX_RETRY_CNT	10
-#define DEFAULT_FTM_CNT		6
-#define DEFAULT_RETRY_CNT	6
-
-
-/* DSSS, CCK and 802.11n rates in [500kbps] units */
-#define WL_MAXRATE	108	/* in 500kbps units */
-#define WL_RATE_1M	2	/* in 500kbps units */
-#define WL_RATE_2M	4	/* in 500kbps units */
-#define WL_RATE_5M5	11	/* in 500kbps units */
-#define WL_RATE_11M	22	/* in 500kbps units */
-#define WL_RATE_6M	12	/* in 500kbps units */
-#define WL_RATE_9M	18	/* in 500kbps units */
-#define WL_RATE_12M	24	/* in 500kbps units */
-#define WL_RATE_18M	36	/* in 500kbps units */
-#define WL_RATE_24M	48	/* in 500kbps units */
-#define WL_RATE_36M	72	/* in 500kbps units */
-#define WL_RATE_48M	96	/* in 500kbps units */
-#define WL_RATE_54M	108	/* in 500kbps units */
-
-
-enum rtt_role {
-	RTT_INITIATOR = 0,
-	RTT_TARGET = 1
-};
-enum rtt_status {
-	RTT_STOPPED = 0,
-	RTT_STARTED = 1
-};
-typedef int64_t wifi_timestamp; /* In microseconds (us) */
-typedef int64_t wifi_timespan;
-typedef int wifi_rssi;
-
-typedef enum {
-	RTT_INVALID,
-	RTT_ONE_WAY,
-	RTT_TWO_WAY,
-	RTT_AUTO
-} rtt_type_t;
-
-typedef enum {
-	RTT_PEER_STA,
-	RTT_PEER_AP,
-	RTT_PEER_P2P,
-	RTT_PEER_NAN,
-	RTT_PEER_INVALID
-} rtt_peer_type_t;
-
-typedef enum rtt_reason {
-	RTT_REASON_SUCCESS,
-	RTT_REASON_FAILURE,
-	RTT_REASON_NO_RSP,
-	RTT_REASON_REJECTED,
-	RTT_REASON_NOT_SCHEDULED_YET,
-	RTT_REASON_TIMEOUT,
-	RTT_REASON_AP_ON_DIFF_CH,
-	RTT_REASON_AP_NO_CAP,
-	RTT_REASON_ABORT
-} rtt_reason_t;
-
-typedef enum rtt_capability {
-	RTT_CAP_NONE = 0,
-	RTT_CAP_ONE_WAY	 = (1 << (0)),
-	RTT_CAP_11V_WAY  = (1 << (1)),  /* IEEE802.11v */
-	RTT_CAP_11MC_WAY  = (1 << (2)), /* IEEE802.11mc */
-	RTT_CAP_VS_WAY = (1 << (3)) /* BRCM vendor specific */
-} rtt_capability_t;
-
-typedef struct wifi_channel_info {
-	wifi_channel_width_t width;
-	wifi_channel center_freq; /* primary 20 MHz channel */
-	wifi_channel center_freq0; /* center freq (MHz) first segment */
-	wifi_channel center_freq1; /* center freq (MHz) second segment valid for 80 + 80 */
-} wifi_channel_info_t;
-
-typedef struct wifi_rate {
-	uint32 preamble :3; /* 0: OFDM, 1: CCK, 2 : HT, 3: VHT, 4..7 reserved */
-	uint32 nss		:2; /* 0 : 1x1, 1: 2x2, 3: 3x3, 4: 4x4 */
-	uint32 bw		:3; /* 0: 20Mhz, 1: 40Mhz, 2: 80Mhz, 3: 160Mhz */
-	/* OFDM/CCK rate code would be as per IEEE std in the unit of 0.5 mb
-	* HT/VHT it would be mcs index
-	*/
-	uint32 rateMcsIdx :8;
-	uint32 reserved :16; /* reserved */
-	uint32 bitrate;	/* unit of 100 Kbps */
-} wifi_rate_t;
-
-typedef struct rtt_target_info {
-	struct ether_addr addr;
-	rtt_type_t type; /* rtt_type */
-	rtt_peer_type_t peer; /* peer type */
-	wifi_channel_info_t channel; /* channel information */
-	chanspec_t chanspec; /* chanspec for channel */
-	int8	continuous; /* 0 = single shot or 1 = continous raging */
-	bool	disable; /* disable for RTT measurement */
-	uint32	interval; /* interval of RTT measurement (unit ms) when continuous = true */
-	uint32	measure_cnt; /* total number of RTT measurement when continuous */
-	uint32	ftm_cnt; /* num of packets in each RTT measurement */
-	uint32	retry_cnt; /* num of retries if sampling fails */
-} rtt_target_info_t;
-
-typedef struct rtt_result {
-	struct list_head list;
-	uint16 ver;			/* version */
-	rtt_target_info_t *target_info; /* target info */
-	uint16 mode;			/* mode: target/initiator */
-	uint16 method;			/* method: rssi/TOF/AOA */
-	uint8  err_code;		/* error classification */
-	uint8  TOF_type;		/* one way or two way TOF */
-	wifi_rate_t tx_rate;           /* tx rate */
-	struct ether_addr peer_mac;	/* (e.g for tgt:initiator's */
-	int32 distance;		/* dst to tgt, units (meter * 16) */
-	uint32 meanrtt;			/* mean delta */
-	uint32 modertt;			/* Mode delta */
-	uint32 medianrtt;		/* median RTT */
-	uint32 sdrtt;			/* Standard deviation of RTT */
-	int16  avg_rssi;		/* avg rssi across the ftm frames */
-	int16  validfrmcnt;		/* Firmware's valid frame counts */
-	wifi_timestamp ts; /* the time elapsed from boot time when driver get this result */
-	uint16 ftm_cnt;			/*  num of rtd measurments/length in the ftm buffer  */
-	ftm_sample_t ftm_buff[1];	/* 1 ... ftm_cnt  */
-} rtt_result_t;
-
-typedef struct rtt_report {
-	struct ether_addr addr;
-	uint num_measurement; /* measurement number in case of continous raging */
-	rtt_reason_t status; /* raging status */
-	rtt_type_t type; /* rtt type */
-	rtt_peer_type_t peer; /* peer type */
-	wifi_channel_info_t channel; /* channel information */
-	wifi_rssi  rssi; /* avg rssi accroos the ftm frames */
-	wifi_rssi  rssi_spread; /* rssi spread in 0.5 db steps e.g. 5 implies 2.5 spread */
-	wifi_rate_t tx_rate;           /* tx rate */
-	wifi_timespan rtt;	/*  round trip time in nanoseconds */
-	wifi_timespan rtt_sd;	/* rtt standard deviation in nanoseconds */
-	wifi_timespan rtt_spread; /* difference between max and min rtt times recorded */
-	int32 distance; /* distance in cm (optional) */
-	int32 distance_sd; /* standard deviation in cm (optional) */
-	int32 distance_spread; /* difference between max and min distance recorded (optional) */
-	wifi_timestamp ts; /* time of the measurement (in microseconds since boot) */
-} rtt_report_t;
-
-/* RTT Capabilities */
-typedef struct rtt_capabilities {
-	uint8 rtt_one_sided_supported;  /* if 1-sided rtt data collection is supported */
-	uint8 rtt_11v_supported;        /* if 11v rtt data collection is supported */
-	uint8 rtt_ftm_supported;        /* if ftm rtt data collection is supported */
-	uint8 rtt_vs_supported;		/* if vendor specific data collection supported */
-} rtt_capabilities_t;
-
-typedef struct rtt_config_params {
-	int8 rtt_target_cnt;
-	rtt_target_info_t target_info[RTT_MAX_TARGET_CNT];
-} rtt_config_params_t;
-
-typedef void (*dhd_rtt_compl_noti_fn)(void *ctx, void *rtt_data);
-/* Linux wrapper to call common dhd_rtt_set_cfg */
-int
-dhd_dev_rtt_set_cfg(struct net_device *dev, void *buf);
-
-int
-dhd_dev_rtt_cancel_cfg(struct net_device *dev, struct ether_addr *mac_list, int mac_cnt);
-
-int
-dhd_dev_rtt_register_noti_callback(struct net_device *dev, void *ctx,
-	dhd_rtt_compl_noti_fn noti_fn);
-
-int
-dhd_dev_rtt_unregister_noti_callback(struct net_device *dev, dhd_rtt_compl_noti_fn noti_fn);
-
-int
-dhd_dev_rtt_capability(struct net_device *dev, rtt_capabilities_t *capa);
-
-/* export to upper layer */
-chanspec_t
-dhd_rtt_convert_to_chspec(wifi_channel_info_t channel);
-
-int
-dhd_rtt_set_cfg(dhd_pub_t *dhd, rtt_config_params_t *params);
-
-int
-dhd_rtt_stop(dhd_pub_t *dhd, struct ether_addr *mac_list, int mac_cnt);
-
-
-int
-dhd_rtt_register_noti_callback(dhd_pub_t *dhd, void *ctx, dhd_rtt_compl_noti_fn noti_fn);
-
-int
-dhd_rtt_unregister_noti_callback(dhd_pub_t *dhd, dhd_rtt_compl_noti_fn noti_fn);
-
-int
-dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data);
-
-int
-dhd_rtt_capability(dhd_pub_t *dhd, rtt_capabilities_t *capa);
-
-int
-dhd_rtt_init(dhd_pub_t *dhd);
-
-int
-dhd_rtt_deinit(dhd_pub_t *dhd);
-#endif /* __DHD_RTT_H__ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
deleted file mode 100644
index a4e6e3a..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ /dev/null
@@ -1,8407 +0,0 @@
-/*
- * DHD Bus Module for SDIO
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_sdio.c 593728 2015-10-19 09:20:32Z $
- */
-
-#include <typedefs.h>
-#include <osl.h>
-#include <bcmsdh.h>
-
-#ifdef BCMEMBEDIMAGE
-#include BCMEMBEDIMAGE
-#endif /* BCMEMBEDIMAGE */
-
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <bcmendian.h>
-#include <bcmdevs.h>
-
-#include <siutils.h>
-#include <hndpmu.h>
-#include <hndsoc.h>
-#include <bcmsdpcm.h>
-#include <hnd_armtrap.h>
-#include <hnd_cons.h>
-#include <sbchipc.h>
-#include <sbhnddma.h>
-
-#include <sdio.h>
-#include <sbsdio.h>
-#include <sbsdpcmdev.h>
-#include <bcmsdpcm.h>
-#include <bcmsdbus.h>
-
-#include <proto/ethernet.h>
-#include <proto/802.1d.h>
-#include <proto/802.11.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#include <dhdioctl.h>
-#include <sdiovar.h>
-
-#ifdef PROP_TXSTATUS
-#include <dhd_wlfc.h>
-#endif
-#ifdef DHDTCPACK_SUPPRESS
-#include <dhd_ip.h>
-#endif /* DHDTCPACK_SUPPRESS */
-
-bool dhd_mp_halting(dhd_pub_t *dhdp);
-extern void bcmsdh_waitfor_iodrain(void *sdh);
-extern void bcmsdh_reject_ioreqs(void *sdh, bool reject);
-extern bool  bcmsdh_fatal_error(void *sdh);
-
-#ifndef DHDSDIO_MEM_DUMP_FNAME
-#define DHDSDIO_MEM_DUMP_FNAME         "mem_dump"
-#endif
-
-#define QLEN		(1024) /* bulk rx and tx queue lengths */
-#define FCHI		(QLEN - 10)
-#define FCLOW		(FCHI / 2)
-#define PRIOMASK	7
-
-#define TXRETRIES	2	/* # of retries for tx frames */
-#define READ_FRM_CNT_RETRIES	3
-#ifndef DHD_RXBOUND
-#define DHD_RXBOUND	50	/* Default for max rx frames in one scheduling */
-#endif
-
-#ifndef DHD_TXBOUND
-#define DHD_TXBOUND	20	/* Default for max tx frames in one scheduling */
-#endif
-
-#define DHD_TXMINMAX	1	/* Max tx frames if rx still pending */
-
-#define MEMBLOCK	2048		/* Block size used for downloading of dongle image */
-#define MAX_DATA_BUF	(64 * 1024)	/* Must be large enough to hold biggest possible glom */
-
-#ifndef DHD_FIRSTREAD
-#define DHD_FIRSTREAD   32
-#endif
-#if !ISPOWEROF2(DHD_FIRSTREAD)
-#error DHD_FIRSTREAD is not a power of 2!
-#endif
-
-/* Total length of frame header for dongle protocol */
-#define SDPCM_HDRLEN	(SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
-#define SDPCM_HDRLEN_TXGLOM	(SDPCM_HDRLEN + SDPCM_HWEXT_LEN)
-#define MAX_TX_PKTCHAIN_CNT	SDPCM_MAXGLOM_SIZE
-
-#ifdef SDTEST
-#define SDPCM_RESERVE	(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
-#else
-#define SDPCM_RESERVE	(SDPCM_HDRLEN + DHD_SDALIGN)
-#endif
-
-/* Space for header read, limit for data packets */
-#ifndef MAX_HDR_READ
-#define MAX_HDR_READ	32
-#endif
-#if !ISPOWEROF2(MAX_HDR_READ)
-#error MAX_HDR_READ is not a power of 2!
-#endif
-
-#define MAX_RX_DATASZ	2048
-
-/* Maximum milliseconds to wait for F2 to come up */
-#define DHD_WAIT_F2RDY	3000
-
-/* Bump up limit on waiting for HT to account for first startup;
- * if the image is doing a CRC calculation before programming the PMU
- * for HT availability, it could take a couple hundred ms more, so
- * max out at a 1 second (1000000us).
- */
-#if (PMU_MAX_TRANSITION_DLY <= 1000000)
-#undef PMU_MAX_TRANSITION_DLY
-#define PMU_MAX_TRANSITION_DLY 1000000
-#endif
-
-/* hooks for limiting threshold custom tx num in rx processing */
-#define DEFAULT_TXINRX_THRES    0
-#ifndef CUSTOM_TXINRX_THRES
-#define CUSTOM_TXINRX_THRES     DEFAULT_TXINRX_THRES
-#endif
-
-/* Value for ChipClockCSR during initial setup */
-#define DHD_INIT_CLKCTL1	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
-#define DHD_INIT_CLKCTL2	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
-
-/* Flags for SDH calls */
-#define F2SYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
-
-/* Packet free applicable unconditionally for sdio and sdspi.  Conditional if
- * bufpool was present for gspi bus.
- */
-#define PKTFREE2()		if ((bus->bus != SPI_BUS) || bus->usebufpool) \
-					PKTFREE(bus->dhd->osh, pkt, FALSE);
-DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
-
-
-/* Device console log buffer state */
-#define CONSOLE_LINE_MAX	192
-#define CONSOLE_BUFFER_MAX	2024
-typedef struct dhd_console {
-	uint		count;			/* Poll interval msec counter */
-	uint		log_addr;		/* Log struct address (fixed) */
-	hnd_log_t	log;			/* Log struct (host copy) */
-	uint		bufsize;		/* Size of log buffer */
-	uint8		*buf;			/* Log buffer (host copy) */
-	uint		last;			/* Last buffer read index */
-} dhd_console_t;
-
-#define	REMAP_ENAB(bus)			((bus)->remap)
-#define	REMAP_ISADDR(bus, a)		(((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize)))
-#define	KSO_ENAB(bus)			((bus)->kso)
-#define	SR_ENAB(bus)			((bus)->_srenab)
-#define	SLPAUTO_ENAB(bus)		((SR_ENAB(bus)) && ((bus)->_slpauto))
-#define	MIN_RSRC_ADDR			(SI_ENUM_BASE + 0x618)
-#define	MIN_RSRC_SR			0x3
-#define	CORE_CAPEXT_ADDR		(SI_ENUM_BASE + 0x64c)
-#define	CORE_CAPEXT_SR_SUPPORTED_MASK	(1 << 1)
-#define RCTL_MACPHY_DISABLE_MASK	(1 << 26)
-#define RCTL_LOGIC_DISABLE_MASK		(1 << 27)
-
-#define	OOB_WAKEUP_ENAB(bus)		((bus)->_oobwakeup)
-#define	GPIO_DEV_SRSTATE		16	/* Host gpio17 mapped to device gpio0 SR state */
-#define	GPIO_DEV_SRSTATE_TIMEOUT	320000	/* 320ms */
-#define	GPIO_DEV_WAKEUP			17	/* Host gpio17 mapped to device gpio1 wakeup */
-#define	CC_CHIPCTRL2_GPIO1_WAKEUP	(1  << 0)
-#define	CC_CHIPCTRL3_SR_ENG_ENABLE	(1  << 2)
-#define OVERFLOW_BLKSZ512_WM		96
-#define OVERFLOW_BLKSZ512_MES		80
-
-#define CC_PMUCC3	(0x3)
-/* Private data for SDIO bus interaction */
-typedef struct dhd_bus {
-	dhd_pub_t	*dhd;
-
-	bcmsdh_info_t	*sdh;			/* Handle for BCMSDH calls */
-	si_t		*sih;			/* Handle for SI calls */
-	char		*vars;			/* Variables (from CIS and/or other) */
-	uint		varsz;			/* Size of variables buffer */
-	uint32		sbaddr;			/* Current SB window pointer (-1, invalid) */
-
-	sdpcmd_regs_t	*regs;			/* Registers for SDIO core */
-	uint		sdpcmrev;		/* SDIO core revision */
-	uint		armrev;			/* CPU core revision */
-	uint		ramrev;			/* SOCRAM core revision */
-	uint32		ramsize;		/* Size of RAM in SOCRAM (bytes) */
-	uint32		orig_ramsize;		/* Size of RAM in SOCRAM (bytes) */
-	uint32		srmemsize;		/* Size of SRMEM */
-
-	uint32		bus;			/* gSPI or SDIO bus */
-	uint32		bus_num;		/* bus number */
-	uint32		slot_num;		/* slot ID */
-	uint32		hostintmask;	/* Copy of Host Interrupt Mask */
-	uint32		intstatus;		/* Intstatus bits (events) pending */
-	bool		dpc_sched;		/* Indicates DPC schedule (intrpt rcvd) */
-	bool		fcstate;		/* State of dongle flow-control */
-
-	uint16		cl_devid;		/* cached devid for dhdsdio_probe_attach() */
-	char		*fw_path;		/* module_param: path to firmware image */
-	char		*nv_path;		/* module_param: path to nvram vars file */
-
-	uint		blocksize;		/* Block size of SDIO transfers */
-	uint		roundup;		/* Max roundup limit */
-
-	struct pktq	txq;			/* Queue length used for flow-control */
-	uint8		flowcontrol;		/* per prio flow control bitmask */
-	uint8		tx_seq;			/* Transmit sequence number (next) */
-	uint8		tx_max;			/* Maximum transmit sequence allowed */
-
-	uint8		hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
-	uint8		*rxhdr;			/* Header of current rx frame (in hdrbuf) */
-	uint16		nextlen;		/* Next Read Len from last header */
-	uint8		rx_seq;			/* Receive sequence number (expected) */
-	bool		rxskip;			/* Skip receive (awaiting NAK ACK) */
-
-	void		*glomd;			/* Packet containing glomming descriptor */
-	void		*glom;			/* Packet chain for glommed superframe */
-	uint		glomerr;		/* Glom packet read errors */
-
-	uint8		*rxbuf;			/* Buffer for receiving control packets */
-	uint		rxblen;			/* Allocated length of rxbuf */
-	uint8		*rxctl;			/* Aligned pointer into rxbuf */
-	uint8		*databuf;		/* Buffer for receiving big glom packet */
-	uint8		*dataptr;		/* Aligned pointer into databuf */
-	uint		rxlen;			/* Length of valid data in buffer */
-
-	uint8		sdpcm_ver;		/* Bus protocol reported by dongle */
-
-	bool		intr;			/* Use interrupts */
-	bool		poll;			/* Use polling */
-	bool		ipend;			/* Device interrupt is pending */
-	bool		intdis;			/* Interrupts disabled by isr */
-	uint 		intrcount;		/* Count of device interrupt callbacks */
-	uint		lastintrs;		/* Count as of last watchdog timer */
-	uint		spurious;		/* Count of spurious interrupts */
-	uint		pollrate;		/* Ticks between device polls */
-	uint		polltick;		/* Tick counter */
-	uint		pollcnt;		/* Count of active polls */
-
-#ifdef DHD_DEBUG
-	dhd_console_t	console;		/* Console output polling support */
-	uint		console_addr;		/* Console address from shared struct */
-#endif /* DHD_DEBUG */
-
-	uint		regfails;		/* Count of R_REG/W_REG failures */
-
-	uint		clkstate;		/* State of sd and backplane clock(s) */
-	bool		activity;		/* Activity flag for clock down */
-	int32		idletime;		/* Control for activity timeout */
-	int32		idlecount;		/* Activity timeout counter */
-	int32		idleclock;		/* How to set bus driver when idle */
-	int32		sd_divisor;		/* Speed control to bus driver */
-	int32		sd_mode;		/* Mode control to bus driver */
-	int32		sd_rxchain;		/* If bcmsdh api accepts PKT chains */
-	bool		use_rxchain;		/* If dhd should use PKT chains */
-	bool		sleeping;		/* Is SDIO bus sleeping? */
-#if defined(SUPPORT_P2P_GO_PS)
-	wait_queue_head_t bus_sleep;
-#endif /* LINUX && SUPPORT_P2P_GO_PS */
-	uint		rxflow_mode;		/* Rx flow control mode */
-	bool		rxflow;			/* Is rx flow control on */
-	uint		prev_rxlim_hit;		/* Is prev rx limit exceeded (per dpc schedule) */
-	bool		alp_only;		/* Don't use HT clock (ALP only) */
-	/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
-	bool		usebufpool;
-	int32		txinrx_thres;	/* num of in-queued pkts */
-	int32		dotxinrx;	/* tx first in dhdsdio_readframes */
-#ifdef SDTEST
-	/* external loopback */
-	bool		ext_loop;
-	uint8		loopid;
-
-	/* pktgen configuration */
-	uint		pktgen_freq;		/* Ticks between bursts */
-	uint		pktgen_count;		/* Packets to send each burst */
-	uint		pktgen_print;		/* Bursts between count displays */
-	uint		pktgen_total;		/* Stop after this many */
-	uint		pktgen_minlen;		/* Minimum packet data len */
-	uint		pktgen_maxlen;		/* Maximum packet data len */
-	uint		pktgen_mode;		/* Configured mode: tx, rx, or echo */
-	uint		pktgen_stop;		/* Number of tx failures causing stop */
-
-	/* active pktgen fields */
-	uint		pktgen_tick;		/* Tick counter for bursts */
-	uint		pktgen_ptick;		/* Burst counter for printing */
-	uint		pktgen_sent;		/* Number of test packets generated */
-	uint		pktgen_rcvd;		/* Number of test packets received */
-	uint		pktgen_prev_time;	/* Time at which previous stats where printed */
-	uint		pktgen_prev_sent;	/* Number of test packets generated when
-						 * previous stats were printed
-						 */
-	uint		pktgen_prev_rcvd;	/* Number of test packets received when
-						 * previous stats were printed
-						 */
-	uint		pktgen_fail;		/* Number of failed send attempts */
-	uint16		pktgen_len;		/* Length of next packet to send */
-#define PKTGEN_RCV_IDLE     (0)
-#define PKTGEN_RCV_ONGOING  (1)
-	uint16		pktgen_rcv_state;		/* receive state */
-	uint		pktgen_rcvd_rcvsession;	/* test pkts rcvd per rcv session. */
-#endif /* SDTEST */
-
-	/* Some additional counters */
-	uint		tx_sderrs;		/* Count of tx attempts with sd errors */
-	uint		fcqueued;		/* Tx packets that got queued */
-	uint		rxrtx;			/* Count of rtx requests (NAK to dongle) */
-	uint		rx_toolong;		/* Receive frames too long to receive */
-	uint		rxc_errors;		/* SDIO errors when reading control frames */
-	uint		rx_hdrfail;		/* SDIO errors on header reads */
-	uint		rx_badhdr;		/* Bad received headers (roosync?) */
-	uint		rx_badseq;		/* Mismatched rx sequence number */
-	uint		fc_rcvd;		/* Number of flow-control events received */
-	uint		fc_xoff;		/* Number which turned on flow-control */
-	uint		fc_xon;			/* Number which turned off flow-control */
-	uint		rxglomfail;		/* Failed deglom attempts */
-	uint		rxglomframes;		/* Number of glom frames (superframes) */
-	uint		rxglompkts;		/* Number of packets from glom frames */
-	uint		f2rxhdrs;		/* Number of header reads */
-	uint		f2rxdata;		/* Number of frame data reads */
-	uint		f2txdata;		/* Number of f2 frame writes */
-	uint		f1regdata;		/* Number of f1 register accesses */
-#ifdef DHDENABLE_TAILPAD
-	uint		tx_tailpad_chain;	/* Number of tail padding by chaining pad_pkt */
-	uint		tx_tailpad_pktget;	/* Number of tail padding by new PKTGET */
-#endif /* DHDENABLE_TAILPAD */
-	uint8		*ctrl_frame_buf;
-	uint32		ctrl_frame_len;
-	bool		ctrl_frame_stat;
-	uint32		rxint_mode;	/* rx interrupt mode */
-	bool		remap;		/* Contiguous 1MB RAM: 512K socram + 512K devram
-					 * Available with socram rev 16
-					 * Remap region not DMA-able
-					 */
-	bool		kso;
-	bool		_slpauto;
-	bool		_oobwakeup;
-	bool		_srenab;
-	bool        readframes;
-	bool        reqbussleep;
-	uint32		resetinstr;
-	uint32		dongle_ram_base;
-
-	void		*glom_pkt_arr[SDPCM_MAXGLOM_SIZE];	/* Array of pkts for glomming */
-	uint32		txglom_cnt;	/* Number of pkts in the glom array */
-	uint32		txglom_total_len;	/* Total length of pkts in glom array */
-	bool		txglom_enable;	/* Flag to indicate whether tx glom is enabled/disabled */
-	uint32		txglomsize;	/* Glom size limitation */
-#ifdef DHDENABLE_TAILPAD
-	void		*pad_pkt;
-#endif /* DHDENABLE_TAILPAD */
-} dhd_bus_t;
-
-/* clkstate */
-#define CLK_NONE	0
-#define CLK_SDONLY	1
-#define CLK_PENDING	2	/* Not used yet */
-#define CLK_AVAIL	3
-
-#define DHD_NOPMU(dhd)	(FALSE)
-
-#if defined(BCMSDIOH_STD)
-#define BLK_64_MAXTXGLOM 20
-#endif /* BCMSDIOH_STD */
-
-#ifdef DHD_DEBUG
-static int qcount[NUMPRIO];
-static int tx_packets[NUMPRIO];
-#endif /* DHD_DEBUG */
-
-/* Deferred transmit */
-const uint dhd_deferred_tx = 1;
-
-extern uint dhd_watchdog_ms;
-
-extern void dhd_os_wd_timer(void *bus, uint wdtick);
-int dhd_enableOOB(dhd_pub_t *dhd, bool sleep);
-
-/* Tx/Rx bounds */
-uint dhd_txbound;
-uint dhd_rxbound;
-uint dhd_txminmax = DHD_TXMINMAX;
-
-/* override the RAM size if possible */
-#define DONGLE_MIN_RAMSIZE (128 *1024)
-int dhd_dongle_ramsize;
-
-uint dhd_doflow = TRUE;
-uint dhd_dpcpoll = FALSE;
-
-module_param(dhd_doflow, uint, 0644);
-module_param(dhd_dpcpoll, uint, 0644);
-
-static bool dhd_alignctl;
-
-static bool sd1idle;
-
-static bool retrydata;
-#define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
-
-static uint watermark = 8;
-static uint mesbusyctrl = 0;
-static const uint firstread = DHD_FIRSTREAD;
-
-/* Retry count for register access failures */
-static const uint retry_limit = 2;
-
-/* Force even SD lengths (some host controllers mess up on odd bytes) */
-static bool forcealign;
-
-#define ALIGNMENT  4
-
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
-#endif
-
-#if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
-#error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
-#endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
-#define PKTALIGN(osh, p, len, align)					\
-	do {								\
-		uintptr datalign;						\
-		datalign = (uintptr)PKTDATA((osh), (p));		\
-		datalign = ROUNDUP(datalign, (align)) - datalign;	\
-		ASSERT(datalign < (align));				\
-		ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign));	\
-		if (datalign)						\
-			PKTPULL((osh), (p), (uint)datalign);			\
-		PKTSETLEN((osh), (p), (len));				\
-	} while (0)
-
-/* Limit on rounding up frames */
-static const uint max_roundup = 512;
-
-/* Try doing readahead */
-static bool dhd_readahead;
-
-/* To check if there's window offered */
-#define DATAOK(bus) \
-	(((uint8)(bus->tx_max - bus->tx_seq) > 1) && \
-	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
-
-/* To check if there's window offered for ctrl frame */
-#define TXCTLOK(bus) \
-	(((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
-	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
-
-/* Number of pkts available in dongle for data RX */
-#define DATABUFCNT(bus) \
-	((uint8)(bus->tx_max - bus->tx_seq) - 1)
-
-/* Macros to get register read/write status */
-/* NOTE: these assume a local dhdsdio_bus_t *bus! */
-#define R_SDREG(regvar, regaddr, retryvar) \
-do { \
-	retryvar = 0; \
-	do { \
-		regvar = R_REG(bus->dhd->osh, regaddr); \
-	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
-	if (retryvar) { \
-		bus->regfails += (retryvar-1); \
-		if (retryvar > retry_limit) { \
-			DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
-			           __FUNCTION__, __LINE__)); \
-			regvar = 0; \
-		} \
-	} \
-} while (0)
-
-#define W_SDREG(regval, regaddr, retryvar) \
-do { \
-	retryvar = 0; \
-	do { \
-		W_REG(bus->dhd->osh, regaddr, regval); \
-	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
-	if (retryvar) { \
-		bus->regfails += (retryvar-1); \
-		if (retryvar > retry_limit) \
-			DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
-			           __FUNCTION__, __LINE__)); \
-	} \
-} while (0)
-
-#define BUS_WAKE(bus) \
-	do { \
-		bus->idlecount = 0; \
-		if ((bus)->sleeping) \
-			dhdsdio_bussleep((bus), FALSE); \
-	} while (0);
-
-/*
- * pktavail interrupts from dongle to host can be managed in 3 different ways
- * whenever there is a packet available in dongle to transmit to host.
- *
- * Mode 0:	Dongle writes the software host mailbox and host is interrupted.
- * Mode 1:	(sdiod core rev >= 4)
- *		Device sets a new bit in the intstatus whenever there is a packet
- *		available in fifo.  Host can't clear this specific status bit until all the
- *		packets are read from the FIFO.  No need to ack dongle intstatus.
- * Mode 2:	(sdiod core rev >= 4)
- *		Device sets a bit in the intstatus, and host acks this by writing
- *		one to this bit.  Dongle won't generate anymore packet interrupts
- *		until host reads all the packets from the dongle and reads a zero to
- *		figure that there are no more packets.  No need to disable host ints.
- *		Need to ack the intstatus.
- */
-
-#define SDIO_DEVICE_HMB_RXINT		0	/* default old way */
-#define SDIO_DEVICE_RXDATAINT_MODE_0	1	/* from sdiod rev 4 */
-#define SDIO_DEVICE_RXDATAINT_MODE_1	2	/* from sdiod rev 4 */
-
-
-#define FRAME_AVAIL_MASK(bus) 	\
-	((bus->rxint_mode == SDIO_DEVICE_HMB_RXINT) ? I_HMB_FRAME_IND : I_XMTDATA_AVAIL)
-
-#define DHD_BUS			SDIO_BUS
-
-#define PKT_AVAILABLE(bus, intstatus)	((intstatus) & (FRAME_AVAIL_MASK(bus)))
-
-#define HOSTINTMASK		(I_HMB_SW_MASK | I_CHIPACTIVE)
-
-#define GSPI_PR55150_BAILOUT
-
-#ifdef SDTEST
-static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
-static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count);
-#endif
-
-static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size);
-#ifdef DHD_DEBUG
-static int dhd_serialconsole(dhd_bus_t *bus, bool get, bool enable, int *bcmerror);
-#endif /* DHD_DEBUG */
-
-#if defined(DHD_FW_COREDUMP)
-static int dhdsdio_mem_dump(dhd_bus_t *bus);
-#endif /* DHD_FW_COREDUMP */
-static int dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap);
-static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
-
-static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
-static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh);
-static void dhdsdio_disconnect(void *ptr);
-static bool dhdsdio_chipmatch(uint16 chipid);
-static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh,
-                                 void * regsva, uint16  devid);
-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh);
-static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh);
-static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation,
-	bool reset_flag);
-
-static void dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size);
-static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
-	uint8 *buf, uint nbytes,
-	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
-static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
-	uint8 *buf, uint nbytes,
-	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry);
-static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt);
-static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
-	int prev_chain_total_len, bool last_chained_pkt,
-	int *pad_pkt_len, void **new_pkt);
-static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt);
-
-static int dhdsdio_download_firmware(dhd_bus_t *bus, osl_t *osh, void *sdh);
-static int _dhdsdio_download_firmware(dhd_bus_t *bus);
-
-static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path);
-static int dhdsdio_download_nvram(dhd_bus_t *bus);
-#ifdef BCMEMBEDIMAGE
-static int dhdsdio_download_code_array(dhd_bus_t *bus);
-#endif
-static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep);
-static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok);
-static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus);
-
-#ifdef WLMEDIA_HTSF
-#include <htsf.h>
-extern uint32 dhd_get_htsf(void *dhd, int ifidx);
-#endif /* WLMEDIA_HTSF */
-
-static void
-dhdsdio_tune_fifoparam(struct dhd_bus *bus)
-{
-	int err;
-	uint8 devctl, wm, mes;
-
-	if (bus->sih->buscorerev >= 15) {
-		/* See .ppt in PR for these recommended values */
-		if (bus->blocksize == 512) {
-			wm = OVERFLOW_BLKSZ512_WM;
-			mes = OVERFLOW_BLKSZ512_MES;
-		} else {
-			mes = bus->blocksize/4;
-			wm = bus->blocksize/4;
-		}
-
-		watermark = wm;
-		mesbusyctrl = mes;
-	} else {
-		DHD_INFO(("skip fifotune: SdioRev(%d) is lower than minimal requested ver\n",
-			bus->sih->buscorerev));
-		return;
-	}
-
-	/* Update watermark */
-	if (wm > 0) {
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, wm, &err);
-
-		devctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
-		devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
-	}
-
-	/* Update MES */
-	if (mes > 0) {
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
-			(mes | SBSDIO_MESBUSYCTRL_ENAB), &err);
-	}
-
-	DHD_INFO(("Apply overflow WAR: 0x%02x 0x%02x 0x%02x\n",
-		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err),
-		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, &err),
-		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, &err)));
-}
-
-static void
-dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size)
-{
-	int32 min_size =  DONGLE_MIN_RAMSIZE;
-	/* Restrict the ramsize to user specified limit */
-	DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
-		dhd_dongle_ramsize, min_size));
-	if ((dhd_dongle_ramsize > min_size) &&
-		(dhd_dongle_ramsize < (int32)bus->orig_ramsize))
-		bus->ramsize = dhd_dongle_ramsize;
-}
-
-static int
-dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address)
-{
-	int err = 0;
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
-	                 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
-	if (!err)
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
-		                 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
-	if (!err)
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
-		                 (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
-	return err;
-}
-
-
-#ifdef USE_OOB_GPIO1
-static int
-dhdsdio_oobwakeup_init(dhd_bus_t *bus)
-{
-	uint32 val, addr, data;
-
-	bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP);
-
-	addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
-	data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
-
-	/* Set device for gpio1 wakeup */
-	bcmsdh_reg_write(bus->sdh, addr, 4, 2);
-	val = bcmsdh_reg_read(bus->sdh, data, 4);
-	val |= CC_CHIPCTRL2_GPIO1_WAKEUP;
-	bcmsdh_reg_write(bus->sdh, data, 4, val);
-
-	bus->_oobwakeup = TRUE;
-
-	return 0;
-}
-#endif /* USE_OOB_GPIO1 */
-
-/*
- * Query if FW is in SR mode
- */
-static bool
-dhdsdio_sr_cap(dhd_bus_t *bus)
-{
-	bool cap = FALSE;
-	uint32  core_capext, addr, data;
-
-	if (bus->sih->chip == BCM43430_CHIP_ID) {
-		/* check if fw initialized sr engine */
-		addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, sr_control1);
-		if (bcmsdh_reg_read(bus->sdh, addr, 4) != 0)
-			cap = TRUE;
-
-		return cap;
-	}
-	if (bus->sih->chip == BCM4324_CHIP_ID) {
-			addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
-			data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
-			bcmsdh_reg_write(bus->sdh, addr, 4, 3);
-			core_capext = bcmsdh_reg_read(bus->sdh, data, 4);
-	} else if (bus->sih->chip == BCM4330_CHIP_ID) {
-			core_capext = FALSE;
-	} else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
-		(bus->sih->chip == BCM4339_CHIP_ID) ||
-		(bus->sih->chip == BCM43349_CHIP_ID) ||
-		(bus->sih->chip == BCM4345_CHIP_ID) ||
-		(bus->sih->chip == BCM43454_CHIP_ID) ||
-		(bus->sih->chip == BCM4354_CHIP_ID) ||
-		(bus->sih->chip == BCM4356_CHIP_ID) ||
-		(bus->sih->chip == BCM4358_CHIP_ID) ||
-		(BCM4349_CHIP(bus->sih->chip))		||
-		(bus->sih->chip == BCM4350_CHIP_ID)) {
-		core_capext = TRUE;
-	} else {
-			core_capext = bcmsdh_reg_read(bus->sdh, CORE_CAPEXT_ADDR, 4);
-			core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
-	}
-	if (!(core_capext))
-		return FALSE;
-
-	if (bus->sih->chip == BCM4324_CHIP_ID) {
-		/* FIX: Should change to query SR control register instead */
-		cap = TRUE;
-	} else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
-		(bus->sih->chip == BCM4339_CHIP_ID) ||
-		(bus->sih->chip == BCM43349_CHIP_ID) ||
-		(bus->sih->chip == BCM4345_CHIP_ID) ||
-		(bus->sih->chip == BCM43454_CHIP_ID) ||
-		(bus->sih->chip == BCM4354_CHIP_ID) ||
-		(bus->sih->chip == BCM4356_CHIP_ID) ||
-		(bus->sih->chip == BCM4358_CHIP_ID) ||
-		(bus->sih->chip == BCM4350_CHIP_ID)) {
-		uint32 enabval = 0;
-		addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
-		data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
-		bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3);
-		enabval = bcmsdh_reg_read(bus->sdh, data, 4);
-
-		if ((bus->sih->chip == BCM4350_CHIP_ID) ||
-			(bus->sih->chip == BCM4345_CHIP_ID) ||
-			(bus->sih->chip == BCM43454_CHIP_ID) ||
-			(bus->sih->chip == BCM4354_CHIP_ID) ||
-			(bus->sih->chip == BCM4356_CHIP_ID) ||
-			(bus->sih->chip == BCM4358_CHIP_ID))
-			enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE;
-
-		if (enabval)
-			cap = TRUE;
-	} else {
-		data = bcmsdh_reg_read(bus->sdh,
-			SI_ENUM_BASE + OFFSETOF(chipcregs_t, retention_ctl), 4);
-		if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0)
-			cap = TRUE;
-	}
-
-	return cap;
-}
-
-static int
-dhdsdio_srwar_init(dhd_bus_t *bus)
-{
-	bcmsdh_gpio_init(bus->sdh);
-
-#ifdef USE_OOB_GPIO1
-	dhdsdio_oobwakeup_init(bus);
-#endif
-
-
-	return 0;
-}
-
-static int
-dhdsdio_sr_init(dhd_bus_t *bus)
-{
-	uint8 val;
-	int err = 0;
-
-	if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2))
-		dhdsdio_srwar_init(bus);
-
-	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
-	val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
-		1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
-	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
-
-#ifdef USE_CMD14
-	/* Add CMD14 Support */
-	dhdsdio_devcap_set(bus,
-		(SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT));
-#endif /* USE_CMD14 */
-
-	dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC);
-
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
-		SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
-
-	bus->_slpauto = dhd_slpauto ? TRUE : FALSE;
-
-	bus->_srenab = TRUE;
-
-	return 0;
-}
-
-/*
- * FIX: Be sure KSO bit is enabled
- * Currently, it's defaulting to 0 which should be 1.
- */
-static int
-dhdsdio_clk_kso_init(dhd_bus_t *bus)
-{
-	uint8 val;
-	int err = 0;
-
-	/* set flag */
-	bus->kso = TRUE;
-
-	/*
-	 * Enable KeepSdioOn (KSO) bit for normal operation
-	 * Default is 0 (4334A0) so set it. Fixed in B0.
-	 */
-	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, NULL);
-	if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
-		val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, val, &err);
-		if (err)
-			DHD_ERROR(("%s: SBSDIO_FUNC1_SLEEPCSR err: 0x%x\n", __FUNCTION__, err));
-	}
-
-	return 0;
-}
-
-#define KSO_DBG(x)
-#define KSO_WAIT_US 50
-#define KSO_WAIT_MS 1
-#define KSO_SLEEP_RETRY_COUNT 20
-#define KSO_WAKE_RETRY_COUNT 100
-#define ERROR_BCME_NODEVICE_MAX 1
-
-#define DEFAULT_MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
-#ifndef CUSTOM_MAX_KSO_ATTEMPTS
-#define CUSTOM_MAX_KSO_ATTEMPTS DEFAULT_MAX_KSO_ATTEMPTS
-#endif
-
-static int
-dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on)
-{
-	uint8 wr_val = 0, rd_val, cmp_val, bmask;
-	int err = 0;
-	int try_cnt = 0;
-
-	KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR")));
-
-	wr_val |= (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
-
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
-
-	if (on) {
-		cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |  SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
-		bmask = cmp_val;
-
-		OSL_SLEEP(3);
-
-	} else {
-		/* Put device to sleep, turn off  KSO  */
-		cmp_val = 0;
-		bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
-	}
-
-	do {
-		rd_val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
-		if (((rd_val & bmask) == cmp_val) && !err)
-			break;
-
-		KSO_DBG(("%s> KSO wr/rd retry:%d, ERR:%x \n", __FUNCTION__, try_cnt, err));
-
-		if (((try_cnt + 1) % KSO_SLEEP_RETRY_COUNT) == 0) {
-			OSL_SLEEP(KSO_WAIT_MS);
-		} else
-			OSL_DELAY(KSO_WAIT_US);
-
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
-	} while (try_cnt++ < CUSTOM_MAX_KSO_ATTEMPTS);
-
-
-	if (try_cnt > 2)
-		KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n",
-			__FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
-
-	if (try_cnt > CUSTOM_MAX_KSO_ATTEMPTS)  {
-		DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n",
-			__FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
-	}
-
-	return err;
-}
-
-static int
-dhdsdio_clk_kso_iovar(dhd_bus_t *bus, bool on)
-{
-	int err = 0;
-
-	if (on == FALSE) {
-
-		BUS_WAKE(bus);
-		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-		DHD_ERROR(("%s: KSO disable clk: 0x%x\n", __FUNCTION__,
-			bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
-			SBSDIO_FUNC1_CHIPCLKCSR, &err)));
-		dhdsdio_clk_kso_enab(bus, FALSE);
-	} else {
-		DHD_ERROR(("%s: KSO enable\n", __FUNCTION__));
-
-		/* Make sure we have SD bus access */
-		if (bus->clkstate == CLK_NONE) {
-			DHD_ERROR(("%s: Request SD clk\n", __FUNCTION__));
-			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-		}
-
-		dhdsdio_clk_kso_enab(bus, TRUE);
-
-		DHD_ERROR(("%s: sleepcsr: 0x%x\n", __FUNCTION__,
-			dhdsdio_sleepcsr_get(bus)));
-	}
-
-	bus->kso = on;
-	BCM_REFERENCE(err);
-
-	return 0;
-}
-
-static uint8
-dhdsdio_sleepcsr_get(dhd_bus_t *bus)
-{
-	int err = 0;
-	uint8 val = 0;
-
-	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
-	if (err)
-		DHD_TRACE(("Failed to read SLEEPCSR: %d\n", err));
-
-	return val;
-}
-
-uint8
-dhdsdio_devcap_get(dhd_bus_t *bus)
-{
-	return bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, NULL);
-}
-
-static int
-dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap)
-{
-	int err = 0;
-
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, cap, &err);
-	if (err)
-		DHD_ERROR(("%s: devcap set err: 0x%x\n", __FUNCTION__, err));
-
-	return 0;
-}
-
-static int
-dhdsdio_clk_devsleep_iovar(dhd_bus_t *bus, bool on)
-{
-	int err = 0, retry;
-	uint8 val;
-
-	retry = 0;
-	if (on == TRUE) {
-		/* Enter Sleep */
-
-		/* Be sure we request clk before going to sleep
-		 * so we can wake-up with clk request already set
-		 * else device can go back to sleep immediately
-		 */
-		if (!SLPAUTO_ENAB(bus))
-			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-		else {
-			val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
-			if ((val & SBSDIO_CSR_MASK) == 0) {
-				DHD_ERROR(("%s: No clock before enter sleep:0x%x\n",
-					__FUNCTION__, val));
-
-				/* Reset clock request */
-				bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-					SBSDIO_ALP_AVAIL_REQ, &err);
-				DHD_ERROR(("%s: clock before sleep:0x%x\n", __FUNCTION__,
-					bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
-					SBSDIO_FUNC1_CHIPCLKCSR, &err)));
-			}
-		}
-
-		DHD_TRACE(("%s: clk before sleep: 0x%x\n", __FUNCTION__,
-			bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
-			SBSDIO_FUNC1_CHIPCLKCSR, &err)));
-#ifdef USE_CMD14
-		err = bcmsdh_sleep(bus->sdh, TRUE);
-#else
-
-
-		err = dhdsdio_clk_kso_enab(bus, FALSE);
-		if (OOB_WAKEUP_ENAB(bus))
-		{
-			err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, FALSE);  /* GPIO_1 is off */
-		}
-#endif /* USE_CMD14 */
-	} else {
-		/* Exit Sleep */
-		/* Make sure we have SD bus access */
-		if (bus->clkstate == CLK_NONE) {
-			DHD_TRACE(("%s: Request SD clk\n", __FUNCTION__));
-			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-		}
-
-		if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) {
-			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
-				(bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) != TRUE),
-				GPIO_DEV_SRSTATE_TIMEOUT);
-
-			if (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) == FALSE) {
-				DHD_ERROR(("ERROR: GPIO_DEV_SRSTATE still low!\n"));
-			}
-		}
-#ifdef USE_CMD14
-		err = bcmsdh_sleep(bus->sdh, FALSE);
-		if (SLPAUTO_ENAB(bus) && (err != 0)) {
-			OSL_DELAY(10000);
-			DHD_TRACE(("%s: Resync device sleep\n", __FUNCTION__));
-
-			/* Toggle sleep to resync with host and device */
-			err = bcmsdh_sleep(bus->sdh, TRUE);
-			OSL_DELAY(10000);
-			err = bcmsdh_sleep(bus->sdh, FALSE);
-
-			if (err) {
-				OSL_DELAY(10000);
-				DHD_ERROR(("%s: CMD14 exit failed again!\n", __FUNCTION__));
-
-				/* Toggle sleep to resync with host and device */
-				err = bcmsdh_sleep(bus->sdh, TRUE);
-				OSL_DELAY(10000);
-				err = bcmsdh_sleep(bus->sdh, FALSE);
-				if (err) {
-					DHD_ERROR(("%s: CMD14 exit failed twice!\n", __FUNCTION__));
-					DHD_ERROR(("%s: FATAL: Device non-response!\n",
-						__FUNCTION__));
-					err = 0;
-				}
-			}
-		}
-#else
-		if (OOB_WAKEUP_ENAB(bus))
-		{
-			err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, TRUE);  /* GPIO_1 is on */
-		}
-		do {
-			err = dhdsdio_clk_kso_enab(bus, TRUE);
-			if (err)
-				OSL_SLEEP(10);
-		} while ((err != 0) && (++retry < 3));
-
-		if (err != 0) {
-			DHD_ERROR(("ERROR: kso set failed retry: %d\n", retry));
-			err = 0; /* continue anyway */
-		}
-
-
-#endif /* !USE_CMD14 */
-
-		if (err == 0) {
-			uint8 csr;
-
-			/* Wait for device ready during transition to wake-up */
-			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
-				(((csr = dhdsdio_sleepcsr_get(bus)) &
-				SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK) !=
-				(SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), (20000));
-
-			DHD_TRACE(("%s: ExitSleep sleepcsr: 0x%x\n", __FUNCTION__, csr));
-
-			if (!(csr & SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)) {
-				DHD_ERROR(("%s:ERROR: ExitSleep device NOT Ready! 0x%x\n",
-					__FUNCTION__, csr));
-				err = BCME_NODEVICE;
-			}
-
-			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
-				(((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
-				SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) !=
-				(SBSDIO_HT_AVAIL)), (10000));
-
-			DHD_TRACE(("%s: SBSDIO_FUNC1_CHIPCLKCSR : 0x%x\n", __FUNCTION__, csr));
-			if (!err && ((csr & SBSDIO_HT_AVAIL) != SBSDIO_HT_AVAIL)) {
-				DHD_ERROR(("%s:ERROR: device NOT Ready! 0x%x\n",
-					__FUNCTION__, csr));
-				err = BCME_NODEVICE;
-			}
-		}
-	}
-
-	/* Update if successful */
-	if (err == 0)
-		bus->kso = on ? FALSE : TRUE;
-	else {
-		DHD_ERROR(("%s: Sleep request failed: kso:%d on:%d err:%d\n",
-			__FUNCTION__, bus->kso, on, err));
-		if (!on && retry > 2)
-			bus->kso = FALSE;
-	}
-
-	return err;
-}
-
-/* Turn backplane clock on or off */
-static int
-dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
-{
-#define HT_AVAIL_ERROR_MAX 10
-	static int ht_avail_error = 0;
-	int err;
-	uint8 clkctl, clkreq, devctl;
-	bcmsdh_info_t *sdh;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	clkctl = 0;
-	sdh = bus->sdh;
-
-
-	if (!KSO_ENAB(bus))
-		return BCME_OK;
-
-	if (SLPAUTO_ENAB(bus)) {
-		bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
-		return BCME_OK;
-	}
-
-	if (on) {
-		/* Request HT Avail */
-		clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
-
-
-
-		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
-		if (err) {
-			ht_avail_error++;
-			if (ht_avail_error < HT_AVAIL_ERROR_MAX) {
-				DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
-			}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-			else if (ht_avail_error == HT_AVAIL_ERROR_MAX) {
-				bus->dhd->hang_reason = HANG_REASON_HT_AVAIL_ERROR;
-				dhd_os_send_hang_message(bus->dhd);
-			}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
-			return BCME_ERROR;
-		} else {
-			ht_avail_error = 0;
-		}
-
-
-		/* Check current status */
-		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
-		if (err) {
-			DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err));
-			return BCME_ERROR;
-		}
-
-#if !defined(OOB_INTR_ONLY)
-		/* Go to pending and await interrupt if appropriate */
-		if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
-			/* Allow only clock-available interrupt */
-			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
-			if (err) {
-				DHD_ERROR(("%s: Devctl access error setting CA: %d\n",
-				           __FUNCTION__, err));
-				return BCME_ERROR;
-			}
-
-			devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
-			DHD_INFO(("CLKCTL: set PENDING\n"));
-			bus->clkstate = CLK_PENDING;
-			return BCME_OK;
-		} else
-#endif /* !defined (OOB_INTR_ONLY) */
-		{
-			if (bus->clkstate == CLK_PENDING) {
-				/* Cancel CA-only interrupt filter */
-				devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
-				devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
-			}
-		}
-
-		/* Otherwise, wait here (polling) for HT Avail */
-		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
-			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
-				((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
-			                                    SBSDIO_FUNC1_CHIPCLKCSR, &err)),
-			          !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY);
-		}
-		if (err) {
-			DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
-			return BCME_ERROR;
-		}
-		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
-			DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
-			           __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl));
-			return BCME_ERROR;
-		}
-
-		/* Mark clock available */
-		bus->clkstate = CLK_AVAIL;
-		DHD_INFO(("CLKCTL: turned ON\n"));
-
-#if defined(DHD_DEBUG)
-		if (bus->alp_only == TRUE) {
-#if !defined(BCMLXSDMMC)
-			if (!SBSDIO_ALPONLY(clkctl)) {
-				DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__));
-			}
-#endif /* !defined(BCMLXSDMMC) */
-		} else {
-			if (SBSDIO_ALPONLY(clkctl)) {
-				DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__));
-			}
-		}
-#endif /* defined (DHD_DEBUG) */
-
-		bus->activity = TRUE;
-#ifdef DHD_USE_IDLECOUNT
-		bus->idlecount = 0;
-#endif /* DHD_USE_IDLECOUNT */
-	} else {
-		clkreq = 0;
-
-		if (bus->clkstate == CLK_PENDING) {
-			/* Cancel CA-only interrupt filter */
-			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
-			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
-		}
-
-		bus->clkstate = CLK_SDONLY;
-		if (!SR_ENAB(bus)) {
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
-			DHD_INFO(("CLKCTL: turned OFF\n"));
-			if (err) {
-				DHD_ERROR(("%s: Failed access turning clock off: %d\n",
-				           __FUNCTION__, err));
-				return BCME_ERROR;
-			}
-		}
-	}
-	return BCME_OK;
-}
-
-/* Change idle/active SD state */
-static int
-dhdsdio_sdclk(dhd_bus_t *bus, bool on)
-{
-	int err;
-	int32 iovalue;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (on) {
-		if (bus->idleclock == DHD_IDLE_STOP) {
-			/* Turn on clock and restore mode */
-			iovalue = 1;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
-			                      &iovalue, sizeof(iovalue), TRUE);
-			if (err) {
-				DHD_ERROR(("%s: error enabling sd_clock: %d\n",
-				           __FUNCTION__, err));
-				return BCME_ERROR;
-			}
-
-			iovalue = bus->sd_mode;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
-			                      &iovalue, sizeof(iovalue), TRUE);
-			if (err) {
-				DHD_ERROR(("%s: error changing sd_mode: %d\n",
-				           __FUNCTION__, err));
-				return BCME_ERROR;
-			}
-		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
-			/* Restore clock speed */
-			iovalue = bus->sd_divisor;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
-			                      &iovalue, sizeof(iovalue), TRUE);
-			if (err) {
-				DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
-				           __FUNCTION__, err));
-				return BCME_ERROR;
-			}
-		}
-		bus->clkstate = CLK_SDONLY;
-	} else {
-		/* Stop or slow the SD clock itself */
-		if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
-			DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
-			           __FUNCTION__, bus->sd_divisor, bus->sd_mode));
-			return BCME_ERROR;
-		}
-		if (bus->idleclock == DHD_IDLE_STOP) {
-			if (sd1idle) {
-				/* Change to SD1 mode and turn off clock */
-				iovalue = 1;
-				err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
-				                      &iovalue, sizeof(iovalue), TRUE);
-				if (err) {
-					DHD_ERROR(("%s: error changing sd_clock: %d\n",
-					           __FUNCTION__, err));
-					return BCME_ERROR;
-				}
-			}
-
-			iovalue = 0;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
-			                      &iovalue, sizeof(iovalue), TRUE);
-			if (err) {
-				DHD_ERROR(("%s: error disabling sd_clock: %d\n",
-				           __FUNCTION__, err));
-				return BCME_ERROR;
-			}
-		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
-			/* Set divisor to idle value */
-			iovalue = bus->idleclock;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
-			                      &iovalue, sizeof(iovalue), TRUE);
-			if (err) {
-				DHD_ERROR(("%s: error changing sd_divisor: %d\n",
-				           __FUNCTION__, err));
-				return BCME_ERROR;
-			}
-		}
-		bus->clkstate = CLK_NONE;
-	}
-
-	return BCME_OK;
-}
-
-/* Transition SD and backplane clock readiness */
-static int
-dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
-{
-	int ret = BCME_OK;
-#ifdef DHD_DEBUG
-	uint oldstate = bus->clkstate;
-#endif /* DHD_DEBUG */
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	/* Early exit if we're already there */
-	if (bus->clkstate == target) {
-		if (target == CLK_AVAIL) {
-			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
-			bus->activity = TRUE;
-#ifdef DHD_USE_IDLECOUNT
-			bus->idlecount = 0;
-#endif /* DHD_USE_IDLECOUNT */
-		}
-		return ret;
-	}
-
-	switch (target) {
-	case CLK_AVAIL:
-		/* Make sure SD clock is available */
-		if (bus->clkstate == CLK_NONE)
-			dhdsdio_sdclk(bus, TRUE);
-		/* Now request HT Avail on the backplane */
-		ret = dhdsdio_htclk(bus, TRUE, pendok);
-		if (ret == BCME_OK) {
-			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
-		bus->activity = TRUE;
-#ifdef DHD_USE_IDLECOUNT
-			bus->idlecount = 0;
-#endif /* DHD_USE_IDLECOUNT */
-		}
-		break;
-
-	case CLK_SDONLY:
-		/* Remove HT request, or bring up SD clock */
-		if (bus->clkstate == CLK_NONE)
-			ret = dhdsdio_sdclk(bus, TRUE);
-		else if (bus->clkstate == CLK_AVAIL)
-			ret = dhdsdio_htclk(bus, FALSE, FALSE);
-		else
-			DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
-			           bus->clkstate, target));
-		if (ret == BCME_OK) {
-			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
-		}
-		break;
-
-	case CLK_NONE:
-		/* Make sure to remove HT request */
-		if (bus->clkstate == CLK_AVAIL)
-			ret = dhdsdio_htclk(bus, FALSE, FALSE);
-		/* Now remove the SD clock */
-		ret = dhdsdio_sdclk(bus, FALSE);
-#ifdef DHD_DEBUG
-		if (dhd_console_ms == 0)
-#endif /* DHD_DEBUG */
-		if (bus->poll == 0)
-			dhd_os_wd_timer(bus->dhd, 0);
-		break;
-	}
-#ifdef DHD_DEBUG
-	DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
-#endif /* DHD_DEBUG */
-
-	return ret;
-}
-
-static int
-dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
-{
-	int err = 0;
-	bcmsdh_info_t *sdh = bus->sdh;
-	sdpcmd_regs_t *regs = bus->regs;
-	uint retries = 0;
-
-	DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
-	          (sleep ? "SLEEP" : "WAKE"),
-	          (bus->sleeping ? "SLEEP" : "WAKE")));
-
-	if (bus->dhd->hang_was_sent)
-		return BCME_ERROR;
-
-	/* Done if we're already in the requested state */
-	if (sleep == bus->sleeping)
-		return BCME_OK;
-
-	/* Going to sleep: set the alarm and turn off the lights... */
-	if (sleep) {
-		/* Don't sleep if something is pending */
-#ifdef DHD_USE_IDLECOUNT
-		if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq) || bus->readframes ||
-			bus->ctrl_frame_stat)
-#else
-		if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
-#endif /* DHD_USE_IDLECOUNT */
-			return BCME_BUSY;
-
-
-		if (!SLPAUTO_ENAB(bus)) {
-			/* Disable SDIO interrupts (no longer interested) */
-			bcmsdh_intr_disable(bus->sdh);
-
-			/* Make sure the controller has the bus up */
-			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-			/* Tell device to start using OOB wakeup */
-			W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
-			if (retries > retry_limit)
-				DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
-
-			/* Turn off our contribution to the HT clock request */
-			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
-
-			/* Isolate the bus */
-			if (bus->sih->chip != BCM4329_CHIP_ID &&
-				bus->sih->chip != BCM4319_CHIP_ID) {
-				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					SBSDIO_DEVCTL_PADS_ISO, NULL);
-			}
-		} else {
-			/* Leave interrupts enabled since device can exit sleep and
-			 * interrupt host
-			 */
-			err = dhdsdio_clk_devsleep_iovar(bus, TRUE /* sleep */);
-		}
-
-		/* Change state */
-		bus->sleeping = TRUE;
-#if defined(SUPPORT_P2P_GO_PS)
-		wake_up(&bus->bus_sleep);
-#endif /* LINUX && SUPPORT_P2P_GO_PS */
-	} else {
-		/* Waking up: bus power up is ok, set local state */
-
-		if (!SLPAUTO_ENAB(bus)) {
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, &err);
-
-			/* Force pad isolation off if possible (in case power never toggled) */
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
-
-
-			/* Make sure the controller has the bus up */
-			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-			/* Send misc interrupt to indicate OOB not needed */
-			W_SDREG(0, &regs->tosbmailboxdata, retries);
-			if (retries <= retry_limit)
-				W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
-
-			if (retries > retry_limit)
-				DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
-
-			/* Make sure we have SD bus access */
-			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-
-			/* Enable interrupts again */
-			if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
-				bus->intdis = FALSE;
-				bcmsdh_intr_enable(bus->sdh);
-			}
-		} else {
-			err = dhdsdio_clk_devsleep_iovar(bus, FALSE /* wake */);
-		}
-
-		if (err == 0) {
-			/* Change state */
-			bus->sleeping = FALSE;
-		}
-	}
-
-	return err;
-}
-
-#ifdef USE_DYNAMIC_F2_BLKSIZE
-int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size)
-{
-	int func_blk_size = function_num;
-	int bcmerr = 0;
-	int result;
-
-	bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size,
-		sizeof(int), &result, sizeof(int), IOV_GET);
-
-	if (bcmerr != BCME_OK) {
-		DHD_ERROR(("%s: Get F%d Block size error\n", __FUNCTION__, function_num));
-		return BCME_ERROR;
-	}
-
-	if (result != block_size) {
-		DHD_TRACE_HW4(("%s: F%d Block size set from %d to %d\n",
-			__FUNCTION__, function_num, result, block_size));
-		func_blk_size = function_num << 16 | block_size;
-		bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", NULL,
-			0, &func_blk_size, sizeof(int32), IOV_SET);
-		if (bcmerr != BCME_OK) {
-			DHD_ERROR(("%s: Set F2 Block size error\n", __FUNCTION__));
-			return BCME_ERROR;
-		}
-	}
-
-	return BCME_OK;
-}
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
-
-#if defined(OOB_INTR_ONLY)
-void
-dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
-{
-#if defined(HW_OOB)
-	bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
-#else
-	sdpcmd_regs_t *regs = bus->regs;
-	uint retries = 0;
-
-	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-	if (enable == TRUE) {
-
-		/* Tell device to start using OOB wakeup */
-		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
-		if (retries > retry_limit)
-			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
-
-	} else {
-		/* Send misc interrupt to indicate OOB not needed */
-		W_SDREG(0, &regs->tosbmailboxdata, retries);
-		if (retries <= retry_limit)
-			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
-	}
-
-	/* Turn off our contribution to the HT clock request */
-	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-#endif /* !defined(HW_OOB) */
-}
-#endif 
-
-int
-dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
-{
-	int ret = BCME_ERROR;
-	osl_t *osh;
-	uint datalen, prec;
-#if defined(DHD_TX_DUMP)
-	uint8 *dump_data;
-	uint16 protocol;
-#endif /* DHD_TX_DUMP */
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	osh = bus->dhd->osh;
-	datalen = PKTLEN(osh, pkt);
-
-#ifdef SDTEST
-	/* Push the test header if doing loopback */
-	if (bus->ext_loop) {
-		uint8* data;
-		PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN);
-		data = PKTDATA(osh, pkt);
-		*data++ = SDPCM_TEST_ECHOREQ;
-		*data++ = (uint8)bus->loopid++;
-		*data++ = (datalen >> 0);
-		*data++ = (datalen >> 8);
-		datalen += SDPCM_TEST_HDRLEN;
-	}
-#else /* SDTEST */
-	BCM_REFERENCE(datalen);
-#endif /* SDTEST */
-
-#if defined(DHD_TX_DUMP)
-	dump_data = PKTDATA(osh, pkt);
-	dump_data += 4; /* skip 4 bytes header */
-	protocol = (dump_data[12] << 8) | dump_data[13];
-
-	if (protocol == ETHER_TYPE_802_1X) {
-		DHD_ERROR(("ETHER_TYPE_802_1X [TX]: ver %d, type %d, replay %d\n",
-			dump_data[14], dump_data[15], dump_data[30]));
-	}
-#endif /* DHD_TX_DUMP */
-
-#if defined(DHD_TX_DUMP) && defined(DHD_TX_FULL_DUMP)
-	{
-		int i;
-		DHD_ERROR(("TX DUMP\n"));
-
-		for (i = 0; i < (datalen - 4); i++) {
-			DHD_ERROR(("%02X ", dump_data[i]));
-			if ((i & 15) == 15)
-				printk("\n");
-		}
-		DHD_ERROR(("\n"));
-	}
-#endif /* DHD_TX_DUMP && DHD_TX_FULL_DUMP */
-
-	prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
-
-	/* Check for existing queue, current flow-control, pending event, or pending clock */
-	if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched ||
-	    (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
-	    (bus->clkstate != CLK_AVAIL)) {
-		bool deq_ret;
-		int pkq_len;
-
-		DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, pktq_len(&bus->txq)));
-		bus->fcqueued++;
-
-		/* Priority based enq */
-		dhd_os_sdlock_txq(bus->dhd);
-		deq_ret = dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec);
-		dhd_os_sdunlock_txq(bus->dhd);
-
-		if (!deq_ret) {
-#ifdef PROP_TXSTATUS
-			if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) == 0)
-#endif /* PROP_TXSTATUS */
-			{
-#ifdef DHDTCPACK_SUPPRESS
-				if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
-					DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using\n",
-						__FUNCTION__, __LINE__));
-					dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
-				}
-#endif /* DHDTCPACK_SUPPRESS */
-				dhd_txcomplete(bus->dhd, pkt, FALSE);
-				PKTFREE(osh, pkt, TRUE);
-			}
-			ret = BCME_NORESOURCE;
-		} else
-			ret = BCME_OK;
-
-		dhd_os_sdlock_txq(bus->dhd);
-		pkq_len = pktq_len(&bus->txq);
-		dhd_os_sdunlock_txq(bus->dhd);
-		if (pkq_len >= FCHI) {
-			bool wlfc_enabled = FALSE;
-#ifdef PROP_TXSTATUS
-			wlfc_enabled = (dhd_wlfc_flowcontrol(bus->dhd, ON, FALSE) !=
-				WLFC_UNSUPPORTED);
-#endif
-			if (!wlfc_enabled && dhd_doflow) {
-				dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
-			}
-		}
-
-#ifdef DHD_DEBUG
-		dhd_os_sdlock_txq(bus->dhd);
-		if (pktq_plen(&bus->txq, prec) > qcount[prec])
-			qcount[prec] = pktq_plen(&bus->txq, prec);
-		dhd_os_sdunlock_txq(bus->dhd);
-#endif
-
-		/* Schedule DPC if needed to send queued packet(s) */
-		if (dhd_deferred_tx && !bus->dpc_sched) {
-			bus->dpc_sched = TRUE;
-			dhd_sched_dpc(bus->dhd);
-		}
-	} else {
-		int chan = SDPCM_DATA_CHANNEL;
-
-#ifdef SDTEST
-		chan = (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL);
-#endif
-		/* Lock: we're about to use shared data/code (and SDIO) */
-		dhd_os_sdlock(bus->dhd);
-
-		/* Otherwise, send it now */
-		BUS_WAKE(bus);
-		/* Make sure back plane ht clk is on, no pending allowed */
-		dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
-
-		ret = dhdsdio_txpkt(bus, chan, &pkt, 1, TRUE);
-
-		if (ret != BCME_OK)
-			bus->dhd->tx_errors++;
-		else
-			bus->dhd->dstats.tx_bytes += datalen;
-
-		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
-			bus->activity = FALSE;
-			dhdsdio_clkctl(bus, CLK_NONE, TRUE);
-		}
-
-		dhd_os_sdunlock(bus->dhd);
-	}
-
-	return ret;
-}
-
-/* align packet data pointer and packet length to n-byte boundary, process packet headers,
- * a new packet may be allocated if there is not enough head and/or tail from for padding.
- * the caller is responsible for updating the glom size in the head packet (when glom is
- * used)
- *
- * pad_pkt_len: returns the length of extra padding needed from the padding packet, this parameter
- * is taken in tx glom mode only
- *
- * new_pkt: out, pointer of the new packet allocated due to insufficient head room for alignment
- * padding, NULL if not needed, the caller is responsible for freeing the new packet
- *
- * return: positive value - length of the packet, including head and tail padding
- *		   negative value - errors
- */
-static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
-	int prev_chain_total_len, bool last_chained_pkt,
-	int *pad_pkt_len, void **new_pkt)
-{
-	osl_t *osh;
-	uint8 *frame;
-	int pkt_len;
-	int modulo;
-	int head_padding;
-	int tail_padding = 0;
-	uint32 swheader;
-	uint32 swhdr_offset;
-	bool alloc_new_pkt = FALSE;
-	uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
-
-	*new_pkt = NULL;
-	osh = bus->dhd->osh;
-
-#ifdef DHDTCPACK_SUPPRESS
-	if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
-		DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
-			__FUNCTION__, __LINE__));
-		dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
-	}
-#endif /* DHDTCPACK_SUPPRESS */
-
-	/* Add space for the SDPCM hardware/software headers */
-	PKTPUSH(osh, pkt, sdpcm_hdrlen);
-	ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2));
-
-	frame = (uint8*)PKTDATA(osh, pkt);
-	pkt_len = (uint16)PKTLEN(osh, pkt);
-
-#ifdef WLMEDIA_HTSF
-	frame = (uint8*)PKTDATA(osh, pkt);
-	if (PKTLEN(osh, pkt) >= 100) {
-		htsf_ts = (htsfts_t*) (frame + HTSF_HOSTOFFSET + 12);
-		if (htsf_ts->magic == HTSFMAGIC) {
-			htsf_ts->c20 = get_cycles();
-			htsf_ts->t20 = dhd_get_htsf(bus->dhd->info, 0);
-		}
-	}
-#endif /* WLMEDIA_HTSF */
-#ifdef DHD_DEBUG
-	if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets))
-		tx_packets[PKTPRIO(pkt)]++;
-#endif /* DHD_DEBUG */
-
-	/* align the data pointer, allocate a new packet if there is not enough space (new
-	 * packet data pointer will be aligned thus no padding will be needed)
-	 */
-	head_padding = (ulong)frame % DHD_SDALIGN;
-	if (PKTHEADROOM(osh, pkt) < head_padding) {
-		head_padding = 0;
-		alloc_new_pkt = TRUE;
-	} else {
-		uint cur_chain_total_len;
-		int chain_tail_padding = 0;
-
-		/* All packets need to be aligned by DHD_SDALIGN */
-		modulo = (pkt_len + head_padding) % DHD_SDALIGN;
-		tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
-
-		/* Total pkt chain length needs to be aligned by block size,
-		 * unless it is a single pkt chain with total length less than one block size,
-		 * which we prefer sending by byte mode.
-		 *
-		 * Do the chain alignment here if
-		 * 1. This is the last pkt of the chain of multiple pkts or a single pkt.
-		 * 2-1. This chain is of multiple pkts, or
-		 * 2-2. This is a single pkt whose size is longer than one block size.
-		 */
-		cur_chain_total_len = prev_chain_total_len +
-			(head_padding + pkt_len + tail_padding);
-		if (last_chained_pkt && bus->blocksize != 0 &&
-			(cur_chain_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
-			modulo = cur_chain_total_len % bus->blocksize;
-			chain_tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
-		}
-
-#ifdef DHDENABLE_TAILPAD
-		if (PKTTAILROOM(osh, pkt) < tail_padding) {
-			/* We don't have tail room to align by DHD_SDALIGN */
-			alloc_new_pkt = TRUE;
-			bus->tx_tailpad_pktget++;
-		} else if (PKTTAILROOM(osh, pkt) < tail_padding + chain_tail_padding) {
-			/* We have tail room for tail_padding of this pkt itself, but not for
-			 * total pkt chain alignment by block size.
-			 * Use the padding packet to avoid memory copy if applicable,
-			 * otherwise, just allocate a new pkt.
-			 */
-			if (bus->pad_pkt) {
-				*pad_pkt_len = chain_tail_padding;
-				bus->tx_tailpad_chain++;
-			} else {
-				alloc_new_pkt = TRUE;
-				bus->tx_tailpad_pktget++;
-			}
-		} else
-		/* This last pkt's tailroom is sufficient to hold both tail_padding
-		 * of the pkt itself and chain_tail_padding of total pkt chain
-		 */
-#endif /* DHDENABLE_TAILPAD */
-		tail_padding += chain_tail_padding;
-	}
-
-	DHD_INFO(("%s sdhdr len + orig_pkt_len %d h_pad %d t_pad %d pad_pkt_len %d\n",
-		__FUNCTION__, pkt_len, head_padding, tail_padding, *pad_pkt_len));
-
-	if (alloc_new_pkt) {
-		void *tmp_pkt;
-		int newpkt_size;
-		int cur_total_len;
-
-		ASSERT(*pad_pkt_len == 0);
-
-		DHD_INFO(("%s allocating new packet for padding\n", __FUNCTION__));
-
-		/* head pointer is aligned now, no padding needed */
-		head_padding = 0;
-
-		/* update the tail padding as it depends on the head padding, since a new packet is
-		 * allocated, the head padding is non longer needed and packet length is chagned
-		 */
-
-		cur_total_len = prev_chain_total_len + pkt_len;
-		if (last_chained_pkt && bus->blocksize != 0 &&
-			(cur_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
-			modulo = cur_total_len % bus->blocksize;
-			tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
-		}
-		else {
-			modulo = pkt_len % DHD_SDALIGN;
-			tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
-		}
-
-		newpkt_size = PKTLEN(osh, pkt) + bus->blocksize + DHD_SDALIGN;
-		bus->dhd->tx_realloc++;
-		tmp_pkt = PKTGET(osh, newpkt_size, TRUE);
-		if (tmp_pkt == NULL) {
-			DHD_ERROR(("failed to alloc new %d byte packet\n", newpkt_size));
-			return BCME_NOMEM;
-		}
-		PKTALIGN(osh, tmp_pkt, PKTLEN(osh, pkt), DHD_SDALIGN);
-		bcopy(PKTDATA(osh, pkt), PKTDATA(osh, tmp_pkt), PKTLEN(osh, pkt));
-		*new_pkt = tmp_pkt;
-		pkt = tmp_pkt;
-	}
-
-	if (head_padding)
-		PKTPUSH(osh, pkt, head_padding);
-
-	frame = (uint8*)PKTDATA(osh, pkt);
-	bzero(frame, head_padding + sdpcm_hdrlen);
-	pkt_len = (uint16)PKTLEN(osh, pkt);
-
-	/* the header has the followming format
-	 * 4-byte HW frame tag: length, ~length (for glom this is the total length)
-	 *
-	 * 8-byte HW extesion flags (glom mode only) as the following:
-	 *			2-byte packet length, excluding HW tag and padding
-	 *			2-byte frame channel and frame flags (e.g. next frame following)
-	 *			2-byte header length
-	 *			2-byte tail padding size
-	 *
-	 * 8-byte SW frame tags as the following
-	 *			4-byte flags: host tx seq, channel, data offset
-	 *			4-byte flags: TBD
-	 */
-
-	swhdr_offset = SDPCM_FRAMETAG_LEN;
-
-	/* hardware frame tag:
-	 *
-	 * in tx-glom mode, dongle only checks the hardware frame tag in the first
-	 * packet and sees it as the total lenght of the glom (including tail padding),
-	 * for each packet in the glom, the packet length needs to be updated, (see
-	 * below PKTSETLEN)
-	 *
-	 * in non tx-glom mode, PKTLEN still need to include tail padding as to be
-	 * referred to in sdioh_request_buffer(). The tail length will be excluded in
-	 * dhdsdio_txpkt_postprocess().
-	 */
-	*(uint16*)frame = (uint16)htol16(pkt_len);
-	*(((uint16*)frame) + 1) = (uint16)htol16(~pkt_len);
-	pkt_len += tail_padding;
-
-	/* hardware extesion flags */
-	if (bus->txglom_enable) {
-		uint32 hwheader1;
-		uint32 hwheader2;
-
-		swhdr_offset += SDPCM_HWEXT_LEN;
-		hwheader1 = (pkt_len - SDPCM_FRAMETAG_LEN - tail_padding) |
-			(last_chained_pkt << 24);
-		hwheader2 = (tail_padding) << 16;
-		htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
-		htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
-	}
-	PKTSETLEN((osh), (pkt), (pkt_len));
-
-	/* software frame tags */
-	swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
-		| (txseq % SDPCM_SEQUENCE_WRAP) |
-		(((head_padding + sdpcm_hdrlen) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
-	htol32_ua_store(swheader, frame + swhdr_offset);
-	htol32_ua_store(0, frame + swhdr_offset + sizeof(swheader));
-
-	return pkt_len;
-}
-
-static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt)
-{
-	osl_t *osh;
-	uint8 *frame;
-	int data_offset;
-	int tail_padding;
-	int swhdr_offset = SDPCM_FRAMETAG_LEN + (bus->txglom_enable ? SDPCM_HWEXT_LEN : 0);
-
-	(void)osh;
-	osh = bus->dhd->osh;
-
-	/* restore pkt buffer pointer, but keeps the header pushed by dhd_prot_hdrpush */
-	frame = (uint8*)PKTDATA(osh, pkt);
-
-	DHD_INFO(("%s PKTLEN before postprocess %d",
-		__FUNCTION__, PKTLEN(osh, pkt)));
-
-	/* PKTLEN still includes tail_padding, so exclude it.
-	 * We shall have head_padding + original pkt_len for PKTLEN afterwards.
-	 */
-	if (bus->txglom_enable) {
-		/* txglom pkts have tail_padding length in HW ext header */
-		tail_padding = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + 4) >> 16;
-		PKTSETLEN(osh, pkt, PKTLEN(osh, pkt) - tail_padding);
-		DHD_INFO((" txglom pkt: tail_padding %d PKTLEN %d\n",
-			tail_padding, PKTLEN(osh, pkt)));
-	} else {
-		/* non-txglom pkts have head_padding + original pkt length in HW frame tag.
-		 * We cannot refer to this field for txglom pkts as the first pkt of the chain will
-		 * have the field for the total length of the chain.
-		 */
-		PKTSETLEN(osh, pkt, *(uint16*)frame);
-		DHD_INFO((" non-txglom pkt: HW frame tag len %d after PKTLEN %d\n",
-			*(uint16*)frame, PKTLEN(osh, pkt)));
-	}
-
-	data_offset = ltoh32_ua(frame + swhdr_offset);
-	data_offset = (data_offset & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT;
-	/* Get rid of sdpcm header + head_padding */
-	PKTPULL(osh, pkt, data_offset);
-
-	DHD_INFO(("%s data_offset %d, PKTLEN %d\n",
-		__FUNCTION__, data_offset, PKTLEN(osh, pkt)));
-
-	return BCME_OK;
-}
-
-static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt)
-{
-	int i;
-	int ret = 0;
-	osl_t *osh;
-	bcmsdh_info_t *sdh;
-	void *pkt = NULL;
-	void *pkt_chain;
-	int total_len = 0;
-	void *head_pkt = NULL;
-	void *prev_pkt = NULL;
-	int pad_pkt_len = 0;
-	int new_pkt_num = 0;
-	void *new_pkts[MAX_TX_PKTCHAIN_CNT];
-	bool wlfc_enabled = FALSE;
-
-	if (bus->dhd->dongle_reset)
-		return BCME_NOTREADY;
-
-	sdh = bus->sdh;
-	osh = bus->dhd->osh;
-	/* init new_pkts[0] to make some compiler happy, not necessary as we check new_pkt_num */
-	new_pkts[0] = NULL;
-
-	for (i = 0; i < num_pkt; i++) {
-		int pkt_len;
-		bool last_pkt;
-		void *new_pkt = NULL;
-
-		pkt = pkts[i];
-		ASSERT(pkt);
-		last_pkt = (i == num_pkt - 1);
-		pkt_len = dhdsdio_txpkt_preprocess(bus, pkt, chan, bus->tx_seq + i,
-			total_len, last_pkt, &pad_pkt_len, &new_pkt);
-		if (pkt_len <= 0)
-			goto done;
-		if (new_pkt) {
-			pkt = new_pkt;
-			new_pkts[new_pkt_num++] = new_pkt;
-		}
-		total_len += pkt_len;
-
-		PKTSETNEXT(osh, pkt, NULL);
-		/* insert the packet into the list */
-		head_pkt ? PKTSETNEXT(osh, prev_pkt, pkt) : (head_pkt = pkt);
-		prev_pkt = pkt;
-
-	}
-
-	/* Update the HW frame tag (total length) in the first pkt of the glom */
-	if (bus->txglom_enable) {
-		uint8 *frame;
-
-		total_len += pad_pkt_len;
-		frame = (uint8*)PKTDATA(osh, head_pkt);
-		*(uint16*)frame = (uint16)htol16(total_len);
-		*(((uint16*)frame) + 1) = (uint16)htol16(~total_len);
-
-	}
-
-#ifdef DHDENABLE_TAILPAD
-	/* if a padding packet if needed, insert it to the end of the link list */
-	if (pad_pkt_len) {
-		PKTSETLEN(osh, bus->pad_pkt, pad_pkt_len);
-		PKTSETNEXT(osh, pkt, bus->pad_pkt);
-	}
-#endif /* DHDENABLE_TAILPAD */
-
-	/* dhd_bcmsdh_send_buf ignores the buffer pointer if he packet
-	 * parameter is not NULL, for non packet chian we pass NULL pkt pointer
-	 * so it will take the aligned length and buffer pointer.
-	 */
-	pkt_chain = PKTNEXT(osh, head_pkt) ? head_pkt : NULL;
-	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
-		PKTDATA(osh, head_pkt), total_len, pkt_chain, NULL, NULL, TXRETRIES);
-	if (ret == BCME_OK)
-		bus->tx_seq = (bus->tx_seq + num_pkt) % SDPCM_SEQUENCE_WRAP;
-
-	/* if a padding packet was needed, remove it from the link list as it not a data pkt */
-	if (pad_pkt_len && pkt)
-		PKTSETNEXT(osh, pkt, NULL);
-
-done:
-	pkt = head_pkt;
-	while (pkt) {
-		void *pkt_next = PKTNEXT(osh, pkt);
-		PKTSETNEXT(osh, pkt, NULL);
-		dhdsdio_txpkt_postprocess(bus, pkt);
-		pkt = pkt_next;
-	}
-
-	/* new packets might be allocated due to insufficient room for padding, but we
-	 * still have to indicate the original packets to upper layer
-	 */
-	for (i = 0; i < num_pkt; i++) {
-		pkt = pkts[i];
-		wlfc_enabled = FALSE;
-#ifdef PROP_TXSTATUS
-		if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt))) {
-			wlfc_enabled = (dhd_wlfc_txcomplete(bus->dhd, pkt, ret == 0) !=
-				WLFC_UNSUPPORTED);
-		}
-#endif /* PROP_TXSTATUS */
-		if (!wlfc_enabled) {
-			PKTSETNEXT(osh, pkt, NULL);
-			dhd_txcomplete(bus->dhd, pkt, ret != 0);
-			if (free_pkt)
-				PKTFREE(osh, pkt, TRUE);
-		}
-	}
-
-	for (i = 0; i < new_pkt_num; i++)
-		PKTFREE(osh, new_pkts[i], TRUE);
-
-	return ret;
-}
-
-static uint
-dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
-{
-	uint cnt = 0;
-	uint8 tx_prec_map;
-	uint16 txpktqlen = 0;
-	uint32 intstatus = 0;
-	uint retries = 0;
-	osl_t *osh;
-	uint datalen = 0;
-	dhd_pub_t *dhd = bus->dhd;
-	sdpcmd_regs_t *regs = bus->regs;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (!KSO_ENAB(bus)) {
-		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
-		return BCME_NODEVICE;
-	}
-
-	osh = dhd->osh;
-	tx_prec_map = ~bus->flowcontrol;
-#ifdef DHD_LOSSLESS_ROAMING
-	tx_prec_map &= dhd->dequeue_prec_map;
-#endif
-	for (cnt = 0; (cnt < maxframes) && DATAOK(bus);) {
-		int i;
-		int num_pkt = 1;
-		void *pkts[MAX_TX_PKTCHAIN_CNT];
-		int prec_out;
-
-		dhd_os_sdlock_txq(bus->dhd);
-		if (bus->txglom_enable) {
-			uint32 glomlimit = (uint32)bus->txglomsize;
-#if defined(BCMSDIOH_STD)
-			if (bus->blocksize == 64) {
-				glomlimit = MIN((uint32)bus->txglomsize, BLK_64_MAXTXGLOM);
-			}
-#endif /* BCMSDIOH_STD */
-			num_pkt = MIN((uint32)DATABUFCNT(bus), glomlimit);
-			num_pkt = MIN(num_pkt, ARRAYSIZE(pkts));
-		}
-		num_pkt = MIN(num_pkt, pktq_mlen(&bus->txq, tx_prec_map));
-		for (i = 0; i < num_pkt; i++) {
-			pkts[i] = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
-			if (!pkts[i]) {
-				DHD_ERROR(("%s: pktq_mlen non-zero when no pkt\n",
-					__FUNCTION__));
-				ASSERT(0);
-				break;
-			}
-			PKTORPHAN(pkts[i]);
-			datalen += PKTLEN(osh, pkts[i]);
-		}
-		dhd_os_sdunlock_txq(bus->dhd);
-
-		if (i == 0)
-			break;
-		if (dhdsdio_txpkt(bus, SDPCM_DATA_CHANNEL, pkts, i, TRUE) != BCME_OK)
-			dhd->tx_errors++;
-		else
-			dhd->dstats.tx_bytes += datalen;
-		cnt += i;
-
-		/* In poll mode, need to check for other events */
-		if (!bus->intr && cnt)
-		{
-			/* Check device status, signal pending interrupt */
-			R_SDREG(intstatus, &regs->intstatus, retries);
-			bus->f2txdata++;
-			if (bcmsdh_regfail(bus->sdh))
-				break;
-			if (intstatus & bus->hostintmask)
-				bus->ipend = TRUE;
-		}
-
-	}
-
-	dhd_os_sdlock_txq(bus->dhd);
-	txpktqlen = pktq_len(&bus->txq);
-	dhd_os_sdunlock_txq(bus->dhd);
-
-	/* Do flow-control if needed */
-	if (dhd->up && (dhd->busstate == DHD_BUS_DATA) && (txpktqlen < FCLOW)) {
-		bool wlfc_enabled = FALSE;
-#ifdef PROP_TXSTATUS
-		wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, OFF, TRUE) != WLFC_UNSUPPORTED);
-#endif
-		if (!wlfc_enabled && dhd_doflow && dhd->txoff) {
-			dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
-		}
-	}
-
-	return cnt;
-}
-
-static void
-dhdsdio_sendpendctl(dhd_bus_t *bus)
-{
-	bcmsdh_info_t *sdh = bus->sdh;
-	int ret;
-	uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN;
-
-	if (bus->txglom_enable)
-		frame_seq += SDPCM_HWEXT_LEN;
-
-	if (*frame_seq != bus->tx_seq) {
-		DHD_INFO(("%s IOCTL frame seq lag detected!"
-			" frm_seq:%d != bus->tx_seq:%d, corrected\n",
-			__FUNCTION__, *frame_seq, bus->tx_seq));
-		*frame_seq = bus->tx_seq;
-	}
-
-	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
-		(uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len,
-		NULL, NULL, NULL, 1);
-	if (ret == BCME_OK)
-		bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
-
-	bus->ctrl_frame_stat = FALSE;
-	dhd_wait_event_wakeup(bus->dhd);
-}
-
-int
-dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
-{
-	static int err_nodevice = 0;
-	uint8 *frame;
-	uint16 len;
-	uint32 swheader;
-	bcmsdh_info_t *sdh = bus->sdh;
-	uint8 doff = 0;
-	int ret = -1;
-	uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (bus->dhd->dongle_reset)
-		return -EIO;
-
-	/* Back the pointer to make a room for bus header */
-	frame = msg - sdpcm_hdrlen;
-	len = (msglen += sdpcm_hdrlen);
-
-	/* Add alignment padding (optional for ctl frames) */
-	if (dhd_alignctl) {
-		if ((doff = ((uintptr)frame % DHD_SDALIGN))) {
-			frame -= doff;
-			len += doff;
-			msglen += doff;
-			bzero(frame, doff + sdpcm_hdrlen);
-		}
-		ASSERT(doff < DHD_SDALIGN);
-	}
-	doff += sdpcm_hdrlen;
-
-	/* Round send length to next SDIO block */
-	if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
-		uint16 pad = bus->blocksize - (len % bus->blocksize);
-		if ((pad <= bus->roundup) && (pad < bus->blocksize))
-			len += pad;
-	} else if (len % DHD_SDALIGN) {
-		len += DHD_SDALIGN - (len % DHD_SDALIGN);
-	}
-
-	/* Satisfy length-alignment requirements */
-	if (forcealign && (len & (ALIGNMENT - 1)))
-		len = ROUNDUP(len, ALIGNMENT);
-
-	ASSERT(ISALIGNED((uintptr)frame, 2));
-
-
-	/* Need to lock here to protect txseq and SDIO tx calls */
-	dhd_os_sdlock(bus->dhd);
-
-	BUS_WAKE(bus);
-
-	/* Make sure backplane clock is on */
-	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
-	*(uint16*)frame = htol16((uint16)msglen);
-	*(((uint16*)frame) + 1) = htol16(~msglen);
-
-	if (bus->txglom_enable) {
-		uint32 hwheader1, hwheader2;
-		/* Software tag: channel, sequence number, data offset */
-		swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
-				| bus->tx_seq
-				| ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
-		htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN);
-		htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN
-			+ SDPCM_HWEXT_LEN + sizeof(swheader));
-
-		hwheader1 = (msglen - SDPCM_FRAMETAG_LEN) | (1 << 24);
-		hwheader2 = (len - (msglen)) << 16;
-		htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
-		htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
-
-		*(uint16*)frame = htol16(len);
-		*(((uint16*)frame) + 1) = htol16(~(len));
-	} else {
-		/* Software tag: channel, sequence number, data offset */
-		swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
-		        | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
-		htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
-		htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
-	}
-	if (!TXCTLOK(bus)) {
-		DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
-			__FUNCTION__, bus->tx_max, bus->tx_seq));
-		bus->ctrl_frame_stat = TRUE;
-		/* Send from dpc */
-		bus->ctrl_frame_buf = frame;
-		bus->ctrl_frame_len = len;
-
-		if (!bus->dpc_sched) {
-			bus->dpc_sched = TRUE;
-			dhd_sched_dpc(bus->dhd);
-		}
-		if (bus->ctrl_frame_stat) {
-			dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
-		}
-
-		if (bus->ctrl_frame_stat == FALSE) {
-			DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
-			ret = 0;
-		} else {
-			bus->dhd->txcnt_timeout++;
-			if (!bus->dhd->hang_was_sent) {
-#ifdef CUSTOMER_HW4_DEBUG
-				uint32 status, retry = 0;
-				R_SDREG(status, &bus->regs->intstatus, retry);
-				DHD_TRACE_HW4(("%s: txcnt_timeout, INT status=0x%08X\n",
-					__FUNCTION__, status));
-				DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n",
-					__FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate));
-#endif /* CUSTOMER_HW4_DEBUG */
-				DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n",
-					__FUNCTION__, bus->dhd->txcnt_timeout));
-			}
-			ret = -1;
-			bus->ctrl_frame_stat = FALSE;
-			goto done;
-		}
-	}
-
-	bus->dhd->txcnt_timeout = 0;
-	bus->ctrl_frame_stat = TRUE;
-
-	if (ret == -1) {
-#ifdef DHD_DEBUG
-		if (DHD_BYTES_ON() && DHD_CTL_ON()) {
-			prhex("Tx Frame", frame, len);
-		} else if (DHD_HDRS_ON()) {
-			prhex("TxHdr", frame, MIN(len, 16));
-		}
-#endif
-		ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
-		                          frame, len, NULL, NULL, NULL, TXRETRIES);
-		if (ret == BCME_OK)
-			bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
-	}
-	bus->ctrl_frame_stat = FALSE;
-
-done:
-	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
-		bus->activity = FALSE;
-		dhdsdio_clkctl(bus, CLK_NONE, TRUE);
-	}
-
-	dhd_os_sdunlock(bus->dhd);
-
-	if (ret)
-		bus->dhd->tx_ctlerrs++;
-	else
-		bus->dhd->tx_ctlpkts++;
-
-	if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT)
-		return -ETIMEDOUT;
-
-	if (ret == BCME_NODEVICE)
-		err_nodevice++;
-	else
-		err_nodevice = 0;
-
-	return ret ? err_nodevice >= ERROR_BCME_NODEVICE_MAX ? -ETIMEDOUT : -EIO : 0;
-}
-
-int
-dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
-{
-	int timeleft;
-	uint rxlen = 0;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (bus->dhd->dongle_reset)
-		return -EIO;
-
-	/* Wait until control frame is available */
-	timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen);
-
-	dhd_os_sdlock(bus->dhd);
-	rxlen = bus->rxlen;
-	bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
-	bus->rxlen = 0;
-	dhd_os_sdunlock(bus->dhd);
-
-	if (rxlen) {
-		DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
-			__FUNCTION__, rxlen, msglen));
-	} else if (timeleft == 0) {
-#ifdef DHD_DEBUG
-		uint32 status, retry = 0;
-		R_SDREG(status, &bus->regs->intstatus, retry);
-		DHD_ERROR(("%s: resumed on timeout, INT status=0x%08X\n",
-			__FUNCTION__, status));
-#else
-		DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
-#endif /* DHD_DEBUG */
-		dhd_os_sdlock(bus->dhd);
-		dhdsdio_checkdied(bus, NULL, 0);
-		dhd_os_sdunlock(bus->dhd);
-	} else {
-		DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
-		dhd_os_sdlock(bus->dhd);
-		dhdsdio_checkdied(bus, NULL, 0);
-		dhd_os_sdunlock(bus->dhd);
-	}
-	if (timeleft == 0) {
-		if (rxlen == 0)
-			bus->dhd->rxcnt_timeout++;
-		DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__,
-			bus->dhd->rxcnt_timeout, rxlen));
-	}
-	else
-		bus->dhd->rxcnt_timeout = 0;
-
-	if (rxlen)
-		bus->dhd->rx_ctlpkts++;
-	else
-		bus->dhd->rx_ctlerrs++;
-
-	if (bus->dhd->rxcnt_timeout >= MAX_CNTL_RX_TIMEOUT)
-		return -ETIMEDOUT;
-
-	if (bus->dhd->dongle_trap_occured)
-		return -EREMOTEIO;
-
-	return rxlen ? (int)rxlen : -EIO;
-}
-
-/* IOVar table */
-enum {
-	IOV_INTR = 1,
-	IOV_POLLRATE,
-	IOV_SDREG,
-	IOV_SBREG,
-	IOV_SDCIS,
-	IOV_MEMBYTES,
-	IOV_RAMSIZE,
-	IOV_RAMSTART,
-#ifdef DHD_DEBUG
-	IOV_CHECKDIED,
-	IOV_SERIALCONS,
-#endif /* DHD_DEBUG */
-	IOV_SET_DOWNLOAD_STATE,
-	IOV_SOCRAM_STATE,
-	IOV_FORCEEVEN,
-	IOV_SDIOD_DRIVE,
-	IOV_READAHEAD,
-	IOV_SDRXCHAIN,
-	IOV_ALIGNCTL,
-	IOV_SDALIGN,
-	IOV_DEVRESET,
-	IOV_CPU,
-#if defined(USE_SDIOFIFO_IOVAR)
-	IOV_WATERMARK,
-	IOV_MESBUSYCTRL,
-#endif /* USE_SDIOFIFO_IOVAR */
-#ifdef SDTEST
-	IOV_PKTGEN,
-	IOV_EXTLOOP,
-#endif /* SDTEST */
-	IOV_SPROM,
-	IOV_TXBOUND,
-	IOV_RXBOUND,
-	IOV_TXMINMAX,
-	IOV_IDLETIME,
-	IOV_IDLECLOCK,
-	IOV_SD1IDLE,
-	IOV_SLEEP,
-	IOV_DONGLEISOLATION,
-	IOV_KSO,
-	IOV_DEVSLEEP,
-	IOV_DEVCAP,
-	IOV_VARS,
-#ifdef SOFTAP
-	IOV_FWPATH,
-#endif
-	IOV_TXGLOMSIZE,
-	IOV_TXGLOMMODE,
-	IOV_HANGREPORT,
-	IOV_TXINRX_THRES
-};
-
-const bcm_iovar_t dhdsdio_iovars[] = {
-	{"intr",	IOV_INTR,	0,	IOVT_BOOL,	0 },
-	{"sleep",	IOV_SLEEP,	0,	IOVT_BOOL,	0 },
-	{"pollrate",	IOV_POLLRATE,	0,	IOVT_UINT32,	0 },
-	{"idletime",	IOV_IDLETIME,	0,	IOVT_INT32,	0 },
-	{"idleclock",	IOV_IDLECLOCK,	0,	IOVT_INT32,	0 },
-	{"sd1idle",	IOV_SD1IDLE,	0,	IOVT_BOOL,	0 },
-	{"membytes",	IOV_MEMBYTES,	0,	IOVT_BUFFER,	2 * sizeof(int) },
-	{"ramsize",	IOV_RAMSIZE,	0,	IOVT_UINT32,	0 },
-	{"ramstart",	IOV_RAMSTART,	0,	IOVT_UINT32,	0 },
-	{"dwnldstate",	IOV_SET_DOWNLOAD_STATE,	0,	IOVT_BOOL,	0 },
-	{"socram_state",	IOV_SOCRAM_STATE,	0,	IOVT_BOOL,	0 },
-	{"vars",	IOV_VARS,	0,	IOVT_BUFFER,	0 },
-	{"sdiod_drive",	IOV_SDIOD_DRIVE, 0,	IOVT_UINT32,	0 },
-	{"readahead",	IOV_READAHEAD,	0,	IOVT_BOOL,	0 },
-	{"sdrxchain",	IOV_SDRXCHAIN,	0,	IOVT_BOOL,	0 },
-	{"alignctl",	IOV_ALIGNCTL,	0,	IOVT_BOOL,	0 },
-	{"sdalign",	IOV_SDALIGN,	0,	IOVT_BOOL,	0 },
-	{"devreset",	IOV_DEVRESET,	0,	IOVT_BOOL,	0 },
-#ifdef DHD_DEBUG
-	{"sdreg",	IOV_SDREG,	0,	IOVT_BUFFER,	sizeof(sdreg_t) },
-	{"sbreg",	IOV_SBREG,	0,	IOVT_BUFFER,	sizeof(sdreg_t) },
-	{"sd_cis",	IOV_SDCIS,	0,	IOVT_BUFFER,	DHD_IOCTL_MAXLEN },
-	{"forcealign",	IOV_FORCEEVEN,	0,	IOVT_BOOL,	0 },
-	{"txbound",	IOV_TXBOUND,	0,	IOVT_UINT32,	0 },
-	{"rxbound",	IOV_RXBOUND,	0,	IOVT_UINT32,	0 },
-	{"txminmax",	IOV_TXMINMAX,	0,	IOVT_UINT32,	0 },
-	{"cpu",		IOV_CPU,	0,	IOVT_BOOL,	0 },
-#ifdef DHD_DEBUG
-	{"checkdied",	IOV_CHECKDIED,	0,	IOVT_BUFFER,	0 },
-	{"serial",	IOV_SERIALCONS,	0,	IOVT_UINT32,	0 },
-#endif /* DHD_DEBUG  */
-#endif /* DHD_DEBUG */
-#ifdef SDTEST
-	{"extloop",	IOV_EXTLOOP,	0,	IOVT_BOOL,	0 },
-	{"pktgen",	IOV_PKTGEN,	0,	IOVT_BUFFER,	sizeof(dhd_pktgen_t) },
-#endif /* SDTEST */
-#if defined(USE_SDIOFIFO_IOVAR)
-	{"watermark",	IOV_WATERMARK,	0,	IOVT_UINT32,	0 },
-	{"mesbusyctrl",	IOV_MESBUSYCTRL,	0,	IOVT_UINT32,	0 },
-#endif /* USE_SDIOFIFO_IOVAR */
-	{"devcap", IOV_DEVCAP,	0,	IOVT_UINT32,	0 },
-	{"dngl_isolation", IOV_DONGLEISOLATION,	0,	IOVT_UINT32,	0 },
-	{"kso",	IOV_KSO,	0,	IOVT_UINT32,	0 },
-	{"devsleep", IOV_DEVSLEEP,	0,	IOVT_UINT32,	0 },
-#ifdef SOFTAP
-	{"fwpath", IOV_FWPATH, 0, IOVT_BUFFER, 0 },
-#endif
-	{"txglomsize", IOV_TXGLOMSIZE, 0, IOVT_UINT32, 0 },
-	{"fw_hang_report", IOV_HANGREPORT, 0, IOVT_BOOL, 0 },
-	{"txinrx_thres", IOV_TXINRX_THRES, 0, IOVT_INT32, 0 },
-	{NULL, 0, 0, 0, 0 }
-};
-
-static void
-dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
-{
-	uint q1, q2;
-
-	if (!div) {
-		bcm_bprintf(strbuf, "%s N/A", desc);
-	} else {
-		q1 = num / div;
-		q2 = (100 * (num - (q1 * div))) / div;
-		bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
-	}
-}
-
-void
-dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
-{
-	dhd_bus_t *bus = dhdp->bus;
-
-	bcm_bprintf(strbuf, "Bus SDIO structure:\n");
-	bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
-	            bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
-	bcm_bprintf(strbuf, "fcstate %d qlen %u tx_seq %d, max %d, rxskip %d rxlen %u rx_seq %d\n",
-	            bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip,
-	            bus->rxlen, bus->rx_seq);
-	bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n",
-	            bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
-	bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n",
-	            bus->pollrate, bus->pollcnt, bus->regfails);
-
-	bcm_bprintf(strbuf, "\nAdditional counters:\n");
-#ifdef DHDENABLE_TAILPAD
-	bcm_bprintf(strbuf, "tx_tailpad_chain %u tx_tailpad_pktget %u\n",
-	            bus->tx_tailpad_chain, bus->tx_tailpad_pktget);
-#endif /* DHDENABLE_TAILPAD */
-	bcm_bprintf(strbuf, "tx_sderrs %u fcqueued %u rxrtx %u rx_toolong %u rxc_errors %u\n",
-	            bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
-	            bus->rxc_errors);
-	bcm_bprintf(strbuf, "rx_hdrfail %u badhdr %u badseq %u\n",
-	            bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
-	bcm_bprintf(strbuf, "fc_rcvd %u, fc_xoff %u, fc_xon %u\n",
-	            bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
-	bcm_bprintf(strbuf, "rxglomfail %u, rxglomframes %u, rxglompkts %u\n",
-	            bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
-	bcm_bprintf(strbuf, "f2rx (hdrs/data) %u (%u/%u), f2tx %u f1regs %u\n",
-	            (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata,
-	            bus->f2txdata, bus->f1regdata);
-	{
-		dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
-		             (bus->f2rxhdrs + bus->f2rxdata));
-		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata);
-		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
-		             (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
-		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount);
-		bcm_bprintf(strbuf, "\n");
-
-		dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
-		             bus->dhd->rx_packets);
-		dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes);
-		bcm_bprintf(strbuf, "\n");
-
-		dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata);
-		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata);
-		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
-		             (bus->f2txdata + bus->f1regdata));
-		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount);
-		bcm_bprintf(strbuf, "\n");
-
-		dhd_dump_pct(strbuf, "Total: pkts/f2rw",
-		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
-		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
-		dhd_dump_pct(strbuf, ", pkts/f1sd",
-		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata);
-		dhd_dump_pct(strbuf, ", pkts/sd",
-		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
-		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
-		dhd_dump_pct(strbuf, ", pkts/int",
-		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount);
-		bcm_bprintf(strbuf, "\n\n");
-	}
-
-#ifdef SDTEST
-	if (bus->pktgen_count) {
-		bcm_bprintf(strbuf, "pktgen config and count:\n");
-		bcm_bprintf(strbuf, "freq %u count %u print %u total %u min %u len %u\n",
-		            bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print,
-		            bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen);
-		bcm_bprintf(strbuf, "send attempts %u rcvd %u fail %u\n",
-		            bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
-	}
-#endif /* SDTEST */
-#ifdef DHD_DEBUG
-	bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
-	            bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
-	bcm_bprintf(strbuf, "blocksize %u roundup %u\n", bus->blocksize, bus->roundup);
-#endif /* DHD_DEBUG */
-	bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
-	            bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping);
-}
-
-void
-dhd_bus_clearcounts(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
-
-	bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
-	bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
-	bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
-#ifdef DHDENABLE_TAILPAD
-	bus->tx_tailpad_chain = bus->tx_tailpad_pktget = 0;
-#endif /* DHDENABLE_TAILPAD */
-	bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
-	bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
-	bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
-}
-
-#ifdef SDTEST
-static int
-dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg)
-{
-	dhd_pktgen_t pktgen;
-
-	pktgen.version = DHD_PKTGEN_VERSION;
-	pktgen.freq = bus->pktgen_freq;
-	pktgen.count = bus->pktgen_count;
-	pktgen.print = bus->pktgen_print;
-	pktgen.total = bus->pktgen_total;
-	pktgen.minlen = bus->pktgen_minlen;
-	pktgen.maxlen = bus->pktgen_maxlen;
-	pktgen.numsent = bus->pktgen_sent;
-	pktgen.numrcvd = bus->pktgen_rcvd;
-	pktgen.numfail = bus->pktgen_fail;
-	pktgen.mode = bus->pktgen_mode;
-	pktgen.stop = bus->pktgen_stop;
-
-	bcopy(&pktgen, arg, sizeof(pktgen));
-
-	return 0;
-}
-
-static int
-dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg)
-{
-	dhd_pktgen_t pktgen;
-	uint oldcnt, oldmode;
-
-	bcopy(arg, &pktgen, sizeof(pktgen));
-	if (pktgen.version != DHD_PKTGEN_VERSION)
-		return BCME_BADARG;
-
-	oldcnt = bus->pktgen_count;
-	oldmode = bus->pktgen_mode;
-
-	bus->pktgen_freq = pktgen.freq;
-	bus->pktgen_count = pktgen.count;
-	bus->pktgen_print = pktgen.print;
-	bus->pktgen_total = pktgen.total;
-	bus->pktgen_minlen = pktgen.minlen;
-	bus->pktgen_maxlen = pktgen.maxlen;
-	bus->pktgen_mode = pktgen.mode;
-	bus->pktgen_stop = pktgen.stop;
-
-	bus->pktgen_tick = bus->pktgen_ptick = 0;
-	bus->pktgen_prev_time = jiffies;
-	bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen);
-	bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen);
-
-	/* Clear counts for a new pktgen (mode change, or was stopped) */
-	if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) {
-		bus->pktgen_sent = bus->pktgen_prev_sent = bus->pktgen_rcvd = 0;
-		bus->pktgen_prev_rcvd = bus->pktgen_fail = 0;
-	}
-
-	return 0;
-}
-#endif /* SDTEST */
-
-static void
-dhdsdio_devram_remap(dhd_bus_t *bus, bool val)
-{
-	uint8 enable, protect, remap;
-
-	si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
-	remap = val ? TRUE : FALSE;
-	si_socdevram(bus->sih, TRUE, &enable, &protect, &remap);
-}
-
-static int
-dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size)
-{
-	int bcmerror = 0;
-	uint32 sdaddr;
-	uint dsize;
-
-	/* In remap mode, adjust address beyond socram and redirect
-	 * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize
-	 * is not backplane accessible
-	 */
-	if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address)) {
-		address -= bus->orig_ramsize;
-		address += SOCDEVRAM_BP_ADDR;
-	}
-
-	/* Determine initial transfer parameters */
-	sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
-	if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
-		dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
-	else
-		dsize = size;
-
-	/* Set the backplane window to include the start address */
-	if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
-		DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
-		goto xfer_done;
-	}
-
-	/* Do the transfer(s) */
-	while (size) {
-		DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
-		          __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr,
-		          (address & SBSDIO_SBWINDOW_MASK)));
-		if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) {
-			DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
-			break;
-		}
-
-		/* Adjust for next transfer (if any) */
-		if ((size -= dsize)) {
-			data += dsize;
-			address += dsize;
-			if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
-				DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
-				break;
-			}
-			sdaddr = 0;
-			dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size);
-		}
-
-	}
-
-xfer_done:
-	/* Return the window to backplane enumeration space for core access */
-	if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
-		DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__,
-			bcmsdh_cur_sbwad(bus->sdh)));
-	}
-
-	return bcmerror;
-}
-
-static int
-dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
-{
-	uint32 addr;
-	int rv, i;
-	uint32 shaddr = 0;
-
-	if (bus->sih == NULL) {
-		if (bus->dhd && bus->dhd->dongle_reset) {
-			DHD_ERROR(("%s: Dongle is in reset state\n", __FUNCTION__));
-			return BCME_NOTREADY;
-		} else {
-			ASSERT(bus->dhd);
-			ASSERT(bus->sih);
-			DHD_ERROR(("%s: The address of sih is invalid\n", __FUNCTION__));
-			return BCME_ERROR;
-		}
-	}
-	if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID && !dhdsdio_sr_cap(bus))
-		bus->srmemsize = 0;
-
-	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
-	i = 0;
-	do {
-		/* Read last word in memory to determine address of sdpcm_shared structure */
-		if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
-			return rv;
-
-		addr = ltoh32(addr);
-
-		DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
-
-		/*
-		 * Check if addr is valid.
-		 * NVRAM length at the end of memory should have been overwritten.
-		 */
-		if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
-			if ((bus->srmemsize > 0) && (i++ == 0)) {
-				shaddr -= bus->srmemsize;
-			} else {
-				DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
-					__FUNCTION__, addr));
-				return BCME_ERROR;
-			}
-		} else
-			break;
-	} while (i < 2);
-
-	/* Read hndrte_shared structure */
-	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
-		return rv;
-
-	/* Endianness */
-	sh->flags = ltoh32(sh->flags);
-	sh->trap_addr = ltoh32(sh->trap_addr);
-	sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
-	sh->assert_file_addr = ltoh32(sh->assert_file_addr);
-	sh->assert_line = ltoh32(sh->assert_line);
-	sh->console_addr = ltoh32(sh->console_addr);
-	sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
-
-	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1)
-		return BCME_OK;
-
-	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
-		DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
-		           "is different than sdpcm_shared version %d in dongle\n",
-		           __FUNCTION__, SDPCM_SHARED_VERSION,
-		           sh->flags & SDPCM_SHARED_VERSION_MASK));
-		return BCME_ERROR;
-	}
-
-	return BCME_OK;
-}
-
-#define CONSOLE_LINE_MAX	192
-
-#ifdef DHD_DEBUG
-static int
-dhdsdio_readconsole(dhd_bus_t *bus)
-{
-	dhd_console_t *c = &bus->console;
-	uint8 line[CONSOLE_LINE_MAX], ch;
-	uint32 n, idx, addr;
-	int rv;
-
-	/* Don't do anything until FWREADY updates console address */
-	if (bus->console_addr == 0)
-		return 0;
-
-	if (!KSO_ENAB(bus))
-		return 0;
-
-	/* Read console log struct */
-	addr = bus->console_addr + OFFSETOF(hnd_cons_t, log);
-	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
-		return rv;
-
-	/* Allocate console buffer (one time only) */
-	if (c->buf == NULL) {
-		c->bufsize = ltoh32(c->log.buf_size);
-		if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
-			return BCME_NOMEM;
-	}
-
-	idx = ltoh32(c->log.idx);
-
-	/* Protect against corrupt value */
-	if (idx > c->bufsize)
-		return BCME_ERROR;
-
-	/* Skip reading the console buffer if the index pointer has not moved */
-	if (idx == c->last)
-		return BCME_OK;
-
-	/* Read the console buffer */
-	addr = ltoh32(c->log.buf);
-	if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
-		return rv;
-
-	while (c->last != idx) {
-		for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
-			if (c->last == idx) {
-				/* This would output a partial line.  Instead, back up
-				 * the buffer pointer and output this line next time around.
-				 */
-				if (c->last >= n)
-					c->last -= n;
-				else
-					c->last = c->bufsize - n;
-				goto break2;
-			}
-			ch = c->buf[c->last];
-			c->last = (c->last + 1) % c->bufsize;
-			if (ch == '\n')
-				break;
-			line[n] = ch;
-		}
-
-		if (n > 0) {
-			if (line[n - 1] == '\r')
-				n--;
-			line[n] = 0;
-			printf("CONSOLE: %s\n", line);
-#ifdef LOG_INTO_TCPDUMP
-			dhd_sendup_log(bus->dhd, line, n);
-#endif /* LOG_INTO_TCPDUMP */
-		}
-	}
-break2:
-
-	return BCME_OK;
-}
-#endif /* DHD_DEBUG */
-
-static int
-dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size)
-{
-	int bcmerror = 0;
-	uint msize = 512;
-	char *mbuffer = NULL;
-	char *console_buffer = NULL;
-	uint maxstrlen = 256;
-	char *str = NULL;
-	trap_t tr;
-	sdpcm_shared_t sdpcm_shared;
-	struct bcmstrbuf strbuf;
-	uint32 console_ptr, console_size, console_index;
-	uint8 line[CONSOLE_LINE_MAX], ch;
-	uint32 n, i, addr;
-	int rv;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (DHD_NOCHECKDIED_ON())
-		return 0;
-
-	if (data == NULL) {
-		/*
-		 * Called after a rx ctrl timeout. "data" is NULL.
-		 * allocate memory to trace the trap or assert.
-		 */
-		size = msize;
-		mbuffer = data = MALLOC(bus->dhd->osh, msize);
-		if (mbuffer == NULL) {
-			DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize));
-			bcmerror = BCME_NOMEM;
-			goto done;
-		}
-	}
-
-	if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) {
-		DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen));
-		bcmerror = BCME_NOMEM;
-		goto done;
-	}
-
-	if ((bcmerror = dhdsdio_readshared(bus, &sdpcm_shared)) < 0)
-		goto done;
-
-	bcm_binit(&strbuf, data, size);
-
-	bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address  : 0x%08X\n",
-	            sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
-
-	if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
-		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
-		 * (Avoids conflict with real asserts for programmatic parsing of output.)
-		 */
-		bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
-	}
-
-	if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) {
-		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
-		 * (Avoids conflict with real asserts for programmatic parsing of output.)
-		 */
-		bcm_bprintf(&strbuf, "No trap%s in dongle",
-		          (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
-		          ?"/assrt" :"");
-	} else {
-		if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
-			/* Download assert */
-			bcm_bprintf(&strbuf, "Dongle assert");
-			if (sdpcm_shared.assert_exp_addr != 0) {
-				str[0] = '\0';
-				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
-				                                 sdpcm_shared.assert_exp_addr,
-				                                 (uint8 *)str, maxstrlen)) < 0)
-					goto done;
-
-				str[maxstrlen - 1] = '\0';
-				bcm_bprintf(&strbuf, " expr \"%s\"", str);
-			}
-
-			if (sdpcm_shared.assert_file_addr != 0) {
-				str[0] = '\0';
-				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
-				                                 sdpcm_shared.assert_file_addr,
-				                                 (uint8 *)str, maxstrlen)) < 0)
-					goto done;
-
-				str[maxstrlen - 1] = '\0';
-				bcm_bprintf(&strbuf, " file \"%s\"", str);
-			}
-
-			bcm_bprintf(&strbuf, " line %d ", sdpcm_shared.assert_line);
-		}
-
-		if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
-			bus->dhd->dongle_trap_occured = TRUE;
-			if ((bcmerror = dhdsdio_membytes(bus, FALSE,
-			                                 sdpcm_shared.trap_addr,
-			                                 (uint8*)&tr, sizeof(trap_t))) < 0)
-				goto done;
-
-			bcm_bprintf(&strbuf,
-			"Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
-			            "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
-			"r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, "
-			"r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
-			ltoh32(tr.type), ltoh32(tr.epc), ltoh32(tr.cpsr), ltoh32(tr.spsr),
-			ltoh32(tr.r13), ltoh32(tr.r14), ltoh32(tr.pc),
-			ltoh32(sdpcm_shared.trap_addr),
-			ltoh32(tr.r0), ltoh32(tr.r1), ltoh32(tr.r2), ltoh32(tr.r3),
-			ltoh32(tr.r4), ltoh32(tr.r5), ltoh32(tr.r6), ltoh32(tr.r7));
-
-			addr = sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log);
-			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
-				(uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
-				goto printbuf;
-
-			addr = sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.buf_size);
-			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
-				(uint8 *)&console_size, sizeof(console_size))) < 0)
-				goto printbuf;
-
-			addr = sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.idx);
-			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
-				(uint8 *)&console_index, sizeof(console_index))) < 0)
-				goto printbuf;
-
-			console_ptr = ltoh32(console_ptr);
-			console_size = ltoh32(console_size);
-			console_index = ltoh32(console_index);
-
-			if (console_size > CONSOLE_BUFFER_MAX ||
-				!(console_buffer = MALLOC(bus->dhd->osh, console_size)))
-				goto printbuf;
-
-			if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr,
-				(uint8 *)console_buffer, console_size)) < 0)
-				goto printbuf;
-
-			for (i = 0, n = 0; i < console_size; i += n + 1) {
-				for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
-					ch = console_buffer[(console_index + i + n) % console_size];
-					if (ch == '\n')
-						break;
-					line[n] = ch;
-				}
-
-
-				if (n > 0) {
-					if (line[n - 1] == '\r')
-						n--;
-					line[n] = 0;
-					/* Don't use DHD_ERROR macro since we print
-					 * a lot of information quickly. The macro
-					 * will truncate a lot of the printfs
-					 */
-
-					if (dhd_msg_level & DHD_ERROR_VAL)
-						printf("CONSOLE: %s\n", line);
-				}
-			}
-		}
-	}
-
-printbuf:
-	if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
-		DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
-	}
-
-#if defined(DHD_FW_COREDUMP)
-	if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
-		/* Mem dump to a file on device */
-		dhdsdio_mem_dump(bus);
-	}
-#endif /* #if defined(DHD_FW_COREDUMP) */
-
-done:
-	if (mbuffer)
-		MFREE(bus->dhd->osh, mbuffer, msize);
-	if (str)
-		MFREE(bus->dhd->osh, str, maxstrlen);
-	if (console_buffer)
-		MFREE(bus->dhd->osh, console_buffer, console_size);
-
-	return bcmerror;
-}
-
-#if defined(DHD_FW_COREDUMP)
-static int
-dhdsdio_mem_dump(dhd_bus_t *bus)
-{
-	int ret = 0;
-	int size; /* Full mem size */
-	int start = bus->dongle_ram_base; /* Start address */
-	int read_size = 0; /* Read size of each iteration */
-	uint8 *buf = NULL, *databuf = NULL;
-
-	/* Get full mem size */
-	size = bus->ramsize;
-	buf = MALLOC(bus->dhd->osh, size);
-	if (!buf) {
-		printf("%s: Out of memory (%d bytes)\n", __FUNCTION__, size);
-		return -1;
-	}
-
-	/* Read mem content */
-	printf("Dump dongle memory");
-	databuf = buf;
-	while (size)
-	{
-		read_size = MIN(MEMBLOCK, size);
-		if ((ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size)))
-		{
-			printf("%s: Error membytes %d\n", __FUNCTION__, ret);
-			if (buf) {
-				MFREE(bus->dhd->osh, buf, size);
-			}
-			return -1;
-		}
-		/* Decrement size and increment start address */
-		size -= read_size;
-		start += read_size;
-		databuf += read_size;
-	}
-	printf("Done\n");
-
-	dhd_save_fwdump(bus->dhd, buf, bus->ramsize);
-	/* free buf before return !!! */
-	if (write_to_file(bus->dhd, buf, bus->ramsize))
-	{
-		printf("%s: Error writing to files\n", __FUNCTION__);
-		return -1;
-	}
-
-	/* buf free handled in write_to_file, not here */
-	return 0;
-}
-#endif /* DHD_FW_COREDUMP */
-
-int
-dhd_socram_dump(dhd_bus_t * bus)
-{
-#if defined(DHD_FW_COREDUMP)
-	return (dhdsdio_mem_dump(bus));
-#else
-	return -1;
-#endif
-}
-
-int
-dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
-{
-	int bcmerror = BCME_OK;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	/* Basic sanity checks */
-	if (bus->dhd->up) {
-		bcmerror = BCME_NOTDOWN;
-		goto err;
-	}
-	if (!len) {
-		bcmerror = BCME_BUFTOOSHORT;
-		goto err;
-	}
-
-	/* Free the old ones and replace with passed variables */
-	if (bus->vars)
-		MFREE(bus->dhd->osh, bus->vars, bus->varsz);
-
-	bus->vars = MALLOC(bus->dhd->osh, len);
-	bus->varsz = bus->vars ? len : 0;
-	if (bus->vars == NULL) {
-		bcmerror = BCME_NOMEM;
-		goto err;
-	}
-
-	/* Copy the passed variables, which should include the terminating double-null */
-	bcopy(arg, bus->vars, bus->varsz);
-err:
-	return bcmerror;
-}
-
-#ifdef DHD_DEBUG
-
-#define CC_PLL_CHIPCTRL_SERIAL_ENAB		(1  << 24)
-#define CC_CHIPCTRL_JTAG_SEL			(1  << 3)
-#define CC_CHIPCTRL_GPIO_SEL				(0x3)
-#define CC_PLL_CHIPCTRL_SERIAL_ENAB_4334	(1  << 28)
-
-static int
-dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror)
-{
-	int int_val;
-	uint32 addr, data, uart_enab = 0;
-	uint32 jtag_sel = CC_CHIPCTRL_JTAG_SEL;
-	uint32 gpio_sel = CC_CHIPCTRL_GPIO_SEL;
-
-	addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
-	data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
-	*bcmerror = 0;
-
-	bcmsdh_reg_write(bus->sdh, addr, 4, 1);
-	if (bcmsdh_regfail(bus->sdh)) {
-		*bcmerror = BCME_SDIO_ERROR;
-		return -1;
-	}
-	int_val = bcmsdh_reg_read(bus->sdh, data, 4);
-	if (bcmsdh_regfail(bus->sdh)) {
-		*bcmerror = BCME_SDIO_ERROR;
-		return -1;
-	}
-	if (bus->sih->chip == BCM4330_CHIP_ID) {
-		uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB;
-	}
-	else if (bus->sih->chip == BCM4334_CHIP_ID ||
-		bus->sih->chip == BCM43340_CHIP_ID ||
-		bus->sih->chip == BCM43341_CHIP_ID ||
-		bus->sih->chip == BCM43342_CHIP_ID ||
-		0) {
-		if (enable) {
-			/* Moved to PMU chipcontrol 1 from 4330 */
-			int_val &= ~gpio_sel;
-			int_val |= jtag_sel;
-		} else {
-			int_val |= gpio_sel;
-			int_val &= ~jtag_sel;
-		}
-		uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB_4334;
-	}
-
-	if (!set)
-		return (int_val & uart_enab);
-	if (enable)
-		int_val |= uart_enab;
-	else
-		int_val &= ~uart_enab;
-	bcmsdh_reg_write(bus->sdh, data, 4, int_val);
-	if (bcmsdh_regfail(bus->sdh)) {
-		*bcmerror = BCME_SDIO_ERROR;
-		return -1;
-	}
-	if (bus->sih->chip == BCM4330_CHIP_ID) {
-		uint32 chipcontrol;
-		addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol);
-		chipcontrol = bcmsdh_reg_read(bus->sdh, addr, 4);
-		chipcontrol &= ~jtag_sel;
-		if (enable) {
-			chipcontrol |=  jtag_sel;
-			chipcontrol &= ~gpio_sel;
-		}
-		bcmsdh_reg_write(bus->sdh, addr, 4, chipcontrol);
-	}
-
-	return (int_val & uart_enab);
-}
-#endif 
-
-static int
-dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
-                void *params, int plen, void *arg, int len, int val_size)
-{
-	int bcmerror = 0;
-	int32 int_val = 0;
-	bool bool_val = 0;
-
-	DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
-	           __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
-
-	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
-		goto exit;
-
-	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
-
-	bool_val = (int_val != 0) ? TRUE : FALSE;
-
-
-	/* Some ioctls use the bus */
-	dhd_os_sdlock(bus->dhd);
-
-	/* Check if dongle is in reset. If so, only allow DEVRESET iovars */
-	if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
-	                                actionid == IOV_GVAL(IOV_DEVRESET))) {
-		bcmerror = BCME_NOTREADY;
-		goto exit;
-	}
-
-	/*
-	 * Special handling for keepSdioOn: New SDIO Wake-up Mechanism
-	 */
-	if ((vi->varid == IOV_KSO) && (IOV_ISSET(actionid))) {
-		dhdsdio_clk_kso_iovar(bus, bool_val);
-		goto exit;
-	} else if ((vi->varid == IOV_DEVSLEEP) && (IOV_ISSET(actionid))) {
-		{
-			dhdsdio_clk_devsleep_iovar(bus, bool_val);
-			if (!SLPAUTO_ENAB(bus) && (bool_val == FALSE) && (bus->ipend)) {
-				DHD_ERROR(("INT pending in devsleep 1, dpc_sched: %d\n",
-					bus->dpc_sched));
-				if (!bus->dpc_sched) {
-					bus->dpc_sched = TRUE;
-					dhd_sched_dpc(bus->dhd);
-				}
-			}
-		}
-		goto exit;
-	}
-
-	/* Handle sleep stuff before any clock mucking */
-	if (vi->varid == IOV_SLEEP) {
-		if (IOV_ISSET(actionid)) {
-			bcmerror = dhdsdio_bussleep(bus, bool_val);
-		} else {
-			int_val = (int32)bus->sleeping;
-			bcopy(&int_val, arg, val_size);
-		}
-		goto exit;
-	}
-
-	/* Request clock to allow SDIO accesses */
-	if (!bus->dhd->dongle_reset) {
-		BUS_WAKE(bus);
-		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-	}
-
-	switch (actionid) {
-	case IOV_GVAL(IOV_INTR):
-		int_val = (int32)bus->intr;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_INTR):
-		bus->intr = bool_val;
-		bus->intdis = FALSE;
-		if (bus->dhd->up) {
-			if (bus->intr) {
-				DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
-				bcmsdh_intr_enable(bus->sdh);
-			} else {
-				DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
-				bcmsdh_intr_disable(bus->sdh);
-			}
-		}
-		break;
-
-	case IOV_GVAL(IOV_POLLRATE):
-		int_val = (int32)bus->pollrate;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_POLLRATE):
-		bus->pollrate = (uint)int_val;
-		bus->poll = (bus->pollrate != 0);
-		break;
-
-	case IOV_GVAL(IOV_IDLETIME):
-		int_val = bus->idletime;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_IDLETIME):
-		if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) {
-			bcmerror = BCME_BADARG;
-		} else {
-			bus->idletime = int_val;
-		}
-		break;
-
-	case IOV_GVAL(IOV_IDLECLOCK):
-		int_val = (int32)bus->idleclock;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_IDLECLOCK):
-		bus->idleclock = int_val;
-		break;
-
-	case IOV_GVAL(IOV_SD1IDLE):
-		int_val = (int32)sd1idle;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_SD1IDLE):
-		sd1idle = bool_val;
-		break;
-
-
-	case IOV_SVAL(IOV_MEMBYTES):
-	case IOV_GVAL(IOV_MEMBYTES):
-	{
-		uint32 address;
-		uint size, dsize;
-		uint8 *data;
-
-		bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
-
-		ASSERT(plen >= 2*sizeof(int));
-
-		address = (uint32)int_val;
-		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
-		size = (uint)int_val;
-
-		/* Do some validation */
-		dsize = set ? plen - (2 * sizeof(int)) : len;
-		if (dsize < size) {
-			DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
-			           __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
-			bcmerror = BCME_BADARG;
-			break;
-		}
-
-		DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
-		          (set ? "write" : "read"), size, address));
-
-		/* check if CR4 */
-		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
-			/*
-			 * If address is start of RAM (i.e. a downloaded image),
-			 * store the reset instruction to be written in 0
-			 */
-			if (set && address == bus->dongle_ram_base) {
-				bus->resetinstr = *(((uint32*)params) + 2);
-			}
-		} else {
-		/* If we know about SOCRAM, check for a fit */
-		if ((bus->orig_ramsize) &&
-		    ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize)))
-		{
-			uint8 enable, protect, remap;
-			si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
-			if (!enable || protect) {
-				DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n",
-					__FUNCTION__, bus->orig_ramsize, size, address));
-				DHD_ERROR(("%s: socram enable %d, protect %d\n",
-					__FUNCTION__, enable, protect));
-				bcmerror = BCME_BADARG;
-				break;
-			}
-
-			if (!REMAP_ENAB(bus) && (address >= SOCDEVRAM_ARM_ADDR)) {
-				uint32 devramsize = si_socdevram_size(bus->sih);
-				if ((address < SOCDEVRAM_ARM_ADDR) ||
-					(address + size > (SOCDEVRAM_ARM_ADDR + devramsize))) {
-					DHD_ERROR(("%s: bad address 0x%08x, size 0x%08x\n",
-						__FUNCTION__, address, size));
-					DHD_ERROR(("%s: socram range 0x%08x,size 0x%08x\n",
-						__FUNCTION__, SOCDEVRAM_ARM_ADDR, devramsize));
-					bcmerror = BCME_BADARG;
-					break;
-				}
-				/* move it such that address is real now */
-				address -= SOCDEVRAM_ARM_ADDR;
-				address += SOCDEVRAM_BP_ADDR;
-				DHD_INFO(("%s: Request to %s %d bytes @ Mapped address 0x%08x\n",
-					__FUNCTION__, (set ? "write" : "read"), size, address));
-			} else if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address) && remap) {
-				/* Can not access remap region while devram remap bit is set
-				 * ROM content would be returned in this case
-				 */
-				DHD_ERROR(("%s: Need to disable remap for address 0x%08x\n",
-					__FUNCTION__, address));
-				bcmerror = BCME_ERROR;
-				break;
-			}
-		}
-		}
-
-		/* Generate the actual data pointer */
-		data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
-
-		/* Call to do the transfer */
-		bcmerror = dhdsdio_membytes(bus, set, address, data, size);
-
-		break;
-	}
-
-	case IOV_GVAL(IOV_RAMSIZE):
-		int_val = (int32)bus->ramsize;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_RAMSTART):
-		int_val = (int32)bus->dongle_ram_base;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_SDIOD_DRIVE):
-		int_val = (int32)dhd_sdiod_drive_strength;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_SDIOD_DRIVE):
-		dhd_sdiod_drive_strength = int_val;
-		si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength);
-		break;
-
-	case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):
-		bcmerror = dhdsdio_download_state(bus, bool_val);
-		break;
-
-	case IOV_SVAL(IOV_SOCRAM_STATE):
-		bcmerror = dhdsdio_download_state(bus, bool_val);
-		break;
-
-	case IOV_SVAL(IOV_VARS):
-		bcmerror = dhdsdio_downloadvars(bus, arg, len);
-		break;
-
-	case IOV_GVAL(IOV_READAHEAD):
-		int_val = (int32)dhd_readahead;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_READAHEAD):
-		if (bool_val && !dhd_readahead)
-			bus->nextlen = 0;
-		dhd_readahead = bool_val;
-		break;
-
-	case IOV_GVAL(IOV_SDRXCHAIN):
-		int_val = (int32)bus->use_rxchain;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_SDRXCHAIN):
-		if (bool_val && !bus->sd_rxchain)
-			bcmerror = BCME_UNSUPPORTED;
-		else
-			bus->use_rxchain = bool_val;
-		break;
-	case IOV_GVAL(IOV_ALIGNCTL):
-		int_val = (int32)dhd_alignctl;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_ALIGNCTL):
-		dhd_alignctl = bool_val;
-		break;
-
-	case IOV_GVAL(IOV_SDALIGN):
-		int_val = DHD_SDALIGN;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-#ifdef DHD_DEBUG
-	case IOV_GVAL(IOV_VARS):
-		if (bus->varsz < (uint)len)
-			bcopy(bus->vars, arg, bus->varsz);
-		else
-			bcmerror = BCME_BUFTOOSHORT;
-		break;
-#endif /* DHD_DEBUG */
-
-#ifdef DHD_DEBUG
-	case IOV_GVAL(IOV_SDREG):
-	{
-		sdreg_t *sd_ptr;
-		uint32 addr, size;
-
-		sd_ptr = (sdreg_t *)params;
-
-		addr = (uint32)((ulong)bus->regs + sd_ptr->offset);
-		size = sd_ptr->func;
-		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
-		if (bcmsdh_regfail(bus->sdh))
-			bcmerror = BCME_SDIO_ERROR;
-		bcopy(&int_val, arg, sizeof(int32));
-		break;
-	}
-
-	case IOV_SVAL(IOV_SDREG):
-	{
-		sdreg_t *sd_ptr;
-		uint32 addr, size;
-
-		sd_ptr = (sdreg_t *)params;
-
-		addr = (uint32)((ulong)bus->regs + sd_ptr->offset);
-		size = sd_ptr->func;
-		bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
-		if (bcmsdh_regfail(bus->sdh))
-			bcmerror = BCME_SDIO_ERROR;
-		break;
-	}
-
-	/* Same as above, but offset is not backplane (not SDIO core) */
-	case IOV_GVAL(IOV_SBREG):
-	{
-		sdreg_t sdreg;
-		uint32 addr, size;
-
-		bcopy(params, &sdreg, sizeof(sdreg));
-
-		addr = SI_ENUM_BASE + sdreg.offset;
-		size = sdreg.func;
-		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
-		if (bcmsdh_regfail(bus->sdh))
-			bcmerror = BCME_SDIO_ERROR;
-		bcopy(&int_val, arg, sizeof(int32));
-		break;
-	}
-
-	case IOV_SVAL(IOV_SBREG):
-	{
-		sdreg_t sdreg;
-		uint32 addr, size;
-
-		bcopy(params, &sdreg, sizeof(sdreg));
-
-		addr = SI_ENUM_BASE + sdreg.offset;
-		size = sdreg.func;
-		bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
-		if (bcmsdh_regfail(bus->sdh))
-			bcmerror = BCME_SDIO_ERROR;
-		break;
-	}
-
-	case IOV_GVAL(IOV_SDCIS):
-	{
-		*(char *)arg = 0;
-
-		bcmstrcat(arg, "\nFunc 0\n");
-		bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
-		bcmstrcat(arg, "\nFunc 1\n");
-		bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
-		bcmstrcat(arg, "\nFunc 2\n");
-		bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
-		break;
-	}
-
-	case IOV_GVAL(IOV_FORCEEVEN):
-		int_val = (int32)forcealign;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_FORCEEVEN):
-		forcealign = bool_val;
-		break;
-
-	case IOV_GVAL(IOV_TXBOUND):
-		int_val = (int32)dhd_txbound;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_TXBOUND):
-		dhd_txbound = (uint)int_val;
-		break;
-
-	case IOV_GVAL(IOV_RXBOUND):
-		int_val = (int32)dhd_rxbound;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_RXBOUND):
-		dhd_rxbound = (uint)int_val;
-		break;
-
-	case IOV_GVAL(IOV_TXMINMAX):
-		int_val = (int32)dhd_txminmax;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_TXMINMAX):
-		dhd_txminmax = (uint)int_val;
-		break;
-
-	case IOV_GVAL(IOV_SERIALCONS):
-		int_val = dhd_serialconsole(bus, FALSE, 0, &bcmerror);
-		if (bcmerror != 0)
-			break;
-
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_SERIALCONS):
-		dhd_serialconsole(bus, TRUE, bool_val, &bcmerror);
-		break;
-
-
-#endif /* DHD_DEBUG */
-
-
-#ifdef SDTEST
-	case IOV_GVAL(IOV_EXTLOOP):
-		int_val = (int32)bus->ext_loop;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_EXTLOOP):
-		bus->ext_loop = bool_val;
-		break;
-
-	case IOV_GVAL(IOV_PKTGEN):
-		bcmerror = dhdsdio_pktgen_get(bus, arg);
-		break;
-
-	case IOV_SVAL(IOV_PKTGEN):
-		bcmerror = dhdsdio_pktgen_set(bus, arg);
-		break;
-#endif /* SDTEST */
-
-#if defined(USE_SDIOFIFO_IOVAR)
-	case IOV_GVAL(IOV_WATERMARK):
-		int_val = (int32)watermark;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_WATERMARK):
-		watermark = (uint)int_val;
-		watermark = (watermark > SBSDIO_WATERMARK_MASK) ? SBSDIO_WATERMARK_MASK : watermark;
-		DHD_ERROR(("Setting watermark as 0x%x.\n", watermark));
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, NULL);
-		break;
-
-	case IOV_GVAL(IOV_MESBUSYCTRL):
-		int_val = (int32)mesbusyctrl;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_MESBUSYCTRL):
-		mesbusyctrl = (uint)int_val;
-		mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK)
-			? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl;
-		DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl));
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
-			((uint8)mesbusyctrl | 0x80), NULL);
-		break;
-#endif 
-
-
-	case IOV_GVAL(IOV_DONGLEISOLATION):
-		int_val = bus->dhd->dongle_isolation;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DONGLEISOLATION):
-		bus->dhd->dongle_isolation = bool_val;
-		break;
-
-	case IOV_SVAL(IOV_DEVRESET):
-		DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n",
-		           __FUNCTION__, bool_val, bus->dhd->dongle_reset,
-		           bus->dhd->busstate));
-
-		ASSERT(bus->dhd->osh);
-		/* ASSERT(bus->cl_devid); */
-
-		dhd_bus_devreset(bus->dhd, (uint8)bool_val);
-
-		break;
-	/*
-	 * softap firmware is updated through module parameter or android private command
-	 */
-
-	case IOV_GVAL(IOV_DEVRESET):
-		DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
-
-		/* Get its status */
-		int_val = (bool) bus->dhd->dongle_reset;
-		bcopy(&int_val, arg, val_size);
-
-		break;
-
-	case IOV_GVAL(IOV_KSO):
-		int_val = dhdsdio_sleepcsr_get(bus);
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_DEVCAP):
-		int_val = dhdsdio_devcap_get(bus);
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DEVCAP):
-		dhdsdio_devcap_set(bus, (uint8) int_val);
-		break;
-	case IOV_GVAL(IOV_TXGLOMSIZE):
-		int_val = (int32)bus->txglomsize;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_SVAL(IOV_TXGLOMSIZE):
-		if (int_val > SDPCM_MAXGLOM_SIZE) {
-			bcmerror = BCME_ERROR;
-		} else {
-			bus->txglomsize = (uint)int_val;
-		}
-		break;
-	case IOV_SVAL(IOV_HANGREPORT):
-		bus->dhd->hang_report = bool_val;
-		DHD_ERROR(("%s: Set hang_report as %d\n", __FUNCTION__, bus->dhd->hang_report));
-		break;
-
-	case IOV_GVAL(IOV_HANGREPORT):
-		int_val = (int32)bus->dhd->hang_report;
-		bcopy(&int_val, arg, val_size);
-		break;
-
-	case IOV_GVAL(IOV_TXINRX_THRES):
-		int_val = bus->txinrx_thres;
-		bcopy(&int_val, arg, val_size);
-		break;
-	case IOV_SVAL(IOV_TXINRX_THRES):
-		if (int_val < 0) {
-			bcmerror = BCME_BADARG;
-		} else {
-			bus->txinrx_thres = int_val;
-		}
-		break;
-
-	default:
-		bcmerror = BCME_UNSUPPORTED;
-		break;
-	}
-
-exit:
-	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
-		bus->activity = FALSE;
-		dhdsdio_clkctl(bus, CLK_NONE, TRUE);
-	}
-
-	dhd_os_sdunlock(bus->dhd);
-
-	return bcmerror;
-}
-
-static int
-dhdsdio_write_vars(dhd_bus_t *bus)
-{
-	int bcmerror = 0;
-	uint32 varsize, phys_size;
-	uint32 varaddr;
-	uint8 *vbuffer;
-	uint32 varsizew;
-#ifdef DHD_DEBUG
-	uint8 *nvram_ularray;
-#endif /* DHD_DEBUG */
-
-	/* Even if there are no vars are to be written, we still need to set the ramsize. */
-	varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
-	varaddr = (bus->ramsize - 4) - varsize;
-
-	varaddr += bus->dongle_ram_base;
-
-	if (bus->vars) {
-		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 7)) {
-			if (((varaddr & 0x3C) == 0x3C) && (varsize > 4)) {
-				DHD_ERROR(("PR85623WAR in place\n"));
-				varsize += 4;
-				varaddr -= 4;
-			}
-		}
-
-		vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
-		if (!vbuffer)
-			return BCME_NOMEM;
-
-		bzero(vbuffer, varsize);
-		bcopy(bus->vars, vbuffer, bus->varsz);
-
-		/* Write the vars list */
-		bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize);
-#ifdef DHD_DEBUG
-		/* Verify NVRAM bytes */
-		DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
-		nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize);
-		if (!nvram_ularray)
-			return BCME_NOMEM;
-
-		/* Upload image to verify downloaded contents. */
-		memset(nvram_ularray, 0xaa, varsize);
-
-		/* Read the vars list to temp buffer for comparison */
-		bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
-		if (bcmerror) {
-				DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
-					__FUNCTION__, bcmerror, varsize, varaddr));
-		}
-		/* Compare the org NVRAM with the one read from RAM */
-		if (memcmp(vbuffer, nvram_ularray, varsize)) {
-			DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
-		} else
-			DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
-			__FUNCTION__));
-
-		MFREE(bus->dhd->osh, nvram_ularray, varsize);
-#endif /* DHD_DEBUG */
-
-		MFREE(bus->dhd->osh, vbuffer, varsize);
-	}
-
-	phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize;
-
-	phys_size += bus->dongle_ram_base;
-
-	/* adjust to the user specified RAM */
-	DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
-		phys_size, bus->ramsize));
-	DHD_INFO(("Vars are at %d, orig varsize is %d\n",
-		varaddr, varsize));
-	varsize = ((phys_size - 4) - varaddr);
-
-	/*
-	 * Determine the length token:
-	 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
-	 */
-	if (bcmerror) {
-		varsizew = 0;
-	} else {
-		varsizew = varsize / 4;
-		varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
-		varsizew = htol32(varsizew);
-	}
-
-	DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
-
-	/* Write the length token to the last word */
-	bcmerror = dhdsdio_membytes(bus, TRUE, (phys_size - 4),
-		(uint8*)&varsizew, 4);
-
-	return bcmerror;
-}
-
-static int
-dhdsdio_download_state(dhd_bus_t *bus, bool enter)
-{
-	uint retries;
-	int bcmerror = 0;
-	int foundcr4 = 0;
-
-	if (!bus->sih)
-		return BCME_ERROR;
-	/* To enter download state, disable ARM and reset SOCRAM.
-	 * To exit download state, simply reset ARM (default is RAM boot).
-	 */
-	if (enter) {
-		bus->alp_only = TRUE;
-
-		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
-		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
-			if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
-				foundcr4 = 1;
-			} else {
-				DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-		}
-
-		if (!foundcr4) {
-			si_core_disable(bus->sih, 0);
-			if (bcmsdh_regfail(bus->sdh)) {
-				bcmerror = BCME_SDIO_ERROR;
-				goto fail;
-			}
-
-			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-
-			si_core_reset(bus->sih, 0, 0);
-			if (bcmsdh_regfail(bus->sdh)) {
-				DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n",
-				           __FUNCTION__));
-				bcmerror = BCME_SDIO_ERROR;
-				goto fail;
-			}
-
-			/* Disable remap for download */
-			if (REMAP_ENAB(bus) && si_socdevram_remap_isenb(bus->sih))
-				dhdsdio_devram_remap(bus, FALSE);
-
-			if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID) {
-				/* Disabling Remap for SRAM_3 */
-				si_socram_set_bankpda(bus->sih, 0x3, 0x0);
-			}
-
-			/* Clear the top bit of memory */
-			if (bus->ramsize) {
-				uint32 zeros = 0;
-				if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4,
-				                     (uint8*)&zeros, 4) < 0) {
-					bcmerror = BCME_SDIO_ERROR;
-					goto fail;
-				}
-			}
-		} else {
-			/* For CR4,
-			 * Halt ARM
-			 * Remove ARM reset
-			 * Read RAM base address [0x18_0000]
-			 * [next] Download firmware
-			 * [done at else] Populate the reset vector
-			 * [done at else] Remove ARM halt
-			*/
-			/* Halt ARM & remove reset */
-			si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT);
-		}
-	} else {
-		if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
-			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-
-			if (!si_iscoreup(bus->sih)) {
-				DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-
-			if ((bcmerror = dhdsdio_write_vars(bus))) {
-				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
-				goto fail;
-			}
-
-			/* Enable remap before ARM reset but after vars.
-			 * No backplane access in remap mode
-			 */
-			if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih))
-				dhdsdio_devram_remap(bus, TRUE);
-
-			if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
-			    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
-				DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-			W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
-
-
-			if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
-			    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-		} else {
-			/* cr4 has no socram, but tcm's */
-			/* write vars */
-			if ((bcmerror = dhdsdio_write_vars(bus))) {
-				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
-				goto fail;
-			}
-
-			if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
-			    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
-				DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-			W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
-
-			/* switch back to arm core again */
-			if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
-				DHD_ERROR(("%s: Failed to find ARM CR4 core!\n", __FUNCTION__));
-				bcmerror = BCME_ERROR;
-				goto fail;
-			}
-			/* write address 0 with reset instruction */
-			bcmerror = dhdsdio_membytes(bus, TRUE, 0,
-				(uint8 *)&bus->resetinstr, sizeof(bus->resetinstr));
-
-			if (bcmerror == BCME_OK) {
-				uint32 tmp;
-
-				/* verify write */
-				bcmerror = dhdsdio_membytes(bus, FALSE, 0,
-				                            (uint8 *)&tmp, sizeof(tmp));
-
-				if (bcmerror == BCME_OK && tmp != bus->resetinstr) {
-					DHD_ERROR(("%s: Failed to write 0x%08x to addr 0\n",
-					          __FUNCTION__, bus->resetinstr));
-					DHD_ERROR(("%s: contents of addr 0 is 0x%08x\n",
-					          __FUNCTION__, tmp));
-					bcmerror = BCME_SDIO_ERROR;
-					goto fail;
-				}
-			}
-
-			/* now remove reset and halt and continue to run CR4 */
-		}
-
-		si_core_reset(bus->sih, 0, 0);
-		if (bcmsdh_regfail(bus->sdh)) {
-			DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__));
-			bcmerror = BCME_SDIO_ERROR;
-			goto fail;
-		}
-
-		/* Allow HT Clock now that the ARM is running. */
-		bus->alp_only = FALSE;
-
-		bus->dhd->busstate = DHD_BUS_LOAD;
-	}
-
-fail:
-	/* Always return to SDIOD core */
-	if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
-		si_setcore(bus->sih, SDIOD_CORE_ID, 0);
-
-	return bcmerror;
-}
-
-int
-dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
-                 void *params, int plen, void *arg, int len, bool set)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	const bcm_iovar_t *vi = NULL;
-	int bcmerror = 0;
-	int val_size;
-	uint32 actionid;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	ASSERT(name);
-	ASSERT(len >= 0);
-
-	/* Get MUST have return space */
-	ASSERT(set || (arg && len));
-
-	/* Set does NOT take qualifiers */
-	ASSERT(!set || (!params && !plen));
-
-	/* Look up var locally; if not found pass to host driver */
-	if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) {
-		dhd_os_sdlock(bus->dhd);
-
-		BUS_WAKE(bus);
-
-		/* Turn on clock in case SD command needs backplane */
-		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-		bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set);
-
-		/* Check for bus configuration changes of interest */
-
-		/* If it was divisor change, read the new one */
-		if (set && strcmp(name, "sd_divisor") == 0) {
-			if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
-			                    &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
-				bus->sd_divisor = -1;
-				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
-			} else {
-				DHD_INFO(("%s: noted %s update, value now %d\n",
-				          __FUNCTION__, name, bus->sd_divisor));
-			}
-		}
-		/* If it was a mode change, read the new one */
-		if (set && strcmp(name, "sd_mode") == 0) {
-			if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
-			                    &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
-				bus->sd_mode = -1;
-				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
-			} else {
-				DHD_INFO(("%s: noted %s update, value now %d\n",
-				          __FUNCTION__, name, bus->sd_mode));
-			}
-		}
-		/* Similar check for blocksize change */
-		if (set && strcmp(name, "sd_blocksize") == 0) {
-			int32 fnum = 2;
-			if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32),
-			                    &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
-				bus->blocksize = 0;
-				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
-			} else {
-				DHD_INFO(("%s: noted %s update, value now %d\n",
-				          __FUNCTION__, "sd_blocksize", bus->blocksize));
-
-				dhdsdio_tune_fifoparam(bus);
-			}
-		}
-		bus->roundup = MIN(max_roundup, bus->blocksize);
-
-		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
-			bus->activity = FALSE;
-			dhdsdio_clkctl(bus, CLK_NONE, TRUE);
-		}
-
-		dhd_os_sdunlock(bus->dhd);
-		goto exit;
-	}
-
-	DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
-	         name, (set ? "set" : "get"), len, plen));
-
-	/* set up 'params' pointer in case this is a set command so that
-	 * the convenience int and bool code can be common to set and get
-	 */
-	if (params == NULL) {
-		params = arg;
-		plen = len;
-	}
-
-	if (vi->type == IOVT_VOID)
-		val_size = 0;
-	else if (vi->type == IOVT_BUFFER)
-		val_size = len;
-	else
-		/* all other types are integer sized */
-		val_size = sizeof(int);
-
-	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
-	bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
-
-exit:
-	return bcmerror;
-}
-
-void
-dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
-{
-	osl_t *osh;
-	uint32 local_hostintmask;
-	uint8 saveclk;
-	uint retries;
-	int err;
-	bool wlfc_enabled = FALSE;
-
-	if (!bus->dhd)
-		return;
-
-	osh = bus->dhd->osh;
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	bcmsdh_waitlockfree(bus->sdh);
-
-	if (enforce_mutex)
-		dhd_os_sdlock(bus->dhd);
-
-	if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) {
-		/* if Firmware already hangs disbale any interrupt */
-		bus->dhd->busstate = DHD_BUS_DOWN;
-		bus->hostintmask = 0;
-		bcmsdh_intr_disable(bus->sdh);
-	} else {
-
-		BUS_WAKE(bus);
-
-		if (KSO_ENAB(bus)) {
-
-		/* Enable clock for device interrupts */
-		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-		/* Disable and clear interrupts at the chip level also */
-		W_SDREG(0, &bus->regs->hostintmask, retries);
-		local_hostintmask = bus->hostintmask;
-		bus->hostintmask = 0;
-
-		/* Change our idea of bus state */
-		bus->dhd->busstate = DHD_BUS_DOWN;
-
-		/* Force clocks on backplane to be sure F2 interrupt propagates */
-		saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
-		if (!err) {
-			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-			                 (saveclk | SBSDIO_FORCE_HT), &err);
-		}
-		if (err) {
-			DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
-			            __FUNCTION__, err));
-		}
-
-		/* Turn off the bus (F2), free any pending packets */
-		DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
-		bcmsdh_intr_disable(bus->sdh);
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
-
-		/* Clear any pending interrupts now that F2 is disabled */
-		W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
-		}
-
-		/* Turn off the backplane clock (only) */
-		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-	}
-
-#ifdef PROP_TXSTATUS
-	wlfc_enabled = (dhd_wlfc_cleanup_txq(bus->dhd, NULL, 0) != WLFC_UNSUPPORTED);
-#endif
-	if (!wlfc_enabled) {
-#ifdef DHDTCPACK_SUPPRESS
-		/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
-		 * when there is a newly coming packet from network stack.
-		 */
-		dhd_tcpack_info_tbl_clean(bus->dhd);
-#endif /* DHDTCPACK_SUPPRESS */
-		/* Clear the data packet queues */
-		pktq_flush(osh, &bus->txq, TRUE, NULL, 0);
-	}
-
-	/* Clear any held glomming stuff */
-	if (bus->glomd)
-		PKTFREE(osh, bus->glomd, FALSE);
-
-	if (bus->glom)
-		PKTFREE(osh, bus->glom, FALSE);
-
-	bus->glom = bus->glomd = NULL;
-
-	/* Clear rx control and wake any waiters */
-	bus->rxlen = 0;
-	dhd_os_ioctl_resp_wake(bus->dhd);
-
-	/* Reset some F2 state stuff */
-	bus->rxskip = FALSE;
-	bus->tx_seq = bus->rx_seq = 0;
-
-	bus->tx_max = 4;
-
-	if (enforce_mutex)
-		dhd_os_sdunlock(bus->dhd);
-}
-
-#if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STD)
-extern uint sd_txglom;
-#endif
-void
-dhd_txglom_enable(dhd_pub_t *dhdp, bool enable)
-{
-	/* can't enable host txglom by default, some platforms have no
-	 * (or crappy) ADMA support and txglom will cause kernel assertions (e.g.
-	 * panda board)
-	 */
-	dhd_bus_t *bus = dhdp->bus;
-#ifdef BCMSDIOH_TXGLOM
-	char buf[256];
-	uint32 rxglom;
-	int32 ret;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-#ifdef BCMSDIOH_STD
-	if (enable)
-		enable = sd_txglom;
-#endif /* BCMSDIOH_STD */
-
-	if (enable) {
-		rxglom = 1;
-		memset(buf, 0, sizeof(buf));
-		bcm_mkiovar("bus:rxglom", (void *)&rxglom, 4, buf, sizeof(buf));
-		ret = dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
-		if (ret >= 0)
-			bus->txglom_enable = TRUE;
-		else {
-#ifdef BCMSDIOH_STD
-			sd_txglom = 0;
-#endif /* BCMSDIOH_STD */
-			bus->txglom_enable = FALSE;
-		}
-	} else
-#endif /* BCMSDIOH_TXGLOM */
-		bus->txglom_enable = FALSE;
-}
-
-int
-dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	dhd_timeout_t tmo;
-	uint retries = 0;
-	uint8 ready, enable;
-	int err, ret = 0;
-	uint8 saveclk;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	ASSERT(bus->dhd);
-	if (!bus->dhd)
-		return 0;
-
-	if (enforce_mutex)
-		dhd_os_sdlock(bus->dhd);
-
-	/* Make sure backplane clock is on, needed to generate F2 interrupt */
-	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-	if (bus->clkstate != CLK_AVAIL) {
-		DHD_ERROR(("%s: clock state is wrong. state = %d\n", __FUNCTION__, bus->clkstate));
-		ret = -1;
-		goto exit;
-	}
-
-
-	/* Force clocks on backplane to be sure F2 interrupt propagates */
-	saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
-	if (!err) {
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-		                 (saveclk | SBSDIO_FORCE_HT), &err);
-	}
-	if (err) {
-		DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
-		ret = -1;
-		goto exit;
-	}
-
-	/* Enable function 2 (frame transfers) */
-	W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
-	        &bus->regs->tosbmailboxdata, retries);
-	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
-
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
-
-	/* Give the dongle some time to do its thing and set IOR2 */
-	dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
-
-	ready = 0;
-	while (ready != enable && !dhd_timeout_expired(&tmo))
-	        ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL);
-
-	DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
-	          __FUNCTION__, enable, ready, tmo.elapsed));
-
-
-	/* If F2 successfully enabled, set core and enable interrupts */
-	if (ready == enable) {
-		/* Make sure we're talking to the core. */
-		if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)))
-			bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0);
-		ASSERT(bus->regs != NULL);
-
-		/* Set up the interrupt mask and enable interrupts */
-		bus->hostintmask = HOSTINTMASK;
-		/* corerev 4 could use the newer interrupt logic to detect the frames */
-		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 4) &&
-			(bus->rxint_mode != SDIO_DEVICE_HMB_RXINT)) {
-			bus->hostintmask &= ~I_HMB_FRAME_IND;
-			bus->hostintmask |= I_XMTDATA_AVAIL;
-		}
-		W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
-
-		if (bus->sih->buscorerev < 15) {
-			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
-				(uint8)watermark, &err);
-		}
-
-		/* Set bus state according to enable result */
-		dhdp->busstate = DHD_BUS_DATA;
-
-		/* Need to set fn2 block size to match fn1 block size.
-		 * Requests to fn2 go thru fn1. *
-		 * faltwig has this code contitioned with #if !BCMSPI_ANDROID.
-		 * It would be cleaner to use the ->sdh->block_sz[fno] instead of
-		 * 64, but this layer has no access to sdh types.
-		 */
-
-		/* bcmsdh_intr_unmask(bus->sdh); */
-
-		bus->intdis = FALSE;
-		if (bus->intr) {
-			DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
-			bcmsdh_intr_enable(bus->sdh);
-		} else {
-			DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
-			bcmsdh_intr_disable(bus->sdh);
-		}
-
-	}
-
-
-	else {
-		/* Disable F2 again */
-		enable = SDIO_FUNC_ENABLE_1;
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
-	}
-
-	if (dhdsdio_sr_cap(bus)) {
-		dhdsdio_sr_init(bus);
-		/* Masking the chip active interrupt  permanantly */
-		bus->hostintmask &= ~I_CHIPACTIVE;
-		W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
-		DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n",
-		__FUNCTION__, bus->hostintmask));
-	}
-	else
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
-			SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
-
-	/* If we didn't come up, turn off backplane clock */
-	if (dhdp->busstate != DHD_BUS_DATA)
-		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
-
-exit:
-	if (enforce_mutex)
-		dhd_os_sdunlock(bus->dhd);
-
-	return ret;
-}
-
-static void
-dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
-{
-	bcmsdh_info_t *sdh = bus->sdh;
-	sdpcmd_regs_t *regs = bus->regs;
-	uint retries = 0;
-	uint16 lastrbc;
-	uint8 hi, lo;
-	int err;
-
-	DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__,
-	           (abort ? "abort command, " : ""), (rtx ? ", send NAK" : "")));
-
-	if (!KSO_ENAB(bus)) {
-		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
-		return;
-	}
-
-	if (abort) {
-		bcmsdh_abort(sdh, SDIO_FUNC_2);
-	}
-
-	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err);
-	if (err) {
-		DHD_ERROR(("%s: SBSDIO_FUNC1_FRAMECTRL cmd err\n", __FUNCTION__));
-		goto fail;
-	}
-	bus->f1regdata++;
-
-	/* Wait until the packet has been flushed (device/FIFO stable) */
-	for (lastrbc = retries = 0xffff; retries > 0; retries--) {
-		hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL);
-		lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, &err);
-		if (err) {
-			DHD_ERROR(("%s: SBSDIO_FUNC1_RFAMEBCLO cmd err\n", __FUNCTION__));
-			goto fail;
-		}
-
-		bus->f1regdata += 2;
-
-		if ((hi == 0) && (lo == 0))
-			break;
-
-		if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
-			DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n",
-			           __FUNCTION__, lastrbc, ((hi << 8) + lo)));
-		}
-		lastrbc = (hi << 8) + lo;
-	}
-
-	if (!retries) {
-		DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc));
-	} else {
-		DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries)));
-	}
-
-	if (rtx) {
-		bus->rxrtx++;
-		W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
-		bus->f1regdata++;
-		if (retries <= retry_limit) {
-			bus->rxskip = TRUE;
-		}
-	}
-
-	/* Clear partial in any case */
-	bus->nextlen = 0;
-
-fail:
-	/* If we can't reach the device, signal failure */
-	if (err || bcmsdh_regfail(sdh))
-		bus->dhd->busstate = DHD_BUS_DOWN;
-}
-
-static void
-dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff)
-{
-	bcmsdh_info_t *sdh = bus->sdh;
-	uint rdlen, pad;
-
-	int sdret;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	/* Control data already received in aligned rxctl */
-	if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
-		goto gotpkt;
-
-	ASSERT(bus->rxbuf);
-	/* Set rxctl for frame (w/optional alignment) */
-	bus->rxctl = bus->rxbuf;
-	if (dhd_alignctl) {
-		bus->rxctl += firstread;
-		if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
-			bus->rxctl += (DHD_SDALIGN - pad);
-		bus->rxctl -= firstread;
-	}
-	ASSERT(bus->rxctl >= bus->rxbuf);
-
-	/* Copy the already-read portion over */
-	bcopy(hdr, bus->rxctl, firstread);
-	if (len <= firstread)
-		goto gotpkt;
-
-	/* Copy the full data pkt in gSPI case and process ioctl. */
-	if (bus->bus == SPI_BUS) {
-		bcopy(hdr, bus->rxctl, len);
-		goto gotpkt;
-	}
-
-	/* Raise rdlen to next SDIO block to avoid tail command */
-	rdlen = len - firstread;
-	if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
-		pad = bus->blocksize - (rdlen % bus->blocksize);
-		if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
-		    ((len + pad) < bus->dhd->maxctl))
-			rdlen += pad;
-	} else if (rdlen % DHD_SDALIGN) {
-		rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
-	}
-
-	/* Satisfy length-alignment requirements */
-	if (forcealign && (rdlen & (ALIGNMENT - 1)))
-		rdlen = ROUNDUP(rdlen, ALIGNMENT);
-
-	/* Drop if the read is too big or it exceeds our maximum */
-	if ((rdlen + firstread) > bus->dhd->maxctl) {
-		DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
-		           __FUNCTION__, rdlen, bus->dhd->maxctl));
-		bus->dhd->rx_errors++;
-		dhdsdio_rxfail(bus, FALSE, FALSE);
-		goto done;
-	}
-
-	if ((len - doff) > bus->dhd->maxctl) {
-		DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
-		           __FUNCTION__, len, (len - doff), bus->dhd->maxctl));
-		bus->dhd->rx_errors++; bus->rx_toolong++;
-		dhdsdio_rxfail(bus, FALSE, FALSE);
-		goto done;
-	}
-
-
-	/* Read remainder of frame body into the rxctl buffer */
-	sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
-	                            (bus->rxctl + firstread), rdlen, NULL, NULL, NULL);
-	bus->f2rxdata++;
-	ASSERT(sdret != BCME_PENDING);
-
-	/* Control frame failures need retransmission */
-	if (sdret < 0) {
-		DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret));
-		bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
-		dhdsdio_rxfail(bus, TRUE, TRUE);
-		goto done;
-	}
-
-gotpkt:
-
-#ifdef DHD_DEBUG
-	if (DHD_BYTES_ON() && DHD_CTL_ON()) {
-		prhex("RxCtrl", bus->rxctl, len);
-	}
-#endif
-
-	/* Point to valid data and indicate its length */
-	bus->rxctl += doff;
-	bus->rxlen = len - doff;
-
-done:
-	/* Awake any waiters */
-	dhd_os_ioctl_resp_wake(bus->dhd);
-}
-int
-dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len,
-	void **pkt, uint32 *pkt_count);
-
-static uint8
-dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
-{
-	uint16 dlen, totlen;
-	uint8 *dptr, num = 0;
-
-	uint16 sublen, check;
-	void *pfirst, *plast, *pnext;
-	void * list_tail[DHD_MAX_IFS] = { NULL };
-	void * list_head[DHD_MAX_IFS] = { NULL };
-	uint8 idx;
-	osl_t *osh = bus->dhd->osh;
-
-	int errcode;
-	uint8 chan, seq, doff, sfdoff;
-	uint8 txmax;
-	uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
-	uint reorder_info_len;
-
-	int ifidx = 0;
-	bool usechain = bus->use_rxchain;
-
-	/* If packets, issue read(s) and send up packet chain */
-	/* Return sequence numbers consumed? */
-
-	DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom));
-
-	/* If there's a descriptor, generate the packet chain */
-	if (bus->glomd) {
-		dhd_os_sdlock_rxq(bus->dhd);
-
-		pfirst = plast = pnext = NULL;
-		dlen = (uint16)PKTLEN(osh, bus->glomd);
-		dptr = PKTDATA(osh, bus->glomd);
-		if (!dlen || (dlen & 1)) {
-			DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n",
-			           __FUNCTION__, dlen));
-			dlen = 0;
-		}
-
-		for (totlen = num = 0; dlen; num++) {
-			/* Get (and move past) next length */
-			sublen = ltoh16_ua(dptr);
-			dlen -= sizeof(uint16);
-			dptr += sizeof(uint16);
-			if ((sublen < SDPCM_HDRLEN) ||
-			    ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
-				DHD_ERROR(("%s: descriptor len %d bad: %d\n",
-				           __FUNCTION__, num, sublen));
-				pnext = NULL;
-				break;
-			}
-			if (sublen % DHD_SDALIGN) {
-				DHD_ERROR(("%s: sublen %d not a multiple of %d\n",
-				           __FUNCTION__, sublen, DHD_SDALIGN));
-				usechain = FALSE;
-			}
-			totlen += sublen;
-
-			/* For last frame, adjust read len so total is a block multiple */
-			if (!dlen) {
-				sublen += (ROUNDUP(totlen, bus->blocksize) - totlen);
-				totlen = ROUNDUP(totlen, bus->blocksize);
-			}
-
-			/* Allocate/chain packet for next subframe */
-			if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) {
-				DHD_ERROR(("%s: PKTGET failed, num %d len %d\n",
-				           __FUNCTION__, num, sublen));
-				break;
-			}
-			ASSERT(!PKTLINK(pnext));
-			if (!pfirst) {
-				ASSERT(!plast);
-				pfirst = plast = pnext;
-			} else {
-				ASSERT(plast);
-				PKTSETNEXT(osh, plast, pnext);
-				plast = pnext;
-			}
-
-			/* Adhere to start alignment requirements */
-			PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
-		}
-
-		/* If all allocations succeeded, save packet chain in bus structure */
-		if (pnext) {
-			DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n",
-			          __FUNCTION__, totlen, num));
-			if (DHD_GLOM_ON() && bus->nextlen) {
-				if (totlen != bus->nextlen) {
-					DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d "
-					          "rxseq %d\n", __FUNCTION__, bus->nextlen,
-					          totlen, rxseq));
-				}
-			}
-			bus->glom = pfirst;
-			pfirst = pnext = NULL;
-		} else {
-			if (pfirst)
-				PKTFREE(osh, pfirst, FALSE);
-			bus->glom = NULL;
-			num = 0;
-		}
-
-		/* Done with descriptor packet */
-		PKTFREE(osh, bus->glomd, FALSE);
-		bus->glomd = NULL;
-		bus->nextlen = 0;
-
-		dhd_os_sdunlock_rxq(bus->dhd);
-	}
-
-	/* Ok -- either we just generated a packet chain, or had one from before */
-	if (bus->glom) {
-		if (DHD_GLOM_ON()) {
-			DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__));
-			for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) {
-				DHD_GLOM(("    %p: %p len 0x%04x (%d)\n",
-				          pnext, (uint8*)PKTDATA(osh, pnext),
-				          PKTLEN(osh, pnext), PKTLEN(osh, pnext)));
-			}
-		}
-
-		pfirst = bus->glom;
-		dlen = (uint16)pkttotlen(osh, pfirst);
-
-		/* Do an SDIO read for the superframe.  Configurable iovar to
-		 * read directly into the chained packet, or allocate a large
-		 * packet and and copy into the chain.
-		 */
-		if (usechain) {
-			errcode = dhd_bcmsdh_recv_buf(bus,
-			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
-			                              F2SYNC, (uint8*)PKTDATA(osh, pfirst),
-			                              dlen, pfirst, NULL, NULL);
-		} else if (bus->dataptr) {
-			errcode = dhd_bcmsdh_recv_buf(bus,
-			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
-			                              F2SYNC, bus->dataptr,
-			                              dlen, NULL, NULL, NULL);
-			sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr);
-			if (sublen != dlen) {
-				DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
-				           __FUNCTION__, dlen, sublen));
-				errcode = -1;
-			}
-			pnext = NULL;
-		} else {
-			DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen));
-			errcode = -1;
-		}
-		bus->f2rxdata++;
-		ASSERT(errcode != BCME_PENDING);
-
-		/* On failure, kill the superframe, allow a couple retries */
-		if (errcode < 0) {
-			DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
-			           __FUNCTION__, dlen, errcode));
-			bus->dhd->rx_errors++;
-
-			if (bus->glomerr++ < 3) {
-				dhdsdio_rxfail(bus, TRUE, TRUE);
-			} else {
-				bus->glomerr = 0;
-				dhdsdio_rxfail(bus, TRUE, FALSE);
-				dhd_os_sdlock_rxq(bus->dhd);
-				PKTFREE(osh, bus->glom, FALSE);
-				dhd_os_sdunlock_rxq(bus->dhd);
-				bus->rxglomfail++;
-				bus->glom = NULL;
-			}
-			return 0;
-		}
-
-#ifdef DHD_DEBUG
-		if (DHD_GLOM_ON()) {
-			prhex("SUPERFRAME", PKTDATA(osh, pfirst),
-			      MIN(PKTLEN(osh, pfirst), 48));
-		}
-#endif
-
-
-		/* Validate the superframe header */
-		dptr = (uint8 *)PKTDATA(osh, pfirst);
-		sublen = ltoh16_ua(dptr);
-		check = ltoh16_ua(dptr + sizeof(uint16));
-
-		chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
-		seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
-		bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
-		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
-			DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n",
-			          __FUNCTION__, bus->nextlen, seq));
-			bus->nextlen = 0;
-		}
-		doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-		txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-
-		errcode = 0;
-		if ((uint16)~(sublen^check)) {
-			DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
-			           __FUNCTION__, sublen, check));
-			errcode = -1;
-		} else if (ROUNDUP(sublen, bus->blocksize) != dlen) {
-			DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
-			           __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen));
-			errcode = -1;
-		} else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) {
-			DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__,
-			           SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN])));
-			errcode = -1;
-		} else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
-			DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__));
-			errcode = -1;
-		} else if ((doff < SDPCM_HDRLEN) ||
-		           (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) {
-			DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n",
-				__FUNCTION__, doff, sublen, PKTLEN(osh, pfirst),
-				SDPCM_HDRLEN));
-			errcode = -1;
-		}
-
-		/* Check sequence number of superframe SW header */
-		if (rxseq != seq) {
-			DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
-			          __FUNCTION__, seq, rxseq));
-			bus->rx_badseq++;
-			rxseq = seq;
-		}
-
-		/* Check window for sanity */
-		if ((uint8)(txmax - bus->tx_seq) > 0x70) {
-			DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
-			           __FUNCTION__, txmax, bus->tx_seq));
-			txmax = bus->tx_max;
-		}
-		bus->tx_max = txmax;
-
-		/* Remove superframe header, remember offset */
-		PKTPULL(osh, pfirst, doff);
-		sfdoff = doff;
-
-		/* Validate all the subframe headers */
-		for (num = 0, pnext = pfirst; pnext && !errcode;
-		     num++, pnext = PKTNEXT(osh, pnext)) {
-			dptr = (uint8 *)PKTDATA(osh, pnext);
-			dlen = (uint16)PKTLEN(osh, pnext);
-			sublen = ltoh16_ua(dptr);
-			check = ltoh16_ua(dptr + sizeof(uint16));
-			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
-			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-#ifdef DHD_DEBUG
-			if (DHD_GLOM_ON()) {
-				prhex("subframe", dptr, 32);
-			}
-#endif
-
-			if ((uint16)~(sublen^check)) {
-				DHD_ERROR(("%s (subframe %d): HW hdr error: "
-				           "len/check 0x%04x/0x%04x\n",
-				           __FUNCTION__, num, sublen, check));
-				errcode = -1;
-			} else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
-				DHD_ERROR(("%s (subframe %d): length mismatch: "
-				           "len 0x%04x, expect 0x%04x\n",
-				           __FUNCTION__, num, sublen, dlen));
-				errcode = -1;
-			} else if ((chan != SDPCM_DATA_CHANNEL) &&
-			           (chan != SDPCM_EVENT_CHANNEL)) {
-				DHD_ERROR(("%s (subframe %d): bad channel %d\n",
-				           __FUNCTION__, num, chan));
-				errcode = -1;
-			} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
-				DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
-				           __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN));
-				errcode = -1;
-			}
-		}
-
-		if (errcode) {
-			/* Terminate frame on error, request a couple retries */
-			if (bus->glomerr++ < 3) {
-				/* Restore superframe header space */
-				PKTPUSH(osh, pfirst, sfdoff);
-				dhdsdio_rxfail(bus, TRUE, TRUE);
-			} else {
-				bus->glomerr = 0;
-				dhdsdio_rxfail(bus, TRUE, FALSE);
-				dhd_os_sdlock_rxq(bus->dhd);
-				PKTFREE(osh, bus->glom, FALSE);
-				dhd_os_sdunlock_rxq(bus->dhd);
-				bus->rxglomfail++;
-				bus->glom = NULL;
-			}
-			bus->nextlen = 0;
-			return 0;
-		}
-
-		/* Basic SD framing looks ok - process each packet (header) */
-		bus->glom = NULL;
-		plast = NULL;
-
-		dhd_os_sdlock_rxq(bus->dhd);
-		for (num = 0; pfirst; rxseq++, pfirst = pnext) {
-			pnext = PKTNEXT(osh, pfirst);
-			PKTSETNEXT(osh, pfirst, NULL);
-
-			dptr = (uint8 *)PKTDATA(osh, pfirst);
-			sublen = ltoh16_ua(dptr);
-			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
-			seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
-			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-
-			DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
-			          __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst),
-			          PKTLEN(osh, pfirst), sublen, chan, seq));
-
-			ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL));
-
-			if (rxseq != seq) {
-				DHD_GLOM(("%s: rx_seq %d, expected %d\n",
-				          __FUNCTION__, seq, rxseq));
-				bus->rx_badseq++;
-				rxseq = seq;
-			}
-
-#ifdef DHD_DEBUG
-			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
-				prhex("Rx Subframe Data", dptr, dlen);
-			}
-#endif
-
-			PKTSETLEN(osh, pfirst, sublen);
-			PKTPULL(osh, pfirst, doff);
-
-			reorder_info_len = sizeof(reorder_info_buf);
-
-			if (PKTLEN(osh, pfirst) == 0) {
-				PKTFREE(bus->dhd->osh, pfirst, FALSE);
-				continue;
-			} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf,
-				&reorder_info_len) != 0) {
-				DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
-				bus->dhd->rx_errors++;
-				PKTFREE(osh, pfirst, FALSE);
-				continue;
-			}
-			if (reorder_info_len) {
-				uint32 free_buf_count;
-				void *ppfirst;
-
-				ppfirst = pfirst;
-				/* Reordering info from the firmware */
-				dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf,
-					reorder_info_len, &ppfirst, &free_buf_count);
-
-				if (free_buf_count == 0) {
-					continue;
-				}
-				else {
-					void *temp;
-
-					/*  go to the end of the chain and attach the pnext there */
-					temp = ppfirst;
-					while (PKTNEXT(osh, temp) != NULL) {
-						temp = PKTNEXT(osh, temp);
-					}
-					pfirst = temp;
-					if (list_tail[ifidx] == NULL)
-						list_head[ifidx] = ppfirst;
-					else
-						PKTSETNEXT(osh, list_tail[ifidx], ppfirst);
-					list_tail[ifidx] = pfirst;
-				}
-
-				num += (uint8)free_buf_count;
-			}
-			else {
-				/* this packet will go up, link back into chain and count it */
-
-				if (list_tail[ifidx] == NULL) {
-					list_head[ifidx] = list_tail[ifidx] = pfirst;
-				}
-				else {
-					PKTSETNEXT(osh, list_tail[ifidx], pfirst);
-					list_tail[ifidx] = pfirst;
-				}
-				num++;
-			}
-#ifdef DHD_DEBUG
-			if (DHD_GLOM_ON()) {
-				DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n",
-				          __FUNCTION__, num, pfirst,
-				          PKTDATA(osh, pfirst), PKTLEN(osh, pfirst),
-				          PKTNEXT(osh, pfirst), PKTLINK(pfirst)));
-				prhex("", (uint8 *)PKTDATA(osh, pfirst),
-				      MIN(PKTLEN(osh, pfirst), 32));
-			}
-#endif /* DHD_DEBUG */
-		}
-		dhd_os_sdunlock_rxq(bus->dhd);
-
-		for (idx = 0; idx < DHD_MAX_IFS; idx++) {
-			if (list_head[idx]) {
-				void *temp;
-				uint8 cnt = 0;
-				temp = list_head[idx];
-				do {
-					temp = PKTNEXT(osh, temp);
-					cnt++;
-				} while (temp);
-				if (cnt) {
-					dhd_os_sdunlock(bus->dhd);
-					dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0);
-					dhd_os_sdlock(bus->dhd);
-				}
-			}
-		}
-		bus->rxglomframes++;
-		bus->rxglompkts += num;
-	}
-	return num;
-}
-
-
-/* Return TRUE if there may be more frames to read */
-static uint
-dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
-{
-	osl_t *osh = bus->dhd->osh;
-	bcmsdh_info_t *sdh = bus->sdh;
-
-	uint16 len, check;	/* Extracted hardware header fields */
-	uint8 chan, seq, doff;	/* Extracted software header fields */
-	uint8 fcbits;		/* Extracted fcbits from software header */
-	uint8 delta;
-
-	void *pkt;	/* Packet for event or data frames */
-	uint16 pad;	/* Number of pad bytes to read */
-	uint16 rdlen;	/* Total number of bytes to read */
-	uint8 rxseq;	/* Next sequence number to expect */
-	uint rxleft = 0;	/* Remaining number of frames allowed */
-	int sdret;	/* Return code from bcmsdh calls */
-	uint8 txmax;	/* Maximum tx sequence offered */
-	bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
-	uint8 *rxbuf;
-	int ifidx = 0;
-	uint rxcount = 0; /* Total frames read */
-	uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
-	uint reorder_info_len;
-	uint pkt_count;
-
-#if defined(DHD_DEBUG) || defined(SDTEST)
-	bool sdtest = FALSE;	/* To limit message spew from test mode */
-#endif
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	bus->readframes = TRUE;
-
-	if (!KSO_ENAB(bus)) {
-		DHD_ERROR(("%s: KSO off\n", __FUNCTION__));
-		bus->readframes = FALSE;
-		return 0;
-	}
-
-	ASSERT(maxframes);
-
-#ifdef SDTEST
-	/* Allow pktgen to override maxframes */
-	if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
-		maxframes = bus->pktgen_count;
-		sdtest = TRUE;
-	}
-#endif
-
-	/* Not finished unless we encounter no more frames indication */
-	*finished = FALSE;
-
-
-	for (rxseq = bus->rx_seq, rxleft = maxframes;
-	     !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
-	     rxseq++, rxleft--) {
-#ifdef DHDTCPACK_SUP_DBG
-		if (bus->dhd->tcpack_sup_mode != TCPACK_SUP_DELAYTX) {
-			if (bus->dotxinrx == FALSE)
-				DHD_ERROR(("%s %d: dotxinrx FALSE with tcpack_sub_mode %d\n",
-					__FUNCTION__, __LINE__, bus->dhd->tcpack_sup_mode));
-		}
-#ifdef DEBUG_COUNTER
-		else if (pktq_mlen(&bus->txq, ~bus->flowcontrol) > 0) {
-			tack_tbl.cnt[bus->dotxinrx ? 6 : 7]++;
-		}
-#endif /* DEBUG_COUNTER */
-#endif /* DHDTCPACK_SUP_DBG */
-		/* tx more to improve rx performance */
-		if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
-			dhdsdio_sendpendctl(bus);
-		} else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) &&
-			!bus->fcstate && DATAOK(bus) &&
-			(pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) {
-			dhdsdio_sendfromq(bus, dhd_txbound);
-#ifdef DHDTCPACK_SUPPRESS
-			/* In TCPACK_SUP_DELAYTX mode, do txinrx only if
-			 * 1. Any DATA packet to TX
-			 * 2. TCPACK to TCPDATA PSH packets.
-			 * in bus txq.
-			 */
-			bus->dotxinrx = (bus->dhd->tcpack_sup_mode == TCPACK_SUP_DELAYTX) ?
-				FALSE : TRUE;
-#endif
-		}
-
-		/* Handle glomming separately */
-		if (bus->glom || bus->glomd) {
-			uint8 cnt;
-			DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
-			          __FUNCTION__, bus->glomd, bus->glom));
-			cnt = dhdsdio_rxglom(bus, rxseq);
-			DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt));
-			rxseq += cnt - 1;
-			rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
-			continue;
-		}
-
-		/* Try doing single read if we can */
-		if (dhd_readahead && bus->nextlen) {
-			uint16 nextlen = bus->nextlen;
-			bus->nextlen = 0;
-
-			if (bus->bus == SPI_BUS) {
-				rdlen = len = nextlen;
-			}
-			else {
-				rdlen = len = nextlen << 4;
-
-				/* Pad read to blocksize for efficiency */
-				if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
-					pad = bus->blocksize - (rdlen % bus->blocksize);
-					if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
-						((rdlen + pad + firstread) < MAX_RX_DATASZ))
-						rdlen += pad;
-				} else if (rdlen % DHD_SDALIGN) {
-					rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
-				}
-			}
-
-			/* We use bus->rxctl buffer in WinXP for initial control pkt receives.
-			 * Later we use buffer-poll for data as well as control packets.
-			 * This is required because dhd receives full frame in gSPI unlike SDIO.
-			 * After the frame is received we have to distinguish whether it is data
-			 * or non-data frame.
-			 */
-			/* Allocate a packet buffer */
-			dhd_os_sdlock_rxq(bus->dhd);
-			if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) {
-				if (bus->bus == SPI_BUS) {
-					bus->usebufpool = FALSE;
-					bus->rxctl = bus->rxbuf;
-					if (dhd_alignctl) {
-						bus->rxctl += firstread;
-						if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
-							bus->rxctl += (DHD_SDALIGN - pad);
-						bus->rxctl -= firstread;
-					}
-					ASSERT(bus->rxctl >= bus->rxbuf);
-					rxbuf = bus->rxctl;
-					/* Read the entire frame */
-					sdret = dhd_bcmsdh_recv_buf(bus,
-					                            bcmsdh_cur_sbwad(sdh),
-					                            SDIO_FUNC_2,
-					                            F2SYNC, rxbuf, rdlen,
-					                            NULL, NULL, NULL);
-					bus->f2rxdata++;
-					ASSERT(sdret != BCME_PENDING);
-
-
-					/* Control frame failures need retransmission */
-					if (sdret < 0) {
-						DHD_ERROR(("%s: read %d control bytes failed: %d\n",
-						   __FUNCTION__, rdlen, sdret));
-						/* dhd.rx_ctlerrs is higher level */
-						bus->rxc_errors++;
-						dhd_os_sdunlock_rxq(bus->dhd);
-						dhdsdio_rxfail(bus, TRUE,
-						    (bus->bus == SPI_BUS) ? FALSE : TRUE);
-						continue;
-					}
-				} else {
-					/* Give up on data, request rtx of events */
-					DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d "
-					           "expected rxseq %d\n",
-					           __FUNCTION__, len, rdlen, rxseq));
-					/* Just go try again w/normal header read */
-					dhd_os_sdunlock_rxq(bus->dhd);
-					continue;
-				}
-			} else {
-				if (bus->bus == SPI_BUS)
-					bus->usebufpool = TRUE;
-
-				ASSERT(!PKTLINK(pkt));
-				PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
-				rxbuf = (uint8 *)PKTDATA(osh, pkt);
-				/* Read the entire frame */
-				sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
-				                            SDIO_FUNC_2,
-				                            F2SYNC, rxbuf, rdlen,
-				                            pkt, NULL, NULL);
-				bus->f2rxdata++;
-				ASSERT(sdret != BCME_PENDING);
-
-				if (sdret < 0) {
-					DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
-					   __FUNCTION__, rdlen, sdret));
-					PKTFREE(bus->dhd->osh, pkt, FALSE);
-					bus->dhd->rx_errors++;
-					dhd_os_sdunlock_rxq(bus->dhd);
-					/* Force retry w/normal header read.  Don't attempt NAK for
-					 * gSPI
-					 */
-					dhdsdio_rxfail(bus, TRUE,
-					      (bus->bus == SPI_BUS) ? FALSE : TRUE);
-					continue;
-				}
-			}
-			dhd_os_sdunlock_rxq(bus->dhd);
-
-			/* Now check the header */
-			bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
-
-			/* Extract hardware header fields */
-			len = ltoh16_ua(bus->rxhdr);
-			check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
-
-			/* All zeros means readahead info was bad */
-			if (!(len|check)) {
-				DHD_INFO(("%s (nextlen): read zeros in HW header???\n",
-				           __FUNCTION__));
-				dhd_os_sdlock_rxq(bus->dhd);
-				PKTFREE2();
-				dhd_os_sdunlock_rxq(bus->dhd);
-				GSPI_PR55150_BAILOUT;
-				continue;
-			}
-
-			/* Validate check bytes */
-			if ((uint16)~(len^check)) {
-				DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check"
-				           " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen,
-				           len, check));
-				dhd_os_sdlock_rxq(bus->dhd);
-				PKTFREE2();
-				dhd_os_sdunlock_rxq(bus->dhd);
-				bus->rx_badhdr++;
-				dhdsdio_rxfail(bus, FALSE, FALSE);
-				GSPI_PR55150_BAILOUT;
-				continue;
-			}
-
-			/* Validate frame length */
-			if (len < SDPCM_HDRLEN) {
-				DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n",
-				           __FUNCTION__, len));
-				dhd_os_sdlock_rxq(bus->dhd);
-				PKTFREE2();
-				dhd_os_sdunlock_rxq(bus->dhd);
-				GSPI_PR55150_BAILOUT;
-				continue;
-			}
-
-			/* Check for consistency with readahead info */
-				len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4));
-			if (len_consistent) {
-				/* Mismatch, force retry w/normal header (may be >4K) */
-				DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; "
-				           "expected rxseq %d\n",
-				           __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq));
-				dhd_os_sdlock_rxq(bus->dhd);
-				PKTFREE2();
-				dhd_os_sdunlock_rxq(bus->dhd);
-				dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE);
-				GSPI_PR55150_BAILOUT;
-				continue;
-			}
-
-
-			/* Extract software header fields */
-			chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-			seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-			doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-			txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-
-				bus->nextlen =
-				         bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
-				if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
-					DHD_INFO(("%s (nextlen): got frame w/nextlen too large"
-					          " (%d), seq %d\n", __FUNCTION__, bus->nextlen,
-					          seq));
-					bus->nextlen = 0;
-				}
-
-				bus->dhd->rx_readahead_cnt ++;
-			/* Handle Flow Control */
-			fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-
-			delta = 0;
-			if (~bus->flowcontrol & fcbits) {
-				bus->fc_xoff++;
-				delta = 1;
-			}
-			if (bus->flowcontrol & ~fcbits) {
-				bus->fc_xon++;
-				delta = 1;
-			}
-
-			if (delta) {
-				bus->fc_rcvd++;
-				bus->flowcontrol = fcbits;
-			}
-
-			/* Check and update sequence number */
-			if (rxseq != seq) {
-				DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n",
-				          __FUNCTION__, seq, rxseq));
-				bus->rx_badseq++;
-				rxseq = seq;
-			}
-
-			/* Check window for sanity */
-			if ((uint8)(txmax - bus->tx_seq) > 0x70) {
-					DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
-						__FUNCTION__, txmax, bus->tx_seq));
-					txmax = bus->tx_max;
-			}
-			bus->tx_max = txmax;
-
-#ifdef DHD_DEBUG
-			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
-				prhex("Rx Data", rxbuf, len);
-			} else if (DHD_HDRS_ON()) {
-				prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
-			}
-#endif
-
-			if (chan == SDPCM_CONTROL_CHANNEL) {
-				if (bus->bus == SPI_BUS) {
-					dhdsdio_read_control(bus, rxbuf, len, doff);
-					if (bus->usebufpool) {
-						dhd_os_sdlock_rxq(bus->dhd);
-						PKTFREE(bus->dhd->osh, pkt, FALSE);
-						dhd_os_sdunlock_rxq(bus->dhd);
-					}
-					continue;
-				} else {
-					DHD_ERROR(("%s (nextlen): readahead on control"
-					           " packet %d?\n", __FUNCTION__, seq));
-					/* Force retry w/normal header read */
-					bus->nextlen = 0;
-					dhdsdio_rxfail(bus, FALSE, TRUE);
-					dhd_os_sdlock_rxq(bus->dhd);
-					PKTFREE2();
-					dhd_os_sdunlock_rxq(bus->dhd);
-					continue;
-				}
-			}
-
-			if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
-				DHD_ERROR(("Received %d bytes on %d channel. Running out of "
-				           "rx pktbuf's or not yet malloced.\n", len, chan));
-				continue;
-			}
-
-			/* Validate data offset */
-			if ((doff < SDPCM_HDRLEN) || (doff > len)) {
-				DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
-				           __FUNCTION__, doff, len, SDPCM_HDRLEN));
-				dhd_os_sdlock_rxq(bus->dhd);
-				PKTFREE2();
-				dhd_os_sdunlock_rxq(bus->dhd);
-				ASSERT(0);
-				dhdsdio_rxfail(bus, FALSE, FALSE);
-				continue;
-			}
-
-			/* All done with this one -- now deliver the packet */
-			goto deliver;
-		}
-		/* gSPI frames should not be handled in fractions */
-		if (bus->bus == SPI_BUS) {
-			break;
-		}
-
-		/* Read frame header (hardware and software) */
-		sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
-		                            bus->rxhdr, firstread, NULL, NULL, NULL);
-		bus->f2rxhdrs++;
-		ASSERT(sdret != BCME_PENDING);
-
-		if (sdret < 0) {
-			DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret));
-			bus->rx_hdrfail++;
-			dhdsdio_rxfail(bus, TRUE, TRUE);
-			continue;
-		}
-
-#ifdef DHD_DEBUG
-		if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
-			prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
-		}
-#endif
-
-		/* Extract hardware header fields */
-		len = ltoh16_ua(bus->rxhdr);
-		check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
-
-		/* All zeros means no more frames */
-		if (!(len|check)) {
-			*finished = TRUE;
-			break;
-		}
-
-		/* Validate check bytes */
-		if ((uint16)~(len^check)) {
-			DHD_ERROR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n",
-			           __FUNCTION__, len, check));
-			bus->rx_badhdr++;
-			dhdsdio_rxfail(bus, FALSE, FALSE);
-			continue;
-		}
-
-		/* Validate frame length */
-		if (len < SDPCM_HDRLEN) {
-			DHD_ERROR(("%s: HW hdr length invalid: %d\n", __FUNCTION__, len));
-			continue;
-		}
-
-		/* Extract software header fields */
-		chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-		seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-		doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-		txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-
-		/* Validate data offset */
-		if ((doff < SDPCM_HDRLEN) || (doff > len)) {
-			DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n",
-			           __FUNCTION__, doff, len, SDPCM_HDRLEN, seq));
-			bus->rx_badhdr++;
-			ASSERT(0);
-			dhdsdio_rxfail(bus, FALSE, FALSE);
-			continue;
-		}
-
-		/* Save the readahead length if there is one */
-		bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
-		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
-			DHD_INFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n",
-			          __FUNCTION__, bus->nextlen, seq));
-			bus->nextlen = 0;
-		}
-
-		/* Handle Flow Control */
-		fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-
-		delta = 0;
-		if (~bus->flowcontrol & fcbits) {
-			bus->fc_xoff++;
-			delta = 1;
-		}
-		if (bus->flowcontrol & ~fcbits) {
-			bus->fc_xon++;
-			delta = 1;
-		}
-
-		if (delta) {
-			bus->fc_rcvd++;
-			bus->flowcontrol = fcbits;
-		}
-
-		/* Check and update sequence number */
-		if (rxseq != seq) {
-			DHD_INFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq));
-			bus->rx_badseq++;
-			rxseq = seq;
-		}
-
-		/* Check window for sanity */
-		if ((uint8)(txmax - bus->tx_seq) > 0x70) {
-			DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
-			           __FUNCTION__, txmax, bus->tx_seq));
-			txmax = bus->tx_max;
-		}
-		bus->tx_max = txmax;
-
-		/* Call a separate function for control frames */
-		if (chan == SDPCM_CONTROL_CHANNEL) {
-			dhdsdio_read_control(bus, bus->rxhdr, len, doff);
-			continue;
-		}
-
-		ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) ||
-		       (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL));
-
-		/* Length to read */
-		rdlen = (len > firstread) ? (len - firstread) : 0;
-
-		/* May pad read to blocksize for efficiency */
-		if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
-			pad = bus->blocksize - (rdlen % bus->blocksize);
-			if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
-			    ((rdlen + pad + firstread) < MAX_RX_DATASZ))
-				rdlen += pad;
-		} else if (rdlen % DHD_SDALIGN) {
-			rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
-		}
-
-		/* Satisfy length-alignment requirements */
-		if (forcealign && (rdlen & (ALIGNMENT - 1)))
-			rdlen = ROUNDUP(rdlen, ALIGNMENT);
-
-		if ((rdlen + firstread) > MAX_RX_DATASZ) {
-			/* Too long -- skip this frame */
-			DHD_ERROR(("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen));
-			bus->dhd->rx_errors++; bus->rx_toolong++;
-			dhdsdio_rxfail(bus, FALSE, FALSE);
-			continue;
-		}
-
-		dhd_os_sdlock_rxq(bus->dhd);
-		if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) {
-			/* Give up on data, request rtx of events */
-			DHD_ERROR(("%s: PKTGET failed: rdlen %d chan %d\n",
-			           __FUNCTION__, rdlen, chan));
-			bus->dhd->rx_dropped++;
-			dhd_os_sdunlock_rxq(bus->dhd);
-			dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan));
-			continue;
-		}
-		dhd_os_sdunlock_rxq(bus->dhd);
-
-		ASSERT(!PKTLINK(pkt));
-
-		/* Leave room for what we already read, and align remainder */
-		ASSERT(firstread < (PKTLEN(osh, pkt)));
-		PKTPULL(osh, pkt, firstread);
-		PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
-
-		/* Read the remaining frame data */
-		sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
-		                            ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL);
-		bus->f2rxdata++;
-		ASSERT(sdret != BCME_PENDING);
-
-		if (sdret < 0) {
-			DHD_ERROR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen,
-			           ((chan == SDPCM_EVENT_CHANNEL) ? "event" :
-			            ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret));
-			dhd_os_sdlock_rxq(bus->dhd);
-			PKTFREE(bus->dhd->osh, pkt, FALSE);
-			dhd_os_sdunlock_rxq(bus->dhd);
-			bus->dhd->rx_errors++;
-			dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan));
-			continue;
-		}
-
-		/* Copy the already-read portion */
-		PKTPUSH(osh, pkt, firstread);
-		bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread);
-
-#ifdef DHD_DEBUG
-		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
-			prhex("Rx Data", PKTDATA(osh, pkt), len);
-		}
-#endif
-
-deliver:
-		/* Save superframe descriptor and allocate packet frame */
-		if (chan == SDPCM_GLOM_CHANNEL) {
-			if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
-				DHD_GLOM(("%s: got glom descriptor, %d bytes:\n",
-				          __FUNCTION__, len));
-#ifdef DHD_DEBUG
-				if (DHD_GLOM_ON()) {
-					prhex("Glom Data", PKTDATA(osh, pkt), len);
-				}
-#endif
-				PKTSETLEN(osh, pkt, len);
-				ASSERT(doff == SDPCM_HDRLEN);
-				PKTPULL(osh, pkt, SDPCM_HDRLEN);
-				bus->glomd = pkt;
-			} else {
-				DHD_ERROR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__));
-				dhdsdio_rxfail(bus, FALSE, FALSE);
-			}
-			continue;
-		}
-
-		/* Fill in packet len and prio, deliver upward */
-		PKTSETLEN(osh, pkt, len);
-		PKTPULL(osh, pkt, doff);
-
-#ifdef SDTEST
-		/* Test channel packets are processed separately */
-		if (chan == SDPCM_TEST_CHANNEL) {
-			dhdsdio_testrcv(bus, pkt, seq);
-			continue;
-		}
-#endif /* SDTEST */
-
-		if (PKTLEN(osh, pkt) == 0) {
-			dhd_os_sdlock_rxq(bus->dhd);
-			PKTFREE(bus->dhd->osh, pkt, FALSE);
-			dhd_os_sdunlock_rxq(bus->dhd);
-			continue;
-		} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt, reorder_info_buf,
-			&reorder_info_len) != 0) {
-			DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
-			dhd_os_sdlock_rxq(bus->dhd);
-			PKTFREE(bus->dhd->osh, pkt, FALSE);
-			dhd_os_sdunlock_rxq(bus->dhd);
-			bus->dhd->rx_errors++;
-			continue;
-		}
-		if (reorder_info_len) {
-			/* Reordering info from the firmware */
-			dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, reorder_info_len,
-				&pkt, &pkt_count);
-			if (pkt_count == 0)
-				continue;
-		}
-		else
-			pkt_count = 1;
-
-		/* Unlock during rx call */
-		dhd_os_sdunlock(bus->dhd);
-		dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan);
-		dhd_os_sdlock(bus->dhd);
-	}
-	rxcount = maxframes - rxleft;
-#ifdef DHD_DEBUG
-	/* Message if we hit the limit */
-	if (!rxleft && !sdtest)
-		DHD_DATA(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes));
-	else
-#endif /* DHD_DEBUG */
-	DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount));
-	/* Back off rxseq if awaiting rtx, update rx_seq */
-	if (bus->rxskip)
-		rxseq--;
-	bus->rx_seq = rxseq;
-
-	if (bus->reqbussleep)
-	{
-	    dhdsdio_bussleep(bus, TRUE);
-		bus->reqbussleep = FALSE;
-	}
-	bus->readframes = FALSE;
-
-	return rxcount;
-}
-
-static uint32
-dhdsdio_hostmail(dhd_bus_t *bus)
-{
-	sdpcmd_regs_t *regs = bus->regs;
-	uint32 intstatus = 0;
-	uint32 hmb_data;
-	uint8 fcbits;
-	uint retries = 0;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	/* Read mailbox data and ack that we did so */
-	R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
-	if (retries <= retry_limit)
-		W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
-	bus->f1regdata += 2;
-
-	/* Dongle recomposed rx frames, accept them again */
-	if (hmb_data & HMB_DATA_NAKHANDLED) {
-		DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq));
-		if (!bus->rxskip) {
-			DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__));
-		}
-		bus->rxskip = FALSE;
-		intstatus |= FRAME_AVAIL_MASK(bus);
-	}
-
-	/*
-	 * DEVREADY does not occur with gSPI.
-	 */
-	if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
-		bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT;
-		if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
-			DHD_ERROR(("Version mismatch, dongle reports %d, expecting %d\n",
-			           bus->sdpcm_ver, SDPCM_PROT_VERSION));
-		else
-			DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver));
-		/* make sure for the SDIO_DEVICE_RXDATAINT_MODE_1 corecontrol is proper */
-		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
-		    (bus->rxint_mode  == SDIO_DEVICE_RXDATAINT_MODE_1)) {
-			uint32 val;
-
-			val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
-			val &= ~CC_XMTDATAAVAIL_MODE;
-			val |= CC_XMTDATAAVAIL_CTRL;
-			W_REG(bus->dhd->osh, &bus->regs->corecontrol, val);
-
-			val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
-		}
-
-#ifdef DHD_DEBUG
-		/* Retrieve console state address now that firmware should have updated it */
-		{
-			sdpcm_shared_t shared;
-			if (dhdsdio_readshared(bus, &shared) == 0)
-				bus->console_addr = shared.console_addr;
-		}
-#endif /* DHD_DEBUG */
-	}
-
-	/*
-	 * Flow Control has been moved into the RX headers and this out of band
-	 * method isn't used any more.  Leave this here for possibly remaining backward
-	 * compatible with older dongles
-	 */
-	if (hmb_data & HMB_DATA_FC) {
-		fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT;
-
-		if (fcbits & ~bus->flowcontrol)
-			bus->fc_xoff++;
-		if (bus->flowcontrol & ~fcbits)
-			bus->fc_xon++;
-
-		bus->fc_rcvd++;
-		bus->flowcontrol = fcbits;
-	}
-
-	/* At least print a message if FW halted */
-	if (hmb_data & HMB_DATA_FWHALT) {
-		DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED : set BUS DOWN\n"));
-		dhdsdio_checkdied(bus, NULL, 0);
-		bus->dhd->busstate = DHD_BUS_DOWN;
-	}
-
-	/* Shouldn't be any others */
-	if (hmb_data & ~(HMB_DATA_DEVREADY |
-	                 HMB_DATA_FWHALT |
-	                 HMB_DATA_NAKHANDLED |
-	                 HMB_DATA_FC |
-	                 HMB_DATA_FWREADY |
-	                 HMB_DATA_FCDATA_MASK |
-	                 HMB_DATA_VERSION_MASK)) {
-		DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
-	}
-
-	return intstatus;
-}
-
-static bool
-dhdsdio_dpc(dhd_bus_t *bus)
-{
-	bcmsdh_info_t *sdh = bus->sdh;
-	sdpcmd_regs_t *regs = bus->regs;
-	uint32 intstatus, newstatus = 0;
-	uint retries = 0;
-	uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */
-	uint txlimit = dhd_txbound; /* Tx frames to send before resched */
-	uint framecnt = 0;		  /* Temporary counter of tx/rx frames */
-	bool rxdone = TRUE;		  /* Flag for no more read data */
-	bool resched = FALSE;	  /* Flag indicating resched wanted */
-#ifdef DEBUG_DPC_THREAD_WATCHDOG
-	bool is_resched_by_readframe = FALSE;
-#endif /* DEBUG_DPC_THREAD_WATCHDOG */
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	dhd_os_sdlock(bus->dhd);
-
-	if (bus->dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
-		bus->intstatus = 0;
-		dhd_os_sdunlock(bus->dhd);
-		return 0;
-	}
-
-	/* Start with leftover status bits */
-	intstatus = bus->intstatus;
-
-	if (!SLPAUTO_ENAB(bus) && !KSO_ENAB(bus)) {
-		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
-		goto exit;
-	}
-
-	/* If waiting for HTAVAIL, check status */
-	if (!SLPAUTO_ENAB(bus) && (bus->clkstate == CLK_PENDING)) {
-		int err;
-		uint8 clkctl, devctl = 0;
-
-#ifdef DHD_DEBUG
-		/* Check for inconsistent device control */
-		devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
-		if (err) {
-			DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err));
-			bus->dhd->busstate = DHD_BUS_DOWN;
-		} else {
-			ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
-		}
-#endif /* DHD_DEBUG */
-
-		/* Read CSR, if clock on switch to AVAIL, else ignore */
-		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
-		if (err) {
-			DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err));
-			bus->dhd->busstate = DHD_BUS_DOWN;
-		}
-
-		DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl));
-
-		if (SBSDIO_HTAV(clkctl)) {
-			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
-			if (err) {
-				DHD_ERROR(("%s: error reading DEVCTL: %d\n",
-				           __FUNCTION__, err));
-				bus->dhd->busstate = DHD_BUS_DOWN;
-			}
-			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
-			if (err) {
-				DHD_ERROR(("%s: error writing DEVCTL: %d\n",
-				           __FUNCTION__, err));
-				bus->dhd->busstate = DHD_BUS_DOWN;
-			}
-			bus->clkstate = CLK_AVAIL;
-		} else {
-			goto clkwait;
-		}
-	}
-
-	BUS_WAKE(bus);
-
-	/* Make sure backplane clock is on */
-	dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
-	if (bus->clkstate != CLK_AVAIL)
-		goto clkwait;
-
-	/* Pending interrupt indicates new device status */
-	if (bus->ipend) {
-		bus->ipend = FALSE;
-		R_SDREG(newstatus, &regs->intstatus, retries);
-		bus->f1regdata++;
-		if (bcmsdh_regfail(bus->sdh))
-			newstatus = 0;
-		newstatus &= bus->hostintmask;
-		bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
-		if (newstatus) {
-			bus->f1regdata++;
-			if ((bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_0) &&
-				(newstatus == I_XMTDATA_AVAIL)) {
-			}
-			else
-				W_SDREG(newstatus, &regs->intstatus, retries);
-		}
-	}
-
-	/* Merge new bits with previous */
-	intstatus |= newstatus;
-	bus->intstatus = 0;
-
-	/* Handle flow-control change: read new state in case our ack
-	 * crossed another change interrupt.  If change still set, assume
-	 * FC ON for safety, let next loop through do the debounce.
-	 */
-	if (intstatus & I_HMB_FC_CHANGE) {
-		intstatus &= ~I_HMB_FC_CHANGE;
-		W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
-		R_SDREG(newstatus, &regs->intstatus, retries);
-		bus->f1regdata += 2;
-		bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
-		intstatus |= (newstatus & bus->hostintmask);
-	}
-
-	/* Just being here means nothing more to do for chipactive */
-	if (intstatus & I_CHIPACTIVE) {
-		/* ASSERT(bus->clkstate == CLK_AVAIL); */
-		intstatus &= ~I_CHIPACTIVE;
-	}
-
-	/* Handle host mailbox indication */
-	if (intstatus & I_HMB_HOST_INT) {
-		intstatus &= ~I_HMB_HOST_INT;
-		intstatus |= dhdsdio_hostmail(bus);
-	}
-
-	/* Generally don't ask for these, can get CRC errors... */
-	if (intstatus & I_WR_OOSYNC) {
-		DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
-		intstatus &= ~I_WR_OOSYNC;
-	}
-
-	if (intstatus & I_RD_OOSYNC) {
-		DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
-		intstatus &= ~I_RD_OOSYNC;
-	}
-
-	if (intstatus & I_SBINT) {
-		DHD_ERROR(("Dongle reports SBINT\n"));
-		intstatus &= ~I_SBINT;
-	}
-
-	/* Would be active due to wake-wlan in gSPI */
-	if (intstatus & I_CHIPACTIVE) {
-		DHD_INFO(("Dongle reports CHIPACTIVE\n"));
-		intstatus &= ~I_CHIPACTIVE;
-	}
-
-	if (intstatus & I_HMB_FC_STATE) {
-		DHD_INFO(("Dongle reports HMB_FC_STATE\n"));
-		intstatus &= ~I_HMB_FC_STATE;
-	}
-
-	/* Ignore frame indications if rxskip is set */
-	if (bus->rxskip) {
-		intstatus &= ~FRAME_AVAIL_MASK(bus);
-	}
-
-	/* On frame indication, read available frames */
-	if (PKT_AVAILABLE(bus, intstatus)) {
-		framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
-		if (rxdone || bus->rxskip)
-			intstatus  &= ~FRAME_AVAIL_MASK(bus);
-		rxlimit -= MIN(framecnt, rxlimit);
-	}
-
-	/* Keep still-pending events for next scheduling */
-	bus->intstatus = intstatus;
-
-clkwait:
-	/* Re-enable interrupts to detect new device events (mailbox, rx frame)
-	 * or clock availability.  (Allows tx loop to check ipend if desired.)
-	 * (Unless register access seems hosed, as we may not be able to ACK...)
-	 */
-	if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
-		DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
-		          __FUNCTION__, rxdone, framecnt));
-		bus->intdis = FALSE;
-#if defined(OOB_INTR_ONLY)
-		bcmsdh_oob_intr_set(bus->sdh, TRUE);
-#endif /* defined(OOB_INTR_ONLY) */
-		bcmsdh_intr_enable(sdh);
-	}
-
-#if defined(OOB_INTR_ONLY) && !defined(HW_OOB)
-	/* In case of SW-OOB(using edge trigger),
-	 * Check interrupt status in the dongle again after enable irq on the host.
-	 * and rechedule dpc if interrupt is pended in the dongle.
-	 * There is a chance to miss OOB interrupt while irq is disabled on the host.
-	 * No need to do this with HW-OOB(level trigger)
-	 */
-	R_SDREG(newstatus, &regs->intstatus, retries);
-	if (bcmsdh_regfail(bus->sdh))
-		newstatus = 0;
-	if (newstatus & bus->hostintmask) {
-		bus->ipend = TRUE;
-		resched = TRUE;
-	}
-#endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */
-
-#ifdef PROP_TXSTATUS
-	dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE);
-#endif
-
-	if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
-		dhdsdio_sendpendctl(bus);
-
-	/* Send queued frames (limit 1 if rx may still be pending) */
-	else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
-	    pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
-		framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax);
-		framecnt = dhdsdio_sendfromq(bus, framecnt);
-		txlimit -= framecnt;
-	}
-	/* Resched the DPC if ctrl cmd is pending on bus credit */
-	if (bus->ctrl_frame_stat)
-		resched = TRUE;
-
-	/* Resched if events or tx frames are pending, else await next interrupt */
-	/* On failed register access, all bets are off: no resched or interrupts */
-	if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
-		if ((bus->sih && bus->sih->buscorerev >= 12) && !(dhdsdio_sleepcsr_get(bus) &
-			SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
-			/* Bus failed because of KSO */
-			DHD_ERROR(("%s: Bus failed due to KSO\n", __FUNCTION__));
-			bus->kso = FALSE;
-		} else {
-			DHD_ERROR(("%s: failed backplane access over SDIO, halting operation\n",
-				__FUNCTION__));
-			bus->dhd->busstate = DHD_BUS_DOWN;
-			bus->intstatus = 0;
-		}
-	} else if (bus->clkstate == CLK_PENDING) {
-		/* Awaiting I_CHIPACTIVE; don't resched */
-	} else if (bus->intstatus || bus->ipend ||
-	           (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
-			PKT_AVAILABLE(bus, bus->intstatus)) {  /* Read multiple frames */
-		resched = TRUE;
-	}
-
-	bus->dpc_sched = resched;
-
-	/* If we're done for now, turn off clock request. */
-	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && (bus->clkstate != CLK_PENDING)) {
-		bus->activity = FALSE;
-		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
-	}
-
-exit:
-
-	if (!resched && dhd_dpcpoll) {
-		if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0) {
-			resched = TRUE;
-#ifdef DEBUG_DPC_THREAD_WATCHDOG
-			is_resched_by_readframe = TRUE;
-#endif /* DEBUG_DPC_THREAD_WATCHDOG */
-		}
-	}
-
-	dhd_os_sdunlock(bus->dhd);
-#ifdef DEBUG_DPC_THREAD_WATCHDOG
-	if (bus->dhd->dhd_bug_on) {
-		DHD_INFO(("%s: resched = %d ctrl_frame_stat = %d intstatus 0x%08x"
-			" ipend = %d pktq_mlen = %d is_resched_by_readframe = %d \n",
-			__FUNCTION__, resched, bus->ctrl_frame_stat,
-			bus->intstatus, bus->ipend,
-			pktq_mlen(&bus->txq, ~bus->flowcontrol), is_resched_by_readframe));
-
-			bus->dhd->dhd_bug_on = FALSE;
-	}
-#endif /* DEBUG_DPC_THREAD_WATCHDOG */
-	return resched;
-}
-
-bool
-dhd_bus_dpc(struct dhd_bus *bus)
-{
-	bool resched;
-
-	/* Call the DPC directly. */
-	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
-	resched = dhdsdio_dpc(bus);
-
-	return resched;
-}
-
-void
-dhdsdio_isr(void *arg)
-{
-	dhd_bus_t *bus = (dhd_bus_t*)arg;
-	bcmsdh_info_t *sdh;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (!bus) {
-		DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
-		return;
-	}
-	sdh = bus->sdh;
-
-	if (bus->dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
-		return;
-	}
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	/* Count the interrupt call */
-	bus->intrcount++;
-	bus->ipend = TRUE;
-
-	/* Shouldn't get this interrupt if we're sleeping? */
-	if (!SLPAUTO_ENAB(bus)) {
-		if (bus->sleeping) {
-			DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
-			return;
-		} else if (!KSO_ENAB(bus)) {
-			DHD_ERROR(("ISR in devsleep 1\n"));
-		}
-	}
-
-	/* Disable additional interrupts (is this needed now)? */
-	if (bus->intr) {
-		DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
-	} else {
-		DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
-	}
-
-	bcmsdh_intr_disable(sdh);
-	bus->intdis = TRUE;
-
-#if defined(SDIO_ISR_THREAD)
-	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
-	DHD_OS_WAKE_LOCK(bus->dhd);
-	dhdsdio_dpc(bus);
-	DHD_OS_WAKE_UNLOCK(bus->dhd);
-#else
-	bus->dpc_sched = TRUE;
-	dhd_sched_dpc(bus->dhd);
-
-#endif /* defined(SDIO_ISR_THREAD) */
-
-}
-
-#ifdef SDTEST
-static void
-dhdsdio_pktgen_init(dhd_bus_t *bus)
-{
-	/* Default to specified length, or full range */
-	if (dhd_pktgen_len) {
-		bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN);
-		bus->pktgen_minlen = bus->pktgen_maxlen;
-	} else {
-		bus->pktgen_maxlen = MAX_PKTGEN_LEN;
-		bus->pktgen_minlen = 0;
-	}
-	bus->pktgen_len = (uint16)bus->pktgen_minlen;
-
-	/* Default to per-watchdog burst with 10s print time */
-	bus->pktgen_freq = 1;
-	bus->pktgen_print = dhd_watchdog_ms ? (10000 / dhd_watchdog_ms) : 0;
-	bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
-
-	/* Default to echo mode */
-	bus->pktgen_mode = DHD_PKTGEN_ECHO;
-	bus->pktgen_stop = 1;
-}
-
-static void
-dhdsdio_pktgen(dhd_bus_t *bus)
-{
-	void *pkt;
-	uint8 *data;
-	uint pktcount;
-	uint fillbyte;
-	osl_t *osh = bus->dhd->osh;
-	uint16 len;
-	ulong time_lapse;
-	uint sent_pkts;
-	uint rcvd_pkts;
-
-	/* Display current count if appropriate */
-	if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
-		bus->pktgen_ptick = 0;
-		printf("%s: send attempts %d, rcvd %d, errors %d\n",
-		       __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
-
-		/* Print throughput stats only for constant length packet runs */
-		if (bus->pktgen_minlen == bus->pktgen_maxlen) {
-			time_lapse = jiffies - bus->pktgen_prev_time;
-			bus->pktgen_prev_time = jiffies;
-			sent_pkts = bus->pktgen_sent - bus->pktgen_prev_sent;
-			bus->pktgen_prev_sent = bus->pktgen_sent;
-			rcvd_pkts = bus->pktgen_rcvd - bus->pktgen_prev_rcvd;
-			bus->pktgen_prev_rcvd = bus->pktgen_rcvd;
-
-			printf("%s: Tx Throughput %d kbps, Rx Throughput %d kbps\n",
-			  __FUNCTION__,
-			  (sent_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8,
-			  (rcvd_pkts * bus->pktgen_len  / jiffies_to_msecs(time_lapse)) * 8);
-		}
-	}
-
-	/* For recv mode, just make sure dongle has started sending */
-	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
-		if (bus->pktgen_rcv_state == PKTGEN_RCV_IDLE) {
-			bus->pktgen_rcv_state = PKTGEN_RCV_ONGOING;
-			dhdsdio_sdtest_set(bus, bus->pktgen_total);
-		}
-		return;
-	}
-
-	/* Otherwise, generate or request the specified number of packets */
-	for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
-		/* Stop if total has been reached */
-		if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) {
-			bus->pktgen_count = 0;
-			break;
-		}
-
-		/* Allocate an appropriate-sized packet */
-		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
-			len = SDPCM_TEST_PKT_CNT_FLD_LEN;
-		} else {
-			len = bus->pktgen_len;
-		}
-		if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
-		                   TRUE))) {;
-			DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
-			break;
-		}
-		PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
-		data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
-
-		/* Write test header cmd and extra based on mode */
-		switch (bus->pktgen_mode) {
-		case DHD_PKTGEN_ECHO:
-			*data++ = SDPCM_TEST_ECHOREQ;
-			*data++ = (uint8)bus->pktgen_sent;
-			break;
-
-		case DHD_PKTGEN_SEND:
-			*data++ = SDPCM_TEST_DISCARD;
-			*data++ = (uint8)bus->pktgen_sent;
-			break;
-
-		case DHD_PKTGEN_RXBURST:
-			*data++ = SDPCM_TEST_BURST;
-			*data++ = (uint8)bus->pktgen_count; /* Just for backward compatability */
-			break;
-
-		default:
-			DHD_ERROR(("Unrecognized pktgen mode %d\n", bus->pktgen_mode));
-			PKTFREE(osh, pkt, TRUE);
-			bus->pktgen_count = 0;
-			return;
-		}
-
-		/* Write test header length field */
-		*data++ = (bus->pktgen_len >> 0);
-		*data++ = (bus->pktgen_len >> 8);
-
-		/* Write frame count in a 4 byte field adjucent to SDPCM test header for
-		 * burst mode
-		 */
-		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
-			*data++ = (uint8)(bus->pktgen_count >> 0);
-			*data++ = (uint8)(bus->pktgen_count >> 8);
-			*data++ = (uint8)(bus->pktgen_count >> 16);
-			*data++ = (uint8)(bus->pktgen_count >> 24);
-		} else {
-
-			/* Then fill in the remainder -- N/A for burst */
-			for (fillbyte = 0; fillbyte < len; fillbyte++)
-				*data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent);
-		}
-
-#ifdef DHD_DEBUG
-		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
-			data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
-			prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN);
-		}
-#endif
-
-		/* Send it */
-		if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) {
-			bus->pktgen_fail++;
-			if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail)
-				bus->pktgen_count = 0;
-		}
-		bus->pktgen_sent++;
-
-		/* Bump length if not fixed, wrap at max */
-		if (++bus->pktgen_len > bus->pktgen_maxlen)
-			bus->pktgen_len = (uint16)bus->pktgen_minlen;
-
-		/* Special case for burst mode: just send one request! */
-		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
-			break;
-	}
-}
-
-static void
-dhdsdio_sdtest_set(dhd_bus_t *bus, uint count)
-{
-	void *pkt;
-	uint8 *data;
-	osl_t *osh = bus->dhd->osh;
-
-	/* Allocate the packet */
-	if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
-		SDPCM_TEST_PKT_CNT_FLD_LEN + DHD_SDALIGN, TRUE))) {
-		DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
-		return;
-	}
-	PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
-		SDPCM_TEST_PKT_CNT_FLD_LEN), DHD_SDALIGN);
-	data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
-
-	/* Fill in the test header */
-	*data++ = SDPCM_TEST_SEND;
-	*data++ = (count > 0)?TRUE:FALSE;
-	*data++ = (bus->pktgen_maxlen >> 0);
-	*data++ = (bus->pktgen_maxlen >> 8);
-	*data++ = (uint8)(count >> 0);
-	*data++ = (uint8)(count >> 8);
-	*data++ = (uint8)(count >> 16);
-	*data++ = (uint8)(count >> 24);
-
-	/* Send it */
-	if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK)
-		bus->pktgen_fail++;
-}
-
-
-static void
-dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq)
-{
-	osl_t *osh = bus->dhd->osh;
-	uint8 *data;
-	uint pktlen;
-
-	uint8 cmd;
-	uint8 extra;
-	uint16 len;
-	uint16 offset;
-
-	/* Check for min length */
-	if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) {
-		DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen));
-		PKTFREE(osh, pkt, FALSE);
-		return;
-	}
-
-	/* Extract header fields */
-	data = PKTDATA(osh, pkt);
-	cmd = *data++;
-	extra = *data++;
-	len = *data++; len += *data++ << 8;
-	DHD_TRACE(("%s:cmd:%d, xtra:%d,len:%d\n", __FUNCTION__, cmd, extra, len));
-	/* Check length for relevant commands */
-	if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) {
-		if (pktlen != len + SDPCM_TEST_HDRLEN) {
-			DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d"
-			           " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
-			PKTFREE(osh, pkt, FALSE);
-			return;
-		}
-	}
-
-	/* Process as per command */
-	switch (cmd) {
-	case SDPCM_TEST_ECHOREQ:
-		/* Rx->Tx turnaround ok (even on NDIS w/current implementation) */
-		*(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP;
-		if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) == BCME_OK) {
-			bus->pktgen_sent++;
-		} else {
-			bus->pktgen_fail++;
-			PKTFREE(osh, pkt, FALSE);
-		}
-		bus->pktgen_rcvd++;
-		break;
-
-	case SDPCM_TEST_ECHORSP:
-		if (bus->ext_loop) {
-			PKTFREE(osh, pkt, FALSE);
-			bus->pktgen_rcvd++;
-			break;
-		}
-
-		for (offset = 0; offset < len; offset++, data++) {
-			if (*data != SDPCM_TEST_FILL(offset, extra)) {
-				DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: "
-				           "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
-				           offset, len, SDPCM_TEST_FILL(offset, extra), *data));
-				break;
-			}
-		}
-		PKTFREE(osh, pkt, FALSE);
-		bus->pktgen_rcvd++;
-		break;
-
-	case SDPCM_TEST_DISCARD:
-		{
-			int i = 0;
-			uint8 *prn = data;
-			uint8 testval = extra;
-			for (i = 0; i < len; i++) {
-				if (*prn != testval) {
-					DHD_ERROR(("DIErr@Pkt#:%d,Ix:%d, expected:0x%x, got:0x%x\n",
-						i, bus->pktgen_rcvd_rcvsession, testval, *prn));
-					prn++; testval++;
-				}
-			}
-		}
-		PKTFREE(osh, pkt, FALSE);
-		bus->pktgen_rcvd++;
-		break;
-
-	case SDPCM_TEST_BURST:
-	case SDPCM_TEST_SEND:
-	default:
-		DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d"
-		          " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
-		PKTFREE(osh, pkt, FALSE);
-		break;
-	}
-
-	/* For recv mode, stop at limit (and tell dongle to stop sending) */
-	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
-		if (bus->pktgen_rcv_state != PKTGEN_RCV_IDLE) {
-			bus->pktgen_rcvd_rcvsession++;
-
-			if (bus->pktgen_total &&
-				(bus->pktgen_rcvd_rcvsession >= bus->pktgen_total)) {
-			bus->pktgen_count = 0;
-			DHD_ERROR(("Pktgen:rcv test complete!\n"));
-			bus->pktgen_rcv_state = PKTGEN_RCV_IDLE;
-			dhdsdio_sdtest_set(bus, FALSE);
-				bus->pktgen_rcvd_rcvsession = 0;
-			}
-		}
-	}
-}
-#endif /* SDTEST */
-
-int dhd_bus_oob_intr_register(dhd_pub_t *dhdp)
-{
-	int err = 0;
-
-#if defined(OOB_INTR_ONLY)
-	err = bcmsdh_oob_intr_register(dhdp->bus->sdh, dhdsdio_isr, dhdp->bus);
-#endif
-	return err;
-}
-
-void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp)
-{
-#if defined(OOB_INTR_ONLY)
-	bcmsdh_oob_intr_unregister(dhdp->bus->sdh);
-#endif
-}
-
-void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable)
-{
-#if defined(OOB_INTR_ONLY)
-	bcmsdh_oob_intr_set(dhdp->bus->sdh, enable);
-#endif
-}
-
-void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub)
-{
-	bcmsdh_dev_pm_stay_awake(dhdpub->bus->sdh);
-}
-
-void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub)
-{
-	bcmsdh_dev_relax(dhdpub->bus->sdh);
-}
-
-bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub)
-{
-	bool enabled = FALSE;
-
-	enabled = bcmsdh_dev_pm_enabled(dhdpub->bus->sdh);
-	return enabled;
-}
-
-extern bool
-dhd_bus_watchdog(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus;
-
-	DHD_TIMER(("%s: Enter\n", __FUNCTION__));
-
-	bus = dhdp->bus;
-
-	if (bus->dhd->dongle_reset)
-		return FALSE;
-
-	if (bus->dhd->hang_was_sent) {
-		dhd_os_wd_timer(bus->dhd, 0);
-		return FALSE;
-	}
-
-	/* Ignore the timer if simulating bus down */
-	if (!SLPAUTO_ENAB(bus) && bus->sleeping)
-		return FALSE;
-
-	if (dhdp->busstate == DHD_BUS_DOWN)
-		return FALSE;
-
-	dhd_os_sdlock(bus->dhd);
-
-	/* Poll period: check device if appropriate. */
-	if (!SLPAUTO_ENAB(bus) && (bus->poll && (++bus->polltick >= bus->pollrate))) {
-		uint32 intstatus = 0;
-
-		/* Reset poll tick */
-		bus->polltick = 0;
-
-		/* Check device if no interrupts */
-		if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
-
-			if (!bus->dpc_sched) {
-				uint8 devpend;
-				devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
-				                          SDIOD_CCCR_INTPEND, NULL);
-				intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2);
-			}
-
-			/* If there is something, make like the ISR and schedule the DPC */
-			if (intstatus) {
-				bus->pollcnt++;
-				bus->ipend = TRUE;
-				if (bus->intr) {
-					bcmsdh_intr_disable(bus->sdh);
-				}
-				bus->dpc_sched = TRUE;
-				dhd_sched_dpc(bus->dhd);
-			}
-		}
-
-		/* Update interrupt tracking */
-		bus->lastintrs = bus->intrcount;
-	}
-
-#ifdef DHD_DEBUG
-	/* Poll for console output periodically */
-	if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
-		bus->console.count += dhd_watchdog_ms;
-		if (bus->console.count >= dhd_console_ms) {
-			bus->console.count -= dhd_console_ms;
-			/* Make sure backplane clock is on */
-			if (SLPAUTO_ENAB(bus))
-				dhdsdio_bussleep(bus, FALSE);
-			else
-			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-			if (dhdsdio_readconsole(bus) < 0)
-				dhd_console_ms = 0;	/* On error, stop trying */
-		}
-	}
-#endif /* DHD_DEBUG */
-
-#ifdef SDTEST
-	/* Generate packets if configured */
-	if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
-		/* Make sure backplane clock is on */
-		if (SLPAUTO_ENAB(bus))
-			dhdsdio_bussleep(bus, FALSE);
-		else
-			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-		bus->pktgen_tick = 0;
-		dhdsdio_pktgen(bus);
-	}
-#endif
-
-	/* On idle timeout clear activity flag and/or turn off clock */
-#ifdef DHD_USE_IDLECOUNT
-	if (bus->activity)
-		bus->activity = FALSE;
-	else {
-		bus->idlecount++;
-
-		if ((bus->idletime > 0) && (bus->idlecount >= bus->idletime)) {
-			DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__));
-			if (SLPAUTO_ENAB(bus)) {
-				if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY)
-					dhd_os_wd_timer(bus->dhd, 0);
-			} else
-				dhdsdio_clkctl(bus, CLK_NONE, FALSE);
-
-			bus->idlecount = 0;
-		}
-	}
-#else
-	if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
-		if (++bus->idlecount >= bus->idletime) {
-			bus->idlecount = 0;
-			if (bus->activity) {
-				bus->activity = FALSE;
-				if (SLPAUTO_ENAB(bus)) {
-					if (!bus->readframes)
-						dhdsdio_bussleep(bus, TRUE);
-					else
-						bus->reqbussleep = TRUE;
-				}
-				else
-					dhdsdio_clkctl(bus, CLK_NONE, FALSE);
-			}
-		}
-	}
-#endif /* DHD_USE_IDLECOUNT */
-
-	dhd_os_sdunlock(bus->dhd);
-
-	return bus->ipend;
-}
-
-#ifdef DHD_DEBUG
-extern int
-dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	uint32 addr, val;
-	int rv;
-	void *pkt;
-
-	/* Address could be zero if CONSOLE := 0 in dongle Makefile */
-	if (bus->console_addr == 0)
-		return BCME_UNSUPPORTED;
-
-	/* Exclusive bus access */
-	dhd_os_sdlock(bus->dhd);
-
-	/* Don't allow input if dongle is in reset */
-	if (bus->dhd->dongle_reset) {
-		dhd_os_sdunlock(bus->dhd);
-		return BCME_NOTREADY;
-	}
-
-	/* Request clock to allow SDIO accesses */
-	BUS_WAKE(bus);
-	/* No pend allowed since txpkt is called later, ht clk has to be on */
-	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-	/* Zero cbuf_index */
-	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf_idx);
-	val = htol32(0);
-	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
-		goto done;
-
-	/* Write message into cbuf */
-	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf);
-	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
-		goto done;
-
-	/* Write length into vcons_in */
-	addr = bus->console_addr + OFFSETOF(hnd_cons_t, vcons_in);
-	val = htol32(msglen);
-	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
-		goto done;
-
-	/* Bump dongle by sending an empty packet on the event channel.
-	 * sdpcm_sendup (RX) checks for virtual console input.
-	 */
-	if ((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL)
-		rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE);
-
-done:
-	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
-		bus->activity = FALSE;
-		dhdsdio_clkctl(bus, CLK_NONE, TRUE);
-	}
-
-	dhd_os_sdunlock(bus->dhd);
-
-	return rv;
-}
-#endif /* DHD_DEBUG */
-
-#ifdef DHD_DEBUG
-static void
-dhd_dump_cis(uint fn, uint8 *cis)
-{
-	uint byte, tag, tdata;
-	DHD_INFO(("Function %d CIS:\n", fn));
-
-	for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
-		if ((byte % 16) == 0)
-			DHD_INFO(("    "));
-		DHD_INFO(("%02x ", cis[byte]));
-		if ((byte % 16) == 15)
-			DHD_INFO(("\n"));
-		if (!tdata--) {
-			tag = cis[byte];
-			if (tag == 0xff)
-				break;
-			else if (!tag)
-				tdata = 0;
-			else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
-				tdata = cis[byte + 1] + 1;
-			else
-				DHD_INFO(("]"));
-		}
-	}
-	if ((byte % 16) != 15)
-		DHD_INFO(("\n"));
-}
-#endif /* DHD_DEBUG */
-
-static bool
-dhdsdio_chipmatch(uint16 chipid)
-{
-	if (chipid == BCM4325_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4329_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4315_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4319_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4336_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4330_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43237_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43362_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4314_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43242_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43340_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43341_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43143_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43342_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4334_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43239_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4324_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4335_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4339_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43349_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4345_CHIP_ID || chipid == BCM43454_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4350_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4354_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4356_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM4358_CHIP_ID)
-		return TRUE;
-	if (chipid == BCM43430_CHIP_ID)
-		return TRUE;
-	if (BCM4349_CHIP(chipid))
-		return TRUE;
-	return FALSE;
-}
-
-static void *
-dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
-	uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
-{
-	int ret;
-	dhd_bus_t *bus;
-
-
-	/* Init global variables at run-time, not as part of the declaration.
-	 * This is required to support init/de-init of the driver. Initialization
-	 * of globals as part of the declaration results in non-deterministic
-	 * behavior since the value of the globals may be different on the
-	 * first time that the driver is initialized vs subsequent initializations.
-	 */
-	dhd_txbound = DHD_TXBOUND;
-	dhd_rxbound = DHD_RXBOUND;
-	dhd_alignctl = TRUE;
-	sd1idle = TRUE;
-	dhd_readahead = TRUE;
-	retrydata = FALSE;
-
-#ifdef DISABLE_FLOW_CONTROL
-	dhd_doflow = FALSE;
-#endif /* DISABLE_FLOW_CONTROL */
-	dhd_dongle_ramsize = 0;
-	dhd_txminmax = DHD_TXMINMAX;
-
-	forcealign = TRUE;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-	DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid));
-
-	/* We make assumptions about address window mappings */
-	ASSERT((uintptr)regsva == SI_ENUM_BASE);
-
-	/* BCMSDH passes venid and devid based on CIS parsing -- but low-power start
-	 * means early parse could fail, so here we should get either an ID
-	 * we recognize OR (-1) indicating we must request power first.
-	 */
-	/* Check the Vendor ID */
-	switch (venid) {
-		case 0x0000:
-		case VENDOR_BROADCOM:
-			break;
-		default:
-			DHD_ERROR(("%s: unknown vendor: 0x%04x\n",
-			           __FUNCTION__, venid));
-			goto forcereturn;
-	}
-
-	/* Check the Device ID and make sure it's one that we support */
-	switch (devid) {
-		case BCM4325_D11DUAL_ID:		/* 4325 802.11a/g id */
-		case BCM4325_D11G_ID:			/* 4325 802.11g 2.4Ghz band id */
-		case BCM4325_D11A_ID:			/* 4325 802.11a 5Ghz band id */
-			DHD_INFO(("%s: found 4325 Dongle\n", __FUNCTION__));
-			break;
-		case BCM4329_D11N_ID:		/* 4329 802.11n dualband device */
-		case BCM4329_D11N2G_ID:		/* 4329 802.11n 2.4G device */
-		case BCM4329_D11N5G_ID:		/* 4329 802.11n 5G device */
-		case 0x4329:
-			DHD_INFO(("%s: found 4329 Dongle\n", __FUNCTION__));
-			break;
-		case BCM4315_D11DUAL_ID:		/* 4315 802.11a/g id */
-		case BCM4315_D11G_ID:			/* 4315 802.11g id */
-		case BCM4315_D11A_ID:			/* 4315 802.11a id */
-			DHD_INFO(("%s: found 4315 Dongle\n", __FUNCTION__));
-			break;
-		case BCM4319_D11N_ID:			/* 4319 802.11n id */
-		case BCM4319_D11N2G_ID:			/* 4319 802.11n2g id */
-		case BCM4319_D11N5G_ID:			/* 4319 802.11n5g id */
-			DHD_INFO(("%s: found 4319 Dongle\n", __FUNCTION__));
-			break;
-		case 0:
-			DHD_INFO(("%s: allow device id 0, will check chip internals\n",
-			          __FUNCTION__));
-			break;
-
-		default:
-			DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
-			           __FUNCTION__, venid, devid));
-			goto forcereturn;
-	}
-
-	if (osh == NULL) {
-		DHD_ERROR(("%s: osh is NULL!\n", __FUNCTION__));
-		goto forcereturn;
-	}
-
-	/* Allocate private bus interface state */
-	if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) {
-		DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
-		goto fail;
-	}
-	bzero(bus, sizeof(dhd_bus_t));
-	bus->sdh = sdh;
-	bus->cl_devid = (uint16)devid;
-	bus->bus = DHD_BUS;
-	bus->bus_num = bus_no;
-	bus->slot_num = slot;
-	bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
-	bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */
-
-#if defined(SUPPORT_P2P_GO_PS)
-	init_waitqueue_head(&bus->bus_sleep);
-#endif /* LINUX && SUPPORT_P2P_GO_PS */
-
-	/* attempt to attach to the dongle */
-	if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) {
-		DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__));
-		goto fail;
-	}
-
-	/* Attach to the dhd/OS/network interface */
-	if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) {
-		DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
-		goto fail;
-	}
-
-	/* Allocate buffers */
-	if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
-		DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__));
-		goto fail;
-	}
-
-	if (!(dhdsdio_probe_init(bus, osh, sdh))) {
-		DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__));
-		goto fail;
-	}
-
-	if (bus->intr) {
-		/* Register interrupt callback, but mask it (not operational yet). */
-		DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
-		bcmsdh_intr_disable(sdh);
-		if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
-			DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
-			           __FUNCTION__, ret));
-			goto fail;
-		}
-		DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
-	} else {
-		DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode\n",
-		           __FUNCTION__));
-	}
-
-	DHD_INFO(("%s: completed!!\n", __FUNCTION__));
-
-	/* if firmware path present try to download and bring up bus */
-	bus->dhd->hang_report  = TRUE;
-	if (dhd_download_fw_on_driverload) {
-		if ((ret = dhd_bus_start(bus->dhd)) != 0) {
-			DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__));
-				goto fail;
-		}
-	}
-	else {
-		/* Set random MAC address during boot time */
-		get_random_bytes(&bus->dhd->mac.octet[3], 3);
-		/* Adding BRCM OUI */
-		bus->dhd->mac.octet[0] = 0;
-		bus->dhd->mac.octet[1] = 0x90;
-		bus->dhd->mac.octet[2] = 0x4C;
-	}
-	/* Ok, have the per-port tell the stack we're open for business */
-	if (dhd_register_if(bus->dhd, 0, TRUE) != 0) {
-		DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__));
-		goto fail;
-	}
-
-#ifdef BCMHOST_XTAL_PU_TIME_MOD
-	bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11);
-#ifdef BCM4330_CHIP
-	bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x0000F801);
-#else
-	bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00F80001);
-#endif /* BCM4330_CHIP */
-#endif /* BCMHOST_XTAL_PU_TIME_MOD */
-
-
-	return bus;
-
-fail:
-	dhdsdio_release(bus, osh);
-
-forcereturn:
-
-	return NULL;
-}
-
-static bool
-dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
-                     uint16 devid)
-{
-	int err = 0;
-	uint8 clkctl = 0;
-
-	bus->alp_only = TRUE;
-	bus->sih = NULL;
-
-	/* Return the window to backplane enumeration space for core access */
-	if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE)) {
-		DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__));
-	}
-
-#if defined(DHD_DEBUG) && !defined(CUSTOMER_HW4_DEBUG)
-	DHD_ERROR(("F1 signature read @0x18000000=0x%4x\n",
-		bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4)));
-#endif /* DHD_DEBUG && !CUSTOMER_HW4_DEBUG */
-
-
-	/* Force PLL off until si_attach() programs PLL control regs */
-
-
-
-	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err);
-	if (!err)
-		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
-
-	if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
-		DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
-		           err, DHD_INIT_CLKCTL1, clkctl));
-		goto fail;
-	}
-
-#ifdef DHD_DEBUG
-	if (DHD_INFO_ON()) {
-		uint fn, numfn;
-		uint8 *cis[SDIOD_MAX_IOFUNCS];
-		int err = 0;
-
-		numfn = bcmsdh_query_iofnum(sdh);
-		ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
-
-		/* Make sure ALP is available before trying to read CIS */
-		SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
-		                                    SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
-		          !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
-
-		/* Now request ALP be put on the bus */
-		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-		                 DHD_INIT_CLKCTL2, &err);
-		OSL_DELAY(65);
-
-		for (fn = 0; fn <= numfn; fn++) {
-			if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) {
-				DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn));
-				break;
-			}
-			bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT);
-
-			if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT))) {
-				DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err));
-				MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
-				break;
-			}
-			dhd_dump_cis(fn, cis[fn]);
-		}
-
-		while (fn-- > 0) {
-			ASSERT(cis[fn]);
-			MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
-		}
-
-		if (err) {
-			DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n"));
-			goto fail;
-		}
-	}
-#endif /* DHD_DEBUG */
-
-	/* si_attach() will provide an SI handle and scan the backplane */
-	if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh,
-	                           &bus->vars, &bus->varsz))) {
-		DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__));
-		goto fail;
-	}
-
-#ifdef DHD_DEBUG
-	DHD_ERROR(("F1 signature OK, socitype:0x%x chip:0x%4x rev:0x%x pkg:0x%x\n",
-		bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, bus->sih->chippkg));
-#endif /* DHD_DEBUG */
-
-
-	bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev);
-
-	if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) {
-		DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
-		           __FUNCTION__, bus->sih->chip));
-		goto fail;
-	}
-
-	if (bus->sih->buscorerev >= 12)
-		dhdsdio_clk_kso_init(bus);
-	else
-		bus->kso = TRUE;
-
-	if (CST4330_CHIPMODE_SDIOD(bus->sih->chipst)) {
-	}
-
-	si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
-
-
-	/* Get info on the ARM and SOCRAM cores... */
-	if (!DHD_NOPMU(bus)) {
-		if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) ||
-		    (si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) ||
-		    (si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
-			bus->armrev = si_corerev(bus->sih);
-		} else {
-			DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__));
-			goto fail;
-		}
-
-		if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
-			if (!(bus->orig_ramsize = si_socram_size(bus->sih))) {
-				DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__));
-				goto fail;
-			}
-		} else {
-			/* cr4 has a different way to find the RAM size from TCM's */
-			if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) {
-				DHD_ERROR(("%s: failed to find CR4-TCM memory!\n", __FUNCTION__));
-				goto fail;
-			}
-			/* also populate base address */
-			switch ((uint16)bus->sih->chip) {
-			case BCM4335_CHIP_ID:
-			case BCM4339_CHIP_ID:
-			case BCM43349_CHIP_ID:
-				bus->dongle_ram_base = CR4_4335_RAM_BASE;
-				break;
-			case BCM4350_CHIP_ID:
-			case BCM4354_CHIP_ID:
-			case BCM4356_CHIP_ID:
-			case BCM4358_CHIP_ID:
-				bus->dongle_ram_base = CR4_4350_RAM_BASE;
-				break;
-			case BCM4360_CHIP_ID:
-				bus->dongle_ram_base = CR4_4360_RAM_BASE;
-				break;
-			case BCM4345_CHIP_ID:
-			case BCM43454_CHIP_ID:
-				bus->dongle_ram_base = (bus->sih->chiprev < 6)  /* from 4345C0 */
-					? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
-				break;
-			case BCM4349_CHIP_GRPID:
-				/* RAM base changed from 4349c0(revid=9) onwards */
-				bus->dongle_ram_base = ((bus->sih->chiprev < 9) ?
-				CR4_4349_RAM_BASE: CR4_4349_RAM_BASE_FROM_REV_9);
-				break;
-			default:
-				bus->dongle_ram_base = 0;
-				DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n",
-				           __FUNCTION__, bus->dongle_ram_base));
-			}
-		}
-		bus->ramsize = bus->orig_ramsize;
-		if (dhd_dongle_ramsize)
-			dhd_dongle_setramsize(bus, dhd_dongle_ramsize);
-
-		DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n",
-		           bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base));
-
-		bus->srmemsize = si_socram_srmem_size(bus->sih);
-	}
-
-	/* ...but normally deal with the SDPCMDEV core */
-	if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) &&
-	    !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) {
-		DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__));
-		goto fail;
-	}
-	bus->sdpcmrev = si_corerev(bus->sih);
-
-	/* Set core control so an SDIO reset does a backplane reset */
-	OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
-	bus->rxint_mode = SDIO_DEVICE_HMB_RXINT;
-
-	if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
-		(bus->rxint_mode  == SDIO_DEVICE_RXDATAINT_MODE_1))
-	{
-		uint32 val;
-
-		val = R_REG(osh, &bus->regs->corecontrol);
-		val &= ~CC_XMTDATAAVAIL_MODE;
-		val |= CC_XMTDATAAVAIL_CTRL;
-		W_REG(osh, &bus->regs->corecontrol, val);
-	}
-
-
-	pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
-
-	/* Locate an appropriately-aligned portion of hdrbuf */
-	bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN);
-
-	/* Set the poll and/or interrupt flags */
-	bus->intr = (bool)dhd_intr;
-	if ((bus->poll = (bool)dhd_poll))
-		bus->pollrate = 1;
-
-	/* Setting default Glom size */
-	bus->txglomsize = SDPCM_DEFGLOM_SIZE;
-
-	return TRUE;
-
-fail:
-	if (bus->sih != NULL) {
-		si_detach(bus->sih);
-		bus->sih = NULL;
-	}
-	return FALSE;
-}
-
-static bool
-dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (bus->dhd->maxctl) {
-		bus->rxblen = ROUNDUP((bus->dhd->maxctl+SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
-		if (!(bus->rxbuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_RXBUF, bus->rxblen))) {
-			DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n",
-			           __FUNCTION__, bus->rxblen));
-			goto fail;
-		}
-	}
-	/* Allocate buffer to receive glomed packet */
-	if (!(bus->databuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) {
-		DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n",
-			__FUNCTION__, MAX_DATA_BUF));
-		/* release rxbuf which was already located as above */
-		if (!bus->rxblen)
-			DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen);
-		goto fail;
-	}
-
-	/* Align the buffer */
-	if ((uintptr)bus->databuf % DHD_SDALIGN)
-		bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN));
-	else
-		bus->dataptr = bus->databuf;
-
-	return TRUE;
-
-fail:
-	return FALSE;
-}
-
-static bool
-dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
-{
-	int32 fnum;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	bus->_srenab = FALSE;
-
-#ifdef SDTEST
-	dhdsdio_pktgen_init(bus);
-#endif /* SDTEST */
-
-	/* Disable F2 to clear any intermediate frame state on the dongle */
-	bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
-
-	bus->dhd->busstate = DHD_BUS_DOWN;
-	bus->sleeping = FALSE;
-	bus->rxflow = FALSE;
-	bus->prev_rxlim_hit = 0;
-
-	/* Done with backplane-dependent accesses, can drop clock... */
-	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
-
-	/* ...and initialize clock/power states */
-	bus->clkstate = CLK_SDONLY;
-	bus->idletime = (int32)dhd_idletime;
-	bus->idleclock = DHD_IDLE_ACTIVE;
-
-	/* Query the SD clock speed */
-	if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
-	                    &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
-		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_divisor"));
-		bus->sd_divisor = -1;
-	} else {
-		DHD_INFO(("%s: Initial value for %s is %d\n",
-		          __FUNCTION__, "sd_divisor", bus->sd_divisor));
-	}
-
-	/* Query the SD bus mode */
-	if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
-	                    &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
-		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_mode"));
-		bus->sd_mode = -1;
-	} else {
-		DHD_INFO(("%s: Initial value for %s is %d\n",
-		          __FUNCTION__, "sd_mode", bus->sd_mode));
-	}
-
-	/* Query the F2 block size, set roundup accordingly */
-	fnum = 2;
-	if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32),
-	                    &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
-		bus->blocksize = 0;
-		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
-	} else {
-		DHD_INFO(("%s: Initial value for %s is %d\n",
-		          __FUNCTION__, "sd_blocksize", bus->blocksize));
-
-		dhdsdio_tune_fifoparam(bus);
-	}
-	bus->roundup = MIN(max_roundup, bus->blocksize);
-
-#ifdef DHDENABLE_TAILPAD
-	if (bus->pad_pkt)
-		PKTFREE(osh, bus->pad_pkt, FALSE);
-	bus->pad_pkt = PKTGET(osh, SDIO_MAX_BLOCK_SIZE, FALSE);
-	if (bus->pad_pkt == NULL)
-		DHD_ERROR(("failed to allocate padding packet\n"));
-	else {
-		int alignment_offset = 0;
-		uintptr pktprt = (uintptr)PKTDATA(osh, bus->pad_pkt);
-		if (!(pktprt&1) && (pktprt = (pktprt % DHD_SDALIGN)))
-			PKTPUSH(osh, bus->pad_pkt, alignment_offset);
-		PKTSETNEXT(osh, bus->pad_pkt, NULL);
-	}
-#endif /* DHDENABLE_TAILPAD */
-
-	/* Query if bus module supports packet chaining, default to use if supported */
-	if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
-	                    &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) {
-		bus->sd_rxchain = FALSE;
-	} else {
-		DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
-		          __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support")));
-	}
-	bus->use_rxchain = (bool)bus->sd_rxchain;
-	bus->txinrx_thres = CUSTOM_TXINRX_THRES;
-	/* TX first in dhdsdio_readframes() */
-	bus->dotxinrx = TRUE;
-
-	return TRUE;
-}
-
-int
-dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
-                          char *pfw_path, char *pnv_path)
-{
-	int ret;
-
-	bus->fw_path = pfw_path;
-	bus->nv_path = pnv_path;
-
-	ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
-
-
-	return ret;
-}
-
-static int
-dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
-{
-	int ret;
-
-
-	DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n",
-		__FUNCTION__, bus->fw_path, bus->nv_path));
-	DHD_OS_WAKE_LOCK(bus->dhd);
-
-	/* Download the firmware */
-	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-	ret = _dhdsdio_download_firmware(bus);
-
-	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-
-	DHD_OS_WAKE_UNLOCK(bus->dhd);
-	return ret;
-}
-
-/* Detach and free everything */
-static void
-dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
-{
-	bool dongle_isolation = FALSE;
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (bus) {
-		ASSERT(osh);
-
-		if (bus->dhd) {
-			dongle_isolation = bus->dhd->dongle_isolation;
-			dhd_detach(bus->dhd);
-		}
-
-		/* De-register interrupt handler */
-		bcmsdh_intr_disable(bus->sdh);
-		bcmsdh_intr_dereg(bus->sdh);
-
-		if (bus->dhd) {
-			dhdsdio_release_dongle(bus, osh, dongle_isolation, TRUE);
-			dhd_free(bus->dhd);
-			bus->dhd = NULL;
-		}
-
-		dhdsdio_release_malloc(bus, osh);
-
-#ifdef DHD_DEBUG
-		if (bus->console.buf != NULL)
-			MFREE(osh, bus->console.buf, bus->console.bufsize);
-#endif
-
-#ifdef DHDENABLE_TAILPAD
-		if (bus->pad_pkt)
-			PKTFREE(osh, bus->pad_pkt, FALSE);
-#endif /* DHDENABLE_TAILPAD */
-
-		MFREE(osh, bus, sizeof(dhd_bus_t));
-	}
-
-	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
-}
-
-static void
-dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	if (bus->dhd && bus->dhd->dongle_reset)
-		return;
-
-	if (bus->rxbuf) {
-#ifndef CONFIG_DHD_USE_STATIC_BUF
-		MFREE(osh, bus->rxbuf, bus->rxblen);
-#endif
-		bus->rxctl = bus->rxbuf = NULL;
-		bus->rxlen = 0;
-	}
-
-	if (bus->databuf) {
-#ifndef CONFIG_DHD_USE_STATIC_BUF
-		MFREE(osh, bus->databuf, MAX_DATA_BUF);
-#endif
-		bus->databuf = NULL;
-	}
-
-	if (bus->vars && bus->varsz) {
-		MFREE(osh, bus->vars, bus->varsz);
-		bus->vars = NULL;
-	}
-
-}
-
-
-static void
-dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
-{
-	DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
-		bus->dhd, bus->dhd->dongle_reset));
-
-	if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag)
-		return;
-
-	if (bus->sih) {
-#if !defined(BCMLXSDMMC)
-		if (bus->dhd) {
-			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-		}
-		if (KSO_ENAB(bus) && (dongle_isolation == FALSE))
-			si_watchdog(bus->sih, 4);
-#endif /* !defined(BCMLXSDMMC) */
-		if (bus->dhd) {
-			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
-		}
-		si_detach(bus->sih);
-		bus->sih = NULL;
-		if (bus->vars && bus->varsz)
-			MFREE(osh, bus->vars, bus->varsz);
-		bus->vars = NULL;
-	}
-
-	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
-}
-
-static void
-dhdsdio_disconnect(void *ptr)
-{
-	dhd_bus_t *bus = (dhd_bus_t *)ptr;
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-
-
-	if (bus) {
-		ASSERT(bus->dhd);
-		dhdsdio_release(bus, bus->dhd->osh);
-	}
-
-
-
-	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
-}
-
-static int
-dhdsdio_suspend(void *context)
-{
-	int ret = 0;
-
-	dhd_bus_t *bus = (dhd_bus_t*)context;
-#ifdef SUPPORT_P2P_GO_PS
-	int wait_time = 0;
-
-	if (bus->idletime > 0) {
-		wait_time = msecs_to_jiffies(bus->idletime * dhd_watchdog_ms);
-	}
-#endif /* SUPPORT_P2P_GO_PS */
-	ret = dhd_os_check_wakelock(bus->dhd);
-#ifdef SUPPORT_P2P_GO_PS
-	if ((!ret) && (bus->dhd->up) && (bus->dhd->op_mode != DHD_FLAG_HOSTAP_MODE)) {
-		if (wait_event_timeout(bus->bus_sleep, bus->sleeping, wait_time) == 0) {
-			if (!bus->sleeping) {
-				return 1;
-			}
-		}
-	}
-#endif /* SUPPORT_P2P_GO_PS */
-	return ret;
-}
-
-static int
-dhdsdio_resume(void *context)
-{
-#if defined(OOB_INTR_ONLY)
-	dhd_bus_t *bus = (dhd_bus_t*)context;
-
-	if (dhd_os_check_if_up(bus->dhd))
-		bcmsdh_oob_intr_set(bus->sdh, TRUE);
-#endif 
-	return 0;
-}
-
-
-/* Register/Unregister functions are called by the main DHD entry
- * point (e.g. module insertion) to link with the bus driver, in
- * order to look for or await the device.
- */
-
-static bcmsdh_driver_t dhd_sdio = {
-	dhdsdio_probe,
-	dhdsdio_disconnect,
-	dhdsdio_suspend,
-	dhdsdio_resume
-};
-
-int
-dhd_bus_register(void)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	return bcmsdh_register(&dhd_sdio);
-}
-
-void
-dhd_bus_unregister(void)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	bcmsdh_unregister();
-}
-
-#if defined(BCMLXSDMMC)
-/* Register a dummy SDIO client driver in order to be notified of new SDIO device */
-int dhd_bus_reg_sdio_notify(void* semaphore)
-{
-	return bcmsdh_reg_sdio_notify(semaphore);
-}
-
-void dhd_bus_unreg_sdio_notify(void)
-{
-	bcmsdh_unreg_sdio_notify();
-}
-#endif /* defined(BCMLXSDMMC) */
-
-#ifdef BCMEMBEDIMAGE
-static int
-dhdsdio_download_code_array(struct dhd_bus *bus)
-{
-	int bcmerror = -1;
-	int offset = 0;
-	unsigned char *ularray = NULL;
-
-	DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__));
-
-	/* Download image */
-	while ((offset + MEMBLOCK) < sizeof(dlarray)) {
-		/* check if CR4 */
-		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
-			/* if address is 0, store the reset instruction to be written in 0 */
-
-			if (offset == 0) {
-				bus->resetinstr = *(((uint32*)dlarray));
-				/* Add start of RAM address to the address given by user */
-				offset += bus->dongle_ram_base;
-			}
-		}
-
-		bcmerror = dhdsdio_membytes(bus, TRUE, offset,
-			(uint8 *) (dlarray + offset), MEMBLOCK);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
-			        __FUNCTION__, bcmerror, MEMBLOCK, offset));
-			goto err;
-		}
-
-		offset += MEMBLOCK;
-	}
-
-	if (offset < sizeof(dlarray)) {
-		bcmerror = dhdsdio_membytes(bus, TRUE, offset,
-			(uint8 *) (dlarray + offset), sizeof(dlarray) - offset);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
-			        __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
-			goto err;
-		}
-	}
-
-#ifdef DHD_DEBUG
-	/* Upload and compare the downloaded code */
-	{
-		ularray = MALLOC(bus->dhd->osh, bus->ramsize);
-		/* Upload image to verify downloaded contents. */
-		offset = 0;
-		memset(ularray, 0xaa, bus->ramsize);
-		while ((offset + MEMBLOCK) < sizeof(dlarray)) {
-			bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK);
-			if (bcmerror) {
-				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
-					__FUNCTION__, bcmerror, MEMBLOCK, offset));
-				goto err;
-			}
-
-			offset += MEMBLOCK;
-		}
-
-		if (offset < sizeof(dlarray)) {
-			bcmerror = dhdsdio_membytes(bus, FALSE, offset,
-				ularray + offset, sizeof(dlarray) - offset);
-			if (bcmerror) {
-				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
-					__FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
-				goto err;
-			}
-		}
-
-		if (memcmp(dlarray, ularray, sizeof(dlarray))) {
-			DHD_ERROR(("%s: Downloaded image is corrupted (%s, %s, %s).\n",
-			           __FUNCTION__, dlimagename, dlimagever, dlimagedate));
-			goto err;
-		} else
-			DHD_ERROR(("%s: Download, Upload and compare succeeded (%s, %s, %s).\n",
-			           __FUNCTION__, dlimagename, dlimagever, dlimagedate));
-
-	}
-#endif /* DHD_DEBUG */
-
-err:
-	if (ularray)
-		MFREE(bus->dhd->osh, ularray, bus->ramsize);
-	return bcmerror;
-}
-#endif /* BCMEMBEDIMAGE */
-
-static int
-dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
-{
-	int bcmerror = -1;
-	int offset = 0;
-	int len;
-	void *image = NULL;
-	uint8 *memblock = NULL, *memptr;
-
-	DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
-
-	image = dhd_os_open_image(pfw_path);
-	if (image == NULL)
-		goto err;
-
-	memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
-	if (memblock == NULL) {
-		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
-		goto err;
-	}
-	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
-		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
-
-	/* Download image */
-	while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, image))) {
-		if (len < 0) {
-			DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
-			bcmerror = BCME_ERROR;
-			goto err;
-		}
-		/* check if CR4 */
-		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
-			/* if address is 0, store the reset instruction to be written in 0 */
-
-			if (offset == 0) {
-				bus->resetinstr = *(((uint32*)memptr));
-				/* Add start of RAM address to the address given by user */
-				offset += bus->dongle_ram_base;
-			}
-		}
-
-		bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
-			        __FUNCTION__, bcmerror, MEMBLOCK, offset));
-			goto err;
-		}
-
-		offset += MEMBLOCK;
-	}
-
-err:
-	if (memblock)
-		MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN);
-
-	if (image)
-		dhd_os_close_image(image);
-
-	return bcmerror;
-}
-
-static int
-dhdsdio_download_nvram(struct dhd_bus *bus)
-{
-	int bcmerror = -1;
-	uint len;
-	void * image = NULL;
-	char * memblock = NULL;
-	char *bufp;
-	char *pnv_path;
-	bool nvram_file_exists;
-
-	pnv_path = bus->nv_path;
-
-	nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
-
-	/* For Get nvram from UEFI */
-	if (nvram_file_exists)
-		image = dhd_os_open_image(pnv_path);
-
-	memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE);
-	if (memblock == NULL) {
-		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
-		           __FUNCTION__, MAX_NVRAMBUF_SIZE));
-		goto err;
-	}
-
-	/* For Get nvram from image or UEFI (when image == NULL ) */
-	len = dhd_os_get_image_block(memblock, MAX_NVRAMBUF_SIZE, image);
-
-	if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
-		bufp = (char *)memblock;
-		bufp[len] = 0;
-		len = process_nvram_vars(bufp, len);
-		if (len % 4) {
-			len += 4 - (len % 4);
-		}
-		bufp += len;
-		*bufp++ = 0;
-		if (len)
-			bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error downloading vars: %d\n",
-			           __FUNCTION__, bcmerror));
-		}
-	}
-	else {
-		DHD_ERROR(("%s: error reading nvram file: %d\n",
-		           __FUNCTION__, len));
-		bcmerror = BCME_SDIO_ERROR;
-	}
-
-err:
-	if (memblock)
-		MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE);
-
-	if (image)
-		dhd_os_close_image(image);
-
-	return bcmerror;
-}
-
-static int
-_dhdsdio_download_firmware(struct dhd_bus *bus)
-{
-	int bcmerror = -1;
-
-	bool embed = FALSE;	/* download embedded firmware */
-	bool dlok = FALSE;	/* download firmware succeeded */
-
-	/* Out immediately if no image to download */
-	if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
-#ifdef BCMEMBEDIMAGE
-		embed = TRUE;
-#else
-		return 0;
-#endif
-	}
-
-	/* Keep arm in reset */
-	if (dhdsdio_download_state(bus, TRUE)) {
-		DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__));
-		goto err;
-	}
-
-	/* External image takes precedence if specified */
-	if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
-		if (dhdsdio_download_code_file(bus, bus->fw_path)) {
-			DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
-#ifdef BCMEMBEDIMAGE
-			embed = TRUE;
-#else
-			goto err;
-#endif
-		}
-		else {
-			embed = FALSE;
-			dlok = TRUE;
-		}
-	}
-
-#ifdef BCMEMBEDIMAGE
-	if (embed) {
-		if (dhdsdio_download_code_array(bus)) {
-			DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__));
-			goto err;
-		}
-		else {
-			dlok = TRUE;
-		}
-	}
-#else
-	BCM_REFERENCE(embed);
-#endif
-	if (!dlok) {
-		DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
-		goto err;
-	}
-
-	/* External nvram takes precedence if specified */
-	if (dhdsdio_download_nvram(bus)) {
-		DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
-		goto err;
-	}
-
-	/* Take arm out of reset */
-	if (dhdsdio_download_state(bus, FALSE)) {
-		DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__));
-		goto err;
-	}
-
-	bcmerror = 0;
-
-err:
-	return bcmerror;
-}
-
-static int
-dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
-	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle)
-{
-	int status;
-
-	if (!KSO_ENAB(bus)) {
-		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
-		return BCME_NODEVICE;
-	}
-
-	status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle);
-
-	return status;
-}
-
-static int
-dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
-	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry)
-{
-	int ret;
-	int i = 0;
-	int retries = 0;
-	bcmsdh_info_t *sdh;
-
-	if (!KSO_ENAB(bus)) {
-		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
-		return BCME_NODEVICE;
-	}
-
-	sdh = bus->sdh;
-	do {
-		ret = bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes,
-			pkt, complete, handle);
-
-		bus->f2txdata++;
-		ASSERT(ret != BCME_PENDING);
-
-		if (ret == BCME_NODEVICE) {
-			DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__));
-		} else if (ret < 0) {
-			/* On failure, abort the command and terminate the frame */
-			DHD_ERROR(("%s: sdio error %d, abort command and terminate frame.\n",
-				__FUNCTION__, ret));
-			bus->tx_sderrs++;
-			bus->f1regdata++;
-			bus->dhd->tx_errors++;
-			bcmsdh_abort(sdh, SDIO_FUNC_2);
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
-				SFC_WF_TERM, NULL);
-			for (i = 0; i < READ_FRM_CNT_RETRIES; i++) {
-				uint8 hi, lo;
-				hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCHI,
-					NULL);
-				lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCLO,
-					NULL);
-				bus->f1regdata += 2;
-				if ((hi == 0) && (lo == 0))
-					break;
-			}
-		}
-	} while ((ret < 0) && retrydata && ++retries < max_retry);
-
-	return ret;
-}
-
-uint8
-dhd_bus_is_ioready(struct dhd_bus *bus)
-{
-	uint8 enable;
-	bcmsdh_info_t *sdh;
-	ASSERT(bus);
-	ASSERT(bus->sih != NULL);
-	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
-	sdh = bus->sdh;
-	return (enable == bcmsdh_cfg_read(sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL));
-}
-
-uint
-dhd_bus_chip(struct dhd_bus *bus)
-{
-	ASSERT(bus->sih != NULL);
-	return bus->sih->chip;
-}
-
-uint
-dhd_bus_chiprev(struct dhd_bus *bus)
-{
-	ASSERT(bus);
-	ASSERT(bus->sih != NULL);
-	return bus->sih->chiprev;
-}
-
-void *
-dhd_bus_pub(struct dhd_bus *bus)
-{
-	return bus->dhd;
-}
-
-void *
-dhd_bus_sih(struct dhd_bus *bus)
-{
-	return (void *)bus->sih;
-}
-
-void *
-dhd_bus_txq(struct dhd_bus *bus)
-{
-	return &bus->txq;
-}
-
-uint
-dhd_bus_hdrlen(struct dhd_bus *bus)
-{
-	return (bus->txglom_enable) ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
-}
-
-void
-dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val)
-{
-	bus->dotxinrx = val;
-}
-
-int
-dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
-{
-	int bcmerror = 0;
-	dhd_bus_t *bus;
-
-	bus = dhdp->bus;
-
-	if (flag == TRUE) {
-		if (!bus->dhd->dongle_reset) {
-			dhd_os_sdlock(dhdp);
-			dhd_os_wd_timer(dhdp, 0);
-#if !defined(IGNORE_ETH0_DOWN)
-			/* Force flow control as protection when stop come before ifconfig_down */
-			dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
-#endif /* !defined(IGNORE_ETH0_DOWN) */
-			/* Expect app to have torn down any connection before calling */
-			/* Stop the bus, disable F2 */
-			dhd_bus_stop(bus, FALSE);
-
-#if defined(OOB_INTR_ONLY)
-			/* Clean up any pending IRQ */
-			dhd_enable_oob_intr(bus, FALSE);
-			bcmsdh_oob_intr_set(bus->sdh, FALSE);
-			bcmsdh_oob_intr_unregister(bus->sdh);
-#endif 
-
-			/* Clean tx/rx buffer pointers, detach from the dongle */
-			dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE);
-
-			bus->dhd->dongle_reset = TRUE;
-			bus->dhd->up = FALSE;
-			dhd_txglom_enable(dhdp, FALSE);
-			dhd_os_sdunlock(dhdp);
-
-			DHD_TRACE(("%s:  WLAN OFF DONE\n", __FUNCTION__));
-			/* App can now remove power from device */
-		} else
-			bcmerror = BCME_SDIO_ERROR;
-	} else {
-		/* App must have restored power to device before calling */
-
-		DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __FUNCTION__));
-
-		if (bus->dhd->dongle_reset) {
-			/* Turn on WLAN */
-			dhd_os_sdlock(dhdp);
-			/* Reset SD client */
-			bcmsdh_reset(bus->sdh);
-
-			/* Attempt to re-attach & download */
-			if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
-				(uint32 *)SI_ENUM_BASE,
-				bus->cl_devid)) {
-				/* Attempt to download binary to the dongle */
-				if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) &&
-				    dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh) >= 0) {
-
-					/* Re-init bus, enable F2 transfer */
-					bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
-					if (bcmerror == BCME_OK) {
-#if defined(OOB_INTR_ONLY)
-						dhd_enable_oob_intr(bus, TRUE);
-						bcmsdh_oob_intr_register(bus->sdh,
-							dhdsdio_isr, bus);
-						bcmsdh_oob_intr_set(bus->sdh, TRUE);
-#endif 
-
-						bus->dhd->dongle_reset = FALSE;
-						bus->dhd->up = TRUE;
-
-#if !defined(IGNORE_ETH0_DOWN)
-						/* Restore flow control  */
-						dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
-#endif 
-						dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
-
-						DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
-					} else {
-						dhd_bus_stop(bus, FALSE);
-						dhdsdio_release_dongle(bus, bus->dhd->osh,
-							TRUE, FALSE);
-					}
-				} else {
-					DHD_ERROR(("%s Failed to download binary to the dongle\n",
-						__FUNCTION__));
-					if (bus->sih != NULL) {
-						si_detach(bus->sih);
-						bus->sih = NULL;
-					}
-					bcmerror = BCME_SDIO_ERROR;
-				}
-			} else
-				bcmerror = BCME_SDIO_ERROR;
-
-				dhd_os_sdunlock(dhdp);
-		} else {
-			bcmerror = BCME_SDIO_ERROR;
-			DHD_INFO(("%s called when dongle is not in reset\n",
-				__FUNCTION__));
-			DHD_INFO(("Will call dhd_bus_start instead\n"));
-			dhd_bus_resume(dhdp, 1);
-			if ((bcmerror = dhd_bus_start(dhdp)) != 0)
-				DHD_ERROR(("%s: dhd_bus_start fail with %d\n",
-					__FUNCTION__, bcmerror));
-		}
-	}
-	return bcmerror;
-}
-
-int dhd_bus_suspend(dhd_pub_t *dhdpub)
-{
-	return bcmsdh_stop(dhdpub->bus->sdh);
-}
-
-int dhd_bus_resume(dhd_pub_t *dhdpub, int stage)
-{
-	return bcmsdh_start(dhdpub->bus->sdh, stage);
-}
-
-/* Get Chip ID version */
-uint dhd_bus_chip_id(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-
-	return  bus->sih->chip;
-}
-
-/* Get Chip Rev ID version */
-uint dhd_bus_chiprev_id(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-
-	return bus->sih->chiprev;
-}
-
-/* Get Chip Pkg ID version */
-uint dhd_bus_chippkg_id(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-
-	return bus->sih->chippkg;
-}
-
-int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num, uint32 *slot_num)
-{
-	*bus_type = bus->bus;
-	*bus_num = bus->bus_num;
-	*slot_num = bus->slot_num;
-	return 0;
-}
-
-int
-dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size)
-{
-	dhd_bus_t *bus;
-
-	bus = dhdp->bus;
-	return dhdsdio_membytes(bus, set, address, data, size);
-}
-
-
-void
-dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path)
-{
-	bus->fw_path = pfw_path;
-	bus->nv_path = pnv_path;
-}
-
-int
-dhd_enableOOB(dhd_pub_t *dhd, bool sleep)
-{
-	dhd_bus_t *bus = dhd->bus;
-	sdpcmd_regs_t *regs = bus->regs;
-	uint retries = 0;
-
-	if (sleep) {
-		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-		/* Tell device to start using OOB wakeup */
-		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
-		if (retries > retry_limit) {
-			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
-			return BCME_BUSY;
-		}
-		/* Turn off our contribution to the HT clock request */
-		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-	} else {
-		/* Make sure the controller has the bus up */
-		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-		/* Send misc interrupt to indicate OOB not needed */
-		W_SDREG(0, &regs->tosbmailboxdata, retries);
-		if (retries <= retry_limit)
-			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
-
-		if (retries > retry_limit)
-			DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
-
-		/* Make sure we have SD bus access */
-		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-	}
-	return BCME_OK;
-}
-
-void
-dhd_bus_pktq_flush(dhd_pub_t *dhdp)
-{
-	dhd_bus_t *bus = dhdp->bus;
-	bool wlfc_enabled = FALSE;
-
-#ifdef PROP_TXSTATUS
-	wlfc_enabled = (dhd_wlfc_cleanup_txq(dhdp, NULL, 0) != WLFC_UNSUPPORTED);
-#endif
-	if (!wlfc_enabled) {
-#ifdef DHDTCPACK_SUPPRESS
-		/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
-		 * when there is a newly coming packet from network stack.
-		 */
-		dhd_tcpack_info_tbl_clean(bus->dhd);
-#endif /* DHDTCPACK_SUPPRESS */
-		/* Clear the data packet queues */
-		pktq_flush(dhdp->osh, &bus->txq, TRUE, NULL, 0);
-	}
-}
-
-#ifdef BCMSDIO
-int
-dhd_sr_config(dhd_pub_t *dhd, bool on)
-{
-	dhd_bus_t *bus = dhd->bus;
-
-	if (!bus->_srenab)
-		return -1;
-
-	return dhdsdio_clk_devsleep_iovar(bus, on);
-}
-
-uint16
-dhd_get_chipid(dhd_pub_t *dhd)
-{
-	dhd_bus_t *bus = dhd->bus;
-
-	if (bus && bus->sih)
-		return (uint16)bus->sih->chip;
-	else
-		return 0;
-}
-#endif /* BCMSDIO */
-
-#ifdef DEBUGGER
-uint32 dhd_sdio_reg_read(void *h, uint32 addr)
-{
-	uint32 rval;
-	struct dhd_bus *bus = (struct dhd_bus *) h;
-
-	dhd_os_sdlock(bus->dhd);
-
-	BUS_WAKE(bus);
-
-	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-	rval = bcmsdh_reg_read(bus->sdh, addr, 4);
-
-	dhd_os_sdunlock(bus->dhd);
-
-	return rval;
-}
-
-void dhd_sdio_reg_write(void *h, uint32 addr, uint32 val)
-{
-	struct dhd_bus *bus = (struct dhd_bus *) h;
-
-	dhd_os_sdlock(bus->dhd);
-
-	BUS_WAKE(bus);
-
-	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
-	bcmsdh_reg_write(bus->sdh, addr, 4, val);
-
-	dhd_os_sdunlock(bus->dhd);
-}
-#endif /* DEBUGGER */
diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.c b/drivers/net/wireless/bcmdhd/dhd_wlfc.c
deleted file mode 100644
index 0e74318..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_wlfc.c
+++ /dev/null
@@ -1,4507 +0,0 @@
-/*
- * DHD PROP_TXSTATUS Module.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_wlfc.c 579277 2015-08-14 04:49:50Z $
- *
- */
-
-
-#include <typedefs.h>
-#include <osl.h>
-
-#include <bcmutils.h>
-#include <bcmendian.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-
-#include <dhd_bus.h>
-
-#include <dhd_dbg.h>
-
-#ifdef PROP_TXSTATUS /* a form of flow control between host and dongle */
-#include <wlfc_proto.h>
-#include <dhd_wlfc.h>
-#endif
-
-#ifdef DHDTCPACK_SUPPRESS
-#include <dhd_ip.h>
-#endif /* DHDTCPACK_SUPPRESS */
-
-
-/*
- * wlfc naming and lock rules:
- *
- * 1. Private functions name like _dhd_wlfc_XXX, declared as static and avoid wlfc lock operation.
- * 2. Public functions name like dhd_wlfc_XXX, use wlfc lock if needed.
- * 3. Non-Proptxstatus module call public functions only and avoid wlfc lock operation.
- *
- */
-
-#if defined(DHD_WLFC_THREAD)
-#define WLFC_THREAD_QUICK_RETRY_WAIT_MS    10      /* 10 msec */
-#define WLFC_THREAD_RETRY_WAIT_MS          10000   /* 10 sec */
-#endif /* defined (DHD_WLFC_THREAD) */
-
-
-#ifdef PROP_TXSTATUS
-
-#define DHD_WLFC_QMON_COMPLETE(entry)
-
-#define LIMIT_BORROW
-
-
-/** reordering related */
-
-#if defined(DHD_WLFC_THREAD)
-static void
-_dhd_wlfc_thread_wakeup(dhd_pub_t *dhdp)
-{
-	dhdp->wlfc_thread_go = TRUE;
-	wake_up_interruptible(&dhdp->wlfc_wqhead);
-}
-#endif /* DHD_WLFC_THREAD */
-
-static uint16
-_dhd_wlfc_adjusted_seq(void* p, uint8 current_seq)
-{
-	uint16 seq;
-
-	if (!p) {
-		return 0xffff;
-	}
-
-	seq = WL_TXSTATUS_GET_FREERUNCTR(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
-	if (seq < current_seq) {
-		/* wrap around */
-		seq += 256;
-	}
-
-	return seq;
-}
-
-/**
- * Enqueue a caller supplied packet on a caller supplied precedence queue, optionally reorder
- * suppressed packets.
- *    @param[in] pq       caller supplied packet queue to enqueue the packet on
- *    @param[in] prec     precedence of the to-be-queued packet
- *    @param[in] p        transmit packet to enqueue
- *    @param[in] qHead    if TRUE, enqueue to head instead of tail. Used to maintain d11 seq order.
- *    @param[in] current_seq
- *    @param[in] reOrder  reOrder on odd precedence (=suppress queue)
- */
-static void
-_dhd_wlfc_prec_enque(struct pktq *pq, int prec, void* p, bool qHead,
-	uint8 current_seq, bool reOrder)
-{
-	struct pktq_prec *q;
-	uint16 seq, seq2;
-	void *p2, *p2_prev;
-
-	if (!p)
-		return;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-	/* queueing chains not allowed and no segmented SKB (Kernel-3.18.y) */
-	ASSERT(!((PKTLINK(p) != NULL) && (PKTLINK(p) != p)));
-
-	ASSERT(!pktq_full(pq));
-	ASSERT(!pktq_pfull(pq, prec));
-
-	q = &pq->q[prec];
-
-	PKTSETLINK(p, NULL);
-	if (q->head == NULL) {
-		/* empty queue */
-		q->head = p;
-		q->tail = p;
-	} else {
-		if (reOrder && (prec & 1)) {
-			seq = _dhd_wlfc_adjusted_seq(p, current_seq);
-			p2 = qHead ? q->head : q->tail;
-			seq2 = _dhd_wlfc_adjusted_seq(p2, current_seq);
-
-			if ((qHead &&((seq+1) > seq2)) || (!qHead && ((seq2+1) > seq))) {
-				/* need reorder */
-				p2 = q->head;
-				p2_prev = NULL;
-				seq2 = _dhd_wlfc_adjusted_seq(p2, current_seq);
-
-				while (seq > seq2) {
-					p2_prev = p2;
-					p2 = PKTLINK(p2);
-					if (!p2) {
-						break;
-					}
-					seq2 = _dhd_wlfc_adjusted_seq(p2, current_seq);
-				}
-
-				if (p2_prev == NULL) {
-					/* insert head */
-					PKTSETLINK(p, q->head);
-					q->head = p;
-				} else if (p2 == NULL) {
-					/* insert tail */
-					PKTSETLINK(p2_prev, p);
-					q->tail = p;
-				} else {
-					/* insert after p2_prev */
-					PKTSETLINK(p, PKTLINK(p2_prev));
-					PKTSETLINK(p2_prev, p);
-				}
-				goto exit;
-			}
-		}
-
-		if (qHead) {
-			PKTSETLINK(p, q->head);
-			q->head = p;
-		} else {
-			PKTSETLINK(q->tail, p);
-			q->tail = p;
-		}
-	}
-
-exit:
-
-	q->len++;
-	pq->len++;
-
-	if (pq->hi_prec < prec)
-		pq->hi_prec = (uint8)prec;
-} /* _dhd_wlfc_prec_enque */
-
-/**
- * Create a place to store all packet pointers submitted to the firmware until a status comes back,
- * suppress or otherwise.
- *
- * hang-er: noun, a contrivance on which things are hung, as a hook.
- */
-/** @deprecated soon */
-static void*
-_dhd_wlfc_hanger_create(dhd_pub_t *dhd, int max_items)
-{
-	int i;
-	wlfc_hanger_t* hanger;
-
-	/* allow only up to a specific size for now */
-	ASSERT(max_items == WLFC_HANGER_MAXITEMS);
-
-	if ((hanger = (wlfc_hanger_t*)DHD_OS_PREALLOC(dhd, DHD_PREALLOC_DHD_WLFC_HANGER,
-		WLFC_HANGER_SIZE(max_items))) == NULL) {
-		return NULL;
-	}
-	memset(hanger, 0, WLFC_HANGER_SIZE(max_items));
-	hanger->max_items = max_items;
-
-	for (i = 0; i < hanger->max_items; i++) {
-		hanger->items[i].state = WLFC_HANGER_ITEM_STATE_FREE;
-	}
-	return hanger;
-}
-
-/** @deprecated soon */
-static int
-_dhd_wlfc_hanger_delete(dhd_pub_t *dhd, void* hanger)
-{
-	wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
-
-	if (h) {
-		DHD_OS_PREFREE(dhd, h, WLFC_HANGER_SIZE(h->max_items));
-		return BCME_OK;
-	}
-	return BCME_BADARG;
-}
-
-/** @deprecated soon */
-static uint16
-_dhd_wlfc_hanger_get_free_slot(void* hanger)
-{
-	uint32 i;
-	wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
-
-	if (h) {
-		i = h->slot_pos + 1;
-		if (i == h->max_items) {
-			i = 0;
-		}
-		while (i != h->slot_pos) {
-			if (h->items[i].state == WLFC_HANGER_ITEM_STATE_FREE) {
-				h->slot_pos = i;
-				return (uint16)i;
-			}
-			i++;
-			if (i == h->max_items)
-				i = 0;
-		}
-		h->failed_slotfind++;
-	}
-	return WLFC_HANGER_MAXITEMS;
-}
-
-/** @deprecated soon */
-static int
-_dhd_wlfc_hanger_get_genbit(void* hanger, void* pkt, uint32 slot_id, int* gen)
-{
-	int rc = BCME_OK;
-	wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
-
-	*gen = 0xff;
-
-	/* this packet was not pushed at the time it went to the firmware */
-	if (slot_id == WLFC_HANGER_MAXITEMS)
-		return BCME_NOTFOUND;
-
-	if (h) {
-		if (h->items[slot_id].state != WLFC_HANGER_ITEM_STATE_FREE) {
-			*gen = h->items[slot_id].gen;
-		}
-		else {
-			DHD_ERROR(("Error: %s():%d item not used\n",
-				__FUNCTION__, __LINE__));
-			rc = BCME_NOTFOUND;
-		}
-
-	} else {
-		rc = BCME_BADARG;
-	}
-
-	return rc;
-}
-
-/** @deprecated soon */
-static int
-_dhd_wlfc_hanger_pushpkt(void* hanger, void* pkt, uint32 slot_id)
-{
-	int rc = BCME_OK;
-	wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
-
-	if (h && (slot_id < WLFC_HANGER_MAXITEMS)) {
-		if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_FREE) {
-			h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE;
-			h->items[slot_id].pkt = pkt;
-			h->items[slot_id].pkt_state = 0;
-			h->items[slot_id].pkt_txstatus = 0;
-			h->pushed++;
-		} else {
-			h->failed_to_push++;
-			rc = BCME_NOTFOUND;
-		}
-	} else {
-		rc = BCME_BADARG;
-	}
-
-	return rc;
-}
-
-/** @deprecated soon */
-static int
-_dhd_wlfc_hanger_poppkt(void* hanger, uint32 slot_id, void** pktout, bool remove_from_hanger)
-{
-	int rc = BCME_OK;
-	wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
-
-	*pktout = NULL;
-
-	/* this packet was not pushed at the time it went to the firmware */
-	if (slot_id == WLFC_HANGER_MAXITEMS)
-		return BCME_NOTFOUND;
-
-	if (h) {
-		if (h->items[slot_id].state != WLFC_HANGER_ITEM_STATE_FREE) {
-			*pktout = h->items[slot_id].pkt;
-			if (remove_from_hanger) {
-				h->items[slot_id].state =
-					WLFC_HANGER_ITEM_STATE_FREE;
-				h->items[slot_id].pkt = NULL;
-				h->items[slot_id].gen = 0xff;
-				h->items[slot_id].identifier = 0;
-				h->popped++;
-			}
-		} else {
-			h->failed_to_pop++;
-			rc = BCME_NOTFOUND;
-		}
-	} else {
-		rc = BCME_BADARG;
-	}
-
-	return rc;
-}
-
-/** @deprecated soon */
-static int
-_dhd_wlfc_hanger_mark_suppressed(void* hanger, uint32 slot_id, uint8 gen)
-{
-	int rc = BCME_OK;
-	wlfc_hanger_t* h = (wlfc_hanger_t*)hanger;
-
-	/* this packet was not pushed at the time it went to the firmware */
-	if (slot_id == WLFC_HANGER_MAXITEMS)
-		return BCME_NOTFOUND;
-	if (h) {
-		h->items[slot_id].gen = gen;
-		if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) {
-			h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED;
-		} else {
-			rc = BCME_BADARG;
-		}
-	} else {
-		rc = BCME_BADARG;
-	}
-
-	return rc;
-}
-
-/** remove reference of specific packet in hanger */
-/** @deprecated soon */
-static bool
-_dhd_wlfc_hanger_remove_reference(wlfc_hanger_t* h, void* pkt)
-{
-	int i;
-
-	if (!h || !pkt) {
-		return FALSE;
-	}
-
-	i = WL_TXSTATUS_GET_HSLOT(DHD_PKTTAG_H2DTAG(PKTTAG(pkt)));
-
-	if ((i < h->max_items) && (pkt == h->items[i].pkt)) {
-		if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) {
-			h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE;
-			h->items[i].pkt = NULL;
-			h->items[i].gen = 0xff;
-			h->items[i].identifier = 0;
-			return TRUE;
-		} else {
-			DHD_ERROR(("Error: %s():%d item not suppressed\n",
-				__FUNCTION__, __LINE__));
-		}
-	}
-
-	return FALSE;
-}
-
-/** afq = At Firmware Queue, queue containing packets pending in the dongle */
-static int
-_dhd_wlfc_enque_afq(athost_wl_status_info_t* ctx, void *p)
-{
-	wlfc_mac_descriptor_t* entry;
-	uint16 entry_idx = WL_TXSTATUS_GET_HSLOT(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
-	uint8 prec = DHD_PKTTAG_FIFO(PKTTAG(p));
-
-	if (entry_idx < WLFC_MAC_DESC_TABLE_SIZE)
-		entry  = &ctx->destination_entries.nodes[entry_idx];
-	else if (entry_idx < (WLFC_MAC_DESC_TABLE_SIZE + WLFC_MAX_IFNUM))
-		entry = &ctx->destination_entries.interfaces[entry_idx - WLFC_MAC_DESC_TABLE_SIZE];
-	else
-		entry = &ctx->destination_entries.other;
-
-	pktq_penq(&entry->afq, prec, p);
-
-	return BCME_OK;
-}
-
-/** afq = At Firmware Queue, queue containing packets pending in the dongle */
-static int
-_dhd_wlfc_deque_afq(athost_wl_status_info_t* ctx, uint16 hslot, uint8 hcnt, uint8 prec,
-	void **pktout)
-{
-	wlfc_mac_descriptor_t *entry;
-	struct pktq *pq;
-	struct pktq_prec *q;
-	void *p, *b;
-
-	if (!ctx) {
-		DHD_ERROR(("%s: ctx(%p), pktout(%p)\n", __FUNCTION__, ctx, pktout));
-		return BCME_BADARG;
-	}
-
-	if (pktout) {
-		*pktout = NULL;
-	}
-
-	ASSERT(hslot < (WLFC_MAC_DESC_TABLE_SIZE + WLFC_MAX_IFNUM + 1));
-
-	if (hslot < WLFC_MAC_DESC_TABLE_SIZE)
-		entry  = &ctx->destination_entries.nodes[hslot];
-	else if (hslot < (WLFC_MAC_DESC_TABLE_SIZE + WLFC_MAX_IFNUM))
-		entry = &ctx->destination_entries.interfaces[hslot - WLFC_MAC_DESC_TABLE_SIZE];
-	else
-		entry = &ctx->destination_entries.other;
-
-	pq = &entry->afq;
-
-	ASSERT(prec < pq->num_prec);
-
-	q = &pq->q[prec];
-
-	b = NULL;
-	p = q->head;
-
-	while (p && (hcnt != WL_TXSTATUS_GET_FREERUNCTR(DHD_PKTTAG_H2DTAG(PKTTAG(p)))))
-	{
-		b = p;
-		p = PKTLINK(p);
-	}
-
-	if (p == NULL) {
-		/* none is matched */
-		if (b) {
-			DHD_ERROR(("%s: can't find matching seq(%d)\n", __FUNCTION__, hcnt));
-		} else {
-			DHD_ERROR(("%s: queue is empty\n", __FUNCTION__));
-		}
-
-		return BCME_ERROR;
-	}
-
-	bcm_pkt_validate_chk(p);
-
-	if (!b) {
-		/* head packet is matched */
-		if ((q->head = PKTLINK(p)) == NULL) {
-			q->tail = NULL;
-		}
-	} else {
-		/* middle packet is matched */
-		DHD_INFO(("%s: out of order, seq(%d), head_seq(%d)\n", __FUNCTION__, hcnt,
-			WL_TXSTATUS_GET_FREERUNCTR(DHD_PKTTAG_H2DTAG(PKTTAG(q->head)))));
-		ctx->stats.ooo_pkts[prec]++;
-		PKTSETLINK(b, PKTLINK(p));
-		if (PKTLINK(p) == NULL) {
-			q->tail = b;
-		}
-	}
-
-	q->len--;
-	pq->len--;
-
-	PKTSETLINK(p, NULL);
-
-	if (pktout) {
-		*pktout = p;
-	}
-
-	return BCME_OK;
-} /* _dhd_wlfc_deque_afq */
-
-/**
- * Flow control information piggy backs on packets, in the form of one or more TLVs. This function
- * pushes one or more TLVs onto a packet that is going to be sent towards the dongle.
- *
- *     @param[in]     ctx
- *     @param[in/out] packet
- *     @param[in]     tim_signal TRUE if parameter 'tim_bmp' is valid
- *     @param[in]     tim_bmp
- *     @param[in]     mac_handle
- *     @param[in]     htodtag
- *     @param[in]     htodseq d11 seqno for seqno reuse, only used if 'seq reuse' was agreed upon
- *                    earlier between host and firmware.
- *     @param[in]     skip_wlfc_hdr
- */
-static int
-_dhd_wlfc_pushheader(athost_wl_status_info_t* ctx, void** packet, bool tim_signal,
-	uint8 tim_bmp, uint8 mac_handle, uint32 htodtag, uint16 htodseq, bool skip_wlfc_hdr)
-{
-	uint32 wl_pktinfo = 0;
-	uint8* wlh;
-	uint8 dataOffset = 0;
-	uint8 fillers;
-	uint8 tim_signal_len = 0;
-	dhd_pub_t *dhdp = (dhd_pub_t *)ctx->dhdp;
-
-	struct bdc_header *h;
-	void *p = *packet;
-
-	if (skip_wlfc_hdr)
-		goto push_bdc_hdr;
-
-	if (tim_signal) {
-		tim_signal_len = TLV_HDR_LEN + WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP;
-	}
-
-	/* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */
-	dataOffset = WLFC_CTL_VALUE_LEN_PKTTAG + TLV_HDR_LEN + tim_signal_len;
-	if (WLFC_GET_REUSESEQ(dhdp->wlfc_mode)) {
-		dataOffset += WLFC_CTL_VALUE_LEN_SEQ;
-	}
-
-	fillers = ROUNDUP(dataOffset, 4) - dataOffset;
-	dataOffset += fillers;
-
-	PKTPUSH(ctx->osh, p, dataOffset);
-	wlh = (uint8*) PKTDATA(ctx->osh, p);
-
-	wl_pktinfo = htol32(htodtag);
-
-	wlh[TLV_TAG_OFF] = WLFC_CTL_TYPE_PKTTAG;
-	wlh[TLV_LEN_OFF] = WLFC_CTL_VALUE_LEN_PKTTAG;
-	memcpy(&wlh[TLV_HDR_LEN] /* dst */, &wl_pktinfo, sizeof(uint32));
-
-	if (WLFC_GET_REUSESEQ(dhdp->wlfc_mode)) {
-		uint16 wl_seqinfo = htol16(htodseq);
-		wlh[TLV_LEN_OFF] += WLFC_CTL_VALUE_LEN_SEQ;
-		memcpy(&wlh[TLV_HDR_LEN + WLFC_CTL_VALUE_LEN_PKTTAG], &wl_seqinfo,
-			WLFC_CTL_VALUE_LEN_SEQ);
-	}
-
-	if (tim_signal_len) {
-		wlh[dataOffset - fillers - tim_signal_len ] =
-			WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP;
-		wlh[dataOffset - fillers - tim_signal_len + 1] =
-			WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP;
-		wlh[dataOffset - fillers - tim_signal_len + 2] = mac_handle;
-		wlh[dataOffset - fillers - tim_signal_len + 3] = tim_bmp;
-	}
-	if (fillers)
-		memset(&wlh[dataOffset - fillers], WLFC_CTL_TYPE_FILLER, fillers);
-
-push_bdc_hdr:
-	PKTPUSH(ctx->osh, p, BDC_HEADER_LEN);
-	h = (struct bdc_header *)PKTDATA(ctx->osh, p);
-	h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
-	if (PKTSUMNEEDED(p))
-		h->flags |= BDC_FLAG_SUM_NEEDED;
-
-
-	h->priority = (PKTPRIO(p) & BDC_PRIORITY_MASK);
-	h->flags2 = 0;
-	h->dataOffset = dataOffset >> 2;
-	BDC_SET_IF_IDX(h, DHD_PKTTAG_IF(PKTTAG(p)));
-	*packet = p;
-	return BCME_OK;
-} /* _dhd_wlfc_pushheader */
-
-/**
- * Removes (PULLs) flow control related headers from the caller supplied packet, is invoked eg
- * when a packet is about to be freed.
- */
-static int
-_dhd_wlfc_pullheader(athost_wl_status_info_t* ctx, void* pktbuf)
-{
-	struct bdc_header *h;
-
-	if (PKTLEN(ctx->osh, pktbuf) < BDC_HEADER_LEN) {
-		DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__,
-		           PKTLEN(ctx->osh, pktbuf), BDC_HEADER_LEN));
-		return BCME_ERROR;
-	}
-	h = (struct bdc_header *)PKTDATA(ctx->osh, pktbuf);
-
-	/* pull BDC header */
-	PKTPULL(ctx->osh, pktbuf, BDC_HEADER_LEN);
-
-	if (PKTLEN(ctx->osh, pktbuf) < (uint)(h->dataOffset << 2)) {
-		DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__,
-		           PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2)));
-		return BCME_ERROR;
-	}
-
-	/* pull wl-header */
-	PKTPULL(ctx->osh, pktbuf, (h->dataOffset << 2));
-	return BCME_OK;
-}
-
-/**
- * @param[in/out] p packet
- */
-static wlfc_mac_descriptor_t*
-_dhd_wlfc_find_table_entry(athost_wl_status_info_t* ctx, void* p)
-{
-	int i;
-	wlfc_mac_descriptor_t* table = ctx->destination_entries.nodes;
-	uint8 ifid = DHD_PKTTAG_IF(PKTTAG(p));
-	uint8* dstn = DHD_PKTTAG_DSTN(PKTTAG(p));
-	wlfc_mac_descriptor_t* entry = DHD_PKTTAG_ENTRY(PKTTAG(p));
-	int iftype = ctx->destination_entries.interfaces[ifid].iftype;
-
-	/* saved one exists, return it */
-	if (entry)
-		return entry;
-
-	/* Multicast destination, STA and P2P clients get the interface entry.
-	 * STA/GC gets the Mac Entry for TDLS destinations, TDLS destinations
-	 * have their own entry.
-	 */
-	if ((iftype == WLC_E_IF_ROLE_STA || ETHER_ISMULTI(dstn) ||
-		iftype == WLC_E_IF_ROLE_P2P_CLIENT) &&
-		(ctx->destination_entries.interfaces[ifid].occupied)) {
-			entry = &ctx->destination_entries.interfaces[ifid];
-	}
-
-	if (entry && ETHER_ISMULTI(dstn)) {
-		DHD_PKTTAG_SET_ENTRY(PKTTAG(p), entry);
-		return entry;
-	}
-
-	for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) {
-		if (table[i].occupied) {
-			if (table[i].interface_id == ifid) {
-				if (!memcmp(table[i].ea, dstn, ETHER_ADDR_LEN)) {
-					entry = &table[i];
-					break;
-				}
-			}
-		}
-	}
-
-	if (entry == NULL)
-		entry = &ctx->destination_entries.other;
-
-	DHD_PKTTAG_SET_ENTRY(PKTTAG(p), entry);
-
-	return entry;
-} /* _dhd_wlfc_find_table_entry */
-
-/**
- * In case a packet must be dropped (because eg the queues are full), various tallies have to be
- * be updated. Called from several other functions.
- *     @param[in] dhdp pointer to public DHD structure
- *     @param[in] prec precedence of the packet
- *     @param[in] p    the packet to be dropped
- *     @param[in] bPktInQ TRUE if packet is part of a queue
- */
-static int
-_dhd_wlfc_prec_drop(dhd_pub_t *dhdp, int prec, void* p, bool bPktInQ)
-{
-	athost_wl_status_info_t* ctx;
-	void *pout = NULL;
-
-	ASSERT(dhdp && p);
-	ASSERT(prec >= 0 && prec <= WLFC_PSQ_PREC_COUNT);
-
-	ctx = (athost_wl_status_info_t*)dhdp->wlfc_state;
-
-	if (!WLFC_GET_AFQ(dhdp->wlfc_mode) && (prec & 1)) {
-		/* suppressed queue, need pop from hanger */
-		_dhd_wlfc_hanger_poppkt(ctx->hanger, WL_TXSTATUS_GET_HSLOT(DHD_PKTTAG_H2DTAG
-					(PKTTAG(p))), &pout, TRUE);
-		ASSERT(p == pout);
-	}
-
-	if (!(prec & 1)) {
-#ifdef DHDTCPACK_SUPPRESS
-		/* pkt in delayed q, so fake push BDC header for
-		 * dhd_tcpack_check_xmit() and dhd_txcomplete().
-		 */
-		_dhd_wlfc_pushheader(ctx, &p, FALSE, 0, 0, 0, 0, TRUE);
-
-		/* This packet is about to be freed, so remove it from tcp_ack_info_tbl
-		 * This must be one of...
-		 * 1. A pkt already in delayQ is evicted by another pkt with higher precedence
-		 * in _dhd_wlfc_prec_enq_with_drop()
-		 * 2. A pkt could not be enqueued to delayQ because it is full,
-		 * in _dhd_wlfc_enque_delayq().
-		 * 3. A pkt could not be enqueued to delayQ because it is full,
-		 * in _dhd_wlfc_rollback_packet_toq().
-		 */
-		if (dhd_tcpack_check_xmit(dhdp, p) == BCME_ERROR) {
-			DHD_ERROR(("%s %d: tcpack_suppress ERROR!!!"
-				" Stop using it\n",
-				__FUNCTION__, __LINE__));
-			dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF);
-		}
-#endif /* DHDTCPACK_SUPPRESS */
-	}
-
-	if (bPktInQ) {
-		ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(p))][prec>>1]--;
-		ctx->pkt_cnt_per_ac[prec>>1]--;
-		ctx->pkt_cnt_in_psq--;
-	}
-
-	ctx->pkt_cnt_in_drv[DHD_PKTTAG_IF(PKTTAG(p))][DHD_PKTTAG_FIFO(PKTTAG(p))]--;
-	ctx->stats.pktout++;
-	ctx->stats.drop_pkts[prec]++;
-
-	dhd_txcomplete(dhdp, p, FALSE);
-	PKTFREE(ctx->osh, p, TRUE);
-
-	return 0;
-} /* _dhd_wlfc_prec_drop */
-
-/**
- * Called when eg the host handed a new packet over to the driver, or when the dongle reported
- * that a packet could currently not be transmitted (=suppressed). This function enqueues a transmit
- * packet in the host driver to be (re)transmitted at a later opportunity.
- *     @param[in] dhdp pointer to public DHD structure
- *     @param[in] qHead When TRUE, queue packet at head instead of tail, to preserve d11 sequence
- */
-static bool
-_dhd_wlfc_prec_enq_with_drop(dhd_pub_t *dhdp, struct pktq *pq, void *pkt, int prec, bool qHead,
-	uint8 current_seq)
-{
-	void *p = NULL;
-	int eprec = -1;		/* precedence to evict from */
-	athost_wl_status_info_t* ctx;
-
-	ASSERT(dhdp && pq && pkt);
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	ctx = (athost_wl_status_info_t*)dhdp->wlfc_state;
-
-	/* Fast case, precedence queue is not full and we are also not
-	 * exceeding total queue length
-	 */
-	if (!pktq_pfull(pq, prec) && !pktq_full(pq)) {
-		goto exit;
-	}
-
-	/* Determine precedence from which to evict packet, if any */
-	if (pktq_pfull(pq, prec)) {
-		eprec = prec;
-	} else if (pktq_full(pq)) {
-		p = pktq_peek_tail(pq, &eprec);
-		if (!p) {
-			DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-			return FALSE;
-		}
-		if ((eprec > prec) || (eprec < 0)) {
-			if (!pktq_pempty(pq, prec)) {
-				eprec = prec;
-			} else {
-				return FALSE;
-			}
-		}
-	}
-
-	/* Evict if needed */
-	if (eprec >= 0) {
-		/* Detect queueing to unconfigured precedence */
-		ASSERT(!pktq_pempty(pq, eprec));
-		/* Evict all fragmented frames */
-		dhd_prec_drop_pkts(dhdp, pq, eprec, _dhd_wlfc_prec_drop);
-	}
-
-exit:
-	/* Enqueue */
-	_dhd_wlfc_prec_enque(pq, prec, pkt, qHead, current_seq,
-		WLFC_GET_REORDERSUPP(dhdp->wlfc_mode));
-	ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(pkt))][prec>>1]++;
-	ctx->pkt_cnt_per_ac[prec>>1]++;
-	ctx->pkt_cnt_in_psq++;
-
-	return TRUE;
-} /* _dhd_wlfc_prec_enq_with_drop */
-
-/**
- * Called during eg the 'committing' of a transmit packet from the OS layer to a lower layer, in
- * the event that this 'commit' failed.
- */
-static int
-_dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx,
-	void* p, ewlfc_packet_state_t pkt_type, uint32 hslot)
-{
-	/*
-	 * put the packet back to the head of queue
-	 * - suppressed packet goes back to suppress sub-queue
-	 * - pull out the header, if new or delayed packet
-	 *
-	 * Note: hslot is used only when header removal is done.
-	 */
-	wlfc_mac_descriptor_t* entry;
-	int rc = BCME_OK;
-	int prec, fifo_id;
-
-	entry = _dhd_wlfc_find_table_entry(ctx, p);
-	prec = DHD_PKTTAG_FIFO(PKTTAG(p));
-	fifo_id = prec << 1;
-	if (pkt_type == eWLFC_PKTTYPE_SUPPRESSED)
-		fifo_id += 1;
-	if (entry != NULL) {
-		/*
-		if this packet did not count against FIFO credit, it must have
-		taken a requested_credit from the firmware (for pspoll etc.)
-		*/
-		if ((prec != AC_COUNT) && !DHD_PKTTAG_CREDITCHECK(PKTTAG(p)))
-			entry->requested_credit++;
-
-		if (pkt_type == eWLFC_PKTTYPE_DELAYED) {
-			/* decrement sequence count */
-			WLFC_DECR_SEQCOUNT(entry, prec);
-			/* remove header first */
-			rc = _dhd_wlfc_pullheader(ctx, p);
-			if (rc != BCME_OK) {
-				DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-				goto exit;
-			}
-		}
-
-		if (_dhd_wlfc_prec_enq_with_drop(ctx->dhdp, &entry->psq, p, fifo_id, TRUE,
-			WLFC_SEQCOUNT(entry, fifo_id>>1))
-			== FALSE) {
-			/* enque failed */
-			DHD_ERROR(("Error: %s():%d, fifo_id(%d)\n",
-				__FUNCTION__, __LINE__, fifo_id));
-			rc = BCME_ERROR;
-		}
-	} else {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		rc = BCME_ERROR;
-	}
-
-exit:
-	if (rc != BCME_OK) {
-		ctx->stats.rollback_failed++;
-		_dhd_wlfc_prec_drop(ctx->dhdp, fifo_id, p, FALSE);
-	} else {
-		ctx->stats.rollback++;
-	}
-
-	return rc;
-} /* _dhd_wlfc_rollback_packet_toq */
-
-/** Returns TRUE if host OS -> DHD flow control is allowed on the caller supplied interface */
-static bool
-_dhd_wlfc_allow_fc(athost_wl_status_info_t* ctx, uint8 ifid)
-{
-	int prec, ac_traffic = WLFC_NO_TRAFFIC;
-
-	for (prec = 0; prec < AC_COUNT; prec++) {
-		if (ctx->pkt_cnt_in_drv[ifid][prec] > 0) {
-			if (ac_traffic == WLFC_NO_TRAFFIC)
-				ac_traffic = prec + 1;
-			else if (ac_traffic != (prec + 1))
-				ac_traffic = WLFC_MULTI_TRAFFIC;
-		}
-	}
-
-	if (ac_traffic >= 1 && ac_traffic <= AC_COUNT) {
-		/* single AC (BE/BK/VI/VO) in queue */
-		if (ctx->allow_fc) {
-			return TRUE;
-		} else {
-			uint32 delta;
-			uint32 curr_t = OSL_SYSUPTIME();
-
-			if (ctx->fc_defer_timestamp == 0) {
-				/* first single ac scenario */
-				ctx->fc_defer_timestamp = curr_t;
-				return FALSE;
-			}
-
-			/* single AC duration, this handles wrap around, e.g. 1 - ~0 = 2. */
-			delta = curr_t - ctx->fc_defer_timestamp;
-			if (delta >= WLFC_FC_DEFER_PERIOD_MS) {
-				ctx->allow_fc = TRUE;
-			}
-		}
-	} else {
-		/* multiple ACs or BCMC in queue */
-		ctx->allow_fc = FALSE;
-		ctx->fc_defer_timestamp = 0;
-	}
-
-	return ctx->allow_fc;
-} /* _dhd_wlfc_allow_fc */
-
-/**
- * Starts or stops the flow of transmit packets from the host OS towards the DHD, depending on
- * low/high watermarks.
- */
-static void
-_dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint8 if_id)
-{
-	dhd_pub_t *dhdp;
-
-	ASSERT(ctx);
-
-	dhdp = (dhd_pub_t *)ctx->dhdp;
-	ASSERT(dhdp);
-
-	if (dhdp->skip_fc && dhdp->skip_fc())
-		return;
-
-	if ((ctx->hostif_flow_state[if_id] == OFF) && !_dhd_wlfc_allow_fc(ctx, if_id))
-		return;
-
-	if ((pq->len <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) {
-		/* start traffic */
-		ctx->hostif_flow_state[if_id] = OFF;
-		/*
-		WLFC_DBGMESG(("qlen:%02d, if:%02d, ->OFF, start traffic %s()\n",
-		pq->len, if_id, __FUNCTION__));
-		*/
-		WLFC_DBGMESG(("F"));
-
-		dhd_txflowcontrol(dhdp, if_id, OFF);
-
-		ctx->toggle_host_if = 0;
-	}
-
-	if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) {
-		/* stop traffic */
-		ctx->hostif_flow_state[if_id] = ON;
-		/*
-		WLFC_DBGMESG(("qlen:%02d, if:%02d, ->ON, stop traffic   %s()\n",
-		pq->len, if_id, __FUNCTION__));
-		*/
-		WLFC_DBGMESG(("N"));
-
-		dhd_txflowcontrol(dhdp, if_id, ON);
-
-		ctx->host_ifidx = if_id;
-		ctx->toggle_host_if = 1;
-	}
-
-	return;
-} /* _dhd_wlfc_flow_control_check */
-
-static int
-_dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry,
-	uint8 ta_bmp)
-{
-	int rc = BCME_OK;
-	void* p = NULL;
-	int dummylen = ((dhd_pub_t *)ctx->dhdp)->hdrlen+ 16;
-	dhd_pub_t *dhdp = (dhd_pub_t *)ctx->dhdp;
-
-	if (dhdp->proptxstatus_txoff) {
-		rc = BCME_NORESOURCE;
-		return rc;
-	}
-
-	/* allocate a dummy packet */
-	p = PKTGET(ctx->osh, dummylen, TRUE);
-	if (p) {
-		PKTPULL(ctx->osh, p, dummylen);
-		DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), 0);
-		_dhd_wlfc_pushheader(ctx, &p, TRUE, ta_bmp, entry->mac_handle, 0, 0, FALSE);
-		DHD_PKTTAG_SETSIGNALONLY(PKTTAG(p), 1);
-		DHD_PKTTAG_WLFCPKT_SET(PKTTAG(p), 1);
-#ifdef PROP_TXSTATUS_DEBUG
-		ctx->stats.signal_only_pkts_sent++;
-#endif
-
-#if defined(BCMPCIE)
-		rc = dhd_bus_txdata(dhdp->bus, p, ctx->host_ifidx);
-#else
-		rc = dhd_bus_txdata(dhdp->bus, p);
-#endif
-		if (rc != BCME_OK) {
-			_dhd_wlfc_pullheader(ctx, p);
-			PKTFREE(ctx->osh, p, TRUE);
-		}
-	} else {
-		DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n",
-		           __FUNCTION__, dummylen));
-		rc = BCME_NOMEM;
-		dhdp->tx_pktgetfail++;
-	}
-
-	return rc;
-} /* _dhd_wlfc_send_signalonly_packet */
-
-/**
- * Called on eg receiving 'mac close' indication from dongle. Updates the per-MAC administration
- * maintained in caller supplied parameter 'entry'.
- *
- *    @param[in/out] entry  administration about a remote MAC entity
- *    @param[in]     prec   precedence queue for this remote MAC entitity
- *
- * Return value: TRUE if traffic availability changed
- */
-static bool
-_dhd_wlfc_traffic_pending_check(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry,
-	int prec)
-{
-	bool rc = FALSE;
-
-	if (entry->state == WLFC_STATE_CLOSE) {
-		if ((pktq_plen(&entry->psq, (prec << 1)) == 0) &&
-			(pktq_plen(&entry->psq, ((prec << 1) + 1)) == 0)) {
-			/* no packets in both 'normal' and 'suspended' queues */
-			if (entry->traffic_pending_bmp & NBITVAL(prec)) {
-				rc = TRUE;
-				entry->traffic_pending_bmp =
-					entry->traffic_pending_bmp & ~ NBITVAL(prec);
-			}
-		} else {
-			/* packets are queued in host for transmission to dongle */
-			if (!(entry->traffic_pending_bmp & NBITVAL(prec))) {
-				rc = TRUE;
-				entry->traffic_pending_bmp =
-					entry->traffic_pending_bmp | NBITVAL(prec);
-			}
-		}
-	}
-
-	if (rc) {
-		/* request a TIM update to firmware at the next piggyback opportunity */
-		if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) {
-			entry->send_tim_signal = 1;
-			_dhd_wlfc_send_signalonly_packet(ctx, entry, entry->traffic_pending_bmp);
-			entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
-			entry->send_tim_signal = 0;
-		} else {
-			rc = FALSE;
-		}
-	}
-
-	return rc;
-} /* _dhd_wlfc_traffic_pending_check */
-
-/**
- * Called on receiving a 'd11 suppressed' or 'wl suppressed' tx status from the firmware. Enqueues
- * the packet to transmit to firmware again at a later opportunity.
- */
-static int
-_dhd_wlfc_enque_suppressed(athost_wl_status_info_t* ctx, int prec, void* p)
-{
-	wlfc_mac_descriptor_t* entry;
-
-	entry = _dhd_wlfc_find_table_entry(ctx, p);
-	if (entry == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_NOTFOUND;
-	}
-	/*
-	- suppressed packets go to sub_queue[2*prec + 1] AND
-	- delayed packets go to sub_queue[2*prec + 0] to ensure
-	order of delivery.
-	*/
-	if (_dhd_wlfc_prec_enq_with_drop(ctx->dhdp, &entry->psq, p, ((prec << 1) + 1), FALSE,
-		WLFC_SEQCOUNT(entry, prec))
-		== FALSE) {
-		ctx->stats.delayq_full_error++;
-		/* WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); */
-		WLFC_DBGMESG(("s"));
-		return BCME_ERROR;
-	}
-
-	/* A packet has been pushed, update traffic availability bitmap, if applicable */
-	_dhd_wlfc_traffic_pending_check(ctx, entry, prec);
-	_dhd_wlfc_flow_control_check(ctx, &entry->psq, DHD_PKTTAG_IF(PKTTAG(p)));
-	return BCME_OK;
-}
-
-/**
- * Called when a transmit packet is about to be 'committed' from the OS layer to a lower layer
- * towards the dongle (eg the DBUS layer). Updates wlfc administration. May modify packet.
- *
- *     @param[in/out] ctx    driver specific flow control administration
- *     @param[in/out] entry  The remote MAC entity for which the packet is destined.
- *     @param[in/out] packet Packet to send. This function optionally adds TLVs to the packet.
- *     @param[in] header_needed True if packet is 'new' to flow control
- *     @param[out] slot Handle to container in which the packet was 'parked'
- */
-static int
-_dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx,
-	wlfc_mac_descriptor_t* entry, void** packet, int header_needed, uint32* slot)
-{
-	int rc = BCME_OK;
-	int hslot = WLFC_HANGER_MAXITEMS;
-	bool send_tim_update = FALSE;
-	uint32 htod = 0;
-	uint16 htodseq = 0;
-	uint8 free_ctr;
-	int gen = 0xff;
-	dhd_pub_t *dhdp = (dhd_pub_t *)ctx->dhdp;
-	void * p = *packet;
-
-	*slot = hslot;
-
-	if (entry == NULL) {
-		entry = _dhd_wlfc_find_table_entry(ctx, p);
-	}
-
-	if (entry == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_ERROR;
-	}
-
-	if (entry->send_tim_signal) {
-		/* sends a traffic indication bitmap to the dongle */
-		send_tim_update = TRUE;
-		entry->send_tim_signal = 0;
-		entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
-	}
-
-	if (header_needed) {
-		if (WLFC_GET_AFQ(dhdp->wlfc_mode)) {
-			hslot = (uint)(entry - &ctx->destination_entries.nodes[0]);
-		} else {
-			hslot = _dhd_wlfc_hanger_get_free_slot(ctx->hanger);
-		}
-		gen = entry->generation;
-		free_ctr = WLFC_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p)));
-	} else {
-		if (WLFC_GET_REUSESEQ(dhdp->wlfc_mode)) {
-			htodseq = DHD_PKTTAG_H2DSEQ(PKTTAG(p));
-		}
-
-		hslot = WL_TXSTATUS_GET_HSLOT(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
-
-		if (WLFC_GET_REORDERSUPP(dhdp->wlfc_mode)) {
-			gen = entry->generation;
-		} else if (WLFC_GET_AFQ(dhdp->wlfc_mode)) {
-			gen = WL_TXSTATUS_GET_GENERATION(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
-		} else {
-			_dhd_wlfc_hanger_get_genbit(ctx->hanger, p, hslot, &gen);
-		}
-
-		free_ctr = WL_TXSTATUS_GET_FREERUNCTR(DHD_PKTTAG_H2DTAG(PKTTAG(p)));
-		/* remove old header */
-		_dhd_wlfc_pullheader(ctx, p);
-	}
-
-	if (hslot >= WLFC_HANGER_MAXITEMS) {
-		DHD_ERROR(("Error: %s():no hanger slot available\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	WL_TXSTATUS_SET_FREERUNCTR(htod, free_ctr);
-	WL_TXSTATUS_SET_HSLOT(htod, hslot);
-	WL_TXSTATUS_SET_FIFO(htod, DHD_PKTTAG_FIFO(PKTTAG(p)));
-	WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST);
-	WL_TXSTATUS_SET_GENERATION(htod, gen);
-	DHD_PKTTAG_SETPKTDIR(PKTTAG(p), 1);
-
-	if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) {
-		/*
-		Indicate that this packet is being sent in response to an
-		explicit request from the firmware side.
-		*/
-		WLFC_PKTFLAG_SET_PKTREQUESTED(htod);
-	} else {
-		WLFC_PKTFLAG_CLR_PKTREQUESTED(htod);
-	}
-
-	rc = _dhd_wlfc_pushheader(ctx, &p, send_tim_update,
-		entry->traffic_lastreported_bmp, entry->mac_handle, htod, htodseq, FALSE);
-	if (rc == BCME_OK) {
-		DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod);
-
-		if (!WLFC_GET_AFQ(dhdp->wlfc_mode)) {
-			wlfc_hanger_t *h = (wlfc_hanger_t*)(ctx->hanger);
-			if (header_needed) {
-				/*
-				a new header was created for this packet.
-				push to hanger slot and scrub q. Since bus
-				send succeeded, increment seq number as well.
-				*/
-				rc = _dhd_wlfc_hanger_pushpkt(ctx->hanger, p, hslot);
-				if (rc == BCME_OK) {
-#ifdef PROP_TXSTATUS_DEBUG
-					h->items[hslot].push_time =
-						OSL_SYSUPTIME();
-#endif
-				} else {
-					DHD_ERROR(("%s() hanger_pushpkt() failed, rc: %d\n",
-						__FUNCTION__, rc));
-				}
-			} else {
-				/* clear hanger state */
-				if (((wlfc_hanger_t*)(ctx->hanger))->items[hslot].pkt != p)
-					DHD_ERROR(("%s() pkt not match: cur %p, hanger pkt %p\n",
-						__FUNCTION__, p, h->items[hslot].pkt));
-				ASSERT(h->items[hslot].pkt == p);
-				bcm_object_feature_set(h->items[hslot].pkt,
-					BCM_OBJECT_FEATURE_PKT_STATE, 0);
-				h->items[hslot].pkt_state = 0;
-				h->items[hslot].pkt_txstatus = 0;
-				h->items[hslot].state = WLFC_HANGER_ITEM_STATE_INUSE;
-			}
-		} else if (!WLFC_GET_AFQ(dhdp->wlfc_mode)) {
-			/* clear hanger state */
-			((wlfc_hanger_t*)(ctx->hanger))->items[hslot].pkt_state = 0;
-			((wlfc_hanger_t*)(ctx->hanger))->items[hslot].pkt_txstatus = 0;
-		}
-
-		if ((rc == BCME_OK) && header_needed) {
-			/* increment free running sequence count */
-			WLFC_INCR_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p)));
-		}
-	}
-	*slot = hslot;
-	*packet = p;
-	return rc;
-} /* _dhd_wlfc_pretx_pktprocess */
-
-/**
- * A remote wireless mac may be temporarily 'closed' due to power management. Returns '1' if remote
- * mac is in the 'open' state, otherwise '0'.
- */
-static int
-_dhd_wlfc_is_destination_open(athost_wl_status_info_t* ctx,
-	wlfc_mac_descriptor_t* entry, int prec)
-{
-	if (entry->interface_id >= WLFC_MAX_IFNUM) {
-		ASSERT(&ctx->destination_entries.other == entry);
-		return 1;
-	}
-
-	if (ctx->destination_entries.interfaces[entry->interface_id].iftype ==
-		WLC_E_IF_ROLE_P2P_GO) {
-		/* - destination interface is of type p2p GO.
-		For a p2pGO interface, if the destination is OPEN but the interface is
-		CLOSEd, do not send traffic. But if the dstn is CLOSEd while there is
-		destination-specific-credit left send packets. This is because the
-		firmware storing the destination-specific-requested packet in queue.
-		*/
-		if ((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) &&
-			(entry->requested_packet == 0)) {
-			return 0;
-		}
-	}
-
-	/* AP, p2p_go -> unicast desc entry, STA/p2p_cl -> interface desc. entry */
-	if (((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) &&
-		(entry->requested_packet == 0)) ||
-		(!(entry->ac_bitmap & (1 << prec)))) {
-		return 0;
-	}
-
-	return 1;
-} /* _dhd_wlfc_is_destination_open */
-
-/**
- * Dequeues a suppressed or delayed packet from a queue
- *    @param[in/out] ctx          Driver specific flow control administration
- *    @param[in]  prec            Precedence of queue to dequeue from
- *    @param[out] ac_credit_spent Boolean, returns 0 or 1
- *    @param[out] needs_hdr       Boolean, returns 0 or 1
- *    @param[out] entry_out       The remote MAC for which the packet is destined
- *    @param[in]  only_no_credit  If TRUE, searches all entries instead of just the active ones
- *
- * Return value: the dequeued packet
- */
-static void*
-_dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, int prec,
-	uint8* ac_credit_spent, uint8* needs_hdr, wlfc_mac_descriptor_t** entry_out,
-	bool only_no_credit)
-{
-	wlfc_mac_descriptor_t* entry;
-	int total_entries;
-	void* p = NULL;
-	int i;
-	uint8 credit_spent = ((prec == AC_COUNT) && !ctx->bcmc_credit_supported) ? 0 : 1;
-
-	*entry_out = NULL;
-	/* most cases a packet will count against FIFO credit */
-	*ac_credit_spent = credit_spent;
-
-	/* search all entries, include nodes as well as interfaces */
-	if (only_no_credit) {
-		total_entries = ctx->requested_entry_count;
-	} else {
-		total_entries = ctx->active_entry_count;
-	}
-
-	for (i = 0; i < total_entries; i++) {
-		if (only_no_credit) {
-			entry = ctx->requested_entry[i];
-		} else {
-			entry = ctx->active_entry_head;
-			/* move head to ensure fair round-robin */
-			ctx->active_entry_head = ctx->active_entry_head->next;
-		}
-		ASSERT(entry);
-
-		if (entry->occupied && _dhd_wlfc_is_destination_open(ctx, entry, prec) &&
-			(entry->transit_count < WL_TXSTATUS_FREERUNCTR_MASK) &&
-			(!entry->suppressed)) {
-			*ac_credit_spent = credit_spent;
-			if (entry->state == WLFC_STATE_CLOSE) {
-				*ac_credit_spent = 0;
-			}
-
-			/* higher precedence will be picked up first,
-			 * i.e. suppressed packets before delayed ones
-			 */
-			p = pktq_pdeq(&entry->psq, PSQ_SUP_IDX(prec));
-			*needs_hdr = 0;
-			if (p == NULL) {
-				/* De-Q from delay Q */
-				p = pktq_pdeq(&entry->psq, PSQ_DLY_IDX(prec));
-				*needs_hdr = 1;
-			}
-
-			if (p != NULL) {
-				bcm_pkt_validate_chk(p);
-				/* did the packet come from suppress sub-queue? */
-				if (entry->requested_credit > 0) {
-					entry->requested_credit--;
-#ifdef PROP_TXSTATUS_DEBUG
-					entry->dstncredit_sent_packets++;
-#endif
-				} else if (entry->requested_packet > 0) {
-					entry->requested_packet--;
-					DHD_PKTTAG_SETONETIMEPKTRQST(PKTTAG(p));
-				}
-
-				*entry_out = entry;
-				ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(p))][prec]--;
-				ctx->pkt_cnt_per_ac[prec]--;
-				ctx->pkt_cnt_in_psq--;
-				_dhd_wlfc_flow_control_check(ctx, &entry->psq,
-					DHD_PKTTAG_IF(PKTTAG(p)));
-				/*
-				 * A packet has been picked up, update traffic availability bitmap,
-				 * if applicable.
-				 */
-				_dhd_wlfc_traffic_pending_check(ctx, entry, prec);
-				return p;
-			}
-		}
-	}
-	return NULL;
-} /* _dhd_wlfc_deque_delayedq */
-
-/** Enqueues caller supplied packet on either a 'suppressed' or 'delayed' queue */
-static int
-_dhd_wlfc_enque_delayq(athost_wl_status_info_t* ctx, void* pktbuf, int prec)
-{
-	wlfc_mac_descriptor_t* entry;
-
-	if (pktbuf != NULL) {
-		entry = _dhd_wlfc_find_table_entry(ctx, pktbuf);
-		if (entry == NULL) {
-			DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-			return BCME_ERROR;
-		}
-
-		/*
-		- suppressed packets go to sub_queue[2*prec + 1] AND
-		- delayed packets go to sub_queue[2*prec + 0] to ensure
-		order of delivery.
-		*/
-		if (_dhd_wlfc_prec_enq_with_drop(ctx->dhdp, &entry->psq, pktbuf, (prec << 1),
-			FALSE, WLFC_SEQCOUNT(entry, prec))
-			== FALSE) {
-			WLFC_DBGMESG(("D"));
-			ctx->stats.delayq_full_error++;
-			return BCME_ERROR;
-		}
-
-
-		/* A packet has been pushed, update traffic availability bitmap, if applicable */
-		_dhd_wlfc_traffic_pending_check(ctx, entry, prec);
-	}
-
-	return BCME_OK;
-} /* _dhd_wlfc_enque_delayq */
-
-/** Returns TRUE if caller supplied packet is destined for caller supplied interface */
-static bool _dhd_wlfc_ifpkt_fn(void* p, void *p_ifid)
-{
-	if (!p || !p_ifid)
-		return FALSE;
-
-	return (DHD_PKTTAG_WLFCPKT(PKTTAG(p))&& (*((uint8 *)p_ifid) == DHD_PKTTAG_IF(PKTTAG(p))));
-}
-
-/** Returns TRUE if caller supplied packet is destined for caller supplied remote MAC */
-static bool _dhd_wlfc_entrypkt_fn(void* p, void *entry)
-{
-	if (!p || !entry)
-		return FALSE;
-
-	return (DHD_PKTTAG_WLFCPKT(PKTTAG(p))&& (entry == DHD_PKTTAG_ENTRY(PKTTAG(p))));
-}
-
-static void
-_dhd_wlfc_return_implied_credit(athost_wl_status_info_t* wlfc, void* pkt)
-{
-	dhd_pub_t *dhdp;
-	bool credit_return = FALSE;
-
-	if (!wlfc || !pkt) {
-		return;
-	}
-
-	dhdp = (dhd_pub_t *)(wlfc->dhdp);
-	if (dhdp && (dhdp->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) &&
-		DHD_PKTTAG_CREDITCHECK(PKTTAG(pkt))) {
-		int lender, credit_returned = 0;
-		uint8 fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pkt));
-
-		credit_return = TRUE;
-
-		/* Note that borrower is fifo_id */
-		/* Return credits to highest priority lender first */
-		for (lender = AC_COUNT; lender >= 0; lender--) {
-			if (wlfc->credits_borrowed[fifo_id][lender] > 0) {
-				wlfc->FIFO_credit[lender]++;
-				wlfc->credits_borrowed[fifo_id][lender]--;
-				credit_returned = 1;
-				break;
-			}
-		}
-
-		if (!credit_returned) {
-			wlfc->FIFO_credit[fifo_id]++;
-		}
-	}
-
-	BCM_REFERENCE(credit_return);
-#if defined(DHD_WLFC_THREAD)
-	if (credit_return) {
-		_dhd_wlfc_thread_wakeup(dhdp);
-	}
-#endif /* defined(DHD_WLFC_THREAD) */
-}
-
-/** Removes and frees a packet from the hanger. Called during eg tx complete. */
-static void
-_dhd_wlfc_hanger_free_pkt(athost_wl_status_info_t* wlfc, uint32 slot_id, uint8 pkt_state,
-	int pkt_txstatus)
-{
-	wlfc_hanger_t* hanger;
-	wlfc_hanger_item_t* item;
-
-	if (!wlfc)
-		return;
-
-	hanger = (wlfc_hanger_t*)wlfc->hanger;
-	if (!hanger)
-		return;
-
-	if (slot_id == WLFC_HANGER_MAXITEMS)
-		return;
-
-	item = &hanger->items[slot_id];
-
-	if (item->pkt) {
-		item->pkt_state |= pkt_state;
-		if (pkt_txstatus != -1)
-			item->pkt_txstatus = (uint8)pkt_txstatus;
-		bcm_object_feature_set(item->pkt, BCM_OBJECT_FEATURE_PKT_STATE, item->pkt_state);
-		if (item->pkt_state == WLFC_HANGER_PKT_STATE_COMPLETE) {
-			void *p = NULL;
-			void *pkt = item->pkt;
-			uint8 old_state = item->state;
-			int ret = _dhd_wlfc_hanger_poppkt(wlfc->hanger, slot_id, &p, TRUE);
-			BCM_REFERENCE(ret);
-			BCM_REFERENCE(pkt);
-			ASSERT((ret == BCME_OK) && p && (pkt == p));
-			if (old_state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) {
-				printf("ERROR: free a suppressed pkt %p state %d pkt_state %d\n",
-					pkt, old_state, item->pkt_state);
-			}
-			ASSERT(old_state != WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED);
-
-			/* free packet */
-			wlfc->pkt_cnt_in_drv[DHD_PKTTAG_IF(PKTTAG(p))]
-				[DHD_PKTTAG_FIFO(PKTTAG(p))]--;
-			wlfc->stats.pktout++;
-			dhd_txcomplete((dhd_pub_t *)wlfc->dhdp, p, item->pkt_txstatus);
-			PKTFREE(wlfc->osh, p, TRUE);
-		}
-	} else {
-		/* free slot */
-		if (item->state == WLFC_HANGER_ITEM_STATE_FREE)
-			DHD_ERROR(("Error: %s():%d Multiple TXSTATUS or BUSRETURNED: %d (%d)\n",
-			    __FUNCTION__, __LINE__, item->pkt_state, pkt_state));
-		item->state = WLFC_HANGER_ITEM_STATE_FREE;
-	}
-} /* _dhd_wlfc_hanger_free_pkt */
-
-/** Called during eg detach() */
-static void
-_dhd_wlfc_pktq_flush(athost_wl_status_info_t* ctx, struct pktq *pq,
-	bool dir, f_processpkt_t fn, void *arg, q_type_t q_type)
-{
-	int prec;
-	dhd_pub_t *dhdp = (dhd_pub_t *)ctx->dhdp;
-
-	ASSERT(dhdp);
-
-	/* Optimize flush, if pktq len = 0, just return.
-	 * pktq len of 0 means pktq's prec q's are all empty.
-	 */
-	if (pq->len == 0) {
-		return;
-	}
-
-	for (prec = 0; prec < pq->num_prec; prec++) {
-		struct pktq_prec *q;
-		void *p, *prev = NULL;
-
-		q = &pq->q[prec];
-		p = q->head;
-		while (p) {
-			bcm_pkt_validate_chk(p);
-			if (fn == NULL || (*fn)(p, arg)) {
-				bool head = (p == q->head);
-				if (head)
-					q->head = PKTLINK(p);
-				else
-					PKTSETLINK(prev, PKTLINK(p));
-				if (q_type == Q_TYPE_PSQ) {
-					if (!WLFC_GET_AFQ(dhdp->wlfc_mode) && (prec & 1)) {
-						_dhd_wlfc_hanger_remove_reference(ctx->hanger, p);
-					}
-					ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(p))][prec>>1]--;
-					ctx->pkt_cnt_per_ac[prec>>1]--;
-					ctx->pkt_cnt_in_psq--;
-					ctx->stats.cleanup_psq_cnt++;
-					if (!(prec & 1)) {
-						/* pkt in delayed q, so fake push BDC header for
-						 * dhd_tcpack_check_xmit() and dhd_txcomplete().
-						 */
-						_dhd_wlfc_pushheader(ctx, &p, FALSE, 0, 0,
-							0, 0, TRUE);
-#ifdef DHDTCPACK_SUPPRESS
-						if (dhd_tcpack_check_xmit(dhdp, p) == BCME_ERROR) {
-							DHD_ERROR(("%s %d: tcpack_suppress ERROR!!!"
-								" Stop using it\n",
-								__FUNCTION__, __LINE__));
-							dhd_tcpack_suppress_set(dhdp,
-								TCPACK_SUP_OFF);
-						}
-#endif /* DHDTCPACK_SUPPRESS */
-					}
-				} else if (q_type == Q_TYPE_AFQ) {
-					wlfc_mac_descriptor_t* entry =
-						_dhd_wlfc_find_table_entry(ctx, p);
-					if (entry->transit_count)
-						entry->transit_count--;
-					if (entry->suppr_transit_count) {
-						entry->suppr_transit_count--;
-						if (entry->suppressed &&
-							(!entry->onbus_pkts_count) &&
-							(!entry->suppr_transit_count))
-							entry->suppressed = FALSE;
-					}
-					_dhd_wlfc_return_implied_credit(ctx, p);
-					ctx->stats.cleanup_fw_cnt++;
-				}
-				PKTSETLINK(p, NULL);
-				if (dir) {
-					ctx->pkt_cnt_in_drv[DHD_PKTTAG_IF(PKTTAG(p))][prec>>1]--;
-					ctx->stats.pktout++;
-					dhd_txcomplete(dhdp, p, FALSE);
-				}
-				PKTFREE(ctx->osh, p, dir);
-
-				q->len--;
-				pq->len--;
-				p = (head ? q->head : PKTLINK(prev));
-			} else {
-				prev = p;
-				p = PKTLINK(p);
-			}
-		}
-
-		if (q->head == NULL) {
-			ASSERT(q->len == 0);
-			q->tail = NULL;
-		}
-
-	}
-
-	if (fn == NULL)
-		ASSERT(pq->len == 0);
-} /* _dhd_wlfc_pktq_flush */
-
-
-/** !BCMDBUS specific function. Dequeues a packet from the caller supplied queue. */
-static void*
-_dhd_wlfc_pktq_pdeq_with_fn(struct pktq *pq, int prec, f_processpkt_t fn, void *arg)
-{
-	struct pktq_prec *q;
-	void *p, *prev = NULL;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	q = &pq->q[prec];
-	p = q->head;
-
-	while (p) {
-		if (fn == NULL || (*fn)(p, arg)) {
-			break;
-		} else {
-			prev = p;
-			p = PKTLINK(p);
-		}
-	}
-	if (p == NULL)
-		return NULL;
-
-	bcm_pkt_validate_chk(p);
-
-	if (prev == NULL) {
-		if ((q->head = PKTLINK(p)) == NULL) {
-			q->tail = NULL;
-		}
-	} else {
-		PKTSETLINK(prev, PKTLINK(p));
-		if (q->tail == p) {
-			q->tail = prev;
-		}
-	}
-
-	q->len--;
-
-	pq->len--;
-
-	PKTSETLINK(p, NULL);
-
-	return p;
-}
-
-/** !BCMDBUS specific function */
-static void
-_dhd_wlfc_cleanup_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
-{
-	int prec;
-	void *pkt = NULL, *head = NULL, *tail = NULL;
-	struct pktq *txq = (struct pktq *)dhd_bus_txq(dhd->bus);
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger;
-	wlfc_mac_descriptor_t* entry;
-
-	dhd_os_sdlock_txq(dhd);
-	for (prec = 0; prec < txq->num_prec; prec++) {
-		while ((pkt = _dhd_wlfc_pktq_pdeq_with_fn(txq, prec, fn, arg))) {
-#ifdef DHDTCPACK_SUPPRESS
-			if (dhd_tcpack_check_xmit(dhd, pkt) == BCME_ERROR) {
-				DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
-					__FUNCTION__, __LINE__));
-				dhd_tcpack_suppress_set(dhd, TCPACK_SUP_OFF);
-			}
-#endif /* DHDTCPACK_SUPPRESS */
-			if (!head) {
-				head = pkt;
-			}
-			if (tail) {
-				PKTSETLINK(tail, pkt);
-			}
-			tail = pkt;
-		}
-	}
-	dhd_os_sdunlock_txq(dhd);
-
-
-	while ((pkt = head)) {
-		head = PKTLINK(pkt);
-		PKTSETLINK(pkt, NULL);
-		entry = _dhd_wlfc_find_table_entry(wlfc, pkt);
-
-		if (!WLFC_GET_AFQ(dhd->wlfc_mode) &&
-			!_dhd_wlfc_hanger_remove_reference(h, pkt)) {
-			DHD_ERROR(("%s: can't find pkt(%p) in hanger, free it anyway\n",
-				__FUNCTION__, pkt));
-		}
-		if (entry->transit_count)
-			entry->transit_count--;
-		if (entry->suppr_transit_count) {
-			entry->suppr_transit_count--;
-			if (entry->suppressed &&
-				(!entry->onbus_pkts_count) &&
-				(!entry->suppr_transit_count))
-				entry->suppressed = FALSE;
-		}
-		_dhd_wlfc_return_implied_credit(wlfc, pkt);
-		wlfc->pkt_cnt_in_drv[DHD_PKTTAG_IF(PKTTAG(pkt))][DHD_PKTTAG_FIFO(PKTTAG(pkt))]--;
-		wlfc->stats.pktout++;
-		wlfc->stats.cleanup_txq_cnt++;
-		dhd_txcomplete(dhd, pkt, FALSE);
-		PKTFREE(wlfc->osh, pkt, TRUE);
-	}
-} /* _dhd_wlfc_cleanup_txq */
-
-/** called during eg detach */
-void
-_dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
-{
-	int i;
-	int total_entries;
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	wlfc_mac_descriptor_t* table;
-	wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger;
-
-	wlfc->stats.cleanup_txq_cnt = 0;
-	wlfc->stats.cleanup_psq_cnt = 0;
-	wlfc->stats.cleanup_fw_cnt = 0;
-
-	/*
-	*  flush sequence should be txq -> psq -> hanger/afq, hanger has to be last one
-	*/
-	/* flush bus->txq */
-	_dhd_wlfc_cleanup_txq(dhd, fn, arg);
-
-	/* flush psq, search all entries, include nodes as well as interfaces */
-	total_entries = sizeof(wlfc->destination_entries)/sizeof(wlfc_mac_descriptor_t);
-	table = (wlfc_mac_descriptor_t*)&wlfc->destination_entries;
-
-	for (i = 0; i < total_entries; i++) {
-		if (table[i].occupied) {
-			/* release packets held in PSQ (both delayed and suppressed) */
-			if (table[i].psq.len) {
-				WLFC_DBGMESG(("%s(): PSQ[%d].len = %d\n",
-					__FUNCTION__, i, table[i].psq.len));
-				_dhd_wlfc_pktq_flush(wlfc, &table[i].psq, TRUE,
-					fn, arg, Q_TYPE_PSQ);
-			}
-
-			/* free packets held in AFQ */
-			if (WLFC_GET_AFQ(dhd->wlfc_mode) && (table[i].afq.len)) {
-				_dhd_wlfc_pktq_flush(wlfc, &table[i].afq, TRUE,
-					fn, arg, Q_TYPE_AFQ);
-			}
-
-			if ((fn == NULL) && (&table[i] != &wlfc->destination_entries.other)) {
-				table[i].occupied = 0;
-				if (table[i].transit_count || table[i].suppr_transit_count) {
-					DHD_ERROR(("%s: table[%d] transit(%d), suppr_tansit(%d)\n",
-						__FUNCTION__, i,
-						table[i].transit_count,
-						table[i].suppr_transit_count));
-				}
-			}
-		}
-	}
-
-	/*
-		. flush remained pkt in hanger queue, not in bus->txq nor psq.
-		. the remained pkt was successfully downloaded to dongle already.
-		. hanger slot state cannot be set to free until receive txstatus update.
-	*/
-	if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
-		for (i = 0; i < h->max_items; i++) {
-			if ((h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) ||
-				(h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED)) {
-				if (fn == NULL || (*fn)(h->items[i].pkt, arg)) {
-					h->items[i].state = WLFC_HANGER_ITEM_STATE_FLUSHED;
-				}
-			}
-		}
-	}
-
-	return;
-} /* _dhd_wlfc_cleanup */
-
-/** Called after eg the dongle signalled a new remote MAC that it connected with to the DHD */
-static int
-_dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry,
-	uint8 action, uint8 ifid, uint8 iftype, uint8* ea,
-	f_processpkt_t fn, void *arg)
-{
-	int rc = BCME_OK;
-
-
-	if ((action == eWLFC_MAC_ENTRY_ACTION_ADD) || (action == eWLFC_MAC_ENTRY_ACTION_UPDATE)) {
-		entry->occupied = 1;
-		entry->state = WLFC_STATE_OPEN;
-		entry->requested_credit = 0;
-		entry->interface_id = ifid;
-		entry->iftype = iftype;
-		entry->ac_bitmap = 0xff; /* update this when handling APSD */
-
-		/* for an interface entry we may not care about the MAC address */
-		if (ea != NULL)
-			memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN);
-
-		if (action == eWLFC_MAC_ENTRY_ACTION_ADD) {
-			entry->suppressed = FALSE;
-			entry->transit_count = 0;
-			entry->suppr_transit_count = 0;
-			entry->onbus_pkts_count = 0;
-		}
-
-		if (action == eWLFC_MAC_ENTRY_ACTION_ADD) {
-			dhd_pub_t *dhdp = (dhd_pub_t *)(ctx->dhdp);
-
-			pktq_init(&entry->psq, WLFC_PSQ_PREC_COUNT, WLFC_PSQ_LEN);
-
-			if (WLFC_GET_AFQ(dhdp->wlfc_mode)) {
-				pktq_init(&entry->afq, WLFC_AFQ_PREC_COUNT, WLFC_PSQ_LEN);
-			}
-
-			if (entry->next == NULL) {
-				/* not linked to anywhere, add to tail */
-				if (ctx->active_entry_head) {
-					entry->prev = ctx->active_entry_head->prev;
-					ctx->active_entry_head->prev->next = entry;
-					ctx->active_entry_head->prev = entry;
-					entry->next = ctx->active_entry_head;
-				} else {
-					ASSERT(ctx->active_entry_count == 0);
-					entry->prev = entry->next = entry;
-					ctx->active_entry_head = entry;
-				}
-				ctx->active_entry_count++;
-			} else {
-				DHD_ERROR(("%s():%d, entry(%d)\n", __FUNCTION__, __LINE__,
-					(int)(entry - &ctx->destination_entries.nodes[0])));
-			}
-		}
-	} else if (action == eWLFC_MAC_ENTRY_ACTION_DEL) {
-		/* When the entry is deleted, the packets that are queued in the entry must be
-		   cleanup. The cleanup action should be before the occupied is set as 0.
-		*/
-		_dhd_wlfc_cleanup(ctx->dhdp, fn, arg);
-		_dhd_wlfc_flow_control_check(ctx, &entry->psq, ifid);
-
-		entry->occupied = 0;
-		entry->state = WLFC_STATE_CLOSE;
-		memset(&entry->ea[0], 0, ETHER_ADDR_LEN);
-
-		if (entry->next) {
-			/* not floating, remove from Q */
-			if (ctx->active_entry_count <= 1) {
-				/* last item */
-				ctx->active_entry_head = NULL;
-				ctx->active_entry_count = 0;
-			} else {
-				entry->prev->next = entry->next;
-				entry->next->prev = entry->prev;
-				if (entry == ctx->active_entry_head) {
-					ctx->active_entry_head = entry->next;
-				}
-				ctx->active_entry_count--;
-			}
-			entry->next = entry->prev = NULL;
-		} else {
-			DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		}
-	}
-	return rc;
-} /* _dhd_wlfc_mac_entry_update */
-
-
-#ifdef LIMIT_BORROW
-
-/** LIMIT_BORROW specific function */
-static int
-_dhd_wlfc_borrow_credit(athost_wl_status_info_t* ctx, int highest_lender_ac, int borrower_ac,
-	bool bBorrowAll)
-{
-	int lender_ac, borrow_limit = 0;
-	int rc = -1;
-
-	if (ctx == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return -1;
-	}
-
-	/* Borrow from lowest priority available AC (including BC/MC credits) */
-	for (lender_ac = 0; lender_ac <= highest_lender_ac; lender_ac++) {
-		if (!bBorrowAll) {
-			borrow_limit = ctx->Init_FIFO_credit[lender_ac]/WLFC_BORROW_LIMIT_RATIO;
-		} else {
-			borrow_limit = 0;
-		}
-
-		if (ctx->FIFO_credit[lender_ac] > borrow_limit) {
-			ctx->credits_borrowed[borrower_ac][lender_ac]++;
-			ctx->FIFO_credit[lender_ac]--;
-			rc = lender_ac;
-			break;
-		}
-	}
-
-	return rc;
-}
-
-/** LIMIT_BORROW specific function */
-static int _dhd_wlfc_return_credit(athost_wl_status_info_t* ctx, int lender_ac, int borrower_ac)
-{
-	if ((ctx == NULL) || (lender_ac < 0) || (lender_ac > AC_COUNT) ||
-		(borrower_ac < 0) || (borrower_ac > AC_COUNT)) {
-		DHD_ERROR(("Error: %s():%d, ctx(%p), lender_ac(%d), borrower_ac(%d)\n",
-			__FUNCTION__, __LINE__, ctx, lender_ac, borrower_ac));
-
-		return BCME_BADARG;
-	}
-
-	ctx->credits_borrowed[borrower_ac][lender_ac]--;
-	ctx->FIFO_credit[lender_ac]++;
-
-	return BCME_OK;
-}
-
-#endif /* LIMIT_BORROW */
-
-/**
- * Called on an interface event (WLC_E_IF) indicated by firmware.
- *     @param action : eg eWLFC_MAC_ENTRY_ACTION_UPDATE or eWLFC_MAC_ENTRY_ACTION_ADD
- */
-static int
-_dhd_wlfc_interface_entry_update(void* state,
-	uint8 action, uint8 ifid, uint8 iftype, uint8* ea)
-{
-	athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state;
-	wlfc_mac_descriptor_t* entry;
-
-	if (ifid >= WLFC_MAX_IFNUM)
-		return BCME_BADARG;
-
-	entry = &ctx->destination_entries.interfaces[ifid];
-
-	return _dhd_wlfc_mac_entry_update(ctx, entry, action, ifid, iftype, ea,
-		_dhd_wlfc_ifpkt_fn, &ifid);
-}
-
-/**
- * Called eg on receiving a WLC_E_BCMC_CREDIT_SUPPORT event from the dongle (broadcast/multicast
- * specific)
- */
-static int
-_dhd_wlfc_BCMCCredit_support_update(void* state)
-{
-	athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state;
-
-	ctx->bcmc_credit_supported = TRUE;
-	return BCME_OK;
-}
-
-/** Called eg on receiving a WLC_E_FIFO_CREDIT_MAP event from the dongle */
-static int
-_dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits)
-{
-	athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state;
-	int i;
-
-	for (i = 0; i <= 4; i++) {
-		if (ctx->Init_FIFO_credit[i] != ctx->FIFO_credit[i]) {
-			DHD_ERROR(("%s: credit[i] is not returned, (%d %d)\n",
-				__FUNCTION__, ctx->Init_FIFO_credit[i], ctx->FIFO_credit[i]));
-		}
-	}
-
-	/* update the AC FIFO credit map */
-	ctx->FIFO_credit[0] += (credits[0] - ctx->Init_FIFO_credit[0]);
-	ctx->FIFO_credit[1] += (credits[1] - ctx->Init_FIFO_credit[1]);
-	ctx->FIFO_credit[2] += (credits[2] - ctx->Init_FIFO_credit[2]);
-	ctx->FIFO_credit[3] += (credits[3] - ctx->Init_FIFO_credit[3]);
-	ctx->FIFO_credit[4] += (credits[4] - ctx->Init_FIFO_credit[4]);
-
-	ctx->Init_FIFO_credit[0] = credits[0];
-	ctx->Init_FIFO_credit[1] = credits[1];
-	ctx->Init_FIFO_credit[2] = credits[2];
-	ctx->Init_FIFO_credit[3] = credits[3];
-	ctx->Init_FIFO_credit[4] = credits[4];
-
-	/* credit for ATIM FIFO is not used yet. */
-	ctx->Init_FIFO_credit[5] = ctx->FIFO_credit[5] = 0;
-
-	return BCME_OK;
-}
-
-/**
- * Called during committing of a transmit packet from the OS DHD layer to the next layer towards
- * the dongle (eg the DBUS layer). All transmit packets flow via this function to the next layer.
- *
- *     @param[in/out] ctx      Driver specific flow control administration
- *     @param[in] ac           Access Category (QoS) of called supplied packet
- *     @param[in] commit_info  Contains eg the packet to send
- *     @param[in] fcommit      Function pointer to transmit function of next software layer
- *     @param[in] commit_ctx   Opaque context used when calling next layer
- */
-static int
-_dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac,
-    dhd_wlfc_commit_info_t *commit_info, f_commitpkt_t fcommit, void* commit_ctx)
-{
-	uint32 hslot;
-	int	rc;
-	dhd_pub_t *dhdp = (dhd_pub_t *)(ctx->dhdp);
-
-	/*
-		if ac_fifo_credit_spent = 0
-
-		This packet will not count against the FIFO credit.
-		To ensure the txstatus corresponding to this packet
-		does not provide an implied credit (default behavior)
-		mark the packet accordingly.
-
-		if ac_fifo_credit_spent = 1
-
-		This is a normal packet and it counts against the FIFO
-		credit count.
-	*/
-	DHD_PKTTAG_SETCREDITCHECK(PKTTAG(commit_info->p), commit_info->ac_fifo_credit_spent);
-	rc = _dhd_wlfc_pretx_pktprocess(ctx, commit_info->mac_entry, &commit_info->p,
-	     commit_info->needs_hdr, &hslot);
-
-	if (rc == BCME_OK) {
-		rc = fcommit(commit_ctx, commit_info->p);
-		if (rc == BCME_OK) {
-			uint8 gen = WL_TXSTATUS_GET_GENERATION(
-				DHD_PKTTAG_H2DTAG(PKTTAG(commit_info->p)));
-			ctx->stats.pkt2bus++;
-			if (commit_info->ac_fifo_credit_spent || (ac == AC_COUNT)) {
-				ctx->stats.send_pkts[ac]++;
-				WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac);
-			}
-
-			if (gen != commit_info->mac_entry->generation) {
-				/* will be suppressed back by design */
-				if (!commit_info->mac_entry->suppressed) {
-					commit_info->mac_entry->suppressed = TRUE;
-				}
-				commit_info->mac_entry->suppr_transit_count++;
-			}
-			commit_info->mac_entry->transit_count++;
-			commit_info->mac_entry->onbus_pkts_count++;
-		} else if (commit_info->needs_hdr) {
-			if (!WLFC_GET_AFQ(dhdp->wlfc_mode)) {
-				void *pout = NULL;
-				/* pop hanger for delayed packet */
-				_dhd_wlfc_hanger_poppkt(ctx->hanger, WL_TXSTATUS_GET_HSLOT(
-					DHD_PKTTAG_H2DTAG(PKTTAG(commit_info->p))), &pout, TRUE);
-				ASSERT(commit_info->p == pout);
-			}
-		}
-	} else {
-		ctx->stats.generic_error++;
-	}
-
-	if (rc != BCME_OK) {
-		/*
-		   pretx pkt process or bus commit has failed, rollback.
-		   - remove wl-header for a delayed packet
-		   - save wl-header header for suppressed packets
-		   - reset credit check flag
-		*/
-		_dhd_wlfc_rollback_packet_toq(ctx, commit_info->p, commit_info->pkt_type, hslot);
-		DHD_PKTTAG_SETCREDITCHECK(PKTTAG(commit_info->p), 0);
-	}
-
-	return rc;
-} /* _dhd_wlfc_handle_packet_commit */
-
-/** Returns remote MAC descriptor for caller supplied MAC address */
-static uint8
-_dhd_wlfc_find_mac_desc_id_from_mac(dhd_pub_t *dhdp, uint8 *ea)
-{
-	wlfc_mac_descriptor_t* table =
-		((athost_wl_status_info_t*)dhdp->wlfc_state)->destination_entries.nodes;
-	uint8 table_index;
-
-	if (ea != NULL) {
-		for (table_index = 0; table_index < WLFC_MAC_DESC_TABLE_SIZE; table_index++) {
-			if ((memcmp(ea, &table[table_index].ea[0], ETHER_ADDR_LEN) == 0) &&
-				table[table_index].occupied)
-				return table_index;
-		}
-	}
-	return WLFC_MAC_DESC_ID_INVALID;
-}
-
-/**
- * Called when the host receives a WLFC_CTL_TYPE_TXSTATUS event from the dongle, indicating the
- * status of a frame that the dongle attempted to transmit over the wireless medium.
- */
-static int
-dhd_wlfc_suppressed_acked_update(dhd_pub_t *dhd, uint16 hslot, uint8 prec, uint8 hcnt)
-{
-	athost_wl_status_info_t* ctx;
-	wlfc_mac_descriptor_t* entry = NULL;
-	struct pktq *pq;
-	struct pktq_prec *q;
-	void *p, *b;
-
-	if (!dhd) {
-		DHD_ERROR(("%s: dhd(%p)\n", __FUNCTION__, dhd));
-		return BCME_BADARG;
-	}
-	ctx = (athost_wl_status_info_t*)dhd->wlfc_state;
-	if (!ctx) {
-		DHD_ERROR(("%s: ctx(%p)\n", __FUNCTION__, ctx));
-		return BCME_ERROR;
-	}
-
-	ASSERT(hslot < (WLFC_MAC_DESC_TABLE_SIZE + WLFC_MAX_IFNUM + 1));
-
-	if (hslot < WLFC_MAC_DESC_TABLE_SIZE)
-		entry  = &ctx->destination_entries.nodes[hslot];
-	else if (hslot < (WLFC_MAC_DESC_TABLE_SIZE + WLFC_MAX_IFNUM))
-		entry = &ctx->destination_entries.interfaces[hslot - WLFC_MAC_DESC_TABLE_SIZE];
-	else
-		entry = &ctx->destination_entries.other;
-
-	pq = &entry->psq;
-
-	ASSERT(((prec << 1) + 1) < pq->num_prec);
-
-	q = &pq->q[((prec << 1) + 1)];
-
-	b = NULL;
-	p = q->head;
-
-	while (p && (hcnt != WL_TXSTATUS_GET_FREERUNCTR(DHD_PKTTAG_H2DTAG(PKTTAG(p))))) {
-		b = p;
-		p = PKTLINK(p);
-	}
-
-	if (p == NULL) {
-		/* none is matched */
-		if (b) {
-			DHD_ERROR(("%s: can't find matching seq(%d)\n", __FUNCTION__, hcnt));
-		} else {
-			DHD_ERROR(("%s: queue is empty\n", __FUNCTION__));
-		}
-
-		return BCME_ERROR;
-	}
-
-	if (!b) {
-		/* head packet is matched */
-		if ((q->head = PKTLINK(p)) == NULL) {
-			q->tail = NULL;
-		}
-	} else {
-		/* middle packet is matched */
-		PKTSETLINK(b, PKTLINK(p));
-		if (PKTLINK(p) == NULL) {
-			q->tail = b;
-		}
-	}
-
-	q->len--;
-	pq->len--;
-	ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(p))][prec]--;
-	ctx->pkt_cnt_per_ac[prec]--;
-
-	PKTSETLINK(p, NULL);
-
-	if (WLFC_GET_AFQ(dhd->wlfc_mode)) {
-		_dhd_wlfc_enque_afq(ctx, p);
-	} else {
-		_dhd_wlfc_hanger_pushpkt(ctx->hanger, p, hslot);
-	}
-
-	entry->transit_count++;
-
-	return BCME_OK;
-}
-
-static int
-_dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len, void** p_mac)
-{
-	uint8 status_flag_ori, status_flag;
-	uint32 status;
-	int ret = BCME_OK;
-	int remove_from_hanger_ori, remove_from_hanger = 1;
-	void* pktbuf = NULL;
-	uint8 fifo_id = 0, gen = 0, count = 0, hcnt;
-	uint16 hslot;
-	wlfc_mac_descriptor_t* entry = NULL;
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	uint16 seq = 0, seq_fromfw = 0, seq_num = 0;
-
-	memcpy(&status, pkt_info, sizeof(uint32));
-	status = ltoh32(status);
-	status_flag = WL_TXSTATUS_GET_FLAGS(status);
-	hcnt = WL_TXSTATUS_GET_FREERUNCTR(status);
-	hslot = WL_TXSTATUS_GET_HSLOT(status);
-	fifo_id = WL_TXSTATUS_GET_FIFO(status);
-	gen = WL_TXSTATUS_GET_GENERATION(status);
-
-	if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) {
-		memcpy(&seq, pkt_info + WLFC_CTL_VALUE_LEN_TXSTATUS, WLFC_CTL_VALUE_LEN_SEQ);
-		seq = ltoh16(seq);
-		seq_fromfw = WL_SEQ_GET_FROMFW(seq);
-		seq_num = WL_SEQ_GET_NUM(seq);
-	}
-
-	wlfc->stats.txstatus_in += len;
-
-	if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) {
-		wlfc->stats.pkt_freed += len;
-	} else if (status_flag == WLFC_CTL_PKTFLAG_DISCARD_NOACK) {
-		wlfc->stats.pkt_freed += len;
-	} else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) {
-		wlfc->stats.d11_suppress += len;
-		remove_from_hanger = 0;
-	} else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) {
-		wlfc->stats.wl_suppress += len;
-		remove_from_hanger = 0;
-	} else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) {
-		wlfc->stats.wlc_tossed_pkts += len;
-	}
-
-	else if (status_flag == WLFC_CTL_PKTFLAG_SUPPRESS_ACKED) {
-		wlfc->stats.pkt_freed += len;
-	}
-
-	if (dhd->proptxstatus_txstatus_ignore) {
-		if (!remove_from_hanger) {
-			DHD_ERROR(("suppress txstatus: %d\n", status_flag));
-		}
-		return BCME_OK;
-	}
-
-	status_flag_ori = status_flag;
-	remove_from_hanger_ori = remove_from_hanger;
-
-	while (count < len) {
-		if (status_flag == WLFC_CTL_PKTFLAG_SUPPRESS_ACKED) {
-			dhd_wlfc_suppressed_acked_update(dhd, hslot, fifo_id, hcnt);
-		}
-		if (WLFC_GET_AFQ(dhd->wlfc_mode)) {
-			ret = _dhd_wlfc_deque_afq(wlfc, hslot, hcnt, fifo_id, &pktbuf);
-		} else {
-			status_flag = status_flag_ori;
-			remove_from_hanger = remove_from_hanger_ori;
-			ret = _dhd_wlfc_hanger_poppkt(wlfc->hanger, hslot, &pktbuf, FALSE);
-			if (!pktbuf) {
-				_dhd_wlfc_hanger_free_pkt(wlfc, hslot,
-					WLFC_HANGER_PKT_STATE_TXSTATUS, -1);
-				goto cont;
-			} else {
-				wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger;
-				if (h->items[hslot].state == WLFC_HANGER_ITEM_STATE_FLUSHED) {
-					status_flag = WLFC_CTL_PKTFLAG_DISCARD;
-					remove_from_hanger = 1;
-				}
-			}
-		}
-
-		if ((ret != BCME_OK) || !pktbuf) {
-			goto cont;
-		}
-
-		bcm_pkt_validate_chk(pktbuf);
-
-		/* set fifo_id to correct value because not all FW does that */
-		fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf));
-
-		entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf);
-
-		if (!remove_from_hanger) {
-			/* this packet was suppressed */
-			if (!entry->suppressed || (entry->generation != gen)) {
-				if (!entry->suppressed) {
-					entry->suppr_transit_count = entry->transit_count;
-					if (p_mac) {
-						*p_mac = entry;
-					}
-				} else {
-					DHD_ERROR(("gen(%d), entry->generation(%d)\n",
-						gen, entry->generation));
-				}
-				entry->suppressed = TRUE;
-
-			}
-			entry->generation = gen;
-		}
-
-#ifdef PROP_TXSTATUS_DEBUG
-		if (!WLFC_GET_AFQ(dhd->wlfc_mode))
-		{
-			uint32 new_t = OSL_SYSUPTIME();
-			uint32 old_t;
-			uint32 delta;
-			old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[hslot].push_time;
-
-
-			wlfc->stats.latency_sample_count++;
-			if (new_t > old_t)
-				delta = new_t - old_t;
-			else
-				delta = 0xffffffff + new_t - old_t;
-			wlfc->stats.total_status_latency += delta;
-			wlfc->stats.latency_most_recent = delta;
-
-			wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta;
-			if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32))
-				wlfc->stats.idx_delta = 0;
-		}
-#endif /* PROP_TXSTATUS_DEBUG */
-
-		/* pick up the implicit credit from this packet */
-		if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) {
-			_dhd_wlfc_return_implied_credit(wlfc, pktbuf);
-		} else {
-			/*
-			if this packet did not count against FIFO credit, it must have
-			taken a requested_credit from the destination entry (for pspoll etc.)
-			*/
-			if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) {
-				entry->requested_credit++;
-#if defined(DHD_WLFC_THREAD)
-				_dhd_wlfc_thread_wakeup(dhd);
-#endif /* DHD_WLFC_THREAD */
-			}
-#ifdef PROP_TXSTATUS_DEBUG
-			entry->dstncredit_acks++;
-#endif
-		}
-
-		if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) ||
-			(status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) {
-			/* save generation bit inside packet */
-			WL_TXSTATUS_SET_GENERATION(DHD_PKTTAG_H2DTAG(PKTTAG(pktbuf)), gen);
-
-			if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) {
-				WL_SEQ_SET_FROMDRV(DHD_PKTTAG_H2DSEQ(PKTTAG(pktbuf)), seq_fromfw);
-				WL_SEQ_SET_NUM(DHD_PKTTAG_H2DSEQ(PKTTAG(pktbuf)), seq_num);
-			}
-
-			ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf);
-			if (ret != BCME_OK) {
-				/* delay q is full, drop this packet */
-				DHD_WLFC_QMON_COMPLETE(entry);
-				_dhd_wlfc_prec_drop(dhd, (fifo_id << 1) + 1, pktbuf, FALSE);
-			} else {
-				if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
-					/* Mark suppressed to avoid a double free
-					during wlfc cleanup
-					*/
-					_dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, hslot, gen);
-				}
-			}
-		} else {
-
-			DHD_WLFC_QMON_COMPLETE(entry);
-
-			if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
-				_dhd_wlfc_hanger_free_pkt(wlfc, hslot,
-					WLFC_HANGER_PKT_STATE_TXSTATUS, TRUE);
-			} else {
-				dhd_txcomplete(dhd, pktbuf, TRUE);
-				wlfc->pkt_cnt_in_drv[DHD_PKTTAG_IF(PKTTAG(pktbuf))]
-					[DHD_PKTTAG_FIFO(PKTTAG(pktbuf))]--;
-				wlfc->stats.pktout++;
-				/* free the packet */
-				PKTFREE(wlfc->osh, pktbuf, TRUE);
-			}
-		}
-		/* pkt back from firmware side */
-		if (entry->transit_count)
-			entry->transit_count--;
-		if (entry->suppr_transit_count) {
-			entry->suppr_transit_count--;
-			if (entry->suppressed &&
-				(!entry->onbus_pkts_count) &&
-				(!entry->suppr_transit_count))
-				entry->suppressed = FALSE;
-		}
-
-cont:
-		hcnt = (hcnt + 1) & WL_TXSTATUS_FREERUNCTR_MASK;
-		if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
-			hslot = (hslot + 1) & WL_TXSTATUS_HSLOT_MASK;
-		}
-
-		if (WLFC_GET_REUSESEQ(dhd->wlfc_mode) && seq_fromfw) {
-			seq_num = (seq_num + 1) & WL_SEQ_NUM_MASK;
-		}
-
-		count++;
-	}
-
-	return BCME_OK;
-} /* _dhd_wlfc_compressed_txstatus_update */
-
-/**
- * Called when eg host receives a 'WLFC_CTL_TYPE_FIFO_CREDITBACK' event from the dongle.
- *    @param[in] credits caller supplied credit that will be added to the host credit.
- */
-static int
-_dhd_wlfc_fifocreditback_indicate(dhd_pub_t *dhd, uint8* credits)
-{
-	int i;
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	for (i = 0; i < WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK; i++) {
-#ifdef PROP_TXSTATUS_DEBUG
-		wlfc->stats.fifo_credits_back[i] += credits[i];
-#endif
-
-		/* update FIFO credits */
-		if (dhd->proptxstatus_mode == WLFC_FCMODE_EXPLICIT_CREDIT)
-		{
-			int lender; /* Note that borrower is i */
-
-			/* Return credits to highest priority lender first */
-			for (lender = AC_COUNT; (lender >= 0) && (credits[i] > 0); lender--) {
-				if (wlfc->credits_borrowed[i][lender] > 0) {
-					if (credits[i] >= wlfc->credits_borrowed[i][lender]) {
-						credits[i] -=
-							(uint8)wlfc->credits_borrowed[i][lender];
-						wlfc->FIFO_credit[lender] +=
-						    wlfc->credits_borrowed[i][lender];
-						wlfc->credits_borrowed[i][lender] = 0;
-					} else {
-						wlfc->credits_borrowed[i][lender] -= credits[i];
-						wlfc->FIFO_credit[lender] += credits[i];
-						credits[i] = 0;
-					}
-				}
-			}
-
-			/* If we have more credits left over, these must belong to the AC */
-			if (credits[i] > 0) {
-				wlfc->FIFO_credit[i] += credits[i];
-			}
-
-			if (wlfc->FIFO_credit[i] > wlfc->Init_FIFO_credit[i]) {
-				wlfc->FIFO_credit[i] = wlfc->Init_FIFO_credit[i];
-			}
-		}
-	}
-
-#if defined(DHD_WLFC_THREAD)
-	_dhd_wlfc_thread_wakeup(dhd);
-#endif /* defined(DHD_WLFC_THREAD) */
-
-	return BCME_OK;
-} /* _dhd_wlfc_fifocreditback_indicate */
-
-
-/** !BCMDBUS specific function */
-static void
-_dhd_wlfc_suppress_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
-{
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	wlfc_mac_descriptor_t* entry;
-	int prec;
-	void *pkt = NULL, *head = NULL, *tail = NULL;
-	struct pktq *txq = (struct pktq *)dhd_bus_txq(dhd->bus);
-	uint8	results[WLFC_CTL_VALUE_LEN_TXSTATUS+WLFC_CTL_VALUE_LEN_SEQ];
-	uint8 credits[WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK] = {0};
-	uint32 htod = 0;
-	uint16 htodseq = 0;
-	bool bCreditUpdate = FALSE;
-
-	dhd_os_sdlock_txq(dhd);
-	for (prec = 0; prec < txq->num_prec; prec++) {
-		while ((pkt = _dhd_wlfc_pktq_pdeq_with_fn(txq, prec, fn, arg))) {
-			if (!head) {
-				head = pkt;
-			}
-			if (tail) {
-				PKTSETLINK(tail, pkt);
-			}
-			tail = pkt;
-		}
-	}
-	dhd_os_sdunlock_txq(dhd);
-
-	while ((pkt = head)) {
-		head = PKTLINK(pkt);
-		PKTSETLINK(pkt, NULL);
-
-		entry = _dhd_wlfc_find_table_entry(wlfc, pkt);
-		if (entry) {
-			if (entry->onbus_pkts_count > 0)
-				entry->onbus_pkts_count--;
-			if (entry->suppressed &&
-				(!entry->onbus_pkts_count) &&
-				(!entry->suppr_transit_count))
-				entry->suppressed = FALSE;
-		}
-
-		/* fake a suppression txstatus */
-		htod = DHD_PKTTAG_H2DTAG(PKTTAG(pkt));
-		WL_TXSTATUS_SET_FLAGS(htod, WLFC_CTL_PKTFLAG_WLSUPPRESS);
-		WL_TXSTATUS_SET_GENERATION(htod, entry->generation);
-		htod = htol32(htod);
-		memcpy(results, &htod, WLFC_CTL_VALUE_LEN_TXSTATUS);
-		if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) {
-			htodseq = DHD_PKTTAG_H2DSEQ(PKTTAG(pkt));
-			if (WL_SEQ_GET_FROMDRV(htodseq)) {
-				WL_SEQ_SET_FROMFW(htodseq, 1);
-				WL_SEQ_SET_FROMDRV(htodseq, 0);
-			}
-			htodseq = htol16(htodseq);
-			memcpy(results + WLFC_CTL_VALUE_LEN_TXSTATUS, &htodseq,
-				WLFC_CTL_VALUE_LEN_SEQ);
-		}
-		if (WLFC_GET_AFQ(dhd->wlfc_mode)) {
-			_dhd_wlfc_enque_afq(wlfc, pkt);
-		}
-		_dhd_wlfc_compressed_txstatus_update(dhd, results, 1, NULL);
-
-		/* fake a fifo credit back */
-		if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pkt))) {
-			credits[DHD_PKTTAG_FIFO(PKTTAG(pkt))]++;
-			bCreditUpdate = TRUE;
-		}
-	}
-
-	if (bCreditUpdate) {
-		_dhd_wlfc_fifocreditback_indicate(dhd, credits);
-	}
-} /* _dhd_wlfc_suppress_txq */
-
-static int
-_dhd_wlfc_dbg_senum_check(dhd_pub_t *dhd, uint8 *value)
-{
-	uint32 timestamp;
-
-	(void)dhd;
-
-	bcopy(&value[2], &timestamp, sizeof(uint32));
-	timestamp = ltoh32(timestamp);
-	DHD_INFO(("RXPKT: SEQ: %d, timestamp %d\n", value[1], timestamp));
-	return BCME_OK;
-}
-
-static int
-_dhd_wlfc_rssi_indicate(dhd_pub_t *dhd, uint8* rssi)
-{
-	(void)dhd;
-	(void)rssi;
-	return BCME_OK;
-}
-
-static void
-_dhd_wlfc_add_requested_entry(athost_wl_status_info_t* wlfc, wlfc_mac_descriptor_t* entry)
-{
-	int i;
-
-	if (!wlfc || !entry) {
-		return;
-	}
-
-	for (i = 0; i < wlfc->requested_entry_count; i++) {
-		if (entry == wlfc->requested_entry[i]) {
-			break;
-		}
-	}
-
-	if (i == wlfc->requested_entry_count) {
-		/* no match entry found */
-		ASSERT(wlfc->requested_entry_count <= (WLFC_MAC_DESC_TABLE_SIZE-1));
-		wlfc->requested_entry[wlfc->requested_entry_count++] = entry;
-	}
-}
-
-/** called on eg receiving 'mac open' event from the dongle. */
-static void
-_dhd_wlfc_remove_requested_entry(athost_wl_status_info_t* wlfc, wlfc_mac_descriptor_t* entry)
-{
-	int i;
-
-	if (!wlfc || !entry) {
-		return;
-	}
-
-	for (i = 0; i < wlfc->requested_entry_count; i++) {
-		if (entry == wlfc->requested_entry[i]) {
-			break;
-		}
-	}
-
-	if (i < wlfc->requested_entry_count) {
-		/* found */
-		ASSERT(wlfc->requested_entry_count > 0);
-		wlfc->requested_entry_count--;
-		if (i != wlfc->requested_entry_count) {
-			wlfc->requested_entry[i] =
-				wlfc->requested_entry[wlfc->requested_entry_count];
-		}
-		wlfc->requested_entry[wlfc->requested_entry_count] = NULL;
-	}
-}
-
-/** called on eg receiving a WLFC_CTL_TYPE_MACDESC_ADD TLV from the dongle */
-static int
-_dhd_wlfc_mac_table_update(dhd_pub_t *dhd, uint8* value, uint8 type)
-{
-	int rc;
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	wlfc_mac_descriptor_t* table;
-	uint8 existing_index;
-	uint8 table_index;
-	uint8 ifid;
-	uint8* ea;
-
-	WLFC_DBGMESG(("%s(), mac [%02x:%02x:%02x:%02x:%02x:%02x],%s,idx:%d,id:0x%02x\n",
-		__FUNCTION__, value[2], value[3], value[4], value[5], value[6], value[7],
-		((type == WLFC_CTL_TYPE_MACDESC_ADD) ? "ADD":"DEL"),
-		WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]), value[0]));
-
-	table = wlfc->destination_entries.nodes;
-	table_index = WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]);
-	ifid = value[1];
-	ea = &value[2];
-
-	_dhd_wlfc_remove_requested_entry(wlfc, &table[table_index]);
-	if (type == WLFC_CTL_TYPE_MACDESC_ADD) {
-		existing_index = _dhd_wlfc_find_mac_desc_id_from_mac(dhd, &value[2]);
-		if ((existing_index != WLFC_MAC_DESC_ID_INVALID) &&
-			(existing_index != table_index) && table[existing_index].occupied) {
-			/*
-			there is an existing different entry, free the old one
-			and move it to new index if necessary.
-			*/
-			rc = _dhd_wlfc_mac_entry_update(wlfc, &table[existing_index],
-				eWLFC_MAC_ENTRY_ACTION_DEL, table[existing_index].interface_id,
-				table[existing_index].iftype, NULL, _dhd_wlfc_entrypkt_fn,
-				&table[existing_index]);
-		}
-
-		if (!table[table_index].occupied) {
-			/* this new MAC entry does not exist, create one */
-			table[table_index].mac_handle = value[0];
-			rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index],
-				eWLFC_MAC_ENTRY_ACTION_ADD, ifid,
-				wlfc->destination_entries.interfaces[ifid].iftype,
-				ea, NULL, NULL);
-		} else {
-			/* the space should have been empty, but it's not */
-			wlfc->stats.mac_update_failed++;
-		}
-	}
-
-	if (type == WLFC_CTL_TYPE_MACDESC_DEL) {
-		if (table[table_index].occupied) {
-				rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index],
-					eWLFC_MAC_ENTRY_ACTION_DEL, ifid,
-					wlfc->destination_entries.interfaces[ifid].iftype,
-					ea, _dhd_wlfc_entrypkt_fn, &table[table_index]);
-		} else {
-			/* the space should have been occupied, but it's not */
-			wlfc->stats.mac_update_failed++;
-		}
-	}
-	BCM_REFERENCE(rc);
-	return BCME_OK;
-} /* _dhd_wlfc_mac_table_update */
-
-/** Called on a 'mac open' or 'mac close' event indicated by the dongle */
-static int
-_dhd_wlfc_psmode_update(dhd_pub_t *dhd, uint8* value, uint8 type)
-{
-	/* Handle PS on/off indication */
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	wlfc_mac_descriptor_t* table;
-	wlfc_mac_descriptor_t* desc; /* a table maps from mac handle to mac descriptor */
-	uint8 mac_handle = value[0];
-	int i;
-
-	table = wlfc->destination_entries.nodes;
-	desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)];
-	if (desc->occupied) {
-		if (type == WLFC_CTL_TYPE_MAC_OPEN) {
-			desc->state = WLFC_STATE_OPEN;
-			desc->ac_bitmap = 0xff;
-			DHD_WLFC_CTRINC_MAC_OPEN(desc);
-			desc->requested_credit = 0;
-			desc->requested_packet = 0;
-			_dhd_wlfc_remove_requested_entry(wlfc, desc);
-		} else {
-			desc->state = WLFC_STATE_CLOSE;
-			DHD_WLFC_CTRINC_MAC_CLOSE(desc);
-			/* Indicate to firmware if there is any traffic pending. */
-			for (i = 0; i < AC_COUNT; i++) {
-				_dhd_wlfc_traffic_pending_check(wlfc, desc, i);
-			}
-		}
-	} else {
-		wlfc->stats.psmode_update_failed++;
-	}
-
-	return BCME_OK;
-} /* _dhd_wlfc_psmode_update */
-
-/** called upon receiving 'interface open' or 'interface close' event from the dongle */
-static int
-_dhd_wlfc_interface_update(dhd_pub_t *dhd, uint8* value, uint8 type)
-{
-	/* Handle PS on/off indication */
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	wlfc_mac_descriptor_t* table;
-	uint8 if_id = value[0];
-
-	if (if_id < WLFC_MAX_IFNUM) {
-		table = wlfc->destination_entries.interfaces;
-		if (table[if_id].occupied) {
-			if (type == WLFC_CTL_TYPE_INTERFACE_OPEN) {
-				table[if_id].state = WLFC_STATE_OPEN;
-				/* WLFC_DBGMESG(("INTERFACE[%d] OPEN\n", if_id)); */
-			} else {
-				table[if_id].state = WLFC_STATE_CLOSE;
-				/* WLFC_DBGMESG(("INTERFACE[%d] CLOSE\n", if_id)); */
-			}
-			return BCME_OK;
-		}
-	}
-	wlfc->stats.interface_update_failed++;
-
-	return BCME_OK;
-}
-
-/** Called on receiving a WLFC_CTL_TYPE_MAC_REQUEST_CREDIT TLV from the dongle */
-static int
-_dhd_wlfc_credit_request(dhd_pub_t *dhd, uint8* value)
-{
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	wlfc_mac_descriptor_t* table;
-	wlfc_mac_descriptor_t* desc;
-	uint8 mac_handle;
-	uint8 credit;
-
-	table = wlfc->destination_entries.nodes;
-	mac_handle = value[1];
-	credit = value[0];
-
-	desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)];
-	if (desc->occupied) {
-		desc->requested_credit = credit;
-
-		desc->ac_bitmap = value[2] & (~(1<<AC_COUNT));
-		_dhd_wlfc_add_requested_entry(wlfc, desc);
-#if defined(DHD_WLFC_THREAD)
-		if (credit) {
-			_dhd_wlfc_thread_wakeup(dhd);
-		}
-#endif /* DHD_WLFC_THREAD */
-	} else {
-		wlfc->stats.credit_request_failed++;
-	}
-
-	return BCME_OK;
-}
-
-/** Called on receiving a WLFC_CTL_TYPE_MAC_REQUEST_PACKET TLV from the dongle */
-static int
-_dhd_wlfc_packet_request(dhd_pub_t *dhd, uint8* value)
-{
-	athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	wlfc_mac_descriptor_t* table;
-	wlfc_mac_descriptor_t* desc;
-	uint8 mac_handle;
-	uint8 packet_count;
-
-	table = wlfc->destination_entries.nodes;
-	mac_handle = value[1];
-	packet_count = value[0];
-
-	desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)];
-	if (desc->occupied) {
-		desc->requested_packet = packet_count;
-
-		desc->ac_bitmap = value[2] & (~(1<<AC_COUNT));
-		_dhd_wlfc_add_requested_entry(wlfc, desc);
-#if defined(DHD_WLFC_THREAD)
-		if (packet_count) {
-			_dhd_wlfc_thread_wakeup(dhd);
-		}
-#endif /* DHD_WLFC_THREAD */
-	} else {
-		wlfc->stats.packet_request_failed++;
-	}
-
-	return BCME_OK;
-}
-
-/** Called when host receives a WLFC_CTL_TYPE_HOST_REORDER_RXPKTS TLV from the dongle */
-static void
-_dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len)
-{
-	if (info_len) {
-		if (info_buf) {
-			bcopy(val, info_buf, len);
-			*info_len = len;
-		} else {
-			*info_len = 0;
-		}
-	}
-}
-
-/*
- * public functions
- */
-
-bool dhd_wlfc_is_supported(dhd_pub_t *dhd)
-{
-	bool rc = TRUE;
-
-	if (dhd == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return FALSE;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		rc =  FALSE;
-	}
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return rc;
-}
-
-int dhd_wlfc_enable(dhd_pub_t *dhd)
-{
-	int i, rc = BCME_OK;
-	athost_wl_status_info_t* wlfc;
-
-	if (dhd == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if (!dhd->wlfc_enabled || dhd->wlfc_state) {
-		rc = BCME_OK;
-		goto exit;
-	}
-
-	/* allocate space to track txstatus propagated from firmware */
-	dhd->wlfc_state = DHD_OS_PREALLOC(dhd, DHD_PREALLOC_DHD_WLFC_INFO,
-		sizeof(athost_wl_status_info_t));
-	if (dhd->wlfc_state == NULL) {
-		rc = BCME_NOMEM;
-		goto exit;
-	}
-
-	/* initialize state space */
-	wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	memset(wlfc, 0, sizeof(athost_wl_status_info_t));
-
-	/* remember osh & dhdp */
-	wlfc->osh = dhd->osh;
-	wlfc->dhdp = dhd;
-
-	if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
-		wlfc->hanger = _dhd_wlfc_hanger_create(dhd, WLFC_HANGER_MAXITEMS);
-		if (wlfc->hanger == NULL) {
-			DHD_OS_PREFREE(dhd, dhd->wlfc_state,
-				sizeof(athost_wl_status_info_t));
-			dhd->wlfc_state = NULL;
-			rc = BCME_NOMEM;
-			goto exit;
-		}
-	}
-
-	dhd->proptxstatus_mode = WLFC_FCMODE_EXPLICIT_CREDIT;
-	/* default to check rx pkt */
-	dhd->wlfc_rxpkt_chk = TRUE;
-	if (dhd->op_mode & DHD_FLAG_IBSS_MODE) {
-		dhd->wlfc_rxpkt_chk = FALSE;
-	}
-
-	/* initialize all interfaces to accept traffic */
-	for (i = 0; i < WLFC_MAX_IFNUM; i++) {
-		wlfc->hostif_flow_state[i] = OFF;
-	}
-
-	_dhd_wlfc_mac_entry_update(wlfc, &wlfc->destination_entries.other,
-		eWLFC_MAC_ENTRY_ACTION_ADD, 0xff, 0, NULL, NULL, NULL);
-
-	wlfc->allow_credit_borrow = 0;
-	wlfc->single_ac = 0;
-	wlfc->single_ac_timestamp = 0;
-
-
-exit:
-	dhd_os_wlfc_unblock(dhd);
-
-	return rc;
-} /* dhd_wlfc_enable */
-
-#ifdef SUPPORT_P2P_GO_PS
-
-/**
- * Called when the host platform enters a lower power mode, eg right before a system hibernate.
- * SUPPORT_P2P_GO_PS specific function.
- */
-int
-dhd_wlfc_suspend(dhd_pub_t *dhd)
-{
-	uint32 tlv = 0;
-
-	DHD_TRACE(("%s: masking wlfc events\n", __FUNCTION__));
-	if (!dhd->wlfc_enabled)
-		return -1;
-
-	if (!dhd_wl_ioctl_get_intiovar(dhd, "tlv", &tlv, WLC_GET_VAR, FALSE, 0))
-		return -1;
-	if ((tlv & (WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS)) == 0)
-		return 0;
-	tlv &= ~(WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS);
-	if (!dhd_wl_ioctl_set_intiovar(dhd, "tlv", tlv, WLC_SET_VAR, TRUE, 0))
-		return -1;
-
-	return 0;
-}
-
-/**
- * Called when the host platform resumes from a power management operation, eg resume after a
- * system hibernate. SUPPORT_P2P_GO_PS specific function.
- */
-int
-dhd_wlfc_resume(dhd_pub_t *dhd)
-{
-	uint32 tlv = 0;
-
-	DHD_TRACE(("%s: unmasking wlfc events\n", __FUNCTION__));
-	if (!dhd->wlfc_enabled)
-		return -1;
-
-	if (!dhd_wl_ioctl_get_intiovar(dhd, "tlv", &tlv, WLC_GET_VAR, FALSE, 0))
-		return -1;
-	if ((tlv & (WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS)) ==
-		(WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS))
-		return 0;
-	tlv |= (WLFC_FLAGS_RSSI_SIGNALS | WLFC_FLAGS_XONXOFF_SIGNALS);
-	if (!dhd_wl_ioctl_set_intiovar(dhd, "tlv", tlv, WLC_SET_VAR, TRUE, 0))
-		return -1;
-
-	return 0;
-}
-
-#endif /* SUPPORT_P2P_GO_PS */
-
-/** A flow control header was received from firmware, containing one or more TLVs */
-int
-dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, uchar *reorder_info_buf,
-	uint *reorder_info_len)
-{
-	uint8 type, len;
-	uint8* value;
-	uint8* tmpbuf;
-	uint16 remainder = (uint16)tlv_hdr_len;
-	uint16 processed = 0;
-	athost_wl_status_info_t* wlfc = NULL;
-	void* entry;
-
-	if ((dhd == NULL) || (pktbuf == NULL)) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if (dhd->proptxstatus_mode != WLFC_ONLY_AMPDU_HOSTREORDER) {
-		if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-			dhd_os_wlfc_unblock(dhd);
-			return WLFC_UNSUPPORTED;
-		}
-		wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	}
-
-	tmpbuf = (uint8*)PKTDATA(dhd->osh, pktbuf);
-
-	if (remainder) {
-		while ((processed < (WLFC_MAX_PENDING_DATALEN * 2)) && (remainder > 0)) {
-			type = tmpbuf[processed];
-			if (type == WLFC_CTL_TYPE_FILLER) {
-				remainder -= 1;
-				processed += 1;
-				continue;
-			}
-
-			len  = tmpbuf[processed + 1];
-			value = &tmpbuf[processed + 2];
-
-			if (remainder < (2 + len))
-				break;
-
-			remainder -= 2 + len;
-			processed += 2 + len;
-			entry = NULL;
-
-			DHD_INFO(("%s():%d type %d remainder %d processed %d\n",
-				__FUNCTION__, __LINE__, type, remainder, processed));
-
-			if (type == WLFC_CTL_TYPE_HOST_REORDER_RXPKTS)
-				_dhd_wlfc_reorderinfo_indicate(value, len, reorder_info_buf,
-					reorder_info_len);
-
-			if (wlfc == NULL) {
-				ASSERT(dhd->proptxstatus_mode == WLFC_ONLY_AMPDU_HOSTREORDER);
-
-				if (type != WLFC_CTL_TYPE_HOST_REORDER_RXPKTS &&
-					type != WLFC_CTL_TYPE_TRANS_ID)
-					DHD_INFO(("%s():%d dhd->wlfc_state is NULL yet!"
-					" type %d remainder %d processed %d\n",
-					__FUNCTION__, __LINE__, type, remainder, processed));
-				continue;
-			}
-
-			if (type == WLFC_CTL_TYPE_TXSTATUS) {
-				_dhd_wlfc_compressed_txstatus_update(dhd, value, 1, &entry);
-			} else if (type == WLFC_CTL_TYPE_COMP_TXSTATUS) {
-				uint8 compcnt_offset = WLFC_CTL_VALUE_LEN_TXSTATUS;
-
-				if (WLFC_GET_REUSESEQ(dhd->wlfc_mode)) {
-					compcnt_offset += WLFC_CTL_VALUE_LEN_SEQ;
-				}
-				_dhd_wlfc_compressed_txstatus_update(dhd, value,
-					value[compcnt_offset], &entry);
-			} else if (type == WLFC_CTL_TYPE_FIFO_CREDITBACK) {
-				_dhd_wlfc_fifocreditback_indicate(dhd, value);
-			} else if (type == WLFC_CTL_TYPE_RSSI) {
-				_dhd_wlfc_rssi_indicate(dhd, value);
-			} else if (type == WLFC_CTL_TYPE_MAC_REQUEST_CREDIT) {
-				_dhd_wlfc_credit_request(dhd, value);
-			} else if (type == WLFC_CTL_TYPE_MAC_REQUEST_PACKET) {
-				_dhd_wlfc_packet_request(dhd, value);
-			} else if ((type == WLFC_CTL_TYPE_MAC_OPEN) ||
-				(type == WLFC_CTL_TYPE_MAC_CLOSE)) {
-				_dhd_wlfc_psmode_update(dhd, value, type);
-			} else if ((type == WLFC_CTL_TYPE_MACDESC_ADD) ||
-				(type == WLFC_CTL_TYPE_MACDESC_DEL)) {
-				_dhd_wlfc_mac_table_update(dhd, value, type);
-			} else if (type == WLFC_CTL_TYPE_TRANS_ID) {
-				_dhd_wlfc_dbg_senum_check(dhd, value);
-			} else if ((type == WLFC_CTL_TYPE_INTERFACE_OPEN) ||
-				(type == WLFC_CTL_TYPE_INTERFACE_CLOSE)) {
-				_dhd_wlfc_interface_update(dhd, value, type);
-			}
-
-			if (entry && WLFC_GET_REORDERSUPP(dhd->wlfc_mode)) {
-				/* suppress all packets for this mac entry from bus->txq */
-				_dhd_wlfc_suppress_txq(dhd, _dhd_wlfc_entrypkt_fn, entry);
-			}
-		} /* while */
-
-		if (remainder != 0 && wlfc) {
-			/* trouble..., something is not right */
-			wlfc->stats.tlv_parse_failed++;
-		}
-	} /* if */
-
-	if (wlfc)
-		wlfc->stats.dhd_hdrpulls++;
-
-	dhd_os_wlfc_unblock(dhd);
-	return BCME_OK;
-} /* dhd_wlfc_parse_header_info */
-
-KERNEL_THREAD_RETURN_TYPE
-dhd_wlfc_transfer_packets(void *data)
-{
-	dhd_pub_t *dhdp = (dhd_pub_t *)data;
-	int ac, single_ac = 0, rc = BCME_OK;
-	dhd_wlfc_commit_info_t  commit_info;
-	athost_wl_status_info_t* ctx;
-	int bus_retry_count = 0;
-	int pkt_send = 0;
-
-	uint8 tx_map = 0; /* packets (send + in queue), Bitmask for 4 ACs + BC/MC */
-	uint8 rx_map = 0; /* received packets, Bitmask for 4 ACs + BC/MC */
-	uint8 packets_map = 0; /* packets in queue, Bitmask for 4 ACs + BC/MC */
-	bool no_credit = FALSE;
-
-	int lender;
-
-#if defined(DHD_WLFC_THREAD)
-	/* wait till someone wakeup me up, will change it at running time */
-	int wait_msec = msecs_to_jiffies(0xFFFFFFFF);
-#endif /* defined(DHD_WLFC_THREAD) */
-
-#if defined(DHD_WLFC_THREAD)
-	while (1) {
-		bus_retry_count = 0;
-		pkt_send = 0;
-		tx_map = 0;
-		rx_map = 0;
-		packets_map = 0;
-		wait_msec = wait_event_interruptible_timeout(dhdp->wlfc_wqhead,
-			dhdp->wlfc_thread_go, wait_msec);
-		if (kthread_should_stop()) {
-			break;
-		}
-		dhdp->wlfc_thread_go = FALSE;
-
-		dhd_os_wlfc_block(dhdp);
-#endif /* defined(DHD_WLFC_THREAD) */
-		ctx = (athost_wl_status_info_t*)dhdp->wlfc_state;
-#if defined(DHD_WLFC_THREAD)
-		if (!ctx)
-			goto exit;
-#endif /* defined(DHD_WLFC_THREAD) */
-
-	memset(&commit_info, 0, sizeof(commit_info));
-
-	/*
-	Commit packets for regular AC traffic. Higher priority first.
-	First, use up FIFO credits available to each AC. Based on distribution
-	and credits left, borrow from other ACs as applicable
-
-	-NOTE:
-	If the bus between the host and firmware is overwhelmed by the
-	traffic from host, it is possible that higher priority traffic
-	starves the lower priority queue. If that occurs often, we may
-	have to employ weighted round-robin or ucode scheme to avoid
-	low priority packet starvation.
-	*/
-
-	for (ac = AC_COUNT; ac >= 0; ac--) {
-		if (dhdp->wlfc_rxpkt_chk) {
-			/* check rx packet */
-			uint32 curr_t = OSL_SYSUPTIME(), delta;
-
-			delta = curr_t - ctx->rx_timestamp[ac];
-			if (delta < WLFC_RX_DETECTION_THRESHOLD_MS) {
-				rx_map |= (1 << ac);
-			}
-		}
-
-		if (ctx->pkt_cnt_per_ac[ac] == 0) {
-			continue;
-		}
-
-		tx_map |= (1 << ac);
-		single_ac = ac + 1;
-		while (FALSE == dhdp->proptxstatus_txoff) {
-			/* packets from delayQ with less priority are fresh and
-			 * they'd need header and have no MAC entry
-			 */
-			no_credit = (ctx->FIFO_credit[ac] < 1);
-			if (dhdp->proptxstatus_credit_ignore ||
-				((ac == AC_COUNT) && !ctx->bcmc_credit_supported)) {
-				no_credit = FALSE;
-			}
-
-			lender = -1;
-#ifdef LIMIT_BORROW
-			if (no_credit && (ac < AC_COUNT) && (tx_map >= rx_map)) {
-				/* try borrow from lower priority */
-				lender = _dhd_wlfc_borrow_credit(ctx, ac - 1, ac, FALSE);
-				if (lender != -1) {
-					no_credit = FALSE;
-				}
-			}
-#endif
-			commit_info.needs_hdr = 1;
-			commit_info.mac_entry = NULL;
-			commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac,
-				&(commit_info.ac_fifo_credit_spent),
-				&(commit_info.needs_hdr),
-				&(commit_info.mac_entry),
-				no_credit);
-			commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED :
-				eWLFC_PKTTYPE_SUPPRESSED;
-
-			if (commit_info.p == NULL) {
-#ifdef LIMIT_BORROW
-				if (lender != -1) {
-					_dhd_wlfc_return_credit(ctx, lender, ac);
-				}
-#endif
-				break;
-			}
-
-			if (!dhdp->proptxstatus_credit_ignore && (lender == -1)) {
-				ASSERT(ctx->FIFO_credit[ac] >= commit_info.ac_fifo_credit_spent);
-			}
-			/* here we can ensure have credit or no credit needed */
-			rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info,
-				ctx->fcommit, ctx->commit_ctx);
-
-			/* Bus commits may fail (e.g. flow control); abort after retries */
-			if (rc == BCME_OK) {
-				pkt_send++;
-				if (commit_info.ac_fifo_credit_spent && (lender == -1)) {
-					ctx->FIFO_credit[ac]--;
-				}
-#ifdef LIMIT_BORROW
-				else if (!commit_info.ac_fifo_credit_spent && (lender != -1)) {
-					_dhd_wlfc_return_credit(ctx, lender, ac);
-				}
-#endif
-			} else {
-#ifdef LIMIT_BORROW
-				if (lender != -1) {
-					_dhd_wlfc_return_credit(ctx, lender, ac);
-				}
-#endif
-				bus_retry_count++;
-				if (bus_retry_count >= BUS_RETRIES) {
-					DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc));
-					goto exit;
-				}
-			}
-		}
-
-		if (ctx->pkt_cnt_per_ac[ac]) {
-			packets_map |= (1 << ac);
-		}
-	}
-
-	if ((tx_map == 0) || dhdp->proptxstatus_credit_ignore) {
-		/* nothing send out or remain in queue */
-		rc = BCME_OK;
-		goto exit;
-	}
-
-	if (((tx_map & (tx_map - 1)) == 0) && (tx_map >= rx_map)) {
-		/* only one tx ac exist and no higher rx ac */
-		if ((single_ac == ctx->single_ac) && ctx->allow_credit_borrow) {
-			ac = single_ac - 1;
-		} else {
-			uint32 delta;
-			uint32 curr_t = OSL_SYSUPTIME();
-
-			if (single_ac != ctx->single_ac) {
-				/* new single ac traffic (first single ac or different single ac) */
-				ctx->allow_credit_borrow = 0;
-				ctx->single_ac_timestamp = curr_t;
-				ctx->single_ac = (uint8)single_ac;
-				rc = BCME_OK;
-				goto exit;
-			}
-			/* same ac traffic, check if it lasts enough time */
-			delta = curr_t - ctx->single_ac_timestamp;
-
-			if (delta >= WLFC_BORROW_DEFER_PERIOD_MS) {
-				/* wait enough time, can borrow now */
-				ctx->allow_credit_borrow = 1;
-				ac = single_ac - 1;
-			} else {
-				rc = BCME_OK;
-				goto exit;
-			}
-		}
-	} else {
-		/* If we have multiple AC traffic, turn off borrowing, mark time and bail out */
-		ctx->allow_credit_borrow = 0;
-		ctx->single_ac_timestamp = 0;
-		ctx->single_ac = 0;
-		rc = BCME_OK;
-		goto exit;
-	}
-
-	if (packets_map == 0) {
-		/* nothing to send, skip borrow */
-		rc = BCME_OK;
-		goto exit;
-	}
-
-	/* At this point, borrow all credits only for ac */
-	while (FALSE == dhdp->proptxstatus_txoff) {
-#ifdef LIMIT_BORROW
-		if ((lender = _dhd_wlfc_borrow_credit(ctx, AC_COUNT, ac, TRUE)) == -1) {
-			break;
-		}
-#endif
-		commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac,
-			&(commit_info.ac_fifo_credit_spent),
-			&(commit_info.needs_hdr),
-			&(commit_info.mac_entry),
-			FALSE);
-		if (commit_info.p == NULL) {
-			/* before borrow only one ac exists and now this only ac is empty */
-#ifdef LIMIT_BORROW
-			_dhd_wlfc_return_credit(ctx, lender, ac);
-#endif
-			break;
-		}
-
-		commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED :
-			eWLFC_PKTTYPE_SUPPRESSED;
-
-		rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info,
-		     ctx->fcommit, ctx->commit_ctx);
-
-		/* Bus commits may fail (e.g. flow control); abort after retries */
-		if (rc == BCME_OK) {
-			pkt_send++;
-			if (commit_info.ac_fifo_credit_spent) {
-#ifndef LIMIT_BORROW
-				ctx->FIFO_credit[ac]--;
-#endif
-			} else {
-#ifdef LIMIT_BORROW
-				_dhd_wlfc_return_credit(ctx, lender, ac);
-#endif
-			}
-		} else {
-#ifdef LIMIT_BORROW
-			_dhd_wlfc_return_credit(ctx, lender, ac);
-#endif
-			bus_retry_count++;
-			if (bus_retry_count >= BUS_RETRIES) {
-				DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc));
-				goto exit;
-			}
-		}
-	}
-
-	BCM_REFERENCE(pkt_send);
-
-exit:
-#if defined(DHD_WLFC_THREAD)
-		dhd_os_wlfc_unblock(dhdp);
-		if (ctx && ctx->pkt_cnt_in_psq && pkt_send) {
-			wait_msec = msecs_to_jiffies(WLFC_THREAD_QUICK_RETRY_WAIT_MS);
-		} else {
-			wait_msec = msecs_to_jiffies(WLFC_THREAD_RETRY_WAIT_MS);
-		}
-	}
-	return 0;
-#else
-	return rc;
-#endif /* defined(DHD_WLFC_THREAD) */
-}
-
-/**
- * Enqueues a transmit packet in the next layer towards the dongle, eg the DBUS layer. Called by
- * eg dhd_sendpkt().
- *     @param[in] dhdp                  Pointer to public DHD structure
- *     @param[in] fcommit               Pointer to transmit function of next layer
- *     @param[in] commit_ctx            Opaque context used when calling next layer
- *     @param[in] pktbuf                Packet to send
- *     @param[in] need_toggle_host_if   If TRUE, resets flag ctx->toggle_host_if
- */
-int
-dhd_wlfc_commit_packets(dhd_pub_t *dhdp, f_commitpkt_t fcommit, void* commit_ctx, void *pktbuf,
-	bool need_toggle_host_if)
-{
-	int rc = BCME_OK;
-	athost_wl_status_info_t* ctx;
-
-#if defined(DHD_WLFC_THREAD)
-	if (!pktbuf)
-		return BCME_OK;
-#endif /* defined(DHD_WLFC_THREAD) */
-
-	if ((dhdp == NULL) || (fcommit == NULL)) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhdp);
-
-	if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		if (pktbuf) {
-			DHD_PKTTAG_WLFCPKT_SET(PKTTAG(pktbuf), 0);
-		}
-		rc =  WLFC_UNSUPPORTED;
-		goto exit;
-	}
-
-	ctx = (athost_wl_status_info_t*)dhdp->wlfc_state;
-
-
-	if (dhdp->proptxstatus_module_ignore) {
-		if (pktbuf) {
-			uint32 htod = 0;
-			WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST);
-			_dhd_wlfc_pushheader(ctx, &pktbuf, FALSE, 0, 0, htod, 0, FALSE);
-			if (fcommit(commit_ctx, pktbuf)) {
-				/* free it if failed, otherwise do it in tx complete cb */
-				PKTFREE(ctx->osh, pktbuf, TRUE);
-			}
-			rc = BCME_OK;
-		}
-		goto exit;
-	}
-
-	if (pktbuf) {
-		int ac = DHD_PKTTAG_FIFO(PKTTAG(pktbuf));
-		ASSERT(ac <= AC_COUNT);
-		DHD_PKTTAG_WLFCPKT_SET(PKTTAG(pktbuf), 1);
-		/* en-queue the packets to respective queue. */
-		rc = _dhd_wlfc_enque_delayq(ctx, pktbuf, ac);
-		if (rc) {
-			_dhd_wlfc_prec_drop(ctx->dhdp, (ac << 1), pktbuf, FALSE);
-		} else {
-			ctx->stats.pktin++;
-			ctx->pkt_cnt_in_drv[DHD_PKTTAG_IF(PKTTAG(pktbuf))][ac]++;
-		}
-	}
-
-	if (!ctx->fcommit) {
-		ctx->fcommit = fcommit;
-	} else {
-		ASSERT(ctx->fcommit == fcommit);
-	}
-	if (!ctx->commit_ctx) {
-		ctx->commit_ctx = commit_ctx;
-	} else {
-		ASSERT(ctx->commit_ctx == commit_ctx);
-	}
-
-#if defined(DHD_WLFC_THREAD)
-	_dhd_wlfc_thread_wakeup(dhdp);
-#else
-	dhd_wlfc_transfer_packets(dhdp);
-#endif /* defined(DHD_WLFC_THREAD) */
-
-exit:
-	dhd_os_wlfc_unblock(dhdp);
-	return rc;
-} /* dhd_wlfc_commit_packets */
-
-/**
- * Called when the (lower) DBUS layer indicates completion (succesfull or not) of a transmit packet
- */
-int
-dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success)
-{
-	athost_wl_status_info_t* wlfc;
-	wlfc_mac_descriptor_t *entry;
-	void* pout = NULL;
-	int rtn = BCME_OK;
-	if ((dhd == NULL) || (txp == NULL)) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	bcm_pkt_validate_chk(txp);
-
-	dhd_os_wlfc_block(dhd);
-
-	if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		rtn = WLFC_UNSUPPORTED;
-		goto EXIT;
-	}
-
-	wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-	if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) {
-#ifdef PROP_TXSTATUS_DEBUG
-		wlfc->stats.signal_only_pkts_freed++;
-#endif
-		/* is this a signal-only packet? */
-		_dhd_wlfc_pullheader(wlfc, txp);
-		PKTFREE(wlfc->osh, txp, TRUE);
-		goto EXIT;
-	}
-
-	entry = _dhd_wlfc_find_table_entry(wlfc, txp);
-	ASSERT(entry);
-
-	if (!success || dhd->proptxstatus_txstatus_ignore) {
-		WLFC_DBGMESG(("At: %s():%d, bus_complete() failure for %p, htod_tag:0x%08x\n",
-			__FUNCTION__, __LINE__, txp, DHD_PKTTAG_H2DTAG(PKTTAG(txp))));
-		if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
-			_dhd_wlfc_hanger_poppkt(wlfc->hanger, WL_TXSTATUS_GET_HSLOT(
-				DHD_PKTTAG_H2DTAG(PKTTAG(txp))), &pout, TRUE);
-			ASSERT(txp == pout);
-		}
-
-		/* indicate failure and free the packet */
-		dhd_txcomplete(dhd, txp, success);
-
-		/* return the credit, if necessary */
-		_dhd_wlfc_return_implied_credit(wlfc, txp);
-
-		if (entry->transit_count)
-			entry->transit_count--;
-		if (entry->suppr_transit_count)
-			entry->suppr_transit_count--;
-		wlfc->pkt_cnt_in_drv[DHD_PKTTAG_IF(PKTTAG(txp))][DHD_PKTTAG_FIFO(PKTTAG(txp))]--;
-		wlfc->stats.pktout++;
-		PKTFREE(wlfc->osh, txp, TRUE);
-	} else {
-		/* bus confirmed pkt went to firmware side */
-		if (WLFC_GET_AFQ(dhd->wlfc_mode)) {
-			_dhd_wlfc_enque_afq(wlfc, txp);
-		} else {
-			int hslot = WL_TXSTATUS_GET_HSLOT(DHD_PKTTAG_H2DTAG(PKTTAG(txp)));
-			_dhd_wlfc_hanger_free_pkt(wlfc, hslot,
-				WLFC_HANGER_PKT_STATE_BUSRETURNED, -1);
-		}
-	}
-
-	ASSERT(entry->onbus_pkts_count > 0);
-	if (entry->onbus_pkts_count > 0)
-		entry->onbus_pkts_count--;
-	if (entry->suppressed &&
-		(!entry->onbus_pkts_count) &&
-		(!entry->suppr_transit_count))
-		entry->suppressed = FALSE;
-EXIT:
-	dhd_os_wlfc_unblock(dhd);
-	return rtn;
-} /* dhd_wlfc_txcomplete */
-
-int
-dhd_wlfc_init(dhd_pub_t *dhd)
-{
-	/* enable all signals & indicate host proptxstatus logic is active */
-	uint32 tlv, mode, fw_caps;
-	int ret = 0;
-
-	if (dhd == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-	if (dhd->wlfc_enabled) {
-		DHD_INFO(("%s():%d, Already enabled!\n", __FUNCTION__, __LINE__));
-		dhd_os_wlfc_unblock(dhd);
-		return BCME_OK;
-	}
-	dhd->wlfc_enabled = TRUE;
-	dhd_os_wlfc_unblock(dhd);
-
-	tlv = WLFC_FLAGS_RSSI_SIGNALS |
-		WLFC_FLAGS_XONXOFF_SIGNALS |
-		WLFC_FLAGS_CREDIT_STATUS_SIGNALS |
-		WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE |
-		WLFC_FLAGS_HOST_RXRERODER_ACTIVE;
-
-
-	/*
-	try to enable/disable signaling by sending "tlv" iovar. if that fails,
-	fallback to no flow control? Print a message for now.
-	*/
-
-	/* enable proptxtstatus signaling by default */
-	if (!dhd_wl_ioctl_set_intiovar(dhd, "tlv", tlv, WLC_SET_VAR, TRUE, 0)) {
-		/*
-		Leaving the message for now, it should be removed after a while; once
-		the tlv situation is stable.
-		*/
-		DHD_INFO(("dhd_wlfc_init(): successfully %s bdcv2 tlv signaling, %d\n",
-			dhd->wlfc_enabled?"enabled":"disabled", tlv));
-	}
-
-	mode = 0;
-
-	/* query caps */
-	ret = dhd_wl_ioctl_get_intiovar(dhd, "wlfc_mode", &fw_caps, WLC_GET_VAR, FALSE, 0);
-
-	if (!ret) {
-		DHD_INFO(("%s: query wlfc_mode succeed, fw_caps=0x%x\n", __FUNCTION__, fw_caps));
-
-		if (WLFC_IS_OLD_DEF(fw_caps)) {
-			/* enable proptxtstatus v2 by default */
-			mode = WLFC_MODE_AFQ;
-		} else {
-			WLFC_SET_AFQ(mode, WLFC_GET_AFQ(fw_caps));
-			WLFC_SET_REUSESEQ(mode, WLFC_GET_REUSESEQ(fw_caps));
-			WLFC_SET_REORDERSUPP(mode, WLFC_GET_REORDERSUPP(fw_caps));
-		}
-		ret = dhd_wl_ioctl_set_intiovar(dhd, "wlfc_mode", mode, WLC_SET_VAR, TRUE, 0);
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	dhd->wlfc_mode = 0;
-	if (ret >= 0) {
-		if (WLFC_IS_OLD_DEF(mode)) {
-			WLFC_SET_AFQ(dhd->wlfc_mode, (mode == WLFC_MODE_AFQ));
-		} else {
-			dhd->wlfc_mode = mode;
-		}
-	}
-
-	DHD_INFO(("dhd_wlfc_init(): wlfc_mode=0x%x, ret=%d\n", dhd->wlfc_mode, ret));
-
-	dhd_os_wlfc_unblock(dhd);
-
-	if (dhd->plat_init)
-		dhd->plat_init((void *)dhd);
-
-	return BCME_OK;
-} /* dhd_wlfc_init */
-
-/** AMPDU host reorder specific function */
-int
-dhd_wlfc_hostreorder_init(dhd_pub_t *dhd)
-{
-	/* enable only ampdu hostreorder here */
-	uint32 tlv;
-
-	if (dhd == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	DHD_TRACE(("%s():%d Enter\n", __FUNCTION__, __LINE__));
-
-	tlv = WLFC_FLAGS_HOST_RXRERODER_ACTIVE;
-
-	/* enable proptxtstatus signaling by default */
-	if (dhd_wl_ioctl_set_intiovar(dhd, "tlv", tlv, WLC_SET_VAR, TRUE, 0)) {
-		DHD_ERROR(("%s(): failed to enable/disable bdcv2 tlv signaling\n",
-			__FUNCTION__));
-	} else {
-		/*
-		Leaving the message for now, it should be removed after a while; once
-		the tlv situation is stable.
-		*/
-		DHD_ERROR(("%s(): successful bdcv2 tlv signaling, %d\n",
-			__FUNCTION__, tlv));
-	}
-
-	dhd_os_wlfc_block(dhd);
-	dhd->proptxstatus_mode = WLFC_ONLY_AMPDU_HOSTREORDER;
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-int
-dhd_wlfc_cleanup_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
-{
-	if (dhd == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhd);
-		return WLFC_UNSUPPORTED;
-	}
-
-	_dhd_wlfc_cleanup_txq(dhd, fn, arg);
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** release all packet resources */
-int
-dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void *arg)
-{
-	if (dhd == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhd);
-		return WLFC_UNSUPPORTED;
-	}
-
-	_dhd_wlfc_cleanup(dhd, fn, arg);
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-int
-dhd_wlfc_deinit(dhd_pub_t *dhd)
-{
-	/* cleanup all psq related resources */
-	athost_wl_status_info_t* wlfc;
-	uint32 tlv = 0;
-	uint32 hostreorder = 0;
-
-	if (dhd == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-	if (!dhd->wlfc_enabled) {
-		DHD_ERROR(("%s():%d, Already disabled!\n", __FUNCTION__, __LINE__));
-		dhd_os_wlfc_unblock(dhd);
-		return BCME_OK;
-	}
-
-	dhd->wlfc_enabled = FALSE;
-	dhd_os_wlfc_unblock(dhd);
-
-	/* query ampdu hostreorder */
-	(void) dhd_wl_ioctl_get_intiovar(dhd, "ampdu_hostreorder",
-		&hostreorder, WLC_GET_VAR, FALSE, 0);
-
-	if (hostreorder) {
-		tlv = WLFC_FLAGS_HOST_RXRERODER_ACTIVE;
-		DHD_ERROR(("%s():%d, maintain HOST RXRERODER flag in tvl\n",
-			__FUNCTION__, __LINE__));
-	}
-
-	/* Disable proptxtstatus signaling for deinit */
-	(void) dhd_wl_ioctl_set_intiovar(dhd, "tlv", tlv, WLC_SET_VAR, TRUE, 0);
-
-	dhd_os_wlfc_block(dhd);
-
-	if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhd);
-		return WLFC_UNSUPPORTED;
-	}
-
-	wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-
-	_dhd_wlfc_cleanup(dhd, NULL, NULL);
-
-	if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
-		int i;
-		wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger;
-		for (i = 0; i < h->max_items; i++) {
-			if (h->items[i].state != WLFC_HANGER_ITEM_STATE_FREE) {
-				_dhd_wlfc_hanger_free_pkt(wlfc, i,
-					WLFC_HANGER_PKT_STATE_COMPLETE, TRUE);
-			}
-		}
-
-		/* delete hanger */
-		_dhd_wlfc_hanger_delete(dhd, h);
-	}
-
-
-	/* free top structure */
-	DHD_OS_PREFREE(dhd, dhd->wlfc_state,
-		sizeof(athost_wl_status_info_t));
-	dhd->wlfc_state = NULL;
-	dhd->proptxstatus_mode = hostreorder ?
-		WLFC_ONLY_AMPDU_HOSTREORDER : WLFC_FCMODE_NONE;
-
-	dhd_os_wlfc_unblock(dhd);
-
-	if (dhd->plat_deinit)
-		dhd->plat_deinit((void *)dhd);
-	return BCME_OK;
-} /* dhd_wlfc_init */
-
-/**
- * Called on an interface event (WLC_E_IF) indicated by firmware
- *     @param[in] dhdp   Pointer to public DHD structure
- *     @param[in] action eg eWLFC_MAC_ENTRY_ACTION_UPDATE or eWLFC_MAC_ENTRY_ACTION_ADD
- */
-int dhd_wlfc_interface_event(dhd_pub_t *dhdp, uint8 action, uint8 ifid, uint8 iftype, uint8* ea)
-{
-	int rc;
-
-	if (dhdp == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhdp);
-
-	if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhdp);
-		return WLFC_UNSUPPORTED;
-	}
-
-	rc = _dhd_wlfc_interface_entry_update(dhdp->wlfc_state, action, ifid, iftype, ea);
-
-	dhd_os_wlfc_unblock(dhdp);
-	return rc;
-}
-
-/** Called eg on receiving a WLC_E_FIFO_CREDIT_MAP event from the dongle */
-int dhd_wlfc_FIFOcreditmap_event(dhd_pub_t *dhdp, uint8* event_data)
-{
-	int rc;
-
-	if (dhdp == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhdp);
-
-	if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhdp);
-		return WLFC_UNSUPPORTED;
-	}
-
-	rc = _dhd_wlfc_FIFOcreditmap_update(dhdp->wlfc_state, event_data);
-
-	dhd_os_wlfc_unblock(dhdp);
-
-	return rc;
-}
-
-/**
- * Called eg on receiving a WLC_E_BCMC_CREDIT_SUPPORT event from the dongle (broadcast/multicast
- * specific)
- */
-int dhd_wlfc_BCMCCredit_support_event(dhd_pub_t *dhdp)
-{
-	int rc;
-
-	if (dhdp == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhdp);
-
-	if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhdp);
-		return WLFC_UNSUPPORTED;
-	}
-
-	rc = _dhd_wlfc_BCMCCredit_support_update(dhdp->wlfc_state);
-
-	dhd_os_wlfc_unblock(dhdp);
-	return rc;
-}
-
-/** debug specific function */
-int
-dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
-{
-	int i;
-	uint8* ea;
-	athost_wl_status_info_t* wlfc;
-	wlfc_hanger_t* h;
-	wlfc_mac_descriptor_t* mac_table;
-	wlfc_mac_descriptor_t* interfaces;
-	char* iftypes[] = {"STA", "AP", "WDS", "p2pGO", "p2pCL"};
-
-	if (!dhdp || !strbuf) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhdp);
-
-	if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhdp);
-		return WLFC_UNSUPPORTED;
-	}
-
-	wlfc = (athost_wl_status_info_t*)dhdp->wlfc_state;
-
-	h = (wlfc_hanger_t*)wlfc->hanger;
-	if (h == NULL) {
-		bcm_bprintf(strbuf, "wlfc-hanger not initialized yet\n");
-	}
-
-	mac_table = wlfc->destination_entries.nodes;
-	interfaces = wlfc->destination_entries.interfaces;
-	bcm_bprintf(strbuf, "---- wlfc stats ----\n");
-
-	if (!WLFC_GET_AFQ(dhdp->wlfc_mode)) {
-		h = (wlfc_hanger_t*)wlfc->hanger;
-		if (h == NULL) {
-			bcm_bprintf(strbuf, "wlfc-hanger not initialized yet\n");
-		} else {
-			bcm_bprintf(strbuf, "wlfc hanger (pushed,popped,f_push,"
-				"f_pop,f_slot, pending) = (%d,%d,%d,%d,%d,%d)\n",
-				h->pushed,
-				h->popped,
-				h->failed_to_push,
-				h->failed_to_pop,
-				h->failed_slotfind,
-				(h->pushed - h->popped));
-		}
-	}
-
-	bcm_bprintf(strbuf, "wlfc fail(tlv,credit_rqst,mac_update,psmode_update), "
-		"(dq_full,rollback_fail) = (%d,%d,%d,%d), (%d,%d)\n",
-		wlfc->stats.tlv_parse_failed,
-		wlfc->stats.credit_request_failed,
-		wlfc->stats.mac_update_failed,
-		wlfc->stats.psmode_update_failed,
-		wlfc->stats.delayq_full_error,
-		wlfc->stats.rollback_failed);
-
-	bcm_bprintf(strbuf, "PKTS (init_credit,credit,sent,drop_d,drop_s,outoforder) "
-		"(AC0[%d,%d,%d,%d,%d,%d],AC1[%d,%d,%d,%d,%d,%d],AC2[%d,%d,%d,%d,%d,%d],"
-		"AC3[%d,%d,%d,%d,%d,%d],BC_MC[%d,%d,%d,%d,%d,%d])\n",
-		wlfc->Init_FIFO_credit[0], wlfc->FIFO_credit[0], wlfc->stats.send_pkts[0],
-		wlfc->stats.drop_pkts[0], wlfc->stats.drop_pkts[1], wlfc->stats.ooo_pkts[0],
-		wlfc->Init_FIFO_credit[1], wlfc->FIFO_credit[1], wlfc->stats.send_pkts[1],
-		wlfc->stats.drop_pkts[2], wlfc->stats.drop_pkts[3], wlfc->stats.ooo_pkts[1],
-		wlfc->Init_FIFO_credit[2], wlfc->FIFO_credit[2], wlfc->stats.send_pkts[2],
-		wlfc->stats.drop_pkts[4], wlfc->stats.drop_pkts[5], wlfc->stats.ooo_pkts[2],
-		wlfc->Init_FIFO_credit[3], wlfc->FIFO_credit[3], wlfc->stats.send_pkts[3],
-		wlfc->stats.drop_pkts[6], wlfc->stats.drop_pkts[7], wlfc->stats.ooo_pkts[3],
-		wlfc->Init_FIFO_credit[4], wlfc->FIFO_credit[4], wlfc->stats.send_pkts[4],
-		wlfc->stats.drop_pkts[8], wlfc->stats.drop_pkts[9], wlfc->stats.ooo_pkts[4]);
-
-	bcm_bprintf(strbuf, "\n");
-	for (i = 0; i < WLFC_MAX_IFNUM; i++) {
-		if (interfaces[i].occupied) {
-			char* iftype_desc;
-
-			if (interfaces[i].iftype > WLC_E_IF_ROLE_P2P_CLIENT)
-				iftype_desc = "<Unknown";
-			else
-				iftype_desc = iftypes[interfaces[i].iftype];
-
-			ea = interfaces[i].ea;
-			bcm_bprintf(strbuf, "INTERFACE[%d].ea = "
-				"[%02x:%02x:%02x:%02x:%02x:%02x], if:%d, type: %s "
-				"netif_flow_control:%s\n", i,
-				ea[0], ea[1], ea[2], ea[3], ea[4], ea[5],
-				interfaces[i].interface_id,
-				iftype_desc, ((wlfc->hostif_flow_state[i] == OFF)
-				? " OFF":" ON"));
-
-			bcm_bprintf(strbuf, "INTERFACE[%d].PSQ(len,state,credit),"
-				"(trans,supp_trans,onbus)"
-				"= (%d,%s,%d),(%d,%d,%d)\n",
-				i,
-				interfaces[i].psq.len,
-				((interfaces[i].state ==
-				WLFC_STATE_OPEN) ? "OPEN":"CLOSE"),
-				interfaces[i].requested_credit,
-				interfaces[i].transit_count,
-				interfaces[i].suppr_transit_count,
-				interfaces[i].onbus_pkts_count);
-
-			bcm_bprintf(strbuf, "INTERFACE[%d].PSQ"
-				"(delay0,sup0,afq0),(delay1,sup1,afq1),(delay2,sup2,afq2),"
-				"(delay3,sup3,afq3),(delay4,sup4,afq4) = (%d,%d,%d),"
-				"(%d,%d,%d),(%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n",
-				i,
-				interfaces[i].psq.q[0].len,
-				interfaces[i].psq.q[1].len,
-				interfaces[i].afq.q[0].len,
-				interfaces[i].psq.q[2].len,
-				interfaces[i].psq.q[3].len,
-				interfaces[i].afq.q[1].len,
-				interfaces[i].psq.q[4].len,
-				interfaces[i].psq.q[5].len,
-				interfaces[i].afq.q[2].len,
-				interfaces[i].psq.q[6].len,
-				interfaces[i].psq.q[7].len,
-				interfaces[i].afq.q[3].len,
-				interfaces[i].psq.q[8].len,
-				interfaces[i].psq.q[9].len,
-				interfaces[i].afq.q[4].len);
-		}
-	}
-
-	bcm_bprintf(strbuf, "\n");
-	for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) {
-		if (mac_table[i].occupied) {
-			ea = mac_table[i].ea;
-			bcm_bprintf(strbuf, "MAC_table[%d].ea = "
-				"[%02x:%02x:%02x:%02x:%02x:%02x], if:%d \n", i,
-				ea[0], ea[1], ea[2], ea[3], ea[4], ea[5],
-				mac_table[i].interface_id);
-
-			bcm_bprintf(strbuf, "MAC_table[%d].PSQ(len,state,credit),"
-				"(trans,supp_trans,onbus)"
-				"= (%d,%s,%d),(%d,%d,%d)\n",
-				i,
-				mac_table[i].psq.len,
-				((mac_table[i].state ==
-				WLFC_STATE_OPEN) ? " OPEN":"CLOSE"),
-				mac_table[i].requested_credit,
-				mac_table[i].transit_count,
-				mac_table[i].suppr_transit_count,
-				mac_table[i].onbus_pkts_count);
-#ifdef PROP_TXSTATUS_DEBUG
-			bcm_bprintf(strbuf, "MAC_table[%d]: (opened, closed) = (%d, %d)\n",
-				i, mac_table[i].opened_ct, mac_table[i].closed_ct);
-#endif
-			bcm_bprintf(strbuf, "MAC_table[%d].PSQ"
-				"(delay0,sup0,afq0),(delay1,sup1,afq1),(delay2,sup2,afq2),"
-				"(delay3,sup3,afq3),(delay4,sup4,afq4) =(%d,%d,%d),"
-				"(%d,%d,%d),(%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n",
-				i,
-				mac_table[i].psq.q[0].len,
-				mac_table[i].psq.q[1].len,
-				mac_table[i].afq.q[0].len,
-				mac_table[i].psq.q[2].len,
-				mac_table[i].psq.q[3].len,
-				mac_table[i].afq.q[1].len,
-				mac_table[i].psq.q[4].len,
-				mac_table[i].psq.q[5].len,
-				mac_table[i].afq.q[2].len,
-				mac_table[i].psq.q[6].len,
-				mac_table[i].psq.q[7].len,
-				mac_table[i].afq.q[3].len,
-				mac_table[i].psq.q[8].len,
-				mac_table[i].psq.q[9].len,
-				mac_table[i].afq.q[4].len);
-
-		}
-	}
-
-#ifdef PROP_TXSTATUS_DEBUG
-	{
-		int avg;
-		int moving_avg = 0;
-		int moving_samples;
-
-		if (wlfc->stats.latency_sample_count) {
-			moving_samples = sizeof(wlfc->stats.deltas)/sizeof(uint32);
-
-			for (i = 0; i < moving_samples; i++)
-				moving_avg += wlfc->stats.deltas[i];
-			moving_avg /= moving_samples;
-
-			avg = (100 * wlfc->stats.total_status_latency) /
-				wlfc->stats.latency_sample_count;
-			bcm_bprintf(strbuf, "txstatus latency (average, last, moving[%d]) = "
-				"(%d.%d, %03d, %03d)\n",
-				moving_samples, avg/100, (avg - (avg/100)*100),
-				wlfc->stats.latency_most_recent,
-				moving_avg);
-		}
-	}
-
-	bcm_bprintf(strbuf, "wlfc- fifo[0-5] credit stats: sent = (%d,%d,%d,%d,%d,%d), "
-		"back = (%d,%d,%d,%d,%d,%d)\n",
-		wlfc->stats.fifo_credits_sent[0],
-		wlfc->stats.fifo_credits_sent[1],
-		wlfc->stats.fifo_credits_sent[2],
-		wlfc->stats.fifo_credits_sent[3],
-		wlfc->stats.fifo_credits_sent[4],
-		wlfc->stats.fifo_credits_sent[5],
-
-		wlfc->stats.fifo_credits_back[0],
-		wlfc->stats.fifo_credits_back[1],
-		wlfc->stats.fifo_credits_back[2],
-		wlfc->stats.fifo_credits_back[3],
-		wlfc->stats.fifo_credits_back[4],
-		wlfc->stats.fifo_credits_back[5]);
-	{
-		uint32 fifo_cr_sent = 0;
-		uint32 fifo_cr_acked = 0;
-		uint32 request_cr_sent = 0;
-		uint32 request_cr_ack = 0;
-		uint32 bc_mc_cr_ack = 0;
-
-		for (i = 0; i < sizeof(wlfc->stats.fifo_credits_sent)/sizeof(uint32); i++) {
-			fifo_cr_sent += wlfc->stats.fifo_credits_sent[i];
-		}
-
-		for (i = 0; i < sizeof(wlfc->stats.fifo_credits_back)/sizeof(uint32); i++) {
-			fifo_cr_acked += wlfc->stats.fifo_credits_back[i];
-		}
-
-		for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) {
-			if (wlfc->destination_entries.nodes[i].occupied) {
-				request_cr_sent +=
-					wlfc->destination_entries.nodes[i].dstncredit_sent_packets;
-			}
-		}
-		for (i = 0; i < WLFC_MAX_IFNUM; i++) {
-			if (wlfc->destination_entries.interfaces[i].occupied) {
-				request_cr_sent +=
-				wlfc->destination_entries.interfaces[i].dstncredit_sent_packets;
-			}
-		}
-		for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) {
-			if (wlfc->destination_entries.nodes[i].occupied) {
-				request_cr_ack +=
-					wlfc->destination_entries.nodes[i].dstncredit_acks;
-			}
-		}
-		for (i = 0; i < WLFC_MAX_IFNUM; i++) {
-			if (wlfc->destination_entries.interfaces[i].occupied) {
-				request_cr_ack +=
-					wlfc->destination_entries.interfaces[i].dstncredit_acks;
-			}
-		}
-		bcm_bprintf(strbuf, "wlfc- (sent, status) => pq(%d,%d), vq(%d,%d),"
-			"other:%d, bc_mc:%d, signal-only, (sent,freed): (%d,%d)",
-			fifo_cr_sent, fifo_cr_acked,
-			request_cr_sent, request_cr_ack,
-			wlfc->destination_entries.other.dstncredit_acks,
-			bc_mc_cr_ack,
-			wlfc->stats.signal_only_pkts_sent, wlfc->stats.signal_only_pkts_freed);
-	}
-#endif /* PROP_TXSTATUS_DEBUG */
-	bcm_bprintf(strbuf, "\n");
-	bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull,out),(dropped,hdr_only,wlc_tossed)"
-		"(freed,free_err,rollback)) = "
-		"((%d,%d,%d,%d,%d),(%d,%d,%d),(%d,%d,%d))\n",
-		wlfc->stats.pktin,
-		wlfc->stats.pkt2bus,
-		wlfc->stats.txstatus_in,
-		wlfc->stats.dhd_hdrpulls,
-		wlfc->stats.pktout,
-
-		wlfc->stats.pktdropped,
-		wlfc->stats.wlfc_header_only_pkt,
-		wlfc->stats.wlc_tossed_pkts,
-
-		wlfc->stats.pkt_freed,
-		wlfc->stats.pkt_free_err, wlfc->stats.rollback);
-
-	bcm_bprintf(strbuf, "wlfc- suppress((d11,wlc,err),enq(d11,wl,hq,mac?),retx(d11,wlc,hq)) = "
-		"((%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d))\n",
-		wlfc->stats.d11_suppress,
-		wlfc->stats.wl_suppress,
-		wlfc->stats.bad_suppress,
-
-		wlfc->stats.psq_d11sup_enq,
-		wlfc->stats.psq_wlsup_enq,
-		wlfc->stats.psq_hostq_enq,
-		wlfc->stats.mac_handle_notfound,
-
-		wlfc->stats.psq_d11sup_retx,
-		wlfc->stats.psq_wlsup_retx,
-		wlfc->stats.psq_hostq_retx);
-
-	bcm_bprintf(strbuf, "wlfc- cleanup(txq,psq,fw) = (%d,%d,%d)\n",
-		wlfc->stats.cleanup_txq_cnt,
-		wlfc->stats.cleanup_psq_cnt,
-		wlfc->stats.cleanup_fw_cnt);
-
-	bcm_bprintf(strbuf, "wlfc- generic error: %d\n", wlfc->stats.generic_error);
-
-	for (i = 0; i < WLFC_MAX_IFNUM; i++) {
-		bcm_bprintf(strbuf, "wlfc- if[%d], pkt_cnt_in_q/AC[0-4] = (%d,%d,%d,%d,%d)\n", i,
-			wlfc->pkt_cnt_in_q[i][0],
-			wlfc->pkt_cnt_in_q[i][1],
-			wlfc->pkt_cnt_in_q[i][2],
-			wlfc->pkt_cnt_in_q[i][3],
-			wlfc->pkt_cnt_in_q[i][4]);
-	}
-	bcm_bprintf(strbuf, "\n");
-
-	dhd_os_wlfc_unblock(dhdp);
-	return BCME_OK;
-} /* dhd_wlfc_dump */
-
-int dhd_wlfc_clear_counts(dhd_pub_t *dhd)
-{
-	athost_wl_status_info_t* wlfc;
-	wlfc_hanger_t* hanger;
-
-	if (dhd == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhd);
-		return WLFC_UNSUPPORTED;
-	}
-
-	wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-
-	memset(&wlfc->stats, 0, sizeof(athost_wl_stat_counters_t));
-
-	if (!WLFC_GET_AFQ(dhd->wlfc_mode)) {
-		hanger = (wlfc_hanger_t*)wlfc->hanger;
-
-		hanger->pushed = 0;
-		hanger->popped = 0;
-		hanger->failed_slotfind = 0;
-		hanger->failed_to_pop = 0;
-		hanger->failed_to_push = 0;
-	}
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** returns TRUE if flow control is enabled */
-int dhd_wlfc_get_enable(dhd_pub_t *dhd, bool *val)
-{
-	if (!dhd || !val) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	*val = dhd->wlfc_enabled;
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** Called via an IOVAR */
-int dhd_wlfc_get_mode(dhd_pub_t *dhd, int *val)
-{
-	if (!dhd || !val) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	*val = dhd->wlfc_state ? dhd->proptxstatus_mode : 0;
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** Called via an IOVAR */
-int dhd_wlfc_set_mode(dhd_pub_t *dhd, int val)
-{
-	if (!dhd) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if (dhd->wlfc_state) {
-		dhd->proptxstatus_mode = val & 0xff;
-	}
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** Called when rx frame is received from the dongle */
-bool dhd_wlfc_is_header_only_pkt(dhd_pub_t * dhd, void *pktbuf)
-{
-	athost_wl_status_info_t* wlfc;
-	bool rc = FALSE;
-
-	if (dhd == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return FALSE;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhd);
-		return FALSE;
-	}
-
-	wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-
-	if (PKTLEN(wlfc->osh, pktbuf) == 0) {
-		wlfc->stats.wlfc_header_only_pkt++;
-		rc = TRUE;
-	}
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return rc;
-}
-
-int dhd_wlfc_flowcontrol(dhd_pub_t *dhdp, bool state, bool bAcquireLock)
-{
-	if (dhdp == NULL) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	if (bAcquireLock) {
-		dhd_os_wlfc_block(dhdp);
-	}
-
-	if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE) ||
-		dhdp->proptxstatus_module_ignore) {
-		if (bAcquireLock) {
-			dhd_os_wlfc_unblock(dhdp);
-		}
-		return WLFC_UNSUPPORTED;
-	}
-
-	if (state != dhdp->proptxstatus_txoff) {
-		dhdp->proptxstatus_txoff = state;
-	}
-
-	if (bAcquireLock) {
-		dhd_os_wlfc_unblock(dhdp);
-	}
-
-#if defined(DHD_WLFC_THREAD)
-	_dhd_wlfc_thread_wakeup(dhd);
-#endif /* defined(DHD_WLFC_THREAD) */
-
-	return BCME_OK;
-}
-
-/** Called when eg an rx frame is received from the dongle */
-int dhd_wlfc_save_rxpath_ac_time(dhd_pub_t * dhd, uint8 prio)
-{
-	athost_wl_status_info_t* wlfc;
-	int rx_path_ac = -1;
-
-	if ((dhd == NULL) || (prio >= NUMPRIO)) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if (!dhd->wlfc_rxpkt_chk) {
-		dhd_os_wlfc_unblock(dhd);
-		return BCME_OK;
-	}
-
-	if (!dhd->wlfc_state || (dhd->proptxstatus_mode == WLFC_FCMODE_NONE)) {
-		dhd_os_wlfc_unblock(dhd);
-		return WLFC_UNSUPPORTED;
-	}
-
-	wlfc = (athost_wl_status_info_t*)dhd->wlfc_state;
-
-	rx_path_ac = prio2fifo[prio];
-	wlfc->rx_timestamp[rx_path_ac] = OSL_SYSUPTIME();
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** called via an IOVAR */
-int dhd_wlfc_get_module_ignore(dhd_pub_t *dhd, int *val)
-{
-	if (!dhd || !val) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	*val = dhd->proptxstatus_module_ignore;
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** called via an IOVAR */
-int dhd_wlfc_set_module_ignore(dhd_pub_t *dhd, int val)
-{
-	uint32 tlv = 0;
-	bool bChanged = FALSE;
-
-	if (!dhd) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	if ((bool)val != dhd->proptxstatus_module_ignore) {
-		dhd->proptxstatus_module_ignore = (val != 0);
-		/* force txstatus_ignore sync with proptxstatus_module_ignore */
-		dhd->proptxstatus_txstatus_ignore = dhd->proptxstatus_module_ignore;
-		if (FALSE == dhd->proptxstatus_module_ignore) {
-			tlv = WLFC_FLAGS_RSSI_SIGNALS |
-				WLFC_FLAGS_XONXOFF_SIGNALS |
-				WLFC_FLAGS_CREDIT_STATUS_SIGNALS |
-				WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE;
-		}
-		/* always enable host reorder */
-		tlv |= WLFC_FLAGS_HOST_RXRERODER_ACTIVE;
-		bChanged = TRUE;
-	}
-
-	dhd_os_wlfc_unblock(dhd);
-
-	if (bChanged) {
-		/* select enable proptxtstatus signaling */
-		if (dhd_wl_ioctl_set_intiovar(dhd, "tlv", tlv, WLC_SET_VAR, TRUE, 0)) {
-			DHD_ERROR(("%s: failed to set bdcv2 tlv signaling to 0x%x\n",
-				__FUNCTION__, tlv));
-		} else {
-			DHD_ERROR(("%s: successfully set bdcv2 tlv signaling to 0x%x\n",
-				__FUNCTION__, tlv));
-		}
-	}
-	return BCME_OK;
-}
-
-/** called via an IOVAR */
-int dhd_wlfc_get_credit_ignore(dhd_pub_t *dhd, int *val)
-{
-	if (!dhd || !val) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	*val = dhd->proptxstatus_credit_ignore;
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** called via an IOVAR */
-int dhd_wlfc_set_credit_ignore(dhd_pub_t *dhd, int val)
-{
-	if (!dhd) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	dhd->proptxstatus_credit_ignore = (val != 0);
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** called via an IOVAR */
-int dhd_wlfc_get_txstatus_ignore(dhd_pub_t *dhd, int *val)
-{
-	if (!dhd || !val) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	*val = dhd->proptxstatus_txstatus_ignore;
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** called via an IOVAR */
-int dhd_wlfc_set_txstatus_ignore(dhd_pub_t *dhd, int val)
-{
-	if (!dhd) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	dhd->proptxstatus_txstatus_ignore = (val != 0);
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** called via an IOVAR */
-int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val)
-{
-	if (!dhd || !val) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	*val = dhd->wlfc_rxpkt_chk;
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-/** called via an IOVAR */
-int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val)
-{
-	if (!dhd) {
-		DHD_ERROR(("Error: %s():%d\n", __FUNCTION__, __LINE__));
-		return BCME_BADARG;
-	}
-
-	dhd_os_wlfc_block(dhd);
-
-	dhd->wlfc_rxpkt_chk = (val != 0);
-
-	dhd_os_wlfc_unblock(dhd);
-
-	return BCME_OK;
-}
-
-#endif /* PROP_TXSTATUS */
diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.h b/drivers/net/wireless/bcmdhd/dhd_wlfc.h
deleted file mode 100644
index a6fd465..0000000
--- a/drivers/net/wireless/bcmdhd/dhd_wlfc.h
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhd_wlfc.h 557035 2015-05-15 18:48:57Z $
- *
- */
-#ifndef __wlfc_host_driver_definitions_h__
-#define __wlfc_host_driver_definitions_h__
-
-
-/* #define OOO_DEBUG */
-
-#define KERNEL_THREAD_RETURN_TYPE int
-
-typedef int (*f_commitpkt_t)(void* ctx, void* p);
-typedef bool (*f_processpkt_t)(void* p, void* arg);
-
-#define WLFC_UNSUPPORTED -9999
-
-#define WLFC_NO_TRAFFIC	-1
-#define WLFC_MULTI_TRAFFIC 0
-
-#define BUS_RETRIES 1	/* # of retries before aborting a bus tx operation */
-
-/** 16 bits will provide an absolute max of 65536 slots */
-#define WLFC_HANGER_MAXITEMS 3072
-
-#define WLFC_HANGER_ITEM_STATE_FREE			1
-#define WLFC_HANGER_ITEM_STATE_INUSE			2
-#define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED		3
-#define WLFC_HANGER_ITEM_STATE_FLUSHED			4
-
-#define WLFC_HANGER_PKT_STATE_TXSTATUS			1
-#define WLFC_HANGER_PKT_STATE_BUSRETURNED		2
-#define WLFC_HANGER_PKT_STATE_COMPLETE			\
-	(WLFC_HANGER_PKT_STATE_TXSTATUS | WLFC_HANGER_PKT_STATE_BUSRETURNED)
-
-typedef enum {
-	Q_TYPE_PSQ, /**< Power Save Queue, contains both delayed and suppressed packets */
-	Q_TYPE_AFQ  /**< At Firmware Queue */
-} q_type_t;
-
-typedef enum ewlfc_packet_state {
-	eWLFC_PKTTYPE_NEW,        /**< unused in the code (Jan 2015) */
-	eWLFC_PKTTYPE_DELAYED,    /**< packet did not enter wlfc yet */
-	eWLFC_PKTTYPE_SUPPRESSED, /**< packet entered wlfc and was suppressed by the dongle */
-	eWLFC_PKTTYPE_MAX
-} ewlfc_packet_state_t;
-
-typedef enum ewlfc_mac_entry_action {
-	eWLFC_MAC_ENTRY_ACTION_ADD,
-	eWLFC_MAC_ENTRY_ACTION_DEL,
-	eWLFC_MAC_ENTRY_ACTION_UPDATE,
-	eWLFC_MAC_ENTRY_ACTION_MAX
-} ewlfc_mac_entry_action_t;
-
-typedef struct wlfc_hanger_item {
-	uint8	state;
-	uint8   gen;
-	uint8	pkt_state;     /**< bitmask containing eg WLFC_HANGER_PKT_STATE_TXCOMPLETE */
-	uint8	pkt_txstatus;
-	uint32	identifier;
-	void*	pkt;
-#ifdef PROP_TXSTATUS_DEBUG
-	uint32	push_time;
-#endif
-	struct wlfc_hanger_item *next;
-} wlfc_hanger_item_t;
-
-/** hanger contains packets that have been posted by the dhd to the dongle and are expected back */
-typedef struct wlfc_hanger {
-	int max_items;
-	uint32 pushed;
-	uint32 popped;
-	uint32 failed_to_push;
-	uint32 failed_to_pop;
-	uint32 failed_slotfind;
-	uint32 slot_pos;
-	wlfc_hanger_item_t items[1];
-} wlfc_hanger_t;
-
-#define WLFC_HANGER_SIZE(n)	((sizeof(wlfc_hanger_t) - \
-	sizeof(wlfc_hanger_item_t)) + ((n)*sizeof(wlfc_hanger_item_t)))
-
-#define WLFC_STATE_OPEN		1	/**< remote MAC is able to receive packets */
-#define WLFC_STATE_CLOSE	2	/**< remote MAC is in power save mode */
-
-#define WLFC_PSQ_PREC_COUNT		((AC_COUNT + 1) * 2) /**< 2 for each AC traffic and bc/mc */
-#define WLFC_AFQ_PREC_COUNT		(AC_COUNT + 1)
-
-#define WLFC_PSQ_LEN			2048
-
-#define WLFC_FLOWCONTROL_HIWATER	(2048 - 256)
-#define WLFC_FLOWCONTROL_LOWATER	256
-
-#if (WLFC_FLOWCONTROL_HIWATER >= (WLFC_PSQ_LEN - 256))
-#undef WLFC_FLOWCONTROL_HIWATER
-#define WLFC_FLOWCONTROL_HIWATER	(WLFC_PSQ_LEN - 256)
-#undef WLFC_FLOWCONTROL_LOWATER
-#define WLFC_FLOWCONTROL_LOWATER	(WLFC_FLOWCONTROL_HIWATER / 4)
-#endif
-
-#define WLFC_LOG_BUF_SIZE		(1024*1024)
-
-/** Properties related to a remote MAC entity */
-typedef struct wlfc_mac_descriptor {
-	uint8 occupied;         /**< if 0, this descriptor is unused and thus can be (re)used */
-	uint8 interface_id;
-	uint8 iftype;           /**< eg WLC_E_IF_ROLE_STA */
-	uint8 state;            /**< eg WLFC_STATE_OPEN */
-	uint8 ac_bitmap;        /**< automatic power save delivery (APSD) */
-	uint8 requested_credit;
-	uint8 requested_packet; /**< unit: [number of packets] */
-	uint8 ea[ETHER_ADDR_LEN];
-
-	/** maintain (MAC,AC) based seq count for packets going to the device. As well as bc/mc. */
-	uint8 seq[AC_COUNT + 1];
-	uint8 generation;       /**< toggles between 0 and 1 */
-	struct pktq	psq;    /**< contains both 'delayed' and 'suppressed' packets */
-	/** packets at firmware queue */
-	struct pktq	afq;
-	/** The AC pending bitmap that was reported to the fw at last change */
-	uint8 traffic_lastreported_bmp;
-	/** The new AC pending bitmap */
-	uint8 traffic_pending_bmp;
-	/** 1= send on next opportunity */
-	uint8 send_tim_signal;
-	uint8 mac_handle;          /**< mac handles are assigned by the dongle */
-	/** Number of packets at dongle for this entry. */
-	int transit_count;
-	/** Number of suppression to wait before evict from delayQ */
-	int suppr_transit_count;
-	/** pkt sent to bus but no bus TX complete yet */
-	int onbus_pkts_count;
-	/** flag. TRUE when remote MAC is in suppressed state */
-	uint8 suppressed;
-
-
-#ifdef PROP_TXSTATUS_DEBUG
-	uint32 dstncredit_sent_packets;
-	uint32 dstncredit_acks;
-	uint32 opened_ct;
-	uint32 closed_ct;
-#endif
-	struct wlfc_mac_descriptor* prev;
-	struct wlfc_mac_descriptor* next;
-} wlfc_mac_descriptor_t;
-
-/** A 'commit' is the hand over of a packet from the host OS layer to the layer below (eg DBUS) */
-typedef struct dhd_wlfc_commit_info {
-	uint8					needs_hdr;
-	uint8					ac_fifo_credit_spent;
-	ewlfc_packet_state_t	pkt_type;
-	wlfc_mac_descriptor_t*	mac_entry;
-	void*					p;
-} dhd_wlfc_commit_info_t;
-
-#define WLFC_DECR_SEQCOUNT(entry, prec) do { if (entry->seq[(prec)] == 0) {\
-	entry->seq[prec] = 0xff; } else entry->seq[prec]--;} while (0)
-
-#define WLFC_INCR_SEQCOUNT(entry, prec) entry->seq[(prec)]++
-#define WLFC_SEQCOUNT(entry, prec) entry->seq[(prec)]
-
-typedef struct athost_wl_stat_counters {
-	uint32	pktin;
-	uint32	pktout;
-	uint32	pkt2bus;
-	uint32	pktdropped;
-	uint32	tlv_parse_failed;
-	uint32	rollback;
-	uint32	rollback_failed;
-	uint32	delayq_full_error;
-	uint32	credit_request_failed;
-	uint32	packet_request_failed;
-	uint32	mac_update_failed;
-	uint32	psmode_update_failed;
-	uint32	interface_update_failed;
-	uint32	wlfc_header_only_pkt;
-	uint32	txstatus_in;
-	uint32	d11_suppress;
-	uint32	wl_suppress;
-	uint32	bad_suppress;
-	uint32	pkt_freed;
-	uint32	pkt_free_err;
-	uint32	psq_wlsup_retx;
-	uint32	psq_wlsup_enq;
-	uint32	psq_d11sup_retx;
-	uint32	psq_d11sup_enq;
-	uint32	psq_hostq_retx;
-	uint32	psq_hostq_enq;
-	uint32	mac_handle_notfound;
-	uint32	wlc_tossed_pkts;
-	uint32	dhd_hdrpulls;
-	uint32	generic_error;
-	/* an extra one for bc/mc traffic */
-	uint32	send_pkts[AC_COUNT + 1];
-	uint32	drop_pkts[WLFC_PSQ_PREC_COUNT];
-	uint32	ooo_pkts[AC_COUNT + 1];
-#ifdef PROP_TXSTATUS_DEBUG
-	/** all pkt2bus -> txstatus latency accumulated */
-	uint32	latency_sample_count;
-	uint32	total_status_latency;
-	uint32	latency_most_recent;
-	int	idx_delta;
-	uint32	deltas[10];
-	uint32	fifo_credits_sent[6];
-	uint32	fifo_credits_back[6];
-	uint32	dropped_qfull[6];
-	uint32	signal_only_pkts_sent;
-	uint32	signal_only_pkts_freed;
-#endif
-	uint32	cleanup_txq_cnt;
-	uint32	cleanup_psq_cnt;
-	uint32	cleanup_fw_cnt;
-} athost_wl_stat_counters_t;
-
-#ifdef PROP_TXSTATUS_DEBUG
-#define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do { \
-	(ctx)->stats.fifo_credits_sent[(ac)]++;} while (0)
-#define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do { \
-	(ctx)->stats.fifo_credits_back[(ac)]++;} while (0)
-#define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do { \
-	(ctx)->stats.dropped_qfull[(ac)]++;} while (0)
-#else
-#define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do {} while (0)
-#define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do {} while (0)
-#define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do {} while (0)
-#endif
-
-#define WLFC_FCMODE_NONE				0
-#define WLFC_FCMODE_IMPLIED_CREDIT		1
-#define WLFC_FCMODE_EXPLICIT_CREDIT		2
-#define WLFC_ONLY_AMPDU_HOSTREORDER		3
-
-/** Reserved credits ratio when borrowed by hihger priority */
-#define WLFC_BORROW_LIMIT_RATIO		4
-
-/** How long to defer borrowing in milliseconds */
-#define WLFC_BORROW_DEFER_PERIOD_MS 100
-
-/** How long to defer flow control in milliseconds */
-#define WLFC_FC_DEFER_PERIOD_MS 200
-
-/** How long to detect occurance per AC in miliseconds */
-#define WLFC_RX_DETECTION_THRESHOLD_MS	100
-
-/** Mask to represent available ACs (note: BC/MC is ignored) */
-#define WLFC_AC_MASK 0xF
-
-/** flow control specific information, only 1 instance during driver lifetime */
-typedef struct athost_wl_status_info {
-	uint8	last_seqid_to_wlc;
-
-	/** OSL handle */
-	osl_t *osh;
-	/** dhd public struct pointer */
-	void *dhdp;
-
-	f_commitpkt_t fcommit;
-	void* commit_ctx;
-
-	/** statistics */
-	athost_wl_stat_counters_t stats;
-
-	/** incremented on eg receiving a credit map event from the dongle */
-	int		Init_FIFO_credit[AC_COUNT + 2];
-	/** the additional ones are for bc/mc and ATIM FIFO */
-	int		FIFO_credit[AC_COUNT + 2];
-	/** Credit borrow counts for each FIFO from each of the other FIFOs */
-	int		credits_borrowed[AC_COUNT + 2][AC_COUNT + 2];
-
-	/** packet hanger and MAC->handle lookup table */
-	void *hanger;
-
-	struct {
-		/** table for individual nodes */
-		wlfc_mac_descriptor_t	nodes[WLFC_MAC_DESC_TABLE_SIZE];
-		/** table for interfaces */
-		wlfc_mac_descriptor_t	interfaces[WLFC_MAX_IFNUM];
-		/* OS may send packets to unknown (unassociated) destinations */
-		/** A place holder for bc/mc and packets to unknown destinations */
-		wlfc_mac_descriptor_t	other;
-	} destination_entries;
-
-	wlfc_mac_descriptor_t *active_entry_head; /**< a chain of MAC descriptors */
-	int active_entry_count;
-
-	wlfc_mac_descriptor_t *requested_entry[WLFC_MAC_DESC_TABLE_SIZE];
-	int requested_entry_count;
-
-	/* pkt counts for each interface and ac */
-	int	pkt_cnt_in_q[WLFC_MAX_IFNUM][AC_COUNT+1];
-	int	pkt_cnt_per_ac[AC_COUNT+1];
-	int	pkt_cnt_in_drv[WLFC_MAX_IFNUM][AC_COUNT+1];
-	int	pkt_cnt_in_psq;
-	uint8	allow_fc;              /**< Boolean */
-	uint32  fc_defer_timestamp;
-	uint32	rx_timestamp[AC_COUNT+1];
-
-	/** ON/OFF state for flow control to the host network interface */
-	uint8	hostif_flow_state[WLFC_MAX_IFNUM];
-	uint8	host_ifidx;
-
-	/** to flow control an OS interface */
-	uint8	toggle_host_if;
-
-	/** To borrow credits */
-	uint8   allow_credit_borrow;
-
-	/** ac number for the first single ac traffic */
-	uint8	single_ac;
-
-	/** Timestamp for the first single ac traffic */
-	uint32  single_ac_timestamp;
-
-	bool	bcmc_credit_supported;
-
-} athost_wl_status_info_t;
-
-/** Please be mindful that total pkttag space is 32 octets only */
-typedef struct dhd_pkttag {
-
-#ifdef BCM_OBJECT_TRACE
-	/* if use this field, keep it at the first 4 bytes */
-	uint32 sn;
-#endif /* BCM_OBJECT_TRACE */
-
-	/**
-	b[15]  - 1 = wlfc packet
-	b[14:13]  - encryption exemption
-	b[12 ] - 1 = event channel
-	b[11 ] - 1 = this packet was sent in response to one time packet request,
-	do not increment credit on status for this one. [WLFC_CTL_TYPE_MAC_REQUEST_PACKET].
-	b[10 ] - 1 = signal-only-packet to firmware [i.e. nothing to piggyback on]
-	b[9  ] - 1 = packet is host->firmware (transmit direction)
-	       - 0 = packet received from firmware (firmware->host)
-	b[8  ] - 1 = packet was sent due to credit_request (pspoll),
-	             packet does not count against FIFO credit.
-	       - 0 = normal transaction, packet counts against FIFO credit
-	b[7  ] - 1 = AP, 0 = STA
-	b[6:4] - AC FIFO number
-	b[3:0] - interface index
-	*/
-	uint16	if_flags;
-
-	/**
-	 * destination MAC address for this packet so that not every module needs to open the packet
-	 * to find this
-	 */
-	uint8	dstn_ether[ETHER_ADDR_LEN];
-
-	/** This 32-bit goes from host to device for every packet. */
-	uint32	htod_tag;
-
-	/** This 16-bit is original seq number for every suppress packet. */
-	uint16	htod_seq;
-
-	/** This address is mac entry for every packet. */
-	void *entry;
-
-	/** bus specific stuff */
-	union {
-		struct {
-			void *stuff;
-			uint32 thing1;
-			uint32 thing2;
-		} sd;
-
-		struct {
-			void *bus;
-			void *urb;
-		} usb;
-	} bus_specific;
-} dhd_pkttag_t;
-
-#define DHD_PKTTAG_WLFCPKT_MASK			0x1
-#define DHD_PKTTAG_WLFCPKT_SHIFT		15
-#define DHD_PKTTAG_WLFCPKT_SET(tag, value)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & \
-	~(DHD_PKTTAG_WLFCPKT_MASK << DHD_PKTTAG_WLFCPKT_SHIFT)) | \
-	(((value) & DHD_PKTTAG_WLFCPKT_MASK) << DHD_PKTTAG_WLFCPKT_SHIFT)
-#define DHD_PKTTAG_WLFCPKT(tag)	((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_WLFCPKT_SHIFT) & DHD_PKTTAG_WLFCPKT_MASK)
-
-#define DHD_PKTTAG_EXEMPT_MASK			0x3
-#define DHD_PKTTAG_EXEMPT_SHIFT			13
-#define DHD_PKTTAG_EXEMPT_SET(tag, value)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & \
-	~(DHD_PKTTAG_EXEMPT_MASK << DHD_PKTTAG_EXEMPT_SHIFT)) | \
-	(((value) & DHD_PKTTAG_EXEMPT_MASK) << DHD_PKTTAG_EXEMPT_SHIFT)
-#define DHD_PKTTAG_EXEMPT(tag)	((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_EXEMPT_SHIFT) & DHD_PKTTAG_EXEMPT_MASK)
-
-#define DHD_PKTTAG_EVENT_MASK			0x1
-#define DHD_PKTTAG_EVENT_SHIFT			12
-#define DHD_PKTTAG_SETEVENT(tag, event)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & \
-	~(DHD_PKTTAG_EVENT_MASK << DHD_PKTTAG_EVENT_SHIFT)) | \
-	(((event) & DHD_PKTTAG_EVENT_MASK) << DHD_PKTTAG_EVENT_SHIFT)
-#define DHD_PKTTAG_EVENT(tag)	((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_EVENT_SHIFT) & DHD_PKTTAG_EVENT_MASK)
-
-#define DHD_PKTTAG_ONETIMEPKTRQST_MASK		0x1
-#define DHD_PKTTAG_ONETIMEPKTRQST_SHIFT		11
-#define DHD_PKTTAG_SETONETIMEPKTRQST(tag)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & \
-	~(DHD_PKTTAG_ONETIMEPKTRQST_MASK << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)) | \
-	(1 << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)
-#define DHD_PKTTAG_ONETIMEPKTRQST(tag)	((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_ONETIMEPKTRQST_SHIFT) & DHD_PKTTAG_ONETIMEPKTRQST_MASK)
-
-#define DHD_PKTTAG_SIGNALONLY_MASK		0x1
-#define DHD_PKTTAG_SIGNALONLY_SHIFT		10
-#define DHD_PKTTAG_SETSIGNALONLY(tag, signalonly)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & \
-	~(DHD_PKTTAG_SIGNALONLY_MASK << DHD_PKTTAG_SIGNALONLY_SHIFT)) | \
-	(((signalonly) & DHD_PKTTAG_SIGNALONLY_MASK) << DHD_PKTTAG_SIGNALONLY_SHIFT)
-#define DHD_PKTTAG_SIGNALONLY(tag)	((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_SIGNALONLY_SHIFT) & DHD_PKTTAG_SIGNALONLY_MASK)
-
-#define DHD_PKTTAG_PKTDIR_MASK			0x1
-#define DHD_PKTTAG_PKTDIR_SHIFT			9
-#define DHD_PKTTAG_SETPKTDIR(tag, dir)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & \
-	~(DHD_PKTTAG_PKTDIR_MASK << DHD_PKTTAG_PKTDIR_SHIFT)) | \
-	(((dir) & DHD_PKTTAG_PKTDIR_MASK) << DHD_PKTTAG_PKTDIR_SHIFT)
-#define DHD_PKTTAG_PKTDIR(tag)	((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_PKTDIR_SHIFT) & DHD_PKTTAG_PKTDIR_MASK)
-
-#define DHD_PKTTAG_CREDITCHECK_MASK		0x1
-#define DHD_PKTTAG_CREDITCHECK_SHIFT		8
-#define DHD_PKTTAG_SETCREDITCHECK(tag, check)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & \
-	~(DHD_PKTTAG_CREDITCHECK_MASK << DHD_PKTTAG_CREDITCHECK_SHIFT)) | \
-	(((check) & DHD_PKTTAG_CREDITCHECK_MASK) << DHD_PKTTAG_CREDITCHECK_SHIFT)
-#define DHD_PKTTAG_CREDITCHECK(tag)	((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_CREDITCHECK_SHIFT) & DHD_PKTTAG_CREDITCHECK_MASK)
-
-#define DHD_PKTTAG_IFTYPE_MASK			0x1
-#define DHD_PKTTAG_IFTYPE_SHIFT			7
-#define DHD_PKTTAG_SETIFTYPE(tag, isAP)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & \
-	~(DHD_PKTTAG_IFTYPE_MASK << DHD_PKTTAG_IFTYPE_SHIFT)) | \
-	(((isAP) & DHD_PKTTAG_IFTYPE_MASK) << DHD_PKTTAG_IFTYPE_SHIFT)
-#define DHD_PKTTAG_IFTYPE(tag)	((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_IFTYPE_SHIFT) & DHD_PKTTAG_IFTYPE_MASK)
-
-#define DHD_PKTTAG_FIFO_MASK			0x7
-#define DHD_PKTTAG_FIFO_SHIFT			4
-#define DHD_PKTTAG_SETFIFO(tag, fifo)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_FIFO_MASK << DHD_PKTTAG_FIFO_SHIFT)) | \
-	(((fifo) & DHD_PKTTAG_FIFO_MASK) << DHD_PKTTAG_FIFO_SHIFT)
-#define DHD_PKTTAG_FIFO(tag)		((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_FIFO_SHIFT) & DHD_PKTTAG_FIFO_MASK)
-
-#define DHD_PKTTAG_IF_MASK			0xf
-#define DHD_PKTTAG_IF_SHIFT			0
-#define DHD_PKTTAG_SETIF(tag, if)	((dhd_pkttag_t*)(tag))->if_flags = \
-	(((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_IF_MASK << DHD_PKTTAG_IF_SHIFT)) | \
-	(((if) & DHD_PKTTAG_IF_MASK) << DHD_PKTTAG_IF_SHIFT)
-#define DHD_PKTTAG_IF(tag)		((((dhd_pkttag_t*)(tag))->if_flags >> \
-	DHD_PKTTAG_IF_SHIFT) & DHD_PKTTAG_IF_MASK)
-
-#define DHD_PKTTAG_SETDSTN(tag, dstn_MAC_ea)	memcpy(((dhd_pkttag_t*)((tag)))->dstn_ether, \
-	(dstn_MAC_ea), ETHER_ADDR_LEN)
-#define DHD_PKTTAG_DSTN(tag)	((dhd_pkttag_t*)(tag))->dstn_ether
-
-#define DHD_PKTTAG_SET_H2DTAG(tag, h2dvalue)	((dhd_pkttag_t*)(tag))->htod_tag = (h2dvalue)
-#define DHD_PKTTAG_H2DTAG(tag)			(((dhd_pkttag_t*)(tag))->htod_tag)
-
-#define DHD_PKTTAG_SET_H2DSEQ(tag, seq)		((dhd_pkttag_t*)(tag))->htod_seq = (seq)
-#define DHD_PKTTAG_H2DSEQ(tag)			(((dhd_pkttag_t*)(tag))->htod_seq)
-
-#define DHD_PKTTAG_SET_ENTRY(tag, entry)	((dhd_pkttag_t*)(tag))->entry = (entry)
-#define DHD_PKTTAG_ENTRY(tag)			(((dhd_pkttag_t*)(tag))->entry)
-
-#define PSQ_SUP_IDX(x) (x * 2 + 1)
-#define PSQ_DLY_IDX(x) (x * 2)
-
-#ifdef PROP_TXSTATUS_DEBUG
-#define DHD_WLFC_CTRINC_MAC_CLOSE(entry)	do { (entry)->closed_ct++; } while (0)
-#define DHD_WLFC_CTRINC_MAC_OPEN(entry)		do { (entry)->opened_ct++; } while (0)
-#else
-#define DHD_WLFC_CTRINC_MAC_CLOSE(entry)	do {} while (0)
-#define DHD_WLFC_CTRINC_MAC_OPEN(entry)		do {} while (0)
-#endif
-
-#ifdef BCM_OBJECT_TRACE
-#define DHD_PKTTAG_SET_SN(tag, val)		((dhd_pkttag_t*)(tag))->sn = (val)
-#define DHD_PKTTAG_SN(tag)			(((dhd_pkttag_t*)(tag))->sn)
-#endif /* BCM_OBJECT_TRACE */
-
-/* public functions */
-int dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len,
-	uchar *reorder_info_buf, uint *reorder_info_len);
-KERNEL_THREAD_RETURN_TYPE dhd_wlfc_transfer_packets(void *data);
-int dhd_wlfc_commit_packets(dhd_pub_t *dhdp, f_commitpkt_t fcommit,
-	void* commit_ctx, void *pktbuf, bool need_toggle_host_if);
-int dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success);
-int dhd_wlfc_init(dhd_pub_t *dhd);
-#ifdef SUPPORT_P2P_GO_PS
-int dhd_wlfc_suspend(dhd_pub_t *dhd);
-int dhd_wlfc_resume(dhd_pub_t *dhd);
-#endif /* SUPPORT_P2P_GO_PS */
-int dhd_wlfc_hostreorder_init(dhd_pub_t *dhd);
-int dhd_wlfc_cleanup_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg);
-int dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void* arg);
-int dhd_wlfc_deinit(dhd_pub_t *dhd);
-int dhd_wlfc_interface_event(dhd_pub_t *dhdp, uint8 action, uint8 ifid, uint8 iftype, uint8* ea);
-int dhd_wlfc_FIFOcreditmap_event(dhd_pub_t *dhdp, uint8* event_data);
-int dhd_wlfc_BCMCCredit_support_event(dhd_pub_t *dhdp);
-int dhd_wlfc_enable(dhd_pub_t *dhdp);
-int dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
-int dhd_wlfc_clear_counts(dhd_pub_t *dhd);
-int dhd_wlfc_get_enable(dhd_pub_t *dhd, bool *val);
-int dhd_wlfc_get_mode(dhd_pub_t *dhd, int *val);
-int dhd_wlfc_set_mode(dhd_pub_t *dhd, int val);
-bool dhd_wlfc_is_supported(dhd_pub_t *dhd);
-bool dhd_wlfc_is_header_only_pkt(dhd_pub_t * dhd, void *pktbuf);
-int dhd_wlfc_flowcontrol(dhd_pub_t *dhdp, bool state, bool bAcquireLock);
-int dhd_wlfc_save_rxpath_ac_time(dhd_pub_t * dhd, uint8 prio);
-
-int dhd_wlfc_get_module_ignore(dhd_pub_t *dhd, int *val);
-int dhd_wlfc_set_module_ignore(dhd_pub_t *dhd, int val);
-int dhd_wlfc_get_credit_ignore(dhd_pub_t *dhd, int *val);
-int dhd_wlfc_set_credit_ignore(dhd_pub_t *dhd, int val);
-int dhd_wlfc_get_txstatus_ignore(dhd_pub_t *dhd, int *val);
-int dhd_wlfc_set_txstatus_ignore(dhd_pub_t *dhd, int val);
-
-int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val);
-int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val);
-
-#endif /* __wlfc_host_driver_definitions_h__ */
diff --git a/drivers/net/wireless/bcmdhd/dngl_stats.h b/drivers/net/wireless/bcmdhd/dngl_stats.h
deleted file mode 100644
index 66e4f45..0000000
--- a/drivers/net/wireless/bcmdhd/dngl_stats.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Common stats definitions for clients of dongle
- * ports
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dngl_stats.h 523030 2014-12-25 17:28:07Z $
- */
-
-#ifndef _dngl_stats_h_
-#define _dngl_stats_h_
-
-#include <proto/ethernet.h>
-#include <proto/802.11.h>
-
-typedef struct {
-	unsigned long	rx_packets;		/* total packets received */
-	unsigned long	tx_packets;		/* total packets transmitted */
-	unsigned long	rx_bytes;		/* total bytes received */
-	unsigned long	tx_bytes;		/* total bytes transmitted */
-	unsigned long	rx_errors;		/* bad packets received */
-	unsigned long	tx_errors;		/* packet transmit problems */
-	unsigned long	rx_dropped;		/* packets dropped by dongle */
-	unsigned long	tx_dropped;		/* packets dropped by dongle */
-	unsigned long   multicast;      /* multicast packets received */
-} dngl_stats_t;
-
-typedef int32 wifi_radio;
-typedef int32 wifi_channel;
-typedef int32 wifi_rssi;
-typedef struct { uint16 version; uint16 length; } ver_len;
-
-typedef enum wifi_channel_width {
-	WIFI_CHAN_WIDTH_20	  = 0,
-	WIFI_CHAN_WIDTH_40	  = 1,
-	WIFI_CHAN_WIDTH_80	  = 2,
-	WIFI_CHAN_WIDTH_160   = 3,
-	WIFI_CHAN_WIDTH_80P80 = 4,
-	WIFI_CHAN_WIDTH_5	  = 5,
-	WIFI_CHAN_WIDTH_10	  = 6,
-	WIFI_CHAN_WIDTH_INVALID = -1
-} wifi_channel_width_t;
-
-typedef enum {
-	WIFI_DISCONNECTED = 0,
-	WIFI_AUTHENTICATING = 1,
-	WIFI_ASSOCIATING = 2,
-	WIFI_ASSOCIATED = 3,
-	WIFI_EAPOL_STARTED = 4,   /* if done by firmware/driver */
-	WIFI_EAPOL_COMPLETED = 5, /* if done by firmware/driver */
-} wifi_connection_state;
-
-typedef enum {
-	WIFI_ROAMING_IDLE = 0,
-	WIFI_ROAMING_ACTIVE = 1
-} wifi_roam_state;
-
-typedef enum {
-	WIFI_INTERFACE_STA = 0,
-	WIFI_INTERFACE_SOFTAP = 1,
-	WIFI_INTERFACE_IBSS = 2,
-	WIFI_INTERFACE_P2P_CLIENT = 3,
-	WIFI_INTERFACE_P2P_GO = 4,
-	WIFI_INTERFACE_NAN = 5,
-	WIFI_INTERFACE_MESH = 6
-} wifi_interface_mode;
-
-#define WIFI_CAPABILITY_QOS          0x00000001     /* set for QOS association */
-#define WIFI_CAPABILITY_PROTECTED    0x00000002     /* set for protected association (802.11
-						     * beacon frame control protected bit set)
-						     */
-#define WIFI_CAPABILITY_INTERWORKING 0x00000004     /* set if 802.11 Extended Capabilities
-						     * element interworking bit is set
-						     */
-#define WIFI_CAPABILITY_HS20         0x00000008     /* set for HS20 association */
-#define WIFI_CAPABILITY_SSID_UTF8    0x00000010     /* set is 802.11 Extended Capabilities
-						     * element UTF-8 SSID bit is set
-						     */
-#define WIFI_CAPABILITY_COUNTRY      0x00000020     /* set is 802.11 Country Element is present */
-
-typedef struct {
-	wifi_interface_mode mode;     /* interface mode */
-	uint8 mac_addr[6];               /* interface mac address (self) */
-	wifi_connection_state state;  /* connection state (valid for STA, CLI only) */
-	wifi_roam_state roaming;      /* roaming state */
-	uint32 capabilities;             /* WIFI_CAPABILITY_XXX (self) */
-	uint8 ssid[DOT11_MAX_SSID_LEN+1]; /* null terminated SSID */
-	uint8 bssid[ETHER_ADDR_LEN];     /* bssid */
-	uint8 ap_country_str[3];         /* country string advertised by AP */
-	uint8 country_str[3];            /* country string for this association */
-} wifi_interface_info;
-
-typedef wifi_interface_info *wifi_interface_handle;
-
-/* channel information */
-typedef struct {
-	wifi_channel_width_t width;   /* channel width (20, 40, 80, 80+80, 160) */
-	wifi_channel center_freq;   /* primary 20 MHz channel */
-	wifi_channel center_freq0;  /* center frequency (MHz) first segment */
-	wifi_channel center_freq1;  /* center frequency (MHz) second segment */
-} wifi_channel_info;
-
-/* wifi rate */
-typedef struct {
-	uint32 preamble;   /* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
-	uint32 nss;   	/* 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
-	uint32 bw;   	/* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
-	uint32 rateMcsIdx; /* OFDM/CCK rate code would be as per ieee std
-			    * in the units of 0.5mbps
-			    */
-			/* HT/VHT it would be mcs index */
-	uint32 reserved;   /* reserved */
-	uint32 bitrate;    /* units of 100 Kbps */
-} wifi_rate;
-
-/* channel statistics */
-typedef struct {
-	wifi_channel_info channel;  /* channel */
-	uint32 on_time;         	/* msecs the radio is awake (32 bits number
-				         * accruing over time)
-					 */
-	uint32 cca_busy_time;          /* msecs the CCA register is busy (32 bits number
-					* accruing over time)
-					*/
-} wifi_channel_stat;
-
-/* radio statistics */
-typedef struct {
-	struct {
-		uint16 version;
-		uint16 length;
-	};
-	wifi_radio radio;               /* wifi radio (if multiple radio supported) */
-	uint32 on_time;                    /* msecs the radio is awake (32 bits number
-					    * accruing over time)
-					    */
-	uint32 tx_time;                    /* msecs the radio is transmitting (32 bits
-					    * number accruing over time)
-					    */
-	uint32 rx_time;                    /* msecs the radio is in active receive (32 bits
-					    * number accruing over time)
-					    */
-	uint32 on_time_scan;               /* msecs the radio is awake due to all scan (32 bits
-					    * number accruing over time)
-					    */
-	uint32 on_time_nbd;                /* msecs the radio is awake due to NAN (32 bits
-					    * number accruing over time)
-					    */
-	uint32 on_time_gscan;              /* msecs the radio is awake due to G?scan (32 bits
-					    * number accruing over time)
-					    */
-	uint32 on_time_roam_scan;          /* msecs the radio is awake due to roam?scan (32 bits
-					    * number accruing over time)
-					    */
-	uint32 on_time_pno_scan;           /* msecs the radio is awake due to PNO scan (32 bits
-					    * number accruing over time)
-					    */
-	uint32 on_time_hs20;               /* msecs the radio is awake due to HS2.0 scans and
-					    * GAS exchange (32 bits number accruing over time)
-					    */
-	uint32 num_channels;               /* number of channels */
-	wifi_channel_stat channels[1];   /* channel statistics */
-} wifi_radio_stat;
-
-/* per rate statistics */
-typedef struct {
-	struct {
-		uint16 version;
-		uint16 length;
-	};
-	uint32 tx_mpdu;        /* number of successfully transmitted data pkts (ACK rcvd) */
-	uint32 rx_mpdu;        /* number of received data pkts */
-	uint32 mpdu_lost;      /* number of data packet losses (no ACK) */
-	uint32 retries;        /* total number of data pkt retries */
-	uint32 retries_short;  /* number of short data pkt retries */
-	uint32 retries_long;   /* number of long data pkt retries */
-	wifi_rate rate;     /* rate information */
-} wifi_rate_stat;
-
-/* access categories */
-typedef enum {
-	WIFI_AC_VO  = 0,
-	WIFI_AC_VI  = 1,
-	WIFI_AC_BE  = 2,
-	WIFI_AC_BK  = 3,
-	WIFI_AC_MAX = 4
-} wifi_traffic_ac;
-
-/* wifi peer type */
-typedef enum
-{
-	WIFI_PEER_STA,
-	WIFI_PEER_AP,
-	WIFI_PEER_P2P_GO,
-	WIFI_PEER_P2P_CLIENT,
-	WIFI_PEER_NAN,
-	WIFI_PEER_TDLS,
-	WIFI_PEER_INVALID
-} wifi_peer_type;
-
-/* per peer statistics */
-typedef struct {
-	wifi_peer_type type;           /* peer type (AP, TDLS, GO etc.) */
-	uint8 peer_mac_address[6];        /* mac address */
-	uint32 capabilities;              /* peer WIFI_CAPABILITY_XXX */
-	uint32 num_rate;                  /* number of rates */
-	wifi_rate_stat rate_stats[1];   /* per rate statistics, number of entries  = num_rate */
-} wifi_peer_info;
-
-/* per access category statistics */
-typedef struct {
-	wifi_traffic_ac ac;             /* access category (VI, VO, BE, BK) */
-	uint32 tx_mpdu;                    /* number of successfully transmitted unicast data pkts
-					    * (ACK rcvd)
-					    */
-	uint32 rx_mpdu;                    /* number of received unicast mpdus */
-	uint32 tx_mcast;                   /* number of succesfully transmitted multicast
-					    * data packets
-					    */
-					   /* STA case: implies ACK received from AP for the
-					    * unicast packet in which mcast pkt was sent
-					    */
-	uint32 rx_mcast;                   /* number of received multicast data packets */
-	uint32 rx_ampdu;                   /* number of received unicast a-mpdus */
-	uint32 tx_ampdu;                   /* number of transmitted unicast a-mpdus */
-	uint32 mpdu_lost;                  /* number of data pkt losses (no ACK) */
-	uint32 retries;                    /* total number of data pkt retries */
-	uint32 retries_short;              /* number of short data pkt retries */
-	uint32 retries_long;               /* number of long data pkt retries */
-	uint32 contention_time_min;        /* data pkt min contention time (usecs) */
-	uint32 contention_time_max;        /* data pkt max contention time (usecs) */
-	uint32 contention_time_avg;        /* data pkt avg contention time (usecs) */
-	uint32 contention_num_samples;     /* num of data pkts used for contention statistics */
-} wifi_wmm_ac_stat;
-
-/* interface statistics */
-typedef struct {
-	wifi_interface_handle iface;          /* wifi interface */
-	wifi_interface_info info;             /* current state of the interface */
-	uint32 beacon_rx;                     /* access point beacon received count from
-					       * connected AP
-					       */
-	uint32 mgmt_rx;                       /* access point mgmt frames received count from
-					       * connected AP (including Beacon)
-					       */
-	uint32 mgmt_action_rx;                /* action frames received count */
-	uint32 mgmt_action_tx;                /* action frames transmit count */
-	wifi_rssi rssi_mgmt;                  /* access Point Beacon and Management frames RSSI
-					       * (averaged)
-					       */
-	wifi_rssi rssi_data;                  /* access Point Data Frames RSSI (averaged) from
-					       * connected AP
-					       */
-	wifi_rssi rssi_ack;                   /* access Point ACK RSSI (averaged) from
-					       * connected AP
-					       */
-	wifi_wmm_ac_stat ac[WIFI_AC_MAX];     /* per ac data packet statistics */
-	uint32 num_peers;                        /* number of peers */
-	wifi_peer_info peer_info[1];           /* per peer statistics */
-} wifi_iface_stat;
-
-#endif /* _dngl_stats_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dngl_wlhdr.h b/drivers/net/wireless/bcmdhd/dngl_wlhdr.h
deleted file mode 100644
index 93e0b5a..0000000
--- a/drivers/net/wireless/bcmdhd/dngl_wlhdr.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Dongle WL Header definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dngl_wlhdr.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef _dngl_wlhdr_h_
-#define _dngl_wlhdr_h_
-
-typedef struct wl_header {
-    uint8   type;           /* Header type */
-    uint8   version;        /* Header version */
-	int8	rssi;			/* RSSI */
-	uint8	pad;			/* Unused */
-} wl_header_t;
-
-#define WL_HEADER_LEN   sizeof(wl_header_t)
-#define WL_HEADER_TYPE  0
-#define WL_HEADER_VER   1
-#endif /* _dngl_wlhdr_h_ */
diff --git a/drivers/net/wireless/bcmdhd/hnd_pktpool.c b/drivers/net/wireless/bcmdhd/hnd_pktpool.c
deleted file mode 100644
index f3555e4..0000000
--- a/drivers/net/wireless/bcmdhd/hnd_pktpool.c
+++ /dev/null
@@ -1,1131 +0,0 @@
-/*
- * HND generic packet pool operation primitives
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hnd_pktpool.c 591285 2015-10-07 11:56:29Z $
- */
-
-#include <typedefs.h>
-#include <osl.h>
-#include <osl_ext.h>
-#include <bcmutils.h>
-#include <hnd_pktpool.h>
-
-/* mutex macros for thread safe */
-#ifdef HND_PKTPOOL_THREAD_SAFE
-#define HND_PKTPOOL_MUTEX_CREATE(name, mutex)	osl_ext_mutex_create(name, mutex)
-#define HND_PKTPOOL_MUTEX_DELETE(mutex)		osl_ext_mutex_delete(mutex)
-#define HND_PKTPOOL_MUTEX_ACQUIRE(mutex, msec)	osl_ext_mutex_acquire(mutex, msec)
-#define HND_PKTPOOL_MUTEX_RELEASE(mutex)	osl_ext_mutex_release(mutex)
-#else
-#define HND_PKTPOOL_MUTEX_CREATE(name, mutex)	OSL_EXT_SUCCESS
-#define HND_PKTPOOL_MUTEX_DELETE(mutex)		OSL_EXT_SUCCESS
-#define HND_PKTPOOL_MUTEX_ACQUIRE(mutex, msec)	OSL_EXT_SUCCESS
-#define HND_PKTPOOL_MUTEX_RELEASE(mutex)	OSL_EXT_SUCCESS
-#endif
-
-/* Registry size is one larger than max pools, as slot #0 is reserved */
-#define PKTPOOLREG_RSVD_ID				(0U)
-#define PKTPOOLREG_RSVD_PTR				(POOLPTR(0xdeaddead))
-#define PKTPOOLREG_FREE_PTR				(POOLPTR(NULL))
-
-#define PKTPOOL_REGISTRY_SET(id, pp)	(pktpool_registry_set((id), (pp)))
-#define PKTPOOL_REGISTRY_CMP(id, pp)	(pktpool_registry_cmp((id), (pp)))
-
-/* Tag a registry entry as free for use */
-#define PKTPOOL_REGISTRY_CLR(id)		\
-		PKTPOOL_REGISTRY_SET((id), PKTPOOLREG_FREE_PTR)
-#define PKTPOOL_REGISTRY_ISCLR(id)		\
-		(PKTPOOL_REGISTRY_CMP((id), PKTPOOLREG_FREE_PTR))
-
-/* Tag registry entry 0 as reserved */
-#define PKTPOOL_REGISTRY_RSV()			\
-		PKTPOOL_REGISTRY_SET(PKTPOOLREG_RSVD_ID, PKTPOOLREG_RSVD_PTR)
-#define PKTPOOL_REGISTRY_ISRSVD()		\
-		(PKTPOOL_REGISTRY_CMP(PKTPOOLREG_RSVD_ID, PKTPOOLREG_RSVD_PTR))
-
-/* Walk all un-reserved entries in registry */
-#define PKTPOOL_REGISTRY_FOREACH(id)	\
-		for ((id) = 1U; (id) <= pktpools_max; (id)++)
-
-enum pktpool_empty_cb_state {
-	EMPTYCB_ENABLED = 0,	/* Enable callback when new packets are added to pool */
-	EMPTYCB_DISABLED,	/* Disable callback when new packets are added to pool */
-	EMPTYCB_SKIPPED		/* Packet was added to pool when callback was disabled */
-};
-
-uint32 pktpools_max = 0U; /* maximum number of pools that may be initialized */
-pktpool_t *pktpools_registry[PKTPOOL_MAXIMUM_ID + 1]; /* Pktpool registry */
-
-/* Register/Deregister a pktpool with registry during pktpool_init/deinit */
-static int pktpool_register(pktpool_t * poolptr);
-static int pktpool_deregister(pktpool_t * poolptr);
-
-/** add declaration */
-static int pktpool_avail_notify(pktpool_t *pktp);
-
-/** accessor functions required when ROMming this file, forced into RAM */
-
-
-pktpool_t *
-BCMRAMFN(get_pktpools_registry)(int id)
-{
-	return pktpools_registry[id];
-}
-
-static void
-BCMRAMFN(pktpool_registry_set)(int id, pktpool_t *pp)
-{
-	pktpools_registry[id] = pp;
-}
-
-static bool
-BCMRAMFN(pktpool_registry_cmp)(int id, pktpool_t *pp)
-{
-	return pktpools_registry[id] == pp;
-}
-
-int /* Construct a pool registry to serve a maximum of total_pools */
-pktpool_attach(osl_t *osh, uint32 total_pools)
-{
-	uint32 poolid;
-
-	if (pktpools_max != 0U) {
-		return BCME_ERROR;
-	}
-
-	ASSERT(total_pools <= PKTPOOL_MAXIMUM_ID);
-
-	/* Initialize registry: reserve slot#0 and tag others as free */
-	PKTPOOL_REGISTRY_RSV();		/* reserve slot#0 */
-
-	PKTPOOL_REGISTRY_FOREACH(poolid) {	/* tag all unreserved entries as free */
-		PKTPOOL_REGISTRY_CLR(poolid);
-	}
-
-	pktpools_max = total_pools;
-
-	return (int)pktpools_max;
-}
-
-int /* Destruct the pool registry. Ascertain all pools were first de-inited */
-pktpool_dettach(osl_t *osh)
-{
-	uint32 poolid;
-
-	if (pktpools_max == 0U) {
-		return BCME_OK;
-	}
-
-	/* Ascertain that no pools are still registered */
-	ASSERT(PKTPOOL_REGISTRY_ISRSVD()); /* assert reserved slot */
-
-	PKTPOOL_REGISTRY_FOREACH(poolid) {	/* ascertain all others are free */
-		ASSERT(PKTPOOL_REGISTRY_ISCLR(poolid));
-	}
-
-	pktpools_max = 0U; /* restore boot state */
-
-	return BCME_OK;
-}
-
-static int	/* Register a pool in a free slot; return the registry slot index */
-pktpool_register(pktpool_t * poolptr)
-{
-	uint32 poolid;
-
-	if (pktpools_max == 0U) {
-		return PKTPOOL_INVALID_ID; /* registry has not yet been constructed */
-	}
-
-	ASSERT(pktpools_max != 0U);
-
-	/* find an empty slot in pktpools_registry */
-	PKTPOOL_REGISTRY_FOREACH(poolid) {
-		if (PKTPOOL_REGISTRY_ISCLR(poolid)) {
-			PKTPOOL_REGISTRY_SET(poolid, POOLPTR(poolptr)); /* register pool */
-			return (int)poolid; /* return pool ID */
-		}
-	} /* FOREACH */
-
-	return PKTPOOL_INVALID_ID;	/* error: registry is full */
-}
-
-static int	/* Deregister a pktpool, given the pool pointer; tag slot as free */
-pktpool_deregister(pktpool_t * poolptr)
-{
-	uint32 poolid;
-
-	ASSERT(POOLPTR(poolptr) != POOLPTR(NULL));
-
-	poolid = POOLID(poolptr);
-	ASSERT(poolid <= pktpools_max);
-
-	/* Asertain that a previously registered poolptr is being de-registered */
-	if (PKTPOOL_REGISTRY_CMP(poolid, POOLPTR(poolptr))) {
-		PKTPOOL_REGISTRY_CLR(poolid); /* mark as free */
-	} else {
-		ASSERT(0);
-		return BCME_ERROR; /* mismatch in registry */
-	}
-
-	return BCME_OK;
-}
-
-
-/*
- * pktpool_init:
- * User provides a pktpool_t sturcture and specifies the number of packets to
- * be pre-filled into the pool (pplen). The size of all packets in a pool must
- * be the same and is specified by plen.
- * pktpool_init first attempts to register the pool and fetch a unique poolid.
- * If registration fails, it is considered an BCME_ERR, caused by either the
- * registry was not pre-created (pktpool_attach) or the registry is full.
- * If registration succeeds, then the requested number of packets will be filled
- * into the pool as part of initialization. In the event that there is no
- * available memory to service the request, then BCME_NOMEM will be returned
- * along with the count of how many packets were successfully allocated.
- * In dongle builds, prior to memory reclaimation, one should limit the number
- * of packets to be allocated during pktpool_init and fill the pool up after
- * reclaim stage.
- */
-int
-pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx, uint8 type)
-{
-	int i, err = BCME_OK;
-	int pktplen;
-	uint8 pktp_id;
-
-	ASSERT(pktp != NULL);
-	ASSERT(osh != NULL);
-	ASSERT(pplen != NULL);
-
-	pktplen = *pplen;
-
-	bzero(pktp, sizeof(pktpool_t));
-
-	/* assign a unique pktpool id */
-	if ((pktp_id = (uint8) pktpool_register(pktp)) == PKTPOOL_INVALID_ID) {
-		return BCME_ERROR;
-	}
-	POOLSETID(pktp, pktp_id);
-
-	pktp->inited = TRUE;
-	pktp->istx = istx ? TRUE : FALSE;
-	pktp->plen = (uint16)plen;
-	pktp->type = type;
-
-	if (HND_PKTPOOL_MUTEX_CREATE("pktpool", &pktp->mutex) != OSL_EXT_SUCCESS) {
-		return BCME_ERROR;
-	}
-
-	pktp->maxlen = PKTPOOL_LEN_MAX;
-	pktplen = LIMIT_TO_MAX(pktplen, pktp->maxlen);
-
-	for (i = 0; i < pktplen; i++) {
-		void *p;
-		p = PKTGET(osh, plen, TRUE);
-
-		if (p == NULL) {
-			/* Not able to allocate all requested pkts
-			 * so just return what was actually allocated
-			 * We can add to the pool later
-			 */
-			if (pktp->freelist == NULL) /* pktpool free list is empty */
-				err = BCME_NOMEM;
-
-			goto exit;
-		}
-
-		PKTSETPOOL(osh, p, TRUE, pktp); /* Tag packet with pool ID */
-
-		PKTSETFREELIST(p, pktp->freelist); /* insert p at head of free list */
-		pktp->freelist = p;
-
-		pktp->avail++;
-
-#ifdef BCMDBG_POOL
-		pktp->dbg_q[pktp->dbg_qlen++].p = p;
-#endif
-	}
-
-exit:
-	pktp->len = pktp->avail;
-
-	*pplen = pktp->len;
-	return err;
-}
-
-/*
- * pktpool_deinit:
- * Prior to freeing a pktpool, all packets must be first freed into the pktpool.
- * Upon pktpool_deinit, all packets in the free pool will be freed to the heap.
- * An assert is in place to ensure that there are no packets still lingering
- * around. Packets freed to a pool after the deinit will cause a memory
- * corruption as the pktpool_t structure no longer exists.
- */
-int
-pktpool_deinit(osl_t *osh, pktpool_t *pktp)
-{
-	uint16 freed = 0;
-
-	ASSERT(osh != NULL);
-	ASSERT(pktp != NULL);
-
-#ifdef BCMDBG_POOL
-	{
-		int i;
-		for (i = 0; i <= pktp->len; i++) {
-			pktp->dbg_q[i].p = NULL;
-		}
-	}
-#endif
-
-	while (pktp->freelist != NULL) {
-		void * p = pktp->freelist;
-
-		pktp->freelist = PKTFREELIST(p); /* unlink head packet from free list */
-		PKTSETFREELIST(p, NULL);
-
-		PKTSETPOOL(osh, p, FALSE, NULL); /* clear pool ID tag in pkt */
-
-		PKTFREE(osh, p, pktp->istx); /* free the packet */
-
-		freed++;
-		ASSERT(freed <= pktp->len);
-	}
-
-	pktp->avail -= freed;
-	ASSERT(pktp->avail == 0);
-
-	pktp->len -= freed;
-
-	pktpool_deregister(pktp); /* release previously acquired unique pool id */
-	POOLSETID(pktp, PKTPOOL_INVALID_ID);
-
-	if (HND_PKTPOOL_MUTEX_DELETE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	pktp->inited = FALSE;
-
-	/* Are there still pending pkts? */
-	ASSERT(pktp->len == 0);
-
-	return 0;
-}
-
-int
-pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal)
-{
-	void *p;
-	int err = 0;
-	int len, psize, maxlen;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	ASSERT(pktp->plen != 0);
-
-	maxlen = pktp->maxlen;
-	psize = minimal ? (maxlen >> 2) : maxlen;
-	for (len = (int)pktp->len; len < psize; len++) {
-
-		p = PKTGET(osh, pktp->len, TRUE);
-
-		if (p == NULL) {
-			err = BCME_NOMEM;
-			break;
-		}
-
-		if (pktpool_add(pktp, p) != BCME_OK) {
-			PKTFREE(osh, p, FALSE);
-			err = BCME_ERROR;
-			break;
-		}
-	}
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	if (pktp->cbcnt) {
-		if (pktp->empty == FALSE)
-			pktpool_avail_notify(pktp);
-	}
-
-	return err;
-}
-
-static void *
-pktpool_deq(pktpool_t *pktp)
-{
-	void *p = NULL;
-
-	if (pktp->avail == 0)
-		return NULL;
-
-	ASSERT(pktp->freelist != NULL);
-
-	p = pktp->freelist;  /* dequeue packet from head of pktpool free list */
-	pktp->freelist = PKTFREELIST(p); /* free list points to next packet */
-	PKTSETFREELIST(p, NULL);
-
-	pktp->avail--;
-
-	return p;
-}
-
-static void
-pktpool_enq(pktpool_t *pktp, void *p)
-{
-	ASSERT(p != NULL);
-
-	PKTSETFREELIST(p, pktp->freelist); /* insert at head of pktpool free list */
-	pktp->freelist = p; /* free list points to newly inserted packet */
-
-	pktp->avail++;
-	ASSERT(pktp->avail <= pktp->len);
-}
-
-/* utility for registering host addr fill function called from pciedev */
-int
-/* BCMATTACHFN */
-(pktpool_hostaddr_fill_register)(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg)
-{
-
-	ASSERT(cb != NULL);
-
-	ASSERT(pktp->cbext.cb == NULL);
-	pktp->cbext.cb = cb;
-	pktp->cbext.arg = arg;
-	return 0;
-}
-
-int
-pktpool_rxcplid_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg)
-{
-
-	ASSERT(cb != NULL);
-
-	if (pktp == NULL)
-		return BCME_ERROR;
-	ASSERT(pktp->rxcplidfn.cb == NULL);
-	pktp->rxcplidfn.cb = cb;
-	pktp->rxcplidfn.arg = arg;
-	return 0;
-}
-/* Callback functions for split rx modes */
-/* when evr host posts rxbuffer, invike dma_rxfill from pciedev layer */
-void
-pktpool_invoke_dmarxfill(pktpool_t *pktp)
-{
-	ASSERT(pktp->dmarxfill.cb);
-	ASSERT(pktp->dmarxfill.arg);
-
-	if (pktp->dmarxfill.cb)
-		pktp->dmarxfill.cb(pktp, pktp->dmarxfill.arg);
-}
-int
-pkpool_haddr_avail_register_cb(pktpool_t *pktp, pktpool_cb_t cb, void *arg)
-{
-
-	ASSERT(cb != NULL);
-
-	pktp->dmarxfill.cb = cb;
-	pktp->dmarxfill.arg = arg;
-
-	return 0;
-}
-/* No BCMATTACHFN as it is used in xdc_enable_ep which is not an attach function */
-int
-pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg)
-{
-	int err = 0;
-	int i;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	ASSERT(cb != NULL);
-
-	i = pktp->cbcnt;
-	if (i == PKTPOOL_CB_MAX_AVL) {
-		err = BCME_ERROR;
-		goto done;
-	}
-
-	ASSERT(pktp->cbs[i].cb == NULL);
-	pktp->cbs[i].cb = cb;
-	pktp->cbs[i].arg = arg;
-	pktp->cbcnt++;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return err;
-}
-
-int
-pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg)
-{
-	int err = 0;
-	int i;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	ASSERT(cb != NULL);
-
-	i = pktp->ecbcnt;
-	if (i == PKTPOOL_CB_MAX) {
-		err = BCME_ERROR;
-		goto done;
-	}
-
-	ASSERT(pktp->ecbs[i].cb == NULL);
-	pktp->ecbs[i].cb = cb;
-	pktp->ecbs[i].arg = arg;
-	pktp->ecbcnt++;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return err;
-}
-
-static int
-pktpool_empty_notify(pktpool_t *pktp)
-{
-	int i;
-
-	pktp->empty = TRUE;
-	for (i = 0; i < pktp->ecbcnt; i++) {
-		ASSERT(pktp->ecbs[i].cb != NULL);
-		pktp->ecbs[i].cb(pktp, pktp->ecbs[i].arg);
-	}
-	pktp->empty = FALSE;
-
-	return 0;
-}
-
-#ifdef BCMDBG_POOL
-int
-pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg)
-{
-	int err = 0;
-	int i;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	ASSERT(cb);
-
-	i = pktp->dbg_cbcnt;
-	if (i == PKTPOOL_CB_MAX) {
-		err = BCME_ERROR;
-		goto done;
-	}
-
-	ASSERT(pktp->dbg_cbs[i].cb == NULL);
-	pktp->dbg_cbs[i].cb = cb;
-	pktp->dbg_cbs[i].arg = arg;
-	pktp->dbg_cbcnt++;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return err;
-}
-
-int pktpool_dbg_notify(pktpool_t *pktp);
-
-int
-pktpool_dbg_notify(pktpool_t *pktp)
-{
-	int i;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	for (i = 0; i < pktp->dbg_cbcnt; i++) {
-		ASSERT(pktp->dbg_cbs[i].cb);
-		pktp->dbg_cbs[i].cb(pktp, pktp->dbg_cbs[i].arg);
-	}
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return 0;
-}
-
-int
-pktpool_dbg_dump(pktpool_t *pktp)
-{
-	int i;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	printf("pool len=%d maxlen=%d\n",  pktp->dbg_qlen, pktp->maxlen);
-	for (i = 0; i < pktp->dbg_qlen; i++) {
-		ASSERT(pktp->dbg_q[i].p);
-		printf("%d, p: 0x%x dur:%lu us state:%d\n", i,
-			pktp->dbg_q[i].p, pktp->dbg_q[i].dur/100, PKTPOOLSTATE(pktp->dbg_q[i].p));
-	}
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return 0;
-}
-
-int
-pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats)
-{
-	int i;
-	int state;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	bzero(stats, sizeof(pktpool_stats_t));
-	for (i = 0; i < pktp->dbg_qlen; i++) {
-		ASSERT(pktp->dbg_q[i].p != NULL);
-
-		state = PKTPOOLSTATE(pktp->dbg_q[i].p);
-		switch (state) {
-			case POOL_TXENQ:
-				stats->enq++; break;
-			case POOL_TXDH:
-				stats->txdh++; break;
-			case POOL_TXD11:
-				stats->txd11++; break;
-			case POOL_RXDH:
-				stats->rxdh++; break;
-			case POOL_RXD11:
-				stats->rxd11++; break;
-			case POOL_RXFILL:
-				stats->rxfill++; break;
-			case POOL_IDLE:
-				stats->idle++; break;
-		}
-	}
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return 0;
-}
-
-int
-pktpool_start_trigger(pktpool_t *pktp, void *p)
-{
-	uint32 cycles, i;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	if (!PKTPOOL(OSH_NULL, p))
-		goto done;
-
-	OSL_GETCYCLES(cycles);
-
-	for (i = 0; i < pktp->dbg_qlen; i++) {
-		ASSERT(pktp->dbg_q[i].p != NULL);
-
-		if (pktp->dbg_q[i].p == p) {
-			pktp->dbg_q[i].cycles = cycles;
-			break;
-		}
-	}
-
-done:
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return 0;
-}
-
-int pktpool_stop_trigger(pktpool_t *pktp, void *p);
-int
-pktpool_stop_trigger(pktpool_t *pktp, void *p)
-{
-	uint32 cycles, i;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	if (!PKTPOOL(OSH_NULL, p))
-		goto done;
-
-	OSL_GETCYCLES(cycles);
-
-	for (i = 0; i < pktp->dbg_qlen; i++) {
-		ASSERT(pktp->dbg_q[i].p != NULL);
-
-		if (pktp->dbg_q[i].p == p) {
-			if (pktp->dbg_q[i].cycles == 0)
-				break;
-
-			if (cycles >= pktp->dbg_q[i].cycles)
-				pktp->dbg_q[i].dur = cycles - pktp->dbg_q[i].cycles;
-			else
-				pktp->dbg_q[i].dur =
-					(((uint32)-1) - pktp->dbg_q[i].cycles) + cycles + 1;
-
-			pktp->dbg_q[i].cycles = 0;
-			break;
-		}
-	}
-
-done:
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return 0;
-}
-#endif /* BCMDBG_POOL */
-
-int
-pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp)
-{
-	ASSERT(pktp);
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	pktp->availcb_excl = NULL;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return 0;
-}
-
-int
-pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb)
-{
-	int i;
-	int err;
-
-	ASSERT(pktp);
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	ASSERT(pktp->availcb_excl == NULL);
-	for (i = 0; i < pktp->cbcnt; i++) {
-		if (cb == pktp->cbs[i].cb) {
-			pktp->availcb_excl = &pktp->cbs[i];
-			break;
-		}
-	}
-
-	if (pktp->availcb_excl == NULL)
-		err = BCME_ERROR;
-	else
-		err = 0;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return err;
-}
-
-static int
-pktpool_avail_notify(pktpool_t *pktp)
-{
-	int i, k, idx;
-	int avail;
-
-	ASSERT(pktp);
-	if (pktp->availcb_excl != NULL) {
-		pktp->availcb_excl->cb(pktp, pktp->availcb_excl->arg);
-		return 0;
-	}
-
-	k = pktp->cbcnt - 1;
-	for (i = 0; i < pktp->cbcnt; i++) {
-		avail = pktp->avail;
-
-		if (avail) {
-			if (pktp->cbtoggle)
-				idx = i;
-			else
-				idx = k--;
-
-			ASSERT(pktp->cbs[idx].cb != NULL);
-			pktp->cbs[idx].cb(pktp, pktp->cbs[idx].arg);
-		}
-	}
-
-	/* Alternate between filling from head or tail
-	 */
-	pktp->cbtoggle ^= 1;
-
-	return 0;
-}
-
-void *
-pktpool_get(pktpool_t *pktp)
-{
-	void *p;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-
-	p = pktpool_deq(pktp);
-
-	if (p == NULL) {
-		/* Notify and try to reclaim tx pkts */
-		if (pktp->ecbcnt)
-			pktpool_empty_notify(pktp);
-
-		p = pktpool_deq(pktp);
-		if (p == NULL)
-			goto done;
-	}
-
-
-done:
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void
-pktpool_free(pktpool_t *pktp, void *p)
-{
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return;
-
-	ASSERT(p != NULL);
-#ifdef BCMDBG_POOL
-	/* pktpool_stop_trigger(pktp, p); */
-#endif
-
-	pktpool_enq(pktp, p);
-
-	/**
-	 * Feed critical DMA with freshly freed packets, to avoid DMA starvation.
-	 * If any avail callback functions are registered, send a notification
-	 * that a new packet is available in the pool.
-	 */
-	if (pktp->cbcnt) {
-		/* To more efficiently use the cpu cycles, callbacks can be temporarily disabled.
-		 * This allows to feed on burst basis as opposed to inefficient per-packet basis.
-		 */
-		if (pktp->emptycb_disable == EMPTYCB_ENABLED) {
-			/**
-			 * If the call originated from pktpool_empty_notify, the just freed packet
-			 * is needed in pktpool_get.
-			 * Therefore don't call pktpool_avail_notify.
-			 */
-			if (pktp->empty == FALSE)
-				pktpool_avail_notify(pktp);
-		} else {
-			/**
-			 * The callback is temporarily disabled, log that a packet has been freed.
-			 */
-			pktp->emptycb_disable = EMPTYCB_SKIPPED;
-		}
-	}
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return;
-}
-
-int
-pktpool_add(pktpool_t *pktp, void *p)
-{
-	int err = 0;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	ASSERT(p != NULL);
-
-	if (pktp->len == pktp->maxlen) {
-		err = BCME_RANGE;
-		goto done;
-	}
-
-	/* pkts in pool have same length */
-	ASSERT(pktp->plen == PKTLEN(OSH_NULL, p));
-	PKTSETPOOL(OSH_NULL, p, TRUE, pktp);
-
-	pktp->len++;
-	pktpool_enq(pktp, p);
-
-#ifdef BCMDBG_POOL
-	pktp->dbg_q[pktp->dbg_qlen++].p = p;
-#endif
-
-done:
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return err;
-}
-
-/* Force pktpool_setmaxlen () into RAM as it uses a constant
- * (PKTPOOL_LEN_MAX) that may be changed post tapeout for ROM-based chips.
- */
-int
-BCMRAMFN(pktpool_setmaxlen)(pktpool_t *pktp, uint16 maxlen)
-{
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	if (maxlen > PKTPOOL_LEN_MAX)
-		maxlen = PKTPOOL_LEN_MAX;
-
-	/* if pool is already beyond maxlen, then just cap it
-	 * since we currently do not reduce the pool len
-	 * already allocated
-	 */
-	pktp->maxlen = (pktp->len > maxlen) ? pktp->len : maxlen;
-
-	/* protect shared resource */
-	if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS)
-		return BCME_ERROR;
-
-	return pktp->maxlen;
-}
-
-void
-pktpool_emptycb_disable(pktpool_t *pktp, bool disable)
-{
-	ASSERT(pktp);
-
-	/**
-	 * To more efficiently use the cpu cycles, callbacks can be temporarily disabled.
-	 * If callback is going to be re-enabled, check if any packet got
-	 * freed and added back to the pool while callback was disabled.
-	 * When this is the case do the callback now, provided that callback functions
-	 * are registered and this call did not originate from pktpool_empty_notify.
-	 */
-	if ((!disable) && (pktp->cbcnt) && (pktp->empty == FALSE) &&
-		(pktp->emptycb_disable == EMPTYCB_SKIPPED)) {
-			pktpool_avail_notify(pktp);
-	}
-
-	/* Enable or temporarily disable callback when packet becomes available. */
-	pktp->emptycb_disable = disable ? EMPTYCB_DISABLED : EMPTYCB_ENABLED;
-}
-
-bool
-pktpool_emptycb_disabled(pktpool_t *pktp)
-{
-	ASSERT(pktp);
-	return pktp->emptycb_disable != EMPTYCB_ENABLED;
-}
-
-#ifdef BCMPKTPOOL
-#include <hnd_lbuf.h>
-
-pktpool_t *pktpool_shared = NULL;
-
-#ifdef BCMFRAGPOOL
-pktpool_t *pktpool_shared_lfrag = NULL;
-#endif /* BCMFRAGPOOL */
-
-pktpool_t *pktpool_shared_rxlfrag = NULL;
-
-static osl_t *pktpool_osh = NULL;
-
-void
-hnd_pktpool_init(osl_t *osh)
-{
-	int n;
-
-	/* Construct a packet pool registry before initializing packet pools */
-	n = pktpool_attach(osh, PKTPOOL_MAXIMUM_ID);
-	if (n != PKTPOOL_MAXIMUM_ID) {
-		ASSERT(0);
-		return;
-	}
-
-	pktpool_shared = MALLOCZ(osh, sizeof(pktpool_t));
-	if (pktpool_shared == NULL) {
-		ASSERT(0);
-		goto error1;
-	}
-
-#if defined(BCMFRAGPOOL) && !defined(BCMFRAGPOOL_DISABLED)
-	pktpool_shared_lfrag = MALLOCZ(osh, sizeof(pktpool_t));
-	if (pktpool_shared_lfrag == NULL) {
-		ASSERT(0);
-		goto error2;
-	}
-#endif
-
-#if defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED)
-	pktpool_shared_rxlfrag = MALLOCZ(osh, sizeof(pktpool_t));
-	if (pktpool_shared_rxlfrag == NULL) {
-		ASSERT(0);
-		goto error3;
-	}
-#endif
-
-
-	/*
-	 * At this early stage, there's not enough memory to allocate all
-	 * requested pkts in the shared pool.  Need to add to the pool
-	 * after reclaim
-	 *
-	 * n = NRXBUFPOST + SDPCMD_RXBUFS;
-	 *
-	 * Initialization of packet pools may fail (BCME_ERROR), if the packet pool
-	 * registry is not initialized or the registry is depleted.
-	 *
-	 * A BCME_NOMEM error only indicates that the requested number of packets
-	 * were not filled into the pool.
-	 */
-	n = 1;
-	if (pktpool_init(osh, pktpool_shared,
-	                 &n, PKTBUFSZ, FALSE, lbuf_basic) == BCME_ERROR) {
-		ASSERT(0);
-		goto error4;
-	}
-	pktpool_setmaxlen(pktpool_shared, SHARED_POOL_LEN);
-
-#if defined(BCMFRAGPOOL) && !defined(BCMFRAGPOOL_DISABLED)
-	n = 1;
-	if (pktpool_init(osh, pktpool_shared_lfrag,
-	                 &n, PKTFRAGSZ, TRUE, lbuf_frag) == BCME_ERROR) {
-		ASSERT(0);
-		goto error5;
-	}
-	pktpool_setmaxlen(pktpool_shared_lfrag, SHARED_FRAG_POOL_LEN);
-#endif
-#if defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED)
-	n = 1;
-	if (pktpool_init(osh, pktpool_shared_rxlfrag,
-	                 &n, PKTRXFRAGSZ, TRUE, lbuf_rxfrag) == BCME_ERROR) {
-		ASSERT(0);
-		goto error6;
-	}
-	pktpool_setmaxlen(pktpool_shared_rxlfrag, SHARED_RXFRAG_POOL_LEN);
-#endif
-
-	pktpool_osh = osh;
-
-	return;
-
-#if defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED)
-error6:
-#endif
-
-#if defined(BCMFRAGPOOL) && !defined(BCMFRAGPOOL_DISABLED)
-	pktpool_deinit(osh, pktpool_shared_lfrag);
-error5:
-#endif
-
-#if (defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED)) || \
-	(defined(BCMFRAGPOOL) && !defined(BCMFRAGPOOL_DISABLED))
-	pktpool_deinit(osh, pktpool_shared);
-#endif
-
-error4:
-#if defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED)
-	hnd_free(pktpool_shared_rxlfrag);
-	pktpool_shared_rxlfrag = (pktpool_t *)NULL;
-error3:
-#endif /* BCMRXFRAGPOOL */
-
-#if defined(BCMFRAGPOOL) && !defined(BCMFRAGPOOL_DISABLED)
-	hnd_free(pktpool_shared_lfrag);
-	pktpool_shared_lfrag = (pktpool_t *)NULL;
-error2:
-#endif /* BCMFRAGPOOL */
-
-	hnd_free(pktpool_shared);
-	pktpool_shared = (pktpool_t *)NULL;
-
-error1:
-	pktpool_dettach(osh);
-}
-
-void
-hnd_pktpool_fill(pktpool_t *pktpool, bool minimal)
-{
-	pktpool_fill(pktpool_osh, pktpool, minimal);
-}
-
-/* refill pktpools after reclaim */
-void
-hnd_pktpool_refill(bool minimal)
-{
-	if (POOL_ENAB(pktpool_shared)) {
-		pktpool_fill(pktpool_osh, pktpool_shared, minimal);
-	}
-/* fragpool reclaim */
-#ifdef BCMFRAGPOOL
-	if (POOL_ENAB(pktpool_shared_lfrag)) {
-		pktpool_fill(pktpool_osh, pktpool_shared_lfrag, minimal);
-	}
-#endif /* BCMFRAGPOOL */
-/* rx fragpool reclaim */
-#ifdef BCMRXFRAGPOOL
-	if (POOL_ENAB(pktpool_shared_rxlfrag)) {
-		pktpool_fill(pktpool_osh, pktpool_shared_rxlfrag, minimal);
-	}
-#endif
-}
-#endif /* BCMPKTPOOL */
diff --git a/drivers/net/wireless/bcmdhd/hnd_pktq.c b/drivers/net/wireless/bcmdhd/hnd_pktq.c
deleted file mode 100644
index 4d1a780..0000000
--- a/drivers/net/wireless/bcmdhd/hnd_pktq.c
+++ /dev/null
@@ -1,888 +0,0 @@
-/*
- * HND generic pktq operation primitives
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hnd_pktq.c 605726 2015-12-11 07:08:16Z $
- */
-
-#include <typedefs.h>
-#include <osl.h>
-#include <osl_ext.h>
-#include <bcmutils.h>
-#include <hnd_pktq.h>
-
-/* mutex macros for thread safe */
-#ifdef HND_PKTQ_THREAD_SAFE
-#define HND_PKTQ_MUTEX_CREATE(name, mutex)	osl_ext_mutex_create(name, mutex)
-#define HND_PKTQ_MUTEX_DELETE(mutex)		osl_ext_mutex_delete(mutex)
-#define HND_PKTQ_MUTEX_ACQUIRE(mutex, msec)	osl_ext_mutex_acquire(mutex, msec)
-#define HND_PKTQ_MUTEX_RELEASE(mutex)		osl_ext_mutex_release(mutex)
-#else
-#define HND_PKTQ_MUTEX_CREATE(name, mutex)	OSL_EXT_SUCCESS
-#define HND_PKTQ_MUTEX_DELETE(mutex)		OSL_EXT_SUCCESS
-#define HND_PKTQ_MUTEX_ACQUIRE(mutex, msec)	OSL_EXT_SUCCESS
-#define HND_PKTQ_MUTEX_RELEASE(mutex)		OSL_EXT_SUCCESS
-#endif
-
-/*
- * osl multiple-precedence packet queue
- * hi_prec is always >= the number of the highest non-empty precedence
- */
-void * BCMFASTPATH
-pktq_penq(struct pktq *pq, int prec, void *p)
-{
-	struct pktq_prec *q;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-	/* queueing chains not allowed and no segmented SKB (Kernel-3.18.y) */
-	ASSERT(!((PKTLINK(p) != NULL) && (PKTLINK(p) != p)));
-
-	ASSERT(!pktq_full(pq));
-	ASSERT(!pktq_pfull(pq, prec));
-
-	q = &pq->q[prec];
-
-	if (q->head)
-		PKTSETLINK(q->tail, p);
-	else
-		q->head = p;
-
-	q->tail = p;
-	q->len++;
-
-	pq->len++;
-
-	if (pq->hi_prec < prec)
-		pq->hi_prec = (uint8)prec;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void * BCMFASTPATH
-pktq_penq_head(struct pktq *pq, int prec, void *p)
-{
-	struct pktq_prec *q;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-	/* queueing chains not allowed and no segmented SKB (Kernel-3.18.y) */
-	ASSERT(!((PKTLINK(p) != NULL) && (PKTLINK(p) != p)));
-
-	ASSERT(!pktq_full(pq));
-	ASSERT(!pktq_pfull(pq, prec));
-
-	q = &pq->q[prec];
-
-	if (q->head == NULL)
-		q->tail = p;
-
-	PKTSETLINK(p, q->head);
-	q->head = p;
-	q->len++;
-
-	pq->len++;
-
-	if (pq->hi_prec < prec)
-		pq->hi_prec = (uint8)prec;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-/*
- * Append spktq 'list' to the tail of pktq 'pq'
- */
-void BCMFASTPATH
-pktq_append(struct pktq *pq, int prec, struct spktq *list)
-{
-	struct pktq_prec *q;
-	struct pktq_prec *list_q;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return;
-
-	list_q = &list->q[0];
-
-	/* empty list check */
-	if (list_q->head == NULL)
-		goto done;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-	ASSERT(PKTLINK(list_q->tail) == NULL);         /* terminated list */
-
-	ASSERT(!pktq_full(pq));
-	ASSERT(!pktq_pfull(pq, prec));
-
-	q = &pq->q[prec];
-
-	if (q->head)
-		PKTSETLINK(q->tail, list_q->head);
-	else
-		q->head = list_q->head;
-
-	q->tail = list_q->tail;
-	q->len += list_q->len;
-	pq->len += list_q->len;
-
-	if (pq->hi_prec < prec)
-		pq->hi_prec = (uint8)prec;
-
-	list_q->head = NULL;
-	list_q->tail = NULL;
-	list_q->len = 0;
-	list->len = 0;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return;
-}
-
-/*
- * Prepend spktq 'list' to the head of pktq 'pq'
- */
-void BCMFASTPATH
-pktq_prepend(struct pktq *pq, int prec, struct spktq *list)
-{
-	struct pktq_prec *q;
-	struct pktq_prec *list_q;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return;
-
-	list_q = &list->q[0];
-
-	/* empty list check */
-	if (list_q->head == NULL)
-		goto done;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-	ASSERT(PKTLINK(list_q->tail) == NULL);         /* terminated list */
-
-	ASSERT(!pktq_full(pq));
-	ASSERT(!pktq_pfull(pq, prec));
-
-	q = &pq->q[prec];
-
-	/* set the tail packet of list to point at the former pq head */
-	PKTSETLINK(list_q->tail, q->head);
-	/* the new q head is the head of list */
-	q->head = list_q->head;
-
-	/* If the q tail was non-null, then it stays as is.
-	 * If the q tail was null, it is now the tail of list
-	 */
-	if (q->tail == NULL) {
-		q->tail = list_q->tail;
-	}
-
-	q->len += list_q->len;
-	pq->len += list_q->len;
-
-	if (pq->hi_prec < prec)
-		pq->hi_prec = (uint8)prec;
-
-	list_q->head = NULL;
-	list_q->tail = NULL;
-	list_q->len = 0;
-	list->len = 0;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return;
-}
-
-void * BCMFASTPATH
-pktq_pdeq(struct pktq *pq, int prec)
-{
-	struct pktq_prec *q;
-	void *p;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	q = &pq->q[prec];
-
-	if ((p = q->head) == NULL)
-		goto done;
-
-	if ((q->head = PKTLINK(p)) == NULL)
-		q->tail = NULL;
-
-	q->len--;
-
-	pq->len--;
-
-	PKTSETLINK(p, NULL);
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void * BCMFASTPATH
-pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p)
-{
-	struct pktq_prec *q;
-	void *p = NULL;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	q = &pq->q[prec];
-
-	if (prev_p == NULL)
-		goto done;
-
-	if ((p = PKTLINK(prev_p)) == NULL)
-		goto done;
-
-	q->len--;
-
-	pq->len--;
-
-	PKTSETLINK(prev_p, PKTLINK(p));
-	PKTSETLINK(p, NULL);
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void * BCMFASTPATH
-pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg)
-{
-	struct pktq_prec *q;
-	void *p, *prev = NULL;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	q = &pq->q[prec];
-	p = q->head;
-
-	while (p) {
-		if (fn == NULL || (*fn)(p, arg)) {
-			break;
-		} else {
-			prev = p;
-			p = PKTLINK(p);
-		}
-	}
-	if (p == NULL)
-		goto done;
-
-	if (prev == NULL) {
-		if ((q->head = PKTLINK(p)) == NULL) {
-			q->tail = NULL;
-		}
-	} else {
-		PKTSETLINK(prev, PKTLINK(p));
-		if (q->tail == p) {
-			q->tail = prev;
-		}
-	}
-
-	q->len--;
-
-	pq->len--;
-
-	PKTSETLINK(p, NULL);
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void * BCMFASTPATH
-pktq_pdeq_tail(struct pktq *pq, int prec)
-{
-	struct pktq_prec *q;
-	void *p, *prev;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	q = &pq->q[prec];
-
-	if ((p = q->head) == NULL)
-		goto done;
-
-	for (prev = NULL; p != q->tail; p = PKTLINK(p))
-		prev = p;
-
-	if (prev)
-		PKTSETLINK(prev, NULL);
-	else
-		q->head = NULL;
-
-	q->tail = prev;
-	q->len--;
-
-	pq->len--;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void
-pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg)
-{
-	struct pktq_prec *q;
-	void *p, *next, *prev = NULL;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return;
-
-	q = &pq->q[prec];
-	p = q->head;
-	while (p) {
-		next = PKTLINK(p);
-		if (fn == NULL || (*fn)(p, arg)) {
-			bool head = (p == q->head);
-			if (head)
-				q->head = next;
-			else
-				PKTSETLINK(prev, next);
-			PKTSETLINK(p, NULL);
-			PKTFREE(osh, p, dir);
-			q->len--;
-			pq->len--;
-		} else {
-			prev = p;
-		}
-		p = next;
-	}
-
-	q->tail = prev;
-
-	if (q->head == NULL) {
-		ASSERT(q->len == 0);
-		ASSERT(q->tail == NULL);
-	}
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return;
-}
-
-bool BCMFASTPATH
-pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
-{
-	bool ret = FALSE;
-	struct pktq_prec *q;
-	void *p = NULL;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return FALSE;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	/* Should this just assert pktbuf? */
-	if (!pktbuf)
-		goto done;
-
-	q = &pq->q[prec];
-
-	if (q->head == pktbuf) {
-		if ((q->head = PKTLINK(pktbuf)) == NULL)
-			q->tail = NULL;
-	} else {
-		for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p))
-			;
-		if (p == NULL)
-			goto done;
-
-		PKTSETLINK(p, PKTLINK(pktbuf));
-		if (q->tail == pktbuf)
-			q->tail = p;
-	}
-
-	q->len--;
-	pq->len--;
-	PKTSETLINK(pktbuf, NULL);
-	ret = TRUE;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return FALSE;
-
-	return ret;
-}
-
-bool
-pktq_init(struct pktq *pq, int num_prec, int max_len)
-{
-	int prec;
-
-	if (HND_PKTQ_MUTEX_CREATE("pktq", &pq->mutex) != OSL_EXT_SUCCESS)
-		return FALSE;
-
-	ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
-
-	/* pq is variable size; only zero out what's requested */
-	bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
-
-	pq->num_prec = (uint16)num_prec;
-
-	pq->max = (uint16)max_len;
-
-	for (prec = 0; prec < num_prec; prec++)
-		pq->q[prec].max = pq->max;
-
-	return TRUE;
-}
-
-bool
-pktq_deinit(struct pktq *pq)
-{
-	if (HND_PKTQ_MUTEX_DELETE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return FALSE;
-
-	return TRUE;
-}
-
-void
-pktq_set_max_plen(struct pktq *pq, int prec, int max_len)
-{
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return;
-
-	if (prec < pq->num_prec)
-		pq->q[prec].max = (uint16)max_len;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return;
-}
-
-void * BCMFASTPATH
-pktq_deq(struct pktq *pq, int *prec_out)
-{
-	struct pktq_prec *q;
-	void *p = NULL;
-	int prec;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	if (pq->len == 0)
-		goto done;
-
-	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
-		pq->hi_prec--;
-
-	q = &pq->q[prec];
-
-	if ((p = q->head) == NULL)
-		goto done;
-
-	if ((q->head = PKTLINK(p)) == NULL)
-		q->tail = NULL;
-
-	q->len--;
-
-	pq->len--;
-
-	if (prec_out)
-		*prec_out = prec;
-
-	PKTSETLINK(p, NULL);
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void * BCMFASTPATH
-pktq_deq_tail(struct pktq *pq, int *prec_out)
-{
-	struct pktq_prec *q;
-	void *p = NULL, *prev;
-	int prec;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	if (pq->len == 0)
-		goto done;
-
-	for (prec = 0; prec < pq->hi_prec; prec++)
-		if (pq->q[prec].head)
-			break;
-
-	q = &pq->q[prec];
-
-	if ((p = q->head) == NULL)
-		goto done;
-
-	for (prev = NULL; p != q->tail; p = PKTLINK(p))
-		prev = p;
-
-	if (prev)
-		PKTSETLINK(prev, NULL);
-	else
-		q->head = NULL;
-
-	q->tail = prev;
-	q->len--;
-
-	pq->len--;
-
-	if (prec_out)
-		*prec_out = prec;
-
-	PKTSETLINK(p, NULL);
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void *
-pktq_peek(struct pktq *pq, int *prec_out)
-{
-	int prec;
-	void *p = NULL;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	if (pq->len == 0)
-		goto done;
-
-	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
-		pq->hi_prec--;
-
-	if (prec_out)
-		*prec_out = prec;
-
-	p = pq->q[prec].head;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void *
-pktq_peek_tail(struct pktq *pq, int *prec_out)
-{
-	int prec;
-	void *p = NULL;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	if (pq->len == 0)
-		goto done;
-
-	for (prec = 0; prec < pq->hi_prec; prec++)
-		if (pq->q[prec].head)
-			break;
-
-	if (prec_out)
-		*prec_out = prec;
-
-	p = pq->q[prec].tail;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-void
-pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg)
-{
-	int prec;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return;
-
-	/* Optimize flush, if pktq len = 0, just return.
-	 * pktq len of 0 means pktq's prec q's are all empty.
-	 */
-	if (pq->len == 0)
-		goto done;
-
-	for (prec = 0; prec < pq->num_prec; prec++)
-		pktq_pflush(osh, pq, prec, dir, fn, arg);
-	if (fn == NULL)
-		ASSERT(pq->len == 0);
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return;
-}
-
-/* Return sum of lengths of a specific set of precedences */
-int
-pktq_mlen(struct pktq *pq, uint prec_bmp)
-{
-	int prec, len;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return 0;
-
-	len = 0;
-
-	for (prec = 0; prec <= pq->hi_prec; prec++)
-		if (prec_bmp & (1 << prec))
-			len += pq->q[prec].len;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return 0;
-
-	return len;
-}
-
-/* Priority peek from a specific set of precedences */
-void * BCMFASTPATH
-pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out)
-{
-	struct pktq_prec *q;
-	void *p = NULL;
-	int prec;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	if (pq->len == 0)
-		goto done;
-
-	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
-		pq->hi_prec--;
-
-	while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
-		if (prec-- == 0)
-			goto done;
-
-	q = &pq->q[prec];
-
-	if ((p = q->head) == NULL)
-		goto done;
-
-	if (prec_out)
-		*prec_out = prec;
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-/* Priority dequeue from a specific set of precedences */
-void * BCMFASTPATH
-pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
-{
-	struct pktq_prec *q;
-	void *p = NULL;
-	int prec;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	if (pq->len == 0)
-		goto done;
-
-	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
-		pq->hi_prec--;
-
-	while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0))
-		if (prec-- == 0)
-			goto done;
-
-	q = &pq->q[prec];
-
-	if ((p = q->head) == NULL)
-		goto done;
-
-	if ((q->head = PKTLINK(p)) == NULL)
-		q->tail = NULL;
-
-	q->len--;
-
-	if (prec_out)
-		*prec_out = prec;
-
-	pq->len--;
-
-	PKTSETLINK(p, NULL);
-
-done:
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return NULL;
-
-	return p;
-}
-
-#ifdef HND_PKTQ_THREAD_SAFE
-int
-pktq_pavail(struct pktq *pq, int prec)
-{
-	int ret;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return 0;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	ret = pq->q[prec].max - pq->q[prec].len;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return 0;
-
-	return ret;
-}
-
-bool
-pktq_pfull(struct pktq *pq, int prec)
-{
-	bool ret;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return FALSE;
-
-	ASSERT(prec >= 0 && prec < pq->num_prec);
-
-	ret = pq->q[prec].len >= pq->q[prec].max;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return FALSE;
-
-	return ret;
-}
-
-int
-pktq_avail(struct pktq *pq)
-{
-	int ret;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return 0;
-
-	ret = pq->max - pq->len;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return 0;
-
-	return ret;
-}
-
-bool
-pktq_full(struct pktq *pq)
-{
-	bool ret;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
-		return FALSE;
-
-	ret = pq->len >= pq->max;
-
-	/* protect shared resource */
-	if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
-		return FALSE;
-
-	return ret;
-}
-#endif	/* HND_PKTQ_THREAD_SAFE */
diff --git a/drivers/net/wireless/bcmdhd/hndpmu.c b/drivers/net/wireless/bcmdhd/hndpmu.c
deleted file mode 100644
index c0c6582..0000000
--- a/drivers/net/wireless/bcmdhd/hndpmu.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Misc utility routines for accessing PMU corerev specific features
- * of the SiliconBackplane-based Broadcom chips.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hndpmu.c 530092 2015-01-29 04:44:58Z $
- */
-
-
-/*
- * Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs.
- * However, in the context of this file the baseband ('BB') PLL/FLL is referred to.
- *
- * Throughout this code, the prefixes 'pmu0_', 'pmu1_' and 'pmu2_' are used.
- * They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012)
- * pmu1_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop). It supports
- * fractional frequency generation. pmu2_ does not support fractional frequency generation.
- */
-
-#include <bcm_cfg.h>
-#include <typedefs.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <bcmdevs.h>
-#include <hndsoc.h>
-#include <sbchipc.h>
-#include <hndpmu.h>
-
-#define	PMU_ERROR(args)
-
-#define	PMU_MSG(args)
-
-/* To check in verbose debugging messages not intended
- * to be on except on private builds.
- */
-#define	PMU_NONE(args)
-
-/** contains resource bit positions for a specific chip */
-struct rsc_per_chip_s {
-	uint8 ht_avail;
-	uint8 macphy_clkavail;
-	uint8 ht_start;
-	uint8 otp_pu;
-};
-
-typedef struct rsc_per_chip_s rsc_per_chip_t;
-
-
-/* SDIO Pad drive strength to select value mappings.
- * The last strength value in each table must be 0 (the tri-state value).
- */
-typedef struct {
-	uint8 strength;			/* Pad Drive Strength in mA */
-	uint8 sel;			/* Chip-specific select value */
-} sdiod_drive_str_t;
-
-/* SDIO Drive Strength to sel value table for PMU Rev 1 */
-static const sdiod_drive_str_t sdiod_drive_strength_tab1[] = {
-	{4, 0x2},
-	{2, 0x3},
-	{1, 0x0},
-	{0, 0x0} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
-static const sdiod_drive_str_t sdiod_drive_strength_tab2[] = {
-	{12, 0x7},
-	{10, 0x6},
-	{8, 0x5},
-	{6, 0x4},
-	{4, 0x2},
-	{2, 0x1},
-	{0, 0x0} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
-static const sdiod_drive_str_t sdiod_drive_strength_tab3[] = {
-	{32, 0x7},
-	{26, 0x6},
-	{22, 0x5},
-	{16, 0x4},
-	{12, 0x3},
-	{8, 0x2},
-	{4, 0x1},
-	{0, 0x0} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8v) */
-static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v8[] = {
-	{32, 0x6},
-	{26, 0x7},
-	{22, 0x4},
-	{16, 0x5},
-	{12, 0x2},
-	{8, 0x3},
-	{4, 0x0},
-	{0, 0x1} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.2v) */
-
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (2.5v) */
-
-/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
-static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = {
-	{6, 0x7},
-	{5, 0x6},
-	{4, 0x5},
-	{3, 0x4},
-	{2, 0x2},
-	{1, 0x1},
-	{0, 0x0} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */
-
-/** SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
-static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = {
-	{3, 0x3},
-	{2, 0x2},
-	{1, 0x1},
-	{0, 0x0} };
-
-
-/**
- * SDIO Drive Strength to sel value table for 43143 PMU Rev 17, see Confluence 43143 Toplevel
- * architecture page, section 'PMU Chip Control 1 Register definition', click link to picture
- * BCM43143_sel_sdio_signals.jpg. Valid after PMU Chip Control 0 Register, bit31 (override) has
- * been written '1'.
- */
-#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33
-
-static const sdiod_drive_str_t sdiod_drive_strength_tab7_3v3[] = {
-	/* note: for 14, 10, 6 and 2mA hw timing is not met according to rtl team */
-	{16, 0x7},
-	{12, 0x5},
-	{8,  0x3},
-	{4,  0x1} }; /* note: 43143 does not support tristate */
-
-#else
-
-static const sdiod_drive_str_t sdiod_drive_strength_tab7_1v8[] = {
-	/* note: for 7, 5, 3 and 1mA hw timing is not met according to rtl team */
-	{8, 0x7},
-	{6, 0x5},
-	{4,  0x3},
-	{2,  0x1} }; /* note: 43143 does not support tristate */
-
-#endif /* BCM_SDIO_VDDIO */
-
-#define SDIOD_DRVSTR_KEY(chip, pmu)	(((chip) << 16) | (pmu))
-
-/**
- * Balance between stable SDIO operation and power consumption is achieved using this function.
- * Note that each drive strength table is for a specific VDDIO of the SDIO pads, ideally this
- * function should read the VDDIO itself to select the correct table. For now it has been solved
- * with the 'BCM_SDIO_VDDIO' preprocessor constant.
- *
- * 'drivestrength': desired pad drive strength in mA. Drive strength of 0 requests tri-state (if
- *		    hardware supports this), if no hw support drive strength is not programmed.
- */
-void
-si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
-{
-	sdiod_drive_str_t *str_tab = NULL;
-	uint32 str_mask = 0;	/* only alter desired bits in PMU chipcontrol 1 register */
-	uint32 str_shift = 0;
-	uint32 str_ovr_pmuctl = PMU_CHIPCTL0; /* PMU chipcontrol register containing override bit */
-	uint32 str_ovr_pmuval = 0;            /* position of bit within this register */
-	pmuregs_t *pmu;
-	uint origidx;
-
-	if (!(sih->cccaps & CC_CAP_PMU)) {
-		return;
-	}
-
-	/* Remember original core before switch to chipc/pmu */
-	origidx = si_coreidx(sih);
-	if (AOB_ENAB(sih)) {
-		pmu = si_setcore(sih, PMU_CORE_ID, 0);
-	} else {
-		pmu = si_setcoreidx(sih, SI_CC_IDX);
-	}
-	ASSERT(pmu != NULL);
-
-	switch (SDIOD_DRVSTR_KEY(CHIPID(sih->chip), sih->pmurev)) {
-	case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
-		str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1;
-		str_mask = 0x30000000;
-		str_shift = 28;
-		break;
-	case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
-	case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
-	case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4):
-		str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2;
-		str_mask = 0x00003800;
-		str_shift = 11;
-		break;
-	case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
-	case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 11):
-		if (sih->pmurev == 8) {
-			str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3;
-		}
-		else if (sih->pmurev == 11) {
-			str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8;
-		}
-		str_mask = 0x00003800;
-		str_shift = 11;
-		break;
-	case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
-		str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8;
-		str_mask = 0x00003800;
-		str_shift = 11;
-		break;
-	case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
-		str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab5_1v8;
-		str_mask = 0x00003800;
-		str_shift = 11;
-		break;
-	case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
-		str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab6_1v8;
-		str_mask = 0x00001800;
-		str_shift = 11;
-		break;
-	case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
-#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33
-		if (drivestrength >=  ARRAYLAST(sdiod_drive_strength_tab7_3v3)->strength) {
-			str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_3v3;
-		}
-#else
-		if (drivestrength >=  ARRAYLAST(sdiod_drive_strength_tab7_1v8)->strength) {
-			str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_1v8;
-		}
-#endif /* BCM_SDIO_VDDIO */
-		str_mask = 0x00000007;
-		str_ovr_pmuval = PMU43143_CC0_SDIO_DRSTR_OVR;
-		break;
-	default:
-		PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
-		         bcm_chipname(
-			 CHIPID(sih->chip), chn, 8), CHIPREV(sih->chiprev), sih->pmurev));
-		break;
-	}
-
-	if (str_tab != NULL) {
-		uint32 cc_data_temp;
-		int i;
-
-		/* Pick the lowest available drive strength equal or greater than the
-		 * requested strength.	Drive strength of 0 requests tri-state.
-		 */
-		for (i = 0; drivestrength < str_tab[i].strength; i++)
-			;
-
-		if (i > 0 && drivestrength > str_tab[i].strength)
-			i--;
-
-		W_REG(osh, &pmu->chipcontrol_addr, PMU_CHIPCTL1);
-		cc_data_temp = R_REG(osh, &pmu->chipcontrol_data);
-		cc_data_temp &= ~str_mask;
-		cc_data_temp |= str_tab[i].sel << str_shift;
-		W_REG(osh, &pmu->chipcontrol_data, cc_data_temp);
-		if (str_ovr_pmuval) { /* enables the selected drive strength */
-			W_REG(osh,  &pmu->chipcontrol_addr, str_ovr_pmuctl);
-			OR_REG(osh, &pmu->chipcontrol_data, str_ovr_pmuval);
-		}
-		PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n",
-		         drivestrength, str_tab[i].strength));
-	}
-
-	/* Return to original core */
-	si_setcoreidx(sih, origidx);
-} /* si_sdiod_drive_strength_init */
diff --git a/drivers/net/wireless/bcmdhd/include/aidmp.h b/drivers/net/wireless/bcmdhd/include/aidmp.h
deleted file mode 100644
index 6654364..0000000
--- a/drivers/net/wireless/bcmdhd/include/aidmp.h
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * Broadcom AMBA Interconnect definitions.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: aidmp.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_AIDMP_H
-#define	_AIDMP_H
-
-/* Manufacturer Ids */
-#define	MFGID_ARM		0x43b
-#define	MFGID_BRCM		0x4bf
-#define	MFGID_MIPS		0x4a7
-
-/* Component Classes */
-#define	CC_SIM			0
-#define	CC_EROM			1
-#define	CC_CORESIGHT		9
-#define	CC_VERIF		0xb
-#define	CC_OPTIMO		0xd
-#define	CC_GEN			0xe
-#define	CC_PRIMECELL		0xf
-
-/* Enumeration ROM registers */
-#define	ER_EROMENTRY		0x000
-#define	ER_REMAPCONTROL		0xe00
-#define	ER_REMAPSELECT		0xe04
-#define	ER_MASTERSELECT		0xe10
-#define	ER_ITCR			0xf00
-#define	ER_ITIP			0xf04
-
-/* Erom entries */
-#define	ER_TAG			0xe
-#define	ER_TAG1			0x6
-#define	ER_VALID		1
-#define	ER_CI			0
-#define	ER_MP			2
-#define	ER_ADD			4
-#define	ER_END			0xe
-#define	ER_BAD			0xffffffff
-#define	ER_SZ_MAX		4096 /* 4KB */
-
-/* EROM CompIdentA */
-#define	CIA_MFG_MASK		0xfff00000
-#define	CIA_MFG_SHIFT		20
-#define	CIA_CID_MASK		0x000fff00
-#define	CIA_CID_SHIFT		8
-#define	CIA_CCL_MASK		0x000000f0
-#define	CIA_CCL_SHIFT		4
-
-/* EROM CompIdentB */
-#define	CIB_REV_MASK		0xff000000
-#define	CIB_REV_SHIFT		24
-#define	CIB_NSW_MASK		0x00f80000
-#define	CIB_NSW_SHIFT		19
-#define	CIB_NMW_MASK		0x0007c000
-#define	CIB_NMW_SHIFT		14
-#define	CIB_NSP_MASK		0x00003e00
-#define	CIB_NSP_SHIFT		9
-#define	CIB_NMP_MASK		0x000001f0
-#define	CIB_NMP_SHIFT		4
-
-/* EROM MasterPortDesc */
-#define	MPD_MUI_MASK		0x0000ff00
-#define	MPD_MUI_SHIFT		8
-#define	MPD_MP_MASK		0x000000f0
-#define	MPD_MP_SHIFT		4
-
-/* EROM AddrDesc */
-#define	AD_ADDR_MASK		0xfffff000
-#define	AD_SP_MASK		0x00000f00
-#define	AD_SP_SHIFT		8
-#define	AD_ST_MASK		0x000000c0
-#define	AD_ST_SHIFT		6
-#define	AD_ST_SLAVE		0x00000000
-#define	AD_ST_BRIDGE		0x00000040
-#define	AD_ST_SWRAP		0x00000080
-#define	AD_ST_MWRAP		0x000000c0
-#define	AD_SZ_MASK		0x00000030
-#define	AD_SZ_SHIFT		4
-#define	AD_SZ_4K		0x00000000
-#define	AD_SZ_8K		0x00000010
-#define	AD_SZ_16K		0x00000020
-#define	AD_SZ_SZD		0x00000030
-#define	AD_AG32			0x00000008
-#define	AD_ADDR_ALIGN		0x00000fff
-#define	AD_SZ_BASE		0x00001000	/* 4KB */
-
-/* EROM SizeDesc */
-#define	SD_SZ_MASK		0xfffff000
-#define	SD_SG32			0x00000008
-#define	SD_SZ_ALIGN		0x00000fff
-
-
-#if !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__)
-
-typedef volatile struct _aidmp {
-	uint32	oobselina30;	/* 0x000 */
-	uint32	oobselina74;	/* 0x004 */
-	uint32	PAD[6];
-	uint32	oobselinb30;	/* 0x020 */
-	uint32	oobselinb74;	/* 0x024 */
-	uint32	PAD[6];
-	uint32	oobselinc30;	/* 0x040 */
-	uint32	oobselinc74;	/* 0x044 */
-	uint32	PAD[6];
-	uint32	oobselind30;	/* 0x060 */
-	uint32	oobselind74;	/* 0x064 */
-	uint32	PAD[38];
-	uint32	oobselouta30;	/* 0x100 */
-	uint32	oobselouta74;	/* 0x104 */
-	uint32	PAD[6];
-	uint32	oobseloutb30;	/* 0x120 */
-	uint32	oobseloutb74;	/* 0x124 */
-	uint32	PAD[6];
-	uint32	oobseloutc30;	/* 0x140 */
-	uint32	oobseloutc74;	/* 0x144 */
-	uint32	PAD[6];
-	uint32	oobseloutd30;	/* 0x160 */
-	uint32	oobseloutd74;	/* 0x164 */
-	uint32	PAD[38];
-	uint32	oobsynca;	/* 0x200 */
-	uint32	oobseloutaen;	/* 0x204 */
-	uint32	PAD[6];
-	uint32	oobsyncb;	/* 0x220 */
-	uint32	oobseloutben;	/* 0x224 */
-	uint32	PAD[6];
-	uint32	oobsyncc;	/* 0x240 */
-	uint32	oobseloutcen;	/* 0x244 */
-	uint32	PAD[6];
-	uint32	oobsyncd;	/* 0x260 */
-	uint32	oobseloutden;	/* 0x264 */
-	uint32	PAD[38];
-	uint32	oobaextwidth;	/* 0x300 */
-	uint32	oobainwidth;	/* 0x304 */
-	uint32	oobaoutwidth;	/* 0x308 */
-	uint32	PAD[5];
-	uint32	oobbextwidth;	/* 0x320 */
-	uint32	oobbinwidth;	/* 0x324 */
-	uint32	oobboutwidth;	/* 0x328 */
-	uint32	PAD[5];
-	uint32	oobcextwidth;	/* 0x340 */
-	uint32	oobcinwidth;	/* 0x344 */
-	uint32	oobcoutwidth;	/* 0x348 */
-	uint32	PAD[5];
-	uint32	oobdextwidth;	/* 0x360 */
-	uint32	oobdinwidth;	/* 0x364 */
-	uint32	oobdoutwidth;	/* 0x368 */
-	uint32	PAD[37];
-	uint32	ioctrlset;	/* 0x400 */
-	uint32	ioctrlclear;	/* 0x404 */
-	uint32	ioctrl;		/* 0x408 */
-	uint32	PAD[61];
-	uint32	iostatus;	/* 0x500 */
-	uint32	PAD[127];
-	uint32	ioctrlwidth;	/* 0x700 */
-	uint32	iostatuswidth;	/* 0x704 */
-	uint32	PAD[62];
-	uint32	resetctrl;	/* 0x800 */
-	uint32	resetstatus;	/* 0x804 */
-	uint32	resetreadid;	/* 0x808 */
-	uint32	resetwriteid;	/* 0x80c */
-	uint32	PAD[60];
-	uint32	errlogctrl;	/* 0x900 */
-	uint32	errlogdone;	/* 0x904 */
-	uint32	errlogstatus;	/* 0x908 */
-	uint32	errlogaddrlo;	/* 0x90c */
-	uint32	errlogaddrhi;	/* 0x910 */
-	uint32	errlogid;	/* 0x914 */
-	uint32	errloguser;	/* 0x918 */
-	uint32	errlogflags;	/* 0x91c */
-	uint32	PAD[56];
-	uint32	intstatus;	/* 0xa00 */
-	uint32	PAD[255];
-	uint32	config;		/* 0xe00 */
-	uint32	PAD[63];
-	uint32	itcr;		/* 0xf00 */
-	uint32	PAD[3];
-	uint32	itipooba;	/* 0xf10 */
-	uint32	itipoobb;	/* 0xf14 */
-	uint32	itipoobc;	/* 0xf18 */
-	uint32	itipoobd;	/* 0xf1c */
-	uint32	PAD[4];
-	uint32	itipoobaout;	/* 0xf30 */
-	uint32	itipoobbout;	/* 0xf34 */
-	uint32	itipoobcout;	/* 0xf38 */
-	uint32	itipoobdout;	/* 0xf3c */
-	uint32	PAD[4];
-	uint32	itopooba;	/* 0xf50 */
-	uint32	itopoobb;	/* 0xf54 */
-	uint32	itopoobc;	/* 0xf58 */
-	uint32	itopoobd;	/* 0xf5c */
-	uint32	PAD[4];
-	uint32	itopoobain;	/* 0xf70 */
-	uint32	itopoobbin;	/* 0xf74 */
-	uint32	itopoobcin;	/* 0xf78 */
-	uint32	itopoobdin;	/* 0xf7c */
-	uint32	PAD[4];
-	uint32	itopreset;	/* 0xf90 */
-	uint32	PAD[15];
-	uint32	peripherialid4;	/* 0xfd0 */
-	uint32	peripherialid5;	/* 0xfd4 */
-	uint32	peripherialid6;	/* 0xfd8 */
-	uint32	peripherialid7;	/* 0xfdc */
-	uint32	peripherialid0;	/* 0xfe0 */
-	uint32	peripherialid1;	/* 0xfe4 */
-	uint32	peripherialid2;	/* 0xfe8 */
-	uint32	peripherialid3;	/* 0xfec */
-	uint32	componentid0;	/* 0xff0 */
-	uint32	componentid1;	/* 0xff4 */
-	uint32	componentid2;	/* 0xff8 */
-	uint32	componentid3;	/* 0xffc */
-} aidmp_t;
-
-#endif /* !_LANGUAGE_ASSEMBLY && !__ASSEMBLY__ */
-
-/* Out-of-band Router registers */
-#define	OOB_BUSCONFIG		0x020
-#define	OOB_STATUSA		0x100
-#define	OOB_STATUSB		0x104
-#define	OOB_STATUSC		0x108
-#define	OOB_STATUSD		0x10c
-#define	OOB_ENABLEA0		0x200
-#define	OOB_ENABLEA1		0x204
-#define	OOB_ENABLEA2		0x208
-#define	OOB_ENABLEA3		0x20c
-#define	OOB_ENABLEB0		0x280
-#define	OOB_ENABLEB1		0x284
-#define	OOB_ENABLEB2		0x288
-#define	OOB_ENABLEB3		0x28c
-#define	OOB_ENABLEC0		0x300
-#define	OOB_ENABLEC1		0x304
-#define	OOB_ENABLEC2		0x308
-#define	OOB_ENABLEC3		0x30c
-#define	OOB_ENABLED0		0x380
-#define	OOB_ENABLED1		0x384
-#define	OOB_ENABLED2		0x388
-#define	OOB_ENABLED3		0x38c
-#define	OOB_ITCR		0xf00
-#define	OOB_ITIPOOBA		0xf10
-#define	OOB_ITIPOOBB		0xf14
-#define	OOB_ITIPOOBC		0xf18
-#define	OOB_ITIPOOBD		0xf1c
-#define	OOB_ITOPOOBA		0xf30
-#define	OOB_ITOPOOBB		0xf34
-#define	OOB_ITOPOOBC		0xf38
-#define	OOB_ITOPOOBD		0xf3c
-
-/* DMP wrapper registers */
-#define	AI_OOBSELINA30		0x000
-#define	AI_OOBSELINA74		0x004
-#define	AI_OOBSELINB30		0x020
-#define	AI_OOBSELINB74		0x024
-#define	AI_OOBSELINC30		0x040
-#define	AI_OOBSELINC74		0x044
-#define	AI_OOBSELIND30		0x060
-#define	AI_OOBSELIND74		0x064
-#define	AI_OOBSELOUTA30		0x100
-#define	AI_OOBSELOUTA74		0x104
-#define	AI_OOBSELOUTB30		0x120
-#define	AI_OOBSELOUTB74		0x124
-#define	AI_OOBSELOUTC30		0x140
-#define	AI_OOBSELOUTC74		0x144
-#define	AI_OOBSELOUTD30		0x160
-#define	AI_OOBSELOUTD74		0x164
-#define	AI_OOBSYNCA		0x200
-#define	AI_OOBSELOUTAEN		0x204
-#define	AI_OOBSYNCB		0x220
-#define	AI_OOBSELOUTBEN		0x224
-#define	AI_OOBSYNCC		0x240
-#define	AI_OOBSELOUTCEN		0x244
-#define	AI_OOBSYNCD		0x260
-#define	AI_OOBSELOUTDEN		0x264
-#define	AI_OOBAEXTWIDTH		0x300
-#define	AI_OOBAINWIDTH		0x304
-#define	AI_OOBAOUTWIDTH		0x308
-#define	AI_OOBBEXTWIDTH		0x320
-#define	AI_OOBBINWIDTH		0x324
-#define	AI_OOBBOUTWIDTH		0x328
-#define	AI_OOBCEXTWIDTH		0x340
-#define	AI_OOBCINWIDTH		0x344
-#define	AI_OOBCOUTWIDTH		0x348
-#define	AI_OOBDEXTWIDTH		0x360
-#define	AI_OOBDINWIDTH		0x364
-#define	AI_OOBDOUTWIDTH		0x368
-
-
-#define	AI_IOCTRLSET		0x400
-#define	AI_IOCTRLCLEAR		0x404
-#define	AI_IOCTRL		0x408
-#define	AI_IOSTATUS		0x500
-#define	AI_RESETCTRL		0x800
-#define	AI_RESETSTATUS		0x804
-
-#define	AI_IOCTRLWIDTH		0x700
-#define	AI_IOSTATUSWIDTH	0x704
-
-#define	AI_RESETREADID		0x808
-#define	AI_RESETWRITEID		0x80c
-#define	AI_ERRLOGCTRL		0x900
-#define	AI_ERRLOGDONE		0x904
-#define	AI_ERRLOGSTATUS		0x908
-#define	AI_ERRLOGADDRLO		0x90c
-#define	AI_ERRLOGADDRHI		0x910
-#define	AI_ERRLOGID		0x914
-#define	AI_ERRLOGUSER		0x918
-#define	AI_ERRLOGFLAGS		0x91c
-#define	AI_INTSTATUS		0xa00
-#define	AI_CONFIG		0xe00
-#define	AI_ITCR			0xf00
-#define	AI_ITIPOOBA		0xf10
-#define	AI_ITIPOOBB		0xf14
-#define	AI_ITIPOOBC		0xf18
-#define	AI_ITIPOOBD		0xf1c
-#define	AI_ITIPOOBAOUT		0xf30
-#define	AI_ITIPOOBBOUT		0xf34
-#define	AI_ITIPOOBCOUT		0xf38
-#define	AI_ITIPOOBDOUT		0xf3c
-#define	AI_ITOPOOBA		0xf50
-#define	AI_ITOPOOBB		0xf54
-#define	AI_ITOPOOBC		0xf58
-#define	AI_ITOPOOBD		0xf5c
-#define	AI_ITOPOOBAIN		0xf70
-#define	AI_ITOPOOBBIN		0xf74
-#define	AI_ITOPOOBCIN		0xf78
-#define	AI_ITOPOOBDIN		0xf7c
-#define	AI_ITOPRESET		0xf90
-#define	AI_PERIPHERIALID4	0xfd0
-#define	AI_PERIPHERIALID5	0xfd4
-#define	AI_PERIPHERIALID6	0xfd8
-#define	AI_PERIPHERIALID7	0xfdc
-#define	AI_PERIPHERIALID0	0xfe0
-#define	AI_PERIPHERIALID1	0xfe4
-#define	AI_PERIPHERIALID2	0xfe8
-#define	AI_PERIPHERIALID3	0xfec
-#define	AI_COMPONENTID0		0xff0
-#define	AI_COMPONENTID1		0xff4
-#define	AI_COMPONENTID2		0xff8
-#define	AI_COMPONENTID3		0xffc
-
-/* resetctrl */
-#define	AIRC_RESET		1
-
-/* errlogctrl */
-#define AIELC_TO_EXP_MASK	0x0000001f0		/* backplane timeout exponent */
-#define AIELC_TO_EXP_SHIFT	4
-#define AIELC_TO_ENAB_SHIFT	9			/* backplane timeout enable */
-
-/* errlogdone */
-#define AIELD_ERRDONE_MASK	0x3
-
-/* errlogstatus */
-#define AIELS_TIMEOUT_MASK	0x3
-
-/* config */
-#define	AICFG_OOB		0x00000020
-#define	AICFG_IOS		0x00000010
-#define	AICFG_IOC		0x00000008
-#define	AICFG_TO		0x00000004
-#define	AICFG_ERRL		0x00000002
-#define	AICFG_RST		0x00000001
-
-/* bit defines for AI_OOBSELOUTB74 reg */
-#define OOB_SEL_OUTEN_B_5	15
-#define OOB_SEL_OUTEN_B_6	23
-
-/* AI_OOBSEL for A/B/C/D, 0-7 */
-#define AI_OOBSEL_MASK		0x1F
-#define AI_OOBSEL_0_SHIFT	0
-#define AI_OOBSEL_1_SHIFT	8
-#define AI_OOBSEL_2_SHIFT	16
-#define AI_OOBSEL_3_SHIFT	24
-#define AI_OOBSEL_4_SHIFT	0
-#define AI_OOBSEL_5_SHIFT	8
-#define AI_OOBSEL_6_SHIFT	16
-#define AI_OOBSEL_7_SHIFT	24
-#define AI_IOCTRL_ENABLE_D11_PME	(1 << 14)
-
-#endif	/* _AIDMP_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcm_cfg.h b/drivers/net/wireless/bcmdhd/include/bcm_cfg.h
deleted file mode 100644
index e71f5c8..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcm_cfg.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * BCM common config options
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcm_cfg.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef _bcm_cfg_h_
-#define _bcm_cfg_h_
-#endif /* _bcm_cfg_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h b/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h
deleted file mode 100644
index 79ae0f5..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Memory pools library, Public interface
- *
- * API Overview
- *
- * This package provides a memory allocation subsystem based on pools of
- * homogenous objects.
- *
- * Instrumentation is available for reporting memory utilization both
- * on a per-data-structure basis and system wide.
- *
- * There are two main types defined in this API.
- *
- *    pool manager: A singleton object that acts as a factory for
- *                  pool allocators. It also is used for global
- *                  instrumentation, such as reporting all blocks
- *                  in use across all data structures. The pool manager
- *                  creates and provides individual memory pools
- *                  upon request to application code.
- *
- *    memory pool:  An object for allocating homogenous memory blocks.
- *
- * Global identifiers in this module use the following prefixes:
- *    bcm_mpm_*     Memory pool manager
- *    bcm_mp_*      Memory pool
- *
- * There are two main types of memory pools:
- *
- *    prealloc: The contiguous memory block of objects can either be supplied
- *              by the client or malloc'ed by the memory manager. The objects are
- *              allocated out of a block of memory and freed back to the block.
- *
- *    heap:     The memory pool allocator uses the heap (malloc/free) for memory.
- *              In this case, the pool allocator is just providing statistics
- *              and instrumentation on top of the heap, without modifying the heap
- *              allocation implementation.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcm_mpool_pub.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef _BCM_MPOOL_PUB_H
-#define _BCM_MPOOL_PUB_H 1
-
-#include <typedefs.h> /* needed for uint16 */
-
-
-/*
-**************************************************************************
-*
-* Type definitions, handles
-*
-**************************************************************************
-*/
-
-/* Forward declaration of OSL handle. */
-struct osl_info;
-
-/* Forward declaration of string buffer. */
-struct bcmstrbuf;
-
-/*
- * Opaque type definition for the pool manager handle. This object is used for global
- * memory pool operations such as obtaining a new pool, deleting a pool, iterating and
- * instrumentation/debugging.
- */
-struct bcm_mpm_mgr;
-typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h;
-
-/*
- * Opaque type definition for an instance of a pool. This handle is used for allocating
- * and freeing memory through the pool, as well as management/instrumentation on this
- * specific pool.
- */
-struct bcm_mp_pool;
-typedef struct bcm_mp_pool *bcm_mp_pool_h;
-
-
-/*
- * To make instrumentation more readable, every memory
- * pool must have a readable name. Pool names are up to
- * 8 bytes including '\0' termination. (7 printable characters.)
- */
-#define BCM_MP_NAMELEN 8
-
-
-/*
- * Type definition for pool statistics.
- */
-typedef struct bcm_mp_stats {
-	char name[BCM_MP_NAMELEN];  /* Name of this pool. */
-	unsigned int objsz;         /* Object size allocated in this pool */
-	uint16 nobj;                /* Total number of objects in this pool */
-	uint16 num_alloc;           /* Number of objects currently allocated */
-	uint16 high_water;          /* Max number of allocated objects. */
-	uint16 failed_alloc;        /* Failed allocations. */
-} bcm_mp_stats_t;
-
-
-/*
-**************************************************************************
-*
-* API Routines on the pool manager.
-*
-**************************************************************************
-*/
-
-/*
- * bcm_mpm_init() - initialize the whole memory pool system.
- *
- * Parameters:
- *    osh:       INPUT  Operating system handle. Needed for heap memory allocation.
- *    max_pools: INPUT Maximum number of mempools supported.
- *    mgr:       OUTPUT The handle is written with the new pools manager object/handle.
- *
- * Returns:
- *    BCME_OK     Object initialized successfully. May be used.
- *    BCME_NOMEM  Initialization failed due to no memory. Object must not be used.
- */
-int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp);
-
-
-/*
- * bcm_mpm_deinit() - de-initialize the whole memory pool system.
- *
- * Parameters:
- *    mgr:     INPUT  Pointer to pool manager handle.
- *
- * Returns:
- *    BCME_OK  Memory pool manager successfully de-initialized.
- *    other    Indicated error occured during de-initialization.
- */
-int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp);
-
-/*
- * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The
- *                                  pool uses a contiguous block of pre-alloced
- *                                  memory. The memory block may either be provided
- *                                  by the client or dynamically allocated by the
- *                                  pool manager.
- *
- * Parameters:
- *    mgr:      INPUT  The handle to the pool manager
- *    obj_sz:   INPUT  Size of objects that will be allocated by the new pool
- *                     Must be >= sizeof(void *).
- *    nobj:     INPUT  Maximum number of concurrently existing objects to support
- *    memstart  INPUT  Pointer to the memory to use, or NULL to malloc()
- *    memsize   INPUT  Number of bytes referenced from memstart (for error checking).
- *                     Must be 0 if 'memstart' is NULL.
- *    poolname  INPUT  For instrumentation, the name of the pool
- *    newp:     OUTPUT The handle for the new pool, if creation is successful
- *
- * Returns:
- *    BCME_OK   Pool created ok.
- *    other     Pool not created due to indicated error. newpoolp set to NULL.
- *
- *
- */
-int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr,
-                                 unsigned int obj_sz,
-                                 int nobj,
-                                 void *memstart,
-                                 unsigned int memsize,
-                                 const char poolname[BCM_MP_NAMELEN],
-                                 bcm_mp_pool_h *newp);
-
-
-/*
- * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after
- *                                  all memory objects have been freed back to the pool.
- *
- * Parameters:
- *    mgr:     INPUT The handle to the pools manager
- *    pool:    INPUT The handle of the  pool to delete
- *
- * Returns:
- *    BCME_OK   Pool deleted ok.
- *    other     Pool not deleted due to indicated error.
- *
- */
-int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp);
-
-/*
- * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory
- *                              pool allocator uses the heap (malloc/free) for memory.
- *                              In this case, the pool allocator is just providing
- *                              statistics and instrumentation on top of the heap,
- *                              without modifying the heap allocation implementation.
- *
- * Parameters:
- *    mgr:      INPUT  The handle to the pool manager
- *    obj_sz:   INPUT  Size of objects that will be allocated by the new pool
- *    poolname  INPUT  For instrumentation, the name of the pool
- *    newp:     OUTPUT The handle for the new pool, if creation is successful
- *
- * Returns:
- *    BCME_OK   Pool created ok.
- *    other     Pool not created due to indicated error. newpoolp set to NULL.
- *
- *
- */
-int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz,
-                             const char poolname[BCM_MP_NAMELEN],
-                             bcm_mp_pool_h *newp);
-
-
-/*
- * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after
- *                              all memory objects have been freed back to the pool.
- *
- * Parameters:
- *    mgr:     INPUT The handle to the pools manager
- *    pool:    INPUT The handle of the  pool to delete
- *
- * Returns:
- *    BCME_OK   Pool deleted ok.
- *    other     Pool not deleted due to indicated error.
- *
- */
-int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp);
-
-
-/*
- * bcm_mpm_stats() - Return stats for all pools
- *
- * Parameters:
- *    mgr:         INPUT   The handle to the pools manager
- *    stats:       OUTPUT  Array of pool statistics.
- *    nentries:    MOD     Max elements in 'stats' array on INPUT. Actual number
- *                         of array elements copied to 'stats' on OUTPUT.
- *
- * Returns:
- *    BCME_OK   Ok
- *    other     Error getting stats.
- *
- */
-int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries);
-
-
-/*
- * bcm_mpm_dump() - Display statistics on all pools
- *
- * Parameters:
- *    mgr:     INPUT  The handle to the pools manager
- *    b:       OUTPUT Output buffer.
- *
- * Returns:
- *    BCME_OK   Ok
- *    other     Error during dump.
- *
- */
-int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b);
-
-
-/*
- * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to
- *                          compensate for alignment requirements of the objects.
- *                          This function provides the padded object size. If clients
- *                          pre-allocate a memory slab for a memory pool, the
- *                          padded object size should be used by the client to allocate
- *                          the memory slab (in order to provide sufficent space for
- *                          the maximum number of objects).
- *
- * Parameters:
- *    mgr:            INPUT   The handle to the pools manager.
- *    obj_sz:         INPUT   Input object size.
- *    padded_obj_sz:  OUTPUT  Padded object size.
- *
- * Returns:
- *    BCME_OK      Ok
- *    BCME_BADARG  Bad arguments.
- *
- */
-int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz);
-
-
-/*
-***************************************************************************
-*
-* API Routines on a specific pool.
-*
-***************************************************************************
-*/
-
-
-/*
- * bcm_mp_alloc() - Allocate a memory pool object.
- *
- * Parameters:
- *    pool:    INPUT    The handle to the pool.
- *
- * Returns:
- *    A pointer to the new object. NULL on error.
- *
- */
-void* bcm_mp_alloc(bcm_mp_pool_h pool);
-
-/*
- * bcm_mp_free() - Free a memory pool object.
- *
- * Parameters:
- *    pool:  INPUT   The handle to the pool.
- *    objp:  INPUT   A pointer to the object to free.
- *
- * Returns:
- *    BCME_OK   Ok
- *    other     Error during free.
- *
- */
-int bcm_mp_free(bcm_mp_pool_h pool, void *objp);
-
-/*
- * bcm_mp_stats() - Return stats for this pool
- *
- * Parameters:
- *    pool:     INPUT    The handle to the pool
- *    stats:    OUTPUT   Pool statistics
- *
- * Returns:
- *    BCME_OK   Ok
- *    other     Error getting statistics.
- *
- */
-int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats);
-
-
-/*
- * bcm_mp_dump() - Dump a pool
- *
- * Parameters:
- *    pool:    INPUT    The handle to the pool
- *    b        OUTPUT   Output buffer
- *
- * Returns:
- *    BCME_OK   Ok
- *    other     Error during dump.
- *
- */
-int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b);
-
-
-#endif /* _BCM_MPOOL_PUB_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcm_ring.h b/drivers/net/wireless/bcmdhd/include/bcm_ring.h
deleted file mode 100644
index 5f1b38c..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcm_ring.h
+++ /dev/null
@@ -1,616 +0,0 @@
-#ifndef __bcm_ring_included__
-#define __bcm_ring_included__
-
-/*
- * +----------------------------------------------------------------------------
- *
- * bcm_ring.h : Ring context abstraction
- *
- * The ring context tracks the WRITE and READ indices where elements may be
- * produced and consumed respectively. All elements in the ring need to be
- * fixed size.
- *
- * NOTE: A ring of size N, may only hold N-1 elements.
- *
- * +----------------------------------------------------------------------------
- *
- * API Notes:
- *
- * Ring manipulation API allows for:
- *  Pending operations: Often before some work can be completed, it may be
- *  desired that several resources are available, e.g. space for production in
- *  a ring. Approaches such as, #1) reserve resources one by one and return them
- *  if another required resource is not available, or #2) employ a two pass
- *  algorithm of first testing whether all resources are available, have a
- *  an impact on performance critical code. The approach taken here is more akin
- *  to approach #2, where a test for resource availability essentially also
- *  provides the index for production in an un-committed state.
- *  The same approach is taken for the consumer side.
- *
- *  - Pending production: Fetch the next index where a ring element may be
- *    produced. The caller may not commit the WRITE of the element.
- *  - Pending consumption: Fetch the next index where a ring element may be
- *    consumed. The caller may not commut the READ of the element.
- *
- *  Producer side API:
- *  - bcm_ring_is_full  : Test whether ring is full
- *  - bcm_ring_prod     : Fetch index where an element may be produced (commit)
- *  - bcm_ring_prod_pend: Fetch index where an element may be produced (pending)
- *  - bcm_ring_prod_done: Commit a previous pending produce fetch
- *  - bcm_ring_prod_avail: Fetch total number free slots eligible for production
- *
- * Consumer side API:
- *  - bcm_ring_is_empty : Test whether ring is empty
- *  - bcm_ring_cons     : Fetch index where an element may be consumed (commit)
- *  - bcm_ring_cons_pend: Fetch index where an element may be consumed (pending)
- *  - bcm_ring_cons_done: Commit a previous pending consume fetch
- *  - bcm_ring_cons_avail: Fetch total number elements eligible for consumption
- *
- *  - bcm_ring_sync_read: Sync read offset in peer ring, from local ring
- *  - bcm_ring_sync_write: Sync write offset in peer ring, from local ring
- *
- * +----------------------------------------------------------------------------
- *
- * Design Notes:
- * Following items are not tracked in a ring context (design decision)
- *  - width of a ring element.
- *  - depth of the ring.
- *  - base of the buffer, where the elements are stored.
- *  - count of number of free slots in the ring
- *
- * Implementation Notes:
- *  - When BCM_RING_DEBUG is enabled, need explicit bcm_ring_init().
- *  - BCM_RING_EMPTY and BCM_RING_FULL are (-1)
- *
- * +----------------------------------------------------------------------------
- *
- * Usage Notes:
- * An application may incarnate a ring of some fixed sized elements, by defining
- *  - a ring data buffer to store the ring elements.
- *  - depth of the ring (max number of elements managed by ring context).
- *    Preferrably, depth may be represented as a constant.
- *  - width of a ring element: to be used in pointer arithmetic with the ring's
- *    data buffer base and an index to fetch the ring element.
- *
- * Use bcm_workq_t to instantiate a pair of workq constructs, one for the
- * producer and the other for the consumer, both pointing to the same circular
- * buffer. The producer may operate on it's own local workq and flush the write
- * index to the consumer. Likewise the consumer may use its local workq and
- * flush the read index to the producer. This way we do not repeatedly access
- * the peer's context. The two peers may reside on different CPU cores with a
- * private L1 data cache.
- * +----------------------------------------------------------------------------
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcm_ring.h 591283 2015-10-07 11:52:00Z $
- *
- * -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
- * vim: set ts=4 noet sw=4 tw=80:
- *
- * +----------------------------------------------------------------------------
- */
-
-#ifdef ____cacheline_aligned
-#define __ring_aligned                      ____cacheline_aligned
-#else
-#define __ring_aligned
-#endif
-
-/* Conditional compile for debug */
-/* #define BCM_RING_DEBUG */
-
-#define BCM_RING_EMPTY                      (-1)
-#define BCM_RING_FULL                       (-1)
-#define BCM_RING_NULL                       ((bcm_ring_t *)NULL)
-
-#if defined(BCM_RING_DEBUG)
-#define RING_ASSERT(exp)                    ASSERT(exp)
-#define BCM_RING_IS_VALID(ring)             (((ring) != BCM_RING_NULL) && \
-	                                         ((ring)->self == (ring)))
-#else  /* ! BCM_RING_DEBUG */
-#define RING_ASSERT(exp)                    do {} while (0)
-#define BCM_RING_IS_VALID(ring)             ((ring) != BCM_RING_NULL)
-#endif /* ! BCM_RING_DEBUG */
-
-#define BCM_RING_SIZE_IS_VALID(ring_size)   ((ring_size) > 0)
-
-/*
- * +----------------------------------------------------------------------------
- * Ring Context
- * +----------------------------------------------------------------------------
- */
-typedef struct bcm_ring {     /* Ring context */
-#if defined(BCM_RING_DEBUG)
-	struct bcm_ring *self;    /* ptr to self for IS VALID test */
-#endif /* BCM_RING_DEBUG */
-	int write __ring_aligned; /* WRITE index in a circular ring */
-	int read  __ring_aligned; /* READ index in a circular ring */
-} bcm_ring_t;
-
-
-static INLINE void bcm_ring_init(bcm_ring_t *ring);
-static INLINE void bcm_ring_copy(bcm_ring_t *to, bcm_ring_t *from);
-static INLINE bool bcm_ring_is_empty(bcm_ring_t *ring);
-
-static INLINE int  __bcm_ring_next_write(bcm_ring_t *ring, const int ring_size);
-
-static INLINE bool __bcm_ring_full(bcm_ring_t *ring, int next_write);
-static INLINE bool bcm_ring_is_full(bcm_ring_t *ring, const int ring_size);
-
-static INLINE void bcm_ring_prod_done(bcm_ring_t *ring, int write);
-static INLINE int  bcm_ring_prod_pend(bcm_ring_t *ring, int *pend_write,
-                                      const int ring_size);
-static INLINE int  bcm_ring_prod(bcm_ring_t *ring, const int ring_size);
-
-static INLINE void bcm_ring_cons_done(bcm_ring_t *ring, int read);
-static INLINE int  bcm_ring_cons_pend(bcm_ring_t *ring, int *pend_read,
-                                      const int ring_size);
-static INLINE int  bcm_ring_cons(bcm_ring_t *ring, const int ring_size);
-
-static INLINE void bcm_ring_sync_read(bcm_ring_t *peer, const bcm_ring_t *self);
-static INLINE void bcm_ring_sync_write(bcm_ring_t *peer, const bcm_ring_t *self);
-
-static INLINE int  bcm_ring_prod_avail(const bcm_ring_t *ring,
-                                       const int ring_size);
-static INLINE int  bcm_ring_cons_avail(const bcm_ring_t *ring,
-                                       const int ring_size);
-static INLINE void bcm_ring_cons_all(bcm_ring_t *ring);
-
-
-/**
- * bcm_ring_init - initialize a ring context.
- * @ring: pointer to a ring context
- */
-static INLINE void
-bcm_ring_init(bcm_ring_t *ring)
-{
-	ASSERT(ring != (bcm_ring_t *)NULL);
-#if defined(BCM_RING_DEBUG)
-	ring->self = ring;
-#endif /* BCM_RING_DEBUG */
-	ring->write = 0;
-	ring->read = 0;
-}
-
-/**
- * bcm_ring_copy - copy construct a ring
- * @to: pointer to the new ring context
- * @from: pointer to orig ring context
- */
-static INLINE void
-bcm_ring_copy(bcm_ring_t *to, bcm_ring_t *from)
-{
-	bcm_ring_init(to);
-
-	to->write = from->write;
-	to->read  = from->read;
-}
-
-/**
- * bcm_ring_is_empty - "Boolean" test whether ring is empty.
- * @ring: pointer to a ring context
- *
- * PS. does not return BCM_RING_EMPTY value.
- */
-static INLINE bool
-bcm_ring_is_empty(bcm_ring_t *ring)
-{
-	RING_ASSERT(BCM_RING_IS_VALID(ring));
-	return (ring->read == ring->write);
-}
-
-
-/**
- * __bcm_ring_next_write - determine the index where the next write may occur
- *                         (with wrap-around).
- * @ring: pointer to a ring context
- * @ring_size: size of the ring
- *
- * PRIVATE INTERNAL USE ONLY.
- */
-static INLINE int
-__bcm_ring_next_write(bcm_ring_t *ring, const int ring_size)
-{
-	RING_ASSERT(BCM_RING_IS_VALID(ring) && BCM_RING_SIZE_IS_VALID(ring_size));
-	return ((ring->write + 1) % ring_size);
-}
-
-
-/**
- * __bcm_ring_full - support function for ring full test.
- * @ring: pointer to a ring context
- * @next_write: next location in ring where an element is to be produced
- *
- * PRIVATE INTERNAL USE ONLY.
- */
-static INLINE bool
-__bcm_ring_full(bcm_ring_t *ring, int next_write)
-{
-	return (next_write == ring->read);
-}
-
-
-/**
- * bcm_ring_is_full - "Boolean" test whether a ring is full.
- * @ring: pointer to a ring context
- * @ring_size: size of the ring
- *
- * PS. does not return BCM_RING_FULL value.
- */
-static INLINE bool
-bcm_ring_is_full(bcm_ring_t *ring, const int ring_size)
-{
-	int next_write;
-	RING_ASSERT(BCM_RING_IS_VALID(ring) && BCM_RING_SIZE_IS_VALID(ring_size));
-	next_write = __bcm_ring_next_write(ring, ring_size);
-	return __bcm_ring_full(ring, next_write);
-}
-
-
-/**
- * bcm_ring_prod_done - commit a previously pending index where production
- * was requested.
- * @ring: pointer to a ring context
- * @write: index into ring upto where production was done.
- * +----------------------------------------------------------------------------
- */
-static INLINE void
-bcm_ring_prod_done(bcm_ring_t *ring, int write)
-{
-	RING_ASSERT(BCM_RING_IS_VALID(ring));
-	ring->write = write;
-}
-
-
-/**
- * bcm_ring_prod_pend - Fetch in "pend" mode, the index where an element may be
- * produced.
- * @ring: pointer to a ring context
- * @pend_write: next index, after the returned index
- * @ring_size: size of the ring
- */
-static INLINE int
-bcm_ring_prod_pend(bcm_ring_t *ring, int *pend_write, const int ring_size)
-{
-	int rtn;
-	RING_ASSERT(BCM_RING_IS_VALID(ring) && BCM_RING_SIZE_IS_VALID(ring_size));
-	*pend_write = __bcm_ring_next_write(ring, ring_size);
-	if (__bcm_ring_full(ring, *pend_write)) {
-		*pend_write = BCM_RING_FULL;
-		rtn = BCM_RING_FULL;
-	} else {
-		/* production is not committed, caller needs to explicitly commit */
-		rtn = ring->write;
-	}
-	return rtn;
-}
-
-
-/**
- * bcm_ring_prod - Fetch and "commit" the next index where a ring element may
- * be produced.
- * @ring: pointer to a ring context
- * @ring_size: size of the ring
- */
-static INLINE int
-bcm_ring_prod(bcm_ring_t *ring, const int ring_size)
-{
-	int next_write, prod_write;
-	RING_ASSERT(BCM_RING_IS_VALID(ring) && BCM_RING_SIZE_IS_VALID(ring_size));
-
-	next_write = __bcm_ring_next_write(ring, ring_size);
-	if (__bcm_ring_full(ring, next_write)) {
-		prod_write = BCM_RING_FULL;
-	} else {
-		prod_write = ring->write;
-		bcm_ring_prod_done(ring, next_write); /* "commit" production */
-	}
-	return prod_write;
-}
-
-
-/**
- * bcm_ring_cons_done - commit a previously pending read
- * @ring: pointer to a ring context
- * @read: index upto which elements have been consumed.
- */
-static INLINE void
-bcm_ring_cons_done(bcm_ring_t *ring, int read)
-{
-	RING_ASSERT(BCM_RING_IS_VALID(ring));
-	ring->read = read;
-}
-
-
-/**
- * bcm_ring_cons_pend - fetch in "pend" mode, the next index where a ring
- * element may be consumed.
- * @ring: pointer to a ring context
- * @pend_read: index into ring upto which elements may be consumed.
- * @ring_size: size of the ring
- */
-static INLINE int
-bcm_ring_cons_pend(bcm_ring_t *ring, int *pend_read, const int ring_size)
-{
-	int rtn;
-	RING_ASSERT(BCM_RING_IS_VALID(ring) && BCM_RING_SIZE_IS_VALID(ring_size));
-	if (bcm_ring_is_empty(ring)) {
-		*pend_read = BCM_RING_EMPTY;
-		rtn = BCM_RING_EMPTY;
-	} else {
-		*pend_read = (ring->read + 1) % ring_size;
-		/* production is not committed, caller needs to explicitly commit */
-		rtn = ring->read;
-	}
-	return rtn;
-}
-
-
-/**
- * bcm_ring_cons - fetch and "commit" the next index where a ring element may
- * be consumed.
- * @ring: pointer to a ring context
- * @ring_size: size of the ring
- */
-static INLINE int
-bcm_ring_cons(bcm_ring_t *ring, const int ring_size)
-{
-	int cons_read;
-	RING_ASSERT(BCM_RING_IS_VALID(ring) && BCM_RING_SIZE_IS_VALID(ring_size));
-	if (bcm_ring_is_empty(ring)) {
-		cons_read = BCM_RING_EMPTY;
-	} else {
-		cons_read = ring->read;
-		ring->read = (ring->read + 1) % ring_size; /* read is committed */
-	}
-	return cons_read;
-}
-
-
-/**
- * bcm_ring_sync_read - on consumption, update peer's read index.
- * @peer: pointer to peer's producer ring context
- * @self: pointer to consumer's ring context
- */
-static INLINE void
-bcm_ring_sync_read(bcm_ring_t *peer, const bcm_ring_t *self)
-{
-	RING_ASSERT(BCM_RING_IS_VALID(peer));
-	RING_ASSERT(BCM_RING_IS_VALID(self));
-	peer->read = self->read; /* flush read update to peer producer */
-}
-
-
-/**
- * bcm_ring_sync_write - on consumption, update peer's write index.
- * @peer: pointer to peer's consumer ring context
- * @self: pointer to producer's ring context
- */
-static INLINE void
-bcm_ring_sync_write(bcm_ring_t *peer, const bcm_ring_t *self)
-{
-	RING_ASSERT(BCM_RING_IS_VALID(peer));
-	RING_ASSERT(BCM_RING_IS_VALID(self));
-	peer->write = self->write; /* flush write update to peer consumer */
-}
-
-
-/**
- * bcm_ring_prod_avail - fetch total number of available empty slots in the
- * ring for production.
- * @ring: pointer to a ring context
- * @ring_size: size of the ring
- */
-static INLINE int
-bcm_ring_prod_avail(const bcm_ring_t *ring, const int ring_size)
-{
-	int prod_avail;
-	RING_ASSERT(BCM_RING_IS_VALID(ring) && BCM_RING_SIZE_IS_VALID(ring_size));
-	if (ring->write >= ring->read) {
-		prod_avail = (ring_size - (ring->write - ring->read) - 1);
-	} else {
-		prod_avail = (ring->read - (ring->write + 1));
-	}
-	ASSERT(prod_avail < ring_size);
-	return prod_avail;
-}
-
-
-/**
- * bcm_ring_cons_avail - fetch total number of available elements for consumption.
- * @ring: pointer to a ring context
- * @ring_size: size of the ring
- */
-static INLINE int
-bcm_ring_cons_avail(const bcm_ring_t *ring, const int ring_size)
-{
-	int cons_avail;
-	RING_ASSERT(BCM_RING_IS_VALID(ring) && BCM_RING_SIZE_IS_VALID(ring_size));
-	if (ring->read == ring->write) {
-		cons_avail = 0;
-	} else if (ring->read > ring->write) {
-		cons_avail = ((ring_size - ring->read) + ring->write);
-	} else {
-		cons_avail = ring->write - ring->read;
-	}
-	ASSERT(cons_avail < ring_size);
-	return cons_avail;
-}
-
-
-/**
- * bcm_ring_cons_all - set ring in state where all elements are consumed.
- * @ring: pointer to a ring context
- */
-static INLINE void
-bcm_ring_cons_all(bcm_ring_t *ring)
-{
-	ring->read = ring->write;
-}
-
-
-/**
- * Work Queue
- * A work Queue is composed of a ring of work items, of a specified depth.
- * It HAS-A bcm_ring object, comprising of a RD and WR offset, to implement a
- * producer/consumer circular ring.
- */
-
-struct bcm_workq {
-	bcm_ring_t ring;        /* Ring context abstraction */
-	struct bcm_workq *peer; /* Peer workq context */
-	void       *buffer;     /* Buffer storage for work items in workQ */
-	int        ring_size;   /* Depth of workQ */
-} __ring_aligned;
-
-typedef struct bcm_workq bcm_workq_t;
-
-
-/* #define BCM_WORKQ_DEBUG */
-#if defined(BCM_WORKQ_DEBUG)
-#define WORKQ_ASSERT(exp)               ASSERT(exp)
-#else  /* ! BCM_WORKQ_DEBUG */
-#define WORKQ_ASSERT(exp)               do {} while (0)
-#endif /* ! BCM_WORKQ_DEBUG */
-
-#define WORKQ_AUDIT(workq) \
-	WORKQ_ASSERT((workq) != BCM_WORKQ_NULL); \
-	WORKQ_ASSERT(WORKQ_PEER(workq) != BCM_WORKQ_NULL); \
-	WORKQ_ASSERT((workq)->buffer == WORKQ_PEER(workq)->buffer); \
-	WORKQ_ASSERT((workq)->ring_size == WORKQ_PEER(workq)->ring_size);
-
-#define BCM_WORKQ_NULL                  ((bcm_workq_t *)NULL)
-
-#define WORKQ_PEER(workq)               ((workq)->peer)
-#define WORKQ_RING(workq)               (&((workq)->ring))
-#define WORKQ_PEER_RING(workq)          (&((workq)->peer->ring))
-
-#define WORKQ_ELEMENT(__elem_type, __workq, __index) ({ \
-	WORKQ_ASSERT((__workq) != BCM_WORKQ_NULL); \
-	WORKQ_ASSERT((__index) < ((__workq)->ring_size)); \
-	((__elem_type *)((__workq)->buffer)) + (__index); \
-})
-
-
-static INLINE void bcm_workq_init(bcm_workq_t *workq, bcm_workq_t *workq_peer,
-                                  void *buffer, int ring_size);
-
-static INLINE bool bcm_workq_is_empty(bcm_workq_t *workq_prod);
-
-static INLINE void bcm_workq_prod_sync(bcm_workq_t *workq_prod);
-static INLINE void bcm_workq_cons_sync(bcm_workq_t *workq_cons);
-
-static INLINE void bcm_workq_prod_refresh(bcm_workq_t *workq_prod);
-static INLINE void bcm_workq_cons_refresh(bcm_workq_t *workq_cons);
-
-/**
- * bcm_workq_init - initialize a workq
- * @workq: pointer to a workq context
- * @buffer: pointer to a pre-allocated circular buffer to serve as a ring
- * @ring_size: size of the ring in terms of max number of elements.
- */
-static INLINE void
-bcm_workq_init(bcm_workq_t *workq, bcm_workq_t *workq_peer,
-               void *buffer, int ring_size)
-{
-	ASSERT(workq != BCM_WORKQ_NULL);
-	ASSERT(workq_peer != BCM_WORKQ_NULL);
-	ASSERT(buffer != NULL);
-	ASSERT(ring_size > 0);
-
-	WORKQ_PEER(workq) = workq_peer;
-	WORKQ_PEER(workq_peer) = workq;
-
-	bcm_ring_init(WORKQ_RING(workq));
-	bcm_ring_init(WORKQ_RING(workq_peer));
-
-	workq->buffer = workq_peer->buffer = buffer;
-	workq->ring_size = workq_peer->ring_size = ring_size;
-}
-
-/**
- * bcm_workq_empty - test whether there is work
- * @workq_prod: producer's workq
- */
-static INLINE bool
-bcm_workq_is_empty(bcm_workq_t *workq_prod)
-{
-	return bcm_ring_is_empty(WORKQ_RING(workq_prod));
-}
-
-/**
- * bcm_workq_prod_sync - Commit the producer write index to peer workq's ring
- * @workq_prod: producer's workq whose write index must be synced to peer
- */
-static INLINE void
-bcm_workq_prod_sync(bcm_workq_t *workq_prod)
-{
-	WORKQ_AUDIT(workq_prod);
-
-	/* cons::write <--- prod::write */
-	bcm_ring_sync_write(WORKQ_PEER_RING(workq_prod), WORKQ_RING(workq_prod));
-}
-
-/**
- * bcm_workq_cons_sync - Commit the consumer read index to the peer workq's ring
- * @workq_cons: consumer's workq whose read index must be synced to peer
- */
-static INLINE void
-bcm_workq_cons_sync(bcm_workq_t *workq_cons)
-{
-	WORKQ_AUDIT(workq_cons);
-
-	/* prod::read <--- cons::read */
-	bcm_ring_sync_read(WORKQ_PEER_RING(workq_cons), WORKQ_RING(workq_cons));
-}
-
-
-/**
- * bcm_workq_prod_refresh - Fetch the updated consumer's read index
- * @workq_prod: producer's workq whose read index must be refreshed from peer
- */
-static INLINE void
-bcm_workq_prod_refresh(bcm_workq_t *workq_prod)
-{
-	WORKQ_AUDIT(workq_prod);
-
-	/* prod::read <--- cons::read */
-	bcm_ring_sync_read(WORKQ_RING(workq_prod), WORKQ_PEER_RING(workq_prod));
-}
-
-/**
- * bcm_workq_cons_refresh - Fetch the updated producer's write index
- * @workq_cons: consumer's workq whose write index must be refreshed from peer
- */
-static INLINE void
-bcm_workq_cons_refresh(bcm_workq_t *workq_cons)
-{
-	WORKQ_AUDIT(workq_cons);
-
-	/* cons::write <--- prod::write */
-	bcm_ring_sync_write(WORKQ_RING(workq_cons), WORKQ_PEER_RING(workq_cons));
-}
-
-
-#endif /* ! __bcm_ring_h_included__ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmcdc.h b/drivers/net/wireless/bcmdhd/include/bcmcdc.h
deleted file mode 100644
index a95dc31..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmcdc.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * CDC network driver ioctl/indication encoding
- * Broadcom 802.11abg Networking Device Driver
- *
- * Definitions subject to change without notice.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmcdc.h 514727 2014-11-12 03:02:48Z $
- */
-#ifndef _bcmcdc_h_
-#define	_bcmcdc_h_
-#include <proto/ethernet.h>
-
-typedef struct cdc_ioctl {
-	uint32 cmd;      /* ioctl command value */
-	uint32 len;      /* lower 16: output buflen; upper 16: input buflen (excludes header) */
-	uint32 flags;    /* flag defns given below */
-	uint32 status;   /* status code returned from the device */
-} cdc_ioctl_t;
-
-/* Max valid buffer size that can be sent to the dongle */
-#define CDC_MAX_MSG_SIZE   ETHER_MAX_LEN
-
-/* len field is divided into input and output buffer lengths */
-#define CDCL_IOC_OUTLEN_MASK   0x0000FFFF  /* maximum or expected response length, */
-					   /* excluding IOCTL header */
-#define CDCL_IOC_OUTLEN_SHIFT  0
-#define CDCL_IOC_INLEN_MASK    0xFFFF0000   /* input buffer length, excluding IOCTL header */
-#define CDCL_IOC_INLEN_SHIFT   16
-
-/* CDC flag definitions */
-#define CDCF_IOC_ERROR		0x01	/* 0=success, 1=ioctl cmd failed */
-#define CDCF_IOC_SET		0x02	/* 0=get, 1=set cmd */
-#define CDCF_IOC_OVL_IDX_MASK	0x3c	/* overlay region index mask */
-#define CDCF_IOC_OVL_RSV	0x40	/* 1=reserve this overlay region */
-#define CDCF_IOC_OVL		0x80	/* 1=this ioctl corresponds to an overlay */
-#define CDCF_IOC_ACTION_MASK	0xfe	/* SET/GET, OVL_IDX, OVL_RSV, OVL mask */
-#define CDCF_IOC_ACTION_SHIFT	1	/* SET/GET, OVL_IDX, OVL_RSV, OVL shift */
-#define CDCF_IOC_IF_MASK	0xF000	/* I/F index */
-#define CDCF_IOC_IF_SHIFT	12
-#define CDCF_IOC_ID_MASK	0xFFFF0000	/* used to uniquely id an ioctl req/resp pairing */
-#define CDCF_IOC_ID_SHIFT	16		/* # of bits of shift for ID Mask */
-
-#define CDC_IOC_IF_IDX(flags)	(((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
-#define CDC_IOC_ID(flags)	(((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
-
-#define CDC_GET_IF_IDX(hdr) \
-	((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
-#define CDC_SET_IF_IDX(hdr, idx) \
-	((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT)))
-
-/*
- * BDC header
- *
- *   The BDC header is used on data packets to convey priority across USB.
- */
-
-struct bdc_header {
-	uint8	flags;			/* Flags */
-	uint8	priority;		/* 802.1d Priority 0:2 bits, 4:7 USB flow control info */
-	uint8	flags2;
-	uint8	dataOffset;		/* Offset from end of BDC header to packet data, in
-					 * 4-byte words.  Leaves room for optional headers.
-					 */
-};
-
-#define	BDC_HEADER_LEN		4
-
-/* flags field bitmap */
-#define BDC_FLAG_80211_PKT	0x01	/* Packet is in 802.11 format (dongle -> host) */
-#define BDC_FLAG_SUM_GOOD	0x04	/* Dongle has verified good RX checksums */
-#define BDC_FLAG_SUM_NEEDED	0x08	/* Dongle needs to do TX checksums: host->device */
-#define BDC_FLAG_EVENT_MSG	0x08	/* Payload contains an event msg: device->host */
-#define BDC_FLAG_VER_MASK	0xf0	/* Protocol version mask */
-#define BDC_FLAG_VER_SHIFT	4	/* Protocol version shift */
-
-/* priority field bitmap */
-#define BDC_PRIORITY_MASK	0x07
-#define BDC_PRIORITY_FC_MASK	0xf0	/* flow control info mask */
-#define BDC_PRIORITY_FC_SHIFT	4	/* flow control info shift */
-
-/* flags2 field bitmap */
-#define BDC_FLAG2_IF_MASK	0x0f	/* interface index (host <-> dongle) */
-#define BDC_FLAG2_IF_SHIFT	0
-#define BDC_FLAG2_FC_FLAG	0x10	/* flag to indicate if pkt contains */
-					/* FLOW CONTROL info only */
-
-/* version numbers */
-#define BDC_PROTO_VER_1		1	/* Old Protocol version */
-#define BDC_PROTO_VER		2	/* Protocol version */
-
-/* flags2.if field access macros */
-#define BDC_GET_IF_IDX(hdr) \
-	((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
-#define BDC_SET_IF_IDX(hdr, idx) \
-	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT)))
-
-#define BDC_FLAG2_PAD_MASK		0xf0
-#define BDC_FLAG_PAD_MASK		0x03
-#define BDC_FLAG2_PAD_SHIFT		2
-#define BDC_FLAG_PAD_SHIFT		0
-#define BDC_FLAG2_PAD_IDX		0x3c
-#define BDC_FLAG_PAD_IDX		0x03
-#define BDC_GET_PAD_LEN(hdr) \
-	((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \
-	((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT)))
-#define BDC_SET_PAD_LEN(hdr, idx) \
-	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \
-	(((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \
-	((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \
-	(((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT)))
-
-#endif /* _bcmcdc_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmdefs.h b/drivers/net/wireless/bcmdhd/include/bcmdefs.h
deleted file mode 100644
index a024999..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmdefs.h
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Misc system wide definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmdefs.h 601026 2015-11-20 06:53:19Z $
- */
-
-#ifndef	_bcmdefs_h_
-#define	_bcmdefs_h_
-
-/*
- * One doesn't need to include this file explicitly, gets included automatically if
- * typedefs.h is included.
- */
-
-/* Use BCM_REFERENCE to suppress warnings about intentionally-unused function
- * arguments or local variables.
- */
-#define BCM_REFERENCE(data)	((void)(data))
-
-/* Allow for suppressing unused variable warnings. */
-#ifdef __GNUC__
-#define UNUSED_VAR     __attribute__ ((unused))
-#else
-#define UNUSED_VAR
-#endif
-
-/* Compile-time assert can be used in place of ASSERT if the expression evaluates
- * to a constant at compile time.
- */
-#define STATIC_ASSERT(expr) { \
-	/* Make sure the expression is constant. */ \
-	typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e UNUSED_VAR; \
-	/* Make sure the expression is true. */ \
-	typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1] UNUSED_VAR; \
-}
-
-/* Reclaiming text and data :
- * The following macros specify special linker sections that can be reclaimed
- * after a system is considered 'up'.
- * BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN,
- * as in most cases, the attach function calls the detach function to clean up on error).
- */
-
-#define bcmreclaimed 		0
-#define _data	_data
-#define _fn	_fn
-#define BCMPREATTACHDATA(_data)	_data
-#define BCMPREATTACHFN(_fn)	_fn
-#define _data	_data
-#define _fn		_fn
-#define _fn	_fn
-#define	BCMNMIATTACHFN(_fn)	_fn
-#define	BCMNMIATTACHDATA(_data)	_data
-#define CONST	const
-
-#undef BCM47XX_CA9
-
-#ifndef BCMFASTPATH
-#define BCMFASTPATH
-#define BCMFASTPATH_HOST
-#endif /* BCMFASTPATH */
-
-
-/* Use the BCMRAMFN() macro to tag functions in source that must be included in RAM (excluded from
- * ROM). This should eliminate the need to manually specify these functions in the ROM config file.
- * It should only be used in special cases where the function must be in RAM for *all* ROM-based
- * chips.
- */
-	#define BCMRAMFN(_fn)	_fn
-
-#define STATIC	static
-
-/* Bus types */
-#define	SI_BUS			0	/* SOC Interconnect */
-#define	PCI_BUS			1	/* PCI target */
-#define	PCMCIA_BUS		2	/* PCMCIA target */
-#define SDIO_BUS		3	/* SDIO target */
-#define JTAG_BUS		4	/* JTAG */
-#define USB_BUS			5	/* USB (does not support R/W REG) */
-#define SPI_BUS			6	/* gSPI target */
-#define RPC_BUS			7	/* RPC target */
-
-/* Allows size optimization for single-bus image */
-#ifdef BCMBUSTYPE
-#define BUSTYPE(bus) 	(BCMBUSTYPE)
-#else
-#define BUSTYPE(bus) 	(bus)
-#endif
-
-/* Allows size optimization for single-backplane image */
-#ifdef BCMCHIPTYPE
-#define CHIPTYPE(bus) 	(BCMCHIPTYPE)
-#else
-#define CHIPTYPE(bus) 	(bus)
-#endif
-
-
-/* Allows size optimization for SPROM support */
-#if defined(BCMSPROMBUS)
-#define SPROMBUS	(BCMSPROMBUS)
-#elif defined(SI_PCMCIA_SROM)
-#define SPROMBUS	(PCMCIA_BUS)
-#else
-#define SPROMBUS	(PCI_BUS)
-#endif
-
-/* Allows size optimization for single-chip image */
-#ifdef BCMCHIPID
-#define CHIPID(chip)	(BCMCHIPID)
-#else
-#define CHIPID(chip)	(chip)
-#endif
-
-#ifdef BCMCHIPREV
-#define CHIPREV(rev)	(BCMCHIPREV)
-#else
-#define CHIPREV(rev)	(rev)
-#endif
-
-#ifdef BCMPCIEREV
-#define PCIECOREREV(rev)	(BCMPCIEREV)
-#else
-#define PCIECOREREV(rev)	(rev)
-#endif
-
-/* Defines for DMA Address Width - Shared between OSL and HNDDMA */
-#define DMADDR_MASK_32 0x0		/* Address mask for 32-bits */
-#define DMADDR_MASK_30 0xc0000000	/* Address mask for 30-bits */
-#define DMADDR_MASK_26 0xFC000000	/* Address maks for 26-bits */
-#define DMADDR_MASK_0  0xffffffff	/* Address mask for 0-bits (hi-part) */
-
-#define	DMADDRWIDTH_26  26 /* 26-bit addressing capability */
-#define	DMADDRWIDTH_30  30 /* 30-bit addressing capability */
-#define	DMADDRWIDTH_32  32 /* 32-bit addressing capability */
-#define	DMADDRWIDTH_63  63 /* 64-bit addressing capability */
-#define	DMADDRWIDTH_64  64 /* 64-bit addressing capability */
-
-typedef struct {
-	uint32 loaddr;
-	uint32 hiaddr;
-} dma64addr_t;
-
-#define PHYSADDR64HI(_pa) ((_pa).hiaddr)
-#define PHYSADDR64HISET(_pa, _val) \
-	do { \
-		(_pa).hiaddr = (_val);		\
-	} while (0)
-#define PHYSADDR64LO(_pa) ((_pa).loaddr)
-#define PHYSADDR64LOSET(_pa, _val) \
-	do { \
-		(_pa).loaddr = (_val);		\
-	} while (0)
-
-#ifdef BCMDMA64OSL
-typedef dma64addr_t dmaaddr_t;
-#define PHYSADDRHI(_pa) PHYSADDR64HI(_pa)
-#define PHYSADDRHISET(_pa, _val) PHYSADDR64HISET(_pa, _val)
-#define PHYSADDRLO(_pa)  PHYSADDR64LO(_pa)
-#define PHYSADDRLOSET(_pa, _val) PHYSADDR64LOSET(_pa, _val)
-#define PHYSADDRTOULONG(_pa, _ulong) \
-	do { \
-		_ulong = ((unsigned long)(_pa).hiaddr << 32) | ((_pa).loaddr); \
-	} while (0)
-
-#else
-typedef unsigned long dmaaddr_t;
-#define PHYSADDRHI(_pa) (0)
-#define PHYSADDRHISET(_pa, _val)
-#define PHYSADDRLO(_pa) ((_pa))
-#define PHYSADDRLOSET(_pa, _val) \
-	do { \
-		(_pa) = (_val);			\
-	} while (0)
-#endif /* BCMDMA64OSL */
-#define PHYSADDRISZERO(_pa) (PHYSADDRLO(_pa) == 0 && PHYSADDRHI(_pa) == 0)
-
-/* One physical DMA segment */
-typedef struct  {
-	dmaaddr_t addr;
-	uint32	  length;
-} hnddma_seg_t;
-
-#define MAX_DMA_SEGS 8
-
-
-typedef struct {
-	void *oshdmah; /* Opaque handle for OSL to store its information */
-	uint origsize; /* Size of the virtual packet */
-	uint nsegs;
-	hnddma_seg_t segs[MAX_DMA_SEGS];
-} hnddma_seg_map_t;
-
-
-/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF).
- * By doing, we avoid the need  to allocate an extra buffer for the header when bridging to WL.
- * There is a compile time check in wlc.c which ensure that this value is at least as big
- * as TXOFF. This value is used in dma_rxfill (hnddma.c).
- */
-
-#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY)
-/* add 40 bytes to allow for extra RPC header and info  */
-#define BCMEXTRAHDROOM 260
-#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */
-#define BCMEXTRAHDROOM 204
-#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */
-
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef SDALIGN
-#define SDALIGN	32
-#endif
-
-/* Headroom required for dongle-to-host communication.  Packets allocated
- * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should
- * leave this much room in front for low-level message headers which may
- * be needed to get across the dongle bus to the host.  (These messages
- * don't go over the network, so room for the full WL header above would
- * be a waste.).
-*/
-#define BCMDONGLEHDRSZ 12
-#define BCMDONGLEPADSZ 16
-
-#define BCMDONGLEOVERHEAD	(BCMDONGLEHDRSZ + BCMDONGLEPADSZ)
-
-
-#if defined(NO_BCMDBG_ASSERT)
-# undef BCMDBG_ASSERT
-# undef BCMASSERT_LOG
-#endif
-
-#if defined(BCMASSERT_LOG)
-#define BCMASSERT_SUPPORT
-#endif 
-
-/* Macros for doing definition and get/set of bitfields
- * Usage example, e.g. a three-bit field (bits 4-6):
- *    #define <NAME>_M	BITFIELD_MASK(3)
- *    #define <NAME>_S	4
- * ...
- *    regval = R_REG(osh, &regs->regfoo);
- *    field = GFIELD(regval, <NAME>);
- *    regval = SFIELD(regval, <NAME>, 1);
- *    W_REG(osh, &regs->regfoo, regval);
- */
-#define BITFIELD_MASK(width) \
-		(((unsigned)1 << (width)) - 1)
-#define GFIELD(val, field) \
-		(((val) >> field ## _S) & field ## _M)
-#define SFIELD(val, field, bits) \
-		(((val) & (~(field ## _M << field ## _S))) | \
-		 ((unsigned)(bits) << field ## _S))
-
-/* define BCMSMALL to remove misc features for memory-constrained environments */
-#ifdef BCMSMALL
-#undef	BCMSPACE
-#define bcmspace	FALSE	/* if (bcmspace) code is discarded */
-#else
-#define	BCMSPACE
-#define bcmspace	TRUE	/* if (bcmspace) code is retained */
-#endif
-
-/* Max. nvram variable table size */
-#ifndef MAXSZ_NVRAM_VARS
-#ifdef LARGE_NVRAM_MAXSZ
-#define MAXSZ_NVRAM_VARS	LARGE_NVRAM_MAXSZ
-#else
-/* SROM12 changes */
-#define	MAXSZ_NVRAM_VARS	6144
-#endif /* LARGE_NVRAM_MAXSZ */
-#endif /* !MAXSZ_NVRAM_VARS */
-
-
-
-/* WL_ENAB_RUNTIME_CHECK may be set based upon the #define below (for ROM builds). It may also
- * be defined via makefiles (e.g. ROM auto abandon unoptimized compiles).
- */
-
-
-#ifdef BCMLFRAG /* BCMLFRAG support enab macros  */
-	extern bool _bcmlfrag;
-	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
-		#define BCMLFRAG_ENAB() (_bcmlfrag)
-	#elif defined(BCMLFRAG_DISABLED)
-		#define BCMLFRAG_ENAB()	(0)
-	#else
-		#define BCMLFRAG_ENAB()	(1)
-	#endif
-#else
-	#define BCMLFRAG_ENAB()		(0)
-#endif /* BCMLFRAG_ENAB */
-#define	RXMODE1	1	/* descriptor split */
-#define	RXMODE2	2	/* descriptor split + classification */
-#define	RXMODE3	3	/* fifo split + classification */
-#define	RXMODE4	4	/* fifo split + classification + hdr conversion */
-
-#ifdef BCMSPLITRX /* BCMLFRAG support enab macros  */
-	extern bool _bcmsplitrx;
-	extern uint8 _bcmsplitrx_mode;
-	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
-		#define BCMSPLITRX_ENAB() (_bcmsplitrx)
-		#define BCMSPLITRX_MODE() (_bcmsplitrx_mode)
-	#elif defined(BCMSPLITRX_DISABLED)
-		#define BCMSPLITRX_ENAB()	(0)
-		#define BCMSPLITRX_MODE()	(0)
-	#else
-		#define BCMSPLITRX_ENAB()	(1)
-		#define BCMSPLITRX_MODE() (_bcmsplitrx_mode)
-	#endif
-#else
-	#define BCMSPLITRX_ENAB()		(0)
-	#define BCMSPLITRX_MODE()		(0)
-#endif /* BCMSPLITRX */
-
-#ifdef BCMPCIEDEV /* BCMPCIEDEV support enab macros */
-extern bool _pciedevenab;
-	#if defined(WL_ENAB_RUNTIME_CHECK)
-		#define BCMPCIEDEV_ENAB() (_pciedevenab)
-	#elif defined(BCMPCIEDEV_ENABLED)
-		#define BCMPCIEDEV_ENAB()	1
-	#else
-		#define BCMPCIEDEV_ENAB()	0
-	#endif
-#else
-	#define BCMPCIEDEV_ENAB()	0
-#endif /* BCMPCIEDEV */
-
-#define SPLIT_RXMODE1()	((BCMSPLITRX_MODE() == RXMODE1))
-#define SPLIT_RXMODE2()	((BCMSPLITRX_MODE() == RXMODE2))
-#define SPLIT_RXMODE3()	((BCMSPLITRX_MODE() == RXMODE3))
-#define SPLIT_RXMODE4()	((BCMSPLITRX_MODE() == RXMODE4))
-
-#define PKT_CLASSIFY()	(SPLIT_RXMODE2() || SPLIT_RXMODE3() || SPLIT_RXMODE4())
-#define RXFIFO_SPLIT()	(SPLIT_RXMODE3() || SPLIT_RXMODE4())
-#define HDR_CONV()	(SPLIT_RXMODE4())
-
-#define PKT_CLASSIFY_EN(x)	((PKT_CLASSIFY()) && (PKT_CLASSIFY_FIFO == (x)))
-#ifdef BCM_SPLITBUF
-	extern bool _bcmsplitbuf;
-	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
-		#define BCM_SPLITBUF_ENAB() (_bcmsplitbuf)
-	#elif defined(BCM_SPLITBUF_DISABLED)
-		#define BCM_SPLITBUF_ENAB()	(0)
-	#else
-		#define BCM_SPLITBUF_ENAB()	(1)
-	#endif
-#else
-	#define BCM_SPLITBUF_ENAB()		(0)
-#endif	/* BCM_SPLITBUF */
-
-/* Max size for reclaimable NVRAM array */
-#ifdef DL_NVRAM
-#define NVRAM_ARRAY_MAXSIZE	DL_NVRAM
-#else
-#define NVRAM_ARRAY_MAXSIZE	MAXSZ_NVRAM_VARS
-#endif /* DL_NVRAM */
-
-extern uint32 gFWID;
-
-
-#endif /* _bcmdefs_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmdevs.h b/drivers/net/wireless/bcmdhd/include/bcmdevs.h
deleted file mode 100644
index 2b0ec49..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmdevs.h
+++ /dev/null
@@ -1,803 +0,0 @@
-/*
- * Broadcom device-specific manifest constants.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmdevs.h 582052 2015-08-26 09:30:53Z $
- */
-
-#ifndef	_BCMDEVS_H
-#define	_BCMDEVS_H
-
-/* PCI vendor IDs */
-#define	VENDOR_EPIGRAM		0xfeda
-#define	VENDOR_BROADCOM		0x14e4
-#define	VENDOR_3COM		0x10b7
-#define	VENDOR_NETGEAR		0x1385
-#define	VENDOR_DIAMOND		0x1092
-#define	VENDOR_INTEL		0x8086
-#define	VENDOR_DELL		0x1028
-#define	VENDOR_HP		0x103c
-#define	VENDOR_HP_COMPAQ	0x0e11
-#define	VENDOR_APPLE		0x106b
-#define VENDOR_SI_IMAGE		0x1095		/* Silicon Image, used by Arasan SDIO Host */
-#define VENDOR_BUFFALO		0x1154		/* Buffalo vendor id */
-#define VENDOR_TI		0x104c		/* Texas Instruments */
-#define VENDOR_RICOH		0x1180		/* Ricoh */
-#define VENDOR_JMICRON		0x197b
-
-
-/* PCMCIA vendor IDs */
-#define	VENDOR_BROADCOM_PCMCIA	0x02d0
-
-/* SDIO vendor IDs */
-#define	VENDOR_BROADCOM_SDIO	0x00BF
-
-/* DONGLE VID/PIDs */
-#define BCM_DNGL_VID		0x0a5c
-#define BCM_DNGL_BL_PID_4328	0xbd12
-#define BCM_DNGL_BL_PID_4322	0xbd13
-#define BCM_DNGL_BL_PID_4319    0xbd16
-#define BCM_DNGL_BL_PID_43236   0xbd17
-#define BCM_DNGL_BL_PID_4332	0xbd18
-#define BCM_DNGL_BL_PID_4330	0xbd19
-#define BCM_DNGL_BL_PID_4334	0xbd1a
-#define BCM_DNGL_BL_PID_43239   0xbd1b
-#define BCM_DNGL_BL_PID_4324	0xbd1c
-#define BCM_DNGL_BL_PID_4360	0xbd1d
-#define BCM_DNGL_BL_PID_43143	0xbd1e
-#define BCM_DNGL_BL_PID_43242	0xbd1f
-#define BCM_DNGL_BL_PID_43342	0xbd21
-#define BCM_DNGL_BL_PID_4335	0xbd20
-#define BCM_DNGL_BL_PID_43341	0xbd22
-#define BCM_DNGL_BL_PID_4350    0xbd23
-#define BCM_DNGL_BL_PID_4345    0xbd24
-#define BCM_DNGL_BL_PID_4349	0xbd25
-#define BCM_DNGL_BL_PID_4354	0xbd26
-#define BCM_DNGL_BL_PID_43569   0xbd27
-#define BCM_DNGL_BL_PID_43909	0xbd28
-
-#define BCM_DNGL_BDC_PID	0x0bdc
-#define BCM_DNGL_JTAG_PID	0x4a44
-
-/* HW USB BLOCK [CPULESS USB] PIDs */
-#define BCM_HWUSB_PID_43239     43239
-
-/* PCI Device IDs */
-#define	BCM4210_DEVICE_ID	0x1072		/* never used */
-#define	BCM4230_DEVICE_ID	0x1086		/* never used */
-#define	BCM4401_ENET_ID		0x170c		/* 4401b0 production enet cards */
-#define	BCM3352_DEVICE_ID	0x3352		/* bcm3352 device id */
-#define	BCM3360_DEVICE_ID	0x3360		/* bcm3360 device id */
-#define	BCM4211_DEVICE_ID	0x4211
-#define	BCM4231_DEVICE_ID	0x4231
-#define	BCM4303_D11B_ID		0x4303		/* 4303 802.11b */
-#define	BCM4311_D11G_ID		0x4311		/* 4311 802.11b/g id */
-#define	BCM4311_D11DUAL_ID	0x4312		/* 4311 802.11a/b/g id */
-#define	BCM4311_D11A_ID		0x4313		/* 4311 802.11a id */
-#define	BCM4328_D11DUAL_ID	0x4314		/* 4328/4312 802.11a/g id */
-#define	BCM4328_D11G_ID		0x4315		/* 4328/4312 802.11g id */
-#define	BCM4328_D11A_ID		0x4316		/* 4328/4312 802.11a id */
-#define	BCM4318_D11G_ID		0x4318		/* 4318 802.11b/g id */
-#define	BCM4318_D11DUAL_ID	0x4319		/* 4318 802.11a/b/g id */
-#define	BCM4318_D11A_ID		0x431a		/* 4318 802.11a id */
-#define	BCM4325_D11DUAL_ID	0x431b		/* 4325 802.11a/g id */
-#define	BCM4325_D11G_ID		0x431c		/* 4325 802.11g id */
-#define	BCM4325_D11A_ID		0x431d		/* 4325 802.11a id */
-#define	BCM4306_D11G_ID		0x4320		/* 4306 802.11g */
-#define	BCM4306_D11A_ID		0x4321		/* 4306 802.11a */
-#define	BCM4306_UART_ID		0x4322		/* 4306 uart */
-#define	BCM4306_V90_ID		0x4323		/* 4306 v90 codec */
-#define	BCM4306_D11DUAL_ID	0x4324		/* 4306 dual A+B */
-#define	BCM4306_D11G_ID2	0x4325		/* BCM4306_D11G_ID; INF w/loose binding war */
-#define	BCM4321_D11N_ID		0x4328		/* 4321 802.11n dualband id */
-#define	BCM4321_D11N2G_ID	0x4329		/* 4321 802.11n 2.4Ghz band id */
-#define	BCM4321_D11N5G_ID	0x432a		/* 4321 802.11n 5Ghz band id */
-#define BCM4322_D11N_ID		0x432b		/* 4322 802.11n dualband device */
-#define BCM4322_D11N2G_ID	0x432c		/* 4322 802.11n 2.4GHz device */
-#define BCM4322_D11N5G_ID	0x432d		/* 4322 802.11n 5GHz device */
-#define BCM4329_D11N_ID		0x432e		/* 4329 802.11n dualband device */
-#define BCM4329_D11N2G_ID	0x432f		/* 4329 802.11n 2.4G device */
-#define BCM4329_D11N5G_ID	0x4330		/* 4329 802.11n 5G device */
-#define	BCM4315_D11DUAL_ID	0x4334		/* 4315 802.11a/g id */
-#define	BCM4315_D11G_ID		0x4335		/* 4315 802.11g id */
-#define	BCM4315_D11A_ID		0x4336		/* 4315 802.11a id */
-#define BCM4319_D11N_ID		0x4337		/* 4319 802.11n dualband device */
-#define BCM4319_D11N2G_ID	0x4338		/* 4319 802.11n 2.4G device */
-#define BCM4319_D11N5G_ID	0x4339		/* 4319 802.11n 5G device */
-#define BCM43231_D11N2G_ID	0x4340		/* 43231 802.11n 2.4GHz device */
-#define BCM43221_D11N2G_ID	0x4341		/* 43221 802.11n 2.4GHz device */
-#define BCM43222_D11N_ID	0x4350		/* 43222 802.11n dualband device */
-#define BCM43222_D11N2G_ID	0x4351		/* 43222 802.11n 2.4GHz device */
-#define BCM43222_D11N5G_ID	0x4352		/* 43222 802.11n 5GHz device */
-#define BCM43224_D11N_ID	0x4353		/* 43224 802.11n dualband device */
-#define BCM43224_D11N_ID_VEN1	0x0576		/* Vendor specific 43224 802.11n db device */
-#define BCM43226_D11N_ID	0x4354		/* 43226 802.11n dualband device */
-#define BCM43236_D11N_ID	0x4346		/* 43236 802.11n dualband device */
-#define BCM43236_D11N2G_ID	0x4347		/* 43236 802.11n 2.4GHz device */
-#define BCM43236_D11N5G_ID	0x4348		/* 43236 802.11n 5GHz device */
-#define BCM43225_D11N2G_ID	0x4357		/* 43225 802.11n 2.4GHz device */
-#define BCM43421_D11N_ID	0xA99D		/* 43421 802.11n dualband device */
-#define BCM4313_D11N2G_ID	0x4727		/* 4313 802.11n 2.4G device */
-#define BCM4330_D11N_ID         0x4360          /* 4330 802.11n dualband device */
-#define BCM4330_D11N2G_ID       0x4361          /* 4330 802.11n 2.4G device */
-#define BCM4330_D11N5G_ID       0x4362          /* 4330 802.11n 5G device */
-#define BCM4336_D11N_ID		0x4343		/* 4336 802.11n 2.4GHz device */
-#define BCM6362_D11N_ID		0x435f		/* 6362 802.11n dualband device */
-#define BCM6362_D11N2G_ID	0x433f		/* 6362 802.11n 2.4Ghz band id */
-#define BCM6362_D11N5G_ID	0x434f		/* 6362 802.11n 5Ghz band id */
-#define BCM4331_D11N_ID		0x4331		/* 4331 802.11n dualband id */
-#define BCM4331_D11N2G_ID	0x4332		/* 4331 802.11n 2.4Ghz band id */
-#define BCM4331_D11N5G_ID	0x4333		/* 4331 802.11n 5Ghz band id */
-#define BCM43237_D11N_ID	0x4355		/* 43237 802.11n dualband device */
-#define BCM43237_D11N5G_ID	0x4356		/* 43237 802.11n 5GHz device */
-#define BCM43227_D11N2G_ID	0x4358		/* 43228 802.11n 2.4GHz device */
-#define BCM43228_D11N_ID	0x4359		/* 43228 802.11n DualBand device */
-#define BCM43228_D11N5G_ID	0x435a		/* 43228 802.11n 5GHz device */
-#define BCM43362_D11N_ID	0x4363		/* 43362 802.11n 2.4GHz device */
-#define BCM43239_D11N_ID	0x4370		/* 43239 802.11n dualband device */
-#define BCM4324_D11N_ID		0x4374		/* 4324 802.11n dualband device */
-#define BCM43217_D11N2G_ID	0x43a9		/* 43217 802.11n 2.4GHz device */
-#define BCM43131_D11N2G_ID	0x43aa		/* 43131 802.11n 2.4GHz device */
-#define BCM4314_D11N2G_ID	0x4364		/* 4314 802.11n 2.4G device */
-#define BCM43142_D11N2G_ID	0x4365		/* 43142 802.11n 2.4G device */
-#define BCM43143_D11N2G_ID	0x4366		/* 43143 802.11n 2.4G device */
-#define BCM4334_D11N_ID		0x4380		/* 4334 802.11n dualband device */
-#define BCM4334_D11N2G_ID	0x4381		/* 4334 802.11n 2.4G device */
-#define BCM4334_D11N5G_ID	0x4382		/* 4334 802.11n 5G device */
-#define BCM43342_D11N_ID	0x4383		/* 43342 802.11n dualband device */
-#define BCM43342_D11N2G_ID	0x4384		/* 43342 802.11n 2.4G device */
-#define BCM43342_D11N5G_ID	0x4385		/* 43342 802.11n 5G device */
-#define BCM43341_D11N_ID	0x4386		/* 43341 802.11n dualband device */
-#define BCM43341_D11N2G_ID	0x4387		/* 43341 802.11n 2.4G device */
-#define BCM43341_D11N5G_ID	0x4388		/* 43341 802.11n 5G device */
-#define BCM4360_D11AC_ID	0x43a0
-#define BCM4360_D11AC2G_ID	0x43a1
-#define BCM4360_D11AC5G_ID	0x43a2
-#define BCM4345_D11AC_ID	0x43ab		/* 4345 802.11ac dualband device */
-#define BCM4345_D11AC2G_ID	0x43ac		/* 4345 802.11ac 2.4G device */
-#define BCM4345_D11AC5G_ID	0x43ad		/* 4345 802.11ac 5G device */
-#define BCM4335_D11AC_ID	0x43ae
-#define BCM4335_D11AC2G_ID	0x43af
-#define BCM4335_D11AC5G_ID	0x43b0
-#define BCM4352_D11AC_ID	0x43b1		/* 4352 802.11ac dualband device */
-#define BCM4352_D11AC2G_ID	0x43b2		/* 4352 802.11ac 2.4G device */
-#define BCM4352_D11AC5G_ID	0x43b3		/* 4352 802.11ac 5G device */
-#define BCM43602_D11AC_ID	0x43ba		/* ac dualband PCI devid SPROM programmed */
-#define BCM43602_D11AC2G_ID	0x43bb		/* 43602 802.11ac 2.4G device */
-#define BCM43602_D11AC5G_ID	0x43bc		/* 43602 802.11ac 5G device */
-#define BCM4349_D11AC_ID	0x4349		/* 4349 802.11ac dualband device */
-#define BCM4349_D11AC2G_ID	0x43dd		/* 4349 802.11ac 2.4G device */
-#define BCM4349_D11AC5G_ID	0x43de		/* 4349 802.11ac 5G device */
-#define BCM53573_D11AC_ID	0x43b4		/* 53573 802.11ac dualband device */
-#define BCM53573_D11AC2G_ID	0x43b5		/* 53573 802.11ac 2.4G device */
-#define BCM53573_D11AC5G_ID	0x43b6		/* 53573 802.11ac 5G device */
-#define BCM47189_D11AC_ID	0x43c6		/* 47189 802.11ac dualband device */
-#define BCM47189_D11AC2G_ID	0x43c7		/* 47189 802.11ac 2.4G device */
-#define BCM47189_D11AC5G_ID	0x43c8		/* 47189 802.11ac 5G device */
-#define BCM4355_D11AC_ID	0x43dc		/* 4355 802.11ac dualband device */
-#define BCM4355_D11AC2G_ID	0x43fc		/* 4355 802.11ac 2.4G device */
-#define BCM4355_D11AC5G_ID	0x43fd		/* 4355 802.11ac 5G device */
-#define BCM4359_D11AC_ID	0x43ef		/* 4359 802.11ac dualband device */
-#define BCM4359_D11AC2G_ID	0x43fe		/* 4359 802.11ac 2.4G device */
-#define BCM4359_D11AC5G_ID	0x43ff		/* 4359 802.11ac 5G device */
-#define BCM43596_D11AC_ID	0x4415		/* 43596 802.11ac dualband device */
-#define BCM43596_D11AC2G_ID	0x4416		/* 43596 802.11ac 2.4G device */
-#define BCM43596_D11AC5G_ID	0x4417		/* 43596 802.11ac 5G device */
-#define BCM43909_D11AC_ID	0x43d0		/* 43909 802.11ac dualband device */
-#define BCM43909_D11AC2G_ID	0x43d1		/* 43909 802.11ac 2.4G device */
-#define BCM43909_D11AC5G_ID	0x43d2		/* 43909 802.11ac 5G device */
-
-/* PCI Subsystem ID */
-#define BCM943228HMB_SSID_VEN1	0x0607
-#define BCM94313HMGBL_SSID_VEN1	0x0608
-#define BCM94313HMG_SSID_VEN1	0x0609
-#define BCM943142HM_SSID_VEN1	0x0611
-
-#define BCM43143_D11N2G_ID	0x4366		/* 43143 802.11n 2.4G device */
-
-#define BCM43242_D11N_ID	0x4367		/* 43242 802.11n dualband device */
-#define BCM43242_D11N2G_ID	0x4368		/* 43242 802.11n 2.4G device */
-#define BCM43242_D11N5G_ID	0x4369		/* 43242 802.11n 5G device */
-
-#define BCM4350_D11AC_ID	0x43a3
-#define BCM4350_D11AC2G_ID	0x43a4
-#define BCM4350_D11AC5G_ID	0x43a5
-
-#define BCM43556_D11AC_ID	0x43b7
-#define BCM43556_D11AC2G_ID	0x43b8
-#define BCM43556_D11AC5G_ID	0x43b9
-
-#define BCM43558_D11AC_ID	0x43c0
-#define BCM43558_D11AC2G_ID	0x43c1
-#define BCM43558_D11AC5G_ID	0x43c2
-
-#define BCM43566_D11AC_ID	0x43d3
-#define BCM43566_D11AC2G_ID	0x43d4
-#define BCM43566_D11AC5G_ID	0x43d5
-
-#define BCM43568_D11AC_ID	0x43d6
-#define BCM43568_D11AC2G_ID	0x43d7
-#define BCM43568_D11AC5G_ID	0x43d8
-
-#define BCM43569_D11AC_ID	0x43d9
-#define BCM43569_D11AC2G_ID	0x43da
-#define BCM43569_D11AC5G_ID	0x43db
-
-#define BCM43570_D11AC_ID	0x43d9
-#define BCM43570_D11AC2G_ID	0x43da
-#define BCM43570_D11AC5G_ID	0x43db
-
-#define BCM4354_D11AC_ID	0x43df		/* 4354 802.11ac dualband device */
-#define BCM4354_D11AC2G_ID	0x43e0		/* 4354 802.11ac 2.4G device */
-#define BCM4354_D11AC5G_ID	0x43e1		/* 4354 802.11ac 5G device */
-#define BCM43430_D11N2G_ID	0x43e2		/* 43430 802.11n 2.4G device */
-
-
-#define BCM4365_D11AC_ID	0x43ca
-#define BCM4365_D11AC2G_ID	0x43cb
-#define BCM4365_D11AC5G_ID	0x43cc
-
-#define BCM4366_D11AC_ID	0x43c3
-#define BCM4366_D11AC2G_ID	0x43c4
-#define BCM4366_D11AC5G_ID	0x43c5
-
-#define BCM43349_D11N_ID	0x43e6		/* 43349 802.11n dualband id */
-#define BCM43349_D11N2G_ID	0x43e7		/* 43349 802.11n 2.4Ghz band id */
-#define BCM43349_D11N5G_ID	0x43e8		/* 43349 802.11n 5Ghz band id */
-
-#define BCM4358_D11AC_ID        0x43e9          /* 4358 802.11ac dualband device */
-#define BCM4358_D11AC2G_ID      0x43ea          /* 4358 802.11ac 2.4G device */
-#define BCM4358_D11AC5G_ID      0x43eb          /* 4358 802.11ac 5G device */
-
-#define BCM4356_D11AC_ID	0x43ec		/* 4356 802.11ac dualband device */
-#define BCM4356_D11AC2G_ID	0x43ed		/* 4356 802.11ac 2.4G device */
-#define BCM4356_D11AC5G_ID	0x43ee		/* 4356 802.11ac 5G device */
-
-#define	BCMGPRS_UART_ID		0x4333		/* Uart id used by 4306/gprs card */
-#define	BCMGPRS2_UART_ID	0x4344		/* Uart id used by 4306/gprs card */
-#define FPGA_JTAGM_ID		0x43f0		/* FPGA jtagm device id */
-#define BCM_JTAGM_ID		0x43f1		/* BCM jtagm device id */
-#define SDIOH_FPGA_ID		0x43f2		/* sdio host fpga */
-#define BCM_SDIOH_ID		0x43f3		/* BCM sdio host id */
-#define SDIOD_FPGA_ID		0x43f4		/* sdio device fpga */
-#define SPIH_FPGA_ID		0x43f5		/* PCI SPI Host Controller FPGA */
-#define BCM_SPIH_ID		0x43f6		/* Synopsis SPI Host Controller */
-#define MIMO_FPGA_ID		0x43f8		/* FPGA mimo minimacphy device id */
-#define BCM_JTAGM2_ID		0x43f9		/* BCM alternate jtagm device id */
-#define SDHCI_FPGA_ID		0x43fa		/* Standard SDIO Host Controller FPGA */
-#define	BCM4402_ENET_ID		0x4402		/* 4402 enet */
-#define	BCM4402_V90_ID		0x4403		/* 4402 v90 codec */
-#define	BCM4410_DEVICE_ID	0x4410		/* bcm44xx family pci iline */
-#define	BCM4412_DEVICE_ID	0x4412		/* bcm44xx family pci enet */
-#define	BCM4430_DEVICE_ID	0x4430		/* bcm44xx family cardbus iline */
-#define	BCM4432_DEVICE_ID	0x4432		/* bcm44xx family cardbus enet */
-#define	BCM4704_ENET_ID		0x4706		/* 4704 enet (Use 47XX_ENET_ID instead!) */
-#define	BCM4710_DEVICE_ID	0x4710		/* 4710 primary function 0 */
-#define	BCM47XX_AUDIO_ID	0x4711		/* 47xx audio codec */
-#define	BCM47XX_V90_ID		0x4712		/* 47xx v90 codec */
-#define	BCM47XX_ENET_ID		0x4713		/* 47xx enet */
-#define	BCM47XX_EXT_ID		0x4714		/* 47xx external i/f */
-#define	BCM47XX_GMAC_ID		0x4715		/* 47xx Unimac based GbE */
-#define	BCM47XX_USBH_ID		0x4716		/* 47xx usb host */
-#define	BCM47XX_USBD_ID		0x4717		/* 47xx usb device */
-#define	BCM47XX_IPSEC_ID	0x4718		/* 47xx ipsec */
-#define	BCM47XX_ROBO_ID		0x4719		/* 47xx/53xx roboswitch core */
-#define	BCM47XX_USB20H_ID	0x471a		/* 47xx usb 2.0 host */
-#define	BCM47XX_USB20D_ID	0x471b		/* 47xx usb 2.0 device */
-#define	BCM47XX_ATA100_ID	0x471d		/* 47xx parallel ATA */
-#define	BCM47XX_SATAXOR_ID	0x471e		/* 47xx serial ATA & XOR DMA */
-#define	BCM47XX_GIGETH_ID	0x471f		/* 47xx GbE (5700) */
-#define	BCM4712_MIPS_ID		0x4720		/* 4712 base devid */
-#define	BCM4716_DEVICE_ID	0x4722		/* 4716 base devid */
-#define	BCM47XX_USB30H_ID	0x472a		/* 47xx usb 3.0 host */
-#define	BCM47XX_USB30D_ID	0x472b		/* 47xx usb 3.0 device */
-#define BCM47XX_SMBUS_EMU_ID	0x47fe		/* 47xx emulated SMBus device */
-#define	BCM47XX_XOR_EMU_ID	0x47ff		/* 47xx emulated XOR engine */
-#define	EPI41210_DEVICE_ID	0xa0fa		/* bcm4210 */
-#define	EPI41230_DEVICE_ID	0xa10e		/* bcm4230 */
-#define JINVANI_SDIOH_ID	0x4743		/* Jinvani SDIO Gold Host */
-#define BCM27XX_SDIOH_ID	0x2702		/* BCM27xx Standard SDIO Host */
-#define PCIXX21_FLASHMEDIA_ID	0x803b		/* TI PCI xx21 Standard Host Controller */
-#define PCIXX21_SDIOH_ID	0x803c		/* TI PCI xx21 Standard Host Controller */
-#define R5C822_SDIOH_ID		0x0822		/* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host */
-#define JMICRON_SDIOH_ID	0x2381		/* JMicron Standard SDIO Host Controller */
-
-/* Chip IDs */
-#define	BCM4306_CHIP_ID		0x4306		/* 4306 chipcommon chipid */
-#define	BCM4311_CHIP_ID		0x4311		/* 4311 PCIe 802.11a/b/g */
-#define	BCM43111_CHIP_ID	43111		/* 43111 chipcommon chipid (OTP chipid) */
-#define	BCM43112_CHIP_ID	43112		/* 43112 chipcommon chipid (OTP chipid) */
-#define	BCM4312_CHIP_ID		0x4312		/* 4312 chipcommon chipid */
-#define BCM4313_CHIP_ID		0x4313		/* 4313 chip id */
-#define	BCM43131_CHIP_ID	43131		/* 43131 chip id (OTP chipid) */
-#define	BCM4315_CHIP_ID		0x4315		/* 4315 chip id */
-#define	BCM4318_CHIP_ID		0x4318		/* 4318 chipcommon chipid */
-#define	BCM4319_CHIP_ID		0x4319		/* 4319 chip id */
-#define	BCM4320_CHIP_ID		0x4320		/* 4320 chipcommon chipid */
-#define	BCM4321_CHIP_ID		0x4321		/* 4321 chipcommon chipid */
-#define	BCM43217_CHIP_ID	43217		/* 43217 chip id (OTP chipid) */
-#define	BCM4322_CHIP_ID		0x4322		/* 4322 chipcommon chipid */
-#define	BCM43221_CHIP_ID	43221		/* 43221 chipcommon chipid (OTP chipid) */
-#define	BCM43222_CHIP_ID	43222		/* 43222 chipcommon chipid */
-#define	BCM43224_CHIP_ID	43224		/* 43224 chipcommon chipid */
-#define	BCM43225_CHIP_ID	43225		/* 43225 chipcommon chipid */
-#define	BCM43227_CHIP_ID	43227		/* 43227 chipcommon chipid */
-#define	BCM43228_CHIP_ID	43228		/* 43228 chipcommon chipid */
-#define	BCM43226_CHIP_ID	43226		/* 43226 chipcommon chipid */
-#define	BCM43231_CHIP_ID	43231		/* 43231 chipcommon chipid (OTP chipid) */
-#define	BCM43234_CHIP_ID	43234		/* 43234 chipcommon chipid */
-#define	BCM43235_CHIP_ID	43235		/* 43235 chipcommon chipid */
-#define	BCM43236_CHIP_ID	43236		/* 43236 chipcommon chipid */
-#define	BCM43237_CHIP_ID	43237		/* 43237 chipcommon chipid */
-#define	BCM43238_CHIP_ID	43238		/* 43238 chipcommon chipid */
-#define	BCM43239_CHIP_ID	43239		/* 43239 chipcommon chipid */
-#define	BCM43420_CHIP_ID	43420		/* 43222 chipcommon chipid (OTP, RBBU) */
-#define	BCM43421_CHIP_ID	43421		/* 43224 chipcommon chipid (OTP, RBBU) */
-#define	BCM43428_CHIP_ID	43428		/* 43228 chipcommon chipid (OTP, RBBU) */
-#define	BCM43431_CHIP_ID	43431		/* 4331  chipcommon chipid (OTP, RBBU) */
-#define	BCM43460_CHIP_ID	43460		/* 4360  chipcommon chipid (OTP, RBBU) */
-#define	BCM4325_CHIP_ID		0x4325		/* 4325 chip id */
-#define	BCM4328_CHIP_ID		0x4328		/* 4328 chip id */
-#define	BCM4329_CHIP_ID		0x4329		/* 4329 chipcommon chipid */
-#define	BCM4331_CHIP_ID		0x4331		/* 4331 chipcommon chipid */
-#define BCM4336_CHIP_ID		0x4336		/* 4336 chipcommon chipid */
-#define BCM43362_CHIP_ID	43362		/* 43362 chipcommon chipid */
-#define BCM4330_CHIP_ID		0x4330		/* 4330 chipcommon chipid */
-#define BCM6362_CHIP_ID		0x6362		/* 6362 chipcommon chipid */
-#define BCM4314_CHIP_ID		0x4314		/* 4314 chipcommon chipid */
-#define BCM43142_CHIP_ID	43142		/* 43142 chipcommon chipid */
-#define BCM43143_CHIP_ID	43143		/* 43143 chipcommon chipid */
-#define	BCM4324_CHIP_ID		0x4324		/* 4324 chipcommon chipid */
-#define	BCM43242_CHIP_ID	43242		/* 43242 chipcommon chipid */
-#define	BCM43243_CHIP_ID	43243		/* 43243 chipcommon chipid */
-#define BCM4334_CHIP_ID		0x4334		/* 4334 chipcommon chipid */
-#define BCM4335_CHIP_ID		0x4335		/* 4335 chipcommon chipid */
-#define BCM4339_CHIP_ID		0x4339		/* 4339 chipcommon chipid */
-#define BCM43349_CHIP_ID	43349			/* 43349(0xA955) chipcommon chipid */
-#define BCM4360_CHIP_ID		0x4360          /* 4360 chipcommon chipid */
-#define BCM4364_CHIP_ID		0x4364			/* 4364 chipcommon chipid */
-#define BCM4352_CHIP_ID		0x4352          /* 4352 chipcommon chipid */
-#define BCM43526_CHIP_ID	0xAA06
-#define BCM43340_CHIP_ID	43340		/* 43340 chipcommon chipid */
-#define BCM43341_CHIP_ID	43341		/* 43341 chipcommon chipid */
-#define BCM43342_CHIP_ID	43342		/* 43342 chipcommon chipid */
-#define BCM4350_CHIP_ID		0x4350          /* 4350 chipcommon chipid */
-#define BCM4354_CHIP_ID		0x4354          /* 4354 chipcommon chipid */
-#define BCM4356_CHIP_ID		0x4356          /* 4356 chipcommon chipid */
-#define BCM43556_CHIP_ID	0xAA24          /* 43556 chipcommon chipid */
-#define BCM43558_CHIP_ID	0xAA26          /* 43558 chipcommon chipid */
-#define BCM43566_CHIP_ID	0xAA2E          /* 43566 chipcommon chipid */
-#define BCM43567_CHIP_ID	0xAA2F          /* 43567 chipcommon chipid */
-#define BCM43568_CHIP_ID	0xAA30          /* 43568 chipcommon chipid */
-#define BCM43569_CHIP_ID	0xAA31          /* 43569 chipcommon chipid */
-#define BCM43570_CHIP_ID	0xAA32          /* 43570 chipcommon chipid */
-#define BCM4358_CHIP_ID         0x4358          /* 4358 chipcommon chipid */
-#define	BCM43012_CHIP_ID	0xA804			/* 43012 chipcommon chipid */
-#define BCM4350_CHIP(chipid)	((CHIPID(chipid) == BCM4350_CHIP_ID) || \
-				(CHIPID(chipid) == BCM4354_CHIP_ID) || \
-				(CHIPID(chipid) == BCM4356_CHIP_ID) || \
-				(CHIPID(chipid) == BCM43556_CHIP_ID) || \
-				(CHIPID(chipid) == BCM43558_CHIP_ID) || \
-				(CHIPID(chipid) == BCM43566_CHIP_ID) || \
-				(CHIPID(chipid) == BCM43567_CHIP_ID) || \
-				(CHIPID(chipid) == BCM43568_CHIP_ID) || \
-				(CHIPID(chipid) == BCM43569_CHIP_ID) || \
-				(CHIPID(chipid) == BCM43570_CHIP_ID) || \
-				(CHIPID(chipid) == BCM4358_CHIP_ID)) /* 4350 variations */
-#define BCM4345_CHIP_ID		0x4345		/* 4345 chipcommon chipid */
-#define BCM43454_CHIP_ID	43454		/* 43454 chipcommon chipid */
-#define BCM43455_CHIP_ID    43455       /* 43455 chipcommon chipid */
-#define BCM43457_CHIP_ID    43457       /* 43457 chipcommon chipid */
-#define BCM43458_CHIP_ID    43458       /* 43458 chipcommon chipid */
-#define BCM43430_CHIP_ID	43430		/* 43430 chipcommon chipid */
-#define BCM4349_CHIP_ID		0x4349		/* 4349 chipcommon chipid */
-#define BCM4355_CHIP_ID		0x4355		/* 4355 chipcommon chipid */
-#define BCM4359_CHIP_ID		0x4359		/* 4359 chipcommon chipid */
-#define BCM4349_CHIP(chipid)	((CHIPID(chipid) == BCM4349_CHIP_ID) || \
-				(CHIPID(chipid) == BCM4355_CHIP_ID) || \
-				(CHIPID(chipid) == BCM4359_CHIP_ID))
-
-#define BCM4345_CHIP(chipid)    (CHIPID(chipid) == BCM4345_CHIP_ID || \
-				CHIPID(chipid) == BCM43454_CHIP_ID || \
-				CHIPID(chipid) == BCM43455_CHIP_ID || \
-				CHIPID(chipid) == BCM43457_CHIP_ID || \
-				CHIPID(chipid) == BCM43458_CHIP_ID)
-
-#define CASE_BCM4345_CHIP   case BCM4345_CHIP_ID: /* fallthrough */ \
-				case BCM43454_CHIP_ID: /* fallthrough */ \
-				case BCM43455_CHIP_ID: /* fallthrough */ \
-				case BCM43457_CHIP_ID: /* fallthrough */ \
-				case BCM43458_CHIP_ID
-
-#define BCM4349_CHIP_GRPID		BCM4349_CHIP_ID: \
-					case BCM4355_CHIP_ID: \
-					case BCM4359_CHIP_ID
-
-#define BCM4365_CHIP_ID		0x4365		/* 4365 chipcommon chipid */
-#define BCM4366_CHIP_ID		0x4366		/* 4366 chipcommon chipid */
-
-#define BCM43909_CHIP_ID	0xab85		/* 43909 chipcommon chipid */
-
-#define BCM43602_CHIP_ID	0xaa52		/* 43602 chipcommon chipid */
-#define BCM43462_CHIP_ID	0xa9c6		/* 43462 chipcommon chipid */
-#define BCM43522_CHIP_ID	0xaa02		/* 43522 chipcommon chipid */
-#define BCM43602_CHIP(chipid)	((CHIPID(chipid) == BCM43602_CHIP_ID) || \
-				(CHIPID(chipid) == BCM43462_CHIP_ID) || \
-				(CHIPID(chipid) == BCM43522_CHIP_ID)) /* 43602 variations */
-#define CASE_BCM43602_CHIP		case BCM43602_CHIP_ID: /* fallthrough */ \
-				case BCM43462_CHIP_ID: /* fallthrough */ \
-				case BCM43522_CHIP_ID
-
-#define	BCM4342_CHIP_ID		4342		/* 4342 chipcommon chipid (OTP, RBBU) */
-#define	BCM4402_CHIP_ID		0x4402		/* 4402 chipid */
-#define	BCM4704_CHIP_ID		0x4704		/* 4704 chipcommon chipid */
-#define	BCM4706_CHIP_ID		0x5300		/* 4706 chipcommon chipid */
-#define BCM4707_CHIP_ID		53010		/* 4707 chipcommon chipid */
-#define BCM47094_CHIP_ID	53030		/* 47094 chipcommon chipid */
-#define BCM53018_CHIP_ID	53018		/* 53018 chipcommon chipid */
-#define BCM4707_CHIP(chipid)	(((chipid) == BCM4707_CHIP_ID) || \
-				((chipid) == BCM53018_CHIP_ID) || \
-				((chipid) == BCM47094_CHIP_ID))
-#define	BCM4710_CHIP_ID		0x4710		/* 4710 chipid */
-#define	BCM4712_CHIP_ID		0x4712		/* 4712 chipcommon chipid */
-#define	BCM4716_CHIP_ID		0x4716		/* 4716 chipcommon chipid */
-#define	BCM47162_CHIP_ID	47162		/* 47162 chipcommon chipid */
-#define	BCM4748_CHIP_ID		0x4748		/* 4716 chipcommon chipid (OTP, RBBU) */
-#define	BCM4749_CHIP_ID		0x4749		/* 5357 chipcommon chipid (OTP, RBBU) */
-#define BCM4785_CHIP_ID		0x4785		/* 4785 chipcommon chipid */
-#define	BCM5350_CHIP_ID		0x5350		/* 5350 chipcommon chipid */
-#define	BCM5352_CHIP_ID		0x5352		/* 5352 chipcommon chipid */
-#define	BCM5354_CHIP_ID		0x5354		/* 5354 chipcommon chipid */
-#define BCM5365_CHIP_ID		0x5365		/* 5365 chipcommon chipid */
-#define	BCM5356_CHIP_ID		0x5356		/* 5356 chipcommon chipid */
-#define	BCM5357_CHIP_ID		0x5357		/* 5357 chipcommon chipid */
-#define	BCM53572_CHIP_ID	53572		/* 53572 chipcommon chipid */
-#define	BCM53573_CHIP_ID	53573		/* 53573 chipcommon chipid */
-#define BCM53573_CHIP(chipid)	(CHIPID(chipid) == BCM53573_CHIP_ID)
-#define BCM53573_CHIP_GRPID	BCM53573_CHIP_ID
-
-/* Package IDs */
-#define	BCM4303_PKG_ID		2		/* 4303 package id */
-#define	BCM4309_PKG_ID		1		/* 4309 package id */
-#define	BCM4712LARGE_PKG_ID	0		/* 340pin 4712 package id */
-#define	BCM4712SMALL_PKG_ID	1		/* 200pin 4712 package id */
-#define	BCM4712MID_PKG_ID	2		/* 225pin 4712 package id */
-#define BCM4328USBD11G_PKG_ID	2		/* 4328 802.11g USB package id */
-#define BCM4328USBDUAL_PKG_ID	3		/* 4328 802.11a/g USB package id */
-#define BCM4328SDIOD11G_PKG_ID	4		/* 4328 802.11g SDIO package id */
-#define BCM4328SDIODUAL_PKG_ID	5		/* 4328 802.11a/g SDIO package id */
-#define BCM4329_289PIN_PKG_ID	0		/* 4329 289-pin package id */
-#define BCM4329_182PIN_PKG_ID	1		/* 4329N 182-pin package id */
-#define BCM5354E_PKG_ID		1		/* 5354E package id */
-#define	BCM4716_PKG_ID		8		/* 4716 package id */
-#define	BCM4717_PKG_ID		9		/* 4717 package id */
-#define	BCM4718_PKG_ID		10		/* 4718 package id */
-#define BCM5356_PKG_NONMODE	1		/* 5356 package without nmode suppport */
-#define BCM5358U_PKG_ID		8		/* 5358U package id */
-#define BCM5358_PKG_ID		9		/* 5358 package id */
-#define BCM47186_PKG_ID		10		/* 47186 package id */
-#define BCM5357_PKG_ID		11		/* 5357 package id */
-#define BCM5356U_PKG_ID		12		/* 5356U package id */
-#define BCM53572_PKG_ID		8		/* 53572 package id */
-#define BCM5357C0_PKG_ID	8		/* 5357c0 package id (the same as 53572) */
-#define BCM47188_PKG_ID		9		/* 47188 package id */
-#define BCM5358C0_PKG_ID	0xa		/* 5358c0 package id */
-#define BCM5356C0_PKG_ID	0xb		/* 5356c0 package id */
-#define BCM4331TT_PKG_ID        8		/* 4331 12x12 package id */
-#define BCM4331TN_PKG_ID        9		/* 4331 12x9 package id */
-#define BCM4331TNA0_PKG_ID     0xb		/* 4331 12x9 package id */
-#define BCM47189_PKG_ID		1		/* 47189 package id */
-#define BCM53573_PKG_ID		0		/* 53573 package id */
-#define	BCM4706L_PKG_ID		1		/* 4706L package id */
-
-#define HDLSIM5350_PKG_ID	1		/* HDL simulator package id for a 5350 */
-#define HDLSIM_PKG_ID		14		/* HDL simulator package id */
-#define HWSIM_PKG_ID		15		/* Hardware simulator package id */
-#define BCM43224_FAB_CSM	0x8		/* the chip is manufactured by CSM */
-#define BCM43224_FAB_SMIC	0xa		/* the chip is manufactured by SMIC */
-#define BCM4336_WLBGA_PKG_ID	0x8
-#define BCM4330_WLBGA_PKG_ID	0x0
-#define BCM4314PCIE_ARM_PKG_ID		(8 | 0)	/* 4314 QFN PCI package id, bit 3 tie high */
-#define BCM4314SDIO_PKG_ID		(8 | 1)	/* 4314 QFN SDIO package id */
-#define BCM4314PCIE_PKG_ID		(8 | 2)	/* 4314 QFN PCI (ARM-less) package id */
-#define BCM4314SDIO_ARM_PKG_ID		(8 | 3)	/* 4314 QFN SDIO (ARM-less) package id */
-#define BCM4314SDIO_FPBGA_PKG_ID	(8 | 4)	/* 4314 FpBGA SDIO package id */
-#define BCM4314DEV_PKG_ID		(8 | 6)	/* 4314 Developement package id */
-
-#define BCM4707_PKG_ID		1		/* 4707 package id */
-#define BCM4708_PKG_ID		2		/* 4708 package id */
-#define BCM4709_PKG_ID		0		/* 4709 package id */
-
-#define PCIXX21_FLASHMEDIA0_ID	0x8033		/* TI PCI xx21 Standard Host Controller */
-#define PCIXX21_SDIOH0_ID	0x8034		/* TI PCI xx21 Standard Host Controller */
-
-#define BCM4335_WLCSP_PKG_ID	(0x0)	/* WLCSP Module/Mobile SDIO/HSIC. */
-#define BCM4335_FCBGA_PKG_ID	(0x1)	/* FCBGA PC/Embeded/Media PCIE/SDIO */
-#define BCM4335_WLBGA_PKG_ID	(0x2)	/* WLBGA COB/Mobile SDIO/HSIC. */
-#define BCM4335_FCBGAD_PKG_ID	(0x3)	/* FCBGA Debug Debug/Dev All if's. */
-#define BCM4335_PKG_MASK	(0x3)
-#define BCM43602_12x12_PKG_ID	(0x1)	/* 12x12 pins package, used for e.g. router designs */
-
-/* boardflags */
-#define	BFL_BTC2WIRE		0x00000001  /* old 2wire Bluetooth coexistence, OBSOLETE */
-#define BFL_BTCOEX      0x00000001      /* Board supports BTCOEX */
-#define	BFL_PACTRL		0x00000002  /* Board has gpio 9 controlling the PA */
-#define BFL_AIRLINEMODE	0x00000004  /* Board implements gpio 13 radio disable indication, UNUSED */
-#define	BFL_ADCDIV		0x00000008  /* Board has the rssi ADC divider */
-#define BFL_DIS_256QAM		0x00000008
-#define	BFL_ENETROBO		0x00000010  /* Board has robo switch or core */
-#define	BFL_TSSIAVG   		0x00000010  /* TSSI averaging for ACPHY chips */
-#define	BFL_NOPLLDOWN		0x00000020  /* Not ok to power down the chip pll and oscillator */
-#define	BFL_CCKHIPWR		0x00000040  /* Can do high-power CCK transmission */
-#define	BFL_ENETADM		0x00000080  /* Board has ADMtek switch */
-#define	BFL_ENETVLAN		0x00000100  /* Board has VLAN capability */
-#define	BFL_LTECOEX		0x00000200  /* LTE Coex enabled */
-#define BFL_NOPCI		0x00000400  /* Board leaves PCI floating */
-#define BFL_FEM			0x00000800  /* Board supports the Front End Module */
-#define BFL_EXTLNA		0x00001000  /* Board has an external LNA in 2.4GHz band */
-#define BFL_HGPA		0x00002000  /* Board has a high gain PA */
-#define	BFL_BTC2WIRE_ALTGPIO	0x00004000  /* Board's BTC 2wire is in the alternate gpios */
-#define	BFL_ALTIQ		0x00008000  /* Alternate I/Q settings */
-#define BFL_NOPA		0x00010000  /* Board has no PA */
-#define BFL_RSSIINV		0x00020000  /* Board's RSSI uses positive slope(not TSSI) */
-#define BFL_PAREF		0x00040000  /* Board uses the PARef LDO */
-#define BFL_3TSWITCH		0x00080000  /* Board uses a triple throw switch shared with BT */
-#define BFL_PHASESHIFT		0x00100000  /* Board can support phase shifter */
-#define BFL_BUCKBOOST		0x00200000  /* Power topology uses BUCKBOOST */
-#define BFL_FEM_BT		0x00400000  /* Board has FEM and switch to share antenna w/ BT */
-#define BFL_NOCBUCK		0x00800000  /* Power topology doesn't use CBUCK */
-#define BFL_CCKFAVOREVM		0x01000000  /* Favor CCK EVM over spectral mask */
-#define BFL_PALDO		0x02000000  /* Power topology uses PALDO */
-#define BFL_LNLDO2_2P5		0x04000000  /* Select 2.5V as LNLDO2 output voltage */
-#define BFL_FASTPWR		0x08000000
-#define BFL_UCPWRCTL_MININDX	0x08000000  /* Enforce min power index to avoid FEM damage */
-#define BFL_EXTLNA_5GHz		0x10000000  /* Board has an external LNA in 5GHz band */
-#define BFL_TRSW_1by2		0x20000000  /* Board has 2 TRSW's in 1by2 designs */
-#define BFL_GAINBOOSTA01        0x20000000  /* 5g Gainboost for core0 and core1 */
-#define BFL_LO_TRSW_R_5GHz	0x40000000  /* In 5G do not throw TRSW to T for clipLO gain */
-#define BFL_ELNA_GAINDEF	0x80000000  /* Backoff InitGain based on elna_2g/5g field
-					     * when this flag is set
-					     */
-#define BFL_EXTLNA_TX	0x20000000	/* Temp boardflag to indicate to */
-
-/* boardflags2 */
-#define BFL2_RXBB_INT_REG_DIS	0x00000001  /* Board has an external rxbb regulator */
-#define BFL2_APLL_WAR		0x00000002  /* Flag to implement alternative A-band PLL settings */
-#define BFL2_TXPWRCTRL_EN	0x00000004  /* Board permits enabling TX Power Control */
-#define BFL2_2X4_DIV		0x00000008  /* Board supports the 2X4 diversity switch */
-#define BFL2_5G_PWRGAIN		0x00000010  /* Board supports 5G band power gain */
-#define BFL2_PCIEWAR_OVR	0x00000020  /* Board overrides ASPM and Clkreq settings */
-#define BFL2_CAESERS_BRD	0x00000040  /* Board is Caesers brd (unused by sw) */
-#define BFL2_BTC3WIRE		0x00000080  /* Board support legacy 3 wire or 4 wire */
-#define BFL2_BTCLEGACY          0x00000080  /* Board support legacy 3/4 wire, to replace
-					     * BFL2_BTC3WIRE
-					     */
-#define BFL2_SKWRKFEM_BRD	0x00000100  /* 4321mcm93 board uses Skyworks FEM */
-#define BFL2_SPUR_WAR		0x00000200  /* Board has a WAR for clock-harmonic spurs */
-#define BFL2_GPLL_WAR		0x00000400  /* Flag to narrow G-band PLL loop b/w */
-#define BFL2_TRISTATE_LED	0x00000800  /* Tri-state the LED */
-#define BFL2_SINGLEANT_CCK	0x00001000  /* Tx CCK pkts on Ant 0 only */
-#define BFL2_2G_SPUR_WAR	0x00002000  /* WAR to reduce and avoid clock-harmonic spurs in 2G */
-#define BFL2_BPHY_ALL_TXCORES	0x00004000  /* Transmit bphy frames using all tx cores */
-#define BFL2_FCC_BANDEDGE_WAR	0x00008000  /* Activates WAR to improve FCC bandedge performance */
-#define BFL2_DAC_SPUR_IMPROVEMENT 0x00008000       /* Reducing DAC Spurs */
-#define BFL2_GPLL_WAR2	        0x00010000  /* Flag to widen G-band PLL loop b/w */
-#define BFL2_REDUCED_PA_TURNONTIME 0x00010000  /* Flag to reduce PA turn on Time */
-#define BFL2_IPALVLSHIFT_3P3    0x00020000
-#define BFL2_INTERNDET_TXIQCAL  0x00040000  /* Use internal envelope detector for TX IQCAL */
-#define BFL2_XTALBUFOUTEN       0x00080000  /* Keep the buffered Xtal output from radio on */
-				/* Most drivers will turn it off without this flag */
-				/* to save power. */
-
-#define BFL2_ANAPACTRL_2G	0x00100000  /* 2G ext PAs are controlled by analog PA ctrl lines */
-#define BFL2_ANAPACTRL_5G	0x00200000  /* 5G ext PAs are controlled by analog PA ctrl lines */
-#define BFL2_ELNACTRL_TRSW_2G	0x00400000  /* AZW4329: 2G gmode_elna_gain controls TR Switch */
-#define BFL2_BT_SHARE_ANT0	0x00800000  /* share core0 antenna with BT */
-#define BFL2_TEMPSENSE_HIGHER	0x01000000  /* The tempsense threshold can sustain higher value
-					     * than programmed. The exact delta is decided by
-					     * driver per chip/boardtype. This can be used
-					     * when tempsense qualification happens after shipment
-					     */
-#define BFL2_BTC3WIREONLY       0x02000000  /* standard 3 wire btc only.  4 wire not supported */
-#define BFL2_PWR_NOMINAL	0x04000000  /* 0: power reduction on, 1: no power reduction */
-#define BFL2_EXTLNA_PWRSAVE	0x08000000  /* boardflag to enable ucode to apply power save */
-						/* ucode control of eLNA during Tx */
-#define BFL2_4313_RADIOREG	0x10000000
-									   /*  board rework */
-#define BFL2_DYNAMIC_VMID	0x10000000  /* enable dynamic Vmid in idle TSSI CAL for 4331 */
-
-#define BFL2_SDR_EN		0x20000000  /* SDR enabled or disabled */
-#define BFL2_DYNAMIC_VMID	0x10000000  /* boardflag to enable dynamic Vmid idle TSSI CAL */
-#define BFL2_LNA1BYPFORTR2G	0x40000000  /* acphy, enable lna1 bypass for clip gain, 2g */
-#define BFL2_LNA1BYPFORTR5G	0x80000000  /* acphy, enable lna1 bypass for clip gain, 5g */
-
-/* SROM 11 - 11ac boardflag definitions */
-#define BFL_SROM11_BTCOEX  0x00000001  /* Board supports BTCOEX */
-#define BFL_SROM11_WLAN_BT_SH_XTL  0x00000002  /* bluetooth and wlan share same crystal */
-#define BFL_SROM11_EXTLNA	0x00001000  /* Board has an external LNA in 2.4GHz band */
-#define BFL_SROM11_EPA_TURNON_TIME     0x00018000  /* 2 bits for different PA turn on times */
-#define BFL_SROM11_EPA_TURNON_TIME_SHIFT  15
-#define BFL_SROM11_PRECAL_TX_IDX	0x00040000  /* Dedicated TX IQLOCAL IDX values */
-				/* per subband, as derived from 43602A1 MCH5 */
-#define BFL_SROM11_EXTLNA_5GHz	0x10000000  /* Board has an external LNA in 5GHz band */
-#define BFL_SROM11_GAINBOOSTA01	0x20000000  /* 5g Gainboost for core0 and core1 */
-#define BFL2_SROM11_APLL_WAR	0x00000002  /* Flag to implement alternative A-band PLL settings */
-#define BFL2_SROM11_ANAPACTRL_2G  0x00100000  /* 2G ext PAs are ctrl-ed by analog PA ctrl lines */
-#define BFL2_SROM11_ANAPACTRL_5G  0x00200000  /* 5G ext PAs are ctrl-ed by analog PA ctrl lines */
-#define BFL2_SROM11_SINGLEANT_CCK	0x00001000  /* Tx CCK pkts on Ant 0 only */
-#define BFL2_SROM11_EPA_ON_DURING_TXIQLOCAL    0x00020000  /* Keep ext. PA's on in TX IQLO CAL */
-
-/* boardflags3 */
-#define BFL3_FEMCTRL_SUB	  0x00000007  /* acphy, subrevs of femctrl on top of srom_femctrl */
-#define BFL3_RCAL_WAR		  0x00000008  /* acphy, rcal war active on this board (4335a0) */
-#define BFL3_TXGAINTBLID	  0x00000070  /* acphy, txgain table id */
-#define BFL3_TXGAINTBLID_SHIFT	  0x4         /* acphy, txgain table id shift bit */
-#define BFL3_TSSI_DIV_WAR	  0x00000080  /* acphy, Seperate paparam for 20/40/80 */
-#define BFL3_TSSI_DIV_WAR_SHIFT	  0x7         /* acphy, Seperate paparam for 20/40/80 shift bit */
-#define BFL3_FEMTBL_FROM_NVRAM    0x00000100  /* acphy, femctrl table is read from nvram */
-#define BFL3_FEMTBL_FROM_NVRAM_SHIFT 0x8         /* acphy, femctrl table is read from nvram */
-#define BFL3_AGC_CFG_2G           0x00000200  /* acphy, gain control configuration for 2G */
-#define BFL3_AGC_CFG_5G           0x00000400  /* acphy, gain control configuration for 5G */
-#define BFL3_PPR_BIT_EXT          0x00000800  /* acphy, bit position for 1bit extension for ppr */
-#define BFL3_PPR_BIT_EXT_SHIFT    11          /* acphy, bit shift for 1bit extension for ppr */
-#define BFL3_BBPLL_SPR_MODE_DIS	  0x00001000  /* acphy, disables bbpll spur modes */
-#define BFL3_RCAL_OTP_VAL_EN      0x00002000  /* acphy, to read rcal_trim value from otp */
-#define BFL3_2GTXGAINTBL_BLANK	  0x00004000  /* acphy, blank the first X ticks of 2g gaintbl */
-#define BFL3_2GTXGAINTBL_BLANK_SHIFT 14       /* acphy, blank the first X ticks of 2g gaintbl */
-#define BFL3_5GTXGAINTBL_BLANK	  0x00008000  /* acphy, blank the first X ticks of 5g gaintbl */
-#define BFL3_5GTXGAINTBL_BLANK_SHIFT 15       /* acphy, blank the first X ticks of 5g gaintbl */
-#define BFL3_PHASETRACK_MAX_ALPHABETA	  0x00010000  /* acphy, to max out alpha,beta to 511 */
-#define BFL3_PHASETRACK_MAX_ALPHABETA_SHIFT 16       /* acphy, to max out alpha,beta to 511 */
-/* acphy, to use backed off gaintbl for lte-coex */
-#define BFL3_LTECOEX_GAINTBL_EN           0x00060000
-/* acphy, to use backed off gaintbl for lte-coex */
-#define BFL3_LTECOEX_GAINTBL_EN_SHIFT 17
-#define BFL3_5G_SPUR_WAR          0x00080000  /* acphy, enable spur WAR in 5G band */
-#define BFL3_1X1_RSDB_ANT	  0x01000000  /* to find if 2-ant RSDB board or 1-ant RSDB board */
-#define BFL3_1X1_RSDB_ANT_SHIFT           24
-
-/* acphy: lpmode2g and lpmode_5g related boardflags */
-#define BFL3_ACPHY_LPMODE_2G	  0x00300000  /* bits 20:21 for lpmode_2g choice */
-#define BFL3_ACPHY_LPMODE_2G_SHIFT	  20
-
-#define BFL3_ACPHY_LPMODE_5G	  0x00C00000  /* bits 22:23 for lpmode_5g choice */
-#define BFL3_ACPHY_LPMODE_5G_SHIFT	  22
-
-#define BFL3_EXT_LPO_ISCLOCK      0x02000000  /* External LPO is clock, not x-tal */
-#define BFL3_FORCE_INT_LPO_SEL    0x04000000  /* Force internal lpo */
-#define BFL3_FORCE_EXT_LPO_SEL    0x08000000  /* Force external lpo */
-
-#define BFL3_EN_BRCM_IMPBF        0x10000000  /* acphy, Allow BRCM Implicit TxBF */
-#define BFL3_AVVMID_FROM_NVRAM    0x40000000  /* Read Av Vmid from NVRAM  */
-#define BFL3_VLIN_EN_FROM_NVRAM    0x80000000  /* Read Vlin En from NVRAM  */
-
-#define BFL3_AVVMID_FROM_NVRAM_SHIFT   30   /* Read Av Vmid from NVRAM  */
-#define BFL3_VLIN_EN_FROM_NVRAM_SHIFT   31   /* Enable Vlin  from NVRAM  */
-
-/* boardflags4 for SROM12 */
-#define BFL4_SROM12_4dBPAD      (1 << 0)   /* To distinguigh between normal and 4dB pad board */
-
-
-/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */
-#define	BOARD_GPIO_BTC3W_IN	0x850	/* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */
-#define	BOARD_GPIO_BTC3W_OUT	0x020	/* bit 5 is TX_CONF */
-#define	BOARD_GPIO_BTCMOD_IN	0x010	/* bit 4 is the alternate BT Coexistence Input */
-#define	BOARD_GPIO_BTCMOD_OUT	0x020	/* bit 5 is the alternate BT Coexistence Out */
-#define	BOARD_GPIO_BTC_IN	0x080	/* bit 7 is BT Coexistence Input */
-#define	BOARD_GPIO_BTC_OUT	0x100	/* bit 8 is BT Coexistence Out */
-#define	BOARD_GPIO_PACTRL	0x200	/* bit 9 controls the PA on new 4306 boards */
-#define BOARD_GPIO_12		0x1000	/* gpio 12 */
-#define BOARD_GPIO_13		0x2000	/* gpio 13 */
-#define BOARD_GPIO_BTC4_IN	0x0800	/* gpio 11, coex4, in */
-#define BOARD_GPIO_BTC4_BT	0x2000	/* gpio 12, coex4, bt active */
-#define BOARD_GPIO_BTC4_STAT	0x4000	/* gpio 14, coex4, status */
-#define BOARD_GPIO_BTC4_WLAN	0x8000	/* gpio 15, coex4, wlan active */
-#define	BOARD_GPIO_1_WLAN_PWR	0x02	/* throttle WLAN power on X21 board */
-#define	BOARD_GPIO_2_WLAN_PWR	0x04	/* throttle WLAN power on X29C board */
-#define	BOARD_GPIO_3_WLAN_PWR	0x08	/* throttle WLAN power on X28 board */
-#define	BOARD_GPIO_4_WLAN_PWR	0x10	/* throttle WLAN power on X19 board */
-#define	BOARD_GPIO_13_WLAN_PWR	0x2000	/* throttle WLAN power on X14 board */
-
-#define GPIO_BTC4W_OUT_4312  0x010  /* bit 4 is BT_IODISABLE */
-#define GPIO_BTC4W_OUT_43224  0x020  /* bit 5 is BT_IODISABLE */
-#define GPIO_BTC4W_OUT_43224_SHARED  0x0e0  /* bit 5 is BT_IODISABLE */
-#define GPIO_BTC4W_OUT_43225  0x0e0  /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */
-#define GPIO_BTC4W_OUT_43421  0x020  /* bit 5 is BT_IODISABLE */
-#define GPIO_BTC4W_OUT_4313  0x060  /* bit 5 SW_BT, bit 6 SW_WL */
-#define GPIO_BTC4W_OUT_4331_SHARED  0x010  /* GPIO 4  */
-
-#define	PCI_CFG_GPIO_SCS	0x10	/* PCI config space bit 4 for 4306c0 slow clock source */
-#define PCI_CFG_GPIO_HWRAD	0x20	/* PCI config space GPIO 13 for hw radio disable */
-#define PCI_CFG_GPIO_XTAL	0x40	/* PCI config space GPIO 14 for Xtal power-up */
-#define PCI_CFG_GPIO_PLL	0x80	/* PCI config space GPIO 15 for PLL power-down */
-
-/* power control defines */
-#define PLL_DELAY		150		/* us pll on delay */
-#define FREF_DELAY		200		/* us fref change delay */
-#define MIN_SLOW_CLK		32		/* us Slow clock period */
-#define	XTAL_ON_DELAY		1000		/* us crystal power-on delay */
-
-
-/* 43341 Boards */
-#define BCM943341WLABGS_SSID	0x062d
-
-/* 43342 Boards */
-#define BCM943342FCAGBI_SSID	0x0641
-
-/* 43602 Boards, unclear yet what boards will be created. */
-#define BCM943602RSVD1_SSID	0x06a5
-#define BCM943602RSVD2_SSID	0x06a6
-#define BCM943602X87            0X0133
-#define BCM943602X87P2          0X0143
-#define BCM943602X238           0X0132
-#define BCM943602X238D          0X014A
-
-/* # of GPIO pins */
-#define GPIO_NUMPINS		32
-
-/* These values are used by dhd host driver. */
-#define RDL_RAM_BASE_4319 0x60000000
-#define RDL_RAM_BASE_4329 0x60000000
-#define RDL_RAM_SIZE_4319 0x48000
-#define RDL_RAM_SIZE_4329  0x48000
-#define RDL_RAM_SIZE_43236 0x70000
-#define RDL_RAM_BASE_43236 0x60000000
-#define RDL_RAM_SIZE_4328 0x60000
-#define RDL_RAM_BASE_4328 0x80000000
-#define RDL_RAM_SIZE_4322 0x60000
-#define RDL_RAM_BASE_4322 0x60000000
-#define RDL_RAM_SIZE_4360  0xA0000
-#define RDL_RAM_BASE_4360  0x60000000
-#define RDL_RAM_SIZE_43242  0x90000
-#define RDL_RAM_BASE_43242  0x60000000
-#define RDL_RAM_SIZE_43143  0x70000
-#define RDL_RAM_BASE_43143  0x60000000
-#define RDL_RAM_SIZE_4350  0xC0000
-#define RDL_RAM_BASE_4350  0x180800
-
-/* generic defs for nvram "muxenab" bits
-* Note: these differ for 4335a0. refer bcmchipc.h for specific mux options.
-*/
-#define MUXENAB_UART		0x00000001
-#define MUXENAB_GPIO		0x00000002
-#define MUXENAB_ERCX		0x00000004	/* External Radio BT coex */
-#define MUXENAB_JTAG		0x00000008
-#define MUXENAB_HOST_WAKE	0x00000010	/* configure GPIO for SDIO host_wake */
-#define MUXENAB_I2S_EN		0x00000020
-#define MUXENAB_I2S_MASTER	0x00000040
-#define MUXENAB_I2S_FULL	0x00000080
-#define MUXENAB_SFLASH		0x00000100
-#define MUXENAB_RFSWCTRL0	0x00000200
-#define MUXENAB_RFSWCTRL1	0x00000400
-#define MUXENAB_RFSWCTRL2	0x00000800
-#define MUXENAB_SECI		0x00001000
-#define MUXENAB_BT_LEGACY	0x00002000
-#define MUXENAB_HOST_WAKE1	0x00004000	/* configure alternative GPIO for SDIO host_wake */
-
-/* Boot flags */
-#define FLASH_KERNEL_NFLASH	0x00000001
-#define FLASH_BOOT_NFLASH	0x00000002
-
-#endif /* _BCMDEVS_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmendian.h b/drivers/net/wireless/bcmdhd/include/bcmendian.h
deleted file mode 100644
index 27f2379..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmendian.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Byte order utilities
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- *  $Id: bcmendian.h 514727 2014-11-12 03:02:48Z $
- *
- * This file by default provides proper behavior on little-endian architectures.
- * On big-endian architectures, IL_BIGENDIAN should be defined.
- */
-
-#ifndef _BCMENDIAN_H_
-#define _BCMENDIAN_H_
-
-#include <typedefs.h>
-
-/* Reverse the bytes in a 16-bit value */
-#define BCMSWAP16(val) \
-	((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \
-		  (((uint16)(val) & (uint16)0xff00U) >> 8)))
-
-/* Reverse the bytes in a 32-bit value */
-#define BCMSWAP32(val) \
-	((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \
-		  (((uint32)(val) & (uint32)0x0000ff00U) <<  8) | \
-		  (((uint32)(val) & (uint32)0x00ff0000U) >>  8) | \
-		  (((uint32)(val) & (uint32)0xff000000U) >> 24)))
-
-/* Reverse the two 16-bit halves of a 32-bit value */
-#define BCMSWAP32BY16(val) \
-	((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \
-		  (((uint32)(val) & (uint32)0xffff0000U) >> 16)))
-
-/* Reverse the bytes in a 64-bit value */
-#define BCMSWAP64(val) \
-	((uint64)((((uint64)(val) & 0x00000000000000ffULL) << 56) | \
-	          (((uint64)(val) & 0x000000000000ff00ULL) << 40) | \
-	          (((uint64)(val) & 0x0000000000ff0000ULL) << 24) | \
-	          (((uint64)(val) & 0x00000000ff000000ULL) <<  8) | \
-	          (((uint64)(val) & 0x000000ff00000000ULL) >>  8) | \
-	          (((uint64)(val) & 0x0000ff0000000000ULL) >> 24) | \
-	          (((uint64)(val) & 0x00ff000000000000ULL) >> 40) | \
-	          (((uint64)(val) & 0xff00000000000000ULL) >> 56)))
-
-/* Reverse the two 32-bit halves of a 64-bit value */
-#define BCMSWAP64BY32(val) \
-	((uint64)((((uint64)(val) & 0x00000000ffffffffULL) << 32) | \
-	          (((uint64)(val) & 0xffffffff00000000ULL) >> 32)))
-
-
-/* Byte swapping macros
- *    Host <=> Network (Big Endian) for 16- and 32-bit values
- *    Host <=> Little-Endian for 16- and 32-bit values
- */
-#ifndef hton16
-#define HTON16(i) BCMSWAP16(i)
-#define	hton16(i) bcmswap16(i)
-#define	HTON32(i) BCMSWAP32(i)
-#define	hton32(i) bcmswap32(i)
-#define	NTOH16(i) BCMSWAP16(i)
-#define	ntoh16(i) bcmswap16(i)
-#define	NTOH32(i) BCMSWAP32(i)
-#define	ntoh32(i) bcmswap32(i)
-#define LTOH16(i) (i)
-#define ltoh16(i) (i)
-#define LTOH32(i) (i)
-#define ltoh32(i) (i)
-#define HTOL16(i) (i)
-#define htol16(i) (i)
-#define HTOL32(i) (i)
-#define htol32(i) (i)
-#define HTOL64(i) (i)
-#define htol64(i) (i)
-#endif /* hton16 */
-
-#define ltoh16_buf(buf, i)
-#define htol16_buf(buf, i)
-
-/* Unaligned loads and stores in host byte order */
-#define load32_ua(a)		ltoh32_ua(a)
-#define store32_ua(a, v)	htol32_ua_store(v, a)
-#define load16_ua(a)		ltoh16_ua(a)
-#define store16_ua(a, v)	htol16_ua_store(v, a)
-
-#define _LTOH16_UA(cp)	((cp)[0] | ((cp)[1] << 8))
-#define _LTOH32_UA(cp)	((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24))
-#define _NTOH16_UA(cp)	(((cp)[0] << 8) | (cp)[1])
-#define _NTOH32_UA(cp)	(((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3])
-
-#define ltoh_ua(ptr) \
-	(sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
-	 sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \
-	 sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \
-	 *(uint8 *)0)
-
-#define ntoh_ua(ptr) \
-	(sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
-	 sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \
-	 sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \
-	 *(uint8 *)0)
-
-#ifdef __GNUC__
-
-/* GNU macro versions avoid referencing the argument multiple times, while also
- * avoiding the -fno-inline used in ROM builds.
- */
-
-#define bcmswap16(val) ({ \
-	uint16 _val = (val); \
-	BCMSWAP16(_val); \
-})
-
-#define bcmswap32(val) ({ \
-	uint32 _val = (val); \
-	BCMSWAP32(_val); \
-})
-
-#define bcmswap64(val) ({ \
-	uint64 _val = (val); \
-	BCMSWAP64(_val); \
-})
-
-#define bcmswap32by16(val) ({ \
-	uint32 _val = (val); \
-	BCMSWAP32BY16(_val); \
-})
-
-#define bcmswap16_buf(buf, len) ({ \
-	uint16 *_buf = (uint16 *)(buf); \
-	uint _wds = (len) / 2; \
-	while (_wds--) { \
-		*_buf = bcmswap16(*_buf); \
-		_buf++; \
-	} \
-})
-
-#define htol16_ua_store(val, bytes) ({ \
-	uint16 _val = (val); \
-	uint8 *_bytes = (uint8 *)(bytes); \
-	_bytes[0] = _val & 0xff; \
-	_bytes[1] = _val >> 8; \
-})
-
-#define htol32_ua_store(val, bytes) ({ \
-	uint32 _val = (val); \
-	uint8 *_bytes = (uint8 *)(bytes); \
-	_bytes[0] = _val & 0xff; \
-	_bytes[1] = (_val >> 8) & 0xff; \
-	_bytes[2] = (_val >> 16) & 0xff; \
-	_bytes[3] = _val >> 24; \
-})
-
-#define hton16_ua_store(val, bytes) ({ \
-	uint16 _val = (val); \
-	uint8 *_bytes = (uint8 *)(bytes); \
-	_bytes[0] = _val >> 8; \
-	_bytes[1] = _val & 0xff; \
-})
-
-#define hton32_ua_store(val, bytes) ({ \
-	uint32 _val = (val); \
-	uint8 *_bytes = (uint8 *)(bytes); \
-	_bytes[0] = _val >> 24; \
-	_bytes[1] = (_val >> 16) & 0xff; \
-	_bytes[2] = (_val >> 8) & 0xff; \
-	_bytes[3] = _val & 0xff; \
-})
-
-#define ltoh16_ua(bytes) ({ \
-	const uint8 *_bytes = (const uint8 *)(bytes); \
-	_LTOH16_UA(_bytes); \
-})
-
-#define ltoh32_ua(bytes) ({ \
-	const uint8 *_bytes = (const uint8 *)(bytes); \
-	_LTOH32_UA(_bytes); \
-})
-
-#define ntoh16_ua(bytes) ({ \
-	const uint8 *_bytes = (const uint8 *)(bytes); \
-	_NTOH16_UA(_bytes); \
-})
-
-#define ntoh32_ua(bytes) ({ \
-	const uint8 *_bytes = (const uint8 *)(bytes); \
-	_NTOH32_UA(_bytes); \
-})
-
-#else /* !__GNUC__ */
-
-/* Inline versions avoid referencing the argument multiple times */
-static INLINE uint16
-bcmswap16(uint16 val)
-{
-	return BCMSWAP16(val);
-}
-
-static INLINE uint32
-bcmswap32(uint32 val)
-{
-	return BCMSWAP32(val);
-}
-
-static INLINE uint64
-bcmswap64(uint64 val)
-{
-	return BCMSWAP64(val);
-}
-
-static INLINE uint32
-bcmswap32by16(uint32 val)
-{
-	return BCMSWAP32BY16(val);
-}
-
-/* Reverse pairs of bytes in a buffer (not for high-performance use) */
-/* buf	- start of buffer of shorts to swap */
-/* len  - byte length of buffer */
-static INLINE void
-bcmswap16_buf(uint16 *buf, uint len)
-{
-	len = len / 2;
-
-	while (len--) {
-		*buf = bcmswap16(*buf);
-		buf++;
-	}
-}
-
-/*
- * Store 16-bit value to unaligned little-endian byte array.
- */
-static INLINE void
-htol16_ua_store(uint16 val, uint8 *bytes)
-{
-	bytes[0] = val & 0xff;
-	bytes[1] = val >> 8;
-}
-
-/*
- * Store 32-bit value to unaligned little-endian byte array.
- */
-static INLINE void
-htol32_ua_store(uint32 val, uint8 *bytes)
-{
-	bytes[0] = val & 0xff;
-	bytes[1] = (val >> 8) & 0xff;
-	bytes[2] = (val >> 16) & 0xff;
-	bytes[3] = val >> 24;
-}
-
-/*
- * Store 16-bit value to unaligned network-(big-)endian byte array.
- */
-static INLINE void
-hton16_ua_store(uint16 val, uint8 *bytes)
-{
-	bytes[0] = val >> 8;
-	bytes[1] = val & 0xff;
-}
-
-/*
- * Store 32-bit value to unaligned network-(big-)endian byte array.
- */
-static INLINE void
-hton32_ua_store(uint32 val, uint8 *bytes)
-{
-	bytes[0] = val >> 24;
-	bytes[1] = (val >> 16) & 0xff;
-	bytes[2] = (val >> 8) & 0xff;
-	bytes[3] = val & 0xff;
-}
-
-/*
- * Load 16-bit value from unaligned little-endian byte array.
- */
-static INLINE uint16
-ltoh16_ua(const void *bytes)
-{
-	return _LTOH16_UA((const uint8 *)bytes);
-}
-
-/*
- * Load 32-bit value from unaligned little-endian byte array.
- */
-static INLINE uint32
-ltoh32_ua(const void *bytes)
-{
-	return _LTOH32_UA((const uint8 *)bytes);
-}
-
-/*
- * Load 16-bit value from unaligned big-(network-)endian byte array.
- */
-static INLINE uint16
-ntoh16_ua(const void *bytes)
-{
-	return _NTOH16_UA((const uint8 *)bytes);
-}
-
-/*
- * Load 32-bit value from unaligned big-(network-)endian byte array.
- */
-static INLINE uint32
-ntoh32_ua(const void *bytes)
-{
-	return _NTOH32_UA((const uint8 *)bytes);
-}
-
-#endif /* !__GNUC__ */
-#endif /* !_BCMENDIAN_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmmsgbuf.h b/drivers/net/wireless/bcmdhd/include/bcmmsgbuf.h
deleted file mode 100644
index ab1375e..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmmsgbuf.h
+++ /dev/null
@@ -1,863 +0,0 @@
-/*
- * MSGBUF network driver ioctl/indication encoding
- * Broadcom 802.11abg Networking Device Driver
- *
- * Definitions subject to change without notice.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmmsgbuf.h 541060 2015-03-13 23:28:01Z $
- */
-#ifndef _bcmmsgbuf_h_
-#define	_bcmmsgbuf_h_
-
-#include <proto/ethernet.h>
-#include <wlioctl.h>
-#include <bcmpcie.h>
-
-#define MSGBUF_MAX_MSG_SIZE   ETHER_MAX_LEN
-
-#define D2H_EPOCH_MODULO		253 /* sequence number wrap */
-#define D2H_EPOCH_INIT_VAL		(D2H_EPOCH_MODULO + 1)
-
-#define H2D_EPOCH_MODULO		253 /* sequence number wrap */
-#define H2D_EPOCH_INIT_VAL		(H2D_EPOCH_MODULO + 1)
-
-#define H2DRING_TXPOST_ITEMSIZE		48
-#define H2DRING_RXPOST_ITEMSIZE		32
-#define H2DRING_CTRL_SUB_ITEMSIZE	40
-#define D2HRING_TXCMPLT_ITEMSIZE	16
-#define D2HRING_RXCMPLT_ITEMSIZE	32
-#define D2HRING_CTRL_CMPLT_ITEMSIZE	24
-
-#define H2DRING_TXPOST_MAX_ITEM			512
-#define H2DRING_RXPOST_MAX_ITEM			512
-#define H2DRING_CTRL_SUB_MAX_ITEM		64
-#define D2HRING_TXCMPLT_MAX_ITEM		1024
-#define D2HRING_RXCMPLT_MAX_ITEM		512
-
-#define D2HRING_CTRL_CMPLT_MAX_ITEM		64
-
-enum {
-	DNGL_TO_HOST_MSGBUF,
-	HOST_TO_DNGL_MSGBUF
-};
-
-enum {
-	HOST_TO_DNGL_TXP_DATA,
-	HOST_TO_DNGL_RXP_DATA,
-	HOST_TO_DNGL_CTRL,
-	DNGL_TO_HOST_DATA,
-	DNGL_TO_HOST_CTRL
-};
-
-#define MESSAGE_PAYLOAD(a) (a & MSG_TYPE_INTERNAL_USE_START) ? TRUE : FALSE
-
-#ifdef PCIE_API_REV1
-
-#define BCMMSGBUF_DUMMY_REF(a, b)	do {BCM_REFERENCE((a));BCM_REFERENCE((b));}  while (0)
-
-#define BCMMSGBUF_API_IFIDX(a)		0
-#define BCMMSGBUF_API_SEQNUM(a)		0
-#define BCMMSGBUF_IOCTL_XTID(a)		0
-#define BCMMSGBUF_IOCTL_PKTID(a)	((a)->cmd_id)
-
-#define BCMMSGBUF_SET_API_IFIDX(a, b)	BCMMSGBUF_DUMMY_REF(a, b)
-#define BCMMSGBUF_SET_API_SEQNUM(a, b)	BCMMSGBUF_DUMMY_REF(a, b)
-#define BCMMSGBUF_IOCTL_SET_PKTID(a, b)	(BCMMSGBUF_IOCTL_PKTID(a) = (b))
-#define BCMMSGBUF_IOCTL_SET_XTID(a, b)	BCMMSGBUF_DUMMY_REF(a, b)
-
-#else /* PCIE_API_REV1 */
-
-#define BCMMSGBUF_API_IFIDX(a)		((a)->if_id)
-#define BCMMSGBUF_IOCTL_PKTID(a)	((a)->pkt_id)
-#define BCMMSGBUF_API_SEQNUM(a)		((a)->u.seq.seq_no)
-#define BCMMSGBUF_IOCTL_XTID(a)		((a)->xt_id)
-
-#define BCMMSGBUF_SET_API_IFIDX(a, b)	(BCMMSGBUF_API_IFIDX((a)) = (b))
-#define BCMMSGBUF_SET_API_SEQNUM(a, b)	(BCMMSGBUF_API_SEQNUM((a)) = (b))
-#define BCMMSGBUF_IOCTL_SET_PKTID(a, b)	(BCMMSGBUF_IOCTL_PKTID((a)) = (b))
-#define BCMMSGBUF_IOCTL_SET_XTID(a, b)	(BCMMSGBUF_IOCTL_XTID((a)) = (b))
-
-#endif /* PCIE_API_REV1 */
-
-/* utility data structures */
-
-union addr64 {
-	struct {
-		uint32 low;
-		uint32 high;
-	};
-	struct {
-		uint32 low_addr;
-		uint32 high_addr;
-	};
-	uint64 u64;
-} DECLSPEC_ALIGN(8);
-
-typedef union addr64 bcm_addr64_t;
-
-/* IOCTL req Hdr */
-/* cmn Msg Hdr */
-typedef struct cmn_msg_hdr {
-	/** message type */
-	uint8 msg_type;
-	/** interface index this is valid for */
-	uint8 if_id;
-	/* flags */
-	uint8 flags;
-	/** sequence number */
-	uint8 epoch;
-	/** packet Identifier for the associated host buffer */
-	uint32 request_id;
-} cmn_msg_hdr_t;
-
-/** message type */
-typedef enum bcmpcie_msgtype {
-	MSG_TYPE_GEN_STATUS 		= 0x1,
-	MSG_TYPE_RING_STATUS		= 0x2,
-	MSG_TYPE_FLOW_RING_CREATE	= 0x3,
-	MSG_TYPE_FLOW_RING_CREATE_CMPLT	= 0x4,
-	MSG_TYPE_FLOW_RING_DELETE	= 0x5,
-	MSG_TYPE_FLOW_RING_DELETE_CMPLT	= 0x6,
-	MSG_TYPE_FLOW_RING_FLUSH	= 0x7,
-	MSG_TYPE_FLOW_RING_FLUSH_CMPLT	= 0x8,
-	MSG_TYPE_IOCTLPTR_REQ		= 0x9,
-	MSG_TYPE_IOCTLPTR_REQ_ACK	= 0xA,
-	MSG_TYPE_IOCTLRESP_BUF_POST	= 0xB,
-	MSG_TYPE_IOCTL_CMPLT		= 0xC,
-	MSG_TYPE_EVENT_BUF_POST		= 0xD,
-	MSG_TYPE_WL_EVENT		= 0xE,
-	MSG_TYPE_TX_POST		= 0xF,
-	MSG_TYPE_TX_STATUS		= 0x10,
-	MSG_TYPE_RXBUF_POST		= 0x11,
-	MSG_TYPE_RX_CMPLT		= 0x12,
-	MSG_TYPE_LPBK_DMAXFER 		= 0x13,
-	MSG_TYPE_LPBK_DMAXFER_CMPLT	= 0x14,
-	MSG_TYPE_FLOW_RING_RESUME	 = 0x15,
-	MSG_TYPE_FLOW_RING_RESUME_CMPLT	= 0x16,
-	MSG_TYPE_FLOW_RING_SUSPEND	= 0x17,
-	MSG_TYPE_FLOW_RING_SUSPEND_CMPLT	= 0x18,
-	MSG_TYPE_INFO_BUF_POST		= 0x19,
-	MSG_TYPE_INFO_BUF_CMPLT		= 0x1A,
-	MSG_TYPE_H2D_RING_CREATE	= 0x1B,
-	MSG_TYPE_D2H_RING_CREATE	= 0x1C,
-	MSG_TYPE_H2D_RING_CREATE_CMPLT	= 0x1D,
-	MSG_TYPE_D2H_RING_CREATE_CMPLT	= 0x1E,
-	MSG_TYPE_H2D_RING_CONFIG	= 0x1F,
-	MSG_TYPE_D2H_RING_CONFIG	= 0x20,
-	MSG_TYPE_H2D_RING_CONFIG_CMPLT	= 0x21,
-	MSG_TYPE_D2H_RING_CONFIG_CMPLT	= 0x22,
-	MSG_TYPE_H2D_MAILBOX_DATA	= 0x23,
-	MSG_TYPE_D2H_MAILBOX_DATA	= 0x24,
-
-	MSG_TYPE_API_MAX_RSVD		= 0x3F
-} bcmpcie_msg_type_t;
-
-typedef enum bcmpcie_msgtype_int {
-	MSG_TYPE_INTERNAL_USE_START	= 0x40,
-	MSG_TYPE_EVENT_PYLD		= 0x41,
-	MSG_TYPE_IOCT_PYLD		= 0x42,
-	MSG_TYPE_RX_PYLD		= 0x43,
-	MSG_TYPE_HOST_FETCH		= 0x44,
-	MSG_TYPE_LPBK_DMAXFER_PYLD	= 0x45,
-	MSG_TYPE_TXMETADATA_PYLD	= 0x46,
-	MSG_TYPE_INDX_UPDATE		= 0x47
-} bcmpcie_msgtype_int_t;
-
-typedef enum bcmpcie_msgtype_u {
-	MSG_TYPE_TX_BATCH_POST		= 0x80,
-	MSG_TYPE_IOCTL_REQ		= 0x81,
-	MSG_TYPE_HOST_EVNT		= 0x82, /* console related */
-	MSG_TYPE_LOOPBACK		= 0x83
-} bcmpcie_msgtype_u_t;
-
-/**
- * D2H ring host wakeup soft doorbell, override the PCIE doorbell.
- * Host configures an <32bit address,value> tuple, and dongle uses SBTOPCIE
- * Transl0 to write specified value to host address.
- *
- * Use case: 32bit Address mapped to HW Accelerator Core/Thread Wakeup Register
- * and value is Core/Thread context. Host will ensure routing the 32bit address
- * offerred to PCIE to the mapped register.
- *
- * D2H_RING_CONFIG_SUBTYPE_SOFT_DOORBELL
- */
-typedef struct bcmpcie_soft_doorbell {
-	uint32	value;  /* host defined value to be written, eg HW threadid */
-	bcm_addr64_t haddr; /* host address, eg thread wakeup register address */
-	uint16	items;  /* interrupt coalescing: item count before wakeup */
-	uint16	msecs;  /* interrupt coalescing: timeout in millisecs */
-} bcmpcie_soft_doorbell_t;
-
-
-/* if_id */
-#define BCMPCIE_CMNHDR_IFIDX_PHYINTF_SHFT	5
-#define BCMPCIE_CMNHDR_IFIDX_PHYINTF_MAX	0x7
-#define BCMPCIE_CMNHDR_IFIDX_PHYINTF_MASK	\
-	(BCMPCIE_CMNHDR_IFIDX_PHYINTF_MAX << BCMPCIE_CMNHDR_IFIDX_PHYINTF_SHFT)
-#define BCMPCIE_CMNHDR_IFIDX_VIRTINTF_SHFT	0
-#define BCMPCIE_CMNHDR_IFIDX_VIRTINTF_MAX	0x1F
-#define BCMPCIE_CMNHDR_IFIDX_VIRTINTF_MASK	\
-	(BCMPCIE_CMNHDR_IFIDX_PHYINTF_MAX << BCMPCIE_CMNHDR_IFIDX_PHYINTF_SHFT)
-
-/* flags */
-#define BCMPCIE_CMNHDR_FLAGS_DMA_R_IDX		0x1
-#define BCMPCIE_CMNHDR_FLAGS_DMA_R_IDX_INTR	0x2
-#define BCMPCIE_CMNHDR_FLAGS_PHASE_BIT		0x80
-
-
-/* IOCTL request message */
-typedef struct ioctl_req_msg {
-	/** common message header */
-	cmn_msg_hdr_t 	cmn_hdr;
-	/** ioctl command type */
-	uint32		cmd;
-	/** ioctl transaction ID, to pair with a ioctl response */
-	uint16		trans_id;
-	/** input arguments buffer len */
-	uint16		input_buf_len;
-	/** expected output len */
-	uint16		output_buf_len;
-	/** to align the host address on 8 byte boundary */
-	uint16		rsvd[3];
-	/** always align on 8 byte boundary */
-	bcm_addr64_t	host_input_buf_addr;
-	/* rsvd */
-	uint32		rsvd1[2];
-} ioctl_req_msg_t;
-
-/** buffer post messages for device to use to return IOCTL responses, Events */
-typedef struct ioctl_resp_evt_buf_post_msg {
-	/** common message header */
-	cmn_msg_hdr_t	cmn_hdr;
-	/** length of the host buffer supplied */
-	uint16		host_buf_len;
-	/** to align the host address on 8 byte boundary */
-	uint16		reserved[3];
-	/** always align on 8 byte boundary */
-	bcm_addr64_t	host_buf_addr;
-	uint32		rsvd[4];
-} ioctl_resp_evt_buf_post_msg_t;
-
-
-typedef struct pcie_dma_xfer_params {
-	/** common message header */
-	cmn_msg_hdr_t	cmn_hdr;
-
-	/** always align on 8 byte boundary */
-	bcm_addr64_t	host_input_buf_addr;
-
-	/** always align on 8 byte boundary */
-	bcm_addr64_t	host_ouput_buf_addr;
-
-	/** length of transfer */
-	uint32		xfer_len;
-	/** delay before doing the src txfer */
-	uint32		srcdelay;
-	/** delay before doing the dest txfer */
-	uint32		destdelay;
-	uint32		rsvd;
-} pcie_dma_xfer_params_t;
-
-/** Complete msgbuf hdr for flow ring update from host to dongle */
-typedef struct tx_flowring_create_request {
-	cmn_msg_hdr_t   msg;
-	uint8	da[ETHER_ADDR_LEN];
-	uint8	sa[ETHER_ADDR_LEN];
-	uint8	tid;
-	uint8 	if_flags;
-	uint16	flow_ring_id;
-	uint8 	tc;
-	uint8	priority;
-	uint16 	int_vector;
-	uint16	max_items;
-	uint16	len_item;
-	bcm_addr64_t flow_ring_ptr;
-} tx_flowring_create_request_t;
-
-typedef struct tx_flowring_delete_request {
-	cmn_msg_hdr_t   msg;
-	uint16	flow_ring_id;
-	uint16 	reason;
-	uint32	rsvd[7];
-} tx_flowring_delete_request_t;
-
-typedef struct tx_flowring_flush_request {
-	cmn_msg_hdr_t   msg;
-	uint16	flow_ring_id;
-	uint16 	reason;
-	uint32	rsvd[7];
-} tx_flowring_flush_request_t;
-
-/** Subtypes for ring_config_req control message */
-typedef enum ring_config_subtype {
-	/** Default D2H PCIE doorbell override using ring_config_req msg */
-	D2H_RING_CONFIG_SUBTYPE_SOFT_DOORBELL = 1, /* Software doorbell */
-	D2H_RING_CONFIG_SUBTYPE_MSI_DOORBELL = 2   /* MSI configuration */
-} ring_config_subtype_t;
-
-typedef struct ring_config_req {
-	cmn_msg_hdr_t	msg;
-	uint16	subtype;
-	uint16	ring_id;
-	uint32	rsvd;
-	union {
-		uint32  data[6];
-		/** D2H_RING_CONFIG_SUBTYPE_SOFT_DOORBELL */
-		bcmpcie_soft_doorbell_t soft_doorbell;
-	};
-} ring_config_req_t;
-
-typedef union ctrl_submit_item {
-	ioctl_req_msg_t			ioctl_req;
-	ioctl_resp_evt_buf_post_msg_t	resp_buf_post;
-	pcie_dma_xfer_params_t		dma_xfer;
-	tx_flowring_create_request_t	flow_create;
-	tx_flowring_delete_request_t	flow_delete;
-	tx_flowring_flush_request_t	flow_flush;
-	ring_config_req_t		ring_config_req;
-	unsigned char			check[H2DRING_CTRL_SUB_ITEMSIZE];
-} ctrl_submit_item_t;
-
-/** Control Completion messages (20 bytes) */
-typedef struct compl_msg_hdr {
-	/** status for the completion */
-	int16	status;
-	/** submisison flow ring id which generated this status */
-	uint16	flow_ring_id;
-} compl_msg_hdr_t;
-
-/** XOR checksum or a magic number to audit DMA done */
-typedef uint32 dma_done_t;
-
-/* completion header status codes */
-#define	BCMPCIE_SUCCESS			0
-#define BCMPCIE_NOTFOUND		1
-#define BCMPCIE_NOMEM			2
-#define BCMPCIE_BADOPTION		3
-#define BCMPCIE_RING_IN_USE		4
-#define BCMPCIE_RING_ID_INVALID		5
-#define BCMPCIE_PKT_FLUSH		6
-#define BCMPCIE_NO_EVENT_BUF		7
-#define BCMPCIE_NO_RX_BUF		8
-#define BCMPCIE_NO_IOCTLRESP_BUF	9
-#define BCMPCIE_MAX_IOCTLRESP_BUF	10
-#define BCMPCIE_MAX_EVENT_BUF		11
-
-/** IOCTL completion response */
-typedef struct ioctl_compl_resp_msg {
-	/** common message header */
-	cmn_msg_hdr_t		cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t		compl_hdr;
-	/** response buffer len where a host buffer is involved */
-	uint16			resp_len;
-	/** transaction id to pair with a request */
-	uint16			trans_id;
-	/** cmd id */
-	uint32			cmd;
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t		marker;
-} ioctl_comp_resp_msg_t;
-
-/** IOCTL request acknowledgement */
-typedef struct ioctl_req_ack_msg {
-	/** common message header */
-	cmn_msg_hdr_t		cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t 	compl_hdr;
-	/** cmd id */
-	uint32			cmd;
-	uint32			rsvd;
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t		marker;
-} ioctl_req_ack_msg_t;
-
-/** WL event message: send from device to host */
-typedef struct wlevent_req_msg {
-	/** common message header */
-	cmn_msg_hdr_t		cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t		compl_hdr;
-	/** event data len valid with the event buffer */
-	uint16			event_data_len;
-	/** sequence number */
-	uint16			seqnum;
-	/** rsvd	*/
-	uint32			rsvd;
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t		marker;
-} wlevent_req_msg_t;
-
-/** dma xfer complete message */
-typedef struct pcie_dmaxfer_cmplt {
-	/** common message header */
-	cmn_msg_hdr_t		cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t		compl_hdr;
-	uint32			rsvd[2];
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t		marker;
-} pcie_dmaxfer_cmplt_t;
-
-/** general status message */
-typedef struct pcie_gen_status {
-	/** common message header */
-	cmn_msg_hdr_t		cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t		compl_hdr;
-	uint32			rsvd[2];
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t		marker;
-} pcie_gen_status_t;
-
-/** ring status message */
-typedef struct pcie_ring_status {
-	/** common message header */
-	cmn_msg_hdr_t		cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t		compl_hdr;
-	/** message which firmware couldn't decode */
-	uint16			write_idx;
-	uint16			rsvd[3];
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t		marker;
-} pcie_ring_status_t;
-
-typedef struct tx_flowring_create_response {
-	cmn_msg_hdr_t		msg;
-	compl_msg_hdr_t 	cmplt;
-	uint32			rsvd[2];
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t		marker;
-} tx_flowring_create_response_t;
-
-typedef struct tx_flowring_delete_response {
-	cmn_msg_hdr_t		msg;
-	compl_msg_hdr_t 	cmplt;
-	uint32			rsvd[2];
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t		marker;
-} tx_flowring_delete_response_t;
-
-typedef struct tx_flowring_flush_response {
-	cmn_msg_hdr_t		msg;
-	compl_msg_hdr_t 	cmplt;
-	uint32			rsvd[2];
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t		marker;
-} tx_flowring_flush_response_t;
-
-/** Common layout of all d2h control messages */
-typedef struct ctrl_compl_msg {
-	/** common message header */
-	cmn_msg_hdr_t       cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t     compl_hdr;
-	uint32          rsvd[2];
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t      marker;
-} ctrl_compl_msg_t;
-
-typedef struct ring_config_resp {
-	/** common message header */
-	cmn_msg_hdr_t       cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t     compl_hdr;
-	uint32          rsvd[2];
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t      marker;
-} ring_config_resp_t;
-
-typedef union ctrl_completion_item {
-	ioctl_comp_resp_msg_t		ioctl_resp;
-	wlevent_req_msg_t		event;
-	ioctl_req_ack_msg_t		ioct_ack;
-	pcie_dmaxfer_cmplt_t		pcie_xfer_cmplt;
-	pcie_gen_status_t		pcie_gen_status;
-	pcie_ring_status_t		pcie_ring_status;
-	tx_flowring_create_response_t	txfl_create_resp;
-	tx_flowring_delete_response_t	txfl_delete_resp;
-	tx_flowring_flush_response_t	txfl_flush_resp;
-	ctrl_compl_msg_t		ctrl_compl;
-	ring_config_resp_t		ring_config_resp;
-	unsigned char		check[D2HRING_CTRL_CMPLT_ITEMSIZE];
-} ctrl_completion_item_t;
-
-/** H2D Rxpost ring work items */
-typedef struct host_rxbuf_post {
-	/** common message header */
-	cmn_msg_hdr_t   cmn_hdr;
-	/** provided meta data buffer len */
-	uint16		metadata_buf_len;
-	/** provided data buffer len to receive data */
-	uint16		data_buf_len;
-	/** alignment to make the host buffers start on 8 byte boundary */
-	uint32		rsvd;
-	/** provided meta data buffer */
-	bcm_addr64_t	metadata_buf_addr;
-	/** provided data buffer to receive data */
-	bcm_addr64_t	data_buf_addr;
-} host_rxbuf_post_t;
-
-typedef union rxbuf_submit_item {
-	host_rxbuf_post_t	rxpost;
-	unsigned char		check[H2DRING_RXPOST_ITEMSIZE];
-} rxbuf_submit_item_t;
-
-
-/** D2H Rxcompletion ring work items */
-typedef struct host_rxbuf_cmpl {
-	/** common message header */
-	cmn_msg_hdr_t	cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t	compl_hdr;
-	/**  filled up meta data len */
-	uint16		metadata_len;
-	/** filled up buffer len to receive data */
-	uint16		data_len;
-	/** offset in the host rx buffer where the data starts */
-	uint16		data_offset;
-	/** offset in the host rx buffer where the data starts */
-	uint16		flags;
-	/** rx status */
-	uint32		rx_status_0;
-	uint32		rx_status_1;
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t	marker;
-} host_rxbuf_cmpl_t;
-
-typedef union rxbuf_complete_item {
-	host_rxbuf_cmpl_t	rxcmpl;
-	unsigned char		check[D2HRING_RXCMPLT_ITEMSIZE];
-} rxbuf_complete_item_t;
-
-
-typedef struct host_txbuf_post {
-	/** common message header */
-	cmn_msg_hdr_t   cmn_hdr;
-	/** eth header */
-	uint8		txhdr[ETHER_HDR_LEN];
-	/** flags */
-	uint8		flags;
-	/** number of segments */
-	uint8		seg_cnt;
-
-	/** provided meta data buffer for txstatus */
-	bcm_addr64_t	metadata_buf_addr;
-	/** provided data buffer to receive data */
-	bcm_addr64_t	data_buf_addr;
-	/** provided meta data buffer len */
-	uint16		metadata_buf_len;
-	/** provided data buffer len to receive data */
-	uint16		data_len;
-	/** XOR checksum or a magic number to audit DMA done */
-	dma_done_t	marker;
-} host_txbuf_post_t;
-
-#define BCMPCIE_PKT_FLAGS_FRAME_802_3	0x01
-#define BCMPCIE_PKT_FLAGS_FRAME_802_11	0x02
-
-#define BCMPCIE_PKT_FLAGS_FRAME_EXEMPT_MASK	0x03	/* Exempt uses 2 bits */
-#define BCMPCIE_PKT_FLAGS_FRAME_EXEMPT_SHIFT	0x02	/* needs to be shifted past other bits */
-
-
-#define BCMPCIE_PKT_FLAGS_PRIO_SHIFT		5
-#define BCMPCIE_PKT_FLAGS_PRIO_MASK		(7 << BCMPCIE_PKT_FLAGS_PRIO_SHIFT)
-
-/* These are added to fix up compile issues */
-#define BCMPCIE_TXPOST_FLAGS_FRAME_802_3	BCMPCIE_PKT_FLAGS_FRAME_802_3
-#define BCMPCIE_TXPOST_FLAGS_FRAME_802_11	BCMPCIE_PKT_FLAGS_FRAME_802_11
-#define BCMPCIE_TXPOST_FLAGS_PRIO_SHIFT		BCMPCIE_PKT_FLAGS_PRIO_SHIFT
-#define BCMPCIE_TXPOST_FLAGS_PRIO_MASK		BCMPCIE_PKT_FLAGS_PRIO_MASK
-
-/** H2D Txpost ring work items */
-typedef union txbuf_submit_item {
-	host_txbuf_post_t	txpost;
-	unsigned char		check[H2DRING_TXPOST_ITEMSIZE];
-} txbuf_submit_item_t;
-
-/** D2H Txcompletion ring work items */
-typedef struct host_txbuf_cmpl {
-	/** common message header */
-	cmn_msg_hdr_t	cmn_hdr;
-	/** completion message header */
-	compl_msg_hdr_t	compl_hdr;
-	union {
-		struct {
-			/** provided meta data len */
-			uint16	metadata_len;
-			/** WLAN side txstatus */
-			uint16	tx_status;
-		};
-		/** XOR checksum or a magic number to audit DMA done */
-		dma_done_t	marker;
-	};
-} host_txbuf_cmpl_t;
-
-typedef union txbuf_complete_item {
-	host_txbuf_cmpl_t	txcmpl;
-	unsigned char		check[D2HRING_TXCMPLT_ITEMSIZE];
-} txbuf_complete_item_t;
-
-#define BCMPCIE_D2H_METADATA_HDRLEN	4
-#define BCMPCIE_D2H_METADATA_MINLEN	(BCMPCIE_D2H_METADATA_HDRLEN + 4)
-
-/** ret buf struct */
-typedef struct ret_buf_ptr {
-	uint32 low_addr;
-	uint32 high_addr;
-} ret_buf_t;
-
-
-#ifdef PCIE_API_REV1
-
-/* ioctl specific hdr */
-typedef struct ioctl_hdr {
-	uint16 		cmd;
-	uint16		retbuf_len;
-	uint32		cmd_id;
-} ioctl_hdr_t;
-
-typedef struct ioctlptr_hdr {
-	uint16 		cmd;
-	uint16		retbuf_len;
-	uint16 		buflen;
-	uint16		rsvd;
-	uint32		cmd_id;
-} ioctlptr_hdr_t;
-
-#else /* PCIE_API_REV1 */
-
-typedef struct ioctl_req_hdr {
-	uint32		pkt_id;	/**< Packet ID */
-	uint32 		cmd;	/**< IOCTL ID */
-	uint16		retbuf_len;
-	uint16 		buflen;
-	uint16		xt_id;	/**< transaction ID */
-	uint16		rsvd[1];
-} ioctl_req_hdr_t;
-
-#endif /* PCIE_API_REV1 */
-
-
-/** Complete msgbuf hdr for ioctl from host to dongle */
-typedef struct ioct_reqst_hdr {
-	cmn_msg_hdr_t msg;
-#ifdef PCIE_API_REV1
-	ioctl_hdr_t ioct_hdr;
-#else
-	ioctl_req_hdr_t ioct_hdr;
-#endif
-	ret_buf_t ret_buf;
-} ioct_reqst_hdr_t;
-
-typedef struct ioctptr_reqst_hdr {
-	cmn_msg_hdr_t msg;
-#ifdef PCIE_API_REV1
-	ioctlptr_hdr_t ioct_hdr;
-#else
-	ioctl_req_hdr_t ioct_hdr;
-#endif
-	ret_buf_t ret_buf;
-	ret_buf_t ioct_buf;
-} ioctptr_reqst_hdr_t;
-
-/** ioctl response header */
-typedef struct ioct_resp_hdr {
-	cmn_msg_hdr_t   msg;
-#ifdef PCIE_API_REV1
-	uint32	cmd_id;
-#else
-	uint32	pkt_id;
-#endif
-	uint32	status;
-	uint32	ret_len;
-	uint32  inline_data;
-#ifdef PCIE_API_REV1
-#else
-	uint16	xt_id;	/**< transaction ID */
-	uint16	rsvd[1];
-#endif
-} ioct_resp_hdr_t;
-
-/* ioct resp header used in dongle */
-/* ret buf hdr will be stripped off inside dongle itself */
-typedef struct msgbuf_ioctl_resp {
-	ioct_resp_hdr_t	ioct_hdr;
-	ret_buf_t	ret_buf;	/**< ret buf pointers */
-} msgbuf_ioct_resp_t;
-
-/** WL event hdr info */
-typedef struct wl_event_hdr {
-	cmn_msg_hdr_t   msg;
-	uint16 event;
-	uint8 flags;
-	uint8 rsvd;
-	uint16 retbuf_len;
-	uint16 rsvd1;
-	uint32 rxbufid;
-} wl_event_hdr_t;
-
-#define TXDESCR_FLOWID_PCIELPBK_1	0xFF
-#define TXDESCR_FLOWID_PCIELPBK_2	0xFE
-
-typedef struct txbatch_lenptr_tup {
-	uint32 pktid;
-	uint16 pktlen;
-	uint16 rsvd;
-	ret_buf_t	ret_buf;	/**< ret buf pointers */
-} txbatch_lenptr_tup_t;
-
-typedef struct txbatch_cmn_msghdr {
-	cmn_msg_hdr_t   msg;
-	uint8 priority;
-	uint8 hdrlen;
-	uint8 pktcnt;
-	uint8 flowid;
-	uint8 txhdr[ETHER_HDR_LEN];
-	uint16 rsvd;
-} txbatch_cmn_msghdr_t;
-
-typedef struct txbatch_msghdr {
-	txbatch_cmn_msghdr_t txcmn;
-	txbatch_lenptr_tup_t tx_tup[0]; /**< Based on packet count */
-} txbatch_msghdr_t;
-
-/* TX desc posting header */
-typedef struct tx_lenptr_tup {
-	uint16 pktlen;
-	uint16 rsvd;
-	ret_buf_t	ret_buf;	/**< ret buf pointers */
-} tx_lenptr_tup_t;
-
-typedef struct txdescr_cmn_msghdr {
-	cmn_msg_hdr_t   msg;
-	uint8 priority;
-	uint8 hdrlen;
-	uint8 descrcnt;
-	uint8 flowid;
-	uint32 pktid;
-} txdescr_cmn_msghdr_t;
-
-typedef struct txdescr_msghdr {
-	txdescr_cmn_msghdr_t txcmn;
-	uint8 txhdr[ETHER_HDR_LEN];
-	uint16 rsvd;
-	tx_lenptr_tup_t tx_tup[0];	/**< Based on descriptor count */
-} txdescr_msghdr_t;
-
-/** Tx status header info */
-typedef struct txstatus_hdr {
-	cmn_msg_hdr_t   msg;
-	uint32 pktid;
-} txstatus_hdr_t;
-
-/** RX bufid-len-ptr tuple */
-typedef struct rx_lenptr_tup {
-	uint32 rxbufid;
-	uint16 len;
-	uint16 rsvd2;
-	ret_buf_t	ret_buf;	/**< ret buf pointers */
-} rx_lenptr_tup_t;
-
-/** Rx descr Post hdr info */
-typedef struct rxdesc_msghdr {
-	cmn_msg_hdr_t   msg;
-	uint16 rsvd0;
-	uint8 rsvd1;
-	uint8 descnt;
-	rx_lenptr_tup_t rx_tup[0];
-} rxdesc_msghdr_t;
-
-/** RX complete tuples */
-typedef struct rxcmplt_tup {
-	uint16 retbuf_len;
-	uint16 data_offset;
-	uint32 rxstatus0;
-	uint32 rxstatus1;
-	uint32 rxbufid;
-} rxcmplt_tup_t;
-
-/** RX complete messge hdr */
-typedef struct rxcmplt_hdr {
-	cmn_msg_hdr_t   msg;
-	uint16 rsvd0;
-	uint16 rxcmpltcnt;
-	rxcmplt_tup_t rx_tup[0];
-} rxcmplt_hdr_t;
-
-typedef struct hostevent_hdr {
-	cmn_msg_hdr_t   msg;
-	uint32 evnt_pyld;
-} hostevent_hdr_t;
-
-typedef struct dma_xfer_params {
-	uint32 src_physaddr_hi;
-	uint32 src_physaddr_lo;
-	uint32 dest_physaddr_hi;
-	uint32 dest_physaddr_lo;
-	uint32 len;
-	uint32 srcdelay;
-	uint32 destdelay;
-} dma_xfer_params_t;
-
-enum {
-	HOST_EVENT_CONS_CMD = 1
-};
-
-/* defines for flags */
-#define MSGBUF_IOC_ACTION_MASK 0x1
-
-#define MAX_SUSPEND_REQ 15
-
-typedef struct tx_idle_flowring_suspend_request {
-	cmn_msg_hdr_t	msg;
-	uint16	ring_id[MAX_SUSPEND_REQ];      /**< ring Id's */
-	uint16	num;    /**< number of flowid's to suspend */
-} tx_idle_flowring_suspend_request_t;
-
-typedef struct tx_idle_flowring_suspend_response {
-	cmn_msg_hdr_t	msg;
-	compl_msg_hdr_t	cmplt;
-	uint32			rsvd[2];
-	dma_done_t		marker;
-} tx_idle_flowring_suspend_response_t;
-
-typedef struct tx_idle_flowring_resume_request {
-	cmn_msg_hdr_t	msg;
-	uint16	flow_ring_id;
-	uint16	reason;
-	uint32	rsvd[7];
-} tx_idle_flowring_resume_request_t;
-
-typedef struct tx_idle_flowring_resume_response {
-	cmn_msg_hdr_t	msg;
-	compl_msg_hdr_t	cmplt;
-	uint32			rsvd[2];
-	dma_done_t		marker;
-} tx_idle_flowring_resume_response_t;
-
-#endif /* _bcmmsgbuf_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmnvram.h b/drivers/net/wireless/bcmdhd/include/bcmnvram.h
deleted file mode 100644
index e3ba9b4..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmnvram.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * NVRAM variable manipulation
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmnvram.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef _bcmnvram_h_
-#define _bcmnvram_h_
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-#include <typedefs.h>
-#include <bcmdefs.h>
-
-struct nvram_header {
-	uint32 magic;
-	uint32 len;
-	uint32 crc_ver_init;	/* 0:7 crc, 8:15 ver, 16:31 sdram_init */
-	uint32 config_refresh;	/* 0:15 sdram_config, 16:31 sdram_refresh */
-	uint32 config_ncdl;	/* ncdl values for memc */
-};
-
-struct nvram_tuple {
-	char *name;
-	char *value;
-	struct nvram_tuple *next;
-};
-
-/*
- * Get default value for an NVRAM variable
- */
-extern char *nvram_default_get(const char *name);
-/*
- * validate/restore all per-interface related variables
- */
-extern void nvram_validate_all(char *prefix, bool restore);
-
-/*
- * restore specific per-interface variable
- */
-extern void nvram_restore_var(char *prefix, char *name);
-
-/*
- * Initialize NVRAM access. May be unnecessary or undefined on certain
- * platforms.
- */
-extern int nvram_init(void *sih);
-extern int nvram_deinit(void *sih);
-
-
-/*
- * Append a chunk of nvram variables to the global list
- */
-extern int nvram_append(void *si, char *vars, uint varsz);
-
-extern void nvram_get_global_vars(char **varlst, uint *varsz);
-
-
-/*
- * Check for reset button press for restoring factory defaults.
- */
-extern int nvram_reset(void *sih);
-
-/*
- * Disable NVRAM access. May be unnecessary or undefined on certain
- * platforms.
- */
-extern void nvram_exit(void *sih);
-
-/*
- * Get the value of an NVRAM variable. The pointer returned may be
- * invalid after a set.
- * @param	name	name of variable to get
- * @return	value of variable or NULL if undefined
- */
-extern char * nvram_get(const char *name);
-
-/*
- * Get the value of an NVRAM variable. The pointer returned may be
- * invalid after a set.
- * @param	name	name of variable to get
- * @param	bit	bit value to get
- * @return	value of variable or NULL if undefined
- */
-extern char * nvram_get_bitflag(const char *name, const int bit);
-
-/*
- * Read the reset GPIO value from the nvram and set the GPIO
- * as input
- */
-extern int nvram_resetgpio_init(void *sih);
-
-/*
- * Get the value of an NVRAM variable.
- * @param	name	name of variable to get
- * @return	value of variable or NUL if undefined
- */
-static INLINE char *
-nvram_safe_get(const char *name)
-{
-	char *p = nvram_get(name);
-	return p ? p : "";
-}
-
-/*
- * Match an NVRAM variable.
- * @param	name	name of variable to match
- * @param	match	value to compare against value of variable
- * @return	TRUE if variable is defined and its value is string equal
- *		to match or FALSE otherwise
- */
-static INLINE int
-nvram_match(const char *name, const char *match)
-{
-	const char *value = nvram_get(name);
-	return (value && !strcmp(value, match));
-}
-
-/*
- * Match an NVRAM variable.
- * @param	name	name of variable to match
- * @param	bit	bit value to get
- * @param	match	value to compare against value of variable
- * @return	TRUE if variable is defined and its value is string equal
- *		to match or FALSE otherwise
- */
-static INLINE int
-nvram_match_bitflag(const char *name, const int bit, const char *match)
-{
-	const char *value = nvram_get_bitflag(name, bit);
-	return (value && !strcmp(value, match));
-}
-
-/*
- * Inversely match an NVRAM variable.
- * @param	name	name of variable to match
- * @param	match	value to compare against value of variable
- * @return	TRUE if variable is defined and its value is not string
- *		equal to invmatch or FALSE otherwise
- */
-static INLINE int
-nvram_invmatch(const char *name, const char *invmatch)
-{
-	const char *value = nvram_get(name);
-	return (value && strcmp(value, invmatch));
-}
-
-/*
- * Set the value of an NVRAM variable. The name and value strings are
- * copied into private storage. Pointers to previously set values
- * may become invalid. The new value may be immediately
- * retrieved but will not be permanently stored until a commit.
- * @param	name	name of variable to set
- * @param	value	value of variable
- * @return	0 on success and errno on failure
- */
-extern int nvram_set(const char *name, const char *value);
-
-/*
- * Set the value of an NVRAM variable. The name and value strings are
- * copied into private storage. Pointers to previously set values
- * may become invalid. The new value may be immediately
- * retrieved but will not be permanently stored until a commit.
- * @param	name	name of variable to set
- * @param	bit	bit value to set
- * @param	value	value of variable
- * @return	0 on success and errno on failure
- */
-extern int nvram_set_bitflag(const char *name, const int bit, const int value);
-/*
- * Unset an NVRAM variable. Pointers to previously set values
- * remain valid until a set.
- * @param	name	name of variable to unset
- * @return	0 on success and errno on failure
- * NOTE: use nvram_commit to commit this change to flash.
- */
-extern int nvram_unset(const char *name);
-
-/*
- * Commit NVRAM variables to permanent storage. All pointers to values
- * may be invalid after a commit.
- * NVRAM values are undefined after a commit.
- * @param   nvram_corrupt    true to corrupt nvram, false otherwise.
- * @return	0 on success and errno on failure
- */
-extern int nvram_commit_internal(bool nvram_corrupt);
-
-/*
- * Commit NVRAM variables to permanent storage. All pointers to values
- * may be invalid after a commit.
- * NVRAM values are undefined after a commit.
- * @return	0 on success and errno on failure
- */
-extern int nvram_commit(void);
-
-/*
- * Get all NVRAM variables (format name=value\0 ... \0\0).
- * @param	buf	buffer to store variables
- * @param	count	size of buffer in bytes
- * @return	0 on success and errno on failure
- */
-extern int nvram_getall(char *nvram_buf, int count);
-
-/*
- * returns the crc value of the nvram
- * @param	nvh	nvram header pointer
- */
-uint8 nvram_calc_crc(struct nvram_header * nvh);
-
-extern int nvram_space;
-#endif /* _LANGUAGE_ASSEMBLY */
-
-/* The NVRAM version number stored as an NVRAM variable */
-#define NVRAM_SOFTWARE_VERSION	"1"
-
-#define NVRAM_MAGIC		0x48534C46	/* 'FLSH' */
-#define NVRAM_CLEAR_MAGIC	0x0
-#define NVRAM_INVALID_MAGIC	0xFFFFFFFF
-#define NVRAM_VERSION		1
-#define NVRAM_HEADER_SIZE	20
-/* This definition is for precommit staging, and will be removed */
-#define NVRAM_SPACE		0x8000
-/* For CFE builds this gets passed in thru the makefile */
-#ifndef MAX_NVRAM_SPACE
-#define MAX_NVRAM_SPACE		0x10000
-#endif
-#define DEF_NVRAM_SPACE		0x8000
-#define ROM_ENVRAM_SPACE	0x1000
-#define NVRAM_LZMA_MAGIC	0x4c5a4d41	/* 'LZMA' */
-
-#define NVRAM_MAX_VALUE_LEN 255
-#define NVRAM_MAX_PARAM_LEN 64
-
-#define NVRAM_CRC_START_POSITION	9 /* magic, len, crc8 to be skipped */
-#define NVRAM_CRC_VER_MASK	0xffffff00 /* for crc_ver_init */
-
-/* Offsets to embedded nvram area */
-#define NVRAM_START_COMPRESSED	0x400
-#define NVRAM_START		0x1000
-
-#define BCM_JUMBO_NVRAM_DELIMIT '\n'
-#define BCM_JUMBO_START "Broadcom Jumbo Nvram file"
-
-
-#if (defined(FAILSAFE_UPGRADE) || defined(CONFIG_FAILSAFE_UPGRADE) || \
-	defined(__CONFIG_FAILSAFE_UPGRADE_SUPPORT__))
-#define IMAGE_SIZE "image_size"
-#define BOOTPARTITION "bootpartition"
-#define IMAGE_BOOT BOOTPARTITION
-#define PARTIALBOOTS "partialboots"
-#define MAXPARTIALBOOTS "maxpartialboots"
-#define IMAGE_1ST_FLASH_TRX "flash0.trx"
-#define IMAGE_1ST_FLASH_OS "flash0.os"
-#define IMAGE_2ND_FLASH_TRX "flash0.trx2"
-#define IMAGE_2ND_FLASH_OS "flash0.os2"
-#define IMAGE_FIRST_OFFSET "image_first_offset"
-#define IMAGE_SECOND_OFFSET "image_second_offset"
-#define LINUX_FIRST "linux"
-#define LINUX_SECOND "linux2"
-#endif
-
-#if (defined(DUAL_IMAGE) || defined(CONFIG_DUAL_IMAGE) || \
-	defined(__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__))
-/* Shared by all: CFE, Linux Kernel, and Ap */
-#define IMAGE_BOOT "image_boot"
-#define BOOTPARTITION IMAGE_BOOT
-/* CFE variables */
-#define IMAGE_1ST_FLASH_TRX "flash0.trx"
-#define IMAGE_1ST_FLASH_OS "flash0.os"
-#define IMAGE_2ND_FLASH_TRX "flash0.trx2"
-#define IMAGE_2ND_FLASH_OS "flash0.os2"
-#define IMAGE_SIZE "image_size"
-
-/* CFE and Linux Kernel shared variables */
-#define IMAGE_FIRST_OFFSET "image_first_offset"
-#define IMAGE_SECOND_OFFSET "image_second_offset"
-
-/* Linux application variables */
-#define LINUX_FIRST "linux"
-#define LINUX_SECOND "linux2"
-#define POLICY_TOGGLE "toggle"
-#define LINUX_PART_TO_FLASH "linux_to_flash"
-#define LINUX_FLASH_POLICY "linux_flash_policy"
-
-#endif /* defined(DUAL_IMAGE||CONFIG_DUAL_IMAGE)||__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__ */
-
-#endif /* _bcmnvram_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmpcie.h b/drivers/net/wireless/bcmdhd/include/bcmpcie.h
deleted file mode 100644
index 0c15055..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmpcie.h
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Broadcom PCIE
- * Software-specific definitions shared between device and host side
- * Explains the shared area between host and dongle
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmpcie.h 604490 2015-12-07 15:48:45Z $
- */
-
-
-#ifndef	_bcmpcie_h_
-#define	_bcmpcie_h_
-
-#include <bcmutils.h>
-
-#define ADDR_64(x)			(x.addr)
-#define HIGH_ADDR_32(x)     ((uint32) (((sh_addr_t) x).high_addr))
-#define LOW_ADDR_32(x)      ((uint32) (((sh_addr_t) x).low_addr))
-
-typedef struct {
-	uint32 low_addr;
-	uint32 high_addr;
-} sh_addr_t;
-
-
-/* May be overridden by 43xxxxx-roml.mk */
-#if !defined(BCMPCIE_MAX_TX_FLOWS)
-#define BCMPCIE_MAX_TX_FLOWS	40
-#endif /* ! BCMPCIE_MAX_TX_FLOWS */
-
-/**
- * Feature flags enabled in dongle. Advertised by dongle to DHD via the PCIe Shared structure that
- * is located in device memory.
- */
-#define PCIE_SHARED_VERSION		0x00005
-#define PCIE_SHARED_VERSION_MASK	0x000FF
-#define PCIE_SHARED_ASSERT_BUILT	0x00100
-#define PCIE_SHARED_ASSERT		0x00200
-#define PCIE_SHARED_TRAP		0x00400
-#define PCIE_SHARED_IN_BRPT		0x00800
-#define PCIE_SHARED_SET_BRPT		0x01000
-#define PCIE_SHARED_PENDING_BRPT	0x02000
-#define PCIE_SHARED_TXPUSH_SPRT		0x04000
-#define PCIE_SHARED_EVT_SEQNUM		0x08000
-#define PCIE_SHARED_DMA_INDEX		0x10000
-
-/**
- * There are host types where a device interrupt can 'race ahead' of data written by the device into
- * host memory. The dongle can avoid this condition using a variety of techniques (read barrier,
- * using PCIe Message Signalled Interrupts, or by using the PCIE_DMA_INDEX feature). Unfortunately
- * these techniques have drawbacks on router platforms. For these platforms, it was decided to not
- * avoid the condition, but to detect the condition instead and act on it.
- * D2H M2M DMA Complete Sync mechanism: Modulo-253-SeqNum or XORCSUM
- */
-#define PCIE_SHARED_D2H_SYNC_SEQNUM     0x20000
-#define PCIE_SHARED_D2H_SYNC_XORCSUM    0x40000
-#define PCIE_SHARED_D2H_SYNC_MODE_MASK \
-	(PCIE_SHARED_D2H_SYNC_SEQNUM | PCIE_SHARED_D2H_SYNC_XORCSUM)
-#define PCIE_SHARED_IDLE_FLOW_RING		0x80000
-#define PCIE_SHARED_2BYTE_INDICES       0x100000
-
-
-#define PCIE_SHARED_D2H_MAGIC		0xFEDCBA09
-#define PCIE_SHARED_H2D_MAGIC		0x12345678
-
-/**
- * Message rings convey messages between host and device. They are unidirectional, and are located
- * in host memory.
- *
- * This is the minimal set of message rings, known as 'common message rings':
- */
-#define BCMPCIE_H2D_MSGRING_CONTROL_SUBMIT		0
-#define BCMPCIE_H2D_MSGRING_RXPOST_SUBMIT		1
-#define BCMPCIE_D2H_MSGRING_CONTROL_COMPLETE		2
-#define BCMPCIE_D2H_MSGRING_TX_COMPLETE			3
-#define BCMPCIE_D2H_MSGRING_RX_COMPLETE			4
-#define BCMPCIE_COMMON_MSGRING_MAX_ID			4
-
-#define BCMPCIE_H2D_COMMON_MSGRINGS			2
-#define BCMPCIE_D2H_COMMON_MSGRINGS			3
-#define BCMPCIE_COMMON_MSGRINGS				5
-
-#define BCMPCIE_H2D_MSGRINGS(max_tx_flows) \
-	(BCMPCIE_H2D_COMMON_MSGRINGS + (max_tx_flows))
-
-/**
- * H2D and D2H, WR and RD index, are maintained in the following arrays:
- * - Array of all H2D WR Indices
- * - Array of all H2D RD Indices
- * - Array of all D2H WR Indices
- * - Array of all D2H RD Indices
- *
- * The offset of the WR or RD indexes (for common rings) in these arrays are
- * listed below. Arrays ARE NOT indexed by a ring's id.
- *
- * D2H common rings WR and RD index start from 0, even though their ringids
- * start from BCMPCIE_H2D_COMMON_MSGRINGS
- */
-
-#define BCMPCIE_H2D_RING_IDX(h2d_ring_id) (h2d_ring_id)
-
-enum h2dring_idx {
-	/* H2D common rings */
-	BCMPCIE_H2D_MSGRING_CONTROL_SUBMIT_IDX =
-		BCMPCIE_H2D_RING_IDX(BCMPCIE_H2D_MSGRING_CONTROL_SUBMIT),
-	BCMPCIE_H2D_MSGRING_RXPOST_SUBMIT_IDX =
-		BCMPCIE_H2D_RING_IDX(BCMPCIE_H2D_MSGRING_RXPOST_SUBMIT),
-
-	/* First TxPost's WR or RD index starts after all H2D common rings */
-	BCMPCIE_H2D_MSGRING_TXFLOW_IDX_START =
-		BCMPCIE_H2D_RING_IDX(BCMPCIE_H2D_COMMON_MSGRINGS)
-};
-
-#define BCMPCIE_D2H_RING_IDX(d2h_ring_id) \
-	((d2h_ring_id) - BCMPCIE_H2D_COMMON_MSGRINGS)
-
-enum d2hring_idx {
-	/* D2H Common Rings */
-	BCMPCIE_D2H_MSGRING_CONTROL_COMPLETE_IDX =
-		BCMPCIE_D2H_RING_IDX(BCMPCIE_D2H_MSGRING_CONTROL_COMPLETE),
-	BCMPCIE_D2H_MSGRING_TX_COMPLETE_IDX =
-		BCMPCIE_D2H_RING_IDX(BCMPCIE_D2H_MSGRING_TX_COMPLETE),
-	BCMPCIE_D2H_MSGRING_RX_COMPLETE_IDX =
-		BCMPCIE_D2H_RING_IDX(BCMPCIE_D2H_MSGRING_RX_COMPLETE)
-};
-
-/**
- * Macros for managing arrays of RD WR indices:
- * rw_index_sz:
- *    - in dongle, rw_index_sz is known at compile time
- *    - in host/DHD, rw_index_sz is derived from advertized pci_shared flags
- *
- *  ring_idx: See h2dring_idx and d2hring_idx
- */
-
-/** Offset of a RD or WR index in H2D or D2H indices array */
-#define BCMPCIE_RW_INDEX_OFFSET(rw_index_sz, ring_idx) \
-	((rw_index_sz) * (ring_idx))
-
-/** Fetch the address of RD or WR index in H2D or D2H indices array */
-#define BCMPCIE_RW_INDEX_ADDR(indices_array_base, rw_index_sz, ring_idx) \
-	(void *)((uint32)(indices_array_base) + \
-	BCMPCIE_RW_INDEX_OFFSET((rw_index_sz), (ring_idx)))
-
-/** H2D DMA Indices array size: given max flow rings */
-#define BCMPCIE_H2D_RW_INDEX_ARRAY_SZ(rw_index_sz, max_tx_flows) \
-	((rw_index_sz) * BCMPCIE_H2D_MSGRINGS(max_tx_flows))
-
-/** D2H DMA Indices array size */
-#define BCMPCIE_D2H_RW_INDEX_ARRAY_SZ(rw_index_sz) \
-	((rw_index_sz) * BCMPCIE_D2H_COMMON_MSGRINGS)
-
-/**
- * This type is used by a 'message buffer' (which is a FIFO for messages). Message buffers are used
- * for host<->device communication and are instantiated on both sides. ring_mem_t is instantiated
- * both in host as well as device memory.
- */
-typedef struct ring_mem {
-	uint16		idx;       /* ring id */
-	uint8		type;
-	uint8		rsvd;
-	uint16		max_item;  /* Max number of items in flow ring */
-	uint16		len_items; /* Items are fixed size. Length in bytes of one item */
-	sh_addr_t	base_addr; /* 64 bits address, either in host or device memory */
-} ring_mem_t;
-
-
-/**
- * Per flow ring, information is maintained in device memory, e.g. at what address the ringmem and
- * ringstate are located. The flow ring itself can be instantiated in either host or device memory.
- *
- * Perhaps this type should be renamed to make clear that it resides in device memory only.
- */
-typedef struct ring_info {
-	uint32		ringmem_ptr; /* ring mem location in dongle memory */
-
-	/* Following arrays are indexed using h2dring_idx and d2hring_idx, and not
-	 * by a ringid.
-	 */
-
-	/* 32bit ptr to arrays of WR or RD indices for all rings in dongle memory */
-	uint32		h2d_w_idx_ptr; /* Array of all H2D ring's WR indices */
-	uint32		h2d_r_idx_ptr; /* Array of all H2D ring's RD indices */
-	uint32		d2h_w_idx_ptr; /* Array of all D2H ring's WR indices */
-	uint32		d2h_r_idx_ptr; /* Array of all D2H ring's RD indices */
-
-	/* PCIE_DMA_INDEX feature: Dongle uses mem2mem DMA to sync arrays in host.
-	 * Host may directly fetch WR and RD indices from these host-side arrays.
-	 *
-	 * 64bit ptr to arrays of WR or RD indices for all rings in host memory.
-	 */
-	sh_addr_t	h2d_w_idx_hostaddr; /* Array of all H2D ring's WR indices */
-	sh_addr_t	h2d_r_idx_hostaddr; /* Array of all H2D ring's RD indices */
-	sh_addr_t	d2h_w_idx_hostaddr; /* Array of all D2H ring's WR indices */
-	sh_addr_t	d2h_r_idx_hostaddr; /* Array of all D2H ring's RD indices */
-
-	uint16		max_sub_queues; /* maximum number of H2D rings: common + flow */
-	uint16		rsvd;
-} ring_info_t;
-
-/**
- * A structure located in TCM that is shared between host and device, primarily used during
- * initialization.
- */
-typedef struct {
-	/** shared area version captured at flags 7:0 */
-	uint32	flags;
-
-	uint32  trap_addr;
-	uint32  assert_exp_addr;
-	uint32  assert_file_addr;
-	uint32  assert_line;
-	uint32	console_addr;		/**< Address of hnd_cons_t */
-
-	uint32  msgtrace_addr;
-
-	uint32  fwid;
-
-	/* Used for debug/flow control */
-	uint16  total_lfrag_pkt_cnt;
-	uint16  max_host_rxbufs; /* rsvd in spec */
-
-	uint32 dma_rxoffset; /* rsvd in spec */
-
-	/** these will be used for sleep request/ack, d3 req/ack */
-	uint32  h2d_mb_data_ptr;
-	uint32  d2h_mb_data_ptr;
-
-	/* information pertinent to host IPC/msgbuf channels */
-	/** location in the TCM memory which has the ring_info */
-	uint32	rings_info_ptr;
-
-	/** block of host memory for the scratch buffer */
-	uint32		host_dma_scratch_buffer_len;
-	sh_addr_t	host_dma_scratch_buffer;
-
-	/** block of host memory for the dongle to push the status into */
-	uint32		device_rings_stsblk_len;
-	sh_addr_t	device_rings_stsblk;
-
-	uint32	buzzz;	/* BUZZZ state format strings and trace buffer */
-
-} pciedev_shared_t;
-
-extern pciedev_shared_t pciedev_shared;
-
-/**
- * Mailboxes notify a remote party that an event took place, using interrupts. They use hardware
- * support.
- */
-
-/* H2D mail box Data */
-#define H2D_HOST_D3_INFORM	0x00000001
-#define H2D_HOST_DS_ACK		0x00000002
-#define H2D_HOST_DS_NAK		0x00000004
-#define H2D_HOST_CONS_INT	0x80000000	/**< h2d int for console cmds  */
-#define H2D_FW_TRAP			0x20000000	/**< dump HW reg info for Livelock issue */
-#define H2D_HOST_D0_INFORM_IN_USE	0x00000008
-#define H2D_HOST_D0_INFORM	0x00000010
-
-/* D2H mail box Data */
-#define D2H_DEV_D3_ACK		0x00000001
-#define D2H_DEV_DS_ENTER_REQ	0x00000002
-#define D2H_DEV_DS_EXIT_NOTE	0x00000004
-#define D2H_DEV_FWHALT		0x10000000
-#define D2H_DEV_MB_MASK		(D2H_DEV_D3_ACK | D2H_DEV_DS_ENTER_REQ | \
-				D2H_DEV_DS_EXIT_NOTE | D2H_DEV_FWHALT)
-#define D2H_DEV_MB_INVALIDATED(x)	((!x) || (x & ~D2H_DEV_MB_MASK))
-
-/** These macro's operate on type 'inuse_lclbuf_pool_t' and are used by firmware only */
-#define NEXTTXP(i, d)           ((((i)+1) >= (d)) ? 0 : ((i)+1))
-#define NTXPACTIVE(r, w, d)     (((r) <= (w)) ? ((w)-(r)) : ((d)-(r)+(w)))
-#define NTXPAVAIL(r, w, d)      (((d) - NTXPACTIVE((r), (w), (d))) > 1)
-
-/* Function can be used to notify host of FW halt */
-#define READ_AVAIL_SPACE(w, r, d)		\
-			((w >= r) ? (w - r) : (d - r))
-
-#define WRITE_SPACE_AVAIL_CONTINUOUS(r, w, d)		((w >= r) ? (d - w) : (r - w))
-#define WRITE_SPACE_AVAIL(r, w, d)	(d - (NTXPACTIVE(r, w, d)) - 1)
-#define CHECK_WRITE_SPACE(r, w, d)	\
-		MIN(WRITE_SPACE_AVAIL(r, w, d), WRITE_SPACE_AVAIL_CONTINUOUS(r, w, d))
-
-
-#define WRT_PEND(x)	((x)->wr_pending)
-#define DNGL_RING_WPTR(msgbuf)		(*((msgbuf)->tcm_rs_w_ptr))
-#define BCMMSGBUF_RING_SET_W_PTR(msgbuf, a)	(DNGL_RING_WPTR(msgbuf) = (a))
-
-#define DNGL_RING_RPTR(msgbuf)		(*((msgbuf)->tcm_rs_r_ptr))
-#define BCMMSGBUF_RING_SET_R_PTR(msgbuf, a)	(DNGL_RING_RPTR(msgbuf) = (a))
-
-#define RING_START_PTR(x)	((x)->ringmem->base_addr.low_addr)
-#define RING_MAX_ITEM(x)	((x)->ringmem->max_item)
-#define RING_LEN_ITEMS(x)	((x)->ringmem->len_items)
-
-#endif	/* _bcmpcie_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmpcispi.h b/drivers/net/wireless/bcmdhd/include/bcmpcispi.h
deleted file mode 100644
index 66c783c..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmpcispi.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Broadcom PCI-SPI Host Controller Register Definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmpcispi.h 514727 2014-11-12 03:02:48Z $
- */
-#ifndef	_BCM_PCI_SPI_H
-#define	_BCM_PCI_SPI_H
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif	/* PAD */
-
-
-typedef volatile struct {
-	uint32 spih_ctrl;		/* 0x00 SPI Control Register */
-	uint32 spih_stat;		/* 0x04 SPI Status Register */
-	uint32 spih_data;		/* 0x08 SPI Data Register, 32-bits wide */
-	uint32 spih_ext;		/* 0x0C SPI Extension Register */
-	uint32 PAD[4];			/* 0x10-0x1F PADDING */
-
-	uint32 spih_gpio_ctrl;		/* 0x20 SPI GPIO Control Register */
-	uint32 spih_gpio_data;		/* 0x24 SPI GPIO Data Register */
-	uint32 PAD[6];			/* 0x28-0x3F PADDING */
-
-	uint32 spih_int_edge;		/* 0x40 SPI Interrupt Edge Register (0=Level, 1=Edge) */
-	uint32 spih_int_pol;		/* 0x44 SPI Interrupt Polarity Register (0=Active Low, */
-							/* 1=Active High) */
-	uint32 spih_int_mask;		/* 0x48 SPI Interrupt Mask */
-	uint32 spih_int_status;		/* 0x4C SPI Interrupt Status */
-	uint32 PAD[4];			/* 0x50-0x5F PADDING */
-
-	uint32 spih_hex_disp;		/* 0x60 SPI 4-digit hex display value */
-	uint32 spih_current_ma;		/* 0x64 SPI SD card current consumption in mA */
-	uint32 PAD[1];			/* 0x68 PADDING */
-	uint32 spih_disp_sel;		/* 0x6c SPI 4-digit hex display mode select (1=current) */
-	uint32 PAD[4];			/* 0x70-0x7F PADDING */
-	uint32 PAD[8];			/* 0x80-0x9F PADDING */
-	uint32 PAD[8];			/* 0xA0-0xBF PADDING */
-	uint32 spih_pll_ctrl;	/* 0xC0 PLL Control Register */
-	uint32 spih_pll_status;	/* 0xC4 PLL Status Register */
-	uint32 spih_xtal_freq;	/* 0xC8 External Clock Frequency in units of 10000Hz */
-	uint32 spih_clk_count;	/* 0xCC External Clock Count Register */
-
-} spih_regs_t;
-
-typedef volatile struct {
-	uint32 cfg_space[0x40];		/* 0x000-0x0FF PCI Configuration Space (Read Only) */
-	uint32 P_IMG_CTRL0;		/* 0x100 PCI Image0 Control Register */
-
-	uint32 P_BA0;			/* 0x104 32 R/W PCI Image0 Base Address register */
-	uint32 P_AM0;			/* 0x108 32 R/W PCI Image0 Address Mask register */
-	uint32 P_TA0;			/* 0x10C 32 R/W PCI Image0 Translation Address register */
-	uint32 P_IMG_CTRL1;		/* 0x110 32 R/W PCI Image1 Control register */
-	uint32 P_BA1;			/* 0x114 32 R/W PCI Image1 Base Address register */
-	uint32 P_AM1;			/* 0x118 32 R/W PCI Image1 Address Mask register */
-	uint32 P_TA1;			/* 0x11C 32 R/W PCI Image1 Translation Address register */
-	uint32 P_IMG_CTRL2;		/* 0x120 32 R/W PCI Image2 Control register */
-	uint32 P_BA2;			/* 0x124 32 R/W PCI Image2 Base Address register */
-	uint32 P_AM2;			/* 0x128 32 R/W PCI Image2 Address Mask register */
-	uint32 P_TA2;			/* 0x12C 32 R/W PCI Image2 Translation Address register */
-	uint32 P_IMG_CTRL3;		/* 0x130 32 R/W PCI Image3 Control register */
-	uint32 P_BA3;			/* 0x134 32 R/W PCI Image3 Base Address register */
-	uint32 P_AM3;			/* 0x138 32 R/W PCI Image3 Address Mask register */
-	uint32 P_TA3;			/* 0x13C 32 R/W PCI Image3 Translation Address register */
-	uint32 P_IMG_CTRL4;		/* 0x140 32 R/W PCI Image4 Control register */
-	uint32 P_BA4;			/* 0x144 32 R/W PCI Image4 Base Address register */
-	uint32 P_AM4;			/* 0x148 32 R/W PCI Image4 Address Mask register */
-	uint32 P_TA4;			/* 0x14C 32 R/W PCI Image4 Translation Address register */
-	uint32 P_IMG_CTRL5;		/* 0x150 32 R/W PCI Image5 Control register */
-	uint32 P_BA5;			/* 0x154 32 R/W PCI Image5 Base Address register */
-	uint32 P_AM5;			/* 0x158 32 R/W PCI Image5 Address Mask register */
-	uint32 P_TA5;			/* 0x15C 32 R/W PCI Image5 Translation Address register */
-	uint32 P_ERR_CS;		/* 0x160 32 R/W PCI Error Control and Status register */
-	uint32 P_ERR_ADDR;		/* 0x164 32 R PCI Erroneous Address register */
-	uint32 P_ERR_DATA;		/* 0x168 32 R PCI Erroneous Data register */
-
-	uint32 PAD[5];			/* 0x16C-0x17F PADDING */
-
-	uint32 WB_CONF_SPC_BAR;		/* 0x180 32 R WISHBONE Configuration Space Base Address */
-	uint32 W_IMG_CTRL1;		/* 0x184 32 R/W WISHBONE Image1 Control register */
-	uint32 W_BA1;			/* 0x188 32 R/W WISHBONE Image1 Base Address register */
-	uint32 W_AM1;			/* 0x18C 32 R/W WISHBONE Image1 Address Mask register */
-	uint32 W_TA1;			/* 0x190 32 R/W WISHBONE Image1 Translation Address reg */
-	uint32 W_IMG_CTRL2;		/* 0x194 32 R/W WISHBONE Image2 Control register */
-	uint32 W_BA2;			/* 0x198 32 R/W WISHBONE Image2 Base Address register */
-	uint32 W_AM2;			/* 0x19C 32 R/W WISHBONE Image2 Address Mask register */
-	uint32 W_TA2;			/* 0x1A0 32 R/W WISHBONE Image2 Translation Address reg */
-	uint32 W_IMG_CTRL3;		/* 0x1A4 32 R/W WISHBONE Image3 Control register */
-	uint32 W_BA3;			/* 0x1A8 32 R/W WISHBONE Image3 Base Address register */
-	uint32 W_AM3;			/* 0x1AC 32 R/W WISHBONE Image3 Address Mask register */
-	uint32 W_TA3;			/* 0x1B0 32 R/W WISHBONE Image3 Translation Address reg */
-	uint32 W_IMG_CTRL4;		/* 0x1B4 32 R/W WISHBONE Image4 Control register */
-	uint32 W_BA4;			/* 0x1B8 32 R/W WISHBONE Image4 Base Address register */
-	uint32 W_AM4;			/* 0x1BC 32 R/W WISHBONE Image4 Address Mask register */
-	uint32 W_TA4;			/* 0x1C0 32 R/W WISHBONE Image4 Translation Address reg */
-	uint32 W_IMG_CTRL5;		/* 0x1C4 32 R/W WISHBONE Image5 Control register */
-	uint32 W_BA5;			/* 0x1C8 32 R/W WISHBONE Image5 Base Address register */
-	uint32 W_AM5;			/* 0x1CC 32 R/W WISHBONE Image5 Address Mask register */
-	uint32 W_TA5;			/* 0x1D0 32 R/W WISHBONE Image5 Translation Address reg */
-	uint32 W_ERR_CS;		/* 0x1D4 32 R/W WISHBONE Error Control and Status reg */
-	uint32 W_ERR_ADDR;		/* 0x1D8 32 R WISHBONE Erroneous Address register */
-	uint32 W_ERR_DATA;		/* 0x1DC 32 R WISHBONE Erroneous Data register */
-	uint32 CNF_ADDR;		/* 0x1E0 32 R/W Configuration Cycle register */
-	uint32 CNF_DATA;		/* 0x1E4 32 R/W Configuration Cycle Generation Data reg */
-
-	uint32 INT_ACK;			/* 0x1E8 32 R Interrupt Acknowledge register */
-	uint32 ICR;			/* 0x1EC 32 R/W Interrupt Control register */
-	uint32 ISR;			/* 0x1F0 32 R/W Interrupt Status register */
-} spih_pciregs_t;
-
-/*
- * PCI Core interrupt enable and status bit definitions.
- */
-
-/* PCI Core ICR Register bit definitions */
-#define PCI_INT_PROP_EN		(1 << 0)	/* Interrupt Propagation Enable */
-#define PCI_WB_ERR_INT_EN	(1 << 1)	/* Wishbone Error Interrupt Enable */
-#define PCI_PCI_ERR_INT_EN	(1 << 2)	/* PCI Error Interrupt Enable */
-#define PCI_PAR_ERR_INT_EN	(1 << 3)	/* Parity Error Interrupt Enable */
-#define PCI_SYS_ERR_INT_EN	(1 << 4)	/* System Error Interrupt Enable */
-#define PCI_SOFTWARE_RESET	(1U << 31)	/* Software reset of the PCI Core. */
-
-
-/* PCI Core ISR Register bit definitions */
-#define PCI_INT_PROP_ST		(1 << 0)	/* Interrupt Propagation Status */
-#define PCI_WB_ERR_INT_ST	(1 << 1)	/* Wishbone Error Interrupt Status */
-#define PCI_PCI_ERR_INT_ST	(1 << 2)	/* PCI Error Interrupt Status */
-#define PCI_PAR_ERR_INT_ST	(1 << 3)	/* Parity Error Interrupt Status */
-#define PCI_SYS_ERR_INT_ST	(1 << 4)	/* System Error Interrupt Status */
-
-
-/* Registers on the Wishbone bus */
-#define SPIH_CTLR_INTR		(1 << 0)	/* SPI Host Controller Core Interrupt */
-#define SPIH_DEV_INTR		(1 << 1)	/* SPI Device Interrupt */
-#define SPIH_WFIFO_INTR		(1 << 2)	/* SPI Tx FIFO Empty Intr (FPGA Rev >= 8) */
-
-/* GPIO Bit definitions */
-#define SPIH_CS			(1 << 0)	/* SPI Chip Select (active low) */
-#define SPIH_SLOT_POWER		(1 << 1)	/* SD Card Slot Power Enable */
-#define SPIH_CARD_DETECT	(1 << 2)	/* SD Card Detect */
-
-/* SPI Status Register Bit definitions */
-#define SPIH_STATE_MASK		0x30		/* SPI Transfer State Machine state mask */
-#define SPIH_STATE_SHIFT	4		/* SPI Transfer State Machine state shift */
-#define SPIH_WFFULL		(1 << 3)	/* SPI Write FIFO Full */
-#define SPIH_WFEMPTY		(1 << 2)	/* SPI Write FIFO Empty */
-#define SPIH_RFFULL		(1 << 1)	/* SPI Read FIFO Full */
-#define SPIH_RFEMPTY		(1 << 0)	/* SPI Read FIFO Empty */
-
-#define SPIH_EXT_CLK		(1U << 31)	/* Use External Clock as PLL Clock source. */
-
-#define SPIH_PLL_NO_CLK		(1 << 1)	/* Set to 1 if the PLL's input clock is lost. */
-#define SPIH_PLL_LOCKED		(1 << 3)	/* Set to 1 when the PLL is locked. */
-
-/* Spin bit loop bound check */
-#define SPI_SPIN_BOUND		0xf4240		/* 1 million */
-
-#endif /* _BCM_PCI_SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmperf.h b/drivers/net/wireless/bcmdhd/include/bcmperf.h
deleted file mode 100644
index 823c3b6..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmperf.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Performance counters software interface.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmperf.h 514727 2014-11-12 03:02:48Z $
- */
-/* essai */
-#ifndef _BCMPERF_H_
-#define _BCMPERF_H_
-/* get cache hits and misses */
-#define BCMPERF_ENABLE_INSTRCOUNT()
-#define BCMPERF_ENABLE_ICACHE_MISS()
-#define BCMPERF_ENABLE_ICACHE_HIT()
-#define	BCMPERF_GETICACHE_MISS(x)	((x) = 0)
-#define	BCMPERF_GETICACHE_HIT(x)	((x) = 0)
-#define	BCMPERF_GETINSTRCOUNT(x)	((x) = 0)
-#endif /* _BCMPERF_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdbus.h b/drivers/net/wireless/bcmdhd/include/bcmsdbus.h
deleted file mode 100644
index ce75ffa..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmsdbus.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Definitions for API from sdio common code (bcmsdh) to individual
- * host controller drivers.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsdbus.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_sdio_api_h_
-#define	_sdio_api_h_
-
-
-#define SDIOH_API_RC_SUCCESS                          (0x00)
-#define SDIOH_API_RC_FAIL	                      (0x01)
-#define SDIOH_API_SUCCESS(status) (status == 0)
-
-#define SDIOH_READ              0	/* Read request */
-#define SDIOH_WRITE             1	/* Write request */
-
-#define SDIOH_DATA_FIX          0	/* Fixed addressing */
-#define SDIOH_DATA_INC          1	/* Incremental addressing */
-
-#define SDIOH_CMD_TYPE_NORMAL   0       /* Normal command */
-#define SDIOH_CMD_TYPE_APPEND   1       /* Append command */
-#define SDIOH_CMD_TYPE_CUTTHRU  2       /* Cut-through command */
-
-#define SDIOH_DATA_PIO          0       /* PIO mode */
-#define SDIOH_DATA_DMA          1       /* DMA mode */
-
-/* Max number of glommed pkts */
-#ifdef CUSTOM_MAX_TXGLOM_SIZE
-#define SDPCM_MAXGLOM_SIZE  CUSTOM_MAX_TXGLOM_SIZE
-#else
-#define SDPCM_MAXGLOM_SIZE	40
-#endif /* CUSTOM_MAX_TXGLOM_SIZE */
-
-#define SDPCM_TXGLOM_CPY 0			/* SDIO 2.0 should use copy mode */
-#define SDPCM_TXGLOM_MDESC	1		/* SDIO 3.0 should use multi-desc mode */
-
-#ifdef CUSTOM_DEF_TXGLOM_SIZE
-#define SDPCM_DEFGLOM_SIZE  CUSTOM_DEF_TXGLOM_SIZE
-#else
-#define SDPCM_DEFGLOM_SIZE SDPCM_MAXGLOM_SIZE
-#endif /* CUSTOM_DEF_TXGLOM_SIZE */
-
-#if SDPCM_DEFGLOM_SIZE > SDPCM_MAXGLOM_SIZE
-#warning "SDPCM_DEFGLOM_SIZE cannot be higher than SDPCM_MAXGLOM_SIZE!!"
-#undef SDPCM_DEFGLOM_SIZE
-#define SDPCM_DEFGLOM_SIZE SDPCM_MAXGLOM_SIZE
-#endif
-
-typedef int SDIOH_API_RC;
-
-/* SDio Host structure */
-typedef struct sdioh_info sdioh_info_t;
-
-/* callback function, taking one arg */
-typedef void (*sdioh_cb_fn_t)(void *);
-
-extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si, sdioh_cb_fn_t fn, void *argh);
-extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si);
-
-/* query whether SD interrupt is enabled or not */
-extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff);
-
-/* enable or disable SD interrupt */
-extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
-
-#if defined(DHD_DEBUG)
-extern bool sdioh_interrupt_pending(sdioh_info_t *si);
-#endif
-
-/* read or write one byte using cmd52 */
-extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc, uint addr, uint8 *byte);
-
-/* read or write 2/4 bytes using cmd53 */
-extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type, uint rw, uint fnc,
-	uint addr, uint32 *word, uint nbyte);
-
-/* read or write any buffer using cmd53 */
-extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma, uint fix_inc,
-	uint rw, uint fnc_num, uint32 addr, uint regwidth, uint32 buflen, uint8 *buffer,
-	void *pkt);
-
-/* get cis data */
-extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, uint8 *cis, uint32 length);
-
-extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, uint32 addr, uint8 *data);
-extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, uint32 addr, uint8 *data);
-
-/* query number of io functions */
-extern uint sdioh_query_iofnum(sdioh_info_t *si);
-
-/* handle iovars */
-extern int sdioh_iovar_op(sdioh_info_t *si, const char *name,
-                          void *params, int plen, void *arg, int len, bool set);
-
-/* Issue abort to the specified function and clear controller as needed */
-extern int sdioh_abort(sdioh_info_t *si, uint fnc);
-
-/* Start and Stop SDIO without re-enumerating the SD card. */
-extern int sdioh_start(sdioh_info_t *si, int stage);
-extern int sdioh_stop(sdioh_info_t *si);
-
-/* Wait system lock free */
-extern int sdioh_waitlockfree(sdioh_info_t *si);
-
-/* Reset and re-initialize the device */
-extern int sdioh_sdio_reset(sdioh_info_t *si);
-
-
-
-#if defined(BCMSDIOH_STD)
-	#define SDIOH_SLEEP_ENABLED
-#endif
-extern SDIOH_API_RC sdioh_sleep(sdioh_info_t *si, bool enab);
-
-/* GPIO support */
-extern SDIOH_API_RC sdioh_gpio_init(sdioh_info_t *sd);
-extern bool sdioh_gpioin(sdioh_info_t *sd, uint32 gpio);
-extern SDIOH_API_RC sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio);
-extern SDIOH_API_RC sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab);
-
-#endif /* _sdio_api_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh.h b/drivers/net/wireless/bcmdhd/include/bcmsdh.h
deleted file mode 100644
index 3b3e6b6..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmsdh.h
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * SDIO host client driver interface of Broadcom HNBU
- *     export functions to client drivers
- *     abstract OS and BUS specific details of SDIO
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsdh.h 514727 2014-11-12 03:02:48Z $
- */
-
-/**
- * @file bcmsdh.h
- */
-
-#ifndef	_bcmsdh_h_
-#define	_bcmsdh_h_
-
-#define BCMSDH_ERROR_VAL	0x0001 /* Error */
-#define BCMSDH_INFO_VAL		0x0002 /* Info */
-extern const uint bcmsdh_msglevel;
-
-#define BCMSDH_ERROR(x)
-#define BCMSDH_INFO(x)
-
-#if defined(BCMSDIO) && (defined(BCMSDIOH_STD) || defined(BCMSDIOH_BCM) || \
-	defined(BCMSDIOH_SPI))
-#define BCMSDH_ADAPTER
-#endif /* BCMSDIO && (BCMSDIOH_STD || BCMSDIOH_BCM || BCMSDIOH_SPI) */
-
-/* forward declarations */
-typedef struct bcmsdh_info bcmsdh_info_t;
-typedef void (*bcmsdh_cb_fn_t)(void *);
-
-extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *sdioh, ulong *regsva);
-/**
- * BCMSDH API context
- */
-struct bcmsdh_info
-{
-	bool	init_success;	/* underlying driver successfully attached */
-	void	*sdioh;		/* handler for sdioh */
-	uint32  vendevid;	/* Target Vendor and Device ID on SD bus */
-	osl_t   *osh;
-	bool	regfail;	/* Save status of last reg_read/reg_write call */
-	uint32	sbwad;		/* Save backplane window address */
-	void	*os_cxt;        /* Pointer to per-OS private data */
-};
-
-/* Detach - freeup resources allocated in attach */
-extern int bcmsdh_detach(osl_t *osh, void *sdh);
-
-/* Query if SD device interrupts are enabled */
-extern bool bcmsdh_intr_query(void *sdh);
-
-/* Enable/disable SD interrupt */
-extern int bcmsdh_intr_enable(void *sdh);
-extern int bcmsdh_intr_disable(void *sdh);
-
-/* Register/deregister device interrupt handler. */
-extern int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh);
-extern int bcmsdh_intr_dereg(void *sdh);
-/* Enable/disable SD card interrupt forward */
-extern void bcmsdh_intr_forward(void *sdh, bool pass);
-
-#if defined(DHD_DEBUG)
-/* Query pending interrupt status from the host controller */
-extern bool bcmsdh_intr_pending(void *sdh);
-#endif
-
-/* Register a callback to be called if and when bcmsdh detects
- * device removal. No-op in the case of non-removable/hardwired devices.
- */
-extern int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh);
-
-/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
- *   fn:   function number
- *   addr: unmodified SDIO-space address
- *   data: data byte to write
- *   err:  pointer to error code (or NULL)
- */
-extern uint8 bcmsdh_cfg_read(void *sdh, uint func, uint32 addr, int *err);
-extern void bcmsdh_cfg_write(void *sdh, uint func, uint32 addr, uint8 data, int *err);
-
-/* Read/Write 4bytes from/to cfg space */
-extern uint32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err);
-extern void bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err);
-
-/* Read CIS content for specified function.
- *   fn:     function whose CIS is being requested (0 is common CIS)
- *   cis:    pointer to memory location to place results
- *   length: number of bytes to read
- * Internally, this routine uses the values from the cis base regs (0x9-0xB)
- * to form an SDIO-space address to read the data from.
- */
-extern int bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length);
-
-/* Synchronous access to device (client) core registers via CMD53 to F1.
- *   addr: backplane address (i.e. >= regsva from attach)
- *   size: register width in bytes (2 or 4)
- *   data: data for register write
- */
-extern uint32 bcmsdh_reg_read(void *sdh, uint32 addr, uint size);
-extern uint32 bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data);
-
-/* set sb address window */
-extern int bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set);
-
-/* Indicate if last reg read/write failed */
-extern bool bcmsdh_regfail(void *sdh);
-
-/* Buffer transfer to/from device (client) core via cmd53.
- *   fn:       function number
- *   addr:     backplane address (i.e. >= regsva from attach)
- *   flags:    backplane width, address increment, sync/async
- *   buf:      pointer to memory data buffer
- *   nbytes:   number of bytes to transfer to/from buf
- *   pkt:      pointer to packet associated with buf (if any)
- *   complete: callback function for command completion (async only)
- *   handle:   handle for completion callback (first arg in callback)
- * Returns 0 or error code.
- * NOTE: Async operation is not currently supported.
- */
-typedef void (*bcmsdh_cmplt_fn_t)(void *handle, int status, bool sync_waiting);
-extern int bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags,
-                           uint8 *buf, uint nbytes, void *pkt,
-                           bcmsdh_cmplt_fn_t complete_fn, void *handle);
-extern int bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags,
-                           uint8 *buf, uint nbytes, void *pkt,
-                           bcmsdh_cmplt_fn_t complete_fn, void *handle);
-
-extern void bcmsdh_glom_post(void *sdh, uint8 *frame, void *pkt, uint len);
-extern void bcmsdh_glom_clear(void *sdh);
-extern uint bcmsdh_set_mode(void *sdh, uint mode);
-extern bool bcmsdh_glom_enabled(void);
-/* Flags bits */
-#define SDIO_REQ_4BYTE	0x1	/* Four-byte target (backplane) width (vs. two-byte) */
-#define SDIO_REQ_FIXED	0x2	/* Fixed address (FIFO) (vs. incrementing address) */
-#define SDIO_REQ_ASYNC	0x4	/* Async request (vs. sync request) */
-#define SDIO_BYTE_MODE	0x8	/* Byte mode request(non-block mode) */
-
-/* Pending (non-error) return code */
-#define BCME_PENDING	1
-
-/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
- *   rw:       read or write (0/1)
- *   addr:     direct SDIO address
- *   buf:      pointer to memory data buffer
- *   nbytes:   number of bytes to transfer to/from buf
- * Returns 0 or error code.
- */
-extern int bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes);
-
-/* Issue an abort to the specified function */
-extern int bcmsdh_abort(void *sdh, uint fn);
-
-/* Start SDIO Host Controller communication */
-extern int bcmsdh_start(void *sdh, int stage);
-
-/* Stop SDIO Host Controller communication */
-extern int bcmsdh_stop(void *sdh);
-
-/* Wait system lock free */
-extern int bcmsdh_waitlockfree(void *sdh);
-
-/* Returns the "Device ID" of target device on the SDIO bus. */
-extern int bcmsdh_query_device(void *sdh);
-
-/* Returns the number of IO functions reported by the device */
-extern uint bcmsdh_query_iofnum(void *sdh);
-
-/* Miscellaneous knob tweaker. */
-extern int bcmsdh_iovar_op(void *sdh, const char *name,
-                           void *params, int plen, void *arg, int len, bool set);
-
-/* Reset and reinitialize the device */
-extern int bcmsdh_reset(bcmsdh_info_t *sdh);
-
-/* helper functions */
-
-/* callback functions */
-typedef struct {
-	/* probe the device */
-	void *(*probe)(uint16 vend_id, uint16 dev_id, uint16 bus, uint16 slot,
-	                uint16 func, uint bustype, void * regsva, osl_t * osh,
-	                void * param);
-	/* remove the device */
-	void (*remove)(void *context);
-	/* can we suspend now */
-	int (*suspend)(void *context);
-	/* resume from suspend */
-	int (*resume)(void *context);
-} bcmsdh_driver_t;
-
-/* platform specific/high level functions */
-extern int bcmsdh_register(bcmsdh_driver_t *driver);
-extern void bcmsdh_unregister(void);
-extern bool bcmsdh_chipmatch(uint16 vendor, uint16 device);
-extern void bcmsdh_device_remove(void * sdh);
-
-extern int bcmsdh_reg_sdio_notify(void* semaphore);
-extern void bcmsdh_unreg_sdio_notify(void);
-
-#if defined(OOB_INTR_ONLY)
-extern int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handler,
-	void* oob_irq_handler_context);
-extern void bcmsdh_oob_intr_unregister(bcmsdh_info_t *sdh);
-extern void bcmsdh_oob_intr_set(bcmsdh_info_t *sdh, bool enable);
-#endif 
-extern void bcmsdh_dev_pm_stay_awake(bcmsdh_info_t *sdh);
-extern void bcmsdh_dev_relax(bcmsdh_info_t *sdh);
-extern bool bcmsdh_dev_pm_enabled(bcmsdh_info_t *sdh);
-
-int bcmsdh_suspend(bcmsdh_info_t *bcmsdh);
-int bcmsdh_resume(bcmsdh_info_t *bcmsdh);
-
-/* Function to pass device-status bits to DHD. */
-extern uint32 bcmsdh_get_dstatus(void *sdh);
-
-/* Function to return current window addr */
-extern uint32 bcmsdh_cur_sbwad(void *sdh);
-
-/* Function to pass chipid and rev to lower layers for controlling pr's */
-extern void bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev);
-
-
-extern int bcmsdh_sleep(void *sdh, bool enab);
-
-/* GPIO support */
-extern int bcmsdh_gpio_init(void *sd);
-extern bool bcmsdh_gpioin(void *sd, uint32 gpio);
-extern int bcmsdh_gpioouten(void *sd, uint32 gpio);
-extern int bcmsdh_gpioout(void *sd, uint32 gpio, bool enab);
-
-#endif	/* _bcmsdh_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h
deleted file mode 100644
index 07903f9..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Proprietary,Open:>>
- *
- * $Id: bcmsdh_sdmmc.h 591160 2015-10-07 06:01:58Z $
- */
-
-#ifndef __BCMSDH_SDMMC_H__
-#define __BCMSDH_SDMMC_H__
-
-#define sd_err(x)	do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-
-#define sd_sync_dma(sd, read, nbytes)
-#define sd_init_dma(sd)
-#define sd_ack_intr(sd)
-#define sd_wakeup(sd);
-
-#define sd_log(x)
-
-#define SDIOH_ASSERT(exp) \
-	do { if (!(exp)) \
-		printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
-	} while (0)
-
-#define BLOCK_SIZE_4318 64
-#define BLOCK_SIZE_4328 512
-
-/* internal return code */
-#define SUCCESS	0
-#define ERROR	1
-
-/* private bus modes */
-#define SDIOH_MODE_SD4		2
-#define CLIENT_INTR			0x100	/* Get rid of this! */
-#define SDIOH_SDMMC_MAX_SG_ENTRIES	32
-
-struct sdioh_info {
-	osl_t		*osh;			/* osh handler */
-	void		*bcmsdh;		/* upper layer handle */
-	bool		client_intr_enabled;	/* interrupt connnected flag */
-	bool		intr_handler_valid;	/* client driver interrupt handler valid */
-	sdioh_cb_fn_t	intr_handler;		/* registered interrupt handler */
-	void		*intr_handler_arg;	/* argument to call interrupt handler */
-	uint16		intmask;		/* Current active interrupts */
-
-	int		intrcount;		/* Client interrupts */
-	bool		sd_use_dma;		/* DMA on CMD53 */
-	bool		sd_blockmode;		/* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
-						/*  Must be on for sd_multiblock to be effective */
-	bool		use_client_ints;	/* If this is false, make sure to restore */
-	int		sd_mode;		/* SD1/SD4/SPI */
-	int		client_block_size[SDIOD_MAX_IOFUNCS];		/* Blocksize */
-	uint8		num_funcs;		/* Supported funcs on client */
-	uint32		com_cis_ptr;
-	uint32		func_cis_ptr[SDIOD_MAX_IOFUNCS];
-	bool		use_rxchain;
-	struct scatterlist	sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES];
-	struct sdio_func	fake_func0;
-	struct sdio_func	*func[SDIOD_MAX_IOFUNCS];
-
-};
-
-/************************************************************
- * Internal interfaces: per-port references into bcmsdh_sdmmc.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/* OS-independent interrupt handler */
-extern bool check_client_intr(sdioh_info_t *sd);
-
-/* Core interrupt enable/disable of device interrupts */
-extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
-extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
-
-
-/**************************************************************
- * Internal interfaces: bcmsdh_sdmmc.c references to per-port code
- */
-
-/* Register mapping routines */
-extern uint32 *sdioh_sdmmc_reg_map(osl_t *osh, int32 addr, int size);
-extern void sdioh_sdmmc_reg_unmap(osl_t *osh, int32 addr, int size);
-
-/* Interrupt (de)registration routines */
-extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq);
-extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
-
-extern sdioh_info_t *sdioh_attach(osl_t *osh, struct sdio_func *func);
-extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *sd);
-#endif /* __BCMSDH_SDMMC_H__ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h b/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h
deleted file mode 100644
index 5c0adff..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Broadcom SDIO/PCMCIA
- * Software-specific definitions shared between device and host side
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsdpcm.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_bcmsdpcm_h_
-#define	_bcmsdpcm_h_
-
-/*
- * Software allocation of To SB Mailbox resources
- */
-
-/* intstatus bits */
-#define I_SMB_NAK	I_SMB_SW0	/* To SB Mailbox Frame NAK */
-#define I_SMB_INT_ACK	I_SMB_SW1	/* To SB Mailbox Host Interrupt ACK */
-#define I_SMB_USE_OOB	I_SMB_SW2	/* To SB Mailbox Use OOB Wakeup */
-#define I_SMB_DEV_INT	I_SMB_SW3	/* To SB Mailbox Miscellaneous Interrupt */
-
-#define I_TOSBMAIL      (I_SMB_NAK | I_SMB_INT_ACK | I_SMB_USE_OOB | I_SMB_DEV_INT)
-
-/* tosbmailbox bits corresponding to intstatus bits */
-#define SMB_NAK		(1 << 0)	/* To SB Mailbox Frame NAK */
-#define SMB_INT_ACK	(1 << 1)	/* To SB Mailbox Host Interrupt ACK */
-#define SMB_USE_OOB	(1 << 2)	/* To SB Mailbox Use OOB Wakeup */
-#define SMB_DEV_INT	(1 << 3)	/* To SB Mailbox Miscellaneous Interrupt */
-#define SMB_MASK	0x0000000f	/* To SB Mailbox Mask */
-
-/* tosbmailboxdata */
-#define SMB_DATA_VERSION_MASK	0x00ff0000	/* host protocol version (sent with F2 enable) */
-#define SMB_DATA_VERSION_SHIFT	16		/* host protocol version (sent with F2 enable) */
-
-/*
- * Software allocation of To Host Mailbox resources
- */
-
-/* intstatus bits */
-#define I_HMB_FC_STATE	I_HMB_SW0	/* To Host Mailbox Flow Control State */
-#define I_HMB_FC_CHANGE	I_HMB_SW1	/* To Host Mailbox Flow Control State Changed */
-#define I_HMB_FRAME_IND	I_HMB_SW2	/* To Host Mailbox Frame Indication */
-#define I_HMB_HOST_INT	I_HMB_SW3	/* To Host Mailbox Miscellaneous Interrupt */
-
-#define I_TOHOSTMAIL    (I_HMB_FC_CHANGE | I_HMB_FRAME_IND | I_HMB_HOST_INT)
-
-/* tohostmailbox bits corresponding to intstatus bits */
-#define HMB_FC_ON	(1 << 0)	/* To Host Mailbox Flow Control State */
-#define HMB_FC_CHANGE	(1 << 1)	/* To Host Mailbox Flow Control State Changed */
-#define HMB_FRAME_IND	(1 << 2)	/* To Host Mailbox Frame Indication */
-#define HMB_HOST_INT	(1 << 3)	/* To Host Mailbox Miscellaneous Interrupt */
-#define HMB_MASK	0x0000000f	/* To Host Mailbox Mask */
-
-/* tohostmailboxdata */
-#define HMB_DATA_NAKHANDLED	0x01	/* we're ready to retransmit NAK'd frame to host */
-#define HMB_DATA_DEVREADY	0x02	/* we're ready to to talk to host after enable */
-#define HMB_DATA_FC		0x04	/* per prio flowcontrol update flag to host */
-#define HMB_DATA_FWREADY	0x08	/* firmware is ready for protocol activity */
-#define HMB_DATA_FWHALT		0x10	/* firmware has halted operation */
-
-#define HMB_DATA_FCDATA_MASK	0xff000000	/* per prio flowcontrol data */
-#define HMB_DATA_FCDATA_SHIFT	24		/* per prio flowcontrol data */
-
-#define HMB_DATA_VERSION_MASK	0x00ff0000	/* device protocol version (with devready) */
-#define HMB_DATA_VERSION_SHIFT	16		/* device protocol version (with devready) */
-
-/*
- * Software-defined protocol header
- */
-
-/* Current protocol version */
-#define SDPCM_PROT_VERSION	4
-
-/* SW frame header */
-#define SDPCM_SEQUENCE_MASK		0x000000ff	/* Sequence Number Mask */
-#define SDPCM_PACKET_SEQUENCE(p) (((uint8 *)p)[0] & 0xff) /* p starts w/SW Header */
-
-#define SDPCM_CHANNEL_MASK		0x00000f00	/* Channel Number Mask */
-#define SDPCM_CHANNEL_SHIFT		8		/* Channel Number Shift */
-#define SDPCM_PACKET_CHANNEL(p) (((uint8 *)p)[1] & 0x0f) /* p starts w/SW Header */
-
-#define SDPCM_FLAGS_MASK		0x0000f000	/* Mask of flag bits */
-#define SDPCM_FLAGS_SHIFT		12		/* Flag bits shift */
-#define SDPCM_PACKET_FLAGS(p) ((((uint8 *)p)[1] & 0xf0) >> 4) /* p starts w/SW Header */
-
-/* Next Read Len: lookahead length of next frame, in 16-byte units (rounded up) */
-#define SDPCM_NEXTLEN_MASK		0x00ff0000	/* Next Read Len Mask */
-#define SDPCM_NEXTLEN_SHIFT		16		/* Next Read Len Shift */
-#define SDPCM_NEXTLEN_VALUE(p) ((((uint8 *)p)[2] & 0xff) << 4) /* p starts w/SW Header */
-#define SDPCM_NEXTLEN_OFFSET		2
-
-/* Data Offset from SOF (HW Tag, SW Tag, Pad) */
-#define SDPCM_DOFFSET_OFFSET		3		/* Data Offset */
-#define SDPCM_DOFFSET_VALUE(p) 		(((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff)
-#define SDPCM_DOFFSET_MASK		0xff000000
-#define SDPCM_DOFFSET_SHIFT		24
-
-#define SDPCM_FCMASK_OFFSET		4		/* Flow control */
-#define SDPCM_FCMASK_VALUE(p)		(((uint8 *)p)[SDPCM_FCMASK_OFFSET ] & 0xff)
-#define SDPCM_WINDOW_OFFSET		5		/* Credit based fc */
-#define SDPCM_WINDOW_VALUE(p)		(((uint8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff)
-#define SDPCM_VERSION_OFFSET		6		/* Version # */
-#define SDPCM_VERSION_VALUE(p)		(((uint8 *)p)[SDPCM_VERSION_OFFSET] & 0xff)
-#define SDPCM_UNUSED_OFFSET		7		/* Spare */
-#define SDPCM_UNUSED_VALUE(p)		(((uint8 *)p)[SDPCM_UNUSED_OFFSET] & 0xff)
-
-#define SDPCM_SWHEADER_LEN	8	/* SW header is 64 bits */
-
-/* logical channel numbers */
-#define SDPCM_CONTROL_CHANNEL	0	/* Control Request/Response Channel Id */
-#define SDPCM_EVENT_CHANNEL	1	/* Asyc Event Indication Channel Id */
-#define SDPCM_DATA_CHANNEL	2	/* Data Xmit/Recv Channel Id */
-#define SDPCM_GLOM_CHANNEL	3	/* For coalesced packets (superframes) */
-#define SDPCM_TEST_CHANNEL	15	/* Reserved for test/debug packets */
-#define SDPCM_MAX_CHANNEL	15
-
-#define SDPCM_SEQUENCE_WRAP	256	/* wrap-around val for eight-bit frame seq number */
-
-#define SDPCM_FLAG_RESVD0	0x01
-#define SDPCM_FLAG_RESVD1	0x02
-#define SDPCM_FLAG_GSPI_TXENAB	0x04
-#define SDPCM_FLAG_GLOMDESC	0x08	/* Superframe descriptor mask */
-
-/* For GLOM_CHANNEL frames, use a flag to indicate descriptor frame */
-#define SDPCM_GLOMDESC_FLAG	(SDPCM_FLAG_GLOMDESC << SDPCM_FLAGS_SHIFT)
-
-#define SDPCM_GLOMDESC(p)	(((uint8 *)p)[1] & 0x80)
-
-/* For TEST_CHANNEL packets, define another 4-byte header */
-#define SDPCM_TEST_HDRLEN		4	/* Generally: Cmd(1), Ext(1), Len(2);
-						 * Semantics of Ext byte depend on command.
-						 * Len is current or requested frame length, not
-						 * including test header; sent little-endian.
-						 */
-#define SDPCM_TEST_PKT_CNT_FLD_LEN	4	/* Packet count filed legth */
-#define SDPCM_TEST_DISCARD		0x01	/* Receiver discards. Ext is a pattern id. */
-#define SDPCM_TEST_ECHOREQ		0x02	/* Echo request. Ext is a pattern id. */
-#define SDPCM_TEST_ECHORSP		0x03	/* Echo response. Ext is a pattern id. */
-#define SDPCM_TEST_BURST		0x04	/* Receiver to send a burst. Ext is a frame count
-						 * (Backward compatabilty) Set frame count in a
-						 * 4 byte filed adjacent to the HDR
-						 */
-#define SDPCM_TEST_SEND			0x05	/* Receiver sets send mode. Ext is boolean on/off
-						 * Set frame count in a 4 byte filed adjacent to
-						 * the HDR
-						 */
-
-/* Handy macro for filling in datagen packets with a pattern */
-#define SDPCM_TEST_FILL(byteno, id)	((uint8)(id + byteno))
-
-/*
- * Software counters (first part matches hardware counters)
- */
-
-typedef volatile struct {
-	uint32 cmd52rd;		/* Cmd52RdCount, SDIO: cmd52 reads */
-	uint32 cmd52wr;		/* Cmd52WrCount, SDIO: cmd52 writes */
-	uint32 cmd53rd;		/* Cmd53RdCount, SDIO: cmd53 reads */
-	uint32 cmd53wr;		/* Cmd53WrCount, SDIO: cmd53 writes */
-	uint32 abort;		/* AbortCount, SDIO: aborts */
-	uint32 datacrcerror;	/* DataCrcErrorCount, SDIO: frames w/CRC error */
-	uint32 rdoutofsync;	/* RdOutOfSyncCount, SDIO/PCMCIA: Rd Frm out of sync */
-	uint32 wroutofsync;	/* RdOutOfSyncCount, SDIO/PCMCIA: Wr Frm out of sync */
-	uint32 writebusy;	/* WriteBusyCount, SDIO: device asserted "busy" */
-	uint32 readwait;	/* ReadWaitCount, SDIO: no data ready for a read cmd */
-	uint32 readterm;	/* ReadTermCount, SDIO: read frame termination cmds */
-	uint32 writeterm;	/* WriteTermCount, SDIO: write frames termination cmds */
-	uint32 rxdescuflo;	/* receive descriptor underflows */
-	uint32 rxfifooflo;	/* receive fifo overflows */
-	uint32 txfifouflo;	/* transmit fifo underflows */
-	uint32 runt;		/* runt (too short) frames recv'd from bus */
-	uint32 badlen;		/* frame's rxh len does not match its hw tag len */
-	uint32 badcksum;	/* frame's hw tag chksum doesn't agree with len value */
-	uint32 seqbreak;	/* break in sequence # space from one rx frame to the next */
-	uint32 rxfcrc;		/* frame rx header indicates crc error */
-	uint32 rxfwoos;		/* frame rx header indicates write out of sync */
-	uint32 rxfwft;		/* frame rx header indicates write frame termination */
-	uint32 rxfabort;	/* frame rx header indicates frame aborted */
-	uint32 woosint;		/* write out of sync interrupt */
-	uint32 roosint;		/* read out of sync interrupt */
-	uint32 rftermint;	/* read frame terminate interrupt */
-	uint32 wftermint;	/* write frame terminate interrupt */
-} sdpcmd_cnt_t;
-
-/*
- * Register Access Macros
- */
-
-#define SDIODREV_IS(var, val)	((var) == (val))
-#define SDIODREV_GE(var, val)	((var) >= (val))
-#define SDIODREV_GT(var, val)	((var) > (val))
-#define SDIODREV_LT(var, val)	((var) < (val))
-#define SDIODREV_LE(var, val)	((var) <= (val))
-
-#define SDIODDMAREG32(h, dir, chnl) \
-	((dir) == DMA_TX ? \
-	 (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].xmt) : \
-	 (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].rcv))
-
-#define SDIODDMAREG64(h, dir, chnl) \
-	((dir) == DMA_TX ? \
-	 (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].xmt) : \
-	 (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].rcv))
-
-#define SDIODDMAREG(h, dir, chnl) \
-	(SDIODREV_LT((h)->corerev, 1) ? \
-	 SDIODDMAREG32((h), (dir), (chnl)) : \
-	 SDIODDMAREG64((h), (dir), (chnl)))
-
-#define PCMDDMAREG(h, dir, chnl) \
-	((dir) == DMA_TX ? \
-	 (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.xmt) : \
-	 (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.rcv))
-
-#define SDPCMDMAREG(h, dir, chnl, coreid) \
-	((coreid) == SDIOD_CORE_ID ? \
-	 SDIODDMAREG(h, dir, chnl) : \
-	 PCMDDMAREG(h, dir, chnl))
-
-#define SDIODFIFOREG(h, corerev) \
-	(SDIODREV_LT((corerev), 1) ? \
-	 ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod32.dmafifo)) : \
-	 ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod64.dmafifo)))
-
-#define PCMDFIFOREG(h) \
-	((dma32diag_t *)(uintptr)&((h)->regs->dma.pcm32.dmafifo))
-
-#define SDPCMFIFOREG(h, coreid, corerev) \
-	((coreid) == SDIOD_CORE_ID ? \
-	 SDIODFIFOREG(h, corerev) : \
-	 PCMDFIFOREG(h))
-
-/*
- * Shared structure between dongle and the host.
- * The structure contains pointers to trap or assert information.
- */
-#define SDPCM_SHARED_VERSION       0x0001
-#define SDPCM_SHARED_VERSION_MASK  0x00FF
-#define SDPCM_SHARED_ASSERT_BUILT  0x0100
-#define SDPCM_SHARED_ASSERT        0x0200
-#define SDPCM_SHARED_TRAP          0x0400
-#define SDPCM_SHARED_IN_BRPT       0x0800
-#define SDPCM_SHARED_SET_BRPT      0x1000
-#define SDPCM_SHARED_PENDING_BRPT  0x2000
-
-typedef struct {
-	uint32	flags;
-	uint32  trap_addr;
-	uint32  assert_exp_addr;
-	uint32  assert_file_addr;
-	uint32  assert_line;
-	uint32	console_addr;		/* Address of hnd_cons_t */
-	uint32  msgtrace_addr;
-	uint32  fwid;
-} sdpcm_shared_t;
-
-extern sdpcm_shared_t sdpcm_shared;
-
-#endif	/* _bcmsdpcm_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdspi.h b/drivers/net/wireless/bcmdhd/include/bcmsdspi.h
deleted file mode 100644
index b1831db..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmsdspi.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * SD-SPI Protocol Conversion - BCMSDH->SPI Translation Layer
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsdspi.h 514727 2014-11-12 03:02:48Z $
- */
-#ifndef	_BCM_SD_SPI_H
-#define	_BCM_SD_SPI_H
-
-/* global msglevel for debug messages - bitvals come from sdiovar.h */
-
-#define sd_err(x)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-
-#define sd_log(x)
-
-#define SDIOH_ASSERT(exp) \
-	do { if (!(exp)) \
-		printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
-	} while (0)
-
-#define BLOCK_SIZE_4318 64
-#define BLOCK_SIZE_4328 512
-
-/* internal return code */
-#define SUCCESS	0
-#undef ERROR
-#define ERROR	1
-
-/* private bus modes */
-#define SDIOH_MODE_SPI		0
-
-#define USE_BLOCKMODE		0x2	/* Block mode can be single block or multi */
-#define USE_MULTIBLOCK		0x4
-
-struct sdioh_info {
-	uint cfg_bar;                   	/* pci cfg address for bar */
-	uint32 caps;                    	/* cached value of capabilities reg */
-	uint		bar0;			/* BAR0 for PCI Device */
-	osl_t 		*osh;			/* osh handler */
-	void		*controller;	/* Pointer to SPI Controller's private data struct */
-
-	uint		lockcount; 		/* nest count of sdspi_lock() calls */
-	bool		client_intr_enabled;	/* interrupt connnected flag */
-	bool		intr_handler_valid;	/* client driver interrupt handler valid */
-	sdioh_cb_fn_t	intr_handler;		/* registered interrupt handler */
-	void		*intr_handler_arg;	/* argument to call interrupt handler */
-	bool		initialized;		/* card initialized */
-	uint32		target_dev;		/* Target device ID */
-	uint32		intmask;		/* Current active interrupts */
-	void		*sdos_info;		/* Pointer to per-OS private data */
-
-	uint32		controller_type;	/* Host controller type */
-	uint8		version;		/* Host Controller Spec Compliance Version */
-	uint 		irq;			/* Client irq */
-	uint32 		intrcount;		/* Client interrupts */
-	uint32 		local_intrcount;	/* Controller interrupts */
-	bool 		host_init_done;		/* Controller initted */
-	bool 		card_init_done;		/* Client SDIO interface initted */
-	bool 		polled_mode;		/* polling for command completion */
-
-	bool		sd_use_dma;		/* DMA on CMD53 */
-	bool 		sd_blockmode;		/* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
-						/*  Must be on for sd_multiblock to be effective */
-	bool 		use_client_ints;	/* If this is false, make sure to restore */
-	bool		got_hcint;		/* Host Controller interrupt. */
-						/*  polling hack in wl_linux.c:wl_timer() */
-	int 		adapter_slot;		/* Maybe dealing with multiple slots/controllers */
-	int 		sd_mode;		/* SD1/SD4/SPI */
-	int 		client_block_size[SDIOD_MAX_IOFUNCS];		/* Blocksize */
-	uint32 		data_xfer_count;	/* Current register transfer size */
-	uint32		cmd53_wr_data;		/* Used to pass CMD53 write data */
-	uint32		card_response;		/* Used to pass back response status byte */
-	uint32		card_rsp_data;		/* Used to pass back response data word */
-	uint16 		card_rca;		/* Current Address */
-	uint8 		num_funcs;		/* Supported funcs on client */
-	uint32 		com_cis_ptr;
-	uint32 		func_cis_ptr[SDIOD_MAX_IOFUNCS];
-	void		*dma_buf;
-	ulong		dma_phys;
-	int 		r_cnt;			/* rx count */
-	int 		t_cnt;			/* tx_count */
-};
-
-/************************************************************
- * Internal interfaces: per-port references into bcmsdspi.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/**************************************************************
- * Internal interfaces: bcmsdspi.c references to per-port code
- */
-
-/* Register mapping routines */
-extern uint32 *spi_reg_map(osl_t *osh, uintptr addr, int size);
-extern void spi_reg_unmap(osl_t *osh, uintptr addr, int size);
-
-/* Interrupt (de)registration routines */
-extern int spi_register_irq(sdioh_info_t *sd, uint irq);
-extern void spi_free_irq(uint irq, sdioh_info_t *sd);
-
-/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
-extern void spi_lock(sdioh_info_t *sd);
-extern void spi_unlock(sdioh_info_t *sd);
-
-/* Allocate/init/free per-OS private data */
-extern int spi_osinit(sdioh_info_t *sd);
-extern void spi_osfree(sdioh_info_t *sd);
-
-#endif /* _BCM_SD_SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h
deleted file mode 100644
index 24df8de..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- *  'Standard' SDIO HOST CONTROLLER driver
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsdstd.h 514727 2014-11-12 03:02:48Z $
- */
-#ifndef	_BCM_SD_STD_H
-#define	_BCM_SD_STD_H
-
-/* global msglevel for debug messages - bitvals come from sdiovar.h */
-#define sd_err(x)	do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-#define sd_dma(x)
-
-#define sd_sync_dma(sd, read, nbytes)
-#define sd_init_dma(sd)
-#define sd_ack_intr(sd)
-#define sd_wakeup(sd);
-/* Allocate/init/free per-OS private data */
-extern int sdstd_osinit(sdioh_info_t *sd);
-extern void sdstd_osfree(sdioh_info_t *sd);
-
-#define sd_log(x)
-
-#define SDIOH_ASSERT(exp) \
-	do { if (!(exp)) \
-		printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
-	} while (0)
-
-#define BLOCK_SIZE_4318 64
-#define BLOCK_SIZE_4328 512
-
-/* internal return code */
-#define SUCCESS	0
-#define ERROR	1
-
-/* private bus modes */
-#define SDIOH_MODE_SPI		0
-#define SDIOH_MODE_SD1		1
-#define SDIOH_MODE_SD4		2
-
-#define MAX_SLOTS 6 	/* For PCI: Only 6 BAR entries => 6 slots */
-#define SDIOH_REG_WINSZ	0x100 /* Number of registers in Standard Host Controller */
-
-#define SDIOH_TYPE_ARASAN_HDK	1
-#define SDIOH_TYPE_BCM27XX	2
-#define SDIOH_TYPE_TI_PCIXX21	4	/* TI PCIxx21 Standard Host Controller */
-#define SDIOH_TYPE_RICOH_R5C822	5	/* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter */
-#define SDIOH_TYPE_JMICRON	6	/* JMicron Standard SDIO Host Controller */
-
-/* For linux, allow yielding for dongle */
-#define BCMSDYIELD
-
-/* Expected card status value for CMD7 */
-#define SDIOH_CMD7_EXP_STATUS   0x00001E00
-
-#define RETRIES_LARGE 100000
-#define sdstd_os_yield(sd)	do {} while (0)
-#define RETRIES_SMALL 100
-
-
-#define USE_BLOCKMODE		0x2	/* Block mode can be single block or multi */
-#define USE_MULTIBLOCK		0x4
-
-#define USE_FIFO		0x8	/* Fifo vs non-fifo */
-
-#define CLIENT_INTR 		0x100	/* Get rid of this! */
-
-#define HC_INTR_RETUNING	0x1000
-
-
-#ifdef BCMSDIOH_TXGLOM
-/* Total glom pkt can not exceed 64K
- * need one more slot for glom padding packet
- */
-#define SDIOH_MAXGLOM_SIZE	(40+1)
-
-typedef struct glom_buf {
-	uint32 count;				/* Total number of pkts queued */
-	void *dma_buf_arr[SDIOH_MAXGLOM_SIZE];	/* Frame address */
-	ulong dma_phys_arr[SDIOH_MAXGLOM_SIZE]; /* DMA_MAPed address of frames */
-	uint16 nbytes[SDIOH_MAXGLOM_SIZE];	/* Size of each frame */
-} glom_buf_t;
-#endif
-
-struct sdioh_info {
-	uint cfg_bar;                   	/* pci cfg address for bar */
-	uint32 caps;                    	/* cached value of capabilities reg */
-	uint32 curr_caps;                    	/* max current capabilities reg */
-
-	osl_t 		*osh;			/* osh handler */
-	volatile char 	*mem_space;		/* pci device memory va */
-	uint		lockcount; 		/* nest count of sdstd_lock() calls */
-	bool		client_intr_enabled;	/* interrupt connnected flag */
-	bool		intr_handler_valid;	/* client driver interrupt handler valid */
-	sdioh_cb_fn_t	intr_handler;		/* registered interrupt handler */
-	void		*intr_handler_arg;	/* argument to call interrupt handler */
-	bool		initialized;		/* card initialized */
-	uint		target_dev;		/* Target device ID */
-	uint16		intmask;		/* Current active interrupts */
-	void		*sdos_info;		/* Pointer to per-OS private data */
-	void		*bcmsdh;		/* handler to upper layer stack (bcmsdh) */
-
-	uint32		controller_type;	/* Host controller type */
-	uint8		version;		/* Host Controller Spec Compliance Version */
-	uint		irq;			/* Client irq */
-	int		intrcount;		/* Client interrupts */
-	int		local_intrcount;	/* Controller interrupts */
-	bool		host_init_done;		/* Controller initted */
-	bool		card_init_done;		/* Client SDIO interface initted */
-	bool		polled_mode;		/* polling for command completion */
-
-	bool		sd_blockmode;		/* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
-						/*  Must be on for sd_multiblock to be effective */
-	bool		use_client_ints;	/* If this is false, make sure to restore */
-						/*  polling hack in wl_linux.c:wl_timer() */
-	int		adapter_slot;		/* Maybe dealing with multiple slots/controllers */
-	int		sd_mode;		/* SD1/SD4/SPI */
-	int		client_block_size[SDIOD_MAX_IOFUNCS];		/* Blocksize */
-	uint32		data_xfer_count;	/* Current transfer */
-	uint16		card_rca;		/* Current Address */
-	int8		sd_dma_mode;		/* DMA Mode (PIO, SDMA, ... ADMA2) on CMD53 */
-	uint8		num_funcs;		/* Supported funcs on client */
-	uint32		com_cis_ptr;
-	uint32		func_cis_ptr[SDIOD_MAX_IOFUNCS];
-	void		*dma_buf;		/* DMA Buffer virtual address */
-	ulong		dma_phys;		/* DMA Buffer physical address */
-	void		*adma2_dscr_buf;	/* ADMA2 Descriptor Buffer virtual address */
-	ulong		adma2_dscr_phys;	/* ADMA2 Descriptor Buffer physical address */
-
-	/* adjustments needed to make the dma align properly */
-	void		*dma_start_buf;
-	ulong		dma_start_phys;
-	uint		alloced_dma_size;
-	void		*adma2_dscr_start_buf;
-	ulong		adma2_dscr_start_phys;
-	uint		alloced_adma2_dscr_size;
-
-	int 		r_cnt;			/* rx count */
-	int 		t_cnt;			/* tx_count */
-	bool		got_hcint;		/* local interrupt flag */
-	uint16		last_intrstatus;	/* to cache intrstatus */
-	int 	host_UHSISupported;		/* whether UHSI is supported for HC. */
-	int 	card_UHSI_voltage_Supported; 	/* whether UHSI is supported for
-						 * Card in terms of Voltage [1.8 or 3.3].
-						 */
-	int	global_UHSI_Supp;	/* type of UHSI support in both host and card.
-					 * HOST_SDR_UNSUPP: capabilities not supported/matched
-					 * HOST_SDR_12_25: SDR12 and SDR25 supported
-					 * HOST_SDR_50_104_DDR: one of SDR50/SDR104 or DDR50 supptd
-					 */
-	volatile int	sd3_dat_state; 		/* data transfer state used for retuning check */
-	volatile int	sd3_tun_state; 		/* tuning state used for retuning check */
-	bool	sd3_tuning_reqd; 	/* tuning requirement parameter */
-	uint32	caps3;			/* cached value of 32 MSbits capabilities reg (SDIO 3.0) */
-#ifdef BCMSDIOH_TXGLOM
-	glom_buf_t glom_info;		/* pkt information used for glomming */
-	uint	txglom_mode;		/* Txglom mode: 0 - copy, 1 - multi-descriptor */
-#endif
-};
-
-#define DMA_MODE_NONE	0
-#define DMA_MODE_SDMA	1
-#define DMA_MODE_ADMA1	2
-#define DMA_MODE_ADMA2	3
-#define DMA_MODE_ADMA2_64 4
-#define DMA_MODE_AUTO	-1
-
-#define USE_DMA(sd)		((bool)((sd->sd_dma_mode > 0) ? TRUE : FALSE))
-
-/* States for Tuning and corr data */
-#define TUNING_IDLE 			0
-#define TUNING_START 			1
-#define TUNING_START_AFTER_DAT 	2
-#define TUNING_ONGOING 			3
-
-#define DATA_TRANSFER_IDLE 		0
-#define DATA_TRANSFER_ONGOING	1
-
-#define CHECK_TUNING_PRE_DATA	1
-#define CHECK_TUNING_POST_DATA	2
-
-
-#ifdef DHD_DEBUG
-#define SD_DHD_DISABLE_PERIODIC_TUNING 0x01
-#define SD_DHD_ENABLE_PERIODIC_TUNING  0x00
-#endif
-
-
-/************************************************************
- * Internal interfaces: per-port references into bcmsdstd.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/* OS-independent interrupt handler */
-extern bool check_client_intr(sdioh_info_t *sd);
-
-/* Core interrupt enable/disable of device interrupts */
-extern void sdstd_devintr_on(sdioh_info_t *sd);
-extern void sdstd_devintr_off(sdioh_info_t *sd);
-
-/* Enable/disable interrupts for local controller events */
-extern void sdstd_intrs_on(sdioh_info_t *sd, uint16 norm, uint16 err);
-extern void sdstd_intrs_off(sdioh_info_t *sd, uint16 norm, uint16 err);
-
-/* Wait for specified interrupt and error bits to be set */
-extern void sdstd_spinbits(sdioh_info_t *sd, uint16 norm, uint16 err);
-
-
-/**************************************************************
- * Internal interfaces: bcmsdstd.c references to per-port code
- */
-
-/* Register mapping routines */
-extern uint32 *sdstd_reg_map(osl_t *osh, ulong addr, int size);
-extern void sdstd_reg_unmap(osl_t *osh, ulong addr, int size);
-
-/* Interrupt (de)registration routines */
-extern int sdstd_register_irq(sdioh_info_t *sd, uint irq);
-extern void sdstd_free_irq(uint irq, sdioh_info_t *sd);
-
-/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
-extern void sdstd_lock(sdioh_info_t *sd);
-extern void sdstd_unlock(sdioh_info_t *sd);
-extern void sdstd_waitlockfree(sdioh_info_t *sd);
-
-/* OS-specific wrappers for safe concurrent register access */
-extern void sdstd_os_lock_irqsave(sdioh_info_t *sd, ulong* flags);
-extern void sdstd_os_unlock_irqrestore(sdioh_info_t *sd, ulong* flags);
-
-/* OS-specific wait-for-interrupt-or-status */
-extern int sdstd_waitbits(sdioh_info_t *sd, uint16 norm, uint16 err, bool yield, uint16 *bits);
-
-/* used by bcmsdstd_linux [implemented in sdstd] */
-extern void sdstd_3_enable_retuning_int(sdioh_info_t *sd);
-extern void sdstd_3_disable_retuning_int(sdioh_info_t *sd);
-extern bool sdstd_3_is_retuning_int_set(sdioh_info_t *sd);
-extern void sdstd_3_check_and_do_tuning(sdioh_info_t *sd, int tuning_param);
-extern bool sdstd_3_check_and_set_retuning(sdioh_info_t *sd);
-extern int sdstd_3_get_tune_state(sdioh_info_t *sd);
-extern int sdstd_3_get_data_state(sdioh_info_t *sd);
-extern void sdstd_3_set_tune_state(sdioh_info_t *sd, int state);
-extern void sdstd_3_set_data_state(sdioh_info_t *sd, int state);
-extern uint8 sdstd_3_get_tuning_exp(sdioh_info_t *sd);
-extern uint32 sdstd_3_get_uhsi_clkmode(sdioh_info_t *sd);
-extern int sdstd_3_clk_tuning(sdioh_info_t *sd, uint32 sd3ClkMode);
-
-/* used by sdstd [implemented in bcmsdstd_linux/ndis] */
-extern void sdstd_3_start_tuning(sdioh_info_t *sd);
-extern void sdstd_3_osinit_tuning(sdioh_info_t *sd);
-extern void sdstd_3_osclean_tuning(sdioh_info_t *sd);
-
-extern void sdstd_enable_disable_periodic_timer(sdioh_info_t * sd, uint val);
-
-extern sdioh_info_t *sdioh_attach(osl_t *osh, void *bar0, uint irq);
-extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *sd);
-#endif /* _BCM_SD_STD_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmspi.h b/drivers/net/wireless/bcmdhd/include/bcmspi.h
deleted file mode 100644
index e9a906e..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmspi.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Broadcom SPI Low-Level Hardware Driver API
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmspi.h 514727 2014-11-12 03:02:48Z $
- */
-#ifndef	_BCM_SPI_H
-#define	_BCM_SPI_H
-
-extern void spi_devintr_off(sdioh_info_t *sd);
-extern void spi_devintr_on(sdioh_info_t *sd);
-extern bool spi_start_clock(sdioh_info_t *sd, uint16 new_sd_divisor);
-extern bool spi_controller_highspeed_mode(sdioh_info_t *sd, bool hsmode);
-extern bool spi_check_client_intr(sdioh_info_t *sd, int *is_dev_intr);
-extern bool spi_hw_attach(sdioh_info_t *sd);
-extern bool spi_hw_detach(sdioh_info_t *sd);
-extern void spi_sendrecv(sdioh_info_t *sd, uint8 *msg_out, uint8 *msg_in, int msglen);
-extern void spi_spinbits(sdioh_info_t *sd);
-extern void spi_waitbits(sdioh_info_t *sd, bool yield);
-
-#endif /* _BCM_SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h b/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h
deleted file mode 100644
index 7c2bfc4..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmspibrcm.h 514727 2014-11-12 03:02:48Z $
- */
-#ifndef	_BCM_SPI_BRCM_H
-#define	_BCM_SPI_BRCM_H
-
-#ifndef SPI_MAX_IOFUNCS
-/* Maximum number of I/O funcs */
-#define SPI_MAX_IOFUNCS		4
-#endif
-/* global msglevel for debug messages - bitvals come from sdiovar.h */
-
-#if defined(DHD_DEBUG)
-#define sd_err(x)	do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
-#define sd_trace(x)	do { if (sd_msglevel & SDH_TRACE_VAL) printf x; } while (0)
-#define sd_info(x)	do { if (sd_msglevel & SDH_INFO_VAL)  printf x; } while (0)
-#define sd_debug(x)	do { if (sd_msglevel & SDH_DEBUG_VAL) printf x; } while (0)
-#define sd_data(x)	do { if (sd_msglevel & SDH_DATA_VAL)  printf x; } while (0)
-#define sd_ctrl(x)	do { if (sd_msglevel & SDH_CTRL_VAL)  printf x; } while (0)
-#else
-#define sd_err(x)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-#endif
-
-#define sd_log(x)
-
-#define SDIOH_ASSERT(exp) \
-	do { if (!(exp)) \
-		printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
-	} while (0)
-
-#define BLOCK_SIZE_F1		64
-#define BLOCK_SIZE_F2 		2048
-#define BLOCK_SIZE_F3 		2048
-
-/* internal return code */
-#define SUCCESS	0
-#undef ERROR
-#define ERROR	1
-#define ERROR_UF	2
-#define ERROR_OF	3
-
-/* private bus modes */
-#define SDIOH_MODE_SPI		0
-
-#define USE_BLOCKMODE		0x2	/* Block mode can be single block or multi */
-#define USE_MULTIBLOCK		0x4
-
-struct sdioh_info {
-	uint		cfg_bar;		/* pci cfg address for bar */
-	uint32		caps;			/* cached value of capabilities reg */
-	void		*bar0;			/* BAR0 for PCI Device */
-	osl_t		*osh;			/* osh handler */
-	void		*controller;	/* Pointer to SPI Controller's private data struct */
-	uint		lockcount;		/* nest count of spi_lock() calls */
-	bool		client_intr_enabled;	/* interrupt connnected flag */
-	bool		intr_handler_valid;	/* client driver interrupt handler valid */
-	sdioh_cb_fn_t	intr_handler;		/* registered interrupt handler */
-	void		*intr_handler_arg;	/* argument to call interrupt handler */
-	bool		initialized;		/* card initialized */
-	uint32		target_dev;		/* Target device ID */
-	uint32		intmask;		/* Current active interrupts */
-	void		*sdos_info;		/* Pointer to per-OS private data */
-	uint32		controller_type;	/* Host controller type */
-	uint8		version;		/* Host Controller Spec Compliance Version */
-	uint		irq;			/* Client irq */
-	uint32		intrcount;		/* Client interrupts */
-	uint32		local_intrcount;	/* Controller interrupts */
-	bool 		host_init_done;		/* Controller initted */
-	bool 		card_init_done;		/* Client SDIO interface initted */
-	bool 		polled_mode;		/* polling for command completion */
-
-	bool		sd_use_dma;		/* DMA on CMD53 */
-	bool 		sd_blockmode;		/* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
-						/*  Must be on for sd_multiblock to be effective */
-	bool 		use_client_ints;	/* If this is false, make sure to restore */
-						/*  polling hack in wl_linux.c:wl_timer() */
-	int 		adapter_slot;		/* Maybe dealing with multiple slots/controllers */
-	int 		sd_mode;		/* SD1/SD4/SPI */
-	int 		client_block_size[SPI_MAX_IOFUNCS];		/* Blocksize */
-	uint32 		data_xfer_count;	/* Current transfer */
-	uint16 		card_rca;		/* Current Address */
-	uint8 		num_funcs;		/* Supported funcs on client */
-	uint32 		card_dstatus;		/* 32bit device status */
-	uint32 		com_cis_ptr;
-	uint32 		func_cis_ptr[SPI_MAX_IOFUNCS];
-	void		*dma_buf;
-	ulong		dma_phys;
-	int 		r_cnt;			/* rx count */
-	int 		t_cnt;			/* tx_count */
-	uint32		wordlen;			/* host processor 16/32bits */
-	uint32		prev_fun;
-	uint32		chip;
-	uint32		chiprev;
-	bool		resp_delay_all;
-	bool		dwordmode;
-	bool		resp_delay_new;
-
-	struct spierrstats_t spierrstats;
-};
-
-/************************************************************
- * Internal interfaces: per-port references into bcmspibrcm.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/**************************************************************
- * Internal interfaces: bcmspibrcm.c references to per-port code
- */
-
-/* Interrupt (de)registration routines */
-extern int spi_register_irq(sdioh_info_t *sd, uint irq);
-extern void spi_free_irq(uint irq, sdioh_info_t *sd);
-
-/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
-extern void spi_lock(sdioh_info_t *sd);
-extern void spi_unlock(sdioh_info_t *sd);
-
-/* Allocate/init/free per-OS private data */
-extern int spi_osinit(sdioh_info_t *sd);
-extern void spi_osfree(sdioh_info_t *sd);
-
-#define SPI_RW_FLAG_M			BITFIELD_MASK(1)	/* Bit [31] - R/W Command Bit */
-#define SPI_RW_FLAG_S			31
-#define SPI_ACCESS_M			BITFIELD_MASK(1)	/* Bit [30] - Fixed/Incr Access */
-#define SPI_ACCESS_S			30
-#define SPI_FUNCTION_M			BITFIELD_MASK(2)	/* Bit [29:28] - Function Number */
-#define SPI_FUNCTION_S			28
-#define SPI_REG_ADDR_M			BITFIELD_MASK(17)	/* Bit [27:11] - Address */
-#define SPI_REG_ADDR_S			11
-#define SPI_LEN_M			BITFIELD_MASK(11)	/* Bit [10:0] - Packet length */
-#define SPI_LEN_S			0
-
-#endif /* _BCM_SPI_BRCM_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h b/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h
deleted file mode 100644
index a40bd56..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h
+++ /dev/null
@@ -1,965 +0,0 @@
-/*
- * SROM format definition.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsrom_fmt.h 553280 2015-04-29 07:55:29Z $
- */
-
-#ifndef	_bcmsrom_fmt_h_
-#define	_bcmsrom_fmt_h_
-
-#define SROM_MAXREV		13	/* max revision supported by driver */
-
-/* Maximum srom: 12 Kilobits == 1536 bytes */
-
-#define	SROM_MAX		1536
-#define SROM_MAXW		594
-
-#ifdef LARGE_NVRAM_MAXSZ
-#define VARS_MAX                LARGE_NVRAM_MAXSZ
-#else
-#define VARS_MAX                4096
-#endif /* LARGE_NVRAM_MAXSZ */
-
-/* PCI fields */
-#define PCI_F0DEVID		48
-
-
-#define	SROM_WORDS		64
-
-#define SROM3_SWRGN_OFF		28	/* s/w region offset in words */
-
-#define	SROM_SSID		2
-#define	SROM_SVID		3
-
-#define	SROM_WL1LHMAXP		29
-
-#define	SROM_WL1LPAB0		30
-#define	SROM_WL1LPAB1		31
-#define	SROM_WL1LPAB2		32
-
-#define	SROM_WL1HPAB0		33
-#define	SROM_WL1HPAB1		34
-#define	SROM_WL1HPAB2		35
-
-#define	SROM_MACHI_IL0		36
-#define	SROM_MACMID_IL0		37
-#define	SROM_MACLO_IL0		38
-#define	SROM_MACHI_ET0		39
-#define	SROM_MACMID_ET0		40
-#define	SROM_MACLO_ET0		41
-#define	SROM_MACHI_ET1		42
-#define	SROM_MACMID_ET1		43
-#define	SROM_MACLO_ET1		44
-#define	SROM3_MACHI		37
-#define	SROM3_MACMID		38
-#define	SROM3_MACLO		39
-
-#define	SROM_BXARSSI2G		40
-#define	SROM_BXARSSI5G		41
-
-#define	SROM_TRI52G		42
-#define	SROM_TRI5GHL		43
-
-#define	SROM_RXPO52G		45
-
-#define	SROM2_ENETPHY		45
-
-#define	SROM_AABREV		46
-/* Fields in AABREV */
-#define	SROM_BR_MASK		0x00ff
-#define	SROM_CC_MASK		0x0f00
-#define	SROM_CC_SHIFT		8
-#define	SROM_AA0_MASK		0x3000
-#define	SROM_AA0_SHIFT		12
-#define	SROM_AA1_MASK		0xc000
-#define	SROM_AA1_SHIFT		14
-
-#define	SROM_WL0PAB0		47
-#define	SROM_WL0PAB1		48
-#define	SROM_WL0PAB2		49
-
-#define	SROM_LEDBH10		50
-#define	SROM_LEDBH32		51
-
-#define	SROM_WL10MAXP		52
-
-#define	SROM_WL1PAB0		53
-#define	SROM_WL1PAB1		54
-#define	SROM_WL1PAB2		55
-
-#define	SROM_ITT		56
-
-#define	SROM_BFL		57
-#define	SROM_BFL2		28
-#define	SROM3_BFL2		61
-
-#define	SROM_AG10		58
-
-#define	SROM_CCODE		59
-
-#define	SROM_OPO		60
-
-#define	SROM3_LEDDC		62
-
-#define	SROM_CRCREV		63
-
-/* SROM Rev 4: Reallocate the software part of the srom to accomodate
- * MIMO features. It assumes up to two PCIE functions and 440 bytes
- * of useable srom i.e. the useable storage in chips with OTP that
- * implements hardware redundancy.
- */
-
-#define	SROM4_WORDS		220
-
-#define	SROM4_SIGN		32
-#define	SROM4_SIGNATURE		0x5372
-
-#define	SROM4_BREV		33
-
-#define	SROM4_BFL0		34
-#define	SROM4_BFL1		35
-#define	SROM4_BFL2		36
-#define	SROM4_BFL3		37
-#define	SROM5_BFL0		37
-#define	SROM5_BFL1		38
-#define	SROM5_BFL2		39
-#define	SROM5_BFL3		40
-
-#define	SROM4_MACHI		38
-#define	SROM4_MACMID		39
-#define	SROM4_MACLO		40
-#define	SROM5_MACHI		41
-#define	SROM5_MACMID		42
-#define	SROM5_MACLO		43
-
-#define	SROM4_CCODE		41
-#define	SROM4_REGREV		42
-#define	SROM5_CCODE		34
-#define	SROM5_REGREV		35
-
-#define	SROM4_LEDBH10		43
-#define	SROM4_LEDBH32		44
-#define	SROM5_LEDBH10		59
-#define	SROM5_LEDBH32		60
-
-#define	SROM4_LEDDC		45
-#define	SROM5_LEDDC		45
-
-#define	SROM4_AA		46
-#define	SROM4_AA2G_MASK		0x00ff
-#define	SROM4_AA2G_SHIFT	0
-#define	SROM4_AA5G_MASK		0xff00
-#define	SROM4_AA5G_SHIFT	8
-
-#define	SROM4_AG10		47
-#define	SROM4_AG32		48
-
-#define	SROM4_TXPID2G		49
-#define	SROM4_TXPID5G		51
-#define	SROM4_TXPID5GL		53
-#define	SROM4_TXPID5GH		55
-
-#define SROM4_TXRXC		61
-#define SROM4_TXCHAIN_MASK	0x000f
-#define SROM4_TXCHAIN_SHIFT	0
-#define SROM4_RXCHAIN_MASK	0x00f0
-#define SROM4_RXCHAIN_SHIFT	4
-#define SROM4_SWITCH_MASK	0xff00
-#define SROM4_SWITCH_SHIFT	8
-
-
-/* Per-path fields */
-#define	MAX_PATH_SROM		4
-#define	SROM4_PATH0		64
-#define	SROM4_PATH1		87
-#define	SROM4_PATH2		110
-#define	SROM4_PATH3		133
-
-#define	SROM4_2G_ITT_MAXP	0
-#define	SROM4_2G_PA		1
-#define	SROM4_5G_ITT_MAXP	5
-#define	SROM4_5GLH_MAXP		6
-#define	SROM4_5G_PA		7
-#define	SROM4_5GL_PA		11
-#define	SROM4_5GH_PA		15
-
-/* Fields in the ITT_MAXP and 5GLH_MAXP words */
-#define	B2G_MAXP_MASK		0xff
-#define	B2G_ITT_SHIFT		8
-#define	B5G_MAXP_MASK		0xff
-#define	B5G_ITT_SHIFT		8
-#define	B5GH_MAXP_MASK		0xff
-#define	B5GL_MAXP_SHIFT		8
-
-/* All the miriad power offsets */
-#define	SROM4_2G_CCKPO		156
-#define	SROM4_2G_OFDMPO		157
-#define	SROM4_5G_OFDMPO		159
-#define	SROM4_5GL_OFDMPO	161
-#define	SROM4_5GH_OFDMPO	163
-#define	SROM4_2G_MCSPO		165
-#define	SROM4_5G_MCSPO		173
-#define	SROM4_5GL_MCSPO		181
-#define	SROM4_5GH_MCSPO		189
-#define	SROM4_CDDPO		197
-#define	SROM4_STBCPO		198
-#define	SROM4_BW40PO		199
-#define	SROM4_BWDUPPO		200
-
-#define	SROM4_CRCREV		219
-
-
-/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
- * This is acombined srom for both MIMO and SISO boards, usable in
- * the .130 4Kilobit OTP with hardware redundancy.
- */
-
-#define	SROM8_SIGN		64
-
-#define	SROM8_BREV		65
-
-#define	SROM8_BFL0		66
-#define	SROM8_BFL1		67
-#define	SROM8_BFL2		68
-#define	SROM8_BFL3		69
-
-#define	SROM8_MACHI		70
-#define	SROM8_MACMID		71
-#define	SROM8_MACLO		72
-
-#define	SROM8_CCODE		73
-#define	SROM8_REGREV		74
-
-#define	SROM8_LEDBH10		75
-#define	SROM8_LEDBH32		76
-
-#define	SROM8_LEDDC		77
-
-#define	SROM8_AA		78
-
-#define	SROM8_AG10		79
-#define	SROM8_AG32		80
-
-#define	SROM8_TXRXC		81
-
-#define	SROM8_BXARSSI2G		82
-#define	SROM8_BXARSSI5G		83
-#define	SROM8_TRI52G		84
-#define	SROM8_TRI5GHL		85
-#define	SROM8_RXPO52G		86
-
-#define SROM8_FEM2G		87
-#define SROM8_FEM5G		88
-#define SROM8_FEM_ANTSWLUT_MASK		0xf800
-#define SROM8_FEM_ANTSWLUT_SHIFT	11
-#define SROM8_FEM_TR_ISO_MASK		0x0700
-#define SROM8_FEM_TR_ISO_SHIFT		8
-#define SROM8_FEM_PDET_RANGE_MASK	0x00f8
-#define SROM8_FEM_PDET_RANGE_SHIFT	3
-#define SROM8_FEM_EXTPA_GAIN_MASK	0x0006
-#define SROM8_FEM_EXTPA_GAIN_SHIFT	1
-#define SROM8_FEM_TSSIPOS_MASK		0x0001
-#define SROM8_FEM_TSSIPOS_SHIFT		0
-
-#define SROM8_THERMAL		89
-
-/* Temp sense related entries */
-#define SROM8_MPWR_RAWTS		90
-#define SROM8_TS_SLP_OPT_CORRX	91
-/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
-#define SROM8_FOC_HWIQ_IQSWP	92
-
-#define SROM8_EXTLNAGAIN        93
-
-/* Temperature delta for PHY calibration */
-#define SROM8_PHYCAL_TEMPDELTA	94
-
-/* Measured power 1 & 2, 0-13 bits at offset 95, MSB 2 bits are unused for now. */
-#define SROM8_MPWR_1_AND_2	95
-
-
-/* Per-path offsets & fields */
-#define	SROM8_PATH0		96
-#define	SROM8_PATH1		112
-#define	SROM8_PATH2		128
-#define	SROM8_PATH3		144
-
-#define	SROM8_2G_ITT_MAXP	0
-#define	SROM8_2G_PA		1
-#define	SROM8_5G_ITT_MAXP	4
-#define	SROM8_5GLH_MAXP		5
-#define	SROM8_5G_PA		6
-#define	SROM8_5GL_PA		9
-#define	SROM8_5GH_PA		12
-
-/* All the miriad power offsets */
-#define	SROM8_2G_CCKPO		160
-
-#define	SROM8_2G_OFDMPO		161
-#define	SROM8_5G_OFDMPO		163
-#define	SROM8_5GL_OFDMPO	165
-#define	SROM8_5GH_OFDMPO	167
-
-#define	SROM8_2G_MCSPO		169
-#define	SROM8_5G_MCSPO		177
-#define	SROM8_5GL_MCSPO		185
-#define	SROM8_5GH_MCSPO		193
-
-#define	SROM8_CDDPO		201
-#define	SROM8_STBCPO		202
-#define	SROM8_BW40PO		203
-#define	SROM8_BWDUPPO		204
-
-/* SISO PA parameters are in the path0 spaces */
-#define	SROM8_SISO		96
-
-/* Legacy names for SISO PA paramters */
-#define	SROM8_W0_ITTMAXP	(SROM8_SISO + SROM8_2G_ITT_MAXP)
-#define	SROM8_W0_PAB0		(SROM8_SISO + SROM8_2G_PA)
-#define	SROM8_W0_PAB1		(SROM8_SISO + SROM8_2G_PA + 1)
-#define	SROM8_W0_PAB2		(SROM8_SISO + SROM8_2G_PA + 2)
-#define	SROM8_W1_ITTMAXP	(SROM8_SISO + SROM8_5G_ITT_MAXP)
-#define	SROM8_W1_MAXP_LCHC	(SROM8_SISO + SROM8_5GLH_MAXP)
-#define	SROM8_W1_PAB0		(SROM8_SISO + SROM8_5G_PA)
-#define	SROM8_W1_PAB1		(SROM8_SISO + SROM8_5G_PA + 1)
-#define	SROM8_W1_PAB2		(SROM8_SISO + SROM8_5G_PA + 2)
-#define	SROM8_W1_PAB0_LC	(SROM8_SISO + SROM8_5GL_PA)
-#define	SROM8_W1_PAB1_LC	(SROM8_SISO + SROM8_5GL_PA + 1)
-#define	SROM8_W1_PAB2_LC	(SROM8_SISO + SROM8_5GL_PA + 2)
-#define	SROM8_W1_PAB0_HC	(SROM8_SISO + SROM8_5GH_PA)
-#define	SROM8_W1_PAB1_HC	(SROM8_SISO + SROM8_5GH_PA + 1)
-#define	SROM8_W1_PAB2_HC	(SROM8_SISO + SROM8_5GH_PA + 2)
-
-#define	SROM8_CRCREV		219
-
-/* SROM REV 9 */
-#define SROM9_2GPO_CCKBW20	160
-#define SROM9_2GPO_CCKBW20UL	161
-#define SROM9_2GPO_LOFDMBW20	162
-#define SROM9_2GPO_LOFDMBW20UL	164
-
-#define SROM9_5GLPO_LOFDMBW20	166
-#define SROM9_5GLPO_LOFDMBW20UL	168
-#define SROM9_5GMPO_LOFDMBW20	170
-#define SROM9_5GMPO_LOFDMBW20UL	172
-#define SROM9_5GHPO_LOFDMBW20	174
-#define SROM9_5GHPO_LOFDMBW20UL	176
-
-#define SROM9_2GPO_MCSBW20	178
-#define SROM9_2GPO_MCSBW20UL	180
-#define SROM9_2GPO_MCSBW40	182
-
-#define SROM9_5GLPO_MCSBW20	184
-#define SROM9_5GLPO_MCSBW20UL	186
-#define SROM9_5GLPO_MCSBW40	188
-#define SROM9_5GMPO_MCSBW20	190
-#define SROM9_5GMPO_MCSBW20UL	192
-#define SROM9_5GMPO_MCSBW40	194
-#define SROM9_5GHPO_MCSBW20	196
-#define SROM9_5GHPO_MCSBW20UL	198
-#define SROM9_5GHPO_MCSBW40	200
-
-#define SROM9_PO_MCS32		202
-#define SROM9_PO_LOFDM40DUP	203
-#define SROM9_EU_EDCRSTH	204
-#define SROM10_EU_EDCRSTH	204
-#define SROM8_RXGAINERR_2G	205
-#define SROM8_RXGAINERR_5GL	206
-#define SROM8_RXGAINERR_5GM	207
-#define SROM8_RXGAINERR_5GH	208
-#define SROM8_RXGAINERR_5GU	209
-#define SROM8_SUBBAND_PPR	210
-#define SROM8_PCIEINGRESS_WAR	211
-#define SROM8_EU_EDCRSTH	212
-#define SROM9_SAR		212
-
-#define SROM8_NOISELVL_2G	213
-#define SROM8_NOISELVL_5GL	214
-#define SROM8_NOISELVL_5GM	215
-#define SROM8_NOISELVL_5GH	216
-#define SROM8_NOISELVL_5GU	217
-#define SROM8_NOISECALOFFSET	218
-
-#define SROM9_REV_CRC		219
-
-#define SROM10_CCKPWROFFSET	218
-#define SROM10_SIGN		219
-#define SROM10_SWCTRLMAP_2G	220
-#define SROM10_CRCREV		229
-
-#define	SROM10_WORDS		230
-#define	SROM10_SIGNATURE	SROM4_SIGNATURE
-
-
-/* SROM REV 11 */
-#define SROM11_BREV			65
-
-#define SROM11_BFL0			66
-#define SROM11_BFL1			67
-#define SROM11_BFL2			68
-#define SROM11_BFL3			69
-#define SROM11_BFL4			70
-#define SROM11_BFL5			71
-
-#define SROM11_MACHI			72
-#define SROM11_MACMID			73
-#define SROM11_MACLO			74
-
-#define SROM11_CCODE			75
-#define SROM11_REGREV			76
-
-#define SROM11_LEDBH10			77
-#define SROM11_LEDBH32			78
-
-#define SROM11_LEDDC			79
-
-#define SROM11_AA			80
-
-#define SROM11_AGBG10			81
-#define SROM11_AGBG2A0			82
-#define SROM11_AGA21			83
-
-#define SROM11_TXRXC			84
-
-#define SROM11_FEM_CFG1			85
-#define SROM11_FEM_CFG2			86
-
-/* Masks and offsets for FEM_CFG */
-#define SROM11_FEMCTRL_MASK		0xf800
-#define SROM11_FEMCTRL_SHIFT		11
-#define SROM11_PAPDCAP_MASK		0x0400
-#define SROM11_PAPDCAP_SHIFT		10
-#define SROM11_TWORANGETSSI_MASK	0x0200
-#define SROM11_TWORANGETSSI_SHIFT	9
-#define SROM11_PDGAIN_MASK		0x01f0
-#define SROM11_PDGAIN_SHIFT		4
-#define SROM11_EPAGAIN_MASK		0x000e
-#define SROM11_EPAGAIN_SHIFT		1
-#define SROM11_TSSIPOSSLOPE_MASK	0x0001
-#define SROM11_TSSIPOSSLOPE_SHIFT	0
-#define SROM11_GAINCTRLSPH_MASK		0xf800
-#define SROM11_GAINCTRLSPH_SHIFT	11
-
-#define SROM11_THERMAL			87
-#define SROM11_MPWR_RAWTS		88
-#define SROM11_TS_SLP_OPT_CORRX		89
-#define SROM11_XTAL_FREQ		90
-#define SROM11_5GB0_4080_W0_A1          91
-#define SROM11_PHYCAL_TEMPDELTA  	92
-#define SROM11_MPWR_1_AND_2 		93
-#define SROM11_5GB0_4080_W1_A1          94
-#define SROM11_TSSIFLOOR_2G 		95
-#define SROM11_TSSIFLOOR_5GL 		96
-#define SROM11_TSSIFLOOR_5GM 		97
-#define SROM11_TSSIFLOOR_5GH 		98
-#define SROM11_TSSIFLOOR_5GU 		99
-
-/* Masks and offsets for Thermal parameters */
-#define SROM11_TEMPS_PERIOD_MASK	0xf0
-#define SROM11_TEMPS_PERIOD_SHIFT	4
-#define SROM11_TEMPS_HYSTERESIS_MASK	0x0f
-#define SROM11_TEMPS_HYSTERESIS_SHIFT	0
-#define SROM11_TEMPCORRX_MASK		0xfc
-#define SROM11_TEMPCORRX_SHIFT		2
-#define SROM11_TEMPSENSE_OPTION_MASK	0x3
-#define SROM11_TEMPSENSE_OPTION_SHIFT	0
-
-#define SROM11_PDOFF_2G_40M_A0_MASK     0x000f
-#define SROM11_PDOFF_2G_40M_A0_SHIFT    0
-#define SROM11_PDOFF_2G_40M_A1_MASK     0x00f0
-#define SROM11_PDOFF_2G_40M_A1_SHIFT    4
-#define SROM11_PDOFF_2G_40M_A2_MASK     0x0f00
-#define SROM11_PDOFF_2G_40M_A2_SHIFT    8
-#define SROM11_PDOFF_2G_40M_VALID_MASK  0x8000
-#define SROM11_PDOFF_2G_40M_VALID_SHIFT 15
-
-#define SROM11_PDOFF_2G_40M     	100
-#define SROM11_PDOFF_40M_A0		101
-#define SROM11_PDOFF_40M_A1		102
-#define SROM11_PDOFF_40M_A2		103
-#define SROM11_5GB0_4080_W2_A1          103
-#define SROM11_PDOFF_80M_A0		104
-#define SROM11_PDOFF_80M_A1		105
-#define SROM11_PDOFF_80M_A2		106
-#define SROM11_5GB1_4080_W0_A1          106
-
-#define SROM11_SUBBAND5GVER 		107
-
-/* Per-path fields and offset */
-#define	MAX_PATH_SROM_11		3
-#define SROM11_PATH0			108
-#define SROM11_PATH1			128
-#define SROM11_PATH2			148
-
-#define	SROM11_2G_MAXP			0
-#define SROM11_5GB1_4080_PA             0
-#define	SROM11_2G_PA			1
-#define SROM11_5GB2_4080_PA             2
-#define	SROM11_RXGAINS1			4
-#define	SROM11_RXGAINS			5
-#define SROM11_5GB3_4080_PA             5
-#define	SROM11_5GB1B0_MAXP		6
-#define	SROM11_5GB3B2_MAXP		7
-#define	SROM11_5GB0_PA			8
-#define	SROM11_5GB1_PA			11
-#define	SROM11_5GB2_PA			14
-#define	SROM11_5GB3_PA			17
-
-/* Masks and offsets for rxgains */
-#define SROM11_RXGAINS5GTRELNABYPA_MASK		0x8000
-#define SROM11_RXGAINS5GTRELNABYPA_SHIFT	15
-#define SROM11_RXGAINS5GTRISOA_MASK		0x7800
-#define SROM11_RXGAINS5GTRISOA_SHIFT		11
-#define SROM11_RXGAINS5GELNAGAINA_MASK		0x0700
-#define SROM11_RXGAINS5GELNAGAINA_SHIFT		8
-#define SROM11_RXGAINS2GTRELNABYPA_MASK		0x0080
-#define SROM11_RXGAINS2GTRELNABYPA_SHIFT	7
-#define SROM11_RXGAINS2GTRISOA_MASK		0x0078
-#define SROM11_RXGAINS2GTRISOA_SHIFT		3
-#define SROM11_RXGAINS2GELNAGAINA_MASK		0x0007
-#define SROM11_RXGAINS2GELNAGAINA_SHIFT		0
-#define SROM11_RXGAINS5GHTRELNABYPA_MASK	0x8000
-#define SROM11_RXGAINS5GHTRELNABYPA_SHIFT	15
-#define SROM11_RXGAINS5GHTRISOA_MASK		0x7800
-#define SROM11_RXGAINS5GHTRISOA_SHIFT		11
-#define SROM11_RXGAINS5GHELNAGAINA_MASK		0x0700
-#define SROM11_RXGAINS5GHELNAGAINA_SHIFT	8
-#define SROM11_RXGAINS5GMTRELNABYPA_MASK	0x0080
-#define SROM11_RXGAINS5GMTRELNABYPA_SHIFT	7
-#define SROM11_RXGAINS5GMTRISOA_MASK		0x0078
-#define SROM11_RXGAINS5GMTRISOA_SHIFT		3
-#define SROM11_RXGAINS5GMELNAGAINA_MASK		0x0007
-#define SROM11_RXGAINS5GMELNAGAINA_SHIFT	0
-
-/* Power per rate */
-#define SROM11_CCKBW202GPO		168
-#define SROM11_CCKBW20UL2GPO		169
-#define SROM11_MCSBW202GPO		170
-#define SROM11_MCSBW202GPO_1		171
-#define SROM11_MCSBW402GPO		172
-#define SROM11_MCSBW402GPO_1		173
-#define SROM11_DOT11AGOFDMHRBW202GPO	174
-#define SROM11_OFDMLRBW202GPO		175
-
-#define SROM11_MCSBW205GLPO 		176
-#define SROM11_MCSBW205GLPO_1		177
-#define SROM11_MCSBW405GLPO 		178
-#define SROM11_MCSBW405GLPO_1		179
-#define SROM11_MCSBW805GLPO 		180
-#define SROM11_MCSBW805GLPO_1		181
-#define SROM11_RPCAL_2G			182
-#define SROM11_RPCAL_5GL		183
-#define SROM11_MCSBW205GMPO 		184
-#define SROM11_MCSBW205GMPO_1		185
-#define SROM11_MCSBW405GMPO 		186
-#define SROM11_MCSBW405GMPO_1		187
-#define SROM11_MCSBW805GMPO 		188
-#define SROM11_MCSBW805GMPO_1		189
-#define SROM11_RPCAL_5GM		190
-#define SROM11_RPCAL_5GH		191
-#define SROM11_MCSBW205GHPO 		192
-#define SROM11_MCSBW205GHPO_1		193
-#define SROM11_MCSBW405GHPO 		194
-#define SROM11_MCSBW405GHPO_1		195
-#define SROM11_MCSBW805GHPO 		196
-#define SROM11_MCSBW805GHPO_1		197
-#define SROM11_RPCAL_5GU		198
-#define SROM11_PDOFF_2G_CCK	        199
-#define SROM11_MCSLR5GLPO		200
-#define SROM11_MCSLR5GMPO		201
-#define SROM11_MCSLR5GHPO		202
-
-#define SROM11_SB20IN40HRPO		203
-#define SROM11_SB20IN80AND160HR5GLPO 	204
-#define SROM11_SB40AND80HR5GLPO		205
-#define SROM11_SB20IN80AND160HR5GMPO 	206
-#define SROM11_SB40AND80HR5GMPO		207
-#define SROM11_SB20IN80AND160HR5GHPO 	208
-#define SROM11_SB40AND80HR5GHPO		209
-#define SROM11_SB20IN40LRPO 		210
-#define SROM11_SB20IN80AND160LR5GLPO	211
-#define SROM11_SB40AND80LR5GLPO		212
-#define SROM11_TXIDXCAP2G               212
-#define SROM11_SB20IN80AND160LR5GMPO	213
-#define SROM11_SB40AND80LR5GMPO		214
-#define SROM11_TXIDXCAP5G               214
-#define SROM11_SB20IN80AND160LR5GHPO	215
-#define SROM11_SB40AND80LR5GHPO		216
-
-#define SROM11_DOT11AGDUPHRPO 		217
-#define SROM11_DOT11AGDUPLRPO		218
-
-/* MISC */
-#define SROM11_PCIEINGRESS_WAR		220
-#define SROM11_SAR			221
-
-#define SROM11_NOISELVL_2G		222
-#define SROM11_NOISELVL_5GL 		223
-#define SROM11_NOISELVL_5GM 		224
-#define SROM11_NOISELVL_5GH 		225
-#define SROM11_NOISELVL_5GU 		226
-
-#define SROM11_RXGAINERR_2G		227
-#define SROM11_RXGAINERR_5GL		228
-#define SROM11_RXGAINERR_5GM		229
-#define SROM11_RXGAINERR_5GH		230
-#define SROM11_RXGAINERR_5GU		231
-
-#define SROM11_EU_EDCRSTH	        232
-#define SROM12_EU_EDCRSTH	        232
-
-#define SROM11_SIGN 			64
-#define SROM11_CRCREV 			233
-
-#define	SROM11_WORDS				234
-#define	SROM11_SIGNATURE		0x0634
-
-
-/* SROM REV 12 */
-#define SROM12_SIGN                     64
-#define SROM12_WORDS			512
-#define SROM12_SIGNATURE		0x8888
-#define SROM12_CRCREV			511
-
-#define SROM12_BFL6				486
-#define SROM12_BFL7				487
-
-#define SROM12_MCSBW205GX1PO		234
-#define SROM12_MCSBW205GX1PO_1		235
-#define SROM12_MCSBW405GX1PO		236
-#define SROM12_MCSBW405GX1PO_1		237
-#define SROM12_MCSBW805GX1PO		238
-#define SROM12_MCSBW805GX1PO_1		239
-#define SROM12_MCSLR5GX1PO			240
-#define SROM12_SB40AND80LR5GX1PO		241
-#define SROM12_SB20IN80AND160LR5GX1PO	242
-#define SROM12_SB20IN80AND160HR5GX1PO	243
-#define SROM12_SB40AND80HR5GX1PO		244
-
-#define SROM12_MCSBW205GX2PO		245
-#define SROM12_MCSBW205GX2PO_1		246
-#define SROM12_MCSBW405GX2PO		247
-#define SROM12_MCSBW405GX2PO_1		248
-#define SROM12_MCSBW805GX2PO		249
-#define SROM12_MCSBW805GX2PO_1		250
-#define SROM12_MCSLR5GX2PO			251
-#define SROM12_SB40AND80LR5GX2PO	252
-#define SROM12_SB20IN80AND160LR5GX2PO	253
-#define SROM12_SB20IN80AND160HR5GX2PO	254
-#define SROM12_SB40AND80HR5GX2PO		255
-
-/* MISC */
-#define	SROM12_RXGAINS10			483
-#define	SROM12_RXGAINS11			484
-#define	SROM12_RXGAINS12			485
-
-/* Per-path fields and offset */
-#define	MAX_PATH_SROM_12			3
-#define SROM12_PATH0				256
-#define SROM12_PATH1				328
-#define SROM12_PATH2				400
-
-#define	SROM12_5GB42G_MAXP				0
-#define SROM12_2GB0_PA					1
-#define SROM12_2GB0_PA_W0				1
-#define SROM12_2GB0_PA_W1				2
-#define SROM12_2GB0_PA_W2				3
-#define SROM12_2GB0_PA_W3				4
-
-#define	SROM12_RXGAINS					5
-#define	SROM12_5GB1B0_MAXP				6
-#define	SROM12_5GB3B2_MAXP				7
-
-#define SROM12_5GB0_PA					8
-#define SROM12_5GB0_PA_W0				8
-#define SROM12_5GB0_PA_W1				9
-#define SROM12_5GB0_PA_W2				10
-#define SROM12_5GB0_PA_W3				11
-
-#define SROM12_5GB1_PA					12
-#define SROM12_5GB1_PA_W0				12
-#define SROM12_5GB1_PA_W1				13
-#define SROM12_5GB1_PA_W2				14
-#define SROM12_5GB1_PA_W3				15
-
-#define SROM12_5GB2_PA					16
-#define SROM12_5GB2_PA_W0				16
-#define SROM12_5GB2_PA_W1				17
-#define SROM12_5GB2_PA_W2				18
-#define SROM12_5GB2_PA_W3				19
-
-#define SROM12_5GB3_PA					20
-#define SROM12_5GB3_PA_W0				20
-#define SROM12_5GB3_PA_W1				21
-#define SROM12_5GB3_PA_W2				22
-#define SROM12_5GB3_PA_W3				23
-
-#define SROM12_5GB4_PA					24
-#define SROM12_5GB4_PA_W0				24
-#define SROM12_5GB4_PA_W1				25
-#define SROM12_5GB4_PA_W2				26
-#define SROM12_5GB4_PA_W3				27
-
-#define SROM12_2G40B0_PA				28
-#define SROM12_2G40B0_PA_W0				28
-#define SROM12_2G40B0_PA_W1				29
-#define SROM12_2G40B0_PA_W2				30
-#define SROM12_2G40B0_PA_W3				31
-
-#define SROM12_5G40B0_PA				32
-#define SROM12_5G40B0_PA_W0				32
-#define SROM12_5G40B0_PA_W1				33
-#define SROM12_5G40B0_PA_W2				34
-#define SROM12_5G40B0_PA_W3				35
-
-#define SROM12_5G40B1_PA				36
-#define SROM12_5G40B1_PA_W0				36
-#define SROM12_5G40B1_PA_W1				37
-#define SROM12_5G40B1_PA_W2				38
-#define SROM12_5G40B1_PA_W3				39
-
-#define SROM12_5G40B2_PA				40
-#define SROM12_5G40B2_PA_W0				40
-#define SROM12_5G40B2_PA_W1				41
-#define SROM12_5G40B2_PA_W2				42
-#define SROM12_5G40B2_PA_W3				43
-
-#define SROM12_5G40B3_PA				44
-#define SROM12_5G40B3_PA_W0				44
-#define SROM12_5G40B3_PA_W1				45
-#define SROM12_5G40B3_PA_W2				46
-#define SROM12_5G40B3_PA_W3				47
-
-#define SROM12_5G40B4_PA				48
-#define SROM12_5G40B4_PA_W0				48
-#define SROM12_5G40B4_PA_W1				49
-#define SROM12_5G40B4_PA_W2				50
-#define SROM12_5G40B4_PA_W3				51
-
-#define SROM12_5G80B0_PA				52
-#define SROM12_5G80B0_PA_W0				52
-#define SROM12_5G80B0_PA_W1				53
-#define SROM12_5G80B0_PA_W2				54
-#define SROM12_5G80B0_PA_W3				55
-
-#define SROM12_5G80B1_PA				56
-#define SROM12_5G80B1_PA_W0				56
-#define SROM12_5G80B1_PA_W1				57
-#define SROM12_5G80B1_PA_W2				58
-#define SROM12_5G80B1_PA_W3				59
-
-#define SROM12_5G80B2_PA				60
-#define SROM12_5G80B2_PA_W0				60
-#define SROM12_5G80B2_PA_W1				61
-#define SROM12_5G80B2_PA_W2				62
-#define SROM12_5G80B2_PA_W3				63
-
-#define SROM12_5G80B3_PA				64
-#define SROM12_5G80B3_PA_W0				64
-#define SROM12_5G80B3_PA_W1				65
-#define SROM12_5G80B3_PA_W2				66
-#define SROM12_5G80B3_PA_W3				67
-
-#define SROM12_5G80B4_PA				68
-#define SROM12_5G80B4_PA_W0				68
-#define SROM12_5G80B4_PA_W1				69
-#define SROM12_5G80B4_PA_W2				70
-#define SROM12_5G80B4_PA_W3				71
-
-/* PD offset */
-#define SROM12_PDOFF_2G_CCK				472
-
-#define SROM12_PDOFF_20in40M_5G_B0		473
-#define SROM12_PDOFF_20in40M_5G_B1		474
-#define SROM12_PDOFF_20in40M_5G_B2		475
-#define SROM12_PDOFF_20in40M_5G_B3		476
-#define SROM12_PDOFF_20in40M_5G_B4		477
-
-#define SROM12_PDOFF_40in80M_5G_B0		478
-#define SROM12_PDOFF_40in80M_5G_B1		479
-#define SROM12_PDOFF_40in80M_5G_B2		480
-#define SROM12_PDOFF_40in80M_5G_B3		481
-#define SROM12_PDOFF_40in80M_5G_B4		482
-
-#define SROM12_PDOFF_20in80M_5G_B0		488
-#define SROM12_PDOFF_20in80M_5G_B1		489
-#define SROM12_PDOFF_20in80M_5G_B2		490
-#define SROM12_PDOFF_20in80M_5G_B3		491
-#define SROM12_PDOFF_20in80M_5G_B4		492
-
-#define SROM13_PDOFFSET20IN40M5GCORE3           98
-#define SROM13_PDOFFSET20IN40M5GCORE3_1         99
-#define SROM13_PDOFFSET20IN80M5GCORE3           510
-#define SROM13_PDOFFSET20IN80M5GCORE3_1         511
-#define SROM13_PDOFFSET40IN80M5GCORE3           105
-#define SROM13_PDOFFSET40IN80M5GCORE3_1         106
-
-#define SROM13_PDOFFSET20IN40M2G                94
-#define SROM13_PDOFFSET20IN40M2GCORE3           95
-
-#define SROM12_GPDN_L				91  /* GPIO pull down bits [15:0]  */
-#define SROM12_GPDN_H				233 /* GPIO pull down bits [31:16] */
-
-#define SROM13_SIGN                     64
-#define SROM13_WORDS                    590
-#define SROM13_SIGNATURE                0x4d55
-#define SROM13_CRCREV                   589
-
-
-/* Per-path fields and offset */
-#define MAX_PATH_SROM_13                        4
-#define SROM13_PATH0                            256
-#define SROM13_PATH1                            328
-#define SROM13_PATH2                            400
-#define SROM13_PATH3                            512
-#define SROM13_RXGAINS                         5
-
-#define SROM13_XTALFREQ                 90
-
-#define SROM13_PDOFFSET20IN40M2G        94
-#define SROM13_PDOFFSET20IN40M2GCORE3   95
-#define SROM13_SB20IN40HRLRPOX          96
-
-#define SROM13_RXGAINS1CORE3            97
-
-#define SROM13_PDOFFSET20IN40M5GCORE3   98
-#define SROM13_PDOFFSET20IN40M5GCORE3_1 99
-
-#define SROM13_ANTGAIN_BANDBGA          100
-
-#define SROM13_RXGAINS2CORE0            101
-#define SROM13_RXGAINS2CORE1            102
-#define SROM13_RXGAINS2CORE2            103
-#define SROM13_RXGAINS2CORE3            104
-
-#define SROM13_PDOFFSET40IN80M5GCORE3   105
-#define SROM13_PDOFFSET40IN80M5GCORE3_1 106
-
-/* power per rate */
-#define SROM13_MCS1024QAM2GPO           108
-#define SROM13_MCS1024QAM5GLPO          109
-#define SROM13_MCS1024QAM5GLPO_1        110
-#define SROM13_MCS1024QAM5GMPO          111
-#define SROM13_MCS1024QAM5GMPO_1        112
-#define SROM13_MCS1024QAM5GHPO          113
-#define SROM13_MCS1024QAM5GHPO_1        114
-#define SROM13_MCS1024QAM5GX1PO         115
-#define SROM13_MCS1024QAM5GX1PO_1       116
-#define SROM13_MCS1024QAM5GX2PO         117
-#define SROM13_MCS1024QAM5GX2PO_1       118
-
-#define SROM13_MCSBW1605GLPO            119
-#define SROM13_MCSBW1605GLPO_1          120
-#define SROM13_MCSBW1605GMPO            121
-#define SROM13_MCSBW1605GMPO_1          122
-#define SROM13_MCSBW1605GHPO            123
-#define SROM13_MCSBW1605GHPO_1          124
-
-#define SROM13_MCSBW1605GX1PO           125
-#define SROM13_MCSBW1605GX1PO_1         126
-#define SROM13_MCSBW1605GX2PO           127
-#define SROM13_MCSBW1605GX2PO_1         128
-
-#define SROM13_ULBPPROFFS5GB0		129
-#define SROM13_ULBPPROFFS5GB1           130
-#define SROM13_ULBPPROFFS5GB2           131
-#define SROM13_ULBPPROFFS5GB3           132
-#define SROM13_ULBPPROFFS5GB4           133
-#define SROM13_ULBPPROFFS2G		134
-
-#define SROM13_MCS8POEXP                135
-#define SROM13_MCS8POEXP_1              136
-#define SROM13_MCS9POEXP                137
-#define SROM13_MCS9POEXP_1              138
-#define SROM13_MCS10POEXP               139
-#define SROM13_MCS10POEXP_1             140
-#define SROM13_MCS11POEXP               141
-#define SROM13_MCS11POEXP_1             142
-#define SROM13_ULBPDOFFS5GB0A0		143
-#define SROM13_ULBPDOFFS5GB0A1          144
-#define SROM13_ULBPDOFFS5GB0A2          145
-#define SROM13_ULBPDOFFS5GB0A3          146
-#define SROM13_ULBPDOFFS5GB1A0          147
-#define SROM13_ULBPDOFFS5GB1A1          148
-#define SROM13_ULBPDOFFS5GB1A2          149
-#define SROM13_ULBPDOFFS5GB1A3          150
-#define SROM13_ULBPDOFFS5GB2A0          151
-#define SROM13_ULBPDOFFS5GB2A1          152
-#define SROM13_ULBPDOFFS5GB2A2          153
-#define SROM13_ULBPDOFFS5GB2A3          154
-#define SROM13_ULBPDOFFS5GB3A0          155
-#define SROM13_ULBPDOFFS5GB3A1          156
-#define SROM13_ULBPDOFFS5GB3A2          157
-#define SROM13_ULBPDOFFS5GB3A3          158
-#define SROM13_ULBPDOFFS5GB4A0          159
-#define SROM13_ULBPDOFFS5GB4A1          160
-#define SROM13_ULBPDOFFS5GB4A2          161
-#define SROM13_ULBPDOFFS5GB4A3          162
-#define SROM13_ULBPDOFFS2GA0		163
-#define SROM13_ULBPDOFFS2GA1		164
-#define SROM13_ULBPDOFFS2GA2		165
-#define SROM13_ULBPDOFFS2GA3		166
-
-#define SROM13_RPCAL5GB4                199
-
-#define SROM13_EU_EDCRSTH               232
-
-#define SROM13_SWCTRLMAP4_CFG			493
-#define SROM13_SWCTRLMAP4_TX2G_FEM3TO0		494
-#define SROM13_SWCTRLMAP4_RX2G_FEM3TO0		495
-#define SROM13_SWCTRLMAP4_RXBYP2G_FEM3TO0	496
-#define SROM13_SWCTRLMAP4_MISC2G_FEM3TO0	497
-#define SROM13_SWCTRLMAP4_TX5G_FEM3TO0		498
-#define SROM13_SWCTRLMAP4_RX5G_FEM3TO0		499
-#define SROM13_SWCTRLMAP4_RXBYP5G_FEM3TO0	500
-#define SROM13_SWCTRLMAP4_MISC5G_FEM3TO0	501
-#define SROM13_SWCTRLMAP4_TX2G_FEM7TO4		502
-#define SROM13_SWCTRLMAP4_RX2G_FEM7TO4		503
-#define SROM13_SWCTRLMAP4_RXBYP2G_FEM7TO4	504
-#define SROM13_SWCTRLMAP4_MISC2G_FEM7TO4	505
-#define SROM13_SWCTRLMAP4_TX5G_FEM7TO4		506
-#define SROM13_SWCTRLMAP4_RX5G_FEM7TO4		507
-#define SROM13_SWCTRLMAP4_RXBYP5G_FEM7TO4	508
-#define SROM13_SWCTRLMAP4_MISC5G_FEM7TO4	509
-
-#define SROM13_PDOFFSET20IN80M5GCORE3   510
-#define SROM13_PDOFFSET20IN80M5GCORE3_1 511
-
-#define SROM13_NOISELVLCORE3            584
-#define SROM13_NOISELVLCORE3_1          585
-#define SROM13_RXGAINERRCORE3           586
-#define SROM13_RXGAINERRCORE3_1         587
-
-
-typedef struct {
-	uint8 tssipos;		/* TSSI positive slope, 1: positive, 0: negative */
-	uint8 extpagain;	/* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
-	uint8 pdetrange;	/* support 32 combinations of different Pdet dynamic ranges */
-	uint8 triso;		/* TR switch isolation */
-	uint8 antswctrllut;	/* antswctrl lookup table configuration: 32 possible choices */
-} srom_fem_t;
-
-#endif	/* _bcmsrom_fmt_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h b/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h
deleted file mode 100644
index f2775fb..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h
+++ /dev/null
@@ -1,1400 +0,0 @@
-/*
- * Table that encodes the srom formats for PCI/PCIe NICs.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmsrom_tbl.h 553564 2015-04-30 06:19:30Z $
- */
-
-#ifndef	_bcmsrom_tbl_h_
-#define	_bcmsrom_tbl_h_
-
-#include "sbpcmcia.h"
-#include "wlioctl.h"
-#include <bcmsrom_fmt.h>
-
-typedef struct {
-	const char *name;
-	uint32	revmask;
-	uint32	flags;
-	uint16	off;
-	uint16	mask;
-} sromvar_t;
-
-#define SRFL_MORE	1		/* value continues as described by the next entry */
-#define	SRFL_NOFFS	2		/* value bits can't be all one's */
-#define	SRFL_PRHEX	4		/* value is in hexdecimal format */
-#define	SRFL_PRSIGN	8		/* value is in signed decimal format */
-#define	SRFL_CCODE	0x10		/* value is in country code format */
-#define	SRFL_ETHADDR	0x20		/* value is an Ethernet address */
-#define SRFL_LEDDC	0x40		/* value is an LED duty cycle */
-#define SRFL_NOVAR	0x80		/* do not generate a nvram param, entry is for mfgc */
-#define SRFL_ARRAY	0x100		/* value is in an array. All elements EXCEPT FOR THE LAST
-					 * ONE in the array should have this flag set.
-					 */
-
-
-#define SROM_DEVID_PCIE	48
-
-/**
- * Assumptions:
- * - Ethernet address spans across 3 consecutive words
- *
- * Table rules:
- * - Add multiple entries next to each other if a value spans across multiple words
- *   (even multiple fields in the same word) with each entry except the last having
- *   it's SRFL_MORE bit set.
- * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
- *   bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
- * - The last entry's name field must be NULL to indicate the end of the table. Other
- *   entries must have non-NULL name.
- */
-static const sromvar_t pci_sromvars[] = {
-/*	name		revmask		flags		off			mask */
-#if defined(CABLECPE)
-	{"devid",	0xffffff00,	SRFL_PRHEX,	PCI_F0DEVID,		0xffff},
-#elif defined(BCMPCIEDEV) && defined(BCMPCIEDEV_ENABLED)
-	{"devid",	0xffffff00,	SRFL_PRHEX, SROM_DEVID_PCIE,		0xffff},
-#else
-	{"devid",	0xffffff00,	SRFL_PRHEX|SRFL_NOVAR,	PCI_F0DEVID,	0xffff},
-#endif 
-	{"boardrev",	0x0000000e,	SRFL_PRHEX,	SROM_AABREV,		SROM_BR_MASK},
-	{"boardrev",	0x000000f0,	SRFL_PRHEX,	SROM4_BREV,		0xffff},
-	{"boardrev",	0xffffff00,	SRFL_PRHEX,	SROM8_BREV,		0xffff},
-	{"boardflags",	0x00000002,	SRFL_PRHEX,	SROM_BFL,		0xffff},
-	{"boardflags",	0x00000004,	SRFL_PRHEX|SRFL_MORE,	SROM_BFL,	0xffff},
-	{"",		0,		0,		SROM_BFL2,		0xffff},
-	{"boardflags",	0x00000008,	SRFL_PRHEX|SRFL_MORE,	SROM_BFL,	0xffff},
-	{"",		0,		0,		SROM3_BFL2,		0xffff},
-	{"boardflags",	0x00000010,	SRFL_PRHEX|SRFL_MORE,	SROM4_BFL0,	0xffff},
-	{"",		0,		0,		SROM4_BFL1,		0xffff},
-	{"boardflags",	0x000000e0,	SRFL_PRHEX|SRFL_MORE,	SROM5_BFL0,	0xffff},
-	{"",		0,		0,		SROM5_BFL1,		0xffff},
-	{"boardflags",	0xffffff00,	SRFL_PRHEX|SRFL_MORE,	SROM8_BFL0,	0xffff},
-	{"",		0,		0,		SROM8_BFL1,		0xffff},
-	{"boardflags2", 0x00000010,	SRFL_PRHEX|SRFL_MORE,	SROM4_BFL2,	0xffff},
-	{"",		0,		0,		SROM4_BFL3,		0xffff},
-	{"boardflags2", 0x000000e0,	SRFL_PRHEX|SRFL_MORE,	SROM5_BFL2,	0xffff},
-	{"",		0,		0,		SROM5_BFL3,		0xffff},
-	{"boardflags2", 0xffffff00,	SRFL_PRHEX|SRFL_MORE,	SROM8_BFL2,	0xffff},
-	{"",		0,		0,		SROM8_BFL3,		0xffff},
-	{"boardtype",	0xfffffffc,	SRFL_PRHEX,	SROM_SSID,		0xffff},
-	{"subvid",	0xfffffffc,	SRFL_PRHEX,	SROM_SVID,		0xffff},
-	{"boardnum",	0x00000006,	0,		SROM_MACLO_IL0,		0xffff},
-	{"boardnum",	0x00000008,	0,		SROM3_MACLO,		0xffff},
-	{"boardnum",	0x00000010,	0,		SROM4_MACLO,		0xffff},
-	{"boardnum",	0x000000e0,	0,		SROM5_MACLO,		0xffff},
-	{"boardnum",	0x00000700,	0,		SROM8_MACLO,		0xffff},
-	{"cc",		0x00000002,	0,		SROM_AABREV,		SROM_CC_MASK},
-	{"regrev",	0x00000008,	0,		SROM_OPO,		0xff00},
-	{"regrev",	0x00000010,	0,		SROM4_REGREV,		0x00ff},
-	{"regrev",	0x000000e0,	0,		SROM5_REGREV,		0x00ff},
-	{"regrev",	0x00000700,	0,		SROM8_REGREV,		0x00ff},
-	{"ledbh0",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH10,		0x00ff},
-	{"ledbh1",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH10,		0xff00},
-	{"ledbh2",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH32,		0x00ff},
-	{"ledbh3",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH32,		0xff00},
-	{"ledbh0",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH10,		0x00ff},
-	{"ledbh1",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH10,		0xff00},
-	{"ledbh2",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH32,		0x00ff},
-	{"ledbh3",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH32,		0xff00},
-	{"ledbh0",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH10,		0x00ff},
-	{"ledbh1",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH10,		0xff00},
-	{"ledbh2",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH32,		0x00ff},
-	{"ledbh3",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH32,		0xff00},
-	{"ledbh0",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH10,		0x00ff},
-	{"ledbh1",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH10,		0xff00},
-	{"ledbh2",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH32,		0x00ff},
-	{"ledbh3",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH32,		0xff00},
-	{"pa0b0",	0x0000000e,	SRFL_PRHEX,	SROM_WL0PAB0,		0xffff},
-	{"pa0b1",	0x0000000e,	SRFL_PRHEX,	SROM_WL0PAB1,		0xffff},
-	{"pa0b2",	0x0000000e,	SRFL_PRHEX,	SROM_WL0PAB2,		0xffff},
-	{"pa0itssit",	0x0000000e,	0,		SROM_ITT,		0x00ff},
-	{"pa0maxpwr",	0x0000000e,	0,		SROM_WL10MAXP,		0x00ff},
-	{"pa0b0",	0x00000700,	SRFL_PRHEX,	SROM8_W0_PAB0,		0xffff},
-	{"pa0b1",	0x00000700,	SRFL_PRHEX,	SROM8_W0_PAB1,		0xffff},
-	{"pa0b2",	0x00000700,	SRFL_PRHEX,	SROM8_W0_PAB2,		0xffff},
-	{"pa0itssit",	0x00000700,	0,		SROM8_W0_ITTMAXP,	0xff00},
-	{"pa0maxpwr",	0x00000700,	0,		SROM8_W0_ITTMAXP,	0x00ff},
-	{"opo",		0x0000000c,	0,		SROM_OPO,		0x00ff},
-	{"opo",		0x00000700,	0,		SROM8_2G_OFDMPO,	0x00ff},
-	{"aa2g",	0x0000000e,	0,		SROM_AABREV,		SROM_AA0_MASK},
-	{"aa2g",	0x000000f0,	0,		SROM4_AA,		0x00ff},
-	{"aa2g",	0x00000700,	0,		SROM8_AA,		0x00ff},
-	{"aa5g",	0x0000000e,	0,		SROM_AABREV,		SROM_AA1_MASK},
-	{"aa5g",	0x000000f0,	0,		SROM4_AA,		0xff00},
-	{"aa5g",	0x00000700,	0,		SROM8_AA,		0xff00},
-	{"ag0",		0x0000000e,	0,		SROM_AG10,		0x00ff},
-	{"ag1",		0x0000000e,	0,		SROM_AG10,		0xff00},
-	{"ag0",		0x000000f0,	0,		SROM4_AG10,		0x00ff},
-	{"ag1",		0x000000f0,	0,		SROM4_AG10,		0xff00},
-	{"ag2",		0x000000f0,	0,		SROM4_AG32,		0x00ff},
-	{"ag3",		0x000000f0,	0,		SROM4_AG32,		0xff00},
-	{"ag0",		0x00000700,	0,		SROM8_AG10,		0x00ff},
-	{"ag1",		0x00000700,	0,		SROM8_AG10,		0xff00},
-	{"ag2",		0x00000700,	0,		SROM8_AG32,		0x00ff},
-	{"ag3",		0x00000700,	0,		SROM8_AG32,		0xff00},
-	{"pa1b0",	0x0000000e,	SRFL_PRHEX,	SROM_WL1PAB0,		0xffff},
-	{"pa1b1",	0x0000000e,	SRFL_PRHEX,	SROM_WL1PAB1,		0xffff},
-	{"pa1b2",	0x0000000e,	SRFL_PRHEX,	SROM_WL1PAB2,		0xffff},
-	{"pa1lob0",	0x0000000c,	SRFL_PRHEX,	SROM_WL1LPAB0,		0xffff},
-	{"pa1lob1",	0x0000000c,	SRFL_PRHEX,	SROM_WL1LPAB1,		0xffff},
-	{"pa1lob2",	0x0000000c,	SRFL_PRHEX,	SROM_WL1LPAB2,		0xffff},
-	{"pa1hib0",	0x0000000c,	SRFL_PRHEX,	SROM_WL1HPAB0,		0xffff},
-	{"pa1hib1",	0x0000000c,	SRFL_PRHEX,	SROM_WL1HPAB1,		0xffff},
-	{"pa1hib2",	0x0000000c,	SRFL_PRHEX,	SROM_WL1HPAB2,		0xffff},
-	{"pa1itssit",	0x0000000e,	0,		SROM_ITT,		0xff00},
-	{"pa1maxpwr",	0x0000000e,	0,		SROM_WL10MAXP,		0xff00},
-	{"pa1lomaxpwr",	0x0000000c,	0,		SROM_WL1LHMAXP,		0xff00},
-	{"pa1himaxpwr",	0x0000000c,	0,		SROM_WL1LHMAXP,		0x00ff},
-	{"pa1b0",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB0,		0xffff},
-	{"pa1b1",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB1,		0xffff},
-	{"pa1b2",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB2,		0xffff},
-	{"pa1lob0",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB0_LC,	0xffff},
-	{"pa1lob1",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB1_LC,	0xffff},
-	{"pa1lob2",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB2_LC,	0xffff},
-	{"pa1hib0",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB0_HC,	0xffff},
-	{"pa1hib1",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB1_HC,	0xffff},
-	{"pa1hib2",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB2_HC,	0xffff},
-	{"pa1itssit",	0x00000700,	0,		SROM8_W1_ITTMAXP,	0xff00},
-	{"pa1maxpwr",	0x00000700,	0,		SROM8_W1_ITTMAXP,	0x00ff},
-	{"pa1lomaxpwr",	0x00000700,	0,		SROM8_W1_MAXP_LCHC,	0xff00},
-	{"pa1himaxpwr",	0x00000700,	0,		SROM8_W1_MAXP_LCHC,	0x00ff},
-	{"bxa2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x1800},
-	{"rssisav2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x0700},
-	{"rssismc2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x00f0},
-	{"rssismf2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x000f},
-	{"bxa2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x1800},
-	{"rssisav2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x0700},
-	{"rssismc2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x00f0},
-	{"rssismf2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x000f},
-	{"bxa5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x1800},
-	{"rssisav5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x0700},
-	{"rssismc5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x00f0},
-	{"rssismf5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x000f},
-	{"bxa5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x1800},
-	{"rssisav5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x0700},
-	{"rssismc5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x00f0},
-	{"rssismf5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x000f},
-	{"tri2g",	0x00000008,	0,		SROM_TRI52G,		0x00ff},
-	{"tri5g",	0x00000008,	0,		SROM_TRI52G,		0xff00},
-	{"tri5gl",	0x00000008,	0,		SROM_TRI5GHL,		0x00ff},
-	{"tri5gh",	0x00000008,	0,		SROM_TRI5GHL,		0xff00},
-	{"tri2g",	0x00000700,	0,		SROM8_TRI52G,		0x00ff},
-	{"tri5g",	0x00000700,	0,		SROM8_TRI52G,		0xff00},
-	{"tri5gl",	0x00000700,	0,		SROM8_TRI5GHL,		0x00ff},
-	{"tri5gh",	0x00000700,	0,		SROM8_TRI5GHL,		0xff00},
-	{"rxpo2g",	0x00000008,	SRFL_PRSIGN,	SROM_RXPO52G,		0x00ff},
-	{"rxpo5g",	0x00000008,	SRFL_PRSIGN,	SROM_RXPO52G,		0xff00},
-	{"rxpo2g",	0x00000700,	SRFL_PRSIGN,	SROM8_RXPO52G,		0x00ff},
-	{"rxpo5g",	0x00000700,	SRFL_PRSIGN,	SROM8_RXPO52G,		0xff00},
-	{"txchain",	0x000000f0,	SRFL_NOFFS,	SROM4_TXRXC,		SROM4_TXCHAIN_MASK},
-	{"rxchain",	0x000000f0,	SRFL_NOFFS,	SROM4_TXRXC,		SROM4_RXCHAIN_MASK},
-	{"antswitch",	0x000000f0,	SRFL_NOFFS,	SROM4_TXRXC,		SROM4_SWITCH_MASK},
-	{"txchain",	0x00000700,	SRFL_NOFFS,	SROM8_TXRXC,		SROM4_TXCHAIN_MASK},
-	{"rxchain",	0x00000700,	SRFL_NOFFS,	SROM8_TXRXC,		SROM4_RXCHAIN_MASK},
-	{"antswitch",	0x00000700,	SRFL_NOFFS,	SROM8_TXRXC,		SROM4_SWITCH_MASK},
-	{"tssipos2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_TSSIPOS_MASK},
-	{"extpagain2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_EXTPA_GAIN_MASK},
-	{"pdetrange2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_PDET_RANGE_MASK},
-	{"triso2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_TR_ISO_MASK},
-	{"antswctl2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_ANTSWLUT_MASK},
-	{"tssipos5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_TSSIPOS_MASK},
-	{"extpagain5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_EXTPA_GAIN_MASK},
-	{"pdetrange5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_PDET_RANGE_MASK},
-	{"triso5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_TR_ISO_MASK},
-	{"antswctl5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_ANTSWLUT_MASK},
-	{"txpid2ga0",	0x000000f0,	0,		SROM4_TXPID2G,		0x00ff},
-	{"txpid2ga1",	0x000000f0,	0,		SROM4_TXPID2G,		0xff00},
-	{"txpid2ga2",	0x000000f0,	0,		SROM4_TXPID2G + 1,	0x00ff},
-	{"txpid2ga3",	0x000000f0,	0,		SROM4_TXPID2G + 1,	0xff00},
-	{"txpid5ga0",	0x000000f0,	0,		SROM4_TXPID5G,		0x00ff},
-	{"txpid5ga1",	0x000000f0,	0,		SROM4_TXPID5G,		0xff00},
-	{"txpid5ga2",	0x000000f0,	0,		SROM4_TXPID5G + 1,	0x00ff},
-	{"txpid5ga3",	0x000000f0,	0,		SROM4_TXPID5G + 1,	0xff00},
-	{"txpid5gla0",	0x000000f0,	0,		SROM4_TXPID5GL,		0x00ff},
-	{"txpid5gla1",	0x000000f0,	0,		SROM4_TXPID5GL,		0xff00},
-	{"txpid5gla2",	0x000000f0,	0,		SROM4_TXPID5GL + 1,	0x00ff},
-	{"txpid5gla3",	0x000000f0,	0,		SROM4_TXPID5GL + 1,	0xff00},
-	{"txpid5gha0",	0x000000f0,	0,		SROM4_TXPID5GH,		0x00ff},
-	{"txpid5gha1",	0x000000f0,	0,		SROM4_TXPID5GH,		0xff00},
-	{"txpid5gha2",	0x000000f0,	0,		SROM4_TXPID5GH + 1,	0x00ff},
-	{"txpid5gha3",	0x000000f0,	0,		SROM4_TXPID5GH + 1,	0xff00},
-
-	{"ccode",	0x0000000f,	SRFL_CCODE,	SROM_CCODE,		0xffff},
-	{"ccode",	0x00000010,	SRFL_CCODE,	SROM4_CCODE,		0xffff},
-	{"ccode",	0x000000e0,	SRFL_CCODE,	SROM5_CCODE,		0xffff},
-	{"ccode",	0x00000700,	SRFL_CCODE,	SROM8_CCODE,		0xffff},
-	{"macaddr",	0x00000700,	SRFL_ETHADDR,	SROM8_MACHI,		0xffff},
-	{"macaddr",	0x000000e0,	SRFL_ETHADDR,	SROM5_MACHI,		0xffff},
-	{"macaddr",	0x00000010,	SRFL_ETHADDR,	SROM4_MACHI,		0xffff},
-	{"macaddr",	0x00000008,	SRFL_ETHADDR,	SROM3_MACHI,		0xffff},
-	{"il0macaddr",	0x00000007,	SRFL_ETHADDR,	SROM_MACHI_IL0,		0xffff},
-	{"et1macaddr",	0x00000007,	SRFL_ETHADDR,	SROM_MACHI_ET1,		0xffff},
-	{"leddc",	0x00000700,	SRFL_NOFFS|SRFL_LEDDC,	SROM8_LEDDC,	0xffff},
-	{"leddc",	0x000000e0,	SRFL_NOFFS|SRFL_LEDDC,	SROM5_LEDDC,	0xffff},
-	{"leddc",	0x00000010,	SRFL_NOFFS|SRFL_LEDDC,	SROM4_LEDDC,	0xffff},
-	{"leddc",	0x00000008,	SRFL_NOFFS|SRFL_LEDDC,	SROM3_LEDDC,	0xffff},
-
-	{"tempthresh",	0x00000700,	0,		SROM8_THERMAL,		0xff00},
-	{"tempoffset",	0x00000700,	0,		SROM8_THERMAL,		0x00ff},
-	{"rawtempsense", 0x00000700,	SRFL_PRHEX,	SROM8_MPWR_RAWTS,	0x01ff},
-	{"measpower",	0x00000700,	SRFL_PRHEX,	SROM8_MPWR_RAWTS,	0xfe00},
-	{"tempsense_slope",	0x00000700,	SRFL_PRHEX, 	SROM8_TS_SLP_OPT_CORRX,	0x00ff},
-	{"tempcorrx",	0x00000700,	SRFL_PRHEX, 	SROM8_TS_SLP_OPT_CORRX,	0xfc00},
-	{"tempsense_option",	0x00000700,	SRFL_PRHEX,	SROM8_TS_SLP_OPT_CORRX,	0x0300},
-	{"freqoffset_corr",	0x00000700,	SRFL_PRHEX,	SROM8_FOC_HWIQ_IQSWP,	0x000f},
-	{"iqcal_swp_dis",	0x00000700,	SRFL_PRHEX,	SROM8_FOC_HWIQ_IQSWP,	0x0010},
-	{"hw_iqcal_en",	0x00000700,	SRFL_PRHEX,	SROM8_FOC_HWIQ_IQSWP,	0x0020},
-	{"elna2g",      0x00000700,     0,              SROM8_EXTLNAGAIN,       0x00ff},
-	{"elna5g",      0x00000700,     0,              SROM8_EXTLNAGAIN,       0xff00},
-	{"phycal_tempdelta",	0x00000700,	0,	SROM8_PHYCAL_TEMPDELTA,	0x00ff},
-	{"temps_period",	0x00000700,	0,	SROM8_PHYCAL_TEMPDELTA,	0x0f00},
-	{"temps_hysteresis",	0x00000700,	0,	SROM8_PHYCAL_TEMPDELTA,	0xf000},
-	{"measpower1", 0x00000700,	SRFL_PRHEX, SROM8_MPWR_1_AND_2, 	0x007f},
-	{"measpower2",	0x00000700, 	SRFL_PRHEX, SROM8_MPWR_1_AND_2, 	0x3f80},
-
-	{"cck2gpo",	0x000000f0,	0,		SROM4_2G_CCKPO,		0xffff},
-	{"cck2gpo",	0x00000100,	0,		SROM8_2G_CCKPO,		0xffff},
-	{"ofdm2gpo",	0x000000f0,	SRFL_MORE,	SROM4_2G_OFDMPO,	0xffff},
-	{"",		0,		0,		SROM4_2G_OFDMPO + 1,	0xffff},
-	{"ofdm5gpo",	0x000000f0,	SRFL_MORE,	SROM4_5G_OFDMPO,	0xffff},
-	{"",		0,		0,		SROM4_5G_OFDMPO + 1,	0xffff},
-	{"ofdm5glpo",	0x000000f0,	SRFL_MORE,	SROM4_5GL_OFDMPO,	0xffff},
-	{"",		0,		0,		SROM4_5GL_OFDMPO + 1,	0xffff},
-	{"ofdm5ghpo",	0x000000f0,	SRFL_MORE,	SROM4_5GH_OFDMPO,	0xffff},
-	{"",		0,		0,		SROM4_5GH_OFDMPO + 1,	0xffff},
-	{"ofdm2gpo",	0x00000100,	SRFL_MORE,	SROM8_2G_OFDMPO,	0xffff},
-	{"",		0,		0,		SROM8_2G_OFDMPO + 1,	0xffff},
-	{"ofdm5gpo",	0x00000100,	SRFL_MORE,	SROM8_5G_OFDMPO,	0xffff},
-	{"",		0,		0,		SROM8_5G_OFDMPO + 1,	0xffff},
-	{"ofdm5glpo",	0x00000100,	SRFL_MORE,	SROM8_5GL_OFDMPO,	0xffff},
-	{"",		0,		0,		SROM8_5GL_OFDMPO + 1,	0xffff},
-	{"ofdm5ghpo",	0x00000100,	SRFL_MORE,	SROM8_5GH_OFDMPO,	0xffff},
-	{"",		0,		0,		SROM8_5GH_OFDMPO + 1,	0xffff},
-	{"mcs2gpo0",	0x000000f0,	0,		SROM4_2G_MCSPO,		0xffff},
-	{"mcs2gpo1",	0x000000f0,	0,		SROM4_2G_MCSPO + 1,	0xffff},
-	{"mcs2gpo2",	0x000000f0,	0,		SROM4_2G_MCSPO + 2,	0xffff},
-	{"mcs2gpo3",	0x000000f0,	0,		SROM4_2G_MCSPO + 3,	0xffff},
-	{"mcs2gpo4",	0x000000f0,	0,		SROM4_2G_MCSPO + 4,	0xffff},
-	{"mcs2gpo5",	0x000000f0,	0,		SROM4_2G_MCSPO + 5,	0xffff},
-	{"mcs2gpo6",	0x000000f0,	0,		SROM4_2G_MCSPO + 6,	0xffff},
-	{"mcs2gpo7",	0x000000f0,	0,		SROM4_2G_MCSPO + 7,	0xffff},
-	{"mcs5gpo0",	0x000000f0,	0,		SROM4_5G_MCSPO,		0xffff},
-	{"mcs5gpo1",	0x000000f0,	0,		SROM4_5G_MCSPO + 1,	0xffff},
-	{"mcs5gpo2",	0x000000f0,	0,		SROM4_5G_MCSPO + 2,	0xffff},
-	{"mcs5gpo3",	0x000000f0,	0,		SROM4_5G_MCSPO + 3,	0xffff},
-	{"mcs5gpo4",	0x000000f0,	0,		SROM4_5G_MCSPO + 4,	0xffff},
-	{"mcs5gpo5",	0x000000f0,	0,		SROM4_5G_MCSPO + 5,	0xffff},
-	{"mcs5gpo6",	0x000000f0,	0,		SROM4_5G_MCSPO + 6,	0xffff},
-	{"mcs5gpo7",	0x000000f0,	0,		SROM4_5G_MCSPO + 7,	0xffff},
-	{"mcs5glpo0",	0x000000f0,	0,		SROM4_5GL_MCSPO,	0xffff},
-	{"mcs5glpo1",	0x000000f0,	0,		SROM4_5GL_MCSPO + 1,	0xffff},
-	{"mcs5glpo2",	0x000000f0,	0,		SROM4_5GL_MCSPO + 2,	0xffff},
-	{"mcs5glpo3",	0x000000f0,	0,		SROM4_5GL_MCSPO + 3,	0xffff},
-	{"mcs5glpo4",	0x000000f0,	0,		SROM4_5GL_MCSPO + 4,	0xffff},
-	{"mcs5glpo5",	0x000000f0,	0,		SROM4_5GL_MCSPO + 5,	0xffff},
-	{"mcs5glpo6",	0x000000f0,	0,		SROM4_5GL_MCSPO + 6,	0xffff},
-	{"mcs5glpo7",	0x000000f0,	0,		SROM4_5GL_MCSPO + 7,	0xffff},
-	{"mcs5ghpo0",	0x000000f0,	0,		SROM4_5GH_MCSPO,	0xffff},
-	{"mcs5ghpo1",	0x000000f0,	0,		SROM4_5GH_MCSPO + 1,	0xffff},
-	{"mcs5ghpo2",	0x000000f0,	0,		SROM4_5GH_MCSPO + 2,	0xffff},
-	{"mcs5ghpo3",	0x000000f0,	0,		SROM4_5GH_MCSPO + 3,	0xffff},
-	{"mcs5ghpo4",	0x000000f0,	0,		SROM4_5GH_MCSPO + 4,	0xffff},
-	{"mcs5ghpo5",	0x000000f0,	0,		SROM4_5GH_MCSPO + 5,	0xffff},
-	{"mcs5ghpo6",	0x000000f0,	0,		SROM4_5GH_MCSPO + 6,	0xffff},
-	{"mcs5ghpo7",	0x000000f0,	0,		SROM4_5GH_MCSPO + 7,	0xffff},
-	{"mcs2gpo0",	0x00000100,	0,		SROM8_2G_MCSPO,		0xffff},
-	{"mcs2gpo1",	0x00000100,	0,		SROM8_2G_MCSPO + 1,	0xffff},
-	{"mcs2gpo2",	0x00000100,	0,		SROM8_2G_MCSPO + 2,	0xffff},
-	{"mcs2gpo3",	0x00000100,	0,		SROM8_2G_MCSPO + 3,	0xffff},
-	{"mcs2gpo4",	0x00000100,	0,		SROM8_2G_MCSPO + 4,	0xffff},
-	{"mcs2gpo5",	0x00000100,	0,		SROM8_2G_MCSPO + 5,	0xffff},
-	{"mcs2gpo6",	0x00000100,	0,		SROM8_2G_MCSPO + 6,	0xffff},
-	{"mcs2gpo7",	0x00000100,	0,		SROM8_2G_MCSPO + 7,	0xffff},
-	{"mcs5gpo0",	0x00000100,	0,		SROM8_5G_MCSPO,		0xffff},
-	{"mcs5gpo1",	0x00000100,	0,		SROM8_5G_MCSPO + 1,	0xffff},
-	{"mcs5gpo2",	0x00000100,	0,		SROM8_5G_MCSPO + 2,	0xffff},
-	{"mcs5gpo3",	0x00000100,	0,		SROM8_5G_MCSPO + 3,	0xffff},
-	{"mcs5gpo4",	0x00000100,	0,		SROM8_5G_MCSPO + 4,	0xffff},
-	{"mcs5gpo5",	0x00000100,	0,		SROM8_5G_MCSPO + 5,	0xffff},
-	{"mcs5gpo6",	0x00000100,	0,		SROM8_5G_MCSPO + 6,	0xffff},
-	{"mcs5gpo7",	0x00000100,	0,		SROM8_5G_MCSPO + 7,	0xffff},
-	{"mcs5glpo0",	0x00000100,	0,		SROM8_5GL_MCSPO,	0xffff},
-	{"mcs5glpo1",	0x00000100,	0,		SROM8_5GL_MCSPO + 1,	0xffff},
-	{"mcs5glpo2",	0x00000100,	0,		SROM8_5GL_MCSPO + 2,	0xffff},
-	{"mcs5glpo3",	0x00000100,	0,		SROM8_5GL_MCSPO + 3,	0xffff},
-	{"mcs5glpo4",	0x00000100,	0,		SROM8_5GL_MCSPO + 4,	0xffff},
-	{"mcs5glpo5",	0x00000100,	0,		SROM8_5GL_MCSPO + 5,	0xffff},
-	{"mcs5glpo6",	0x00000100,	0,		SROM8_5GL_MCSPO + 6,	0xffff},
-	{"mcs5glpo7",	0x00000100,	0,		SROM8_5GL_MCSPO + 7,	0xffff},
-	{"mcs5ghpo0",	0x00000100,	0,		SROM8_5GH_MCSPO,	0xffff},
-	{"mcs5ghpo1",	0x00000100,	0,		SROM8_5GH_MCSPO + 1,	0xffff},
-	{"mcs5ghpo2",	0x00000100,	0,		SROM8_5GH_MCSPO + 2,	0xffff},
-	{"mcs5ghpo3",	0x00000100,	0,		SROM8_5GH_MCSPO + 3,	0xffff},
-	{"mcs5ghpo4",	0x00000100,	0,		SROM8_5GH_MCSPO + 4,	0xffff},
-	{"mcs5ghpo5",	0x00000100,	0,		SROM8_5GH_MCSPO + 5,	0xffff},
-	{"mcs5ghpo6",	0x00000100,	0,		SROM8_5GH_MCSPO + 6,	0xffff},
-	{"mcs5ghpo7",	0x00000100,	0,		SROM8_5GH_MCSPO + 7,	0xffff},
-	{"cddpo",	0x000000f0,	0,		SROM4_CDDPO,		0xffff},
-	{"stbcpo",	0x000000f0,	0,		SROM4_STBCPO,		0xffff},
-	{"bw40po",	0x000000f0,	0,		SROM4_BW40PO,		0xffff},
-	{"bwduppo",	0x000000f0,	0,		SROM4_BWDUPPO,		0xffff},
-	{"cddpo",	0x00000100,	0,		SROM8_CDDPO,		0xffff},
-	{"stbcpo",	0x00000100,	0,		SROM8_STBCPO,		0xffff},
-	{"bw40po",	0x00000100,	0,		SROM8_BW40PO,		0xffff},
-	{"bwduppo",	0x00000100,	0,		SROM8_BWDUPPO,		0xffff},
-
-	/* power per rate from sromrev 9 */
-	{"cckbw202gpo",		0x00000600,	0,	SROM9_2GPO_CCKBW20,		0xffff},
-	{"cckbw20ul2gpo",	0x00000600,	0,	SROM9_2GPO_CCKBW20UL,		0xffff},
-	{"legofdmbw202gpo",	0x00000600,	SRFL_MORE, SROM9_2GPO_LOFDMBW20,	0xffff},
-	{"",			0,		0,	SROM9_2GPO_LOFDMBW20 + 1,	0xffff},
-	{"legofdmbw20ul2gpo",	0x00000600,	SRFL_MORE, SROM9_2GPO_LOFDMBW20UL,	0xffff},
-	{"",			0,		0,	SROM9_2GPO_LOFDMBW20UL + 1,	0xffff},
-	{"legofdmbw205glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_LOFDMBW20,	0xffff},
-	{"",			0,		0,	SROM9_5GLPO_LOFDMBW20 + 1,	0xffff},
-	{"legofdmbw20ul5glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,	0xffff},
-	{"",			0,		0,	SROM9_5GLPO_LOFDMBW20UL + 1,	0xffff},
-	{"legofdmbw205gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_LOFDMBW20,	0xffff},
-	{"",			0,		0,	SROM9_5GMPO_LOFDMBW20 + 1,	0xffff},
-	{"legofdmbw20ul5gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,	0xffff},
-	{"",			0,		0,	SROM9_5GMPO_LOFDMBW20UL + 1,	0xffff},
-	{"legofdmbw205ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_LOFDMBW20,	0xffff},
-	{"",			0,		0,	SROM9_5GHPO_LOFDMBW20 + 1,	0xffff},
-	{"legofdmbw20ul5ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,	0xffff},
-	{"",			0,		0,	SROM9_5GHPO_LOFDMBW20UL + 1,	0xffff},
-	{"mcsbw202gpo",		0x00000600,	SRFL_MORE, SROM9_2GPO_MCSBW20,		0xffff},
-	{"",			0,		0,	SROM9_2GPO_MCSBW20 + 1,		0xffff},
-	{"mcsbw20ul2gpo",      	0x00000600,	SRFL_MORE, SROM9_2GPO_MCSBW20UL,	0xffff},
-	{"",			0,		0,	SROM9_2GPO_MCSBW20UL + 1,	0xffff},
-	{"mcsbw402gpo",		0x00000600,	SRFL_MORE, SROM9_2GPO_MCSBW40,		0xffff},
-	{"",			0,		0,	SROM9_2GPO_MCSBW40 + 1,		0xffff},
-	{"mcsbw205glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_MCSBW20,		0xffff},
-	{"",			0,		0,	SROM9_5GLPO_MCSBW20 + 1,	0xffff},
-	{"mcsbw20ul5glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_MCSBW20UL,	0xffff},
-	{"",			0,		0,	SROM9_5GLPO_MCSBW20UL + 1,	0xffff},
-	{"mcsbw405glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_MCSBW40,		0xffff},
-	{"",			0,		0,	SROM9_5GLPO_MCSBW40 + 1,	0xffff},
-	{"mcsbw205gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_MCSBW20,		0xffff},
-	{"",			0,		0,	SROM9_5GMPO_MCSBW20 + 1,	0xffff},
-	{"mcsbw20ul5gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_MCSBW20UL,	0xffff},
-	{"",			0,		0,	SROM9_5GMPO_MCSBW20UL + 1,	0xffff},
-	{"mcsbw405gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_MCSBW40,		0xffff},
-	{"",			0,		0,	SROM9_5GMPO_MCSBW40 + 1,	0xffff},
-	{"mcsbw205ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_MCSBW20,		0xffff},
-	{"",			0,		0,	SROM9_5GHPO_MCSBW20 + 1,	0xffff},
-	{"mcsbw20ul5ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_MCSBW20UL,	0xffff},
-	{"",			0,		0,	SROM9_5GHPO_MCSBW20UL + 1,	0xffff},
-	{"mcsbw405ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_MCSBW40,		0xffff},
-	{"",			0,		0,	SROM9_5GHPO_MCSBW40 + 1,	0xffff},
-	{"mcs32po",		0x00000600,	0,	SROM9_PO_MCS32,			0xffff},
-	{"legofdm40duppo",	0x00000600,	0,	SROM9_PO_LOFDM40DUP,	0xffff},
-	{"pcieingress_war",	0x00000700,	0,	SROM8_PCIEINGRESS_WAR,	0xf},
-	{"eu_edthresh2g",	0x00000100,	0,	SROM8_EU_EDCRSTH,		0x00ff},
-	{"eu_edthresh5g",	0x00000100,	0,	SROM8_EU_EDCRSTH,		0xff00},
-	{"eu_edthresh2g",	0x00000200,	0,	SROM9_EU_EDCRSTH,		0x00ff},
-	{"eu_edthresh5g",	0x00000200,	0,	SROM9_EU_EDCRSTH,		0xff00},
-	{"rxgainerr2ga0",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0x003f},
-	{"rxgainerr2ga0",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0x003f},
-	{"rxgainerr2ga1",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0x07c0},
-	{"rxgainerr2ga2",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0xf800},
-	{"rxgainerr5gla0",	0x00000700,	0,	SROM8_RXGAINERR_5GL,	0x003f},
-	{"rxgainerr5gla1",	0x00000700,	0,	SROM8_RXGAINERR_5GL,	0x07c0},
-	{"rxgainerr5gla2",	0x00000700,	0,	SROM8_RXGAINERR_5GL,	0xf800},
-	{"rxgainerr5gma0",	0x00000700,	0,	SROM8_RXGAINERR_5GM,	0x003f},
-	{"rxgainerr5gma1",	0x00000700,	0,	SROM8_RXGAINERR_5GM,	0x07c0},
-	{"rxgainerr5gma2",	0x00000700,	0,	SROM8_RXGAINERR_5GM,	0xf800},
-	{"rxgainerr5gha0",	0x00000700,	0,	SROM8_RXGAINERR_5GH,	0x003f},
-	{"rxgainerr5gha1",	0x00000700,	0,	SROM8_RXGAINERR_5GH,	0x07c0},
-	{"rxgainerr5gha2",	0x00000700,	0,	SROM8_RXGAINERR_5GH,	0xf800},
-	{"rxgainerr5gua0",	0x00000700,	0,	SROM8_RXGAINERR_5GU,	0x003f},
-	{"rxgainerr5gua1",	0x00000700,	0,	SROM8_RXGAINERR_5GU,	0x07c0},
-	{"rxgainerr5gua2",	0x00000700,	0,	SROM8_RXGAINERR_5GU,	0xf800},
-	{"sar2g",       	0x00000600,	0,	SROM9_SAR,          	0x00ff},
-	{"sar5g",           0x00000600,	0,	SROM9_SAR,	            0xff00},
-	{"noiselvl2ga0",	0x00000700,	0,	SROM8_NOISELVL_2G,		0x001f},
-	{"noiselvl2ga1",	0x00000700,	0,	SROM8_NOISELVL_2G,		0x03e0},
-	{"noiselvl2ga2",	0x00000700,	0,	SROM8_NOISELVL_2G,		0x7c00},
-	{"noiselvl5gla0",	0x00000700,	0,	SROM8_NOISELVL_5GL,		0x001f},
-	{"noiselvl5gla1",	0x00000700,	0,	SROM8_NOISELVL_5GL,		0x03e0},
-	{"noiselvl5gla2",	0x00000700,	0,	SROM8_NOISELVL_5GL,		0x7c00},
-	{"noiselvl5gma0",	0x00000700,	0,	SROM8_NOISELVL_5GM,		0x001f},
-	{"noiselvl5gma1",	0x00000700,	0,	SROM8_NOISELVL_5GM,		0x03e0},
-	{"noiselvl5gma2",	0x00000700,	0,	SROM8_NOISELVL_5GM,		0x7c00},
-	{"noiselvl5gha0",	0x00000700,	0,	SROM8_NOISELVL_5GH,		0x001f},
-	{"noiselvl5gha1",	0x00000700,	0,	SROM8_NOISELVL_5GH,		0x03e0},
-	{"noiselvl5gha2",	0x00000700,	0,	SROM8_NOISELVL_5GH,		0x7c00},
-	{"noiselvl5gua0",	0x00000700,	0,	SROM8_NOISELVL_5GU,		0x001f},
-	{"noiselvl5gua1",	0x00000700,	0,	SROM8_NOISELVL_5GU,		0x03e0},
-	{"noiselvl5gua2",	0x00000700,	0,	SROM8_NOISELVL_5GU,		0x7c00},
-	{"noisecaloffset",	0x00000300,	0,	SROM8_NOISECALOFFSET,		0x00ff},
-	{"noisecaloffset5g",	0x00000300,	0,	SROM8_NOISECALOFFSET,		0xff00},
-	{"subband5gver",	0x00000700,	0,	SROM8_SUBBAND_PPR,		0x7},
-
-	{"cckPwrOffset",	0x00000400,	0,	SROM10_CCKPWROFFSET,		0xffff},
-	{"eu_edthresh2g",	0x00000400,	0,	SROM10_EU_EDCRSTH,		0x00ff},
-	{"eu_edthresh5g",	0x00000400,	0,	SROM10_EU_EDCRSTH,		0xff00},
-	/* swctrlmap_2g array, note that the last element doesn't have SRFL_ARRAY flag set */
-	{"swctrlmap_2g", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G, 0xffff},
-	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 1,			0xffff},
-	{"",	0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 2, 	0xffff},
-	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 3,			0xffff},
-	{"",	0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 4,	0xffff},
-	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 5,			0xffff},
-	{"",	0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 6,	0xffff},
-	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 7,			0xffff},
-	{"",	0x00000400, SRFL_PRHEX,	SROM10_SWCTRLMAP_2G + 8,			0xffff},
-
-	/* sromrev 11 */
-	{"boardflags3",	0xfffff800,	SRFL_PRHEX|SRFL_MORE,	SROM11_BFL4,	0xffff},
-	{"",		0,		0,			SROM11_BFL5,	0xffff},
-	{"boardnum",	0xfffff800,	0,			SROM11_MACLO,	0xffff},
-	{"macaddr",	0xfffff800,	SRFL_ETHADDR,		SROM11_MACHI,	0xffff},
-	{"ccode",	0xfffff800,	SRFL_CCODE,		SROM11_CCODE,	0xffff},
-	{"regrev",	0xfffff800,	0,			SROM11_REGREV,	0x00ff},
-	{"ledbh0",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH10,	0x00ff},
-	{"ledbh1",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH10,	0xff00},
-	{"ledbh2",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH32,	0x00ff},
-	{"ledbh3",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH32,	0xff00},
-	{"leddc",	0xfffff800,	SRFL_NOFFS|SRFL_LEDDC,	SROM11_LEDDC,	0xffff},
-	{"aa2g",	0xfffff800,	0,			SROM11_AA,	0x00ff},
-	{"aa5g",	0xfffff800,	0,			SROM11_AA,	0xff00},
-	{"agbg0",	0xfffff800,	0,			SROM11_AGBG10,  0xff00},
-	{"agbg1",	0xfffff800,	0,			SROM11_AGBG10,	0x00ff},
-	{"agbg2",	0xfffff800,	0,			SROM11_AGBG2A0,	0xff00},
-	{"aga0",	0xfffff800,	0,			SROM11_AGBG2A0,	0x00ff},
-	{"aga1",	0xfffff800,	0,			SROM11_AGA21,   0xff00},
-	{"aga2",	0xfffff800,	0,			SROM11_AGA21,	0x00ff},
-	{"txchain",	0xfffff800,	SRFL_NOFFS,	SROM11_TXRXC,	SROM4_TXCHAIN_MASK},
-	{"rxchain",	0xfffff800,	SRFL_NOFFS,	SROM11_TXRXC,	SROM4_RXCHAIN_MASK},
-	{"antswitch",	0xfffff800,	SRFL_NOFFS,	SROM11_TXRXC,	SROM4_SWITCH_MASK},
-
-	{"tssiposslope2g",	0xfffff800,	0,		SROM11_FEM_CFG1, 	0x0001},
-	{"epagain2g",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0x000e},
-	{"pdgain2g",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0x01f0},
-	{"tworangetssi2g",	0xfffff800,	0,		SROM11_FEM_CFG1, 	0x0200},
-	{"papdcap2g",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0x0400},
-	{"femctrl",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0xf800},
-
-	{"tssiposslope5g",	0xfffff800,	0,		SROM11_FEM_CFG2, 	0x0001},
-	{"epagain5g",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0x000e},
-	{"pdgain5g",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0x01f0},
-	{"tworangetssi5g",	0xfffff800,	0,		SROM11_FEM_CFG2, 	0x0200},
-	{"papdcap5g",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0x0400},
-	{"gainctrlsph",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0xf800},
-
-	{"tempthresh",		0xfffff800,	0,		SROM11_THERMAL,		0xff00},
-	{"tempoffset",		0xfffff800,	0,		SROM11_THERMAL,		0x00ff},
-	{"rawtempsense", 	0xfffff800,	SRFL_PRHEX,	SROM11_MPWR_RAWTS,	0x01ff},
-	{"measpower",		0xfffff800,	SRFL_PRHEX,	SROM11_MPWR_RAWTS,	0xfe00},
-	{"tempsense_slope",	0xfffff800,	SRFL_PRHEX, 	SROM11_TS_SLP_OPT_CORRX, 0x00ff},
-	{"tempcorrx",		0xfffff800,	SRFL_PRHEX, 	SROM11_TS_SLP_OPT_CORRX, 0xfc00},
-	{"tempsense_option",	0xfffff800,	SRFL_PRHEX,	SROM11_TS_SLP_OPT_CORRX, 0x0300},
-	{"xtalfreq",		0xfffff800,	0,		SROM11_XTAL_FREQ, 	0xffff},
-	/* Special PA Params for 4350 5G Band, 40/80 MHz BW Ant #1 */
-	{"pa5gbw4080a1", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W0_A1, 0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W1_A1,                 0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W2_A1,                 0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_4080_W0_A1,                 0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_4080_PA,     0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_4080_PA + 1, 0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA,     0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA + 1, 0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA + 2, 0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_4080_PA,     0xffff},
-	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_4080_PA + 1, 0xffff},
-	{"", 0xfffff800, SRFL_PRHEX,              SROM11_PATH2 + SROM11_5GB3_4080_PA + 2, 0xffff},
-	{"phycal_tempdelta",	0xfffff800,	0,		SROM11_PHYCAL_TEMPDELTA, 0x00ff},
-	{"temps_period",	0xfffff800,	0,		SROM11_PHYCAL_TEMPDELTA, 0x0f00},
-	{"temps_hysteresis",	0xfffff800,	0,		SROM11_PHYCAL_TEMPDELTA, 0xf000},
-	{"measpower1", 		0xfffff800,	SRFL_PRHEX,	SROM11_MPWR_1_AND_2, 	0x007f},
-	{"measpower2",		0xfffff800, 	SRFL_PRHEX,	SROM11_MPWR_1_AND_2, 	0x3f80},
-	{"tssifloor2g",		0xfffff800,	SRFL_PRHEX,	SROM11_TSSIFLOOR_2G,	0x03ff},
-	{"tssifloor5g",	0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GL,	0x03ff},
-	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GM,	0x03ff},
-	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GH,	0x03ff},
-	{"",		0xfffff800,	SRFL_PRHEX,		SROM11_TSSIFLOOR_5GU,	0x03ff},
-	{"pdoffset2g40ma0",     0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x000f},
-	{"pdoffset2g40ma1",     0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x00f0},
-	{"pdoffset2g40ma2",     0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x0f00},
-	{"pdoffset2g40mvalid",  0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x8000},
-	{"pdoffset40ma0",      	0xfffff800,	0,		SROM11_PDOFF_40M_A0,   	0xffff},
-	{"pdoffset40ma1",      	0xfffff800,	0,		SROM11_PDOFF_40M_A1,   	0xffff},
-	{"pdoffset40ma2",      	0xfffff800,	0,		SROM11_PDOFF_40M_A2,   	0xffff},
-	{"pdoffset80ma0",      	0xfffff800,	0,		SROM11_PDOFF_80M_A0,   	0xffff},
-	{"pdoffset80ma1",      	0xfffff800,	0,		SROM11_PDOFF_80M_A1,   	0xffff},
-	{"pdoffset80ma2",      	0xfffff800,	0,		SROM11_PDOFF_80M_A2,   	0xffff},
-
-	{"subband5gver",	0xfffff800, 	SRFL_PRHEX,	SROM11_SUBBAND5GVER, 	0xffff},
-	{"paparambwver",	0xfffff800, 	0,		SROM11_MCSLR5GLPO, 	0xf000},
-	{"rx5ggainwar",         0xfffff800,     0,              SROM11_MCSLR5GMPO,      0x2000},
-	/* Special PA Params for 4350 5G Band, 40/80 MHz BW Ant #0 */
-	{"pa5gbw4080a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 +SROM11_5GB0_PA, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 2, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA,     0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 2, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA,     0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 2, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA,     0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH2 + SROM11_5GB3_PA + 2, 0xffff},
-	/* Special PA Params for 4335 5G Band, 40 MHz BW */
-	{"pa5gbw40a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA + 2, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA,     0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA + 2, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA,     0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA + 2, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB3_PA,     0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB3_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH1 + SROM11_5GB3_PA + 2, 0xffff},
-	/* Special PA Params for 4335 5G Band, 80 MHz BW */
-	{"pa5gbw80a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 2, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA,     0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 2, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA,     0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 2, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA,     0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH2 + SROM11_5GB3_PA + 2, 0xffff},
-	/* Special PA Params for 4335 2G Band, CCK */
-	{"pa2gccka0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_2G_PA, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_2G_PA + 1, 0xffff},
-	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH1 + SROM11_2G_PA + 2, 0xffff},
-
-	/* power per rate */
-	{"cckbw202gpo",		0xfffff800,	0,		SROM11_CCKBW202GPO, 	0xffff},
-	{"cckbw20ul2gpo",	0xfffff800,	0,		SROM11_CCKBW20UL2GPO, 	0xffff},
-	{"mcsbw202gpo",		0xfffff800,	SRFL_MORE,	SROM11_MCSBW202GPO,   	0xffff},
-	{"",            	0xfffff800, 	0,          	SROM11_MCSBW202GPO_1, 	0xffff},
-	{"mcsbw402gpo",		0xfffff800,	SRFL_MORE,	SROM11_MCSBW402GPO,   	0xffff},
-	{"",            	0xfffff800, 	0,   		SROM11_MCSBW402GPO_1, 	0xffff},
-	{"dot11agofdmhrbw202gpo", 0xfffff800, 	0, 	SROM11_DOT11AGOFDMHRBW202GPO, 	0xffff},
-	{"ofdmlrbw202gpo",	0xfffff800, 	0, 		SROM11_OFDMLRBW202GPO,	0xffff},
-	{"mcsbw205glpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW205GLPO, 	0xffff},
-	{"",           		0xfffff800, 	0,   		SROM11_MCSBW205GLPO_1, 	0xffff},
-	{"mcsbw405glpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW405GLPO, 	0xffff},
-	{"",           		0xfffff800, 	0,     		SROM11_MCSBW405GLPO_1, 	0xffff},
-	{"mcsbw805glpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW805GLPO, 	0xffff},
-	{"",           		0xfffff800, 	0,    		SROM11_MCSBW805GLPO_1, 	0xffff},
-	{"mcsbw205gmpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW205GMPO, 	0xffff},
-	{"",           		0xfffff800, 	0,     		SROM11_MCSBW205GMPO_1, 	0xffff},
-	{"mcsbw405gmpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW405GMPO, 	0xffff},
-	{"",           		0xfffff800, 	0,     		SROM11_MCSBW405GMPO_1, 	0xffff},
-	{"mcsbw805gmpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW805GMPO, 	0xffff},
-	{"",           		0xfffff800, 	0,   		SROM11_MCSBW805GMPO_1, 	0xffff},
-	{"mcsbw205ghpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW205GHPO, 	0xffff},
-	{"",           		0xfffff800, 	0,  		SROM11_MCSBW205GHPO_1, 	0xffff},
-	{"mcsbw405ghpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW405GHPO, 	0xffff},
-	{"",           		0xfffff800, 	0,   		SROM11_MCSBW405GHPO_1, 	0xffff},
-	{"mcsbw805ghpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW805GHPO, 	0xffff},
-	{"",           		0xfffff800, 	0,    		SROM11_MCSBW805GHPO_1, 	0xffff},
-	{"mcslr5glpo",		0xfffff800,	0,		SROM11_MCSLR5GLPO, 	0x0fff},
-	{"mcslr5gmpo",		0xfffff800,	0,		SROM11_MCSLR5GMPO, 	0xffff},
-	{"mcslr5ghpo",		0xfffff800,	0,		SROM11_MCSLR5GHPO, 	0xffff},
-	{"sb20in40hrpo", 	0xfffff800,	0,	SROM11_SB20IN40HRPO,		0xffff},
-	{"sb20in80and160hr5glpo", 0xfffff800, 	0, 	SROM11_SB20IN80AND160HR5GLPO, 	0xffff},
-	{"sb40and80hr5glpo",	  0xfffff800, 	0,	SROM11_SB40AND80HR5GLPO,	0xffff},
-	{"sb20in80and160hr5gmpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160HR5GMPO, 	0xffff},
-	{"sb40and80hr5gmpo",	  0xfffff800, 	0,	SROM11_SB40AND80HR5GMPO,	0xffff},
-	{"sb20in80and160hr5ghpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160HR5GHPO, 	0xffff},
-	{"sb40and80hr5ghpo",	  0xfffff800, 	0,	SROM11_SB40AND80HR5GHPO,	0xffff},
-	{"sb20in40lrpo",	  0xfffff800, 	0,	SROM11_SB20IN40LRPO,		0xffff},
-	{"sb20in80and160lr5glpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160LR5GLPO, 	0xffff},
-	{"sb40and80lr5glpo",	  0xfffff800, 	0,	SROM11_SB40AND80LR5GLPO,	0xffff},
-	{"sb20in80and160lr5gmpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160LR5GMPO, 	0xffff},
-	{"sb40and80lr5gmpo",	  0xfffff800, 	0,	SROM11_SB40AND80LR5GMPO,	0xffff},
-	{"sb20in80and160lr5ghpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160LR5GHPO, 	0xffff},
-	{"sb40and80lr5ghpo",	  0xfffff800, 	0,	SROM11_SB40AND80LR5GHPO,	0xffff},
-	{"dot11agduphrpo",	  0xfffff800, 	0,	SROM11_DOT11AGDUPHRPO,		0xffff},
-	{"dot11agduplrpo",	  0xfffff800, 	0,	SROM11_DOT11AGDUPLRPO,		0xffff},
-
-	/* Misc */
-	{"sar2g",       	0xfffff800,	0,	SROM11_SAR,          	0x00ff},
-	{"sar5g",           	0xfffff800,	0,	SROM11_SAR,		0xff00},
-
-	{"noiselvl2ga0",	0xfffff800,	0,		SROM11_NOISELVL_2G,	0x001f},
-	{"noiselvl2ga1",	0xfffff800,	0,		SROM11_NOISELVL_2G,	0x03e0},
-	{"noiselvl2ga2",	0xfffff800,	0,		SROM11_NOISELVL_2G,	0x7c00},
-	{"noiselvl5ga0",	0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GL,	0x001f},
-	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GM,	0x001f},
-	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GH,	0x001f},
-	{"",			0xfffff800,	0,		SROM11_NOISELVL_5GU,	0x001f},
-	{"noiselvl5ga1",	0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GL,	0x03e0},
-	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GM,	0x03e0},
-	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GH,	0x03e0},
-	{"",			0xfffff800,	0,		SROM11_NOISELVL_5GU,	0x03e0},
-	{"noiselvl5ga2",	0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GL,	0x7c00},
-	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GM,	0x7c00},
-	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GH,	0x7c00},
-	{"",			0xfffff800,	0,		SROM11_NOISELVL_5GU,	0x7c00},
-	{"eu_edthresh2g",	0x00000800,	0,	        SROM11_EU_EDCRSTH,	0x00ff},
-	{"eu_edthresh5g",	0x00000800,	0,	        SROM11_EU_EDCRSTH,	0xff00},
-
-	{"rxgainerr2ga0", 	0xfffff800, 	0,    		SROM11_RXGAINERR_2G,    0x003f},
-	{"rxgainerr2ga1", 	0xfffff800, 	0,    		SROM11_RXGAINERR_2G,    0x07c0},
-	{"rxgainerr2ga2", 	0xfffff800, 	0,    		SROM11_RXGAINERR_2G,    0xf800},
-	{"rxgainerr5ga0",      	0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GL,   0x003f},
-	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GM,   0x003f},
-	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GH,   0x003f},
-	{"",      		0xfffff800, 	0,    		SROM11_RXGAINERR_5GU,   0x003f},
-	{"rxgainerr5ga1",      	0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GL,   0x07c0},
-	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GM,   0x07c0},
-	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GH,   0x07c0},
-	{"",      		0xfffff800, 	0,    		SROM11_RXGAINERR_5GU,   0x07c0},
-	{"rxgainerr5ga2",      	0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GL,   0xf800},
-	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GM,   0xf800},
-	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GH,   0xf800},
-	{"",      		0xfffff800, 	0,    		SROM11_RXGAINERR_5GU,   0xf800},
-	{"rpcal2g",      	0xfffff800, 	0,		SROM11_RPCAL_2G,        0xffff},
-	{"rpcal5gb0",      	0xfffff800, 	0,		SROM11_RPCAL_5GL,       0xffff},
-	{"rpcal5gb1",      	0xfffff800, 	0,		SROM11_RPCAL_5GM,       0xffff},
-	{"rpcal5gb2",      	0xfffff800, 	0,		SROM11_RPCAL_5GH,       0xffff},
-	{"rpcal5gb3",      	0xfffff800, 	0,		SROM11_RPCAL_5GU,       0xffff},
-	{"txidxcap2g",      	0xfffff800, 	0,		SROM11_TXIDXCAP2G,      0x0ff0},
-	{"txidxcap5g",      	0xfffff800, 	0,		SROM11_TXIDXCAP5G,      0x0ff0},
-	{"pdoffsetcckma0",      0xfffff800,     0,              SROM11_PDOFF_2G_CCK,    0x000f},
-	{"pdoffsetcckma1",      0xfffff800,     0,              SROM11_PDOFF_2G_CCK,    0x00f0},
-	{"pdoffsetcckma2",      0xfffff800,     0,              SROM11_PDOFF_2G_CCK,    0x0f00},
-
-	/* sromrev 12 */
-	{"boardflags4",		0xfffff000,	SRFL_PRHEX|SRFL_MORE,	SROM12_BFL6,	0xffff},
-	{"",	0,	0,			SROM12_BFL7,	0xffff},
-	{"pdoffsetcck",		0xfffff000,	0,      SROM12_PDOFF_2G_CCK,       0xffff},
-	{"pdoffset20in40m5gb0",	0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B0,    0xffff},
-	{"pdoffset20in40m5gb1", 0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B1,    0xffff},
-	{"pdoffset20in40m5gb2", 0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B2,    0xffff},
-	{"pdoffset20in40m5gb3", 0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B3,    0xffff},
-	{"pdoffset20in40m5gb4", 0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B4,    0xffff},
-	{"pdoffset40in80m5gb0", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B0,    0xffff},
-	{"pdoffset40in80m5gb1", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B1,    0xffff},
-	{"pdoffset40in80m5gb2", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B2,    0xffff},
-	{"pdoffset40in80m5gb3", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B3,    0xffff},
-	{"pdoffset40in80m5gb4", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B4,    0xffff},
-	{"pdoffset20in80m5gb0", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B0,    0xffff},
-	{"pdoffset20in80m5gb1", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B1,    0xffff},
-	{"pdoffset20in80m5gb2", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B2,    0xffff},
-	{"pdoffset20in80m5gb3", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B3,    0xffff},
-	{"pdoffset20in80m5gb4", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B4,    0xffff},
-
-	{"pdoffset20in40m5gcore3",   0xffffe000, 0,     SROM13_PDOFFSET20IN40M5GCORE3,   0xffff},
-	{"pdoffset20in40m5gcore3_1", 0xffffe000, 0,     SROM13_PDOFFSET20IN40M5GCORE3_1, 0xffff},
-	{"pdoffset20in80m5gcore3",   0xffffe000, 0,     SROM13_PDOFFSET20IN80M5GCORE3,   0xffff},
-	{"pdoffset20in80m5gcore3_1", 0xffffe000, 0,     SROM13_PDOFFSET20IN80M5GCORE3_1, 0xffff},
-	{"pdoffset40in80m5gcore3",   0xffffe000, 0,     SROM13_PDOFFSET40IN80M5GCORE3,   0xffff},
-	{"pdoffset40in80m5gcore3_1", 0xffffe000, 0,     SROM13_PDOFFSET40IN80M5GCORE3_1, 0xffff},
-
-	{"pdoffset20in40m2g",        0xffffe000, 0,     SROM13_PDOFFSET20IN40M2G,        0xffff},
-	{"pdoffset20in40m2gcore3",   0xffffe000, 0,     SROM13_PDOFFSET20IN40M2GCORE3,   0xffff},
-
-	/* power per rate */
-	{"mcsbw205gx1po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW205GX1PO,   0xffff},
-	{"",                    0xfffff000,     0,              SROM12_MCSBW205GX1PO_1, 0xffff},
-	{"mcsbw405gx1po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW405GX1PO,   0xffff},
-	{"",                    0xfffff000,     0,              SROM12_MCSBW405GX1PO_1, 0xffff},
-	{"mcsbw805gx1po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW805GX1PO,   0xffff},
-	{"",                    0xfffff000,     0,              SROM12_MCSBW805GX1PO_1, 0xffff},
-	{"mcsbw205gx2po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW205GX2PO,   0xffff},
-	{"",                    0xfffff000,     0,              SROM12_MCSBW205GX2PO_1, 0xffff},
-	{"mcsbw405gx2po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW405GX2PO,   0xffff},
-	{"",                    0xfffff000,     0,              SROM12_MCSBW405GX2PO_1, 0xffff},
-	{"mcsbw805gx2po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW805GX2PO,   0xffff},
-	{"",                    0xfffff000,     0,              SROM12_MCSBW805GX2PO_1, 0xffff},
-
-	{"sb20in80and160hr5gx1po", 0xfffff000,  0,      SROM12_SB20IN80AND160HR5GX1PO,  0xffff},
-	{"sb40and80hr5gx1po",     0xfffff000,   0,      SROM12_SB40AND80HR5GX1PO,       0xffff},
-	{"sb20in80and160lr5gx1po", 0xfffff000,  0,      SROM12_SB20IN80AND160LR5GX1PO,  0xffff},
-	{"sb40and80hr5gx1po",     0xfffff000,   0,      SROM12_SB40AND80HR5GX1PO,       0xffff},
-	{"sb20in80and160hr5gx2po", 0xfffff000,  0,      SROM12_SB20IN80AND160HR5GX2PO,  0xffff},
-	{"sb40and80hr5gx2po",     0xfffff000,   0,      SROM12_SB40AND80HR5GX2PO,       0xffff},
-	{"sb20in80and160lr5gx2po", 0xfffff000,  0,      SROM12_SB20IN80AND160LR5GX2PO,  0xffff},
-	{"sb40and80hr5gx2po",     0xfffff000,   0,      SROM12_SB40AND80HR5GX2PO,       0xffff},
-
-	{"rxgains5gmelnagaina0",	0xfffff000,	0,       SROM12_RXGAINS10,	0x0007},
-	{"rxgains5gmelnagaina1",	0xfffff000,	0,       SROM12_RXGAINS11,	0x0007},
-	{"rxgains5gmelnagaina2",	0xfffff000,	0,       SROM12_RXGAINS12,	0x0007},
-	{"rxgains5gmtrisoa0",	0xfffff000,	0,       SROM12_RXGAINS10,	0x0078},
-	{"rxgains5gmtrisoa1",	0xfffff000,	0,       SROM12_RXGAINS11,	0x0078},
-	{"rxgains5gmtrisoa2",	0xfffff000,	0,       SROM12_RXGAINS12,	0x0078},
-	{"rxgains5gmtrelnabypa0", 0xfffff000,	0,       SROM12_RXGAINS10,	0x0080},
-	{"rxgains5gmtrelnabypa1", 0xfffff000,	0,       SROM12_RXGAINS11,	0x0080},
-	{"rxgains5gmtrelnabypa2", 0xfffff000,	0,       SROM12_RXGAINS12,	0x0080},
-	{"rxgains5ghelnagaina0",	0xfffff000,	0,       SROM12_RXGAINS10,	0x0700},
-	{"rxgains5ghelnagaina1",	0xfffff000,	0,       SROM12_RXGAINS11,	0x0700},
-	{"rxgains5ghelnagaina2",	0xfffff000,	0,       SROM12_RXGAINS12,	0x0700},
-	{"rxgains5ghtrisoa0",	0xfffff000,	0,	 SROM12_RXGAINS10,	0x7800},
-	{"rxgains5ghtrisoa1",	0xfffff000,	0,	 SROM12_RXGAINS11,	0x7800},
-	{"rxgains5ghtrisoa2",	0xfffff000,	0,	 SROM12_RXGAINS12,	0x7800},
-	{"rxgains5ghtrelnabypa0", 0xfffff000,	0,	 SROM12_RXGAINS10,	0x8000},
-	{"rxgains5ghtrelnabypa1", 0xfffff000,	0,	 SROM12_RXGAINS11,	0x8000},
-	{"rxgains5ghtrelnabypa2", 0xfffff000,	0,	 SROM12_RXGAINS12,	0x8000},
-	{"eu_edthresh2g",	0x00001000,	0,       SROM12_EU_EDCRSTH,	0x00ff},
-	{"eu_edthresh5g",	0x00001000,	0,       SROM12_EU_EDCRSTH,	0xff00},
-
-	{"gpdn",		0xfffff000,	SRFL_PRHEX|SRFL_MORE,	SROM12_GPDN_L,	0xffff},
-	{"",			0,		0,			SROM12_GPDN_H,	0xffff},
-
-	{"eu_edthresh2g",       0x00002000,     0,       SROM13_EU_EDCRSTH,     0x00ff},
-	{"eu_edthresh5g",       0x00002000,     0,       SROM13_EU_EDCRSTH,     0xff00},
-
-	{"agbg3",       0xffffe000,     0,              SROM13_ANTGAIN_BANDBGA, 0xff00},
-	{"aga3",        0xffffe000,     0,              SROM13_ANTGAIN_BANDBGA, 0x00ff},
-	{"noiselvl2ga3",        0xffffe000,     0,              SROM13_NOISELVLCORE3,   0x001f},
-	{"noiselvl5ga3",        0xffffe000,     SRFL_ARRAY,     SROM13_NOISELVLCORE3,   0x03e0},
-	{"",                    0xffffe000,     SRFL_ARRAY,     SROM13_NOISELVLCORE3,   0x7c00},
-	{"",                    0xffffe000,     SRFL_ARRAY,     SROM13_NOISELVLCORE3_1, 0x001f},
-	{"",                    0xffffe000,     0,              SROM13_NOISELVLCORE3_1, 0x03e0},
-	{"rxgainerr2ga3",       0xffffe000,     0,              SROM13_RXGAINERRCORE3,  0x001f},
-	{"rxgainerr5ga3",       0xffffe000,     SRFL_ARRAY,     SROM13_RXGAINERRCORE3,  0x03e0},
-	{"",                    0xffffe000,     SRFL_ARRAY,     SROM13_RXGAINERRCORE3,  0x7c00},
-	{"",                    0xffffe000,     SRFL_ARRAY,     SROM13_RXGAINERRCORE3_1, 0x001f},
-	{"",                    0xffffe000,     0,              SROM13_RXGAINERRCORE3_1, 0x03e0},
-	{"rxgains5gmelnagaina3",        0xffffe000,     0,       SROM13_RXGAINS1CORE3,  0x0007},
-	{"rxgains5gmtrisoa3",   0xffffe000,     0,       SROM13_RXGAINS1CORE3,  0x0078},
-	{"rxgains5gmtrelnabypa3", 0xffffe000,   0,       SROM13_RXGAINS1CORE3,  0x0080},
-	{"rxgains5ghelnagaina3",        0xffffe000,     0,       SROM13_RXGAINS1CORE3,  0x0700},
-	{"rxgains5ghtrisoa3",   0xffffe000,     0,       SROM13_RXGAINS1CORE3,  0x7800},
-	{"rxgains5ghtrelnabypa3", 0xffffe000,   0,       SROM13_RXGAINS1CORE3,  0x8000},
-
-	/* power per rate */
-	{"mcs1024qam2gpo",      0xffffe000,     0,           SROM13_MCS1024QAM2GPO,     0xffff},
-	{"mcs1024qam5glpo",     0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GLPO,    0xffff},
-	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GLPO_1,  0xffff},
-	{"mcs1024qam5gmpo",     0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GMPO,    0xffff},
-	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GMPO_1,  0xffff},
-	{"mcs1024qam5ghpo",     0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GHPO,    0xffff},
-	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GHPO_1,  0xffff},
-	{"mcs1024qam5gx1po",    0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GX1PO,   0xffff},
-	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GX1PO_1, 0xffff},
-	{"mcs1024qam5gx2po",    0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GX2PO,   0xffff},
-	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GX2PO_1, 0xffff},
-
-	{"mcsbw1605glpo",       0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GLPO,   0xffff},
-	{"",                    0xffffe000,     0,              SROM13_MCSBW1605GLPO_1, 0xffff},
-	{"mcsbw1605gmpo",       0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GMPO,   0xffff},
-	{"",                    0xffffe000,     0,              SROM13_MCSBW1605GMPO_1, 0xffff},
-	{"mcsbw1605ghpo",       0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GHPO,   0xffff},
-	{"",                    0xffffe000,     0,              SROM13_MCSBW1605GHPO_1, 0xffff},
-	{"mcsbw1605gx1po",      0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GX1PO,  0xffff},
-	{"",                    0xffffe000,     0,      SROM13_MCSBW1605GX1PO_1,        0xffff},
-	{"mcsbw1605gx2po",      0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GX2PO,  0xffff},
-	{"",                    0xffffe000,     0,      SROM13_MCSBW1605GX2PO_1,        0xffff},
-
-	{"ulbpproffs2g",        0xffffe000,     0,      SROM13_ULBPPROFFS2G,            0xffff},
-
-	{"mcs8poexp",           0xffffe000,     SRFL_MORE,    SROM13_MCS8POEXP,         0xffff},
-	{"",                    0xffffe000,     0,            SROM13_MCS8POEXP_1,       0xffff},
-	{"mcs9poexp",           0xffffe000,     SRFL_MORE,    SROM13_MCS9POEXP,         0xffff},
-	{"",                    0xffffe000,     0,            SROM13_MCS9POEXP_1,       0xffff},
-	{"mcs10poexp",          0xffffe000,     SRFL_MORE,    SROM13_MCS10POEXP,        0xffff},
-	{"",                    0xffffe000,     0,            SROM13_MCS10POEXP_1,      0xffff},
-	{"mcs11poexp",          0xffffe000,     SRFL_MORE,    SROM13_MCS11POEXP,        0xffff},
-	{"",                    0xffffe000,     0,            SROM13_MCS11POEXP_1,      0xffff},
-
-	{"ulbpdoffs5gb0a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB0A0,         0xffff},
-	{"ulbpdoffs5gb0a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB0A1,         0xffff},
-	{"ulbpdoffs5gb0a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB0A2,         0xffff},
-	{"ulbpdoffs5gb0a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB0A3,         0xffff},
-	{"ulbpdoffs5gb1a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB1A0,         0xffff},
-	{"ulbpdoffs5gb1a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB1A1,         0xffff},
-	{"ulbpdoffs5gb1a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB1A2,         0xffff},
-	{"ulbpdoffs5gb1a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB1A3,         0xffff},
-	{"ulbpdoffs5gb2a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB2A0,         0xffff},
-	{"ulbpdoffs5gb2a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB2A1,         0xffff},
-	{"ulbpdoffs5gb2a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB2A2,         0xffff},
-	{"ulbpdoffs5gb2a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB2A3,         0xffff},
-	{"ulbpdoffs5gb3a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB3A0,         0xffff},
-	{"ulbpdoffs5gb3a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB3A1,         0xffff},
-	{"ulbpdoffs5gb3a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB3A2,         0xffff},
-	{"ulbpdoffs5gb3a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB3A3,         0xffff},
-	{"ulbpdoffs5gb4a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB4A0,         0xffff},
-	{"ulbpdoffs5gb4a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB4A1,         0xffff},
-	{"ulbpdoffs5gb4a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB4A2,         0xffff},
-	{"ulbpdoffs5gb4a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB4A3,         0xffff},
-	{"ulbpdoffs2ga0",       0xffffe000,     0,      SROM13_ULBPDOFFS2GA0,           0xffff},
-	{"ulbpdoffs2ga1",       0xffffe000,     0,      SROM13_ULBPDOFFS2GA1,           0xffff},
-	{"ulbpdoffs2ga2",       0xffffe000,     0,      SROM13_ULBPDOFFS2GA2,           0xffff},
-	{"ulbpdoffs2ga3",       0xffffe000,     0,      SROM13_ULBPDOFFS2GA3,           0xffff},
-
-	{"rpcal5gb4",           0xffffe000,     0,      SROM13_RPCAL5GB4,               0xffff},
-
-	{"sb20in40hrlrpox",     0xffffe000,     0,       SROM13_SB20IN40HRLRPOX,        0xffff},
-
-	{"pdoffset20in40m2g",   0xffffe000,     0,      SROM13_PDOFFSET20IN40M2G,       0xffff},
-	{"pdoffset20in40m2gcore3", 0xffffe000,  0,      SROM13_PDOFFSET20IN40M2GCORE3,  0xffff},
-
-	{"pdoffset20in40m5gcore3", 0xffffe000, SRFL_MORE, SROM13_PDOFFSET20IN40M5GCORE3, 0xffff},
-	{"",                    0xffffe000,     0,  SROM13_PDOFFSET20IN40M5GCORE3_1,   0xffff},
-	{"pdoffset40in80m5gcore3", 0xffffe000, SRFL_MORE, SROM13_PDOFFSET40IN80M5GCORE3, 0xffff},
-	{"",                    0xffffe000,     0,  SROM13_PDOFFSET40IN80M5GCORE3_1,   0xffff},
-	{"pdoffset20in80m5gcore3", 0xffffe000, SRFL_MORE, SROM13_PDOFFSET20IN80M5GCORE3, 0xffff},
-	{"",                    0xffffe000,     0,  SROM13_PDOFFSET20IN80M5GCORE3_1,   0xffff},
-
-	{"swctrlmap4_cfg",      0xffffe000,     0,      SROM13_SWCTRLMAP4_CFG,          0xffff},
-	{"swctrlmap4_TX2g_fem3to0", 0xffffe000, 0,      SROM13_SWCTRLMAP4_TX2G_FEM3TO0, 0xffff},
-	{"swctrlmap4_RX2g_fem3to0", 0xffffe000, 0,      SROM13_SWCTRLMAP4_RX2G_FEM3TO0, 0xffff},
-	{"swctrlmap4_RXByp2g_fem3to0", 0xffffe000, 0, SROM13_SWCTRLMAP4_RXBYP2G_FEM3TO0, 0xffff},
-	{"swctrlmap4_misc2g_fem3to0", 0xffffe000, 0,  SROM13_SWCTRLMAP4_MISC2G_FEM3TO0, 0xffff},
-	{"swctrlmap4_TX5g_fem3to0", 0xffffe000, 0,      SROM13_SWCTRLMAP4_TX5G_FEM3TO0, 0xffff},
-	{"swctrlmap4_RX5g_fem3to0", 0xffffe000, 0,      SROM13_SWCTRLMAP4_RX5G_FEM3TO0, 0xffff},
-	{"swctrlmap4_RXByp5g_fem3to0", 0xffffe000, 0, SROM13_SWCTRLMAP4_RXBYP5G_FEM3TO0, 0xffff},
-	{"swctrlmap4_misc5g_fem3to0", 0xffffe000, 0,  SROM13_SWCTRLMAP4_MISC5G_FEM3TO0, 0xffff},
-	{"swctrlmap4_TX2g_fem7to4", 0xffffe000, 0,      SROM13_SWCTRLMAP4_TX2G_FEM7TO4, 0xffff},
-	{"swctrlmap4_RX2g_fem7to4", 0xffffe000, 0,      SROM13_SWCTRLMAP4_RX2G_FEM7TO4, 0xffff},
-	{"swctrlmap4_RXByp2g_fem7to4", 0xffffe000, 0, SROM13_SWCTRLMAP4_RXBYP2G_FEM7TO4, 0xffff},
-	{"swctrlmap4_misc2g_fem7to4", 0xffffe000, 0,  SROM13_SWCTRLMAP4_MISC2G_FEM7TO4, 0xffff},
-	{"swctrlmap4_TX5g_fem7to4", 0xffffe000, 0,      SROM13_SWCTRLMAP4_TX5G_FEM7TO4, 0xffff},
-	{"swctrlmap4_RX5g_fem7to4", 0xffffe000, 0,      SROM13_SWCTRLMAP4_RX5G_FEM7TO4, 0xffff},
-	{"swctrlmap4_RXByp5g_fem7to4", 0xffffe000, 0, SROM13_SWCTRLMAP4_RXBYP5G_FEM7TO4, 0xffff},
-	{"swctrlmap4_misc5g_fem7to4", 0xffffe000, 0,  SROM13_SWCTRLMAP4_MISC5G_FEM7TO4, 0xffff},
-	{NULL,		0,		0,		0,			0}
-};
-
-static const sromvar_t perpath_pci_sromvars[] = {
-	{"maxp2ga",	0x000000f0,	0,		SROM4_2G_ITT_MAXP,	0x00ff},
-	{"itt2ga",	0x000000f0,	0,		SROM4_2G_ITT_MAXP,	0xff00},
-	{"itt5ga",	0x000000f0,	0,		SROM4_5G_ITT_MAXP,	0xff00},
-	{"pa2gw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA,		0xffff},
-	{"pa2gw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA + 1,	0xffff},
-	{"pa2gw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA + 2,	0xffff},
-	{"pa2gw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA + 3,	0xffff},
-	{"maxp5ga",	0x000000f0,	0,		SROM4_5G_ITT_MAXP,	0x00ff},
-	{"maxp5gha",	0x000000f0,	0,		SROM4_5GLH_MAXP,	0x00ff},
-	{"maxp5gla",	0x000000f0,	0,		SROM4_5GLH_MAXP,	0xff00},
-	{"pa5gw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA,		0xffff},
-	{"pa5gw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA + 1,	0xffff},
-	{"pa5gw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA + 2,	0xffff},
-	{"pa5gw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA + 3,	0xffff},
-	{"pa5glw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA,		0xffff},
-	{"pa5glw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA + 1,	0xffff},
-	{"pa5glw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA + 2,	0xffff},
-	{"pa5glw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA + 3,	0xffff},
-	{"pa5ghw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA,		0xffff},
-	{"pa5ghw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA + 1,	0xffff},
-	{"pa5ghw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA + 2,	0xffff},
-	{"pa5ghw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA + 3,	0xffff},
-	{"maxp2ga",	0x00000700,	0,		SROM8_2G_ITT_MAXP,	0x00ff},
-	{"itt2ga",	0x00000700,	0,		SROM8_2G_ITT_MAXP,	0xff00},
-	{"itt5ga",	0x00000700,	0,		SROM8_5G_ITT_MAXP,	0xff00},
-	{"pa2gw0a",	0x00000700,	SRFL_PRHEX,	SROM8_2G_PA,		0xffff},
-	{"pa2gw1a",	0x00000700,	SRFL_PRHEX,	SROM8_2G_PA + 1,	0xffff},
-	{"pa2gw2a",	0x00000700,	SRFL_PRHEX,	SROM8_2G_PA + 2,	0xffff},
-	{"maxp5ga",	0x00000700,	0,		SROM8_5G_ITT_MAXP,	0x00ff},
-	{"maxp5gha",	0x00000700,	0,		SROM8_5GLH_MAXP,	0x00ff},
-	{"maxp5gla",	0x00000700,	0,		SROM8_5GLH_MAXP,	0xff00},
-	{"pa5gw0a",	0x00000700,	SRFL_PRHEX,	SROM8_5G_PA,		0xffff},
-	{"pa5gw1a",	0x00000700,	SRFL_PRHEX,	SROM8_5G_PA + 1,	0xffff},
-	{"pa5gw2a",	0x00000700,	SRFL_PRHEX,	SROM8_5G_PA + 2,	0xffff},
-	{"pa5glw0a",	0x00000700,	SRFL_PRHEX,	SROM8_5GL_PA,		0xffff},
-	{"pa5glw1a",	0x00000700,	SRFL_PRHEX,	SROM8_5GL_PA + 1,	0xffff},
-	{"pa5glw2a",	0x00000700,	SRFL_PRHEX,	SROM8_5GL_PA + 2,	0xffff},
-	{"pa5ghw0a",	0x00000700,	SRFL_PRHEX,	SROM8_5GH_PA,		0xffff},
-	{"pa5ghw1a",	0x00000700,	SRFL_PRHEX,	SROM8_5GH_PA + 1,	0xffff},
-	{"pa5ghw2a",	0x00000700,	SRFL_PRHEX,	SROM8_5GH_PA + 2,	0xffff},
-
-	/* sromrev 11 */
-	{"maxp2ga",	0xfffff800,	0,			 SROM11_2G_MAXP,	0x00ff},
-	{"pa2ga",	0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA,		0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA + 1,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX,		 SROM11_2G_PA + 2,	0xffff},
-	{"rxgains5gmelnagaina",	0x00000800,	0,		 SROM11_RXGAINS1,	0x0007},
-	{"rxgains5gmtrisoa",	0x00000800,	0,		 SROM11_RXGAINS1,	0x0078},
-	{"rxgains5gmtrelnabypa", 0x00000800,	0,		 SROM11_RXGAINS1,	0x0080},
-	{"rxgains5ghelnagaina",	0x00000800,	0,		 SROM11_RXGAINS1,	0x0700},
-	{"rxgains5ghtrisoa",	0x00000800,	0,		 SROM11_RXGAINS1,	0x7800},
-	{"rxgains5ghtrelnabypa", 0x00000800,	0,		 SROM11_RXGAINS1,	0x8000},
-	{"rxgains2gelnagaina",	0x00000800,	0,		 SROM11_RXGAINS,	0x0007},
-	{"rxgains2gtrisoa",	0x00000800,	0,		 SROM11_RXGAINS,	0x0078},
-	{"rxgains2gtrelnabypa",	0x00000800,	0,		 SROM11_RXGAINS,	0x0080},
-	{"rxgains5gelnagaina",	0x00000800,	0,		 SROM11_RXGAINS,	0x0700},
-	{"rxgains5gtrisoa",	0x00000800,	0,		 SROM11_RXGAINS,	0x7800},
-	{"rxgains5gtrelnabypa",	0x00000800,	0,		 SROM11_RXGAINS,	0x8000},
-	{"maxp5ga",	0x00000800,	SRFL_ARRAY,		 SROM11_5GB1B0_MAXP,	0x00ff},
-	{"",		0x00000800,	SRFL_ARRAY,		 SROM11_5GB1B0_MAXP,	0xff00},
-	{"",		0x00000800,	SRFL_ARRAY,		 SROM11_5GB3B2_MAXP,	0x00ff},
-	{"",		0x00000800,	0,			 SROM11_5GB3B2_MAXP,	0xff00},
-	{"pa5ga",	0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 1,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 2,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 1,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 2,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 1,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 2,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA + 1,	0xffff},
-	{"",		0x00000800,	SRFL_PRHEX,		 SROM11_5GB3_PA + 2,	0xffff},
-
-	/* sromrev 12 */
-	{"maxp5gb4a",	0xfffff000,	0,		 SROM12_5GB42G_MAXP,	0x00ff00},
-	{"pa2ga",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,  SROM12_2GB0_PA_W0,	0x00ffff},
-	{"",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,	  SROM12_2GB0_PA_W1,	0x00ffff},
-	{"",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,	  SROM12_2GB0_PA_W2,	0x00ffff},
-	{"",	0xfffff000,	SRFL_PRHEX,		 SROM12_2GB0_PA_W3,	0x00ffff},
-
-	{"pa2g40a",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,  SROM12_2G40B0_PA_W0,	0x00ffff},
-	{"",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,	  SROM12_2G40B0_PA_W1,	0x00ffff},
-	{"",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,	  SROM12_2G40B0_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX,		 SROM12_2G40B0_PA_W3,	0x00ffff},
-	{"maxp5gb0a",	0xfffff000, 0,	     SROM12_5GB1B0_MAXP,	0x00ff},
-	{"maxp5gb1a",	0xfffff000, 0,       SROM12_5GB1B0_MAXP,	0x00ff00},
-	{"maxp5gb2a",	0xfffff000, 0,	     SROM12_5GB3B2_MAXP,	0x00ff},
-	{"maxp5gb3a",	0xfffff000, 0,	     SROM12_5GB3B2_MAXP,	0x00ff00},
-
-	{"pa5ga",   0xfffff000, SRFL_PRHEX | SRFL_ARRAY,   SROM12_5GB0_PA_W0,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB0_PA_W1,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,         SROM12_5GB0_PA_W2,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB0_PA_W3,		0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB1_PA_W0,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB1_PA_W1,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB1_PA_W2,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB1_PA_W3,		0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB2_PA_W0,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB2_PA_W1,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB2_PA_W2,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB2_PA_W3,		0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB3_PA_W0,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB3_PA_W1,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,         SROM12_5GB3_PA_W2,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB3_PA_W3,		0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB4_PA_W0,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB4_PA_W1,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB4_PA_W2,		0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX,	                   SROM12_5GB4_PA_W3,		0x00ffff},
-
-	{"pa5g40a",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY, SROM12_5G40B0_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B0_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B0_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B0_PA_W3,	0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B1_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B1_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B1_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,         SROM12_5G40B1_PA_W3,	0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B2_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B2_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B2_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B2_PA_W3,	0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B3_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B3_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B3_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B3_PA_W3,	0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B4_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B4_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B4_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX,		             SROM12_5G40B4_PA_W3,	0x00ffff},
-
-	{"pa5g80a",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	 SROM12_5G80B0_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B0_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B0_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B0_PA_W3,	0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B1_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B1_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B1_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B1_PA_W3,	0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B2_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B2_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B2_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B2_PA_W3,	0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B3_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B3_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B3_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B3_PA_W3,	0x00ffff},
-
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B4_PA_W0,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B4_PA_W1,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B4_PA_W2,	0x00ffff},
-	{"",	0xfffff000, SRFL_PRHEX,		                 SROM12_5G80B4_PA_W3,	0x00ffff},
-	/* sromrev 13 */
-	{"rxgains2gelnagaina",   0xffffe000,     0,       SROM13_RXGAINS,  0x0007},
-	{"rxgains2gtrisoa",     0xffffe000,     0,       SROM13_RXGAINS,  0x0078},
-	{"rxgains2gtrelnabypa", 0xffffe000,     0,       SROM13_RXGAINS,  0x0080},
-	{"rxgains5gelnagaina",  0xffffe000,     0,       SROM13_RXGAINS,  0x0700},
-	{"rxgains5gtrisoa",     0xffffe000,     0,       SROM13_RXGAINS,  0x7800},
-	{"rxgains5gtrelnabypa", 0xffffe000,     0,       SROM13_RXGAINS,  0x8000},
-	{NULL,		0,		0,		0, 			0}
-};
-
-#if !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N))
-#define	PHY_TYPE_HT		7	/* HT-Phy value */
-#define	PHY_TYPE_N		4	/* N-Phy value */
-#endif /* !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N)) */
-#if !defined(PHY_TYPE_AC)
-#define	PHY_TYPE_AC		11	/* AC-Phy value */
-#endif /* !defined(PHY_TYPE_AC) */
-#if !defined(PHY_TYPE_LCN20)
-#define	PHY_TYPE_LCN20		12	/* LCN20-Phy value */
-#endif /* !defined(PHY_TYPE_LCN20) */
-#if !defined(PHY_TYPE_NULL)
-#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
-#endif /* !defined(PHY_TYPE_NULL) */
-
-typedef struct {
-	uint16	phy_type;
-	uint16	bandrange;
-	uint16	chain;
-	const char *vars;
-} pavars_t;
-
-static const pavars_t pavars[] = {
-	/* HTPHY */
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G,  0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G,  1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G,  2, "pa2gw0a2 pa2gw1a2 pa2gw2a2"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 2, "pa5glw0a2 pa5glw1a2 pa5glw2a2"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 2, "pa5gw0a2 pa5gw1a2 pa5gw2a2"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 0, "pa5gw0a3 pa5gw1a3 pa5gw2a3"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 1,  "pa5glw0a3 pa5glw1a3 pa5glw2a3"},
-	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 2, "pa5ghw0a3 pa5ghw1a3 pa5ghw2a3"},
-	/* NPHY */
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,  0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,  1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND0, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND0, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND1, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND1, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
-	/* ACPHY */
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  2, "pa2ga2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5ga2"},
-	/* LCN20PHY */
-	{PHY_TYPE_LCN20, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
-	{PHY_TYPE_NULL, 0, 0, ""}
-};
-
-
-static const pavars_t pavars_SROM12[] = {
-	/* ACPHY */
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  2, "pa2ga2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  0, "pa2g40a0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  1, "pa2g40a1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  2, "pa2g40a2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  0, "pa5ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  1, "pa5ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  2, "pa5ga2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  0, "pa5g40a0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  1, "pa5g40a1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  2, "pa5g40a2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  0, "pa5g80a0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  1, "pa5g80a1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  2, "pa5g80a2"},
-	{PHY_TYPE_NULL, 0, 0, ""}
-};
-
-static const pavars_t pavars_SROM13[] = {
-	/* ACPHY */
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  2, "pa2ga2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  3, "pa2ga3"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  0, "pa2g40a0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  1, "pa2g40a1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  2, "pa2g40a2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  3, "pa2g40a3"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  0, "pa5ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  1, "pa5ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  2, "pa5ga2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  3, "pa5ga3"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  0, "pa5g40a0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  1, "pa5g40a1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  2, "pa5g40a2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  3, "pa5g40a3"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  0, "pa5g80a0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  1, "pa5g80a1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  2, "pa5g80a2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  3, "pa5g80a3"},
-	{PHY_TYPE_NULL, 0, 0, ""}
-};
-
-/* pavars table when paparambwver is 1 */
-static const pavars_t pavars_bwver_1[] = {
-	/* ACPHY */
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2gccka0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga2"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5gbw40a0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5gbw80a0"},
-	{PHY_TYPE_NULL, 0, 0, ""}
-};
-
-/* pavars table when paparambwver is 2 */
-static const pavars_t pavars_bwver_2[] = {
-	/* ACPHY */
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5gbw4080a0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  3, "pa5gbw4080a1"},
-	{PHY_TYPE_NULL, 0, 0, ""}
-};
-
-/* pavars table when paparambwver is 3 */
-static const pavars_t pavars_bwver_3[] = {
-	/* ACPHY */
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  2, "pa2gccka0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  3, "pa2gccka1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5ga1"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5gbw4080a0"},
-	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  3, "pa5gbw4080a1"},
-	{PHY_TYPE_NULL, 0, 0, ""}
-};
-
-typedef struct {
-	uint16	phy_type;
-	uint16	bandrange;
-	const char *vars;
-} povars_t;
-
-static const povars_t povars[] = {
-	/* NPHY */
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,  "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 "
-	"mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 "
-	"mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 "
-	"mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 "
-	"mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"},
-	{PHY_TYPE_NULL, 0, ""}
-};
-
-typedef struct {
-	uint8	tag;		/* Broadcom subtag name */
-	uint32	revmask;	/* Supported cis_sromrev bitmask. Some of the parameters in
-				 * different tuples have the same name. Therefore, the MFGc tool
-				 * needs to know which tuple to generate when seeing these
-				 * parameters (given that we know sromrev from user input, like the
-				 * nvram file).
-				 */
-	uint8	len;		/* Length field of the tuple, note that it includes the
-				 * subtag name (1 byte): 1 + tuple content length
-				 */
-	const char *params;
-} cis_tuple_t;
-
-#define OTP_RAW		(0xff - 1)	/* Reserved tuple number for wrvar Raw input */
-#define OTP_VERS_1	(0xff - 2)	/* CISTPL_VERS_1 */
-#define OTP_MANFID	(0xff - 3)	/* CISTPL_MANFID */
-#define OTP_RAW1	(0xff - 4)	/* Like RAW, but comes first */
-
-/** this array is used by CIS creating/writing applications */
-static const cis_tuple_t cis_hnbuvars[] = {
-/*       tag			revmask   len  params */
-	{OTP_RAW1,		0xffffffff, 0, ""},	/* special case */
-	{OTP_VERS_1,	0xffffffff, 0, "smanf sproductname"},	/* special case (non BRCM tuple) */
-	{OTP_MANFID,	0xffffffff, 4, "2manfid 2prodid"},	/* special case (non BRCM tuple) */
-	/* Unified OTP: tupple to embed USB manfid inside SDIO CIS */
-	{HNBU_UMANFID,		0xffffffff, 8, "8usbmanfid"},
-	{HNBU_SROMREV,		0xffffffff, 2, "1sromrev"},
-	/* NOTE: subdevid is also written to boardtype.
-	 *       Need to write HNBU_BOARDTYPE to change it if it is different.
-	 */
-	{HNBU_CHIPID,		0xffffffff, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"},
-	{HNBU_BOARDREV,		0xffffffff, 3, "2boardrev"},
-	{HNBU_PAPARMS,		0xffffffff, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"},
-	{HNBU_AA,		0xffffffff, 3, "1aa2g 1aa5g"},
-	{HNBU_AA,		0xffffffff, 3, "1aa0 1aa1"}, /* backward compatibility */
-	{HNBU_AG,		0xffffffff, 5, "1ag0 1ag1 1ag2 1ag3"},
-	{HNBU_BOARDFLAGS,	0xffffffff, 21, "4boardflags 4boardflags2 4boardflags3 "
-	"4boardflags4 4boardflags5 "},
-	{HNBU_LEDS,		0xffffffff, 17, "1ledbh0 1ledbh1 1ledbh2 1ledbh3 1ledbh4 1ledbh5 "
-	"1ledbh6 1ledbh7 1ledbh8 1ledbh9 1ledbh10 1ledbh11 1ledbh12 1ledbh13 1ledbh14 1ledbh15"},
-	{HNBU_CCODE,		0xffffffff, 4, "2ccode 1cctl"},
-	{HNBU_CCKPO,		0xffffffff, 3, "2cckpo"},
-	{HNBU_OFDMPO,		0xffffffff, 5, "4ofdmpo"},
-	{HNBU_PAPARMS5G,	0xffffffff, 23, "2pa1b0 2pa1b1 2pa1b2 2pa1lob0 2pa1lob1 2pa1lob2 "
-	"2pa1hib0 2pa1hib1 2pa1hib2 1pa1itssit "
-	"1pa1maxpwr 1pa1lomaxpwr 1pa1himaxpwr"},
-	{HNBU_RDLID,		0xffffffff, 3, "2rdlid"},
-	{HNBU_RSSISMBXA2G, 0xffffffff, 3, "0rssismf2g 0rssismc2g "
-	"0rssisav2g 0bxa2g"}, /* special case */
-	{HNBU_RSSISMBXA5G, 0xffffffff, 3, "0rssismf5g 0rssismc5g "
-	"0rssisav5g 0bxa5g"}, /* special case */
-	{HNBU_XTALFREQ,		0xffffffff, 5, "4xtalfreq"},
-	{HNBU_TRI2G,		0xffffffff, 2, "1tri2g"},
-	{HNBU_TRI5G,		0xffffffff, 4, "1tri5gl 1tri5g 1tri5gh"},
-	{HNBU_RXPO2G,		0xffffffff, 2, "1rxpo2g"},
-	{HNBU_RXPO5G,		0xffffffff, 2, "1rxpo5g"},
-	{HNBU_BOARDNUM,		0xffffffff, 3, "2boardnum"},
-	{HNBU_MACADDR,		0xffffffff, 7, "6macaddr"},	/* special case */
-	{HNBU_RDLSN,		0xffffffff, 3, "2rdlsn"},
-	{HNBU_BOARDTYPE,	0xffffffff, 3, "2boardtype"},
-	{HNBU_LEDDC,		0xffffffff, 3, "2leddc"},
-	{HNBU_RDLRNDIS,		0xffffffff, 2, "1rdlndis"},
-	{HNBU_CHAINSWITCH,	0xffffffff, 5, "1txchain 1rxchain 2antswitch"},
-	{HNBU_REGREV,		0xffffffff, 2, "1regrev"},
-	{HNBU_FEM,		0x000007fe, 5, "0antswctl2g 0triso2g 0pdetrange2g 0extpagain2g "
-	"0tssipos2g 0antswctl5g 0triso5g 0pdetrange5g 0extpagain5g 0tssipos5g"}, /* special case */
-	{HNBU_PAPARMS_C0,	0x000007fe, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 "
-	"2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 2pa5gw1a0 2pa5gw2a0 "
-	"2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 2pa5ghw1a0 2pa5ghw2a0"},
-	{HNBU_PAPARMS_C1,	0x000007fe, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 "
-	"2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 2pa5gw1a1 2pa5gw2a1 "
-	"2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 2pa5ghw1a1 2pa5ghw2a1"},
-	{HNBU_PO_CCKOFDM,	0xffffffff, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo "
-	"4ofdm5ghpo"},
-	{HNBU_PO_MCS2G,		0xffffffff, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 "
-	"2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"},
-	{HNBU_PO_MCS5GM,	0xffffffff, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 "
-	"2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"},
-	{HNBU_PO_MCS5GLH,	0xffffffff, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 "
-	"2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 "
-	"2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 "
-	"2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"},
-	{HNBU_CCKFILTTYPE,	0xffffffff, 2, "1cckdigfilttype"},
-	{HNBU_PO_CDD,		0xffffffff, 3, "2cddpo"},
-	{HNBU_PO_STBC,		0xffffffff, 3, "2stbcpo"},
-	{HNBU_PO_40M,		0xffffffff, 3, "2bw40po"},
-	{HNBU_PO_40MDUP,	0xffffffff, 3, "2bwduppo"},
-	{HNBU_RDLRWU,		0xffffffff, 2, "1rdlrwu"},
-	{HNBU_WPS,		0xffffffff, 3, "1wpsgpio 1wpsled"},
-	{HNBU_USBFS,		0xffffffff, 2, "1usbfs"},
-	{HNBU_ELNA2G,           0xffffffff, 2, "1elna2g"},
-	{HNBU_ELNA5G,           0xffffffff, 2, "1elna5g"},
-	{HNBU_CUSTOM1,		0xffffffff, 5, "4customvar1"},
-	{OTP_RAW,		0xffffffff, 0, ""},	/* special case */
-	{HNBU_OFDMPO5G,		0xffffffff, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"},
-	{HNBU_USBEPNUM,		0xffffffff, 3, "2usbepnum"},
-	{HNBU_CCKBW202GPO,	0xffffffff, 7, "2cckbw202gpo 2cckbw20ul2gpo 2cckbw20in802gpo"},
-	{HNBU_LEGOFDMBW202GPO,	0xffffffff, 9, "4legofdmbw202gpo 4legofdmbw20ul2gpo"},
-	{HNBU_LEGOFDMBW205GPO,	0xffffffff, 25, "4legofdmbw205glpo 4legofdmbw20ul5glpo "
-	"4legofdmbw205gmpo 4legofdmbw20ul5gmpo 4legofdmbw205ghpo 4legofdmbw20ul5ghpo"},
-	{HNBU_MCS2GPO,	0xffffffff, 17,	"4mcsbw202gpo 4mcsbw20ul2gpo 4mcsbw402gpo 4mcsbw802gpo"},
-	{HNBU_MCS5GLPO,	0xffffffff, 13,	"4mcsbw205glpo 4mcsbw20ul5glpo 4mcsbw405glpo"},
-	{HNBU_MCS5GMPO,	0xffffffff, 13,	"4mcsbw205gmpo 4mcsbw20ul5gmpo 4mcsbw405gmpo"},
-	{HNBU_MCS5GHPO,	0xffffffff, 13,	"4mcsbw205ghpo 4mcsbw20ul5ghpo 4mcsbw405ghpo"},
-	{HNBU_MCS32PO,	0xffffffff, 3,	"2mcs32po"},
-	{HNBU_LEG40DUPPO,	0xffffffff, 3,	"2legofdm40duppo"},
-	{HNBU_TEMPTHRESH,	0xffffffff, 7,	"1tempthresh 0temps_period 0temps_hysteresis "
-	"1tempoffset 1tempsense_slope 0tempcorrx 0tempsense_option "
-	"1phycal_tempdelta"}, /* special case */
-	{HNBU_MUXENAB,		0xffffffff, 2,	"1muxenab"},
-	{HNBU_FEM_CFG,		0xfffff800, 5,	"0femctrl 0papdcap2g 0tworangetssi2g 0pdgain2g "
-	"0epagain2g 0tssiposslope2g 0gainctrlsph 0papdcap5g 0tworangetssi5g 0pdgain5g 0epagain5g "
-	"0tssiposslope5g"}, /* special case */
-	{HNBU_ACPA_C0,		0xfffff800, 39,	"2subband5gver 2maxp2ga0 2*3pa2ga0 "
-	"1*4maxp5ga0 2*12pa5ga0"},
-	{HNBU_ACPA_C1,		0xfffff800, 37,	"2maxp2ga1 2*3pa2ga1 1*4maxp5ga1 2*12pa5ga1"},
-	{HNBU_ACPA_C2,		0xfffff800, 37,	"2maxp2ga2 2*3pa2ga2 1*4maxp5ga2 2*12pa5ga2"},
-	{HNBU_MEAS_PWR,		0xfffff800, 5,	"1measpower 1measpower1 1measpower2 2rawtempsense"},
-	{HNBU_PDOFF,		0xfffff800, 13,	"2pdoffset40ma0 2pdoffset40ma1 2pdoffset40ma2 "
-	"2pdoffset80ma0 2pdoffset80ma1 2pdoffset80ma2"},
-	{HNBU_ACPPR_2GPO,	0xfffff800, 13,	"2dot11agofdmhrbw202gpo 2ofdmlrbw202gpo "
-	"2sb20in40dot11agofdm2gpo 2sb20in80dot11agofdm2gpo 2sb20in40ofdmlrbw202gpo "
-	"2sb20in80ofdmlrbw202gpo"},
-	{HNBU_ACPPR_5GPO,	0xfffff800, 59,	"4mcsbw805glpo 4mcsbw1605glpo 4mcsbw805gmpo "
-	"4mcsbw1605gmpo 4mcsbw805ghpo 4mcsbw1605ghpo 2mcslr5glpo 2mcslr5gmpo 2mcslr5ghpo "
-	"4mcsbw80p805glpo 4mcsbw80p805gmpo 4mcsbw80p805ghpo 4mcsbw80p805gx1po 2mcslr5gx1po "
-	"2mcslr5g80p80po 4mcsbw805gx1po 4mcsbw1605gx1po"},
-	{HNBU_MCS5Gx1PO,	0xfffff800, 9,	"4mcsbw205gx1po 4mcsbw405gx1po"},
-	{HNBU_ACPPR_SBPO,	0xfffff800, 49,	"2sb20in40hrpo 2sb20in80and160hr5glpo "
-	"2sb40and80hr5glpo 2sb20in80and160hr5gmpo 2sb40and80hr5gmpo 2sb20in80and160hr5ghpo "
-	"2sb40and80hr5ghpo 2sb20in40lrpo 2sb20in80and160lr5glpo 2sb40and80lr5glpo "
-	"2sb20in80and160lr5gmpo 2sb40and80lr5gmpo 2sb20in80and160lr5ghpo 2sb40and80lr5ghpo "
-	"4dot11agduphrpo 4dot11agduplrpo 2sb20in40and80hrpo 2sb20in40and80lrpo "
-	"2sb20in80and160hr5gx1po 2sb20in80and160lr5gx1po 2sb40and80hr5gx1po 2sb40and80lr5gx1po "
-	},
-	{HNBU_ACPPR_SB8080_PO, 0xfffff800, 23, "2sb2040and80in80p80hr5glpo "
-	"2sb2040and80in80p80lr5glpo 2sb2040and80in80p80hr5gmpo "
-	"2sb2040and80in80p80lr5gmpo 2sb2040and80in80p80hr5ghpo 2sb2040and80in80p80lr5ghpo "
-	"2sb2040and80in80p80hr5gx1po 2sb2040and80in80p80lr5gx1po 2sb20in80p80hr5gpo "
-	"2sb20in80p80lr5gpo 2dot11agduppo"},
-	{HNBU_NOISELVL,		0xfffff800, 16, "1noiselvl2ga0 1noiselvl2ga1 1noiselvl2ga2 "
-	"1*4noiselvl5ga0 1*4noiselvl5ga1 1*4noiselvl5ga2"},
-	{HNBU_RXGAIN_ERR,	0xfffff800, 16, "1rxgainerr2ga0 1rxgainerr2ga1 1rxgainerr2ga2 "
-	"1*4rxgainerr5ga0 1*4rxgainerr5ga1 1*4rxgainerr5ga2"},
-	{HNBU_AGBGA,		0xfffff800, 7, "1agbg0 1agbg1 1agbg2 1aga0 1aga1 1aga2"},
-	{HNBU_USBDESC_COMPOSITE, 0xffffffff, 3, "2usbdesc_composite"},
-	{HNBU_UUID, 		0xffffffff, 17,	"16uuid"},
-	{HNBU_WOWLGPIO,		0xffffffff, 2,  "1wowl_gpio"},
-	{HNBU_ACRXGAINS_C0,	0xfffff800, 5, "0rxgains5gtrelnabypa0 0rxgains5gtrisoa0 "
-	"0rxgains5gelnagaina0 0rxgains2gtrelnabypa0 0rxgains2gtrisoa0 0rxgains2gelnagaina0 "
-	"0rxgains5ghtrelnabypa0 0rxgains5ghtrisoa0 0rxgains5ghelnagaina0 0rxgains5gmtrelnabypa0 "
-	"0rxgains5gmtrisoa0 0rxgains5gmelnagaina0"},	/* special case */
-	{HNBU_ACRXGAINS_C1,	0xfffff800, 5, "0rxgains5gtrelnabypa1 0rxgains5gtrisoa1 "
-	"0rxgains5gelnagaina1 0rxgains2gtrelnabypa1 0rxgains2gtrisoa1 0rxgains2gelnagaina1 "
-	"0rxgains5ghtrelnabypa1 0rxgains5ghtrisoa1 0rxgains5ghelnagaina1 0rxgains5gmtrelnabypa1 "
-	"0rxgains5gmtrisoa1 0rxgains5gmelnagaina1"},	/* special case */
-	{HNBU_ACRXGAINS_C2,	0xfffff800, 5, "0rxgains5gtrelnabypa2 0rxgains5gtrisoa2 "
-	"0rxgains5gelnagaina2 0rxgains2gtrelnabypa2 0rxgains2gtrisoa2 0rxgains2gelnagaina2 "
-	"0rxgains5ghtrelnabypa2 0rxgains5ghtrisoa2 0rxgains5ghelnagaina2 0rxgains5gmtrelnabypa2 "
-	"0rxgains5gmtrisoa2 0rxgains5gmelnagaina2"},	/* special case */
-	{HNBU_TXDUTY, 		0xfffff800, 9,	"2tx_duty_cycle_ofdm_40_5g "
-	"2tx_duty_cycle_thresh_40_5g 2tx_duty_cycle_ofdm_80_5g 2tx_duty_cycle_thresh_80_5g"},
-	{HNBU_PDOFF_2G,		0xfffff800, 3,	"0pdoffset2g40ma0 0pdoffset2g40ma1 "
-	"0pdoffset2g40ma2 0pdoffset2g40mvalid"},
-	{HNBU_ACPA_CCK,		0xfffff800, 7,	"2*3pa2gccka0"},
-	{HNBU_ACPA_40,		0xfffff800, 25,	"2*12pa5gbw40a0"},
-	{HNBU_ACPA_80,		0xfffff800, 25,	"2*12pa5gbw80a0"},
-	{HNBU_ACPA_4080,	0xfffff800, 49,	"2*12pa5gbw4080a0 2*12pa5gbw4080a1"},
-	{HNBU_SUBBAND5GVER,	0xfffff800, 3,	"2subband5gver"},
-	{HNBU_PAPARAMBWVER,	0xfffff800, 2,	"1paparambwver"},
-	{HNBU_TXBFRPCALS,  0xfffff800, 11,
-	"2rpcal2g 2rpcal5gb0 2rpcal5gb1 2rpcal5gb2 2rpcal5gb3"}, /* txbf rpcalvars */
-	{HNBU_GPIO_PULL_DOWN,	0xffffffff, 5, "4gpdn"},
-	{0xFF,			0xffffffff, 0, ""}
-};
-
-#endif /* _bcmsrom_tbl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmutils.h b/drivers/net/wireless/bcmdhd/include/bcmutils.h
deleted file mode 100644
index 6cc925c..0000000
--- a/drivers/net/wireless/bcmdhd/include/bcmutils.h
+++ /dev/null
@@ -1,1302 +0,0 @@
-/*
- * Misc useful os-independent macros and functions.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmutils.h 563776 2015-06-15 15:51:15Z $
- */
-
-#ifndef	_bcmutils_h_
-#define	_bcmutils_h_
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define bcm_strncpy_s(dst, noOfElements, src, count)    strncpy((dst), (src), (count))
-#define bcm_strncat_s(dst, noOfElements, src, count)    strncat((dst), (src), (count))
-#define bcm_snprintf_s snprintf
-#define bcm_sprintf_s snprintf
-
-/*
- * #define bcm_strcpy_s(dst, count, src)            strncpy((dst), (src), (count))
- * Use bcm_strcpy_s instead as it is a safer option
- * bcm_strcat_s: Use bcm_strncat_s as a safer option
- *
- */
-
-/* ctype replacement */
-#define _BCM_U	0x01	/* upper */
-#define _BCM_L	0x02	/* lower */
-#define _BCM_D	0x04	/* digit */
-#define _BCM_C	0x08	/* cntrl */
-#define _BCM_P	0x10	/* punct */
-#define _BCM_S	0x20	/* white space (space/lf/tab) */
-#define _BCM_X	0x40	/* hex digit */
-#define _BCM_SP	0x80	/* hard space (0x20) */
-
-extern const unsigned char bcm_ctype[];
-#define bcm_ismask(x)	(bcm_ctype[(int)(unsigned char)(x)])
-
-#define bcm_isalnum(c)	((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0)
-#define bcm_isalpha(c)	((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0)
-#define bcm_iscntrl(c)	((bcm_ismask(c)&(_BCM_C)) != 0)
-#define bcm_isdigit(c)	((bcm_ismask(c)&(_BCM_D)) != 0)
-#define bcm_isgraph(c)	((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0)
-#define bcm_islower(c)	((bcm_ismask(c)&(_BCM_L)) != 0)
-#define bcm_isprint(c)	((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0)
-#define bcm_ispunct(c)	((bcm_ismask(c)&(_BCM_P)) != 0)
-#define bcm_isspace(c)	((bcm_ismask(c)&(_BCM_S)) != 0)
-#define bcm_isupper(c)	((bcm_ismask(c)&(_BCM_U)) != 0)
-#define bcm_isxdigit(c)	((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0)
-#define bcm_tolower(c)	(bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
-#define bcm_toupper(c)	(bcm_islower((c)) ? ((c) + 'A' - 'a') : (c))
-
-#define CIRCULAR_ARRAY_FULL(rd_idx, wr_idx, max) ((wr_idx + 1)%max == rd_idx)
-
-#define KB(bytes)	(((bytes) + 1023) / 1024)
-
-/* Buffer structure for collecting string-formatted data
-* using bcm_bprintf() API.
-* Use bcm_binit() to initialize before use
-*/
-
-struct bcmstrbuf {
-	char *buf;	/* pointer to current position in origbuf */
-	unsigned int size;	/* current (residual) size in bytes */
-	char *origbuf;	/* unmodified pointer to orignal buffer */
-	unsigned int origsize;	/* unmodified orignal buffer size in bytes */
-};
-
-#define BCMSTRBUF_LEN(b)	(b->size)
-#define BCMSTRBUF_BUF(b)	(b->buf)
-
-/* ** driver-only section ** */
-#ifdef BCMDRIVER
-#include <osl.h>
-#include <hnd_pktq.h>
-#include <hnd_pktpool.h>
-
-#define GPIO_PIN_NOTDEFINED 	0x20	/* Pin not defined */
-
-/*
- * Spin at most 'us' microseconds while 'exp' is true.
- * Caller should explicitly test 'exp' when this completes
- * and take appropriate error action if 'exp' is still true.
- */
-#ifndef SPINWAIT_POLL_PERIOD
-#define SPINWAIT_POLL_PERIOD	10
-#endif
-
-#define SPINWAIT(exp, us) { \
-	uint countdown = (us) + (SPINWAIT_POLL_PERIOD - 1); \
-	while ((exp) && (countdown >= SPINWAIT_POLL_PERIOD)) { \
-		OSL_DELAY(SPINWAIT_POLL_PERIOD); \
-		countdown -= SPINWAIT_POLL_PERIOD; \
-	} \
-}
-
-/* forward definition of ether_addr structure used by some function prototypes */
-
-struct ether_addr;
-
-extern int ether_isbcast(const void *ea);
-extern int ether_isnulladdr(const void *ea);
-
-#define BCM_MAC_RXCPL_IDX_BITS			12
-#define BCM_MAX_RXCPL_IDX_INVALID		0
-#define BCM_MAC_RXCPL_IFIDX_BITS		3
-#define BCM_MAC_RXCPL_DOT11_BITS		1
-#define BCM_MAX_RXCPL_IFIDX			((1 << BCM_MAC_RXCPL_IFIDX_BITS) - 1)
-#define BCM_MAC_RXCPL_FLAG_BITS			4
-#define BCM_RXCPL_FLAGS_IN_TRANSIT		0x1
-#define BCM_RXCPL_FLAGS_FIRST_IN_FLUSHLIST	0x2
-#define BCM_RXCPL_FLAGS_RXCPLVALID		0x4
-#define BCM_RXCPL_FLAGS_RSVD			0x8
-
-#define BCM_RXCPL_SET_IN_TRANSIT(a)	((a)->rxcpl_id.flags |= BCM_RXCPL_FLAGS_IN_TRANSIT)
-#define BCM_RXCPL_CLR_IN_TRANSIT(a)	((a)->rxcpl_id.flags &= ~BCM_RXCPL_FLAGS_IN_TRANSIT)
-#define BCM_RXCPL_IN_TRANSIT(a)		((a)->rxcpl_id.flags & BCM_RXCPL_FLAGS_IN_TRANSIT)
-
-#define BCM_RXCPL_SET_FRST_IN_FLUSH(a)	((a)->rxcpl_id.flags |= BCM_RXCPL_FLAGS_FIRST_IN_FLUSHLIST)
-#define BCM_RXCPL_CLR_FRST_IN_FLUSH(a)	((a)->rxcpl_id.flags &= ~BCM_RXCPL_FLAGS_FIRST_IN_FLUSHLIST)
-#define BCM_RXCPL_FRST_IN_FLUSH(a)	((a)->rxcpl_id.flags & BCM_RXCPL_FLAGS_FIRST_IN_FLUSHLIST)
-
-#define BCM_RXCPL_SET_VALID_INFO(a)	((a)->rxcpl_id.flags |= BCM_RXCPL_FLAGS_RXCPLVALID)
-#define BCM_RXCPL_CLR_VALID_INFO(a)	((a)->rxcpl_id.flags &= ~BCM_RXCPL_FLAGS_RXCPLVALID)
-#define BCM_RXCPL_VALID_INFO(a) (((a)->rxcpl_id.flags & BCM_RXCPL_FLAGS_RXCPLVALID) ? TRUE : FALSE)
-
-#define UP_TABLE_MAX	((IPV4_TOS_DSCP_MASK >> IPV4_TOS_DSCP_SHIFT) + 1)	/* 64 max */
-
-struct reorder_rxcpl_id_list {
-	uint16 head;
-	uint16 tail;
-	uint32 cnt;
-};
-
-typedef struct rxcpl_id {
-	uint32		idx : BCM_MAC_RXCPL_IDX_BITS;
-	uint32		next_idx : BCM_MAC_RXCPL_IDX_BITS;
-	uint32		ifidx : BCM_MAC_RXCPL_IFIDX_BITS;
-	uint32		dot11 : BCM_MAC_RXCPL_DOT11_BITS;
-	uint32		flags : BCM_MAC_RXCPL_FLAG_BITS;
-} rxcpl_idx_id_t;
-
-typedef struct rxcpl_data_len {
-	uint32		metadata_len_w : 6;
-	uint32		dataoffset: 10;
-	uint32		datalen : 16;
-} rxcpl_data_len_t;
-
-typedef struct rxcpl_info {
-	rxcpl_idx_id_t		rxcpl_id;
-	uint32		host_pktref;
-	union {
-		rxcpl_data_len_t	rxcpl_len;
-		struct rxcpl_info	*free_next;
-	};
-} rxcpl_info_t;
-
-/* rx completion list */
-typedef struct bcm_rxcplid_list {
-	uint32			max;
-	uint32			avail;
-	rxcpl_info_t		*rxcpl_ptr;
-	rxcpl_info_t		*free_list;
-} bcm_rxcplid_list_t;
-
-extern bool bcm_alloc_rxcplid_list(osl_t *osh, uint32 max);
-extern rxcpl_info_t * bcm_alloc_rxcplinfo(void);
-extern void bcm_free_rxcplinfo(rxcpl_info_t *ptr);
-extern void bcm_chain_rxcplid(uint16 first,  uint16 next);
-extern rxcpl_info_t *bcm_id2rxcplinfo(uint16 id);
-extern uint16 bcm_rxcplinfo2id(rxcpl_info_t *ptr);
-extern rxcpl_info_t *bcm_rxcpllist_end(rxcpl_info_t *ptr, uint32 *count);
-
-/* externs */
-/* packet */
-extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf);
-extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf);
-extern uint pkttotlen(osl_t *osh, void *p);
-extern void *pktlast(osl_t *osh, void *p);
-extern uint pktsegcnt(osl_t *osh, void *p);
-extern uint pktsegcnt_war(osl_t *osh, void *p);
-extern uint8 *pktdataoffset(osl_t *osh, void *p,  uint offset);
-extern void *pktoffset(osl_t *osh, void *p,  uint offset);
-
-/* Get priority from a packet and pass it back in scb (or equiv) */
-#define	PKTPRIO_VDSCP	0x100		/* DSCP prio found after VLAN tag */
-#define	PKTPRIO_VLAN	0x200		/* VLAN prio found */
-#define	PKTPRIO_UPD	0x400		/* DSCP used to update VLAN prio */
-#define	PKTPRIO_DSCP	0x800		/* DSCP prio found */
-
-/* DSCP type definitions (RFC4594) */
-/* AF1x: High-Throughput Data (RFC2597) */
-#define DSCP_AF11	0x0A
-#define DSCP_AF12	0x0C
-#define DSCP_AF13	0x0E
-/* AF2x: Low-Latency Data (RFC2597) */
-#define DSCP_AF21	0x12
-#define DSCP_AF22	0x14
-#define DSCP_AF23	0x16
-/* AF3x: Multimedia Streaming (RFC2597) */
-#define DSCP_AF31	0x1A
-#define DSCP_AF32	0x1C
-#define DSCP_AF33	0x1E
-/* EF: Telephony (RFC3246) */
-#define DSCP_EF		0x2E
-
-extern uint pktsetprio(void *pkt, bool update_vtag);
-extern uint pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag);
-extern bool pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp);
-
-/* string */
-extern int bcm_atoi(const char *s);
-extern ulong bcm_strtoul(const char *cp, char **endp, uint base);
-extern char *bcmstrstr(const char *haystack, const char *needle);
-extern char *bcmstrnstr(const char *s, uint s_len, const char *substr, uint substr_len);
-extern char *bcmstrcat(char *dest, const char *src);
-extern char *bcmstrncat(char *dest, const char *src, uint size);
-extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen);
-char* bcmstrtok(char **string, const char *delimiters, char *tokdelim);
-int bcmstricmp(const char *s1, const char *s2);
-int bcmstrnicmp(const char* s1, const char* s2, int cnt);
-
-
-/* ethernet address */
-extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf);
-extern int bcm_ether_atoe(const char *p, struct ether_addr *ea);
-
-/* ip address */
-struct ipv4_addr;
-extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf);
-extern char *bcm_ipv6_ntoa(void *ipv6, char *buf);
-extern int bcm_atoipv4(const char *p, struct ipv4_addr *ip);
-
-/* delay */
-extern void bcm_mdelay(uint ms);
-/* variable access */
-#define NVRAM_RECLAIM_CHECK(name)
-
-extern char *getvar(char *vars, const char *name);
-extern int getintvar(char *vars, const char *name);
-extern int getintvararray(char *vars, const char *name, int index);
-extern int getintvararraysize(char *vars, const char *name);
-extern uint getgpiopin(char *vars, char *pin_name, uint def_pin);
-#define bcm_perf_enable()
-#define bcmstats(fmt)
-#define	bcmlog(fmt, a1, a2)
-#define	bcmdumplog(buf, size)	*buf = '\0'
-#define	bcmdumplogent(buf, idx)	-1
-
-#define TSF_TICKS_PER_MS	1000
-#define TS_ENTER		0xdeadbeef	/* Timestamp profiling enter */
-#define TS_EXIT			0xbeefcafe	/* Timestamp profiling exit */
-
-#define bcmtslog(tstamp, fmt, a1, a2)
-#define bcmprinttslogs()
-#define bcmprinttstamp(us)
-#define bcmdumptslog(b)
-
-extern char *bcm_nvram_vars(uint *length);
-extern int bcm_nvram_cache(void *sih);
-
-/* Support for sharing code across in-driver iovar implementations.
- * The intent is that a driver use this structure to map iovar names
- * to its (private) iovar identifiers, and the lookup function to
- * find the entry.  Macros are provided to map ids and get/set actions
- * into a single number space for a switch statement.
- */
-
-/* iovar structure */
-typedef struct bcm_iovar {
-	const char *name;	/* name for lookup and display */
-	uint16 varid;		/* id for switch */
-	uint16 flags;		/* driver-specific flag bits */
-	uint16 type;		/* base type of argument */
-	uint16 minlen;		/* min length for buffer vars */
-} bcm_iovar_t;
-
-/* varid definitions are per-driver, may use these get/set bits */
-
-/* IOVar action bits for id mapping */
-#define IOV_GET 0 /* Get an iovar */
-#define IOV_SET 1 /* Set an iovar */
-
-/* Varid to actionid mapping */
-#define IOV_GVAL(id)		((id) * 2)
-#define IOV_SVAL(id)		((id) * 2 + IOV_SET)
-#define IOV_ISSET(actionid)	((actionid & IOV_SET) == IOV_SET)
-#define IOV_ID(actionid)	(actionid >> 1)
-
-/* flags are per-driver based on driver attributes */
-
-extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name);
-extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set);
-#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
-	defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
-extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len);
-#endif 
-#endif	/* BCMDRIVER */
-
-/* Base type definitions */
-#define IOVT_VOID	0	/* no value (implictly set only) */
-#define IOVT_BOOL	1	/* any value ok (zero/nonzero) */
-#define IOVT_INT8	2	/* integer values are range-checked */
-#define IOVT_UINT8	3	/* unsigned int 8 bits */
-#define IOVT_INT16	4	/* int 16 bits */
-#define IOVT_UINT16	5	/* unsigned int 16 bits */
-#define IOVT_INT32	6	/* int 32 bits */
-#define IOVT_UINT32	7	/* unsigned int 32 bits */
-#define IOVT_BUFFER	8	/* buffer is size-checked as per minlen */
-#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER)
-
-/* Initializer for IOV type strings */
-#define BCM_IOV_TYPE_INIT { \
-	"void", \
-	"bool", \
-	"int8", \
-	"uint8", \
-	"int16", \
-	"uint16", \
-	"int32", \
-	"uint32", \
-	"buffer", \
-	"" }
-
-#define BCM_IOVT_IS_INT(type) (\
-	(type == IOVT_BOOL) || \
-	(type == IOVT_INT8) || \
-	(type == IOVT_UINT8) || \
-	(type == IOVT_INT16) || \
-	(type == IOVT_UINT16) || \
-	(type == IOVT_INT32) || \
-	(type == IOVT_UINT32))
-
-/* ** driver/apps-shared section ** */
-
-#define BCME_STRLEN 		64	/* Max string length for BCM errors */
-#define VALID_BCMERROR(e)  ((e <= 0) && (e >= BCME_LAST))
-
-
-/*
- * error codes could be added but the defined ones shouldn't be changed/deleted
- * these error codes are exposed to the user code
- * when ever a new error code is added to this list
- * please update errorstring table with the related error string and
- * update osl files with os specific errorcode map
-*/
-
-#define BCME_OK				0	/* Success */
-#define BCME_ERROR			-1	/* Error generic */
-#define BCME_BADARG			-2	/* Bad Argument */
-#define BCME_BADOPTION			-3	/* Bad option */
-#define BCME_NOTUP			-4	/* Not up */
-#define BCME_NOTDOWN			-5	/* Not down */
-#define BCME_NOTAP			-6	/* Not AP */
-#define BCME_NOTSTA			-7	/* Not STA  */
-#define BCME_BADKEYIDX			-8	/* BAD Key Index */
-#define BCME_RADIOOFF 			-9	/* Radio Off */
-#define BCME_NOTBANDLOCKED		-10	/* Not  band locked */
-#define BCME_NOCLK			-11	/* No Clock */
-#define BCME_BADRATESET			-12	/* BAD Rate valueset */
-#define BCME_BADBAND			-13	/* BAD Band */
-#define BCME_BUFTOOSHORT		-14	/* Buffer too short */
-#define BCME_BUFTOOLONG			-15	/* Buffer too long */
-#define BCME_BUSY			-16	/* Busy */
-#define BCME_NOTASSOCIATED		-17	/* Not Associated */
-#define BCME_BADSSIDLEN			-18	/* Bad SSID len */
-#define BCME_OUTOFRANGECHAN		-19	/* Out of Range Channel */
-#define BCME_BADCHAN			-20	/* Bad Channel */
-#define BCME_BADADDR			-21	/* Bad Address */
-#define BCME_NORESOURCE			-22	/* Not Enough Resources */
-#define BCME_UNSUPPORTED		-23	/* Unsupported */
-#define BCME_BADLEN			-24	/* Bad length */
-#define BCME_NOTREADY			-25	/* Not Ready */
-#define BCME_EPERM			-26	/* Not Permitted */
-#define BCME_NOMEM			-27	/* No Memory */
-#define BCME_ASSOCIATED			-28	/* Associated */
-#define BCME_RANGE			-29	/* Not In Range */
-#define BCME_NOTFOUND			-30	/* Not Found */
-#define BCME_WME_NOT_ENABLED		-31	/* WME Not Enabled */
-#define BCME_TSPEC_NOTFOUND		-32	/* TSPEC Not Found */
-#define BCME_ACM_NOTSUPPORTED		-33	/* ACM Not Supported */
-#define BCME_NOT_WME_ASSOCIATION	-34	/* Not WME Association */
-#define BCME_SDIO_ERROR			-35	/* SDIO Bus Error */
-#define BCME_DONGLE_DOWN		-36	/* Dongle Not Accessible */
-#define BCME_VERSION			-37 	/* Incorrect version */
-#define BCME_TXFAIL			-38 	/* TX failure */
-#define BCME_RXFAIL			-39	/* RX failure */
-#define BCME_NODEVICE			-40 	/* Device not present */
-#define BCME_NMODE_DISABLED		-41 	/* NMODE disabled */
-#define BCME_NONRESIDENT		-42 /* access to nonresident overlay */
-#define BCME_SCANREJECT			-43 	/* reject scan request */
-#define BCME_USAGE_ERROR                -44     /* WLCMD usage error */
-#define BCME_IOCTL_ERROR                -45     /* WLCMD ioctl error */
-#define BCME_SERIAL_PORT_ERR            -46     /* RWL serial port error */
-#define BCME_DISABLED			-47     /* Disabled in this build */
-#define BCME_DECERR				-48		/* Decrypt error */
-#define BCME_ENCERR				-49		/* Encrypt error */
-#define BCME_MICERR				-50		/* Integrity/MIC error */
-#define BCME_REPLAY				-51		/* Replay */
-#define BCME_IE_NOTFOUND		-52		/* IE not found */
-#define BCME_DATA_NOTFOUND		-53		/* Complete data not found in buffer */
-#define BCME_LAST			BCME_DATA_NOTFOUND
-
-#define BCME_NOTENABLED BCME_DISABLED
-
-/* These are collection of BCME Error strings */
-#define BCMERRSTRINGTABLE {		\
-	"OK",				\
-	"Undefined error",		\
-	"Bad Argument",			\
-	"Bad Option",			\
-	"Not up",			\
-	"Not down",			\
-	"Not AP",			\
-	"Not STA",			\
-	"Bad Key Index",		\
-	"Radio Off",			\
-	"Not band locked",		\
-	"No clock",			\
-	"Bad Rate valueset",		\
-	"Bad Band",			\
-	"Buffer too short",		\
-	"Buffer too long",		\
-	"Busy",				\
-	"Not Associated",		\
-	"Bad SSID len",			\
-	"Out of Range Channel",		\
-	"Bad Channel",			\
-	"Bad Address",			\
-	"Not Enough Resources",		\
-	"Unsupported",			\
-	"Bad length",			\
-	"Not Ready",			\
-	"Not Permitted",		\
-	"No Memory",			\
-	"Associated",			\
-	"Not In Range",			\
-	"Not Found",			\
-	"WME Not Enabled",		\
-	"TSPEC Not Found",		\
-	"ACM Not Supported",		\
-	"Not WME Association",		\
-	"SDIO Bus Error",		\
-	"Dongle Not Accessible",	\
-	"Incorrect version",		\
-	"TX Failure",			\
-	"RX Failure",			\
-	"Device Not Present",		\
-	"NMODE Disabled",		\
-	"Nonresident overlay access", \
-	"Scan Rejected",		\
-	"WLCMD usage error",		\
-	"WLCMD ioctl error",		\
-	"RWL serial port error", 	\
-	"Disabled",			\
-	"Decrypt error", \
-	"Encrypt error", \
-	"MIC error", \
-	"Replay", \
-	"IE not found", \
-	"Data not found", \
-}
-
-#ifndef ABS
-#define	ABS(a)			(((a) < 0) ? -(a) : (a))
-#endif /* ABS */
-
-#ifndef MIN
-#define	MIN(a, b)		(((a) < (b)) ? (a) : (b))
-#endif /* MIN */
-
-#ifndef MAX
-#define	MAX(a, b)		(((a) > (b)) ? (a) : (b))
-#endif /* MAX */
-
-/* limit to [min, max] */
-#ifndef LIMIT_TO_RANGE
-#define LIMIT_TO_RANGE(x, min, max) \
-	((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
-#endif /* LIMIT_TO_RANGE */
-
-/* limit to  max */
-#ifndef LIMIT_TO_MAX
-#define LIMIT_TO_MAX(x, max) \
-	(((x) > (max) ? (max) : (x)))
-#endif /* LIMIT_TO_MAX */
-
-/* limit to min */
-#ifndef LIMIT_TO_MIN
-#define LIMIT_TO_MIN(x, min) \
-	(((x) < (min) ? (min) : (x)))
-#endif /* LIMIT_TO_MIN */
-
-#define DELTA(curr, prev) ((curr) > (prev) ? ((curr) - (prev)) : \
-	(0xffffffff - (prev) + (curr) + 1))
-#define CEIL(x, y)		(((x) + ((y) - 1)) / (y))
-#define ROUNDUP(x, y)		((((x) + ((y) - 1)) / (y)) * (y))
-#define ROUNDDN(p, align)	((p) & ~((align) - 1))
-#define	ISALIGNED(a, x)		(((uintptr)(a) & ((x) - 1)) == 0)
-#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \
-	                                         & ~((boundary) - 1))
-#define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \
-	                                         & ~((boundary) - 1))
-#define	ISPOWEROF2(x)		((((x) - 1) & (x)) == 0)
-#define VALID_MASK(mask)	!((mask) & ((mask) + 1))
-
-#ifndef OFFSETOF
-#ifdef __ARMCC_VERSION
-/*
- * The ARM RVCT compiler complains when using OFFSETOF where a constant
- * expression is expected, such as an initializer for a static object.
- * offsetof from the runtime library doesn't have that problem.
- */
-#include <stddef.h>
-#define	OFFSETOF(type, member)	offsetof(type, member)
-#else
-#  if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 8))
-/* GCC 4.8+ complains when using our OFFSETOF macro in array length declarations. */
-#    define	OFFSETOF(type, member)	__builtin_offsetof(type, member)
-#  else
-#    define	OFFSETOF(type, member)	((uint)(uintptr)&((type *)0)->member)
-#  endif /* GCC 4.8 or newer */
-#endif /* __ARMCC_VERSION */
-#endif /* OFFSETOF */
-
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(a)		(sizeof(a) / sizeof(a[0]))
-#endif
-
-#ifndef ARRAYLAST /* returns pointer to last array element */
-#define ARRAYLAST(a)		(&a[ARRAYSIZE(a)-1])
-#endif
-
-/* Reference a function; used to prevent a static function from being optimized out */
-extern void *_bcmutils_dummy_fn;
-#define REFERENCE_FUNCTION(f)	(_bcmutils_dummy_fn = (void *)(f))
-
-/* bit map related macros */
-#ifndef setbit
-#ifndef NBBY		/* the BSD family defines NBBY */
-#define	NBBY	8	/* 8 bits per byte */
-#endif /* #ifndef NBBY */
-#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
-extern void setbit(void *array, uint bit);
-extern void clrbit(void *array, uint bit);
-extern bool isset(const void *array, uint bit);
-extern bool isclr(const void *array, uint bit);
-#else
-#define	setbit(a, i)	(((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY))
-#define	clrbit(a, i)	(((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY)))
-#define	isset(a, i)	(((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY)))
-#define	isclr(a, i)	((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0)
-#endif
-#endif /* setbit */
-extern void set_bitrange(void *array, uint start, uint end, uint maxbit);
-
-#define	isbitset(a, i)	(((a) & (1 << (i))) != 0)
-
-#define	NBITS(type)	(sizeof(type) * 8)
-#define NBITVAL(nbits)	(1 << (nbits))
-#define MAXBITVAL(nbits)	((1 << (nbits)) - 1)
-#define	NBITMASK(nbits)	MAXBITVAL(nbits)
-#define MAXNBVAL(nbyte)	MAXBITVAL((nbyte) * 8)
-
-extern void bcm_bitprint32(const uint32 u32);
-
-/*
- * ----------------------------------------------------------------------------
- * Multiword map of 2bits, nibbles
- * setbit2 setbit4 (void *ptr, uint32 ix, uint32 val)
- * getbit2 getbit4 (void *ptr, uint32 ix)
- * ----------------------------------------------------------------------------
- */
-
-#define DECLARE_MAP_API(NB, RSH, LSH, OFF, MSK)                     \
-static INLINE void setbit##NB(void *ptr, uint32 ix, uint32 val)     \
-{                                                                   \
-	uint32 *addr = (uint32 *)ptr;                                   \
-	uint32 *a = addr + (ix >> RSH); /* (ix / 2^RSH) */              \
-	uint32 pos = (ix & OFF) << LSH; /* (ix % 2^RSH) * 2^LSH */      \
-	uint32 mask = (MSK << pos);                                     \
-	uint32 tmp = *a & ~mask;                                        \
-	*a = tmp | (val << pos);                                        \
-}                                                                   \
-static INLINE uint32 getbit##NB(void *ptr, uint32 ix)               \
-{                                                                   \
-	uint32 *addr = (uint32 *)ptr;                                   \
-	uint32 *a = addr + (ix >> RSH);                                 \
-	uint32 pos = (ix & OFF) << LSH;                                 \
-	return ((*a >> pos) & MSK);                                     \
-}
-
-DECLARE_MAP_API(2, 4, 1, 15U, 0x0003) /* setbit2() and getbit2() */
-DECLARE_MAP_API(4, 3, 2, 7U, 0x000F) /* setbit4() and getbit4() */
-DECLARE_MAP_API(8, 2, 3, 3U, 0x00FF) /* setbit8() and getbit8() */
-
-/* basic mux operation - can be optimized on several architectures */
-#define MUX(pred, true, false) ((pred) ? (true) : (false))
-
-/* modulo inc/dec - assumes x E [0, bound - 1] */
-#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
-#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
-
-/* modulo inc/dec, bound = 2^k */
-#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
-#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
-
-/* modulo add/sub - assumes x, y E [0, bound - 1] */
-#define MODADD(x, y, bound) \
-    MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y))
-#define MODSUB(x, y, bound) \
-    MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y))
-
-/* module add/sub, bound = 2^k */
-#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
-#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
-
-/* crc defines */
-#define CRC8_INIT_VALUE  0xff		/* Initial CRC8 checksum value */
-#define CRC8_GOOD_VALUE  0x9f		/* Good final CRC8 checksum value */
-#define CRC16_INIT_VALUE 0xffff		/* Initial CRC16 checksum value */
-#define CRC16_GOOD_VALUE 0xf0b8		/* Good final CRC16 checksum value */
-#define CRC32_INIT_VALUE 0xffffffff	/* Initial CRC32 checksum value */
-#define CRC32_GOOD_VALUE 0xdebb20e3	/* Good final CRC32 checksum value */
-
-/* use for direct output of MAC address in printf etc */
-#define MACF				"%02x:%02x:%02x:%02x:%02x:%02x"
-#define ETHERP_TO_MACF(ea)	((struct ether_addr *) (ea))->octet[0], \
-							((struct ether_addr *) (ea))->octet[1], \
-							((struct ether_addr *) (ea))->octet[2], \
-							((struct ether_addr *) (ea))->octet[3], \
-							((struct ether_addr *) (ea))->octet[4], \
-							((struct ether_addr *) (ea))->octet[5]
-
-#define ETHER_TO_MACF(ea) 	(ea).octet[0], \
-							(ea).octet[1], \
-							(ea).octet[2], \
-							(ea).octet[3], \
-							(ea).octet[4], \
-							(ea).octet[5]
-#if !defined(SIMPLE_MAC_PRINT)
-#define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5]
-#else
-#define MACDBG				"%02x:%02x:%02x"
-#define MAC2STRDBG(ea) (ea)[0], (ea)[4], (ea)[5]
-#endif /* SIMPLE_MAC_PRINT */
-
-/* bcm_format_flags() bit description structure */
-typedef struct bcm_bit_desc {
-	uint32	bit;
-	const char* name;
-} bcm_bit_desc_t;
-
-/* bcm_format_field */
-typedef struct bcm_bit_desc_ex {
-	uint32 mask;
-	const bcm_bit_desc_t *bitfield;
-} bcm_bit_desc_ex_t;
-
-/* buffer length for ethernet address from bcm_ether_ntoa() */
-#define ETHER_ADDR_STR_LEN	18	/* 18-bytes of Ethernet address buffer length */
-
-static INLINE uint32 /* 32bit word aligned xor-32 */
-bcm_compute_xor32(volatile uint32 *u32_val, int num_u32)
-{
-	int idx;
-	uint32 xor32 = 0;
-	for (idx = 0; idx < num_u32; idx++)
-		xor32 ^= *(u32_val + idx);
-	return xor32;
-}
-
-/* crypto utility function */
-/* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */
-static INLINE void
-xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst)
-{
-	if (
-#ifdef __i386__
-	    1 ||
-#endif
-	    (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) {
-		/* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */
-		/* x86 supports unaligned.  This version runs 6x-9x faster on x86. */
-		((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0];
-		((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1];
-		((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2];
-		((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3];
-	} else {
-		/* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */
-		int k;
-		for (k = 0; k < 16; k++)
-			dst[k] = src1[k] ^ src2[k];
-	}
-}
-
-/* externs */
-/* crc */
-extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc);
-extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc);
-extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc);
-
-/* format/print */
-#if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \
-	defined(WLMSG_ASSOC)
-/* print out the value a field has: fields may have 1-32 bits and may hold any value */
-extern int bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 field, char* buf, int len);
-/* print out which bits in flags are set */
-extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len);
-#endif
-
-extern int bcm_format_hex(char *str, const void *bytes, int len);
-
-extern const char *bcm_crypto_algo_name(uint algo);
-extern char *bcm_chipname(uint chipid, char *buf, uint len);
-extern char *bcm_brev_str(uint32 brev, char *buf);
-extern void printbig(char *buf);
-extern void prhex(const char *msg, uchar *buf, uint len);
-
-/* IE parsing */
-
-/* packing is required if struct is passed across the bus */
-#include <packed_section_start.h>
-/* tag_ID/length/value_buffer tuple */
-typedef struct bcm_tlv {
-	uint8	id;
-	uint8	len;
-	uint8	data[1];
-} bcm_tlv_t;
-
-/* bcm tlv w/ 16 bit id/len */
-typedef BWL_PRE_PACKED_STRUCT struct bcm_xtlv {
-	uint16	id;
-	uint16	len;
-	uint8	data[1];
-} BWL_POST_PACKED_STRUCT bcm_xtlv_t;
-#include <packed_section_end.h>
-
-
-/* descriptor of xtlv data src or dst  */
-typedef struct {
-	uint16	type;
-	uint16	len;
-	void	*ptr; /* ptr to memory location */
-} xtlv_desc_t;
-
-/* xtlv options */
-#define BCM_XTLV_OPTION_NONE	0x0000
-#define BCM_XTLV_OPTION_ALIGN32	0x0001
-
-typedef uint16 bcm_xtlv_opts_t;
-struct bcm_xtlvbuf {
-	bcm_xtlv_opts_t opts;
-	uint16 size;
-	uint8 *head; /* point to head of buffer */
-	uint8 *buf; /* current position of buffer */
-	/* allocated buffer may follow, but not necessarily */
-};
-typedef struct bcm_xtlvbuf bcm_xtlvbuf_t;
-
-#define BCM_TLV_MAX_DATA_SIZE (255)
-#define BCM_XTLV_MAX_DATA_SIZE (65535)
-#define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data))
-
-#define BCM_XTLV_HDR_SIZE (OFFSETOF(bcm_xtlv_t, data))
-/* LEN only stores the value's length without padding */
-#define BCM_XTLV_LEN(elt) ltoh16_ua(&(elt->len))
-#define BCM_XTLV_ID(elt) ltoh16_ua(&(elt->id))
-/* entire size of the XTLV including header, data, and optional padding */
-#define BCM_XTLV_SIZE(elt, opts) bcm_xtlv_size(elt, opts)
-#define bcm_valid_xtlv(elt, buflen, opts) (elt && ((int)(buflen) >= (int)BCM_XTLV_SIZE(elt, opts)))
-
-/* Check that bcm_tlv_t fits into the given buflen */
-#define bcm_valid_tlv(elt, buflen) (\
-	 ((int)(buflen) >= (int)BCM_TLV_HDR_SIZE) && \
-	 ((int)(buflen) >= (int)(BCM_TLV_HDR_SIZE + (elt)->len)))
-
-
-extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen);
-extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key);
-extern bcm_tlv_t *bcm_parse_tlvs_min_bodylen(void *buf, int buflen, uint key, int min_bodylen);
-
-extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key);
-
-extern bcm_tlv_t *bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type,
-	int type_len);
-
-extern uint8 *bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst);
-extern uint8 *bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst,
-	int dst_maxlen);
-
-extern uint8 *bcm_copy_tlv(const void *src, uint8 *dst);
-extern uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen);
-
-/* xtlv */
-
-/* return the next xtlv element, and update buffer len (remaining). Buffer length
- * updated includes padding as specified by options
- */
-extern bcm_xtlv_t *bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts);
-
-/* initialize an xtlv buffer. Use options specified for packing/unpacking using
- * the buffer. Caller is responsible for allocating both buffers.
- */
-extern int bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len,
-	bcm_xtlv_opts_t opts);
-
-extern uint16 bcm_xtlv_buf_len(struct bcm_xtlvbuf *tbuf);
-extern uint16 bcm_xtlv_buf_rlen(struct bcm_xtlvbuf *tbuf);
-extern uint8 *bcm_xtlv_buf(struct bcm_xtlvbuf *tbuf);
-extern uint8 *bcm_xtlv_head(struct bcm_xtlvbuf *tbuf);
-extern int bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const void *data, uint16 dlen);
-extern int bcm_xtlv_put_8(bcm_xtlvbuf_t *tbuf, uint16 type, const int8 data);
-extern int bcm_xtlv_put_16(bcm_xtlvbuf_t *tbuf, uint16 type, const int16 data);
-extern int bcm_xtlv_put_32(bcm_xtlvbuf_t *tbuf, uint16 type, const int32 data);
-extern int bcm_unpack_xtlv_entry(uint8 **buf, uint16 xpct_type, uint16 xpct_len,
-	void *dst, bcm_xtlv_opts_t opts);
-extern int bcm_pack_xtlv_entry(uint8 **buf, uint16 *buflen, uint16 type, uint16 len,
-	void *src, bcm_xtlv_opts_t opts);
-extern int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
-
-/* callback for unpacking xtlv from a buffer into context. */
-typedef int (bcm_xtlv_unpack_cbfn_t)(void *ctx, uint8 *buf, uint16 type, uint16 len);
-
-/* unpack a tlv buffer using buffer, options, and callback */
-extern int bcm_unpack_xtlv_buf(void *ctx, uint8 *buf, uint16 buflen,
-	bcm_xtlv_opts_t opts, bcm_xtlv_unpack_cbfn_t *cbfn);
-
-/* unpack a set of tlvs from the buffer using provided xtlv desc */
-extern int bcm_unpack_xtlv_buf_to_mem(void *buf, int *buflen, xtlv_desc_t *items,
-	bcm_xtlv_opts_t opts);
-
-/* pack a set of tlvs into buffer using provided xtlv desc */
-extern int bcm_pack_xtlv_buf_from_mem(void **buf, uint16 *buflen, xtlv_desc_t *items,
-	bcm_xtlv_opts_t opts);
-
-/* return data pointer of a given ID from xtlv buffer
- * xtlv data length is given to *datalen_out, if the pointer is valid
- */
-extern void *bcm_get_data_from_xtlv_buf(uint8 *tlv_buf, uint16 buflen, uint16 id,
-	uint16 *datalen_out, bcm_xtlv_opts_t opts);
-
-/* callback to return next tlv id and len to pack, if there is more tlvs to come and
- * options e.g. alignment
- */
-typedef bool (*bcm_pack_xtlv_next_info_cbfn_t)(void *ctx, uint16 *tlv_id, uint16 *tlv_len);
-
-/* callback to pack the tlv into length validated buffer */
-typedef void (*bcm_pack_xtlv_pack_next_cbfn_t)(void *ctx,
-	uint16 tlv_id, uint16 tlv_len, uint8* buf);
-
-/* pack a set of tlvs into buffer using get_next to interate */
-int bcm_pack_xtlv_buf(void *ctx, void *tlv_buf, uint16 buflen,
-	bcm_xtlv_opts_t opts, bcm_pack_xtlv_next_info_cbfn_t get_next,
-	bcm_pack_xtlv_pack_next_cbfn_t pack_next, int *outlen);
-
-/* bcmerror */
-extern const char *bcmerrorstr(int bcmerror);
-
-/* multi-bool data type: set of bools, mbool is true if any is set */
-typedef uint32 mbool;
-#define mboolset(mb, bit)		((mb) |= (bit))		/* set one bool */
-#define mboolclr(mb, bit)		((mb) &= ~(bit))	/* clear one bool */
-#define mboolisset(mb, bit)		(((mb) & (bit)) != 0)	/* TRUE if one bool is set */
-#define	mboolmaskset(mb, mask, val)	((mb) = (((mb) & ~(mask)) | (val)))
-
-/* generic datastruct to help dump routines */
-struct fielddesc {
-	const char *nameandfmt;
-	uint32 offset;
-	uint32 len;
-};
-
-extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size);
-extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline,
-	const uint8 *buf, int len);
-
-extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount);
-extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes);
-extern void bcm_print_bytes(const char *name, const uchar *cdata, int len);
-
-typedef  uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset);
-extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str,
-                          char *buf, uint32 bufsize);
-extern uint bcm_bitcount(uint8 *bitmap, uint bytelength);
-
-extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...);
-
-/* power conversion */
-extern uint16 bcm_qdbm_to_mw(uint8 qdbm);
-extern uint8 bcm_mw_to_qdbm(uint16 mw);
-extern uint bcm_mkiovar(const char *name, char *data, uint datalen, char *buf, uint len);
-
-unsigned int process_nvram_vars(char *varbuf, unsigned int len);
-
-/* trace any object allocation / free, with / without features (flags) set to the object */
-
-#define BCM_OBJDBG_ADD           1
-#define BCM_OBJDBG_REMOVE        2
-#define BCM_OBJDBG_ADD_PKT       3
-
-/* object feature: set or clear flags */
-#define BCM_OBJECT_FEATURE_FLAG       1
-#define BCM_OBJECT_FEATURE_PKT_STATE  2
-/* object feature: flag bits */
-#define BCM_OBJECT_FEATURE_0     (1 << 0)
-#define BCM_OBJECT_FEATURE_1     (1 << 1)
-#define BCM_OBJECT_FEATURE_2     (1 << 2)
-/* object feature: clear flag bits field set with this flag */
-#define BCM_OBJECT_FEATURE_CLEAR (1 << 31)
-#ifdef BCM_OBJECT_TRACE
-#define bcm_pkt_validate_chk(obj)	do { \
-	void * pkttag; \
-	bcm_object_trace_chk(obj, 0, 0, \
-		__FUNCTION__, __LINE__); \
-	if ((pkttag = PKTTAG(obj))) { \
-		bcm_object_trace_chk(obj, 1, DHD_PKTTAG_SN(pkttag), \
-			__FUNCTION__, __LINE__); \
-	} \
-} while (0)
-extern void bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line);
-extern void bcm_object_trace_upd(void *obj, void *obj_new);
-extern void bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn,
-	const char *caller, int line);
-extern void bcm_object_feature_set(void *obj, uint32 type, uint32 value);
-extern int  bcm_object_feature_get(void *obj, uint32 type, uint32 value);
-extern void bcm_object_trace_init(void);
-extern void bcm_object_trace_deinit(void);
-#else
-#define bcm_pkt_validate_chk(obj)
-#define bcm_object_trace_opr(a, b, c, d)
-#define bcm_object_trace_upd(a, b)
-#define bcm_object_trace_chk(a, b, c, d, e)
-#define bcm_object_feature_set(a, b, c)
-#define bcm_object_feature_get(a, b, c)
-#define bcm_object_trace_init()
-#define bcm_object_trace_deinit()
-#endif /* BCM_OBJECT_TRACE */
-
-/* calculate a * b + c */
-extern void bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c);
-/* calculate a / b */
-extern void bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
-
-
-/* Public domain bit twiddling hacks/utilities: Sean Eron Anderson */
-
-/* Table driven count set bits. */
-static const uint8 /* Table only for use by bcm_cntsetbits */
-_CSBTBL[256] =
-{
-#	define B2(n)    n,     n + 1,     n + 1,     n + 2
-#	define B4(n) B2(n), B2(n + 1), B2(n + 1), B2(n + 2)
-#	define B6(n) B4(n), B4(n + 1), B4(n + 1), B4(n + 2)
-	B6(0), B6(0 + 1), B6(0 + 1), B6(0 + 2)
-};
-
-static INLINE uint32 /* Uses table _CSBTBL for fast counting of 1's in a u32 */
-bcm_cntsetbits(const uint32 u32arg)
-{
-	/* function local scope declaration of const _CSBTBL[] */
-	const uint8 * p = (const uint8 *)&u32arg;
-	return (_CSBTBL[p[0]] + _CSBTBL[p[1]] + _CSBTBL[p[2]] + _CSBTBL[p[3]]);
-}
-
-
-static INLINE int /* C equivalent count of leading 0's in a u32 */
-C_bcm_count_leading_zeros(uint32 u32arg)
-{
-	int shifts = 0;
-	while (u32arg) {
-		shifts++; u32arg >>= 1;
-	}
-	return (32U - shifts);
-}
-
-#ifdef BCMDRIVER
-/*
- * Assembly instructions: Count Leading Zeros
- * "clz"	: MIPS, ARM
- * "cntlzw"	: PowerPC
- * "BSF"	: x86
- * "lzcnt"	: AMD, SPARC
- */
-
-#if defined(__arm__)
-#if defined(__ARM_ARCH_7M__) /* Cortex M3 */
-#define __USE_ASM_CLZ__
-#endif /* __ARM_ARCH_7M__ */
-#if defined(__ARM_ARCH_7R__) /* Cortex R4 */
-#define __USE_ASM_CLZ__
-#endif /* __ARM_ARCH_7R__ */
-#endif /* __arm__ */
-
-static INLINE int
-bcm_count_leading_zeros(uint32 u32arg)
-{
-#if defined(__USE_ASM_CLZ__)
-	int zeros;
-	__asm__ volatile("clz    %0, %1 \n" : "=r" (zeros) : "r"  (u32arg));
-	return zeros;
-#else	/* C equivalent */
-	return C_bcm_count_leading_zeros(u32arg);
-#endif  /* C equivalent */
-}
-
-/*
- * Macro to count leading zeroes
- *
- */
-#if defined(__GNUC__)
-#define CLZ(x) __builtin_clzl(x)
-#elif defined(__arm__)
-#define CLZ(x) __clz(x)
-#else
-#define CLZ(x) bcm_count_leading_zeros(x)
-#endif /* __GNUC__ */
-
-/* INTERFACE: Multiword bitmap based small id allocator. */
-struct bcm_mwbmap;	/* forward declaration for use as an opaque mwbmap handle */
-
-#define BCM_MWBMAP_INVALID_HDL	((struct bcm_mwbmap *)NULL)
-#define BCM_MWBMAP_INVALID_IDX	((uint32)(~0U))
-
-/* Incarnate a multiword bitmap based small index allocator */
-extern struct bcm_mwbmap * bcm_mwbmap_init(osl_t * osh, uint32 items_max);
-
-/* Free up the multiword bitmap index allocator */
-extern void bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl);
-
-/* Allocate a unique small index using a multiword bitmap index allocator */
-extern uint32 bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl);
-
-/* Force an index at a specified position to be in use */
-extern void bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
-
-/* Free a previously allocated index back into the multiword bitmap allocator */
-extern void bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
-
-/* Fetch the toal number of free indices in the multiword bitmap allocator */
-extern uint32 bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl);
-
-/* Determine whether an index is inuse or free */
-extern bool bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
-
-/* Debug dump a multiword bitmap allocator */
-extern void bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl);
-
-extern void bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl);
-/* End - Multiword bitmap based small Id allocator. */
-
-
-/* INTERFACE: Simple unique 16bit Id Allocator using a stack implementation. */
-
-#define ID16_INVALID                ((uint16)(~0))
-#define ID16_UNDEFINED              (ID16_INVALID)
-
-/*
- * Construct a 16bit id allocator, managing 16bit ids in the range:
- *    [start_val16 .. start_val16+total_ids)
- * Note: start_val16 is inclusive.
- * Returns an opaque handle to the 16bit id allocator.
- */
-extern void * id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16);
-extern void * id16_map_fini(osl_t *osh, void * id16_map_hndl);
-extern void id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16);
-
-/* Allocate a unique 16bit id */
-extern uint16 id16_map_alloc(void * id16_map_hndl);
-
-/* Free a 16bit id value into the id16 allocator */
-extern void id16_map_free(void * id16_map_hndl, uint16 val16);
-
-/* Get the number of failures encountered during id allocation. */
-extern uint32 id16_map_failures(void * id16_map_hndl);
-
-/* Audit the 16bit id allocator state. */
-extern bool id16_map_audit(void * id16_map_hndl);
-/* End - Simple 16bit Id Allocator. */
-#endif /* BCMDRIVER */
-
-extern void bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
-
-void bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset);
-void bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset);
-
-/* calculate checksum for ip header, tcp / udp header / data */
-uint16 bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum);
-
-#ifndef _dll_t_
-#define _dll_t_
-/*
- * -----------------------------------------------------------------------------
- *                      Double Linked List Macros
- * -----------------------------------------------------------------------------
- *
- * All dll operations must be performed on a pre-initialized node.
- * Inserting an uninitialized node into a list effectively initialized it.
- *
- * When a node is deleted from a list, you may initialize it to avoid corruption
- * incurred by double deletion. You may skip initialization if the node is
- * immediately inserted into another list.
- *
- * By placing a dll_t element at the start of a struct, you may cast a dll_t *
- * to the struct or vice versa.
- *
- * Example of declaring an initializing someList and inserting nodeA, nodeB
- *
- *     typedef struct item {
- *         dll_t node;
- *         int someData;
- *     } Item_t;
- *     Item_t nodeA, nodeB, nodeC;
- *     nodeA.someData = 11111, nodeB.someData = 22222, nodeC.someData = 33333;
- *
- *     dll_t someList;
- *     dll_init(&someList);
- *
- *     dll_append(&someList, (dll_t *) &nodeA);
- *     dll_prepend(&someList, &nodeB.node);
- *     dll_insert((dll_t *)&nodeC, &nodeA.node);
- *
- *     dll_delete((dll_t *) &nodeB);
- *
- * Example of a for loop to walk someList of node_p
- *
- *   extern void mydisplay(Item_t * item_p);
- *
- *   dll_t * item_p, * next_p;
- *   for (item_p = dll_head_p(&someList); ! dll_end(&someList, item_p);
- *        item_p = next_p)
- *   {
- *       next_p = dll_next_p(item_p);
- *       ... use item_p at will, including removing it from list ...
- *       mydisplay((PItem_t)item_p);
- *   }
- *
- * -----------------------------------------------------------------------------
- */
-typedef struct dll {
-	struct dll * next_p;
-	struct dll * prev_p;
-} dll_t;
-
-static INLINE void
-dll_init(dll_t *node_p)
-{
-	node_p->next_p = node_p;
-	node_p->prev_p = node_p;
-}
-/* dll macros returing a pointer to dll_t */
-
-static INLINE dll_t *
-dll_head_p(dll_t *list_p)
-{
-	return list_p->next_p;
-}
-
-
-static INLINE dll_t *
-dll_tail_p(dll_t *list_p)
-{
-	return (list_p)->prev_p;
-}
-
-
-static INLINE dll_t *
-dll_next_p(dll_t *node_p)
-{
-	return (node_p)->next_p;
-}
-
-
-static INLINE dll_t *
-dll_prev_p(dll_t *node_p)
-{
-	return (node_p)->prev_p;
-}
-
-
-static INLINE bool
-dll_empty(dll_t *list_p)
-{
-	return ((list_p)->next_p == (list_p));
-}
-
-
-static INLINE bool
-dll_end(dll_t *list_p, dll_t * node_p)
-{
-	return (list_p == node_p);
-}
-
-
-/* inserts the node new_p "after" the node at_p */
-static INLINE void
-dll_insert(dll_t *new_p, dll_t * at_p)
-{
-	new_p->next_p = at_p->next_p;
-	new_p->prev_p = at_p;
-	at_p->next_p = new_p;
-	(new_p->next_p)->prev_p = new_p;
-}
-
-static INLINE void
-dll_append(dll_t *list_p, dll_t *node_p)
-{
-	dll_insert(node_p, dll_tail_p(list_p));
-}
-
-static INLINE void
-dll_prepend(dll_t *list_p, dll_t *node_p)
-{
-	dll_insert(node_p, list_p);
-}
-
-
-/* deletes a node from any list that it "may" be in, if at all. */
-static INLINE void
-dll_delete(dll_t *node_p)
-{
-	node_p->prev_p->next_p = node_p->next_p;
-	node_p->next_p->prev_p = node_p->prev_p;
-}
-#endif  /* ! defined(_dll_t_) */
-
-/* Elements managed in a double linked list */
-
-typedef struct dll_pool {
-	dll_t       free_list;
-	uint16      free_count;
-	uint16      elems_max;
-	uint16      elem_size;
-	dll_t       elements[1];
-} dll_pool_t;
-
-dll_pool_t * dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size);
-void * dll_pool_alloc(dll_pool_t * dll_pool_p);
-void dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p);
-void dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p);
-typedef void (* dll_elem_dump)(void * elem_p);
-void dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size);
-
-#ifdef __cplusplus
-	}
-#endif
-
-/* #define DEBUG_COUNTER */
-#ifdef DEBUG_COUNTER
-#define CNTR_TBL_MAX 10
-typedef struct _counter_tbl_t {
-	char name[16];				/* name of this counter table */
-	uint32 prev_log_print;		/* Internal use. Timestamp of the previous log print */
-	uint log_print_interval;	/* Desired interval to print logs in ms */
-	uint needed_cnt;			/* How many counters need to be used */
-	uint32 cnt[CNTR_TBL_MAX];		/* Counting entries to increase at desired places */
-	bool enabled;				/* Whether to enable printing log */
-} counter_tbl_t;
-
-
-void counter_printlog(counter_tbl_t *ctr_tbl);
-#endif /* DEBUG_COUNTER */
-
-/* Given a number 'n' returns 'm' that is next larger power of 2 after n */
-static INLINE uint32 next_larger_power2(uint32 num)
-{
-	num--;
-	num |= (num >> 1);
-	num |= (num >> 2);
-	num |= (num >> 4);
-	num |= (num >> 8);
-	num |= (num >> 16);
-	return (num + 1);
-}
-
-#endif	/* _bcmutils_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/brcm_nl80211.h b/drivers/net/wireless/bcmdhd/include/brcm_nl80211.h
deleted file mode 100644
index 8888631..0000000
--- a/drivers/net/wireless/bcmdhd/include/brcm_nl80211.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Definitions for nl80211 vendor command/event access to host driver
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: brcm_nl80211.h 556083 2015-05-12 14:03:00Z $
- *
- */
-
-#ifndef _brcm_nl80211_h_
-#define _brcm_nl80211_h_
-
-#define OUI_BRCM  0x001018
-
-enum wl_vendor_subcmd {
-	BRCM_VENDOR_SCMD_UNSPEC,
-	BRCM_VENDOR_SCMD_PRIV_STR,
-	BRCM_VENDOR_SCMD_BCM_STR
-};
-
-
-struct bcm_nlmsg_hdr {
-	uint cmd;	/* common ioctl definition */
-	int len;	/* expected return buffer length */
-	uint offset;	/* user buffer offset */
-	uint set;	/* get or set request optional */
-	uint magic;	/* magic number for verification */
-};
-
-enum bcmnl_attrs {
-	BCM_NLATTR_UNSPEC,
-
-	BCM_NLATTR_LEN,
-	BCM_NLATTR_DATA,
-
-	__BCM_NLATTR_AFTER_LAST,
-	BCM_NLATTR_MAX = __BCM_NLATTR_AFTER_LAST - 1
-};
-
-struct nl_prv_data {
-	int err;			/* return result */
-	void *data;			/* ioctl return buffer pointer */
-	uint len;			/* ioctl return buffer length */
-	struct bcm_nlmsg_hdr *nlioc;	/* bcm_nlmsg_hdr header pointer */
-};
-
-#endif /* _brcm_nl80211_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/dbus.h b/drivers/net/wireless/bcmdhd/include/dbus.h
deleted file mode 100644
index b066c67..0000000
--- a/drivers/net/wireless/bcmdhd/include/dbus.h
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * Dongle BUS interface Abstraction layer
- *   target serial buses like USB, SDIO, SPI, etc.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dbus.h 553311 2015-04-29 10:23:08Z $
- */
-
-#ifndef __DBUS_H__
-#define __DBUS_H__
-
-#include "typedefs.h"
-
-#define DBUSTRACE(args)
-#define DBUSERR(args)
-#define DBUSINFO(args)
-#define DBUSDBGLOCK(args)
-
-enum {
-	DBUS_OK = 0,
-	DBUS_ERR = -200,
-	DBUS_ERR_TIMEOUT,
-	DBUS_ERR_DISCONNECT,
-	DBUS_ERR_NODEVICE,
-	DBUS_ERR_UNSUPPORTED,
-	DBUS_ERR_PENDING,
-	DBUS_ERR_NOMEM,
-	DBUS_ERR_TXFAIL,
-	DBUS_ERR_TXTIMEOUT,
-	DBUS_ERR_TXDROP,
-	DBUS_ERR_RXFAIL,
-	DBUS_ERR_RXDROP,
-	DBUS_ERR_TXCTLFAIL,
-	DBUS_ERR_RXCTLFAIL,
-	DBUS_ERR_REG_PARAM,
-	DBUS_STATUS_CANCELLED,
-	DBUS_ERR_NVRAM,
-	DBUS_JUMBO_NOMATCH,
-	DBUS_JUMBO_BAD_FORMAT,
-	DBUS_NVRAM_NONTXT,
-	DBUS_ERR_RXZLP
-};
-
-#define BCM_OTP_SIZE_43236  84	/* number of 16 bit values */
-#define BCM_OTP_SW_RGN_43236	24  /* start offset of SW config region */
-#define BCM_OTP_ADDR_43236 0x18000800 /* address of otp base */
-
-#define ERR_CBMASK_TXFAIL		0x00000001
-#define ERR_CBMASK_RXFAIL		0x00000002
-#define ERR_CBMASK_ALL			0xFFFFFFFF
-
-#define DBUS_CBCTL_WRITE			0
-#define DBUS_CBCTL_READ				1
-#if defined(INTR_EP_ENABLE)
-#define DBUS_CBINTR_POLL			2
-#endif /* defined(INTR_EP_ENABLE) */
-
-#define DBUS_TX_RETRY_LIMIT		3		/* retries for failed txirb */
-#define DBUS_TX_TIMEOUT_INTERVAL	250		/* timeout for txirb complete, in ms */
-
-#define DBUS_BUFFER_SIZE_TX	32000
-#define DBUS_BUFFER_SIZE_RX	24000
-
-#define DBUS_BUFFER_SIZE_TX_NOAGG	2048
-#define DBUS_BUFFER_SIZE_RX_NOAGG	2048
-
-/** DBUS types */
-enum {
-	DBUS_USB,
-	DBUS_SDIO,
-	DBUS_SPI,
-	DBUS_UNKNOWN
-};
-
-enum dbus_state {
-	DBUS_STATE_DL_PENDING,
-	DBUS_STATE_DL_DONE,
-	DBUS_STATE_UP,
-	DBUS_STATE_DOWN,
-	DBUS_STATE_PNP_FWDL,
-	DBUS_STATE_DISCONNECT,
-	DBUS_STATE_SLEEP,
-	DBUS_STATE_DL_NEEDED
-};
-
-enum dbus_pnp_state {
-	DBUS_PNP_DISCONNECT,
-	DBUS_PNP_SLEEP,
-	DBUS_PNP_RESUME
-};
-
-enum dbus_file {
-    DBUS_FIRMWARE,
-    DBUS_NVFILE
-};
-
-typedef enum _DEVICE_SPEED {
-	INVALID_SPEED = -1,
-	LOW_SPEED     =  1,	/**< USB 1.1: 1.5 Mbps */
-	FULL_SPEED,     	/**< USB 1.1: 12  Mbps */
-	HIGH_SPEED,		/**< USB 2.0: 480 Mbps */
-	SUPER_SPEED,		/**< USB 3.0: 4.8 Gbps */
-} DEVICE_SPEED;
-
-typedef struct {
-	int bustype;
-	int vid;
-	int pid;
-	int devid;
-	int chiprev; /**< chip revsion number */
-	int mtu;
-	int nchan; /**< Data Channels */
-	int has_2nd_bulk_in_ep;
-} dbus_attrib_t;
-
-/* FIX: Account for errors related to DBUS;
- * Let upper layer account for packets/bytes
- */
-typedef struct {
-	uint32 rx_errors;
-	uint32 tx_errors;
-	uint32 rx_dropped;
-	uint32 tx_dropped;
-} dbus_stats_t;
-
-/**
- * Configurable BUS parameters
- */
-enum {
-	DBUS_CONFIG_ID_RXCTL_DEFERRES = 1,
-	DBUS_CONFIG_ID_AGGR_LIMIT
-};
-
-typedef struct {
-	uint32 config_id;
-	union {
-		bool rxctl_deferrespok;
-		struct {
-			int maxrxsf;
-			int maxrxsize;
-			int maxtxsf;
-			int maxtxsize;
-		} aggr_param;
-	};
-} dbus_config_t;
-
-/**
- * External Download Info
- */
-typedef struct dbus_extdl {
-	uint8 *fw;
-	int fwlen;
-	uint8 *vars;
-	int varslen;
-} dbus_extdl_t;
-
-struct dbus_callbacks;
-struct exec_parms;
-
-typedef void *(*probe_cb_t)(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
-typedef void (*disconnect_cb_t)(void *arg);
-typedef void *(*exec_cb_t)(struct exec_parms *args);
-
-/** Client callbacks registered during dbus_attach() */
-typedef struct dbus_callbacks {
-	void (*send_complete)(void *cbarg, void *info, int status);
-	void (*recv_buf)(void *cbarg, uint8 *buf, int len);
-	void (*recv_pkt)(void *cbarg, void *pkt);
-	void (*txflowcontrol)(void *cbarg, bool onoff);
-	void (*errhandler)(void *cbarg, int err);
-	void (*ctl_complete)(void *cbarg, int type, int status);
-	void (*state_change)(void *cbarg, int state);
-	void *(*pktget)(void *cbarg, uint len, bool send);
-	void (*pktfree)(void *cbarg, void *p, bool send);
-} dbus_callbacks_t;
-
-struct dbus_pub;
-struct bcmstrbuf;
-struct dbus_irb;
-struct dbus_irb_rx;
-struct dbus_irb_tx;
-struct dbus_intf_callbacks;
-
-typedef struct {
-	void* (*attach)(struct dbus_pub *pub, void *cbarg, struct dbus_intf_callbacks *cbs);
-	void (*detach)(struct dbus_pub *pub, void *bus);
-
-	int (*up)(void *bus);
-	int (*down)(void *bus);
-	int (*send_irb)(void *bus, struct dbus_irb_tx *txirb);
-	int (*recv_irb)(void *bus, struct dbus_irb_rx *rxirb);
-	int (*cancel_irb)(void *bus, struct dbus_irb_tx *txirb);
-	int (*send_ctl)(void *bus, uint8 *buf, int len);
-	int (*recv_ctl)(void *bus, uint8 *buf, int len);
-	int (*get_stats)(void *bus, dbus_stats_t *stats);
-	int (*get_attrib)(void *bus, dbus_attrib_t *attrib);
-
-	int (*pnp)(void *bus, int evnt);
-	int (*remove)(void *bus);
-	int (*resume)(void *bus);
-	int (*suspend)(void *bus);
-	int (*stop)(void *bus);
-	int (*reset)(void *bus);
-
-	/* Access to bus buffers directly */
-	void *(*pktget)(void *bus, int len);
-	void (*pktfree)(void *bus, void *pkt);
-
-	int  (*iovar_op)(void *bus, const char *name, void *params, int plen, void *arg, int len,
-		bool set);
-	void (*dump)(void *bus, struct bcmstrbuf *strbuf);
-	int  (*set_config)(void *bus, dbus_config_t *config);
-	int  (*get_config)(void *bus, dbus_config_t *config);
-
-	bool (*device_exists)(void *bus);
-	bool (*dlneeded)(void *bus);
-	int  (*dlstart)(void *bus, uint8 *fw, int len);
-	int  (*dlrun)(void *bus);
-	bool (*recv_needed)(void *bus);
-
-	void *(*exec_rxlock)(void *bus, exec_cb_t func, struct exec_parms *args);
-	void *(*exec_txlock)(void *bus, exec_cb_t func, struct exec_parms *args);
-
-	int (*tx_timer_init)(void *bus);
-	int (*tx_timer_start)(void *bus, uint timeout);
-	int (*tx_timer_stop)(void *bus);
-
-	int (*sched_dpc)(void *bus);
-	int (*lock)(void *bus);
-	int (*unlock)(void *bus);
-	int (*sched_probe_cb)(void *bus);
-
-	int (*shutdown)(void *bus);
-
-	int (*recv_stop)(void *bus);
-	int (*recv_resume)(void *bus);
-
-	int (*recv_irb_from_ep)(void *bus, struct dbus_irb_rx *rxirb, uint ep_idx);
-
-	int (*readreg)(void *bus, uint32 regaddr, int datalen, uint32 *value);
-
-	/* Add from the bottom */
-} dbus_intf_t;
-
-typedef struct dbus_pub {
-	struct osl_info *osh;
-	dbus_stats_t stats;
-	dbus_attrib_t attrib;
-	enum dbus_state busstate;
-	DEVICE_SPEED device_speed;
-	int ntxq, nrxq, rxsize;
-	void *bus;
-	struct shared_info *sh;
-    void *dev_info;
-} dbus_pub_t;
-
-#define BUS_INFO(bus, type) (((type *) bus)->pub->bus)
-
-#define	ALIGNED_LOCAL_VARIABLE(var, align)					\
-	uint8	buffer[SDALIGN+64];						\
-	uint8	*var = (uint8 *)(((uintptr)&buffer[0]) & ~(align-1)) + align;
-
-/*
- * Public Bus Function Interface
- */
-
-/*
- * FIX: Is there better way to pass OS/Host handles to DBUS but still
- *      maintain common interface for all OS??
- * Under NDIS, param1 needs to be MiniportHandle
- *  For NDIS60, param2 is WdfDevice
- * Under Linux, param1 and param2 are NULL;
- */
-extern int dbus_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb, void *prarg,
-	void *param1, void *param2);
-extern int dbus_deregister(void);
-
-extern dbus_pub_t *dbus_attach(struct osl_info *osh, int rxsize, int nrxq, int ntxq,
-	void *cbarg, dbus_callbacks_t *cbs, dbus_extdl_t *extdl, struct shared_info *sh);
-extern void dbus_detach(dbus_pub_t *pub);
-
-extern int dbus_download_firmware(dbus_pub_t *pub);
-extern int dbus_up(dbus_pub_t *pub);
-extern int dbus_down(dbus_pub_t *pub);
-extern int dbus_stop(dbus_pub_t *pub);
-extern int dbus_shutdown(dbus_pub_t *pub);
-extern void dbus_flowctrl_rx(dbus_pub_t *pub, bool on);
-
-extern int dbus_send_txdata(dbus_pub_t *dbus, void *pktbuf);
-extern int dbus_send_buf(dbus_pub_t *pub, uint8 *buf, int len, void *info);
-extern int dbus_send_pkt(dbus_pub_t *pub, void *pkt, void *info);
-extern int dbus_send_ctl(dbus_pub_t *pub, uint8 *buf, int len);
-extern int dbus_recv_ctl(dbus_pub_t *pub, uint8 *buf, int len);
-extern int dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx);
-extern int dbus_poll_intr(dbus_pub_t *pub);
-extern int dbus_get_stats(dbus_pub_t *pub, dbus_stats_t *stats);
-extern int dbus_get_attrib(dbus_pub_t *pub, dbus_attrib_t *attrib);
-extern int dbus_get_device_speed(dbus_pub_t *pub);
-extern int dbus_set_config(dbus_pub_t *pub, dbus_config_t *config);
-extern int dbus_get_config(dbus_pub_t *pub, dbus_config_t *config);
-extern void * dbus_get_devinfo(dbus_pub_t *pub);
-
-extern void *dbus_pktget(dbus_pub_t *pub, int len);
-extern void dbus_pktfree(dbus_pub_t *pub, void* pkt);
-
-extern int dbus_set_errmask(dbus_pub_t *pub, uint32 mask);
-extern int dbus_pnp_sleep(dbus_pub_t *pub);
-extern int dbus_pnp_resume(dbus_pub_t *pub, int *fw_reload);
-extern int dbus_pnp_disconnect(dbus_pub_t *pub);
-
-extern int dbus_iovar_op(dbus_pub_t *pub, const char *name,
-	void *params, int plen, void *arg, int len, bool set);
-
-extern void *dhd_dbus_txq(const dbus_pub_t *pub);
-extern uint dhd_dbus_hdrlen(const dbus_pub_t *pub);
-
-/*
- * Private Common Bus Interface
- */
-
-/** IO Request Block (IRB) */
-typedef struct dbus_irb {
-	struct dbus_irb *next;	/**< it's casted from dbus_irb_tx or dbus_irb_rx struct */
-} dbus_irb_t;
-
-typedef struct dbus_irb_rx {
-	struct dbus_irb irb; /* Must be first */
-	uint8 *buf;
-	int buf_len;
-	int actual_len;
-	void *pkt;
-	void *info;
-	void *arg;
-} dbus_irb_rx_t;
-
-typedef struct dbus_irb_tx {
-	struct dbus_irb irb; 	/** Must be first */
-	uint8 *buf;		/** mutually exclusive with struct member 'pkt' */
-	int len;		/** length of field 'buf' */
-	void *pkt;		/** mutually exclusive with struct member 'buf' */
-	int retry_count;
-	void *info;
-	void *arg;
-	void *send_buf;		/**< linear  bufffer for LINUX when aggreagtion is enabled */
-} dbus_irb_tx_t;
-
-/**
- * DBUS interface callbacks are different from user callbacks
- * so, internally, different info can be passed to upper layer
- */
-typedef struct dbus_intf_callbacks {
-	void (*send_irb_timeout)(void *cbarg, dbus_irb_tx_t *txirb);
-	void (*send_irb_complete)(void *cbarg, dbus_irb_tx_t *txirb, int status);
-	void (*recv_irb_complete)(void *cbarg, dbus_irb_rx_t *rxirb, int status);
-	void (*errhandler)(void *cbarg, int err);
-	void (*ctl_complete)(void *cbarg, int type, int status);
-	void (*state_change)(void *cbarg, int state);
-	bool (*isr)(void *cbarg, bool *wantdpc);
-	bool (*dpc)(void *cbarg, bool bounded);
-	void (*watchdog)(void *cbarg);
-	void *(*pktget)(void *cbarg, uint len, bool send);
-	void (*pktfree)(void *cbarg, void *p, bool send);
-	struct dbus_irb* (*getirb)(void *cbarg, bool send);
-	void (*rxerr_indicate)(void *cbarg, bool on);
-} dbus_intf_callbacks_t;
-
-/*
- * Porting: To support new bus, port these functions below
- */
-
-/*
- * Bus specific Interface
- * Implemented by dbus_usb.c/dbus_sdio.c
- */
-extern int dbus_bus_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb, void *prarg,
-	dbus_intf_t **intf, void *param1, void *param2);
-extern int dbus_bus_deregister(void);
-extern void dbus_bus_fw_get(void *bus, uint8 **fw, int *fwlen, int *decomp);
-
-/*
- * Bus-specific and OS-specific Interface
- * Implemented by dbus_usb_[linux/ndis].c/dbus_sdio_[linux/ndis].c
- */
-extern int dbus_bus_osl_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb,
-	void *prarg, dbus_intf_t **intf, void *param1, void *param2);
-extern int dbus_bus_osl_deregister(void);
-
-/*
- * Bus-specific, OS-specific, HW-specific Interface
- * Mainly for SDIO Host HW controller
- */
-extern int dbus_bus_osl_hw_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb,
-	void *prarg, dbus_intf_t **intf);
-extern int dbus_bus_osl_hw_deregister(void);
-
-extern uint usbdev_bulkin_eps(void);
-#if defined(BCM_REQUEST_FW)
-extern void *dbus_get_fw_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen, int type,
-  uint16 boardtype, uint16 boardrev);
-extern void dbus_release_fw_nvfile(void *firmware);
-#endif  /* #if defined(BCM_REQUEST_FW) */
-
-
-#if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX)
-
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-	/* Backward compatibility */
-	typedef unsigned int gfp_t;
-
-	#define dma_pool pci_pool
-	#define dma_pool_create(name, dev, size, align, alloc) \
-		pci_pool_create(name, dev, size, align, alloc, GFP_DMA | GFP_ATOMIC)
-	#define dma_pool_destroy(pool) pci_pool_destroy(pool)
-	#define dma_pool_alloc(pool, flags, handle) pci_pool_alloc(pool, flags, handle)
-	#define dma_pool_free(pool, vaddr, addr) pci_pool_free(pool, vaddr, addr)
-
-	#define dma_map_single(dev, addr, size, dir)	pci_map_single(dev, addr, size, dir)
-	#define dma_unmap_single(dev, hnd, size, dir)	pci_unmap_single(dev, hnd, size, dir)
-	#define DMA_FROM_DEVICE PCI_DMA_FROMDEVICE
-	#define DMA_TO_DEVICE PCI_DMA_TODEVICE
-#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */
-
-/* Availability of these functions varies (when present, they have two arguments) */
-#ifndef hc32_to_cpu
-	#define hc32_to_cpu(x)	le32_to_cpu(x)
-	#define cpu_to_hc32(x)	cpu_to_le32(x)
-	typedef unsigned int __hc32;
-#else
-	#error Two-argument functions needed
-#endif
-
-/* Private USB opcode base */
-#define EHCI_FASTPATH		0x31
-#define	EHCI_SET_EP_BYPASS	EHCI_FASTPATH
-#define	EHCI_SET_BYPASS_CB	(EHCI_FASTPATH + 1)
-#define	EHCI_SET_BYPASS_DEV	(EHCI_FASTPATH + 2)
-#define	EHCI_DUMP_STATE		(EHCI_FASTPATH + 3)
-#define	EHCI_SET_BYPASS_POOL	(EHCI_FASTPATH + 4)
-#define	EHCI_CLR_EP_BYPASS	(EHCI_FASTPATH + 5)
-
-/*
- * EHCI QTD structure (hardware and extension)
- * NOTE that is does not need to (and does not) match its kernel counterpart
- */
-#define EHCI_QTD_NBUFFERS       5
-#define EHCI_QTD_ALIGN  	32
-#define EHCI_BULK_PACKET_SIZE	512
-#define EHCI_QTD_XACTERR_MAX	32
-
-struct ehci_qtd {
-	/* Hardware map */
-	volatile uint32_t	qtd_next;
-	volatile uint32_t	qtd_altnext;
-	volatile uint32_t	qtd_status;
-#define	EHCI_QTD_GET_BYTES(x)	(((x)>>16) & 0x7fff)
-#define	EHCI_QTD_IOC            0x00008000
-#define	EHCI_QTD_GET_CERR(x)	(((x)>>10) & 0x3)
-#define EHCI_QTD_SET_CERR(x)    ((x) << 10)
-#define	EHCI_QTD_GET_PID(x)	(((x)>>8) & 0x3)
-#define EHCI_QTD_SET_PID(x)     ((x) <<  8)
-#define EHCI_QTD_ACTIVE         0x80
-#define EHCI_QTD_HALTED         0x40
-#define EHCI_QTD_BUFERR         0x20
-#define EHCI_QTD_BABBLE         0x10
-#define EHCI_QTD_XACTERR        0x08
-#define EHCI_QTD_MISSEDMICRO    0x04
-	volatile uint32_t 	qtd_buffer[EHCI_QTD_NBUFFERS];
-	volatile uint32_t 	qtd_buffer_hi[EHCI_QTD_NBUFFERS];
-
-	/* Implementation extension */
-	dma_addr_t		qtd_self;		/**< own hardware address */
-	struct ehci_qtd		*obj_next;		/**< software link to the next QTD */
-	void			*rpc;			/**< pointer to the rpc buffer */
-	size_t			length;			/**< length of the data in the buffer */
-	void			*buff;			/**< pointer to the reassembly buffer */
-	int			xacterrs;		/**< retry counter for qtd xact error */
-} __attribute__ ((aligned(EHCI_QTD_ALIGN)));
-
-#define	EHCI_NULL	__constant_cpu_to_le32(1) /* HW null pointer shall be odd */
-
-#define SHORT_READ_Q(token) (EHCI_QTD_GET_BYTES(token) != 0 && EHCI_QTD_GET_PID(token) == 1)
-
-/**
- * Queue Head
- * NOTE This structure is slightly different from the one in the kernel; but needs to stay
- * compatible.
- */
-struct ehci_qh {
-	/* Hardware map */
-	volatile uint32_t 	qh_link;
-	volatile uint32_t 	qh_endp;
-	volatile uint32_t 	qh_endphub;
-	volatile uint32_t 	qh_curqtd;
-
-	/* QTD overlay */
-	volatile uint32_t	ow_next;
-	volatile uint32_t	ow_altnext;
-	volatile uint32_t	ow_status;
-	volatile uint32_t	ow_buffer [EHCI_QTD_NBUFFERS];
-	volatile uint32_t	ow_buffer_hi [EHCI_QTD_NBUFFERS];
-
-	/* Extension (should match the kernel layout) */
-	dma_addr_t		unused0;
-	void 			*unused1;
-	struct list_head	unused2;
-	struct ehci_qtd		*dummy;
-	struct ehci_qh		*unused3;
-
-	struct ehci_hcd		*unused4;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-	struct kref		unused5;
-	unsigned		unused6;
-
-	uint8_t			unused7;
-
-	/* periodic schedule info */
-	uint8_t			unused8;
-	uint8_t			unused9;
-	uint8_t			unused10;
-	uint16_t		unused11;
-	uint16_t		unused12;
-	uint16_t		unused13;
-	struct usb_device	*unused14;
-#else
-	unsigned		unused5;
-
-	u8			unused6;
-
-	/* periodic schedule info */
-	u8			unused7;
-	u8			unused8;
-	u8			unused9;
-	unsigned short		unused10;
-	unsigned short		unused11;
-#define NO_FRAME ((unsigned short)~0)
-#ifdef EHCI_QUIRK_FIX
-	struct usb_device	*unused12;
-#endif /* EHCI_QUIRK_FIX */
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */
-	struct ehci_qtd		*first_qtd;
-		/* Link to the first QTD; this is an optimized equivalent of the qtd_list field */
-		/* NOTE that ehci_qh in ehci.h shall reserve this word */
-} __attribute__ ((aligned(EHCI_QTD_ALIGN)));
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-/** The corresponding structure in the kernel is used to get the QH */
-struct hcd_dev {	/* usb_device.hcpriv points to this */
-	struct list_head	unused0;
-	struct list_head	unused1;
-
-	/* array of QH pointers */
-	void			*ep[32];
-};
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */
-
-int optimize_qtd_fill_with_rpc(const dbus_pub_t *pub,  int epn, struct ehci_qtd *qtd, void *rpc,
-	int token, int len);
-int optimize_qtd_fill_with_data(const dbus_pub_t *pub, int epn, struct ehci_qtd *qtd, void *data,
-	int token, int len);
-int optimize_submit_async(struct ehci_qtd *qtd, int epn);
-void inline optimize_ehci_qtd_init(struct ehci_qtd *qtd, dma_addr_t dma);
-struct ehci_qtd *optimize_ehci_qtd_alloc(gfp_t flags);
-void optimize_ehci_qtd_free(struct ehci_qtd *qtd);
-void optimize_submit_rx_request(const dbus_pub_t *pub, int epn, struct ehci_qtd *qtd_in, void *buf);
-#endif /* EHCI_FASTPATH_TX || EHCI_FASTPATH_RX */
-
-void  dbus_flowctrl_tx(void *dbi, bool on);
-#endif /* __DBUS_H__ */
diff --git a/drivers/net/wireless/bcmdhd/include/devctrl_if/wlioctl_defs.h b/drivers/net/wireless/bcmdhd/include/devctrl_if/wlioctl_defs.h
deleted file mode 100644
index 2fbe8e0..0000000
--- a/drivers/net/wireless/bcmdhd/include/devctrl_if/wlioctl_defs.h
+++ /dev/null
@@ -1,2114 +0,0 @@
-/*
- * Custom OID/ioctl definitions for
- * Broadcom 802.11abg Networking Device Driver
- *
- * Definitions subject to change without notice.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wlioctl_defs.h 403826 2013-05-22 16:40:55Z $
- */
-
-
-#ifndef wlioctl_defs_h
-#define wlioctl_defs_h
-
-
-
-
-
-/* All builds use the new 11ac ratespec/chanspec */
-#undef  D11AC_IOTYPES
-#define D11AC_IOTYPES
-
-/* WL_RSPEC defines for rate information */
-#define WL_RSPEC_RATE_MASK      0x000000FF      /* rate or HT MCS value */
-#define WL_RSPEC_VHT_MCS_MASK   0x0000000F      /* VHT MCS value */
-#define WL_RSPEC_VHT_NSS_MASK   0x000000F0      /* VHT Nss value */
-#define WL_RSPEC_VHT_NSS_SHIFT  4               /* VHT Nss value shift */
-#define WL_RSPEC_TXEXP_MASK     0x00000300
-#define WL_RSPEC_TXEXP_SHIFT    8
-#define WL_RSPEC_BW_MASK        0x00070000      /* bandwidth mask */
-#define WL_RSPEC_BW_SHIFT       16              /* bandwidth shift */
-#define WL_RSPEC_STBC           0x00100000      /* STBC encoding, Nsts = 2 x Nss */
-#define WL_RSPEC_TXBF           0x00200000      /* bit indicates TXBF mode */
-#define WL_RSPEC_LDPC           0x00400000      /* bit indicates adv coding in use */
-#define WL_RSPEC_SGI            0x00800000      /* Short GI mode */
-#define WL_RSPEC_ENCODING_MASK  0x03000000      /* Encoding of Rate/MCS field */
-#define WL_RSPEC_OVERRIDE_RATE  0x40000000      /* bit indicate to override mcs only */
-#define WL_RSPEC_OVERRIDE_MODE  0x80000000      /* bit indicates override both rate & mode */
-
-/* WL_RSPEC_ENCODING field defs */
-#define WL_RSPEC_ENCODE_RATE    0x00000000      /* Legacy rate is stored in RSPEC_RATE_MASK */
-#define WL_RSPEC_ENCODE_HT      0x01000000      /* HT MCS is stored in RSPEC_RATE_MASK */
-#define WL_RSPEC_ENCODE_VHT     0x02000000      /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */
-
-/* WL_RSPEC_BW field defs */
-#define WL_RSPEC_BW_UNSPECIFIED 0
-#define WL_RSPEC_BW_20MHZ       0x00010000
-#define WL_RSPEC_BW_40MHZ       0x00020000
-#define WL_RSPEC_BW_80MHZ       0x00030000
-#define WL_RSPEC_BW_160MHZ      0x00040000
-#define WL_RSPEC_BW_10MHZ	0x00050000
-#define WL_RSPEC_BW_5MHZ	0x00060000
-#define WL_RSPEC_BW_2P5MHZ      0x00070000
-
-/* Legacy defines for the nrate iovar */
-#define OLD_NRATE_MCS_INUSE         0x00000080 /* MSC in use,indicates b0-6 holds an mcs */
-#define OLD_NRATE_RATE_MASK         0x0000007f /* rate/mcs value */
-#define OLD_NRATE_STF_MASK          0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */
-#define OLD_NRATE_STF_SHIFT         8          /* stf mode shift */
-#define OLD_NRATE_OVERRIDE          0x80000000 /* bit indicates override both rate & mode */
-#define OLD_NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */
-#define OLD_NRATE_SGI               0x00800000 /* sgi mode */
-#define OLD_NRATE_LDPC_CODING       0x00400000 /* bit indicates adv coding in use */
-
-#define OLD_NRATE_STF_SISO	0		/* stf mode SISO */
-#define OLD_NRATE_STF_CDD	1		/* stf mode CDD */
-#define OLD_NRATE_STF_STBC	2		/* stf mode STBC */
-#define OLD_NRATE_STF_SDM	3		/* stf mode SDM */
-
-#define HIGHEST_SINGLE_STREAM_MCS	7 /* MCS values greater than this enable multiple streams */
-
-#define WLC_11N_N_PROP_MCS	6
-#define WLC_11N_FIRST_PROP_MCS	87
-#define WLC_11N_LAST_PROP_MCS	102
-
-
-#define MAX_CCA_CHANNELS 38	/* Max number of 20 Mhz wide channels */
-#define MAX_CCA_SECS	60	/* CCA keeps this many seconds history */
-
-#define IBSS_MED        15	/* Mediom in-bss congestion percentage */
-#define IBSS_HI         25	/* Hi in-bss congestion percentage */
-#define OBSS_MED        12
-#define OBSS_HI         25
-#define INTERFER_MED    5
-#define INTERFER_HI     10
-
-#define  CCA_FLAG_2G_ONLY		0x01	/* Return a channel from 2.4 Ghz band */
-#define  CCA_FLAG_5G_ONLY		0x02	/* Return a channel from 2.4 Ghz band */
-#define  CCA_FLAG_IGNORE_DURATION	0x04	/* Ignore dwell time for each channel */
-#define  CCA_FLAGS_PREFER_1_6_11	0x10
-#define  CCA_FLAG_IGNORE_INTERFER 	0x20 /* do not exlude channel based on interfer level */
-
-#define CCA_ERRNO_BAND 		1	/* After filtering for band pref, no choices left */
-#define CCA_ERRNO_DURATION	2	/* After filtering for duration, no choices left */
-#define CCA_ERRNO_PREF_CHAN	3	/* After filtering for chan pref, no choices left */
-#define CCA_ERRNO_INTERFER	4	/* After filtering for interference, no choices left */
-#define CCA_ERRNO_TOO_FEW	5	/* Only 1 channel was input */
-
-#define WL_STA_AID(a)		((a) &~ 0xc000)
-
-/* Flags for sta_info_t indicating properties of STA */
-#define WL_STA_BRCM		0x00000001	/* Running a Broadcom driver */
-#define WL_STA_WME		0x00000002	/* WMM association */
-#define WL_STA_NONERP		0x00000004	/* No ERP */
-#define WL_STA_AUTHE		0x00000008	/* Authenticated */
-#define WL_STA_ASSOC		0x00000010	/* Associated */
-#define WL_STA_AUTHO		0x00000020	/* Authorized */
-#define WL_STA_WDS		0x00000040	/* Wireless Distribution System */
-#define WL_STA_WDS_LINKUP	0x00000080	/* WDS traffic/probes flowing properly */
-#define WL_STA_PS		0x00000100	/* STA is in power save mode from AP's viewpoint */
-#define WL_STA_APSD_BE		0x00000200	/* APSD delv/trigger for AC_BE is default enabled */
-#define WL_STA_APSD_BK		0x00000400	/* APSD delv/trigger for AC_BK is default enabled */
-#define WL_STA_APSD_VI		0x00000800	/* APSD delv/trigger for AC_VI is default enabled */
-#define WL_STA_APSD_VO		0x00001000	/* APSD delv/trigger for AC_VO is default enabled */
-#define WL_STA_N_CAP		0x00002000	/* STA 802.11n capable */
-#define WL_STA_SCBSTATS		0x00004000	/* Per STA debug stats */
-#define WL_STA_AMPDU_CAP	0x00008000	/* STA AMPDU capable */
-#define WL_STA_AMSDU_CAP	0x00010000	/* STA AMSDU capable */
-#define WL_STA_MIMO_PS		0x00020000	/* mimo ps mode is enabled */
-#define WL_STA_MIMO_RTS		0x00040000	/* send rts in mimo ps mode */
-#define WL_STA_RIFS_CAP		0x00080000	/* rifs enabled */
-#define WL_STA_VHT_CAP		0x00100000	/* STA VHT(11ac) capable */
-#define WL_STA_WPS		0x00200000	/* WPS state */
-
-#define WL_WDS_LINKUP		WL_STA_WDS_LINKUP	/* deprecated */
-
-/* STA HT cap fields */
-#define WL_STA_CAP_LDPC_CODING		0x0001	/* Support for rx of LDPC coded pkts */
-#define WL_STA_CAP_40MHZ		0x0002  /* FALSE:20Mhz, TRUE:20/40MHZ supported */
-#define WL_STA_CAP_MIMO_PS_MASK		0x000C  /* Mimo PS mask */
-#define WL_STA_CAP_MIMO_PS_SHIFT	0x0002	/* Mimo PS shift */
-#define WL_STA_CAP_MIMO_PS_OFF		0x0003	/* Mimo PS, no restriction */
-#define WL_STA_CAP_MIMO_PS_RTS		0x0001	/* Mimo PS, send RTS/CTS around MIMO frames */
-#define WL_STA_CAP_MIMO_PS_ON		0x0000	/* Mimo PS, MIMO disallowed */
-#define WL_STA_CAP_GF			0x0010	/* Greenfield preamble support */
-#define WL_STA_CAP_SHORT_GI_20		0x0020	/* 20MHZ short guard interval support */
-#define WL_STA_CAP_SHORT_GI_40		0x0040	/* 40Mhz short guard interval support */
-#define WL_STA_CAP_TX_STBC		0x0080	/* Tx STBC support */
-#define WL_STA_CAP_RX_STBC_MASK		0x0300	/* Rx STBC mask */
-#define WL_STA_CAP_RX_STBC_SHIFT	8	/* Rx STBC shift */
-#define WL_STA_CAP_DELAYED_BA		0x0400	/* delayed BA support */
-#define WL_STA_CAP_MAX_AMSDU		0x0800	/* Max AMSDU size in bytes , 0=3839, 1=7935 */
-#define WL_STA_CAP_DSSS_CCK		0x1000	/* DSSS/CCK supported by the BSS */
-#define WL_STA_CAP_PSMP			0x2000	/* Power Save Multi Poll support */
-#define WL_STA_CAP_40MHZ_INTOLERANT	0x4000	/* 40MHz Intolerant */
-#define WL_STA_CAP_LSIG_TXOP		0x8000	/* L-SIG TXOP protection support */
-
-#define WL_STA_CAP_RX_STBC_NO		0x0	/* no rx STBC support */
-#define WL_STA_CAP_RX_STBC_ONE_STREAM	0x1	/* rx STBC support of 1 spatial stream */
-#define WL_STA_CAP_RX_STBC_TWO_STREAM	0x2	/* rx STBC support of 1-2 spatial streams */
-#define WL_STA_CAP_RX_STBC_THREE_STREAM	0x3	/* rx STBC support of 1-3 spatial streams */
-
-/* scb vht flags */
-#define WL_STA_VHT_LDPCCAP	0x0001
-#define WL_STA_SGI80		0x0002
-#define WL_STA_SGI160		0x0004
-#define WL_STA_VHT_TX_STBCCAP	0x0008
-#define WL_STA_VHT_RX_STBCCAP	0x0010
-#define WL_STA_SU_BEAMFORMER	0x0020
-#define WL_STA_SU_BEAMFORMEE	0x0040
-#define WL_STA_MU_BEAMFORMER	0x0080
-#define WL_STA_MU_BEAMFORMEE	0x0100
-#define WL_STA_VHT_TXOP_PS	0x0200
-#define WL_STA_HTC_VHT_CAP	0x0400
-
-/* Values for TX Filter override mode */
-#define WLC_TXFILTER_OVERRIDE_DISABLED  0
-#define WLC_TXFILTER_OVERRIDE_ENABLED   1
-
-#define WL_IOCTL_ACTION_GET		0x0
-#define WL_IOCTL_ACTION_SET		0x1
-#define WL_IOCTL_ACTION_OVL_IDX_MASK	0x1e
-#define WL_IOCTL_ACTION_OVL_RSV		0x20
-#define WL_IOCTL_ACTION_OVL		0x40
-#define WL_IOCTL_ACTION_MASK		0x7e
-#define WL_IOCTL_ACTION_OVL_SHIFT	1
-
-/* For WLC_SET_INFRA ioctl & infra_configuration iovar SET/GET operations */
-#define WL_BSSTYPE_INDEP 0
-#define WL_BSSTYPE_INFRA 1
-#define WL_BSSTYPE_ANY   2	/* deprecated */
-#define WL_BSSTYPE_MESH  3
-
-/* Bitmask for scan_type */
-#define WL_SCANFLAGS_PASSIVE	0x01	/* force passive scan */
-#define WL_SCANFLAGS_RESERVED	0x02	/* Reserved */
-#define WL_SCANFLAGS_PROHIBITED	0x04	/* allow scanning prohibited channels */
-#define WL_SCANFLAGS_OFFCHAN	0x08	/* allow scanning/reporting off-channel APs */
-#define WL_SCANFLAGS_HOTSPOT	0x10	/* automatic ANQP to hotspot APs */
-#define WL_SCANFLAGS_SWTCHAN	0x20	/* Force channel switch for differerent bandwidth */
-#define WL_SCANFLAGS_FORCE_PARALLEL 0x40 /* Force parallel scan even when actcb_fn_t is on.
-					  * by default parallel scan will be disabled if actcb_fn_t
-					  * is provided.
-					  */
-
-/* wl_iscan_results status values */
-#define WL_SCAN_RESULTS_SUCCESS	0
-#define WL_SCAN_RESULTS_PARTIAL	1
-#define WL_SCAN_RESULTS_PENDING	2
-#define WL_SCAN_RESULTS_ABORTED	3
-#define WL_SCAN_RESULTS_NO_MEM  4
-
-#define SCANOL_ENABLED			(1 << 0)
-#define SCANOL_BCAST_SSID		(1 << 1)
-#define SCANOL_NOTIFY_BCAST_SSID	(1 << 2)
-#define SCANOL_RESULTS_PER_CYCLE	(1 << 3)
-
-/* scan times in milliseconds */
-#define SCANOL_HOME_TIME		45	/* for home channel processing */
-#define SCANOL_ASSOC_TIME		20	/* dwell on a channel while associated */
-#define SCANOL_UNASSOC_TIME		40	/* dwell on a channel while unassociated */
-#define SCANOL_PASSIVE_TIME		110	/* listen on a channelfor passive scan */
-#define SCANOL_AWAY_LIMIT		100	/* max time to be away from home channel */
-#define SCANOL_IDLE_REST_TIME		40
-#define SCANOL_IDLE_REST_MULTIPLIER	0
-#define SCANOL_ACTIVE_REST_TIME		20
-#define SCANOL_ACTIVE_REST_MULTIPLIER	0
-#define SCANOL_CYCLE_IDLE_REST_TIME	300000	/* Idle Rest Time between Scan Cycle (msec) */
-#define SCANOL_CYCLE_IDLE_REST_MULTIPLIER	0	/* Idle Rest Time Multiplier */
-#define SCANOL_CYCLE_ACTIVE_REST_TIME	200
-#define SCANOL_CYCLE_ACTIVE_REST_MULTIPLIER	0
-#define SCANOL_MAX_REST_TIME		3600000	/* max rest time between scan cycle (msec) */
-#define SCANOL_CYCLE_DEFAULT		0	/* default for Max Scan Cycle, 0 = forever */
-#define SCANOL_CYCLE_MAX		864000	/* Max Scan Cycle */
-						/* 10 sec/scan cycle => 100 days */
-#define SCANOL_NPROBES			2	/* for Active scan; send n probes on each channel */
-#define SCANOL_NPROBES_MAX		5	/* for Active scan; send n probes on each channel */
-#define SCANOL_SCAN_START_DLY		10	/* delay start of offload scan (sec) */
-#define SCANOL_SCAN_START_DLY_MAX	240	/* delay start of offload scan (sec) */
-#define SCANOL_MULTIPLIER_MAX		10	/* Max Multiplier */
-#define SCANOL_UNASSOC_TIME_MAX		100	/* max dwell on a channel while unassociated */
-#define SCANOL_PASSIVE_TIME_MAX		500	/* max listen on a channel for passive scan */
-#define SCANOL_SSID_MAX			16	/* max supported preferred SSID */
-
-/* masks for channel and ssid count */
-#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff
-#define WL_SCAN_PARAMS_NSSID_SHIFT 16
-
-#define WL_SCAN_ACTION_START      1
-#define WL_SCAN_ACTION_CONTINUE   2
-#define WL_SCAN_ACTION_ABORT      3
-
-
-#define ANTENNA_NUM_1	1		/* total number of antennas to be used */
-#define ANTENNA_NUM_2	2
-#define ANTENNA_NUM_3	3
-#define ANTENNA_NUM_4	4
-
-#define ANT_SELCFG_AUTO		0x80	/* bit indicates antenna sel AUTO */
-#define ANT_SELCFG_MASK		0x33	/* antenna configuration mask */
-#define ANT_SELCFG_TX_UNICAST	0	/* unicast tx antenna configuration */
-#define ANT_SELCFG_RX_UNICAST	1	/* unicast rx antenna configuration */
-#define ANT_SELCFG_TX_DEF	2	/* default tx antenna configuration */
-#define ANT_SELCFG_RX_DEF	3	/* default rx antenna configuration */
-
-/* interference source detection and identification mode */
-#define ITFR_MODE_DISABLE	0	/* disable feature */
-#define ITFR_MODE_MANUAL_ENABLE	1	/* enable manual detection */
-#define ITFR_MODE_AUTO_ENABLE	2	/* enable auto detection */
-
-/* bit definitions for flags in interference source report */
-#define ITFR_INTERFERENCED	1	/* interference detected */
-#define ITFR_HOME_CHANNEL	2	/* home channel has interference */
-#define ITFR_NOISY_ENVIRONMENT	4	/* noisy environemnt so feature stopped */
-
-#define WL_NUM_RPI_BINS		8
-#define WL_RM_TYPE_BASIC	1
-#define WL_RM_TYPE_CCA		2
-#define WL_RM_TYPE_RPI		3
-#define WL_RM_TYPE_ABORT	-1	/* ABORT any in-progress RM request */
-
-#define WL_RM_FLAG_PARALLEL	(1<<0)
-
-#define WL_RM_FLAG_LATE		(1<<1)
-#define WL_RM_FLAG_INCAPABLE	(1<<2)
-#define WL_RM_FLAG_REFUSED	(1<<3)
-
-/* flags */
-#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */
-
-#define WLC_CIS_DEFAULT	0	/* built-in default */
-#define WLC_CIS_SROM	1	/* source is sprom */
-#define WLC_CIS_OTP	2	/* source is otp */
-
-/* PCL - Power Control Loop */
-/* current gain setting is replaced by user input */
-#define WL_ATTEN_APP_INPUT_PCL_OFF	0	/* turn off PCL, apply supplied input */
-#define WL_ATTEN_PCL_ON			1	/* turn on PCL */
-/* current gain setting is maintained */
-#define WL_ATTEN_PCL_OFF		2	/* turn off PCL. */
-
-/* defines used by poweridx iovar - it controls power in a-band */
-/* current gain setting is maintained */
-#define WL_PWRIDX_PCL_OFF	-2	/* turn off PCL.  */
-#define WL_PWRIDX_PCL_ON	-1	/* turn on PCL */
-#define WL_PWRIDX_LOWER_LIMIT	-2	/* lower limit */
-#define WL_PWRIDX_UPPER_LIMIT	63	/* upper limit */
-/* value >= 0 causes
- *	- input to be set to that value
- *	- PCL to be off
- */
-
-#define BCM_MAC_STATUS_INDICATION	(0x40010200L)
-
-/* Values for TX Filter override mode */
-#define WLC_TXFILTER_OVERRIDE_DISABLED  0
-#define WLC_TXFILTER_OVERRIDE_ENABLED   1
-
-/* magic pattern used for mismatch driver and wl */
-#define WL_TXFIFO_SZ_MAGIC	0xa5a5
-
-/* check this magic number */
-#define WLC_IOCTL_MAGIC		0x14e46c77
-
-/* bss_info_cap_t flags */
-#define WL_BSS_FLAGS_FROM_BEACON	0x01	/* bss_info derived from beacon */
-#define WL_BSS_FLAGS_FROM_CACHE		0x02	/* bss_info collected from cache */
-#define WL_BSS_FLAGS_RSSI_ONCHANNEL	0x04	/* rssi info received on channel (vs offchannel) */
-#define WL_BSS_FLAGS_HS20		0x08	/* hotspot 2.0 capable */
-#define WL_BSS_FLAGS_RSSI_INVALID	0x10	/* BSS contains invalid RSSI */
-#define WL_BSS_FLAGS_RSSI_INACCURATE	0x20	/* BSS contains inaccurate RSSI */
-#define WL_BSS_FLAGS_SNR_INVALID	0x40	/* BSS contains invalid SNR */
-#define WL_BSS_FLAGS_NF_INVALID		0x80	/* BSS contains invalid noise floor */
-
-/* bssinfo flag for nbss_cap */
-#define VHT_BI_SGI_80MHZ			0x00000100
-#define VHT_BI_80MHZ			    0x00000200
-#define VHT_BI_160MHZ			    0x00000400
-#define VHT_BI_8080MHZ			    0x00000800
-
-/* reference to wl_ioctl_t struct used by usermode driver */
-#define ioctl_subtype	set		/* subtype param */
-#define ioctl_pid	used		/* pid param */
-#define ioctl_status	needed		/* status param */
-
-
-/* Enumerate crypto algorithms */
-#define	CRYPTO_ALGO_OFF			0
-#define	CRYPTO_ALGO_WEP1		1
-#define	CRYPTO_ALGO_TKIP		2
-#define	CRYPTO_ALGO_WEP128		3
-#define CRYPTO_ALGO_AES_CCM		4
-#define CRYPTO_ALGO_AES_OCB_MSDU	5
-#define CRYPTO_ALGO_AES_OCB_MPDU	6
-#if !defined(BCMEXTCCX)
-#define CRYPTO_ALGO_NALG		7
-#else
-#define CRYPTO_ALGO_CKIP		7
-#define CRYPTO_ALGO_CKIP_MMH	8
-#define CRYPTO_ALGO_WEP_MMH		9
-#define CRYPTO_ALGO_NALG		10
-#endif 
-
-#define CRYPTO_ALGO_SMS4		11
-#define CRYPTO_ALGO_PMK			12	/* for 802.1x supp to set PMK before 4-way */
-#define CRYPTO_ALGO_BIP			13  /* 802.11w BIP (aes cmac) */
-
-#define CRYPTO_ALGO_AES_GCM     14  /* 128 bit GCM */
-#define CRYPTO_ALGO_AES_CCM256  15  /* 256 bit CCM */
-#define CRYPTO_ALGO_AES_GCM256  16  /* 256 bit GCM */
-#define CRYPTO_ALGO_BIP_CMAC256 17  /* 256 bit BIP CMAC */
-#define CRYPTO_ALGO_BIP_GMAC    18  /* 128 bit BIP GMAC */
-#define CRYPTO_ALGO_BIP_GMAC256 19  /* 256 bit BIP GMAC */
-
-#define CRYPTO_ALGO_NONE        CRYPTO_ALGO_OFF
-
-#define WSEC_GEN_MIC_ERROR	0x0001
-#define WSEC_GEN_REPLAY		0x0002
-#define WSEC_GEN_ICV_ERROR	0x0004
-#define WSEC_GEN_MFP_ACT_ERROR	0x0008
-#define WSEC_GEN_MFP_DISASSOC_ERROR	0x0010
-#define WSEC_GEN_MFP_DEAUTH_ERROR	0x0020
-
-#define WL_SOFT_KEY	(1 << 0)	/* Indicates this key is using soft encrypt */
-#define WL_PRIMARY_KEY	(1 << 1)	/* Indicates this key is the primary (ie tx) key */
-#if defined(BCMEXTCCX)
-#define WL_CKIP_KP	(1 << 4)	/* CMIC */
-#define WL_CKIP_MMH	(1 << 5)	/* CKIP */
-#else
-#define WL_KF_RES_4	(1 << 4)	/* Reserved for backward compat */
-#define WL_KF_RES_5	(1 << 5)	/* Reserved for backward compat */
-#endif 
-#define WL_IBSS_PEER_GROUP_KEY	(1 << 6)	/* Indicates a group key for a IBSS PEER */
-
-/* wireless security bitvec */
-#define WEP_ENABLED		0x0001
-#define TKIP_ENABLED		0x0002
-#define AES_ENABLED		0x0004
-#define WSEC_SWFLAG		0x0008
-#define SES_OW_ENABLED		0x0040	/* to go into transition mode without setting wep */
-
-/* wsec macros for operating on the above definitions */
-#define WSEC_WEP_ENABLED(wsec)	((wsec) & WEP_ENABLED)
-#define WSEC_TKIP_ENABLED(wsec)	((wsec) & TKIP_ENABLED)
-#define WSEC_AES_ENABLED(wsec)	((wsec) & AES_ENABLED)
-
-#define WSEC_ENABLED(wsec)	((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
-#define WSEC_SES_OW_ENABLED(wsec)	((wsec) & SES_OW_ENABLED)
-
-/* Following macros are not used any more. Just kept here to
- * avoid build issue in BISON/CARIBOU branch
- */
-#define MFP_CAPABLE		0x0200
-#define MFP_REQUIRED	0x0400
-#define MFP_SHA256		0x0800 /* a special configuration for STA for WIFI test tool */
-
-/* WPA authentication mode bitvec */
-#define WPA_AUTH_DISABLED	0x0000	/* Legacy (i.e., non-WPA) */
-#define WPA_AUTH_NONE		0x0001	/* none (IBSS) */
-#define WPA_AUTH_UNSPECIFIED	0x0002	/* over 802.1x */
-#define WPA_AUTH_PSK		0x0004	/* Pre-shared key */
-#if defined(BCMEXTCCX)
-#define WPA_AUTH_CCKM		0x0008	/* CCKM */
-#define WPA2_AUTH_CCKM		0x0010	/* CCKM2 */
-#endif	
-/* #define WPA_AUTH_8021X 0x0020 */	/* 802.1x, reserved */
-#define WPA2_AUTH_UNSPECIFIED	0x0040	/* over 802.1x */
-#define WPA2_AUTH_PSK		0x0080	/* Pre-shared key */
-#define BRCM_AUTH_PSK           0x0100  /* BRCM specific PSK */
-#define BRCM_AUTH_DPT		0x0200	/* DPT PSK without group keys */
-#define WPA2_AUTH_1X_SHA256	0x1000  /* 1X with SHA256 key derivation */
-#define WPA2_AUTH_TPK		0x2000	/* TDLS Peer Key */
-#define WPA2_AUTH_FT		0x4000	/* Fast Transition. */
-#define WPA2_AUTH_PSK_SHA256	0x8000	/* PSK with SHA256 key derivation */
-/* WPA2_AUTH_SHA256 not used anymore. Just kept here to avoid build issue in DINGO */
-#define WPA2_AUTH_SHA256	0x8000
-#define WPA_AUTH_PFN_ANY	0xffffffff	/* for PFN, match only ssid */
-
-/* pmkid */
-#define	MAXPMKID		16
-
-/* SROM12 changes */
-#define	WLC_IOCTL_MAXLEN		8192	/* max length ioctl buffer required */
-
-
-#define	WLC_IOCTL_SMLEN			256	/* "small" length ioctl buffer required */
-#define WLC_IOCTL_MEDLEN		1536    /* "med" length ioctl buffer required */
-#if defined(LCNCONF) || defined(LCN40CONF) || defined(LCN20CONF)
-#define WLC_SAMPLECOLLECT_MAXLEN	8192	/* Max Sample Collect buffer */
-#else
-#define WLC_SAMPLECOLLECT_MAXLEN	10240	/* Max Sample Collect buffer for two cores */
-#endif
-#define WLC_SAMPLECOLLECT_MAXLEN_LCN40  8192
-
-/* common ioctl definitions */
-#define WLC_GET_MAGIC				0
-#define WLC_GET_VERSION				1
-#define WLC_UP					2
-#define WLC_DOWN				3
-#define WLC_GET_LOOP				4
-#define WLC_SET_LOOP				5
-#define WLC_DUMP				6
-#define WLC_GET_MSGLEVEL			7
-#define WLC_SET_MSGLEVEL			8
-#define WLC_GET_PROMISC				9
-#define WLC_SET_PROMISC				10
-/* #define WLC_OVERLAY_IOCTL			11 */ /* not supported */
-#define WLC_GET_RATE				12
-#define WLC_GET_MAX_RATE			13
-#define WLC_GET_INSTANCE			14
-/* #define WLC_GET_FRAG				15 */ /* no longer supported */
-/* #define WLC_SET_FRAG				16 */ /* no longer supported */
-/* #define WLC_GET_RTS				17 */ /* no longer supported */
-/* #define WLC_SET_RTS				18 */ /* no longer supported */
-#define WLC_GET_INFRA				19
-#define WLC_SET_INFRA				20
-#define WLC_GET_AUTH				21
-#define WLC_SET_AUTH				22
-#define WLC_GET_BSSID				23
-#define WLC_SET_BSSID				24
-#define WLC_GET_SSID				25
-#define WLC_SET_SSID				26
-#define WLC_RESTART				27
-#define WLC_TERMINATED				28
-/* #define WLC_DUMP_SCB				28 */ /* no longer supported */
-#define WLC_GET_CHANNEL				29
-#define WLC_SET_CHANNEL				30
-#define WLC_GET_SRL				31
-#define WLC_SET_SRL				32
-#define WLC_GET_LRL				33
-#define WLC_SET_LRL				34
-#define WLC_GET_PLCPHDR				35
-#define WLC_SET_PLCPHDR				36
-#define WLC_GET_RADIO				37
-#define WLC_SET_RADIO				38
-#define WLC_GET_PHYTYPE				39
-#define WLC_DUMP_RATE				40
-#define WLC_SET_RATE_PARAMS			41
-#define WLC_GET_FIXRATE				42
-#define WLC_SET_FIXRATE				43
-/* #define WLC_GET_WEP				42 */ /* no longer supported */
-/* #define WLC_SET_WEP				43 */ /* no longer supported */
-#define WLC_GET_KEY				44
-#define WLC_SET_KEY				45
-#define WLC_GET_REGULATORY			46
-#define WLC_SET_REGULATORY			47
-#define WLC_GET_PASSIVE_SCAN			48
-#define WLC_SET_PASSIVE_SCAN			49
-#define WLC_SCAN				50
-#define WLC_SCAN_RESULTS			51
-#define WLC_DISASSOC				52
-#define WLC_REASSOC				53
-#define WLC_GET_ROAM_TRIGGER			54
-#define WLC_SET_ROAM_TRIGGER			55
-#define WLC_GET_ROAM_DELTA			56
-#define WLC_SET_ROAM_DELTA			57
-#define WLC_GET_ROAM_SCAN_PERIOD		58
-#define WLC_SET_ROAM_SCAN_PERIOD		59
-#define WLC_EVM					60	/* diag */
-#define WLC_GET_TXANT				61
-#define WLC_SET_TXANT				62
-#define WLC_GET_ANTDIV				63
-#define WLC_SET_ANTDIV				64
-/* #define WLC_GET_TXPWR			65 */ /* no longer supported */
-/* #define WLC_SET_TXPWR			66 */ /* no longer supported */
-#define WLC_GET_CLOSED				67
-#define WLC_SET_CLOSED				68
-#define WLC_GET_MACLIST				69
-#define WLC_SET_MACLIST				70
-#define WLC_GET_RATESET				71
-#define WLC_SET_RATESET				72
-/* #define WLC_GET_LOCALE			73 */ /* no longer supported */
-#define WLC_LONGTRAIN				74
-#define WLC_GET_BCNPRD				75
-#define WLC_SET_BCNPRD				76
-#define WLC_GET_DTIMPRD				77
-#define WLC_SET_DTIMPRD				78
-#define WLC_GET_SROM				79
-#define WLC_SET_SROM				80
-#define WLC_GET_WEP_RESTRICT			81
-#define WLC_SET_WEP_RESTRICT			82
-#define WLC_GET_COUNTRY				83
-#define WLC_SET_COUNTRY				84
-#define WLC_GET_PM				85
-#define WLC_SET_PM				86
-#define WLC_GET_WAKE				87
-#define WLC_SET_WAKE				88
-/* #define WLC_GET_D11CNTS			89 */ /* -> "counters" iovar */
-#define WLC_GET_FORCELINK			90	/* ndis only */
-#define WLC_SET_FORCELINK			91	/* ndis only */
-#define WLC_FREQ_ACCURACY			92	/* diag */
-#define WLC_CARRIER_SUPPRESS			93	/* diag */
-#define WLC_GET_PHYREG				94
-#define WLC_SET_PHYREG				95
-#define WLC_GET_RADIOREG			96
-#define WLC_SET_RADIOREG			97
-#define WLC_GET_REVINFO				98
-#define WLC_GET_UCANTDIV			99
-#define WLC_SET_UCANTDIV			100
-#define WLC_R_REG				101
-#define WLC_W_REG				102
-/* #define WLC_DIAG_LOOPBACK			103	old tray diag */
-/* #define WLC_RESET_D11CNTS			104 */ /* -> "reset_d11cnts" iovar */
-#define WLC_GET_MACMODE				105
-#define WLC_SET_MACMODE				106
-#define WLC_GET_MONITOR				107
-#define WLC_SET_MONITOR				108
-#define WLC_GET_GMODE				109
-#define WLC_SET_GMODE				110
-#define WLC_GET_LEGACY_ERP			111
-#define WLC_SET_LEGACY_ERP			112
-#define WLC_GET_RX_ANT				113
-#define WLC_GET_CURR_RATESET			114	/* current rateset */
-#define WLC_GET_SCANSUPPRESS			115
-#define WLC_SET_SCANSUPPRESS			116
-#define WLC_GET_AP				117
-#define WLC_SET_AP				118
-#define WLC_GET_EAP_RESTRICT			119
-#define WLC_SET_EAP_RESTRICT			120
-#define WLC_SCB_AUTHORIZE			121
-#define WLC_SCB_DEAUTHORIZE			122
-#define WLC_GET_WDSLIST				123
-#define WLC_SET_WDSLIST				124
-#define WLC_GET_ATIM				125
-#define WLC_SET_ATIM				126
-#define WLC_GET_RSSI				127
-#define WLC_GET_PHYANTDIV			128
-#define WLC_SET_PHYANTDIV			129
-#define WLC_AP_RX_ONLY				130
-#define WLC_GET_TX_PATH_PWR			131
-#define WLC_SET_TX_PATH_PWR			132
-#define WLC_GET_WSEC				133
-#define WLC_SET_WSEC				134
-#define WLC_GET_PHY_NOISE			135
-#define WLC_GET_BSS_INFO			136
-#define WLC_GET_PKTCNTS				137
-#define WLC_GET_LAZYWDS				138
-#define WLC_SET_LAZYWDS				139
-#define WLC_GET_BANDLIST			140
-
-#define WLC_GET_BAND				141
-#define WLC_SET_BAND				142
-#define WLC_SCB_DEAUTHENTICATE			143
-#define WLC_GET_SHORTSLOT			144
-#define WLC_GET_SHORTSLOT_OVERRIDE		145
-#define WLC_SET_SHORTSLOT_OVERRIDE		146
-#define WLC_GET_SHORTSLOT_RESTRICT		147
-#define WLC_SET_SHORTSLOT_RESTRICT		148
-#define WLC_GET_GMODE_PROTECTION		149
-#define WLC_GET_GMODE_PROTECTION_OVERRIDE	150
-#define WLC_SET_GMODE_PROTECTION_OVERRIDE	151
-#define WLC_UPGRADE				152
-/* #define WLC_GET_MRATE			153 */ /* no longer supported */
-/* #define WLC_SET_MRATE			154 */ /* no longer supported */
-#define WLC_GET_IGNORE_BCNS			155
-#define WLC_SET_IGNORE_BCNS			156
-#define WLC_GET_SCB_TIMEOUT			157
-#define WLC_SET_SCB_TIMEOUT			158
-#define WLC_GET_ASSOCLIST			159
-#define WLC_GET_CLK				160
-#define WLC_SET_CLK				161
-#define WLC_GET_UP				162
-#define WLC_OUT					163
-#define WLC_GET_WPA_AUTH			164
-#define WLC_SET_WPA_AUTH			165
-#define WLC_GET_UCFLAGS				166
-#define WLC_SET_UCFLAGS				167
-#define WLC_GET_PWRIDX				168
-#define WLC_SET_PWRIDX				169
-#define WLC_GET_TSSI				170
-#define WLC_GET_SUP_RATESET_OVERRIDE		171
-#define WLC_SET_SUP_RATESET_OVERRIDE		172
-/* #define WLC_SET_FAST_TIMER			173 */ /* no longer supported */
-/* #define WLC_GET_FAST_TIMER			174 */ /* no longer supported */
-/* #define WLC_SET_SLOW_TIMER			175 */ /* no longer supported */
-/* #define WLC_GET_SLOW_TIMER			176 */ /* no longer supported */
-/* #define WLC_DUMP_PHYREGS			177 */ /* no longer supported */
-#define WLC_GET_PROTECTION_CONTROL		178
-#define WLC_SET_PROTECTION_CONTROL		179
-#define WLC_GET_PHYLIST				180
-#define WLC_ENCRYPT_STRENGTH			181	/* ndis only */
-#define WLC_DECRYPT_STATUS			182	/* ndis only */
-#define WLC_GET_KEY_SEQ				183
-#define WLC_GET_SCAN_CHANNEL_TIME		184
-#define WLC_SET_SCAN_CHANNEL_TIME		185
-#define WLC_GET_SCAN_UNASSOC_TIME		186
-#define WLC_SET_SCAN_UNASSOC_TIME		187
-#define WLC_GET_SCAN_HOME_TIME			188
-#define WLC_SET_SCAN_HOME_TIME			189
-#define WLC_GET_SCAN_NPROBES			190
-#define WLC_SET_SCAN_NPROBES			191
-#define WLC_GET_PRB_RESP_TIMEOUT		192
-#define WLC_SET_PRB_RESP_TIMEOUT		193
-#define WLC_GET_ATTEN				194
-#define WLC_SET_ATTEN				195
-#define WLC_GET_SHMEM				196	/* diag */
-#define WLC_SET_SHMEM				197	/* diag */
-/* #define WLC_GET_GMODE_PROTECTION_CTS		198 */ /* no longer supported */
-/* #define WLC_SET_GMODE_PROTECTION_CTS		199 */ /* no longer supported */
-#define WLC_SET_WSEC_TEST			200
-#define WLC_SCB_DEAUTHENTICATE_FOR_REASON	201
-#define WLC_TKIP_COUNTERMEASURES		202
-#define WLC_GET_PIOMODE				203
-#define WLC_SET_PIOMODE				204
-#define WLC_SET_ASSOC_PREFER			205
-#define WLC_GET_ASSOC_PREFER			206
-#define WLC_SET_ROAM_PREFER			207
-#define WLC_GET_ROAM_PREFER			208
-#define WLC_SET_LED				209
-#define WLC_GET_LED				210
-#define WLC_GET_INTERFERENCE_MODE		211
-#define WLC_SET_INTERFERENCE_MODE		212
-#define WLC_GET_CHANNEL_QA			213
-#define WLC_START_CHANNEL_QA			214
-#define WLC_GET_CHANNEL_SEL			215
-#define WLC_START_CHANNEL_SEL			216
-#define WLC_GET_VALID_CHANNELS			217
-#define WLC_GET_FAKEFRAG			218
-#define WLC_SET_FAKEFRAG			219
-#define WLC_GET_PWROUT_PERCENTAGE		220
-#define WLC_SET_PWROUT_PERCENTAGE		221
-#define WLC_SET_BAD_FRAME_PREEMPT		222
-#define WLC_GET_BAD_FRAME_PREEMPT		223
-#define WLC_SET_LEAP_LIST			224
-#define WLC_GET_LEAP_LIST			225
-#define WLC_GET_CWMIN				226
-#define WLC_SET_CWMIN				227
-#define WLC_GET_CWMAX				228
-#define WLC_SET_CWMAX				229
-#define WLC_GET_WET				230
-#define WLC_SET_WET				231
-#define WLC_GET_PUB				232
-/* #define WLC_SET_GLACIAL_TIMER		233 */ /* no longer supported */
-/* #define WLC_GET_GLACIAL_TIMER		234 */ /* no longer supported */
-#define WLC_GET_KEY_PRIMARY			235
-#define WLC_SET_KEY_PRIMARY			236
-
-
-/* #define WLC_DUMP_RADIOREGS			237 */ /* no longer supported */
-#define WLC_GET_ACI_ARGS			238
-#define WLC_SET_ACI_ARGS			239
-#define WLC_UNSET_CALLBACK			240
-#define WLC_SET_CALLBACK			241
-#define WLC_GET_RADAR				242
-#define WLC_SET_RADAR				243
-#define WLC_SET_SPECT_MANAGMENT			244
-#define WLC_GET_SPECT_MANAGMENT			245
-#define WLC_WDS_GET_REMOTE_HWADDR		246	/* handled in wl_linux.c/wl_vx.c */
-#define WLC_WDS_GET_WPA_SUP			247
-#define WLC_SET_CS_SCAN_TIMER			248
-#define WLC_GET_CS_SCAN_TIMER			249
-#define WLC_MEASURE_REQUEST			250
-#define WLC_INIT				251
-#define WLC_SEND_QUIET				252
-#define WLC_KEEPALIVE			253
-#define WLC_SEND_PWR_CONSTRAINT			254
-#define WLC_UPGRADE_STATUS			255
-#define WLC_CURRENT_PWR				256
-#define WLC_GET_SCAN_PASSIVE_TIME		257
-#define WLC_SET_SCAN_PASSIVE_TIME		258
-#define WLC_LEGACY_LINK_BEHAVIOR		259
-#define WLC_GET_CHANNELS_IN_COUNTRY		260
-#define WLC_GET_COUNTRY_LIST			261
-#define WLC_GET_VAR				262	/* get value of named variable */
-#define WLC_SET_VAR				263	/* set named variable to value */
-#define WLC_NVRAM_GET				264	/* deprecated */
-#define WLC_NVRAM_SET				265
-#define WLC_NVRAM_DUMP				266
-#define WLC_REBOOT				267
-#define WLC_SET_WSEC_PMK			268
-#define WLC_GET_AUTH_MODE			269
-#define WLC_SET_AUTH_MODE			270
-#define WLC_GET_WAKEENTRY			271
-#define WLC_SET_WAKEENTRY			272
-#define WLC_NDCONFIG_ITEM			273	/* currently handled in wl_oid.c */
-#define WLC_NVOTPW				274
-#define WLC_OTPW				275
-#define WLC_IOV_BLOCK_GET			276
-#define WLC_IOV_MODULES_GET			277
-#define WLC_SOFT_RESET				278
-#define WLC_GET_ALLOW_MODE			279
-#define WLC_SET_ALLOW_MODE			280
-#define WLC_GET_DESIRED_BSSID			281
-#define WLC_SET_DESIRED_BSSID			282
-#define	WLC_DISASSOC_MYAP			283
-#define WLC_GET_NBANDS				284	/* for Dongle EXT_STA support */
-#define WLC_GET_BANDSTATES			285	/* for Dongle EXT_STA support */
-#define WLC_GET_WLC_BSS_INFO			286	/* for Dongle EXT_STA support */
-#define WLC_GET_ASSOC_INFO			287	/* for Dongle EXT_STA support */
-#define WLC_GET_OID_PHY				288	/* for Dongle EXT_STA support */
-#define WLC_SET_OID_PHY				289	/* for Dongle EXT_STA support */
-#define WLC_SET_ASSOC_TIME			290	/* for Dongle EXT_STA support */
-#define WLC_GET_DESIRED_SSID			291	/* for Dongle EXT_STA support */
-#define WLC_GET_CHANSPEC			292	/* for Dongle EXT_STA support */
-#define WLC_GET_ASSOC_STATE			293	/* for Dongle EXT_STA support */
-#define WLC_SET_PHY_STATE			294	/* for Dongle EXT_STA support */
-#define WLC_GET_SCAN_PENDING			295	/* for Dongle EXT_STA support */
-#define WLC_GET_SCANREQ_PENDING			296	/* for Dongle EXT_STA support */
-#define WLC_GET_PREV_ROAM_REASON		297	/* for Dongle EXT_STA support */
-#define WLC_SET_PREV_ROAM_REASON		298	/* for Dongle EXT_STA support */
-#define WLC_GET_BANDSTATES_PI			299	/* for Dongle EXT_STA support */
-#define WLC_GET_PHY_STATE			300	/* for Dongle EXT_STA support */
-#define WLC_GET_BSS_WPA_RSN			301	/* for Dongle EXT_STA support */
-#define WLC_GET_BSS_WPA2_RSN			302	/* for Dongle EXT_STA support */
-#define WLC_GET_BSS_BCN_TS			303	/* for Dongle EXT_STA support */
-#define WLC_GET_INT_DISASSOC			304	/* for Dongle EXT_STA support */
-#define WLC_SET_NUM_PEERS			305     /* for Dongle EXT_STA support */
-#define WLC_GET_NUM_BSS				306	/* for Dongle EXT_STA support */
-#define WLC_PHY_SAMPLE_COLLECT			307	/* phy sample collect mode */
-/* #define WLC_UM_PRIV				308 */	/* Deprecated: usermode driver */
-#define WLC_GET_CMD				309
-/* #define WLC_LAST				310 */	/* Never used - can be reused */
-#define WLC_SET_INTERFERENCE_OVERRIDE_MODE	311	/* set inter mode override */
-#define WLC_GET_INTERFERENCE_OVERRIDE_MODE	312	/* get inter mode override */
-/* #define WLC_GET_WAI_RESTRICT			313 */	/* for WAPI, deprecated use iovar instead */
-/* #define WLC_SET_WAI_RESTRICT			314 */	/* for WAPI, deprecated use iovar instead */
-/* #define WLC_SET_WAI_REKEY			315 */	/* for WAPI, deprecated use iovar instead */
-#define WLC_SET_NAT_CONFIG			316	/* for configuring NAT filter driver */
-#define WLC_GET_NAT_STATE			317
-#define WLC_GET_TXBF_RATESET			318
-#define WLC_SET_TXBF_RATESET			319
-#define WLC_SCAN_CQ				320
-#define WLC_GET_RSSI_QDB			321 /* qdB portion of the RSSI */
-#define WLC_DUMP_RATESET			322
-#define WLC_ECHO				323
-#define WLC_LAST				324
-#ifndef EPICTRL_COOKIE
-#define EPICTRL_COOKIE		0xABADCEDE
-#endif
-
-/* vx wlc ioctl's offset */
-#define CMN_IOCTL_OFF 0x180
-
-/*
- * custom OID support
- *
- * 0xFF - implementation specific OID
- * 0xE4 - first byte of Broadcom PCI vendor ID
- * 0x14 - second byte of Broadcom PCI vendor ID
- * 0xXX - the custom OID number
- */
-
-/* begin 0x1f values beyond the start of the ET driver range. */
-#define WL_OID_BASE		0xFFE41420
-
-/* NDIS overrides */
-#define OID_WL_GETINSTANCE	(WL_OID_BASE + WLC_GET_INSTANCE)
-#define OID_WL_GET_FORCELINK	(WL_OID_BASE + WLC_GET_FORCELINK)
-#define OID_WL_SET_FORCELINK	(WL_OID_BASE + WLC_SET_FORCELINK)
-#define	OID_WL_ENCRYPT_STRENGTH	(WL_OID_BASE + WLC_ENCRYPT_STRENGTH)
-#define OID_WL_DECRYPT_STATUS	(WL_OID_BASE + WLC_DECRYPT_STATUS)
-#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR)
-#define OID_WL_NDCONFIG_ITEM	(WL_OID_BASE + WLC_NDCONFIG_ITEM)
-
-/* EXT_STA Dongle suuport */
-#define OID_STA_CHANSPEC	(WL_OID_BASE + WLC_GET_CHANSPEC)
-#define OID_STA_NBANDS		(WL_OID_BASE + WLC_GET_NBANDS)
-#define OID_STA_GET_PHY		(WL_OID_BASE + WLC_GET_OID_PHY)
-#define OID_STA_SET_PHY		(WL_OID_BASE + WLC_SET_OID_PHY)
-#define OID_STA_ASSOC_TIME	(WL_OID_BASE + WLC_SET_ASSOC_TIME)
-#define OID_STA_DESIRED_SSID	(WL_OID_BASE + WLC_GET_DESIRED_SSID)
-#define OID_STA_SET_PHY_STATE	(WL_OID_BASE + WLC_SET_PHY_STATE)
-#define OID_STA_SCAN_PENDING	(WL_OID_BASE + WLC_GET_SCAN_PENDING)
-#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING)
-#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON)
-#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON)
-#define OID_STA_GET_PHY_STATE	(WL_OID_BASE + WLC_GET_PHY_STATE)
-#define OID_STA_INT_DISASSOC	(WL_OID_BASE + WLC_GET_INT_DISASSOC)
-#define OID_STA_SET_NUM_PEERS	(WL_OID_BASE + WLC_SET_NUM_PEERS)
-#define OID_STA_GET_NUM_BSS	(WL_OID_BASE + WLC_GET_NUM_BSS)
-
-/* NAT filter driver support */
-#define OID_NAT_SET_CONFIG	(WL_OID_BASE + WLC_SET_NAT_CONFIG)
-#define OID_NAT_GET_STATE	(WL_OID_BASE + WLC_GET_NAT_STATE)
-
-#define WL_DECRYPT_STATUS_SUCCESS	1
-#define WL_DECRYPT_STATUS_FAILURE	2
-#define WL_DECRYPT_STATUS_UNKNOWN	3
-
-/* allows user-mode app to poll the status of USB image upgrade */
-#define WLC_UPGRADE_SUCCESS			0
-#define WLC_UPGRADE_PENDING			1
-
-/* WLC_GET_AUTH, WLC_SET_AUTH values */
-#define WL_AUTH_OPEN_SYSTEM		0	/* d11 open authentication */
-#define WL_AUTH_SHARED_KEY		1	/* d11 shared authentication */
-#define WL_AUTH_OPEN_SHARED		2	/* try open, then shared if open failed w/rc 13 */
-
-/* a large TX Power as an init value to factor out of MIN() calculations,
- * keep low enough to fit in an int8, units are .25 dBm
- */
-#define WLC_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
-
-/* "diag" iovar argument and error code */
-#define WL_DIAG_INTERRUPT			1	/* d11 loopback interrupt test */
-#define WL_DIAG_LOOPBACK			2	/* d11 loopback data test */
-#define WL_DIAG_MEMORY				3	/* d11 memory test */
-#define WL_DIAG_LED				4	/* LED test */
-#define WL_DIAG_REG				5	/* d11/phy register test */
-#define WL_DIAG_SROM				6	/* srom read/crc test */
-#define WL_DIAG_DMA				7	/* DMA test */
-#define WL_DIAG_LOOPBACK_EXT			8	/* enhenced d11 loopback data test */
-
-#define WL_DIAGERR_SUCCESS			0
-#define WL_DIAGERR_FAIL_TO_RUN			1	/* unable to run requested diag */
-#define WL_DIAGERR_NOT_SUPPORTED		2	/* diag requested is not supported */
-#define WL_DIAGERR_INTERRUPT_FAIL		3	/* loopback interrupt test failed */
-#define WL_DIAGERR_LOOPBACK_FAIL		4	/* loopback data test failed */
-#define WL_DIAGERR_SROM_FAIL			5	/* srom read failed */
-#define WL_DIAGERR_SROM_BADCRC			6	/* srom crc failed */
-#define WL_DIAGERR_REG_FAIL			7	/* d11/phy register test failed */
-#define WL_DIAGERR_MEMORY_FAIL			8	/* d11 memory test failed */
-#define WL_DIAGERR_NOMEM			9	/* diag test failed due to no memory */
-#define WL_DIAGERR_DMA_FAIL			10	/* DMA test failed */
-
-#define WL_DIAGERR_MEMORY_TIMEOUT		11	/* d11 memory test didn't finish in time */
-#define WL_DIAGERR_MEMORY_BADPATTERN		12	/* d11 memory test result in bad pattern */
-
-/* band types */
-#define	WLC_BAND_AUTO		0	/* auto-select */
-#define	WLC_BAND_5G		1	/* 5 Ghz */
-#define	WLC_BAND_2G		2	/* 2.4 Ghz */
-#define	WLC_BAND_ALL		3	/* all bands */
-
-/* band range returned by band_range iovar */
-#define WL_CHAN_FREQ_RANGE_2G      0
-#define WL_CHAN_FREQ_RANGE_5GL     1
-#define WL_CHAN_FREQ_RANGE_5GM     2
-#define WL_CHAN_FREQ_RANGE_5GH     3
-
-#define WL_CHAN_FREQ_RANGE_5GLL_5BAND    4
-#define WL_CHAN_FREQ_RANGE_5GLH_5BAND    5
-#define WL_CHAN_FREQ_RANGE_5GML_5BAND    6
-#define WL_CHAN_FREQ_RANGE_5GMH_5BAND    7
-#define WL_CHAN_FREQ_RANGE_5GH_5BAND     8
-
-#define WL_CHAN_FREQ_RANGE_5G_BAND0     1
-#define WL_CHAN_FREQ_RANGE_5G_BAND1     2
-#define WL_CHAN_FREQ_RANGE_5G_BAND2     3
-#define WL_CHAN_FREQ_RANGE_5G_BAND3     4
-#define WL_CHAN_FREQ_RANGE_5G_4BAND     5
-
-
-/* SROM12 */
-#define WL_CHAN_FREQ_RANGE_5G_BAND4 5
-#define WL_CHAN_FREQ_RANGE_2G_40 6
-#define WL_CHAN_FREQ_RANGE_5G_BAND0_40 7
-#define WL_CHAN_FREQ_RANGE_5G_BAND1_40 8
-#define WL_CHAN_FREQ_RANGE_5G_BAND2_40 9
-#define WL_CHAN_FREQ_RANGE_5G_BAND3_40 10
-#define WL_CHAN_FREQ_RANGE_5G_BAND4_40 11
-#define WL_CHAN_FREQ_RANGE_5G_BAND0_80 12
-#define WL_CHAN_FREQ_RANGE_5G_BAND1_80 13
-#define WL_CHAN_FREQ_RANGE_5G_BAND2_80 14
-#define WL_CHAN_FREQ_RANGE_5G_BAND3_80 15
-#define WL_CHAN_FREQ_RANGE_5G_BAND4_80 16
-
-#define WL_CHAN_FREQ_RANGE_5G_5BAND	18
-#define WL_CHAN_FREQ_RANGE_5G_5BAND_40	19
-#define WL_CHAN_FREQ_RANGE_5G_5BAND_80	20
-
-#define WLC_MACMODE_DISABLED	0	/* MAC list disabled */
-#define WLC_MACMODE_DENY	1	/* Deny specified (i.e. allow unspecified) */
-#define WLC_MACMODE_ALLOW	2	/* Allow specified (i.e. deny unspecified) */
-
-/*
- * 54g modes (basic bits may still be overridden)
- *
- * GMODE_LEGACY_B			Rateset: 1b, 2b, 5.5, 11
- *					Preamble: Long
- *					Shortslot: Off
- * GMODE_AUTO				Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
- *					Extended Rateset: 6, 9, 12, 48
- *					Preamble: Long
- *					Shortslot: Auto
- * GMODE_ONLY				Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
- *					Extended Rateset: 6b, 9, 12b, 48
- *					Preamble: Short required
- *					Shortslot: Auto
- * GMODE_B_DEFERRED			Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
- *					Extended Rateset: 6, 9, 12, 48
- *					Preamble: Long
- *					Shortslot: On
- * GMODE_PERFORMANCE			Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
- *					Preamble: Short required
- *					Shortslot: On and required
- * GMODE_LRS				Rateset: 1b, 2b, 5.5b, 11b
- *					Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
- *					Preamble: Long
- *					Shortslot: Auto
- */
-#define GMODE_LEGACY_B		0
-#define GMODE_AUTO		1
-#define GMODE_ONLY		2
-#define GMODE_B_DEFERRED	3
-#define GMODE_PERFORMANCE	4
-#define GMODE_LRS		5
-#define GMODE_MAX		6
-
-/* values for PLCPHdr_override */
-#define WLC_PLCP_AUTO	-1
-#define WLC_PLCP_SHORT	0
-#define WLC_PLCP_LONG	1
-
-/* values for g_protection_override and n_protection_override */
-#define WLC_PROTECTION_AUTO		-1
-#define WLC_PROTECTION_OFF		0
-#define WLC_PROTECTION_ON		1
-#define WLC_PROTECTION_MMHDR_ONLY	2
-#define WLC_PROTECTION_CTS_ONLY		3
-
-/* values for g_protection_control and n_protection_control */
-#define WLC_PROTECTION_CTL_OFF		0
-#define WLC_PROTECTION_CTL_LOCAL	1
-#define WLC_PROTECTION_CTL_OVERLAP	2
-
-/* values for n_protection */
-#define WLC_N_PROTECTION_OFF		0
-#define WLC_N_PROTECTION_OPTIONAL	1
-#define WLC_N_PROTECTION_20IN40		2
-#define WLC_N_PROTECTION_MIXEDMODE	3
-
-/* values for n_preamble_type */
-#define WLC_N_PREAMBLE_MIXEDMODE	0
-#define WLC_N_PREAMBLE_GF		1
-#define WLC_N_PREAMBLE_GF_BRCM          2
-
-/* values for band specific 40MHz capabilities (deprecated) */
-#define WLC_N_BW_20ALL			0
-#define WLC_N_BW_40ALL			1
-#define WLC_N_BW_20IN2G_40IN5G		2
-
-#define WLC_BW_20MHZ_BIT		(1<<0)
-#define WLC_BW_40MHZ_BIT		(1<<1)
-#define WLC_BW_80MHZ_BIT		(1<<2)
-#define WLC_BW_160MHZ_BIT		(1<<3)
-#define WLC_BW_10MHZ_BIT		(1<<4)
-#define WLC_BW_5MHZ_BIT			(1<<5)
-#define WLC_BW_2P5MHZ_BIT		(1<<6)
-
-/* Bandwidth capabilities */
-#define WLC_BW_CAP_20MHZ		(WLC_BW_20MHZ_BIT)
-#define WLC_BW_CAP_40MHZ		(WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
-#define WLC_BW_CAP_80MHZ		(WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
-#define WLC_BW_CAP_160MHZ		(WLC_BW_160MHZ_BIT|WLC_BW_80MHZ_BIT| \
-	WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
-#define WLC_BW_CAP_2P5MHZ		(WLC_BW_2P5MHZ_BIT)
-#define WLC_BW_CAP_5MHZ			(WLC_BW_5MHZ_BIT)
-#define WLC_BW_CAP_10MHZ		(WLC_BW_10MHZ_BIT)
-#define WLC_BW_CAP_UNRESTRICTED		0xFF
-
-#define WL_BW_CAP_20MHZ(bw_cap)	(((bw_cap) & WLC_BW_20MHZ_BIT) ? TRUE : FALSE)
-#define WL_BW_CAP_40MHZ(bw_cap)	(((bw_cap) & WLC_BW_40MHZ_BIT) ? TRUE : FALSE)
-#define WL_BW_CAP_80MHZ(bw_cap)	(((bw_cap) & WLC_BW_80MHZ_BIT) ? TRUE : FALSE)
-#define WL_BW_CAP_160MHZ(bw_cap)(((bw_cap) & WLC_BW_160MHZ_BIT) ? TRUE : FALSE)
-#define WL_BW_CAP_2P5MHZ(bw_cap)(((bw_cap) & WLC_BW_2P5MHZ_BIT) ? TRUE : FALSE)
-#define WL_BW_CAP_5MHZ(bw_cap)	(((bw_cap) & WLC_BW_5MHZ_BIT) ? TRUE : FALSE)
-#define WL_BW_CAP_10MHZ(bw_cap)	(((bw_cap) & WLC_BW_10MHZ_BIT) ? TRUE : FALSE)
-
-/* values to force tx/rx chain */
-#define WLC_N_TXRX_CHAIN0		0
-#define WLC_N_TXRX_CHAIN1		1
-
-/* bitflags for SGI support (sgi_rx iovar) */
-#define WLC_N_SGI_20			0x01
-#define WLC_N_SGI_40			0x02
-#define WLC_VHT_SGI_80			0x04
-
-/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */
-#define WLC_SGI_ALL				0x02
-
-#define LISTEN_INTERVAL			10
-/* interference mitigation options */
-#define	INTERFERE_OVRRIDE_OFF	-1	/* interference override off */
-#define	INTERFERE_NONE	0	/* off */
-#define	NON_WLAN	1	/* foreign/non 802.11 interference, no auto detect */
-#define	WLAN_MANUAL	2	/* ACI: no auto detection */
-#define	WLAN_AUTO	3	/* ACI: auto detect */
-#define	WLAN_AUTO_W_NOISE	4	/* ACI: auto - detect and non 802.11 interference */
-#define AUTO_ACTIVE	(1 << 7) /* Auto is currently active */
-
-/* interfernece mode bit-masks (ACPHY) */
-#define ACPHY_ACI_GLITCHBASED_DESENSE 1   /* bit 0 */
-#define ACPHY_ACI_HWACI_PKTGAINLMT 2      /* bit 1 */
-#define ACPHY_ACI_W2NB_PKTGAINLMT 4       /* bit 2 */
-#define ACPHY_ACI_PREEMPTION 8            /* bit 3 */
-#define ACPHY_HWACI_MITIGATION 16            /* bit 4 */
-#define ACPHY_ACI_MAX_MODE 31
-
-/* AP environment */
-#define AP_ENV_DETECT_NOT_USED		0 /* We aren't using AP environment detection */
-#define AP_ENV_DENSE			1 /* "Corporate" or other AP dense environment */
-#define AP_ENV_SPARSE			2 /* "Home" or other sparse environment */
-#define AP_ENV_INDETERMINATE		3 /* AP environment hasn't been identified */
-
-#define TRIGGER_NOW				0
-#define TRIGGER_CRS				0x01
-#define TRIGGER_CRSDEASSERT			0x02
-#define TRIGGER_GOODFCS				0x04
-#define TRIGGER_BADFCS				0x08
-#define TRIGGER_BADPLCP				0x10
-#define TRIGGER_CRSGLITCH			0x20
-
-#define	WL_SAMPLEDATA_HEADER_TYPE	1
-#define WL_SAMPLEDATA_HEADER_SIZE	80	/* sample collect header size (bytes) */
-#define	WL_SAMPLEDATA_TYPE		2
-#define	WL_SAMPLEDATA_SEQ		0xff	/* sequence # */
-#define	WL_SAMPLEDATA_MORE_DATA		0x100	/* more data mask */
-
-/* WL_OTA START */
-#define WL_OTA_ARG_PARSE_BLK_SIZE	1200
-#define WL_OTA_TEST_MAX_NUM_RATE	30
-#define WL_OTA_TEST_MAX_NUM_SEQ		100
-#define WL_OTA_TEST_MAX_NUM_RSSI	85
-
-#define WL_THRESHOLD_LO_BAND	70	/* range from 5250MHz - 5350MHz */
-
-/* radar iovar SET defines */
-#define WL_RADAR_DETECTOR_OFF		0	/* radar detector off */
-#define WL_RADAR_DETECTOR_ON		1	/* radar detector on */
-#define WL_RADAR_SIMULATED		2	/* force radar detector to declare
-						 * detection once
-						 */
-#define WL_RADAR_SIMULATED_SC		3	/* force radar detector to declare
-						 * detection once on scan core
-						 * if available and active
-						 */
-#define WL_RSSI_ANT_VERSION	1	/* current version of wl_rssi_ant_t */
-#define WL_ANT_RX_MAX		2	/* max 2 receive antennas */
-#define WL_ANT_HT_RX_MAX	4	/* max 4 receive antennas/cores */
-#define WL_ANT_IDX_1		0	/* antenna index 1 */
-#define WL_ANT_IDX_2		1	/* antenna index 2 */
-
-#ifndef WL_RSSI_ANT_MAX
-#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
-#elif WL_RSSI_ANT_MAX != 4
-#error "WL_RSSI_ANT_MAX does not match"
-#endif
-
-/* dfs_status iovar-related defines */
-
-/* cac - channel availability check,
- * ism - in-service monitoring
- * csa - channel switching announcement
- */
-
-/* cac state values */
-#define WL_DFS_CACSTATE_IDLE		0	/* state for operating in non-radar channel */
-#define	WL_DFS_CACSTATE_PREISM_CAC	1	/* CAC in progress */
-#define WL_DFS_CACSTATE_ISM		2	/* ISM in progress */
-#define WL_DFS_CACSTATE_CSA		3	/* csa */
-#define WL_DFS_CACSTATE_POSTISM_CAC	4	/* ISM CAC */
-#define WL_DFS_CACSTATE_PREISM_OOC	5	/* PREISM OOC */
-#define WL_DFS_CACSTATE_POSTISM_OOC	6	/* POSTISM OOC */
-#define WL_DFS_CACSTATES		7	/* this many states exist */
-
-/* Defines used with channel_bandwidth for curpower */
-#define WL_BW_20MHZ		0
-#define WL_BW_40MHZ		1
-#define WL_BW_80MHZ		2
-#define WL_BW_160MHZ		3
-#define WL_BW_8080MHZ		4
-#define WL_BW_2P5MHZ		5
-#define WL_BW_5MHZ		6
-#define WL_BW_10MHZ		7
-
-/* tx_power_t.flags bits */
-#define WL_TX_POWER_F_ENABLED	1
-#define WL_TX_POWER_F_HW		2
-#define WL_TX_POWER_F_MIMO		4
-#define WL_TX_POWER_F_SISO		8
-#define WL_TX_POWER_F_HT		0x10
-#define WL_TX_POWER_F_VHT		0x20
-#define WL_TX_POWER_F_OPENLOOP		0x40
-#define WL_TX_POWER_F_PROP11NRATES	0x80
-
-/* Message levels */
-#define WL_ERROR_VAL		0x00000001
-#define WL_TRACE_VAL		0x00000002
-#define WL_PRHDRS_VAL		0x00000004
-#define WL_PRPKT_VAL		0x00000008
-#define WL_INFORM_VAL		0x00000010
-#define WL_TMP_VAL		0x00000020
-#define WL_OID_VAL		0x00000040
-#define WL_RATE_VAL		0x00000080
-#define WL_ASSOC_VAL		0x00000100
-#define WL_PRUSR_VAL		0x00000200
-#define WL_PS_VAL		0x00000400
-#define WL_TXPWR_VAL		0x00000000	/* retired in TOT on 6/10/2009 */
-#define WL_MODE_SWITCH_VAL	0x00000800 /* Using retired TXPWR val */
-#define WL_PORT_VAL		0x00001000
-#define WL_DUAL_VAL		0x00002000
-#define WL_WSEC_VAL		0x00004000
-#define WL_WSEC_DUMP_VAL	0x00008000
-#define WL_LOG_VAL		0x00010000
-#define WL_NRSSI_VAL		0x00000000	/* retired in TOT on 6/10/2009 */
-#define WL_BCNTRIM_VAL		0x00020000	/* Using retired NRSSI VAL */
-#define WL_LOFT_VAL		0x00000000	/* retired in TOT on 6/10/2009 */
-#define WL_PFN_VAL		0x00040000 /* Using retired LOFT_VAL */
-#define WL_REGULATORY_VAL	0x00080000
-#define WL_TAF_VAL		0x00100000
-#define WL_RADAR_VAL		0x00000000	/* retired in TOT on 6/10/2009 */
-#define WL_WDI_VAL		0x00200000	/* Using retired WL_RADAR_VAL VAL */
-#define WL_MPC_VAL		0x00400000
-#define WL_APSTA_VAL		0x00800000
-#define WL_DFS_VAL		0x01000000
-#define WL_BA_VAL		0x00000000	/* retired in TOT on 6/14/2010 */
-#define WL_MUMIMO_VAL		0x02000000      /* Using retired WL_BA_VAL */
-#define WL_ACI_VAL		0x04000000
-#define WL_PRMAC_VAL		0x04000000
-#define WL_MBSS_VAL		0x04000000
-#define WL_CAC_VAL		0x08000000
-#define WL_AMSDU_VAL		0x10000000
-#define WL_AMPDU_VAL		0x20000000
-#define WL_FFPLD_VAL		0x40000000
-
-/* wl_msg_level is full. For new bits take the next one and AND with
- * wl_msg_level2 in wl_dbg.h
- */
-#define WL_DPT_VAL		0x00000001
-/* re-using WL_DPT_VAL */
-#define WL_MESH_VAL		0x00000001
-#define WL_SCAN_VAL		0x00000002
-#define WL_WOWL_VAL		0x00000004
-#define WL_COEX_VAL		0x00000008
-#define WL_RTDC_VAL		0x00000010
-#define WL_PROTO_VAL		0x00000020
-#define WL_BTA_VAL		0x00000040
-#define WL_CHANINT_VAL		0x00000080
-#define WL_WMF_VAL		0x00000100
-#define WL_P2P_VAL		0x00000200
-#define WL_ITFR_VAL		0x00000400
-#define WL_MCHAN_VAL		0x00000800
-#define WL_TDLS_VAL		0x00001000
-#define WL_MCNX_VAL		0x00002000
-#define WL_PROT_VAL		0x00004000
-#define WL_PSTA_VAL		0x00008000
-#define WL_TSO_VAL		0x00010000
-#define WL_TRF_MGMT_VAL		0x00020000
-#define WL_LPC_VAL	        0x00040000
-#define WL_L2FILTER_VAL		0x00080000
-#define WL_TXBF_VAL		0x00100000
-#define WL_P2PO_VAL		0x00200000
-#define WL_TBTT_VAL		0x00400000
-#define WL_FBT_VAL		0x00800000
-#define WL_MQ_VAL		0x01000000
-
-/* This level is currently used in Phoenix2 only */
-#define WL_SRSCAN_VAL		0x02000000
-
-#define WL_WNM_VAL		0x04000000
-#define WL_PWRSEL_VAL		0x10000000
-#define WL_NET_DETECT_VAL	0x20000000
-#define WL_PCIE_VAL		0x40000000
-#define WL_PMDUR_VAL	0x80000000
-
-
-/* use top-bit for WL_TIME_STAMP_VAL because this is a modifier
- * rather than a message-type of its own
- */
-#define WL_TIMESTAMP_VAL        0x80000000
-
-/* max # of leds supported by GPIO (gpio pin# == led index#) */
-#define	WL_LED_NUMGPIO		32	/* gpio 0-31 */
-
-/* led per-pin behaviors */
-#define	WL_LED_OFF		0		/* always off */
-#define	WL_LED_ON		1		/* always on */
-#define	WL_LED_ACTIVITY		2		/* activity */
-#define	WL_LED_RADIO		3		/* radio enabled */
-#define	WL_LED_ARADIO		4		/* 5  Ghz radio enabled */
-#define	WL_LED_BRADIO		5		/* 2.4Ghz radio enabled */
-#define	WL_LED_BGMODE		6		/* on if gmode, off if bmode */
-#define	WL_LED_WI1		7
-#define	WL_LED_WI2		8
-#define	WL_LED_WI3		9
-#define	WL_LED_ASSOC		10		/* associated state indicator */
-#define	WL_LED_INACTIVE		11		/* null behavior (clears default behavior) */
-#define	WL_LED_ASSOCACT		12		/* on when associated; blink fast for activity */
-#define WL_LED_WI4		13
-#define WL_LED_WI5		14
-#define	WL_LED_BLINKSLOW	15		/* blink slow */
-#define	WL_LED_BLINKMED		16		/* blink med */
-#define	WL_LED_BLINKFAST	17		/* blink fast */
-#define	WL_LED_BLINKCUSTOM	18		/* blink custom */
-#define	WL_LED_BLINKPERIODIC	19		/* blink periodic (custom 1000ms / off 400ms) */
-#define WL_LED_ASSOC_WITH_SEC	20		/* when connected with security */
-						/* keep on for 300 sec */
-#define WL_LED_START_OFF	21		/* off upon boot, could be turned on later */
-#define WL_LED_WI6		22
-#define WL_LED_WI7		23
-#define WL_LED_WI8		24
-#define	WL_LED_NUMBEHAVIOR	25
-
-/* led behavior numeric value format */
-#define	WL_LED_BEH_MASK		0x3f		/* behavior mask */
-#define	WL_LED_PMU_OVERRIDE	0x40		/* need to set PMU Override bit for the GPIO */
-#define	WL_LED_AL_MASK		0x80		/* activelow (polarity) bit */
-
-/* number of bytes needed to define a proper bit mask for MAC event reporting */
-#define BCMIO_ROUNDUP(x, y)	((((x) + ((y) - 1)) / (y)) * (y))
-#define BCMIO_NBBY		8
-#define WL_EVENTING_MASK_LEN	16
-
-
-/* join preference types */
-#define WL_JOIN_PREF_RSSI	1	/* by RSSI */
-#define WL_JOIN_PREF_WPA	2	/* by akm and ciphers */
-#define WL_JOIN_PREF_BAND	3	/* by 802.11 band */
-#define WL_JOIN_PREF_RSSI_DELTA	4	/* by 802.11 band only if RSSI delta condition matches */
-#define WL_JOIN_PREF_TRANS_PREF	5	/* defined by requesting AP */
-
-/* band preference */
-#define WLJP_BAND_ASSOC_PREF	255	/* use what WLC_SET_ASSOC_PREFER ioctl specifies */
-
-/* any multicast cipher suite */
-#define WL_WPA_ACP_MCS_ANY	"\x00\x00\x00\x00"
-
-/* 802.11h measurement types */
-#define WLC_MEASURE_TPC			1
-#define WLC_MEASURE_CHANNEL_BASIC	2
-#define WLC_MEASURE_CHANNEL_CCA		3
-#define WLC_MEASURE_CHANNEL_RPI		4
-
-/* regulatory enforcement levels */
-#define SPECT_MNGMT_OFF			0		/* both 11h and 11d disabled */
-#define SPECT_MNGMT_LOOSE_11H		1		/* allow non-11h APs in scan lists */
-#define SPECT_MNGMT_STRICT_11H		2		/* prune out non-11h APs from scan list */
-#define SPECT_MNGMT_STRICT_11D		3		/* switch to 802.11D mode */
-/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE
- * adoption is done regardless of capability spectrum_management
- */
-#define SPECT_MNGMT_LOOSE_11H_D		4		/* operation defined above */
-
-#define WL_CHAN_VALID_HW	(1 << 0)	/* valid with current HW */
-#define WL_CHAN_VALID_SW	(1 << 1)	/* valid with current country setting */
-#define WL_CHAN_BAND_5G		(1 << 2)	/* 5GHz-band channel */
-#define WL_CHAN_RADAR		(1 << 3)	/* radar sensitive  channel */
-#define WL_CHAN_INACTIVE	(1 << 4)	/* temporarily inactive due to radar */
-#define WL_CHAN_PASSIVE		(1 << 5)	/* channel is in passive mode */
-#define WL_CHAN_RESTRICTED	(1 << 6)	/* restricted use channel */
-
-/* BTC mode used by "btc_mode" iovar */
-#define	WL_BTC_DISABLE		0	/* disable BT coexistence */
-#define WL_BTC_FULLTDM      1	/* full TDM COEX */
-#define WL_BTC_ENABLE       1	/* full TDM COEX to maintain backward compatiblity */
-#define WL_BTC_PREMPT      2    /* full TDM COEX with preemption */
-#define WL_BTC_LITE        3	/* light weight coex for large isolation platform */
-#define WL_BTC_PARALLEL		4   /* BT and WLAN run in parallel with separate antenna  */
-#define WL_BTC_HYBRID		5   /* hybrid coex, only ack is allowed to transmit in BT slot */
-#define WL_BTC_DEFAULT		8	/* set the default mode for the device */
-#define WL_INF_BTC_DISABLE      0
-#define WL_INF_BTC_ENABLE       1
-#define WL_INF_BTC_AUTO         3
-
-/* BTC wire used by "btc_wire" iovar */
-#define	WL_BTC_DEFWIRE		0	/* use default wire setting */
-#define WL_BTC_2WIRE		2	/* use 2-wire BTC */
-#define WL_BTC_3WIRE		3	/* use 3-wire BTC */
-#define WL_BTC_4WIRE		4	/* use 4-wire BTC */
-
-/* BTC flags: BTC configuration that can be set by host */
-#define WL_BTC_FLAG_PREMPT               (1 << 0)
-#define WL_BTC_FLAG_BT_DEF               (1 << 1)
-#define WL_BTC_FLAG_ACTIVE_PROT          (1 << 2)
-#define WL_BTC_FLAG_SIM_RSP              (1 << 3)
-#define WL_BTC_FLAG_PS_PROTECT           (1 << 4)
-#define WL_BTC_FLAG_SIM_TX_LP	         (1 << 5)
-#define WL_BTC_FLAG_ECI                  (1 << 6)
-#define WL_BTC_FLAG_LIGHT                (1 << 7)
-#define WL_BTC_FLAG_PARALLEL             (1 << 8)
-
-/* maximum channels returned by the get valid channels iovar */
-#define WL_NUMCHANNELS		64
-
-/* max number of chanspecs (used by the iovar to calc. buf space) */
-#ifdef WL11AC_80P80
-#define WL_NUMCHANSPECS 206
-#else
-#define WL_NUMCHANSPECS 110
-#endif
-
-/* WDS link local endpoint WPA role */
-#define WL_WDS_WPA_ROLE_AUTH	0	/* authenticator */
-#define WL_WDS_WPA_ROLE_SUP	1	/* supplicant */
-#define WL_WDS_WPA_ROLE_AUTO	255	/* auto, based on mac addr value */
-
-/* Base offset values */
-#define WL_PKT_FILTER_BASE_PKT   0
-#define WL_PKT_FILTER_BASE_END   1
-#define WL_PKT_FILTER_BASE_D11_H 2 /* May be removed */
-#define WL_PKT_FILTER_BASE_D11_D 3 /* May be removed */
-#define WL_PKT_FILTER_BASE_ETH_H 4
-#define WL_PKT_FILTER_BASE_ETH_D 5
-#define WL_PKT_FILTER_BASE_ARP_H 6
-#define WL_PKT_FILTER_BASE_ARP_D 7 /* May be removed */
-#define WL_PKT_FILTER_BASE_IP4_H 8
-#define WL_PKT_FILTER_BASE_IP4_D 9
-#define WL_PKT_FILTER_BASE_IP6_H 10
-#define WL_PKT_FILTER_BASE_IP6_D 11
-#define WL_PKT_FILTER_BASE_TCP_H 12
-#define WL_PKT_FILTER_BASE_TCP_D 13 /* May be removed */
-#define WL_PKT_FILTER_BASE_UDP_H 14
-#define WL_PKT_FILTER_BASE_UDP_D 15
-#define WL_PKT_FILTER_BASE_IP6_P 16
-#define WL_PKT_FILTER_BASE_COUNT 17 /* May be removed */
-
-/* String mapping for bases that may be used by applications or debug */
-#define WL_PKT_FILTER_BASE_NAMES \
-	{ "START", WL_PKT_FILTER_BASE_PKT },   \
-	{ "END",   WL_PKT_FILTER_BASE_END },   \
-	{ "ETH_H", WL_PKT_FILTER_BASE_ETH_H }, \
-	{ "ETH_D", WL_PKT_FILTER_BASE_ETH_D }, \
-	{ "D11_H", WL_PKT_FILTER_BASE_D11_H }, \
-	{ "D11_D", WL_PKT_FILTER_BASE_D11_D }, \
-	{ "ARP_H", WL_PKT_FILTER_BASE_ARP_H }, \
-	{ "IP4_H", WL_PKT_FILTER_BASE_IP4_H }, \
-	{ "IP4_D", WL_PKT_FILTER_BASE_IP4_D }, \
-	{ "IP6_H", WL_PKT_FILTER_BASE_IP6_H }, \
-	{ "IP6_D", WL_PKT_FILTER_BASE_IP6_D }, \
-	{ "IP6_P", WL_PKT_FILTER_BASE_IP6_P }, \
-	{ "TCP_H", WL_PKT_FILTER_BASE_TCP_H }, \
-	{ "TCP_D", WL_PKT_FILTER_BASE_TCP_D }, \
-	{ "UDP_H", WL_PKT_FILTER_BASE_UDP_H }, \
-	{ "UDP_D", WL_PKT_FILTER_BASE_UDP_D }
-
-/* Flags for a pattern list element */
-#define WL_PKT_FILTER_MFLAG_NEG 0x0001
-
-/*
- * Packet engine interface
- */
-
-#define WL_PKTENG_PER_TX_START			0x01
-#define WL_PKTENG_PER_TX_STOP			0x02
-#define WL_PKTENG_PER_RX_START			0x04
-#define WL_PKTENG_PER_RX_WITH_ACK_START		0x05
-#define WL_PKTENG_PER_TX_WITH_ACK_START		0x06
-#define WL_PKTENG_PER_RX_STOP			0x08
-#define WL_PKTENG_PER_MASK			0xff
-
-#define WL_PKTENG_SYNCHRONOUS			0x100	/* synchronous flag */
-#define WL_PKTENG_SYNCHRONOUS_UNBLK		0x200	/* synchronous unblock flag */
-
-#define WL_PKTENG_MAXPKTSZ				16384	/* max pktsz limit for pkteng */
-
-#define NUM_80211b_RATES	4
-#define NUM_80211ag_RATES	8
-#define NUM_80211n_RATES	32
-#define NUM_80211_RATES		(NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES)
-
-/*
- * WOWL capability/override settings
- */
-#define WL_WOWL_MAGIC           (1 << 0)    /* Wakeup on Magic packet */
-#define WL_WOWL_NET             (1 << 1)    /* Wakeup on Netpattern */
-#define WL_WOWL_DIS             (1 << 2)    /* Wakeup on loss-of-link due to Disassoc/Deauth */
-#define WL_WOWL_RETR            (1 << 3)    /* Wakeup on retrograde TSF */
-#define WL_WOWL_BCN             (1 << 4)    /* Wakeup on loss of beacon */
-#define WL_WOWL_TST             (1 << 5)    /* Wakeup after test */
-#define WL_WOWL_M1              (1 << 6)    /* Wakeup after PTK refresh */
-#define WL_WOWL_EAPID           (1 << 7)    /* Wakeup after receipt of EAP-Identity Req */
-#define WL_WOWL_PME_GPIO        (1 << 8)    /* Wakeind via PME(0) or GPIO(1) */
-#define WL_WOWL_ULP_BAILOUT     (1 << 8)    /* wakeind via unknown pkt by basic ULP-offloads -
- * WL_WOWL_ULP_BAILOUT - same as WL_WOWL_PME_GPIO used only for DONGLE BUILDS and
- * not WLC_HIGH_ONLY case
- */
-#define WL_WOWL_NEEDTKIP1       (1 << 9)    /* need tkip phase 1 key to be updated by the driver */
-#define WL_WOWL_GTK_FAILURE     (1 << 10)   /* enable wakeup if GTK fails */
-#define WL_WOWL_EXTMAGPAT       (1 << 11)   /* support extended magic packets */
-#define WL_WOWL_ARPOFFLOAD      (1 << 12)   /* support ARP/NS/keepalive offloading */
-#define WL_WOWL_WPA2            (1 << 13)   /* read protocol version for EAPOL frames */
-#define WL_WOWL_KEYROT          (1 << 14)   /* If the bit is set, use key rotaton */
-#define WL_WOWL_BCAST           (1 << 15)   /* If the bit is set, frm received was bcast frame */
-#define WL_WOWL_SCANOL          (1 << 16)   /* If the bit is set, scan offload is enabled */
-#define WL_WOWL_TCPKEEP_TIME    (1 << 17)   /* Wakeup on tcpkeep alive timeout */
-#define WL_WOWL_MDNS_CONFLICT   (1 << 18)   /* Wakeup on mDNS Conflict Resolution */
-#define WL_WOWL_MDNS_SERVICE    (1 << 19)   /* Wakeup on mDNS Service Connect */
-#define WL_WOWL_TCPKEEP_DATA    (1 << 20)   /* tcp keepalive got data */
-#define WL_WOWL_FW_HALT         (1 << 21)   /* Firmware died in wowl mode */
-#define WL_WOWL_ENAB_HWRADIO    (1 << 22)   /* Enable detection of radio button changes */
-#define WL_WOWL_MIC_FAIL        (1 << 23)   /* Offloads detected MIC failure(s) */
-#define WL_WOWL_UNASSOC         (1 << 24)   /* Wakeup in Unassociated state (Net/Magic Pattern) */
-#define WL_WOWL_SECURE          (1 << 25)   /* Wakeup if received matched secured pattern */
-#define WL_WOWL_LINKDOWN        (1 << 31)   /* Link Down indication in WoWL mode */
-
-#define WL_WOWL_TCPKEEP         (1 << 20)   /* temp copy to satisfy automerger */
-#define MAGIC_PKT_MINLEN 102    /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */
-
-#define WOWL_PATTEN_TYPE_ARP	(1 << 0)	/* ARP offload Pattern */
-#define WOWL_PATTEN_TYPE_NA	(1 << 1)	/* NA offload Pattern */
-
-#define MAGIC_PKT_MINLEN	102    /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */
-#define MAGIC_PKT_NUM_MAC_ADDRS	16
-
-
-/* Overlap BSS Scan parameters default, minimum, maximum */
-#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT		20	/* unit TU */
-#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN			5	/* unit TU */
-#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX			1000	/* unit TU */
-#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT		10	/* unit TU */
-#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN			10	/* unit TU */
-#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX			1000	/* unit TU */
-#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT	300	/* unit Sec */
-#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN		10	/* unit Sec */
-#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX		900	/* unit Sec */
-#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT	5
-#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN	5
-#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX	100
-#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT	200	/* unit TU */
-#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN	200	/* unit TU */
-#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX	10000	/* unit TU */
-#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT	20	/* unit TU */
-#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN	20	/* unit TU */
-#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX	10000	/* unit TU */
-#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT	25	/* unit percent */
-#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN		0	/* unit percent */
-#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX		100	/* unit percent */
-
-#define WL_MIN_NUM_OBSS_SCAN_ARG 7	/* minimum number of arguments required for OBSS Scan */
-
-#define WL_COEX_INFO_MASK		0x07
-#define WL_COEX_INFO_REQ		0x01
-#define	WL_COEX_40MHZ_INTOLERANT	0x02
-#define	WL_COEX_WIDTH20			0x04
-
-#define	WLC_RSSI_INVALID	 0	/* invalid RSSI value */
-
-#define MAX_RSSI_LEVELS 8
-
-/* **** EXTLOG **** */
-#define EXTLOG_CUR_VER		0x0100
-
-#define MAX_ARGSTR_LEN		18 /* At least big enough for storing ETHER_ADDR_STR_LEN */
-
-/* log modules (bitmap) */
-#define LOG_MODULE_COMMON	0x0001
-#define LOG_MODULE_ASSOC	0x0002
-#define LOG_MODULE_EVENT	0x0004
-#define LOG_MODULE_MAX		3			/* Update when adding module */
-
-/* log levels */
-#define WL_LOG_LEVEL_DISABLE	0
-#define WL_LOG_LEVEL_ERR	1
-#define WL_LOG_LEVEL_WARN	2
-#define WL_LOG_LEVEL_INFO	3
-#define WL_LOG_LEVEL_MAX	WL_LOG_LEVEL_INFO	/* Update when adding level */
-
-/* flag */
-#define LOG_FLAG_EVENT		1
-
-/* log arg_type */
-#define LOG_ARGTYPE_NULL	0
-#define LOG_ARGTYPE_STR		1	/* %s */
-#define LOG_ARGTYPE_INT		2	/* %d */
-#define LOG_ARGTYPE_INT_STR	3	/* %d...%s */
-#define LOG_ARGTYPE_STR_INT	4	/* %s...%d */
-
-/* 802.11 Mgmt Packet flags */
-#define VNDR_IE_BEACON_FLAG	0x1
-#define VNDR_IE_PRBRSP_FLAG	0x2
-#define VNDR_IE_ASSOCRSP_FLAG	0x4
-#define VNDR_IE_AUTHRSP_FLAG	0x8
-#define VNDR_IE_PRBREQ_FLAG	0x10
-#define VNDR_IE_ASSOCREQ_FLAG	0x20
-#define VNDR_IE_IWAPID_FLAG	0x40 /* vendor IE in IW advertisement protocol ID field */
-#define VNDR_IE_CUSTOM_FLAG	0x100 /* allow custom IE id */
-
-#if defined(WLP2P)
-/* P2P Action Frames flags (spec ordered) */
-#define VNDR_IE_GONREQ_FLAG     0x001000
-#define VNDR_IE_GONRSP_FLAG     0x002000
-#define VNDR_IE_GONCFM_FLAG     0x004000
-#define VNDR_IE_INVREQ_FLAG     0x008000
-#define VNDR_IE_INVRSP_FLAG     0x010000
-#define VNDR_IE_DISREQ_FLAG     0x020000
-#define VNDR_IE_DISRSP_FLAG     0x040000
-#define VNDR_IE_PRDREQ_FLAG     0x080000
-#define VNDR_IE_PRDRSP_FLAG     0x100000
-
-#define VNDR_IE_P2PAF_SHIFT	12
-#endif /* WLP2P */
-
-/* channel interference measurement (chanim) related defines */
-
-/* chanim mode */
-#define CHANIM_DISABLE	0	/* disabled */
-#define CHANIM_DETECT	1	/* detection only */
-#define CHANIM_EXT		2	/* external state machine */
-#define CHANIM_ACT		3	/* full internal state machine, detect + act */
-#define CHANIM_MODE_MAX 4
-
-/* define for apcs reason code */
-#define APCS_INIT		0
-#define APCS_IOCTL		1
-#define APCS_CHANIM		2
-#define APCS_CSTIMER		3
-#define APCS_BTA		4
-#define APCS_TXDLY		5
-#define APCS_NONACSD		6
-#define APCS_DFS_REENTRY	7
-#define APCS_TXFAIL		8
-#define APCS_MAX		9
-
-/* number of ACS record entries */
-#define CHANIM_ACS_RECORD			10
-
-/* CHANIM */
-#define CCASTATS_TXDUR  0
-#define CCASTATS_INBSS  1
-#define CCASTATS_OBSS   2
-#define CCASTATS_NOCTG  3
-#define CCASTATS_NOPKT  4
-#define CCASTATS_DOZE   5
-#define CCASTATS_TXOP	6
-#define CCASTATS_GDTXDUR        7
-#define CCASTATS_BDTXDUR        8
-#define CCASTATS_MAX    9
-
-#define WL_CHANIM_COUNT_ALL	0xff
-#define WL_CHANIM_COUNT_ONE	0x1
-
-/* ap tpc modes */
-#define	AP_TPC_OFF		0
-#define	AP_TPC_BSS_PWR		1	/* BSS power control */
-#define AP_TPC_AP_PWR		2	/* AP power control */
-#define	AP_TPC_AP_BSS_PWR	3	/* Both AP and BSS power control */
-#define AP_TPC_MAX_LINK_MARGIN	127
-
-/* ap tpc modes */
-#define	AP_TPC_OFF		0
-#define	AP_TPC_BSS_PWR		1	/* BSS power control */
-#define AP_TPC_AP_PWR		2	/* AP power control */
-#define	AP_TPC_AP_BSS_PWR	3	/* Both AP and BSS power control */
-#define AP_TPC_MAX_LINK_MARGIN	127
-
-/* state */
-#define WL_P2P_DISC_ST_SCAN	0
-#define WL_P2P_DISC_ST_LISTEN	1
-#define WL_P2P_DISC_ST_SEARCH	2
-
-/* i/f type */
-#define WL_P2P_IF_CLIENT	0
-#define WL_P2P_IF_GO		1
-#define WL_P2P_IF_DYNBCN_GO	2
-#define WL_P2P_IF_DEV		3
-
-/* count */
-#define WL_P2P_SCHED_RSVD	0
-#define WL_P2P_SCHED_REPEAT	255	/* anything > 255 will be treated as 255 */
-
-#define WL_P2P_SCHED_FIXED_LEN		3
-
-/* schedule type */
-#define WL_P2P_SCHED_TYPE_ABS		0	/* Scheduled Absence */
-#define WL_P2P_SCHED_TYPE_REQ_ABS	1	/* Requested Absence */
-
-/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */
-#define WL_P2P_SCHED_ACTION_NONE	0	/* no action */
-#define WL_P2P_SCHED_ACTION_DOZE	1	/* doze */
-/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */
-#define WL_P2P_SCHED_ACTION_GOOFF	2	/* turn off GO beacon/prbrsp functions */
-/* schedule option - WL_P2P_SCHED_TYPE_XXX */
-#define WL_P2P_SCHED_ACTION_RESET	255	/* reset */
-
-/* schedule option - WL_P2P_SCHED_TYPE_ABS */
-#define WL_P2P_SCHED_OPTION_NORMAL	0	/* normal start/interval/duration/count */
-#define WL_P2P_SCHED_OPTION_BCNPCT	1	/* percentage of beacon interval */
-/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */
-#define WL_P2P_SCHED_OPTION_TSFOFS	2	/* normal start/internal/duration/count with
-						 * start being an offset of the 'current' TSF
-						 */
-
-/* feature flags */
-#define WL_P2P_FEAT_GO_CSA	(1 << 0)	/* GO moves with the STA using CSA method */
-#define WL_P2P_FEAT_GO_NOLEGACY	(1 << 1)	/* GO does not probe respond to non-p2p probe
-						 * requests
-						 */
-#define WL_P2P_FEAT_RESTRICT_DEV_RESP (1 << 2)	/* Restrict p2p dev interface from responding */
-
-/* n-mode support capability */
-/* 2x2 includes both 1x1 & 2x2 devices
- * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
- * control it independently
- */
-#define WL_11N_2x2			1
-#define WL_11N_3x3			3
-#define WL_11N_4x4			4
-
-/* define 11n feature disable flags */
-#define WLFEATURE_DISABLE_11N		0x00000001
-#define WLFEATURE_DISABLE_11N_STBC_TX	0x00000002
-#define WLFEATURE_DISABLE_11N_STBC_RX	0x00000004
-#define WLFEATURE_DISABLE_11N_SGI_TX	0x00000008
-#define WLFEATURE_DISABLE_11N_SGI_RX	0x00000010
-#define WLFEATURE_DISABLE_11N_AMPDU_TX	0x00000020
-#define WLFEATURE_DISABLE_11N_AMPDU_RX	0x00000040
-#define WLFEATURE_DISABLE_11N_GF	0x00000080
-
-/* Proxy STA modes */
-#define PSTA_MODE_DISABLED		0
-#define PSTA_MODE_PROXY			1
-#define PSTA_MODE_REPEATER		2
-
-/* op code in nat_cfg */
-#define NAT_OP_ENABLE		1	/* enable NAT on given interface */
-#define NAT_OP_DISABLE		2	/* disable NAT on given interface */
-#define NAT_OP_DISABLE_ALL	3	/* disable NAT on all interfaces */
-
-/* NAT state */
-#define NAT_STATE_ENABLED	1	/* NAT is enabled */
-#define NAT_STATE_DISABLED	2	/* NAT is disabled */
-
-#define CHANNEL_5G_LOW_START	36	/* 5G low (36..48) CDD enable/disable bit mask */
-#define CHANNEL_5G_MID_START	52	/* 5G mid (52..64) CDD enable/disable bit mask */
-#define CHANNEL_5G_HIGH_START	100	/* 5G high (100..140) CDD enable/disable bit mask */
-#define CHANNEL_5G_UPPER_START	149	/* 5G upper (149..161) CDD enable/disable bit mask */
-
-/* D0 Coalescing */
-#define IPV4_ARP_FILTER		0x0001
-#define IPV4_NETBT_FILTER	0x0002
-#define IPV4_LLMNR_FILTER	0x0004
-#define IPV4_SSDP_FILTER	0x0008
-#define IPV4_WSD_FILTER		0x0010
-#define IPV6_NETBT_FILTER	0x0200
-#define IPV6_LLMNR_FILTER	0x0400
-#define IPV6_SSDP_FILTER	0x0800
-#define IPV6_WSD_FILTER		0x1000
-
-/* Network Offload Engine */
-#define NWOE_OL_ENABLE		0x00000001
-
-/*
- * Traffic management structures/defines.
- */
-
-/* Traffic management bandwidth parameters */
-#define TRF_MGMT_MAX_PRIORITIES                 3
-
-#define TRF_MGMT_FLAG_ADD_DSCP                  0x0001  /* Add DSCP to IP TOS field */
-#define TRF_MGMT_FLAG_DISABLE_SHAPING           0x0002  /* Don't shape traffic */
-#define TRF_MGMT_FLAG_MANAGE_LOCAL_TRAFFIC      0x0008  /* Manage traffic over our local subnet */
-#define TRF_MGMT_FLAG_FILTER_ON_MACADDR         0x0010  /* filter on MAC address */
-#define TRF_MGMT_FLAG_NO_RX                     0x0020  /* do not apply fiters to rx packets */
-
-#define TRF_FILTER_MAC_ADDR              0x0001 /* L2 filter use dst mac address for filtering */
-#define TRF_FILTER_IP_ADDR               0x0002 /* L3 filter use ip ddress for filtering */
-#define TRF_FILTER_L4                    0x0004 /* L4 filter use tcp/udp for filtering */
-#define TRF_FILTER_DWM                   0x0008 /* L3 filter use DSCP for filtering */
-#define TRF_FILTER_FAVORED               0x0010 /* Tag the packet FAVORED */
-
-/* WNM/NPS subfeatures mask */
-#define WL_WNM_BSSTRANS		0x00000001
-#define WL_WNM_PROXYARP		0x00000002
-#define WL_WNM_MAXIDLE		0x00000004
-#define WL_WNM_TIMBC		0x00000008
-#define WL_WNM_TFS		0x00000010
-#define WL_WNM_SLEEP		0x00000020
-#define WL_WNM_DMS		0x00000040
-#define WL_WNM_FMS		0x00000080
-#define WL_WNM_NOTIF		0x00000100
-#define WL_WNM_MAX		0x00000200
-
-#ifdef WLWNM_BRCM
-#define BRCM_WNM_FEATURE_SET\
-					(WL_WNM_PROXYARP | \
-					WL_WNM_SLEEP | \
-					WL_WNM_FMS | \
-					WL_WNM_TFS | \
-					WL_WNM_TIMBC | \
-					WL_WNM_BSSTRANS | \
-					WL_WNM_DMS | \
-					WL_WNM_NOTIF | \
-					0)
-#endif /* WLWNM_BRCM */
-
-#ifndef ETHER_MAX_DATA
-#define ETHER_MAX_DATA	1500
-#endif /* ETHER_MAX_DATA */
-
-/* Different discovery modes for dpt */
-#define	DPT_DISCOVERY_MANUAL	0x01	/* manual discovery mode */
-#define	DPT_DISCOVERY_AUTO	0x02	/* auto discovery mode */
-#define	DPT_DISCOVERY_SCAN	0x04	/* scan-based discovery mode */
-
-/* different path selection values */
-#define DPT_PATHSEL_AUTO	0	/* auto mode for path selection */
-#define DPT_PATHSEL_DIRECT	1	/* always use direct DPT path */
-#define DPT_PATHSEL_APPATH	2	/* always use AP path */
-
-/* different ops for deny list */
-#define DPT_DENY_LIST_ADD	1	/* add to dpt deny list */
-#define DPT_DENY_LIST_REMOVE	2	/* remove from dpt deny list */
-
-/* different ops for manual end point */
-#define DPT_MANUAL_EP_CREATE	1	/* create manual dpt endpoint */
-#define DPT_MANUAL_EP_MODIFY	2	/* modify manual dpt endpoint */
-#define DPT_MANUAL_EP_DELETE	3	/* delete manual dpt endpoint */
-
-/* flags to indicate DPT status */
-#define	DPT_STATUS_ACTIVE	0x01	/* link active (though may be suspended) */
-#define	DPT_STATUS_AES		0x02	/* link secured through AES encryption */
-#define	DPT_STATUS_FAILED	0x04	/* DPT link failed */
-
-#ifdef WLTDLS
-/* different ops for manual end point */
-#define TDLS_MANUAL_EP_CREATE	1	/* create manual dpt endpoint */
-#define TDLS_MANUAL_EP_MODIFY	2	/* modify manual dpt endpoint */
-#define TDLS_MANUAL_EP_DELETE	3	/* delete manual dpt endpoint */
-#define TDLS_MANUAL_EP_PM		4	/*  put dpt endpoint in PM mode */
-#define TDLS_MANUAL_EP_WAKE		5	/* wake up dpt endpoint from PM */
-#define TDLS_MANUAL_EP_DISCOVERY	6	/* discover if endpoint is TDLS capable */
-#define TDLS_MANUAL_EP_CHSW		7	/* channel switch */
-#define TDLS_MANUAL_EP_WFD_TPQ	8	/* WiFi-Display Tunneled Probe reQuest */
-
-/* modes */
-#define TDLS_WFD_IE_TX			0
-#define TDLS_WFD_IE_RX			1
-#define TDLS_WFD_PROBE_IE_TX	2
-#define TDLS_WFD_PROBE_IE_RX	3
-#endif /* WLTDLS */
-
-/* define for flag */
-#define TSPEC_PENDING		0	/* TSPEC pending */
-#define TSPEC_ACCEPTED		1	/* TSPEC accepted */
-#define TSPEC_REJECTED		2	/* TSPEC rejected */
-#define TSPEC_UNKNOWN		3	/* TSPEC unknown */
-#define TSPEC_STATUS_MASK	7	/* TSPEC status mask */
-
-
-/* Software feature flag defines used by wlfeatureflag */
-#ifdef WLAFTERBURNER
-#define WL_SWFL_ABBFL       0x0001 /* Allow Afterburner on systems w/o hardware BFL */
-#define WL_SWFL_ABENCORE    0x0002 /* Allow AB on non-4318E chips */
-#endif /* WLAFTERBURNER */
-#define WL_SWFL_NOHWRADIO	0x0004
-#define WL_SWFL_FLOWCONTROL     0x0008 /* Enable backpressure to OS stack */
-#define WL_SWFL_WLBSSSORT	0x0010 /* Per-port supports sorting of BSS */
-
-#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */
-
-#define CSA_BROADCAST_ACTION_FRAME	0	/* csa broadcast action frame */
-#define CSA_UNICAST_ACTION_FRAME	  1 /* csa unicast action frame */
-
-/* Roaming trigger definitions for WLC_SET_ROAM_TRIGGER.
- *
- * (-100 < value < 0)   value is used directly as a roaming trigger in dBm
- * (0 <= value) value specifies a logical roaming trigger level from
- *                      the list below
- *
- * WLC_GET_ROAM_TRIGGER always returns roaming trigger value in dBm, never
- * the logical roam trigger value.
- */
-#define WLC_ROAM_TRIGGER_DEFAULT	0 /* default roaming trigger */
-#define WLC_ROAM_TRIGGER_BANDWIDTH	1 /* optimize for bandwidth roaming trigger */
-#define WLC_ROAM_TRIGGER_DISTANCE	2 /* optimize for distance roaming trigger */
-#define WLC_ROAM_TRIGGER_AUTO		3 /* auto-detect environment */
-#define WLC_ROAM_TRIGGER_MAX_VALUE	3 /* max. valid value */
-
-#define WLC_ROAM_NEVER_ROAM_TRIGGER	(-100) /* Avoid Roaming by setting a large value */
-
-/* Preferred Network Offload (PNO, formerly PFN) defines */
-#define WPA_AUTH_PFN_ANY	0xffffffff	/* for PFN, match only ssid */
-
-#define SORT_CRITERIA_BIT		0
-#define AUTO_NET_SWITCH_BIT		1
-#define ENABLE_BKGRD_SCAN_BIT		2
-#define IMMEDIATE_SCAN_BIT		3
-#define	AUTO_CONNECT_BIT		4
-#define	ENABLE_BD_SCAN_BIT		5
-#define ENABLE_ADAPTSCAN_BIT		6
-#define IMMEDIATE_EVENT_BIT		8
-#define SUPPRESS_SSID_BIT		9
-#define ENABLE_NET_OFFLOAD_BIT		10
-/* report found/lost events for SSID and BSSID networks seperately */
-#define REPORT_SEPERATELY_BIT		11
-#define BESTN_BSSID_ONLY_BIT		12
-
-#define SORT_CRITERIA_MASK		0x0001
-#define AUTO_NET_SWITCH_MASK		0x0002
-#define ENABLE_BKGRD_SCAN_MASK		0x0004
-#define IMMEDIATE_SCAN_MASK		0x0008
-#define	AUTO_CONNECT_MASK		0x0010
-
-#define ENABLE_BD_SCAN_MASK		0x0020
-#define ENABLE_ADAPTSCAN_MASK		0x00c0
-#define IMMEDIATE_EVENT_MASK		0x0100
-#define SUPPRESS_SSID_MASK		0x0200
-#define ENABLE_NET_OFFLOAD_MASK		0x0400
-/* report found/lost events for SSID and BSSID networks seperately */
-#define REPORT_SEPERATELY_MASK		0x0800
-#define BESTN_BSSID_ONLY_MASK		0x1000
-
-#define PFN_VERSION			2
-#define PFN_SCANRESULT_VERSION		1
-#define MAX_PFN_LIST_COUNT		16
-
-#define PFN_COMPLETE			1
-#define PFN_INCOMPLETE			0
-
-#define DEFAULT_BESTN			2
-#define DEFAULT_MSCAN			0
-#define DEFAULT_REPEAT			10
-#define DEFAULT_EXP				2
-
-#define PFN_PARTIAL_SCAN_BIT		0
-#define PFN_PARTIAL_SCAN_MASK		1
-
-#define WL_PFN_SUPPRESSFOUND_MASK	0x08
-#define WL_PFN_SUPPRESSLOST_MASK	0x10
-#define WL_PFN_RSSI_MASK		0xff00
-#define WL_PFN_RSSI_SHIFT		8
-
-#define WL_PFN_REPORT_ALLNET    0
-#define WL_PFN_REPORT_SSIDNET   1
-#define WL_PFN_REPORT_BSSIDNET  2
-
-#define WL_PFN_CFG_FLAGS_PROHIBITED	0x00000001	/* Accept and use prohibited channels */
-#define WL_PFN_CFG_FLAGS_HISTORY_OFF	0x00000002	/* Scan history suppressed */
-
-#define WL_PFN_HIDDEN_BIT		2
-#define PNO_SCAN_MAX_FW			508*1000	/* max time scan time in msec */
-#define PNO_SCAN_MAX_FW_SEC		PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */
-#define PNO_SCAN_MIN_FW_SEC		10			/* min time scan time in SEC */
-#define WL_PFN_HIDDEN_MASK		0x4
-
-#ifndef BESTN_MAX
-#define BESTN_MAX			8
-#endif
-
-#ifndef MSCAN_MAX
-#define MSCAN_MAX			32
-#endif
-
-/* TCP Checksum Offload error injection for testing */
-#define TOE_ERRTEST_TX_CSUM	0x00000001
-#define TOE_ERRTEST_RX_CSUM	0x00000002
-#define TOE_ERRTEST_RX_CSUM2	0x00000004
-
-/* ARP Offload feature flags for arp_ol iovar */
-#define ARP_OL_AGENT		0x00000001
-#define ARP_OL_SNOOP		0x00000002
-#define ARP_OL_HOST_AUTO_REPLY	0x00000004
-#define ARP_OL_PEER_AUTO_REPLY	0x00000008
-
-/* ARP Offload error injection */
-#define ARP_ERRTEST_REPLY_PEER	0x1
-#define ARP_ERRTEST_REPLY_HOST	0x2
-
-#define ARP_MULTIHOMING_MAX	8	/* Maximum local host IP addresses */
-#define ND_MULTIHOMING_MAX 10	/* Maximum local host IP addresses */
-#define ND_REQUEST_MAX		5	/* Max set of offload params */
-
-
-/* AOAC wake event flag */
-#define WAKE_EVENT_NLO_DISCOVERY_BIT		1
-#define WAKE_EVENT_AP_ASSOCIATION_LOST_BIT	2
-#define WAKE_EVENT_GTK_HANDSHAKE_ERROR_BIT 4
-#define WAKE_EVENT_4WAY_HANDSHAKE_REQUEST_BIT 8
-#define WAKE_EVENT_NET_PACKET_BIT 0x10
-
-
-#define MAX_NUM_WOL_PATTERN	22 /* LOGO requirements min 22 */
-
-
-/* Packet filter operation mode */
-/* True: 1; False: 0 */
-#define PKT_FILTER_MODE_FORWARD_ON_MATCH		1
-/* Enable and disable pkt_filter as a whole */
-#define PKT_FILTER_MODE_DISABLE					2
-/* Cache first matched rx pkt(be queried by host later) */
-#define PKT_FILTER_MODE_PKT_CACHE_ON_MATCH		4
-/* If pkt_filter is enabled and no filter is set, don't forward anything */
-#define PKT_FILTER_MODE_PKT_FORWARD_OFF_DEFAULT 8
-
-#ifdef DONGLEOVERLAYS
-#define OVERLAY_IDX_MASK		0x000000ff
-#define OVERLAY_IDX_SHIFT		0
-#define OVERLAY_FLAGS_MASK		0xffffff00
-#define OVERLAY_FLAGS_SHIFT		8
-/* overlay written to device memory immediately after loading the base image */
-#define OVERLAY_FLAG_POSTLOAD	0x100
-/* defer overlay download until the device responds w/WLC_E_OVL_DOWNLOAD event */
-#define OVERLAY_FLAG_DEFER_DL	0x200
-/* overlay downloaded prior to the host going to sleep */
-#define OVERLAY_FLAG_PRESLEEP	0x400
-#define OVERLAY_DOWNLOAD_CHUNKSIZE	1024
-#endif /* DONGLEOVERLAYS */
-
-/* reuse two number in the sc/rc space */
-#define	SMFS_CODE_MALFORMED 0xFFFE
-#define SMFS_CODE_IGNORED	0xFFFD
-
-/* RFAWARE def */
-#define BCM_ACTION_RFAWARE		0x77
-#define BCM_ACTION_RFAWARE_DCS  0x01
-
-/* DCS reason code define */
-#define BCM_DCS_IOVAR		0x1
-#define BCM_DCS_UNKNOWN		0xFF
-
-
-#ifdef PROP_TXSTATUS
-/* Bit definitions for tlv iovar */
-/*
- * enable RSSI signals:
- * WLFC_CTL_TYPE_RSSI
- */
-#define WLFC_FLAGS_RSSI_SIGNALS			0x0001
-
-/* enable (if/mac_open, if/mac_close,, mac_add, mac_del) signals:
- *
- * WLFC_CTL_TYPE_MAC_OPEN
- * WLFC_CTL_TYPE_MAC_CLOSE
- *
- * WLFC_CTL_TYPE_INTERFACE_OPEN
- * WLFC_CTL_TYPE_INTERFACE_CLOSE
- *
- * WLFC_CTL_TYPE_MACDESC_ADD
- * WLFC_CTL_TYPE_MACDESC_DEL
- *
- */
-#define WLFC_FLAGS_XONXOFF_SIGNALS		0x0002
-
-/* enable (status, fifo_credit, mac_credit) signals
- * WLFC_CTL_TYPE_MAC_REQUEST_CREDIT
- * WLFC_CTL_TYPE_TXSTATUS
- * WLFC_CTL_TYPE_FIFO_CREDITBACK
- */
-#define WLFC_FLAGS_CREDIT_STATUS_SIGNALS	0x0004
-
-#define WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE	0x0008
-#define WLFC_FLAGS_PSQ_GENERATIONFSM_ENABLE	0x0010
-#define WLFC_FLAGS_PSQ_ZERO_BUFFER_ENABLE	0x0020
-#define WLFC_FLAGS_HOST_RXRERODER_ACTIVE	0x0040
-#define WLFC_FLAGS_PKT_STAMP_SIGNALS		0x0080
-
-#endif /* PROP_TXSTATUS */
-
-#define WL_TIMBC_STATUS_AP_UNKNOWN	255	/* AP status for internal use only */
-
-#define WL_DFRTS_LOGIC_OFF	0	/* Feature is disabled */
-#define WL_DFRTS_LOGIC_OR	1	/* OR all non-zero threshold conditions */
-#define WL_DFRTS_LOGIC_AND	2	/* AND all non-zero threshold conditions */
-
-/* Definitions for Reliable Multicast */
-#define WL_RELMCAST_MAX_CLIENT		32
-#define WL_RELMCAST_FLAG_INBLACKLIST	1
-#define WL_RELMCAST_FLAG_ACTIVEACKER	2
-#define WL_RELMCAST_FLAG_RELMCAST	4
-
-/* structures for proximity detection device role */
-#define WL_PROXD_MODE_DISABLE	0
-#define WL_PROXD_MODE_NEUTRAL	1
-#define WL_PROXD_MODE_INITIATOR	2
-#define WL_PROXD_MODE_TARGET	3
-#define WL_PROXD_RANDOM_WAKEUP	0x8000
-
-
-#ifdef NET_DETECT
-#define NET_DETECT_MAX_WAKE_DATA_SIZE	2048
-#define NET_DETECT_MAX_PROFILES		16
-#define NET_DETECT_MAX_CHANNELS		50
-#endif /* NET_DETECT */
-
-/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
-#define WL_RADIO_SW_DISABLE		(1<<0)
-#define WL_RADIO_HW_DISABLE		(1<<1)
-#define WL_RADIO_MPC_DISABLE		(1<<2)
-#define WL_RADIO_COUNTRY_DISABLE	(1<<3)	/* some countries don't support any channel */
-#define WL_RADIO_PERCORE_DISABLE	(1<<4)	/* Radio diable per core for DVT */
-
-#define	WL_SPURAVOID_OFF	0
-#define	WL_SPURAVOID_ON1	1
-#define	WL_SPURAVOID_ON2	2
-
-
-#define WL_4335_SPURAVOID_ON1	1
-#define WL_4335_SPURAVOID_ON2	2
-#define WL_4335_SPURAVOID_ON3	3
-#define WL_4335_SPURAVOID_ON4	4
-#define WL_4335_SPURAVOID_ON5	5
-#define WL_4335_SPURAVOID_ON6	6
-#define WL_4335_SPURAVOID_ON7	7
-#define WL_4335_SPURAVOID_ON8	8
-#define WL_4335_SPURAVOID_ON9	9
-
-/* Override bit for WLC_SET_TXPWR.  if set, ignore other level limits */
-#define WL_TXPWR_OVERRIDE	(1U<<31)
-#define WL_TXPWR_NEG   (1U<<30)
-
-
-/* phy types (returned by WLC_GET_PHYTPE) */
-#define	WLC_PHY_TYPE_A		0
-#define	WLC_PHY_TYPE_B		1
-#define	WLC_PHY_TYPE_G		2
-#define	WLC_PHY_TYPE_N		4
-#define	WLC_PHY_TYPE_LP		5
-#define	WLC_PHY_TYPE_SSN	6
-#define	WLC_PHY_TYPE_HT		7
-#define	WLC_PHY_TYPE_LCN	8
-#define	WLC_PHY_TYPE_LCN40	10
-#define WLC_PHY_TYPE_AC		11
-#define	WLC_PHY_TYPE_LCN20	12
-#define	WLC_PHY_TYPE_NULL	0xf
-
-/* Values for PM */
-#define PM_OFF	0
-#define PM_MAX	1
-#define PM_FAST 2
-#define PM_FORCE_OFF 3		/* use this bit to force PM off even bt is active */
-
-#define WL_WME_CNT_VERSION	1	/* current version of wl_wme_cnt_t */
-
-/* fbt_cap: FBT assoc / reassoc modes. */
-#define WLC_FBT_CAP_DRV_4WAY_AND_REASSOC  1 /* Driver 4-way handshake & reassoc (WLFBT). */
-
-/* monitor_promisc_level bits */
-#define WL_MONPROMISC_PROMISC 0x0001
-#define WL_MONPROMISC_CTRL 0x0002
-#define WL_MONPROMISC_FCS 0x0004
-
-/* TCP Checksum Offload defines */
-#define TOE_TX_CSUM_OL		0x00000001
-#define TOE_RX_CSUM_OL		0x00000002
-
-/* Wi-Fi Display Services (WFDS) */
-#define WL_P2P_SOCIAL_CHANNELS_MAX  WL_NUMCHANNELS
-#define MAX_WFDS_SEEK_SVC 4	/* Max # of wfds services to seek */
-#define MAX_WFDS_ADVERT_SVC 4	/* Max # of wfds services to advertise */
-#define MAX_WFDS_SVC_NAME_LEN 200	/* maximum service_name length */
-#define MAX_WFDS_ADV_SVC_INFO_LEN 65000	/* maximum adv service_info length */
-#define P2P_WFDS_HASH_LEN 6		/* Length of a WFDS service hash */
-#define MAX_WFDS_SEEK_SVC_INFO_LEN 255	/* maximum seek service_info req length */
-#define MAX_WFDS_SEEK_SVC_NAME_LEN 200	/* maximum service_name length */
-
-/* ap_isolate bitmaps */
-#define AP_ISOLATE_DISABLED		0x0
-#define AP_ISOLATE_SENDUP_ALL		0x01
-#define AP_ISOLATE_SENDUP_MCAST		0x02
-
-#endif /* wlioctl_defs_h */
diff --git a/drivers/net/wireless/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/bcmdhd/include/dhdioctl.h
deleted file mode 100644
index 9e79ddb..0000000
--- a/drivers/net/wireless/bcmdhd/include/dhdioctl.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Definitions for ioctls to access DHD iovars.
- * Based on wlioctl.h (for Broadcom 802.11abg driver).
- * (Moves towards generic ioctls for BCM drivers/iovars.)
- *
- * Definitions subject to change without notice.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: dhdioctl.h 585723 2015-09-11 06:26:37Z $
- */
-
-#ifndef _dhdioctl_h_
-#define	_dhdioctl_h_
-
-#include <typedefs.h>
-
-
-/* require default structure packing */
-#define BWL_DEFAULT_PACKING
-#include <packed_section_start.h>
-
-
-/* Linux network driver ioctl encoding */
-typedef struct dhd_ioctl {
-	uint cmd;	/* common ioctl definition */
-	void *buf;	/* pointer to user buffer */
-	uint len;	/* length of user buffer */
-	bool set;	/* get or set request (optional) */
-	uint used;	/* bytes read or written (optional) */
-	uint needed;	/* bytes needed (optional) */
-	uint driver;	/* to identify target driver */
-} dhd_ioctl_t;
-
-/* Underlying BUS definition */
-enum {
-	BUS_TYPE_USB = 0, /* for USB dongles */
-	BUS_TYPE_SDIO, /* for SDIO dongles */
-	BUS_TYPE_PCIE /* for PCIE dongles */
-};
-
-/* per-driver magic numbers */
-#define DHD_IOCTL_MAGIC		0x00444944
-
-/* bump this number if you change the ioctl interface */
-#define DHD_IOCTL_VERSION	1
-
-#define	DHD_IOCTL_MAXLEN	8192		/* max length ioctl buffer required */
-#define	DHD_IOCTL_SMLEN		256		/* "small" length ioctl buffer required */
-
-/* common ioctl definitions */
-#define DHD_GET_MAGIC				0
-#define DHD_GET_VERSION				1
-#define DHD_GET_VAR				2
-#define DHD_SET_VAR				3
-
-/* message levels */
-#define DHD_ERROR_VAL	0x0001
-#define DHD_TRACE_VAL	0x0002
-#define DHD_INFO_VAL	0x0004
-#define DHD_DATA_VAL	0x0008
-#define DHD_CTL_VAL	0x0010
-#define DHD_TIMER_VAL	0x0020
-#define DHD_HDRS_VAL	0x0040
-#define DHD_BYTES_VAL	0x0080
-#define DHD_INTR_VAL	0x0100
-#define DHD_LOG_VAL	0x0200
-#define DHD_GLOM_VAL	0x0400
-#define DHD_EVENT_VAL	0x0800
-#define DHD_BTA_VAL	0x1000
-#define DHD_ISCAN_VAL	0x2000
-#define DHD_ARPOE_VAL	0x4000
-#define DHD_REORDER_VAL	0x8000
-#define DHD_WL_VAL		0x10000
-#define DHD_NOCHECKDIED_VAL		0x20000 /* UTF WAR */
-#define DHD_WL_VAL2		0x40000
-#define DHD_PNO_VAL		0x80000
-#define DHD_MSGTRACE_VAL	0x100000
-#define DHD_FWLOG_VAL		0x400000
-#define DHD_RTT_VAL		0x200000
-#define DHD_IOV_INFO_VAL	0x800000
-
-#ifdef SDTEST
-/* For pktgen iovar */
-typedef struct dhd_pktgen {
-	uint version;		/* To allow structure change tracking */
-	uint freq;		/* Max ticks between tx/rx attempts */
-	uint count;		/* Test packets to send/rcv each attempt */
-	uint print;		/* Print counts every <print> attempts */
-	uint total;		/* Total packets (or bursts) */
-	uint minlen;		/* Minimum length of packets to send */
-	uint maxlen;		/* Maximum length of packets to send */
-	uint numsent;		/* Count of test packets sent */
-	uint numrcvd;		/* Count of test packets received */
-	uint numfail;		/* Count of test send failures */
-	uint mode;		/* Test mode (type of test packets) */
-	uint stop;		/* Stop after this many tx failures */
-} dhd_pktgen_t;
-
-/* Version in case structure changes */
-#define DHD_PKTGEN_VERSION 2
-
-/* Type of test packets to use */
-#define DHD_PKTGEN_ECHO		1 /* Send echo requests */
-#define DHD_PKTGEN_SEND 	2 /* Send discard packets */
-#define DHD_PKTGEN_RXBURST	3 /* Request dongle send N packets */
-#define DHD_PKTGEN_RECV		4 /* Continuous rx from continuous tx dongle */
-#endif /* SDTEST */
-
-/* Enter idle immediately (no timeout) */
-#define DHD_IDLE_IMMEDIATE	(-1)
-
-/* Values for idleclock iovar: other values are the sd_divisor to use when idle */
-#define DHD_IDLE_ACTIVE	0	/* Do not request any SD clock change when idle */
-#define DHD_IDLE_STOP   (-1)	/* Request SD clock be stopped (and use SD1 mode) */
-
-
-/* require default structure packing */
-#include <packed_section_end.h>
-
-#endif /* _dhdioctl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
deleted file mode 100644
index 7601256..0000000
--- a/drivers/net/wireless/bcmdhd/include/epivers.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $
- *
-*/
-
-#ifndef _epivers_h_
-#define _epivers_h_
-
-#define	EPI_MAJOR_VERSION	1
-
-#define	EPI_MINOR_VERSION	363
-
-#define	EPI_RC_NUMBER		59
-
-#define	EPI_INCREMENTAL_NUMBER	144
-
-#define	EPI_BUILD_NUMBER	0
-
-#define	EPI_VERSION		1, 363, 59, 144
-
-#define	EPI_VERSION_NUM		0x0116b3b9
-
-#define EPI_VERSION_DEV		1.363.59
-
-/* Driver Version String, ASCII, 32 chars max */
-#define	EPI_VERSION_STR		"1.363.59.144 (r)"
-
-#endif /* _epivers_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/event_log.h b/drivers/net/wireless/bcmdhd/include/event_log.h
deleted file mode 100644
index d06d811..0000000
--- a/drivers/net/wireless/bcmdhd/include/event_log.h
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * EVENT_LOG system definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: event_log.h 591285 2015-10-07 11:56:29Z $
- */
-
-#ifndef _EVENT_LOG_H_
-#define _EVENT_LOG_H_
-
-#include <typedefs.h>
-#include <proto/event_log_set.h>
-#include <proto/event_log_tag.h>
-
-/* logstrs header */
-#define LOGSTRS_MAGIC   0x4C4F4753
-#define LOGSTRS_VERSION 0x1
-
-/* We make sure that the block size will fit in a single packet
- *  (allowing for a bit of overhead on each packet
- */
-#define EVENT_LOG_MAX_BLOCK_SIZE	1400
-#define EVENT_LOG_WL_BLOCK_SIZE		0x200
-#define EVENT_LOG_PSM_BLOCK_SIZE	0x200
-#define EVENT_LOG_BUS_BLOCK_SIZE	0x200
-#define EVENT_LOG_ERROR_BLOCK_SIZE	0x200
-
-/*
- * There are multiple levels of objects define here:
- *   event_log_set - a set of buffers
- *   event log groups - every event log call is part of just one.  All
- *                      event log calls in a group are handled the
- *                      same way.  Each event log group is associated
- *                      with an event log set or is off.
- */
-
-#ifndef __ASSEMBLER__
-
-/* On the external system where the dumper is we need to make sure
- * that these types are the same size as they are on the ARM the
- * produced them
- */
-#ifdef EVENT_LOG_DUMPER
-#define _EL_BLOCK_PTR uint32
-#define _EL_TYPE_PTR uint32
-#define _EL_SET_PTR uint32
-#define _EL_TOP_PTR uint32
-#else
-#define _EL_BLOCK_PTR struct event_log_block *
-#define _EL_TYPE_PTR uint32 *
-#define _EL_SET_PTR struct event_log_set **
-#define _EL_TOP_PTR struct event_log_top *
-#endif /* EVENT_LOG_DUMPER */
-
-/* Event log sets (a logical circurlar buffer) consist of one or more
- * event_log_blocks.  The blocks themselves form a logical circular
- * list.  The log entries are placed in each event_log_block until it
- * is full.  Logging continues with the next event_log_block in the
- * event_set until the last event_log_block is reached and then
- * logging starts over with the first event_log_block in the
- * event_set.
- */
-typedef struct event_log_block {
-	_EL_BLOCK_PTR next_block;
-	_EL_BLOCK_PTR prev_block;
-	_EL_TYPE_PTR end_ptr;
-
-	/* Start of packet sent for log tracing */
-	uint16 pktlen;			/* Size of rest of block */
-	uint16 count;			/* Logtrace counter */
-	uint32 timestamp;		/* Timestamp at start of use */
-	uint32 event_logs;
-} event_log_block_t;
-
-/* There can be multiple event_sets with each logging a set of
- * associated events (i.e, "fast" and "slow" events).
- */
-typedef struct event_log_set {
-	_EL_BLOCK_PTR first_block; 	/* Pointer to first event_log block */
-	_EL_BLOCK_PTR last_block; 	/* Pointer to last event_log block */
-	_EL_BLOCK_PTR logtrace_block;	/* next block traced */
-	_EL_BLOCK_PTR cur_block;   	/* Pointer to current event_log block */
-	_EL_TYPE_PTR cur_ptr;      	/* Current event_log pointer */
-	uint32 blockcount;		/* Number of blocks */
-	uint16 logtrace_count;		/* Last count for logtrace */
-	uint16 blockfill_count;		/* Fill count for logtrace */
-	uint32 timestamp;		/* Last timestamp event */
-	uint32 cyclecount;		/* Cycles at last timestamp event */
-} event_log_set_t;
-
-/* Top data structure for access to everything else */
-typedef struct event_log_top {
-	uint32 magic;
-#define EVENT_LOG_TOP_MAGIC 0x474C8669 /* 'EVLG' */
-	uint32 version;
-#define EVENT_LOG_VERSION 1
-	uint32 num_sets;
-	uint32 logstrs_size;		/* Size of lognums + logstrs area */
-	uint32 timestamp;		/* Last timestamp event */
-	uint32 cyclecount;		/* Cycles at last timestamp event */
-	_EL_SET_PTR sets; 		/* Ptr to array of <num_sets> set ptrs */
-} event_log_top_t;
-
-/* Data structure of Keeping the Header from logstrs.bin */
-typedef struct {
-	uint32 logstrs_size;    /* Size of the file */
-	uint32 rom_lognums_offset; /* Offset to the ROM lognum */
-	uint32 ram_lognums_offset; /* Offset to the RAM lognum */
-	uint32 rom_logstrs_offset; /* Offset to the ROM logstr */
-	uint32 ram_logstrs_offset; /* Offset to the RAM logstr */
-	/* Keep version and magic last since "header" is appended to the end of logstrs file. */
-	uint32 version;            /* Header version */
-	uint32 log_magic;       /* MAGIC number for verification 'LOGS' */
-} logstr_header_t;
-
-/*
- * Use the following macros for generating log events.
- *
- * The FAST versions check the enable of the tag before evaluating the arguments and calling the
- * event_log function.  This adds 5 instructions.  The COMPACT versions evaluate the arguments
- * and call the event_log function unconditionally.  The event_log function will then skip logging
- * if this tag is disabled.
- *
- * To support easy usage of existing debugging (e.g. msglevel) via macro re-definition there are
- * two variants of these macros to help.
- *
- * First there are the CAST versions.  The event_log function normally logs uint32 values or else
- * they have to be cast to uint32.  The CAST versions blindly cast for you so you don't have to edit
- * any existing code.
- *
- * Second there are the PAREN_ARGS versions.  These expect the logging format string and arguments
- * to be enclosed in parentheses.  This allows us to make the following mapping of an existing
- * msglevel macro:
- *  #define WL_ERROR(args)   EVENT_LOG_CAST_PAREN_ARGS(EVENT_LOG_TAG_WL_ERROR, args)
- *
- * The versions of the macros without FAST or COMPACT in their name are just synonyms for the
- * COMPACT versions.
- *
- * You should use the COMPACT macro (or its synonym) in cases where there is some preceding logic
- * that prevents the execution of the macro, e.g. WL_ERROR by definition rarely gets executed.
- * Use the FAST macro in performance sensitive paths. The key concept here is that you should be
- * assuming that your macro usage is compiled into ROM and can't be changed ... so choose wisely.
- *
- */
-
-#ifndef EVENT_LOG_DUMPER
-
-#ifndef EVENT_LOG_COMPILE
-
-/* Null define if no tracing */
-#define EVENT_LOG(format, ...)
-#define EVENT_LOG_FAST(tag, fmt, ...)
-#define EVENT_LOG_COMPACT(tag, fmt, ...)
-
-#define EVENT_LOG_CAST(tag, fmt, ...)
-#define EVENT_LOG_FAST_CAST(tag, fmt, ...)
-#define EVENT_LOG_COMPACT_CAST(tag, fmt, ...)
-
-#define EVENT_LOG_CAST_PAREN_ARGS(tag, pargs)
-#define EVENT_LOG_FAST_CAST_PAREN_ARGS(tag, pargs)
-#define EVENT_LOG_COMPACT_CAST_PAREN_ARGS(tag, pargs)
-
-#define EVENT_LOG_IS_LOG_ON(tag)	0
-
-#else  /* EVENT_LOG_COMPILE */
-
-/* The first few are special because they can be done more efficiently
- * this way and they are the common case.  Once there are too many
- * parameters the code size starts to be an issue and a loop is better
- */
-#define _EVENT_LOG0(tag, fmt_num) 			\
-	event_log0(tag, fmt_num)
-#define _EVENT_LOG1(tag, fmt_num, t1) 			\
-	event_log1(tag, fmt_num, t1)
-#define _EVENT_LOG2(tag, fmt_num, t1, t2) 		\
-	event_log2(tag, fmt_num, t1, t2)
-#define _EVENT_LOG3(tag, fmt_num, t1, t2, t3) 		\
-	event_log3(tag, fmt_num, t1, t2, t3)
-#define _EVENT_LOG4(tag, fmt_num, t1, t2, t3, t4) 	\
-	event_log4(tag, fmt_num, t1, t2, t3, t4)
-
-/* The rest call the generic routine that takes a count */
-#define _EVENT_LOG5(tag, fmt_num, ...) event_logn(5, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG6(tag, fmt_num, ...) event_logn(6, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG7(tag, fmt_num, ...) event_logn(7, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG8(tag, fmt_num, ...) event_logn(8, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG9(tag, fmt_num, ...) event_logn(9, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOGA(tag, fmt_num, ...) event_logn(10, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOGB(tag, fmt_num, ...) event_logn(11, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOGC(tag, fmt_num, ...) event_logn(12, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOGD(tag, fmt_num, ...) event_logn(13, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOGE(tag, fmt_num, ...) event_logn(14, tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOGF(tag, fmt_num, ...) event_logn(15, tag, fmt_num, __VA_ARGS__)
-
-
-/* Casting  low level macros */
-#define _EVENT_LOG_CAST0(tag, fmt_num)			\
-	event_log0(tag, fmt_num)
-#define _EVENT_LOG_CAST1(tag, fmt_num, t1)		\
-	event_log1(tag, fmt_num, (uint32)(t1))
-#define _EVENT_LOG_CAST2(tag, fmt_num, t1, t2)		\
-	event_log2(tag, fmt_num, (uint32)(t1), (uint32)(t2))
-#define _EVENT_LOG_CAST3(tag, fmt_num, t1, t2, t3)	\
-	event_log3(tag, fmt_num, (uint32)(t1), (uint32)(t2), (uint32)(t3))
-#define _EVENT_LOG_CAST4(tag, fmt_num, t1, t2, t3, t4)	\
-	event_log4(tag, fmt_num, (uint32)(t1), (uint32)(t2), (uint32)(t3), (uint32)(t4))
-
-/* The rest call the generic routine that takes a count */
-#define _EVENT_LOG_CAST5(tag, fmt_num, ...) _EVENT_LOG5(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CAST6(tag, fmt_num, ...) _EVENT_LOG6(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CAST7(tag, fmt_num, ...) _EVENT_LOG7(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CAST8(tag, fmt_num, ...) _EVENT_LOG8(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CAST9(tag, fmt_num, ...) _EVENT_LOG9(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CASTA(tag, fmt_num, ...) _EVENT_LOGA(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CASTB(tag, fmt_num, ...) _EVENT_LOGB(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CASTC(tag, fmt_num, ...) _EVENT_LOGC(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CASTD(tag, fmt_num, ...) _EVENT_LOGD(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CASTE(tag, fmt_num, ...) _EVENT_LOGE(tag, fmt_num, __VA_ARGS__)
-#define _EVENT_LOG_CASTF(tag, fmt_num, ...) _EVENT_LOGF(tag, fmt_num, __VA_ARGS__)
-
-/* Hack to make the proper routine call when variadic macros get
- * passed.  Note the max of 15 arguments.  More than that can't be
- * handled by the event_log entries anyways so best to catch it at compile
- * time
- */
-
-#define _EVENT_LOG_VA_NUM_ARGS(F, _1, _2, _3, _4, _5, _6, _7, _8, _9,	\
-			       _A, _B, _C, _D, _E, _F, N, ...) F ## N
-
-/* cast = _EVENT_LOG for no casting
- * cast = _EVENT_LOG_CAST for casting of fmt arguments to uint32.
- *        Only first 4 arguments are casted to uint32. event_logn() is called
- *        if more than 4 arguments are present. This function internally assumes
- *        all arguments are uint32
- */
-#define _EVENT_LOG(cast, tag, fmt, ...)					\
-	static char logstr[] __attribute__ ((section(".logstrs"))) = fmt; \
-	static uint32 fmtnum __attribute__ ((section(".lognums"))) = (uint32) &logstr; \
-	_EVENT_LOG_VA_NUM_ARGS(cast, ##__VA_ARGS__,			\
-			       F, E, D, C, B, A, 9, 8,			\
-			       7, 6, 5, 4, 3, 2, 1, 0)			\
-	(tag, (int) &fmtnum , ## __VA_ARGS__)
-
-
-#define EVENT_LOG_FAST(tag, fmt, ...)					\
-	do {								\
-		if (event_log_tag_sets != NULL) {			\
-			uint8 tag_flag = *(event_log_tag_sets + tag);	\
-			if (tag_flag != 0) {				\
-				_EVENT_LOG(_EVENT_LOG, tag, fmt , ## __VA_ARGS__);	\
-			}						\
-		}							\
-	} while (0)
-
-#define EVENT_LOG_COMPACT(tag, fmt, ...)				\
-	do {								\
-		_EVENT_LOG(_EVENT_LOG, tag, fmt , ## __VA_ARGS__);	\
-	} while (0)
-
-/* Event log macro with casting to uint32 of arguments */
-#define EVENT_LOG_FAST_CAST(tag, fmt, ...)				\
-	do {								\
-		if (event_log_tag_sets != NULL) {			\
-			uint8 tag_flag = *(event_log_tag_sets + tag);	\
-			if (tag_flag != 0) {				\
-				_EVENT_LOG(_EVENT_LOG_CAST, tag, fmt , ## __VA_ARGS__);	\
-			}						\
-		}							\
-	} while (0)
-
-#define EVENT_LOG_COMPACT_CAST(tag, fmt, ...)				\
-	do {								\
-		_EVENT_LOG(_EVENT_LOG_CAST, tag, fmt , ## __VA_ARGS__);	\
-	} while (0)
-
-
-#define EVENT_LOG(tag, fmt, ...) EVENT_LOG_COMPACT(tag, fmt , ## __VA_ARGS__)
-
-#define EVENT_LOG_CAST(tag, fmt, ...) EVENT_LOG_COMPACT_CAST(tag, fmt , ## __VA_ARGS__)
-
-#define _EVENT_LOG_REMOVE_PAREN(...) __VA_ARGS__
-#define EVENT_LOG_REMOVE_PAREN(args) _EVENT_LOG_REMOVE_PAREN args
-
-#define EVENT_LOG_CAST_PAREN_ARGS(tag, pargs)				\
-		EVENT_LOG_CAST(tag, EVENT_LOG_REMOVE_PAREN(pargs))
-
-#define EVENT_LOG_FAST_CAST_PAREN_ARGS(tag, pargs)			\
-		EVENT_LOG_FAST_CAST(tag, EVENT_LOG_REMOVE_PAREN(pargs))
-
-#define EVENT_LOG_COMPACT_CAST_PAREN_ARGS(tag, pargs)			\
-		EVENT_LOG_COMPACT_CAST(tag, EVENT_LOG_REMOVE_PAREN(pargs))
-
-
-#define EVENT_LOG_IS_LOG_ON(tag) (*(event_log_tag_sets + (tag)) & EVENT_LOG_TAG_FLAG_LOG)
-
-#define EVENT_DUMP	event_log_buffer
-
-extern uint8 *event_log_tag_sets;
-
-#include <siutils.h>
-
-extern int event_log_init(si_t *sih);
-extern int event_log_set_init(si_t *sih, int set_num, int size);
-extern int event_log_set_expand(si_t *sih, int set_num, int size);
-extern int event_log_set_shrink(si_t *sih, int set_num, int size);
-extern int event_log_tag_start(int tag, int set_num, int flags);
-extern int event_log_tag_stop(int tag);
-extern int event_log_get(int set_num, int buflen, void *buf);
-extern uint8 * event_log_next_logtrace(int set_num);
-
-extern void event_log0(int tag, int fmtNum);
-extern void event_log1(int tag, int fmtNum, uint32 t1);
-extern void event_log2(int tag, int fmtNum, uint32 t1, uint32 t2);
-extern void event_log3(int tag, int fmtNum, uint32 t1, uint32 t2, uint32 t3);
-extern void event_log4(int tag, int fmtNum, uint32 t1, uint32 t2, uint32 t3, uint32 t4);
-extern void event_logn(int num_args, int tag, int fmtNum, ...);
-
-extern void event_log_time_sync(uint32 ms);
-extern void event_log_buffer(int tag, uint8 *buf, int size);
-
-#endif /* EVENT_LOG_DUMPER */
-
-#endif /* EVENT_LOG_COMPILE */
-
-#endif /* __ASSEMBLER__ */
-
-#endif /* _EVENT_LOG_H */
diff --git a/drivers/net/wireless/bcmdhd/include/hnd_armtrap.h b/drivers/net/wireless/bcmdhd/include/hnd_armtrap.h
deleted file mode 100644
index baf5572..0000000
--- a/drivers/net/wireless/bcmdhd/include/hnd_armtrap.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * HND arm trap handling.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hnd_armtrap.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_hnd_armtrap_h_
-#define	_hnd_armtrap_h_
-
-
-/* ARM trap handling */
-
-/* Trap types defined by ARM (see arminc.h) */
-
-/* Trap locations in lo memory */
-#define	TRAP_STRIDE	4
-#define FIRST_TRAP	TR_RST
-#define LAST_TRAP	(TR_FIQ * TRAP_STRIDE)
-
-#if defined(__ARM_ARCH_4T__)
-#define	MAX_TRAP_TYPE	(TR_FIQ + 1)
-#elif defined(__ARM_ARCH_7M__)
-#define	MAX_TRAP_TYPE	(TR_ISR + ARMCM3_NUMINTS)
-#endif	/* __ARM_ARCH_7M__ */
-
-/* The trap structure is defined here as offsets for assembly */
-#define	TR_TYPE		0x00
-#define	TR_EPC		0x04
-#define	TR_CPSR		0x08
-#define	TR_SPSR		0x0c
-#define	TR_REGS		0x10
-#define	TR_REG(n)	(TR_REGS + (n) * 4)
-#define	TR_SP		TR_REG(13)
-#define	TR_LR		TR_REG(14)
-#define	TR_PC		TR_REG(15)
-
-#define	TRAP_T_SIZE	80
-#define ASSERT_TRAP_SVC_NUMBER	255
-
-#ifndef	_LANGUAGE_ASSEMBLY
-
-#include <typedefs.h>
-
-typedef struct _trap_struct {
-	uint32		type;
-	uint32		epc;
-	uint32		cpsr;
-	uint32		spsr;
-	uint32		r0;	/* a1 */
-	uint32		r1;	/* a2 */
-	uint32		r2;	/* a3 */
-	uint32		r3;	/* a4 */
-	uint32		r4;	/* v1 */
-	uint32		r5;	/* v2 */
-	uint32		r6;	/* v3 */
-	uint32		r7;	/* v4 */
-	uint32		r8;	/* v5 */
-	uint32		r9;	/* sb/v6 */
-	uint32		r10;	/* sl/v7 */
-	uint32		r11;	/* fp/v8 */
-	uint32		r12;	/* ip */
-	uint32		r13;	/* sp */
-	uint32		r14;	/* lr */
-	uint32		pc;	/* r15 */
-} trap_t;
-
-#endif	/* !_LANGUAGE_ASSEMBLY */
-
-#endif	/* _hnd_armtrap_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/hnd_cons.h b/drivers/net/wireless/bcmdhd/include/hnd_cons.h
deleted file mode 100644
index 2dee71a..0000000
--- a/drivers/net/wireless/bcmdhd/include/hnd_cons.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Console support for RTE - for host use only.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hnd_cons.h 514727 2014-11-12 03:02:48Z $
- */
-#ifndef	_hnd_cons_h_
-#define	_hnd_cons_h_
-
-#include <typedefs.h>
-#include <siutils.h>
-
-#define CBUF_LEN	(128)
-
-#define LOG_BUF_LEN	1024
-
-#ifdef BOOTLOADER_CONSOLE_OUTPUT
-#undef RWL_MAX_DATA_LEN
-#undef CBUF_LEN
-#undef LOG_BUF_LEN
-#define RWL_MAX_DATA_LEN (4 * 1024 + 8)
-#define CBUF_LEN	(RWL_MAX_DATA_LEN + 64)
-#define LOG_BUF_LEN (16 * 1024)
-#endif
-
-typedef struct {
-	uint32		buf;		/* Can't be pointer on (64-bit) hosts */
-	uint		buf_size;
-	uint		idx;
-	uint		out_idx;	/* output index */
-} hnd_log_t;
-
-typedef struct {
-	/* Virtual UART
-	 *   When there is no UART (e.g. Quickturn), the host should write a complete
-	 *   input line directly into cbuf and then write the length into vcons_in.
-	 *   This may also be used when there is a real UART (at risk of conflicting with
-	 *   the real UART).  vcons_out is currently unused.
-	 */
-	volatile uint	vcons_in;
-	volatile uint	vcons_out;
-
-	/* Output (logging) buffer
-	 *   Console output is written to a ring buffer log_buf at index log_idx.
-	 *   The host may read the output when it sees log_idx advance.
-	 *   Output will be lost if the output wraps around faster than the host polls.
-	 */
-	hnd_log_t	log;
-
-	/* Console input line buffer
-	 *   Characters are read one at a time into cbuf until <CR> is received, then
-	 *   the buffer is processed as a command line.  Also used for virtual UART.
-	 */
-	uint		cbuf_idx;
-	char		cbuf[CBUF_LEN];
-} hnd_cons_t;
-
-#endif /* _hnd_cons_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/hnd_pktpool.h b/drivers/net/wireless/bcmdhd/include/hnd_pktpool.h
deleted file mode 100644
index 3cf46727..0000000
--- a/drivers/net/wireless/bcmdhd/include/hnd_pktpool.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * HND generic packet pool operation primitives
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hnd_pktpool.h 591285 2015-10-07 11:56:29Z $
- */
-
-#ifndef _hnd_pktpool_h_
-#define _hnd_pktpool_h_
-
-#include <osl_ext.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* mutex macros for thread safe */
-#ifdef HND_PKTPOOL_THREAD_SAFE
-#define HND_PKTPOOL_MUTEX_DECL(mutex)		OSL_EXT_MUTEX_DECL(mutex)
-#else
-#define HND_PKTPOOL_MUTEX_DECL(mutex)
-#endif
-
-#ifdef BCMPKTPOOL
-#define POOL_ENAB(pool)		((pool) && (pool)->inited)
-#else /* BCMPKTPOOL */
-#define POOL_ENAB(bus)		0
-#endif /* BCMPKTPOOL */
-
-#ifndef PKTPOOL_LEN_MAX
-#define PKTPOOL_LEN_MAX		40
-#endif /* PKTPOOL_LEN_MAX */
-#define PKTPOOL_CB_MAX		3
-#define PKTPOOL_CB_MAX_AVL	4
-
-
-/* forward declaration */
-struct pktpool;
-
-typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg);
-typedef struct {
-	pktpool_cb_t cb;
-	void *arg;
-} pktpool_cbinfo_t;
-
-/** PCIe SPLITRX related: call back fn extension to populate host address in pool pkt */
-typedef int (*pktpool_cb_extn_t)(struct pktpool *pool, void *arg1, void* pkt, bool arg2);
-typedef struct {
-	pktpool_cb_extn_t cb;
-	void *arg;
-} pktpool_cbextn_info_t;
-
-
-#ifdef BCMDBG_POOL
-/* pkt pool debug states */
-#define POOL_IDLE	0
-#define POOL_RXFILL	1
-#define POOL_RXDH	2
-#define POOL_RXD11	3
-#define POOL_TXDH	4
-#define POOL_TXD11	5
-#define POOL_AMPDU	6
-#define POOL_TXENQ	7
-
-typedef struct {
-	void *p;
-	uint32 cycles;
-	uint32 dur;
-} pktpool_dbg_t;
-
-typedef struct {
-	uint8 txdh;	/* tx to host */
-	uint8 txd11;	/* tx to d11 */
-	uint8 enq;	/* waiting in q */
-	uint8 rxdh;	/* rx from host */
-	uint8 rxd11;	/* rx from d11 */
-	uint8 rxfill;	/* dma_rxfill */
-	uint8 idle;	/* avail in pool */
-} pktpool_stats_t;
-#endif /* BCMDBG_POOL */
-
-typedef struct pktpool {
-	bool inited;            /**< pktpool_init was successful */
-	uint8 type;             /**< type of lbuf: basic, frag, etc */
-	uint8 id;               /**< pktpool ID:  index in registry */
-	bool istx;              /**< direction: transmit or receive data path */
-	HND_PKTPOOL_MUTEX_DECL(mutex)	/**< thread-safe mutex */
-
-	void * freelist;        /**< free list: see PKTNEXTFREE(), PKTSETNEXTFREE() */
-	uint16 avail;           /**< number of packets in pool's free list */
-	uint16 len;             /**< number of packets managed by pool */
-	uint16 maxlen;          /**< maximum size of pool <= PKTPOOL_LEN_MAX */
-	uint16 plen;            /**< size of pkt buffer, excluding lbuf|lbuf_frag */
-
-	bool empty;
-	uint8 cbtoggle;
-	uint8 cbcnt;
-	uint8 ecbcnt;
-	uint8 emptycb_disable;	/**< Value of type enum pktpool_empty_cb_state */
-	pktpool_cbinfo_t *availcb_excl;
-	pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX_AVL];
-	pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX];
-	pktpool_cbextn_info_t cbext;	/**< PCIe SPLITRX related */
-	pktpool_cbextn_info_t rxcplidfn;
-#ifdef BCMDBG_POOL
-	uint8 dbg_cbcnt;
-	pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX];
-	uint16 dbg_qlen;
-	pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1];
-#endif
-	pktpool_cbinfo_t dmarxfill;
-} pktpool_t;
-
-
-pktpool_t *get_pktpools_registry(int id);
-
-/* Incarnate a pktpool registry. On success returns total_pools. */
-extern int pktpool_attach(osl_t *osh, uint32 total_pools);
-extern int pktpool_dettach(osl_t *osh); /* Relinquish registry */
-
-extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx, uint8 type);
-extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp);
-extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal);
-extern void* pktpool_get(pktpool_t *pktp);
-extern void pktpool_free(pktpool_t *pktp, void *p);
-extern int pktpool_add(pktpool_t *pktp, void *p);
-extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp);
-extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb);
-extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
-extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
-extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen);
-extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen);
-extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable);
-extern bool pktpool_emptycb_disabled(pktpool_t *pktp);
-extern int pktpool_hostaddr_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg1);
-extern int pktpool_rxcplid_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg);
-extern void pktpool_invoke_dmarxfill(pktpool_t *pktp);
-extern int pkpool_haddr_avail_register_cb(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
-
-#define POOLPTR(pp)         ((pktpool_t *)(pp))
-#define POOLID(pp)          (POOLPTR(pp)->id)
-
-#define POOLSETID(pp, ppid) (POOLPTR(pp)->id = (ppid))
-
-#define pktpool_len(pp)     (POOLPTR(pp)->len)
-#define pktpool_avail(pp)   (POOLPTR(pp)->avail)
-#define pktpool_plen(pp)    (POOLPTR(pp)->plen)
-#define pktpool_maxlen(pp)  (POOLPTR(pp)->maxlen)
-
-
-/*
- * ----------------------------------------------------------------------------
- * A pool ID is assigned with a pkt pool during pool initialization. This is
- * done by maintaining a registry of all initialized pools, and the registry
- * index at which the pool is registered is used as the pool's unique ID.
- * ID 0 is reserved and is used to signify an invalid pool ID.
- * All packets henceforth allocated from a pool will be tagged with the pool's
- * unique ID. Packets allocated from the heap will use the reserved ID = 0.
- * Packets with non-zero pool id signify that they were allocated from a pool.
- * A maximum of 15 pools are supported, allowing a 4bit pool ID to be used
- * in place of a 32bit pool pointer in each packet.
- * ----------------------------------------------------------------------------
- */
-#define PKTPOOL_INVALID_ID          (0)
-#define PKTPOOL_MAXIMUM_ID          (15)
-
-/* Registry of pktpool(s) */
-/* Pool ID to/from Pool Pointer converters */
-#define PKTPOOL_ID2PTR(id)          (get_pktpools_registry(id))
-#define PKTPOOL_PTR2ID(pp)          (POOLID(pp))
-
-#ifdef BCMDBG_POOL
-extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
-extern int pktpool_start_trigger(pktpool_t *pktp, void *p);
-extern int pktpool_dbg_dump(pktpool_t *pktp);
-extern int pktpool_dbg_notify(pktpool_t *pktp);
-extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats);
-#endif /* BCMDBG_POOL */
-
-#ifdef BCMPKTPOOL
-#define SHARED_POOL		(pktpool_shared)
-extern pktpool_t *pktpool_shared;
-#ifdef BCMFRAGPOOL
-#define SHARED_FRAG_POOL	(pktpool_shared_lfrag)
-extern pktpool_t *pktpool_shared_lfrag;
-#endif
-
-/** PCIe SPLITRX related */
-#define SHARED_RXFRAG_POOL	(pktpool_shared_rxlfrag)
-extern pktpool_t *pktpool_shared_rxlfrag;
-
-void hnd_pktpool_init(osl_t *osh);
-void hnd_pktpool_fill(pktpool_t *pktpool, bool minimal);
-void hnd_pktpool_refill(bool minimal);
-#else /* BCMPKTPOOL */
-#define SHARED_POOL		((struct pktpool *)NULL)
-#endif /* BCMPKTPOOL */
-
-#ifdef __cplusplus
-	}
-#endif
-
-#endif /* _hnd_pktpool_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/hnd_pktq.h b/drivers/net/wireless/bcmdhd/include/hnd_pktq.h
deleted file mode 100644
index 1586de3..0000000
--- a/drivers/net/wireless/bcmdhd/include/hnd_pktq.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * HND generic pktq operation primitives
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hnd_pktq.h 591283 2015-10-07 11:52:00Z $
- */
-
-#ifndef _hnd_pktq_h_
-#define _hnd_pktq_h_
-
-#include <osl_ext.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* mutex macros for thread safe */
-#ifdef HND_PKTQ_THREAD_SAFE
-#define HND_PKTQ_MUTEX_DECL(mutex)		OSL_EXT_MUTEX_DECL(mutex)
-#else
-#define HND_PKTQ_MUTEX_DECL(mutex)
-#endif
-
-/* osl multi-precedence packet queue */
-#define PKTQ_LEN_MAX            0xFFFF  /* Max uint16 65535 packets */
-#ifndef PKTQ_LEN_DEFAULT
-#define PKTQ_LEN_DEFAULT        128	/* Max 128 packets */
-#endif
-#ifndef PKTQ_MAX_PREC
-#define PKTQ_MAX_PREC           16	/* Maximum precedence levels */
-#endif
-
-typedef struct pktq_prec {
-	void *head;     /**< first packet to dequeue */
-	void *tail;     /**< last packet to dequeue */
-	uint16 len;     /**< number of queued packets */
-	uint16 max;     /**< maximum number of queued packets */
-} pktq_prec_t;
-
-#ifdef PKTQ_LOG
-typedef struct {
-	uint32 requested;    /**< packets requested to be stored */
-	uint32 stored;	     /**< packets stored */
-	uint32 saved;	     /**< packets saved,
-	                            because a lowest priority queue has given away one packet
-	                      */
-	uint32 selfsaved;    /**< packets saved,
-	                            because an older packet from the same queue has been dropped
-	                      */
-	uint32 full_dropped; /**< packets dropped,
-	                            because pktq is full with higher precedence packets
-	                      */
-	uint32 dropped;      /**< packets dropped because pktq per that precedence is full */
-	uint32 sacrificed;   /**< packets dropped,
-	                            in order to save one from a queue of a highest priority
-	                      */
-	uint32 busy;         /**< packets droped because of hardware/transmission error */
-	uint32 retry;        /**< packets re-sent because they were not received */
-	uint32 ps_retry;     /**< packets retried again prior to moving power save mode */
-	uint32 suppress;     /**< packets which were suppressed and not transmitted */
-	uint32 retry_drop;   /**< packets finally dropped after retry limit */
-	uint32 max_avail;    /**< the high-water mark of the queue capacity for packets -
-	                            goes to zero as queue fills
-	                      */
-	uint32 max_used;     /**< the high-water mark of the queue utilisation for packets -
-						        increases with use ('inverse' of max_avail)
-				          */
-	uint32 queue_capacity; /**< the maximum capacity of the queue */
-	uint32 rtsfail;        /**< count of rts attempts that failed to receive cts */
-	uint32 acked;          /**< count of packets sent (acked) successfully */
-	uint32 txrate_succ;    /**< running total of phy rate of packets sent successfully */
-	uint32 txrate_main;    /**< running totoal of primary phy rate of all packets */
-	uint32 throughput;     /**< actual data transferred successfully */
-	uint32 airtime;        /**< cumulative total medium access delay in useconds */
-	uint32  _logtime;      /**< timestamp of last counter clear  */
-} pktq_counters_t;
-
-typedef struct {
-	uint32                  _prec_log;
-	pktq_counters_t*        _prec_cnt[PKTQ_MAX_PREC];     /**< Counters per queue  */
-} pktq_log_t;
-#endif /* PKTQ_LOG */
-
-
-#define PKTQ_COMMON	\
-	uint16 num_prec;        /**< number of precedences in use */			\
-	uint16 hi_prec;         /**< rapid dequeue hint (>= highest non-empty prec) */	\
-	uint16 max;             /**< total max packets */					\
-	uint16 len;             /**< total number of packets */
-
-/* multi-priority pkt queue */
-struct pktq {
-	PKTQ_COMMON
-	/* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
-	struct pktq_prec q[PKTQ_MAX_PREC];
-	HND_PKTQ_MUTEX_DECL(mutex)
-#ifdef PKTQ_LOG
-	pktq_log_t*      pktqlog;
-#endif
-};
-
-/* simple, non-priority pkt queue */
-struct spktq {
-	PKTQ_COMMON
-	/* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
-	struct pktq_prec q[1];
-	HND_PKTQ_MUTEX_DECL(mutex)
-};
-
-#define PKTQ_PREC_ITER(pq, prec)        for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
-
-/* fn(pkt, arg).  return true if pkt belongs to if */
-typedef bool (*ifpkt_cb_t)(void*, int);
-
-/* operations on a specific precedence in packet queue */
-
-#define pktq_psetmax(pq, prec, _max)	((pq)->q[prec].max = (_max))
-#define pktq_pmax(pq, prec)		((pq)->q[prec].max)
-#define pktq_plen(pq, prec)		((pq)->q[prec].len)
-#define pktq_pempty(pq, prec)		((pq)->q[prec].len == 0)
-#define pktq_ppeek(pq, prec)		((pq)->q[prec].head)
-#define pktq_ppeek_tail(pq, prec)	((pq)->q[prec].tail)
-#ifdef HND_PKTQ_THREAD_SAFE
-extern int pktq_pavail(struct pktq *pq, int prec);
-extern bool pktq_pfull(struct pktq *pq, int prec);
-#else
-#define pktq_pavail(pq, prec)	((pq)->q[prec].max - (pq)->q[prec].len)
-#define pktq_pfull(pq, prec)	((pq)->q[prec].len >= (pq)->q[prec].max)
-#endif	/* HND_PKTQ_THREAD_SAFE */
-
-extern void  pktq_append(struct pktq *pq, int prec, struct spktq *list);
-extern void  pktq_prepend(struct pktq *pq, int prec, struct spktq *list);
-
-extern void *pktq_penq(struct pktq *pq, int prec, void *p);
-extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
-extern void *pktq_pdeq(struct pktq *pq, int prec);
-extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p);
-extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg);
-extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
-/* Empty the queue at particular precedence level */
-extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir,
-	ifpkt_cb_t fn, int arg);
-/* Remove a specified packet from its queue */
-extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
-
-/* operations on a set of precedences in packet queue */
-
-extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
-extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
-extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out);
-
-/* operations on packet queue as a whole */
-
-#define pktq_len(pq)		((int)(pq)->len)
-#define pktq_max(pq)		((int)(pq)->max)
-#define pktq_empty(pq)		((pq)->len == 0)
-#ifdef HND_PKTQ_THREAD_SAFE
-extern int pktq_avail(struct pktq *pq);
-extern bool pktq_full(struct pktq *pq);
-#else
-#define pktq_avail(pq)		((int)((pq)->max - (pq)->len))
-#define pktq_full(pq)		((pq)->len >= (pq)->max)
-#endif	/* HND_PKTQ_THREAD_SAFE */
-
-/* operations for single precedence queues */
-#define pktenq(pq, p)		pktq_penq(((struct pktq *)(void *)pq), 0, (p))
-#define pktenq_head(pq, p)	pktq_penq_head(((struct pktq *)(void *)pq), 0, (p))
-#define pktdeq(pq)		pktq_pdeq(((struct pktq *)(void *)pq), 0)
-#define pktdeq_tail(pq)		pktq_pdeq_tail(((struct pktq *)(void *)pq), 0)
-#define pktqflush(osh, pq)	pktq_flush(osh, ((struct pktq *)(void *)pq), TRUE, NULL, 0)
-#define pktqinit(pq, len)	pktq_init(((struct pktq *)(void *)pq), 1, len)
-#define pktqdeinit(pq)		pktq_deinit((struct pktq *)(void *)pq)
-#define pktqavail(pq)		pktq_avail((struct pktq *)(void *)pq)
-#define pktqfull(pq)		pktq_full((struct pktq *)(void *)pq)
-
-extern bool pktq_init(struct pktq *pq, int num_prec, int max_len);
-extern bool pktq_deinit(struct pktq *pq);
-
-extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len);
-
-/* prec_out may be NULL if caller is not interested in return value */
-extern void *pktq_deq(struct pktq *pq, int *prec_out);
-extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
-extern void *pktq_peek(struct pktq *pq, int *prec_out);
-extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
-extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg);
-
-#ifdef __cplusplus
-	}
-#endif
-
-#endif /* _hnd_pktq_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/hndpmu.h b/drivers/net/wireless/bcmdhd/include/hndpmu.h
deleted file mode 100644
index dfc83d3..0000000
--- a/drivers/net/wireless/bcmdhd/include/hndpmu.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * HND SiliconBackplane PMU support.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hndpmu.h 530150 2015-01-29 08:43:40Z $
- */
-
-#ifndef _hndpmu_h_
-#define _hndpmu_h_
-
-#include <typedefs.h>
-#include <osl_decl.h>
-#include <siutils.h>
-
-
-extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on, uint32* min_res_mask);
-extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength);
-
-extern void si_pmu_minresmask_htavail_set(si_t *sih, osl_t *osh, bool set_clear);
-extern void si_pmu_slow_clk_reinit(si_t *sih, osl_t *osh);
-extern void si_pmu_avbtimer_enable(si_t *sih, osl_t *osh, bool set_flag);
-
-#endif /* _hndpmu_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/hndsoc.h b/drivers/net/wireless/bcmdhd/include/hndsoc.h
deleted file mode 100644
index 36884a0..0000000
--- a/drivers/net/wireless/bcmdhd/include/hndsoc.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Broadcom HND chip & on-chip-interconnect-related definitions.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hndsoc.h 517544 2014-11-26 00:40:42Z $
- */
-
-#ifndef	_HNDSOC_H
-#define	_HNDSOC_H
-
-/* Include the soci specific files */
-#include <sbconfig.h>
-#include <aidmp.h>
-
-/*
- * SOC Interconnect Address Map.
- * All regions may not exist on all chips.
- */
-#define SI_SDRAM_BASE		0x00000000	/* Physical SDRAM */
-#define SI_PCI_MEM		0x08000000	/* Host Mode sb2pcitranslation0 (64 MB) */
-#define SI_PCI_MEM_SZ		(64 * 1024 * 1024)
-#define SI_PCI_CFG		0x0c000000	/* Host Mode sb2pcitranslation1 (64 MB) */
-#define	SI_SDRAM_SWAPPED	0x10000000	/* Byteswapped Physical SDRAM */
-#define SI_SDRAM_R2		0x80000000	/* Region 2 for sdram (512 MB) */
-
-#define SI_ENUM_BASE    	0x18000000	/* Enumeration space base */
-
-#define SI_WRAP_BASE    	0x18100000	/* Wrapper space base */
-#define SI_CORE_SIZE    	0x1000		/* each core gets 4Kbytes for registers */
-
-#ifndef SI_MAXCORES
-#define	SI_MAXCORES		32		/* NorthStar has more cores */
-#endif /* SI_MAXCORES */
-
-#define	SI_MAXBR		4		/* Max bridges (this is arbitrary, for software
-					 * convenience and could be changed if we
-					 * make any larger chips
-					 */
-
-#define	SI_FASTRAM		0x19000000	/* On-chip RAM on chips that also have DDR */
-#define	SI_FASTRAM_SWAPPED	0x19800000
-
-#define	SI_FLASH2		0x1c000000	/* Flash Region 2 (region 1 shadowed here) */
-#define	SI_FLASH2_SZ		0x02000000	/* Size of Flash Region 2 */
-#define	SI_ARMCM3_ROM		0x1e000000	/* ARM Cortex-M3 ROM */
-#define	SI_FLASH1		0x1fc00000	/* MIPS Flash Region 1 */
-#define	SI_FLASH1_SZ		0x00400000	/* MIPS Size of Flash Region 1 */
-#define	SI_FLASH_WINDOW		0x01000000	/* Flash XIP Window */
-
-#define SI_NS_NANDFLASH		0x1c000000	/* NorthStar NAND flash base */
-#define SI_NS_NORFLASH		0x1e000000	/* NorthStar NOR flash base */
-#define SI_NS_ROM		0xfffd0000	/* NorthStar ROM */
-#define	SI_NS_FLASH_WINDOW	0x02000000	/* Flash XIP Window */
-
-#define	SI_ARM7S_ROM		0x20000000	/* ARM7TDMI-S ROM */
-#define	SI_ARMCR4_ROM		0x000f0000	/* ARM Cortex-R4 ROM */
-#define	SI_ARMCM3_SRAM2		0x60000000	/* ARM Cortex-M3 SRAM Region 2 */
-#define	SI_ARM7S_SRAM2		0x80000000	/* ARM7TDMI-S SRAM Region 2 */
-#define	SI_ARMCA7_ROM		0x00000000	/* ARM Cortex-A7 ROM */
-#define	SI_ARMCA7_RAM		0x00200000	/* ARM Cortex-A7 RAM */
-#define	SI_ARM_FLASH1		0xffff0000	/* ARM Flash Region 1 */
-#define	SI_ARM_FLASH1_SZ	0x00010000	/* ARM Size of Flash Region 1 */
-
-#define SI_SFLASH		0x14000000
-#define SI_PCI_DMA		0x40000000	/* Client Mode sb2pcitranslation2 (1 GB) */
-#define SI_PCI_DMA2		0x80000000	/* Client Mode sb2pcitranslation2 (1 GB) */
-#define SI_PCI_DMA_SZ		0x40000000	/* Client Mode sb2pcitranslation2 size in bytes */
-#define SI_PCIE_DMA_L32		0x00000000	/* PCIE Client Mode sb2pcitranslation2
-						 * (2 ZettaBytes), low 32 bits
-						 */
-#define SI_PCIE_DMA_H32		0x80000000	/* PCIE Client Mode sb2pcitranslation2
-						 * (2 ZettaBytes), high 32 bits
-						 */
-
-#define SI_BCM53573_NANDFLASH	0x30000000	/* 53573 NAND flash base */
-#define SI_BCM53573_NORFLASH	0x1c000000	/* 53573 NOR flash base */
-
-#define	SI_BCM53573_NORFLASH_WINDOW	0x01000000	/* only support 16M direct access for
-							 * 3-byte address modes in spi flash
-							 */
-#define	SI_BCM53573_BOOTDEV_MASK	0x3
-#define	SI_BCM53573_BOOTDEV_NOR		0x0
-
-#define	SI_BCM53573_DDRTYPE_MASK	0x10
-#define	SI_BCM53573_DDRTYPE_DDR3	0x10
-
-/* APB bridge code */
-#define	APB_BRIDGE_ID		0x135		/* APB Bridge 0, 1, etc. */
-
-/* core codes */
-#define	NODEV_CORE_ID		0x700		/* Invalid coreid */
-#define	CC_CORE_ID		0x800		/* chipcommon core */
-#define	ILINE20_CORE_ID		0x801		/* iline20 core */
-#define	SRAM_CORE_ID		0x802		/* sram core */
-#define	SDRAM_CORE_ID		0x803		/* sdram core */
-#define	PCI_CORE_ID		0x804		/* pci core */
-#define	MIPS_CORE_ID		0x805		/* mips core */
-#define	ENET_CORE_ID		0x806		/* enet mac core */
-#define	CODEC_CORE_ID		0x807		/* v90 codec core */
-#define	USB_CORE_ID		0x808		/* usb 1.1 host/device core */
-#define	ADSL_CORE_ID		0x809		/* ADSL core */
-#define	ILINE100_CORE_ID	0x80a		/* iline100 core */
-#define	IPSEC_CORE_ID		0x80b		/* ipsec core */
-#define	UTOPIA_CORE_ID		0x80c		/* utopia core */
-#define	PCMCIA_CORE_ID		0x80d		/* pcmcia core */
-#define	SOCRAM_CORE_ID		0x80e		/* internal memory core */
-#define	MEMC_CORE_ID		0x80f		/* memc sdram core */
-#define	OFDM_CORE_ID		0x810		/* OFDM phy core */
-#define	EXTIF_CORE_ID		0x811		/* external interface core */
-#define	D11_CORE_ID		0x812		/* 802.11 MAC core */
-#define	APHY_CORE_ID		0x813		/* 802.11a phy core */
-#define	BPHY_CORE_ID		0x814		/* 802.11b phy core */
-#define	GPHY_CORE_ID		0x815		/* 802.11g phy core */
-#define	MIPS33_CORE_ID		0x816		/* mips3302 core */
-#define	USB11H_CORE_ID		0x817		/* usb 1.1 host core */
-#define	USB11D_CORE_ID		0x818		/* usb 1.1 device core */
-#define	USB20H_CORE_ID		0x819		/* usb 2.0 host core */
-#define	USB20D_CORE_ID		0x81a		/* usb 2.0 device core */
-#define	SDIOH_CORE_ID		0x81b		/* sdio host core */
-#define	ROBO_CORE_ID		0x81c		/* roboswitch core */
-#define	ATA100_CORE_ID		0x81d		/* parallel ATA core */
-#define	SATAXOR_CORE_ID		0x81e		/* serial ATA & XOR DMA core */
-#define	GIGETH_CORE_ID		0x81f		/* gigabit ethernet core */
-#define	PCIE_CORE_ID		0x820		/* pci express core */
-#define	NPHY_CORE_ID		0x821		/* 802.11n 2x2 phy core */
-#define	SRAMC_CORE_ID		0x822		/* SRAM controller core */
-#define	MINIMAC_CORE_ID		0x823		/* MINI MAC/phy core */
-#define	ARM11_CORE_ID		0x824		/* ARM 1176 core */
-#define	ARM7S_CORE_ID		0x825		/* ARM7tdmi-s core */
-#define	LPPHY_CORE_ID		0x826		/* 802.11a/b/g phy core */
-#define	PMU_CORE_ID		0x827		/* PMU core */
-#define	SSNPHY_CORE_ID		0x828		/* 802.11n single-stream phy core */
-#define	SDIOD_CORE_ID		0x829		/* SDIO device core */
-#define	ARMCM3_CORE_ID		0x82a		/* ARM Cortex M3 core */
-#define	HTPHY_CORE_ID		0x82b		/* 802.11n 4x4 phy core */
-#define	MIPS74K_CORE_ID		0x82c		/* mips 74k core */
-#define	GMAC_CORE_ID		0x82d		/* Gigabit MAC core */
-#define	DMEMC_CORE_ID		0x82e		/* DDR1/2 memory controller core */
-#define	PCIERC_CORE_ID		0x82f		/* PCIE Root Complex core */
-#define	OCP_CORE_ID		0x830		/* OCP2OCP bridge core */
-#define	SC_CORE_ID		0x831		/* shared common core */
-#define	AHB_CORE_ID		0x832		/* OCP2AHB bridge core */
-#define	SPIH_CORE_ID		0x833		/* SPI host core */
-#define	I2S_CORE_ID		0x834		/* I2S core */
-#define	DMEMS_CORE_ID		0x835		/* SDR/DDR1 memory controller core */
-#define	DEF_SHIM_COMP		0x837		/* SHIM component in ubus/6362 */
-
-#define ACPHY_CORE_ID		0x83b		/* Dot11 ACPHY */
-#define PCIE2_CORE_ID		0x83c		/* pci express Gen2 core */
-#define USB30D_CORE_ID		0x83d		/* usb 3.0 device core */
-#define ARMCR4_CORE_ID		0x83e		/* ARM CR4 CPU */
-#define GCI_CORE_ID		0x840		/* GCI Core */
-#define M2MDMA_CORE_ID          0x844           /* memory to memory dma */
-#define CMEM_CORE_ID		0x846		/* CNDS DDR2/3 memory controller */
-#define ARMCA7_CORE_ID		0x847		/* ARM CA7 CPU */
-#define SYSMEM_CORE_ID		0x849		/* System memory core */
-#define APB_BRIDGE_CORE_ID	0x135		/* APB bridge core ID */
-#define AXI_CORE_ID		0x301		/* AXI/GPV core ID */
-#define EROM_CORE_ID		0x366		/* EROM core ID */
-#define OOB_ROUTER_CORE_ID	0x367		/* OOB router core ID */
-#define DEF_AI_COMP		0xfff		/* Default component, in ai chips it maps all
-						 * unused address ranges
-						 */
-
-#define CC_4706_CORE_ID		0x500		/* chipcommon core */
-#define NS_PCIEG2_CORE_ID	0x501		/* PCIE Gen 2 core */
-#define NS_DMA_CORE_ID		0x502		/* DMA core */
-#define NS_SDIO3_CORE_ID	0x503		/* SDIO3 core */
-#define NS_USB20_CORE_ID	0x504		/* USB2.0 core */
-#define NS_USB30_CORE_ID	0x505		/* USB3.0 core */
-#define NS_A9JTAG_CORE_ID	0x506		/* ARM Cortex A9 JTAG core */
-#define NS_DDR23_CORE_ID	0x507		/* Denali DDR2/DDR3 memory controller */
-#define NS_ROM_CORE_ID		0x508		/* ROM core */
-#define NS_NAND_CORE_ID		0x509		/* NAND flash controller core */
-#define NS_QSPI_CORE_ID		0x50a		/* SPI flash controller core */
-#define NS_CCB_CORE_ID		0x50b		/* ChipcommonB core */
-#define SOCRAM_4706_CORE_ID	0x50e		/* internal memory core */
-#define NS_SOCRAM_CORE_ID	SOCRAM_4706_CORE_ID
-#define	ARMCA9_CORE_ID		0x510		/* ARM Cortex A9 core (ihost) */
-#define	NS_IHOST_CORE_ID	ARMCA9_CORE_ID	/* ARM Cortex A9 core (ihost) */
-#define GMAC_COMMON_4706_CORE_ID	0x5dc		/* Gigabit MAC core */
-#define GMAC_4706_CORE_ID	0x52d		/* Gigabit MAC core */
-#define AMEMC_CORE_ID		0x52e		/* DDR1/2 memory controller core */
-#define ALTA_CORE_ID		0x534		/* I2S core */
-#define DDR23_PHY_CORE_ID	0x5dd
-
-#define SI_PCI1_MEM     0x40000000  /* Host Mode sb2pcitranslation0 (64 MB) */
-#define SI_PCI1_CFG     0x44000000  /* Host Mode sb2pcitranslation1 (64 MB) */
-#define SI_PCIE1_DMA_H32		0xc0000000	/* PCIE Client Mode sb2pcitranslation2
-						 * (2 ZettaBytes), high 32 bits
-						 */
-#define CC_4706B0_CORE_REV	0x8000001f		/* chipcommon core */
-#define SOCRAM_4706B0_CORE_REV	0x80000005		/* internal memory core */
-#define GMAC_4706B0_CORE_REV	0x80000000		/* Gigabit MAC core */
-#define NS_PCIEG2_CORE_REV_B0	0x7		/* NS-B0 PCIE Gen 2 core rev */
-
-/* There are TWO constants on all HND chips: SI_ENUM_BASE above,
- * and chipcommon being the first core:
- */
-#define	SI_CC_IDX		0
-/* SOC Interconnect types (aka chip types) */
-#define	SOCI_SB			0
-#define	SOCI_AI			1
-#define	SOCI_UBUS		2
-#define	SOCI_NAI		3
-
-/* Common core control flags */
-#define	SICF_BIST_EN		0x8000
-#define	SICF_PME_EN		0x4000
-#define	SICF_CORE_BITS		0x3ffc
-#define	SICF_FGC		0x0002
-#define	SICF_CLOCK_EN		0x0001
-
-/* Common core status flags */
-#define	SISF_BIST_DONE		0x8000
-#define	SISF_BIST_ERROR		0x4000
-#define	SISF_GATED_CLK		0x2000
-#define	SISF_DMA64		0x1000
-#define	SISF_CORE_BITS		0x0fff
-
-/* Norstar core status flags */
-#define SISF_NS_BOOTDEV_MASK	0x0003	/* ROM core */
-#define SISF_NS_BOOTDEV_NOR	0x0000	/* ROM core */
-#define SISF_NS_BOOTDEV_NAND	0x0001	/* ROM core */
-#define SISF_NS_BOOTDEV_ROM	0x0002	/* ROM core */
-#define SISF_NS_BOOTDEV_OFFLOAD	0x0003	/* ROM core */
-#define SISF_NS_SKUVEC_MASK	0x000c	/* ROM core */
-
-/* A register that is common to all cores to
- * communicate w/PMU regarding clock control.
- */
-#define SI_CLK_CTL_ST		0x1e0		/* clock control and status */
-#define SI_PWR_CTL_ST		0x1e8		/* For memory clock gating */
-
-/* clk_ctl_st register */
-#define	CCS_FORCEALP		0x00000001	/* force ALP request */
-#define	CCS_FORCEHT		0x00000002	/* force HT request */
-#define	CCS_FORCEILP		0x00000004	/* force ILP request */
-#define	CCS_ALPAREQ		0x00000008	/* ALP Avail Request */
-#define	CCS_HTAREQ		0x00000010	/* HT Avail Request */
-#define	CCS_FORCEHWREQOFF	0x00000020	/* Force HW Clock Request Off */
-#define CCS_HQCLKREQ		0x00000040	/* HQ Clock Required */
-#define CCS_USBCLKREQ		0x00000100	/* USB Clock Req */
-#define CCS_SECICLKREQ		0x00000100	/* SECI Clock Req */
-#define CCS_ARMFASTCLOCKREQ	0x00000100	/* ARM CR4/CA7 fast clock request */
-#define CCS_AVBCLKREQ		0x00000400	/* AVB Clock enable request */
-#define CCS_ERSRC_REQ_MASK	0x00000700	/* external resource requests */
-#define CCS_ERSRC_REQ_SHIFT	8
-#define	CCS_ALPAVAIL		0x00010000	/* ALP is available */
-#define	CCS_HTAVAIL		0x00020000	/* HT is available */
-#define CCS_BP_ON_APL		0x00040000	/* RO: Backplane is running on ALP clock */
-#define CCS_BP_ON_HT		0x00080000	/* RO: Backplane is running on HT clock */
-#define CCS_ARMFASTCLOCKSTATUS	0x01000000	/* Fast CPU clock is running */
-#define CCS_ERSRC_STS_MASK	0x07000000	/* external resource status */
-#define CCS_ERSRC_STS_SHIFT	24
-
-#define	CCS0_HTAVAIL		0x00010000	/* HT avail in chipc and pcmcia on 4328a0 */
-#define	CCS0_ALPAVAIL		0x00020000	/* ALP avail in chipc and pcmcia on 4328a0 */
-
-/* Not really related to SOC Interconnect, but a couple of software
- * conventions for the use the flash space:
- */
-
-/* Minumum amount of flash we support */
-#define FLASH_MIN		0x00020000	/* Minimum flash size */
-
-/* A boot/binary may have an embedded block that describes its size  */
-#define	BISZ_OFFSET		0x3e0		/* At this offset into the binary */
-#define	BISZ_MAGIC		0x4249535a	/* Marked with this value: 'BISZ' */
-#define	BISZ_MAGIC_IDX		0		/* Word 0: magic */
-#define	BISZ_TXTST_IDX		1		/*	1: text start */
-#define	BISZ_TXTEND_IDX		2		/*	2: text end */
-#define	BISZ_DATAST_IDX		3		/*	3: data start */
-#define	BISZ_DATAEND_IDX	4		/*	4: data end */
-#define	BISZ_BSSST_IDX		5		/*	5: bss start */
-#define	BISZ_BSSEND_IDX		6		/*	6: bss end */
-#define BISZ_SIZE		7		/* descriptor size in 32-bit integers */
-
-/* Boot/Kernel related defintion and functions */
-#define	SOC_BOOTDEV_ROM		0x00000001
-#define	SOC_BOOTDEV_PFLASH	0x00000002
-#define	SOC_BOOTDEV_SFLASH	0x00000004
-#define	SOC_BOOTDEV_NANDFLASH	0x00000008
-
-#define	SOC_KNLDEV_NORFLASH	0x00000002
-#define	SOC_KNLDEV_NANDFLASH	0x00000004
-
-#if !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__)
-int soc_boot_dev(void *sih);
-int soc_knl_dev(void *sih);
-#endif	/* !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__) */
-
-#endif /* _HNDSOC_H */
diff --git a/drivers/net/wireless/bcmdhd/include/linux_osl.h b/drivers/net/wireless/bcmdhd/include/linux_osl.h
deleted file mode 100644
index 539a2fa..0000000
--- a/drivers/net/wireless/bcmdhd/include/linux_osl.h
+++ /dev/null
@@ -1,1088 +0,0 @@
-/*
- * Linux OS Independent Layer
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: linux_osl.h 601764 2015-11-24 03:47:41Z $
- */
-
-#ifndef _linux_osl_h_
-#define _linux_osl_h_
-
-#include <typedefs.h>
-#define DECLSPEC_ALIGN(x)	__attribute__ ((aligned(x)))
-
-/* Linux Kernel: File Operations: start */
-extern void * osl_os_open_image(char * filename);
-extern int osl_os_get_image_block(char * buf, int len, void * image);
-extern void osl_os_close_image(void * image);
-extern int osl_os_image_size(void *image);
-/* Linux Kernel: File Operations: end */
-
-#ifdef BCMDRIVER
-
-/* OSL initialization */
-#ifdef SHARED_OSL_CMN
-extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag, void **osh_cmn);
-#else
-extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag);
-#endif /* SHARED_OSL_CMN */
-
-extern void osl_detach(osl_t *osh);
-extern int osl_static_mem_init(osl_t *osh, void *adapter);
-extern int osl_static_mem_deinit(osl_t *osh, void *adapter);
-extern void osl_set_bus_handle(osl_t *osh, void *bus_handle);
-extern void* osl_get_bus_handle(osl_t *osh);
-
-/* Global ASSERT type */
-extern uint32 g_assert_type;
-
-/* ASSERT */
-#if defined(BCMASSERT_LOG)
-	#define ASSERT(exp) \
-	  do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
-extern void osl_assert(const char *exp, const char *file, int line);
-#else
-	#ifdef __GNUC__
-		#define GCC_VERSION \
-			(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
-		#if GCC_VERSION > 30100
-			#define ASSERT(exp)	do {} while (0)
-		#else
-			/* ASSERT could cause segmentation fault on GCC3.1, use empty instead */
-			#define ASSERT(exp)
-		#endif /* GCC_VERSION > 30100 */
-	#endif /* __GNUC__ */
-#endif 
-
-/* bcm_prefetch_32B */
-static inline void bcm_prefetch_32B(const uint8 *addr, const int cachelines_32B)
-{
-}
-
-/* microsecond delay */
-#define	OSL_DELAY(usec)		osl_delay(usec)
-extern void osl_delay(uint usec);
-
-#define OSL_SLEEP(ms)			osl_sleep(ms)
-extern void osl_sleep(uint ms);
-
-#define	OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \
-	osl_pcmcia_read_attr((osh), (offset), (buf), (size))
-#define	OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \
-	osl_pcmcia_write_attr((osh), (offset), (buf), (size))
-extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size);
-extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size);
-
-/* PCI configuration space access macros */
-#define	OSL_PCI_READ_CONFIG(osh, offset, size) \
-	osl_pci_read_config((osh), (offset), (size))
-#define	OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \
-	osl_pci_write_config((osh), (offset), (size), (val))
-extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size);
-extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val);
-
-/* PCI device bus # and slot # */
-#define OSL_PCI_BUS(osh)	osl_pci_bus(osh)
-#define OSL_PCI_SLOT(osh)	osl_pci_slot(osh)
-#define OSL_PCIE_DOMAIN(osh)	osl_pcie_domain(osh)
-#define OSL_PCIE_BUS(osh)	osl_pcie_bus(osh)
-extern uint osl_pci_bus(osl_t *osh);
-extern uint osl_pci_slot(osl_t *osh);
-extern uint osl_pcie_domain(osl_t *osh);
-extern uint osl_pcie_bus(osl_t *osh);
-extern struct pci_dev *osl_pci_device(osl_t *osh);
-
-#define OSL_ACP_COHERENCE		(1<<1L)
-
-/* Pkttag flag should be part of public information */
-typedef struct {
-	bool pkttag;
-	bool mmbus;		/**< Bus supports memory-mapped register accesses */
-	pktfree_cb_fn_t tx_fn;  /**< Callback function for PKTFREE */
-	void *tx_ctx;		/**< Context to the callback function */
-	void	*unused[3];
-} osl_pubinfo_t;
-
-extern void osl_flag_set(osl_t *osh, uint32 mask);
-extern bool osl_is_flag_set(osl_t *osh, uint32 mask);
-
-#define PKTFREESETCB(osh, _tx_fn, _tx_ctx)		\
-	do {						\
-	   ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn;	\
-	   ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx;	\
-	} while (0)
-
-
-/* host/bus architecture-specific byte swap */
-#define BUS_SWAP32(v)		(v)
-	#define MALLOC(osh, size)	osl_malloc((osh), (size))
-	#define MALLOCZ(osh, size)	osl_mallocz((osh), (size))
-	#define MFREE(osh, addr, size)	osl_mfree((osh), (addr), (size))
-	#define MALLOCED(osh)		osl_malloced((osh))
-	#define MEMORY_LEFTOVER(osh) osl_check_memleak(osh)
-	extern void *osl_malloc(osl_t *osh, uint size);
-	extern void *osl_mallocz(osl_t *osh, uint size);
-	extern void osl_mfree(osl_t *osh, void *addr, uint size);
-	extern uint osl_malloced(osl_t *osh);
-	extern uint osl_check_memleak(osl_t *osh);
-
-
-#define	MALLOC_FAILED(osh)	osl_malloc_failed((osh))
-extern uint osl_malloc_failed(osl_t *osh);
-
-/* allocate/free shared (dma-able) consistent memory */
-#define	DMA_CONSISTENT_ALIGN	osl_dma_consistent_align()
-#define	DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \
-	osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
-#define	DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \
-	osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
-
-#define	DMA_ALLOC_CONSISTENT_FORCE32(osh, size, align, tot, pap, dmah) \
-	osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
-#define	DMA_FREE_CONSISTENT_FORCE32(osh, va, size, pa, dmah) \
-	osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
-
-extern uint osl_dma_consistent_align(void);
-extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align,
-	uint *tot, dmaaddr_t *pap);
-extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa);
-
-/* map/unmap direction */
-#define	DMA_TX	1	/* TX direction for DMA */
-#define	DMA_RX	2	/* RX direction for DMA */
-
-/* map/unmap shared (dma-able) memory */
-#define	DMA_UNMAP(osh, pa, size, direction, p, dmah) \
-	osl_dma_unmap((osh), (pa), (size), (direction))
-extern dmaaddr_t osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p,
-	hnddma_seg_map_t *txp_dmah);
-extern void osl_dma_unmap(osl_t *osh, dmaaddr_t pa, uint size, int direction);
-
-/* API for DMA addressing capability */
-#define OSL_DMADDRWIDTH(osh, addrwidth) ({BCM_REFERENCE(osh); BCM_REFERENCE(addrwidth);})
-
-#define OSL_SMP_WMB()	smp_wmb()
-
-/* API for CPU relax */
-extern void osl_cpu_relax(void);
-#define OSL_CPU_RELAX() osl_cpu_relax()
-
-#if (!defined(DHD_USE_COHERENT_MEM_FOR_RING) && defined(__ARM_ARCH_7A__)) || \
-	(defined(STBLINUX) && defined(__ARM_ARCH_7A__)) || (defined(CONFIG_ARCH_MSM8996) || \
-	defined(CONFIG_SOC_EXYNOS8890))
-	extern void osl_cache_flush(void *va, uint size);
-	extern void osl_cache_inv(void *va, uint size);
-	extern void osl_prefetch(const void *ptr);
-	#define OSL_CACHE_FLUSH(va, len)	osl_cache_flush((void *) va, len)
-	#define OSL_CACHE_INV(va, len)		osl_cache_inv((void *) va, len)
-	#define OSL_PREFETCH(ptr)			osl_prefetch(ptr)
-#ifdef __ARM_ARCH_7A__
-	extern int osl_arch_is_coherent(void);
-	#define OSL_ARCH_IS_COHERENT()		osl_arch_is_coherent()
-	extern int osl_acp_war_enab(void);
-	#define OSL_ACP_WAR_ENAB()			osl_acp_war_enab()
-#else
-	#define OSL_ARCH_IS_COHERENT()		NULL
-	#define OSL_ACP_WAR_ENAB()			NULL
-#endif /* __ARM_ARCH_7A__ */
-#else
-	#define OSL_CACHE_FLUSH(va, len)	BCM_REFERENCE(va)
-	#define OSL_CACHE_INV(va, len)		BCM_REFERENCE(va)
-	#define OSL_PREFETCH(ptr)		BCM_REFERENCE(ptr)
-
-	#define OSL_ARCH_IS_COHERENT()		NULL
-	#define OSL_ACP_WAR_ENAB()			NULL
-#endif 
-
-/* register access macros */
-#if defined(BCMSDIO)
-	#include <bcmsdh.h>
-	#define OSL_WRITE_REG(osh, r, v) (bcmsdh_reg_write(osl_get_bus_handle(osh), \
-		(uintptr)(r), sizeof(*(r)), (v)))
-	#define OSL_READ_REG(osh, r) (bcmsdh_reg_read(osl_get_bus_handle(osh), \
-		(uintptr)(r), sizeof(*(r))))
-#endif 
-
-#if defined(BCMSDIO)
-	#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) if (((osl_pubinfo_t*)(osh))->mmbus) \
-		mmap_op else bus_op
-	#define SELECT_BUS_READ(osh, mmap_op, bus_op) (((osl_pubinfo_t*)(osh))->mmbus) ? \
-		mmap_op : bus_op
-#else
-	#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); mmap_op;})
-	#define SELECT_BUS_READ(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); mmap_op;})
-#endif 
-
-#define OSL_ERROR(bcmerror)	osl_error(bcmerror)
-extern int osl_error(int bcmerror);
-
-/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
-#define	PKTBUFSZ	2048   /* largest reasonable packet buffer, driver uses for ethernet MTU */
-
-#define OSH_NULL   NULL
-
-/*
- * BINOSL selects the slightly slower function-call-based binary compatible osl.
- * Macros expand to calls to functions defined in linux_osl.c .
- */
-#include <linuxver.h>           /* use current 2.4.x calling conventions */
-#include <linux/kernel.h>       /* for vsn/printf's */
-#include <linux/string.h>       /* for mem*, str* */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 29)
-#define OSL_SYSUPTIME()		((uint32)jiffies_to_msecs(jiffies))
-#else
-#define OSL_SYSUPTIME()		((uint32)jiffies * (1000 / HZ))
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 29) */
-#define	printf(fmt, args...)	printk(fmt , ## args)
-#include <linux/kernel.h>	/* for vsn/printf's */
-#include <linux/string.h>	/* for mem*, str* */
-/* bcopy's: Linux kernel doesn't provide these (anymore) */
-#define	bcopy(src, dst, len)	memcpy((dst), (src), (len))
-#define	bcmp(b1, b2, len)	memcmp((b1), (b2), (len))
-#define	bzero(b, len)		memset((b), '\0', (len))
-
-/* register access macros */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 1)) && defined(CONFIG_64BIT) && \
-	defined(CONFIG_X86)
-#define R_REG(osh, r) (\
-	SELECT_BUS_READ(osh, \
-		({ \
-			__typeof(*(r)) __osl_v; \
-			switch (sizeof(*(r))) { \
-				case sizeof(uint8):	__osl_v = \
-					readb((volatile uint8*)(r)); break; \
-				case sizeof(uint16):	__osl_v = \
-					readw((volatile uint16*)(r)); break; \
-				case sizeof(uint32):	__osl_v = \
-					readl((volatile uint32*)(r)); break; \
-				case sizeof(uint64):	__osl_v = \
-					readq((volatile uint64*)(r)); break;  \
-			} \
-			__osl_v; \
-		}), \
-		OSL_READ_REG(osh, r)) \
-)
-#else
-#define R_REG(osh, r) (\
-	SELECT_BUS_READ(osh, \
-		({ \
-			__typeof(*(r)) __osl_v; \
-			switch (sizeof(*(r))) { \
-				case sizeof(uint8):	__osl_v = \
-					readb((volatile uint8*)(r)); break; \
-				case sizeof(uint16):	__osl_v = \
-					readw((volatile uint16*)(r)); break; \
-				case sizeof(uint32):	__osl_v = \
-					readl((volatile uint32*)(r)); break; \
-			} \
-			__osl_v; \
-		}), \
-		OSL_READ_REG(osh, r)) \
-)
-#endif /* KERNEL_VERSION(3, 11, 1)) && defined(CONFIG_64BIT) && defined(CONFIG_X86) */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 1)) && defined(CONFIG_64BIT) && \
-	defined(CONFIG_X86)
-#define W_REG(osh, r, v) do { \
-	SELECT_BUS_WRITE(osh, \
-		switch (sizeof(*(r))) { \
-			case sizeof(uint8):	writeb((uint8)(v), (volatile uint8*)(r)); break; \
-			case sizeof(uint16):	writew((uint16)(v), (volatile uint16*)(r)); break; \
-			case sizeof(uint32):	writel((uint32)(v), (volatile uint32*)(r)); break; \
-			case sizeof(uint64):	writeq((uint64)(v), (volatile uint64*)(r)); break; \
-		}, \
-		(OSL_WRITE_REG(osh, r, v))); \
-	} while (0)
-#else
-#define W_REG(osh, r, v) do { \
-	SELECT_BUS_WRITE(osh, \
-		switch (sizeof(*(r))) { \
-			case sizeof(uint8):	writeb((uint8)(v), (volatile uint8*)(r)); break; \
-			case sizeof(uint16):	writew((uint16)(v), (volatile uint16*)(r)); break; \
-			case sizeof(uint32):	writel((uint32)(v), (volatile uint32*)(r)); break; \
-		}, \
-		(OSL_WRITE_REG(osh, r, v))); \
-	} while (0)
-#endif  /* KERNEL_VERSION(3, 11, 1)) && defined(CONFIG_64BIT) && defined(CONFIG_X86) */
-
-#define	AND_REG(osh, r, v)		W_REG(osh, (r), R_REG(osh, r) & (v))
-#define	OR_REG(osh, r, v)		W_REG(osh, (r), R_REG(osh, r) | (v))
-
-/* bcopy, bcmp, and bzero functions */
-#define	bcopy(src, dst, len)	memcpy((dst), (src), (len))
-#define	bcmp(b1, b2, len)	memcmp((b1), (b2), (len))
-#define	bzero(b, len)		memset((b), '\0', (len))
-
-/* uncached/cached virtual address */
-#define OSL_UNCACHED(va)	((void *)va)
-#define OSL_CACHED(va)		((void *)va)
-
-#define OSL_PREF_RANGE_LD(va, sz) BCM_REFERENCE(va)
-#define OSL_PREF_RANGE_ST(va, sz) BCM_REFERENCE(va)
-
-/* get processor cycle count */
-#if defined(__i386__)
-#define	OSL_GETCYCLES(x)	rdtscl((x))
-#else
-#define OSL_GETCYCLES(x)	((x) = 0)
-#endif 
-
-/* dereference an address that may cause a bus exception */
-#define	BUSPROBE(val, addr)	({ (val) = R_REG(NULL, (addr)); 0; })
-
-/* map/unmap physical to virtual I/O */
-#if !defined(CONFIG_MMC_MSM7X00A)
-#define	REG_MAP(pa, size)	ioremap_nocache((unsigned long)(pa), (unsigned long)(size))
-#else
-#define REG_MAP(pa, size)       (void *)(0)
-#endif /* !defined(CONFIG_MMC_MSM7X00A */
-#define	REG_UNMAP(va)		iounmap((va))
-
-/* shared (dma-able) memory access macros */
-#define	R_SM(r)			*(r)
-#define	W_SM(r, v)		(*(r) = (v))
-#define	BZERO_SM(r, len)	memset((r), '\0', (len))
-
-/* Because the non BINOSL implemenation of the PKT OSL routines are macros (for
- * performance reasons),  we need the Linux headers.
- */
-#include <linuxver.h>		/* use current 2.4.x calling conventions */
-
-/* packet primitives */
-#ifdef BCMDBG_CTRACE
-#define	PKTGET(osh, len, send)		osl_pktget((osh), (len), __LINE__, __FILE__)
-#define	PKTDUP(osh, skb)		osl_pktdup((osh), (skb), __LINE__, __FILE__)
-#else
-#ifdef BCM_OBJECT_TRACE
-#define	PKTGET(osh, len, send)		osl_pktget((osh), (len), __LINE__, __FUNCTION__)
-#define	PKTDUP(osh, skb)		osl_pktdup((osh), (skb), __LINE__, __FUNCTION__)
-#else
-#define	PKTGET(osh, len, send)		osl_pktget((osh), (len))
-#define	PKTDUP(osh, skb)		osl_pktdup((osh), (skb))
-#endif /* BCM_OBJECT_TRACE */
-#endif /* BCMDBG_CTRACE */
-#define PKTLIST_DUMP(osh, buf)		BCM_REFERENCE(osh)
-#define PKTDBG_TRACE(osh, pkt, bit)	BCM_REFERENCE(osh)
-#if defined(BCM_OBJECT_TRACE)
-#define	PKTFREE(osh, skb, send)		osl_pktfree((osh), (skb), (send), __LINE__, __FUNCTION__)
-#else
-#define	PKTFREE(osh, skb, send)		osl_pktfree((osh), (skb), (send))
-#endif /* BCM_OBJECT_TRACE */
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-#define	PKTGET_STATIC(osh, len, send)		osl_pktget_static((osh), (len))
-#define	PKTFREE_STATIC(osh, skb, send)		osl_pktfree_static((osh), (skb), (send))
-#else
-#define	PKTGET_STATIC	PKTGET
-#define	PKTFREE_STATIC	PKTFREE
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-#define	PKTDATA(osh, skb)		({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->data);})
-#define	PKTLEN(osh, skb)		({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->len);})
-#define PKTHEADROOM(osh, skb)		(PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head))
-#define PKTEXPHEADROOM(osh, skb, b)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 skb_realloc_headroom((struct sk_buff*)(skb), (b)); \
-	 })
-#define PKTTAILROOM(osh, skb)		\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 skb_tailroom((struct sk_buff*)(skb)); \
-	 })
-#define PKTPADTAILROOM(osh, skb, padlen) \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 skb_pad((struct sk_buff*)(skb), (padlen)); \
-	 })
-#define	PKTNEXT(osh, skb)		({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->next);})
-#define	PKTSETNEXT(osh, skb, x)		\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)); \
-	 })
-#define	PKTSETLEN(osh, skb, len)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 __skb_trim((struct sk_buff*)(skb), (len)); \
-	 })
-#define	PKTPUSH(osh, skb, bytes)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 skb_push((struct sk_buff*)(skb), (bytes)); \
-	 })
-#define	PKTPULL(osh, skb, bytes)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 skb_pull((struct sk_buff*)(skb), (bytes)); \
-	 })
-#define	PKTTAG(skb)			((void*)(((struct sk_buff*)(skb))->cb))
-#define PKTSETPOOL(osh, skb, x, y)	BCM_REFERENCE(osh)
-#define	PKTPOOL(osh, skb)		({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
-#define PKTFREELIST(skb)        PKTLINK(skb)
-#define PKTSETFREELIST(skb, x)  PKTSETLINK((skb), (x))
-#define PKTPTR(skb)             (skb)
-#define PKTID(skb)              ({BCM_REFERENCE(skb); 0;})
-#define PKTSETID(skb, id)       ({BCM_REFERENCE(skb); BCM_REFERENCE(id);})
-#define PKTSHRINK(osh, m)		({BCM_REFERENCE(osh); m;})
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && defined(TSQ_MULTIPLIER)
-#define PKTORPHAN(skb)          osl_pkt_orphan_partial(skb)
-extern void osl_pkt_orphan_partial(struct sk_buff *skb);
-#else
-#define PKTORPHAN(skb)          ({BCM_REFERENCE(skb); 0;})
-#endif /* LINUX VERSION >= 3.6 */
-
-
-#ifdef BCMDBG_CTRACE
-#define	DEL_CTRACE(zosh, zskb) { \
-	unsigned long zflags; \
-	spin_lock_irqsave(&(zosh)->ctrace_lock, zflags); \
-	list_del(&(zskb)->ctrace_list); \
-	(zosh)->ctrace_num--; \
-	(zskb)->ctrace_start = 0; \
-	(zskb)->ctrace_count = 0; \
-	spin_unlock_irqrestore(&(zosh)->ctrace_lock, zflags); \
-}
-
-#define	UPDATE_CTRACE(zskb, zfile, zline) { \
-	struct sk_buff *_zskb = (struct sk_buff *)(zskb); \
-	if (_zskb->ctrace_count < CTRACE_NUM) { \
-		_zskb->func[_zskb->ctrace_count] = zfile; \
-		_zskb->line[_zskb->ctrace_count] = zline; \
-		_zskb->ctrace_count++; \
-	} \
-	else { \
-		_zskb->func[_zskb->ctrace_start] = zfile; \
-		_zskb->line[_zskb->ctrace_start] = zline; \
-		_zskb->ctrace_start++; \
-		if (_zskb->ctrace_start >= CTRACE_NUM) \
-			_zskb->ctrace_start = 0; \
-	} \
-}
-
-#define	ADD_CTRACE(zosh, zskb, zfile, zline) { \
-	unsigned long zflags; \
-	spin_lock_irqsave(&(zosh)->ctrace_lock, zflags); \
-	list_add(&(zskb)->ctrace_list, &(zosh)->ctrace_list); \
-	(zosh)->ctrace_num++; \
-	UPDATE_CTRACE(zskb, zfile, zline); \
-	spin_unlock_irqrestore(&(zosh)->ctrace_lock, zflags); \
-}
-
-#define PKTCALLER(zskb)	UPDATE_CTRACE((struct sk_buff *)zskb, (char *)__FUNCTION__, __LINE__)
-#endif /* BCMDBG_CTRACE */
-
-#ifdef CTFPOOL
-#define	CTFPOOL_REFILL_THRESH	3
-typedef struct ctfpool {
-	void		*head;
-	spinlock_t	lock;
-	uint		max_obj;
-	uint		curr_obj;
-	uint		obj_size;
-	uint		refills;
-	uint		fast_allocs;
-	uint 		fast_frees;
-	uint 		slow_allocs;
-} ctfpool_t;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
-#define	FASTBUF	(1 << 0)
-#define	PKTSETFAST(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 ((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF); \
-	 })
-#define	PKTCLRFAST(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 ((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF)); \
-	 })
-#define	PKTISFAST(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 ((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF); \
-	 })
-#define	PKTFAST(osh, skb)	(((struct sk_buff*)(skb))->pktc_flags)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
-#define	FASTBUF	(1 << 16)
-#define	PKTSETFAST(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF); \
-	 })
-#define	PKTCLRFAST(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)); \
-	 })
-#define	PKTISFAST(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 ((((struct sk_buff*)(skb))->mac_len) & FASTBUF); \
-	 })
-#define	PKTFAST(osh, skb)	(((struct sk_buff*)(skb))->mac_len)
-#else
-#define	FASTBUF	(1 << 0)
-#define	PKTSETFAST(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 ((((struct sk_buff*)(skb))->__unused) |= FASTBUF); \
-	 })
-#define	PKTCLRFAST(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 ((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF)); \
-	 })
-#define	PKTISFAST(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 ((((struct sk_buff*)(skb))->__unused) & FASTBUF); \
-	 })
-#define	PKTFAST(osh, skb)	(((struct sk_buff*)(skb))->__unused)
-#endif /* 2.6.22 */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
-#define	CTFPOOLPTR(osh, skb)	(((struct sk_buff*)(skb))->ctfpool)
-#define	CTFPOOLHEAD(osh, skb)	(((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head)
-#else
-#define	CTFPOOLPTR(osh, skb)	(((struct sk_buff*)(skb))->sk)
-#define	CTFPOOLHEAD(osh, skb)	(((ctfpool_t *)((struct sk_buff*)(skb))->sk)->head)
-#endif
-
-extern void *osl_ctfpool_add(osl_t *osh);
-extern void osl_ctfpool_replenish(osl_t *osh, uint thresh);
-extern int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size);
-extern void osl_ctfpool_cleanup(osl_t *osh);
-extern void osl_ctfpool_stats(osl_t *osh, void *b);
-#else /* CTFPOOL */
-#define	PKTSETFAST(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTCLRFAST(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTISFAST(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
-#endif /* CTFPOOL */
-
-#define	PKTSETCTF(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTCLRCTF(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTISCTF(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
-
-#ifdef HNDCTF
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
-#define	SKIPCT	(1 << 2)
-#define	CHAINED	(1 << 3)
-#define	PKTSETSKIPCT(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags |= SKIPCT); \
-	 })
-#define	PKTCLRSKIPCT(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags &= (~SKIPCT)); \
-	 })
-#define	PKTSKIPCT(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags & SKIPCT); \
-	 })
-#define	PKTSETCHAINED(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags |= CHAINED); \
-	 })
-#define	PKTCLRCHAINED(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags &= (~CHAINED)); \
-	 })
-#define	PKTISCHAINED(skb)	(((struct sk_buff*)(skb))->pktc_flags & CHAINED)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
-#define	SKIPCT	(1 << 18)
-#define	CHAINED	(1 << 19)
-#define	PKTSETSKIPCT(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->mac_len |= SKIPCT); \
-	 })
-#define	PKTCLRSKIPCT(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)); \
-	 })
-#define	PKTSKIPCT(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->mac_len & SKIPCT); \
-	 })
-#define	PKTSETCHAINED(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->mac_len |= CHAINED); \
-	 })
-#define	PKTCLRCHAINED(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->mac_len &= (~CHAINED)); \
-	 })
-#define	PKTISCHAINED(skb)	(((struct sk_buff*)(skb))->mac_len & CHAINED)
-#else /* 2.6.22 */
-#define	SKIPCT	(1 << 2)
-#define	CHAINED	(1 << 3)
-#define	PKTSETSKIPCT(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->__unused |= SKIPCT); \
-	 })
-#define	PKTCLRSKIPCT(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->__unused &= (~SKIPCT)); \
-	 })
-#define	PKTSKIPCT(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->__unused & SKIPCT); \
-	 })
-#define	PKTSETCHAINED(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->__unused |= CHAINED); \
-	 })
-#define	PKTCLRCHAINED(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->__unused &= (~CHAINED)); \
-	 })
-#define	PKTISCHAINED(skb)	(((struct sk_buff*)(skb))->__unused & CHAINED)
-#endif /* 2.6.22 */
-typedef struct ctf_mark {
-	uint32	value;
-}	ctf_mark_t;
-#define CTF_MARK(m)				(m.value)
-#else /* HNDCTF */
-#define	PKTSETSKIPCT(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTCLRSKIPCT(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTSKIPCT(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define CTF_MARK(m)		({BCM_REFERENCE(m); 0;})
-#endif /* HNDCTF */
-
-#if defined(BCM_GMAC3)
-
-/** pktalloced accounting in devices using GMAC Bulk Forwarding to DHD */
-
-/* Account for packets delivered to downstream forwarder by GMAC interface. */
-extern void osl_pkt_tofwder(osl_t *osh, void *skbs, int skb_cnt);
-#define PKTTOFWDER(osh, skbs, skb_cnt)  \
-	osl_pkt_tofwder(((osl_t *)osh), (void *)(skbs), (skb_cnt))
-
-/* Account for packets received from downstream forwarder. */
-#if defined(BCMDBG_CTRACE) /* pkt logging */
-extern void osl_pkt_frmfwder(osl_t *osh, void *skbs, int skb_cnt,
-                             int line, char *file);
-#define PKTFRMFWDER(osh, skbs, skb_cnt) \
-	osl_pkt_frmfwder(((osl_t *)osh), (void *)(skbs), (skb_cnt), \
-	                 __LINE__, __FILE__)
-#else  /* ! (BCMDBG_PKT || BCMDBG_CTRACE) */
-extern void osl_pkt_frmfwder(osl_t *osh, void *skbs, int skb_cnt);
-#define PKTFRMFWDER(osh, skbs, skb_cnt) \
-	osl_pkt_frmfwder(((osl_t *)osh), (void *)(skbs), (skb_cnt))
-#endif 
-
-
-/** GMAC Forwarded packet tagging for reduced cache flush/invalidate.
- * In FWDERBUF tagged packet, only FWDER_PKTMAPSZ amount of data would have
- * been accessed in the GMAC forwarder. This may be used to limit the number of
- * cachelines that need to be flushed or invalidated.
- * Packets sent to the DHD from a GMAC forwarder will be tagged w/ FWDERBUF.
- * DHD may clear the FWDERBUF tag, if more than FWDER_PKTMAPSZ was accessed.
- * Likewise, a debug print of a packet payload in say the ethernet driver needs
- * to be accompanied with a clear of the FWDERBUF tag.
- */
-
-/** Forwarded packets, have a HWRXOFF sized rx header (etc.h) */
-#define FWDER_HWRXOFF       (30)
-
-/** Maximum amount of a pktadat that a downstream forwarder (GMAC) may have
- * read into the L1 cache (not dirty). This may be used in reduced cache ops.
- *
- * Max 56: ET HWRXOFF[30] + BRCMHdr[4] + EtherHdr[14] + VlanHdr[4] + IP[4]
- */
-#define FWDER_PKTMAPSZ      (FWDER_HWRXOFF + 4 + 14 + 4 + 4)
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
-
-#define FWDERBUF            (1 << 4)
-#define PKTSETFWDERBUF(osh, skb) \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags |= FWDERBUF); \
-	 })
-#define PKTCLRFWDERBUF(osh, skb) \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags &= (~FWDERBUF)); \
-	 })
-#define PKTISFWDERBUF(osh, skb) \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags & FWDERBUF); \
-	 })
-
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
-
-#define FWDERBUF	        (1 << 20)
-#define PKTSETFWDERBUF(osh, skb) \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->mac_len |= FWDERBUF); \
-	 })
-#define PKTCLRFWDERBUF(osh, skb)  \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->mac_len &= (~FWDERBUF)); \
-	 })
-#define PKTISFWDERBUF(osh, skb) \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->mac_len & FWDERBUF); \
-	 })
-
-#else /* 2.6.22 */
-
-#define FWDERBUF            (1 << 4)
-#define PKTSETFWDERBUF(osh, skb)  \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->__unused |= FWDERBUF); \
-	 })
-#define PKTCLRFWDERBUF(osh, skb)  \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->__unused &= (~FWDERBUF)); \
-	 })
-#define PKTISFWDERBUF(osh, skb) \
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->__unused & FWDERBUF); \
-	 })
-
-#endif /* 2.6.22 */
-
-#else  /* ! BCM_GMAC3 */
-
-#define PKTSETFWDERBUF(osh, skb)  ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); })
-#define PKTCLRFWDERBUF(osh, skb)  ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); })
-#define PKTISFWDERBUF(osh, skb)   ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
-
-#endif /* ! BCM_GMAC3 */
-
-
-#ifdef HNDCTF
-/* For broadstream iqos */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
-#define	TOBR		(1 << 5)
-#define	PKTSETTOBR(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags |= TOBR); \
-	 })
-#define	PKTCLRTOBR(osh, skb)	\
-	({ \
-	 BCM_REFERENCE(osh); \
-	 (((struct sk_buff*)(skb))->pktc_flags &= (~TOBR)); \
-	 })
-#define	PKTISTOBR(skb)	(((struct sk_buff*)(skb))->pktc_flags & TOBR)
-#define	PKTSETCTFIPCTXIF(skb, ifp)	(((struct sk_buff*)(skb))->ctf_ipc_txif = ifp)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
-#define	PKTSETTOBR(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTCLRTOBR(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTISTOBR(skb)	({BCM_REFERENCE(skb); FALSE;})
-#define	PKTSETCTFIPCTXIF(skb, ifp)	({BCM_REFERENCE(skb); BCM_REFERENCE(ifp);})
-#else /* 2.6.22 */
-#define	PKTSETTOBR(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTCLRTOBR(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTISTOBR(skb)	({BCM_REFERENCE(skb); FALSE;})
-#define	PKTSETCTFIPCTXIF(skb, ifp)	({BCM_REFERENCE(skb); BCM_REFERENCE(ifp);})
-#endif /* 2.6.22 */
-#else /* HNDCTF */
-#define	PKTSETTOBR(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTCLRTOBR(osh, skb)	({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
-#define	PKTISTOBR(skb)	({BCM_REFERENCE(skb); FALSE;})
-#endif /* HNDCTF */
-
-
-#ifdef BCMFA
-#ifdef BCMFA_HW_HASH
-#define PKTSETFAHIDX(skb, idx)	(((struct sk_buff*)(skb))->napt_idx = idx)
-#else
-#define PKTSETFAHIDX(skb, idx)	({BCM_REFERENCE(skb); BCM_REFERENCE(idx);})
-#endif /* BCMFA_SW_HASH */
-#define PKTGETFAHIDX(skb)	(((struct sk_buff*)(skb))->napt_idx)
-#define PKTSETFADEV(skb, imp)	(((struct sk_buff*)(skb))->dev = imp)
-#define PKTSETRXDEV(skb)	(((struct sk_buff*)(skb))->rxdev = ((struct sk_buff*)(skb))->dev)
-
-#define	AUX_TCP_FIN_RST	(1 << 0)
-#define	AUX_FREED	(1 << 1)
-#define PKTSETFAAUX(skb)	(((struct sk_buff*)(skb))->napt_flags |= AUX_TCP_FIN_RST)
-#define	PKTCLRFAAUX(skb)	(((struct sk_buff*)(skb))->napt_flags &= (~AUX_TCP_FIN_RST))
-#define	PKTISFAAUX(skb)		(((struct sk_buff*)(skb))->napt_flags & AUX_TCP_FIN_RST)
-#define PKTSETFAFREED(skb)	(((struct sk_buff*)(skb))->napt_flags |= AUX_FREED)
-#define	PKTCLRFAFREED(skb)	(((struct sk_buff*)(skb))->napt_flags &= (~AUX_FREED))
-#define	PKTISFAFREED(skb)	(((struct sk_buff*)(skb))->napt_flags & AUX_FREED)
-#define	PKTISFABRIDGED(skb)	PKTISFAAUX(skb)
-#else
-#define	PKTISFAAUX(skb)		({BCM_REFERENCE(skb); FALSE;})
-#define	PKTISFABRIDGED(skb)	({BCM_REFERENCE(skb); FALSE;})
-#define	PKTISFAFREED(skb)	({BCM_REFERENCE(skb); FALSE;})
-
-#define	PKTCLRFAAUX(skb)	BCM_REFERENCE(skb)
-#define PKTSETFAFREED(skb)	BCM_REFERENCE(skb)
-#define	PKTCLRFAFREED(skb)	BCM_REFERENCE(skb)
-#endif /* BCMFA */
-
-#if defined(BCM_OBJECT_TRACE)
-extern void osl_pktfree(osl_t *osh, void *skb, bool send, int line, const char *caller);
-#else
-extern void osl_pktfree(osl_t *osh, void *skb, bool send);
-#endif /* BCM_OBJECT_TRACE */
-extern void *osl_pktget_static(osl_t *osh, uint len);
-extern void osl_pktfree_static(osl_t *osh, void *skb, bool send);
-extern void osl_pktclone(osl_t *osh, void **pkt);
-
-#ifdef BCMDBG_CTRACE
-#define PKT_CTRACE_DUMP(osh, b)	osl_ctrace_dump((osh), (b))
-extern void *osl_pktget(osl_t *osh, uint len, int line, char *file);
-extern void *osl_pkt_frmnative(osl_t *osh, void *skb, int line, char *file);
-extern int osl_pkt_is_frmnative(osl_t *osh, struct sk_buff *pkt);
-extern void *osl_pktdup(osl_t *osh, void *skb, int line, char *file);
-struct bcmstrbuf;
-extern void osl_ctrace_dump(osl_t *osh, struct bcmstrbuf *b);
-#else
-#ifdef BCM_OBJECT_TRACE
-extern void *osl_pktget(osl_t *osh, uint len, int line, const char *caller);
-extern void *osl_pktdup(osl_t *osh, void *skb, int line, const char *caller);
-#else
-extern void *osl_pktget(osl_t *osh, uint len);
-extern void *osl_pktdup(osl_t *osh, void *skb);
-#endif /* BCM_OBJECT_TRACE */
-extern void *osl_pkt_frmnative(osl_t *osh, void *skb);
-#endif /* BCMDBG_CTRACE */
-extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt);
-#ifdef BCMDBG_CTRACE
-#define PKTFRMNATIVE(osh, skb)  osl_pkt_frmnative(((osl_t *)osh), \
-				(struct sk_buff*)(skb), __LINE__, __FILE__)
-#define	PKTISFRMNATIVE(osh, skb) osl_pkt_is_frmnative((osl_t *)(osh), (struct sk_buff *)(skb))
-#else
-#define PKTFRMNATIVE(osh, skb)	osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb))
-#endif /* BCMDBG_CTRACE */
-#define PKTTONATIVE(osh, pkt)		osl_pkt_tonative((osl_t *)(osh), (pkt))
-
-#define	PKTLINK(skb)			(((struct sk_buff*)(skb))->prev)
-#define	PKTSETLINK(skb, x)		(((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x))
-#define	PKTPRIO(skb)			(((struct sk_buff*)(skb))->priority)
-#define	PKTSETPRIO(skb, x)		(((struct sk_buff*)(skb))->priority = (x))
-#define PKTSUMNEEDED(skb)		(((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW)
-#define PKTSETSUMGOOD(skb, x)		(((struct sk_buff*)(skb))->ip_summed = \
-						((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
-/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */
-#define PKTSHARED(skb)                  (((struct sk_buff*)(skb))->cloned)
-
-#ifdef CONFIG_NF_CONNTRACK_MARK
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-#define PKTMARK(p)                     (((struct sk_buff *)(p))->mark)
-#define PKTSETMARK(p, m)               ((struct sk_buff *)(p))->mark = (m)
-#else /* !2.6.0 */
-#define PKTMARK(p)                     (((struct sk_buff *)(p))->nfmark)
-#define PKTSETMARK(p, m)               ((struct sk_buff *)(p))->nfmark = (m)
-#endif /* 2.6.0 */
-#else /* CONFIG_NF_CONNTRACK_MARK */
-#define PKTMARK(p)                     0
-#define PKTSETMARK(p, m)
-#endif /* CONFIG_NF_CONNTRACK_MARK */
-
-#define PKTALLOCED(osh)		osl_pktalloced(osh)
-extern uint osl_pktalloced(osl_t *osh);
-
-#define OSL_RAND()		osl_rand()
-extern uint32 osl_rand(void);
-
-#define	DMA_MAP(osh, va, size, direction, p, dmah) \
-	osl_dma_map((osh), (va), (size), (direction), (p), (dmah))
-
-#ifdef PKTC
-/* Use 8 bytes of skb tstamp field to store below info */
-struct chain_node {
-	struct sk_buff	*link;
-	unsigned int	flags:3, pkts:9, bytes:20;
-};
-
-#define CHAIN_NODE(skb)		((struct chain_node*)(((struct sk_buff*)skb)->pktc_cb))
-
-#define	PKTCSETATTR(s, f, p, b)	({CHAIN_NODE(s)->flags = (f); CHAIN_NODE(s)->pkts = (p); \
-	                         CHAIN_NODE(s)->bytes = (b);})
-#define	PKTCCLRATTR(s)		({CHAIN_NODE(s)->flags = CHAIN_NODE(s)->pkts = \
-	                         CHAIN_NODE(s)->bytes = 0;})
-#define	PKTCGETATTR(s)		(CHAIN_NODE(s)->flags << 29 | CHAIN_NODE(s)->pkts << 20 | \
-	                         CHAIN_NODE(s)->bytes)
-#define	PKTCCNT(skb)		(CHAIN_NODE(skb)->pkts)
-#define	PKTCLEN(skb)		(CHAIN_NODE(skb)->bytes)
-#define	PKTCGETFLAGS(skb)	(CHAIN_NODE(skb)->flags)
-#define	PKTCSETFLAGS(skb, f)	(CHAIN_NODE(skb)->flags = (f))
-#define	PKTCCLRFLAGS(skb)	(CHAIN_NODE(skb)->flags = 0)
-#define	PKTCFLAGS(skb)		(CHAIN_NODE(skb)->flags)
-#define	PKTCSETCNT(skb, c)	(CHAIN_NODE(skb)->pkts = (c))
-#define	PKTCINCRCNT(skb)	(CHAIN_NODE(skb)->pkts++)
-#define	PKTCADDCNT(skb, c)	(CHAIN_NODE(skb)->pkts += (c))
-#define	PKTCSETLEN(skb, l)	(CHAIN_NODE(skb)->bytes = (l))
-#define	PKTCADDLEN(skb, l)	(CHAIN_NODE(skb)->bytes += (l))
-#define	PKTCSETFLAG(skb, fb)	(CHAIN_NODE(skb)->flags |= (fb))
-#define	PKTCCLRFLAG(skb, fb)	(CHAIN_NODE(skb)->flags &= ~(fb))
-#define	PKTCLINK(skb)		(CHAIN_NODE(skb)->link)
-#define	PKTSETCLINK(skb, x)	(CHAIN_NODE(skb)->link = (struct sk_buff*)(x))
-#define FOREACH_CHAINED_PKT(skb, nskb) \
-	for (; (skb) != NULL; (skb) = (nskb)) \
-		if ((nskb) = (PKTISCHAINED(skb) ? PKTCLINK(skb) : NULL), \
-		    PKTSETCLINK((skb), NULL), 1)
-#define	PKTCFREE(osh, skb, send) \
-do { \
-	void *nskb; \
-	ASSERT((skb) != NULL); \
-	FOREACH_CHAINED_PKT((skb), nskb) { \
-		PKTCLRCHAINED((osh), (skb)); \
-		PKTCCLRFLAGS((skb)); \
-		PKTFREE((osh), (skb), (send)); \
-	} \
-} while (0)
-#define PKTCENQTAIL(h, t, p) \
-do { \
-	if ((t) == NULL) { \
-		(h) = (t) = (p); \
-	} else { \
-		PKTSETCLINK((t), (p)); \
-		(t) = (p); \
-	} \
-} while (0)
-#endif /* PKTC */
-
-#else /* ! BCMDRIVER */
-
-
-/* ASSERT */
-	#define ASSERT(exp)	do {} while (0)
-
-/* MALLOC and MFREE */
-#define MALLOC(o, l) malloc(l)
-#define MFREE(o, p, l) free(p)
-#include <stdlib.h>
-
-/* str* and mem* functions */
-#include <string.h>
-
-/* *printf functions */
-#include <stdio.h>
-
-/* bcopy, bcmp, and bzero */
-extern void bcopy(const void *src, void *dst, size_t len);
-extern int bcmp(const void *b1, const void *b2, size_t len);
-extern void bzero(void *b, size_t len);
-#endif /* ! BCMDRIVER */
-
-typedef struct sec_cma_info {
-	struct sec_mem_elem *sec_alloc_list;
-	struct sec_mem_elem *sec_alloc_list_tail;
-} sec_cma_info_t;
-
-/* Current STB 7445D1 doesn't use ACP and it is non-coherrent.
- * Adding these dummy values for build apss only
- * When we revisit need to change these.
- */
-#if defined(STBLINUX)
-
-#if defined(__ARM_ARCH_7A__)
-#define ACP_WAR_ENAB() 0
-#define ACP_WIN_LIMIT 1
-#define arch_is_coherent() 0
-#endif /* __ARM_ARCH_7A__ */
-
-#endif /* STBLINUX */
-
-#ifdef BCM_SECURE_DMA
-
-#define	SECURE_DMA_MAP(osh, va, size, direction, p, dmah, pcma, offset) \
-	osl_sec_dma_map((osh), (va), (size), (direction), (p), (dmah), (pcma), (offset))
-#define	SECURE_DMA_DD_MAP(osh, va, size, direction, p, dmah) \
-	osl_sec_dma_dd_map((osh), (va), (size), (direction), (p), (dmah))
-#define	SECURE_DMA_MAP_TXMETA(osh, va, size, direction, p, dmah, pcma) \
-	osl_sec_dma_map_txmeta((osh), (va), (size), (direction), (p), (dmah), (pcma))
-#define	SECURE_DMA_UNMAP(osh, pa, size, direction, p, dmah, pcma, offset) \
-	osl_sec_dma_unmap((osh), (pa), (size), (direction), (p), (dmah), (pcma), (offset))
-#define	SECURE_DMA_UNMAP_ALL(osh, pcma) \
-	osl_sec_dma_unmap_all((osh), (pcma))
-#if defined(__ARM_ARCH_7A__)
-#define CMA_BUFSIZE_4K	4096
-#define CMA_BUFSIZE_2K	2048
-#define CMA_BUFSIZE_512	512
-
-#define	CMA_BUFNUM		2048
-#define SEC_CMA_COHERENT_BLK 0x8000 /* 32768 */
-#define SEC_CMA_COHERENT_MAX 32
-#define CMA_DMA_DESC_MEMBLOCK	(SEC_CMA_COHERENT_BLK * SEC_CMA_COHERENT_MAX)
-#define CMA_DMA_DATA_MEMBLOCK	(CMA_BUFSIZE_4K*CMA_BUFNUM)
-#define	CMA_MEMBLOCK		(CMA_DMA_DESC_MEMBLOCK + CMA_DMA_DATA_MEMBLOCK)
-#define CONT_ARMREGION	0x02		/* Region CMA */
-#else
-#define CONT_MIPREGION	0x00		/* To access the MIPs mem, Not yet... */
-#endif /* !defined __ARM_ARCH_7A__ */
-
-#define SEC_DMA_ALIGN	(1<<16)
-typedef struct sec_mem_elem {
-	size_t			size;
-	int				direction;
-	phys_addr_t		pa_cma;     /**< physical  address */
-	void			*va;        /**< virtual address of driver pkt */
-	dma_addr_t		dma_handle; /**< bus address assign by linux */
-	void			*vac;       /**< virtual address of cma buffer */
-	struct	sec_mem_elem	*next;
-} sec_mem_elem_t;
-
-extern dma_addr_t osl_sec_dma_map(osl_t *osh, void *va, uint size, int direction, void *p,
-	hnddma_seg_map_t *dmah, void *ptr_cma_info, uint offset);
-extern dma_addr_t osl_sec_dma_dd_map(osl_t *osh, void *va, uint size, int direction, void *p,
-	hnddma_seg_map_t *dmah);
-extern dma_addr_t osl_sec_dma_map_txmeta(osl_t *osh, void *va, uint size,
-  int direction, void *p, hnddma_seg_map_t *dmah, void *ptr_cma_info);
-extern void osl_sec_dma_unmap(osl_t *osh, dma_addr_t dma_handle, uint size, int direction,
-	void *p, hnddma_seg_map_t *map, void *ptr_cma_info, uint offset);
-extern void osl_sec_dma_unmap_all(osl_t *osh, void *ptr_cma_info);
-
-#endif /* BCM_SECURE_DMA */
-
-typedef struct sk_buff_head PKT_LIST;
-#define PKTLIST_INIT(x)		skb_queue_head_init((x))
-#define PKTLIST_ENQ(x, y)	skb_queue_head((struct sk_buff_head *)(x), (struct sk_buff *)(y))
-#define PKTLIST_DEQ(x)		skb_dequeue((struct sk_buff_head *)(x))
-#define PKTLIST_UNLINK(x, y)	skb_unlink((struct sk_buff *)(y), (struct sk_buff_head *)(x))
-#define PKTLIST_FINI(x)		skb_queue_purge((struct sk_buff_head *)(x))
-
-#endif	/* _linux_osl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h
deleted file mode 100644
index 7fa3e7b..0000000
--- a/drivers/net/wireless/bcmdhd/include/linuxver.h
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * Linux-specific abstractions to gain some independence from linux kernel versions.
- * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: linuxver.h 604758 2015-12-08 12:01:08Z $
- */
-
-#ifndef _linuxver_h_
-#define _linuxver_h_
-
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
-#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
-#endif
-
-#include <typedefs.h>
-#include <linux/version.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-#include <linux/config.h>
-#else
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
-#include <generated/autoconf.h>
-#else
-#include <linux/autoconf.h>
-#endif
-#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
-#include <linux/kconfig.h>
-#endif
-#include <linux/module.h>
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0))
-/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */
-#ifdef __UNDEF_NO_VERSION__
-#undef __NO_VERSION__
-#else
-#define __NO_VERSION__
-#endif
-#endif	/* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
-#define module_param(_name_, _type_, _perm_)	MODULE_PARM(_name_, "i")
-#define module_param_string(_name_, _string_, _size_, _perm_) \
-		MODULE_PARM(_string_, "c" __MODULE_STRING(_size_))
-#endif
-
-/* linux/malloc.h is deprecated, use linux/slab.h instead. */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9))
-#include <linux/malloc.h>
-#else
-#include <linux/slab.h>
-#endif
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/kthread.h>
-#include <linux/netdevice.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-#include <linux/semaphore.h>
-#else
-#include <asm/semaphore.h>
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
-#undef IP_TOS
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) */
-#include <asm/io.h>
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41))
-#include <linux/workqueue.h>
-#else
-#include <linux/tqueue.h>
-#ifndef work_struct
-#define work_struct tq_struct
-#endif
-#ifndef INIT_WORK
-#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data))
-#endif
-#ifndef schedule_work
-#define schedule_work(_work) schedule_task((_work))
-#endif
-#ifndef flush_scheduled_work
-#define flush_scheduled_work() flush_scheduled_tasks()
-#endif
-#endif	/* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-#define DAEMONIZE(a)	do { \
-		allow_signal(SIGKILL);	\
-		allow_signal(SIGTERM);	\
-	} while (0)
-#elif ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && \
-	(LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)))
-#define DAEMONIZE(a) daemonize(a); \
-	allow_signal(SIGKILL); \
-	allow_signal(SIGTERM);
-#else /* Linux 2.4 (w/o preemption patch) */
-#define RAISE_RX_SOFTIRQ() \
-	cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
-#define DAEMONIZE(a) daemonize(); \
-	do { if (a) \
-		strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a)))); \
-	} while (0);
-#endif /* LINUX_VERSION_CODE  */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
-#define	MY_INIT_WORK(_work, _func)	INIT_WORK(_work, _func)
-#else
-#define	MY_INIT_WORK(_work, _func)	INIT_WORK(_work, _func, _work)
-#if !(LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18) && defined(RHEL_MAJOR) && \
-	(RHEL_MAJOR == 5))
-/* Exclude RHEL 5 */
-typedef void (*work_func_t)(void *work);
-#endif
-#endif	/* >= 2.6.20 */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-/* Some distributions have their own 2.6.x compatibility layers */
-#ifndef IRQ_NONE
-typedef void irqreturn_t;
-#define IRQ_NONE
-#define IRQ_HANDLED
-#define IRQ_RETVAL(x)
-#endif
-#else
-typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
-#endif	/* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
-#define IRQF_SHARED	SA_SHIRQ
-#endif /* < 2.6.18 */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
-#ifdef	CONFIG_NET_RADIO
-#define	CONFIG_WIRELESS_EXT
-#endif
-#endif	/* < 2.6.17 */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67)
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
-#include <linux/sched.h>
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
-#include <linux/sched/rt.h>
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
-#include <net/lib80211.h>
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
-#include <linux/ieee80211.h>
-#else
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
-#include <net/ieee80211.h>
-#endif
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */
-
-
-#ifndef __exit
-#define __exit
-#endif
-#ifndef __devexit
-#define __devexit
-#endif
-#ifndef __devinit
-#  if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
-#    define __devinit	__init
-#  else
-/* All devices are hotpluggable since linux 3.8.0 */
-#    define __devinit
-#  endif
-#endif /* !__devinit */
-#ifndef __devinitdata
-#define __devinitdata
-#endif
-#ifndef __devexit_p
-#define __devexit_p(x)	x
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0))
-
-#define pci_get_drvdata(dev)		(dev)->sysdata
-#define pci_set_drvdata(dev, value)	(dev)->sysdata = (value)
-
-/*
- * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration
- */
-
-struct pci_device_id {
-	unsigned int vendor, device;		/* Vendor and device ID or PCI_ANY_ID */
-	unsigned int subvendor, subdevice;	/* Subsystem ID's or PCI_ANY_ID */
-	unsigned int class, class_mask;		/* (class,subclass,prog-if) triplet */
-	unsigned long driver_data;		/* Data private to the driver */
-};
-
-struct pci_driver {
-	struct list_head node;
-	char *name;
-	const struct pci_device_id *id_table;	/* NULL if wants all devices */
-	int (*probe)(struct pci_dev *dev,
-	             const struct pci_device_id *id); /* New device inserted */
-	void (*remove)(struct pci_dev *dev);	/* Device removed (NULL if not a hot-plug
-						 * capable driver)
-						 */
-	void (*suspend)(struct pci_dev *dev);	/* Device suspended */
-	void (*resume)(struct pci_dev *dev);	/* Device woken up */
-};
-
-#define MODULE_DEVICE_TABLE(type, name)
-#define PCI_ANY_ID (~0)
-
-/* compatpci.c */
-#define pci_module_init pci_register_driver
-extern int pci_register_driver(struct pci_driver *drv);
-extern void pci_unregister_driver(struct pci_driver *drv);
-
-#endif /* PCI registration */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18))
-#define pci_module_init pci_register_driver
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18))
-#ifdef MODULE
-#define module_init(x) int init_module(void) { return x(); }
-#define module_exit(x) void cleanup_module(void) { x(); }
-#else
-#define module_init(x)	__initcall(x);
-#define module_exit(x)	__exitcall(x);
-#endif
-#endif	/* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
-#define WL_USE_NETDEV_OPS
-#else
-#undef WL_USE_NETDEV_OPS
-#endif
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL)
-#define WL_CONFIG_RFKILL
-#else
-#undef WL_CONFIG_RFKILL
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48))
-#define list_for_each(pos, head) \
-	for (pos = (head)->next; pos != (head); pos = pos->next)
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13))
-#define pci_resource_start(dev, bar)	((dev)->base_address[(bar)])
-#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44))
-#define pci_resource_start(dev, bar)	((dev)->resource[(bar)].start)
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23))
-#define pci_enable_device(dev) do { } while (0)
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14))
-#define net_device device
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42))
-
-/*
- * DMA mapping
- *
- * See linux/Documentation/DMA-mapping.txt
- */
-
-#ifndef PCI_DMA_TODEVICE
-#define	PCI_DMA_TODEVICE	1
-#define	PCI_DMA_FROMDEVICE	2
-#endif
-
-typedef u32 dma_addr_t;
-
-/* Pure 2^n version of get_order */
-static inline int get_order(unsigned long size)
-{
-	int order;
-
-	size = (size-1) >> (PAGE_SHIFT-1);
-	order = -1;
-	do {
-		size >>= 1;
-		order++;
-	} while (size);
-	return order;
-}
-
-static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                                         dma_addr_t *dma_handle)
-{
-	void *ret;
-	int gfp = GFP_ATOMIC | GFP_DMA;
-
-	ret = (void *)__get_free_pages(gfp, get_order(size));
-
-	if (ret != NULL) {
-		memset(ret, 0, size);
-		*dma_handle = virt_to_bus(ret);
-	}
-	return ret;
-}
-static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                                       void *vaddr, dma_addr_t dma_handle)
-{
-	free_pages((unsigned long)vaddr, get_order(size));
-}
-#define pci_map_single(cookie, address, size, dir)	virt_to_bus(address)
-#define pci_unmap_single(cookie, address, size, dir)
-
-#endif /* DMA mapping */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43))
-
-#define dev_kfree_skb_any(a)		dev_kfree_skb(a)
-#define netif_down(dev)			do { (dev)->start = 0; } while (0)
-
-/* pcmcia-cs provides its own netdevice compatibility layer */
-#ifndef _COMPAT_NETDEVICE_H
-
-/*
- * SoftNet
- *
- * For pre-softnet kernels we need to tell the upper layer not to
- * re-enter start_xmit() while we are in there. However softnet
- * guarantees not to enter while we are in there so there is no need
- * to do the netif_stop_queue() dance unless the transmit queue really
- * gets stuck. This should also improve performance according to tests
- * done by Aman Singla.
- */
-
-#define dev_kfree_skb_irq(a)	dev_kfree_skb(a)
-#define netif_wake_queue(dev) \
-		do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0)
-#define netif_stop_queue(dev)	set_bit(0, &(dev)->tbusy)
-
-static inline void netif_start_queue(struct net_device *dev)
-{
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-}
-
-#define netif_queue_stopped(dev)	(dev)->tbusy
-#define netif_running(dev)		(dev)->start
-
-#endif /* _COMPAT_NETDEVICE_H */
-
-#define netif_device_attach(dev)	netif_start_queue(dev)
-#define netif_device_detach(dev)	netif_stop_queue(dev)
-
-/* 2.4.x renamed bottom halves to tasklets */
-#define tasklet_struct				tq_struct
-static inline void tasklet_schedule(struct tasklet_struct *tasklet)
-{
-	queue_task(tasklet, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-}
-
-static inline void tasklet_init(struct tasklet_struct *tasklet,
-                                void (*func)(unsigned long),
-                                unsigned long data)
-{
-	tasklet->next = NULL;
-	tasklet->sync = 0;
-	tasklet->routine = (void (*)(void *))func;
-	tasklet->data = (void *)data;
-}
-#define tasklet_kill(tasklet)	{ do {} while (0); }
-
-/* 2.4.x introduced del_timer_sync() */
-#define del_timer_sync(timer) del_timer(timer)
-
-#else
-
-#define netif_down(dev)
-
-#endif /* SoftNet */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3))
-
-/*
- * Emit code to initialise a tq_struct's routine and data pointers
- */
-#define PREPARE_TQUEUE(_tq, _routine, _data)			\
-	do {							\
-		(_tq)->routine = _routine;			\
-		(_tq)->data = _data;				\
-	} while (0)
-
-/*
- * Emit code to initialise all of a tq_struct
- */
-#define INIT_TQUEUE(_tq, _routine, _data)			\
-	do {							\
-		INIT_LIST_HEAD(&(_tq)->list);			\
-		(_tq)->sync = 0;				\
-		PREPARE_TQUEUE((_tq), (_routine), (_data));	\
-	} while (0)
-
-#endif	/* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */
-
-/* Power management related macro & routines */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9)
-#define	PCI_SAVE_STATE(a, b)	pci_save_state(a)
-#define	PCI_RESTORE_STATE(a, b)	pci_restore_state(a)
-#else
-#define	PCI_SAVE_STATE(a, b)	pci_save_state(a, b)
-#define	PCI_RESTORE_STATE(a, b)	pci_restore_state(a, b)
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6))
-static inline int
-pci_save_state(struct pci_dev *dev, u32 *buffer)
-{
-	int i;
-	if (buffer) {
-		for (i = 0; i < 16; i++)
-			pci_read_config_dword(dev, i * 4, &buffer[i]);
-	}
-	return 0;
-}
-
-static inline int
-pci_restore_state(struct pci_dev *dev, u32 *buffer)
-{
-	int i;
-
-	if (buffer) {
-		for (i = 0; i < 16; i++)
-			pci_write_config_dword(dev, i * 4, buffer[i]);
-	}
-	/*
-	 * otherwise, write the context information we know from bootup.
-	 * This works around a problem where warm-booting from Windows
-	 * combined with a D3(hot)->D0 transition causes PCI config
-	 * header data to be forgotten.
-	 */
-	else {
-		for (i = 0; i < 6; i ++)
-			pci_write_config_dword(dev,
-			                       PCI_BASE_ADDRESS_0 + (i * 4),
-			                       pci_resource_start(dev, i));
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
-	return 0;
-}
-#endif /* PCI power management */
-
-/* Old cp0 access macros deprecated in 2.4.19 */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19))
-#define read_c0_count() read_32bit_cp0_register(CP0_COUNT)
-#endif
-
-/* Module refcount handled internally in 2.6.x */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
-#ifndef SET_MODULE_OWNER
-#define SET_MODULE_OWNER(dev)		do {} while (0)
-#define OLD_MOD_INC_USE_COUNT		MOD_INC_USE_COUNT
-#define OLD_MOD_DEC_USE_COUNT		MOD_DEC_USE_COUNT
-#else
-#define OLD_MOD_INC_USE_COUNT		do {} while (0)
-#define OLD_MOD_DEC_USE_COUNT		do {} while (0)
-#endif
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */
-#ifndef SET_MODULE_OWNER
-#define SET_MODULE_OWNER(dev)		do {} while (0)
-#endif
-#ifndef MOD_INC_USE_COUNT
-#define MOD_INC_USE_COUNT			do {} while (0)
-#endif
-#ifndef MOD_DEC_USE_COUNT
-#define MOD_DEC_USE_COUNT			do {} while (0)
-#endif
-#define OLD_MOD_INC_USE_COUNT		MOD_INC_USE_COUNT
-#define OLD_MOD_DEC_USE_COUNT		MOD_DEC_USE_COUNT
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */
-
-#ifndef SET_NETDEV_DEV
-#define SET_NETDEV_DEV(net, pdev)	do {} while (0)
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
-#ifndef HAVE_FREE_NETDEV
-#define free_netdev(dev)		kfree(dev)
-#endif
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-/* struct packet_type redefined in 2.6.x */
-#define af_packet_priv			data
-#endif
-
-/* suspend args */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
-#define DRV_SUSPEND_STATE_TYPE pm_message_t
-#else
-#define DRV_SUSPEND_STATE_TYPE uint32
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
-#define CHECKSUM_HW	CHECKSUM_PARTIAL
-#endif
-
-typedef struct {
-	void	*parent;  /* some external entity that the thread supposed to work for */
-	char	*proc_name;
-	struct	task_struct *p_task;
-	long	thr_pid;
-	int		prio; /* priority */
-	struct	semaphore sema;
-	int	terminated;
-	struct	completion completed;
-	spinlock_t	spinlock;
-	int		up_cnt;
-} tsk_ctl_t;
-
-
-/* requires  tsk_ctl_t tsk  argument, the caller's priv data is passed in owner ptr */
-/* note this macro assumes there may be only one context waiting on thread's completion */
-#ifdef DHD_DEBUG
-#define DBG_THR(x) printk x
-#else
-#define DBG_THR(x)
-#endif
-
-static inline bool binary_sema_down(tsk_ctl_t *tsk)
-{
-	if (down_interruptible(&tsk->sema) == 0) {
-		unsigned long flags = 0;
-		spin_lock_irqsave(&tsk->spinlock, flags);
-		if (tsk->up_cnt == 1)
-			tsk->up_cnt--;
-		else {
-			DBG_THR(("dhd_dpc_thread: Unexpected up_cnt %d\n", tsk->up_cnt));
-		}
-		spin_unlock_irqrestore(&tsk->spinlock, flags);
-		return false;
-	} else
-		return true;
-}
-
-static inline bool binary_sema_up(tsk_ctl_t *tsk)
-{
-	bool sem_up = false;
-	unsigned long flags = 0;
-
-	spin_lock_irqsave(&tsk->spinlock, flags);
-	if (tsk->up_cnt == 0) {
-		tsk->up_cnt++;
-		sem_up = true;
-	} else if (tsk->up_cnt == 1) {
-		/* dhd_sched_dpc: dpc is alread up! */
-	} else
-		DBG_THR(("dhd_sched_dpc: unexpected up cnt %d!\n", tsk->up_cnt));
-
-	spin_unlock_irqrestore(&tsk->spinlock, flags);
-
-	if (sem_up)
-		up(&tsk->sema);
-
-	return sem_up;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x)
-#else
-#define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x)
-#endif
-
-#define PROC_START(thread_func, owner, tsk_ctl, flags, name) \
-{ \
-	sema_init(&((tsk_ctl)->sema), 0); \
-	init_completion(&((tsk_ctl)->completed)); \
-	(tsk_ctl)->parent = owner; \
-	(tsk_ctl)->proc_name = name;  \
-	(tsk_ctl)->terminated = FALSE; \
-	(tsk_ctl)->p_task  = kthread_run(thread_func, tsk_ctl, (char*)name); \
-	if (IS_ERR((tsk_ctl)->p_task)) { \
-		(tsk_ctl)->thr_pid = DHD_PID_KT_INVALID; \
-		DBG_THR(("%s(): thread:%s:%lx failed\n", __FUNCTION__, \
-			(tsk_ctl)->proc_name, (tsk_ctl)->thr_pid)); \
-	} else { \
-		(tsk_ctl)->thr_pid = (tsk_ctl)->p_task->pid; \
-		spin_lock_init(&((tsk_ctl)->spinlock)); \
-		DBG_THR(("%s(): thread:%s:%lx started\n", __FUNCTION__, \
-			(tsk_ctl)->proc_name, (tsk_ctl)->thr_pid)); \
-	} \
-}
-
-#define PROC_STOP(tsk_ctl) \
-{ \
-	(tsk_ctl)->terminated = TRUE; \
-	smp_wmb(); \
-	up(&((tsk_ctl)->sema));	\
-	wait_for_completion(&((tsk_ctl)->completed)); \
-	DBG_THR(("%s(): thread:%s:%lx terminated OK\n", __FUNCTION__, \
-			 (tsk_ctl)->proc_name, (tsk_ctl)->thr_pid)); \
-	(tsk_ctl)->thr_pid = -1; \
-}
-
-/*  ----------------------- */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
-#define KILL_PROC(nr, sig) \
-{ \
-struct task_struct *tsk; \
-struct pid *pid;    \
-pid = find_get_pid((pid_t)nr);    \
-tsk = pid_task(pid, PIDTYPE_PID);    \
-if (tsk) send_sig(sig, tsk, 1); \
-}
-#else
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
-	KERNEL_VERSION(2, 6, 30))
-#define KILL_PROC(pid, sig) \
-{ \
-	struct task_struct *tsk; \
-	tsk = find_task_by_vpid(pid); \
-	if (tsk) send_sig(sig, tsk, 1); \
-}
-#else
-#define KILL_PROC(pid, sig) \
-{ \
-	kill_proc(pid, sig, 1); \
-}
-#endif
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-#include <linux/time.h>
-#include <linux/wait.h>
-#else
-#include <linux/sched.h>
-
-#define __wait_event_interruptible_timeout(wq, condition, ret)		\
-do {									\
-	wait_queue_t __wait;						\
-	init_waitqueue_entry(&__wait, current);				\
-									\
-	add_wait_queue(&wq, &__wait);					\
-	for (;;) {							\
-		set_current_state(TASK_INTERRUPTIBLE);			\
-		if (condition)						\
-			break;						\
-		if (!signal_pending(current)) {				\
-			ret = schedule_timeout(ret);			\
-			if (!ret)					\
-				break;					\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		break;							\
-	}								\
-	current->state = TASK_RUNNING;					\
-	remove_wait_queue(&wq, &__wait);				\
-} while (0)
-
-#define wait_event_interruptible_timeout(wq, condition, timeout)	\
-({									\
-	long __ret = timeout;						\
-	if (!(condition))						\
-		__wait_event_interruptible_timeout(wq, condition, __ret); \
-	__ret;								\
-})
-
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */
-
-/*
-For < 2.6.24, wl creates its own netdev but doesn't
-align the priv area like the genuine alloc_netdev().
-Since netdev_priv() always gives us the aligned address, it will
-not match our unaligned address for < 2.6.24
-*/
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
-#define DEV_PRIV(dev)	(dev->priv)
-#else
-#define DEV_PRIV(dev)	netdev_priv(dev)
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
-#define WL_ISR(i, d, p)         wl_isr((i), (d))
-#else
-#define WL_ISR(i, d, p)         wl_isr((i), (d), (p))
-#endif  /* < 2.6.20 */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
-#define netdev_priv(dev) dev->priv
-#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-#define CAN_SLEEP()	((!in_atomic() && !irqs_disabled()))
-#else
-#define CAN_SLEEP()	(FALSE)
-#endif
-
-#define KMALLOC_FLAG (CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC)
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-#define RANDOM32	prandom_u32
-#else
-#define RANDOM32	random32
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-#define SRANDOM32(entropy)	prandom_seed(entropy)
-#else
-#define SRANDOM32(entropy)	srandom32(entropy)
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */
-
-/*
- * Overide latest kfifo functions with
- * older version to work on older kernels
- */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
-#define kfifo_in_spinlocked(a, b, c, d)		kfifo_put(a, (u8 *)b, c)
-#define kfifo_out_spinlocked(a, b, c, d)	kfifo_get(a, (u8 *)b, c)
-#define kfifo_esize(a)				1
-#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)) && \
-	(LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)) &&	!defined(WL_COMPAT_WIRELESS)
-#define kfifo_in_spinlocked(a, b, c, d)		kfifo_in_locked(a, b, c, d)
-#define kfifo_out_spinlocked(a, b, c, d)	kfifo_out_locked(a, b, c, d)
-#define kfifo_esize(a)				1
-#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) */
-
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
-#pragma GCC diagnostic pop
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-static inline struct inode *file_inode(const struct file *f)
-{
-	return f->f_dentry->d_inode;
-}
-#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) */
-
-#endif /* _linuxver_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/miniopt.h b/drivers/net/wireless/bcmdhd/include/miniopt.h
deleted file mode 100644
index 2eb6d18..0000000
--- a/drivers/net/wireless/bcmdhd/include/miniopt.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Command line options parser.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: miniopt.h 514727 2014-11-12 03:02:48Z $
- */
-
-
-#ifndef MINI_OPT_H
-#define MINI_OPT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* ---- Include Files ---------------------------------------------------- */
-
-
-/* ---- Constants and Types ---------------------------------------------- */
-
-#define MINIOPT_MAXKEY	128	/* Max options */
-typedef struct miniopt {
-
-	/* These are persistent after miniopt_init() */
-	const char* name;		/* name for prompt in error strings */
-	const char* flags;		/* option chars that take no args */
-	bool longflags;		/* long options may be flags */
-	bool opt_end;		/* at end of options (passed a "--") */
-
-	/* These are per-call to miniopt() */
-
-	int consumed;		/* number of argv entries cosumed in
-				 * the most recent call to miniopt()
-				 */
-	bool positional;
-	bool good_int;		/* 'val' member is the result of a sucessful
-				 * strtol conversion of the option value
-				 */
-	char opt;
-	char key[MINIOPT_MAXKEY];
-	char* valstr;		/* positional param, or value for the option,
-				 * or null if the option had
-				 * no accompanying value
-				 */
-	uint uval;		/* strtol translation of valstr */
-	int  val;		/* strtol translation of valstr */
-} miniopt_t;
-
-void miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags);
-int miniopt(miniopt_t *t, char **argv);
-
-
-/* ---- Variable Externs ------------------------------------------------- */
-/* ---- Function Prototypes ---------------------------------------------- */
-
-
-#ifdef __cplusplus
-	}
-#endif
-
-#endif  /* MINI_OPT_H  */
diff --git a/drivers/net/wireless/bcmdhd/include/msgtrace.h b/drivers/net/wireless/bcmdhd/include/msgtrace.h
deleted file mode 100644
index 0d67000..0000000
--- a/drivers/net/wireless/bcmdhd/include/msgtrace.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Trace messages sent over HBUS
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: msgtrace.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_MSGTRACE_H
-#define	_MSGTRACE_H
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-/* for osl_t */
-#include <osl_decl.h>
-#define MSGTRACE_VERSION 1
-
-/* Message trace header */
-typedef BWL_PRE_PACKED_STRUCT struct msgtrace_hdr {
-	uint8	version;
-	uint8   trace_type;
-#define MSGTRACE_HDR_TYPE_MSG 0
-#define MSGTRACE_HDR_TYPE_LOG 1
-	uint16	len;	/* Len of the trace */
-	uint32	seqnum;	/* Sequence number of message. Useful if the messsage has been lost
-			 * because of DMA error or a bus reset (ex: SDIO Func2)
-			 */
-	/* Msgtrace type  only */
-	uint32  discarded_bytes;  /* Number of discarded bytes because of trace overflow  */
-	uint32  discarded_printf; /* Number of discarded printf because of trace overflow */
-} BWL_POST_PACKED_STRUCT msgtrace_hdr_t;
-
-#define MSGTRACE_HDRLEN 	sizeof(msgtrace_hdr_t)
-
-/* The hbus driver generates traces when sending a trace message. This causes endless traces.
- * This flag must be set to TRUE in any hbus traces. The flag is reset in the function msgtrace_put.
- * This prevents endless traces but generates hasardous lost of traces only in bus device code.
- * It is recommendat to set this flag in macro SD_TRACE but not in SD_ERROR for avoiding missing
- * hbus error traces. hbus error trace should not generates endless traces.
- */
-extern bool msgtrace_hbus_trace;
-
-typedef void (*msgtrace_func_send_t)(void *hdl1, void *hdl2, uint8 *hdr,
-                                     uint16 hdrlen, uint8 *buf, uint16 buflen);
-extern void msgtrace_start(void);
-extern void msgtrace_stop(void);
-extern int msgtrace_sent(void);
-extern void msgtrace_put(char *buf, int count);
-extern void msgtrace_init(void *hdl1, void *hdl2, msgtrace_func_send_t func_send);
-extern bool msgtrace_event_enabled(void);
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif	/* _MSGTRACE_H */
diff --git a/drivers/net/wireless/bcmdhd/include/osl.h b/drivers/net/wireless/bcmdhd/include/osl.h
deleted file mode 100644
index 8a00f9d..0000000
--- a/drivers/net/wireless/bcmdhd/include/osl.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * OS Abstraction Layer
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: osl.h 526460 2015-01-14 08:25:24Z $
- */
-
-#ifndef _osl_h_
-#define _osl_h_
-
-#include <osl_decl.h>
-
-#define OSL_PKTTAG_SZ	32 /* Size of PktTag */
-
-/* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */
-typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status);
-
-/* Drivers use REGOPSSET() to register register read/write funcitons */
-typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size);
-typedef void  (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size);
-
-
-
-#if defined(WL_UNITTEST)
-#include <utest_osl.h>
-#else
-#include <linux_osl.h>
-#endif 
-
-#ifndef PKTDBG_TRACE
-#define PKTDBG_TRACE(osh, pkt, bit)	BCM_REFERENCE(osh)
-#endif
-
-#define PKTCTFMAP(osh, p)		BCM_REFERENCE(osh)
-
-/* --------------------------------------------------------------------------
-** Register manipulation macros.
-*/
-
-#define	SET_REG(osh, r, mask, val)	W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val)))
-
-#ifndef AND_REG
-#define AND_REG(osh, r, v)		W_REG(osh, (r), R_REG(osh, r) & (v))
-#endif   /* !AND_REG */
-
-#ifndef OR_REG
-#define OR_REG(osh, r, v)		W_REG(osh, (r), R_REG(osh, r) | (v))
-#endif   /* !OR_REG */
-
-#if !defined(OSL_SYSUPTIME)
-#define OSL_SYSUPTIME() (0)
-#define OSL_SYSUPTIME_SUPPORT FALSE
-#else
-#define OSL_SYSUPTIME_SUPPORT TRUE
-#endif /* OSL_SYSUPTIME */
-
-#ifndef OSL_SYS_HALT
-#define OSL_SYS_HALT()	do {} while (0)
-#endif
-
-#ifndef OSL_MEM_AVAIL
-#define OSL_MEM_AVAIL()	(0xffffffff)
-#endif
-
-#if !defined(PKTC) && !defined(PKTC_DONGLE)
-#define	PKTCGETATTR(skb)	(0)
-#define	PKTCSETATTR(skb, f, p, b) BCM_REFERENCE(skb)
-#define	PKTCCLRATTR(skb)	BCM_REFERENCE(skb)
-#define	PKTCCNT(skb)		(1)
-#define	PKTCLEN(skb)		PKTLEN(NULL, skb)
-#define	PKTCGETFLAGS(skb)	(0)
-#define	PKTCSETFLAGS(skb, f)	BCM_REFERENCE(skb)
-#define	PKTCCLRFLAGS(skb)	BCM_REFERENCE(skb)
-#define	PKTCFLAGS(skb)		(0)
-#define	PKTCSETCNT(skb, c)	BCM_REFERENCE(skb)
-#define	PKTCINCRCNT(skb)	BCM_REFERENCE(skb)
-#define	PKTCADDCNT(skb, c)	BCM_REFERENCE(skb)
-#define	PKTCSETLEN(skb, l)	BCM_REFERENCE(skb)
-#define	PKTCADDLEN(skb, l)	BCM_REFERENCE(skb)
-#define	PKTCSETFLAG(skb, fb)	BCM_REFERENCE(skb)
-#define	PKTCCLRFLAG(skb, fb)	BCM_REFERENCE(skb)
-#define	PKTCLINK(skb)		NULL
-#define	PKTSETCLINK(skb, x)	BCM_REFERENCE(skb)
-#define FOREACH_CHAINED_PKT(skb, nskb) \
-	for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb))
-#define	PKTCFREE		PKTFREE
-#define PKTCENQTAIL(h, t, p) \
-do { \
-	if ((t) == NULL) { \
-		(h) = (t) = (p); \
-	} \
-} while (0)
-#endif /* !linux || !PKTC */
-
-#if !defined(HNDCTF) && !defined(PKTC_TX_DONGLE)
-#define PKTSETCHAINED(osh, skb)		BCM_REFERENCE(osh)
-#define PKTCLRCHAINED(osh, skb)		BCM_REFERENCE(osh)
-#define PKTISCHAINED(skb)		FALSE
-#endif
-
-/* Lbuf with fraglist */
-#define PKTFRAGPKTID(osh, lb)		(0)
-#define PKTSETFRAGPKTID(osh, lb, id)	BCM_REFERENCE(osh)
-#define PKTFRAGTOTNUM(osh, lb)		(0)
-#define PKTSETFRAGTOTNUM(osh, lb, tot)	BCM_REFERENCE(osh)
-#define PKTFRAGTOTLEN(osh, lb)		(0)
-#define PKTSETFRAGTOTLEN(osh, lb, len)	BCM_REFERENCE(osh)
-#define PKTIFINDEX(osh, lb)		(0)
-#define PKTSETIFINDEX(osh, lb, idx)	BCM_REFERENCE(osh)
-#define	PKTGETLF(osh, len, send, lbuf_type)	(0)
-
-/* in rx path, reuse totlen as used len */
-#define PKTFRAGUSEDLEN(osh, lb)			(0)
-#define PKTSETFRAGUSEDLEN(osh, lb, len)		BCM_REFERENCE(osh)
-
-#define PKTFRAGLEN(osh, lb, ix)			(0)
-#define PKTSETFRAGLEN(osh, lb, ix, len)		BCM_REFERENCE(osh)
-#define PKTFRAGDATA_LO(osh, lb, ix)		(0)
-#define PKTSETFRAGDATA_LO(osh, lb, ix, addr)	BCM_REFERENCE(osh)
-#define PKTFRAGDATA_HI(osh, lb, ix)		(0)
-#define PKTSETFRAGDATA_HI(osh, lb, ix, addr)	BCM_REFERENCE(osh)
-
-/* RX FRAG */
-#define PKTISRXFRAG(osh, lb)    	(0)
-#define PKTSETRXFRAG(osh, lb)		BCM_REFERENCE(osh)
-#define PKTRESETRXFRAG(osh, lb)		BCM_REFERENCE(osh)
-
-/* TX FRAG */
-#define PKTISTXFRAG(osh, lb)		(0)
-#define PKTSETTXFRAG(osh, lb)		BCM_REFERENCE(osh)
-
-/* Need Rx completion used for AMPDU reordering */
-#define PKTNEEDRXCPL(osh, lb)           (TRUE)
-#define PKTSETNORXCPL(osh, lb)          BCM_REFERENCE(osh)
-#define PKTRESETNORXCPL(osh, lb)        BCM_REFERENCE(osh)
-
-#define PKTISFRAG(osh, lb)		(0)
-#define PKTFRAGISCHAINED(osh, i)	(0)
-/* TRIM Tail bytes from lfrag */
-#define PKTFRAG_TRIM_TAILBYTES(osh, p, len, type)	PKTSETLEN(osh, p, PKTLEN(osh, p) - len)
-
-#ifdef BCM_SECURE_DMA
-#define SECURE_DMA_ENAB(osh) (1)
-#else
-
-#define SECURE_DMA_ENAB(osh) (0)
-#define	SECURE_DMA_MAP(osh, va, size, direction, p, dmah, pcma, offset) ((dmaaddr_t) {(0)})
-#define	SECURE_DMA_DD_MAP(osh, va, size, direction, p, dmah) 0
-#define	SECURE_DMA_MAP_TXMETA(osh, va, size, direction, p, dmah, pcma) ((dmaaddr_t) {(0)})
-#define	SECURE_DMA_UNMAP(osh, pa, size, direction, p, dmah, pcma, offset)
-#define	SECURE_DMA_UNMAP_ALL(osh, pcma)
-
-#endif
-
-
-#endif	/* _osl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/osl_decl.h b/drivers/net/wireless/bcmdhd/include/osl_decl.h
deleted file mode 100644
index 6c8d86e..0000000
--- a/drivers/net/wireless/bcmdhd/include/osl_decl.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * osl forward declarations
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: osl_decl.h 591283 2015-10-07 11:52:00Z $
- */
-
-#ifndef _osl_decl_h_
-#define _osl_decl_h_
-
-/* osl handle type forward declaration */
-typedef struct osl_info osl_t;
-typedef struct osl_dmainfo osldma_t;
-extern unsigned int lmtest; /* low memory test */
-#endif
diff --git a/drivers/net/wireless/bcmdhd/include/osl_ext.h b/drivers/net/wireless/bcmdhd/include/osl_ext.h
deleted file mode 100644
index 61984e6..0000000
--- a/drivers/net/wireless/bcmdhd/include/osl_ext.h
+++ /dev/null
@@ -1,697 +0,0 @@
-/*
- * OS Abstraction Layer Extension - the APIs defined by the "extension" API
- * are only supported by a subset of all operating systems.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: osl_ext.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef _osl_ext_h_
-#define _osl_ext_h_
-
-
-/* ---- Include Files ---------------------------------------------------- */
-
-#if defined(TARGETOS_symbian)
-	#include <e32def.h>
-	#include <symbian_osl_ext.h>
-#elif defined(THREADX)
-	#include <threadx_osl_ext.h>
-#else
-	#define OSL_EXT_DISABLED
-#endif
-
-/* Include base operating system abstraction. */
-#include <osl.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* ---- Constants and Types ---------------------------------------------- */
-
-/* -----------------------------------------------------------------------
- * Generic OS types.
- */
-typedef enum osl_ext_status_t
-{
-	OSL_EXT_SUCCESS,
-	OSL_EXT_ERROR,
-	OSL_EXT_TIMEOUT
-
-} osl_ext_status_t;
-#define OSL_EXT_STATUS_DECL(status)	osl_ext_status_t status;
-
-#define OSL_EXT_TIME_FOREVER ((osl_ext_time_ms_t)(-1))
-typedef unsigned int osl_ext_time_ms_t;
-
-typedef unsigned int osl_ext_event_bits_t;
-
-typedef unsigned int osl_ext_interrupt_state_t;
-
-/* -----------------------------------------------------------------------
- * Timers.
- */
-typedef enum
-{
-	/* One-shot timer. */
-	OSL_EXT_TIMER_MODE_ONCE,
-
-	/* Periodic timer. */
-	OSL_EXT_TIMER_MODE_REPEAT
-
-} osl_ext_timer_mode_t;
-
-/* User registered callback and parameter to invoke when timer expires. */
-typedef void* osl_ext_timer_arg_t;
-typedef void (*osl_ext_timer_callback)(osl_ext_timer_arg_t arg);
-
-
-/* -----------------------------------------------------------------------
- * Tasks.
- */
-
-/* Task entry argument. */
-typedef void* osl_ext_task_arg_t;
-
-/* Task entry function. */
-typedef void (*osl_ext_task_entry)(osl_ext_task_arg_t arg);
-
-/* Abstract task priority levels. */
-typedef enum
-{
-	OSL_EXT_TASK_IDLE_PRIORITY,
-	OSL_EXT_TASK_LOW_PRIORITY,
-	OSL_EXT_TASK_LOW_NORMAL_PRIORITY,
-	OSL_EXT_TASK_NORMAL_PRIORITY,
-	OSL_EXT_TASK_HIGH_NORMAL_PRIORITY,
-	OSL_EXT_TASK_HIGHEST_PRIORITY,
-	OSL_EXT_TASK_TIME_CRITICAL_PRIORITY,
-
-	/* This must be last. */
-	OSL_EXT_TASK_NUM_PRIORITES
-} osl_ext_task_priority_t;
-
-
-#ifndef OSL_EXT_DISABLED
-
-/* ---- Variable Externs ------------------------------------------------- */
-/* ---- Function Prototypes ---------------------------------------------- */
-
-
-/* --------------------------------------------------------------------------
-** Semaphore
-*/
-
-/****************************************************************************
-* Function:   osl_ext_sem_create
-*
-* Purpose:    Creates a counting semaphore object, which can subsequently be
-*             used for thread notification.
-*
-* Parameters: name     (in)  Name to assign to the semaphore (must be unique).
-*             init_cnt (in)  Initial count that the semaphore should have.
-*             sem      (out) Newly created semaphore.
-*
-* Returns:    OSL_EXT_SUCCESS if the semaphore was created successfully, or an
-*             error code if the semaphore could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_sem_create(char *name, int init_cnt, osl_ext_sem_t *sem);
-
-/****************************************************************************
-* Function:   osl_ext_sem_delete
-*
-* Purpose:    Destroys a previously created semaphore object.
-*
-* Parameters: sem (mod) Semaphore object to destroy.
-*
-* Returns:    OSL_EXT_SUCCESS if the semaphore was deleted successfully, or an
-*             error code if the semaphore could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_sem_delete(osl_ext_sem_t *sem);
-
-/****************************************************************************
-* Function:   osl_ext_sem_give
-*
-* Purpose:    Increments the count associated with the semaphore. This will
-*             cause one thread blocked on a take to wake up.
-*
-* Parameters: sem (mod) Semaphore object to give.
-*
-* Returns:    OSL_EXT_SUCCESS if the semaphore was given successfully, or an
-*             error code if the semaphore could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_sem_give(osl_ext_sem_t *sem);
-
-/****************************************************************************
-* Function:   osl_ext_sem_take
-*
-* Purpose:    Decrements the count associated with the semaphore. If the count
-*             is less than zero, then the calling task will become blocked until
-*             another thread does a give on the semaphore. This function will only
-*             block the calling thread for timeout_msec milliseconds, before
-*             returning with OSL_EXT_TIMEOUT.
-*
-* Parameters: sem          (mod) Semaphore object to take.
-*             timeout_msec (in)  Number of milliseconds to wait for the
-*                                semaphore to enter a state where it can be
-*                                taken.
-*
-* Returns:    OSL_EXT_SUCCESS if the semaphore was taken successfully, or an
-*             error code if the semaphore could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_sem_take(osl_ext_sem_t *sem, osl_ext_time_ms_t timeout_msec);
-
-
-/* --------------------------------------------------------------------------
-** Mutex
-*/
-
-/****************************************************************************
-* Function:   osl_ext_mutex_create
-*
-* Purpose:    Creates a mutex object, which can subsequently be used to control
-*             mutually exclusion of resources.
-*
-* Parameters: name  (in)  Name to assign to the mutex (must be unique).
-*             mutex (out) Mutex object to initialize.
-*
-* Returns:    OSL_EXT_SUCCESS if the mutex was created successfully, or an
-*             error code if the mutex could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_mutex_create(char *name, osl_ext_mutex_t *mutex);
-
-/****************************************************************************
-* Function:   osl_ext_mutex_delete
-*
-* Purpose:    Destroys a previously created mutex object.
-*
-* Parameters: mutex (mod) Mutex object to destroy.
-*
-* Returns:    OSL_EXT_SUCCESS if the mutex was deleted successfully, or an
-*             error code if the mutex could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_mutex_delete(osl_ext_mutex_t *mutex);
-
-/****************************************************************************
-* Function:   osl_ext_mutex_acquire
-*
-* Purpose:    Acquires the indicated mutual exclusion object. If the object is
-*             currently acquired by another task, then this function will wait
-*             for timeout_msec milli-seconds before returning with OSL_EXT_TIMEOUT.
-*
-* Parameters: mutex        (mod) Mutex object to acquire.
-*             timeout_msec (in)  Number of milliseconds to wait for the mutex.
-*
-* Returns:    OSL_EXT_SUCCESS if the mutex was acquired successfully, or an
-*             error code if the mutex could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_mutex_acquire(osl_ext_mutex_t *mutex, osl_ext_time_ms_t timeout_msec);
-
-/****************************************************************************
-* Function:   osl_ext_mutex_release
-*
-* Purpose:    Releases the indicated mutual exclusion object. This makes it
-*             available for another task to acquire.
-*
-* Parameters: mutex (mod) Mutex object to release.
-*
-* Returns:    OSL_EXT_SUCCESS if the mutex was released successfully, or an
-*             error code if the mutex could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_mutex_release(osl_ext_mutex_t *mutex);
-
-
-/* --------------------------------------------------------------------------
-** Timers
-*/
-
-/****************************************************************************
-* Function:   osl_ext_timer_create
-*
-* Purpose:    Creates a timer object.
-*
-* Parameters: name (in)         Name of timer.
-*             timeout_msec (in) Invoke callback after this number of milliseconds.
-*             mode (in)         One-shot or periodic timer.
-*             func (in)         Callback function to invoke on timer expiry.
-*             arg (in)          Argument to callback function.
-*             timer (out)       Timer object to create.
-*
-* Note: The function callback occurs in interrupt context. The application is
-*       required to provide context switch for the callback if required.
-*
-* Returns:    OSL_EXT_SUCCESS if the timer was created successfully, or an
-*             error code if the timer could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t
-osl_ext_timer_create(char *name, osl_ext_time_ms_t timeout_msec, osl_ext_timer_mode_t mode,
-                 osl_ext_timer_callback func, osl_ext_timer_arg_t arg, osl_ext_timer_t *timer);
-
-/****************************************************************************
-* Function:   osl_ext_timer_delete
-*
-* Purpose:    Destroys a previously created timer object.
-*
-* Parameters: timer (mod) Timer object to destroy.
-*
-* Returns:    OSL_EXT_SUCCESS if the timer was created successfully, or an
-*             error code if the timer could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_timer_delete(osl_ext_timer_t *timer);
-
-/****************************************************************************
-* Function:   osl_ext_timer_start
-*
-* Purpose:    Start a previously created timer object.
-*
-* Parameters: timer (in)        Timer object.
-*             timeout_msec (in) Invoke callback after this number of milliseconds.
-*             mode (in)         One-shot or periodic timer.
-*
-* Returns:    OSL_EXT_SUCCESS if the timer was created successfully, or an
-*             error code if the timer could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t
-osl_ext_timer_start(osl_ext_timer_t *timer,
-	osl_ext_time_ms_t timeout_msec, osl_ext_timer_mode_t mode);
-
-/****************************************************************************
-* Function:   osl_ext_timer_stop
-*
-* Purpose:    Stop a previously created timer object.
-*
-* Parameters: timer (in)        Timer object.
-*
-* Returns:    OSL_EXT_SUCCESS if the timer was created successfully, or an
-*             error code if the timer could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t
-osl_ext_timer_stop(osl_ext_timer_t *timer);
-
-/****************************************************************************
-* Function:   osl_ext_time_get
-*
-* Purpose:    Returns incrementing time counter.
-*
-* Parameters: None.
-*
-* Returns:    Returns incrementing time counter in msec.
-*****************************************************************************
-*/
-osl_ext_time_ms_t osl_ext_time_get(void);
-
-/* --------------------------------------------------------------------------
-** Tasks
-*/
-
-/****************************************************************************
-* Function:   osl_ext_task_create
-*
-* Purpose:    Create a task.
-*
-* Parameters: name       (in)  Pointer to task string descriptor.
-*             stack      (in)  Pointer to stack. NULL to allocate.
-*             stack_size (in)  Stack size - in bytes.
-*             priority   (in)  Abstract task priority.
-*             func       (in)  A pointer to the task entry point function.
-*             arg        (in)  Value passed into task entry point function.
-*             task       (out) Task to create.
-*
-* Returns:    OSL_EXT_SUCCESS if the task was created successfully, or an
-*             error code if the task could not be created.
-*****************************************************************************
-*/
-
-#define osl_ext_task_create(name, stack, stack_size, priority, func, arg, task) \
-	   osl_ext_task_create_ex((name), (stack), (stack_size), (priority), 0, (func), \
-	   (arg), (task))
-
-osl_ext_status_t osl_ext_task_create_ex(char* name,
-	void *stack, unsigned int stack_size, osl_ext_task_priority_t priority,
-	osl_ext_time_ms_t timslice_msec, osl_ext_task_entry func, osl_ext_task_arg_t arg,
-	osl_ext_task_t *task);
-
-/****************************************************************************
-* Function:   osl_ext_task_delete
-*
-* Purpose:    Destroy a task.
-*
-* Parameters: task (mod) Task to destroy.
-*
-* Returns:    OSL_EXT_SUCCESS if the task was created successfully, or an
-*             error code if the task could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_task_delete(osl_ext_task_t *task);
-
-
-/****************************************************************************
-* Function:   osl_ext_task_is_running
-*
-* Purpose:    Returns current running task.
-*
-* Parameters: None.
-*
-* Returns:    osl_ext_task_t of current running task.
-*****************************************************************************
-*/
-osl_ext_task_t *osl_ext_task_current(void);
-
-
-/****************************************************************************
-* Function:   osl_ext_task_yield
-*
-* Purpose:    Yield the CPU to other tasks of the same priority that are
-*             ready-to-run.
-*
-* Parameters: None.
-*
-* Returns:    OSL_EXT_SUCCESS if successful, else error code.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_task_yield(void);
-
-
-/****************************************************************************
-* Function:   osl_ext_task_enable_stack_check
-*
-* Purpose:    Enable task stack checking.
-*
-* Parameters: None.
-*
-* Returns:    OSL_EXT_SUCCESS if successful, else error code.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_task_enable_stack_check(void);
-
-
-/* --------------------------------------------------------------------------
-** Queue
-*/
-
-/****************************************************************************
-* Function:   osl_ext_queue_create
-*
-* Purpose:    Create a queue.
-*
-* Parameters: name     (in)  Name to assign to the queue (must be unique).
-*             buffer   (in)  Queue buffer. NULL to allocate.
-*             size     (in)  Size of the queue.
-*             queue    (out) Newly created queue.
-*
-* Returns:    OSL_EXT_SUCCESS if the queue was created successfully, or an
-*             error code if the queue could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_queue_create(char *name,
-	void *queue_buffer, unsigned int queue_size,
-	osl_ext_queue_t *queue);
-
-/****************************************************************************
-* Function:   osl_ext_queue_delete
-*
-* Purpose:    Destroys a previously created queue object.
-*
-* Parameters: queue    (mod) Queue object to destroy.
-*
-* Returns:    OSL_EXT_SUCCESS if the queue was deleted successfully, or an
-*             error code if the queue could not be deleteed.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_queue_delete(osl_ext_queue_t *queue);
-
-/****************************************************************************
-* Function:   osl_ext_queue_send
-*
-* Purpose:    Send/add data to the queue. This function will not block the
-*             calling thread if the queue is full.
-*
-* Parameters: queue    (mod) Queue object.
-*             data     (in)  Data pointer to be queued.
-*
-* Returns:    OSL_EXT_SUCCESS if the data was queued successfully, or an
-*             error code if the data could not be queued.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_queue_send(osl_ext_queue_t *queue, void *data);
-
-/****************************************************************************
-* Function:   osl_ext_queue_send_synchronous
-*
-* Purpose:    Send/add data to the queue. This function will block the
-*             calling thread until the data is dequeued.
-*
-* Parameters: queue    (mod) Queue object.
-*             data     (in)  Data pointer to be queued.
-*
-* Returns:    OSL_EXT_SUCCESS if the data was queued successfully, or an
-*             error code if the data could not be queued.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_queue_send_synchronous(osl_ext_queue_t *queue, void *data);
-
-/****************************************************************************
-* Function:   osl_ext_queue_receive
-*
-* Purpose:    Receive/remove data from the queue. This function will only
-*             block the calling thread for timeout_msec milliseconds, before
-*             returning with OSL_EXT_TIMEOUT.
-*
-* Parameters: queue        (mod) Queue object.
-*             timeout_msec (in)  Number of milliseconds to wait for the
-*                                data from the queue.
-*             data         (out) Data pointer received/removed from the queue.
-*
-* Returns:    OSL_EXT_SUCCESS if the data was dequeued successfully, or an
-*             error code if the data could not be dequeued.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_queue_receive(osl_ext_queue_t *queue,
-                 osl_ext_time_ms_t timeout_msec, void **data);
-
-/****************************************************************************
-* Function:   osl_ext_queue_count
-*
-* Purpose:    Returns the number of items in the queue.
-*
-* Parameters: queue        (mod) Queue object.
-*             count        (out) Data pointer received/removed from the queue.
-*
-* Returns:    OSL_EXT_SUCCESS if the count was returned successfully, or an
-*             error code if the count is invalid.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_queue_count(osl_ext_queue_t *queue, int *count);
-
-
-/* --------------------------------------------------------------------------
-** Event
-*/
-
-/****************************************************************************
-* Function:   osl_ext_event_create
-*
-* Purpose:    Creates a event object, which can subsequently be used to
-*             notify and trigger tasks.
-*
-* Parameters: name  (in)  Name to assign to the event (must be unique).
-*             event (out) Event object to initialize.
-*
-* Returns:    OSL_EXT_SUCCESS if the event was created successfully, or an
-*             error code if the event could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_event_create(char *name, osl_ext_event_t *event);
-
-/****************************************************************************
-* Function:   osl_ext_event_delete
-*
-* Purpose:    Destroys a previously created event object.
-*
-* Parameters: event (mod) Event object to destroy.
-*
-* Returns:    OSL_EXT_SUCCESS if the event was created successfully, or an
-*             error code if the event could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_event_delete(osl_ext_event_t *event);
-
-/****************************************************************************
-* Function:   osl_ext_event_get
-*
-* Purpose:    Get event from specified event object.
-*
-* Parameters: event        (mod) Event object to get.
-*             requested    (in)  Requested event to get.
-*             timeout_msec (in)  Number of milliseconds to wait for the event.
-*             event_bits   (out) Event bits retrieved.
-*
-* Returns:    OSL_EXT_SUCCESS if the event was created successfully, or an
-*             error code if the event could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_event_get(osl_ext_event_t *event,
-	osl_ext_event_bits_t requested,	osl_ext_time_ms_t timeout_msec,
-	osl_ext_event_bits_t *event_bits);
-
-/****************************************************************************
-* Function:   osl_ext_event_set
-*
-* Purpose:    Set event of specified event object.
-*
-* Parameters: event      (mod) Event object to set.
-*             event_bits (in)  Event bits to set.
-*
-* Returns:    OSL_EXT_SUCCESS if the event was created successfully, or an
-*             error code if the event could not be created.
-*****************************************************************************
-*/
-osl_ext_status_t osl_ext_event_set(osl_ext_event_t *event,
-	osl_ext_event_bits_t event_bits);
-
-
-/* --------------------------------------------------------------------------
-** Interrupt
-*/
-
-/****************************************************************************
-* Function:   osl_ext_interrupt_disable
-*
-* Purpose:    Disable CPU interrupt.
-*
-* Parameters: None.
-*
-* Returns:    The interrupt state before disable for restoring interrupt.
-*****************************************************************************
-*/
-osl_ext_interrupt_state_t osl_ext_interrupt_disable(void);
-
-
-/****************************************************************************
-* Function:   osl_ext_interrupt_restore
-*
-* Purpose:    Restore CPU interrupt state.
-*
-* Parameters: state (in)  Interrupt state to restore returned from
-*                         osl_ext_interrupt_disable().
-*
-* Returns:   None.
-*****************************************************************************
-*/
-void osl_ext_interrupt_restore(osl_ext_interrupt_state_t state);
-
-#else
-
-/* ---- Constants and Types ---------------------------------------------- */
-
-/* Semaphore. */
-#define osl_ext_sem_t
-#define OSL_EXT_SEM_DECL(sem)
-
-/* Mutex. */
-#define osl_ext_mutex_t
-#define OSL_EXT_MUTEX_DECL(mutex)
-
-/* Timer. */
-#define osl_ext_timer_t
-#define OSL_EXT_TIMER_DECL(timer)
-
-/* Task. */
-#define osl_ext_task_t void
-#define OSL_EXT_TASK_DECL(task)
-
-/* Queue. */
-#define osl_ext_queue_t
-#define OSL_EXT_QUEUE_DECL(queue)
-
-/* Event. */
-#define osl_ext_event_t
-#define OSL_EXT_EVENT_DECL(event)
-
-/* ---- Variable Externs ------------------------------------------------- */
-/* ---- Function Prototypes ---------------------------------------------- */
-
-#define osl_ext_sem_create(name, init_cnt, sem)		(OSL_EXT_SUCCESS)
-#define osl_ext_sem_delete(sem)				(OSL_EXT_SUCCESS)
-#define osl_ext_sem_give(sem)				(OSL_EXT_SUCCESS)
-#define osl_ext_sem_take(sem, timeout_msec)		(OSL_EXT_SUCCESS)
-
-#define osl_ext_mutex_create(name, mutex)		(OSL_EXT_SUCCESS)
-#define osl_ext_mutex_delete(mutex)			(OSL_EXT_SUCCESS)
-#define osl_ext_mutex_acquire(mutex, timeout_msec)	(OSL_EXT_SUCCESS)
-#define osl_ext_mutex_release(mutex)			(OSL_EXT_SUCCESS)
-
-#define osl_ext_timer_create(name, timeout_msec, mode, func, arg, timer) \
-	(OSL_EXT_SUCCESS)
-#define osl_ext_timer_delete(timer)			(OSL_EXT_SUCCESS)
-#define osl_ext_timer_start(timer, timeout_msec, mode)	(OSL_EXT_SUCCESS)
-#define osl_ext_timer_stop(timer)			(OSL_EXT_SUCCESS)
-#define osl_ext_time_get()				(0)
-
-#define osl_ext_task_create(name, stack, stack_size, priority, func, arg, task) \
-	(OSL_EXT_SUCCESS)
-#define osl_ext_task_delete(task)			(OSL_EXT_SUCCESS)
-#define osl_ext_task_current()				(NULL)
-#define osl_ext_task_yield()				(OSL_EXT_SUCCESS)
-#define osl_ext_task_enable_stack_check()		(OSL_EXT_SUCCESS)
-
-#define osl_ext_queue_create(name, queue_buffer, queue_size, queue) \
-	(OSL_EXT_SUCCESS)
-#define osl_ext_queue_delete(queue)			(OSL_EXT_SUCCESS)
-#define osl_ext_queue_send(queue, data)			(OSL_EXT_SUCCESS)
-#define osl_ext_queue_send_synchronous(queue, data)	(OSL_EXT_SUCCESS)
-#define osl_ext_queue_receive(queue, timeout_msec, data) \
-	(OSL_EXT_SUCCESS)
-#define osl_ext_queue_count(queue, count)		(OSL_EXT_SUCCESS)
-
-#define osl_ext_event_create(name, event)		(OSL_EXT_SUCCESS)
-#define osl_ext_event_delete(event)			(OSL_EXT_SUCCESS)
-#define osl_ext_event_get(event, requested, timeout_msec, event_bits) \
-	(OSL_EXT_SUCCESS)
-#define osl_ext_event_set(event, event_bits)		(OSL_EXT_SUCCESS)
-
-#define osl_ext_interrupt_disable(void)
-#define osl_ext_interrupt_restore(state)
-
-#endif	/* OSL_EXT_DISABLED */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* _osl_ext_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/packed_section_end.h b/drivers/net/wireless/bcmdhd/include/packed_section_end.h
deleted file mode 100644
index e3a35c7..0000000
--- a/drivers/net/wireless/bcmdhd/include/packed_section_end.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Declare directives for structure packing. No padding will be provided
- * between the members of packed structures, and therefore, there is no
- * guarantee that structure members will be aligned.
- *
- * Declaring packed structures is compiler specific. In order to handle all
- * cases, packed structures should be delared as:
- *
- * #include <packed_section_start.h>
- *
- * typedef BWL_PRE_PACKED_STRUCT struct foobar_t {
- *    some_struct_members;
- * } BWL_POST_PACKED_STRUCT foobar_t;
- *
- * #include <packed_section_end.h>
- *
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: packed_section_end.h 514727 2014-11-12 03:02:48Z $
- */
-
-
-/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
- * and undefined in packed_section_end.h. If it is NOT defined at this
- * point, then there is a missing include of packed_section_start.h.
- */
-#ifdef BWL_PACKED_SECTION
-	#undef BWL_PACKED_SECTION
-#else
-	#error "BWL_PACKED_SECTION is NOT defined!"
-#endif
-
-
-
-
-/* Compiler-specific directives for structure packing are declared in
- * packed_section_start.h. This marks the end of the structure packing section,
- * so, undef them here.
- */
-#undef	BWL_PRE_PACKED_STRUCT
-#undef	BWL_POST_PACKED_STRUCT
diff --git a/drivers/net/wireless/bcmdhd/include/packed_section_start.h b/drivers/net/wireless/bcmdhd/include/packed_section_start.h
deleted file mode 100644
index 6171764..0000000
--- a/drivers/net/wireless/bcmdhd/include/packed_section_start.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Declare directives for structure packing. No padding will be provided
- * between the members of packed structures, and therefore, there is no
- * guarantee that structure members will be aligned.
- *
- * Declaring packed structures is compiler specific. In order to handle all
- * cases, packed structures should be delared as:
- *
- * #include <packed_section_start.h>
- *
- * typedef BWL_PRE_PACKED_STRUCT struct foobar_t {
- *    some_struct_members;
- * } BWL_POST_PACKED_STRUCT foobar_t;
- *
- * #include <packed_section_end.h>
- *
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: packed_section_start.h 514727 2014-11-12 03:02:48Z $
- */
-
-
-/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
- * and undefined in packed_section_end.h. If it is already defined at this
- * point, then there is a missing include of packed_section_end.h.
- */
-#ifdef BWL_PACKED_SECTION
-	#error "BWL_PACKED_SECTION is already defined!"
-#else
-	#define BWL_PACKED_SECTION
-#endif
-
-
-
-
-/* Declare compiler-specific directives for structure packing. */
-#if defined(__GNUC__) || defined(__lint)
-	#define	BWL_PRE_PACKED_STRUCT
-	#define	BWL_POST_PACKED_STRUCT	__attribute__ ((packed))
-#elif defined(__CC_ARM)
-	#define	BWL_PRE_PACKED_STRUCT	__packed
-	#define	BWL_POST_PACKED_STRUCT
-#else
-	#error "Unknown compiler!"
-#endif
diff --git a/drivers/net/wireless/bcmdhd/include/pcicfg.h b/drivers/net/wireless/bcmdhd/include/pcicfg.h
deleted file mode 100644
index be0a92a..0000000
--- a/drivers/net/wireless/bcmdhd/include/pcicfg.h
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * pcicfg.h: PCI configuration constants and structures.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: pcicfg.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_h_pcicfg_
-#define	_h_pcicfg_
-
-
-/* pci config status reg has a bit to indicate that capability ptr is present */
-
-#define PCI_CAPPTR_PRESENT	0x0010
-
-/* A structure for the config registers is nice, but in most
- * systems the config space is not memory mapped, so we need
- * field offsetts. :-(
- */
-#define	PCI_CFG_VID		0
-#define	PCI_CFG_DID		2
-#define	PCI_CFG_CMD		4
-#define	PCI_CFG_STAT		6
-#define	PCI_CFG_REV		8
-#define	PCI_CFG_PROGIF		9
-#define	PCI_CFG_SUBCL		0xa
-#define	PCI_CFG_BASECL		0xb
-#define	PCI_CFG_CLSZ		0xc
-#define	PCI_CFG_LATTIM		0xd
-#define	PCI_CFG_HDR		0xe
-#define	PCI_CFG_BIST		0xf
-#define	PCI_CFG_BAR0		0x10
-#define	PCI_CFG_BAR1		0x14
-#define	PCI_CFG_BAR2		0x18
-#define	PCI_CFG_BAR3		0x1c
-#define	PCI_CFG_BAR4		0x20
-#define	PCI_CFG_BAR5		0x24
-#define	PCI_CFG_CIS		0x28
-#define	PCI_CFG_SVID		0x2c
-#define	PCI_CFG_SSID		0x2e
-#define	PCI_CFG_ROMBAR		0x30
-#define PCI_CFG_CAPPTR		0x34
-#define	PCI_CFG_INT		0x3c
-#define	PCI_CFG_PIN		0x3d
-#define	PCI_CFG_MINGNT		0x3e
-#define	PCI_CFG_MAXLAT		0x3f
-#define	PCI_CFG_DEVCTRL		0xd8
-
-
-/* PCI CAPABILITY DEFINES */
-#define PCI_CAP_POWERMGMTCAP_ID		0x01
-#define PCI_CAP_MSICAP_ID		0x05
-#define PCI_CAP_VENDSPEC_ID		0x09
-#define PCI_CAP_PCIECAP_ID		0x10
-
-/* Data structure to define the Message Signalled Interrupt facility
- * Valid for PCI and PCIE configurations
- */
-typedef struct _pciconfig_cap_msi {
-	uint8	capID;
-	uint8	nextptr;
-	uint16	msgctrl;
-	uint32	msgaddr;
-} pciconfig_cap_msi;
-#define MSI_ENABLE	0x1		/* bit 0 of msgctrl */
-
-/* Data structure to define the Power managment facility
- * Valid for PCI and PCIE configurations
- */
-typedef struct _pciconfig_cap_pwrmgmt {
-	uint8	capID;
-	uint8	nextptr;
-	uint16	pme_cap;
-	uint16	pme_sts_ctrl;
-	uint8	pme_bridge_ext;
-	uint8	data;
-} pciconfig_cap_pwrmgmt;
-
-#define PME_CAP_PM_STATES (0x1f << 27)	/* Bits 31:27 states that can generate PME */
-#define PME_CSR_OFFSET	    0x4		/* 4-bytes offset */
-#define PME_CSR_PME_EN	  (1 << 8)	/* Bit 8 Enable generating of PME */
-#define PME_CSR_PME_STAT  (1 << 15)	/* Bit 15 PME got asserted */
-
-/* Data structure to define the PCIE capability */
-typedef struct _pciconfig_cap_pcie {
-	uint8	capID;
-	uint8	nextptr;
-	uint16	pcie_cap;
-	uint32	dev_cap;
-	uint16	dev_ctrl;
-	uint16	dev_status;
-	uint32	link_cap;
-	uint16	link_ctrl;
-	uint16	link_status;
-	uint32	slot_cap;
-	uint16	slot_ctrl;
-	uint16	slot_status;
-	uint16	root_ctrl;
-	uint16	root_cap;
-	uint32	root_status;
-} pciconfig_cap_pcie;
-
-/* PCIE Enhanced CAPABILITY DEFINES */
-#define PCIE_EXTCFG_OFFSET	0x100
-#define PCIE_ADVERRREP_CAPID	0x0001
-#define PCIE_VC_CAPID		0x0002
-#define PCIE_DEVSNUM_CAPID	0x0003
-#define PCIE_PWRBUDGET_CAPID	0x0004
-
-/* PCIE Extended configuration */
-#define PCIE_ADV_CORR_ERR_MASK	0x114
-#define CORR_ERR_RE	(1 << 0) /* Receiver  */
-#define CORR_ERR_BT 	(1 << 6) /* Bad TLP  */
-#define CORR_ERR_BD	(1 << 7) /* Bad DLLP */
-#define CORR_ERR_RR	(1 << 8) /* REPLAY_NUM rollover */
-#define CORR_ERR_RT	(1 << 12) /* Reply timer timeout */
-#define ALL_CORR_ERRORS (CORR_ERR_RE | CORR_ERR_BT | CORR_ERR_BD | \
-			 CORR_ERR_RR | CORR_ERR_RT)
-
-/* PCIE Root Control Register bits (Host mode only) */
-#define	PCIE_RC_CORR_SERR_EN		0x0001
-#define	PCIE_RC_NONFATAL_SERR_EN	0x0002
-#define	PCIE_RC_FATAL_SERR_EN		0x0004
-#define	PCIE_RC_PME_INT_EN		0x0008
-#define	PCIE_RC_CRS_EN			0x0010
-
-/* PCIE Root Capability Register bits (Host mode only) */
-#define	PCIE_RC_CRS_VISIBILITY		0x0001
-
-/* Header to define the PCIE specific capabilities in the extended config space */
-typedef struct _pcie_enhanced_caphdr {
-	uint16	capID;
-	uint16	cap_ver : 4;
-	uint16	next_ptr : 12;
-} pcie_enhanced_caphdr;
-
-
-#define	PCI_BAR0_WIN		0x80	/* backplane addres space accessed by BAR0 */
-#define	PCI_BAR1_WIN		0x84	/* backplane addres space accessed by BAR1 */
-#define	PCI_SPROM_CONTROL	0x88	/* sprom property control */
-#define	PCI_BAR1_CONTROL	0x8c	/* BAR1 region burst control */
-#define	PCI_INT_STATUS		0x90	/* PCI and other cores interrupts */
-#define	PCI_INT_MASK		0x94	/* mask of PCI and other cores interrupts */
-#define PCI_TO_SB_MB		0x98	/* signal backplane interrupts */
-#define PCI_BACKPLANE_ADDR	0xa0	/* address an arbitrary location on the system backplane */
-#define PCI_BACKPLANE_DATA	0xa4	/* data at the location specified by above address */
-#define	PCI_CLK_CTL_ST		0xa8	/* pci config space clock control/status (>=rev14) */
-#define	PCI_BAR0_WIN2		0xac	/* backplane addres space accessed by second 4KB of BAR0 */
-#define	PCI_GPIO_IN		0xb0	/* pci config space gpio input (>=rev3) */
-#define	PCI_GPIO_OUT		0xb4	/* pci config space gpio output (>=rev3) */
-#define	PCI_GPIO_OUTEN		0xb8	/* pci config space gpio output enable (>=rev3) */
-#define	PCI_L1SS_CTRL2		0x24c	/* The L1 PM Substates Control register */
-
-/* Private Registers */
-#define	PCI_STAT_CTRL		0xa80
-#define	PCI_L0_EVENTCNT		0xa84
-#define	PCI_L0_STATETMR		0xa88
-#define	PCI_L1_EVENTCNT		0xa8c
-#define	PCI_L1_STATETMR		0xa90
-#define	PCI_L1_1_EVENTCNT	0xa94
-#define	PCI_L1_1_STATETMR	0xa98
-#define	PCI_L1_2_EVENTCNT	0xa9c
-#define	PCI_L1_2_STATETMR	0xaa0
-#define	PCI_L2_EVENTCNT		0xaa4
-#define	PCI_L2_STATETMR		0xaa8
-
-#define	PCI_PMCR_REFUP		0x1814	/* Trefup time */
-#define	PCI_PMCR_REFUP_EXT	0x1818	/* Trefup extend Max */
-#define PCI_TPOWER_SCALE_MASK 0x3
-#define PCI_TPOWER_SCALE_SHIFT 3 /* 0:1 is scale and 2 is rsvd */
-
-
-#define	PCI_BAR0_SHADOW_OFFSET	(2 * 1024)	/* bar0 + 2K accesses sprom shadow (in pci core) */
-#define	PCI_BAR0_SPROM_OFFSET	(4 * 1024)	/* bar0 + 4K accesses external sprom */
-#define	PCI_BAR0_PCIREGS_OFFSET	(6 * 1024)	/* bar0 + 6K accesses pci core registers */
-#define	PCI_BAR0_PCISBR_OFFSET	(4 * 1024)	/* pci core SB registers are at the end of the
-						 * 8KB window, so their address is the "regular"
-						 * address plus 4K
-						 */
-/*
- * PCIE GEN2 changed some of the above locations for
- * Bar0WrapperBase, SecondaryBAR0Window and SecondaryBAR0WrapperBase
- * BAR0 maps 32K of register space
-*/
-#define PCIE2_BAR0_WIN2		0x70 /* backplane addres space accessed by second 4KB of BAR0 */
-#define PCIE2_BAR0_CORE2_WIN	0x74 /* backplane addres space accessed by second 4KB of BAR0 */
-#define PCIE2_BAR0_CORE2_WIN2	0x78 /* backplane addres space accessed by second 4KB of BAR0 */
-
-#define PCI_BAR0_WINSZ		(16 * 1024)	/* bar0 window size Match with corerev 13 */
-/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */
-#define	PCI_16KB0_PCIREGS_OFFSET (8 * 1024)	/* bar0 + 8K accesses pci/pcie core registers */
-#define	PCI_16KB0_CCREGS_OFFSET	(12 * 1024)	/* bar0 + 12K accesses chipc core registers */
-#define PCI_16KBB0_WINSZ	(16 * 1024)	/* bar0 window size */
-#define PCI_SECOND_BAR0_OFFSET	(16 * 1024)	/* secondary  bar 0 window */
-
-
-/* Header types */
-#define	PCI_HEADER_MULTI	0x80
-#define	PCI_HEADER_MASK		0x7f
-typedef enum {
-	PCI_HEADER_NORMAL,
-	PCI_HEADER_BRIDGE,
-	PCI_HEADER_CARDBUS
-} pci_header_types;
-
-#define PCI_CONFIG_SPACE_SIZE	256
-
-#define DWORD_ALIGN(x)  (x & ~(0x03))
-#define BYTE_POS(x) (x & 0x3)
-#define WORD_POS(x) (x & 0x1)
-
-#define BYTE_SHIFT(x)  (8 * BYTE_POS(x))
-#define WORD_SHIFT(x)  (16 * WORD_POS(x))
-
-#define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF)
-#define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF)
-
-#define read_pci_cfg_byte(a) \
-	(BYTE_VAL(OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4), a) & 0xff)
-
-#define read_pci_cfg_word(a) \
-	(WORD_VAL(OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4), a) & 0xffff)
-
-#define write_pci_cfg_byte(a, val) do { \
-	uint32 tmpval; \
-	tmpval = (OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4) & ~0xFF << BYTE_POS(a)) | \
-	        val << BYTE_POS(a); \
-	OSL_PCI_WRITE_CONFIG(osh, DWORD_ALIGN(a), 4, tmpval); \
-	} while (0)
-
-#define write_pci_cfg_word(a, val) do { \
-	uint32 tmpval; \
-	tmpval = (OSL_PCI_READ_CONFIG(osh, DWORD_ALIGN(a), 4) & ~0xFFFF << WORD_POS(a)) | \
-	        val << WORD_POS(a); \
-	OSL_PCI_WRITE_CONFIG(osh, DWORD_ALIGN(a), 4, tmpval); \
-	} while (0)
-
-#endif	/* _h_pcicfg_ */
diff --git a/drivers/net/wireless/bcmdhd/include/pcie_core.h b/drivers/net/wireless/bcmdhd/include/pcie_core.h
deleted file mode 100644
index 25a156a..0000000
--- a/drivers/net/wireless/bcmdhd/include/pcie_core.h
+++ /dev/null
@@ -1,652 +0,0 @@
-/*
- * BCM43XX PCIE core hardware definitions.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: pcie_core.h 514727 2014-11-12 03:02:48Z $
- */
-#ifndef	_PCIE_CORE_H
-#define	_PCIE_CORE_H
-
-#include <sbhnddma.h>
-#include <siutils.h>
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif
-
-/* PCIE Enumeration space offsets */
-#define  PCIE_CORE_CONFIG_OFFSET	0x0
-#define  PCIE_FUNC0_CONFIG_OFFSET	0x400
-#define  PCIE_FUNC1_CONFIG_OFFSET	0x500
-#define  PCIE_FUNC2_CONFIG_OFFSET	0x600
-#define  PCIE_FUNC3_CONFIG_OFFSET	0x700
-#define  PCIE_SPROM_SHADOW_OFFSET	0x800
-#define  PCIE_SBCONFIG_OFFSET		0xE00
-
-
-#define PCIEDEV_MAX_DMAS			4
-
-/* PCIE Bar0 Address Mapping. Each function maps 16KB config space */
-#define PCIE_DEV_BAR0_SIZE		0x4000
-#define PCIE_BAR0_WINMAPCORE_OFFSET	0x0
-#define PCIE_BAR0_EXTSPROM_OFFSET	0x1000
-#define PCIE_BAR0_PCIECORE_OFFSET	0x2000
-#define PCIE_BAR0_CCCOREREG_OFFSET	0x3000
-
-/* different register spaces to access thr'u pcie indirect access */
-#define PCIE_CONFIGREGS 	1		/* Access to config space */
-#define PCIE_PCIEREGS 		2		/* Access to pcie registers */
-
-/* dma regs to control the flow between host2dev and dev2host  */
-typedef struct pcie_devdmaregs {
-	dma64regs_t	tx;
-	uint32		PAD[2];
-	dma64regs_t	rx;
-	uint32		PAD[2];
-} pcie_devdmaregs_t;
-
-#define PCIE_DB_HOST2DEV_0		0x1
-#define PCIE_DB_HOST2DEV_1		0x2
-#define PCIE_DB_DEV2HOST_0		0x3
-#define PCIE_DB_DEV2HOST_1		0x4
-
-/* door bell register sets */
-typedef struct pcie_doorbell {
-	uint32		host2dev_0;
-	uint32		host2dev_1;
-	uint32		dev2host_0;
-	uint32		dev2host_1;
-} pcie_doorbell_t;
-
-/* SB side: PCIE core and host control registers */
-typedef struct sbpcieregs {
-	uint32 control;		/* host mode only */
-	uint32 iocstatus;	/* PCIE2: iostatus */
-	uint32 PAD[1];
-	uint32 biststatus;	/* bist Status: 0x00C */
-	uint32 gpiosel;		/* PCIE gpio sel: 0x010 */
-	uint32 gpioouten;	/* PCIE gpio outen: 0x14 */
-	uint32 PAD[2];
-	uint32 intstatus;	/* Interrupt status: 0x20 */
-	uint32 intmask;		/* Interrupt mask: 0x24 */
-	uint32 sbtopcimailbox;	/* sb to pcie mailbox: 0x028 */
-	uint32 obffcontrol;	/* PCIE2: 0x2C */
-	uint32 obffintstatus;	/* PCIE2: 0x30 */
-	uint32 obffdatastatus;	/* PCIE2: 0x34 */
-	uint32 PAD[2];
-	uint32 errlog;		/* PCIE2: 0x40 */
-	uint32 errlogaddr;	/* PCIE2: 0x44 */
-	uint32 mailboxint;	/* PCIE2: 0x48 */
-	uint32 mailboxintmsk; /* PCIE2: 0x4c */
-	uint32 ltrspacing;	/* PCIE2: 0x50 */
-	uint32 ltrhysteresiscnt;	/* PCIE2: 0x54 */
-	uint32 PAD[42];
-
-	uint32 sbtopcie0;	/* sb to pcie translation 0: 0x100 */
-	uint32 sbtopcie1;	/* sb to pcie translation 1: 0x104 */
-	uint32 sbtopcie2;	/* sb to pcie translation 2: 0x108 */
-	uint32 PAD[5];
-
-	/* pcie core supports in direct access to config space */
-	uint32 configaddr;	/* pcie config space access: Address field: 0x120 */
-	uint32 configdata;	/* pcie config space access: Data field: 0x124 */
-	union {
-		struct {
-			/* mdio access to serdes */
-			uint32 mdiocontrol;	/* controls the mdio access: 0x128 */
-			uint32 mdiodata;	/* Data to the mdio access: 0x12c */
-			/* pcie protocol phy/dllp/tlp register indirect access mechanism */
-			uint32 pcieindaddr; /* indirect access to the internal register: 0x130 */
-			uint32 pcieinddata;	/* Data to/from the internal regsiter: 0x134 */
-			uint32 clkreqenctrl;	/* >= rev 6, Clkreq rdma control : 0x138 */
-			uint32 PAD[177];
-		} pcie1;
-		struct {
-			/* mdio access to serdes */
-			uint32 mdiocontrol;	/* controls the mdio access: 0x128 */
-			uint32 mdiowrdata;	/* write data to mdio 0x12C */
-			uint32 mdiorddata;	/* read data to mdio 0x130 */
-			uint32	PAD[3]; 	/* 0x134-0x138-0x13c */
-			/* door bell registers available from gen2 rev5 onwards */
-			pcie_doorbell_t	   dbls[PCIEDEV_MAX_DMAS]; /* 0x140 - 0x17F */
-			uint32	dataintf;	/* 0x180 */
-			uint32  PAD[1];		/* 0x184 */
-			uint32	d2h_intrlazy_0; /* 0x188 */
-			uint32	h2d_intrlazy_0; /* 0x18c */
-			uint32  h2d_intstat_0;  /* 0x190 */
-			uint32  h2d_intmask_0;	/* 0x194 */
-			uint32  d2h_intstat_0;  /* 0x198 */
-			uint32  d2h_intmask_0;  /* 0x19c */
-			uint32	ltr_state;	/* 0x1A0 */
-			uint32	pwr_int_status;	/* 0x1A4 */
-			uint32	pwr_int_mask;	/* 0x1A8 */
-			uint32  PAD[13]; 	/* 0x1AC - 0x1DF */
-			uint32  clk_ctl_st;	/* 0x1E0 */
-			uint32  PAD[7]; 	/* 0x1E4 - 0x1FF */
-			pcie_devdmaregs_t  h2d0_dmaregs; /* 0x200 - 0x23c */
-			pcie_devdmaregs_t  d2h0_dmaregs; /* 0x240 - 0x27c */
-			pcie_devdmaregs_t  h2d1_dmaregs; /* 0x280 - 0x2bc */
-			pcie_devdmaregs_t  d2h1_dmaregs; /* 0x2c0 - 0x2fc */
-			pcie_devdmaregs_t  h2d2_dmaregs; /* 0x300 - 0x33c */
-			pcie_devdmaregs_t  d2h2_dmaregs; /* 0x340 - 0x37c */
-			pcie_devdmaregs_t  h2d3_dmaregs; /* 0x380 - 0x3bc */
-			pcie_devdmaregs_t  d2h3_dmaregs; /* 0x3c0 - 0x3fc */
-		} pcie2;
-	} u;
-	uint32 pciecfg[4][64];	/* 0x400 - 0x7FF, PCIE Cfg Space */
-	uint16 sprom[64];	/* SPROM shadow Area */
-} sbpcieregs_t;
-
-/* PCI control */
-#define PCIE_RST_OE	0x01	/* When set, drives PCI_RESET out to pin */
-#define PCIE_RST	0x02	/* Value driven out to pin */
-#define PCIE_SPERST	0x04	/* SurvivePeRst */
-#define PCIE_DISABLE_L1CLK_GATING	0x10
-#define PCIE_DLYPERST	0x100	/* Delay PeRst to CoE Core */
-#define PCIE_DISSPROMLD	0x200	/* DisableSpromLoadOnPerst */
-#define PCIE_WakeModeL2	0x1000	/* Wake on L2 */
-#define PCIE_PipeIddqDisable0	0x8000	/* Disable assertion of pcie_pipe_iddq during L1.2 and L2 */
-#define PCIE_PipeIddqDisable1	0x10000	/* Disable assertion of pcie_pipe_iddq during L2 */
-
-#define	PCIE_CFGADDR	0x120	/* offsetof(configaddr) */
-#define	PCIE_CFGDATA	0x124	/* offsetof(configdata) */
-
-/* Interrupt status/mask */
-#define PCIE_INTA	0x01	/* PCIE INTA message is received */
-#define PCIE_INTB	0x02	/* PCIE INTB message is received */
-#define PCIE_INTFATAL	0x04	/* PCIE INTFATAL message is received */
-#define PCIE_INTNFATAL	0x08	/* PCIE INTNONFATAL message is received */
-#define PCIE_INTCORR	0x10	/* PCIE INTCORR message is received */
-#define PCIE_INTPME	0x20	/* PCIE INTPME message is received */
-#define PCIE_PERST	0x40	/* PCIE Reset Interrupt */
-
-#define PCIE_INT_MB_FN0_0 0x0100 /* PCIE to SB Mailbox int Fn0.0 is received */
-#define PCIE_INT_MB_FN0_1 0x0200 /* PCIE to SB Mailbox int Fn0.1 is received */
-#define PCIE_INT_MB_FN1_0 0x0400 /* PCIE to SB Mailbox int Fn1.0 is received */
-#define PCIE_INT_MB_FN1_1 0x0800 /* PCIE to SB Mailbox int Fn1.1 is received */
-#define PCIE_INT_MB_FN2_0 0x1000 /* PCIE to SB Mailbox int Fn2.0 is received */
-#define PCIE_INT_MB_FN2_1 0x2000 /* PCIE to SB Mailbox int Fn2.1 is received */
-#define PCIE_INT_MB_FN3_0 0x4000 /* PCIE to SB Mailbox int Fn3.0 is received */
-#define PCIE_INT_MB_FN3_1 0x8000 /* PCIE to SB Mailbox int Fn3.1 is received */
-
-/* PCIE MailboxInt/MailboxIntMask register */
-#define PCIE_MB_TOSB_FN0_0   	0x0001 /* write to assert PCIEtoSB Mailbox interrupt */
-#define PCIE_MB_TOSB_FN0_1   	0x0002
-#define PCIE_MB_TOSB_FN1_0   	0x0004
-#define PCIE_MB_TOSB_FN1_1   	0x0008
-#define PCIE_MB_TOSB_FN2_0   	0x0010
-#define PCIE_MB_TOSB_FN2_1   	0x0020
-#define PCIE_MB_TOSB_FN3_0   	0x0040
-#define PCIE_MB_TOSB_FN3_1   	0x0080
-#define PCIE_MB_TOPCIE_FN0_0 	0x0100 /* int status/mask for SBtoPCIE Mailbox interrupts */
-#define PCIE_MB_TOPCIE_FN0_1 	0x0200
-#define PCIE_MB_TOPCIE_FN1_0 	0x0400
-#define PCIE_MB_TOPCIE_FN1_1 	0x0800
-#define PCIE_MB_TOPCIE_FN2_0 	0x1000
-#define PCIE_MB_TOPCIE_FN2_1 	0x2000
-#define PCIE_MB_TOPCIE_FN3_0 	0x4000
-#define PCIE_MB_TOPCIE_FN3_1 	0x8000
-#define	PCIE_MB_TOPCIE_D2H0_DB0	0x10000
-#define	PCIE_MB_TOPCIE_D2H0_DB1	0x20000
-#define	PCIE_MB_TOPCIE_D2H1_DB0	0x40000
-#define	PCIE_MB_TOPCIE_D2H1_DB1	0x80000
-#define	PCIE_MB_TOPCIE_D2H2_DB0	0x100000
-#define	PCIE_MB_TOPCIE_D2H2_DB1	0x200000
-#define	PCIE_MB_TOPCIE_D2H3_DB0	0x400000
-#define	PCIE_MB_TOPCIE_D2H3_DB1	0x800000
-
-#define PCIE_MB_D2H_MB_MASK		\
-	(PCIE_MB_TOPCIE_D2H0_DB0 | PCIE_MB_TOPCIE_D2H0_DB1 |	\
-	PCIE_MB_TOPCIE_D2H1_DB0  | PCIE_MB_TOPCIE_D2H1_DB1 |	\
-	PCIE_MB_TOPCIE_D2H2_DB0  | PCIE_MB_TOPCIE_D2H2_DB1 |	\
-	PCIE_MB_TOPCIE_D2H3_DB0  | PCIE_MB_TOPCIE_D2H3_DB1)
-
-/* SB to PCIE translation masks */
-#define SBTOPCIE0_MASK	0xfc000000
-#define SBTOPCIE1_MASK	0xfc000000
-#define SBTOPCIE2_MASK	0xc0000000
-
-/* Access type bits (0:1) */
-#define SBTOPCIE_MEM	0
-#define SBTOPCIE_IO	1
-#define SBTOPCIE_CFG0	2
-#define SBTOPCIE_CFG1	3
-
-/* Prefetch enable bit 2 */
-#define SBTOPCIE_PF		4
-
-/* Write Burst enable for memory write bit 3 */
-#define SBTOPCIE_WR_BURST	8
-
-/* config access */
-#define CONFIGADDR_FUNC_MASK	0x7000
-#define CONFIGADDR_FUNC_SHF	12
-#define CONFIGADDR_REG_MASK	0x0FFF
-#define CONFIGADDR_REG_SHF	0
-
-#define PCIE_CONFIG_INDADDR(f, r)	((((f) & CONFIGADDR_FUNC_MASK) << CONFIGADDR_FUNC_SHF) | \
-			                 (((r) & CONFIGADDR_REG_MASK) << CONFIGADDR_REG_SHF))
-
-/* PCIE protocol regs Indirect Address */
-#define PCIEADDR_PROT_MASK	0x300
-#define PCIEADDR_PROT_SHF	8
-#define PCIEADDR_PL_TLP		0
-#define PCIEADDR_PL_DLLP	1
-#define PCIEADDR_PL_PLP		2
-
-/* PCIE protocol PHY diagnostic registers */
-#define	PCIE_PLP_MODEREG		0x200 /* Mode */
-#define	PCIE_PLP_STATUSREG		0x204 /* Status */
-#define PCIE_PLP_LTSSMCTRLREG		0x208 /* LTSSM control */
-#define PCIE_PLP_LTLINKNUMREG		0x20c /* Link Training Link number */
-#define PCIE_PLP_LTLANENUMREG		0x210 /* Link Training Lane number */
-#define PCIE_PLP_LTNFTSREG		0x214 /* Link Training N_FTS */
-#define PCIE_PLP_ATTNREG		0x218 /* Attention */
-#define PCIE_PLP_ATTNMASKREG		0x21C /* Attention Mask */
-#define PCIE_PLP_RXERRCTR		0x220 /* Rx Error */
-#define PCIE_PLP_RXFRMERRCTR		0x224 /* Rx Framing Error */
-#define PCIE_PLP_RXERRTHRESHREG		0x228 /* Rx Error threshold */
-#define PCIE_PLP_TESTCTRLREG		0x22C /* Test Control reg */
-#define PCIE_PLP_SERDESCTRLOVRDREG	0x230 /* SERDES Control Override */
-#define PCIE_PLP_TIMINGOVRDREG		0x234 /* Timing param override */
-#define PCIE_PLP_RXTXSMDIAGREG		0x238 /* RXTX State Machine Diag */
-#define PCIE_PLP_LTSSMDIAGREG		0x23C /* LTSSM State Machine Diag */
-
-/* PCIE protocol DLLP diagnostic registers */
-#define PCIE_DLLP_LCREG			0x100 /* Link Control */
-#define PCIE_DLLP_LSREG			0x104 /* Link Status */
-#define PCIE_DLLP_LAREG			0x108 /* Link Attention */
-#define PCIE_DLLP_LAMASKREG		0x10C /* Link Attention Mask */
-#define PCIE_DLLP_NEXTTXSEQNUMREG	0x110 /* Next Tx Seq Num */
-#define PCIE_DLLP_ACKEDTXSEQNUMREG	0x114 /* Acked Tx Seq Num */
-#define PCIE_DLLP_PURGEDTXSEQNUMREG	0x118 /* Purged Tx Seq Num */
-#define PCIE_DLLP_RXSEQNUMREG		0x11C /* Rx Sequence Number */
-#define PCIE_DLLP_LRREG			0x120 /* Link Replay */
-#define PCIE_DLLP_LACKTOREG		0x124 /* Link Ack Timeout */
-#define PCIE_DLLP_PMTHRESHREG		0x128 /* Power Management Threshold */
-#define PCIE_DLLP_RTRYWPREG		0x12C /* Retry buffer write ptr */
-#define PCIE_DLLP_RTRYRPREG		0x130 /* Retry buffer Read ptr */
-#define PCIE_DLLP_RTRYPPREG		0x134 /* Retry buffer Purged ptr */
-#define PCIE_DLLP_RTRRWREG		0x138 /* Retry buffer Read/Write */
-#define PCIE_DLLP_ECTHRESHREG		0x13C /* Error Count Threshold */
-#define PCIE_DLLP_TLPERRCTRREG		0x140 /* TLP Error Counter */
-#define PCIE_DLLP_ERRCTRREG		0x144 /* Error Counter */
-#define PCIE_DLLP_NAKRXCTRREG		0x148 /* NAK Received Counter */
-#define PCIE_DLLP_TESTREG		0x14C /* Test */
-#define PCIE_DLLP_PKTBIST		0x150 /* Packet BIST */
-#define PCIE_DLLP_PCIE11		0x154 /* DLLP PCIE 1.1 reg */
-
-#define PCIE_DLLP_LSREG_LINKUP		(1 << 16)
-
-/* PCIE protocol TLP diagnostic registers */
-#define PCIE_TLP_CONFIGREG		0x000 /* Configuration */
-#define PCIE_TLP_WORKAROUNDSREG		0x004 /* TLP Workarounds */
-#define PCIE_TLP_WRDMAUPPER		0x010 /* Write DMA Upper Address */
-#define PCIE_TLP_WRDMALOWER		0x014 /* Write DMA Lower Address */
-#define PCIE_TLP_WRDMAREQ_LBEREG	0x018 /* Write DMA Len/ByteEn Req */
-#define PCIE_TLP_RDDMAUPPER		0x01C /* Read DMA Upper Address */
-#define PCIE_TLP_RDDMALOWER		0x020 /* Read DMA Lower Address */
-#define PCIE_TLP_RDDMALENREG		0x024 /* Read DMA Len Req */
-#define PCIE_TLP_MSIDMAUPPER		0x028 /* MSI DMA Upper Address */
-#define PCIE_TLP_MSIDMALOWER		0x02C /* MSI DMA Lower Address */
-#define PCIE_TLP_MSIDMALENREG		0x030 /* MSI DMA Len Req */
-#define PCIE_TLP_SLVREQLENREG		0x034 /* Slave Request Len */
-#define PCIE_TLP_FCINPUTSREQ		0x038 /* Flow Control Inputs */
-#define PCIE_TLP_TXSMGRSREQ		0x03C /* Tx StateMachine and Gated Req */
-#define PCIE_TLP_ADRACKCNTARBLEN	0x040 /* Address Ack XferCnt and ARB Len */
-#define PCIE_TLP_DMACPLHDR0		0x044 /* DMA Completion Hdr 0 */
-#define PCIE_TLP_DMACPLHDR1		0x048 /* DMA Completion Hdr 1 */
-#define PCIE_TLP_DMACPLHDR2		0x04C /* DMA Completion Hdr 2 */
-#define PCIE_TLP_DMACPLMISC0		0x050 /* DMA Completion Misc0 */
-#define PCIE_TLP_DMACPLMISC1		0x054 /* DMA Completion Misc1 */
-#define PCIE_TLP_DMACPLMISC2		0x058 /* DMA Completion Misc2 */
-#define PCIE_TLP_SPTCTRLLEN		0x05C /* Split Controller Req len */
-#define PCIE_TLP_SPTCTRLMSIC0		0x060 /* Split Controller Misc 0 */
-#define PCIE_TLP_SPTCTRLMSIC1		0x064 /* Split Controller Misc 1 */
-#define PCIE_TLP_BUSDEVFUNC		0x068 /* Bus/Device/Func */
-#define PCIE_TLP_RESETCTR		0x06C /* Reset Counter */
-#define PCIE_TLP_RTRYBUF		0x070 /* Retry Buffer value */
-#define PCIE_TLP_TGTDEBUG1		0x074 /* Target Debug Reg1 */
-#define PCIE_TLP_TGTDEBUG2		0x078 /* Target Debug Reg2 */
-#define PCIE_TLP_TGTDEBUG3		0x07C /* Target Debug Reg3 */
-#define PCIE_TLP_TGTDEBUG4		0x080 /* Target Debug Reg4 */
-
-/* PCIE2 MDIO register offsets */
-#define PCIE2_MDIO_CONTROL    0x128
-#define PCIE2_MDIO_WR_DATA    0x12C
-#define PCIE2_MDIO_RD_DATA    0x130
-
-
-/* MDIO control */
-#define MDIOCTL_DIVISOR_MASK		0x7f	/* clock to be used on MDIO */
-#define MDIOCTL_DIVISOR_VAL		0x2
-#define MDIOCTL_PREAM_EN		0x80	/* Enable preamble sequnce */
-#define MDIOCTL_ACCESS_DONE		0x100   /* Tranaction complete */
-
-/* MDIO Data */
-#define MDIODATA_MASK			0x0000ffff	/* data 2 bytes */
-#define MDIODATA_TA			0x00020000	/* Turnaround */
-#define MDIODATA_REGADDR_SHF_OLD	18		/* Regaddr shift (rev < 10) */
-#define MDIODATA_REGADDR_MASK_OLD	0x003c0000	/* Regaddr Mask (rev < 10) */
-#define MDIODATA_DEVADDR_SHF_OLD	22		/* Physmedia devaddr shift (rev < 10) */
-#define MDIODATA_DEVADDR_MASK_OLD	0x0fc00000	/* Physmedia devaddr Mask (rev < 10) */
-#define MDIODATA_REGADDR_SHF		18		/* Regaddr shift */
-#define MDIODATA_REGADDR_MASK		0x007c0000	/* Regaddr Mask */
-#define MDIODATA_DEVADDR_SHF		23		/* Physmedia devaddr shift */
-#define MDIODATA_DEVADDR_MASK		0x0f800000	/* Physmedia devaddr Mask */
-#define MDIODATA_WRITE			0x10000000	/* write Transaction */
-#define MDIODATA_READ			0x20000000	/* Read Transaction */
-#define MDIODATA_START			0x40000000	/* start of Transaction */
-
-#define MDIODATA_DEV_ADDR		0x0		/* dev address for serdes */
-#define	MDIODATA_BLK_ADDR		0x1F		/* blk address for serdes */
-
-/* MDIO control/wrData/rdData register defines for PCIE Gen 2 */
-#define MDIOCTL2_DIVISOR_MASK		0x7f	/* clock to be used on MDIO */
-#define MDIOCTL2_DIVISOR_VAL		0x2
-#define MDIOCTL2_REGADDR_SHF		8		/* Regaddr shift */
-#define MDIOCTL2_REGADDR_MASK		0x00FFFF00	/* Regaddr Mask */
-#define MDIOCTL2_DEVADDR_SHF		24		/* Physmedia devaddr shift */
-#define MDIOCTL2_DEVADDR_MASK		0x0f000000	/* Physmedia devaddr Mask */
-#define MDIOCTL2_SLAVE_BYPASS		0x10000000	/* IP slave bypass */
-#define MDIOCTL2_READ			0x20000000	/* IP slave bypass */
-
-#define MDIODATA2_DONE			0x80000000	/* rd/wr transaction done */
-#define MDIODATA2_MASK			0x7FFFFFFF	/* rd/wr transaction data */
-#define MDIODATA2_DEVADDR_SHF		4		/* Physmedia devaddr shift */
-
-
-/* MDIO devices (SERDES modules)
- *  unlike old pcie cores (rev < 10), rev10 pcie serde organizes registers into a few blocks.
- *  two layers mapping (blockidx, register offset) is required
- */
-#define MDIO_DEV_IEEE0		0x000
-#define MDIO_DEV_IEEE1		0x001
-#define MDIO_DEV_BLK0		0x800
-#define MDIO_DEV_BLK1		0x801
-#define MDIO_DEV_BLK2		0x802
-#define MDIO_DEV_BLK3		0x803
-#define MDIO_DEV_BLK4		0x804
-#define MDIO_DEV_TXPLL		0x808	/* TXPLL register block idx */
-#define MDIO_DEV_TXCTRL0	0x820
-#define MDIO_DEV_SERDESID	0x831
-#define MDIO_DEV_RXCTRL0	0x840
-
-
-/* XgxsBlk1_A Register Offsets */
-#define BLK1_PWR_MGMT0		0x16
-#define BLK1_PWR_MGMT1		0x17
-#define BLK1_PWR_MGMT2		0x18
-#define BLK1_PWR_MGMT3		0x19
-#define BLK1_PWR_MGMT4		0x1A
-
-/* serdes regs (rev < 10) */
-#define MDIODATA_DEV_PLL       		0x1d	/* SERDES PLL Dev */
-#define MDIODATA_DEV_TX        		0x1e	/* SERDES TX Dev */
-#define MDIODATA_DEV_RX        		0x1f	/* SERDES RX Dev */
-	/* SERDES RX registers */
-#define SERDES_RX_CTRL			1	/* Rx cntrl */
-#define SERDES_RX_TIMER1		2	/* Rx Timer1 */
-#define SERDES_RX_CDR			6	/* CDR */
-#define SERDES_RX_CDRBW			7	/* CDR BW */
-
-	/* SERDES RX control register */
-#define SERDES_RX_CTRL_FORCE		0x80	/* rxpolarity_force */
-#define SERDES_RX_CTRL_POLARITY		0x40	/* rxpolarity_value */
-
-	/* SERDES PLL registers */
-#define SERDES_PLL_CTRL                 1       /* PLL control reg */
-#define PLL_CTRL_FREQDET_EN             0x4000  /* bit 14 is FREQDET on */
-
-/* Power management threshold */
-#define PCIE_L0THRESHOLDTIME_MASK       0xFF00	/* bits 0 - 7 */
-#define PCIE_L1THRESHOLDTIME_MASK       0xFF00	/* bits 8 - 15 */
-#define PCIE_L1THRESHOLDTIME_SHIFT      8	/* PCIE_L1THRESHOLDTIME_SHIFT */
-#define PCIE_L1THRESHOLD_WARVAL         0x72	/* WAR value */
-#define PCIE_ASPMTIMER_EXTEND		0x01000000	/* > rev7: enable extend ASPM timer */
-
-/* SPROM offsets */
-#define SRSH_ASPM_OFFSET		4	/* word 4 */
-#define SRSH_ASPM_ENB			0x18	/* bit 3, 4 */
-#define SRSH_ASPM_L1_ENB		0x10	/* bit 4 */
-#define SRSH_ASPM_L0s_ENB		0x8	/* bit 3 */
-#define SRSH_PCIE_MISC_CONFIG		5	/* word 5 */
-#define SRSH_L23READY_EXIT_NOPERST	0x8000	/* bit 15 */
-#define SRSH_CLKREQ_OFFSET_REV5		20	/* word 20 for srom rev <= 5 */
-#define SRSH_CLKREQ_OFFSET_REV8		52	/* word 52 for srom rev 8 */
-#define SRSH_CLKREQ_ENB			0x0800	/* bit 11 */
-#define SRSH_BD_OFFSET                  6       /* word 6 */
-#define SRSH_AUTOINIT_OFFSET            18      /* auto initialization enable */
-
-/* Linkcontrol reg offset in PCIE Cap */
-#define PCIE_CAP_LINKCTRL_OFFSET	16	/* linkctrl offset in pcie cap */
-#define PCIE_CAP_LCREG_ASPML0s		0x01	/* ASPM L0s in linkctrl */
-#define PCIE_CAP_LCREG_ASPML1		0x02	/* ASPM L1 in linkctrl */
-#define PCIE_CLKREQ_ENAB		0x100	/* CLKREQ Enab in linkctrl */
-#define PCIE_LINKSPEED_MASK       	0xF0000	/* bits 0 - 3 of high word */
-#define PCIE_LINKSPEED_SHIFT      	16	/* PCIE_LINKSPEED_SHIFT */
-
-/* Devcontrol reg offset in PCIE Cap */
-#define PCIE_CAP_DEVCTRL_OFFSET		8	/* devctrl offset in pcie cap */
-#define PCIE_CAP_DEVCTRL_MRRS_MASK	0x7000	/* Max read request size mask */
-#define PCIE_CAP_DEVCTRL_MRRS_SHIFT	12	/* Max read request size shift */
-#define PCIE_CAP_DEVCTRL_MRRS_128B	0	/* 128 Byte */
-#define PCIE_CAP_DEVCTRL_MRRS_256B	1	/* 256 Byte */
-#define PCIE_CAP_DEVCTRL_MRRS_512B	2	/* 512 Byte */
-#define PCIE_CAP_DEVCTRL_MRRS_1024B	3	/* 1024 Byte */
-#define PCIE_CAP_DEVCTRL_MPS_MASK	0x00e0	/* Max payload size mask */
-#define PCIE_CAP_DEVCTRL_MPS_SHIFT	5	/* Max payload size shift */
-#define PCIE_CAP_DEVCTRL_MPS_128B	0	/* 128 Byte */
-#define PCIE_CAP_DEVCTRL_MPS_256B	1	/* 256 Byte */
-#define PCIE_CAP_DEVCTRL_MPS_512B	2	/* 512 Byte */
-#define PCIE_CAP_DEVCTRL_MPS_1024B	3	/* 1024 Byte */
-
-#define PCIE_ASPM_ENAB			3	/* ASPM L0s & L1 in linkctrl */
-#define PCIE_ASPM_L1_ENAB		2	/* ASPM L0s & L1 in linkctrl */
-#define PCIE_ASPM_L0s_ENAB		1	/* ASPM L0s & L1 in linkctrl */
-#define PCIE_ASPM_DISAB			0	/* ASPM L0s & L1 in linkctrl */
-
-#define PCIE_ASPM_L11_ENAB		8	/* ASPM L1.1 in PML1_sub_control2 */
-#define PCIE_ASPM_L12_ENAB		4	/* ASPM L1.2 in PML1_sub_control2 */
-
-/* Devcontrol2 reg offset in PCIE Cap */
-#define PCIE_CAP_DEVCTRL2_OFFSET	0x28	/* devctrl2 offset in pcie cap */
-#define PCIE_CAP_DEVCTRL2_LTR_ENAB_MASK	0x400	/* Latency Tolerance Reporting Enable */
-#define PCIE_CAP_DEVCTRL2_OBFF_ENAB_SHIFT 13	/* Enable OBFF mechanism, select signaling method */
-#define PCIE_CAP_DEVCTRL2_OBFF_ENAB_MASK 0x6000	/* Enable OBFF mechanism, select signaling method */
-
-/* LTR registers in PCIE Cap */
-#define PCIE_LTR0_REG_OFFSET	0x844	/* ltr0_reg offset in pcie cap */
-#define PCIE_LTR1_REG_OFFSET	0x848	/* ltr1_reg offset in pcie cap */
-#define PCIE_LTR2_REG_OFFSET	0x84c	/* ltr2_reg offset in pcie cap */
-#define PCIE_LTR0_REG_DEFAULT_60	0x883c883c	/* active latency default to 60usec */
-#define PCIE_LTR0_REG_DEFAULT_150	0x88968896	/* active latency default to 150usec */
-#define PCIE_LTR1_REG_DEFAULT		0x88648864	/* idle latency default to 100usec */
-#define PCIE_LTR2_REG_DEFAULT		0x90039003	/* sleep latency default to 3msec */
-
-/* Status reg PCIE_PLP_STATUSREG */
-#define PCIE_PLP_POLARITYINV_STAT	0x10
-
-
-/* PCIE BRCM Vendor CAP REVID reg  bits */
-#define BRCMCAP_PCIEREV_CT_MASK			0xF00
-#define BRCMCAP_PCIEREV_CT_SHIFT		8
-#define BRCMCAP_PCIEREV_REVID_MASK		0xFF
-#define BRCMCAP_PCIEREV_REVID_SHIFT		0
-
-#define PCIE_REVREG_CT_PCIE1		0
-#define PCIE_REVREG_CT_PCIE2		1
-
-/* PCIE GEN2 specific defines */
-/* PCIE BRCM Vendor Cap offsets w.r.t to vendor cap ptr */
-#define PCIE2R0_BRCMCAP_REVID_OFFSET		4
-#define PCIE2R0_BRCMCAP_BAR0_WIN0_WRAP_OFFSET	8
-#define PCIE2R0_BRCMCAP_BAR0_WIN2_OFFSET	12
-#define PCIE2R0_BRCMCAP_BAR0_WIN2_WRAP_OFFSET	16
-#define PCIE2R0_BRCMCAP_BAR0_WIN_OFFSET		20
-#define PCIE2R0_BRCMCAP_BAR1_WIN_OFFSET		24
-#define PCIE2R0_BRCMCAP_SPROM_CTRL_OFFSET	28
-#define PCIE2R0_BRCMCAP_BAR2_WIN_OFFSET		32
-#define PCIE2R0_BRCMCAP_INTSTATUS_OFFSET	36
-#define PCIE2R0_BRCMCAP_INTMASK_OFFSET		40
-#define PCIE2R0_BRCMCAP_PCIE2SB_MB_OFFSET	44
-#define PCIE2R0_BRCMCAP_BPADDR_OFFSET		48
-#define PCIE2R0_BRCMCAP_BPDATA_OFFSET		52
-#define PCIE2R0_BRCMCAP_CLKCTLSTS_OFFSET	56
-
-/* definition of configuration space registers of PCIe gen2
- * http://hwnbu-twiki.sj.broadcom.com/twiki/pub/Mwgroup/CurrentPcieGen2ProgramGuide/pcie_ep.htm
- */
-#define PCIECFGREG_STATUS_CMD		0x4
-#define PCIECFGREG_PM_CSR		0x4C
-#define PCIECFGREG_MSI_CAP		0x58
-#define PCIECFGREG_MSI_ADDR_L		0x5C
-#define PCIECFGREG_MSI_ADDR_H		0x60
-#define PCIECFGREG_MSI_DATA		0x64
-#define PCIECFGREG_LINK_STATUS_CTRL	0xBC
-#define PCIECFGREG_LINK_STATUS_CTRL2	0xDC
-#define PCIECFGREG_RBAR_CTRL		0x228
-#define PCIECFGREG_PML1_SUB_CTRL1	0x248
-#define PCIECFGREG_REG_BAR2_CONFIG	0x4E0
-#define PCIECFGREG_REG_BAR3_CONFIG	0x4F4
-#define PCIECFGREG_PDL_CTRL1		0x1004
-#define PCIECFGREG_PDL_IDDQ		0x1814
-#define PCIECFGREG_REG_PHY_CTL7		0x181c
-
-/* PCIECFGREG_PML1_SUB_CTRL1 Bit Definition */
-#define PCI_PM_L1_2_ENA_MASK		0x00000001	/* PCI-PM L1.2 Enabled */
-#define PCI_PM_L1_1_ENA_MASK		0x00000002	/* PCI-PM L1.1 Enabled */
-#define ASPM_L1_2_ENA_MASK		0x00000004	/* ASPM L1.2 Enabled */
-#define ASPM_L1_1_ENA_MASK		0x00000008	/* ASPM L1.1 Enabled */
-
-/* PCIe gen2 mailbox interrupt masks */
-#define I_MB    0x3
-#define I_BIT0  0x1
-#define I_BIT1  0x2
-
-/* PCIE gen2 config regs */
-#define PCIIntstatus	0x090
-#define PCIIntmask	0x094
-#define PCISBMbx	0x98
-
-/* enumeration Core regs */
-#define PCIH2D_MailBox  0x140
-#define PCIH2D_DB1 0x144
-#define PCID2H_MailBox  0x148
-#define PCIMailBoxInt	0x48
-#define PCIMailBoxMask	0x4C
-
-#define I_F0_B0         (0x1 << 8) /* Mail box interrupt Function 0 interrupt, bit 0 */
-#define I_F0_B1         (0x1 << 9) /* Mail box interrupt Function 0 interrupt, bit 1 */
-
-#define PCIECFGREG_DEVCONTROL	0xB4
-#define PCIECFGREG_DEVCONTROL_MRRS_SHFT	12
-#define PCIECFGREG_DEVCONTROL_MRRS_MASK	(0x7 << PCIECFGREG_DEVCONTROL_MRRS_SHFT)
-
-/* SROM hardware region */
-#define SROM_OFFSET_BAR1_CTRL  52
-
-#define BAR1_ENC_SIZE_MASK	0x000e
-#define BAR1_ENC_SIZE_SHIFT	1
-
-#define BAR1_ENC_SIZE_1M	0
-#define BAR1_ENC_SIZE_2M	1
-#define BAR1_ENC_SIZE_4M	2
-
-#define PCIEGEN2_CAP_DEVSTSCTRL2_OFFSET		0xD4
-#define PCIEGEN2_CAP_DEVSTSCTRL2_LTRENAB	0x400
-
-/*
- * Latency Tolerance Reporting (LTR) states
- * Active has the least tolerant latency requirement
- * Sleep is most tolerant
- */
-#define LTR_ACTIVE				2
-#define LTR_ACTIVE_IDLE				1
-#define LTR_SLEEP				0
-#define LTR_FINAL_MASK				0x300
-#define LTR_FINAL_SHIFT				8
-
-/* pwrinstatus, pwrintmask regs */
-#define PCIEGEN2_PWRINT_D0_STATE_SHIFT		0
-#define PCIEGEN2_PWRINT_D1_STATE_SHIFT		1
-#define PCIEGEN2_PWRINT_D2_STATE_SHIFT		2
-#define PCIEGEN2_PWRINT_D3_STATE_SHIFT		3
-#define PCIEGEN2_PWRINT_L0_LINK_SHIFT		4
-#define PCIEGEN2_PWRINT_L0s_LINK_SHIFT		5
-#define PCIEGEN2_PWRINT_L1_LINK_SHIFT		6
-#define PCIEGEN2_PWRINT_L2_L3_LINK_SHIFT	7
-#define PCIEGEN2_PWRINT_OBFF_CHANGE_SHIFT	8
-
-#define PCIEGEN2_PWRINT_D0_STATE_MASK		(1 << PCIEGEN2_PWRINT_D0_STATE_SHIFT)
-#define PCIEGEN2_PWRINT_D1_STATE_MASK		(1 << PCIEGEN2_PWRINT_D1_STATE_SHIFT)
-#define PCIEGEN2_PWRINT_D2_STATE_MASK		(1 << PCIEGEN2_PWRINT_D2_STATE_SHIFT)
-#define PCIEGEN2_PWRINT_D3_STATE_MASK		(1 << PCIEGEN2_PWRINT_D3_STATE_SHIFT)
-#define PCIEGEN2_PWRINT_L0_LINK_MASK		(1 << PCIEGEN2_PWRINT_L0_LINK_SHIFT)
-#define PCIEGEN2_PWRINT_L0s_LINK_MASK		(1 << PCIEGEN2_PWRINT_L0s_LINK_SHIFT)
-#define PCIEGEN2_PWRINT_L1_LINK_MASK		(1 << PCIEGEN2_PWRINT_L1_LINK_SHIFT)
-#define PCIEGEN2_PWRINT_L2_L3_LINK_MASK		(1 << PCIEGEN2_PWRINT_L2_L3_LINK_SHIFT)
-#define PCIEGEN2_PWRINT_OBFF_CHANGE_MASK	(1 << PCIEGEN2_PWRINT_OBFF_CHANGE_SHIFT)
-
-/* sbtopcie mail box */
-#define SBTOPCIE_MB_FUNC0_SHIFT 8
-#define SBTOPCIE_MB_FUNC1_SHIFT 10
-#define SBTOPCIE_MB_FUNC2_SHIFT 12
-#define SBTOPCIE_MB_FUNC3_SHIFT 14
-
-/* pcieiocstatus */
-#define PCIEGEN2_IOC_D0_STATE_SHIFT		8
-#define PCIEGEN2_IOC_D1_STATE_SHIFT		9
-#define PCIEGEN2_IOC_D2_STATE_SHIFT		10
-#define PCIEGEN2_IOC_D3_STATE_SHIFT		11
-#define PCIEGEN2_IOC_L0_LINK_SHIFT		12
-#define PCIEGEN2_IOC_L1_LINK_SHIFT		13
-#define PCIEGEN2_IOC_L1L2_LINK_SHIFT		14
-#define PCIEGEN2_IOC_L2_L3_LINK_SHIFT		15
-
-#define PCIEGEN2_IOC_D0_STATE_MASK		(1 << PCIEGEN2_IOC_D0_STATE_SHIFT)
-#define PCIEGEN2_IOC_D1_STATE_MASK		(1 << PCIEGEN2_IOC_D1_STATE_SHIFT)
-#define PCIEGEN2_IOC_D2_STATE_MASK		(1 << PCIEGEN2_IOC_D2_STATE_SHIFT)
-#define PCIEGEN2_IOC_D3_STATE_MASK		(1 << PCIEGEN2_IOC_D3_STATE_SHIFT)
-#define PCIEGEN2_IOC_L0_LINK_MASK		(1 << PCIEGEN2_IOC_L0_LINK_SHIFT)
-#define PCIEGEN2_IOC_L1_LINK_MASK		(1 << PCIEGEN2_IOC_L1_LINK_SHIFT)
-#define PCIEGEN2_IOC_L1L2_LINK_MASK		(1 << PCIEGEN2_IOC_L1L2_LINK_SHIFT)
-#define PCIEGEN2_IOC_L2_L3_LINK_MASK		(1 << PCIEGEN2_IOC_L2_L3_LINK_SHIFT)
-
-/* stat_ctrl */
-#define PCIE_STAT_CTRL_RESET		0x1
-#define PCIE_STAT_CTRL_ENABLE		0x2
-#define PCIE_STAT_CTRL_INTENABLE	0x4
-#define PCIE_STAT_CTRL_INTSTATUS	0x8
-
-#ifdef BCMDRIVER
-void pcie_watchdog_reset(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs);
-void pcie_serdes_iddqdisable(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs);
-#endif /* BCMDRIVER */
-
-#endif	/* _PCIE_CORE_H */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11.h b/drivers/net/wireless/bcmdhd/include/proto/802.11.h
deleted file mode 100644
index 7aaea5d..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/802.11.h
+++ /dev/null
@@ -1,4445 +0,0 @@
-/*
- * Fundamental types and constants relating to 802.11
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: 802.11.h 556559 2015-05-14 01:48:17Z $
- */
-
-#ifndef _802_11_H_
-#define _802_11_H_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-#ifndef _NET_ETHERNET_H_
-#include <proto/ethernet.h>
-#endif
-
-#include <proto/wpa.h>
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-
-#define DOT11_TU_TO_US			1024	/* 802.11 Time Unit is 1024 microseconds */
-
-/* Generic 802.11 frame constants */
-#define DOT11_A3_HDR_LEN		24	/* d11 header length with A3 */
-#define DOT11_A4_HDR_LEN		30	/* d11 header length with A4 */
-#define DOT11_MAC_HDR_LEN		DOT11_A3_HDR_LEN	/* MAC header length */
-#define DOT11_FCS_LEN			4	/* d11 FCS length */
-#define DOT11_ICV_LEN			4	/* d11 ICV length */
-#define DOT11_ICV_AES_LEN		8	/* d11 ICV/AES length */
-#define DOT11_QOS_LEN			2	/* d11 QoS length */
-#define DOT11_HTC_LEN			4	/* d11 HT Control field length */
-
-#define DOT11_KEY_INDEX_SHIFT		6	/* d11 key index shift */
-#define DOT11_IV_LEN			4	/* d11 IV length */
-#define DOT11_IV_TKIP_LEN		8	/* d11 IV TKIP length */
-#define DOT11_IV_AES_OCB_LEN		4	/* d11 IV/AES/OCB length */
-#define DOT11_IV_AES_CCM_LEN		8	/* d11 IV/AES/CCM length */
-#define DOT11_IV_MAX_LEN		8	/* maximum iv len for any encryption */
-
-/* Includes MIC */
-#define DOT11_MAX_MPDU_BODY_LEN		2304	/* max MPDU body length */
-/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */
-#define DOT11_MAX_MPDU_LEN		(DOT11_A4_HDR_LEN + \
-					 DOT11_QOS_LEN + \
-					 DOT11_IV_AES_CCM_LEN + \
-					 DOT11_MAX_MPDU_BODY_LEN + \
-					 DOT11_ICV_LEN + \
-					 DOT11_FCS_LEN)	/* d11 max MPDU length */
-
-#define DOT11_MAX_SSID_LEN		32	/* d11 max ssid length */
-
-/* dot11RTSThreshold */
-#define DOT11_DEFAULT_RTS_LEN		2347	/* d11 default RTS length */
-#define DOT11_MAX_RTS_LEN		2347	/* d11 max RTS length */
-
-/* dot11FragmentationThreshold */
-#define DOT11_MIN_FRAG_LEN		256	/* d11 min fragmentation length */
-#define DOT11_MAX_FRAG_LEN		2346	/* Max frag is also limited by aMPDUMaxLength
-						* of the attached PHY
-						*/
-#define DOT11_DEFAULT_FRAG_LEN		2346	/* d11 default fragmentation length */
-
-/* dot11BeaconPeriod */
-#define DOT11_MIN_BEACON_PERIOD		1	/* d11 min beacon period */
-#define DOT11_MAX_BEACON_PERIOD		0xFFFF	/* d11 max beacon period */
-
-/* dot11DTIMPeriod */
-#define DOT11_MIN_DTIM_PERIOD		1	/* d11 min DTIM period */
-#define DOT11_MAX_DTIM_PERIOD		0xFF	/* d11 max DTIM period */
-
-/** 802.2 LLC/SNAP header used by 802.11 per 802.1H */
-#define DOT11_LLC_SNAP_HDR_LEN		8	/* d11 LLC/SNAP header length */
-#define DOT11_OUI_LEN			3	/* d11 OUI length */
-BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header {
-	uint8	dsap;				/* always 0xAA */
-	uint8	ssap;				/* always 0xAA */
-	uint8	ctl;				/* always 0x03 */
-	uint8	oui[DOT11_OUI_LEN];		/* RFC1042: 0x00 0x00 0x00
-						 * Bridge-Tunnel: 0x00 0x00 0xF8
-						 */
-	uint16	type;				/* ethertype */
-} BWL_POST_PACKED_STRUCT;
-
-/* RFC1042 header used by 802.11 per 802.1H */
-#define RFC1042_HDR_LEN	(ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN)	/* RCF1042 header length */
-
-/* Generic 802.11 MAC header */
-/**
- * N.B.: This struct reflects the full 4 address 802.11 MAC header.
- *		 The fields are defined such that the shorter 1, 2, and 3
- *		 address headers just use the first k fields.
- */
-BWL_PRE_PACKED_STRUCT struct dot11_header {
-	uint16			fc;		/* frame control */
-	uint16			durid;		/* duration/ID */
-	struct ether_addr	a1;		/* address 1 */
-	struct ether_addr	a2;		/* address 2 */
-	struct ether_addr	a3;		/* address 3 */
-	uint16			seq;		/* sequence control */
-	struct ether_addr	a4;		/* address 4 */
-} BWL_POST_PACKED_STRUCT;
-
-/* Control frames */
-
-BWL_PRE_PACKED_STRUCT struct dot11_rts_frame {
-	uint16			fc;		/* frame control */
-	uint16			durid;		/* duration/ID */
-	struct ether_addr	ra;		/* receiver address */
-	struct ether_addr	ta;		/* transmitter address */
-} BWL_POST_PACKED_STRUCT;
-#define	DOT11_RTS_LEN		16		/* d11 RTS frame length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_cts_frame {
-	uint16			fc;		/* frame control */
-	uint16			durid;		/* duration/ID */
-	struct ether_addr	ra;		/* receiver address */
-} BWL_POST_PACKED_STRUCT;
-#define	DOT11_CTS_LEN		10		/* d11 CTS frame length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_ack_frame {
-	uint16			fc;		/* frame control */
-	uint16			durid;		/* duration/ID */
-	struct ether_addr	ra;		/* receiver address */
-} BWL_POST_PACKED_STRUCT;
-#define	DOT11_ACK_LEN		10		/* d11 ACK frame length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame {
-	uint16			fc;		/* frame control */
-	uint16			durid;		/* AID */
-	struct ether_addr	bssid;		/* receiver address, STA in AP */
-	struct ether_addr	ta;		/* transmitter address */
-} BWL_POST_PACKED_STRUCT;
-#define	DOT11_PS_POLL_LEN	16		/* d11 PS poll frame length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame {
-	uint16			fc;		/* frame control */
-	uint16			durid;		/* duration/ID */
-	struct ether_addr	ra;		/* receiver address */
-	struct ether_addr	bssid;		/* transmitter address, STA in AP */
-} BWL_POST_PACKED_STRUCT;
-#define	DOT11_CS_END_LEN	16		/* d11 CF-END frame length */
-
-/**
- * RWL wifi protocol: The Vendor Specific Action frame is defined for vendor-specific signaling
- *  category+OUI+vendor specific content ( this can be variable)
- */
-BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific {
-	uint8	category;
-	uint8	OUI[3];
-	uint8	type;
-	uint8	subtype;
-	uint8	data[1040];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t;
-
-/** generic vendor specific action frame with variable length */
-BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr {
-	uint8	category;
-	uint8	OUI[3];
-	uint8	type;
-	uint8	subtype;
-	uint8	data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t;
-
-#define DOT11_ACTION_VS_HDR_LEN	6
-
-#define BCM_ACTION_OUI_BYTE0	0x00
-#define BCM_ACTION_OUI_BYTE1	0x90
-#define BCM_ACTION_OUI_BYTE2	0x4c
-
-/* BA/BAR Control parameters */
-#define DOT11_BA_CTL_POLICY_NORMAL	0x0000	/* normal ack */
-#define DOT11_BA_CTL_POLICY_NOACK	0x0001	/* no ack */
-#define DOT11_BA_CTL_POLICY_MASK	0x0001	/* ack policy mask */
-
-#define DOT11_BA_CTL_MTID		0x0002	/* multi tid BA */
-#define DOT11_BA_CTL_COMPRESSED		0x0004	/* compressed bitmap */
-
-#define DOT11_BA_CTL_NUMMSDU_MASK	0x0FC0	/* num msdu in bitmap mask */
-#define DOT11_BA_CTL_NUMMSDU_SHIFT	6	/* num msdu in bitmap shift */
-
-#define DOT11_BA_CTL_TID_MASK		0xF000	/* tid mask */
-#define DOT11_BA_CTL_TID_SHIFT		12	/* tid shift */
-
-/** control frame header (BA/BAR) */
-BWL_PRE_PACKED_STRUCT struct dot11_ctl_header {
-	uint16			fc;		/* frame control */
-	uint16			durid;		/* duration/ID */
-	struct ether_addr	ra;		/* receiver address */
-	struct ether_addr	ta;		/* transmitter address */
-} BWL_POST_PACKED_STRUCT;
-#define DOT11_CTL_HDR_LEN	16		/* control frame hdr len */
-
-/** BAR frame payload */
-BWL_PRE_PACKED_STRUCT struct dot11_bar {
-	uint16			bar_control;	/* BAR Control */
-	uint16			seqnum;		/* Starting Sequence control */
-} BWL_POST_PACKED_STRUCT;
-#define DOT11_BAR_LEN		4		/* BAR frame payload length */
-
-#define DOT11_BA_BITMAP_LEN	128		/* bitmap length */
-#define DOT11_BA_CMP_BITMAP_LEN	8		/* compressed bitmap length */
-/** BA frame payload */
-BWL_PRE_PACKED_STRUCT struct dot11_ba {
-	uint16			ba_control;	/* BA Control */
-	uint16			seqnum;		/* Starting Sequence control */
-	uint8			bitmap[DOT11_BA_BITMAP_LEN];	/* Block Ack Bitmap */
-} BWL_POST_PACKED_STRUCT;
-#define DOT11_BA_LEN		4		/* BA frame payload len (wo bitmap) */
-
-/** Management frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_management_header {
-	uint16			fc;		/* frame control */
-	uint16			durid;		/* duration/ID */
-	struct ether_addr	da;		/* receiver address */
-	struct ether_addr	sa;		/* transmitter address */
-	struct ether_addr	bssid;		/* BSS ID */
-	uint16			seq;		/* sequence control */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_management_header dot11_management_header_t;
-#define	DOT11_MGMT_HDR_LEN	24		/* d11 management header length */
-
-/* Management frame payloads */
-
-BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb {
-	uint32			timestamp[2];
-	uint16			beacon_interval;
-	uint16			capability;
-} BWL_POST_PACKED_STRUCT;
-#define	DOT11_BCN_PRB_LEN	12		/* 802.11 beacon/probe frame fixed length */
-#define	DOT11_BCN_PRB_FIXED_LEN	12		/* 802.11 beacon/probe frame fixed length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_auth {
-	uint16			alg;		/* algorithm */
-	uint16			seq;		/* sequence control */
-	uint16			status;		/* status code */
-} BWL_POST_PACKED_STRUCT;
-#define DOT11_AUTH_FIXED_LEN	6		/* length of auth frame without challenge IE */
-
-BWL_PRE_PACKED_STRUCT struct dot11_assoc_req {
-	uint16			capability;	/* capability information */
-	uint16			listen;		/* listen interval */
-} BWL_POST_PACKED_STRUCT;
-#define DOT11_ASSOC_REQ_FIXED_LEN	4	/* length of assoc frame without info elts */
-
-BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req {
-	uint16			capability;	/* capability information */
-	uint16			listen;		/* listen interval */
-	struct ether_addr	ap;		/* Current AP address */
-} BWL_POST_PACKED_STRUCT;
-#define DOT11_REASSOC_REQ_FIXED_LEN	10	/* length of assoc frame without info elts */
-
-BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp {
-	uint16			capability;	/* capability information */
-	uint16			status;		/* status code */
-	uint16			aid;		/* association ID */
-} BWL_POST_PACKED_STRUCT;
-#define DOT11_ASSOC_RESP_FIXED_LEN	6	/* length of assoc resp frame without info elts */
-
-BWL_PRE_PACKED_STRUCT struct dot11_action_measure {
-	uint8	category;
-	uint8	action;
-	uint8	token;
-	uint8	data[1];
-} BWL_POST_PACKED_STRUCT;
-#define DOT11_ACTION_MEASURE_LEN	3	/* d11 action measurement header length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width {
-	uint8	category;
-	uint8	action;
-	uint8	ch_width;
-} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops {
-	uint8	category;
-	uint8	action;
-	uint8	control;
-} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query {
-	uint8	category;
-	uint8	action;
-	uint16	id;
-} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct dot11_action_vht_oper_mode {
-	uint8	category;
-	uint8	action;
-	uint8	mode;
-} BWL_POST_PACKED_STRUCT;
-
-/* These lengths assume 64 MU groups, as specified in 802.11ac-2013 */
-#define DOT11_ACTION_GID_MEMBERSHIP_LEN  8    /* bytes */
-#define DOT11_ACTION_GID_USER_POS_LEN   16    /* bytes */
-BWL_PRE_PACKED_STRUCT struct dot11_action_group_id {
-	uint8   category;
-	uint8   action;
-	uint8   membership_status[DOT11_ACTION_GID_MEMBERSHIP_LEN];
-	uint8   user_position[DOT11_ACTION_GID_USER_POS_LEN];
-} BWL_POST_PACKED_STRUCT;
-
-#define SM_PWRSAVE_ENABLE	1
-#define SM_PWRSAVE_MODE		2
-
-/* ************* 802.11h related definitions. ************* */
-BWL_PRE_PACKED_STRUCT struct dot11_power_cnst {
-	uint8 id;
-	uint8 len;
-	uint8 power;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_power_cnst dot11_power_cnst_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_power_cap {
-	int8 min;
-	int8 max;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_power_cap dot11_power_cap_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep {
-	uint8 id;
-	uint8 len;
-	uint8 tx_pwr;
-	uint8 margin;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tpc_rep dot11_tpc_rep_t;
-#define DOT11_MNG_IE_TPC_REPORT_LEN	2 	/* length of IE data, not including 2 byte header */
-
-BWL_PRE_PACKED_STRUCT struct dot11_supp_channels {
-	uint8 id;
-	uint8 len;
-	uint8 first_channel;
-	uint8 num_channels;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_supp_channels dot11_supp_channels_t;
-
-/**
- * Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband
- * offset for 40MHz operation.  The possible 3 values are:
- * 1 = above control channel
- * 3 = below control channel
- * 0 = no extension channel
- */
-BWL_PRE_PACKED_STRUCT struct dot11_extch {
-	uint8	id;		/* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */
-	uint8	len;		/* IE length */
-	uint8	extch;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_extch dot11_extch_ie_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch {
-	uint8	id;		/* IE ID, 221, DOT11_MNG_PROPR_ID */
-	uint8	len;		/* IE length */
-	uint8	oui[3];
-	uint8	type;           /* type indicates what follows */
-	uint8	extch;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t;
-
-#define BRCM_EXTCH_IE_LEN	5
-#define BRCM_EXTCH_IE_TYPE	53	/* 802.11n ID not yet assigned */
-#define DOT11_EXTCH_IE_LEN	1
-#define DOT11_EXT_CH_MASK	0x03	/* extension channel mask */
-#define DOT11_EXT_CH_UPPER	0x01	/* ext. ch. on upper sb */
-#define DOT11_EXT_CH_LOWER	0x03	/* ext. ch. on lower sb */
-#define DOT11_EXT_CH_NONE	0x00	/* no extension ch.  */
-
-BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr {
-	uint8	category;
-	uint8	action;
-	uint8	data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_action_frmhdr dot11_action_frmhdr_t;
-#define DOT11_ACTION_FRMHDR_LEN	2
-
-/** CSA IE data structure */
-BWL_PRE_PACKED_STRUCT struct dot11_channel_switch {
-	uint8 id;	/* id DOT11_MNG_CHANNEL_SWITCH_ID */
-	uint8 len;	/* length of IE */
-	uint8 mode;	/* mode 0 or 1 */
-	uint8 channel;	/* channel switch to */
-	uint8 count;	/* number of beacons before switching */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_channel_switch dot11_chan_switch_ie_t;
-
-#define DOT11_SWITCH_IE_LEN	3	/* length of IE data, not including 2 byte header */
-/* CSA mode - 802.11h-2003 $7.3.2.20 */
-#define DOT11_CSA_MODE_ADVISORY		0	/* no DOT11_CSA_MODE_NO_TX restriction imposed */
-#define DOT11_CSA_MODE_NO_TX		1	/* no transmission upon receiving CSA frame. */
-
-BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel {
-	uint8	category;
-	uint8	action;
-	dot11_chan_switch_ie_t chan_switch_ie;	/* for switch IE */
-	dot11_brcm_extch_ie_t extch_ie;		/* extension channel offset */
-} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct dot11_csa_body {
-	uint8 mode;	/* mode 0 or 1 */
-	uint8 reg;	/* regulatory class */
-	uint8 channel;	/* channel switch to */
-	uint8 count;	/* number of beacons before switching */
-} BWL_POST_PACKED_STRUCT;
-
-/** 11n Extended Channel Switch IE data structure */
-BWL_PRE_PACKED_STRUCT struct dot11_ext_csa {
-	uint8 id;	/* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */
-	uint8 len;	/* length of IE */
-	struct dot11_csa_body b;	/* body of the ie */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ext_csa dot11_ext_csa_ie_t;
-#define DOT11_EXT_CSA_IE_LEN	4	/* length of extended channel switch IE body */
-
-BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa {
-	uint8	category;
-	uint8	action;
-	dot11_ext_csa_ie_t chan_switch_ie;	/* for switch IE */
-} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa {
-	uint8	category;
-	uint8	action;
-	struct dot11_csa_body b;	/* body of the ie */
-} BWL_POST_PACKED_STRUCT;
-
-/**  Wide Bandwidth Channel Switch IE data structure */
-BWL_PRE_PACKED_STRUCT struct dot11_wide_bw_channel_switch {
-	uint8 id;				/* id DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID */
-	uint8 len;				/* length of IE */
-	uint8 channel_width;			/* new channel width */
-	uint8 center_frequency_segment_0;	/* center frequency segment 0 */
-	uint8 center_frequency_segment_1;	/* center frequency segment 1 */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_wide_bw_channel_switch dot11_wide_bw_chan_switch_ie_t;
-
-#define DOT11_WIDE_BW_SWITCH_IE_LEN     3       /* length of IE data, not including 2 byte header */
-
-/** Channel Switch Wrapper IE data structure */
-BWL_PRE_PACKED_STRUCT struct dot11_channel_switch_wrapper {
-	uint8 id;				/* id DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID */
-	uint8 len;				/* length of IE */
-	dot11_wide_bw_chan_switch_ie_t wb_chan_switch_ie;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_channel_switch_wrapper dot11_chan_switch_wrapper_ie_t;
-
-/** VHT Transmit Power Envelope IE data structure */
-BWL_PRE_PACKED_STRUCT struct dot11_vht_transmit_power_envelope {
-	uint8 id;				/* id DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID */
-	uint8 len;				/* length of IE */
-	uint8 transmit_power_info;
-	uint8 local_max_transmit_power_20;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_vht_transmit_power_envelope dot11_vht_transmit_power_envelope_ie_t;
-
-/* vht transmit power envelope IE length depends on channel width */
-#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_40MHZ	1
-#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_80MHZ	2
-#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_160MHZ	3
-
-BWL_PRE_PACKED_STRUCT struct dot11_obss_coex {
-	uint8	id;
-	uint8	len;
-	uint8	info;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_obss_coex dot11_obss_coex_t;
-#define DOT11_OBSS_COEXINFO_LEN	1	/* length of OBSS Coexistence INFO IE */
-
-#define	DOT11_OBSS_COEX_INFO_REQ		0x01
-#define	DOT11_OBSS_COEX_40MHZ_INTOLERANT	0x02
-#define	DOT11_OBSS_COEX_20MHZ_WIDTH_REQ	0x04
-
-BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist {
-	uint8	id;
-	uint8	len;
-	uint8	regclass;
-	uint8	chanlist[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_obss_chanlist dot11_obss_chanlist_t;
-#define DOT11_OBSS_CHANLIST_FIXED_LEN	1	/* fixed length of regclass */
-
-BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie {
-	uint8 id;
-	uint8 len;
-	uint8 cap[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_extcap_ie dot11_extcap_ie_t;
-
-#define DOT11_EXTCAP_LEN_COEX	1
-#define DOT11_EXTCAP_LEN_BT	3
-#define DOT11_EXTCAP_LEN_IW	4
-#define DOT11_EXTCAP_LEN_SI	6
-
-#define DOT11_EXTCAP_LEN_TDLS	5
-#define DOT11_11AC_EXTCAP_LEN_TDLS	8
-
-#define DOT11_EXTCAP_LEN_FMS			2
-#define DOT11_EXTCAP_LEN_PROXY_ARP		2
-#define DOT11_EXTCAP_LEN_TFS			3
-#define DOT11_EXTCAP_LEN_WNM_SLEEP		3
-#define DOT11_EXTCAP_LEN_TIMBC			3
-#define DOT11_EXTCAP_LEN_BSSTRANS		3
-#define DOT11_EXTCAP_LEN_DMS			4
-#define DOT11_EXTCAP_LEN_WNM_NOTIFICATION	6
-#define DOT11_EXTCAP_LEN_TDLS_WBW		8
-#define DOT11_EXTCAP_LEN_OPMODE_NOTIFICATION	8
-
-/* TDLS Capabilities */
-#define DOT11_TDLS_CAP_TDLS			37		/* TDLS support */
-#define DOT11_TDLS_CAP_PU_BUFFER_STA	28		/* TDLS Peer U-APSD buffer STA support */
-#define DOT11_TDLS_CAP_PEER_PSM		20		/* TDLS Peer PSM support */
-#define DOT11_TDLS_CAP_CH_SW			30		/* TDLS Channel switch */
-#define DOT11_TDLS_CAP_PROH			38		/* TDLS prohibited */
-#define DOT11_TDLS_CAP_CH_SW_PROH		39		/* TDLS Channel switch prohibited */
-#define DOT11_TDLS_CAP_TDLS_WIDER_BW	61	/* TDLS Wider Band-Width */
-
-#define TDLS_CAP_MAX_BIT		39		/* TDLS max bit defined in ext cap */
-
-/* 802.11h/802.11k Measurement Request/Report IEs */
-/* Measurement Type field */
-#define DOT11_MEASURE_TYPE_BASIC 	0   /* d11 measurement basic type */
-#define DOT11_MEASURE_TYPE_CCA 		1   /* d11 measurement CCA type */
-#define DOT11_MEASURE_TYPE_RPI		2   /* d11 measurement RPI type */
-#define DOT11_MEASURE_TYPE_CHLOAD	3   /* d11 measurement Channel Load type */
-#define DOT11_MEASURE_TYPE_NOISE	4   /* d11 measurement Noise Histogram type */
-#define DOT11_MEASURE_TYPE_BEACON	5   /* d11 measurement Beacon type */
-#define DOT11_MEASURE_TYPE_FRAME	6   /* d11 measurement Frame type */
-#define DOT11_MEASURE_TYPE_STAT		7   /* d11 measurement STA Statistics type */
-#define DOT11_MEASURE_TYPE_LCI		8   /* d11 measurement LCI type */
-#define DOT11_MEASURE_TYPE_TXSTREAM	9   /* d11 measurement TX Stream type */
-#define DOT11_MEASURE_TYPE_MCDIAGS	10  /* d11 measurement multicast diagnostics */
-#define DOT11_MEASURE_TYPE_CIVICLOC	11  /* d11 measurement location civic */
-#define DOT11_MEASURE_TYPE_LOC_ID	12  /* d11 measurement location identifier */
-#define DOT11_MEASURE_TYPE_DIRCHANQ	13  /* d11 measurement dir channel quality */
-#define DOT11_MEASURE_TYPE_DIRMEAS	14  /* d11 measurement directional */
-#define DOT11_MEASURE_TYPE_DIRSTATS	15  /* d11 measurement directional stats */
-#define DOT11_MEASURE_TYPE_FTMRANGE	16  /* d11 measurement Fine Timing */
-#define DOT11_MEASURE_TYPE_PAUSE	255	/* d11 measurement pause type */
-
-/* Measurement Request Modes */
-#define DOT11_MEASURE_MODE_PARALLEL 	(1<<0)	/* d11 measurement parallel */
-#define DOT11_MEASURE_MODE_ENABLE 	(1<<1)	/* d11 measurement enable */
-#define DOT11_MEASURE_MODE_REQUEST	(1<<2)	/* d11 measurement request */
-#define DOT11_MEASURE_MODE_REPORT 	(1<<3)	/* d11 measurement report */
-#define DOT11_MEASURE_MODE_DUR 	(1<<4)	/* d11 measurement dur mandatory */
-/* Measurement Report Modes */
-#define DOT11_MEASURE_MODE_LATE 	(1<<0)	/* d11 measurement late */
-#define DOT11_MEASURE_MODE_INCAPABLE	(1<<1)	/* d11 measurement incapable */
-#define DOT11_MEASURE_MODE_REFUSED	(1<<2)	/* d11 measurement refuse */
-/* Basic Measurement Map bits */
-#define DOT11_MEASURE_BASIC_MAP_BSS	((uint8)(1<<0))	/* d11 measurement basic map BSS */
-#define DOT11_MEASURE_BASIC_MAP_OFDM	((uint8)(1<<1))	/* d11 measurement map OFDM */
-#define DOT11_MEASURE_BASIC_MAP_UKNOWN	((uint8)(1<<2))	/* d11 measurement map unknown */
-#define DOT11_MEASURE_BASIC_MAP_RADAR	((uint8)(1<<3))	/* d11 measurement map radar */
-#define DOT11_MEASURE_BASIC_MAP_UNMEAS	((uint8)(1<<4))	/* d11 measurement map unmeasuremnt */
-
-BWL_PRE_PACKED_STRUCT struct dot11_meas_req {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint8 channel;
-	uint8 start_time[8];
-	uint16 duration;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_meas_req dot11_meas_req_t;
-#define DOT11_MNG_IE_MREQ_LEN 14	/* d11 measurement request IE length */
-/* length of Measure Request IE data not including variable len */
-#define DOT11_MNG_IE_MREQ_FIXED_LEN 3	/* d11 measurement request IE fixed length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_meas_req_loc {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	BWL_PRE_PACKED_STRUCT union
-	{
-		BWL_PRE_PACKED_STRUCT struct {
-			uint8 subject;
-			uint8 data[1];
-		} BWL_POST_PACKED_STRUCT lci;
-		BWL_PRE_PACKED_STRUCT struct {
-			uint8 subject;
-			uint8 type;  /* type of civic location */
-			uint8 siu;   /* service interval units */
-			uint16 si; /* service interval */
-			uint8 data[1];
-		} BWL_POST_PACKED_STRUCT civic;
-		BWL_PRE_PACKED_STRUCT struct {
-			uint16 max_init_delay;		/* maximum random initial delay */
-			uint8 min_ap_count;
-			uint8 data[1];
-		} BWL_POST_PACKED_STRUCT ftm_range;
-	} BWL_POST_PACKED_STRUCT req;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_meas_req_loc dot11_meas_req_loc_t;
-#define DOT11_MNG_IE_MREQ_MIN_LEN           4	/* d11 measurement report IE length */
-#define DOT11_MNG_IE_MREQ_LCI_FIXED_LEN     4	/* d11 measurement report IE length */
-#define DOT11_MNG_IE_MREQ_CIVIC_FIXED_LEN   8	/* d11 measurement report IE length */
-#define DOT11_MNG_IE_MREQ_FRNG_FIXED_LEN    6	/* d11 measurement report IE length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_lci_subelement {
-	uint8 subelement;
-	uint8 length;
-	uint8 lci_data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_lci_subelement dot11_lci_subelement_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_civic_subelement {
-	uint8 type;  /* type of civic location */
-	uint8 subelement;
-	uint8 length;
-	uint8 civic_data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_civic_subelement dot11_civic_subelement_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_meas_rep {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	BWL_PRE_PACKED_STRUCT union
-	{
-		BWL_PRE_PACKED_STRUCT struct {
-			uint8 channel;
-			uint8 start_time[8];
-			uint16 duration;
-			uint8 map;
-		} BWL_POST_PACKED_STRUCT basic;
-		BWL_PRE_PACKED_STRUCT struct {
-			uint8 subelement;
-			uint8 length;
-			uint8 data[1];
-		} BWL_POST_PACKED_STRUCT lci;
-		BWL_PRE_PACKED_STRUCT struct {
-			uint8 type;  /* type of civic location */
-			uint8 subelement;
-			uint8 length;
-			uint8 data[1];
-		} BWL_POST_PACKED_STRUCT civic;
-		BWL_PRE_PACKED_STRUCT struct {
-			uint8 entry_count;
-			uint8 data[1];
-		} BWL_POST_PACKED_STRUCT ftm_range;
-		uint8 data[1];
-	} BWL_POST_PACKED_STRUCT rep;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_meas_rep dot11_meas_rep_t;
-#define DOT11_MNG_IE_MREP_MIN_LEN           5	/* d11 measurement report IE length */
-#define DOT11_MNG_IE_MREP_LCI_FIXED_LEN     5	/* d11 measurement report IE length */
-#define DOT11_MNG_IE_MREP_CIVIC_FIXED_LEN   6	/* d11 measurement report IE length */
-#define DOT11_MNG_IE_MREP_BASIC_FIXED_LEN   15	/* d11 measurement report IE length */
-#define DOT11_MNG_IE_MREP_FRNG_FIXED_LEN    4
-
-/* length of Measure Report IE data not including variable len */
-#define DOT11_MNG_IE_MREP_FIXED_LEN	3	/* d11 measurement response IE fixed length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic {
-	uint8 channel;
-	uint8 start_time[8];
-	uint16 duration;
-	uint8 map;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t;
-#define DOT11_MEASURE_BASIC_REP_LEN	12	/* d11 measurement basic report length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_quiet {
-	uint8 id;
-	uint8 len;
-	uint8 count;	/* TBTTs until beacon interval in quiet starts */
-	uint8 period;	/* Beacon intervals between periodic quiet periods ? */
-	uint16 duration;	/* Length of quiet period, in TU's */
-	uint16 offset;	/* TU's offset from TBTT in Count field */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_quiet dot11_quiet_t;
-
-BWL_PRE_PACKED_STRUCT struct chan_map_tuple {
-	uint8 channel;
-	uint8 map;
-} BWL_POST_PACKED_STRUCT;
-typedef struct chan_map_tuple chan_map_tuple_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs {
-	uint8 id;
-	uint8 len;
-	uint8 eaddr[ETHER_ADDR_LEN];
-	uint8 interval;
-	chan_map_tuple_t map[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ibss_dfs dot11_ibss_dfs_t;
-
-/* WME Elements */
-#define WME_OUI			"\x00\x50\xf2"	/* WME OUI */
-#define WME_OUI_LEN		3
-#define WME_OUI_TYPE		2	/* WME type */
-#define WME_TYPE		2	/* WME type, deprecated */
-#define WME_SUBTYPE_IE		0	/* Information Element */
-#define WME_SUBTYPE_PARAM_IE	1	/* Parameter Element */
-#define WME_SUBTYPE_TSPEC	2	/* Traffic Specification */
-#define WME_VER			1	/* WME version */
-
-/* WME Access Category Indices (ACIs) */
-#define AC_BE			0	/* Best Effort */
-#define AC_BK			1	/* Background */
-#define AC_VI			2	/* Video */
-#define AC_VO			3	/* Voice */
-#define AC_COUNT		4	/* number of ACs */
-
-typedef uint8 ac_bitmap_t;	/* AC bitmap of (1 << AC_xx) */
-
-#define AC_BITMAP_NONE		0x0	/* No ACs */
-#define AC_BITMAP_ALL		0xf	/* All ACs */
-#define AC_BITMAP_TST(ab, ac)	(((ab) & (1 << (ac))) != 0)
-#define AC_BITMAP_SET(ab, ac)	(((ab) |= (1 << (ac))))
-#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac))))
-
-
-/** WME Information Element (IE) */
-BWL_PRE_PACKED_STRUCT struct wme_ie {
-	uint8 oui[3];
-	uint8 type;
-	uint8 subtype;
-	uint8 version;
-	uint8 qosinfo;
-} BWL_POST_PACKED_STRUCT;
-typedef struct wme_ie wme_ie_t;
-#define WME_IE_LEN 7	/* WME IE length */
-
-BWL_PRE_PACKED_STRUCT struct edcf_acparam {
-	uint8	ACI;
-	uint8	ECW;
-	uint16  TXOP;		/* stored in network order (ls octet first) */
-} BWL_POST_PACKED_STRUCT;
-typedef struct edcf_acparam edcf_acparam_t;
-
-/** WME Parameter Element (PE) */
-BWL_PRE_PACKED_STRUCT struct wme_param_ie {
-	uint8 oui[3];
-	uint8 type;
-	uint8 subtype;
-	uint8 version;
-	uint8 qosinfo;
-	uint8 rsvd;
-	edcf_acparam_t acparam[AC_COUNT];
-} BWL_POST_PACKED_STRUCT;
-typedef struct wme_param_ie wme_param_ie_t;
-#define WME_PARAM_IE_LEN            24          /* WME Parameter IE length */
-
-/* QoS Info field for IE as sent from AP */
-#define WME_QI_AP_APSD_MASK         0x80        /* U-APSD Supported mask */
-#define WME_QI_AP_APSD_SHIFT        7           /* U-APSD Supported shift */
-#define WME_QI_AP_COUNT_MASK        0x0f        /* Parameter set count mask */
-#define WME_QI_AP_COUNT_SHIFT       0           /* Parameter set count shift */
-
-/* QoS Info field for IE as sent from STA */
-#define WME_QI_STA_MAXSPLEN_MASK    0x60        /* Max Service Period Length mask */
-#define WME_QI_STA_MAXSPLEN_SHIFT   5           /* Max Service Period Length shift */
-#define WME_QI_STA_APSD_ALL_MASK    0xf         /* APSD all AC bits mask */
-#define WME_QI_STA_APSD_ALL_SHIFT   0           /* APSD all AC bits shift */
-#define WME_QI_STA_APSD_BE_MASK     0x8         /* APSD AC_BE mask */
-#define WME_QI_STA_APSD_BE_SHIFT    3           /* APSD AC_BE shift */
-#define WME_QI_STA_APSD_BK_MASK     0x4         /* APSD AC_BK mask */
-#define WME_QI_STA_APSD_BK_SHIFT    2           /* APSD AC_BK shift */
-#define WME_QI_STA_APSD_VI_MASK     0x2         /* APSD AC_VI mask */
-#define WME_QI_STA_APSD_VI_SHIFT    1           /* APSD AC_VI shift */
-#define WME_QI_STA_APSD_VO_MASK     0x1         /* APSD AC_VO mask */
-#define WME_QI_STA_APSD_VO_SHIFT    0           /* APSD AC_VO shift */
-
-/* ACI */
-#define EDCF_AIFSN_MIN               1           /* AIFSN minimum value */
-#define EDCF_AIFSN_MAX               15          /* AIFSN maximum value */
-#define EDCF_AIFSN_MASK              0x0f        /* AIFSN mask */
-#define EDCF_ACM_MASK                0x10        /* ACM mask */
-#define EDCF_ACI_MASK                0x60        /* ACI mask */
-#define EDCF_ACI_SHIFT               5           /* ACI shift */
-#define EDCF_AIFSN_SHIFT             12          /* 4 MSB(0xFFF) in ifs_ctl for AC idx */
-
-/* ECW */
-#define EDCF_ECW_MIN                 0           /* cwmin/cwmax exponent minimum value */
-#define EDCF_ECW_MAX                 15          /* cwmin/cwmax exponent maximum value */
-#define EDCF_ECW2CW(exp)             ((1 << (exp)) - 1)
-#define EDCF_ECWMIN_MASK             0x0f        /* cwmin exponent form mask */
-#define EDCF_ECWMAX_MASK             0xf0        /* cwmax exponent form mask */
-#define EDCF_ECWMAX_SHIFT            4           /* cwmax exponent form shift */
-
-/* TXOP */
-#define EDCF_TXOP_MIN                0           /* TXOP minimum value */
-#define EDCF_TXOP_MAX                65535       /* TXOP maximum value */
-#define EDCF_TXOP2USEC(txop)         ((txop) << 5)
-
-/* Default BE ACI value for non-WME connection STA */
-#define NON_EDCF_AC_BE_ACI_STA          0x02
-
-/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */
-#define EDCF_AC_BE_ACI_STA           0x03	/* STA ACI value for best effort AC */
-#define EDCF_AC_BE_ECW_STA           0xA4	/* STA ECW value for best effort AC */
-#define EDCF_AC_BE_TXOP_STA          0x0000	/* STA TXOP value for best effort AC */
-#define EDCF_AC_BK_ACI_STA           0x27	/* STA ACI value for background AC */
-#define EDCF_AC_BK_ECW_STA           0xA4	/* STA ECW value for background AC */
-#define EDCF_AC_BK_TXOP_STA          0x0000	/* STA TXOP value for background AC */
-#define EDCF_AC_VI_ACI_STA           0x42	/* STA ACI value for video AC */
-#define EDCF_AC_VI_ECW_STA           0x43	/* STA ECW value for video AC */
-#define EDCF_AC_VI_TXOP_STA          0x005e	/* STA TXOP value for video AC */
-#define EDCF_AC_VO_ACI_STA           0x62	/* STA ACI value for audio AC */
-#define EDCF_AC_VO_ECW_STA           0x32	/* STA ECW value for audio AC */
-#define EDCF_AC_VO_TXOP_STA          0x002f	/* STA TXOP value for audio AC */
-
-/* Default EDCF parameters that AP uses; WMM draft Table 14 */
-#define EDCF_AC_BE_ACI_AP            0x03	/* AP ACI value for best effort AC */
-#define EDCF_AC_BE_ECW_AP            0x64	/* AP ECW value for best effort AC */
-#define EDCF_AC_BE_TXOP_AP           0x0000	/* AP TXOP value for best effort AC */
-#define EDCF_AC_BK_ACI_AP            0x27	/* AP ACI value for background AC */
-#define EDCF_AC_BK_ECW_AP            0xA4	/* AP ECW value for background AC */
-#define EDCF_AC_BK_TXOP_AP           0x0000	/* AP TXOP value for background AC */
-#define EDCF_AC_VI_ACI_AP            0x41	/* AP ACI value for video AC */
-#define EDCF_AC_VI_ECW_AP            0x43	/* AP ECW value for video AC */
-#define EDCF_AC_VI_TXOP_AP           0x005e	/* AP TXOP value for video AC */
-#define EDCF_AC_VO_ACI_AP            0x61	/* AP ACI value for audio AC */
-#define EDCF_AC_VO_ECW_AP            0x32	/* AP ECW value for audio AC */
-#define EDCF_AC_VO_TXOP_AP           0x002f	/* AP TXOP value for audio AC */
-
-/** EDCA Parameter IE */
-BWL_PRE_PACKED_STRUCT struct edca_param_ie {
-	uint8 qosinfo;
-	uint8 rsvd;
-	edcf_acparam_t acparam[AC_COUNT];
-} BWL_POST_PACKED_STRUCT;
-typedef struct edca_param_ie edca_param_ie_t;
-#define EDCA_PARAM_IE_LEN            18          /* EDCA Parameter IE length */
-
-/** QoS Capability IE */
-BWL_PRE_PACKED_STRUCT struct qos_cap_ie {
-	uint8 qosinfo;
-} BWL_POST_PACKED_STRUCT;
-typedef struct qos_cap_ie qos_cap_ie_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie {
-	uint8 id; 			/* 11, DOT11_MNG_QBSS_LOAD_ID */
-	uint8 length;
-	uint16 station_count; 		/* total number of STAs associated */
-	uint8 channel_utilization;	/* % of time, normalized to 255, QAP sensed medium busy */
-	uint16 aac; 			/* available admission capacity */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t;
-#define BSS_LOAD_IE_SIZE 	7	/* BSS load IE size */
-
-#define WLC_QBSS_LOAD_CHAN_FREE_MAX	0xff	/* max for channel free score */
-
-/* nom_msdu_size */
-#define FIXED_MSDU_SIZE 0x8000		/* MSDU size is fixed */
-#define MSDU_SIZE_MASK	0x7fff		/* (Nominal or fixed) MSDU size */
-
-/* surplus_bandwidth */
-/* Represented as 3 bits of integer, binary point, 13 bits fraction */
-#define	INTEGER_SHIFT	13	/* integer shift */
-#define FRACTION_MASK	0x1FFF	/* fraction mask */
-
-/** Management Notification Frame */
-BWL_PRE_PACKED_STRUCT struct dot11_management_notification {
-	uint8 category;			/* DOT11_ACTION_NOTIFICATION */
-	uint8 action;
-	uint8 token;
-	uint8 status;
-	uint8 data[1];			/* Elements */
-} BWL_POST_PACKED_STRUCT;
-#define DOT11_MGMT_NOTIFICATION_LEN 4	/* Fixed length */
-
-/** Timeout Interval IE */
-BWL_PRE_PACKED_STRUCT struct ti_ie {
-	uint8 ti_type;
-	uint32 ti_val;
-} BWL_POST_PACKED_STRUCT;
-typedef struct ti_ie ti_ie_t;
-#define TI_TYPE_REASSOC_DEADLINE	1
-#define TI_TYPE_KEY_LIFETIME		2
-
-/* WME Action Codes */
-#define WME_ADDTS_REQUEST	0	/* WME ADDTS request */
-#define WME_ADDTS_RESPONSE	1	/* WME ADDTS response */
-#define WME_DELTS_REQUEST	2	/* WME DELTS request */
-
-/* WME Setup Response Status Codes */
-#define WME_ADMISSION_ACCEPTED		0	/* WME admission accepted */
-#define WME_INVALID_PARAMETERS		1	/* WME invalide parameters */
-#define WME_ADMISSION_REFUSED		3	/* WME admission refused */
-
-/* Macro to take a pointer to a beacon or probe response
- * body and return the char* pointer to the SSID info element
- */
-#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN)
-
-/* Authentication frame payload constants */
-#define DOT11_OPEN_SYSTEM	0	/* d11 open authentication */
-#define DOT11_SHARED_KEY	1	/* d11 shared authentication */
-#define DOT11_FAST_BSS		2	/* d11 fast bss authentication */
-#define DOT11_CHALLENGE_LEN	128	/* d11 challenge text length */
-
-/* Frame control macros */
-#define FC_PVER_MASK		0x3	/* PVER mask */
-#define FC_PVER_SHIFT		0	/* PVER shift */
-#define FC_TYPE_MASK		0xC	/* type mask */
-#define FC_TYPE_SHIFT		2	/* type shift */
-#define FC_SUBTYPE_MASK		0xF0	/* subtype mask */
-#define FC_SUBTYPE_SHIFT	4	/* subtype shift */
-#define FC_TODS			0x100	/* to DS */
-#define FC_TODS_SHIFT		8	/* to DS shift */
-#define FC_FROMDS		0x200	/* from DS */
-#define FC_FROMDS_SHIFT		9	/* from DS shift */
-#define FC_MOREFRAG		0x400	/* more frag. */
-#define FC_MOREFRAG_SHIFT	10	/* more frag. shift */
-#define FC_RETRY		0x800	/* retry */
-#define FC_RETRY_SHIFT		11	/* retry shift */
-#define FC_PM			0x1000	/* PM */
-#define FC_PM_SHIFT		12	/* PM shift */
-#define FC_MOREDATA		0x2000	/* more data */
-#define FC_MOREDATA_SHIFT	13	/* more data shift */
-#define FC_WEP			0x4000	/* WEP */
-#define FC_WEP_SHIFT		14	/* WEP shift */
-#define FC_ORDER		0x8000	/* order */
-#define FC_ORDER_SHIFT		15	/* order shift */
-
-/* sequence control macros */
-#define SEQNUM_SHIFT		4	/* seq. number shift */
-#define SEQNUM_MAX		0x1000	/* max seqnum + 1 */
-#define FRAGNUM_MASK		0xF	/* frag. number mask */
-
-/* Frame Control type/subtype defs */
-
-/* FC Types */
-#define FC_TYPE_MNG		0	/* management type */
-#define FC_TYPE_CTL		1	/* control type */
-#define FC_TYPE_DATA		2	/* data type */
-
-/* Management Subtypes */
-#define FC_SUBTYPE_ASSOC_REQ		0	/* assoc. request */
-#define FC_SUBTYPE_ASSOC_RESP		1	/* assoc. response */
-#define FC_SUBTYPE_REASSOC_REQ		2	/* reassoc. request */
-#define FC_SUBTYPE_REASSOC_RESP		3	/* reassoc. response */
-#define FC_SUBTYPE_PROBE_REQ		4	/* probe request */
-#define FC_SUBTYPE_PROBE_RESP		5	/* probe response */
-#define FC_SUBTYPE_BEACON		8	/* beacon */
-#define FC_SUBTYPE_ATIM			9	/* ATIM */
-#define FC_SUBTYPE_DISASSOC		10	/* disassoc. */
-#define FC_SUBTYPE_AUTH			11	/* authentication */
-#define FC_SUBTYPE_DEAUTH		12	/* de-authentication */
-#define FC_SUBTYPE_ACTION		13	/* action */
-#define FC_SUBTYPE_ACTION_NOACK		14	/* action no-ack */
-
-/* Control Subtypes */
-#define FC_SUBTYPE_CTL_WRAPPER		7	/* Control Wrapper */
-#define FC_SUBTYPE_BLOCKACK_REQ		8	/* Block Ack Req */
-#define FC_SUBTYPE_BLOCKACK		9	/* Block Ack */
-#define FC_SUBTYPE_PS_POLL		10	/* PS poll */
-#define FC_SUBTYPE_RTS			11	/* RTS */
-#define FC_SUBTYPE_CTS			12	/* CTS */
-#define FC_SUBTYPE_ACK			13	/* ACK */
-#define FC_SUBTYPE_CF_END		14	/* CF-END */
-#define FC_SUBTYPE_CF_END_ACK		15	/* CF-END ACK */
-
-/* Data Subtypes */
-#define FC_SUBTYPE_DATA			0	/* Data */
-#define FC_SUBTYPE_DATA_CF_ACK		1	/* Data + CF-ACK */
-#define FC_SUBTYPE_DATA_CF_POLL		2	/* Data + CF-Poll */
-#define FC_SUBTYPE_DATA_CF_ACK_POLL	3	/* Data + CF-Ack + CF-Poll */
-#define FC_SUBTYPE_NULL			4	/* Null */
-#define FC_SUBTYPE_CF_ACK		5	/* CF-Ack */
-#define FC_SUBTYPE_CF_POLL		6	/* CF-Poll */
-#define FC_SUBTYPE_CF_ACK_POLL		7	/* CF-Ack + CF-Poll */
-#define FC_SUBTYPE_QOS_DATA		8	/* QoS Data */
-#define FC_SUBTYPE_QOS_DATA_CF_ACK	9	/* QoS Data + CF-Ack */
-#define FC_SUBTYPE_QOS_DATA_CF_POLL	10	/* QoS Data + CF-Poll */
-#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL	11	/* QoS Data + CF-Ack + CF-Poll */
-#define FC_SUBTYPE_QOS_NULL		12	/* QoS Null */
-#define FC_SUBTYPE_QOS_CF_POLL		14	/* QoS CF-Poll */
-#define FC_SUBTYPE_QOS_CF_ACK_POLL	15	/* QoS CF-Ack + CF-Poll */
-
-/* Data Subtype Groups */
-#define FC_SUBTYPE_ANY_QOS(s)		(((s) & 8) != 0)
-#define FC_SUBTYPE_ANY_NULL(s)		(((s) & 4) != 0)
-#define FC_SUBTYPE_ANY_CF_POLL(s)	(((s) & 2) != 0)
-#define FC_SUBTYPE_ANY_CF_ACK(s)	(((s) & 1) != 0)
-#define FC_SUBTYPE_ANY_PSPOLL(s)	(((s) & 10) != 0)
-
-/* Type/Subtype Combos */
-#define FC_KIND_MASK		(FC_TYPE_MASK | FC_SUBTYPE_MASK)	/* FC kind mask */
-
-#define FC_KIND(t, s)	(((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT))	/* FC kind */
-
-#define FC_SUBTYPE(fc)	(((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT)	/* Subtype from FC */
-#define FC_TYPE(fc)	(((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT)	/* Type from FC */
-
-#define FC_ASSOC_REQ	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ)	/* assoc. request */
-#define FC_ASSOC_RESP	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP)	/* assoc. response */
-#define FC_REASSOC_REQ	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ)	/* reassoc. request */
-#define FC_REASSOC_RESP	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP)	/* reassoc. response */
-#define FC_PROBE_REQ	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ)	/* probe request */
-#define FC_PROBE_RESP	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP)	/* probe response */
-#define FC_BEACON	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON)		/* beacon */
-#define FC_ATIM		FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ATIM)		/* ATIM */
-#define FC_DISASSOC	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC)	/* disassoc */
-#define FC_AUTH		FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH)		/* authentication */
-#define FC_DEAUTH	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH)		/* deauthentication */
-#define FC_ACTION	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION)		/* action */
-#define FC_ACTION_NOACK	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK)	/* action no-ack */
-
-#define FC_CTL_WRAPPER	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER)	/* Control Wrapper */
-#define FC_BLOCKACK_REQ	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ)	/* Block Ack Req */
-#define FC_BLOCKACK	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK)	/* Block Ack */
-#define FC_PS_POLL	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL)	/* PS poll */
-#define FC_RTS		FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS)		/* RTS */
-#define FC_CTS		FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS)		/* CTS */
-#define FC_ACK		FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK)		/* ACK */
-#define FC_CF_END	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END)		/* CF-END */
-#define FC_CF_END_ACK	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK)	/* CF-END ACK */
-
-#define FC_DATA		FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA)		/* data */
-#define FC_NULL_DATA	FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL)		/* null data */
-#define FC_DATA_CF_ACK	FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK)	/* data CF ACK */
-#define FC_QOS_DATA	FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA)	/* QoS data */
-#define FC_QOS_NULL	FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL)	/* QoS null */
-
-/* QoS Control Field */
-
-/* 802.1D Priority */
-#define QOS_PRIO_SHIFT		0	/* QoS priority shift */
-#define QOS_PRIO_MASK		0x0007	/* QoS priority mask */
-#define QOS_PRIO(qos)		(((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT)	/* QoS priority */
-
-/* Traffic Identifier */
-#define QOS_TID_SHIFT		0	/* QoS TID shift */
-#define QOS_TID_MASK		0x000f	/* QoS TID mask */
-#define QOS_TID(qos)		(((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT)	/* QoS TID */
-
-/* End of Service Period (U-APSD) */
-#define QOS_EOSP_SHIFT		4	/* QoS End of Service Period shift */
-#define QOS_EOSP_MASK		0x0010	/* QoS End of Service Period mask */
-#define QOS_EOSP(qos)		(((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT)	/* Qos EOSP */
-
-/* Ack Policy */
-#define QOS_ACK_NORMAL_ACK	0	/* Normal Ack */
-#define QOS_ACK_NO_ACK		1	/* No Ack (eg mcast) */
-#define QOS_ACK_NO_EXP_ACK	2	/* No Explicit Ack */
-#define QOS_ACK_BLOCK_ACK	3	/* Block Ack */
-#define QOS_ACK_SHIFT		5	/* QoS ACK shift */
-#define QOS_ACK_MASK		0x0060	/* QoS ACK mask */
-#define QOS_ACK(qos)		(((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT)	/* QoS ACK */
-
-/* A-MSDU flag */
-#define QOS_AMSDU_SHIFT		7	/* AMSDU shift */
-#define QOS_AMSDU_MASK		0x0080	/* AMSDU mask */
-
-/* Management Frames */
-
-/* Management Frame Constants */
-
-/* Fixed fields */
-#define DOT11_MNG_AUTH_ALGO_LEN		2	/* d11 management auth. algo. length */
-#define DOT11_MNG_AUTH_SEQ_LEN		2	/* d11 management auth. seq. length */
-#define DOT11_MNG_BEACON_INT_LEN	2	/* d11 management beacon interval length */
-#define DOT11_MNG_CAP_LEN		2	/* d11 management cap. length */
-#define DOT11_MNG_AP_ADDR_LEN		6	/* d11 management AP address length */
-#define DOT11_MNG_LISTEN_INT_LEN	2	/* d11 management listen interval length */
-#define DOT11_MNG_REASON_LEN		2	/* d11 management reason length */
-#define DOT11_MNG_AID_LEN		2	/* d11 management AID length */
-#define DOT11_MNG_STATUS_LEN		2	/* d11 management status length */
-#define DOT11_MNG_TIMESTAMP_LEN		8	/* d11 management timestamp length */
-
-/* DUR/ID field in assoc resp is 0xc000 | AID */
-#define DOT11_AID_MASK			0x3fff	/* d11 AID mask */
-
-/* Reason Codes */
-#define DOT11_RC_RESERVED		0	/* d11 RC reserved */
-#define DOT11_RC_UNSPECIFIED		1	/* Unspecified reason */
-#define DOT11_RC_AUTH_INVAL		2	/* Previous authentication no longer valid */
-#define DOT11_RC_DEAUTH_LEAVING		3	/* Deauthenticated because sending station
-						 * is leaving (or has left) IBSS or ESS
-						 */
-#define DOT11_RC_INACTIVITY		4	/* Disassociated due to inactivity */
-#define DOT11_RC_BUSY			5	/* Disassociated because AP is unable to handle
-						 * all currently associated stations
-						 */
-#define DOT11_RC_INVAL_CLASS_2		6	/* Class 2 frame received from
-						 * nonauthenticated station
-						 */
-#define DOT11_RC_INVAL_CLASS_3		7	/* Class 3 frame received from
-						 *  nonassociated station
-						 */
-#define DOT11_RC_DISASSOC_LEAVING	8	/* Disassociated because sending station is
-						 * leaving (or has left) BSS
-						 */
-#define DOT11_RC_NOT_AUTH		9	/* Station requesting (re)association is not
-						 * authenticated with responding station
-						 */
-#define DOT11_RC_BAD_PC			10	/* Unacceptable power capability element */
-#define DOT11_RC_BAD_CHANNELS		11	/* Unacceptable supported channels element */
-
-/* 12 is unused by STA but could be used by AP/GO */
-#define DOT11_RC_DISASSOC_BTM		12	/* Disassociated due to BSS Transition Magmt */
-
-
-/* 32-39 are QSTA specific reasons added in 11e */
-#define DOT11_RC_UNSPECIFIED_QOS	32	/* unspecified QoS-related reason */
-#define DOT11_RC_INSUFFCIENT_BW		33	/* QAP lacks sufficient bandwidth */
-#define DOT11_RC_EXCESSIVE_FRAMES	34	/* excessive number of frames need ack */
-#define DOT11_RC_TX_OUTSIDE_TXOP	35	/* transmitting outside the limits of txop */
-#define DOT11_RC_LEAVING_QBSS		36	/* QSTA is leaving the QBSS (or restting) */
-#define DOT11_RC_BAD_MECHANISM		37	/* does not want to use the mechanism */
-#define DOT11_RC_SETUP_NEEDED		38	/* mechanism needs a setup */
-#define DOT11_RC_TIMEOUT		39	/* timeout */
-
-#define DOT11_RC_MESH_PEERING_CANCELLED		52
-#define DOT11_RC_MESH_MAX_PEERS			53
-#define DOT11_RC_MESH_CONFIG_POLICY_VIOLN	54
-#define DOT11_RC_MESH_CLOSE_RECVD		55
-#define DOT11_RC_MESH_MAX_RETRIES		56
-#define DOT11_RC_MESH_CONFIRM_TIMEOUT		57
-#define DOT11_RC_MESH_INVALID_GTK		58
-#define DOT11_RC_MESH_INCONSISTENT_PARAMS	59
-
-#define DOT11_RC_MESH_INVALID_SEC_CAP		60
-#define DOT11_RC_MESH_PATHERR_NOPROXYINFO	61
-#define DOT11_RC_MESH_PATHERR_NOFWINFO		62
-#define DOT11_RC_MESH_PATHERR_DSTUNREACH	63
-#define DOT11_RC_MESH_MBSSMAC_EXISTS		64
-#define DOT11_RC_MESH_CHANSWITCH_REGREQ		65
-#define DOT11_RC_MESH_CHANSWITCH_UNSPEC		66
-
-#define DOT11_RC_MAX			66	/* Reason codes > 66 are reserved */
-
-#define DOT11_RC_TDLS_PEER_UNREACH	25
-#define DOT11_RC_TDLS_DOWN_UNSPECIFIED	26
-
-/* Status Codes */
-#define DOT11_SC_SUCCESS		0	/* Successful */
-#define DOT11_SC_FAILURE		1	/* Unspecified failure */
-#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2	/* TDLS wakeup schedule rejected but alternative  */
-					/* schedule provided */
-#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3	/* TDLS wakeup schedule rejected */
-#define DOT11_SC_TDLS_SEC_DISABLED	5	/* TDLS Security disabled */
-#define DOT11_SC_LIFETIME_REJ		6	/* Unacceptable lifetime */
-#define DOT11_SC_NOT_SAME_BSS		7	/* Not in same BSS */
-#define DOT11_SC_CAP_MISMATCH		10	/* Cannot support all requested
-						 * capabilities in the Capability
-						 * Information field
-						 */
-#define DOT11_SC_REASSOC_FAIL		11	/* Reassociation denied due to inability
-						 * to confirm that association exists
-						 */
-#define DOT11_SC_ASSOC_FAIL		12	/* Association denied due to reason
-						 * outside the scope of this standard
-						 */
-#define DOT11_SC_AUTH_MISMATCH		13	/* Responding station does not support
-						 * the specified authentication
-						 * algorithm
-						 */
-#define DOT11_SC_AUTH_SEQ		14	/* Received an Authentication frame
-						 * with authentication transaction
-						 * sequence number out of expected
-						 * sequence
-						 */
-#define DOT11_SC_AUTH_CHALLENGE_FAIL	15	/* Authentication rejected because of
-						 * challenge failure
-						 */
-#define DOT11_SC_AUTH_TIMEOUT		16	/* Authentication rejected due to timeout
-						 * waiting for next frame in sequence
-						 */
-#define DOT11_SC_ASSOC_BUSY_FAIL	17	/* Association denied because AP is
-						 * unable to handle additional
-						 * associated stations
-						 */
-#define DOT11_SC_ASSOC_RATE_MISMATCH	18	/* Association denied due to requesting
-						 * station not supporting all of the
-						 * data rates in the BSSBasicRateSet
-						 * parameter
-						 */
-#define DOT11_SC_ASSOC_SHORT_REQUIRED	19	/* Association denied due to requesting
-						 * station not supporting the Short
-						 * Preamble option
-						 */
-#define DOT11_SC_ASSOC_PBCC_REQUIRED	20	/* Association denied due to requesting
-						 * station not supporting the PBCC
-						 * Modulation option
-						 */
-#define DOT11_SC_ASSOC_AGILITY_REQUIRED	21	/* Association denied due to requesting
-						 * station not supporting the Channel
-						 * Agility option
-						 */
-#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED	22	/* Association denied because Spectrum
-							 * Management capability is required.
-							 */
-#define DOT11_SC_ASSOC_BAD_POWER_CAP	23	/* Association denied because the info
-						 * in the Power Cap element is
-						 * unacceptable.
-						 */
-#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS	24	/* Association denied because the info
-						 * in the Supported Channel element is
-						 * unacceptable
-						 */
-#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED	25	/* Association denied due to requesting
-							 * station not supporting the Short Slot
-							 * Time option
-							 */
-#define DOT11_SC_ASSOC_DSSSOFDM_REQUIRED 26	/* Association denied because requesting station
-						 * does not support the DSSS-OFDM option
-						 */
-#define DOT11_SC_ASSOC_HT_REQUIRED	27	/* Association denied because the requesting
-						 * station does not support HT features
-						 */
-#define DOT11_SC_ASSOC_R0KH_UNREACHABLE	28	/* Association denied due to AP
-						 * being unable to reach the R0 Key Holder
-						 */
-#define DOT11_SC_ASSOC_TRY_LATER	30	/* Association denied temporarily, try again later
-						 */
-#define DOT11_SC_ASSOC_MFP_VIOLATION	31	/* Association denied due to Robust Management
-						 * frame policy violation
-						 */
-
-#define	DOT11_SC_DECLINED		37	/* request declined */
-#define	DOT11_SC_INVALID_PARAMS		38	/* One or more params have invalid values */
-#define DOT11_SC_INVALID_PAIRWISE_CIPHER	42 /* invalid pairwise cipher */
-#define	DOT11_SC_INVALID_AKMP		43	/* Association denied due to invalid AKMP */
-#define DOT11_SC_INVALID_RSNIE_CAP	45	/* invalid RSN IE capabilities */
-#define DOT11_SC_DLS_NOT_ALLOWED	48	/* DLS is not allowed in the BSS by policy */
-#define	DOT11_SC_INVALID_PMKID		53	/* Association denied due to invalid PMKID */
-#define	DOT11_SC_INVALID_MDID		54	/* Association denied due to invalid MDID */
-#define	DOT11_SC_INVALID_FTIE		55	/* Association denied due to invalid FTIE */
-
-#define DOT11_SC_ADV_PROTO_NOT_SUPPORTED	59	/* ad proto not supported */
-#define DOT11_SC_NO_OUTSTAND_REQ			60	/* no outstanding req */
-#define DOT11_SC_RSP_NOT_RX_FROM_SERVER		61	/* no response from server */
-#define DOT11_SC_TIMEOUT					62	/* timeout */
-#define DOT11_SC_QUERY_RSP_TOO_LARGE		63	/* query rsp too large */
-#define DOT11_SC_SERVER_UNREACHABLE			65	/* server unreachable */
-
-#define DOT11_SC_UNEXP_MSG			70	/* Unexpected message */
-#define DOT11_SC_INVALID_SNONCE		71	/* Invalid SNonce */
-#define DOT11_SC_INVALID_RSNIE		72	/* Invalid contents of RSNIE */
-
-#define DOT11_SC_ANTICLOG_TOCKEN_REQUIRED	76	/* Anti-clogging tocken required */
-#define DOT11_SC_INVALID_FINITE_CYCLIC_GRP	77	/* Invalid contents of RSNIE */
-
-#define DOT11_SC_ASSOC_VHT_REQUIRED	104	/* Association denied because the requesting
-						 * station does not support VHT features.
-						 */
-
-#define DOT11_SC_TRANSMIT_FAILURE	79	/* transmission failure */
-
-/* Info Elts, length of INFORMATION portion of Info Elts */
-#define DOT11_MNG_DS_PARAM_LEN			1	/* d11 management DS parameter length */
-#define DOT11_MNG_IBSS_PARAM_LEN		2	/* d11 management IBSS parameter length */
-
-/* TIM Info element has 3 bytes fixed info in INFORMATION field,
- * followed by 1 to 251 bytes of Partial Virtual Bitmap
- */
-#define DOT11_MNG_TIM_FIXED_LEN			3	/* d11 management TIM fixed length */
-#define DOT11_MNG_TIM_DTIM_COUNT		0	/* d11 management DTIM count */
-#define DOT11_MNG_TIM_DTIM_PERIOD		1	/* d11 management DTIM period */
-#define DOT11_MNG_TIM_BITMAP_CTL		2	/* d11 management TIM BITMAP control  */
-#define DOT11_MNG_TIM_PVB			3	/* d11 management TIM PVB */
-
-/* TLV defines */
-#define TLV_TAG_OFF		0	/* tag offset */
-#define TLV_LEN_OFF		1	/* length offset */
-#define TLV_HDR_LEN		2	/* header length */
-#define TLV_BODY_OFF		2	/* body offset */
-#define TLV_BODY_LEN_MAX	255	/* max body length */
-
-/* Management Frame Information Element IDs */
-#define DOT11_MNG_SSID_ID			0	/* d11 management SSID id */
-#define DOT11_MNG_RATES_ID			1	/* d11 management rates id */
-#define DOT11_MNG_FH_PARMS_ID			2	/* d11 management FH parameter id */
-#define DOT11_MNG_DS_PARMS_ID			3	/* d11 management DS parameter id */
-#define DOT11_MNG_CF_PARMS_ID			4	/* d11 management CF parameter id */
-#define DOT11_MNG_TIM_ID			5	/* d11 management TIM id */
-#define DOT11_MNG_IBSS_PARMS_ID			6	/* d11 management IBSS parameter id */
-#define DOT11_MNG_COUNTRY_ID			7	/* d11 management country id */
-#define DOT11_MNG_HOPPING_PARMS_ID		8	/* d11 management hopping parameter id */
-#define DOT11_MNG_HOPPING_TABLE_ID		9	/* d11 management hopping table id */
-#define DOT11_MNG_REQUEST_ID			10	/* d11 management request id */
-#define DOT11_MNG_QBSS_LOAD_ID 			11	/* d11 management QBSS Load id */
-#define DOT11_MNG_EDCA_PARAM_ID			12	/* 11E EDCA Parameter id */
-#define DOT11_MNG_TSPEC_ID			13	/* d11 management TSPEC id */
-#define DOT11_MNG_TCLAS_ID			14	/* d11 management TCLAS id */
-#define DOT11_MNG_CHALLENGE_ID			16	/* d11 management chanllenge id */
-#define DOT11_MNG_PWR_CONSTRAINT_ID		32	/* 11H PowerConstraint */
-#define DOT11_MNG_PWR_CAP_ID			33	/* 11H PowerCapability */
-#define DOT11_MNG_TPC_REQUEST_ID 		34	/* 11H TPC Request */
-#define DOT11_MNG_TPC_REPORT_ID			35	/* 11H TPC Report */
-#define DOT11_MNG_SUPP_CHANNELS_ID		36	/* 11H Supported Channels */
-#define DOT11_MNG_CHANNEL_SWITCH_ID		37	/* 11H ChannelSwitch Announcement */
-#define DOT11_MNG_MEASURE_REQUEST_ID		38	/* 11H MeasurementRequest */
-#define DOT11_MNG_MEASURE_REPORT_ID		39	/* 11H MeasurementReport */
-#define DOT11_MNG_QUIET_ID			40	/* 11H Quiet */
-#define DOT11_MNG_IBSS_DFS_ID			41	/* 11H IBSS_DFS */
-#define DOT11_MNG_ERP_ID			42	/* d11 management ERP id */
-#define DOT11_MNG_TS_DELAY_ID			43	/* d11 management TS Delay id */
-#define DOT11_MNG_TCLAS_PROC_ID			44	/* d11 management TCLAS processing id */
-#define	DOT11_MNG_HT_CAP			45	/* d11 mgmt HT cap id */
-#define DOT11_MNG_QOS_CAP_ID			46	/* 11E QoS Capability id */
-#define DOT11_MNG_NONERP_ID			47	/* d11 management NON-ERP id */
-#define DOT11_MNG_RSN_ID			48	/* d11 management RSN id */
-#define DOT11_MNG_EXT_RATES_ID			50	/* d11 management ext. rates id */
-#define DOT11_MNG_AP_CHREP_ID			51	/* 11k AP Channel report id */
-#define DOT11_MNG_NEIGHBOR_REP_ID		52	/* 11k & 11v Neighbor report id */
-#define DOT11_MNG_RCPI_ID			53	/* 11k RCPI */
-#define DOT11_MNG_MDIE_ID			54	/* 11r Mobility domain id */
-#define DOT11_MNG_FTIE_ID			55	/* 11r Fast Bss Transition id */
-#define DOT11_MNG_FT_TI_ID			56	/* 11r Timeout Interval id */
-#define DOT11_MNG_RDE_ID			57	/* 11r RIC Data Element id */
-#define	DOT11_MNG_REGCLASS_ID			59	/* d11 management regulatory class id */
-#define DOT11_MNG_EXT_CSA_ID			60	/* d11 Extended CSA */
-#define	DOT11_MNG_HT_ADD			61	/* d11 mgmt additional HT info */
-#define	DOT11_MNG_EXT_CHANNEL_OFFSET		62	/* d11 mgmt ext channel offset */
-#define DOT11_MNG_BSS_AVR_ACCESS_DELAY_ID	63	/* 11k bss average access delay */
-#define DOT11_MNG_ANTENNA_ID			64	/* 11k antenna id */
-#define DOT11_MNG_RSNI_ID			65	/* 11k RSNI id */
-#define DOT11_MNG_MEASUREMENT_PILOT_TX_ID	66	/* 11k measurement pilot tx info id */
-#define DOT11_MNG_BSS_AVAL_ADMISSION_CAP_ID	67	/* 11k bss aval admission cap id */
-#define DOT11_MNG_BSS_AC_ACCESS_DELAY_ID	68	/* 11k bss AC access delay id */
-#define DOT11_MNG_WAPI_ID			68	/* d11 management WAPI id */
-#define DOT11_MNG_TIME_ADVERTISE_ID	69	/* 11p time advertisement */
-#define DOT11_MNG_RRM_CAP_ID		70	/* 11k radio measurement capability */
-#define DOT11_MNG_MULTIPLE_BSSID_ID		71	/* 11k multiple BSSID id */
-#define	DOT11_MNG_HT_BSS_COEXINFO_ID		72	/* d11 mgmt OBSS Coexistence INFO */
-#define	DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID	73	/* d11 mgmt OBSS Intolerant Channel list */
-#define	DOT11_MNG_HT_OBSS_ID			74	/* d11 mgmt OBSS HT info */
-#define DOT11_MNG_MMIE_ID			76	/* d11 mgmt MIC IE */
-#define DOT11_MNG_FMS_DESCR_ID			86	/* 11v FMS descriptor */
-#define DOT11_MNG_FMS_REQ_ID			87	/* 11v FMS request id */
-#define DOT11_MNG_FMS_RESP_ID			88	/* 11v FMS response id */
-#define DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID	90	/* 11v bss max idle id */
-#define DOT11_MNG_TFS_REQUEST_ID		91	/* 11v tfs request id */
-#define DOT11_MNG_TFS_RESPONSE_ID		92	/* 11v tfs response id */
-#define DOT11_MNG_WNM_SLEEP_MODE_ID		93	/* 11v wnm-sleep mode id */
-#define DOT11_MNG_TIMBC_REQ_ID			94	/* 11v TIM broadcast request id */
-#define DOT11_MNG_TIMBC_RESP_ID			95	/* 11v TIM broadcast response id */
-#define DOT11_MNG_CHANNEL_USAGE			97	/* 11v channel usage */
-#define DOT11_MNG_TIME_ZONE_ID			98	/* 11v time zone */
-#define DOT11_MNG_DMS_REQUEST_ID		99	/* 11v dms request id */
-#define DOT11_MNG_DMS_RESPONSE_ID		100	/* 11v dms response id */
-#define DOT11_MNG_LINK_IDENTIFIER_ID		101	/* 11z TDLS Link Identifier IE */
-#define DOT11_MNG_WAKEUP_SCHEDULE_ID		102	/* 11z TDLS Wakeup Schedule IE */
-#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID	104	/* 11z TDLS Channel Switch Timing IE */
-#define DOT11_MNG_PTI_CONTROL_ID		105	/* 11z TDLS PTI Control IE */
-#define DOT11_MNG_PU_BUFFER_STATUS_ID	106	/* 11z TDLS PU Buffer Status IE */
-#define DOT11_MNG_INTERWORKING_ID		107	/* 11u interworking */
-#define DOT11_MNG_ADVERTISEMENT_ID		108	/* 11u advertisement protocol */
-#define DOT11_MNG_EXP_BW_REQ_ID			109	/* 11u expedited bandwith request */
-#define DOT11_MNG_QOS_MAP_ID			110	/* 11u QoS map set */
-#define DOT11_MNG_ROAM_CONSORT_ID		111	/* 11u roaming consortium */
-#define DOT11_MNG_EMERGCY_ALERT_ID		112	/* 11u emergency alert identifier */
-#define DOT11_MNG_MESH_CONFIG			113	/* Mesh Configuration */
-#define DOT11_MNG_MESH_ID			114	/* Mesh ID */
-#define DOT11_MNG_MESH_PEER_MGMT_ID		117	/* Mesh PEER MGMT IE */
-
-#define DOT11_MNG_EXT_CAP_ID			127	/* d11 mgmt ext capability */
-#define DOT11_MNG_EXT_PREQ_ID			130	/* Mesh PREQ IE */
-#define DOT11_MNG_EXT_PREP_ID			131	/* Mesh PREP IE */
-#define DOT11_MNG_EXT_PERR_ID			132	/* Mesh PERR IE */
-#define	DOT11_MNG_VHT_CAP_ID			191	/* d11 mgmt VHT cap id */
-#define	DOT11_MNG_VHT_OPERATION_ID		192	/* d11 mgmt VHT op id */
-#define	DOT11_MNG_EXT_BSSLOAD_ID		193	/* d11 mgmt VHT extended bss load id */
-#define DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID		194	/* Wide BW Channel Switch IE */
-#define DOT11_MNG_VHT_TRANSMIT_POWER_ENVELOPE_ID	195	/* VHT transmit Power Envelope IE */
-#define DOT11_MNG_CHANNEL_SWITCH_WRAPPER_ID		196	/* Channel Switch Wrapper IE */
-#define DOT11_MNG_AID_ID					197	/* Association ID  IE */
-#define	DOT11_MNG_OPER_MODE_NOTIF_ID	199	/* d11 mgmt VHT oper mode notif */
-#define DOT11_MNG_FTM_PARAMS_ID			206
-
-#define DOT11_MNG_WPA_ID			221	/* d11 management WPA id */
-#define DOT11_MNG_PROPR_ID			221
-/* should start using this one instead of above two */
-#define DOT11_MNG_VS_ID				221	/* d11 management Vendor Specific IE */
-
-/* Rate Defines */
-
-/* Valid rates for the Supported Rates and Extended Supported Rates IEs.
- * Encoding is the rate in 500kbps units, rouding up for fractional values.
- * 802.11-2012, section 6.5.5.2, DATA_RATE parameter enumerates all the values.
- * The rate values cover DSSS, HR/DSSS, ERP, and OFDM phy rates.
- * The defines below do not cover the rates specific to 10MHz, {3, 4.5, 27},
- * and 5MHz, {1.5, 2.25, 3, 4.5, 13.5}, which are not supported by Broadcom devices.
- */
-
-#define DOT11_RATE_1M   2       /* 1  Mbps in 500kbps units */
-#define DOT11_RATE_2M   4       /* 2  Mbps in 500kbps units */
-#define DOT11_RATE_5M5  11      /* 5.5 Mbps in 500kbps units */
-#define DOT11_RATE_11M  22      /* 11 Mbps in 500kbps units */
-#define DOT11_RATE_6M   12      /* 6  Mbps in 500kbps units */
-#define DOT11_RATE_9M   18      /* 9  Mbps in 500kbps units */
-#define DOT11_RATE_12M  24      /* 12 Mbps in 500kbps units */
-#define DOT11_RATE_18M  36      /* 18 Mbps in 500kbps units */
-#define DOT11_RATE_24M  48      /* 24 Mbps in 500kbps units */
-#define DOT11_RATE_36M  72      /* 36 Mbps in 500kbps units */
-#define DOT11_RATE_48M  96      /* 48 Mbps in 500kbps units */
-#define DOT11_RATE_54M  108     /* 54 Mbps in 500kbps units */
-#define DOT11_RATE_MAX  108     /* highest rate (54 Mbps) in 500kbps units */
-
-/* Supported Rates and Extended Supported Rates IEs
- * The supported rates octets are defined a the MSB indicatin a Basic Rate
- * and bits 0-6 as the rate value
- */
-#define DOT11_RATE_BASIC                0x80 /* flag for a Basic Rate */
-#define DOT11_RATE_MASK                 0x7F /* mask for numeric part of rate */
-
-/* BSS Membership Selector parameters
- * 802.11-2012 and 802.11ac_D4.0 sec 8.4.2.3
- * These selector values are advertised in Supported Rates and Extended Supported Rates IEs
- * in the supported rates list with the Basic rate bit set.
- * Constants below include the basic bit.
- */
-#define DOT11_BSS_MEMBERSHIP_HT         0xFF  /* Basic 0x80 + 127, HT Required to join */
-#define DOT11_BSS_MEMBERSHIP_VHT        0xFE  /* Basic 0x80 + 126, VHT Required to join */
-
-/* ERP info element bit values */
-#define DOT11_MNG_ERP_LEN			1	/* ERP is currently 1 byte long */
-#define DOT11_MNG_NONERP_PRESENT		0x01	/* NonERP (802.11b) STAs are present
-							 *in the BSS
-							 */
-#define DOT11_MNG_USE_PROTECTION		0x02	/* Use protection mechanisms for
-							 *ERP-OFDM frames
-							 */
-#define DOT11_MNG_BARKER_PREAMBLE		0x04	/* Short Preambles: 0 == allowed,
-							 * 1 == not allowed
-							 */
-/* TS Delay element offset & size */
-#define DOT11_MGN_TS_DELAY_LEN		4	/* length of TS DELAY IE */
-#define TS_DELAY_FIELD_SIZE			4	/* TS DELAY field size */
-
-/* Capability Information Field */
-#define DOT11_CAP_ESS				0x0001	/* d11 cap. ESS */
-#define DOT11_CAP_IBSS				0x0002	/* d11 cap. IBSS */
-#define DOT11_CAP_POLLABLE			0x0004	/* d11 cap. pollable */
-#define DOT11_CAP_POLL_RQ			0x0008	/* d11 cap. poll request */
-#define DOT11_CAP_PRIVACY			0x0010	/* d11 cap. privacy */
-#define DOT11_CAP_SHORT				0x0020	/* d11 cap. short */
-#define DOT11_CAP_PBCC				0x0040	/* d11 cap. PBCC */
-#define DOT11_CAP_AGILITY			0x0080	/* d11 cap. agility */
-#define DOT11_CAP_SPECTRUM			0x0100	/* d11 cap. spectrum */
-#define DOT11_CAP_QOS				0x0200	/* d11 cap. qos */
-#define DOT11_CAP_SHORTSLOT			0x0400	/* d11 cap. shortslot */
-#define DOT11_CAP_APSD				0x0800	/* d11 cap. apsd */
-#define DOT11_CAP_RRM				0x1000	/* d11 cap. 11k radio measurement */
-#define DOT11_CAP_CCK_OFDM			0x2000	/* d11 cap. CCK/OFDM */
-#define DOT11_CAP_DELAY_BA			0x4000	/* d11 cap. delayed block ack */
-#define DOT11_CAP_IMMEDIATE_BA			0x8000	/* d11 cap. immediate block ack */
-
-/* Extended capabilities IE bitfields */
-/* 20/40 BSS Coexistence Management support bit position */
-#define DOT11_EXT_CAP_OBSS_COEX_MGMT		0
-/* Extended Channel Switching support bit position */
-#define DOT11_EXT_CAP_EXT_CHAN_SWITCHING	2
-/* scheduled PSMP support bit position */
-#define DOT11_EXT_CAP_SPSMP			6
-/*  Flexible Multicast Service */
-#define DOT11_EXT_CAP_FMS			11
-/* proxy ARP service support bit position */
-#define DOT11_EXT_CAP_PROXY_ARP			12
-/* Civic Location */
-#define DOT11_EXT_CAP_CIVIC_LOC			14
-/* Geospatial Location */
-#define DOT11_EXT_CAP_LCI			15
-/* Traffic Filter Service */
-#define DOT11_EXT_CAP_TFS			16
-/* WNM-Sleep Mode */
-#define DOT11_EXT_CAP_WNM_SLEEP			17
-/* TIM Broadcast service */
-#define DOT11_EXT_CAP_TIMBC			18
-/* BSS Transition Management support bit position */
-#define DOT11_EXT_CAP_BSSTRANS_MGMT		19
-/* Direct Multicast Service */
-#define DOT11_EXT_CAP_DMS			26
-/* Interworking support bit position */
-#define DOT11_EXT_CAP_IW			31
-/* QoS map support bit position */
-#define DOT11_EXT_CAP_QOS_MAP		32
-/* service Interval granularity bit position and mask */
-#define DOT11_EXT_CAP_SI			41
-#define DOT11_EXT_CAP_SI_MASK			0x0E
-/* WNM notification */
-#define DOT11_EXT_CAP_WNM_NOTIF			46
-/* Operating mode notification - VHT (11ac D3.0 - 8.4.2.29) */
-#define DOT11_EXT_CAP_OPER_MODE_NOTIF		62
-/* Fine timing measurement - D3.0 */
-#define DOT11_EXT_CAP_FTM_RESPONDER		70
-#define DOT11_EXT_CAP_FTM_INITIATOR		71 /* tentative 11mcd3.0 */
-#ifdef WL_FTM
-#define DOT11_EXT_CAP_MAX_BIT_IDX		95	/* !!!update this please!!! */
-#else
-#define DOT11_EXT_CAP_MAX_BIT_IDX		62	/* !!!update this please!!! */
-#endif
-
-/* extended capability */
-#ifndef DOT11_EXTCAP_LEN_MAX
-#define DOT11_EXTCAP_LEN_MAX ((DOT11_EXT_CAP_MAX_BIT_IDX + 8) >> 3)
-#endif
-
-BWL_PRE_PACKED_STRUCT struct dot11_extcap {
-	uint8 extcap[DOT11_EXTCAP_LEN_MAX];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_extcap dot11_extcap_t;
-
-/* VHT Operating mode bit fields -  (11ac D3.0 - 8.4.1.50) */
-#define DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT 0
-#define DOT11_OPER_MODE_CHANNEL_WIDTH_MASK 0x3
-#define DOT11_OPER_MODE_RXNSS_SHIFT 4
-#define DOT11_OPER_MODE_RXNSS_MASK 0x70
-#define DOT11_OPER_MODE_RXNSS_TYPE_SHIFT 7
-#define DOT11_OPER_MODE_RXNSS_TYPE_MASK 0x80
-
-#define DOT11_OPER_MODE(type, nss, chanw) (\
-	((type) << DOT11_OPER_MODE_RXNSS_TYPE_SHIFT &\
-		 DOT11_OPER_MODE_RXNSS_TYPE_MASK) |\
-	(((nss) - 1) << DOT11_OPER_MODE_RXNSS_SHIFT & DOT11_OPER_MODE_RXNSS_MASK) |\
-	((chanw) << DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT &\
-		 DOT11_OPER_MODE_CHANNEL_WIDTH_MASK))
-
-#define DOT11_OPER_MODE_CHANNEL_WIDTH(mode) \
-	(((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK)\
-		>> DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT)
-#define DOT11_OPER_MODE_RXNSS(mode) \
-	((((mode) & DOT11_OPER_MODE_RXNSS_MASK)		\
-		>> DOT11_OPER_MODE_RXNSS_SHIFT) + 1)
-#define DOT11_OPER_MODE_RXNSS_TYPE(mode) \
-	(((mode) & DOT11_OPER_MODE_RXNSS_TYPE_MASK)\
-		>> DOT11_OPER_MODE_RXNSS_TYPE_SHIFT)
-
-#define DOT11_OPER_MODE_20MHZ 0
-#define DOT11_OPER_MODE_40MHZ 1
-#define DOT11_OPER_MODE_80MHZ 2
-#define DOT11_OPER_MODE_160MHZ 3
-#define DOT11_OPER_MODE_8080MHZ 3
-
-#define DOT11_OPER_MODE_CHANNEL_WIDTH_20MHZ(mode) (\
-	((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_20MHZ)
-#define DOT11_OPER_MODE_CHANNEL_WIDTH_40MHZ(mode) (\
-	((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_40MHZ)
-#define DOT11_OPER_MODE_CHANNEL_WIDTH_80MHZ(mode) (\
-	((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_80MHZ)
-#define DOT11_OPER_MODE_CHANNEL_WIDTH_160MHZ(mode) (\
-	((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_160MHZ)
-#define DOT11_OPER_MODE_CHANNEL_WIDTH_8080MHZ(mode) (\
-	((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_8080MHZ)
-
-/* Operating mode information element 802.11ac D3.0 - 8.4.2.168 */
-BWL_PRE_PACKED_STRUCT struct dot11_oper_mode_notif_ie {
-	uint8 mode;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_oper_mode_notif_ie dot11_oper_mode_notif_ie_t;
-
-#define DOT11_OPER_MODE_NOTIF_IE_LEN 1
-
-/* Extended Capability Information Field */
-#define DOT11_OBSS_COEX_MNG_SUPPORT	0x01	/* 20/40 BSS Coexistence Management support */
-
-/*
- * Action Frame Constants
- */
-#define DOT11_ACTION_HDR_LEN		2	/* action frame category + action field */
-#define DOT11_ACTION_CAT_OFF		0	/* category offset */
-#define DOT11_ACTION_ACT_OFF		1	/* action offset */
-
-/* Action Category field (sec 8.4.1.11) */
-#define DOT11_ACTION_CAT_ERR_MASK	0x80	/* category error mask */
-#define DOT11_ACTION_CAT_MASK		0x7F	/* category mask */
-#define DOT11_ACTION_CAT_SPECT_MNG	0	/* category spectrum management */
-#define DOT11_ACTION_CAT_QOS		1	/* category QoS */
-#define DOT11_ACTION_CAT_DLS		2	/* category DLS */
-#define DOT11_ACTION_CAT_BLOCKACK	3	/* category block ack */
-#define DOT11_ACTION_CAT_PUBLIC		4	/* category public */
-#define DOT11_ACTION_CAT_RRM		5	/* category radio measurements */
-#define DOT11_ACTION_CAT_FBT	6	/* category fast bss transition */
-#define DOT11_ACTION_CAT_HT		7	/* category for HT */
-#define	DOT11_ACTION_CAT_SA_QUERY	8	/* security association query */
-#define	DOT11_ACTION_CAT_PDPA		9	/* protected dual of public action */
-#define DOT11_ACTION_CAT_WNM		10	/* category for WNM */
-#define DOT11_ACTION_CAT_UWNM		11	/* category for Unprotected WNM */
-#define DOT11_ACTION_CAT_MESH		13	/* category for Mesh */
-#define DOT11_ACTION_CAT_SELFPROT	15	/* category for Mesh, self protected */
-#define DOT11_ACTION_NOTIFICATION	17
-#define DOT11_ACTION_CAT_VHT		21	/* VHT action */
-#define DOT11_ACTION_CAT_VSP		126	/* protected vendor specific */
-#define DOT11_ACTION_CAT_VS		127	/* category Vendor Specific */
-
-/* Spectrum Management Action IDs (sec 7.4.1) */
-#define DOT11_SM_ACTION_M_REQ		0	/* d11 action measurement request */
-#define DOT11_SM_ACTION_M_REP		1	/* d11 action measurement response */
-#define DOT11_SM_ACTION_TPC_REQ		2	/* d11 action TPC request */
-#define DOT11_SM_ACTION_TPC_REP		3	/* d11 action TPC response */
-#define DOT11_SM_ACTION_CHANNEL_SWITCH	4	/* d11 action channel switch */
-#define DOT11_SM_ACTION_EXT_CSA		5	/* d11 extened CSA for 11n */
-
-/* QoS action ids */
-#define DOT11_QOS_ACTION_ADDTS_REQ	0	/* d11 action ADDTS request */
-#define DOT11_QOS_ACTION_ADDTS_RESP	1	/* d11 action ADDTS response */
-#define DOT11_QOS_ACTION_DELTS		2	/* d11 action DELTS */
-#define DOT11_QOS_ACTION_SCHEDULE	3	/* d11 action schedule */
-#define DOT11_QOS_ACTION_QOS_MAP	4	/* d11 action QOS map */
-
-/* HT action ids */
-#define DOT11_ACTION_ID_HT_CH_WIDTH	0	/* notify channel width action id */
-#define DOT11_ACTION_ID_HT_MIMO_PS	1	/* mimo ps action id */
-
-/* Public action ids */
-#define DOT11_PUB_ACTION_BSS_COEX_MNG	0	/* 20/40 Coexistence Management action id */
-#define DOT11_PUB_ACTION_CHANNEL_SWITCH	4	/* d11 action channel switch */
-#define DOT11_PUB_ACTION_GAS_CB_REQ	12	/* GAS Comeback Request */
-#define DOT11_PUB_ACTION_FTM_REQ	32		/* FTM request */
-#define DOT11_PUB_ACTION_FTM		33		/* FTM measurement */
-
-/* Block Ack action types */
-#define DOT11_BA_ACTION_ADDBA_REQ	0	/* ADDBA Req action frame type */
-#define DOT11_BA_ACTION_ADDBA_RESP	1	/* ADDBA Resp action frame type */
-#define DOT11_BA_ACTION_DELBA		2	/* DELBA action frame type */
-
-/* ADDBA action parameters */
-#define DOT11_ADDBA_PARAM_AMSDU_SUP	0x0001	/* AMSDU supported under BA */
-#define DOT11_ADDBA_PARAM_POLICY_MASK	0x0002	/* policy mask(ack vs delayed) */
-#define DOT11_ADDBA_PARAM_POLICY_SHIFT	1	/* policy shift */
-#define DOT11_ADDBA_PARAM_TID_MASK	0x003c	/* tid mask */
-#define DOT11_ADDBA_PARAM_TID_SHIFT	2	/* tid shift */
-#define DOT11_ADDBA_PARAM_BSIZE_MASK	0xffc0	/* buffer size mask */
-#define DOT11_ADDBA_PARAM_BSIZE_SHIFT	6	/* buffer size shift */
-
-#define DOT11_ADDBA_POLICY_DELAYED	0	/* delayed BA policy */
-#define DOT11_ADDBA_POLICY_IMMEDIATE	1	/* immediate BA policy */
-
-/* Fast Transition action types */
-#define DOT11_FT_ACTION_FT_RESERVED		0
-#define DOT11_FT_ACTION_FT_REQ			1	/* FBT request - for over-the-DS FBT */
-#define DOT11_FT_ACTION_FT_RES			2	/* FBT response - for over-the-DS FBT */
-#define DOT11_FT_ACTION_FT_CON			3	/* FBT confirm - for OTDS with RRP */
-#define DOT11_FT_ACTION_FT_ACK			4	/* FBT ack */
-
-/* DLS action types */
-#define DOT11_DLS_ACTION_REQ			0	/* DLS Request */
-#define DOT11_DLS_ACTION_RESP			1	/* DLS Response */
-#define DOT11_DLS_ACTION_TD			2	/* DLS Teardown */
-
-/* Wireless Network Management (WNM) action types */
-#define DOT11_WNM_ACTION_EVENT_REQ		0
-#define DOT11_WNM_ACTION_EVENT_REP		1
-#define DOT11_WNM_ACTION_DIAG_REQ		2
-#define DOT11_WNM_ACTION_DIAG_REP		3
-#define DOT11_WNM_ACTION_LOC_CFG_REQ		4
-#define DOT11_WNM_ACTION_LOC_RFG_RESP		5
-#define DOT11_WNM_ACTION_BSSTRANS_QUERY		6
-#define DOT11_WNM_ACTION_BSSTRANS_REQ		7
-#define DOT11_WNM_ACTION_BSSTRANS_RESP		8
-#define DOT11_WNM_ACTION_FMS_REQ		9
-#define DOT11_WNM_ACTION_FMS_RESP		10
-#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ	11
-#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP	12
-#define DOT11_WNM_ACTION_TFS_REQ		13
-#define DOT11_WNM_ACTION_TFS_RESP		14
-#define DOT11_WNM_ACTION_TFS_NOTIFY_REQ		15
-#define DOT11_WNM_ACTION_WNM_SLEEP_REQ		16
-#define DOT11_WNM_ACTION_WNM_SLEEP_RESP		17
-#define DOT11_WNM_ACTION_TIMBC_REQ		18
-#define DOT11_WNM_ACTION_TIMBC_RESP		19
-#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD	20
-#define DOT11_WNM_ACTION_CHAN_USAGE_REQ		21
-#define DOT11_WNM_ACTION_CHAN_USAGE_RESP	22
-#define DOT11_WNM_ACTION_DMS_REQ		23
-#define DOT11_WNM_ACTION_DMS_RESP		24
-#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ	25
-#define DOT11_WNM_ACTION_NOTFCTN_REQ		26
-#define DOT11_WNM_ACTION_NOTFCTN_RESP		27
-#define DOT11_WNM_ACTION_TFS_NOTIFY_RESP	28
-
-/* Unprotected Wireless Network Management (WNM) action types */
-#define DOT11_UWNM_ACTION_TIM			0
-#define DOT11_UWNM_ACTION_TIMING_MEASUREMENT	1
-
-#define DOT11_MNG_COUNTRY_ID_LEN 3
-
-/* VHT category action types - 802.11ac D3.0 - 8.5.23.1 */
-#define DOT11_VHT_ACTION_CBF				0	/* Compressed Beamforming */
-#define DOT11_VHT_ACTION_GID_MGMT			1	/* Group ID Management */
-#define DOT11_VHT_ACTION_OPER_MODE_NOTIF	2	/* Operating mode notif'n */
-
-/** DLS Request frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_dls_req {
-	uint8 category;			/* category of action frame (2) */
-	uint8 action;				/* DLS action: req (0) */
-	struct ether_addr	da;		/* destination address */
-	struct ether_addr	sa;		/* source address */
-	uint16 cap;				/* capability */
-	uint16 timeout;			/* timeout value */
-	uint8 data[1];				/* IE:support rate, extend support rate, HT cap */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_dls_req dot11_dls_req_t;
-#define DOT11_DLS_REQ_LEN 18	/* Fixed length */
-
-/** DLS response frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_dls_resp {
-	uint8 category;			/* category of action frame (2) */
-	uint8 action;				/* DLS action: req (0) */
-	uint16 status;				/* status code field */
-	struct ether_addr	da;		/* destination address */
-	struct ether_addr	sa;		/* source address */
-	uint8 data[1];				/* optional: capability, rate ... */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_dls_resp dot11_dls_resp_t;
-#define DOT11_DLS_RESP_LEN 16	/* Fixed length */
-
-
-/* ************* 802.11v related definitions. ************* */
-
-/** BSS Management Transition Query frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_query {
-	uint8 category;			/* category of action frame (10) */
-	uint8 action;			/* WNM action: trans_query (6) */
-	uint8 token;			/* dialog token */
-	uint8 reason;			/* transition query reason */
-	uint8 data[1];			/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_bsstrans_query dot11_bsstrans_query_t;
-#define DOT11_BSSTRANS_QUERY_LEN 4	/* Fixed length */
-
-/* BTM transition reason */
-#define DOT11_BSSTRANS_REASON_UNSPECIFIED		0
-#define DOT11_BSSTRANS_REASON_EXC_FRAME_LOSS		1
-#define DOT11_BSSTRANS_REASON_EXC_TRAFFIC_DELAY		2
-#define DOT11_BSSTRANS_REASON_INSUFF_QOS_CAPACITY	3
-#define DOT11_BSSTRANS_REASON_FIRST_ASSOC		4
-#define DOT11_BSSTRANS_REASON_LOAD_BALANCING		5
-#define DOT11_BSSTRANS_REASON_BETTER_AP_FOUND		6
-#define DOT11_BSSTRANS_REASON_DEAUTH_RX			7
-#define DOT11_BSSTRANS_REASON_8021X_EAP_AUTH_FAIL	8
-#define DOT11_BSSTRANS_REASON_4WAY_HANDSHK_FAIL		9
-#define DOT11_BSSTRANS_REASON_MANY_REPLAYCNT_FAIL	10
-#define DOT11_BSSTRANS_REASON_MANY_DATAMIC_FAIL		11
-#define DOT11_BSSTRANS_REASON_EXCEED_MAX_RETRANS	12
-#define DOT11_BSSTRANS_REASON_MANY_BCAST_DISASSOC_RX	13
-#define DOT11_BSSTRANS_REASON_MANY_BCAST_DEAUTH_RX	14
-#define DOT11_BSSTRANS_REASON_PREV_TRANSITION_FAIL	15
-#define DOT11_BSSTRANS_REASON_LOW_RSSI			16
-#define DOT11_BSSTRANS_REASON_ROAM_FROM_NON_80211	17
-#define DOT11_BSSTRANS_REASON_RX_BTM_REQ		18
-#define DOT11_BSSTRANS_REASON_PREF_LIST_INCLUDED	19
-#define DOT11_BSSTRANS_REASON_LEAVING_ESS		20
-
-/** BSS Management Transition Request frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_req {
-	uint8 category;			/* category of action frame (10) */
-	uint8 action;			/* WNM action: trans_req (7) */
-	uint8 token;			/* dialog token */
-	uint8 reqmode;			/* transition request mode */
-	uint16 disassoc_tmr;		/* disassociation timer */
-	uint8 validity_intrvl;		/* validity interval */
-	uint8 data[1];			/* optional: BSS term duration, ... */
-						/* ...session info URL, candidate list */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_bsstrans_req dot11_bsstrans_req_t;
-#define DOT11_BSSTRANS_REQ_LEN 7	/* Fixed length */
-
-/* BSS Mgmt Transition Request Mode Field - 802.11v */
-#define DOT11_BSSTRANS_REQMODE_PREF_LIST_INCL		0x01
-#define DOT11_BSSTRANS_REQMODE_ABRIDGED			0x02
-#define DOT11_BSSTRANS_REQMODE_DISASSOC_IMMINENT	0x04
-#define DOT11_BSSTRANS_REQMODE_BSS_TERM_INCL		0x08
-#define DOT11_BSSTRANS_REQMODE_ESS_DISASSOC_IMNT	0x10
-
-/** BSS Management transition response frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_resp {
-	uint8 category;			/* category of action frame (10) */
-	uint8 action;			/* WNM action: trans_resp (8) */
-	uint8 token;			/* dialog token */
-	uint8 status;			/* transition status */
-	uint8 term_delay;		/* validity interval */
-	uint8 data[1];			/* optional: BSSID target, candidate list */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_bsstrans_resp dot11_bsstrans_resp_t;
-#define DOT11_BSSTRANS_RESP_LEN 5	/* Fixed length */
-
-/* BSS Mgmt Transition Response Status Field */
-#define DOT11_BSSTRANS_RESP_STATUS_ACCEPT			0
-#define DOT11_BSSTRANS_RESP_STATUS_REJECT			1
-#define DOT11_BSSTRANS_RESP_STATUS_REJ_INSUFF_BCN		2
-#define DOT11_BSSTRANS_RESP_STATUS_REJ_INSUFF_CAP		3
-#define DOT11_BSSTRANS_RESP_STATUS_REJ_TERM_UNDESIRED		4
-#define DOT11_BSSTRANS_RESP_STATUS_REJ_TERM_DELAY_REQ		5
-#define DOT11_BSSTRANS_RESP_STATUS_REJ_BSS_LIST_PROVIDED	6
-#define DOT11_BSSTRANS_RESP_STATUS_REJ_NO_SUITABLE_BSS		7
-#define DOT11_BSSTRANS_RESP_STATUS_REJ_LEAVING_ESS		8
-
-
-/** BSS Max Idle Period element */
-BWL_PRE_PACKED_STRUCT struct dot11_bss_max_idle_period_ie {
-	uint8 id;				/* 90, DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID */
-	uint8 len;
-	uint16 max_idle_period;			/* in unit of 1000 TUs */
-	uint8 idle_opt;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_bss_max_idle_period_ie dot11_bss_max_idle_period_ie_t;
-#define DOT11_BSS_MAX_IDLE_PERIOD_IE_LEN	3	/* bss max idle period IE size */
-#define DOT11_BSS_MAX_IDLE_PERIOD_OPT_PROTECTED	1	/* BSS max idle option */
-
-/** TIM Broadcast request element */
-BWL_PRE_PACKED_STRUCT struct dot11_timbc_req_ie {
-	uint8 id;				/* 94, DOT11_MNG_TIMBC_REQ_ID */
-	uint8 len;
-	uint8 interval;				/* in unit of beacon interval */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_timbc_req_ie dot11_timbc_req_ie_t;
-#define DOT11_TIMBC_REQ_IE_LEN		1	/* Fixed length */
-
-/** TIM Broadcast request frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_timbc_req {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: DOT11_WNM_ACTION_TIMBC_REQ(18) */
-	uint8 token;				/* dialog token */
-	uint8 data[1];				/* TIM broadcast request element */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_timbc_req dot11_timbc_req_t;
-#define DOT11_TIMBC_REQ_LEN		3	/* Fixed length */
-
-/** TIM Broadcast response element */
-BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp_ie {
-	uint8 id;				/* 95, DOT11_MNG_TIM_BROADCAST_RESP_ID */
-	uint8 len;
-	uint8 status;				/* status of add request */
-	uint8 interval;				/* in unit of beacon interval */
-	int32 offset;				/* in unit of ms */
-	uint16 high_rate;			/* in unit of 0.5 Mb/s */
-	uint16 low_rate;			/* in unit of 0.5 Mb/s */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_timbc_resp_ie dot11_timbc_resp_ie_t;
-#define DOT11_TIMBC_DENY_RESP_IE_LEN	1	/* Deny. Fixed length */
-#define DOT11_TIMBC_ACCEPT_RESP_IE_LEN	10	/* Accept. Fixed length */
-
-#define DOT11_TIMBC_STATUS_ACCEPT		0
-#define DOT11_TIMBC_STATUS_ACCEPT_TSTAMP	1
-#define DOT11_TIMBC_STATUS_DENY			2
-#define DOT11_TIMBC_STATUS_OVERRIDDEN		3
-#define DOT11_TIMBC_STATUS_RESERVED		4
-
-/** TIM Broadcast request frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp {
-	uint8 category;			/* category of action frame (10) */
-	uint8 action;			/* action: DOT11_WNM_ACTION_TIMBC_RESP(19) */
-	uint8 token;			/* dialog token */
-	uint8 data[1];			/* TIM broadcast response element */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_timbc_resp dot11_timbc_resp_t;
-#define DOT11_TIMBC_RESP_LEN	3	/* Fixed length */
-
-/** TIM element */
-BWL_PRE_PACKED_STRUCT struct dot11_tim_ie {
-	uint8 id;			/* 5, DOT11_MNG_TIM_ID	 */
-	uint8 len;			/* 4 - 255 */
-	uint8 dtim_count;		/* DTIM decrementing counter */
-	uint8 dtim_period;		/* DTIM period */
-	uint8 bitmap_control;		/* AID 0 + bitmap offset */
-	uint8 pvb[1];			/* Partial Virtual Bitmap, variable length */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tim_ie dot11_tim_ie_t;
-#define DOT11_TIM_IE_FIXED_LEN	3	/* Fixed length, without id and len */
-#define DOT11_TIM_IE_FIXED_TOTAL_LEN	5	/* Fixed length, with id and len */
-
-/** TIM Broadcast frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_timbc {
-	uint8 category;			/* category of action frame (11) */
-	uint8 action;			/* action: TIM (0) */
-	uint8 check_beacon;		/* need to check-beacon */
-	uint8 tsf[8];			/* Time Synchronization Function */
-	dot11_tim_ie_t tim_ie;		/* TIM element */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_timbc dot11_timbc_t;
-#define DOT11_TIMBC_HDR_LEN	(sizeof(dot11_timbc_t) - sizeof(dot11_tim_ie_t))
-#define DOT11_TIMBC_FIXED_LEN	(sizeof(dot11_timbc_t) - 1)	/* Fixed length */
-#define DOT11_TIMBC_LEN			11	/* Fixed length */
-
-/** TCLAS frame classifier type */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_hdr {
-	uint8 type;
-	uint8 mask;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_fc_hdr dot11_tclas_fc_hdr_t;
-#define DOT11_TCLAS_FC_HDR_LEN		2	/* Fixed length */
-
-#define DOT11_TCLAS_MASK_0		0x1
-#define DOT11_TCLAS_MASK_1		0x2
-#define DOT11_TCLAS_MASK_2		0x4
-#define DOT11_TCLAS_MASK_3		0x8
-#define DOT11_TCLAS_MASK_4		0x10
-#define DOT11_TCLAS_MASK_5		0x20
-#define DOT11_TCLAS_MASK_6		0x40
-#define DOT11_TCLAS_MASK_7		0x80
-
-#define DOT11_TCLAS_FC_0_ETH		0
-#define DOT11_TCLAS_FC_1_IP		1
-#define DOT11_TCLAS_FC_2_8021Q		2
-#define DOT11_TCLAS_FC_3_OFFSET		3
-#define DOT11_TCLAS_FC_4_IP_HIGHER	4
-#define DOT11_TCLAS_FC_5_8021D		5
-
-/** TCLAS frame classifier type 0 parameters for Ethernet */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_0_eth {
-	uint8 type;
-	uint8 mask;
-	uint8 sa[ETHER_ADDR_LEN];
-	uint8 da[ETHER_ADDR_LEN];
-	uint16 eth_type;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_fc_0_eth dot11_tclas_fc_0_eth_t;
-#define DOT11_TCLAS_FC_0_ETH_LEN	16
-
-/** TCLAS frame classifier type 1 parameters for IPV4 */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_1_ipv4 {
-	uint8 type;
-	uint8 mask;
-	uint8 version;
-	uint32 src_ip;
-	uint32 dst_ip;
-	uint16 src_port;
-	uint16 dst_port;
-	uint8 dscp;
-	uint8 protocol;
-	uint8 reserved;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_fc_1_ipv4 dot11_tclas_fc_1_ipv4_t;
-#define DOT11_TCLAS_FC_1_IPV4_LEN	18
-
-/** TCLAS frame classifier type 2 parameters for 802.1Q */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_2_8021q {
-	uint8 type;
-	uint8 mask;
-	uint16 tci;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_fc_2_8021q dot11_tclas_fc_2_8021q_t;
-#define DOT11_TCLAS_FC_2_8021Q_LEN	4
-
-/** TCLAS frame classifier type 3 parameters for filter offset */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_3_filter {
-	uint8 type;
-	uint8 mask;
-	uint16 offset;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_fc_3_filter dot11_tclas_fc_3_filter_t;
-#define DOT11_TCLAS_FC_3_FILTER_LEN	4
-
-/** TCLAS frame classifier type 4 parameters for IPV4 is the same as TCLAS type 1 */
-typedef struct dot11_tclas_fc_1_ipv4 dot11_tclas_fc_4_ipv4_t;
-#define DOT11_TCLAS_FC_4_IPV4_LEN	DOT11_TCLAS_FC_1_IPV4_LEN
-
-/** TCLAS frame classifier type 4 parameters for IPV6 */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_4_ipv6 {
-	uint8 type;
-	uint8 mask;
-	uint8 version;
-	uint8 saddr[16];
-	uint8 daddr[16];
-	uint16 src_port;
-	uint16 dst_port;
-	uint8 dscp;
-	uint8 nexthdr;
-	uint8 flow_lbl[3];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_fc_4_ipv6 dot11_tclas_fc_4_ipv6_t;
-#define DOT11_TCLAS_FC_4_IPV6_LEN	44
-
-/** TCLAS frame classifier type 5 parameters for 802.1D */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_5_8021d {
-	uint8 type;
-	uint8 mask;
-	uint8 pcp;
-	uint8 cfi;
-	uint16 vid;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_fc_5_8021d dot11_tclas_fc_5_8021d_t;
-#define DOT11_TCLAS_FC_5_8021D_LEN	6
-
-/** TCLAS frame classifier type parameters */
-BWL_PRE_PACKED_STRUCT union dot11_tclas_fc {
-	uint8 data[1];
-	dot11_tclas_fc_hdr_t hdr;
-	dot11_tclas_fc_0_eth_t t0_eth;
-	dot11_tclas_fc_1_ipv4_t	t1_ipv4;
-	dot11_tclas_fc_2_8021q_t t2_8021q;
-	dot11_tclas_fc_3_filter_t t3_filter;
-	dot11_tclas_fc_4_ipv4_t	t4_ipv4;
-	dot11_tclas_fc_4_ipv6_t	t4_ipv6;
-	dot11_tclas_fc_5_8021d_t t5_8021d;
-} BWL_POST_PACKED_STRUCT;
-typedef union dot11_tclas_fc dot11_tclas_fc_t;
-
-#define DOT11_TCLAS_FC_MIN_LEN		4	/* Classifier Type 2 has the min size */
-#define DOT11_TCLAS_FC_MAX_LEN		254
-
-/** TCLAS element */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_ie {
-	uint8 id;				/* 14, DOT11_MNG_TCLAS_ID */
-	uint8 len;
-	uint8 user_priority;
-	dot11_tclas_fc_t fc;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_ie dot11_tclas_ie_t;
-#define DOT11_TCLAS_IE_LEN		3	/* Fixed length, include id and len */
-
-/** TCLAS processing element */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_proc_ie {
-	uint8 id;				/* 44, DOT11_MNG_TCLAS_PROC_ID */
-	uint8 len;
-	uint8 process;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_proc_ie dot11_tclas_proc_ie_t;
-#define DOT11_TCLAS_PROC_IE_LEN		3	/* Fixed length, include id and len */
-
-#define DOT11_TCLAS_PROC_MATCHALL	0	/* All high level element need to match */
-#define DOT11_TCLAS_PROC_MATCHONE	1	/* One high level element need to match */
-#define DOT11_TCLAS_PROC_NONMATCH	2	/* Non match to any high level element */
-
-
-/* TSPEC element defined in 802.11 std section 8.4.2.32 - Not supported */
-#define DOT11_TSPEC_IE_LEN		57	/* Fixed length */
-
-/** TFS request element */
-BWL_PRE_PACKED_STRUCT struct dot11_tfs_req_ie {
-	uint8 id;				/* 91, DOT11_MNG_TFS_REQUEST_ID */
-	uint8 len;
-	uint8 tfs_id;
-	uint8 actcode;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tfs_req_ie dot11_tfs_req_ie_t;
-#define DOT11_TFS_REQ_IE_LEN		2	/* Fixed length, without id and len */
-
-/** TFS request action codes (bitfield) */
-#define DOT11_TFS_ACTCODE_DELETE	1
-#define DOT11_TFS_ACTCODE_NOTIFY	2
-
-/** TFS request subelement IDs */
-#define DOT11_TFS_REQ_TFS_SE_ID		1
-#define DOT11_TFS_REQ_VENDOR_SE_ID	221
-
-/** TFS subelement */
-BWL_PRE_PACKED_STRUCT struct dot11_tfs_se {
-	uint8 sub_id;
-	uint8 len;
-	uint8 data[1];				/* TCLAS element(s) + optional TCLAS proc */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tfs_se dot11_tfs_se_t;
-
-
-/** TFS response element */
-BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp_ie {
-	uint8 id;				/* 92, DOT11_MNG_TFS_RESPONSE_ID */
-	uint8 len;
-	uint8 tfs_id;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tfs_resp_ie dot11_tfs_resp_ie_t;
-#define DOT11_TFS_RESP_IE_LEN		1	/* Fixed length, without id and len */
-
-/** TFS response subelement IDs (same subelments, but different IDs than in TFS request */
-#define DOT11_TFS_RESP_TFS_STATUS_SE_ID		1
-#define DOT11_TFS_RESP_TFS_SE_ID		2
-#define DOT11_TFS_RESP_VENDOR_SE_ID		221
-
-/** TFS status subelement */
-BWL_PRE_PACKED_STRUCT struct dot11_tfs_status_se {
-	uint8 sub_id;				/* 92, DOT11_MNG_TFS_RESPONSE_ID */
-	uint8 len;
-	uint8 resp_st;
-	uint8 data[1];				/* Potential dot11_tfs_se_t included */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tfs_status_se dot11_tfs_status_se_t;
-#define DOT11_TFS_STATUS_SE_LEN			1	/* Fixed length, without id and len */
-
-/* Following Definition should be merged to FMS_TFS macro below */
-/* TFS Response status code. Identical to FMS Element status, without N/A  */
-#define DOT11_TFS_STATUS_ACCEPT			0
-#define DOT11_TFS_STATUS_DENY_FORMAT		1
-#define DOT11_TFS_STATUS_DENY_RESOURCE		2
-#define DOT11_TFS_STATUS_DENY_POLICY		4
-#define DOT11_TFS_STATUS_DENY_UNSPECIFIED	5
-#define DOT11_TFS_STATUS_ALTPREF_POLICY		7
-#define DOT11_TFS_STATUS_ALTPREF_TCLAS_UNSUPP	14
-
-/* FMS Element Status and TFS Response Status Definition */
-#define DOT11_FMS_TFS_STATUS_ACCEPT		0
-#define DOT11_FMS_TFS_STATUS_DENY_FORMAT	1
-#define DOT11_FMS_TFS_STATUS_DENY_RESOURCE	2
-#define DOT11_FMS_TFS_STATUS_DENY_MULTIPLE_DI	3
-#define DOT11_FMS_TFS_STATUS_DENY_POLICY	4
-#define DOT11_FMS_TFS_STATUS_DENY_UNSPECIFIED	5
-#define DOT11_FMS_TFS_STATUS_ALT_DIFF_DI	6
-#define DOT11_FMS_TFS_STATUS_ALT_POLICY		7
-#define DOT11_FMS_TFS_STATUS_ALT_CHANGE_DI	8
-#define DOT11_FMS_TFS_STATUS_ALT_MCRATE		9
-#define DOT11_FMS_TFS_STATUS_TERM_POLICY	10
-#define DOT11_FMS_TFS_STATUS_TERM_RESOURCE	11
-#define DOT11_FMS_TFS_STATUS_TERM_HIGHER_PRIO	12
-#define DOT11_FMS_TFS_STATUS_ALT_CHANGE_MDI	13
-#define DOT11_FMS_TFS_STATUS_ALT_TCLAS_UNSUPP	14
-
-/** TFS Management Request frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_tfs_req {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: TFS request (13) */
-	uint8 token;				/* dialog token */
-	uint8 data[1];				/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tfs_req dot11_tfs_req_t;
-#define DOT11_TFS_REQ_LEN		3	/* Fixed length */
-
-/** TFS Management Response frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: TFS request (14) */
-	uint8 token;				/* dialog token */
-	uint8 data[1];				/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tfs_resp dot11_tfs_resp_t;
-#define DOT11_TFS_RESP_LEN		3	/* Fixed length */
-
-/** TFS Management Notify frame request header */
-BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify_req {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: TFS notify request (15) */
-	uint8 tfs_id_cnt;			/* TFS IDs count */
-	uint8 tfs_id[1];			/* Array of TFS IDs */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tfs_notify_req dot11_tfs_notify_req_t;
-#define DOT11_TFS_NOTIFY_REQ_LEN	3	/* Fixed length */
-
-/** TFS Management Notify frame response header */
-BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify_resp {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: TFS notify response (28) */
-	uint8 tfs_id_cnt;			/* TFS IDs count */
-	uint8 tfs_id[1];			/* Array of TFS IDs */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tfs_notify_resp dot11_tfs_notify_resp_t;
-#define DOT11_TFS_NOTIFY_RESP_LEN	3	/* Fixed length */
-
-
-/** WNM-Sleep Management Request frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_req {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: wnm-sleep request (16) */
-	uint8 token;				/* dialog token */
-	uint8 data[1];				/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_wnm_sleep_req dot11_wnm_sleep_req_t;
-#define DOT11_WNM_SLEEP_REQ_LEN		3	/* Fixed length */
-
-/** WNM-Sleep Management Response frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_resp {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: wnm-sleep request (17) */
-	uint8 token;				/* dialog token */
-	uint16 key_len;				/* key data length */
-	uint8 data[1];				/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_wnm_sleep_resp dot11_wnm_sleep_resp_t;
-#define DOT11_WNM_SLEEP_RESP_LEN	5	/* Fixed length */
-
-#define DOT11_WNM_SLEEP_SUBELEM_ID_GTK	0
-#define DOT11_WNM_SLEEP_SUBELEM_ID_IGTK	1
-
-BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_subelem_gtk {
-	uint8 sub_id;
-	uint8 len;
-	uint16 key_info;
-	uint8 key_length;
-	uint8 rsc[8];
-	uint8 key[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_wnm_sleep_subelem_gtk dot11_wnm_sleep_subelem_gtk_t;
-#define DOT11_WNM_SLEEP_SUBELEM_GTK_FIXED_LEN	11	/* without sub_id, len, and key */
-#define DOT11_WNM_SLEEP_SUBELEM_GTK_MAX_LEN	43	/* without sub_id and len */
-
-BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_subelem_igtk {
-	uint8 sub_id;
-	uint8 len;
-	uint16 key_id;
-	uint8 pn[6];
-	uint8 key[16];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_wnm_sleep_subelem_igtk dot11_wnm_sleep_subelem_igtk_t;
-#define DOT11_WNM_SLEEP_SUBELEM_IGTK_LEN 24	/* Fixed length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_ie {
-	uint8 id;				/* 93, DOT11_MNG_WNM_SLEEP_MODE_ID */
-	uint8 len;
-	uint8 act_type;
-	uint8 resp_status;
-	uint16 interval;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_wnm_sleep_ie dot11_wnm_sleep_ie_t;
-#define DOT11_WNM_SLEEP_IE_LEN		4	/* Fixed length */
-
-#define DOT11_WNM_SLEEP_ACT_TYPE_ENTER	0
-#define DOT11_WNM_SLEEP_ACT_TYPE_EXIT	1
-
-#define DOT11_WNM_SLEEP_RESP_ACCEPT	0
-#define DOT11_WNM_SLEEP_RESP_UPDATE	1
-#define DOT11_WNM_SLEEP_RESP_DENY	2
-#define DOT11_WNM_SLEEP_RESP_DENY_TEMP	3
-#define DOT11_WNM_SLEEP_RESP_DENY_KEY	4
-#define DOT11_WNM_SLEEP_RESP_DENY_INUSE	5
-#define DOT11_WNM_SLEEP_RESP_LAST	6
-
-/** DMS Management Request frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_dms_req {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: dms request (23) */
-	uint8 token;				/* dialog token */
-	uint8 data[1];				/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_dms_req dot11_dms_req_t;
-#define DOT11_DMS_REQ_LEN		3	/* Fixed length */
-
-/** DMS Management Response frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_dms_resp {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: dms request (24) */
-	uint8 token;				/* dialog token */
-	uint8 data[1];				/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_dms_resp dot11_dms_resp_t;
-#define DOT11_DMS_RESP_LEN		3	/* Fixed length */
-
-/** DMS request element */
-BWL_PRE_PACKED_STRUCT struct dot11_dms_req_ie {
-	uint8 id;				/* 99, DOT11_MNG_DMS_REQUEST_ID */
-	uint8 len;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_dms_req_ie dot11_dms_req_ie_t;
-#define DOT11_DMS_REQ_IE_LEN		2	/* Fixed length */
-
-/** DMS response element */
-BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_ie {
-	uint8 id;				/* 100, DOT11_MNG_DMS_RESPONSE_ID */
-	uint8 len;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_dms_resp_ie dot11_dms_resp_ie_t;
-#define DOT11_DMS_RESP_IE_LEN		2	/* Fixed length */
-
-/** DMS request descriptor */
-BWL_PRE_PACKED_STRUCT struct dot11_dms_req_desc {
-	uint8 dms_id;
-	uint8 len;
-	uint8 type;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_dms_req_desc dot11_dms_req_desc_t;
-#define DOT11_DMS_REQ_DESC_LEN		3	/* Fixed length */
-
-#define DOT11_DMS_REQ_TYPE_ADD		0
-#define DOT11_DMS_REQ_TYPE_REMOVE	1
-#define DOT11_DMS_REQ_TYPE_CHANGE	2
-
-/** DMS response status */
-BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_st {
-	uint8 dms_id;
-	uint8 len;
-	uint8 type;
-	uint16 lsc;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_dms_resp_st dot11_dms_resp_st_t;
-#define DOT11_DMS_RESP_STATUS_LEN	5	/* Fixed length */
-
-#define DOT11_DMS_RESP_TYPE_ACCEPT	0
-#define DOT11_DMS_RESP_TYPE_DENY	1
-#define DOT11_DMS_RESP_TYPE_TERM	2
-
-#define DOT11_DMS_RESP_LSC_UNSUPPORTED	0xFFFF
-
-/** FMS Management Request frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_fms_req {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: fms request (9) */
-	uint8 token;				/* dialog token */
-	uint8 data[1];				/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_fms_req dot11_fms_req_t;
-#define DOT11_FMS_REQ_LEN		3	/* Fixed length */
-
-/** FMS Management Response frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_fms_resp {
-	uint8 category;				/* category of action frame (10) */
-	uint8 action;				/* WNM action: fms request (10) */
-	uint8 token;				/* dialog token */
-	uint8 data[1];				/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_fms_resp dot11_fms_resp_t;
-#define DOT11_FMS_RESP_LEN		3	/* Fixed length */
-
-/** FMS Descriptor element */
-BWL_PRE_PACKED_STRUCT struct dot11_fms_desc {
-	uint8 id;
-	uint8 len;
-	uint8 num_fms_cnt;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_fms_desc dot11_fms_desc_t;
-#define DOT11_FMS_DESC_LEN		1	/* Fixed length */
-
-#define DOT11_FMS_CNTR_MAX		0x8
-#define DOT11_FMS_CNTR_ID_MASK		0x7
-#define DOT11_FMS_CNTR_ID_SHIFT		0x0
-#define DOT11_FMS_CNTR_COUNT_MASK	0xf1
-#define DOT11_FMS_CNTR_SHIFT		0x3
-
-/** FMS request element */
-BWL_PRE_PACKED_STRUCT struct dot11_fms_req_ie {
-	uint8 id;
-	uint8 len;
-	uint8 fms_token;			/* token used to identify fms stream set */
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_fms_req_ie dot11_fms_req_ie_t;
-#define DOT11_FMS_REQ_IE_FIX_LEN		1	/* Fixed length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_rate_id_field {
-	uint8 mask;
-	uint8 mcs_idx;
-	uint16 rate;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rate_id_field dot11_rate_id_field_t;
-#define DOT11_RATE_ID_FIELD_MCS_SEL_MASK	0x7
-#define DOT11_RATE_ID_FIELD_MCS_SEL_OFFSET	0
-#define DOT11_RATE_ID_FIELD_RATETYPE_MASK	0x18
-#define DOT11_RATE_ID_FIELD_RATETYPE_OFFSET	3
-#define DOT11_RATE_ID_FIELD_LEN		sizeof(dot11_rate_id_field_t)
-
-/** FMS request subelements */
-BWL_PRE_PACKED_STRUCT struct dot11_fms_se {
-	uint8 sub_id;
-	uint8 len;
-	uint8 interval;
-	uint8 max_interval;
-	dot11_rate_id_field_t rate;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_fms_se dot11_fms_se_t;
-#define DOT11_FMS_REQ_SE_LEN		6	/* Fixed length */
-
-#define DOT11_FMS_REQ_SE_ID_FMS		1	/* FMS subelement */
-#define DOT11_FMS_REQ_SE_ID_VS		221	/* Vendor Specific subelement */
-
-/** FMS response element */
-BWL_PRE_PACKED_STRUCT struct dot11_fms_resp_ie {
-	uint8 id;
-	uint8 len;
-	uint8 fms_token;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_fms_resp_ie dot11_fms_resp_ie_t;
-#define DOT11_FMS_RESP_IE_FIX_LEN		1	/* Fixed length */
-
-/* FMS status subelements */
-#define DOT11_FMS_STATUS_SE_ID_FMS	1	/* FMS Status */
-#define DOT11_FMS_STATUS_SE_ID_TCLAS	2	/* TCLAS Status */
-#define DOT11_FMS_STATUS_SE_ID_VS	221	/* Vendor Specific subelement */
-
-/** FMS status subelement */
-BWL_PRE_PACKED_STRUCT struct dot11_fms_status_se {
-	uint8 sub_id;
-	uint8 len;
-	uint8 status;
-	uint8 interval;
-	uint8 max_interval;
-	uint8 fmsid;
-	uint8 counter;
-	dot11_rate_id_field_t rate;
-	uint8 mcast_addr[ETHER_ADDR_LEN];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_fms_status_se dot11_fms_status_se_t;
-#define DOT11_FMS_STATUS_SE_LEN		15	/* Fixed length */
-
-/** TCLAS status subelement */
-BWL_PRE_PACKED_STRUCT struct dot11_tclas_status_se {
-	uint8 sub_id;
-	uint8 len;
-	uint8 fmsid;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_tclas_status_se dot11_tclas_status_se_t;
-#define DOT11_TCLAS_STATUS_SE_LEN		1	/* Fixed length */
-
-BWL_PRE_PACKED_STRUCT struct dot11_addba_req {
-	uint8 category;				/* category of action frame (3) */
-	uint8 action;				/* action: addba req */
-	uint8 token;				/* identifier */
-	uint16 addba_param_set;		/* parameter set */
-	uint16 timeout;				/* timeout in seconds */
-	uint16 start_seqnum;		/* starting sequence number */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_addba_req dot11_addba_req_t;
-#define DOT11_ADDBA_REQ_LEN		9	/* length of addba req frame */
-
-BWL_PRE_PACKED_STRUCT struct dot11_addba_resp {
-	uint8 category;				/* category of action frame (3) */
-	uint8 action;				/* action: addba resp */
-	uint8 token;				/* identifier */
-	uint16 status;				/* status of add request */
-	uint16 addba_param_set;			/* negotiated parameter set */
-	uint16 timeout;				/* negotiated timeout in seconds */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_addba_resp dot11_addba_resp_t;
-#define DOT11_ADDBA_RESP_LEN		9	/* length of addba resp frame */
-
-/* DELBA action parameters */
-#define DOT11_DELBA_PARAM_INIT_MASK	0x0800	/* initiator mask */
-#define DOT11_DELBA_PARAM_INIT_SHIFT	11	/* initiator shift */
-#define DOT11_DELBA_PARAM_TID_MASK	0xf000	/* tid mask */
-#define DOT11_DELBA_PARAM_TID_SHIFT	12	/* tid shift */
-
-BWL_PRE_PACKED_STRUCT struct dot11_delba {
-	uint8 category;				/* category of action frame (3) */
-	uint8 action;				/* action: addba req */
-	uint16 delba_param_set;			/* paarmeter set */
-	uint16 reason;				/* reason for dellba */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_delba dot11_delba_t;
-#define DOT11_DELBA_LEN			6	/* length of delba frame */
-
-/* SA Query action field value */
-#define SA_QUERY_REQUEST		0
-#define SA_QUERY_RESPONSE		1
-
-/* ************* 802.11r related definitions. ************* */
-
-/** Over-the-DS Fast Transition Request frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_ft_req {
-	uint8 category;			/* category of action frame (6) */
-	uint8 action;			/* action: ft req */
-	uint8 sta_addr[ETHER_ADDR_LEN];
-	uint8 tgt_ap_addr[ETHER_ADDR_LEN];
-	uint8 data[1];			/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ft_req dot11_ft_req_t;
-#define DOT11_FT_REQ_FIXED_LEN 14
-
-/** Over-the-DS Fast Transition Response frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_ft_res {
-	uint8 category;			/* category of action frame (6) */
-	uint8 action;			/* action: ft resp */
-	uint8 sta_addr[ETHER_ADDR_LEN];
-	uint8 tgt_ap_addr[ETHER_ADDR_LEN];
-	uint16 status;			/* status code */
-	uint8 data[1];			/* Elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ft_res dot11_ft_res_t;
-#define DOT11_FT_RES_FIXED_LEN 16
-
-/** RDE RIC Data Element. */
-BWL_PRE_PACKED_STRUCT struct dot11_rde_ie {
-	uint8 id;			/* 11r, DOT11_MNG_RDE_ID */
-	uint8 length;
-	uint8 rde_id;			/* RDE identifier. */
-	uint8 rd_count;			/* Resource Descriptor Count. */
-	uint16 status;			/* Status Code. */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rde_ie dot11_rde_ie_t;
-
-/* 11r - Size of the RDE (RIC Data Element) IE, including TLV header. */
-#define DOT11_MNG_RDE_IE_LEN sizeof(dot11_rde_ie_t)
-
-
-/* ************* 802.11k related definitions. ************* */
-
-/* Radio measurements enabled capability ie */
-#define DOT11_RRM_CAP_LEN		5	/* length of rrm cap bitmap */
-#define RCPI_IE_LEN 1
-#define RSNI_IE_LEN 1
-BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie {
-	uint8 cap[DOT11_RRM_CAP_LEN];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t;
-
-/* Bitmap definitions for cap ie */
-#define DOT11_RRM_CAP_LINK		0
-#define DOT11_RRM_CAP_NEIGHBOR_REPORT	1
-#define DOT11_RRM_CAP_PARALLEL		2
-#define DOT11_RRM_CAP_REPEATED		3
-#define DOT11_RRM_CAP_BCN_PASSIVE	4
-#define DOT11_RRM_CAP_BCN_ACTIVE	5
-#define DOT11_RRM_CAP_BCN_TABLE		6
-#define DOT11_RRM_CAP_BCN_REP_COND	7
-#define DOT11_RRM_CAP_FM		8
-#define DOT11_RRM_CAP_CLM		9
-#define DOT11_RRM_CAP_NHM		10
-#define DOT11_RRM_CAP_SM		11
-#define DOT11_RRM_CAP_LCIM		12
-#define DOT11_RRM_CAP_LCIA		13
-#define DOT11_RRM_CAP_TSCM		14
-#define DOT11_RRM_CAP_TTSCM		15
-#define DOT11_RRM_CAP_AP_CHANREP	16
-#define DOT11_RRM_CAP_RMMIB		17
-/* bit18-bit26, not used for RRM_IOVAR */
-#define DOT11_RRM_CAP_MPTI		27
-#define DOT11_RRM_CAP_NBRTSFO		28
-#define DOT11_RRM_CAP_RCPI		29
-#define DOT11_RRM_CAP_RSNI		30
-#define DOT11_RRM_CAP_BSSAAD		31
-#define DOT11_RRM_CAP_BSSAAC		32
-#define DOT11_RRM_CAP_AI		33
-#define DOT11_RRM_CAP_FTM_RANGE		34
-#define DOT11_RRM_CAP_CIVIC_LOC		35
-#define DOT11_RRM_CAP_LAST		35
-
-/* Operating Class (formerly "Regulatory Class") definitions */
-#define DOT11_OP_CLASS_NONE			255
-
-BWL_PRE_PACKED_STRUCT struct do11_ap_chrep {
-	uint8 id;
-	uint8 len;
-	uint8 reg;
-	uint8 chanlist[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct do11_ap_chrep dot11_ap_chrep_t;
-
-/* Radio Measurements action ids */
-#define DOT11_RM_ACTION_RM_REQ		0	/* Radio measurement request */
-#define DOT11_RM_ACTION_RM_REP		1	/* Radio measurement report */
-#define DOT11_RM_ACTION_LM_REQ		2	/* Link measurement request */
-#define DOT11_RM_ACTION_LM_REP		3	/* Link measurement report */
-#define DOT11_RM_ACTION_NR_REQ		4	/* Neighbor report request */
-#define DOT11_RM_ACTION_NR_REP		5	/* Neighbor report response */
-
-/** Generic radio measurement action frame header */
-BWL_PRE_PACKED_STRUCT struct dot11_rm_action {
-	uint8 category;				/* category of action frame (5) */
-	uint8 action;				/* radio measurement action */
-	uint8 token;				/* dialog token */
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rm_action dot11_rm_action_t;
-#define DOT11_RM_ACTION_LEN 3
-
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq {
-	uint8 category;				/* category of action frame (5) */
-	uint8 action;				/* radio measurement action */
-	uint8 token;				/* dialog token */
-	uint16 reps;				/* no. of repetitions */
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq dot11_rmreq_t;
-#define DOT11_RMREQ_LEN	5
-
-BWL_PRE_PACKED_STRUCT struct dot11_rm_ie {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rm_ie dot11_rm_ie_t;
-#define DOT11_RM_IE_LEN	5
-
-/* Definitions for "mode" bits in rm req */
-#define DOT11_RMREQ_MODE_PARALLEL	1
-#define DOT11_RMREQ_MODE_ENABLE		2
-#define DOT11_RMREQ_MODE_REQUEST	4
-#define DOT11_RMREQ_MODE_REPORT		8
-#define DOT11_RMREQ_MODE_DURMAND	0x10	/* Duration Mandatory */
-
-/* Definitions for "mode" bits in rm rep */
-#define DOT11_RMREP_MODE_LATE		1
-#define DOT11_RMREP_MODE_INCAPABLE	2
-#define DOT11_RMREP_MODE_REFUSED	4
-
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint8 reg;
-	uint8 channel;
-	uint16 interval;
-	uint16 duration;
-	uint8 bcn_mode;
-	struct ether_addr	bssid;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t;
-#define DOT11_RMREQ_BCN_LEN	18
-
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn {
-	uint8 reg;
-	uint8 channel;
-	uint32 starttime[2];
-	uint16 duration;
-	uint8 frame_info;
-	uint8 rcpi;
-	uint8 rsni;
-	struct ether_addr	bssid;
-	uint8 antenna_id;
-	uint32 parent_tsf;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t;
-#define DOT11_RMREP_BCN_LEN	26
-
-/* Beacon request measurement mode */
-#define DOT11_RMREQ_BCN_PASSIVE	0
-#define DOT11_RMREQ_BCN_ACTIVE	1
-#define DOT11_RMREQ_BCN_TABLE	2
-
-/* Sub-element IDs for Beacon Request */
-#define DOT11_RMREQ_BCN_SSID_ID 0
-#define DOT11_RMREQ_BCN_REPINFO_ID  1
-#define DOT11_RMREQ_BCN_REPDET_ID   2
-#define DOT11_RMREQ_BCN_REQUEST_ID  10
-#define DOT11_RMREQ_BCN_APCHREP_ID  DOT11_MNG_AP_CHREP_ID
-
-/* Reporting Detail element definition */
-#define DOT11_RMREQ_BCN_REPDET_FIXED	0	/* Fixed length fields only */
-#define DOT11_RMREQ_BCN_REPDET_REQUEST	1	/* + requested information elems */
-#define DOT11_RMREQ_BCN_REPDET_ALL	2	/* All fields */
-
-/* Reporting Information (reporting condition) element definition */
-#define DOT11_RMREQ_BCN_REPINFO_LEN	2	/* Beacon Reporting Information length */
-#define DOT11_RMREQ_BCN_REPCOND_DEFAULT	0	/* Report to be issued after each measurement */
-
-/* Sub-element IDs for Beacon Report */
-#define DOT11_RMREP_BCN_FRM_BODY	1
-#define DOT11_RMREP_BCN_FRM_BODY_LEN_MAX	224 /* 802.11k-2008 7.3.2.22.6 */
-
-/* Sub-element IDs for Frame Report */
-#define DOT11_RMREP_FRAME_COUNT_REPORT 1
-
-/* Statistics Group Report: Group IDs */
-#define DOT11_RRM_STATS_GRP_ID_0	0
-
-/* Statistics Group Report: Group Data length  */
-#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_0	28
-
-/* Channel load request */
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_chanload {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint8 reg;
-	uint8 channel;
-	uint16 interval;
-	uint16 duration;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_chanload dot11_rmreq_chanload_t;
-#define DOT11_RMREQ_CHANLOAD_LEN	11
-
-/** Channel load report */
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_chanload {
-	uint8 reg;
-	uint8 channel;
-	uint32 starttime[2];
-	uint16 duration;
-	uint8 channel_load;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_chanload dot11_rmrep_chanload_t;
-#define DOT11_RMREP_CHANLOAD_LEN	13
-
-/** Noise histogram request */
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_noise {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint8 reg;
-	uint8 channel;
-	uint16 interval;
-	uint16 duration;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_noise dot11_rmreq_noise_t;
-#define DOT11_RMREQ_NOISE_LEN 11
-
-/** Noise histogram report */
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_noise {
-	uint8 reg;
-	uint8 channel;
-	uint32 starttime[2];
-	uint16 duration;
-	uint8 antid;
-	uint8 anpi;
-	uint8 ipi0_dens;
-	uint8 ipi1_dens;
-	uint8 ipi2_dens;
-	uint8 ipi3_dens;
-	uint8 ipi4_dens;
-	uint8 ipi5_dens;
-	uint8 ipi6_dens;
-	uint8 ipi7_dens;
-	uint8 ipi8_dens;
-	uint8 ipi9_dens;
-	uint8 ipi10_dens;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_noise dot11_rmrep_noise_t;
-#define DOT11_RMREP_NOISE_LEN 25
-
-/** Frame request */
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_frame {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint8 reg;
-	uint8 channel;
-	uint16 interval;
-	uint16 duration;
-	uint8 req_type;
-	struct ether_addr	ta;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_frame dot11_rmreq_frame_t;
-#define DOT11_RMREQ_FRAME_LEN 18
-
-/** Frame report */
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frame {
-	uint8 reg;
-	uint8 channel;
-	uint32 starttime[2];
-	uint16 duration;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_frame dot11_rmrep_frame_t;
-#define DOT11_RMREP_FRAME_LEN 12
-
-/** Frame report entry */
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frmentry {
-	struct ether_addr	ta;
-	struct ether_addr	bssid;
-	uint8 phy_type;
-	uint8 avg_rcpi;
-	uint8 last_rsni;
-	uint8 last_rcpi;
-	uint8 ant_id;
-	uint16 frame_cnt;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_frmentry dot11_rmrep_frmentry_t;
-#define DOT11_RMREP_FRMENTRY_LEN 19
-
-/** STA statistics request */
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_stat {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	struct ether_addr	peer;
-	uint16 interval;
-	uint16 duration;
-	uint8 group_id;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_stat dot11_rmreq_stat_t;
-#define DOT11_RMREQ_STAT_LEN 16
-
-/** STA statistics report */
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_stat {
-	uint16 duration;
-	uint8 group_id;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_stat dot11_rmrep_stat_t;
-
-/** Transmit stream/category measurement request */
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_tx_stream {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint16 interval;
-	uint16 duration;
-	struct ether_addr	peer;
-	uint8 traffic_id;
-	uint8 bin0_range;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_tx_stream dot11_rmreq_tx_stream_t;
-
-/** Transmit stream/category measurement report */
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_tx_stream {
-	uint32 starttime[2];
-	uint16 duration;
-	struct ether_addr	peer;
-	uint8 traffic_id;
-	uint8 reason;
-	uint32 txmsdu_cnt;
-	uint32 msdu_discarded_cnt;
-	uint32 msdufailed_cnt;
-	uint32 msduretry_cnt;
-	uint32 cfpolls_lost_cnt;
-	uint32 avrqueue_delay;
-	uint32 avrtx_delay;
-	uint8 bin0_range;
-	uint32 bin0;
-	uint32 bin1;
-	uint32 bin2;
-	uint32 bin3;
-	uint32 bin4;
-	uint32 bin5;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_tx_stream dot11_rmrep_tx_stream_t;
-
-enum {
-	DOT11_FTM_LOCATION_SUBJ_LOCAL = 0, 		/* Where am I? */
-	DOT11_FTM_LOCATION_SUBJ_REMOTE = 1,		/* Where are you? */
-	DOT11_FTM_LOCATION_SUBJ_THIRDPARTY = 2   /* Where is he/she? */
-};
-
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_ftm_lci {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint8 subj;
-
-	/* Following 3 fields are unused. Keep for ROM compatibility. */
-	uint8 lat_res;
-	uint8 lon_res;
-	uint8 alt_res;
-
-	/* optional sub-elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_ftm_lci dot11_rmreq_ftm_lci_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_ftm_lci {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint8 lci_sub_id;
-	uint8 lci_sub_len;
-	/* optional LCI field */
-	/* optional sub-elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_ftm_lci dot11_rmrep_ftm_lci_t;
-
-#define DOT11_FTM_LCI_SUBELEM_ID 		0
-#define DOT11_FTM_LCI_SUBELEM_LEN 		2
-#define DOT11_FTM_LCI_FIELD_LEN 		16
-#define DOT11_FTM_LCI_UNKNOWN_LEN 		2
-
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_ftm_civic {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint8 subj;
-	uint8 civloc_type;
-	uint8 siu;	/* service interval units */
-	uint16 si;  /* service interval */
-	/* optional sub-elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_ftm_civic dot11_rmreq_ftm_civic_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_ftm_civic {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint8 civloc_type;
-	uint8 civloc_sub_id;
-	uint8 civloc_sub_len;
-	/* optional location civic field */
-	/* optional sub-elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_ftm_civic dot11_rmrep_ftm_civic_t;
-
-#define DOT11_FTM_CIVIC_LOC_TYPE_RFC4776	0
-#define DOT11_FTM_CIVIC_SUBELEM_ID 			0
-#define DOT11_FTM_CIVIC_SUBELEM_LEN 		2
-#define DOT11_FTM_CIVIC_LOC_SI_NONE			0
-#define DOT11_FTM_CIVIC_TYPE_LEN			1
-#define DOT11_FTM_CIVIC_UNKNOWN_LEN 		3
-
-BWL_PRE_PACKED_STRUCT struct dot11_ftm_range_subel {
-	uint8 id;
-	uint8 len;
-	uint16 max_age;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ftm_range_subel dot11_ftm_range_subel_t;
-#define DOT11_FTM_RANGE_SUBELEM_ID      4
-#define DOT11_FTM_RANGE_SUBELEM_LEN     2
-
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_ftm_range {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint16 max_init_delay;		/* maximum random initial delay */
-	uint8 min_ap_count;
-	uint8 data[1];
-	/* neighbor report sub-elements */
-	/* optional sub-elements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_ftm_range dot11_rmreq_ftm_range_t;
-#define DOT11_RMREQ_FTM_RANGE_LEN 8
-
-BWL_PRE_PACKED_STRUCT struct dot11_ftm_range_entry {
-	uint32 start_tsf;		/* 4 lsb of tsf */
-	struct ether_addr bssid;
-	uint16 range;
-	uint16 max_err;
-	uint8  rsvd;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ftm_range_entry dot11_ftm_range_entry_t;
-#define DOT11_FTM_RANGE_ENTRY_MAX_COUNT   15
-
-enum {
-	DOT11_FTM_RANGE_ERROR_AP_INCAPABLE = 3,
-	DOT11_FTM_RANGE_ERROR_AP_FAILED = 4,
-	DOT11_FTM_RANGE_ERROR_TX_FAILED = 8,
-	DOT11_FTM_RANGE_ERROR_MAX
-};
-
-BWL_PRE_PACKED_STRUCT struct dot11_ftm_range_error_entry {
-	uint32 start_tsf;		/* 4 lsb of tsf */
-	struct ether_addr bssid;
-	uint8  code;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ftm_range_error_entry dot11_ftm_range_error_entry_t;
-#define DOT11_FTM_RANGE_ERROR_ENTRY_MAX_COUNT   11
-
-BWL_PRE_PACKED_STRUCT struct dot11_rmrep_ftm_range {
-    uint8 id;
-    uint8 len;
-    uint8 token;
-    uint8 mode;
-    uint8 type;
-    uint8 entry_count;
-    uint8 data[2]; /* includes pad */
-	/*
-	dot11_ftm_range_entry_t entries[entry_count];
-	uint8 error_count;
-	dot11_ftm_error_entry_t errors[error_count];
-	 */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmrep_ftm_range dot11_rmrep_ftm_range_t;
-
-#define DOT11_FTM_RANGE_REP_MIN_LEN     6       /* No extra byte for error_count */
-#define DOT11_FTM_RANGE_ENTRY_CNT_MAX   15
-#define DOT11_FTM_RANGE_ERROR_CNT_MAX   11
-#define DOT11_FTM_RANGE_REP_FIXED_LEN   1       /* No extra byte for error_count */
-/** Measurement pause request */
-BWL_PRE_PACKED_STRUCT struct dot11_rmreq_pause_time {
-	uint8 id;
-	uint8 len;
-	uint8 token;
-	uint8 mode;
-	uint8 type;
-	uint16 pause_time;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_rmreq_pause_time dot11_rmreq_pause_time_t;
-
-
-/* Neighbor Report subelements ID (11k & 11v) */
-#define DOT11_NGBR_TSF_INFO_SE_ID	1
-#define DOT11_NGBR_CCS_SE_ID		2
-#define DOT11_NGBR_BSSTRANS_PREF_SE_ID	3
-#define DOT11_NGBR_BSS_TERM_DUR_SE_ID	4
-#define DOT11_NGBR_BEARING_SE_ID	5
-
-/** Neighbor Report, BSS Transition Candidate Preference subelement */
-BWL_PRE_PACKED_STRUCT struct dot11_ngbr_bsstrans_pref_se {
-	uint8 sub_id;
-	uint8 len;
-	uint8 preference;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ngbr_bsstrans_pref_se dot11_ngbr_bsstrans_pref_se_t;
-#define DOT11_NGBR_BSSTRANS_PREF_SE_LEN	1
-
-/** Neighbor Report, BSS Termination Duration subelement */
-BWL_PRE_PACKED_STRUCT struct dot11_ngbr_bss_term_dur_se {
-	uint8 sub_id;
-	uint8 len;
-	uint8 tsf[8];
-	uint16 duration;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ngbr_bss_term_dur_se dot11_ngbr_bss_term_dur_se_t;
-#define DOT11_NGBR_BSS_TERM_DUR_SE_LEN	10
-
-/* Neighbor Report BSSID Information Field */
-#define DOT11_NGBR_BI_REACHABILTY_UNKN	0x0002
-#define DOT11_NGBR_BI_REACHABILTY	0x0003
-#define DOT11_NGBR_BI_SEC		0x0004
-#define DOT11_NGBR_BI_KEY_SCOPE		0x0008
-#define DOT11_NGBR_BI_CAP		0x03f0
-#define DOT11_NGBR_BI_CAP_SPEC_MGMT	0x0010
-#define DOT11_NGBR_BI_CAP_QOS		0x0020
-#define DOT11_NGBR_BI_CAP_APSD		0x0040
-#define DOT11_NGBR_BI_CAP_RDIO_MSMT	0x0080
-#define DOT11_NGBR_BI_CAP_DEL_BA	0x0100
-#define DOT11_NGBR_BI_CAP_IMM_BA	0x0200
-#define DOT11_NGBR_BI_MOBILITY		0x0400
-#define DOT11_NGBR_BI_HT		0x0800
-#define DOT11_NGBR_BI_VHT		0x1000
-#define DOT11_NGBR_BI_FTM		0x2000
-
-/** Neighbor Report element (11k & 11v) */
-BWL_PRE_PACKED_STRUCT struct dot11_neighbor_rep_ie {
-	uint8 id;
-	uint8 len;
-	struct ether_addr bssid;
-	uint32 bssid_info;
-	uint8 reg;		/* Operating class */
-	uint8 channel;
-	uint8 phytype;
-	uint8 data[1]; 		/* Variable size subelements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_neighbor_rep_ie dot11_neighbor_rep_ie_t;
-#define DOT11_NEIGHBOR_REP_IE_FIXED_LEN	13
-
-
-/* MLME Enumerations */
-#define DOT11_BSSTYPE_INFRASTRUCTURE		0	/* d11 infrastructure */
-#define DOT11_BSSTYPE_INDEPENDENT		1	/* d11 independent */
-#define DOT11_BSSTYPE_ANY			2	/* d11 any BSS type */
-#define DOT11_BSSTYPE_MESH			3	/* d11 Mesh */
-#define DOT11_SCANTYPE_ACTIVE			0	/* d11 scan active */
-#define DOT11_SCANTYPE_PASSIVE			1	/* d11 scan passive */
-
-/** Link Measurement */
-BWL_PRE_PACKED_STRUCT struct dot11_lmreq {
-	uint8 category;				/* category of action frame (5) */
-	uint8 action;				/* radio measurement action */
-	uint8 token;				/* dialog token */
-	uint8 txpwr;				/* Transmit Power Used */
-	uint8 maxtxpwr;				/* Max Transmit Power */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_lmreq dot11_lmreq_t;
-#define DOT11_LMREQ_LEN	5
-
-BWL_PRE_PACKED_STRUCT struct dot11_lmrep {
-	uint8 category;				/* category of action frame (5) */
-	uint8 action;				/* radio measurement action */
-	uint8 token;				/* dialog token */
-	dot11_tpc_rep_t tpc;			/* TPC element */
-	uint8 rxant;				/* Receive Antenna ID */
-	uint8 txant;				/* Transmit Antenna ID */
-	uint8 rcpi;				/* RCPI */
-	uint8 rsni;				/* RSNI */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_lmrep dot11_lmrep_t;
-#define DOT11_LMREP_LEN	11
-
-/* 802.11 BRCM "Compromise" Pre N constants */
-#define PREN_PREAMBLE		24	/* green field preamble time */
-#define PREN_MM_EXT		12	/* extra mixed mode preamble time */
-#define PREN_PREAMBLE_EXT	4	/* extra preamble (multiply by unique_streams-1) */
-
-/* 802.11N PHY constants */
-#define RIFS_11N_TIME		2	/* NPHY RIFS time */
-
-/* 802.11 HT PLCP format 802.11n-2009, sec 20.3.9.4.3
- * HT-SIG is composed of two 24 bit parts, HT-SIG1 and HT-SIG2
- */
-/* HT-SIG1 */
-#define HT_SIG1_MCS_MASK        0x00007F
-#define HT_SIG1_CBW             0x000080
-#define HT_SIG1_HT_LENGTH       0xFFFF00
-
-/* HT-SIG2 */
-#define HT_SIG2_SMOOTHING       0x000001
-#define HT_SIG2_NOT_SOUNDING    0x000002
-#define HT_SIG2_RESERVED        0x000004
-#define HT_SIG2_AGGREGATION     0x000008
-#define HT_SIG2_STBC_MASK       0x000030
-#define HT_SIG2_STBC_SHIFT      4
-#define HT_SIG2_FEC_CODING      0x000040
-#define HT_SIG2_SHORT_GI        0x000080
-#define HT_SIG2_ESS_MASK        0x000300
-#define HT_SIG2_ESS_SHIFT       8
-#define HT_SIG2_CRC             0x03FC00
-#define HT_SIG2_TAIL            0x1C0000
-
-/* HT Timing-related parameters (802.11-2012, sec 20.3.6) */
-#define HT_T_LEG_PREAMBLE      16
-#define HT_T_L_SIG              4
-#define HT_T_SIG                8
-#define HT_T_LTF1               4
-#define HT_T_GF_LTF1            8
-#define HT_T_LTFs               4
-#define HT_T_STF                4
-#define HT_T_GF_STF             8
-#define HT_T_SYML               4
-
-#define HT_N_SERVICE           16       /* bits in SERVICE field */
-#define HT_N_TAIL               6       /* tail bits per BCC encoder */
-
-/* 802.11 A PHY constants */
-#define APHY_SLOT_TIME          9       /* APHY slot time */
-#define APHY_SIFS_TIME          16      /* APHY SIFS time */
-#define APHY_DIFS_TIME          (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME))  /* APHY DIFS time */
-#define APHY_PREAMBLE_TIME      16      /* APHY preamble time */
-#define APHY_SIGNAL_TIME        4       /* APHY signal time */
-#define APHY_SYMBOL_TIME        4       /* APHY symbol time */
-#define APHY_SERVICE_NBITS      16      /* APHY service nbits */
-#define APHY_TAIL_NBITS         6       /* APHY tail nbits */
-#define APHY_CWMIN              15      /* APHY cwmin */
-#define APHY_PHYHDR_DUR		20	/* APHY PHY Header Duration */
-
-/* 802.11 B PHY constants */
-#define BPHY_SLOT_TIME          20      /* BPHY slot time */
-#define BPHY_SIFS_TIME          10      /* BPHY SIFS time */
-#define BPHY_DIFS_TIME          50      /* BPHY DIFS time */
-#define BPHY_PLCP_TIME          192     /* BPHY PLCP time */
-#define BPHY_PLCP_SHORT_TIME    96      /* BPHY PLCP short time */
-#define BPHY_CWMIN              31      /* BPHY cwmin */
-#define BPHY_SHORT_PHYHDR_DUR	96	/* BPHY Short PHY Header Duration */
-#define BPHY_LONG_PHYHDR_DUR	192	/* BPHY Long PHY Header Duration */
-
-/* 802.11 G constants */
-#define DOT11_OFDM_SIGNAL_EXTENSION	6	/* d11 OFDM signal extension */
-
-#define PHY_CWMAX		1023	/* PHY cwmax */
-
-#define	DOT11_MAXNUMFRAGS	16	/* max # fragments per MSDU */
-
-/* 802.11 VHT constants */
-
-typedef int vht_group_id_t;
-
-/* for VHT-A1 */
-/* SIG-A1 reserved bits */
-#define VHT_SIGA1_CONST_MASK            0x800004
-
-#define VHT_SIGA1_BW_MASK               0x000003
-#define VHT_SIGA1_20MHZ_VAL             0x000000
-#define VHT_SIGA1_40MHZ_VAL             0x000001
-#define VHT_SIGA1_80MHZ_VAL             0x000002
-#define VHT_SIGA1_160MHZ_VAL            0x000003
-
-#define VHT_SIGA1_STBC                  0x000008
-
-#define VHT_SIGA1_GID_MASK              0x0003f0
-#define VHT_SIGA1_GID_SHIFT             4
-#define VHT_SIGA1_GID_TO_AP             0x00
-#define VHT_SIGA1_GID_NOT_TO_AP         0x3f
-#define VHT_SIGA1_GID_MAX_GID           0x3f
-
-#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00
-#define VHT_SIGA1_NSTS_SHIFT            10
-#define VHT_SIGA1_MAX_USERPOS           3
-
-#define VHT_SIGA1_PARTIAL_AID_MASK      0x3fe000
-#define VHT_SIGA1_PARTIAL_AID_SHIFT     13
-
-#define VHT_SIGA1_TXOP_PS_NOT_ALLOWED   0x400000
-
-/* for VHT-A2 */
-#define VHT_SIGA2_GI_NONE               0x000000
-#define VHT_SIGA2_GI_SHORT              0x000001
-#define VHT_SIGA2_GI_W_MOD10            0x000002
-#define VHT_SIGA2_CODING_LDPC           0x000004
-#define VHT_SIGA2_LDPC_EXTRA_OFDM_SYM   0x000008
-#define VHT_SIGA2_BEAMFORM_ENABLE       0x000100
-#define VHT_SIGA2_MCS_SHIFT             4
-
-#define VHT_SIGA2_B9_RESERVED           0x000200
-#define VHT_SIGA2_TAIL_MASK             0xfc0000
-#define VHT_SIGA2_TAIL_VALUE            0x000000
-
-/* VHT Timing-related parameters (802.11ac D4.0, sec 22.3.6) */
-#define VHT_T_LEG_PREAMBLE      16
-#define VHT_T_L_SIG              4
-#define VHT_T_SIG_A              8
-#define VHT_T_LTF                4
-#define VHT_T_STF                4
-#define VHT_T_SIG_B              4
-#define VHT_T_SYML               4
-
-#define VHT_N_SERVICE           16	/* bits in SERVICE field */
-#define VHT_N_TAIL               6	/* tail bits per BCC encoder */
-
-
-/** dot11Counters Table - 802.11 spec., Annex D */
-typedef struct d11cnt {
-	uint32		txfrag;		/* dot11TransmittedFragmentCount */
-	uint32		txmulti;	/* dot11MulticastTransmittedFrameCount */
-	uint32		txfail;		/* dot11FailedCount */
-	uint32		txretry;	/* dot11RetryCount */
-	uint32		txretrie;	/* dot11MultipleRetryCount */
-	uint32		rxdup;		/* dot11FrameduplicateCount */
-	uint32		txrts;		/* dot11RTSSuccessCount */
-	uint32		txnocts;	/* dot11RTSFailureCount */
-	uint32		txnoack;	/* dot11ACKFailureCount */
-	uint32		rxfrag;		/* dot11ReceivedFragmentCount */
-	uint32		rxmulti;	/* dot11MulticastReceivedFrameCount */
-	uint32		rxcrc;		/* dot11FCSErrorCount */
-	uint32		txfrmsnt;	/* dot11TransmittedFrameCount */
-	uint32		rxundec;	/* dot11WEPUndecryptableCount */
-} d11cnt_t;
-
-#define BRCM_PROP_OUI		"\x00\x90\x4C"
-
-
-/* Action frame type for FTM Initiator Report */
-#define BRCM_FTM_VS_AF_TYPE	14
-enum {
-	BRCM_FTM_VS_INITIATOR_RPT_SUBTYPE = 1,	/* FTM Initiator Report */
-	BRCM_FTM_VS_COLLECT_SUBTYPE = 2,	/* FTM Collect debug protocol */
-};
-
-/* Action frame type for RWL */
-#define RWL_WIFI_DEFAULT		0
-#define RWL_WIFI_FIND_MY_PEER		9 /* Used while finding server */
-#define RWL_WIFI_FOUND_PEER		10 /* Server response to the client  */
-#define RWL_ACTION_WIFI_FRAG_TYPE	85 /* Fragment indicator for receiver */
-
-#define PROXD_AF_TYPE			11 /* Wifi proximity action frame type */
-#define BRCM_RELMACST_AF_TYPE	        12 /* RMC action frame type */
-
-
-
-/* brcm syscap_ie cap */
-#define BRCM_SYSCAP_WET_TUNNEL	0x0100	/* Device with WET_TUNNEL support */
-
-#define BRCM_OUI		"\x00\x10\x18"	/* Broadcom OUI */
-
-/** BRCM info element */
-BWL_PRE_PACKED_STRUCT struct brcm_ie {
-	uint8	id;		/* IE ID, 221, DOT11_MNG_PROPR_ID */
-	uint8	len;		/* IE length */
-	uint8	oui[3];
-	uint8	ver;		/* type/ver of this IE */
-	uint8	assoc;		/* # of assoc STAs */
-	uint8	flags;		/* misc flags */
-	uint8	flags1;		/* misc flags */
-	uint16	amsdu_mtu_pref;	/* preferred A-MSDU MTU */
-} BWL_POST_PACKED_STRUCT;
-typedef	struct brcm_ie brcm_ie_t;
-#define BRCM_IE_LEN		11	/* BRCM IE length */
-#define BRCM_IE_VER		2	/* BRCM IE version */
-#define BRCM_IE_LEGACY_AES_VER	1	/* BRCM IE legacy AES version */
-
-/* brcm_ie flags */
-#define	BRF_ABCAP		0x1	/* afterburner is obsolete,  defined for backward compat */
-#define	BRF_ABRQRD		0x2	/* afterburner is obsolete,  defined for backward compat */
-#define	BRF_LZWDS		0x4	/* lazy wds enabled */
-#define	BRF_BLOCKACK		0x8	/* BlockACK capable */
-#define BRF_ABCOUNTER_MASK	0xf0	/* afterburner is obsolete,  defined for backward compat */
-#define BRF_PROP_11N_MCS	0x10	/* re-use afterburner bit */
-#define BRF_MEDIA_CLIENT	0x20	/* re-use afterburner bit to indicate media client device */
-
-#define GET_BRF_PROP_11N_MCS(brcm_ie) \
-	(!((brcm_ie)->flags & BRF_ABCAP) && ((brcm_ie)->flags & BRF_PROP_11N_MCS))
-
-/* brcm_ie flags1 */
-#define	BRF1_AMSDU		0x1	/* A-MSDU capable */
-#define	BRF1_WNM		0x2	/* WNM capable */
-#define BRF1_WMEPS		0x4	/* AP is capable of handling WME + PS w/o APSD */
-#define BRF1_PSOFIX		0x8	/* AP has fixed PS mode out-of-order packets */
-#define	BRF1_RX_LARGE_AGG	0x10	/* device can rx large aggregates */
-#define BRF1_RFAWARE_DCS	0x20    /* RFAWARE dynamic channel selection (DCS) */
-#define BRF1_SOFTAP		0x40    /* Configure as Broadcom SOFTAP */
-#define BRF1_DWDS		0x80    /* DWDS capable */
-
-/** Vendor IE structure */
-BWL_PRE_PACKED_STRUCT struct vndr_ie {
-	uchar id;
-	uchar len;
-	uchar oui [3];
-	uchar data [1]; 	/* Variable size data */
-} BWL_POST_PACKED_STRUCT;
-typedef struct vndr_ie vndr_ie_t;
-
-#define VNDR_IE_HDR_LEN		2	/* id + len field */
-#define VNDR_IE_MIN_LEN		3	/* size of the oui field */
-#define VNDR_IE_FIXED_LEN	(VNDR_IE_HDR_LEN + VNDR_IE_MIN_LEN)
-
-#define VNDR_IE_MAX_LEN		255	/* vendor IE max length, without ID and len */
-
-/** BRCM PROP DEVICE PRIMARY MAC ADDRESS IE */
-BWL_PRE_PACKED_STRUCT struct member_of_brcm_prop_ie {
-	uchar id;
-	uchar len;
-	uchar oui[3];
-	uint8	type;           /* type indicates what follows */
-	struct ether_addr ea;   /* Device Primary MAC Adrress */
-} BWL_POST_PACKED_STRUCT;
-typedef struct member_of_brcm_prop_ie member_of_brcm_prop_ie_t;
-
-#define MEMBER_OF_BRCM_PROP_IE_LEN		10	/* IE max length */
-#define MEMBER_OF_BRCM_PROP_IE_HDRLEN	        (sizeof(member_of_brcm_prop_ie_t))
-#define MEMBER_OF_BRCM_PROP_IE_TYPE		54
-
-/** BRCM Reliable Multicast IE */
-BWL_PRE_PACKED_STRUCT struct relmcast_brcm_prop_ie {
-	uint8 id;
-	uint8 len;
-	uint8 oui[3];
-	uint8 type;           /* type indicates what follows */
-	struct ether_addr ea;   /* The ack sender's MAC Adrress */
-	struct ether_addr mcast_ea;  /* The multicast MAC address */
-	uint8 updtmo; /* time interval(second) for client to send null packet to report its rssi */
-} BWL_POST_PACKED_STRUCT;
-typedef struct relmcast_brcm_prop_ie relmcast_brcm_prop_ie_t;
-
-/* IE length */
-/* BRCM_PROP_IE_LEN = sizeof(relmcast_brcm_prop_ie_t)-((sizeof (id) + sizeof (len)))? */
-#define RELMCAST_BRCM_PROP_IE_LEN	(sizeof(relmcast_brcm_prop_ie_t)-(2*sizeof(uint8)))
-
-#define RELMCAST_BRCM_PROP_IE_TYPE	55
-
-/* BRCM BTC IE */
-BWL_PRE_PACKED_STRUCT struct btc_brcm_prop_ie {
-	uint8 id;
-	uint8 len;
-	uint8 oui[3];
-	uint8 type;           /* type inidicates what follows */
-	uint32 info;
-} BWL_POST_PACKED_STRUCT;
-typedef struct btc_brcm_prop_ie btc_brcm_prop_ie_t;
-
-#define BTC_INFO_BRCM_PROP_IE_TYPE	90
-#define BRCM_BTC_INFO_TYPE_LEN	(sizeof(btc_brcm_prop_ie_t) - (2 * sizeof(uint8)))
-
-/* ************* HT definitions. ************* */
-#define MCSSET_LEN	16	/* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */
-#define MAX_MCS_NUM	(128)	/* max mcs number = 128 */
-
-BWL_PRE_PACKED_STRUCT struct ht_cap_ie {
-	uint16	cap;
-	uint8	params;
-	uint8	supp_mcs[MCSSET_LEN];
-	uint16	ext_htcap;
-	uint32	txbf_cap;
-	uint8	as_cap;
-} BWL_POST_PACKED_STRUCT;
-typedef struct ht_cap_ie ht_cap_ie_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_ht_cap_ie {
-	uint8	id;
-	uint8	len;
-	ht_cap_ie_t ht_cap;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ht_cap_ie dot11_ht_cap_ie_t;
-
-/* CAP IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
-/* the capability IE is primarily used to convey this nodes abilities */
-BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie {
-	uint8	id;		/* IE ID, 221, DOT11_MNG_PROPR_ID */
-	uint8	len;		/* IE length */
-	uint8	oui[3];
-	uint8	type;           /* type indicates what follows */
-	ht_cap_ie_t cap_ie;
-} BWL_POST_PACKED_STRUCT;
-typedef struct ht_prop_cap_ie ht_prop_cap_ie_t;
-
-#define HT_PROP_IE_OVERHEAD	4	/* overhead bytes for prop oui ie */
-#define HT_CAP_IE_LEN		26	/* HT capability len (based on .11n d2.0) */
-#define HT_CAP_IE_TYPE		51
-
-#define HT_CAP_LDPC_CODING	0x0001	/* Support for rx of LDPC coded pkts */
-#define HT_CAP_40MHZ		0x0002  /* FALSE:20Mhz, TRUE:20/40MHZ supported */
-#define HT_CAP_MIMO_PS_MASK	0x000C  /* Mimo PS mask */
-#define HT_CAP_MIMO_PS_SHIFT	0x0002	/* Mimo PS shift */
-#define HT_CAP_MIMO_PS_OFF	0x0003	/* Mimo PS, no restriction */
-#define HT_CAP_MIMO_PS_RTS	0x0001	/* Mimo PS, send RTS/CTS around MIMO frames */
-#define HT_CAP_MIMO_PS_ON	0x0000	/* Mimo PS, MIMO disallowed */
-#define HT_CAP_GF		0x0010	/* Greenfield preamble support */
-#define HT_CAP_SHORT_GI_20	0x0020	/* 20MHZ short guard interval support */
-#define HT_CAP_SHORT_GI_40	0x0040	/* 40Mhz short guard interval support */
-#define HT_CAP_TX_STBC		0x0080	/* Tx STBC support */
-#define HT_CAP_RX_STBC_MASK	0x0300	/* Rx STBC mask */
-#define HT_CAP_RX_STBC_SHIFT	8	/* Rx STBC shift */
-#define HT_CAP_DELAYED_BA	0x0400	/* delayed BA support */
-#define HT_CAP_MAX_AMSDU	0x0800	/* Max AMSDU size in bytes , 0=3839, 1=7935 */
-
-#define HT_CAP_DSSS_CCK	0x1000	/* DSSS/CCK supported by the BSS */
-#define HT_CAP_PSMP		0x2000	/* Power Save Multi Poll support */
-#define HT_CAP_40MHZ_INTOLERANT 0x4000	/* 40MHz Intolerant */
-#define HT_CAP_LSIG_TXOP	0x8000	/* L-SIG TXOP protection support */
-
-#define HT_CAP_RX_STBC_NO		0x0	/* no rx STBC support */
-#define HT_CAP_RX_STBC_ONE_STREAM	0x1	/* rx STBC support of 1 spatial stream */
-#define HT_CAP_RX_STBC_TWO_STREAM	0x2	/* rx STBC support of 1-2 spatial streams */
-#define HT_CAP_RX_STBC_THREE_STREAM	0x3	/* rx STBC support of 1-3 spatial streams */
-
-
-#define HT_CAP_TXBF_CAP_IMPLICIT_TXBF_RX	0x1
-#define HT_CAP_TXBF_CAP_NDP_RX			0x8
-#define HT_CAP_TXBF_CAP_NDP_TX			0x10
-#define HT_CAP_TXBF_CAP_EXPLICIT_CSI		0x100
-#define HT_CAP_TXBF_CAP_EXPLICIT_NC_STEERING	0x200
-#define HT_CAP_TXBF_CAP_EXPLICIT_C_STEERING	0x400
-#define HT_CAP_TXBF_CAP_EXPLICIT_CSI_FB_MASK	0x1800
-#define HT_CAP_TXBF_CAP_EXPLICIT_CSI_FB_SHIFT	11
-#define HT_CAP_TXBF_CAP_EXPLICIT_NC_FB_MASK	0x6000
-#define HT_CAP_TXBF_CAP_EXPLICIT_NC_FB_SHIFT	13
-#define HT_CAP_TXBF_CAP_EXPLICIT_C_FB_MASK	0x18000
-#define HT_CAP_TXBF_CAP_EXPLICIT_C_FB_SHIFT	15
-#define HT_CAP_TXBF_CAP_CSI_BFR_ANT_SHIFT	19
-#define HT_CAP_TXBF_CAP_NC_BFR_ANT_SHIFT	21
-#define HT_CAP_TXBF_CAP_C_BFR_ANT_SHIFT		23
-#define HT_CAP_TXBF_CAP_C_BFR_ANT_MASK		0x1800000
-
-#define HT_CAP_TXBF_CAP_CHAN_ESTIM_SHIFT	27
-#define HT_CAP_TXBF_CAP_CHAN_ESTIM_MASK		0x18000000
-
-#define HT_CAP_TXBF_FB_TYPE_NONE 	0
-#define HT_CAP_TXBF_FB_TYPE_DELAYED 	1
-#define HT_CAP_TXBF_FB_TYPE_IMMEDIATE 	2
-#define HT_CAP_TXBF_FB_TYPE_BOTH 	3
-
-#define HT_CAP_TX_BF_CAP_EXPLICIT_CSI_FB_MASK	0x400
-#define HT_CAP_TX_BF_CAP_EXPLICIT_CSI_FB_SHIFT	10
-#define HT_CAP_TX_BF_CAP_EXPLICIT_COMPRESSED_FB_MASK 0x18000
-#define HT_CAP_TX_BF_CAP_EXPLICIT_COMPRESSED_FB_SHIFT 15
-
-#define VHT_MAX_MPDU		11454	/* max mpdu size for now (bytes) */
-#define VHT_MPDU_MSDU_DELTA	56		/* Difference in spec - vht mpdu, amsdu len */
-/* Max AMSDU len - per spec */
-#define VHT_MAX_AMSDU		(VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA)
-
-#define HT_MAX_AMSDU		7935	/* max amsdu size (bytes) per the HT spec */
-#define HT_MIN_AMSDU		3835	/* min amsdu size (bytes) per the HT spec */
-
-#define HT_PARAMS_RX_FACTOR_MASK	0x03	/* ampdu rcv factor mask */
-#define HT_PARAMS_DENSITY_MASK		0x1C	/* ampdu density mask */
-#define HT_PARAMS_DENSITY_SHIFT	2	/* ampdu density shift */
-
-/* HT/AMPDU specific define */
-#define AMPDU_MAX_MPDU_DENSITY  7       /* max mpdu density; in 1/4 usec units */
-#define AMPDU_DENSITY_NONE      0       /* No density requirement */
-#define AMPDU_DENSITY_1over4_US 1       /* 1/4 us density */
-#define AMPDU_DENSITY_1over2_US 2       /* 1/2 us density */
-#define AMPDU_DENSITY_1_US      3       /*   1 us density */
-#define AMPDU_DENSITY_2_US      4       /*   2 us density */
-#define AMPDU_DENSITY_4_US      5       /*   4 us density */
-#define AMPDU_DENSITY_8_US      6       /*   8 us density */
-#define AMPDU_DENSITY_16_US     7       /*  16 us density */
-#define AMPDU_RX_FACTOR_8K      0       /* max rcv ampdu len (8kb) */
-#define AMPDU_RX_FACTOR_16K     1       /* max rcv ampdu len (16kb) */
-#define AMPDU_RX_FACTOR_32K     2       /* max rcv ampdu len (32kb) */
-#define AMPDU_RX_FACTOR_64K     3       /* max rcv ampdu len (64kb) */
-
-/* AMPDU RX factors for VHT rates */
-#define AMPDU_RX_FACTOR_128K    4       /* max rcv ampdu len (128kb) */
-#define AMPDU_RX_FACTOR_256K    5       /* max rcv ampdu len (256kb) */
-#define AMPDU_RX_FACTOR_512K    6       /* max rcv ampdu len (512kb) */
-#define AMPDU_RX_FACTOR_1024K   7       /* max rcv ampdu len (1024kb) */
-
-#define AMPDU_RX_FACTOR_BASE    8*1024  /* ampdu factor base for rx len */
-#define AMPDU_RX_FACTOR_BASE_PWR	13	/* ampdu factor base for rx len in power of 2 */
-
-#define AMPDU_DELIMITER_LEN	4	/* length of ampdu delimiter */
-#define AMPDU_DELIMITER_LEN_MAX	63	/* max length of ampdu delimiter(enforced in HW) */
-
-#define HT_CAP_EXT_PCO			0x0001
-#define HT_CAP_EXT_PCO_TTIME_MASK	0x0006
-#define HT_CAP_EXT_PCO_TTIME_SHIFT	1
-#define HT_CAP_EXT_MCS_FEEDBACK_MASK	0x0300
-#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT	8
-#define HT_CAP_EXT_HTC			0x0400
-#define HT_CAP_EXT_RD_RESP		0x0800
-
-/** 'ht_add' is called 'HT Operation' information element in the 802.11 standard */
-BWL_PRE_PACKED_STRUCT struct ht_add_ie {
-	uint8	ctl_ch;			/* control channel number */
-	uint8	byte1;			/* ext ch,rec. ch. width, RIFS support */
-	uint16	opmode;			/* operation mode */
-	uint16	misc_bits;		/* misc bits */
-	uint8	basic_mcs[MCSSET_LEN];  /* required MCS set */
-} BWL_POST_PACKED_STRUCT;
-typedef struct ht_add_ie ht_add_ie_t;
-
-/* ADD IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
-/* the additional IE is primarily used to convey the current BSS configuration */
-BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie {
-	uint8	id;		/* IE ID, 221, DOT11_MNG_PROPR_ID */
-	uint8	len;		/* IE length */
-	uint8	oui[3];
-	uint8	type;		/* indicates what follows */
-	ht_add_ie_t add_ie;
-} BWL_POST_PACKED_STRUCT;
-typedef struct ht_prop_add_ie ht_prop_add_ie_t;
-
-#define HT_ADD_IE_LEN	22
-#define HT_ADD_IE_TYPE	52
-
-/* byte1 defn's */
-#define HT_BW_ANY		0x04	/* set, STA can use 20 or 40MHz */
-#define HT_RIFS_PERMITTED     	0x08	/* RIFS allowed */
-
-/* opmode defn's */
-#define HT_OPMODE_MASK	        0x0003	/* protection mode mask */
-#define HT_OPMODE_SHIFT		0	/* protection mode shift */
-#define HT_OPMODE_PURE		0x0000	/* protection mode PURE */
-#define HT_OPMODE_OPTIONAL	0x0001	/* protection mode optional */
-#define HT_OPMODE_HT20IN40	0x0002	/* protection mode 20MHz HT in 40MHz BSS */
-#define HT_OPMODE_MIXED	0x0003	/* protection mode Mixed Mode */
-#define HT_OPMODE_NONGF	0x0004	/* protection mode non-GF */
-#define DOT11N_TXBURST		0x0008	/* Tx burst limit */
-#define DOT11N_OBSS_NONHT	0x0010	/* OBSS Non-HT STA present */
-
-/* misc_bites defn's */
-#define HT_BASIC_STBC_MCS	0x007f	/* basic STBC MCS */
-#define HT_DUAL_STBC_PROT	0x0080	/* Dual STBC Protection */
-#define HT_SECOND_BCN		0x0100	/* Secondary beacon support */
-#define HT_LSIG_TXOP		0x0200	/* L-SIG TXOP Protection full support */
-#define HT_PCO_ACTIVE		0x0400	/* PCO active */
-#define HT_PCO_PHASE		0x0800	/* PCO phase */
-#define HT_DUALCTS_PROTECTION	0x0080	/* DUAL CTS protection needed */
-
-/* Tx Burst Limits */
-#define DOT11N_2G_TXBURST_LIMIT	6160	/* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */
-#define DOT11N_5G_TXBURST_LIMIT	3080	/* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */
-
-/* Macros for opmode */
-#define GET_HT_OPMODE(add_ie)		((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
-					>> HT_OPMODE_SHIFT)
-#define HT_MIXEDMODE_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
-					== HT_OPMODE_MIXED)	/* mixed mode present */
-#define HT_HT20_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
-					== HT_OPMODE_HT20IN40)	/* 20MHz HT present */
-#define HT_OPTIONAL_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
-					== HT_OPMODE_OPTIONAL)	/* Optional protection present */
-#define HT_USE_PROTECTION(add_ie)	(HT_HT20_PRESENT((add_ie)) || \
-					HT_MIXEDMODE_PRESENT((add_ie))) /* use protection */
-#define HT_NONGF_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \
-					== HT_OPMODE_NONGF)	/* non-GF present */
-#define DOT11N_TXBURST_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \
-					== DOT11N_TXBURST)	/* Tx Burst present */
-#define DOT11N_OBSS_NONHT_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \
-					== DOT11N_OBSS_NONHT)	/* OBSS Non-HT present */
-
-BWL_PRE_PACKED_STRUCT struct obss_params {
-	uint16	passive_dwell;
-	uint16	active_dwell;
-	uint16	bss_widthscan_interval;
-	uint16	passive_total;
-	uint16	active_total;
-	uint16	chanwidth_transition_dly;
-	uint16	activity_threshold;
-} BWL_POST_PACKED_STRUCT;
-typedef struct obss_params obss_params_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_obss_ie {
-	uint8	id;
-	uint8	len;
-	obss_params_t obss_params;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_obss_ie dot11_obss_ie_t;
-#define DOT11_OBSS_SCAN_IE_LEN	sizeof(obss_params_t)	/* HT OBSS len (based on 802.11n d3.0) */
-
-/* HT control field */
-#define HT_CTRL_LA_TRQ		0x00000002	/* sounding request */
-#define HT_CTRL_LA_MAI		0x0000003C	/* MCS request or antenna selection indication */
-#define HT_CTRL_LA_MAI_SHIFT	2
-#define HT_CTRL_LA_MAI_MRQ	0x00000004	/* MCS request */
-#define HT_CTRL_LA_MAI_MSI	0x00000038	/* MCS request sequence identifier */
-#define HT_CTRL_LA_MFSI		0x000001C0	/* MFB sequence identifier */
-#define HT_CTRL_LA_MFSI_SHIFT	6
-#define HT_CTRL_LA_MFB_ASELC	0x0000FE00	/* MCS feedback, antenna selection command/data */
-#define HT_CTRL_LA_MFB_ASELC_SH	9
-#define HT_CTRL_LA_ASELC_CMD	0x00000C00	/* ASEL command */
-#define HT_CTRL_LA_ASELC_DATA	0x0000F000	/* ASEL data */
-#define HT_CTRL_CAL_POS		0x00030000	/* Calibration position */
-#define HT_CTRL_CAL_SEQ		0x000C0000	/* Calibration sequence */
-#define HT_CTRL_CSI_STEERING	0x00C00000	/* CSI/Steering */
-#define HT_CTRL_CSI_STEER_SHIFT	22
-#define HT_CTRL_CSI_STEER_NFB	0		/* no fedback required */
-#define HT_CTRL_CSI_STEER_CSI	1		/* CSI, H matrix */
-#define HT_CTRL_CSI_STEER_NCOM	2		/* non-compressed beamforming */
-#define HT_CTRL_CSI_STEER_COM	3		/* compressed beamforming */
-#define HT_CTRL_NDP_ANNOUNCE	0x01000000	/* NDP announcement */
-#define HT_CTRL_AC_CONSTRAINT	0x40000000	/* AC Constraint */
-#define HT_CTRL_RDG_MOREPPDU	0x80000000	/* RDG/More PPDU */
-
-/* ************* VHT definitions. ************* */
-
-/**
- * VHT Capabilites IE (sec 8.4.2.160)
- */
-
-BWL_PRE_PACKED_STRUCT struct vht_cap_ie {
-	uint32  vht_cap_info;
-	/* supported MCS set - 64 bit field */
-	uint16	rx_mcs_map;
-	uint16  rx_max_rate;
-	uint16  tx_mcs_map;
-	uint16	tx_max_rate;
-} BWL_POST_PACKED_STRUCT;
-typedef struct vht_cap_ie vht_cap_ie_t;
-
-/* 4B cap_info + 8B supp_mcs */
-#define VHT_CAP_IE_LEN 12
-
-/* VHT Capabilities Info field - 32bit - in VHT Cap IE */
-#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK          0x00000003
-#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK       0x0000000c
-#define VHT_CAP_INFO_LDPC                       0x00000010
-#define VHT_CAP_INFO_SGI_80MHZ                  0x00000020
-#define VHT_CAP_INFO_SGI_160MHZ                 0x00000040
-#define VHT_CAP_INFO_TX_STBC                    0x00000080
-#define VHT_CAP_INFO_RX_STBC_MASK               0x00000700
-#define VHT_CAP_INFO_RX_STBC_SHIFT              8
-#define VHT_CAP_INFO_SU_BEAMFMR                 0x00000800
-#define VHT_CAP_INFO_SU_BEAMFMEE                0x00001000
-#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK         0x0000e000
-#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT        13
-#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK      0x00070000
-#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT     16
-#define VHT_CAP_INFO_MU_BEAMFMR                 0x00080000
-#define VHT_CAP_INFO_MU_BEAMFMEE                0x00100000
-#define VHT_CAP_INFO_TXOPPS                     0x00200000
-#define VHT_CAP_INFO_HTCVHT                     0x00400000
-#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK      0x03800000
-#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT     23
-#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK        0x0c000000
-#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT       26
-
-/* VHT Supported MCS Set - 64-bit - in VHT Cap IE */
-#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK   0x1fff
-#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT  0
-
-#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK   0x1fff
-#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT  0
-
-#define VHT_CAP_MCS_MAP_0_7                     0
-#define VHT_CAP_MCS_MAP_0_8                     1
-#define VHT_CAP_MCS_MAP_0_9                     2
-#define VHT_CAP_MCS_MAP_NONE                    3
-#define VHT_CAP_MCS_MAP_S                       2 /* num bits for 1-stream */
-#define VHT_CAP_MCS_MAP_M                       0x3 /* mask for 1-stream */
-/* assumes VHT_CAP_MCS_MAP_NONE is 3 and 2 bits are used for encoding */
-#define VHT_CAP_MCS_MAP_NONE_ALL                0xffff
-
-/* VHT rates bitmap */
-#define VHT_CAP_MCS_0_7_RATEMAP		0x00ff
-#define VHT_CAP_MCS_0_8_RATEMAP		0x01ff
-#define VHT_CAP_MCS_0_9_RATEMAP		0x03ff
-#define VHT_CAP_MCS_FULL_RATEMAP 	VHT_CAP_MCS_0_9_RATEMAP
-
-#define VHT_PROP_MCS_MAP_10_11                   0
-#define VHT_PROP_MCS_MAP_UNUSED1                 1
-#define VHT_PROP_MCS_MAP_UNUSED2                 2
-#define VHT_PROP_MCS_MAP_NONE                    3
-#define VHT_PROP_MCS_MAP_NONE_ALL                0xffff
-
-/* VHT prop rates bitmap */
-#define VHT_PROP_MCS_10_11_RATEMAP	0x0c00
-#define VHT_PROP_MCS_FULL_RATEMAP	VHT_PROP_MCS_10_11_RATEMAP
-
-#if !defined(VHT_CAP_MCS_MAP_0_9_NSS3)
-/* mcsmap with MCS0-9 for Nss = 3 */
-#define VHT_CAP_MCS_MAP_0_9_NSS3 \
-	        ((VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(1)) | \
-	         (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(2)) | \
-	         (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(3)))
-#endif /* !VHT_CAP_MCS_MAP_0_9_NSS3 */
-
-#define VHT_CAP_MCS_MAP_NSS_MAX                 8
-
-/* get mcsmap with given mcs for given nss streams */
-#define VHT_CAP_MCS_MAP_CREATE(mcsmap, nss, mcs) \
-	do { \
-		int i; \
-		for (i = 1; i <= nss; i++) { \
-			VHT_MCS_MAP_SET_MCS_PER_SS(i, mcs, mcsmap); \
-		} \
-	} while (0)
-
-/* Map the mcs code to mcs bit map */
-#define VHT_MCS_CODE_TO_MCS_MAP(mcs_code) \
-	((mcs_code == VHT_CAP_MCS_MAP_0_7) ? VHT_CAP_MCS_0_7_RATEMAP : \
-	 (mcs_code == VHT_CAP_MCS_MAP_0_8) ? VHT_CAP_MCS_0_8_RATEMAP : \
-	 (mcs_code == VHT_CAP_MCS_MAP_0_9) ? VHT_CAP_MCS_0_9_RATEMAP : 0)
-
-#define VHT_PROP_MCS_CODE_TO_PROP_MCS_MAP(mcs_code) \
-	((mcs_code == VHT_PROP_MCS_MAP_10_11) ? VHT_PROP_MCS_10_11_RATEMAP : 0)
-
-/* Map the mcs bit map to mcs code */
-#define VHT_MCS_MAP_TO_MCS_CODE(mcs_map) \
-	((mcs_map == VHT_CAP_MCS_0_7_RATEMAP) ? VHT_CAP_MCS_MAP_0_7 : \
-	 (mcs_map == VHT_CAP_MCS_0_8_RATEMAP) ? VHT_CAP_MCS_MAP_0_8 : \
-	 (mcs_map == VHT_CAP_MCS_0_9_RATEMAP) ? VHT_CAP_MCS_MAP_0_9 : VHT_CAP_MCS_MAP_NONE)
-
-#define VHT_PROP_MCS_MAP_TO_PROP_MCS_CODE(mcs_map) \
-	(((mcs_map & 0xc00) == 0xc00)  ? VHT_PROP_MCS_MAP_10_11 : VHT_PROP_MCS_MAP_NONE)
-
-/** VHT Capabilities Supported Channel Width */
-typedef enum vht_cap_chan_width {
-	VHT_CAP_CHAN_WIDTH_SUPPORT_MANDATORY = 0x00,
-	VHT_CAP_CHAN_WIDTH_SUPPORT_160       = 0x04,
-	VHT_CAP_CHAN_WIDTH_SUPPORT_160_8080  = 0x08
-} vht_cap_chan_width_t;
-
-/** VHT Capabilities Supported max MPDU LEN (sec 8.4.2.160.2) */
-typedef enum vht_cap_max_mpdu_len {
-	VHT_CAP_MPDU_MAX_4K     = 0x00,
-	VHT_CAP_MPDU_MAX_8K     = 0x01,
-	VHT_CAP_MPDU_MAX_11K    = 0x02
-} vht_cap_max_mpdu_len_t;
-
-/* Maximum MPDU Length byte counts for the VHT Capabilities advertised limits */
-#define VHT_MPDU_LIMIT_4K        3895
-#define VHT_MPDU_LIMIT_8K        7991
-#define VHT_MPDU_LIMIT_11K      11454
-
-
-/**
- * VHT Operation IE (sec 8.4.2.161)
- */
-
-BWL_PRE_PACKED_STRUCT struct vht_op_ie {
-	uint8	chan_width;
-	uint8	chan1;
-	uint8	chan2;
-	uint16	supp_mcs;  /*  same def as above in vht cap */
-} BWL_POST_PACKED_STRUCT;
-typedef struct vht_op_ie vht_op_ie_t;
-
-/* 3B VHT Op info + 2B Basic MCS */
-#define VHT_OP_IE_LEN 5
-
-typedef enum vht_op_chan_width {
-	VHT_OP_CHAN_WIDTH_20_40	= 0,
-	VHT_OP_CHAN_WIDTH_80	= 1,
-	VHT_OP_CHAN_WIDTH_160	= 2,
-	VHT_OP_CHAN_WIDTH_80_80	= 3
-} vht_op_chan_width_t;
-
-/* AID length */
-#define AID_IE_LEN		2
-/**
- * BRCM vht features IE header
- * The header if the fixed part of the IE
- * On the 5GHz band this is the entire IE,
- * on 2.4GHz the VHT IEs as defined in the 802.11ac
- * specification follows
- *
- *
- * VHT features rates  bitmap.
- * Bit0:		5G MCS 0-9 BW 160MHz
- * Bit1:		5G MCS 0-9 support BW 80MHz
- * Bit2:		5G MCS 0-9 support BW 20MHz
- * Bit3:		2.4G MCS 0-9 support BW 20MHz
- * Bits:4-7	Reserved for future use
- *
- */
-#define VHT_FEATURES_IE_TYPE	0x4
-BWL_PRE_PACKED_STRUCT struct vht_features_ie_hdr {
-	uint8 oui[3];
-	uint8 type;		/* type of this IE = 4 */
-	uint8 rate_mask;	/* VHT rate mask */
-} BWL_POST_PACKED_STRUCT;
-typedef struct vht_features_ie_hdr vht_features_ie_hdr_t;
-
-/* Def for rx & tx basic mcs maps - ea ss num has 2 bits of info */
-#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1) * VHT_CAP_MCS_MAP_S)
-#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \
-	(((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & VHT_CAP_MCS_MAP_M)
-#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \
-	do { \
-	 (mcsMap) &= (~(VHT_CAP_MCS_MAP_M << VHT_MCS_MAP_GET_SS_IDX(nss))); \
-	 (mcsMap) |= (((numMcs) & VHT_CAP_MCS_MAP_M) << VHT_MCS_MAP_GET_SS_IDX(nss)); \
-	} while (0)
-#define VHT_MCS_SS_SUPPORTED(nss, mcsMap) \
-		 (VHT_MCS_MAP_GET_MCS_PER_SS((nss), (mcsMap)) != VHT_CAP_MCS_MAP_NONE)
-
-
-/* ************* WPA definitions. ************* */
-#define WPA_OUI			"\x00\x50\xF2"	/* WPA OUI */
-#define WPA_OUI_LEN		3		/* WPA OUI length */
-#define WPA_OUI_TYPE		1
-#define WPA_VERSION		1		/* WPA version */
-#define WPA2_OUI		"\x00\x0F\xAC"	/* WPA2 OUI */
-#define WPA2_OUI_LEN		3		/* WPA2 OUI length */
-#define WPA2_VERSION		1		/* WPA2 version */
-#define WPA2_VERSION_LEN	2		/* WAP2 version length */
-
-/* ************* WPS definitions. ************* */
-#define WPS_OUI			"\x00\x50\xF2"	/* WPS OUI */
-#define WPS_OUI_LEN		3		/* WPS OUI length */
-#define WPS_OUI_TYPE		4
-
-/* ************* WFA definitions. ************* */
-
-#ifdef P2P_IE_OVRD
-#define WFA_OUI			MAC_OUI
-#else
-#define WFA_OUI			"\x50\x6F\x9A"	/* WFA OUI */
-#endif /* P2P_IE_OVRD */
-#define WFA_OUI_LEN		3		/* WFA OUI length */
-#ifdef P2P_IE_OVRD
-#define WFA_OUI_TYPE_P2P	MAC_OUI_TYPE_P2P
-#else
-#define WFA_OUI_TYPE_TPC	8
-#define WFA_OUI_TYPE_P2P	9
-#endif
-
-#define WFA_OUI_TYPE_TPC	8
-#ifdef WLTDLS
-#define WFA_OUI_TYPE_TPQ	4	/* WFD Tunneled Probe ReQuest */
-#define WFA_OUI_TYPE_TPS	5	/* WFD Tunneled Probe ReSponse */
-#define WFA_OUI_TYPE_WFD	10
-#endif /* WTDLS */
-#define WFA_OUI_TYPE_HS20	0x10
-#define WFA_OUI_TYPE_OSEN	0x12
-#define WFA_OUI_TYPE_NAN	0x13
-
-/* RSN authenticated key managment suite */
-#define RSN_AKM_NONE		0	/* None (IBSS) */
-#define RSN_AKM_UNSPECIFIED	1	/* Over 802.1x */
-#define RSN_AKM_PSK		2	/* Pre-shared Key */
-#define RSN_AKM_FBT_1X		3	/* Fast Bss transition using 802.1X */
-#define RSN_AKM_FBT_PSK		4	/* Fast Bss transition using Pre-shared Key */
-/* RSN_AKM_MFP_1X and RSN_AKM_MFP_PSK are not used any more
- * Just kept here to avoid build issue in BISON/CARIBOU branch
- */
-#define RSN_AKM_MFP_1X		5	/* SHA256 key derivation, using 802.1X */
-#define RSN_AKM_MFP_PSK		6	/* SHA256 key derivation, using Pre-shared Key */
-#define RSN_AKM_SHA256_1X	5	/* SHA256 key derivation, using 802.1X */
-#define RSN_AKM_SHA256_PSK	6	/* SHA256 key derivation, using Pre-shared Key */
-#define RSN_AKM_TPK		7	/* TPK(TDLS Peer Key) handshake */
-
-/* OSEN authenticated key managment suite */
-#define OSEN_AKM_UNSPECIFIED	RSN_AKM_UNSPECIFIED	/* Over 802.1x */
-
-/* Key related defines */
-#define DOT11_MAX_DEFAULT_KEYS	4	/* number of default keys */
-#define DOT11_MAX_IGTK_KEYS		2
-#define DOT11_MAX_KEY_SIZE	32	/* max size of any key */
-#define DOT11_MAX_IV_SIZE	16	/* max size of any IV */
-#define DOT11_EXT_IV_FLAG	(1<<5)	/* flag to indicate IV is > 4 bytes */
-#define DOT11_WPA_KEY_RSC_LEN   8       /* WPA RSC key len */
-
-#define WEP1_KEY_SIZE		5	/* max size of any WEP key */
-#define WEP1_KEY_HEX_SIZE	10	/* size of WEP key in hex. */
-#define WEP128_KEY_SIZE		13	/* max size of any WEP key */
-#define WEP128_KEY_HEX_SIZE	26	/* size of WEP key in hex. */
-#define TKIP_MIC_SIZE		8	/* size of TKIP MIC */
-#define TKIP_EOM_SIZE		7	/* max size of TKIP EOM */
-#define TKIP_EOM_FLAG		0x5a	/* TKIP EOM flag byte */
-#define TKIP_KEY_SIZE		32	/* size of any TKIP key, includs MIC keys */
-#define TKIP_TK_SIZE		16
-#define TKIP_MIC_KEY_SIZE	8
-#define TKIP_MIC_AUTH_TX	16	/* offset to Authenticator MIC TX key */
-#define TKIP_MIC_AUTH_RX	24	/* offset to Authenticator MIC RX key */
-#define TKIP_MIC_SUP_RX		TKIP_MIC_AUTH_TX	/* offset to Supplicant MIC RX key */
-#define TKIP_MIC_SUP_TX		TKIP_MIC_AUTH_RX	/* offset to Supplicant MIC TX key */
-#define AES_KEY_SIZE		16	/* size of AES key */
-#define AES_MIC_SIZE		8	/* size of AES MIC */
-#define BIP_KEY_SIZE		16	/* size of BIP key */
-#define BIP_MIC_SIZE		8   /* sizeof BIP MIC */
-
-#define AES_GCM_MIC_SIZE	16	/* size of MIC for 128-bit GCM - .11adD9 */
-
-#define AES256_KEY_SIZE		32	/* size of AES 256 key - .11acD5 */
-#define AES256_MIC_SIZE		16	/* size of MIC for 256 bit keys, incl BIP */
-
-/* WCN */
-#define WCN_OUI			"\x00\x50\xf2"	/* WCN OUI */
-#define WCN_TYPE		4	/* WCN type */
-
-
-/* 802.11r protocol definitions */
-
-/** Mobility Domain IE */
-BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie {
-	uint8 id;
-	uint8 len;
-	uint16 mdid;		/* Mobility Domain Id */
-	uint8 cap;
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_mdid_ie dot11_mdid_ie_t;
-
-#define FBT_MDID_CAP_OVERDS	0x01	/* Fast Bss transition over the DS support */
-#define FBT_MDID_CAP_RRP	0x02	/* Resource request protocol support */
-
-/** Fast Bss Transition IE */
-BWL_PRE_PACKED_STRUCT struct dot11_ft_ie {
-	uint8 id;
-	uint8 len;
-	uint16 mic_control;		/* Mic Control */
-	uint8 mic[16];
-	uint8 anonce[32];
-	uint8 snonce[32];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ft_ie dot11_ft_ie_t;
-
-#define TIE_TYPE_RESERVED		0
-#define TIE_TYPE_REASSOC_DEADLINE	1
-#define TIE_TYPE_KEY_LIEFTIME		2
-#define TIE_TYPE_ASSOC_COMEBACK		3
-BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie {
-	uint8 id;
-	uint8 len;
-	uint8 type;		/* timeout interval type */
-	uint32 value;		/* timeout interval value */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_timeout_ie dot11_timeout_ie_t;
-
-/** GTK ie */
-BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie {
-	uint8 id;
-	uint8 len;
-	uint16 key_info;
-	uint8 key_len;
-	uint8 rsc[8];
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_gtk_ie dot11_gtk_ie_t;
-
-/** Management MIC ie */
-BWL_PRE_PACKED_STRUCT struct mmic_ie {
-	uint8   id;					/* IE ID: DOT11_MNG_MMIE_ID */
-	uint8   len;				/* IE length */
-	uint16  key_id;				/* key id */
-	uint8   ipn[6];				/* ipn */
-	uint8   mic[16];			/* mic */
-} BWL_POST_PACKED_STRUCT;
-typedef struct mmic_ie mmic_ie_t;
-
-/* 802.11r-2008, 11A.10.3 - RRB frame format */
-BWL_PRE_PACKED_STRUCT struct dot11_ft_rrb_frame {
-	uint8  frame_type; /* 1 for RRB */
-	uint8  packet_type; /* 0 for Request 1 for Response */
-	uint16 len;
-	uint8  cur_ap_addr[ETHER_ADDR_LEN];
-	uint8  data[1];	/* IEs Received/Sent in FT Action Req/Resp Frame */
-} BWL_POST_PACKED_STRUCT;
-
-typedef struct dot11_ft_rrb_frame dot11_ft_rrb_frame_t;
-
-#define DOT11_FT_RRB_FIXED_LEN 10
-#define DOT11_FT_REMOTE_FRAME_TYPE 1
-#define DOT11_FT_PACKET_REQ 0
-#define DOT11_FT_PACKET_RESP 1
-
-#define BSSID_INVALID           "\x00\x00\x00\x00\x00\x00"
-#define BSSID_BROADCAST         "\xFF\xFF\xFF\xFF\xFF\xFF"
-
-
-/* ************* WMM Parameter definitions. ************* */
-#define WMM_OUI			"\x00\x50\xF2"	/* WNN OUI */
-#define WMM_OUI_LEN		3		/* WMM OUI length */
-#define WMM_OUI_TYPE	2		/* WMM OUT type */
-#define WMM_VERSION		1
-#define WMM_VERSION_LEN	1
-
-/* WMM OUI subtype */
-#define WMM_OUI_SUBTYPE_PARAMETER	1
-#define WMM_PARAMETER_IE_LEN		24
-
-/** Link Identifier Element */
-BWL_PRE_PACKED_STRUCT struct link_id_ie {
-	uint8 id;
-	uint8 len;
-	struct ether_addr	bssid;
-	struct ether_addr	tdls_init_mac;
-	struct ether_addr	tdls_resp_mac;
-} BWL_POST_PACKED_STRUCT;
-typedef struct link_id_ie link_id_ie_t;
-#define TDLS_LINK_ID_IE_LEN		18
-
-/** Link Wakeup Schedule Element */
-BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie {
-	uint8 id;
-	uint8 len;
-	uint32 offset;			/* in ms between TSF0 and start of 1st Awake Window */
-	uint32 interval;		/* in ms bwtween the start of 2 Awake Windows */
-	uint32 awake_win_slots;	/* in backof slots, duration of Awake Window */
-	uint32 max_wake_win;	/* in ms, max duration of Awake Window */
-	uint16 idle_cnt;		/* number of consecutive Awake Windows */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wakeup_sch_ie wakeup_sch_ie_t;
-#define TDLS_WAKEUP_SCH_IE_LEN		18
-
-/** Channel Switch Timing Element */
-BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie {
-	uint8 id;
-	uint8 len;
-	uint16 switch_time;		/* in ms, time to switch channels */
-	uint16 switch_timeout;	/* in ms */
-} BWL_POST_PACKED_STRUCT;
-typedef struct channel_switch_timing_ie channel_switch_timing_ie_t;
-#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN		4
-
-/** PTI Control Element */
-BWL_PRE_PACKED_STRUCT struct pti_control_ie {
-	uint8 id;
-	uint8 len;
-	uint8 tid;
-	uint16 seq_control;
-} BWL_POST_PACKED_STRUCT;
-typedef struct pti_control_ie pti_control_ie_t;
-#define TDLS_PTI_CONTROL_IE_LEN		3
-
-/** PU Buffer Status Element */
-BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie {
-	uint8 id;
-	uint8 len;
-	uint8 status;
-} BWL_POST_PACKED_STRUCT;
-typedef struct pu_buffer_status_ie pu_buffer_status_ie_t;
-#define TDLS_PU_BUFFER_STATUS_IE_LEN	1
-#define TDLS_PU_BUFFER_STATUS_AC_BK		1
-#define TDLS_PU_BUFFER_STATUS_AC_BE		2
-#define TDLS_PU_BUFFER_STATUS_AC_VI		4
-#define TDLS_PU_BUFFER_STATUS_AC_VO		8
-
-/* TDLS Action Field Values */
-#define TDLS_SETUP_REQ				0
-#define TDLS_SETUP_RESP				1
-#define TDLS_SETUP_CONFIRM			2
-#define TDLS_TEARDOWN				3
-#define TDLS_PEER_TRAFFIC_IND			4
-#define TDLS_CHANNEL_SWITCH_REQ			5
-#define TDLS_CHANNEL_SWITCH_RESP		6
-#define TDLS_PEER_PSM_REQ			7
-#define TDLS_PEER_PSM_RESP			8
-#define TDLS_PEER_TRAFFIC_RESP			9
-#define TDLS_DISCOVERY_REQ			10
-
-/* 802.11z TDLS Public Action Frame action field */
-#define TDLS_DISCOVERY_RESP			14
-
-/* 802.11u GAS action frames */
-#define GAS_REQUEST_ACTION_FRAME				10
-#define GAS_RESPONSE_ACTION_FRAME				11
-#define GAS_COMEBACK_REQUEST_ACTION_FRAME		12
-#define GAS_COMEBACK_RESPONSE_ACTION_FRAME		13
-
-/* FTM - fine timing measurement public action frames */
-BWL_PRE_PACKED_STRUCT struct dot11_ftm_req {
-	uint8 category;				/* category of action frame (4) */
-	uint8 action;				/* public action (32) */
-	uint8 trigger;				/* trigger/continue? */
-	/* optional lci, civic loc, ftm params */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ftm_req dot11_ftm_req_t;
-
-BWL_PRE_PACKED_STRUCT struct dot11_ftm {
-	uint8 category;				/* category of action frame (4) */
-	uint8 action;				/* public action (33) */
-	uint8 dialog;				/* dialog token */
-	uint8 follow_up;			/* follow up dialog token */
-	uint8 tod[6];				/* t1 - last depart timestamp */
-	uint8 toa[6];				/* t4 - last ack arrival timestamp */
-	uint8 tod_err[2];			/* t1 error */
-	uint8 toa_err[2];			/* t4 error */
-	/* optional lci report, civic loc report, ftm params */
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ftm dot11_ftm_t;
-
-#define DOT11_FTM_ERR_NOT_CONT_OFFSET 0
-#define DOT11_FTM_ERR_NOT_CONT_MASK 0x0001
-#define DOT11_FTM_ERR_NOT_CONT_SHIFT 0
-#define DOT11_FTM_ERR_NOT_CONT(_err) (((_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET] & \
-	DOT11_FTM_ERR_NOT_CONT_MASK) >> DOT11_FTM_ERR_NOT_CONT_SHIFT)
-#define DOT11_FTM_ERR_SET_NOT_CONT(_err, _val) do {\
-	uint8 _err2 = (_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET]; \
-	_err2 &= ~DOT11_FTM_ERR_NOT_CONT_MASK; \
-	_err2 |= ((_val) << DOT11_FTM_ERR_NOT_CONT_SHIFT) & DOT11_FTM_ERR_NOT_CONT_MASK; \
-	(_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET] = _err2; \
-} while (0)
-
-#define DOT11_FTM_ERR_MAX_ERR_OFFSET 0
-#define DOT11_FTM_ERR_MAX_ERR_MASK 0xfff7
-#define DOT11_FTM_ERR_MAX_ERR_SHIFT 1
-#define DOT11_FTM_ERR_MAX_ERR(_err) ((((_err)[1] << 7) | (_err)[0]) >> 1)
-#define DOT11_FTM_ERR_SET_MAX_ERR(_err, _val) do {\
-	uint16 _val2; \
-	_val2 =  (((_val) << DOT11_FTM_ERR_MAX_ERR_SHIFT) |\
-		 ((_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET] & DOT11_FTM_ERR_NOT_CONT_MASK)); \
-	(_err)[0] = _val2 & 0xff; \
-	(_err)[1] = _val2 >> 8 & 0xff; \
-} while (0)
-
-BWL_PRE_PACKED_STRUCT struct dot11_ftm_params {
-	uint8 id;		/* DOT11_MNG_FTM_PARAM_ID 8.4.2.166 11mcd2.6/2014 - revisit */
-	uint8 len;
-	uint8 info[9];
-} BWL_POST_PACKED_STRUCT;
-typedef struct dot11_ftm_params dot11_ftm_params_t;
-#define DOT11_FTM_PARAMS_IE_LEN (sizeof(dot11_ftm_params_t) - 2)
-
-#define FTM_PARAMS_FIELD(_p, _off, _mask, _shift) (((_p)->info[(_off)] & (_mask)) >> (_shift))
-#define FTM_PARAMS_SET_FIELD(_p, _off, _mask, _shift, _val) do {\
-	uint8 _ptmp = (_p)->info[_off] & ~(_mask); \
-	(_p)->info[(_off)] = _ptmp | (((_val) << (_shift)) & (_mask)); \
-} while (0)
-
-#define FTM_PARAMS_STATUS_OFFSET 0
-#define FTM_PARAMS_STATUS_MASK 0x03
-#define FTM_PARAMS_STATUS_SHIFT 0
-#define FTM_PARAMS_STATUS(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_STATUS_OFFSET, \
-	FTM_PARAMS_STATUS_MASK, FTM_PARAMS_STATUS_SHIFT)
-#define FTM_PARAMS_SET_STATUS(_p, _status) FTM_PARAMS_SET_FIELD(_p, \
-	FTM_PARAMS_STATUS_OFFSET, FTM_PARAMS_STATUS_MASK, FTM_PARAMS_STATUS_SHIFT, _status)
-
-#define FTM_PARAMS_VALUE_OFFSET 0
-#define FTM_PARAMS_VALUE_MASK 0x7c
-#define FTM_PARAMS_VALUE_SHIFT 2
-#define FTM_PARAMS_VALUE(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_VALUE_OFFSET, \
-	FTM_PARAMS_VALUE_MASK, FTM_PARAMS_VALUE_SHIFT)
-#define FTM_PARAMS_SET_VALUE(_p, _value) FTM_PARAMS_SET_FIELD(_p, \
-	FTM_PARAMS_VALUE_OFFSET, FTM_PARAMS_VALUE_MASK, FTM_PARAMS_VALUE_SHIFT, _value)
-#define FTM_PARAMS_MAX_VALUE 32
-
-#define FTM_PARAMS_NBURSTEXP_OFFSET 1
-#define FTM_PARAMS_NBURSTEXP_MASK 0x0f
-#define FTM_PARAMS_NBURSTEXP_SHIFT 0
-#define FTM_PARAMS_NBURSTEXP(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_NBURSTEXP_OFFSET, \
-	FTM_PARAMS_NBURSTEXP_MASK, FTM_PARAMS_NBURSTEXP_SHIFT)
-#define FTM_PARAMS_SET_NBURSTEXP(_p, _bexp) FTM_PARAMS_SET_FIELD(_p, \
-	FTM_PARAMS_NBURSTEXP_OFFSET, FTM_PARAMS_NBURSTEXP_MASK, FTM_PARAMS_NBURSTEXP_SHIFT, \
-	_bexp)
-
-#define FTM_PARAMS_NBURST(_p) (1 << FTM_PARAMS_NBURSTEXP(_p))
-
-enum {
-	FTM_PARAMS_BURSTTMO_NOPREF = 15
-};
-
-#define FTM_PARAMS_BURSTTMO_OFFSET 1
-#define FTM_PARAMS_BURSTTMO_MASK 0xf0
-#define FTM_PARAMS_BURSTTMO_SHIFT 4
-#define FTM_PARAMS_BURSTTMO(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_BURSTTMO_OFFSET, \
-	FTM_PARAMS_BURSTTMO_MASK, FTM_PARAMS_BURSTTMO_SHIFT)
-/* set timeout in params using _tmo where timeout = 2^(_tmo) * 250us */
-#define FTM_PARAMS_SET_BURSTTMO(_p, _tmo) FTM_PARAMS_SET_FIELD(_p, \
-	FTM_PARAMS_BURSTTMO_OFFSET, FTM_PARAMS_BURSTTMO_MASK, FTM_PARAMS_BURSTTMO_SHIFT, (_tmo)+2)
-
-#define FTM_PARAMS_BURSTTMO_USEC(_val) ((1 << ((_val)-2)) * 250)
-#define FTM_PARAMS_BURSTTMO_VALID(_val) ((((_val) < 12 && (_val) > 1)) || \
-	(_val) == FTM_PARAMS_BURSTTMO_NOPREF)
-#define FTM_PARAMS_BURSTTMO_MAX_MSEC 128 /* 2^9 * 250us */
-#define FTM_PARAMS_BURSTTMO_MAX_USEC 128000 /* 2^9 * 250us */
-
-#define FTM_PARAMS_MINDELTA_OFFSET 2
-#define FTM_PARAMS_MINDELTA_USEC(_p) ((_p)->info[FTM_PARAMS_MINDELTA_OFFSET] * 100)
-#define FTM_PARAMS_SET_MINDELTA_USEC(_p, _delta) do { \
-	(_p)->info[FTM_PARAMS_MINDELTA_OFFSET] = (_delta) / 100; \
-} while (0)
-
-#define FTM_PARAMS_PARTIAL_TSF(_p) ((_p)->info[4] << 8 | (_p)->info[3])
-#define FTM_PARAMS_SET_PARTIAL_TSF(_p, _partial_tsf) do { \
-	(_p)->info[3] = (_partial_tsf) & 0xff; \
-	(_p)->info[4] = ((_partial_tsf) >> 8) & 0xff; \
-} while (0)
-
-#define FTM_PARAMS_PARTIAL_TSF_MASK 0x0000000003fffc00ULL
-#define FTM_PARAMS_PARTIAL_TSF_SHIFT 10
-#define FTM_PARAMS_PARTIAL_TSF_BIT_LEN 16
-#define FTM_PARAMS_PARTIAL_TSF_MAX 0xffff
-
-#define FTM_PARAMS_ASAP_OFFSET 5
-#define FTM_PARAMS_ASAP_MASK 0x4
-#define FTM_PARAMS_ASAP_SHIFT 2
-#define FTM_PARAMS_ASAP(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_ASAP_OFFSET, \
-	FTM_PARAMS_ASAP_MASK, FTM_PARAMS_ASAP_SHIFT)
-#define FTM_PARAMS_SET_ASAP(_p, _asap) FTM_PARAMS_SET_FIELD(_p, \
-	FTM_PARAMS_ASAP_OFFSET, FTM_PARAMS_ASAP_MASK, FTM_PARAMS_ASAP_SHIFT, _asap)
-
-#define FTM_PARAMS_FTM1_OFFSET 5
-#define FTM_PARAMS_FTM1_MASK 0x02
-#define FTM_PARAMS_FTM1_SHIFT 1
-#define FTM_PARAMS_FTM1(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_FTM1_OFFSET, \
-	FTM_PARAMS_FTM1_MASK, FTM_PARAMS_FTM1_SHIFT)
-#define FTM_PARAMS_SET_FTM1(_p, _ftm1) FTM_PARAMS_SET_FIELD(_p, \
-	FTM_PARAMS_FTM1_OFFSET, FTM_PARAMS_FTM1_MASK, FTM_PARAMS_FTM1_SHIFT, _ftm1)
-
-#define FTM_PARAMS_FTMS_PER_BURST_OFFSET 5
-#define FTM_PARAMS_FTMS_PER_BURST_MASK 0xf8
-#define FTM_PARAMS_FTMS_PER_BURST_SHIFT 3
-#define FTM_PARAMS_FTMS_PER_BURST(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_FTMS_PER_BURST_OFFSET, \
-	FTM_PARAMS_FTMS_PER_BURST_MASK, FTM_PARAMS_FTMS_PER_BURST_SHIFT)
-#define FTM_PARAMS_SET_FTMS_PER_BURST(_p, _nftms) FTM_PARAMS_SET_FIELD(_p, \
-	FTM_PARAMS_FTMS_PER_BURST_OFFSET, FTM_PARAMS_FTMS_PER_BURST_MASK, \
-	FTM_PARAMS_FTMS_PER_BURST_SHIFT, _nftms)
-
-#define FTM_PARAMS_CHAN_INFO_OFFSET 6
-#define FTM_PARAMS_CHAN_INFO_MASK 0xfc
-#define FTM_PARAMS_CHAN_INFO_SHIFT 2
-#define FTM_PARAMS_CHAN_INFO(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_CHAN_INFO_OFFSET, \
-	FTM_PARAMS_CHAN_INFO_MASK, FTM_PARAMS_CHAN_INFO_SHIFT)
-#define FTM_PARAMS_SET_CHAN_INFO(_p, _ci) FTM_PARAMS_SET_FIELD(_p, \
-	FTM_PARAMS_CHAN_INFO_OFFSET, FTM_PARAMS_CHAN_INFO_MASK, FTM_PARAMS_CHAN_INFO_SHIFT, _ci)
-
-/* burst period - units of 100ms */
-#define FTM_PARAMS_BURST_PERIOD(_p) (((_p)->info[8] << 8) | (_p)->info[7])
-#define FTM_PARAMS_SET_BURST_PERIOD(_p, _bp) do {\
-	(_p)->info[7] = (_bp) & 0xff; \
-	(_p)->info[8] = ((_bp) >> 8) & 0xff; \
-} while (0)
-
-#define FTM_PARAMS_BURST_PERIOD_MS(_p) (FTM_PARAMS_BURST_PERIOD(_p) * 100)
-
-/* FTM status values - last updated from 11mcD4.0 */
-enum {
-	FTM_PARAMS_STATUS_RESERVED	= 0,
-	FTM_PARAMS_STATUS_SUCCESSFUL = 1,
-	FTM_PARAMS_STATUS_INCAPABLE = 2,
-	FTM_PARAMS_STATUS_FAILED = 3,
-	/* Below are obsolte */
-	FTM_PARAMS_STATUS_OVERRIDDEN = 4,
-	FTM_PARAMS_STATUS_ASAP_INCAPABLE = 5,
-	FTM_PARAMS_STATUS_ASAP_FAILED = 6,
-	/* rest are reserved */
-};
-
-enum {
-	FTM_PARAMS_CHAN_INFO_NO_PREF 		= 0,
-	FTM_PARAMS_CHAN_INFO_RESERVE1 		= 1,
-	FTM_PARAMS_CHAN_INFO_RESERVE2 		= 2,
-	FTM_PARAMS_CHAN_INFO_RESERVE3 		= 3,
-	FTM_PARAMS_CHAN_INFO_NON_HT_5 		= 4,
-	FTM_PARAMS_CHAN_INFO_RESERVE5		= 5,
-	FTM_PARAMS_CHAN_INFO_NON_HT_10 		= 6,
-	FTM_PARAMS_CHAN_INFO_RESERVE7		= 7,
-	FTM_PARAMS_CHAN_INFO_NON_HT_20 		= 8, /* excludes 2.4G, and High rate DSSS */
-	FTM_PARAMS_CHAN_INFO_HT_MF_20 		= 9,
-	FTM_PARAMS_CHAN_INFO_VHT_20 		= 10,
-	FTM_PARAMS_CHAN_INFO_HT_MF_40 		= 11,
-	FTM_PARAMS_CHAN_INFO_VHT_40 		= 12,
-	FTM_PARAMS_CHAN_INFO_VHT_80 		= 13,
-	FTM_PARAMS_CHAN_INFO_VHT_80_80 		= 14,
-	FTM_PARAMS_CHAN_INFO_VHT_160_2_RFLOS 	= 15,
-	FTM_PARAMS_CHAN_INFO_VHT_160		= 16,
-	/* Reserved from 17 - 30 */
-	FTM_PARAMS_CHAN_INFO_DMG_2160 		= 31,
-	/* Reserved from 32 - 63 */
-	FTM_PARAMS_CHAN_INFO_MAX		= 63
-};
-
-/* 802.11u interworking access network options */
-#define IW_ANT_MASK					0x0f
-#define IW_INTERNET_MASK				0x10
-#define IW_ASRA_MASK					0x20
-#define IW_ESR_MASK					0x40
-#define IW_UESA_MASK					0x80
-
-/* 802.11u interworking access network type */
-#define IW_ANT_PRIVATE_NETWORK				0
-#define IW_ANT_PRIVATE_NETWORK_WITH_GUEST		1
-#define IW_ANT_CHARGEABLE_PUBLIC_NETWORK		2
-#define IW_ANT_FREE_PUBLIC_NETWORK			3
-#define IW_ANT_PERSONAL_DEVICE_NETWORK			4
-#define IW_ANT_EMERGENCY_SERVICES_NETWORK		5
-#define IW_ANT_TEST_NETWORK				14
-#define IW_ANT_WILDCARD_NETWORK				15
-
-/* 802.11u advertisement protocol */
-#define ADVP_ANQP_PROTOCOL_ID				0
-#define ADVP_MIH_PROTOCOL_ID				1
-
-/* 802.11u advertisement protocol masks */
-#define ADVP_QRL_MASK					0x7f
-#define ADVP_PAME_BI_MASK				0x80
-
-/* 802.11u advertisement protocol values */
-#define ADVP_QRL_REQUEST				0x00
-#define ADVP_QRL_RESPONSE				0x7f
-#define ADVP_PAME_BI_DEPENDENT				0x00
-#define ADVP_PAME_BI_INDEPENDENT			ADVP_PAME_BI_MASK
-
-/* 802.11u ANQP information ID */
-#define ANQP_ID_QUERY_LIST				256
-#define ANQP_ID_CAPABILITY_LIST				257
-#define ANQP_ID_VENUE_NAME_INFO				258
-#define ANQP_ID_EMERGENCY_CALL_NUMBER_INFO		259
-#define ANQP_ID_NETWORK_AUTHENTICATION_TYPE_INFO	260
-#define ANQP_ID_ROAMING_CONSORTIUM_LIST			261
-#define ANQP_ID_IP_ADDRESS_TYPE_AVAILABILITY_INFO	262
-#define ANQP_ID_NAI_REALM_LIST				263
-#define ANQP_ID_G3PP_CELLULAR_NETWORK_INFO		264
-#define ANQP_ID_AP_GEOSPATIAL_LOCATION			265
-#define ANQP_ID_AP_CIVIC_LOCATION			266
-#define ANQP_ID_AP_LOCATION_PUBLIC_ID_URI		267
-#define ANQP_ID_DOMAIN_NAME_LIST			268
-#define ANQP_ID_EMERGENCY_ALERT_ID_URI			269
-#define ANQP_ID_EMERGENCY_NAI				271
-#define ANQP_ID_VENDOR_SPECIFIC_LIST			56797
-
-/* 802.11u ANQP OUI */
-#define ANQP_OUI_SUBTYPE				9
-
-/* 802.11u venue name */
-#define VENUE_LANGUAGE_CODE_SIZE			3
-#define VENUE_NAME_SIZE					255
-
-/* 802.11u venue groups */
-#define VENUE_UNSPECIFIED				0
-#define VENUE_ASSEMBLY					1
-#define VENUE_BUSINESS					2
-#define VENUE_EDUCATIONAL				3
-#define VENUE_FACTORY					4
-#define VENUE_INSTITUTIONAL				5
-#define VENUE_MERCANTILE				6
-#define VENUE_RESIDENTIAL				7
-#define VENUE_STORAGE					8
-#define VENUE_UTILITY					9
-#define VENUE_VEHICULAR					10
-#define VENUE_OUTDOOR					11
-
-/* 802.11u network authentication type indicator */
-#define NATI_UNSPECIFIED				-1
-#define NATI_ACCEPTANCE_OF_TERMS_CONDITIONS		0
-#define NATI_ONLINE_ENROLLMENT_SUPPORTED		1
-#define NATI_HTTP_HTTPS_REDIRECTION			2
-#define NATI_DNS_REDIRECTION				3
-
-/* 802.11u IP address type availability - IPv6 */
-#define IPA_IPV6_SHIFT					0
-#define IPA_IPV6_MASK					(0x03 << IPA_IPV6_SHIFT)
-#define	IPA_IPV6_NOT_AVAILABLE				0x00
-#define IPA_IPV6_AVAILABLE				0x01
-#define IPA_IPV6_UNKNOWN_AVAILABILITY			0x02
-
-/* 802.11u IP address type availability - IPv4 */
-#define IPA_IPV4_SHIFT					2
-#define IPA_IPV4_MASK					(0x3f << IPA_IPV4_SHIFT)
-#define	IPA_IPV4_NOT_AVAILABLE				0x00
-#define IPA_IPV4_PUBLIC					0x01
-#define IPA_IPV4_PORT_RESTRICT				0x02
-#define IPA_IPV4_SINGLE_NAT				0x03
-#define IPA_IPV4_DOUBLE_NAT				0x04
-#define IPA_IPV4_PORT_RESTRICT_SINGLE_NAT		0x05
-#define IPA_IPV4_PORT_RESTRICT_DOUBLE_NAT		0x06
-#define IPA_IPV4_UNKNOWN_AVAILABILITY			0x07
-
-/* 802.11u NAI realm encoding */
-#define REALM_ENCODING_RFC4282				0
-#define REALM_ENCODING_UTF8				1
-
-/* 802.11u IANA EAP method type numbers */
-#define REALM_EAP_TLS					13
-#define REALM_EAP_LEAP					17
-#define REALM_EAP_SIM					18
-#define REALM_EAP_TTLS					21
-#define REALM_EAP_AKA					23
-#define REALM_EAP_PEAP					25
-#define REALM_EAP_FAST					43
-#define REALM_EAP_PSK					47
-#define REALM_EAP_AKAP					50
-#define REALM_EAP_EXPANDED				254
-
-/* 802.11u authentication ID */
-#define REALM_EXPANDED_EAP				1
-#define REALM_NON_EAP_INNER_AUTHENTICATION		2
-#define REALM_INNER_AUTHENTICATION_EAP			3
-#define REALM_EXPANDED_INNER_EAP			4
-#define REALM_CREDENTIAL				5
-#define REALM_TUNNELED_EAP_CREDENTIAL			6
-#define REALM_VENDOR_SPECIFIC_EAP			221
-
-/* 802.11u non-EAP inner authentication type */
-#define REALM_RESERVED_AUTH				0
-#define REALM_PAP					1
-#define REALM_CHAP					2
-#define REALM_MSCHAP					3
-#define REALM_MSCHAPV2					4
-
-/* 802.11u credential type */
-#define REALM_SIM					1
-#define REALM_USIM					2
-#define REALM_NFC					3
-#define REALM_HARDWARE_TOKEN				4
-#define REALM_SOFTOKEN					5
-#define REALM_CERTIFICATE				6
-#define REALM_USERNAME_PASSWORD				7
-#define REALM_SERVER_SIDE				8
-#define REALM_RESERVED_CRED				9
-#define REALM_VENDOR_SPECIFIC_CRED			10
-
-/* 802.11u 3GPP PLMN */
-#define G3PP_GUD_VERSION				0
-#define G3PP_PLMN_LIST_IE				0
-
-/** hotspot2.0 indication element (vendor specific) */
-BWL_PRE_PACKED_STRUCT struct hs20_ie {
-	uint8 oui[3];
-	uint8 type;
-	uint8 config;
-} BWL_POST_PACKED_STRUCT;
-typedef struct hs20_ie hs20_ie_t;
-#define HS20_IE_LEN 5	/* HS20 IE length */
-
-/** IEEE 802.11 Annex E */
-typedef enum {
-	DOT11_2GHZ_20MHZ_CLASS_12	= 81,	/* Ch 1-11 */
-	DOT11_5GHZ_20MHZ_CLASS_1	= 115,	/* Ch 36-48 */
-	DOT11_5GHZ_20MHZ_CLASS_2_DFS	= 118,	/* Ch 52-64 */
-	DOT11_5GHZ_20MHZ_CLASS_3	= 124,	/* Ch 149-161 */
-	DOT11_5GHZ_20MHZ_CLASS_4_DFS	= 121,	/* Ch 100-140 */
-	DOT11_5GHZ_20MHZ_CLASS_5	= 125,	/* Ch 149-165 */
-	DOT11_5GHZ_40MHZ_CLASS_22	= 116,	/* Ch 36-44,   lower */
-	DOT11_5GHZ_40MHZ_CLASS_23_DFS 	= 119,	/* Ch 52-60,   lower */
-	DOT11_5GHZ_40MHZ_CLASS_24_DFS	= 122,	/* Ch 100-132, lower */
-	DOT11_5GHZ_40MHZ_CLASS_25	= 126,	/* Ch 149-157, lower */
-	DOT11_5GHZ_40MHZ_CLASS_27	= 117,	/* Ch 40-48,   upper */
-	DOT11_5GHZ_40MHZ_CLASS_28_DFS	= 120,	/* Ch 56-64,   upper */
-	DOT11_5GHZ_40MHZ_CLASS_29_DFS	= 123,	/* Ch 104-136, upper */
-	DOT11_5GHZ_40MHZ_CLASS_30	= 127,	/* Ch 153-161, upper */
-	DOT11_2GHZ_40MHZ_CLASS_32	= 83,	/* Ch 1-7,     lower */
-	DOT11_2GHZ_40MHZ_CLASS_33	= 84,	/* Ch 5-11,    upper */
-} dot11_op_class_t;
-
-/* QoS map */
-#define QOS_MAP_FIXED_LENGTH	(8 * 2)	/* DSCP ranges fixed with 8 entries */
-
-#define BCM_AIBSS_IE_TYPE 56
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif /* _802_11_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h b/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h
deleted file mode 100644
index f1da1c1..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * BT-AMP (BlueTooth Alternate Mac and Phy) 802.11 PAL (Protocol Adaptation Layer)
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: 802.11_bta.h 518342 2014-12-01 23:21:41Z $
-*/
-
-#ifndef _802_11_BTA_H_
-#define _802_11_BTA_H_
-
-#define BT_SIG_SNAP_MPROT		"\xAA\xAA\x03\x00\x19\x58"
-
-/* BT-AMP 802.11 PAL Protocols */
-#define BTA_PROT_L2CAP				1
-#define	BTA_PROT_ACTIVITY_REPORT		2
-#define BTA_PROT_SECURITY			3
-#define BTA_PROT_LINK_SUPERVISION_REQUEST	4
-#define BTA_PROT_LINK_SUPERVISION_REPLY		5
-
-/* BT-AMP 802.11 PAL AMP_ASSOC Type IDs */
-#define BTA_TYPE_ID_MAC_ADDRESS			1
-#define BTA_TYPE_ID_PREFERRED_CHANNELS		2
-#define BTA_TYPE_ID_CONNECTED_CHANNELS		3
-#define BTA_TYPE_ID_CAPABILITIES		4
-#define BTA_TYPE_ID_VERSION			5
-#endif /* _802_11_bta_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11e.h b/drivers/net/wireless/bcmdhd/include/proto/802.11e.h
deleted file mode 100644
index ccfa965..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/802.11e.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 802.11e protocol header file
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: 802.11e.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _802_11e_H_
-#define _802_11e_H_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-
-/* WME Traffic Specification (TSPEC) element */
-#define WME_TSPEC_HDR_LEN           2           /* WME TSPEC header length */
-#define WME_TSPEC_BODY_OFF          2           /* WME TSPEC body offset */
-
-#define WME_CATEGORY_CODE_OFFSET	0		/* WME Category code offset */
-#define WME_ACTION_CODE_OFFSET		1		/* WME Action code offset */
-#define WME_TOKEN_CODE_OFFSET		2		/* WME Token code offset */
-#define WME_STATUS_CODE_OFFSET		3		/* WME Status code offset */
-
-BWL_PRE_PACKED_STRUCT struct tsinfo {
-	uint8 octets[3];
-} BWL_POST_PACKED_STRUCT;
-
-typedef struct tsinfo tsinfo_t;
-
-/* 802.11e TSPEC IE */
-typedef BWL_PRE_PACKED_STRUCT struct tspec {
-	uint8 oui[DOT11_OUI_LEN];	/* WME_OUI */
-	uint8 type;					/* WME_TYPE */
-	uint8 subtype;				/* WME_SUBTYPE_TSPEC */
-	uint8 version;				/* WME_VERSION */
-	tsinfo_t tsinfo;			/* TS Info bit field */
-	uint16 nom_msdu_size;		/* (Nominal or fixed) MSDU Size (bytes) */
-	uint16 max_msdu_size;		/* Maximum MSDU Size (bytes) */
-	uint32 min_srv_interval;	/* Minimum Service Interval (us) */
-	uint32 max_srv_interval;	/* Maximum Service Interval (us) */
-	uint32 inactivity_interval;	/* Inactivity Interval (us) */
-	uint32 suspension_interval; /* Suspension Interval (us) */
-	uint32 srv_start_time;		/* Service Start Time (us) */
-	uint32 min_data_rate;		/* Minimum Data Rate (bps) */
-	uint32 mean_data_rate;		/* Mean Data Rate (bps) */
-	uint32 peak_data_rate;		/* Peak Data Rate (bps) */
-	uint32 max_burst_size;		/* Maximum Burst Size (bytes) */
-	uint32 delay_bound;			/* Delay Bound (us) */
-	uint32 min_phy_rate;		/* Minimum PHY Rate (bps) */
-	uint16 surplus_bw;			/* Surplus Bandwidth Allowance (range 1.0-8.0) */
-	uint16 medium_time;			/* Medium Time (32 us/s periods) */
-} BWL_POST_PACKED_STRUCT tspec_t;
-
-#define WME_TSPEC_LEN	(sizeof(tspec_t))		/* not including 2-bytes of header */
-
-/* ts_info */
-/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */
-#define TS_INFO_TID_SHIFT		1	/* TS info. TID shift */
-#define TS_INFO_TID_MASK		(0xf << TS_INFO_TID_SHIFT)	/* TS info. TID mask */
-#define TS_INFO_CONTENTION_SHIFT	7	/* TS info. contention shift */
-#define TS_INFO_CONTENTION_MASK	(0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */
-#define TS_INFO_DIRECTION_SHIFT	5	/* TS info. direction shift */
-#define TS_INFO_DIRECTION_MASK	(0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */
-#define TS_INFO_PSB_SHIFT		2		/* TS info. PSB bit Shift */
-#define TS_INFO_PSB_MASK		(1 << TS_INFO_PSB_SHIFT)	/* TS info. PSB mask */
-#define TS_INFO_UPLINK			(0 << TS_INFO_DIRECTION_SHIFT)	/* TS info. uplink */
-#define TS_INFO_DOWNLINK		(1 << TS_INFO_DIRECTION_SHIFT)	/* TS info. downlink */
-#define TS_INFO_BIDIRECTIONAL	(3 << TS_INFO_DIRECTION_SHIFT)	/* TS info. bidirectional */
-#define TS_INFO_USER_PRIO_SHIFT	3	/* TS info. user priority shift */
-/* TS info. user priority mask */
-#define TS_INFO_USER_PRIO_MASK	(0x7 << TS_INFO_USER_PRIO_SHIFT)
-
-/* Macro to get/set bit(s) field in TSINFO */
-#define WLC_CAC_GET_TID(pt)	((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT)
-#define WLC_CAC_GET_DIR(pt)	((((pt).octets[0]) & \
-	TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT)
-#define WLC_CAC_GET_PSB(pt)	((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT)
-#define WLC_CAC_GET_USER_PRIO(pt)	((((pt).octets[1]) & \
-	TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT)
-
-#define WLC_CAC_SET_TID(pt, id)	((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \
-	((id) << TS_INFO_TID_SHIFT))
-#define WLC_CAC_SET_USER_PRIO(pt, prio)	((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \
-	((prio) << TS_INFO_USER_PRIO_SHIFT))
-
-/* 802.11e QBSS Load IE */
-#define QBSS_LOAD_IE_LEN		5	/* QBSS Load IE length */
-#define QBSS_LOAD_AAC_OFF		3	/* AAC offset in IE */
-
-#define CAC_ADDTS_RESP_TIMEOUT		1000	/* default ADDTS response timeout in ms */
-						/* DEFVAL dot11ADDTSResponseTimeout = 1s */
-
-/* 802.11e ADDTS status code */
-#define DOT11E_STATUS_ADMISSION_ACCEPTED	0	/* TSPEC Admission accepted status */
-#define DOT11E_STATUS_ADDTS_INVALID_PARAM	1	/* TSPEC invalid parameter status */
-#define DOT11E_STATUS_ADDTS_REFUSED_NSBW	3	/* ADDTS refused (non-sufficient BW) */
-#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE	47	/* ADDTS refused but could retry later */
-
-/* 802.11e DELTS status code */
-#define DOT11E_STATUS_QSTA_LEAVE_QBSS		36	/* STA leave QBSS */
-#define DOT11E_STATUS_END_TS				37	/* END TS */
-#define DOT11E_STATUS_UNKNOWN_TS			38	/* UNKNOWN TS */
-#define DOT11E_STATUS_QSTA_REQ_TIMEOUT		39	/* STA ADDTS request timeout */
-
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif /* _802_11e_CAC_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.1d.h b/drivers/net/wireless/bcmdhd/include/proto/802.1d.h
deleted file mode 100644
index 9610b55..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/802.1d.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Fundamental types and constants relating to 802.1D
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: 802.1d.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _802_1_D_
-#define _802_1_D_
-
-/* 802.1D priority defines */
-#define	PRIO_8021D_NONE		2	/* None = - */
-#define	PRIO_8021D_BK		1	/* BK - Background */
-#define	PRIO_8021D_BE		0	/* BE - Best-effort */
-#define	PRIO_8021D_EE		3	/* EE - Excellent-effort */
-#define	PRIO_8021D_CL		4	/* CL - Controlled Load */
-#define	PRIO_8021D_VI		5	/* Vi - Video */
-#define	PRIO_8021D_VO		6	/* Vo - Voice */
-#define	PRIO_8021D_NC		7	/* NC - Network Control */
-#define	MAXPRIO			7	/* 0-7 */
-#define NUMPRIO			(MAXPRIO + 1)
-
-#define ALLPRIO		-1	/* All prioirty */
-
-/* Converts prio to precedence since the numerical value of
- * PRIO_8021D_BE and PRIO_8021D_NONE are swapped.
- */
-#define PRIO2PREC(prio) \
-	(((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio))
-
-#endif /* _802_1_D__ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.3.h b/drivers/net/wireless/bcmdhd/include/proto/802.3.h
deleted file mode 100644
index 9f108c8..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/802.3.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Fundamental constants relating to 802.3
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: 802.3.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _802_3_h_
-#define _802_3_h_
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-#define SNAP_HDR_LEN	6	/* 802.3 SNAP header length */
-#define DOT3_OUI_LEN	3	/* 802.3 oui length */
-
-BWL_PRE_PACKED_STRUCT struct dot3_mac_llc_snap_header {
-	uint8	ether_dhost[ETHER_ADDR_LEN];	/* dest mac */
-	uint8	ether_shost[ETHER_ADDR_LEN];	/* src mac */
-	uint16	length;				/* frame length incl header */
-	uint8	dsap;				/* always 0xAA */
-	uint8	ssap;				/* always 0xAA */
-	uint8	ctl;				/* always 0x03 */
-	uint8	oui[DOT3_OUI_LEN];		/* RFC1042: 0x00 0x00 0x00
-						 * Bridge-Tunnel: 0x00 0x00 0xF8
-						 */
-	uint16	type;				/* ethertype */
-} BWL_POST_PACKED_STRUCT;
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif	/* #ifndef _802_3_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmdhcp.h b/drivers/net/wireless/bcmdhd/include/proto/bcmdhcp.h
deleted file mode 100644
index 5e51979..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/bcmdhcp.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Fundamental constants relating to DHCP Protocol
- *
- * Copyright (C) 2016, Broadcom Corporation
- * All Rights Reserved.
- * 
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
- * the contents of this file may not be disclosed to third parties, copied
- * or duplicated in any form, in whole or in part, without the prior
- * written permission of Broadcom Corporation.
- *
- *
- * <<Broadcom-WL-IPTag/Proprietary:>>
- *
- * $Id: bcmdhcp.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _bcmdhcp_h_
-#define _bcmdhcp_h_
-
-/* DHCP params */
-#define DHCP_TYPE_OFFSET	0	/* DHCP type (request|reply) offset */
-#define DHCP_TID_OFFSET		4	/* DHCP transition id offset */
-#define DHCP_FLAGS_OFFSET	10	/* DHCP flags offset */
-#define DHCP_CIADDR_OFFSET	12	/* DHCP client IP address offset */
-#define DHCP_YIADDR_OFFSET	16	/* DHCP your IP address offset */
-#define DHCP_GIADDR_OFFSET	24	/* DHCP relay agent IP address offset */
-#define DHCP_CHADDR_OFFSET	28	/* DHCP client h/w address offset */
-#define DHCP_OPT_OFFSET		236	/* DHCP options offset */
-
-#define DHCP_OPT_MSGTYPE	53	/* DHCP message type */
-#define DHCP_OPT_MSGTYPE_REQ	3
-#define DHCP_OPT_MSGTYPE_ACK	5	/* DHCP message type - ACK */
-
-#define DHCP_OPT_CODE_OFFSET	0	/* Option identifier */
-#define DHCP_OPT_LEN_OFFSET	1	/* Option data length */
-#define DHCP_OPT_DATA_OFFSET	2	/* Option data */
-
-#define DHCP_OPT_CODE_CLIENTID	61	/* Option identifier */
-
-#define DHCP_TYPE_REQUEST	1	/* DHCP request (discover|request) */
-#define DHCP_TYPE_REPLY		2	/* DHCP reply (offset|ack) */
-
-#define DHCP_PORT_SERVER	67	/* DHCP server UDP port */
-#define DHCP_PORT_CLIENT	68	/* DHCP client UDP port */
-
-#define DHCP_FLAG_BCAST	0x8000	/* DHCP broadcast flag */
-
-#define DHCP_FLAGS_LEN	2	/* DHCP flags field length */
-
-#define DHCP6_TYPE_SOLICIT	1	/* DHCP6 solicit */
-#define DHCP6_TYPE_ADVERTISE	2	/* DHCP6 advertise */
-#define DHCP6_TYPE_REQUEST	3	/* DHCP6 request */
-#define DHCP6_TYPE_CONFIRM	4	/* DHCP6 confirm */
-#define DHCP6_TYPE_RENEW	5	/* DHCP6 renew */
-#define DHCP6_TYPE_REBIND	6	/* DHCP6 rebind */
-#define DHCP6_TYPE_REPLY	7	/* DHCP6 reply */
-#define DHCP6_TYPE_RELEASE	8	/* DHCP6 release */
-#define DHCP6_TYPE_DECLINE	9	/* DHCP6 decline */
-#define DHCP6_TYPE_RECONFIGURE	10	/* DHCP6 reconfigure */
-#define DHCP6_TYPE_INFOREQ	11	/* DHCP6 information request */
-#define DHCP6_TYPE_RELAYFWD	12	/* DHCP6 relay forward */
-#define DHCP6_TYPE_RELAYREPLY	13	/* DHCP6 relay reply */
-
-#define DHCP6_TYPE_OFFSET	0	/* DHCP6 type offset */
-
-#define	DHCP6_MSG_OPT_OFFSET	4	/* Offset of options in client server messages */
-#define	DHCP6_RELAY_OPT_OFFSET	34	/* Offset of options in relay messages */
-
-#define	DHCP6_OPT_CODE_OFFSET	0	/* Option identifier */
-#define	DHCP6_OPT_LEN_OFFSET	2	/* Option data length */
-#define	DHCP6_OPT_DATA_OFFSET	4	/* Option data */
-
-#define	DHCP6_OPT_CODE_CLIENTID	1	/* DHCP6 CLIENTID option */
-#define	DHCP6_OPT_CODE_SERVERID	2	/* DHCP6 SERVERID option */
-
-#define DHCP6_PORT_SERVER	547	/* DHCP6 server UDP port */
-#define DHCP6_PORT_CLIENT	546	/* DHCP6 client UDP port */
-
-#endif	/* #ifndef _bcmdhcp_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
deleted file mode 100644
index 7ad453d..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Broadcom Ethernettype  protocol definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmeth.h 518342 2014-12-01 23:21:41Z $
- */
-
-/*
- * Broadcom Ethernet protocol defines
- */
-
-#ifndef _BCMETH_H_
-#define _BCMETH_H_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-/* ETHER_TYPE_BRCM is defined in ethernet.h */
-
-/*
- * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field
- * in one of two formats: (only subtypes 32768-65535 are in use now)
- *
- * subtypes 0-32767:
- *     8 bit subtype (0-127)
- *     8 bit length in bytes (0-255)
- *
- * subtypes 32768-65535:
- *     16 bit big-endian subtype
- *     16 bit big-endian length in bytes (0-65535)
- *
- * length is the number of additional bytes beyond the 4 or 6 byte header
- *
- * Reserved values:
- * 0 reserved
- * 5-15 reserved for iLine protocol assignments
- * 17-126 reserved, assignable
- * 127 reserved
- * 32768 reserved
- * 32769-65534 reserved, assignable
- * 65535 reserved
- */
-
-/*
- * While adding the subtypes and their specific processing code make sure
- * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition
- */
-
-#define	BCMILCP_SUBTYPE_RATE		1
-#define	BCMILCP_SUBTYPE_LINK		2
-#define	BCMILCP_SUBTYPE_CSA		3
-#define	BCMILCP_SUBTYPE_LARQ		4
-#define BCMILCP_SUBTYPE_VENDOR		5
-#define	BCMILCP_SUBTYPE_FLH		17
-
-#define BCMILCP_SUBTYPE_VENDOR_LONG	32769
-#define BCMILCP_SUBTYPE_CERT		32770
-#define BCMILCP_SUBTYPE_SES		32771
-
-
-#define BCMILCP_BCM_SUBTYPE_RESERVED		0
-#define BCMILCP_BCM_SUBTYPE_EVENT		1
-#define BCMILCP_BCM_SUBTYPE_SES			2
-/*
- * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded
- * within BCMILCP_BCM_SUBTYPE_EVENT type messages
- */
-/* #define BCMILCP_BCM_SUBTYPE_EAPOL		3 */
-#define BCMILCP_BCM_SUBTYPE_DPT                 4
-
-#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH	8
-#define BCMILCP_BCM_SUBTYPEHDR_VERSION		0
-
-/* These fields are stored in network order */
-typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr
-{
-	uint16	subtype;	/* Vendor specific..32769 */
-	uint16	length;
-	uint8	version;	/* Version is 0 */
-	uint8	oui[3];		/* Broadcom OUI */
-	/* user specific Data */
-	uint16	usr_subtype;
-} BWL_POST_PACKED_STRUCT bcmeth_hdr_t;
-
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif	/*  _BCMETH_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h
deleted file mode 100644
index 6c30d57..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- * Broadcom Event  protocol definitions
- *
- * Dependencies: proto/bcmeth.h
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmevent.h 555154 2015-05-07 20:46:07Z $
- *
- */
-
-/*
- * Broadcom Ethernet Events protocol defines
- *
- */
-
-#ifndef _BCMEVENT_H_
-#define _BCMEVENT_H_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-/* #include <ethernet.h> -- TODO: req., excluded to overwhelming coupling (break up ethernet.h) */
-#include <proto/bcmeth.h>
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-#define BCM_EVENT_MSG_VERSION		2	/* wl_event_msg_t struct version */
-#define BCM_MSG_IFNAME_MAX		16	/* max length of interface name */
-
-/* flags */
-#define WLC_EVENT_MSG_LINK		0x01	/* link is up */
-#define WLC_EVENT_MSG_FLUSHTXQ		0x02	/* flush tx queue on MIC error */
-#define WLC_EVENT_MSG_GROUP		0x04	/* group MIC error */
-#define WLC_EVENT_MSG_UNKBSS		0x08	/* unknown source bsscfg */
-#define WLC_EVENT_MSG_UNKIF		0x10	/* unknown source OS i/f */
-
-/* these fields are stored in network order */
-
-/* version 1 */
-typedef BWL_PRE_PACKED_STRUCT struct
-{
-	uint16	version;
-	uint16	flags;			/* see flags below */
-	uint32	event_type;		/* Message (see below) */
-	uint32	status;			/* Status code (see below) */
-	uint32	reason;			/* Reason code (if applicable) */
-	uint32	auth_type;		/* WLC_E_AUTH */
-	uint32	datalen;		/* data buf */
-	struct ether_addr	addr;	/* Station address (if applicable) */
-	char	ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */
-} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t;
-
-/* the current version */
-typedef BWL_PRE_PACKED_STRUCT struct
-{
-	uint16	version;
-	uint16	flags;			/* see flags below */
-	uint32	event_type;		/* Message (see below) */
-	uint32	status;			/* Status code (see below) */
-	uint32	reason;			/* Reason code (if applicable) */
-	uint32	auth_type;		/* WLC_E_AUTH */
-	uint32	datalen;		/* data buf */
-	struct ether_addr	addr;	/* Station address (if applicable) */
-	char	ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */
-	uint8	ifidx;			/* destination OS i/f index */
-	uint8	bsscfgidx;		/* source bsscfg index */
-} BWL_POST_PACKED_STRUCT wl_event_msg_t;
-
-/* used by driver msgs */
-typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
-	struct ether_header eth;
-	bcmeth_hdr_t		bcm_hdr;
-	wl_event_msg_t		event;
-	/* data portion follows */
-} BWL_POST_PACKED_STRUCT bcm_event_t;
-
-#define BCM_MSG_LEN	(sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header))
-
-/* Event messages */
-#define WLC_E_SET_SSID		0	/* indicates status of set SSID */
-#define WLC_E_JOIN		1	/* differentiates join IBSS from found (WLC_E_START) IBSS */
-#define WLC_E_START		2	/* STA founded an IBSS or AP started a BSS */
-#define WLC_E_AUTH		3	/* 802.11 AUTH request */
-#define WLC_E_AUTH_IND		4	/* 802.11 AUTH indication */
-#define WLC_E_DEAUTH		5	/* 802.11 DEAUTH request */
-#define WLC_E_DEAUTH_IND	6	/* 802.11 DEAUTH indication */
-#define WLC_E_ASSOC		7	/* 802.11 ASSOC request */
-#define WLC_E_ASSOC_IND		8	/* 802.11 ASSOC indication */
-#define WLC_E_REASSOC		9	/* 802.11 REASSOC request */
-#define WLC_E_REASSOC_IND	10	/* 802.11 REASSOC indication */
-#define WLC_E_DISASSOC		11	/* 802.11 DISASSOC request */
-#define WLC_E_DISASSOC_IND	12	/* 802.11 DISASSOC indication */
-#define WLC_E_QUIET_START	13	/* 802.11h Quiet period started */
-#define WLC_E_QUIET_END		14	/* 802.11h Quiet period ended */
-#define WLC_E_BEACON_RX		15	/* BEACONS received/lost indication */
-#define WLC_E_LINK		16	/* generic link indication */
-#define WLC_E_MIC_ERROR		17	/* TKIP MIC error occurred */
-#define WLC_E_NDIS_LINK		18	/* NDIS style link indication */
-#define WLC_E_ROAM		19	/* roam attempt occurred: indicate status & reason */
-#define WLC_E_TXFAIL		20	/* change in dot11FailedCount (txfail) */
-#define WLC_E_PMKID_CACHE	21	/* WPA2 pmkid cache indication */
-#define WLC_E_RETROGRADE_TSF	22	/* current AP's TSF value went backward */
-#define WLC_E_PRUNE		23	/* AP was pruned from join list for reason */
-#define WLC_E_AUTOAUTH		24	/* report AutoAuth table entry match for join attempt */
-#define WLC_E_EAPOL_MSG		25	/* Event encapsulating an EAPOL message */
-#define WLC_E_SCAN_COMPLETE	26	/* Scan results are ready or scan was aborted */
-#define WLC_E_ADDTS_IND		27	/* indicate to host addts fail/success */
-#define WLC_E_DELTS_IND		28	/* indicate to host delts fail/success */
-#define WLC_E_BCNSENT_IND	29	/* indicate to host of beacon transmit */
-#define WLC_E_BCNRX_MSG		30	/* Send the received beacon up to the host */
-#define WLC_E_BCNLOST_MSG	31	/* indicate to host loss of beacon */
-#define WLC_E_ROAM_PREP		32	/* before attempting to roam */
-#define WLC_E_PFN_NET_FOUND	33	/* PFN network found event */
-#define WLC_E_PFN_NET_LOST	34	/* PFN network lost event */
-#define WLC_E_RESET_COMPLETE	35
-#define WLC_E_JOIN_START	36
-#define WLC_E_ROAM_START	37
-#define WLC_E_ASSOC_START	38
-#define WLC_E_IBSS_ASSOC	39
-#define WLC_E_RADIO		40
-#define WLC_E_PSM_WATCHDOG	41	/* PSM microcode watchdog fired */
-#define WLC_E_PROBREQ_MSG       44      /* probe request received */
-#define WLC_E_SCAN_CONFIRM_IND  45
-#define WLC_E_PSK_SUP		46	/* WPA Handshake fail */
-#define WLC_E_COUNTRY_CODE_CHANGED	47
-#define	WLC_E_EXCEEDED_MEDIUM_TIME	48	/* WMMAC excedded medium time */
-#define WLC_E_ICV_ERROR		49	/* WEP ICV error occurred */
-#define WLC_E_UNICAST_DECODE_ERROR	50	/* Unsupported unicast encrypted frame */
-#define WLC_E_MULTICAST_DECODE_ERROR	51	/* Unsupported multicast encrypted frame */
-#define WLC_E_TRACE		52
-#define WLC_E_IF		54	/* I/F change (for dongle host notification) */
-#define WLC_E_P2P_DISC_LISTEN_COMPLETE	55	/* listen state expires */
-#define WLC_E_RSSI		56	/* indicate RSSI change based on configured levels */
-#define WLC_E_PFN_BEST_BATCHING	57	/* PFN best network batching event */
-#define WLC_E_EXTLOG_MSG	58
-#define WLC_E_ACTION_FRAME      59	/* Action frame Rx */
-#define WLC_E_ACTION_FRAME_COMPLETE	60	/* Action frame Tx complete */
-#define WLC_E_PRE_ASSOC_IND	61	/* assoc request received */
-#define WLC_E_PRE_REASSOC_IND	62	/* re-assoc request received */
-#define WLC_E_CHANNEL_ADOPTED	63
-#define WLC_E_AP_STARTED	64	/* AP started */
-#define WLC_E_DFS_AP_STOP	65	/* AP stopped due to DFS */
-#define WLC_E_DFS_AP_RESUME	66	/* AP resumed due to DFS */
-#define WLC_E_WAI_STA_EVENT	67	/* WAI stations event */
-#define WLC_E_WAI_MSG 		68	/* event encapsulating an WAI message */
-#define WLC_E_ESCAN_RESULT 	69	/* escan result event */
-#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 	70	/* action frame off channel complete */
-#define WLC_E_PROBRESP_MSG	71	/* probe response received */
-#define WLC_E_P2P_PROBREQ_MSG	72	/* P2P Probe request received */
-#define WLC_E_DCS_REQUEST	73
-#define WLC_E_FIFO_CREDIT_MAP	74	/* credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */
-#define WLC_E_ACTION_FRAME_RX	75	/* Received action frame event WITH
-					 * wl_event_rx_frame_data_t header
-					 */
-#define WLC_E_WAKE_EVENT	76	/* Wake Event timer fired, used for wake WLAN test mode */
-#define WLC_E_RM_COMPLETE	77	/* Radio measurement complete */
-#define WLC_E_HTSFSYNC		78	/* Synchronize TSF with the host */
-#define WLC_E_OVERLAY_REQ	79	/* request an overlay IOCTL/iovar from the host */
-#define WLC_E_CSA_COMPLETE_IND		80	/* 802.11 CHANNEL SWITCH ACTION completed */
-#define WLC_E_EXCESS_PM_WAKE_EVENT	81	/* excess PM Wake Event to inform host  */
-#define WLC_E_PFN_SCAN_NONE		82	/* no PFN networks around */
-/* PFN BSSID network found event, conflict/share with  WLC_E_PFN_SCAN_NONE */
-#define WLC_E_PFN_BSSID_NET_FOUND	82
-#define WLC_E_PFN_SCAN_ALLGONE		83	/* last found PFN network gets lost */
-/* PFN BSSID network lost event, conflict/share with WLC_E_PFN_SCAN_ALLGONE */
-#define WLC_E_PFN_BSSID_NET_LOST	83
-#define WLC_E_GTK_PLUMBED		84
-#define WLC_E_ASSOC_IND_NDIS		85	/* 802.11 ASSOC indication for NDIS only */
-#define WLC_E_REASSOC_IND_NDIS		86	/* 802.11 REASSOC indication for NDIS only */
-#define WLC_E_ASSOC_REQ_IE		87
-#define WLC_E_ASSOC_RESP_IE		88
-#define WLC_E_ASSOC_RECREATED		89	/* association recreated on resume */
-#define WLC_E_ACTION_FRAME_RX_NDIS	90	/* rx action frame event for NDIS only */
-#define WLC_E_AUTH_REQ			91	/* authentication request received */
-#define WLC_E_TDLS_PEER_EVENT		92	/* discovered peer, connected/disconnected peer */
-#define WLC_E_SPEEDY_RECREATE_FAIL	93	/* fast assoc recreation failed */
-#define WLC_E_NATIVE			94	/* port-specific event and payload (e.g. NDIS) */
-#define WLC_E_PKTDELAY_IND		95	/* event for tx pkt delay suddently jump */
-#define WLC_E_PSTA_PRIMARY_INTF_IND	99	/* psta primary interface indication */
-#define WLC_E_NAN			100     /* NAN event */
-#define WLC_E_BEACON_FRAME_RX		101
-#define WLC_E_SERVICE_FOUND		102	/* desired service found */
-#define WLC_E_GAS_FRAGMENT_RX		103	/* GAS fragment received */
-#define WLC_E_GAS_COMPLETE		104	/* GAS sessions all complete */
-#define WLC_E_P2PO_ADD_DEVICE		105	/* New device found by p2p offload */
-#define WLC_E_P2PO_DEL_DEVICE		106	/* device has been removed by p2p offload */
-#define WLC_E_WNM_STA_SLEEP		107	/* WNM event to notify STA enter sleep mode */
-#define WLC_E_TXFAIL_THRESH		108	/* Indication of MAC tx failures (exhaustion of
-						 * 802.11 retries) exceeding threshold(s)
-						 */
-#define WLC_E_PROXD			109	/* Proximity Detection event */
-#define WLC_E_IBSS_COALESCE		110	/* IBSS Coalescing */
-#define WLC_E_AIBSS_TXFAIL		110	/* TXFAIL event for AIBSS, re using event 110 */
-#define WLC_E_BSS_LOAD			114	/* Inform host of beacon bss load */
-#define WLC_E_MSCH			120	/* Multiple channel scheduler event */
-#define WLC_E_CSA_START_IND		121
-#define WLC_E_CSA_DONE_IND		122
-#define WLC_E_CSA_FAILURE_IND		123
-#define WLC_E_CCA_CHAN_QUAL		124	/* CCA based channel quality report */
-#define WLC_E_BSSID		125	/* to report change in BSSID while roaming */
-#define WLC_E_TX_STAT_ERROR		126	/* tx error indication */
-#define WLC_E_BCMC_CREDIT_SUPPORT	127	/* credit check for BCMC supported */
-#define WLC_E_BT_WIFI_HANDOVER_REQ	130	/* Handover Request Initiated */
-#define WLC_E_SPW_TXINHIBIT		131     /* Southpaw TxInhibit notification */
-#define WLC_E_FBT_AUTH_REQ_IND		132	/* FBT Authentication Request Indication */
-#define WLC_E_RSSI_LQM			133	/* Enhancement addition for WLC_E_RSSI */
-#define WLC_E_PFN_GSCAN_FULL_RESULT		134 /* Full probe/beacon (IEs etc) results */
-#define WLC_E_PFN_SWC		135 /* Significant change in rssi of bssids being tracked */
-#define WLC_E_AUTHORIZED	136	/* a STA been authroized for traffic */
-#define WLC_E_PROBREQ_MSG_RX	137 /* probe req with wl_event_rx_frame_data_t header */
-#define WLC_E_PFN_SCAN_COMPLETE	138	/* PFN completed scan of network list */
-#define WLC_E_RMC_EVENT		139	/* RMC Event */
-#define WLC_E_DPSTA_INTF_IND	140 /* DPSTA interface indication */
-#define WLC_E_RRM			141	/* RRM Event */
-#define WLC_E_PFN_SSID_EXT      142    /* SSID EXT event */
-#define WLC_E_ROAM_EXP_EVENT    143  /* Expanded roam event */
-#define WLC_E_LAST		144	/* highest val + 1 for range checking */
-#if (WLC_E_LAST > 144)
-#error "WLC_E_LAST: Invalid value for last event; must be <= 141."
-#endif /* WLC_E_LAST */
-
-/* define an API for getting the string name of an event */
-extern const char *bcmevent_get_name(uint event_type);
-extern void wl_event_to_host_order(wl_event_msg_t * evt);
-extern void wl_event_to_network_order(wl_event_msg_t * evt);
-
-/* conversion between host and network order for events */
-void wl_event_to_host_order(wl_event_msg_t * evt);
-void wl_event_to_network_order(wl_event_msg_t * evt);
-
-
-/* Event status codes */
-#define WLC_E_STATUS_SUCCESS		0	/* operation was successful */
-#define WLC_E_STATUS_FAIL		1	/* operation failed */
-#define WLC_E_STATUS_TIMEOUT		2	/* operation timed out */
-#define WLC_E_STATUS_NO_NETWORKS	3	/* failed due to no matching network found */
-#define WLC_E_STATUS_ABORT		4	/* operation was aborted */
-#define WLC_E_STATUS_NO_ACK		5	/* protocol failure: packet not ack'd */
-#define WLC_E_STATUS_UNSOLICITED	6	/* AUTH or ASSOC packet was unsolicited */
-#define WLC_E_STATUS_ATTEMPT		7	/* attempt to assoc to an auto auth configuration */
-#define WLC_E_STATUS_PARTIAL		8	/* scan results are incomplete */
-#define WLC_E_STATUS_NEWSCAN		9	/* scan aborted by another scan */
-#define WLC_E_STATUS_NEWASSOC		10	/* scan aborted due to assoc in progress */
-#define WLC_E_STATUS_11HQUIET		11	/* 802.11h quiet period started */
-#define WLC_E_STATUS_SUPPRESS		12	/* user disabled scanning (WLC_SET_SCANSUPPRESS) */
-#define WLC_E_STATUS_NOCHANS		13	/* no allowable channels to scan */
-#define WLC_E_STATUS_CS_ABORT		15	/* abort channel select */
-#define WLC_E_STATUS_ERROR		16	/* request failed due to error */
-#define WLC_E_STATUS_INVALID 0xff  /* Invalid status code to init variables. */
-
-/* roam reason codes */
-#define WLC_E_REASON_INITIAL_ASSOC	0	/* initial assoc */
-#define WLC_E_REASON_LOW_RSSI		1	/* roamed due to low RSSI */
-#define WLC_E_REASON_DEAUTH		2	/* roamed due to DEAUTH indication */
-#define WLC_E_REASON_DISASSOC		3	/* roamed due to DISASSOC indication */
-#define WLC_E_REASON_BCNS_LOST		4	/* roamed due to lost beacons */
-
-/* Roam codes used primarily by CCX */
-#define WLC_E_REASON_FAST_ROAM_FAILED	5	/* roamed due to fast roam failure */
-#define WLC_E_REASON_DIRECTED_ROAM	6	/* roamed due to request by AP */
-#define WLC_E_REASON_TSPEC_REJECTED	7	/* roamed due to TSPEC rejection */
-#define WLC_E_REASON_BETTER_AP		8	/* roamed due to finding better AP */
-#define WLC_E_REASON_MINTXRATE		9	/* roamed because at mintxrate for too long */
-#define WLC_E_REASON_TXFAIL		10	/* We can hear AP, but AP can't hear us */
-/* retained for precommit auto-merging errors; remove once all branches are synced */
-#define WLC_E_REASON_REQUESTED_ROAM	11
-#define WLC_E_REASON_BSSTRANS_REQ	11	/* roamed due to BSS Transition request by AP */
-
-/* prune reason codes */
-#define WLC_E_PRUNE_ENCR_MISMATCH	1	/* encryption mismatch */
-#define WLC_E_PRUNE_BCAST_BSSID		2	/* AP uses a broadcast BSSID */
-#define WLC_E_PRUNE_MAC_DENY		3	/* STA's MAC addr is in AP's MAC deny list */
-#define WLC_E_PRUNE_MAC_NA		4	/* STA's MAC addr is not in AP's MAC allow list */
-#define WLC_E_PRUNE_REG_PASSV		5	/* AP not allowed due to regulatory restriction */
-#define WLC_E_PRUNE_SPCT_MGMT		6	/* AP does not support STA locale spectrum mgmt */
-#define WLC_E_PRUNE_RADAR		7	/* AP is on a radar channel of STA locale */
-#define WLC_E_RSN_MISMATCH		8	/* STA does not support AP's RSN */
-#define WLC_E_PRUNE_NO_COMMON_RATES	9	/* No rates in common with AP */
-#define WLC_E_PRUNE_BASIC_RATES		10	/* STA does not support all basic rates of BSS */
-#define WLC_E_PRUNE_CIPHER_NA		12	/* BSS's cipher not supported */
-#define WLC_E_PRUNE_KNOWN_STA		13	/* AP is already known to us as a STA */
-#define WLC_E_PRUNE_WDS_PEER		15	/* AP is already known to us as a WDS peer */
-#define WLC_E_PRUNE_QBSS_LOAD		16	/* QBSS LOAD - AAC is too low */
-#define WLC_E_PRUNE_HOME_AP		17	/* prune home AP */
-#define WLC_E_PRUNE_AUTH_RESP_MAC	20	/* suppress auth resp by MAC filter */
-
-/* WPA failure reason codes carried in the WLC_E_PSK_SUP event */
-#define WLC_E_SUP_OTHER			0	/* Other reason */
-#define WLC_E_SUP_DECRYPT_KEY_DATA	1	/* Decryption of key data failed */
-#define WLC_E_SUP_BAD_UCAST_WEP128	2	/* Illegal use of ucast WEP128 */
-#define WLC_E_SUP_BAD_UCAST_WEP40	3	/* Illegal use of ucast WEP40 */
-#define WLC_E_SUP_UNSUP_KEY_LEN		4	/* Unsupported key length */
-#define WLC_E_SUP_PW_KEY_CIPHER		5	/* Unicast cipher mismatch in pairwise key */
-#define WLC_E_SUP_MSG3_TOO_MANY_IE	6	/* WPA IE contains > 1 RSN IE in key msg 3 */
-#define WLC_E_SUP_MSG3_IE_MISMATCH	7	/* WPA IE mismatch in key message 3 */
-#define WLC_E_SUP_NO_INSTALL_FLAG	8	/* INSTALL flag unset in 4-way msg */
-#define WLC_E_SUP_MSG3_NO_GTK		9	/* encapsulated GTK missing from msg 3 */
-#define WLC_E_SUP_GRP_KEY_CIPHER	10	/* Multicast cipher mismatch in group key */
-#define WLC_E_SUP_GRP_MSG1_NO_GTK	11	/* encapsulated GTK missing from group msg 1 */
-#define WLC_E_SUP_GTK_DECRYPT_FAIL	12	/* GTK decrypt failure */
-#define WLC_E_SUP_SEND_FAIL		13	/* message send failure */
-#define WLC_E_SUP_DEAUTH		14	/* received FC_DEAUTH */
-#define WLC_E_SUP_WPA_PSK_TMO		15	/* WPA PSK 4-way handshake timeout */
-
-/* Event data for events that include frames received over the air */
-/* WLC_E_PROBRESP_MSG
- * WLC_E_P2P_PROBREQ_MSG
- * WLC_E_ACTION_FRAME_RX
- */
-typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data {
-	uint16	version;
-	uint16	channel;	/* Matches chanspec_t format from bcmwifi_channels.h */
-	int32	rssi;
-	uint32	mactime;
-	uint32	rate;
-} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t;
-
-#define BCM_RX_FRAME_DATA_VERSION 1
-
-/* WLC_E_IF event data */
-typedef struct wl_event_data_if {
-	uint8 ifidx;		/* RTE virtual device index (for dongle) */
-	uint8 opcode;		/* see I/F opcode */
-	uint8 reserved;		/* bit mask (WLC_E_IF_FLAGS_XXX ) */
-	uint8 bssidx;		/* bsscfg index */
-	uint8 role;		/* see I/F role */
-} wl_event_data_if_t;
-
-/* opcode in WLC_E_IF event */
-#define WLC_E_IF_ADD		1	/* bsscfg add */
-#define WLC_E_IF_DEL		2	/* bsscfg delete */
-#define WLC_E_IF_CHANGE		3	/* bsscfg role change */
-
-/* I/F role code in WLC_E_IF event */
-#define WLC_E_IF_ROLE_STA		0	/* Infra STA */
-#define WLC_E_IF_ROLE_AP		1	/* Access Point */
-#define WLC_E_IF_ROLE_WDS		2	/* WDS link */
-#define WLC_E_IF_ROLE_P2P_GO		3	/* P2P Group Owner */
-#define WLC_E_IF_ROLE_P2P_CLIENT	4	/* P2P Client */
-#define WLC_E_IF_ROLE_IBSS              8       /* IBSS */
-
-/* WLC_E_RSSI event data */
-typedef struct wl_event_data_rssi {
-	int32 rssi;
-	int32 snr;
-	int32 noise;
-} wl_event_data_rssi_t;
-
-/* WLC_E_IF flag */
-#define WLC_E_IF_FLAGS_BSSCFG_NOIF	0x1	/* no host I/F creation needed */
-
-/* Reason codes for LINK */
-#define WLC_E_LINK_BCN_LOSS     1   /* Link down because of beacon loss */
-#define WLC_E_LINK_DISASSOC     2   /* Link down because of disassoc */
-#define WLC_E_LINK_ASSOC_REC    3   /* Link down because assoc recreate failed */
-#define WLC_E_LINK_BSSCFG_DIS   4   /* Link down due to bsscfg down */
-
-
-/* WLC_E_NDIS_LINK event data */
-typedef BWL_PRE_PACKED_STRUCT struct ndis_link_parms {
-	struct ether_addr peer_mac; /* 6 bytes */
-	uint16 chanspec;            /* 2 bytes */
-	uint32 link_speed;          /* current datarate in units of 500 Kbit/s */
-	uint32 max_link_speed;      /* max possible datarate for link in units of 500 Kbit/s  */
-	int32  rssi;                /* average rssi */
-} BWL_POST_PACKED_STRUCT ndis_link_parms_t;
-
-/* reason codes for WLC_E_OVERLAY_REQ event */
-#define WLC_E_OVL_DOWNLOAD		0	/* overlay download request */
-#define WLC_E_OVL_UPDATE_IND	1	/* device indication of host overlay update */
-
-/* reason codes for WLC_E_TDLS_PEER_EVENT event */
-#define WLC_E_TDLS_PEER_DISCOVERED		0	/* peer is ready to establish TDLS */
-#define WLC_E_TDLS_PEER_CONNECTED		1
-#define WLC_E_TDLS_PEER_DISCONNECTED	2
-
-/* reason codes for WLC_E_RMC_EVENT event */
-#define WLC_E_REASON_RMC_NONE		0
-#define WLC_E_REASON_RMC_AR_LOST		1
-#define WLC_E_REASON_RMC_AR_NO_ACK		2
-
-#ifdef WLTDLS
-/* TDLS Action Category code */
-#define TDLS_AF_CATEGORY		12
-/* Wi-Fi Display (WFD) Vendor Specific Category */
-/* used for WFD Tunneled Probe Request and Response */
-#define TDLS_VENDOR_SPECIFIC		127
-/* TDLS Action Field Values */
-#define TDLS_ACTION_SETUP_REQ		0
-#define TDLS_ACTION_SETUP_RESP		1
-#define TDLS_ACTION_SETUP_CONFIRM	2
-#define TDLS_ACTION_TEARDOWN		3
-#define WLAN_TDLS_SET_PROBE_WFD_IE	11
-#define WLAN_TDLS_SET_SETUP_WFD_IE	12
-#define WLAN_TDLS_SET_WFD_ENABLED	13
-#define WLAN_TDLS_SET_WFD_DISABLED	14
-#endif
-
-
-/* GAS event data */
-typedef BWL_PRE_PACKED_STRUCT struct wl_event_gas {
-	uint16	channel;		/* channel of GAS protocol */
-	uint8	dialog_token;	/* GAS dialog token */
-	uint8	fragment_id;	/* fragment id */
-	uint16	status_code;	/* status code on GAS completion */
-	uint16 	data_len;		/* length of data to follow */
-	uint8	data[1];		/* variable length specified by data_len */
-} BWL_POST_PACKED_STRUCT wl_event_gas_t;
-
-/* service discovery TLV */
-typedef BWL_PRE_PACKED_STRUCT struct wl_sd_tlv {
-	uint16	length;			/* length of response_data */
-	uint8	protocol;		/* service protocol type */
-	uint8	transaction_id;		/* service transaction id */
-	uint8	status_code;		/* status code */
-	uint8	data[1];		/* response data */
-} BWL_POST_PACKED_STRUCT wl_sd_tlv_t;
-
-/* service discovery event data */
-typedef BWL_PRE_PACKED_STRUCT struct wl_event_sd {
-	uint16	channel;		/* channel */
-	uint8	count;			/* number of tlvs */
-	wl_sd_tlv_t	tlv[1];		/* service discovery TLV */
-} BWL_POST_PACKED_STRUCT wl_event_sd_t;
-
-/* Note: proxd has a new API (ver 3.0) deprecates the following */
-
-/* Reason codes for WLC_E_PROXD */
-#define WLC_E_PROXD_FOUND		1	/* Found a proximity device */
-#define WLC_E_PROXD_GONE		2	/* Lost a proximity device */
-#define WLC_E_PROXD_START		3	/* used by: target  */
-#define WLC_E_PROXD_STOP		4	/* used by: target   */
-#define WLC_E_PROXD_COMPLETED		5	/* used by: initiator completed */
-#define WLC_E_PROXD_ERROR		6	/* used by both initiator and target */
-#define WLC_E_PROXD_COLLECT_START	7	/* used by: target & initiator */
-#define WLC_E_PROXD_COLLECT_STOP	8	/* used by: target */
-#define WLC_E_PROXD_COLLECT_COMPLETED	9	/* used by: initiator completed */
-#define WLC_E_PROXD_COLLECT_ERROR	10	/* used by both initiator and target */
-#define WLC_E_PROXD_NAN_EVENT		11	/* used by both initiator and target */
-#define WLC_E_PROXD_TS_RESULTS          12      /* used by: initiator completed */
-
-/*  proxd_event data */
-typedef struct ftm_sample {
-	uint32 value;	/* RTT in ns */
-	int8 rssi;	/* RSSI */
-} ftm_sample_t;
-
-typedef struct ts_sample {
-	uint32 t1;
-	uint32 t2;
-	uint32 t3;
-	uint32 t4;
-} ts_sample_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct proxd_event_data {
-	uint16 ver;			/* version */
-	uint16 mode;			/* mode: target/initiator */
-	uint16 method;			/* method: rssi/TOF/AOA */
-	uint8  err_code;		/* error classification */
-	uint8  TOF_type;		/* one way or two way TOF */
-	uint8  OFDM_frame_type;		/* legacy or VHT */
-	uint8  bandwidth;		/* Bandwidth is 20, 40,80, MHZ */
-	struct ether_addr peer_mac;	/* (e.g for tgt:initiator's */
-	uint32 distance;		/* dst to tgt, units meter */
-	uint32 meanrtt;			/* mean delta */
-	uint32 modertt;			/* Mode delta */
-	uint32 medianrtt;		/* median RTT */
-	uint32 sdrtt;			/* Standard deviation of RTT */
-	int32  gdcalcresult;		/* Software or Hardware Kind of redundant, but if */
-					/* frame type is VHT, then we should do it by hardware */
-	int16  avg_rssi;		/* avg rssi accroos the ftm frames */
-	int16  validfrmcnt;		/* Firmware's valid frame counts */
-	int32  peer_router_info;	/* Peer router information if available in TLV, */
-					/* We will add this field later  */
-	int32 var1;			/* average of group delay */
-	int32 var2;			/* average of threshold crossing */
-	int32 var3;			/* difference between group delay and threshold crossing */
-					/* raw Fine Time Measurements (ftm) data */
-	uint16 ftm_unit;		/* ftm cnt resolution in picoseconds , 6250ps - default */
-	uint16 ftm_cnt;			/*  num of rtd measurments/length in the ftm buffer  */
-	ftm_sample_t ftm_buff[1];	/* 1 ... ftm_cnt  */
-} BWL_POST_PACKED_STRUCT wl_proxd_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct proxd_event_ts_results {
-	uint16 ver;                     /* version */
-	uint16 mode;                    /* mode: target/initiator */
-	uint16 method;                  /* method: rssi/TOF/AOA */
-	uint8  err_code;                /* error classification */
-	uint8  TOF_type;                /* one way or two way TOF */
-	uint16  ts_cnt;                 /* number of timestamp measurements */
-	ts_sample_t ts_buff[1];         /* Timestamps */
-} BWL_POST_PACKED_STRUCT wl_proxd_event_ts_results_t;
-
-
-/* Video Traffic Interference Monitor Event */
-#define INTFER_EVENT_VERSION		1
-#define INTFER_STREAM_TYPE_NONTCP	1
-#define INTFER_STREAM_TYPE_TCP		2
-#define WLINTFER_STATS_NSMPLS		4
-typedef struct wl_intfer_event {
-	uint16 version;			/* version */
-	uint16 status;			/* status */
-	uint8 txfail_histo[WLINTFER_STATS_NSMPLS]; /* txfail histo */
-} wl_intfer_event_t;
-
-/* WLC_E_PSTA_PRIMARY_INTF_IND event data */
-typedef struct wl_psta_primary_intf_event {
-	struct ether_addr prim_ea;	/* primary intf ether addr */
-} wl_psta_primary_intf_event_t;
-
-/* WLC_E_DPSTA_INTF_IND event data */
-typedef enum {
-	WL_INTF_PSTA = 1,
-	WL_INTF_DWDS = 2
-} wl_dpsta_intf_type;
-
-typedef struct wl_dpsta_intf_event {
-	wl_dpsta_intf_type intf_type;    /* dwds/psta intf register */
-} wl_dpsta_intf_event_t;
-
-/*  **********  NAN protocol events/subevents  ********** */
-#define NAN_EVENT_BUFFER_SIZE 512 /* max size */
-/* nan application events to the host driver */
-typedef enum nan_app_events {
-	WL_NAN_EVENT_START = 1,     /* NAN cluster started */
-	WL_NAN_EVENT_JOIN = 2,      /* Joined to a NAN cluster */
-	WL_NAN_EVENT_ROLE = 3,      /* Role or State changed */
-	WL_NAN_EVENT_SCAN_COMPLETE = 4,
-	WL_NAN_EVENT_DISCOVERY_RESULT = 5,
-	WL_NAN_EVENT_REPLIED = 6,
-	WL_NAN_EVENT_TERMINATED = 7,	/* the instance ID will be present in the ev data */
-	WL_NAN_EVENT_RECEIVE = 8,
-	WL_NAN_EVENT_STATUS_CHG = 9,  /* generated on any change in nan_mac status */
-	WL_NAN_EVENT_MERGE = 10,      /* Merged to a NAN cluster */
-	WL_NAN_EVENT_STOP = 11,       /* NAN stopped */
-	WL_NAN_EVENT_P2P = 12,       /* NAN P2P EVENT */
-	WL_NAN_EVENT_WINDOW_BEGIN_P2P = 13, /* Event for begin of P2P further availability window */
-	WL_NAN_EVENT_WINDOW_BEGIN_MESH = 14,
-	WL_NAN_EVENT_WINDOW_BEGIN_IBSS = 15,
-	WL_NAN_EVENT_WINDOW_BEGIN_RANGING = 16,
-	WL_NAN_EVENT_POST_DISC = 17, /* Event for post discovery data */
-	WL_NAN_EVENT_INVALID	/* delimiter for max value */
-} nan_app_events_e;
-
-#define IS_NAN_EVT_ON(var, evt) ((var & (1 << (evt-1))) != 0)
-/*  ******************* end of NAN section *************** */
-
-#define MSCH_EVENTS_BUFFER_SIZE 2048
-
-/* Reason codes for WLC_E_MSCH */
-#define WLC_E_MSCH_START		0	/* start event check */
-#define WLC_E_MSCH_EXIT			1	/* exit event check */
-#define WLC_E_MSCH_REQ			2	/* request event */
-#define WLC_E_MSCH_CALLBACK		3	/* call back event */
-#define WLC_E_MSCH_MESSAGE		4	/* message event */
-#define WLC_E_MSCH_PROFILE_START	5
-#define WLC_E_MSCH_PROFILE_END		6
-#define WLC_E_MSCH_REQ_HANDLE		7
-#define WLC_E_MSCH_REQ_ENTITY		8
-#define WLC_E_MSCH_CHAN_CTXT		9
-#define WLC_E_MSCH_TIMESLOT		10
-#define WLC_E_MSCH_REQ_TIMING		11
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_event_data {
-	uint32	time_lo;		/* Request time */
-	uint32	time_hi;
-} BWL_POST_PACKED_STRUCT msch_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_start_event_data {
-	uint32	time_lo;		/* Request time */
-	uint32	time_hi;
-	uint32	status;
-} BWL_POST_PACKED_STRUCT msch_start_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_message_event_data {
-	uint32	time_lo;		/* Request time */
-	uint32	time_hi;
-	char	message[1];		/* message */
-} BWL_POST_PACKED_STRUCT msch_message_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_req_param_event_data {
-	uint16  flags;			/* Describe various request properties */
-	uint8	req_type;		/* Describe start and end time flexiblilty */
-	uint8	priority;		/* Define the request priority */
-	uint32	start_time_l;		/* Requested start time offset in us unit */
-	uint32	start_time_h;
-	uint32	duration;		/* Requested duration in us unit */
-	uint32	interval;		/* Requested periodic interval in us unit,
-					 * 0 means non-periodic
-					 */
-	union {
-		uint32	dur_flex;	/* MSCH_REG_DUR_FLEX, min_dur = duration - dur_flex */
-		struct {
-			uint32 min_dur;			/* min duration for traffic, maps to home_time */
-			uint32 max_away_dur;		/* max acceptable away dur, maps to home_away_time*/
-			uint32 lo_prio_time_l;
-			uint32 lo_prio_time_h;
-			uint32 lo_prio_interval; 	/* repeated low priority interval */
-			uint32 hi_prio_time_l;
-			uint32 hi_prio_time_h;
-			uint32 hi_prio_interval; 	/* repeated high priority interval */
-		} bf;
-	} flex;
-} BWL_POST_PACKED_STRUCT msch_req_param_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_timeslot_event_data {
-	uint32 p_timeslot;
-	uint32 p_prev;
-	uint32 p_next;
-	uint32 timeslot_id;
-	uint32 pre_start_time_l;
-	uint32 pre_start_time_h;
-	uint32 end_time_l;
-	uint32 end_time_h;
-	uint32 sch_dur_l;
-	uint32 sch_dur_h;
-	uint32 p_chan_ctxt;
-	uint32 fire_time_l;
-	uint32 fire_time_h;
-	uint32 state;
-} BWL_POST_PACKED_STRUCT msch_timeslot_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_req_timing_event_data {
-	uint32 p_req_timing;
-	uint32 p_prev;
-	uint32 p_next;
-	uint16 flags;
-	uint16 timeslot_ptr;
-	uint32 fire_time_l;
-	uint32 fire_time_h;
-	uint32 pre_start_time_l;
-	uint32 pre_start_time_h;
-	uint32 start_time_l;
-	uint32 start_time_h;
-	uint32 end_time_l;
-	uint32 end_time_h;
-	uint32 p_timeslot;
-} BWL_POST_PACKED_STRUCT msch_req_timing_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_chan_ctxt_event_data {
-	uint32 p_chan_ctxt;
-	uint32 p_prev;
-	uint32 p_next;
-	uint16 chanspec;
-	uint16 bf_sch_pending;
-	uint32 bf_link_prev;
-	uint32 bf_link_next;
-	uint32 onchan_time_l;
-	uint32 onchan_time_h;
-	uint32 actual_onchan_dur_l;
-	uint32 actual_onchan_dur_h;
-	uint32 pend_onchan_dur_l;
-	uint32 pend_onchan_dur_h;
-	uint16 req_entity_list_cnt;
-	uint16 req_entity_list_ptr;
-	uint16 bf_entity_list_cnt;
-	uint16 bf_entity_list_ptr;
-} BWL_POST_PACKED_STRUCT msch_chan_ctxt_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_prio_event_data {
-	uint32 is_lo;
-	uint32 time_l;
-	uint32 time_h;
-	uint32 p_entity;
-} BWL_POST_PACKED_STRUCT msch_prio_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_req_entity_event_data {
-	uint32 p_req_entity;
-	uint32 req_hdl_link_prev;
-	uint32 req_hdl_link_next;
-	uint32 chan_ctxt_link_prev;
-	uint32 chan_ctxt_link_next;
-	uint32 rt_specific_link_prev;
-	uint32 rt_specific_link_next;
-	uint16 chanspec;
-	uint16 req_param_ptr;
-	uint16 cur_slot_ptr;
-	uint16 pend_slot_ptr;
-	msch_prio_event_data_t lo_event;
-	msch_prio_event_data_t hi_event;
-	uint32 ts_change_dur_flex;
-	uint16 ts_change_flags;
-	uint16 chan_ctxt_ptr;
-	uint32 p_chan_ctxt;
-	uint32 p_req_hdl;
-	uint32 hi_cnt_l;
-	uint32 hi_cnt_h;
-	uint32 bf_last_serv_time_l;
-	uint32 bf_last_serv_time_h;
-} BWL_POST_PACKED_STRUCT msch_req_entity_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_req_handle_event_data {
-	uint32 p_req_handle;
-	uint32 p_prev;
-	uint32 p_next;
-	uint32 cb_func;
-	uint32 cb_ctxt;
-	uint16 req_param_ptr;
-	uint16 req_entity_list_cnt;
-	uint16 req_entity_list_ptr;
-	uint16 chan_cnt;
-	uint16 schd_chan_cnt;
-	uint16 chanspec_list_cnt;
-	uint16 chanspec_list_ptr;
-	uint16 pad;
-} BWL_POST_PACKED_STRUCT msch_req_handle_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_profile_event_data {
-	uint32 time_lo;			/* Request time */
-	uint32 time_hi;
-	uint32 free_req_hdl_list;
-	uint32 free_req_entity_list;
-	uint32 free_chan_ctxt_list;
-	uint32 free_timeslot_list;
-	uint32 free_chanspec_list;
-	uint16 cur_msch_timeslot_ptr;
-	uint16 pad;
-	uint32 p_cur_msch_timeslot;
-	uint32 cur_armed_timeslot;
-	uint32 cur_armed_req_timing;
-	uint32 ts_id;
-	uint32 service_interval;
-	uint32 max_lo_prio_interval;
-	uint16 flex_list_cnt;
-	uint16 msch_chanspec_alloc_cnt;
-	uint16 msch_req_entity_alloc_cnt;
-	uint16 msch_req_hdl_alloc_cnt;
-	uint16 msch_chan_ctxt_alloc_cnt;
-	uint16 msch_timeslot_alloc_cnt;
-	uint16 msch_req_hdl_list_cnt;
-	uint16 msch_req_hdl_list_ptr;
-	uint16 msch_chan_ctxt_list_cnt;
-	uint16 msch_chan_ctxt_list_ptr;
-	uint16 msch_timeslot_list_cnt;
-	uint16 msch_timeslot_list_ptr;
-	uint16 msch_req_timing_list_cnt;
-	uint16 msch_req_timing_list_ptr;
-	uint16 msch_start_flex_list_cnt;
-	uint16 msch_start_flex_list_ptr;
-	uint16 msch_both_flex_list_cnt;
-	uint16 msch_both_flex_list_ptr;
-} BWL_POST_PACKED_STRUCT msch_profile_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_req_event_data {
-	uint32 time_lo;			/* Request time */
-	uint32 time_hi;
-	uint16 chanspec_cnt;
-	uint16 chanspec_ptr;
-	uint16 req_param_ptr;
-	uint16 pad;
-} BWL_POST_PACKED_STRUCT msch_req_event_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct msch_callback_event_data {
-	uint32 time_lo;			/* Request time */
-	uint32 time_hi;
-	uint16 type;			/* callback type */
-	uint16 chanspec; 		/* actual chanspec, may different with requested one */
-	uint32 pre_start_time_l;	/* time slot prestart time low 32bit */
-	uint32 pre_start_time_h;	/* time slot prestart time high 32bit */
-	uint32 end_time_l;		/* time slot end time low 32 bit */
-	uint32 end_time_h;		/* time slot end time high 32 bit */
-	uint32 timeslot_id;		/* unique time slot id */
-} BWL_POST_PACKED_STRUCT msch_callback_event_data_t;
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif /* _BCMEVENT_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmip.h b/drivers/net/wireless/bcmdhd/include/proto/bcmip.h
deleted file mode 100644
index eaa679c..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/bcmip.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Fundamental constants relating to IP Protocol
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmip.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _bcmip_h_
-#define _bcmip_h_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-
-/* IPV4 and IPV6 common */
-#define IP_VER_OFFSET		0x0	/* offset to version field */
-#define IP_VER_MASK		0xf0	/* version mask */
-#define IP_VER_SHIFT		4	/* version shift */
-#define IP_VER_4		4	/* version number for IPV4 */
-#define IP_VER_6		6	/* version number for IPV6 */
-
-#define IP_VER(ip_body) \
-	((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT)
-
-#define IP_PROT_ICMP		0x1	/* ICMP protocol */
-#define IP_PROT_IGMP		0x2	/* IGMP protocol */
-#define IP_PROT_TCP		0x6	/* TCP protocol */
-#define IP_PROT_UDP		0x11	/* UDP protocol type */
-#define IP_PROT_ICMP6		0x3a	/* ICMPv6 protocol type */
-
-/* IPV4 field offsets */
-#define IPV4_VER_HL_OFFSET      0       /* version and ihl byte offset */
-#define IPV4_TOS_OFFSET         1       /* type of service offset */
-#define IPV4_PKTLEN_OFFSET      2       /* packet length offset */
-#define IPV4_PKTFLAG_OFFSET     6       /* more-frag,dont-frag flag offset */
-#define IPV4_PROT_OFFSET        9       /* protocol type offset */
-#define IPV4_CHKSUM_OFFSET      10      /* IP header checksum offset */
-#define IPV4_SRC_IP_OFFSET      12      /* src IP addr offset */
-#define IPV4_DEST_IP_OFFSET     16      /* dest IP addr offset */
-#define IPV4_OPTIONS_OFFSET     20      /* IP options offset */
-#define IPV4_MIN_HEADER_LEN     20      /* Minimum size for an IP header (no options) */
-
-/* IPV4 field decodes */
-#define IPV4_VER_MASK		0xf0	/* IPV4 version mask */
-#define IPV4_VER_SHIFT		4	/* IPV4 version shift */
-
-#define IPV4_HLEN_MASK		0x0f	/* IPV4 header length mask */
-#define IPV4_HLEN(ipv4_body)	(4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK))
-
-#define IPV4_ADDR_LEN		4	/* IPV4 address length */
-
-#define IPV4_ADDR_NULL(a)	((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \
-				  ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0)
-
-#define IPV4_ADDR_BCAST(a)	((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \
-				  ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff)
-
-#define	IPV4_TOS_DSCP_MASK	0xfc	/* DiffServ codepoint mask */
-#define	IPV4_TOS_DSCP_SHIFT	2	/* DiffServ codepoint shift */
-
-#define	IPV4_TOS(ipv4_body)	(((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET])
-
-#define	IPV4_TOS_PREC_MASK	0xe0	/* Historical precedence mask */
-#define	IPV4_TOS_PREC_SHIFT	5	/* Historical precedence shift */
-
-#define IPV4_TOS_LOWDELAY	0x10	/* Lowest delay requested */
-#define IPV4_TOS_THROUGHPUT	0x8	/* Best throughput requested */
-#define IPV4_TOS_RELIABILITY	0x4	/* Most reliable delivery requested */
-
-#define IPV4_TOS_ROUTINE        0
-#define IPV4_TOS_PRIORITY       1
-#define IPV4_TOS_IMMEDIATE      2
-#define IPV4_TOS_FLASH          3
-#define IPV4_TOS_FLASHOVERRIDE  4
-#define IPV4_TOS_CRITICAL       5
-#define IPV4_TOS_INETWORK_CTRL  6
-#define IPV4_TOS_NETWORK_CTRL   7
-
-#define IPV4_PROT(ipv4_body)	(((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET])
-
-#define IPV4_FRAG_RESV		0x8000	/* Reserved */
-#define IPV4_FRAG_DONT		0x4000	/* Don't fragment */
-#define IPV4_FRAG_MORE		0x2000	/* More fragments */
-#define IPV4_FRAG_OFFSET_MASK	0x1fff	/* Fragment offset */
-
-#define IPV4_ADDR_STR_LEN	16	/* Max IP address length in string format */
-
-/* IPV4 packet formats */
-BWL_PRE_PACKED_STRUCT struct ipv4_addr {
-	uint8	addr[IPV4_ADDR_LEN];
-} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct ipv4_hdr {
-	uint8	version_ihl;		/* Version and Internet Header Length */
-	uint8	tos;			/* Type Of Service */
-	uint16	tot_len;		/* Number of bytes in packet (max 65535) */
-	uint16	id;
-	uint16	frag;			/* 3 flag bits and fragment offset */
-	uint8	ttl;			/* Time To Live */
-	uint8	prot;			/* Protocol */
-	uint16	hdr_chksum;		/* IP header checksum */
-	uint8	src_ip[IPV4_ADDR_LEN];	/* Source IP Address */
-	uint8	dst_ip[IPV4_ADDR_LEN];	/* Destination IP Address */
-} BWL_POST_PACKED_STRUCT;
-
-/* IPV6 field offsets */
-#define IPV6_PAYLOAD_LEN_OFFSET	4	/* payload length offset */
-#define IPV6_NEXT_HDR_OFFSET	6	/* next header/protocol offset */
-#define IPV6_HOP_LIMIT_OFFSET	7	/* hop limit offset */
-#define IPV6_SRC_IP_OFFSET	8	/* src IP addr offset */
-#define IPV6_DEST_IP_OFFSET	24	/* dst IP addr offset */
-
-/* IPV6 field decodes */
-#define IPV6_TRAFFIC_CLASS(ipv6_body) \
-	(((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \
-	 ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4))
-
-#define IPV6_FLOW_LABEL(ipv6_body) \
-	(((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \
-	 (((uint8 *)(ipv6_body))[2] << 8) | \
-	 (((uint8 *)(ipv6_body))[3]))
-
-#define IPV6_PAYLOAD_LEN(ipv6_body) \
-	((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \
-	 ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1])
-
-#define IPV6_NEXT_HDR(ipv6_body) \
-	(((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET])
-
-#define IPV6_PROT(ipv6_body)	IPV6_NEXT_HDR(ipv6_body)
-
-#define IPV6_ADDR_LEN		16	/* IPV6 address length */
-
-/* IPV4 TOS or IPV6 Traffic Classifier or 0 */
-#define IP_TOS46(ip_body) \
-	(IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \
-	 IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0)
-
-#define IP_DSCP46(ip_body) (IP_TOS46(ip_body) >> IPV4_TOS_DSCP_SHIFT);
-
-/* IPV4 or IPV6 Protocol Classifier or 0 */
-#define IP_PROT46(ip_body) \
-	(IP_VER(ip_body) == IP_VER_4 ? IPV4_PROT(ip_body) : \
-	 IP_VER(ip_body) == IP_VER_6 ? IPV6_PROT(ip_body) : 0)
-
-/* IPV6 extension headers (options) */
-#define IPV6_EXTHDR_HOP		0
-#define IPV6_EXTHDR_ROUTING	43
-#define IPV6_EXTHDR_FRAGMENT	44
-#define IPV6_EXTHDR_AUTH	51
-#define IPV6_EXTHDR_NONE	59
-#define IPV6_EXTHDR_DEST	60
-
-#define IPV6_EXTHDR(prot)	(((prot) == IPV6_EXTHDR_HOP) || \
-	                         ((prot) == IPV6_EXTHDR_ROUTING) || \
-	                         ((prot) == IPV6_EXTHDR_FRAGMENT) || \
-	                         ((prot) == IPV6_EXTHDR_AUTH) || \
-	                         ((prot) == IPV6_EXTHDR_NONE) || \
-	                         ((prot) == IPV6_EXTHDR_DEST))
-
-#define IPV6_MIN_HLEN 		40
-
-#define IPV6_EXTHDR_LEN(eh)	((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3)
-
-BWL_PRE_PACKED_STRUCT struct ipv6_exthdr {
-	uint8	nexthdr;
-	uint8	hdrlen;
-} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag {
-	uint8	nexthdr;
-	uint8	rsvd;
-	uint16	frag_off;
-	uint32	ident;
-} BWL_POST_PACKED_STRUCT;
-
-static INLINE int32
-ipv6_exthdr_len(uint8 *h, uint8 *proto)
-{
-	uint16 len = 0, hlen;
-	struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h;
-
-	while (IPV6_EXTHDR(eh->nexthdr)) {
-		if (eh->nexthdr == IPV6_EXTHDR_NONE)
-			return -1;
-		else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT)
-			hlen = 8;
-		else if (eh->nexthdr == IPV6_EXTHDR_AUTH)
-			hlen = (eh->hdrlen + 2) << 2;
-		else
-			hlen = IPV6_EXTHDR_LEN(eh);
-
-		len += hlen;
-		eh = (struct ipv6_exthdr *)(h + len);
-	}
-
-	*proto = eh->nexthdr;
-	return len;
-}
-
-#define IPV4_ISMULTI(a) (((a) & 0xf0000000) == 0xe0000000)
-
-#define IPV4_MCAST_TO_ETHER_MCAST(ipv4, ether) \
-{ \
-	ether[0] = 0x01; \
-	ether[1] = 0x00; \
-	ether[2] = 0x5E; \
-	ether[3] = (ipv4 & 0x7f0000) >> 16; \
-	ether[4] = (ipv4 & 0xff00) >> 8; \
-	ether[5] = (ipv4 & 0xff); \
-}
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#define IPV4_ADDR_STR "%d.%d.%d.%d"
-#define IPV4_ADDR_TO_STR(addr)	((uint32)addr & 0xff000000) >> 24, \
-								((uint32)addr & 0x00ff0000) >> 16, \
-								((uint32)addr & 0x0000ff00) >> 8, \
-								((uint32)addr & 0x000000ff)
-
-#endif	/* _bcmip_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmipv6.h b/drivers/net/wireless/bcmdhd/include/proto/bcmipv6.h
deleted file mode 100644
index fbab037..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/bcmipv6.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Fundamental constants relating to Neighbor Discovery Protocol
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmipv6.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _bcmipv6_h_
-#define _bcmipv6_h_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-/* Extension headers */
-#define IPV6_EXT_HOP	0
-#define IPV6_EXT_ROUTE	43
-#define IPV6_EXT_FRAG	44
-#define IPV6_EXT_DEST	60
-#define IPV6_EXT_ESEC	50
-#define IPV6_EXT_AUTH	51
-
-/* Minimum size (extension header "word" length) */
-#define IPV6_EXT_WORD	8
-
-/* Offsets for most extension headers */
-#define IPV6_EXT_NEXTHDR	0
-#define IPV6_EXT_HDRLEN		1
-
-/* Constants specific to fragmentation header */
-#define IPV6_FRAG_MORE_MASK	0x0001
-#define IPV6_FRAG_MORE_SHIFT	0
-#define IPV6_FRAG_OFFS_MASK	0xfff8
-#define IPV6_FRAG_OFFS_SHIFT	3
-
-/* For icmpv6 */
-#define ICMPV6_HEADER_TYPE	0x3A
-#define ICMPV6_PKT_TYPE_RA	134
-#define ICMPV6_PKT_TYPE_NS	135
-#define ICMPV6_PKT_TYPE_NA	136
-
-#define ICMPV6_ND_OPT_TYPE_TARGET_MAC	2
-#define ICMPV6_ND_OPT_TYPE_SRC_MAC		1
-
-#define ICMPV6_ND_OPT_LEN_LINKADDR		1
-
-#define ICMPV6_ND_OPT_LEN_LINKADDR		1
-
-#define IPV6_VERSION 	6
-#define IPV6_HOP_LIMIT 	255
-
-#define IPV6_ADDR_NULL(a)	((a[0] | a[1] | a[2] | a[3] | a[4] | \
-							 a[5] | a[6] | a[7] | a[8] | a[9] | \
-							 a[10] | a[11] | a[12] | a[13] | \
-							 a[14] | a[15]) == 0)
-
-#define IPV6_ADDR_LOCAL(a)	(((a[0] == 0xfe) && (a[1] & 0x80))? TRUE: FALSE)
-
-/* IPV6 address */
-BWL_PRE_PACKED_STRUCT struct ipv6_addr {
-		uint8		addr[16];
-} BWL_POST_PACKED_STRUCT;
-
-
-/* ICMPV6 Header */
-BWL_PRE_PACKED_STRUCT struct icmp6_hdr {
-	uint8	icmp6_type;
-	uint8	icmp6_code;
-	uint16	icmp6_cksum;
-	BWL_PRE_PACKED_STRUCT union {
-		uint32 reserved;
-		BWL_PRE_PACKED_STRUCT struct nd_advt {
-			uint32	reserved1:5,
-				override:1,
-				solicited:1,
-				router:1,
-				reserved2:24;
-		} BWL_POST_PACKED_STRUCT nd_advt;
-	} BWL_POST_PACKED_STRUCT opt;
-} BWL_POST_PACKED_STRUCT;
-
-/* Ipv6 Header Format */
-BWL_PRE_PACKED_STRUCT struct ipv6_hdr {
-	uint8	priority:4,
-		version:4;
-	uint8	flow_lbl[3];
-	uint16	payload_len;
-	uint8	nexthdr;
-	uint8 	hop_limit;
-	struct	ipv6_addr	saddr;
-	struct	ipv6_addr	daddr;
-} BWL_POST_PACKED_STRUCT;
-
-/* Neighbor Advertisement/Solicitation Packet Structure */
-BWL_PRE_PACKED_STRUCT struct bcm_nd_msg {
-	struct	icmp6_hdr	icmph;
-	struct	ipv6_addr	target;
-} BWL_POST_PACKED_STRUCT;
-
-
-/* Neighibor Solicitation/Advertisement Optional Structure */
-BWL_PRE_PACKED_STRUCT struct nd_msg_opt {
-	uint8 type;
-	uint8 len;
-	uint8 mac_addr[ETHER_ADDR_LEN];
-} BWL_POST_PACKED_STRUCT;
-
-/* Ipv6 Fragmentation Header */
-BWL_PRE_PACKED_STRUCT struct ipv6_frag {
-	uint8	nexthdr;
-	uint8	reserved;
-	uint16	frag_offset;
-	uint32	ident;
-} BWL_POST_PACKED_STRUCT;
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-static const struct ipv6_addr all_node_ipv6_maddr = {
-									{ 0xff, 0x2, 0, 0,
-									0, 0, 0, 0,
-									0, 0, 0, 0,
-									0, 0, 0, 1
-									}};
-
-#define IPV6_ISMULTI(a) (a[0] == 0xff)
-
-#define IPV6_MCAST_TO_ETHER_MCAST(ipv6, ether) \
-{ \
-	ether[0] = 0x33; \
-	ether[1] = 0x33; \
-	ether[2] = ipv6[12]; \
-	ether[3] = ipv6[13]; \
-	ether[4] = ipv6[14]; \
-	ether[5] = ipv6[15]; \
-}
-
-#endif	/* !defined(_bcmipv6_h_) */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmtcp.h b/drivers/net/wireless/bcmdhd/include/proto/bcmtcp.h
deleted file mode 100644
index 661e1f8..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/bcmtcp.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Fundamental constants relating to TCP Protocol
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bcmtcp.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _bcmtcp_h_
-#define _bcmtcp_h_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-
-#define TCP_SRC_PORT_OFFSET	0	/* TCP source port offset */
-#define TCP_DEST_PORT_OFFSET	2	/* TCP dest port offset */
-#define TCP_SEQ_NUM_OFFSET	4	/* TCP sequence number offset */
-#define TCP_ACK_NUM_OFFSET	8	/* TCP acknowledgement number offset */
-#define TCP_HLEN_OFFSET		12	/* HLEN and reserved bits offset */
-#define TCP_FLAGS_OFFSET	13	/* FLAGS and reserved bits offset */
-#define TCP_CHKSUM_OFFSET	16	/* TCP body checksum offset */
-
-#define TCP_PORT_LEN		2	/* TCP port field length */
-
-/* 8bit TCP flag field */
-#define TCP_FLAG_URG            0x20
-#define TCP_FLAG_ACK            0x10
-#define TCP_FLAG_PSH            0x08
-#define TCP_FLAG_RST            0x04
-#define TCP_FLAG_SYN            0x02
-#define TCP_FLAG_FIN            0x01
-
-#define TCP_HLEN_MASK           0xf000
-#define TCP_HLEN_SHIFT          12
-
-/* These fields are stored in network order */
-BWL_PRE_PACKED_STRUCT struct bcmtcp_hdr
-{
-	uint16	src_port;	/* Source Port Address */
-	uint16	dst_port;	/* Destination Port Address */
-	uint32	seq_num;	/* TCP Sequence Number */
-	uint32	ack_num;	/* TCP Sequence Number */
-	uint16	hdrlen_rsvd_flags;	/* Header length, reserved bits and flags */
-	uint16	tcpwin;		/* TCP window */
-	uint16	chksum;		/* Segment checksum with pseudoheader */
-	uint16	urg_ptr;	/* Points to seq-num of byte following urg data */
-} BWL_POST_PACKED_STRUCT;
-
-#define TCP_MIN_HEADER_LEN 20
-
-#define TCP_HDRLEN_MASK 0xf0
-#define TCP_HDRLEN_SHIFT 4
-#define TCP_HDRLEN(hdrlen) (((hdrlen) & TCP_HDRLEN_MASK) >> TCP_HDRLEN_SHIFT)
-
-#define TCP_FLAGS_MASK  0x1f
-#define TCP_FLAGS(hdrlen) ((hdrlen) & TCP_FLAGS_MASK)
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-/* To address round up by 32bit. */
-#define IS_TCPSEQ_GE(a, b) ((a - b) < NBITVAL(31))		/* a >= b */
-#define IS_TCPSEQ_LE(a, b) ((b - a) < NBITVAL(31))		/* a =< b */
-#define IS_TCPSEQ_GT(a, b) !IS_TCPSEQ_LE(a, b)		/* a > b */
-#define IS_TCPSEQ_LT(a, b) !IS_TCPSEQ_GE(a, b)		/* a < b */
-
-#endif	/* #ifndef _bcmtcp_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmudp.h b/drivers/net/wireless/bcmdhd/include/proto/bcmudp.h
deleted file mode 100644
index 97cf815..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/bcmudp.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Fundamental constants relating to UDP Protocol
- *
- * Copyright (C) 2016, Broadcom Corporation
- * All Rights Reserved.
- * 
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
- * the contents of this file may not be disclosed to third parties, copied
- * or duplicated in any form, in whole or in part, without the prior
- * written permission of Broadcom Corporation.
- *
- *
- * <<Broadcom-WL-IPTag/Proprietary:>>
- *
- * $Id: bcmudp.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _bcmudp_h_
-#define _bcmudp_h_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-
-/* UDP header */
-#define UDP_DEST_PORT_OFFSET	2	/* UDP dest port offset */
-#define UDP_LEN_OFFSET		4	/* UDP length offset */
-#define UDP_CHKSUM_OFFSET	6	/* UDP body checksum offset */
-
-#define UDP_HDR_LEN	8	/* UDP header length */
-#define UDP_PORT_LEN	2	/* UDP port length */
-
-/* These fields are stored in network order */
-BWL_PRE_PACKED_STRUCT struct bcmudp_hdr
-{
-	uint16	src_port;	/* Source Port Address */
-	uint16	dst_port;	/* Destination Port Address */
-	uint16	len;		/* Number of bytes in datagram including header */
-	uint16	chksum;		/* entire datagram checksum with pseudoheader */
-} BWL_POST_PACKED_STRUCT;
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif	/* #ifndef _bcmudp_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h b/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h
deleted file mode 100644
index 4e948d2..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * BT-AMP (BlueTooth Alternate Mac and Phy) HCI (Host/Controller Interface)
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: bt_amp_hci.h 518342 2014-12-01 23:21:41Z $
-*/
-
-#ifndef _bt_amp_hci_h
-#define _bt_amp_hci_h
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-
-/* AMP HCI CMD packet format */
-typedef BWL_PRE_PACKED_STRUCT struct amp_hci_cmd {
-	uint16 opcode;
-	uint8 plen;
-	uint8 parms[1];
-} BWL_POST_PACKED_STRUCT amp_hci_cmd_t;
-
-#define HCI_CMD_PREAMBLE_SIZE		OFFSETOF(amp_hci_cmd_t, parms)
-#define HCI_CMD_DATA_SIZE		255
-
-/* AMP HCI CMD opcode layout */
-#define HCI_CMD_OPCODE(ogf, ocf)	((((ogf) & 0x3F) << 10) | ((ocf) & 0x03FF))
-#define HCI_CMD_OGF(opcode)		((uint8)(((opcode) >> 10) & 0x3F))
-#define HCI_CMD_OCF(opcode)		((opcode) & 0x03FF)
-
-/* AMP HCI command opcodes */
-#define HCI_Read_Failed_Contact_Counter		HCI_CMD_OPCODE(0x05, 0x0001)
-#define HCI_Reset_Failed_Contact_Counter	HCI_CMD_OPCODE(0x05, 0x0002)
-#define HCI_Read_Link_Quality			HCI_CMD_OPCODE(0x05, 0x0003)
-#define HCI_Read_Local_AMP_Info			HCI_CMD_OPCODE(0x05, 0x0009)
-#define HCI_Read_Local_AMP_ASSOC		HCI_CMD_OPCODE(0x05, 0x000A)
-#define HCI_Write_Remote_AMP_ASSOC		HCI_CMD_OPCODE(0x05, 0x000B)
-#define HCI_Create_Physical_Link		HCI_CMD_OPCODE(0x01, 0x0035)
-#define HCI_Accept_Physical_Link_Request	HCI_CMD_OPCODE(0x01, 0x0036)
-#define HCI_Disconnect_Physical_Link		HCI_CMD_OPCODE(0x01, 0x0037)
-#define HCI_Create_Logical_Link			HCI_CMD_OPCODE(0x01, 0x0038)
-#define HCI_Accept_Logical_Link			HCI_CMD_OPCODE(0x01, 0x0039)
-#define HCI_Disconnect_Logical_Link		HCI_CMD_OPCODE(0x01, 0x003A)
-#define HCI_Logical_Link_Cancel			HCI_CMD_OPCODE(0x01, 0x003B)
-#define HCI_Flow_Spec_Modify			HCI_CMD_OPCODE(0x01, 0x003C)
-#define HCI_Write_Flow_Control_Mode		HCI_CMD_OPCODE(0x01, 0x0067)
-#define HCI_Read_Best_Effort_Flush_Timeout	HCI_CMD_OPCODE(0x01, 0x0069)
-#define HCI_Write_Best_Effort_Flush_Timeout	HCI_CMD_OPCODE(0x01, 0x006A)
-#define HCI_Short_Range_Mode			HCI_CMD_OPCODE(0x01, 0x006B)
-#define HCI_Reset				HCI_CMD_OPCODE(0x03, 0x0003)
-#define HCI_Read_Connection_Accept_Timeout	HCI_CMD_OPCODE(0x03, 0x0015)
-#define HCI_Write_Connection_Accept_Timeout	HCI_CMD_OPCODE(0x03, 0x0016)
-#define HCI_Read_Link_Supervision_Timeout	HCI_CMD_OPCODE(0x03, 0x0036)
-#define HCI_Write_Link_Supervision_Timeout	HCI_CMD_OPCODE(0x03, 0x0037)
-#define HCI_Enhanced_Flush			HCI_CMD_OPCODE(0x03, 0x005F)
-#define HCI_Read_Logical_Link_Accept_Timeout	HCI_CMD_OPCODE(0x03, 0x0061)
-#define HCI_Write_Logical_Link_Accept_Timeout	HCI_CMD_OPCODE(0x03, 0x0062)
-#define HCI_Set_Event_Mask_Page_2		HCI_CMD_OPCODE(0x03, 0x0063)
-#define HCI_Read_Location_Data_Command		HCI_CMD_OPCODE(0x03, 0x0064)
-#define HCI_Write_Location_Data_Command		HCI_CMD_OPCODE(0x03, 0x0065)
-#define HCI_Read_Local_Version_Info		HCI_CMD_OPCODE(0x04, 0x0001)
-#define HCI_Read_Local_Supported_Commands	HCI_CMD_OPCODE(0x04, 0x0002)
-#define HCI_Read_Buffer_Size			HCI_CMD_OPCODE(0x04, 0x0005)
-#define HCI_Read_Data_Block_Size		HCI_CMD_OPCODE(0x04, 0x000A)
-
-/* AMP HCI command parameters */
-typedef BWL_PRE_PACKED_STRUCT struct read_local_cmd_parms {
-	uint8 plh;
-	uint8 offset[2];			/* length so far */
-	uint8 max_remote[2];
-} BWL_POST_PACKED_STRUCT read_local_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct write_remote_cmd_parms {
-	uint8 plh;
-	uint8 offset[2];
-	uint8 len[2];
-	uint8 frag[1];
-} BWL_POST_PACKED_STRUCT write_remote_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct phy_link_cmd_parms {
-	uint8 plh;
-	uint8 key_length;
-	uint8 key_type;
-	uint8 key[1];
-} BWL_POST_PACKED_STRUCT phy_link_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_cmd_parms {
-	uint8 plh;
-	uint8 reason;
-} BWL_POST_PACKED_STRUCT dis_phy_link_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct log_link_cmd_parms {
-	uint8 plh;
-	uint8 txflow[16];
-	uint8 rxflow[16];
-} BWL_POST_PACKED_STRUCT log_link_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct ext_flow_spec {
-	uint8 id;
-	uint8 service_type;
-	uint8 max_sdu[2];
-	uint8 sdu_ia_time[4];
-	uint8 access_latency[4];
-	uint8 flush_timeout[4];
-} BWL_POST_PACKED_STRUCT ext_flow_spec_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_cmd_parms {
-	uint8 plh;
-	uint8 tx_fs_ID;
-} BWL_POST_PACKED_STRUCT log_link_cancel_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_cmd_parms {
-	uint8 llh[2];
-	uint8 txflow[16];
-	uint8 rxflow[16];
-} BWL_POST_PACKED_STRUCT flow_spec_mod_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct plh_pad {
-	uint8 plh;
-	uint8 pad;
-} BWL_POST_PACKED_STRUCT plh_pad_t;
-
-typedef BWL_PRE_PACKED_STRUCT union hci_handle {
-	uint16 bredr;
-	plh_pad_t amp;
-} BWL_POST_PACKED_STRUCT hci_handle_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct ls_to_cmd_parms {
-	hci_handle_t handle;
-	uint8 timeout[2];
-} BWL_POST_PACKED_STRUCT ls_to_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct befto_cmd_parms {
-	uint8 llh[2];
-	uint8 befto[4];
-} BWL_POST_PACKED_STRUCT befto_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct srm_cmd_parms {
-	uint8 plh;
-	uint8 srm;
-} BWL_POST_PACKED_STRUCT srm_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct ld_cmd_parms {
-	uint8 ld_aware;
-	uint8 ld[2];
-	uint8 ld_opts;
-	uint8 l_opts;
-} BWL_POST_PACKED_STRUCT ld_cmd_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct eflush_cmd_parms {
-	uint8 llh[2];
-	uint8 packet_type;
-} BWL_POST_PACKED_STRUCT eflush_cmd_parms_t;
-
-/* Generic AMP extended flow spec service types */
-#define EFS_SVCTYPE_NO_TRAFFIC		0
-#define EFS_SVCTYPE_BEST_EFFORT		1
-#define EFS_SVCTYPE_GUARANTEED		2
-
-/* AMP HCI event packet format */
-typedef BWL_PRE_PACKED_STRUCT struct amp_hci_event {
-	uint8 ecode;
-	uint8 plen;
-	uint8 parms[1];
-} BWL_POST_PACKED_STRUCT amp_hci_event_t;
-
-#define HCI_EVT_PREAMBLE_SIZE			OFFSETOF(amp_hci_event_t, parms)
-
-/* AMP HCI event codes */
-#define HCI_Command_Complete			0x0E
-#define HCI_Command_Status			0x0F
-#define HCI_Flush_Occurred			0x11
-#define HCI_Enhanced_Flush_Complete		0x39
-#define HCI_Physical_Link_Complete		0x40
-#define HCI_Channel_Select			0x41
-#define HCI_Disconnect_Physical_Link_Complete	0x42
-#define HCI_Logical_Link_Complete		0x45
-#define HCI_Disconnect_Logical_Link_Complete	0x46
-#define HCI_Flow_Spec_Modify_Complete		0x47
-#define HCI_Number_of_Completed_Data_Blocks	0x48
-#define HCI_Short_Range_Mode_Change_Complete	0x4C
-#define HCI_Status_Change_Event			0x4D
-#define HCI_Vendor_Specific			0xFF
-
-/* AMP HCI event mask bit positions */
-#define HCI_Physical_Link_Complete_Event_Mask			0x0001
-#define HCI_Channel_Select_Event_Mask				0x0002
-#define HCI_Disconnect_Physical_Link_Complete_Event_Mask	0x0004
-#define HCI_Logical_Link_Complete_Event_Mask			0x0020
-#define HCI_Disconnect_Logical_Link_Complete_Event_Mask		0x0040
-#define HCI_Flow_Spec_Modify_Complete_Event_Mask		0x0080
-#define HCI_Number_of_Completed_Data_Blocks_Event_Mask		0x0100
-#define HCI_Short_Range_Mode_Change_Complete_Event_Mask		0x1000
-#define HCI_Status_Change_Event_Mask				0x2000
-#define HCI_All_Event_Mask					0x31e7
-/* AMP HCI event parameters */
-typedef BWL_PRE_PACKED_STRUCT struct cmd_status_parms {
-	uint8 status;
-	uint8 cmdpkts;
-	uint16 opcode;
-} BWL_POST_PACKED_STRUCT cmd_status_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct cmd_complete_parms {
-	uint8 cmdpkts;
-	uint16 opcode;
-	uint8 parms[1];
-} BWL_POST_PACKED_STRUCT cmd_complete_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct flush_occurred_evt_parms {
-	uint16 handle;
-} BWL_POST_PACKED_STRUCT flush_occurred_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct write_remote_evt_parms {
-	uint8 status;
-	uint8 plh;
-} BWL_POST_PACKED_STRUCT write_remote_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct read_local_evt_parms {
-	uint8 status;
-	uint8 plh;
-	uint16 len;
-	uint8 frag[1];
-} BWL_POST_PACKED_STRUCT read_local_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct read_local_info_evt_parms {
-	uint8 status;
-	uint8 AMP_status;
-	uint32 bandwidth;
-	uint32 gbandwidth;
-	uint32 latency;
-	uint32 PDU_size;
-	uint8 ctrl_type;
-	uint16 PAL_cap;
-	uint16 AMP_ASSOC_len;
-	uint32 max_flush_timeout;
-	uint32 be_flush_timeout;
-} BWL_POST_PACKED_STRUCT read_local_info_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct log_link_evt_parms {
-	uint8 status;
-	uint16 llh;
-	uint8 plh;
-	uint8 tx_fs_ID;
-} BWL_POST_PACKED_STRUCT log_link_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct disc_log_link_evt_parms {
-	uint8 status;
-	uint16 llh;
-	uint8 reason;
-} BWL_POST_PACKED_STRUCT disc_log_link_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_evt_parms {
-	uint8 status;
-	uint8 plh;
-	uint8 tx_fs_ID;
-} BWL_POST_PACKED_STRUCT log_link_cancel_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_evt_parms {
-	uint8 status;
-	uint16 llh;
-} BWL_POST_PACKED_STRUCT flow_spec_mod_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct phy_link_evt_parms {
-	uint8 status;
-	uint8 plh;
-} BWL_POST_PACKED_STRUCT phy_link_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_evt_parms {
-	uint8 status;
-	uint8 plh;
-	uint8 reason;
-} BWL_POST_PACKED_STRUCT dis_phy_link_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct read_ls_to_evt_parms {
-	uint8 status;
-	hci_handle_t handle;
-	uint16 timeout;
-} BWL_POST_PACKED_STRUCT read_ls_to_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct read_lla_ca_to_evt_parms {
-	uint8 status;
-	uint16 timeout;
-} BWL_POST_PACKED_STRUCT read_lla_ca_to_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct read_data_block_size_evt_parms {
-	uint8 status;
-	uint16 ACL_pkt_len;
-	uint16 data_block_len;
-	uint16 data_block_num;
-} BWL_POST_PACKED_STRUCT read_data_block_size_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct data_blocks {
-	uint16 handle;
-	uint16 pkts;
-	uint16 blocks;
-} BWL_POST_PACKED_STRUCT data_blocks_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct num_completed_data_blocks_evt_parms {
-	uint16 num_blocks;
-	uint8 num_handles;
-	data_blocks_t completed[1];
-} BWL_POST_PACKED_STRUCT num_completed_data_blocks_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct befto_evt_parms {
-	uint8 status;
-	uint32 befto;
-} BWL_POST_PACKED_STRUCT befto_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct srm_evt_parms {
-	uint8 status;
-	uint8 plh;
-	uint8 srm;
-} BWL_POST_PACKED_STRUCT srm_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct contact_counter_evt_parms {
-	uint8 status;
-	uint8 llh[2];
-	uint16 counter;
-} BWL_POST_PACKED_STRUCT contact_counter_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct contact_counter_reset_evt_parms {
-	uint8 status;
-	uint8 llh[2];
-} BWL_POST_PACKED_STRUCT contact_counter_reset_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct read_linkq_evt_parms {
-	uint8 status;
-	hci_handle_t handle;
-	uint8 link_quality;
-} BWL_POST_PACKED_STRUCT read_linkq_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct ld_evt_parms {
-	uint8 status;
-	uint8 ld_aware;
-	uint8 ld[2];
-	uint8 ld_opts;
-	uint8 l_opts;
-} BWL_POST_PACKED_STRUCT ld_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct eflush_complete_evt_parms {
-	uint16 handle;
-} BWL_POST_PACKED_STRUCT eflush_complete_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct vendor_specific_evt_parms {
-	uint8 len;
-	uint8 parms[1];
-} BWL_POST_PACKED_STRUCT vendor_specific_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct local_version_info_evt_parms {
-	uint8 status;
-	uint8 hci_version;
-	uint16 hci_revision;
-	uint8 pal_version;
-	uint16 mfg_name;
-	uint16 pal_subversion;
-} BWL_POST_PACKED_STRUCT local_version_info_evt_parms_t;
-
-#define MAX_SUPPORTED_CMD_BYTE	64
-typedef BWL_PRE_PACKED_STRUCT struct local_supported_cmd_evt_parms {
-	uint8 status;
-	uint8 cmd[MAX_SUPPORTED_CMD_BYTE];
-} BWL_POST_PACKED_STRUCT local_supported_cmd_evt_parms_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct status_change_evt_parms {
-	uint8 status;
-	uint8 amp_status;
-} BWL_POST_PACKED_STRUCT status_change_evt_parms_t;
-
-/* AMP HCI error codes */
-#define HCI_SUCCESS				0x00
-#define HCI_ERR_ILLEGAL_COMMAND			0x01
-#define HCI_ERR_NO_CONNECTION			0x02
-#define HCI_ERR_MEMORY_FULL			0x07
-#define HCI_ERR_CONNECTION_TIMEOUT		0x08
-#define HCI_ERR_MAX_NUM_OF_CONNECTIONS		0x09
-#define HCI_ERR_CONNECTION_EXISTS		0x0B
-#define HCI_ERR_CONNECTION_DISALLOWED		0x0C
-#define HCI_ERR_CONNECTION_ACCEPT_TIMEOUT	0x10
-#define HCI_ERR_UNSUPPORTED_VALUE		0x11
-#define HCI_ERR_ILLEGAL_PARAMETER_FMT		0x12
-#define HCI_ERR_CONN_TERM_BY_LOCAL_HOST		0x16
-#define HCI_ERR_UNSPECIFIED			0x1F
-#define HCI_ERR_UNIT_KEY_USED			0x26
-#define HCI_ERR_QOS_REJECTED			0x2D
-#define HCI_ERR_PARAM_OUT_OF_RANGE		0x30
-#define HCI_ERR_NO_SUITABLE_CHANNEL		0x39
-#define HCI_ERR_CHANNEL_MOVE			0xFF
-
-/* AMP HCI ACL Data packet format */
-typedef BWL_PRE_PACKED_STRUCT struct amp_hci_ACL_data {
-	uint16	handle;			/* 12-bit connection handle + 2-bit PB and 2-bit BC flags */
-	uint16	dlen;			/* data total length */
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT amp_hci_ACL_data_t;
-
-#define HCI_ACL_DATA_PREAMBLE_SIZE	OFFSETOF(amp_hci_ACL_data_t, data)
-
-#define HCI_ACL_DATA_BC_FLAGS		(0x0 << 14)
-#define HCI_ACL_DATA_PB_FLAGS		(0x3 << 12)
-
-#define HCI_ACL_DATA_HANDLE(handle)	((handle) & 0x0fff)
-#define HCI_ACL_DATA_FLAGS(handle)	((handle) >> 12)
-
-/* AMP Activity Report packet formats */
-typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report {
-	uint8	ScheduleKnown;
-	uint8	NumReports;
-	uint8	data[1];
-} BWL_POST_PACKED_STRUCT amp_hci_activity_report_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report_triple {
-	uint32	StartTime;
-	uint32	Duration;
-	uint32	Periodicity;
-} BWL_POST_PACKED_STRUCT amp_hci_activity_report_triple_t;
-
-#define HCI_AR_SCHEDULE_KNOWN		0x01
-
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif /* _bt_amp_hci_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/eapol.h b/drivers/net/wireless/bcmdhd/include/proto/eapol.h
deleted file mode 100644
index be4ef53..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/eapol.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 802.1x EAPOL definitions
- *
- * See
- * IEEE Std 802.1X-2001
- * IEEE 802.1X RADIUS Usage Guidelines
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- * 
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: eapol.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _eapol_h_
-#define _eapol_h_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-#include <bcmcrypto/aeskeywrap.h>
-
-/* EAPOL for 802.3/Ethernet */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	struct ether_header eth;	/* 802.3/Ethernet header */
-	unsigned char version;		/* EAPOL protocol version */
-	unsigned char type;		/* EAPOL type */
-	unsigned short length;		/* Length of body */
-	unsigned char body[1];		/* Body (optional) */
-} BWL_POST_PACKED_STRUCT eapol_header_t;
-
-#define EAPOL_HEADER_LEN 18
-
-typedef struct {
-	unsigned char version;		/* EAPOL protocol version */
-	unsigned char type;		/* EAPOL type */
-	unsigned short length;		/* Length of body */
-} eapol_hdr_t;
-
-#define EAPOL_HDR_LEN 4
-
-/* EAPOL version */
-#define WPA2_EAPOL_VERSION	2
-#define WPA_EAPOL_VERSION	1
-#define LEAP_EAPOL_VERSION	1
-#define SES_EAPOL_VERSION	1
-
-/* EAPOL types */
-#define EAP_PACKET		0
-#define EAPOL_START		1
-#define EAPOL_LOGOFF		2
-#define EAPOL_KEY		3
-#define EAPOL_ASF		4
-
-/* EAPOL-Key types */
-#define EAPOL_RC4_KEY		1
-#define EAPOL_WPA2_KEY		2	/* 802.11i/WPA2 */
-#define EAPOL_WPA_KEY		254	/* WPA */
-
-/* RC4 EAPOL-Key header field sizes */
-#define EAPOL_KEY_REPLAY_LEN	8
-#define EAPOL_KEY_IV_LEN	16
-#define EAPOL_KEY_SIG_LEN	16
-
-/* RC4 EAPOL-Key */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	unsigned char type;			/* Key Descriptor Type */
-	unsigned short length;			/* Key Length (unaligned) */
-	unsigned char replay[EAPOL_KEY_REPLAY_LEN];	/* Replay Counter */
-	unsigned char iv[EAPOL_KEY_IV_LEN];		/* Key IV */
-	unsigned char index;				/* Key Flags & Index */
-	unsigned char signature[EAPOL_KEY_SIG_LEN];	/* Key Signature */
-	unsigned char key[1];				/* Key (optional) */
-} BWL_POST_PACKED_STRUCT eapol_key_header_t;
-
-#define EAPOL_KEY_HEADER_LEN 	44
-
-/* RC4 EAPOL-Key flags */
-#define EAPOL_KEY_FLAGS_MASK	0x80
-#define EAPOL_KEY_BROADCAST	0
-#define EAPOL_KEY_UNICAST	0x80
-
-/* RC4 EAPOL-Key index */
-#define EAPOL_KEY_INDEX_MASK	0x7f
-
-/* WPA/802.11i/WPA2 EAPOL-Key header field sizes */
-#define EAPOL_WPA_KEY_REPLAY_LEN	8
-#define EAPOL_WPA_KEY_NONCE_LEN		32
-#define EAPOL_WPA_KEY_IV_LEN		16
-#define EAPOL_WPA_KEY_RSC_LEN		8
-#define EAPOL_WPA_KEY_ID_LEN		8
-#define EAPOL_WPA_KEY_MIC_LEN		16
-#define EAPOL_WPA_KEY_DATA_LEN		(EAPOL_WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN)
-#define EAPOL_WPA_MAX_KEY_SIZE		32
-
-/* WPA EAPOL-Key */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	unsigned char type;		/* Key Descriptor Type */
-	unsigned short key_info;	/* Key Information (unaligned) */
-	unsigned short key_len;		/* Key Length (unaligned) */
-	unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN];	/* Replay Counter */
-	unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN];	/* Nonce */
-	unsigned char iv[EAPOL_WPA_KEY_IV_LEN];		/* Key IV */
-	unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN];	/* Key RSC */
-	unsigned char id[EAPOL_WPA_KEY_ID_LEN];		/* WPA:Key ID, 802.11i/WPA2: Reserved */
-	unsigned char mic[EAPOL_WPA_KEY_MIC_LEN];	/* Key MIC */
-	unsigned short data_len;			/* Key Data Length */
-	unsigned char data[EAPOL_WPA_KEY_DATA_LEN];	/* Key data */
-} BWL_POST_PACKED_STRUCT eapol_wpa_key_header_t;
-
-#define EAPOL_WPA_KEY_LEN 		95
-
-/* WPA/802.11i/WPA2 KEY KEY_INFO bits */
-#define WPA_KEY_DESC_OSEN	0x0
-#define WPA_KEY_DESC_V1		0x01
-#define WPA_KEY_DESC_V2		0x02
-#define WPA_KEY_DESC_V3		0x03
-#define WPA_KEY_PAIRWISE	0x08
-#define WPA_KEY_INSTALL		0x40
-#define WPA_KEY_ACK		0x80
-#define WPA_KEY_MIC		0x100
-#define WPA_KEY_SECURE		0x200
-#define WPA_KEY_ERROR		0x400
-#define WPA_KEY_REQ		0x800
-
-#define WPA_KEY_DESC_V2_OR_V3 WPA_KEY_DESC_V2
-
-/* WPA-only KEY KEY_INFO bits */
-#define WPA_KEY_INDEX_0		0x00
-#define WPA_KEY_INDEX_1		0x10
-#define WPA_KEY_INDEX_2		0x20
-#define WPA_KEY_INDEX_3		0x30
-#define WPA_KEY_INDEX_MASK	0x30
-#define WPA_KEY_INDEX_SHIFT	0x04
-
-/* 802.11i/WPA2-only KEY KEY_INFO bits */
-#define WPA_KEY_ENCRYPTED_DATA	0x1000
-
-/* Key Data encapsulation */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint8 type;
-	uint8 length;
-	uint8 oui[3];
-	uint8 subtype;
-	uint8 data[1];
-} BWL_POST_PACKED_STRUCT eapol_wpa2_encap_data_t;
-
-#define EAPOL_WPA2_ENCAP_DATA_HDR_LEN 	6
-
-#define WPA2_KEY_DATA_SUBTYPE_GTK	1
-#define WPA2_KEY_DATA_SUBTYPE_STAKEY	2
-#define WPA2_KEY_DATA_SUBTYPE_MAC	3
-#define WPA2_KEY_DATA_SUBTYPE_PMKID	4
-#define WPA2_KEY_DATA_SUBTYPE_IGTK	9
-
-/* GTK encapsulation */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint8	flags;
-	uint8	reserved;
-	uint8	gtk[EAPOL_WPA_MAX_KEY_SIZE];
-} BWL_POST_PACKED_STRUCT eapol_wpa2_key_gtk_encap_t;
-
-#define EAPOL_WPA2_KEY_GTK_ENCAP_HDR_LEN 	2
-
-#define WPA2_GTK_INDEX_MASK	0x03
-#define WPA2_GTK_INDEX_SHIFT	0x00
-
-#define WPA2_GTK_TRANSMIT	0x04
-
-/* IGTK encapsulation */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint16	key_id;
-	uint8	ipn[6];
-	uint8	key[EAPOL_WPA_MAX_KEY_SIZE];
-} BWL_POST_PACKED_STRUCT eapol_wpa2_key_igtk_encap_t;
-
-#define EAPOL_WPA2_KEY_IGTK_ENCAP_HDR_LEN 	8
-
-/* STAKey encapsulation */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint8	reserved[2];
-	uint8	mac[ETHER_ADDR_LEN];
-	uint8	stakey[EAPOL_WPA_MAX_KEY_SIZE];
-} BWL_POST_PACKED_STRUCT eapol_wpa2_key_stakey_encap_t;
-
-#define WPA2_KEY_DATA_PAD	0xdd
-
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif /* _eapol_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/ethernet.h b/drivers/net/wireless/bcmdhd/include/proto/ethernet.h
deleted file mode 100644
index 022fee4..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/ethernet.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: ethernet.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _NET_ETHERNET_H_	/* use native BSD ethernet.h when available */
-#define _NET_ETHERNET_H_
-
-#ifndef _TYPEDEFS_H_
-#include "typedefs.h"
-#endif
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-
-/*
- * The number of bytes in an ethernet (MAC) address.
- */
-#define	ETHER_ADDR_LEN		6
-
-/*
- * The number of bytes in the type field.
- */
-#define	ETHER_TYPE_LEN		2
-
-/*
- * The number of bytes in the trailing CRC field.
- */
-#define	ETHER_CRC_LEN		4
-
-/*
- * The length of the combined header.
- */
-#define	ETHER_HDR_LEN		(ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
-
-/*
- * The minimum packet length.
- */
-#define	ETHER_MIN_LEN		64
-
-/*
- * The minimum packet user data length.
- */
-#define	ETHER_MIN_DATA		46
-
-/*
- * The maximum packet length.
- */
-#define	ETHER_MAX_LEN		1518
-
-/*
- * The maximum packet user data length.
- */
-#define	ETHER_MAX_DATA		1500
-
-/* ether types */
-#define ETHER_TYPE_MIN		0x0600		/* Anything less than MIN is a length */
-#define	ETHER_TYPE_IP		0x0800		/* IP */
-#define ETHER_TYPE_ARP		0x0806		/* ARP */
-#define ETHER_TYPE_8021Q	0x8100		/* 802.1Q */
-#define	ETHER_TYPE_IPV6		0x86dd		/* IPv6 */
-#define	ETHER_TYPE_BRCM		0x886c		/* Broadcom Corp. */
-#define	ETHER_TYPE_802_1X	0x888e		/* 802.1x */
-#define	ETHER_TYPE_802_1X_PREAUTH 0x88c7	/* 802.1x preauthentication */
-#define ETHER_TYPE_WAI		0x88b4		/* WAI */
-#define ETHER_TYPE_89_0D	0x890d		/* 89-0d frame for TDLS */
-#define ETHER_TYPE_RRB		ETHER_TYPE_89_0D  /* RRB 802.11r 2008 */
-
-#define ETHER_TYPE_PPP_SES	0x8864		/* PPPoE Session */
-
-#define ETHER_TYPE_IAPP_L2_UPDATE	0x6	/* IAPP L2 update frame */
-
-/* Broadcom subtype follows ethertype;  First 2 bytes are reserved; Next 2 are subtype; */
-#define	ETHER_BRCM_SUBTYPE_LEN	4	/* Broadcom 4 byte subtype */
-
-/* ether header */
-#define ETHER_DEST_OFFSET	(0 * ETHER_ADDR_LEN)	/* dest address offset */
-#define ETHER_SRC_OFFSET	(1 * ETHER_ADDR_LEN)	/* src address offset */
-#define ETHER_TYPE_OFFSET	(2 * ETHER_ADDR_LEN)	/* ether type offset */
-
-/*
- * A macro to validate a length with
- */
-#define	ETHER_IS_VALID_LEN(foo)	\
-	((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
-
-#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) {		\
-		((uint8 *)ea)[0] = 0x01;			\
-		((uint8 *)ea)[1] = 0x00;			\
-		((uint8 *)ea)[2] = 0x5e;			\
-		((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f;	\
-		((uint8 *)ea)[4] = ((mgrp_ip) >>  8) & 0xff;	\
-		((uint8 *)ea)[5] = ((mgrp_ip) >>  0) & 0xff;	\
-}
-
-#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */
-/*
- * Structure of a 10Mb/s Ethernet header.
- */
-BWL_PRE_PACKED_STRUCT struct ether_header {
-	uint8	ether_dhost[ETHER_ADDR_LEN];
-	uint8	ether_shost[ETHER_ADDR_LEN];
-	uint16	ether_type;
-} BWL_POST_PACKED_STRUCT;
-
-/*
- * Structure of a 48-bit Ethernet address.
- */
-BWL_PRE_PACKED_STRUCT struct	ether_addr {
-	uint8 octet[ETHER_ADDR_LEN];
-} BWL_POST_PACKED_STRUCT;
-#endif	/* !__INCif_etherh Quick and ugly hack for VxWorks */
-
-/*
- * Takes a pointer, set, test, clear, toggle locally admininistered
- * address bit in the 48-bit Ethernet address.
- */
-#define ETHER_SET_LOCALADDR(ea)	(((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2))
-#define ETHER_IS_LOCALADDR(ea) 	(((uint8 *)(ea))[0] & 2)
-#define ETHER_CLR_LOCALADDR(ea)	(((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd))
-#define ETHER_TOGGLE_LOCALADDR(ea)	(((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2))
-
-/* Takes a pointer, marks unicast address bit in the MAC address */
-#define ETHER_SET_UNICAST(ea)	(((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1))
-
-/*
- * Takes a pointer, returns true if a 48-bit multicast address
- * (including broadcast, since it is all ones)
- */
-#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1)
-
-
-/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */
-#define eacmp(a, b)	((((const uint16 *)(a))[0] ^ ((const uint16 *)(b))[0]) | \
-	                 (((const uint16 *)(a))[1] ^ ((const uint16 *)(b))[1]) | \
-	                 (((const uint16 *)(a))[2] ^ ((const uint16 *)(b))[2]))
-
-#define	ether_cmp(a, b)	eacmp(a, b)
-
-/* copy an ethernet address - assumes the pointers can be referenced as shorts */
-#define eacopy(s, d) \
-do { \
-	((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \
-	((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \
-	((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \
-} while (0)
-
-#define	ether_copy(s, d) eacopy(s, d)
-
-/* Copy an ethernet address in reverse order */
-#define	ether_rcopy(s, d) \
-do { \
-	((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \
-	((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \
-	((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \
-} while (0)
-
-/* Copy 14B ethernet header: 32bit aligned source and destination. */
-#define ehcopy32(s, d) \
-do { \
-	((uint32 *)(d))[0] = ((const uint32 *)(s))[0]; \
-	((uint32 *)(d))[1] = ((const uint32 *)(s))[1]; \
-	((uint32 *)(d))[2] = ((const uint32 *)(s))[2]; \
-	((uint16 *)(d))[6] = ((const uint16 *)(s))[6]; \
-} while (0)
-
-
-static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
-static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}};
-static const struct ether_addr ether_ipv6_mcast = {{0x33, 0x33, 0x00, 0x00, 0x00, 0x01}};
-
-#define ETHER_ISBCAST(ea)	((((const uint8 *)(ea))[0] &		\
-	                          ((const uint8 *)(ea))[1] &		\
-				  ((const uint8 *)(ea))[2] &		\
-				  ((const uint8 *)(ea))[3] &		\
-				  ((const uint8 *)(ea))[4] &		\
-				  ((const uint8 *)(ea))[5]) == 0xff)
-#define ETHER_ISNULLADDR(ea)	((((const uint8 *)(ea))[0] |		\
-				  ((const uint8 *)(ea))[1] |		\
-				  ((const uint8 *)(ea))[2] |		\
-				  ((const uint8 *)(ea))[3] |		\
-				  ((const uint8 *)(ea))[4] |		\
-				  ((const uint8 *)(ea))[5]) == 0)
-
-#define ETHER_ISNULLDEST(da)	((((const uint16 *)(da))[0] |           \
-				  ((const uint16 *)(da))[1] |           \
-				  ((const uint16 *)(da))[2]) == 0)
-#define ETHER_ISNULLSRC(sa)	ETHER_ISNULLDEST(sa)
-
-#define ETHER_MOVE_HDR(d, s) \
-do { \
-	struct ether_header t; \
-	t = *(struct ether_header *)(s); \
-	*(struct ether_header *)(d) = t; \
-} while (0)
-
-#define  ETHER_ISUCAST(ea) ((((uint8 *)(ea))[0] & 0x01) == 0)
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif /* _NET_ETHERNET_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/event_log_set.h b/drivers/net/wireless/bcmdhd/include/proto/event_log_set.h
deleted file mode 100644
index 910cbcf..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/event_log_set.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * EVENT_LOG system definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: event_log.h 241182 2011-02-17 21:50:03Z $
- */
-
-#ifndef _EVENT_LOG_SET_H_
-#define _EVENT_LOG_SET_H_
-
-/* Set a maximum number of sets here.  It is not dynamic for
- *  efficiency of the EVENT_LOG calls.
- */
-#define NUM_EVENT_LOG_SETS 8
-
-/* Define new event log sets here */
-#define EVENT_LOG_SET_BUS	0
-#define EVENT_LOG_SET_WL	1
-#define EVENT_LOG_SET_PSM	2
-#define EVENT_LOG_SET_ERROR	3
-#define EVENT_LOG_SET_MEM_API	4
-
-#endif /* _EVENT_LOG_SET_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/event_log_tag.h b/drivers/net/wireless/bcmdhd/include/proto/event_log_tag.h
deleted file mode 100644
index 25acbc7..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/event_log_tag.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * EVENT_LOG system definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: event_log.h 241182 2011-02-17 21:50:03Z $
- */
-
-#ifndef _EVENT_LOG_TAG_H_
-#define _EVENT_LOG_TAG_H_
-
-#include <typedefs.h>
-
-/* Define new event log tags here */
-#define EVENT_LOG_TAG_NULL	0	/* Special null tag */
-#define EVENT_LOG_TAG_TS	1	/* Special timestamp tag */
-#define EVENT_LOG_TAG_BUS_OOB	2
-#define EVENT_LOG_TAG_BUS_STATE	3
-#define EVENT_LOG_TAG_BUS_PROTO	4
-#define EVENT_LOG_TAG_BUS_CTL	5
-#define EVENT_LOG_TAG_BUS_EVENT	6
-#define EVENT_LOG_TAG_BUS_PKT	7
-#define EVENT_LOG_TAG_BUS_FRAME	8
-#define EVENT_LOG_TAG_BUS_DESC	9
-#define EVENT_LOG_TAG_BUS_SETUP	10
-#define EVENT_LOG_TAG_BUS_MISC	11
-#define EVENT_LOG_TAG_SRSCAN		22
-#define EVENT_LOG_TAG_PWRSTATS_INFO	23
-#define EVENT_LOG_TAG_UCODE_WATCHDOG 26
-#define EVENT_LOG_TAG_UCODE_FIFO 27
-#define EVENT_LOG_TAG_SCAN_TRACE_LOW	28
-#define EVENT_LOG_TAG_SCAN_TRACE_HIGH	29
-#define EVENT_LOG_TAG_SCAN_ERROR	30
-#define EVENT_LOG_TAG_SCAN_WARN	31
-#define EVENT_LOG_TAG_MPF_ERR	32
-#define EVENT_LOG_TAG_MPF_WARN	33
-#define EVENT_LOG_TAG_MPF_INFO	34
-#define EVENT_LOG_TAG_MPF_DEBUG	35
-#define EVENT_LOG_TAG_EVENT_INFO	36
-#define EVENT_LOG_TAG_EVENT_ERR	37
-#define EVENT_LOG_TAG_PWRSTATS_ERROR	38
-#define EVENT_LOG_TAG_EXCESS_PM_ERROR	39
-#define EVENT_LOG_TAG_IOCTL_LOG			40
-#define EVENT_LOG_TAG_PFN_ERR	41
-#define EVENT_LOG_TAG_PFN_WARN	42
-#define EVENT_LOG_TAG_PFN_INFO	43
-#define EVENT_LOG_TAG_PFN_DEBUG	44
-#define EVENT_LOG_TAG_BEACON_LOG	45
-#define EVENT_LOG_TAG_WNM_BSSTRANS_INFO 46
-#define EVENT_LOG_TAG_TRACE_CHANSW 47
-#define EVENT_LOG_TAG_PCI_ERROR	48
-#define EVENT_LOG_TAG_PCI_TRACE	49
-#define EVENT_LOG_TAG_PCI_WARN	50
-#define EVENT_LOG_TAG_PCI_INFO	51
-#define EVENT_LOG_TAG_PCI_DBG	52
-#define EVENT_LOG_TAG_PCI_DATA  53
-#define EVENT_LOG_TAG_PCI_RING	54
-#define EVENT_LOG_TAG_AWDL_TRACE_RANGING	55
-#define EVENT_LOG_TAG_WL_ERROR		56
-#define EVENT_LOG_TAG_PHY_ERROR		57
-#define EVENT_LOG_TAG_OTP_ERROR		58
-#define EVENT_LOG_TAG_NOTIF_ERROR	59
-#define EVENT_LOG_TAG_MPOOL_ERROR	60
-#define EVENT_LOG_TAG_OBJR_ERROR	61
-#define EVENT_LOG_TAG_DMA_ERROR		62
-#define EVENT_LOG_TAG_PMU_ERROR		63
-#define EVENT_LOG_TAG_BSROM_ERROR	64
-#define EVENT_LOG_TAG_SI_ERROR		65
-#define EVENT_LOG_TAG_ROM_PRINTF	66
-#define EVENT_LOG_TAG_RATE_CNT		67
-#define EVENT_LOG_TAG_CTL_MGT_CNT	68
-#define EVENT_LOG_TAG_AMPDU_DUMP	69
-#define EVENT_LOG_TAG_MEM_ALLOC_SUCC	70
-#define EVENT_LOG_TAG_MEM_ALLOC_FAIL	71
-#define EVENT_LOG_TAG_MEM_FREE		72
-#define EVENT_LOG_TAG_WL_ASSOC_LOG	73
-#define EVENT_LOG_TAG_WL_PS_LOG		74
-#define EVENT_LOG_TAG_WL_ROAM_LOG	75
-#define EVENT_LOG_TAG_WL_MPC_LOG	76
-#define EVENT_LOG_TAG_WL_WSEC_LOG	77
-#define EVENT_LOG_TAG_WL_WSEC_DUMP	78
-#define EVENT_LOG_TAG_WL_MCNX_LOG	79
-#define EVENT_LOG_TAG_HEALTH_CHECK_ERROR 80
-#define EVENT_LOG_TAG_HNDRTE_EVENT_ERROR 81
-#define EVENT_LOG_TAG_ECOUNTERS_ERROR	82
-#define EVENT_LOG_TAG_WL_COUNTERS	83
-#define EVENT_LOG_TAG_ECOUNTERS_IPCSTATS	84
-#define EVENT_LOG_TAG_WL_P2P_LOG            85
-#define EVENT_LOG_TAG_SDIO_ERROR		86
-#define EVENT_LOG_TAG_SDIO_TRACE		87
-#define EVENT_LOG_TAG_SDIO_DBG          88
-#define EVENT_LOG_TAG_SDIO_PRHDRS		89
-#define EVENT_LOG_TAG_SDIO_PRPKT		90
-#define EVENT_LOG_TAG_SDIO_INFORM		91
-#define EVENT_LOG_TAG_MIMO_PS_ERROR	92
-#define EVENT_LOG_TAG_MIMO_PS_TRACE	93
-#define EVENT_LOG_TAG_MIMO_PS_INFO	94
-#define EVENT_LOG_TAG_BTCX_STATS	95
-#define EVENT_LOG_TAG_LEAKY_AP_STATS	96
-#define EVENT_LOG_TAG_AWDL_TRACE_ELECTION	97
-#define EVENT_LOG_TAG_MIMO_PS_STATS	98
-#define EVENT_LOG_TAG_PWRSTATS_PHY	99
-#define EVENT_LOG_TAG_PWRSTATS_SCAN	100
-#define EVENT_LOG_TAG_PWRSTATS_AWDL	101
-#define EVENT_LOG_TAG_PWRSTATS_WAKE_V2	102
-#define EVENT_LOG_TAG_LQM		103
-#define EVENT_LOG_TAG_TRACE_WL_INFO	104
-#define EVENT_LOG_TAG_TRACE_BTCOEX_INFO	105
-#define EVENT_LOG_TAG_MAX		105 /* Set to the same value of last tag, not last tag + 1 */
-/* Note: New event should be added/reserved in trunk before adding it to branches */
-
-
-#define	SD_PRHDRS(i, s, h, p, n, l)
-#define	SD_PRPKT(m, b, n)
-#define	SD_INFORM(args)
-
-/* Flags for tag control */
-#define EVENT_LOG_TAG_FLAG_NONE		0
-#define EVENT_LOG_TAG_FLAG_LOG		0x80
-#define EVENT_LOG_TAG_FLAG_PRINT	0x40
-#define EVENT_LOG_TAG_FLAG_SET_MASK	0x3f
-
-/* Each event log entry has a type.  The type is the LAST word of the
- * event log.  The printing code walks the event entries in reverse
- * order to find the first entry.
- */
-typedef union event_log_hdr {
-	struct {
-		uint8 tag;		/* Event_log entry tag */
-		uint8 count;		/* Count of 4-byte entries */
-		uint16 fmt_num;		/* Format number */
-	};
-	uint32 t;			/* Type cheat */
-} event_log_hdr_t;
-
-#endif /* _EVENT_LOG_TAG_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/p2p.h b/drivers/net/wireless/bcmdhd/include/proto/p2p.h
deleted file mode 100644
index 91f5147..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/p2p.h
+++ /dev/null
@@ -1,713 +0,0 @@
-/*
- * Fundamental types and constants relating to WFA P2P (aka WiFi Direct)
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: p2p.h 536785 2015-02-24 08:35:00Z $
- */
-
-#ifndef _P2P_H_
-#define _P2P_H_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-#include <wlioctl.h>
-#include <proto/802.11.h>
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-
-/* WiFi P2P OUI values */
-#define P2P_OUI			WFA_OUI			/* WiFi P2P OUI */
-#define P2P_VER			WFA_OUI_TYPE_P2P	/* P2P version: 9=WiFi P2P v1.0 */
-
-#define P2P_IE_ID		0xdd			/* P2P IE element ID */
-
-/* WiFi P2P IE */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_ie {
-	uint8	id;		/* IE ID: 0xDD */
-	uint8	len;		/* IE length */
-	uint8	OUI[3];		/* WiFi P2P specific OUI: P2P_OUI */
-	uint8	oui_type;	/* Identifies P2P version: P2P_VER */
-	uint8	subelts[1];	/* variable length subelements */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_ie wifi_p2p_ie_t;
-
-#define P2P_IE_FIXED_LEN	6
-
-#define P2P_ATTR_ID_OFF		0
-#define P2P_ATTR_LEN_OFF	1
-#define P2P_ATTR_DATA_OFF	3
-
-#define P2P_ATTR_ID_LEN		1	/* ID filed length */
-#define P2P_ATTR_LEN_LEN	2	/* length field length */
-#define P2P_ATTR_HDR_LEN	3 /* ID + 2-byte length field spec 1.02 */
-
-#define P2P_WFDS_HASH_LEN		6
-#define P2P_WFDS_MAX_SVC_NAME_LEN	32
-
-/* P2P IE Subelement IDs from WiFi P2P Technical Spec 1.00 */
-#define P2P_SEID_STATUS			0	/* Status */
-#define P2P_SEID_MINOR_RC		1	/* Minor Reason Code */
-#define P2P_SEID_P2P_INFO		2	/* P2P Capability (capabilities info) */
-#define P2P_SEID_DEV_ID			3	/* P2P Device ID */
-#define P2P_SEID_INTENT			4	/* Group Owner Intent */
-#define P2P_SEID_CFG_TIMEOUT		5	/* Configuration Timeout */
-#define P2P_SEID_CHANNEL		6	/* Listen channel */
-#define P2P_SEID_GRP_BSSID		7	/* P2P Group BSSID */
-#define P2P_SEID_XT_TIMING		8	/* Extended Listen Timing */
-#define P2P_SEID_INTINTADDR		9	/* Intended P2P Interface Address */
-#define P2P_SEID_P2P_MGBTY		10	/* P2P Manageability */
-#define P2P_SEID_CHAN_LIST		11	/* Channel List */
-#define P2P_SEID_ABSENCE		12	/* Notice of Absence */
-#define P2P_SEID_DEV_INFO		13	/* Device Info */
-#define P2P_SEID_GROUP_INFO		14	/* Group Info */
-#define P2P_SEID_GROUP_ID		15	/* Group ID */
-#define P2P_SEID_P2P_IF			16	/* P2P Interface */
-#define P2P_SEID_OP_CHANNEL		17	/* Operating Channel */
-#define P2P_SEID_INVITE_FLAGS		18	/* Invitation Flags */
-#define P2P_SEID_SERVICE_HASH		21	/* Service hash */
-#define P2P_SEID_SESSION		22	/* Session information */
-#define P2P_SEID_CONNECT_CAP		23	/* Connection capability */
-#define P2P_SEID_ADVERTISE_ID		24	/* Advertisement ID */
-#define P2P_SEID_ADVERTISE_SERVICE	25	/* Advertised service */
-#define P2P_SEID_SESSION_ID		26	/* Session ID */
-#define P2P_SEID_FEATURE_CAP		27	/* Feature capability */
-#define	P2P_SEID_PERSISTENT_GROUP	28	/* Persistent group */
-#define P2P_SEID_SESSION_INFO_RESP	29	/* Session Information Response */
-#define P2P_SEID_VNDR			221	/* Vendor-specific subelement */
-
-#define P2P_SE_VS_ID_SERVICES	0x1b
-
-
-/* WiFi P2P IE subelement: P2P Capability (capabilities info) */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_info_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_P2P_INFO */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	dev;		/* Device Capability Bitmap */
-	uint8	group;		/* Group Capability Bitmap */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_info_se_s wifi_p2p_info_se_t;
-
-/* P2P Capability subelement's Device Capability Bitmap bit values */
-#define P2P_CAPSE_DEV_SERVICE_DIS	0x1 /* Service Discovery */
-#define P2P_CAPSE_DEV_CLIENT_DIS	0x2 /* Client Discoverability */
-#define P2P_CAPSE_DEV_CONCURRENT	0x4 /* Concurrent Operation */
-#define P2P_CAPSE_DEV_INFRA_MAN		0x8 /* P2P Infrastructure Managed */
-#define P2P_CAPSE_DEV_LIMIT			0x10 /* P2P Device Limit */
-#define P2P_CAPSE_INVITE_PROC		0x20 /* P2P Invitation Procedure */
-
-/* P2P Capability subelement's Group Capability Bitmap bit values */
-#define P2P_CAPSE_GRP_OWNER			0x1 /* P2P Group Owner */
-#define P2P_CAPSE_PERSIST_GRP		0x2 /* Persistent P2P Group */
-#define P2P_CAPSE_GRP_LIMIT			0x4 /* P2P Group Limit */
-#define P2P_CAPSE_GRP_INTRA_BSS		0x8 /* Intra-BSS Distribution */
-#define P2P_CAPSE_GRP_X_CONNECT		0x10 /* Cross Connection */
-#define P2P_CAPSE_GRP_PERSISTENT	0x20 /* Persistent Reconnect */
-#define P2P_CAPSE_GRP_FORMATION		0x40 /* Group Formation */
-
-
-/* WiFi P2P IE subelement: Group Owner Intent */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_intent_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_INTENT */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	intent;		/* Intent Value 0...15 (0=legacy 15=master only) */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_intent_se_s wifi_p2p_intent_se_t;
-
-/* WiFi P2P IE subelement: Configuration Timeout */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_cfg_tmo_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_CFG_TIMEOUT */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	go_tmo;		/* GO config timeout in units of 10 ms */
-	uint8	client_tmo;	/* Client config timeout in units of 10 ms */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_cfg_tmo_se_s wifi_p2p_cfg_tmo_se_t;
-
-/* WiFi P2P IE subelement: Listen Channel */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_listen_channel_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_CHANNEL */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	country[3];	/* Country String */
-	uint8	op_class;	/* Operating Class */
-	uint8	channel;	/* Channel */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_listen_channel_se_s wifi_p2p_listen_channel_se_t;
-
-/* WiFi P2P IE subelement: P2P Group BSSID */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_bssid_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_GRP_BSSID */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	mac[6];		/* P2P group bssid */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_grp_bssid_se_s wifi_p2p_grp_bssid_se_t;
-
-/* WiFi P2P IE subelement: P2P Group ID */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_id_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_GROUP_ID */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	mac[6];		/* P2P device address */
-	uint8	ssid[1];	/* ssid. device id. variable length */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_grp_id_se_s wifi_p2p_grp_id_se_t;
-
-/* WiFi P2P IE subelement: P2P Interface */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_intf_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_P2P_IF */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	mac[6];		/* P2P device address */
-	uint8	ifaddrs;	/* P2P Interface Address count */
-	uint8	ifaddr[1][6];	/* P2P Interface Address list */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_intf_se_s wifi_p2p_intf_se_t;
-
-/* WiFi P2P IE subelement: Status */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_status_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_STATUS */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	status;		/* Status Code: P2P_STATSE_* */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_status_se_s wifi_p2p_status_se_t;
-
-/* Status subelement Status Code definitions */
-#define P2P_STATSE_SUCCESS			0
-				/* Success */
-#define P2P_STATSE_FAIL_INFO_CURR_UNAVAIL	1
-				/* Failed, information currently unavailable */
-#define P2P_STATSE_PASSED_UP			P2P_STATSE_FAIL_INFO_CURR_UNAVAIL
-				/* Old name for above in P2P spec 1.08 and older */
-#define P2P_STATSE_FAIL_INCOMPAT_PARAMS		2
-				/* Failed, incompatible parameters */
-#define P2P_STATSE_FAIL_LIMIT_REACHED		3
-				/* Failed, limit reached */
-#define P2P_STATSE_FAIL_INVALID_PARAMS		4
-				/* Failed, invalid parameters */
-#define P2P_STATSE_FAIL_UNABLE_TO_ACCOM		5
-				/* Failed, unable to accomodate request */
-#define P2P_STATSE_FAIL_PROTO_ERROR		6
-				/* Failed, previous protocol error or disruptive behaviour */
-#define P2P_STATSE_FAIL_NO_COMMON_CHAN		7
-				/* Failed, no common channels */
-#define P2P_STATSE_FAIL_UNKNOWN_GROUP		8
-				/* Failed, unknown P2P Group */
-#define P2P_STATSE_FAIL_INTENT			9
-				/* Failed, both peers indicated Intent 15 in GO Negotiation */
-#define P2P_STATSE_FAIL_INCOMPAT_PROVIS		10
-				/* Failed, incompatible provisioning method */
-#define P2P_STATSE_FAIL_USER_REJECT		11
-				/* Failed, rejected by user */
-#define P2P_STATSE_SUCCESS_USER_ACCEPT		12
-				/* Success, accepted by user */
-
-/* WiFi P2P IE attribute: Extended Listen Timing */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_ext_se_s {
-	uint8	eltId;		/* ID: P2P_SEID_EXT_TIMING */
-	uint8	len[2];		/* length not including eltId, len fields */
-	uint8	avail[2];	/* availibility period */
-	uint8	interval[2];	/* availibility interval */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_ext_se_s wifi_p2p_ext_se_t;
-
-#define P2P_EXT_MIN	10	/* minimum 10ms */
-
-/* WiFi P2P IE subelement: Intended P2P Interface Address */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_intintad_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_INTINTADDR */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	mac[6];		/* intended P2P interface MAC address */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_intintad_se_s wifi_p2p_intintad_se_t;
-
-/* WiFi P2P IE subelement: Channel */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_channel_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_STATUS */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	band;		/* Regulatory Class (band) */
-	uint8	channel;	/* Channel */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_channel_se_s wifi_p2p_channel_se_t;
-
-
-/* Channel Entry structure within the Channel List SE */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_entry_s {
-	uint8	band;						/* Regulatory Class (band) */
-	uint8	num_channels;				/* # of channels in the channel list */
-	uint8	channels[WL_NUMCHANNELS];	/* Channel List */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_chanlist_entry_s wifi_p2p_chanlist_entry_t;
-#define WIFI_P2P_CHANLIST_SE_MAX_ENTRIES 2
-
-/* WiFi P2P IE subelement: Channel List */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_CHAN_LIST */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	country[3];	/* Country String */
-	uint8	num_entries;	/* # of channel entries */
-	wifi_p2p_chanlist_entry_t	entries[WIFI_P2P_CHANLIST_SE_MAX_ENTRIES];
-						/* Channel Entry List */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_chanlist_se_s wifi_p2p_chanlist_se_t;
-
-/* WiFi Primary Device Type structure */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_pri_devtype_s {
-	uint16	cat_id;		/* Category ID */
-	uint8	OUI[3];		/* WFA OUI: 0x0050F2 */
-	uint8	oui_type;	/* WPS_OUI_TYPE */
-	uint16	sub_cat_id;	/* Sub Category ID */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_pri_devtype_s wifi_p2p_pri_devtype_t;
-
-/* WiFi P2P Device Info Sub Element Primary Device Type Sub Category
- * maximum values for each category
- */
-#define P2P_DISE_SUBCATEGORY_MINVAL		1
-#define P2P_DISE_CATEGORY_COMPUTER		1
-#define P2P_DISE_SUBCATEGORY_COMPUTER_MAXVAL		8
-#define P2P_DISE_CATEGORY_INPUT_DEVICE		2
-#define P2P_DISE_SUBCATEGORY_INPUT_DEVICE_MAXVAL	9
-#define P2P_DISE_CATEGORY_PRINTER		3
-#define P2P_DISE_SUBCATEGORY_PRINTER_MAXVAL		5
-#define P2P_DISE_CATEGORY_CAMERA		4
-#define P2P_DISE_SUBCATEGORY_CAMERA_MAXVAL		4
-#define P2P_DISE_CATEGORY_STORAGE		5
-#define P2P_DISE_SUBCATEGORY_STORAGE_MAXVAL		1
-#define P2P_DISE_CATEGORY_NETWORK_INFRA		6
-#define P2P_DISE_SUBCATEGORY_NETWORK_INFRA_MAXVAL	4
-#define P2P_DISE_CATEGORY_DISPLAY		7
-#define P2P_DISE_SUBCATEGORY_DISPLAY_MAXVAL		4
-#define P2P_DISE_CATEGORY_MULTIMEDIA		8
-#define P2P_DISE_SUBCATEGORY_MULTIMEDIA_MAXVAL		6
-#define P2P_DISE_CATEGORY_GAMING		9
-#define P2P_DISE_SUBCATEGORY_GAMING_MAXVAL		5
-#define P2P_DISE_CATEGORY_TELEPHONE		10
-#define P2P_DISE_SUBCATEGORY_TELEPHONE_MAXVAL		5
-#define P2P_DISE_CATEGORY_AUDIO			11
-#define P2P_DISE_SUBCATEGORY_AUDIO_MAXVAL		6
-
-/* WiFi P2P IE's Device Info subelement */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_devinfo_se_s {
-	uint8	eltId;			/* SE ID: P2P_SEID_DEVINFO */
-	uint8	len[2];			/* SE length not including eltId, len fields */
-	uint8	mac[6];			/* P2P Device MAC address */
-	uint16	wps_cfg_meths;		/* Config Methods: reg_prototlv.h WPS_CONFMET_* */
-	uint8	pri_devtype[8];		/* Primary Device Type */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_devinfo_se_s wifi_p2p_devinfo_se_t;
-
-#define P2P_DEV_TYPE_LEN	8
-
-/* WiFi P2P IE's Group Info subelement Client Info Descriptor */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_cid_fixed_s {
-	uint8	len;
-	uint8	devaddr[ETHER_ADDR_LEN];	/* P2P Device Address */
-	uint8	ifaddr[ETHER_ADDR_LEN];		/* P2P Interface Address */
-	uint8	devcap;				/* Device Capability */
-	uint8	cfg_meths[2];			/* Config Methods: reg_prototlv.h WPS_CONFMET_* */
-	uint8	pridt[P2P_DEV_TYPE_LEN];	/* Primary Device Type */
-	uint8	secdts;				/* Number of Secondary Device Types */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_cid_fixed_s wifi_p2p_cid_fixed_t;
-
-/* WiFi P2P IE's Device ID subelement */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_devid_se_s {
-	uint8	eltId;
-	uint8	len[2];
-	struct ether_addr	addr;			/* P2P Device MAC address */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_devid_se_s wifi_p2p_devid_se_t;
-
-/* WiFi P2P IE subelement: P2P Manageability */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_mgbt_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_P2P_MGBTY */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	mg_bitmap;	/* manageability bitmap */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_mgbt_se_s wifi_p2p_mgbt_se_t;
-/* mg_bitmap field bit values */
-#define P2P_MGBTSE_P2PDEVMGMT_FLAG   0x1 /* AP supports Managed P2P Device */
-
-/* WiFi P2P IE subelement: Group Info */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_grpinfo_se_s {
-	uint8	eltId;			/* SE ID: P2P_SEID_GROUP_INFO */
-	uint8	len[2];			/* SE length not including eltId, len fields */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_grpinfo_se_s wifi_p2p_grpinfo_se_t;
-
-/* WiFi IE subelement: Operating Channel */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_op_channel_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_OP_CHANNEL */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	country[3];	/* Country String */
-	uint8	op_class;	/* Operating Class */
-	uint8	channel;	/* Channel */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_op_channel_se_s wifi_p2p_op_channel_se_t;
-
-/* WiFi IE subelement: INVITATION FLAGS */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_invite_flags_se_s {
-	uint8	eltId;		/* SE ID: P2P_SEID_INVITE_FLAGS */
-	uint8	len[2];		/* SE length not including eltId, len fields */
-	uint8	flags;		/* Flags */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_invite_flags_se_s wifi_p2p_invite_flags_se_t;
-
-/* WiFi P2P IE subelement: Service Hash */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_serv_hash_se_s {
-	uint8	eltId;			/* SE ID: P2P_SEID_SERVICE_HASH */
-	uint8	len[2];			/* SE length not including eltId, len fields
-					 * in multiple of 6 Bytes
-					*/
-	uint8	hash[1];		/* Variable length - SHA256 hash of
-					 * service names (can be more than one hashes)
-					*/
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_serv_hash_se_s wifi_p2p_serv_hash_se_t;
-
-/* WiFi P2P IE subelement: Service Instance Data */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_serv_inst_data_se_s {
-	uint8	eltId;			/* SE ID: P2P_SEID_SESSION */
-	uint8	len[2];			/* SE length not including eltId, len */
-	uint8	ssn_info[1];		/* Variable length - Session information as specified by
-					 * the service layer, type matches serv. name
-					*/
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_serv_inst_data_se_s wifi_p2p_serv_inst_data_se_t;
-
-
-/* WiFi P2P IE subelement: Connection capability */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_conn_cap_data_se_s {
-	uint8	eltId;			/* SE ID: P2P_SEID_CONNECT_CAP */
-	uint8	len[2];			/* SE length not including eltId, len */
-	uint8	conn_cap;		/* 1byte capability as specified by the
-					 * service layer, valid bitmask/values
-					*/
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_conn_cap_data_se_s wifi_p2p_conn_cap_data_se_t;
-
-
-/* WiFi P2P IE subelement: Advertisement ID */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_advt_id_se_s {
-	uint8	eltId;			/* SE ID: P2P_SEID_ADVERTISE_ID */
-	uint8	len[2];			/* SE length not including eltId, len fixed 4 Bytes */
-	uint8	advt_id[4];		/* 4byte Advertisement ID of the peer device sent in
-					 * PROV Disc in Network byte order
-					*/
-	uint8	advt_mac[6];			/* P2P device address of the service advertiser */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_advt_id_se_s wifi_p2p_advt_id_se_t;
-
-
-/* WiFi P2P IE subelement: Advertise Service Hash */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_adv_serv_info_s {
-	uint8	advt_id[4];		/* SE Advertise ID for the service */
-	uint16	nw_cfg_method;	/* SE Network Config method for the service */
-	uint8	serv_name_len;	/* SE length of the service name */
-	uint8	serv_name[1];	/* Variable length service name field */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_adv_serv_info_s wifi_p2p_adv_serv_info_t;
-
-
-/* WiFi P2P IE subelement: Advertise Service Hash */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_advt_serv_se_s {
-	uint8	eltId;			/* SE ID: P2P_SEID_ADVERTISE_SERVICE */
-	uint8	len[2];			/* SE length not including eltId, len fields mutiple len of
-					 * wifi_p2p_adv_serv_info_t entries
-					*/
-	wifi_p2p_adv_serv_info_t	p_advt_serv_info[1]; /* Variable length
-								of multiple instances
-								of the advertise service info
-								*/
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_advt_serv_se_s wifi_p2p_advt_serv_se_t;
-
-
-/* WiFi P2P IE subelement: Session ID */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_ssn_id_se_s {
-	uint8	eltId;			/* SE ID: P2P_SEID_SESSION_ID */
-	uint8	len[2];			/* SE length not including eltId, len fixed 4 Bytes */
-	uint8	ssn_id[4];		/* 4byte Session ID of the peer device sent in
-							 * PROV Disc in Network byte order
-							 */
-	uint8	ssn_mac[6];		/* P2P device address of the seeker - session mac */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_ssn_id_se_s wifi_p2p_ssn_id_se_t;
-
-
-#define P2P_ADVT_SERV_SE_FIXED_LEN	3	/* Includes only the element ID and len */
-#define P2P_ADVT_SERV_INFO_FIXED_LEN	7	/* Per ADV Service Instance advt_id +
-						 * nw_config_method + serv_name_len
-						 */
-
-/* WiFi P2P Action Frame */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_action_frame {
-	uint8	category;	/* P2P_AF_CATEGORY */
-	uint8	OUI[3];		/* OUI - P2P_OUI */
-	uint8	type;		/* OUI Type - P2P_VER */
-	uint8	subtype;	/* OUI Subtype - P2P_AF_* */
-	uint8	dialog_token;	/* nonzero, identifies req/resp tranaction */
-	uint8	elts[1];	/* Variable length information elements.  Max size =
-				 * ACTION_FRAME_SIZE - sizeof(this structure) - 1
-				 */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_action_frame wifi_p2p_action_frame_t;
-#define P2P_AF_CATEGORY		0x7f
-
-#define P2P_AF_FIXED_LEN	7
-
-/* WiFi P2P Action Frame OUI Subtypes */
-#define P2P_AF_NOTICE_OF_ABSENCE	0	/* Notice of Absence */
-#define P2P_AF_PRESENCE_REQ		1	/* P2P Presence Request */
-#define P2P_AF_PRESENCE_RSP		2	/* P2P Presence Response */
-#define P2P_AF_GO_DISC_REQ		3	/* GO Discoverability Request */
-
-
-/* WiFi P2P Public Action Frame */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_pub_act_frame {
-	uint8	category;	/* P2P_PUB_AF_CATEGORY */
-	uint8	action;		/* P2P_PUB_AF_ACTION */
-	uint8	oui[3];		/* P2P_OUI */
-	uint8	oui_type;	/* OUI type - P2P_VER */
-	uint8	subtype;	/* OUI subtype - P2P_TYPE_* */
-	uint8	dialog_token;	/* nonzero, identifies req/rsp transaction */
-	uint8	elts[1];	/* Variable length information elements.  Max size =
-				 * ACTION_FRAME_SIZE - sizeof(this structure) - 1
-				 */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_pub_act_frame wifi_p2p_pub_act_frame_t;
-#define P2P_PUB_AF_FIXED_LEN	8
-#define P2P_PUB_AF_CATEGORY	0x04
-#define P2P_PUB_AF_ACTION	0x09
-
-/* WiFi P2P Public Action Frame OUI Subtypes */
-#define P2P_PAF_GON_REQ		0	/* Group Owner Negotiation Req */
-#define P2P_PAF_GON_RSP		1	/* Group Owner Negotiation Rsp */
-#define P2P_PAF_GON_CONF	2	/* Group Owner Negotiation Confirm */
-#define P2P_PAF_INVITE_REQ	3	/* P2P Invitation Request */
-#define P2P_PAF_INVITE_RSP	4	/* P2P Invitation Response */
-#define P2P_PAF_DEVDIS_REQ	5	/* Device Discoverability Request */
-#define P2P_PAF_DEVDIS_RSP	6	/* Device Discoverability Response */
-#define P2P_PAF_PROVDIS_REQ	7	/* Provision Discovery Request */
-#define P2P_PAF_PROVDIS_RSP	8	/* Provision Discovery Response */
-#define P2P_PAF_SUBTYPE_INVALID	255	/* Invalid Subtype */
-
-/* TODO: Stop using these obsolete aliases for P2P_PAF_GON_* */
-#define P2P_TYPE_MNREQ		P2P_PAF_GON_REQ
-#define P2P_TYPE_MNRSP		P2P_PAF_GON_RSP
-#define P2P_TYPE_MNCONF		P2P_PAF_GON_CONF
-
-/* WiFi P2P IE subelement: Notice of Absence */
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_desc {
-	uint8	cnt_type;	/* Count/Type */
-	uint32	duration;	/* Duration */
-	uint32	interval;	/* Interval */
-	uint32	start;		/* Start Time */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_noa_desc wifi_p2p_noa_desc_t;
-
-BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_se {
-	uint8	eltId;		/* Subelement ID */
-	uint8	len[2];		/* Length */
-	uint8	index;		/* Index */
-	uint8	ops_ctw_parms;	/* CTWindow and OppPS Parameters */
-	wifi_p2p_noa_desc_t	desc[1];	/* Notice of Absence Descriptor(s) */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2p_noa_se wifi_p2p_noa_se_t;
-
-#define P2P_NOA_SE_FIXED_LEN	5
-
-#define P2P_NOA_SE_MAX_DESC	2	/* max NoA descriptors in presence request */
-
-/* cnt_type field values */
-#define P2P_NOA_DESC_CNT_RESERVED	0	/* reserved and should not be used */
-#define P2P_NOA_DESC_CNT_REPEAT		255	/* continuous schedule */
-#define P2P_NOA_DESC_TYPE_PREFERRED	1	/* preferred values */
-#define P2P_NOA_DESC_TYPE_ACCEPTABLE	2	/* acceptable limits */
-
-/* ctw_ops_parms field values */
-#define P2P_NOA_CTW_MASK	0x7f
-#define P2P_NOA_OPS_MASK	0x80
-#define P2P_NOA_OPS_SHIFT	7
-
-#define P2P_CTW_MIN	10	/* minimum 10TU */
-
-/*
- * P2P Service Discovery related
- */
-#define	P2PSD_ACTION_CATEGORY		0x04
-				/* Public action frame */
-#define	P2PSD_ACTION_ID_GAS_IREQ	0x0a
-				/* Action value for GAS Initial Request AF */
-#define	P2PSD_ACTION_ID_GAS_IRESP	0x0b
-				/* Action value for GAS Initial Response AF */
-#define	P2PSD_ACTION_ID_GAS_CREQ	0x0c
-				/* Action value for GAS Comeback Request AF */
-#define	P2PSD_ACTION_ID_GAS_CRESP	0x0d
-				/* Action value for GAS Comeback Response AF */
-#define P2PSD_AD_EID				0x6c
-				/* Advertisement Protocol IE ID */
-#define P2PSD_ADP_TUPLE_QLMT_PAMEBI	0x00
-				/* Query Response Length Limit 7 bits plus PAME-BI 1 bit */
-#define P2PSD_ADP_PROTO_ID			0x00
-				/* Advertisement Protocol ID. Always 0 for P2P SD */
-#define P2PSD_GAS_OUI				P2P_OUI
-				/* WFA OUI */
-#define P2PSD_GAS_OUI_SUBTYPE		P2P_VER
-				/* OUI Subtype for GAS IE */
-#define P2PSD_GAS_NQP_INFOID		0xDDDD
-				/* NQP Query Info ID: 56797 */
-#define P2PSD_GAS_COMEBACKDEALY		0x00
-				/* Not used in the Native GAS protocol */
-
-/* Service Protocol Type */
-typedef enum p2psd_svc_protype {
-	SVC_RPOTYPE_ALL = 0,
-	SVC_RPOTYPE_BONJOUR = 1,
-	SVC_RPOTYPE_UPNP = 2,
-	SVC_RPOTYPE_WSD = 3,
-	SVC_RPOTYPE_WFDS = 11,
-	SVC_RPOTYPE_VENDOR = 255
-} p2psd_svc_protype_t;
-
-/* Service Discovery response status code */
-typedef enum {
-	P2PSD_RESP_STATUS_SUCCESS = 0,
-	P2PSD_RESP_STATUS_PROTYPE_NA = 1,
-	P2PSD_RESP_STATUS_DATA_NA = 2,
-	P2PSD_RESP_STATUS_BAD_REQUEST = 3
-} p2psd_resp_status_t;
-
-/* Advertisement Protocol IE tuple field */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_tpl {
-	uint8	llm_pamebi;	/* Query Response Length Limit bit 0-6, set to 0 plus
-				* Pre-Associated Message Exchange BSSID Independent bit 7, set to 0
-				*/
-	uint8	adp_id;		/* Advertisement Protocol ID: 0 for NQP Native Query Protocol */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_adp_tpl wifi_p2psd_adp_tpl_t;
-
-/* Advertisement Protocol IE */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_ie {
-	uint8	id;		/* IE ID: 0x6c - 108 */
-	uint8	len;	/* IE length */
-	wifi_p2psd_adp_tpl_t adp_tpl;  /* Advertisement Protocol Tuple field. Only one
-				* tuple is defined for P2P Service Discovery
-				*/
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_adp_ie wifi_p2psd_adp_ie_t;
-
-/* NQP Vendor-specific Content */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_nqp_query_vsc {
-	uint8	oui_subtype;	/* OUI Subtype: 0x09 */
-	uint16	svc_updi;		/* Service Update Indicator */
-	uint8	svc_tlvs[1];	/* wifi_p2psd_qreq_tlv_t type for service request,
-				* wifi_p2psd_qresp_tlv_t type for service response
-				*/
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_nqp_query_vsc wifi_p2psd_nqp_query_vsc_t;
-
-/* Service Request TLV */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_tlv {
-	uint16	len;			/* Length: 5 plus size of Query Data */
-	uint8	svc_prot;		/* Service Protocol Type */
-	uint8	svc_tscid;		/* Service Transaction ID */
-	uint8	query_data[1];	/* Query Data, passed in from above Layer 2 */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_qreq_tlv wifi_p2psd_qreq_tlv_t;
-
-/* Query Request Frame, defined in generic format, instead of NQP specific */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_frame {
-	uint16	info_id;	/* Info ID: 0xDDDD */
-	uint16	len;		/* Length of service request TLV, 5 plus the size of request data */
-	uint8	oui[3];		/* WFA OUI: 0x0050F2 */
-	uint8	qreq_vsc[1]; /* Vendor-specific Content: wifi_p2psd_nqp_query_vsc_t type for NQP */
-
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_qreq_frame wifi_p2psd_qreq_frame_t;
-
-/* GAS Initial Request AF body, "elts" in wifi_p2p_pub_act_frame */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_ireq_frame {
-	wifi_p2psd_adp_ie_t		adp_ie;		/* Advertisement Protocol IE */
-	uint16					qreq_len;	/* Query Request Length */
-	uint8	qreq_frm[1];	/* Query Request Frame wifi_p2psd_qreq_frame_t */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_gas_ireq_frame wifi_p2psd_gas_ireq_frame_t;
-
-/* Service Response TLV */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_tlv {
-	uint16	len;				/* Length: 5 plus size of Query Data */
-	uint8	svc_prot;			/* Service Protocol Type */
-	uint8	svc_tscid;			/* Service Transaction ID */
-	uint8	status;				/* Value defined in Table 57 of P2P spec. */
-	uint8	query_data[1];		/* Response Data, passed in from above Layer 2 */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_qresp_tlv wifi_p2psd_qresp_tlv_t;
-
-/* Query Response Frame, defined in generic format, instead of NQP specific */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_frame {
-	uint16	info_id;	/* Info ID: 0xDDDD */
-	uint16	len;		/* Lenth of service response TLV, 6 plus the size of resp data */
-	uint8	oui[3];		/* WFA OUI: 0x0050F2 */
-	uint8	qresp_vsc[1]; /* Vendor-specific Content: wifi_p2psd_qresp_tlv_t type for NQP */
-
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_qresp_frame wifi_p2psd_qresp_frame_t;
-
-/* GAS Initial Response AF body, "elts" in wifi_p2p_pub_act_frame */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_iresp_frame {
-	uint16	status;			/* Value defined in Table 7-23 of IEEE P802.11u */
-	uint16	cb_delay;		/* GAS Comeback Delay */
-	wifi_p2psd_adp_ie_t	adp_ie;		/* Advertisement Protocol IE */
-	uint16		qresp_len;	/* Query Response Length */
-	uint8	qresp_frm[1];	/* Query Response Frame wifi_p2psd_qresp_frame_t */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_gas_iresp_frame wifi_p2psd_gas_iresp_frame_t;
-
-/* GAS Comeback Response AF body, "elts" in wifi_p2p_pub_act_frame */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_cresp_frame {
-	uint16	status;			/* Value defined in Table 7-23 of IEEE P802.11u */
-	uint8	fragment_id;	/* Fragmentation ID */
-	uint16	cb_delay;		/* GAS Comeback Delay */
-	wifi_p2psd_adp_ie_t	adp_ie;		/* Advertisement Protocol IE */
-	uint16	qresp_len;		/* Query Response Length */
-	uint8	qresp_frm[1];	/* Query Response Frame wifi_p2psd_qresp_frame_t */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_gas_cresp_frame wifi_p2psd_gas_cresp_frame_t;
-
-/* Wi-Fi GAS Public Action Frame */
-BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_pub_act_frame {
-	uint8	category;		/* 0x04 Public Action Frame */
-	uint8	action;			/* 0x6c Advertisement Protocol */
-	uint8	dialog_token;	/* nonzero, identifies req/rsp transaction */
-	uint8	query_data[1];	/* Query Data. wifi_p2psd_gas_ireq_frame_t
-					 * or wifi_p2psd_gas_iresp_frame_t format
-					 */
-} BWL_POST_PACKED_STRUCT;
-typedef struct wifi_p2psd_gas_pub_act_frame wifi_p2psd_gas_pub_act_frame_t;
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif /* _P2P_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/sdspi.h b/drivers/net/wireless/bcmdhd/include/proto/sdspi.h
deleted file mode 100644
index a1d7ac9..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/sdspi.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * SD-SPI Protocol Standard
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sdspi.h 518342 2014-12-01 23:21:41Z $
- */
-#ifndef	_SD_SPI_H
-#define	_SD_SPI_H
-
-#define SPI_START_M		BITFIELD_MASK(1)	/* Bit [31] 	- Start Bit */
-#define SPI_START_S		31
-#define SPI_DIR_M		BITFIELD_MASK(1)	/* Bit [30] 	- Direction */
-#define SPI_DIR_S		30
-#define SPI_CMD_INDEX_M		BITFIELD_MASK(6)	/* Bits [29:24] - Command number */
-#define SPI_CMD_INDEX_S		24
-#define SPI_RW_M		BITFIELD_MASK(1)	/* Bit [23] 	- Read=0, Write=1 */
-#define SPI_RW_S		23
-#define SPI_FUNC_M		BITFIELD_MASK(3)	/* Bits [22:20]	- Function Number */
-#define SPI_FUNC_S		20
-#define SPI_RAW_M		BITFIELD_MASK(1)	/* Bit [19] 	- Read After Wr */
-#define SPI_RAW_S		19
-#define SPI_STUFF_M		BITFIELD_MASK(1)	/* Bit [18] 	- Stuff bit */
-#define SPI_STUFF_S		18
-#define SPI_BLKMODE_M		BITFIELD_MASK(1)	/* Bit [19] 	- Blockmode 1=blk */
-#define SPI_BLKMODE_S		19
-#define SPI_OPCODE_M		BITFIELD_MASK(1)	/* Bit [18] 	- OP Code */
-#define SPI_OPCODE_S		18
-#define SPI_ADDR_M		BITFIELD_MASK(17)	/* Bits [17:1] 	- Address */
-#define SPI_ADDR_S		1
-#define SPI_STUFF0_M		BITFIELD_MASK(1)	/* Bit [0] 	- Stuff bit */
-#define SPI_STUFF0_S		0
-
-#define SPI_RSP_START_M		BITFIELD_MASK(1)	/* Bit [7] 	- Start Bit (always 0) */
-#define SPI_RSP_START_S		7
-#define SPI_RSP_PARAM_ERR_M	BITFIELD_MASK(1)	/* Bit [6] 	- Parameter Error */
-#define SPI_RSP_PARAM_ERR_S	6
-#define SPI_RSP_RFU5_M		BITFIELD_MASK(1)	/* Bit [5] 	- RFU (Always 0) */
-#define SPI_RSP_RFU5_S		5
-#define SPI_RSP_FUNC_ERR_M	BITFIELD_MASK(1)	/* Bit [4] 	- Function number error */
-#define SPI_RSP_FUNC_ERR_S	4
-#define SPI_RSP_CRC_ERR_M	BITFIELD_MASK(1)	/* Bit [3] 	- COM CRC Error */
-#define SPI_RSP_CRC_ERR_S	3
-#define SPI_RSP_ILL_CMD_M	BITFIELD_MASK(1)	/* Bit [2] 	- Illegal Command error */
-#define SPI_RSP_ILL_CMD_S	2
-#define SPI_RSP_RFU1_M		BITFIELD_MASK(1)	/* Bit [1] 	- RFU (Always 0) */
-#define SPI_RSP_RFU1_S		1
-#define SPI_RSP_IDLE_M		BITFIELD_MASK(1)	/* Bit [0] 	- In idle state */
-#define SPI_RSP_IDLE_S		0
-
-/* SD-SPI Protocol Definitions */
-#define SDSPI_COMMAND_LEN	6	/* Number of bytes in an SD command */
-#define SDSPI_START_BLOCK	0xFE	/* SD Start Block Token */
-#define SDSPI_IDLE_PAD		0xFF	/* SD-SPI idle value for MOSI */
-#define SDSPI_START_BIT_MASK	0x80
-
-#endif /* _SD_SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/vlan.h b/drivers/net/wireless/bcmdhd/include/proto/vlan.h
deleted file mode 100644
index 77b1458..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/vlan.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 802.1Q VLAN protocol definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: vlan.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _vlan_h_
-#define _vlan_h_
-
-#ifndef _TYPEDEFS_H_
-#include <typedefs.h>
-#endif
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-#ifndef	 VLAN_VID_MASK
-#define VLAN_VID_MASK		0xfff	/* low 12 bits are vlan id */
-#endif
-
-#define	VLAN_CFI_SHIFT		12	/* canonical format indicator bit */
-#define VLAN_PRI_SHIFT		13	/* user priority */
-
-#define VLAN_PRI_MASK		7	/* 3 bits of priority */
-
-#define	VLAN_TPID_OFFSET	12	/* offset of tag protocol id field */
-#define	VLAN_TCI_OFFSET		14	/* offset of tag ctrl info field */
-
-#define	VLAN_TAG_LEN		4
-#define	VLAN_TAG_OFFSET		(2 * ETHER_ADDR_LEN)	/* offset in Ethernet II packet only */
-
-#define VLAN_TPID		0x8100	/* VLAN ethertype/Tag Protocol ID */
-
-struct vlan_header {
-	uint16	vlan_type;		/* 0x8100 */
-	uint16	vlan_tag;		/* priority, cfi and vid */
-};
-
-struct ethervlan_header {
-	uint8	ether_dhost[ETHER_ADDR_LEN];
-	uint8	ether_shost[ETHER_ADDR_LEN];
-	uint16	vlan_type;		/* 0x8100 */
-	uint16	vlan_tag;		/* priority, cfi and vid */
-	uint16	ether_type;
-};
-
-struct dot3_mac_llc_snapvlan_header {
-	uint8	ether_dhost[ETHER_ADDR_LEN];	/* dest mac */
-	uint8	ether_shost[ETHER_ADDR_LEN];	/* src mac */
-	uint16	length;				/* frame length incl header */
-	uint8	dsap;				/* always 0xAA */
-	uint8	ssap;				/* always 0xAA */
-	uint8	ctl;				/* always 0x03 */
-	uint8	oui[3];				/* RFC1042: 0x00 0x00 0x00
-						 * Bridge-Tunnel: 0x00 0x00 0xF8
-						 */
-	uint16	vlan_type;			/* 0x8100 */
-	uint16	vlan_tag;			/* priority, cfi and vid */
-	uint16	ether_type;			/* ethertype */
-};
-
-#define	ETHERVLAN_HDR_LEN	(ETHER_HDR_LEN + VLAN_TAG_LEN)
-
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#define ETHERVLAN_MOVE_HDR(d, s) \
-do { \
-	struct ethervlan_header t; \
-	t = *(struct ethervlan_header *)(s); \
-	*(struct ethervlan_header *)(d) = t; \
-} while (0)
-
-#endif /* _vlan_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/wpa.h b/drivers/net/wireless/bcmdhd/include/proto/wpa.h
deleted file mode 100644
index ef5d664..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/wpa.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Fundamental types and constants relating to WPA
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wpa.h 518342 2014-12-01 23:21:41Z $
- */
-
-#ifndef _proto_wpa_h_
-#define _proto_wpa_h_
-
-#include <typedefs.h>
-#include <proto/ethernet.h>
-
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-/* Reason Codes */
-
-/* 13 through 23 taken from IEEE Std 802.11i-2004 */
-#define DOT11_RC_INVALID_WPA_IE		13	/* Invalid info. element */
-#define DOT11_RC_MIC_FAILURE		14	/* Michael failure */
-#define DOT11_RC_4WH_TIMEOUT		15	/* 4-way handshake timeout */
-#define DOT11_RC_GTK_UPDATE_TIMEOUT	16	/* Group key update timeout */
-#define DOT11_RC_WPA_IE_MISMATCH	17	/* WPA IE in 4-way handshake differs from
-						 * (re-)assoc. request/probe response
-						 */
-#define DOT11_RC_INVALID_MC_CIPHER	18	/* Invalid multicast cipher */
-#define DOT11_RC_INVALID_UC_CIPHER	19	/* Invalid unicast cipher */
-#define DOT11_RC_INVALID_AKMP		20	/* Invalid authenticated key management protocol */
-#define DOT11_RC_BAD_WPA_VERSION	21	/* Unsupported WPA version */
-#define DOT11_RC_INVALID_WPA_CAP	22	/* Invalid WPA IE capabilities */
-#define DOT11_RC_8021X_AUTH_FAIL	23	/* 802.1X authentication failure */
-
-#define WPA2_PMKID_LEN	16
-
-/* WPA IE fixed portion */
-typedef BWL_PRE_PACKED_STRUCT struct
-{
-	uint8 tag;	/* TAG */
-	uint8 length;	/* TAG length */
-	uint8 oui[3];	/* IE OUI */
-	uint8 oui_type;	/* OUI type */
-	BWL_PRE_PACKED_STRUCT struct {
-		uint8 low;
-		uint8 high;
-	} BWL_POST_PACKED_STRUCT version;	/* IE version */
-} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t;
-#define WPA_IE_OUITYPE_LEN	4
-#define WPA_IE_FIXED_LEN	8
-#define WPA_IE_TAG_FIXED_LEN	6
-
-#define BIP_OUI_TYPE WPA2_OUI "\x06"
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint8 tag;	/* TAG */
-	uint8 length;	/* TAG length */
-	BWL_PRE_PACKED_STRUCT struct {
-		uint8 low;
-		uint8 high;
-	} BWL_POST_PACKED_STRUCT version;	/* IE version */
-} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t;
-#define WPA_RSN_IE_FIXED_LEN	4
-#define WPA_RSN_IE_TAG_FIXED_LEN	2
-typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN];
-
-#define WFA_OSEN_IE_FIXED_LEN	6
-
-/* WPA suite/multicast suite */
-typedef BWL_PRE_PACKED_STRUCT struct
-{
-	uint8 oui[3];
-	uint8 type;
-} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t;
-#define WPA_SUITE_LEN	4
-
-/* WPA unicast suite list/key management suite list */
-typedef BWL_PRE_PACKED_STRUCT struct
-{
-	BWL_PRE_PACKED_STRUCT struct {
-		uint8 low;
-		uint8 high;
-	} BWL_POST_PACKED_STRUCT count;
-	wpa_suite_t list[1];
-} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
-#define WPA_IE_SUITE_COUNT_LEN	2
-typedef BWL_PRE_PACKED_STRUCT struct
-{
-	BWL_PRE_PACKED_STRUCT struct {
-		uint8 low;
-		uint8 high;
-	} BWL_POST_PACKED_STRUCT count;
-	wpa_pmkid_t list[1];
-} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t;
-
-/* WPA cipher suites */
-#define WPA_CIPHER_NONE		0	/* None */
-#define WPA_CIPHER_WEP_40	1	/* WEP (40-bit) */
-#define WPA_CIPHER_TKIP		2	/* TKIP: default for WPA */
-#define WPA_CIPHER_AES_OCB	3	/* AES (OCB) */
-#define WPA_CIPHER_AES_CCM	4	/* AES (CCM) */
-#define WPA_CIPHER_WEP_104	5	/* WEP (104-bit) */
-#define WPA_CIPHER_BIP		6	/* WEP (104-bit) */
-#define WPA_CIPHER_TPK		7	/* Group addressed traffic not allowed */
-
-
-#define IS_WPA_CIPHER(cipher)	((cipher) == WPA_CIPHER_NONE || \
-				 (cipher) == WPA_CIPHER_WEP_40 || \
-				 (cipher) == WPA_CIPHER_WEP_104 || \
-				 (cipher) == WPA_CIPHER_TKIP || \
-				 (cipher) == WPA_CIPHER_AES_OCB || \
-				 (cipher) == WPA_CIPHER_AES_CCM || \
-				 (cipher) == WPA_CIPHER_TPK)
-
-
-/* WPA TKIP countermeasures parameters */
-#define WPA_TKIP_CM_DETECT	60	/* multiple MIC failure window (seconds) */
-#define WPA_TKIP_CM_BLOCK	60	/* countermeasures active window (seconds) */
-
-/* RSN IE defines */
-#define RSN_CAP_LEN		2	/* Length of RSN capabilities field (2 octets) */
-
-/* RSN Capabilities defined in 802.11i */
-#define RSN_CAP_PREAUTH			0x0001
-#define RSN_CAP_NOPAIRWISE		0x0002
-#define RSN_CAP_PTK_REPLAY_CNTR_MASK	0x000C
-#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT	2
-#define RSN_CAP_GTK_REPLAY_CNTR_MASK	0x0030
-#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT	4
-#define RSN_CAP_1_REPLAY_CNTR		0
-#define RSN_CAP_2_REPLAY_CNTRS		1
-#define RSN_CAP_4_REPLAY_CNTRS		2
-#define RSN_CAP_16_REPLAY_CNTRS		3
-#define RSN_CAP_MFPR			0x0040
-#define RSN_CAP_MFPC			0x0080
-#define RSN_CAP_SPPC			0x0400
-#define RSN_CAP_SPPR			0x0800
-
-/* WPA capabilities defined in 802.11i */
-#define WPA_CAP_4_REPLAY_CNTRS		RSN_CAP_4_REPLAY_CNTRS
-#define WPA_CAP_16_REPLAY_CNTRS		RSN_CAP_16_REPLAY_CNTRS
-#define WPA_CAP_REPLAY_CNTR_SHIFT	RSN_CAP_PTK_REPLAY_CNTR_SHIFT
-#define WPA_CAP_REPLAY_CNTR_MASK	RSN_CAP_PTK_REPLAY_CNTR_MASK
-
-/* WPA capabilities defined in 802.11zD9.0 */
-#define WPA_CAP_PEER_KEY_ENABLE		(0x1 << 1)	/* bit 9 */
-
-/* WPA Specific defines */
-#define WPA_CAP_LEN	RSN_CAP_LEN	/* Length of RSN capabilities in RSN IE (2 octets) */
-#define WPA_PMKID_CNT_LEN	2 	/* Length of RSN PMKID count (2 octests) */
-
-#define	WPA_CAP_WPA2_PREAUTH		RSN_CAP_PREAUTH
-
-#define WPA2_PMKID_COUNT_LEN	2
-
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif /* _proto_wpa_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/proto/wps.h b/drivers/net/wireless/bcmdhd/include/proto/wps.h
deleted file mode 100644
index 495d7f1..0000000
--- a/drivers/net/wireless/bcmdhd/include/proto/wps.h
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * WPS IE definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id$
- */
-
-#ifndef _WPS_
-#define _WPS_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Data Element Definitions */
-#define WPS_ID_AP_CHANNEL         0x1001
-#define WPS_ID_ASSOC_STATE        0x1002
-#define WPS_ID_AUTH_TYPE          0x1003
-#define WPS_ID_AUTH_TYPE_FLAGS    0x1004
-#define WPS_ID_AUTHENTICATOR      0x1005
-#define WPS_ID_CONFIG_METHODS     0x1008
-#define WPS_ID_CONFIG_ERROR       0x1009
-#define WPS_ID_CONF_URL4          0x100A
-#define WPS_ID_CONF_URL6          0x100B
-#define WPS_ID_CONN_TYPE          0x100C
-#define WPS_ID_CONN_TYPE_FLAGS    0x100D
-#define WPS_ID_CREDENTIAL         0x100E
-#define WPS_ID_DEVICE_NAME        0x1011
-#define WPS_ID_DEVICE_PWD_ID      0x1012
-#define WPS_ID_E_HASH1            0x1014
-#define WPS_ID_E_HASH2            0x1015
-#define WPS_ID_E_SNONCE1          0x1016
-#define WPS_ID_E_SNONCE2          0x1017
-#define WPS_ID_ENCR_SETTINGS      0x1018
-#define WPS_ID_ENCR_TYPE          0x100F
-#define WPS_ID_ENCR_TYPE_FLAGS    0x1010
-#define WPS_ID_ENROLLEE_NONCE     0x101A
-#define WPS_ID_FEATURE_ID         0x101B
-#define WPS_ID_IDENTITY           0x101C
-#define WPS_ID_IDENTITY_PROOF     0x101D
-#define WPS_ID_KEY_WRAP_AUTH      0x101E
-#define WPS_ID_KEY_IDENTIFIER     0x101F
-#define WPS_ID_MAC_ADDR           0x1020
-#define WPS_ID_MANUFACTURER       0x1021
-#define WPS_ID_MSG_TYPE           0x1022
-#define WPS_ID_MODEL_NAME         0x1023
-#define WPS_ID_MODEL_NUMBER       0x1024
-#define WPS_ID_NW_INDEX           0x1026
-#define WPS_ID_NW_KEY             0x1027
-#define WPS_ID_NW_KEY_INDEX       0x1028
-#define WPS_ID_NEW_DEVICE_NAME    0x1029
-#define WPS_ID_NEW_PWD            0x102A
-#define WPS_ID_OOB_DEV_PWD        0x102C
-#define WPS_ID_OS_VERSION         0x102D
-#define WPS_ID_POWER_LEVEL        0x102F
-#define WPS_ID_PSK_CURRENT        0x1030
-#define WPS_ID_PSK_MAX            0x1031
-#define WPS_ID_PUBLIC_KEY         0x1032
-#define WPS_ID_RADIO_ENABLED      0x1033
-#define WPS_ID_REBOOT             0x1034
-#define WPS_ID_REGISTRAR_CURRENT  0x1035
-#define WPS_ID_REGISTRAR_ESTBLSHD 0x1036
-#define WPS_ID_REGISTRAR_LIST     0x1037
-#define WPS_ID_REGISTRAR_MAX      0x1038
-#define WPS_ID_REGISTRAR_NONCE    0x1039
-#define WPS_ID_REQ_TYPE           0x103A
-#define WPS_ID_RESP_TYPE          0x103B
-#define WPS_ID_RF_BAND            0x103C
-#define WPS_ID_R_HASH1            0x103D
-#define WPS_ID_R_HASH2            0x103E
-#define WPS_ID_R_SNONCE1          0x103F
-#define WPS_ID_R_SNONCE2          0x1040
-#define WPS_ID_SEL_REGISTRAR      0x1041
-#define WPS_ID_SERIAL_NUM         0x1042
-#define WPS_ID_SC_STATE           0x1044
-#define WPS_ID_SSID               0x1045
-#define WPS_ID_TOT_NETWORKS       0x1046
-#define WPS_ID_UUID_E             0x1047
-#define WPS_ID_UUID_R             0x1048
-#define WPS_ID_VENDOR_EXT         0x1049
-#define WPS_ID_VERSION            0x104A
-#define WPS_ID_X509_CERT_REQ      0x104B
-#define WPS_ID_X509_CERT          0x104C
-#define WPS_ID_EAP_IDENTITY       0x104D
-#define WPS_ID_MSG_COUNTER        0x104E
-#define WPS_ID_PUBKEY_HASH        0x104F
-#define WPS_ID_REKEY_KEY          0x1050
-#define WPS_ID_KEY_LIFETIME       0x1051
-#define WPS_ID_PERM_CFG_METHODS   0x1052
-#define WPS_ID_SEL_REG_CFG_METHODS 0x1053
-#define WPS_ID_PRIM_DEV_TYPE      0x1054
-#define WPS_ID_SEC_DEV_TYPE_LIST  0x1055
-#define WPS_ID_PORTABLE_DEVICE    0x1056
-#define WPS_ID_AP_SETUP_LOCKED    0x1057
-#define WPS_ID_APP_LIST           0x1058
-#define WPS_ID_EAP_TYPE           0x1059
-#define WPS_ID_INIT_VECTOR        0x1060
-#define WPS_ID_KEY_PROVIDED_AUTO  0x1061
-#define WPS_ID_8021X_ENABLED      0x1062
-#define WPS_ID_WEP_TRANSMIT_KEY   0x1064
-#define WPS_ID_REQ_DEV_TYPE       0x106A
-
-/* WSC 2.0, WFA Vendor Extension Subelements */
-#define WFA_VENDOR_EXT_ID                 "\x00\x37\x2A"
-#define WPS_WFA_SUBID_VERSION2            0x00
-#define WPS_WFA_SUBID_AUTHORIZED_MACS     0x01
-#define WPS_WFA_SUBID_NW_KEY_SHAREABLE    0x02
-#define WPS_WFA_SUBID_REQ_TO_ENROLL       0x03
-#define WPS_WFA_SUBID_SETTINGS_DELAY_TIME 0x04
-#define WPS_WFA_SUBID_REG_CFG_METHODS     0x05
-
-
-/* WCN-NET Windows Rally Vertical Pairing Vendor Extensions */
-#define MS_VENDOR_EXT_ID           "\x00\x01\x37"
-#define WPS_MS_ID_VPI               0x1001	/* Vertical Pairing Identifier TLV */
-#define WPS_MS_ID_TRANSPORT_UUID    0x1002      /* Transport UUID TLV */
-
-/* Vertical Pairing Identifier TLV Definitions */
-#define WPS_MS_VPI_TRANSPORT_NONE   0x00        /* None */
-#define WPS_MS_VPI_TRANSPORT_DPWS   0x01        /* Devices Profile for Web Services */
-#define WPS_MS_VPI_TRANSPORT_UPNP   0x02        /* uPnP */
-#define WPS_MS_VPI_TRANSPORT_SDNWS  0x03        /* Secure Devices Profile for Web Services */
-#define WPS_MS_VPI_NO_PROFILE_REQ   0x00        /* Wi-Fi profile not requested.
-						 * Not supported in Windows 7
-						 */
-#define WPS_MS_VPI_PROFILE_REQ      0x01        /* Wi-Fi profile requested.  */
-
-/* sizes of the fixed size elements */
-#define WPS_ID_AP_CHANNEL_S       2
-#define WPS_ID_ASSOC_STATE_S      2
-#define WPS_ID_AUTH_TYPE_S        2
-#define WPS_ID_AUTH_TYPE_FLAGS_S  2
-#define WPS_ID_AUTHENTICATOR_S    8
-#define WPS_ID_CONFIG_METHODS_S   2
-#define WPS_ID_CONFIG_ERROR_S     2
-#define WPS_ID_CONN_TYPE_S          1
-#define WPS_ID_CONN_TYPE_FLAGS_S    1
-#define WPS_ID_DEVICE_PWD_ID_S      2
-#define WPS_ID_ENCR_TYPE_S          2
-#define WPS_ID_ENCR_TYPE_FLAGS_S    2
-#define WPS_ID_FEATURE_ID_S         4
-#define WPS_ID_MAC_ADDR_S           6
-#define WPS_ID_MSG_TYPE_S           1
-#define WPS_ID_SC_STATE_S           1
-#define WPS_ID_RF_BAND_S            1
-#define WPS_ID_OS_VERSION_S         4
-#define WPS_ID_VERSION_S            1
-#define WPS_ID_SEL_REGISTRAR_S      1
-#define WPS_ID_SEL_REG_CFG_METHODS_S 2
-#define WPS_ID_REQ_TYPE_S           1
-#define WPS_ID_RESP_TYPE_S          1
-#define WPS_ID_AP_SETUP_LOCKED_S    1
-
-/* WSC 2.0, WFA Vendor Extension Subelements */
-#define WPS_WFA_SUBID_VERSION2_S            1
-#define WPS_WFA_SUBID_NW_KEY_SHAREABLE_S    1
-#define WPS_WFA_SUBID_REQ_TO_ENROLL_S       1
-#define WPS_WFA_SUBID_SETTINGS_DELAY_TIME_S 1
-#define WPS_WFA_SUBID_REG_CFG_METHODS_S     2
-
-/* Association states */
-#define WPS_ASSOC_NOT_ASSOCIATED  0
-#define WPS_ASSOC_CONN_SUCCESS    1
-#define WPS_ASSOC_CONFIG_FAIL     2
-#define WPS_ASSOC_ASSOC_FAIL      3
-#define WPS_ASSOC_IP_FAIL         4
-
-/* Authentication types */
-#define WPS_AUTHTYPE_OPEN        0x0001
-#define WPS_AUTHTYPE_WPAPSK      0x0002	/* Deprecated in WSC 2.0 */
-#define WPS_AUTHTYPE_SHARED      0x0004	/* Deprecated in WSC 2.0 */
-#define WPS_AUTHTYPE_WPA         0x0008	/* Deprecated in WSC 2.0 */
-#define WPS_AUTHTYPE_WPA2        0x0010
-#define WPS_AUTHTYPE_WPA2PSK     0x0020
-
-/* Config methods */
-#define WPS_CONFMET_USBA            0x0001	/* Deprecated in WSC 2.0 */
-#define WPS_CONFMET_ETHERNET        0x0002	/* Deprecated in WSC 2.0 */
-#define WPS_CONFMET_LABEL           0x0004
-#define WPS_CONFMET_DISPLAY         0x0008
-#define WPS_CONFMET_EXT_NFC_TOK     0x0010
-#define WPS_CONFMET_INT_NFC_TOK     0x0020
-#define WPS_CONFMET_NFC_INTF        0x0040
-#define WPS_CONFMET_PBC             0x0080
-#define WPS_CONFMET_KEYPAD          0x0100
-/* WSC 2.0 */
-#define WPS_CONFMET_VIRT_PBC        0x0280
-#define WPS_CONFMET_PHY_PBC         0x0480
-#define WPS_CONFMET_VIRT_DISPLAY    0x2008
-#define WPS_CONFMET_PHY_DISPLAY     0x4008
-
-/* WPS error messages */
-#define WPS_ERROR_NO_ERROR                0
-#define WPS_ERROR_OOB_INT_READ_ERR        1
-#define WPS_ERROR_DECRYPT_CRC_FAIL        2
-#define WPS_ERROR_CHAN24_NOT_SUPP         3
-#define WPS_ERROR_CHAN50_NOT_SUPP         4
-#define WPS_ERROR_SIGNAL_WEAK             5	/* Deprecated in WSC 2.0 */
-#define WPS_ERROR_NW_AUTH_FAIL            6	/* Deprecated in WSC 2.0 */
-#define WPS_ERROR_NW_ASSOC_FAIL           7	/* Deprecated in WSC 2.0 */
-#define WPS_ERROR_NO_DHCP_RESP            8	/* Deprecated in WSC 2.0 */
-#define WPS_ERROR_FAILED_DHCP_CONF        9	/* Deprecated in WSC 2.0 */
-#define WPS_ERROR_IP_ADDR_CONFLICT        10	/* Deprecated in WSC 2.0 */
-#define WPS_ERROR_FAIL_CONN_REGISTRAR     11
-#define WPS_ERROR_MULTI_PBC_DETECTED      12
-#define WPS_ERROR_ROGUE_SUSPECTED         13
-#define WPS_ERROR_DEVICE_BUSY             14
-#define WPS_ERROR_SETUP_LOCKED            15
-#define WPS_ERROR_MSG_TIMEOUT             16	/* Deprecated in WSC 2.0 */
-#define WPS_ERROR_REG_SESSION_TIMEOUT     17	/* Deprecated in WSC 2.0 */
-#define WPS_ERROR_DEV_PWD_AUTH_FAIL       18
-#define WPS_ERROR_60GHZ_NOT_SUPPORT       19
-#define WPS_ERROR_PKH_MISMATCH            20	/* Public Key Hash Mismatch */
-
-/* Connection types */
-#define WPS_CONNTYPE_ESS    0x01
-#define WPS_CONNTYPE_IBSS   0x02
-
-/* Device password ID */
-#define WPS_DEVICEPWDID_DEFAULT          0x0000
-#define WPS_DEVICEPWDID_USER_SPEC        0x0001
-#define WPS_DEVICEPWDID_MACHINE_SPEC     0x0002
-#define WPS_DEVICEPWDID_REKEY            0x0003
-#define WPS_DEVICEPWDID_PUSH_BTN         0x0004
-#define WPS_DEVICEPWDID_REG_SPEC         0x0005
-#define WPS_DEVICEPWDID_IBSS             0x0006
-#define WPS_DEVICEPWDID_NFC_CHO          0x0007	/* NFC-Connection-Handover */
-#define WPS_DEVICEPWDID_WFDS             0x0008	/* Wi-Fi Direct Services Specification */
-
-/* Encryption type */
-#define WPS_ENCRTYPE_NONE    0x0001
-#define WPS_ENCRTYPE_WEP     0x0002	/* Deprecated in WSC 2.0 */
-#define WPS_ENCRTYPE_TKIP    0x0004	/* Deprecated in version 2.0. TKIP can only
-					  * be advertised on the AP when Mixed Mode
-					  * is enabled (Encryption Type is 0x000c).
-					  */
-#define WPS_ENCRTYPE_AES     0x0008
-
-
-/* WPS Message Types */
-#define WPS_ID_BEACON            0x01
-#define WPS_ID_PROBE_REQ         0x02
-#define WPS_ID_PROBE_RESP        0x03
-#define WPS_ID_MESSAGE_M1        0x04
-#define WPS_ID_MESSAGE_M2        0x05
-#define WPS_ID_MESSAGE_M2D       0x06
-#define WPS_ID_MESSAGE_M3        0x07
-#define WPS_ID_MESSAGE_M4        0x08
-#define WPS_ID_MESSAGE_M5        0x09
-#define WPS_ID_MESSAGE_M6        0x0A
-#define WPS_ID_MESSAGE_M7        0x0B
-#define WPS_ID_MESSAGE_M8        0x0C
-#define WPS_ID_MESSAGE_ACK       0x0D
-#define WPS_ID_MESSAGE_NACK      0x0E
-#define WPS_ID_MESSAGE_DONE      0x0F
-
-/* WSP private ID for local use */
-#define WPS_PRIVATE_ID_IDENTITY		(WPS_ID_MESSAGE_DONE + 1)
-#define WPS_PRIVATE_ID_WPS_START	(WPS_ID_MESSAGE_DONE + 2)
-#define WPS_PRIVATE_ID_FAILURE		(WPS_ID_MESSAGE_DONE + 3)
-#define WPS_PRIVATE_ID_FRAG		(WPS_ID_MESSAGE_DONE + 4)
-#define WPS_PRIVATE_ID_FRAG_ACK		(WPS_ID_MESSAGE_DONE + 5)
-#define WPS_PRIVATE_ID_EAPOL_START	(WPS_ID_MESSAGE_DONE + 6)
-
-
-/* Device Type categories for primary and secondary device types */
-#define WPS_DEVICE_TYPE_CAT_COMPUTER        1
-#define WPS_DEVICE_TYPE_CAT_INPUT_DEVICE    2
-#define WPS_DEVICE_TYPE_CAT_PRINTER         3
-#define WPS_DEVICE_TYPE_CAT_CAMERA          4
-#define WPS_DEVICE_TYPE_CAT_STORAGE         5
-#define WPS_DEVICE_TYPE_CAT_NW_INFRA        6
-#define WPS_DEVICE_TYPE_CAT_DISPLAYS        7
-#define WPS_DEVICE_TYPE_CAT_MM_DEVICES      8
-#define WPS_DEVICE_TYPE_CAT_GAME_DEVICES    9
-#define WPS_DEVICE_TYPE_CAT_TELEPHONE       10
-#define WPS_DEVICE_TYPE_CAT_AUDIO_DEVICES   11	/* WSC 2.0 */
-
-/* Device Type sub categories for primary and secondary device types */
-#define WPS_DEVICE_TYPE_SUB_CAT_COMP_PC         1
-#define WPS_DEVICE_TYPE_SUB_CAT_COMP_SERVER     2
-#define WPS_DEVICE_TYPE_SUB_CAT_COMP_MEDIA_CTR  3
-#define WPS_DEVICE_TYPE_SUB_CAT_COMP_UM_PC      4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_COMP_NOTEBOOK   5	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_COMP_DESKTOP    6	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_COMP_MID        7	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_COMP_NETBOOK    8	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_INP_Keyboard    1	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_INP_MOUSE       2	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_INP_JOYSTICK    3	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_INP_TRACKBALL   4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_INP_GAM_CTRL    5	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_INP_REMOTE      6	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_INP_TOUCHSCREEN 7	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_INP_BIO_READER  8	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_INP_BAR_READER  9	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_PRINTER    1
-#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_SCANNER    2
-#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_FAX        3	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_COPIER     4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_ALLINONE   5	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_CAM_DGTL_STILL  1
-#define WPS_DEVICE_TYPE_SUB_CAT_CAM_VIDEO_CAM   2	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_CAM_WEB_CAM     3	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_CAM_SECU_CAM    4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_STOR_NAS        1
-#define WPS_DEVICE_TYPE_SUB_CAT_NW_AP           1
-#define WPS_DEVICE_TYPE_SUB_CAT_NW_ROUTER       2
-#define WPS_DEVICE_TYPE_SUB_CAT_NW_SWITCH       3
-#define WPS_DEVICE_TYPE_SUB_CAT_NW_GATEWAY      4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_NW_BRIDGE       5	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_DISP_TV         1
-#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PIC_FRAME  2
-#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PROJECTOR  3
-#define WPS_DEVICE_TYPE_SUB_CAT_DISP_MONITOR    4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_MM_DAR          1
-#define WPS_DEVICE_TYPE_SUB_CAT_MM_PVR          2
-#define WPS_DEVICE_TYPE_SUB_CAT_MM_MCX          3
-#define WPS_DEVICE_TYPE_SUB_CAT_MM_STB          4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_MM_MS_ME        5	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_MM_PVP          6	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX        1
-#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX_360    2
-#define WPS_DEVICE_TYPE_SUB_CAT_GAM_PS          3
-#define WPS_DEVICE_TYPE_SUB_CAT_GAM_GC          4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_GAM_PGD         5	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_WM        1
-#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_PSM       2	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_PDM       3	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_SSM       4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_SDM       5	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_TUNER     1	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_SPEAKERS  2	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_PMP       3	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HEADSET   4	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HPHONE    5	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_MPHONE    6	/* WSC 2.0 */
-#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HTS       7	/* WSC 2.0 */
-
-
-/* Device request/response type */
-#define WPS_MSGTYPE_ENROLLEE_INFO_ONLY    0x00
-#define WPS_MSGTYPE_ENROLLEE_OPEN_8021X   0x01
-#define WPS_MSGTYPE_REGISTRAR             0x02
-#define WPS_MSGTYPE_AP_WLAN_MGR           0x03
-
-/* RF Band */
-#define WPS_RFBAND_24GHZ    0x01
-#define WPS_RFBAND_50GHZ    0x02
-
-/* Simple Config state */
-#define WPS_SCSTATE_UNCONFIGURED    0x01
-#define WPS_SCSTATE_CONFIGURED      0x02
-#define WPS_SCSTATE_OFF 11
-
-/* WPS Vendor extension key */
-#define WPS_OUI_HEADER_LEN 2
-#define WPS_OUI_HEADER_SIZE 4
-#define WPS_OUI_FIXED_HEADER_OFF 16
-#define WPS_WFA_SUBID_V2_OFF 3
-#define WPS_WFA_V2_OFF 5
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _WPS_ */
diff --git a/drivers/net/wireless/bcmdhd/include/rte_ioctl.h b/drivers/net/wireless/bcmdhd/include/rte_ioctl.h
deleted file mode 100644
index 9c214ae..0000000
--- a/drivers/net/wireless/bcmdhd/include/rte_ioctl.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * HND Run Time Environment ioctl.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: rte_ioctl.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef _rte_ioctl_h_
-#define _rte_ioctl_h_
-
-/* RTE IOCTL definitions for generic ether devices */
-#define RTEGHWADDR		0x8901
-#define RTESHWADDR		0x8902
-#define RTEGMTU			0x8903
-#define RTEGSTATS		0x8904
-#define RTEGALLMULTI		0x8905
-#define RTESALLMULTI		0x8906
-#define RTEGPROMISC		0x8907
-#define RTESPROMISC		0x8908
-#define RTESMULTILIST	0x8909
-#define RTEGUP			0x890A
-#define RTEGPERMADDR		0x890B
-#define RTEDEVPWRSTCHG		0x890C	/* Device pwr state change for PCIedev */
-#define RTEDEVPMETOGGLE		0x890D	/* Toggle PME# to wake up the host */
-
-#define RTE_IOCTL_QUERY			0x00
-#define RTE_IOCTL_SET			0x01
-#define RTE_IOCTL_OVL_IDX_MASK	0x1e
-#define RTE_IOCTL_OVL_RSV		0x20
-#define RTE_IOCTL_OVL			0x40
-#define RTE_IOCTL_OVL_IDX_SHIFT	1
-
-enum hnd_ioctl_cmd {
-	HND_RTE_DNGL_IS_SS = 1, /* true if device connected at super speed */
-
-	/* PCIEDEV specific wl <--> bus ioctls */
-	BUS_GET_VAR = 2,
-	BUS_SET_VAR = 3,
-	BUS_FLUSH_RXREORDER_Q = 4,
-	BUS_SET_LTR_STATE = 5,
-	BUS_FLUSH_CHAINED_PKTS = 6,
-	BUS_SET_COPY_COUNT = 7
-};
-
-#define SDPCMDEV_SET_MAXTXPKTGLOM	1
-
-typedef struct memuse_info {
-	uint16 ver;			/* version of this struct */
-	uint16 len;			/* length in bytes of this structure */
-	uint32 tot;			/* Total memory */
-	uint32 text_len;	/* Size of Text segment memory */
-	uint32 data_len;	/* Size of Data segment memory */
-	uint32 bss_len;		/* Size of BSS segment memory */
-
-	uint32 arena_size;	/* Total Heap size */
-	uint32 arena_free;	/* Heap memory available or free */
-	uint32 inuse_size;	/* Heap memory currently in use */
-	uint32 inuse_hwm;	/* High watermark of memory - reclaimed memory */
-	uint32 inuse_overhead;	/* tally of allocated mem_t blocks */
-	uint32 inuse_total;	/* Heap in-use + Heap overhead memory  */
-} memuse_info_t;
-
-#endif /* _rte_ioctl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h
deleted file mode 100644
index 0f8c52e..0000000
--- a/drivers/net/wireless/bcmdhd/include/sbchipc.h
+++ /dev/null
@@ -1,3761 +0,0 @@
-/*
- * SiliconBackplane Chipcommon core hardware definitions.
- *
- * The chipcommon core provides chip identification, SB control,
- * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer,
- * GPIO interface, extbus, and support for serial and parallel flashes.
- *
- * $Id: sbchipc.h 574579 2015-07-27 15:36:37Z $
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- */
-
-#ifndef	_SBCHIPC_H
-#define	_SBCHIPC_H
-
-#if !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__)
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif	/* PAD */
-
-/**
- * In chipcommon rev 49 the pmu registers have been moved from chipc to the pmu core if the
- * 'AOBPresent' bit of 'CoreCapabilitiesExt' is set. If this field is set, the traditional chipc to
- * [pmu|gci|sreng] register interface is deprecated and removed. These register blocks would instead
- * be assigned their respective chipc-specific address space and connected to the Always On
- * Backplane via the APB interface.
- */
-typedef volatile struct {
-	uint32  PAD[384];
-	uint32	pmucontrol;		/* 0x600 */
-	uint32	pmucapabilities;
-	uint32	pmustatus;
-	uint32	res_state;
-	uint32	res_pending;
-	uint32	pmutimer;
-	uint32	min_res_mask;
-	uint32	max_res_mask;
-	uint32	res_table_sel;
-	uint32	res_dep_mask;
-	uint32	res_updn_timer;
-	uint32	res_timer;
-	uint32	clkstretch;
-	uint32	pmuwatchdog;
-	uint32	gpiosel;		/* 0x638, rev >= 1 */
-	uint32	gpioenable;		/* 0x63c, rev >= 1 */
-	uint32	res_req_timer_sel;
-	uint32	res_req_timer;
-	uint32	res_req_mask;
-	uint32	PAD;
-	uint32	chipcontrol_addr;	/* 0x650 */
-	uint32	chipcontrol_data;	/* 0x654 */
-	uint32	regcontrol_addr;
-	uint32	regcontrol_data;
-	uint32	pllcontrol_addr;
-	uint32	pllcontrol_data;
-	uint32	pmustrapopt;		/* 0x668, corerev >= 28 */
-	uint32	pmu_xtalfreq;		/* 0x66C, pmurev >= 10 */
-	uint32  retention_ctl;		/* 0x670 */
-	uint32  PAD[3];
-	uint32  retention_grpidx;	/* 0x680 */
-	uint32  retention_grpctl;	/* 0x684 */
-	uint32  PAD[20];
-	uint32	pmucontrol_ext;		/* 0x6d8 */
-	uint32	slowclkperiod;		/* 0x6dc */
-	uint32	PAD[8];
-	uint32	pmuintmask0;		/* 0x700 */
-	uint32	pmuintmask1;		/* 0x704 */
-	uint32  PAD[14];
-	uint32  pmuintstatus;		/* 0x740 */
-	uint32	PAD[15];
-	uint32  pmuintctrl0;		/* 0x780 */
-} pmuregs_t;
-
-typedef struct eci_prerev35 {
-	uint32	eci_output;
-	uint32	eci_control;
-	uint32	eci_inputlo;
-	uint32	eci_inputmi;
-	uint32	eci_inputhi;
-	uint32	eci_inputintpolaritylo;
-	uint32	eci_inputintpolaritymi;
-	uint32	eci_inputintpolarityhi;
-	uint32	eci_intmasklo;
-	uint32	eci_intmaskmi;
-	uint32	eci_intmaskhi;
-	uint32	eci_eventlo;
-	uint32	eci_eventmi;
-	uint32	eci_eventhi;
-	uint32	eci_eventmasklo;
-	uint32	eci_eventmaskmi;
-	uint32	eci_eventmaskhi;
-	uint32	PAD[3];
-} eci_prerev35_t;
-
-typedef struct eci_rev35 {
-	uint32	eci_outputlo;
-	uint32	eci_outputhi;
-	uint32	eci_controllo;
-	uint32	eci_controlhi;
-	uint32	eci_inputlo;
-	uint32	eci_inputhi;
-	uint32	eci_inputintpolaritylo;
-	uint32	eci_inputintpolarityhi;
-	uint32	eci_intmasklo;
-	uint32	eci_intmaskhi;
-	uint32	eci_eventlo;
-	uint32	eci_eventhi;
-	uint32	eci_eventmasklo;
-	uint32	eci_eventmaskhi;
-	uint32	eci_auxtx;
-	uint32	eci_auxrx;
-	uint32	eci_datatag;
-	uint32	eci_uartescvalue;
-	uint32	eci_autobaudctr;
-	uint32	eci_uartfifolevel;
-} eci_rev35_t;
-
-typedef struct flash_config {
-	uint32	PAD[19];
-	/* Flash struct configuration registers (0x18c) for BCM4706 (corerev = 31) */
-	uint32 flashstrconfig;
-} flash_config_t;
-
-typedef volatile struct {
-	uint32	chipid;			/* 0x0 */
-	uint32	capabilities;
-	uint32	corecontrol;		/* corerev >= 1 */
-	uint32	bist;
-
-	/* OTP */
-	uint32	otpstatus;		/* 0x10, corerev >= 10 */
-	uint32	otpcontrol;
-	uint32	otpprog;
-	uint32	otplayout;		/* corerev >= 23 */
-
-	/* Interrupt control */
-	uint32	intstatus;		/* 0x20 */
-	uint32	intmask;
-
-	/* Chip specific regs */
-	uint32	chipcontrol;		/* 0x28, rev >= 11 */
-	uint32	chipstatus;		/* 0x2c, rev >= 11 */
-
-	/* Jtag Master */
-	uint32	jtagcmd;		/* 0x30, rev >= 10 */
-	uint32	jtagir;
-	uint32	jtagdr;
-	uint32	jtagctrl;
-
-	/* serial flash interface registers */
-	uint32	flashcontrol;		/* 0x40 */
-	uint32	flashaddress;
-	uint32	flashdata;
-	uint32	otplayoutextension;	/* rev >= 35 */
-
-	/* Silicon backplane configuration broadcast control */
-	uint32	broadcastaddress;	/* 0x50 */
-	uint32	broadcastdata;
-
-	/* gpio - cleared only by power-on-reset */
-	uint32	gpiopullup;		/* 0x58, corerev >= 20 */
-	uint32	gpiopulldown;		/* 0x5c, corerev >= 20 */
-	uint32	gpioin;			/* 0x60 */
-	uint32	gpioout;		/* 0x64 */
-	uint32	gpioouten;		/* 0x68 */
-	uint32	gpiocontrol;		/* 0x6C */
-	uint32	gpiointpolarity;	/* 0x70 */
-	uint32	gpiointmask;		/* 0x74 */
-
-	/* GPIO events corerev >= 11 */
-	uint32	gpioevent;
-	uint32	gpioeventintmask;
-
-	/* Watchdog timer */
-	uint32	watchdog;		/* 0x80 */
-
-	/* GPIO events corerev >= 11 */
-	uint32	gpioeventintpolarity;
-
-	/* GPIO based LED powersave registers corerev >= 16 */
-	uint32  gpiotimerval;		/* 0x88 */
-	uint32  gpiotimeroutmask;
-
-	/* clock control */
-	uint32	clockcontrol_n;		/* 0x90 */
-	uint32	clockcontrol_sb;	/* aka m0 */
-	uint32	clockcontrol_pci;	/* aka m1 */
-	uint32	clockcontrol_m2;	/* mii/uart/mipsref */
-	uint32	clockcontrol_m3;	/* cpu */
-	uint32	clkdiv;			/* corerev >= 3 */
-	uint32	gpiodebugsel;		/* corerev >= 28 */
-	uint32	capabilities_ext;               	/* 0xac  */
-
-	/* pll delay registers (corerev >= 4) */
-	uint32	pll_on_delay;		/* 0xb0 */
-	uint32	fref_sel_delay;
-	uint32	slow_clk_ctl;		/* 5 < corerev < 10 */
-	uint32	PAD;
-
-	/* Instaclock registers (corerev >= 10) */
-	uint32	system_clk_ctl;		/* 0xc0 */
-	uint32	clkstatestretch;
-	uint32	PAD[2];
-
-	/* Indirect backplane access (corerev >= 22) */
-	uint32	bp_addrlow;		/* 0xd0 */
-	uint32	bp_addrhigh;
-	uint32	bp_data;
-	uint32	PAD;
-	uint32	bp_indaccess;
-	/* SPI registers, corerev >= 37 */
-	uint32	gsioctrl;
-	uint32	gsioaddress;
-	uint32	gsiodata;
-
-	/* More clock dividers (corerev >= 32) */
-	uint32	clkdiv2;
-	/* FAB ID (corerev >= 40) */
-	uint32	otpcontrol1;
-	uint32	fabid;			/* 0xf8 */
-
-	/* In AI chips, pointer to erom */
-	uint32	eromptr;		/* 0xfc */
-
-	/* ExtBus control registers (corerev >= 3) */
-	uint32	pcmcia_config;		/* 0x100 */
-	uint32	pcmcia_memwait;
-	uint32	pcmcia_attrwait;
-	uint32	pcmcia_iowait;
-	uint32	ide_config;
-	uint32	ide_memwait;
-	uint32	ide_attrwait;
-	uint32	ide_iowait;
-	uint32	prog_config;
-	uint32	prog_waitcount;
-	uint32	flash_config;
-	uint32	flash_waitcount;
-	uint32  SECI_config;		/* 0x130 SECI configuration */
-	uint32	SECI_status;
-	uint32	SECI_statusmask;
-	uint32	SECI_rxnibchanged;
-
-	uint32	PAD[20];
-
-	/* SROM interface (corerev >= 32) */
-	uint32	sromcontrol;		/* 0x190 */
-	uint32	sromaddress;
-	uint32	sromdata;
-	uint32	PAD[1];				/* 0x19C */
-	/* NAND flash registers for BCM4706 (corerev = 31) */
-	uint32  nflashctrl;         /* 0x1a0 */
-	uint32  nflashconf;
-	uint32  nflashcoladdr;
-	uint32  nflashrowaddr;
-	uint32  nflashdata;
-	uint32  nflashwaitcnt0;		/* 0x1b4 */
-	uint32  PAD[2];
-
-	uint32  seci_uart_data;		/* 0x1C0 */
-	uint32  seci_uart_bauddiv;
-	uint32  seci_uart_fcr;
-	uint32  seci_uart_lcr;
-	uint32  seci_uart_mcr;
-	uint32  seci_uart_lsr;
-	uint32  seci_uart_msr;
-	uint32  seci_uart_baudadj;
-	/* Clock control and hardware workarounds (corerev >= 20) */
-	uint32	clk_ctl_st;		/* 0x1e0 */
-	uint32	hw_war;
-	uint32	PAD[70];
-
-	/* UARTs */
-	uint8	uart0data;		/* 0x300 */
-	uint8	uart0imr;
-	uint8	uart0fcr;
-	uint8	uart0lcr;
-	uint8	uart0mcr;
-	uint8	uart0lsr;
-	uint8	uart0msr;
-	uint8	uart0scratch;
-	uint8	PAD[248];		/* corerev >= 1 */
-
-	uint8	uart1data;		/* 0x400 */
-	uint8	uart1imr;
-	uint8	uart1fcr;
-	uint8	uart1lcr;
-	uint8	uart1mcr;
-	uint8	uart1lsr;
-	uint8	uart1msr;
-	uint8	uart1scratch;		/* 0x407 */
-	uint32	PAD[62];
-
-	/* save/restore, corerev >= 48 */
-	uint32	sr_capability;		/* 0x500 */
-	uint32	sr_control0;		/* 0x504 */
-	uint32	sr_control1;		/* 0x508 */
-	uint32  gpio_control;		/* 0x50C */
-	uint32	PAD[60];
-
-	/* PMU registers (corerev >= 20) */
-	/* Note: all timers driven by ILP clock are updated asynchronously to HT/ALP.
-	 * The CPU must read them twice, compare, and retry if different.
-	 */
-	uint32	pmucontrol;		/* 0x600 */
-	uint32	pmucapabilities;
-	uint32	pmustatus;
-	uint32	res_state;
-	uint32	res_pending;
-	uint32	pmutimer;
-	uint32	min_res_mask;
-	uint32	max_res_mask;
-	uint32	res_table_sel;
-	uint32	res_dep_mask;
-	uint32	res_updn_timer;
-	uint32	res_timer;
-	uint32	clkstretch;
-	uint32	pmuwatchdog;
-	uint32	gpiosel;		/* 0x638, rev >= 1 */
-	uint32	gpioenable;		/* 0x63c, rev >= 1 */
-	uint32	res_req_timer_sel;
-	uint32	res_req_timer;
-	uint32	res_req_mask;
-	uint32	PAD;
-	uint32	chipcontrol_addr;	/* 0x650 */
-	uint32	chipcontrol_data;	/* 0x654 */
-	uint32	regcontrol_addr;
-	uint32	regcontrol_data;
-	uint32	pllcontrol_addr;
-	uint32	pllcontrol_data;
-	uint32	pmustrapopt;		/* 0x668, corerev >= 28 */
-	uint32	pmu_xtalfreq;		/* 0x66C, pmurev >= 10 */
-	uint32  retention_ctl;		/* 0x670 */
-	uint32  PAD[3];
-	uint32  retention_grpidx;	/* 0x680 */
-	uint32  retention_grpctl;	/* 0x684 */
-	uint32  PAD[20];
-	uint32	pmucontrol_ext;		/* 0x6d8 */
-	uint32	slowclkperiod;		/* 0x6dc */
-	uint32	PAD[8];
-	uint32	pmuintmask0;		/* 0x700 */
-	uint32	pmuintmask1;		/* 0x704 */
-	uint32  PAD[14];
-	uint32  pmuintstatus;		/* 0x740 */
-	uint32	PAD[15];
-	uint32  pmuintctrl0;		/* 0x780 */
-	uint32  PAD[31];
-	uint16	sromotp[512];		/* 0x800 */
-#ifdef CCNFLASH_SUPPORT
-	/* Nand flash MLC controller registers (corerev >= 38) */
-	uint32	nand_revision;		/* 0xC00 */
-	uint32	nand_cmd_start;
-	uint32	nand_cmd_addr_x;
-	uint32	nand_cmd_addr;
-	uint32	nand_cmd_end_addr;
-	uint32	nand_cs_nand_select;
-	uint32	nand_cs_nand_xor;
-	uint32	PAD;
-	uint32	nand_spare_rd0;
-	uint32	nand_spare_rd4;
-	uint32	nand_spare_rd8;
-	uint32	nand_spare_rd12;
-	uint32	nand_spare_wr0;
-	uint32	nand_spare_wr4;
-	uint32	nand_spare_wr8;
-	uint32	nand_spare_wr12;
-	uint32	nand_acc_control;
-	uint32	PAD;
-	uint32	nand_config;
-	uint32	PAD;
-	uint32	nand_timing_1;
-	uint32	nand_timing_2;
-	uint32	nand_semaphore;
-	uint32	PAD;
-	uint32	nand_devid;
-	uint32	nand_devid_x;
-	uint32	nand_block_lock_status;
-	uint32	nand_intfc_status;
-	uint32	nand_ecc_corr_addr_x;
-	uint32	nand_ecc_corr_addr;
-	uint32	nand_ecc_unc_addr_x;
-	uint32	nand_ecc_unc_addr;
-	uint32	nand_read_error_count;
-	uint32	nand_corr_stat_threshold;
-	uint32	PAD[2];
-	uint32	nand_read_addr_x;
-	uint32	nand_read_addr;
-	uint32	nand_page_program_addr_x;
-	uint32	nand_page_program_addr;
-	uint32	nand_copy_back_addr_x;
-	uint32	nand_copy_back_addr;
-	uint32	nand_block_erase_addr_x;
-	uint32	nand_block_erase_addr;
-	uint32	nand_inv_read_addr_x;
-	uint32	nand_inv_read_addr;
-	uint32	PAD[2];
-	uint32	nand_blk_wr_protect;
-	uint32	PAD[3];
-	uint32	nand_acc_control_cs1;
-	uint32	nand_config_cs1;
-	uint32	nand_timing_1_cs1;
-	uint32	nand_timing_2_cs1;
-	uint32	PAD[20];
-	uint32	nand_spare_rd16;
-	uint32	nand_spare_rd20;
-	uint32	nand_spare_rd24;
-	uint32	nand_spare_rd28;
-	uint32	nand_cache_addr;
-	uint32	nand_cache_data;
-	uint32	nand_ctrl_config;
-	uint32	nand_ctrl_status;
-#endif /* CCNFLASH_SUPPORT */
-	uint32  gci_corecaps0; /* GCI starting at 0xC00 */
-	uint32  gci_corecaps1;
-	uint32  gci_corecaps2;
-	uint32  gci_corectrl;
-	uint32  gci_corestat; /* 0xC10 */
-	uint32  gci_intstat; /* 0xC14 */
-	uint32  gci_intmask; /* 0xC18 */
-	uint32  gci_wakemask; /* 0xC1C */
-	uint32  gci_levelintstat; /* 0xC20 */
-	uint32  gci_eventintstat; /* 0xC24 */
-	uint32  PAD[6];
-	uint32  gci_indirect_addr; /* 0xC40 */
-	uint32  gci_gpioctl; /* 0xC44 */
-	uint32	gci_gpiostatus;
-	uint32  gci_gpiomask; /* 0xC4C */
-	uint32  PAD;
-	uint32  gci_miscctl; /* 0xC54 */
-	uint32	gci_gpiointmask;
-	uint32	gci_gpiowakemask;
-	uint32  gci_input[32]; /* C60 */
-	uint32  gci_event[32]; /* CE0 */
-	uint32  gci_output[4]; /* D60 */
-	uint32  gci_control_0; /* 0xD70 */
-	uint32  gci_control_1; /* 0xD74 */
-	uint32  gci_intpolreg; /* 0xD78 */
-	uint32  gci_levelintmask; /* 0xD7C */
-	uint32  gci_eventintmask; /* 0xD80 */
-	uint32  PAD[3];
-	uint32  gci_inbandlevelintmask; /* 0xD90 */
-	uint32  gci_inbandeventintmask; /* 0xD94 */
-	uint32  PAD[2];
-	uint32  gci_seciauxtx; /* 0xDA0 */
-	uint32  gci_seciauxrx; /* 0xDA4 */
-	uint32  gci_secitx_datatag; /* 0xDA8 */
-	uint32  gci_secirx_datatag; /* 0xDAC */
-	uint32  gci_secitx_datamask; /* 0xDB0 */
-	uint32  gci_seciusef0tx_reg; /* 0xDB4 */
-	uint32  gci_secif0tx_offset; /* 0xDB8 */
-	uint32  gci_secif0rx_offset; /* 0xDBC */
-	uint32  gci_secif1tx_offset; /* 0xDC0 */
-	uint32	gci_rxfifo_common_ctrl; /* 0xDC4 */
-	uint32	gci_rxfifoctrl; /* 0xDC8 */
-	uint32	gci_uartreadid; /* DCC */
-	uint32  gci_uartescval; /* DD0 */
-	uint32	PAD;
-	uint32	gci_secififolevel; /* DD8 */
-	uint32	gci_seciuartdata; /* DDC */
-	uint32  gci_secibauddiv; /* DE0 */
-	uint32  gci_secifcr; /* DE4 */
-	uint32  gci_secilcr; /* DE8 */
-	uint32  gci_secimcr; /* DEC */
-	uint32	gci_secilsr; /* DF0 */
-	uint32	gci_secimsr; /* DF4 */
-	uint32  gci_baudadj; /* DF8 */
-	uint32  PAD;
-	uint32  gci_chipctrl; /* 0xE00 */
-	uint32  gci_chipsts; /* 0xE04 */
-	uint32	gci_gpioout; /* 0xE08 */
-	uint32	gci_gpioout_read; /* 0xE0C */
-	uint32	gci_mpwaketx; /* 0xE10 */
-	uint32	gci_mpwakedetect; /* 0xE14 */
-	uint32	gci_seciin_ctrl; /* 0xE18 */
-	uint32	gci_seciout_ctrl; /* 0xE1C */
-	uint32	gci_seciin_auxfifo_en; /* 0xE20 */
-	uint32	gci_seciout_txen_txbr; /* 0xE24 */
-	uint32	gci_seciin_rxbrstatus; /* 0xE28 */
-	uint32	gci_seciin_rxerrstatus; /* 0xE2C */
-	uint32	gci_seciin_fcstatus; /* 0xE30 */
-	uint32	gci_seciout_txstatus; /* 0xE34 */
-	uint32	gci_seciout_txbrstatus; /* 0xE38 */
-} chipcregs_t;
-
-#endif /* !_LANGUAGE_ASSEMBLY && !__ASSEMBLY__ */
-
-
-#define	CC_CHIPID		0
-#define	CC_CAPABILITIES		4
-#define	CC_CHIPST		0x2c
-#define	CC_EROMPTR		0xfc
-
-#define	CC_OTPST		0x10
-#define	CC_INTSTATUS		0x20
-#define	CC_INTMASK		0x24
-#define	CC_JTAGCMD		0x30
-#define	CC_JTAGIR		0x34
-#define	CC_JTAGDR		0x38
-#define	CC_JTAGCTRL		0x3c
-#define	CC_GPIOPU		0x58
-#define	CC_GPIOPD		0x5c
-#define	CC_GPIOIN		0x60
-#define	CC_GPIOOUT		0x64
-#define	CC_GPIOOUTEN		0x68
-#define	CC_GPIOCTRL		0x6c
-#define	CC_GPIOPOL		0x70
-#define	CC_GPIOINTM		0x74
-#define	CC_GPIOEVENT		0x78
-#define	CC_GPIOEVENTMASK	0x7c
-#define	CC_WATCHDOG		0x80
-#define	CC_GPIOEVENTPOL		0x84
-#define	CC_CLKC_N		0x90
-#define	CC_CLKC_M0		0x94
-#define	CC_CLKC_M1		0x98
-#define	CC_CLKC_M2		0x9c
-#define	CC_CLKC_M3		0xa0
-#define	CC_CLKDIV		0xa4
-#define	CC_CAP_EXT		0xac
-#define	CC_SYS_CLK_CTL		0xc0
-#define	CC_CLKDIV2		0xf0
-#define	CC_CLK_CTL_ST		SI_CLK_CTL_ST
-#define	PMU_CTL			0x600
-#define	PMU_CAP			0x604
-#define	PMU_ST			0x608
-#define PMU_RES_STATE		0x60c
-#define PMU_RES_PENDING		0x610
-#define PMU_TIMER		0x614
-#define	PMU_MIN_RES_MASK	0x618
-#define	PMU_MAX_RES_MASK	0x61c
-#define CC_CHIPCTL_ADDR         0x650
-#define CC_CHIPCTL_DATA         0x654
-#define PMU_REG_CONTROL_ADDR	0x658
-#define PMU_REG_CONTROL_DATA	0x65C
-#define PMU_PLL_CONTROL_ADDR 	0x660
-#define PMU_PLL_CONTROL_DATA 	0x664
-#define CC_SROM_CTRL		0x190
-#define	CC_SROM_OTP		0x800		/* SROM/OTP address space */
-#define CC_GCI_INDIRECT_ADDR_REG	0xC40
-#define CC_GCI_CHIP_CTRL_REG	0xE00
-#define CC_GCI_CC_OFFSET_2	2
-#define CC_GCI_CC_OFFSET_5	5
-#define CC_SWD_CTRL		0x380
-#define CC_SWD_REQACK		0x384
-#define CC_SWD_DATA		0x388
-
-
-#define CHIPCTRLREG0 0x0
-#define CHIPCTRLREG1 0x1
-#define CHIPCTRLREG2 0x2
-#define CHIPCTRLREG3 0x3
-#define CHIPCTRLREG4 0x4
-#define CHIPCTRLREG5 0x5
-#define CHIPCTRLREG6 0x6
-#define REGCTRLREG4 0x4
-#define REGCTRLREG5 0x5
-#define REGCTRLREG6 0x6
-#define MINRESMASKREG 0x618
-#define MAXRESMASKREG 0x61c
-#define CHIPCTRLADDR 0x650
-#define CHIPCTRLDATA 0x654
-#define RSRCTABLEADDR 0x620
-#define PMU_RES_DEP_MASK 0x624
-#define RSRCUPDWNTIME 0x628
-#define PMUREG_RESREQ_MASK 0x68c
-#define PMUREG_RESREQ_TIMER 0x688
-#define PMUREG_RESREQ_MASK1 0x6f4
-#define PMUREG_RESREQ_TIMER1 0x6f0
-#define EXT_LPO_AVAIL 0x100
-#define LPO_SEL					(1 << 0)
-#define CC_EXT_LPO_PU 0x200000
-#define GC_EXT_LPO_PU 0x2
-#define CC_INT_LPO_PU 0x100000
-#define GC_INT_LPO_PU 0x1
-#define EXT_LPO_SEL 0x8
-#define INT_LPO_SEL 0x4
-#define ENABLE_FINE_CBUCK_CTRL 			(1 << 30)
-#define REGCTRL5_PWM_AUTO_CTRL_MASK 		0x007e0000
-#define REGCTRL5_PWM_AUTO_CTRL_SHIFT		17
-#define REGCTRL6_PWM_AUTO_CTRL_MASK 		0x3fff0000
-#define REGCTRL6_PWM_AUTO_CTRL_SHIFT		16
-#define CC_BP_IND_ACCESS_START_SHIFT		9
-#define CC_BP_IND_ACCESS_START_MASK		(1 << CC_BP_IND_ACCESS_START_SHIFT)
-#define CC_BP_IND_ACCESS_RDWR_SHIFT		8
-#define CC_BP_IND_ACCESS_RDWR_MASK		(1 << CC_BP_IND_ACCESS_RDWR_SHIFT)
-#define CC_BP_IND_ACCESS_ERROR_SHIFT		10
-#define CC_BP_IND_ACCESS_ERROR_MASK		(1 << CC_BP_IND_ACCESS_ERROR_SHIFT)
-
-#ifdef SR_DEBUG
-#define SUBCORE_POWER_ON 0x0001
-#define PHY_POWER_ON 0x0010
-#define VDDM_POWER_ON 0x0100
-#define MEMLPLDO_POWER_ON 0x1000
-#define SUBCORE_POWER_ON_CHK 0x00040000
-#define PHY_POWER_ON_CHK 0x00080000
-#define VDDM_POWER_ON_CHK 0x00100000
-#define MEMLPLDO_POWER_ON_CHK 0x00200000
-#endif /* SR_DEBUG */
-
-#ifdef CCNFLASH_SUPPORT
-/* NAND flash support */
-#define CC_NAND_REVISION	0xC00
-#define CC_NAND_CMD_START	0xC04
-#define CC_NAND_CMD_ADDR	0xC0C
-#define CC_NAND_SPARE_RD_0	0xC20
-#define CC_NAND_SPARE_RD_4	0xC24
-#define CC_NAND_SPARE_RD_8	0xC28
-#define CC_NAND_SPARE_RD_C	0xC2C
-#define CC_NAND_CONFIG		0xC48
-#define CC_NAND_DEVID		0xC60
-#define CC_NAND_DEVID_EXT	0xC64
-#define CC_NAND_INTFC_STATUS	0xC6C
-#endif /* CCNFLASH_SUPPORT */
-
-/* chipid */
-#define	CID_ID_MASK		0x0000ffff	/**< Chip Id mask */
-#define	CID_REV_MASK		0x000f0000	/**< Chip Revision mask */
-#define	CID_REV_SHIFT		16		/**< Chip Revision shift */
-#define	CID_PKG_MASK		0x00f00000	/**< Package Option mask */
-#define	CID_PKG_SHIFT		20		/**< Package Option shift */
-#define	CID_CC_MASK		0x0f000000	/**< CoreCount (corerev >= 4) */
-#define CID_CC_SHIFT		24
-#define	CID_TYPE_MASK		0xf0000000	/**< Chip Type */
-#define CID_TYPE_SHIFT		28
-
-/* capabilities */
-#define	CC_CAP_UARTS_MASK	0x00000003	/**< Number of UARTs */
-#define CC_CAP_MIPSEB		0x00000004	/**< MIPS is in big-endian mode */
-#define CC_CAP_UCLKSEL		0x00000018	/**< UARTs clock select */
-#define CC_CAP_UINTCLK		0x00000008	/**< UARTs are driven by internal divided clock */
-#define CC_CAP_UARTGPIO		0x00000020	/**< UARTs own GPIOs 15:12 */
-#define CC_CAP_EXTBUS_MASK	0x000000c0	/**< External bus mask */
-#define CC_CAP_EXTBUS_NONE	0x00000000	/**< No ExtBus present */
-#define CC_CAP_EXTBUS_FULL	0x00000040	/**< ExtBus: PCMCIA, IDE & Prog */
-#define CC_CAP_EXTBUS_PROG	0x00000080	/**< ExtBus: ProgIf only */
-#define	CC_CAP_FLASH_MASK	0x00000700	/**< Type of flash */
-#define	CC_CAP_PLL_MASK		0x00038000	/**< Type of PLL */
-#define CC_CAP_PWR_CTL		0x00040000	/**< Power control */
-#define CC_CAP_OTPSIZE		0x00380000	/**< OTP Size (0 = none) */
-#define CC_CAP_OTPSIZE_SHIFT	19		/**< OTP Size shift */
-#define CC_CAP_OTPSIZE_BASE	5		/**< OTP Size base */
-#define CC_CAP_JTAGP		0x00400000	/**< JTAG Master Present */
-#define CC_CAP_ROM		0x00800000	/**< Internal boot rom active */
-#define CC_CAP_BKPLN64		0x08000000	/**< 64-bit backplane */
-#define	CC_CAP_PMU		0x10000000	/**< PMU Present, rev >= 20 */
-#define	CC_CAP_ECI		0x20000000	/**< ECI Present, rev >= 21 */
-#define	CC_CAP_SROM		0x40000000	/**< Srom Present, rev >= 32 */
-#define	CC_CAP_NFLASH		0x80000000	/**< Nand flash present, rev >= 35 */
-
-#define	CC_CAP2_SECI		0x00000001	/**< SECI Present, rev >= 36 */
-#define	CC_CAP2_GSIO		0x00000002	/**< GSIO (spi/i2c) present, rev >= 37 */
-
-/* capabilities extension */
-#define CC_CAP_EXT_SECI_PRESENT	0x00000001	/**< SECI present */
-#define CC_CAP_EXT_GSIO_PRESENT	0x00000002	/**< GSIO present */
-#define CC_CAP_EXT_GCI_PRESENT  0x00000004	/**< GCI present */
-#define CC_CAP_EXT_AOB_PRESENT  0x00000040	/**< AOB present */
-#define CC_CAP_EXT_SWD_PRESENT  0x00000400	/**< SWD present */
-
-/* WL Channel Info to BT via GCI - bits 40 - 47 */
-#define GCI_WL_CHN_INFO_MASK	(0xFF00)
-/* bits [51:48] - reserved for wlan TX pwr index */
-/* bits [55:52] btc mode indication */
-#define GCI_WL_BTC_MODE_SHIFT	(20)
-#define GCI_WL_BTC_MODE_MASK	(0xF << GCI_WL_BTC_MODE_SHIFT)
-#define GCI_WL_ANT_BIT_MASK	(0x00c0)
-#define GCI_WL_ANT_SHIFT_BITS	(6)
-/* PLL type */
-#define PLL_NONE		0x00000000
-#define PLL_TYPE1		0x00010000	/**< 48MHz base, 3 dividers */
-#define PLL_TYPE2		0x00020000	/**< 48MHz, 4 dividers */
-#define PLL_TYPE3		0x00030000	/**< 25MHz, 2 dividers */
-#define PLL_TYPE4		0x00008000	/**< 48MHz, 4 dividers */
-#define PLL_TYPE5		0x00018000	/**< 25MHz, 4 dividers */
-#define PLL_TYPE6		0x00028000	/**< 100/200 or 120/240 only */
-#define PLL_TYPE7		0x00038000	/**< 25MHz, 4 dividers */
-
-/* ILP clock */
-#define	ILP_CLOCK		32000
-
-/* ALP clock on pre-PMU chips */
-#define	ALP_CLOCK		20000000
-
-#ifdef CFG_SIM
-#define NS_ALP_CLOCK		84922
-#define NS_SLOW_ALP_CLOCK	84922
-#define NS_CPU_CLOCK		534500
-#define NS_SLOW_CPU_CLOCK	534500
-#define NS_SI_CLOCK		271750
-#define NS_SLOW_SI_CLOCK	271750
-#define NS_FAST_MEM_CLOCK	271750
-#define NS_MEM_CLOCK		271750
-#define NS_SLOW_MEM_CLOCK	271750
-#else
-#define NS_ALP_CLOCK		125000000
-#define NS_SLOW_ALP_CLOCK	100000000
-#define NS_CPU_CLOCK		1000000000
-#define NS_SLOW_CPU_CLOCK	800000000
-#define NS_SI_CLOCK		250000000
-#define NS_SLOW_SI_CLOCK	200000000
-#define NS_FAST_MEM_CLOCK	800000000
-#define NS_MEM_CLOCK		533000000
-#define NS_SLOW_MEM_CLOCK	400000000
-#endif /* CFG_SIM */
-
-/* HT clock */
-#define	HT_CLOCK		80000000
-
-/* corecontrol */
-#define CC_UARTCLKO		0x00000001	/**< Drive UART with internal clock */
-#define	CC_SE			0x00000002	/**< sync clk out enable (corerev >= 3) */
-#define CC_ASYNCGPIO	0x00000004	/**< 1=generate GPIO interrupt without backplane clock */
-#define CC_UARTCLKEN		0x00000008	/**< enable UART Clock (corerev > = 21 */
-
-/* retention_ctl */
-#define RCTL_MEM_RET_SLEEP_LOG_SHIFT	29
-#define RCTL_MEM_RET_SLEEP_LOG_MASK	(1 << RCTL_MEM_RET_SLEEP_LOG_SHIFT)
-
-/* 4321 chipcontrol */
-#define CHIPCTRL_4321A0_DEFAULT	0x3a4
-#define CHIPCTRL_4321A1_DEFAULT	0x0a4
-#define CHIPCTRL_4321_PLL_DOWN	0x800000	/**< serdes PLL down override */
-
-/* Fields in the otpstatus register in rev >= 21 */
-#define OTPS_OL_MASK		0x000000ff
-#define OTPS_OL_MFG		0x00000001	/**< manuf row is locked */
-#define OTPS_OL_OR1		0x00000002	/**< otp redundancy row 1 is locked */
-#define OTPS_OL_OR2		0x00000004	/**< otp redundancy row 2 is locked */
-#define OTPS_OL_GU		0x00000008	/**< general use region is locked */
-#define OTPS_GUP_MASK		0x00000f00
-#define OTPS_GUP_SHIFT		8
-#define OTPS_GUP_HW		0x00000100	/**< h/w subregion is programmed */
-#define OTPS_GUP_SW		0x00000200	/**< s/w subregion is programmed */
-#define OTPS_GUP_CI		0x00000400	/**< chipid/pkgopt subregion is programmed */
-#define OTPS_GUP_FUSE		0x00000800	/**< fuse subregion is programmed */
-#define OTPS_READY		0x00001000
-#define OTPS_RV(x)		(1 << (16 + (x)))	/**< redundancy entry valid */
-#define OTPS_RV_MASK		0x0fff0000
-#define OTPS_PROGOK     0x40000000
-
-/* Fields in the otpcontrol register in rev >= 21 */
-#define OTPC_PROGSEL		0x00000001
-#define OTPC_PCOUNT_MASK	0x0000000e
-#define OTPC_PCOUNT_SHIFT	1
-#define OTPC_VSEL_MASK		0x000000f0
-#define OTPC_VSEL_SHIFT		4
-#define OTPC_TMM_MASK		0x00000700
-#define OTPC_TMM_SHIFT		8
-#define OTPC_ODM		0x00000800
-#define OTPC_PROGEN		0x80000000
-
-/* Fields in the 40nm otpcontrol register in rev >= 40 */
-#define OTPC_40NM_PROGSEL_SHIFT	0
-#define OTPC_40NM_PCOUNT_SHIFT	1
-#define OTPC_40NM_PCOUNT_WR	0xA
-#define OTPC_40NM_PCOUNT_V1X	0xB
-#define OTPC_40NM_REGCSEL_SHIFT	5
-#define OTPC_40NM_REGCSEL_DEF	0x4
-#define OTPC_40NM_PROGIN_SHIFT	8
-#define OTPC_40NM_R2X_SHIFT	10
-#define OTPC_40NM_ODM_SHIFT	11
-#define OTPC_40NM_DF_SHIFT	15
-#define OTPC_40NM_VSEL_SHIFT	16
-#define OTPC_40NM_VSEL_WR	0xA
-#define OTPC_40NM_VSEL_V1X	0xA
-#define OTPC_40NM_VSEL_R1X	0x5
-#define OTPC_40NM_COFAIL_SHIFT	30
-
-#define OTPC1_CPCSEL_SHIFT	0
-#define OTPC1_CPCSEL_DEF	6
-#define OTPC1_TM_SHIFT		8
-#define OTPC1_TM_WR		0x84
-#define OTPC1_TM_V1X		0x84
-#define OTPC1_TM_R1X		0x4
-#define OTPC1_CLK_EN_MASK	0x00020000
-#define OTPC1_CLK_DIV_MASK	0x00FC0000
-
-/* Fields in otpprog in rev >= 21 and HND OTP */
-#define OTPP_COL_MASK		0x000000ff
-#define OTPP_COL_SHIFT		0
-#define OTPP_ROW_MASK		0x0000ff00
-#define OTPP_ROW_MASK9		0x0001ff00		/* for ccrev >= 49 */
-#define OTPP_ROW_SHIFT		8
-#define OTPP_OC_MASK		0x0f000000
-#define OTPP_OC_SHIFT		24
-#define OTPP_READERR		0x10000000
-#define OTPP_VALUE_MASK		0x20000000
-#define OTPP_VALUE_SHIFT	29
-#define OTPP_START_BUSY		0x80000000
-#define	OTPP_READ		0x40000000	/* HND OTP */
-
-/* Fields in otplayout register */
-#define OTPL_HWRGN_OFF_MASK	0x00000FFF
-#define OTPL_HWRGN_OFF_SHIFT	0
-#define OTPL_WRAP_REVID_MASK	0x00F80000
-#define OTPL_WRAP_REVID_SHIFT	19
-#define OTPL_WRAP_TYPE_MASK	0x00070000
-#define OTPL_WRAP_TYPE_SHIFT	16
-#define OTPL_WRAP_TYPE_65NM	0
-#define OTPL_WRAP_TYPE_40NM	1
-#define OTPL_ROW_SIZE_MASK	0x0000F000
-#define OTPL_ROW_SIZE_SHIFT	12
-
-/* otplayout reg corerev >= 36 */
-#define OTP_CISFORMAT_NEW	0x80000000
-
-/* Opcodes for OTPP_OC field */
-#define OTPPOC_READ		0
-#define OTPPOC_BIT_PROG		1
-#define OTPPOC_VERIFY		3
-#define OTPPOC_INIT		4
-#define OTPPOC_SET		5
-#define OTPPOC_RESET		6
-#define OTPPOC_OCST		7
-#define OTPPOC_ROW_LOCK		8
-#define OTPPOC_PRESCN_TEST	9
-
-/* Opcodes for OTPP_OC field (40NM) */
-#define OTPPOC_READ_40NM	0
-#define OTPPOC_PROG_ENABLE_40NM 1
-#define OTPPOC_PROG_DISABLE_40NM	2
-#define OTPPOC_VERIFY_40NM	3
-#define OTPPOC_WORD_VERIFY_1_40NM	4
-#define OTPPOC_ROW_LOCK_40NM	5
-#define OTPPOC_STBY_40NM	6
-#define OTPPOC_WAKEUP_40NM	7
-#define OTPPOC_WORD_VERIFY_0_40NM	8
-#define OTPPOC_PRESCN_TEST_40NM 9
-#define OTPPOC_BIT_PROG_40NM	10
-#define OTPPOC_WORDPROG_40NM	11
-#define OTPPOC_BURNIN_40NM	12
-#define OTPPOC_AUTORELOAD_40NM	13
-#define OTPPOC_OVST_READ_40NM	14
-#define OTPPOC_OVST_PROG_40NM	15
-
-/* Fields in otplayoutextension */
-#define OTPLAYOUTEXT_FUSE_MASK	0x3FF
-
-
-/* Jtagm characteristics that appeared at a given corerev */
-#define	JTAGM_CREV_OLD		10	/**< Old command set, 16bit max IR */
-#define	JTAGM_CREV_IRP		22	/**< Able to do pause-ir */
-#define	JTAGM_CREV_RTI		28	/**< Able to do return-to-idle */
-
-/* jtagcmd */
-#define JCMD_START		0x80000000
-#define JCMD_BUSY		0x80000000
-#define JCMD_STATE_MASK		0x60000000
-#define JCMD_STATE_TLR		0x00000000	/**< Test-logic-reset */
-#define JCMD_STATE_PIR		0x20000000	/**< Pause IR */
-#define JCMD_STATE_PDR		0x40000000	/**< Pause DR */
-#define JCMD_STATE_RTI		0x60000000	/**< Run-test-idle */
-#define JCMD0_ACC_MASK		0x0000f000
-#define JCMD0_ACC_IRDR		0x00000000
-#define JCMD0_ACC_DR		0x00001000
-#define JCMD0_ACC_IR		0x00002000
-#define JCMD0_ACC_RESET		0x00003000
-#define JCMD0_ACC_IRPDR		0x00004000
-#define JCMD0_ACC_PDR		0x00005000
-#define JCMD0_IRW_MASK		0x00000f00
-#define JCMD_ACC_MASK		0x000f0000	/**< Changes for corerev 11 */
-#define JCMD_ACC_IRDR		0x00000000
-#define JCMD_ACC_DR		0x00010000
-#define JCMD_ACC_IR		0x00020000
-#define JCMD_ACC_RESET		0x00030000
-#define JCMD_ACC_IRPDR		0x00040000
-#define JCMD_ACC_PDR		0x00050000
-#define JCMD_ACC_PIR		0x00060000
-#define JCMD_ACC_IRDR_I		0x00070000	/**< rev 28: return to run-test-idle */
-#define JCMD_ACC_DR_I		0x00080000	/**< rev 28: return to run-test-idle */
-#define JCMD_IRW_MASK		0x00001f00
-#define JCMD_IRW_SHIFT		8
-#define JCMD_DRW_MASK		0x0000003f
-
-/* jtagctrl */
-#define JCTRL_FORCE_CLK		4		/**< Force clock */
-#define JCTRL_EXT_EN		2		/**< Enable external targets */
-#define JCTRL_EN		1		/**< Enable Jtag master */
-#define JCTRL_TAPSEL_BIT	0x00000008	/**< JtagMasterCtrl tap_sel bit */
-
-/* swdmasterctrl */
-#define SWDCTRL_INT_EN		8		/**< Enable internal targets */
-#define SWDCTRL_FORCE_CLK	4		/**< Force clock */
-#define SWDCTRL_OVJTAG		2		/**< Enable shared SWD/JTAG pins */
-#define SWDCTRL_EN		1		/**< Enable Jtag master */
-
-/* Fields in clkdiv */
-#define	CLKD_SFLASH		0x1f000000
-#define	CLKD_SFLASH_SHIFT	24
-#define	CLKD_OTP		0x000f0000
-#define	CLKD_OTP_SHIFT		16
-#define	CLKD_JTAG		0x00000f00
-#define	CLKD_JTAG_SHIFT		8
-#define	CLKD_UART		0x000000ff
-
-#define	CLKD2_SROM		0x00000003
-#define	CLKD2_SWD		0xf8000000
-#define	CLKD2_SWD_SHIFT		27
-
-/* intstatus/intmask */
-#define	CI_GPIO			0x00000001	/**< gpio intr */
-#define	CI_EI			0x00000002	/**< extif intr (corerev >= 3) */
-#define	CI_TEMP			0x00000004	/**< temp. ctrl intr (corerev >= 15) */
-#define	CI_SIRQ			0x00000008	/**< serial IRQ intr (corerev >= 15) */
-#define	CI_ECI			0x00000010	/**< eci intr (corerev >= 21) */
-#define	CI_PMU			0x00000020	/**< pmu intr (corerev >= 21) */
-#define	CI_UART			0x00000040	/**< uart intr (corerev >= 21) */
-#define	CI_WDRESET		0x80000000	/**< watchdog reset occurred */
-
-/* slow_clk_ctl */
-#define SCC_SS_MASK		0x00000007	/**< slow clock source mask */
-#define	SCC_SS_LPO		0x00000000	/**< source of slow clock is LPO */
-#define	SCC_SS_XTAL		0x00000001	/**< source of slow clock is crystal */
-#define	SCC_SS_PCI		0x00000002	/**< source of slow clock is PCI */
-#define SCC_LF			0x00000200	/**< LPOFreqSel, 1: 160Khz, 0: 32KHz */
-#define SCC_LP			0x00000400	/**< LPOPowerDown, 1: LPO is disabled,
-						 * 0: LPO is enabled
-						 */
-#define SCC_FS			0x00000800 /**< ForceSlowClk, 1: sb/cores running on slow clock,
-						 * 0: power logic control
-						 */
-#define SCC_IP			0x00001000 /**< IgnorePllOffReq, 1/0: power logic ignores/honors
-						 * PLL clock disable requests from core
-						 */
-#define SCC_XC			0x00002000	/**< XtalControlEn, 1/0: power logic does/doesn't
-						 * disable crystal when appropriate
-						 */
-#define SCC_XP			0x00004000	/**< XtalPU (RO), 1/0: crystal running/disabled */
-#define SCC_CD_MASK		0xffff0000	/**< ClockDivider (SlowClk = 1/(4+divisor)) */
-#define SCC_CD_SHIFT		16
-
-/* system_clk_ctl */
-#define	SYCC_IE			0x00000001	/**< ILPen: Enable Idle Low Power */
-#define	SYCC_AE			0x00000002	/**< ALPen: Enable Active Low Power */
-#define	SYCC_FP			0x00000004	/**< ForcePLLOn */
-#define	SYCC_AR			0x00000008	/**< Force ALP (or HT if ALPen is not set */
-#define	SYCC_HR			0x00000010	/**< Force HT */
-#define SYCC_CD_MASK		0xffff0000	/**< ClkDiv  (ILP = 1/(4 * (divisor + 1)) */
-#define SYCC_CD_SHIFT		16
-
-/* Indirect backplane access */
-#define	BPIA_BYTEEN		0x0000000f
-#define	BPIA_SZ1		0x00000001
-#define	BPIA_SZ2		0x00000003
-#define	BPIA_SZ4		0x00000007
-#define	BPIA_SZ8		0x0000000f
-#define	BPIA_WRITE		0x00000100
-#define	BPIA_START		0x00000200
-#define	BPIA_BUSY		0x00000200
-#define	BPIA_ERROR		0x00000400
-
-/* pcmcia/prog/flash_config */
-#define	CF_EN			0x00000001	/**< enable */
-#define	CF_EM_MASK		0x0000000e	/**< mode */
-#define	CF_EM_SHIFT		1
-#define	CF_EM_FLASH		0		/**< flash/asynchronous mode */
-#define	CF_EM_SYNC		2		/**< synchronous mode */
-#define	CF_EM_PCMCIA		4		/**< pcmcia mode */
-#define	CF_DS			0x00000010	/**< destsize:  0=8bit, 1=16bit */
-#define	CF_BS			0x00000020	/**< byteswap */
-#define	CF_CD_MASK		0x000000c0	/**< clock divider */
-#define	CF_CD_SHIFT		6
-#define	CF_CD_DIV2		0x00000000	/**< backplane/2 */
-#define	CF_CD_DIV3		0x00000040	/**< backplane/3 */
-#define	CF_CD_DIV4		0x00000080	/**< backplane/4 */
-#define	CF_CE			0x00000100	/**< clock enable */
-#define	CF_SB			0x00000200	/**< size/bytestrobe (synch only) */
-
-/* pcmcia_memwait */
-#define	PM_W0_MASK		0x0000003f	/**< waitcount0 */
-#define	PM_W1_MASK		0x00001f00	/**< waitcount1 */
-#define	PM_W1_SHIFT		8
-#define	PM_W2_MASK		0x001f0000	/**< waitcount2 */
-#define	PM_W2_SHIFT		16
-#define	PM_W3_MASK		0x1f000000	/**< waitcount3 */
-#define	PM_W3_SHIFT		24
-
-/* pcmcia_attrwait */
-#define	PA_W0_MASK		0x0000003f	/**< waitcount0 */
-#define	PA_W1_MASK		0x00001f00	/**< waitcount1 */
-#define	PA_W1_SHIFT		8
-#define	PA_W2_MASK		0x001f0000	/**< waitcount2 */
-#define	PA_W2_SHIFT		16
-#define	PA_W3_MASK		0x1f000000	/**< waitcount3 */
-#define	PA_W3_SHIFT		24
-
-/* pcmcia_iowait */
-#define	PI_W0_MASK		0x0000003f	/**< waitcount0 */
-#define	PI_W1_MASK		0x00001f00	/**< waitcount1 */
-#define	PI_W1_SHIFT		8
-#define	PI_W2_MASK		0x001f0000	/**< waitcount2 */
-#define	PI_W2_SHIFT		16
-#define	PI_W3_MASK		0x1f000000	/**< waitcount3 */
-#define	PI_W3_SHIFT		24
-
-/* prog_waitcount */
-#define	PW_W0_MASK		0x0000001f	/**< waitcount0 */
-#define	PW_W1_MASK		0x00001f00	/**< waitcount1 */
-#define	PW_W1_SHIFT		8
-#define	PW_W2_MASK		0x001f0000	/**< waitcount2 */
-#define	PW_W2_SHIFT		16
-#define	PW_W3_MASK		0x1f000000	/**< waitcount3 */
-#define	PW_W3_SHIFT		24
-
-#define PW_W0       		0x0000000c
-#define PW_W1       		0x00000a00
-#define PW_W2       		0x00020000
-#define PW_W3       		0x01000000
-
-/* flash_waitcount */
-#define	FW_W0_MASK		0x0000003f	/**< waitcount0 */
-#define	FW_W1_MASK		0x00001f00	/**< waitcount1 */
-#define	FW_W1_SHIFT		8
-#define	FW_W2_MASK		0x001f0000	/**< waitcount2 */
-#define	FW_W2_SHIFT		16
-#define	FW_W3_MASK		0x1f000000	/**< waitcount3 */
-#define	FW_W3_SHIFT		24
-
-/* When Srom support present, fields in sromcontrol */
-#define	SRC_START		0x80000000
-#define	SRC_BUSY		0x80000000
-#define	SRC_OPCODE		0x60000000
-#define	SRC_OP_READ		0x00000000
-#define	SRC_OP_WRITE		0x20000000
-#define	SRC_OP_WRDIS		0x40000000
-#define	SRC_OP_WREN		0x60000000
-#define	SRC_OTPSEL		0x00000010
-#define SRC_OTPPRESENT		0x00000020
-#define	SRC_LOCK		0x00000008
-#define	SRC_SIZE_MASK		0x00000006
-#define	SRC_SIZE_1K		0x00000000
-#define	SRC_SIZE_4K		0x00000002
-#define	SRC_SIZE_16K		0x00000004
-#define	SRC_SIZE_SHIFT		1
-#define	SRC_PRESENT		0x00000001
-
-/* Fields in pmucontrol */
-#define	PCTL_ILP_DIV_MASK	0xffff0000
-#define	PCTL_ILP_DIV_SHIFT	16
-#define PCTL_LQ_REQ_EN		0x00008000
-#define PCTL_PLL_PLLCTL_UPD	0x00000400	/**< rev 2 */
-#define PCTL_NOILP_ON_WAIT	0x00000200	/**< rev 1 */
-#define	PCTL_HT_REQ_EN		0x00000100
-#define	PCTL_ALP_REQ_EN		0x00000080
-#define	PCTL_XTALFREQ_MASK	0x0000007c
-#define	PCTL_XTALFREQ_SHIFT	2
-#define	PCTL_ILP_DIV_EN		0x00000002
-#define	PCTL_LPO_SEL		0x00000001
-
-/*  Retention Control */
-#define PMU_RCTL_CLK_DIV_SHIFT		0
-#define PMU_RCTL_CHAIN_LEN_SHIFT	12
-#define PMU_RCTL_MACPHY_DISABLE_SHIFT	26
-#define PMU_RCTL_MACPHY_DISABLE_MASK	(1 << 26)
-#define PMU_RCTL_LOGIC_DISABLE_SHIFT	27
-#define PMU_RCTL_LOGIC_DISABLE_MASK	(1 << 27)
-#define PMU_RCTL_MEMSLP_LOG_SHIFT	28
-#define PMU_RCTL_MEMSLP_LOG_MASK	(1 << 28)
-#define PMU_RCTL_MEMRETSLP_LOG_SHIFT	29
-#define PMU_RCTL_MEMRETSLP_LOG_MASK	(1 << 29)
-
-/*  Retention Group Control */
-#define PMU_RCTLGRP_CHAIN_LEN_SHIFT	0
-#define PMU_RCTLGRP_RMODE_ENABLE_SHIFT	14
-#define PMU_RCTLGRP_RMODE_ENABLE_MASK	(1 << 14)
-#define PMU_RCTLGRP_DFT_ENABLE_SHIFT	15
-#define PMU_RCTLGRP_DFT_ENABLE_MASK	(1 << 15)
-#define PMU_RCTLGRP_NSRST_DISABLE_SHIFT	16
-#define PMU_RCTLGRP_NSRST_DISABLE_MASK	(1 << 16)
-/*  Retention Group Control special for 4334 */
-#define PMU4334_RCTLGRP_CHAIN_LEN_GRP0	338
-#define PMU4334_RCTLGRP_CHAIN_LEN_GRP1	315
-/*  Retention Group Control special for 43341 */
-#define PMU43341_RCTLGRP_CHAIN_LEN_GRP0	366
-#define PMU43341_RCTLGRP_CHAIN_LEN_GRP1	330
-
-/* Fields in clkstretch */
-#define CSTRETCH_HT		0xffff0000
-#define CSTRETCH_ALP		0x0000ffff
-
-/* gpiotimerval */
-#define GPIO_ONTIME_SHIFT	16
-
-/* clockcontrol_n */
-#define	CN_N1_MASK		0x3f		/**< n1 control */
-#define	CN_N2_MASK		0x3f00		/**< n2 control */
-#define	CN_N2_SHIFT		8
-#define	CN_PLLC_MASK		0xf0000		/**< pll control */
-#define	CN_PLLC_SHIFT		16
-
-/* clockcontrol_sb/pci/uart */
-#define	CC_M1_MASK		0x3f		/**< m1 control */
-#define	CC_M2_MASK		0x3f00		/**< m2 control */
-#define	CC_M2_SHIFT		8
-#define	CC_M3_MASK		0x3f0000	/**< m3 control */
-#define	CC_M3_SHIFT		16
-#define	CC_MC_MASK		0x1f000000	/**< mux control */
-#define	CC_MC_SHIFT		24
-
-/* N3M Clock control magic field values */
-#define	CC_F6_2			0x02		/**< A factor of 2 in */
-#define	CC_F6_3			0x03		/**< 6-bit fields like */
-#define	CC_F6_4			0x05		/**< N1, M1 or M3 */
-#define	CC_F6_5			0x09
-#define	CC_F6_6			0x11
-#define	CC_F6_7			0x21
-
-#define	CC_F5_BIAS		5		/**< 5-bit fields get this added */
-
-#define	CC_MC_BYPASS		0x08
-#define	CC_MC_M1		0x04
-#define	CC_MC_M1M2		0x02
-#define	CC_MC_M1M2M3		0x01
-#define	CC_MC_M1M3		0x11
-
-/* Type 2 Clock control magic field values */
-#define	CC_T2_BIAS		2		/**< n1, n2, m1 & m3 bias */
-#define	CC_T2M2_BIAS		3		/**< m2 bias */
-
-#define	CC_T2MC_M1BYP		1
-#define	CC_T2MC_M2BYP		2
-#define	CC_T2MC_M3BYP		4
-
-/* Type 6 Clock control magic field values */
-#define	CC_T6_MMASK		1		/**< bits of interest in m */
-#define	CC_T6_M0		120000000	/**< sb clock for m = 0 */
-#define	CC_T6_M1		100000000	/**< sb clock for m = 1 */
-#define	SB2MIPS_T6(sb)		(2 * (sb))
-
-/* Common clock base */
-#define	CC_CLOCK_BASE1		24000000	/**< Half the clock freq */
-#define CC_CLOCK_BASE2		12500000	/**< Alternate crystal on some PLLs */
-
-/* Clock control values for 200MHz in 5350 */
-#define	CLKC_5350_N		0x0311
-#define	CLKC_5350_M		0x04020009
-
-/* Flash types in the chipcommon capabilities register */
-#define FLASH_NONE		0x000		/**< No flash */
-#define SFLASH_ST		0x100		/**< ST serial flash */
-#define SFLASH_AT		0x200		/**< Atmel serial flash */
-#define NFLASH			0x300
-#define	PFLASH			0x700		/**< Parallel flash */
-#define QSPIFLASH_ST		0x800
-#define QSPIFLASH_AT		0x900
-
-/* Bits in the ExtBus config registers */
-#define	CC_CFG_EN		0x0001		/**< Enable */
-#define	CC_CFG_EM_MASK		0x000e		/**< Extif Mode */
-#define	CC_CFG_EM_ASYNC		0x0000		/**<   Async/Parallel flash */
-#define	CC_CFG_EM_SYNC		0x0002		/**<   Synchronous */
-#define	CC_CFG_EM_PCMCIA	0x0004		/**<   PCMCIA */
-#define	CC_CFG_EM_IDE		0x0006		/**<   IDE */
-#define	CC_CFG_DS		0x0010		/**< Data size, 0=8bit, 1=16bit */
-#define	CC_CFG_CD_MASK		0x00e0		/**< Sync: Clock divisor, rev >= 20 */
-#define	CC_CFG_CE		0x0100		/**< Sync: Clock enable, rev >= 20 */
-#define	CC_CFG_SB		0x0200		/**< Sync: Size/Bytestrobe, rev >= 20 */
-#define	CC_CFG_IS		0x0400		/**< Extif Sync Clk Select, rev >= 20 */
-
-/* ExtBus address space */
-#define	CC_EB_BASE		0x1a000000	/**< Chipc ExtBus base address */
-#define	CC_EB_PCMCIA_MEM	0x1a000000	/**< PCMCIA 0 memory base address */
-#define	CC_EB_PCMCIA_IO		0x1a200000	/**< PCMCIA 0 I/O base address */
-#define	CC_EB_PCMCIA_CFG	0x1a400000	/**< PCMCIA 0 config base address */
-#define	CC_EB_IDE		0x1a800000	/**< IDE memory base */
-#define	CC_EB_PCMCIA1_MEM	0x1a800000	/**< PCMCIA 1 memory base address */
-#define	CC_EB_PCMCIA1_IO	0x1aa00000	/**< PCMCIA 1 I/O base address */
-#define	CC_EB_PCMCIA1_CFG	0x1ac00000	/**< PCMCIA 1 config base address */
-#define	CC_EB_PROGIF		0x1b000000	/**< ProgIF Async/Sync base address */
-
-
-/* Start/busy bit in flashcontrol */
-#define SFLASH_OPCODE		0x000000ff
-#define SFLASH_ACTION		0x00000700
-#define	SFLASH_CS_ACTIVE	0x00001000	/**< Chip Select Active, rev >= 20 */
-#define SFLASH_START		0x80000000
-#define SFLASH_BUSY		SFLASH_START
-
-/* flashcontrol action codes */
-#define	SFLASH_ACT_OPONLY	0x0000		/**< Issue opcode only */
-#define	SFLASH_ACT_OP1D		0x0100		/**< opcode + 1 data byte */
-#define	SFLASH_ACT_OP3A		0x0200		/**< opcode + 3 addr bytes */
-#define	SFLASH_ACT_OP3A1D	0x0300		/**< opcode + 3 addr & 1 data bytes */
-#define	SFLASH_ACT_OP3A4D	0x0400		/**< opcode + 3 addr & 4 data bytes */
-#define	SFLASH_ACT_OP3A4X4D	0x0500		/**< opcode + 3 addr, 4 don't care & 4 data bytes */
-#define	SFLASH_ACT_OP3A1X4D	0x0700		/**< opcode + 3 addr, 1 don't care & 4 data bytes */
-
-/* flashcontrol action+opcodes for ST flashes */
-#define SFLASH_ST_WREN		0x0006		/**< Write Enable */
-#define SFLASH_ST_WRDIS		0x0004		/**< Write Disable */
-#define SFLASH_ST_RDSR		0x0105		/**< Read Status Register */
-#define SFLASH_ST_WRSR		0x0101		/**< Write Status Register */
-#define SFLASH_ST_READ		0x0303		/**< Read Data Bytes */
-#define SFLASH_ST_PP		0x0302		/**< Page Program */
-#define SFLASH_ST_SE		0x02d8		/**< Sector Erase */
-#define SFLASH_ST_BE		0x00c7		/**< Bulk Erase */
-#define SFLASH_ST_DP		0x00b9		/**< Deep Power-down */
-#define SFLASH_ST_RES		0x03ab		/**< Read Electronic Signature */
-#define SFLASH_ST_CSA		0x1000		/**< Keep chip select asserted */
-#define SFLASH_ST_SSE		0x0220		/**< Sub-sector Erase */
-
-#define SFLASH_MXIC_RDID	0x0390		/**< Read Manufacture ID */
-#define SFLASH_MXIC_MFID	0xc2		/**< MXIC Manufacture ID */
-
-/* Status register bits for ST flashes */
-#define SFLASH_ST_WIP		0x01		/**< Write In Progress */
-#define SFLASH_ST_WEL		0x02		/**< Write Enable Latch */
-#define SFLASH_ST_BP_MASK	0x1c		/**< Block Protect */
-#define SFLASH_ST_BP_SHIFT	2
-#define SFLASH_ST_SRWD		0x80		/**< Status Register Write Disable */
-
-/* flashcontrol action+opcodes for Atmel flashes */
-#define SFLASH_AT_READ				0x07e8
-#define SFLASH_AT_PAGE_READ			0x07d2
-#define SFLASH_AT_BUF1_READ
-#define SFLASH_AT_BUF2_READ
-#define SFLASH_AT_STATUS			0x01d7
-#define SFLASH_AT_BUF1_WRITE			0x0384
-#define SFLASH_AT_BUF2_WRITE			0x0387
-#define SFLASH_AT_BUF1_ERASE_PROGRAM		0x0283
-#define SFLASH_AT_BUF2_ERASE_PROGRAM		0x0286
-#define SFLASH_AT_BUF1_PROGRAM			0x0288
-#define SFLASH_AT_BUF2_PROGRAM			0x0289
-#define SFLASH_AT_PAGE_ERASE			0x0281
-#define SFLASH_AT_BLOCK_ERASE			0x0250
-#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM	0x0382
-#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM	0x0385
-#define SFLASH_AT_BUF1_LOAD			0x0253
-#define SFLASH_AT_BUF2_LOAD			0x0255
-#define SFLASH_AT_BUF1_COMPARE			0x0260
-#define SFLASH_AT_BUF2_COMPARE			0x0261
-#define SFLASH_AT_BUF1_REPROGRAM		0x0258
-#define SFLASH_AT_BUF2_REPROGRAM		0x0259
-
-/* Status register bits for Atmel flashes */
-#define SFLASH_AT_READY				0x80
-#define SFLASH_AT_MISMATCH			0x40
-#define SFLASH_AT_ID_MASK			0x38
-#define SFLASH_AT_ID_SHIFT			3
-
-/* SPI register bits, corerev >= 37 */
-#define GSIO_START			0x80000000
-#define GSIO_BUSY			GSIO_START
-
-/*
- * These are the UART port assignments, expressed as offsets from the base
- * register.  These assignments should hold for any serial port based on
- * a 8250, 16450, or 16550(A).
- */
-
-#define UART_RX		0	/**< In:  Receive buffer (DLAB=0) */
-#define UART_TX		0	/**< Out: Transmit buffer (DLAB=0) */
-#define UART_DLL	0	/**< Out: Divisor Latch Low (DLAB=1) */
-#define UART_IER	1	/**< In/Out: Interrupt Enable Register (DLAB=0) */
-#define UART_DLM	1	/**< Out: Divisor Latch High (DLAB=1) */
-#define UART_IIR	2	/**< In: Interrupt Identity Register  */
-#define UART_FCR	2	/**< Out: FIFO Control Register */
-#define UART_LCR	3	/**< Out: Line Control Register */
-#define UART_MCR	4	/**< Out: Modem Control Register */
-#define UART_LSR	5	/**< In:  Line Status Register */
-#define UART_MSR	6	/**< In:  Modem Status Register */
-#define UART_SCR	7	/**< I/O: Scratch Register */
-#define UART_LCR_DLAB	0x80	/**< Divisor latch access bit */
-#define UART_LCR_WLEN8	0x03	/**< Word length: 8 bits */
-#define UART_MCR_OUT2	0x08	/**< MCR GPIO out 2 */
-#define UART_MCR_LOOP	0x10	/**< Enable loopback test mode */
-#define UART_LSR_RX_FIFO 	0x80	/**< Receive FIFO error */
-#define UART_LSR_TDHR		0x40	/**< Data-hold-register empty */
-#define UART_LSR_THRE		0x20	/**< Transmit-hold-register empty */
-#define UART_LSR_BREAK		0x10	/**< Break interrupt */
-#define UART_LSR_FRAMING	0x08	/**< Framing error */
-#define UART_LSR_PARITY		0x04	/**< Parity error */
-#define UART_LSR_OVERRUN	0x02	/**< Overrun error */
-#define UART_LSR_RXRDY		0x01	/**< Receiver ready */
-#define UART_FCR_FIFO_ENABLE 1	/**< FIFO control register bit controlling FIFO enable/disable */
-
-/* Interrupt Identity Register (IIR) bits */
-#define UART_IIR_FIFO_MASK	0xc0	/**< IIR FIFO disable/enabled mask */
-#define UART_IIR_INT_MASK	0xf	/**< IIR interrupt ID source */
-#define UART_IIR_MDM_CHG	0x0	/**< Modem status changed */
-#define UART_IIR_NOINT		0x1	/**< No interrupt pending */
-#define UART_IIR_THRE		0x2	/**< THR empty */
-#define UART_IIR_RCVD_DATA	0x4	/**< Received data available */
-#define UART_IIR_RCVR_STATUS 	0x6	/**< Receiver status */
-#define UART_IIR_CHAR_TIME 	0xc	/**< Character time */
-
-/* Interrupt Enable Register (IER) bits */
-#define UART_IER_PTIME	128	/**< Programmable THRE Interrupt Mode Enable */
-#define UART_IER_EDSSI	8	/**< enable modem status interrupt */
-#define UART_IER_ELSI	4	/**< enable receiver line status interrupt */
-#define UART_IER_ETBEI  2	/**< enable transmitter holding register empty interrupt */
-#define UART_IER_ERBFI	1	/**< enable data available interrupt */
-
-/* pmustatus */
-#define PST_SLOW_WR_PENDING 0x0400
-#define PST_EXTLPOAVAIL	0x0100
-#define PST_WDRESET	0x0080
-#define	PST_INTPEND	0x0040
-#define	PST_SBCLKST	0x0030
-#define	PST_SBCLKST_ILP	0x0010
-#define	PST_SBCLKST_ALP	0x0020
-#define	PST_SBCLKST_HT	0x0030
-#define	PST_ALPAVAIL	0x0008
-#define	PST_HTAVAIL	0x0004
-#define	PST_RESINIT	0x0003
-
-/* pmucapabilities */
-#define PCAP_REV_MASK	0x000000ff
-#define PCAP_RC_MASK	0x00001f00
-#define PCAP_RC_SHIFT	8
-#define PCAP_TC_MASK	0x0001e000
-#define PCAP_TC_SHIFT	13
-#define PCAP_PC_MASK	0x001e0000
-#define PCAP_PC_SHIFT	17
-#define PCAP_VC_MASK	0x01e00000
-#define PCAP_VC_SHIFT	21
-#define PCAP_CC_MASK	0x1e000000
-#define PCAP_CC_SHIFT	25
-#define PCAP5_PC_MASK	0x003e0000	/**< PMU corerev >= 5 */
-#define PCAP5_PC_SHIFT	17
-#define PCAP5_VC_MASK	0x07c00000
-#define PCAP5_VC_SHIFT	22
-#define PCAP5_CC_MASK	0xf8000000
-#define PCAP5_CC_SHIFT	27
-
-/* PMU Resource Request Timer registers */
-/* This is based on PmuRev0 */
-#define	PRRT_TIME_MASK	0x03ff
-#define	PRRT_INTEN	0x0400
-#define	PRRT_REQ_ACTIVE	0x0800
-#define	PRRT_ALP_REQ	0x1000
-#define	PRRT_HT_REQ	0x2000
-#define PRRT_HQ_REQ 0x4000
-
-/* PMU Int Control register bits */
-#define PMU_INTC_ALP_REQ	0x1
-#define PMU_INTC_HT_REQ		0x2
-#define PMU_INTC_HQ_REQ		0x4
-
-/* bit 0 of the PMU interrupt vector is asserted if this mask is enabled */
-#define RSRC_INTR_MASK_TIMER_INT_0 1
-
-/* PMU resource bit position */
-#define PMURES_BIT(bit)	(1 << (bit))
-
-/* PMU resource number limit */
-#define PMURES_MAX_RESNUM	30
-
-/* PMU chip control0 register */
-#define	PMU_CHIPCTL0		0
-#define PMU43143_CC0_SDIO_DRSTR_OVR	(1 << 31) /* sdio drive strength override enable */
-
-/* clock req types */
-#define PMU_CC1_CLKREQ_TYPE_SHIFT	19
-#define PMU_CC1_CLKREQ_TYPE_MASK	(1 << PMU_CC1_CLKREQ_TYPE_SHIFT)
-
-#define CLKREQ_TYPE_CONFIG_OPENDRAIN		0
-#define CLKREQ_TYPE_CONFIG_PUSHPULL		1
-
-/* PMU chip control1 register */
-#define	PMU_CHIPCTL1			1
-#define	PMU_CC1_RXC_DLL_BYPASS		0x00010000
-#define PMU_CC1_ENABLE_BBPLL_PWR_DOWN	0x00000010
-
-#define PMU_CC1_IF_TYPE_MASK   		0x00000030
-#define PMU_CC1_IF_TYPE_RMII    	0x00000000
-#define PMU_CC1_IF_TYPE_MII     	0x00000010
-#define PMU_CC1_IF_TYPE_RGMII   	0x00000020
-
-#define PMU_CC1_SW_TYPE_MASK    	0x000000c0
-#define PMU_CC1_SW_TYPE_EPHY    	0x00000000
-#define PMU_CC1_SW_TYPE_EPHYMII 	0x00000040
-#define PMU_CC1_SW_TYPE_EPHYRMII	0x00000080
-#define PMU_CC1_SW_TYPE_RGMII   	0x000000c0
-
-#define PMU_CC1_ENABLE_CLOSED_LOOP_MASK 0x00000080
-#define PMU_CC1_ENABLE_CLOSED_LOOP      0x00000000
-
-/* PMU chip control2 register */
-#define	PMU_CHIPCTL2		2
-#define PMU_CC2_FORCE_SUBCORE_PWR_SWITCH_ON   	(1 << 18)
-#define PMU_CC2_FORCE_PHY_PWR_SWITCH_ON   	(1 << 19)
-#define PMU_CC2_FORCE_VDDM_PWR_SWITCH_ON   	(1 << 20)
-#define PMU_CC2_FORCE_MEMLPLDO_PWR_SWITCH_ON   	(1 << 21)
-#define PMU_CC2_MASK_WL_DEV_WAKE             (1 << 22)
-#define PMU_CC2_INV_GPIO_POLARITY_PMU_WAKE   (1 << 25)
-
-
-/* PMU chip control3 register */
-#define	PMU_CHIPCTL3		3
-#define PMU_CC3_ENABLE_SDIO_WAKEUP_SHIFT  19
-#define PMU_CC3_ENABLE_RF_SHIFT           22
-#define PMU_CC3_RF_DISABLE_IVALUE_SHIFT   23
-
-/* PMU chip control4 register */
-#define PMU_CHIPCTL4                    4
-
-/* 53537 series moved switch_type and gmac_if_type to CC4 [15:14] and [13:12] */
-#define PMU_CC4_IF_TYPE_MASK		0x00003000
-#define PMU_CC4_IF_TYPE_RMII		0x00000000
-#define PMU_CC4_IF_TYPE_MII		0x00001000
-#define PMU_CC4_IF_TYPE_RGMII		0x00002000
-
-#define PMU_CC4_SW_TYPE_MASK		0x0000c000
-#define PMU_CC4_SW_TYPE_EPHY		0x00000000
-#define PMU_CC4_SW_TYPE_EPHYMII		0x00004000
-#define PMU_CC4_SW_TYPE_EPHYRMII	0x00008000
-#define PMU_CC4_SW_TYPE_RGMII		0x0000c000
-
-/* PMU chip control5 register */
-#define PMU_CHIPCTL5                    5
-
-/* PMU chip control6 register */
-#define PMU_CHIPCTL6                    6
-#define PMU_CC6_ENABLE_CLKREQ_WAKEUP    (1 << 4)
-#define PMU_CC6_ENABLE_PMU_WAKEUP_ALP   (1 << 6)
-
-/* PMU chip control7 register */
-#define PMU_CHIPCTL7				7
-#define PMU_CC7_ENABLE_L2REFCLKPAD_PWRDWN	(1 << 25)
-#define PMU_CC7_ENABLE_MDIO_RESET_WAR		(1 << 27)
-/* 53537 series have gmca1 gmac_if_type in cc7 [7:6](defalut 0b01) */
-#define PMU_CC7_IF_TYPE_MASK		0x000000c0
-#define PMU_CC7_IF_TYPE_RMII		0x00000000
-#define PMU_CC7_IF_TYPE_MII		0x00000040
-#define PMU_CC7_IF_TYPE_RGMII		0x00000080
-
-
-/* PMU corerev and chip specific PLL controls.
- * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
- * to differentiate different PLLs controlled by the same PMU rev.
- */
-/* pllcontrol registers */
-/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */
-#define	PMU0_PLL0_PLLCTL0		0
-#define	PMU0_PLL0_PC0_PDIV_MASK		1
-#define	PMU0_PLL0_PC0_PDIV_FREQ		25000
-#define PMU0_PLL0_PC0_DIV_ARM_MASK	0x00000038
-#define PMU0_PLL0_PC0_DIV_ARM_SHIFT	3
-#define PMU0_PLL0_PC0_DIV_ARM_BASE	8
-
-/* PC0_DIV_ARM for PLLOUT_ARM */
-#define PMU0_PLL0_PC0_DIV_ARM_110MHZ	0
-#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ	1
-#define PMU0_PLL0_PC0_DIV_ARM_88MHZ	2
-#define PMU0_PLL0_PC0_DIV_ARM_80MHZ	3 /* Default */
-#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ	4
-#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ	5
-#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ	6
-#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ	7
-
-/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */
-#define	PMU0_PLL0_PLLCTL1		1
-#define	PMU0_PLL0_PC1_WILD_INT_MASK	0xf0000000
-#define	PMU0_PLL0_PC1_WILD_INT_SHIFT	28
-#define	PMU0_PLL0_PC1_WILD_FRAC_MASK	0x0fffff00
-#define	PMU0_PLL0_PC1_WILD_FRAC_SHIFT	8
-#define	PMU0_PLL0_PC1_STOP_MOD		0x00000040
-
-/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */
-#define	PMU0_PLL0_PLLCTL2		2
-#define	PMU0_PLL0_PC2_WILD_INT_MASK	0xf
-#define	PMU0_PLL0_PC2_WILD_INT_SHIFT	4
-
-/* pllcontrol registers */
-/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
-#define PMU1_PLL0_PLLCTL0		0
-#define PMU1_PLL0_PC0_P1DIV_MASK	0x00f00000
-#define PMU1_PLL0_PC0_P1DIV_SHIFT	20
-#define PMU1_PLL0_PC0_P2DIV_MASK	0x0f000000
-#define PMU1_PLL0_PC0_P2DIV_SHIFT	24
-
-/* m<x>div */
-#define PMU1_PLL0_PLLCTL1		1
-#define PMU1_PLL0_PC1_M1DIV_MASK	0x000000ff
-#define PMU1_PLL0_PC1_M1DIV_SHIFT	0
-#define PMU1_PLL0_PC1_M2DIV_MASK	0x0000ff00
-#define PMU1_PLL0_PC1_M2DIV_SHIFT	8
-#define PMU1_PLL0_PC1_M3DIV_MASK	0x00ff0000
-#define PMU1_PLL0_PC1_M3DIV_SHIFT	16
-#define PMU1_PLL0_PC1_M4DIV_MASK	0xff000000
-#define PMU1_PLL0_PC1_M4DIV_SHIFT	24
-#define PMU1_PLL0_PC1_M4DIV_BY_9	9
-#define PMU1_PLL0_PC1_M4DIV_BY_18	0x12
-#define PMU1_PLL0_PC1_M4DIV_BY_36	0x24
-#define PMU1_PLL0_PC1_M4DIV_BY_60	0x3C
-
-#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8
-#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
-#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL  (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
-
-/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
-#define PMU1_PLL0_PLLCTL2		2
-#define PMU1_PLL0_PC2_M5DIV_MASK	0x000000ff
-#define PMU1_PLL0_PC2_M5DIV_SHIFT	0
-#define PMU1_PLL0_PC2_M5DIV_BY_12	0xc
-#define PMU1_PLL0_PC2_M5DIV_BY_18	0x12
-#define PMU1_PLL0_PC2_M5DIV_BY_36	0x24
-#define PMU1_PLL0_PC2_M6DIV_MASK	0x0000ff00
-#define PMU1_PLL0_PC2_M6DIV_SHIFT	8
-#define PMU1_PLL0_PC2_M6DIV_BY_18	0x12
-#define PMU1_PLL0_PC2_M6DIV_BY_36	0x24
-#define PMU1_PLL0_PC2_NDIV_MODE_MASK	0x000e0000
-#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT	17
-#define PMU1_PLL0_PC2_NDIV_MODE_MASH	1
-#define PMU1_PLL0_PC2_NDIV_MODE_MFB	2	/**< recommended for 4319 */
-#define PMU1_PLL0_PC2_NDIV_INT_MASK	0x1ff00000
-#define PMU1_PLL0_PC2_NDIV_INT_SHIFT	20
-
-/* ndiv_frac */
-#define PMU1_PLL0_PLLCTL3		3
-#define PMU1_PLL0_PC3_NDIV_FRAC_MASK	0x00ffffff
-#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT	0
-
-/* pll_ctrl */
-#define PMU1_PLL0_PLLCTL4		4
-
-/* pll_ctrl, vco_rng, clkdrive_ch<x> */
-#define PMU1_PLL0_PLLCTL5		5
-#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00
-#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8
-
-#define PMU1_PLL0_PLLCTL6		6
-#define PMU1_PLL0_PLLCTL7		7
-#define PMU1_PLL0_PLLCTL8		8
-
-#define PMU1_PLLCTL8_OPENLOOP_MASK	(1 << 1)
-#define PMU_PLL4350_OPENLOOP_MASK	(1 << 7)
-
-/* PMU rev 2 control words */
-#define PMU2_PHY_PLL_PLLCTL		4
-#define PMU2_SI_PLL_PLLCTL		10
-
-/* PMU rev 2 */
-/* pllcontrol registers */
-/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
-#define PMU2_PLL_PLLCTL0		0
-#define PMU2_PLL_PC0_P1DIV_MASK 	0x00f00000
-#define PMU2_PLL_PC0_P1DIV_SHIFT	20
-#define PMU2_PLL_PC0_P2DIV_MASK 	0x0f000000
-#define PMU2_PLL_PC0_P2DIV_SHIFT	24
-
-/* m<x>div */
-#define PMU2_PLL_PLLCTL1		1
-#define PMU2_PLL_PC1_M1DIV_MASK 	0x000000ff
-#define PMU2_PLL_PC1_M1DIV_SHIFT	0
-#define PMU2_PLL_PC1_M2DIV_MASK 	0x0000ff00
-#define PMU2_PLL_PC1_M2DIV_SHIFT	8
-#define PMU2_PLL_PC1_M3DIV_MASK 	0x00ff0000
-#define PMU2_PLL_PC1_M3DIV_SHIFT	16
-#define PMU2_PLL_PC1_M4DIV_MASK 	0xff000000
-#define PMU2_PLL_PC1_M4DIV_SHIFT	24
-
-/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
-#define PMU2_PLL_PLLCTL2		2
-#define PMU2_PLL_PC2_M5DIV_MASK 	0x000000ff
-#define PMU2_PLL_PC2_M5DIV_SHIFT	0
-#define PMU2_PLL_PC2_M6DIV_MASK 	0x0000ff00
-#define PMU2_PLL_PC2_M6DIV_SHIFT	8
-#define PMU2_PLL_PC2_NDIV_MODE_MASK	0x000e0000
-#define PMU2_PLL_PC2_NDIV_MODE_SHIFT	17
-#define PMU2_PLL_PC2_NDIV_INT_MASK	0x1ff00000
-#define PMU2_PLL_PC2_NDIV_INT_SHIFT	20
-
-/* ndiv_frac */
-#define PMU2_PLL_PLLCTL3		3
-#define PMU2_PLL_PC3_NDIV_FRAC_MASK	0x00ffffff
-#define PMU2_PLL_PC3_NDIV_FRAC_SHIFT	0
-
-/* pll_ctrl */
-#define PMU2_PLL_PLLCTL4		4
-
-/* pll_ctrl, vco_rng, clkdrive_ch<x> */
-#define PMU2_PLL_PLLCTL5		5
-#define PMU2_PLL_PC5_CLKDRIVE_CH1_MASK	0x00000f00
-#define PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT	8
-#define PMU2_PLL_PC5_CLKDRIVE_CH2_MASK	0x0000f000
-#define PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT	12
-#define PMU2_PLL_PC5_CLKDRIVE_CH3_MASK	0x000f0000
-#define PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT	16
-#define PMU2_PLL_PC5_CLKDRIVE_CH4_MASK	0x00f00000
-#define PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT	20
-#define PMU2_PLL_PC5_CLKDRIVE_CH5_MASK	0x0f000000
-#define PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT	24
-#define PMU2_PLL_PC5_CLKDRIVE_CH6_MASK	0xf0000000
-#define PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT	28
-
-/* PMU rev 5 (& 6) */
-#define	PMU5_PLL_P1P2_OFF		0
-#define	PMU5_PLL_P1_MASK		0x0f000000
-#define	PMU5_PLL_P1_SHIFT		24
-#define	PMU5_PLL_P2_MASK		0x00f00000
-#define	PMU5_PLL_P2_SHIFT		20
-#define	PMU5_PLL_M14_OFF		1
-#define	PMU5_PLL_MDIV_MASK		0x000000ff
-#define	PMU5_PLL_MDIV_WIDTH		8
-#define	PMU5_PLL_NM5_OFF		2
-#define	PMU5_PLL_NDIV_MASK		0xfff00000
-#define	PMU5_PLL_NDIV_SHIFT		20
-#define	PMU5_PLL_NDIV_MODE_MASK		0x000e0000
-#define	PMU5_PLL_NDIV_MODE_SHIFT	17
-#define	PMU5_PLL_FMAB_OFF		3
-#define	PMU5_PLL_MRAT_MASK		0xf0000000
-#define	PMU5_PLL_MRAT_SHIFT		28
-#define	PMU5_PLL_ABRAT_MASK		0x08000000
-#define	PMU5_PLL_ABRAT_SHIFT		27
-#define	PMU5_PLL_FDIV_MASK		0x07ffffff
-#define	PMU5_PLL_PLLCTL_OFF		4
-#define	PMU5_PLL_PCHI_OFF		5
-#define	PMU5_PLL_PCHI_MASK		0x0000003f
-
-/* pmu XtalFreqRatio */
-#define	PMU_XTALFREQ_REG_ILPCTR_MASK	0x00001FFF
-#define	PMU_XTALFREQ_REG_MEASURE_MASK	0x80000000
-#define	PMU_XTALFREQ_REG_MEASURE_SHIFT	31
-
-/* Divider allocation in 4716/47162/5356/5357 */
-#define	PMU5_MAINPLL_CPU		1
-#define	PMU5_MAINPLL_MEM		2
-#define	PMU5_MAINPLL_SI			3
-
-/* 4706 PMU */
-#define PMU4706_MAINPLL_PLL0	0
-#define PMU6_4706_PROCPLL_OFF	4	/**< The CPU PLL */
-#define PMU6_4706_PROC_P2DIV_MASK		0x000f0000
-#define PMU6_4706_PROC_P2DIV_SHIFT	16
-#define PMU6_4706_PROC_P1DIV_MASK		0x0000f000
-#define PMU6_4706_PROC_P1DIV_SHIFT	12
-#define PMU6_4706_PROC_NDIV_INT_MASK	0x00000ff8
-#define PMU6_4706_PROC_NDIV_INT_SHIFT	3
-#define PMU6_4706_PROC_NDIV_MODE_MASK		0x00000007
-#define PMU6_4706_PROC_NDIV_MODE_SHIFT	0
-
-#define PMU7_PLL_PLLCTL7                7
-#define PMU7_PLL_CTL7_M4DIV_MASK	0xff000000
-#define PMU7_PLL_CTL7_M4DIV_SHIFT 	24
-#define PMU7_PLL_CTL7_M4DIV_BY_6	6
-#define PMU7_PLL_CTL7_M4DIV_BY_12	0xc
-#define PMU7_PLL_CTL7_M4DIV_BY_24	0x18
-#define PMU7_PLL_PLLCTL8                8
-#define PMU7_PLL_CTL8_M5DIV_MASK	0x000000ff
-#define PMU7_PLL_CTL8_M5DIV_SHIFT	0
-#define PMU7_PLL_CTL8_M5DIV_BY_8	8
-#define PMU7_PLL_CTL8_M5DIV_BY_12	0xc
-#define PMU7_PLL_CTL8_M5DIV_BY_24	0x18
-#define PMU7_PLL_CTL8_M6DIV_MASK	0x0000ff00
-#define PMU7_PLL_CTL8_M6DIV_SHIFT	8
-#define PMU7_PLL_CTL8_M6DIV_BY_12	0xc
-#define PMU7_PLL_CTL8_M6DIV_BY_24	0x18
-#define PMU7_PLL_PLLCTL11		11
-#define PMU7_PLL_PLLCTL11_MASK		0xffffff00
-#define PMU7_PLL_PLLCTL11_VAL		0x22222200
-
-/* PMU rev 15 */
-#define PMU15_PLL_PLLCTL0		0
-#define PMU15_PLL_PC0_CLKSEL_MASK	0x00000003
-#define PMU15_PLL_PC0_CLKSEL_SHIFT	0
-#define PMU15_PLL_PC0_FREQTGT_MASK	0x003FFFFC
-#define PMU15_PLL_PC0_FREQTGT_SHIFT	2
-#define PMU15_PLL_PC0_PRESCALE_MASK	0x00C00000
-#define PMU15_PLL_PC0_PRESCALE_SHIFT	22
-#define PMU15_PLL_PC0_KPCTRL_MASK	0x07000000
-#define PMU15_PLL_PC0_KPCTRL_SHIFT	24
-#define PMU15_PLL_PC0_FCNTCTRL_MASK	0x38000000
-#define PMU15_PLL_PC0_FCNTCTRL_SHIFT	27
-#define PMU15_PLL_PC0_FDCMODE_MASK	0x40000000
-#define PMU15_PLL_PC0_FDCMODE_SHIFT	30
-#define PMU15_PLL_PC0_CTRLBIAS_MASK	0x80000000
-#define PMU15_PLL_PC0_CTRLBIAS_SHIFT	31
-
-#define PMU15_PLL_PLLCTL1			1
-#define PMU15_PLL_PC1_BIAS_CTLM_MASK		0x00000060
-#define PMU15_PLL_PC1_BIAS_CTLM_SHIFT		5
-#define PMU15_PLL_PC1_BIAS_CTLM_RST_MASK	0x00000040
-#define PMU15_PLL_PC1_BIAS_CTLM_RST_SHIFT	6
-#define PMU15_PLL_PC1_BIAS_SS_DIVR_MASK		0x0001FF80
-#define PMU15_PLL_PC1_BIAS_SS_DIVR_SHIFT	7
-#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_MASK	0x03FE0000
-#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_SHIFT	17
-#define PMU15_PLL_PC1_BIAS_INTG_BW_MASK		0x0C000000
-#define PMU15_PLL_PC1_BIAS_INTG_BW_SHIFT	26
-#define PMU15_PLL_PC1_BIAS_INTG_BYP_MASK	0x10000000
-#define PMU15_PLL_PC1_BIAS_INTG_BYP_SHIFT	28
-#define PMU15_PLL_PC1_OPENLP_EN_MASK		0x40000000
-#define PMU15_PLL_PC1_OPENLP_EN_SHIFT		30
-
-#define PMU15_PLL_PLLCTL2			2
-#define PMU15_PLL_PC2_CTEN_MASK			0x00000001
-#define PMU15_PLL_PC2_CTEN_SHIFT		0
-
-#define PMU15_PLL_PLLCTL3			3
-#define PMU15_PLL_PC3_DITHER_EN_MASK		0x00000001
-#define PMU15_PLL_PC3_DITHER_EN_SHIFT		0
-#define PMU15_PLL_PC3_DCOCTLSP_MASK		0xFE000000
-#define PMU15_PLL_PC3_DCOCTLSP_SHIFT		25
-#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_MASK	0x01
-#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_SHIFT	0
-#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_MASK	0x02
-#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_SHIFT	1
-#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_MASK	0x04
-#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_SHIFT	2
-#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_MASK	0x18
-#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_SHIFT	3
-#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_MASK	0x60
-#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_SHIFT	5
-#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV1	0
-#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV2	1
-#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV3	2
-#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV5	3
-
-#define PMU15_PLL_PLLCTL4			4
-#define PMU15_PLL_PC4_FLLCLK1_DIV_MASK		0x00000007
-#define PMU15_PLL_PC4_FLLCLK1_DIV_SHIFT		0
-#define PMU15_PLL_PC4_FLLCLK2_DIV_MASK		0x00000038
-#define PMU15_PLL_PC4_FLLCLK2_DIV_SHIFT		3
-#define PMU15_PLL_PC4_FLLCLK3_DIV_MASK		0x000001C0
-#define PMU15_PLL_PC4_FLLCLK3_DIV_SHIFT		6
-#define PMU15_PLL_PC4_DBGMODE_MASK		0x00000E00
-#define PMU15_PLL_PC4_DBGMODE_SHIFT		9
-#define PMU15_PLL_PC4_FLL480_CTLSP_LK_MASK	0x00001000
-#define PMU15_PLL_PC4_FLL480_CTLSP_LK_SHIFT	12
-#define PMU15_PLL_PC4_FLL480_CTLSP_MASK		0x000FE000
-#define PMU15_PLL_PC4_FLL480_CTLSP_SHIFT	13
-#define PMU15_PLL_PC4_DINPOL_MASK		0x00100000
-#define PMU15_PLL_PC4_DINPOL_SHIFT		20
-#define PMU15_PLL_PC4_CLKOUT_PD_MASK		0x00200000
-#define PMU15_PLL_PC4_CLKOUT_PD_SHIFT		21
-#define PMU15_PLL_PC4_CLKDIV2_PD_MASK		0x00400000
-#define PMU15_PLL_PC4_CLKDIV2_PD_SHIFT		22
-#define PMU15_PLL_PC4_CLKDIV4_PD_MASK		0x00800000
-#define PMU15_PLL_PC4_CLKDIV4_PD_SHIFT		23
-#define PMU15_PLL_PC4_CLKDIV8_PD_MASK		0x01000000
-#define PMU15_PLL_PC4_CLKDIV8_PD_SHIFT		24
-#define PMU15_PLL_PC4_CLKDIV16_PD_MASK		0x02000000
-#define PMU15_PLL_PC4_CLKDIV16_PD_SHIFT		25
-#define PMU15_PLL_PC4_TEST_EN_MASK		0x04000000
-#define PMU15_PLL_PC4_TEST_EN_SHIFT		26
-
-#define PMU15_PLL_PLLCTL5			5
-#define PMU15_PLL_PC5_FREQTGT_MASK		0x000FFFFF
-#define PMU15_PLL_PC5_FREQTGT_SHIFT		0
-#define PMU15_PLL_PC5_DCOCTLSP_MASK		0x07F00000
-#define PMU15_PLL_PC5_DCOCTLSP_SHIFT		20
-#define PMU15_PLL_PC5_PRESCALE_MASK		0x18000000
-#define PMU15_PLL_PC5_PRESCALE_SHIFT		27
-
-#define PMU15_PLL_PLLCTL6		6
-#define PMU15_PLL_PC6_FREQTGT_MASK	0x000FFFFF
-#define PMU15_PLL_PC6_FREQTGT_SHIFT	0
-#define PMU15_PLL_PC6_DCOCTLSP_MASK	0x07F00000
-#define PMU15_PLL_PC6_DCOCTLSP_SHIFT	20
-#define PMU15_PLL_PC6_PRESCALE_MASK	0x18000000
-#define PMU15_PLL_PC6_PRESCALE_SHIFT	27
-
-#define PMU15_FREQTGT_480_DEFAULT	0x19AB1
-#define PMU15_FREQTGT_492_DEFAULT	0x1A4F5
-#define PMU15_ARM_96MHZ			96000000	/**< 96 Mhz */
-#define PMU15_ARM_98MHZ			98400000	/**< 98.4 Mhz */
-#define PMU15_ARM_97MHZ			97000000	/**< 97 Mhz */
-
-
-#define PMU17_PLLCTL2_NDIVTYPE_MASK		0x00000070
-#define PMU17_PLLCTL2_NDIVTYPE_SHIFT		4
-
-#define PMU17_PLLCTL2_NDIV_MODE_INT		0
-#define PMU17_PLLCTL2_NDIV_MODE_INT1B8		1
-#define PMU17_PLLCTL2_NDIV_MODE_MASH111		2
-#define PMU17_PLLCTL2_NDIV_MODE_MASH111B8	3
-
-#define PMU17_PLLCTL0_BBPLL_PWRDWN		0
-#define PMU17_PLLCTL0_BBPLL_DRST		3
-#define PMU17_PLLCTL0_BBPLL_DISBL_CLK		8
-
-/* PLL usage in 4716/47162 */
-#define	PMU4716_MAINPLL_PLL0		12
-
-/* PLL usage in 4335 */
-#define PMU4335_PLL0_PC2_P1DIV_MASK			0x000f0000
-#define PMU4335_PLL0_PC2_P1DIV_SHIFT		16
-#define PMU4335_PLL0_PC2_NDIV_INT_MASK		0xff800000
-#define PMU4335_PLL0_PC2_NDIV_INT_SHIFT		23
-#define PMU4335_PLL0_PC1_MDIV2_MASK			0x0000ff00
-#define PMU4335_PLL0_PC1_MDIV2_SHIFT		8
-
-
-/* PLL usage in 5356/5357 */
-#define	PMU5356_MAINPLL_PLL0		0
-#define	PMU5357_MAINPLL_PLL0		0
-
-/* 4716/47162 resources */
-#define RES4716_PROC_PLL_ON		0x00000040
-#define RES4716_PROC_HT_AVAIL		0x00000080
-
-/* 4716/4717/4718 Chip specific ChipControl register bits */
-#define CCTRL_471X_I2S_PINS_ENABLE	0x0080 /* I2S pins off by default, shared w/ pflash */
-
-/* 5357 Chip specific ChipControl register bits */
-/* 2nd - 32-bit reg */
-#define CCTRL_5357_I2S_PINS_ENABLE	0x00040000 /* I2S pins enable */
-#define CCTRL_5357_I2CSPI_PINS_ENABLE	0x00080000 /* I2C/SPI pins enable */
-
-/* 5354 resources */
-#define RES5354_EXT_SWITCHER_PWM	0	/**< 0x00001 */
-#define RES5354_BB_SWITCHER_PWM		1	/**< 0x00002 */
-#define RES5354_BB_SWITCHER_BURST	2	/**< 0x00004 */
-#define RES5354_BB_EXT_SWITCHER_BURST	3	/**< 0x00008 */
-#define RES5354_ILP_REQUEST		4	/**< 0x00010 */
-#define RES5354_RADIO_SWITCHER_PWM	5	/**< 0x00020 */
-#define RES5354_RADIO_SWITCHER_BURST	6	/**< 0x00040 */
-#define RES5354_ROM_SWITCH		7	/**< 0x00080 */
-#define RES5354_PA_REF_LDO		8	/**< 0x00100 */
-#define RES5354_RADIO_LDO		9	/**< 0x00200 */
-#define RES5354_AFE_LDO			10	/**< 0x00400 */
-#define RES5354_PLL_LDO			11	/**< 0x00800 */
-#define RES5354_BG_FILTBYP		12	/**< 0x01000 */
-#define RES5354_TX_FILTBYP		13	/**< 0x02000 */
-#define RES5354_RX_FILTBYP		14	/**< 0x04000 */
-#define RES5354_XTAL_PU			15	/**< 0x08000 */
-#define RES5354_XTAL_EN			16	/**< 0x10000 */
-#define RES5354_BB_PLL_FILTBYP		17	/**< 0x20000 */
-#define RES5354_RF_PLL_FILTBYP		18	/**< 0x40000 */
-#define RES5354_BB_PLL_PU		19	/**< 0x80000 */
-
-/* 5357 Chip specific ChipControl register bits */
-#define CCTRL5357_EXTPA                 (1<<14) /* extPA in ChipControl 1, bit 14 */
-#define CCTRL5357_ANT_MUX_2o3		(1<<15) /* 2o3 in ChipControl 1, bit 15 */
-#define CCTRL5357_NFLASH		(1<<16) /* Nandflash in ChipControl 1, bit 16 */
-
-/* 43217 Chip specific ChipControl register bits */
-#define CCTRL43217_EXTPA_C0             (1<<13) /* core0 extPA in ChipControl 1, bit 13 */
-#define CCTRL43217_EXTPA_C1             (1<<8)  /* core1 extPA in ChipControl 1, bit 8 */
-
-/* 43228 Chip specific ChipControl register bits */
-#define CCTRL43228_EXTPA_C0             (1<<14) /* core1 extPA in ChipControl 1, bit 14 */
-#define CCTRL43228_EXTPA_C1             (1<<9)  /* core0 extPA in ChipControl 1, bit 1 */
-
-/* 4328 resources */
-#define RES4328_EXT_SWITCHER_PWM	0	/**< 0x00001 */
-#define RES4328_BB_SWITCHER_PWM		1	/**< 0x00002 */
-#define RES4328_BB_SWITCHER_BURST	2	/**< 0x00004 */
-#define RES4328_BB_EXT_SWITCHER_BURST	3	/**< 0x00008 */
-#define RES4328_ILP_REQUEST		4	/**< 0x00010 */
-#define RES4328_RADIO_SWITCHER_PWM	5	/**< 0x00020 */
-#define RES4328_RADIO_SWITCHER_BURST	6	/**< 0x00040 */
-#define RES4328_ROM_SWITCH		7	/**< 0x00080 */
-#define RES4328_PA_REF_LDO		8	/**< 0x00100 */
-#define RES4328_RADIO_LDO		9	/**< 0x00200 */
-#define RES4328_AFE_LDO			10	/**< 0x00400 */
-#define RES4328_PLL_LDO			11	/**< 0x00800 */
-#define RES4328_BG_FILTBYP		12	/**< 0x01000 */
-#define RES4328_TX_FILTBYP		13	/**< 0x02000 */
-#define RES4328_RX_FILTBYP		14	/**< 0x04000 */
-#define RES4328_XTAL_PU			15	/**< 0x08000 */
-#define RES4328_XTAL_EN			16	/**< 0x10000 */
-#define RES4328_BB_PLL_FILTBYP		17	/**< 0x20000 */
-#define RES4328_RF_PLL_FILTBYP		18	/**< 0x40000 */
-#define RES4328_BB_PLL_PU		19	/**< 0x80000 */
-
-/* 4325 A0/A1 resources */
-#define RES4325_BUCK_BOOST_BURST	0	/**< 0x00000001 */
-#define RES4325_CBUCK_BURST		1	/**< 0x00000002 */
-#define RES4325_CBUCK_PWM		2	/**< 0x00000004 */
-#define RES4325_CLDO_CBUCK_BURST	3	/**< 0x00000008 */
-#define RES4325_CLDO_CBUCK_PWM		4	/**< 0x00000010 */
-#define RES4325_BUCK_BOOST_PWM		5	/**< 0x00000020 */
-#define RES4325_ILP_REQUEST		6	/**< 0x00000040 */
-#define RES4325_ABUCK_BURST		7	/**< 0x00000080 */
-#define RES4325_ABUCK_PWM		8	/**< 0x00000100 */
-#define RES4325_LNLDO1_PU		9	/**< 0x00000200 */
-#define RES4325_OTP_PU			10	/**< 0x00000400 */
-#define RES4325_LNLDO3_PU		11	/**< 0x00000800 */
-#define RES4325_LNLDO4_PU		12	/**< 0x00001000 */
-#define RES4325_XTAL_PU			13	/**< 0x00002000 */
-#define RES4325_ALP_AVAIL		14	/**< 0x00004000 */
-#define RES4325_RX_PWRSW_PU		15	/**< 0x00008000 */
-#define RES4325_TX_PWRSW_PU		16	/**< 0x00010000 */
-#define RES4325_RFPLL_PWRSW_PU		17	/**< 0x00020000 */
-#define RES4325_LOGEN_PWRSW_PU		18	/**< 0x00040000 */
-#define RES4325_AFE_PWRSW_PU		19	/**< 0x00080000 */
-#define RES4325_BBPLL_PWRSW_PU		20	/**< 0x00100000 */
-#define RES4325_HT_AVAIL		21	/**< 0x00200000 */
-
-/* 4325 B0/C0 resources */
-#define RES4325B0_CBUCK_LPOM		1	/**< 0x00000002 */
-#define RES4325B0_CBUCK_BURST		2	/**< 0x00000004 */
-#define RES4325B0_CBUCK_PWM		3	/**< 0x00000008 */
-#define RES4325B0_CLDO_PU		4	/**< 0x00000010 */
-
-/* 4325 C1 resources */
-#define RES4325C1_LNLDO2_PU		12	/**< 0x00001000 */
-
-/* 4325 chip-specific ChipStatus register bits */
-#define CST4325_SPROM_OTP_SEL_MASK	0x00000003
-#define CST4325_DEFCIS_SEL		0	/**< OTP is powered up, use def. CIS, no SPROM */
-#define CST4325_SPROM_SEL		1	/**< OTP is powered up, SPROM is present */
-#define CST4325_OTP_SEL			2	/**< OTP is powered up, no SPROM */
-#define CST4325_OTP_PWRDN		3	/**< OTP is powered down, SPROM is present */
-#define CST4325_SDIO_USB_MODE_MASK	0x00000004
-#define CST4325_SDIO_USB_MODE_SHIFT	2
-#define CST4325_RCAL_VALID_MASK		0x00000008
-#define CST4325_RCAL_VALID_SHIFT	3
-#define CST4325_RCAL_VALUE_MASK		0x000001f0
-#define CST4325_RCAL_VALUE_SHIFT	4
-#define CST4325_PMUTOP_2B_MASK 		0x00000200	/**< 1 for 2b, 0 for to 2a */
-#define CST4325_PMUTOP_2B_SHIFT   	9
-
-#define RES4329_RESERVED0		0	/**< 0x00000001 */
-#define RES4329_CBUCK_LPOM		1	/**< 0x00000002 */
-#define RES4329_CBUCK_BURST		2	/**< 0x00000004 */
-#define RES4329_CBUCK_PWM		3	/**< 0x00000008 */
-#define RES4329_CLDO_PU			4	/**< 0x00000010 */
-#define RES4329_PALDO_PU		5	/**< 0x00000020 */
-#define RES4329_ILP_REQUEST		6	/**< 0x00000040 */
-#define RES4329_RESERVED7		7	/**< 0x00000080 */
-#define RES4329_RESERVED8		8	/**< 0x00000100 */
-#define RES4329_LNLDO1_PU		9	/**< 0x00000200 */
-#define RES4329_OTP_PU			10	/**< 0x00000400 */
-#define RES4329_RESERVED11		11	/**< 0x00000800 */
-#define RES4329_LNLDO2_PU		12	/**< 0x00001000 */
-#define RES4329_XTAL_PU			13	/**< 0x00002000 */
-#define RES4329_ALP_AVAIL		14	/**< 0x00004000 */
-#define RES4329_RX_PWRSW_PU		15	/**< 0x00008000 */
-#define RES4329_TX_PWRSW_PU		16	/**< 0x00010000 */
-#define RES4329_RFPLL_PWRSW_PU		17	/**< 0x00020000 */
-#define RES4329_LOGEN_PWRSW_PU		18	/**< 0x00040000 */
-#define RES4329_AFE_PWRSW_PU		19	/**< 0x00080000 */
-#define RES4329_BBPLL_PWRSW_PU		20	/**< 0x00100000 */
-#define RES4329_HT_AVAIL		21	/**< 0x00200000 */
-
-#define CST4329_SPROM_OTP_SEL_MASK	0x00000003
-#define CST4329_DEFCIS_SEL		0	/**< OTP is powered up, use def. CIS, no SPROM */
-#define CST4329_SPROM_SEL		1	/**< OTP is powered up, SPROM is present */
-#define CST4329_OTP_SEL			2	/**< OTP is powered up, no SPROM */
-#define CST4329_OTP_PWRDN		3	/**< OTP is powered down, SPROM is present */
-#define CST4329_SPI_SDIO_MODE_MASK	0x00000004
-#define CST4329_SPI_SDIO_MODE_SHIFT	2
-
-/* 4312 chip-specific ChipStatus register bits */
-#define CST4312_SPROM_OTP_SEL_MASK	0x00000003
-#define CST4312_DEFCIS_SEL		0	/**< OTP is powered up, use def. CIS, no SPROM */
-#define CST4312_SPROM_SEL		1	/**< OTP is powered up, SPROM is present */
-#define CST4312_OTP_SEL			2	/**< OTP is powered up, no SPROM */
-#define CST4312_OTP_BAD			3	/**< OTP is broken, SPROM is present */
-
-/* 4312 resources (all PMU chips with little memory constraint) */
-#define RES4312_SWITCHER_BURST		0	/**< 0x00000001 */
-#define RES4312_SWITCHER_PWM    	1	/**< 0x00000002 */
-#define RES4312_PA_REF_LDO		2	/**< 0x00000004 */
-#define RES4312_CORE_LDO_BURST		3	/**< 0x00000008 */
-#define RES4312_CORE_LDO_PWM		4	/**< 0x00000010 */
-#define RES4312_RADIO_LDO		5	/**< 0x00000020 */
-#define RES4312_ILP_REQUEST		6	/**< 0x00000040 */
-#define RES4312_BG_FILTBYP		7	/**< 0x00000080 */
-#define RES4312_TX_FILTBYP		8	/**< 0x00000100 */
-#define RES4312_RX_FILTBYP		9	/**< 0x00000200 */
-#define RES4312_XTAL_PU			10	/**< 0x00000400 */
-#define RES4312_ALP_AVAIL		11	/**< 0x00000800 */
-#define RES4312_BB_PLL_FILTBYP		12	/**< 0x00001000 */
-#define RES4312_RF_PLL_FILTBYP		13	/**< 0x00002000 */
-#define RES4312_HT_AVAIL		14	/**< 0x00004000 */
-
-/* 4322 resources */
-#define RES4322_RF_LDO			0
-#define RES4322_ILP_REQUEST		1
-#define RES4322_XTAL_PU			2
-#define RES4322_ALP_AVAIL		3
-#define RES4322_SI_PLL_ON		4
-#define RES4322_HT_SI_AVAIL		5
-#define RES4322_PHY_PLL_ON		6
-#define RES4322_HT_PHY_AVAIL		7
-#define RES4322_OTP_PU			8
-
-/* 4322 chip-specific ChipStatus register bits */
-#define CST4322_XTAL_FREQ_20_40MHZ	0x00000020
-#define CST4322_SPROM_OTP_SEL_MASK	0x000000c0
-#define CST4322_SPROM_OTP_SEL_SHIFT	6
-#define CST4322_NO_SPROM_OTP		0	/**< no OTP, no SPROM */
-#define CST4322_SPROM_PRESENT		1	/**< SPROM is present */
-#define CST4322_OTP_PRESENT		2	/**< OTP is present */
-#define CST4322_PCI_OR_USB		0x00000100
-#define CST4322_BOOT_MASK		0x00000600
-#define CST4322_BOOT_SHIFT		9
-#define CST4322_BOOT_FROM_SRAM		0	/**< boot from SRAM, ARM in reset */
-#define CST4322_BOOT_FROM_ROM		1	/**< boot from ROM */
-#define CST4322_BOOT_FROM_FLASH		2	/**< boot from FLASH */
-#define CST4322_BOOT_FROM_INVALID	3
-#define CST4322_ILP_DIV_EN		0x00000800
-#define CST4322_FLASH_TYPE_MASK		0x00001000
-#define CST4322_FLASH_TYPE_SHIFT	12
-#define CST4322_FLASH_TYPE_SHIFT_ST	0	/**< ST serial FLASH */
-#define CST4322_FLASH_TYPE_SHIFT_ATMEL	1	/**< ATMEL flash */
-#define CST4322_ARM_TAP_SEL		0x00002000
-#define CST4322_RES_INIT_MODE_MASK	0x0000c000
-#define CST4322_RES_INIT_MODE_SHIFT	14
-#define CST4322_RES_INIT_MODE_ILPAVAIL	0	/**< resinitmode: ILP available */
-#define CST4322_RES_INIT_MODE_ILPREQ	1	/**< resinitmode: ILP request */
-#define CST4322_RES_INIT_MODE_ALPAVAIL	2	/**< resinitmode: ALP available */
-#define CST4322_RES_INIT_MODE_HTAVAIL	3	/**< resinitmode: HT available */
-#define CST4322_PCIPLLCLK_GATING	0x00010000
-#define CST4322_CLK_SWITCH_PCI_TO_ALP	0x00020000
-#define CST4322_PCI_CARDBUS_MODE	0x00040000
-
-/* 43224 chip-specific ChipControl register bits */
-#define CCTRL43224_GPIO_TOGGLE          0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */
-#define CCTRL_43224A0_12MA_LED_DRIVE    0x00F000F0 /* 12 mA drive strength */
-#define CCTRL_43224B0_12MA_LED_DRIVE    0xF0    /* 12 mA drive strength for later 43224s */
-
-/* 43236 resources */
-#define RES43236_REGULATOR		0
-#define RES43236_ILP_REQUEST		1
-#define RES43236_XTAL_PU		2
-#define RES43236_ALP_AVAIL		3
-#define RES43236_SI_PLL_ON		4
-#define RES43236_HT_SI_AVAIL		5
-
-/* 43236 chip-specific ChipControl register bits */
-#define CCTRL43236_BT_COEXIST		(1<<0)	/**< 0 disable */
-#define CCTRL43236_SECI			(1<<1)	/**< 0 SECI is disabled (JATG functional) */
-#define CCTRL43236_EXT_LNA		(1<<2)	/**< 0 disable */
-#define CCTRL43236_ANT_MUX_2o3          (1<<3)	/**< 2o3 mux, chipcontrol bit 3 */
-#define CCTRL43236_GSIO			(1<<4)	/**< 0 disable */
-
-/* 43236 Chip specific ChipStatus register bits */
-#define CST43236_SFLASH_MASK		0x00000040
-#define CST43236_OTP_SEL_MASK		0x00000080
-#define CST43236_OTP_SEL_SHIFT		7
-#define CST43236_HSIC_MASK		0x00000100	/**< USB/HSIC */
-#define CST43236_BP_CLK			0x00000200	/**< 120/96Mbps */
-#define CST43236_BOOT_MASK		0x00001800
-#define CST43236_BOOT_SHIFT		11
-#define CST43236_BOOT_FROM_SRAM		0	/**< boot from SRAM, ARM in reset */
-#define CST43236_BOOT_FROM_ROM		1	/**< boot from ROM */
-#define CST43236_BOOT_FROM_FLASH	2	/**< boot from FLASH */
-#define CST43236_BOOT_FROM_INVALID	3
-
-/* 43237 resources */
-#define RES43237_REGULATOR		0
-#define RES43237_ILP_REQUEST		1
-#define RES43237_XTAL_PU		2
-#define RES43237_ALP_AVAIL		3
-#define RES43237_SI_PLL_ON		4
-#define RES43237_HT_SI_AVAIL		5
-
-/* 43237 chip-specific ChipControl register bits */
-#define CCTRL43237_BT_COEXIST		(1<<0)	/**< 0 disable */
-#define CCTRL43237_SECI			(1<<1)	/**< 0 SECI is disabled (JATG functional) */
-#define CCTRL43237_EXT_LNA		(1<<2)	/**< 0 disable */
-#define CCTRL43237_ANT_MUX_2o3          (1<<3)	/**< 2o3 mux, chipcontrol bit 3 */
-#define CCTRL43237_GSIO			(1<<4)	/**< 0 disable */
-
-/* 43237 Chip specific ChipStatus register bits */
-#define CST43237_SFLASH_MASK		0x00000040
-#define CST43237_OTP_SEL_MASK		0x00000080
-#define CST43237_OTP_SEL_SHIFT		7
-#define CST43237_HSIC_MASK		0x00000100	/**< USB/HSIC */
-#define CST43237_BP_CLK			0x00000200	/**< 120/96Mbps */
-#define CST43237_BOOT_MASK		0x00001800
-#define CST43237_BOOT_SHIFT		11
-#define CST43237_BOOT_FROM_SRAM		0	/**< boot from SRAM, ARM in reset */
-#define CST43237_BOOT_FROM_ROM		1	/**< boot from ROM */
-#define CST43237_BOOT_FROM_FLASH	2	/**< boot from FLASH */
-#define CST43237_BOOT_FROM_INVALID	3
-
-/* 43239 resources */
-#define RES43239_OTP_PU			9
-#define RES43239_MACPHY_CLKAVAIL	23
-#define RES43239_HT_AVAIL		24
-
-/* 43239 Chip specific ChipStatus register bits */
-#define CST43239_SPROM_MASK			0x00000002
-#define CST43239_SFLASH_MASK		0x00000004
-#define	CST43239_RES_INIT_MODE_SHIFT	7
-#define	CST43239_RES_INIT_MODE_MASK		0x000001f0
-#define CST43239_CHIPMODE_SDIOD(cs)	((cs) & (1 << 15))	/**< SDIO || gSPI */
-#define CST43239_CHIPMODE_USB20D(cs)	(~(cs) & (1 << 15))	/**< USB || USBDA */
-#define CST43239_CHIPMODE_SDIO(cs)	(((cs) & (1 << 0)) == 0)	/**< SDIO */
-#define CST43239_CHIPMODE_GSPI(cs)	(((cs) & (1 << 0)) == (1 << 0))	/**< gSPI */
-
-/* 4324 resources */
-/* 43242 use same PMU as 4324 */
-#define RES4324_LPLDO_PU			0
-#define RES4324_RESET_PULLDN_DIS		1
-#define RES4324_PMU_BG_PU			2
-#define RES4324_HSIC_LDO_PU			3
-#define RES4324_CBUCK_LPOM_PU			4
-#define RES4324_CBUCK_PFM_PU			5
-#define RES4324_CLDO_PU				6
-#define RES4324_LPLDO2_LVM			7
-#define RES4324_LNLDO1_PU			8
-#define RES4324_LNLDO2_PU			9
-#define RES4324_LDO3P3_PU			10
-#define RES4324_OTP_PU				11
-#define RES4324_XTAL_PU				12
-#define RES4324_BBPLL_PU			13
-#define RES4324_LQ_AVAIL			14
-#define RES4324_WL_CORE_READY			17
-#define RES4324_ILP_REQ				18
-#define RES4324_ALP_AVAIL			19
-#define RES4324_PALDO_PU			20
-#define RES4324_RADIO_PU			21
-#define RES4324_SR_CLK_STABLE			22
-#define RES4324_SR_SAVE_RESTORE			23
-#define RES4324_SR_PHY_PWRSW			24
-#define RES4324_SR_PHY_PIC			25
-#define RES4324_SR_SUBCORE_PWRSW		26
-#define RES4324_SR_SUBCORE_PIC			27
-#define RES4324_SR_MEM_PM0			28
-#define RES4324_HT_AVAIL			29
-#define RES4324_MACPHY_CLKAVAIL			30
-
-/* 4324 Chip specific ChipStatus register bits */
-#define CST4324_SPROM_MASK			0x00000080
-#define CST4324_SFLASH_MASK			0x00400000
-#define	CST4324_RES_INIT_MODE_SHIFT	10
-#define	CST4324_RES_INIT_MODE_MASK	0x00000c00
-#define CST4324_CHIPMODE_MASK		0x7
-#define CST4324_CHIPMODE_SDIOD(cs)	((~(cs)) & (1 << 2))	/**< SDIO || gSPI */
-#define CST4324_CHIPMODE_USB20D(cs)	(((cs) & CST4324_CHIPMODE_MASK) == 0x6)	/**< USB || USBDA */
-
-/* 43242 Chip specific ChipStatus register bits */
-#define CST43242_SFLASH_MASK                    0x00000008
-#define CST43242_SR_HALT			(1<<25)
-#define CST43242_SR_CHIP_STATUS_2		27 /* bit 27 */
-
-/* 4331 resources */
-#define RES4331_REGULATOR		0
-#define RES4331_ILP_REQUEST		1
-#define RES4331_XTAL_PU			2
-#define RES4331_ALP_AVAIL		3
-#define RES4331_SI_PLL_ON		4
-#define RES4331_HT_SI_AVAIL		5
-
-/* 4331 chip-specific ChipControl register bits */
-#define CCTRL4331_BT_COEXIST		(1<<0)	/**< 0 disable */
-#define CCTRL4331_SECI			(1<<1)	/**< 0 SECI is disabled (JATG functional) */
-#define CCTRL4331_EXT_LNA_G		(1<<2)	/**< 0 disable */
-#define CCTRL4331_SPROM_GPIO13_15       (1<<3)	/**< sprom/gpio13-15 mux */
-#define CCTRL4331_EXTPA_EN		(1<<4)	/**< 0 ext pa disable, 1 ext pa enabled */
-#define CCTRL4331_GPIOCLK_ON_SPROMCS	(1<<5)	/**< set drive out GPIO_CLK on sprom_cs pin */
-#define CCTRL4331_PCIE_MDIO_ON_SPROMCS	(1<<6)	/**< use sprom_cs pin as PCIE mdio interface */
-#define CCTRL4331_EXTPA_ON_GPIO2_5	(1<<7)	/* aband extpa will be at gpio2/5 and sprom_dout */
-#define CCTRL4331_OVR_PIPEAUXCLKEN	(1<<8)	/**< override core control on pipe_AuxClkEnable */
-#define CCTRL4331_OVR_PIPEAUXPWRDOWN	(1<<9)	/**< override core control on pipe_AuxPowerDown */
-#define CCTRL4331_PCIE_AUXCLKEN		(1<<10)	/**< pcie_auxclkenable */
-#define CCTRL4331_PCIE_PIPE_PLLDOWN	(1<<11)	/**< pcie_pipe_pllpowerdown */
-#define CCTRL4331_EXTPA_EN2		(1<<12)	/**< 0 ext pa disable, 1 ext pa enabled */
-#define CCTRL4331_EXT_LNA_A		(1<<13)	/**< 0 disable */
-#define CCTRL4331_BT_SHD0_ON_GPIO4	(1<<16)	/**< enable bt_shd0 at gpio4 */
-#define CCTRL4331_BT_SHD1_ON_GPIO5	(1<<17)	/**< enable bt_shd1 at gpio5 */
-#define CCTRL4331_EXTPA_ANA_EN		(1<<24)	/**< 0 ext pa disable, 1 ext pa enabled */
-
-/* 4331 Chip specific ChipStatus register bits */
-#define	CST4331_XTAL_FREQ		0x00000001	/**< crystal frequency 20/40Mhz */
-#define	CST4331_SPROM_OTP_SEL_MASK	0x00000006
-#define	CST4331_SPROM_OTP_SEL_SHIFT	1
-#define	CST4331_SPROM_PRESENT		0x00000002
-#define	CST4331_OTP_PRESENT		0x00000004
-#define	CST4331_LDO_RF			0x00000008
-#define	CST4331_LDO_PAR			0x00000010
-
-/* 4315 resource */
-#define RES4315_CBUCK_LPOM		1	/**< 0x00000002 */
-#define RES4315_CBUCK_BURST		2	/**< 0x00000004 */
-#define RES4315_CBUCK_PWM		3	/**< 0x00000008 */
-#define RES4315_CLDO_PU			4	/**< 0x00000010 */
-#define RES4315_PALDO_PU		5	/**< 0x00000020 */
-#define RES4315_ILP_REQUEST		6	/**< 0x00000040 */
-#define RES4315_LNLDO1_PU		9	/**< 0x00000200 */
-#define RES4315_OTP_PU			10	/**< 0x00000400 */
-#define RES4315_LNLDO2_PU		12	/**< 0x00001000 */
-#define RES4315_XTAL_PU			13	/**< 0x00002000 */
-#define RES4315_ALP_AVAIL		14	/**< 0x00004000 */
-#define RES4315_RX_PWRSW_PU		15	/**< 0x00008000 */
-#define RES4315_TX_PWRSW_PU		16	/**< 0x00010000 */
-#define RES4315_RFPLL_PWRSW_PU		17	/**< 0x00020000 */
-#define RES4315_LOGEN_PWRSW_PU		18	/**< 0x00040000 */
-#define RES4315_AFE_PWRSW_PU		19	/**< 0x00080000 */
-#define RES4315_BBPLL_PWRSW_PU		20	/**< 0x00100000 */
-#define RES4315_HT_AVAIL		21	/**< 0x00200000 */
-
-/* 4315 chip-specific ChipStatus register bits */
-#define CST4315_SPROM_OTP_SEL_MASK	0x00000003	/**< gpio [7:6], SDIO CIS selection */
-#define CST4315_DEFCIS_SEL		0x00000000	/**< use default CIS, OTP is powered up */
-#define CST4315_SPROM_SEL		0x00000001	/**< use SPROM, OTP is powered up */
-#define CST4315_OTP_SEL			0x00000002	/**< use OTP, OTP is powered up */
-#define CST4315_OTP_PWRDN		0x00000003	/**< use SPROM, OTP is powered down */
-#define CST4315_SDIO_MODE		0x00000004	/**< gpio [8], sdio/usb mode */
-#define CST4315_RCAL_VALID		0x00000008
-#define CST4315_RCAL_VALUE_MASK		0x000001f0
-#define CST4315_RCAL_VALUE_SHIFT	4
-#define CST4315_PALDO_EXTPNP		0x00000200 /**< PALDO is configured with external PNP */
-#define CST4315_CBUCK_MODE_MASK		0x00000c00
-#define CST4315_CBUCK_MODE_BURST	0x00000400
-#define CST4315_CBUCK_MODE_LPBURST	0x00000c00
-
-/* 4319 resources */
-#define RES4319_CBUCK_LPOM		1	/**< 0x00000002 */
-#define RES4319_CBUCK_BURST		2	/**< 0x00000004 */
-#define RES4319_CBUCK_PWM		3	/**< 0x00000008 */
-#define RES4319_CLDO_PU			4	/**< 0x00000010 */
-#define RES4319_PALDO_PU		5	/**< 0x00000020 */
-#define RES4319_ILP_REQUEST		6	/**< 0x00000040 */
-#define RES4319_LNLDO1_PU		9	/**< 0x00000200 */
-#define RES4319_OTP_PU			10	/**< 0x00000400 */
-#define RES4319_LNLDO2_PU		12	/**< 0x00001000 */
-#define RES4319_XTAL_PU			13	/**< 0x00002000 */
-#define RES4319_ALP_AVAIL		14	/**< 0x00004000 */
-#define RES4319_RX_PWRSW_PU		15	/**< 0x00008000 */
-#define RES4319_TX_PWRSW_PU		16	/**< 0x00010000 */
-#define RES4319_RFPLL_PWRSW_PU		17	/**< 0x00020000 */
-#define RES4319_LOGEN_PWRSW_PU		18	/**< 0x00040000 */
-#define RES4319_AFE_PWRSW_PU		19	/**< 0x00080000 */
-#define RES4319_BBPLL_PWRSW_PU		20	/**< 0x00100000 */
-#define RES4319_HT_AVAIL		21	/**< 0x00200000 */
-
-/* 4319 chip-specific ChipStatus register bits */
-#define	CST4319_SPI_CPULESSUSB		0x00000001
-#define	CST4319_SPI_CLK_POL		0x00000002
-#define	CST4319_SPI_CLK_PH		0x00000008
-#define	CST4319_SPROM_OTP_SEL_MASK	0x000000c0	/**< gpio [7:6], SDIO CIS selection */
-#define	CST4319_SPROM_OTP_SEL_SHIFT	6
-#define	CST4319_DEFCIS_SEL		0x00000000	/**< use default CIS, OTP is powered up */
-#define	CST4319_SPROM_SEL		0x00000040	/**< use SPROM, OTP is powered up */
-#define	CST4319_OTP_SEL			0x00000080      /* use OTP, OTP is powered up */
-#define	CST4319_OTP_PWRDN		0x000000c0      /* use SPROM, OTP is powered down */
-#define	CST4319_SDIO_USB_MODE		0x00000100	/**< gpio [8], sdio/usb mode */
-#define	CST4319_REMAP_SEL_MASK		0x00000600
-#define	CST4319_ILPDIV_EN		0x00000800
-#define	CST4319_XTAL_PD_POL		0x00001000
-#define	CST4319_LPO_SEL			0x00002000
-#define	CST4319_RES_INIT_MODE		0x0000c000
-#define	CST4319_PALDO_EXTPNP		0x00010000 /**< PALDO is configured with external PNP */
-#define	CST4319_CBUCK_MODE_MASK		0x00060000
-#define CST4319_CBUCK_MODE_BURST	0x00020000
-#define CST4319_CBUCK_MODE_LPBURST	0x00060000
-#define	CST4319_RCAL_VALID		0x01000000
-#define	CST4319_RCAL_VALUE_MASK		0x3e000000
-#define	CST4319_RCAL_VALUE_SHIFT	25
-
-#define PMU1_PLL0_CHIPCTL0		0
-#define PMU1_PLL0_CHIPCTL1		1
-#define PMU1_PLL0_CHIPCTL2		2
-#define CCTL_4319USB_XTAL_SEL_MASK	0x00180000
-#define CCTL_4319USB_XTAL_SEL_SHIFT	19
-#define CCTL_4319USB_48MHZ_PLL_SEL	1
-#define CCTL_4319USB_24MHZ_PLL_SEL	2
-
-/* PMU resources for 4336 */
-#define	RES4336_CBUCK_LPOM		0
-#define	RES4336_CBUCK_BURST		1
-#define	RES4336_CBUCK_LP_PWM		2
-#define	RES4336_CBUCK_PWM		3
-#define	RES4336_CLDO_PU			4
-#define	RES4336_DIS_INT_RESET_PD	5
-#define	RES4336_ILP_REQUEST		6
-#define	RES4336_LNLDO_PU		7
-#define	RES4336_LDO3P3_PU		8
-#define	RES4336_OTP_PU			9
-#define	RES4336_XTAL_PU			10
-#define	RES4336_ALP_AVAIL		11
-#define	RES4336_RADIO_PU		12
-#define	RES4336_BG_PU			13
-#define	RES4336_VREG1p4_PU_PU		14
-#define	RES4336_AFE_PWRSW_PU		15
-#define	RES4336_RX_PWRSW_PU		16
-#define	RES4336_TX_PWRSW_PU		17
-#define	RES4336_BB_PWRSW_PU		18
-#define	RES4336_SYNTH_PWRSW_PU		19
-#define	RES4336_MISC_PWRSW_PU		20
-#define	RES4336_LOGEN_PWRSW_PU		21
-#define	RES4336_BBPLL_PWRSW_PU		22
-#define	RES4336_MACPHY_CLKAVAIL		23
-#define	RES4336_HT_AVAIL		24
-#define	RES4336_RSVD			25
-
-/* 4336 chip-specific ChipStatus register bits */
-#define	CST4336_SPI_MODE_MASK		0x00000001
-#define	CST4336_SPROM_PRESENT		0x00000002
-#define	CST4336_OTP_PRESENT		0x00000004
-#define	CST4336_ARMREMAP_0		0x00000008
-#define	CST4336_ILPDIV_EN_MASK		0x00000010
-#define	CST4336_ILPDIV_EN_SHIFT		4
-#define	CST4336_XTAL_PD_POL_MASK	0x00000020
-#define	CST4336_XTAL_PD_POL_SHIFT	5
-#define	CST4336_LPO_SEL_MASK		0x00000040
-#define	CST4336_LPO_SEL_SHIFT		6
-#define	CST4336_RES_INIT_MODE_MASK	0x00000180
-#define	CST4336_RES_INIT_MODE_SHIFT	7
-#define	CST4336_CBUCK_MODE_MASK		0x00000600
-#define	CST4336_CBUCK_MODE_SHIFT	9
-
-/* 4336 Chip specific PMU ChipControl register bits */
-#define PCTL_4336_SERIAL_ENAB	(1  << 24)
-
-/* 4330 resources */
-#define	RES4330_CBUCK_LPOM		0
-#define	RES4330_CBUCK_BURST		1
-#define	RES4330_CBUCK_LP_PWM		2
-#define	RES4330_CBUCK_PWM		3
-#define	RES4330_CLDO_PU			4
-#define	RES4330_DIS_INT_RESET_PD	5
-#define	RES4330_ILP_REQUEST		6
-#define	RES4330_LNLDO_PU		7
-#define	RES4330_LDO3P3_PU		8
-#define	RES4330_OTP_PU			9
-#define	RES4330_XTAL_PU			10
-#define	RES4330_ALP_AVAIL		11
-#define	RES4330_RADIO_PU		12
-#define	RES4330_BG_PU			13
-#define	RES4330_VREG1p4_PU_PU		14
-#define	RES4330_AFE_PWRSW_PU		15
-#define	RES4330_RX_PWRSW_PU		16
-#define	RES4330_TX_PWRSW_PU		17
-#define	RES4330_BB_PWRSW_PU		18
-#define	RES4330_SYNTH_PWRSW_PU		19
-#define	RES4330_MISC_PWRSW_PU		20
-#define	RES4330_LOGEN_PWRSW_PU		21
-#define	RES4330_BBPLL_PWRSW_PU		22
-#define	RES4330_MACPHY_CLKAVAIL		23
-#define	RES4330_HT_AVAIL		24
-#define	RES4330_5gRX_PWRSW_PU		25
-#define	RES4330_5gTX_PWRSW_PU		26
-#define	RES4330_5g_LOGEN_PWRSW_PU	27
-
-/* 4330 chip-specific ChipStatus register bits */
-#define CST4330_CHIPMODE_SDIOD(cs)	(((cs) & 0x7) < 6)	/**< SDIO || gSPI */
-#define CST4330_CHIPMODE_USB20D(cs)	(((cs) & 0x7) >= 6)	/**< USB || USBDA */
-#define CST4330_CHIPMODE_SDIO(cs)	(((cs) & 0x4) == 0)	/**< SDIO */
-#define CST4330_CHIPMODE_GSPI(cs)	(((cs) & 0x6) == 4)	/**< gSPI */
-#define CST4330_CHIPMODE_USB(cs)	(((cs) & 0x7) == 6)	/**< USB packet-oriented */
-#define CST4330_CHIPMODE_USBDA(cs)	(((cs) & 0x7) == 7)	/**< USB Direct Access */
-#define	CST4330_OTP_PRESENT		0x00000010
-#define	CST4330_LPO_AUTODET_EN		0x00000020
-#define	CST4330_ARMREMAP_0		0x00000040
-#define	CST4330_SPROM_PRESENT		0x00000080	/**< takes priority over OTP if both set */
-#define	CST4330_ILPDIV_EN		0x00000100
-#define	CST4330_LPO_SEL			0x00000200
-#define	CST4330_RES_INIT_MODE_SHIFT	10
-#define	CST4330_RES_INIT_MODE_MASK	0x00000c00
-#define CST4330_CBUCK_MODE_SHIFT	12
-#define CST4330_CBUCK_MODE_MASK		0x00003000
-#define	CST4330_CBUCK_POWER_OK		0x00004000
-#define	CST4330_BB_PLL_LOCKED		0x00008000
-#define SOCDEVRAM_BP_ADDR		0x1E000000
-#define SOCDEVRAM_ARM_ADDR		0x00800000
-
-/* 4330 Chip specific PMU ChipControl register bits */
-#define PCTL_4330_SERIAL_ENAB	(1  << 24)
-
-/* 4330 Chip specific ChipControl register bits */
-#define CCTRL_4330_GPIO_SEL		0x00000001    /* 1=select GPIOs to be muxed out */
-#define CCTRL_4330_ERCX_SEL		0x00000002    /* 1=select ERCX BT coex to be muxed out */
-#define CCTRL_4330_SDIO_HOST_WAKE	0x00000004    /* SDIO: 1=configure GPIO0 for host wake */
-#define CCTRL_4330_JTAG_DISABLE	0x00000008    /* 1=disable JTAG interface on mux'd pins */
-
-#define PMU_VREG0_ADDR				0
-#define PMU_VREG0_DISABLE_PULLD_BT_SHIFT	2
-#define PMU_VREG0_DISABLE_PULLD_WL_SHIFT	3
-
-#define PMU_VREG4_ADDR			4
-
-#define PMU_VREG4_CLDO_PWM_SHIFT	4
-#define PMU_VREG4_CLDO_PWM_MASK		0x7
-
-#define PMU_VREG4_LPLDO1_SHIFT		15
-#define PMU_VREG4_LPLDO1_MASK		0x7
-#define PMU_VREG4_LPLDO1_1p20V		0
-#define PMU_VREG4_LPLDO1_1p15V		1
-#define PMU_VREG4_LPLDO1_1p10V		2
-#define PMU_VREG4_LPLDO1_1p25V		3
-#define PMU_VREG4_LPLDO1_1p05V		4
-#define PMU_VREG4_LPLDO1_1p00V		5
-#define PMU_VREG4_LPLDO1_0p95V		6
-#define PMU_VREG4_LPLDO1_0p90V		7
-
-/* 4350/4345 VREG4 settings */
-#define PMU4350_VREG4_LPLDO1_1p10V	0
-#define PMU4350_VREG4_LPLDO1_1p15V	1
-#define PMU4350_VREG4_LPLDO1_1p21V	2
-#define PMU4350_VREG4_LPLDO1_1p24V	3
-#define PMU4350_VREG4_LPLDO1_0p90V	4
-#define PMU4350_VREG4_LPLDO1_0p96V	5
-#define PMU4350_VREG4_LPLDO1_1p01V	6
-#define PMU4350_VREG4_LPLDO1_1p04V	7
-
-#define PMU_VREG4_LPLDO2_LVM_SHIFT	18
-#define PMU_VREG4_LPLDO2_LVM_MASK	0x7
-#define PMU_VREG4_LPLDO2_HVM_SHIFT	21
-#define PMU_VREG4_LPLDO2_HVM_MASK	0x7
-#define PMU_VREG4_LPLDO2_LVM_HVM_MASK	0x3f
-#define PMU_VREG4_LPLDO2_1p00V		0
-#define PMU_VREG4_LPLDO2_1p15V		1
-#define PMU_VREG4_LPLDO2_1p20V		2
-#define PMU_VREG4_LPLDO2_1p10V		3
-#define PMU_VREG4_LPLDO2_0p90V		4	/**< 4 - 7 is 0.90V */
-
-#define PMU_VREG4_HSICLDO_BYPASS_SHIFT	27
-#define PMU_VREG4_HSICLDO_BYPASS_MASK	0x1
-
-#define PMU_VREG5_ADDR			5
-#define PMU_VREG5_HSICAVDD_PD_SHIFT	6
-#define PMU_VREG5_HSICAVDD_PD_MASK	0x1
-#define PMU_VREG5_HSICDVDD_PD_SHIFT	11
-#define PMU_VREG5_HSICDVDD_PD_MASK	0x1
-
-/* 4334 resources */
-#define RES4334_LPLDO_PU		0
-#define RES4334_RESET_PULLDN_DIS	1
-#define RES4334_PMU_BG_PU		2
-#define RES4334_HSIC_LDO_PU		3
-#define RES4334_CBUCK_LPOM_PU		4
-#define RES4334_CBUCK_PFM_PU		5
-#define RES4334_CLDO_PU			6
-#define RES4334_LPLDO2_LVM		7
-#define RES4334_LNLDO_PU		8
-#define RES4334_LDO3P3_PU		9
-#define RES4334_OTP_PU			10
-#define RES4334_XTAL_PU			11
-#define RES4334_WL_PWRSW_PU		12
-#define RES4334_LQ_AVAIL		13
-#define RES4334_LOGIC_RET		14
-#define RES4334_MEM_SLEEP		15
-#define RES4334_MACPHY_RET		16
-#define RES4334_WL_CORE_READY		17
-#define RES4334_ILP_REQ			18
-#define RES4334_ALP_AVAIL		19
-#define RES4334_MISC_PWRSW_PU		20
-#define RES4334_SYNTH_PWRSW_PU		21
-#define RES4334_RX_PWRSW_PU		22
-#define RES4334_RADIO_PU		23
-#define RES4334_WL_PMU_PU		24
-#define RES4334_VCO_LDO_PU		25
-#define RES4334_AFE_LDO_PU		26
-#define RES4334_RX_LDO_PU		27
-#define RES4334_TX_LDO_PU		28
-#define RES4334_HT_AVAIL		29
-#define RES4334_MACPHY_CLK_AVAIL	30
-
-/* 4334 chip-specific ChipStatus register bits */
-#define CST4334_CHIPMODE_MASK		7
-#define CST4334_SDIO_MODE		0x00000000
-#define CST4334_SPI_MODE		0x00000004
-#define CST4334_HSIC_MODE		0x00000006
-#define CST4334_BLUSB_MODE		0x00000007
-#define CST4334_CHIPMODE_HSIC(cs)	(((cs) & CST4334_CHIPMODE_MASK) == CST4334_HSIC_MODE)
-#define CST4334_OTP_PRESENT		0x00000010
-#define CST4334_LPO_AUTODET_EN		0x00000020
-#define CST4334_ARMREMAP_0		0x00000040
-#define CST4334_SPROM_PRESENT		0x00000080
-#define CST4334_ILPDIV_EN_MASK		0x00000100
-#define CST4334_ILPDIV_EN_SHIFT		8
-#define CST4334_LPO_SEL_MASK		0x00000200
-#define CST4334_LPO_SEL_SHIFT		9
-#define CST4334_RES_INIT_MODE_MASK	0x00000C00
-#define CST4334_RES_INIT_MODE_SHIFT	10
-
-/* 4334 Chip specific PMU ChipControl register bits */
-#define PCTL_4334_GPIO3_ENAB    (1  << 3)
-
-/* 4334 Chip control */
-#define CCTRL4334_PMU_WAKEUP_GPIO1	(1  << 0)
-#define CCTRL4334_PMU_WAKEUP_HSIC	(1  << 1)
-#define CCTRL4334_PMU_WAKEUP_AOS	(1  << 2)
-#define CCTRL4334_HSIC_WAKE_MODE	(1  << 3)
-#define CCTRL4334_HSIC_INBAND_GPIO1	(1  << 4)
-#define CCTRL4334_HSIC_LDO_PU		(1  << 23)
-
-/* 4334 Chip control 3 */
-#define CCTRL4334_BLOCK_EXTRNL_WAKE		(1  << 4)
-#define CCTRL4334_SAVERESTORE_FIX		(1  << 5)
-
-/* 43341 Chip control 3 */
-#define CCTRL43341_BLOCK_EXTRNL_WAKE		(1  << 13)
-#define CCTRL43341_SAVERESTORE_FIX		(1  << 14)
-#define CCTRL43341_BT_ISO_SEL			(1  << 16)
-
-/* 4334 Chip specific ChipControl1 register bits */
-#define CCTRL1_4334_GPIO_SEL		(1 << 0)    /* 1=select GPIOs to be muxed out */
-#define CCTRL1_4334_ERCX_SEL		(1 << 1)    /* 1=select ERCX BT coex to be muxed out */
-#define CCTRL1_4334_SDIO_HOST_WAKE (1 << 2)  /* SDIO: 1=configure GPIO0 for host wake */
-#define CCTRL1_4334_JTAG_DISABLE	(1 << 3)    /* 1=disable JTAG interface on mux'd pins */
-#define CCTRL1_4334_UART_ON_4_5	(1 << 28) /**< 1=UART_TX/UART_RX muxed on GPIO_4/5 (4334B0/1) */
-
-/* 4324 Chip specific ChipControl1 register bits */
-#define CCTRL1_4324_GPIO_SEL            (1 << 0)    /* 1=select GPIOs to be muxed out */
-#define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2)  /* SDIO: 1=configure GPIO0 for host wake */
-
-/* 43143 chip-specific ChipStatus register bits based on Confluence documentation */
-/* register contains strap values sampled during POR */
-#define CST43143_REMAP_TO_ROM	 (3 << 0)    /* 00=Boot SRAM, 01=Boot ROM, 10=Boot SFLASH */
-#define CST43143_SDIO_EN	 (1 << 2)    /* 0 = USB Enab, SDIO pins are GPIO or I2S */
-#define CST43143_SDIO_ISO	 (1 << 3)    /* 1 = SDIO isolated */
-#define CST43143_USB_CPU_LESS	 (1 << 4)   /* 1 = CPULess mode Enabled */
-#define CST43143_CBUCK_MODE	 (3 << 6)   /* Indicates what controller mode CBUCK is in */
-#define CST43143_POK_CBUCK	 (1 << 8)   /* 1 = 1.2V CBUCK voltage ready */
-#define CST43143_PMU_OVRSPIKE	 (1 << 9)
-#define CST43143_PMU_OVRTEMP	 (0xF << 10)
-#define CST43143_SR_FLL_CAL_DONE (1 << 14)
-#define CST43143_USB_PLL_LOCKDET (1 << 15)
-#define CST43143_PMU_PLL_LOCKDET (1 << 16)
-#define CST43143_CHIPMODE_SDIOD(cs)	(((cs) & CST43143_SDIO_EN) != 0) /* SDIO */
-
-/* 43143 Chip specific ChipControl register bits */
-/* 00: SECI is disabled (JATG functional), 01: 2 wire, 10: 4 wire  */
-#define CCTRL_43143_SECI		(1<<0)
-#define CCTRL_43143_BT_LEGACY		(1<<1)
-#define CCTRL_43143_I2S_MODE		(1<<2)	/**< 0: SDIO enabled */
-#define CCTRL_43143_I2S_MASTER		(1<<3)	/**< 0: I2S MCLK input disabled */
-#define CCTRL_43143_I2S_FULL		(1<<4)	/**< 0: I2S SDIN and SPDIF_TX inputs disabled */
-#define CCTRL_43143_GSIO		(1<<5)	/**< 0: sFlash enabled */
-#define CCTRL_43143_RF_SWCTRL_MASK	(7<<6)	/**< 0: disabled */
-#define CCTRL_43143_RF_SWCTRL_0		(1<<6)
-#define CCTRL_43143_RF_SWCTRL_1		(2<<6)
-#define CCTRL_43143_RF_SWCTRL_2		(4<<6)
-#define CCTRL_43143_RF_XSWCTRL		(1<<9)	/**< 0: UART enabled */
-#define CCTRL_43143_HOST_WAKE0		(1<<11)	/**< 1: SDIO separate interrupt output from GPIO4 */
-#define CCTRL_43143_HOST_WAKE1		(1<<12)	/* 1: SDIO separate interrupt output from GPIO16 */
-
-/* 43143 resources, based on pmu_params.xls V1.19 */
-#define RES43143_EXT_SWITCHER_PWM	0	/**< 0x00001 */
-#define RES43143_XTAL_PU		1	/**< 0x00002 */
-#define RES43143_ILP_REQUEST		2	/**< 0x00004 */
-#define RES43143_ALP_AVAIL		3	/**< 0x00008 */
-#define RES43143_WL_CORE_READY		4	/**< 0x00010 */
-#define RES43143_BBPLL_PWRSW_PU		5	/**< 0x00020 */
-#define RES43143_HT_AVAIL		6	/**< 0x00040 */
-#define RES43143_RADIO_PU		7	/**< 0x00080 */
-#define RES43143_MACPHY_CLK_AVAIL	8	/**< 0x00100 */
-#define RES43143_OTP_PU			9	/**< 0x00200 */
-#define RES43143_LQ_AVAIL		10	/**< 0x00400 */
-
-#define PMU43143_XTAL_CORE_SIZE_MASK	0x3F
-
-/* 4313 resources */
-#define	RES4313_BB_PU_RSRC		0
-#define	RES4313_ILP_REQ_RSRC		1
-#define	RES4313_XTAL_PU_RSRC		2
-#define	RES4313_ALP_AVAIL_RSRC		3
-#define	RES4313_RADIO_PU_RSRC		4
-#define	RES4313_BG_PU_RSRC		5
-#define	RES4313_VREG1P4_PU_RSRC		6
-#define	RES4313_AFE_PWRSW_RSRC		7
-#define	RES4313_RX_PWRSW_RSRC		8
-#define	RES4313_TX_PWRSW_RSRC		9
-#define	RES4313_BB_PWRSW_RSRC		10
-#define	RES4313_SYNTH_PWRSW_RSRC	11
-#define	RES4313_MISC_PWRSW_RSRC		12
-#define	RES4313_BB_PLL_PWRSW_RSRC	13
-#define	RES4313_HT_AVAIL_RSRC		14
-#define	RES4313_MACPHY_CLK_AVAIL_RSRC	15
-
-/* 4313 chip-specific ChipStatus register bits */
-#define	CST4313_SPROM_PRESENT			1
-#define	CST4313_OTP_PRESENT			2
-#define	CST4313_SPROM_OTP_SEL_MASK		0x00000002
-#define	CST4313_SPROM_OTP_SEL_SHIFT		0
-
-/* 4313 Chip specific ChipControl register bits */
-#define CCTRL_4313_12MA_LED_DRIVE    0x00000007    /* 12 mA drive strengh for later 4313 */
-
-/* PMU respources for 4314 */
-#define RES4314_LPLDO_PU		0
-#define RES4314_PMU_SLEEP_DIS		1
-#define RES4314_PMU_BG_PU		2
-#define RES4314_CBUCK_LPOM_PU		3
-#define RES4314_CBUCK_PFM_PU		4
-#define RES4314_CLDO_PU			5
-#define RES4314_LPLDO2_LVM		6
-#define RES4314_WL_PMU_PU		7
-#define RES4314_LNLDO_PU		8
-#define RES4314_LDO3P3_PU		9
-#define RES4314_OTP_PU			10
-#define RES4314_XTAL_PU			11
-#define RES4314_WL_PWRSW_PU		12
-#define RES4314_LQ_AVAIL		13
-#define RES4314_LOGIC_RET		14
-#define RES4314_MEM_SLEEP		15
-#define RES4314_MACPHY_RET		16
-#define RES4314_WL_CORE_READY		17
-#define RES4314_ILP_REQ			18
-#define RES4314_ALP_AVAIL		19
-#define RES4314_MISC_PWRSW_PU		20
-#define RES4314_SYNTH_PWRSW_PU		21
-#define RES4314_RX_PWRSW_PU		22
-#define RES4314_RADIO_PU		23
-#define RES4314_VCO_LDO_PU		24
-#define RES4314_AFE_LDO_PU		25
-#define RES4314_RX_LDO_PU		26
-#define RES4314_TX_LDO_PU		27
-#define RES4314_HT_AVAIL		28
-#define RES4314_MACPHY_CLK_AVAIL	29
-
-/* 4314 chip-specific ChipStatus register bits */
-#define CST4314_OTP_ENABLED		0x00200000
-
-/* 43228 resources */
-#define RES43228_NOT_USED		0
-#define RES43228_ILP_REQUEST		1
-#define RES43228_XTAL_PU		2
-#define RES43228_ALP_AVAIL		3
-#define RES43228_PLL_EN			4
-#define RES43228_HT_PHY_AVAIL		5
-
-/* 43228 chipstatus  reg bits */
-#define CST43228_ILP_DIV_EN		0x1
-#define	CST43228_OTP_PRESENT		0x2
-#define	CST43228_SERDES_REFCLK_PADSEL	0x4
-#define	CST43228_SDIO_MODE		0x8
-#define	CST43228_SDIO_OTP_PRESENT	0x10
-#define	CST43228_SDIO_RESET		0x20
-
-/* 4706 chipstatus reg bits */
-#define	CST4706_PKG_OPTION		(1<<0) /* 0: full-featured package 1: low-cost package */
-#define	CST4706_SFLASH_PRESENT	(1<<1) /* 0: parallel, 1: serial flash is present */
-#define	CST4706_SFLASH_TYPE		(1<<2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */
-#define	CST4706_MIPS_BENDIAN	(1<<3) /* 0: little,  1: big endian */
-#define	CST4706_PCIE1_DISABLE	(1<<5) /* PCIE1 enable strap pin */
-
-/* 4706 flashstrconfig reg bits */
-#define FLSTRCF4706_MASK		0x000000ff
-#define FLSTRCF4706_SF1			0x00000001	/**< 2nd serial flash present */
-#define FLSTRCF4706_PF1			0x00000002	/**< 2nd parallel flash present */
-#define FLSTRCF4706_SF1_TYPE	0x00000004	/**< 2nd serial flash type : 0 : ST, 1 : Atmel */
-#define FLSTRCF4706_NF1			0x00000008	/**< 2nd NAND flash present */
-#define FLSTRCF4706_1ST_MADDR_SEG_MASK		0x000000f0	/**< Valid value mask */
-#define FLSTRCF4706_1ST_MADDR_SEG_4MB		0x00000010	/**< 4MB */
-#define FLSTRCF4706_1ST_MADDR_SEG_8MB		0x00000020	/**< 8MB */
-#define FLSTRCF4706_1ST_MADDR_SEG_16MB		0x00000030	/**< 16MB */
-#define FLSTRCF4706_1ST_MADDR_SEG_32MB		0x00000040	/**< 32MB */
-#define FLSTRCF4706_1ST_MADDR_SEG_64MB		0x00000050	/**< 64MB */
-#define FLSTRCF4706_1ST_MADDR_SEG_128MB		0x00000060	/**< 128MB */
-#define FLSTRCF4706_1ST_MADDR_SEG_256MB		0x00000070	/**< 256MB */
-
-/* 4360 Chip specific ChipControl register bits */
-#define CCTRL4360_I2C_MODE			(1 << 0)
-#define CCTRL4360_UART_MODE			(1 << 1)
-#define CCTRL4360_SECI_MODE			(1 << 2)
-#define CCTRL4360_BTSWCTRL_MODE			(1 << 3)
-#define CCTRL4360_DISCRETE_FEMCTRL_MODE		(1 << 4)
-#define CCTRL4360_DIGITAL_PACTRL_MODE		(1 << 5)
-#define CCTRL4360_BTSWCTRL_AND_DIGPA_PRESENT	(1 << 6)
-#define CCTRL4360_EXTRA_GPIO_MODE		(1 << 7)
-#define CCTRL4360_EXTRA_FEMCTRL_MODE		(1 << 8)
-#define CCTRL4360_BT_LGCY_MODE			(1 << 9)
-#define CCTRL4360_CORE2FEMCTRL4_ON		(1 << 21)
-#define CCTRL4360_SECI_ON_GPIO01		(1 << 24)
-
-/* 4360 Chip specific Regulator Control register bits */
-#define RCTRL4360_RFLDO_PWR_DOWN		(1 << 1)
-
-/* 4360 PMU resources and chip status bits */
-#define RES4360_REGULATOR          0
-#define RES4360_ILP_AVAIL          1
-#define RES4360_ILP_REQ            2
-#define RES4360_XTAL_LDO_PU        3
-#define RES4360_XTAL_PU            4
-#define RES4360_ALP_AVAIL          5
-#define RES4360_BBPLLPWRSW_PU      6
-#define RES4360_HT_AVAIL           7
-#define RES4360_OTP_PU             8
-#define RES4360_AVB_PLL_PWRSW_PU   9
-#define RES4360_PCIE_TL_CLK_AVAIL  10
-
-#define CST4360_XTAL_40MZ                  0x00000001
-#define CST4360_SFLASH                     0x00000002
-#define CST4360_SPROM_PRESENT              0x00000004
-#define CST4360_SFLASH_TYPE                0x00000004
-#define CST4360_OTP_ENABLED                0x00000008
-#define CST4360_REMAP_ROM                  0x00000010
-#define CST4360_RSRC_INIT_MODE_MASK        0x00000060
-#define CST4360_RSRC_INIT_MODE_SHIFT       5
-#define CST4360_ILP_DIVEN                  0x00000080
-#define CST4360_MODE_USB                   0x00000100
-#define CST4360_SPROM_SIZE_MASK            0x00000600
-#define CST4360_SPROM_SIZE_SHIFT           9
-#define CST4360_BBPLL_LOCK                 0x00000800
-#define CST4360_AVBBPLL_LOCK               0x00001000
-#define CST4360_USBBBPLL_LOCK              0x00002000
-#define CST4360_RSRC_INIT_MODE(cs)	((cs & CST4360_RSRC_INIT_MODE_MASK) >> \
-					CST4360_RSRC_INIT_MODE_SHIFT)
-
-#define CCTRL_4360_UART_SEL	0x2
-#define CST4360_RSRC_INIT_MODE(cs)	((cs & CST4360_RSRC_INIT_MODE_MASK) >> \
-					CST4360_RSRC_INIT_MODE_SHIFT)
-
-
-/* 43602 PMU resources based on pmu_params.xls version v0.95 */
-#define RES43602_LPLDO_PU		0
-#define RES43602_REGULATOR		1
-#define RES43602_PMU_SLEEP		2
-#define RES43602_RSVD_3			3
-#define RES43602_XTALLDO_PU		4
-#define RES43602_SERDES_PU		5
-#define RES43602_BBPLL_PWRSW_PU		6
-#define RES43602_SR_CLK_START		7
-#define RES43602_SR_PHY_PWRSW		8
-#define RES43602_SR_SUBCORE_PWRSW	9
-#define RES43602_XTAL_PU		10
-#define	RES43602_PERST_OVR		11
-#define RES43602_SR_CLK_STABLE		12
-#define RES43602_SR_SAVE_RESTORE	13
-#define RES43602_SR_SLEEP		14
-#define RES43602_LQ_START		15
-#define RES43602_LQ_AVAIL		16
-#define RES43602_WL_CORE_RDY		17
-#define RES43602_ILP_REQ		18
-#define RES43602_ALP_AVAIL		19
-#define RES43602_RADIO_PU		20
-#define RES43602_RFLDO_PU		21
-#define RES43602_HT_START		22
-#define RES43602_HT_AVAIL		23
-#define RES43602_MACPHY_CLKAVAIL	24
-#define RES43602_PARLDO_PU		25
-#define RES43602_RSVD_26		26
-
-/* 43602 chip status bits */
-#define CST43602_SPROM_PRESENT             (1<<1)
-#define CST43602_SPROM_SIZE                (1<<10) /* 0 = 16K, 1 = 4K */
-#define CST43602_BBPLL_LOCK                (1<<11)
-#define CST43602_RF_LDO_OUT_OK             (1<<15) /* RF LDO output OK */
-
-#define PMU43602_CC1_GPIO12_OVRD           (1<<28) /* GPIO12 override */
-
-#define PMU43602_CC2_PCIE_CLKREQ_L_WAKE_EN (1<<1)  /* creates gated_pcie_wake, pmu_wakeup logic */
-#define PMU43602_CC2_PCIE_PERST_L_WAKE_EN  (1<<2)  /* creates gated_pcie_wake, pmu_wakeup logic */
-#define PMU43602_CC2_ENABLE_L2REFCLKPAD_PWRDWN (1<<3)
-#define PMU43602_CC2_PMU_WAKE_ALP_AVAIL_EN (1<<5)  /* enable pmu_wakeup to request for ALP_AVAIL */
-#define PMU43602_CC2_PERST_L_EXTEND_EN     (1<<9)  /* extend perst_l until rsc PERST_OVR comes up */
-#define PMU43602_CC2_FORCE_EXT_LPO         (1<<19) /* 1=ext LPO clock is the final LPO clock */
-#define PMU43602_CC2_XTAL32_SEL            (1<<30) /* 0=ext_clock, 1=xtal */
-
-#define CC_SR1_43602_SR_ASM_ADDR	(0x0)
-
-/* PLL CTL register values for open loop, used during S/R operation */
-#define PMU43602_PLL_CTL6_VAL		0x68000528
-#define PMU43602_PLL_CTL7_VAL		0x6
-
-#define PMU43602_CC3_ARMCR4_DBG_CLK	(1 << 29)
-
-/* 4365 PMU resources */
-#define RES4365_REGULATOR_PU			0
-#define RES4365_XTALLDO_PU			1
-#define RES4365_XTAL_PU				2
-#define RES4365_CPU_PLLLDO_PU			3
-#define RES4365_CPU_PLL_PU			4
-#define RES4365_WL_CORE_RDY			5
-#define RES4365_ILP_REQ				6
-#define RES4365_ALP_AVAIL			7
-#define RES4365_HT_AVAIL			8
-#define RES4365_BB_PLLLDO_PU			9
-#define RES4365_BB_PLL_PU			10
-#define RES4365_MINIMU_PU			11
-#define RES4365_RADIO_PU			12
-#define RES4365_MACPHY_CLK_AVAIL		13
-
-/* 4349 related */
-#define RES4349_LPLDO_PU			0
-#define RES4349_BG_PU				1
-#define RES4349_PMU_SLEEP			2
-#define RES4349_PALDO3P3_PU			3
-#define RES4349_CBUCK_LPOM_PU		4
-#define RES4349_CBUCK_PFM_PU		5
-#define RES4349_COLD_START_WAIT		6
-#define RES4349_RSVD_7				7
-#define RES4349_LNLDO_PU			8
-#define RES4349_XTALLDO_PU			9
-#define RES4349_LDO3P3_PU			10
-#define RES4349_OTP_PU				11
-#define RES4349_XTAL_PU				12
-#define RES4349_SR_CLK_START		13
-#define RES4349_LQ_AVAIL			14
-#define RES4349_LQ_START			15
-#define RES4349_PERST_OVR			16
-#define RES4349_WL_CORE_RDY			17
-#define RES4349_ILP_REQ				18
-#define RES4349_ALP_AVAIL			19
-#define RES4349_MINI_PMU			20
-#define RES4349_RADIO_PU			21
-#define RES4349_SR_CLK_STABLE		22
-#define RES4349_SR_SAVE_RESTORE		23
-#define RES4349_SR_PHY_PWRSW		24
-#define RES4349_SR_VDDM_PWRSW		25
-#define RES4349_SR_SUBCORE_PWRSW	26
-#define RES4349_SR_SLEEP			27
-#define RES4349_HT_START			28
-#define RES4349_HT_AVAIL			29
-#define RES4349_MACPHY_CLKAVAIL		30
-
-#define CR4_4349_RAM_BASE			(0x180000)
-#define CR4_4349_RAM_BASE_FROM_REV_9		(0x160000)
-
-/* SR binary offset is at 8K */
-#define CC_SR1_4349_SR_ASM_ADDR		(0x10)
-
-#define CST4349_CHIPMODE_SDIOD(cs)	(((cs) & (1 << 6)) != 0)	/* SDIO */
-#define CST4349_CHIPMODE_PCIE(cs)	(((cs) & (1 << 7)) != 0)	/* PCIE */
-
-#define CST4349_SPROM_PRESENT		0x00000010
-
-#define CC2_4349_VDDM_PWRSW_EN_MASK		(1 << 20)
-#define CC2_4349_VDDM_PWRSW_EN_SHIFT		(20)
-#define CC2_4349_SDIO_AOS_WAKEUP_MASK		(1 << 24)
-#define CC2_4349_SDIO_AOS_WAKEUP_SHIFT		(24)
-
-
-#define CC6_4349_PCIE_CLKREQ_WAKEUP_MASK	(1 << 4)
-#define CC6_4349_PCIE_CLKREQ_WAKEUP_SHIFT	(4)
-#define CC6_4349_PMU_WAKEUP_ALPAVAIL_MASK	(1 << 6)
-#define CC6_4349_PMU_WAKEUP_ALPAVAIL_SHIFT	(6)
-#define CC6_4349_PMU_EN_EXT_PERST_MASK		(1 << 13)
-#define CC6_4349_PMU_ENABLE_L2REFCLKPAD_PWRDWN	(1 << 15)
-#define CC6_4349_PMU_EN_MDIO_MASK		(1 << 16)
-#define CC6_4349_PMU_EN_ASSERT_L2_MASK		(1 << 25)
-
-
-
-/* 43430 PMU resources based on pmu_params.xls */
-#define RES43430_LPLDO_PU				0
-#define RES43430_BG_PU					1
-#define RES43430_PMU_SLEEP				2
-#define RES43430_RSVD_3					3
-#define RES43430_CBUCK_LPOM_PU			4
-#define RES43430_CBUCK_PFM_PU			5
-#define RES43430_COLD_START_WAIT		6
-#define RES43430_RSVD_7					7
-#define RES43430_LNLDO_PU				8
-#define RES43430_RSVD_9					9
-#define RES43430_LDO3P3_PU				10
-#define RES43430_OTP_PU					11
-#define RES43430_XTAL_PU				12
-#define RES43430_SR_CLK_START			13
-#define RES43430_LQ_AVAIL				14
-#define RES43430_LQ_START				15
-#define RES43430_RSVD_16				16
-#define RES43430_WL_CORE_RDY			17
-#define RES43430_ILP_REQ				18
-#define RES43430_ALP_AVAIL				19
-#define RES43430_MINI_PMU				20
-#define RES43430_RADIO_PU				21
-#define RES43430_SR_CLK_STABLE			22
-#define RES43430_SR_SAVE_RESTORE		23
-#define RES43430_SR_PHY_PWRSW			24
-#define RES43430_SR_VDDM_PWRSW			25
-#define RES43430_SR_SUBCORE_PWRSW		26
-#define RES43430_SR_SLEEP				27
-#define RES43430_HT_START				28
-#define RES43430_HT_AVAIL				29
-#define RES43430_MACPHY_CLK_AVAIL		30
-
-/* 43430 chip status bits */
-#define CST43430_SDIO_MODE				0x00000001
-#define CST43430_GSPI_MODE				0x00000002
-#define CST43430_RSRC_INIT_MODE_0		0x00000080
-#define CST43430_RSRC_INIT_MODE_1		0x00000100
-#define CST43430_SEL0_SDIO				0x00000200
-#define CST43430_SEL1_SDIO				0x00000400
-#define CST43430_SEL2_SDIO				0x00000800
-#define CST43430_BBPLL_LOCKED			0x00001000
-#define CST43430_DBG_INST_DETECT		0x00004000
-#define CST43430_CLB2WL_BT_READY		0x00020000
-#define CST43430_JTAG_MODE				0x00100000
-#define CST43430_HOST_IFACE				0x00400000
-#define CST43430_TRIM_EN				0x00800000
-#define CST43430_DIN_PACKAGE_OPTION		0x10000000
-
-#define PMU_MACCORE_0_RES_REQ_TIMER		0x19000000
-#define PMU_MACCORE_0_RES_REQ_MASK		0x5FF2364F
-
-#define PMU_MACCORE_1_RES_REQ_TIMER		0x19000000
-#define PMU_MACCORE_1_RES_REQ_MASK		0x5FF2364F
-
-/* defines to detect active host interface in use */
-#define CHIP_HOSTIF_PCIEMODE	0x1
-#define CHIP_HOSTIF_USBMODE	0x2
-#define CHIP_HOSTIF_SDIOMODE	0x4
-#define CHIP_HOSTIF_PCIE(sih)	(si_chip_hostif(sih) == CHIP_HOSTIF_PCIEMODE)
-#define CHIP_HOSTIF_USB(sih)	(si_chip_hostif(sih) == CHIP_HOSTIF_USBMODE)
-#define CHIP_HOSTIF_SDIO(sih)	(si_chip_hostif(sih) == CHIP_HOSTIF_SDIOMODE)
-
-/* 4335 resources */
-#define RES4335_LPLDO_PO           0
-#define RES4335_PMU_BG_PU          1
-#define RES4335_PMU_SLEEP          2
-#define RES4335_RSVD_3             3
-#define RES4335_CBUCK_LPOM_PU		4
-#define RES4335_CBUCK_PFM_PU		5
-#define RES4335_RSVD_6             6
-#define RES4335_RSVD_7             7
-#define RES4335_LNLDO_PU           8
-#define RES4335_XTALLDO_PU         9
-#define RES4335_LDO3P3_PU			10
-#define RES4335_OTP_PU				11
-#define RES4335_XTAL_PU				12
-#define RES4335_SR_CLK_START       13
-#define RES4335_LQ_AVAIL			14
-#define RES4335_LQ_START           15
-#define RES4335_RSVD_16            16
-#define RES4335_WL_CORE_RDY        17
-#define RES4335_ILP_REQ				18
-#define RES4335_ALP_AVAIL			19
-#define RES4335_MINI_PMU           20
-#define RES4335_RADIO_PU			21
-#define RES4335_SR_CLK_STABLE		22
-#define RES4335_SR_SAVE_RESTORE		23
-#define RES4335_SR_PHY_PWRSW		24
-#define RES4335_SR_VDDM_PWRSW      25
-#define RES4335_SR_SUBCORE_PWRSW	26
-#define RES4335_SR_SLEEP           27
-#define RES4335_HT_START           28
-#define RES4335_HT_AVAIL			29
-#define RES4335_MACPHY_CLKAVAIL		30
-
-/* 4335 Chip specific ChipStatus register bits */
-#define CST4335_SPROM_MASK			0x00000020
-#define CST4335_SFLASH_MASK			0x00000040
-#define	CST4335_RES_INIT_MODE_SHIFT	7
-#define	CST4335_RES_INIT_MODE_MASK	0x00000180
-#define CST4335_CHIPMODE_MASK		0xF
-#define CST4335_CHIPMODE_SDIOD(cs)	(((cs) & (1 << 0)) != 0)	/* SDIO */
-#define CST4335_CHIPMODE_GSPI(cs)	(((cs) & (1 << 1)) != 0)	/* gSPI */
-#define CST4335_CHIPMODE_USB20D(cs)	(((cs) & (1 << 2)) != 0)	/**< HSIC || USBDA */
-#define CST4335_CHIPMODE_PCIE(cs)	(((cs) & (1 << 3)) != 0)	/* PCIE */
-
-/* 4335 Chip specific ChipControl1 register bits */
-#define CCTRL1_4335_GPIO_SEL		(1 << 0)    /* 1=select GPIOs to be muxed out */
-#define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2)  /* SDIO: 1=configure GPIO0 for host wake */
-
-/* 4335 Chip specific ChipControl2 register bits */
-#define CCTRL2_4335_AOSBLOCK		(1 << 30)
-#define CCTRL2_4335_PMUWAKE		(1 << 31)
-#define PATCHTBL_SIZE			(0x800)
-#define CR4_4335_RAM_BASE                    (0x180000)
-#define CR4_4345_LT_C0_RAM_BASE              (0x1b0000)
-#define CR4_4345_GE_C0_RAM_BASE              (0x198000)
-#define CR4_4349_RAM_BASE                    (0x180000)
-#define CR4_4350_RAM_BASE                    (0x180000)
-#define CR4_4360_RAM_BASE                    (0x0)
-#define CR4_43602_RAM_BASE                   (0x180000)
-#define CA7_4365_RAM_BASE                    (0x200000)
-
-
-/* 4335 chip OTP present & OTP select bits. */
-#define SPROM4335_OTP_SELECT	0x00000010
-#define SPROM4335_OTP_PRESENT	0x00000020
-
-/* 4335 GCI specific bits. */
-#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_PRESENT	(1 << 24)
-#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_TYPE	25
-#define CC4335_GCI_FUNC_SEL_PAD_SDIO	0x00707770
-
-/* SFLASH clkdev specific bits. */
-#define CC4335_SFLASH_CLKDIV_MASK	0x1F000000
-#define CC4335_SFLASH_CLKDIV_SHIFT	25
-
-/* 4335 OTP bits for SFLASH. */
-#define CC4335_SROM_OTP_SFLASH	40
-#define CC4335_SROM_OTP_SFLASH_PRESENT	0x1
-#define CC4335_SROM_OTP_SFLASH_TYPE	0x2
-#define CC4335_SROM_OTP_SFLASH_CLKDIV_MASK	0x003C
-#define CC4335_SROM_OTP_SFLASH_CLKDIV_SHIFT	2
-
-
-/* 4335 chip OTP present & OTP select bits. */
-#define SPROM4335_OTP_SELECT	0x00000010
-#define SPROM4335_OTP_PRESENT	0x00000020
-
-/* 4335 GCI specific bits. */
-#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_PRESENT	(1 << 24)
-#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_TYPE	25
-#define CC4335_GCI_FUNC_SEL_PAD_SDIO	0x00707770
-
-/* SFLASH clkdev specific bits. */
-#define CC4335_SFLASH_CLKDIV_MASK	0x1F000000
-#define CC4335_SFLASH_CLKDIV_SHIFT	25
-
-/* 4335 OTP bits for SFLASH. */
-#define CC4335_SROM_OTP_SFLASH	40
-#define CC4335_SROM_OTP_SFLASH_PRESENT	0x1
-#define CC4335_SROM_OTP_SFLASH_TYPE	0x2
-#define CC4335_SROM_OTP_SFLASH_CLKDIV_MASK	0x003C
-#define CC4335_SROM_OTP_SFLASH_CLKDIV_SHIFT	2
-
-/* 4335 resources--END */
-
-/* 4345 Chip specific ChipStatus register bits */
-#define CST4345_SPROM_MASK		0x00000020
-#define CST4345_SFLASH_MASK		0x00000040
-#define CST4345_RES_INIT_MODE_SHIFT	7
-#define CST4345_RES_INIT_MODE_MASK	0x00000180
-#define CST4345_CHIPMODE_MASK		0x4000F
-#define CST4345_CHIPMODE_SDIOD(cs)	(((cs) & (1 << 0)) != 0)	/* SDIO */
-#define CST4345_CHIPMODE_GSPI(cs)	(((cs) & (1 << 1)) != 0)	/* gSPI */
-#define CST4345_CHIPMODE_HSIC(cs)	(((cs) & (1 << 2)) != 0)	/* HSIC */
-#define CST4345_CHIPMODE_PCIE(cs)	(((cs) & (1 << 3)) != 0)	/* PCIE */
-#define CST4345_CHIPMODE_USB20D(cs)	(((cs) & (1 << 18)) != 0)	/* USBDA */
-
-/* 4350 Chipcommon ChipStatus bits */
-#define CST4350_SDIO_MODE		0x00000001
-#define CST4350_HSIC20D_MODE		0x00000002
-#define CST4350_BP_ON_HSIC_CLK		0x00000004
-#define CST4350_PCIE_MODE		0x00000008
-#define CST4350_USB20D_MODE		0x00000010
-#define CST4350_USB30D_MODE		0x00000020
-#define CST4350_SPROM_PRESENT		0x00000040
-#define CST4350_RSRC_INIT_MODE_0	0x00000080
-#define CST4350_RSRC_INIT_MODE_1	0x00000100
-#define CST4350_SEL0_SDIO		0x00000200
-#define CST4350_SEL1_SDIO		0x00000400
-#define CST4350_SDIO_PAD_MODE		0x00000800
-#define CST4350_BBPLL_LOCKED		0x00001000
-#define CST4350_USBPLL_LOCKED		0x00002000
-#define CST4350_LINE_STATE		0x0000C000
-#define CST4350_SERDES_PIPE_PLLLOCK	0x00010000
-#define CST4350_BT_READY		0x00020000
-#define CST4350_SFLASH_PRESENT		0x00040000
-#define CST4350_CPULESS_ENABLE		0x00080000
-#define CST4350_STRAP_HOST_IFC_1	0x00100000
-#define CST4350_STRAP_HOST_IFC_2	0x00200000
-#define CST4350_STRAP_HOST_IFC_3	0x00400000
-#define CST4350_RAW_SPROM_PRESENT	0x00800000
-#define CST4350_APP_CLK_SWITCH_SEL_RDBACK	0x01000000
-#define CST4350_RAW_RSRC_INIT_MODE_0	0x02000000
-#define CST4350_SDIO_PAD_VDDIO		0x04000000
-#define CST4350_GSPI_MODE		0x08000000
-#define CST4350_PACKAGE_OPTION		0xF0000000
-#define CST4350_PACKAGE_SHIFT		28
-
-/* package option for 4350 */
-#define CST4350_PACKAGE_WLCSP		0x0
-#define CST4350_PACKAGE_PCIE		0x1
-#define CST4350_PACKAGE_WLBGA		0x2
-#define CST4350_PACKAGE_DBG		0x3
-#define CST4350_PACKAGE_USB		0x4
-#define CST4350_PACKAGE_USB_HSIC	0x4
-
-#define CST4350_PKG_MODE(cs)	((cs & CST4350_PACKAGE_OPTION) >> CST4350_PACKAGE_SHIFT)
-
-#define CST4350_PKG_WLCSP(cs)		(CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_WLCSP))
-#define CST4350_PKG_PCIE(cs)		(CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_PCIE))
-#define CST4350_PKG_WLBGA(cs)		(CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_WLBGA))
-#define CST4350_PKG_USB(cs)		(CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_USB))
-#define CST4350_PKG_USB_HSIC(cs)	(CST4350_PKG_MODE(cs) == (CST4350_PACKAGE_USB_HSIC))
-
-/* 4350C0 USB PACKAGE using raw_sprom_present to indicate 40mHz xtal */
-#define CST4350_PKG_USB_40M(cs)		(cs & CST4350_RAW_SPROM_PRESENT)
-
-#define CST4350_CHIPMODE_SDIOD(cs)	(CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_SDIOD))
-#define CST4350_CHIPMODE_USB20D(cs)	((CST4350_IFC_MODE(cs)) == (CST4350_IFC_MODE_USB20D))
-#define CST4350_CHIPMODE_HSIC20D(cs)	(CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC20D))
-#define CST4350_CHIPMODE_HSIC30D(cs)	(CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC30D))
-#define CST4350_CHIPMODE_USB30D(cs)	(CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D))
-#define CST4350_CHIPMODE_USB30D_WL(cs)	(CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D_WL))
-#define CST4350_CHIPMODE_PCIE(cs)	(CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_PCIE))
-
-/* strap_host_ifc strap value */
-#define CST4350_HOST_IFC_MASK		0x00700000
-#define CST4350_HOST_IFC_SHIFT		20
-
-/* host_ifc raw mode */
-#define CST4350_IFC_MODE_SDIOD			0x0
-#define CST4350_IFC_MODE_HSIC20D		0x1
-#define CST4350_IFC_MODE_HSIC30D		0x2
-#define CST4350_IFC_MODE_PCIE			0x3
-#define CST4350_IFC_MODE_USB20D			0x4
-#define CST4350_IFC_MODE_USB30D			0x5
-#define CST4350_IFC_MODE_USB30D_WL		0x6
-#define CST4350_IFC_MODE_USB30D_BT		0x7
-
-#define CST4350_IFC_MODE(cs)	((cs & CST4350_HOST_IFC_MASK) >> CST4350_HOST_IFC_SHIFT)
-
-/* 4350 PMU resources */
-#define RES4350_LPLDO_PU	0
-#define RES4350_PMU_BG_PU	1
-#define RES4350_PMU_SLEEP	2
-#define RES4350_RSVD_3		3
-#define RES4350_CBUCK_LPOM_PU	4
-#define RES4350_CBUCK_PFM_PU	5
-#define RES4350_COLD_START_WAIT	6
-#define RES4350_RSVD_7		7
-#define RES4350_LNLDO_PU	8
-#define RES4350_XTALLDO_PU	9
-#define RES4350_LDO3P3_PU	10
-#define RES4350_OTP_PU		11
-#define RES4350_XTAL_PU		12
-#define RES4350_SR_CLK_START	13
-#define RES4350_LQ_AVAIL	14
-#define RES4350_LQ_START	15
-#define RES4350_PERST_OVR	16
-#define RES4350_WL_CORE_RDY	17
-#define RES4350_ILP_REQ		18
-#define RES4350_ALP_AVAIL	19
-#define RES4350_MINI_PMU	20
-#define RES4350_RADIO_PU	21
-#define RES4350_SR_CLK_STABLE	22
-#define RES4350_SR_SAVE_RESTORE	23
-#define RES4350_SR_PHY_PWRSW	24
-#define RES4350_SR_VDDM_PWRSW	25
-#define RES4350_SR_SUBCORE_PWRSW	26
-#define RES4350_SR_SLEEP	27
-#define RES4350_HT_START	28
-#define RES4350_HT_AVAIL	29
-#define RES4350_MACPHY_CLKAVAIL	30
-
-#define MUXENAB4350_UART_MASK		(0x0000000f)
-#define MUXENAB4350_UART_SHIFT		0
-#define MUXENAB4350_HOSTWAKE_MASK	(0x000000f0)	/**< configure GPIO for SDIO host_wake */
-#define MUXENAB4350_HOSTWAKE_SHIFT	4
-
-
-/* 4350 GCI function sel values */
-#define CC4350_FNSEL_HWDEF		(0)
-#define CC4350_FNSEL_SAMEASPIN		(1)
-#define CC4350_FNSEL_UART		(2)
-#define CC4350_FNSEL_SFLASH		(3)
-#define CC4350_FNSEL_SPROM		(4)
-#define CC4350_FNSEL_I2C		(5)
-#define CC4350_FNSEL_MISC0		(6)
-#define CC4350_FNSEL_GCI		(7)
-#define CC4350_FNSEL_MISC1		(8)
-#define CC4350_FNSEL_MISC2		(9)
-#define CC4350_FNSEL_PWDOG 		(10)
-#define CC4350_FNSEL_IND		(12)
-#define CC4350_FNSEL_PDN		(13)
-#define CC4350_FNSEL_PUP		(14)
-#define CC4350_FNSEL_TRISTATE		(15)
-#define CC4350C_FNSEL_UART		(3)
-
-
-/* 4350 GPIO */
-#define CC4350_PIN_GPIO_00		(0)
-#define CC4350_PIN_GPIO_01		(1)
-#define CC4350_PIN_GPIO_02		(2)
-#define CC4350_PIN_GPIO_03		(3)
-#define CC4350_PIN_GPIO_04		(4)
-#define CC4350_PIN_GPIO_05		(5)
-#define CC4350_PIN_GPIO_06		(6)
-#define CC4350_PIN_GPIO_07		(7)
-#define CC4350_PIN_GPIO_08		(8)
-#define CC4350_PIN_GPIO_09		(9)
-#define CC4350_PIN_GPIO_10		(10)
-#define CC4350_PIN_GPIO_11		(11)
-#define CC4350_PIN_GPIO_12		(12)
-#define CC4350_PIN_GPIO_13		(13)
-#define CC4350_PIN_GPIO_14		(14)
-#define CC4350_PIN_GPIO_15		(15)
-
-#define CC4350_RSVD_16_SHIFT		16
-
-#define CC2_4350_PHY_PWRSW_UPTIME_MASK		(0xf << 0)
-#define CC2_4350_PHY_PWRSW_UPTIME_SHIFT		(0)
-#define CC2_4350_VDDM_PWRSW_UPDELAY_MASK	(0xf << 4)
-#define CC2_4350_VDDM_PWRSW_UPDELAY_SHIFT	(4)
-#define CC2_4350_VDDM_PWRSW_UPTIME_MASK		(0xf << 8)
-#define CC2_4350_VDDM_PWRSW_UPTIME_SHIFT	(8)
-#define CC2_4350_SBC_PWRSW_DNDELAY_MASK		(0x3 << 12)
-#define CC2_4350_SBC_PWRSW_DNDELAY_SHIFT	(12)
-#define CC2_4350_PHY_PWRSW_DNDELAY_MASK		(0x3 << 14)
-#define CC2_4350_PHY_PWRSW_DNDELAY_SHIFT	(14)
-#define CC2_4350_VDDM_PWRSW_DNDELAY_MASK	(0x3 << 16)
-#define CC2_4350_VDDM_PWRSW_DNDELAY_SHIFT	(16)
-#define CC2_4350_VDDM_PWRSW_EN_MASK		(1 << 20)
-#define CC2_4350_VDDM_PWRSW_EN_SHIFT		(20)
-#define CC2_4350_MEMLPLDO_PWRSW_EN_MASK		(1 << 21)
-#define CC2_4350_MEMLPLDO_PWRSW_EN_SHIFT	(21)
-#define CC2_4350_SDIO_AOS_WAKEUP_MASK		(1 << 24)
-#define CC2_4350_SDIO_AOS_WAKEUP_SHIFT		(24)
-
-/* Applies to 4335/4350/4345 */
-#define CC3_SR_CLK_SR_MEM_MASK			(1 << 0)
-#define CC3_SR_CLK_SR_MEM_SHIFT			(0)
-#define CC3_SR_BIT1_TBD_MASK			(1 << 1)
-#define CC3_SR_BIT1_TBD_SHIFT			(1)
-#define CC3_SR_ENGINE_ENABLE_MASK		(1 << 2)
-#define CC3_SR_ENGINE_ENABLE_SHIFT		(2)
-#define CC3_SR_BIT3_TBD_MASK			(1 << 3)
-#define CC3_SR_BIT3_TBD_SHIFT			(3)
-#define CC3_SR_MINDIV_FAST_CLK_MASK		(0xF << 4)
-#define CC3_SR_MINDIV_FAST_CLK_SHIFT		(4)
-#define CC3_SR_R23_SR2_RISE_EDGE_TRIG_MASK	(1 << 8)
-#define CC3_SR_R23_SR2_RISE_EDGE_TRIG_SHIFT	(8)
-#define CC3_SR_R23_SR2_FALL_EDGE_TRIG_MASK	(1 << 9)
-#define CC3_SR_R23_SR2_FALL_EDGE_TRIG_SHIFT	(9)
-#define CC3_SR_R23_SR_RISE_EDGE_TRIG_MASK	(1 << 10)
-#define CC3_SR_R23_SR_RISE_EDGE_TRIG_SHIFT	(10)
-#define CC3_SR_R23_SR_FALL_EDGE_TRIG_MASK	(1 << 11)
-#define CC3_SR_R23_SR_FALL_EDGE_TRIG_SHIFT	(11)
-#define CC3_SR_NUM_CLK_HIGH_MASK		(0x7 << 12)
-#define CC3_SR_NUM_CLK_HIGH_SHIFT		(12)
-#define CC3_SR_BIT15_TBD_MASK			(1 << 15)
-#define CC3_SR_BIT15_TBD_SHIFT			(15)
-#define CC3_SR_PHY_FUNC_PIC_MASK		(1 << 16)
-#define CC3_SR_PHY_FUNC_PIC_SHIFT		(16)
-#define CC3_SR_BIT17_19_TBD_MASK		(0x7 << 17)
-#define CC3_SR_BIT17_19_TBD_SHIFT		(17)
-#define CC3_SR_CHIP_TRIGGER_1_MASK		(1 << 20)
-#define CC3_SR_CHIP_TRIGGER_1_SHIFT		(20)
-#define CC3_SR_CHIP_TRIGGER_2_MASK		(1 << 21)
-#define CC3_SR_CHIP_TRIGGER_2_SHIFT		(21)
-#define CC3_SR_CHIP_TRIGGER_3_MASK		(1 << 22)
-#define CC3_SR_CHIP_TRIGGER_3_SHIFT		(22)
-#define CC3_SR_CHIP_TRIGGER_4_MASK		(1 << 23)
-#define CC3_SR_CHIP_TRIGGER_4_SHIFT		(23)
-#define CC3_SR_ALLOW_SBC_FUNC_PIC_MASK		(1 << 24)
-#define CC3_SR_ALLOW_SBC_FUNC_PIC_SHIFT		(24)
-#define CC3_SR_BIT25_26_TBD_MASK		(0x3 << 25)
-#define CC3_SR_BIT25_26_TBD_SHIFT		(25)
-#define CC3_SR_ALLOW_SBC_STBY_MASK		(1 << 27)
-#define CC3_SR_ALLOW_SBC_STBY_SHIFT		(27)
-#define CC3_SR_GPIO_MUX_MASK			(0xF << 28)
-#define CC3_SR_GPIO_MUX_SHIFT			(28)
-
-/* Applies to 4335/4350/4345 */
-#define CC4_SR_INIT_ADDR_MASK		(0x3FF0000)
-#define 	CC4_4350_SR_ASM_ADDR	(0x30)
-#define CC4_4350_C0_SR_ASM_ADDR		(0x0)
-#define 	CC4_4335_SR_ASM_ADDR	(0x48)
-#define 	CC4_4345_SR_ASM_ADDR	(0x48)
-#define CC4_SR_INIT_ADDR_SHIFT		(16)
-
-#define CC4_4350_EN_SR_CLK_ALP_MASK	(1 << 30)
-#define CC4_4350_EN_SR_CLK_ALP_SHIFT	(30)
-#define CC4_4350_EN_SR_CLK_HT_MASK	(1 << 31)
-#define CC4_4350_EN_SR_CLK_HT_SHIFT	(31)
-
-#define VREG4_4350_MEMLPDO_PU_MASK	(1 << 31)
-#define VREG4_4350_MEMLPDO_PU_SHIFT	31
-
-#define VREG6_4350_SR_EXT_CLKDIR_MASK	(1 << 20)
-#define VREG6_4350_SR_EXT_CLKDIR_SHIFT	20
-#define VREG6_4350_SR_EXT_CLKDIV_MASK	(0x3 << 21)
-#define VREG6_4350_SR_EXT_CLKDIV_SHIFT	21
-#define VREG6_4350_SR_EXT_CLKEN_MASK	(1 << 23)
-#define VREG6_4350_SR_EXT_CLKEN_SHIFT	23
-
-#define CC5_4350_PMU_EN_ASSERT_MASK	(1 << 13)
-#define CC5_4350_PMU_EN_ASSERT_SHIFT	(13)
-
-#define CC6_4350_PCIE_CLKREQ_WAKEUP_MASK	(1 << 4)
-#define CC6_4350_PCIE_CLKREQ_WAKEUP_SHIFT	(4)
-#define CC6_4350_PMU_WAKEUP_ALPAVAIL_MASK	(1 << 6)
-#define CC6_4350_PMU_WAKEUP_ALPAVAIL_SHIFT	(6)
-#define CC6_4350_PMU_EN_EXT_PERST_MASK		(1 << 17)
-#define CC6_4350_PMU_EN_EXT_PERST_SHIFT		(17)
-#define CC6_4350_PMU_EN_WAKEUP_MASK		(1 << 18)
-#define CC6_4350_PMU_EN_WAKEUP_SHIFT		(18)
-
-#define CC7_4350_PMU_EN_ASSERT_L2_MASK	(1 << 26)
-#define CC7_4350_PMU_EN_ASSERT_L2_SHIFT	(26)
-#define CC7_4350_PMU_EN_MDIO_MASK	(1 << 27)
-#define CC7_4350_PMU_EN_MDIO_SHIFT	(27)
-
-#define CC6_4345_PMU_EN_PERST_DEASSERT_MASK		(1 << 13)
-#define CC6_4345_PMU_EN_PERST_DEASSERT_SHIF		(13)
-#define CC6_4345_PMU_EN_L2_DEASSERT_MASK		(1 << 14)
-#define CC6_4345_PMU_EN_L2_DEASSERT_SHIF		(14)
-#define CC6_4345_PMU_EN_ASSERT_L2_MASK		(1 << 15)
-#define CC6_4345_PMU_EN_ASSERT_L2_SHIFT		(15)
-#define CC6_4345_PMU_EN_MDIO_MASK		(1 << 24)
-#define CC6_4345_PMU_EN_MDIO_SHIFT		(24)
-
-/* GCI chipcontrol register indices */
-#define CC_GCI_CHIPCTRL_00	(0)
-#define CC_GCI_CHIPCTRL_01	(1)
-#define CC_GCI_CHIPCTRL_02	(2)
-#define CC_GCI_CHIPCTRL_03	(3)
-#define CC_GCI_CHIPCTRL_04	(4)
-#define CC_GCI_CHIPCTRL_05	(5)
-#define CC_GCI_CHIPCTRL_06	(6)
-#define CC_GCI_CHIPCTRL_07	(7)
-#define CC_GCI_CHIPCTRL_08	(8)
-#define CC_GCI_CHIPCTRL_11	(11)
-#define CC_GCI_XTAL_BUFSTRG_NFC (0xff << 12)
-
-#define CC_GCI_06_JTAG_SEL_SHIFT	4
-#define CC_GCI_06_JTAG_SEL_MASK		(1 << 4)
-
-#define CC_GCI_NUMCHIPCTRLREGS(cap1)	((cap1 & 0xF00) >> 8)
-
-/* 4345 PMU resources */
-#define RES4345_LPLDO_PU		0
-#define RES4345_PMU_BG_PU		1
-#define RES4345_PMU_SLEEP 		2
-#define RES4345_HSICLDO_PU		3
-#define RES4345_CBUCK_LPOM_PU		4
-#define RES4345_CBUCK_PFM_PU		5
-#define RES4345_COLD_START_WAIT		6
-#define RES4345_RSVD_7			7
-#define RES4345_LNLDO_PU		8
-#define RES4345_XTALLDO_PU		9
-#define RES4345_LDO3P3_PU		10
-#define RES4345_OTP_PU			11
-#define RES4345_XTAL_PU			12
-#define RES4345_SR_CLK_START		13
-#define RES4345_LQ_AVAIL		14
-#define RES4345_LQ_START		15
-#define RES4345_PERST_OVR		16
-#define RES4345_WL_CORE_RDY		17
-#define RES4345_ILP_REQ			18
-#define RES4345_ALP_AVAIL		19
-#define RES4345_MINI_PMU		20
-#define RES4345_RADIO_PU		21
-#define RES4345_SR_CLK_STABLE		22
-#define RES4345_SR_SAVE_RESTORE		23
-#define RES4345_SR_PHY_PWRSW		24
-#define RES4345_SR_VDDM_PWRSW		25
-#define RES4345_SR_SUBCORE_PWRSW	26
-#define RES4345_SR_SLEEP		27
-#define RES4345_HT_START		28
-#define RES4345_HT_AVAIL		29
-#define RES4345_MACPHY_CLK_AVAIL	30
-
-/* 4335 pins
-* note: only the values set as default/used are added here.
-*/
-#define CC4335_PIN_GPIO_00		(0)
-#define CC4335_PIN_GPIO_01		(1)
-#define CC4335_PIN_GPIO_02		(2)
-#define CC4335_PIN_GPIO_03		(3)
-#define CC4335_PIN_GPIO_04		(4)
-#define CC4335_PIN_GPIO_05		(5)
-#define CC4335_PIN_GPIO_06		(6)
-#define CC4335_PIN_GPIO_07		(7)
-#define CC4335_PIN_GPIO_08		(8)
-#define CC4335_PIN_GPIO_09		(9)
-#define CC4335_PIN_GPIO_10		(10)
-#define CC4335_PIN_GPIO_11		(11)
-#define CC4335_PIN_GPIO_12		(12)
-#define CC4335_PIN_GPIO_13		(13)
-#define CC4335_PIN_GPIO_14		(14)
-#define CC4335_PIN_GPIO_15		(15)
-#define CC4335_PIN_SDIO_CLK		(16)
-#define CC4335_PIN_SDIO_CMD		(17)
-#define CC4335_PIN_SDIO_DATA0	(18)
-#define CC4335_PIN_SDIO_DATA1	(19)
-#define CC4335_PIN_SDIO_DATA2	(20)
-#define CC4335_PIN_SDIO_DATA3	(21)
-#define CC4335_PIN_RF_SW_CTRL_6	(22)
-#define CC4335_PIN_RF_SW_CTRL_7	(23)
-#define CC4335_PIN_RF_SW_CTRL_8	(24)
-#define CC4335_PIN_RF_SW_CTRL_9	(25)
-/* Last GPIO Pad */
-#define CC4335_PIN_GPIO_LAST	(31)
-
-/* 4335 GCI function sel values
-*/
-#define CC4335_FNSEL_HWDEF		(0)
-#define CC4335_FNSEL_SAMEASPIN	(1)
-#define CC4335_FNSEL_GPIO0		(2)
-#define CC4335_FNSEL_GPIO1		(3)
-#define CC4335_FNSEL_GCI0		(4)
-#define CC4335_FNSEL_GCI1		(5)
-#define CC4335_FNSEL_UART		(6)
-#define CC4335_FNSEL_SFLASH		(7)
-#define CC4335_FNSEL_SPROM		(8)
-#define CC4335_FNSEL_MISC0		(9)
-#define CC4335_FNSEL_MISC1		(10)
-#define CC4335_FNSEL_MISC2		(11)
-#define CC4335_FNSEL_IND		(12)
-#define CC4335_FNSEL_PDN		(13)
-#define CC4335_FNSEL_PUP		(14)
-#define CC4335_FNSEL_TRI		(15)
-
-/* GCI Core Control Reg */
-#define	GCI_CORECTRL_SR_MASK	(1 << 0)	/**< SECI block Reset */
-#define	GCI_CORECTRL_RSL_MASK	(1 << 1)	/**< ResetSECILogic */
-#define	GCI_CORECTRL_ES_MASK	(1 << 2)	/**< EnableSECI */
-#define	GCI_CORECTRL_FSL_MASK	(1 << 3)	/**< Force SECI Out Low */
-#define	GCI_CORECTRL_SOM_MASK	(7 << 4)	/**< SECI Op Mode */
-#define	GCI_CORECTRL_US_MASK	(1 << 7)	/**< Update SECI */
-#define	GCI_CORECTRL_BOS_MASK	(1 << 8)	/**< Break On Sleep */
-
-/* 4345 pins
-* note: only the values set as default/used are added here.
-*/
-#define CC4345_PIN_GPIO_00		(0)
-#define CC4345_PIN_GPIO_01		(1)
-#define CC4345_PIN_GPIO_02		(2)
-#define CC4345_PIN_GPIO_03		(3)
-#define CC4345_PIN_GPIO_04		(4)
-#define CC4345_PIN_GPIO_05		(5)
-#define CC4345_PIN_GPIO_06		(6)
-#define CC4345_PIN_GPIO_07		(7)
-#define CC4345_PIN_GPIO_08		(8)
-#define CC4345_PIN_GPIO_09		(9)
-#define CC4345_PIN_GPIO_10		(10)
-#define CC4345_PIN_GPIO_11		(11)
-#define CC4345_PIN_GPIO_12		(12)
-#define CC4345_PIN_GPIO_13		(13)
-#define CC4345_PIN_GPIO_14		(14)
-#define CC4345_PIN_GPIO_15		(15)
-#define CC4345_PIN_GPIO_16		(16)
-#define CC4345_PIN_SDIO_CLK		(17)
-#define CC4345_PIN_SDIO_CMD		(18)
-#define CC4345_PIN_SDIO_DATA0	(19)
-#define CC4345_PIN_SDIO_DATA1	(20)
-#define CC4345_PIN_SDIO_DATA2	(21)
-#define CC4345_PIN_SDIO_DATA3	(22)
-#define CC4345_PIN_RF_SW_CTRL_0	(23)
-#define CC4345_PIN_RF_SW_CTRL_1	(24)
-#define CC4345_PIN_RF_SW_CTRL_2	(25)
-#define CC4345_PIN_RF_SW_CTRL_3	(26)
-#define CC4345_PIN_RF_SW_CTRL_4	(27)
-#define CC4345_PIN_RF_SW_CTRL_5	(28)
-#define CC4345_PIN_RF_SW_CTRL_6	(29)
-#define CC4345_PIN_RF_SW_CTRL_7	(30)
-#define CC4345_PIN_RF_SW_CTRL_8	(31)
-#define CC4345_PIN_RF_SW_CTRL_9	(32)
-
-/* 4345 GCI function sel values
-*/
-#define CC4345_FNSEL_HWDEF		(0)
-#define CC4345_FNSEL_SAMEASPIN		(1)
-#define CC4345_FNSEL_GPIO0		(2)
-#define CC4345_FNSEL_GPIO1		(3)
-#define CC4345_FNSEL_GCI0		(4)
-#define CC4345_FNSEL_GCI1		(5)
-#define CC4345_FNSEL_UART		(6)
-#define CC4345_FNSEL_SFLASH		(7)
-#define CC4345_FNSEL_SPROM		(8)
-#define CC4345_FNSEL_MISC0		(9)
-#define CC4345_FNSEL_MISC1		(10)
-#define CC4345_FNSEL_MISC2		(11)
-#define CC4345_FNSEL_IND		(12)
-#define CC4345_FNSEL_PDN		(13)
-#define CC4345_FNSEL_PUP		(14)
-#define CC4345_FNSEL_TRI		(15)
-
-#define MUXENAB4345_UART_MASK		(0x0000000f)
-#define MUXENAB4345_UART_SHIFT		0
-#define MUXENAB4345_HOSTWAKE_MASK	(0x000000f0)
-#define MUXENAB4345_HOSTWAKE_SHIFT	4
-
-/* 4349 Group (4349, 4355, 4359) GCI AVS function sel values */
-#define CC4349_GRP_GCI_AVS_CTRL_MASK   (0xffe00000)
-#define CC4349_GRP_GCI_AVS_CTRL_SHIFT  (21)
-#define CC4349_GRP_GCI_AVS_CTRL_ENAB   (1 << 5)
-
-/* 4345 GCI AVS function sel values */
-#define CC4345_GCI_AVS_CTRL_MASK   (0xfc)
-#define CC4345_GCI_AVS_CTRL_SHIFT  (2)
-#define CC4345_GCI_AVS_CTRL_ENAB   (1 << 5)
-
-/* GCI GPIO for function sel GCI-0/GCI-1 */
-#define CC_GCI_GPIO_0			(0)
-#define CC_GCI_GPIO_1			(1)
-#define CC_GCI_GPIO_2			(2)
-#define CC_GCI_GPIO_3			(3)
-#define CC_GCI_GPIO_4			(4)
-#define CC_GCI_GPIO_5			(5)
-#define CC_GCI_GPIO_6			(6)
-#define CC_GCI_GPIO_7			(7)
-#define CC_GCI_GPIO_8			(8)
-#define CC_GCI_GPIO_9			(9)
-#define CC_GCI_GPIO_10			(10)
-#define CC_GCI_GPIO_11			(11)
-#define CC_GCI_GPIO_12			(12)
-#define CC_GCI_GPIO_13			(13)
-#define CC_GCI_GPIO_14			(14)
-#define CC_GCI_GPIO_15			(15)
-
-
-/* indicates Invalid GPIO, e.g. when PAD GPIO doesn't map to GCI GPIO */
-#define CC_GCI_GPIO_INVALID		0xFF
-
-/* find the 4 bit mask given the bit position */
-#define GCIMASK(pos)  (((uint32)0xF) << pos)
-/* get the value which can be used to directly OR with chipcontrol reg */
-#define GCIPOSVAL(val, pos)  ((((uint32)val) << pos) & GCIMASK(pos))
-/* Extract nibble from a given position */
-#define GCIGETNBL(val, pos)	((val >> pos) & 0xF)
-
-
-/* find the 8 bit mask given the bit position */
-#define GCIMASK_8B(pos)  (((uint32)0xFF) << pos)
-/* get the value which can be used to directly OR with chipcontrol reg */
-#define GCIPOSVAL_8B(val, pos)  ((((uint32)val) << pos) & GCIMASK_8B(pos))
-/* Extract nibble from a given position */
-#define GCIGETNBL_8B(val, pos)	((val >> pos) & 0xFF)
-
-/* find the 4 bit mask given the bit position */
-#define GCIMASK_4B(pos)  (((uint32)0xF) << pos)
-/* get the value which can be used to directly OR with chipcontrol reg */
-#define GCIPOSVAL_4B(val, pos)  ((((uint32)val) << pos) & GCIMASK_4B(pos))
-/* Extract nibble from a given position */
-#define GCIGETNBL_4B(val, pos)	((val >> pos) & 0xF)
-
-
-/* 4335 GCI Intstatus(Mask)/WakeMask Register bits. */
-#define GCI_INTSTATUS_RBI	(1 << 0)	/**< Rx Break Interrupt */
-#define GCI_INTSTATUS_UB	(1 << 1)	/**< UART Break Interrupt */
-#define GCI_INTSTATUS_SPE	(1 << 2)	/**< SECI Parity Error Interrupt */
-#define GCI_INTSTATUS_SFE	(1 << 3)	/**< SECI Framing Error Interrupt */
-#define GCI_INTSTATUS_SRITI	(1 << 9)	/**< SECI Rx Idle Timer Interrupt */
-#define GCI_INTSTATUS_STFF	(1 << 10)	/**< SECI Tx FIFO Full Interrupt */
-#define GCI_INTSTATUS_STFAE	(1 << 11)	/**< SECI Tx FIFO Almost Empty Intr */
-#define GCI_INTSTATUS_SRFAF	(1 << 12)	/**< SECI Rx FIFO Almost Full */
-#define GCI_INTSTATUS_SRFNE	(1 << 14)	/**< SECI Rx FIFO Not Empty */
-#define GCI_INTSTATUS_SRFOF	(1 << 15)	/**< SECI Rx FIFO Not Empty Timeout */
-#define GCI_INTSTATUS_GPIOINT	(1 << 25)	/**< GCIGpioInt */
-#define GCI_INTSTATUS_GPIOWAKE	(1 << 26)	/**< GCIGpioWake */
-
-/* 4335 GCI IntMask Register bits. */
-#define GCI_INTMASK_RBI		(1 << 0)	/**< Rx Break Interrupt */
-#define GCI_INTMASK_UB		(1 << 1)	/**< UART Break Interrupt */
-#define GCI_INTMASK_SPE		(1 << 2)	/**< SECI Parity Error Interrupt */
-#define GCI_INTMASK_SFE		(1 << 3)	/**< SECI Framing Error Interrupt */
-#define GCI_INTMASK_SRITI	(1 << 9)	/**< SECI Rx Idle Timer Interrupt */
-#define GCI_INTMASK_STFF	(1 << 10)	/**< SECI Tx FIFO Full Interrupt */
-#define GCI_INTMASK_STFAE	(1 << 11)	/**< SECI Tx FIFO Almost Empty Intr */
-#define GCI_INTMASK_SRFAF	(1 << 12)	/**< SECI Rx FIFO Almost Full */
-#define GCI_INTMASK_SRFNE	(1 << 14)	/**< SECI Rx FIFO Not Empty */
-#define GCI_INTMASK_SRFOF	(1 << 15)	/**< SECI Rx FIFO Not Empty Timeout */
-#define GCI_INTMASK_GPIOINT	(1 << 25)	/**< GCIGpioInt */
-#define GCI_INTMASK_GPIOWAKE	(1 << 26)	/**< GCIGpioWake */
-
-/* 4335 GCI WakeMask Register bits. */
-#define GCI_WAKEMASK_RBI	(1 << 0)	/**< Rx Break Interrupt */
-#define GCI_WAKEMASK_UB		(1 << 1)	/**< UART Break Interrupt */
-#define GCI_WAKEMASK_SPE	(1 << 2)	/**< SECI Parity Error Interrupt */
-#define GCI_WAKEMASK_SFE	(1 << 3)	/**< SECI Framing Error Interrupt */
-#define GCI_WAKE_SRITI		(1 << 9)	/**< SECI Rx Idle Timer Interrupt */
-#define GCI_WAKEMASK_STFF	(1 << 10)	/**< SECI Tx FIFO Full Interrupt */
-#define GCI_WAKEMASK_STFAE	(1 << 11)	/**< SECI Tx FIFO Almost Empty Intr */
-#define GCI_WAKEMASK_SRFAF	(1 << 12)	/**< SECI Rx FIFO Almost Full */
-#define GCI_WAKEMASK_SRFNE	(1 << 14)	/**< SECI Rx FIFO Not Empty */
-#define GCI_WAKEMASK_SRFOF	(1 << 15)	/**< SECI Rx FIFO Not Empty Timeout */
-#define GCI_WAKEMASK_GPIOINT	(1 << 25)	/**< GCIGpioInt */
-#define GCI_WAKEMASK_GPIOWAKE	(1 << 26)	/**< GCIGpioWake */
-
-#define	GCI_WAKE_ON_GCI_GPIO1	1
-#define	GCI_WAKE_ON_GCI_GPIO2	2
-#define	GCI_WAKE_ON_GCI_GPIO3	3
-#define	GCI_WAKE_ON_GCI_GPIO4	4
-#define	GCI_WAKE_ON_GCI_GPIO5	5
-#define	GCI_WAKE_ON_GCI_GPIO6	6
-#define	GCI_WAKE_ON_GCI_GPIO7	7
-#define	GCI_WAKE_ON_GCI_GPIO8	8
-#define	GCI_WAKE_ON_GCI_SECI_IN	9
-
-/* 4335 MUX options. each nibble belongs to a setting. Non-zero value specifies a logic
-* for now only UART for bootloader.
-*/
-#define MUXENAB4335_UART_MASK		(0x0000000f)
-
-#define MUXENAB4335_UART_SHIFT		0
-#define MUXENAB4335_HOSTWAKE_MASK	(0x000000f0)	/**< configure GPIO for SDIO host_wake */
-#define MUXENAB4335_HOSTWAKE_SHIFT	4
-#define MUXENAB4335_GETIX(val, name) \
-	((((val) & MUXENAB4335_ ## name ## _MASK) >> MUXENAB4335_ ## name ## _SHIFT) - 1)
-
-/*
-* Maximum delay for the PMU state transition in us.
-* This is an upper bound intended for spinwaits etc.
-*/
-#define PMU_MAX_TRANSITION_DLY	15000
-
-/* PMU resource up transition time in ILP cycles */
-#define PMURES_UP_TRANSITION	2
-
-
-/* SECI configuration */
-#define SECI_MODE_UART			0x0
-#define SECI_MODE_SECI			0x1
-#define SECI_MODE_LEGACY_3WIRE_BT	0x2
-#define SECI_MODE_LEGACY_3WIRE_WLAN	0x3
-#define SECI_MODE_HALF_SECI		0x4
-
-#define SECI_RESET		(1 << 0)
-#define SECI_RESET_BAR_UART	(1 << 1)
-#define SECI_ENAB_SECI_ECI	(1 << 2)
-#define SECI_ENAB_SECIOUT_DIS	(1 << 3)
-#define SECI_MODE_MASK		0x7
-#define SECI_MODE_SHIFT		4 /* (bits 5, 6, 7) */
-#define SECI_UPD_SECI		(1 << 7)
-
-#define SECI_SLIP_ESC_CHAR	0xDB
-#define SECI_SIGNOFF_0		SECI_SLIP_ESC_CHAR
-#define SECI_SIGNOFF_1     0
-#define SECI_REFRESH_REQ	0xDA
-
-/* seci clk_ctl_st bits */
-#define CLKCTL_STS_SECI_CLK_REQ		(1 << 8)
-#define CLKCTL_STS_SECI_CLK_AVAIL	(1 << 24)
-
-#define SECI_UART_MSR_CTS_STATE		(1 << 0)
-#define SECI_UART_MSR_RTS_STATE		(1 << 1)
-#define SECI_UART_SECI_IN_STATE		(1 << 2)
-#define SECI_UART_SECI_IN2_STATE	(1 << 3)
-
-/* GCI RX FIFO Control Register */
-#define	GCI_RXF_LVL_MASK	(0xFF << 0)
-#define	GCI_RXF_TIMEOUT_MASK	(0xFF << 8)
-
-/* GCI UART Registers' Bit definitions */
-/* Seci Fifo Level Register */
-#define	SECI_TXF_LVL_MASK	(0x3F << 8)
-#define	TXF_AE_LVL_DEFAULT	0x4
-#define	SECI_RXF_LVL_FC_MASK	(0x3F << 16)
-
-/* SeciUARTFCR Bit definitions */
-#define	SECI_UART_FCR_RFR		(1 << 0)
-#define	SECI_UART_FCR_TFR		(1 << 1)
-#define	SECI_UART_FCR_SR		(1 << 2)
-#define	SECI_UART_FCR_THP		(1 << 3)
-#define	SECI_UART_FCR_AB		(1 << 4)
-#define	SECI_UART_FCR_ATOE		(1 << 5)
-#define	SECI_UART_FCR_ARTSOE		(1 << 6)
-#define	SECI_UART_FCR_ABV		(1 << 7)
-#define	SECI_UART_FCR_ALM		(1 << 8)
-
-/* SECI UART LCR register bits */
-#define SECI_UART_LCR_STOP_BITS		(1 << 0) /* 0 - 1bit, 1 - 2bits */
-#define SECI_UART_LCR_PARITY_EN		(1 << 1)
-#define SECI_UART_LCR_PARITY		(1 << 2) /* 0 - odd, 1 - even */
-#define SECI_UART_LCR_RX_EN		(1 << 3)
-#define SECI_UART_LCR_LBRK_CTRL		(1 << 4) /* 1 => SECI_OUT held low */
-#define SECI_UART_LCR_TXO_EN		(1 << 5)
-#define SECI_UART_LCR_RTSO_EN		(1 << 6)
-#define SECI_UART_LCR_SLIPMODE_EN	(1 << 7)
-#define SECI_UART_LCR_RXCRC_CHK		(1 << 8)
-#define SECI_UART_LCR_TXCRC_INV		(1 << 9)
-#define SECI_UART_LCR_TXCRC_LSBF	(1 << 10)
-#define SECI_UART_LCR_TXCRC_EN		(1 << 11)
-#define	SECI_UART_LCR_RXSYNC_EN		(1 << 12)
-
-#define SECI_UART_MCR_TX_EN		(1 << 0)
-#define SECI_UART_MCR_PRTS		(1 << 1)
-#define SECI_UART_MCR_SWFLCTRL_EN	(1 << 2)
-#define SECI_UART_MCR_HIGHRATE_EN	(1 << 3)
-#define SECI_UART_MCR_LOOPBK_EN		(1 << 4)
-#define SECI_UART_MCR_AUTO_RTS		(1 << 5)
-#define SECI_UART_MCR_AUTO_TX_DIS	(1 << 6)
-#define SECI_UART_MCR_BAUD_ADJ_EN	(1 << 7)
-#define SECI_UART_MCR_XONOFF_RPT	(1 << 9)
-
-/* SeciUARTLSR Bit Mask */
-#define	SECI_UART_LSR_RXOVR_MASK	(1 << 0)
-#define	SECI_UART_LSR_RFF_MASK		(1 << 1)
-#define	SECI_UART_LSR_TFNE_MASK		(1 << 2)
-#define	SECI_UART_LSR_TI_MASK		(1 << 3)
-#define	SECI_UART_LSR_TPR_MASK		(1 << 4)
-#define	SECI_UART_LSR_TXHALT_MASK	(1 << 5)
-
-/* SeciUARTMSR Bit Mask */
-#define	SECI_UART_MSR_CTSS_MASK		(1 << 0)
-#define	SECI_UART_MSR_RTSS_MASK		(1 << 1)
-#define	SECI_UART_MSR_SIS_MASK		(1 << 2)
-#define	SECI_UART_MSR_SIS2_MASK		(1 << 3)
-
-/* SeciUARTData Bits */
-#define SECI_UART_DATA_RF_NOT_EMPTY_BIT	(1 << 12)
-#define SECI_UART_DATA_RF_FULL_BIT	(1 << 13)
-#define SECI_UART_DATA_RF_OVRFLOW_BIT	(1 << 14)
-#define	SECI_UART_DATA_FIFO_PTR_MASK	0xFF
-#define	SECI_UART_DATA_RF_RD_PTR_SHIFT	16
-#define	SECI_UART_DATA_RF_WR_PTR_SHIFT	24
-
-/* LTECX: ltecxmux */
-#define LTECX_EXTRACT_MUX(val, idx)	(getbit4(&(val), (idx)))
-
-/* LTECX: ltecxmux MODE */
-#define LTECX_MUX_MODE_IDX		0
-#define LTECX_MUX_MODE_WCI2		0x0
-#define LTECX_MUX_MODE_GPIO		0x1
-
-
-/* LTECX GPIO Information Index */
-#define LTECX_NVRAM_FSYNC_IDX	0
-#define LTECX_NVRAM_LTERX_IDX	1
-#define LTECX_NVRAM_LTETX_IDX	2
-#define LTECX_NVRAM_WLPRIO_IDX	3
-
-/* LTECX WCI2 Information Index */
-#define LTECX_NVRAM_WCI2IN_IDX	0
-#define LTECX_NVRAM_WCI2OUT_IDX	1
-
-/* LTECX: Macros to get GPIO/FNSEL/GCIGPIO */
-#define LTECX_EXTRACT_PADNUM(val, idx)	(getbit8(&(val), (idx)))
-#define LTECX_EXTRACT_FNSEL(val, idx)	(getbit4(&(val), (idx)))
-#define LTECX_EXTRACT_GCIGPIO(val, idx)	(getbit4(&(val), (idx)))
-
-/* WLAN channel numbers - used from wifi.h */
-
-/* WLAN BW */
-#define ECI_BW_20   0x0
-#define ECI_BW_25   0x1
-#define ECI_BW_30   0x2
-#define ECI_BW_35   0x3
-#define ECI_BW_40   0x4
-#define ECI_BW_45   0x5
-#define ECI_BW_50   0x6
-#define ECI_BW_ALL  0x7
-
-/* WLAN - number of antenna */
-#define WLAN_NUM_ANT1 TXANT_0
-#define WLAN_NUM_ANT2 TXANT_1
-
-/* otpctrl1 0xF4 */
-#define OTPC_FORCE_PWR_OFF	0x02000000
-/* chipcommon s/r registers introduced with cc rev >= 48 */
-#define CC_SR_CTL0_ENABLE_MASK             0x1
-#define CC_SR_CTL0_ENABLE_SHIFT              0
-#define CC_SR_CTL0_EN_SR_ENG_CLK_SHIFT       1 /* sr_clk to sr_memory enable */
-#define CC_SR_CTL0_RSRC_TRIGGER_SHIFT        2 /* Rising edge resource trigger 0 to sr_engine  */
-#define CC_SR_CTL0_MIN_DIV_SHIFT             6 /* Min division value for fast clk in sr_engine */
-#define CC_SR_CTL0_EN_SBC_STBY_SHIFT        16 /* Allow Subcore mem StandBy? */
-#define CC_SR_CTL0_EN_SR_ALP_CLK_MASK_SHIFT 18
-#define CC_SR_CTL0_EN_SR_HT_CLK_SHIFT       19
-#define CC_SR_CTL0_ALLOW_PIC_SHIFT          20 /* Allow pic to separate power domains */
-#define CC_SR_CTL0_MAX_SR_LQ_CLK_CNT_SHIFT  25
-#define CC_SR_CTL0_EN_MEM_DISABLE_FOR_SLEEP 30
-
-#define CC_SR_CTL1_SR_INIT_MASK             0x3FF
-#define CC_SR_CTL1_SR_INIT_SHIFT            0
-
-#define	ECI_INLO_PKTDUR_MASK	0x000000f0 /* [7:4] - 4 bits */
-#define ECI_INLO_PKTDUR_SHIFT	4
-
-/* gci chip control bits */
-#define GCI_GPIO_CHIPCTRL_ENAB_IN_BIT		0
-#define GCI_GPIO_CHIPCTRL_ENAB_OP_BIT		1
-#define GCI_GPIO_CHIPCTRL_INVERT_BIT		2
-#define GCI_GPIO_CHIPCTRL_PULLUP_BIT		3
-#define GCI_GPIO_CHIPCTRL_PULLDN_BIT		4
-#define GCI_GPIO_CHIPCTRL_ENAB_BTSIG_BIT	5
-#define GCI_GPIO_CHIPCTRL_ENAB_OD_OP_BIT	6
-#define GCI_GPIO_CHIPCTRL_ENAB_EXT_GPIO_BIT	7
-
-/* gci GPIO input status bits */
-#define GCI_GPIO_STS_VALUE_BIT			0
-#define GCI_GPIO_STS_POS_EDGE_BIT		1
-#define GCI_GPIO_STS_NEG_EDGE_BIT		2
-#define GCI_GPIO_STS_FAST_EDGE_BIT		3
-#define GCI_GPIO_STS_CLEAR			0xF
-
-#define GCI_GPIO_STS_VALUE	(1 << GCI_GPIO_STS_VALUE_BIT)
-
-#endif	/* _SBCHIPC_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sbconfig.h b/drivers/net/wireless/bcmdhd/include/sbconfig.h
deleted file mode 100644
index 53e26ae..0000000
--- a/drivers/net/wireless/bcmdhd/include/sbconfig.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Broadcom SiliconBackplane hardware register definitions.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sbconfig.h 530150 2015-01-29 08:43:40Z $
- */
-
-#ifndef	_SBCONFIG_H
-#define	_SBCONFIG_H
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif
-
-/* enumeration in SB is based on the premise that cores are contiguos in the
- * enumeration space.
- */
-#define SB_BUS_SIZE		0x10000		/**< Each bus gets 64Kbytes for cores */
-#define SB_BUS_BASE(b)		(SI_ENUM_BASE + (b) * SB_BUS_SIZE)
-#define	SB_BUS_MAXCORES		(SB_BUS_SIZE / SI_CORE_SIZE)	/**< Max cores per bus */
-
-/*
- * Sonics Configuration Space Registers.
- */
-#define	SBCONFIGOFF		0xf00		/**< core sbconfig regs are top 256bytes of regs */
-#define	SBCONFIGSIZE		256		/**< sizeof (sbconfig_t) */
-
-#define SBIPSFLAG		0x08
-#define SBTPSFLAG		0x18
-#define	SBTMERRLOGA		0x48		/**< sonics >= 2.3 */
-#define	SBTMERRLOG		0x50		/**< sonics >= 2.3 */
-#define SBADMATCH3		0x60
-#define SBADMATCH2		0x68
-#define SBADMATCH1		0x70
-#define SBIMSTATE		0x90
-#define SBINTVEC		0x94
-#define SBTMSTATELOW		0x98
-#define SBTMSTATEHIGH		0x9c
-#define SBBWA0			0xa0
-#define SBIMCONFIGLOW		0xa8
-#define SBIMCONFIGHIGH		0xac
-#define SBADMATCH0		0xb0
-#define SBTMCONFIGLOW		0xb8
-#define SBTMCONFIGHIGH		0xbc
-#define SBBCONFIG		0xc0
-#define SBBSTATE		0xc8
-#define SBACTCNFG		0xd8
-#define	SBFLAGST		0xe8
-#define SBIDLOW			0xf8
-#define SBIDHIGH		0xfc
-
-/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have
- * a few registers *below* that line. I think it would be very confusing to try
- * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here,
- */
-
-#define SBIMERRLOGA		0xea8
-#define SBIMERRLOG		0xeb0
-#define SBTMPORTCONNID0		0xed8
-#define SBTMPORTLOCK0		0xef8
-
-#if !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__)
-
-typedef volatile struct _sbconfig {
-	uint32	PAD[2];
-	uint32	sbipsflag;		/**< initiator port ocp slave flag */
-	uint32	PAD[3];
-	uint32	sbtpsflag;		/**< target port ocp slave flag */
-	uint32	PAD[11];
-	uint32	sbtmerrloga;		/**< (sonics >= 2.3) */
-	uint32	PAD;
-	uint32	sbtmerrlog;		/**< (sonics >= 2.3) */
-	uint32	PAD[3];
-	uint32	sbadmatch3;		/**< address match3 */
-	uint32	PAD;
-	uint32	sbadmatch2;		/**< address match2 */
-	uint32	PAD;
-	uint32	sbadmatch1;		/**< address match1 */
-	uint32	PAD[7];
-	uint32	sbimstate;		/**< initiator agent state */
-	uint32	sbintvec;		/**< interrupt mask */
-	uint32	sbtmstatelow;		/**< target state */
-	uint32	sbtmstatehigh;		/**< target state */
-	uint32	sbbwa0;			/**< bandwidth allocation table0 */
-	uint32	PAD;
-	uint32	sbimconfiglow;		/**< initiator configuration */
-	uint32	sbimconfighigh;		/**< initiator configuration */
-	uint32	sbadmatch0;		/**< address match0 */
-	uint32	PAD;
-	uint32	sbtmconfiglow;		/**< target configuration */
-	uint32	sbtmconfighigh;		/**< target configuration */
-	uint32	sbbconfig;		/**< broadcast configuration */
-	uint32	PAD;
-	uint32	sbbstate;		/**< broadcast state */
-	uint32	PAD[3];
-	uint32	sbactcnfg;		/**< activate configuration */
-	uint32	PAD[3];
-	uint32	sbflagst;		/**< current sbflags */
-	uint32	PAD[3];
-	uint32	sbidlow;		/**< identification */
-	uint32	sbidhigh;		/**< identification */
-} sbconfig_t;
-
-#endif /* !_LANGUAGE_ASSEMBLY && !__ASSEMBLY__ */
-
-/* sbipsflag */
-#define	SBIPS_INT1_MASK		0x3f		/**< which sbflags get routed to mips interrupt 1 */
-#define	SBIPS_INT1_SHIFT	0
-#define	SBIPS_INT2_MASK		0x3f00		/**< which sbflags get routed to mips interrupt 2 */
-#define	SBIPS_INT2_SHIFT	8
-#define	SBIPS_INT3_MASK		0x3f0000	/**< which sbflags get routed to mips interrupt 3 */
-#define	SBIPS_INT3_SHIFT	16
-#define	SBIPS_INT4_MASK		0x3f000000	/**< which sbflags get routed to mips interrupt 4 */
-#define	SBIPS_INT4_SHIFT	24
-
-/* sbtpsflag */
-#define	SBTPS_NUM0_MASK		0x3f		/**< interrupt sbFlag # generated by this core */
-#define	SBTPS_F0EN0		0x40		/**< interrupt is always sent on the backplane */
-
-/* sbtmerrlog */
-#define	SBTMEL_CM		0x00000007	/**< command */
-#define	SBTMEL_CI		0x0000ff00	/**< connection id */
-#define	SBTMEL_EC		0x0f000000	/**< error code */
-#define	SBTMEL_ME		0x80000000	/**< multiple error */
-
-/* sbimstate */
-#define	SBIM_PC			0xf		/**< pipecount */
-#define	SBIM_AP_MASK		0x30		/**< arbitration policy */
-#define	SBIM_AP_BOTH		0x00		/**< use both timeslaces and token */
-#define	SBIM_AP_TS		0x10		/**< use timesliaces only */
-#define	SBIM_AP_TK		0x20		/**< use token only */
-#define	SBIM_AP_RSV		0x30		/**< reserved */
-#define	SBIM_IBE		0x20000		/**< inbanderror */
-#define	SBIM_TO			0x40000		/**< timeout */
-#define	SBIM_BY			0x01800000	/**< busy (sonics >= 2.3) */
-#define	SBIM_RJ			0x02000000	/**< reject (sonics >= 2.3) */
-
-/* sbtmstatelow */
-#define	SBTML_RESET		0x0001		/**< reset */
-#define	SBTML_REJ_MASK		0x0006		/**< reject field */
-#define	SBTML_REJ		0x0002		/**< reject */
-#define	SBTML_TMPREJ		0x0004		/**< temporary reject, for error recovery */
-
-#define	SBTML_SICF_SHIFT	16	/**< Shift to locate the SI control flags in sbtml */
-
-/* sbtmstatehigh */
-#define	SBTMH_SERR		0x0001		/**< serror */
-#define	SBTMH_INT		0x0002		/**< interrupt */
-#define	SBTMH_BUSY		0x0004		/**< busy */
-#define	SBTMH_TO		0x0020		/**< timeout (sonics >= 2.3) */
-
-#define	SBTMH_SISF_SHIFT	16		/**< Shift to locate the SI status flags in sbtmh */
-
-/* sbbwa0 */
-#define	SBBWA_TAB0_MASK		0xffff		/**< lookup table 0 */
-#define	SBBWA_TAB1_MASK		0xffff		/**< lookup table 1 */
-#define	SBBWA_TAB1_SHIFT	16
-
-/* sbimconfiglow */
-#define	SBIMCL_STO_MASK		0x7		/**< service timeout */
-#define	SBIMCL_RTO_MASK		0x70		/**< request timeout */
-#define	SBIMCL_RTO_SHIFT	4
-#define	SBIMCL_CID_MASK		0xff0000	/**< connection id */
-#define	SBIMCL_CID_SHIFT	16
-
-/* sbimconfighigh */
-#define	SBIMCH_IEM_MASK		0xc		/**< inband error mode */
-#define	SBIMCH_TEM_MASK		0x30		/**< timeout error mode */
-#define	SBIMCH_TEM_SHIFT	4
-#define	SBIMCH_BEM_MASK		0xc0		/**< bus error mode */
-#define	SBIMCH_BEM_SHIFT	6
-
-/* sbadmatch0 */
-#define	SBAM_TYPE_MASK		0x3		/**< address type */
-#define	SBAM_AD64		0x4		/**< reserved */
-#define	SBAM_ADINT0_MASK	0xf8		/**< type0 size */
-#define	SBAM_ADINT0_SHIFT	3
-#define	SBAM_ADINT1_MASK	0x1f8		/**< type1 size */
-#define	SBAM_ADINT1_SHIFT	3
-#define	SBAM_ADINT2_MASK	0x1f8		/**< type2 size */
-#define	SBAM_ADINT2_SHIFT	3
-#define	SBAM_ADEN		0x400		/**< enable */
-#define	SBAM_ADNEG		0x800		/**< negative decode */
-#define	SBAM_BASE0_MASK		0xffffff00	/**< type0 base address */
-#define	SBAM_BASE0_SHIFT	8
-#define	SBAM_BASE1_MASK		0xfffff000	/**< type1 base address for the core */
-#define	SBAM_BASE1_SHIFT	12
-#define	SBAM_BASE2_MASK		0xffff0000	/**< type2 base address for the core */
-#define	SBAM_BASE2_SHIFT	16
-
-/* sbtmconfiglow */
-#define	SBTMCL_CD_MASK		0xff		/**< clock divide */
-#define	SBTMCL_CO_MASK		0xf800		/**< clock offset */
-#define	SBTMCL_CO_SHIFT		11
-#define	SBTMCL_IF_MASK		0xfc0000	/**< interrupt flags */
-#define	SBTMCL_IF_SHIFT		18
-#define	SBTMCL_IM_MASK		0x3000000	/**< interrupt mode */
-#define	SBTMCL_IM_SHIFT		24
-
-/* sbtmconfighigh */
-#define	SBTMCH_BM_MASK		0x3		/**< busy mode */
-#define	SBTMCH_RM_MASK		0x3		/**< retry mode */
-#define	SBTMCH_RM_SHIFT		2
-#define	SBTMCH_SM_MASK		0x30		/**< stop mode */
-#define	SBTMCH_SM_SHIFT		4
-#define	SBTMCH_EM_MASK		0x300		/**< sb error mode */
-#define	SBTMCH_EM_SHIFT		8
-#define	SBTMCH_IM_MASK		0xc00		/**< int mode */
-#define	SBTMCH_IM_SHIFT		10
-
-/* sbbconfig */
-#define	SBBC_LAT_MASK		0x3		/**< sb latency */
-#define	SBBC_MAX0_MASK		0xf0000		/**< maxccntr0 */
-#define	SBBC_MAX0_SHIFT		16
-#define	SBBC_MAX1_MASK		0xf00000	/**< maxccntr1 */
-#define	SBBC_MAX1_SHIFT		20
-
-/* sbbstate */
-#define	SBBS_SRD		0x1		/**< st reg disable */
-#define	SBBS_HRD		0x2		/**< hold reg disable */
-
-/* sbidlow */
-#define	SBIDL_CS_MASK		0x3		/**< config space */
-#define	SBIDL_AR_MASK		0x38		/**< # address ranges supported */
-#define	SBIDL_AR_SHIFT		3
-#define	SBIDL_SYNCH		0x40		/**< sync */
-#define	SBIDL_INIT		0x80		/**< initiator */
-#define	SBIDL_MINLAT_MASK	0xf00		/**< minimum backplane latency */
-#define	SBIDL_MINLAT_SHIFT	8
-#define	SBIDL_MAXLAT		0xf000		/**< maximum backplane latency */
-#define	SBIDL_MAXLAT_SHIFT	12
-#define	SBIDL_FIRST		0x10000		/**< this initiator is first */
-#define	SBIDL_CW_MASK		0xc0000		/**< cycle counter width */
-#define	SBIDL_CW_SHIFT		18
-#define	SBIDL_TP_MASK		0xf00000	/**< target ports */
-#define	SBIDL_TP_SHIFT		20
-#define	SBIDL_IP_MASK		0xf000000	/**< initiator ports */
-#define	SBIDL_IP_SHIFT		24
-#define	SBIDL_RV_MASK		0xf0000000	/**< sonics backplane revision code */
-#define	SBIDL_RV_SHIFT		28
-#define	SBIDL_RV_2_2		0x00000000	/**< version 2.2 or earlier */
-#define	SBIDL_RV_2_3		0x10000000	/**< version 2.3 */
-
-/* sbidhigh */
-#define	SBIDH_RC_MASK		0x000f		/**< revision code */
-#define	SBIDH_RCE_MASK		0x7000		/**< revision code extension field */
-#define	SBIDH_RCE_SHIFT		8
-#define	SBCOREREV(sbidh) \
-	((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
-#define	SBIDH_CC_MASK		0x8ff0		/**< core code */
-#define	SBIDH_CC_SHIFT		4
-#define	SBIDH_VC_MASK		0xffff0000	/**< vendor code */
-#define	SBIDH_VC_SHIFT		16
-
-#define	SB_COMMIT		0xfd8		/**< update buffered registers value */
-
-/* vendor codes */
-#define	SB_VEND_BCM		0x4243		/**< Broadcom's SB vendor code */
-
-#endif	/* _SBCONFIG_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sbhnddma.h b/drivers/net/wireless/bcmdhd/include/sbhnddma.h
deleted file mode 100644
index 5692ea9..0000000
--- a/drivers/net/wireless/bcmdhd/include/sbhnddma.h
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Generic Broadcom Home Networking Division (HND) DMA engine HW interface
- * This supports the following chips: BCM42xx, 44xx, 47xx .
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sbhnddma.h 530150 2015-01-29 08:43:40Z $
- */
-
-#ifndef	_sbhnddma_h_
-#define	_sbhnddma_h_
-
-/* DMA structure:
- *  support two DMA engines: 32 bits address or 64 bit addressing
- *  basic DMA register set is per channel(transmit or receive)
- *  a pair of channels is defined for convenience
- */
-
-
-/* 32 bits addressing */
-
-/** dma registers per channel(xmt or rcv) */
-typedef volatile struct {
-	uint32	control;		/**< enable, et al */
-	uint32	addr;			/**< descriptor ring base address (4K aligned) */
-	uint32	ptr;			/**< last descriptor posted to chip */
-	uint32	status;			/**< current active descriptor, et al */
-} dma32regs_t;
-
-typedef volatile struct {
-	dma32regs_t	xmt;		/**< dma tx channel */
-	dma32regs_t	rcv;		/**< dma rx channel */
-} dma32regp_t;
-
-typedef volatile struct {	/* diag access */
-	uint32	fifoaddr;		/**< diag address */
-	uint32	fifodatalow;		/**< low 32bits of data */
-	uint32	fifodatahigh;		/**< high 32bits of data */
-	uint32	pad;			/**< reserved */
-} dma32diag_t;
-
-/**
- * DMA Descriptor
- * Descriptors are only read by the hardware, never written back.
- */
-typedef volatile struct {
-	uint32	ctrl;		/**< misc control bits & bufcount */
-	uint32	addr;		/**< data buffer address */
-} dma32dd_t;
-
-/** Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. */
-#define	D32RINGALIGN_BITS	12
-#define	D32MAXRINGSZ		(1 << D32RINGALIGN_BITS)
-#define	D32RINGALIGN		(1 << D32RINGALIGN_BITS)
-
-#define	D32MAXDD	(D32MAXRINGSZ / sizeof (dma32dd_t))
-
-/* transmit channel control */
-#define	XC_XE		((uint32)1 << 0)	/**< transmit enable */
-#define	XC_SE		((uint32)1 << 1)	/**< transmit suspend request */
-#define	XC_LE		((uint32)1 << 2)	/**< loopback enable */
-#define	XC_FL		((uint32)1 << 4)	/**< flush request */
-#define XC_MR_MASK	0x000001C0		/**< Multiple outstanding reads */
-#define XC_MR_SHIFT	6
-#define	XC_PD		((uint32)1 << 11)	/**< parity check disable */
-#define	XC_AE		((uint32)3 << 16)	/**< address extension bits */
-#define	XC_AE_SHIFT	16
-#define XC_BL_MASK	0x001C0000		/**< BurstLen bits */
-#define XC_BL_SHIFT	18
-#define XC_PC_MASK	0x00E00000		/**< Prefetch control */
-#define XC_PC_SHIFT	21
-#define XC_PT_MASK	0x03000000		/**< Prefetch threshold */
-#define XC_PT_SHIFT	24
-
-/** Multiple outstanding reads */
-#define DMA_MR_1	0
-#define DMA_MR_2	1
-#define DMA_MR_4	2
-#define DMA_MR_8	3
-#define DMA_MR_12	4
-#define DMA_MR_16	5
-#define DMA_MR_20	6
-#define DMA_MR_32	7
-
-/** DMA Burst Length in bytes */
-#define DMA_BL_16	0
-#define DMA_BL_32	1
-#define DMA_BL_64	2
-#define DMA_BL_128	3
-#define DMA_BL_256	4
-#define DMA_BL_512	5
-#define DMA_BL_1024	6
-
-/** Prefetch control */
-#define DMA_PC_0	0
-#define DMA_PC_4	1
-#define DMA_PC_8	2
-#define DMA_PC_16	3
-/* others: reserved */
-
-/** Prefetch threshold */
-#define DMA_PT_1	0
-#define DMA_PT_2	1
-#define DMA_PT_4	2
-#define DMA_PT_8	3
-
-/* transmit descriptor table pointer */
-#define	XP_LD_MASK	0xfff			/**< last valid descriptor */
-
-/* transmit channel status */
-#define	XS_CD_MASK	0x0fff			/**< current descriptor pointer */
-#define	XS_XS_MASK	0xf000			/**< transmit state */
-#define	XS_XS_SHIFT	12
-#define	XS_XS_DISABLED	0x0000			/**< disabled */
-#define	XS_XS_ACTIVE	0x1000			/**< active */
-#define	XS_XS_IDLE	0x2000			/**< idle wait */
-#define	XS_XS_STOPPED	0x3000			/**< stopped */
-#define	XS_XS_SUSP	0x4000			/**< suspend pending */
-#define	XS_XE_MASK	0xf0000			/**< transmit errors */
-#define	XS_XE_SHIFT	16
-#define	XS_XE_NOERR	0x00000			/**< no error */
-#define	XS_XE_DPE	0x10000			/**< descriptor protocol error */
-#define	XS_XE_DFU	0x20000			/**< data fifo underrun */
-#define	XS_XE_BEBR	0x30000			/**< bus error on buffer read */
-#define	XS_XE_BEDA	0x40000			/**< bus error on descriptor access */
-#define	XS_AD_MASK	0xfff00000		/**< active descriptor */
-#define	XS_AD_SHIFT	20
-
-/* receive channel control */
-#define	RC_RE		((uint32)1 << 0)	/**< receive enable */
-#define	RC_RO_MASK	0xfe			/**< receive frame offset */
-#define	RC_RO_SHIFT	1
-#define	RC_FM		((uint32)1 << 8)	/**< direct fifo receive (pio) mode */
-#define	RC_SH		((uint32)1 << 9)	/**< separate rx header descriptor enable */
-#define	RC_OC		((uint32)1 << 10)	/**< overflow continue */
-#define	RC_PD		((uint32)1 << 11)	/**< parity check disable */
-#define	RC_AE		((uint32)3 << 16)	/**< address extension bits */
-#define	RC_AE_SHIFT	16
-#define RC_BL_MASK	0x001C0000		/**< BurstLen bits */
-#define RC_BL_SHIFT	18
-#define RC_PC_MASK	0x00E00000		/**< Prefetch control */
-#define RC_PC_SHIFT	21
-#define RC_PT_MASK	0x03000000		/**< Prefetch threshold */
-#define RC_PT_SHIFT	24
-
-/* receive descriptor table pointer */
-#define	RP_LD_MASK	0xfff			/**< last valid descriptor */
-
-/* receive channel status */
-#define	RS_CD_MASK	0x0fff			/**< current descriptor pointer */
-#define	RS_RS_MASK	0xf000			/**< receive state */
-#define	RS_RS_SHIFT	12
-#define	RS_RS_DISABLED	0x0000			/**< disabled */
-#define	RS_RS_ACTIVE	0x1000			/**< active */
-#define	RS_RS_IDLE	0x2000			/**< idle wait */
-#define	RS_RS_STOPPED	0x3000			/**< reserved */
-#define	RS_RE_MASK	0xf0000			/**< receive errors */
-#define	RS_RE_SHIFT	16
-#define	RS_RE_NOERR	0x00000			/**< no error */
-#define	RS_RE_DPE	0x10000			/**< descriptor protocol error */
-#define	RS_RE_DFO	0x20000			/**< data fifo overflow */
-#define	RS_RE_BEBW	0x30000			/**< bus error on buffer write */
-#define	RS_RE_BEDA	0x40000			/**< bus error on descriptor access */
-#define	RS_AD_MASK	0xfff00000		/**< active descriptor */
-#define	RS_AD_SHIFT	20
-
-/* fifoaddr */
-#define	FA_OFF_MASK	0xffff			/**< offset */
-#define	FA_SEL_MASK	0xf0000			/**< select */
-#define	FA_SEL_SHIFT	16
-#define	FA_SEL_XDD	0x00000			/**< transmit dma data */
-#define	FA_SEL_XDP	0x10000			/**< transmit dma pointers */
-#define	FA_SEL_RDD	0x40000			/**< receive dma data */
-#define	FA_SEL_RDP	0x50000			/**< receive dma pointers */
-#define	FA_SEL_XFD	0x80000			/**< transmit fifo data */
-#define	FA_SEL_XFP	0x90000			/**< transmit fifo pointers */
-#define	FA_SEL_RFD	0xc0000			/**< receive fifo data */
-#define	FA_SEL_RFP	0xd0000			/**< receive fifo pointers */
-#define	FA_SEL_RSD	0xe0000			/**< receive frame status data */
-#define	FA_SEL_RSP	0xf0000			/**< receive frame status pointers */
-
-/* descriptor control flags */
-#define	CTRL_BC_MASK	0x00001fff		/**< buffer byte count, real data len must <= 4KB */
-#define	CTRL_AE		((uint32)3 << 16)	/**< address extension bits */
-#define	CTRL_AE_SHIFT	16
-#define	CTRL_PARITY	((uint32)3 << 18)	/**< parity bit */
-#define	CTRL_EOT	((uint32)1 << 28)	/**< end of descriptor table */
-#define	CTRL_IOC	((uint32)1 << 29)	/**< interrupt on completion */
-#define	CTRL_EOF	((uint32)1 << 30)	/**< end of frame */
-#define	CTRL_SOF	((uint32)1 << 31)	/**< start of frame */
-
-/** control flags in the range [27:20] are core-specific and not defined here */
-#define	CTRL_CORE_MASK	0x0ff00000
-
-/* 64 bits addressing */
-
-/** dma registers per channel(xmt or rcv) */
-typedef volatile struct {
-	uint32	control;	/**< enable, et al */
-	uint32	ptr;		/**< last descriptor posted to chip */
-	uint32	addrlow;	/**< descriptor ring base address low 32-bits (8K aligned) */
-	uint32	addrhigh;	/**< descriptor ring base address bits 63:32 (8K aligned) */
-	uint32	status0;	/**< current descriptor, xmt state */
-	uint32	status1;	/**< active descriptor, xmt error */
-} dma64regs_t;
-
-typedef volatile struct {
-	dma64regs_t	tx;		/**< dma64 tx channel */
-	dma64regs_t	rx;		/**< dma64 rx channel */
-} dma64regp_t;
-
-typedef volatile struct {		/**< diag access */
-	uint32	fifoaddr;		/**< diag address */
-	uint32	fifodatalow;		/**< low 32bits of data */
-	uint32	fifodatahigh;		/**< high 32bits of data */
-	uint32	pad;			/**< reserved */
-} dma64diag_t;
-
-/**
- * DMA Descriptor
- * Descriptors are only read by the hardware, never written back.
- */
-typedef volatile struct {
-	uint32	ctrl1;		/**< misc control bits */
-	uint32	ctrl2;		/**< buffer count and address extension */
-	uint32	addrlow;	/**< memory address of the date buffer, bits 31:0 */
-	uint32	addrhigh;	/**< memory address of the date buffer, bits 63:32 */
-} dma64dd_t;
-
-/**
- * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss.
- */
-#define D64RINGALIGN_BITS	13
-#define	D64MAXRINGSZ		(1 << D64RINGALIGN_BITS)
-#define	D64RINGBOUNDARY		(1 << D64RINGALIGN_BITS)
-
-#define	D64MAXDD	(D64MAXRINGSZ / sizeof (dma64dd_t))
-
-/** for cores with large descriptor ring support, descriptor ring size can be up to 4096 */
-#define	D64MAXDD_LARGE		((1 << 16) / sizeof (dma64dd_t))
-
-/**
- * for cores with large descriptor ring support (4k descriptors), descriptor ring cannot cross
- * 64K boundary
- */
-#define	D64RINGBOUNDARY_LARGE	(1 << 16)
-
-/*
- * Default DMA Burstlen values for USBRev >= 12 and SDIORev >= 11.
- * When this field contains the value N, the burst length is 2**(N + 4) bytes.
- */
-#define D64_DEF_USBBURSTLEN     2
-#define D64_DEF_SDIOBURSTLEN    1
-
-
-#ifndef D64_USBBURSTLEN
-#define D64_USBBURSTLEN	DMA_BL_64
-#endif
-#ifndef D64_SDIOBURSTLEN
-#define D64_SDIOBURSTLEN	DMA_BL_32
-#endif
-
-/* transmit channel control */
-#define	D64_XC_XE		0x00000001	/**< transmit enable */
-#define	D64_XC_SE		0x00000002	/**< transmit suspend request */
-#define	D64_XC_LE		0x00000004	/**< loopback enable */
-#define	D64_XC_FL		0x00000010	/**< flush request */
-#define D64_XC_MR_MASK		0x000001C0	/**< Multiple outstanding reads */
-#define D64_XC_MR_SHIFT		6
-#define	D64_XC_PD		0x00000800	/**< parity check disable */
-#define	D64_XC_AE		0x00030000	/**< address extension bits */
-#define	D64_XC_AE_SHIFT		16
-#define D64_XC_BL_MASK		0x001C0000	/**< BurstLen bits */
-#define D64_XC_BL_SHIFT		18
-#define D64_XC_PC_MASK		0x00E00000		/**< Prefetch control */
-#define D64_XC_PC_SHIFT		21
-#define D64_XC_PT_MASK		0x03000000		/**< Prefetch threshold */
-#define D64_XC_PT_SHIFT		24
-
-/* transmit descriptor table pointer */
-#define	D64_XP_LD_MASK		0x00001fff	/**< last valid descriptor */
-
-/* transmit channel status */
-#define	D64_XS0_CD_MASK		(di->d64_xs0_cd_mask)	/**< current descriptor pointer */
-#define	D64_XS0_XS_MASK		0xf0000000     	/**< transmit state */
-#define	D64_XS0_XS_SHIFT		28
-#define	D64_XS0_XS_DISABLED	0x00000000	/**< disabled */
-#define	D64_XS0_XS_ACTIVE	0x10000000	/**< active */
-#define	D64_XS0_XS_IDLE		0x20000000	/**< idle wait */
-#define	D64_XS0_XS_STOPPED	0x30000000	/**< stopped */
-#define	D64_XS0_XS_SUSP		0x40000000	/**< suspend pending */
-
-#define	D64_XS1_AD_MASK		(di->d64_xs1_ad_mask)	/**< active descriptor */
-#define	D64_XS1_XE_MASK		0xf0000000     	/**< transmit errors */
-#define	D64_XS1_XE_SHIFT		28
-#define	D64_XS1_XE_NOERR	0x00000000	/**< no error */
-#define	D64_XS1_XE_DPE		0x10000000	/**< descriptor protocol error */
-#define	D64_XS1_XE_DFU		0x20000000	/**< data fifo underrun */
-#define	D64_XS1_XE_DTE		0x30000000	/**< data transfer error */
-#define	D64_XS1_XE_DESRE	0x40000000	/**< descriptor read error */
-#define	D64_XS1_XE_COREE	0x50000000	/**< core error */
-
-/* receive channel control */
-#define	D64_RC_RE		0x00000001	/**< receive enable */
-#define	D64_RC_RO_MASK		0x000000fe	/**< receive frame offset */
-#define	D64_RC_RO_SHIFT		1
-#define	D64_RC_FM		0x00000100	/**< direct fifo receive (pio) mode */
-#define	D64_RC_SH		0x00000200	/**< separate rx header descriptor enable */
-#define	D64_RC_SHIFT		9	/**< separate rx header descriptor enable */
-#define	D64_RC_OC		0x00000400	/**< overflow continue */
-#define	D64_RC_PD		0x00000800	/**< parity check disable */
-#define D64_RC_SA		0x00002000	/**< select active */
-#define D64_RC_GE		0x00004000	/**< Glom enable */
-#define	D64_RC_AE		0x00030000	/**< address extension bits */
-#define	D64_RC_AE_SHIFT		16
-#define D64_RC_BL_MASK		0x001C0000	/**< BurstLen bits */
-#define D64_RC_BL_SHIFT		18
-#define D64_RC_PC_MASK		0x00E00000	/**< Prefetch control */
-#define D64_RC_PC_SHIFT		21
-#define D64_RC_PT_MASK		0x03000000	/**< Prefetch threshold */
-#define D64_RC_PT_SHIFT		24
-
-/* flags for dma controller */
-#define DMA_CTRL_PEN		(1 << 0)	/**< partity enable */
-#define DMA_CTRL_ROC		(1 << 1)	/**< rx overflow continue */
-#define DMA_CTRL_RXMULTI	(1 << 2)	/**< allow rx scatter to multiple descriptors */
-#define DMA_CTRL_UNFRAMED	(1 << 3)	/**< Unframed Rx/Tx data */
-#define DMA_CTRL_USB_BOUNDRY4KB_WAR (1 << 4)
-#define DMA_CTRL_DMA_AVOIDANCE_WAR (1 << 5)	/**< DMA avoidance WAR for 4331 */
-#define DMA_CTRL_RXSINGLE	(1 << 6)	/**< always single buffer */
-#define DMA_CTRL_SDIO_RXGLOM	(1 << 7)	/**< DMA Rx glome is enabled */
-
-/* receive descriptor table pointer */
-#define	D64_RP_LD_MASK		0x00001fff	/**< last valid descriptor */
-
-/* receive channel status */
-#define	D64_RS0_CD_MASK		(di->d64_rs0_cd_mask)	/**< current descriptor pointer */
-#define	D64_RS0_RS_MASK		0xf0000000     	/**< receive state */
-#define	D64_RS0_RS_SHIFT		28
-#define	D64_RS0_RS_DISABLED	0x00000000	/**< disabled */
-#define	D64_RS0_RS_ACTIVE	0x10000000	/**< active */
-#define	D64_RS0_RS_IDLE		0x20000000	/**< idle wait */
-#define	D64_RS0_RS_STOPPED	0x30000000	/**< stopped */
-#define	D64_RS0_RS_SUSP		0x40000000	/**< suspend pending */
-
-#define	D64_RS1_AD_MASK		0x0001ffff	/**< active descriptor */
-#define	D64_RS1_RE_MASK		0xf0000000     	/**< receive errors */
-#define	D64_RS1_RE_SHIFT		28
-#define	D64_RS1_RE_NOERR	0x00000000	/**< no error */
-#define	D64_RS1_RE_DPO		0x10000000	/**< descriptor protocol error */
-#define	D64_RS1_RE_DFU		0x20000000	/**< data fifo overflow */
-#define	D64_RS1_RE_DTE		0x30000000	/**< data transfer error */
-#define	D64_RS1_RE_DESRE	0x40000000	/**< descriptor read error */
-#define	D64_RS1_RE_COREE	0x50000000	/**< core error */
-
-/* fifoaddr */
-#define	D64_FA_OFF_MASK		0xffff		/**< offset */
-#define	D64_FA_SEL_MASK		0xf0000		/**< select */
-#define	D64_FA_SEL_SHIFT	16
-#define	D64_FA_SEL_XDD		0x00000		/**< transmit dma data */
-#define	D64_FA_SEL_XDP		0x10000		/**< transmit dma pointers */
-#define	D64_FA_SEL_RDD		0x40000		/**< receive dma data */
-#define	D64_FA_SEL_RDP		0x50000		/**< receive dma pointers */
-#define	D64_FA_SEL_XFD		0x80000		/**< transmit fifo data */
-#define	D64_FA_SEL_XFP		0x90000		/**< transmit fifo pointers */
-#define	D64_FA_SEL_RFD		0xc0000		/**< receive fifo data */
-#define	D64_FA_SEL_RFP		0xd0000		/**< receive fifo pointers */
-#define	D64_FA_SEL_RSD		0xe0000		/**< receive frame status data */
-#define	D64_FA_SEL_RSP		0xf0000		/**< receive frame status pointers */
-
-/* descriptor control flags 1 */
-#define D64_CTRL_COREFLAGS	0x0ff00000		/**< core specific flags */
-#define	D64_CTRL1_NOTPCIE	((uint32)1 << 18)	/**< buirst size control */
-#define	D64_CTRL1_EOT		((uint32)1 << 28)	/**< end of descriptor table */
-#define	D64_CTRL1_IOC		((uint32)1 << 29)	/**< interrupt on completion */
-#define	D64_CTRL1_EOF		((uint32)1 << 30)	/**< end of frame */
-#define	D64_CTRL1_SOF		((uint32)1 << 31)	/**< start of frame */
-
-/* descriptor control flags 2 */
-#define	D64_CTRL2_BC_MASK	0x00007fff /**< buffer byte count. real data len must <= 16KB */
-#define	D64_CTRL2_AE		0x00030000 /**< address extension bits */
-#define	D64_CTRL2_AE_SHIFT	16
-#define D64_CTRL2_PARITY	0x00040000      /* parity bit */
-
-/** control flags in the range [27:20] are core-specific and not defined here */
-#define	D64_CTRL_CORE_MASK	0x0ff00000
-
-#define D64_RX_FRM_STS_LEN	0x0000ffff	/**< frame length mask */
-#define D64_RX_FRM_STS_OVFL	0x00800000	/**< RxOverFlow */
-#define D64_RX_FRM_STS_DSCRCNT	0x0f000000 /**< no. of descriptors used - 1, d11corerev >= 22 */
-#define D64_RX_FRM_STS_DATATYPE	0xf0000000	/**< core-dependent data type */
-
-/** receive frame status */
-typedef volatile struct {
-	uint16 len;
-	uint16 flags;
-} dma_rxh_t;
-
-#endif	/* _sbhnddma_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/sbpcmcia.h b/drivers/net/wireless/bcmdhd/include/sbpcmcia.h
deleted file mode 100644
index d2e42ff..0000000
--- a/drivers/net/wireless/bcmdhd/include/sbpcmcia.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sbpcmcia.h 521344 2014-12-17 10:03:55Z $
- */
-
-#ifndef	_SBPCMCIA_H
-#define	_SBPCMCIA_H
-
-/* All the addresses that are offsets in attribute space are divided
- * by two to account for the fact that odd bytes are invalid in
- * attribute space and our read/write routines make the space appear
- * as if they didn't exist. Still we want to show the original numbers
- * as documented in the hnd_pcmcia core manual.
- */
-
-/* PCMCIA Function Configuration Registers */
-#define	PCMCIA_FCR		(0x700 / 2)
-
-#define	FCR0_OFF		0
-#define	FCR1_OFF		(0x40 / 2)
-#define	FCR2_OFF		(0x80 / 2)
-#define	FCR3_OFF		(0xc0 / 2)
-
-#define	PCMCIA_FCR0		(0x700 / 2)
-#define	PCMCIA_FCR1		(0x740 / 2)
-#define	PCMCIA_FCR2		(0x780 / 2)
-#define	PCMCIA_FCR3		(0x7c0 / 2)
-
-/* Standard PCMCIA FCR registers */
-
-#define	PCMCIA_COR		0
-
-#define	COR_RST			0x80
-#define	COR_LEV			0x40
-#define	COR_IRQEN		0x04
-#define	COR_BLREN		0x01
-#define	COR_FUNEN		0x01
-
-
-#define	PCICIA_FCSR		(2 / 2)
-#define	PCICIA_PRR		(4 / 2)
-#define	PCICIA_SCR		(6 / 2)
-#define	PCICIA_ESR		(8 / 2)
-
-
-#define PCM_MEMOFF		0x0000
-#define F0_MEMOFF		0x1000
-#define F1_MEMOFF		0x2000
-#define F2_MEMOFF		0x3000
-#define F3_MEMOFF		0x4000
-
-/* Memory base in the function fcr's */
-#define MEM_ADDR0		(0x728 / 2)
-#define MEM_ADDR1		(0x72a / 2)
-#define MEM_ADDR2		(0x72c / 2)
-
-/* PCMCIA base plus Srom access in fcr0: */
-#define PCMCIA_ADDR0		(0x072e / 2)
-#define PCMCIA_ADDR1		(0x0730 / 2)
-#define PCMCIA_ADDR2		(0x0732 / 2)
-
-#define MEM_SEG			(0x0734 / 2)
-#define SROM_CS			(0x0736 / 2)
-#define SROM_DATAL		(0x0738 / 2)
-#define SROM_DATAH		(0x073a / 2)
-#define SROM_ADDRL		(0x073c / 2)
-#define SROM_ADDRH		(0x073e / 2)
-#define	SROM_INFO2		(0x0772 / 2)	/* Corerev >= 2 && <= 5 */
-#define	SROM_INFO		(0x07be / 2)	/* Corerev >= 6 */
-
-/*  Values for srom_cs: */
-#define SROM_IDLE		0
-#define SROM_WRITE		1
-#define SROM_READ		2
-#define SROM_WEN		4
-#define SROM_WDS		7
-#define SROM_DONE		8
-
-/* Fields in srom_info: */
-#define	SRI_SZ_MASK		0x03
-#define	SRI_BLANK		0x04
-#define	SRI_OTP			0x80
-
-
-/* sbtmstatelow */
-#define SBTML_INT_ACK		0x40000		/* ack the sb interrupt */
-#define SBTML_INT_EN		0x20000		/* enable sb interrupt */
-
-/* sbtmstatehigh */
-#define SBTMH_INT_STATUS	0x40000		/* sb interrupt status */
-
-#endif	/* _SBPCMCIA_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sbsdio.h b/drivers/net/wireless/bcmdhd/include/sbsdio.h
deleted file mode 100644
index f4760a2..0000000
--- a/drivers/net/wireless/bcmdhd/include/sbsdio.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * SDIO device core hardware definitions.
- * sdio is a portion of the pcmcia core in core rev 3 - rev 8
- *
- * SDIO core support 1bit, 4 bit SDIO mode as well as SPI mode.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sbsdio.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_SBSDIO_H
-#define	_SBSDIO_H
-
-#define SBSDIO_NUM_FUNCTION		3	/* as of sdiod rev 0, supports 3 functions */
-
-/* function 1 miscellaneous registers */
-#define SBSDIO_SPROM_CS			0x10000		/* sprom command and status */
-#define SBSDIO_SPROM_INFO		0x10001		/* sprom info register */
-#define SBSDIO_SPROM_DATA_LOW		0x10002		/* sprom indirect access data byte 0 */
-#define SBSDIO_SPROM_DATA_HIGH		0x10003 	/* sprom indirect access data byte 1 */
-#define SBSDIO_SPROM_ADDR_LOW		0x10004		/* sprom indirect access addr byte 0 */
-#define SBSDIO_SPROM_ADDR_HIGH		0x10005		/* sprom indirect access addr byte 0 */
-#define SBSDIO_CHIP_CTRL_DATA		0x10006		/* xtal_pu (gpio) output */
-#define SBSDIO_CHIP_CTRL_EN		0x10007		/* xtal_pu (gpio) enable */
-#define SBSDIO_WATERMARK		0x10008		/* rev < 7, watermark for sdio device */
-#define SBSDIO_DEVICE_CTL		0x10009		/* control busy signal generation */
-
-/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */
-#define SBSDIO_FUNC1_SBADDRLOW		0x1000A		/* SB Address Window Low (b15) */
-#define SBSDIO_FUNC1_SBADDRMID		0x1000B		/* SB Address Window Mid (b23:b16) */
-#define SBSDIO_FUNC1_SBADDRHIGH		0x1000C		/* SB Address Window High (b31:b24)    */
-#define SBSDIO_FUNC1_FRAMECTRL		0x1000D		/* Frame Control (frame term/abort) */
-#define SBSDIO_FUNC1_CHIPCLKCSR		0x1000E		/* ChipClockCSR (ALP/HT ctl/status) */
-#define SBSDIO_FUNC1_SDIOPULLUP 	0x1000F		/* SdioPullUp (on cmd, d0-d2) */
-#define SBSDIO_FUNC1_WFRAMEBCLO		0x10019		/* Write Frame Byte Count Low */
-#define SBSDIO_FUNC1_WFRAMEBCHI		0x1001A		/* Write Frame Byte Count High */
-#define SBSDIO_FUNC1_RFRAMEBCLO		0x1001B		/* Read Frame Byte Count Low */
-#define SBSDIO_FUNC1_RFRAMEBCHI		0x1001C		/* Read Frame Byte Count High */
-#define SBSDIO_FUNC1_MESBUSYCTRL	0x1001D		/* MesBusyCtl at 0x1001D (rev 11) */
-
-#define SBSDIO_FUNC1_MISC_REG_START	0x10000 	/* f1 misc register start */
-#define SBSDIO_FUNC1_MISC_REG_LIMIT	0x1001C 	/* f1 misc register end */
-
-/* Sdio Core Rev 12 */
-#define SBSDIO_FUNC1_WAKEUPCTRL			0x1001E
-#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK		0x1
-#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT	0
-#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK		0x2
-#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT		1
-#define SBSDIO_FUNC1_SLEEPCSR			0x1001F
-#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK		0x1
-#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT		0
-#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN		1
-#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK	0x2
-#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT	1
-
-/* SBSDIO_SPROM_CS */
-#define SBSDIO_SPROM_IDLE		0
-#define SBSDIO_SPROM_WRITE		1
-#define SBSDIO_SPROM_READ		2
-#define SBSDIO_SPROM_WEN		4
-#define SBSDIO_SPROM_WDS		7
-#define SBSDIO_SPROM_DONE		8
-
-/* SBSDIO_SPROM_INFO */
-#define SROM_SZ_MASK			0x03		/* SROM size, 1: 4k, 2: 16k */
-#define SROM_BLANK			0x04		/* depreciated in corerev 6 */
-#define	SROM_OTP			0x80		/* OTP present */
-
-/* SBSDIO_CHIP_CTRL */
-#define SBSDIO_CHIP_CTRL_XTAL		0x01		/* or'd with onchip xtal_pu,
-							 * 1: power on oscillator
-							 * (for 4318 only)
-							 */
-/* SBSDIO_WATERMARK */
-#define SBSDIO_WATERMARK_MASK		0x7f		/* number of words - 1 for sd device
-							 * to wait before sending data to host
-							 */
-
-/* SBSDIO_MESBUSYCTRL */
-/* When RX FIFO has less entries than this & MBE is set
- * => busy signal is asserted between data blocks.
-*/
-#define SBSDIO_MESBUSYCTRL_MASK		0x7f
-#define SBSDIO_MESBUSYCTRL_ENAB		0x80		/* Enable busy capability for MES access */
-
-/* SBSDIO_DEVICE_CTL */
-#define SBSDIO_DEVCTL_SETBUSY		0x01		/* 1: device will assert busy signal when
-							 * receiving CMD53
-							 */
-#define SBSDIO_DEVCTL_SPI_INTR_SYNC	0x02		/* 1: assertion of sdio interrupt is
-							 * synchronous to the sdio clock
-							 */
-#define SBSDIO_DEVCTL_CA_INT_ONLY	0x04		/* 1: mask all interrupts to host
-							 * except the chipActive (rev 8)
-							 */
-#define SBSDIO_DEVCTL_PADS_ISO		0x08		/* 1: isolate internal sdio signals, put
-							 * external pads in tri-state; requires
-							 * sdio bus power cycle to clear (rev 9)
-							 */
-#define SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK 0x10  /* Enable function 2 tx for each block */
-#define SBSDIO_DEVCTL_F2WM_ENAB		0x10		/* Enable F2 Watermark */
-#define SBSDIO_DEVCTL_NONDAT_PADS_ISO 	0x20		/* Isolate sdio clk and cmd (non-data) */
-
-/* SBSDIO_FUNC1_CHIPCLKCSR */
-#define SBSDIO_FORCE_ALP		0x01		/* Force ALP request to backplane */
-#define SBSDIO_FORCE_HT			0x02		/* Force HT request to backplane */
-#define SBSDIO_FORCE_ILP		0x04		/* Force ILP request to backplane */
-#define SBSDIO_ALP_AVAIL_REQ		0x08		/* Make ALP ready (power up xtal) */
-#define SBSDIO_HT_AVAIL_REQ		0x10		/* Make HT ready (power up PLL) */
-#define SBSDIO_FORCE_HW_CLKREQ_OFF	0x20		/* Squelch clock requests from HW */
-#define SBSDIO_ALP_AVAIL		0x40		/* Status: ALP is ready */
-#define SBSDIO_HT_AVAIL			0x80		/* Status: HT is ready */
-/* In rev8, actual avail bits followed original docs */
-#define SBSDIO_Rev8_HT_AVAIL		0x40
-#define SBSDIO_Rev8_ALP_AVAIL		0x80
-#define SBSDIO_CSR_MASK			0x1F
-
-#define SBSDIO_AVBITS			(SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
-#define SBSDIO_ALPAV(regval)		((regval) & SBSDIO_AVBITS)
-#define SBSDIO_HTAV(regval)		(((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
-#define SBSDIO_ALPONLY(regval)		(SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
-#define SBSDIO_CLKAV(regval, alponly)	(SBSDIO_ALPAV(regval) && \
-					(alponly ? 1 : SBSDIO_HTAV(regval)))
-
-/* SBSDIO_FUNC1_SDIOPULLUP */
-#define SBSDIO_PULLUP_D0		0x01		/* Enable D0/MISO pullup */
-#define SBSDIO_PULLUP_D1		0x02		/* Enable D1/INT# pullup */
-#define SBSDIO_PULLUP_D2		0x04		/* Enable D2 pullup */
-#define SBSDIO_PULLUP_CMD		0x08		/* Enable CMD/MOSI pullup */
-#define SBSDIO_PULLUP_ALL		0x0f		/* All valid bits */
-
-/* function 1 OCP space */
-#define SBSDIO_SB_OFT_ADDR_MASK		0x07FFF		/* sb offset addr is <= 15 bits, 32k */
-#define SBSDIO_SB_OFT_ADDR_LIMIT	0x08000
-#define SBSDIO_SB_ACCESS_2_4B_FLAG	0x08000		/* with b15, maps to 32-bit SB access */
-
-/* some duplication with sbsdpcmdev.h here */
-/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
-#define SBSDIO_SBADDRLOW_MASK		0x80		/* Valid bits in SBADDRLOW */
-#define SBSDIO_SBADDRMID_MASK		0xff		/* Valid bits in SBADDRMID */
-#define SBSDIO_SBADDRHIGH_MASK		0xffU		/* Valid bits in SBADDRHIGH */
-#define SBSDIO_SBWINDOW_MASK		0xffff8000	/* Address bits from SBADDR regs */
-
-/* direct(mapped) cis space */
-#define SBSDIO_CIS_BASE_COMMON		0x1000		/* MAPPED common CIS address */
-#define SBSDIO_CIS_SIZE_LIMIT		0x200		/* maximum bytes in one CIS */
-#define SBSDIO_OTP_CIS_SIZE_LIMIT       0x078           /* maximum bytes OTP CIS */
-
-#define SBSDIO_CIS_OFT_ADDR_MASK	0x1FFFF		/* cis offset addr is < 17 bits */
-
-#define SBSDIO_CIS_MANFID_TUPLE_LEN	6		/* manfid tuple length, include tuple,
-							 * link bytes
-							 */
-
-/* indirect cis access (in sprom) */
-#define SBSDIO_SPROM_CIS_OFFSET		0x8		/* 8 control bytes first, CIS starts from
-							 * 8th byte
-							 */
-
-#define SBSDIO_BYTEMODE_DATALEN_MAX	64		/* sdio byte mode: maximum length of one
-							 * data comamnd
-							 */
-
-#define SBSDIO_CORE_ADDR_MASK		0x1FFFF		/* sdio core function one address mask */
-
-#endif	/* _SBSDIO_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h b/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h
deleted file mode 100644
index c0c889e..0000000
--- a/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Broadcom SiliconBackplane SDIO/PCMCIA hardware-specific
- * device core support
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sbsdpcmdev.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_sbsdpcmdev_h_
-#define	_sbsdpcmdev_h_
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif	/* PAD */
-
-
-typedef volatile struct {
-	dma64regs_t	xmt;		/* dma tx */
-	uint32 PAD[2];
-	dma64regs_t	rcv;		/* dma rx */
-	uint32 PAD[2];
-} dma64p_t;
-
-/* dma64 sdiod corerev >= 1 */
-typedef volatile struct {
-	dma64p_t dma64regs[2];
-	dma64diag_t dmafifo;		/* DMA Diagnostic Regs, 0x280-0x28c */
-	uint32 PAD[92];
-} sdiodma64_t;
-
-/* dma32 sdiod corerev == 0 */
-typedef volatile struct {
-	dma32regp_t dma32regs[2];	/* dma tx & rx, 0x200-0x23c */
-	dma32diag_t dmafifo;		/* DMA Diagnostic Regs, 0x240-0x24c */
-	uint32 PAD[108];
-} sdiodma32_t;
-
-/* dma32 regs for pcmcia core */
-typedef volatile struct {
-	dma32regp_t dmaregs;		/* DMA Regs, 0x200-0x21c, rev8 */
-	dma32diag_t dmafifo;		/* DMA Diagnostic Regs, 0x220-0x22c */
-	uint32 PAD[116];
-} pcmdma32_t;
-
-/* core registers */
-typedef volatile struct {
-	uint32 corecontrol;		/* CoreControl, 0x000, rev8 */
-	uint32 corestatus;		/* CoreStatus, 0x004, rev8  */
-	uint32 PAD[1];
-	uint32 biststatus;		/* BistStatus, 0x00c, rev8  */
-
-	/* PCMCIA access */
-	uint16 pcmciamesportaladdr;	/* PcmciaMesPortalAddr, 0x010, rev8   */
-	uint16 PAD[1];
-	uint16 pcmciamesportalmask;	/* PcmciaMesPortalMask, 0x014, rev8   */
-	uint16 PAD[1];
-	uint16 pcmciawrframebc;		/* PcmciaWrFrameBC, 0x018, rev8   */
-	uint16 PAD[1];
-	uint16 pcmciaunderflowtimer;	/* PcmciaUnderflowTimer, 0x01c, rev8   */
-	uint16 PAD[1];
-
-	/* interrupt */
-	uint32 intstatus;		/* IntStatus, 0x020, rev8   */
-	uint32 hostintmask;		/* IntHostMask, 0x024, rev8   */
-	uint32 intmask;			/* IntSbMask, 0x028, rev8   */
-	uint32 sbintstatus;		/* SBIntStatus, 0x02c, rev8   */
-	uint32 sbintmask;		/* SBIntMask, 0x030, rev8   */
-	uint32 funcintmask;		/* SDIO Function Interrupt Mask, SDIO rev4 */
-	uint32 PAD[2];
-	uint32 tosbmailbox;		/* ToSBMailbox, 0x040, rev8   */
-	uint32 tohostmailbox;		/* ToHostMailbox, 0x044, rev8   */
-	uint32 tosbmailboxdata;		/* ToSbMailboxData, 0x048, rev8   */
-	uint32 tohostmailboxdata;	/* ToHostMailboxData, 0x04c, rev8   */
-
-	/* synchronized access to registers in SDIO clock domain */
-	uint32 sdioaccess;		/* SdioAccess, 0x050, rev8   */
-	uint32 PAD[3];
-
-	/* PCMCIA frame control */
-	uint8 pcmciaframectrl;		/* pcmciaFrameCtrl, 0x060, rev8   */
-	uint8 PAD[3];
-	uint8 pcmciawatermark;		/* pcmciaWaterMark, 0x064, rev8   */
-	uint8 PAD[155];
-
-	/* interrupt batching control */
-	uint32 intrcvlazy;		/* IntRcvLazy, 0x100, rev8 */
-	uint32 PAD[3];
-
-	/* counters */
-	uint32 cmd52rd;			/* Cmd52RdCount, 0x110, rev8, SDIO: cmd52 reads */
-	uint32 cmd52wr;			/* Cmd52WrCount, 0x114, rev8, SDIO: cmd52 writes */
-	uint32 cmd53rd;			/* Cmd53RdCount, 0x118, rev8, SDIO: cmd53 reads */
-	uint32 cmd53wr;			/* Cmd53WrCount, 0x11c, rev8, SDIO: cmd53 writes */
-	uint32 abort;			/* AbortCount, 0x120, rev8, SDIO: aborts */
-	uint32 datacrcerror;		/* DataCrcErrorCount, 0x124, rev8, SDIO: frames w/bad CRC */
-	uint32 rdoutofsync;		/* RdOutOfSyncCount, 0x128, rev8, SDIO/PCMCIA: Rd Frm OOS */
-	uint32 wroutofsync;		/* RdOutOfSyncCount, 0x12c, rev8, SDIO/PCMCIA: Wr Frm OOS */
-	uint32 writebusy;		/* WriteBusyCount, 0x130, rev8, SDIO: dev asserted "busy" */
-	uint32 readwait;		/* ReadWaitCount, 0x134, rev8, SDIO: read: no data avail */
-	uint32 readterm;		/* ReadTermCount, 0x138, rev8, SDIO: rd frm terminates */
-	uint32 writeterm;		/* WriteTermCount, 0x13c, rev8, SDIO: wr frm terminates */
-	uint32 PAD[40];
-	uint32 clockctlstatus;		/* ClockCtlStatus, 0x1e0, rev8 */
-	uint32 PAD[7];
-
-	/* DMA engines */
-	volatile union {
-		pcmdma32_t pcm32;
-		sdiodma32_t sdiod32;
-		sdiodma64_t sdiod64;
-	} dma;
-
-	/* SDIO/PCMCIA CIS region */
-	char cis[512];			/* 512 byte CIS, 0x400-0x5ff, rev6 */
-
-	/* PCMCIA function control registers */
-	char pcmciafcr[256];		/* PCMCIA FCR, 0x600-6ff, rev6 */
-	uint16 PAD[55];
-
-	/* PCMCIA backplane access */
-	uint16 backplanecsr;		/* BackplaneCSR, 0x76E, rev6 */
-	uint16 backplaneaddr0;		/* BackplaneAddr0, 0x770, rev6 */
-	uint16 backplaneaddr1;		/* BackplaneAddr1, 0x772, rev6 */
-	uint16 backplaneaddr2;		/* BackplaneAddr2, 0x774, rev6 */
-	uint16 backplaneaddr3;		/* BackplaneAddr3, 0x776, rev6 */
-	uint16 backplanedata0;		/* BackplaneData0, 0x778, rev6 */
-	uint16 backplanedata1;		/* BackplaneData1, 0x77a, rev6 */
-	uint16 backplanedata2;		/* BackplaneData2, 0x77c, rev6 */
-	uint16 backplanedata3;		/* BackplaneData3, 0x77e, rev6 */
-	uint16 PAD[31];
-
-	/* sprom "size" & "blank" info */
-	uint16 spromstatus;		/* SPROMStatus, 0x7BE, rev2 */
-	uint32 PAD[464];
-
-	/* Sonics SiliconBackplane registers */
-	sbconfig_t sbconfig;		/* SbConfig Regs, 0xf00-0xfff, rev8 */
-} sdpcmd_regs_t;
-
-/* corecontrol */
-#define CC_CISRDY		(1 << 0)	/* CIS Ready */
-#define CC_BPRESEN		(1 << 1)	/* CCCR RES signal causes backplane reset */
-#define CC_F2RDY		(1 << 2)	/* set CCCR IOR2 bit */
-#define CC_CLRPADSISO		(1 << 3)	/* clear SDIO pads isolation bit (rev 11) */
-#define CC_XMTDATAAVAIL_MODE	(1 << 4)	/* data avail generates an interrupt */
-#define CC_XMTDATAAVAIL_CTRL	(1 << 5)	/* data avail interrupt ctrl */
-
-/* corestatus */
-#define CS_PCMCIAMODE	(1 << 0)	/* Device Mode; 0=SDIO, 1=PCMCIA */
-#define CS_SMARTDEV	(1 << 1)	/* 1=smartDev enabled */
-#define CS_F2ENABLED	(1 << 2)	/* 1=host has enabled the device */
-
-#define PCMCIA_MES_PA_MASK	0x7fff	/* PCMCIA Message Portal Address Mask */
-#define PCMCIA_MES_PM_MASK	0x7fff	/* PCMCIA Message Portal Mask Mask */
-#define PCMCIA_WFBC_MASK	0xffff	/* PCMCIA Write Frame Byte Count Mask */
-#define PCMCIA_UT_MASK		0x07ff	/* PCMCIA Underflow Timer Mask */
-
-/* intstatus */
-#define I_SMB_SW0	(1 << 0)	/* To SB Mail S/W interrupt 0 */
-#define I_SMB_SW1	(1 << 1)	/* To SB Mail S/W interrupt 1 */
-#define I_SMB_SW2	(1 << 2)	/* To SB Mail S/W interrupt 2 */
-#define I_SMB_SW3	(1 << 3)	/* To SB Mail S/W interrupt 3 */
-#define I_SMB_SW_MASK	0x0000000f	/* To SB Mail S/W interrupts mask */
-#define I_SMB_SW_SHIFT	0		/* To SB Mail S/W interrupts shift */
-#define I_HMB_SW0	(1 << 4)	/* To Host Mail S/W interrupt 0 */
-#define I_HMB_SW1	(1 << 5)	/* To Host Mail S/W interrupt 1 */
-#define I_HMB_SW2	(1 << 6)	/* To Host Mail S/W interrupt 2 */
-#define I_HMB_SW3	(1 << 7)	/* To Host Mail S/W interrupt 3 */
-#define I_HMB_SW_MASK	0x000000f0	/* To Host Mail S/W interrupts mask */
-#define I_HMB_SW_SHIFT	4		/* To Host Mail S/W interrupts shift */
-#define I_WR_OOSYNC	(1 << 8)	/* Write Frame Out Of Sync */
-#define I_RD_OOSYNC	(1 << 9)	/* Read Frame Out Of Sync */
-#define	I_PC		(1 << 10)	/* descriptor error */
-#define	I_PD		(1 << 11)	/* data error */
-#define	I_DE		(1 << 12)	/* Descriptor protocol Error */
-#define	I_RU		(1 << 13)	/* Receive descriptor Underflow */
-#define	I_RO		(1 << 14)	/* Receive fifo Overflow */
-#define	I_XU		(1 << 15)	/* Transmit fifo Underflow */
-#define	I_RI		(1 << 16)	/* Receive Interrupt */
-#define I_BUSPWR	(1 << 17)	/* SDIO Bus Power Change (rev 9) */
-#define I_XMTDATA_AVAIL (1 << 23)	/* bits in fifo */
-#define	I_XI		(1 << 24)	/* Transmit Interrupt */
-#define I_RF_TERM	(1 << 25)	/* Read Frame Terminate */
-#define I_WF_TERM	(1 << 26)	/* Write Frame Terminate */
-#define I_PCMCIA_XU	(1 << 27)	/* PCMCIA Transmit FIFO Underflow */
-#define I_SBINT		(1 << 28)	/* sbintstatus Interrupt */
-#define I_CHIPACTIVE	(1 << 29)	/* chip transitioned from doze to active state */
-#define I_SRESET	(1 << 30)	/* CCCR RES interrupt */
-#define I_IOE2		(1U << 31)	/* CCCR IOE2 Bit Changed */
-#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)	/* DMA Errors */
-#define I_DMA		(I_RI | I_XI | I_ERRORS)
-
-/* sbintstatus */
-#define I_SB_SERR	(1 << 8)	/* Backplane SError (write) */
-#define I_SB_RESPERR	(1 << 9)	/* Backplane Response Error (read) */
-#define I_SB_SPROMERR	(1 << 10)	/* Error accessing the sprom */
-
-/* sdioaccess */
-#define SDA_DATA_MASK	0x000000ff	/* Read/Write Data Mask */
-#define SDA_ADDR_MASK	0x000fff00	/* Read/Write Address Mask */
-#define SDA_ADDR_SHIFT	8		/* Read/Write Address Shift */
-#define SDA_WRITE	0x01000000	/* Write bit  */
-#define SDA_READ	0x00000000	/* Write bit cleared for Read */
-#define SDA_BUSY	0x80000000	/* Busy bit */
-
-/* sdioaccess-accessible register address spaces */
-#define SDA_CCCR_SPACE		0x000	/* sdioAccess CCCR register space */
-#define SDA_F1_FBR_SPACE	0x100	/* sdioAccess F1 FBR register space */
-#define SDA_F2_FBR_SPACE	0x200	/* sdioAccess F2 FBR register space */
-#define SDA_F1_REG_SPACE	0x300	/* sdioAccess F1 core-specific register space */
-
-/* SDA_F1_REG_SPACE sdioaccess-accessible F1 reg space register offsets */
-#define SDA_CHIPCONTROLDATA	0x006	/* ChipControlData */
-#define SDA_CHIPCONTROLENAB	0x007	/* ChipControlEnable */
-#define SDA_F2WATERMARK		0x008	/* Function 2 Watermark */
-#define SDA_DEVICECONTROL	0x009	/* DeviceControl */
-#define SDA_SBADDRLOW		0x00a	/* SbAddrLow */
-#define SDA_SBADDRMID		0x00b	/* SbAddrMid */
-#define SDA_SBADDRHIGH		0x00c	/* SbAddrHigh */
-#define SDA_FRAMECTRL		0x00d	/* FrameCtrl */
-#define SDA_CHIPCLOCKCSR	0x00e	/* ChipClockCSR */
-#define SDA_SDIOPULLUP		0x00f	/* SdioPullUp */
-#define SDA_SDIOWRFRAMEBCLOW	0x019	/* SdioWrFrameBCLow */
-#define SDA_SDIOWRFRAMEBCHIGH	0x01a	/* SdioWrFrameBCHigh */
-#define SDA_SDIORDFRAMEBCLOW	0x01b	/* SdioRdFrameBCLow */
-#define SDA_SDIORDFRAMEBCHIGH	0x01c	/* SdioRdFrameBCHigh */
-
-/* SDA_F2WATERMARK */
-#define SDA_F2WATERMARK_MASK	0x7f	/* F2Watermark Mask */
-
-/* SDA_SBADDRLOW */
-#define SDA_SBADDRLOW_MASK	0x80	/* SbAddrLow Mask */
-
-/* SDA_SBADDRMID */
-#define SDA_SBADDRMID_MASK	0xff	/* SbAddrMid Mask */
-
-/* SDA_SBADDRHIGH */
-#define SDA_SBADDRHIGH_MASK	0xff	/* SbAddrHigh Mask */
-
-/* SDA_FRAMECTRL */
-#define SFC_RF_TERM	(1 << 0)	/* Read Frame Terminate */
-#define SFC_WF_TERM	(1 << 1)	/* Write Frame Terminate */
-#define SFC_CRC4WOOS	(1 << 2)	/* HW reports CRC error for write out of sync */
-#define SFC_ABORTALL	(1 << 3)	/* Abort cancels all in-progress frames */
-
-/* pcmciaframectrl */
-#define PFC_RF_TERM	(1 << 0)	/* Read Frame Terminate */
-#define PFC_WF_TERM	(1 << 1)	/* Write Frame Terminate */
-
-/* intrcvlazy */
-#define	IRL_TO_MASK	0x00ffffff	/* timeout */
-#define	IRL_FC_MASK	0xff000000	/* frame count */
-#define	IRL_FC_SHIFT	24		/* frame count */
-
-/* rx header */
-typedef volatile struct {
-	uint16 len;
-	uint16 flags;
-} sdpcmd_rxh_t;
-
-/* rx header flags */
-#define RXF_CRC		0x0001		/* CRC error detected */
-#define RXF_WOOS	0x0002		/* write frame out of sync */
-#define RXF_WF_TERM	0x0004		/* write frame terminated */
-#define RXF_ABORT	0x0008		/* write frame aborted */
-#define RXF_DISCARD	(RXF_CRC | RXF_WOOS | RXF_WF_TERM | RXF_ABORT)	/* bad frame */
-
-/* HW frame tag */
-#define SDPCM_FRAMETAG_LEN	4	/* HW frametag: 2 bytes len, 2 bytes check val */
-
-#define SDPCM_HWEXT_LEN	8
-
-#endif	/* _sbsdpcmdev_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/sbsocram.h b/drivers/net/wireless/bcmdhd/include/sbsocram.h
deleted file mode 100644
index cfe12e1..0000000
--- a/drivers/net/wireless/bcmdhd/include/sbsocram.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * BCM47XX Sonics SiliconBackplane embedded ram core
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sbsocram.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_SBSOCRAM_H
-#define	_SBSOCRAM_H
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif	/* PAD */
-
-/* Memcsocram core registers */
-typedef volatile struct sbsocramregs {
-	uint32	coreinfo;
-	uint32	bwalloc;
-	uint32	extracoreinfo;
-	uint32	biststat;
-	uint32	bankidx;
-	uint32	standbyctrl;
-
-	uint32	errlogstatus;	/* rev 6 */
-	uint32	errlogaddr;	/* rev 6 */
-	/* used for patching rev 3 & 5 */
-	uint32	cambankidx;
-	uint32	cambankstandbyctrl;
-	uint32	cambankpatchctrl;
-	uint32	cambankpatchtblbaseaddr;
-	uint32	cambankcmdreg;
-	uint32	cambankdatareg;
-	uint32	cambankmaskreg;
-	uint32	PAD[1];
-	uint32	bankinfo;	/* corev 8 */
-	uint32	bankpda;
-	uint32	PAD[14];
-	uint32	extmemconfig;
-	uint32	extmemparitycsr;
-	uint32	extmemparityerrdata;
-	uint32	extmemparityerrcnt;
-	uint32	extmemwrctrlandsize;
-	uint32	PAD[84];
-	uint32	workaround;
-	uint32	pwrctl;		/* corerev >= 2 */
-	uint32	PAD[133];
-	uint32  sr_control;     /* corerev >= 15 */
-	uint32  sr_status;      /* corerev >= 15 */
-	uint32  sr_address;     /* corerev >= 15 */
-	uint32  sr_data;        /* corerev >= 15 */
-} sbsocramregs_t;
-
-#endif	/* _LANGUAGE_ASSEMBLY */
-
-/* Register offsets */
-#define	SR_COREINFO		0x00
-#define	SR_BWALLOC		0x04
-#define	SR_BISTSTAT		0x0c
-#define	SR_BANKINDEX		0x10
-#define	SR_BANKSTBYCTL		0x14
-#define SR_PWRCTL		0x1e8
-
-/* Coreinfo register */
-#define	SRCI_PT_MASK		0x00070000	/* corerev >= 6; port type[18:16] */
-#define	SRCI_PT_SHIFT		16
-/* port types : SRCI_PT_<processorPT>_<backplanePT> */
-#define SRCI_PT_OCP_OCP		0
-#define SRCI_PT_AXI_OCP		1
-#define SRCI_PT_ARM7AHB_OCP	2
-#define SRCI_PT_CM3AHB_OCP	3
-#define SRCI_PT_AXI_AXI		4
-#define SRCI_PT_AHB_AXI		5
-/* corerev >= 3 */
-#define SRCI_LSS_MASK		0x00f00000
-#define SRCI_LSS_SHIFT		20
-#define SRCI_LRS_MASK		0x0f000000
-#define SRCI_LRS_SHIFT		24
-
-/* In corerev 0, the memory size is 2 to the power of the
- * base plus 16 plus to the contents of the memsize field plus 1.
- */
-#define	SRCI_MS0_MASK		0xf
-#define SR_MS0_BASE		16
-
-/*
- * In corerev 1 the bank size is 2 ^ the bank size field plus 14,
- * the memory size is number of banks times bank size.
- * The same applies to rom size.
- */
-#define	SRCI_ROMNB_MASK		0xf000
-#define	SRCI_ROMNB_SHIFT	12
-#define	SRCI_ROMBSZ_MASK	0xf00
-#define	SRCI_ROMBSZ_SHIFT	8
-#define	SRCI_SRNB_MASK		0xf0
-#define	SRCI_SRNB_SHIFT		4
-#define	SRCI_SRBSZ_MASK		0xf
-#define	SRCI_SRBSZ_SHIFT	0
-
-#define SR_BSZ_BASE		14
-
-/* Standby control register */
-#define	SRSC_SBYOVR_MASK	0x80000000
-#define	SRSC_SBYOVR_SHIFT	31
-#define	SRSC_SBYOVRVAL_MASK	0x60000000
-#define	SRSC_SBYOVRVAL_SHIFT	29
-#define	SRSC_SBYEN_MASK		0x01000000	/* rev >= 3 */
-#define	SRSC_SBYEN_SHIFT	24
-
-/* Power control register */
-#define SRPC_PMU_STBYDIS_MASK	0x00000010	/* rev >= 3 */
-#define SRPC_PMU_STBYDIS_SHIFT	4
-#define SRPC_STBYOVRVAL_MASK	0x00000008
-#define SRPC_STBYOVRVAL_SHIFT	3
-#define SRPC_STBYOVR_MASK	0x00000007
-#define SRPC_STBYOVR_SHIFT	0
-
-/* Extra core capability register */
-#define SRECC_NUM_BANKS_MASK   0x000000F0
-#define SRECC_NUM_BANKS_SHIFT  4
-#define SRECC_BANKSIZE_MASK    0x0000000F
-#define SRECC_BANKSIZE_SHIFT   0
-
-#define SRECC_BANKSIZE(value)	 (1 << (value))
-
-/* CAM bank patch control */
-#define SRCBPC_PATCHENABLE 0x80000000
-
-#define SRP_ADDRESS   0x0001FFFC
-#define SRP_VALID     0x8000
-
-/* CAM bank command reg */
-#define SRCMD_WRITE  0x00020000
-#define SRCMD_READ   0x00010000
-#define SRCMD_DONE   0x80000000
-
-#define SRCMD_DONE_DLY	1000
-
-/* bankidx and bankinfo reg defines corerev >= 8 */
-#define SOCRAM_BANKINFO_SZMASK		0x7f
-#define SOCRAM_BANKIDX_ROM_MASK		0x100
-
-#define SOCRAM_BANKIDX_MEMTYPE_SHIFT	8
-/* socram bankinfo memtype */
-#define SOCRAM_MEMTYPE_RAM		0
-#define SOCRAM_MEMTYPE_R0M		1
-#define SOCRAM_MEMTYPE_DEVRAM		2
-
-#define	SOCRAM_BANKINFO_REG		0x40
-#define	SOCRAM_BANKIDX_REG		0x10
-#define	SOCRAM_BANKINFO_STDBY_MASK	0x400
-#define	SOCRAM_BANKINFO_STDBY_TIMER	0x800
-
-/* bankinfo rev >= 10 */
-#define SOCRAM_BANKINFO_DEVRAMSEL_SHIFT		13
-#define SOCRAM_BANKINFO_DEVRAMSEL_MASK		0x2000
-#define SOCRAM_BANKINFO_DEVRAMPRO_SHIFT		14
-#define SOCRAM_BANKINFO_DEVRAMPRO_MASK		0x4000
-#define SOCRAM_BANKINFO_SLPSUPP_SHIFT		15
-#define SOCRAM_BANKINFO_SLPSUPP_MASK		0x8000
-#define SOCRAM_BANKINFO_RETNTRAM_SHIFT		16
-#define SOCRAM_BANKINFO_RETNTRAM_MASK		0x00010000
-#define SOCRAM_BANKINFO_PDASZ_SHIFT		17
-#define SOCRAM_BANKINFO_PDASZ_MASK		0x003E0000
-#define SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT	24
-#define SOCRAM_BANKINFO_DEVRAMREMAP_MASK	0x01000000
-
-/* extracoreinfo register */
-#define SOCRAM_DEVRAMBANK_MASK		0xF000
-#define SOCRAM_DEVRAMBANK_SHIFT		12
-
-/* bank info to calculate bank size */
-#define   SOCRAM_BANKINFO_SZBASE          8192
-#define SOCRAM_BANKSIZE_SHIFT         13      /* SOCRAM_BANKINFO_SZBASE */
-
-
-#endif	/* _SBSOCRAM_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sbsysmem.h b/drivers/net/wireless/bcmdhd/include/sbsysmem.h
deleted file mode 100644
index 99a810c..0000000
--- a/drivers/net/wireless/bcmdhd/include/sbsysmem.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * SiliconBackplane System Memory core
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sbsysmem.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_SBSYSMEM_H
-#define	_SBSYSMEM_H
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif	/* PAD */
-
-/* sysmem core registers */
-typedef volatile struct sysmemregs {
-	uint32	coreinfo;
-	uint32	bwalloc;
-	uint32	extracoreinfo;
-	uint32	biststat;
-	uint32	bankidx;
-	uint32	standbyctrl;
-
-	uint32	errlogstatus;
-	uint32	errlogaddr;
-
-	uint32	cambankidx;
-	uint32	cambankstandbyctrl;
-	uint32	cambankpatchctrl;
-	uint32	cambankpatchtblbaseaddr;
-	uint32	cambankcmdreg;
-	uint32	cambankdatareg;
-	uint32	cambankmaskreg;
-	uint32	PAD[1];
-	uint32	bankinfo;
-	uint32	PAD[15];
-	uint32	extmemconfig;
-	uint32	extmemparitycsr;
-	uint32	extmemparityerrdata;
-	uint32	extmemparityerrcnt;
-	uint32	extmemwrctrlandsize;
-	uint32	PAD[84];
-	uint32	workaround;
-	uint32	pwrctl;
-	uint32	PAD[133];
-	uint32  sr_control;
-	uint32  sr_status;
-	uint32  sr_address;
-	uint32  sr_data;
-} sysmemregs_t;
-
-#endif	/* _LANGUAGE_ASSEMBLY */
-
-/* Register offsets */
-#define	SR_COREINFO		0x00
-#define	SR_BWALLOC		0x04
-#define	SR_BISTSTAT		0x0c
-#define	SR_BANKINDEX		0x10
-#define	SR_BANKSTBYCTL		0x14
-#define SR_PWRCTL		0x1e8
-
-/* Coreinfo register */
-#define	SRCI_PT_MASK		0x00070000	/* port type[18:16] */
-#define	SRCI_PT_SHIFT		16
-/* port types : SRCI_PT_<processorPT>_<backplanePT> */
-#define SRCI_PT_OCP_OCP		0
-#define SRCI_PT_AXI_OCP		1
-#define SRCI_PT_ARM7AHB_OCP	2
-#define SRCI_PT_CM3AHB_OCP	3
-#define SRCI_PT_AXI_AXI		4
-#define SRCI_PT_AHB_AXI		5
-
-#define SRCI_LSS_MASK		0x00f00000
-#define SRCI_LSS_SHIFT		20
-#define SRCI_LRS_MASK		0x0f000000
-#define SRCI_LRS_SHIFT		24
-
-/* In corerev 0, the memory size is 2 to the power of the
- * base plus 16 plus to the contents of the memsize field plus 1.
- */
-#define	SRCI_MS0_MASK		0xf
-#define SR_MS0_BASE		16
-
-/*
- * In corerev 1 the bank size is 2 ^ the bank size field plus 14,
- * the memory size is number of banks times bank size.
- * The same applies to rom size.
- */
-#define	SRCI_ROMNB_MASK		0xf000
-#define	SRCI_ROMNB_SHIFT	12
-#define	SRCI_ROMBSZ_MASK	0xf00
-#define	SRCI_ROMBSZ_SHIFT	8
-#define	SRCI_SRNB_MASK		0xf0
-#define	SRCI_SRNB_SHIFT		4
-#define	SRCI_SRBSZ_MASK		0xf
-#define	SRCI_SRBSZ_SHIFT	0
-
-#define SR_BSZ_BASE		14
-
-/* Standby control register */
-#define	SRSC_SBYOVR_MASK	0x80000000
-#define	SRSC_SBYOVR_SHIFT	31
-#define	SRSC_SBYOVRVAL_MASK	0x60000000
-#define	SRSC_SBYOVRVAL_SHIFT	29
-#define	SRSC_SBYEN_MASK		0x01000000
-#define	SRSC_SBYEN_SHIFT	24
-
-/* Power control register */
-#define SRPC_PMU_STBYDIS_MASK	0x00000010
-#define SRPC_PMU_STBYDIS_SHIFT	4
-#define SRPC_STBYOVRVAL_MASK	0x00000008
-#define SRPC_STBYOVRVAL_SHIFT	3
-#define SRPC_STBYOVR_MASK	0x00000007
-#define SRPC_STBYOVR_SHIFT	0
-
-/* Extra core capability register */
-#define SRECC_NUM_BANKS_MASK   0x000000F0
-#define SRECC_NUM_BANKS_SHIFT  4
-#define SRECC_BANKSIZE_MASK    0x0000000F
-#define SRECC_BANKSIZE_SHIFT   0
-
-#define SRECC_BANKSIZE(value)	 (1 << (value))
-
-/* CAM bank patch control */
-#define SRCBPC_PATCHENABLE 0x80000000
-
-#define SRP_ADDRESS   0x0001FFFC
-#define SRP_VALID     0x8000
-
-/* CAM bank command reg */
-#define SRCMD_WRITE  0x00020000
-#define SRCMD_READ   0x00010000
-#define SRCMD_DONE   0x80000000
-
-#define SRCMD_DONE_DLY	1000
-
-/* bankidx and bankinfo reg defines */
-#define SYSMEM_BANKINFO_SZMASK		0x7f
-#define SYSMEM_BANKIDX_ROM_MASK		0x100
-
-#define SYSMEM_BANKIDX_MEMTYPE_SHIFT	8
-/* sysmem bankinfo memtype */
-#define SYSMEM_MEMTYPE_RAM		0
-#define SYSMEM_MEMTYPE_R0M		1
-#define SYSMEM_MEMTYPE_DEVRAM		2
-
-#define	SYSMEM_BANKINFO_REG		0x40
-#define	SYSMEM_BANKIDX_REG		0x10
-#define	SYSMEM_BANKINFO_STDBY_MASK	0x400
-#define	SYSMEM_BANKINFO_STDBY_TIMER	0x800
-
-#define SYSMEM_BANKINFO_DEVRAMSEL_SHIFT		13
-#define SYSMEM_BANKINFO_DEVRAMSEL_MASK		0x2000
-#define SYSMEM_BANKINFO_DEVRAMPRO_SHIFT		14
-#define SYSMEM_BANKINFO_DEVRAMPRO_MASK		0x4000
-#define SYSMEM_BANKINFO_SLPSUPP_SHIFT		15
-#define SYSMEM_BANKINFO_SLPSUPP_MASK		0x8000
-#define SYSMEM_BANKINFO_RETNTRAM_SHIFT		16
-#define SYSMEM_BANKINFO_RETNTRAM_MASK		0x00010000
-#define SYSMEM_BANKINFO_PDASZ_SHIFT		17
-#define SYSMEM_BANKINFO_PDASZ_MASK		0x003E0000
-#define SYSMEM_BANKINFO_DEVRAMREMAP_SHIFT	24
-#define SYSMEM_BANKINFO_DEVRAMREMAP_MASK	0x01000000
-
-/* extracoreinfo register */
-#define SYSMEM_DEVRAMBANK_MASK		0xF000
-#define SYSMEM_DEVRAMBANK_SHIFT		12
-
-/* bank info to calculate bank size */
-#define	SYSMEM_BANKINFO_SZBASE          8192
-#define SYSMEM_BANKSIZE_SHIFT		13      /* SYSMEM_BANKINFO_SZBASE */
-
-#endif	/* _SBSYSMEM_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sdio.h b/drivers/net/wireless/bcmdhd/include/sdio.h
deleted file mode 100644
index ca53afb..0000000
--- a/drivers/net/wireless/bcmdhd/include/sdio.h
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * SDIO spec header file
- * Protocol and standard (common) device definitions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sdio.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_SDIO_H
-#define	_SDIO_H
-
-#ifdef BCMSDIO
-
-/* CCCR structure for function 0 */
-typedef volatile struct {
-	uint8	cccr_sdio_rev;		/* RO, cccr and sdio revision */
-	uint8	sd_rev;			/* RO, sd spec revision */
-	uint8	io_en;			/* I/O enable */
-	uint8	io_rdy;			/* I/O ready reg */
-	uint8	intr_ctl;		/* Master and per function interrupt enable control */
-	uint8	intr_status;		/* RO, interrupt pending status */
-	uint8	io_abort;		/* read/write abort or reset all functions */
-	uint8	bus_inter;		/* bus interface control */
-	uint8	capability;		/* RO, card capability */
-
-	uint8	cis_base_low;		/* 0x9 RO, common CIS base address, LSB */
-	uint8	cis_base_mid;
-	uint8	cis_base_high;		/* 0xB RO, common CIS base address, MSB */
-
-	/* suspend/resume registers */
-	uint8	bus_suspend;		/* 0xC */
-	uint8	func_select;		/* 0xD */
-	uint8	exec_flag;		/* 0xE */
-	uint8	ready_flag;		/* 0xF */
-
-	uint8	fn0_blk_size[2];	/* 0x10(LSB), 0x11(MSB) */
-
-	uint8	power_control;		/* 0x12 (SDIO version 1.10) */
-
-	uint8	speed_control;		/* 0x13 */
-} sdio_regs_t;
-
-/* SDIO Device CCCR offsets */
-#define SDIOD_CCCR_REV			0x00
-#define SDIOD_CCCR_SDREV		0x01
-#define SDIOD_CCCR_IOEN			0x02
-#define SDIOD_CCCR_IORDY		0x03
-#define SDIOD_CCCR_INTEN		0x04
-#define SDIOD_CCCR_INTPEND		0x05
-#define SDIOD_CCCR_IOABORT		0x06
-#define SDIOD_CCCR_BICTRL		0x07
-#define SDIOD_CCCR_CAPABLITIES		0x08
-#define SDIOD_CCCR_CISPTR_0		0x09
-#define SDIOD_CCCR_CISPTR_1		0x0A
-#define SDIOD_CCCR_CISPTR_2		0x0B
-#define SDIOD_CCCR_BUSSUSP		0x0C
-#define SDIOD_CCCR_FUNCSEL		0x0D
-#define SDIOD_CCCR_EXECFLAGS		0x0E
-#define SDIOD_CCCR_RDYFLAGS		0x0F
-#define SDIOD_CCCR_BLKSIZE_0		0x10
-#define SDIOD_CCCR_BLKSIZE_1		0x11
-#define SDIOD_CCCR_POWER_CONTROL	0x12
-#define SDIOD_CCCR_SPEED_CONTROL	0x13
-#define SDIOD_CCCR_UHSI_SUPPORT		0x14
-#define SDIOD_CCCR_DRIVER_STRENGTH	0x15
-#define SDIOD_CCCR_INTR_EXTN		0x16
-
-/* Broadcom extensions (corerev >= 1) */
-#define SDIOD_CCCR_BRCM_CARDCAP		0xf0
-#define SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT	0x02
-#define SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT	0x04
-#define SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC	0x08
-#define SDIOD_CCCR_BRCM_CARDCTL			0xf1
-#define SDIOD_CCCR_BRCM_SEPINT			0xf2
-
-/* cccr_sdio_rev */
-#define SDIO_REV_SDIOID_MASK	0xf0	/* SDIO spec revision number */
-#define SDIO_REV_CCCRID_MASK	0x0f	/* CCCR format version number */
-#define SDIO_SPEC_VERSION_3_0	0x40	/* SDIO spec version 3.0 */
-
-/* sd_rev */
-#define SD_REV_PHY_MASK		0x0f	/* SD format version number */
-
-/* io_en */
-#define SDIO_FUNC_ENABLE_1	0x02	/* function 1 I/O enable */
-#define SDIO_FUNC_ENABLE_2	0x04	/* function 2 I/O enable */
-
-/* io_rdys */
-#define SDIO_FUNC_READY_1	0x02	/* function 1 I/O ready */
-#define SDIO_FUNC_READY_2	0x04	/* function 2 I/O ready */
-
-/* intr_ctl */
-#define INTR_CTL_MASTER_EN	0x1	/* interrupt enable master */
-#define INTR_CTL_FUNC1_EN	0x2	/* interrupt enable for function 1 */
-#define INTR_CTL_FUNC2_EN	0x4	/* interrupt enable for function 2 */
-
-/* intr_status */
-#define INTR_STATUS_FUNC1	0x2	/* interrupt pending for function 1 */
-#define INTR_STATUS_FUNC2	0x4	/* interrupt pending for function 2 */
-
-/* io_abort */
-#define IO_ABORT_RESET_ALL	0x08	/* I/O card reset */
-#define IO_ABORT_FUNC_MASK	0x07	/* abort selction: function x */
-
-/* bus_inter */
-#define BUS_CARD_DETECT_DIS	0x80	/* Card Detect disable */
-#define BUS_SPI_CONT_INTR_CAP	0x40	/* support continuous SPI interrupt */
-#define BUS_SPI_CONT_INTR_EN	0x20	/* continuous SPI interrupt enable */
-#define BUS_SD_DATA_WIDTH_MASK	0x03	/* bus width mask */
-#define BUS_SD_DATA_WIDTH_4BIT	0x02	/* bus width 4-bit mode */
-#define BUS_SD_DATA_WIDTH_1BIT	0x00	/* bus width 1-bit mode */
-
-/* capability */
-#define SDIO_CAP_4BLS		0x80	/* 4-bit support for low speed card */
-#define SDIO_CAP_LSC		0x40	/* low speed card */
-#define SDIO_CAP_E4MI		0x20	/* enable interrupt between block of data in 4-bit mode */
-#define SDIO_CAP_S4MI		0x10	/* support interrupt between block of data in 4-bit mode */
-#define SDIO_CAP_SBS		0x08	/* support suspend/resume */
-#define SDIO_CAP_SRW		0x04	/* support read wait */
-#define SDIO_CAP_SMB		0x02	/* support multi-block transfer */
-#define SDIO_CAP_SDC		0x01	/* Support Direct commands during multi-byte transfer */
-
-/* power_control */
-#define SDIO_POWER_SMPC		0x01	/* supports master power control (RO) */
-#define SDIO_POWER_EMPC		0x02	/* enable master power control (allow > 200mA) (RW) */
-
-/* speed_control (control device entry into high-speed clocking mode) */
-#define SDIO_SPEED_SHS		0x01	/* supports high-speed [clocking] mode (RO) */
-#define SDIO_SPEED_EHS		0x02	/* enable high-speed [clocking] mode (RW) */
-#define SDIO_SPEED_UHSI_DDR50	   0x08
-
-/* for setting bus speed in card: 0x13h */
-#define SDIO_BUS_SPEED_UHSISEL_M	BITFIELD_MASK(3)
-#define SDIO_BUS_SPEED_UHSISEL_S	1
-
-/* for getting bus speed cap in card: 0x14h */
-#define SDIO_BUS_SPEED_UHSICAP_M	BITFIELD_MASK(3)
-#define SDIO_BUS_SPEED_UHSICAP_S	0
-
-/* for getting driver type CAP in card: 0x15h */
-#define SDIO_BUS_DRVR_TYPE_CAP_M	BITFIELD_MASK(3)
-#define SDIO_BUS_DRVR_TYPE_CAP_S	0
-
-/* for setting driver type selection in card: 0x15h */
-#define SDIO_BUS_DRVR_TYPE_SEL_M	BITFIELD_MASK(2)
-#define SDIO_BUS_DRVR_TYPE_SEL_S	4
-
-/* for getting async int support in card: 0x16h */
-#define SDIO_BUS_ASYNCINT_CAP_M	BITFIELD_MASK(1)
-#define SDIO_BUS_ASYNCINT_CAP_S	0
-
-/* for setting async int selection in card: 0x16h */
-#define SDIO_BUS_ASYNCINT_SEL_M	BITFIELD_MASK(1)
-#define SDIO_BUS_ASYNCINT_SEL_S	1
-
-/* brcm sepint */
-#define SDIO_SEPINT_MASK	0x01	/* route sdpcmdev intr onto separate pad (chip-specific) */
-#define SDIO_SEPINT_OE		0x02	/* 1 asserts output enable for above pad */
-#define SDIO_SEPINT_ACT_HI	0x04	/* use active high interrupt level instead of active low */
-
-/* FBR structure for function 1-7, FBR addresses and register offsets */
-typedef volatile struct {
-	uint8	devctr;			/* device interface, CSA control */
-	uint8	ext_dev;		/* extended standard I/O device type code */
-	uint8	pwr_sel;		/* power selection support */
-	uint8	PAD[6];			/* reserved */
-
-	uint8	cis_low;		/* CIS LSB */
-	uint8	cis_mid;
-	uint8	cis_high;		/* CIS MSB */
-	uint8	csa_low;		/* code storage area, LSB */
-	uint8	csa_mid;
-	uint8	csa_high;		/* code storage area, MSB */
-	uint8	csa_dat_win;		/* data access window to function */
-
-	uint8	fnx_blk_size[2];	/* block size, little endian */
-} sdio_fbr_t;
-
-/* Maximum number of I/O funcs */
-#define SDIOD_MAX_FUNCS			8
-#define SDIOD_MAX_IOFUNCS		7
-
-/* SDIO Device FBR Start Address  */
-#define SDIOD_FBR_STARTADDR		0x100
-
-/* SDIO Device FBR Size */
-#define SDIOD_FBR_SIZE			0x100
-
-/* Macro to calculate FBR register base */
-#define SDIOD_FBR_BASE(n)		((n) * 0x100)
-
-/* Function register offsets */
-#define SDIOD_FBR_DEVCTR		0x00	/* basic info for function */
-#define SDIOD_FBR_EXT_DEV		0x01	/* extended I/O device code */
-#define SDIOD_FBR_PWR_SEL		0x02	/* power selection bits */
-
-/* SDIO Function CIS ptr offset */
-#define SDIOD_FBR_CISPTR_0		0x09
-#define SDIOD_FBR_CISPTR_1		0x0A
-#define SDIOD_FBR_CISPTR_2		0x0B
-
-/* Code Storage Area pointer */
-#define SDIOD_FBR_CSA_ADDR_0		0x0C
-#define SDIOD_FBR_CSA_ADDR_1		0x0D
-#define SDIOD_FBR_CSA_ADDR_2		0x0E
-#define SDIOD_FBR_CSA_DATA		0x0F
-
-/* SDIO Function I/O Block Size */
-#define SDIOD_FBR_BLKSIZE_0		0x10
-#define SDIOD_FBR_BLKSIZE_1		0x11
-
-/* devctr */
-#define SDIOD_FBR_DEVCTR_DIC	0x0f	/* device interface code */
-#define SDIOD_FBR_DECVTR_CSA	0x40	/* CSA support flag */
-#define SDIOD_FBR_DEVCTR_CSA_EN	0x80	/* CSA enabled */
-/* interface codes */
-#define SDIOD_DIC_NONE		0	/* SDIO standard interface is not supported */
-#define SDIOD_DIC_UART		1
-#define SDIOD_DIC_BLUETOOTH_A	2
-#define SDIOD_DIC_BLUETOOTH_B	3
-#define SDIOD_DIC_GPS		4
-#define SDIOD_DIC_CAMERA	5
-#define SDIOD_DIC_PHS		6
-#define SDIOD_DIC_WLAN		7
-#define SDIOD_DIC_EXT		0xf	/* extended device interface, read ext_dev register */
-
-/* pwr_sel */
-#define SDIOD_PWR_SEL_SPS	0x01	/* supports power selection */
-#define SDIOD_PWR_SEL_EPS	0x02	/* enable power selection (low-current mode) */
-
-/* misc defines */
-#define SDIO_FUNC_0		0
-#define SDIO_FUNC_1		1
-#define SDIO_FUNC_2		2
-#define SDIO_FUNC_3		3
-#define SDIO_FUNC_4		4
-#define SDIO_FUNC_5		5
-#define SDIO_FUNC_6		6
-#define SDIO_FUNC_7		7
-
-#define SD_CARD_TYPE_UNKNOWN	0	/* bad type or unrecognized */
-#define SD_CARD_TYPE_IO		1	/* IO only card */
-#define SD_CARD_TYPE_MEMORY	2	/* memory only card */
-#define SD_CARD_TYPE_COMBO	3	/* IO and memory combo card */
-
-#define SDIO_MAX_BLOCK_SIZE	2048	/* maximum block size for block mode operation */
-#define SDIO_MIN_BLOCK_SIZE	1	/* minimum block size for block mode operation */
-
-/* Card registers: status bit position */
-#define CARDREG_STATUS_BIT_OUTOFRANGE		31
-#define CARDREG_STATUS_BIT_COMCRCERROR		23
-#define CARDREG_STATUS_BIT_ILLEGALCOMMAND	22
-#define CARDREG_STATUS_BIT_ERROR		19
-#define CARDREG_STATUS_BIT_IOCURRENTSTATE3	12
-#define CARDREG_STATUS_BIT_IOCURRENTSTATE2	11
-#define CARDREG_STATUS_BIT_IOCURRENTSTATE1	10
-#define CARDREG_STATUS_BIT_IOCURRENTSTATE0	9
-#define CARDREG_STATUS_BIT_FUN_NUM_ERROR	4
-
-
-
-#define SD_CMD_GO_IDLE_STATE		0	/* mandatory for SDIO */
-#define SD_CMD_SEND_OPCOND		1
-#define SD_CMD_MMC_SET_RCA		3
-#define SD_CMD_IO_SEND_OP_COND		5	/* mandatory for SDIO */
-#define SD_CMD_SELECT_DESELECT_CARD	7
-#define SD_CMD_SEND_CSD			9
-#define SD_CMD_SEND_CID			10
-#define SD_CMD_STOP_TRANSMISSION	12
-#define SD_CMD_SEND_STATUS		13
-#define SD_CMD_GO_INACTIVE_STATE	15
-#define SD_CMD_SET_BLOCKLEN		16
-#define SD_CMD_READ_SINGLE_BLOCK	17
-#define SD_CMD_READ_MULTIPLE_BLOCK	18
-#define SD_CMD_WRITE_BLOCK		24
-#define SD_CMD_WRITE_MULTIPLE_BLOCK	25
-#define SD_CMD_PROGRAM_CSD		27
-#define SD_CMD_SET_WRITE_PROT		28
-#define SD_CMD_CLR_WRITE_PROT		29
-#define SD_CMD_SEND_WRITE_PROT		30
-#define SD_CMD_ERASE_WR_BLK_START	32
-#define SD_CMD_ERASE_WR_BLK_END		33
-#define SD_CMD_ERASE			38
-#define SD_CMD_LOCK_UNLOCK		42
-#define SD_CMD_IO_RW_DIRECT		52	/* mandatory for SDIO */
-#define SD_CMD_IO_RW_EXTENDED		53	/* mandatory for SDIO */
-#define SD_CMD_APP_CMD			55
-#define SD_CMD_GEN_CMD			56
-#define SD_CMD_READ_OCR			58
-#define SD_CMD_CRC_ON_OFF		59	/* mandatory for SDIO */
-#define SD_ACMD_SD_STATUS		13
-#define SD_ACMD_SEND_NUM_WR_BLOCKS	22
-#define SD_ACMD_SET_WR_BLOCK_ERASE_CNT	23
-#define SD_ACMD_SD_SEND_OP_COND		41
-#define SD_ACMD_SET_CLR_CARD_DETECT	42
-#define SD_ACMD_SEND_SCR		51
-
-/* argument for SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED */
-#define SD_IO_OP_READ		0   /* Read_Write: Read */
-#define SD_IO_OP_WRITE		1   /* Read_Write: Write */
-#define SD_IO_RW_NORMAL		0   /* no RAW */
-#define SD_IO_RW_RAW		1   /* RAW */
-#define SD_IO_BYTE_MODE		0   /* Byte Mode */
-#define SD_IO_BLOCK_MODE	1   /* BlockMode */
-#define SD_IO_FIXED_ADDRESS	0   /* fix Address */
-#define SD_IO_INCREMENT_ADDRESS	1   /* IncrementAddress */
-
-/* build SD_CMD_IO_RW_DIRECT Argument */
-#define SDIO_IO_RW_DIRECT_ARG(rw, raw, func, addr, data) \
-	((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((raw) & 1) << 27) | \
-	 (((addr) & 0x1FFFF) << 9) | ((data) & 0xFF))
-
-/* build SD_CMD_IO_RW_EXTENDED Argument */
-#define SDIO_IO_RW_EXTENDED_ARG(rw, blk, func, addr, inc_addr, count) \
-	((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((blk) & 1) << 27) | \
-	 (((inc_addr) & 1) << 26) | (((addr) & 0x1FFFF) << 9) | ((count) & 0x1FF))
-
-/* SDIO response parameters */
-#define SD_RSP_NO_NONE			0
-#define SD_RSP_NO_1			1
-#define SD_RSP_NO_2			2
-#define SD_RSP_NO_3			3
-#define SD_RSP_NO_4			4
-#define SD_RSP_NO_5			5
-#define SD_RSP_NO_6			6
-
-	/* Modified R6 response (to CMD3) */
-#define SD_RSP_MR6_COM_CRC_ERROR	0x8000
-#define SD_RSP_MR6_ILLEGAL_COMMAND	0x4000
-#define SD_RSP_MR6_ERROR		0x2000
-
-	/* Modified R1 in R4 Response (to CMD5) */
-#define SD_RSP_MR1_SBIT			0x80
-#define SD_RSP_MR1_PARAMETER_ERROR	0x40
-#define SD_RSP_MR1_RFU5			0x20
-#define SD_RSP_MR1_FUNC_NUM_ERROR	0x10
-#define SD_RSP_MR1_COM_CRC_ERROR	0x08
-#define SD_RSP_MR1_ILLEGAL_COMMAND	0x04
-#define SD_RSP_MR1_RFU1			0x02
-#define SD_RSP_MR1_IDLE_STATE		0x01
-
-	/* R5 response (to CMD52 and CMD53) */
-#define SD_RSP_R5_COM_CRC_ERROR		0x80
-#define SD_RSP_R5_ILLEGAL_COMMAND	0x40
-#define SD_RSP_R5_IO_CURRENTSTATE1	0x20
-#define SD_RSP_R5_IO_CURRENTSTATE0	0x10
-#define SD_RSP_R5_ERROR			0x08
-#define SD_RSP_R5_RFU			0x04
-#define SD_RSP_R5_FUNC_NUM_ERROR	0x02
-#define SD_RSP_R5_OUT_OF_RANGE		0x01
-
-#define SD_RSP_R5_ERRBITS		0xCB
-
-
-/* ------------------------------------------------
- *  SDIO Commands and responses
- *
- *  I/O only commands are:
- *      CMD0, CMD3, CMD5, CMD7, CMD14, CMD15, CMD52, CMD53
- * ------------------------------------------------
- */
-
-/* SDIO Commands */
-#define SDIOH_CMD_0		0
-#define SDIOH_CMD_3		3
-#define SDIOH_CMD_5		5
-#define SDIOH_CMD_7		7
-#define SDIOH_CMD_11		11
-#define SDIOH_CMD_14		14
-#define SDIOH_CMD_15		15
-#define SDIOH_CMD_19		19
-#define SDIOH_CMD_52		52
-#define SDIOH_CMD_53		53
-#define SDIOH_CMD_59		59
-
-/* SDIO Command Responses */
-#define SDIOH_RSP_NONE		0
-#define SDIOH_RSP_R1		1
-#define SDIOH_RSP_R2		2
-#define SDIOH_RSP_R3		3
-#define SDIOH_RSP_R4		4
-#define SDIOH_RSP_R5		5
-#define SDIOH_RSP_R6		6
-
-/*
- *  SDIO Response Error flags
- */
-#define SDIOH_RSP5_ERROR_FLAGS	0xCB
-
-/* ------------------------------------------------
- * SDIO Command structures. I/O only commands are:
- *
- * 	CMD0, CMD3, CMD5, CMD7, CMD15, CMD52, CMD53
- * ------------------------------------------------
- */
-
-#define CMD5_OCR_M		BITFIELD_MASK(24)
-#define CMD5_OCR_S		0
-
-#define CMD5_S18R_M		BITFIELD_MASK(1)
-#define CMD5_S18R_S		24
-
-#define CMD7_RCA_M		BITFIELD_MASK(16)
-#define CMD7_RCA_S		16
-
-#define CMD14_RCA_M		BITFIELD_MASK(16)
-#define CMD14_RCA_S		16
-#define CMD14_SLEEP_M		BITFIELD_MASK(1)
-#define CMD14_SLEEP_S		15
-
-#define CMD_15_RCA_M		BITFIELD_MASK(16)
-#define CMD_15_RCA_S		16
-
-#define CMD52_DATA_M		BITFIELD_MASK(8)  /* Bits [7:0]    - Write Data/Stuff bits of CMD52
-						   */
-#define CMD52_DATA_S		0
-#define CMD52_REG_ADDR_M	BITFIELD_MASK(17) /* Bits [25:9]   - register address */
-#define CMD52_REG_ADDR_S	9
-#define CMD52_RAW_M		BITFIELD_MASK(1)  /* Bit  27       - Read after Write flag */
-#define CMD52_RAW_S		27
-#define CMD52_FUNCTION_M	BITFIELD_MASK(3)  /* Bits [30:28]  - Function number */
-#define CMD52_FUNCTION_S	28
-#define CMD52_RW_FLAG_M		BITFIELD_MASK(1)  /* Bit  31       - R/W flag */
-#define CMD52_RW_FLAG_S		31
-
-
-#define CMD53_BYTE_BLK_CNT_M	BITFIELD_MASK(9) /* Bits [8:0]     - Byte/Block Count of CMD53 */
-#define CMD53_BYTE_BLK_CNT_S	0
-#define CMD53_REG_ADDR_M	BITFIELD_MASK(17) /* Bits [25:9]   - register address */
-#define CMD53_REG_ADDR_S	9
-#define CMD53_OP_CODE_M		BITFIELD_MASK(1)  /* Bit  26       - R/W Operation Code */
-#define CMD53_OP_CODE_S		26
-#define CMD53_BLK_MODE_M	BITFIELD_MASK(1)  /* Bit  27       - Block Mode */
-#define CMD53_BLK_MODE_S	27
-#define CMD53_FUNCTION_M	BITFIELD_MASK(3)  /* Bits [30:28]  - Function number */
-#define CMD53_FUNCTION_S	28
-#define CMD53_RW_FLAG_M		BITFIELD_MASK(1)  /* Bit  31       - R/W flag */
-#define CMD53_RW_FLAG_S		31
-
-/* ------------------------------------------------------
- * SDIO Command Response structures for SD1 and SD4 modes
- *  -----------------------------------------------------
- */
-#define RSP4_IO_OCR_M		BITFIELD_MASK(24) /* Bits [23:0]  - Card's OCR Bits [23:0] */
-#define RSP4_IO_OCR_S		0
-
-#define RSP4_S18A_M			BITFIELD_MASK(1) /* Bits [23:0]  - Card's OCR Bits [23:0] */
-#define RSP4_S18A_S			24
-
-#define RSP4_STUFF_M		BITFIELD_MASK(3)  /* Bits [26:24] - Stuff bits */
-#define RSP4_STUFF_S		24
-#define RSP4_MEM_PRESENT_M	BITFIELD_MASK(1)  /* Bit  27      - Memory present */
-#define RSP4_MEM_PRESENT_S	27
-#define RSP4_NUM_FUNCS_M	BITFIELD_MASK(3)  /* Bits [30:28] - Number of I/O funcs */
-#define RSP4_NUM_FUNCS_S	28
-#define RSP4_CARD_READY_M	BITFIELD_MASK(1)  /* Bit  31      - SDIO card ready */
-#define RSP4_CARD_READY_S	31
-
-#define RSP6_STATUS_M		BITFIELD_MASK(16) /* Bits [15:0]  - Card status bits [19,22,23,12:0]
-						   */
-#define RSP6_STATUS_S		0
-#define RSP6_IO_RCA_M		BITFIELD_MASK(16) /* Bits [31:16] - RCA bits[31-16] */
-#define RSP6_IO_RCA_S		16
-
-#define RSP1_AKE_SEQ_ERROR_M	BITFIELD_MASK(1)  /* Bit 3       - Authentication seq error */
-#define RSP1_AKE_SEQ_ERROR_S	3
-#define RSP1_APP_CMD_M		BITFIELD_MASK(1)  /* Bit 5       - Card expects ACMD */
-#define RSP1_APP_CMD_S		5
-#define RSP1_READY_FOR_DATA_M	BITFIELD_MASK(1)  /* Bit 8       - Ready for data (buff empty) */
-#define RSP1_READY_FOR_DATA_S	8
-#define RSP1_CURR_STATE_M	BITFIELD_MASK(4)  /* Bits [12:9] - State of card
-						   * when Cmd was received
-						   */
-#define RSP1_CURR_STATE_S	9
-#define RSP1_EARSE_RESET_M	BITFIELD_MASK(1)  /* Bit 13   - Erase seq cleared */
-#define RSP1_EARSE_RESET_S	13
-#define RSP1_CARD_ECC_DISABLE_M	BITFIELD_MASK(1)  /* Bit 14   - Card ECC disabled */
-#define RSP1_CARD_ECC_DISABLE_S	14
-#define RSP1_WP_ERASE_SKIP_M	BITFIELD_MASK(1)  /* Bit 15   - Partial blocks erased due to W/P */
-#define RSP1_WP_ERASE_SKIP_S	15
-#define RSP1_CID_CSD_OVERW_M	BITFIELD_MASK(1)  /* Bit 16   - Illegal write to CID or R/O bits
-						   * of CSD
-						   */
-#define RSP1_CID_CSD_OVERW_S	16
-#define RSP1_ERROR_M		BITFIELD_MASK(1)  /* Bit 19   - General/Unknown error */
-#define RSP1_ERROR_S		19
-#define RSP1_CC_ERROR_M		BITFIELD_MASK(1)  /* Bit 20   - Internal Card Control error */
-#define RSP1_CC_ERROR_S		20
-#define RSP1_CARD_ECC_FAILED_M	BITFIELD_MASK(1)  /* Bit 21   - Card internal ECC failed
-						   * to correct data
-						   */
-#define RSP1_CARD_ECC_FAILED_S	21
-#define RSP1_ILLEGAL_CMD_M	BITFIELD_MASK(1)  /* Bit 22   - Cmd not legal for the card state */
-#define RSP1_ILLEGAL_CMD_S	22
-#define RSP1_COM_CRC_ERROR_M	BITFIELD_MASK(1)  /* Bit 23   - CRC check of previous command failed
-						   */
-#define RSP1_COM_CRC_ERROR_S	23
-#define RSP1_LOCK_UNLOCK_FAIL_M	BITFIELD_MASK(1)  /* Bit 24   - Card lock-unlock Cmd Seq error */
-#define RSP1_LOCK_UNLOCK_FAIL_S	24
-#define RSP1_CARD_LOCKED_M	BITFIELD_MASK(1)  /* Bit 25   - Card locked by the host */
-#define RSP1_CARD_LOCKED_S	25
-#define RSP1_WP_VIOLATION_M	BITFIELD_MASK(1)  /* Bit 26   - Attempt to program
-						   * write-protected blocks
-						   */
-#define RSP1_WP_VIOLATION_S	26
-#define RSP1_ERASE_PARAM_M	BITFIELD_MASK(1)  /* Bit 27   - Invalid erase blocks */
-#define RSP1_ERASE_PARAM_S	27
-#define RSP1_ERASE_SEQ_ERR_M	BITFIELD_MASK(1)  /* Bit 28   - Erase Cmd seq error */
-#define RSP1_ERASE_SEQ_ERR_S	28
-#define RSP1_BLK_LEN_ERR_M	BITFIELD_MASK(1)  /* Bit 29   - Block length error */
-#define RSP1_BLK_LEN_ERR_S	29
-#define RSP1_ADDR_ERR_M		BITFIELD_MASK(1)  /* Bit 30   - Misaligned address */
-#define RSP1_ADDR_ERR_S		30
-#define RSP1_OUT_OF_RANGE_M	BITFIELD_MASK(1)  /* Bit 31   - Cmd arg was out of range */
-#define RSP1_OUT_OF_RANGE_S	31
-
-
-#define RSP5_DATA_M		BITFIELD_MASK(8)  /* Bits [0:7]   - data */
-#define RSP5_DATA_S		0
-#define RSP5_FLAGS_M		BITFIELD_MASK(8)  /* Bit  [15:8]  - Rsp flags */
-#define RSP5_FLAGS_S		8
-#define RSP5_STUFF_M		BITFIELD_MASK(16) /* Bits [31:16] - Stuff bits */
-#define RSP5_STUFF_S		16
-
-/* ----------------------------------------------
- * SDIO Command Response structures for SPI mode
- * ----------------------------------------------
- */
-#define SPIRSP4_IO_OCR_M	BITFIELD_MASK(16) /* Bits [15:0]    - Card's OCR Bits [23:8] */
-#define SPIRSP4_IO_OCR_S	0
-#define SPIRSP4_STUFF_M		BITFIELD_MASK(3)  /* Bits [18:16]   - Stuff bits */
-#define SPIRSP4_STUFF_S		16
-#define SPIRSP4_MEM_PRESENT_M	BITFIELD_MASK(1)  /* Bit  19        - Memory present */
-#define SPIRSP4_MEM_PRESENT_S	19
-#define SPIRSP4_NUM_FUNCS_M	BITFIELD_MASK(3)  /* Bits [22:20]   - Number of I/O funcs */
-#define SPIRSP4_NUM_FUNCS_S	20
-#define SPIRSP4_CARD_READY_M	BITFIELD_MASK(1)  /* Bit  23        - SDIO card ready */
-#define SPIRSP4_CARD_READY_S	23
-#define SPIRSP4_IDLE_STATE_M	BITFIELD_MASK(1)  /* Bit  24        - idle state */
-#define SPIRSP4_IDLE_STATE_S	24
-#define SPIRSP4_ILLEGAL_CMD_M	BITFIELD_MASK(1)  /* Bit  26        - Illegal Cmd error */
-#define SPIRSP4_ILLEGAL_CMD_S	26
-#define SPIRSP4_COM_CRC_ERROR_M	BITFIELD_MASK(1)  /* Bit  27        - COM CRC error */
-#define SPIRSP4_COM_CRC_ERROR_S	27
-#define SPIRSP4_FUNC_NUM_ERROR_M	BITFIELD_MASK(1)  /* Bit  28        - Function number error
-							   */
-#define SPIRSP4_FUNC_NUM_ERROR_S	28
-#define SPIRSP4_PARAM_ERROR_M	BITFIELD_MASK(1)  /* Bit  30        - Parameter Error Bit */
-#define SPIRSP4_PARAM_ERROR_S	30
-#define SPIRSP4_START_BIT_M	BITFIELD_MASK(1)  /* Bit  31        - Start Bit */
-#define SPIRSP4_START_BIT_S	31
-
-#define SPIRSP5_DATA_M			BITFIELD_MASK(8)  /* Bits [23:16]   - R/W Data */
-#define SPIRSP5_DATA_S			16
-#define SPIRSP5_IDLE_STATE_M		BITFIELD_MASK(1)  /* Bit  24        - Idle state */
-#define SPIRSP5_IDLE_STATE_S		24
-#define SPIRSP5_ILLEGAL_CMD_M		BITFIELD_MASK(1)  /* Bit  26        - Illegal Cmd error */
-#define SPIRSP5_ILLEGAL_CMD_S		26
-#define SPIRSP5_COM_CRC_ERROR_M		BITFIELD_MASK(1)  /* Bit  27        - COM CRC error */
-#define SPIRSP5_COM_CRC_ERROR_S		27
-#define SPIRSP5_FUNC_NUM_ERROR_M	BITFIELD_MASK(1)  /* Bit  28        - Function number error
-							   */
-#define SPIRSP5_FUNC_NUM_ERROR_S	28
-#define SPIRSP5_PARAM_ERROR_M		BITFIELD_MASK(1)  /* Bit  30        - Parameter Error Bit */
-#define SPIRSP5_PARAM_ERROR_S		30
-#define SPIRSP5_START_BIT_M		BITFIELD_MASK(1)  /* Bit  31        - Start Bit */
-#define SPIRSP5_START_BIT_S		31
-
-/* RSP6 card status format; Pg 68 Physical Layer spec v 1.10 */
-#define RSP6STAT_AKE_SEQ_ERROR_M	BITFIELD_MASK(1)  /* Bit 3	- Authentication seq error
-							   */
-#define RSP6STAT_AKE_SEQ_ERROR_S	3
-#define RSP6STAT_APP_CMD_M		BITFIELD_MASK(1)  /* Bit 5	- Card expects ACMD */
-#define RSP6STAT_APP_CMD_S		5
-#define RSP6STAT_READY_FOR_DATA_M	BITFIELD_MASK(1)  /* Bit 8	- Ready for data
-							   * (buff empty)
-							   */
-#define RSP6STAT_READY_FOR_DATA_S	8
-#define RSP6STAT_CURR_STATE_M		BITFIELD_MASK(4)  /* Bits [12:9] - Card state at
-							   * Cmd reception
-							   */
-#define RSP6STAT_CURR_STATE_S		9
-#define RSP6STAT_ERROR_M		BITFIELD_MASK(1)  /* Bit 13  - General/Unknown error Bit 19
-							   */
-#define RSP6STAT_ERROR_S		13
-#define RSP6STAT_ILLEGAL_CMD_M		BITFIELD_MASK(1)  /* Bit 14  - Illegal cmd for
-							   * card state Bit 22
-							   */
-#define RSP6STAT_ILLEGAL_CMD_S		14
-#define RSP6STAT_COM_CRC_ERROR_M	BITFIELD_MASK(1)  /* Bit 15  - CRC previous command
-							   * failed Bit 23
-							   */
-#define RSP6STAT_COM_CRC_ERROR_S	15
-
-#define SDIOH_XFER_TYPE_READ    SD_IO_OP_READ
-#define SDIOH_XFER_TYPE_WRITE   SD_IO_OP_WRITE
-
-/* command issue options */
-#define CMD_OPTION_DEFAULT	0
-#define CMD_OPTION_TUNING	1
-
-#endif /* def BCMSDIO */
-#endif /* _SDIO_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sdioh.h b/drivers/net/wireless/bcmdhd/include/sdioh.h
deleted file mode 100644
index bc1fcbc..0000000
--- a/drivers/net/wireless/bcmdhd/include/sdioh.h
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * SDIO Host Controller Spec header file
- * Register map and definitions for the Standard Host Controller
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sdioh.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_SDIOH_H
-#define	_SDIOH_H
-
-#define SD_SysAddr			0x000
-#define SD_BlockSize			0x004
-#define SD_BlockCount 			0x006
-#define SD_Arg0				0x008
-#define SD_Arg1 			0x00A
-#define SD_TransferMode			0x00C
-#define SD_Command 			0x00E
-#define SD_Response0			0x010
-#define SD_Response1 			0x012
-#define SD_Response2			0x014
-#define SD_Response3 			0x016
-#define SD_Response4			0x018
-#define SD_Response5 			0x01A
-#define SD_Response6			0x01C
-#define SD_Response7 			0x01E
-#define SD_BufferDataPort0		0x020
-#define SD_BufferDataPort1 		0x022
-#define SD_PresentState			0x024
-#define SD_HostCntrl			0x028
-#define SD_PwrCntrl			0x029
-#define SD_BlockGapCntrl 		0x02A
-#define SD_WakeupCntrl 			0x02B
-#define SD_ClockCntrl			0x02C
-#define SD_TimeoutCntrl 		0x02E
-#define SD_SoftwareReset		0x02F
-#define SD_IntrStatus			0x030
-#define SD_ErrorIntrStatus 		0x032
-#define SD_IntrStatusEnable		0x034
-#define SD_ErrorIntrStatusEnable 	0x036
-#define SD_IntrSignalEnable		0x038
-#define SD_ErrorIntrSignalEnable 	0x03A
-#define SD_CMD12ErrorStatus		0x03C
-#define SD_Capabilities			0x040
-#define SD_Capabilities3		0x044
-#define SD_MaxCurCap			0x048
-#define SD_MaxCurCap_Reserved		0x04C
-#define SD_ADMA_ErrStatus		0x054
-#define SD_ADMA_SysAddr			0x58
-#define SD_SlotInterruptStatus		0x0FC
-#define SD_HostControllerVersion 	0x0FE
-#define	SD_GPIO_Reg			0x100
-#define	SD_GPIO_OE			0x104
-#define	SD_GPIO_Enable			0x108
-
-/* SD specific registers in PCI config space */
-#define SD_SlotInfo	0x40
-
-/* HC 3.0 specific registers and offsets */
-#define SD3_HostCntrl2			0x03E
-/* preset regsstart and count */
-#define SD3_PresetValStart		0x060
-#define SD3_PresetValCount		8
-/* preset-indiv regs */
-#define SD3_PresetVal_init		0x060
-#define SD3_PresetVal_default	0x062
-#define SD3_PresetVal_HS		0x064
-#define SD3_PresetVal_SDR12		0x066
-#define SD3_PresetVal_SDR25		0x068
-#define SD3_PresetVal_SDR50		0x06a
-#define SD3_PresetVal_SDR104	0x06c
-#define SD3_PresetVal_DDR50		0x06e
-/* SDIO3.0 Revx specific Registers */
-#define SD3_Tuning_Info_Register 0x0EC
-#define SD3_WL_BT_reset_register 0x0F0
-
-
-/* preset value indices */
-#define SD3_PRESETVAL_INITIAL_IX	0
-#define SD3_PRESETVAL_DESPEED_IX	1
-#define SD3_PRESETVAL_HISPEED_IX	2
-#define SD3_PRESETVAL_SDR12_IX		3
-#define SD3_PRESETVAL_SDR25_IX		4
-#define SD3_PRESETVAL_SDR50_IX		5
-#define SD3_PRESETVAL_SDR104_IX		6
-#define SD3_PRESETVAL_DDR50_IX		7
-
-/* SD_Capabilities reg (0x040) */
-#define CAP_TO_CLKFREQ_M 	BITFIELD_MASK(6)
-#define CAP_TO_CLKFREQ_S 	0
-#define CAP_TO_CLKUNIT_M  	BITFIELD_MASK(1)
-#define CAP_TO_CLKUNIT_S 	7
-/* Note: for sdio-2.0 case, this mask has to be 6 bits, but msb 2
-	bits are reserved. going ahead with 8 bits, as it is req for 3.0
-*/
-#define CAP_BASECLK_M 		BITFIELD_MASK(8)
-#define CAP_BASECLK_S 		8
-#define CAP_MAXBLOCK_M 		BITFIELD_MASK(2)
-#define CAP_MAXBLOCK_S		16
-#define CAP_ADMA2_M		BITFIELD_MASK(1)
-#define CAP_ADMA2_S		19
-#define CAP_ADMA1_M		BITFIELD_MASK(1)
-#define CAP_ADMA1_S		20
-#define CAP_HIGHSPEED_M		BITFIELD_MASK(1)
-#define CAP_HIGHSPEED_S		21
-#define CAP_DMA_M		BITFIELD_MASK(1)
-#define CAP_DMA_S		22
-#define CAP_SUSPEND_M		BITFIELD_MASK(1)
-#define CAP_SUSPEND_S		23
-#define CAP_VOLT_3_3_M		BITFIELD_MASK(1)
-#define CAP_VOLT_3_3_S		24
-#define CAP_VOLT_3_0_M		BITFIELD_MASK(1)
-#define CAP_VOLT_3_0_S		25
-#define CAP_VOLT_1_8_M		BITFIELD_MASK(1)
-#define CAP_VOLT_1_8_S		26
-#define CAP_64BIT_HOST_M	BITFIELD_MASK(1)
-#define CAP_64BIT_HOST_S	28
-
-#define SDIO_OCR_READ_FAIL	(2)
-
-
-#define CAP_ASYNCINT_SUP_M	BITFIELD_MASK(1)
-#define CAP_ASYNCINT_SUP_S	29
-
-#define CAP_SLOTTYPE_M		BITFIELD_MASK(2)
-#define CAP_SLOTTYPE_S		30
-
-#define CAP3_MSBits_OFFSET	(32)
-/* note: following are caps MSB32 bits.
-	So the bits start from 0, instead of 32. that is why
-	CAP3_MSBits_OFFSET is subtracted.
-*/
-#define CAP3_SDR50_SUP_M		BITFIELD_MASK(1)
-#define CAP3_SDR50_SUP_S		(32 - CAP3_MSBits_OFFSET)
-
-#define CAP3_SDR104_SUP_M	BITFIELD_MASK(1)
-#define CAP3_SDR104_SUP_S	(33 - CAP3_MSBits_OFFSET)
-
-#define CAP3_DDR50_SUP_M	BITFIELD_MASK(1)
-#define CAP3_DDR50_SUP_S	(34 - CAP3_MSBits_OFFSET)
-
-/* for knowing the clk caps in a single read */
-#define CAP3_30CLKCAP_M		BITFIELD_MASK(3)
-#define CAP3_30CLKCAP_S		(32 - CAP3_MSBits_OFFSET)
-
-#define CAP3_DRIVTYPE_A_M	BITFIELD_MASK(1)
-#define CAP3_DRIVTYPE_A_S	(36 - CAP3_MSBits_OFFSET)
-
-#define CAP3_DRIVTYPE_C_M	BITFIELD_MASK(1)
-#define CAP3_DRIVTYPE_C_S	(37 - CAP3_MSBits_OFFSET)
-
-#define CAP3_DRIVTYPE_D_M	BITFIELD_MASK(1)
-#define CAP3_DRIVTYPE_D_S	(38 - CAP3_MSBits_OFFSET)
-
-#define CAP3_RETUNING_TC_M	BITFIELD_MASK(4)
-#define CAP3_RETUNING_TC_S	(40 - CAP3_MSBits_OFFSET)
-
-#define CAP3_TUNING_SDR50_M	BITFIELD_MASK(1)
-#define CAP3_TUNING_SDR50_S	(45 - CAP3_MSBits_OFFSET)
-
-#define CAP3_RETUNING_MODES_M	BITFIELD_MASK(2)
-#define CAP3_RETUNING_MODES_S	(46 - CAP3_MSBits_OFFSET)
-
-#define CAP3_CLK_MULT_M		BITFIELD_MASK(8)
-#define CAP3_CLK_MULT_S		(48 - CAP3_MSBits_OFFSET)
-
-#define PRESET_DRIVR_SELECT_M	BITFIELD_MASK(2)
-#define PRESET_DRIVR_SELECT_S	14
-
-#define PRESET_CLK_DIV_M	BITFIELD_MASK(10)
-#define PRESET_CLK_DIV_S	0
-
-/* SD_MaxCurCap reg (0x048) */
-#define CAP_CURR_3_3_M		BITFIELD_MASK(8)
-#define CAP_CURR_3_3_S		0
-#define CAP_CURR_3_0_M		BITFIELD_MASK(8)
-#define CAP_CURR_3_0_S		8
-#define CAP_CURR_1_8_M		BITFIELD_MASK(8)
-#define CAP_CURR_1_8_S		16
-
-/* SD_SysAddr: Offset 0x0000, Size 4 bytes */
-
-/* SD_BlockSize: Offset 0x004, Size 2 bytes */
-#define BLKSZ_BLKSZ_M		BITFIELD_MASK(12)
-#define BLKSZ_BLKSZ_S		0
-#define BLKSZ_BNDRY_M		BITFIELD_MASK(3)
-#define BLKSZ_BNDRY_S		12
-
-/* SD_BlockCount: Offset 0x006, size 2 bytes */
-
-/* SD_Arg0: Offset 0x008, size = 4 bytes  */
-/* SD_TransferMode Offset 0x00C, size = 2 bytes */
-#define XFER_DMA_ENABLE_M   	BITFIELD_MASK(1)
-#define XFER_DMA_ENABLE_S	0
-#define XFER_BLK_COUNT_EN_M 	BITFIELD_MASK(1)
-#define XFER_BLK_COUNT_EN_S	1
-#define XFER_CMD_12_EN_M    	BITFIELD_MASK(1)
-#define XFER_CMD_12_EN_S 	2
-#define XFER_DATA_DIRECTION_M	BITFIELD_MASK(1)
-#define XFER_DATA_DIRECTION_S	4
-#define XFER_MULTI_BLOCK_M	BITFIELD_MASK(1)
-#define XFER_MULTI_BLOCK_S	5
-
-/* SD_Command: Offset 0x00E, size = 2 bytes */
-/* resp_type field */
-#define RESP_TYPE_NONE 		0
-#define RESP_TYPE_136  		1
-#define RESP_TYPE_48   		2
-#define RESP_TYPE_48_BUSY	3
-/* type field */
-#define CMD_TYPE_NORMAL		0
-#define CMD_TYPE_SUSPEND	1
-#define CMD_TYPE_RESUME		2
-#define CMD_TYPE_ABORT		3
-
-#define CMD_RESP_TYPE_M		BITFIELD_MASK(2)	/* Bits [0-1] 	- Response type */
-#define CMD_RESP_TYPE_S		0
-#define CMD_CRC_EN_M		BITFIELD_MASK(1)	/* Bit 3 	- CRC enable */
-#define CMD_CRC_EN_S		3
-#define CMD_INDEX_EN_M		BITFIELD_MASK(1)	/* Bit 4 	- Enable index checking */
-#define CMD_INDEX_EN_S		4
-#define CMD_DATA_EN_M		BITFIELD_MASK(1)	/* Bit 5 	- Using DAT line */
-#define CMD_DATA_EN_S		5
-#define CMD_TYPE_M		BITFIELD_MASK(2)	/* Bit [6-7] 	- Normal, abort, resume, etc
-							 */
-#define CMD_TYPE_S		6
-#define CMD_INDEX_M		BITFIELD_MASK(6)	/* Bits [8-13] 	- Command number */
-#define CMD_INDEX_S		8
-
-/* SD_BufferDataPort0	: Offset 0x020, size = 2 or 4 bytes */
-/* SD_BufferDataPort1 	: Offset 0x022, size = 2 bytes */
-/* SD_PresentState	: Offset 0x024, size = 4 bytes */
-#define PRES_CMD_INHIBIT_M	BITFIELD_MASK(1)	/* Bit 0	May use CMD */
-#define PRES_CMD_INHIBIT_S	0
-#define PRES_DAT_INHIBIT_M	BITFIELD_MASK(1)	/* Bit 1	May use DAT */
-#define PRES_DAT_INHIBIT_S	1
-#define PRES_DAT_BUSY_M		BITFIELD_MASK(1)	/* Bit 2	DAT is busy */
-#define PRES_DAT_BUSY_S		2
-#define PRES_PRESENT_RSVD_M	BITFIELD_MASK(5)	/* Bit [3-7]	rsvd */
-#define PRES_PRESENT_RSVD_S	3
-#define PRES_WRITE_ACTIVE_M	BITFIELD_MASK(1)	/* Bit 8	Write is active */
-#define PRES_WRITE_ACTIVE_S	8
-#define PRES_READ_ACTIVE_M	BITFIELD_MASK(1)	/* Bit 9	Read is active */
-#define PRES_READ_ACTIVE_S	9
-#define PRES_WRITE_DATA_RDY_M	BITFIELD_MASK(1)	/* Bit 10	Write buf is avail */
-#define PRES_WRITE_DATA_RDY_S	10
-#define PRES_READ_DATA_RDY_M	BITFIELD_MASK(1)	/* Bit 11	Read buf data avail */
-#define PRES_READ_DATA_RDY_S	11
-#define PRES_CARD_PRESENT_M	BITFIELD_MASK(1)	/* Bit 16	Card present - debounced */
-#define PRES_CARD_PRESENT_S	16
-#define PRES_CARD_STABLE_M	BITFIELD_MASK(1)	/* Bit 17	Debugging */
-#define PRES_CARD_STABLE_S	17
-#define PRES_CARD_PRESENT_RAW_M	BITFIELD_MASK(1)	/* Bit 18	Not debounced */
-#define PRES_CARD_PRESENT_RAW_S	18
-#define PRES_WRITE_ENABLED_M	BITFIELD_MASK(1)	/* Bit 19	Write protected? */
-#define PRES_WRITE_ENABLED_S	19
-#define PRES_DAT_SIGNAL_M	BITFIELD_MASK(4)	/* Bit [20-23]	Debugging */
-#define PRES_DAT_SIGNAL_S	20
-#define PRES_CMD_SIGNAL_M	BITFIELD_MASK(1)	/* Bit 24	Debugging */
-#define PRES_CMD_SIGNAL_S	24
-
-/* SD_HostCntrl: Offset 0x028, size = 1 bytes */
-#define HOST_LED_M		BITFIELD_MASK(1)	/* Bit 0	LED On/Off */
-#define HOST_LED_S		0
-#define HOST_DATA_WIDTH_M	BITFIELD_MASK(1)	/* Bit 1	4 bit enable */
-#define HOST_DATA_WIDTH_S	1
-#define HOST_HI_SPEED_EN_M	BITFIELD_MASK(1)	/* Bit 2	High speed vs low speed */
-#define HOST_DMA_SEL_S		3
-#define HOST_DMA_SEL_M		BITFIELD_MASK(2)	/* Bit 4:3	DMA Select */
-#define HOST_HI_SPEED_EN_S	2
-
-/* Host Control2: */
-#define HOSTCtrl2_PRESVAL_EN_M	BITFIELD_MASK(1)	/* 1 bit */
-#define HOSTCtrl2_PRESVAL_EN_S	15					/* bit# */
-
-#define HOSTCtrl2_ASYINT_EN_M	BITFIELD_MASK(1)	/* 1 bit */
-#define HOSTCtrl2_ASYINT_EN_S	14					/* bit# */
-
-#define HOSTCtrl2_SAMPCLK_SEL_M	BITFIELD_MASK(1)	/* 1 bit */
-#define HOSTCtrl2_SAMPCLK_SEL_S	7					/* bit# */
-
-#define HOSTCtrl2_EXEC_TUNING_M	BITFIELD_MASK(1)	/* 1 bit */
-#define HOSTCtrl2_EXEC_TUNING_S	6					/* bit# */
-
-#define HOSTCtrl2_DRIVSTRENGTH_SEL_M	BITFIELD_MASK(2)	/* 2 bit */
-#define HOSTCtrl2_DRIVSTRENGTH_SEL_S	4					/* bit# */
-
-#define HOSTCtrl2_1_8SIG_EN_M	BITFIELD_MASK(1)	/* 1 bit */
-#define HOSTCtrl2_1_8SIG_EN_S	3					/* bit# */
-
-#define HOSTCtrl2_UHSMODE_SEL_M	BITFIELD_MASK(3)	/* 3 bit */
-#define HOSTCtrl2_UHSMODE_SEL_S	0					/* bit# */
-
-#define HOST_CONTR_VER_2		(1)
-#define HOST_CONTR_VER_3		(2)
-
-/* misc defines */
-#define SD1_MODE 		0x1	/* SD Host Cntrlr Spec */
-#define SD4_MODE 		0x2	/* SD Host Cntrlr Spec */
-
-/* SD_PwrCntrl: Offset 0x029, size = 1 bytes */
-#define PWR_BUS_EN_M		BITFIELD_MASK(1)	/* Bit 0	Power the bus */
-#define PWR_BUS_EN_S		0
-#define PWR_VOLTS_M		BITFIELD_MASK(3)	/* Bit [1-3]	Voltage Select */
-#define PWR_VOLTS_S		1
-
-/* SD_SoftwareReset: Offset 0x02F, size = 1 byte */
-#define SW_RESET_ALL_M		BITFIELD_MASK(1)	/* Bit 0	Reset All */
-#define SW_RESET_ALL_S		0
-#define SW_RESET_CMD_M		BITFIELD_MASK(1)	/* Bit 1	CMD Line Reset */
-#define SW_RESET_CMD_S		1
-#define SW_RESET_DAT_M		BITFIELD_MASK(1)	/* Bit 2	DAT Line Reset */
-#define SW_RESET_DAT_S		2
-
-/* SD_IntrStatus: Offset 0x030, size = 2 bytes */
-/* Defs also serve SD_IntrStatusEnable and SD_IntrSignalEnable */
-#define INTSTAT_CMD_COMPLETE_M		BITFIELD_MASK(1)	/* Bit 0 */
-#define INTSTAT_CMD_COMPLETE_S		0
-#define INTSTAT_XFER_COMPLETE_M		BITFIELD_MASK(1)
-#define INTSTAT_XFER_COMPLETE_S		1
-#define INTSTAT_BLOCK_GAP_EVENT_M	BITFIELD_MASK(1)
-#define INTSTAT_BLOCK_GAP_EVENT_S	2
-#define INTSTAT_DMA_INT_M		BITFIELD_MASK(1)
-#define INTSTAT_DMA_INT_S		3
-#define INTSTAT_BUF_WRITE_READY_M	BITFIELD_MASK(1)
-#define INTSTAT_BUF_WRITE_READY_S	4
-#define INTSTAT_BUF_READ_READY_M	BITFIELD_MASK(1)
-#define INTSTAT_BUF_READ_READY_S	5
-#define INTSTAT_CARD_INSERTION_M	BITFIELD_MASK(1)
-#define INTSTAT_CARD_INSERTION_S	6
-#define INTSTAT_CARD_REMOVAL_M		BITFIELD_MASK(1)
-#define INTSTAT_CARD_REMOVAL_S		7
-#define INTSTAT_CARD_INT_M		BITFIELD_MASK(1)
-#define INTSTAT_CARD_INT_S		8
-#define INTSTAT_RETUNING_INT_M		BITFIELD_MASK(1)	/* Bit 12 */
-#define INTSTAT_RETUNING_INT_S		12
-#define INTSTAT_ERROR_INT_M		BITFIELD_MASK(1)	/* Bit 15 */
-#define INTSTAT_ERROR_INT_S		15
-
-/* SD_ErrorIntrStatus: Offset 0x032, size = 2 bytes */
-/* Defs also serve SD_ErrorIntrStatusEnable and SD_ErrorIntrSignalEnable */
-#define ERRINT_CMD_TIMEOUT_M		BITFIELD_MASK(1)
-#define ERRINT_CMD_TIMEOUT_S		0
-#define ERRINT_CMD_CRC_M		BITFIELD_MASK(1)
-#define ERRINT_CMD_CRC_S		1
-#define ERRINT_CMD_ENDBIT_M		BITFIELD_MASK(1)
-#define ERRINT_CMD_ENDBIT_S		2
-#define ERRINT_CMD_INDEX_M		BITFIELD_MASK(1)
-#define ERRINT_CMD_INDEX_S		3
-#define ERRINT_DATA_TIMEOUT_M		BITFIELD_MASK(1)
-#define ERRINT_DATA_TIMEOUT_S		4
-#define ERRINT_DATA_CRC_M		BITFIELD_MASK(1)
-#define ERRINT_DATA_CRC_S		5
-#define ERRINT_DATA_ENDBIT_M		BITFIELD_MASK(1)
-#define ERRINT_DATA_ENDBIT_S		6
-#define ERRINT_CURRENT_LIMIT_M		BITFIELD_MASK(1)
-#define ERRINT_CURRENT_LIMIT_S		7
-#define ERRINT_AUTO_CMD12_M		BITFIELD_MASK(1)
-#define ERRINT_AUTO_CMD12_S		8
-#define ERRINT_VENDOR_M			BITFIELD_MASK(4)
-#define ERRINT_VENDOR_S			12
-#define ERRINT_ADMA_M			BITFIELD_MASK(1)
-#define ERRINT_ADMA_S			9
-
-/* Also provide definitions in "normal" form to allow combined masks */
-#define ERRINT_CMD_TIMEOUT_BIT		0x0001
-#define ERRINT_CMD_CRC_BIT		0x0002
-#define ERRINT_CMD_ENDBIT_BIT		0x0004
-#define ERRINT_CMD_INDEX_BIT		0x0008
-#define ERRINT_DATA_TIMEOUT_BIT		0x0010
-#define ERRINT_DATA_CRC_BIT		0x0020
-#define ERRINT_DATA_ENDBIT_BIT		0x0040
-#define ERRINT_CURRENT_LIMIT_BIT	0x0080
-#define ERRINT_AUTO_CMD12_BIT		0x0100
-#define ERRINT_ADMA_BIT		0x0200
-
-/* Masks to select CMD vs. DATA errors */
-#define ERRINT_CMD_ERRS		(ERRINT_CMD_TIMEOUT_BIT | ERRINT_CMD_CRC_BIT |\
-				 ERRINT_CMD_ENDBIT_BIT | ERRINT_CMD_INDEX_BIT)
-#define ERRINT_DATA_ERRS	(ERRINT_DATA_TIMEOUT_BIT | ERRINT_DATA_CRC_BIT |\
-				 ERRINT_DATA_ENDBIT_BIT | ERRINT_ADMA_BIT)
-#define ERRINT_TRANSFER_ERRS	(ERRINT_CMD_ERRS | ERRINT_DATA_ERRS)
-
-/* SD_WakeupCntr_BlockGapCntrl : Offset 0x02A , size = bytes */
-/* SD_ClockCntrl	: Offset 0x02C , size = bytes */
-/* SD_SoftwareReset_TimeoutCntrl 	: Offset 0x02E , size = bytes */
-/* SD_IntrStatus	: Offset 0x030 , size = bytes */
-/* SD_ErrorIntrStatus 	: Offset 0x032 , size = bytes */
-/* SD_IntrStatusEnable	: Offset 0x034 , size = bytes */
-/* SD_ErrorIntrStatusEnable : Offset 0x036 , size = bytes */
-/* SD_IntrSignalEnable	: Offset 0x038 , size = bytes */
-/* SD_ErrorIntrSignalEnable : Offset 0x03A , size = bytes */
-/* SD_CMD12ErrorStatus	: Offset 0x03C , size = bytes */
-/* SD_Capabilities	: Offset 0x040 , size = bytes */
-/* SD_MaxCurCap		: Offset 0x048 , size = bytes */
-/* SD_MaxCurCap_Reserved: Offset 0x04C , size = bytes */
-/* SD_SlotInterruptStatus: Offset 0x0FC , size = bytes */
-/* SD_HostControllerVersion : Offset 0x0FE , size = bytes */
-
-/* SDIO Host Control Register DMA Mode Definitions */
-#define SDIOH_SDMA_MODE			0
-#define SDIOH_ADMA1_MODE		1
-#define SDIOH_ADMA2_MODE		2
-#define SDIOH_ADMA2_64_MODE		3
-
-#define ADMA2_ATTRIBUTE_VALID		(1 << 0)	/* ADMA Descriptor line valid */
-#define ADMA2_ATTRIBUTE_END			(1 << 1)	/* End of Descriptor */
-#define ADMA2_ATTRIBUTE_INT			(1 << 2)	/* Interrupt when line is done */
-#define ADMA2_ATTRIBUTE_ACT_NOP		(0 << 4)	/* Skip current line, go to next. */
-#define ADMA2_ATTRIBUTE_ACT_RSV		(1 << 4)	/* Same as NOP */
-#define ADMA1_ATTRIBUTE_ACT_SET		(1 << 4)	/* ADMA1 Only - set transfer length */
-#define ADMA2_ATTRIBUTE_ACT_TRAN	(2 << 4)	/* Transfer Data of one descriptor line. */
-#define ADMA2_ATTRIBUTE_ACT_LINK	(3 << 4)	/* Link Descriptor */
-
-/* ADMA2 Descriptor Table Entry for 32-bit Address */
-typedef struct adma2_dscr_32b {
-	uint32 len_attr;
-	uint32 phys_addr;
-} adma2_dscr_32b_t;
-
-/* ADMA1 Descriptor Table Entry */
-typedef struct adma1_dscr {
-	uint32 phys_addr_attr;
-} adma1_dscr_t;
-
-#endif /* _SDIOH_H */
diff --git a/drivers/net/wireless/bcmdhd/include/sdiovar.h b/drivers/net/wireless/bcmdhd/include/sdiovar.h
deleted file mode 100644
index 15b74ab..0000000
--- a/drivers/net/wireless/bcmdhd/include/sdiovar.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Structure used by apps whose drivers access SDIO drivers.
- * Pulled out separately so dhdu and wlu can both use it.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sdiovar.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef _sdiovar_h_
-#define _sdiovar_h_
-
-#include <typedefs.h>
-
-/* require default structure packing */
-#define BWL_DEFAULT_PACKING
-#include <packed_section_start.h>
-
-typedef struct sdreg {
-	int func;
-	int offset;
-	int value;
-} sdreg_t;
-
-/* Common msglevel constants */
-#define SDH_ERROR_VAL		0x0001	/* Error */
-#define SDH_TRACE_VAL		0x0002	/* Trace */
-#define SDH_INFO_VAL		0x0004	/* Info */
-#define SDH_DEBUG_VAL		0x0008	/* Debug */
-#define SDH_DATA_VAL		0x0010	/* Data */
-#define SDH_CTRL_VAL		0x0020	/* Control Regs */
-#define SDH_LOG_VAL		0x0040	/* Enable bcmlog */
-#define SDH_DMA_VAL		0x0080	/* DMA */
-
-#define NUM_PREV_TRANSACTIONS	16
-
-
-#include <packed_section_end.h>
-
-#endif /* _sdiovar_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/siutils.h b/drivers/net/wireless/bcmdhd/include/siutils.h
deleted file mode 100644
index 27ad7c4..0000000
--- a/drivers/net/wireless/bcmdhd/include/siutils.h
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * Misc utility routines for accessing the SOC Interconnects
- * of Broadcom HNBU chips.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: siutils.h 530150 2015-01-29 08:43:40Z $
- */
-
-#ifndef	_siutils_h_
-#define	_siutils_h_
-
-#ifdef SR_DEBUG
-#include "wlioctl.h"
-#endif /* SR_DEBUG */
-
-
-/**
- * Data structure to export all chip specific common variables
- *   public (read-only) portion of siutils handle returned by si_attach()/si_kattach()
- */
-struct si_pub {
-	uint	socitype;		/**< SOCI_SB, SOCI_AI */
-
-	uint	bustype;		/**< SI_BUS, PCI_BUS */
-	uint	buscoretype;		/**< PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
-	uint	buscorerev;		/**< buscore rev */
-	uint	buscoreidx;		/**< buscore index */
-	int	ccrev;			/**< chip common core rev */
-	uint32	cccaps;			/**< chip common capabilities */
-	uint32  cccaps_ext;			/**< chip common capabilities extension */
-	int	pmurev;			/**< pmu core rev */
-	uint32	pmucaps;		/**< pmu capabilities */
-	uint	boardtype;		/**< board type */
-	uint    boardrev;               /* board rev */
-	uint	boardvendor;		/**< board vendor */
-	uint	boardflags;		/**< board flags */
-	uint	boardflags2;		/**< board flags2 */
-	uint	chip;			/**< chip number */
-	uint	chiprev;		/**< chip revision */
-	uint	chippkg;		/**< chip package option */
-	uint32	chipst;			/**< chip status */
-	bool	issim;			/**< chip is in simulation or emulation */
-	uint    socirev;		/**< SOC interconnect rev */
-	bool	pci_pr32414;
-
-};
-
-/* for HIGH_ONLY driver, the si_t must be writable to allow states sync from BMAC to HIGH driver
- * for monolithic driver, it is readonly to prevent accident change
- */
-typedef const struct si_pub si_t;
-
-/*
- * Many of the routines below take an 'sih' handle as their first arg.
- * Allocate this by calling si_attach().  Free it by calling si_detach().
- * At any one time, the sih is logically focused on one particular si core
- * (the "current core").
- * Use si_setcore() or si_setcoreidx() to change the association to another core.
- */
-#define	SI_OSH		NULL	/**< Use for si_kattach when no osh is available */
-
-#define	BADIDX		(SI_MAXCORES + 1)
-
-/* clkctl xtal what flags */
-#define	XTAL			0x1	/**< primary crystal oscillator (2050) */
-#define	PLL			0x2	/**< main chip pll */
-
-/* clkctl clk mode */
-#define	CLK_FAST		0	/**< force fast (pll) clock */
-#define	CLK_DYNAMIC		2	/**< enable dynamic clock control */
-
-/* GPIO usage priorities */
-#define GPIO_DRV_PRIORITY	0	/**< Driver */
-#define GPIO_APP_PRIORITY	1	/**< Application */
-#define GPIO_HI_PRIORITY	2	/**< Highest priority. Ignore GPIO reservation */
-
-/* GPIO pull up/down */
-#define GPIO_PULLUP		0
-#define GPIO_PULLDN		1
-
-/* GPIO event regtype */
-#define GPIO_REGEVT		0	/**< GPIO register event */
-#define GPIO_REGEVT_INTMSK	1	/**< GPIO register event int mask */
-#define GPIO_REGEVT_INTPOL	2	/**< GPIO register event int polarity */
-
-/* device path */
-#define SI_DEVPATH_BUFSZ	16	/**< min buffer size in bytes */
-
-/* SI routine enumeration: to be used by update function with multiple hooks */
-#define	SI_DOATTACH	1
-#define SI_PCIDOWN	2	/**< wireless interface is down */
-#define SI_PCIUP	3	/**< wireless interface is up */
-
-#ifdef SR_DEBUG
-#define PMU_RES		31
-#endif /* SR_DEBUG */
-
-#define	ISSIM_ENAB(sih)	FALSE
-
-/* PMU clock/power control */
-#if defined(BCMPMUCTL)
-#define PMUCTL_ENAB(sih)	(BCMPMUCTL)
-#else
-#define PMUCTL_ENAB(sih)	((sih)->cccaps & CC_CAP_PMU)
-#endif
-
-#define AOB_ENAB(sih)	((sih)->ccrev >= 35 ? \
-			((sih)->cccaps_ext & CC_CAP_EXT_AOB_PRESENT) : 0)
-
-/* chipcommon clock/power control (exclusive with PMU's) */
-#if defined(BCMPMUCTL) && BCMPMUCTL
-#define CCCTL_ENAB(sih)		(0)
-#define CCPLL_ENAB(sih)		(0)
-#else
-#define CCCTL_ENAB(sih)		((sih)->cccaps & CC_CAP_PWR_CTL)
-#define CCPLL_ENAB(sih)		((sih)->cccaps & CC_CAP_PLL_MASK)
-#endif
-
-typedef void (*gci_gpio_handler_t)(uint32 stat, void *arg);
-
-/* External BT Coex enable mask */
-#define CC_BTCOEX_EN_MASK  0x01
-/* External PA enable mask */
-#define GPIO_CTRL_EPA_EN_MASK 0x40
-/* WL/BT control enable mask */
-#define GPIO_CTRL_5_6_EN_MASK 0x60
-#define GPIO_CTRL_7_6_EN_MASK 0xC0
-#define GPIO_OUT_7_EN_MASK 0x80
-
-
-
-/* CR4 specific defines used by the host driver */
-#define SI_CR4_CAP			(0x04)
-#define SI_CR4_BANKIDX		(0x40)
-#define SI_CR4_BANKINFO		(0x44)
-#define SI_CR4_BANKPDA		(0x4C)
-
-#define	ARMCR4_TCBBNB_MASK	0xf0
-#define	ARMCR4_TCBBNB_SHIFT	4
-#define	ARMCR4_TCBANB_MASK	0xf
-#define	ARMCR4_TCBANB_SHIFT	0
-
-#define	SICF_CPUHALT		(0x0020)
-#define	ARMCR4_BSZ_MASK		0x3f
-#define	ARMCR4_BSZ_MULT		8192
-#define	SI_BPIND_1BYTE		0x1
-#define	SI_BPIND_2BYTE		0x3
-#define	SI_BPIND_4BYTE		0xF
-#include <osl_decl.h>
-/* === exported functions === */
-extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype,
-                       void *sdh, char **vars, uint *varsz);
-extern si_t *si_kattach(osl_t *osh);
-extern void si_detach(si_t *sih);
-extern bool si_pci_war16165(si_t *sih);
-extern void *
-si_d11_switch_addrbase(si_t *sih, uint coreunit);
-extern uint si_corelist(si_t *sih, uint coreid[]);
-extern uint si_coreid(si_t *sih);
-extern uint si_flag(si_t *sih);
-extern uint si_flag_alt(si_t *sih);
-extern uint si_intflag(si_t *sih);
-extern uint si_coreidx(si_t *sih);
-extern uint si_coreunit(si_t *sih);
-extern uint si_corevendor(si_t *sih);
-extern uint si_corerev(si_t *sih);
-extern void *si_osh(si_t *sih);
-extern void si_setosh(si_t *sih, osl_t *osh);
-extern uint si_backplane_access(si_t *sih, uint addr, uint size,
-	uint *val, bool read);
-extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val);
-extern uint si_pmu_corereg(si_t *sih, uint32 idx, uint regoff, uint mask, uint val);
-extern uint32 *si_corereg_addr(si_t *sih, uint coreidx, uint regoff);
-extern void *si_coreregs(si_t *sih);
-extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
-extern uint si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val);
-extern void *si_wrapperregs(si_t *sih);
-extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val);
-extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val);
-extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val);
-extern void si_d11rsdb_core1_alt_reg_clk_dis(si_t *sih);
-extern void si_d11rsdb_core1_alt_reg_clk_en(si_t *sih);
-extern bool si_iscoreup(si_t *sih);
-extern uint si_numcoreunits(si_t *sih, uint coreid);
-extern uint si_numd11coreunits(si_t *sih);
-extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit);
-extern void *si_setcoreidx(si_t *sih, uint coreidx);
-extern void *si_setcore(si_t *sih, uint coreid, uint coreunit);
-extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val);
-extern void si_restore_core(si_t *sih, uint coreid, uint intr_val);
-extern int si_numaddrspaces(si_t *sih);
-extern uint32 si_addrspace(si_t *sih, uint asidx);
-extern uint32 si_addrspacesize(si_t *sih, uint asidx);
-extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size);
-extern int si_corebist(si_t *sih);
-extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
-extern void si_core_disable(si_t *sih, uint32 bits);
-extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m);
-extern uint si_chip_hostif(si_t *sih);
-extern bool si_read_pmu_autopll(si_t *sih);
-extern uint32 si_clock(si_t *sih);
-extern uint32 si_alp_clock(si_t *sih); /* returns [Hz] units */
-extern uint32 si_ilp_clock(si_t *sih); /* returns [Hz] units */
-extern void si_pci_setup(si_t *sih, uint coremask);
-extern void si_pcmcia_init(si_t *sih);
-extern void si_setint(si_t *sih, int siflag);
-extern bool si_backplane64(si_t *sih);
-extern void si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
-	void *intrsenabled_fn, void *intr_arg);
-extern void si_deregister_intr_callback(si_t *sih);
-extern void si_clkctl_init(si_t *sih);
-extern uint16 si_clkctl_fast_pwrup_delay(si_t *sih);
-extern bool si_clkctl_cc(si_t *sih, uint mode);
-extern int si_clkctl_xtal(si_t *sih, uint what, bool on);
-extern uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 val);
-extern void si_btcgpiowar(si_t *sih);
-extern bool si_deviceremoved(si_t *sih);
-extern uint32 si_sysmem_size(si_t *sih);
-extern uint32 si_socram_size(si_t *sih);
-extern uint32 si_socdevram_size(si_t *sih);
-extern uint32 si_socram_srmem_size(si_t *sih);
-extern void si_socram_set_bankpda(si_t *sih, uint32 bankidx, uint32 bankpda);
-extern void si_socdevram(si_t *sih, bool set, uint8 *ennable, uint8 *protect, uint8 *remap);
-extern bool si_socdevram_pkg(si_t *sih);
-extern bool si_socdevram_remap_isenb(si_t *sih);
-extern uint32 si_socdevram_remap_size(si_t *sih);
-
-extern void si_watchdog(si_t *sih, uint ticks);
-extern void si_watchdog_ms(si_t *sih, uint32 ms);
-extern uint32 si_watchdog_msticks(void);
-extern void *si_gpiosetcore(si_t *sih);
-extern uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority);
-extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority);
-extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority);
-extern uint32 si_gpioin(si_t *sih);
-extern uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority);
-extern uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority);
-extern uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val);
-extern uint32 si_gpioreserve(si_t *sih, uint32 gpio_num, uint8 priority);
-extern uint32 si_gpiorelease(si_t *sih, uint32 gpio_num, uint8 priority);
-extern uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val);
-extern uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val);
-extern uint32 si_gpio_int_enable(si_t *sih, bool enable);
-extern void si_gci_uart_init(si_t *sih, osl_t *osh, uint8 seci_mode);
-extern void si_gci_enable_gpio(si_t *sih, uint8 gpio, uint32 mask, uint32 value);
-extern uint8 si_gci_host_wake_gpio_init(si_t *sih);
-extern void si_gci_host_wake_gpio_enable(si_t *sih, uint8 gpio, bool state);
-
-/* GCI interrupt handlers */
-extern void si_gci_handler_process(si_t *sih);
-
-/* GCI GPIO event handlers */
-extern void *si_gci_gpioint_handler_register(si_t *sih, uint8 gpio, uint8 sts,
-	gci_gpio_handler_t cb, void *arg);
-extern void si_gci_gpioint_handler_unregister(si_t *sih, void* gci_i);
-extern uint8 si_gci_gpio_status(si_t *sih, uint8 gci_gpio, uint8 mask, uint8 value);
-
-/* Wake-on-wireless-LAN (WOWL) */
-extern bool si_pci_pmecap(si_t *sih);
-extern bool si_pci_fastpmecap(struct osl_info *osh);
-extern bool si_pci_pmestat(si_t *sih);
-extern void si_pci_pmeclr(si_t *sih);
-extern void si_pci_pmeen(si_t *sih);
-extern void si_pci_pmestatclr(si_t *sih);
-extern uint si_pcie_readreg(void *sih, uint addrtype, uint offset);
-extern uint si_pcie_writereg(void *sih, uint addrtype, uint offset, uint val);
-extern void si_deepsleep_count(si_t *sih, bool arm_wakeup);
-
-
-#ifdef BCMSDIO
-extern void si_sdio_init(si_t *sih);
-#endif
-
-extern uint16 si_d11_devid(si_t *sih);
-extern int si_corepciid(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice,
-	uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, uint8 *pciheader);
-
-#define si_eci(sih) 0
-static INLINE void * si_eci_init(si_t *sih) {return NULL;}
-#define si_eci_notify_bt(sih, type, val)  (0)
-#define si_seci(sih) 0
-#define si_seci_upd(sih, a)	do {} while (0)
-static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;}
-static INLINE void * si_gci_init(si_t *sih) {return NULL;}
-#define si_seci_down(sih) do {} while (0)
-#define si_gci(sih) 0
-
-/* OTP status */
-extern bool si_is_otp_disabled(si_t *sih);
-extern bool si_is_otp_powered(si_t *sih);
-extern void si_otp_power(si_t *sih, bool on, uint32* min_res_mask);
-
-/* SPROM availability */
-extern bool si_is_sprom_available(si_t *sih);
-extern bool si_is_sprom_enabled(si_t *sih);
-extern void si_sprom_enable(si_t *sih, bool enable);
-
-/* OTP/SROM CIS stuff */
-extern int si_cis_source(si_t *sih);
-#define CIS_DEFAULT	0
-#define CIS_SROM	1
-#define CIS_OTP		2
-
-/* Fab-id information */
-#define	DEFAULT_FAB	0x0	/**< Original/first fab used for this chip */
-#define	CSM_FAB7	0x1	/**< CSM Fab7 chip */
-#define	TSMC_FAB12	0x2	/**< TSMC Fab12/Fab14 chip */
-#define	SMIC_FAB4	0x3	/**< SMIC Fab4 chip */
-
-extern int si_otp_fabid(si_t *sih, uint16 *fabid, bool rw);
-extern uint16 si_fabid(si_t *sih);
-extern uint16 si_chipid(si_t *sih);
-
-/*
- * Build device path. Path size must be >= SI_DEVPATH_BUFSZ.
- * The returned path is NULL terminated and has trailing '/'.
- * Return 0 on success, nonzero otherwise.
- */
-extern int si_devpath(si_t *sih, char *path, int size);
-extern int si_devpath_pcie(si_t *sih, char *path, int size);
-/* Read variable with prepending the devpath to the name */
-extern char *si_getdevpathvar(si_t *sih, const char *name);
-extern int si_getdevpathintvar(si_t *sih, const char *name);
-extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name);
-
-
-extern uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val);
-extern uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val);
-extern uint8 si_pcieltrenable(si_t *sih, uint32 mask, uint32 val);
-extern uint8 si_pcieobffenable(si_t *sih, uint32 mask, uint32 val);
-extern uint32 si_pcieltr_reg(si_t *sih, uint32 reg, uint32 mask, uint32 val);
-extern uint32 si_pcieltrspacing_reg(si_t *sih, uint32 mask, uint32 val);
-extern uint32 si_pcieltrhysteresiscnt_reg(si_t *sih, uint32 mask, uint32 val);
-extern void si_pcie_set_error_injection(si_t *sih, uint32 mode);
-extern void si_pcie_set_L1substate(si_t *sih, uint32 substate);
-extern uint32 si_pcie_get_L1substate(si_t *sih);
-extern void si_war42780_clkreq(si_t *sih, bool clkreq);
-extern void si_pci_down(si_t *sih);
-extern void si_pci_up(si_t *sih);
-extern void si_pci_sleep(si_t *sih);
-extern void si_pcie_war_ovr_update(si_t *sih, uint8 aspm);
-extern void si_pcie_power_save_enable(si_t *sih, bool enable);
-extern void si_pcie_extendL1timer(si_t *sih, bool extend);
-extern int si_pci_fixcfg(si_t *sih);
-extern void si_chippkg_set(si_t *sih, uint);
-
-extern void si_chipcontrl_btshd0_4331(si_t *sih, bool on);
-extern void si_chipcontrl_restore(si_t *sih, uint32 val);
-extern uint32 si_chipcontrl_read(si_t *sih);
-extern void si_chipcontrl_epa4331(si_t *sih, bool on);
-extern void si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl);
-extern void si_chipcontrl_srom4360(si_t *sih, bool on);
-extern void si_clk_srom4365(si_t *sih);
-/* Enable BT-COEX & Ex-PA for 4313 */
-extern void si_epa_4313war(si_t *sih);
-extern void si_btc_enable_chipcontrol(si_t *sih);
-/* BT/WL selection for 4313 bt combo >= P250 boards */
-extern void si_btcombo_p250_4313_war(si_t *sih);
-extern void si_btcombo_43228_war(si_t *sih);
-extern void si_clk_pmu_htavail_set(si_t *sih, bool set_clear);
-extern void si_pmu_avb_clk_set(si_t *sih, osl_t *osh, bool set_flag);
-extern void si_pmu_synth_pwrsw_4313_war(si_t *sih);
-extern uint si_pll_reset(si_t *sih);
-/* === debug routines === */
-
-extern bool si_taclear(si_t *sih, bool details);
-
-#if defined(BCMDBG_PHYDUMP)
-struct bcmstrbuf;
-extern int si_dump_pcieinfo(si_t *sih, struct bcmstrbuf *b);
-#endif 
-
-#if defined(BCMDBG_PHYDUMP)
-extern void si_dumpregs(si_t *sih, struct bcmstrbuf *b);
-#endif 
-
-extern uint32 si_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
-extern uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type);
-extern int si_bpind_access(si_t *sih, uint32 addr_high, uint32 addr_low,
-	int32* data, bool read);
-#ifdef SR_DEBUG
-extern void si_dump_pmu(si_t *sih, void *pmu_var);
-extern void si_pmu_keep_on(si_t *sih, int32 int_val);
-extern uint32 si_pmu_keep_on_get(si_t *sih);
-extern uint32 si_power_island_set(si_t *sih, uint32 int_val);
-extern uint32 si_power_island_get(si_t *sih);
-#endif /* SR_DEBUG */
-extern uint32 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val);
-extern void si_pcie_set_request_size(si_t *sih, uint16 size);
-extern uint16 si_pcie_get_request_size(si_t *sih);
-extern void si_pcie_set_maxpayload_size(si_t *sih, uint16 size);
-extern uint16 si_pcie_get_maxpayload_size(si_t *sih);
-extern uint16 si_pcie_get_ssid(si_t *sih);
-extern uint32 si_pcie_get_bar0(si_t *sih);
-extern int si_pcie_configspace_cache(si_t *sih);
-extern int si_pcie_configspace_restore(si_t *sih);
-extern int si_pcie_configspace_get(si_t *sih, uint8 *buf, uint size);
-
-char *si_getnvramflvar(si_t *sih, const char *name);
-
-
-extern uint32 si_tcm_size(si_t *sih);
-extern bool si_has_flops(si_t *sih);
-
-extern int si_set_sromctl(si_t *sih, uint32 value);
-extern uint32 si_get_sromctl(si_t *sih);
-
-extern uint32 si_gci_direct(si_t *sih, uint offset, uint32 mask, uint32 val);
-extern uint32 si_gci_indirect(si_t *sih, uint regidx, uint offset, uint32 mask, uint32 val);
-extern uint32 si_gci_output(si_t *sih, uint reg, uint32 mask, uint32 val);
-extern uint32 si_gci_input(si_t *sih, uint reg);
-extern uint32 si_gci_int_enable(si_t *sih, bool enable);
-extern void si_gci_reset(si_t *sih);
-#ifdef BCMLTECOEX
-extern void si_gci_seci_init(si_t *sih);
-extern void si_ercx_init(si_t *sih, uint32 ltecx_mux, uint32 ltecx_padnum,
-	uint32 ltecx_fnsel, uint32 ltecx_gcigpio);
-extern void si_wci2_init(si_t *sih, uint8 baudrate, uint32 ltecx_mux, uint32 ltecx_padnum,
-	uint32 ltecx_fnsel, uint32 ltecx_gcigpio);
-#endif /* BCMLTECOEX */
-extern void si_gci_set_functionsel(si_t *sih, uint32 pin, uint8 fnsel);
-extern uint32 si_gci_get_functionsel(si_t *sih, uint32 pin);
-extern void si_gci_clear_functionsel(si_t *sih, uint8 fnsel);
-extern uint8 si_gci_get_chipctrlreg_idx(uint32 pin, uint32 *regidx, uint32 *pos);
-extern uint32 si_gci_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val);
-extern uint32 si_gci_chipstatus(si_t *sih, uint reg);
-extern uint16 si_cc_get_reg16(uint32 reg_offs);
-extern uint32 si_cc_get_reg32(uint32 reg_offs);
-extern uint32 si_cc_set_reg32(uint32 reg_offs, uint32 val);
-extern uint32 si_gci_preinit_upd_indirect(uint32 regidx, uint32 setval, uint32 mask);
-extern uint8 si_enable_device_wake(si_t *sih, uint8 *wake_status, uint8 *cur_status);
-extern void si_swdenable(si_t *sih, uint32 swdflag);
-
-#define CHIPCTRLREG1 0x1
-#define CHIPCTRLREG2 0x2
-#define CHIPCTRLREG3 0x3
-#define CHIPCTRLREG4 0x4
-#define CHIPCTRLREG5 0x5
-#define MINRESMASKREG 0x618
-#define MAXRESMASKREG 0x61c
-#define CHIPCTRLADDR 0x650
-#define CHIPCTRLDATA 0x654
-#define RSRCTABLEADDR 0x620
-#define RSRCUPDWNTIME 0x628
-#define PMUREG_RESREQ_MASK 0x68c
-
-void si_update_masks(si_t *sih);
-void si_force_islanding(si_t *sih, bool enable);
-extern uint32 si_pmu_res_req_timer_clr(si_t *sih);
-extern void si_pmu_rfldo(si_t *sih, bool on);
-extern void si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 spert_val);
-extern uint32 si_pcie_set_ctrlreg(si_t *sih, uint32 sperst_mask, uint32 spert_val);
-extern void si_pcie_ltr_war(si_t *sih);
-extern void si_pcie_hw_LTR_war(si_t *sih);
-extern void si_pcie_hw_L1SS_war(si_t *sih);
-extern void si_pciedev_crwlpciegen2(si_t *sih);
-extern void si_pcie_prep_D3(si_t *sih, bool enter_D3);
-extern void si_pciedev_reg_pm_clk_period(si_t *sih);
-
-#ifdef WLRSDB
-extern void si_d11rsdb_core_disable(si_t *sih, uint32 bits);
-extern void si_d11rsdb_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
-#endif
-
-
-/* Macro to enable clock gating changes in different cores */
-#define MEM_CLK_GATE_BIT 	5
-#define GCI_CLK_GATE_BIT 	18
-
-#define USBAPP_CLK_BIT		0
-#define PCIE_CLK_BIT		3
-#define ARMCR4_DBG_CLK_BIT	4
-#define SAMPLE_SYNC_CLK_BIT 	17
-#define PCIE_TL_CLK_BIT		18
-#define HQ_REQ_BIT		24
-#define PLL_DIV2_BIT_START	9
-#define PLL_DIV2_MASK		(0x37 << PLL_DIV2_BIT_START)
-#define PLL_DIV2_DIS_OP		(0x37 << PLL_DIV2_BIT_START)
-
-#define pmu_corereg(si, cc_idx, member, mask, val) \
-	(AOB_ENAB(si) ? \
-		si_pmu_corereg(si, si_findcoreidx(si, PMU_CORE_ID, 0), \
-			       OFFSETOF(pmuregs_t, member), mask, val): \
-		si_pmu_corereg(si, cc_idx, OFFSETOF(chipcregs_t, member), mask, val))
-
-/* GCI Macros */
-#define ALLONES_32				0xFFFFFFFF
-#define GCI_CCTL_SECIRST_OFFSET			0 /**< SeciReset */
-#define GCI_CCTL_RSTSL_OFFSET			1 /**< ResetSeciLogic */
-#define GCI_CCTL_SECIEN_OFFSET			2 /**< EnableSeci  */
-#define GCI_CCTL_FSL_OFFSET			3 /**< ForceSeciOutLow */
-#define GCI_CCTL_SMODE_OFFSET			4 /**< SeciOpMode, 6:4 */
-#define GCI_CCTL_US_OFFSET			7 /**< UpdateSeci */
-#define GCI_CCTL_BRKONSLP_OFFSET		8 /**< BreakOnSleep */
-#define GCI_CCTL_SILOWTOUT_OFFSET		9 /**< SeciInLowTimeout, 10:9 */
-#define GCI_CCTL_RSTOCC_OFFSET			11 /**< ResetOffChipCoex */
-#define GCI_CCTL_ARESEND_OFFSET			12 /**< AutoBTSigResend */
-#define GCI_CCTL_FGCR_OFFSET			16 /**< ForceGciClkReq */
-#define GCI_CCTL_FHCRO_OFFSET			17 /**< ForceHWClockReqOff */
-#define GCI_CCTL_FREGCLK_OFFSET			18 /**< ForceRegClk */
-#define GCI_CCTL_FSECICLK_OFFSET		19 /**< ForceSeciClk */
-#define GCI_CCTL_FGCA_OFFSET			20 /**< ForceGciClkAvail */
-#define GCI_CCTL_FGCAV_OFFSET			21 /**< ForceGciClkAvailValue */
-#define GCI_CCTL_SCS_OFFSET			24 /**< SeciClkStretch, 31:24 */
-
-#define GCI_MODE_UART				0x0
-#define GCI_MODE_SECI				0x1
-#define GCI_MODE_BTSIG				0x2
-#define GCI_MODE_GPIO				0x3
-#define GCI_MODE_MASK				0x7
-
-#define GCI_CCTL_LOWTOUT_DIS			0x0
-#define GCI_CCTL_LOWTOUT_10BIT			0x1
-#define GCI_CCTL_LOWTOUT_20BIT			0x2
-#define GCI_CCTL_LOWTOUT_30BIT			0x3
-#define GCI_CCTL_LOWTOUT_MASK			0x3
-
-#define GCI_CCTL_SCS_DEF			0x19
-#define GCI_CCTL_SCS_MASK			0xFF
-
-#define GCI_SECIIN_MODE_OFFSET			0
-#define GCI_SECIIN_GCIGPIO_OFFSET		4
-#define GCI_SECIIN_RXID2IP_OFFSET		8
-
-#define GCI_SECIOUT_MODE_OFFSET			0
-#define GCI_SECIOUT_GCIGPIO_OFFSET		4
-#define GCI_SECIOUT_SECIINRELATED_OFFSET	16
-
-#define GCI_SECIAUX_RXENABLE_OFFSET		0
-#define GCI_SECIFIFO_RXENABLE_OFFSET		16
-
-#define GCI_SECITX_ENABLE_OFFSET		0
-
-#define GCI_GPIOCTL_INEN_OFFSET			0
-#define GCI_GPIOCTL_OUTEN_OFFSET		1
-#define GCI_GPIOCTL_PDN_OFFSET			4
-
-#define GCI_GPIOIDX_OFFSET			16
-
-#define GCI_LTECX_SECI_ID			0 /**< SECI port for LTECX */
-
-/* To access per GCI bit registers */
-#define GCI_REG_WIDTH				32
-
-/* GCI bit positions */
-/* GCI [127:000] = WLAN [127:0] */
-#define GCI_WLAN_IP_ID				0
-#define GCI_WLAN_BEGIN				0
-#define GCI_WLAN_PRIO_POS			(GCI_WLAN_BEGIN + 4)
-
-/* GCI [639:512] = LTE [127:0] */
-#define GCI_LTE_IP_ID				4
-#define GCI_LTE_BEGIN				512
-#define GCI_LTE_FRAMESYNC_POS			(GCI_LTE_BEGIN + 0)
-#define GCI_LTE_RX_POS				(GCI_LTE_BEGIN + 1)
-#define GCI_LTE_TX_POS				(GCI_LTE_BEGIN + 2)
-#define GCI_LTE_AUXRXDVALID_POS			(GCI_LTE_BEGIN + 56)
-
-/* Reg Index corresponding to ECI bit no x of ECI space */
-#define GCI_REGIDX(x)				((x)/GCI_REG_WIDTH)
-/* Bit offset of ECI bit no x in 32-bit words */
-#define GCI_BITOFFSET(x)			((x)%GCI_REG_WIDTH)
-
-/* End - GCI Macros */
-
-#ifdef REROUTE_OOBINT
-#define CC_OOB          0x0
-#define M2MDMA_OOB      0x1
-#define PMU_OOB         0x2
-#define D11_OOB         0x3
-#define SDIOD_OOB       0x4
-#define WLAN_OOB	0x5
-#define PMU_OOB_BIT     0x12
-#endif /* REROUTE_OOBINT */
-
-extern void si_pll_sr_reinit(si_t *sih);
-extern void si_pll_closeloop(si_t *sih);
-
-#endif	/* _siutils_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/spid.h b/drivers/net/wireless/bcmdhd/include/spid.h
deleted file mode 100644
index 9a39aaf..0000000
--- a/drivers/net/wireless/bcmdhd/include/spid.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * SPI device spec header file
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: spid.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef	_SPI_H
-#define	_SPI_H
-
-/*
- * Brcm SPI Device Register Map.
- *
- */
-
-typedef volatile struct {
-	uint8	config;			/* 0x00, len, endian, clock, speed, polarity, wakeup */
-	uint8	response_delay;		/* 0x01, read response delay in bytes (corerev < 3) */
-	uint8	status_enable;		/* 0x02, status-enable, intr with status, response_delay
-					 * function selection, command/data error check
-					 */
-	uint8	reset_bp;		/* 0x03, reset on wlan/bt backplane reset (corerev >= 1) */
-	uint16	intr_reg;		/* 0x04, Intr status register */
-	uint16	intr_en_reg;		/* 0x06, Intr mask register */
-	uint32	status_reg;		/* 0x08, RO, Status bits of last spi transfer */
-	uint16	f1_info_reg;		/* 0x0c, RO, enabled, ready for data transfer, blocksize */
-	uint16	f2_info_reg;		/* 0x0e, RO, enabled, ready for data transfer, blocksize */
-	uint16	f3_info_reg;		/* 0x10, RO, enabled, ready for data transfer, blocksize */
-	uint32	test_read;		/* 0x14, RO 0xfeedbead signature */
-	uint32	test_rw;		/* 0x18, RW */
-	uint8	resp_delay_f0;		/* 0x1c, read resp delay bytes for F0 (corerev >= 3) */
-	uint8	resp_delay_f1;		/* 0x1d, read resp delay bytes for F1 (corerev >= 3) */
-	uint8	resp_delay_f2;		/* 0x1e, read resp delay bytes for F2 (corerev >= 3) */
-	uint8	resp_delay_f3;		/* 0x1f, read resp delay bytes for F3 (corerev >= 3) */
-} spi_regs_t;
-
-/* SPI device register offsets */
-#define SPID_CONFIG			0x00
-#define SPID_RESPONSE_DELAY		0x01
-#define SPID_STATUS_ENABLE		0x02
-#define SPID_RESET_BP			0x03	/* (corerev >= 1) */
-#define SPID_INTR_REG			0x04	/* 16 bits - Interrupt status */
-#define SPID_INTR_EN_REG		0x06	/* 16 bits - Interrupt mask */
-#define SPID_STATUS_REG			0x08	/* 32 bits */
-#define SPID_F1_INFO_REG		0x0C	/* 16 bits */
-#define SPID_F2_INFO_REG		0x0E	/* 16 bits */
-#define SPID_F3_INFO_REG		0x10	/* 16 bits */
-#define SPID_TEST_READ			0x14	/* 32 bits */
-#define SPID_TEST_RW			0x18	/* 32 bits */
-#define SPID_RESP_DELAY_F0		0x1c	/* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F1		0x1d	/* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F2		0x1e	/* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F3		0x1f	/* 8 bits (corerev >= 3) */
-
-/* Bit masks for SPID_CONFIG device register */
-#define WORD_LENGTH_32	0x1	/* 0/1 16/32 bit word length */
-#define ENDIAN_BIG	0x2	/* 0/1 Little/Big Endian */
-#define CLOCK_PHASE	0x4	/* 0/1 clock phase delay */
-#define CLOCK_POLARITY	0x8	/* 0/1 Idle state clock polarity is low/high */
-#define HIGH_SPEED_MODE	0x10	/* 1/0 High Speed mode / Normal mode */
-#define INTR_POLARITY	0x20	/* 1/0 Interrupt active polarity is high/low */
-#define WAKE_UP		0x80	/* 0/1 Wake-up command from Host to WLAN */
-
-/* Bit mask for SPID_RESPONSE_DELAY device register */
-#define RESPONSE_DELAY_MASK	0xFF	/* Configurable rd response delay in multiples of 8 bits */
-
-/* Bit mask for SPID_STATUS_ENABLE device register */
-#define STATUS_ENABLE		0x1	/* 1/0 Status sent/not sent to host after read/write */
-#define INTR_WITH_STATUS	0x2	/* 0/1 Do-not / do-interrupt if status is sent */
-#define RESP_DELAY_ALL		0x4	/* Applicability of resp delay to F1 or all func's read */
-#define DWORD_PKT_LEN_EN	0x8	/* Packet len denoted in dwords instead of bytes */
-#define CMD_ERR_CHK_EN		0x20	/* Command error check enable */
-#define DATA_ERR_CHK_EN		0x40	/* Data error check enable */
-
-/* Bit mask for SPID_RESET_BP device register */
-#define RESET_ON_WLAN_BP_RESET	0x4	/* enable reset for WLAN backplane */
-#define RESET_ON_BT_BP_RESET	0x8	/* enable reset for BT backplane */
-#define RESET_SPI		0x80	/* reset the above enabled logic */
-
-/* Bit mask for SPID_INTR_REG device register */
-#define DATA_UNAVAILABLE	0x0001	/* Requested data not available; Clear by writing a "1" */
-#define F2_F3_FIFO_RD_UNDERFLOW	0x0002
-#define F2_F3_FIFO_WR_OVERFLOW	0x0004
-#define COMMAND_ERROR		0x0008	/* Cleared by writing 1 */
-#define DATA_ERROR		0x0010	/* Cleared by writing 1 */
-#define F2_PACKET_AVAILABLE	0x0020
-#define F3_PACKET_AVAILABLE	0x0040
-#define F1_OVERFLOW		0x0080	/* Due to last write. Bkplane has pending write requests */
-#define MISC_INTR0		0x0100
-#define MISC_INTR1		0x0200
-#define MISC_INTR2		0x0400
-#define MISC_INTR3		0x0800
-#define MISC_INTR4		0x1000
-#define F1_INTR			0x2000
-#define F2_INTR			0x4000
-#define F3_INTR			0x8000
-
-/* Bit mask for 32bit SPID_STATUS_REG device register */
-#define STATUS_DATA_NOT_AVAILABLE	0x00000001
-#define STATUS_UNDERFLOW		0x00000002
-#define STATUS_OVERFLOW			0x00000004
-#define STATUS_F2_INTR			0x00000008
-#define STATUS_F3_INTR			0x00000010
-#define STATUS_F2_RX_READY		0x00000020
-#define STATUS_F3_RX_READY		0x00000040
-#define STATUS_HOST_CMD_DATA_ERR	0x00000080
-#define STATUS_F2_PKT_AVAILABLE		0x00000100
-#define STATUS_F2_PKT_LEN_MASK		0x000FFE00
-#define STATUS_F2_PKT_LEN_SHIFT		9
-#define STATUS_F3_PKT_AVAILABLE		0x00100000
-#define STATUS_F3_PKT_LEN_MASK		0xFFE00000
-#define STATUS_F3_PKT_LEN_SHIFT		21
-
-/* Bit mask for 16 bits SPID_F1_INFO_REG device register */
-#define F1_ENABLED 			0x0001
-#define F1_RDY_FOR_DATA_TRANSFER	0x0002
-#define F1_MAX_PKT_SIZE			0x01FC
-
-/* Bit mask for 16 bits SPID_F2_INFO_REG device register */
-#define F2_ENABLED 			0x0001
-#define F2_RDY_FOR_DATA_TRANSFER	0x0002
-#define F2_MAX_PKT_SIZE			0x3FFC
-
-/* Bit mask for 16 bits SPID_F3_INFO_REG device register */
-#define F3_ENABLED 			0x0001
-#define F3_RDY_FOR_DATA_TRANSFER	0x0002
-#define F3_MAX_PKT_SIZE			0x3FFC
-
-/* Bit mask for 32 bits SPID_TEST_READ device register read in 16bit LE mode */
-#define TEST_RO_DATA_32BIT_LE		0xFEEDBEAD
-
-/* Maximum number of I/O funcs */
-#define SPI_MAX_IOFUNCS		4
-
-#define SPI_MAX_PKT_LEN		(2048*4)
-
-/* Misc defines */
-#define SPI_FUNC_0		0
-#define SPI_FUNC_1		1
-#define SPI_FUNC_2		2
-#define SPI_FUNC_3		3
-
-#define WAIT_F2RXFIFORDY	100
-#define WAIT_F2RXFIFORDY_DELAY	20
-
-#endif /* _SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/include/trxhdr.h b/drivers/net/wireless/bcmdhd/include/trxhdr.h
deleted file mode 100644
index f7404be..0000000
--- a/drivers/net/wireless/bcmdhd/include/trxhdr.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * TRX image file header format.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: trxhdr.h 520026 2014-12-10 01:29:40Z $
- */
-
-#ifndef _TRX_HDR_H
-#define _TRX_HDR_H
-
-#include <typedefs.h>
-
-#define TRX_MAGIC	0x30524448	/* "HDR0" */
-#define TRX_MAX_LEN	0x3B0000	/* Max length */
-#define TRX_NO_HEADER	1		/* Do not write TRX header */
-#define TRX_GZ_FILES	0x2     /* Contains up to TRX_MAX_OFFSET individual gzip files */
-#define TRX_EMBED_UCODE	0x8	/* Trx contains embedded ucode image */
-#define TRX_ROMSIM_IMAGE	0x10	/* Trx contains ROM simulation image */
-#define TRX_UNCOMP_IMAGE	0x20	/* Trx contains uncompressed rtecdc.bin image */
-#define TRX_BOOTLOADER		0x40	/* the image is a bootloader */
-
-#define TRX_V1		1
-#define TRX_V1_MAX_OFFSETS	3		/* V1: Max number of individual files */
-
-#ifndef BCMTRXV2
-#define TRX_VERSION	TRX_V1		/* Version 1 */
-#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS
-#endif
-
-/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as
- * Ver 2 of trx header. To make it generic, trx_header is structure is modified
- * as below where size of "offsets" field will vary as per the TRX version.
- * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well.
- * To make sure, other applications like "dhdl" which are yet to be enhanced to support
- * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2
- * is defined.
- */
-struct trx_header {
-	uint32 magic;		/* "HDR0" */
-	uint32 len;		/* Length of file including header */
-	uint32 crc32;		/* 32-bit CRC from flag_version to end of file */
-	uint32 flag_version;	/* 0:15 flags, 16:31 version */
-#ifndef BCMTRXV2
-	uint32 offsets[TRX_MAX_OFFSET];	/* Offsets of partitions from start of header */
-#else
-	uint32 offsets[1];	/* Offsets of partitions from start of header */
-#endif
-};
-
-#ifdef BCMTRXV2
-#define TRX_VERSION		TRX_V2		/* Version 2 */
-#define TRX_MAX_OFFSET  TRX_V2_MAX_OFFSETS
-
-#define TRX_V2		2
-/* V2: Max number of individual files
- * To support SDR signature + Config data region
- */
-#define TRX_V2_MAX_OFFSETS	5
-#define SIZEOF_TRXHDR_V1	(sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32))
-#define SIZEOF_TRXHDR_V2	(sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32))
-#define TRX_VER(trx)		((trx)->flag_version>>16)
-#define ISTRX_V1(trx)		(TRX_VER(trx) == TRX_V1)
-#define ISTRX_V2(trx)		(TRX_VER(trx) == TRX_V2)
-/* For V2, return size of V2 size: others, return V1 size */
-#define SIZEOF_TRX(trx)	    (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1)
-#else
-#define SIZEOF_TRX(trx)	    (sizeof(struct trx_header))
-#endif /* BCMTRXV2 */
-
-/* Compatibility */
-typedef struct trx_header TRXHDR, *PTRXHDR;
-
-#endif /* _TRX_HDR_H */
diff --git a/drivers/net/wireless/bcmdhd/include/typedefs.h b/drivers/net/wireless/bcmdhd/include/typedefs.h
deleted file mode 100644
index 0e110a1..0000000
--- a/drivers/net/wireless/bcmdhd/include/typedefs.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: typedefs.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef _TYPEDEFS_H_
-#define _TYPEDEFS_H_
-
-#ifdef SITE_TYPEDEFS
-
-/*
- * Define SITE_TYPEDEFS in the compile to include a site-specific
- * typedef file "site_typedefs.h".
- *
- * If SITE_TYPEDEFS is not defined, then the code section below makes
- * inferences about the compile environment based on defined symbols and
- * possibly compiler pragmas.
- *
- * Following these two sections is the Default Typedefs section.
- * This section is only processed if USE_TYPEDEF_DEFAULTS is
- * defined. This section has a default set of typedefs and a few
- * preprocessor symbols (TRUE, FALSE, NULL, ...).
- */
-
-#include "site_typedefs.h"
-
-#else
-
-/*
- * Infer the compile environment based on preprocessor symbols and pragmas.
- * Override type definitions as needed, and include configuration-dependent
- * header files to define types.
- */
-
-#ifdef __cplusplus
-
-#define TYPEDEF_BOOL
-#ifndef FALSE
-#define FALSE	false
-#endif
-#ifndef TRUE
-#define TRUE	true
-#endif
-
-#else	/* ! __cplusplus */
-
-
-#endif	/* ! __cplusplus */
-
-#if defined(__LP64__)
-#define TYPEDEF_UINTPTR
-typedef unsigned long long int uintptr;
-#endif
-
-
-
-
-
-#if defined(_NEED_SIZE_T_)
-typedef long unsigned int size_t;
-#endif
-
-
-
-
-
-#if defined(__sparc__)
-#define TYPEDEF_ULONG
-#endif
-
-/*
- * If this is either a Linux hybrid build or the per-port code of a hybrid build
- * then use the Linux header files to get some of the typedefs.  Otherwise, define
- * them entirely in this file.  We can't always define the types because we get
- * a duplicate typedef error; there is no way to "undefine" a typedef.
- * We know when it's per-port code because each file defines LINUX_PORT at the top.
- */
-#define TYPEDEF_UINT
-#ifndef TARGETENV_android
-#define TYPEDEF_USHORT
-#define TYPEDEF_ULONG
-#endif /* TARGETENV_android */
-#ifdef __KERNEL__
-#include <linux/version.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
-#define TYPEDEF_BOOL
-#endif	/* >= 2.6.19 */
-/* special detection for 2.6.18-128.7.1.0.1.el5 */
-#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18))
-#include <linux/compiler.h>
-#ifdef noinline_for_stack
-#define TYPEDEF_BOOL
-#endif
-#endif	/* == 2.6.18 */
-#endif	/* __KERNEL__ */
-
-
-/* Do not support the (u)int64 types with strict ansi for GNU C */
-#if defined(__GNUC__) && defined(__STRICT_ANSI__)
-#define TYPEDEF_INT64
-#define TYPEDEF_UINT64
-#endif /* defined(__GNUC__) && defined(__STRICT_ANSI__) */
-
-/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode
- * for signed or unsigned
- */
-#if defined(__ICL)
-
-#define TYPEDEF_INT64
-
-#if defined(__STDC__)
-#define TYPEDEF_UINT64
-#endif
-
-#endif /* __ICL */
-
-#if !defined(__DJGPP__)
-
-/* pick up ushort & uint from standard types.h */
-#if defined(__KERNEL__)
-
-/* See note above */
-#include <linux/types.h>	/* sys/types.h and linux/types.h are oil and water */
-
-#else
-
-#include <sys/types.h>
-
-#endif /* linux && __KERNEL__ */
-
-#endif 
-
-
-/* use the default typedefs in the next section of this file */
-#define USE_TYPEDEF_DEFAULTS
-
-#endif /* SITE_TYPEDEFS */
-
-
-/*
- * Default Typedefs
- */
-
-#ifdef USE_TYPEDEF_DEFAULTS
-#undef USE_TYPEDEF_DEFAULTS
-
-#ifndef TYPEDEF_BOOL
-typedef	/* @abstract@ */ unsigned char	bool;
-#endif /* endif TYPEDEF_BOOL */
-
-/* define uchar, ushort, uint, ulong */
-
-#ifndef TYPEDEF_UCHAR
-typedef unsigned char	uchar;
-#endif
-
-#ifndef TYPEDEF_USHORT
-typedef unsigned short	ushort;
-#endif
-
-#ifndef TYPEDEF_UINT
-typedef unsigned int	uint;
-#endif
-
-#ifndef TYPEDEF_ULONG
-typedef unsigned long	ulong;
-#endif
-
-/* define [u]int8/16/32/64, uintptr */
-
-#ifndef TYPEDEF_UINT8
-typedef unsigned char	uint8;
-#endif
-
-#ifndef TYPEDEF_UINT16
-typedef unsigned short	uint16;
-#endif
-
-#ifndef TYPEDEF_UINT32
-typedef unsigned int	uint32;
-#endif
-
-#ifndef TYPEDEF_UINT64
-typedef unsigned long long uint64;
-#endif
-
-#ifndef TYPEDEF_UINTPTR
-typedef unsigned int	uintptr;
-#endif
-
-#ifndef TYPEDEF_INT8
-typedef signed char	int8;
-#endif
-
-#ifndef TYPEDEF_INT16
-typedef signed short	int16;
-#endif
-
-#ifndef TYPEDEF_INT32
-typedef signed int	int32;
-#endif
-
-#ifndef TYPEDEF_INT64
-typedef signed long long int64;
-#endif
-
-/* define float32/64, float_t */
-
-#ifndef TYPEDEF_FLOAT32
-typedef float		float32;
-#endif
-
-#ifndef TYPEDEF_FLOAT64
-typedef double		float64;
-#endif
-
-/*
- * abstracted floating point type allows for compile time selection of
- * single or double precision arithmetic.  Compiling with -DFLOAT32
- * selects single precision; the default is double precision.
- */
-
-#ifndef TYPEDEF_FLOAT_T
-
-#if defined(FLOAT32)
-typedef float32 float_t;
-#else /* default to double precision floating point */
-typedef float64 float_t;
-#endif
-
-#endif /* TYPEDEF_FLOAT_T */
-
-/* define macro values */
-
-#ifndef FALSE
-#define FALSE	0
-#endif
-
-#ifndef TRUE
-#define TRUE	1  /* TRUE */
-#endif
-
-#ifndef NULL
-#define	NULL	0
-#endif
-
-#ifndef OFF
-#define	OFF	0
-#endif
-
-#ifndef ON
-#define	ON	1  /* ON = 1 */
-#endif
-
-#define	AUTO	(-1) /* Auto = -1 */
-
-/* define PTRSZ, INLINE */
-
-#ifndef PTRSZ
-#define	PTRSZ	sizeof(char*)
-#endif
-
-
-/* Detect compiler type. */
-#if defined(__GNUC__) || defined(__lint)
-	#define BWL_COMPILER_GNU
-#elif defined(__CC_ARM) && __CC_ARM
-	#define BWL_COMPILER_ARMCC
-#else
-	#error "Unknown compiler!"
-#endif 
-
-
-#ifndef INLINE
-	#if defined(BWL_COMPILER_MICROSOFT)
-		#define INLINE __inline
-	#elif defined(BWL_COMPILER_GNU)
-		#define INLINE __inline__
-	#elif defined(BWL_COMPILER_ARMCC)
-		#define INLINE	__inline
-	#else
-		#define INLINE
-	#endif 
-#endif /* INLINE */
-
-#undef TYPEDEF_BOOL
-#undef TYPEDEF_UCHAR
-#undef TYPEDEF_USHORT
-#undef TYPEDEF_UINT
-#undef TYPEDEF_ULONG
-#undef TYPEDEF_UINT8
-#undef TYPEDEF_UINT16
-#undef TYPEDEF_UINT32
-#undef TYPEDEF_UINT64
-#undef TYPEDEF_UINTPTR
-#undef TYPEDEF_INT8
-#undef TYPEDEF_INT16
-#undef TYPEDEF_INT32
-#undef TYPEDEF_INT64
-#undef TYPEDEF_FLOAT32
-#undef TYPEDEF_FLOAT64
-#undef TYPEDEF_FLOAT_T
-
-#endif /* USE_TYPEDEF_DEFAULTS */
-
-/* Suppress unused parameter warning */
-#define UNUSED_PARAMETER(x) (void)(x)
-
-/* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */
-#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr))
-
-/*
- * Including the bcmdefs.h here, to make sure everyone including typedefs.h
- * gets this automatically
-*/
-#include <bcmdefs.h>
-#endif /* _TYPEDEFS_H_ */
diff --git a/drivers/net/wireless/bcmdhd/include/wlfc_proto.h b/drivers/net/wireless/bcmdhd/include/wlfc_proto.h
deleted file mode 100644
index 0d5b434..0000000
--- a/drivers/net/wireless/bcmdhd/include/wlfc_proto.h
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wlfc_proto.h 542895 2015-03-22 14:13:12Z $
- *
- */
-
-/** WL flow control for PROP_TXSTATUS. Related to host AMPDU reordering. */
-
-
-#ifndef __wlfc_proto_definitions_h__
-#define __wlfc_proto_definitions_h__
-
-	/* Use TLV to convey WLFC information.
-	 ---------------------------------------------------------------------------
-	| Type |  Len | value                    | Description
-	 ---------------------------------------------------------------------------
-	|  1   |   1  | (handle)                 | MAC OPEN
-	 ---------------------------------------------------------------------------
-	|  2   |   1  | (handle)                 | MAC CLOSE
-	 ---------------------------------------------------------------------------
-	|  3   |   2  | (count, handle, prec_bmp)| Set the credit depth for a MAC dstn
-	 ---------------------------------------------------------------------------
-	|  4   |   4+ | see pkttag comments      | TXSTATUS
-	|      |   12 | TX status & timestamps   | Present only when pkt timestamp is enabled
-	 ---------------------------------------------------------------------------
-	|  5   |   4  | see pkttag comments      | PKKTTAG [host->firmware]
-	 ---------------------------------------------------------------------------
-	|  6   |   8  | (handle, ifid, MAC)      | MAC ADD
-	 ---------------------------------------------------------------------------
-	|  7   |   8  | (handle, ifid, MAC)      | MAC DEL
-	 ---------------------------------------------------------------------------
-	|  8   |   1  | (rssi)                   | RSSI - RSSI value for the packet.
-	 ---------------------------------------------------------------------------
-	|  9   |   1  | (interface ID)           | Interface OPEN
-	 ---------------------------------------------------------------------------
-	|  10  |   1  | (interface ID)           | Interface CLOSE
-	 ---------------------------------------------------------------------------
-	|  11  |   8  | fifo credit returns map  | FIFO credits back to the host
-	|      |      |                          |
-	|      |      |                          | --------------------------------------
-	|      |      |                          | | ac0 | ac1 | ac2 | ac3 | bcmc | atim |
-	|      |      |                          | --------------------------------------
-	|      |      |                          |
-	 ---------------------------------------------------------------------------
-	|  12  |   2  | MAC handle,              | Host provides a bitmap of pending
-	|      |      | AC[0-3] traffic bitmap   | unicast traffic for MAC-handle dstn.
-	|      |      |                          | [host->firmware]
-	 ---------------------------------------------------------------------------
-	|  13  |   3  | (count, handle, prec_bmp)| One time request for packet to a specific
-	|      |      |                          | MAC destination.
-	 ---------------------------------------------------------------------------
-	|  15  |  12  | (pkttag, timestamps)     | Send TX timestamp at reception from host
-	 ---------------------------------------------------------------------------
-	|  16  |  12  | (pkttag, timestamps)     | Send WLAN RX timestamp along with RX frame
-	 ---------------------------------------------------------------------------
-	| 255  |  N/A |  N/A                     | FILLER - This is a special type
-	|      |      |                          | that has no length or value.
-	|      |      |                          | Typically used for padding.
-	 ---------------------------------------------------------------------------
-	*/
-
-#define WLFC_CTL_TYPE_MAC_OPEN			1
-#define WLFC_CTL_TYPE_MAC_CLOSE			2
-#define WLFC_CTL_TYPE_MAC_REQUEST_CREDIT	3
-#define WLFC_CTL_TYPE_TXSTATUS			4
-#define WLFC_CTL_TYPE_PKTTAG			5	/** host<->dongle */
-
-#define WLFC_CTL_TYPE_MACDESC_ADD		6
-#define WLFC_CTL_TYPE_MACDESC_DEL		7
-#define WLFC_CTL_TYPE_RSSI			8
-
-#define WLFC_CTL_TYPE_INTERFACE_OPEN		9
-#define WLFC_CTL_TYPE_INTERFACE_CLOSE		10
-
-#define WLFC_CTL_TYPE_FIFO_CREDITBACK		11
-
-#define WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP	12	/** host->dongle */
-#define WLFC_CTL_TYPE_MAC_REQUEST_PACKET	13
-#define WLFC_CTL_TYPE_HOST_REORDER_RXPKTS	14
-
-#define WLFC_CTL_TYPE_TX_ENTRY_STAMP		15
-#define WLFC_CTL_TYPE_RX_STAMP			16
-#define WLFC_CTL_TYPE_TX_STATUS_STAMP		17	/** obsolete */
-
-#define WLFC_CTL_TYPE_TRANS_ID			18
-#define WLFC_CTL_TYPE_COMP_TXSTATUS		19
-
-#define WLFC_CTL_TYPE_TID_OPEN			20
-#define WLFC_CTL_TYPE_TID_CLOSE			21
-
-
-#define WLFC_CTL_TYPE_FILLER			255
-
-#define WLFC_CTL_VALUE_LEN_MACDESC		8	/** handle, interface, MAC */
-
-#define WLFC_CTL_VALUE_LEN_MAC			1	/** MAC-handle */
-#define WLFC_CTL_VALUE_LEN_RSSI			1
-
-#define WLFC_CTL_VALUE_LEN_INTERFACE		1
-#define WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP	2
-
-#define WLFC_CTL_VALUE_LEN_TXSTATUS		4
-#define WLFC_CTL_VALUE_LEN_PKTTAG		4
-#define WLFC_CTL_VALUE_LEN_TIMESTAMP		12	/** 4-byte rate info + 2 TSF */
-
-#define WLFC_CTL_VALUE_LEN_SEQ			2
-
-/* The high bits of ratespec report in timestamp are used for various status */
-#define WLFC_TSFLAGS_RX_RETRY		(1 << 31)
-#define WLFC_TSFLAGS_PM_ENABLED		(1 << 30)
-#define WLFC_TSFLAGS_MASK		(WLFC_TSFLAGS_RX_RETRY | WLFC_TSFLAGS_PM_ENABLED)
-
-/* enough space to host all 4 ACs, bc/mc and atim fifo credit */
-#define WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK	6
-
-#define WLFC_CTL_VALUE_LEN_REQUEST_CREDIT	3	/* credit, MAC-handle, prec_bitmap */
-#define WLFC_CTL_VALUE_LEN_REQUEST_PACKET	3	/* credit, MAC-handle, prec_bitmap */
-
-
-#define WLFC_PKTFLAG_PKTFROMHOST	0x01
-#define WLFC_PKTFLAG_PKT_REQUESTED	0x02
-
-#define WL_TXSTATUS_STATUS_MASK			0xff /* allow 8 bits */
-#define WL_TXSTATUS_STATUS_SHIFT		24
-
-#define WL_TXSTATUS_SET_STATUS(x, status)	((x)  = \
-	((x) & ~(WL_TXSTATUS_STATUS_MASK << WL_TXSTATUS_STATUS_SHIFT)) | \
-	(((status) & WL_TXSTATUS_STATUS_MASK) << WL_TXSTATUS_STATUS_SHIFT))
-#define WL_TXSTATUS_GET_STATUS(x)	(((x) >> WL_TXSTATUS_STATUS_SHIFT) & \
-	WL_TXSTATUS_STATUS_MASK)
-
-/**
- * Bit 31 of the 32-bit packet tag is defined as 'generation ID'. It is set by the host to the
- * "current" generation, and by the firmware to the "expected" generation, toggling on suppress. The
- * firmware accepts a packet when the generation matches; on reset (startup) both "current" and
- * "expected" are set to 0.
- */
-#define WL_TXSTATUS_GENERATION_MASK		1 /* allow 1 bit */
-#define WL_TXSTATUS_GENERATION_SHIFT		31
-
-#define WL_TXSTATUS_SET_GENERATION(x, gen)	((x) = \
-	((x) & ~(WL_TXSTATUS_GENERATION_MASK << WL_TXSTATUS_GENERATION_SHIFT)) | \
-	(((gen) & WL_TXSTATUS_GENERATION_MASK) << WL_TXSTATUS_GENERATION_SHIFT))
-
-#define WL_TXSTATUS_GET_GENERATION(x)	(((x) >> WL_TXSTATUS_GENERATION_SHIFT) & \
-	WL_TXSTATUS_GENERATION_MASK)
-
-#define WL_TXSTATUS_FLAGS_MASK			0xf /* allow 4 bits only */
-#define WL_TXSTATUS_FLAGS_SHIFT			27
-
-#define WL_TXSTATUS_SET_FLAGS(x, flags)	((x)  = \
-	((x) & ~(WL_TXSTATUS_FLAGS_MASK << WL_TXSTATUS_FLAGS_SHIFT)) | \
-	(((flags) & WL_TXSTATUS_FLAGS_MASK) << WL_TXSTATUS_FLAGS_SHIFT))
-#define WL_TXSTATUS_GET_FLAGS(x)		(((x) >> WL_TXSTATUS_FLAGS_SHIFT) & \
-	WL_TXSTATUS_FLAGS_MASK)
-
-#define WL_TXSTATUS_FIFO_MASK			0x7 /* allow 3 bits for FIFO ID */
-#define WL_TXSTATUS_FIFO_SHIFT			24
-
-#define WL_TXSTATUS_SET_FIFO(x, flags)	((x)  = \
-	((x) & ~(WL_TXSTATUS_FIFO_MASK << WL_TXSTATUS_FIFO_SHIFT)) | \
-	(((flags) & WL_TXSTATUS_FIFO_MASK) << WL_TXSTATUS_FIFO_SHIFT))
-#define WL_TXSTATUS_GET_FIFO(x)		(((x) >> WL_TXSTATUS_FIFO_SHIFT) & WL_TXSTATUS_FIFO_MASK)
-
-#define WL_TXSTATUS_PKTID_MASK			0xffffff /* allow 24 bits */
-#define WL_TXSTATUS_SET_PKTID(x, num)	((x) = \
-	((x) & ~WL_TXSTATUS_PKTID_MASK) | (num))
-#define WL_TXSTATUS_GET_PKTID(x)		((x) & WL_TXSTATUS_PKTID_MASK)
-
-#define WL_TXSTATUS_HSLOT_MASK			0xffff /* allow 16 bits */
-#define WL_TXSTATUS_HSLOT_SHIFT			8
-
-#define WL_TXSTATUS_SET_HSLOT(x, hslot)	((x)  = \
-	((x) & ~(WL_TXSTATUS_HSLOT_MASK << WL_TXSTATUS_HSLOT_SHIFT)) | \
-	(((hslot) & WL_TXSTATUS_HSLOT_MASK) << WL_TXSTATUS_HSLOT_SHIFT))
-#define WL_TXSTATUS_GET_HSLOT(x)	(((x) >> WL_TXSTATUS_HSLOT_SHIFT)& \
-	WL_TXSTATUS_HSLOT_MASK)
-
-#define WL_TXSTATUS_FREERUNCTR_MASK		0xff /* allow 8 bits */
-
-#define WL_TXSTATUS_SET_FREERUNCTR(x, ctr)	((x)  = \
-	((x) & ~(WL_TXSTATUS_FREERUNCTR_MASK)) | \
-	((ctr) & WL_TXSTATUS_FREERUNCTR_MASK))
-#define WL_TXSTATUS_GET_FREERUNCTR(x)		((x)& WL_TXSTATUS_FREERUNCTR_MASK)
-
-/* Seq number part of AMSDU */
-#define WL_SEQ_AMSDU_MASK             0x1 /* allow 1 bit */
-#define WL_SEQ_AMSDU_SHIFT            14
-#define WL_SEQ_SET_AMSDU(x, val)      ((x) = \
-	((x) & ~(WL_SEQ_AMSDU_MASK << WL_SEQ_AMSDU_SHIFT)) | \
-	(((val) & WL_SEQ_AMSDU_MASK) << WL_SEQ_AMSDU_SHIFT))
-#define WL_SEQ_GET_AMSDU(x)   (((x) >> WL_SEQ_AMSDU_SHIFT) & \
-					WL_SEQ_AMSDU_MASK)
-
-/* Seq number is valid coming from FW */
-#define WL_SEQ_FROMFW_MASK		0x1 /* allow 1 bit */
-#define WL_SEQ_FROMFW_SHIFT		13
-#define WL_SEQ_SET_FROMFW(x, val)	((x) = \
-	((x) & ~(WL_SEQ_FROMFW_MASK << WL_SEQ_FROMFW_SHIFT)) | \
-	(((val) & WL_SEQ_FROMFW_MASK) << WL_SEQ_FROMFW_SHIFT))
-#define WL_SEQ_GET_FROMFW(x)	(((x) >> WL_SEQ_FROMFW_SHIFT) & \
-	WL_SEQ_FROMFW_MASK)
-
-/**
- * Proptxstatus related.
- *
- * Pkt from bus layer (DHD for SDIO and pciedev for PCIE)
- * is re-using seq number previously suppressed
- * so FW should not assign new one
- */
-#define WL_SEQ_FROMDRV_MASK		0x1 /* allow 1 bit */
-#define WL_SEQ_FROMDRV_SHIFT		12
-#define WL_SEQ_SET_FROMDRV(x, val)	((x) = \
-	((x) & ~(WL_SEQ_FROMDRV_MASK << WL_SEQ_FROMDRV_SHIFT)) | \
-	(((val) & WL_SEQ_FROMDRV_MASK) << WL_SEQ_FROMDRV_SHIFT))
-#define WL_SEQ_GET_FROMDRV(x)	(((x) >> WL_SEQ_FROMDRV_SHIFT) & \
-	WL_SEQ_FROMDRV_MASK)
-
-#define WL_SEQ_NUM_MASK			0xfff /* allow 12 bit */
-#define WL_SEQ_NUM_SHIFT		0
-#define WL_SEQ_SET_NUM(x, val)	((x) = \
-	((x) & ~(WL_SEQ_NUM_MASK << WL_SEQ_NUM_SHIFT)) | \
-	(((val) & WL_SEQ_NUM_MASK) << WL_SEQ_NUM_SHIFT))
-#define WL_SEQ_GET_NUM(x)	(((x) >> WL_SEQ_NUM_SHIFT) & \
-	WL_SEQ_NUM_MASK)
-
-#define WL_SEQ_AMSDU_SUPPR_MASK	((WL_SEQ_FROMDRV_MASK << WL_SEQ_FROMDRV_SHIFT) | \
-				(WL_SEQ_AMSDU_MASK << WL_SEQ_AMSDU_SHIFT) | \
-				(WL_SEQ_NUM_MASK << WL_SEQ_NUM_SHIFT))
-
-/* 32 STA should be enough??, 6 bits; Must be power of 2 */
-#define WLFC_MAC_DESC_TABLE_SIZE	32
-#define WLFC_MAX_IFNUM				16
-#define WLFC_MAC_DESC_ID_INVALID	0xff
-
-/* b[7:5] -reuse guard, b[4:0] -value */
-#define WLFC_MAC_DESC_GET_LOOKUP_INDEX(x) ((x) & 0x1f)
-
-#define WLFC_PKTFLAG_SET_PKTREQUESTED(x)	(x) |= \
-	(WLFC_PKTFLAG_PKT_REQUESTED << WL_TXSTATUS_FLAGS_SHIFT)
-
-#define WLFC_PKTFLAG_CLR_PKTREQUESTED(x)	(x) &= \
-	~(WLFC_PKTFLAG_PKT_REQUESTED << WL_TXSTATUS_FLAGS_SHIFT)
-
-
-#define WLFC_MAX_PENDING_DATALEN	120
-
-/* host is free to discard the packet */
-#define WLFC_CTL_PKTFLAG_DISCARD	0
-/* D11 suppressed a packet */
-#define WLFC_CTL_PKTFLAG_D11SUPPRESS	1
-/* WL firmware suppressed a packet because MAC is
-	already in PSMode (short time window)
-*/
-#define WLFC_CTL_PKTFLAG_WLSUPPRESS	2
-/* Firmware tossed this packet */
-#define WLFC_CTL_PKTFLAG_TOSSED_BYWLC	3
-/* Firmware tossed after retries */
-#define WLFC_CTL_PKTFLAG_DISCARD_NOACK	4
-/* Firmware wrongly reported suppressed previously,now fixing to acked */
-#define WLFC_CTL_PKTFLAG_SUPPRESS_ACKED	5
-
-#define WLFC_D11_STATUS_INTERPRET(txs)	\
-	((txs)->status.was_acked ? WLFC_CTL_PKTFLAG_DISCARD : \
-	(TXS_SUPR_MAGG_DONE((txs)->status.suppr_ind) ? \
-	WLFC_CTL_PKTFLAG_DISCARD_NOACK : WLFC_CTL_PKTFLAG_D11SUPPRESS))
-
-
-#ifdef PROP_TXSTATUS_DEBUG
-#define WLFC_DBGMESG(x) printf x
-/* wlfc-breadcrumb */
-#define WLFC_BREADCRUMB(x) do {if ((x) == NULL) \
-	{printf("WLFC: %s():%d:caller:%p\n", \
-	__FUNCTION__, __LINE__, __builtin_return_address(0));}} while (0)
-#define WLFC_PRINTMAC(banner, ea) do {printf("%s MAC: [%02x:%02x:%02x:%02x:%02x:%02x]\n", \
-	banner, ea[0], 	ea[1], 	ea[2], 	ea[3], 	ea[4], 	ea[5]); } while (0)
-#define WLFC_WHEREIS(s) printf("WLFC: at %s():%d, %s\n", __FUNCTION__, __LINE__, (s))
-#else
-#define WLFC_DBGMESG(x)
-#define WLFC_BREADCRUMB(x)
-#define WLFC_PRINTMAC(banner, ea)
-#define WLFC_WHEREIS(s)
-#endif
-
-/* AMPDU host reorder packet flags */
-#define WLHOST_REORDERDATA_MAXFLOWS		256
-#define WLHOST_REORDERDATA_LEN		 10
-#define WLHOST_REORDERDATA_TOTLEN	(WLHOST_REORDERDATA_LEN + 1 + 1) /* +tag +len */
-
-#define WLHOST_REORDERDATA_FLOWID_OFFSET		0
-#define WLHOST_REORDERDATA_MAXIDX_OFFSET		2
-#define WLHOST_REORDERDATA_FLAGS_OFFSET			4
-#define WLHOST_REORDERDATA_CURIDX_OFFSET		6
-#define WLHOST_REORDERDATA_EXPIDX_OFFSET		8
-
-#define WLHOST_REORDERDATA_DEL_FLOW		0x01
-#define WLHOST_REORDERDATA_FLUSH_ALL		0x02
-#define WLHOST_REORDERDATA_CURIDX_VALID		0x04
-#define WLHOST_REORDERDATA_EXPIDX_VALID		0x08
-#define WLHOST_REORDERDATA_NEW_HOLE		0x10
-
-/* transaction id data len byte 0: rsvd, byte 1: seqnumber, byte 2-5 will be used for timestampe */
-#define WLFC_CTL_TRANS_ID_LEN			6
-#define WLFC_TYPE_TRANS_ID_LEN			6
-
-#define WLFC_MODE_HANGER	1 /* use hanger */
-#define WLFC_MODE_AFQ		2 /* use afq (At Firmware Queue) */
-#define WLFC_IS_OLD_DEF(x) ((x & 1) || (x & 2))
-
-#define WLFC_MODE_AFQ_SHIFT		2	/* afq bit */
-#define WLFC_SET_AFQ(x, val)	((x) = \
-	((x) & ~(1 << WLFC_MODE_AFQ_SHIFT)) | \
-	(((val) & 1) << WLFC_MODE_AFQ_SHIFT))
-#define WLFC_GET_AFQ(x)	(((x) >> WLFC_MODE_AFQ_SHIFT) & 1)
-
-#define WLFC_MODE_REUSESEQ_SHIFT	3	/* seq reuse bit */
-#define WLFC_SET_REUSESEQ(x, val)	((x) = \
-	((x) & ~(1 << WLFC_MODE_REUSESEQ_SHIFT)) | \
-	(((val) & 1) << WLFC_MODE_REUSESEQ_SHIFT))
-#define WLFC_GET_REUSESEQ(x)	(((x) >> WLFC_MODE_REUSESEQ_SHIFT) & 1)
-
-#define WLFC_MODE_REORDERSUPP_SHIFT	4	/* host reorder suppress pkt bit */
-#define WLFC_SET_REORDERSUPP(x, val)	((x) = \
-	((x) & ~(1 << WLFC_MODE_REORDERSUPP_SHIFT)) | \
-	(((val) & 1) << WLFC_MODE_REORDERSUPP_SHIFT))
-#define WLFC_GET_REORDERSUPP(x)	(((x) >> WLFC_MODE_REORDERSUPP_SHIFT) & 1)
-
-#endif /* __wlfc_proto_definitions_h__ */
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
deleted file mode 100644
index 4447ca0..0000000
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
+++ /dev/null
@@ -1,8065 +0,0 @@
-/*
- * Custom OID/ioctl definitions for
- *
- *
- * Broadcom 802.11abg Networking Device Driver
- *
- * Definitions subject to change without notice.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wlioctl.h 609280 2016-01-01 06:31:38Z $
- */
-
-#ifndef _wlioctl_h_
-#define	_wlioctl_h_
-
-#include <typedefs.h>
-#include <proto/ethernet.h>
-#include <proto/bcmip.h>
-#include <proto/bcmeth.h>
-#include <proto/bcmip.h>
-#include <proto/bcmevent.h>
-#include <proto/802.11.h>
-#include <proto/802.1d.h>
-#include <bcmwifi_channels.h>
-#include <bcmwifi_rates.h>
-#include <devctrl_if/wlioctl_defs.h>
-#include <proto/bcmipv6.h>
-
-#include <bcm_mpool_pub.h>
-#include <bcmcdc.h>
-
-
-
-
-
-typedef struct {
-	uint32 num;
-	chanspec_t list[1];
-} chanspec_list_t;
-
-#define RSN_KCK_LENGTH	16
-#define RSN_KEK_LENGTH	16
-
-
-#ifndef INTF_NAME_SIZ
-#define INTF_NAME_SIZ	16
-#endif
-
-/* Used to send ioctls over the transport pipe */
-typedef struct remote_ioctl {
-	cdc_ioctl_t	msg;
-	uint32		data_len;
-	char           intf_name[INTF_NAME_SIZ];
-} rem_ioctl_t;
-#define REMOTE_SIZE	sizeof(rem_ioctl_t)
-
-
-/* DFS Forced param */
-typedef struct wl_dfs_forced_params {
-	chanspec_t chspec;
-	uint16 version;
-	chanspec_list_t chspec_list;
-} wl_dfs_forced_t;
-
-#define DFS_PREFCHANLIST_VER 0x01
-#define WL_CHSPEC_LIST_FIXED_SIZE	OFFSETOF(chanspec_list_t, list)
-#define WL_DFS_FORCED_PARAMS_FIXED_SIZE \
-	(WL_CHSPEC_LIST_FIXED_SIZE + OFFSETOF(wl_dfs_forced_t, chspec_list))
-#define WL_DFS_FORCED_PARAMS_MAX_SIZE \
-	WL_DFS_FORCED_PARAMS_FIXED_SIZE + (WL_NUMCHANNELS * sizeof(chanspec_t))
-
-/* association decision information */
-typedef struct {
-	bool		assoc_approved;		/**< (re)association approved */
-	uint16		reject_reason;		/**< reason code for rejecting association */
-	struct		ether_addr   da;
-	int64		sys_time;		/**< current system time */
-} assoc_decision_t;
-
-#define DFS_SCAN_S_IDLE		-1
-#define DFS_SCAN_S_RADAR_FREE 0
-#define DFS_SCAN_S_RADAR_FOUND 1
-#define DFS_SCAN_S_INPROGESS 2
-#define DFS_SCAN_S_SCAN_ABORTED 3
-#define DFS_SCAN_S_SCAN_MODESW_INPROGRESS 4
-#define DFS_SCAN_S_MAX 5
-
-
-#define ACTION_FRAME_SIZE 1800
-
-typedef struct wl_action_frame {
-	struct ether_addr 	da;
-	uint16 			len;
-	uint32 			packetId;
-	uint8			data[ACTION_FRAME_SIZE];
-} wl_action_frame_t;
-
-#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame)
-
-typedef struct ssid_info
-{
-	uint8		ssid_len;	/**< the length of SSID */
-	uint8		ssid[32];	/**< SSID string */
-} ssid_info_t;
-
-typedef struct wl_af_params {
-	uint32 			channel;
-	int32 			dwell_time;
-	struct ether_addr 	BSSID;
-	wl_action_frame_t	action_frame;
-} wl_af_params_t;
-
-#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params)
-
-#define MFP_TEST_FLAG_NORMAL	0
-#define MFP_TEST_FLAG_ANY_KEY	1
-typedef struct wl_sa_query {
-	uint32			flag;
-	uint8 			action;
-	uint16 			id;
-	struct ether_addr 	da;
-} wl_sa_query_t;
-
-/* require default structure packing */
-#define BWL_DEFAULT_PACKING
-#include <packed_section_start.h>
-
-
-/* Flags for OBSS IOVAR Parameters */
-#define WL_OBSS_DYN_BWSW_FLAG_ACTIVITY_PERIOD        (0x01)
-#define WL_OBSS_DYN_BWSW_FLAG_NOACTIVITY_PERIOD      (0x02)
-#define WL_OBSS_DYN_BWSW_FLAG_NOACTIVITY_INCR_PERIOD (0x04)
-#define WL_OBSS_DYN_BWSW_FLAG_PSEUDO_SENSE_PERIOD    (0x08)
-#define WL_OBSS_DYN_BWSW_FLAG_RX_CRS_PERIOD          (0x10)
-#define WL_OBSS_DYN_BWSW_FLAG_DUR_THRESHOLD          (0x20)
-#define WL_OBSS_DYN_BWSW_FLAG_TXOP_PERIOD            (0x40)
-
-/* OBSS IOVAR Version information */
-#define WL_PROT_OBSS_CONFIG_PARAMS_VERSION 1
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint8 obss_bwsw_activity_cfm_count_cfg; /* configurable count in
-		* seconds before we confirm that OBSS is present and
-		* dynamically activate dynamic bwswitch.
-		*/
-	uint8 obss_bwsw_no_activity_cfm_count_cfg; /* configurable count in
-		* seconds before we confirm that OBSS is GONE and
-		* dynamically start pseudo upgrade. If in pseudo sense time, we
-		* will see OBSS, [means that, we false detected that OBSS-is-gone
-		* in watchdog] this count will be incremented in steps of
-		* obss_bwsw_no_activity_cfm_count_incr_cfg for confirming OBSS
-		* detection again. Note that, at present, max 30seconds is
-		* allowed like this. [OBSS_BWSW_NO_ACTIVITY_MAX_INCR_DEFAULT]
-		*/
-	uint8 obss_bwsw_no_activity_cfm_count_incr_cfg; /* see above
-		*/
-	uint16 obss_bwsw_pseudo_sense_count_cfg; /* number of msecs/cnt to be in
-		* pseudo state. This is used to sense/measure the stats from lq.
-		*/
-	uint8 obss_bwsw_rx_crs_threshold_cfg; /* RX CRS default threshold */
-	uint8 obss_bwsw_dur_thres; /* OBSS dyn bwsw trigger/RX CRS Sec */
-	uint8 obss_bwsw_txop_threshold_cfg; /* TXOP default threshold */
-} BWL_POST_PACKED_STRUCT wlc_prot_dynbwsw_config_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 version;	/**< version field */
-	uint32 config_mask;
-	uint32 reset_mask;
-	wlc_prot_dynbwsw_config_t config_params;
-} BWL_POST_PACKED_STRUCT obss_config_params_t;
-
-
-/* bsscfg type */
-typedef enum bsscfg_type_t {
-	BSSCFG_TYPE_GENERIC = 0,	/**< default */
-	BSSCFG_TYPE_P2P = 1,	/**< The BSS is for p2p link */
-	BSSCFG_TYPE_BTA = 2,
-	BSSCFG_TYPE_TDLS = 4,
-	BSSCFG_TYPE_AWDL = 5,
-	BSSCFG_TYPE_PROXD = 6,
-	BSSCFG_TYPE_NAN = 7,
-	BSSCFG_TYPE_MAX
-} bsscfg_type_t;
-
-/* bsscfg subtype */
-enum {
-	BSSCFG_GENERIC_STA  = 1, /* GENERIC */
-	BSSCFG_GENERIC_AP = 2, /* GENERIC */
-	BSSCFG_P2P_GC   = 3, /* P2P */
-	BSSCFG_P2P_GO   = 4, /* P2P */
-	BSSCFG_P2P_DISC = 5, /* P2P */
-};
-
-typedef struct wlc_bsscfg_info {
-	uint32 type;
-	uint32 subtype;
-} wlc_bsscfg_info_t;
-
-
-
-/* Legacy structure to help keep backward compatible wl tool and tray app */
-
-#define	LEGACY_WL_BSS_INFO_VERSION	107	/**< older version of wl_bss_info struct */
-
-typedef struct wl_bss_info_107 {
-	uint32		version;		/**< version field */
-	uint32		length;			/**< byte length of data in this record,
-						 * starting at version and including IEs
-						 */
-	struct ether_addr BSSID;
-	uint16		beacon_period;		/**< units are Kusec */
-	uint16		capability;		/**< Capability information */
-	uint8		SSID_len;
-	uint8		SSID[32];
-	struct {
-		uint	count;			/**< # rates in this set */
-		uint8	rates[16];		/**< rates in 500kbps units w/hi bit set if basic */
-	} rateset;				/**< supported rates */
-	uint8		channel;		/**< Channel no. */
-	uint16		atim_window;		/**< units are Kusec */
-	uint8		dtim_period;		/**< DTIM period */
-	int16		RSSI;			/**< receive signal strength (in dBm) */
-	int8		phy_noise;		/**< noise (in dBm) */
-	uint32		ie_length;		/**< byte length of Information Elements */
-	/* variable length Information Elements */
-} wl_bss_info_107_t;
-
-/*
- * Per-BSS information structure.
- */
-
-#define	LEGACY2_WL_BSS_INFO_VERSION	108		/**< old version of wl_bss_info struct */
-
-/* BSS info structure
- * Applications MUST CHECK ie_offset field and length field to access IEs and
- * next bss_info structure in a vector (in wl_scan_results_t)
- */
-typedef struct wl_bss_info_108 {
-	uint32		version;		/**< version field */
-	uint32		length;			/**< byte length of data in this record,
-						 * starting at version and including IEs
-						 */
-	struct ether_addr BSSID;
-	uint16		beacon_period;		/**< units are Kusec */
-	uint16		capability;		/**< Capability information */
-	uint8		SSID_len;
-	uint8		SSID[32];
-	struct {
-		uint	count;			/**< # rates in this set */
-		uint8	rates[16];		/**< rates in 500kbps units w/hi bit set if basic */
-	} rateset;				/**< supported rates */
-	chanspec_t	chanspec;		/**< chanspec for bss */
-	uint16		atim_window;		/**< units are Kusec */
-	uint8		dtim_period;		/**< DTIM period */
-	int16		RSSI;			/**< receive signal strength (in dBm) */
-	int8		phy_noise;		/**< noise (in dBm) */
-
-	uint8		n_cap;			/**< BSS is 802.11N Capable */
-	uint32		nbss_cap;		/**< 802.11N BSS Capabilities (based on HT_CAP_*) */
-	uint8		ctl_ch;			/**< 802.11N BSS control channel number */
-	uint32		reserved32[1];		/**< Reserved for expansion of BSS properties */
-	uint8		flags;			/**< flags */
-	uint8		reserved[3];		/**< Reserved for expansion of BSS properties */
-	uint8		basic_mcs[MCSSET_LEN];	/**< 802.11N BSS required MCS set */
-
-	uint16		ie_offset;		/**< offset at which IEs start, from beginning */
-	uint32		ie_length;		/**< byte length of Information Elements */
-	/* Add new fields here */
-	/* variable length Information Elements */
-} wl_bss_info_108_t;
-
-#define	WL_BSS_INFO_VERSION	109		/**< current version of wl_bss_info struct */
-
-/* BSS info structure
- * Applications MUST CHECK ie_offset field and length field to access IEs and
- * next bss_info structure in a vector (in wl_scan_results_t)
- */
-typedef struct wl_bss_info {
-	uint32		version;		/**< version field */
-	uint32		length;			/**< byte length of data in this record,
-						 * starting at version and including IEs
-						 */
-	struct ether_addr BSSID;
-	uint16		beacon_period;		/**< units are Kusec */
-	uint16		capability;		/**< Capability information */
-	uint8		SSID_len;
-	uint8		SSID[32];
-	struct {
-		uint	count;			/**< # rates in this set */
-		uint8	rates[16];		/**< rates in 500kbps units w/hi bit set if basic */
-	} rateset;				/**< supported rates */
-	chanspec_t	chanspec;		/**< chanspec for bss */
-	uint16		atim_window;		/**< units are Kusec */
-	uint8		dtim_period;		/**< DTIM period */
-	int16		RSSI;			/**< receive signal strength (in dBm) */
-	int8		phy_noise;		/**< noise (in dBm) */
-
-	uint8		n_cap;			/**< BSS is 802.11N Capable */
-	uint32		nbss_cap;		/**< 802.11N+AC BSS Capabilities */
-	uint8		ctl_ch;			/**< 802.11N BSS control channel number */
-	uint8		padding1[3];		/**< explicit struct alignment padding */
-	uint16		vht_rxmcsmap;	/**< VHT rx mcs map (802.11ac IE, VHT_CAP_MCS_MAP_*) */
-	uint16		vht_txmcsmap;	/**< VHT tx mcs map (802.11ac IE, VHT_CAP_MCS_MAP_*) */
-	uint8		flags;			/**< flags */
-	uint8		vht_cap;		/**< BSS is vht capable */
-	uint8		reserved[2];		/**< Reserved for expansion of BSS properties */
-	uint8		basic_mcs[MCSSET_LEN];	/**< 802.11N BSS required MCS set */
-
-	uint16		ie_offset;		/**< offset at which IEs start, from beginning */
-	uint32		ie_length;		/**< byte length of Information Elements */
-	int16		SNR;			/**< average SNR of during frame reception */
-	uint16		vht_mcsmap;		/**< STA's Associated vhtmcsmap */
-	uint16		vht_mcsmap_prop;	/**< STA's Associated prop vhtmcsmap */
-	uint16		vht_txmcsmap_prop;	/**< prop VHT tx mcs prop */
-	/* Add new fields here */
-	/* variable length Information Elements */
-} wl_bss_info_t;
-
-#define	WL_GSCAN_BSS_INFO_VERSION	1	/* current version of wl_gscan_bss_info struct */
-#define WL_GSCAN_INFO_FIXED_FIELD_SIZE   (sizeof(wl_gscan_bss_info_t) - sizeof(wl_bss_info_t))
-
-typedef struct wl_gscan_bss_info {
-	uint32      timestamp[2];
-	wl_bss_info_t info;
-	/* Do not add any more members below, fixed  */
-	/* and variable length Information Elements to follow */
-} wl_gscan_bss_info_t;
-
-
-typedef struct wl_bsscfg {
-	uint32  bsscfg_idx;
-	uint32  wsec;
-	uint32  WPA_auth;
-	uint32  wsec_index;
-	uint32  associated;
-	uint32  BSS;
-	uint32  phytest_on;
-	struct ether_addr   prev_BSSID;
-	struct ether_addr   BSSID;
-	uint32  targetbss_wpa2_flags;
-	uint32 assoc_type;
-	uint32 assoc_state;
-} wl_bsscfg_t;
-
-typedef struct wl_if_add {
-	uint32  bsscfg_flags;
-	uint32  if_flags;
-	uint32  ap;
-	struct ether_addr   mac_addr;
-	uint32  wlc_index;
-} wl_if_add_t;
-
-typedef struct wl_bss_config {
-	uint32	atim_window;
-	uint32	beacon_period;
-	uint32	chanspec;
-} wl_bss_config_t;
-
-#define WL_BSS_USER_RADAR_CHAN_SELECT	0x1	/**< User application will randomly select
-						 * radar channel.
-						 */
-
-#define DLOAD_HANDLER_VER			1	/**< Downloader version */
-#define DLOAD_FLAG_VER_MASK		0xf000	/**< Downloader version mask */
-#define DLOAD_FLAG_VER_SHIFT	12	/**< Downloader version shift */
-
-#define DL_CRC_NOT_INUSE	0x0001
-#define DL_BEGIN		0x0002
-#define DL_END			0x0004
-
-/* generic download types & flags */
-enum {
-	DL_TYPE_UCODE = 1,
-	DL_TYPE_CLM = 2
-};
-
-/* ucode type values */
-enum {
-	UCODE_FW,
-	INIT_VALS,
-	BS_INIT_VALS
-};
-
-struct wl_dload_data {
-	uint16 flag;
-	uint16 dload_type;
-	uint32 len;
-	uint32 crc;
-	uint8  data[1];
-};
-typedef struct wl_dload_data wl_dload_data_t;
-
-struct wl_ucode_info {
-	uint32 ucode_type;
-	uint32 num_chunks;
-	uint32 chunk_len;
-	uint32 chunk_num;
-	uint8  data_chunk[1];
-};
-typedef struct wl_ucode_info wl_ucode_info_t;
-
-struct wl_clm_dload_info {
-	uint32 ds_id;
-	uint32 clm_total_len;
-	uint32 num_chunks;
-	uint32 chunk_len;
-	uint32 chunk_offset;
-	uint8  data_chunk[1];
-};
-typedef struct wl_clm_dload_info wl_clm_dload_info_t;
-
-typedef struct wlc_ssid {
-	uint32		SSID_len;
-	uchar		SSID[DOT11_MAX_SSID_LEN];
-} wlc_ssid_t;
-
-typedef struct wlc_ssid_ext {
-	bool       hidden;
-	uint32		SSID_len;
-	uchar		SSID[DOT11_MAX_SSID_LEN];
-} wlc_ssid_ext_t;
-
-
-#define MAX_PREFERRED_AP_NUM     5
-typedef struct wlc_fastssidinfo {
-	uint32				SSID_channel[MAX_PREFERRED_AP_NUM];
-	wlc_ssid_t		SSID_info[MAX_PREFERRED_AP_NUM];
-} wlc_fastssidinfo_t;
-
-#ifdef CUSTOMER_HW_31_1
-
-#define AP_NORM		0
-#define AP_STEALTH  1
-#define STREET_PASS_AP	2
-
-#define NSC_MAX_TGT_SSID	20
-typedef struct nsc_ssid_entry_list {
-	wlc_ssid_t ssid_info;
-	int ssid_type;
-} nsc_ssid_entry_list_t;
-
-typedef struct nsc_ssid_list {
-	uint32 num_entries;				/* N wants 150 */
-	nsc_ssid_entry_list_t ssid_entry[1];
-} nsc_ssid_list_t;
-
-#define NSC_TGT_SSID_BUFSZ	(sizeof(nsc_ssid_entry_list_t) * \
-		(NSC_MAX_TGT_SSID - 1) + sizeof(nsc_ssid_list_t))
-
-/* Default values from N */
-#define NSC_SCPATT_ARRSZ	32
-
-/* scan types */
-#define UNI_SCAN	0
-#define SP_SCAN_ACTIVE	1
-#define SP_SCAN_PASSIVE	2
-#define DOZE	3
-
-/* what we found */
-typedef struct nsc_scan_results {
-	wlc_ssid_t ssid;
-	struct ether_addr mac;
-	int scantype;
-	uint16 channel;
-} nsc_scan_results_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct nsc_af_body {
-	uint8			type;		/* should be 0x7f */
-	uint8			oui[DOT11_OUI_LEN];	/* just like it says */
-	uint8			subtype;
-	uint8			ielen;		/* */
-	uint8			data[1];	/* variable */
-} BWL_POST_PACKED_STRUCT nsc_af_body_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct nsc_sdlist {
-	uint8	scantype;
-	uint16	duration;
-	uint16	channel;		/* SP only */
-	uint8	ssid_index;		/* SP only */
-	uint16	rate;			/* SP only */
-} BWL_POST_PACKED_STRUCT nsc_sdlist_t;
-
-typedef struct nsc_scandes {
-	uint32 	num_entries;	/* number of list entries */
-	nsc_sdlist_t sdlist[1];	/* variable */
-} nsc_scandes_t;
-
-#define NSC_MAX_SDLIST_ENTRIES	8
-#define NSC_SDDESC_BUFSZ	(sizeof(nsc_sdlist_t) * \
-		(NSC_MAX_SDLIST_ENTRIES - 1) + sizeof(nsc_scandes_t))
-
-#define SCAN_ARR_END	(NSC_MAX_SDLIST_ENTRIES)
-#endif /* CUSTOMER_HW_31_1 */
-
-typedef BWL_PRE_PACKED_STRUCT struct wnm_url {
-	uint8   len;
-	uint8   data[1];
-} BWL_POST_PACKED_STRUCT wnm_url_t;
-
-#define WNM_BSS_SELECT_TYPE_RSSI   0
-#define WNM_BSS_SELECT_TYPE_CU   1
-
-#define WNM_BSSLOAD_MONITOR_VERSION   1
-typedef struct wnm_bssload_monitor_cfg {
-	uint8 version;
-	uint8 band;
-	uint8 duration; /* duration between 1 to 20sec */
-} wnm_bssload_monitor_cfg_t;
-
-#define BSS_MAXTABLE_SIZE 10
-#define WNM_BSS_SELECT_FACTOR_VERSION   1
-typedef struct wnm_bss_select_factor_params {
-	uint8 low;
-	uint8 high;
-	uint8 factor;
-	uint8 pad;
-} wnm_bss_select_factor_params_t;
-
-typedef struct wnm_bss_select_factor_cfg {
-	uint8 version;
-	uint8 band;
-	uint16 type;
-	uint16 pad;
-	uint16 count;
-	wnm_bss_select_factor_params_t params[1];
-} wnm_bss_select_factor_cfg_t;
-
-#define WNM_BSS_SELECT_WEIGHT_VERSION   1
-typedef struct wnm_bss_select_weight_cfg {
-	uint8 version;
-	uint8 band;
-	uint16 type;
-	uint16 weight; /* weightage for each type between 0 to 100 */
-} wnm_bss_select_weight_cfg_t;
-
-#define WNM_ROAM_TRIGGER_VERSION   1
-typedef struct wnm_roam_trigger_cfg {
-	uint8 version;
-	uint8 band;
-	uint16 type;
-	int16 trigger; /* trigger for each type in new roam algorithm */
-} wnm_roam_trigger_cfg_t;
-
-typedef struct chan_scandata {
-	uint8		txpower;
-	uint8		pad;
-	chanspec_t	channel;	/**< Channel num, bw, ctrl_sb and band */
-	uint32		channel_mintime;
-	uint32		channel_maxtime;
-} chan_scandata_t;
-
-typedef enum wl_scan_type {
-	EXTDSCAN_FOREGROUND_SCAN,
-	EXTDSCAN_BACKGROUND_SCAN,
-	EXTDSCAN_FORCEDBACKGROUND_SCAN
-} wl_scan_type_t;
-
-#define WLC_EXTDSCAN_MAX_SSID		5
-
-typedef struct wl_extdscan_params {
-	int8 		nprobes;		/**< 0, passive, otherwise active */
-	int8    	split_scan;		/**< split scan */
-	int8		band;			/**< band */
-	int8		pad;
-	wlc_ssid_t 	ssid[WLC_EXTDSCAN_MAX_SSID]; /* ssid list */
-	uint32		tx_rate;		/**< in 500ksec units */
-	wl_scan_type_t	scan_type;		/**< enum */
-	int32 		channel_num;
-	chan_scandata_t channel_list[1];	/**< list of chandata structs */
-} wl_extdscan_params_t;
-
-#define WL_EXTDSCAN_PARAMS_FIXED_SIZE 	(sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t))
-
-#define WL_SCAN_PARAMS_SSID_MAX 	10
-
-typedef struct wl_scan_params {
-	wlc_ssid_t ssid;		/**< default: {0, ""} */
-	struct ether_addr bssid;	/**< default: bcast */
-	int8 bss_type;			/**< default: any,
-					 * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
-					 */
-	uint8 scan_type;		/**< flags, 0 use default */
-	int32 nprobes;			/**< -1 use default, number of probes per channel */
-	int32 active_time;		/**< -1 use default, dwell time per channel for
-					 * active scanning
-					 */
-	int32 passive_time;		/**< -1 use default, dwell time per channel
-					 * for passive scanning
-					 */
-	int32 home_time;		/**< -1 use default, dwell time for the home channel
-					 * between channel scans
-					 */
-	int32 channel_num;		/**< count of channels and ssids that follow
-					 *
-					 * low half is count of channels in channel_list, 0
-					 * means default (use all available channels)
-					 *
-					 * high half is entries in wlc_ssid_t array that
-					 * follows channel_list, aligned for int32 (4 bytes)
-					 * meaning an odd channel count implies a 2-byte pad
-					 * between end of channel_list and first ssid
-					 *
-					 * if ssid count is zero, single ssid in the fixed
-					 * parameter portion is assumed, otherwise ssid in
-					 * the fixed portion is ignored
-					 */
-	uint16 channel_list[1];		/**< list of chanspecs */
-} wl_scan_params_t;
-
-/* size of wl_scan_params not including variable length array */
-#define WL_SCAN_PARAMS_FIXED_SIZE 64
-#define WL_MAX_ROAMSCAN_DATSZ	(WL_SCAN_PARAMS_FIXED_SIZE + (WL_NUMCHANNELS * sizeof(uint16)))
-
-#define ISCAN_REQ_VERSION 1
-
-/* incremental scan struct */
-typedef struct wl_iscan_params {
-	uint32 version;
-	uint16 action;
-	uint16 scan_duration;
-	wl_scan_params_t params;
-} wl_iscan_params_t;
-
-/* 3 fields + size of wl_scan_params, not including variable length array */
-#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t))
-
-typedef struct wl_scan_results {
-	uint32 buflen;
-	uint32 version;
-	uint32 count;
-	wl_bss_info_t bss_info[1];
-} wl_scan_results_t;
-
-/* size of wl_scan_results not including variable length array */
-#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t))
-
-
-#define ESCAN_REQ_VERSION 1
-
-/** event scan reduces amount of SOC memory needed to store scan results */
-typedef struct wl_escan_params {
-	uint32 version;
-	uint16 action;
-	uint16 sync_id;
-	wl_scan_params_t params;
-} wl_escan_params_t;
-
-#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t))
-
-/** event scan reduces amount of SOC memory needed to store scan results */
-typedef struct wl_escan_result {
-	uint32 buflen;
-	uint32 version;
-	uint16 sync_id;
-	uint16 bss_count;
-	wl_bss_info_t bss_info[1];
-} wl_escan_result_t;
-
-#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t))
-
-typedef struct wl_gscan_result {
-	uint32 buflen;
-	uint32 version;
-	wl_gscan_bss_info_t bss_info[1];
-} wl_gscan_result_t;
-
-#define WL_GSCAN_RESULTS_FIXED_SIZE (sizeof(wl_gscan_result_t) - sizeof(wl_gscan_bss_info_t))
-
-/* incremental scan results struct */
-typedef struct wl_iscan_results {
-	uint32 status;
-	wl_scan_results_t results;
-} wl_iscan_results_t;
-
-/* size of wl_iscan_results not including variable length array */
-#define WL_ISCAN_RESULTS_FIXED_SIZE \
-	(WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results))
-
-#define SCANOL_PARAMS_VERSION	1
-
-typedef struct scanol_params {
-	uint32 version;
-	uint32 flags;	/**< offload scanning flags */
-	int32 active_time;	/**< -1 use default, dwell time per channel for active scanning */
-	int32 passive_time;	/**< -1 use default, dwell time per channel for passive scanning */
-	int32 idle_rest_time;	/**< -1 use default, time idle between scan cycle */
-	int32 idle_rest_time_multiplier;
-	int32 active_rest_time;
-	int32 active_rest_time_multiplier;
-	int32 scan_cycle_idle_rest_time;
-	int32 scan_cycle_idle_rest_multiplier;
-	int32 scan_cycle_active_rest_time;
-	int32 scan_cycle_active_rest_multiplier;
-	int32 max_rest_time;
-	int32 max_scan_cycles;
-	int32 nprobes;		/**< -1 use default, number of probes per channel */
-	int32 scan_start_delay;
-	uint32 nchannels;
-	uint32 ssid_count;
-	wlc_ssid_t ssidlist[1];
-} scanol_params_t;
-
-typedef struct wl_probe_params {
-	wlc_ssid_t ssid;
-	struct ether_addr bssid;
-	struct ether_addr mac;
-} wl_probe_params_t;
-
-#define WL_MAXRATES_IN_SET		16	/**< max # of rates in a rateset */
-typedef struct wl_rateset {
-	uint32	count;			/**< # rates in this set */
-	uint8	rates[WL_MAXRATES_IN_SET];	/**< rates in 500kbps units w/hi bit set if basic */
-} wl_rateset_t;
-
-typedef struct wl_rateset_args {
-	uint32	count;			/**< # rates in this set */
-	uint8	rates[WL_MAXRATES_IN_SET];	/**< rates in 500kbps units w/hi bit set if basic */
-	uint8   mcs[MCSSET_LEN];        /* supported mcs index bit map */
-	uint16 vht_mcs[VHT_CAP_MCS_MAP_NSS_MAX]; /* supported mcs index bit map per nss */
-} wl_rateset_args_t;
-
-#define TXBF_RATE_MCS_ALL		4
-#define TXBF_RATE_VHT_ALL		4
-#define TXBF_RATE_OFDM_ALL		8
-
-typedef struct wl_txbf_rateset {
-	uint8	txbf_rate_mcs[TXBF_RATE_MCS_ALL];	/**< one for each stream */
-	uint8	txbf_rate_mcs_bcm[TXBF_RATE_MCS_ALL];	/**< one for each stream */
-	uint16	txbf_rate_vht[TXBF_RATE_VHT_ALL];	/**< one for each stream */
-	uint16	txbf_rate_vht_bcm[TXBF_RATE_VHT_ALL];	/**< one for each stream */
-	uint8	txbf_rate_ofdm[TXBF_RATE_OFDM_ALL]; /**< bitmap of ofdm rates that enables txbf */
-	uint8	txbf_rate_ofdm_bcm[TXBF_RATE_OFDM_ALL]; /* bitmap of ofdm rates that enables txbf */
-	uint8	txbf_rate_ofdm_cnt;
-	uint8	txbf_rate_ofdm_cnt_bcm;
-} wl_txbf_rateset_t;
-
-#define OFDM_RATE_MASK			0x0000007f
-typedef uint8 ofdm_rates_t;
-
-typedef struct wl_rates_info {
-	wl_rateset_t rs_tgt;
-	uint32 phy_type;
-	int32 bandtype;
-	uint8 cck_only;
-	uint8 rate_mask;
-	uint8 mcsallow;
-	uint8 bw;
-	uint8 txstreams;
-} wl_rates_info_t;
-
-/* uint32 list */
-typedef struct wl_uint32_list {
-	/* in - # of elements, out - # of entries */
-	uint32 count;
-	/* variable length uint32 list */
-	uint32 element[1];
-} wl_uint32_list_t;
-
-/* used for association with a specific BSSID and chanspec list */
-typedef struct wl_assoc_params {
-	struct ether_addr bssid;	/**< 00:00:00:00:00:00: broadcast scan */
-	uint16 bssid_cnt;		/**< 0: use chanspec_num, and the single bssid,
-					* otherwise count of chanspecs in chanspec_list
-					* AND paired bssids following chanspec_list
-					* also, chanspec_num has to be set to zero
-					* for bssid list to be used
-					*/
-	int32 chanspec_num;		/**< 0: all available channels,
-					* otherwise count of chanspecs in chanspec_list
-					*/
-	chanspec_t chanspec_list[1];	/**< list of chanspecs */
-} wl_assoc_params_t;
-
-#define WL_ASSOC_PARAMS_FIXED_SIZE 	OFFSETOF(wl_assoc_params_t, chanspec_list)
-
-/* used for reassociation/roam to a specific BSSID and channel */
-typedef wl_assoc_params_t wl_reassoc_params_t;
-#define WL_REASSOC_PARAMS_FIXED_SIZE	WL_ASSOC_PARAMS_FIXED_SIZE
-
-/* used for association to a specific BSSID and channel */
-typedef wl_assoc_params_t wl_join_assoc_params_t;
-#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE	WL_ASSOC_PARAMS_FIXED_SIZE
-
-/* used for join with or without a specific bssid and channel list */
-typedef struct wl_join_params {
-	wlc_ssid_t ssid;
-	wl_assoc_params_t params;	/**< optional field, but it must include the fixed portion
-					 * of the wl_assoc_params_t struct when it does present.
-					 */
-} wl_join_params_t;
-
-#define WL_JOIN_PARAMS_FIXED_SIZE 	(OFFSETOF(wl_join_params_t, params) + \
-					 WL_ASSOC_PARAMS_FIXED_SIZE)
-/* scan params for extended join */
-typedef struct wl_join_scan_params {
-	uint8 scan_type;		/**< 0 use default, active or passive scan */
-	int32 nprobes;			/**< -1 use default, number of probes per channel */
-	int32 active_time;		/**< -1 use default, dwell time per channel for
-					 * active scanning
-					 */
-	int32 passive_time;		/**< -1 use default, dwell time per channel
-					 * for passive scanning
-					 */
-	int32 home_time;		/**< -1 use default, dwell time for the home channel
-					 * between channel scans
-					 */
-} wl_join_scan_params_t;
-
-/* extended join params */
-typedef struct wl_extjoin_params {
-	wlc_ssid_t ssid;		/**< {0, ""}: wildcard scan */
-	wl_join_scan_params_t scan;
-	wl_join_assoc_params_t assoc;	/**< optional field, but it must include the fixed portion
-					 * of the wl_join_assoc_params_t struct when it does
-					 * present.
-					 */
-} wl_extjoin_params_t;
-#define WL_EXTJOIN_PARAMS_FIXED_SIZE 	(OFFSETOF(wl_extjoin_params_t, assoc) + \
-					 WL_JOIN_ASSOC_PARAMS_FIXED_SIZE)
-
-#define ANT_SELCFG_MAX		4	/**< max number of antenna configurations */
-#define MAX_STREAMS_SUPPORTED	4	/**< max number of streams supported */
-typedef struct {
-	uint8 ant_config[ANT_SELCFG_MAX];	/**< antenna configuration */
-	uint8 num_antcfg;	/**< number of available antenna configurations */
-} wlc_antselcfg_t;
-
-typedef struct {
-	uint32 duration;	/**< millisecs spent sampling this channel */
-	uint32 congest_ibss;	/**< millisecs in our bss (presumably this traffic will */
-				/**<  move if cur bss moves channels) */
-	uint32 congest_obss;	/**< traffic not in our bss */
-	uint32 interference;	/**< millisecs detecting a non 802.11 interferer. */
-	uint32 timestamp;	/**< second timestamp */
-} cca_congest_t;
-
-typedef struct {
-	chanspec_t chanspec;	/**< Which channel? */
-	uint16 num_secs;	/**< How many secs worth of data */
-	cca_congest_t  secs[1];	/**< Data */
-} cca_congest_channel_req_t;
-
-typedef struct {
-	uint32 duration;	/**< millisecs spent sampling this channel */
-	uint32 congest;		/**< millisecs detecting busy CCA */
-	uint32 timestamp;	/**< second timestamp */
-} cca_congest_simple_t;
-
-typedef struct {
-	uint16 status;
-	uint16 id;
-	chanspec_t chanspec;	/**< Which channel? */
-	uint16 len;
-	union {
-		cca_congest_simple_t  cca_busy;	/**< CCA busy */
-		int noise;			/**< noise floor */
-	};
-} cca_chan_qual_event_t;
-
-
-/* interference sources */
-enum interference_source {
-	ITFR_NONE = 0,		/**< interference */
-	ITFR_PHONE,		/**< wireless phone */
-	ITFR_VIDEO_CAMERA,	/**< wireless video camera */
-	ITFR_MICROWAVE_OVEN,	/**< microwave oven */
-	ITFR_BABY_MONITOR,	/**< wireless baby monitor */
-	ITFR_BLUETOOTH,		/**< bluetooth */
-	ITFR_VIDEO_CAMERA_OR_BABY_MONITOR,	/**< wireless camera or baby monitor */
-	ITFR_BLUETOOTH_OR_BABY_MONITOR,	/**< bluetooth or baby monitor */
-	ITFR_VIDEO_CAMERA_OR_PHONE,	/**< video camera or phone */
-	ITFR_UNIDENTIFIED	/**< interference from unidentified source */
-};
-
-/* structure for interference source report */
-typedef struct {
-	uint32 flags;	/**< flags.  bit definitions below */
-	uint32 source;	/**< last detected interference source */
-	uint32 timestamp;	/**< second timestamp on interferenced flag change */
-} interference_source_rep_t;
-
-#define WLC_CNTRY_BUF_SZ	4		/**< Country string is 3 bytes + NUL */
-
-
-typedef struct wl_country {
-	char country_abbrev[WLC_CNTRY_BUF_SZ];	/**< nul-terminated country code used in
-						 * the Country IE
-						 */
-	int32 rev;				/**< revision specifier for ccode
-						 * on set, -1 indicates unspecified.
-						 * on get, rev >= 0
-						 */
-	char ccode[WLC_CNTRY_BUF_SZ];		/**< nul-terminated built-in country code.
-						 * variable length, but fixed size in
-						 * struct allows simple allocation for
-						 * expected country strings <= 3 chars.
-						 */
-} wl_country_t;
-
-#define CCODE_INFO_VERSION 1
-
-typedef enum wl_ccode_role {
-	WLC_CCODE_ROLE_ACTIVE = 0,
-	WLC_CCODE_ROLE_HOST,
-	WLC_CCODE_ROLE_80211D_ASSOC,
-	WLC_CCODE_ROLE_80211D_SCAN,
-	WLC_CCODE_ROLE_DEFAULT,
-	WLC_CCODE_LAST
-} wl_ccode_role_t;
-#define WLC_NUM_CCODE_INFO WLC_CCODE_LAST
-
-typedef struct wl_ccode_entry {
-	uint16 reserved;
-	uint8 band;
-	uint8 role;
-	char	ccode[WLC_CNTRY_BUF_SZ];
-} wl_ccode_entry_t;
-
-typedef struct wl_ccode_info {
-	uint16 version;
-	uint16 count;   /* Number of ccodes entries in the set */
-	wl_ccode_entry_t ccodelist[1];
-} wl_ccode_info_t;
-#define WL_CCODE_INFO_FIXED_LEN	OFFSETOF(wl_ccode_info_t, ccodelist)
-
-typedef struct wl_channels_in_country {
-	uint32 buflen;
-	uint32 band;
-	char country_abbrev[WLC_CNTRY_BUF_SZ];
-	uint32 count;
-	uint32 channel[1];
-} wl_channels_in_country_t;
-
-typedef struct wl_country_list {
-	uint32 buflen;
-	uint32 band_set;
-	uint32 band;
-	uint32 count;
-	char country_abbrev[1];
-} wl_country_list_t;
-
-typedef struct wl_rm_req_elt {
-	int8	type;
-	int8	flags;
-	chanspec_t	chanspec;
-	uint32	token;		/**< token for this measurement */
-	uint32	tsf_h;		/**< TSF high 32-bits of Measurement start time */
-	uint32	tsf_l;		/**< TSF low 32-bits */
-	uint32	dur;		/**< TUs */
-} wl_rm_req_elt_t;
-
-typedef struct wl_rm_req {
-	uint32	token;		/**< overall measurement set token */
-	uint32	count;		/**< number of measurement requests */
-	void	*cb;		/**< completion callback function: may be NULL */
-	void	*cb_arg;	/**< arg to completion callback function */
-	wl_rm_req_elt_t	req[1];	/**< variable length block of requests */
-} wl_rm_req_t;
-#define WL_RM_REQ_FIXED_LEN	OFFSETOF(wl_rm_req_t, req)
-
-typedef struct wl_rm_rep_elt {
-	int8	type;
-	int8	flags;
-	chanspec_t	chanspec;
-	uint32	token;		/**< token for this measurement */
-	uint32	tsf_h;		/**< TSF high 32-bits of Measurement start time */
-	uint32	tsf_l;		/**< TSF low 32-bits */
-	uint32	dur;		/**< TUs */
-	uint32	len;		/**< byte length of data block */
-	uint8	data[1];	/**< variable length data block */
-} wl_rm_rep_elt_t;
-#define WL_RM_REP_ELT_FIXED_LEN	24	/**< length excluding data block */
-
-#define WL_RPI_REP_BIN_NUM 8
-typedef struct wl_rm_rpi_rep {
-	uint8	rpi[WL_RPI_REP_BIN_NUM];
-	int8	rpi_max[WL_RPI_REP_BIN_NUM];
-} wl_rm_rpi_rep_t;
-
-typedef struct wl_rm_rep {
-	uint32	token;		/**< overall measurement set token */
-	uint32	len;		/**< length of measurement report block */
-	wl_rm_rep_elt_t	rep[1];	/**< variable length block of reports */
-} wl_rm_rep_t;
-#define WL_RM_REP_FIXED_LEN	8
-
-
-typedef enum sup_auth_status {
-	/* Basic supplicant authentication states */
-	WLC_SUP_DISCONNECTED = 0,
-	WLC_SUP_CONNECTING,
-	WLC_SUP_IDREQUIRED,
-	WLC_SUP_AUTHENTICATING,
-	WLC_SUP_AUTHENTICATED,
-	WLC_SUP_KEYXCHANGE,
-	WLC_SUP_KEYED,
-	WLC_SUP_TIMEOUT,
-	WLC_SUP_LAST_BASIC_STATE,
-
-	/* Extended supplicant authentication states */
-	/* Waiting to receive handshake msg M1 */
-	WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED,
-	/* Preparing to send handshake msg M2 */
-	WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE,
-	/* Waiting to receive handshake msg M3 */
-	WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE,
-	WLC_SUP_KEYXCHANGE_PREP_M4,	/**< Preparing to send handshake msg M4 */
-	WLC_SUP_KEYXCHANGE_WAIT_G1,	/**< Waiting to receive handshake msg G1 */
-	WLC_SUP_KEYXCHANGE_PREP_G2	/**< Preparing to send handshake msg G2 */
-} sup_auth_status_t;
-
-typedef struct wl_wsec_key {
-	uint32		index;		/**< key index */
-	uint32		len;		/**< key length */
-	uint8		data[DOT11_MAX_KEY_SIZE];	/**< key data */
-	uint32		pad_1[18];
-	uint32		algo;		/**< CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
-	uint32		flags;		/**< misc flags */
-	uint32		pad_2[2];
-	int		pad_3;
-	int		iv_initialized;	/**< has IV been initialized already? */
-	int		pad_4;
-	/* Rx IV */
-	struct {
-		uint32	hi;		/**< upper 32 bits of IV */
-		uint16	lo;		/**< lower 16 bits of IV */
-	} rxiv;
-	uint32		pad_5[2];
-	struct ether_addr ea;		/**< per station */
-} wl_wsec_key_t;
-
-#define WSEC_MIN_PSK_LEN	8
-#define WSEC_MAX_PSK_LEN	64
-
-/* Flag for key material needing passhash'ing */
-#define WSEC_PASSPHRASE		(1<<0)
-
-/* receptacle for WLC_SET_WSEC_PMK parameter */
-typedef struct {
-	ushort	key_len;		/**< octets in key material */
-	ushort	flags;			/**< key handling qualification */
-	uint8	key[WSEC_MAX_PSK_LEN];	/**< PMK material */
-} wsec_pmk_t;
-
-typedef struct _pmkid {
-	struct ether_addr	BSSID;
-	uint8			PMKID[WPA2_PMKID_LEN];
-} pmkid_t;
-
-typedef struct _pmkid_list {
-	uint32	npmkid;
-	pmkid_t	pmkid[1];
-} pmkid_list_t;
-
-typedef struct _pmkid_cand {
-	struct ether_addr	BSSID;
-	uint8			preauth;
-} pmkid_cand_t;
-
-typedef struct _pmkid_cand_list {
-	uint32	npmkid_cand;
-	pmkid_cand_t	pmkid_cand[1];
-} pmkid_cand_list_t;
-
-#define WL_STA_ANT_MAX		4	/**< max possible rx antennas */
-
-typedef struct wl_assoc_info {
-	uint32		req_len;
-	uint32		resp_len;
-	uint32		flags;
-	struct dot11_assoc_req req;
-	struct ether_addr reassoc_bssid; /* used in reassoc's */
-	struct dot11_assoc_resp resp;
-} wl_assoc_info_t;
-
-typedef struct wl_led_info {
-	uint32      index;      /* led index */
-	uint32      behavior;
-	uint8       activehi;
-} wl_led_info_t;
-
-
-/* srom read/write struct passed through ioctl */
-typedef struct {
-	uint	byteoff;	/**< byte offset */
-	uint	nbytes;		/**< number of bytes */
-	uint16	buf[1];
-} srom_rw_t;
-
-#define CISH_FLAG_PCIECIS	(1 << 15)	/* write CIS format bit for PCIe CIS */
-/* similar cis (srom or otp) struct [iovar: may not be aligned] */
-typedef struct {
-	uint16	source;		/**< cis source */
-	uint16	flags;		/**< flags */
-	uint32	byteoff;	/**< byte offset */
-	uint32	nbytes;		/**< number of bytes */
-	/* data follows here */
-} cis_rw_t;
-
-/* R_REG and W_REG struct passed through ioctl */
-typedef struct {
-	uint32	byteoff;	/**< byte offset of the field in d11regs_t */
-	uint32	val;		/**< read/write value of the field */
-	uint32	size;		/**< sizeof the field */
-	uint	band;		/**< band (optional) */
-} rw_reg_t;
-
-/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */
-/* PCL - Power Control Loop */
-typedef struct {
-	uint16	auto_ctrl;	/**< WL_ATTEN_XX */
-	uint16	bb;		/**< Baseband attenuation */
-	uint16	radio;		/**< Radio attenuation */
-	uint16	txctl1;		/**< Radio TX_CTL1 value */
-} atten_t;
-
-/* Per-AC retry parameters */
-struct wme_tx_params_s {
-	uint8  short_retry;
-	uint8  short_fallback;
-	uint8  long_retry;
-	uint8  long_fallback;
-	uint16 max_rate;  /* In units of 512 Kbps */
-};
-
-typedef struct wme_tx_params_s wme_tx_params_t;
-
-#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT)
-
-/* Used to get specific link/ac parameters */
-typedef struct {
-	int32 ac;
-	uint8 val;
-	struct ether_addr ea;
-} link_val_t;
-
-
-#define WL_PM_MUTE_TX_VER 1
-
-typedef struct wl_pm_mute_tx {
-	uint16 version;		/**< version */
-	uint16 len;		/**< length */
-	uint16 deadline;	/**< deadline timer (in milliseconds) */
-	uint8  enable;		/**< set to 1 to enable mode; set to 0 to disable it */
-} wl_pm_mute_tx_t;
-
-
-typedef struct {
-	uint16			ver;		/**< version of this struct */
-	uint16			len;		/**< length in bytes of this structure */
-	uint16			cap;		/**< sta's advertised capabilities */
-	uint32			flags;		/**< flags defined below */
-	uint32			idle;		/**< time since data pkt rx'd from sta */
-	struct ether_addr	ea;		/**< Station address */
-	wl_rateset_t		rateset;	/**< rateset in use */
-	uint32			in;		/**< seconds elapsed since associated */
-	uint32			listen_interval_inms; /* Min Listen interval in ms for this STA */
-	uint32			tx_pkts;	/**< # of user packets transmitted (unicast) */
-	uint32			tx_failures;	/**< # of user packets failed */
-	uint32			rx_ucast_pkts;	/**< # of unicast packets received */
-	uint32			rx_mcast_pkts;	/**< # of multicast packets received */
-	uint32			tx_rate;	/**< Rate used by last tx frame */
-	uint32			rx_rate;	/**< Rate of last successful rx frame */
-	uint32			rx_decrypt_succeeds;	/**< # of packet decrypted successfully */
-	uint32			rx_decrypt_failures;	/**< # of packet decrypted unsuccessfully */
-	uint32			tx_tot_pkts;	/**< # of user tx pkts (ucast + mcast) */
-	uint32			rx_tot_pkts;	/**< # of data packets recvd (uni + mcast) */
-	uint32			tx_mcast_pkts;	/**< # of mcast pkts txed */
-	uint64			tx_tot_bytes;	/**< data bytes txed (ucast + mcast) */
-	uint64			rx_tot_bytes;	/**< data bytes recvd (ucast + mcast) */
-	uint64			tx_ucast_bytes;	/**< data bytes txed (ucast) */
-	uint64			tx_mcast_bytes;	/**< # data bytes txed (mcast) */
-	uint64			rx_ucast_bytes;	/**< data bytes recvd (ucast) */
-	uint64			rx_mcast_bytes;	/**< data bytes recvd (mcast) */
-	int8			rssi[WL_STA_ANT_MAX]; /* average rssi per antenna
-										   * of data frames
-										   */
-	int8			nf[WL_STA_ANT_MAX];	/**< per antenna noise floor */
-	uint16			aid;		/**< association ID */
-	uint16			ht_capabilities;	/**< advertised ht caps */
-	uint16			vht_flags;		/**< converted vht flags */
-	uint32			tx_pkts_retried;	/**< # of frames where a retry was
-							 * necessary
-							 */
-	uint32			tx_pkts_retry_exhausted; /* # of user frames where a retry
-							  * was exhausted
-							  */
-	int8			rx_lastpkt_rssi[WL_STA_ANT_MAX]; /* Per antenna RSSI of last
-								  * received data frame.
-								  */
-	/* TX WLAN retry/failure statistics:
-	 * Separated for host requested frames and WLAN locally generated frames.
-	 * Include unicast frame only where the retries/failures can be counted.
-	 */
-	uint32			tx_pkts_total;		/**< # user frames sent successfully */
-	uint32			tx_pkts_retries;	/**< # user frames retries */
-	uint32			tx_pkts_fw_total;	/**< # FW generated sent successfully */
-	uint32			tx_pkts_fw_retries;	/**< # retries for FW generated frames */
-	uint32			tx_pkts_fw_retry_exhausted;	/**< # FW generated where a retry
-								 * was exhausted
-								 */
-	uint32			rx_pkts_retried;	/**< # rx with retry bit set */
-	uint32			tx_rate_fallback;	/**< lowest fallback TX rate */
-} sta_info_t;
-
-#define WL_OLD_STAINFO_SIZE	OFFSETOF(sta_info_t, tx_tot_pkts)
-
-#define WL_STA_VER		4
-
-typedef struct {
-	uint32 auto_en;
-	uint32 active_ant;
-	uint32 rxcount;
-	int32 avg_snr_per_ant0;
-	int32 avg_snr_per_ant1;
-	int32 avg_snr_per_ant2;
-	uint32 swap_ge_rxcount0;
-	uint32 swap_ge_rxcount1;
-	uint32 swap_ge_snrthresh0;
-	uint32 swap_ge_snrthresh1;
-	uint32 swap_txfail0;
-	uint32 swap_txfail1;
-	uint32 swap_timer0;
-	uint32 swap_timer1;
-	uint32 swap_alivecheck0;
-	uint32 swap_alivecheck1;
-	uint32 rxcount_per_ant0;
-	uint32 rxcount_per_ant1;
-	uint32 acc_rxcount;
-	uint32 acc_rxcount_per_ant0;
-	uint32 acc_rxcount_per_ant1;
-	uint32 tx_auto_en;
-	uint32 tx_active_ant;
-	uint32 rx_policy;
-	uint32 tx_policy;
-	uint32 cell_policy;
-} wlc_swdiv_stats_t;
-
-#define	WLC_NUMRATES	16	/**< max # of rates in a rateset */
-
-typedef struct wlc_rateset {
-	uint32	count;			/**< number of rates in rates[] */
-	uint8	rates[WLC_NUMRATES];	/**< rates in 500kbps units w/hi bit set if basic */
-	uint8	htphy_membership;	/**< HT PHY Membership */
-	uint8	mcs[MCSSET_LEN];	/**< supported mcs index bit map */
-	uint16  vht_mcsmap;		/**< supported vht mcs nss bit map */
-	uint16  vht_mcsmap_prop;	/**< supported prop vht mcs nss bit map */
-} wlc_rateset_t;
-
-/* Used to get specific STA parameters */
-typedef struct {
-	uint32	val;
-	struct ether_addr ea;
-} scb_val_t;
-
-/* Used by iovar versions of some ioctls, i.e. WLC_SCB_AUTHORIZE et al */
-typedef struct {
-	uint32 code;
-	scb_val_t ioctl_args;
-} authops_t;
-
-/* channel encoding */
-typedef struct channel_info {
-	int hw_channel;
-	int target_channel;
-	int scan_channel;
-} channel_info_t;
-
-/* For ioctls that take a list of MAC addresses */
-typedef struct maclist {
-	uint count;			/**< number of MAC addresses */
-	struct ether_addr ea[1];	/**< variable length array of MAC addresses */
-} maclist_t;
-
-/* get pkt count struct passed through ioctl */
-typedef struct get_pktcnt {
-	uint rx_good_pkt;
-	uint rx_bad_pkt;
-	uint tx_good_pkt;
-	uint tx_bad_pkt;
-	uint rx_ocast_good_pkt; /* unicast packets destined for others */
-} get_pktcnt_t;
-
-/* NINTENDO2 */
-#define LQ_IDX_MIN              0
-#define LQ_IDX_MAX              1
-#define LQ_IDX_AVG              2
-#define LQ_IDX_SUM              2
-#define LQ_IDX_LAST             3
-#define LQ_STOP_MONITOR         0
-#define LQ_START_MONITOR        1
-
-/* Get averages RSSI, Rx PHY rate and SNR values */
-typedef struct {
-	int rssi[LQ_IDX_LAST];  /* Array to keep min, max, avg rssi */
-	int snr[LQ_IDX_LAST];   /* Array to keep min, max, avg snr */
-	int isvalid;            /* Flag indicating whether above data is valid */
-} wl_lq_t; /* Link Quality */
-
-typedef enum wl_wakeup_reason_type {
-	LCD_ON = 1,
-	LCD_OFF,
-	DRC1_WAKE,
-	DRC2_WAKE,
-	REASON_LAST
-} wl_wr_type_t;
-
-typedef struct {
-/* Unique filter id */
-	uint32	id;
-
-/* stores the reason for the last wake up */
-	uint8	reason;
-} wl_wr_t;
-
-/* Get MAC specific rate histogram command */
-typedef struct {
-	struct	ether_addr ea;	/**< MAC Address */
-	uint8	ac_cat;	/**< Access Category */
-	uint8	num_pkts;	/**< Number of packet entries to be averaged */
-} wl_mac_ratehisto_cmd_t;	/**< MAC Specific Rate Histogram command */
-
-/* Get MAC rate histogram response */
-typedef struct {
-	uint32	rate[DOT11_RATE_MAX + 1];	/**< Rates */
-	uint32	mcs[WL_RATESET_SZ_HT_IOCTL * WL_TX_CHAINS_MAX];	/**< MCS counts */
-	uint32	vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX];	/**< VHT counts */
-	uint32	tsf_timer[2][2];	/**< Start and End time for 8bytes value */
-	uint32	prop11n_mcs[WLC_11N_LAST_PROP_MCS - WLC_11N_FIRST_PROP_MCS + 1]; /* MCS counts */
-} wl_mac_ratehisto_res_t;	/**< MAC Specific Rate Histogram Response */
-
-/* Linux network driver ioctl encoding */
-typedef struct wl_ioctl {
-	uint cmd;	/**< common ioctl definition */
-	void *buf;	/**< pointer to user buffer */
-	uint len;	/**< length of user buffer */
-	uint8 set;		/**< 1=set IOCTL; 0=query IOCTL */
-	uint used;	/**< bytes read or written (optional) */
-	uint needed;	/**< bytes needed (optional) */
-} wl_ioctl_t;
-
-#ifdef CONFIG_COMPAT
-typedef struct compat_wl_ioctl {
-	uint cmd;	/**< common ioctl definition */
-	uint32 buf;	/**< pointer to user buffer */
-	uint len;	/**< length of user buffer */
-	uint8 set;		/**< 1=set IOCTL; 0=query IOCTL */
-	uint used;	/**< bytes read or written (optional) */
-	uint needed;	/**< bytes needed (optional) */
-} compat_wl_ioctl_t;
-#endif /* CONFIG_COMPAT */
-
-#define WL_NUM_RATES_CCK			4 /* 1, 2, 5.5, 11 Mbps */
-#define WL_NUM_RATES_OFDM			8 /* 6, 9, 12, 18, 24, 36, 48, 54 Mbps SISO/CDD */
-#define WL_NUM_RATES_MCS_1STREAM	8 /* MCS 0-7 1-stream rates - SISO/CDD/STBC/MCS */
-#define WL_NUM_RATES_EXTRA_VHT		2 /* Additional VHT 11AC rates */
-#define WL_NUM_RATES_VHT			10
-#define WL_NUM_RATES_MCS32			1
-
-
-/*
- * Structure for passing hardware and software
- * revision info up from the driver.
- */
-typedef struct wlc_rev_info {
-	uint		vendorid;	/**< PCI vendor id */
-	uint		deviceid;	/**< device id of chip */
-	uint		radiorev;	/**< radio revision */
-	uint		chiprev;	/**< chip revision */
-	uint		corerev;	/**< core revision */
-	uint		boardid;	/**< board identifier (usu. PCI sub-device id) */
-	uint		boardvendor;	/**< board vendor (usu. PCI sub-vendor id) */
-	uint		boardrev;	/**< board revision */
-	uint		driverrev;	/**< driver version */
-	uint		ucoderev;	/**< microcode version */
-	uint		bus;		/**< bus type */
-	uint		chipnum;	/**< chip number */
-	uint		phytype;	/**< phy type */
-	uint		phyrev;		/**< phy revision */
-	uint		anarev;		/**< anacore rev */
-	uint		chippkg;	/**< chip package info */
-	uint		nvramrev;	/**< nvram revision number */
-} wlc_rev_info_t;
-
-#define WL_REV_INFO_LEGACY_LENGTH	48
-
-#define WL_BRAND_MAX 10
-typedef struct wl_instance_info {
-	uint instance;
-	char brand[WL_BRAND_MAX];
-} wl_instance_info_t;
-
-/* structure to change size of tx fifo */
-typedef struct wl_txfifo_sz {
-	uint16	magic;
-	uint16	fifo;
-	uint16	size;
-} wl_txfifo_sz_t;
-
-/* Transfer info about an IOVar from the driver */
-/* Max supported IOV name size in bytes, + 1 for nul termination */
-#define WLC_IOV_NAME_LEN 30
-typedef struct wlc_iov_trx_s {
-	uint8 module;
-	uint8 type;
-	char name[WLC_IOV_NAME_LEN];
-} wlc_iov_trx_t;
-
-/* bump this number if you change the ioctl interface */
-#define WLC_IOCTL_VERSION	2
-#define WLC_IOCTL_VERSION_LEGACY_IOTYPES	1
-
-#ifdef CONFIG_USBRNDIS_RETAIL
-/* struct passed in for WLC_NDCONFIG_ITEM */
-typedef struct {
-	char *name;
-	void *param;
-} ndconfig_item_t;
-#endif
-
-
-
-#define WL_PHY_PAVARS_LEN	32	/**< Phytype, Bandrange, chain, a[0], b[0], c[0], d[0] .. */
-
-
-#define WL_PHY_PAVAR_VER	1	/**< pavars version */
-#define WL_PHY_PAVARS2_NUM	3	/**< a1, b0, b1 */
-typedef struct wl_pavars2 {
-	uint16 ver;		/**< version of this struct */
-	uint16 len;		/**< len of this structure */
-	uint16 inuse;		/**< driver return 1 for a1,b0,b1 in current band range */
-	uint16 phy_type;	/**< phy type */
-	uint16 bandrange;
-	uint16 chain;
-	uint16 inpa[WL_PHY_PAVARS2_NUM];	/**< phy pavars for one band range */
-} wl_pavars2_t;
-
-typedef struct wl_po {
-	uint16	phy_type;	/**< Phy type */
-	uint16	band;
-	uint16	cckpo;
-	uint32	ofdmpo;
-	uint16	mcspo[8];
-} wl_po_t;
-
-#define WL_NUM_RPCALVARS 5	/**< number of rpcal vars */
-
-typedef struct wl_rpcal {
-	uint16 value;
-	uint16 update;
-} wl_rpcal_t;
-
-typedef struct wl_aci_args {
-	int enter_aci_thresh; /* Trigger level to start detecting ACI */
-	int exit_aci_thresh; /* Trigger level to exit ACI mode */
-	int usec_spin; /* microsecs to delay between rssi samples */
-	int glitch_delay; /* interval between ACI scans when glitch count is consistently high */
-	uint16 nphy_adcpwr_enter_thresh;	/**< ADC power to enter ACI mitigation mode */
-	uint16 nphy_adcpwr_exit_thresh;	/**< ADC power to exit ACI mitigation mode */
-	uint16 nphy_repeat_ctr;		/**< Number of tries per channel to compute power */
-	uint16 nphy_num_samples;	/**< Number of samples to compute power on one channel */
-	uint16 nphy_undetect_window_sz;	/**< num of undetects to exit ACI Mitigation mode */
-	uint16 nphy_b_energy_lo_aci;	/**< low ACI power energy threshold for bphy */
-	uint16 nphy_b_energy_md_aci;	/**< mid ACI power energy threshold for bphy */
-	uint16 nphy_b_energy_hi_aci;	/**< high ACI power energy threshold for bphy */
-	uint16 nphy_noise_noassoc_glitch_th_up; /* wl interference 4 */
-	uint16 nphy_noise_noassoc_glitch_th_dn;
-	uint16 nphy_noise_assoc_glitch_th_up;
-	uint16 nphy_noise_assoc_glitch_th_dn;
-	uint16 nphy_noise_assoc_aci_glitch_th_up;
-	uint16 nphy_noise_assoc_aci_glitch_th_dn;
-	uint16 nphy_noise_assoc_enter_th;
-	uint16 nphy_noise_noassoc_enter_th;
-	uint16 nphy_noise_assoc_rx_glitch_badplcp_enter_th;
-	uint16 nphy_noise_noassoc_crsidx_incr;
-	uint16 nphy_noise_assoc_crsidx_incr;
-	uint16 nphy_noise_crsidx_decr;
-} wl_aci_args_t;
-
-#define WL_ACI_ARGS_LEGACY_LENGTH	16	/**< bytes of pre NPHY aci args */
-#define	WL_SAMPLECOLLECT_T_VERSION	2	/**< version of wl_samplecollect_args_t struct */
-typedef struct wl_samplecollect_args {
-	/* version 0 fields */
-	uint8 coll_us;
-	int cores;
-	/* add'l version 1 fields */
-	uint16 version;     /* see definition of WL_SAMPLECOLLECT_T_VERSION */
-	uint16 length;      /* length of entire structure */
-	int8 trigger;
-	uint16 timeout;
-	uint16 mode;
-	uint32 pre_dur;
-	uint32 post_dur;
-	uint8 gpio_sel;
-	uint8 downsamp;
-	uint8 be_deaf;
-	uint8 agc;		/**< loop from init gain and going down */
-	uint8 filter;		/**< override high pass corners to lowest */
-	/* add'l version 2 fields */
-	uint8 trigger_state;
-	uint8 module_sel1;
-	uint8 module_sel2;
-	uint16 nsamps;
-	int bitStart;
-	uint32 gpioCapMask;
-} wl_samplecollect_args_t;
-
-#define	WL_SAMPLEDATA_T_VERSION		1	/**< version of wl_samplecollect_args_t struct */
-/* version for unpacked sample data, int16 {(I,Q),Core(0..N)} */
-#define	WL_SAMPLEDATA_T_VERSION_SPEC_AN 2
-
-typedef struct wl_sampledata {
-	uint16 version;	/**< structure version */
-	uint16 size;	/**< size of structure */
-	uint16 tag;	/**< Header/Data */
-	uint16 length;	/**< data length */
-	uint32 flag;	/**< bit def */
-} wl_sampledata_t;
-
-
-/* WL_OTA START */
-/* OTA Test Status */
-enum {
-	WL_OTA_TEST_IDLE = 0,	/**< Default Idle state */
-	WL_OTA_TEST_ACTIVE = 1,	/**< Test Running */
-	WL_OTA_TEST_SUCCESS = 2,	/**< Successfully Finished Test */
-	WL_OTA_TEST_FAIL = 3	/**< Test Failed in the Middle */
-};
-/* OTA SYNC Status */
-enum {
-	WL_OTA_SYNC_IDLE = 0,	/**< Idle state */
-	WL_OTA_SYNC_ACTIVE = 1,	/**< Waiting for Sync */
-	WL_OTA_SYNC_FAIL = 2	/**< Sync pkt not recieved */
-};
-
-/* Various error states dut can get stuck during test */
-enum {
-	WL_OTA_SKIP_TEST_CAL_FAIL = 1,		/**< Phy calibration failed */
-	WL_OTA_SKIP_TEST_SYNCH_FAIL = 2,		/**< Sync Packet not recieved */
-	WL_OTA_SKIP_TEST_FILE_DWNLD_FAIL = 3,	/**< Cmd flow file download failed */
-	WL_OTA_SKIP_TEST_NO_TEST_FOUND = 4,	/**< No test found in Flow file */
-	WL_OTA_SKIP_TEST_WL_NOT_UP = 5,		/**< WL UP failed */
-	WL_OTA_SKIP_TEST_UNKNOWN_CALL		/**< Unintentional scheduling on ota test */
-};
-
-/* Differentiator for ota_tx and ota_rx */
-enum {
-	WL_OTA_TEST_TX = 0,		/**< ota_tx */
-	WL_OTA_TEST_RX = 1,		/**< ota_rx */
-};
-
-/* Catch 3 modes of operation: 20Mhz, 40Mhz, 20 in 40 Mhz */
-enum {
-	WL_OTA_TEST_BW_20_IN_40MHZ = 0,		/**< 20 in 40 operation */
-	WL_OTA_TEST_BW_20MHZ = 1,		/**< 20 Mhz operation */
-	WL_OTA_TEST_BW_40MHZ = 2,		/**< full 40Mhz operation */
-	WL_OTA_TEST_BW_80MHZ = 3		/* full 80Mhz operation */
-};
-
-#define HT_MCS_INUSE	0x00000080	/* HT MCS in use,indicates b0-6 holds an mcs */
-#define VHT_MCS_INUSE	0x00000100	/* VHT MCS in use,indicates b0-6 holds an mcs */
-#define OTA_RATE_MASK 0x0000007f	/* rate/mcs value */
-#define OTA_STF_SISO	0
-#define OTA_STF_CDD		1
-#define OTA_STF_STBC	2
-#define OTA_STF_SDM		3
-
-typedef struct ota_rate_info {
-	uint8 rate_cnt;					/**< Total number of rates */
-	uint16 rate_val_mbps[WL_OTA_TEST_MAX_NUM_RATE];	/**< array of rates from 1mbps to 130mbps */
-							/**< for legacy rates : ratein mbps * 2 */
-							/**< for HT rates : mcs index */
-} ota_rate_info_t;
-
-typedef struct ota_power_info {
-	int8 pwr_ctrl_on;	/**< power control on/off */
-	int8 start_pwr;		/**< starting power/index */
-	int8 delta_pwr;		/**< delta power/index */
-	int8 end_pwr;		/**< end power/index */
-} ota_power_info_t;
-
-typedef struct ota_packetengine {
-	uint16 delay;           /* Inter-packet delay */
-				/**< for ota_tx, delay is tx ifs in micro seconds */
-				/* for ota_rx, delay is wait time in milliseconds */
-	uint16 nframes;         /* Number of frames */
-	uint16 length;          /* Packet length */
-} ota_packetengine_t;
-
-/* Test info vector */
-typedef struct wl_ota_test_args {
-	uint8 cur_test;			/**< test phase */
-	uint8 chan;			/**< channel */
-	uint8 bw;			/**< bandwidth */
-	uint8 control_band;		/**< control band */
-	uint8 stf_mode;			/**< stf mode */
-	ota_rate_info_t rt_info;	/**< Rate info */
-	ota_packetengine_t pkteng;	/**< packeteng info */
-	uint8 txant;			/**< tx antenna */
-	uint8 rxant;			/**< rx antenna */
-	ota_power_info_t pwr_info;	/**< power sweep info */
-	uint8 wait_for_sync;		/**< wait for sync or not */
-	uint8 ldpc;
-	uint8 sgi;
-	/* Update WL_OTA_TESTVEC_T_VERSION for adding new members to this structure */
-} wl_ota_test_args_t;
-
-#define WL_OTA_TESTVEC_T_VERSION		1	/* version of wl_ota_test_vector_t struct */
-typedef struct wl_ota_test_vector {
-	uint16 version;
-	wl_ota_test_args_t test_arg[WL_OTA_TEST_MAX_NUM_SEQ];	/**< Test argument struct */
-	uint16 test_cnt;					/**< Total no of test */
-	uint8 file_dwnld_valid;					/**< File successfully downloaded */
-	uint8 sync_timeout;					/**< sync packet timeout */
-	int8 sync_fail_action;					/**< sync fail action */
-	struct ether_addr sync_mac;				/**< macaddress for sync pkt */
-	struct ether_addr tx_mac;				/**< macaddress for tx */
-	struct ether_addr rx_mac;				/**< macaddress for rx */
-	int8 loop_test;					/**< dbg feature to loop the test */
-	uint16 test_rxcnt;
-	/* Update WL_OTA_TESTVEC_T_VERSION for adding new members to this structure */
-} wl_ota_test_vector_t;
-
-
-/* struct copied back form dongle to host to query the status */
-typedef struct wl_ota_test_status {
-	int16 cur_test_cnt;		/**< test phase */
-	int8 skip_test_reason;		/**< skip test reasoin */
-	wl_ota_test_args_t test_arg;	/**< cur test arg details */
-	uint16 test_cnt;		/**< total no of test downloaded */
-	uint8 file_dwnld_valid;		/**< file successfully downloaded ? */
-	uint8 sync_timeout;		/**< sync timeout */
-	int8 sync_fail_action;		/**< sync fail action */
-	struct ether_addr sync_mac;	/**< macaddress for sync pkt */
-	struct ether_addr tx_mac;	/**< tx mac address */
-	struct ether_addr rx_mac;	/**< rx mac address */
-	uint8  test_stage;		/**< check the test status */
-	int8 loop_test;		/**< Debug feature to puts test enfine in a loop */
-	uint8 sync_status;		/**< sync status */
-} wl_ota_test_status_t;
-typedef struct wl_ota_rx_rssi {
-	uint16	pktcnt;		/* Pkt count used for this rx test */
-	chanspec_t chanspec;	/* Channel info on which the packets are received */
-	int16	rssi;		/* Average RSSI of the first 50% packets received */
-} wl_ota_rx_rssi_t;
-
-#define	WL_OTARSSI_T_VERSION		1	/* version of wl_ota_test_rssi_t struct */
-#define WL_OTA_TEST_RSSI_FIXED_SIZE	OFFSETOF(wl_ota_test_rssi_t, rx_rssi)
-
-typedef struct wl_ota_test_rssi {
-	uint8 version;
-	uint8	testcnt;		/* total measured RSSI values, valid on output only */
-	wl_ota_rx_rssi_t rx_rssi[1]; /* Variable length array of wl_ota_rx_rssi_t */
-} wl_ota_test_rssi_t;
-
-/* WL_OTA END */
-
-/* wl_radar_args_t */
-typedef struct {
-	int npulses;	/**< required number of pulses at n * t_int */
-	int ncontig;	/**< required number of pulses at t_int */
-	int min_pw;	/**< minimum pulse width (20 MHz clocks) */
-	int max_pw;	/**< maximum pulse width (20 MHz clocks) */
-	uint16 thresh0;	/**< Radar detection, thresh 0 */
-	uint16 thresh1;	/**< Radar detection, thresh 1 */
-	uint16 blank;	/**< Radar detection, blank control */
-	uint16 fmdemodcfg;	/**< Radar detection, fmdemod config */
-	int npulses_lp;  /* Radar detection, minimum long pulses */
-	int min_pw_lp; /* Minimum pulsewidth for long pulses */
-	int max_pw_lp; /* Maximum pulsewidth for long pulses */
-	int min_fm_lp; /* Minimum fm for long pulses */
-	int max_span_lp;  /* Maximum deltat for long pulses */
-	int min_deltat; /* Minimum spacing between pulses */
-	int max_deltat; /* Maximum spacing between pulses */
-	uint16 autocorr;	/**< Radar detection, autocorr on or off */
-	uint16 st_level_time;	/**< Radar detection, start_timing level */
-	uint16 t2_min; /* minimum clocks needed to remain in state 2 */
-	uint32 version; /* version */
-	uint32 fra_pulse_err;	/**< sample error margin for detecting French radar pulsed */
-	int npulses_fra;  /* Radar detection, minimum French pulses set */
-	int npulses_stg2;  /* Radar detection, minimum staggered-2 pulses set */
-	int npulses_stg3;  /* Radar detection, minimum staggered-3 pulses set */
-	uint16 percal_mask;	/**< defines which period cal is masked from radar detection */
-	int quant;	/**< quantization resolution to pulse positions */
-	uint32 min_burst_intv_lp;	/**< minimum burst to burst interval for bin3 radar */
-	uint32 max_burst_intv_lp;	/**< maximum burst to burst interval for bin3 radar */
-	int nskip_rst_lp;	/**< number of skipped pulses before resetting lp buffer */
-	int max_pw_tol;	/**< maximum tolerance allowd in detected pulse width for radar detection */
-	uint16 feature_mask; /* 16-bit mask to specify enabled features */
-} wl_radar_args_t;
-
-#define WL_RADAR_ARGS_VERSION 2
-
-typedef struct {
-	uint32 version; /* version */
-	uint16 thresh0_20_lo;	/* Radar detection, thresh 0 (range 5250-5350MHz) for BW 20MHz */
-	uint16 thresh1_20_lo;	/* Radar detection, thresh 1 (range 5250-5350MHz) for BW 20MHz */
-	uint16 thresh0_40_lo;	/* Radar detection, thresh 0 (range 5250-5350MHz) for BW 40MHz */
-	uint16 thresh1_40_lo;	/* Radar detection, thresh 1 (range 5250-5350MHz) for BW 40MHz */
-	uint16 thresh0_80_lo;	/* Radar detection, thresh 0 (range 5250-5350MHz) for BW 80MHz */
-	uint16 thresh1_80_lo;	/* Radar detection, thresh 1 (range 5250-5350MHz) for BW 80MHz */
-	uint16 thresh0_20_hi;	/* Radar detection, thresh 0 (range 5470-5725MHz) for BW 20MHz */
-	uint16 thresh1_20_hi;	/* Radar detection, thresh 1 (range 5470-5725MHz) for BW 20MHz */
-	uint16 thresh0_40_hi;	/* Radar detection, thresh 0 (range 5470-5725MHz) for BW 40MHz */
-	uint16 thresh1_40_hi;	/* Radar detection, thresh 1 (range 5470-5725MHz) for BW 40MHz */
-	uint16 thresh0_80_hi;	/* Radar detection, thresh 0 (range 5470-5725MHz) for BW 80MHz */
-	uint16 thresh1_80_hi;	/* Radar detection, thresh 1 (range 5470-5725MHz) for BW 80MHz */
-#ifdef WL11AC160
-	uint16 thresh0_160_lo;	/* Radar detection, thresh 0 (range 5250-5350MHz) for BW 160MHz */
-	uint16 thresh1_160_lo;	/* Radar detection, thresh 1 (range 5250-5350MHz) for BW 160MHz */
-	uint16 thresh0_160_hi;	/* Radar detection, thresh 0 (range 5470-5725MHz) for BW 160MHz */
-	uint16 thresh1_160_hi;	/* Radar detection, thresh 1 (range 5470-5725MHz) for BW 160MHz */
-#endif /* WL11AC160 */
-} wl_radar_thr_t;
-
-#define WL_RADAR_THR_VERSION	2
-
-/* RSSI per antenna */
-typedef struct {
-	uint32	version;		/**< version field */
-	uint32	count;			/**< number of valid antenna rssi */
-	int8 rssi_ant[WL_RSSI_ANT_MAX];	/**< rssi per antenna */
-} wl_rssi_ant_t;
-
-/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */
-typedef struct {
-	uint state;		/**< noted by WL_DFS_CACSTATE_XX. */
-	uint duration;		/**< time spent in ms in state. */
-	/* as dfs enters ISM state, it removes the operational channel from quiet channel
-	 * list and notes the channel in channel_cleared. set to 0 if no channel is cleared
-	 */
-	chanspec_t chanspec_cleared;
-	/* chanspec cleared used to be a uint, add another to uint16 to maintain size */
-	uint16 pad;
-} wl_dfs_status_t;
-
-typedef struct {
-	uint state;		/* noted by WL_DFS_CACSTATE_XX */
-	uint duration;		/* time spent in ms in state */
-	chanspec_t chanspec;	/* chanspec of this core */
-	chanspec_t chanspec_last_cleared; /* chanspec last cleared for operation by scanning */
-	uint16 sub_type;	/* currently just the index of the core or the respective PLL */
-	uint16 pad;
-} wl_dfs_sub_status_t;
-
-#define WL_DFS_STATUS_ALL_VERSION	(1)
-typedef struct {
-	uint16 version;		/* version field; current max version 1 */
-	uint16 num_sub_status;
-	wl_dfs_sub_status_t  dfs_sub_status[1]; /* struct array of length num_sub_status */
-} wl_dfs_status_all_t;
-
-#define WL_DFS_AP_MOVE_VERSION	(1)
-typedef struct wl_dfs_ap_move_status {
-	int8 version;            /* version field; current max version 1 */
-	int8 move_status;        /* DFS move status */
-	chanspec_t chanspec;     /* New AP Chanspec */
-	wl_dfs_status_all_t scan_status; /* status; see dfs_status_all for wl_dfs_status_all_t */
-} wl_dfs_ap_move_status_t;
-
-
-/* data structure used in 'radar_status' wl interface, which is use to query radar det status */
-typedef struct {
-	bool detected;
-	int count;
-	bool pretended;
-	uint32 radartype;
-	uint32 timenow;
-	uint32 timefromL;
-	int lp_csect_single;
-	int detected_pulse_index;
-	int nconsecq_pulses;
-	chanspec_t ch;
-	int pw[10];
-	int intv[10];
-	int fm[10];
-} wl_radar_status_t;
-
-#define NUM_PWRCTRL_RATES 12
-
-typedef struct {
-	uint8 txpwr_band_max[NUM_PWRCTRL_RATES];	/**< User set target */
-	uint8 txpwr_limit[NUM_PWRCTRL_RATES];		/**< reg and local power limit */
-	uint8 txpwr_local_max;				/**< local max according to the AP */
-	uint8 txpwr_local_constraint;			/**< local constraint according to the AP */
-	uint8 txpwr_chan_reg_max;			/**< Regulatory max for this channel */
-	uint8 txpwr_target[2][NUM_PWRCTRL_RATES];	/**< Latest target for 2.4 and 5 Ghz */
-	uint8 txpwr_est_Pout[2];			/**< Latest estimate for 2.4 and 5 Ghz */
-	uint8 txpwr_opo[NUM_PWRCTRL_RATES];		/**< On G phy, OFDM power offset */
-	uint8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES];	/**< Max CCK power for this band (SROM) */
-	uint8 txpwr_bphy_ofdm_max;			/**< Max OFDM power for this band (SROM) */
-	uint8 txpwr_aphy_max[NUM_PWRCTRL_RATES];	/**< Max power for A band (SROM) */
-	int8  txpwr_antgain[2];				/**< Ant gain for each band - from SROM */
-	uint8 txpwr_est_Pout_gofdm;			/**< Pwr estimate for 2.4 OFDM */
-} tx_power_legacy_t;
-
-#define WL_TX_POWER_RATES_LEGACY    45
-#define WL_TX_POWER_MCS20_FIRST         12
-#define WL_TX_POWER_MCS20_NUM           16
-#define WL_TX_POWER_MCS40_FIRST         28
-#define WL_TX_POWER_MCS40_NUM           17
-
-typedef struct {
-	uint32 flags;
-	chanspec_t chanspec;                 /* txpwr report for this channel */
-	chanspec_t local_chanspec;           /* channel on which we are associated */
-	uint8 local_max;                 /* local max according to the AP */
-	uint8 local_constraint;              /* local constraint according to the AP */
-	int8  antgain[2];                /* Ant gain for each band - from SROM */
-	uint8 rf_cores;                  /* count of RF Cores being reported */
-	uint8 est_Pout[4];                           /* Latest tx power out estimate per RF
-							  * chain without adjustment
-							  */
-	uint8 est_Pout_cck;                          /* Latest CCK tx power out estimate */
-	uint8 user_limit[WL_TX_POWER_RATES_LEGACY];  /* User limit */
-	uint8 reg_limit[WL_TX_POWER_RATES_LEGACY];   /* Regulatory power limit */
-	uint8 board_limit[WL_TX_POWER_RATES_LEGACY]; /* Max power board can support (SROM) */
-	uint8 target[WL_TX_POWER_RATES_LEGACY];      /* Latest target power */
-} tx_power_legacy2_t;
-
-#define WL_NUM_2x2_ELEMENTS		4
-#define WL_NUM_3x3_ELEMENTS		6
-#define WL_NUM_4x4_ELEMENTS		10
-
-typedef struct {
-	uint16 ver;				/**< version of this struct */
-	uint16 len;				/**< length in bytes of this structure */
-	uint32 flags;
-	chanspec_t chanspec;			/**< txpwr report for this channel */
-	chanspec_t local_chanspec;		/**< channel on which we are associated */
-	uint32     buflen;			/**< ppr buffer length */
-	uint8      pprbuf[1];			/**< Latest target power buffer */
-} wl_txppr_t;
-
-#define WL_TXPPR_VERSION	1
-#define WL_TXPPR_LENGTH	(sizeof(wl_txppr_t))
-#define TX_POWER_T_VERSION	45
-/* number of ppr serialization buffers, it should be reg, board and target */
-#define WL_TXPPR_SER_BUF_NUM	(3)
-
-typedef struct chanspec_txpwr_max {
-	chanspec_t chanspec;   /* chanspec */
-	uint8 txpwr_max;       /* max txpwr in all the rates */
-	uint8 padding;
-} chanspec_txpwr_max_t;
-
-typedef struct  wl_chanspec_txpwr_max {
-	uint16 ver;			/**< version of this struct */
-	uint16 len;			/**< length in bytes of this structure */
-	uint32 count;		/**< number of elements of (chanspec, txpwr_max) pair */
-	chanspec_txpwr_max_t txpwr[1];	/**< array of (chanspec, max_txpwr) pair */
-} wl_chanspec_txpwr_max_t;
-
-#define WL_CHANSPEC_TXPWR_MAX_VER	1
-#define WL_CHANSPEC_TXPWR_MAX_LEN	(sizeof(wl_chanspec_txpwr_max_t))
-
-typedef struct tx_inst_power {
-	uint8 txpwr_est_Pout[2];			/**< Latest estimate for 2.4 and 5 Ghz */
-	uint8 txpwr_est_Pout_gofdm;			/**< Pwr estimate for 2.4 OFDM */
-} tx_inst_power_t;
-
-#define WL_NUM_TXCHAIN_MAX	4
-typedef struct wl_txchain_pwr_offsets {
-	int8 offset[WL_NUM_TXCHAIN_MAX];	/**< quarter dBm signed offset for each chain */
-} wl_txchain_pwr_offsets_t;
-/* maximum channels returned by the get valid channels iovar */
-#define WL_NUMCHANNELS		64
-
-/*
- * Join preference iovar value is an array of tuples. Each tuple has a one-byte type,
- * a one-byte length, and a variable length value.  RSSI type tuple must be present
- * in the array.
- *
- * Types are defined in "join preference types" section.
- *
- * Length is the value size in octets. It is reserved for WL_JOIN_PREF_WPA type tuple
- * and must be set to zero.
- *
- * Values are defined below.
- *
- * 1. RSSI - 2 octets
- * offset 0: reserved
- * offset 1: reserved
- *
- * 2. WPA - 2 + 12 * n octets (n is # tuples defined below)
- * offset 0: reserved
- * offset 1: # of tuples
- * offset 2: tuple 1
- * offset 14: tuple 2
- * ...
- * offset 2 + 12 * (n - 1) octets: tuple n
- *
- * struct wpa_cfg_tuple {
- *   uint8 akm[DOT11_OUI_LEN+1];     akm suite
- *   uint8 ucipher[DOT11_OUI_LEN+1]; unicast cipher suite
- *   uint8 mcipher[DOT11_OUI_LEN+1]; multicast cipher suite
- * };
- *
- * multicast cipher suite can be specified as a specific cipher suite or WL_WPA_ACP_MCS_ANY.
- *
- * 3. BAND - 2 octets
- * offset 0: reserved
- * offset 1: see "band preference" and "band types"
- *
- * 4. BAND RSSI - 2 octets
- * offset 0: band types
- * offset 1: +ve RSSI boost value in dB
- */
-
-struct tsinfo_arg {
-	uint8 octets[3];
-};
-
-#define RATE_CCK_1MBPS 0
-#define RATE_CCK_2MBPS 1
-#define RATE_CCK_5_5MBPS 2
-#define RATE_CCK_11MBPS 3
-
-#define RATE_LEGACY_OFDM_6MBPS 0
-#define RATE_LEGACY_OFDM_9MBPS 1
-#define RATE_LEGACY_OFDM_12MBPS 2
-#define RATE_LEGACY_OFDM_18MBPS 3
-#define RATE_LEGACY_OFDM_24MBPS 4
-#define RATE_LEGACY_OFDM_36MBPS 5
-#define RATE_LEGACY_OFDM_48MBPS 6
-#define RATE_LEGACY_OFDM_54MBPS 7
-
-#define WL_BSSTRANS_RSSI_RATE_MAP_VERSION 1
-
-typedef struct wl_bsstrans_rssi {
-	int8 rssi_2g;	/**< RSSI in dbm for 2.4 G */
-	int8 rssi_5g;	/**< RSSI in dbm for 5G, unused for cck */
-} wl_bsstrans_rssi_t;
-
-#define RSSI_RATE_MAP_MAX_STREAMS 4	/**< max streams supported */
-
-/* RSSI to rate mapping, all 20Mhz, no SGI */
-typedef struct wl_bsstrans_rssi_rate_map {
-	uint16 ver;
-	uint16 len; /* length of entire structure */
-	wl_bsstrans_rssi_t cck[WL_NUM_RATES_CCK]; /* 2.4G only */
-	wl_bsstrans_rssi_t ofdm[WL_NUM_RATES_OFDM]; /* 6 to 54mbps */
-	wl_bsstrans_rssi_t phy_n[RSSI_RATE_MAP_MAX_STREAMS][WL_NUM_RATES_MCS_1STREAM]; /* MCS0-7 */
-	wl_bsstrans_rssi_t phy_ac[RSSI_RATE_MAP_MAX_STREAMS][WL_NUM_RATES_VHT]; /* MCS0-9 */
-} wl_bsstrans_rssi_rate_map_t;
-
-#define WL_BSSTRANS_ROAMTHROTTLE_VERSION 1
-
-/* Configure number of scans allowed per throttle period */
-typedef struct wl_bsstrans_roamthrottle {
-	uint16 ver;
-	uint16 period;
-	uint16 scans_allowed;
-} wl_bsstrans_roamthrottle_t;
-
-#define	NFIFO			6	/**< # tx/rx fifopairs */
-#define NREINITREASONCOUNT	8
-#define REINITREASONIDX(_x)	(((_x) < NREINITREASONCOUNT) ? (_x) : 0)
-
-#define	WL_CNT_T_VERSION	30	/**< current version of wl_cnt_t struct */
-#define WL_CNT_VERSION_6	6
-#define WL_CNT_VERSION_11	11
-
-#define WLC_WITH_XTLV_CNT
-
-/*
- * tlv IDs uniquely identifies counter component
- * packed into wl_cmd_t container
- */
-enum wl_cnt_xtlv_id {
-	WL_CNT_XTLV_WLC = 0x100,		/**< WLC layer counters */
-	WL_CNT_XTLV_CNTV_LE10_UCODE = 0x200,	/**< wl counter ver < 11 UCODE MACSTAT */
-	WL_CNT_XTLV_LT40_UCODE_V1 = 0x300,	/**< corerev < 40 UCODE MACSTAT */
-	WL_CNT_XTLV_GE40_UCODE_V1 = 0x400,	/**< corerev >= 40 UCODE MACSTAT */
-	WL_CNT_XTLV_GE64_UCODEX_V1 = 0x800	/* corerev >= 64 UCODEX MACSTAT */
-};
-
-/* The number of variables in wl macstat cnt struct.
- * (wl_cnt_ge40mcst_v1_t, wl_cnt_lt40mcst_v1_t, wl_cnt_v_le10_mcst_t)
- */
-#define WL_CNT_MCST_VAR_NUM 64
-/* sizeof(wl_cnt_ge40mcst_v1_t), sizeof(wl_cnt_lt40mcst_v1_t), and sizeof(wl_cnt_v_le10_mcst_t) */
-#define WL_CNT_MCST_STRUCT_SZ ((uint)sizeof(uint32) * WL_CNT_MCST_VAR_NUM)
-
-#define INVALID_CNT_VAL (uint32)(-1)
-#define WL_CNT_MCXST_STRUCT_SZ ((uint)sizeof(wl_cnt_ge64mcxst_v1_t))
-
-#define WL_XTLV_CNTBUF_MAX_SIZE ((uint)(OFFSETOF(wl_cnt_info_t, data)) +        \
-		(uint)BCM_XTLV_HDR_SIZE + (uint)sizeof(wl_cnt_wlc_t) +          \
-		(uint)BCM_XTLV_HDR_SIZE + WL_CNT_MCST_STRUCT_SZ +              \
-		(uint)BCM_XTLV_HDR_SIZE + WL_CNT_MCXST_STRUCT_SZ)
-
-#define WL_CNTBUF_MAX_SIZE MAX(WL_XTLV_CNTBUF_MAX_SIZE, (uint)sizeof(wl_cnt_ver_11_t))
-
-/* Top structure of counters IOVar buffer */
-typedef struct {
-	uint16	version;	/**< see definition of WL_CNT_T_VERSION */
-	uint16	datalen;	/**< length of data including all paddings. */
-	uint8   data [1];	/**< variable length payload:
-				 * 1 or more bcm_xtlv_t type of tuples.
-				 * each tuple is padded to multiple of 4 bytes.
-				 * 'datalen' field of this structure includes all paddings.
-				 */
-} wl_cnt_info_t;
-
-/* wlc layer counters */
-typedef struct {
-	/* transmit stat counters */
-	uint32	txframe;	/**< tx data frames */
-	uint32	txbyte;		/**< tx data bytes */
-	uint32	txretrans;	/**< tx mac retransmits */
-	uint32	txerror;	/**< tx data errors (derived: sum of others) */
-	uint32	txctl;		/**< tx management frames */
-	uint32	txprshort;	/**< tx short preamble frames */
-	uint32	txserr;		/**< tx status errors */
-	uint32	txnobuf;	/**< tx out of buffers errors */
-	uint32	txnoassoc;	/**< tx discard because we're not associated */
-	uint32	txrunt;		/**< tx runt frames */
-	uint32	txchit;		/**< tx header cache hit (fastpath) */
-	uint32	txcmiss;	/**< tx header cache miss (slowpath) */
-
-	/* transmit chip error counters */
-	uint32	txuflo;		/**< tx fifo underflows */
-	uint32	txphyerr;	/**< tx phy errors (indicated in tx status) */
-	uint32	txphycrs;
-
-	/* receive stat counters */
-	uint32	rxframe;	/**< rx data frames */
-	uint32	rxbyte;		/**< rx data bytes */
-	uint32	rxerror;	/**< rx data errors (derived: sum of others) */
-	uint32	rxctl;		/**< rx management frames */
-	uint32	rxnobuf;	/**< rx out of buffers errors */
-	uint32	rxnondata;	/**< rx non data frames in the data channel errors */
-	uint32	rxbadds;	/**< rx bad DS errors */
-	uint32	rxbadcm;	/**< rx bad control or management frames */
-	uint32	rxfragerr;	/**< rx fragmentation errors */
-	uint32	rxrunt;		/**< rx runt frames */
-	uint32	rxgiant;	/**< rx giant frames */
-	uint32	rxnoscb;	/**< rx no scb error */
-	uint32	rxbadproto;	/**< rx invalid frames */
-	uint32	rxbadsrcmac;	/**< rx frames with Invalid Src Mac */
-	uint32	rxbadda;	/**< rx frames tossed for invalid da */
-	uint32	rxfilter;	/**< rx frames filtered out */
-
-	/* receive chip error counters */
-	uint32	rxoflo;		/**< rx fifo overflow errors */
-	uint32	rxuflo[NFIFO];	/**< rx dma descriptor underflow errors */
-
-	uint32	d11cnt_txrts_off;	/**< d11cnt txrts value when reset d11cnt */
-	uint32	d11cnt_rxcrc_off;	/**< d11cnt rxcrc value when reset d11cnt */
-	uint32	d11cnt_txnocts_off;	/**< d11cnt txnocts value when reset d11cnt */
-
-	/* misc counters */
-	uint32	dmade;		/**< tx/rx dma descriptor errors */
-	uint32	dmada;		/**< tx/rx dma data errors */
-	uint32	dmape;		/**< tx/rx dma descriptor protocol errors */
-	uint32	reset;		/**< reset count */
-	uint32	tbtt;		/**< cnts the TBTT int's */
-	uint32	txdmawar;
-	uint32	pkt_callback_reg_fail;	/**< callbacks register failure */
-
-	/* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
-	uint32	txfrag;		/**< dot11TransmittedFragmentCount */
-	uint32	txmulti;	/**< dot11MulticastTransmittedFrameCount */
-	uint32	txfail;		/**< dot11FailedCount */
-	uint32	txretry;	/**< dot11RetryCount */
-	uint32	txretrie;	/**< dot11MultipleRetryCount */
-	uint32	rxdup;		/**< dot11FrameduplicateCount */
-	uint32	txrts;		/**< dot11RTSSuccessCount */
-	uint32	txnocts;	/**< dot11RTSFailureCount */
-	uint32	txnoack;	/**< dot11ACKFailureCount */
-	uint32	rxfrag;		/**< dot11ReceivedFragmentCount */
-	uint32	rxmulti;	/**< dot11MulticastReceivedFrameCount */
-	uint32	rxcrc;		/**< dot11FCSErrorCount */
-	uint32	txfrmsnt;	/**< dot11TransmittedFrameCount (bogus MIB?) */
-	uint32	rxundec;	/**< dot11WEPUndecryptableCount */
-
-	/* WPA2 counters (see rxundec for DecryptFailureCount) */
-	uint32	tkipmicfaill;	/**< TKIPLocalMICFailures */
-	uint32	tkipcntrmsr;	/**< TKIPCounterMeasuresInvoked */
-	uint32	tkipreplay;	/**< TKIPReplays */
-	uint32	ccmpfmterr;	/**< CCMPFormatErrors */
-	uint32	ccmpreplay;	/**< CCMPReplays */
-	uint32	ccmpundec;	/**< CCMPDecryptErrors */
-	uint32	fourwayfail;	/**< FourWayHandshakeFailures */
-	uint32	wepundec;	/**< dot11WEPUndecryptableCount */
-	uint32	wepicverr;	/**< dot11WEPICVErrorCount */
-	uint32	decsuccess;	/**< DecryptSuccessCount */
-	uint32	tkipicverr;	/**< TKIPICVErrorCount */
-	uint32	wepexcluded;	/**< dot11WEPExcludedCount */
-
-	uint32	txchanrej;	/**< Tx frames suppressed due to channel rejection */
-	uint32	psmwds;		/**< Count PSM watchdogs */
-	uint32	phywatchdog;	/**< Count Phy watchdogs (triggered by ucode) */
-
-	/* MBSS counters, AP only */
-	uint32	prq_entries_handled;	/**< PRQ entries read in */
-	uint32	prq_undirected_entries;	/**<    which were bcast bss & ssid */
-	uint32	prq_bad_entries;	/**<    which could not be translated to info */
-	uint32	atim_suppress_count;	/**< TX suppressions on ATIM fifo */
-	uint32	bcn_template_not_ready;	/**< Template marked in use on send bcn ... */
-	uint32	bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */
-	uint32	late_tbtt_dpc;	/**< TBTT DPC did not happen in time */
-
-	/* per-rate receive stat counters */
-	uint32  rx1mbps;	/* packets rx at 1Mbps */
-	uint32  rx2mbps;	/* packets rx at 2Mbps */
-	uint32  rx5mbps5;	/* packets rx at 5.5Mbps */
-	uint32  rx6mbps;	/* packets rx at 6Mbps */
-	uint32  rx9mbps;	/* packets rx at 9Mbps */
-	uint32  rx11mbps;	/* packets rx at 11Mbps */
-	uint32  rx12mbps;	/* packets rx at 12Mbps */
-	uint32  rx18mbps;	/* packets rx at 18Mbps */
-	uint32  rx24mbps;	/* packets rx at 24Mbps */
-	uint32  rx36mbps;	/* packets rx at 36Mbps */
-	uint32  rx48mbps;	/* packets rx at 48Mbps */
-	uint32  rx54mbps;	/* packets rx at 54Mbps */
-	uint32  rx108mbps;	/* packets rx at 108mbps */
-	uint32  rx162mbps;	/* packets rx at 162mbps */
-	uint32  rx216mbps;	/* packets rx at 216 mbps */
-	uint32  rx270mbps;	/* packets rx at 270 mbps */
-	uint32  rx324mbps;	/* packets rx at 324 mbps */
-	uint32  rx378mbps;	/* packets rx at 378 mbps */
-	uint32  rx432mbps;	/* packets rx at 432 mbps */
-	uint32  rx486mbps;	/* packets rx at 486 mbps */
-	uint32  rx540mbps;	/* packets rx at 540 mbps */
-
-	uint32	rfdisable;	/**< count of radio disables */
-
-	uint32	txexptime;	/**< Tx frames suppressed due to timer expiration */
-
-	uint32	txmpdu_sgi;	/**< count for sgi transmit */
-	uint32	rxmpdu_sgi;	/**< count for sgi received */
-	uint32	txmpdu_stbc;	/**< count for stbc transmit */
-	uint32	rxmpdu_stbc;	/**< count for stbc received */
-
-	uint32	rxundec_mcst;	/**< dot11WEPUndecryptableCount */
-
-	/* WPA2 counters (see rxundec for DecryptFailureCount) */
-	uint32	tkipmicfaill_mcst;	/**< TKIPLocalMICFailures */
-	uint32	tkipcntrmsr_mcst;	/**< TKIPCounterMeasuresInvoked */
-	uint32	tkipreplay_mcst;	/**< TKIPReplays */
-	uint32	ccmpfmterr_mcst;	/**< CCMPFormatErrors */
-	uint32	ccmpreplay_mcst;	/**< CCMPReplays */
-	uint32	ccmpundec_mcst;	/**< CCMPDecryptErrors */
-	uint32	fourwayfail_mcst;	/**< FourWayHandshakeFailures */
-	uint32	wepundec_mcst;	/**< dot11WEPUndecryptableCount */
-	uint32	wepicverr_mcst;	/**< dot11WEPICVErrorCount */
-	uint32	decsuccess_mcst;	/**< DecryptSuccessCount */
-	uint32	tkipicverr_mcst;	/**< TKIPICVErrorCount */
-	uint32	wepexcluded_mcst;	/**< dot11WEPExcludedCount */
-
-	uint32	dma_hang;	/**< count for dma hang */
-	uint32	reinit;		/**< count for reinit */
-
-	uint32  pstatxucast;	/**< count of ucast frames xmitted on all psta assoc */
-	uint32  pstatxnoassoc;	/**< count of txnoassoc frames xmitted on all psta assoc */
-	uint32  pstarxucast;	/**< count of ucast frames received on all psta assoc */
-	uint32  pstarxbcmc;	/**< count of bcmc frames received on all psta */
-	uint32  pstatxbcmc;	/**< count of bcmc frames transmitted on all psta */
-
-	uint32  cso_passthrough; /* hw cso required but passthrough */
-	uint32	cso_normal;	/**< hw cso hdr for normal process */
-	uint32	chained;	/**< number of frames chained */
-	uint32	chainedsz1;	/**< number of chain size 1 frames */
-	uint32	unchained;	/**< number of frames not chained */
-	uint32	maxchainsz;	/**< max chain size so far */
-	uint32	currchainsz;	/**< current chain size */
-	uint32	pciereset;	/**< Secondary Bus Reset issued by driver */
-	uint32	cfgrestore;	/**< configspace restore by driver */
-	uint32	reinitreason[NREINITREASONCOUNT]; /* reinitreason counters; 0: Unknown reason */
-	uint32	rxrtry;
-
-	uint32  rxmpdu_mu;      /* Number of MU MPDUs received */
-
-	/* detailed control/management frames */
-	uint32  txbar;          /**< Number of TX BAR */
-	uint32  rxbar;          /**< Number of RX BAR */
-	uint32  txpspoll;       /**< Number of TX PS-poll */
-	uint32  rxpspoll;       /**< Number of RX PS-poll */
-	uint32  txnull;         /**< Number of TX NULL_DATA */
-	uint32  rxnull;         /**< Number of RX NULL_DATA */
-	uint32  txqosnull;      /**< Number of TX NULL_QoSDATA */
-	uint32  rxqosnull;      /**< Number of RX NULL_QoSDATA */
-	uint32  txassocreq;     /**< Number of TX ASSOC request */
-	uint32  rxassocreq;     /**< Number of RX ASSOC request */
-	uint32  txreassocreq;   /**< Number of TX REASSOC request */
-	uint32  rxreassocreq;   /**< Number of RX REASSOC request */
-	uint32  txdisassoc;     /**< Number of TX DISASSOC */
-	uint32  rxdisassoc;     /**< Number of RX DISASSOC */
-	uint32  txassocrsp;     /**< Number of TX ASSOC response */
-	uint32  rxassocrsp;     /**< Number of RX ASSOC response */
-	uint32  txreassocrsp;   /**< Number of TX REASSOC response */
-	uint32  rxreassocrsp;   /**< Number of RX REASSOC response */
-	uint32  txauth;         /**< Number of TX AUTH */
-	uint32  rxauth;         /**< Number of RX AUTH */
-	uint32  txdeauth;       /**< Number of TX DEAUTH */
-	uint32  rxdeauth;       /**< Number of RX DEAUTH */
-	uint32  txprobereq;     /**< Number of TX probe request */
-	uint32  rxprobereq;     /**< Number of RX probe request */
-	uint32  txprobersp;     /**< Number of TX probe response */
-	uint32  rxprobersp;     /**< Number of RX probe response */
-	uint32  txaction;       /**< Number of TX action frame */
-	uint32  rxaction;       /**< Number of RX action frame */
-} wl_cnt_wlc_t;
-
-/* MACXSTAT counters for ucodex (corerev >= 64) */
-typedef struct {
-	uint32 macxsusp;
-	uint32 m2vmsg;
-	uint32 v2mmsg;
-	uint32 mboxout;
-	uint32 musnd;
-	uint32 sfb2v;
-} wl_cnt_ge64mcxst_v1_t;
-
-/* MACSTAT counters for ucode (corerev >= 40) */
-typedef struct {
-	/* MAC counters: 32-bit version of d11.h's macstat_t */
-	uint32	txallfrm;	/**< total number of frames sent, incl. Data, ACK, RTS, CTS,
-				 * Control Management (includes retransmissions)
-				 */
-	uint32	txrtsfrm;	/**< number of RTS sent out by the MAC */
-	uint32	txctsfrm;	/**< number of CTS sent out by the MAC */
-	uint32	txackfrm;	/**< number of ACK frames sent out */
-	uint32	txdnlfrm;	/**< number of Null-Data transmission generated from template  */
-	uint32	txbcnfrm;	/**< beacons transmitted */
-	uint32	txfunfl[6];	/**< per-fifo tx underflows */
-	uint32	txampdu;	/**< number of AMPDUs transmitted */
-	uint32	txmpdu;		/**< number of MPDUs transmitted */
-	uint32	txtplunfl;	/**< Template underflows (mac was too slow to transmit ACK/CTS
-				 * or BCN)
-				 */
-	uint32	txphyerror;	/**< Transmit phy error, type of error is reported in tx-status for
-				 * driver enqueued frames
-				 */
-	uint32  pktengrxducast; /* unicast frames rxed by the pkteng code */
-	uint32  pktengrxdmcast; /* multicast frames rxed by the pkteng code */
-	uint32	rxfrmtoolong;	/**< Received frame longer than legal limit (2346 bytes) */
-	uint32	rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */
-	uint32	rxanyerr;	/**< Any RX error that is not counted by other counters. */
-	uint32	rxbadfcs;	/**< number of frames for which the CRC check failed in the MAC */
-	uint32	rxbadplcp;	/**< parity check of the PLCP header failed */
-	uint32	rxcrsglitch;	/**< PHY was able to correlate the preamble but not the header */
-	uint32	rxstrt;		/**< Number of received frames with a good PLCP
-				 * (i.e. passing parity check)
-				 */
-	uint32	rxdtucastmbss; /**< number of received DATA frames with good FCS and matching RA */
-	uint32	rxmgucastmbss; /**< number of received mgmt frames with good FCS and matching RA */
-	uint32	rxctlucast; /**< number of received CNTRL frames with good FCS and matching RA */
-	uint32	rxrtsucast;	/**< number of unicast RTS addressed to the MAC (good FCS) */
-	uint32	rxctsucast;	/**< number of unicast CTS addressed to the MAC (good FCS) */
-	uint32	rxackucast;	/**< number of ucast ACKS received (good FCS) */
-	uint32	rxdtocast; /**< number of received DATA frames (good FCS and not matching RA) */
-	uint32	rxmgocast; /**< number of received MGMT frames (good FCS and not matching RA) */
-	uint32	rxctlocast; /**< number of received CNTRL frame (good FCS and not matching RA) */
-	uint32	rxrtsocast;	/**< number of received RTS not addressed to the MAC */
-	uint32	rxctsocast;	/**< number of received CTS not addressed to the MAC */
-	uint32	rxdtmcast;	/**< number of RX Data multicast frames received by the MAC */
-	uint32	rxmgmcast;	/**< number of RX Management multicast frames received by the MAC */
-	uint32	rxctlmcast;	/**< number of RX Control multicast frames received by the MAC
-				 * (unlikely to see these)
-				 */
-	uint32	rxbeaconmbss;	/**< beacons received from member of BSS */
-	uint32	rxdtucastobss; /* number of unicast frames addressed to the MAC from
-				  * other BSS (WDS FRAME)
-				  */
-	uint32	rxbeaconobss;	/**< beacons received from other BSS */
-	uint32	rxrsptmout;	/**< number of response timeouts for transmitted frames
-				 * expecting a response
-				 */
-	uint32	bcntxcancl;	/**< transmit beacons canceled due to receipt of beacon (IBSS) */
-	uint32	rxnodelim;	/**< number of no valid delimiter detected by ampdu parser */
-	uint32	rxf0ovfl;	/**< number of receive fifo 0 overflows */
-	uint32	rxf1ovfl;	/**< number of receive fifo 1 overflows */
-	uint32	rxhlovfl;	/**< number of length / header fifo overflows */
-	uint32	missbcn_dbg;	/**< number of beacon missed to receive */
-	uint32	pmqovfl;	/**< number of PMQ overflows */
-	uint32	rxcgprqfrm;	/**< number of received Probe requests that made it into
-				 * the PRQ fifo
-				 */
-	uint32	rxcgprsqovfl;	/**< Rx Probe Request Que overflow in the AP */
-	uint32	txcgprsfail;	/**< Tx Probe Response Fail. AP sent probe response but did
-				 * not get ACK
-				 */
-	uint32	txcgprssuc;	/**< Tx Probe Response Success (ACK was received) */
-	uint32	prs_timeout;	/**< number of probe requests that were dropped from the PRQ
-				 * fifo because a probe response could not be sent out within
-				 * the time limit defined in M_PRS_MAXTIME
-				 */
-	uint32	txrtsfail;	/**< number of rts transmission failure that reach retry limit */
-	uint32	txucast;	/**< number of unicast tx expecting response other than cts/cwcts */
-	uint32  txinrtstxop;	/**< number of data frame transmissions during rts txop */
-	uint32	rxback;		/**< blockack rxcnt */
-	uint32	txback;		/**< blockack txcnt */
-	uint32	bphy_rxcrsglitch;	/**< PHY count of bphy glitches */
-	uint32	rxdrop20s;	/**< drop secondary cnt */
-	uint32	rxtoolate;	/**< receive too late */
-	uint32  bphy_badplcp;	/**< number of bad PLCP reception on BPHY rate */
-} wl_cnt_ge40mcst_v1_t;
-
-/* MACSTAT counters for ucode (corerev < 40) */
-typedef struct {
-	/* MAC counters: 32-bit version of d11.h's macstat_t */
-	uint32	txallfrm;	/**< total number of frames sent, incl. Data, ACK, RTS, CTS,
-				 * Control Management (includes retransmissions)
-				 */
-	uint32	txrtsfrm;	/**< number of RTS sent out by the MAC */
-	uint32	txctsfrm;	/**< number of CTS sent out by the MAC */
-	uint32	txackfrm;	/**< number of ACK frames sent out */
-	uint32	txdnlfrm;	/**< number of Null-Data transmission generated from template  */
-	uint32	txbcnfrm;	/**< beacons transmitted */
-	uint32	txfunfl[6];	/**< per-fifo tx underflows */
-	uint32	txampdu;	/**< number of AMPDUs transmitted */
-	uint32	txmpdu;		/**< number of MPDUs transmitted */
-	uint32	txtplunfl;	/**< Template underflows (mac was too slow to transmit ACK/CTS
-				 * or BCN)
-				 */
-	uint32	txphyerror;	/**< Transmit phy error, type of error is reported in tx-status for
-				 * driver enqueued frames
-				 */
-	uint32  pktengrxducast; /**< unicast frames rxed by the pkteng code */
-	uint32  pktengrxdmcast; /**< multicast frames rxed by the pkteng code */
-	uint32	rxfrmtoolong;	/**< Received frame longer than legal limit (2346 bytes) */
-	uint32	rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */
-	uint32	rxanyerr;	/**< Any RX error that is not counted by other counters. */
-	uint32	rxbadfcs;	/**< number of frames for which the CRC check failed in the MAC */
-	uint32	rxbadplcp;	/**< parity check of the PLCP header failed */
-	uint32	rxcrsglitch;	/**< PHY was able to correlate the preamble but not the header */
-	uint32	rxstrt;		/**< Number of received frames with a good PLCP
-				 * (i.e. passing parity check)
-				 */
-	uint32	rxdtucastmbss; /**< number of received DATA frames with good FCS and matching RA */
-	uint32	rxmgucastmbss; /**< number of received mgmt frames with good FCS and matching RA */
-	uint32	rxctlucast; /**< number of received CNTRL frames with good FCS and matching RA */
-	uint32	rxrtsucast;	/**< number of unicast RTS addressed to the MAC (good FCS) */
-	uint32	rxctsucast;	/**< number of unicast CTS addressed to the MAC (good FCS) */
-	uint32	rxackucast;	/**< number of ucast ACKS received (good FCS) */
-	uint32	rxdtocast;  /**< number of received DATA frames (good FCS and not matching RA) */
-	uint32	rxmgocast;  /**< number of received MGMT frames (good FCS and not matching RA) */
-	uint32	rxctlocast; /**< number of received CNTRL frame (good FCS and not matching RA) */
-	uint32	rxrtsocast;	/**< number of received RTS not addressed to the MAC */
-	uint32	rxctsocast;	/**< number of received CTS not addressed to the MAC */
-	uint32	rxdtmcast;	/**< number of RX Data multicast frames received by the MAC */
-	uint32	rxmgmcast;	/**< number of RX Management multicast frames received by the MAC */
-	uint32	rxctlmcast;	/**< number of RX Control multicast frames received by the MAC
-				 * (unlikely to see these)
-				 */
-	uint32	rxbeaconmbss;	/**< beacons received from member of BSS */
-	uint32	rxdtucastobss; /* number of unicast frames addressed to the MAC from
-				  * other BSS (WDS FRAME)
-				  */
-	uint32	rxbeaconobss;	/**< beacons received from other BSS */
-	uint32	rxrsptmout;	/**< number of response timeouts for transmitted frames
-				 * expecting a response
-				 */
-	uint32	bcntxcancl;	/**< transmit beacons canceled due to receipt of beacon (IBSS) */
-	uint32	rxnodelim;	/**< number of no valid delimiter detected by ampdu parser */
-	uint32	rxf0ovfl;	/**< number of receive fifo 0 overflows */
-	uint32	dbgoff46;
-	uint32	dbgoff47;
-	uint32	dbgoff48;	/**< Used for counting txstatus queue overflow (corerev <= 4)  */
-	uint32	pmqovfl;	/**< number of PMQ overflows */
-	uint32	rxcgprqfrm;	/**< number of received Probe requests that made it into
-				 * the PRQ fifo
-				 */
-	uint32	rxcgprsqovfl;	/**< Rx Probe Request Que overflow in the AP */
-	uint32	txcgprsfail;	/**< Tx Probe Response Fail. AP sent probe response but did
-				 * not get ACK
-				 */
-	uint32	txcgprssuc;	/**< Tx Probe Response Success (ACK was received) */
-	uint32	prs_timeout;	/**< number of probe requests that were dropped from the PRQ
-				 * fifo because a probe response could not be sent out within
-				 * the time limit defined in M_PRS_MAXTIME
-				 */
-	uint32	txrtsfail;	/**< number of rts transmission failure that reach retry limit */
-	uint32	txucast;	/**< number of unicast tx expecting response other than cts/cwcts */
-	uint32  txinrtstxop;	/**< number of data frame transmissions during rts txop */
-	uint32	rxback;		/**< blockack rxcnt */
-	uint32	txback;		/**< blockack txcnt */
-	uint32	bphy_rxcrsglitch;	/**< PHY count of bphy glitches */
-	uint32	phywatch;
-	uint32	rxtoolate;	/**< receive too late */
-	uint32  bphy_badplcp;	/**< number of bad PLCP reception on BPHY rate */
-} wl_cnt_lt40mcst_v1_t;
-
-/* MACSTAT counters for "wl counter" version <= 10 */
-typedef struct {
-	/* MAC counters: 32-bit version of d11.h's macstat_t */
-	uint32	txallfrm;	/**< total number of frames sent, incl. Data, ACK, RTS, CTS,
-				 * Control Management (includes retransmissions)
-				 */
-	uint32	txrtsfrm;	/**< number of RTS sent out by the MAC */
-	uint32	txctsfrm;	/**< number of CTS sent out by the MAC */
-	uint32	txackfrm;	/**< number of ACK frames sent out */
-	uint32	txdnlfrm;	/**< number of Null-Data transmission generated from template  */
-	uint32	txbcnfrm;	/**< beacons transmitted */
-	uint32	txfunfl[6];	/**< per-fifo tx underflows */
-	uint32	txfbw;		/**< transmit at fallback bw (dynamic bw) */
-	uint32	PAD0;		/**< number of MPDUs transmitted */
-	uint32	txtplunfl;	/**< Template underflows (mac was too slow to transmit ACK/CTS
-				 * or BCN)
-				 */
-	uint32	txphyerror;	/**< Transmit phy error, type of error is reported in tx-status for
-				 * driver enqueued frames
-				 */
-	uint32  pktengrxducast; /* unicast frames rxed by the pkteng code */
-	uint32  pktengrxdmcast; /* multicast frames rxed by the pkteng code */
-	uint32	rxfrmtoolong;	/**< Received frame longer than legal limit (2346 bytes) */
-	uint32	rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */
-	uint32	rxinvmachdr;	/**< Either the protocol version != 0 or frame type not
-				 * data/control/management
-				 */
-	uint32	rxbadfcs;	/**< number of frames for which the CRC check failed in the MAC */
-	uint32	rxbadplcp;	/**< parity check of the PLCP header failed */
-	uint32	rxcrsglitch;	/**< PHY was able to correlate the preamble but not the header */
-	uint32	rxstrt;		/**< Number of received frames with a good PLCP
-				 * (i.e. passing parity check)
-				 */
-	uint32	rxdfrmucastmbss; /* number of received DATA frames with good FCS and matching RA */
-	uint32	rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
-	uint32	rxcfrmucast; /**< number of received CNTRL frames with good FCS and matching RA */
-	uint32	rxrtsucast;  /**< number of unicast RTS addressed to the MAC (good FCS) */
-	uint32	rxctsucast;  /**< number of unicast CTS addressed to the MAC (good FCS) */
-	uint32	rxackucast;	/**< number of ucast ACKS received (good FCS) */
-	uint32	rxdfrmocast; /**< number of received DATA frames (good FCS and not matching RA) */
-	uint32	rxmfrmocast; /**< number of received MGMT frames (good FCS and not matching RA) */
-	uint32	rxcfrmocast; /**< number of received CNTRL frame (good FCS and not matching RA) */
-	uint32	rxrtsocast;	/**< number of received RTS not addressed to the MAC */
-	uint32	rxctsocast;	/**< number of received CTS not addressed to the MAC */
-	uint32	rxdfrmmcast;	/**< number of RX Data multicast frames received by the MAC */
-	uint32	rxmfrmmcast;	/**< number of RX Management multicast frames received by the MAC */
-	uint32	rxcfrmmcast;	/**< number of RX Control multicast frames received by the MAC
-				 * (unlikely to see these)
-				 */
-	uint32	rxbeaconmbss;	/**< beacons received from member of BSS */
-	uint32	rxdfrmucastobss; /**< number of unicast frames addressed to the MAC from
-				  * other BSS (WDS FRAME)
-				  */
-	uint32	rxbeaconobss;	/**< beacons received from other BSS */
-	uint32	rxrsptmout;	/**< number of response timeouts for transmitted frames
-				 * expecting a response
-				 */
-	uint32	bcntxcancl;	/**< transmit beacons canceled due to receipt of beacon (IBSS) */
-	uint32	PAD1;
-	uint32	rxf0ovfl;	/**< number of receive fifo 0 overflows */
-	uint32	rxf1ovfl;	/**< Number of receive fifo 1 overflows (obsolete) */
-	uint32	rxf2ovfl;	/**< Number of receive fifo 2 overflows (obsolete) */
-	uint32	txsfovfl;	/**< Number of transmit status fifo overflows (obsolete) */
-	uint32	pmqovfl;	/**< number of PMQ overflows */
-	uint32	rxcgprqfrm;	/**< number of received Probe requests that made it into
-				 * the PRQ fifo
-				 */
-	uint32	rxcgprsqovfl;	/**< Rx Probe Request Que overflow in the AP */
-	uint32	txcgprsfail;	/**< Tx Probe Response Fail. AP sent probe response but did
-				 * not get ACK
-				 */
-	uint32	txcgprssuc;	/**< Tx Probe Response Success (ACK was received) */
-	uint32	prs_timeout;	/**< number of probe requests that were dropped from the PRQ
-				 * fifo because a probe response could not be sent out within
-				 * the time limit defined in M_PRS_MAXTIME
-				 */
-	uint32	rxnack;		/**< obsolete */
-	uint32	frmscons;	/**< obsolete */
-	uint32  txnack;		/**< obsolete */
-	uint32	rxback;		/**< blockack rxcnt */
-	uint32	txback;		/**< blockack txcnt */
-	uint32	bphy_rxcrsglitch;	/**< PHY count of bphy glitches */
-	uint32	rxdrop20s;	/**< drop secondary cnt */
-	uint32	rxtoolate;	/**< receive too late */
-	uint32  bphy_badplcp;	/**< number of bad PLCP reception on BPHY rate */
-} wl_cnt_v_le10_mcst_t;
-
-typedef struct {
-	uint16	version;	/**< see definition of WL_CNT_T_VERSION */
-	uint16	length;		/**< length of entire structure */
-
-	/* transmit stat counters */
-	uint32	txframe;	/**< tx data frames */
-	uint32	txbyte;		/**< tx data bytes */
-	uint32	txretrans;	/**< tx mac retransmits */
-	uint32	txerror;	/**< tx data errors (derived: sum of others) */
-	uint32	txctl;		/**< tx management frames */
-	uint32	txprshort;	/**< tx short preamble frames */
-	uint32	txserr;		/**< tx status errors */
-	uint32	txnobuf;	/**< tx out of buffers errors */
-	uint32	txnoassoc;	/**< tx discard because we're not associated */
-	uint32	txrunt;		/**< tx runt frames */
-	uint32	txchit;		/**< tx header cache hit (fastpath) */
-	uint32	txcmiss;	/**< tx header cache miss (slowpath) */
-
-	/* transmit chip error counters */
-	uint32	txuflo;		/**< tx fifo underflows */
-	uint32	txphyerr;	/**< tx phy errors (indicated in tx status) */
-	uint32	txphycrs;
-
-	/* receive stat counters */
-	uint32	rxframe;	/**< rx data frames */
-	uint32	rxbyte;		/**< rx data bytes */
-	uint32	rxerror;	/**< rx data errors (derived: sum of others) */
-	uint32	rxctl;		/**< rx management frames */
-	uint32	rxnobuf;	/**< rx out of buffers errors */
-	uint32	rxnondata;	/**< rx non data frames in the data channel errors */
-	uint32	rxbadds;	/**< rx bad DS errors */
-	uint32	rxbadcm;	/**< rx bad control or management frames */
-	uint32	rxfragerr;	/**< rx fragmentation errors */
-	uint32	rxrunt;		/**< rx runt frames */
-	uint32	rxgiant;	/**< rx giant frames */
-	uint32	rxnoscb;	/**< rx no scb error */
-	uint32	rxbadproto;	/**< rx invalid frames */
-	uint32	rxbadsrcmac;	/**< rx frames with Invalid Src Mac */
-	uint32	rxbadda;	/**< rx frames tossed for invalid da */
-	uint32	rxfilter;	/**< rx frames filtered out */
-
-	/* receive chip error counters */
-	uint32	rxoflo;		/**< rx fifo overflow errors */
-	uint32	rxuflo[NFIFO];	/**< rx dma descriptor underflow errors */
-
-	uint32	d11cnt_txrts_off;	/**< d11cnt txrts value when reset d11cnt */
-	uint32	d11cnt_rxcrc_off;	/**< d11cnt rxcrc value when reset d11cnt */
-	uint32	d11cnt_txnocts_off;	/**< d11cnt txnocts value when reset d11cnt */
-
-	/* misc counters */
-	uint32	dmade;		/**< tx/rx dma descriptor errors */
-	uint32	dmada;		/**< tx/rx dma data errors */
-	uint32	dmape;		/**< tx/rx dma descriptor protocol errors */
-	uint32	reset;		/**< reset count */
-	uint32	tbtt;		/**< cnts the TBTT int's */
-	uint32	txdmawar;
-	uint32	pkt_callback_reg_fail;	/**< callbacks register failure */
-
-	/* MAC counters: 32-bit version of d11.h's macstat_t */
-	uint32	txallfrm;	/**< total number of frames sent, incl. Data, ACK, RTS, CTS,
-				 * Control Management (includes retransmissions)
-				 */
-	uint32	txrtsfrm;	/**< number of RTS sent out by the MAC */
-	uint32	txctsfrm;	/**< number of CTS sent out by the MAC */
-	uint32	txackfrm;	/**< number of ACK frames sent out */
-	uint32	txdnlfrm;	/**< Not used */
-	uint32	txbcnfrm;	/**< beacons transmitted */
-	uint32	txfunfl[6];	/**< per-fifo tx underflows */
-	uint32	rxtoolate;	/**< receive too late */
-	uint32  txfbw;		/**< transmit at fallback bw (dynamic bw) */
-	uint32	txtplunfl;	/**< Template underflows (mac was too slow to transmit ACK/CTS
-				 * or BCN)
-				 */
-	uint32	txphyerror;	/**< Transmit phy error, type of error is reported in tx-status for
-				 * driver enqueued frames
-				 */
-	uint32	rxfrmtoolong;	/**< Received frame longer than legal limit (2346 bytes) */
-	uint32	rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */
-	uint32	rxinvmachdr;	/**< Either the protocol version != 0 or frame type not
-				 * data/control/management
-				 */
-	uint32	rxbadfcs;	/**< number of frames for which the CRC check failed in the MAC */
-	uint32	rxbadplcp;	/**< parity check of the PLCP header failed */
-	uint32	rxcrsglitch;	/**< PHY was able to correlate the preamble but not the header */
-	uint32	rxstrt;		/**< Number of received frames with a good PLCP
-				 * (i.e. passing parity check)
-				 */
-	uint32	rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */
-	uint32	rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
-	uint32	rxcfrmucast; /**< number of received CNTRL frames with good FCS and matching RA */
-	uint32	rxrtsucast;	/**< number of unicast RTS addressed to the MAC (good FCS) */
-	uint32	rxctsucast;	/**< number of unicast CTS addressed to the MAC (good FCS) */
-	uint32	rxackucast;	/**< number of ucast ACKS received (good FCS) */
-	uint32	rxdfrmocast; /**< number of received DATA frames (good FCS and not matching RA) */
-	uint32	rxmfrmocast; /**< number of received MGMT frames (good FCS and not matching RA) */
-	uint32	rxcfrmocast; /**< number of received CNTRL frame (good FCS and not matching RA) */
-	uint32	rxrtsocast;	/**< number of received RTS not addressed to the MAC */
-	uint32	rxctsocast;	/**< number of received CTS not addressed to the MAC */
-	uint32	rxdfrmmcast;	/**< number of RX Data multicast frames received by the MAC */
-	uint32	rxmfrmmcast;	/**< number of RX Management multicast frames received by the MAC */
-	uint32	rxcfrmmcast;	/**< number of RX Control multicast frames received by the MAC
-				 * (unlikely to see these)
-				 */
-	uint32	rxbeaconmbss;	/**< beacons received from member of BSS */
-	uint32	rxdfrmucastobss; /* number of unicast frames addressed to the MAC from
-				  * other BSS (WDS FRAME)
-				  */
-	uint32	rxbeaconobss;	/**< beacons received from other BSS */
-	uint32	rxrsptmout;	/**< Number of response timeouts for transmitted frames
-				 * expecting a response
-				 */
-	uint32	bcntxcancl;	/**< transmit beacons canceled due to receipt of beacon (IBSS) */
-	uint32	rxf0ovfl;	/**< Number of receive fifo 0 overflows */
-	uint32	rxf1ovfl;	/**< Number of receive fifo 1 overflows (obsolete) */
-	uint32	rxf2ovfl;	/**< Number of receive fifo 2 overflows (obsolete) */
-	uint32	txsfovfl;	/**< Number of transmit status fifo overflows (obsolete) */
-	uint32	pmqovfl;	/**< Number of PMQ overflows */
-	uint32	rxcgprqfrm;	/**< Number of received Probe requests that made it into
-				 * the PRQ fifo
-				 */
-	uint32	rxcgprsqovfl;	/**< Rx Probe Request Que overflow in the AP */
-	uint32	txcgprsfail;	/**< Tx Probe Response Fail. AP sent probe response but did
-				 * not get ACK
-				 */
-	uint32	txcgprssuc;	/**< Tx Probe Response Success (ACK was received) */
-	uint32	prs_timeout;	/**< Number of probe requests that were dropped from the PRQ
-				 * fifo because a probe response could not be sent out within
-				 * the time limit defined in M_PRS_MAXTIME
-				 */
-	uint32	rxnack;		/**< obsolete */
-	uint32	frmscons;	/**< obsolete */
-	uint32  txnack;		/**< obsolete */
-	uint32	rxback;		/**< blockack rxcnt */
-	uint32	txback;		/**< blockack txcnt */
-
-	/* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
-	uint32	txfrag;		/**< dot11TransmittedFragmentCount */
-	uint32	txmulti;	/**< dot11MulticastTransmittedFrameCount */
-	uint32	txfail;		/**< dot11FailedCount */
-	uint32	txretry;	/**< dot11RetryCount */
-	uint32	txretrie;	/**< dot11MultipleRetryCount */
-	uint32	rxdup;		/**< dot11FrameduplicateCount */
-	uint32	txrts;		/**< dot11RTSSuccessCount */
-	uint32	txnocts;	/**< dot11RTSFailureCount */
-	uint32	txnoack;	/**< dot11ACKFailureCount */
-	uint32	rxfrag;		/**< dot11ReceivedFragmentCount */
-	uint32	rxmulti;	/**< dot11MulticastReceivedFrameCount */
-	uint32	rxcrc;		/**< dot11FCSErrorCount */
-	uint32	txfrmsnt;	/**< dot11TransmittedFrameCount (bogus MIB?) */
-	uint32	rxundec;	/**< dot11WEPUndecryptableCount */
-
-	/* WPA2 counters (see rxundec for DecryptFailureCount) */
-	uint32	tkipmicfaill;	/**< TKIPLocalMICFailures */
-	uint32	tkipcntrmsr;	/**< TKIPCounterMeasuresInvoked */
-	uint32	tkipreplay;	/**< TKIPReplays */
-	uint32	ccmpfmterr;	/**< CCMPFormatErrors */
-	uint32	ccmpreplay;	/**< CCMPReplays */
-	uint32	ccmpundec;	/**< CCMPDecryptErrors */
-	uint32	fourwayfail;	/**< FourWayHandshakeFailures */
-	uint32	wepundec;	/**< dot11WEPUndecryptableCount */
-	uint32	wepicverr;	/**< dot11WEPICVErrorCount */
-	uint32	decsuccess;	/**< DecryptSuccessCount */
-	uint32	tkipicverr;	/**< TKIPICVErrorCount */
-	uint32	wepexcluded;	/**< dot11WEPExcludedCount */
-
-	uint32	txchanrej;	/**< Tx frames suppressed due to channel rejection */
-	uint32	psmwds;		/**< Count PSM watchdogs */
-	uint32	phywatchdog;	/**< Count Phy watchdogs (triggered by ucode) */
-
-	/* MBSS counters, AP only */
-	uint32	prq_entries_handled;	/**< PRQ entries read in */
-	uint32	prq_undirected_entries;	/**<    which were bcast bss & ssid */
-	uint32	prq_bad_entries;	/**<    which could not be translated to info */
-	uint32	atim_suppress_count;	/**< TX suppressions on ATIM fifo */
-	uint32	bcn_template_not_ready;	/**< Template marked in use on send bcn ... */
-	uint32	bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */
-	uint32	late_tbtt_dpc;	/**< TBTT DPC did not happen in time */
-
-	/* per-rate receive stat counters */
-	uint32  rx1mbps;	/* packets rx at 1Mbps */
-	uint32  rx2mbps;	/* packets rx at 2Mbps */
-	uint32  rx5mbps5;	/* packets rx at 5.5Mbps */
-	uint32  rx6mbps;	/* packets rx at 6Mbps */
-	uint32  rx9mbps;	/* packets rx at 9Mbps */
-	uint32  rx11mbps;	/* packets rx at 11Mbps */
-	uint32  rx12mbps;	/* packets rx at 12Mbps */
-	uint32  rx18mbps;	/* packets rx at 18Mbps */
-	uint32  rx24mbps;	/* packets rx at 24Mbps */
-	uint32  rx36mbps;	/* packets rx at 36Mbps */
-	uint32  rx48mbps;	/* packets rx at 48Mbps */
-	uint32  rx54mbps;	/* packets rx at 54Mbps */
-	uint32  rx108mbps;	/* packets rx at 108mbps */
-	uint32  rx162mbps;	/* packets rx at 162mbps */
-	uint32  rx216mbps;	/* packets rx at 216 mbps */
-	uint32  rx270mbps;	/* packets rx at 270 mbps */
-	uint32  rx324mbps;	/* packets rx at 324 mbps */
-	uint32  rx378mbps;	/* packets rx at 378 mbps */
-	uint32  rx432mbps;	/* packets rx at 432 mbps */
-	uint32  rx486mbps;	/* packets rx at 486 mbps */
-	uint32  rx540mbps;	/* packets rx at 540 mbps */
-
-	/* pkteng rx frame stats */
-	uint32	pktengrxducast; /* unicast frames rxed by the pkteng code */
-	uint32	pktengrxdmcast; /* multicast frames rxed by the pkteng code */
-
-	uint32	rfdisable;	/**< count of radio disables */
-	uint32	bphy_rxcrsglitch;	/**< PHY count of bphy glitches */
-	uint32  bphy_badplcp;
-
-	uint32	txexptime;	/**< Tx frames suppressed due to timer expiration */
-
-	uint32	txmpdu_sgi;	/**< count for sgi transmit */
-	uint32	rxmpdu_sgi;	/**< count for sgi received */
-	uint32	txmpdu_stbc;	/**< count for stbc transmit */
-	uint32	rxmpdu_stbc;	/**< count for stbc received */
-
-	uint32	rxundec_mcst;	/**< dot11WEPUndecryptableCount */
-
-	/* WPA2 counters (see rxundec for DecryptFailureCount) */
-	uint32	tkipmicfaill_mcst;	/**< TKIPLocalMICFailures */
-	uint32	tkipcntrmsr_mcst;	/**< TKIPCounterMeasuresInvoked */
-	uint32	tkipreplay_mcst;	/**< TKIPReplays */
-	uint32	ccmpfmterr_mcst;	/**< CCMPFormatErrors */
-	uint32	ccmpreplay_mcst;	/**< CCMPReplays */
-	uint32	ccmpundec_mcst;	/**< CCMPDecryptErrors */
-	uint32	fourwayfail_mcst;	/**< FourWayHandshakeFailures */
-	uint32	wepundec_mcst;	/**< dot11WEPUndecryptableCount */
-	uint32	wepicverr_mcst;	/**< dot11WEPICVErrorCount */
-	uint32	decsuccess_mcst;	/**< DecryptSuccessCount */
-	uint32	tkipicverr_mcst;	/**< TKIPICVErrorCount */
-	uint32	wepexcluded_mcst;	/**< dot11WEPExcludedCount */
-
-	uint32	dma_hang;	/**< count for dma hang */
-	uint32	reinit;		/**< count for reinit */
-
-	uint32  pstatxucast;	/**< count of ucast frames xmitted on all psta assoc */
-	uint32  pstatxnoassoc;	/**< count of txnoassoc frames xmitted on all psta assoc */
-	uint32  pstarxucast;	/**< count of ucast frames received on all psta assoc */
-	uint32  pstarxbcmc;	/**< count of bcmc frames received on all psta */
-	uint32  pstatxbcmc;	/**< count of bcmc frames transmitted on all psta */
-
-	uint32  cso_passthrough; /* hw cso required but passthrough */
-	uint32	cso_normal;	/**< hw cso hdr for normal process */
-	uint32	chained;	/**< number of frames chained */
-	uint32	chainedsz1;	/**< number of chain size 1 frames */
-	uint32	unchained;	/**< number of frames not chained */
-	uint32	maxchainsz;	/**< max chain size so far */
-	uint32	currchainsz;	/**< current chain size */
-	uint32	rxdrop20s;	/**< drop secondary cnt */
-	uint32	pciereset;	/**< Secondary Bus Reset issued by driver */
-	uint32	cfgrestore;	/**< configspace restore by driver */
-	uint32	reinitreason[NREINITREASONCOUNT]; /* reinitreason counters; 0: Unknown reason */
-	uint32  rxrtry;		/**< num of received packets with retry bit on */
-	uint32	txmpdu;		/**< macstat cnt only valid in ver 11. number of MPDUs txed.  */
-	uint32	rxnodelim;	/**< macstat cnt only valid in ver 11.
-				 * number of occasions that no valid delimiter is detected
-				 * by ampdu parser.
-				 */
-	uint32  rxmpdu_mu;      /* Number of MU MPDUs received */
-
-	/* detailed control/management frames */
-	uint32  txbar;          /**< Number of TX BAR */
-	uint32  rxbar;          /**< Number of RX BAR */
-	uint32  txpspoll;       /**< Number of TX PS-poll */
-	uint32  rxpspoll;       /**< Number of RX PS-poll */
-	uint32  txnull;         /**< Number of TX NULL_DATA */
-	uint32  rxnull;         /**< Number of RX NULL_DATA */
-	uint32  txqosnull;      /**< Number of TX NULL_QoSDATA */
-	uint32  rxqosnull;      /**< Number of RX NULL_QoSDATA */
-	uint32  txassocreq;     /**< Number of TX ASSOC request */
-	uint32  rxassocreq;     /**< Number of RX ASSOC request */
-	uint32  txreassocreq;   /**< Number of TX REASSOC request */
-	uint32  rxreassocreq;   /**< Number of RX REASSOC request */
-	uint32  txdisassoc;     /**< Number of TX DISASSOC */
-	uint32  rxdisassoc;     /**< Number of RX DISASSOC */
-	uint32  txassocrsp;     /**< Number of TX ASSOC response */
-	uint32  rxassocrsp;     /**< Number of RX ASSOC response */
-	uint32  txreassocrsp;   /**< Number of TX REASSOC response */
-	uint32  rxreassocrsp;   /**< Number of RX REASSOC response */
-	uint32  txauth;         /**< Number of TX AUTH */
-	uint32  rxauth;         /**< Number of RX AUTH */
-	uint32  txdeauth;       /**< Number of TX DEAUTH */
-	uint32  rxdeauth;       /**< Number of RX DEAUTH */
-	uint32  txprobereq;     /**< Number of TX probe request */
-	uint32  rxprobereq;     /**< Number of RX probe request */
-	uint32  txprobersp;     /**< Number of TX probe response */
-	uint32  rxprobersp;     /**< Number of RX probe response */
-	uint32  txaction;       /**< Number of TX action frame */
-	uint32  rxaction;       /**< Number of RX action frame */
-
-} wl_cnt_ver_11_t;
-
-typedef struct {
-	uint16  version;    /* see definition of WL_CNT_T_VERSION */
-	uint16  length;     /* length of entire structure */
-
-	/* transmit stat counters */
-	uint32  txframe;    /* tx data frames */
-	uint32  txbyte;     /* tx data bytes */
-	uint32  txretrans;  /* tx mac retransmits */
-	uint32  txerror;    /* tx data errors (derived: sum of others) */
-	uint32  txctl;      /* tx management frames */
-	uint32  txprshort;  /* tx short preamble frames */
-	uint32  txserr;     /* tx status errors */
-	uint32  txnobuf;    /* tx out of buffers errors */
-	uint32  txnoassoc;  /* tx discard because we're not associated */
-	uint32  txrunt;     /* tx runt frames */
-	uint32  txchit;     /* tx header cache hit (fastpath) */
-	uint32  txcmiss;    /* tx header cache miss (slowpath) */
-
-	/* transmit chip error counters */
-	uint32  txuflo;     /* tx fifo underflows */
-	uint32  txphyerr;   /* tx phy errors (indicated in tx status) */
-	uint32  txphycrs;
-
-	/* receive stat counters */
-	uint32  rxframe;    /* rx data frames */
-	uint32  rxbyte;     /* rx data bytes */
-	uint32  rxerror;    /* rx data errors (derived: sum of others) */
-	uint32  rxctl;      /* rx management frames */
-	uint32  rxnobuf;    /* rx out of buffers errors */
-	uint32  rxnondata;  /* rx non data frames in the data channel errors */
-	uint32  rxbadds;    /* rx bad DS errors */
-	uint32  rxbadcm;    /* rx bad control or management frames */
-	uint32  rxfragerr;  /* rx fragmentation errors */
-	uint32  rxrunt;     /* rx runt frames */
-	uint32  rxgiant;    /* rx giant frames */
-	uint32  rxnoscb;    /* rx no scb error */
-	uint32  rxbadproto; /* rx invalid frames */
-	uint32  rxbadsrcmac;    /* rx frames with Invalid Src Mac */
-	uint32  rxbadda;    /* rx frames tossed for invalid da */
-	uint32  rxfilter;   /* rx frames filtered out */
-
-	/* receive chip error counters */
-	uint32  rxoflo;     /* rx fifo overflow errors */
-	uint32  rxuflo[NFIFO];  /* rx dma descriptor underflow errors */
-
-	uint32  d11cnt_txrts_off;   /* d11cnt txrts value when reset d11cnt */
-	uint32  d11cnt_rxcrc_off;   /* d11cnt rxcrc value when reset d11cnt */
-	uint32  d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */
-
-	/* misc counters */
-	uint32  dmade;      /* tx/rx dma descriptor errors */
-	uint32  dmada;      /* tx/rx dma data errors */
-	uint32  dmape;      /* tx/rx dma descriptor protocol errors */
-	uint32  reset;      /* reset count */
-	uint32  tbtt;       /* cnts the TBTT int's */
-	uint32  txdmawar;
-	uint32  pkt_callback_reg_fail;  /* callbacks register failure */
-
-	/* MAC counters: 32-bit version of d11.h's macstat_t */
-	uint32  txallfrm;   /* total number of frames sent, incl. Data, ACK, RTS, CTS,
-			     * Control Management (includes retransmissions)
-			     */
-	uint32  txrtsfrm;   /* number of RTS sent out by the MAC */
-	uint32  txctsfrm;   /* number of CTS sent out by the MAC */
-	uint32  txackfrm;   /* number of ACK frames sent out */
-	uint32  txdnlfrm;   /* Not used */
-	uint32  txbcnfrm;   /* beacons transmitted */
-	uint32  txfunfl[6]; /* per-fifo tx underflows */
-	uint32	rxtoolate;	/* receive too late */
-	uint32  txfbw;	    /* transmit at fallback bw (dynamic bw) */
-	uint32  txtplunfl;  /* Template underflows (mac was too slow to transmit ACK/CTS
-			     * or BCN)
-			     */
-	uint32  txphyerror; /* Transmit phy error, type of error is reported in tx-status for
-			     * driver enqueued frames
-			     */
-	uint32  rxfrmtoolong;   /* Received frame longer than legal limit (2346 bytes) */
-	uint32  rxfrmtooshrt;   /* Received frame did not contain enough bytes for its frame type */
-	uint32  rxinvmachdr;    /* Either the protocol version != 0 or frame type not
-				 * data/control/management
-			   */
-	uint32  rxbadfcs;   /* number of frames for which the CRC check failed in the MAC */
-	uint32  rxbadplcp;  /* parity check of the PLCP header failed */
-	uint32  rxcrsglitch;    /* PHY was able to correlate the preamble but not the header */
-	uint32  rxstrt;     /* Number of received frames with a good PLCP
-			     * (i.e. passing parity check)
-			     */
-	uint32  rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */
-	uint32  rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
-	uint32  rxcfrmucast;    /* number of received CNTRL frames with good FCS and matching RA */
-	uint32  rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */
-	uint32  rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */
-	uint32  rxackucast; /* number of ucast ACKS received (good FCS) */
-	uint32  rxdfrmocast;    /* number of received DATA frames (good FCS and not matching RA) */
-	uint32  rxmfrmocast;    /* number of received MGMT frames (good FCS and not matching RA) */
-	uint32  rxcfrmocast;    /* number of received CNTRL frame (good FCS and not matching RA) */
-	uint32  rxrtsocast; /* number of received RTS not addressed to the MAC */
-	uint32  rxctsocast; /* number of received CTS not addressed to the MAC */
-	uint32  rxdfrmmcast;    /* number of RX Data multicast frames received by the MAC */
-	uint32  rxmfrmmcast;    /* number of RX Management multicast frames received by the MAC */
-	uint32  rxcfrmmcast;    /* number of RX Control multicast frames received by the MAC
-				 * (unlikely to see these)
-				 */
-	uint32  rxbeaconmbss;   /* beacons received from member of BSS */
-	uint32  rxdfrmucastobss; /* number of unicast frames addressed to the MAC from
-				  * other BSS (WDS FRAME)
-				  */
-	uint32  rxbeaconobss;   /* beacons received from other BSS */
-	uint32  rxrsptmout; /* Number of response timeouts for transmitted frames
-			     * expecting a response
-			     */
-	uint32  bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */
-	uint32  rxf0ovfl;   /* Number of receive fifo 0 overflows */
-	uint32  rxf1ovfl;   /* Number of receive fifo 1 overflows (obsolete) */
-	uint32  rxf2ovfl;   /* Number of receive fifo 2 overflows (obsolete) */
-	uint32  txsfovfl;   /* Number of transmit status fifo overflows (obsolete) */
-	uint32  pmqovfl;    /* Number of PMQ overflows */
-	uint32  rxcgprqfrm; /* Number of received Probe requests that made it into
-			     * the PRQ fifo
-			     */
-	uint32  rxcgprsqovfl;   /* Rx Probe Request Que overflow in the AP */
-	uint32  txcgprsfail;    /* Tx Probe Response Fail. AP sent probe response but did
-				 * not get ACK
-				 */
-	uint32  txcgprssuc; /* Tx Probe Response Success (ACK was received) */
-	uint32  prs_timeout;    /* Number of probe requests that were dropped from the PRQ
-				 * fifo because a probe response could not be sent out within
-				 * the time limit defined in M_PRS_MAXTIME
-				 */
-	uint32  rxnack;
-	uint32  frmscons;
-	uint32  txnack;		/* obsolete */
-	uint32	rxback;		/* blockack rxcnt */
-	uint32	txback;		/* blockack txcnt */
-
-	/* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
-	uint32  txfrag;     /* dot11TransmittedFragmentCount */
-	uint32  txmulti;    /* dot11MulticastTransmittedFrameCount */
-	uint32  txfail;     /* dot11FailedCount */
-	uint32  txretry;    /* dot11RetryCount */
-	uint32  txretrie;   /* dot11MultipleRetryCount */
-	uint32  rxdup;      /* dot11FrameduplicateCount */
-	uint32  txrts;      /* dot11RTSSuccessCount */
-	uint32  txnocts;    /* dot11RTSFailureCount */
-	uint32  txnoack;    /* dot11ACKFailureCount */
-	uint32  rxfrag;     /* dot11ReceivedFragmentCount */
-	uint32  rxmulti;    /* dot11MulticastReceivedFrameCount */
-	uint32  rxcrc;      /* dot11FCSErrorCount */
-	uint32  txfrmsnt;   /* dot11TransmittedFrameCount (bogus MIB?) */
-	uint32  rxundec;    /* dot11WEPUndecryptableCount */
-
-	/* WPA2 counters (see rxundec for DecryptFailureCount) */
-	uint32  tkipmicfaill;   /* TKIPLocalMICFailures */
-	uint32  tkipcntrmsr;    /* TKIPCounterMeasuresInvoked */
-	uint32  tkipreplay; /* TKIPReplays */
-	uint32  ccmpfmterr; /* CCMPFormatErrors */
-	uint32  ccmpreplay; /* CCMPReplays */
-	uint32  ccmpundec;  /* CCMPDecryptErrors */
-	uint32  fourwayfail;    /* FourWayHandshakeFailures */
-	uint32  wepundec;   /* dot11WEPUndecryptableCount */
-	uint32  wepicverr;  /* dot11WEPICVErrorCount */
-	uint32  decsuccess; /* DecryptSuccessCount */
-	uint32  tkipicverr; /* TKIPICVErrorCount */
-	uint32  wepexcluded;    /* dot11WEPExcludedCount */
-
-	uint32  rxundec_mcst;   /* dot11WEPUndecryptableCount */
-
-	/* WPA2 counters (see rxundec for DecryptFailureCount) */
-	uint32  tkipmicfaill_mcst;  /* TKIPLocalMICFailures */
-	uint32  tkipcntrmsr_mcst;   /* TKIPCounterMeasuresInvoked */
-	uint32  tkipreplay_mcst;    /* TKIPReplays */
-	uint32  ccmpfmterr_mcst;    /* CCMPFormatErrors */
-	uint32  ccmpreplay_mcst;    /* CCMPReplays */
-	uint32  ccmpundec_mcst; /* CCMPDecryptErrors */
-	uint32  fourwayfail_mcst;   /* FourWayHandshakeFailures */
-	uint32  wepundec_mcst;  /* dot11WEPUndecryptableCount */
-	uint32  wepicverr_mcst; /* dot11WEPICVErrorCount */
-	uint32  decsuccess_mcst;    /* DecryptSuccessCount */
-	uint32  tkipicverr_mcst;    /* TKIPICVErrorCount */
-	uint32  wepexcluded_mcst;   /* dot11WEPExcludedCount */
-
-	uint32  txchanrej;  /* Tx frames suppressed due to channel rejection */
-	uint32  txexptime;  /* Tx frames suppressed due to timer expiration */
-	uint32  psmwds;     /* Count PSM watchdogs */
-	uint32  phywatchdog;    /* Count Phy watchdogs (triggered by ucode) */
-
-	/* MBSS counters, AP only */
-	uint32  prq_entries_handled;    /* PRQ entries read in */
-	uint32  prq_undirected_entries; /*    which were bcast bss & ssid */
-	uint32  prq_bad_entries;    /*    which could not be translated to info */
-	uint32  atim_suppress_count;    /* TX suppressions on ATIM fifo */
-	uint32  bcn_template_not_ready; /* Template marked in use on send bcn ... */
-	uint32  bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */
-	uint32  late_tbtt_dpc;  /* TBTT DPC did not happen in time */
-
-	/* per-rate receive stat counters */
-	uint32  rx1mbps;    /* packets rx at 1Mbps */
-	uint32  rx2mbps;    /* packets rx at 2Mbps */
-	uint32  rx5mbps5;   /* packets rx at 5.5Mbps */
-	uint32  rx6mbps;    /* packets rx at 6Mbps */
-	uint32  rx9mbps;    /* packets rx at 9Mbps */
-	uint32  rx11mbps;   /* packets rx at 11Mbps */
-	uint32  rx12mbps;   /* packets rx at 12Mbps */
-	uint32  rx18mbps;   /* packets rx at 18Mbps */
-	uint32  rx24mbps;   /* packets rx at 24Mbps */
-	uint32  rx36mbps;   /* packets rx at 36Mbps */
-	uint32  rx48mbps;   /* packets rx at 48Mbps */
-	uint32  rx54mbps;   /* packets rx at 54Mbps */
-	uint32  rx108mbps;  /* packets rx at 108mbps */
-	uint32  rx162mbps;  /* packets rx at 162mbps */
-	uint32  rx216mbps;  /* packets rx at 216 mbps */
-	uint32  rx270mbps;  /* packets rx at 270 mbps */
-	uint32  rx324mbps;  /* packets rx at 324 mbps */
-	uint32  rx378mbps;  /* packets rx at 378 mbps */
-	uint32  rx432mbps;  /* packets rx at 432 mbps */
-	uint32  rx486mbps;  /* packets rx at 486 mbps */
-	uint32  rx540mbps;  /* packets rx at 540 mbps */
-
-	/* pkteng rx frame stats */
-	uint32  pktengrxducast; /* unicast frames rxed by the pkteng code */
-	uint32  pktengrxdmcast; /* multicast frames rxed by the pkteng code */
-
-	uint32  rfdisable;  /* count of radio disables */
-	uint32  bphy_rxcrsglitch;   /* PHY count of bphy glitches */
-	uint32  bphy_badplcp;
-
-	uint32  txmpdu_sgi; /* count for sgi transmit */
-	uint32  rxmpdu_sgi; /* count for sgi received */
-	uint32  txmpdu_stbc;    /* count for stbc transmit */
-	uint32  rxmpdu_stbc;    /* count for stbc received */
-
-	uint32	rxdrop20s;	/* drop secondary cnt */
-} wl_cnt_ver_6_t;
-
-#define	WL_DELTA_STATS_T_VERSION	2	/* current version of wl_delta_stats_t struct */
-
-typedef struct {
-	uint16 version;     /* see definition of WL_DELTA_STATS_T_VERSION */
-	uint16 length;      /* length of entire structure */
-
-	/* transmit stat counters */
-	uint32 txframe;     /* tx data frames */
-	uint32 txbyte;      /* tx data bytes */
-	uint32 txretrans;   /* tx mac retransmits */
-	uint32 txfail;      /* tx failures */
-
-	/* receive stat counters */
-	uint32 rxframe;     /* rx data frames */
-	uint32 rxbyte;      /* rx data bytes */
-
-	/* per-rate receive stat counters */
-	uint32  rx1mbps;	/* packets rx at 1Mbps */
-	uint32  rx2mbps;	/* packets rx at 2Mbps */
-	uint32  rx5mbps5;	/* packets rx at 5.5Mbps */
-	uint32  rx6mbps;	/* packets rx at 6Mbps */
-	uint32  rx9mbps;	/* packets rx at 9Mbps */
-	uint32  rx11mbps;	/* packets rx at 11Mbps */
-	uint32  rx12mbps;	/* packets rx at 12Mbps */
-	uint32  rx18mbps;	/* packets rx at 18Mbps */
-	uint32  rx24mbps;	/* packets rx at 24Mbps */
-	uint32  rx36mbps;	/* packets rx at 36Mbps */
-	uint32  rx48mbps;	/* packets rx at 48Mbps */
-	uint32  rx54mbps;	/* packets rx at 54Mbps */
-	uint32  rx108mbps;	/* packets rx at 108mbps */
-	uint32  rx162mbps;	/* packets rx at 162mbps */
-	uint32  rx216mbps;	/* packets rx at 216 mbps */
-	uint32  rx270mbps;	/* packets rx at 270 mbps */
-	uint32  rx324mbps;	/* packets rx at 324 mbps */
-	uint32  rx378mbps;	/* packets rx at 378 mbps */
-	uint32  rx432mbps;	/* packets rx at 432 mbps */
-	uint32  rx486mbps;	/* packets rx at 486 mbps */
-	uint32  rx540mbps;	/* packets rx at 540 mbps */
-
-	/* phy stats */
-	uint32 rxbadplcp;
-	uint32 rxcrsglitch;
-	uint32 bphy_rxcrsglitch;
-	uint32 bphy_badplcp;
-
-} wl_delta_stats_t;
-
-typedef struct {
-	uint32 packets;
-	uint32 bytes;
-} wl_traffic_stats_t;
-
-typedef struct {
-	uint16	version;	/* see definition of WL_WME_CNT_VERSION */
-	uint16	length;		/* length of entire structure */
-
-	wl_traffic_stats_t tx[AC_COUNT];	/* Packets transmitted */
-	wl_traffic_stats_t tx_failed[AC_COUNT];	/* Packets dropped or failed to transmit */
-	wl_traffic_stats_t rx[AC_COUNT];	/* Packets received */
-	wl_traffic_stats_t rx_failed[AC_COUNT];	/* Packets failed to receive */
-
-	wl_traffic_stats_t forward[AC_COUNT];	/* Packets forwarded by AP */
-
-	wl_traffic_stats_t tx_expired[AC_COUNT];	/* packets dropped due to lifetime expiry */
-
-} wl_wme_cnt_t;
-
-struct wl_msglevel2 {
-	uint32 low;
-	uint32 high;
-};
-
-typedef struct wl_mkeep_alive_pkt {
-	uint16	version; /* Version for mkeep_alive */
-	uint16	length; /* length of fixed parameters in the structure */
-	uint32	period_msec;
-	uint16	len_bytes;
-	uint8	keep_alive_id; /* 0 - 3 for N = 4 */
-	uint8	data[1];
-} wl_mkeep_alive_pkt_t;
-
-#define WL_MKEEP_ALIVE_VERSION		1
-#define WL_MKEEP_ALIVE_FIXED_LEN	OFFSETOF(wl_mkeep_alive_pkt_t, data)
-#define WL_MKEEP_ALIVE_PRECISION	500
-
-/* TCP Keep-Alive conn struct */
-typedef struct wl_mtcpkeep_alive_conn_pkt {
-	struct ether_addr saddr;		/* src mac address */
-	struct ether_addr daddr;		/* dst mac address */
-	struct ipv4_addr sipaddr;		/* source IP addr */
-	struct ipv4_addr dipaddr;		/* dest IP addr */
-	uint16 sport;				/* src port */
-	uint16 dport;				/* dest port */
-	uint32 seq;				/* seq number */
-	uint32 ack;				/* ACK number */
-	uint16 tcpwin;				/* TCP window */
-} wl_mtcpkeep_alive_conn_pkt_t;
-
-/* TCP Keep-Alive interval struct */
-typedef struct wl_mtcpkeep_alive_timers_pkt {
-	uint16 interval;		/* interval timer */
-	uint16 retry_interval;		/* retry_interval timer */
-	uint16 retry_count;		/* retry_count */
-} wl_mtcpkeep_alive_timers_pkt_t;
-
-typedef struct wake_info {
-	uint32 wake_reason;
-	uint32 wake_info_len;		/* size of packet */
-	uchar  packet[1];
-} wake_info_t;
-
-typedef struct wake_pkt {
-	uint32 wake_pkt_len;		/* size of packet */
-	uchar  packet[1];
-} wake_pkt_t;
-
-
-#define WL_MTCPKEEP_ALIVE_VERSION		1
-
-#ifdef WLBA
-
-#define WLC_BA_CNT_VERSION  1   /* current version of wlc_ba_cnt_t */
-
-/* block ack related stats */
-typedef struct wlc_ba_cnt {
-	uint16  version;    /* WLC_BA_CNT_VERSION */
-	uint16  length;     /* length of entire structure */
-
-	/* transmit stat counters */
-	uint32 txpdu;       /* pdus sent */
-	uint32 txsdu;       /* sdus sent */
-	uint32 txfc;        /* tx side flow controlled packets */
-	uint32 txfci;       /* tx side flow control initiated */
-	uint32 txretrans;   /* retransmitted pdus */
-	uint32 txbatimer;   /* ba resend due to timer */
-	uint32 txdrop;      /* dropped packets */
-	uint32 txaddbareq;  /* addba req sent */
-	uint32 txaddbaresp; /* addba resp sent */
-	uint32 txdelba;     /* delba sent */
-	uint32 txba;        /* ba sent */
-	uint32 txbar;       /* bar sent */
-	uint32 txpad[4];    /* future */
-
-	/* receive side counters */
-	uint32 rxpdu;       /* pdus recd */
-	uint32 rxqed;       /* pdus buffered before sending up */
-	uint32 rxdup;       /* duplicate pdus */
-	uint32 rxnobuf;     /* pdus discarded due to no buf */
-	uint32 rxaddbareq;  /* addba req recd */
-	uint32 rxaddbaresp; /* addba resp recd */
-	uint32 rxdelba;     /* delba recd */
-	uint32 rxba;        /* ba recd */
-	uint32 rxbar;       /* bar recd */
-	uint32 rxinvba;     /* invalid ba recd */
-	uint32 rxbaholes;   /* ba recd with holes */
-	uint32 rxunexp;     /* unexpected packets */
-	uint32 rxpad[4];    /* future */
-} wlc_ba_cnt_t;
-#endif /* WLBA */
-
-/* structure for per-tid ampdu control */
-struct ampdu_tid_control {
-	uint8 tid;			/* tid */
-	uint8 enable;			/* enable/disable */
-};
-
-/* struct for ampdu tx/rx aggregation control */
-struct ampdu_aggr {
-	int8 aggr_override;	/* aggr overrided by dongle. Not to be set by host. */
-	uint16 conf_TID_bmap;	/* bitmap of TIDs to configure */
-	uint16 enab_TID_bmap;	/* enable/disable per TID */
-};
-
-/* structure for identifying ea/tid for sending addba/delba */
-struct ampdu_ea_tid {
-	struct ether_addr ea;		/* Station address */
-	uint8 tid;			/* tid */
-	uint8 initiator;	/* 0 is recipient, 1 is originator */
-};
-/* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */
-struct ampdu_retry_tid {
-	uint8 tid;	/* tid */
-	uint8 retry;	/* retry value */
-};
-
-#define BDD_FNAME_LEN       32  /* Max length of friendly name */
-typedef struct bdd_fname {
-	uint8 len;          /* length of friendly name */
-	uchar name[BDD_FNAME_LEN];  /* friendly name */
-} bdd_fname_t;
-
-/* structure for addts arguments */
-/* For ioctls that take a list of TSPEC */
-struct tslist {
-	int count;			/* number of tspecs */
-	struct tsinfo_arg tsinfo[1];	/* variable length array of tsinfo */
-};
-
-#ifdef WLTDLS
-/* structure for tdls iovars */
-typedef struct tdls_iovar {
-	struct ether_addr ea;		/* Station address */
-	uint8 mode;			/* mode: depends on iovar */
-	chanspec_t chanspec;
-	uint32 pad;			/* future */
-} tdls_iovar_t;
-
-#define TDLS_WFD_IE_SIZE		512
-/* structure for tdls wfd ie */
-typedef struct tdls_wfd_ie_iovar {
-	struct ether_addr ea;		/* Station address */
-	uint8 mode;
-	uint16 length;
-	uint8 data[TDLS_WFD_IE_SIZE];
-} tdls_wfd_ie_iovar_t;
-#endif /* WLTDLS */
-
-/* structure for addts/delts arguments */
-typedef struct tspec_arg {
-	uint16 version;			/* see definition of TSPEC_ARG_VERSION */
-	uint16 length;			/* length of entire structure */
-	uint flag;			/* bit field */
-	/* TSPEC Arguments */
-	struct tsinfo_arg tsinfo;	/* TS Info bit field */
-	uint16 nom_msdu_size;		/* (Nominal or fixed) MSDU Size (bytes) */
-	uint16 max_msdu_size;		/* Maximum MSDU Size (bytes) */
-	uint min_srv_interval;		/* Minimum Service Interval (us) */
-	uint max_srv_interval;		/* Maximum Service Interval (us) */
-	uint inactivity_interval;	/* Inactivity Interval (us) */
-	uint suspension_interval;	/* Suspension Interval (us) */
-	uint srv_start_time;		/* Service Start Time (us) */
-	uint min_data_rate;		/* Minimum Data Rate (bps) */
-	uint mean_data_rate;		/* Mean Data Rate (bps) */
-	uint peak_data_rate;		/* Peak Data Rate (bps) */
-	uint max_burst_size;		/* Maximum Burst Size (bytes) */
-	uint delay_bound;		/* Delay Bound (us) */
-	uint min_phy_rate;		/* Minimum PHY Rate (bps) */
-	uint16 surplus_bw;		/* Surplus Bandwidth Allowance (range 1.0 to 8.0) */
-	uint16 medium_time;		/* Medium Time (32 us/s periods) */
-	uint8 dialog_token;		/* dialog token */
-} tspec_arg_t;
-
-/* tspec arg for desired station */
-typedef	struct tspec_per_sta_arg {
-	struct ether_addr ea;
-	struct tspec_arg ts;
-} tspec_per_sta_arg_t;
-
-/* structure for max bandwidth for each access category */
-typedef	struct wme_max_bandwidth {
-	uint32	ac[AC_COUNT];	/* max bandwidth for each access category */
-} wme_max_bandwidth_t;
-
-#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t))
-
-/* current version of wl_tspec_arg_t struct */
-#define	TSPEC_ARG_VERSION		2	/* current version of wl_tspec_arg_t struct */
-#define TSPEC_ARG_LENGTH		55	/* argument length from tsinfo to medium_time */
-#define TSPEC_DEFAULT_DIALOG_TOKEN	42	/* default dialog token */
-#define TSPEC_DEFAULT_SBW_FACTOR	0x3000	/* default surplus bw */
-
-
-#define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE  80
-#define WLC_WOWL_MAX_KEEPALIVE	2
-
-/* Packet lifetime configuration per ac */
-typedef struct wl_lifetime {
-	uint32 ac;	        /* access class */
-	uint32 lifetime;    /* Packet lifetime value in ms */
-} wl_lifetime_t;
-
-
-/* Channel Switch Announcement param */
-typedef struct wl_chan_switch {
-	uint8 mode;		/* value 0 or 1 */
-	uint8 count;		/* count # of beacons before switching */
-	chanspec_t chspec;	/* chanspec */
-	uint8 reg;		/* regulatory class */
-	uint8 frame_type;		/* csa frame type, unicast or broadcast */
-} wl_chan_switch_t;
-
-enum {
-	PFN_LIST_ORDER,
-	PFN_RSSI
-};
-
-enum {
-	DISABLE,
-	ENABLE
-};
-
-enum {
-	OFF_ADAPT,
-	SMART_ADAPT,
-	STRICT_ADAPT,
-	SLOW_ADAPT
-};
-
-#define SORT_CRITERIA_BIT		0
-#define AUTO_NET_SWITCH_BIT		1
-#define ENABLE_BKGRD_SCAN_BIT		2
-#define IMMEDIATE_SCAN_BIT		3
-#define	AUTO_CONNECT_BIT		4
-#define	ENABLE_BD_SCAN_BIT		5
-#define ENABLE_ADAPTSCAN_BIT		6
-#define IMMEDIATE_EVENT_BIT		8
-#define SUPPRESS_SSID_BIT		9
-#define ENABLE_NET_OFFLOAD_BIT		10
-/* report found/lost events for SSID and BSSID networks seperately */
-#define REPORT_SEPERATELY_BIT		11
-
-#define SORT_CRITERIA_MASK	0x0001
-#define AUTO_NET_SWITCH_MASK	0x0002
-#define ENABLE_BKGRD_SCAN_MASK	0x0004
-#define IMMEDIATE_SCAN_MASK	0x0008
-#define AUTO_CONNECT_MASK	0x0010
-
-#define ENABLE_BD_SCAN_MASK	0x0020
-#define ENABLE_ADAPTSCAN_MASK	0x00c0
-#define IMMEDIATE_EVENT_MASK	0x0100
-#define SUPPRESS_SSID_MASK	0x0200
-#define ENABLE_NET_OFFLOAD_MASK	0x0400
-/* report found/lost events for SSID and BSSID networks seperately */
-#define REPORT_SEPERATELY_MASK	0x0800
-
-#define PFN_VERSION			2
-#define PFN_SCANRESULT_VERSION		1
-#define MAX_PFN_LIST_COUNT		16
-
-#define PFN_COMPLETE			1
-#define PFN_INCOMPLETE			0
-
-#define DEFAULT_BESTN			2
-#define DEFAULT_MSCAN			0
-#define DEFAULT_REPEAT			10
-#define DEFAULT_EXP			2
-
-#define PFN_PARTIAL_SCAN_BIT		0
-#define PFN_PARTIAL_SCAN_MASK		1
-#define PFN_SWC_RSSI_WINDOW_MAX   8
-#define PFN_SWC_MAX_NUM_APS       16
-#define PFN_HOTLIST_MAX_NUM_APS   64
-
-/* PFN network info structure */
-typedef struct wl_pfn_subnet_info {
-	struct ether_addr BSSID;
-	uint8	channel; /* channel number only */
-	uint8	SSID_len;
-	uint8	SSID[32];
-} wl_pfn_subnet_info_t;
-
-typedef struct wl_pfn_net_info {
-	wl_pfn_subnet_info_t pfnsubnet;
-	int16	RSSI; /* receive signal strength (in dBm) */
-	uint16	timestamp; /* age in seconds */
-} wl_pfn_net_info_t;
-
-typedef struct wl_pfn_lnet_info {
-	wl_pfn_subnet_info_t pfnsubnet; /* BSSID + channel + SSID len + SSID */
-	uint16	flags; /* partial scan, etc */
-	int16	RSSI; /* receive signal strength (in dBm) */
-	uint32	timestamp; /* age in miliseconds */
-	uint16	rtt0; /* estimated distance to this AP in centimeters */
-	uint16	rtt1; /* standard deviation of the distance to this AP in centimeters */
-} wl_pfn_lnet_info_t;
-
-typedef struct wl_pfn_lscanresults {
-	uint32 version;
-	uint32 status;
-	uint32 count;
-	wl_pfn_lnet_info_t netinfo[1];
-} wl_pfn_lscanresults_t;
-
-/* this is used to report on 1-* pfn scan results */
-typedef struct wl_pfn_scanresults {
-	uint32 version;
-	uint32 status;
-	uint32 count;
-	wl_pfn_net_info_t netinfo[1];
-} wl_pfn_scanresults_t;
-
-typedef struct wl_pfn_significant_net {
-	uint16 flags;
-	uint16 channel;
-	struct ether_addr BSSID;
-	int8 rssi[PFN_SWC_RSSI_WINDOW_MAX];
-} wl_pfn_significant_net_t;
-
-
-typedef struct wl_pfn_swc_results {
-	uint32 version;
-	uint32 pkt_count;
-	uint32 total_count;
-	wl_pfn_significant_net_t list[1];
-} wl_pfn_swc_results_t;
-
-/* used to report exactly one scan result */
-/* plus reports detailed scan info in bss_info */
-typedef struct wl_pfn_scanresult {
-	uint32 version;
-	uint32 status;
-	uint32 count;
-	wl_pfn_net_info_t netinfo;
-	wl_bss_info_t bss_info;
-} wl_pfn_scanresult_t;
-
-/* PFN data structure */
-typedef struct wl_pfn_param {
-	int32 version;			/* PNO parameters version */
-	int32 scan_freq;		/* Scan frequency */
-	int32 lost_network_timeout;	/* Timeout in sec. to declare
-								* discovered network as lost
-								*/
-	int16 flags;			/* Bit field to control features
-							* of PFN such as sort criteria auto
-							* enable switch and background scan
-							*/
-	int16 rssi_margin;		/* Margin to avoid jitter for choosing a
-							* PFN based on RSSI sort criteria
-							*/
-	uint8 bestn; /* number of best networks in each scan */
-	uint8 mscan; /* number of scans recorded */
-	uint8 repeat; /* Minimum number of scan intervals
-				     *before scan frequency changes in adaptive scan
-				     */
-	uint8 exp; /* Exponent of 2 for maximum scan interval */
-	int32 slow_freq; /* slow scan period */
-} wl_pfn_param_t;
-
-typedef struct wl_pfn_bssid {
-	struct ether_addr  macaddr;
-	/* Bit4: suppress_lost, Bit3: suppress_found */
-	uint16             flags;
-} wl_pfn_bssid_t;
-
-typedef struct wl_pfn_significant_bssid {
-	struct ether_addr	macaddr;
-	int8    rssi_low_threshold;
-	int8    rssi_high_threshold;
-} wl_pfn_significant_bssid_t;
-#define WL_PFN_SUPPRESSFOUND_MASK	0x08
-#define WL_PFN_SUPPRESSLOST_MASK	0x10
-#define WL_PFN_RSSI_MASK		0xff00
-#define WL_PFN_RSSI_SHIFT		8
-
-typedef struct wl_pfn_cfg {
-	uint32	reporttype;
-	int32	channel_num;
-	uint16	channel_list[WL_NUMCHANNELS];
-	uint32	flags;
-} wl_pfn_cfg_t;
-
-#define CH_BUCKET_REPORT_REGULAR                0
-#define CH_BUCKET_REPORT_FULL_RESULT            2
-#define CH_BUCKET_GSCAN                         4
-
-
-typedef struct wl_pfn_gscan_channel_bucket {
-	uint16 bucket_end_index;
-	uint8 bucket_freq_multiple;
-	uint8 report_flag;
-} wl_pfn_gscan_channel_bucket_t;
-
-#define GSCAN_SEND_ALL_RESULTS_MASK    (1 << 0)
-#define GSCAN_CFG_FLAGS_ONLY_MASK      (1 << 7)
-
-typedef struct wl_pfn_gscan_cfg {
-	/* BIT0 1 = send probes/beacons to HOST
-	* BIT2 Reserved
-	 * Add any future flags here
-	 * BIT7 1 = no other useful cfg sent
-	 */
-	uint8 flags;
-	/* Buffer filled threshold in % to generate an event */
-	uint8   buffer_threshold;
-	/* No. of BSSIDs with "change" to generate an evt
-	 * change - crosses rssi threshold/lost
-	 */
-	uint8   swc_nbssid_threshold;
-	/* Max=8 (for now) Size of rssi cache buffer */
-	uint8  swc_rssi_window_size;
-	uint16  count_of_channel_buckets;
-	uint16  lost_ap_window;
-	wl_pfn_gscan_channel_bucket_t channel_bucket[1];
-} wl_pfn_gscan_cfg_t;
-
-
-#define WL_PFN_REPORT_ALLNET    0
-#define WL_PFN_REPORT_SSIDNET   1
-#define WL_PFN_REPORT_BSSIDNET  2
-#define WL_PFN_CFG_FLAGS_PROHIBITED	0x00000001	/* Accept and use prohibited channels */
-#define WL_PFN_CFG_FLAGS_RESERVED	0xfffffffe	/* Remaining reserved for future use */
-
-typedef struct wl_pfn {
-	wlc_ssid_t		ssid;			/* ssid name and its length */
-	int32			flags;			/* bit2: hidden */
-	int32			infra;			/* BSS Vs IBSS */
-	int32			auth;			/* Open Vs Closed */
-	int32			wpa_auth;		/* WPA type */
-	int32			wsec;			/* wsec value */
-} wl_pfn_t;
-
-typedef struct wl_pfn_list {
-	uint32		version;
-	uint32		enabled;
-	uint32		count;
-	wl_pfn_t	pfn[1];
-} wl_pfn_list_t;
-
-#define WL_PFN_MAC_OUI_ONLY_MASK      1
-#define WL_PFN_SET_MAC_UNASSOC_MASK   2
-/* To configure pfn_macaddr */
-typedef struct wl_pfn_macaddr_cfg {
-	uint8 version;
-	uint8 flags;
-	struct ether_addr macaddr;
-} wl_pfn_macaddr_cfg_t;
-#define WL_PFN_MACADDR_CFG_VER 1
-typedef BWL_PRE_PACKED_STRUCT struct pfn_olmsg_params_t {
-	wlc_ssid_t ssid;
-	uint32	cipher_type;
-	uint32	auth_type;
-	uint8	channels[4];
-} BWL_POST_PACKED_STRUCT pfn_olmsg_params;
-
-#define WL_PFN_HIDDEN_BIT		2
-#define WL_PFN_HIDDEN_MASK		0x4
-
-#ifndef BESTN_MAX
-#define BESTN_MAX			3
-#endif
-
-#ifndef MSCAN_MAX
-#define MSCAN_MAX			90
-#endif
-
-/*
- * WLFCTS definition
- */
-typedef struct wl_txstatus_additional_info {
-	uint32 rspec;
-	uint32 enq_ts;
-	uint32 last_ts;
-	uint32 entry_ts;
-	uint16 seq;
-	uint8  rts_cnt;
-	uint8  tx_cnt;
-} wl_txstatus_additional_info_t;
-
-/* Service discovery */
-typedef struct {
-	uint8	transaction_id;	/* Transaction id */
-	uint8	protocol;	/* Service protocol type */
-	uint16	query_len;	/* Length of query */
-	uint16	response_len;	/* Length of response */
-	uint8	qrbuf[1];
-} wl_p2po_qr_t;
-
-typedef struct {
-	uint16			period;			/* extended listen period */
-	uint16			interval;		/* extended listen interval */
-	uint16			count;			/* count to repeat */
-	uint16                  pad;                    /* pad for 32bit align */
-} wl_p2po_listen_t;
-
-/* GAS state machine tunable parameters.  Structure field values of 0 means use the default. */
-typedef struct wl_gas_config {
-	uint16 max_retransmit;		/* Max # of firmware/driver retransmits on no Ack
-					 * from peer (on top of the ucode retries).
-					 */
-	uint16 response_timeout;	/* Max time to wait for a GAS-level response
-					 * after sending a packet.
-					 */
-	uint16 max_comeback_delay;	/* Max GAS response comeback delay.
-					 * Exceeding this fails the GAS exchange.
-					 */
-	uint16 max_retries;		/* Max # of GAS state machine retries on failure
-					 * of a GAS frame exchange.
-					 */
-} wl_gas_config_t;
-
-/* P2P Find Offload parameters */
-typedef BWL_PRE_PACKED_STRUCT struct wl_p2po_find_config {
-	uint16 version;			/* Version of this struct */
-	uint16 length;			/* sizeof(wl_p2po_find_config_t) */
-	int32 search_home_time;		/* P2P search state home time when concurrent
-					 * connection exists.  -1 for default.
-					 */
-	uint8 num_social_channels;
-			/* Number of social channels up to WL_P2P_SOCIAL_CHANNELS_MAX.
-			 * 0 means use default social channels.
-			 */
-	uint8 flags;
-	uint16 social_channels[1];	/* Variable length array of social channels */
-} BWL_POST_PACKED_STRUCT wl_p2po_find_config_t;
-#define WL_P2PO_FIND_CONFIG_VERSION 2	/* value for version field */
-
-/* wl_p2po_find_config_t flags */
-#define P2PO_FIND_FLAG_SCAN_ALL_APS 0x01	/* Whether to scan for all APs in the p2po_find
-						 * periodic scans of all channels.
-						 * 0 means scan for only P2P devices.
-						 * 1 means scan for P2P devices plus non-P2P APs.
-						 */
-
-
-/* For adding a WFDS service to seek */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 seek_hdl;		/* unique id chosen by host */
-	uint8 addr[6];			/* Seek service from a specific device with this
-					 * MAC address, all 1's for any device.
-					 */
-	uint8 service_hash[P2P_WFDS_HASH_LEN];
-	uint8 service_name_len;
-	uint8 service_name[MAX_WFDS_SEEK_SVC_NAME_LEN];
-					/* Service name to seek, not null terminated */
-	uint8 service_info_req_len;
-	uint8 service_info_req[1];	/* Service info request, not null terminated.
-					 * Variable length specified by service_info_req_len.
-					 * Maximum length is MAX_WFDS_SEEK_SVC_INFO_LEN.
-					 */
-} BWL_POST_PACKED_STRUCT wl_p2po_wfds_seek_add_t;
-
-/* For deleting a WFDS service to seek */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 seek_hdl;		/* delete service specified by id */
-} BWL_POST_PACKED_STRUCT wl_p2po_wfds_seek_del_t;
-
-
-/* For adding a WFDS service to advertise */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 advertise_hdl;		/* unique id chosen by host */
-	uint8 service_hash[P2P_WFDS_HASH_LEN];
-	uint32 advertisement_id;
-	uint16 service_config_method;
-	uint8 service_name_len;
-	uint8 service_name[MAX_WFDS_SVC_NAME_LEN];
-					/* Service name , not null terminated */
-	uint8 service_status;
-	uint16 service_info_len;
-	uint8 service_info[1];		/* Service info, not null terminated.
-					 * Variable length specified by service_info_len.
-					 * Maximum length is MAX_WFDS_ADV_SVC_INFO_LEN.
-					 */
-} BWL_POST_PACKED_STRUCT wl_p2po_wfds_advertise_add_t;
-
-/* For deleting a WFDS service to advertise */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 advertise_hdl;	/* delete service specified by hdl */
-} BWL_POST_PACKED_STRUCT wl_p2po_wfds_advertise_del_t;
-
-/* P2P Offload discovery mode for the p2po_state iovar */
-typedef enum {
-	WL_P2PO_DISC_STOP,
-	WL_P2PO_DISC_LISTEN,
-	WL_P2PO_DISC_DISCOVERY
-} disc_mode_t;
-
-/* ANQP offload */
-
-#define ANQPO_MAX_QUERY_SIZE		256
-typedef struct {
-	uint16 max_retransmit;		/* ~0 use default, max retransmit on no ACK from peer */
-	uint16 response_timeout;	/* ~0 use default, msec to wait for resp after tx packet */
-	uint16 max_comeback_delay;	/* ~0 use default, max comeback delay in resp else fail */
-	uint16 max_retries;			/* ~0 use default, max retries on failure */
-	uint16 query_len;			/* length of ANQP query */
-	uint8 query_data[1];		/* ANQP encoded query (max ANQPO_MAX_QUERY_SIZE) */
-} wl_anqpo_set_t;
-
-typedef struct {
-	uint16 channel;				/* channel of the peer */
-	struct ether_addr addr;		/* addr of the peer */
-} wl_anqpo_peer_t;
-
-#define ANQPO_MAX_PEER_LIST			64
-typedef struct {
-	uint16 count;				/* number of peers in list */
-	wl_anqpo_peer_t peer[1];	/* max ANQPO_MAX_PEER_LIST */
-} wl_anqpo_peer_list_t;
-
-#define ANQPO_MAX_IGNORE_SSID		64
-typedef struct {
-	bool is_clear;				/* set to clear list (not used on GET) */
-	uint16 count;				/* number of SSID in list */
-	wlc_ssid_t ssid[1];			/* max ANQPO_MAX_IGNORE_SSID */
-} wl_anqpo_ignore_ssid_list_t;
-
-#define ANQPO_MAX_IGNORE_BSSID		64
-typedef struct {
-	bool is_clear;				/* set to clear list (not used on GET) */
-	uint16 count;				/* number of addr in list */
-	struct ether_addr bssid[1];	/* max ANQPO_MAX_IGNORE_BSSID */
-} wl_anqpo_ignore_bssid_list_t;
-
-
-struct toe_ol_stats_t {
-	/* Num of tx packets that don't need to be checksummed */
-	uint32 tx_summed;
-
-	/* Num of tx packets where checksum is filled by offload engine */
-	uint32 tx_iph_fill;
-	uint32 tx_tcp_fill;
-	uint32 tx_udp_fill;
-	uint32 tx_icmp_fill;
-
-	/*  Num of rx packets where toe finds out if checksum is good or bad */
-	uint32 rx_iph_good;
-	uint32 rx_iph_bad;
-	uint32 rx_tcp_good;
-	uint32 rx_tcp_bad;
-	uint32 rx_udp_good;
-	uint32 rx_udp_bad;
-	uint32 rx_icmp_good;
-	uint32 rx_icmp_bad;
-
-	/* Num of tx packets in which csum error is injected */
-	uint32 tx_tcp_errinj;
-	uint32 tx_udp_errinj;
-	uint32 tx_icmp_errinj;
-
-	/* Num of rx packets in which csum error is injected */
-	uint32 rx_tcp_errinj;
-	uint32 rx_udp_errinj;
-	uint32 rx_icmp_errinj;
-};
-
-/* Arp offload statistic counts */
-struct arp_ol_stats_t {
-	uint32  host_ip_entries;	/* Host IP table addresses (more than one if multihomed) */
-	uint32  host_ip_overflow;	/* Host IP table additions skipped due to overflow */
-
-	uint32  arp_table_entries;	/* ARP table entries */
-	uint32  arp_table_overflow;	/* ARP table additions skipped due to overflow */
-
-	uint32  host_request;		/* ARP requests from host */
-	uint32  host_reply;		/* ARP replies from host */
-	uint32  host_service;		/* ARP requests from host serviced by ARP Agent */
-
-	uint32  peer_request;		/* ARP requests received from network */
-	uint32  peer_request_drop;	/* ARP requests from network that were dropped */
-	uint32  peer_reply;		/* ARP replies received from network */
-	uint32  peer_reply_drop;	/* ARP replies from network that were dropped */
-	uint32  peer_service;		/* ARP request from host serviced by ARP Agent */
-};
-
-/* NS offload statistic counts */
-struct nd_ol_stats_t {
-	uint32  host_ip_entries;    /* Host IP table addresses (more than one if multihomed) */
-	uint32  host_ip_overflow;   /* Host IP table additions skipped due to overflow */
-	uint32  peer_request;       /* NS requests received from network */
-	uint32  peer_request_drop;  /* NS requests from network that were dropped */
-	uint32  peer_reply_drop;    /* NA replies from network that were dropped */
-	uint32  peer_service;       /* NS request from host serviced by firmware */
-};
-
-/*
- * Keep-alive packet offloading.
- */
-
-/* NAT keep-alive packets format: specifies the re-transmission period, the packet
- * length, and packet contents.
- */
-typedef struct wl_keep_alive_pkt {
-	uint32	period_msec;	/* Retransmission period (0 to disable packet re-transmits) */
-	uint16	len_bytes;	/* Size of packet to transmit (0 to disable packet re-transmits) */
-	uint8	data[1];	/* Variable length packet to transmit.  Contents should include
-				 * entire ethernet packet (enet header, IP header, UDP header,
-				 * and UDP payload) in network byte order.
-				 */
-} wl_keep_alive_pkt_t;
-
-#define WL_KEEP_ALIVE_FIXED_LEN		OFFSETOF(wl_keep_alive_pkt_t, data)
-
-
-/*
- * Dongle pattern matching filter.
- */
-
-#define MAX_WAKE_PACKET_CACHE_BYTES 128 /* Maximum cached wake packet */
-
-#define MAX_WAKE_PACKET_BYTES	    (DOT11_A3_HDR_LEN +			    \
-				     DOT11_QOS_LEN +			    \
-				     sizeof(struct dot11_llc_snap_header) + \
-				     ETHER_MAX_DATA)
-
-typedef struct pm_wake_packet {
-	uint32	status;		/* Is the wake reason a packet (if all the other field's valid) */
-	uint32	pattern_id;	/* Pattern ID that matched */
-	uint32	original_packet_size;
-	uint32	saved_packet_size;
-	uchar	packet[MAX_WAKE_PACKET_CACHE_BYTES];
-} pm_wake_packet_t;
-
-/* Packet filter types. Currently, only pattern matching is supported. */
-typedef enum wl_pkt_filter_type {
-	WL_PKT_FILTER_TYPE_PATTERN_MATCH=0,	/* Pattern matching filter */
-	WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH=1, /* Magic packet match */
-	WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH=2, /* A pattern list (match all to match filter) */
-	WL_PKT_FILTER_TYPE_ENCRYPTED_PATTERN_MATCH=3, /* SECURE WOWL magic / net pattern match */
-} wl_pkt_filter_type_t;
-
-#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t
-
-/* String mapping for types that may be used by applications or debug */
-#define WL_PKT_FILTER_TYPE_NAMES \
-	{ "PATTERN", WL_PKT_FILTER_TYPE_PATTERN_MATCH },       \
-	{ "MAGIC",   WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH }, \
-	{ "PATLIST", WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH }
-
-/* Secured WOWL packet was encrypted, need decrypted before check filter match */
-typedef struct wl_pkt_decrypter {
-	uint8* (*dec_cb)(void* dec_ctx, const void *sdu, int sending);
-	void*  dec_ctx;
-} wl_pkt_decrypter_t;
-
-/* Pattern matching filter. Specifies an offset within received packets to
- * start matching, the pattern to match, the size of the pattern, and a bitmask
- * that indicates which bits within the pattern should be matched.
- */
-typedef struct wl_pkt_filter_pattern {
-	uint32	offset;		/* Offset within received packet to start pattern matching.
-				 * Offset '0' is the first byte of the ethernet header.
-				 */
-	uint32	size_bytes;	/* Size of the pattern.  Bitmask must be the same size. */
-	uint8   mask_and_pattern[1]; /* Variable length mask and pattern data.  mask starts
-				      * at offset 0.  Pattern immediately follows mask. for
-				      * secured pattern, put the descrypter pointer to the
-				      * beginning, mask and pattern postponed correspondingly
-				      */
-} wl_pkt_filter_pattern_t;
-
-/* A pattern list is a numerically specified list of modified pattern structures. */
-typedef struct wl_pkt_filter_pattern_listel {
-	uint16 rel_offs;	/* Offset to begin match (relative to 'base' below) */
-	uint16 base_offs;	/* Base for offset (defined below) */
-	uint16 size_bytes;	/* Size of mask/pattern */
-	uint16 match_flags;	/* Addition flags controlling the match */
-	uint8  mask_and_data[1]; /* Variable length mask followed by data, each size_bytes */
-} wl_pkt_filter_pattern_listel_t;
-
-typedef struct wl_pkt_filter_pattern_list {
-	uint8 list_cnt;		/* Number of elements in the list */
-	uint8 PAD1[1];		/* Reserved (possible version: reserved) */
-	uint16 totsize;		/* Total size of this pattern list (includes this struct) */
-	wl_pkt_filter_pattern_listel_t patterns[1]; /* Variable number of list elements */
-} wl_pkt_filter_pattern_list_t;
-
-/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
-typedef struct wl_pkt_filter {
-	uint32	id;		/* Unique filter id, specified by app. */
-	uint32	type;		/* Filter type (WL_PKT_FILTER_TYPE_xxx). */
-	uint32	negate_match;	/* Negate the result of filter matches */
-	union {			/* Filter definitions */
-		wl_pkt_filter_pattern_t pattern;	/* Pattern matching filter */
-		wl_pkt_filter_pattern_list_t patlist; /* List of patterns to match */
-	} u;
-} wl_pkt_filter_t;
-
-/* IOVAR "tcp_keep_set" parameter. Used to install tcp keep_alive stuff. */
-typedef struct wl_tcp_keep_set {
-	uint32	val1;
-	uint32	val2;
-} wl_tcp_keep_set_t;
-
-#define WL_PKT_FILTER_FIXED_LEN		  OFFSETOF(wl_pkt_filter_t, u)
-#define WL_PKT_FILTER_PATTERN_FIXED_LEN	  OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern)
-#define WL_PKT_FILTER_PATTERN_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_list_t, patterns)
-#define WL_PKT_FILTER_PATTERN_LISTEL_FIXED_LEN	\
-			OFFSETOF(wl_pkt_filter_pattern_listel_t, mask_and_data)
-
-/* IOVAR "pkt_filter_enable" parameter. */
-typedef struct wl_pkt_filter_enable {
-	uint32	id;		/* Unique filter id */
-	uint32	enable;		/* Enable/disable bool */
-} wl_pkt_filter_enable_t;
-
-/* IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */
-typedef struct wl_pkt_filter_list {
-	uint32	num;		/* Number of installed packet filters */
-	wl_pkt_filter_t	filter[1];	/* Variable array of packet filters. */
-} wl_pkt_filter_list_t;
-
-#define WL_PKT_FILTER_LIST_FIXED_LEN	  OFFSETOF(wl_pkt_filter_list_t, filter)
-
-/* IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */
-typedef struct wl_pkt_filter_stats {
-	uint32	num_pkts_matched;	/* # filter matches for specified filter id */
-	uint32	num_pkts_forwarded;	/* # packets fwded from dongle to host for all filters */
-	uint32	num_pkts_discarded;	/* # packets discarded by dongle for all filters */
-} wl_pkt_filter_stats_t;
-
-/* IOVAR "pkt_filter_ports" parameter.  Configure TCP/UDP port filters. */
-typedef struct wl_pkt_filter_ports {
-	uint8 version;		/* Be proper */
-	uint8 reserved;		/* Be really proper */
-	uint16 count;		/* Number of ports following */
-	/* End of fixed data */
-	uint16 ports[1];	/* Placeholder for ports[<count>] */
-} wl_pkt_filter_ports_t;
-
-#define WL_PKT_FILTER_PORTS_FIXED_LEN	OFFSETOF(wl_pkt_filter_ports_t, ports)
-
-#define WL_PKT_FILTER_PORTS_VERSION	0
-#define WL_PKT_FILTER_PORTS_MAX		128
-
-#define RSN_REPLAY_LEN 8
-typedef struct _gtkrefresh {
-	uchar	KCK[RSN_KCK_LENGTH];
-	uchar	KEK[RSN_KEK_LENGTH];
-	uchar	ReplayCounter[RSN_REPLAY_LEN];
-} gtk_keyinfo_t, *pgtk_keyinfo_t;
-
-/* Sequential Commands ioctl */
-typedef struct wl_seq_cmd_ioctl {
-	uint32 cmd;		/* common ioctl definition */
-	uint32 len;		/* length of user buffer */
-} wl_seq_cmd_ioctl_t;
-
-#define WL_SEQ_CMD_ALIGN_BYTES	4
-
-/* These are the set of get IOCTLs that should be allowed when using
- * IOCTL sequence commands. These are issued implicitly by wl.exe each time
- * it is invoked. We never want to buffer these, or else wl.exe will stop working.
- */
-#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \
-	(((cmd) == WLC_GET_MAGIC)		|| \
-	 ((cmd) == WLC_GET_VERSION)		|| \
-	 ((cmd) == WLC_GET_AP)			|| \
-	 ((cmd) == WLC_GET_INSTANCE))
-
-typedef struct wl_pkteng {
-	uint32 flags;
-	uint32 delay;			/* Inter-packet delay */
-	uint32 nframes;			/* Number of frames */
-	uint32 length;			/* Packet length */
-	uint8  seqno;			/* Enable/disable sequence no. */
-	struct ether_addr dest;		/* Destination address */
-	struct ether_addr src;		/* Source address */
-} wl_pkteng_t;
-
-typedef struct wl_pkteng_stats {
-	uint32 lostfrmcnt;		/* RX PER test: no of frames lost (skip seqno) */
-	int32 rssi;			/* RSSI */
-	int32 snr;			/* signal to noise ratio */
-	uint16 rxpktcnt[NUM_80211_RATES+1];
-	uint8 rssi_qdb;			/* qdB portion of the computed rssi */
-} wl_pkteng_stats_t;
-
-typedef struct wl_txcal_params {
-	wl_pkteng_t pkteng;
-	uint8 gidx_start;
-	int8 gidx_step;
-	uint8 gidx_stop;
-} wl_txcal_params_t;
-
-
-typedef enum {
-	wowl_pattern_type_bitmap = 0,
-	wowl_pattern_type_arp,
-	wowl_pattern_type_na
-} wowl_pattern_type_t;
-
-typedef struct wl_wowl_pattern {
-	uint32		    masksize;		/* Size of the mask in #of bytes */
-	uint32		    offset;		/* Pattern byte offset in packet */
-	uint32		    patternoffset;	/* Offset of start of pattern in the structure */
-	uint32		    patternsize;	/* Size of the pattern itself in #of bytes */
-	uint32		    id;			/* id */
-	uint32		    reasonsize;		/* Size of the wakeup reason code */
-	wowl_pattern_type_t type;		/* Type of pattern */
-	/* Mask follows the structure above */
-	/* Pattern follows the mask is at 'patternoffset' from the start */
-} wl_wowl_pattern_t;
-
-typedef struct wl_wowl_pattern_list {
-	uint			count;
-	wl_wowl_pattern_t	pattern[1];
-} wl_wowl_pattern_list_t;
-
-typedef struct wl_wowl_wakeind {
-	uint8	pci_wakeind;	/* Whether PCI PMECSR PMEStatus bit was set */
-	uint32	ucode_wakeind;	/* What wakeup-event indication was set by ucode */
-} wl_wowl_wakeind_t;
-
-typedef struct {
-	uint32		pktlen;		    /* size of packet */
-	void		*sdu;
-} tcp_keepalive_wake_pkt_infop_t;
-
-/* per AC rate control related data structure */
-typedef struct wl_txrate_class {
-	uint8		init_rate;
-	uint8		min_rate;
-	uint8		max_rate;
-} wl_txrate_class_t;
-
-/* structure for Overlap BSS scan arguments */
-typedef struct wl_obss_scan_arg {
-	int16	passive_dwell;
-	int16	active_dwell;
-	int16	bss_widthscan_interval;
-	int16	passive_total;
-	int16	active_total;
-	int16	chanwidth_transition_delay;
-	int16	activity_threshold;
-} wl_obss_scan_arg_t;
-
-#define WL_OBSS_SCAN_PARAM_LEN	sizeof(wl_obss_scan_arg_t)
-
-/* RSSI event notification configuration. */
-typedef struct wl_rssi_event {
-	uint32 rate_limit_msec;		/* # of events posted to application will be limited to
-					 * one per specified period (0 to disable rate limit).
-					 */
-	uint8 num_rssi_levels;		/* Number of entries in rssi_levels[] below */
-	int8 rssi_levels[MAX_RSSI_LEVELS];	/* Variable number of RSSI levels. An event
-						 * will be posted each time the RSSI of received
-						 * beacons/packets crosses a level.
-						 */
-} wl_rssi_event_t;
-
-/* CCA based channel quality event configuration */
-#define WL_CHAN_QUAL_CCA	0
-#define WL_CHAN_QUAL_NF		1
-#define WL_CHAN_QUAL_NF_LTE	2
-#define WL_CHAN_QUAL_TOTAL	3
-
-#define MAX_CHAN_QUAL_LEVELS	8
-
-typedef struct wl_chan_qual_metric {
-	uint8 id;				/* metric ID */
-	uint8 num_levels;               	/* Number of entries in rssi_levels[] below */
-	uint16 flags;
-	int16 htol[MAX_CHAN_QUAL_LEVELS];	/* threshold level array: hi-to-lo */
-	int16 ltoh[MAX_CHAN_QUAL_LEVELS];	/* threshold level array: lo-to-hi */
-} wl_chan_qual_metric_t;
-
-typedef struct wl_chan_qual_event {
-	uint32 rate_limit_msec;		/* # of events posted to application will be limited to
-					 * one per specified period (0 to disable rate limit).
-					 */
-	uint16 flags;
-	uint16 num_metrics;
-	wl_chan_qual_metric_t metric[WL_CHAN_QUAL_TOTAL];	/* metric array */
-} wl_chan_qual_event_t;
-
-typedef struct wl_action_obss_coex_req {
-	uint8 info;
-	uint8 num;
-	uint8 ch_list[1];
-} wl_action_obss_coex_req_t;
-
-
-/* IOVar parameter block for small MAC address array with type indicator */
-#define WL_IOV_MAC_PARAM_LEN  4
-
-#define WL_IOV_PKTQ_LOG_PRECS 16
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 num_addrs;
-	char   addr_type[WL_IOV_MAC_PARAM_LEN];
-	struct ether_addr ea[WL_IOV_MAC_PARAM_LEN];
-} BWL_POST_PACKED_STRUCT wl_iov_mac_params_t;
-
-/* This is extra info that follows wl_iov_mac_params_t */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 addr_info[WL_IOV_MAC_PARAM_LEN];
-} BWL_POST_PACKED_STRUCT wl_iov_mac_extra_params_t;
-
-/* Combined structure */
-typedef struct {
-	wl_iov_mac_params_t params;
-	wl_iov_mac_extra_params_t extra_params;
-} wl_iov_mac_full_params_t;
-
-/* Parameter block for PKTQ_LOG statistics */
-#define PKTQ_LOG_COUNTERS_V4 \
-	/* packets requested to be stored */ \
-	uint32 requested; \
-	/* packets stored */ \
-	uint32 stored; \
-	/* packets saved, because a lowest priority queue has given away one packet */ \
-	uint32 saved; \
-	/* packets saved, because an older packet from the same queue has been dropped */ \
-	uint32 selfsaved; \
-	/* packets dropped, because pktq is full with higher precedence packets */ \
-	uint32 full_dropped; \
-	 /* packets dropped because pktq per that precedence is full */ \
-	uint32 dropped; \
-	/* packets dropped, in order to save one from a queue of a highest priority */ \
-	uint32 sacrificed; \
-	/* packets droped because of hardware/transmission error */ \
-	uint32 busy; \
-	/* packets re-sent because they were not received */ \
-	uint32 retry; \
-	/* packets retried again (ps pretend) prior to moving power save mode */ \
-	uint32 ps_retry; \
-	 /* suppressed packet count */ \
-	uint32 suppress; \
-	/* packets finally dropped after retry limit */ \
-	uint32 retry_drop; \
-	/* the high-water mark of the queue capacity for packets - goes to zero as queue fills */ \
-	uint32 max_avail; \
-	/* the high-water mark of the queue utilisation for packets - ('inverse' of max_avail) */ \
-	uint32 max_used; \
-	 /* the maximum capacity of the queue */ \
-	uint32 queue_capacity; \
-	/* count of rts attempts that failed to receive cts */ \
-	uint32 rtsfail; \
-	/* count of packets sent (acked) successfully */ \
-	uint32 acked; \
-	/* running total of phy rate of packets sent successfully */ \
-	uint32 txrate_succ; \
-	/* running total of phy 'main' rate */ \
-	uint32 txrate_main; \
-	/* actual data transferred successfully */ \
-	uint32 throughput; \
-	/* time difference since last pktq_stats */ \
-	uint32 time_delta;
-
-typedef struct {
-	PKTQ_LOG_COUNTERS_V4
-} pktq_log_counters_v04_t;
-
-/* v5 is the same as V4 with extra parameter */
-typedef struct {
-	PKTQ_LOG_COUNTERS_V4
-	/* cumulative time to transmit */
-	uint32 airtime;
-} pktq_log_counters_v05_t;
-
-typedef struct {
-	uint8                num_prec[WL_IOV_MAC_PARAM_LEN];
-	pktq_log_counters_v04_t  counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS];
-	uint32               counter_info[WL_IOV_MAC_PARAM_LEN];
-	uint32               pspretend_time_delta[WL_IOV_MAC_PARAM_LEN];
-	char                 headings[1];
-} pktq_log_format_v04_t;
-
-typedef struct {
-	uint8                num_prec[WL_IOV_MAC_PARAM_LEN];
-	pktq_log_counters_v05_t  counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS];
-	uint32               counter_info[WL_IOV_MAC_PARAM_LEN];
-	uint32               pspretend_time_delta[WL_IOV_MAC_PARAM_LEN];
-	char                 headings[1];
-} pktq_log_format_v05_t;
-
-
-typedef struct {
-	uint32               version;
-	wl_iov_mac_params_t  params;
-	union {
-		pktq_log_format_v04_t v04;
-		pktq_log_format_v05_t v05;
-	} pktq_log;
-} wl_iov_pktq_log_t;
-
-/* PKTQ_LOG_AUTO, PKTQ_LOG_DEF_PREC flags introduced in v05, they are ignored by v04 */
-#define PKTQ_LOG_AUTO     (1 << 31)
-#define PKTQ_LOG_DEF_PREC (1 << 30)
-
-
-#define LEGACY1_WL_PFN_MACADDR_CFG_VER 0
-
-#define WL_PFN_MAC_OUI_ONLY_MASK      1
-#define WL_PFN_SET_MAC_UNASSOC_MASK   2
-#define WL_PFN_RESTRICT_LA_MAC_MASK   4
-#define WL_PFN_MACADDR_FLAG_MASK     0x7
-
-
-/*
- * SCB_BS_DATA iovar definitions start.
- */
-#define SCB_BS_DATA_STRUCT_VERSION	1
-
-/* The actual counters maintained for each station */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	/* The following counters are a subset of what pktq_stats provides per precedence. */
-	uint32 retry;          /* packets re-sent because they were not received */
-	uint32 retry_drop;     /* packets finally dropped after retry limit */
-	uint32 rtsfail;        /* count of rts attempts that failed to receive cts */
-	uint32 acked;          /* count of packets sent (acked) successfully */
-	uint32 txrate_succ;    /* running total of phy rate of packets sent successfully */
-	uint32 txrate_main;    /* running total of phy 'main' rate */
-	uint32 throughput;     /* actual data transferred successfully */
-	uint32 time_delta;     /* time difference since last pktq_stats */
-	uint32 airtime;        /* cumulative total medium access delay in useconds */
-} BWL_POST_PACKED_STRUCT iov_bs_data_counters_t;
-
-/* The structure for individual station information. */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	struct ether_addr	station_address;	/* The station MAC address */
-	uint16			station_flags;		/* Bit mask of flags, for future use. */
-	iov_bs_data_counters_t	station_counters;	/* The actual counter values */
-} BWL_POST_PACKED_STRUCT iov_bs_data_record_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint16	structure_version;	/* Structure version number (for wl/wlu matching) */
-	uint16	structure_count;	/* Number of iov_bs_data_record_t records following */
-	iov_bs_data_record_t	structure_record[1];	/* 0 - structure_count records */
-} BWL_POST_PACKED_STRUCT iov_bs_data_struct_t;
-
-/* Bitmask of options that can be passed in to the iovar. */
-enum {
-	SCB_BS_DATA_FLAG_NO_RESET = (1<<0)	/* Do not clear the counters after reading */
-};
-/*
- * SCB_BS_DATA iovar definitions end.
- */
-
-typedef struct wlc_extlog_cfg {
-	int max_number;
-	uint16 module;	/* bitmap */
-	uint8 level;
-	uint8 flag;
-	uint16 version;
-} wlc_extlog_cfg_t;
-
-typedef struct log_record {
-	uint32 time;
-	uint16 module;
-	uint16 id;
-	uint8 level;
-	uint8 sub_unit;
-	uint8 seq_num;
-	int32 arg;
-	char str[MAX_ARGSTR_LEN];
-} log_record_t;
-
-typedef struct wlc_extlog_req {
-	uint32 from_last;
-	uint32 num;
-} wlc_extlog_req_t;
-
-typedef struct wlc_extlog_results {
-	uint16 version;
-	uint16 record_len;
-	uint32 num;
-	log_record_t logs[1];
-} wlc_extlog_results_t;
-
-typedef struct log_idstr {
-	uint16	id;
-	uint16	flag;
-	uint8	arg_type;
-	const char	*fmt_str;
-} log_idstr_t;
-
-#define FMTSTRF_USER		1
-
-/* flat ID definitions
- * New definitions HAVE TO BE ADDED at the end of the table. Otherwise, it will
- * affect backward compatibility with pre-existing apps
- */
-typedef enum {
-	FMTSTR_DRIVER_UP_ID = 0,
-	FMTSTR_DRIVER_DOWN_ID = 1,
-	FMTSTR_SUSPEND_MAC_FAIL_ID = 2,
-	FMTSTR_NO_PROGRESS_ID = 3,
-	FMTSTR_RFDISABLE_ID = 4,
-	FMTSTR_REG_PRINT_ID = 5,
-	FMTSTR_EXPTIME_ID = 6,
-	FMTSTR_JOIN_START_ID = 7,
-	FMTSTR_JOIN_COMPLETE_ID = 8,
-	FMTSTR_NO_NETWORKS_ID = 9,
-	FMTSTR_SECURITY_MISMATCH_ID = 10,
-	FMTSTR_RATE_MISMATCH_ID = 11,
-	FMTSTR_AP_PRUNED_ID = 12,
-	FMTSTR_KEY_INSERTED_ID = 13,
-	FMTSTR_DEAUTH_ID = 14,
-	FMTSTR_DISASSOC_ID = 15,
-	FMTSTR_LINK_UP_ID = 16,
-	FMTSTR_LINK_DOWN_ID = 17,
-	FMTSTR_RADIO_HW_OFF_ID = 18,
-	FMTSTR_RADIO_HW_ON_ID = 19,
-	FMTSTR_EVENT_DESC_ID = 20,
-	FMTSTR_PNP_SET_POWER_ID = 21,
-	FMTSTR_RADIO_SW_OFF_ID = 22,
-	FMTSTR_RADIO_SW_ON_ID = 23,
-	FMTSTR_PWD_MISMATCH_ID = 24,
-	FMTSTR_FATAL_ERROR_ID = 25,
-	FMTSTR_AUTH_FAIL_ID = 26,
-	FMTSTR_ASSOC_FAIL_ID = 27,
-	FMTSTR_IBSS_FAIL_ID = 28,
-	FMTSTR_EXTAP_FAIL_ID = 29,
-	FMTSTR_MAX_ID
-} log_fmtstr_id_t;
-
-#ifdef DONGLEOVERLAYS
-typedef struct {
-	uint32 flags_idx;	/* lower 8 bits: overlay index; upper 24 bits: flags */
-	uint32 offset;		/* offset into overlay region to write code */
-	uint32 len;			/* overlay code len */
-	/* overlay code follows this struct */
-} wl_ioctl_overlay_t;
-#endif /* DONGLEOVERLAYS */
-
-/* 11k Neighbor Report element (unversioned, deprecated) */
-typedef struct nbr_element {
-	uint8 id;
-	uint8 len;
-	struct ether_addr bssid;
-	uint32 bssid_info;
-	uint8 reg;
-	uint8 channel;
-	uint8 phytype;
-	uint8 pad;
-} nbr_element_t;
-
-#define WL_RRM_NBR_RPT_VER		1
-/* 11k Neighbor Report element */
-typedef struct nbr_rpt_elem {
-	uint8 version;
-	uint8 id;
-	uint8 len;
-	uint8 pad;
-	struct ether_addr bssid;
-	uint8 pad_1[2];
-	uint32 bssid_info;
-	uint8 reg;
-	uint8 channel;
-	uint8 phytype;
-	uint8 pad_2;
-	wlc_ssid_t ssid;
-	uint8 bss_trans_preference;
-	uint8 pad_3[3];
-} nbr_rpt_elem_t;
-
-typedef enum event_msgs_ext_command {
-	EVENTMSGS_NONE		=	0,
-	EVENTMSGS_SET_BIT	=	1,
-	EVENTMSGS_RESET_BIT	=	2,
-	EVENTMSGS_SET_MASK	=	3
-} event_msgs_ext_command_t;
-
-#define EVENTMSGS_VER 1
-#define EVENTMSGS_EXT_STRUCT_SIZE	OFFSETOF(eventmsgs_ext_t, mask[0])
-
-/* len-	for SET it would be mask size from the application to the firmware */
-/*		for GET it would be actual firmware mask size */
-/* maxgetsize -	is only used for GET. indicate max mask size that the */
-/*				application can read from the firmware */
-typedef struct eventmsgs_ext
-{
-	uint8	ver;
-	uint8	command;
-	uint8	len;
-	uint8	maxgetsize;
-	uint8	mask[1];
-} eventmsgs_ext_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct pcie_bus_tput_params {
-	/* no of host dma descriptors programmed by the firmware before a commit */
-	uint16		max_dma_descriptors;
-
-	uint16		host_buf_len; /* length of host buffer */
-	dmaaddr_t	host_buf_addr; /* physical address for bus_throughput_buf */
-} BWL_POST_PACKED_STRUCT pcie_bus_tput_params_t;
-typedef BWL_PRE_PACKED_STRUCT struct pcie_bus_tput_stats {
-	uint16		time_taken; /* no of secs the test is run */
-	uint16		nbytes_per_descriptor; /* no of bytes of data dma ed per descriptor */
-
-	/* no of desciptors fo which dma is sucessfully completed within the test time */
-	uint32		count;
-} BWL_POST_PACKED_STRUCT pcie_bus_tput_stats_t;
-
-#define MAX_ROAMOFFL_BSSID_NUM	100
-
-typedef BWL_PRE_PACKED_STRUCT struct roamoffl_bssid_list {
-	int32 cnt;
-	struct ether_addr bssid[1];
-} BWL_POST_PACKED_STRUCT roamoffl_bssid_list_t;
-
-/* no default structure packing */
-#include <packed_section_end.h>
-
-typedef struct keepalives_max_idle {
-	uint16  keepalive_count;        /* nmbr of keepalives per bss_max_idle period */
-	uint8   mkeepalive_index;       /* mkeepalive_index for keepalive frame to be used */
-	uint8   PAD;			/* to align next field */
-	uint16  max_interval;           /* seconds */
-} keepalives_max_idle_t;
-
-#define PM_IGNORE_BCMC_PROXY_ARP (1 << 0)
-#define PM_IGNORE_BCMC_ALL_DMS_ACCEPTED (1 << 1)
-
-/* require strict packing */
-#include <packed_section_start.h>
-
-/* ##### Power Stats section ##### */
-
-#define WL_PWRSTATS_VERSION	2
-
-/* Input structure for pwrstats IOVAR */
-typedef BWL_PRE_PACKED_STRUCT struct wl_pwrstats_query {
-	uint16 length;		/* Number of entries in type array. */
-	uint16 type[1];		/* Types (tags) to retrieve.
-				 * Length 0 (no types) means get all.
-				 */
-} BWL_POST_PACKED_STRUCT wl_pwrstats_query_t;
-
-/* This structure is for version 2; version 1 will be deprecated in by FW */
-typedef BWL_PRE_PACKED_STRUCT struct wl_pwrstats {
-	uint16 version;		      /* Version = 2 is TLV format */
-	uint16 length;		      /* Length of entire structure */
-	uint8 data[1];		      /* TLV data, a series of structures,
-				       * each starting with type and length.
-				       *
-				       * Padded as necessary so each section
-				       * starts on a 4-byte boundary.
-				       *
-				       * Both type and len are uint16, but the
-				       * upper nibble of length is reserved so
-				       * valid len values are 0-4095.
-				       */
-} BWL_POST_PACKED_STRUCT wl_pwrstats_t;
-#define WL_PWR_STATS_HDRLEN	OFFSETOF(wl_pwrstats_t, data)
-
-/* Type values for the data section */
-#define WL_PWRSTATS_TYPE_PHY		0 /* struct wl_pwr_phy_stats */
-#define WL_PWRSTATS_TYPE_SCAN		1 /* struct wl_pwr_scan_stats */
-#define WL_PWRSTATS_TYPE_USB_HSIC	2 /* struct wl_pwr_usb_hsic_stats */
-#define WL_PWRSTATS_TYPE_PM_AWAKE1	3 /* struct wl_pwr_pm_awake_stats_v1 */
-#define WL_PWRSTATS_TYPE_CONNECTION	4 /* struct wl_pwr_connect_stats; assoc and key-exch time */
-#define WL_PWRSTATS_TYPE_PCIE		6 /* struct wl_pwr_pcie_stats */
-#define WL_PWRSTATS_TYPE_PM_AWAKE2	7 /* struct wl_pwr_pm_awake_stats_v2 */
-
-/* Bits for wake reasons */
-#define WLC_PMD_WAKE_SET		0x1
-#define WLC_PMD_PM_AWAKE_BCN		0x2
-#define WLC_PMD_BTA_ACTIVE		0x4
-#define WLC_PMD_SCAN_IN_PROGRESS	0x8
-#define WLC_PMD_RM_IN_PROGRESS		0x10
-#define WLC_PMD_AS_IN_PROGRESS		0x20
-#define WLC_PMD_PM_PEND			0x40
-#define WLC_PMD_PS_POLL			0x80
-#define WLC_PMD_CHK_UNALIGN_TBTT	0x100
-#define WLC_PMD_APSD_STA_UP		0x200
-#define WLC_PMD_TX_PEND_WAR		0x400
-#define WLC_PMD_GPTIMER_STAY_AWAKE	0x800
-#define WLC_PMD_PM2_RADIO_SOFF_PEND	0x2000
-#define WLC_PMD_NON_PRIM_STA_UP		0x4000
-#define WLC_PMD_AP_UP			0x8000
-
-typedef BWL_PRE_PACKED_STRUCT struct wlc_pm_debug {
-	uint32 timestamp;	     /* timestamp in millisecond */
-	uint32 reason;		     /* reason(s) for staying awake */
-} BWL_POST_PACKED_STRUCT wlc_pm_debug_t;
-
-/* WL_PWRSTATS_TYPE_PM_AWAKE1 structures (for 6.25 firmware) */
-#define WLC_STA_AWAKE_STATES_MAX_V1	30
-#define WLC_PMD_EVENT_MAX_V1		32
-/* Data sent as part of pwrstats IOVAR (and EXCESS_PM_WAKE event) */
-typedef BWL_PRE_PACKED_STRUCT struct pm_awake_data_v1 {
-	uint32 curr_time;	/* ms */
-	uint32 hw_macc;		/* HW maccontrol */
-	uint32 sw_macc;		/* SW maccontrol */
-	uint32 pm_dur;		/* Total sleep time in PM, msecs */
-	uint32 mpc_dur;		/* Total sleep time in MPC, msecs */
-
-	/* int32 drifts = remote - local; +ve drift => local-clk slow */
-	int32 last_drift;	/* Most recent TSF drift from beacon */
-	int32 min_drift;	/* Min TSF drift from beacon in magnitude */
-	int32 max_drift;	/* Max TSF drift from beacon in magnitude */
-
-	uint32 avg_drift;	/* Avg TSF drift from beacon */
-
-	/* Wake history tracking */
-	uint8  pmwake_idx;				   /* for stepping through pm_state */
-	wlc_pm_debug_t pm_state[WLC_STA_AWAKE_STATES_MAX_V1]; /* timestamped wake bits */
-	uint32 pmd_event_wake_dur[WLC_PMD_EVENT_MAX_V1];      /* cumulative usecs per wake reason */
-	uint32 drift_cnt;	/* Count of drift readings over which avg_drift was computed */
-} BWL_POST_PACKED_STRUCT pm_awake_data_v1_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_pm_awake_stats_v1 {
-	uint16 type;	     /* WL_PWRSTATS_TYPE_PM_AWAKE */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-
-	pm_awake_data_v1_t awake_data;
-	uint32 frts_time;	/* Cumulative ms spent in frts since driver load */
-	uint32 frts_end_cnt;	/* No of times frts ended since driver load */
-} BWL_POST_PACKED_STRUCT wl_pwr_pm_awake_stats_v1_t;
-
-/* WL_PWRSTATS_TYPE_PM_AWAKE2 structures */
-/* Data sent as part of pwrstats IOVAR */
-typedef BWL_PRE_PACKED_STRUCT struct pm_awake_data_v2 {
-	uint32 curr_time;	/* ms */
-	uint32 hw_macc;		/* HW maccontrol */
-	uint32 sw_macc;		/* SW maccontrol */
-	uint32 pm_dur;		/* Total sleep time in PM, msecs */
-	uint32 mpc_dur;		/* Total sleep time in MPC, msecs */
-
-	/* int32 drifts = remote - local; +ve drift => local-clk slow */
-	int32 last_drift;	/* Most recent TSF drift from beacon */
-	int32 min_drift;	/* Min TSF drift from beacon in magnitude */
-	int32 max_drift;	/* Max TSF drift from beacon in magnitude */
-
-	uint32 avg_drift;	/* Avg TSF drift from beacon */
-
-	/* Wake history tracking */
-
-	/* pmstate array (type wlc_pm_debug_t) start offset */
-	uint16 pm_state_offset;
-	/* pmstate number of array entries */
-	uint16 pm_state_len;
-
-	/* array (type uint32) start offset */
-	uint16 pmd_event_wake_dur_offset;
-	/* pmd_event_wake_dur number of array entries */
-	uint16 pmd_event_wake_dur_len;
-
-	uint32 drift_cnt;	/* Count of drift readings over which avg_drift was computed */
-	uint8  pmwake_idx;	/* for stepping through pm_state */
-	uint8  pad[3];
-	uint32 frts_time;	/* Cumulative ms spent in frts since driver load */
-	uint32 frts_end_cnt;	/* No of times frts ended since driver load */
-} BWL_POST_PACKED_STRUCT pm_awake_data_v2_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_pm_awake_stats_v2 {
-	uint16 type;	     /* WL_PWRSTATS_TYPE_PM_AWAKE */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-
-	pm_awake_data_v2_t awake_data;
-} BWL_POST_PACKED_STRUCT wl_pwr_pm_awake_stats_v2_t;
-
-/* Original bus structure is for HSIC */
-typedef BWL_PRE_PACKED_STRUCT struct bus_metrics {
-	uint32 suspend_ct;	/* suspend count */
-	uint32 resume_ct;	/* resume count */
-	uint32 disconnect_ct;	/* disconnect count */
-	uint32 reconnect_ct;	/* reconnect count */
-	uint32 active_dur;	/* msecs in bus, usecs for user */
-	uint32 suspend_dur;	/* msecs in bus, usecs for user */
-	uint32 disconnect_dur;	/* msecs in bus, usecs for user */
-} BWL_POST_PACKED_STRUCT bus_metrics_t;
-
-/* Bus interface info for USB/HSIC */
-typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_usb_hsic_stats {
-	uint16 type;	     /* WL_PWRSTATS_TYPE_USB_HSIC */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-
-	bus_metrics_t hsic;	/* stats from hsic bus driver */
-} BWL_POST_PACKED_STRUCT wl_pwr_usb_hsic_stats_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct pcie_bus_metrics {
-	uint32 d3_suspend_ct;	/* suspend count */
-	uint32 d0_resume_ct;	/* resume count */
-	uint32 perst_assrt_ct;	/* PERST# assert count */
-	uint32 perst_deassrt_ct;	/* PERST# de-assert count */
-	uint32 active_dur;	/* msecs */
-	uint32 d3_suspend_dur;	/* msecs */
-	uint32 perst_dur;	/* msecs */
-	uint32 l0_cnt;		/* L0 entry count */
-	uint32 l0_usecs;	/* L0 duration in usecs */
-	uint32 l1_cnt;		/* L1 entry count */
-	uint32 l1_usecs;	/* L1 duration in usecs */
-	uint32 l1_1_cnt;	/* L1_1ss entry count */
-	uint32 l1_1_usecs;	/* L1_1ss duration in usecs */
-	uint32 l1_2_cnt;	/* L1_2ss entry count */
-	uint32 l1_2_usecs;	/* L1_2ss duration in usecs */
-	uint32 l2_cnt;		/* L2 entry count */
-	uint32 l2_usecs;	/* L2 duration in usecs */
-	uint32 timestamp;	/* Timestamp on when stats are collected */
-	uint32 num_h2d_doorbell;	/* # of doorbell interrupts - h2d */
-	uint32 num_d2h_doorbell;	/* # of doorbell interrupts - d2h */
-	uint32 num_submissions; /* # of submissions */
-	uint32 num_completions; /* # of completions */
-	uint32 num_rxcmplt;	/* # of rx completions */
-	uint32 num_rxcmplt_drbl;	/* of drbl interrupts for rx complt. */
-	uint32 num_txstatus;	/* # of tx completions */
-	uint32 num_txstatus_drbl;	/* of drbl interrupts for tx complt. */
-	uint32 ltr_active_ct;	/* # of times chip went to LTR ACTIVE */
-	uint32 ltr_active_dur;	/* # of msecs chip was in LTR ACTIVE */
-	uint32 ltr_sleep_ct;	/* # of times chip went to LTR SLEEP */
-	uint32 ltr_sleep_dur;	/* # of msecs chip was in LTR SLEEP */
-	uint32 deepsleep_count; /* # of times chip went to deepsleep */
-	uint32 deepsleep_dur;   /* # of msecs chip was in deepsleep */
-} BWL_POST_PACKED_STRUCT pcie_bus_metrics_t;
-
-/* Bus interface info for PCIE */
-typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_pcie_stats {
-	uint16 type;	     /* WL_PWRSTATS_TYPE_PCIE */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-	pcie_bus_metrics_t pcie;	/* stats from pcie bus driver */
-} BWL_POST_PACKED_STRUCT wl_pwr_pcie_stats_t;
-
-/* Scan information history per category */
-typedef BWL_PRE_PACKED_STRUCT struct scan_data {
-	uint32 count;		/* Number of scans performed */
-	uint32 dur;		/* Total time (in us) used */
-} BWL_POST_PACKED_STRUCT scan_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_scan_stats {
-	uint16 type;	     /* WL_PWRSTATS_TYPE_SCAN */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-
-	/* Scan history */
-	scan_data_t user_scans;	  /* User-requested scans: (i/e/p)scan */
-	scan_data_t assoc_scans;  /* Scans initiated by association requests */
-	scan_data_t roam_scans;	  /* Scans initiated by the roam engine */
-	scan_data_t pno_scans[8]; /* For future PNO bucketing (BSSID, SSID, etc) */
-	scan_data_t other_scans;  /* Scan engine usage not assigned to the above */
-} BWL_POST_PACKED_STRUCT wl_pwr_scan_stats_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_connect_stats {
-	uint16 type;	     /* WL_PWRSTATS_TYPE_SCAN */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-
-	/* Connection (Association + Key exchange) data */
-	uint32 count;	/* Number of connections performed */
-	uint32 dur;		/* Total time (in ms) used */
-} BWL_POST_PACKED_STRUCT wl_pwr_connect_stats_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_phy_stats {
-	uint16 type;	    /* WL_PWRSTATS_TYPE_PHY */
-	uint16 len;	    /* Up to 4K-1, top 4 bits are reserved */
-	uint32 tx_dur;	    /* TX Active duration in us */
-	uint32 rx_dur;	    /* RX Active duration in us */
-} BWL_POST_PACKED_STRUCT wl_pwr_phy_stats_t;
-
-
-/* ##### End of Power Stats section ##### */
-
-/* IPV4 Arp offloads for ndis context */
-BWL_PRE_PACKED_STRUCT struct hostip_id {
-	struct ipv4_addr ipa;
-	uint8 id;
-} BWL_POST_PACKED_STRUCT;
-
-/* Return values */
-#define ND_REPLY_PEER		0x1	/* Reply was sent to service NS request from peer */
-#define ND_REQ_SINK			0x2	/* Input packet should be discarded */
-#define ND_FORCE_FORWARD	0X3	/* For the dongle to forward req to HOST */
-
-/* Neighbor Solicitation Response Offload IOVAR param */
-typedef BWL_PRE_PACKED_STRUCT struct nd_param {
-	struct ipv6_addr	host_ip[2];
-	struct ipv6_addr	solicit_ip;
-	struct ipv6_addr	remote_ip;
-	uint8	host_mac[ETHER_ADDR_LEN];
-	uint32	offload_id;
-} BWL_POST_PACKED_STRUCT nd_param_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pfn_roam_thresh {
-	uint32 pfn_alert_thresh; /* time in ms */
-	uint32 roam_alert_thresh; /* time in ms */
-} BWL_POST_PACKED_STRUCT wl_pfn_roam_thresh_t;
-
-
-/* Reasons for wl_pmalert_t */
-#define PM_DUR_EXCEEDED			(1<<0)
-#define MPC_DUR_EXCEEDED		(1<<1)
-#define ROAM_ALERT_THRESH_EXCEEDED	(1<<2)
-#define PFN_ALERT_THRESH_EXCEEDED	(1<<3)
-#define CONST_AWAKE_DUR_ALERT		(1<<4)
-#define CONST_AWAKE_DUR_RECOVERY	(1<<5)
-
-#define MIN_PM_ALERT_LEN 9
-
-/* Data sent in EXCESS_PM_WAKE event */
-#define WL_PM_ALERT_VERSION 3
-
-#define MAX_P2P_BSS_DTIM_PRD 4
-
-/* This structure is for version 3; version 2 will be deprecated in by FW */
-typedef BWL_PRE_PACKED_STRUCT struct wl_pmalert {
-	uint16 version;		/* Version = 3 is TLV format */
-	uint16 length;		/* Length of entire structure */
-	uint32 reasons;		/* reason(s) for pm_alert */
-	uint8 data[1];		/* TLV data, a series of structures,
-				 * each starting with type and length.
-				 *
-				 * Padded as necessary so each section
-				 * starts on a 4-byte boundary.
-				 *
-				 * Both type and len are uint16, but the
-				 * upper nibble of length is reserved so
-				 * valid len values are 0-4095.
-				*/
-} BWL_POST_PACKED_STRUCT wl_pmalert_t;
-
-/* Type values for the data section */
-#define WL_PMALERT_FIXED	0 /* struct wl_pmalert_fixed_t, fixed fields */
-#define WL_PMALERT_PMSTATE	1 /* struct wl_pmalert_pmstate_t, variable */
-#define WL_PMALERT_EVENT_DUR	2 /* struct wl_pmalert_event_dur_t, variable */
-#define WL_PMALERT_UCODE_DBG	3 /* struct wl_pmalert_ucode_dbg_t, variable */
-#define WL_PMALERT_PS_ALLOWED_HIST	4 /* struct wl_pmalert_ps_allowed_history, variable */
-#define WL_PMALERT_EXT_UCODE_DBG	5 /* struct wl_pmalert_ext_ucode_dbg_t, variable */
-#define WL_PMALERT_EPM_START_EVENT_DUR	6 /* struct wl_pmalert_event_dur_t, variable */
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pmalert_fixed {
-	uint16 type;	     /* WL_PMALERT_FIXED */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-	uint32 prev_stats_time;	/* msecs */
-	uint32 curr_time;	/* ms */
-	uint32 prev_pm_dur;	/* msecs */
-	uint32 pm_dur;		/* Total sleep time in PM, msecs */
-	uint32 prev_mpc_dur;	/* msecs */
-	uint32 mpc_dur;		/* Total sleep time in MPC, msecs */
-	uint32 hw_macc;		/* HW maccontrol */
-	uint32 sw_macc;		/* SW maccontrol */
-
-	/* int32 drifts = remote - local; +ve drift -> local-clk slow */
-	int32 last_drift;	/* Most recent TSF drift from beacon */
-	int32 min_drift;	/* Min TSF drift from beacon in magnitude */
-	int32 max_drift;	/* Max TSF drift from beacon in magnitude */
-
-	uint32 avg_drift;	/* Avg TSF drift from beacon */
-	uint32 drift_cnt;	/* Count of drift readings over which avg_drift was computed */
-	uint32 frts_time;	/* Cumulative ms spent in data frts since driver load */
-	uint32 frts_end_cnt;	/* No of times frts ended since driver load */
-	uint32 prev_frts_dur;	/* Data frts duration at start of pm-period */
-	uint32 cal_dur;		/* Cumulative ms spent in calibration */
-	uint32 prev_cal_dur;	/* cal duration at start of pm-period */
-} BWL_POST_PACKED_STRUCT wl_pmalert_fixed_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pmalert_pmstate {
-	uint16 type;	     /* WL_PMALERT_PMSTATE */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-
-	uint8 pmwake_idx;   /* for stepping through pm_state */
-	uint8 pad[3];
-	/* Array of pmstate; len of array is based on tlv len */
-	wlc_pm_debug_t pmstate[1];
-} BWL_POST_PACKED_STRUCT wl_pmalert_pmstate_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pmalert_event_dur {
-	uint16 type;	     /* WL_PMALERT_EVENT_DUR */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-
-	/* Array of event_dur, len of array is based on tlv len */
-	uint32 event_dur[1];
-} BWL_POST_PACKED_STRUCT wl_pmalert_event_dur_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_pmalert_ucode_dbg {
-	uint16 type;	     /* WL_PMALERT_UCODE_DBG */
-	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
-	uint32 macctrl;
-	uint16 m_p2p_hps;
-	uint32 psm_brc;
-	uint32 ifsstat;
-	uint16 m_p2p_bss_dtim_prd[MAX_P2P_BSS_DTIM_PRD];
-	uint32 psmdebug[20];
-	uint32 phydebug[20];
-} BWL_POST_PACKED_STRUCT wl_pmalert_ucode_dbg_t;
-
-
-/* Structures and constants used for "vndr_ie" IOVar interface */
-#define VNDR_IE_CMD_LEN		4	/* length of the set command string:
-					 * "add", "del" (+ NUL)
-					 */
-
-#define VNDR_IE_INFO_HDR_LEN	(sizeof(uint32))
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 pktflag;			/* bitmask indicating which packet(s) contain this IE */
-	vndr_ie_t vndr_ie_data;		/* vendor IE data */
-} BWL_POST_PACKED_STRUCT vndr_ie_info_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	int iecount;			/* number of entries in the vndr_ie_list[] array */
-	vndr_ie_info_t vndr_ie_list[1];	/* variable size list of vndr_ie_info_t structs */
-} BWL_POST_PACKED_STRUCT vndr_ie_buf_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	char cmd[VNDR_IE_CMD_LEN];	/* vndr_ie IOVar set command : "add", "del" + NUL */
-	vndr_ie_buf_t vndr_ie_buffer;	/* buffer containing Vendor IE list information */
-} BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t;
-
-/* tag_ID/length/value_buffer tuple */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint8	id;
-	uint8	len;
-	uint8	data[1];
-} BWL_POST_PACKED_STRUCT tlv_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 pktflag;			/* bitmask indicating which packet(s) contain this IE */
-	tlv_t ie_data;		/* IE data */
-} BWL_POST_PACKED_STRUCT ie_info_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	int iecount;			/* number of entries in the ie_list[] array */
-	ie_info_t ie_list[1];	/* variable size list of ie_info_t structs */
-} BWL_POST_PACKED_STRUCT ie_buf_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	char cmd[VNDR_IE_CMD_LEN];	/* ie IOVar set command : "add" + NUL */
-	ie_buf_t ie_buffer;	/* buffer containing IE list information */
-} BWL_POST_PACKED_STRUCT ie_setbuf_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 pktflag;		/* bitmask indicating which packet(s) contain this IE */
-	uint8 id;		/* IE type */
-} BWL_POST_PACKED_STRUCT ie_getbuf_t;
-
-/* structures used to define format of wps ie data from probe requests */
-/* passed up to applications via iovar "prbreq_wpsie" */
-typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr {
-	struct ether_addr staAddr;
-	uint16 ieLen;
-} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data {
-	sta_prbreq_wps_ie_hdr_t hdr;
-	uint8 ieData[1];
-} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list {
-	uint32 totLen;
-	uint8 ieDataList[1];
-} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t;
-
-
-#ifdef WLMEDIA_TXFAILEVENT
-typedef BWL_PRE_PACKED_STRUCT struct {
-	char   dest[ETHER_ADDR_LEN]; /* destination MAC */
-	uint8  prio;            /* Packet Priority */
-	uint8  flags;           /* Flags           */
-	uint32 tsf_l;           /* TSF timer low   */
-	uint32 tsf_h;           /* TSF timer high  */
-	uint16 rates;           /* Main Rates      */
-	uint16 txstatus;        /* TX Status       */
-} BWL_POST_PACKED_STRUCT txfailinfo_t;
-#endif /* WLMEDIA_TXFAILEVENT */
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 flags;
-	chanspec_t chanspec;			/* txpwr report for this channel */
-	chanspec_t local_chanspec;		/* channel on which we are associated */
-	uint8 local_max;			/* local max according to the AP */
-	uint8 local_constraint;			/* local constraint according to the AP */
-	int8  antgain[2];			/* Ant gain for each band - from SROM */
-	uint8 rf_cores;				/* count of RF Cores being reported */
-	uint8 est_Pout[4];			/* Latest tx power out estimate per RF chain */
-	uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */
-	uint8 est_Pout_cck;			/* Latest CCK tx power out estimate */
-	uint8 tx_power_max[4];		/* Maximum target power among all rates */
-	uint tx_power_max_rate_ind[4];		/* Index of the rate with the max target power */
-	int8 sar;					/* SAR limit for display by wl executable */
-	int8 channel_bandwidth;		/* 20, 40 or 80 MHz bandwidth? */
-	uint8 version;				/* Version of the data format wlu <--> driver */
-	uint8 display_core;			/* Displayed curpower core */
-	int8 target_offsets[4];		/* Target power offsets for current rate per core */
-	uint32 last_tx_ratespec;	/* Ratespec for last transmition */
-	uint   user_target;		/* user limit */
-	uint32 ppr_len;		/* length of each ppr serialization buffer */
-	int8 SARLIMIT[MAX_STREAMS_SUPPORTED];
-	uint8  pprdata[1];		/* ppr serialization buffer */
-} BWL_POST_PACKED_STRUCT tx_pwr_rpt_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	struct ipv4_addr	ipv4_addr;
-	struct ether_addr nexthop;
-} BWL_POST_PACKED_STRUCT ibss_route_entry_t;
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint32 num_entry;
-	ibss_route_entry_t route_entry[1];
-} BWL_POST_PACKED_STRUCT ibss_route_tbl_t;
-
-#define MAX_IBSS_ROUTE_TBL_ENTRY	64
-
-#define TXPWR_TARGET_VERSION  0
-typedef BWL_PRE_PACKED_STRUCT struct {
-	int32 version;		/* version number */
-	chanspec_t chanspec;	/* txpwr report for this channel */
-	int8 txpwr[WL_STA_ANT_MAX]; /* Max tx target power, in qdb */
-	uint8 rf_cores;		/* count of RF Cores being reported */
-} BWL_POST_PACKED_STRUCT txpwr_target_max_t;
-
-#define BSS_PEER_INFO_PARAM_CUR_VER	0
-/* Input structure for IOV_BSS_PEER_INFO */
-typedef BWL_PRE_PACKED_STRUCT	struct {
-	uint16			version;
-	struct	ether_addr ea;	/* peer MAC address */
-} BWL_POST_PACKED_STRUCT bss_peer_info_param_t;
-
-#define BSS_PEER_INFO_CUR_VER		0
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint16			version;
-	struct ether_addr	ea;
-	int32			rssi;
-	uint32			tx_rate;	/* current tx rate */
-	uint32			rx_rate;	/* current rx rate */
-	wl_rateset_t		rateset;	/* rateset in use */
-	uint32			age;		/* age in seconds */
-} BWL_POST_PACKED_STRUCT bss_peer_info_t;
-
-#define BSS_PEER_LIST_INFO_CUR_VER	0
-
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint16			version;
-	uint16			bss_peer_info_len;	/* length of bss_peer_info_t */
-	uint32			count;			/* number of peer info */
-	bss_peer_info_t		peer_info[1];		/* peer info */
-} BWL_POST_PACKED_STRUCT bss_peer_list_info_t;
-
-#define BSS_PEER_LIST_INFO_FIXED_LEN OFFSETOF(bss_peer_list_info_t, peer_info)
-
-#define AIBSS_BCN_FORCE_CONFIG_VER_0	0
-
-/* structure used to configure AIBSS beacon force xmit */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint16  version;
-	uint16	len;
-	uint32 initial_min_bcn_dur;	/* dur in ms to check a bcn in bcn_flood period */
-	uint32 min_bcn_dur;	/* dur in ms to check a bcn after bcn_flood period */
-	uint32 bcn_flood_dur; /* Initial bcn xmit period in ms */
-} BWL_POST_PACKED_STRUCT aibss_bcn_force_config_t;
-
-#define AIBSS_TXFAIL_CONFIG_VER_0    0
-#define AIBSS_TXFAIL_CONFIG_VER_1    1
-#define AIBSS_TXFAIL_CONFIG_CUR_VER		AIBSS_TXFAIL_CONFIG_VER_1
-
-/* structure used to configure aibss tx fail event */
-typedef BWL_PRE_PACKED_STRUCT struct {
-	uint16  version;
-	uint16  len;
-	uint32 bcn_timeout;     /* dur in seconds to receive 1 bcn */
-	uint32 max_tx_retry;     /* no of consecutive no acks to send txfail event */
-	uint32 max_atim_failure; /* no of consecutive atim failure */
-} BWL_POST_PACKED_STRUCT aibss_txfail_config_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_aibss_if {
-	uint16 version;
-	uint16 len;
-	uint32 flags;
-	struct ether_addr addr;
-	chanspec_t chspec;
-} BWL_POST_PACKED_STRUCT wl_aibss_if_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wlc_ipfo_route_entry {
-	struct ipv4_addr ip_addr;
-	struct ether_addr nexthop;
-} BWL_POST_PACKED_STRUCT wlc_ipfo_route_entry_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wlc_ipfo_route_tbl {
-	uint32 num_entry;
-	wlc_ipfo_route_entry_t route_entry[1];
-} BWL_POST_PACKED_STRUCT wlc_ipfo_route_tbl_t;
-
-#define WL_IPFO_ROUTE_TBL_FIXED_LEN 4
-#define WL_MAX_IPFO_ROUTE_TBL_ENTRY	64
-
-/* no strict structure packing */
-#include <packed_section_end.h>
-
-	/* Global ASSERT Logging */
-#define ASSERTLOG_CUR_VER	0x0100
-#define MAX_ASSRTSTR_LEN	64
-
-	typedef struct assert_record {
-		uint32 time;
-		uint8 seq_num;
-		char str[MAX_ASSRTSTR_LEN];
-	} assert_record_t;
-
-	typedef struct assertlog_results {
-		uint16 version;
-		uint16 record_len;
-		uint32 num;
-		assert_record_t logs[1];
-	} assertlog_results_t;
-
-#define LOGRRC_FIX_LEN	8
-#define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type))
-
-
-	/* chanim acs record */
-	typedef struct {
-		bool valid;
-		uint8 trigger;
-		chanspec_t selected_chspc;
-		int8 bgnoise;
-		uint32 glitch_cnt;
-		uint8 ccastats;
-		uint8 chan_idle;
-		uint timestamp;
-	} chanim_acs_record_t;
-
-	typedef struct {
-		chanim_acs_record_t acs_record[CHANIM_ACS_RECORD];
-		uint8 count;
-		uint timestamp;
-	} wl_acs_record_t;
-
-	typedef struct chanim_stats {
-		uint32 glitchcnt;               /* normalized as per second count */
-		uint32 badplcp;                 /* normalized as per second count */
-		uint8 ccastats[CCASTATS_MAX];   /* normalized as 0-255 */
-		int8 bgnoise;                   /* background noise level (in dBm) */
-		chanspec_t chanspec;            /* ctrl chanspec of the interface */
-		uint32 timestamp;               /* time stamp at which the stats are collected */
-		uint32 bphy_glitchcnt;          /* normalized as per second count */
-		uint32 bphy_badplcp;            /* normalized as per second count */
-		uint8 chan_idle;                /* normalized as 0~255 */
-	} chanim_stats_t;
-
-#define WL_CHANIM_STATS_VERSION 2
-
-typedef struct {
-	uint32 buflen;
-	uint32 version;
-	uint32 count;
-	chanim_stats_t stats[1];
-} wl_chanim_stats_t;
-
-#define WL_CHANIM_STATS_FIXED_LEN OFFSETOF(wl_chanim_stats_t, stats)
-
-/* Noise measurement metrics. */
-#define NOISE_MEASURE_KNOISE	0x1
-
-/* scb probe parameter */
-typedef struct {
-	uint32 scb_timeout;
-	uint32 scb_activity_time;
-	uint32 scb_max_probe;
-} wl_scb_probe_t;
-
-/* structure/defines for selective mgmt frame (smf) stats support */
-
-#define SMFS_VERSION 1
-/* selected mgmt frame (smf) stats element */
-typedef struct wl_smfs_elem {
-	uint32 count;
-	uint16 code;  /* SC or RC code */
-} wl_smfs_elem_t;
-
-typedef struct wl_smf_stats {
-	uint32 version;
-	uint16 length;	/* reserved for future usage */
-	uint8 type;
-	uint8 codetype;
-	uint32 ignored_cnt;
-	uint32 malformed_cnt;
-	uint32 count_total; /* count included the interested group */
-	wl_smfs_elem_t elem[1];
-} wl_smf_stats_t;
-
-#define WL_SMFSTATS_FIXED_LEN OFFSETOF(wl_smf_stats_t, elem);
-
-enum {
-	SMFS_CODETYPE_SC,
-	SMFS_CODETYPE_RC
-};
-
-typedef enum smfs_type {
-	SMFS_TYPE_AUTH,
-	SMFS_TYPE_ASSOC,
-	SMFS_TYPE_REASSOC,
-	SMFS_TYPE_DISASSOC_TX,
-	SMFS_TYPE_DISASSOC_RX,
-	SMFS_TYPE_DEAUTH_TX,
-	SMFS_TYPE_DEAUTH_RX,
-	SMFS_TYPE_MAX
-} smfs_type_t;
-
-#ifdef PHYMON
-
-#define PHYMON_VERSION 1
-
-typedef struct wl_phycal_core_state {
-	/* Tx IQ/LO calibration coeffs */
-	int16 tx_iqlocal_a;
-	int16 tx_iqlocal_b;
-	int8 tx_iqlocal_ci;
-	int8 tx_iqlocal_cq;
-	int8 tx_iqlocal_di;
-	int8 tx_iqlocal_dq;
-	int8 tx_iqlocal_ei;
-	int8 tx_iqlocal_eq;
-	int8 tx_iqlocal_fi;
-	int8 tx_iqlocal_fq;
-
-	/* Rx IQ calibration coeffs */
-	int16 rx_iqcal_a;
-	int16 rx_iqcal_b;
-
-	uint8 tx_iqlocal_pwridx; /* Tx Power Index for Tx IQ/LO calibration */
-	uint32 papd_epsilon_table[64]; /* PAPD epsilon table */
-	int16 papd_epsilon_offset; /* PAPD epsilon offset */
-	uint8 curr_tx_pwrindex; /* Tx power index */
-	int8 idle_tssi; /* Idle TSSI */
-	int8 est_tx_pwr; /* Estimated Tx Power (dB) */
-	int8 est_rx_pwr; /* Estimated Rx Power (dB) from RSSI */
-	uint16 rx_gaininfo; /* Rx gain applied on last Rx pkt */
-	uint16 init_gaincode; /* initgain required for ACI */
-	int8 estirr_tx;
-	int8 estirr_rx;
-
-} wl_phycal_core_state_t;
-
-typedef struct wl_phycal_state {
-	int version;
-	int8 num_phy_cores; /* number of cores */
-	int8 curr_temperature; /* on-chip temperature sensor reading */
-	chanspec_t chspec; /* channspec for this state */
-	bool aci_state; /* ACI state: ON/OFF */
-	uint16 crsminpower; /* crsminpower required for ACI */
-	uint16 crsminpowerl; /* crsminpowerl required for ACI */
-	uint16 crsminpoweru; /* crsminpoweru required for ACI */
-	wl_phycal_core_state_t phycal_core[1];
-} wl_phycal_state_t;
-
-#define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core)
-#endif /* PHYMON */
-
-/* discovery state */
-typedef struct wl_p2p_disc_st {
-	uint8 state;	/* see state */
-	chanspec_t chspec;	/* valid in listen state */
-	uint16 dwell;	/* valid in listen state, in ms */
-} wl_p2p_disc_st_t;
-
-/* scan request */
-typedef struct wl_p2p_scan {
-	uint8 type;		/* 'S' for WLC_SCAN, 'E' for "escan" */
-	uint8 reserved[3];
-	/* scan or escan parms... */
-} wl_p2p_scan_t;
-
-/* i/f request */
-typedef struct wl_p2p_if {
-	struct ether_addr addr;
-	uint8 type;	/* see i/f type */
-	chanspec_t chspec;	/* for p2p_ifadd GO */
-} wl_p2p_if_t;
-
-/* i/f query */
-typedef struct wl_p2p_ifq {
-	uint bsscfgidx;
-	char ifname[BCM_MSG_IFNAME_MAX];
-} wl_p2p_ifq_t;
-
-/* OppPS & CTWindow */
-typedef struct wl_p2p_ops {
-	uint8 ops;	/* 0: disable 1: enable */
-	uint8 ctw;	/* >= 10 */
-} wl_p2p_ops_t;
-
-/* absence and presence request */
-typedef struct wl_p2p_sched_desc {
-	uint32 start;
-	uint32 interval;
-	uint32 duration;
-	uint32 count;	/* see count */
-} wl_p2p_sched_desc_t;
-
-typedef struct wl_p2p_sched {
-	uint8 type;	/* see schedule type */
-	uint8 action;	/* see schedule action */
-	uint8 option;	/* see schedule option */
-	wl_p2p_sched_desc_t desc[1];
-} wl_p2p_sched_t;
-
-typedef struct wl_p2p_wfds_hash {
-	uint32	advt_id;
-	uint16	nw_cfg_method;
-	uint8	wfds_hash[6];
-	uint8	name_len;
-	uint8	service_name[MAX_WFDS_SVC_NAME_LEN];
-} wl_p2p_wfds_hash_t;
-
-typedef struct wl_bcmdcs_data {
-	uint reason;
-	chanspec_t chspec;
-} wl_bcmdcs_data_t;
-
-
-/* NAT configuration */
-typedef struct {
-	uint32 ipaddr;		/* interface ip address */
-	uint32 ipaddr_mask;	/* interface ip address mask */
-	uint32 ipaddr_gateway;	/* gateway ip address */
-	uint8 mac_gateway[6];	/* gateway mac address */
-	uint32 ipaddr_dns;	/* DNS server ip address, valid only for public if */
-	uint8 mac_dns[6];	/* DNS server mac address,  valid only for public if */
-	uint8 GUID[38];		/* interface GUID */
-} nat_if_info_t;
-
-typedef struct {
-	uint op;		/* operation code */
-	bool pub_if;		/* set for public if, clear for private if */
-	nat_if_info_t if_info;	/* interface info */
-} nat_cfg_t;
-
-typedef struct {
-	int state;	/* NAT state returned */
-} nat_state_t;
-
-
-#define BTA_STATE_LOG_SZ	64
-
-/* BTAMP Statemachine states */
-enum {
-	HCIReset = 1,
-	HCIReadLocalAMPInfo,
-	HCIReadLocalAMPASSOC,
-	HCIWriteRemoteAMPASSOC,
-	HCICreatePhysicalLink,
-	HCIAcceptPhysicalLinkRequest,
-	HCIDisconnectPhysicalLink,
-	HCICreateLogicalLink,
-	HCIAcceptLogicalLink,
-	HCIDisconnectLogicalLink,
-	HCILogicalLinkCancel,
-	HCIAmpStateChange,
-	HCIWriteLogicalLinkAcceptTimeout
-};
-
-typedef struct flush_txfifo {
-	uint32 txfifobmp;
-	uint32 hwtxfifoflush;
-	struct ether_addr ea;
-} flush_txfifo_t;
-
-enum {
-	SPATIAL_MODE_2G_IDX = 0,
-	SPATIAL_MODE_5G_LOW_IDX,
-	SPATIAL_MODE_5G_MID_IDX,
-	SPATIAL_MODE_5G_HIGH_IDX,
-	SPATIAL_MODE_5G_UPPER_IDX,
-	SPATIAL_MODE_MAX_IDX
-};
-
-#define WLC_TXCORE_MAX	4	/* max number of txcore supports */
-#define WLC_SUBBAND_MAX	4	/* max number of sub-band supports */
-typedef struct {
-	uint8	band2g[WLC_TXCORE_MAX];
-	uint8	band5g[WLC_SUBBAND_MAX][WLC_TXCORE_MAX];
-} sar_limit_t;
-
-#define WLC_TXCAL_CORE_MAX 2	/* max number of txcore supports for txcal */
-#define MAX_NUM_TXCAL_MEAS 128
-#define MAX_NUM_PWR_STEP 40
-#define TXCAL_ROUNDING_FIX 1
-typedef struct wl_txcal_meas {
-#ifdef TXCAL_ROUNDING_FIX
-	uint16 tssi[WLC_TXCAL_CORE_MAX][MAX_NUM_TXCAL_MEAS];
-#else
-	uint8 tssi[WLC_TXCAL_CORE_MAX][MAX_NUM_TXCAL_MEAS];
-#endif /* TXCAL_ROUNDING_FIX */
-	int16 pwr[WLC_TXCAL_CORE_MAX][MAX_NUM_TXCAL_MEAS];
-	uint8 valid_cnt;
-} wl_txcal_meas_t;
-
-typedef struct wl_txcal_power_tssi {
-	uint8 set_core;
-	uint8 channel;
-	int16 tempsense[WLC_TXCAL_CORE_MAX];
-	int16 pwr_start[WLC_TXCAL_CORE_MAX];
-	uint8 pwr_start_idx[WLC_TXCAL_CORE_MAX];
-	uint8 num_entries[WLC_TXCAL_CORE_MAX];
-	uint8 tssi[WLC_TXCAL_CORE_MAX][MAX_NUM_PWR_STEP];
-	bool gen_tbl;
-} wl_txcal_power_tssi_t;
-
-/* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */
-typedef struct wl_mempool_stats {
-	int	num;		/* Number of memory pools */
-	bcm_mp_stats_t s[1];	/* Variable array of memory pool stats. */
-} wl_mempool_stats_t;
-
-typedef struct {
-	uint32 ipaddr;
-	uint32 ipaddr_netmask;
-	uint32 ipaddr_gateway;
-} nwoe_ifconfig_t;
-
-/* Traffic management priority classes */
-typedef enum trf_mgmt_priority_class {
-	trf_mgmt_priority_low           = 0,        /* Maps to 802.1p BK */
-	trf_mgmt_priority_medium        = 1,        /* Maps to 802.1p BE */
-	trf_mgmt_priority_high          = 2,        /* Maps to 802.1p VI */
-	trf_mgmt_priority_nochange	= 3,	    /* do not update the priority */
-	trf_mgmt_priority_invalid       = (trf_mgmt_priority_nochange + 1)
-} trf_mgmt_priority_class_t;
-
-/* Traffic management configuration parameters */
-typedef struct trf_mgmt_config {
-	uint32  trf_mgmt_enabled;                           /* 0 - disabled, 1 - enabled */
-	uint32  flags;                                      /* See TRF_MGMT_FLAG_xxx defines */
-	uint32  host_ip_addr;                               /* My IP address to determine subnet */
-	uint32  host_subnet_mask;                           /* My subnet mask */
-	uint32  downlink_bandwidth;                         /* In units of kbps */
-	uint32  uplink_bandwidth;                           /* In units of kbps */
-	uint32  min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES];  /* Minimum guaranteed tx bandwidth */
-	uint32  min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES];  /* Minimum guaranteed rx bandwidth */
-} trf_mgmt_config_t;
-
-/* Traffic management filter */
-typedef struct trf_mgmt_filter {
-	struct ether_addr           dst_ether_addr;         /* His L2 address */
-	uint32                      dst_ip_addr;            /* His IP address */
-	uint16                      dst_port;               /* His L4 port */
-	uint16                      src_port;               /* My L4 port */
-	uint16                      prot;                   /* L4 protocol (only TCP or UDP) */
-	uint16                      flags;                  /* TBD. For now, this must be zero. */
-	trf_mgmt_priority_class_t   priority;               /* Priority for filtered packets */
-	uint32                      dscp;                   /* DSCP */
-} trf_mgmt_filter_t;
-
-/* Traffic management filter list (variable length) */
-typedef struct trf_mgmt_filter_list     {
-	uint32              num_filters;
-	trf_mgmt_filter_t   filter[1];
-} trf_mgmt_filter_list_t;
-
-/* Traffic management global info used for all queues */
-typedef struct trf_mgmt_global_info {
-	uint32  maximum_bytes_per_second;
-	uint32  maximum_bytes_per_sampling_period;
-	uint32  total_bytes_consumed_per_second;
-	uint32  total_bytes_consumed_per_sampling_period;
-	uint32  total_unused_bytes_per_sampling_period;
-} trf_mgmt_global_info_t;
-
-/* Traffic management shaping info per priority queue */
-typedef struct trf_mgmt_shaping_info {
-	uint32  gauranteed_bandwidth_percentage;
-	uint32  guaranteed_bytes_per_second;
-	uint32  guaranteed_bytes_per_sampling_period;
-	uint32  num_bytes_produced_per_second;
-	uint32  num_bytes_consumed_per_second;
-	uint32  num_queued_packets;                         /* Number of packets in queue */
-	uint32  num_queued_bytes;                           /* Number of bytes in queue */
-} trf_mgmt_shaping_info_t;
-
-/* Traffic management shaping info array */
-typedef struct trf_mgmt_shaping_info_array {
-	trf_mgmt_global_info_t   tx_global_shaping_info;
-	trf_mgmt_shaping_info_t  tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES];
-	trf_mgmt_global_info_t   rx_global_shaping_info;
-	trf_mgmt_shaping_info_t  rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES];
-} trf_mgmt_shaping_info_array_t;
-
-
-/* Traffic management statistical counters */
-typedef struct trf_mgmt_stats {
-	uint32  num_processed_packets;      /* Number of packets processed */
-	uint32  num_processed_bytes;        /* Number of bytes processed */
-	uint32  num_discarded_packets;      /* Number of packets discarded from queue */
-} trf_mgmt_stats_t;
-
-/* Traffic management statisics array */
-typedef struct trf_mgmt_stats_array {
-	trf_mgmt_stats_t  tx_queue_stats[TRF_MGMT_MAX_PRIORITIES];
-	trf_mgmt_stats_t  rx_queue_stats[TRF_MGMT_MAX_PRIORITIES];
-} trf_mgmt_stats_array_t;
-
-typedef struct powersel_params {
-	/* LPC Params exposed via IOVAR */
-	int32		tp_ratio_thresh;  /* Throughput ratio threshold */
-	uint8		rate_stab_thresh; /* Thresh for rate stability based on nupd */
-	uint8		pwr_stab_thresh; /* Number of successes before power step down */
-	uint8		pwr_sel_exp_time; /* Time lapse for expiry of database */
-} powersel_params_t;
-
-typedef struct lpc_params {
-	/* LPC Params exposed via IOVAR */
-	uint8		rate_stab_thresh; /* Thresh for rate stability based on nupd */
-	uint8		pwr_stab_thresh; /* Number of successes before power step down */
-	uint8		lpc_exp_time; /* Time lapse for expiry of database */
-	uint8		pwrup_slow_step; /* Step size for slow step up */
-	uint8		pwrup_fast_step; /* Step size for fast step up */
-	uint8		pwrdn_slow_step; /* Step size for slow step down */
-} lpc_params_t;
-
-/* tx pkt delay statistics */
-#define	SCB_RETRY_SHORT_DEF	7	/* Default Short retry Limit */
-#define WLPKTDLY_HIST_NBINS	16	/* number of bins used in the Delay histogram */
-
-/* structure to store per-AC delay statistics */
-typedef struct scb_delay_stats {
-	uint32 txmpdu_lost;	/* number of MPDUs lost */
-	uint32 txmpdu_cnt[SCB_RETRY_SHORT_DEF]; /* retry times histogram */
-	uint32 delay_sum[SCB_RETRY_SHORT_DEF]; /* cumulative packet latency */
-	uint32 delay_min;	/* minimum packet latency observed */
-	uint32 delay_max;	/* maximum packet latency observed */
-	uint32 delay_avg;	/* packet latency average */
-	uint32 delay_hist[WLPKTDLY_HIST_NBINS];	/* delay histogram */
-} scb_delay_stats_t;
-
-/* structure for txdelay event */
-typedef struct txdelay_event {
-	uint8	status;
-	int		rssi;
-	chanim_stats_t		chanim_stats;
-	scb_delay_stats_t	delay_stats[AC_COUNT];
-} txdelay_event_t;
-
-/* structure for txdelay parameters */
-typedef struct txdelay_params {
-	uint16	ratio;	/* Avg Txdelay Delta */
-	uint8	cnt;	/* Sample cnt */
-	uint8	period;	/* Sample period */
-	uint8	tune;	/* Debug */
-} txdelay_params_t;
-
-enum {
-	WNM_SERVICE_DMS = 1,
-	WNM_SERVICE_FMS = 2,
-	WNM_SERVICE_TFS = 3
-};
-
-/* Definitions for WNM/NPS TCLAS */
-typedef struct wl_tclas {
-	uint8 user_priority;
-	uint8 fc_len;
-	dot11_tclas_fc_t fc;
-} wl_tclas_t;
-
-#define WL_TCLAS_FIXED_SIZE	OFFSETOF(wl_tclas_t, fc)
-
-typedef struct wl_tclas_list {
-	uint32 num;
-	wl_tclas_t tclas[1];
-} wl_tclas_list_t;
-
-/* Definitions for WNM/NPS Traffic Filter Service */
-typedef struct wl_tfs_req {
-	uint8 tfs_id;
-	uint8 tfs_actcode;
-	uint8 tfs_subelem_id;
-	uint8 send;
-} wl_tfs_req_t;
-
-typedef struct wl_tfs_filter {
-	uint8 status;			/* Status returned by the AP */
-	uint8 tclas_proc;		/* TCLAS processing value (0:and, 1:or)  */
-	uint8 tclas_cnt;		/* count of all wl_tclas_t in tclas array */
-	uint8 tclas[1];			/* VLA of wl_tclas_t */
-} wl_tfs_filter_t;
-#define WL_TFS_FILTER_FIXED_SIZE	OFFSETOF(wl_tfs_filter_t, tclas)
-
-typedef struct wl_tfs_fset {
-	struct ether_addr ea;		/* Address of AP/STA involved with this filter set */
-	uint8 tfs_id;			/* TFS ID field chosen by STA host */
-	uint8 status;			/* Internal status TFS_STATUS_xxx */
-	uint8 actcode;			/* Action code DOT11_TFS_ACTCODE_xxx */
-	uint8 token;			/* Token used in last request frame */
-	uint8 notify;			/* Notify frame sent/received because of this set */
-	uint8 filter_cnt;		/* count of all wl_tfs_filter_t in filter array */
-	uint8 filter[1];		/* VLA of wl_tfs_filter_t */
-} wl_tfs_fset_t;
-#define WL_TFS_FSET_FIXED_SIZE		OFFSETOF(wl_tfs_fset_t, filter)
-
-enum {
-	TFS_STATUS_DISABLED = 0,	/* TFS filter set disabled by user */
-	TFS_STATUS_DISABLING = 1,	/* Empty request just sent to AP */
-	TFS_STATUS_VALIDATED = 2,	/* Filter set validated by AP (but maybe not enabled!) */
-	TFS_STATUS_VALIDATING = 3,	/* Filter set just sent to AP */
-	TFS_STATUS_NOT_ASSOC = 4,	/* STA not associated */
-	TFS_STATUS_NOT_SUPPORT = 5,	/* TFS not supported by AP */
-	TFS_STATUS_DENIED = 6,		/* Filter set refused by AP (=> all sets are disabled!) */
-};
-
-typedef struct wl_tfs_status {
-	uint8 fset_cnt;			/* count of all wl_tfs_fset_t in fset array */
-	wl_tfs_fset_t fset[1];		/* VLA of wl_tfs_fset_t */
-} wl_tfs_status_t;
-
-typedef struct wl_tfs_set {
-	uint8 send;			/* Immediatly register registered sets on AP side */
-	uint8 tfs_id;			/* ID of a specific set (existing or new), or nul for all */
-	uint8 actcode;			/* Action code for this filter set */
-	uint8 tclas_proc;		/* TCLAS processing operator for this filter set */
-} wl_tfs_set_t;
-
-typedef struct wl_tfs_term {
-	uint8 del;			/* Delete internal set once confirmation received */
-	uint8 tfs_id;			/* ID of a specific set (existing), or nul for all */
-} wl_tfs_term_t;
-
-
-#define DMS_DEP_PROXY_ARP (1 << 0)
-
-/* Definitions for WNM/NPS Directed Multicast Service */
-enum {
-	DMS_STATUS_DISABLED = 0,	/* DMS desc disabled by user */
-	DMS_STATUS_ACCEPTED = 1,	/* Request accepted by AP */
-	DMS_STATUS_NOT_ASSOC = 2,	/* STA not associated */
-	DMS_STATUS_NOT_SUPPORT = 3,	/* DMS not supported by AP */
-	DMS_STATUS_DENIED = 4,		/* Request denied by AP */
-	DMS_STATUS_TERM = 5,		/* Request terminated by AP */
-	DMS_STATUS_REMOVING = 6,	/* Remove request just sent */
-	DMS_STATUS_ADDING = 7,		/* Add request just sent */
-	DMS_STATUS_ERROR = 8,		/* Non compliant AP behvior */
-	DMS_STATUS_IN_PROGRESS = 9, /* Request just sent */
-	DMS_STATUS_REQ_MISMATCH = 10 /* Conditions for sending DMS req not met */
-};
-
-typedef struct wl_dms_desc {
-	uint8 user_id;
-	uint8 status;
-	uint8 token;
-	uint8 dms_id;
-	uint8 tclas_proc;
-	uint8 mac_len;		/* length of all ether_addr in data array, 0 if STA */
-	uint8 tclas_len;	/* length of all wl_tclas_t in data array */
-	uint8 data[1];		/* VLA of 'ether_addr' and 'wl_tclas_t' (in this order ) */
-} wl_dms_desc_t;
-
-#define WL_DMS_DESC_FIXED_SIZE	OFFSETOF(wl_dms_desc_t, data)
-
-typedef struct wl_dms_status {
-	uint32 cnt;
-	wl_dms_desc_t desc[1];
-} wl_dms_status_t;
-
-typedef struct wl_dms_set {
-	uint8 send;
-	uint8 user_id;
-	uint8 tclas_proc;
-} wl_dms_set_t;
-
-typedef struct wl_dms_term {
-	uint8 del;
-	uint8 user_id;
-} wl_dms_term_t;
-
-typedef struct wl_service_term {
-	uint8 service;
-	union {
-		wl_dms_term_t dms;
-	} u;
-} wl_service_term_t;
-
-/* Definitions for WNM/NPS BSS Transistion */
-typedef struct wl_bsstrans_req {
-	uint16 tbtt;			/* time of BSS to end of life, in unit of TBTT */
-	uint16 dur;			/* time of BSS to keep off, in unit of minute */
-	uint8 reqmode;			/* request mode of BSS transition request */
-	uint8 unicast;			/* request by unicast or by broadcast */
-} wl_bsstrans_req_t;
-
-enum {
-	BSSTRANS_RESP_AUTO = 0,		/* Currently equivalent to ENABLE */
-	BSSTRANS_RESP_DISABLE = 1,	/* Never answer BSS Trans Req frames */
-	BSSTRANS_RESP_ENABLE = 2,	/* Always answer Req frames with preset data */
-	BSSTRANS_RESP_WAIT = 3,		/* Send ind, wait and/or send preset data (NOT IMPL) */
-	BSSTRANS_RESP_IMMEDIATE = 4	/* After an ind, set data and send resp (NOT IMPL) */
-};
-
-typedef struct wl_bsstrans_resp {
-	uint8 policy;
-	uint8 status;
-	uint8 delay;
-	struct ether_addr target;
-} wl_bsstrans_resp_t;
-
-/* "wnm_bsstrans_policy" argument programs behavior after BSSTRANS Req reception.
- * BSS-Transition feature is used by multiple programs such as NPS-PF, VE-PF,
- * Band-steering, Hotspot 2.0 and customer requirements. Each PF and its test plan
- * mandates different behavior on receiving BSS-transition request. To accomodate
- * such divergent behaviors these policies have been created.
- */
-enum {
-	WL_BSSTRANS_POLICY_ROAM_ALWAYS = 0,	/* Roam (or disassociate) in all cases */
-	WL_BSSTRANS_POLICY_ROAM_IF_MODE = 1,	/* Roam only if requested by Request Mode field */
-	WL_BSSTRANS_POLICY_ROAM_IF_PREF = 2,	/* Roam only if Preferred BSS provided */
-	WL_BSSTRANS_POLICY_WAIT = 3,		/* Wait for deauth and send Accepted status */
-	WL_BSSTRANS_POLICY_PRODUCT = 4,		/* Policy for real product use cases (non-pf) */
-};
-
-/* Definitions for WNM/NPS TIM Broadcast */
-typedef struct wl_timbc_offset {
-	int16 offset;		/* offset in us */
-	uint16 fix_intv;	/* override interval sent from STA */
-	uint16 rate_override;	/* use rate override to send high rate TIM broadcast frame */
-	uint8 tsf_present;	/* show timestamp in TIM broadcast frame */
-} wl_timbc_offset_t;
-
-typedef struct wl_timbc_set {
-	uint8 interval;		/* Interval in DTIM wished or required. */
-	uint8 flags;		/* Bitfield described below */
-	uint16 rate_min;	/* Minimum rate required for High/Low TIM frames. Optionnal */
-	uint16 rate_max;	/* Maximum rate required for High/Low TIM frames. Optionnal */
-} wl_timbc_set_t;
-
-enum {
-	WL_TIMBC_SET_TSF_REQUIRED = 1,	/* Enable TIMBC only if TSF in TIM frames */
-	WL_TIMBC_SET_NO_OVERRIDE = 2,	/* ... if AP does not override interval */
-	WL_TIMBC_SET_PROXY_ARP = 4,	/* ... if AP support Proxy ARP */
-	WL_TIMBC_SET_DMS_ACCEPTED = 8	/* ... if all DMS desc have been accepted */
-};
-
-typedef struct wl_timbc_status {
-	uint8 status_sta;		/* Status from internal state machine (check below) */
-	uint8 status_ap;		/* From AP response frame (check 8.4.2.86 from 802.11) */
-	uint8 interval;
-	uint8 pad;
-	int32 offset;
-	uint16 rate_high;
-	uint16 rate_low;
-} wl_timbc_status_t;
-
-enum {
-	WL_TIMBC_STATUS_DISABLE = 0,		/* TIMBC disabled by user */
-	WL_TIMBC_STATUS_REQ_MISMATCH = 1,	/* AP settings do no match user requirements */
-	WL_TIMBC_STATUS_NOT_ASSOC = 2,		/* STA not associated */
-	WL_TIMBC_STATUS_NOT_SUPPORT = 3,	/* TIMBC not supported by AP */
-	WL_TIMBC_STATUS_DENIED = 4,		/* Req to disable TIMBC sent to AP */
-	WL_TIMBC_STATUS_ENABLE = 5		/* TIMBC enabled */
-};
-
-/* Definitions for PM2 Dynamic Fast Return To Sleep */
-typedef struct wl_pm2_sleep_ret_ext {
-	uint8 logic;			/* DFRTS logic: see WL_DFRTS_LOGIC_* below */
-	uint16 low_ms;			/* Low FRTS timeout */
-	uint16 high_ms;			/* High FRTS timeout */
-	uint16 rx_pkts_threshold;	/* switching threshold: # rx pkts */
-	uint16 tx_pkts_threshold;	/* switching threshold: # tx pkts */
-	uint16 txrx_pkts_threshold;	/* switching threshold: # (tx+rx) pkts */
-	uint32 rx_bytes_threshold;	/* switching threshold: # rx bytes */
-	uint32 tx_bytes_threshold;	/* switching threshold: # tx bytes */
-	uint32 txrx_bytes_threshold;	/* switching threshold: # (tx+rx) bytes */
-} wl_pm2_sleep_ret_ext_t;
-
-#define WL_DFRTS_LOGIC_OFF	0	/* Feature is disabled */
-#define WL_DFRTS_LOGIC_OR	1	/* OR all non-zero threshold conditions */
-#define WL_DFRTS_LOGIC_AND	2	/* AND all non-zero threshold conditions */
-
-/* Values for the passive_on_restricted_mode iovar.  When set to non-zero, this iovar
- * disables automatic conversions of a channel from passively scanned to
- * actively scanned.  These values only have an effect for country codes such
- * as XZ where some 5 GHz channels are defined to be passively scanned.
- */
-#define WL_PASSACTCONV_DISABLE_NONE	0	/* Enable permanent and temporary conversions */
-#define WL_PASSACTCONV_DISABLE_ALL	1	/* Disable permanent and temporary conversions */
-#define WL_PASSACTCONV_DISABLE_PERM	2	/* Disable only permanent conversions */
-
-/* Definitions for Reliable Multicast */
-#define WL_RMC_CNT_VERSION	   1
-#define WL_RMC_TR_VERSION	   1
-#define WL_RMC_MAX_CLIENT	   32
-#define WL_RMC_FLAG_INBLACKLIST	   1
-#define WL_RMC_FLAG_ACTIVEACKER	   2
-#define WL_RMC_FLAG_RELMCAST	   4
-#define WL_RMC_MAX_TABLE_ENTRY     4
-
-#define WL_RMC_VER		   1
-#define WL_RMC_INDEX_ACK_ALL       255
-#define WL_RMC_NUM_OF_MC_STREAMS   4
-#define WL_RMC_MAX_TRS_PER_GROUP   1
-#define WL_RMC_MAX_TRS_IN_ACKALL   1
-#define WL_RMC_ACK_MCAST0          0x02
-#define WL_RMC_ACK_MCAST_ALL       0x01
-#define WL_RMC_ACTF_TIME_MIN       300	 /* time in ms */
-#define WL_RMC_ACTF_TIME_MAX       20000 /* time in ms */
-#define WL_RMC_MAX_NUM_TRS	   32	 /* maximun transmitters allowed */
-#define WL_RMC_ARTMO_MIN           350	 /* time in ms */
-#define WL_RMC_ARTMO_MAX           40000	 /* time in ms */
-
-/* RMC events in action frames */
-enum rmc_opcodes {
-	RELMCAST_ENTRY_OP_DISABLE = 0,   /* Disable multi-cast group */
-	RELMCAST_ENTRY_OP_DELETE  = 1,   /* Delete multi-cast group */
-	RELMCAST_ENTRY_OP_ENABLE  = 2,   /* Enable multi-cast group */
-	RELMCAST_ENTRY_OP_ACK_ALL = 3    /* Enable ACK ALL bit in AMT */
-};
-
-/* RMC operational modes */
-enum rmc_modes {
-	WL_RMC_MODE_RECEIVER    = 0,	 /* Receiver mode by default */
-	WL_RMC_MODE_TRANSMITTER = 1,	 /* Transmitter mode using wl ackreq */
-	WL_RMC_MODE_INITIATOR   = 2	 /* Initiator mode using wl ackreq */
-};
-
-/* Each RMC mcast client info */
-typedef struct wl_relmcast_client {
-	uint8 flag;			/* status of client such as AR, R, or blacklisted */
-	int16 rssi;			/* rssi value of RMC client */
-	struct ether_addr addr;		/* mac address of RMC client */
-} wl_relmcast_client_t;
-
-/* RMC Counters */
-typedef struct wl_rmc_cnts {
-	uint16  version;		/* see definition of WL_CNT_T_VERSION */
-	uint16  length;			/* length of entire structure */
-	uint16	dupcnt;			/* counter for duplicate rmc MPDU */
-	uint16	ackreq_err;		/* counter for wl ackreq error    */
-	uint16	af_tx_err;		/* error count for action frame transmit   */
-	uint16	null_tx_err;		/* error count for rmc null frame transmit */
-	uint16	af_unicast_tx_err;	/* error count for rmc unicast frame transmit */
-	uint16	mc_no_amt_slot;		/* No mcast AMT entry available */
-	/* Unused. Keep for rom compatibility */
-	uint16	mc_no_glb_slot;		/* No mcast entry available in global table */
-	uint16	mc_not_mirrored;	/* mcast group is not mirrored */
-	uint16	mc_existing_tr;		/* mcast group is already taken by transmitter */
-	uint16	mc_exist_in_amt;	/* mcast group is already programmed in amt */
-	/* Unused. Keep for rom compatibility */
-	uint16	mc_not_exist_in_gbl;	/* mcast group is not in global table */
-	uint16	mc_not_exist_in_amt;	/* mcast group is not in AMT table */
-	uint16	mc_utilized;		/* mcast addressed is already taken */
-	uint16	mc_taken_other_tr;	/* multi-cast addressed is already taken */
-	uint32	rmc_rx_frames_mac;      /* no of mc frames received from mac */
-	uint32	rmc_tx_frames_mac;      /* no of mc frames transmitted to mac */
-	uint32	mc_null_ar_cnt;         /* no. of times NULL AR is received */
-	uint32	mc_ar_role_selected;	/* no. of times took AR role */
-	uint32	mc_ar_role_deleted;	/* no. of times AR role cancelled */
-	uint32	mc_noacktimer_expired;  /* no. of times noack timer expired */
-	uint16  mc_no_wl_clk;           /* no wl clk detected when trying to access amt */
-	uint16  mc_tr_cnt_exceeded;     /* No of transmitters in the network exceeded */
-} wl_rmc_cnts_t;
-
-/* RMC Status */
-typedef struct wl_relmcast_st {
-	uint8         ver;		/* version of RMC */
-	uint8         num;		/* number of clients detected by transmitter */
-	wl_relmcast_client_t clients[WL_RMC_MAX_CLIENT];
-	uint16        err;		/* error status (used in infra) */
-	uint16        actf_time;	/* action frame time period */
-} wl_relmcast_status_t;
-
-/* Entry for each STA/node */
-typedef struct wl_rmc_entry {
-	/* operation on multi-cast entry such add,
-	 * delete, ack-all
-	 */
-	int8    flag;
-	struct ether_addr addr;		/* multi-cast group mac address */
-} wl_rmc_entry_t;
-
-/* RMC table */
-typedef struct wl_rmc_entry_table {
-	uint8   index;			/* index to a particular mac entry in table */
-	uint8   opcode;			/* opcodes or operation on entry */
-	wl_rmc_entry_t entry[WL_RMC_MAX_TABLE_ENTRY];
-} wl_rmc_entry_table_t;
-
-typedef struct wl_rmc_trans_elem {
-	struct ether_addr tr_mac;	/* transmitter mac */
-	struct ether_addr ar_mac;	/* ar mac */
-	uint16 artmo;			/* AR timeout */
-	uint8 amt_idx;			/* amt table entry */
-	uint16 flag;			/* entry will be acked, not acked, programmed, full etc */
-} wl_rmc_trans_elem_t;
-
-/* RMC transmitters */
-typedef struct wl_rmc_trans_in_network {
-	uint8         ver;		/* version of RMC */
-	uint8         num_tr;		/* number of transmitters in the network */
-	wl_rmc_trans_elem_t trs[WL_RMC_MAX_NUM_TRS];
-} wl_rmc_trans_in_network_t;
-
-/* To update vendor specific ie for RMC */
-typedef struct wl_rmc_vsie {
-	uint8	oui[DOT11_OUI_LEN];
-	uint16	payload;	/* IE Data Payload */
-} wl_rmc_vsie_t;
-
-
-/* structures  & defines for proximity detection  */
-enum proxd_method {
-	PROXD_UNDEFINED_METHOD = 0,
-	PROXD_RSSI_METHOD = 1,
-	PROXD_TOF_METHOD = 2
-};
-
-/* structures for proximity detection device role */
-#define WL_PROXD_MODE_DISABLE	0
-#define WL_PROXD_MODE_NEUTRAL	1
-#define WL_PROXD_MODE_INITIATOR	2
-#define WL_PROXD_MODE_TARGET	3
-
-#define WL_PROXD_ACTION_STOP		0
-#define WL_PROXD_ACTION_START		1
-
-#define WL_PROXD_FLAG_TARGET_REPORT	0x1
-#define WL_PROXD_FLAG_REPORT_FAILURE	0x2
-#define WL_PROXD_FLAG_INITIATOR_REPORT	0x4
-#define WL_PROXD_FLAG_NOCHANSWT		0x8
-#define WL_PROXD_FLAG_NETRUAL		0x10
-#define WL_PROXD_FLAG_INITIATOR_RPTRTT	0x20
-#define WL_PROXD_FLAG_ONEWAY		0x40
-#define WL_PROXD_FLAG_SEQ_EN		0x80
-
-#define WL_PROXD_RANDOM_WAKEUP	0x8000
-#define WL_PROXD_MAXREPORT	8
-
-typedef struct wl_proxd_iovar {
-	uint16	method;		/* Proxmity Detection method */
-	uint16	mode;		/* Mode (neutral, initiator, target) */
-} wl_proxd_iovar_t;
-
-/*
- * structures for proximity detection parameters
- * consists of two parts, common and method specific params
- * common params should be placed at the beginning
- */
-
-/* require strict packing */
-#include <packed_section_start.h>
-
-typedef	BWL_PRE_PACKED_STRUCT struct	wl_proxd_params_common	{
-	chanspec_t	chanspec;	/* channel spec */
-	int16		tx_power;	/* tx power of Proximity Detection(PD) frames (in dBm) */
-	uint16		tx_rate;	/* tx rate of PD rames  (in 500kbps units) */
-	uint16		timeout;	/* timeout value */
-	uint16		interval;	/* interval between neighbor finding attempts (in TU) */
-	uint16		duration;	/* duration of neighbor finding attempts (in ms) */
-} BWL_POST_PACKED_STRUCT wl_proxd_params_common_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_rssi_method {
-	chanspec_t	chanspec;	/* chanspec for home channel */
-	int16		tx_power;	/* tx power of Proximity Detection frames (in dBm) */
-	uint16		tx_rate;	/* tx rate of PD frames, 500kbps units */
-	uint16		timeout;	/* state machine wait timeout of the frames (in ms) */
-	uint16		interval;	/* interval between neighbor finding attempts (in TU) */
-	uint16		duration;	/* duration of neighbor finding attempts (in ms) */
-					/* method specific ones go after this line */
-	int16		rssi_thresh;	/* RSSI threshold (in dBm) */
-	uint16		maxconvergtmo;	/* max wait converge timeout (in ms) */
-} wl_proxd_params_rssi_method_t;
-
-#define Q1_NS			25	/* Q1 time units */
-
-#define TOF_BW_NUM		3	/* number of bandwidth that the TOF can support */
-#define TOF_BW_SEQ_NUM		(TOF_BW_NUM+2)	/* number of total index */
-enum tof_bw_index {
-	TOF_BW_20MHZ_INDEX = 0,
-	TOF_BW_40MHZ_INDEX = 1,
-	TOF_BW_80MHZ_INDEX = 2,
-	TOF_BW_SEQTX_INDEX = 3,
-	TOF_BW_SEQRX_INDEX = 4
-};
-
-#define BANDWIDTH_BASE	20	/* base value of bandwidth */
-#define TOF_BW_20MHZ    (BANDWIDTH_BASE << TOF_BW_20MHZ_INDEX)
-#define TOF_BW_40MHZ    (BANDWIDTH_BASE << TOF_BW_40MHZ_INDEX)
-#define TOF_BW_80MHZ    (BANDWIDTH_BASE << TOF_BW_80MHZ_INDEX)
-#define TOF_BW_10MHZ    10
-
-#define NFFT_BASE		64	/* base size of fft */
-#define TOF_NFFT_20MHZ  (NFFT_BASE << TOF_BW_20MHZ_INDEX)
-#define TOF_NFFT_40MHZ  (NFFT_BASE << TOF_BW_40MHZ_INDEX)
-#define TOF_NFFT_80MHZ  (NFFT_BASE << TOF_BW_80MHZ_INDEX)
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_tof_method {
-	chanspec_t	chanspec;	/* chanspec for home channel */
-	int16		tx_power;	/* tx power of Proximity Detection(PD) frames (in dBm) */
-	uint16		tx_rate;	/* tx rate of PD rames  (in 500kbps units) */
-	uint16		timeout;	/* state machine wait timeout of the frames (in ms) */
-	uint16		interval;	/* interval between neighbor finding attempts (in TU) */
-	uint16		duration;	/* duration of neighbor finding attempts (in ms) */
-	/* specific for the method go after this line */
-	struct ether_addr tgt_mac;	/* target mac addr for TOF method */
-	uint16		ftm_cnt;	/* number of the frames txed by initiator */
-	uint16		retry_cnt;	/* number of retransmit attampts for ftm frames */
-	int16		vht_rate;	/* ht or vht rate */
-	/* add more params required for other methods can be added here  */
-} BWL_POST_PACKED_STRUCT wl_proxd_params_tof_method_t;
-
-typedef struct wl_proxd_seq_config
-{
-	int16 N_tx_log2;
-	int16 N_rx_log2;
-	int16 N_tx_scale;
-	int16 N_rx_scale;
-	int16 w_len;
-	int16 w_offset;
-} wl_proxd_seq_config_t;
-
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_tof_tune {
-	uint32		Ki;			/* h/w delay K factor for initiator */
-	uint32		Kt;			/* h/w delay K factor for target */
-	int16		vhtack;			/* enable/disable VHT ACK */
-	int16		N_log2[TOF_BW_SEQ_NUM]; /* simple threshold crossing */
-	int16		w_offset[TOF_BW_NUM];	/* offset of threshold crossing window(per BW) */
-	int16		w_len[TOF_BW_NUM];	/* length of threshold crossing window(per BW) */
-	int32		maxDT;			/* max time difference of T4/T1 or T3/T2 */
-	int32		minDT;			/* min time difference of T4/T1 or T3/T2 */
-	uint8		totalfrmcnt;	/* total count of transfered measurement frames */
-	uint16		rsv_media;		/* reserve media value for TOF */
-	uint32		flags;			/* flags */
-	uint8		core;			/* core to use for tx */
-	uint8		force_K;		/* set to force value of K  */
-	int16		N_scale[TOF_BW_SEQ_NUM]; /* simple threshold crossing */
-	uint8		sw_adj;			/* enable sw assisted timestamp adjustment */
-	uint8		hw_adj;			/* enable hw assisted timestamp adjustment */
-	uint8		seq_en;			/* enable ranging sequence */
-	uint8		ftm_cnt[TOF_BW_SEQ_NUM]; /* number of ftm frames based on bandwidth */
-	int16		N_log2_2g;		/* simple threshold crossing for 2g channel */
-	int16		N_scale_2g;		/* simple threshold crossing for 2g channel */
-	wl_proxd_seq_config_t seq_5g20;
-} BWL_POST_PACKED_STRUCT wl_proxd_params_tof_tune_t;
-
-typedef struct wl_proxd_params_iovar {
-	uint16	method;			/* Proxmity Detection method */
-	union {
-		/* common params for pdsvc */
-		wl_proxd_params_common_t	cmn_params;	/* common parameters */
-		/*  method specific */
-		wl_proxd_params_rssi_method_t	rssi_params;	/* RSSI method parameters */
-		wl_proxd_params_tof_method_t	tof_params;	/* TOF meothod parameters */
-		/* tune parameters */
-		wl_proxd_params_tof_tune_t	tof_tune;	/* TOF tune parameters */
-	} u;				/* Method specific optional parameters */
-} wl_proxd_params_iovar_t;
-
-#define PROXD_COLLECT_GET_STATUS	0
-#define PROXD_COLLECT_SET_STATUS	1
-#define PROXD_COLLECT_QUERY_HEADER	2
-#define PROXD_COLLECT_QUERY_DATA	3
-#define PROXD_COLLECT_QUERY_DEBUG	4
-#define PROXD_COLLECT_REMOTE_REQUEST	5
-#define PROXD_COLLECT_DONE			6
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_query {
-	uint32		method;		/* method */
-	uint8		request;	/* Query request. */
-	uint8		status;		/* 0 -- disable, 1 -- enable collection, */
-					/* 2 -- enable collection & debug */
-	uint16		index;		/* The current frame index [0 to total_frames - 1]. */
-	uint16		mode;		/* Initiator or Target */
-	bool		busy;		/* tof sm is busy */
-	bool		remote;		/* Remote collect data */
-} BWL_POST_PACKED_STRUCT wl_proxd_collect_query_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_header {
-	uint16		total_frames;			/* The totral frames for this collect. */
-	uint16		nfft;				/* nfft value */
-	uint16		bandwidth;			/* bandwidth */
-	uint16		channel;			/* channel number */
-	uint32		chanspec;			/* channel spec */
-	uint32		fpfactor;			/* avb timer value factor */
-	uint16		fpfactor_shift;			/* avb timer value shift bits */
-	int32		distance;			/* distance calculated by fw */
-	uint32		meanrtt;			/* mean of RTTs */
-	uint32		modertt;			/* mode of RTTs */
-	uint32		medianrtt;			/* median of RTTs */
-	uint32		sdrtt;				/* standard deviation of RTTs */
-	uint32		clkdivisor;			/* clock divisor */
-	uint16		chipnum;			/* chip type */
-	uint8		chiprev;			/* chip revision */
-	uint8		phyver;				/* phy version */
-	struct ether_addr	loaclMacAddr;		/* local mac address */
-	struct ether_addr	remoteMacAddr;		/* remote mac address */
-	wl_proxd_params_tof_tune_t params;
-} BWL_POST_PACKED_STRUCT wl_proxd_collect_header_t;
-
-
-#ifdef WL_NAN
-/*  ********************** NAN wl interface struct types and defs ******************** */
-
-#define WL_NAN_IOCTL_VERSION	0x1
-#define NAN_IOC_BUFSZ  256 /**< some sufficient ioc buff size for our module */
-#define NAN_IOC_BUFSZ_EXT  1024 /* some sufficient ioc buff size for dump commands */
-
-/*   wl_nan_sub_cmd may also be used in dhd  */
-typedef struct wl_nan_sub_cmd wl_nan_sub_cmd_t;
-typedef int (cmd_handler_t)(void *wl, const wl_nan_sub_cmd_t *cmd, char **argv);
-/* nan cmd list entry  */
-struct wl_nan_sub_cmd {
-	char *name;
-	uint8  version;		/* cmd  version */
-	uint16 id;			/* id for the dongle f/w switch/case  */
-	uint16 type;		/* base type of argument */
-	cmd_handler_t *handler; /* cmd handler  */
-};
-
-/* container for nan iovtls & events */
-typedef BWL_PRE_PACKED_STRUCT struct wl_nan_ioc {
-	uint16	version;	/* interface command or event version */
-	uint16	id;			/* nan ioctl cmd  ID  */
-	uint16	len;		/* total length of all tlv records in data[]  */
-	uint16	pad;		/* pad to be 32 bit aligment */
-	uint8	data [1];	/* var len payload of bcm_xtlv_t type */
-} BWL_POST_PACKED_STRUCT wl_nan_ioc_t;
-
-typedef struct wl_nan_status {
-	uint8 inited;
-	uint8 joined;
-	uint8 role;
-	uint8 hop_count;
-	uint32 chspec;
-	uint8 amr[8];			/* Anchor Master Rank */
-	uint32 cnt_pend_txfrm;		/* pending TX frames */
-	uint32 cnt_bcn_tx;		/* TX disc/sync beacon count */
-	uint32 cnt_bcn_rx;		/* RX disc/sync beacon count */
-	uint32 cnt_svc_disc_tx;		/* TX svc disc frame count */
-	uint32 cnt_svc_disc_rx;		/* RX svc disc frame count */
-	struct ether_addr cid;
-	uint32 chspec_5g;
-} wl_nan_status_t;
-
-typedef struct wl_nan_count {
-	uint32 cnt_bcn_tx;		/* TX disc/sync beacon count */
-	uint32 cnt_bcn_rx;		/* RX disc/sync beacon count */
-	uint32 cnt_svc_disc_tx;		/* TX svc disc frame count */
-	uint32 cnt_svc_disc_rx;		/* RX svc disc frame count */
-} wl_nan_count_t;
-
-/* various params and ctl swithce for nan_debug instance  */
-typedef struct nan_debug_params {
-	uint8	enabled; /* runtime debuging enabled */
-	uint8	collect; /* enables debug svc sdf monitor mode  */
-	uint16	cmd;	/* debug cmd to perform a debug action */
-	uint32	msglevel; /* msg level if enabled */
-	uint16	status;
-} nan_debug_params_t;
-
-/* time slot */
-#define NAN_MAX_TIMESLOT	32
-typedef struct nan_timeslot {
-	uint32	abitmap; /* available bitmap */
-	uint32 chanlist[NAN_MAX_TIMESLOT];
-} nan_timeslot_t;
-
-/* nan passive scan params */
-#define NAN_SCAN_MAX_CHCNT 8
-typedef struct nan_scan_params {
-	uint16 scan_time;
-	uint16 home_time;
-	uint16 ms_intvl; /* interval between merge scan */
-	uint16 ms_dur;  /* duration of merge scan */
-	uint16 chspec_num;
-	uint8 pad[2];
-	chanspec_t chspec_list[NAN_SCAN_MAX_CHCNT]; /* act. used 3, 5 rfu */
-} nan_scan_params_t;
-
-enum wl_nan_role {
-	WL_NAN_ROLE_AUTO = 0,
-	WL_NAN_ROLE_NON_MASTER_NON_SYNC = 1,
-	WL_NAN_ROLE_NON_MASTER_SYNC = 2,
-	WL_NAN_ROLE_MASTER = 3,
-	WL_NAN_ROLE_ANCHOR_MASTER = 4
-};
-#define NAN_MASTER_RANK_LEN 8
-/* nan cmd IDs */
-enum wl_nan_cmds {
-	 /* nan cfg /disc & dbg ioctls */
-	WL_NAN_CMD_ENABLE = 1,
-	WL_NAN_CMD_ATTR = 2,
-	WL_NAN_CMD_NAN_JOIN = 3,
-	WL_NAN_CMD_LEAVE = 4,
-	WL_NAN_CMD_MERGE = 5,
-	WL_NAN_CMD_STATUS = 6,
-	WL_NAN_CMD_TSRESERVE = 7,
-	WL_NAN_CMD_TSSCHEDULE = 8,
-	WL_NAN_CMD_TSRELEASE = 9,
-	WL_NAN_CMD_OUI = 10,
-
-	WL_NAN_CMD_COUNT = 15,
-	WL_NAN_CMD_CLEARCOUNT = 16,
-
-	/*  discovery engine commands */
-	WL_NAN_CMD_PUBLISH = 20,
-	WL_NAN_CMD_SUBSCRIBE = 21,
-	WL_NAN_CMD_CANCEL_PUBLISH = 22,
-	WL_NAN_CMD_CANCEL_SUBSCRIBE = 23,
-	WL_NAN_CMD_TRANSMIT = 24,
-	WL_NAN_CMD_CONNECTION = 25,
-	WL_NAN_CMD_SHOW = 26,
-	WL_NAN_CMD_STOP = 27,	/* stop nan for a given cluster ID  */
-	/*  nan debug iovars & cmds  */
-	WL_NAN_CMD_SCAN_PARAMS = 46,
-	WL_NAN_CMD_SCAN = 47,
-	WL_NAN_CMD_SCAN_RESULTS = 48,
-	WL_NAN_CMD_EVENT_MASK = 49,
-	WL_NAN_CMD_EVENT_CHECK = 50,
-	WL_NAN_CMD_DUMP = 51,
-	WL_NAN_CMD_CLEAR = 52,
-	WL_NAN_CMD_RSSI = 53,
-
-	WL_NAN_CMD_DEBUG = 60,
-	WL_NAN_CMD_TEST1 = 61,
-	WL_NAN_CMD_TEST2 = 62,
-	WL_NAN_CMD_TEST3 = 63,
-	WL_NAN_CMD_DISC_RESULTS = 64
-};
-
-/*
- * tlv IDs uniquely identifies  cmd parameters
- * packed into wl_nan_ioc_t container
- */
-enum wl_nan_cmd_xtlv_id {
-	/* 0x00 ~ 0xFF: standard TLV ID whose data format is the same as NAN attribute TLV */
-	WL_NAN_XTLV_ZERO = 0,		/* used as tlv buf end marker */
-#ifdef NAN_STD_TLV 				/* rfu, don't use yet */
-	WL_NAN_XTLV_MASTER_IND = 1, /* == NAN_ATTR_MASTER_IND, */
-	WL_NAN_XTLV_CLUSTER = 2,	/* == NAN_ATTR_CLUSTER, */
-	WL_NAN_XTLV_VENDOR = 221,	/* == NAN_ATTR_VENDOR, */
-#endif
-	/* 0x02 ~ 0xFF: reserved. In case to use with the same data format as NAN attribute TLV */
-	/* 0x100 ~ : private TLV ID defined just for NAN command */
-	/* common types */
-	WL_NAN_XTLV_MAC_ADDR = 0x102,	/* used in various cmds */
-	WL_NAN_XTLV_REASON = 0x103,
-	WL_NAN_XTLV_ENABLED = 0x104,
-	/* explicit types, primarily for discovery engine iovars  */
-	WL_NAN_XTLV_SVC_PARAMS = 0x120,     /* Contains required params: wl_nan_disc_params_t */
-	WL_NAN_XTLV_MATCH_RX = 0x121,       /* Matching filter to evaluate on receive */
-	WL_NAN_XTLV_MATCH_TX = 0x122,       /* Matching filter to send */
-	WL_NAN_XTLV_SVC_INFO = 0x123,       /* Service specific info */
-	WL_NAN_XTLV_SVC_NAME = 0x124,       /* Optional UTF-8 service name, for debugging. */
-	WL_NAN_XTLV_INSTANCE_ID = 0x125,    /* Identifies unique publish or subscribe instance */
-	WL_NAN_XTLV_PRIORITY = 0x126,       /* used in transmit cmd context */
-	WL_NAN_XTLV_REQUESTOR_ID = 0x127,	/* Requestor instance ID */
-	WL_NAN_XTLV_VNDR = 0x128,		/* Vendor specific attribute */
-	WL_NAN_XTLV_SR_FILTER = 0x129,          /* Service Response Filter */
-	WL_NAN_XTLV_FOLLOWUP = 0x130,	/* Service Info for Follow-Up SDF */
-	WL_NAN_XTLV_PEER_INSTANCE_ID = 0x131, /* Used to parse remote instance Id */
-	/* explicit types, primarily for NAN MAC iovars   */
-	WL_NAN_XTLV_DW_LEN = 0x140,            /* discovery win length */
-	WL_NAN_XTLV_BCN_INTERVAL = 0x141,      /* beacon interval, both sync and descovery bcns?  */
-	WL_NAN_XTLV_CLUSTER_ID = 0x142,
-	WL_NAN_XTLV_IF_ADDR = 0x143,
-	WL_NAN_XTLV_MC_ADDR = 0x144,
-	WL_NAN_XTLV_ROLE = 0x145,
-	WL_NAN_XTLV_START = 0x146,
-
-	WL_NAN_XTLV_MASTER_PREF = 0x147,
-	WL_NAN_XTLV_DW_INTERVAL = 0x148,
-	WL_NAN_XTLV_PTBTT_OVERRIDE = 0x149,
-	/*  nan status command xtlvs  */
-	WL_NAN_XTLV_MAC_INITED = 0x14a,
-	WL_NAN_XTLV_MAC_ENABLED = 0x14b,
-	WL_NAN_XTLV_MAC_CHANSPEC = 0x14c,
-	WL_NAN_XTLV_MAC_AMR = 0x14d,	/* anchormaster rank u8 amr[8] */
-	WL_NAN_XTLV_MAC_HOPCNT = 0x14e,
-	WL_NAN_XTLV_MAC_AMBTT = 0x14f,
-	WL_NAN_XTLV_MAC_TXRATE = 0x150,
-	WL_NAN_XTLV_MAC_STATUS = 0x151,  /* xtlv payload is nan_status_t */
-	WL_NAN_XTLV_NAN_SCANPARAMS = 0x152,  /* payload is nan_scan_params_t */
-	WL_NAN_XTLV_DEBUGPARAMS = 0x153,  /* payload is nan_scan_params_t */
-	WL_NAN_XTLV_SUBSCR_ID = 0x154,   /* subscriber id  */
-	WL_NAN_XTLV_PUBLR_ID = 0x155,	/* publisher id */
-	WL_NAN_XTLV_EVENT_MASK = 0x156,
-	WL_NAN_XTLV_MASTER_RANK = 0x158,
-	WL_NAN_XTLV_WARM_UP_TIME = 0x159,
-	WL_NAN_XTLV_PM_OPTION = 0x15a,
-	WL_NAN_XTLV_OUI = 0x15b,	/* NAN OUI */
-	WL_NAN_XTLV_MAC_COUNT = 0x15c,  /* xtlv payload is nan_count_t */
-	/* nan timeslot management */
-	WL_NAN_XTLV_TSRESERVE = 0x160,
-	WL_NAN_XTLV_TSRELEASE = 0x161,
-	WL_NAN_XTLV_IDLE_DW_TIMEOUT = 0x162,
-	WL_NAN_XTLV_IDLE_DW_LEN = 0x163,
-	WL_NAN_XTLV_RND_FACTOR = 0x164,
-	WL_NAN_XTLV_SVC_DISC_TXTIME = 0x165,     /* svc disc frame tx time in DW */
-	WL_NAN_XTLV_OPERATING_BAND = 0x166,
-	WL_NAN_XTLV_STOP_BCN_TX = 0x167,
-	WL_NAN_XTLV_CONCUR_SCAN = 0x168,
-	WL_NAN_XTLV_DUMP_CLR_TYPE = 0x175, /* wl nan dump/clear subtype */
-	WL_NAN_XTLV_PEER_RSSI = 0x176, /* xtlv payload for wl nan dump rssi */
-	WL_NAN_XTLV_MAC_CHANSPEC_1 = 0x17A,	/* to get chanspec[1] */
-	WL_NAN_XTLV_DISC_RESULTS = 0x17B,        /* get disc results */
-	WL_NAN_XTLV_MAC_STATS = 0x17C /* xtlv payload for wl nan dump stats */
-};
-
-/* Flag bits for Publish and Subscribe (wl_nan_disc_params_t flags) */
-#define WL_NAN_RANGE_LIMITED           0x0040
-/* Bits specific to Publish */
-/* Unsolicited transmissions */
-#define WL_NAN_PUB_UNSOLICIT           0x1000
-/* Solicited transmissions */
-#define WL_NAN_PUB_SOLICIT             0x2000
-#define WL_NAN_PUB_BOTH                0x3000
-/* Set for broadcast solicited transmission
- * Do not set for unicast solicited transmission
- */
-#define WL_NAN_PUB_BCAST               0x4000
-/* Generate event on each solicited transmission */
-#define WL_NAN_PUB_EVENT               0x8000
-/* Used for one-time solicited Publish functions to indicate transmision occurred */
-#define WL_NAN_PUB_SOLICIT_PENDING	0x10000
-/* Follow-up frames */
-#define WL_NAN_FOLLOWUP			0x20000
-/* Bits specific to Subscribe */
-/* Active subscribe mode (Leave unset for passive) */
-#define WL_NAN_SUB_ACTIVE              0x1000
-
-/* Special values for time to live (ttl) parameter */
-#define WL_NAN_TTL_UNTIL_CANCEL	0xFFFFFFFF
-/* Publish -  runs until first transmission
- * Subscribe - runs until first  DiscoveryResult event
- */
-#define WL_NAN_TTL_FIRST	0
-
-/* The service hash (service id) is exactly this many bytes. */
-#define WL_NAN_SVC_HASH_LEN	6
-
-/* Number of hash functions per bloom filter */
-#define WL_NAN_HASHES_PER_BLOOM 4
-
-/* Instance ID type (unique identifier) */
-typedef uint8 wl_nan_instance_id_t;
-
-/* no. of max last disc results */
-#define WL_NAN_MAX_DISC_RESULTS	3
-
-/** Mandatory parameters for publish/subscribe iovars - NAN_TLV_SVC_PARAMS */
-typedef struct wl_nan_disc_params_s {
-	/* Periodicity of unsolicited/query transmissions, in DWs */
-	uint32 period;
-	/* Time to live in DWs */
-	uint32 ttl;
-	/* Flag bits */
-	uint32 flags;
-	/* Publish or subscribe service id, i.e. hash of the service name */
-	uint8 svc_hash[WL_NAN_SVC_HASH_LEN];
-	/* pad to make 4 byte alignment, can be used for something else in the future */
-	uint8 pad;
-	/* Publish or subscribe id */
-	wl_nan_instance_id_t instance_id;
-} wl_nan_disc_params_t;
-
-/* recent discovery results */
-typedef struct wl_nan_disc_result_s
-{
-	wl_nan_instance_id_t instance_id;	/* instance id of pub/sub req */
-	wl_nan_instance_id_t peer_instance_id;	/* peer instance id of pub/sub req/resp */
-	uint8 svc_hash[WL_NAN_SVC_HASH_LEN];	/* service descp string */
-	struct ether_addr peer_mac;	/* peer mac address */
-} wl_nan_disc_result_t;
-
-/* list of recent discovery results */
-typedef struct wl_nan_disc_results_s
-{
-	wl_nan_disc_result_t disc_result[WL_NAN_MAX_DISC_RESULTS];
-} wl_nan_disc_results_list_t;
-
-/*
-* desovery interface event structures *
-*/
-
-/* NAN Ranging */
-
-/* Bit defines for global flags */
-#define WL_NAN_RANGING_ENABLE		1 /* enable RTT */
-#define WL_NAN_RANGING_RANGED		2 /* Report to host if ranged as target */
-typedef struct nan_ranging_config {
-	uint32 chanspec;		/* Ranging chanspec */
-	uint16 timeslot;		/* NAN RTT start time slot  1-511 */
-	uint16 duration;		/* NAN RTT duration in ms */
-	struct ether_addr allow_mac;	/* peer initiated ranging: the allowed peer mac
-					 * address, a unicast (for one peer) or
-					 * a broadcast for all. Setting it to all zeros
-					 * means responding to none,same as not setting
-					 * the flag bit NAN_RANGING_RESPOND
-					 */
-	uint16 flags;
-} wl_nan_ranging_config_t;
-
-/* list of peers for self initiated ranging */
-/* Bit defines for per peer flags */
-#define WL_NAN_RANGING_REPORT (1<<0)	/* Enable reporting range to target */
-typedef struct nan_ranging_peer {
-	uint32 chanspec;		/* desired chanspec for this peer */
-	uint32 abitmap;			/* available bitmap */
-	struct ether_addr ea;		/* peer MAC address */
-	uint8 frmcnt;			/* frame count */
-	uint8 retrycnt;			/* retry count */
-	uint16 flags;			/* per peer flags, report or not */
-} wl_nan_ranging_peer_t;
-typedef struct nan_ranging_list {
-	uint8 count;			/* number of MAC addresses */
-	uint8 num_peers_done;		/* host set to 0, when read, shows number of peers
-					 * completed, success or fail
-					 */
-	uint8 num_dws;			/* time period to do the ranging, specified in dws */
-	uint8 reserve;			/* reserved field */
-	wl_nan_ranging_peer_t rp[1];	/* variable length array of peers */
-} wl_nan_ranging_list_t;
-
-/* ranging results, a list for self initiated ranging and one for peer initiated ranging */
-/* There will be one structure for each peer */
-#define WL_NAN_RANGING_STATUS_SUCCESS		1
-#define WL_NAN_RANGING_STATUS_FAIL			2
-#define WL_NAN_RANGING_STATUS_TIMEOUT		3
-#define WL_NAN_RANGING_STATUS_ABORT		4 /* with partial results if sounding count > 0 */
-typedef struct nan_ranging_result {
-	uint8 status;			/* 1: Success, 2: Fail 3: Timeout 4: Aborted */
-	uint8 sounding_count;		/* number of measurements completed (0 = failure) */
-	struct ether_addr ea;		/* initiator MAC address */
-	uint32 chanspec;		/* Chanspec where the ranging was done */
-	uint32 timestamp;		/* 32bits of the TSF timestamp ranging was completed at */
-	uint32 distance;		/* mean distance in meters expressed as Q4 number.
-					 * Only valid when sounding_count > 0. Examples:
-					 * 0x08 = 0.5m
-					 * 0x10 = 1m
-					 * 0x18 = 1.5m
-					 * set to 0xffffffff to indicate invalid number
-					 */
-	int32 rtt_var;			/* standard deviation in 10th of ns of RTTs measured.
-					 * Only valid when sounding_count > 0
-					 */
-	struct ether_addr tgtea;	/* target MAC address */
-} wl_nan_ranging_result_t;
-typedef struct nan_ranging_event_data {
-	uint8 mode;			/* 1: Result of host initiated ranging */
-					/* 2: Result of peer initiated ranging */
-	uint8 reserved;
-	uint8 success_count;		/* number of peers completed successfully */
-	uint8 count;			/* number of peers in the list */
-	wl_nan_ranging_result_t rr[1];	/* variable array of ranging peers */
-} wl_nan_ranging_event_data_t;
-enum {
-	WL_NAN_RSSI_DATA = 1,
-	WL_NAN_STATS_DATA = 2,
-/*
- * ***** ADD before this line ****
- */
-	WL_NAN_INVALID
-};
-
-typedef struct wl_nan_stats {
-	/* general */
-	uint32 cnt_dw; /* DW slots */
-	uint32 cnt_disc_bcn_sch; /* disc beacon slots */
-	uint32 cnt_amr_exp; /* count of ambtt expiries resetting roles */
-	uint32 cnt_bcn_upd; /* count of beacon template updates */
-	uint32 cnt_bcn_tx; /* count of sync & disc bcn tx */
-	uint32 cnt_bcn_rx; /* count of sync & disc bcn rx */
-	uint32 cnt_sync_bcn_tx; /* count of sync bcn tx within DW */
-	uint32 cnt_disc_bcn_tx; /* count of disc bcn tx */
-	uint32 cnt_sdftx_bcmc; /* count of bcast/mcast sdf tx */
-	uint32 cnt_sdftx_uc; /* count of unicast sdf tx */
-	uint32 cnt_sdftx_fail; /* count of unicast sdf tx fails */
-	uint32 cnt_sdf_rx; /* count of  sdf rx */
-	/* NAN roles */
-	uint32 cnt_am; /* anchor master */
-	uint32 cnt_master; /* master */
-	uint32 cnt_nms; /* non master sync */
-	uint32 cnt_nmns; /* non master non sync */
-	/* TX */
-	uint32 cnt_err_txtime; /* error in txtime */
-	uint32 cnt_err_unsch_tx; /* tx while not in DW/ disc bcn slot */
-	uint32 cnt_err_bcn_tx; /*  beacon tx error */
-	uint32 cnt_sync_bcn_tx_miss; /* no. of times time delta between 2 cosequetive
-						* sync beacons is more than dw interval
-						*/
-	/* SCANS */
-	uint32 cnt_mrg_scan; /* count of merge scans completed */
-	uint32 cnt_err_ms_rej; /* number of merge scan failed */
-	uint32 cnt_scan_results; /* no. of nan beacons scanned */
-	uint32 cnt_join_scan_rej; /* no. of join scans rejected */
-	uint32 cnt_nan_scan_abort; /* no. of join scans rejected */
-	/* enable/disable */
-	uint32 cnt_nan_enab; /* no. of times nan feature got enabled */
-	uint32 cnt_nan_disab; /* no. of times nan feature got disabled */
-} wl_nan_stats_t;
-
-#define WL_NAN_MAC_MAX_NAN_PEERS 6
-#define WL_NAN_MAC_MAX_RSSI_DATA_PER_PEER  10
-
-typedef struct wl_nan_nbr_rssi {
-	uint8 rx_chan; /* channel number on which bcn rcvd */
-	int rssi_raw;  /* received rssi value */
-	int rssi_avg;  /* normalized rssi value */
-} wl_nan_peer_rssi_t;
-
-typedef struct wl_nan_peer_rssi_entry {
-	struct ether_addr mac;  /* peer mac address */
-	uint8 flags;   /* TODO:rssi data order: latest first, oldest first etc */
-	uint8 rssi_cnt;   /* rssi data sample present */
-	wl_nan_peer_rssi_t rssi[WL_NAN_MAC_MAX_RSSI_DATA_PER_PEER]; /* RSSI data frm peer */
-} wl_nan_peer_rssi_entry_t;
-
-#define WL_NAN_PEER_RSSI      0x1
-#define WL_NAN_PEER_RSSI_LIST 0x2
-
-typedef struct wl_nan_nbr_rssi_data {
-	uint8 flags;   /* this is a list or single rssi data */
-	uint8 peer_cnt; /* number of peers */
-	uint16 pad; /* padding */
-	wl_nan_peer_rssi_entry_t peers[1]; /* peers data list */
-} wl_nan_peer_rssi_data_t;
-
-/* ********************* end of NAN section ******************************** */
-#endif /* WL_NAN */
-
-
-#define RSSI_THRESHOLD_SIZE 16
-#define MAX_IMP_RESP_SIZE 256
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_rssi_bias {
-	int32		version;			/* version */
-	int32		threshold[RSSI_THRESHOLD_SIZE];	/* threshold */
-	int32		peak_offset;			/* peak offset */
-	int32		bias;				/* rssi bias */
-	int32		gd_delta;			/* GD - GD_ADJ */
-	int32		imp_resp[MAX_IMP_RESP_SIZE];	/* (Hi*Hi)+(Hr*Hr) */
-} BWL_POST_PACKED_STRUCT wl_proxd_rssi_bias_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_rssi_bias_avg {
-	int32		avg_threshold[RSSI_THRESHOLD_SIZE];	/* avg threshold */
-	int32		avg_peak_offset;			/* avg peak offset */
-	int32		avg_rssi;				/* avg rssi */
-	int32		avg_bias;				/* avg bias */
-} BWL_POST_PACKED_STRUCT wl_proxd_rssi_bias_avg_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_info {
-	uint16		type;	 /* type: 0 channel table, 1 channel smoothing table, 2 and 3 seq */
-	uint16		index;		/* The current frame index, from 1 to total_frames. */
-	uint16		tof_cmd;	/* M_TOF_CMD      */
-	uint16		tof_rsp;	/* M_TOF_RSP      */
-	uint16		tof_avb_rxl;	/* M_TOF_AVB_RX_L */
-	uint16		tof_avb_rxh;	/* M_TOF_AVB_RX_H */
-	uint16		tof_avb_txl;	/* M_TOF_AVB_TX_L */
-	uint16		tof_avb_txh;	/* M_TOF_AVB_TX_H */
-	uint16		tof_id;		/* M_TOF_ID */
-	uint8		tof_frame_type;
-	uint8		tof_frame_bw;
-	int8		tof_rssi;
-	int32		tof_cfo;
-	int32		gd_adj_ns;	/* gound delay */
-	int32		gd_h_adj_ns;	/* group delay + threshold crossing */
-#ifdef RSSI_REFINE
-	wl_proxd_rssi_bias_t rssi_bias; /* RSSI refinement info */
-#endif
-	int16		nfft;		/* number of samples stored in H */
-
-} BWL_POST_PACKED_STRUCT wl_proxd_collect_info_t;
-
-#define k_tof_collect_H_pad  1
-#define k_tof_collect_H_size (256+16+k_tof_collect_H_pad)
-#define k_tof_collect_Hraw_size (2*k_tof_collect_H_size)
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_data {
-	wl_proxd_collect_info_t  info;
-	uint32	H[k_tof_collect_H_size]; /* raw data read from phy used to adjust timestamps */
-
-} BWL_POST_PACKED_STRUCT wl_proxd_collect_data_t;
-
-typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_debug_data {
-	uint8		count;		/* number of packets */
-	uint8		stage;		/* state machone stage */
-	uint8		received;	/* received or txed */
-	uint8		paket_type;	/* packet type */
-	uint8		category;	/* category field */
-	uint8		action;		/* action field */
-	uint8		token;		/* token number */
-	uint8		follow_token;	/* following token number */
-	uint16		index;		/* index of the packet */
-	uint16		tof_cmd;	/* M_TOF_CMD */
-	uint16		tof_rsp;	/* M_TOF_RSP */
-	uint16		tof_avb_rxl;	/* M_TOF_AVB_RX_L */
-	uint16		tof_avb_rxh;	/* M_TOF_AVB_RX_H */
-	uint16		tof_avb_txl;	/* M_TOF_AVB_TX_L */
-	uint16		tof_avb_txh;	/* M_TOF_AVB_TX_H */
-	uint16		tof_id;		/* M_TOF_ID */
-	uint16		tof_status0;	/* M_TOF_STATUS_0 */
-	uint16		tof_status2;	/* M_TOF_STATUS_2 */
-	uint16		tof_chsm0;	/* M_TOF_CHNSM_0 */
-	uint16		tof_phyctl0;	/* M_TOF_PHYCTL0 */
-	uint16		tof_phyctl1;	/* M_TOF_PHYCTL1 */
-	uint16		tof_phyctl2;	/* M_TOF_PHYCTL2 */
-	uint16		tof_lsig;	/* M_TOF_LSIG */
-	uint16		tof_vhta0;	/* M_TOF_VHTA0 */
-	uint16		tof_vhta1;	/* M_TOF_VHTA1 */
-	uint16		tof_vhta2;	/* M_TOF_VHTA2 */
-	uint16		tof_vhtb0;	/* M_TOF_VHTB0 */
-	uint16		tof_vhtb1;	/* M_TOF_VHTB1 */
-	uint16		tof_apmductl;	/* M_TOF_AMPDU_CTL */
-	uint16		tof_apmdudlim;	/* M_TOF_AMPDU_DLIM */
-	uint16		tof_apmdulen;	/* M_TOF_AMPDU_LEN */
-} BWL_POST_PACKED_STRUCT wl_proxd_debug_data_t;
-
-/* version of the wl_wsec_info structure */
-#define WL_WSEC_INFO_VERSION 0x01
-
-/* start enum value for BSS properties */
-#define WL_WSEC_INFO_BSS_BASE 0x0100
-
-/* size of len and type fields of wl_wsec_info_tlv_t struct */
-#define WL_WSEC_INFO_TLV_HDR_LEN OFFSETOF(wl_wsec_info_tlv_t, data)
-
-/* Allowed wl_wsec_info properties; not all of them may be supported. */
-typedef enum {
-	WL_WSEC_INFO_NONE = 0,
-	WL_WSEC_INFO_MAX_KEYS = 1,
-	WL_WSEC_INFO_NUM_KEYS = 2,
-	WL_WSEC_INFO_NUM_HW_KEYS = 3,
-	WL_WSEC_INFO_MAX_KEY_IDX = 4,
-	WL_WSEC_INFO_NUM_REPLAY_CNTRS = 5,
-	WL_WSEC_INFO_SUPPORTED_ALGOS = 6,
-	WL_WSEC_INFO_MAX_KEY_LEN = 7,
-	WL_WSEC_INFO_FLAGS = 8,
-	/* add global/per-wlc properties above */
-	WL_WSEC_INFO_BSS_FLAGS = (WL_WSEC_INFO_BSS_BASE + 1),
-	WL_WSEC_INFO_BSS_WSEC = (WL_WSEC_INFO_BSS_BASE + 2),
-	WL_WSEC_INFO_BSS_TX_KEY_ID = (WL_WSEC_INFO_BSS_BASE + 3),
-	WL_WSEC_INFO_BSS_ALGO = (WL_WSEC_INFO_BSS_BASE + 4),
-	WL_WSEC_INFO_BSS_KEY_LEN = (WL_WSEC_INFO_BSS_BASE + 5),
-	/* add per-BSS properties above */
-	WL_WSEC_INFO_MAX = 0xffff
-} wl_wsec_info_type_t;
-
-/* tlv used to return wl_wsec_info properties */
-typedef struct {
-	uint16 type;
-	uint16 len;		/* data length */
-	uint8 data[1];	/* data follows */
-} wl_wsec_info_tlv_t;
-
-/* input/output data type for wsec_info iovar */
-typedef struct wl_wsec_info {
-	uint8 version; /* structure version */
-	uint8 pad[2];
-	uint8 num_tlvs;
-	wl_wsec_info_tlv_t tlvs[1]; /* tlv data follows */
-} wl_wsec_info_t;
-
-/*
- * scan MAC definitions
- */
-
-/* common iovar struct */
-typedef struct wl_scanmac {
-	uint16 subcmd_id;	/* subcommand id */
-	uint16 len;		/* total length of data[] */
-	uint8 data[1];		/* subcommand data */
-} wl_scanmac_t;
-
-/* subcommand ids */
-#define WL_SCANMAC_SUBCMD_ENABLE   0
-#define WL_SCANMAC_SUBCMD_BSSCFG   1   /* only GET supported */
-#define WL_SCANMAC_SUBCMD_CONFIG   2
-
-/* scanmac enable data struct */
-typedef struct wl_scanmac_enable {
-	uint8 enable;	/* 1 - enable, 0 - disable */
-	uint8 pad[3];	/* 4-byte struct alignment */
-} wl_scanmac_enable_t;
-
-/* scanmac bsscfg data struct */
-typedef struct wl_scanmac_bsscfg {
-	uint32 bsscfg;	/* bsscfg index */
-} wl_scanmac_bsscfg_t;
-
-/* scanmac config data struct */
-typedef struct wl_scanmac_config {
-	struct ether_addr mac;	/* 6 bytes of MAC address or MAC prefix (i.e. OUI) */
-	struct ether_addr random_mask;	/* randomized bits on each scan */
-	uint16 scan_bitmap;	/* scans to use this MAC address */
-	uint8 pad[2];	/* 4-byte struct alignment */
-} wl_scanmac_config_t;
-
-/* scan bitmap */
-#define WL_SCANMAC_SCAN_UNASSOC		(0x01 << 0)	/* unassociated scans */
-#define WL_SCANMAC_SCAN_ASSOC_ROAM	(0x01 << 1)	/* associated roam scans */
-#define WL_SCANMAC_SCAN_ASSOC_PNO	(0x01 << 2)	/* associated PNO scans */
-#define WL_SCANMAC_SCAN_ASSOC_HOST	(0x01 << 3)	/* associated host scans */
-
-/* no default structure packing */
-#include <packed_section_end.h>
-
-enum rssi_reason {
-	RSSI_REASON_UNKNOW = 0,
-	RSSI_REASON_LOWRSSI = 1,
-	RSSI_REASON_NSYC = 2,
-	RSSI_REASON_TIMEOUT = 3
-};
-
-enum tof_reason {
-	TOF_REASON_OK = 0,
-	TOF_REASON_REQEND = 1,
-	TOF_REASON_TIMEOUT = 2,
-	TOF_REASON_NOACK = 3,
-	TOF_REASON_INVALIDAVB = 4,
-	TOF_REASON_INITIAL = 5,
-	TOF_REASON_ABORT = 6
-};
-
-enum rssi_state {
-	RSSI_STATE_POLL = 0,
-	RSSI_STATE_TPAIRING = 1,
-	RSSI_STATE_IPAIRING = 2,
-	RSSI_STATE_THANDSHAKE = 3,
-	RSSI_STATE_IHANDSHAKE = 4,
-	RSSI_STATE_CONFIRMED = 5,
-	RSSI_STATE_PIPELINE = 6,
-	RSSI_STATE_NEGMODE = 7,
-	RSSI_STATE_MONITOR = 8,
-	RSSI_STATE_LAST = 9
-};
-
-enum tof_state {
-	TOF_STATE_IDLE	 = 0,
-	TOF_STATE_IWAITM = 1,
-	TOF_STATE_TWAITM = 2,
-	TOF_STATE_ILEGACY = 3,
-	TOF_STATE_IWAITCL = 4,
-	TOF_STATE_TWAITCL = 5,
-	TOF_STATE_ICONFIRM = 6,
-	TOF_STATE_IREPORT = 7
-};
-
-enum tof_mode_type {
-	TOF_LEGACY_UNKNOWN	= 0,
-	TOF_LEGACY_AP		= 1,
-	TOF_NONLEGACY_AP	= 2
-};
-
-enum tof_way_type {
-	TOF_TYPE_ONE_WAY = 0,
-	TOF_TYPE_TWO_WAY = 1,
-	TOF_TYPE_REPORT = 2
-};
-
-enum tof_rate_type {
-	TOF_FRAME_RATE_VHT = 0,
-	TOF_FRAME_RATE_LEGACY = 1
-};
-
-#define TOF_ADJ_TYPE_NUM	4	/* number of assisted timestamp adjustment */
-enum tof_adj_mode {
-	TOF_ADJ_SOFTWARE = 0,
-	TOF_ADJ_HARDWARE = 1,
-	TOF_ADJ_SEQ = 2,
-	TOF_ADJ_NONE = 3
-};
-
-#define FRAME_TYPE_NUM		4	/* number of frame type */
-enum frame_type {
-	FRAME_TYPE_CCK	= 0,
-	FRAME_TYPE_OFDM	= 1,
-	FRAME_TYPE_11N	= 2,
-	FRAME_TYPE_11AC	= 3
-};
-
-typedef struct wl_proxd_status_iovar {
-	uint16			method;				/* method */
-	uint8			mode;				/* mode */
-	uint8			peermode;			/* peer mode */
-	uint8			state;				/* state */
-	uint8			reason;				/* reason code */
-	uint32			distance;			/* distance */
-	uint32			txcnt;				/* tx pkt counter */
-	uint32			rxcnt;				/* rx pkt counter */
-	struct ether_addr	peer;				/* peer mac address */
-	int8			avg_rssi;			/* average rssi */
-	int8			hi_rssi;			/* highest rssi */
-	int8			low_rssi;			/* lowest rssi */
-	uint32			dbgstatus;			/* debug status */
-	uint16			frame_type_cnt[FRAME_TYPE_NUM];	/* frame types */
-	uint8			adj_type_cnt[TOF_ADJ_TYPE_NUM];	/* adj types HW/SW */
-} wl_proxd_status_iovar_t;
-
-#ifdef NET_DETECT
-typedef struct net_detect_adapter_features {
-	bool	wowl_enabled;
-	bool	net_detect_enabled;
-	bool	nlo_enabled;
-} net_detect_adapter_features_t;
-
-typedef enum net_detect_bss_type {
-	nd_bss_any = 0,
-	nd_ibss,
-	nd_ess
-} net_detect_bss_type_t;
-
-typedef struct net_detect_profile {
-	wlc_ssid_t		ssid;
-	net_detect_bss_type_t   bss_type;	/* Ignore for now since Phase 1 is only for ESS */
-	uint32			cipher_type;	/* DOT11_CIPHER_ALGORITHM enumeration values */
-	uint32			auth_type;	/* DOT11_AUTH_ALGORITHM enumeration values */
-} net_detect_profile_t;
-
-typedef struct net_detect_profile_list {
-	uint32			num_nd_profiles;
-	net_detect_profile_t	nd_profile[0];
-} net_detect_profile_list_t;
-
-typedef struct net_detect_config {
-	bool			    nd_enabled;
-	uint32			    scan_interval;
-	uint32			    wait_period;
-	bool			    wake_if_connected;
-	bool			    wake_if_disconnected;
-	net_detect_profile_list_t   nd_profile_list;
-} net_detect_config_t;
-
-typedef enum net_detect_wake_reason {
-	nd_reason_unknown,
-	nd_net_detected,
-	nd_wowl_event,
-	nd_ucode_error
-} net_detect_wake_reason_t;
-
-typedef struct net_detect_wake_data {
-	net_detect_wake_reason_t    nd_wake_reason;
-	uint32			    nd_wake_date_length;
-	uint8			    nd_wake_data[0];	    /* Wake data (currently unused) */
-} net_detect_wake_data_t;
-
-#endif /* NET_DETECT */
-
-/* (unversioned, deprecated) */
-typedef struct bcnreq {
-	uint8 bcn_mode;
-	int dur;
-	int channel;
-	struct ether_addr da;
-	uint16 random_int;
-	wlc_ssid_t ssid;
-	uint16 reps;
-} bcnreq_t;
-
-#define WL_RRM_BCN_REQ_VER		1
-typedef struct bcn_req {
-	uint8 version;
-	uint8 bcn_mode;
-	uint8 pad_1[2];
-	int32 dur;
-	int32 channel;
-	struct ether_addr da;
-	uint16 random_int;
-	wlc_ssid_t ssid;
-	uint16 reps;
-	uint8 req_elements;
-	uint8 pad_2;
-	chanspec_list_t chspec_list;
-} bcn_req_t;
-
-typedef struct rrmreq {
-	struct ether_addr da;
-	uint8 reg;
-	uint8 chan;
-	uint16 random_int;
-	uint16 dur;
-	uint16 reps;
-} rrmreq_t;
-
-typedef struct framereq {
-	struct ether_addr da;
-	uint8 reg;
-	uint8 chan;
-	uint16 random_int;
-	uint16 dur;
-	struct ether_addr ta;
-	uint16 reps;
-} framereq_t;
-
-typedef struct statreq {
-	struct ether_addr da;
-	struct ether_addr peer;
-	uint16 random_int;
-	uint16 dur;
-	uint8 group_id;
-	uint16 reps;
-} statreq_t;
-
-#define WL_RRM_RPT_VER		0
-#define WL_RRM_RPT_MAX_PAYLOAD	256
-#define WL_RRM_RPT_MIN_PAYLOAD	7
-#define WL_RRM_RPT_FALG_ERR	0
-#define WL_RRM_RPT_FALG_GRP_ID_PROPR	(1 << 0)
-#define WL_RRM_RPT_FALG_GRP_ID_0	(1 << 1)
-typedef struct {
-	uint16 ver;		/* version */
-	struct ether_addr addr;	/* STA MAC addr */
-	uint32 timestamp;	/* timestamp of the report */
-	uint16 flag;		/* flag */
-	uint16 len;		/* length of payload data */
-	unsigned char data[WL_RRM_RPT_MAX_PAYLOAD];
-} statrpt_t;
-
-typedef struct wlc_l2keepalive_ol_params {
-	uint8	flags;
-	uint8	prio;
-	uint16	period_ms;
-} wlc_l2keepalive_ol_params_t;
-
-typedef struct wlc_dwds_config {
-	uint32		enable;
-	uint32		mode; /* STA/AP interface */
-	struct ether_addr ea;
-} wlc_dwds_config_t;
-
-typedef struct wl_el_set_params_s {
-	uint8 set;	/* Set number */
-	uint32 size;	/* Size to make/expand */
-} wl_el_set_params_t;
-
-typedef struct wl_el_tag_params_s {
-	uint16 tag;
-	uint8 set;
-	uint8 flags;
-} wl_el_tag_params_t;
-
-/* Video Traffic Interference Monitor config */
-#define INTFER_VERSION		1
-typedef struct wl_intfer_params {
-	uint16 version;			/* version */
-	uint8 period;			/* sample period */
-	uint8 cnt;			/* sample cnt */
-	uint8 txfail_thresh;	/* non-TCP txfail threshold */
-	uint8 tcptxfail_thresh;	/* tcptxfail threshold */
-} wl_intfer_params_t;
-
-typedef struct wl_staprio_cfg {
-	struct ether_addr ea;	/* mac addr */
-	uint8 prio;		/* scb priority */
-} wl_staprio_cfg_t;
-
-typedef enum wl_stamon_cfg_cmd_type {
-	STAMON_CFG_CMD_DEL = 0,
-	STAMON_CFG_CMD_ADD = 1
-} wl_stamon_cfg_cmd_type_t;
-
-typedef struct wlc_stamon_sta_config {
-	wl_stamon_cfg_cmd_type_t cmd; /* 0 - delete, 1 - add */
-	struct ether_addr ea;
-} wlc_stamon_sta_config_t;
-
-#ifdef SR_DEBUG
-typedef struct /* pmu_reg */{
-	uint32  pmu_control;
-	uint32  pmu_capabilities;
-	uint32  pmu_status;
-	uint32  res_state;
-	uint32  res_pending;
-	uint32  pmu_timer1;
-	uint32  min_res_mask;
-	uint32  max_res_mask;
-	uint32  pmu_chipcontrol1[4];
-	uint32  pmu_regcontrol[5];
-	uint32  pmu_pllcontrol[5];
-	uint32  pmu_rsrc_up_down_timer[31];
-	uint32  rsrc_dep_mask[31];
-} pmu_reg_t;
-#endif /* pmu_reg */
-
-typedef struct wl_taf_define {
-	struct ether_addr ea;	/* STA MAC or 0xFF... */
-	uint16 version;         /* version */
-	uint32 sch;             /* method index */
-	uint32 prio;            /* priority */
-	uint32 misc;            /* used for return value */
-	char   text[1];         /* used to pass and return ascii text */
-} wl_taf_define_t;
-
-/* Received Beacons lengths information */
-#define WL_LAST_BCNS_INFO_FIXED_LEN		OFFSETOF(wlc_bcn_len_hist_t, bcnlen_ring)
-typedef struct wlc_bcn_len_hist {
-	uint16	ver;				/* version field */
-	uint16	cur_index;			/* current pointed index in ring buffer */
-	uint32	max_bcnlen;		/* Max beacon length received */
-	uint32	min_bcnlen;		/* Min beacon length received */
-	uint32	ringbuff_len;		/* Length of the ring buffer 'bcnlen_ring' */
-	uint32	bcnlen_ring[1];	/* ring buffer storing received beacon lengths */
-} wlc_bcn_len_hist_t;
-
-/* WDS net interface types */
-#define WL_WDSIFTYPE_NONE  0x0 /* The interface type is neither WDS nor DWDS. */
-#define WL_WDSIFTYPE_WDS   0x1 /* The interface is WDS type. */
-#define WL_WDSIFTYPE_DWDS  0x2 /* The interface is DWDS type. */
-
-typedef struct wl_bssload_static {
-	bool is_static;
-	uint16 sta_count;
-	uint8 chan_util;
-	uint16 aac;
-} wl_bssload_static_t;
-
-
-/* IO Var Operations - the Value of iov_op In wlc_ap_doiovar */
-typedef enum wlc_ap_iov_operation {
-	WLC_AP_IOV_OP_DELETE                   = -1,
-	WLC_AP_IOV_OP_DISABLE                  = 0,
-	WLC_AP_IOV_OP_ENABLE                   = 1,
-	WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE  = 2,
-	WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE = 3,
-	WLC_AP_IOV_OP_MOVE                     = 4
-} wlc_ap_iov_oper_t;
-
-/* LTE coex info */
-/* Analogue of HCI Set MWS Signaling cmd */
-typedef struct {
-	uint16	mws_rx_assert_offset;
-	uint16	mws_rx_assert_jitter;
-	uint16	mws_rx_deassert_offset;
-	uint16	mws_rx_deassert_jitter;
-	uint16	mws_tx_assert_offset;
-	uint16	mws_tx_assert_jitter;
-	uint16	mws_tx_deassert_offset;
-	uint16	mws_tx_deassert_jitter;
-	uint16	mws_pattern_assert_offset;
-	uint16	mws_pattern_assert_jitter;
-	uint16	mws_inact_dur_assert_offset;
-	uint16	mws_inact_dur_assert_jitter;
-	uint16	mws_scan_freq_assert_offset;
-	uint16	mws_scan_freq_assert_jitter;
-	uint16	mws_prio_assert_offset_req;
-} wci2_config_t;
-
-/* Analogue of HCI MWS Channel Params */
-typedef struct {
-	uint16	mws_rx_center_freq; /* MHz */
-	uint16	mws_tx_center_freq;
-	uint16	mws_rx_channel_bw;  /* KHz */
-	uint16	mws_tx_channel_bw;
-	uint8	mws_channel_en;
-	uint8	mws_channel_type;   /* Don't care for WLAN? */
-} mws_params_t;
-
-/* MWS wci2 message */
-typedef struct {
-	uint8	mws_wci2_data; /* BT-SIG msg */
-	uint16	mws_wci2_interval; /* Interval in us */
-	uint16	mws_wci2_repeat; /* No of msgs to send */
-} mws_wci2_msg_t;
-
-typedef struct {
-	uint32 config;	/* MODE: AUTO (-1), Disable (0), Enable (1) */
-	uint32 status;	/* Current state: Disabled (0), Enabled (1) */
-} wl_config_t;
-
-#define WLC_RSDB_MODE_AUTO_MASK 0x80
-#define WLC_RSDB_EXTRACT_MODE(val) ((int8)((val) & (~(WLC_RSDB_MODE_AUTO_MASK))))
-
-#define	WL_IF_STATS_T_VERSION 1	/* current version of wl_if_stats structure */
-
-/* per interface counters */
-typedef struct wl_if_stats {
-	uint16	version;		/* version of the structure */
-	uint16	length;			/* length of the entire structure */
-	uint32	PAD;			/* padding */
-
-	/* transmit stat counters */
-	uint64	txframe;		/* tx data frames */
-	uint64	txbyte;			/* tx data bytes */
-	uint64	txerror;		/* tx data errors (derived: sum of others) */
-	uint64  txnobuf;		/* tx out of buffer errors */
-	uint64  txrunt;			/* tx runt frames */
-	uint64  txfail;			/* tx failed frames */
-	uint64	txretry;		/* tx retry frames */
-	uint64	txretrie;		/* tx multiple retry frames */
-	uint64	txfrmsnt;		/* tx sent frames */
-	uint64	txmulti;		/* tx mulitcast sent frames */
-	uint64	txfrag;			/* tx fragments sent */
-
-	/* receive stat counters */
-	uint64	rxframe;		/* rx data frames */
-	uint64	rxbyte;			/* rx data bytes */
-	uint64	rxerror;		/* rx data errors (derived: sum of others) */
-	uint64	rxnobuf;		/* rx out of buffer errors */
-	uint64  rxrunt;			/* rx runt frames */
-	uint64  rxfragerr;		/* rx fragment errors */
-	uint64	rxmulti;		/* rx multicast frames */
-}
-wl_if_stats_t;
-
-typedef struct wl_band {
-	uint16		bandtype;		/* WL_BAND_2G, WL_BAND_5G */
-	uint16		bandunit;		/* bandstate[] index */
-	uint16		phytype;		/* phytype */
-	uint16		phyrev;
-}
-wl_band_t;
-
-#define	WL_WLC_VERSION_T_VERSION 1 /* current version of wlc_version structure */
-
-/* wlc interface version */
-typedef struct wl_wlc_version {
-	uint16	version;		/* version of the structure */
-	uint16	length;			/* length of the entire structure */
-
-	/* epi version numbers */
-	uint16	epi_ver_major;		/* epi major version number */
-	uint16	epi_ver_minor;		/* epi minor version number */
-	uint16	epi_rc_num;		/* epi RC number */
-	uint16	epi_incr_num;		/* epi increment number */
-
-	/* wlc interface version numbers */
-	uint16	wlc_ver_major;		/* wlc interface major version number */
-	uint16	wlc_ver_minor;		/* wlc interface minor version number */
-}
-wl_wlc_version_t;
-
-/* Version of WLC interface to be returned as a part of wl_wlc_version structure.
- * For the discussion related to versions update policy refer to
- * http://hwnbu-twiki.broadcom.com/bin/view/Mwgroup/WlShimAbstractionLayer
- * For now the policy is to increment WLC_VERSION_MAJOR each time
- * there is a change that involves both WLC layer and per-port layer.
- * WLC_VERSION_MINOR is currently not in use.
- */
-#define WLC_VERSION_MAJOR	3
-#define WLC_VERSION_MINOR	0
-
-/* begin proxd definitions */
-#include <packed_section_start.h>
-
-#define WL_PROXD_API_VERSION 0x0300	/* version 3.0 */
-
-/* Minimum supported API version */
-#define WL_PROXD_API_MIN_VERSION 0x0300
-
-/* proximity detection methods */
-enum {
-	WL_PROXD_METHOD_NONE	= 0,
-	WL_PROXD_METHOD_RSVD1	= 1, /* backward compatibility - RSSI, not supported */
-	WL_PROXD_METHOD_TOF		= 2,
-	WL_PROXD_METHOD_RSVD2	= 3, /* 11v only - if needed */
-	WL_PROXD_METHOD_FTM		= 4, /* IEEE rev mc/2014 */
-	WL_PROXD_METHOD_MAX
-};
-typedef int16 wl_proxd_method_t;
-
-/* global and method configuration flags */
-enum {
-	WL_PROXD_FLAG_NONE 			= 0x00000000,
-	WL_PROXD_FLAG_RX_ENABLED 	= 0x00000001, /* respond to requests */
-	WL_PROXD_FLAG_RX_RANGE_REQ	= 0x00000002, /* 11mc range requests enabled */
-	WL_PROXD_FLAG_TX_LCI		= 0x00000004, /* transmit location, if available */
-	WL_PROXD_FLAG_TX_CIVIC		= 0x00000008, /* tx civic loc, if available */
-	WL_PROXD_FLAG_RX_AUTO_BURST	= 0x00000010, /* respond to requests w/o host action */
-	WL_PROXD_FLAG_TX_AUTO_BURST	= 0x00000020, /* continue requests w/o host action */
-	WL_PROXD_FLAG_AVAIL_PUBLISH = 0x00000040, /* publish availability */
-	WL_PROXD_FLAG_AVAIL_SCHEDULE = 0x00000080, /* schedule using availability */
-	WL_PROXD_FLAG_ALL 			= 0xffffffff
-};
-typedef uint32 wl_proxd_flags_t;
-
-#define WL_PROXD_FLAGS_AVAIL (WL_PROXD_FLAG_AVAIL_PUBLISH | \
-	WL_PROXD_FLAG_AVAIL_SCHEDULE)
-
-/* session flags */
-enum {
-	WL_PROXD_SESSION_FLAG_NONE 			= 0x00000000,  /* no flags */
-	WL_PROXD_SESSION_FLAG_INITIATOR 	= 0x00000001,  /* local device is initiator */
-	WL_PROXD_SESSION_FLAG_TARGET 		= 0x00000002,  /* local device is target */
-	WL_PROXD_SESSION_FLAG_ONE_WAY		= 0x00000004,  /* (initiated) 1-way rtt */
-	WL_PROXD_SESSION_FLAG_AUTO_BURST	= 0x00000008,  /* created w/ rx_auto_burst */
-	WL_PROXD_SESSION_FLAG_PERSIST		= 0x00000010,  /* good until cancelled */
-	WL_PROXD_SESSION_FLAG_RTT_DETAIL	= 0x00000020,  /* rtt detail in results */
-	WL_PROXD_SESSION_FLAG_TOF_COMPAT	= 0x00000040,  /* TOF  compatibility - TBD */
-	WL_PROXD_SESSION_FLAG_AOA			= 0x00000080,  /* AOA along w/ RTT */
-	WL_PROXD_SESSION_FLAG_RX_AUTO_BURST	= 0x00000100,  /* Same as proxd flags above */
-	WL_PROXD_SESSION_FLAG_TX_AUTO_BURST	= 0x00000200,  /* Same as proxd flags above */
-	WL_PROXD_SESSION_FLAG_NAN_BSS		= 0x00000400,  /* Use NAN BSS, if applicable */
-	WL_PROXD_SESSION_FLAG_TS1			= 0x00000800,  /* e.g. FTM1 - cap or rx */
-	WL_PROXD_SESSION_FLAG_REPORT_FAILURE= 0x00002000, /* report failure to target */
-	WL_PROXD_SESSION_FLAG_INITIATOR_RPT	= 0x00004000, /* report distance to target */
-	WL_PROXD_SESSION_FLAG_NOCHANSWT		= 0x00008000, /* No channel switching */
-	WL_PROXD_SESSION_FLAG_NETRUAL		= 0x00010000, /* netrual mode */
-	WL_PROXD_SESSION_FLAG_SEQ_EN		= 0x00020000, /* Toast */
-	WL_PROXD_SESSION_FLAG_NO_PARAM_OVRD	= 0x00040000, /* no param override from target */
-	WL_PROXD_SESSION_FLAG_ASAP			= 0x00080000, /* ASAP session */
-	WL_PROXD_SESSION_FLAG_REQ_LCI		= 0x00100000, /* transmit LCI req */
-	WL_PROXD_SESSION_FLAG_REQ_CIV		= 0x00200000, /* transmit civic loc req */
-	WL_PROXD_SESSION_FLAG_COLLECT		= 0x80000000,	/* debug - collect */
-	WL_PROXD_SESSION_FLAG_ALL 			= 0xffffffff
-};
-typedef uint32 wl_proxd_session_flags_t;
-
-/* time units - mc supports up to 0.1ns resolution */
-enum {
-	WL_PROXD_TMU_TU			= 0,		/* 1024us */
-	WL_PROXD_TMU_SEC		= 1,
-	WL_PROXD_TMU_MILLI_SEC	= 2,
-	WL_PROXD_TMU_MICRO_SEC	= 3,
-	WL_PROXD_TMU_NANO_SEC	= 4,
-	WL_PROXD_TMU_PICO_SEC	= 5
-};
-typedef int16 wl_proxd_tmu_t;
-
-/* time interval e.g. 10ns */
-typedef struct wl_proxd_intvl {
-	uint32 intvl;
-	wl_proxd_tmu_t tmu;
-	uint8	pad[2];
-} wl_proxd_intvl_t;
-
-/* commands that can apply to proxd, method or a session */
-enum {
-	WL_PROXD_CMD_NONE				= 0,
-	WL_PROXD_CMD_GET_VERSION		= 1,
-	WL_PROXD_CMD_ENABLE 			= 2,
-	WL_PROXD_CMD_DISABLE 			= 3,
-	WL_PROXD_CMD_CONFIG 			= 4,
-	WL_PROXD_CMD_START_SESSION 		= 5,
-	WL_PROXD_CMD_BURST_REQUEST 		= 6,
-	WL_PROXD_CMD_STOP_SESSION 		= 7,
-	WL_PROXD_CMD_DELETE_SESSION 	= 8,
-	WL_PROXD_CMD_GET_RESULT 		= 9,
-	WL_PROXD_CMD_GET_INFO 			= 10,
-	WL_PROXD_CMD_GET_STATUS 		= 11,
-	WL_PROXD_CMD_GET_SESSIONS 		= 12,
-	WL_PROXD_CMD_GET_COUNTERS 		= 13,
-	WL_PROXD_CMD_CLEAR_COUNTERS 	= 14,
-	WL_PROXD_CMD_COLLECT 			= 15,
-	WL_PROXD_CMD_TUNE 				= 16,
-	WL_PROXD_CMD_DUMP 				= 17,
-	WL_PROXD_CMD_START_RANGING		= 18,
-	WL_PROXD_CMD_STOP_RANGING		= 19,
-	WL_PROXD_CMD_GET_RANGING_INFO	= 20,
-	WL_PROXD_CMD_IS_TLV_SUPPORTED	= 21,
-
-	WL_PROXD_CMD_MAX
-};
-typedef int16 wl_proxd_cmd_t;
-
-/* session ids:
- * id 0 is reserved
- * ids 1..0x7fff - allocated by host/app
- * 0x8000-0xffff - allocated by firmware, used for auto/rx
- */
-enum {
-	 WL_PROXD_SESSION_ID_GLOBAL = 0
-};
-
-#define WL_PROXD_SID_HOST_MAX 0x7fff
-#define WL_PROXD_SID_HOST_ALLOC(_sid) ((_sid) > 0 && (_sid) <= WL_PROXD_SID_HOST_MAX)
-
-/* maximum number sessions that can be allocated, may be less if tunable */
-#define WL_PROXD_MAX_SESSIONS 16
-
-typedef uint16 wl_proxd_session_id_t;
-
-/* status - TBD BCME_ vs proxd status - range reserved for BCME_ */
-enum {
-	WL_PROXD_E_POLICY			= -1045,
-	WL_PROXD_E_INCOMPLETE		= -1044,
-	WL_PROXD_E_OVERRIDDEN		= -1043,
-	WL_PROXD_E_ASAP_FAILED		= -1042,
-	WL_PROXD_E_NOTSTARTED		= -1041,
-	WL_PROXD_E_INVALIDAVB		= -1040,
-	WL_PROXD_E_INCAPABLE		= -1039,
-	WL_PROXD_E_MISMATCH			= -1038,
-	WL_PROXD_E_DUP_SESSION		= -1037,
-	WL_PROXD_E_REMOTE_FAIL		= -1036,
-	WL_PROXD_E_REMOTE_INCAPABLE = -1035,
-	WL_PROXD_E_SCHED_FAIL		= -1034,
-	WL_PROXD_E_PROTO			= -1033,
-	WL_PROXD_E_EXPIRED			= -1032,
-	WL_PROXD_E_TIMEOUT			= -1031,
-	WL_PROXD_E_NOACK			= -1030,
-	WL_PROXD_E_DEFERRED			= -1029,
-	WL_PROXD_E_INVALID_SID		= -1028,
-	WL_PROXD_E_REMOTE_CANCEL 	= -1027,
-	WL_PROXD_E_CANCELED			= -1026,	/* local */
-	WL_PROXD_E_INVALID_SESSION	= -1025,
-	WL_PROXD_E_BAD_STATE		= -1024,
-	WL_PROXD_E_ERROR			= -1,
-	WL_PROXD_E_OK				= 0
-};
-typedef int32 wl_proxd_status_t;
-
-/* session states */
-enum {
-	WL_PROXD_SESSION_STATE_NONE				= 0,
-	WL_PROXD_SESSION_STATE_CREATED			= 1,
-	WL_PROXD_SESSION_STATE_CONFIGURED		= 2,
-	WL_PROXD_SESSION_STATE_STARTED			= 3,
-	WL_PROXD_SESSION_STATE_DELAY			= 4,
-	WL_PROXD_SESSION_STATE_USER_WAIT		= 5,
-	WL_PROXD_SESSION_STATE_SCHED_WAIT		= 6,
-	WL_PROXD_SESSION_STATE_BURST			= 7,
-	WL_PROXD_SESSION_STATE_STOPPING			= 8,
-	WL_PROXD_SESSION_STATE_ENDED			= 9,
-	WL_PROXD_SESSION_STATE_DESTROYING		= -1
-};
-typedef int16 wl_proxd_session_state_t;
-
-/* RTT sample flags */
-enum {
-	WL_PROXD_RTT_SAMPLE_NONE 		= 0x00,
-	WL_PROXD_RTT_SAMPLE_DISCARD 	= 0x01
-};
-typedef uint8 wl_proxd_rtt_sample_flags_t;
-
-typedef struct wl_proxd_rtt_sample {
-	uint8				id;			/* id for the sample - non-zero */
-	wl_proxd_rtt_sample_flags_t	flags;
-	int16				rssi;
-	wl_proxd_intvl_t	rtt;		/* round trip time */
-	uint32 				ratespec;
-} wl_proxd_rtt_sample_t;
-
-/*  result flags */
-enum {
-	WL_PRXOD_RESULT_FLAG_NONE	= 0x0000,
-	WL_PROXD_RESULT_FLAG_NLOS	= 0x0001,	/* LOS - if available */
-	WL_PROXD_RESULT_FLAG_LOS    = 0x0002,	/* NLOS - if available */
-	WL_PROXD_RESULT_FLAG_FATAL	= 0x0004,	/* Fatal error during burst */
-	WL_PROXD_RESULT_FLAG_ALL 	= 0xffff
-};
-typedef int16 wl_proxd_result_flags_t;
-
-/* rtt measurement result */
-typedef struct wl_proxd_rtt_result {
-	wl_proxd_session_id_t			sid;
-	wl_proxd_result_flags_t 		flags;
-	wl_proxd_status_t				status;
-	struct ether_addr				peer;
-	wl_proxd_session_state_t 		state; 		/* current state */
-	union {
-		wl_proxd_intvl_t			retry_after; /* hint for errors */
-		wl_proxd_intvl_t			burst_duration; /* burst duration */
-	} u;
-	wl_proxd_rtt_sample_t			avg_rtt;
-	uint32							avg_dist;	/* 1/256m units */
-	uint16							sd_rtt;	/* RTT standard deviation */
-	uint8						num_valid_rtt; /* valid rtt cnt */
-	uint8						num_ftm; /* actual num of ftm cnt */
-	uint16							burst_num;	/* in a session */
-	uint16							num_rtt;	/* 0 if no detail */
-	wl_proxd_rtt_sample_t			rtt[1];		/* variable */
-} wl_proxd_rtt_result_t;
-
-/* aoa measurement result */
-typedef struct wl_proxd_aoa_result {
-	wl_proxd_session_id_t			sid;
-	wl_proxd_result_flags_t			flags;
-	wl_proxd_status_t				status;
-	struct ether_addr				peer;
-	wl_proxd_session_state_t 		state;
-	uint16							burst_num;
-	uint8							pad[2];
-	/* wl_proxd_aoa_sample_t sample_avg; TBD */
-} BWL_POST_PACKED_STRUCT wl_proxd_aoa_result_t;
-
-/* global stats */
-typedef struct wl_proxd_counters {
-	uint32 tx;					/* tx frame count */
-	uint32 rx;					/* rx frame count */
-	uint32 burst;				/* total number of burst */
-	uint32 sessions;			/* total number of sessions */
-	uint32 max_sessions;		/* max concurrency */
-	uint32 sched_fail;			/* scheduling failures */
-	uint32 timeouts;			/* timeouts */
-	uint32 protoerr;			/* protocol errors */
-	uint32 noack;				/* tx w/o ack */
-	uint32 txfail;				/* any tx falure */
-	uint32 lci_req_tx;			/* tx LCI requests */
-	uint32 lci_req_rx;			/* rx LCI requests */
-	uint32 lci_rep_tx;			/* tx LCI reports */
-	uint32 lci_rep_rx;			/* rx LCI reports */
-	uint32 civic_req_tx;		/* tx civic requests */
-	uint32 civic_req_rx;		/* rx civic requests */
-	uint32 civic_rep_tx;		/* tx civic reports */
-	uint32 civic_rep_rx;		/* rx civic reports */
-	uint32 rctx;				/* ranging contexts created */
-	uint32 rctx_done;			/* count of ranging done */
-	uint32 publish_err;     /* availability publishing errors */
-	uint32 on_chan;         /* count of scheduler onchan */
-	uint32 off_chan;        /* count of scheduler offchan */
-} wl_proxd_counters_t;
-
-typedef struct wl_proxd_counters wl_proxd_session_counters_t;
-
-enum {
-	WL_PROXD_CAP_NONE 		= 0x0000,
-	WL_PROXD_CAP_ALL 		= 0xffff
-};
-typedef int16 wl_proxd_caps_t;
-
-/* method capabilities */
-enum {
-	WL_PROXD_FTM_CAP_NONE = 0x0000,
-	WL_PROXD_FTM_CAP_FTM1 = 0x0001
-};
-typedef uint16 wl_proxd_ftm_caps_t;
-
-typedef struct BWL_PRE_PACKED_STRUCT wl_proxd_tlv_id_list {
-	uint16			num_ids;
-	uint16			ids[1];
-} BWL_POST_PACKED_STRUCT wl_proxd_tlv_id_list_t;
-
-typedef struct wl_proxd_session_id_list {
-	uint16 num_ids;
-	wl_proxd_session_id_t ids[1];
-} wl_proxd_session_id_list_t;
-
-/* tlvs returned for get_info on ftm method
- * configuration:
- * 		proxd flags
- *  	event mask
- *  	debug mask
- *  	session defaults (session tlvs)
- * status tlv - not supported for ftm method
- * info tlv
- */
-typedef struct wl_proxd_ftm_info {
-	wl_proxd_ftm_caps_t caps;
-	uint16 max_sessions;
-	uint16 num_sessions;
-	uint16 rx_max_burst;
-} wl_proxd_ftm_info_t;
-
-/* tlvs returned for get_info on session
- * session config (tlvs)
- * session info tlv
- */
-typedef struct wl_proxd_ftm_session_info {
-	uint16 sid;
-	uint8 bss_index;
-	uint8 pad;
-	struct ether_addr bssid;
-	wl_proxd_session_state_t state;
-	wl_proxd_status_t status;
-	uint16	burst_num;
-} wl_proxd_ftm_session_info_t;
-
-typedef struct wl_proxd_ftm_session_status {
-	uint16 sid;
-	wl_proxd_session_state_t state;
-	wl_proxd_status_t status;
-	uint16	burst_num;
-} wl_proxd_ftm_session_status_t;
-
-/* rrm range request */
-typedef struct wl_proxd_range_req {
-	uint16 			num_repeat;
-	uint16			init_delay_range;	/* in TUs */
-	uint8			pad;
-	uint8			num_nbr;			/* number of (possible) neighbors */
-	nbr_element_t   nbr[1];
-} wl_proxd_range_req_t;
-
-#define WL_PROXD_LCI_LAT_OFF 	0
-#define WL_PROXD_LCI_LONG_OFF 	5
-#define WL_PROXD_LCI_ALT_OFF 	10
-
-#define WL_PROXD_LCI_GET_LAT(_lci, _lat, _lat_err) { \
-	unsigned _off = WL_PROXD_LCI_LAT_OFF; \
-	_lat_err = (_lci)->data[(_off)] & 0x3f; \
-	_lat = (_lci)->data[(_off)+1]; \
-	_lat |= (_lci)->data[(_off)+2] << 8; \
-	_lat |= (_lci)->data[_(_off)+3] << 16; \
-	_lat |= (_lci)->data[(_off)+4] << 24; \
-	_lat <<= 2; \
-	_lat |= (_lci)->data[(_off)] >> 6; \
-}
-
-#define WL_PROXD_LCI_GET_LONG(_lci, _lcilong, _long_err) { \
-	unsigned _off = WL_PROXD_LCI_LONG_OFF; \
-	_long_err = (_lci)->data[(_off)] & 0x3f; \
-	_lcilong = (_lci)->data[(_off)+1]; \
-	_lcilong |= (_lci)->data[(_off)+2] << 8; \
-	_lcilong |= (_lci)->data[_(_off)+3] << 16; \
-	_lcilong |= (_lci)->data[(_off)+4] << 24; \
-	__lcilong <<= 2; \
-	_lcilong |= (_lci)->data[(_off)] >> 6; \
-}
-
-#define WL_PROXD_LCI_GET_ALT(_lci, _alt_type, _alt, _alt_err) { \
-	unsigned _off = WL_PROXD_LCI_ALT_OFF; \
-	_alt_type = (_lci)->data[_off] & 0x0f; \
-	_alt_err = (_lci)->data[(_off)] >> 4; \
-	_alt_err |= ((_lci)->data[(_off)+1] & 0x03) << 4; \
-	_alt = (_lci)->data[(_off)+2]; \
-	_alt |= (_lci)->data[(_off)+3] << 8; \
-	_alt |= (_lci)->data[_(_off)+4] << 16; \
-	_alt <<= 6; \
-	_alt |= (_lci)->data[(_off) + 1] >> 2; \
-}
-
-#define WL_PROXD_LCI_VERSION(_lci) ((_lci)->data[15] >> 6)
-
-/* availability. advertising mechanism bss specific */
-/* availablity flags */
-enum {
-	WL_PROXD_AVAIL_NONE = 0,
-	WL_PROXD_AVAIL_NAN_PUBLISHED = 0x0001,
-	WL_PROXD_AVAIL_SCHEDULED = 0x0002        /* scheduled by proxd */
-};
-typedef int16 wl_proxd_avail_flags_t;
-
-/* time reference */
-enum {
-	WL_PROXD_TREF_NONE = 0,
-	WL_PROXD_TREF_DEV_TSF = 1,
-	WL_PROXD_TREF_NAN_DW = 2,
-	WL_PROXD_TREF_TBTT = 3,
-	WL_PROXD_TREF_MAX		/* last entry */
-};
-typedef int16 wl_proxd_time_ref_t;
-
-/* proxd channel-time slot */
-typedef struct {
-	wl_proxd_intvl_t start;         /* from ref */
-	wl_proxd_intvl_t duration;      /* from start */
-	uint32  chanspec;
-} wl_proxd_time_slot_t;
-
-typedef struct wl_proxd_avail24 {
-	wl_proxd_avail_flags_t flags; /* for query only */
-	wl_proxd_time_ref_t time_ref;
-	uint16	max_slots; /* for query only */
-	uint16  num_slots;
-	wl_proxd_time_slot_t slots[1];	/* ROM compat - not used */
-	wl_proxd_intvl_t 	repeat;
-	wl_proxd_time_slot_t ts0[1];
-} wl_proxd_avail24_t;
-#define WL_PROXD_AVAIL24_TIMESLOT(_avail24, _i) (&(_avail24)->ts0[(_i)])
-#define WL_PROXD_AVAIL24_TIMESLOT_OFFSET(_avail24) OFFSETOF(wl_proxd_avail24_t, ts0)
-#define WL_PROXD_AVAIL24_TIMESLOTS(_avail24) WL_PROXD_AVAIL24_TIMESLOT(_avail24, 0)
-#define WL_PROXD_AVAIL24_SIZE(_avail24, _num_slots) (\
-	WL_PROXD_AVAIL24_TIMESLOT_OFFSET(_avail24) + \
-	(_num_slots) * sizeof(*WL_PROXD_AVAIL24_TIMESLOT(_avail24, 0)))
-
-typedef struct wl_proxd_avail {
-	wl_proxd_avail_flags_t flags; /* for query only */
-	wl_proxd_time_ref_t time_ref;
-	uint16	max_slots; /* for query only */
-	uint16  num_slots;
-	wl_proxd_intvl_t 	repeat;
-	wl_proxd_time_slot_t slots[1];
-} wl_proxd_avail_t;
-#define WL_PROXD_AVAIL_TIMESLOT(_avail, _i) (&(_avail)->slots[(_i)])
-#define WL_PROXD_AVAIL_TIMESLOT_OFFSET(_avail) OFFSETOF(wl_proxd_avail_t, slots)
-
-#define WL_PROXD_AVAIL_TIMESLOTS(_avail) WL_PROXD_AVAIL_TIMESLOT(_avail, 0)
-#define WL_PROXD_AVAIL_SIZE(_avail, _num_slots) (\
-	WL_PROXD_AVAIL_TIMESLOT_OFFSET(_avail) + \
-	(_num_slots) * sizeof(*WL_PROXD_AVAIL_TIMESLOT(_avail, 0)))
-
-/* collect support TBD */
-
-/* debugging */
-enum {
-	WL_PROXD_DEBUG_NONE		= 0x00000000,
-	WL_PROXD_DEBUG_LOG		= 0x00000001,
-	WL_PROXD_DEBUG_IOV		= 0x00000002,
-	WL_PROXD_DEBUG_EVENT	= 0x00000004,
-	WL_PROXD_DEBUG_SESSION	= 0x00000008,
-	WL_PROXD_DEBUG_PROTO	= 0x00000010,
-	WL_PROXD_DEBUG_SCHED	= 0x00000020,
-	WL_PROXD_DEBUG_RANGING	= 0x00000040,
-	WL_PROXD_DEBUG_ALL		= 0xffffffff
-};
-typedef uint32 wl_proxd_debug_mask_t;
-
-/* tlv IDs - data length 4 bytes unless overridden by type, alignment 32 bits */
-enum {
-	WL_PROXD_TLV_ID_NONE 			= 0,
-	WL_PROXD_TLV_ID_METHOD 			= 1,
-	WL_PROXD_TLV_ID_FLAGS 			= 2,
-	WL_PROXD_TLV_ID_CHANSPEC 		= 3,	/* note: uint32 */
-	WL_PROXD_TLV_ID_TX_POWER 		= 4,
-	WL_PROXD_TLV_ID_RATESPEC 		= 5,
-	WL_PROXD_TLV_ID_BURST_DURATION 	= 6, 	/* intvl - length of burst */
-	WL_PROXD_TLV_ID_BURST_PERIOD 	= 7,	/* intvl - between bursts */
-	WL_PROXD_TLV_ID_BURST_FTM_SEP 	= 8,	/* intvl - between FTMs */
-	WL_PROXD_TLV_ID_BURST_NUM_FTM 	= 9,	/* uint16 - per burst */
-	WL_PROXD_TLV_ID_NUM_BURST 		= 10,	/* uint16 */
-	WL_PROXD_TLV_ID_FTM_RETRIES 	= 11,	/* uint16 at FTM level */
-	WL_PROXD_TLV_ID_BSS_INDEX		= 12,	/* uint8 */
-	WL_PROXD_TLV_ID_BSSID 			= 13,
-	WL_PROXD_TLV_ID_INIT_DELAY 		= 14,  	/* intvl - optional, non-standalone only */
-	WL_PROXD_TLV_ID_BURST_TIMEOUT	= 15,	/* expect response within - intvl */
-	WL_PROXD_TLV_ID_EVENT_MASK 		= 16,	/* interested events - in/out */
-	WL_PROXD_TLV_ID_FLAGS_MASK 		= 17,	/* interested flags - in only */
-	WL_PROXD_TLV_ID_PEER_MAC		= 18,	/* mac address of peer */
-	WL_PROXD_TLV_ID_FTM_REQ			= 19,	/* dot11_ftm_req */
-	WL_PROXD_TLV_ID_LCI_REQ 		= 20,
-	WL_PROXD_TLV_ID_LCI 			= 21,
-	WL_PROXD_TLV_ID_CIVIC_REQ		= 22,
-	WL_PROXD_TLV_ID_CIVIC			= 23,
-	WL_PROXD_TLV_ID_AVAIL24			= 24,		/* ROM compatibility */
-	WL_PROXD_TLV_ID_SESSION_FLAGS	= 25,
-	WL_PROXD_TLV_ID_SESSION_FLAGS_MASK	= 26,	/* in only */
-	WL_PROXD_TLV_ID_RX_MAX_BURST = 27,		/* uint16 - limit bursts per session */
-	WL_PROXD_TLV_ID_RANGING_INFO	= 28,	/* ranging info */
-	WL_PROXD_TLV_ID_RANGING_FLAGS	= 29,	/* uint16 */
-	WL_PROXD_TLV_ID_RANGING_FLAGS_MASK	= 30,	/* uint16, in only */
-	WL_PROXD_TLV_ID_NAN_MAP_ID          = 31,
-	WL_PROXD_TLV_ID_DEV_ADDR            = 32,
-	WL_PROXD_TLV_ID_AVAIL			= 33,		/* wl_proxd_avail_t  */
-	WL_PROXD_TLV_ID_TLV_ID        = 34,    /* uint16 tlv-id */
-	WL_PROXD_TLV_ID_FTM_REQ_RETRIES  = 35, /* uint16 FTM request retries */
-
-	/* output - 512 + x */
-	WL_PROXD_TLV_ID_STATUS 			= 512,
-	WL_PROXD_TLV_ID_COUNTERS 		= 513,
-	WL_PROXD_TLV_ID_INFO 			= 514,
-	WL_PROXD_TLV_ID_RTT_RESULT 		= 515,
-	WL_PROXD_TLV_ID_AOA_RESULT		= 516,
-	WL_PROXD_TLV_ID_SESSION_INFO 	= 517,
-	WL_PROXD_TLV_ID_SESSION_STATUS	= 518,
-	WL_PROXD_TLV_ID_SESSION_ID_LIST = 519,
-
-	/* debug tlvs can be added starting 1024 */
-	WL_PROXD_TLV_ID_DEBUG_MASK	= 1024,
-	WL_PROXD_TLV_ID_COLLECT 	= 1025,		/* output only */
-	WL_PROXD_TLV_ID_STRBUF		= 1026,
-
-	WL_PROXD_TLV_ID_MAX
-};
-
-typedef struct wl_proxd_tlv {
-	uint16 id;
-	uint16 len;
-	uint8  data[1];
-} wl_proxd_tlv_t;
-
-/* proxd iovar - applies to proxd, method or session */
-typedef struct wl_proxd_iov {
-	uint16 					version;
-	uint16 					len;
-	wl_proxd_cmd_t 			cmd;
-	wl_proxd_method_t 		method;
-	wl_proxd_session_id_t 	sid;
-	uint8					pad[2];
-	wl_proxd_tlv_t 			tlvs[1];	/* variable */
-} wl_proxd_iov_t;
-
-#define WL_PROXD_IOV_HDR_SIZE OFFSETOF(wl_proxd_iov_t, tlvs)
-
-/* The following event definitions may move to bcmevent.h, but sharing proxd types
- * across needs more invasive changes unrelated to proxd
- */
-enum {
-	WL_PROXD_EVENT_NONE				= 0,	/* not an event, reserved */
-	WL_PROXD_EVENT_SESSION_CREATE	= 1,
-	WL_PROXD_EVENT_SESSION_START	= 2,
-	WL_PROXD_EVENT_FTM_REQ			= 3,
-	WL_PROXD_EVENT_BURST_START		= 4,
-	WL_PROXD_EVENT_BURST_END		= 5,
-	WL_PROXD_EVENT_SESSION_END		= 6,
-	WL_PROXD_EVENT_SESSION_RESTART	= 7,
-	WL_PROXD_EVENT_BURST_RESCHED	= 8,	/* burst rescheduled - e.g. partial TSF */
-	WL_PROXD_EVENT_SESSION_DESTROY	= 9,
-	WL_PROXD_EVENT_RANGE_REQ 		= 10,
-	WL_PROXD_EVENT_FTM_FRAME		= 11,
-	WL_PROXD_EVENT_DELAY			= 12,
-	WL_PROXD_EVENT_VS_INITIATOR_RPT = 13,	/* (target) rx initiator-report */
-	WL_PROXD_EVENT_RANGING			= 14,
-	WL_PROXD_EVENT_LCI_MEAS_REP 	= 15,	/* LCI measurement report */
-	WL_PROXD_EVENT_CIVIC_MEAS_REP 	= 16,	/* civic measurement report */
-
-	WL_PROXD_EVENT_MAX
-};
-typedef int16 wl_proxd_event_type_t;
-
-/* proxd event mask - upto 32 events for now */
-typedef uint32 wl_proxd_event_mask_t;
-
-#define WL_PROXD_EVENT_MASK_ALL 0xfffffffe
-#define WL_PROXD_EVENT_MASK_EVENT(_event_type) (1 << (_event_type))
-#define WL_PROXD_EVENT_ENABLED(_mask, _event_type) (\
-	((_mask) & WL_PROXD_EVENT_MASK_EVENT(_event_type)) != 0)
-
-/* proxd event - applies to proxd, method or session */
-typedef struct wl_proxd_event {
-	uint16					version;
-	uint16					len;
-	wl_proxd_event_type_t 	type;
-	wl_proxd_method_t 		method;
-	wl_proxd_session_id_t 	sid;
-	uint8					pad[2];
-	wl_proxd_tlv_t 			tlvs[1];	/* variable */
-} wl_proxd_event_t;
-
-enum {
-	WL_PROXD_RANGING_STATE_NONE = 0,
-	WL_PROXD_RANGING_STATE_NOTSTARTED = 1,
-	WL_PROXD_RANGING_STATE_INPROGRESS = 2,
-	WL_PROXD_RANGING_STATE_DONE = 3
-};
-typedef int16 wl_proxd_ranging_state_t;
-
-/* proxd ranging flags */
-enum {
-	WL_PROXD_RANGING_FLAG_NONE = 0x0000,  /* no flags */
-	WL_PROXD_RANGING_FLAG_DEL_SESSIONS_ON_STOP = 0x0001,
-	WL_PROXD_RANGING_FLAG_ALL = 0xffff
-};
-typedef uint16 wl_proxd_ranging_flags_t;
-
-struct wl_proxd_ranging_info {
-	wl_proxd_status_t   status;
-	wl_proxd_ranging_state_t state;
-	wl_proxd_ranging_flags_t flags;
-	uint16	num_sids;
-	uint16	num_done;
-};
-typedef struct wl_proxd_ranging_info wl_proxd_ranging_info_t;
-#include <packed_section_end.h>
-/* end proxd definitions */
-
-/* require strict packing */
-#include <packed_section_start.h>
-/* Data returned by the bssload_report iovar.
- * This is also the WLC_E_BSS_LOAD event data.
- */
-typedef BWL_PRE_PACKED_STRUCT struct wl_bssload {
-	uint16 sta_count;		/* station count */
-	uint16 aac;			/* available admission capacity */
-	uint8 chan_util;		/* channel utilization */
-} BWL_POST_PACKED_STRUCT wl_bssload_t;
-
-/* Maximum number of configurable BSS Load levels.  The number of BSS Load
- * ranges is always 1 more than the number of configured levels.  eg. if
- * 3 levels of 10, 20, 30 are configured then this defines 4 load ranges:
- * 0-10, 11-20, 21-30, 31-255.  A WLC_E_BSS_LOAD event is generated each time
- * the utilization level crosses into another range, subject to the rate limit.
- */
-#define MAX_BSSLOAD_LEVELS 8
-#define MAX_BSSLOAD_RANGES (MAX_BSSLOAD_LEVELS + 1)
-
-/* BSS Load event notification configuration. */
-typedef struct wl_bssload_cfg {
-	uint32 rate_limit_msec;	/* # of events posted to application will be limited to
-				 * one per specified period (0 to disable rate limit).
-				 */
-	uint8 num_util_levels;	/* Number of entries in util_levels[] below */
-	uint8 util_levels[MAX_BSSLOAD_LEVELS];
-				/* Variable number of BSS Load utilization levels in
-				 * low to high order.  An event will be posted each time
-				 * a received beacon's BSS Load IE channel utilization
-				 * value crosses a level.
-				 */
-} wl_bssload_cfg_t;
-
-/* Multiple roaming profile suport */
-#define WL_MAX_ROAM_PROF_BRACKETS	4
-
-#define WL_MAX_ROAM_PROF_VER	1
-
-#define WL_ROAM_PROF_NONE	(0 << 0)
-#define WL_ROAM_PROF_LAZY	(1 << 0)
-#define WL_ROAM_PROF_NO_CI	(1 << 1)
-#define WL_ROAM_PROF_SUSPEND	(1 << 2)
-#define WL_ROAM_PROF_SYNC_DTIM	(1 << 6)
-#define WL_ROAM_PROF_DEFAULT	(1 << 7)	/* backward compatible single default profile */
-
-#define WL_FACTOR_TABLE_MAX_LIMIT 5
-
-typedef struct wl_roam_prof {
-	int8	roam_flags;		/* bit flags */
-	int8	roam_trigger;		/* RSSI trigger level per profile/RSSI bracket */
-	int8	rssi_lower;
-	int8	roam_delta;
-	int8	rssi_boost_thresh;	/* Min RSSI to qualify for RSSI boost */
-	int8	rssi_boost_delta;	/* RSSI boost for AP in the other band */
-	uint16	nfscan;			/* nuber of full scan to start with */
-	uint16	fullscan_period;
-	uint16	init_scan_period;
-	uint16	backoff_multiplier;
-	uint16	max_scan_period;
-	uint8		channel_usage;
-	uint8		cu_avg_calc_dur;
-} wl_roam_prof_t;
-
-typedef struct wl_roam_prof_band {
-	uint32	band;			/* Must be just one band */
-	uint16	ver;			/* version of this struct */
-	uint16	len;			/* length in bytes of this structure */
-	wl_roam_prof_t roam_prof[WL_MAX_ROAM_PROF_BRACKETS];
-} wl_roam_prof_band_t;
-
-/* Data structures for Interface Create/Remove  */
-
-#define WL_INTERFACE_CREATE_VER	(0)
-
-/*
- * The flags filed of the wl_interface_create is designed to be
- * a Bit Mask. As of now only Bit 0 and Bit 1 are used as mentioned below.
- * The rest of the bits can be used, incase we have to provide
- * more information to the dongle
- */
-
-/*
- * Bit 0 of flags field is used to inform whether the interface requested to
- * be created is STA or AP.
- * 0 - Create a STA interface
- * 1 - Create an AP interface
- */
-#define WL_INTERFACE_CREATE_STA	(0 << 0)
-#define WL_INTERFACE_CREATE_AP	(1 << 0)
-
-/*
- * Bit 1 of flags field is used to inform whether MAC is present in the
- * data structure or not.
- * 0 - Ignore mac_addr field
- * 1 - Use the mac_addr field
- */
-#define WL_INTERFACE_MAC_DONT_USE	(0 << 1)
-#define WL_INTERFACE_MAC_USE		(1 << 1)
-
-typedef struct wl_interface_create {
-	uint16	ver;			/* version of this struct */
-	uint32  flags;			/* flags that defines the operation */
-	struct	ether_addr   mac_addr;	/* Optional Mac address */
-} wl_interface_create_t;
-
-typedef struct wl_interface_info {
-	uint16	ver;			/* version of this struct */
-	struct ether_addr    mac_addr;	/* MAC address of the interface */
-	char	ifname[BCM_MSG_IFNAME_MAX]; /* name of interface */
-	uint8	bsscfgidx;		/* source bsscfg index */
-} wl_interface_info_t;
-
-/* no default structure packing */
-#include <packed_section_end.h>
-
-#define TBOW_MAX_SSID_LEN        32
-#define TBOW_MAX_PASSPHRASE_LEN  63
-
-#define WL_TBOW_SETUPINFO_T_VERSION 1 /* version of tbow_setup_netinfo_t */
-typedef struct tbow_setup_netinfo {
-	uint32 version;
-	uint8 opmode;
-	uint8 pad;
-	uint8 macaddr[ETHER_ADDR_LEN];
-	uint32 ssid_len;
-	uint8 ssid[TBOW_MAX_SSID_LEN];
-	uint8 passphrase_len;
-	uint8 passphrase[TBOW_MAX_PASSPHRASE_LEN];
-	chanspec_t chanspec;
-} tbow_setup_netinfo_t;
-
-typedef enum tbow_ho_opmode {
-	TBOW_HO_MODE_START_GO = 0,
-	TBOW_HO_MODE_START_STA,
-	TBOW_HO_MODE_START_GC,
-	TBOW_HO_MODE_TEST_GO,
-	TBOW_HO_MODE_STOP_GO = 0x10,
-	TBOW_HO_MODE_STOP_STA,
-	TBOW_HO_MODE_STOP_GC,
-	TBOW_HO_MODE_TEARDOWN
-} tbow_ho_opmode_t;
-
-/* Beacon trim feature statistics */
-/* Configuration params */
-#define M_BCNTRIM_N				(0)	/* Enable/Disable Beacon Trim */
-#define M_BCNTRIM_TIMEND		(1)	/* Waiting time for TIM IE to end */
-#define M_BCNTRIM_TSFTLRN		(2)	/* TSF tolerance value (usecs) */
-/* PSM internal use */
-#define M_BCNTRIM_PREVBCNLEN	(3)	/* Beacon length excluding the TIM IE */
-#define M_BCNTRIM_N_COUNTER		(4)	/* PSM's local beacon trim counter */
-#define M_BCNTRIM_STATE			(5)	/* PSM's Beacon trim status register */
-#define M_BCNTRIM_TIMLEN		(6)	/* TIM IE Length */
-#define M_BCNTRIM_BMPCTL		(7)	/* Bitmap control word */
-#define M_BCNTRIM_TSF_L			(8)	/* Lower TSF word */
-#define M_BCNTRIM_TSF_ML		(9)	/* Lower middle TSF word */
-#define M_BCNTRIM_RSSI			(10) /* Partial beacon RSSI */
-#define M_BCNTRIM_CHANNEL		(11) /* Partial beacon channel */
-/* Trimming Counters */
-#define M_BCNTRIM_SBCNRXED		(12) /* Self-BSSID beacon received */
-#define M_BCNTRIM_CANTRIM		(13) /* Num of beacons which can be trimmed */
-#define M_BCNTRIM_TRIMMED		(14) /* # beacons which were trimmed */
-#define M_BCNTRIM_BCNLENCNG		(15) /* # beacons trimmed due to length change */
-#define M_BCNTRIM_TSFADJ		(16) /* # beacons not trimmed due to large TSF delta */
-#define M_BCNTRIM_TIMNOTFOUND	(17) /* # beacons not trimmed due to TIM missing */
-#define M_RXTSFTMRVAL_WD0		(18)
-#define M_RXTSFTMRVAL_WD1		(19)
-#define M_RXTSFTMRVAL_WD2		(20)
-#define M_RXTSFTMRVAL_WD3		(21)
-#define BCNTRIM_STATS_NUMPARAMS	(22) /* 16 bit words */
-
-#define TXPWRCAP_MAX_NUM_CORES 8
-#define TXPWRCAP_MAX_NUM_ANTENNAS (TXPWRCAP_MAX_NUM_CORES * 2)
-
-typedef struct wl_txpwrcap_tbl {
-	uint8 num_antennas_per_core[TXPWRCAP_MAX_NUM_CORES];
-	/* Stores values for valid antennas */
-	int8 pwrcap_cell_on[TXPWRCAP_MAX_NUM_ANTENNAS]; /* qdBm units */
-	int8 pwrcap_cell_off[TXPWRCAP_MAX_NUM_ANTENNAS]; /* qdBm units */
-} wl_txpwrcap_tbl_t;
-
-/* -------------- dynamic BTCOEX --------------- */
-/* require strict packing */
-#include <packed_section_start.h>
-
-#define DCTL_TROWS	2	/* currently practical number of rows  */
-#define DCTL_TROWS_MAX	4	/*  2 extra rows RFU */
-/* DYNCTL profile flags */
-#define DCTL_FLAGS_DYNCTL	(1 << 0)	/*  1 - enabled, 0 - legacy only */
-#define DCTL_FLAGS_DESENSE	(1 << 1)	/* auto desense is enabled */
-#define DCTL_FLAGS_MSWITCH	(1 << 2)	/* mode switching is enabled */
-/* for now AGG on/off is handled separately  */
-#define DCTL_FLAGS_TX_AGG_OFF	(1 << 3) /* TBD: allow TX agg Off */
-#define DCTL_FLAGS_RX_AGG_OFF	(1 << 4) /* TBD: allow RX agg Off */
-/* used for dry run testing only */
-#define DCTL_FLAGS_DRYRUN	(1 << 7) /* Eenables dynctl dry run mode  */
-#define IS_DYNCTL_ON(prof)	((prof->flags & DCTL_FLAGS_DYNCTL) != 0)
-#define IS_DESENSE_ON(prof)	((prof->flags & DCTL_FLAGS_DESENSE) != 0)
-#define IS_MSWITCH_ON(prof)	((prof->flags & DCTL_FLAGS_MSWITCH) != 0)
-/* desense level currently in use */
-#define DESENSE_OFF	0
-#define DFLT_DESENSE_MID	12
-#define DFLT_DESENSE_HIGH	2
-
-/*
- * dynctl data points(a set of btpwr & wlrssi thresholds)
- * for mode & desense switching
- */
-typedef struct btc_thr_data {
-	int8	mode;	/* used by desense sw */
-	int8	bt_pwr;	/* BT tx power threshold */
-	int8	bt_rssi;	/* BT rssi threshold */
-	/* wl rssi range when mode or desense change may be needed */
-	int8	wl_rssi_high;
-	int8	wl_rssi_low;
-} btc_thr_data_t;
-
-/* dynctl. profile data structure  */
-#define DCTL_PROFILE_VER 0x01
-typedef BWL_PRE_PACKED_STRUCT struct  dctl_prof {
-	uint8 version;  /* dynctl profile version */
-	/* dynctl profile flags bit:0 - dynctl On, bit:1 dsns On, bit:2 mode sw On, */
-	uint8 flags;  /* bit[6:3] reserved, bit7 - Dryrun (sim) - On */
-	/*  wl desense levels to apply */
-	uint8	dflt_dsns_level;
-	uint8	low_dsns_level;
-	uint8	mid_dsns_level;
-	uint8	high_dsns_level;
-	/* mode switching hysteresis in dBm */
-	int8	msw_btrssi_hyster;
-	/* default btcoex mode */
-	uint8	default_btc_mode;
-	 /* num of active rows in mode switching table */
-	uint8	msw_rows;
-	/* num of rows in desense table */
-	uint8	dsns_rows;
-	/* dynctl mode switching data table  */
-	btc_thr_data_t msw_data[DCTL_TROWS_MAX];
-	/* dynctl desense switching data table */
-	btc_thr_data_t dsns_data[DCTL_TROWS_MAX];
-} BWL_POST_PACKED_STRUCT dctl_prof_t;
-
-/*  dynctl status info */
-typedef BWL_PRE_PACKED_STRUCT struct  dynctl_status {
-	bool sim_on;	/* true if simulation is On */
-	uint16	bt_pwr_shm; /* BT per/task power as read from ucode  */
-	int8	bt_pwr;		/* BT pwr extracted & converted to dBm */
-	int8	bt_rssi;	/* BT rssi in dBm */
-	int8	wl_rssi;	/* last wl rssi reading used by btcoex */
-	uint8	dsns_level; /* current desense level */
-	uint8	btc_mode;   /* current btcoex mode */
-	/* add more status items if needed,  pad to 4 BB if needed */
-} BWL_POST_PACKED_STRUCT dynctl_status_t;
-
-/*  dynctl simulation (dryrun data) */
-typedef BWL_PRE_PACKED_STRUCT struct  dynctl_sim {
-	bool sim_on;	/* simulation mode on/off */
-	int8 btpwr;		/* simulated BT power in dBm */
-	int8 btrssi;	/* simulated BT rssi in dBm */
-	int8 wlrssi;	/* simulated WL rssi in dBm */
-} BWL_POST_PACKED_STRUCT dynctl_sim_t;
-/* no default structure packing */
-#include <packed_section_end.h>
-
-/* PTK key maintained per SCB */
-#define RSN_TEMP_ENCR_KEY_LEN 16
-typedef struct wpa_ptk {
-	uint8 kck[RSN_KCK_LENGTH]; /* EAPOL-Key Key Confirmation Key (KCK) */
-	uint8 kek[RSN_KEK_LENGTH]; /* EAPOL-Key Key Encryption Key (KEK) */
-	uint8 tk1[RSN_TEMP_ENCR_KEY_LEN]; /* Temporal Key 1 (TK1) */
-	uint8 tk2[RSN_TEMP_ENCR_KEY_LEN]; /* Temporal Key 2 (TK2) */
-} wpa_ptk_t;
-
-/* GTK key maintained per SCB */
-typedef struct wpa_gtk {
-	uint32 idx;
-	uint32 key_len;
-	uint8  key[DOT11_MAX_KEY_SIZE];
-} wpa_gtk_t;
-
-/* FBT Auth Response Data structure */
-typedef struct wlc_fbt_auth_resp {
-	uint8 macaddr[ETHER_ADDR_LEN]; /* station mac address */
-	uint8 pad[2];
-	uint8 pmk_r1_name[WPA2_PMKID_LEN];
-	wpa_ptk_t ptk; /* pairwise key */
-	wpa_gtk_t gtk; /* group key */
-	uint32 ie_len;
-	uint8 status;  /* Status of parsing FBT authentication
-					Request in application
-					*/
-	uint8 ies[1]; /* IEs contains MDIE, RSNIE,
-					FBTIE (ANonce, SNonce,R0KH-ID, R1KH-ID)
-					*/
-} wlc_fbt_auth_resp_t;
-
-/* FBT Action Response frame */
-typedef struct wlc_fbt_action_resp {
-	uint16 version; /* structure version */
-	uint16 length; /* length of structure */
-	uint8 macaddr[ETHER_ADDR_LEN]; /* station mac address */
-	uint8 data_len;  /* len of ie from Category */
-	uint8 data[1]; /* data contains category, action, sta address, target ap,
-						status code,fbt response frame body
-						*/
-} wlc_fbt_action_resp_t;
-
-#define MACDBG_PMAC_ADDR_INPUT_MAXNUM 16
-#define MACDBG_PMAC_OBJ_TYPE_LEN 8
-
-typedef struct _wl_macdbg_pmac_param_t {
-	char type[MACDBG_PMAC_OBJ_TYPE_LEN];
-	uint8 step;
-	uint8 num;
-	uint32 bitmap;
-	bool addr_raw;
-	uint8 addr_num;
-	uint16 addr[MACDBG_PMAC_ADDR_INPUT_MAXNUM];
-} wl_macdbg_pmac_param_t;
-
-/* IOVAR 'svmp_mem' parameter. Used to read/clear svmp memory */
-typedef struct svmp_mem {
-	uint32 addr;	/* offset to read svmp memory from vasip base address */
-	uint16 len;	/* length in count of uint16's */
-	uint16 val;	/* set the range of addr/len with a value */
-} svmp_mem_t;
-
-#define WL_NAN_BAND_STR_SIZE 5       /* sizeof ("auto") */
-
-/* Definitions of different NAN Bands */
-enum {  /* mode selection for reading/writing tx iqlo cal coefficients */
-	NAN_BAND_AUTO,
-	NAN_BAND_B,
-	NAN_BAND_A,
-	NAN_BAND_INVALID = 0xFF
-};
-
-#if defined(WL_LINKSTAT)
-typedef struct {
-	uint32 preamble;
-	uint32 nss;
-	uint32 bw;
-	uint32 rateMcsIdx;
-	uint32 reserved;
-	uint32 bitrate;
-} wifi_rate;
-
-typedef struct {
-	uint16 version;
-	uint16 length;
-	uint32 tx_mpdu;
-	uint32 rx_mpdu;
-	uint32 mpdu_lost;
-	uint32 retries;
-	uint32 retries_short;
-	uint32 retries_long;
-	wifi_rate rate;
-} wifi_rate_stat_t;
-
-typedef int32 wifi_radio;
-
-typedef struct {
-	uint16 version;
-	uint16 length;
-	wifi_radio radio;
-	uint32 on_time;
-	uint32 tx_time;
-	uint32 rx_time;
-	uint32 on_time_scan;
-	uint32 on_time_nbd;
-	uint32 on_time_gscan;
-	uint32 on_time_roam_scan;
-	uint32 on_time_pno_scan;
-	uint32 on_time_hs20;
-	uint32 num_channels;
-	uint8 channels[1];
-} wifi_radio_stat;
-#endif /* WL_LINKSTAT */
-
-#ifdef WL11ULB
-/* ULB Mode configured via "ulb_mode" IOVAR */
-enum {
-    ULB_MODE_DISABLED = 0,
-    ULB_MODE_STD_ALONE_MODE = 1,    /* Standalone ULB Mode */
-    ULB_MODE_DYN_MODE = 2,      /* Dynamic ULB Mode */
-	/* Add all other enums before this */
-    MAX_SUPP_ULB_MODES
-};
-
-/* ULB BWs configured via "ulb_bw" IOVAR during Standalone Mode Only.
- * Values of this enumeration are also used to specify 'Current Operational Bandwidth'
- * and 'Primary Operational Bandwidth' sub-fields in 'ULB Operations' field (used in
- * 'ULB Operations' Attribute or 'ULB Mode Switch' Attribute)
- */
-typedef enum {
-    ULB_BW_DISABLED = 0,
-    ULB_BW_10MHZ    = 1,    /* Standalone ULB BW in 10 MHz BW */
-    ULB_BW_5MHZ = 2,    /* Standalone ULB BW in 5 MHz BW */
-    ULB_BW_2P5MHZ   = 3,    /* Standalone ULB BW in 2.5 MHz BW */
-	/* Add all other enums before this */
-    MAX_SUPP_ULB_BW
-} ulb_bw_type_t;
-#endif /* WL11ULB */
-
-#if defined(WLRCC)
-#define MAX_ROAM_CHANNEL      20
-
-typedef struct {
-	int n;
-	chanspec_t channels[MAX_ROAM_CHANNEL];
-} wl_roam_channel_list_t;
-#endif 
-
-
-/*
- * Neighbor Discover Offload: enable NDO feature
- * Called  by ipv6 event handler when interface comes up
- * Set RA rate limit interval value(%)
- */
-typedef struct nd_ra_ol_limits {
-	uint16 version;         /* version of the iovar buffer */
-	uint16 type;            /* type of data provided */
-	uint16 length;          /* length of the entire structure */
-	uint16 pad1;            /* pad union to 4 byte boundary */
-	union {
-		struct {
-			uint16 min_time;         /* seconds, min time for RA offload hold */
-			uint16 lifetime_percent;
-			/* percent, lifetime percentage for offload hold time */
-		} lifetime_relative;
-		struct {
-			uint16 hold_time;        /* seconds, RA offload hold time */
-			uint16 pad2;             /* unused */
-		} fixed;
-	} limits;
-} nd_ra_ol_limits_t;
-
-#define ND_RA_OL_LIMITS_VER 1
-
-/* nd_ra_ol_limits sub-types */
-#define ND_RA_OL_LIMITS_REL_TYPE   0     /* relative, percent of RA lifetime */
-#define ND_RA_OL_LIMITS_FIXED_TYPE 1     /* fixed time */
-
-/* buffer lengths for the different nd_ra_ol_limits types */
-#define ND_RA_OL_LIMITS_REL_TYPE_LEN   12
-#define ND_RA_OL_LIMITS_FIXED_TYPE_LEN  10
-
-#define ND_RA_OL_SET    "SET"
-#define ND_RA_OL_GET    "GET"
-#define ND_PARAM_SIZE   50
-#define ND_VALUE_SIZE   5
-#define ND_PARAMS_DELIMETER " "
-#define ND_PARAM_VALUE_DELLIMETER   '='
-#define ND_LIMIT_STR_FMT ("%50s %50s")
-
-#define ND_RA_TYPE  "TYPE"
-#define ND_RA_MIN_TIME  "MIN"
-#define ND_RA_PER   "PER"
-#define ND_RA_HOLD  "HOLD"
-
-/*
- * Temperature Throttling control mode
- */
-typedef struct wl_temp_control {
-	bool enable;
-	uint16 control_bit;
-} wl_temp_control_t;
-
-#endif /* _wlioctl_h_ */
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl_utils.h b/drivers/net/wireless/bcmdhd/include/wlioctl_utils.h
deleted file mode 100644
index c3fe428..0000000
--- a/drivers/net/wireless/bcmdhd/include/wlioctl_utils.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Custom OID/ioctl related helper functions.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wlioctl_utils.h 555740 2015-05-11 10:16:23Z $
- */
-
-#ifndef _wlioctl_utils_h_
-#define _wlioctl_utils_h_
-
-#include <wlioctl.h>
-
-#ifndef BCMDRIVER
-#define CCA_THRESH_MILLI	14
-#define CCA_THRESH_INTERFERE	6
-
-extern cca_congest_channel_req_t * cca_per_chan_summary(cca_congest_channel_req_t *input,
-	cca_congest_channel_req_t *avg, bool percent);
-
-extern int cca_analyze(cca_congest_channel_req_t *input[], int num_chans,
-	uint flags, chanspec_t *answer);
-#endif /* BCMDRIVER */
-
-extern int wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf,
-	int buflen, uint32 corerev);
-
-/* Get data pointer of wlc layer counters tuple from xtlv formatted counters IOVar buffer. */
-#define GET_WLCCNT_FROM_CNTBUF(cntbuf)						\
-		bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)cntbuf)->data,	\
-		((wl_cnt_info_t *)cntbuf)->datalen, WL_CNT_XTLV_WLC,		\
-		NULL, BCM_XTLV_OPTION_ALIGN32)
-
-#endif /* _wlioctl_utils_h_ */
diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c
deleted file mode 100644
index 74b65777..0000000
--- a/drivers/net/wireless/bcmdhd/linux_osl.c
+++ /dev/null
@@ -1,2652 +0,0 @@
-/*
- * Linux OS Independent Layer
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: linux_osl.c 602478 2015-11-26 04:46:12Z $
- */
-
-#define LINUX_PORT
-
-#include <typedefs.h>
-#include <bcmendian.h>
-#include <linuxver.h>
-#include <bcmdefs.h>
-
-
-#if !defined(STBLINUX)
-#if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)
-#include <asm/cacheflush.h>
-#endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */
-#endif /* STBLINUX */
-
-#include <linux/random.h>
-
-#include <osl.h>
-#include <bcmutils.h>
-#include <linux/delay.h>
-#include <pcicfg.h>
-
-
-#ifdef BCM_SECURE_DMA
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/printk.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/moduleparam.h>
-#include <asm/io.h>
-#include <linux/skbuff.h>
-#include <linux/vmalloc.h>
-#include <linux/highmem.h>
-#include <linux/dma-mapping.h>
-#include <asm/memory.h>
-#if defined(__ARM_ARCH_7A__)
-#include <arch/arm/include/asm/tlbflush.h>
-#include <arch/arm/mm/mm.h>
-#endif
-#include <linux/brcmstb/cma_driver.h>
-#endif /* BCM_SECURE_DMA */
-
-#include <linux/fs.h>
-
-
-#ifdef BCM_OBJECT_TRACE
-#include <bcmutils.h>
-#endif /* BCM_OBJECT_TRACE */
-
-#define PCI_CFG_RETRY		10
-
-#define OS_HANDLE_MAGIC		0x1234abcd	/* Magic # to recognize osh */
-#define BCM_MEM_FILENAME_LEN	24		/* Mem. filename length */
-#define DUMPBUFSZ 1024
-
-/* dependancy check */
-#if !defined(BCMPCIE) && defined(DHD_USE_STATIC_CTRLBUF)
-#error "DHD_USE_STATIC_CTRLBUF suppored PCIE target only"
-#endif /* !BCMPCIE && DHD_USE_STATIC_CTRLBUF */
-
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-#ifdef DHD_USE_STATIC_CTRLBUF
-#define DHD_SKB_1PAGE_BUFSIZE	(PAGE_SIZE*1)
-#define DHD_SKB_2PAGE_BUFSIZE	(PAGE_SIZE*2)
-#define DHD_SKB_4PAGE_BUFSIZE	(PAGE_SIZE*4)
-
-#define PREALLOC_FREE_MAGIC	0xFEDC
-#define PREALLOC_USED_MAGIC	0xFCDE
-#else
-#define DHD_SKB_HDRSIZE		336
-#define DHD_SKB_1PAGE_BUFSIZE	((PAGE_SIZE*1)-DHD_SKB_HDRSIZE)
-#define DHD_SKB_2PAGE_BUFSIZE	((PAGE_SIZE*2)-DHD_SKB_HDRSIZE)
-#define DHD_SKB_4PAGE_BUFSIZE	((PAGE_SIZE*4)-DHD_SKB_HDRSIZE)
-#endif /* DHD_USE_STATIC_CTRLBUF */
-
-#define STATIC_BUF_MAX_NUM	16
-#define STATIC_BUF_SIZE	(PAGE_SIZE*2)
-#define STATIC_BUF_TOTAL_LEN	(STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)
-
-typedef struct bcm_static_buf {
-	struct semaphore static_sem;
-	unsigned char *buf_ptr;
-	unsigned char buf_use[STATIC_BUF_MAX_NUM];
-} bcm_static_buf_t;
-
-static bcm_static_buf_t *bcm_static_buf = 0;
-
-#ifdef DHD_USE_STATIC_CTRLBUF
-#define STATIC_PKT_4PAGE_NUM	0
-#define DHD_SKB_MAX_BUFSIZE	DHD_SKB_2PAGE_BUFSIZE
-#elif defined(ENHANCED_STATIC_BUF)
-#define STATIC_PKT_4PAGE_NUM	1
-#define DHD_SKB_MAX_BUFSIZE	DHD_SKB_4PAGE_BUFSIZE
-#else
-#define STATIC_PKT_4PAGE_NUM	0
-#define DHD_SKB_MAX_BUFSIZE	DHD_SKB_2PAGE_BUFSIZE
-#endif /* DHD_USE_STATIC_CTRLBUF */
-
-#ifdef DHD_USE_STATIC_CTRLBUF
-#define STATIC_PKT_1PAGE_NUM	0
-#define STATIC_PKT_2PAGE_NUM	64
-#else
-#define STATIC_PKT_1PAGE_NUM	8
-#define STATIC_PKT_2PAGE_NUM	8
-#endif /* DHD_USE_STATIC_CTRLBUF */
-
-#define STATIC_PKT_1_2PAGE_NUM	\
-	((STATIC_PKT_1PAGE_NUM) + (STATIC_PKT_2PAGE_NUM))
-#define STATIC_PKT_MAX_NUM	\
-	((STATIC_PKT_1_2PAGE_NUM) + (STATIC_PKT_4PAGE_NUM))
-
-typedef struct bcm_static_pkt {
-#ifdef DHD_USE_STATIC_CTRLBUF
-	struct sk_buff *skb_8k[STATIC_PKT_2PAGE_NUM];
-	unsigned char pkt_invalid[STATIC_PKT_2PAGE_NUM];
-	spinlock_t osl_pkt_lock;
-	uint32 last_allocated_index;
-#else
-	struct sk_buff *skb_4k[STATIC_PKT_1PAGE_NUM];
-	struct sk_buff *skb_8k[STATIC_PKT_2PAGE_NUM];
-#ifdef ENHANCED_STATIC_BUF
-	struct sk_buff *skb_16k;
-#endif /* ENHANCED_STATIC_BUF */
-	struct semaphore osl_pkt_sem;
-#endif /* DHD_USE_STATIC_CTRLBUF */
-	unsigned char pkt_use[STATIC_PKT_MAX_NUM];
-} bcm_static_pkt_t;
-
-static bcm_static_pkt_t *bcm_static_skb = 0;
-
-void* wifi_platform_prealloc(void *adapter, int section, unsigned long size);
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-
-typedef struct bcm_mem_link {
-	struct bcm_mem_link *prev;
-	struct bcm_mem_link *next;
-	uint	size;
-	int	line;
-	void 	*osh;
-	char	file[BCM_MEM_FILENAME_LEN];
-} bcm_mem_link_t;
-
-struct osl_cmn_info {
-	atomic_t malloced;
-	atomic_t pktalloced;    /* Number of allocated packet buffers */
-	spinlock_t dbgmem_lock;
-	bcm_mem_link_t *dbgmem_list;
-	spinlock_t pktalloc_lock;
-	atomic_t refcount; /* Number of references to this shared structure. */
-};
-typedef struct osl_cmn_info osl_cmn_t;
-
-struct osl_info {
-	osl_pubinfo_t pub;
-	uint32  flags;		/* If specific cases to be handled in the OSL */
-#ifdef CTFPOOL
-	ctfpool_t *ctfpool;
-#endif /* CTFPOOL */
-	uint magic;
-	void *pdev;
-	uint failed;
-	uint bustype;
-	osl_cmn_t *cmn; /* Common OSL related data shred between two OSH's */
-
-	void *bus_handle;
-#ifdef BCMDBG_CTRACE
-	spinlock_t ctrace_lock;
-	struct list_head ctrace_list;
-	int ctrace_num;
-#endif /* BCMDBG_CTRACE */
-#ifdef	BCM_SECURE_DMA
-	struct cma_dev *cma;
-	struct sec_mem_elem *sec_list_512;
-	struct sec_mem_elem *sec_list_base_512;
-	struct sec_mem_elem *sec_list_2048;
-	struct sec_mem_elem *sec_list_base_2048;
-	struct sec_mem_elem *sec_list_4096;
-	struct sec_mem_elem *sec_list_base_4096;
-	phys_addr_t  contig_base;
-	void *contig_base_va;
-	phys_addr_t  contig_base_alloc;
-	void *contig_base_alloc_va;
-	phys_addr_t contig_base_alloc_coherent;
-	void *contig_base_alloc_coherent_va;
-	phys_addr_t contig_delta_va_pa;
-	struct {
-		phys_addr_t pa;
-		void *va;
-		bool avail;
-	} sec_cma_coherent[SEC_CMA_COHERENT_MAX];
-
-#endif /* BCM_SECURE_DMA */
-};
-#ifdef BCM_SECURE_DMA
-phys_addr_t g_contig_delta_va_pa;
-static void osl_sec_dma_setup_contig_mem(osl_t *osh, unsigned long memsize, int regn);
-static int osl_sec_dma_alloc_contig_mem(osl_t *osh, unsigned long memsize, int regn);
-static void osl_sec_dma_free_contig_mem(osl_t *osh, u32 memsize, int regn);
-static void * osl_sec_dma_ioremap(osl_t *osh, struct page *page, size_t size,
-	bool iscache, bool isdecr);
-static void osl_sec_dma_iounmap(osl_t *osh, void *contig_base_va, size_t size);
-static void osl_sec_dma_init_elem_mem_block(osl_t *osh, size_t mbsize, int max,
-	sec_mem_elem_t **list);
-static void osl_sec_dma_deinit_elem_mem_block(osl_t *osh, size_t mbsize, int max,
-	void *sec_list_base);
-static sec_mem_elem_t * osl_sec_dma_alloc_mem_elem(osl_t *osh, void *va, uint size,
-	int direction, struct sec_cma_info *ptr_cma_info, uint offset);
-static void osl_sec_dma_free_mem_elem(osl_t *osh, sec_mem_elem_t *sec_mem_elem);
-static void osl_sec_dma_init_consistent(osl_t *osh);
-static void *osl_sec_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits,
-	ulong *pap);
-static void osl_sec_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa);
-#endif /* BCM_SECURE_DMA */
-
-#ifdef BCM_OBJECT_TRACE
-/* don't clear the first 4 byte that is the pkt sn */
-#define OSL_PKTTAG_CLEAR(p) \
-do { \
-	struct sk_buff *s = (struct sk_buff *)(p); \
-	ASSERT(OSL_PKTTAG_SZ == 32); \
-	*(uint32 *)(&s->cb[4]) = 0; \
-	*(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \
-	*(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \
-	*(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \
-} while (0)
-#else
-#define OSL_PKTTAG_CLEAR(p) \
-do { \
-	struct sk_buff *s = (struct sk_buff *)(p); \
-	ASSERT(OSL_PKTTAG_SZ == 32); \
-	*(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \
-	*(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \
-	*(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \
-	*(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \
-} while (0)
-#endif /* BCM_OBJECT_TRACE */
-
-/* PCMCIA attribute space access macros */
-
-/* Global ASSERT type flag */
-uint32 g_assert_type = 1;
-module_param(g_assert_type, int, 0);
-
-static int16 linuxbcmerrormap[] =
-{	0, 			/* 0 */
-	-EINVAL,		/* BCME_ERROR */
-	-EINVAL,		/* BCME_BADARG */
-	-EINVAL,		/* BCME_BADOPTION */
-	-EINVAL,		/* BCME_NOTUP */
-	-EINVAL,		/* BCME_NOTDOWN */
-	-EINVAL,		/* BCME_NOTAP */
-	-EINVAL,		/* BCME_NOTSTA */
-	-EINVAL,		/* BCME_BADKEYIDX */
-	-EINVAL,		/* BCME_RADIOOFF */
-	-EINVAL,		/* BCME_NOTBANDLOCKED */
-	-EINVAL, 		/* BCME_NOCLK */
-	-EINVAL, 		/* BCME_BADRATESET */
-	-EINVAL, 		/* BCME_BADBAND */
-	-E2BIG,			/* BCME_BUFTOOSHORT */
-	-E2BIG,			/* BCME_BUFTOOLONG */
-	-EBUSY, 		/* BCME_BUSY */
-	-EINVAL, 		/* BCME_NOTASSOCIATED */
-	-EINVAL, 		/* BCME_BADSSIDLEN */
-	-EINVAL, 		/* BCME_OUTOFRANGECHAN */
-	-EINVAL, 		/* BCME_BADCHAN */
-	-EFAULT, 		/* BCME_BADADDR */
-	-ENOMEM, 		/* BCME_NORESOURCE */
-	-EOPNOTSUPP,		/* BCME_UNSUPPORTED */
-	-EMSGSIZE,		/* BCME_BADLENGTH */
-	-EINVAL,		/* BCME_NOTREADY */
-	-EPERM,			/* BCME_EPERM */
-	-ENOMEM, 		/* BCME_NOMEM */
-	-EINVAL, 		/* BCME_ASSOCIATED */
-	-ERANGE, 		/* BCME_RANGE */
-	-EINVAL, 		/* BCME_NOTFOUND */
-	-EINVAL, 		/* BCME_WME_NOT_ENABLED */
-	-EINVAL, 		/* BCME_TSPEC_NOTFOUND */
-	-EINVAL, 		/* BCME_ACM_NOTSUPPORTED */
-	-EINVAL,		/* BCME_NOT_WME_ASSOCIATION */
-	-EIO,			/* BCME_SDIO_ERROR */
-	-ENODEV,		/* BCME_DONGLE_DOWN */
-	-EINVAL,		/* BCME_VERSION */
-	-EIO,			/* BCME_TXFAIL */
-	-EIO,			/* BCME_RXFAIL */
-	-ENODEV,		/* BCME_NODEVICE */
-	-EINVAL,		/* BCME_NMODE_DISABLED */
-	-ENODATA,		/* BCME_NONRESIDENT */
-	-EINVAL,		/* BCME_SCANREJECT */
-	-EINVAL,		/* BCME_USAGE_ERROR */
-	-EIO,     		/* BCME_IOCTL_ERROR */
-	-EIO,			/* BCME_SERIAL_PORT_ERR */
-	-EOPNOTSUPP,	/* BCME_DISABLED, BCME_NOTENABLED */
-	-EIO,			/* BCME_DECERR */
-	-EIO,			/* BCME_ENCERR */
-	-EIO,			/* BCME_MICERR */
-	-ERANGE,		/* BCME_REPLAY */
-	-EINVAL,		/* BCME_IE_NOTFOUND */
-	-EINVAL,		/* BCME_DATA_NOTFOUND */
-
-/* When an new error code is added to bcmutils.h, add os
- * specific error translation here as well
- */
-/* check if BCME_LAST changed since the last time this function was updated */
-#if BCME_LAST != -53
-#error "You need to add a OS error translation in the linuxbcmerrormap \
-	for new error code defined in bcmutils.h"
-#endif
-};
-uint lmtest = FALSE;
-
-/* translate bcmerrors into linux errors */
-int
-osl_error(int bcmerror)
-{
-	if (bcmerror > 0)
-		bcmerror = 0;
-	else if (bcmerror < BCME_LAST)
-		bcmerror = BCME_ERROR;
-
-	/* Array bounds covered by ASSERT in osl_attach */
-	return linuxbcmerrormap[-bcmerror];
-}
-#ifdef SHARED_OSL_CMN
-osl_t *
-osl_attach(void *pdev, uint bustype, bool pkttag, void **osl_cmn)
-{
-#else
-osl_t *
-osl_attach(void *pdev, uint bustype, bool pkttag)
-{
-	void **osl_cmn = NULL;
-#endif /* SHARED_OSL_CMN */
-	osl_t *osh;
-	gfp_t flags;
-
-	flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
-	if (!(osh = kmalloc(sizeof(osl_t), flags)))
-		return osh;
-
-	ASSERT(osh);
-
-	bzero(osh, sizeof(osl_t));
-
-	if (osl_cmn == NULL || *osl_cmn == NULL) {
-		if (!(osh->cmn = kmalloc(sizeof(osl_cmn_t), flags))) {
-			kfree(osh);
-			return NULL;
-		}
-		bzero(osh->cmn, sizeof(osl_cmn_t));
-		if (osl_cmn)
-			*osl_cmn = osh->cmn;
-		atomic_set(&osh->cmn->malloced, 0);
-		osh->cmn->dbgmem_list = NULL;
-		spin_lock_init(&(osh->cmn->dbgmem_lock));
-
-		spin_lock_init(&(osh->cmn->pktalloc_lock));
-
-	} else {
-		osh->cmn = *osl_cmn;
-	}
-	atomic_add(1, &osh->cmn->refcount);
-
-	bcm_object_trace_init();
-
-	/* Check that error map has the right number of entries in it */
-	ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));
-
-	osh->failed = 0;
-	osh->pdev = pdev;
-	osh->pub.pkttag = pkttag;
-	osh->bustype = bustype;
-	osh->magic = OS_HANDLE_MAGIC;
-#ifdef BCM_SECURE_DMA
-
-	osl_sec_dma_setup_contig_mem(osh, CMA_MEMBLOCK, CONT_ARMREGION);
-
-	osh->contig_base_alloc_coherent_va = osl_sec_dma_ioremap(osh,
-		phys_to_page((u32)osh->contig_base_alloc),
-		CMA_DMA_DESC_MEMBLOCK, FALSE, TRUE);
-
-	osh->contig_base_alloc_coherent = osh->contig_base_alloc;
-	osl_sec_dma_init_consistent(osh);
-
-	osh->contig_base_alloc += CMA_DMA_DESC_MEMBLOCK;
-
-	osh->contig_base_alloc_va = osl_sec_dma_ioremap(osh,
-		phys_to_page((u32)osh->contig_base_alloc), CMA_DMA_DATA_MEMBLOCK, TRUE, FALSE);
-	osh->contig_base_va = osh->contig_base_alloc_va;
-
-	/*
-	* osl_sec_dma_init_elem_mem_block(osh, CMA_BUFSIZE_512, CMA_BUFNUM, &osh->sec_list_512);
-	* osh->sec_list_base_512 = osh->sec_list_512;
-	* osl_sec_dma_init_elem_mem_block(osh, CMA_BUFSIZE_2K, CMA_BUFNUM, &osh->sec_list_2048);
-	* osh->sec_list_base_2048 = osh->sec_list_2048;
-	*/
-	osl_sec_dma_init_elem_mem_block(osh, CMA_BUFSIZE_4K, CMA_BUFNUM, &osh->sec_list_4096);
-	osh->sec_list_base_4096 = osh->sec_list_4096;
-
-#endif /* BCM_SECURE_DMA */
-
-	switch (bustype) {
-		case PCI_BUS:
-		case SI_BUS:
-		case PCMCIA_BUS:
-			osh->pub.mmbus = TRUE;
-			break;
-		case JTAG_BUS:
-		case SDIO_BUS:
-		case USB_BUS:
-		case SPI_BUS:
-		case RPC_BUS:
-			osh->pub.mmbus = FALSE;
-			break;
-		default:
-			ASSERT(FALSE);
-			break;
-	}
-
-#ifdef BCMDBG_CTRACE
-	spin_lock_init(&osh->ctrace_lock);
-	INIT_LIST_HEAD(&osh->ctrace_list);
-	osh->ctrace_num = 0;
-#endif /* BCMDBG_CTRACE */
-
-
-	return osh;
-}
-
-int osl_static_mem_init(osl_t *osh, void *adapter)
-{
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-		if (!bcm_static_buf && adapter) {
-			if (!(bcm_static_buf = (bcm_static_buf_t *)wifi_platform_prealloc(adapter,
-				3, STATIC_BUF_SIZE + STATIC_BUF_TOTAL_LEN))) {
-				printk("can not alloc static buf!\n");
-				bcm_static_skb = NULL;
-				ASSERT(osh->magic == OS_HANDLE_MAGIC);
-				return -ENOMEM;
-			} else {
-				printk("alloc static buf at %p!\n", bcm_static_buf);
-			}
-
-			sema_init(&bcm_static_buf->static_sem, 1);
-
-			bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE;
-		}
-
-#if defined(BCMSDIO) || defined(DHD_USE_STATIC_CTRLBUF)
-		if (!bcm_static_skb && adapter) {
-			int i;
-			void *skb_buff_ptr = 0;
-			bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048);
-			skb_buff_ptr = wifi_platform_prealloc(adapter, 4, 0);
-			if (!skb_buff_ptr) {
-				printk("cannot alloc static buf!\n");
-				bcm_static_buf = NULL;
-				bcm_static_skb = NULL;
-				ASSERT(osh->magic == OS_HANDLE_MAGIC);
-				return -ENOMEM;
-			}
-
-			bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) *
-				(STATIC_PKT_MAX_NUM));
-			for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
-				bcm_static_skb->pkt_use[i] = 0;
-			}
-
-#ifdef DHD_USE_STATIC_CTRLBUF
-			spin_lock_init(&bcm_static_skb->osl_pkt_lock);
-			bcm_static_skb->last_allocated_index = 0;
-#else
-			sema_init(&bcm_static_skb->osl_pkt_sem, 1);
-#endif /* DHD_USE_STATIC_CTRLBUF */
-		}
-#endif /* BCMSDIO || DHD_USE_STATIC_CTRLBUF */
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-
-	return 0;
-}
-
-void osl_set_bus_handle(osl_t *osh, void *bus_handle)
-{
-	osh->bus_handle = bus_handle;
-}
-
-void* osl_get_bus_handle(osl_t *osh)
-{
-	return osh->bus_handle;
-}
-
-void
-osl_detach(osl_t *osh)
-{
-	if (osh == NULL)
-		return;
-
-#ifdef BCM_SECURE_DMA
-	osl_sec_dma_free_contig_mem(osh, CMA_MEMBLOCK, CONT_ARMREGION);
-	osl_sec_dma_deinit_elem_mem_block(osh, CMA_BUFSIZE_512, CMA_BUFNUM, osh->sec_list_base_512);
-	osl_sec_dma_deinit_elem_mem_block(osh, CMA_BUFSIZE_2K, CMA_BUFNUM, osh->sec_list_base_2048);
-	osl_sec_dma_deinit_elem_mem_block(osh, CMA_BUFSIZE_4K, CMA_BUFNUM, osh->sec_list_base_4096);
-	osl_sec_dma_iounmap(osh, osh->contig_base_va, CMA_MEMBLOCK);
-#endif /* BCM_SECURE_DMA */
-
-
-	bcm_object_trace_deinit();
-
-	ASSERT(osh->magic == OS_HANDLE_MAGIC);
-	atomic_sub(1, &osh->cmn->refcount);
-	if (atomic_read(&osh->cmn->refcount) == 0) {
-			kfree(osh->cmn);
-	}
-	kfree(osh);
-}
-
-int osl_static_mem_deinit(osl_t *osh, void *adapter)
-{
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-	if (bcm_static_buf) {
-		bcm_static_buf = 0;
-	}
-#ifdef BCMSDIO
-	if (bcm_static_skb) {
-		bcm_static_skb = 0;
-	}
-#endif /* BCMSDIO */
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-	return 0;
-}
-
-static struct sk_buff *osl_alloc_skb(osl_t *osh, unsigned int len)
-{
-	struct sk_buff *skb;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
-	gfp_t flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
-#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_ZONE_DMA)
-	flags |= GFP_ATOMIC;
-#endif
-#ifdef DHD_USE_ATOMIC_PKTGET
-	flags = GFP_ATOMIC;
-#endif /* DHD_USE_ATOMIC_PKTGET */
-	skb = __dev_alloc_skb(len, flags);
-#else
-	skb = dev_alloc_skb(len);
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) */
-	return skb;
-}
-
-#ifdef CTFPOOL
-
-#ifdef CTFPOOL_SPINLOCK
-#define CTFPOOL_LOCK(ctfpool, flags)	spin_lock_irqsave(&(ctfpool)->lock, flags)
-#define CTFPOOL_UNLOCK(ctfpool, flags)	spin_unlock_irqrestore(&(ctfpool)->lock, flags)
-#else
-#define CTFPOOL_LOCK(ctfpool, flags)	spin_lock_bh(&(ctfpool)->lock)
-#define CTFPOOL_UNLOCK(ctfpool, flags)	spin_unlock_bh(&(ctfpool)->lock)
-#endif /* CTFPOOL_SPINLOCK */
-/*
- * Allocate and add an object to packet pool.
- */
-void *
-osl_ctfpool_add(osl_t *osh)
-{
-	struct sk_buff *skb;
-#ifdef CTFPOOL_SPINLOCK
-	unsigned long flags;
-#endif /* CTFPOOL_SPINLOCK */
-
-	if ((osh == NULL) || (osh->ctfpool == NULL))
-		return NULL;
-
-	CTFPOOL_LOCK(osh->ctfpool, flags);
-	ASSERT(osh->ctfpool->curr_obj <= osh->ctfpool->max_obj);
-
-	/* No need to allocate more objects */
-	if (osh->ctfpool->curr_obj == osh->ctfpool->max_obj) {
-		CTFPOOL_UNLOCK(osh->ctfpool, flags);
-		return NULL;
-	}
-
-	/* Allocate a new skb and add it to the ctfpool */
-	skb = osl_alloc_skb(osh, osh->ctfpool->obj_size);
-	if (skb == NULL) {
-		printf("%s: skb alloc of len %d failed\n", __FUNCTION__,
-		       osh->ctfpool->obj_size);
-		CTFPOOL_UNLOCK(osh->ctfpool, flags);
-		return NULL;
-	}
-
-	/* Add to ctfpool */
-	skb->next = (struct sk_buff *)osh->ctfpool->head;
-	osh->ctfpool->head = skb;
-	osh->ctfpool->fast_frees++;
-	osh->ctfpool->curr_obj++;
-
-	/* Hijack a skb member to store ptr to ctfpool */
-	CTFPOOLPTR(osh, skb) = (void *)osh->ctfpool;
-
-	/* Use bit flag to indicate skb from fast ctfpool */
-	PKTFAST(osh, skb) = FASTBUF;
-
-	CTFPOOL_UNLOCK(osh->ctfpool, flags);
-
-	return skb;
-}
-
-/*
- * Add new objects to the pool.
- */
-void
-osl_ctfpool_replenish(osl_t *osh, uint thresh)
-{
-	if ((osh == NULL) || (osh->ctfpool == NULL))
-		return;
-
-	/* Do nothing if no refills are required */
-	while ((osh->ctfpool->refills > 0) && (thresh--)) {
-		osl_ctfpool_add(osh);
-		osh->ctfpool->refills--;
-	}
-}
-
-/*
- * Initialize the packet pool with specified number of objects.
- */
-int32
-osl_ctfpool_init(osl_t *osh, uint numobj, uint size)
-{
-	gfp_t flags;
-
-	flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
-	osh->ctfpool = kzalloc(sizeof(ctfpool_t), flags);
-	ASSERT(osh->ctfpool);
-
-	osh->ctfpool->max_obj = numobj;
-	osh->ctfpool->obj_size = size;
-
-	spin_lock_init(&osh->ctfpool->lock);
-
-	while (numobj--) {
-		if (!osl_ctfpool_add(osh))
-			return -1;
-		osh->ctfpool->fast_frees--;
-	}
-
-	return 0;
-}
-
-/*
- * Cleanup the packet pool objects.
- */
-void
-osl_ctfpool_cleanup(osl_t *osh)
-{
-	struct sk_buff *skb, *nskb;
-#ifdef CTFPOOL_SPINLOCK
-	unsigned long flags;
-#endif /* CTFPOOL_SPINLOCK */
-
-	if ((osh == NULL) || (osh->ctfpool == NULL))
-		return;
-
-	CTFPOOL_LOCK(osh->ctfpool, flags);
-
-	skb = osh->ctfpool->head;
-
-	while (skb != NULL) {
-		nskb = skb->next;
-		dev_kfree_skb(skb);
-		skb = nskb;
-		osh->ctfpool->curr_obj--;
-	}
-
-	ASSERT(osh->ctfpool->curr_obj == 0);
-	osh->ctfpool->head = NULL;
-	CTFPOOL_UNLOCK(osh->ctfpool, flags);
-
-	kfree(osh->ctfpool);
-	osh->ctfpool = NULL;
-}
-
-void
-osl_ctfpool_stats(osl_t *osh, void *b)
-{
-	struct bcmstrbuf *bb;
-
-	if ((osh == NULL) || (osh->ctfpool == NULL))
-		return;
-
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-	if (bcm_static_buf) {
-		bcm_static_buf = 0;
-	}
-#ifdef BCMSDIO
-	if (bcm_static_skb) {
-		bcm_static_skb = 0;
-	}
-#endif /* BCMSDIO */
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-
-	bb = b;
-
-	ASSERT((osh != NULL) && (bb != NULL));
-
-	bcm_bprintf(bb, "max_obj %d obj_size %d curr_obj %d refills %d\n",
-	            osh->ctfpool->max_obj, osh->ctfpool->obj_size,
-	            osh->ctfpool->curr_obj, osh->ctfpool->refills);
-	bcm_bprintf(bb, "fast_allocs %d fast_frees %d slow_allocs %d\n",
-	            osh->ctfpool->fast_allocs, osh->ctfpool->fast_frees,
-	            osh->ctfpool->slow_allocs);
-}
-
-static inline struct sk_buff *
-osl_pktfastget(osl_t *osh, uint len)
-{
-	struct sk_buff *skb;
-#ifdef CTFPOOL_SPINLOCK
-	unsigned long flags;
-#endif /* CTFPOOL_SPINLOCK */
-
-	/* Try to do fast allocate. Return null if ctfpool is not in use
-	 * or if there are no items in the ctfpool.
-	 */
-	if (osh->ctfpool == NULL)
-		return NULL;
-
-	CTFPOOL_LOCK(osh->ctfpool, flags);
-	if (osh->ctfpool->head == NULL) {
-		ASSERT(osh->ctfpool->curr_obj == 0);
-		osh->ctfpool->slow_allocs++;
-		CTFPOOL_UNLOCK(osh->ctfpool, flags);
-		return NULL;
-	}
-
-	if (len > osh->ctfpool->obj_size) {
-		CTFPOOL_UNLOCK(osh->ctfpool, flags);
-		return NULL;
-	}
-
-	ASSERT(len <= osh->ctfpool->obj_size);
-
-	/* Get an object from ctfpool */
-	skb = (struct sk_buff *)osh->ctfpool->head;
-	osh->ctfpool->head = (void *)skb->next;
-
-	osh->ctfpool->fast_allocs++;
-	osh->ctfpool->curr_obj--;
-	ASSERT(CTFPOOLHEAD(osh, skb) == (struct sock *)osh->ctfpool->head);
-	CTFPOOL_UNLOCK(osh->ctfpool, flags);
-
-	/* Init skb struct */
-	skb->next = skb->prev = NULL;
-#if defined(__ARM_ARCH_7A__)
-	skb->data = skb->head + NET_SKB_PAD;
-	skb->tail = skb->head + NET_SKB_PAD;
-#else
-	skb->data = skb->head + 16;
-	skb->tail = skb->head + 16;
-#endif /* __ARM_ARCH_7A__ */
-	skb->len = 0;
-	skb->cloned = 0;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
-	skb->list = NULL;
-#endif
-	atomic_set(&skb->users, 1);
-
-	PKTSETCLINK(skb, NULL);
-	PKTCCLRATTR(skb);
-	PKTFAST(osh, skb) &= ~(CTFBUF | SKIPCT | CHAINED);
-
-	return skb;
-}
-#endif /* CTFPOOL */
-
-#if defined(BCM_GMAC3)
-/* Account for a packet delivered to downstream forwarder.
- * Decrement a GMAC forwarder interface's pktalloced count.
- */
-void BCMFASTPATH
-osl_pkt_tofwder(osl_t *osh, void *skbs, int skb_cnt)
-{
-
-	atomic_sub(skb_cnt, &osh->cmn->pktalloced);
-}
-
-/* Account for a downstream forwarder delivered packet to a WL/DHD driver.
- * Increment a GMAC forwarder interface's pktalloced count.
- */
-#ifdef BCMDBG_CTRACE
-void BCMFASTPATH
-osl_pkt_frmfwder(osl_t *osh, void *skbs, int skb_cnt, int line, char *file)
-#else
-void BCMFASTPATH
-osl_pkt_frmfwder(osl_t *osh, void *skbs, int skb_cnt)
-#endif /* BCMDBG_CTRACE */
-{
-#if defined(BCMDBG_CTRACE)
-	int i;
-	struct sk_buff *skb;
-#endif 
-
-#if defined(BCMDBG_CTRACE)
-	if (skb_cnt > 1) {
-		struct sk_buff **skb_array = (struct sk_buff **)skbs;
-		for (i = 0; i < skb_cnt; i++) {
-			skb = skb_array[i];
-#if defined(BCMDBG_CTRACE)
-			ASSERT(!PKTISCHAINED(skb));
-			ADD_CTRACE(osh, skb, file, line);
-#endif /* BCMDBG_CTRACE */
-		}
-	} else {
-		skb = (struct sk_buff *)skbs;
-#if defined(BCMDBG_CTRACE)
-		ASSERT(!PKTISCHAINED(skb));
-		ADD_CTRACE(osh, skb, file, line);
-#endif /* BCMDBG_CTRACE */
-	}
-#endif 
-
-	atomic_add(skb_cnt, &osh->cmn->pktalloced);
-}
-
-#endif /* BCM_GMAC3 */
-
-/* Convert a driver packet to native(OS) packet
- * In the process, packettag is zeroed out before sending up
- * IP code depends on skb->cb to be setup correctly with various options
- * In our case, that means it should be 0
- */
-struct sk_buff * BCMFASTPATH
-osl_pkt_tonative(osl_t *osh, void *pkt)
-{
-	struct sk_buff *nskb;
-#ifdef BCMDBG_CTRACE
-	struct sk_buff *nskb1, *nskb2;
-#endif
-
-	if (osh->pub.pkttag)
-		OSL_PKTTAG_CLEAR(pkt);
-
-	/* Decrement the packet counter */
-	for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
-		atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->cmn->pktalloced);
-
-#ifdef BCMDBG_CTRACE
-		for (nskb1 = nskb; nskb1 != NULL; nskb1 = nskb2) {
-			if (PKTISCHAINED(nskb1)) {
-				nskb2 = PKTCLINK(nskb1);
-			}
-			else
-				nskb2 = NULL;
-
-			DEL_CTRACE(osh, nskb1);
-		}
-#endif /* BCMDBG_CTRACE */
-	}
-	return (struct sk_buff *)pkt;
-}
-
-/* Convert a native(OS) packet to driver packet.
- * In the process, native packet is destroyed, there is no copying
- * Also, a packettag is zeroed out
- */
-#ifdef BCMDBG_CTRACE
-void * BCMFASTPATH
-osl_pkt_frmnative(osl_t *osh, void *pkt, int line, char *file)
-#else
-void * BCMFASTPATH
-osl_pkt_frmnative(osl_t *osh, void *pkt)
-#endif /* BCMDBG_CTRACE */
-{
-	struct sk_buff *nskb;
-#ifdef BCMDBG_CTRACE
-	struct sk_buff *nskb1, *nskb2;
-#endif
-
-	if (osh->pub.pkttag)
-		OSL_PKTTAG_CLEAR(pkt);
-
-	/* Increment the packet counter */
-	for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
-		atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->cmn->pktalloced);
-
-#ifdef BCMDBG_CTRACE
-		for (nskb1 = nskb; nskb1 != NULL; nskb1 = nskb2) {
-			if (PKTISCHAINED(nskb1)) {
-				nskb2 = PKTCLINK(nskb1);
-			}
-			else
-				nskb2 = NULL;
-
-			ADD_CTRACE(osh, nskb1, file, line);
-		}
-#endif /* BCMDBG_CTRACE */
-	}
-	return (void *)pkt;
-}
-
-/* Return a new packet. zero out pkttag */
-#ifdef BCMDBG_CTRACE
-void * BCMFASTPATH
-osl_pktget(osl_t *osh, uint len, int line, char *file)
-#else
-#ifdef BCM_OBJECT_TRACE
-void * BCMFASTPATH
-osl_pktget(osl_t *osh, uint len, int line, const char *caller)
-#else
-void * BCMFASTPATH
-osl_pktget(osl_t *osh, uint len)
-#endif /* BCM_OBJECT_TRACE */
-#endif /* BCMDBG_CTRACE */
-{
-	struct sk_buff *skb;
-	uchar num = 0;
-	if (lmtest != FALSE) {
-		get_random_bytes(&num, sizeof(uchar));
-		if ((num + 1) <= (256 * lmtest / 100))
-			return NULL;
-	}
-
-#ifdef CTFPOOL
-	/* Allocate from local pool */
-	skb = osl_pktfastget(osh, len);
-	if ((skb != NULL) || ((skb = osl_alloc_skb(osh, len)) != NULL)) {
-#else /* CTFPOOL */
-	if ((skb = osl_alloc_skb(osh, len))) {
-#endif /* CTFPOOL */
-		skb->tail += len;
-		skb->len  += len;
-		skb->priority = 0;
-
-#ifdef BCMDBG_CTRACE
-		ADD_CTRACE(osh, skb, file, line);
-#endif
-		atomic_inc(&osh->cmn->pktalloced);
-#ifdef BCM_OBJECT_TRACE
-		bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, caller, line);
-#endif /* BCM_OBJECT_TRACE */
-	}
-
-	return ((void*) skb);
-}
-
-#ifdef CTFPOOL
-static inline void
-osl_pktfastfree(osl_t *osh, struct sk_buff *skb)
-{
-	ctfpool_t *ctfpool;
-#ifdef CTFPOOL_SPINLOCK
-	unsigned long flags;
-#endif /* CTFPOOL_SPINLOCK */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
-	skb->tstamp.tv.sec = 0;
-#else
-	skb->stamp.tv_sec = 0;
-#endif
-
-	/* We only need to init the fields that we change */
-	skb->dev = NULL;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
-	skb->dst = NULL;
-#endif
-	OSL_PKTTAG_CLEAR(skb);
-	skb->ip_summed = 0;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
-	skb_orphan(skb);
-#else
-	skb->destructor = NULL;
-#endif
-
-	ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb);
-	ASSERT(ctfpool != NULL);
-
-	/* Add object to the ctfpool */
-	CTFPOOL_LOCK(ctfpool, flags);
-	skb->next = (struct sk_buff *)ctfpool->head;
-	ctfpool->head = (void *)skb;
-
-	ctfpool->fast_frees++;
-	ctfpool->curr_obj++;
-
-	ASSERT(ctfpool->curr_obj <= ctfpool->max_obj);
-	CTFPOOL_UNLOCK(ctfpool, flags);
-}
-#endif /* CTFPOOL */
-
-/* Free the driver packet. Free the tag if present */
-#ifdef BCM_OBJECT_TRACE
-void BCMFASTPATH
-osl_pktfree(osl_t *osh, void *p, bool send, int line, const char *caller)
-#else
-void BCMFASTPATH
-osl_pktfree(osl_t *osh, void *p, bool send)
-#endif /* BCM_OBJECT_TRACE */
-{
-	struct sk_buff *skb, *nskb;
-	if (osh == NULL)
-		return;
-
-	skb = (struct sk_buff*) p;
-
-	if (send && osh->pub.tx_fn)
-		osh->pub.tx_fn(osh->pub.tx_ctx, p, 0);
-
-	PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE);
-
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_CTRLBUF)
-	if (skb && (skb->mac_len == PREALLOC_USED_MAGIC)) {
-		printk("%s: pkt %p is from static pool\n",
-			__FUNCTION__, p);
-		dump_stack();
-		return;
-	}
-
-	if (skb && (skb->mac_len == PREALLOC_FREE_MAGIC)) {
-		printk("%s: pkt %p is from static pool and not in used\n",
-			__FUNCTION__, p);
-		dump_stack();
-		return;
-	}
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_CTRLBUF */
-
-	/* perversion: we use skb->next to chain multi-skb packets */
-	while (skb) {
-		nskb = skb->next;
-		skb->next = NULL;
-
-#ifdef BCMDBG_CTRACE
-		DEL_CTRACE(osh, skb);
-#endif
-
-
-#ifdef BCM_OBJECT_TRACE
-		bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, caller, line);
-#endif /* BCM_OBJECT_TRACE */
-
-#ifdef CTFPOOL
-		if (PKTISFAST(osh, skb)) {
-			if (atomic_read(&skb->users) == 1)
-				smp_rmb();
-			else if (!atomic_dec_and_test(&skb->users))
-				goto next_skb;
-			osl_pktfastfree(osh, skb);
-		} else
-#endif
-		{
-			dev_kfree_skb_any(skb);
-		}
-#ifdef CTFPOOL
-next_skb:
-#endif
-		atomic_dec(&osh->cmn->pktalloced);
-		skb = nskb;
-	}
-}
-
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-void*
-osl_pktget_static(osl_t *osh, uint len)
-{
-	int i = 0;
-	struct sk_buff *skb;
-#ifdef DHD_USE_STATIC_CTRLBUF
-	unsigned long flags;
-#endif /* DHD_USE_STATIC_CTRLBUF */
-
-	if (!bcm_static_skb)
-		return osl_pktget(osh, len);
-
-	if (len > DHD_SKB_MAX_BUFSIZE) {
-		printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len);
-		return osl_pktget(osh, len);
-	}
-
-#ifdef DHD_USE_STATIC_CTRLBUF
-	spin_lock_irqsave(&bcm_static_skb->osl_pkt_lock, flags);
-
-	if (len <= DHD_SKB_2PAGE_BUFSIZE) {
-		uint32 index;
-		for (i = 0; i < STATIC_PKT_2PAGE_NUM; i++) {
-			index = bcm_static_skb->last_allocated_index % STATIC_PKT_2PAGE_NUM;
-			bcm_static_skb->last_allocated_index++;
-			if (bcm_static_skb->skb_8k[index] &&
-				bcm_static_skb->pkt_use[index] == 0) {
-				break;
-			}
-		}
-
-		if ((i != STATIC_PKT_2PAGE_NUM) &&
-			(index >= 0) && (index < STATIC_PKT_2PAGE_NUM)) {
-			bcm_static_skb->pkt_use[index] = 1;
-			skb = bcm_static_skb->skb_8k[index];
-			skb->data = skb->head;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-			skb_set_tail_pointer(skb, NET_SKB_PAD);
-#else
-			skb->tail = skb->data + NET_SKB_PAD;
-#endif /* NET_SKBUFF_DATA_USES_OFFSET */
-			skb->data += NET_SKB_PAD;
-			skb->cloned = 0;
-			skb->priority = 0;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-			skb_set_tail_pointer(skb, len);
-#else
-			skb->tail = skb->data + len;
-#endif /* NET_SKBUFF_DATA_USES_OFFSET */
-			skb->len = len;
-			skb->mac_len = PREALLOC_USED_MAGIC;
-			spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags);
-			return skb;
-		}
-	}
-
-	spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags);
-	printk("%s: all static pkt in use!\n", __FUNCTION__);
-	return NULL;
-#else
-	down(&bcm_static_skb->osl_pkt_sem);
-
-	if (len <= DHD_SKB_1PAGE_BUFSIZE) {
-		for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
-			if (bcm_static_skb->skb_4k[i] &&
-				bcm_static_skb->pkt_use[i] == 0) {
-				break;
-			}
-		}
-
-		if (i != STATIC_PKT_MAX_NUM) {
-			bcm_static_skb->pkt_use[i] = 1;
-
-			skb = bcm_static_skb->skb_4k[i];
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-			skb_set_tail_pointer(skb, len);
-#else
-			skb->tail = skb->data + len;
-#endif /* NET_SKBUFF_DATA_USES_OFFSET */
-			skb->len = len;
-
-			up(&bcm_static_skb->osl_pkt_sem);
-			return skb;
-		}
-	}
-
-	if (len <= DHD_SKB_2PAGE_BUFSIZE) {
-		for (i = STATIC_PKT_1PAGE_NUM; i < STATIC_PKT_1_2PAGE_NUM; i++) {
-			if (bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM] &&
-				bcm_static_skb->pkt_use[i] == 0) {
-				break;
-			}
-		}
-
-		if ((i >= STATIC_PKT_1PAGE_NUM) && (i < STATIC_PKT_1_2PAGE_NUM)) {
-			bcm_static_skb->pkt_use[i] = 1;
-			skb = bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM];
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-			skb_set_tail_pointer(skb, len);
-#else
-			skb->tail = skb->data + len;
-#endif /* NET_SKBUFF_DATA_USES_OFFSET */
-			skb->len = len;
-
-			up(&bcm_static_skb->osl_pkt_sem);
-			return skb;
-		}
-	}
-
-#if defined(ENHANCED_STATIC_BUF)
-	if (bcm_static_skb->skb_16k &&
-		bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] == 0) {
-		bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] = 1;
-
-		skb = bcm_static_skb->skb_16k;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-		skb_set_tail_pointer(skb, len);
-#else
-		skb->tail = skb->data + len;
-#endif /* NET_SKBUFF_DATA_USES_OFFSET */
-		skb->len = len;
-
-		up(&bcm_static_skb->osl_pkt_sem);
-		return skb;
-	}
-#endif /* ENHANCED_STATIC_BUF */
-
-	up(&bcm_static_skb->osl_pkt_sem);
-	printk("%s: all static pkt in use!\n", __FUNCTION__);
-	return osl_pktget(osh, len);
-#endif /* DHD_USE_STATIC_CTRLBUF */
-}
-
-void
-osl_pktfree_static(osl_t *osh, void *p, bool send)
-{
-	int i;
-#ifdef DHD_USE_STATIC_CTRLBUF
-	struct sk_buff *skb = (struct sk_buff *)p;
-	unsigned long flags;
-#endif /* DHD_USE_STATIC_CTRLBUF */
-
-	if (!p) {
-		return;
-	}
-
-	if (!bcm_static_skb) {
-		osl_pktfree(osh, p, send);
-		return;
-	}
-
-#ifdef DHD_USE_STATIC_CTRLBUF
-	spin_lock_irqsave(&bcm_static_skb->osl_pkt_lock, flags);
-
-	for (i = 0; i < STATIC_PKT_2PAGE_NUM; i++) {
-		if (p == bcm_static_skb->skb_8k[i]) {
-			if (bcm_static_skb->pkt_use[i] == 0) {
-				printk("%s: static pkt idx %d(%p) is double free\n",
-					__FUNCTION__, i, p);
-			} else {
-				bcm_static_skb->pkt_use[i] = 0;
-			}
-
-			if (skb->mac_len != PREALLOC_USED_MAGIC) {
-				printk("%s: static pkt idx %d(%p) is not in used\n",
-					__FUNCTION__, i, p);
-			}
-
-			skb->mac_len = PREALLOC_FREE_MAGIC;
-			spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags);
-			return;
-		}
-	}
-
-	spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags);
-	printk("%s: packet %p does not exist in the pool\n", __FUNCTION__, p);
-#else
-	down(&bcm_static_skb->osl_pkt_sem);
-	for (i = 0; i < STATIC_PKT_1PAGE_NUM; i++) {
-		if (p == bcm_static_skb->skb_4k[i]) {
-			bcm_static_skb->pkt_use[i] = 0;
-			up(&bcm_static_skb->osl_pkt_sem);
-			return;
-		}
-	}
-
-	for (i = STATIC_PKT_1PAGE_NUM; i < STATIC_PKT_1_2PAGE_NUM; i++) {
-		if (p == bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM]) {
-			bcm_static_skb->pkt_use[i] = 0;
-			up(&bcm_static_skb->osl_pkt_sem);
-			return;
-		}
-	}
-#ifdef ENHANCED_STATIC_BUF
-	if (p == bcm_static_skb->skb_16k) {
-		bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] = 0;
-		up(&bcm_static_skb->osl_pkt_sem);
-		return;
-	}
-#endif
-	up(&bcm_static_skb->osl_pkt_sem);
-	osl_pktfree(osh, p, send);
-#endif /* DHD_USE_STATIC_CTRLBUF */
-}
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-
-uint32
-osl_pci_read_config(osl_t *osh, uint offset, uint size)
-{
-	uint val = 0;
-	uint retry = PCI_CFG_RETRY;
-
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-
-	/* only 4byte access supported */
-	ASSERT(size == 4);
-
-	do {
-		pci_read_config_dword(osh->pdev, offset, &val);
-		if (val != 0xffffffff)
-			break;
-	} while (retry--);
-
-
-	return (val);
-}
-
-void
-osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
-{
-	uint retry = PCI_CFG_RETRY;
-
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-
-	/* only 4byte access supported */
-	ASSERT(size == 4);
-
-	do {
-		pci_write_config_dword(osh->pdev, offset, val);
-		if (offset != PCI_BAR0_WIN)
-			break;
-		if (osl_pci_read_config(osh, offset, size) == val)
-			break;
-	} while (retry--);
-
-}
-
-/* return bus # for the pci device pointed by osh->pdev */
-uint
-osl_pci_bus(osl_t *osh)
-{
-	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
-
-#if defined(__ARM_ARCH_7A__) && LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
-	return pci_domain_nr(((struct pci_dev *)osh->pdev)->bus);
-#else
-	return ((struct pci_dev *)osh->pdev)->bus->number;
-#endif
-}
-
-/* return slot # for the pci device pointed by osh->pdev */
-uint
-osl_pci_slot(osl_t *osh)
-{
-	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
-
-#if defined(__ARM_ARCH_7A__) && LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
-	return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn) + 1;
-#else
-	return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn);
-#endif
-}
-
-/* return domain # for the pci device pointed by osh->pdev */
-uint
-osl_pcie_domain(osl_t *osh)
-{
-	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
-
-	return pci_domain_nr(((struct pci_dev *)osh->pdev)->bus);
-}
-
-/* return bus # for the pci device pointed by osh->pdev */
-uint
-osl_pcie_bus(osl_t *osh)
-{
-	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
-
-	return ((struct pci_dev *)osh->pdev)->bus->number;
-}
-
-/* return the pci device pointed by osh->pdev */
-struct pci_dev *
-osl_pci_device(osl_t *osh)
-{
-	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
-
-	return osh->pdev;
-}
-
-static void
-osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write)
-{
-}
-
-void
-osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size)
-{
-	osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE);
-}
-
-void
-osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size)
-{
-	osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE);
-}
-
-void *
-osl_malloc(osl_t *osh, uint size)
-{
-	void *addr;
-	gfp_t flags;
-
-	/* only ASSERT if osh is defined */
-	if (osh)
-		ASSERT(osh->magic == OS_HANDLE_MAGIC);
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-	if (bcm_static_buf)
-	{
-		int i = 0;
-		if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE))
-		{
-			down(&bcm_static_buf->static_sem);
-
-			for (i = 0; i < STATIC_BUF_MAX_NUM; i++)
-			{
-				if (bcm_static_buf->buf_use[i] == 0)
-					break;
-			}
-
-			if (i == STATIC_BUF_MAX_NUM)
-			{
-				up(&bcm_static_buf->static_sem);
-				printk("all static buff in use!\n");
-				goto original;
-			}
-
-			bcm_static_buf->buf_use[i] = 1;
-			up(&bcm_static_buf->static_sem);
-
-			bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size);
-			if (osh)
-				atomic_add(size, &osh->cmn->malloced);
-
-			return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i));
-		}
-	}
-original:
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-
-	flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC;
-	if ((addr = kmalloc(size, flags)) == NULL) {
-		if (osh)
-			osh->failed++;
-		return (NULL);
-	}
-	if (osh && osh->cmn)
-		atomic_add(size, &osh->cmn->malloced);
-
-	return (addr);
-}
-
-void *
-osl_mallocz(osl_t *osh, uint size)
-{
-	void *ptr;
-
-	ptr = osl_malloc(osh, size);
-
-	if (ptr != NULL) {
-		bzero(ptr, size);
-	}
-
-	return ptr;
-}
-
-void
-osl_mfree(osl_t *osh, void *addr, uint size)
-{
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-	if (bcm_static_buf)
-	{
-		if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr
-			<= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN)))
-		{
-			int buf_idx = 0;
-
-			buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE;
-
-			down(&bcm_static_buf->static_sem);
-			bcm_static_buf->buf_use[buf_idx] = 0;
-			up(&bcm_static_buf->static_sem);
-
-			if (osh && osh->cmn) {
-				ASSERT(osh->magic == OS_HANDLE_MAGIC);
-				atomic_sub(size, &osh->cmn->malloced);
-			}
-			return;
-		}
-	}
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-	if (osh && osh->cmn) {
-		ASSERT(osh->magic == OS_HANDLE_MAGIC);
-
-		ASSERT(size <= osl_malloced(osh));
-
-		atomic_sub(size, &osh->cmn->malloced);
-	}
-	kfree(addr);
-}
-
-uint
-osl_check_memleak(osl_t *osh)
-{
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-	if (atomic_read(&osh->cmn->refcount) == 1)
-		return (atomic_read(&osh->cmn->malloced));
-	else
-		return 0;
-}
-
-uint
-osl_malloced(osl_t *osh)
-{
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-	return (atomic_read(&osh->cmn->malloced));
-}
-
-uint
-osl_malloc_failed(osl_t *osh)
-{
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-	return (osh->failed);
-}
-
-
-uint
-osl_dma_consistent_align(void)
-{
-	return (PAGE_SIZE);
-}
-
-void*
-osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, dmaaddr_t *pap)
-{
-	void *va;
-	uint16 align = (1 << align_bits);
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-
-	if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align))
-		size += align;
-	*alloced = size;
-
-#ifndef	BCM_SECURE_DMA
-#if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)
-	va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO);
-	if (va)
-		*pap = (ulong)__virt_to_phys((ulong)va);
-#else
-	{
-		dma_addr_t pap_lin;
-		struct pci_dev *hwdev = osh->pdev;
-		gfp_t flags;
-#ifdef DHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL
-		flags = GFP_ATOMIC;
-#else
-		flags = GFP_KERNEL;
-#endif /* DHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL */
-		va = dma_alloc_coherent(&hwdev->dev, size, &pap_lin, flags);
-#ifdef BCMDMA64OSL
-		PHYSADDRLOSET(*pap, pap_lin & 0xffffffff);
-		PHYSADDRHISET(*pap, (pap_lin >> 32) & 0xffffffff);
-#else
-		*pap = (dmaaddr_t)pap_lin;
-#endif /* BCMDMA64OSL */
-	}
-#endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */
-#else
-	va = osl_sec_dma_alloc_consistent(osh, size, align_bits, pap);
-#endif /* BCM_SECURE_DMA */
-	return va;
-}
-
-void
-osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa)
-{
-#ifdef BCMDMA64OSL
-	dma_addr_t paddr;
-#endif /* BCMDMA64OSL */
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-
-#ifndef BCM_SECURE_DMA
-#if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)
-	kfree(va);
-#else
-#ifdef BCMDMA64OSL
-	PHYSADDRTOULONG(pa, paddr);
-	pci_free_consistent(osh->pdev, size, va, paddr);
-#else
-	pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa);
-#endif /* BCMDMA64OSL */
-#endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */
-#else
-	osl_sec_dma_free_consistent(osh, va, size, pa);
-#endif /* BCM_SECURE_DMA */
-}
-
-dmaaddr_t BCMFASTPATH
-osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah)
-{
-	int dir;
-#ifdef BCMDMA64OSL
-	dmaaddr_t ret;
-	dma_addr_t  map_addr;
-#endif /* BCMDMA64OSL */
-
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-	dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
-
-
-
-
-#ifdef BCMDMA64OSL
-	map_addr = pci_map_single(osh->pdev, va, size, dir);
-	PHYSADDRLOSET(ret, map_addr & 0xffffffff);
-	PHYSADDRHISET(ret, (map_addr >> 32) & 0xffffffff);
-	return ret;
-#else
-	return (pci_map_single(osh->pdev, va, size, dir));
-#endif /* BCMDMA64OSL */
-}
-
-void BCMFASTPATH
-osl_dma_unmap(osl_t *osh, dmaaddr_t pa, uint size, int direction)
-{
-	int dir;
-#ifdef BCMDMA64OSL
-	dma_addr_t paddr;
-#endif /* BCMDMA64OSL */
-
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-
-
-	dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
-#ifdef BCMDMA64OSL
-	PHYSADDRTOULONG(pa, paddr);
-	pci_unmap_single(osh->pdev, paddr, size, dir);
-#else
-	pci_unmap_single(osh->pdev, (uint32)pa, size, dir);
-#endif /* BCMDMA64OSL */
-}
-
-/* OSL function for CPU relax */
-inline void BCMFASTPATH
-osl_cpu_relax(void)
-{
-	cpu_relax();
-}
-
-
-#if (defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING) || \
-	defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_SOC_EXYNOS8890))
-
-#include <asm/dma-mapping.h>
-
-/*
- * Note that its gauranteed that the Ring is cache line aligned, but
- * the messages are not. And we see that __dma_inv_range in
- * arch/arm64/mm/cache.S invalidates only if the request size is
- * cache line aligned. If not, it will Clean and invalidate.
- * So we'll better invalidate the whole ring.
- *
- * Also, the latest Kernel versions invoke cache maintenance operations
- * from arch/arm64/mm/dma-mapping.c, __swiotlb_sync_single_for_device
- * Only if is_device_dma_coherent returns 0. Since we don't have BSP
- * source, assuming that its the case, since we pass NULL for the dev ptr
- */
-inline void BCMFASTPATH
-osl_cache_flush(void *va, uint size)
-{
-	/*
-	 * using long for address arithmatic is OK, in linux
-	 * 32 bit its 4 bytes and 64 bit its 8 bytes
-	 */
-	unsigned long end_cache_line_start;
-	unsigned long end_addr;
-	unsigned long next_cache_line_start;
-
-	end_addr = (unsigned long)va + size;
-
-	/* Start address beyond the cache line we plan to operate */
-	end_cache_line_start = (end_addr & ~(L1_CACHE_BYTES - 1));
-	next_cache_line_start = end_cache_line_start + L1_CACHE_BYTES;
-
-	/* Align the start address to cache line boundary */
-	va = (void *)((unsigned long)va & ~(L1_CACHE_BYTES - 1));
-
-	/* Ensure that size is also aligned and extends partial line to full */
-	size = next_cache_line_start - (unsigned long)va;
-
-#ifndef BCM_SECURE_DMA
-
-#ifdef CONFIG_ARM64
-	/*
-	 * virt_to_dma is not present in arm64/include/dma-mapping.h
-	 * So have to convert the va to pa first and then get the dma addr
-	 * of the same.
-	 */
-	{
-		phys_addr_t pa;
-		dma_addr_t dma_addr;
-		pa = virt_to_phys(va);
-		dma_addr = phys_to_dma(NULL, pa);
-		if (size > 0)
-			dma_sync_single_for_device(OSH_NULL, dma_addr, size, DMA_TX);
-	}
-#else
-	if (size > 0)
-		dma_sync_single_for_device(OSH_NULL, virt_to_dma(OSH_NULL, va), size, DMA_TX);
-#endif /* !CONFIG_ARM64 */
-#else
-	phys_addr_t orig_pa = (phys_addr_t)(va - g_contig_delta_va_pa);
-	if (size > 0)
-		dma_sync_single_for_device(OSH_NULL, orig_pa, size, DMA_TX);
-#endif /* defined BCM_SECURE_DMA */
-}
-
-inline void BCMFASTPATH
-osl_cache_inv(void *va, uint size)
-{
-	/*
-	 * using long for address arithmatic is OK, in linux
-	 * 32 bit its 4 bytes and 64 bit its 8 bytes
-	 */
-	unsigned long end_cache_line_start;
-	unsigned long end_addr;
-	unsigned long next_cache_line_start;
-
-	end_addr = (unsigned long)va + size;
-
-	/* Start address beyond the cache line we plan to operate */
-	end_cache_line_start = (end_addr & ~(L1_CACHE_BYTES - 1));
-	next_cache_line_start = end_cache_line_start + L1_CACHE_BYTES;
-
-	/* Align the start address to cache line boundary */
-	va = (void *)((unsigned long)va & ~(L1_CACHE_BYTES - 1));
-
-	/* Ensure that size is also aligned and extends partial line to full */
-	size = next_cache_line_start - (unsigned long)va;
-
-#ifndef BCM_SECURE_DMA
-
-#ifdef CONFIG_ARM64
-	/*
-	 * virt_to_dma is not present in arm64/include/dma-mapping.h
-	 * So have to convert the va to pa first and then get the dma addr
-	 * of the same.
-	 */
-	{
-		phys_addr_t pa;
-		dma_addr_t dma_addr;
-		pa = virt_to_phys(va);
-		dma_addr = phys_to_dma(NULL, pa);
-		dma_sync_single_for_cpu(OSH_NULL, dma_addr, size, DMA_RX);
-	}
-#else
-	dma_sync_single_for_cpu(OSH_NULL, virt_to_dma(OSH_NULL, va), size, DMA_RX);
-#endif /* !CONFIG_ARM64 */
-#else
-	phys_addr_t orig_pa = (phys_addr_t)(va - g_contig_delta_va_pa);
-	dma_sync_single_for_cpu(OSH_NULL, orig_pa, size, DMA_RX);
-#endif /* defined BCM_SECURE_DMA */
-}
-
-inline void osl_prefetch(const void *ptr)
-{
-	/* PLD instruction is not applicable in ARM 64. We don't care for now */
-#ifndef CONFIG_ARM64
-	__asm__ __volatile__("pld\t%0" :: "o"(*(const char *)ptr) : "cc");
-#endif
-}
-
-int osl_arch_is_coherent(void)
-{
-	return 0;
-}
-
-
-inline int osl_acp_war_enab(void)
-{
-	return 0;
-}
-
-#endif 
-
-#if defined(BCMASSERT_LOG)
-void
-osl_assert(const char *exp, const char *file, int line)
-{
-	char tempbuf[256];
-	const char *basename;
-
-	basename = strrchr(file, '/');
-	/* skip the '/' */
-	if (basename)
-		basename++;
-
-	if (!basename)
-		basename = file;
-
-#ifdef BCMASSERT_LOG
-	snprintf(tempbuf, 64, "\"%s\": file \"%s\", line %d\n",
-		exp, basename, line);
-#endif /* BCMASSERT_LOG */
-
-
-#if defined(BCMASSERT_LOG)
-	switch (g_assert_type) {
-	case 0:
-		panic("%s", tempbuf);
-		break;
-	case 1:
-		printk("%s", tempbuf);
-		break;
-	case 2:
-		printk("%s", tempbuf);
-		BUG();
-		break;
-	default:
-		break;
-	}
-#endif 
-
-}
-#endif 
-
-void
-osl_delay(uint usec)
-{
-	uint d;
-
-	while (usec > 0) {
-		d = MIN(usec, 1000);
-		udelay(d);
-		usec -= d;
-	}
-}
-
-void
-osl_sleep(uint ms)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
-	if (ms < 20)
-		usleep_range(ms*1000, ms*1000 + 1000);
-	else
-#endif
-	msleep(ms);
-}
-
-
-
-/* Clone a packet.
- * The pkttag contents are NOT cloned.
- */
-#ifdef BCMDBG_CTRACE
-void *
-osl_pktdup(osl_t *osh, void *skb, int line, char *file)
-#else
-#ifdef BCM_OBJECT_TRACE
-void *
-osl_pktdup(osl_t *osh, void *skb, int line, const char *caller)
-#else
-void *
-osl_pktdup(osl_t *osh, void *skb)
-#endif /* BCM_OBJECT_TRACE */
-#endif /* BCMDBG_CTRACE */
-{
-	void * p;
-
-	ASSERT(!PKTISCHAINED(skb));
-
-	/* clear the CTFBUF flag if set and map the rest of the buffer
-	 * before cloning.
-	 */
-	PKTCTFMAP(osh, skb);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
-	if ((p = pskb_copy((struct sk_buff *)skb, GFP_ATOMIC)) == NULL)
-#else
-	if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL)
-#endif
-		return NULL;
-
-#ifdef CTFPOOL
-	if (PKTISFAST(osh, skb)) {
-		ctfpool_t *ctfpool;
-
-		/* if the buffer allocated from ctfpool is cloned then
-		 * we can't be sure when it will be freed. since there
-		 * is a chance that we will be losing a buffer
-		 * from our pool, we increment the refill count for the
-		 * object to be alloced later.
-		 */
-		ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb);
-		ASSERT(ctfpool != NULL);
-		PKTCLRFAST(osh, p);
-		PKTCLRFAST(osh, skb);
-		ctfpool->refills++;
-	}
-#endif /* CTFPOOL */
-
-	/* Clear PKTC  context */
-	PKTSETCLINK(p, NULL);
-	PKTCCLRFLAGS(p);
-	PKTCSETCNT(p, 1);
-	PKTCSETLEN(p, PKTLEN(osh, skb));
-
-	/* skb_clone copies skb->cb.. we don't want that */
-	if (osh->pub.pkttag)
-		OSL_PKTTAG_CLEAR(p);
-
-	/* Increment the packet counter */
-	atomic_inc(&osh->cmn->pktalloced);
-#ifdef BCM_OBJECT_TRACE
-	bcm_object_trace_opr(p, BCM_OBJDBG_ADD_PKT, caller, line);
-#endif /* BCM_OBJECT_TRACE */
-
-#ifdef BCMDBG_CTRACE
-	ADD_CTRACE(osh, (struct sk_buff *)p, file, line);
-#endif
-	return (p);
-}
-
-#ifdef BCMDBG_CTRACE
-int osl_pkt_is_frmnative(osl_t *osh, struct sk_buff *pkt)
-{
-	unsigned long flags;
-	struct sk_buff *skb;
-	int ck = FALSE;
-
-	spin_lock_irqsave(&osh->ctrace_lock, flags);
-
-	list_for_each_entry(skb, &osh->ctrace_list, ctrace_list) {
-		if (pkt == skb) {
-			ck = TRUE;
-			break;
-		}
-	}
-
-	spin_unlock_irqrestore(&osh->ctrace_lock, flags);
-	return ck;
-}
-
-void osl_ctrace_dump(osl_t *osh, struct bcmstrbuf *b)
-{
-	unsigned long flags;
-	struct sk_buff *skb;
-	int idx = 0;
-	int i, j;
-
-	spin_lock_irqsave(&osh->ctrace_lock, flags);
-
-	if (b != NULL)
-		bcm_bprintf(b, " Total %d sbk not free\n", osh->ctrace_num);
-	else
-		printk(" Total %d sbk not free\n", osh->ctrace_num);
-
-	list_for_each_entry(skb, &osh->ctrace_list, ctrace_list) {
-		if (b != NULL)
-			bcm_bprintf(b, "[%d] skb %p:\n", ++idx, skb);
-		else
-			printk("[%d] skb %p:\n", ++idx, skb);
-
-		for (i = 0; i < skb->ctrace_count; i++) {
-			j = (skb->ctrace_start + i) % CTRACE_NUM;
-			if (b != NULL)
-				bcm_bprintf(b, "    [%s(%d)]\n", skb->func[j], skb->line[j]);
-			else
-				printk("    [%s(%d)]\n", skb->func[j], skb->line[j]);
-		}
-		if (b != NULL)
-			bcm_bprintf(b, "\n");
-		else
-			printk("\n");
-	}
-
-	spin_unlock_irqrestore(&osh->ctrace_lock, flags);
-
-	return;
-}
-#endif /* BCMDBG_CTRACE */
-
-
-/*
- * OSLREGOPS specifies the use of osl_XXX routines to be used for register access
- */
-
-/*
- * BINOSL selects the slightly slower function-call-based binary compatible osl.
- */
-
-uint
-osl_pktalloced(osl_t *osh)
-{
-	if (atomic_read(&osh->cmn->refcount) == 1)
-		return (atomic_read(&osh->cmn->pktalloced));
-	else
-		return 0;
-}
-
-uint32
-osl_rand(void)
-{
-	uint32 rand;
-
-	get_random_bytes(&rand, sizeof(rand));
-
-	return rand;
-}
-
-/* Linux Kernel: File Operations: start */
-void *
-osl_os_open_image(char *filename)
-{
-	struct file *fp;
-
-	fp = filp_open(filename, O_RDONLY, 0);
-	/*
-	 * 2.6.11 (FC4) supports filp_open() but later revs don't?
-	 * Alternative:
-	 * fp = open_namei(AT_FDCWD, filename, O_RD, 0);
-	 * ???
-	 */
-	 if (IS_ERR(fp))
-		 fp = NULL;
-
-	 return fp;
-}
-
-int
-osl_os_get_image_block(char *buf, int len, void *image)
-{
-	struct file *fp = (struct file *)image;
-	int rdlen;
-
-	if (!image)
-		return 0;
-
-	rdlen = kernel_read(fp, fp->f_pos, buf, len);
-	if (rdlen > 0)
-		fp->f_pos += rdlen;
-
-	return rdlen;
-}
-
-void
-osl_os_close_image(void *image)
-{
-	if (image)
-		filp_close((struct file *)image, NULL);
-}
-
-int
-osl_os_image_size(void *image)
-{
-	int len = 0, curroffset;
-
-	if (image) {
-		/* store the current offset */
-		curroffset = generic_file_llseek(image, 0, 1);
-		/* goto end of file to get length */
-		len = generic_file_llseek(image, 0, 2);
-		/* restore back the offset */
-		generic_file_llseek(image, curroffset, 0);
-	}
-	return len;
-}
-
-/* Linux Kernel: File Operations: end */
-
-
-/* APIs to set/get specific quirks in OSL layer */
-void
-osl_flag_set(osl_t *osh, uint32 mask)
-{
-	osh->flags |= mask;
-}
-
-bool
-osl_is_flag_set(osl_t *osh, uint32 mask)
-{
-	return (osh->flags & mask);
-}
-
-#ifdef BCM_SECURE_DMA
-
-static void
-osl_sec_dma_setup_contig_mem(osl_t *osh, unsigned long memsize, int regn)
-{
-	int ret;
-
-#if defined(__ARM_ARCH_7A__)
-	if (regn == CONT_ARMREGION) {
-		ret = osl_sec_dma_alloc_contig_mem(osh, memsize, regn);
-		if (ret != BCME_OK)
-			printk("linux_osl.c: CMA memory access failed\n");
-	}
-#endif
-	/* implement the MIPS Here */
-}
-
-static int
-osl_sec_dma_alloc_contig_mem(osl_t *osh, unsigned long memsize, int regn)
-{
-	u64 addr;
-
-	printk("linux_osl.c: The value of cma mem block size = %ld\n", memsize);
-	osh->cma = cma_dev_get_cma_dev(regn);
-	printk("The value of cma = %p\n", osh->cma);
-	if (!osh->cma) {
-		printk("linux_osl.c:contig_region index is invalid\n");
-		return BCME_ERROR;
-	}
-	if (cma_dev_get_mem(osh->cma, &addr, (u32)memsize, SEC_DMA_ALIGN) < 0) {
-		printk("linux_osl.c: contiguous memory block allocation failure\n");
-		return BCME_ERROR;
-	}
-	osh->contig_base_alloc = (phys_addr_t)addr;
-	osh->contig_base = (phys_addr_t)osh->contig_base_alloc;
-	printk("contig base alloc=%lx \n", (ulong)osh->contig_base_alloc);
-
-	return BCME_OK;
-}
-
-static void
-osl_sec_dma_free_contig_mem(osl_t *osh, u32 memsize, int regn)
-{
-	int ret;
-
-	ret = cma_dev_put_mem(osh->cma, (u64)osh->contig_base, memsize);
-	if (ret)
-		printf("%s contig base free failed\n", __FUNCTION__);
-}
-
-static void *
-osl_sec_dma_ioremap(osl_t *osh, struct page *page, size_t size, bool iscache, bool isdecr)
-{
-
-	struct page **map;
-	int order, i;
-	void *addr = NULL;
-
-	size = PAGE_ALIGN(size);
-	order = get_order(size);
-
-	map = kmalloc(sizeof(struct page *) << order, GFP_ATOMIC);
-
-	if (map == NULL)
-		return NULL;
-
-	for (i = 0; i < (size >> PAGE_SHIFT); i++)
-		map[i] = page + i;
-
-	if (iscache) {
-		addr = vmap(map, size >> PAGE_SHIFT, VM_MAP, __pgprot(PAGE_KERNEL));
-		if (isdecr) {
-			osh->contig_delta_va_pa = (phys_addr_t)(addr - page_to_phys(page));
-			g_contig_delta_va_pa = osh->contig_delta_va_pa;
-		}
-	}
-	else {
-
-#if defined(__ARM_ARCH_7A__)
-		addr = vmap(map, size >> PAGE_SHIFT, VM_MAP,
-			pgprot_noncached(__pgprot(PAGE_KERNEL)));
-#endif
-		if (isdecr) {
-			osh->contig_delta_va_pa = (phys_addr_t)(addr - page_to_phys(page));
-			g_contig_delta_va_pa = osh->contig_delta_va_pa;
-		}
-	}
-
-	kfree(map);
-	return (void *)addr;
-}
-
-static void
-osl_sec_dma_iounmap(osl_t *osh, void *contig_base_va, size_t size)
-{
-	vunmap(contig_base_va);
-}
-
-static void
-osl_sec_dma_init_elem_mem_block(osl_t *osh, size_t mbsize, int max, sec_mem_elem_t **list)
-{
-	int i;
-	sec_mem_elem_t *sec_mem_elem;
-
-	if ((sec_mem_elem = kmalloc(sizeof(sec_mem_elem_t)*(max), GFP_ATOMIC)) != NULL) {
-
-		*list = sec_mem_elem;
-		bzero(sec_mem_elem, sizeof(sec_mem_elem_t)*(max));
-		for (i = 0; i < max-1; i++) {
-			sec_mem_elem->next = (sec_mem_elem + 1);
-			sec_mem_elem->size = mbsize;
-			sec_mem_elem->pa_cma = (u32)osh->contig_base_alloc;
-			sec_mem_elem->vac = osh->contig_base_alloc_va;
-
-			osh->contig_base_alloc += mbsize;
-			osh->contig_base_alloc_va += mbsize;
-
-			sec_mem_elem = sec_mem_elem + 1;
-		}
-		sec_mem_elem->next = NULL;
-		sec_mem_elem->size = mbsize;
-		sec_mem_elem->pa_cma = (u32)osh->contig_base_alloc;
-		sec_mem_elem->vac = osh->contig_base_alloc_va;
-
-		osh->contig_base_alloc += mbsize;
-		osh->contig_base_alloc_va += mbsize;
-
-	}
-	else
-		printf("%s sec mem elem kmalloc failed\n", __FUNCTION__);
-}
-
-
-static void
-osl_sec_dma_deinit_elem_mem_block(osl_t *osh, size_t mbsize, int max, void *sec_list_base)
-{
-	if (sec_list_base)
-		kfree(sec_list_base);
-}
-
-static sec_mem_elem_t * BCMFASTPATH
-osl_sec_dma_alloc_mem_elem(osl_t *osh, void *va, uint size, int direction,
-	struct sec_cma_info *ptr_cma_info, uint offset)
-{
-	sec_mem_elem_t *sec_mem_elem = NULL;
-
-	if (size <= 512 && osh->sec_list_512) {
-		sec_mem_elem = osh->sec_list_512;
-		osh->sec_list_512 = sec_mem_elem->next;
-	}
-	else if (size <= 2048 && osh->sec_list_2048) {
-		sec_mem_elem = osh->sec_list_2048;
-		osh->sec_list_2048 = sec_mem_elem->next;
-	}
-	else if (osh->sec_list_4096) {
-		sec_mem_elem = osh->sec_list_4096;
-		osh->sec_list_4096 = sec_mem_elem->next;
-	} else {
-		printf("%s No matching Pool available size=%d \n", __FUNCTION__, size);
-		return NULL;
-	}
-
-	if (sec_mem_elem != NULL) {
-		sec_mem_elem->next = NULL;
-
-	if (ptr_cma_info->sec_alloc_list_tail) {
-		ptr_cma_info->sec_alloc_list_tail->next = sec_mem_elem;
-	}
-
-	ptr_cma_info->sec_alloc_list_tail = sec_mem_elem;
-	if (ptr_cma_info->sec_alloc_list == NULL)
-		ptr_cma_info->sec_alloc_list = sec_mem_elem;
-	}
-	return sec_mem_elem;
-}
-
-static void BCMFASTPATH
-osl_sec_dma_free_mem_elem(osl_t *osh, sec_mem_elem_t *sec_mem_elem)
-{
-	sec_mem_elem->dma_handle = 0x0;
-	sec_mem_elem->va = NULL;
-
-	if (sec_mem_elem->size == 512) {
-		sec_mem_elem->next = osh->sec_list_512;
-		osh->sec_list_512 = sec_mem_elem;
-	}
-	else if (sec_mem_elem->size == 2048) {
-		sec_mem_elem->next = osh->sec_list_2048;
-		osh->sec_list_2048 = sec_mem_elem;
-	}
-	else if (sec_mem_elem->size == 4096) {
-		sec_mem_elem->next = osh->sec_list_4096;
-		osh->sec_list_4096 = sec_mem_elem;
-	}
-	else
-	printf("%s free failed size=%d \n", __FUNCTION__, sec_mem_elem->size);
-}
-
-static sec_mem_elem_t * BCMFASTPATH
-osl_sec_dma_find_rem_elem(osl_t *osh, struct sec_cma_info *ptr_cma_info, dma_addr_t dma_handle)
-{
-	sec_mem_elem_t *sec_mem_elem = ptr_cma_info->sec_alloc_list;
-	sec_mem_elem_t *sec_prv_elem = ptr_cma_info->sec_alloc_list;
-
-	if (sec_mem_elem->dma_handle == dma_handle) {
-
-		ptr_cma_info->sec_alloc_list = sec_mem_elem->next;
-
-		if (sec_mem_elem == ptr_cma_info->sec_alloc_list_tail) {
-			ptr_cma_info->sec_alloc_list_tail = NULL;
-			ASSERT(ptr_cma_info->sec_alloc_list == NULL);
-		}
-
-		return sec_mem_elem;
-	}
-
-	while (sec_mem_elem != NULL) {
-
-		if (sec_mem_elem->dma_handle == dma_handle) {
-
-			sec_prv_elem->next = sec_mem_elem->next;
-			if (sec_mem_elem == ptr_cma_info->sec_alloc_list_tail)
-				ptr_cma_info->sec_alloc_list_tail = sec_prv_elem;
-
-			return sec_mem_elem;
-		}
-		sec_prv_elem = sec_mem_elem;
-		sec_mem_elem = sec_mem_elem->next;
-	}
-	return NULL;
-}
-
-static sec_mem_elem_t *
-osl_sec_dma_rem_first_elem(osl_t *osh, struct sec_cma_info *ptr_cma_info)
-{
-	sec_mem_elem_t *sec_mem_elem = ptr_cma_info->sec_alloc_list;
-
-	if (sec_mem_elem) {
-
-		ptr_cma_info->sec_alloc_list = sec_mem_elem->next;
-
-		if (ptr_cma_info->sec_alloc_list == NULL)
-			ptr_cma_info->sec_alloc_list_tail = NULL;
-
-		return sec_mem_elem;
-
-	} else
-		return NULL;
-}
-
-static void * BCMFASTPATH
-osl_sec_dma_last_elem(osl_t *osh, struct sec_cma_info *ptr_cma_info)
-{
-	return ptr_cma_info->sec_alloc_list_tail;
-}
-
-dma_addr_t BCMFASTPATH
-osl_sec_dma_map_txmeta(osl_t *osh, void *va, uint size, int direction, void *p,
-	hnddma_seg_map_t *dmah, void *ptr_cma_info)
-{
-	sec_mem_elem_t *sec_mem_elem;
-	struct page *pa_cma_page;
-	uint loffset;
-	void *vaorig = va + size;
-	dma_addr_t dma_handle = 0x0;
-	/* packet will be the one added with osl_sec_dma_map() just before this call */
-
-	sec_mem_elem = osl_sec_dma_last_elem(osh, ptr_cma_info);
-
-	if (sec_mem_elem && sec_mem_elem->va == vaorig) {
-
-		pa_cma_page = phys_to_page(sec_mem_elem->pa_cma);
-		loffset = sec_mem_elem->pa_cma -(sec_mem_elem->pa_cma & ~(PAGE_SIZE-1));
-
-		dma_handle = dma_map_page(osh->cma->dev, pa_cma_page, loffset, size,
-			(direction == DMA_TX ? DMA_TO_DEVICE:DMA_FROM_DEVICE));
-
-	} else {
-		printf("%s: error orig va not found va = 0x%p \n",
-			__FUNCTION__, vaorig);
-	}
-	return dma_handle;
-}
-
-dma_addr_t BCMFASTPATH
-osl_sec_dma_map(osl_t *osh, void *va, uint size, int direction, void *p,
-	hnddma_seg_map_t *dmah, void *ptr_cma_info, uint offset)
-{
-
-	sec_mem_elem_t *sec_mem_elem;
-	struct page *pa_cma_page;
-	void *pa_cma_kmap_va = NULL;
-	int *fragva;
-	uint buflen = 0;
-	struct sk_buff *skb;
-	dma_addr_t dma_handle = 0x0;
-	uint loffset;
-	int i = 0;
-
-	sec_mem_elem = osl_sec_dma_alloc_mem_elem(osh, va, size, direction, ptr_cma_info, offset);
-
-	if (sec_mem_elem == NULL) {
-		printk("linux_osl.c: osl_sec_dma_map - cma allocation failed\n");
-		return 0;
-	}
-	sec_mem_elem->va = va;
-	sec_mem_elem->direction = direction;
-	pa_cma_page = phys_to_page(sec_mem_elem->pa_cma);
-
-	loffset = sec_mem_elem->pa_cma -(sec_mem_elem->pa_cma & ~(PAGE_SIZE-1));
-	/* pa_cma_kmap_va = kmap_atomic(pa_cma_page);
-	* pa_cma_kmap_va += loffset;
-	*/
-
-	pa_cma_kmap_va = sec_mem_elem->vac;
-
-	if (direction == DMA_TX) {
-
-		if (p == NULL) {
-
-			memcpy(pa_cma_kmap_va+offset, va, size);
-			buflen = size;
-		}
-		else {
-			for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) {
-				if (skb_is_nonlinear(skb)) {
-
-
-					for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-						skb_frag_t *f = &skb_shinfo(skb)->frags[i];
-						fragva = kmap_atomic(skb_frag_page(f));
-						memcpy((pa_cma_kmap_va+offset+buflen),
-						(fragva + f->page_offset), skb_frag_size(f));
-						kunmap_atomic(fragva);
-						buflen += skb_frag_size(f);
-					}
-				}
-				else {
-					memcpy((pa_cma_kmap_va+offset+buflen), skb->data, skb->len);
-					buflen += skb->len;
-				}
-			}
-
-		}
-		if (dmah) {
-			dmah->nsegs = 1;
-			dmah->origsize = buflen;
-		}
-	}
-
-	else if (direction == DMA_RX)
-	{
-		buflen = size;
-		if ((p != NULL) && (dmah != NULL)) {
-			dmah->nsegs = 1;
-			dmah->origsize = buflen;
-		}
-	}
-	if (direction == DMA_RX || direction == DMA_TX) {
-
-		dma_handle = dma_map_page(osh->cma->dev, pa_cma_page, loffset+offset, buflen,
-			(direction == DMA_TX ? DMA_TO_DEVICE:DMA_FROM_DEVICE));
-
-	}
-	if (dmah) {
-		dmah->segs[0].addr = dma_handle;
-		dmah->segs[0].length = buflen;
-	}
-	sec_mem_elem->dma_handle = dma_handle;
-	/* kunmap_atomic(pa_cma_kmap_va-loffset); */
-	return dma_handle;
-}
-
-dma_addr_t BCMFASTPATH
-osl_sec_dma_dd_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *map)
-{
-
-	struct page *pa_cma_page;
-	phys_addr_t pa_cma;
-	dma_addr_t dma_handle = 0x0;
-	uint loffset;
-
-	pa_cma = (phys_addr_t)(va - osh->contig_delta_va_pa);
-	pa_cma_page = phys_to_page(pa_cma);
-	loffset = pa_cma -(pa_cma & ~(PAGE_SIZE-1));
-
-	dma_handle = dma_map_page(osh->cma->dev, pa_cma_page, loffset, size,
-		(direction == DMA_TX ? DMA_TO_DEVICE:DMA_FROM_DEVICE));
-
-	return dma_handle;
-}
-
-void BCMFASTPATH
-osl_sec_dma_unmap(osl_t *osh, dma_addr_t dma_handle, uint size, int direction,
-void *p, hnddma_seg_map_t *map,	void *ptr_cma_info, uint offset)
-{
-	sec_mem_elem_t *sec_mem_elem;
-	struct page *pa_cma_page;
-	void *pa_cma_kmap_va = NULL;
-	uint buflen = 0;
-	dma_addr_t pa_cma;
-	void *va;
-	uint loffset = 0;
-	int read_count = 0;
-	BCM_REFERENCE(buflen);
-	BCM_REFERENCE(read_count);
-
-	sec_mem_elem = osl_sec_dma_find_rem_elem(osh, ptr_cma_info, dma_handle);
-	if (sec_mem_elem == NULL) {
-		printf("%s sec_mem_elem is NULL and dma_handle =0x%lx and dir=%d\n",
-			__FUNCTION__, (ulong)dma_handle, direction);
-		return;
-	}
-
-	va = sec_mem_elem->va;
-	va -= offset;
-	pa_cma = sec_mem_elem->pa_cma;
-
-	pa_cma_page = phys_to_page(pa_cma);
-	loffset = sec_mem_elem->pa_cma -(sec_mem_elem->pa_cma & ~(PAGE_SIZE-1));
-
-	if (direction == DMA_RX) {
-
-		if (p == NULL) {
-
-			/* pa_cma_kmap_va = kmap_atomic(pa_cma_page);
-			* pa_cma_kmap_va += loffset;
-			*/
-
-			pa_cma_kmap_va = sec_mem_elem->vac;
-
-			dma_unmap_page(osh->cma->dev, pa_cma, size, DMA_FROM_DEVICE);
-			memcpy(va, pa_cma_kmap_va, size);
-			/* kunmap_atomic(pa_cma_kmap_va); */
-		}
-	} else {
-		dma_unmap_page(osh->cma->dev, pa_cma, size+offset, DMA_TO_DEVICE);
-	}
-
-	osl_sec_dma_free_mem_elem(osh, sec_mem_elem);
-}
-
-void
-osl_sec_dma_unmap_all(osl_t *osh, void *ptr_cma_info)
-{
-
-	sec_mem_elem_t *sec_mem_elem;
-
-	sec_mem_elem = osl_sec_dma_rem_first_elem(osh, ptr_cma_info);
-
-	while (sec_mem_elem != NULL) {
-
-		dma_unmap_page(osh->cma->dev, sec_mem_elem->pa_cma, sec_mem_elem->size,
-			sec_mem_elem->direction == DMA_TX ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		osl_sec_dma_free_mem_elem(osh, sec_mem_elem);
-
-		sec_mem_elem = osl_sec_dma_rem_first_elem(osh, ptr_cma_info);
-	}
-}
-
-static void
-osl_sec_dma_init_consistent(osl_t *osh)
-{
-	int i;
-	void *temp_va = osh->contig_base_alloc_coherent_va;
-	phys_addr_t temp_pa = osh->contig_base_alloc_coherent;
-
-	for (i = 0; i < SEC_CMA_COHERENT_MAX; i++) {
-		osh->sec_cma_coherent[i].avail = TRUE;
-		osh->sec_cma_coherent[i].va = temp_va;
-		osh->sec_cma_coherent[i].pa = temp_pa;
-		temp_va += SEC_CMA_COHERENT_BLK;
-		temp_pa += SEC_CMA_COHERENT_BLK;
-	}
-}
-
-static void *
-osl_sec_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, ulong *pap)
-{
-
-	void *temp_va = NULL;
-	ulong temp_pa = 0;
-	int i;
-
-	if (size > SEC_CMA_COHERENT_BLK) {
-		printf("%s unsupported size\n", __FUNCTION__);
-		return NULL;
-	}
-
-	for (i = 0; i < SEC_CMA_COHERENT_MAX; i++) {
-		if (osh->sec_cma_coherent[i].avail == TRUE) {
-			temp_va = osh->sec_cma_coherent[i].va;
-			temp_pa = osh->sec_cma_coherent[i].pa;
-			osh->sec_cma_coherent[i].avail = FALSE;
-			break;
-		}
-	}
-
-	if (i == SEC_CMA_COHERENT_MAX)
-		printf("%s:No coherent mem: va = 0x%p pa = 0x%lx size = %d\n", __FUNCTION__,
-			temp_va, (ulong)temp_pa, size);
-
-	*pap = (unsigned long)temp_pa;
-	return temp_va;
-}
-
-static void
-osl_sec_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa)
-{
-	int i = 0;
-
-	for (i = 0; i < SEC_CMA_COHERENT_MAX; i++) {
-		if (osh->sec_cma_coherent[i].va == va) {
-			osh->sec_cma_coherent[i].avail = TRUE;
-			break;
-		}
-	}
-	if (i == SEC_CMA_COHERENT_MAX)
-		printf("%s:Error: va = 0x%p pa = 0x%lx size = %d\n", __FUNCTION__,
-			va, (ulong)pa, size);
-}
-
-#endif /* BCM_SECURE_DMA */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) && defined(TSQ_MULTIPLIER)
-#include <linux/kallsyms.h>
-#include <net/sock.h>
-void
-osl_pkt_orphan_partial(struct sk_buff *skb)
-{
-	uint32 fraction;
-	static void *p_tcp_wfree = NULL;
-
-	if (!skb->destructor || skb->destructor == sock_wfree)
-		return;
-
-	if (unlikely(!p_tcp_wfree)) {
-		char sym[KSYM_SYMBOL_LEN];
-		sprint_symbol(sym, (unsigned long)skb->destructor);
-		sym[9] = 0;
-		if (!strcmp(sym, "tcp_wfree"))
-			p_tcp_wfree = skb->destructor;
-		else
-			return;
-	}
-
-	if (unlikely(skb->destructor != p_tcp_wfree || !skb->sk))
-		return;
-
-	/* abstract a certain portion of skb truesize from the socket
-	 * sk_wmem_alloc to allow more skb can be allocated for this
-	 * socket for better cusion meeting WiFi device requirement
-	 */
-	fraction = skb->truesize * (TSQ_MULTIPLIER - 1) / TSQ_MULTIPLIER;
-	skb->truesize -= fraction;
-	atomic_sub(fraction, &skb->sk->sk_wmem_alloc);
-}
-#endif /* LINUX_VERSION >= 3.6.0 && TSQ_MULTIPLIER */
diff --git a/drivers/net/wireless/bcmdhd/pcie_core.c b/drivers/net/wireless/bcmdhd/pcie_core.c
deleted file mode 100644
index c36bc62..0000000
--- a/drivers/net/wireless/bcmdhd/pcie_core.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/** @file pcie_core.c
- *
- * Contains PCIe related functions that are shared between different driver models (e.g. firmware
- * builds, DHD builds, BMAC builds), in order to avoid code duplication.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: pcie_core.c 591285 2015-10-07 11:56:29Z $
- */
-
-#include <bcm_cfg.h>
-#include <typedefs.h>
-#include <bcmutils.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <siutils.h>
-#include <hndsoc.h>
-#include <sbchipc.h>
-
-#include "pcie_core.h"
-
-/* local prototypes */
-
-/* local variables */
-
-/* function definitions */
-
-#ifdef BCMDRIVER
-
-void pcie_watchdog_reset(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs)
-{
-	uint32 val, i, lsc;
-	uint16 cfg_offset[] = {PCIECFGREG_STATUS_CMD, PCIECFGREG_PM_CSR,
-		PCIECFGREG_MSI_CAP, PCIECFGREG_MSI_ADDR_L,
-		PCIECFGREG_MSI_ADDR_H, PCIECFGREG_MSI_DATA,
-		PCIECFGREG_LINK_STATUS_CTRL2, PCIECFGREG_RBAR_CTRL,
-		PCIECFGREG_PML1_SUB_CTRL1, PCIECFGREG_REG_BAR2_CONFIG,
-		PCIECFGREG_REG_BAR3_CONFIG};
-	sbpcieregs_t *pcie = NULL;
-	uint32 origidx = si_coreidx(sih);
-
-	/* Switch to PCIE2 core */
-	pcie = (sbpcieregs_t *)si_setcore(sih, PCIE2_CORE_ID, 0);
-	BCM_REFERENCE(pcie);
-	ASSERT(pcie != NULL);
-
-	/* Disable/restore ASPM Control to protect the watchdog reset */
-	W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL);
-	lsc = R_REG(osh, &sbpcieregs->configdata);
-	val = lsc & (~PCIE_ASPM_ENAB);
-	W_REG(osh, &sbpcieregs->configdata, val);
-
-	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 4);
-	OSL_DELAY(100000);
-
-	W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL);
-	W_REG(osh, &sbpcieregs->configdata, lsc);
-
-	if (sih->buscorerev <= 13) {
-		/* Write configuration registers back to the shadow registers
-		 * cause shadow registers are cleared out after watchdog reset.
-		 */
-		for (i = 0; i < ARRAYSIZE(cfg_offset); i++) {
-			W_REG(osh, &sbpcieregs->configaddr, cfg_offset[i]);
-			val = R_REG(osh, &sbpcieregs->configdata);
-			W_REG(osh, &sbpcieregs->configdata, val);
-		}
-	}
-	si_setcoreidx(sih, origidx);
-}
-
-
-/* CRWLPCIEGEN2-117 pcie_pipe_Iddq should be controlled
- * by the L12 state from MAC to save power by putting the
- * SerDes analog in IDDQ mode
- */
-void  pcie_serdes_iddqdisable(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs)
-{
-	sbpcieregs_t *pcie = NULL;
-	uint crwlpciegen2_117_disable = 0;
-	uint32 origidx = si_coreidx(sih);
-
-	crwlpciegen2_117_disable = PCIE_PipeIddqDisable0 | PCIE_PipeIddqDisable1;
-	/* Switch to PCIE2 core */
-	pcie = (sbpcieregs_t *)si_setcore(sih, PCIE2_CORE_ID, 0);
-	BCM_REFERENCE(pcie);
-	ASSERT(pcie != NULL);
-
-	OR_REG(osh, &sbpcieregs->control,
-		crwlpciegen2_117_disable);
-
-	si_setcoreidx(sih, origidx);
-}
-#endif /* BCMDRIVER */
diff --git a/drivers/net/wireless/bcmdhd/sbutils.c b/drivers/net/wireless/bcmdhd/sbutils.c
deleted file mode 100644
index 0804ef45..0000000
--- a/drivers/net/wireless/bcmdhd/sbutils.c
+++ /dev/null
@@ -1,1108 +0,0 @@
-/*
- * Misc utility routines for accessing chip-specific features
- * of the SiliconBackplane-based Broadcom chips.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: sbutils.c 514727 2014-11-12 03:02:48Z $
- */
-
-#include <bcm_cfg.h>
-#include <typedefs.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <bcmdevs.h>
-#include <hndsoc.h>
-#include <sbchipc.h>
-#include <pcicfg.h>
-#include <sbpcmcia.h>
-
-#include "siutils_priv.h"
-
-
-/* local prototypes */
-static uint _sb_coreidx(si_info_t *sii, uint32 sba);
-static uint _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba,
-                     uint ncores);
-static uint32 _sb_coresba(si_info_t *sii);
-static void *_sb_setcoreidx(si_info_t *sii, uint coreidx);
-#define	SET_SBREG(sii, r, mask, val)	\
-		W_SBREG((sii), (r), ((R_SBREG((sii), (r)) & ~(mask)) | (val)))
-#define	REGS2SB(va)	(sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
-
-/* sonicsrev */
-#define	SONICS_2_2	(SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
-#define	SONICS_2_3	(SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
-
-#define	R_SBREG(sii, sbr)	sb_read_sbreg((sii), (sbr))
-#define	W_SBREG(sii, sbr, v)	sb_write_sbreg((sii), (sbr), (v))
-#define	AND_SBREG(sii, sbr, v)	W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) & (v)))
-#define	OR_SBREG(sii, sbr, v)	W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) | (v)))
-
-static uint32
-sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr)
-{
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint8 tmp;
-	uint32 val, intr_val = 0;
-
-
-	/*
-	 * compact flash only has 11 bits address, while we needs 12 bits address.
-	 * MEM_SEG will be OR'd with other 11 bits address in hardware,
-	 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
-	 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
-	 */
-	if (PCMCIA(sii)) {
-		INTR_OFF(sii, intr_val);
-		tmp = 1;
-		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
-		sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
-	}
-
-	val = R_REG(sii->osh, sbr);
-
-	if (PCMCIA(sii)) {
-		tmp = 0;
-		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
-		INTR_RESTORE(sii, intr_val);
-	}
-
-	return (val);
-}
-
-static void
-sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v)
-{
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint8 tmp;
-	volatile uint32 dummy;
-	uint32 intr_val = 0;
-
-
-	/*
-	 * compact flash only has 11 bits address, while we needs 12 bits address.
-	 * MEM_SEG will be OR'd with other 11 bits address in hardware,
-	 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
-	 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
-	 */
-	if (PCMCIA(sii)) {
-		INTR_OFF(sii, intr_val);
-		tmp = 1;
-		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
-		sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
-	}
-
-	if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
-		dummy = R_REG(sii->osh, sbr);
-		BCM_REFERENCE(dummy);
-		W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff));
-		dummy = R_REG(sii->osh, sbr);
-		BCM_REFERENCE(dummy);
-		W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff));
-	} else
-		W_REG(sii->osh, sbr, v);
-
-	if (PCMCIA(sii)) {
-		tmp = 0;
-		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
-		INTR_RESTORE(sii, intr_val);
-	}
-}
-
-uint
-sb_coreid(si_t *sih)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-
-	return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
-}
-
-uint
-sb_intflag(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	void *corereg;
-	sbconfig_t *sb;
-	uint origidx, intflag, intr_val = 0;
-
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-	corereg = si_setcore(sih, CC_CORE_ID, 0);
-	ASSERT(corereg != NULL);
-	sb = REGS2SB(corereg);
-	intflag = R_SBREG(sii, &sb->sbflagst);
-	sb_setcoreidx(sih, origidx);
-	INTR_RESTORE(sii, intr_val);
-
-	return intflag;
-}
-
-uint
-sb_flag(si_t *sih)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-
-	return R_SBREG(sii, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
-}
-
-void
-sb_setint(si_t *sih, int siflag)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-	uint32 vec;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-
-	if (siflag == -1)
-		vec = 0;
-	else
-		vec = 1 << siflag;
-	W_SBREG(sii, &sb->sbintvec, vec);
-}
-
-/* return core index of the core with address 'sba' */
-static uint
-_sb_coreidx(si_info_t *sii, uint32 sba)
-{
-	uint i;
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	for (i = 0; i < sii->numcores; i ++)
-		if (sba == cores_info->coresba[i])
-			return i;
-	return BADIDX;
-}
-
-/* return core address of the current core */
-static uint32
-_sb_coresba(si_info_t *sii)
-{
-	uint32 sbaddr;
-
-
-	switch (BUSTYPE(sii->pub.bustype)) {
-	case SI_BUS: {
-		sbconfig_t *sb = REGS2SB(sii->curmap);
-		sbaddr = sb_base(R_SBREG(sii, &sb->sbadmatch0));
-		break;
-	}
-
-	case PCI_BUS:
-		sbaddr = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
-		break;
-
-	case PCMCIA_BUS: {
-		uint8 tmp = 0;
-		OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1);
-		sbaddr  = (uint32)tmp << 12;
-		OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1);
-		sbaddr |= (uint32)tmp << 16;
-		OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1);
-		sbaddr |= (uint32)tmp << 24;
-		break;
-	}
-
-#ifdef BCMSDIO
-	case SPI_BUS:
-	case SDIO_BUS:
-		sbaddr = (uint32)(uintptr)sii->curmap;
-		break;
-#endif
-
-
-	default:
-		sbaddr = BADCOREADDR;
-		break;
-	}
-
-	return sbaddr;
-}
-
-uint
-sb_corevendor(si_t *sih)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-
-	return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
-}
-
-uint
-sb_corerev(si_t *sih)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-	uint sbidh;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-	sbidh = R_SBREG(sii, &sb->sbidhigh);
-
-	return (SBCOREREV(sbidh));
-}
-
-/* set core-specific control flags */
-void
-sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-	uint32 w;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-
-	ASSERT((val & ~mask) == 0);
-
-	/* mask and set */
-	w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) |
-	        (val << SBTML_SICF_SHIFT);
-	W_SBREG(sii, &sb->sbtmstatelow, w);
-}
-
-/* set/clear core-specific control flags */
-uint32
-sb_core_cflags(si_t *sih, uint32 mask, uint32 val)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-	uint32 w;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-
-	ASSERT((val & ~mask) == 0);
-
-	/* mask and set */
-	if (mask || val) {
-		w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) |
-		        (val << SBTML_SICF_SHIFT);
-		W_SBREG(sii, &sb->sbtmstatelow, w);
-	}
-
-	/* return the new value
-	 * for write operation, the following readback ensures the completion of write opration.
-	 */
-	return (R_SBREG(sii, &sb->sbtmstatelow) >> SBTML_SICF_SHIFT);
-}
-
-/* set/clear core-specific status flags */
-uint32
-sb_core_sflags(si_t *sih, uint32 mask, uint32 val)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-	uint32 w;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-
-	ASSERT((val & ~mask) == 0);
-	ASSERT((mask & ~SISF_CORE_BITS) == 0);
-
-	/* mask and set */
-	if (mask || val) {
-		w = (R_SBREG(sii, &sb->sbtmstatehigh) & ~(mask << SBTMH_SISF_SHIFT)) |
-		        (val << SBTMH_SISF_SHIFT);
-		W_SBREG(sii, &sb->sbtmstatehigh, w);
-	}
-
-	/* return the new value */
-	return (R_SBREG(sii, &sb->sbtmstatehigh) >> SBTMH_SISF_SHIFT);
-}
-
-bool
-sb_iscoreup(si_t *sih)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-
-	return ((R_SBREG(sii, &sb->sbtmstatelow) &
-	         (SBTML_RESET | SBTML_REJ_MASK | (SICF_CLOCK_EN << SBTML_SICF_SHIFT))) ==
-	        (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
-}
-
-/*
- * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
- * switch back to the original core, and return the new value.
- *
- * When using the silicon backplane, no fidleing with interrupts or core switches are needed.
- *
- * Also, when using pci/pcie, we can optimize away the core switching for pci registers
- * and (on newer pci cores) chipcommon registers.
- */
-uint
-sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
-{
-	uint origidx = 0;
-	uint32 *r = NULL;
-	uint w;
-	uint intr_val = 0;
-	bool fast = FALSE;
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	ASSERT(GOODIDX(coreidx));
-	ASSERT(regoff < SI_CORE_SIZE);
-	ASSERT((val & ~mask) == 0);
-
-	if (coreidx >= SI_MAXCORES)
-		return 0;
-
-	if (BUSTYPE(sii->pub.bustype) == SI_BUS) {
-		/* If internal bus, we can always get at everything */
-		fast = TRUE;
-		/* map if does not exist */
-		if (!cores_info->regs[coreidx]) {
-			cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
-			                            SI_CORE_SIZE);
-			ASSERT(GOODREGS(cores_info->regs[coreidx]));
-		}
-		r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
-	} else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
-		/* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
-
-		if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
-			/* Chipc registers are mapped at 12KB */
-
-			fast = TRUE;
-			r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
-		} else if (sii->pub.buscoreidx == coreidx) {
-			/* pci registers are at either in the last 2KB of an 8KB window
-			 * or, in pcie and pci rev 13 at 8KB
-			 */
-			fast = TRUE;
-			if (SI_FAST(sii))
-				r = (uint32 *)((char *)sii->curmap +
-				               PCI_16KB0_PCIREGS_OFFSET + regoff);
-			else
-				r = (uint32 *)((char *)sii->curmap +
-				               ((regoff >= SBCONFIGOFF) ?
-				                PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
-				               regoff);
-		}
-	}
-
-	if (!fast) {
-		INTR_OFF(sii, intr_val);
-
-		/* save current core index */
-		origidx = si_coreidx(&sii->pub);
-
-		/* switch core */
-		r = (uint32*) ((uchar*)sb_setcoreidx(&sii->pub, coreidx) + regoff);
-	}
-	ASSERT(r != NULL);
-
-	/* mask and set */
-	if (mask || val) {
-		if (regoff >= SBCONFIGOFF) {
-			w = (R_SBREG(sii, r) & ~mask) | val;
-			W_SBREG(sii, r, w);
-		} else {
-			w = (R_REG(sii->osh, r) & ~mask) | val;
-			W_REG(sii->osh, r, w);
-		}
-	}
-
-	/* readback */
-	if (regoff >= SBCONFIGOFF)
-		w = R_SBREG(sii, r);
-	else {
-		if ((CHIPID(sii->pub.chip) == BCM5354_CHIP_ID) &&
-		    (coreidx == SI_CC_IDX) &&
-		    (regoff == OFFSETOF(chipcregs_t, watchdog))) {
-			w = val;
-		} else
-			w = R_REG(sii->osh, r);
-	}
-
-	if (!fast) {
-		/* restore core index */
-		if (origidx != coreidx)
-			sb_setcoreidx(&sii->pub, origidx);
-
-		INTR_RESTORE(sii, intr_val);
-	}
-
-	return (w);
-}
-
-/*
- * If there is no need for fiddling with interrupts or core switches (typically silicon
- * back plane registers, pci registers and chipcommon registers), this function
- * returns the register offset on this core to a mapped address. This address can
- * be used for W_REG/R_REG directly.
- *
- * For accessing registers that would need a core switch, this function will return
- * NULL.
- */
-uint32 *
-sb_corereg_addr(si_t *sih, uint coreidx, uint regoff)
-{
-	uint32 *r = NULL;
-	bool fast = FALSE;
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	ASSERT(GOODIDX(coreidx));
-	ASSERT(regoff < SI_CORE_SIZE);
-
-	if (coreidx >= SI_MAXCORES)
-		return 0;
-
-	if (BUSTYPE(sii->pub.bustype) == SI_BUS) {
-		/* If internal bus, we can always get at everything */
-		fast = TRUE;
-		/* map if does not exist */
-		if (!cores_info->regs[coreidx]) {
-			cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
-			                            SI_CORE_SIZE);
-			ASSERT(GOODREGS(cores_info->regs[coreidx]));
-		}
-		r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
-	} else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
-		/* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
-
-		if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
-			/* Chipc registers are mapped at 12KB */
-
-			fast = TRUE;
-			r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
-		} else if (sii->pub.buscoreidx == coreidx) {
-			/* pci registers are at either in the last 2KB of an 8KB window
-			 * or, in pcie and pci rev 13 at 8KB
-			 */
-			fast = TRUE;
-			if (SI_FAST(sii))
-				r = (uint32 *)((char *)sii->curmap +
-				               PCI_16KB0_PCIREGS_OFFSET + regoff);
-			else
-				r = (uint32 *)((char *)sii->curmap +
-				               ((regoff >= SBCONFIGOFF) ?
-				                PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
-				               regoff);
-		}
-	}
-
-	if (!fast)
-		return 0;
-
-	return (r);
-}
-
-/* Scan the enumeration space to find all cores starting from the given
- * bus 'sbba'. Append coreid and other info to the lists in 'si'. 'sba'
- * is the default core address at chip POR time and 'regs' is the virtual
- * address that the default core is mapped at. 'ncores' is the number of
- * cores expected on bus 'sbba'. It returns the total number of cores
- * starting from bus 'sbba', inclusive.
- */
-#define SB_MAXBUSES	2
-static uint
-_sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, uint numcores)
-{
-	uint next;
-	uint ncc = 0;
-	uint i;
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	if (bus >= SB_MAXBUSES) {
-		SI_ERROR(("_sb_scan: bus 0x%08x at level %d is too deep to scan\n", sbba, bus));
-		return 0;
-	}
-	SI_MSG(("_sb_scan: scan bus 0x%08x assume %u cores\n", sbba, numcores));
-
-	/* Scan all cores on the bus starting from core 0.
-	 * Core addresses must be contiguous on each bus.
-	 */
-	for (i = 0, next = sii->numcores; i < numcores && next < SB_BUS_MAXCORES; i++, next++) {
-		cores_info->coresba[next] = sbba + (i * SI_CORE_SIZE);
-
-		/* keep and reuse the initial register mapping */
-		if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && (cores_info->coresba[next] == sba)) {
-			SI_VMSG(("_sb_scan: reuse mapped regs %p for core %u\n", regs, next));
-			cores_info->regs[next] = regs;
-		}
-
-		/* change core to 'next' and read its coreid */
-		sii->curmap = _sb_setcoreidx(sii, next);
-		sii->curidx = next;
-
-		cores_info->coreid[next] = sb_coreid(&sii->pub);
-
-		/* core specific processing... */
-		/* chipc provides # cores */
-		if (cores_info->coreid[next] == CC_CORE_ID) {
-			chipcregs_t *cc = (chipcregs_t *)sii->curmap;
-			uint32 ccrev = sb_corerev(&sii->pub);
-
-			/* determine numcores - this is the total # cores in the chip */
-			if (((ccrev == 4) || (ccrev >= 6))) {
-				ASSERT(cc);
-				numcores = (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK) >>
-				        CID_CC_SHIFT;
-			} else {
-				/* Older chips */
-				uint chip = CHIPID(sii->pub.chip);
-
-				if (chip == BCM4306_CHIP_ID)	/* < 4306c0 */
-					numcores = 6;
-				else if (chip == BCM4704_CHIP_ID)
-					numcores = 9;
-				else if (chip == BCM5365_CHIP_ID)
-					numcores = 7;
-				else {
-					SI_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n",
-					          chip));
-					ASSERT(0);
-					numcores = 1;
-				}
-			}
-			SI_VMSG(("_sb_scan: there are %u cores in the chip %s\n", numcores,
-				sii->pub.issim ? "QT" : ""));
-		}
-		/* scan bridged SB(s) and add results to the end of the list */
-		else if (cores_info->coreid[next] == OCP_CORE_ID) {
-			sbconfig_t *sb = REGS2SB(sii->curmap);
-			uint32 nsbba = R_SBREG(sii, &sb->sbadmatch1);
-			uint nsbcc;
-
-			sii->numcores = next + 1;
-
-			if ((nsbba & 0xfff00000) != SI_ENUM_BASE)
-				continue;
-			nsbba &= 0xfffff000;
-			if (_sb_coreidx(sii, nsbba) != BADIDX)
-				continue;
-
-			nsbcc = (R_SBREG(sii, &sb->sbtmstatehigh) & 0x000f0000) >> 16;
-			nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc);
-			if (sbba == SI_ENUM_BASE)
-				numcores -= nsbcc;
-			ncc += nsbcc;
-		}
-	}
-
-	SI_MSG(("_sb_scan: found %u cores on bus 0x%08x\n", i, sbba));
-
-	sii->numcores = i + ncc;
-	return sii->numcores;
-}
-
-/* scan the sb enumerated space to identify all cores */
-void
-sb_scan(si_t *sih, void *regs, uint devid)
-{
-	uint32 origsba;
-	sbconfig_t *sb;
-	si_info_t *sii = SI_INFO(sih);
-
-	sb = REGS2SB(sii->curmap);
-
-	sii->pub.socirev = (R_SBREG(sii, &sb->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
-
-	/* Save the current core info and validate it later till we know
-	 * for sure what is good and what is bad.
-	 */
-	origsba = _sb_coresba(sii);
-
-	/* scan all SB(s) starting from SI_ENUM_BASE */
-	sii->numcores = _sb_scan(sii, origsba, regs, 0, SI_ENUM_BASE, 1);
-}
-
-/*
- * This function changes logical "focus" to the indicated core;
- * must be called with interrupts off.
- * Moreover, callers should keep interrupts off during switching out of and back to d11 core
- */
-void *
-sb_setcoreidx(si_t *sih, uint coreidx)
-{
-	si_info_t *sii = SI_INFO(sih);
-
-	if (coreidx >= sii->numcores)
-		return (NULL);
-
-	/*
-	 * If the user has provided an interrupt mask enabled function,
-	 * then assert interrupts are disabled before switching the core.
-	 */
-	ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg));
-
-	sii->curmap = _sb_setcoreidx(sii, coreidx);
-	sii->curidx = coreidx;
-
-	return (sii->curmap);
-}
-
-/* This function changes the logical "focus" to the indicated core.
- * Return the current core's virtual address.
- */
-static void *
-_sb_setcoreidx(si_info_t *sii, uint coreidx)
-{
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint32 sbaddr = cores_info->coresba[coreidx];
-	void *regs;
-
-	switch (BUSTYPE(sii->pub.bustype)) {
-	case SI_BUS:
-		/* map new one */
-		if (!cores_info->regs[coreidx]) {
-			cores_info->regs[coreidx] = REG_MAP(sbaddr, SI_CORE_SIZE);
-			ASSERT(GOODREGS(cores_info->regs[coreidx]));
-		}
-		regs = cores_info->regs[coreidx];
-		break;
-
-	case PCI_BUS:
-		/* point bar0 window */
-		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, sbaddr);
-		regs = sii->curmap;
-		break;
-
-	case PCMCIA_BUS: {
-		uint8 tmp = (sbaddr >> 12) & 0x0f;
-		OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1);
-		tmp = (sbaddr >> 16) & 0xff;
-		OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1);
-		tmp = (sbaddr >> 24) & 0xff;
-		OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1);
-		regs = sii->curmap;
-		break;
-	}
-#ifdef BCMSDIO
-	case SPI_BUS:
-	case SDIO_BUS:
-		/* map new one */
-		if (!cores_info->regs[coreidx]) {
-			cores_info->regs[coreidx] = (void *)(uintptr)sbaddr;
-			ASSERT(GOODREGS(cores_info->regs[coreidx]));
-		}
-		regs = cores_info->regs[coreidx];
-		break;
-#endif	/* BCMSDIO */
-
-
-	default:
-		ASSERT(0);
-		regs = NULL;
-		break;
-	}
-
-	return regs;
-}
-
-/* Return the address of sbadmatch0/1/2/3 register */
-static volatile uint32 *
-sb_admatch(si_info_t *sii, uint asidx)
-{
-	sbconfig_t *sb;
-	volatile uint32 *addrm;
-
-	sb = REGS2SB(sii->curmap);
-
-	switch (asidx) {
-	case 0:
-		addrm =  &sb->sbadmatch0;
-		break;
-
-	case 1:
-		addrm =  &sb->sbadmatch1;
-		break;
-
-	case 2:
-		addrm =  &sb->sbadmatch2;
-		break;
-
-	case 3:
-		addrm =  &sb->sbadmatch3;
-		break;
-
-	default:
-		SI_ERROR(("%s: Address space index (%d) out of range\n", __FUNCTION__, asidx));
-		return 0;
-	}
-
-	return (addrm);
-}
-
-/* Return the number of address spaces in current core */
-int
-sb_numaddrspaces(si_t *sih)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-
-	sii = SI_INFO(sih);
-	sb = REGS2SB(sii->curmap);
-
-	/* + 1 because of enumeration space */
-	return ((R_SBREG(sii, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT) + 1;
-}
-
-/* Return the address of the nth address space in the current core */
-uint32
-sb_addrspace(si_t *sih, uint asidx)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-
-	return (sb_base(R_SBREG(sii, sb_admatch(sii, asidx))));
-}
-
-/* Return the size of the nth address space in the current core */
-uint32
-sb_addrspacesize(si_t *sih, uint asidx)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-
-	return (sb_size(R_SBREG(sii, sb_admatch(sii, asidx))));
-}
-
-
-/* do buffered registers update */
-void
-sb_commit(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-
-	origidx = sii->curidx;
-	ASSERT(GOODIDX(origidx));
-
-	INTR_OFF(sii, intr_val);
-
-	/* switch over to chipcommon core if there is one, else use pci */
-	if (sii->pub.ccrev != NOREV) {
-		chipcregs_t *ccregs = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
-		ASSERT(ccregs != NULL);
-
-		/* do the buffer registers update */
-		W_REG(sii->osh, &ccregs->broadcastaddress, SB_COMMIT);
-		W_REG(sii->osh, &ccregs->broadcastdata, 0x0);
-	} else
-		ASSERT(0);
-
-	/* restore core index */
-	sb_setcoreidx(sih, origidx);
-	INTR_RESTORE(sii, intr_val);
-}
-
-void
-sb_core_disable(si_t *sih, uint32 bits)
-{
-	si_info_t *sii;
-	volatile uint32 dummy;
-	sbconfig_t *sb;
-
-	sii = SI_INFO(sih);
-
-	ASSERT(GOODREGS(sii->curmap));
-	sb = REGS2SB(sii->curmap);
-
-	/* if core is already in reset, just return */
-	if (R_SBREG(sii, &sb->sbtmstatelow) & SBTML_RESET)
-		return;
-
-	/* if clocks are not enabled, put into reset and return */
-	if ((R_SBREG(sii, &sb->sbtmstatelow) & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) == 0)
-		goto disable;
-
-	/* set target reject and spin until busy is clear (preserve core-specific bits) */
-	OR_SBREG(sii, &sb->sbtmstatelow, SBTML_REJ);
-	dummy = R_SBREG(sii, &sb->sbtmstatelow);
-	BCM_REFERENCE(dummy);
-	OSL_DELAY(1);
-	SPINWAIT((R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000);
-	if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY)
-		SI_ERROR(("%s: target state still busy\n", __FUNCTION__));
-
-	if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT) {
-		OR_SBREG(sii, &sb->sbimstate, SBIM_RJ);
-		dummy = R_SBREG(sii, &sb->sbimstate);
-		BCM_REFERENCE(dummy);
-		OSL_DELAY(1);
-		SPINWAIT((R_SBREG(sii, &sb->sbimstate) & SBIM_BY), 100000);
-	}
-
-	/* set reset and reject while enabling the clocks */
-	W_SBREG(sii, &sb->sbtmstatelow,
-	        (((bits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
-	         SBTML_REJ | SBTML_RESET));
-	dummy = R_SBREG(sii, &sb->sbtmstatelow);
-	BCM_REFERENCE(dummy);
-	OSL_DELAY(10);
-
-	/* don't forget to clear the initiator reject bit */
-	if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT)
-		AND_SBREG(sii, &sb->sbimstate, ~SBIM_RJ);
-
-disable:
-	/* leave reset and reject asserted */
-	W_SBREG(sii, &sb->sbtmstatelow, ((bits << SBTML_SICF_SHIFT) | SBTML_REJ | SBTML_RESET));
-	OSL_DELAY(1);
-}
-
-/* reset and re-enable a core
- * inputs:
- * bits - core specific bits that are set during and after reset sequence
- * resetbits - core specific bits that are set only during reset sequence
- */
-void
-sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-	volatile uint32 dummy;
-
-	sii = SI_INFO(sih);
-	ASSERT(GOODREGS(sii->curmap));
-	sb = REGS2SB(sii->curmap);
-
-	/*
-	 * Must do the disable sequence first to work for arbitrary current core state.
-	 */
-	sb_core_disable(sih, (bits | resetbits));
-
-	/*
-	 * Now do the initialization sequence.
-	 */
-
-	/* set reset while enabling the clock and forcing them on throughout the core */
-	W_SBREG(sii, &sb->sbtmstatelow,
-	        (((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
-	         SBTML_RESET));
-	dummy = R_SBREG(sii, &sb->sbtmstatelow);
-	BCM_REFERENCE(dummy);
-	OSL_DELAY(1);
-
-	if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_SERR) {
-		W_SBREG(sii, &sb->sbtmstatehigh, 0);
-	}
-	if ((dummy = R_SBREG(sii, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) {
-		AND_SBREG(sii, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO));
-	}
-
-	/* clear reset and allow it to propagate throughout the core */
-	W_SBREG(sii, &sb->sbtmstatelow,
-	        ((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT));
-	dummy = R_SBREG(sii, &sb->sbtmstatelow);
-	BCM_REFERENCE(dummy);
-	OSL_DELAY(1);
-
-	/* leave clock enabled */
-	W_SBREG(sii, &sb->sbtmstatelow, ((bits | SICF_CLOCK_EN) << SBTML_SICF_SHIFT));
-	dummy = R_SBREG(sii, &sb->sbtmstatelow);
-	BCM_REFERENCE(dummy);
-	OSL_DELAY(1);
-}
-
-/*
- * Set the initiator timeout for the "master core".
- * The master core is defined to be the core in control
- * of the chip and so it issues accesses to non-memory
- * locations (Because of dma *any* core can access memeory).
- *
- * The routine uses the bus to decide who is the master:
- *	SI_BUS => mips
- *	JTAG_BUS => chipc
- *	PCI_BUS => pci or pcie
- *	PCMCIA_BUS => pcmcia
- *	SDIO_BUS => pcmcia
- *
- * This routine exists so callers can disable initiator
- * timeouts so accesses to very slow devices like otp
- * won't cause an abort. The routine allows arbitrary
- * settings of the service and request timeouts, though.
- *
- * Returns the timeout state before changing it or -1
- * on error.
- */
-
-#define	TO_MASK	(SBIMCL_RTO_MASK | SBIMCL_STO_MASK)
-
-uint32
-sb_set_initiator_to(si_t *sih, uint32 to, uint idx)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-	uint32 tmp, ret = 0xffffffff;
-	sbconfig_t *sb;
-
-
-	if ((to & ~TO_MASK) != 0)
-		return ret;
-
-	/* Figure out the master core */
-	if (idx == BADIDX) {
-		switch (BUSTYPE(sii->pub.bustype)) {
-		case PCI_BUS:
-			idx = sii->pub.buscoreidx;
-			break;
-		case JTAG_BUS:
-			idx = SI_CC_IDX;
-			break;
-		case PCMCIA_BUS:
-#ifdef BCMSDIO
-		case SDIO_BUS:
-#endif
-			idx = si_findcoreidx(sih, PCMCIA_CORE_ID, 0);
-			break;
-		case SI_BUS:
-			idx = si_findcoreidx(sih, MIPS33_CORE_ID, 0);
-			break;
-		default:
-			ASSERT(0);
-		}
-		if (idx == BADIDX)
-			return ret;
-	}
-
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	sb = REGS2SB(sb_setcoreidx(sih, idx));
-
-	tmp = R_SBREG(sii, &sb->sbimconfiglow);
-	ret = tmp & TO_MASK;
-	W_SBREG(sii, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to);
-
-	sb_commit(sih);
-	sb_setcoreidx(sih, origidx);
-	INTR_RESTORE(sii, intr_val);
-	return ret;
-}
-
-uint32
-sb_base(uint32 admatch)
-{
-	uint32 base;
-	uint type;
-
-	type = admatch & SBAM_TYPE_MASK;
-	ASSERT(type < 3);
-
-	base = 0;
-
-	if (type == 0) {
-		base = admatch & SBAM_BASE0_MASK;
-	} else if (type == 1) {
-		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
-		base = admatch & SBAM_BASE1_MASK;
-	} else if (type == 2) {
-		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
-		base = admatch & SBAM_BASE2_MASK;
-	}
-
-	return (base);
-}
-
-uint32
-sb_size(uint32 admatch)
-{
-	uint32 size;
-	uint type;
-
-	type = admatch & SBAM_TYPE_MASK;
-	ASSERT(type < 3);
-
-	size = 0;
-
-	if (type == 0) {
-		size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1);
-	} else if (type == 1) {
-		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
-		size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1);
-	} else if (type == 2) {
-		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
-		size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1);
-	}
-
-	return (size);
-}
-
-#if defined(BCMDBG_PHYDUMP)
-/* print interesting sbconfig registers */
-void
-sb_dumpregs(si_t *sih, struct bcmstrbuf *b)
-{
-	sbconfig_t *sb;
-	uint origidx, i, intr_val = 0;
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	origidx = sii->curidx;
-
-	INTR_OFF(sii, intr_val);
-
-	for (i = 0; i < sii->numcores; i++) {
-		sb = REGS2SB(sb_setcoreidx(sih, i));
-
-		bcm_bprintf(b, "core 0x%x: \n", cores_info->coreid[i]);
-
-		if (sii->pub.socirev > SONICS_2_2)
-			bcm_bprintf(b, "sbimerrlog 0x%x sbimerrloga 0x%x\n",
-			          sb_corereg(sih, si_coreidx(&sii->pub), SBIMERRLOG, 0, 0),
-			          sb_corereg(sih, si_coreidx(&sii->pub), SBIMERRLOGA, 0, 0));
-
-		bcm_bprintf(b, "sbtmstatelow 0x%x sbtmstatehigh 0x%x sbidhigh 0x%x "
-		            "sbimstate 0x%x\n sbimconfiglow 0x%x sbimconfighigh 0x%x\n",
-		            R_SBREG(sii, &sb->sbtmstatelow), R_SBREG(sii, &sb->sbtmstatehigh),
-		            R_SBREG(sii, &sb->sbidhigh), R_SBREG(sii, &sb->sbimstate),
-		            R_SBREG(sii, &sb->sbimconfiglow), R_SBREG(sii, &sb->sbimconfighigh));
-	}
-
-	sb_setcoreidx(sih, origidx);
-	INTR_RESTORE(sii, intr_val);
-}
-#endif	
diff --git a/drivers/net/wireless/bcmdhd/siutils.c b/drivers/net/wireless/bcmdhd/siutils.c
deleted file mode 100644
index 6ec96d0f..0000000
--- a/drivers/net/wireless/bcmdhd/siutils.c
+++ /dev/null
@@ -1,3245 +0,0 @@
-/*
- * Misc utility routines for accessing chip-specific features
- * of the SiliconBackplane-based Broadcom chips.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: siutils.c 552034 2015-04-24 19:00:35Z $
- */
-
-#include <bcm_cfg.h>
-#include <typedefs.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <bcmdevs.h>
-#include <hndsoc.h>
-#include <sbchipc.h>
-#ifdef BCMPCIEDEV
-#include <pciedev.h>
-#endif /* BCMPCIEDEV */
-#include <pcicfg.h>
-#include <sbpcmcia.h>
-#include <sbsysmem.h>
-#include <sbsocram.h>
-#ifdef BCMSDIO
-#include <bcmsdh.h>
-#include <sdio.h>
-#include <sbsdio.h>
-#include <sbhnddma.h>
-#include <sbsdpcmdev.h>
-#include <bcmsdpcm.h>
-#endif /* BCMSDIO */
-#include <hndpmu.h>
-
-#ifdef BCM_SDRBL
-#include <hndcpu.h>
-#endif /* BCM_SDRBL */
-#ifdef HNDGCI
-#include <hndgci.h>
-#endif /* HNDGCI */
-
-#include "siutils_priv.h"
-
-/**
- * A set of PMU registers is clocked in the ILP domain, which has an implication on register write
- * behavior: if such a register is written, it takes multiple ILP clocks for the PMU block to absorb
- * the write. During that time the 'SlowWritePending' bit in the PMUStatus register is set.
- */
-#define PMUREGS_ILP_SENSITIVE(regoff) \
-	((regoff) == OFFSETOF(pmuregs_t, pmutimer) || \
-	 (regoff) == OFFSETOF(pmuregs_t, pmuwatchdog) || \
-	 (regoff) == OFFSETOF(pmuregs_t, res_req_timer))
-
-#define CHIPCREGS_ILP_SENSITIVE(regoff) \
-	((regoff) == OFFSETOF(chipcregs_t, pmutimer) || \
-	 (regoff) == OFFSETOF(chipcregs_t, pmuwatchdog) || \
-	 (regoff) == OFFSETOF(chipcregs_t, res_req_timer))
-
-/* local prototypes */
-static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
-                              uint bustype, void *sdh, char **vars, uint *varsz);
-static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
-static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
-	uint *origidx, void *regs);
-
-
-static bool si_pmu_is_ilp_sensitive(uint32 idx, uint regoff);
-
-#ifdef BCMLTECOEX
-static void si_config_gcigpio(si_t *sih, uint32 gci_pos, uint8 gcigpio,
-	uint8 gpioctl_mask, uint8 gpioctl_val);
-#endif /* BCMLTECOEX */
-
-
-/* global variable to indicate reservation/release of gpio's */
-static uint32 si_gpioreservation = 0;
-
-/* global flag to prevent shared resources from being initialized multiple times in si_attach() */
-#ifdef SR_DEBUG
-static const uint32 si_power_island_test_array[] = {
-	0x0000, 0x0001, 0x0010, 0x0011,
-	0x0100, 0x0101, 0x0110, 0x0111,
-	0x1000, 0x1001, 0x1010, 0x1011,
-	0x1100, 0x1101, 0x1110, 0x1111
-};
-#endif /* SR_DEBUG */
-
-int do_4360_pcie2_war = 0;
-
-/* global kernel resource */
-static si_info_t ksii;
-static si_cores_info_t ksii_cores_info;
-
-/**
- * Allocate an si handle. This function may be called multiple times.
- *
- * devid - pci device id (used to determine chip#)
- * osh - opaque OS handle
- * regs - virtual address of initial core registers
- * bustype - pci/pcmcia/sb/sdio/etc
- * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
- *        function set 'vars' to NULL, making dereferencing of this parameter undesired.
- * varsz - pointer to int to return the size of the vars
- */
-si_t *
-si_attach(uint devid, osl_t *osh, void *regs,
-                       uint bustype, void *sdh, char **vars, uint *varsz)
-{
-	si_info_t *sii;
-	si_cores_info_t *cores_info;
-	/* alloc si_info_t */
-	if ((sii = MALLOCZ(osh, sizeof (si_info_t))) == NULL) {
-		SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
-		return (NULL);
-	}
-
-	/* alloc si_cores_info_t */
-	if ((cores_info = (si_cores_info_t *)MALLOCZ(osh, sizeof (si_cores_info_t))) == NULL) {
-		SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
-		MFREE(osh, sii, sizeof(si_info_t));
-		return (NULL);
-	}
-	sii->cores_info = cores_info;
-
-	if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
-		MFREE(osh, sii, sizeof(si_info_t));
-		MFREE(osh, cores_info, sizeof(si_cores_info_t));
-		return (NULL);
-	}
-	sii->vars = vars ? *vars : NULL;
-	sii->varsz = varsz ? *varsz : 0;
-
-	return (si_t *)sii;
-}
-
-
-static uint32	wd_msticks;		/* watchdog timer ticks normalized to ms */
-
-/** generic kernel variant of si_attach() */
-si_t *
-si_kattach(osl_t *osh)
-{
-	static bool ksii_attached = FALSE;
-	si_cores_info_t *cores_info;
-
-	if (!ksii_attached) {
-		void *regs = NULL;
-		regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
-		cores_info = (si_cores_info_t *)&ksii_cores_info;
-		ksii.cores_info = cores_info;
-
-		ASSERT(osh);
-		if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
-		                SI_BUS, NULL,
-		                osh != SI_OSH ? &(ksii.vars) : NULL,
-		                osh != SI_OSH ? &(ksii.varsz) : NULL) == NULL) {
-			SI_ERROR(("si_kattach: si_doattach failed\n"));
-			REG_UNMAP(regs);
-			return NULL;
-		}
-		REG_UNMAP(regs);
-
-		/* save ticks normalized to ms for si_watchdog_ms() */
-		if (PMUCTL_ENAB(&ksii.pub)) {
-				/* based on 32KHz ILP clock */
-				wd_msticks = 32;
-		} else {
-			wd_msticks = ALP_CLOCK / 1000;
-		}
-
-		ksii_attached = TRUE;
-		SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
-		        ksii.pub.ccrev, wd_msticks));
-	}
-
-	return &ksii.pub;
-}
-
-
-static bool
-si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
-{
-	/* need to set memseg flag for CF card first before any sb registers access */
-	if (BUSTYPE(bustype) == PCMCIA_BUS)
-		sii->memseg = TRUE;
-
-
-#if defined(BCMSDIO)
-	if (BUSTYPE(bustype) == SDIO_BUS) {
-		int err;
-		uint8 clkset;
-
-		/* Try forcing SDIO core to do ALPAvail request only */
-		clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
-		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
-		if (!err) {
-			uint8 clkval;
-
-			/* If register supported, wait for ALPAvail and then force ALP */
-			clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
-			if ((clkval & ~SBSDIO_AVBITS) == clkset) {
-				SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
-					SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)),
-					PMU_MAX_TRANSITION_DLY);
-				if (!SBSDIO_ALPAV(clkval)) {
-					SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n",
-						clkval));
-					return FALSE;
-				}
-				clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
-				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-					clkset, &err);
-				OSL_DELAY(65);
-			}
-		}
-
-		/* Also, disable the extra SDIO pull-ups */
-		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
-	}
-
-#endif /* BCMSDIO && BCMDONGLEHOST */
-
-	return TRUE;
-}
-
-static bool
-si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
-	uint *origidx, void *regs)
-{
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	bool pci, pcie, pcie_gen2 = FALSE;
-	uint i;
-	uint pciidx, pcieidx, pcirev, pcierev;
-
-	/* first, enable backplane timeouts */
-	if (CHIPTYPE(sii->pub.socitype) == SOCI_AI)
-		ai_enable_backplane_timeouts(&sii->pub);
-
-	cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
-	ASSERT((uintptr)cc);
-
-	/* get chipcommon rev */
-	sii->pub.ccrev = (int)si_corerev(&sii->pub);
-
-	/* get chipcommon chipstatus */
-	if (sii->pub.ccrev >= 11)
-		sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
-
-	/* get chipcommon capabilites */
-	sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
-	/* get chipcommon extended capabilities */
-
-	if (sii->pub.ccrev >= 35)
-		sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
-
-	/* get pmu rev and caps */
-	if (sii->pub.cccaps & CC_CAP_PMU) {
-		if (AOB_ENAB(&sii->pub)) {
-			uint pmucoreidx;
-			pmuregs_t *pmu;
-			pmucoreidx = si_findcoreidx(&sii->pub, PMU_CORE_ID, 0);
-			pmu = si_setcoreidx(&sii->pub, pmucoreidx);
-			sii->pub.pmucaps = R_REG(sii->osh, &pmu->pmucapabilities);
-			si_setcoreidx(&sii->pub, SI_CC_IDX);
-		} else
-			sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
-
-		sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
-	}
-
-	SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
-		sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
-		sii->pub.pmucaps));
-
-	/* figure out bus/orignal core idx */
-	sii->pub.buscoretype = NODEV_CORE_ID;
-	sii->pub.buscorerev = (uint)NOREV;
-	sii->pub.buscoreidx = BADIDX;
-
-	pci = pcie = FALSE;
-	pcirev = pcierev = (uint)NOREV;
-	pciidx = pcieidx = BADIDX;
-
-	for (i = 0; i < sii->numcores; i++) {
-		uint cid, crev;
-
-		si_setcoreidx(&sii->pub, i);
-		cid = si_coreid(&sii->pub);
-		crev = si_corerev(&sii->pub);
-
-		/* Display cores found */
-		SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
-		        i, cid, crev, cores_info->coresba[i], cores_info->regs[i]));
-
-		if (BUSTYPE(bustype) == SI_BUS) {
-			/* now look at the chipstatus register to figure the pacakge */
-			/* for SDIO but downloaded on PCIE dev */
-			if (cid == PCIE2_CORE_ID) {
-				if (BCM43602_CHIP(sii->pub.chip) ||
-					(CHIPID(sii->pub.chip) == BCM4365_CHIP_ID) ||
-					(CHIPID(sii->pub.chip) == BCM4366_CHIP_ID) ||
-					((CHIPID(sii->pub.chip) == BCM4345_CHIP_ID ||
-					CHIPID(sii->pub.chip) == BCM43454_CHIP_ID) &&
-					CST4345_CHIPMODE_PCIE(sii->pub.chipst))) {
-					pcieidx = i;
-					pcierev = crev;
-					pcie = TRUE;
-					pcie_gen2 = TRUE;
-				}
-			}
-
-		}
-		else if (BUSTYPE(bustype) == PCI_BUS) {
-			if (cid == PCI_CORE_ID) {
-				pciidx = i;
-				pcirev = crev;
-				pci = TRUE;
-			} else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) {
-				pcieidx = i;
-				pcierev = crev;
-				pcie = TRUE;
-				if (cid == PCIE2_CORE_ID)
-					pcie_gen2 = TRUE;
-			}
-		} else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
-		           (cid == PCMCIA_CORE_ID)) {
-			sii->pub.buscorerev = crev;
-			sii->pub.buscoretype = cid;
-			sii->pub.buscoreidx = i;
-		}
-#ifdef BCMSDIO
-		else if (((BUSTYPE(bustype) == SDIO_BUS) ||
-		          (BUSTYPE(bustype) == SPI_BUS)) &&
-		         ((cid == PCMCIA_CORE_ID) ||
-		          (cid == SDIOD_CORE_ID))) {
-			sii->pub.buscorerev = crev;
-			sii->pub.buscoretype = cid;
-			sii->pub.buscoreidx = i;
-		}
-#endif /* BCMSDIO */
-
-		/* find the core idx before entering this func. */
-		if ((savewin && (savewin == cores_info->coresba[i])) ||
-		    (regs == cores_info->regs[i]))
-			*origidx = i;
-	}
-
-
-#if defined(PCIE_FULL_DONGLE)
-	if (pcie) {
-		if (pcie_gen2)
-			sii->pub.buscoretype = PCIE2_CORE_ID;
-		else
-			sii->pub.buscoretype = PCIE_CORE_ID;
-		sii->pub.buscorerev = pcierev;
-		sii->pub.buscoreidx = pcieidx;
-	}
-	BCM_REFERENCE(pci);
-	BCM_REFERENCE(pcirev);
-	BCM_REFERENCE(pciidx);
-#else
-	if (pci) {
-		sii->pub.buscoretype = PCI_CORE_ID;
-		sii->pub.buscorerev = pcirev;
-		sii->pub.buscoreidx = pciidx;
-	} else if (pcie) {
-		if (pcie_gen2)
-			sii->pub.buscoretype = PCIE2_CORE_ID;
-		else
-			sii->pub.buscoretype = PCIE_CORE_ID;
-		sii->pub.buscorerev = pcierev;
-		sii->pub.buscoreidx = pcieidx;
-	}
-#endif /* defined(PCIE_FULL_DONGLE) */
-
-	SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
-	         sii->pub.buscorerev));
-
-	if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
-	    (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
-		OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
-
-
-#if defined(BCMSDIO)
-	/* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was
-	 * already running.
-	 */
-	if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
-		if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
-		    si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
-			si_core_disable(&sii->pub, 0);
-	}
-#endif /* BCMSDIO && BCMDONGLEHOST */
-
-	/* return to the original core */
-	si_setcoreidx(&sii->pub, *origidx);
-
-	return TRUE;
-}
-
-
-
-
-uint16
-si_chipid(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-
-	return (sii->chipnew) ? sii->chipnew : sih->chip;
-}
-
-static void
-si_chipid_fixup(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-
-	ASSERT(sii->chipnew == 0);
-	switch (sih->chip) {
-		case BCM43567_CHIP_ID:
-			sii->chipnew = sih->chip; /* save it */
-			sii->pub.chip = BCM43570_CHIP_ID; /* chip class */
-		break;
-		case BCM4358_CHIP_ID:
-		case BCM43566_CHIP_ID:
-			sii->chipnew = sih->chip; /* save it */
-			sii->pub.chip = BCM43569_CHIP_ID; /* chip class */
-		break;
-		case BCM4356_CHIP_ID:
-			sii->chipnew = sih->chip; /* save it */
-			sii->pub.chip = BCM4354_CHIP_ID; /* chip class */
-		break;
-		default:
-		break;
-	}
-}
-
-/**
- * Allocate an si handle. This function may be called multiple times.
- *
- * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
- *        function set 'vars' to NULL.
- */
-static si_info_t *
-si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
-                       uint bustype, void *sdh, char **vars, uint *varsz)
-{
-	struct si_pub *sih = &sii->pub;
-	uint32 w, savewin;
-	chipcregs_t *cc;
-	char *pvars = NULL;
-	uint origidx;
-#if !defined(_CFEZ_) || defined(CFG_WL)
-#endif 
-
-	ASSERT(GOODREGS(regs));
-
-	savewin = 0;
-
-	sih->buscoreidx = BADIDX;
-
-	sii->curmap = regs;
-	sii->sdh = sdh;
-	sii->osh = osh;
-	sii->second_bar0win = ~0x0;
-
-
-	/* check to see if we are a si core mimic'ing a pci core */
-	if ((bustype == PCI_BUS) &&
-	    (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) {
-		SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
-		          "devid:0x%x\n", __FUNCTION__, devid));
-		bustype = SI_BUS;
-	}
-
-	/* find Chipcommon address */
-	if (bustype == PCI_BUS) {
-		savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
-		if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
-			savewin = SI_ENUM_BASE;
-		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
-		if (!regs)
-			return NULL;
-		cc = (chipcregs_t *)regs;
-#ifdef BCMSDIO
-	} else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) {
-		cc = (chipcregs_t *)sii->curmap;
-#endif
-	} else {
-		cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
-	}
-
-	sih->bustype = bustype;
-	if (bustype != BUSTYPE(bustype)) {
-		SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
-			bustype, BUSTYPE(bustype)));
-		return NULL;
-	}
-
-	/* bus/core/clk setup for register access */
-	if (!si_buscore_prep(sii, bustype, devid, sdh)) {
-		SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
-		return NULL;
-	}
-
-	/* ChipID recognition.
-	*   We assume we can read chipid at offset 0 from the regs arg.
-	*   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
-	*   some way of recognizing them needs to be added here.
-	*/
-	if (!cc) {
-		SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__));
-		return NULL;
-	}
-	w = R_REG(osh, &cc->chipid);
-	if ((w & 0xfffff) == 148277) w -= 65532;
-	sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
-	/* Might as wll fill in chip id rev & pkg */
-	sih->chip = w & CID_ID_MASK;
-	sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
-	sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
-
-	si_chipid_fixup(sih);
-
-	if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && CHIPREV(sih->chiprev == 0) &&
-		(sih->chippkg != BCM4329_289PIN_PKG_ID)) {
-		sih->chippkg = BCM4329_182PIN_PKG_ID;
-	}
-	sih->issim = IS_SIM(sih->chippkg);
-
-	/* scan for cores */
-	if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
-		SI_MSG(("Found chip type SB (0x%08x)\n", w));
-		sb_scan(&sii->pub, regs, devid);
-	} else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) ||
-		(CHIPTYPE(sii->pub.socitype) == SOCI_NAI)) {
-		if (CHIPTYPE(sii->pub.socitype) == SOCI_AI)
-			SI_MSG(("Found chip type AI (0x%08x)\n", w));
-		else
-			SI_MSG(("Found chip type NAI (0x%08x)\n", w));
-		/* pass chipc address instead of original core base */
-		ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
-	} else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
-		SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
-		/* pass chipc address instead of original core base */
-		ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
-	} else {
-		SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
-		return NULL;
-	}
-	/* no cores found, bail out */
-	if (sii->numcores == 0) {
-		SI_ERROR(("si_doattach: could not find any cores\n"));
-		return NULL;
-	}
-	/* bus/core/clk setup */
-	origidx = SI_CC_IDX;
-	if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
-		SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
-		goto exit;
-	}
-
-#if !defined(_CFEZ_) || defined(CFG_WL)
-	if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
-		>> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
-		CST4322_SPROM_PRESENT))) {
-		SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
-		return NULL;
-	}
-
-	/* assume current core is CC */
-	if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
-	                                  CHIPID(sih->chip) == BCM43235_CHIP_ID ||
-	                                  CHIPID(sih->chip) == BCM43234_CHIP_ID ||
-	                                  CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
-	                                 (CHIPREV(sii->pub.chiprev) <= 2))) {
-
-		if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
-			uint clkdiv;
-			clkdiv = R_REG(osh, &cc->clkdiv);
-			/* otp_clk_div is even number, 120/14 < 9mhz */
-			clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
-			W_REG(osh, &cc->clkdiv, clkdiv);
-			SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
-		}
-		OSL_DELAY(10);
-	}
-
-	if (bustype == PCI_BUS) {
-
-	}
-#endif 
-#ifdef BCM_SDRBL
-	/* 4360 rom bootloader in PCIE case, if the SDR is enabled, But preotection is
-	 * not turned on, then we want to hold arm in reset.
-	 * Bottomline: In sdrenable case, we allow arm to boot only when protection is
-	 * turned on.
-	 */
-	if (CHIP_HOSTIF_PCIE(&(sii->pub))) {
-		uint32 sflags = si_arm_sflags(&(sii->pub));
-
-		/* If SDR is enabled but protection is not turned on
-		* then we want to force arm to WFI.
-		*/
-		if ((sflags & (SISF_SDRENABLE | SISF_TCMPROT)) == SISF_SDRENABLE) {
-			disable_arm_irq();
-			while (1) {
-				hnd_cpu_wait(sih);
-			}
-		}
-	}
-#endif /* BCM_SDRBL */
-
-	pvars = NULL;
-	BCM_REFERENCE(pvars);
-
-
-
-		if (sii->pub.ccrev >= 20) {
-			uint32 gpiopullup = 0, gpiopulldown = 0;
-			cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
-			ASSERT(cc != NULL);
-
-			/* 4314/43142 has pin muxing, don't clear gpio bits */
-			if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
-				(CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
-				gpiopullup |= 0x402e0;
-				gpiopulldown |= 0x20500;
-			}
-
-
-			W_REG(osh, &cc->gpiopullup, gpiopullup);
-			W_REG(osh, &cc->gpiopulldown, gpiopulldown);
-			si_setcoreidx(sih, origidx);
-		}
-
-
-	/* clear any previous epidiag-induced target abort */
-	ASSERT(!si_taclear(sih, FALSE));
-
-
-#ifdef BOOTLOADER_CONSOLE_OUTPUT
-	/* Enable console prints */
-	si_muxenab(sii, 3);
-#endif
-
-	return (sii);
-
-exit:
-
-	return NULL;
-}
-
-/** may be called with core in reset */
-void
-si_detach(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint idx;
-
-
-	if (BUSTYPE(sih->bustype) == SI_BUS)
-		for (idx = 0; idx < SI_MAXCORES; idx++)
-			if (cores_info->regs[idx]) {
-				REG_UNMAP(cores_info->regs[idx]);
-				cores_info->regs[idx] = NULL;
-			}
-
-
-#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
-	if (cores_info != &ksii_cores_info)
-#endif	/* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
-		MFREE(sii->osh, cores_info, sizeof(si_cores_info_t));
-
-#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
-	if (sii != &ksii)
-#endif	/* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
-		MFREE(sii->osh, sii, sizeof(si_info_t));
-}
-
-void *
-si_osh(si_t *sih)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-	return sii->osh;
-}
-
-void
-si_setosh(si_t *sih, osl_t *osh)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-	if (sii->osh != NULL) {
-		SI_ERROR(("osh is already set....\n"));
-		ASSERT(!sii->osh);
-	}
-	sii->osh = osh;
-}
-
-/** register driver interrupt disabling and restoring callback functions */
-void
-si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
-                          void *intrsenabled_fn, void *intr_arg)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	sii->intr_arg = intr_arg;
-	sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
-	sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
-	sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
-	/* save current core id.  when this function called, the current core
-	 * must be the core which provides driver functions(il, et, wl, etc.)
-	 */
-	sii->dev_coreid = cores_info->coreid[sii->curidx];
-}
-
-void
-si_deregister_intr_callback(si_t *sih)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-	sii->intrsoff_fn = NULL;
-	sii->intrsrestore_fn = NULL;
-	sii->intrsenabled_fn = NULL;
-}
-
-uint
-si_intflag(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_intflag(sih);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return R_REG(sii->osh, ((uint32 *)(uintptr)
-			    (sii->oob_router + OOB_STATUSA)));
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-uint
-si_flag(si_t *sih)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_flag(sih);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_flag(sih);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_flag(sih);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-uint
-si_flag_alt(si_t *sih)
-{
-	if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_flag_alt(sih);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-void
-si_setint(si_t *sih, int siflag)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		sb_setint(sih, siflag);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		ai_setint(sih, siflag);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		ub_setint(sih, siflag);
-	else
-		ASSERT(0);
-}
-
-uint
-si_coreid(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	return cores_info->coreid[sii->curidx];
-}
-
-uint
-si_coreidx(si_t *sih)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-	return sii->curidx;
-}
-
-void *
-si_d11_switch_addrbase(si_t *sih, uint coreunit)
-{
-	return si_setcore(sih,  D11_CORE_ID, coreunit);
-}
-
-/** return the core-type instantiation # of the current core */
-uint
-si_coreunit(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint idx;
-	uint coreid;
-	uint coreunit;
-	uint i;
-
-	coreunit = 0;
-
-	idx = sii->curidx;
-
-	ASSERT(GOODREGS(sii->curmap));
-	coreid = si_coreid(sih);
-
-	/* count the cores of our type */
-	for (i = 0; i < idx; i++)
-		if (cores_info->coreid[i] == coreid)
-			coreunit++;
-
-	return (coreunit);
-}
-
-uint
-si_corevendor(si_t *sih)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_corevendor(sih);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_corevendor(sih);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_corevendor(sih);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-bool
-si_backplane64(si_t *sih)
-{
-	return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
-}
-
-uint
-si_corerev(si_t *sih)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_corerev(sih);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_corerev(sih);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_corerev(sih);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-
-/* return index of coreid or BADIDX if not found */
-uint
-si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint found;
-	uint i;
-
-
-	found = 0;
-
-	for (i = 0; i < sii->numcores; i++)
-		if (cores_info->coreid[i] == coreid) {
-			if (found == coreunit)
-				return (i);
-			found++;
-		}
-
-	return (BADIDX);
-}
-
-/** return total coreunit of coreid or zero if not found */
-uint
-si_numcoreunits(si_t *sih, uint coreid)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint found = 0;
-	uint i;
-
-	for (i = 0; i < sii->numcores; i++) {
-		if (cores_info->coreid[i] == coreid) {
-			found++;
-		}
-	}
-
-	return found;
-}
-
-/** return total D11 coreunits */
-uint
-BCMRAMFN(si_numd11coreunits)(si_t *sih)
-{
-	uint found = 0;
-
-	found = si_numcoreunits(sih, D11_CORE_ID);
-
-#if defined(WLRSDB) && defined(WLRSDB_DISABLED)
-	/* If RSDB functionality is compiled out,
-	 * then ignore any D11 cores beyond the first
-	 * Used in norsdb dongle build variants for rsdb chip.
-	 */
-	found = 1;
-#endif /* defined(WLRSDB) && !defined(WLRSDB_DISABLED) */
-
-	return found;
-}
-
-/** return list of found cores */
-uint
-si_corelist(si_t *sih, uint coreid[])
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	bcopy((uchar*)cores_info->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
-	return (sii->numcores);
-}
-
-/** return current wrapper mapping */
-void *
-si_wrapperregs(si_t *sih)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-	ASSERT(GOODREGS(sii->curwrap));
-
-	return (sii->curwrap);
-}
-
-/** return current register mapping */
-void *
-si_coreregs(si_t *sih)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-	ASSERT(GOODREGS(sii->curmap));
-
-	return (sii->curmap);
-}
-
-/**
- * This function changes logical "focus" to the indicated core;
- * must be called with interrupts off.
- * Moreover, callers should keep interrupts off during switching out of and back to d11 core
- */
-void *
-si_setcore(si_t *sih, uint coreid, uint coreunit)
-{
-	uint idx;
-
-	idx = si_findcoreidx(sih, coreid, coreunit);
-	if (!GOODIDX(idx))
-		return (NULL);
-
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_setcoreidx(sih, idx);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_setcoreidx(sih, idx);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_setcoreidx(sih, idx);
-	else {
-		ASSERT(0);
-		return NULL;
-	}
-}
-
-void *
-si_setcoreidx(si_t *sih, uint coreidx)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_setcoreidx(sih, coreidx);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_setcoreidx(sih, coreidx);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_setcoreidx(sih, coreidx);
-	else {
-		ASSERT(0);
-		return NULL;
-	}
-}
-
-/** Turn off interrupt as required by sb_setcore, before switch core */
-void *
-si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
-{
-	void *cc;
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	if (SI_FAST(sii)) {
-		/* Overloading the origidx variable to remember the coreid,
-		 * this works because the core ids cannot be confused with
-		 * core indices.
-		 */
-		*origidx = coreid;
-		if (coreid == CC_CORE_ID)
-			return (void *)CCREGS_FAST(sii);
-		else if (coreid == sih->buscoretype)
-			return (void *)PCIEREGS(sii);
-	}
-	INTR_OFF(sii, *intr_val);
-	*origidx = sii->curidx;
-	cc = si_setcore(sih, coreid, 0);
-	ASSERT(cc != NULL);
-
-	return cc;
-}
-
-/* restore coreidx and restore interrupt */
-void
-si_restore_core(si_t *sih, uint coreid, uint intr_val)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
-		return;
-
-	si_setcoreidx(sih, coreid);
-	INTR_RESTORE(sii, intr_val);
-}
-
-int
-si_numaddrspaces(si_t *sih)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_numaddrspaces(sih);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_numaddrspaces(sih);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_numaddrspaces(sih);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-uint32
-si_addrspace(si_t *sih, uint asidx)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_addrspace(sih, asidx);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_addrspace(sih, asidx);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_addrspace(sih, asidx);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-uint32
-si_addrspacesize(si_t *sih, uint asidx)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_addrspacesize(sih, asidx);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_addrspacesize(sih, asidx);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_addrspacesize(sih, asidx);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-void
-si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
-{
-	/* Only supported for SOCI_AI */
-	if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		ai_coreaddrspaceX(sih, asidx, addr, size);
-	else
-		*size = 0;
-}
-
-uint32
-si_core_cflags(si_t *sih, uint32 mask, uint32 val)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_core_cflags(sih, mask, val);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_core_cflags(sih, mask, val);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_core_cflags(sih, mask, val);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-void
-si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		sb_core_cflags_wo(sih, mask, val);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		ai_core_cflags_wo(sih, mask, val);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		ub_core_cflags_wo(sih, mask, val);
-	else
-		ASSERT(0);
-}
-
-uint32
-si_core_sflags(si_t *sih, uint32 mask, uint32 val)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_core_sflags(sih, mask, val);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_core_sflags(sih, mask, val);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_core_sflags(sih, mask, val);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-bool
-si_iscoreup(si_t *sih)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_iscoreup(sih);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_iscoreup(sih);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_iscoreup(sih);
-	else {
-		ASSERT(0);
-		return FALSE;
-	}
-}
-
-uint
-si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
-{
-	/* only for AI back plane chips */
-	if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return (ai_wrap_reg(sih, offset, mask, val));
-	return 0;
-}
-/* si_backplane_access is used to read full backplane address from host for PCIE FD
- * it uses secondary bar-0 window which lies at an offset of 16K from primary bar-0
- * Provides support for read/write of 1/2/4 bytes of backplane address
- * Can be used to read/write
- *	1. core regs
- *	2. Wrapper regs
- *	3. memory
- *	4. BT area
- * For accessing any 32 bit backplane address, [31 : 12] of backplane should be given in "region"
- * [11 : 0] should be the "regoff"
- * for reading  4 bytes from reg 0x200 of d11 core use it like below
- * : si_backplane_access(sih, 0x18001000, 0x200, 4, 0, TRUE)
- */
-static int si_backplane_addr_sane(uint addr, uint size)
-{
-	int bcmerror = BCME_OK;
-
-	/* For 2 byte access, address has to be 2 byte aligned */
-	if (size == 2) {
-		if (addr & 0x1) {
-			bcmerror = BCME_ERROR;
-		}
-	}
-	/* For 4 byte access, address has to be 4 byte aligned */
-	if (size == 4) {
-		if (addr & 0x3) {
-			bcmerror = BCME_ERROR;
-		}
-	}
-
-	return bcmerror;
-}
-uint
-si_backplane_access(si_t *sih, uint addr, uint size, uint *val, bool read)
-{
-	uint32 *r = NULL;
-	uint32 region = 0;
-	si_info_t *sii = SI_INFO(sih);
-
-	/* Valid only for pcie bus */
-	if (BUSTYPE(sih->bustype) != PCI_BUS) {
-		SI_ERROR(("Valid only for pcie bus \n"));
-		return BCME_ERROR;
-	}
-
-	/* Split adrr into region and address offset */
-	region = (addr & (0xFFFFF << 12));
-	addr = addr & 0xFFF;
-
-	/* check for address and size sanity */
-	if (si_backplane_addr_sane(addr, size) != BCME_OK)
-		return BCME_ERROR;
-
-	/* Update window if required */
-	if (sii->second_bar0win != region) {
-		OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_CORE2_WIN, 4, region);
-		sii->second_bar0win = region;
-	}
-
-	/* Estimate effective address
-	 * sii->curmap   : bar-0 virtual address
-	 * PCI_SECOND_BAR0_OFFSET  : secondar bar-0 offset
-	 * regoff : actual reg offset
-	 */
-	r = (uint32 *)((char *)sii->curmap + PCI_SECOND_BAR0_OFFSET + addr);
-
-	SI_VMSG(("si curmap %p  region %x regaddr %x effective addr %p READ %d\n",
-		(char*)sii->curmap, region, addr, r, read));
-
-	switch (size) {
-		case sizeof(uint8) :
-			if (read)
-				*val = R_REG(sii->osh, (uint8*)r);
-			else
-				W_REG(sii->osh, (uint8*)r, *val);
-			break;
-		case sizeof(uint16) :
-			if (read)
-				*val = R_REG(sii->osh, (uint16*)r);
-			else
-				W_REG(sii->osh, (uint16*)r, *val);
-			break;
-		case sizeof(uint32) :
-			if (read)
-				*val = R_REG(sii->osh, (uint32*)r);
-			else
-				W_REG(sii->osh, (uint32*)r, *val);
-			break;
-
-		default :
-			SI_ERROR(("Invalid  size %d \n", size));
-			return (BCME_ERROR);
-			break;
-	}
-
-	return (BCME_OK);
-}
-uint
-si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_corereg(sih, coreidx, regoff, mask, val);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_corereg(sih, coreidx, regoff, mask, val);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		return ub_corereg(sih, coreidx, regoff, mask, val);
-	else {
-		ASSERT(0);
-		return 0;
-	}
-}
-
-/** ILP sensitive register access needs special treatment to avoid backplane stalls */
-bool si_pmu_is_ilp_sensitive(uint32 idx, uint regoff)
-{
-	if (idx == SI_CC_IDX) {
-		if (CHIPCREGS_ILP_SENSITIVE(regoff))
-			return TRUE;
-	} else if (PMUREGS_ILP_SENSITIVE(regoff)) {
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-/** 'idx' should refer either to the chipcommon core or the PMU core */
-uint
-si_pmu_corereg(si_t *sih, uint32 idx, uint regoff, uint mask, uint val)
-{
-	int pmustatus_offset;
-
-	/* prevent backplane stall on double write to 'ILP domain' registers in the PMU */
-	if (mask != 0 && sih->pmurev >= 22 &&
-	    si_pmu_is_ilp_sensitive(idx, regoff)) {
-		pmustatus_offset = AOB_ENAB(sih) ? OFFSETOF(pmuregs_t, pmustatus) :
-			OFFSETOF(chipcregs_t, pmustatus);
-
-		while (si_corereg(sih, idx, pmustatus_offset, 0, 0) & PST_SLOW_WR_PENDING)
-			{};
-	}
-
-	return si_corereg(sih, idx, regoff, mask, val);
-}
-
-/*
- * If there is no need for fiddling with interrupts or core switches (typically silicon
- * back plane registers, pci registers and chipcommon registers), this function
- * returns the register offset on this core to a mapped address. This address can
- * be used for W_REG/R_REG directly.
- *
- * For accessing registers that would need a core switch, this function will return
- * NULL.
- */
-uint32 *
-si_corereg_addr(si_t *sih, uint coreidx, uint regoff)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		return sb_corereg_addr(sih, coreidx, regoff);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		return ai_corereg_addr(sih, coreidx, regoff);
-	else {
-		return 0;
-	}
-}
-
-void
-si_core_disable(si_t *sih, uint32 bits)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		sb_core_disable(sih, bits);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		ai_core_disable(sih, bits);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		ub_core_disable(sih, bits);
-}
-
-void
-si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
-{
-	if (CHIPTYPE(sih->socitype) == SOCI_SB)
-		sb_core_reset(sih, bits, resetbits);
-	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
-		ai_core_reset(sih, bits, resetbits);
-	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
-		ub_core_reset(sih, bits, resetbits);
-}
-
-/** Run bist on current core. Caller needs to take care of core-specific bist hazards */
-int
-si_corebist(si_t *sih)
-{
-	uint32 cflags;
-	int result = 0;
-
-	/* Read core control flags */
-	cflags = si_core_cflags(sih, 0, 0);
-
-	/* Set bist & fgc */
-	si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
-
-	/* Wait for bist done */
-	SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
-
-	if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
-		result = BCME_ERROR;
-
-	/* Reset core control flags */
-	si_core_cflags(sih, 0xffff, cflags);
-
-	return result;
-}
-
-static uint32
-factor6(uint32 x)
-{
-	switch (x) {
-	case CC_F6_2:	return 2;
-	case CC_F6_3:	return 3;
-	case CC_F6_4:	return 4;
-	case CC_F6_5:	return 5;
-	case CC_F6_6:	return 6;
-	case CC_F6_7:	return 7;
-	default:	return 0;
-	}
-}
-
-/*
- * Divide the clock by the divisor with protection for
- * a zero divisor.
- */
-static uint32
-divide_clock(uint32 clock, uint32 div)
-{
-	return div ? clock / div : 0;
-}
-
-
-/** calculate the speed the SI would run at given a set of clockcontrol values */
-uint32
-si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
-{
-	uint32 n1, n2, clock, m1, m2, m3, mc;
-
-	n1 = n & CN_N1_MASK;
-	n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
-
-	if (pll_type == PLL_TYPE6) {
-		if (m & CC_T6_MMASK)
-			return CC_T6_M1;
-		else
-			return CC_T6_M0;
-	} else if ((pll_type == PLL_TYPE1) ||
-	           (pll_type == PLL_TYPE3) ||
-	           (pll_type == PLL_TYPE4) ||
-	           (pll_type == PLL_TYPE7)) {
-		n1 = factor6(n1);
-		n2 += CC_F5_BIAS;
-	} else if (pll_type == PLL_TYPE2) {
-		n1 += CC_T2_BIAS;
-		n2 += CC_T2_BIAS;
-		ASSERT((n1 >= 2) && (n1 <= 7));
-		ASSERT((n2 >= 5) && (n2 <= 23));
-	} else if (pll_type == PLL_TYPE5) {
-		return (100000000);
-	} else
-		ASSERT(0);
-	/* PLL types 3 and 7 use BASE2 (25Mhz) */
-	if ((pll_type == PLL_TYPE3) ||
-	    (pll_type == PLL_TYPE7)) {
-		clock = CC_CLOCK_BASE2 * n1 * n2;
-	} else
-		clock = CC_CLOCK_BASE1 * n1 * n2;
-
-	if (clock == 0)
-		return 0;
-
-	m1 = m & CC_M1_MASK;
-	m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
-	m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
-	mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
-
-	if ((pll_type == PLL_TYPE1) ||
-	    (pll_type == PLL_TYPE3) ||
-	    (pll_type == PLL_TYPE4) ||
-	    (pll_type == PLL_TYPE7)) {
-		m1 = factor6(m1);
-		if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
-			m2 += CC_F5_BIAS;
-		else
-			m2 = factor6(m2);
-		m3 = factor6(m3);
-
-		switch (mc) {
-		case CC_MC_BYPASS:	return (clock);
-		case CC_MC_M1:		return divide_clock(clock, m1);
-		case CC_MC_M1M2:	return divide_clock(clock, m1 * m2);
-		case CC_MC_M1M2M3:	return divide_clock(clock, m1 * m2 * m3);
-		case CC_MC_M1M3:	return divide_clock(clock, m1 * m3);
-		default:		return (0);
-		}
-	} else {
-		ASSERT(pll_type == PLL_TYPE2);
-
-		m1 += CC_T2_BIAS;
-		m2 += CC_T2M2_BIAS;
-		m3 += CC_T2_BIAS;
-		ASSERT((m1 >= 2) && (m1 <= 7));
-		ASSERT((m2 >= 3) && (m2 <= 10));
-		ASSERT((m3 >= 2) && (m3 <= 7));
-
-		if ((mc & CC_T2MC_M1BYP) == 0)
-			clock /= m1;
-		if ((mc & CC_T2MC_M2BYP) == 0)
-			clock /= m2;
-		if ((mc & CC_T2MC_M3BYP) == 0)
-			clock /= m3;
-
-		return (clock);
-	}
-	return 0;
-}
-
-/**
- * Some chips could have multiple host interfaces, however only one will be active.
- * For a given chip. Depending pkgopt and cc_chipst return the active host interface.
- */
-uint
-si_chip_hostif(si_t *sih)
-{
-	uint hosti = 0;
-
-	switch (CHIPID(sih->chip)) {
-
-	CASE_BCM43602_CHIP:
-		hosti = CHIP_HOSTIF_PCIEMODE;
-		break;
-
-	case BCM4360_CHIP_ID:
-		/* chippkg bit-0 == 0 is PCIE only pkgs
-		 * chippkg bit-0 == 1 has both PCIE and USB cores enabled
-		 */
-		if ((sih->chippkg & 0x1) && (sih->chipst & CST4360_MODE_USB))
-			hosti = CHIP_HOSTIF_USBMODE;
-		else
-			hosti = CHIP_HOSTIF_PCIEMODE;
-
-		break;
-
-	case BCM4335_CHIP_ID:
-		/* TBD: like in 4360, do we need to check pkg? */
-		if (CST4335_CHIPMODE_USB20D(sih->chipst))
-			hosti = CHIP_HOSTIF_USBMODE;
-		else if (CST4335_CHIPMODE_SDIOD(sih->chipst))
-			hosti = CHIP_HOSTIF_SDIOMODE;
-		else
-			hosti = CHIP_HOSTIF_PCIEMODE;
-		break;
-
-	case BCM4345_CHIP_ID:
-	case BCM43454_CHIP_ID:
-		if (CST4345_CHIPMODE_USB20D(sih->chipst) || CST4345_CHIPMODE_HSIC(sih->chipst))
-			hosti = CHIP_HOSTIF_USBMODE;
-		else if (CST4345_CHIPMODE_SDIOD(sih->chipst))
-			hosti = CHIP_HOSTIF_SDIOMODE;
-		else if (CST4345_CHIPMODE_PCIE(sih->chipst))
-			hosti = CHIP_HOSTIF_PCIEMODE;
-		break;
-
-	case BCM4349_CHIP_GRPID:
-		if (CST4349_CHIPMODE_SDIOD(sih->chipst))
-			hosti = CHIP_HOSTIF_SDIOMODE;
-		else if (CST4349_CHIPMODE_PCIE(sih->chipst))
-			hosti = CHIP_HOSTIF_PCIEMODE;
-		break;
-
-	case BCM4350_CHIP_ID:
-	case BCM4354_CHIP_ID:
-	case BCM4356_CHIP_ID:
-	case BCM43556_CHIP_ID:
-	case BCM43558_CHIP_ID:
-	case BCM43566_CHIP_ID:
-	case BCM43568_CHIP_ID:
-	case BCM43569_CHIP_ID:
-	case BCM43570_CHIP_ID:
-	case BCM4358_CHIP_ID:
-		if (CST4350_CHIPMODE_USB20D(sih->chipst) ||
-		    CST4350_CHIPMODE_HSIC20D(sih->chipst) ||
-		    CST4350_CHIPMODE_USB30D(sih->chipst) ||
-		    CST4350_CHIPMODE_USB30D_WL(sih->chipst) ||
-		    CST4350_CHIPMODE_HSIC30D(sih->chipst))
-			hosti = CHIP_HOSTIF_USBMODE;
-		else if (CST4350_CHIPMODE_SDIOD(sih->chipst))
-			hosti = CHIP_HOSTIF_SDIOMODE;
-		else if (CST4350_CHIPMODE_PCIE(sih->chipst))
-			hosti = CHIP_HOSTIF_PCIEMODE;
-		break;
-
-	default:
-		break;
-	}
-
-	return hosti;
-}
-
-
-/** set chip watchdog reset timer to fire in 'ticks' */
-void
-si_watchdog(si_t *sih, uint ticks)
-{
-	uint nb, maxt;
-
-	if (PMUCTL_ENAB(sih)) {
-
-#if !defined(_CFEZ_) || defined(CFG_WL)
-		if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
-		    (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
-			si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
-			si_setcore(sih, USB20D_CORE_ID, 0);
-			si_core_disable(sih, 1);
-			si_setcore(sih, CC_CORE_ID, 0);
-		}
-#endif 
-
-			nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
-		/* The mips compiler uses the sllv instruction,
-		 * so we specially handle the 32-bit case.
-		 */
-		if (nb == 32)
-			maxt = 0xffffffff;
-		else
-			maxt = ((1 << nb) - 1);
-
-		if (ticks == 1)
-			ticks = 2;
-		else if (ticks > maxt)
-			ticks = maxt;
-
-		pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, ~0, ticks);
-	} else {
-		maxt = (1 << 28) - 1;
-		if (ticks > maxt)
-			ticks = maxt;
-
-		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
-	}
-}
-
-/** trigger watchdog reset after ms milliseconds */
-void
-si_watchdog_ms(si_t *sih, uint32 ms)
-{
-	si_watchdog(sih, wd_msticks * ms);
-}
-
-uint32 si_watchdog_msticks(void)
-{
-	return wd_msticks;
-}
-
-bool
-si_taclear(si_t *sih, bool details)
-{
-	return FALSE;
-}
-
-
-
-/** return the slow clock source - LPO, XTAL, or PCI */
-static uint
-si_slowclk_src(si_info_t *sii)
-{
-	chipcregs_t *cc;
-
-	ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
-
-	if (sii->pub.ccrev < 6) {
-		if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
-		    (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
-		     PCI_CFG_GPIO_SCS))
-			return (SCC_SS_PCI);
-		else
-			return (SCC_SS_XTAL);
-	} else if (sii->pub.ccrev < 10) {
-		cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
-		ASSERT(cc);
-		return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
-	} else	/* Insta-clock */
-		return (SCC_SS_XTAL);
-}
-
-/** return the ILP (slowclock) min or max frequency */
-static uint
-si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
-{
-	uint32 slowclk;
-	uint div;
-
-	ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
-
-	/* shouldn't be here unless we've established the chip has dynamic clk control */
-	ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
-
-	slowclk = si_slowclk_src(sii);
-	if (sii->pub.ccrev < 6) {
-		if (slowclk == SCC_SS_PCI)
-			return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
-		else
-			return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
-	} else if (sii->pub.ccrev < 10) {
-		div = 4 *
-		        (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
-		if (slowclk == SCC_SS_LPO)
-			return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
-		else if (slowclk == SCC_SS_XTAL)
-			return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
-		else if (slowclk == SCC_SS_PCI)
-			return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
-		else
-			ASSERT(0);
-	} else {
-		/* Chipc rev 10 is InstaClock */
-		div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
-		div = 4 * (div + 1);
-		return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
-	}
-	return (0);
-}
-
-static void
-si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
-{
-	chipcregs_t *cc = (chipcregs_t *)chipcregs;
-	uint slowmaxfreq, pll_delay, slowclk;
-	uint pll_on_delay, fref_sel_delay;
-
-	pll_delay = PLL_DELAY;
-
-	/* If the slow clock is not sourced by the xtal then add the xtal_on_delay
-	 * since the xtal will also be powered down by dynamic clk control logic.
-	 */
-
-	slowclk = si_slowclk_src(sii);
-	if (slowclk != SCC_SS_XTAL)
-		pll_delay += XTAL_ON_DELAY;
-
-	/* Starting with 4318 it is ILP that is used for the delays */
-	slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
-
-	pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
-	fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
-
-	W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
-	W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
-}
-
-/** initialize power control delay registers */
-void
-si_clkctl_init(si_t *sih)
-{
-	si_info_t *sii;
-	uint origidx = 0;
-	chipcregs_t *cc;
-	bool fast;
-
-	if (!CCCTL_ENAB(sih))
-		return;
-
-	sii = SI_INFO(sih);
-	fast = SI_FAST(sii);
-	if (!fast) {
-		origidx = sii->curidx;
-		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
-			return;
-	} else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
-		return;
-	ASSERT(cc != NULL);
-
-	/* set all Instaclk chip ILP to 1 MHz */
-	if (sih->ccrev >= 10)
-		SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
-		        (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
-
-	si_clkctl_setdelay(sii, (void *)(uintptr)cc);
-
-	OSL_DELAY(20000);
-
-	if (!fast)
-		si_setcoreidx(sih, origidx);
-}
-
-
-/** change logical "focus" to the gpio core for optimized access */
-void *
-si_gpiosetcore(si_t *sih)
-{
-	return (si_setcoreidx(sih, SI_CC_IDX));
-}
-
-/**
- * mask & set gpiocontrol bits.
- * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin.
- * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated
- *   to some chip-specific purpose.
- */
-uint32
-si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
-{
-	uint regoff;
-
-	regoff = 0;
-
-	/* gpios could be shared on router platforms
-	 * ignore reservation if it's high priority (e.g., test apps)
-	 */
-	if ((priority != GPIO_HI_PRIORITY) &&
-	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
-		mask = priority ? (si_gpioreservation & mask) :
-			((si_gpioreservation | mask) & ~(si_gpioreservation));
-		val &= mask;
-	}
-
-	regoff = OFFSETOF(chipcregs_t, gpiocontrol);
-	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
-}
-
-/** mask&set gpio output enable bits */
-uint32
-si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
-{
-	uint regoff;
-
-	regoff = 0;
-
-	/* gpios could be shared on router platforms
-	 * ignore reservation if it's high priority (e.g., test apps)
-	 */
-	if ((priority != GPIO_HI_PRIORITY) &&
-	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
-		mask = priority ? (si_gpioreservation & mask) :
-			((si_gpioreservation | mask) & ~(si_gpioreservation));
-		val &= mask;
-	}
-
-	regoff = OFFSETOF(chipcregs_t, gpioouten);
-	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
-}
-
-/** mask&set gpio output bits */
-uint32
-si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
-{
-	uint regoff;
-
-	regoff = 0;
-
-	/* gpios could be shared on router platforms
-	 * ignore reservation if it's high priority (e.g., test apps)
-	 */
-	if ((priority != GPIO_HI_PRIORITY) &&
-	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
-		mask = priority ? (si_gpioreservation & mask) :
-			((si_gpioreservation | mask) & ~(si_gpioreservation));
-		val &= mask;
-	}
-
-	regoff = OFFSETOF(chipcregs_t, gpioout);
-	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
-}
-
-/** reserve one gpio */
-uint32
-si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
-{
-	/* only cores on SI_BUS share GPIO's and only applcation users need to
-	 * reserve/release GPIO
-	 */
-	if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
-		ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
-		return 0xffffffff;
-	}
-	/* make sure only one bit is set */
-	if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
-		ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
-		return 0xffffffff;
-	}
-
-	/* already reserved */
-	if (si_gpioreservation & gpio_bitmask)
-		return 0xffffffff;
-	/* set reservation */
-	si_gpioreservation |= gpio_bitmask;
-
-	return si_gpioreservation;
-}
-
-/**
- * release one gpio.
- *
- * releasing the gpio doesn't change the current value on the GPIO last write value
- * persists till someone overwrites it.
- */
-uint32
-si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
-{
-	/* only cores on SI_BUS share GPIO's and only applcation users need to
-	 * reserve/release GPIO
-	 */
-	if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
-		ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
-		return 0xffffffff;
-	}
-	/* make sure only one bit is set */
-	if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
-		ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
-		return 0xffffffff;
-	}
-
-	/* already released */
-	if (!(si_gpioreservation & gpio_bitmask))
-		return 0xffffffff;
-
-	/* clear reservation */
-	si_gpioreservation &= ~gpio_bitmask;
-
-	return si_gpioreservation;
-}
-
-/* return the current gpioin register value */
-uint32
-si_gpioin(si_t *sih)
-{
-	uint regoff;
-
-	regoff = OFFSETOF(chipcregs_t, gpioin);
-	return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
-}
-
-/* mask&set gpio interrupt polarity bits */
-uint32
-si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
-{
-	uint regoff;
-
-	/* gpios could be shared on router platforms */
-	if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
-		mask = priority ? (si_gpioreservation & mask) :
-			((si_gpioreservation | mask) & ~(si_gpioreservation));
-		val &= mask;
-	}
-
-	regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
-	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
-}
-
-/* mask&set gpio interrupt mask bits */
-uint32
-si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
-{
-	uint regoff;
-
-	/* gpios could be shared on router platforms */
-	if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
-		mask = priority ? (si_gpioreservation & mask) :
-			((si_gpioreservation | mask) & ~(si_gpioreservation));
-		val &= mask;
-	}
-
-	regoff = OFFSETOF(chipcregs_t, gpiointmask);
-	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
-}
-
-/* assign the gpio to an led */
-uint32
-si_gpioled(si_t *sih, uint32 mask, uint32 val)
-{
-	if (sih->ccrev < 16)
-		return 0xffffffff;
-
-	/* gpio led powersave reg */
-	return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
-}
-
-/* mask&set gpio timer val */
-uint32
-si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
-{
-	if (sih->ccrev < 16)
-		return 0xffffffff;
-
-	return (si_corereg(sih, SI_CC_IDX,
-		OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
-}
-
-uint32
-si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
-{
-	uint offs;
-
-	if (sih->ccrev < 20)
-		return 0xffffffff;
-
-	offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
-	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
-}
-
-uint32
-si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
-{
-	uint offs;
-
-	if (sih->ccrev < 11)
-		return 0xffffffff;
-
-	if (regtype == GPIO_REGEVT)
-		offs = OFFSETOF(chipcregs_t, gpioevent);
-	else if (regtype == GPIO_REGEVT_INTMSK)
-		offs = OFFSETOF(chipcregs_t, gpioeventintmask);
-	else if (regtype == GPIO_REGEVT_INTPOL)
-		offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
-	else
-		return 0xffffffff;
-
-	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
-}
-
-uint32
-si_gpio_int_enable(si_t *sih, bool enable)
-{
-	uint offs;
-
-	if (sih->ccrev < 11)
-		return 0xffffffff;
-
-	offs = OFFSETOF(chipcregs_t, intmask);
-	return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
-}
-
-/** Return the size of the specified SYSMEM bank */
-static uint
-sysmem_banksize(si_info_t *sii, sysmemregs_t *regs, uint8 idx, uint8 mem_type)
-{
-	uint banksize, bankinfo;
-	uint bankidx = idx | (mem_type << SYSMEM_BANKIDX_MEMTYPE_SHIFT);
-
-	ASSERT(mem_type <= SYSMEM_MEMTYPE_DEVRAM);
-
-	W_REG(sii->osh, &regs->bankidx, bankidx);
-	bankinfo = R_REG(sii->osh, &regs->bankinfo);
-	banksize = SYSMEM_BANKINFO_SZBASE * ((bankinfo & SYSMEM_BANKINFO_SZMASK) + 1);
-	return banksize;
-}
-
-/** Return the RAM size of the SYSMEM core */
-uint32
-si_sysmem_size(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-
-	sysmemregs_t *regs;
-	bool wasup;
-	uint32 coreinfo;
-	uint memsize = 0;
-	uint8 i;
-	uint nb;
-
-	/* Block ints and save current core */
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	/* Switch to SYSMEM core */
-	if (!(regs = si_setcore(sih, SYSMEM_CORE_ID, 0)))
-		goto done;
-
-	/* Get info for determining size */
-	if (!(wasup = si_iscoreup(sih)))
-		si_core_reset(sih, 0, 0);
-	coreinfo = R_REG(sii->osh, &regs->coreinfo);
-
-	nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
-	for (i = 0; i < nb; i++)
-		memsize += sysmem_banksize(sii, regs, i, SYSMEM_MEMTYPE_RAM);
-
-	si_setcoreidx(sih, origidx);
-
-done:
-	INTR_RESTORE(sii, intr_val);
-
-	return memsize;
-}
-
-/** Return the size of the specified SOCRAM bank */
-static uint
-socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
-{
-	uint banksize, bankinfo;
-	uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
-
-	ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
-
-	W_REG(sii->osh, &regs->bankidx, bankidx);
-	bankinfo = R_REG(sii->osh, &regs->bankinfo);
-	banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
-	return banksize;
-}
-
-void si_socram_set_bankpda(si_t *sih, uint32 bankidx, uint32 bankpda)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-	sbsocramregs_t *regs;
-	bool wasup;
-	uint corerev;
-
-	/* Block ints and save current core */
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	/* Switch to SOCRAM core */
-	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
-		goto done;
-
-	if (!(wasup = si_iscoreup(sih)))
-		si_core_reset(sih, 0, 0);
-
-	corerev = si_corerev(sih);
-	if (corerev >= 16) {
-		W_REG(sii->osh, &regs->bankidx, bankidx);
-		W_REG(sii->osh, &regs->bankpda, bankpda);
-	}
-
-	/* Return to previous state and core */
-	if (!wasup)
-		si_core_disable(sih, 0);
-	si_setcoreidx(sih, origidx);
-
-done:
-	INTR_RESTORE(sii, intr_val);
-}
-
-void
-si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-	sbsocramregs_t *regs;
-	bool wasup;
-	uint corerev;
-
-	/* Block ints and save current core */
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	if (!set)
-		*enable = *protect = *remap = 0;
-
-	/* Switch to SOCRAM core */
-	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
-		goto done;
-
-	/* Get info for determining size */
-	if (!(wasup = si_iscoreup(sih)))
-		si_core_reset(sih, 0, 0);
-
-	corerev = si_corerev(sih);
-	if (corerev >= 10) {
-		uint32 extcinfo;
-		uint8 nb;
-		uint8 i;
-		uint32 bankidx, bankinfo;
-
-		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
-		nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
-		for (i = 0; i < nb; i++) {
-			bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
-			W_REG(sii->osh, &regs->bankidx, bankidx);
-			bankinfo = R_REG(sii->osh, &regs->bankinfo);
-			if (set) {
-				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
-				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
-				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK;
-				if (*enable) {
-					bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
-					if (*protect)
-						bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
-					if ((corerev >= 16) && *remap)
-						bankinfo |=
-							(1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT);
-				}
-				W_REG(sii->osh, &regs->bankinfo, bankinfo);
-			}
-			else if (i == 0) {
-				if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
-					*enable = 1;
-					if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
-						*protect = 1;
-					if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK)
-						*remap = 1;
-				}
-			}
-		}
-	}
-
-	/* Return to previous state and core */
-	if (!wasup)
-		si_core_disable(sih, 0);
-	si_setcoreidx(sih, origidx);
-
-done:
-	INTR_RESTORE(sii, intr_val);
-}
-
-bool
-si_socdevram_remap_isenb(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-	sbsocramregs_t *regs;
-	bool wasup, remap = FALSE;
-	uint corerev;
-	uint32 extcinfo;
-	uint8 nb;
-	uint8 i;
-	uint32 bankidx, bankinfo;
-
-	/* Block ints and save current core */
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	/* Switch to SOCRAM core */
-	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
-		goto done;
-
-	/* Get info for determining size */
-	if (!(wasup = si_iscoreup(sih)))
-		si_core_reset(sih, 0, 0);
-
-	corerev = si_corerev(sih);
-	if (corerev >= 16) {
-		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
-		nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
-		for (i = 0; i < nb; i++) {
-			bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
-			W_REG(sii->osh, &regs->bankidx, bankidx);
-			bankinfo = R_REG(sii->osh, &regs->bankinfo);
-			if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
-				remap = TRUE;
-				break;
-			}
-		}
-	}
-
-	/* Return to previous state and core */
-	if (!wasup)
-		si_core_disable(sih, 0);
-	si_setcoreidx(sih, origidx);
-
-done:
-	INTR_RESTORE(sii, intr_val);
-	return remap;
-}
-
-bool
-si_socdevram_pkg(si_t *sih)
-{
-	if (si_socdevram_size(sih) > 0)
-		return TRUE;
-	else
-		return FALSE;
-}
-
-uint32
-si_socdevram_size(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-	uint32 memsize = 0;
-	sbsocramregs_t *regs;
-	bool wasup;
-	uint corerev;
-
-	/* Block ints and save current core */
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	/* Switch to SOCRAM core */
-	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
-		goto done;
-
-	/* Get info for determining size */
-	if (!(wasup = si_iscoreup(sih)))
-		si_core_reset(sih, 0, 0);
-
-	corerev = si_corerev(sih);
-	if (corerev >= 10) {
-		uint32 extcinfo;
-		uint8 nb;
-		uint8 i;
-
-		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
-		nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
-		for (i = 0; i < nb; i++)
-			memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
-	}
-
-	/* Return to previous state and core */
-	if (!wasup)
-		si_core_disable(sih, 0);
-	si_setcoreidx(sih, origidx);
-
-done:
-	INTR_RESTORE(sii, intr_val);
-
-	return memsize;
-}
-
-uint32
-si_socdevram_remap_size(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-	uint32 memsize = 0, banksz;
-	sbsocramregs_t *regs;
-	bool wasup;
-	uint corerev;
-	uint32 extcinfo;
-	uint8 nb;
-	uint8 i;
-	uint32 bankidx, bankinfo;
-
-	/* Block ints and save current core */
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	/* Switch to SOCRAM core */
-	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
-		goto done;
-
-	/* Get info for determining size */
-	if (!(wasup = si_iscoreup(sih)))
-		si_core_reset(sih, 0, 0);
-
-	corerev = si_corerev(sih);
-	if (corerev >= 16) {
-		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
-		nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
-
-		/*
-		 * FIX: A0 Issue: Max addressable is 512KB, instead 640KB
-		 * Only four banks are accessible to ARM
-		 */
-		if ((corerev == 16) && (nb == 5))
-			nb = 4;
-
-		for (i = 0; i < nb; i++) {
-			bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
-			W_REG(sii->osh, &regs->bankidx, bankidx);
-			bankinfo = R_REG(sii->osh, &regs->bankinfo);
-			if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
-				banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
-				memsize += banksz;
-			} else {
-				/* Account only consecutive banks for now */
-				break;
-			}
-		}
-	}
-
-	/* Return to previous state and core */
-	if (!wasup)
-		si_core_disable(sih, 0);
-	si_setcoreidx(sih, origidx);
-
-done:
-	INTR_RESTORE(sii, intr_val);
-
-	return memsize;
-}
-
-/** Return the RAM size of the SOCRAM core */
-uint32
-si_socram_size(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-
-	sbsocramregs_t *regs;
-	bool wasup;
-	uint corerev;
-	uint32 coreinfo;
-	uint memsize = 0;
-
-	/* Block ints and save current core */
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	/* Switch to SOCRAM core */
-	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
-		goto done;
-
-	/* Get info for determining size */
-	if (!(wasup = si_iscoreup(sih)))
-		si_core_reset(sih, 0, 0);
-	corerev = si_corerev(sih);
-	coreinfo = R_REG(sii->osh, &regs->coreinfo);
-
-	/* Calculate size from coreinfo based on rev */
-	if (corerev == 0)
-		memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
-	else if (corerev < 3) {
-		memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
-		memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
-	} else if ((corerev <= 7) || (corerev == 12)) {
-		uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
-		uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
-		uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
-		if (lss != 0)
-			nb --;
-		memsize = nb * (1 << (bsz + SR_BSZ_BASE));
-		if (lss != 0)
-			memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
-	} else {
-		uint8 i;
-		uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
-		for (i = 0; i < nb; i++)
-			memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
-	}
-
-	/* Return to previous state and core */
-	if (!wasup)
-		si_core_disable(sih, 0);
-	si_setcoreidx(sih, origidx);
-
-done:
-	INTR_RESTORE(sii, intr_val);
-
-	return memsize;
-}
-
-
-/** Return the TCM-RAM size of the ARMCR4 core. */
-uint32
-si_tcm_size(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-	uint8 *regs;
-	bool wasup;
-	uint32 corecap;
-	uint memsize = 0;
-	uint32 nab = 0;
-	uint32 nbb = 0;
-	uint32 totb = 0;
-	uint32 bxinfo = 0;
-	uint32 idx = 0;
-	uint32 *arm_cap_reg;
-	uint32 *arm_bidx;
-	uint32 *arm_binfo;
-
-	/* Block ints and save current core */
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	/* Switch to CR4 core */
-	if (!(regs = si_setcore(sih, ARMCR4_CORE_ID, 0)))
-		goto done;
-
-	/* Get info for determining size. If in reset, come out of reset,
-	 * but remain in halt
-	 */
-	if (!(wasup = si_iscoreup(sih)))
-		si_core_reset(sih, SICF_CPUHALT, SICF_CPUHALT);
-
-	arm_cap_reg = (uint32 *)(regs + SI_CR4_CAP);
-	corecap = R_REG(sii->osh, arm_cap_reg);
-
-	nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
-	nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
-	totb = nab + nbb;
-
-	arm_bidx = (uint32 *)(regs + SI_CR4_BANKIDX);
-	arm_binfo = (uint32 *)(regs + SI_CR4_BANKINFO);
-	for (idx = 0; idx < totb; idx++) {
-		W_REG(sii->osh, arm_bidx, idx);
-
-		bxinfo = R_REG(sii->osh, arm_binfo);
-		memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
-	}
-
-	/* Return to previous state and core */
-	if (!wasup)
-		si_core_disable(sih, 0);
-	si_setcoreidx(sih, origidx);
-
-done:
-	INTR_RESTORE(sii, intr_val);
-
-	return memsize;
-}
-
-bool
-si_has_flops(si_t *sih)
-{
-	uint origidx, cr4_rev;
-
-	/* Find out CR4 core revision */
-	origidx = si_coreidx(sih);
-	if (si_setcore(sih, ARMCR4_CORE_ID, 0)) {
-		cr4_rev = si_corerev(sih);
-		si_setcoreidx(sih, origidx);
-
-		if (cr4_rev == 1 || cr4_rev >= 3)
-			return TRUE;
-	}
-	return FALSE;
-}
-
-uint32
-si_socram_srmem_size(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-
-	sbsocramregs_t *regs;
-	bool wasup;
-	uint corerev;
-	uint32 coreinfo;
-	uint memsize = 0;
-
-	if ((CHIPID(sih->chip) == BCM4334_CHIP_ID) && (CHIPREV(sih->chiprev) < 2)) {
-		return (32 * 1024);
-	}
-
-	if (CHIPID(sih->chip) == BCM43430_CHIP_ID) {
-		return (64 * 1024);
-	}
-
-	/* Block ints and save current core */
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(sih);
-
-	/* Switch to SOCRAM core */
-	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
-		goto done;
-
-	/* Get info for determining size */
-	if (!(wasup = si_iscoreup(sih)))
-		si_core_reset(sih, 0, 0);
-	corerev = si_corerev(sih);
-	coreinfo = R_REG(sii->osh, &regs->coreinfo);
-
-	/* Calculate size from coreinfo based on rev */
-	if (corerev >= 16) {
-		uint8 i;
-		uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
-		for (i = 0; i < nb; i++) {
-			W_REG(sii->osh, &regs->bankidx, i);
-			if (R_REG(sii->osh, &regs->bankinfo) & SOCRAM_BANKINFO_RETNTRAM_MASK)
-				memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
-		}
-	}
-
-	/* Return to previous state and core */
-	if (!wasup)
-		si_core_disable(sih, 0);
-	si_setcoreidx(sih, origidx);
-
-done:
-	INTR_RESTORE(sii, intr_val);
-
-	return memsize;
-}
-
-
-#if !defined(_CFEZ_) || defined(CFG_WL)
-void
-si_btcgpiowar(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	uint origidx;
-	uint intr_val = 0;
-	chipcregs_t *cc;
-
-	/* Make sure that there is ChipCommon core present &&
-	 * UART_TX is strapped to 1
-	 */
-	if (!(sih->cccaps & CC_CAP_UARTGPIO))
-		return;
-
-	/* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
-	INTR_OFF(sii, intr_val);
-
-	origidx = si_coreidx(sih);
-
-	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
-	ASSERT(cc != NULL);
-
-	W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
-
-	/* restore the original index */
-	si_setcoreidx(sih, origidx);
-
-	INTR_RESTORE(sii, intr_val);
-}
-
-void
-si_chipcontrl_btshd0_4331(si_t *sih, bool on)
-{
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-	chipcregs_t *cc;
-	uint origidx;
-	uint32 val;
-	uint intr_val = 0;
-
-	INTR_OFF(sii, intr_val);
-
-	origidx = si_coreidx(sih);
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-
-	val = R_REG(sii->osh, &cc->chipcontrol);
-
-	/* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */
-	if (on) {
-		/* Enable bt_shd0 on gpio4: */
-		val |= (CCTRL4331_BT_SHD0_ON_GPIO4);
-		W_REG(sii->osh, &cc->chipcontrol, val);
-	} else {
-		val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4);
-		W_REG(sii->osh, &cc->chipcontrol, val);
-	}
-
-	/* restore the original index */
-	si_setcoreidx(sih, origidx);
-
-	INTR_RESTORE(sii, intr_val);
-}
-
-void
-si_chipcontrl_restore(si_t *sih, uint32 val)
-{
-	si_info_t *sii = SI_INFO(sih);
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-	W_REG(sii->osh, &cc->chipcontrol, val);
-	si_setcoreidx(sih, origidx);
-}
-
-uint32
-si_chipcontrl_read(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-	uint32 val;
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return -1;
-	}
-	val = R_REG(sii->osh, &cc->chipcontrol);
-	si_setcoreidx(sih, origidx);
-	return val;
-}
-
-void
-si_chipcontrl_epa4331(si_t *sih, bool on)
-{
-	si_info_t *sii = SI_INFO(sih);
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-	uint32 val;
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-	val = R_REG(sii->osh, &cc->chipcontrol);
-
-	if (on) {
-		if (sih->chippkg == 9 || sih->chippkg == 0xb) {
-			val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
-			/* Ext PA Controls for 4331 12x9 Package */
-			W_REG(sii->osh, &cc->chipcontrol, val);
-		} else {
-			/* Ext PA Controls for 4331 12x12 Package */
-			if (CHIPREV(sih->chiprev) > 0) {
-				W_REG(sii->osh, &cc->chipcontrol, val |
-				      (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2));
-			} else {
-				W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN));
-			}
-		}
-	} else {
-		val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5);
-		W_REG(sii->osh, &cc->chipcontrol, val);
-	}
-
-	si_setcoreidx(sih, origidx);
-}
-
-/** switch muxed pins, on: SROM, off: FEMCTRL. Called for a family of ac chips, not just 4360. */
-void
-si_chipcontrl_srom4360(si_t *sih, bool on)
-{
-	si_info_t *sii = SI_INFO(sih);
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-	uint32 val;
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-	val = R_REG(sii->osh, &cc->chipcontrol);
-
-	if (on) {
-		val &= ~(CCTRL4360_SECI_MODE |
-			CCTRL4360_BTSWCTRL_MODE |
-			CCTRL4360_EXTRA_FEMCTRL_MODE |
-			CCTRL4360_BT_LGCY_MODE |
-			CCTRL4360_CORE2FEMCTRL4_ON);
-
-		W_REG(sii->osh, &cc->chipcontrol, val);
-	} else {
-	}
-
-	si_setcoreidx(sih, origidx);
-}
-
-void
-si_clk_srom4365(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-	uint32 val;
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-	val = R_REG(sii->osh, &cc->clkdiv2);
-	W_REG(sii->osh, &cc->clkdiv2, ((val&~0xf) | 0x4));
-
-	si_setcoreidx(sih, origidx);
-}
-
-void
-si_d11rsdb_core1_alt_reg_clk_dis(si_t *sih)
-{
-#if defined(WLRSDB) && !defined(WLRSDB_DISABLED)
-	ai_d11rsdb_core1_alt_reg_clk_dis(sih);
-#endif /* defined(WLRSDB) && !defined(WLRSDB_DISABLED) */
-}
-
-void
-si_d11rsdb_core1_alt_reg_clk_en(si_t *sih)
-{
-#if defined(WLRSDB) && !defined(WLRSDB_DISABLED)
-	ai_d11rsdb_core1_alt_reg_clk_en(sih);
-#endif /* defined(WLRSDB) && !defined(WLRSDB_DISABLED) */
-}
-
-void
-si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl)
-{
-	si_info_t *sii;
-	chipcregs_t *cc;
-	uint origidx;
-	uint32 val;
-	bool sel_chip;
-
-	sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
-		(CHIPID(sih->chip) == BCM43431_CHIP_ID);
-	sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb));
-
-	if (!sel_chip)
-		return;
-
-	sii = SI_INFO(sih);
-	origidx = si_coreidx(sih);
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-
-	val = R_REG(sii->osh, &cc->chipcontrol);
-
-	if (enter_wowl) {
-		val |= CCTRL4331_EXTPA_EN;
-		W_REG(sii->osh, &cc->chipcontrol, val);
-	} else {
-		val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
-		W_REG(sii->osh, &cc->chipcontrol, val);
-	}
-	si_setcoreidx(sih, origidx);
-}
-#endif 
-
-uint
-si_pll_reset(si_t *sih)
-{
-	uint err = 0;
-
-	return (err);
-}
-
-/** Enable BT-COEX & Ex-PA for 4313 */
-void
-si_epa_4313war(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-
-	/* EPA Fix */
-	W_REG(sii->osh, &cc->gpiocontrol,
-	R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
-
-	si_setcoreidx(sih, origidx);
-}
-
-void
-si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
-{
-}
-
-void
-si_pmu_avb_clk_set(si_t *sih, osl_t *osh, bool set_flag)
-{
-}
-
-/** Re-enable synth_pwrsw resource in min_res_mask for 4313 */
-void
-si_pmu_synth_pwrsw_4313_war(si_t *sih)
-{
-}
-
-/** WL/BT control for 4313 btcombo boards >= P250 */
-void
-si_btcombo_p250_4313_war(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-	W_REG(sii->osh, &cc->gpiocontrol,
-		R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK);
-
-	W_REG(sii->osh, &cc->gpioouten,
-		R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK);
-
-	si_setcoreidx(sih, origidx);
-}
-void
-si_btc_enable_chipcontrol(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-
-	/* BT fix */
-	W_REG(sii->osh, &cc->chipcontrol,
-		R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
-
-	si_setcoreidx(sih, origidx);
-}
-void
-si_btcombo_43228_war(si_t *sih)
-{
-	si_info_t *sii = SI_INFO(sih);
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-
-	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
-		SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
-		return;
-	}
-
-	W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK);
-	W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK);
-
-	si_setcoreidx(sih, origidx);
-}
-
-/** check if the device is removed */
-bool
-si_deviceremoved(si_t *sih)
-{
-	uint32 w;
-
-	switch (BUSTYPE(sih->bustype)) {
-	case PCI_BUS:
-		ASSERT(SI_INFO(sih)->osh != NULL);
-		w = OSL_PCI_READ_CONFIG(SI_INFO(sih)->osh, PCI_CFG_VID, sizeof(uint32));
-		if ((w & 0xFFFF) != VENDOR_BROADCOM)
-			return TRUE;
-		break;
-	}
-	return FALSE;
-}
-
-bool
-si_is_sprom_available(si_t *sih)
-{
-	if (sih->ccrev >= 31) {
-		si_info_t *sii;
-		uint origidx;
-		chipcregs_t *cc;
-		uint32 sromctrl;
-
-		if ((sih->cccaps & CC_CAP_SROM) == 0)
-			return FALSE;
-
-		sii = SI_INFO(sih);
-		origidx = sii->curidx;
-		cc = si_setcoreidx(sih, SI_CC_IDX);
-		ASSERT(cc);
-		sromctrl = R_REG(sii->osh, &cc->sromcontrol);
-		si_setcoreidx(sih, origidx);
-		return (sromctrl & SRC_PRESENT);
-	}
-
-	switch (CHIPID(sih->chip)) {
-	case BCM4312_CHIP_ID:
-		return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
-	case BCM4325_CHIP_ID:
-		return (sih->chipst & CST4325_SPROM_SEL) != 0;
-	case BCM4322_CHIP_ID:	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
-	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
-	case BCM4342_CHIP_ID: {
-		uint32 spromotp;
-		spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
-		        CST4322_SPROM_OTP_SEL_SHIFT;
-		return (spromotp & CST4322_SPROM_PRESENT) != 0;
-	}
-	case BCM4329_CHIP_ID:
-		return (sih->chipst & CST4329_SPROM_SEL) != 0;
-	case BCM4315_CHIP_ID:
-		return (sih->chipst & CST4315_SPROM_SEL) != 0;
-	case BCM4319_CHIP_ID:
-		return (sih->chipst & CST4319_SPROM_SEL) != 0;
-	case BCM4336_CHIP_ID:
-	case BCM43362_CHIP_ID:
-		return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
-	case BCM4330_CHIP_ID:
-		return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
-	case BCM4313_CHIP_ID:
-		return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
-	case BCM4331_CHIP_ID:
-	case BCM43431_CHIP_ID:
-		return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
-	case BCM43239_CHIP_ID:
-		return ((sih->chipst & CST43239_SPROM_MASK) &&
-			!(sih->chipst & CST43239_SFLASH_MASK));
-	case BCM4324_CHIP_ID:
-	case BCM43242_CHIP_ID:
-		return ((sih->chipst & CST4324_SPROM_MASK) &&
-			!(sih->chipst & CST4324_SFLASH_MASK));
-	case BCM4335_CHIP_ID:
-	case BCM4345_CHIP_ID:
-	case BCM43454_CHIP_ID:
-		return ((sih->chipst & CST4335_SPROM_MASK) &&
-			!(sih->chipst & CST4335_SFLASH_MASK));
-	case BCM4349_CHIP_GRPID:
-		return (sih->chipst & CST4349_SPROM_PRESENT) != 0;
-		break;
-	case BCM4350_CHIP_ID:
-	case BCM4354_CHIP_ID:
-	case BCM4356_CHIP_ID:
-	case BCM43556_CHIP_ID:
-	case BCM43558_CHIP_ID:
-	case BCM43566_CHIP_ID:
-	case BCM43568_CHIP_ID:
-	case BCM43569_CHIP_ID:
-	case BCM43570_CHIP_ID:
-	case BCM4358_CHIP_ID:
-		return (sih->chipst & CST4350_SPROM_PRESENT) != 0;
-	CASE_BCM43602_CHIP:
-		return (sih->chipst & CST43602_SPROM_PRESENT) != 0;
-	case BCM43131_CHIP_ID:
-	case BCM43217_CHIP_ID:
-	case BCM43227_CHIP_ID:
-	case BCM43228_CHIP_ID:
-	case BCM43428_CHIP_ID:
-		return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
-	default:
-		return TRUE;
-	}
-}
-
-
-uint32 si_get_sromctl(si_t *sih)
-{
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-	uint32 sromctl;
-	osl_t *osh = si_osh(sih);
-
-	cc = si_setcoreidx(sih, SI_CC_IDX);
-	ASSERT((uintptr)cc);
-
-	sromctl = R_REG(osh, &cc->sromcontrol);
-
-	/* return to the original core */
-	si_setcoreidx(sih, origidx);
-	return sromctl;
-}
-
-int si_set_sromctl(si_t *sih, uint32 value)
-{
-	chipcregs_t *cc;
-	uint origidx = si_coreidx(sih);
-	osl_t *osh = si_osh(sih);
-	int ret = BCME_OK;
-
-	cc = si_setcoreidx(sih, SI_CC_IDX);
-	ASSERT((uintptr)cc);
-
-	/* get chipcommon rev */
-	if (si_corerev(sih) >= 32) {
-		/* SpromCtrl is only accessible if CoreCapabilities.SpromSupported and
-		 * SpromPresent is 1.
-		 */
-		if ((R_REG(osh, &cc->capabilities) & CC_CAP_SROM) != 0 &&
-		     (R_REG(osh, &cc->sromcontrol) & SRC_PRESENT)) {
-			W_REG(osh, &cc->sromcontrol, value);
-		} else {
-			ret = BCME_NODEVICE;
-		}
-	} else {
-		ret = BCME_UNSUPPORTED;
-	}
-
-	/* return to the original core */
-	si_setcoreidx(sih, origidx);
-
-	return ret;
-}
-
-uint
-si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val)
-{
-	uint origidx, intr_val = 0;
-	uint ret_val;
-	si_info_t *sii = SI_INFO(sih);
-	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
-
-	origidx = si_coreidx(sih);
-
-	INTR_OFF(sii, intr_val);
-	si_setcoreidx(sih, coreidx);
-
-	ret_val = si_wrapperreg(sih, offset, mask, val);
-
-	/* return to the original core */
-	si_setcoreidx(sih, origidx);
-	INTR_RESTORE(sii, intr_val);
-	return ret_val;
-}
-
-
-/* cleanup the timer from the host when ARM is been halted
- * without a chance for ARM cleanup its resources
- * If left not cleanup, Intr from a software timer can still
- * request HT clk when ARM is halted.
- */
-uint32
-si_pmu_res_req_timer_clr(si_t *sih)
-{
-	uint32 mask;
-
-	mask = PRRT_REQ_ACTIVE | PRRT_INTEN | PRRT_HT_REQ;
-	if (CHIPID(sih->chip) != BCM4328_CHIP_ID)
-		mask <<= 14;
-	/* clear mask bits */
-	pmu_corereg(sih, SI_CC_IDX, res_req_timer, mask, 0);
-	/* readback to ensure write completes */
-	return pmu_corereg(sih, SI_CC_IDX, res_req_timer, 0, 0);
-}
-
-/** turn on/off rfldo */
-void
-si_pmu_rfldo(si_t *sih, bool on)
-{
-}
-
-
-#ifdef SURVIVE_PERST_ENAB
-static uint32
-si_pcie_survive_perst(si_t *sih, uint32 mask, uint32 val)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-
-	if (!PCIE(sii))
-		return (0);
-
-	return pcie_survive_perst(sii->pch, mask, val);
-}
-
-static void
-si_watchdog_reset(si_t *sih)
-{
-	uint32 i;
-
-	/* issue a watchdog reset */
-	pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, 2, 2);
-	/* do busy wait for 20ms */
-	for (i = 0; i < 2000; i++) {
-		OSL_DELAY(10);
-	}
-}
-#endif /* SURVIVE_PERST_ENAB */
-
-void
-si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 sperst_val)
-{
-#ifdef SURVIVE_PERST_ENAB
-	if (BUSTYPE(sih->bustype) != PCI_BUS)
-		  return;
-
-	if ((CHIPID(sih->chip) != BCM4360_CHIP_ID && CHIPID(sih->chip) != BCM4352_CHIP_ID) ||
-	    (CHIPREV(sih->chiprev) >= 4))
-		return;
-
-	if (reset) {
-		si_info_t *sii = SI_INFO(sih);
-		uint32 bar0win, bar0win_after;
-
-		/* save the bar0win */
-		bar0win = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
-
-		si_watchdog_reset(sih);
-
-		bar0win_after = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
-		if (bar0win_after != bar0win) {
-			SI_ERROR(("%s: bar0win before %08x, bar0win after %08x\n",
-				__FUNCTION__, bar0win, bar0win_after));
-			OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), bar0win);
-		}
-	}
-	if (sperst_mask) {
-		/* enable survive perst */
-		si_pcie_survive_perst(sih, sperst_mask, sperst_val);
-	}
-#endif /* SURVIVE_PERST_ENAB */
-}
-
-void
-si_pcie_ltr_war(si_t *sih)
-{
-}
-
-void
-si_pcie_hw_LTR_war(si_t *sih)
-{
-}
-
-void
-si_pciedev_reg_pm_clk_period(si_t *sih)
-{
-}
-
-void
-si_pciedev_crwlpciegen2(si_t *sih)
-{
-}
-
-void
-si_pcie_prep_D3(si_t *sih, bool enter_D3)
-{
-}
-
-
-
-void
-si_pll_sr_reinit(si_t *sih)
-{
-}
-
-void
-si_pll_closeloop(si_t *sih)
-{
-#if defined(SAVERESTORE)
-	uint32 data;
-
-	/* disable PLL open loop operation */
-	switch (CHIPID(sih->chip)) {
-#ifdef SAVERESTORE
-		case BCM43430_CHIP_ID:
-			if (SR_ENAB() && sr_isenab(sih)) {
-				/* read back the pll openloop state */
-				data = si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL8, 0, 0);
-				/* current mode is openloop (possible POR) */
-				if ((data & PMU1_PLLCTL8_OPENLOOP_MASK) != 0) {
-					si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL8,
-						PMU1_PLLCTL8_OPENLOOP_MASK, 0);
-					si_pmu_pllupd(sih);
-				}
-			}
-			break;
-#endif /* SAVERESTORE */
-		default:
-			/* any unsupported chip bail */
-			return;
-	}
-#endif 
-}
diff --git a/drivers/net/wireless/bcmdhd/siutils_priv.h b/drivers/net/wireless/bcmdhd/siutils_priv.h
deleted file mode 100644
index 090d791..0000000
--- a/drivers/net/wireless/bcmdhd/siutils_priv.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Include file private to the SOC Interconnect support files.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: siutils_priv.h 520760 2014-12-15 00:54:16Z $
- */
-
-#ifndef	_siutils_priv_h_
-#define	_siutils_priv_h_
-
-#define	SI_ERROR(args)
-
-#define	SI_MSG(args)
-
-#ifdef BCMDBG_SI
-#define	SI_VMSG(args)	printf args
-#else
-#define	SI_VMSG(args)
-#endif
-
-#define	IS_SIM(chippkg)	((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
-
-typedef uint32 (*si_intrsoff_t)(void *intr_arg);
-typedef void (*si_intrsrestore_t)(void *intr_arg, uint32 arg);
-typedef bool (*si_intrsenabled_t)(void *intr_arg);
-
-
-#define SI_GPIO_MAX		16
-
-typedef struct gci_gpio_item {
-	void			*arg;
-	uint8			gci_gpio;
-	uint8			status;
-	gci_gpio_handler_t	handler;
-	struct gci_gpio_item	*next;
-} gci_gpio_item_t;
-
-
-typedef struct si_cores_info {
-	void	*regs[SI_MAXCORES];	/* other regs va */
-
-	uint	coreid[SI_MAXCORES];	/* id of each core */
-	uint32	coresba[SI_MAXCORES];	/* backplane address of each core */
-	void	*regs2[SI_MAXCORES];	/* va of each core second register set (usbh20) */
-	uint32	coresba2[SI_MAXCORES];	/* address of each core second register set (usbh20) */
-	uint32	coresba_size[SI_MAXCORES]; /* backplane address space size */
-	uint32	coresba2_size[SI_MAXCORES]; /* second address space size */
-
-	void	*wrappers[SI_MAXCORES];	/* other cores wrapper va */
-	uint32	wrapba[SI_MAXCORES];	/* address of controlling wrapper */
-
-	void	*wrappers2[SI_MAXCORES];	/* other cores wrapper va */
-	uint32	wrapba2[SI_MAXCORES];	/* address of controlling wrapper */
-
-	uint32	cia[SI_MAXCORES];	/* erom cia entry for each core */
-	uint32	cib[SI_MAXCORES];	/* erom cia entry for each core */
-} si_cores_info_t;
-
-/* misc si info needed by some of the routines */
-typedef struct si_info {
-	struct si_pub pub;		/* back plane public state (must be first field) */
-
-	void	*osh;			/* osl os handle */
-	void	*sdh;			/* bcmsdh handle */
-
-	uint	dev_coreid;		/* the core provides driver functions */
-	void	*intr_arg;		/* interrupt callback function arg */
-	si_intrsoff_t intrsoff_fn;	/* turns chip interrupts off */
-	si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */
-	si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */
-
-	void *pch;			/* PCI/E core handle */
-
-	bool	memseg;			/* flag to toggle MEM_SEG register */
-
-	char *vars;
-	uint varsz;
-
-	void	*curmap;		/* current regs va */
-
-	uint	curidx;			/* current core index */
-	uint	numcores;		/* # discovered cores */
-
-	void	*curwrap;		/* current wrapper va */
-
-	uint32	oob_router;		/* oob router registers for axi */
-
-	void *cores_info;
-	gci_gpio_item_t	*gci_gpio_head;	/* gci gpio interrupts head */
-	uint	chipnew;		/* new chip number */
-	uint second_bar0win;		/* Backplane region */
-	uint	num_br;		/* # discovered bridges */
-	uint32	br_wrapba[SI_MAXBR];	/* address of bridge controlling wrapper */
-	uint32	xtalfreq;
-} si_info_t;
-
-
-#define	SI_INFO(sih)	((si_info_t *)(uintptr)sih)
-
-#define	GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
-		ISALIGNED((x), SI_CORE_SIZE))
-#define	GOODREGS(regs)	((regs) != NULL && ISALIGNED((uintptr)(regs), SI_CORE_SIZE))
-#define BADCOREADDR	0
-#define	GOODIDX(idx)	(((uint)idx) < SI_MAXCORES)
-#define	NOREV		-1		/* Invalid rev */
-
-#define PCI(si)		((BUSTYPE((si)->pub.bustype) == PCI_BUS) &&	\
-			 ((si)->pub.buscoretype == PCI_CORE_ID))
-
-#define PCIE_GEN1(si)	((BUSTYPE((si)->pub.bustype) == PCI_BUS) &&	\
-			 ((si)->pub.buscoretype == PCIE_CORE_ID))
-
-#define PCIE_GEN2(si)	((BUSTYPE((si)->pub.bustype) == PCI_BUS) &&	\
-			 ((si)->pub.buscoretype == PCIE2_CORE_ID))
-
-#define PCIE(si)	(PCIE_GEN1(si) || PCIE_GEN2(si))
-
-#define PCMCIA(si)	((BUSTYPE((si)->pub.bustype) == PCMCIA_BUS) && ((si)->memseg == TRUE))
-
-/* Newer chips can access PCI/PCIE and CC core without requiring to change
- * PCI BAR0 WIN
- */
-#define SI_FAST(si) (PCIE(si) || (PCI(si) && ((si)->pub.buscorerev >= 13)))
-
-#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET))
-#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET))
-
-/*
- * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
- * after core switching to avoid invalid register accesss inside ISR.
- */
-#define INTR_OFF(si, intr_val) \
-	if ((si)->intrsoff_fn && (cores_info)->coreid[(si)->curidx] == (si)->dev_coreid) {	\
-		intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
-#define INTR_RESTORE(si, intr_val) \
-	if ((si)->intrsrestore_fn && (cores_info)->coreid[(si)->curidx] == (si)->dev_coreid) {	\
-		(*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
-
-/* dynamic clock control defines */
-#define	LPOMINFREQ		25000		/* low power oscillator min */
-#define	LPOMAXFREQ		43000		/* low power oscillator max */
-#define	XTALMINFREQ		19800000	/* 20 MHz - 1% */
-#define	XTALMAXFREQ		20200000	/* 20 MHz + 1% */
-#define	PCIMINFREQ		25000000	/* 25 MHz */
-#define	PCIMAXFREQ		34000000	/* 33 MHz + fudge */
-
-#define	ILP_DIV_5MHZ		0		/* ILP = 5 MHz */
-#define	ILP_DIV_1MHZ		4		/* ILP = 1 MHz */
-
-/* Force fast clock for 4360b0 */
-#define PCI_FORCEHT(si)	\
-	(((PCIE_GEN1(si)) && (CHIPID(si->pub.chip) == BCM4311_CHIP_ID) && \
-	((CHIPREV(si->pub.chiprev) <= 1))) || \
-	((PCI(si) || PCIE_GEN1(si)) && (CHIPID(si->pub.chip) == BCM4321_CHIP_ID)) || \
-	(PCIE_GEN1(si) && (CHIPID(si->pub.chip) == BCM4716_CHIP_ID)) || \
-	(PCIE_GEN1(si) && (CHIPID(si->pub.chip) == BCM4748_CHIP_ID)))
-
-/* GPIO Based LED powersave defines */
-#define DEFAULT_GPIO_ONTIME	10		/* Default: 10% on */
-#define DEFAULT_GPIO_OFFTIME	90		/* Default: 10% on */
-
-#ifndef DEFAULT_GPIOTIMERVAL
-#define DEFAULT_GPIOTIMERVAL  ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
-#endif
-
-/* Silicon Backplane externs */
-extern void sb_scan(si_t *sih, void *regs, uint devid);
-extern uint sb_coreid(si_t *sih);
-extern uint sb_intflag(si_t *sih);
-extern uint sb_flag(si_t *sih);
-extern void sb_setint(si_t *sih, int siflag);
-extern uint sb_corevendor(si_t *sih);
-extern uint sb_corerev(si_t *sih);
-extern uint sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val);
-extern uint32 *sb_corereg_addr(si_t *sih, uint coreidx, uint regoff);
-extern bool sb_iscoreup(si_t *sih);
-extern void *sb_setcoreidx(si_t *sih, uint coreidx);
-extern uint32 sb_core_cflags(si_t *sih, uint32 mask, uint32 val);
-extern void sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val);
-extern uint32 sb_core_sflags(si_t *sih, uint32 mask, uint32 val);
-extern void sb_commit(si_t *sih);
-extern uint32 sb_base(uint32 admatch);
-extern uint32 sb_size(uint32 admatch);
-extern void sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
-extern void sb_core_disable(si_t *sih, uint32 bits);
-extern uint32 sb_addrspace(si_t *sih, uint asidx);
-extern uint32 sb_addrspacesize(si_t *sih, uint asidx);
-extern int sb_numaddrspaces(si_t *sih);
-
-extern uint32 sb_set_initiator_to(si_t *sih, uint32 to, uint idx);
-
-extern bool sb_taclear(si_t *sih, bool details);
-
-#if defined(BCMDBG_PHYDUMP)
-extern void sb_dumpregs(si_t *sih, struct bcmstrbuf *b);
-#endif 
-
-/* Wake-on-wireless-LAN (WOWL) */
-extern bool sb_pci_pmecap(si_t *sih);
-struct osl_info;
-extern bool sb_pci_fastpmecap(struct osl_info *osh);
-extern bool sb_pci_pmeclr(si_t *sih);
-extern void sb_pci_pmeen(si_t *sih);
-extern uint sb_pcie_readreg(void *sih, uint addrtype, uint offset);
-
-/* AMBA Interconnect exported externs */
-extern si_t *ai_attach(uint pcidev, osl_t *osh, void *regs, uint bustype,
-                       void *sdh, char **vars, uint *varsz);
-extern si_t *ai_kattach(osl_t *osh);
-extern void ai_scan(si_t *sih, void *regs, uint devid);
-
-extern uint ai_flag(si_t *sih);
-extern uint ai_flag_alt(si_t *sih);
-extern void ai_setint(si_t *sih, int siflag);
-extern uint ai_coreidx(si_t *sih);
-extern uint ai_corevendor(si_t *sih);
-extern uint ai_corerev(si_t *sih);
-extern uint32 *ai_corereg_addr(si_t *sih, uint coreidx, uint regoff);
-extern bool ai_iscoreup(si_t *sih);
-extern void *ai_setcoreidx(si_t *sih, uint coreidx);
-extern void *ai_setcoreidx_2ndwrap(si_t *sih, uint coreidx);
-extern uint32 ai_core_cflags(si_t *sih, uint32 mask, uint32 val);
-extern void ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val);
-extern uint32 ai_core_sflags(si_t *sih, uint32 mask, uint32 val);
-extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val);
-extern void ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
-extern void ai_d11rsdb_core_reset(si_t *sih, uint32 bits,
-	uint32 resetbits, void *p, void *s);
-extern void ai_d11rsdb_core1_alt_reg_clk_en(si_t *sih);
-extern void ai_d11rsdb_core1_alt_reg_clk_dis(si_t *sih);
-
-extern void ai_core_disable(si_t *sih, uint32 bits);
-extern void ai_d11rsdb_core_disable(const si_info_t *sii, uint32 bits,
-	aidmp_t *pmacai, aidmp_t *smacai);
-extern int ai_numaddrspaces(si_t *sih);
-extern uint32 ai_addrspace(si_t *sih, uint asidx);
-extern uint32 ai_addrspacesize(si_t *sih, uint asidx);
-extern void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size);
-extern uint ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
-extern void ai_enable_backplane_timeouts(si_t *sih);
-extern void ai_clear_backplane_to(si_t *sih);
-
-#if defined(BCMDBG_PHYDUMP)
-extern void ai_dumpregs(si_t *sih, struct bcmstrbuf *b);
-#endif 
-
-
-#define ub_scan(a, b, c) do {} while (0)
-#define ub_flag(a) (0)
-#define ub_setint(a, b) do {} while (0)
-#define ub_coreidx(a) (0)
-#define ub_corevendor(a) (0)
-#define ub_corerev(a) (0)
-#define ub_iscoreup(a) (0)
-#define ub_setcoreidx(a, b) (0)
-#define ub_core_cflags(a, b, c) (0)
-#define ub_core_cflags_wo(a, b, c) do {} while (0)
-#define ub_core_sflags(a, b, c) (0)
-#define ub_corereg(a, b, c, d, e) (0)
-#define ub_core_reset(a, b, c) do {} while (0)
-#define ub_core_disable(a, b) do {} while (0)
-#define ub_numaddrspaces(a) (0)
-#define ub_addrspace(a, b)  (0)
-#define ub_addrspacesize(a, b) (0)
-#define ub_view(a, b) do {} while (0)
-#define ub_dumpregs(a, b) do {} while (0)
-
-#endif	/* _siutils_priv_h_ */
diff --git a/drivers/net/wireless/bcmdhd/uamp_api.h b/drivers/net/wireless/bcmdhd/uamp_api.h
deleted file mode 100644
index 0d04a9d..0000000
--- a/drivers/net/wireless/bcmdhd/uamp_api.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- *  Name:       uamp_api.h
- *
- *  Description: Universal AMP API
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: uamp_api.h 514727 2014-11-12 03:02:48Z $
- *
- */
-
-
-#ifndef UAMP_API_H
-#define UAMP_API_H
-
-
-#include "typedefs.h"
-
-
-/*****************************************************************************
-**  Constant and Type Definitions
-******************************************************************************
-*/
-
-#define BT_API
-
-/* Types. */
-typedef bool	BOOLEAN;
-typedef uint8	UINT8;
-typedef uint16	UINT16;
-
-
-/* UAMP identifiers */
-#define UAMP_ID_1   1
-#define UAMP_ID_2   2
-typedef UINT8 tUAMP_ID;
-
-/* UAMP event ids (used by UAMP_CBACK) */
-#define UAMP_EVT_RX_READY           0   /* Data from AMP controller is ready to be read */
-#define UAMP_EVT_CTLR_REMOVED       1   /* Controller removed */
-#define UAMP_EVT_CTLR_READY         2   /* Controller added/ready */
-typedef UINT8 tUAMP_EVT;
-
-
-/* UAMP Channels */
-#define UAMP_CH_HCI_CMD            0   /* HCI Command channel */
-#define UAMP_CH_HCI_EVT            1   /* HCI Event channel */
-#define UAMP_CH_HCI_DATA           2   /* HCI ACL Data channel */
-typedef UINT8 tUAMP_CH;
-
-/* tUAMP_EVT_DATA: union for event-specific data, used by UAMP_CBACK */
-typedef union {
-    tUAMP_CH channel;       /* UAMP_EVT_RX_READY: channel for which rx occured */
-} tUAMP_EVT_DATA;
-
-
-/*****************************************************************************
-**
-** Function:    UAMP_CBACK
-**
-** Description: Callback for events. Register callback using UAMP_Init.
-**
-** Parameters   amp_id:         AMP device identifier that generated the event
-**              amp_evt:        event id
-**              p_amp_evt_data: pointer to event-specific data
-**
-******************************************************************************
-*/
-typedef void (*tUAMP_CBACK)(tUAMP_ID amp_id, tUAMP_EVT amp_evt, tUAMP_EVT_DATA *p_amp_evt_data);
-
-/*****************************************************************************
-**  external function declarations
-******************************************************************************
-*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/*****************************************************************************
-**
-** Function:    UAMP_Init
-**
-** Description: Initialize UAMP driver
-**
-** Parameters   p_cback:    Callback function for UAMP event notification
-**
-******************************************************************************
-*/
-BT_API BOOLEAN UAMP_Init(tUAMP_CBACK p_cback);
-
-
-/*****************************************************************************
-**
-** Function:    UAMP_Open
-**
-** Description: Open connection to local AMP device.
-**
-** Parameters   app_id: Application specific AMP identifer. This value
-**                      will be included in AMP messages sent to the
-**                      BTU task, to identify source of the message
-**
-******************************************************************************
-*/
-BT_API BOOLEAN UAMP_Open(tUAMP_ID amp_id);
-
-/*****************************************************************************
-**
-** Function:    UAMP_Close
-**
-** Description: Close connection to local AMP device.
-**
-** Parameters   app_id: Application specific AMP identifer.
-**
-******************************************************************************
-*/
-BT_API void UAMP_Close(tUAMP_ID amp_id);
-
-
-/*****************************************************************************
-**
-** Function:    UAMP_Write
-**
-** Description: Send buffer to AMP device. Frees GKI buffer when done.
-**
-**
-** Parameters:  app_id:     AMP identifer.
-**              p_buf:      pointer to buffer to write
-**              num_bytes:  number of bytes to write
-**              channel:    UAMP_CH_HCI_ACL, or UAMP_CH_HCI_CMD
-**
-** Returns:     number of bytes written
-**
-******************************************************************************
-*/
-BT_API UINT16 UAMP_Write(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 num_bytes, tUAMP_CH channel);
-
-/*****************************************************************************
-**
-** Function:    UAMP_Read
-**
-** Description: Read incoming data from AMP. Call after receiving a
-**              UAMP_EVT_RX_READY callback event.
-**
-** Parameters:  app_id:     AMP identifer.
-**              p_buf:      pointer to buffer for holding incoming AMP data
-**              buf_size:   size of p_buf
-**              channel:    UAMP_CH_HCI_ACL, or UAMP_CH_HCI_EVT
-**
-** Returns:     number of bytes read
-**
-******************************************************************************
-*/
-BT_API UINT16 UAMP_Read(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 buf_size, tUAMP_CH channel);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* UAMP_API_H */
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
deleted file mode 100644
index 1ba59c1..0000000
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ /dev/null
@@ -1,3357 +0,0 @@
-/*
- * Linux cfg80211 driver - Android related functions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_android.c 608788 2015-12-29 10:59:33Z $
- */
-
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <net/netlink.h>
-#ifdef CONFIG_COMPAT
-#include <linux/compat.h>
-#endif
-
-#include <wl_android.h>
-#include <wldev_common.h>
-#include <wlioctl.h>
-#include <bcmutils.h>
-#include <linux_osl.h>
-#include <dhd_dbg.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <proto/bcmip.h>
-#ifdef PNO_SUPPORT
-#include <dhd_pno.h>
-#endif
-#ifdef BCMSDIO
-#include <bcmsdbus.h>
-#endif
-#ifdef WL_CFG80211
-#include <wl_cfg80211.h>
-#endif
-#ifdef WL_NAN
-#include <wl_cfgnan.h>
-#endif /* WL_NAN */
-#ifdef DHDTCPACK_SUPPRESS
-#include <dhd_ip.h>
-#endif /* DHDTCPACK_SUPPRESS */
-
-/*
- * Android private command strings, PLEASE define new private commands here
- * so they can be updated easily in the future (if needed)
- */
-
-#define CMD_START		"START"
-#define CMD_STOP		"STOP"
-#define	CMD_SCAN_ACTIVE		"SCAN-ACTIVE"
-#define	CMD_SCAN_PASSIVE	"SCAN-PASSIVE"
-#define CMD_RSSI		"RSSI"
-#define CMD_LINKSPEED		"LINKSPEED"
-#define CMD_RXFILTER_START	"RXFILTER-START"
-#define CMD_RXFILTER_STOP	"RXFILTER-STOP"
-#define CMD_RXFILTER_ADD	"RXFILTER-ADD"
-#define CMD_RXFILTER_REMOVE	"RXFILTER-REMOVE"
-#define CMD_BTCOEXSCAN_START	"BTCOEXSCAN-START"
-#define CMD_BTCOEXSCAN_STOP	"BTCOEXSCAN-STOP"
-#define CMD_BTCOEXMODE		"BTCOEXMODE"
-#define CMD_SETSUSPENDOPT	"SETSUSPENDOPT"
-#define CMD_SETSUSPENDMODE      "SETSUSPENDMODE"
-#define CMD_P2P_DEV_ADDR	"P2P_DEV_ADDR"
-#define CMD_SETFWPATH		"SETFWPATH"
-#define CMD_SETBAND		"SETBAND"
-#define CMD_GETBAND		"GETBAND"
-#define CMD_COUNTRY		"COUNTRY"
-#define CMD_P2P_SET_NOA		"P2P_SET_NOA"
-#if !defined WL_ENABLE_P2P_IF
-#define CMD_P2P_GET_NOA			"P2P_GET_NOA"
-#endif /* WL_ENABLE_P2P_IF */
-#define CMD_P2P_SD_OFFLOAD		"P2P_SD_"
-#define CMD_P2P_LISTEN_OFFLOAD		"P2P_LO_"
-#define CMD_P2P_SET_PS		"P2P_SET_PS"
-#define CMD_P2P_ECSA		"P2P_ECSA"
-#define CMD_SET_AP_WPS_P2P_IE 		"SET_AP_WPS_P2P_IE"
-#define CMD_SETROAMMODE 	"SETROAMMODE"
-#define CMD_SETIBSSBEACONOUIDATA	"SETIBSSBEACONOUIDATA"
-#define CMD_MIRACAST		"MIRACAST"
-#ifdef WL_NAN
-#define CMD_NAN         "NAN_"
-#endif /* WL_NAN */
-#define CMD_COUNTRY_DELIMITER "/"
-#ifdef WL11ULB
-#define CMD_ULB_MODE "ULB_MODE"
-#define CMD_ULB_BW "ULB_BW"
-#endif /* WL11ULB */
-
-#if defined(WL_SUPPORT_AUTO_CHANNEL)
-#define CMD_GET_BEST_CHANNELS	"GET_BEST_CHANNELS"
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
-
-#define CMD_80211_MODE    "MODE"  /* 802.11 mode a/b/g/n/ac */
-#define CMD_CHANSPEC      "CHANSPEC"
-#define CMD_DATARATE      "DATARATE"
-#define CMD_ASSOC_CLIENTS "ASSOCLIST"
-#define CMD_SET_CSA       "SETCSA"
-#ifdef WL_SUPPORT_AUTO_CHANNEL
-#define CMD_SET_HAPD_AUTO_CHANNEL	"HAPD_AUTO_CHANNEL"
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
-#ifdef CUSTOMER_HW4_PRIVATE_CMD
-#ifdef SUPPORT_SET_LPC
-#define CMD_HAPD_LPC_ENABLED		"HAPD_LPC_ENABLED"
-#endif /* SUPPORT_SET_LPC */
-#ifdef SUPPORT_TRIGGER_HANG_EVENT
-#define CMD_TEST_FORCE_HANG		"TEST_FORCE_HANG"
-#endif /* SUPPORT_TRIGGER_HANG_EVENT */
-#ifdef TEST_TX_POWER_CONTROL
-#define CMD_TEST_SET_TX_POWER		"TEST_SET_TX_POWER"
-#define CMD_TEST_GET_TX_POWER		"TEST_GET_TX_POWER"
-#endif /* TEST_TX_POWER_CONTROL */
-#define CMD_SARLIMIT_TX_CONTROL		"SET_TX_POWER_CALLING"
-#endif /* CUSTOMER_HW4_PRIVATE_CMD */
-#define CMD_KEEP_ALIVE		"KEEPALIVE"
-
-
-#ifdef PNO_SUPPORT
-#define CMD_PNOSSIDCLR_SET	"PNOSSIDCLR"
-#define CMD_PNOSETUP_SET	"PNOSETUP "
-#define CMD_PNOENABLE_SET	"PNOFORCE"
-#define CMD_PNODEBUG_SET	"PNODEBUG"
-#define CMD_WLS_BATCHING	"WLS_BATCHING"
-#endif /* PNO_SUPPORT */
-
-#define	CMD_HAPD_MAC_FILTER	"HAPD_MAC_FILTER"
-
-#ifdef CUSTOMER_HW4_PRIVATE_CMD
-
-
-#if defined(SUPPORT_RANDOM_MAC_SCAN)
-#define ENABLE_RANDOM_MAC "ENABLE_RANDOM_MAC"
-#define DISABLE_RANDOM_MAC "DISABLE_RANDOM_MAC"
-#endif /* SUPPORT_RANDOM_MAC_SCAN */
-
-
-#define CMD_CHANGE_RL 	"CHANGE_RL"
-#define CMD_RESTORE_RL  "RESTORE_RL"
-
-#define CMD_SET_RMC_ENABLE			"SETRMCENABLE"
-#define CMD_SET_RMC_TXRATE			"SETRMCTXRATE"
-#define CMD_SET_RMC_ACTPERIOD		"SETRMCACTIONPERIOD"
-#define CMD_SET_RMC_IDLEPERIOD		"SETRMCIDLEPERIOD"
-#define CMD_SET_RMC_LEADER			"SETRMCLEADER"
-#define CMD_SET_RMC_EVENT			"SETRMCEVENT"
-
-#define CMD_SET_SCSCAN		"SETSINGLEANT"
-#define CMD_GET_SCSCAN		"GETSINGLEANT"
-
-/* FCC_PWR_LIMIT_2G */
-#define CUSTOMER_HW4_ENABLE		0
-#define CUSTOMER_HW4_DISABLE	-1
-#define CUSTOMER_HW4_EN_CONVERT(i)	(i += 1)
-
-#ifdef WLTDLS
-#define CMD_TDLS_RESET "TDLS_RESET"
-#endif /* WLTDLS */
-
-#ifdef IPV6_NDO_SUPPORT
-#define CMD_NDRA_LIMIT "NDRA_LIMIT"
-#endif /* IPV6_NDO_SUPPORT */
-
-#endif /* CUSTOMER_HW4_PRIVATE_CMD */
-
-
-#define CMD_ROAM_OFFLOAD			"SETROAMOFFLOAD"
-#define CMD_ROAM_OFFLOAD_APLIST			"SETROAMOFFLAPLIST"
-#define CMD_INTERFACE_CREATE			"INTERFACE_CREATE"
-#define CMD_INTERFACE_DELETE			"INTERFACE_DELETE"
-
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-#define CMD_GET_BSS_INFO            "GETBSSINFO"
-#define CMD_GET_ASSOC_REJECT_INFO   "GETASSOCREJECTINFO"
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-
-#ifdef P2PRESP_WFDIE_SRC
-#define CMD_P2P_SET_WFDIE_RESP      "P2P_SET_WFDIE_RESP"
-#define CMD_P2P_GET_WFDIE_RESP      "P2P_GET_WFDIE_RESP"
-#endif /* P2PRESP_WFDIE_SRC */
-
-#define CMD_DFS_AP_MOVE			"DFS_AP_MOVE"
-#define CMD_WBTEXT_ENABLE		"WBTEXT_ENABLE"
-#define CMD_WBTEXT_PROFILE_CONFIG	"WBTEXT_PROFILE_CONFIG"
-#define CMD_WBTEXT_WEIGHT_CONFIG	"WBTEXT_WEIGHT_CONFIG"
-#define CMD_WBTEXT_TABLE_CONFIG		"WBTEXT_TABLE_CONFIG"
-#define CMD_WBTEXT_DELTA_CONFIG		"WBTEXT_DELTA_CONFIG"
-
-#ifdef WLWFDS
-#define CMD_ADD_WFDS_HASH	"ADD_WFDS_HASH"
-#define CMD_DEL_WFDS_HASH	"DEL_WFDS_HASH"
-#endif /* WLWFDS */
-
-#ifdef SET_RPS_CPUS
-#define CMD_RPSMODE  "RPSMODE"
-#endif /* SET_RPS_CPUS */
-
-#ifdef BT_WIFI_HANDOVER
-#define CMD_TBOW_TEARDOWN "TBOW_TEARDOWN"
-#endif /* BT_WIFI_HANDOVER */
-
-#define CMD_MURX_BFE_CAP "MURX_BFE_CAP"
-
-/* miracast related definition */
-#define MIRACAST_MODE_OFF	0
-#define MIRACAST_MODE_SOURCE	1
-#define MIRACAST_MODE_SINK	2
-
-#ifndef MIRACAST_AMPDU_SIZE
-#define MIRACAST_AMPDU_SIZE	8
-#endif
-
-#ifndef MIRACAST_MCHAN_ALGO
-#define MIRACAST_MCHAN_ALGO     1
-#endif
-
-#ifndef MIRACAST_MCHAN_BW
-#define MIRACAST_MCHAN_BW       25
-#endif
-
-#ifdef CONNECTION_STATISTICS
-#define CMD_GET_CONNECTION_STATS	"GET_CONNECTION_STATS"
-
-struct connection_stats {
-	u32 txframe;
-	u32 txbyte;
-	u32 txerror;
-	u32 rxframe;
-	u32 rxbyte;
-	u32 txfail;
-	u32 txretry;
-	u32 txretrie;
-	u32 txrts;
-	u32 txnocts;
-	u32 txexptime;
-	u32 txrate;
-	u8	chan_idle;
-};
-#endif /* CONNECTION_STATISTICS */
-
-static LIST_HEAD(miracast_resume_list);
-static u8 miracast_cur_mode;
-
-#ifdef DHD_LOG_DUMP
-#define CMD_NEW_DEBUG_PRINT_DUMP			"DEBUG_DUMP"
-extern void dhd_schedule_log_dump(dhd_pub_t *dhdp);
-extern int dhd_bus_mem_dump(dhd_pub_t *dhd);
-#endif /* DHD_LOG_DUMP */
-#ifdef DHD_TRACE_WAKE_LOCK
-extern void dhd_wk_lock_stats_dump(dhd_pub_t *dhdp);
-#endif /* DHD_TRACE_WAKE_LOCK */
-
-struct io_cfg {
-	s8 *iovar;
-	s32 param;
-	u32 ioctl;
-	void *arg;
-	u32 len;
-	struct list_head list;
-};
-
-typedef struct _android_wifi_priv_cmd {
-	char *buf;
-	int used_len;
-	int total_len;
-} android_wifi_priv_cmd;
-
-#ifdef CONFIG_COMPAT
-typedef struct _compat_android_wifi_priv_cmd {
-	compat_caddr_t buf;
-	int used_len;
-	int total_len;
-} compat_android_wifi_priv_cmd;
-#endif /* CONFIG_COMPAT */
-
-#if defined(BCMFW_ROAM_ENABLE)
-#define CMD_SET_ROAMPREF	"SET_ROAMPREF"
-
-#define MAX_NUM_SUITES		10
-#define WIDTH_AKM_SUITE		8
-#define JOIN_PREF_RSSI_LEN		0x02
-#define JOIN_PREF_RSSI_SIZE		4	/* RSSI pref header size in bytes */
-#define JOIN_PREF_WPA_HDR_SIZE		4 /* WPA pref header size in bytes */
-#define JOIN_PREF_WPA_TUPLE_SIZE	12	/* Tuple size in bytes */
-#define JOIN_PREF_MAX_WPA_TUPLES	16
-#define MAX_BUF_SIZE		(JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE +	\
-				           (JOIN_PREF_WPA_TUPLE_SIZE * JOIN_PREF_MAX_WPA_TUPLES))
-#endif /* BCMFW_ROAM_ENABLE */
-
-
-/**
- * Extern function declarations (TODO: move them to dhd_linux.h)
- */
-int dhd_net_bus_devreset(struct net_device *dev, uint8 flag);
-int dhd_dev_init_ioctl(struct net_device *dev);
-#ifdef WL_CFG80211
-int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
-int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, dhd_pub_t *dhd, char *command);
-#else
-int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
-{ return 0; }
-int wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
-{ return 0; }
-int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
-{ return 0; }
-int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
-{ return 0; }
-int wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
-{ return 0; }
-#endif /* WK_CFG80211 */
-
-
-#ifdef ENABLE_4335BT_WAR
-extern int bcm_bt_lock(int cookie);
-extern void bcm_bt_unlock(int cookie);
-static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24;	/* cookie is "WiFi" */
-#endif /* ENABLE_4335BT_WAR */
-
-extern bool ap_fw_loaded;
-extern char iface_name[IFNAMSIZ];
-
-/**
- * Local (static) functions and variables
- */
-
-/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
- * time (only) in dhd_open, subsequential wifi on will be handled by
- * wl_android_wifi_on
- */
-static int g_wifi_on = TRUE;
-
-/**
- * Local (static) function definitions
- */
-
-#ifdef WLWFDS
-static int wl_android_set_wfds_hash(
-	struct net_device *dev, char *command, int total_len, bool enable)
-{
-	int error = 0;
-	wl_p2p_wfds_hash_t *wfds_hash = NULL;
-	char *smbuf = NULL;
-	smbuf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
-
-	if (smbuf == NULL) {
-		DHD_ERROR(("%s: failed to allocated memory %d bytes\n",
-			__FUNCTION__, WLC_IOCTL_MAXLEN));
-		return -ENOMEM;
-	}
-
-	if (enable) {
-		wfds_hash = (wl_p2p_wfds_hash_t *)(command + strlen(CMD_ADD_WFDS_HASH) + 1);
-		error = wldev_iovar_setbuf(dev, "p2p_add_wfds_hash", wfds_hash,
-			sizeof(wl_p2p_wfds_hash_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
-	}
-	else {
-		wfds_hash = (wl_p2p_wfds_hash_t *)(command + strlen(CMD_DEL_WFDS_HASH) + 1);
-		error = wldev_iovar_setbuf(dev, "p2p_del_wfds_hash", wfds_hash,
-			sizeof(wl_p2p_wfds_hash_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
-	}
-
-	if (error) {
-		DHD_ERROR(("%s: failed to %s, error=%d\n", __FUNCTION__, command, error));
-	}
-
-	if (smbuf)
-		kfree(smbuf);
-	return error;
-}
-#endif /* WLWFDS */
-
-static int wl_android_get_link_speed(struct net_device *net, char *command, int total_len)
-{
-	int link_speed;
-	int bytes_written;
-	int error;
-
-	error = wldev_get_link_speed(net, &link_speed);
-	if (error)
-		return -1;
-
-	/* Convert Kbps to Android Mbps */
-	link_speed = link_speed / 1000;
-	bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
-	DHD_INFO(("%s: command result is %s\n", __FUNCTION__, command));
-	return bytes_written;
-}
-
-static int wl_android_get_rssi(struct net_device *net, char *command, int total_len)
-{
-	wlc_ssid_t ssid = {0};
-	int bytes_written = 0;
-	int error = 0;
-	scb_val_t scbval;
-	char *delim = NULL;
-
-	delim = strchr(command, ' ');
-	/* For Ap mode rssi command would be
-	 * driver rssi <sta_mac_addr>
-	 * for STA/GC mode
-	 * driver rssi
-	*/
-	if (delim) {
-		/* Ap/GO mode
-		* driver rssi <sta_mac_addr>
-		*/
-		DHD_TRACE(("%s: cmd:%s\n", __FUNCTION__, delim));
-		/* skip space from delim after finding char */
-		delim++;
-		if (!(bcm_ether_atoe((delim), &scbval.ea)))
-		{
-			DHD_ERROR(("%s:address err\n", __FUNCTION__));
-			return -1;
-		}
-	        scbval.val = htod32(0);
-		DHD_TRACE(("%s: address:"MACDBG, __FUNCTION__, MAC2STRDBG(scbval.ea.octet)));
-	}
-	else {
-		/* STA/GC mode */
-		memset(&scbval, 0, sizeof(scb_val_t));
-	}
-
-	error = wldev_get_rssi(net, &scbval);
-	if (error)
-		return -1;
-
-	error = wldev_get_ssid(net, &ssid);
-	if (error)
-		return -1;
-	if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) {
-		DHD_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__));
-	} else {
-		memcpy(command, ssid.SSID, ssid.SSID_len);
-		bytes_written = ssid.SSID_len;
-	}
-	bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", scbval.val);
-	DHD_TRACE(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written));
-	return bytes_written;
-}
-
-static int wl_android_set_suspendopt(struct net_device *dev, char *command, int total_len)
-{
-	int suspend_flag;
-	int ret_now;
-	int ret = 0;
-
-	suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0';
-
-	if (suspend_flag != 0) {
-		suspend_flag = 1;
-	}
-	ret_now = net_os_set_suspend_disable(dev, suspend_flag);
-
-	if (ret_now != suspend_flag) {
-		if (!(ret = net_os_set_suspend(dev, ret_now, 1))) {
-			DHD_INFO(("%s: Suspend Flag %d -> %d\n",
-				__FUNCTION__, ret_now, suspend_flag));
-		} else {
-			DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
-		}
-	}
-
-	return ret;
-}
-
-static int wl_android_set_suspendmode(struct net_device *dev, char *command, int total_len)
-{
-	int ret = 0;
-
-#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND)
-	int suspend_flag;
-
-	suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0';
-	if (suspend_flag != 0)
-		suspend_flag = 1;
-
-	if (!(ret = net_os_set_suspend(dev, suspend_flag, 0)))
-		DHD_INFO(("%s: Suspend Mode %d\n", __FUNCTION__, suspend_flag));
-	else
-		DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
-#endif
-
-	return ret;
-}
-
-int wl_android_get_80211_mode(struct net_device *dev, char *command, int total_len)
-{
-	uint8 mode[4];
-	int  error = 0;
-	int bytes_written = 0;
-
-	error = wldev_get_mode(dev, mode);
-	if (error)
-		return -1;
-
-	DHD_INFO(("%s: mode:%s\n", __FUNCTION__, mode));
-	bytes_written = snprintf(command, total_len, "%s %s", CMD_80211_MODE, mode);
-	DHD_INFO(("%s: command:%s EXIT\n", __FUNCTION__, command));
-	return bytes_written;
-
-}
-
-extern chanspec_t
-wl_chspec_driver_to_host(chanspec_t chanspec);
-int wl_android_get_chanspec(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0;
-	int bytes_written = 0;
-	int chsp = {0};
-	uint16 band = 0;
-	uint16 bw = 0;
-	uint16 channel = 0;
-	u32 sb = 0;
-	chanspec_t chanspec;
-
-	/* command is
-	 * driver chanspec
-	 */
-	error = wldev_iovar_getint(dev, "chanspec", &chsp);
-	if (error)
-		return -1;
-
-	chanspec = wl_chspec_driver_to_host(chsp);
-	DHD_INFO(("%s:return value of chanspec:%x\n", __FUNCTION__, chanspec));
-
-	channel = chanspec & WL_CHANSPEC_CHAN_MASK;
-	band = chanspec & WL_CHANSPEC_BAND_MASK;
-	bw = chanspec & WL_CHANSPEC_BW_MASK;
-
-	DHD_INFO(("%s:channel:%d band:%d bandwidth:%d\n", __FUNCTION__, channel, band, bw));
-
-	if (bw == WL_CHANSPEC_BW_80)
-		bw = WL_CH_BANDWIDTH_80MHZ;
-	else if (bw == WL_CHANSPEC_BW_40)
-		bw = WL_CH_BANDWIDTH_40MHZ;
-	else if	(bw == WL_CHANSPEC_BW_20)
-		bw = WL_CH_BANDWIDTH_20MHZ;
-	else
-		bw = WL_CH_BANDWIDTH_20MHZ;
-
-	if (bw == WL_CH_BANDWIDTH_40MHZ) {
-		if (CHSPEC_SB_UPPER(chanspec)) {
-			channel += CH_10MHZ_APART;
-		} else {
-			channel -= CH_10MHZ_APART;
-		}
-	}
-	else if (bw == WL_CH_BANDWIDTH_80MHZ) {
-		sb = chanspec & WL_CHANSPEC_CTL_SB_MASK;
-		if (sb == WL_CHANSPEC_CTL_SB_LL) {
-			channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
-		} else if (sb == WL_CHANSPEC_CTL_SB_LU) {
-			channel -= CH_10MHZ_APART;
-		} else if (sb == WL_CHANSPEC_CTL_SB_UL) {
-			channel += CH_10MHZ_APART;
-		} else {
-			/* WL_CHANSPEC_CTL_SB_UU */
-			channel += (CH_10MHZ_APART + CH_20MHZ_APART);
-		}
-	}
-	bytes_written = snprintf(command, total_len, "%s channel %d band %s bw %d", CMD_CHANSPEC,
-		channel, band == WL_CHANSPEC_BAND_5G ? "5G":"2G", bw);
-
-	DHD_INFO(("%s: command:%s EXIT\n", __FUNCTION__, command));
-	return bytes_written;
-
-}
-
-/* returns current datarate datarate returned from firmware are in 500kbps */
-int wl_android_get_datarate(struct net_device *dev, char *command, int total_len)
-{
-	int  error = 0;
-	int datarate = 0;
-	int bytes_written = 0;
-
-	error = wldev_get_datarate(dev, &datarate);
-	if (error)
-		return -1;
-
-	DHD_INFO(("%s:datarate:%d\n", __FUNCTION__, datarate));
-
-	bytes_written = snprintf(command, total_len, "%s %d", CMD_DATARATE, (datarate/2));
-	return bytes_written;
-}
-int wl_android_get_assoclist(struct net_device *dev, char *command, int total_len)
-{
-	int  error = 0;
-	int bytes_written = 0;
-	uint i;
-	char mac_buf[MAX_NUM_OF_ASSOCLIST *
-		sizeof(struct ether_addr) + sizeof(uint)] = {0};
-	struct maclist *assoc_maclist = (struct maclist *)mac_buf;
-
-	DHD_TRACE(("%s: ENTER\n", __FUNCTION__));
-
-	assoc_maclist->count = htod32(MAX_NUM_OF_ASSOCLIST);
-
-	error = wldev_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf), false);
-	if (error)
-		return -1;
-
-	assoc_maclist->count = dtoh32(assoc_maclist->count);
-	bytes_written = snprintf(command, total_len, "%s listcount: %d Stations:",
-		CMD_ASSOC_CLIENTS, assoc_maclist->count);
-
-	for (i = 0; i < assoc_maclist->count; i++) {
-		bytes_written += snprintf(command + bytes_written, total_len, " " MACDBG,
-			MAC2STRDBG(assoc_maclist->ea[i].octet));
-	}
-	return bytes_written;
-
-}
-extern chanspec_t
-wl_chspec_host_to_driver(chanspec_t chanspec);
-static int wl_android_set_csa(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0;
-	char smbuf[WLC_IOCTL_SMLEN];
-	wl_chan_switch_t csa_arg;
-	u32 chnsp = 0;
-	int err = 0;
-
-	DHD_INFO(("%s: command:%s\n", __FUNCTION__, command));
-
-	command = (command + strlen(CMD_SET_CSA));
-	/* Order is mode, count channel */
-	if (!*++command) {
-		DHD_ERROR(("%s:error missing arguments\n", __FUNCTION__));
-		return -1;
-	}
-	csa_arg.mode = bcm_atoi(command);
-
-	if (csa_arg.mode != 0 && csa_arg.mode != 1) {
-		DHD_ERROR(("Invalid mode\n"));
-		return -1;
-	}
-
-	if (!*++command) {
-		DHD_ERROR(("%s:error missing count\n", __FUNCTION__));
-		return -1;
-	}
-	command++;
-	csa_arg.count = bcm_atoi(command);
-
-	csa_arg.reg = 0;
-	csa_arg.chspec = 0;
-	command += 2;
-	if (!*command) {
-		DHD_ERROR(("%s:error missing channel\n", __FUNCTION__));
-		return -1;
-	}
-
-	chnsp = wf_chspec_aton(command);
-	if (chnsp == 0)	{
-		DHD_ERROR(("%s:chsp is not correct\n", __FUNCTION__));
-		return -1;
-	}
-	chnsp = wl_chspec_host_to_driver(chnsp);
-	csa_arg.chspec = chnsp;
-
-	if (chnsp & WL_CHANSPEC_BAND_5G) {
-		u32 chanspec = chnsp;
-		err = wldev_iovar_getint(dev, "per_chan_info", &chanspec);
-		if (!err) {
-			if ((chanspec & WL_CHAN_RADAR) || (chanspec & WL_CHAN_PASSIVE)) {
-				DHD_ERROR(("Channel is radar sensitive\n"));
-				return -1;
-			}
-			if (chanspec == 0) {
-				DHD_ERROR(("Invalid hw channel\n"));
-				return -1;
-			}
-		} else  {
-			DHD_ERROR(("does not support per_chan_info\n"));
-			return -1;
-		}
-		DHD_INFO(("non radar sensitivity\n"));
-	}
-	error = wldev_iovar_setbuf(dev, "csa", &csa_arg, sizeof(csa_arg),
-		smbuf, sizeof(smbuf), NULL);
-	if (error) {
-		DHD_ERROR(("%s:set csa failed:%d\n", __FUNCTION__, error));
-		return -1;
-	}
-	return 0;
-}
-static int wl_android_get_band(struct net_device *dev, char *command, int total_len)
-{
-	uint band;
-	int bytes_written;
-	int error;
-
-	error = wldev_get_band(dev, &band);
-	if (error)
-		return -1;
-	bytes_written = snprintf(command, total_len, "Band %d", band);
-	return bytes_written;
-}
-
-#ifdef CUSTOMER_HW4_PRIVATE_CMD
-
-#ifdef FCC_PWR_LIMIT_2G
-int
-wl_android_set_fcc_pwr_limit_2g(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0;
-	int enable = 0;
-
-	sscanf(command+sizeof("SET_FCC_CHANNEL"), "%d", &enable);
-
-	if ((enable != CUSTOMER_HW4_ENABLE) && (enable != CUSTOMER_HW4_DISABLE)) {
-		DHD_ERROR(("%s: Invalid data\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	CUSTOMER_HW4_EN_CONVERT(enable);
-
-	DHD_ERROR(("%s: fccpwrlimit2g set (%d)\n", __FUNCTION__, enable));
-	error = wldev_iovar_setint(dev, "fccpwrlimit2g", enable);
-	if (error) {
-		DHD_ERROR(("%s: fccpwrlimit2g set returned (%d)\n", __FUNCTION__, error));
-		return BCME_ERROR;
-	}
-
-	return error;
-}
-
-int
-wl_android_get_fcc_pwr_limit_2g(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0;
-	int enable = 0;
-	int bytes_written = 0;
-
-	error = wldev_iovar_getint(dev, "fccpwrlimit2g", &enable);
-	if (error) {
-		DHD_ERROR(("%s: fccpwrlimit2g get error (%d)\n", __FUNCTION__, error));
-		return BCME_ERROR;
-	}
-	DHD_ERROR(("%s: fccpwrlimit2g get (%d)\n", __FUNCTION__, enable));
-
-	bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_FCC_PWR_LIMIT_2G, enable);
-
-	return bytes_written;
-}
-#endif /* FCC_PWR_LIMIT_2G */
-
-#ifdef IPV6_NDO_SUPPORT
-int
-wl_android_nd_ra_limit(struct net_device *dev, char *command, int total_len)
-{
-	int err = 0;
-	int bytes_written = 0;
-	uint tokens;
-	char *pos, *token, *delim;
-	char smbuf[WLC_IOCTL_SMLEN];
-	char param[ND_PARAM_SIZE+1], value[ND_VALUE_SIZE+1];
-	uint16 type = 0xff, min = 0, per = 0, hold = 0;
-	nd_ra_ol_limits_t ra_ol_limit;
-
-	WL_TRACE(("command=%s, len=%d\n", command, total_len));
-	pos = command + strlen(CMD_NDRA_LIMIT) + 1;
-	memset(&ra_ol_limit, 0, sizeof(nd_ra_ol_limits_t));
-
-	if (!strncmp(pos, ND_RA_OL_SET, strlen(ND_RA_OL_SET))) {
-		WL_TRACE(("SET NDRA_LIMIT\n"));
-		pos += strlen(ND_RA_OL_SET) + 1;
-		while ((token = strsep(&pos, ND_PARAMS_DELIMETER)) != NULL) {
-			memset(param, 0, sizeof(param));
-			memset(value, 0, sizeof(value));
-
-			delim = strchr(token, ND_PARAM_VALUE_DELLIMETER);
-			if (delim != NULL)
-				*delim = ' ';
-
-			tokens = sscanf(token, ND_LIMIT_STR_FMT, param, value);
-			if (!strncmp(param, ND_RA_TYPE, strlen(ND_RA_TYPE))) {
-				type = simple_strtol(value, NULL, 0);
-			} else if (!strncmp(param, ND_RA_MIN_TIME, strlen(ND_RA_MIN_TIME))) {
-				min = simple_strtol(value, NULL, 0);
-			} else if (!strncmp(param, ND_RA_PER, strlen(ND_RA_PER))) {
-				per = simple_strtol(value, NULL, 0);
-				if (per > 100) {
-					WL_ERR(("Invalid PERCENT %d\n", per));
-					err = BCME_BADARG;
-					goto exit;
-				}
-			} else if (!strncmp(param, ND_RA_HOLD, strlen(ND_RA_HOLD))) {
-				hold = simple_strtol(value, NULL, 0);
-			}
-		}
-
-		ra_ol_limit.version = htod32(ND_RA_OL_LIMITS_VER);
-		ra_ol_limit.type = htod32(type);
-		if (type == ND_RA_OL_LIMITS_REL_TYPE) {
-			if ((min == 0) || (per == 0)) {
-				WL_ERR(("Invalid min_time %d, percent %d\n", min, per));
-				err = BCME_BADARG;
-				goto exit;
-			}
-			ra_ol_limit.length = htod32(ND_RA_OL_LIMITS_REL_TYPE_LEN);
-			ra_ol_limit.limits.lifetime_relative.min_time = htod32(min);
-			ra_ol_limit.limits.lifetime_relative.lifetime_percent = htod32(per);
-		} else if (type == ND_RA_OL_LIMITS_FIXED_TYPE) {
-			if (hold == 0) {
-				WL_ERR(("Invalid hold_time %d\n", hold));
-				err = BCME_BADARG;
-				goto exit;
-			}
-			ra_ol_limit.length = htod32(ND_RA_OL_LIMITS_FIXED_TYPE_LEN);
-			ra_ol_limit.limits.fixed.hold_time = htod32(hold);
-		} else {
-			WL_ERR(("unknown TYPE %d\n", type));
-			err = BCME_BADARG;
-			goto exit;
-		}
-
-		err = wldev_iovar_setbuf(dev, "nd_ra_limit_intv", &ra_ol_limit,
-			sizeof(nd_ra_ol_limits_t), smbuf, sizeof(smbuf), NULL);
-		if (err) {
-			WL_ERR(("Failed to set nd_ra_limit_intv, error = %d\n", err));
-			goto exit;
-		}
-
-		WL_TRACE(("TYPE %d, MIN %d, PER %d, HOLD %d\n", type, min, per, hold));
-	} else if (!strncmp(pos, ND_RA_OL_GET, strlen(ND_RA_OL_GET))) {
-		WL_TRACE(("GET NDRA_LIMIT\n"));
-		err = wldev_iovar_getbuf(dev, "nd_ra_limit_intv", NULL, 0,
-			smbuf, sizeof(smbuf), NULL);
-		if (err) {
-			WL_ERR(("Failed to get nd_ra_limit_intv, error = %d\n", err));
-			goto exit;
-		}
-
-		memcpy(&ra_ol_limit, (uint8 *)smbuf, sizeof(nd_ra_ol_limits_t));
-		type = ra_ol_limit.type;
-		if (ra_ol_limit.version != ND_RA_OL_LIMITS_VER) {
-			WL_ERR(("Invalid Version %d\n", ra_ol_limit.version));
-			err = BCME_VERSION;
-			goto exit;
-		}
-
-		if (ra_ol_limit.type == ND_RA_OL_LIMITS_REL_TYPE) {
-			min = ra_ol_limit.limits.lifetime_relative.min_time;
-			per = ra_ol_limit.limits.lifetime_relative.lifetime_percent;
-			WL_ERR(("TYPE %d, MIN %d, PER %d\n", type, min, per));
-			bytes_written = snprintf(command, total_len,
-				"%s GET TYPE %d, MIN %d, PER %d", CMD_NDRA_LIMIT, type, min, per);
-		} else if (ra_ol_limit.type == ND_RA_OL_LIMITS_FIXED_TYPE) {
-			hold = ra_ol_limit.limits.fixed.hold_time;
-			WL_ERR(("TYPE %d, HOLD %d\n", type, hold));
-			bytes_written = snprintf(command, total_len,
-				"%s GET TYPE %d, HOLD %d", CMD_NDRA_LIMIT, type, hold);
-		} else {
-			WL_ERR(("unknown TYPE %d\n", type));
-			err = BCME_ERROR;
-			goto exit;
-		}
-
-		return bytes_written;
-	} else {
-		WL_ERR(("unknown command\n"));
-		err = BCME_ERROR;
-		goto exit;
-	}
-
-exit:
-	return err;
-}
-#endif /* IPV6_NDO_SUPPORT */
-#ifdef WLTDLS
-int wl_android_tdls_reset(struct net_device *dev)
-{
-	int ret = 0;
-	ret = dhd_tdls_enable(dev, false, false, NULL);
-	if (ret < 0) {
-		DHD_ERROR(("Disable tdls failed. %d\n", ret));
-		return ret;
-	}
-	ret = dhd_tdls_enable(dev, true, true, NULL);
-	if (ret < 0) {
-		DHD_ERROR(("enable tdls failed. %d\n", ret));
-		return ret;
-	}
-	return 0;
-}
-#endif /* WLTDLS */
-#endif /* CUSTOMER_HW4_PRIVATE_CMD */
-static int wl_android_wbtext(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0, argc = 0;
-	int data, bytes_written;
-
-	argc = sscanf(command+sizeof("WBTEXT_ENABLE"), "%d", &data);
-	if (!argc) {
-		error = wldev_iovar_getint(dev, "wnm_bsstrans_resp", &data);
-		if (error) {
-			DHD_ERROR(("%s: Failed to set wbtext error = %d\n",
-				__FUNCTION__, error));
-		}
-		bytes_written = snprintf(command, total_len, "WBTEXT %s\n",
-				(data == WL_BSSTRANS_POLICY_PRODUCT)? "ENABLED" : "DISABLED");
-		return bytes_written;
-	} else {
-		if (data)
-			data = WL_BSSTRANS_POLICY_PRODUCT;
-
-		error = wldev_iovar_setint(dev, "wnm_bsstrans_resp", data);
-		if (error) {
-			DHD_ERROR(("%s: Failed to set wbtext error = %d\n",
-				__FUNCTION__, error));
-		}
-	}
-	return error;
-}
-
-#ifdef PNO_SUPPORT
-#define PNO_PARAM_SIZE 50
-#define VALUE_SIZE 50
-#define LIMIT_STR_FMT  ("%50s %50s")
-static int
-wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len)
-{
-	int err = BCME_OK;
-	uint i, tokens;
-	char *pos, *pos2, *token, *token2, *delim;
-	char param[PNO_PARAM_SIZE], value[VALUE_SIZE];
-	struct dhd_pno_batch_params batch_params;
-	DHD_PNO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
-	if (total_len < strlen(CMD_WLS_BATCHING)) {
-		DHD_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len));
-		err = BCME_ERROR;
-		goto exit;
-	}
-	pos = command + strlen(CMD_WLS_BATCHING) + 1;
-	memset(&batch_params, 0, sizeof(struct dhd_pno_batch_params));
-
-	if (!strncmp(pos, PNO_BATCHING_SET, strlen(PNO_BATCHING_SET))) {
-		pos += strlen(PNO_BATCHING_SET) + 1;
-		while ((token = strsep(&pos, PNO_PARAMS_DELIMETER)) != NULL) {
-			memset(param, 0, sizeof(param));
-			memset(value, 0, sizeof(value));
-			if (token == NULL || !*token)
-				break;
-			if (*token == '\0')
-				continue;
-			delim = strchr(token, PNO_PARAM_VALUE_DELLIMETER);
-			if (delim != NULL)
-				*delim = ' ';
-
-			tokens = sscanf(token, LIMIT_STR_FMT, param, value);
-			if (!strncmp(param, PNO_PARAM_SCANFREQ, strlen(PNO_PARAM_SCANFREQ))) {
-				batch_params.scan_fr = simple_strtol(value, NULL, 0);
-				DHD_PNO(("scan_freq : %d\n", batch_params.scan_fr));
-			} else if (!strncmp(param, PNO_PARAM_BESTN, strlen(PNO_PARAM_BESTN))) {
-				batch_params.bestn = simple_strtol(value, NULL, 0);
-				DHD_PNO(("bestn : %d\n", batch_params.bestn));
-			} else if (!strncmp(param, PNO_PARAM_MSCAN, strlen(PNO_PARAM_MSCAN))) {
-				batch_params.mscan = simple_strtol(value, NULL, 0);
-				DHD_PNO(("mscan : %d\n", batch_params.mscan));
-			} else if (!strncmp(param, PNO_PARAM_CHANNEL, strlen(PNO_PARAM_CHANNEL))) {
-				i = 0;
-				pos2 = value;
-				tokens = sscanf(value, "<%s>", value);
-				if (tokens != 1) {
-					err = BCME_ERROR;
-					DHD_ERROR(("%s : invalid format for channel"
-					" <> params\n", __FUNCTION__));
-					goto exit;
-				}
-					while ((token2 = strsep(&pos2,
-					PNO_PARAM_CHANNEL_DELIMETER)) != NULL) {
-					if (token2 == NULL || !*token2)
-						break;
-					if (*token2 == '\0')
-						continue;
-					if (*token2 == 'A' || *token2 == 'B') {
-						batch_params.band = (*token2 == 'A')?
-							WLC_BAND_5G : WLC_BAND_2G;
-						DHD_PNO(("band : %s\n",
-							(*token2 == 'A')? "A" : "B"));
-					} else {
-						batch_params.chan_list[i++] =
-						simple_strtol(token2, NULL, 0);
-						batch_params.nchan++;
-						DHD_PNO(("channel :%d\n",
-						batch_params.chan_list[i-1]));
-					}
-				 }
-			} else if (!strncmp(param, PNO_PARAM_RTT, strlen(PNO_PARAM_RTT))) {
-				batch_params.rtt = simple_strtol(value, NULL, 0);
-				DHD_PNO(("rtt : %d\n", batch_params.rtt));
-			} else {
-				DHD_ERROR(("%s : unknown param: %s\n", __FUNCTION__, param));
-				err = BCME_ERROR;
-				goto exit;
-			}
-		}
-		err = dhd_dev_pno_set_for_batch(dev, &batch_params);
-		if (err < 0) {
-			DHD_ERROR(("failed to configure batch scan\n"));
-		} else {
-			memset(command, 0, total_len);
-			err = snprintf(command, total_len, "%d", err);
-		}
-	} else if (!strncmp(pos, PNO_BATCHING_GET, strlen(PNO_BATCHING_GET))) {
-		err = dhd_dev_pno_get_for_batch(dev, command, total_len);
-		if (err < 0) {
-			DHD_ERROR(("failed to getting batching results\n"));
-		} else {
-			err = strlen(command);
-		}
-	} else if (!strncmp(pos, PNO_BATCHING_STOP, strlen(PNO_BATCHING_STOP))) {
-		err = dhd_dev_pno_stop_for_batch(dev);
-		if (err < 0) {
-			DHD_ERROR(("failed to stop batching scan\n"));
-		} else {
-			memset(command, 0, total_len);
-			err = snprintf(command, total_len, "OK");
-		}
-	} else {
-		DHD_ERROR(("%s : unknown command\n", __FUNCTION__));
-		err = BCME_ERROR;
-		goto exit;
-	}
-exit:
-	return err;
-}
-#ifndef WL_SCHED_SCAN
-static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
-{
-	wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
-	int res = -1;
-	int nssid = 0;
-	cmd_tlv_t *cmd_tlv_temp;
-	char *str_ptr;
-	int tlv_size_left;
-	int pno_time = 0;
-	int pno_repeat = 0;
-	int pno_freq_expo_max = 0;
-
-#ifdef PNO_SET_DEBUG
-	int i;
-	char pno_in_example[] = {
-		'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
-		'S', '1', '2', '0',
-		'S',
-		0x05,
-		'd', 'l', 'i', 'n', 'k',
-		'S',
-		0x04,
-		'G', 'O', 'O', 'G',
-		'T',
-		'0', 'B',
-		'R',
-		'2',
-		'M',
-		'2',
-		0x00
-		};
-#endif /* PNO_SET_DEBUG */
-	DHD_PNO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
-
-	if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) {
-		DHD_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len));
-		goto exit_proc;
-	}
-#ifdef PNO_SET_DEBUG
-	memcpy(command, pno_in_example, sizeof(pno_in_example));
-	total_len = sizeof(pno_in_example);
-#endif
-	str_ptr = command + strlen(CMD_PNOSETUP_SET);
-	tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET);
-
-	cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
-	memset(ssids_local, 0, sizeof(ssids_local));
-
-	if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
-		(cmd_tlv_temp->version == PNO_TLV_VERSION) &&
-		(cmd_tlv_temp->subtype == PNO_TLV_SUBTYPE_LEGACY_PNO)) {
-
-		str_ptr += sizeof(cmd_tlv_t);
-		tlv_size_left -= sizeof(cmd_tlv_t);
-
-		if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local,
-			MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
-			DHD_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
-			goto exit_proc;
-		} else {
-			if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
-				DHD_ERROR(("%s scan duration corrupted field size %d\n",
-					__FUNCTION__, tlv_size_left));
-				goto exit_proc;
-			}
-			str_ptr++;
-			pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
-			DHD_PNO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
-
-			if (str_ptr[0] != 0) {
-				if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
-					DHD_ERROR(("%s pno repeat : corrupted field\n",
-						__FUNCTION__));
-					goto exit_proc;
-				}
-				str_ptr++;
-				pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
-				DHD_PNO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
-				if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
-					DHD_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n",
-						__FUNCTION__));
-					goto exit_proc;
-				}
-				str_ptr++;
-				pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
-				DHD_PNO(("%s: pno_freq_expo_max=%d\n",
-					__FUNCTION__, pno_freq_expo_max));
-			}
-		}
-	} else {
-		DHD_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
-		goto exit_proc;
-	}
-
-	res = dhd_dev_pno_set_for_ssid(dev, ssids_local, nssid, pno_time, pno_repeat,
-		pno_freq_expo_max, NULL, 0);
-exit_proc:
-	return res;
-}
-#endif /* !WL_SCHED_SCAN */
-#endif /* PNO_SUPPORT  */
-
-static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len)
-{
-	int ret;
-	int bytes_written = 0;
-
-	ret = wl_cfg80211_get_p2p_dev_addr(ndev, (struct ether_addr*)command);
-	if (ret)
-		return 0;
-	bytes_written = sizeof(struct ether_addr);
-	return bytes_written;
-}
-
-
-int
-wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist)
-{
-	int i, j, match;
-	int ret	= 0;
-	char mac_buf[MAX_NUM_OF_ASSOCLIST *
-		sizeof(struct ether_addr) + sizeof(uint)] = {0};
-	struct maclist *assoc_maclist = (struct maclist *)mac_buf;
-
-	/* set filtering mode */
-	if ((ret = wldev_ioctl(dev, WLC_SET_MACMODE, &macmode, sizeof(macmode), true)) != 0) {
-		DHD_ERROR(("%s : WLC_SET_MACMODE error=%d\n", __FUNCTION__, ret));
-		return ret;
-	}
-	if (macmode != MACLIST_MODE_DISABLED) {
-		/* set the MAC filter list */
-		if ((ret = wldev_ioctl(dev, WLC_SET_MACLIST, maclist,
-			sizeof(int) + sizeof(struct ether_addr) * maclist->count, true)) != 0) {
-			DHD_ERROR(("%s : WLC_SET_MACLIST error=%d\n", __FUNCTION__, ret));
-			return ret;
-		}
-		/* get the current list of associated STAs */
-		assoc_maclist->count = MAX_NUM_OF_ASSOCLIST;
-		if ((ret = wldev_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist,
-			sizeof(mac_buf), false)) != 0) {
-			DHD_ERROR(("%s : WLC_GET_ASSOCLIST error=%d\n", __FUNCTION__, ret));
-			return ret;
-		}
-		/* do we have any STA associated?  */
-		if (assoc_maclist->count) {
-			/* iterate each associated STA */
-			for (i = 0; i < assoc_maclist->count; i++) {
-				match = 0;
-				/* compare with each entry */
-				for (j = 0; j < maclist->count; j++) {
-					DHD_INFO(("%s : associated="MACDBG " list="MACDBG "\n",
-					__FUNCTION__, MAC2STRDBG(assoc_maclist->ea[i].octet),
-					MAC2STRDBG(maclist->ea[j].octet)));
-					if (memcmp(assoc_maclist->ea[i].octet,
-						maclist->ea[j].octet, ETHER_ADDR_LEN) == 0) {
-						match = 1;
-						break;
-					}
-				}
-				/* do conditional deauth */
-				/*   "if not in the allow list" or "if in the deny list" */
-				if ((macmode == MACLIST_MODE_ALLOW && !match) ||
-					(macmode == MACLIST_MODE_DENY && match)) {
-					scb_val_t scbval;
-
-					scbval.val = htod32(1);
-					memcpy(&scbval.ea, &assoc_maclist->ea[i],
-						ETHER_ADDR_LEN);
-					if ((ret = wldev_ioctl(dev,
-						WLC_SCB_DEAUTHENTICATE_FOR_REASON,
-						&scbval, sizeof(scb_val_t), true)) != 0)
-						DHD_ERROR(("%s WLC_SCB_DEAUTHENTICATE error=%d\n",
-							__FUNCTION__, ret));
-				}
-			}
-		}
-	}
-	return ret;
-}
-
-/*
- * HAPD_MAC_FILTER mac_mode mac_cnt mac_addr1 mac_addr2
- *
- */
-static int
-wl_android_set_mac_address_filter(struct net_device *dev, const char* str)
-{
-	int i;
-	int ret = 0;
-	int macnum = 0;
-	int macmode = MACLIST_MODE_DISABLED;
-	struct maclist *list;
-	char eabuf[ETHER_ADDR_STR_LEN];
-	char *token;
-
-	/* string should look like below (macmode/macnum/maclist) */
-	/*   1 2 00:11:22:33:44:55 00:11:22:33:44:ff  */
-
-	/* get the MAC filter mode */
-	token = strsep((char**)&str, " ");
-	if (!token) {
-		return -1;
-	}
-	macmode = bcm_atoi(token);
-
-	if (macmode < MACLIST_MODE_DISABLED || macmode > MACLIST_MODE_ALLOW) {
-		DHD_ERROR(("%s : invalid macmode %d\n", __FUNCTION__, macmode));
-		return -1;
-	}
-
-	token = strsep((char**)&str, " ");
-	if (!token) {
-		return -1;
-	}
-	macnum = bcm_atoi(token);
-	if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
-		DHD_ERROR(("%s : invalid number of MAC address entries %d\n",
-			__FUNCTION__, macnum));
-		return -1;
-	}
-	/* allocate memory for the MAC list */
-	list = (struct maclist*)kmalloc(sizeof(int) +
-		sizeof(struct ether_addr) * macnum, GFP_KERNEL);
-	if (!list) {
-		DHD_ERROR(("%s : failed to allocate memory\n", __FUNCTION__));
-		return -1;
-	}
-	/* prepare the MAC list */
-	list->count = htod32(macnum);
-	bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
-	for (i = 0; i < list->count; i++) {
-		strncpy(eabuf, strsep((char**)&str, " "), ETHER_ADDR_STR_LEN - 1);
-		if (!(ret = bcm_ether_atoe(eabuf, &list->ea[i]))) {
-			DHD_ERROR(("%s : mac parsing err index=%d, addr=%s\n",
-				__FUNCTION__, i, eabuf));
-			list->count--;
-			break;
-		}
-		DHD_INFO(("%s : %d/%d MACADDR=%s", __FUNCTION__, i, list->count, eabuf));
-	}
-	/* set the list */
-	if ((ret = wl_android_set_ap_mac_list(dev, macmode, list)) != 0)
-		DHD_ERROR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
-
-	kfree(list);
-
-	return 0;
-}
-
-/**
- * Global function definitions (declared in wl_android.h)
- */
-
-int wl_android_wifi_on(struct net_device *dev)
-{
-	int ret = 0;
-	int retry = POWERUP_MAX_RETRY;
-
-	DHD_ERROR(("%s in\n", __FUNCTION__));
-	if (!dev) {
-		DHD_ERROR(("%s: dev is null\n", __FUNCTION__));
-		return -EINVAL;
-	}
-
-	dhd_net_if_lock(dev);
-	if (!g_wifi_on) {
-		do {
-			dhd_net_wifi_platform_set_power(dev, TRUE, WIFI_TURNON_DELAY);
-#ifdef BCMSDIO
-			ret = dhd_net_bus_resume(dev, 0);
-#endif /* BCMSDIO */
-#ifdef BCMPCIE
-			ret = dhd_net_bus_devreset(dev, FALSE);
-#endif /* BCMPCIE */
-			if (ret == 0) {
-				break;
-			}
-			DHD_ERROR(("\nfailed to power up wifi chip, retry again (%d left) **\n\n",
-				retry));
-#ifdef BCMPCIE
-			dhd_net_bus_devreset(dev, TRUE);
-#endif /* BCMPCIE */
-			dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
-		} while (retry-- > 0);
-		if (ret != 0) {
-			DHD_ERROR(("\nfailed to power up wifi chip, max retry reached **\n\n"));
-			goto exit;
-		}
-#ifdef BCMSDIO
-		ret = dhd_net_bus_devreset(dev, FALSE);
-		dhd_net_bus_resume(dev, 1);
-#endif /* BCMSDIO */
-
-#ifndef BCMPCIE
-		if (!ret) {
-			if (dhd_dev_init_ioctl(dev) < 0) {
-				ret = -EFAULT;
-			}
-		}
-#endif /* !BCMPCIE */
-		g_wifi_on = TRUE;
-	}
-
-exit:
-	dhd_net_if_unlock(dev);
-
-	return ret;
-}
-
-int wl_android_wifi_off(struct net_device *dev, bool on_failure)
-{
-	int ret = 0;
-
-	DHD_ERROR(("%s in\n", __FUNCTION__));
-	if (!dev) {
-		DHD_TRACE(("%s: dev is null\n", __FUNCTION__));
-		return -EINVAL;
-	}
-
-	dhd_net_if_lock(dev);
-	if (g_wifi_on || on_failure) {
-#if defined(BCMSDIO) || defined(BCMPCIE)
-		ret = dhd_net_bus_devreset(dev, TRUE);
-#ifdef BCMSDIO
-		dhd_net_bus_suspend(dev);
-#endif /* BCMSDIO */
-#endif /* BCMSDIO || BCMPCIE */
-		dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
-		g_wifi_on = FALSE;
-	}
-	dhd_net_if_unlock(dev);
-
-	return ret;
-}
-
-static int wl_android_set_fwpath(struct net_device *net, char *command, int total_len)
-{
-	if ((strlen(command) - strlen(CMD_SETFWPATH)) > MOD_PARAM_PATHLEN)
-		return -1;
-	return dhd_net_set_fw_path(net, command + strlen(CMD_SETFWPATH) + 1);
-}
-
-#ifdef CONNECTION_STATISTICS
-static int
-wl_chanim_stats(struct net_device *dev, u8 *chan_idle)
-{
-	int err;
-	wl_chanim_stats_t *list;
-	/* Parameter _and_ returned buffer of chanim_stats. */
-	wl_chanim_stats_t param;
-	u8 result[WLC_IOCTL_SMLEN];
-	chanim_stats_t *stats;
-
-	memset(&param, 0, sizeof(param));
-	memset(result, 0, sizeof(result));
-
-	param.buflen = htod32(sizeof(wl_chanim_stats_t));
-	param.count = htod32(WL_CHANIM_COUNT_ONE);
-
-	if ((err = wldev_iovar_getbuf(dev, "chanim_stats", (char*)&param, sizeof(wl_chanim_stats_t),
-		(char*)result, sizeof(result), 0)) < 0) {
-		WL_ERR(("Failed to get chanim results %d \n", err));
-		return err;
-	}
-
-	list = (wl_chanim_stats_t*)result;
-
-	list->buflen = dtoh32(list->buflen);
-	list->version = dtoh32(list->version);
-	list->count = dtoh32(list->count);
-
-	if (list->buflen == 0) {
-		list->version = 0;
-		list->count = 0;
-	} else if (list->version != WL_CHANIM_STATS_VERSION) {
-		WL_ERR(("Sorry, firmware has wl_chanim_stats version %d "
-			"but driver supports only version %d.\n",
-				list->version, WL_CHANIM_STATS_VERSION));
-		list->buflen = 0;
-		list->count = 0;
-	}
-
-	stats = list->stats;
-	stats->glitchcnt = dtoh32(stats->glitchcnt);
-	stats->badplcp = dtoh32(stats->badplcp);
-	stats->chanspec = dtoh16(stats->chanspec);
-	stats->timestamp = dtoh32(stats->timestamp);
-	stats->chan_idle = dtoh32(stats->chan_idle);
-
-	WL_INFORM(("chanspec: 0x%4x glitch: %d badplcp: %d idle: %d timestamp: %d\n",
-		stats->chanspec, stats->glitchcnt, stats->badplcp, stats->chan_idle,
-		stats->timestamp));
-
-	*chan_idle = stats->chan_idle;
-
-	return (err);
-}
-
-static int
-wl_android_get_connection_stats(struct net_device *dev, char *command, int total_len)
-{
-	wl_cnt_t* cnt = NULL;
-#ifndef DISABLE_IF_COUNTERS
-	wl_if_stats_t* if_stats = NULL;
-#endif /* DISABLE_IF_COUNTERS */
-
-	int link_speed = 0;
-	struct connection_stats *output;
-	unsigned int bufsize = 0;
-	int bytes_written = -1;
-	int ret = 0;
-
-	WL_INFORM(("%s: enter Get Connection Stats\n", __FUNCTION__));
-
-	if (total_len <= 0) {
-		WL_ERR(("%s: invalid buffer size %d\n", __FUNCTION__, total_len));
-		goto error;
-	}
-
-	bufsize = total_len;
-	if (bufsize < sizeof(struct connection_stats)) {
-		WL_ERR(("%s: not enough buffer size, provided=%u, requires=%zu\n",
-			__FUNCTION__, bufsize,
-			sizeof(struct connection_stats)));
-		goto error;
-	}
-
-	output = (struct connection_stats *)command;
-
-#ifndef DISABLE_IF_COUNTERS
-	if ((if_stats = kmalloc(sizeof(*if_stats), GFP_KERNEL)) == NULL) {
-		WL_ERR(("%s(%d): kmalloc failed\n", __FUNCTION__, __LINE__));
-		goto error;
-	}
-	memset(if_stats, 0, sizeof(*if_stats));
-
-	ret = wldev_iovar_getbuf(dev, "if_counters", NULL, 0,
-		(char *)if_stats, sizeof(*if_stats), NULL);
-	if (ret) {
-		WL_ERR(("%s: if_counters not supported ret=%d\n",
-			__FUNCTION__, ret));
-
-		/* In case if_stats IOVAR is not supported, get information from counters. */
-#endif /* DISABLE_IF_COUNTERS */
-		if ((cnt = kmalloc(sizeof(*cnt), GFP_KERNEL)) == NULL) {
-			WL_ERR(("%s(%d): kmalloc failed\n", __FUNCTION__, __LINE__));
-			goto error;
-		}
-		memset(cnt, 0, sizeof(*cnt));
-
-		ret = wldev_iovar_getbuf(dev, "counters", NULL, 0,
-			(char *)cnt, sizeof(wl_cnt_t), NULL);
-		if (ret) {
-			WL_ERR(("%s: wldev_iovar_getbuf() failed, ret=%d\n",
-				__FUNCTION__, ret));
-			goto error;
-		}
-
-		if (dtoh16(cnt->version) > WL_CNT_T_VERSION) {
-			WL_ERR(("%s: incorrect version of wl_cnt_t, expected=%u got=%u\n",
-				__FUNCTION__,  WL_CNT_T_VERSION, cnt->version));
-			goto error;
-		}
-
-		output->txframe   = dtoh32(cnt->txframe);
-		output->txbyte    = dtoh32(cnt->txbyte);
-		output->txerror   = dtoh32(cnt->txerror);
-		output->rxframe   = dtoh32(cnt->rxframe);
-		output->rxbyte    = dtoh32(cnt->rxbyte);
-		output->txfail    = dtoh32(cnt->txfail);
-		output->txretry   = dtoh32(cnt->txretry);
-		output->txretrie  = dtoh32(cnt->txretrie);
-		output->txrts     = dtoh32(cnt->txrts);
-		output->txnocts   = dtoh32(cnt->txnocts);
-		output->txexptime = dtoh32(cnt->txexptime);
-#ifndef DISABLE_IF_COUNTERS
-	} else {
-		/* Populate from if_stats. */
-		if (dtoh16(if_stats->version) > WL_IF_STATS_T_VERSION) {
-			WL_ERR(("%s: incorrect version of wl_if_stats_t, expected=%u got=%u\n",
-				__FUNCTION__,  WL_IF_STATS_T_VERSION, if_stats->version));
-			goto error;
-		}
-
-		output->txframe   = (uint32)dtoh64(if_stats->txframe);
-		output->txbyte    = (uint32)dtoh64(if_stats->txbyte);
-		output->txerror   = (uint32)dtoh64(if_stats->txerror);
-		output->rxframe   = (uint32)dtoh64(if_stats->rxframe);
-		output->rxbyte    = (uint32)dtoh64(if_stats->rxbyte);
-		output->txfail    = (uint32)dtoh64(if_stats->txfail);
-		output->txretry   = (uint32)dtoh64(if_stats->txretry);
-		output->txretrie  = (uint32)dtoh64(if_stats->txretrie);
-		/* Unavailable */
-		output->txrts     = 0;
-		output->txnocts   = 0;
-		output->txexptime = 0;
-	}
-#endif /* DISABLE_IF_COUNTERS */
-
-	/* link_speed is in kbps */
-	ret = wldev_get_link_speed(dev, &link_speed);
-	if (ret || link_speed < 0) {
-		WL_ERR(("%s: wldev_get_link_speed() failed, ret=%d, speed=%d\n",
-			__FUNCTION__, ret, link_speed));
-		goto error;
-	}
-
-	output->txrate    = link_speed;
-
-	/* Channel idle ratio. */
-	if (wl_chanim_stats(dev, &(output->chan_idle)) < 0) {
-		output->chan_idle = 0;
-	};
-
-	bytes_written = sizeof(struct connection_stats);
-
-error:
-#ifndef DISABLE_IF_COUNTERS
-	if (if_stats) {
-		kfree(if_stats);
-	}
-#endif /* DISABLE_IF_COUNTERS */
-	if (cnt) {
-		kfree(cnt);
-	}
-
-	return bytes_written;
-}
-#endif /* CONNECTION_STATISTICS */
-
-
-#ifdef CUSTOMER_HW4_PRIVATE_CMD
-#endif /* CUSTOMER_HW4_PRIVATE_CMD */
-
-/* SoftAP feature */
-#define APCS_BAND_2G_LEGACY1	20
-#define APCS_BAND_2G_LEGACY2	0
-#define APCS_BAND_AUTO		"band=auto"
-#define APCS_BAND_2G		"band=2g"
-#define APCS_BAND_5G		"band=5g"
-#define APCS_MAX_2G_CHANNELS	11
-#define APCS_MAX_RETRY		10
-#define APCS_DEFAULT_2G_CH	1
-#define APCS_DEFAULT_5G_CH	149
-#if defined(WL_SUPPORT_AUTO_CHANNEL)
-static int
-wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
-	char* command, int total_len)
-{
-	int channel = 0;
-	int chosen = 0;
-	int retry = 0;
-	int ret = 0;
-	int spect = 0;
-	u8 *reqbuf = NULL;
-	uint32 band = WLC_BAND_2G;
-	uint32 buf_size;
-
-	if (cmd_str) {
-		WL_INFORM(("Command: %s len:%d \n", cmd_str, (int)strlen(cmd_str)));
-		if (strncmp(cmd_str, APCS_BAND_AUTO, strlen(APCS_BAND_AUTO)) == 0) {
-			band = WLC_BAND_AUTO;
-		} else if (strncmp(cmd_str, APCS_BAND_5G, strlen(APCS_BAND_5G)) == 0) {
-			band = WLC_BAND_5G;
-		} else if (strncmp(cmd_str, APCS_BAND_2G, strlen(APCS_BAND_2G)) == 0) {
-			band = WLC_BAND_2G;
-		} else {
-			/*
-			 * For backward compatibility: Some platforms used to issue argument 20 or 0
-			 * to enforce the 2G channel selection
-			 */
-			channel = bcm_atoi(cmd_str);
-			if ((channel == APCS_BAND_2G_LEGACY1) ||
-				(channel == APCS_BAND_2G_LEGACY2)) {
-				band = WLC_BAND_2G;
-			} else {
-				WL_ERR(("Invalid argument\n"));
-				return -EINVAL;
-			}
-		}
-	} else {
-		/* If no argument is provided, default to 2G */
-		WL_ERR(("No argument given default to 2.4G scan\n"));
-		band = WLC_BAND_2G;
-	}
-	WL_INFORM(("HAPD_AUTO_CHANNEL = %d, band=%d \n", channel, band));
-
-	if ((ret = wldev_ioctl(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect), false)) < 0) {
-		WL_ERR(("ACS: error getting the spect\n"));
-		goto done;
-	}
-
-	if (spect > 0) {
-		/* If STA is connected, return is STA channel, else ACS can be issued,
-		 * set spect to 0 and proceed with ACS
-		 */
-		channel = wl_cfg80211_get_sta_channel();
-		if (channel) {
-			channel = (channel <= CH_MAX_2G_CHANNEL) ? channel : APCS_DEFAULT_2G_CH;
-			goto done2;
-		}
-
-		if ((ret = wl_cfg80211_set_spect(dev, 0) < 0)) {
-			WL_ERR(("ACS: error while setting spect\n"));
-			goto done;
-		}
-	}
-
-	reqbuf = kzalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
-	if (reqbuf == NULL) {
-		WL_ERR(("failed to allocate chanspec buffer\n"));
-		return -ENOMEM;
-	}
-
-	if (band == WLC_BAND_AUTO) {
-		WL_INFORM(("ACS full channel scan \n"));
-		reqbuf[0] = htod32(0);
-	} else if (band == WLC_BAND_5G) {
-		WL_INFORM(("ACS 5G band scan \n"));
-		if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
-			WL_ERR(("ACS 5g chanspec retreival failed! \n"));
-			goto done;
-		}
-	} else if (band == WLC_BAND_2G) {
-		/*
-		 * If channel argument is not provided/ argument 20 is provided,
-		 * Restrict channel to 2GHz, 20MHz BW, No SB
-		 */
-		WL_INFORM(("ACS 2G band scan \n"));
-		if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
-			WL_ERR(("ACS 2g chanspec retreival failed! \n"));
-			goto done;
-		}
-	} else {
-		WL_ERR(("ACS: No band chosen\n"));
-		goto done2;
-	}
-
-	buf_size = (band == WLC_BAND_AUTO) ? sizeof(int) : CHANSPEC_BUF_SIZE;
-	ret = wldev_ioctl(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf,
-		buf_size, true);
-	if (ret < 0) {
-		WL_ERR(("can't start auto channel scan, err = %d\n", ret));
-		channel = 0;
-		goto done;
-	}
-
-	/* Wait for auto channel selection, max 3000 ms */
-	if ((band == WLC_BAND_2G) || (band == WLC_BAND_5G)) {
-		OSL_SLEEP(500);
-	} else {
-		/*
-		 * Full channel scan at the minimum takes 1.2secs
-		 * even with parallel scan. max wait time: 3500ms
-		 */
-		OSL_SLEEP(1000);
-	}
-
-	retry = APCS_MAX_RETRY;
-	while (retry--) {
-		ret = wldev_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen,
-			sizeof(chosen), false);
-		if (ret < 0) {
-			chosen = 0;
-		} else {
-			chosen = dtoh32(chosen);
-		}
-
-		if (chosen) {
-			int chosen_band;
-			int apcs_band;
-#ifdef D11AC_IOTYPES
-			if (wl_cfg80211_get_ioctl_version() == 1) {
-				channel = LCHSPEC_CHANNEL((chanspec_t)chosen);
-			} else {
-				channel = CHSPEC_CHANNEL((chanspec_t)chosen);
-			}
-#else
-			channel = CHSPEC_CHANNEL((chanspec_t)chosen);
-#endif /* D11AC_IOTYPES */
-			apcs_band = (band == WLC_BAND_AUTO) ? WLC_BAND_2G : band;
-			chosen_band = (channel <= CH_MAX_2G_CHANNEL) ? WLC_BAND_2G : WLC_BAND_5G;
-			if (apcs_band == chosen_band) {
-				WL_ERR(("selected channel = %d\n", channel));
-				break;
-			}
-		}
-		WL_INFORM(("%d tried, ret = %d, chosen = 0x%x\n",
-			(APCS_MAX_RETRY - retry), ret, chosen));
-		OSL_SLEEP(250);
-	}
-
-done:
-	if ((retry == 0) || (ret < 0)) {
-		/* On failure, fallback to a default channel */
-		if ((band == WLC_BAND_5G)) {
-			channel = APCS_DEFAULT_5G_CH;
-		} else {
-			channel = APCS_DEFAULT_2G_CH;
-		}
-		WL_ERR(("ACS failed. Fall back to default channel (%d) \n", channel));
-	}
-done2:
-	if (spect > 0) {
-		if ((ret = wl_cfg80211_set_spect(dev, spect) < 0)) {
-			WL_ERR(("ACS: error while setting spect\n"));
-		}
-	}
-
-	if (reqbuf) {
-		kfree(reqbuf);
-	}
-
-	if (channel) {
-		snprintf(command, 4, "%d", channel);
-		WL_INFORM(("command result is %s \n", command));
-		return strlen(command);
-	} else {
-		return ret;
-	}
-}
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
-
-#ifdef CUSTOMER_HW4_PRIVATE_CMD
-
-
-#ifdef SUPPORT_SET_LPC
-static int
-wl_android_set_lpc(struct net_device *dev, const char* string_num)
-{
-	int lpc_enabled, ret;
-	s32 val = 1;
-
-	lpc_enabled = bcm_atoi(string_num);
-	DHD_INFO(("%s : HAPD_LPC_ENABLED = %d\n", __FUNCTION__, lpc_enabled));
-
-	ret = wldev_ioctl(dev, WLC_DOWN, &val, sizeof(s32), true);
-	if (ret < 0)
-		DHD_ERROR(("WLC_DOWN error %d\n", ret));
-
-	wldev_iovar_setint(dev, "lpc", lpc_enabled);
-
-	ret = wldev_ioctl(dev, WLC_UP, &val, sizeof(s32), true);
-	if (ret < 0)
-		DHD_ERROR(("WLC_UP error %d\n", ret));
-
-	return 1;
-}
-#endif /* SUPPORT_SET_LPC */
-
-static int
-wl_android_ch_res_rl(struct net_device *dev, bool change)
-{
-	int error = 0;
-	s32 srl = 7;
-	s32 lrl = 4;
-	printk("%s enter\n", __FUNCTION__);
-	if (change) {
-		srl = 4;
-		lrl = 2;
-	}
-	error = wldev_ioctl(dev, WLC_SET_SRL, &srl, sizeof(s32), true);
-	if (error) {
-		DHD_ERROR(("Failed to set SRL, error = %d\n", error));
-	}
-	error = wldev_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(s32), true);
-	if (error) {
-		DHD_ERROR(("Failed to set LRL, error = %d\n", error));
-	}
-	return error;
-}
-
-
-static int
-wl_android_rmc_enable(struct net_device *net, int rmc_enable)
-{
-	int err;
-
-	err = wldev_iovar_setint(net, "rmc_ackreq", rmc_enable);
-	return err;
-}
-
-static int
-wl_android_rmc_set_leader(struct net_device *dev, const char* straddr)
-{
-	int error  = BCME_OK;
-	char smbuf[WLC_IOCTL_SMLEN];
-	wl_rmc_entry_t rmc_entry;
-	DHD_INFO(("%s: Set new RMC leader %s\n", __FUNCTION__, straddr));
-
-	memset(&rmc_entry, 0, sizeof(wl_rmc_entry_t));
-	if (!bcm_ether_atoe(straddr, &rmc_entry.addr)) {
-		if (strlen(straddr) == 1 && bcm_atoi(straddr) == 0) {
-			DHD_INFO(("%s: Set auto leader selection mode\n", __FUNCTION__));
-			memset(&rmc_entry, 0, sizeof(wl_rmc_entry_t));
-		} else {
-			DHD_ERROR(("%s: No valid mac address provided\n",
-				__FUNCTION__));
-			return BCME_ERROR;
-		}
-	}
-
-	error = wldev_iovar_setbuf(dev, "rmc_ar", &rmc_entry, sizeof(wl_rmc_entry_t),
-		smbuf, sizeof(smbuf), NULL);
-
-	if (error != BCME_OK) {
-		DHD_ERROR(("%s: Unable to set RMC leader, error = %d\n",
-			__FUNCTION__, error));
-	}
-
-	return error;
-}
-
-static int wl_android_set_rmc_event(struct net_device *dev, char *command, int total_len)
-{
-	int err = 0;
-	int pid = 0;
-
-	if (sscanf(command, CMD_SET_RMC_EVENT " %d", &pid) <= 0) {
-		WL_ERR(("Failed to get Parameter from : %s\n", command));
-		return -1;
-	}
-
-	/* set pid, and if the event was happened, let's send a notification through netlink */
-	wl_cfg80211_set_rmc_pid(pid);
-
-	WL_DBG(("RMC pid=%d\n", pid));
-
-	return err;
-}
-
-int wl_android_get_singlecore_scan(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0;
-	int bytes_written = 0;
-	int mode = 0;
-
-	error = wldev_iovar_getint(dev, "scan_ps", &mode);
-	if (error) {
-		DHD_ERROR(("%s: Failed to get single core scan Mode, error = %d\n",
-			__FUNCTION__, error));
-		return -1;
-	}
-
-	bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_SCSCAN, mode);
-
-	return bytes_written;
-}
-
-int wl_android_set_singlecore_scan(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0;
-	int mode = 0;
-
-	if (sscanf(command, "%*s %d", &mode) != 1) {
-		DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
-		return -1;
-	}
-
-	error = wldev_iovar_setint(dev, "scan_ps", mode);
-	if (error) {
-		DHD_ERROR(("%s[1]: Failed to set Mode %d, error = %d\n",
-		__FUNCTION__, mode, error));
-		return -1;
-	}
-
-	return error;
-}
-#ifdef TEST_TX_POWER_CONTROL
-static int
-wl_android_set_tx_power(struct net_device *dev, const char* string_num)
-{
-	int err = 0;
-	s32 dbm;
-	enum nl80211_tx_power_setting type;
-
-	dbm = bcm_atoi(string_num);
-
-	if (dbm < -1) {
-		DHD_ERROR(("%s: dbm is negative...\n", __FUNCTION__));
-		return -EINVAL;
-	}
-
-	if (dbm == -1)
-		type = NL80211_TX_POWER_AUTOMATIC;
-	else
-		type = NL80211_TX_POWER_FIXED;
-
-	err = wl_set_tx_power(dev, type, dbm);
-	if (unlikely(err)) {
-		DHD_ERROR(("%s: error (%d)\n", __FUNCTION__, err));
-		return err;
-	}
-
-	return 1;
-}
-
-static int
-wl_android_get_tx_power(struct net_device *dev, char *command, int total_len)
-{
-	int err;
-	int bytes_written;
-	s32 dbm = 0;
-
-	err = wl_get_tx_power(dev, &dbm);
-	if (unlikely(err)) {
-		DHD_ERROR(("%s: error (%d)\n", __FUNCTION__, err));
-		return err;
-	}
-
-	bytes_written = snprintf(command, total_len, "%s %d",
-		CMD_TEST_GET_TX_POWER, dbm);
-
-	DHD_ERROR(("%s: GET_TX_POWER: dBm=%d\n", __FUNCTION__, dbm));
-
-	return bytes_written;
-}
-#endif /* TEST_TX_POWER_CONTROL */
-
-static int
-wl_android_set_sarlimit_txctrl(struct net_device *dev, const char* string_num)
-{
-	int err = 0;
-	int setval = 0;
-	s32 mode = bcm_atoi(string_num);
-
-	/* As Samsung specific and their requirement, '0' means activate sarlimit
-	 * and '-1' means back to normal state (deactivate sarlimit)
-	 */
-	if (mode == 0) {
-		DHD_INFO(("%s: SAR limit control activated\n", __FUNCTION__));
-		setval = 1;
-	} else if (mode == -1) {
-		DHD_INFO(("%s: SAR limit control deactivated\n", __FUNCTION__));
-		setval = 0;
-	} else {
-		return -EINVAL;
-	}
-
-	err = wldev_iovar_setint(dev, "sar_enable", setval);
-	if (unlikely(err)) {
-		DHD_ERROR(("%s: error (%d)\n", __FUNCTION__, err));
-		return err;
-	}
-	return 1;
-}
-#endif /* CUSTOMER_HW4_PRIVATE_CMD */
-
-int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0;
-	int mode = 0;
-
-	if (sscanf(command, "%*s %d", &mode) != 1) {
-		DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
-		return -1;
-	}
-
-	error = wldev_iovar_setint(dev, "roam_off", mode);
-	if (error) {
-		DHD_ERROR(("%s: Failed to set roaming Mode %d, error = %d\n",
-		__FUNCTION__, mode, error));
-		return -1;
-	}
-	else
-		DHD_ERROR(("%s: succeeded to set roaming Mode %d, error = %d\n",
-		__FUNCTION__, mode, error));
-	return 0;
-}
-
-int wl_android_set_ibss_beacon_ouidata(struct net_device *dev, char *command, int total_len)
-{
-	char ie_buf[VNDR_IE_MAX_LEN];
-	char *ioctl_buf = NULL;
-	char hex[] = "XX";
-	char *pcmd = NULL;
-	int ielen = 0, datalen = 0, idx = 0, tot_len = 0;
-	vndr_ie_setbuf_t *vndr_ie = NULL;
-	s32 iecount;
-	uint32 pktflag;
-	u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
-	s32 err = BCME_OK;
-
-	/* Check the VSIE (Vendor Specific IE) which was added.
-	 *  If exist then send IOVAR to delete it
-	 */
-	if (wl_cfg80211_ibss_vsie_delete(dev) != BCME_OK) {
-		return -EINVAL;
-	}
-
-	pcmd = command + strlen(CMD_SETIBSSBEACONOUIDATA) + 1;
-	for (idx = 0; idx < DOT11_OUI_LEN; idx++) {
-		hex[0] = *pcmd++;
-		hex[1] = *pcmd++;
-		ie_buf[idx] =  (uint8)simple_strtoul(hex, NULL, 16);
-	}
-	pcmd++;
-	while ((*pcmd != '\0') && (idx < VNDR_IE_MAX_LEN)) {
-		hex[0] = *pcmd++;
-		hex[1] = *pcmd++;
-		ie_buf[idx++] =  (uint8)simple_strtoul(hex, NULL, 16);
-		datalen++;
-	}
-	tot_len = sizeof(vndr_ie_setbuf_t) + (datalen - 1);
-	vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, kflags);
-	if (!vndr_ie) {
-		WL_ERR(("IE memory alloc failed\n"));
-		return -ENOMEM;
-	}
-	/* Copy the vndr_ie SET command ("add"/"del") to the buffer */
-	strncpy(vndr_ie->cmd, "add", VNDR_IE_CMD_LEN - 1);
-	vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
-
-	/* Set the IE count - the buffer contains only 1 IE */
-	iecount = htod32(1);
-	memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
-
-	/* Set packet flag to indicate that BEACON's will contain this IE */
-	pktflag = htod32(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG);
-	memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
-		sizeof(u32));
-	/* Set the IE ID */
-	vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar) DOT11_MNG_PROPR_ID;
-
-	memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, &ie_buf,
-		DOT11_OUI_LEN);
-	memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data,
-		&ie_buf[DOT11_OUI_LEN], datalen);
-
-	ielen = DOT11_OUI_LEN + datalen;
-	vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen;
-
-	ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
-	if (!ioctl_buf) {
-		WL_ERR(("ioctl memory alloc failed\n"));
-		if (vndr_ie) {
-			kfree(vndr_ie);
-		}
-		return -ENOMEM;
-	}
-	memset(ioctl_buf, 0, WLC_IOCTL_MEDLEN);	/* init the buffer */
-	err = wldev_iovar_setbuf(dev, "ie", vndr_ie, tot_len, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
-
-
-	if (err != BCME_OK) {
-		err = -EINVAL;
-		if (vndr_ie) {
-			kfree(vndr_ie);
-		}
-	}
-	else {
-		/* do NOT free 'vndr_ie' for the next process */
-		wl_cfg80211_ibss_vsie_set_buffer(vndr_ie, tot_len);
-	}
-
-	if (ioctl_buf) {
-		kfree(ioctl_buf);
-	}
-
-	return err;
-}
-
-#if defined(BCMFW_ROAM_ENABLE)
-static int
-wl_android_set_roampref(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0;
-	char smbuf[WLC_IOCTL_SMLEN];
-	uint8 buf[MAX_BUF_SIZE];
-	uint8 *pref = buf;
-	char *pcmd;
-	int num_ucipher_suites = 0;
-	int num_akm_suites = 0;
-	wpa_suite_t ucipher_suites[MAX_NUM_SUITES];
-	wpa_suite_t akm_suites[MAX_NUM_SUITES];
-	int num_tuples = 0;
-	int total_bytes = 0;
-	int total_len_left;
-	int i, j;
-	char hex[] = "XX";
-
-	pcmd = command + strlen(CMD_SET_ROAMPREF) + 1;
-	total_len_left = total_len - strlen(CMD_SET_ROAMPREF) + 1;
-
-	num_akm_suites = simple_strtoul(pcmd, NULL, 16);
-	/* Increment for number of AKM suites field + space */
-	pcmd += 3;
-	total_len_left -= 3;
-
-	/* check to make sure pcmd does not overrun */
-	if (total_len_left < (num_akm_suites * WIDTH_AKM_SUITE))
-		return -1;
-
-	memset(buf, 0, sizeof(buf));
-	memset(akm_suites, 0, sizeof(akm_suites));
-	memset(ucipher_suites, 0, sizeof(ucipher_suites));
-
-	/* Save the AKM suites passed in the command */
-	for (i = 0; i < num_akm_suites; i++) {
-		/* Store the MSB first, as required by join_pref */
-		for (j = 0; j < 4; j++) {
-			hex[0] = *pcmd++;
-			hex[1] = *pcmd++;
-			buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
-		}
-		memcpy((uint8 *)&akm_suites[i], buf, sizeof(uint32));
-	}
-
-	total_len_left -= (num_akm_suites * WIDTH_AKM_SUITE);
-	num_ucipher_suites = simple_strtoul(pcmd, NULL, 16);
-	/* Increment for number of cipher suites field + space */
-	pcmd += 3;
-	total_len_left -= 3;
-
-	if (total_len_left < (num_ucipher_suites * WIDTH_AKM_SUITE))
-		return -1;
-
-	/* Save the cipher suites passed in the command */
-	for (i = 0; i < num_ucipher_suites; i++) {
-		/* Store the MSB first, as required by join_pref */
-		for (j = 0; j < 4; j++) {
-			hex[0] = *pcmd++;
-			hex[1] = *pcmd++;
-			buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
-		}
-		memcpy((uint8 *)&ucipher_suites[i], buf, sizeof(uint32));
-	}
-
-	/* Join preference for RSSI
-	 * Type	  : 1 byte (0x01)
-	 * Length : 1 byte (0x02)
-	 * Value  : 2 bytes	(reserved)
-	 */
-	*pref++ = WL_JOIN_PREF_RSSI;
-	*pref++ = JOIN_PREF_RSSI_LEN;
-	*pref++ = 0;
-	*pref++ = 0;
-
-	/* Join preference for WPA
-	 * Type	  : 1 byte (0x02)
-	 * Length : 1 byte (not used)
-	 * Value  : (variable length)
-	 *		reserved: 1 byte
-	 *      count	: 1 byte (no of tuples)
-	 *		Tuple1	: 12 bytes
-	 *			akm[4]
-	 *			ucipher[4]
-	 *			mcipher[4]
-	 *		Tuple2	: 12 bytes
-	 *		Tuplen	: 12 bytes
-	 */
-	num_tuples = num_akm_suites * num_ucipher_suites;
-	if (num_tuples != 0) {
-		if (num_tuples <= JOIN_PREF_MAX_WPA_TUPLES) {
-			*pref++ = WL_JOIN_PREF_WPA;
-			*pref++ = 0;
-			*pref++ = 0;
-			*pref++ = (uint8)num_tuples;
-			total_bytes = JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE +
-				(JOIN_PREF_WPA_TUPLE_SIZE * num_tuples);
-		} else {
-			DHD_ERROR(("%s: Too many wpa configs for join_pref \n", __FUNCTION__));
-			return -1;
-		}
-	} else {
-		/* No WPA config, configure only RSSI preference */
-		total_bytes = JOIN_PREF_RSSI_SIZE;
-	}
-
-	/* akm-ucipher-mcipher tuples in the format required for join_pref */
-	for (i = 0; i < num_ucipher_suites; i++) {
-		for (j = 0; j < num_akm_suites; j++) {
-			memcpy(pref, (uint8 *)&akm_suites[j], WPA_SUITE_LEN);
-			pref += WPA_SUITE_LEN;
-			memcpy(pref, (uint8 *)&ucipher_suites[i], WPA_SUITE_LEN);
-			pref += WPA_SUITE_LEN;
-			/* Set to 0 to match any available multicast cipher */
-			memset(pref, 0, WPA_SUITE_LEN);
-			pref += WPA_SUITE_LEN;
-		}
-	}
-
-	prhex("join pref", (uint8 *)buf, total_bytes);
-	error = wldev_iovar_setbuf(dev, "join_pref", buf, total_bytes, smbuf, sizeof(smbuf), NULL);
-	if (error) {
-		DHD_ERROR(("Failed to set join_pref, error = %d\n", error));
-	}
-	return error;
-}
-#endif /* defined(BCMFW_ROAM_ENABLE */
-
-static int
-wl_android_iolist_add(struct net_device *dev, struct list_head *head, struct io_cfg *config)
-{
-	struct io_cfg *resume_cfg;
-	s32 ret;
-
-	resume_cfg = kzalloc(sizeof(struct io_cfg), GFP_KERNEL);
-	if (!resume_cfg)
-		return -ENOMEM;
-
-	if (config->iovar) {
-		ret = wldev_iovar_getint(dev, config->iovar, &resume_cfg->param);
-		if (ret) {
-			DHD_ERROR(("%s: Failed to get current %s value\n",
-				__FUNCTION__, config->iovar));
-			goto error;
-		}
-
-		ret = wldev_iovar_setint(dev, config->iovar, config->param);
-		if (ret) {
-			DHD_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
-				config->iovar, config->param));
-			goto error;
-		}
-
-		resume_cfg->iovar = config->iovar;
-	} else {
-		resume_cfg->arg = kzalloc(config->len, GFP_KERNEL);
-		if (!resume_cfg->arg) {
-			ret = -ENOMEM;
-			goto error;
-		}
-		ret = wldev_ioctl(dev, config->ioctl, resume_cfg->arg, config->len, false);
-		if (ret) {
-			DHD_ERROR(("%s: Failed to get ioctl %d\n", __FUNCTION__,
-				config->ioctl));
-			goto error;
-		}
-		ret = wldev_ioctl(dev, config->ioctl + 1, config->arg, config->len, true);
-		if (ret) {
-			DHD_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
-				config->iovar, config->param));
-			goto error;
-		}
-		if (config->ioctl + 1 == WLC_SET_PM)
-			wl_cfg80211_update_power_mode(dev);
-		resume_cfg->ioctl = config->ioctl;
-		resume_cfg->len = config->len;
-	}
-
-	list_add(&resume_cfg->list, head);
-
-	return 0;
-error:
-	kfree(resume_cfg->arg);
-	kfree(resume_cfg);
-	return ret;
-}
-
-static void
-wl_android_iolist_resume(struct net_device *dev, struct list_head *head)
-{
-	struct io_cfg *config;
-	struct list_head *cur, *q;
-	s32 ret = 0;
-
-	list_for_each_safe(cur, q, head) {
-		config = list_entry(cur, struct io_cfg, list);
-		if (config->iovar) {
-			if (!ret)
-				ret = wldev_iovar_setint(dev, config->iovar,
-					config->param);
-		} else {
-			if (!ret)
-				ret = wldev_ioctl(dev, config->ioctl + 1,
-					config->arg, config->len, true);
-			if (config->ioctl + 1 == WLC_SET_PM)
-				wl_cfg80211_update_power_mode(dev);
-			kfree(config->arg);
-		}
-		list_del(cur);
-		kfree(config);
-	}
-}
-#ifdef WL11ULB
-static int
-wl_android_set_ulb_mode(struct net_device *dev, char *command, int total_len)
-{
-	int mode = 0;
-
-	DHD_INFO(("set ulb mode (%s) \n", command));
-	if (sscanf(command, "%*s %d", &mode) != 1) {
-		DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
-		return -1;
-	}
-	return wl_cfg80211_set_ulb_mode(dev, mode);
-}
-static int
-wl_android_set_ulb_bw(struct net_device *dev, char *command, int total_len)
-{
-	int bw = 0;
-	u8 *pos;
-	char *ifname = NULL;
-	DHD_INFO(("set ulb bw (%s) \n", command));
-
-	/*
-	 * For sta/ap: IFNAME=<ifname> DRIVER ULB_BW <bw> ifname
-	 * For p2p:    IFNAME=wlan0 DRIVER ULB_BW <bw> p2p-dev-wlan0
-	 */
-	if (total_len < strlen(CMD_ULB_BW) + 2)
-		return -EINVAL;
-
-	pos = command + strlen(CMD_ULB_BW) + 1;
-	bw = bcm_atoi(pos);
-
-	if ((strlen(pos) >= 5)) {
-		ifname = pos + 2;
-	}
-
-	DHD_INFO(("[ULB] ifname:%s ulb_bw:%d \n", ifname, bw));
-	return wl_cfg80211_set_ulb_bw(dev, bw, ifname);
-}
-#endif /* WL11ULB */
-static int
-wl_android_set_miracast(struct net_device *dev, char *command, int total_len)
-{
-	int mode, val;
-	int ret = 0;
-	struct io_cfg config;
-
-	if (sscanf(command, "%*s %d", &mode) != 1) {
-		DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
-		return -1;
-	}
-
-	DHD_INFO(("%s: enter miracast mode %d\n", __FUNCTION__, mode));
-
-	if (miracast_cur_mode == mode) {
-		return 0;
-	}
-
-	wl_android_iolist_resume(dev, &miracast_resume_list);
-	miracast_cur_mode = MIRACAST_MODE_OFF;
-
-	switch (mode) {
-	case MIRACAST_MODE_SOURCE:
-		/* setting mchan_algo to platform specific value */
-		config.iovar = "mchan_algo";
-
-		ret = wldev_ioctl(dev, WLC_GET_BCNPRD, &val, sizeof(int), false);
-		if (!ret && val > 100) {
-			config.param = 0;
-			DHD_ERROR(("%s: Connected station's beacon interval: "
-				"%d and set mchan_algo to %d \n",
-				__FUNCTION__, val, config.param));
-		} else {
-			config.param = MIRACAST_MCHAN_ALGO;
-		}
-		ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-		if (ret) {
-			goto resume;
-		}
-
-		/* setting mchan_bw to platform specific value */
-		config.iovar = "mchan_bw";
-		config.param = MIRACAST_MCHAN_BW;
-		ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-		if (ret) {
-			goto resume;
-		}
-
-		/* setting apmdu to platform specific value */
-		config.iovar = "ampdu_mpdu";
-		config.param = MIRACAST_AMPDU_SIZE;
-		ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-		if (ret) {
-			goto resume;
-		}
-		/* FALLTROUGH */
-		/* Source mode shares most configurations with sink mode.
-		 * Fall through here to avoid code duplication
-		 */
-	case MIRACAST_MODE_SINK:
-		/* disable internal roaming */
-		config.iovar = "roam_off";
-		config.param = 1;
-		ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-		if (ret) {
-			goto resume;
-		}
-
-		/* tunr off pm */
-		ret = wldev_ioctl(dev, WLC_GET_PM, &val, sizeof(val), false);
-		if (ret) {
-			goto resume;
-		}
-
-		if (val != PM_OFF) {
-			val = PM_OFF;
-			config.iovar = NULL;
-			config.ioctl = WLC_GET_PM;
-			config.arg = &val;
-			config.len = sizeof(int);
-			ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-			if (ret) {
-				goto resume;
-			}
-		}
-		break;
-	case MIRACAST_MODE_OFF:
-	default:
-		break;
-	}
-	miracast_cur_mode = mode;
-
-	return 0;
-
-resume:
-	DHD_ERROR(("%s: turnoff miracast mode because of err%d\n", __FUNCTION__, ret));
-	wl_android_iolist_resume(dev, &miracast_resume_list);
-	return ret;
-}
-
-#define NETLINK_OXYGEN     30
-#define AIBSS_BEACON_TIMEOUT	10
-
-static struct sock *nl_sk = NULL;
-
-static void wl_netlink_recv(struct sk_buff *skb)
-{
-	WL_ERR(("netlink_recv called\n"));
-}
-
-static int wl_netlink_init(void)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
-	struct netlink_kernel_cfg cfg = {
-		.input	= wl_netlink_recv,
-	};
-#endif
-
-	if (nl_sk != NULL) {
-		WL_ERR(("nl_sk already exist\n"));
-		return BCME_ERROR;
-	}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
-	nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN,
-		0, wl_netlink_recv, NULL, THIS_MODULE);
-#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
-	nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, THIS_MODULE, &cfg);
-#else
-	nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, &cfg);
-#endif
-
-	if (nl_sk == NULL) {
-		WL_ERR(("nl_sk is not ready\n"));
-		return BCME_ERROR;
-	}
-
-	return BCME_OK;
-}
-
-static void wl_netlink_deinit(void)
-{
-	if (nl_sk) {
-		netlink_kernel_release(nl_sk);
-		nl_sk = NULL;
-	}
-}
-
-s32
-wl_netlink_send_msg(int pid, int type, int seq, void *data, size_t size)
-{
-	struct sk_buff *skb = NULL;
-	struct nlmsghdr *nlh = NULL;
-	int ret = -1;
-
-	if (nl_sk == NULL) {
-		WL_ERR(("nl_sk was not initialized\n"));
-		goto nlmsg_failure;
-	}
-
-	skb = alloc_skb(NLMSG_SPACE(size), GFP_ATOMIC);
-	if (skb == NULL) {
-		WL_ERR(("failed to allocate memory\n"));
-		goto nlmsg_failure;
-	}
-
-	nlh = nlmsg_put(skb, 0, 0, 0, size, 0);
-	if (nlh == NULL) {
-		WL_ERR(("failed to build nlmsg, skb_tailroom:%d, nlmsg_total_size:%d\n",
-			skb_tailroom(skb), nlmsg_total_size(size)));
-		dev_kfree_skb(skb);
-		goto nlmsg_failure;
-	}
-
-	memcpy(nlmsg_data(nlh), data, size);
-	nlh->nlmsg_seq = seq;
-	nlh->nlmsg_type = type;
-
-	/* netlink_unicast() takes ownership of the skb and frees it itself. */
-	ret = netlink_unicast(nl_sk, skb, pid, 0);
-	WL_DBG(("netlink_unicast() pid=%d, ret=%d\n", pid, ret));
-
-nlmsg_failure:
-	return ret;
-}
-
-
-int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len)
-{
-	char 				buf[256];
-	const char 			*str;
-	wl_mkeep_alive_pkt_t	mkeep_alive_pkt;
-	wl_mkeep_alive_pkt_t	*mkeep_alive_pktp;
-	int					buf_len;
-	int					str_len;
-	int res 				= -1;
-	uint period_msec = 0;
-
-	if (extra == NULL)
-	{
-		 DHD_ERROR(("%s: extra is NULL\n", __FUNCTION__));
-		 return -1;
-	}
-	if (sscanf(extra, "%d", &period_msec) != 1)
-	{
-		 DHD_ERROR(("%s: sscanf error. check period_msec value\n", __FUNCTION__));
-		 return -EINVAL;
-	}
-	DHD_ERROR(("%s: period_msec is %d\n", __FUNCTION__, period_msec));
-
-	memset(&mkeep_alive_pkt, 0, sizeof(wl_mkeep_alive_pkt_t));
-
-	str = "mkeep_alive";
-	str_len = strlen(str);
-	strncpy(buf, str, str_len);
-	buf[ str_len ] = '\0';
-	mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1);
-	mkeep_alive_pkt.period_msec = period_msec;
-	buf_len = str_len + 1;
-	mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION);
-	mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
-
-	/* Setup keep alive zero for null packet generation */
-	mkeep_alive_pkt.keep_alive_id = 0;
-	mkeep_alive_pkt.len_bytes = 0;
-	buf_len += WL_MKEEP_ALIVE_FIXED_LEN;
-	/* Keep-alive attributes are set in local	variable (mkeep_alive_pkt), and
-	 * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no
-	 * guarantee that the buffer is properly aligned.
-	 */
-	memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN);
-
-	if ((res = wldev_ioctl(dev, WLC_SET_VAR, buf, buf_len, TRUE)) < 0)
-	{
-		DHD_ERROR(("%s:keep_alive set failed. res[%d]\n", __FUNCTION__, res));
-	}
-	else
-	{
-		DHD_ERROR(("%s:keep_alive set ok. res[%d]\n", __FUNCTION__, res));
-	}
-
-	return res;
-}
-
-static const char *
-get_string_by_separator(char *result, int result_len, const char *src, char separator)
-{
-	char *end = result + result_len - 1;
-	while ((result != end) && (*src != separator) && (*src)) {
-		*result++ = *src++;
-	}
-	*result = 0;
-	if (*src == separator) {
-		++src;
-	}
-	return src;
-}
-
-int
-wl_android_set_roam_offload_bssid_list(struct net_device *dev, const char *cmd)
-{
-	char sbuf[32];
-	int i, cnt, size, err, ioctl_buf_len;
-	roamoffl_bssid_list_t *bssid_list;
-	const char *str = cmd;
-	char *ioctl_buf;
-	dhd_pub_t *dhdp = wl_cfg80211_get_dhdp();
-
-	str = get_string_by_separator(sbuf, 32, str, ',');
-	cnt = bcm_atoi(sbuf);
-	cnt = MIN(cnt, MAX_ROAMOFFL_BSSID_NUM);
-
-	if ((cnt > 0) &&
-		(((dhdp->op_mode & DHD_FLAG_STA_MODE) && (dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
-		FALSE)) {
-		WL_ERR(("Can't set ROAMOFFL_BSSID when enabled STA-SoftAP or WES\n"));
-		return -EINVAL;
-	}
-
-	size = sizeof(int32) + sizeof(struct ether_addr) * cnt;
-	WL_ERR(("ROAM OFFLOAD BSSID LIST %d BSSIDs, size %d\n", cnt, size));
-	bssid_list = kmalloc(size, GFP_KERNEL);
-	if (bssid_list == NULL) {
-		WL_ERR(("%s: memory alloc for bssid list(%d) failed\n",
-			__FUNCTION__, size));
-		return -ENOMEM;
-	}
-	ioctl_buf_len = size + 64;
-	ioctl_buf = kmalloc(ioctl_buf_len, GFP_KERNEL);
-	if (ioctl_buf == NULL) {
-		WL_ERR(("%s: memory alloc for ioctl_buf(%d) failed\n",
-			__FUNCTION__, ioctl_buf_len));
-		kfree(bssid_list);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < cnt; i++) {
-		str = get_string_by_separator(sbuf, 32, str, ',');
-		bcm_ether_atoe(sbuf, &bssid_list->bssid[i]);
-	}
-
-	bssid_list->cnt = (int32)cnt;
-	err = wldev_iovar_setbuf(dev, "roamoffl_bssid_list",
-			bssid_list, size, ioctl_buf, ioctl_buf_len, NULL);
-	kfree(bssid_list);
-	kfree(ioctl_buf);
-
-	return err;
-}
-
-#ifdef P2PRESP_WFDIE_SRC
-static int wl_android_get_wfdie_resp(struct net_device *dev, char *command, int total_len)
-{
-	int error = 0;
-	int bytes_written = 0;
-	int only_resp_wfdsrc = 0;
-
-	error = wldev_iovar_getint(dev, "p2p_only_resp_wfdsrc", &only_resp_wfdsrc);
-	if (error) {
-		DHD_ERROR(("%s: Failed to get the mode for only_resp_wfdsrc, error = %d\n",
-			__FUNCTION__, error));
-		return -1;
-	}
-
-	bytes_written = snprintf(command, total_len, "%s %d",
-		CMD_P2P_GET_WFDIE_RESP, only_resp_wfdsrc);
-
-	return bytes_written;
-}
-
-static int wl_android_set_wfdie_resp(struct net_device *dev, int only_resp_wfdsrc)
-{
-	int error = 0;
-
-	error = wldev_iovar_setint(dev, "p2p_only_resp_wfdsrc", only_resp_wfdsrc);
-	if (error) {
-		DHD_ERROR(("%s: Failed to set only_resp_wfdsrc %d, error = %d\n",
-			__FUNCTION__, only_resp_wfdsrc, error));
-		return -1;
-	}
-
-	return 0;
-}
-#endif /* P2PRESP_WFDIE_SRC */
-
-#ifdef BT_WIFI_HANDOVER
-static int
-wl_tbow_teardown(struct net_device *dev, char *command, int total_len)
-{
-	int err = BCME_OK;
-	char buf[WLC_IOCTL_SMLEN];
-	tbow_setup_netinfo_t netinfo;
-	memset(&netinfo, 0, sizeof(netinfo));
-	netinfo.opmode = TBOW_HO_MODE_TEARDOWN;
-
-	err = wldev_iovar_setbuf_bsscfg(dev, "tbow_doho", &netinfo,
-			sizeof(tbow_setup_netinfo_t), buf, WLC_IOCTL_SMLEN, 0, NULL);
-	if (err < 0) {
-		WL_ERR(("tbow_doho iovar error %d\n", err));
-			return err;
-	}
-	return err;
-}
-#endif /* BT_WIFI_HANOVER */
-
-#ifdef SET_RPS_CPUS
-static int
-wl_android_set_rps_cpus(struct net_device *dev, char *command, int total_len)
-{
-	int error, enable;
-
-	enable = command[strlen(CMD_RPSMODE) + 1] - '0';
-	error = dhd_rps_cpus_enable(dev, enable);
-
-#if defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE) && defined(WL_CFG80211)
-	if (!error) {
-		void *dhdp = wl_cfg80211_get_dhdp();
-		if (enable) {
-			DHD_TRACE(("%s : set ack suppress. TCPACK_SUP_HOLD.\n", __FUNCTION__));
-			dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_HOLD);
-		} else {
-			DHD_TRACE(("%s : clear ack suppress.\n", __FUNCTION__));
-			dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF);
-		}
-	}
-#endif /* DHDTCPACK_SUPPRESS && BCMPCIE && WL_CFG80211 */
-
-	return error;
-}
-#endif /* SET_RPS_CPUS */
-#ifdef P2P_LISTEN_OFFLOADING
-s32
-wl_cfg80211_p2plo_offload(struct net_device *dev, char *cmd, char* buf, int len)
-{
-	int ret = 0;
-
-	WL_ERR(("Entry cmd:%s arg_len:%d \n", cmd, len));
-
-	if (strncmp(cmd, "P2P_LO_START", strlen("P2P_LO_START")) == 0) {
-		ret = wl_cfg80211_p2plo_listen_start(dev, buf, len);
-	} else if (strncmp(cmd, "P2P_LO_STOP", strlen("P2P_LO_STOP")) == 0) {
-		ret = wl_cfg80211_p2plo_listen_stop(dev);
-	} else {
-		WL_ERR(("Request for Unsupported CMD:%s \n", buf));
-		ret = -EINVAL;
-	}
-	return ret;
-}
-#endif /* P2P_LISTEN_OFFLOADING */
-
-int
-wl_android_murx_bfe_cap(struct net_device *dev, int val)
-{
-	int err = BCME_OK;
-	int iface_count = wl_cfg80211_iface_count();
-
-	if (iface_count > 1) {
-		DHD_ERROR(("%s: murx_bfe_cap change is not allowed when "
-				"there are multiple interfaces\n", __FUNCTION__));
-		return -EINVAL;
-	}
-	/* Now there is only single interface */
-	err = wldev_iovar_setint(dev, "murx_bfe_cap", val);
-	if (err) {
-		DHD_ERROR(("%s: Failed to set murx_bfe_cap IOVAR to %d,"
-				"error %d\n", __FUNCTION__, val, err));
-		err = -EINVAL;
-	}
-	return err;
-}
-
-int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
-{
-#define PRIVATE_COMMAND_MAX_LEN	8192
-	int ret = 0;
-	char *command = NULL;
-	int bytes_written = 0;
-	android_wifi_priv_cmd priv_cmd;
-
-	net_os_wake_lock(net);
-
-	if (!ifr->ifr_data) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-#ifdef CONFIG_COMPAT
-	if (is_compat_task()) {
-		compat_android_wifi_priv_cmd compat_priv_cmd;
-		if (copy_from_user(&compat_priv_cmd, ifr->ifr_data,
-			sizeof(compat_android_wifi_priv_cmd))) {
-			ret = -EFAULT;
-			goto exit;
-
-		}
-		priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
-		priv_cmd.used_len = compat_priv_cmd.used_len;
-		priv_cmd.total_len = compat_priv_cmd.total_len;
-	} else
-#endif /* CONFIG_COMPAT */
-	{
-		if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
-			ret = -EFAULT;
-			goto exit;
-		}
-	}
-	if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) {
-		DHD_ERROR(("%s: too long priavte command\n", __FUNCTION__));
-		ret = -EINVAL;
-		goto exit;
-	}
-	command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL);
-	if (!command)
-	{
-		DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__));
-		ret = -ENOMEM;
-		goto exit;
-	}
-	if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
-		ret = -EFAULT;
-		goto exit;
-	}
-	command[priv_cmd.total_len] = '\0';
-
-	DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name));
-
-	if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) {
-		DHD_INFO(("%s, Received regular START command\n", __FUNCTION__));
-		bytes_written = wl_android_wifi_on(net);
-	}
-	else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) {
-		bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len);
-	}
-
-	if (!g_wifi_on) {
-		DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n",
-			__FUNCTION__, command, ifr->ifr_name));
-		ret = 0;
-		goto exit;
-	}
-
-	if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) {
-		bytes_written = wl_android_wifi_off(net, FALSE);
-	}
-	else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) {
-		wl_cfg80211_set_passive_scan(net, command);
-	}
-	else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) {
-		wl_cfg80211_set_passive_scan(net, command);
-	}
-	else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) {
-		bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) {
-		bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len);
-	}
-#ifdef PKT_FILTER_SUPPORT
-	else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) {
-		bytes_written = net_os_enable_packet_filter(net, 1);
-	}
-	else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) {
-		bytes_written = net_os_enable_packet_filter(net, 0);
-	}
-	else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) {
-		int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
-		bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
-	}
-	else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) {
-		int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
-		bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
-	}
-#endif /* PKT_FILTER_SUPPORT */
-	else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) {
-		/* TBD: BTCOEXSCAN-START */
-	}
-	else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) {
-		/* TBD: BTCOEXSCAN-STOP */
-	}
-	else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) {
-#ifdef WL_CFG80211
-		void *dhdp = wl_cfg80211_get_dhdp();
-		bytes_written = wl_cfg80211_set_btcoex_dhcp(net, dhdp, command);
-#else
-#ifdef PKT_FILTER_SUPPORT
-		uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
-
-		if (mode == 1)
-			net_os_enable_packet_filter(net, 0); /* DHCP starts */
-		else
-			net_os_enable_packet_filter(net, 1); /* DHCP ends */
-#endif /* PKT_FILTER_SUPPORT */
-#endif /* WL_CFG80211 */
-	}
-	else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) {
-		bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) {
-		bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
-		uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
-		bytes_written = wldev_set_band(net, band);
-	}
-	else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) {
-		bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
-	}
-#ifdef WL_CFG80211
-	/* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */
-	else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
-		/*
-		 * Usage examples:
-		 * DRIVER COUNTRY US
-		 * DRIVER COUNTRY US/7
-		 */
-		char *country_code = command + strlen(CMD_COUNTRY) + 1;
-		char *rev_info_delim = country_code + 2; /* 2 bytes of country code */
-		int revinfo = -1;
-		if ((rev_info_delim) &&
-			(strnicmp(rev_info_delim, CMD_COUNTRY_DELIMITER,
-			strlen(CMD_COUNTRY_DELIMITER)) == 0) &&
-			(rev_info_delim + 1)) {
-			revinfo  = bcm_atoi(rev_info_delim + 1);
-		}
-		bytes_written = wldev_set_country(net, country_code, true, true, revinfo);
-#ifdef FCC_PWR_LIMIT_2G
-		if (wldev_iovar_setint(net, "fccpwrlimit2g", FALSE)) {
-			DHD_ERROR(("%s: fccpwrlimit2g deactivation is failed\n", __FUNCTION__));
-		} else {
-			DHD_ERROR(("%s: fccpwrlimit2g is deactivated\n", __FUNCTION__));
-		}
-#endif /* FCC_PWR_LIMIT_2G */
-	}
-#endif /* WL_CFG80211 */
-	else if (strnicmp(command, CMD_SET_CSA, strlen(CMD_SET_CSA)) == 0) {
-		bytes_written = wl_android_set_csa(net, command, priv_cmd.total_len);
-	} else if (strnicmp(command, CMD_80211_MODE, strlen(CMD_80211_MODE)) == 0) {
-		bytes_written = wl_android_get_80211_mode(net, command, priv_cmd.total_len);
-	} else if (strnicmp(command, CMD_CHANSPEC, strlen(CMD_CHANSPEC)) == 0) {
-		bytes_written = wl_android_get_chanspec(net, command, priv_cmd.total_len);
-	} else if (strnicmp(command, CMD_DATARATE, strlen(CMD_DATARATE)) == 0) {
-		bytes_written = wl_android_get_datarate(net, command, priv_cmd.total_len);
-	} else if (strnicmp(command, CMD_ASSOC_CLIENTS,	strlen(CMD_ASSOC_CLIENTS)) == 0) {
-		bytes_written = wl_android_get_assoclist(net, command, priv_cmd.total_len);
-	}
-
-#ifdef CUSTOMER_HW4_PRIVATE_CMD
-#ifdef WLTDLS
-	else if (strnicmp(command, CMD_TDLS_RESET, strlen(CMD_TDLS_RESET)) == 0) {
-		bytes_written = wl_android_tdls_reset(net);
-	}
-#endif /* WLTDLS */
-#endif /* CUSTOMER_HW4_PRIVATE_CMD */
-
-#ifdef PNO_SUPPORT
-	else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
-		bytes_written = dhd_dev_pno_stop_for_ssid(net);
-	}
-#ifndef WL_SCHED_SCAN
-	else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) {
-		bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len);
-	}
-#endif /* !WL_SCHED_SCAN */
-	else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) {
-		int enable = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
-		bytes_written = (enable)? 0 : dhd_dev_pno_stop_for_ssid(net);
-	}
-	else if (strnicmp(command, CMD_WLS_BATCHING, strlen(CMD_WLS_BATCHING)) == 0) {
-		bytes_written = wls_parse_batching_cmd(net, command, priv_cmd.total_len);
-	}
-#endif /* PNO_SUPPORT */
-	else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
-		bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) {
-		int skip = strlen(CMD_P2P_SET_NOA) + 1;
-		bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
-			priv_cmd.total_len - skip);
-	}
-#ifdef P2P_LISTEN_OFFLOADING
-	else if (strnicmp(command, CMD_P2P_LISTEN_OFFLOAD, strlen(CMD_P2P_LISTEN_OFFLOAD)) == 0) {
-		u8 *sub_command = strchr(command, ' ');
-		bytes_written = wl_cfg80211_p2plo_offload(net, command, sub_command,
-				sub_command ? strlen(sub_command) : 0);
-	}
-#endif /* P2P_LISTEN_OFFLOADING */
-#ifdef WL_NAN
-	else if (strnicmp(command, CMD_NAN, strlen(CMD_NAN)) == 0) {
-		bytes_written = wl_cfg80211_nan_cmd_handler(net, command,
-			priv_cmd.total_len);
-	}
-#endif /* WL_NAN */
-#if !defined WL_ENABLE_P2P_IF
-	else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) {
-		bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
-	}
-#endif /* WL_ENABLE_P2P_IF */
-	else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) {
-		int skip = strlen(CMD_P2P_SET_PS) + 1;
-		bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip,
-			priv_cmd.total_len - skip);
-	}
-	else if (strnicmp(command, CMD_P2P_ECSA, strlen(CMD_P2P_ECSA)) == 0) {
-		int skip = strlen(CMD_P2P_ECSA) + 1;
-		bytes_written = wl_cfg80211_set_p2p_ecsa(net, command + skip,
-			priv_cmd.total_len - skip);
-	}
-#ifdef WL_CFG80211
-	else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE,
-		strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) {
-		int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3;
-		bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
-			priv_cmd.total_len - skip, *(command + skip - 2) - '0');
-	}
-#endif /* WL_CFG80211 */
-#if defined(WL_SUPPORT_AUTO_CHANNEL)
-	else if (strnicmp(command, CMD_GET_BEST_CHANNELS,
-		strlen(CMD_GET_BEST_CHANNELS)) == 0) {
-		bytes_written = wl_cfg80211_get_best_channels(net, command,
-			priv_cmd.total_len);
-	}
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
-#if defined(WL_SUPPORT_AUTO_CHANNEL)
-	else if (strnicmp(command, CMD_SET_HAPD_AUTO_CHANNEL,
-		strlen(CMD_SET_HAPD_AUTO_CHANNEL)) == 0) {
-		int skip = strlen(CMD_SET_HAPD_AUTO_CHANNEL) + 1;
-		bytes_written = wl_android_set_auto_channel(net, (const char*)command+skip, command,
-			priv_cmd.total_len);
-	}
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
-#ifdef CUSTOMER_HW4_PRIVATE_CMD
-#ifdef SUPPORT_SET_LPC
-	else if (strnicmp(command, CMD_HAPD_LPC_ENABLED,
-		strlen(CMD_HAPD_LPC_ENABLED)) == 0) {
-		int skip = strlen(CMD_HAPD_LPC_ENABLED) + 3;
-		wl_android_set_lpc(net, (const char*)command+skip);
-	}
-#endif /* SUPPORT_SET_LPC */
-#ifdef SUPPORT_TRIGGER_HANG_EVENT
-	else if (strnicmp(command, CMD_TEST_FORCE_HANG,
-		strlen(CMD_TEST_FORCE_HANG)) == 0) {
-		int skip = strlen(CMD_TEST_FORCE_HANG) + 1;
-		net_os_send_hang_message_reason(net, (const char*)command+skip);
-	}
-#endif /* SUPPORT_TRIGGER_HANG_EVENT */
-	else if (strnicmp(command, CMD_CHANGE_RL, strlen(CMD_CHANGE_RL)) == 0)
-		bytes_written = wl_android_ch_res_rl(net, true);
-	else if (strnicmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0)
-		bytes_written = wl_android_ch_res_rl(net, false);
-	else if (strnicmp(command, CMD_SET_RMC_ENABLE, strlen(CMD_SET_RMC_ENABLE)) == 0) {
-		int rmc_enable = *(command + strlen(CMD_SET_RMC_ENABLE) + 1) - '0';
-		bytes_written = wl_android_rmc_enable(net, rmc_enable);
-	}
-	else if (strnicmp(command, CMD_SET_RMC_TXRATE, strlen(CMD_SET_RMC_TXRATE)) == 0) {
-		int rmc_txrate;
-		sscanf(command, "%*s %10d", &rmc_txrate);
-		bytes_written = wldev_iovar_setint(net, "rmc_txrate", rmc_txrate * 2);
-	}
-	else if (strnicmp(command, CMD_SET_RMC_ACTPERIOD, strlen(CMD_SET_RMC_ACTPERIOD)) == 0) {
-		int actperiod;
-		sscanf(command, "%*s %10d", &actperiod);
-		bytes_written = wldev_iovar_setint(net, "rmc_actf_time", actperiod);
-	}
-	else if (strnicmp(command, CMD_SET_RMC_IDLEPERIOD, strlen(CMD_SET_RMC_IDLEPERIOD)) == 0) {
-		int acktimeout;
-		sscanf(command, "%*s %10d", &acktimeout);
-		acktimeout *= 1000;
-		bytes_written = wldev_iovar_setint(net, "rmc_acktmo", acktimeout);
-	}
-	else if (strnicmp(command, CMD_SET_RMC_LEADER, strlen(CMD_SET_RMC_LEADER)) == 0) {
-		int skip = strlen(CMD_SET_RMC_LEADER) + 1;
-		bytes_written = wl_android_rmc_set_leader(net, (const char*)command+skip);
-	}
-	else if (strnicmp(command, CMD_SET_RMC_EVENT,
-		strlen(CMD_SET_RMC_EVENT)) == 0)
-		bytes_written = wl_android_set_rmc_event(net, command, priv_cmd.total_len);
-	else if (strnicmp(command, CMD_GET_SCSCAN, strlen(CMD_GET_SCSCAN)) == 0) {
-		bytes_written = wl_android_get_singlecore_scan(net, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_SET_SCSCAN, strlen(CMD_SET_SCSCAN)) == 0) {
-		bytes_written = wl_android_set_singlecore_scan(net, command, priv_cmd.total_len);
-	}
-#ifdef TEST_TX_POWER_CONTROL
-	else if (strnicmp(command, CMD_TEST_SET_TX_POWER,
-		strlen(CMD_TEST_SET_TX_POWER)) == 0) {
-		int skip = strlen(CMD_TEST_SET_TX_POWER) + 1;
-		wl_android_set_tx_power(net, (const char*)command+skip);
-	}
-	else if (strnicmp(command, CMD_TEST_GET_TX_POWER,
-		strlen(CMD_TEST_GET_TX_POWER)) == 0) {
-		wl_android_get_tx_power(net, command, priv_cmd.total_len);
-	}
-#endif /* TEST_TX_POWER_CONTROL */
-	else if (strnicmp(command, CMD_SARLIMIT_TX_CONTROL,
-		strlen(CMD_SARLIMIT_TX_CONTROL)) == 0) {
-		int skip = strlen(CMD_SARLIMIT_TX_CONTROL) + 1;
-		wl_android_set_sarlimit_txctrl(net, (const char*)command+skip);
-	}
-#ifdef IPV6_NDO_SUPPORT
-	else if (strnicmp(command, CMD_NDRA_LIMIT, strlen(CMD_NDRA_LIMIT)) == 0) {
-		bytes_written = wl_android_nd_ra_limit(net, command, priv_cmd.total_len);
-	}
-#endif /* IPV6_NDO_SUPPORT */
-#endif /* CUSTOMER_HW4_PRIVATE_CMD */
-	else if (strnicmp(command, CMD_HAPD_MAC_FILTER, strlen(CMD_HAPD_MAC_FILTER)) == 0) {
-		int skip = strlen(CMD_HAPD_MAC_FILTER) + 1;
-		wl_android_set_mac_address_filter(net, (const char*)command+skip);
-	}
-	else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0)
-		bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len);
-#if defined(BCMFW_ROAM_ENABLE)
-	else if (strnicmp(command, CMD_SET_ROAMPREF, strlen(CMD_SET_ROAMPREF)) == 0) {
-		bytes_written = wl_android_set_roampref(net, command, priv_cmd.total_len);
-	}
-#endif /* BCMFW_ROAM_ENABLE */
-	else if (strnicmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0)
-		bytes_written = wl_android_set_miracast(net, command, priv_cmd.total_len);
-#ifdef WL11ULB
-	else if (strnicmp(command, CMD_ULB_MODE, strlen(CMD_ULB_MODE)) == 0)
-		bytes_written = wl_android_set_ulb_mode(net, command, priv_cmd.total_len);
-	else if (strnicmp(command, CMD_ULB_BW, strlen(CMD_ULB_BW)) == 0)
-		bytes_written = wl_android_set_ulb_bw(net, command, priv_cmd.total_len);
-#endif /* WL11ULB */
-	else if (strnicmp(command, CMD_SETIBSSBEACONOUIDATA, strlen(CMD_SETIBSSBEACONOUIDATA)) == 0)
-		bytes_written = wl_android_set_ibss_beacon_ouidata(net,
-		command, priv_cmd.total_len);
-	else if (strnicmp(command, CMD_KEEP_ALIVE, strlen(CMD_KEEP_ALIVE)) == 0) {
-		int skip = strlen(CMD_KEEP_ALIVE) + 1;
-		bytes_written = wl_keep_alive_set(net, command + skip, priv_cmd.total_len - skip);
-	}
-	else if (strnicmp(command, CMD_ROAM_OFFLOAD, strlen(CMD_ROAM_OFFLOAD)) == 0) {
-		int enable = *(command + strlen(CMD_ROAM_OFFLOAD) + 1) - '0';
-		bytes_written = wl_cfg80211_enable_roam_offload(net, enable);
-	}
-	else if (strnicmp(command, CMD_ROAM_OFFLOAD_APLIST, strlen(CMD_ROAM_OFFLOAD_APLIST)) == 0) {
-		bytes_written = wl_android_set_roam_offload_bssid_list(net,
-			command + strlen(CMD_ROAM_OFFLOAD_APLIST) + 1);
-	}
-#if defined(WL_VIRTUAL_APSTA)
-	else if (strnicmp(command, CMD_INTERFACE_CREATE, strlen(CMD_INTERFACE_CREATE)) == 0) {
-		char *name = (command + strlen(CMD_INTERFACE_CREATE) +1);
-		WL_INFORM(("Creating %s interface\n", name));
-		bytes_written = wl_cfg80211_interface_create(net, name);
-	}
-	else if (strnicmp(command, CMD_INTERFACE_DELETE, strlen(CMD_INTERFACE_DELETE)) == 0) {
-		char *name = (command + strlen(CMD_INTERFACE_DELETE) +1);
-		WL_INFORM(("Deleteing %s interface\n", name));
-		bytes_written = wl_cfg80211_interface_delete(net, name);
-	}
-#endif /* defined (WL_VIRTUAL_APSTA) */
-#ifdef P2PRESP_WFDIE_SRC
-	else if (strnicmp(command, CMD_P2P_SET_WFDIE_RESP,
-		strlen(CMD_P2P_SET_WFDIE_RESP)) == 0) {
-		int mode = *(command + strlen(CMD_P2P_SET_WFDIE_RESP) + 1) - '0';
-		bytes_written = wl_android_set_wfdie_resp(net, mode);
-	} else if (strnicmp(command, CMD_P2P_GET_WFDIE_RESP,
-		strlen(CMD_P2P_GET_WFDIE_RESP)) == 0) {
-		bytes_written = wl_android_get_wfdie_resp(net, command, priv_cmd.total_len);
-	}
-#endif /* P2PRESP_WFDIE_SRC */
-	else if (strnicmp(command, CMD_DFS_AP_MOVE, strlen(CMD_DFS_AP_MOVE)) == 0) {
-		char *data = (command + strlen(CMD_DFS_AP_MOVE) +1);
-		bytes_written = wl_cfg80211_dfs_ap_move(net, data, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_WBTEXT_ENABLE, strlen(CMD_WBTEXT_ENABLE)) == 0) {
-		bytes_written = wl_android_wbtext(net, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_WBTEXT_PROFILE_CONFIG,
-			strlen(CMD_WBTEXT_PROFILE_CONFIG)) == 0) {
-		char *data = (command + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
-		bytes_written = wl_cfg80211_wbtext_config(net, data, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_WBTEXT_WEIGHT_CONFIG,
-			strlen(CMD_WBTEXT_WEIGHT_CONFIG)) == 0) {
-		char *data = (command + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
-		bytes_written = wl_cfg80211_wbtext_weight_config(net, data,
-				command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_WBTEXT_TABLE_CONFIG,
-			strlen(CMD_WBTEXT_TABLE_CONFIG)) == 0) {
-		char *data = (command + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
-		bytes_written = wl_cfg80211_wbtext_table_config(net, data,
-				command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_WBTEXT_DELTA_CONFIG,
-			strlen(CMD_WBTEXT_DELTA_CONFIG)) == 0) {
-		char *data = (command + strlen(CMD_WBTEXT_DELTA_CONFIG) + 1);
-		bytes_written = wl_cfg80211_wbtext_delta_config(net, data,
-				command, priv_cmd.total_len);
-	}
-#ifdef SET_RPS_CPUS
-	else if (strnicmp(command, CMD_RPSMODE, strlen(CMD_RPSMODE)) == 0) {
-		bytes_written = wl_android_set_rps_cpus(net, command, priv_cmd.total_len);
-	}
-#endif /* SET_RPS_CPUS */
-#ifdef WLWFDS
-	else if (strnicmp(command, CMD_ADD_WFDS_HASH, strlen(CMD_ADD_WFDS_HASH)) == 0) {
-		bytes_written = wl_android_set_wfds_hash(net, command, priv_cmd.total_len, 1);
-	}
-	else if (strnicmp(command, CMD_DEL_WFDS_HASH, strlen(CMD_DEL_WFDS_HASH)) == 0) {
-		bytes_written = wl_android_set_wfds_hash(net, command, priv_cmd.total_len, 0);
-	}
-#endif /* WLWFDS */
-#ifdef BT_WIFI_HANDOVER
-	else if (strnicmp(command, CMD_TBOW_TEARDOWN, strlen(CMD_TBOW_TEARDOWN)) == 0) {
-	    ret = wl_tbow_teardown(net, command, priv_cmd.total_len);
-	}
-#endif /* BT_WIFI_HANDOVER */
-#ifdef FCC_PWR_LIMIT_2G
-	else if (strnicmp(command, CMD_GET_FCC_PWR_LIMIT_2G,
-		strlen(CMD_GET_FCC_PWR_LIMIT_2G)) == 0) {
-		bytes_written = wl_android_get_fcc_pwr_limit_2g(net, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_SET_FCC_PWR_LIMIT_2G,
-		strlen(CMD_SET_FCC_PWR_LIMIT_2G)) == 0) {
-		bytes_written = wl_android_set_fcc_pwr_limit_2g(net, command, priv_cmd.total_len);
-	}
-#endif /* FCC_PWR_LIMIT_2G */
-	else if (strnicmp(command, CMD_MURX_BFE_CAP,
-			strlen(CMD_MURX_BFE_CAP)) == 0) {
-		uint val = *(command + strlen(CMD_MURX_BFE_CAP) + 1) - '0';
-		bytes_written = wl_android_murx_bfe_cap(net, val);
-	}
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-	else if (strnicmp(command, CMD_GET_BSS_INFO, strlen(CMD_GET_BSS_INFO)) == 0) {
-		bytes_written = wl_cfg80211_get_bss_info(net, command, priv_cmd.total_len);
-	}
-	else if (strnicmp(command, CMD_GET_ASSOC_REJECT_INFO, strlen(CMD_GET_ASSOC_REJECT_INFO))
-			== 0) {
-		bytes_written = wl_cfg80211_get_connect_failed_status(net, command,
-				priv_cmd.total_len);
-	}
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-#if defined(SUPPORT_RANDOM_MAC_SCAN)
-	else if (strnicmp(command, ENABLE_RANDOM_MAC, strlen(ENABLE_RANDOM_MAC)) == 0) {
-		bytes_written = wl_cfg80211_set_random_mac(net, TRUE);
-	} else if (strnicmp(command, DISABLE_RANDOM_MAC, strlen(DISABLE_RANDOM_MAC)) == 0) {
-		bytes_written = wl_cfg80211_set_random_mac(net, FALSE);
-	}
-#endif /* SUPPORT_RANDOM_MAC_SCAN */
-#ifdef DHD_LOG_DUMP
-	else if (strnicmp(command, CMD_NEW_DEBUG_PRINT_DUMP,
-		strlen(CMD_NEW_DEBUG_PRINT_DUMP)) == 0) {
-		dhd_pub_t *dhdp = wl_cfg80211_get_dhdp();
-#ifdef DHD_TRACE_WAKE_LOCK
-		dhd_wk_lock_stats_dump(dhdp);
-#endif /* DHD_TRACE_WAKE_LOCK */
-		dhd_schedule_log_dump(dhdp);
-#if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
-		dhdp->memdump_type = DUMP_TYPE_BY_SYSDUMP;
-		dhd_bus_mem_dump(dhdp);
-#endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
-	}
-#endif /* DHD_LOG_DUMP */
-	else {
-		DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
-		snprintf(command, 3, "OK");
-		bytes_written = strlen("OK");
-	}
-
-	if (bytes_written >= 0) {
-		if ((bytes_written == 0) && (priv_cmd.total_len > 0))
-			command[0] = '\0';
-		if (bytes_written >= priv_cmd.total_len) {
-			DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written));
-			bytes_written = priv_cmd.total_len;
-		} else {
-			bytes_written++;
-		}
-		priv_cmd.used_len = bytes_written;
-		if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
-			DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__));
-			ret = -EFAULT;
-		}
-	}
-#ifdef CONNECTION_STATISTICS
-	else if (strnicmp(command, CMD_GET_CONNECTION_STATS,
-		strlen(CMD_GET_CONNECTION_STATS)) == 0) {
-		bytes_written = wl_android_get_connection_stats(net, command,
-			priv_cmd.total_len);
-	}
-#endif
-	else {
-		ret = bytes_written;
-	}
-
-exit:
-	net_os_wake_unlock(net);
-	if (command) {
-		kfree(command);
-	}
-
-	return ret;
-}
-
-int wl_android_init(void)
-{
-	int ret = 0;
-
-#ifdef ENABLE_INSMOD_NO_FW_LOAD
-	dhd_download_fw_on_driverload = FALSE;
-#endif /* ENABLE_INSMOD_NO_FW_LOAD */
-	if (!iface_name[0]) {
-		memset(iface_name, 0, IFNAMSIZ);
-		bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ);
-	}
-
-	wl_netlink_init();
-
-	return ret;
-}
-
-int wl_android_exit(void)
-{
-	int ret = 0;
-	struct io_cfg *cur, *q;
-
-	wl_netlink_deinit();
-
-	list_for_each_entry_safe(cur, q, &miracast_resume_list, list) {
-		list_del(&cur->list);
-		kfree(cur);
-	}
-
-	return ret;
-}
-
-void wl_android_post_init(void)
-{
-
-#ifdef ENABLE_4335BT_WAR
-	bcm_bt_unlock(lock_cookie_wifi);
-	printk("%s: btlock released\n", __FUNCTION__);
-#endif /* ENABLE_4335BT_WAR */
-
-	if (!dhd_download_fw_on_driverload)
-		g_wifi_on = FALSE;
-}
diff --git a/drivers/net/wireless/bcmdhd/wl_android.h b/drivers/net/wireless/bcmdhd/wl_android.h
deleted file mode 100644
index 14ffc68..0000000
--- a/drivers/net/wireless/bcmdhd/wl_android.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Linux cfg80211 driver - Android related functions
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_android.h 608194 2015-12-24 04:34:35Z $
- */
-
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <wldev_common.h>
-
-/* If any feature uses the Generic Netlink Interface, put it here to enable WL_GENL
- * automatically
- */
-#if defined(BT_WIFI_HANDOVER) || defined(WL_NAN)
-#define WL_GENL
-#endif
-
-
-
-/**
- * Android platform dependent functions, feel free to add Android specific functions here
- * (save the macros in dhd). Please do NOT declare functions that are NOT exposed to dhd
- * or cfg, define them as static in wl_android.c
- */
-
-/**
- * wl_android_init will be called from module init function (dhd_module_init now), similarly
- * wl_android_exit will be called from module exit function (dhd_module_cleanup now)
- */
-int wl_android_init(void);
-int wl_android_exit(void);
-void wl_android_post_init(void);
-int wl_android_wifi_on(struct net_device *dev);
-int wl_android_wifi_off(struct net_device *dev, bool on_failure);
-int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
-
-s32 wl_netlink_send_msg(int pid, int type, int seq, void *data, size_t size);
-
-/* hostap mac mode */
-#define MACLIST_MODE_DISABLED   0
-#define MACLIST_MODE_DENY       1
-#define MACLIST_MODE_ALLOW      2
-
-/* max number of assoc list */
-#define MAX_NUM_OF_ASSOCLIST    64
-
-/* Bandwidth */
-#define WL_CH_BANDWIDTH_20MHZ 20
-#define WL_CH_BANDWIDTH_40MHZ 40
-#define WL_CH_BANDWIDTH_80MHZ 80
-/* max number of mac filter list
- * restrict max number to 10 as maximum cmd string size is 255
- */
-#define MAX_NUM_MAC_FILT        10
-
-int wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist);
-int wl_android_set_roam_offload_bssid_list(struct net_device *dev, const char *cmd);
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
deleted file mode 100644
index 861afc9..0000000
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ /dev/null
@@ -1,17256 +0,0 @@
-/*
- * Linux cfg80211 driver
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_cfg80211.c 610196 2016-01-06 11:20:45Z $
- */
-/* */
-#include <typedefs.h>
-#include <linuxver.h>
-#include <osl.h>
-#include <linux/kernel.h>
-
-#include <bcmutils.h>
-#include <bcmwifi_channels.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
-#include <proto/802.11.h>
-#include <linux/if_arp.h>
-#include <asm/uaccess.h>
-
-#include <proto/ethernet.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-#include <linux/ieee80211.h>
-#include <linux/wait.h>
-#include <net/cfg80211.h>
-#include <net/rtnetlink.h>
-
-#include <wlioctl.h>
-#include <wldev_common.h>
-#include <wl_cfg80211.h>
-#include <wl_cfgp2p.h>
-#include <wl_android.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_linux.h>
-#include <dhdioctl.h>
-#include <wlioctl.h>
-#include <dhd_cfg80211.h>
-#include <dhd_bus.h>
-#ifdef PNO_SUPPORT
-#include <dhd_pno.h>
-#endif /* PNO_SUPPORT */
-
-#if defined(WL_VENDOR_EXT_SUPPORT)
-#include <wl_cfgvendor.h>
-#endif /* defined(WL_VENDOR_EXT_SUPPORT) */
-
-#ifdef WL_NAN
-#include <wl_cfgnan.h>
-#endif /* WL_NAN */
-
-#ifdef PROP_TXSTATUS
-#include <dhd_wlfc.h>
-#endif
-
-#ifdef BCMPCIE
-#include <dhd_flowring.h>
-#endif
-
-#ifdef WL11U
-#if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
-#error You should enable 'WL_ENABLE_P2P_IF' or 'WL_CFG80211_P2P_DEV_IF' \
-	according to Kernel version and is supported only in Android-JB
-#endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
-#endif /* WL11U */
-
-
-#define IW_WSEC_ENABLED(wsec)   ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
-
-static struct device *cfg80211_parent_dev = NULL;
-/* g_bcm_cfg should be static. Do not change */
-static struct bcm_cfg80211 *g_bcm_cfg = NULL;
-#ifdef CUSTOMER_HW4_DEBUG
-u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_P2P_ACTION;
-#else
-u32 wl_dbg_level = WL_DBG_ERR;
-#endif /* CUSTOMER_HW4_DEBUG */
-
-#define MAX_WAIT_TIME 1500
-#ifdef WLAIBSS_MCHAN
-#define IBSS_IF_NAME "ibss%d"
-#endif /* WLAIBSS_MCHAN */
-
-#ifdef VSDB
-/* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
-#define DEFAULT_SLEEP_TIME_VSDB		120
-#define OFF_CHAN_TIME_THRESHOLD_MS	200
-#define AF_RETRY_DELAY_TIME			40
-
-/* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
-#define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)	\
-	do {	\
-		if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) ||	\
-			wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {	\
-			OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB);			\
-		}	\
-	} while (0)
-#else /* VSDB */
-/* if not VSDB, do nothing */
-#define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)
-#endif /* VSDB */
-
-#ifdef WL_CFG80211_SYNC_GON
-#define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) \
-	(wl_get_drv_status_all(cfg, SENDING_ACT_FRM) || \
-		wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN))
-#else
-#define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) wl_get_drv_status_all(cfg, SENDING_ACT_FRM)
-#endif /* WL_CFG80211_SYNC_GON */
-
-#define DNGL_FUNC(func, parameters) func parameters
-#define COEX_DHCP
-
-#define WLAN_EID_SSID	0
-#define CH_MIN_5G_CHANNEL 34
-#define CH_MIN_2G_CHANNEL 1
-#define ACTIVE_SCAN 1
-#define PASSIVE_SCAN 0
-
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
-_Pragma("GCC diagnostic push") \
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
-(entry) = list_first_entry((ptr), type, member); \
-_Pragma("GCC diagnostic pop") \
-
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
-_Pragma("GCC diagnostic push") \
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
-entry = container_of((ptr), type, member); \
-_Pragma("GCC diagnostic pop") \
-
-#else
-#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
-(entry) = list_first_entry((ptr), type, member); \
-
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
-entry = container_of((ptr), type, member); \
-
-#endif /* STRICT_GCC_WARNINGS */
-
-enum rmc_event_type {
-	RMC_EVENT_NONE,
-	RMC_EVENT_LEADER_CHECK_FAIL
-};
-
-/* This is to override regulatory domains defined in cfg80211 module (reg.c)
- * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
- * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
- * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
- * All the chnages in world regulatory domain are to be done here.
- *
- * this definition reuires disabling missing-field-initializer warning
- * as the ieee80211_regdomain definition differs in plain linux and in Android
- */
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
-#endif
-static const struct ieee80211_regdomain brcm_regdom = {
-	.n_reg_rules = 4,
-	.alpha2 =  "99",
-	.reg_rules = {
-		/* IEEE 802.11b/g, channels 1..11 */
-		REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
-		/* If any */
-		/* IEEE 802.11 channel 14 - Only JP enables
-		 * this and for 802.11b only
-		 */
-		REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
-		/* IEEE 802.11a, channel 36..64 */
-		REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
-		/* IEEE 802.11a, channel 100..165 */
-		REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
-};
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
-	(defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
-static const struct ieee80211_iface_limit common_if_limits[] = {
-	{
-	/*
-	 * Driver can support up to 2 AP's
-	 */
-	.max = 2,
-	.types = BIT(NL80211_IFTYPE_AP),
-	},
-	{
-	/*
-	 * During P2P-GO removal, P2P-GO is first changed to STA and later only
-	 * removed. So setting maximum possible number of STA interfaces according
-	 * to kernel version.
-	 *
-	 * less than linux-3.8 - max:3 (wlan0 + p2p0 + group removal of p2p-p2p0-x)
-	 * linux-3.8 and above - max:2 (wlan0 + group removal of p2p-wlan0-x)
-	 */
-#ifdef WL_ENABLE_P2P_IF
-	.max = 3,
-#else
-	.max = 2,
-#endif /* WL_ENABLE_P2P_IF */
-	.types = BIT(NL80211_IFTYPE_STATION),
-	},
-	{
-	.max = 2,
-	.types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
-	},
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	{
-	.max = 1,
-	.types = BIT(NL80211_IFTYPE_P2P_DEVICE),
-	},
-#endif /* WL_CFG80211_P2P_DEV_IF */
-	{
-	.max = 1,
-	.types = BIT(NL80211_IFTYPE_ADHOC),
-	},
-};
-#ifdef BCM4330_CHIP
-#define NUM_DIFF_CHANNELS 1
-#else
-#define NUM_DIFF_CHANNELS 2
-#endif
-static const struct ieee80211_iface_combination
-common_iface_combinations[] = {
-	{
-	.num_different_channels = NUM_DIFF_CHANNELS,
-	/*
-	 * max_interfaces = 4
-	 * The max no of interfaces will be used in dual p2p case.
-	 * {STA, P2P Device, P2P Group 1, P2P Group 2}. Though we
-	 * will not be using the STA functionality in this case, it
-	 * will remain registered as it is the primary interface.
-	 */
-	.max_interfaces = 4,
-	.limits = common_if_limits,
-	.n_limits = ARRAY_SIZE(common_if_limits),
-	},
-};
-#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
-
-/* Data Element Definitions */
-#define WPS_ID_CONFIG_METHODS     0x1008
-#define WPS_ID_REQ_TYPE           0x103A
-#define WPS_ID_DEVICE_NAME        0x1011
-#define WPS_ID_VERSION            0x104A
-#define WPS_ID_DEVICE_PWD_ID      0x1012
-#define WPS_ID_REQ_DEV_TYPE       0x106A
-#define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
-#define WPS_ID_PRIM_DEV_TYPE      0x1054
-
-/* Device Password ID */
-#define DEV_PW_DEFAULT 0x0000
-#define DEV_PW_USER_SPECIFIED 0x0001,
-#define DEV_PW_MACHINE_SPECIFIED 0x0002
-#define DEV_PW_REKEY 0x0003
-#define DEV_PW_PUSHBUTTON 0x0004
-#define DEV_PW_REGISTRAR_SPECIFIED 0x0005
-
-/* Config Methods */
-#define WPS_CONFIG_USBA 0x0001
-#define WPS_CONFIG_ETHERNET 0x0002
-#define WPS_CONFIG_LABEL 0x0004
-#define WPS_CONFIG_DISPLAY 0x0008
-#define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
-#define WPS_CONFIG_INT_NFC_TOKEN 0x0020
-#define WPS_CONFIG_NFC_INTERFACE 0x0040
-#define WPS_CONFIG_PUSHBUTTON 0x0080
-#define WPS_CONFIG_KEYPAD 0x0100
-#define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
-#define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
-#define WPS_CONFIG_VIRT_DISPLAY 0x2008
-#define WPS_CONFIG_PHY_DISPLAY 0x4008
-
-#define PM_BLOCK 1
-#define PM_ENABLE 0
-
-
-#define WL_AKM_SUITE_SHA256_1X  0x000FAC05
-#define WL_AKM_SUITE_SHA256_PSK 0x000FAC06
-
-#ifndef IBSS_COALESCE_ALLOWED
-#define IBSS_COALESCE_ALLOWED 0
-#endif
-
-#ifndef IBSS_INITIAL_SCAN_ALLOWED
-#define IBSS_INITIAL_SCAN_ALLOWED 0
-#endif
-
-#define CUSTOM_RETRY_MASK 0xff000000 /* Mask for retry counter of custom dwell time */
-#define LONG_LISTEN_TIME 2000
-
-#define MAX_SCAN_ABORT_WAIT_CNT 20
-#define WAIT_SCAN_ABORT_OSL_SLEEP_TIME 10
-
-#define IDSUP_4WAY_HANDSHAKE_TIMEOUT	10000
-enum idsup_event_type {
-	IDSUP_EVENT_SUCCESS = 0,
-	IDSUP_EVENT_4WAY_HANDSHAKE_TIMEOUT
-};
-/*
- * cfg80211_ops api/callback list
- */
-static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
-	const struct ether_addr *sa, const struct ether_addr *bssid,
-	u8 **pheader, u32 *body_len, u8 *pbody);
-static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
-	struct cfg80211_scan_request *request,
-	struct cfg80211_ssid *this_ssid);
-#if defined(WL_CFG80211_P2P_DEV_IF)
-static s32
-wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
-#else
-static s32
-wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
-	struct cfg80211_scan_request *request);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
-#ifdef WLAIBSS_MCHAN
-static bcm_struct_cfgdev* bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name);
-static s32 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
-#endif /* WLAIBSS_MCHAN */
-static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
-	struct cfg80211_ibss_params *params);
-static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
-	struct net_device *dev);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
-	struct net_device *dev, const u8 *mac,
-	struct station_info *sinfo);
-#else
-static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
-	struct net_device *dev, u8 *mac,
-	struct station_info *sinfo);
-#endif
-static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
-	struct net_device *dev, bool enabled,
-	s32 timeout);
-static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
-	struct cfg80211_connect_params *sme);
-static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
-	u16 reason_code);
-#if defined(WL_CFG80211_P2P_DEV_IF)
-static s32
-wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
-	enum nl80211_tx_power_setting type, s32 mbm);
-#else
-static s32
-wl_cfg80211_set_tx_power(struct wiphy *wiphy,
-	enum nl80211_tx_power_setting type, s32 dbm);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-#if defined(WL_CFG80211_P2P_DEV_IF)
-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
-	struct wireless_dev *wdev, s32 *dbm);
-#else
-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
-	struct net_device *dev,
-	u8 key_idx, bool unicast, bool multicast);
-static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
-	u8 key_idx, bool pairwise, const u8 *mac_addr,
-	struct key_params *params);
-static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
-	u8 key_idx, bool pairwise, const u8 *mac_addr);
-static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
-	u8 key_idx, bool pairwise, const u8 *mac_addr,
-	void *cookie, void (*callback) (void *cookie,
-	struct key_params *params));
-static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
-	struct net_device *dev,	u8 key_idx);
-static s32 wl_cfg80211_resume(struct wiphy *wiphy);
-#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
-	2, 0))
-static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
-	bcm_struct_cfgdev *cfgdev, u64 cookie);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
-static s32 wl_cfg80211_del_station(
-		struct wiphy *wiphy, struct net_device *ndev,
-		struct station_del_parameters *params);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
-	struct net_device *ndev, const u8* mac_addr);
-#else
-static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
-	struct net_device *ndev, u8* mac_addr);
-#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
-	struct net_device *dev, const u8 *mac, struct station_parameters *params);
-#else
-static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
-	struct net_device *dev, u8 *mac, struct station_parameters *params);
-#endif
-#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
-static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
-#else
-static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
-#endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
-static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
-	struct cfg80211_pmksa *pmksa);
-static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
-	struct cfg80211_pmksa *pmksa);
-static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
-	struct net_device *dev);
-static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg);
-static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg);
-static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
-	struct net_device *ndev, bool aborted, bool fw_abort);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
-#if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
-	KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
-static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
-	u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
-	u32 peer_capability, const u8 *data, size_t len);
-#elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
-		(LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
-static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
-	const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
-	u32 peer_capability, const u8 *data, size_t len);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
-	const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
-	u32 peer_capability, bool initiator, const u8 *data, size_t len);
-#else
-static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
-	u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
-	size_t len);
-#endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
-	const u8 *peer, enum nl80211_tdls_operation oper);
-#else
-static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
-	u8 *peer, enum nl80211_tdls_operation oper);
-#endif
-#endif 
-#ifdef WL_SCHED_SCAN
-static int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev);
-#endif
-#if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
-bcm_struct_cfgdev*
-wl_cfg80211_create_iface(struct wiphy *wiphy, enum nl80211_iftype
-		 iface_type, u8 *mac_addr, const char *name);
-s32
-wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
-#endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
-
-s32 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
-	struct net_device *ndev, s32 bsscfg_idx,
-	enum nl80211_iftype iface_type, s32 del, u8 *addr);
-s32 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
-	struct net_device *ndev, s32 bsscfg_idx,
-	enum nl80211_iftype iface_type, s32 del, u8 *addr);
-chanspec_t wl_chspec_driver_to_host(chanspec_t chanspec);
-chanspec_t wl_chspec_host_to_driver(chanspec_t chanspec);
-#ifdef WL11ULB
-static s32 wl_cfg80211_get_ulb_bw(struct wireless_dev *wdev);
-static chanspec_t wl_cfg80211_ulb_get_min_bw_chspec(struct wireless_dev *wdev, s32 bssidx);
-static s32 wl_cfg80211_ulbbw_to_ulbchspec(u32 ulb_bw);
-#else
-static inline chanspec_t wl_cfg80211_ulb_get_min_bw_chspec(
-		struct wireless_dev *wdev, s32 bssidx)
-{
-	return WL_CHANSPEC_BW_20;
-}
-#endif /* WL11ULB */
-
-/*
- * event & event Q handlers for cfg80211 interfaces
- */
-static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg);
-static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg);
-static s32 wl_event_handler(void *data);
-static void wl_init_eq(struct bcm_cfg80211 *cfg);
-static void wl_flush_eq(struct bcm_cfg80211 *cfg);
-static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg);
-static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags);
-static void wl_init_eq_lock(struct bcm_cfg80211 *cfg);
-static void wl_init_event_handler(struct bcm_cfg80211 *cfg);
-static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg);
-static s32 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 type,
-	const wl_event_msg_t *msg, void *data);
-static void wl_put_event(struct wl_event_q *e);
-static void wl_wakeup_event(struct bcm_cfg80211 *cfg);
-static s32 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, void *data);
-static s32 wl_notify_connect_status(struct bcm_cfg80211 *cfg,
-	bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
-static s32 wl_notify_roaming_status(struct bcm_cfg80211 *cfg,
-	bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
-static s32 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-static s32 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, void *data, bool completed);
-static s32 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, void *data);
-static s32 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-#ifdef BT_WIFI_HANDOVER
-static s32 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg,
-	bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
-#endif /* BT_WIFI_HANDOVER */
-#ifdef WL_SCHED_SCAN
-static s32
-wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, void *data);
-#endif /* WL_SCHED_SCAN */
-#ifdef PNO_SUPPORT
-static s32 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-#endif /* PNO_SUPPORT */
-#ifdef GSCAN_SUPPORT
-static s32 wl_notify_gscan_event(struct bcm_cfg80211 *wl, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-#endif /* GSCAN_SUPPORT */
-static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
-	enum wl_status state, bool set);
-#ifdef DHD_LOSSLESS_ROAMING
-static s32 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg,
-	bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
-static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg);
-#endif /* DHD_LOSSLESS_ROAMING */
-#ifdef CUSTOM_EVENT_PM_WAKE
-static s32 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-#endif /* CUSTOM_EVENT_PM_WAKE */
-
-#ifdef WLTDLS
-static s32 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-#endif /* WLTDLS */
-/*
- * register/deregister parent device
- */
-static void wl_cfg80211_clear_parent_dev(void);
-/*
- * ioctl utilites
- */
-
-/*
- * cfg80211 set_wiphy_params utilities
- */
-static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
-static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
-static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
-
-/*
- * cfg profile utilities
- */
-static s32 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, const void *data, s32 item);
-static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item);
-static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev);
-
-/*
- * cfg80211 connect utilites
- */
-static s32 wl_set_wpa_version(struct net_device *dev,
-	struct cfg80211_connect_params *sme);
-static s32 wl_set_auth_type(struct net_device *dev,
-	struct cfg80211_connect_params *sme);
-static s32 wl_set_set_cipher(struct net_device *dev,
-	struct cfg80211_connect_params *sme);
-static s32 wl_set_key_mgmt(struct net_device *dev,
-	struct cfg80211_connect_params *sme);
-static s32 wl_set_set_sharedkey(struct net_device *dev,
-	struct cfg80211_connect_params *sme);
-static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev);
-static s32 wl_ch_to_chanspec(struct net_device *dev, int ch,
-	struct wl_join_params *join_params, size_t *join_params_size);
-void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg);
-
-/*
- * information element utilities
- */
-static void wl_rst_ie(struct bcm_cfg80211 *cfg);
-static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v);
-static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
-	bool roam);
-static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size);
-static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size);
-static u32 wl_get_ielen(struct bcm_cfg80211 *cfg);
-
-#ifdef WL11U
-bcm_tlv_t *
-wl_cfg80211_find_interworking_ie(u8 *parse, u32 len);
-static s32
-wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
-            uint8 ie_id, uint8 *data, uint8 data_len);
-#endif /* WL11U */
-
-static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
-static void wl_free_wdev(struct bcm_cfg80211 *cfg);
-#ifdef CONFIG_CFG80211_INTERNAL_REGDB
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-static int
-#else
-static void
-#endif /* kernel version < 3.10.11 */
-wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
-#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
-
-static s32 wl_inform_bss(struct bcm_cfg80211 *cfg);
-static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam);
-static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam);
-static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
-s32 wl_cfg80211_channel_to_freq(u32 channel);
-
-
-static void wl_cfg80211_work_handler(struct work_struct *work);
-static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
-	u8 key_idx, const u8 *mac_addr,
-	struct key_params *params);
-/*
- * key indianess swap utilities
- */
-static void swap_key_from_BE(struct wl_wsec_key *key);
-static void swap_key_to_BE(struct wl_wsec_key *key);
-
-/*
- * bcm_cfg80211 memory init/deinit utilities
- */
-static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg);
-static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg);
-
-static void wl_delay(u32 ms);
-
-/*
- * ibss mode utilities
- */
-static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev);
-static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg);
-
-/*
- * link up/down , default configuration utilities
- */
-static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg);
-static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg);
-static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
-static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e,
-	struct net_device *ndev);
-static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
-static void wl_link_up(struct bcm_cfg80211 *cfg);
-static void wl_link_down(struct bcm_cfg80211 *cfg);
-static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype);
-static void wl_init_conf(struct wl_conf *conf);
-static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
-	struct net_device* ndev);
-
-int wl_cfg80211_get_ioctl_version(void);
-
-/*
- * find most significant bit set
- */
-static __used u32 wl_find_msb(u16 bit16);
-
-/*
- * rfkill support
- */
-static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup);
-static int wl_rfkill_set(void *data, bool blocked);
-#ifdef DEBUGFS_CFG80211
-static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg);
-static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg);
-#endif
-
-static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
-	int nprobes, int *out_params_size);
-static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role);
-
-#ifdef WL_CFG80211_ACL
-/* ACL */
-static int wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
-	const struct cfg80211_acl_data *acl);
-#endif /* WL_CFG80211_ACL */
-
-/*
- * Some external functions, TODO: move them to dhd_linux.h
- */
-int dhd_add_monitor(char *name, struct net_device **new_ndev);
-int dhd_del_monitor(struct net_device *ndev);
-int dhd_monitor_init(void *dhd_pub);
-int dhd_monitor_uninit(void);
-int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
-
-
-#ifdef DHD_IFDEBUG
-void wl_dump_ifinfo(struct bcm_cfg80211 *cfg);
-#endif
-
-#ifdef P2P_LISTEN_OFFLOADING
-s32 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg);
-#endif /* P2P_LISTEN_OFFLOADING */
-
-static int wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const struct ether_addr *bssid);
-
-static int bw2cap[] = { 0, 0, WLC_BW_CAP_20MHZ, WLC_BW_CAP_40MHZ, WLC_BW_CAP_80MHZ,
-	WLC_BW_CAP_160MHZ, WLC_BW_CAP_160MHZ };
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
-#define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
-	cfg80211_disconnected(dev, reason, ie, len, gfp);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
-#define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
-	cfg80211_disconnected(dev, reason, ie, len, loc_gen, gfp);
-#endif
-
-#ifdef RSSI_OFFSET
-static s32 wl_rssi_offset(s32 rssi)
-{
-	rssi += RSSI_OFFSET;
-	if (rssi > 0)
-		rssi = 0;
-	return rssi;
-}
-#else
-#define wl_rssi_offset(x)	x
-#endif
-
-#define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || 			\
-				 (akm) == RSN_AKM_UNSPECIFIED || 	\
-				 (akm) == RSN_AKM_PSK)
-
-
-extern int dhd_wait_pend8021x(struct net_device *dev);
-#ifdef PROP_TXSTATUS_VSDB
-extern int disable_proptx;
-#endif /* PROP_TXSTATUS_VSDB */
-
-
-extern int passive_channel_skip;
-
-static s32
-wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-static s32
-wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-#if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
-	0)))
-struct chan_info {
-	int freq;
-	int chan_type;
-};
-#endif
-
-
-#if (WL_DBG_LEVEL > 0)
-#define WL_DBG_ESTR_MAX	50
-static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
-	"SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
-	"DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
-	"REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
-	"BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
-	"TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
-	"EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
-	"BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
-	"PFN_NET_LOST",
-	"RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
-	"IBSS_ASSOC",
-	"RADIO", "PSM_WATCHDOG",
-	"WLC_E_XXX_ASSOC_START", "WLC_E_XXX_ASSOC_ABORT",
-	"PROBREQ_MSG",
-	"SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
-	"EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
-	"UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
-	"WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
-	"RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
-	"ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
-	"WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
-	"WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
-	"WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
-	"WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
-	"WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
-};
-#endif				/* WL_DBG_LEVEL */
-
-#define CHAN2G(_channel, _freq, _flags) {			\
-	.band			= IEEE80211_BAND_2GHZ,		\
-	.center_freq		= (_freq),			\
-	.hw_value		= (_channel),			\
-	.flags			= (_flags),			\
-	.max_antenna_gain	= 0,				\
-	.max_power		= 30,				\
-}
-
-#define CHAN5G(_channel, _flags) {				\
-	.band			= IEEE80211_BAND_5GHZ,		\
-	.center_freq		= 5000 + (5 * (_channel)),	\
-	.hw_value		= (_channel),			\
-	.flags			= (_flags),			\
-	.max_antenna_gain	= 0,				\
-	.max_power		= 30,				\
-}
-
-#define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
-#define RATETAB_ENT(_rateid, _flags) \
-	{								\
-		.bitrate	= RATE_TO_BASE100KBPS(_rateid),     \
-		.hw_value	= (_rateid),			    \
-		.flags	  = (_flags),			     \
-	}
-
-static struct ieee80211_rate __wl_rates[] = {
-	RATETAB_ENT(DOT11_RATE_1M, 0),
-	RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATETAB_ENT(DOT11_RATE_6M, 0),
-	RATETAB_ENT(DOT11_RATE_9M, 0),
-	RATETAB_ENT(DOT11_RATE_12M, 0),
-	RATETAB_ENT(DOT11_RATE_18M, 0),
-	RATETAB_ENT(DOT11_RATE_24M, 0),
-	RATETAB_ENT(DOT11_RATE_36M, 0),
-	RATETAB_ENT(DOT11_RATE_48M, 0),
-	RATETAB_ENT(DOT11_RATE_54M, 0)
-};
-
-#define wl_a_rates		(__wl_rates + 4)
-#define wl_a_rates_size	8
-#define wl_g_rates		(__wl_rates + 0)
-#define wl_g_rates_size	12
-
-static struct ieee80211_channel __wl_2ghz_channels[] = {
-	CHAN2G(1, 2412, 0),
-	CHAN2G(2, 2417, 0),
-	CHAN2G(3, 2422, 0),
-	CHAN2G(4, 2427, 0),
-	CHAN2G(5, 2432, 0),
-	CHAN2G(6, 2437, 0),
-	CHAN2G(7, 2442, 0),
-	CHAN2G(8, 2447, 0),
-	CHAN2G(9, 2452, 0),
-	CHAN2G(10, 2457, 0),
-	CHAN2G(11, 2462, 0),
-	CHAN2G(12, 2467, 0),
-	CHAN2G(13, 2472, 0),
-	CHAN2G(14, 2484, 0)
-};
-
-static struct ieee80211_channel __wl_5ghz_a_channels[] = {
-	CHAN5G(34, 0), CHAN5G(36, 0),
-	CHAN5G(38, 0), CHAN5G(40, 0),
-	CHAN5G(42, 0), CHAN5G(44, 0),
-	CHAN5G(46, 0), CHAN5G(48, 0),
-	CHAN5G(52, 0), CHAN5G(56, 0),
-	CHAN5G(60, 0), CHAN5G(64, 0),
-	CHAN5G(100, 0), CHAN5G(104, 0),
-	CHAN5G(108, 0), CHAN5G(112, 0),
-	CHAN5G(116, 0), CHAN5G(120, 0),
-	CHAN5G(124, 0), CHAN5G(128, 0),
-	CHAN5G(132, 0), CHAN5G(136, 0),
-	CHAN5G(140, 0), CHAN5G(144, 0),
-	CHAN5G(149, 0), CHAN5G(153, 0),
-	CHAN5G(157, 0), CHAN5G(161, 0),
-	CHAN5G(165, 0)
-};
-
-static struct ieee80211_supported_band __wl_band_2ghz = {
-	.band = IEEE80211_BAND_2GHZ,
-	.channels = __wl_2ghz_channels,
-	.n_channels = ARRAY_SIZE(__wl_2ghz_channels),
-	.bitrates = wl_g_rates,
-	.n_bitrates = wl_g_rates_size
-};
-
-static struct ieee80211_supported_band __wl_band_5ghz_a = {
-	.band = IEEE80211_BAND_5GHZ,
-	.channels = __wl_5ghz_a_channels,
-	.n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
-	.bitrates = wl_a_rates,
-	.n_bitrates = wl_a_rates_size
-};
-
-static const u32 __wl_cipher_suites[] = {
-	WLAN_CIPHER_SUITE_WEP40,
-	WLAN_CIPHER_SUITE_WEP104,
-	WLAN_CIPHER_SUITE_TKIP,
-	WLAN_CIPHER_SUITE_CCMP,
-	WLAN_CIPHER_SUITE_AES_CMAC,
-};
-
-#ifdef WL_SUPPORT_ACS
-/*
- * The firmware code required for this feature to work is currently under
- * BCMINTERNAL flag. In future if this is to enabled we need to bring the
- * required firmware code out of the BCMINTERNAL flag.
- */
-struct wl_dump_survey {
-	u32 obss;
-	u32 ibss;
-	u32 no_ctg;
-	u32 no_pckt;
-	u32 tx;
-	u32 idle;
-};
-#endif /* WL_SUPPORT_ACS */
-
-
-#if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
-static int maxrxpktglom = 0;
-#endif
-
-/* IOCtl version read from targeted driver */
-static int ioctl_version;
-#ifdef DEBUGFS_CFG80211
-#define S_SUBLOGLEVEL 20
-static const struct {
-	u32 log_level;
-	char *sublogname;
-} sublogname_map[] = {
-	{WL_DBG_ERR, "ERR"},
-	{WL_DBG_INFO, "INFO"},
-	{WL_DBG_DBG, "DBG"},
-	{WL_DBG_SCAN, "SCAN"},
-	{WL_DBG_TRACE, "TRACE"},
-	{WL_DBG_P2P_ACTION, "P2PACTION"}
-};
-#endif
-
-#ifdef CUSTOMER_HW4_DEBUG
-uint prev_dhd_console_ms = 0;
-u32 prev_wl_dbg_level = 0;
-bool wl_scan_timeout_dbg_enabled = 0;
-static void wl_scan_timeout_dbg_set(void);
-static void wl_scan_timeout_dbg_clear(void);
-
-static void wl_scan_timeout_dbg_set(void)
-{
-	WL_ERR(("Enter \n"));
-	prev_dhd_console_ms = dhd_console_ms;
-	prev_wl_dbg_level = wl_dbg_level;
-
-	dhd_console_ms = 1;
-	wl_dbg_level |= (WL_DBG_ERR | WL_DBG_P2P_ACTION | WL_DBG_SCAN);
-
-	wl_scan_timeout_dbg_enabled = 1;
-}
-static void wl_scan_timeout_dbg_clear(void)
-{
-	WL_ERR(("Enter \n"));
-	dhd_console_ms = prev_dhd_console_ms;
-	wl_dbg_level = prev_wl_dbg_level;
-
-	wl_scan_timeout_dbg_enabled = 0;
-}
-#endif /* CUSTOMER_HW4_DEBUG */
-
-/* watchdog timer for disconnecting when fw is not associated for FW_ASSOC_WATCHDOG_TIME ms */
-uint32 fw_assoc_watchdog_ms = 0;
-bool fw_assoc_watchdog_started = 0;
-#define FW_ASSOC_WATCHDOG_TIME 10 * 1000 /* msec */
-
-#ifdef DHD_IFDEBUG
-
-void wl_dump_ifinfo(struct bcm_cfg80211 *cfg)
-{
-	WL_ERR(("cfg=%p\n", cfg));
-	if (cfg) {
-		WL_ERR(("cfg->wdev=%p\n", bcmcfg_to_prmry_wdev(cfg)));
-		if (bcmcfg_to_prmry_wdev(cfg)) {
-			WL_ERR(("cfg->wdev->wiphy=%p\n", bcmcfg_to_wiphy(cfg)));
-			WL_ERR(("cfg->wdev->netdev=%p\n", bcmcfg_to_prmry_ndev(cfg)));
-		}
-	}
-}
-#endif
-
-static void wl_add_remove_pm_enable_work(struct bcm_cfg80211 *cfg,
-	enum wl_pm_workq_act_type type)
-{
-	u16 wq_duration = 0;
-
-	if (cfg == NULL)
-		return;
-
-	mutex_lock(&cfg->pm_sync);
-	/*
-	 * Make cancel and schedule work part mutually exclusive
-	 * so that while cancelling, we are sure that there is no
-	 * work getting scheduled.
-	 */
-	if (delayed_work_pending(&cfg->pm_enable_work)) {
-		cancel_delayed_work_sync(&cfg->pm_enable_work);
-		DHD_OS_WAKE_UNLOCK(cfg->pub);
-	}
-
-	if (type == WL_PM_WORKQ_SHORT) {
-		wq_duration = WL_PM_ENABLE_TIMEOUT;
-	} else if (type == WL_PM_WORKQ_LONG) {
-		wq_duration = (WL_PM_ENABLE_TIMEOUT*2);
-	}
-	if (wq_duration) {
-		DHD_OS_WAKE_LOCK(cfg->pub);
-		schedule_delayed_work(&cfg->pm_enable_work,
-				msecs_to_jiffies((const unsigned int)wq_duration));
-	}
-	mutex_unlock(&cfg->pm_sync);
-}
-
-/* Return a new chanspec given a legacy chanspec
- * Returns INVCHANSPEC on error
- */
-static chanspec_t
-wl_chspec_from_legacy(chanspec_t legacy_chspec)
-{
-	chanspec_t chspec;
-
-	/* get the channel number */
-	chspec = LCHSPEC_CHANNEL(legacy_chspec);
-
-	/* convert the band */
-	if (LCHSPEC_IS2G(legacy_chspec)) {
-		chspec |= WL_CHANSPEC_BAND_2G;
-	} else {
-		chspec |= WL_CHANSPEC_BAND_5G;
-	}
-
-	/* convert the bw and sideband */
-	if (LCHSPEC_IS20(legacy_chspec)) {
-		chspec |= WL_CHANSPEC_BW_20;
-	} else {
-		chspec |= WL_CHANSPEC_BW_40;
-		if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
-			chspec |= WL_CHANSPEC_CTL_SB_L;
-		} else {
-			chspec |= WL_CHANSPEC_CTL_SB_U;
-		}
-	}
-
-	if (wf_chspec_malformed(chspec)) {
-		WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
-		        chspec));
-		return INVCHANSPEC;
-	}
-
-	return chspec;
-}
-
-/* Return a legacy chanspec given a new chanspec
- * Returns INVCHANSPEC on error
- */
-static chanspec_t
-wl_chspec_to_legacy(chanspec_t chspec)
-{
-	chanspec_t lchspec;
-
-	if (wf_chspec_malformed(chspec)) {
-		WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
-		        chspec));
-		return INVCHANSPEC;
-	}
-
-	/* get the channel number */
-	lchspec = CHSPEC_CHANNEL(chspec);
-
-	/* convert the band */
-	if (CHSPEC_IS2G(chspec)) {
-		lchspec |= WL_LCHANSPEC_BAND_2G;
-	} else {
-		lchspec |= WL_LCHANSPEC_BAND_5G;
-	}
-
-	/* convert the bw and sideband */
-	if (CHSPEC_IS20(chspec)) {
-		lchspec |= WL_LCHANSPEC_BW_20;
-		lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
-	} else if (CHSPEC_IS40(chspec)) {
-		lchspec |= WL_LCHANSPEC_BW_40;
-		if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
-			lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
-		} else {
-			lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
-		}
-	} else {
-		/* cannot express the bandwidth */
-		char chanbuf[CHANSPEC_STR_LEN];
-		WL_ERR((
-		        "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
-		        "to pre-11ac format\n",
-		        wf_chspec_ntoa(chspec, chanbuf), chspec));
-		return INVCHANSPEC;
-	}
-
-	return lchspec;
-}
-
-/* given a chanspec value, do the endian and chanspec version conversion to
- * a chanspec_t value
- * Returns INVCHANSPEC on error
- */
-chanspec_t
-wl_chspec_host_to_driver(chanspec_t chanspec)
-{
-	if (ioctl_version == 1) {
-		chanspec = wl_chspec_to_legacy(chanspec);
-		if (chanspec == INVCHANSPEC) {
-			return chanspec;
-		}
-	}
-	chanspec = htodchanspec(chanspec);
-
-	return chanspec;
-}
-
-/* given a channel value, do the endian and chanspec version conversion to
- * a chanspec_t value
- * Returns INVCHANSPEC on error
- */
-chanspec_t
-wl_ch_host_to_driver(s32 bssidx, u16 channel)
-{
-	chanspec_t chanspec;
-
-	chanspec = channel & WL_CHANSPEC_CHAN_MASK;
-
-	if (channel <= CH_MAX_2G_CHANNEL)
-		chanspec |= WL_CHANSPEC_BAND_2G;
-	else
-		chanspec |= WL_CHANSPEC_BAND_5G;
-
-	chanspec |= wl_cfg80211_ulb_get_min_bw_chspec(NULL, bssidx);
-
-	chanspec |= WL_CHANSPEC_CTL_SB_NONE;
-
-	return wl_chspec_host_to_driver(chanspec);
-}
-
-/* given a chanspec value from the driver, do the endian and chanspec version conversion to
- * a chanspec_t value
- * Returns INVCHANSPEC on error
- */
-chanspec_t
-wl_chspec_driver_to_host(chanspec_t chanspec)
-{
-	chanspec = dtohchanspec(chanspec);
-	if (ioctl_version == 1) {
-		chanspec = wl_chspec_from_legacy(chanspec);
-	}
-
-	return chanspec;
-}
-
-/*
- * convert ASCII string to MAC address (colon-delimited format)
- * eg: 00:11:22:33:44:55
- */
-int
-wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n)
-{
-	char *c = NULL;
-	int count = 0;
-
-	memset(n, 0, ETHER_ADDR_LEN);
-	for (;;) {
-		n->octet[count++] = (uint8)simple_strtoul(a, &c, 16);
-		if (!*c++ || count == ETHER_ADDR_LEN)
-			break;
-		a = c;
-	}
-	return (count == ETHER_ADDR_LEN);
-}
-
-/* There isn't a lot of sense in it, but you can transmit anything you like */
-static const struct ieee80211_txrx_stypes
-wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
-	[NL80211_IFTYPE_ADHOC] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ACTION >> 4)
-	},
-	[NL80211_IFTYPE_STATION] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
-	},
-	[NL80211_IFTYPE_AP] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
-		BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
-		BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
-		BIT(IEEE80211_STYPE_DISASSOC >> 4) |
-		BIT(IEEE80211_STYPE_AUTH >> 4) |
-		BIT(IEEE80211_STYPE_DEAUTH >> 4) |
-		BIT(IEEE80211_STYPE_ACTION >> 4)
-	},
-	[NL80211_IFTYPE_AP_VLAN] = {
-		/* copy AP */
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
-		BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
-		BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
-		BIT(IEEE80211_STYPE_DISASSOC >> 4) |
-		BIT(IEEE80211_STYPE_AUTH >> 4) |
-		BIT(IEEE80211_STYPE_DEAUTH >> 4) |
-		BIT(IEEE80211_STYPE_ACTION >> 4)
-	},
-	[NL80211_IFTYPE_P2P_CLIENT] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
-	},
-	[NL80211_IFTYPE_P2P_GO] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
-		BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
-		BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
-		BIT(IEEE80211_STYPE_DISASSOC >> 4) |
-		BIT(IEEE80211_STYPE_AUTH >> 4) |
-		BIT(IEEE80211_STYPE_DEAUTH >> 4) |
-		BIT(IEEE80211_STYPE_ACTION >> 4)
-	},
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	[NL80211_IFTYPE_P2P_DEVICE] = {
-		.tx = 0xffff,
-		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
-	},
-#endif /* WL_CFG80211_P2P_DEV_IF */
-};
-
-static void swap_key_from_BE(struct wl_wsec_key *key)
-{
-	key->index = htod32(key->index);
-	key->len = htod32(key->len);
-	key->algo = htod32(key->algo);
-	key->flags = htod32(key->flags);
-	key->rxiv.hi = htod32(key->rxiv.hi);
-	key->rxiv.lo = htod16(key->rxiv.lo);
-	key->iv_initialized = htod32(key->iv_initialized);
-}
-
-static void swap_key_to_BE(struct wl_wsec_key *key)
-{
-	key->index = dtoh32(key->index);
-	key->len = dtoh32(key->len);
-	key->algo = dtoh32(key->algo);
-	key->flags = dtoh32(key->flags);
-	key->rxiv.hi = dtoh32(key->rxiv.hi);
-	key->rxiv.lo = dtoh16(key->rxiv.lo);
-	key->iv_initialized = dtoh32(key->iv_initialized);
-}
-
-/* Dump the contents of the encoded wps ie buffer and get pbc value */
-static void
-wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
-{
-	#define WPS_IE_FIXED_LEN 6
-	u16 len;
-	u8 *subel = NULL;
-	u16 subelt_id;
-	u16 subelt_len;
-	u16 val;
-	u8 *valptr = (uint8*) &val;
-	if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
-		WL_ERR(("invalid argument : NULL\n"));
-		return;
-	}
-	len = (u16)wps_ie[TLV_LEN_OFF];
-
-	if (len > wps_ie_len) {
-		WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
-		return;
-	}
-	WL_DBG(("wps_ie len=%d\n", len));
-	len -= 4;	/* for the WPS IE's OUI, oui_type fields */
-	subel = wps_ie + WPS_IE_FIXED_LEN;
-	while (len >= 4) {		/* must have attr id, attr len fields */
-		valptr[0] = *subel++;
-		valptr[1] = *subel++;
-		subelt_id = HTON16(val);
-
-		valptr[0] = *subel++;
-		valptr[1] = *subel++;
-		subelt_len = HTON16(val);
-
-		len -= 4;			/* for the attr id, attr len fields */
-		len -= subelt_len;	/* for the remaining fields in this attribute */
-		WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
-			subel, subelt_id, subelt_len));
-
-		if (subelt_id == WPS_ID_VERSION) {
-			WL_DBG(("  attr WPS_ID_VERSION: %u\n", *subel));
-		} else if (subelt_id == WPS_ID_REQ_TYPE) {
-			WL_DBG(("  attr WPS_ID_REQ_TYPE: %u\n", *subel));
-		} else if (subelt_id == WPS_ID_CONFIG_METHODS) {
-			valptr[0] = *subel;
-			valptr[1] = *(subel + 1);
-			WL_DBG(("  attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
-		} else if (subelt_id == WPS_ID_DEVICE_NAME) {
-			char devname[100];
-			size_t namelen = MIN(subelt_len, sizeof(devname));
-			if (namelen) {
-				memcpy(devname, subel, namelen);
-				devname[namelen - 1] = '\0';
-				WL_DBG(("  attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
-					devname, subelt_len));
-			}
-		} else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
-			valptr[0] = *subel;
-			valptr[1] = *(subel + 1);
-			WL_DBG(("  attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
-			*pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
-		} else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
-			valptr[0] = *subel;
-			valptr[1] = *(subel + 1);
-			WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
-			valptr[0] = *(subel + 6);
-			valptr[1] = *(subel + 7);
-			WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
-		} else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
-			valptr[0] = *subel;
-			valptr[1] = *(subel + 1);
-			WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
-			valptr[0] = *(subel + 6);
-			valptr[1] = *(subel + 7);
-			WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
-		} else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
-			valptr[0] = *subel;
-			valptr[1] = *(subel + 1);
-			WL_DBG(("  attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
-				": cat=%u\n", HTON16(val)));
-		} else {
-			WL_DBG(("  unknown attr 0x%x\n", subelt_id));
-		}
-
-		subel += subelt_len;
-	}
-}
-
-s32 wl_set_tx_power(struct net_device *dev,
-	enum nl80211_tx_power_setting type, s32 dbm)
-{
-	s32 err = 0;
-	s32 disable = 0;
-	s32 txpwrqdbm;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	/* Make sure radio is off or on as far as software is concerned */
-	disable = WL_RADIO_SW_DISABLE << 16;
-	disable = htod32(disable);
-	err = wldev_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable), true);
-	if (unlikely(err)) {
-		WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
-		return err;
-	}
-
-	if (dbm > 0xffff)
-		dbm = 0xffff;
-	txpwrqdbm = dbm * 4;
-	err = wldev_iovar_setbuf_bsscfg(dev, "qtxpower", (void *)&txpwrqdbm,
-		sizeof(txpwrqdbm), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
-		&cfg->ioctl_buf_sync);
-	if (unlikely(err))
-		WL_ERR(("qtxpower error (%d)\n", err));
-	else
-		WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm, txpwrqdbm));
-
-	return err;
-}
-
-s32 wl_get_tx_power(struct net_device *dev, s32 *dbm)
-{
-	s32 err = 0;
-	s32 txpwrdbm;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	err = wldev_iovar_getbuf_bsscfg(dev, "qtxpower",
-		NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
-	if (unlikely(err)) {
-		WL_ERR(("error (%d)\n", err));
-		return err;
-	}
-
-	memcpy(&txpwrdbm, cfg->ioctl_buf, sizeof(txpwrdbm));
-	txpwrdbm = dtoh32(txpwrdbm);
-	*dbm = (txpwrdbm & ~WL_TXPWR_OVERRIDE) / 4;
-
-	WL_INFORM(("dBm=%d, txpwrdbm=0x%x\n", *dbm, txpwrdbm));
-
-	return err;
-}
-
-static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
-{
-	chanspec_t chspec;
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
-	struct ether_addr bssid;
-	struct wl_bss_info *bss = NULL;
-	s32 bssidx = 0; /* Explicitly set to primary bssidx */
-
-	if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
-		/* STA interface is not associated. So start the new interface on a temp
-		 * channel . Later proper channel will be applied by the above framework
-		 * via set_channel (cfg80211 API).
-		 */
-		WL_DBG(("Not associated. Return a temp channel. \n"));
-		return wl_ch_host_to_driver(bssidx, WL_P2P_TEMP_CHAN);
-	}
-
-
-	*(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
-	if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf,
-		WL_EXTRA_BUF_MAX, false))) {
-			WL_ERR(("Failed to get associated bss info, use temp channel \n"));
-			chspec = wl_ch_host_to_driver(bssidx, WL_P2P_TEMP_CHAN);
-	}
-	else {
-			bss = (struct wl_bss_info *) (cfg->extra_buf + 4);
-			chspec =  bss->chanspec;
-
-			WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
-	}
-	return chspec;
-}
-
-static bcm_struct_cfgdev *
-wl_cfg80211_add_monitor_if(char *name)
-{
-#if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
-	WL_INFORM(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
-	return ERR_PTR(-EOPNOTSUPP);
-#else
-	struct net_device* ndev = NULL;
-
-	dhd_add_monitor(name, &ndev);
-	WL_INFORM(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
-	return ndev_to_cfgdev(ndev);
-#endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
-}
-
-static bcm_struct_cfgdev *
-wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	const char *name,
-#else
-	char *name,
-#endif /* WL_CFG80211_P2P_DEV_IF */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
-	unsigned char name_assign_type,
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
-	enum nl80211_iftype type, u32 *flags,
-	struct vif_params *params)
-{
-	s32 err = -ENODEV;
-	s32 timeout = -1;
-	s32 wlif_type = -1;
-	s32 mode = 0;
-	s32 val = 0;
-	s32 cfg_type;
-	s32 dhd_mode = 0;
-	chanspec_t chspec;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *primary_ndev;
-	struct net_device *new_ndev;
-	struct ether_addr primary_mac;
-#ifdef WL_VIRTUAL_APSTA
-	bcm_struct_cfgdev *new_cfgdev;
-#endif /* WL_VIRTUAL_APSTA */
-#ifdef PROP_TXSTATUS_VSDB
-#if defined(BCMSDIO)
-	s32 up = 1;
-	dhd_pub_t *dhd;
-	bool enabled;
-#endif 
-#endif /* PROP_TXSTATUS_VSDB */
-#if defined(SUPPORT_AP_POWERSAVE)
-	dhd_pub_t *dhd;
-#endif /* SUPPORT_AP_POWERSAVE */
-	bool hang_required = false;
-
-	if (!cfg)
-		return ERR_PTR(-EINVAL);
-
-#ifdef PROP_TXSTATUS_VSDB
-#if defined(BCMSDIO)
-	dhd = (dhd_pub_t *)(cfg->pub);
-#endif 
-#endif /* PROP_TXSTATUS_VSDB */
-#if defined(SUPPORT_AP_POWERSAVE)
-	dhd = (dhd_pub_t *)(cfg->pub);
-#endif /* SUPPORT_AP_POWERSAVE */
-
-	/* Use primary I/F for sending cmds down to firmware */
-	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
-
-	if (unlikely(!wl_get_drv_status(cfg, READY, primary_ndev))) {
-		WL_ERR(("device is not ready\n"));
-		return ERR_PTR(-ENODEV);
-	}
-
-	WL_DBG(("if name: %s, type: %d\n", name, type));
-	switch (type) {
-	case NL80211_IFTYPE_ADHOC:
-#ifdef WLAIBSS_MCHAN
-		return bcm_cfg80211_add_ibss_if(wiphy, (char *)name);
-#endif /* WLAIBSS_MCHAN */
-	case NL80211_IFTYPE_AP_VLAN:
-	case NL80211_IFTYPE_WDS:
-	case NL80211_IFTYPE_MESH_POINT:
-		WL_ERR(("Unsupported interface type\n"));
-		mode = WL_MODE_IBSS;
-		return NULL;
-	case NL80211_IFTYPE_MONITOR:
-		return wl_cfg80211_add_monitor_if((char *)name);
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	case NL80211_IFTYPE_P2P_DEVICE:
-		cfg->down_disc_if = FALSE;
-		return wl_cfgp2p_add_p2p_disc_if(cfg);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-	case NL80211_IFTYPE_STATION:
-#ifdef WL_VIRTUAL_APSTA
-#ifdef WLAIBSS_MCHAN
-		if (cfg->ibss_cfgdev) {
-			WL_ERR(("AIBSS is already operational. "
-					" AIBSS & DUALSTA can't be used together \n"));
-			return ERR_PTR(-ENOMEM);
-		}
-#endif /* WLAIBSS_MCHAN */
-		if (!name) {
-			WL_ERR(("Interface name not provided \n"));
-			return ERR_PTR(-ENODEV);
-		}
-
-		if (wl_cfgp2p_vif_created(cfg)) {
-			WL_ERR(("Could not create new iface."
-				"Already one p2p interface is running"));
-			return ERR_PTR(-ENODEV);
-		}
-		new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
-			NL80211_IFTYPE_STATION, NULL, name);
-		if (!new_cfgdev)
-			return ERR_PTR(-ENOMEM);
-		else
-			return new_cfgdev;
-#endif /* WL_VIRTUAL_APSTA */
-	case NL80211_IFTYPE_P2P_CLIENT:
-		wlif_type = WL_P2P_IF_CLIENT;
-		mode = WL_MODE_BSS;
-		break;
-	case NL80211_IFTYPE_P2P_GO:
-	case NL80211_IFTYPE_AP:
-		wlif_type = WL_P2P_IF_GO;
-		mode = WL_MODE_AP;
-		break;
-	default:
-		WL_ERR(("Unsupported interface type\n"));
-		return ERR_PTR(-ENODEV);
-		break;
-	}
-
-	if (!name) {
-		WL_ERR(("name is NULL\n"));
-		return ERR_PTR(-ENODEV);
-	}
-	if (cfg->p2p_supported && (wlif_type != -1)) {
-		ASSERT(cfg->p2p); /* ensure expectation of p2p initialization */
-
-#ifdef PROP_TXSTATUS_VSDB
-#if defined(BCMSDIO)
-		if (!dhd)
-			return ERR_PTR(-ENODEV);
-#endif 
-#endif /* PROP_TXSTATUS_VSDB */
-		if (!cfg->p2p)
-			return ERR_PTR(-ENODEV);
-
-		if (cfg->cfgdev_bssidx != -1) {
-			WL_ERR(("Failed to start p2p, Maximum no of interface reached"));
-			return ERR_PTR(-ENODEV);
-		}
-
-		if (cfg->p2p && !cfg->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
-			p2p_on(cfg) = true;
-			wl_cfgp2p_set_firm_p2p(cfg);
-			wl_cfgp2p_init_discovery(cfg);
-			get_primary_mac(cfg, &primary_mac);
-			wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
-		}
-
-		strncpy(cfg->p2p->vir_ifname, name, IFNAMSIZ - 1);
-		cfg->p2p->vir_ifname[IFNAMSIZ - 1] = '\0';
-
-		wl_cfg80211_scan_abort(cfg);
-#ifdef PROP_TXSTATUS_VSDB
-#if defined(BCMSDIO)
-		if (!cfg->wlfc_on && !disable_proptx) {
-			dhd_wlfc_get_enable(dhd, &enabled);
-			if (!enabled && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
-				dhd->op_mode != DHD_FLAG_IBSS_MODE) {
-				dhd_wlfc_init(dhd);
-				err = wldev_ioctl(primary_ndev, WLC_UP, &up, sizeof(s32), true);
-				if (err < 0)
-					WL_ERR(("WLC_UP return err:%d\n", err));
-			}
-			cfg->wlfc_on = true;
-		}
-#endif 
-#endif /* PROP_TXSTATUS_VSDB */
-
-		/* Dual p2p doesn't support multiple P2PGO interfaces,
-		 * p2p_go_count is the counter for GO creation
-		 * requests.
-		 */
-		if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
-			WL_ERR(("Fw doesnot support  multiple Go"));
-			return ERR_PTR(-ENOMEM);
-		}
-		/* In concurrency case, STA may be already associated in a particular channel.
-		 * so retrieve the current channel of primary interface and then start the virtual
-		 * interface on that.
-		 */
-		 chspec = wl_cfg80211_get_shared_freq(wiphy);
-
-		/* For P2P mode, use P2P-specific driver features to create the
-		 * bss: "cfg p2p_ifadd"
-		 */
-		if (wl_check_dongle_idle(wiphy) != TRUE) {
-			WL_ERR(("FW is busy to add interface"));
-			return ERR_PTR(-ENOMEM);
-		}
-		wl_set_p2p_status(cfg, IF_ADDING);
-		memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
-		if (wlif_type == WL_P2P_IF_GO)
-			wldev_iovar_setint(primary_ndev, "mpc", 0);
-		cfg_type = wl_cfgp2p_get_conn_idx(cfg);
-		if (cfg_type == BCME_ERROR) {
-			wl_clr_p2p_status(cfg, IF_ADDING);
-			WL_ERR(("Failed to get connection idx for p2p interface"));
-			goto fail;
-		}
-		err = wl_cfgp2p_ifadd(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type),
-			htod32(wlif_type), chspec);
-		if (unlikely(err)) {
-			wl_clr_p2p_status(cfg, IF_ADDING);
-			WL_ERR((" virtual iface add failed (%d) \n", err));
-			return ERR_PTR(-ENOMEM);
-		}
-
-		timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
-			((wl_get_p2p_status(cfg, IF_ADDING) == false) &&
-			(cfg->if_event_info.valid)),
-			msecs_to_jiffies(MAX_WAIT_TIME));
-
-		if (timeout > 0 && !wl_get_p2p_status(cfg, IF_ADDING) && cfg->if_event_info.valid) {
-			struct wireless_dev *vwdev;
-			int pm_mode = PM_ENABLE;
-			wl_if_event_info *event = &cfg->if_event_info;
-			/* IF_ADD event has come back, we can proceed to to register
-			 * the new interface now, use the interface name provided by caller (thus
-			 * ignore the one from wlc)
-			 */
-			new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, cfg->p2p->vir_ifname,
-				event->mac, event->bssidx, event->name);
-			if (new_ndev == NULL)
-				goto fail;
-
-			wl_to_p2p_bss_ndev(cfg, cfg_type) = new_ndev;
-			wl_to_p2p_bss_bssidx(cfg, cfg_type) = event->bssidx;
-			vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
-			if (unlikely(!vwdev)) {
-				WL_ERR(("Could not allocate wireless device\n"));
-				err = -ENOMEM;
-				goto fail;
-			}
-			vwdev->wiphy = cfg->wdev->wiphy;
-			WL_INFORM(("virtual interface(%s) is created\n", cfg->p2p->vir_ifname));
-			if (type == NL80211_IFTYPE_P2P_GO) {
-				cfg->p2p->p2p_go_count++;
-			}
-			vwdev->iftype = type;
-#ifdef DHD_IFDEBUG
-			WL_ERR(("new_ndev: %p\n", new_ndev));
-#endif
-			vwdev->netdev = new_ndev;
-			new_ndev->ieee80211_ptr = vwdev;
-			SET_NETDEV_DEV(new_ndev, wiphy_dev(vwdev->wiphy));
-			wl_set_drv_status(cfg, READY, new_ndev);
-			wl_set_mode_by_netdev(cfg, new_ndev, mode);
-
-			if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
-				wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
-				err = -ENODEV;
-				goto fail;
-			}
-			err = wl_alloc_netinfo(cfg, new_ndev, vwdev, mode, pm_mode, event->bssidx);
-			if (unlikely(err != 0)) {
-				WL_ERR(("Allocation of netinfo failed (%d) \n", err));
-				goto fail;
-			}
-			val = 1;
-			/* Disable firmware roaming for P2P interface  */
-			wldev_iovar_setint(new_ndev, "roam_off", val);
-#ifdef WL11ULB
-			if (cfg->p2p_wdev && is_p2p_group_iface(new_ndev->ieee80211_ptr)) {
-				u32 ulb_bw = wl_cfg80211_get_ulb_bw(cfg->p2p_wdev);
-				if (ulb_bw) {
-					/* Apply ULB BW settings on the newly spawned interface */
-					WL_DBG(("[ULB] Applying ULB BW for the newly"
-						"created P2P interface \n"));
-					if (wl_cfg80211_set_ulb_bw(new_ndev,
-						ulb_bw, new_ndev->name) < 0) {
-						/*
-						 * If ulb_bw set failed, fail the iface creation.
-						 * wl_dealloc_netinfo_by_wdev will be called by the
-						 * unregister notifier.
-						 */
-						wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
-						err = -EINVAL;
-						goto fail;
-					}
-				}
-			}
-#endif /* WL11ULB */
-
-			if (mode != WL_MODE_AP)
-				wldev_iovar_setint(new_ndev, "buf_key_b4_m4", 1);
-
-			WL_ERR((" virtual interface(%s) is "
-				"created net attach done\n", cfg->p2p->vir_ifname));
-			if (mode == WL_MODE_AP)
-				wl_set_drv_status(cfg, CONNECTED, new_ndev);
-#ifdef SUPPORT_AP_POWERSAVE
-			if (mode == WL_MODE_AP) {
-				dhd_set_ap_powersave(dhd, 0, TRUE);
-			}
-#endif /* SUPPORT_AP_POWERSAVE */
-			if (type == NL80211_IFTYPE_P2P_CLIENT)
-				dhd_mode = DHD_FLAG_P2P_GC_MODE;
-			else if (type == NL80211_IFTYPE_P2P_GO)
-				dhd_mode = DHD_FLAG_P2P_GO_MODE;
-			DNGL_FUNC(dhd_cfg80211_set_p2p_info, (cfg, dhd_mode));
-			/* reinitialize completion to clear previous count */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
-			INIT_COMPLETION(cfg->iface_disable);
-#else
-			init_completion(&cfg->iface_disable);
-#endif
-			return ndev_to_cfgdev(new_ndev);
-		} else {
-			wl_clr_p2p_status(cfg, IF_ADDING);
-			WL_ERR((" virtual interface(%s) is not created \n", cfg->p2p->vir_ifname));
-
-			WL_ERR(("left timeout : %d\n", timeout));
-			WL_ERR(("IF_ADDING status : %d\n", wl_get_p2p_status(cfg, IF_ADDING)));
-			WL_ERR(("event valid : %d\n", cfg->if_event_info.valid));
-
-			wl_clr_p2p_status(cfg, GO_NEG_PHASE);
-			wl_set_p2p_status(cfg, IF_DELETING);
-
-			err = wl_cfgp2p_ifdel(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type));
-			if (err == BCME_OK) {
-				timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
-					((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
-					(cfg->if_event_info.valid)),
-					msecs_to_jiffies(MAX_WAIT_TIME));
-				if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
-					cfg->if_event_info.valid) {
-					 /*
-					  * Should indicate upper layer this failure case of p2p
-					  * interface creation
-					  */
-					WL_ERR(("IFDEL operation done\n"));
-				} else {
-					WL_ERR(("IFDEL didn't complete properly\n"));
-					hang_required = true;
-				}
-			} else {
-				hang_required = true;
-			}
-
-			if (hang_required) {
-				struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-				dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-
-				WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
-					err, ndev->name));
-				dhd->hang_reason = HANG_REASON_P2P_IFACE_DEL_FAILURE;
-				net_os_send_hang_message(ndev);
-			}
-
-			memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
-			wl_to_p2p_bss_bssidx(cfg, cfg_type) = -1;
-#ifdef PROP_TXSTATUS_VSDB
-#if defined(BCMSDIO)
-			dhd_wlfc_get_enable(dhd, &enabled);
-			if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
-				dhd->op_mode != DHD_FLAG_IBSS_MODE) {
-				dhd_wlfc_deinit(dhd);
-				cfg->wlfc_on = false;
-			}
-#endif 
-#endif /* PROP_TXSTATUS_VSDB */
-			/*
-			* Returns -ENODEV to upperlayer to indicate that DHD
-			* failed to create p2p interface
-			*/
-			err = -ENODEV;
-		}
-	}
-fail:
-	if (wlif_type == WL_P2P_IF_GO)
-		wldev_iovar_setint(primary_ndev, "mpc", 1);
-	return ERR_PTR(err);
-}
-
-static s32
-wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
-{
-	struct net_device *dev = NULL;
-	struct ether_addr p2p_mac;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	s32 timeout = -1;
-	s32 ret = 0;
-	s32 index = -1;
-	s32 type = -1;
-#ifdef CUSTOM_SET_CPUCORE
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-#endif /* CUSTOM_SET_CPUCORE */
-	WL_DBG(("Enter\n"));
-
-#ifdef CUSTOM_SET_CPUCORE
-	dhd->chan_isvht80 &= ~DHD_FLAG_P2P_MODE;
-	if (!(dhd->chan_isvht80))
-		dhd_set_cpucore(dhd, FALSE);
-#endif /* CUSTOM_SET_CPUCORE */
-#ifdef WL_CFG80211_P2P_DEV_IF
-	if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
-		if (dhd_download_fw_on_driverload) {
-			return wl_cfgp2p_del_p2p_disc_if(cfgdev, cfg);
-		} else {
-			cfg->down_disc_if = TRUE;
-			return 0;
-		}
-	}
-#endif /* WL_CFG80211_P2P_DEV_IF */
-	dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-#ifdef WLAIBSS_MCHAN
-	if (cfgdev == cfg->ibss_cfgdev)
-		return bcm_cfg80211_del_ibss_if(wiphy, cfgdev);
-#endif /* WLAIBSS_MCHAN */
-
-#ifdef WL_VIRTUAL_APSTA
-	if (cfgdev == cfg->bss_cfgdev)
-		return wl_cfg80211_del_iface(wiphy, cfgdev);
-#endif /* WL_VIRTUAL_APSTA */
-	if ((index = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
-		WL_ERR(("Find p2p index from wdev failed\n"));
-		return BCME_ERROR;
-	}
-	if (wl_check_dongle_idle(wiphy) != TRUE) {
-		WL_ERR(("FW is busy to add interface"));
-		return BCME_ERROR;
-	}
-	if (cfg->p2p_supported) {
-		if (wl_cfgp2p_find_type(cfg, index, &type) != BCME_OK)
-			return BCME_ERROR;
-		memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet, ETHER_ADDR_LEN);
-
-		/* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
-		 */
-		WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
-		wl_clr_p2p_status(cfg, GO_NEG_PHASE);
-		if (wl_cfgp2p_vif_created(cfg)) {
-			if (wl_get_drv_status(cfg, SCANNING, dev)) {
-				wl_notify_escan_complete(cfg, dev, true, true);
-			}
-			wldev_iovar_setint(dev, "mpc", 1);
-			/* Delete pm_enable_work */
-			wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
-
-			/* for GC */
-			if (wl_get_drv_status(cfg, DISCONNECTING, dev) &&
-				(wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)) {
-				WL_ERR(("Wait for Link Down event for GC !\n"));
-				wait_for_completion_timeout
-					(&cfg->iface_disable, msecs_to_jiffies(500));
-			}
-
-			memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
-			wl_set_p2p_status(cfg, IF_DELETING);
-			DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (cfg));
-
-			/* for GO */
-			if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
-				wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
-				cfg->p2p->p2p_go_count--;
-				/* disable interface before bsscfg free */
-				ret = wl_cfgp2p_ifdisable(cfg, &p2p_mac);
-				/* if fw doesn't support "ifdis",
-				   do not wait for link down of ap mode
-				 */
-				if (ret == 0) {
-					WL_ERR(("Wait for Link Down event for GO !!!\n"));
-					wait_for_completion_timeout(&cfg->iface_disable,
-						msecs_to_jiffies(500));
-				} else if (ret != BCME_UNSUPPORTED) {
-					msleep(300);
-				}
-			}
-			wl_cfg80211_clear_per_bss_ies(cfg, index);
-
-			if (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)
-				wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
-			memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet,
-			ETHER_ADDR_LEN);
-			CFGP2P_INFO(("primary idx %d : cfg p2p_ifdis "MACDBG"\n",
-			       dev->ifindex, MAC2STRDBG(p2p_mac.octet)));
-
-			/* delete interface after link down */
-			ret = wl_cfgp2p_ifdel(cfg, &p2p_mac);
-			if (ret != BCME_OK) {
-				struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-				dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-
-				WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
-					ret, ndev->name));
-				dhd->hang_reason = HANG_REASON_P2P_IFACE_DEL_FAILURE;
-				net_os_send_hang_message(ndev);
-			} else {
-				/* Wait for IF_DEL operation to be finished */
-				timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
-					((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
-					(cfg->if_event_info.valid)),
-					msecs_to_jiffies(MAX_WAIT_TIME));
-				if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
-					cfg->if_event_info.valid) {
-
-					WL_DBG(("IFDEL operation done\n"));
-					wl_cfg80211_handle_ifdel(cfg, &cfg->if_event_info, dev);
-				} else {
-					WL_ERR(("IFDEL didn't complete properly\n"));
-				}
-			}
-
-			ret = dhd_del_monitor(dev);
-			if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
-				DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t *)(cfg->pub));
-			}
-		}
-	}
-	return ret;
-}
-
-static s32
-wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
-	enum nl80211_iftype type, u32 *flags,
-	struct vif_params *params)
-{
-	s32 ap = 0;
-	s32 infra = 0;
-	s32 ibss = 0;
-	s32 wlif_type;
-	s32 mode = 0;
-	s32 err = BCME_OK;
-	s32 index;
-	s32 conn_idx = -1;
-	chanspec_t chspec;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-
-	WL_DBG(("Enter type %d\n", type));
-	switch (type) {
-	case NL80211_IFTYPE_MONITOR:
-	case NL80211_IFTYPE_WDS:
-	case NL80211_IFTYPE_MESH_POINT:
-		ap = 1;
-		WL_ERR(("type (%d) : currently we do not support this type\n",
-			type));
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		mode = WL_MODE_IBSS;
-		ibss = 1;
-		break;
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_P2P_CLIENT:
-		mode = WL_MODE_BSS;
-		infra = 1;
-		break;
-	case NL80211_IFTYPE_AP:
-		dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
-		/* intentional fall through */
-	case NL80211_IFTYPE_AP_VLAN:
-	case NL80211_IFTYPE_P2P_GO:
-		mode = WL_MODE_AP;
-		ap = 1;
-		break;
-	default:
-		return -EINVAL;
-	}
-	if (!dhd)
-		return -EINVAL;
-
-	/* If any scan is going on, abort it */
-	if (wl_get_drv_status_all(cfg, SCANNING)) {
-		int wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
-		WL_ERR(("Scan in progress. Aborting the scan!\n"));
-		wl_cfg80211_scan_abort(cfg);
-		while (wl_get_drv_status_all(cfg, SCANNING) && wait_cnt) {
-			WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
-			wait_cnt--;
-			OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
-		}
-		if (wl_get_drv_status_all(cfg, SCANNING)) {
-			wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
-		}
-	}
-
-	if (wl_check_dongle_idle(wiphy) != TRUE) {
-		WL_ERR(("FW is busy to add interface"));
-		return -EINVAL;
-	}
-	if (ap) {
-		wl_set_mode_by_netdev(cfg, ndev, mode);
-		if (is_p2p_group_iface(ndev->ieee80211_ptr) &&
-			cfg->p2p && wl_cfgp2p_vif_created(cfg)) {
-			WL_DBG(("p2p_vif_created p2p_on (%d)\n", p2p_on(cfg)));
-			wldev_iovar_setint(ndev, "mpc", 0);
-			wl_notify_escan_complete(cfg, ndev, true, true);
-
-			/* Dual p2p doesn't support multiple P2PGO interfaces,
-			 * p2p_go_count is the counter for GO creation
-			 * requests.
-			 */
-			if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
-				wl_set_mode_by_netdev(cfg, ndev, WL_MODE_BSS);
-				WL_ERR(("Fw doesnot support  multiple GO "));
-				return BCME_ERROR;
-			}
-			/* In concurrency case, STA may be already associated in a particular
-			 * channel. so retrieve the current channel of primary interface and
-			 * then start the virtual interface on that.
-			 */
-			chspec = wl_cfg80211_get_shared_freq(wiphy);
-			index = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
-			if (index < 0) {
-				WL_ERR(("Find p2p index from ndev(%p) failed\n", ndev));
-				return BCME_ERROR;
-			}
-			if (wl_cfgp2p_find_type(cfg, index, &conn_idx) != BCME_OK)
-				return BCME_ERROR;
-
-			wlif_type = WL_P2P_IF_GO;
-			WL_DBG(("%s : ap (%d), infra (%d), iftype (%d) conn_idx (%d)\n",
-				ndev->name, ap, infra, type, conn_idx));
-			wl_set_p2p_status(cfg, IF_CHANGING);
-			wl_clr_p2p_status(cfg, IF_CHANGED);
-			wl_cfgp2p_ifchange(cfg, wl_to_p2p_bss_macaddr(cfg, conn_idx),
-				htod32(wlif_type), chspec, conn_idx);
-			wait_event_interruptible_timeout(cfg->netif_change_event,
-				(wl_get_p2p_status(cfg, IF_CHANGED) == true),
-				msecs_to_jiffies(MAX_WAIT_TIME));
-			wl_set_mode_by_netdev(cfg, ndev, mode);
-			dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
-			dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
-			wl_clr_p2p_status(cfg, IF_CHANGING);
-			wl_clr_p2p_status(cfg, IF_CHANGED);
-			if (mode == WL_MODE_AP)
-				wl_set_drv_status(cfg, CONNECTED, ndev);
-#ifdef SUPPORT_AP_POWERSAVE
-			dhd_set_ap_powersave(dhd, 0, TRUE);
-#endif /* SUPPORT_AP_POWERSAVE */
-		} else if (((ndev == primary_ndev) ||
-			(ndev == ((struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev)))) &&
-			!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
-			wl_set_drv_status(cfg, AP_CREATING, ndev);
-		} else {
-			WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
-			return -EINVAL;
-		}
-	} else {
-		/* P2P GO interface deletion is handled on the basis of role type (AP).
-		 * So avoid changing role for p2p type.
-		 */
-		if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
-			wl_set_mode_by_netdev(cfg, ndev, mode);
-		WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA"));
-#ifdef SUPPORT_AP_POWERSAVE
-		dhd_set_ap_powersave(dhd, 0, FALSE);
-#endif /* SUPPORT_AP_POWERSAVE */
-	}
-
-	if (ibss) {
-		infra = 0;
-		wl_set_mode_by_netdev(cfg, ndev, mode);
-		err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
-		if (err < 0) {
-			WL_ERR(("SET Adhoc error %d\n", err));
-			return -EINVAL;
-		}
-	}
-
-	ndev->ieee80211_ptr->iftype = type;
-	return 0;
-}
-
-s32
-wl_cfg80211_notify_ifadd(int ifidx, char *name, uint8 *mac, uint8 bssidx)
-{
-	bool ifadd_expected = FALSE;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	/* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
-	 * redirect the IF_ADD event to ifchange as it is not a real "new" interface
-	 */
-	if (wl_get_p2p_status(cfg, IF_CHANGING))
-		return wl_cfg80211_notify_ifchange(ifidx, name, mac, bssidx);
-
-	/* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
-	if (wl_get_p2p_status(cfg, IF_ADDING)) {
-		ifadd_expected = TRUE;
-		wl_clr_p2p_status(cfg, IF_ADDING);
-	} else if (cfg->bss_pending_op) {
-		ifadd_expected = TRUE;
-		cfg->bss_pending_op = FALSE;
-	}
-
-	if (ifadd_expected) {
-		wl_if_event_info *if_event_info = &cfg->if_event_info;
-
-		if_event_info->valid = TRUE;
-		if_event_info->ifidx = ifidx;
-		if_event_info->bssidx = bssidx;
-		strncpy(if_event_info->name, name, IFNAMSIZ);
-		if_event_info->name[IFNAMSIZ] = '\0';
-		if (mac)
-			memcpy(if_event_info->mac, mac, ETHER_ADDR_LEN);
-		wake_up_interruptible(&cfg->netif_change_event);
-		return BCME_OK;
-	}
-
-	return BCME_ERROR;
-}
-
-s32
-wl_cfg80211_notify_ifdel(int ifidx, char *name, uint8 *mac, uint8 bssidx)
-{
-	bool ifdel_expected = FALSE;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	wl_if_event_info *if_event_info = &cfg->if_event_info;
-
-	if (wl_get_p2p_status(cfg, IF_DELETING)) {
-		ifdel_expected = TRUE;
-		wl_clr_p2p_status(cfg, IF_DELETING);
-	} else if (cfg->bss_pending_op) {
-		ifdel_expected = TRUE;
-		cfg->bss_pending_op = FALSE;
-	}
-
-	if (ifdel_expected) {
-		if_event_info->valid = TRUE;
-		if_event_info->ifidx = ifidx;
-		if_event_info->bssidx = bssidx;
-		wake_up_interruptible(&cfg->netif_change_event);
-		return BCME_OK;
-	}
-
-	return BCME_ERROR;
-}
-
-s32
-wl_cfg80211_notify_ifchange(int ifidx, char *name, uint8 *mac, uint8 bssidx)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	if (wl_get_p2p_status(cfg, IF_CHANGING)) {
-		wl_set_p2p_status(cfg, IF_CHANGED);
-		wake_up_interruptible(&cfg->netif_change_event);
-		return BCME_OK;
-	}
-
-	return BCME_ERROR;
-}
-
-static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
-	struct net_device* ndev)
-{
-	s32 type = -1;
-	s32 bssidx = -1;
-#ifdef PROP_TXSTATUS_VSDB
-#if defined(BCMSDIO)
-	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
-	bool enabled;
-#endif 
-#endif /* PROP_TXSTATUS_VSDB */
-
-	bssidx = if_event_info->bssidx;
-	if (bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) &&
-		bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2)) {
-		WL_ERR(("got IF_DEL for if %d, not owned by cfg driver\n", bssidx));
-		return BCME_ERROR;
-	}
-
-	if (p2p_is_on(cfg) && wl_cfgp2p_vif_created(cfg)) {
-		if (cfg->scan_request && (cfg->escan_info.ndev == ndev)) {
-			/* Abort any pending scan requests */
-			cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
-			WL_DBG(("ESCAN COMPLETED\n"));
-			wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, false);
-		}
-
-		memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
-		if (wl_cfgp2p_find_type(cfg, bssidx, &type) == BCME_OK) {
-			/* Update P2P data */
-			wl_clr_drv_status(cfg, CONNECTED, wl_to_p2p_bss_ndev(cfg, type));
-			wl_to_p2p_bss_ndev(cfg, type) = NULL;
-			wl_to_p2p_bss_bssidx(cfg, type) = -1;
-		} else if (wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr) < 0) {
-			WL_ERR(("bssidx not known for the given ndev as per net_info data \n"));
-			return BCME_ERROR;
-		}
-
-#ifdef PROP_TXSTATUS_VSDB
-#if defined(BCMSDIO)
-		dhd_wlfc_get_enable(dhd, &enabled);
-		if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
-			dhd->op_mode != DHD_FLAG_IBSS_MODE) {
-			dhd_wlfc_deinit(dhd);
-			cfg->wlfc_on = false;
-		}
-#endif 
-#endif /* PROP_TXSTATUS_VSDB */
-	}
-
-	dhd_net_if_lock(ndev);
-	wl_cfg80211_remove_if(cfg, if_event_info->ifidx, ndev);
-	dhd_net_if_unlock(ndev);
-
-	return BCME_OK;
-}
-
-/* Find listen channel */
-static s32 wl_find_listen_channel(struct bcm_cfg80211 *cfg,
-	const u8 *ie, u32 ie_len)
-{
-	wifi_p2p_ie_t *p2p_ie;
-	u8 *end, *pos;
-	s32 listen_channel;
-
-/* unfortunately const cast required here - function is
- * a callback so its signature must not be changed
- * and cascade of changing wl_cfgp2p_find_p2pie
- * causes need for const cast in other places
- */
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-	pos = (u8 *)ie;
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-	p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
-
-	if (p2p_ie == NULL)
-		return 0;
-
-	pos = p2p_ie->subelts;
-	end = p2p_ie->subelts + (p2p_ie->len - 4);
-
-	CFGP2P_DBG((" found p2p ie ! lenth %d \n",
-		p2p_ie->len));
-
-	while (pos < end) {
-		uint16 attr_len;
-		if (pos + 2 >= end) {
-			CFGP2P_DBG((" -- Invalid P2P attribute"));
-			return 0;
-		}
-		attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
-
-		if (pos + 3 + attr_len > end) {
-			CFGP2P_DBG(("P2P: Attribute underflow "
-				   "(len=%u left=%d)",
-				   attr_len, (int) (end - pos - 3)));
-			return 0;
-		}
-
-		/* if Listen Channel att id is 6 and the vailue is valid,
-		 * return the listen channel
-		 */
-		if (pos[0] == 6) {
-			/* listen channel subel length format
-			 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
-			 */
-			listen_channel = pos[1 + 2 + 3 + 1];
-
-			if (listen_channel == SOCIAL_CHAN_1 ||
-				listen_channel == SOCIAL_CHAN_2 ||
-				listen_channel == SOCIAL_CHAN_3) {
-				CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
-				return listen_channel;
-			}
-		}
-		pos += 3 + attr_len;
-	}
-	return 0;
-}
-
-static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
-{
-	u32 n_ssids;
-	u32 n_channels;
-	u16 channel;
-	chanspec_t chanspec;
-	s32 i = 0, j = 0, offset;
-	char *ptr;
-	wlc_ssid_t ssid;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wireless_dev *wdev;
-
-	memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
-	params->bss_type = DOT11_BSSTYPE_ANY;
-	params->scan_type = 0;
-	params->nprobes = -1;
-	params->active_time = -1;
-	params->passive_time = -1;
-	params->home_time = -1;
-	params->channel_num = 0;
-	memset(&params->ssid, 0, sizeof(wlc_ssid_t));
-
-	WL_SCAN(("Preparing Scan request\n"));
-	WL_SCAN(("nprobes=%d\n", params->nprobes));
-	WL_SCAN(("active_time=%d\n", params->active_time));
-	WL_SCAN(("passive_time=%d\n", params->passive_time));
-	WL_SCAN(("home_time=%d\n", params->home_time));
-	WL_SCAN(("scan_type=%d\n", params->scan_type));
-
-	params->nprobes = htod32(params->nprobes);
-	params->active_time = htod32(params->active_time);
-	params->passive_time = htod32(params->passive_time);
-	params->home_time = htod32(params->home_time);
-
-	/* if request is null just exit so it will be all channel broadcast scan */
-	if (!request)
-		return;
-
-	n_ssids = request->n_ssids;
-	n_channels = request->n_channels;
-
-	/* Copy channel array if applicable */
-	WL_SCAN(("### List of channelspecs to scan ###\n"));
-	if (n_channels > 0) {
-		for (i = 0; i < n_channels; i++) {
-			chanspec = 0;
-			channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
-			/* SKIP DFS channels for Secondary interface */
-			if ((cfg->escan_info.ndev != bcmcfg_to_prmry_ndev(cfg)) &&
-				(request->channels[i]->flags &
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
-				(IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
-#else
-				(IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR)))
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
-				continue;
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-			wdev = request->wdev;
-#else
-			wdev = request->dev->ieee80211_ptr;
-#endif /* WL_CFG80211_P2P_DEV_IF */
-			chanspec = wl_cfg80211_ulb_get_min_bw_chspec(wdev, -1);
-			if (chanspec == INVCHANSPEC) {
-				WL_ERR(("Invalid chanspec! Skipping channel\n"));
-				continue;
-			}
-
-			if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
-				chanspec |= WL_CHANSPEC_BAND_2G;
-			} else {
-				chanspec |= WL_CHANSPEC_BAND_5G;
-			}
-			params->channel_list[j] = channel;
-			params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
-			params->channel_list[j] |= chanspec;
-			WL_SCAN(("Chan : %d, Channel spec: %x \n",
-				channel, params->channel_list[j]));
-			params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
-			j++;
-		}
-	} else {
-		WL_SCAN(("Scanning all channels\n"));
-	}
-	n_channels = j;
-	/* Copy ssid array if applicable */
-	WL_SCAN(("### List of SSIDs to scan ###\n"));
-	if (n_ssids > 0) {
-		offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
-		offset = roundup(offset, sizeof(u32));
-		ptr = (char*)params + offset;
-		for (i = 0; i < n_ssids; i++) {
-			memset(&ssid, 0, sizeof(wlc_ssid_t));
-			ssid.SSID_len = request->ssids[i].ssid_len;
-			memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
-			if (!ssid.SSID_len)
-				WL_SCAN(("%d: Broadcast scan\n", i));
-			else
-				WL_SCAN(("%d: scan  for  %s size =%d\n", i,
-				ssid.SSID, ssid.SSID_len));
-			memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
-			ptr += sizeof(wlc_ssid_t);
-		}
-	} else {
-		WL_SCAN(("Broadcast scan\n"));
-	}
-	/* Adding mask to channel numbers */
-	params->channel_num =
-	        htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
-	               (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
-
-	if (n_channels == 1) {
-		params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
-		params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
-	}
-}
-
-static s32
-wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
-{
-	wl_uint32_list_t *list;
-	s32 err = BCME_OK;
-	if (valid_chan_list == NULL || size <= 0)
-		return -ENOMEM;
-
-	memset(valid_chan_list, 0, size);
-	list = (wl_uint32_list_t *)(void *) valid_chan_list;
-	list->count = htod32(WL_NUMCHANNELS);
-	err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
-	if (err != 0) {
-		WL_ERR(("get channels failed with %d\n", err));
-	}
-
-	return err;
-}
-
-#if defined(USE_INITIAL_SHORT_DWELL_TIME)
-#define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
-bool g_first_broadcast_scan = TRUE;
-#endif 
-
-static s32
-wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	struct cfg80211_scan_request *request, uint16 action)
-{
-	s32 err = BCME_OK;
-	u32 n_channels;
-	u32 n_ssids;
-	s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
-	wl_escan_params_t *params = NULL;
-	u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
-	u32 num_chans = 0;
-	s32 channel;
-	u32 n_valid_chan;
-	s32 search_state = WL_P2P_DISC_ST_SCAN;
-	u32 i, j, n_nodfs = 0;
-	u16 *default_chan_list = NULL;
-	wl_uint32_list_t *list;
-	s32 bssidx = -1;
-	struct net_device *dev = NULL;
-#if defined(USE_INITIAL_SHORT_DWELL_TIME)
-	bool is_first_init_2g_scan = false;
-#endif 
-	p2p_scan_purpose_t	p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
-
-	WL_DBG(("Enter \n"));
-
-	/* scan request can come with empty request : perform all default scan */
-	if (!cfg) {
-		err = -EINVAL;
-		goto exit;
-	}
-	if (!cfg->p2p_supported || !p2p_scan(cfg)) {
-		/* LEGACY SCAN TRIGGER */
-		WL_ERR((" LEGACY E-SCAN START\n"));
-
-#if defined(USE_INITIAL_SHORT_DWELL_TIME)
-		if (!request) {
-			err = -EINVAL;
-			goto exit;
-		}
-		if (ndev == bcmcfg_to_prmry_ndev(cfg) && g_first_broadcast_scan == true) {
-			is_first_init_2g_scan = true;
-			g_first_broadcast_scan = false;
-		}
-#endif 
-
-		/* if scan request is not empty parse scan request paramters */
-		if (request != NULL) {
-			n_channels = request->n_channels;
-			n_ssids = request->n_ssids;
-			if (n_channels % 2)
-				/* If n_channels is odd, add a padd of u16 */
-				params_size += sizeof(u16) * (n_channels + 1);
-			else
-				params_size += sizeof(u16) * n_channels;
-
-			/* Allocate space for populating ssids in wl_escan_params_t struct */
-			params_size += sizeof(struct wlc_ssid) * n_ssids;
-		}
-		params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
-		if (params == NULL) {
-			err = -ENOMEM;
-			goto exit;
-		}
-		wl_scan_prep(&params->params, request);
-
-#if defined(USE_INITIAL_SHORT_DWELL_TIME)
-		/* Override active_time to reduce scan time if it's first bradcast scan. */
-		if (is_first_init_2g_scan)
-			params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
-#endif 
-
-		params->version = htod32(ESCAN_REQ_VERSION);
-		params->action =  htod16(action);
-		wl_escan_set_sync_id(params->sync_id, cfg);
-		wl_escan_set_type(cfg, WL_SCANTYPE_LEGACY);
-		if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
-			WL_ERR(("ioctl buffer length not sufficient\n"));
-			kfree(params);
-			err = -ENOMEM;
-			goto exit;
-		}
-		if (cfg->active_scan == PASSIVE_SCAN) {
-			params->params.scan_type = DOT11_SCANTYPE_PASSIVE;
-			WL_DBG(("Passive scan_type %d \n", params->params.scan_type));
-		}
-
-		bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
-
-		err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
-			cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
-		WL_ERR(("LEGACY_SCAN sync ID: %d, bssidx: %d\n", params->sync_id, bssidx));
-		if (unlikely(err)) {
-			if (err == BCME_EPERM)
-				/* Scan Not permitted at this point of time */
-				WL_DBG((" Escan not permitted at this time (%d)\n", err));
-			else
-				WL_ERR((" Escan set error (%d)\n", err));
-		}
-		kfree(params);
-	}
-	else if (p2p_is_on(cfg) && p2p_scan(cfg)) {
-		/* P2P SCAN TRIGGER */
-		s32 _freq = 0;
-		n_nodfs = 0;
-		if (request && request->n_channels) {
-			num_chans = request->n_channels;
-			WL_ERR((" chann number : %d\n", num_chans));
-			default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
-				GFP_KERNEL);
-			if (default_chan_list == NULL) {
-				WL_ERR(("channel list allocation failed \n"));
-				err = -ENOMEM;
-				goto exit;
-			}
-			if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
-#ifdef P2P_SKIP_DFS
-				int is_printed = false;
-#endif /* P2P_SKIP_DFS */
-				list = (wl_uint32_list_t *) chan_buf;
-				n_valid_chan = dtoh32(list->count);
-				for (i = 0; i < num_chans; i++)
-				{
-					_freq = request->channels[i]->center_freq;
-					channel = ieee80211_frequency_to_channel(_freq);
-
-					/* ignore DFS channels */
-					if (request->channels[i]->flags &
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
-						(IEEE80211_CHAN_NO_IR
-						| IEEE80211_CHAN_RADAR))
-#else
-						(IEEE80211_CHAN_RADAR
-						| IEEE80211_CHAN_PASSIVE_SCAN))
-#endif
-						continue;
-#ifdef P2P_SKIP_DFS
-					if (channel >= 52 && channel <= 144) {
-						if (is_printed == false) {
-							WL_ERR(("SKIP DFS CHANs(52~144)\n"));
-							is_printed = true;
-						}
-						continue;
-					}
-#endif /* P2P_SKIP_DFS */
-
-					for (j = 0; j < n_valid_chan; j++) {
-						/* allows only supported channel on
-						*  current reguatory
-						*/
-						if (channel == (dtoh32(list->element[j])))
-							default_chan_list[n_nodfs++] =
-								channel;
-					}
-
-				}
-			}
-			if (num_chans == SOCIAL_CHAN_CNT && (
-						(default_chan_list[0] == SOCIAL_CHAN_1) &&
-						(default_chan_list[1] == SOCIAL_CHAN_2) &&
-						(default_chan_list[2] == SOCIAL_CHAN_3))) {
-				/* SOCIAL CHANNELS 1, 6, 11 */
-				search_state = WL_P2P_DISC_ST_SEARCH;
-				p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
-				WL_INFORM(("P2P SEARCH PHASE START \n"));
-			} else if (((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1)) &&
-				(wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) ||
-				((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2)) &&
-				(wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP))) {
-				/* If you are already a GO, then do SEARCH only */
-				WL_INFORM(("Already a GO. Do SEARCH Only"));
-				search_state = WL_P2P_DISC_ST_SEARCH;
-				num_chans = n_nodfs;
-				p2p_scan_purpose = P2P_SCAN_NORMAL;
-
-			} else if (num_chans == 1) {
-				p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
-			} else if (num_chans == SOCIAL_CHAN_CNT + 1) {
-			/* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
-			 * the supplicant
-			 */
-				p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
-			} else {
-				WL_INFORM(("P2P SCAN STATE START \n"));
-				num_chans = n_nodfs;
-				p2p_scan_purpose = P2P_SCAN_NORMAL;
-			}
-		} else {
-			err = -EINVAL;
-			goto exit;
-		}
-		err = wl_cfgp2p_escan(cfg, ndev, ACTIVE_SCAN, num_chans, default_chan_list,
-			search_state, action,
-			wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE), NULL,
-			p2p_scan_purpose);
-
-		if (!err)
-			cfg->p2p->search_state = search_state;
-
-		kfree(default_chan_list);
-	}
-exit:
-	if (unlikely(err)) {
-		/* Don't print Error incase of Scan suppress */
-		if ((err == BCME_EPERM) && cfg->scan_suppressed)
-			WL_DBG(("Escan failed: Scan Suppressed \n"));
-		else
-			WL_ERR(("error (%d)\n", err));
-	}
-	return err;
-}
-
-
-static s32
-wl_do_escan(struct bcm_cfg80211 *cfg, struct wiphy *wiphy, struct net_device *ndev,
-	struct cfg80211_scan_request *request)
-{
-	s32 err = BCME_OK;
-	s32 passive_scan;
-	s32 passive_scan_time;
-	s32 passive_scan_time_org;
-	wl_scan_results_t *results;
-	WL_SCAN(("Enter \n"));
-
-	results = wl_escan_get_buf(cfg, FALSE);
-	results->version = 0;
-	results->count = 0;
-	results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
-
-	cfg->escan_info.ndev = ndev;
-	cfg->escan_info.wiphy = wiphy;
-	cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
-	passive_scan = cfg->active_scan ? 0 : 1;
-	err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
-		&passive_scan, sizeof(passive_scan), true);
-	if (unlikely(err)) {
-		WL_ERR(("error (%d)\n", err));
-		goto exit;
-	}
-
-	if (passive_channel_skip) {
-
-		err = wldev_ioctl(ndev, WLC_GET_SCAN_PASSIVE_TIME,
-			&passive_scan_time_org, sizeof(passive_scan_time_org), false);
-		if (unlikely(err)) {
-			WL_ERR(("== error (%d)\n", err));
-			goto exit;
-		}
-
-		WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org));
-
-		passive_scan_time = 0;
-		err = wldev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME,
-			&passive_scan_time, sizeof(passive_scan_time), true);
-		if (unlikely(err)) {
-			WL_ERR(("== error (%d)\n", err));
-			goto exit;
-		}
-
-		WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
-			passive_channel_skip));
-	}
-
-	err = wl_run_escan(cfg, ndev, request, WL_SCAN_ACTION_START);
-
-	if (passive_channel_skip) {
-		err = wldev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME,
-			&passive_scan_time_org, sizeof(passive_scan_time_org), true);
-		if (unlikely(err)) {
-			WL_ERR(("== error (%d)\n", err));
-			goto exit;
-		}
-
-		WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
-			passive_scan_time_org));
-	}
-
-exit:
-	return err;
-}
-
-static s32
-__wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
-	struct cfg80211_scan_request *request,
-	struct cfg80211_ssid *this_ssid)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct cfg80211_ssid *ssids;
-	struct ether_addr primary_mac;
-	bool p2p_ssid;
-#ifdef WL11U
-	bcm_tlv_t *interworking_ie;
-#endif
-	s32 err = 0;
-	s32 bssidx = -1;
-	s32 i;
-
-	unsigned long flags;
-	static s32 busy_count = 0;
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-	struct net_device *remain_on_channel_ndev = NULL;
-#endif
-
-	/*
-	 * Hostapd triggers scan before starting automatic channel selection
-	 * to collect channel characteristics. However firmware scan engine
-	 * doesn't support any channel characteristics collection along with
-	 * scan. Hence return scan success.
-	 */
-	if (request && (scan_req_iftype(request) == NL80211_IFTYPE_AP)) {
-		WL_INFORM(("Scan Command on SoftAP Interface. Ignoring...\n"));
-		return 0;
-	}
-
-	ndev = ndev_to_wlc_ndev(ndev, cfg);
-
-	if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
-		WL_ERR(("Sending Action Frames. Try it again.\n"));
-		return -EAGAIN;
-	}
-
-	WL_DBG(("Enter wiphy (%p)\n", wiphy));
-	if (wl_get_drv_status_all(cfg, SCANNING)) {
-		if (cfg->scan_request == NULL) {
-			wl_clr_drv_status_all(cfg, SCANNING);
-			WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
-		} else {
-			WL_ERR(("Scanning already\n"));
-			return -EAGAIN;
-		}
-	}
-	if (wl_get_drv_status(cfg, SCAN_ABORTING, ndev)) {
-		WL_ERR(("Scanning being aborted\n"));
-		return -EAGAIN;
-	}
-	if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
-		WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
-		return -EOPNOTSUPP;
-	}
-
-#ifdef P2P_LISTEN_OFFLOADING
-	if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
-		WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
-		return -EAGAIN;
-	}
-#endif /* P2P_LISTEN_OFFLOADING */
-
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-	remain_on_channel_ndev = wl_cfg80211_get_remain_on_channel_ndev(cfg);
-	if (remain_on_channel_ndev) {
-		WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
-		wl_notify_escan_complete(cfg, remain_on_channel_ndev, true, true);
-	}
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-
-
-	/* Arm scan timeout timer */
-	mod_timer(&cfg->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
-	if (request) {		/* scan bss */
-		ssids = request->ssids;
-		p2p_ssid = false;
-		for (i = 0; i < request->n_ssids; i++) {
-			if (ssids[i].ssid_len &&
-				IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
-				p2p_ssid = true;
-				break;
-			}
-		}
-		if (p2p_ssid) {
-			if (cfg->p2p_supported) {
-				/* p2p scan trigger */
-				if (p2p_on(cfg) == false) {
-					/* p2p on at the first time */
-					p2p_on(cfg) = true;
-					wl_cfgp2p_set_firm_p2p(cfg);
-					get_primary_mac(cfg, &primary_mac);
-					wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
-#if defined(P2P_IE_MISSING_FIX)
-					cfg->p2p_prb_noti = false;
-#endif
-				}
-				wl_clr_p2p_status(cfg, GO_NEG_PHASE);
-				WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
-				p2p_scan(cfg) = true;
-			}
-		} else {
-			/* legacy scan trigger
-			 * So, we have to disable p2p discovery if p2p discovery is on
-			 */
-			if (cfg->p2p_supported) {
-				p2p_scan(cfg) = false;
-				/* If Netdevice is not equals to primary and p2p is on
-				*  , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
-				*/
-
-				if (p2p_scan(cfg) == false) {
-					if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
-						err = wl_cfgp2p_discover_enable_search(cfg,
-						false);
-						if (unlikely(err)) {
-							goto scan_out;
-						}
-
-					}
-				}
-			}
-			if (!cfg->p2p_supported || !p2p_scan(cfg)) {
-				if ((bssidx = wl_get_bssidx_by_wdev(cfg,
-					ndev->ieee80211_ptr)) < 0) {
-					WL_ERR(("Find p2p index from ndev(%p) failed\n",
-						ndev));
-					err = BCME_ERROR;
-					goto scan_out;
-				}
-#ifdef WL11U
-				if ((interworking_ie = wl_cfg80211_find_interworking_ie(
-					(u8 *)request->ie, request->ie_len)) != NULL) {
-					err = wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
-					       VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
-					       interworking_ie->data, interworking_ie->len);
-
-					if (unlikely(err)) {
-						WL_ERR(("Failed to add interworking IE"));
-					}
-				} else if (cfg->iw_ie_len != 0) {
-				/* we have to clear IW IE and disable gratuitous APR */
-					wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
-						VNDR_IE_CUSTOM_FLAG,
-						DOT11_MNG_INTERWORKING_ID,
-						0, 0);
-
-					(void)wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0,
-						bssidx);
-					cfg->wl11u = FALSE;
-					cfg->iw_ie_len = 0;
-					memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
-					/* we don't care about error */
-				}
-#endif /* WL11U */
-				err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(ndev),
-					bssidx, VNDR_IE_PRBREQ_FLAG, request->ie,
-					request->ie_len);
-
-				if (unlikely(err)) {
-					goto scan_out;
-				}
-
-			}
-		}
-	} else {		/* scan in ibss */
-		ssids = this_ssid;
-	}
-
-	if (request && cfg->p2p_supported && !p2p_scan(cfg)) {
-		WL_TRACE_HW4(("START SCAN\n"));
-		DHD_OS_SCAN_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub),
-			SCAN_WAKE_LOCK_TIMEOUT);
-		DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
-	}
-
-	if (cfg->p2p_supported) {
-		if (p2p_on(cfg) && p2p_scan(cfg)) {
-
-			/* find my listen channel */
-			cfg->afx_hdl->my_listen_chan =
-				wl_find_listen_channel(cfg, request->ie,
-				request->ie_len);
-			err = wl_cfgp2p_enable_discovery(cfg, ndev,
-			request->ie, request->ie_len);
-
-			if (unlikely(err)) {
-				goto scan_out;
-			}
-		}
-	}
-	err = wl_do_escan(cfg, wiphy, ndev, request);
-	if (likely(!err))
-		goto scan_success;
-	else
-		goto scan_out;
-
-scan_success:
-	busy_count = 0;
-	cfg->scan_request = request;
-	wl_set_drv_status(cfg, SCANNING, ndev);
-
-	return 0;
-
-scan_out:
-	if (err == BCME_BUSY || err == BCME_NOTREADY) {
-		WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
-		err = -EBUSY;
-	} else if ((err == BCME_EPERM) && cfg->scan_suppressed) {
-		WL_ERR(("Scan not permitted due to scan suppress\n"));
-		err = -EPERM;
-	} else {
-		/* For all other fw errors, use a generic error code as return
-		 * value to cfg80211 stack
-		 */
-		err = -EAGAIN;
-	}
-
-#define SCAN_EBUSY_RETRY_LIMIT 20
-	if (err == -EBUSY) {
-		if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
-			struct ether_addr bssid;
-			s32 ret = 0;
-#if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
-			dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
-#endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
-			busy_count = 0;
-			WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
-				wl_get_drv_status(cfg, SCANNING, ndev),
-				wl_get_drv_status(cfg, SCAN_ABORTING, ndev),
-				wl_get_drv_status(cfg, CONNECTING, ndev),
-				wl_get_drv_status(cfg, CONNECTED, ndev),
-				wl_get_drv_status(cfg, DISCONNECTING, ndev),
-				wl_get_drv_status(cfg, AP_CREATING, ndev),
-				wl_get_drv_status(cfg, AP_CREATED, ndev),
-				wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev),
-				wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev)));
-
-#if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
-			if (dhdp->memdump_enabled) {
-				dhdp->memdump_type = DUMP_TYPE_SCAN_BUSY;
-				dhd_bus_mem_dump(dhdp);
-			}
-#endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
-
-			bzero(&bssid, sizeof(bssid));
-			if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID,
-				&bssid, ETHER_ADDR_LEN, false)) == 0)
-				WL_ERR(("FW is connected with " MACDBG "/n",
-					MAC2STRDBG(bssid.octet)));
-			else
-				WL_ERR(("GET BSSID failed with %d\n", ret));
-
-			wl_cfg80211_scan_abort(cfg);
-
-		} else {
-			/* Hold the context for 400msec, so that 10 subsequent scans
-			* can give a buffer of 4sec which is enough to
-			* cover any on-going scan in the firmware
-			*/
-			WL_DBG(("Enforcing delay for EBUSY case \n"));
-			msleep(500);
-		}
-	} else {
-		busy_count = 0;
-	}
-
-	wl_clr_drv_status(cfg, SCANNING, ndev);
-	if (timer_pending(&cfg->scan_timeout))
-		del_timer_sync(&cfg->scan_timeout);
-	DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
-	spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
-	cfg->scan_request = NULL;
-	spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
-
-	return err;
-}
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-static s32
-wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
-#else
-static s32
-wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
-	struct cfg80211_scan_request *request)
-#endif /* WL_CFG80211_P2P_DEV_IF */
-{
-	s32 err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-	WL_DBG(("Enter\n"));
-	RETURN_EIO_IF_NOT_UP(cfg);
-
-	if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
-		if (wl_cfg_multip2p_operational(cfg)) {
-			WL_ERR(("wlan0 scan failed, p2p devices are operational"));
-			 return -ENODEV;
-		}
-	}
-
-	mutex_lock(&cfg->usr_sync);
-	err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
-	if (unlikely(err)) {
-		WL_ERR(("scan error (%d)\n", err));
-	}
-	mutex_unlock(&cfg->usr_sync);
-
-	return err;
-}
-
-static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
-{
-	s32 err = 0;
-
-	err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
-	if (unlikely(err)) {
-		WL_ERR(("Error (%d)\n", err));
-		return err;
-	}
-	return err;
-}
-
-static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
-{
-	s32 err = 0;
-
-	err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
-	if (unlikely(err)) {
-		WL_ERR(("Error (%d)\n", err));
-		return err;
-	}
-	return err;
-}
-
-static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
-{
-	s32 err = 0;
-	u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
-
-	retry = htod32(retry);
-	err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true);
-	if (unlikely(err)) {
-		WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
-		return err;
-	}
-	return err;
-}
-
-static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
-{
-	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-	s32 err = 0;
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-	WL_DBG(("Enter\n"));
-	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
-		(cfg->conf->rts_threshold != wiphy->rts_threshold)) {
-		cfg->conf->rts_threshold = wiphy->rts_threshold;
-		err = wl_set_rts(ndev, cfg->conf->rts_threshold);
-		if (!err)
-			return err;
-	}
-	if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
-		(cfg->conf->frag_threshold != wiphy->frag_threshold)) {
-		cfg->conf->frag_threshold = wiphy->frag_threshold;
-		err = wl_set_frag(ndev, cfg->conf->frag_threshold);
-		if (!err)
-			return err;
-	}
-	if (changed & WIPHY_PARAM_RETRY_LONG &&
-		(cfg->conf->retry_long != wiphy->retry_long)) {
-		cfg->conf->retry_long = wiphy->retry_long;
-		err = wl_set_retry(ndev, cfg->conf->retry_long, true);
-		if (!err)
-			return err;
-	}
-	if (changed & WIPHY_PARAM_RETRY_SHORT &&
-		(cfg->conf->retry_short != wiphy->retry_short)) {
-		cfg->conf->retry_short = wiphy->retry_short;
-		err = wl_set_retry(ndev, cfg->conf->retry_short, false);
-		if (!err) {
-			return err;
-		}
-	}
-
-	return err;
-}
-static chanspec_t
-channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	u8 *buf = NULL;
-	wl_uint32_list_t *list;
-	int err = BCME_OK;
-	chanspec_t c = 0, ret_c = 0;
-	int bw = 0, tmp_bw = 0;
-	int i;
-	u32 tmp_c;
-	u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
-#define LOCAL_BUF_SIZE	1024
-	buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
-	if (!buf) {
-		WL_ERR(("buf memory alloc failed\n"));
-		goto exit;
-	}
-	list = (wl_uint32_list_t *)(void *)buf;
-	list->count = htod32(WL_NUMCHANSPECS);
-	err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
-		0, buf, LOCAL_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
-	if (err != BCME_OK) {
-		WL_ERR(("get chanspecs failed with %d\n", err));
-		goto exit;
-	}
-	for (i = 0; i < dtoh32(list->count); i++) {
-		c = dtoh32(list->element[i]);
-		if (channel <= CH_MAX_2G_CHANNEL) {
-			if (!CHSPEC_IS20(c))
-				continue;
-			if (channel == CHSPEC_CHANNEL(c)) {
-				ret_c = c;
-				bw = 20;
-				goto exit;
-			}
-		}
-		tmp_c = wf_chspec_ctlchan(c);
-		tmp_bw = bw2cap[CHSPEC_BW(c) >> WL_CHANSPEC_BW_SHIFT];
-		if (tmp_c != channel)
-			continue;
-
-		if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
-			bw = tmp_bw;
-			ret_c = c;
-			if (bw == bw_cap)
-				goto exit;
-		}
-	}
-exit:
-	if (buf)
-		kfree(buf);
-#undef LOCAL_BUF_SIZE
-	WL_INFORM(("return chanspec %x %d\n", ret_c, bw));
-	return ret_c;
-}
-
-void
-wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	if (cfg != NULL && ibss_vsie != NULL) {
-		if (cfg->ibss_vsie != NULL) {
-			kfree(cfg->ibss_vsie);
-		}
-		cfg->ibss_vsie = ibss_vsie;
-		cfg->ibss_vsie_len = ibss_vsie_len;
-	}
-}
-
-static void
-wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211 *cfg)
-{
-	/* free & initiralize VSIE (Vendor Specific IE) */
-	if (cfg->ibss_vsie != NULL) {
-		kfree(cfg->ibss_vsie);
-		cfg->ibss_vsie = NULL;
-		cfg->ibss_vsie_len = 0;
-	}
-}
-
-s32
-wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	char *ioctl_buf = NULL;
-	s32 ret = BCME_OK;
-
-	if (cfg != NULL && cfg->ibss_vsie != NULL) {
-		ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
-		if (!ioctl_buf) {
-			WL_ERR(("ioctl memory alloc failed\n"));
-			return -ENOMEM;
-		}
-
-		/* change the command from "add" to "del" */
-		strncpy(cfg->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
-		cfg->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
-
-		ret = wldev_iovar_setbuf(dev, "ie",
-			cfg->ibss_vsie, cfg->ibss_vsie_len,
-			ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
-		WL_ERR(("ret=%d\n", ret));
-
-		if (ret == BCME_OK) {
-			/* free & initiralize VSIE */
-			kfree(cfg->ibss_vsie);
-			cfg->ibss_vsie = NULL;
-			cfg->ibss_vsie_len = 0;
-		}
-
-		if (ioctl_buf) {
-			kfree(ioctl_buf);
-		}
-	}
-
-	return ret;
-}
-
-#ifdef WLAIBSS_MCHAN
-static bcm_struct_cfgdev*
-bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct wireless_dev* wdev = NULL;
-	struct net_device *new_ndev = NULL;
-	struct net_device *primary_ndev = NULL;
-	s32 timeout;
-	wl_aibss_if_t aibss_if;
-	wl_if_event_info *event = NULL;
-
-	if (cfg->ibss_cfgdev != NULL) {
-		WL_ERR(("IBSS interface %s already exists\n", name));
-		return NULL;
-	}
-
-	WL_ERR(("Try to create IBSS interface %s\n", name));
-	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
-	/* generate a new MAC address for the IBSS interface */
-	get_primary_mac(cfg, &cfg->ibss_if_addr);
-	cfg->ibss_if_addr.octet[4] ^= 0x40;
-	memset(&aibss_if, sizeof(aibss_if), 0);
-	memcpy(&aibss_if.addr, &cfg->ibss_if_addr, sizeof(aibss_if.addr));
-	aibss_if.chspec = 0;
-	aibss_if.len = sizeof(aibss_if);
-
-	cfg->bss_pending_op = TRUE;
-	memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
-	err = wldev_iovar_setbuf(primary_ndev, "aibss_ifadd", &aibss_if,
-		sizeof(aibss_if), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
-	if (err) {
-		WL_ERR(("IOVAR aibss_ifadd failed with error %d\n", err));
-		goto fail;
-	}
-	timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
-		!cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
-	if (timeout <= 0 || cfg->bss_pending_op)
-		goto fail;
-
-	event = &cfg->if_event_info;
-	/* By calling wl_cfg80211_allocate_if (dhd_allocate_if eventually) we give the control
-	 * over this net_device interface to dhd_linux, hence the interface is managed by dhd_liux
-	 * and will be freed by dhd_detach unless it gets unregistered before that. The
-	 * wireless_dev instance new_ndev->ieee80211_ptr associated with this net_device will
-	 * be freed by wl_dealloc_netinfo
-	 */
-	new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, event->name,
-		event->mac, event->bssidx, event->name);
-	if (new_ndev == NULL)
-		goto fail;
-	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
-	if (wdev == NULL)
-		goto fail;
-	wdev->wiphy = wiphy;
-	wdev->iftype = NL80211_IFTYPE_ADHOC;
-	wdev->netdev = new_ndev;
-	new_ndev->ieee80211_ptr = wdev;
-	SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
-
-	/* rtnl lock must have been acquired, if this is not the case, wl_cfg80211_register_if
-	* needs to be modified to take one parameter (bool need_rtnl_lock)
-	 */
-	ASSERT_RTNL();
-	if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK)
-		goto fail;
-
-	wl_alloc_netinfo(cfg, new_ndev, wdev, WL_MODE_IBSS, PM_ENABLE, event->bssidx);
-	cfg->ibss_cfgdev = ndev_to_cfgdev(new_ndev);
-	WL_ERR(("IBSS interface %s created\n", new_ndev->name));
-	return cfg->ibss_cfgdev;
-
-fail:
-	WL_ERR(("failed to create IBSS interface %s \n", name));
-	cfg->bss_pending_op = FALSE;
-	if (new_ndev)
-		wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
-	if (wdev)
-		kfree(wdev);
-	return NULL;
-}
-
-static s32
-bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *ndev = NULL;
-	struct net_device *primary_ndev = NULL;
-	s32 timeout;
-
-	if (!cfgdev || cfg->ibss_cfgdev != cfgdev || ETHER_ISNULLADDR(&cfg->ibss_if_addr.octet))
-		return -EINVAL;
-	ndev = (struct net_device *)cfgdev_to_ndev(cfg->ibss_cfgdev);
-	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
-
-	cfg->bss_pending_op = TRUE;
-	memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
-	err = wldev_iovar_setbuf(primary_ndev, "aibss_ifdel", &cfg->ibss_if_addr,
-		sizeof(cfg->ibss_if_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
-	if (err) {
-		WL_ERR(("IOVAR aibss_ifdel failed with error %d\n", err));
-		goto fail;
-	}
-	timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
-		!cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
-	if (timeout <= 0 || cfg->bss_pending_op) {
-		WL_ERR(("timeout in waiting IF_DEL event\n"));
-		goto fail;
-	}
-
-	wl_cfg80211_remove_if(cfg, cfg->if_event_info.ifidx, ndev);
-	cfg->ibss_cfgdev = NULL;
-	return 0;
-
-fail:
-	cfg->bss_pending_op = FALSE;
-	return -1;
-}
-#endif /* WLAIBSS_MCHAN */
-
-s32
-wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
-	struct net_device *ndev, s32 bsscfg_idx,
-	enum nl80211_iftype iface_type, s32 del, u8 *addr)
-{
-	wl_interface_create_t iface;
-	s32 ret;
-	wl_interface_info_t *info;
-
-	bzero(&iface, sizeof(wl_interface_create_t));
-
-	iface.ver = WL_INTERFACE_CREATE_VER;
-
-	if (iface_type == NL80211_IFTYPE_AP)
-		iface.flags = WL_INTERFACE_CREATE_AP;
-	else
-		iface.flags = WL_INTERFACE_CREATE_STA;
-
-	if (del) {
-		ret = wldev_iovar_setbuf(ndev, "interface_remove",
-			NULL, 0, cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
-	} else {
-		if (addr) {
-			memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
-			iface.flags |= WL_INTERFACE_MAC_USE;
-		}
-		ret = wldev_iovar_getbuf(ndev, "interface_create",
-			&iface, sizeof(wl_interface_create_t),
-			cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-		if (ret == 0) {
-			/* success */
-			info = (wl_interface_info_t *)cfg->ioctl_buf;
-			WL_DBG(("wl interface create success!! bssidx:%d \n",
-				info->bsscfgidx));
-			ret = info->bsscfgidx;
-		}
-	}
-
-	if (ret < 0)
-		WL_ERR(("Interface %s failed!! ret %d\n",
-			del ? "remove" : "create", ret));
-
-	return ret;
-}
-
-
-s32
-wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
-	struct net_device *ndev, s32 bsscfg_idx,
-	enum nl80211_iftype iface_type, s32 del, u8 *addr)
-{
-	s32 ret = BCME_OK;
-	s32 val = 0;
-
-	struct {
-		s32 cfg;
-		s32 val;
-		struct ether_addr ea;
-	} bss_setbuf;
-
-	WL_INFORM(("iface_type:%d del:%d \n", iface_type, del));
-
-	bzero(&bss_setbuf, sizeof(bss_setbuf));
-
-	/* AP=3, STA=2, up=1, down=0, val=-1 */
-	if (del) {
-		val = -1;
-	} else if (iface_type == NL80211_IFTYPE_AP) {
-		/* AP Interface */
-		WL_DBG(("Adding AP Interface \n"));
-		val = 3;
-	} else if (iface_type == NL80211_IFTYPE_STATION) {
-		WL_DBG(("Adding STA Interface \n"));
-		val = 2;
-	} else {
-		WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", iface_type));
-		return -EINVAL;
-	}
-
-	bss_setbuf.cfg = htod32(bsscfg_idx);
-	bss_setbuf.val = htod32(val);
-
-	if (addr) {
-		memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
-	}
-
-	ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-	if (ret != 0)
-		WL_ERR(("'bss %d' failed with %d\n", val, ret));
-
-	return ret;
-}
-
-#if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
-/* Create a Generic Network Interface and initialize it depending up on
- * the interface type
- */
-bcm_struct_cfgdev*
-wl_cfg80211_create_iface(struct wiphy *wiphy,
-	enum nl80211_iftype iface_type,
-	u8 *mac_addr, const char *name)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *new_ndev = NULL;
-	struct net_device *primary_ndev = NULL;
-	s32 ret = BCME_OK;
-	s32 bsscfg_idx = 0;
-	u32 timeout;
-	wl_if_event_info *event = NULL;
-	struct wireless_dev *wdev = NULL;
-	u8 addr[ETH_ALEN];
-
-	WL_DBG(("Enter\n"));
-
-	if (!name) {
-		WL_ERR(("Interface name not provided\n"));
-		return NULL;
-	}
-
-	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
-
-#ifdef DHD_IFDEBUG
-	WL_ERR(("cfg=%p, primary_ndev=%p, ifname=%s\n", cfg, primary_ndev, name));
-#endif
-
-	/* If any scan is going on, abort it */
-	if (wl_get_drv_status_all(cfg, SCANNING)) {
-		int wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
-		WL_ERR(("Scan in progress. Aborting the scan!\n"));
-		wl_cfg80211_scan_abort(cfg);
-		while (wl_get_drv_status_all(cfg, SCANNING) && wait_cnt) {
-			WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
-			wait_cnt--;
-			OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
-		}
-		if (!wait_cnt && wl_get_drv_status_all(cfg, SCANNING)) {
-			WL_ERR(("Failed to abort scan\n"));
-			return NULL;
-		}
-	}
-
-	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
-	if (likely(!mac_addr)) {
-		/* Use primary MAC with the locally administered bit for the
-		 *  Secondary STA I/F
-		 */
-		memcpy(addr, primary_ndev->dev_addr, ETH_ALEN);
-		addr[0] |= 0x02;
-	} else {
-		/* Use the application provided mac address (if any) */
-		memcpy(addr, mac_addr, ETH_ALEN);
-	}
-
-	if ((iface_type != NL80211_IFTYPE_STATION) && (iface_type != NL80211_IFTYPE_AP)) {
-		WL_ERR(("IFACE type:%d not supported. STA "
-					"or AP IFACE is only supported\n", iface_type));
-		return NULL;
-	}
-
-	cfg->bss_pending_op = TRUE;
-	memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
-
-	/* De-initialize the p2p discovery interface, if operational */
-	if (p2p_is_on(cfg)) {
-		WL_DBG(("Disabling P2P Discovery Interface \n"));
-#ifdef WL_CFG80211_P2P_DEV_IF
-		ret = wl_cfg80211_scan_stop(bcmcfg_to_p2p_wdev(cfg));
-#else
-		ret = wl_cfg80211_scan_stop(cfg->p2p_net);
-#endif
-		if (unlikely(ret < 0)) {
-			CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
-		}
-
-#ifdef DHD_IFDEBUG
-		WL_ERR(("call wl_cfgp2p_disable_discovery()\n"));
-#endif
-		wl_cfgp2p_disable_discovery(cfg);
-		wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
-		p2p_on(cfg) = false;
-	}
-
-	/*
-	 * Intialize the firmware I/F.
-	 */
-	ret = wl_cfg80211_interface_ops(cfg, primary_ndev, bsscfg_idx,
-		NL80211_IFTYPE_STATION, 0, addr);
-	if (ret == BCME_UNSUPPORTED) {
-		/* Use bssidx 1 by default */
-		bsscfg_idx = 1;
-		if ((ret = wl_cfg80211_add_del_bss(cfg, primary_ndev,
-			bsscfg_idx, iface_type, 0, addr)) < 0) {
-			return NULL;
-		}
-	} else if (ret < 0) {
-		WL_ERR(("Interface create failed!! ret:%d \n", ret));
-		goto fail;
-	} else {
-		/* Success */
-		bsscfg_idx = ret;
-	}
-
-	WL_DBG(("Interface created!! bssidx:%d \n", bsscfg_idx));
-
-	/*
-	 * Wait till the firmware send a confirmation event back.
-	 */
-	WL_DBG(("Wait for the FW I/F Event\n"));
-	timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
-		!cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
-	if (timeout <= 0 || cfg->bss_pending_op) {
-		WL_ERR(("ADD_IF event, didn't come. Return \n"));
-		goto fail;
-	}
-
-	/*
-	 * Since FW operation is successful,we can go ahead with the
-	 * the host interface creation.
-	 */
-	event = &cfg->if_event_info;
-	new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx,
-		(char*)name, addr, event->bssidx, event->name);
-	if (!new_ndev) {
-		WL_ERR(("I/F allocation failed! \n"));
-		goto fail;
-	} else
-		WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
-		 event->ifidx, event->bssidx));
-
-	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
-	if (!wdev) {
-		WL_ERR(("wireless_dev alloc failed! \n"));
-		goto fail;
-	}
-
-	wdev->wiphy = wiphy;
-	wdev->iftype = iface_type;
-	new_ndev->ieee80211_ptr = wdev;
-	SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
-
-#ifdef DHD_IFDEBUG
-	WL_ERR(("wdev=%p, new_ndev=%p\n", wdev, new_ndev));
-#endif
-
-	/* RTNL lock must have been acquired. */
-	ASSERT_RTNL();
-
-	/* Set the locally administed mac addr, if not applied already */
-	if (memcmp(addr, event->mac, ETH_ALEN) != 0) {
-		ret = wldev_iovar_setbuf_bsscfg(primary_ndev, "cur_etheraddr",
-			addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
-			event->bssidx, &cfg->ioctl_buf_sync);
-		if (unlikely(ret)) {
-				WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
-				goto fail;
-		}
-		memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
-	}
-
-	if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
-		WL_ERR(("IFACE register failed \n"));
-		goto fail;
-	}
-
-	/* Initialize with the station mode params */
-	wl_alloc_netinfo(cfg, new_ndev, wdev,
-		(iface_type == NL80211_IFTYPE_STATION) ?
-		WL_MODE_BSS : WL_MODE_AP, PM_ENABLE, event->bssidx);
-	cfg->bss_cfgdev = ndev_to_cfgdev(new_ndev);
-	cfg->cfgdev_bssidx = event->bssidx;
-
-	WL_DBG(("Host Network Interface for Secondary I/F created"));
-
-#ifdef DHD_IFDEBUG
-	WL_ERR(("cfg->bss_cfgdev=%p\n", cfg->bss_cfgdev));
-#endif
-
-	return cfg->bss_cfgdev;
-
-fail:
-	cfg->bss_pending_op = FALSE;
-	cfg->cfgdev_bssidx = -1;
-	if (wdev)
-		kfree(wdev);
-	if (new_ndev)
-		wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
-
-#ifdef DHD_IFDEBUG
-	WL_ERR(("failed!!!\n"));
-#endif
-
-	return NULL;
-}
-
-s32
-wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *ndev = NULL;
-	struct net_device *primary_ndev = NULL;
-	s32 ret = BCME_OK;
-	s32 bsscfg_idx = 1;
-	u32 timeout;
-	u32 ifidx;
-	enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
-
-	WL_ERR(("Enter\n"));
-
-	if (!cfg->bss_cfgdev)
-		return 0;
-
-	/* If any scan is going on, abort it */
-	if (wl_get_drv_status_all(cfg, SCANNING)) {
-		WL_ERR(("Scan in progress. Aborting the scan!\n"));
-		wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
-	}
-
-	ndev = (struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev);
-	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
-
-#ifdef DHD_IFDEBUG
-	WL_ERR(("cfg->bss_cfgdev=%p, ndev=%p, primary_ndev=%p\n",
-		cfg->bss_cfgdev, ndev, primary_ndev));
-#endif
-
-	cfg->bss_pending_op = TRUE;
-	memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
-
-	/* Delete the firmware interface. "interface_remove" command
-	 * should go on the interface to be deleted
-	 */
-	ret = wl_cfg80211_interface_ops(cfg, ndev, cfg->cfgdev_bssidx,
-		NL80211_IFTYPE_STATION, 1, NULL);
-	if (ret == BCME_UNSUPPORTED) {
-		if ((ret = wl_cfg80211_add_del_bss(cfg, ndev,
-			bsscfg_idx, iface_type, true, NULL)) < 0) {
-			WL_ERR(("DEL bss failed ret:%d \n", ret));
-			goto exit;
-		}
-	} else if (ret < 0) {
-		WL_ERR(("Interface DEL failed ret:%d \n", ret));
-		goto exit;
-	}
-
-	timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
-		!cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
-	if (timeout <= 0 || cfg->bss_pending_op) {
-		WL_ERR(("timeout in waiting IF_DEL event\n"));
-	}
-
-exit:
-	ifidx = dhd_net2idx(((struct dhd_pub *)(cfg->pub))->info, ndev);
-	wl_cfg80211_remove_if(cfg, ifidx, ndev);
-	cfg->bss_cfgdev = NULL;
-	cfg->cfgdev_bssidx = -1;
-	cfg->bss_pending_op = FALSE;
-
-	WL_ERR(("IF_DEL Done.\n"));
-
-	return ret;
-}
-#endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
-
-static s32
-wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
-	struct cfg80211_ibss_params *params)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct cfg80211_bss *bss;
-	struct ieee80211_channel *chan;
-	struct wl_join_params join_params;
-	int scan_suppress;
-	struct cfg80211_ssid ssid;
-	s32 scan_retry = 0;
-	s32 err = 0;
-	size_t join_params_size;
-	chanspec_t chanspec = 0;
-	u32 param[2] = {0, 0};
-	u32 bw_cap = 0;
-
-	WL_TRACE(("In\n"));
-	RETURN_EIO_IF_NOT_UP(cfg);
-	WL_INFORM(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
-	if (!params->ssid || params->ssid_len <= 0) {
-		WL_ERR(("Invalid parameter\n"));
-		return -EINVAL;
-	}
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	chan = params->chandef.chan;
-#else
-	chan = params->channel;
-#endif /* WL_CFG80211_P2P_DEV_IF */
-	if (chan)
-		cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
-	if (wl_get_drv_status(cfg, CONNECTED, dev)) {
-		struct wlc_ssid *lssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
-		u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
-		u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
-		if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
-			(memcmp(params->ssid, lssid->SSID, lssid->SSID_len) == 0) &&
-			(*channel == cfg->channel))) {
-			WL_ERR(("Connection already existed to " MACDBG "\n",
-				MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
-			return -EISCONN;
-		}
-		WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
-			lssid->SSID, MAC2STRDBG(bssid)));
-	}
-
-	/* remove the VSIE */
-	wl_cfg80211_ibss_vsie_delete(dev);
-
-	bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
-	if (!bss) {
-		if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
-			memcpy(ssid.ssid, params->ssid, params->ssid_len);
-			ssid.ssid_len = params->ssid_len;
-			do {
-				if (unlikely
-					(__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
-					 -EBUSY)) {
-					wl_delay(150);
-				} else {
-					break;
-				}
-			} while (++scan_retry < WL_SCAN_RETRY_MAX);
-
-			/* rtnl lock code is removed here. don't see why rtnl lock
-			 * needs to be released.
-			 */
-
-			/* wait 4 secons till scan done.... */
-			schedule_timeout_interruptible(msecs_to_jiffies(4000));
-
-			bss = cfg80211_get_ibss(wiphy, NULL,
-				params->ssid, params->ssid_len);
-		}
-	}
-	if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
-		((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
-		!memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
-		cfg->ibss_starter = false;
-		WL_DBG(("Found IBSS\n"));
-	} else {
-		cfg->ibss_starter = true;
-	}
-	if (chan) {
-		if (chan->band == IEEE80211_BAND_5GHZ)
-			param[0] = WLC_BAND_5G;
-		else if (chan->band == IEEE80211_BAND_2GHZ)
-			param[0] = WLC_BAND_2G;
-		err = wldev_iovar_getint(dev, "bw_cap", param);
-		if (unlikely(err)) {
-			WL_ERR(("Get bw_cap Failed (%d)\n", err));
-			return err;
-		}
-		bw_cap = param[0];
-		chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
-	}
-	/*
-	 * Join with specific BSSID and cached SSID
-	 * If SSID is zero join based on BSSID only
-	 */
-	memset(&join_params, 0, sizeof(join_params));
-	memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
-		params->ssid_len);
-	join_params.ssid.SSID_len = htod32(params->ssid_len);
-	if (params->bssid) {
-		memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
-		err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
-			ETHER_ADDR_LEN, true);
-		if (unlikely(err)) {
-			WL_ERR(("Error (%d)\n", err));
-			return err;
-		}
-	} else
-		memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
-	wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
-
-	if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
-		scan_suppress = TRUE;
-		/* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
-		err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
-			&scan_suppress, sizeof(int), true);
-		if (unlikely(err)) {
-			WL_ERR(("Scan Suppress Setting Failed (%d)\n", err));
-			return err;
-		}
-	}
-
-	join_params.params.chanspec_list[0] = chanspec;
-	join_params.params.chanspec_num = 1;
-	wldev_iovar_setint(dev, "chanspec", chanspec);
-	join_params_size = sizeof(join_params);
-
-	/* Disable Authentication, IBSS will add key if it required */
-	wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
-	wldev_iovar_setint(dev, "wsec", 0);
-
-
-	err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
-		join_params_size, true);
-	if (unlikely(err)) {
-		WL_ERR(("Error (%d)\n", err));
-		return err;
-	}
-
-	if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
-		scan_suppress = FALSE;
-		/* Reset the SCAN SUPPRESS Flag */
-		err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
-			&scan_suppress, sizeof(int), true);
-		if (unlikely(err)) {
-			WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err));
-			return err;
-		}
-	}
-	wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
-	wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
-	cfg->rmc_event_seq = 0; /* initialize rmcfail sequence */
-	return err;
-}
-
-static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	s32 err = 0;
-	scb_val_t scbval;
-	u8 *curbssid;
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-	wl_link_down(cfg);
-
-	WL_ERR(("Leave IBSS\n"));
-	curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
-	wl_set_drv_status(cfg, DISCONNECTING, dev);
-	scbval.val = 0;
-	memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
-	err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
-		sizeof(scb_val_t), true);
-	if (unlikely(err)) {
-		wl_clr_drv_status(cfg, DISCONNECTING, dev);
-		WL_ERR(("error(%d)\n", err));
-		return err;
-	}
-
-	/* remove the VSIE */
-	wl_cfg80211_ibss_vsie_delete(dev);
-
-	return err;
-}
-
-
-static s32
-wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wl_security *sec;
-	s32 val = 0;
-	s32 err = 0;
-	s32 bssidx;
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
-		val = WPA_AUTH_PSK |
-			WPA_AUTH_UNSPECIFIED;
-	else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
-		val = WPA2_AUTH_PSK|
-			WPA2_AUTH_UNSPECIFIED;
-	else
-		val = WPA_AUTH_DISABLED;
-
-	if (is_wps_conn(sme))
-		val = WPA_AUTH_DISABLED;
-
-	WL_DBG(("setting wpa_auth to 0x%0x\n", val));
-	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
-	if (unlikely(err)) {
-		WL_ERR(("set wpa_auth failed (%d)\n", err));
-		return err;
-	}
-	sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
-	sec->wpa_versions = sme->crypto.wpa_versions;
-	return err;
-}
-
-
-static s32
-wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wl_security *sec;
-	s32 val = 0;
-	s32 err = 0;
-	s32 bssidx;
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	switch (sme->auth_type) {
-	case NL80211_AUTHTYPE_OPEN_SYSTEM:
-		val = WL_AUTH_OPEN_SYSTEM;
-		WL_DBG(("open system\n"));
-		break;
-	case NL80211_AUTHTYPE_SHARED_KEY:
-		val = WL_AUTH_SHARED_KEY;
-		WL_DBG(("shared key\n"));
-		break;
-	case NL80211_AUTHTYPE_AUTOMATIC:
-		val = WL_AUTH_OPEN_SHARED;
-		WL_DBG(("automatic\n"));
-		break;
-	default:
-		val = 2;
-		WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
-		break;
-	}
-
-	err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
-	if (unlikely(err)) {
-		WL_ERR(("set auth failed (%d)\n", err));
-		return err;
-	}
-	sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
-	sec->auth_type = sme->auth_type;
-	return err;
-}
-
-static s32
-wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wl_security *sec;
-	s32 pval = 0;
-	s32 gval = 0;
-	s32 err = 0;
-	s32 wsec_val = 0;
-
-	s32 bssidx;
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	if (sme->crypto.n_ciphers_pairwise) {
-		switch (sme->crypto.ciphers_pairwise[0]) {
-		case WLAN_CIPHER_SUITE_WEP40:
-		case WLAN_CIPHER_SUITE_WEP104:
-			pval = WEP_ENABLED;
-			break;
-		case WLAN_CIPHER_SUITE_TKIP:
-			pval = TKIP_ENABLED;
-			break;
-		case WLAN_CIPHER_SUITE_CCMP:
-		case WLAN_CIPHER_SUITE_AES_CMAC:
-			pval = AES_ENABLED;
-			break;
-		default:
-			WL_ERR(("invalid cipher pairwise (%d)\n",
-				sme->crypto.ciphers_pairwise[0]));
-			return -EINVAL;
-		}
-	}
-	if (sme->crypto.cipher_group) {
-		switch (sme->crypto.cipher_group) {
-		case WLAN_CIPHER_SUITE_WEP40:
-		case WLAN_CIPHER_SUITE_WEP104:
-			gval = WEP_ENABLED;
-			break;
-		case WLAN_CIPHER_SUITE_TKIP:
-			gval = TKIP_ENABLED;
-			break;
-		case WLAN_CIPHER_SUITE_CCMP:
-			gval = AES_ENABLED;
-			break;
-		case WLAN_CIPHER_SUITE_AES_CMAC:
-			gval = AES_ENABLED;
-			break;
-		default:
-			WL_ERR(("invalid cipher group (%d)\n",
-				sme->crypto.cipher_group));
-			return -EINVAL;
-		}
-	}
-
-	WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
-
-	if (is_wps_conn(sme)) {
-		if (sme->privacy)
-			err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
-		else
-			/* WPS-2.0 allows no security */
-			err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
-	} else {
-			WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
-			wsec_val = pval | gval;
-
-			WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
-			err = wldev_iovar_setint_bsscfg(dev, "wsec",
-				wsec_val, bssidx);
-	}
-	if (unlikely(err)) {
-		WL_ERR(("error (%d)\n", err));
-		return err;
-	}
-
-	sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
-	sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
-	sec->cipher_group = sme->crypto.cipher_group;
-
-	return err;
-}
-
-static s32
-wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wl_security *sec;
-	s32 val = 0;
-	s32 err = 0;
-	s32 bssidx;
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	if (sme->crypto.n_akm_suites) {
-		err = wldev_iovar_getint(dev, "wpa_auth", &val);
-		if (unlikely(err)) {
-			WL_ERR(("could not get wpa_auth (%d)\n", err));
-			return err;
-		}
-		if (val & (WPA_AUTH_PSK |
-			WPA_AUTH_UNSPECIFIED)) {
-			switch (sme->crypto.akm_suites[0]) {
-			case WLAN_AKM_SUITE_8021X:
-				val = WPA_AUTH_UNSPECIFIED;
-				break;
-			case WLAN_AKM_SUITE_PSK:
-				val = WPA_AUTH_PSK;
-				break;
-			default:
-				WL_ERR(("invalid akm suite (0x%x)\n",
-					sme->crypto.akm_suites[0]));
-				return -EINVAL;
-			}
-		} else if (val & (WPA2_AUTH_PSK |
-			WPA2_AUTH_UNSPECIFIED)) {
-			switch (sme->crypto.akm_suites[0]) {
-			case WLAN_AKM_SUITE_8021X:
-				val = WPA2_AUTH_UNSPECIFIED;
-				break;
-			case WLAN_AKM_SUITE_PSK:
-				val = WPA2_AUTH_PSK;
-				break;
-			default:
-				WL_ERR(("invalid akm suite (0x%x)\n",
-					sme->crypto.akm_suites[0]));
-				return -EINVAL;
-			}
-		}
-
-
-		WL_DBG(("setting wpa_auth to 0x%x\n", val));
-
-		err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
-		if (unlikely(err)) {
-			WL_ERR(("could not set wpa_auth (%d)\n", err));
-			return err;
-		}
-	}
-	sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
-	sec->wpa_auth = sme->crypto.akm_suites[0];
-
-	return err;
-}
-
-static s32
-wl_set_set_sharedkey(struct net_device *dev,
-	struct cfg80211_connect_params *sme)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wl_security *sec;
-	struct wl_wsec_key key;
-	s32 val;
-	s32 err = 0;
-	s32 bssidx;
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	WL_DBG(("key len (%d)\n", sme->key_len));
-	if (sme->key_len) {
-		sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
-		WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
-			sec->wpa_versions, sec->cipher_pairwise));
-		if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
-			NL80211_WPA_VERSION_2)) &&
-			(sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
-		WLAN_CIPHER_SUITE_WEP104)))
-		{
-			memset(&key, 0, sizeof(key));
-			key.len = (u32) sme->key_len;
-			key.index = (u32) sme->key_idx;
-			if (unlikely(key.len > sizeof(key.data))) {
-				WL_ERR(("Too long key length (%u)\n", key.len));
-				return -EINVAL;
-			}
-			memcpy(key.data, sme->key, key.len);
-			key.flags = WL_PRIMARY_KEY;
-			switch (sec->cipher_pairwise) {
-			case WLAN_CIPHER_SUITE_WEP40:
-				key.algo = CRYPTO_ALGO_WEP1;
-				break;
-			case WLAN_CIPHER_SUITE_WEP104:
-				key.algo = CRYPTO_ALGO_WEP128;
-				break;
-			default:
-				WL_ERR(("Invalid algorithm (%d)\n",
-					sme->crypto.ciphers_pairwise[0]));
-				return -EINVAL;
-			}
-			/* Set the new key/index */
-			WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
-				key.len, key.index, key.algo));
-			WL_DBG(("key \"%s\"\n", key.data));
-			swap_key_from_BE(&key);
-			err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
-				cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-			if (unlikely(err)) {
-				WL_ERR(("WLC_SET_KEY error (%d)\n", err));
-				return err;
-			}
-			if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
-				WL_DBG(("set auth_type to shared key\n"));
-				val = WL_AUTH_SHARED_KEY;	/* shared key */
-				err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
-				if (unlikely(err)) {
-					WL_ERR(("set auth failed (%d)\n", err));
-					return err;
-				}
-			}
-		}
-	}
-	return err;
-}
-
-#if defined(ESCAN_RESULT_PATCH)
-static u8 connect_req_bssid[6];
-static u8 broad_bssid[6];
-#endif /* ESCAN_RESULT_PATCH */
-
-
-
-#if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
-static bool wl_get_chan_isvht80(struct net_device *net, dhd_pub_t *dhd)
-{
-	u32 chanspec = 0;
-	bool isvht80 = 0;
-
-	if (wldev_iovar_getint(net, "chanspec", (s32 *)&chanspec) == BCME_OK)
-		chanspec = wl_chspec_driver_to_host(chanspec);
-
-	isvht80 = chanspec & WL_CHANSPEC_BW_80;
-	WL_INFO(("%s: chanspec(%x:%d)\n", __FUNCTION__, chanspec, isvht80));
-
-	return isvht80;
-}
-#endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
-
-static s32
-wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
-	struct cfg80211_connect_params *sme)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct ieee80211_channel *chan = sme->channel;
-	wl_extjoin_params_t *ext_join_params;
-	struct wl_join_params join_params;
-	size_t join_params_size;
-	s32 err = 0;
-	wpa_ie_fixed_t *wpa_ie;
-	bcm_tlv_t *wpa2_ie;
-	u8* wpaie  = 0;
-	u32 wpaie_len = 0;
-	u32 chan_cnt = 0;
-	struct ether_addr bssid;
-	s32 bssidx = -1;
-	int ret;
-	int wait_cnt;
-
-	WL_DBG(("In\n"));
-
-#if defined(SUPPORT_RANDOM_MAC_SCAN)
-	wl_cfg80211_set_random_mac(dev, FALSE);
-#endif /* SUPPORT_RANDOM_MAC_SCAN */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
-	if (sme->channel_hint) {
-		chan = sme->channel_hint;
-		WL_DBG(("channel_hint (%d), channel_hint center_freq (%d)\n",
-			ieee80211_frequency_to_channel(sme->channel_hint->center_freq),
-			sme->channel_hint->center_freq));
-	}
-	if (sme->bssid_hint) {
-		sme->bssid = sme->bssid_hint;
-		WL_DBG(("bssid_hint "MACDBG" \n", MAC2STRDBG(sme->bssid_hint)));
-	}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
-
-	if (unlikely(!sme->ssid)) {
-		WL_ERR(("Invalid ssid\n"));
-		return -EOPNOTSUPP;
-	}
-
-	if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
-		WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
-			sme->ssid, sme->ssid_len));
-		return -EINVAL;
-	}
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-
-	/*
-	 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
-	 */
-#if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
-	if (cfg->scan_request) {
-		WL_TRACE_HW4(("Aborting the scan! \n"));
-		wl_cfg80211_scan_abort(cfg);
-		wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
-		while (wl_get_drv_status(cfg, SCANNING, dev) && wait_cnt) {
-			WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
-			wait_cnt--;
-			OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
-		}
-		if (wl_get_drv_status(cfg, SCANNING, dev)) {
-			wl_notify_escan_complete(cfg, dev, true, true);
-		}
-	}
-#endif
-#ifdef WL_SCHED_SCAN
-	if (cfg->sched_scan_req) {
-		wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg));
-	}
-#endif
-#if defined(ESCAN_RESULT_PATCH)
-	if (sme->bssid)
-		memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
-	else
-		bzero(connect_req_bssid, ETHER_ADDR_LEN);
-	bzero(broad_bssid, ETHER_ADDR_LEN);
-#endif
-#if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
-	maxrxpktglom = 0;
-#endif
-	bzero(&bssid, sizeof(bssid));
-	if (!wl_get_drv_status(cfg, CONNECTED, dev)&&
-		(ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
-		if (!ETHER_ISNULLADDR(&bssid)) {
-			scb_val_t scbval;
-			wl_set_drv_status(cfg, DISCONNECTING, dev);
-			scbval.val = DOT11_RC_DISASSOC_LEAVING;
-			memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
-			scbval.val = htod32(scbval.val);
-
-			WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
-				MAC2STRDBG(bssid.octet)));
-			err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
-				sizeof(scb_val_t), true);
-			if (unlikely(err)) {
-				wl_clr_drv_status(cfg, DISCONNECTING, dev);
-				WL_ERR(("error (%d)\n", err));
-				return err;
-			}
-			wait_cnt = 500/10;
-			while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
-				WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
-					wait_cnt));
-				wait_cnt--;
-				OSL_SLEEP(10);
-			}
-		} else
-			WL_DBG(("Currently not associated!\n"));
-	} else {
-		/* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
-		wait_cnt = 200/10;
-		while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
-			WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
-			wait_cnt--;
-			OSL_SLEEP(10);
-		}
-		if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
-			WL_ERR(("Force clear DISCONNECTING status!\n"));
-			wl_clr_drv_status(cfg, DISCONNECTING, dev);
-		}
-	}
-
-	/* Clean BSSID */
-	bzero(&bssid, sizeof(bssid));
-	if (!wl_get_drv_status(cfg, DISCONNECTING, dev))
-		wl_update_prof(cfg, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
-
-	if (p2p_is_on(cfg) && (dev != bcmcfg_to_prmry_ndev(cfg))) {
-		/* we only allow to connect using virtual interface in case of P2P */
-			if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-				WL_ERR(("Find p2p index from wdev(%p) failed\n",
-					dev->ieee80211_ptr));
-				return BCME_ERROR;
-			}
-			wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
-				VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
-	} else if (dev == bcmcfg_to_prmry_ndev(cfg)) {
-		/* find the RSN_IE */
-		if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
-			DOT11_MNG_RSN_ID)) != NULL) {
-			WL_DBG((" WPA2 IE is found\n"));
-		}
-		/* find the WPA_IE */
-		if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
-			sme->ie_len)) != NULL) {
-			WL_DBG((" WPA IE is found\n"));
-		}
-		if (wpa_ie != NULL || wpa2_ie != NULL) {
-			wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
-			wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
-			wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
-			err = wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
-				cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-			if (unlikely(err)) {
-				WL_ERR(("wpaie set error (%d)\n", err));
-				return err;
-			}
-		} else {
-			err = wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
-				cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-			if (unlikely(err)) {
-				WL_ERR(("wpaie set error (%d)\n", err));
-				return err;
-			}
-		}
-
-		if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-			WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-			return BCME_ERROR;
-		}
-		err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
-			VNDR_IE_ASSOCREQ_FLAG, (const u8 *)sme->ie, sme->ie_len);
-		if (unlikely(err)) {
-			return err;
-		}
-	}
-	if (chan) {
-		/* If RCC is not enabled, use the channel provided by userspace */
-		cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
-		chan_cnt = 1;
-		WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg->channel,
-			chan->center_freq, chan_cnt));
-	} else {
-		/*
-		 * No channel information from user space. if RCC is enabled, the RCC
-		 * would prepare the channel list, else no channel would be provided
-		 * and firmware would need to do a full channel scan.
-		 */
-		WL_DBG(("No channel info from user space\n"));
-		cfg->channel = 0;
-	}
-	WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
-	WL_DBG(("3. set wpa version \n"));
-	err = wl_set_wpa_version(dev, sme);
-	if (unlikely(err)) {
-		WL_ERR(("Invalid wpa_version\n"));
-		return err;
-	}
-		err = wl_set_auth_type(dev, sme);
-		if (unlikely(err)) {
-			WL_ERR(("Invalid auth type\n"));
-			return err;
-		}
-
-	err = wl_set_set_cipher(dev, sme);
-	if (unlikely(err)) {
-		WL_ERR(("Invalid ciper\n"));
-		return err;
-	}
-
-	err = wl_set_key_mgmt(dev, sme);
-	if (unlikely(err)) {
-		WL_ERR(("Invalid key mgmt\n"));
-		return err;
-	}
-
-	err = wl_set_set_sharedkey(dev, sme);
-	if (unlikely(err)) {
-		WL_ERR(("Invalid shared key\n"));
-		return err;
-	}
-
-	/*
-	 *  Join with specific BSSID and cached SSID
-	 *  If SSID is zero join based on BSSID only
-	 */
-	join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
-		chan_cnt * sizeof(chanspec_t);
-	ext_join_params =  (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
-	if (ext_join_params == NULL) {
-		err = -ENOMEM;
-		wl_clr_drv_status(cfg, CONNECTING, dev);
-		goto exit;
-	}
-	ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
-	memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
-	wl_update_prof(cfg, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
-	ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
-	/* increate dwell time to receive probe response or detect Beacon
-	* from target AP at a noisy air only during connect command
-	*/
-	ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
-	ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
-	/* Set up join scan parameters */
-	ext_join_params->scan.scan_type = -1;
-	ext_join_params->scan.nprobes = chan_cnt ?
-		(ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
-	ext_join_params->scan.home_time = -1;
-
-	if (sme->bssid)
-		memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
-	else
-		memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
-	ext_join_params->assoc.chanspec_num = chan_cnt;
-	if (chan_cnt) {
-		if (cfg->channel) {
-			/*
-			 * Use the channel provided by userspace
-			 */
-			u16 channel, band, bw, ctl_sb;
-			chanspec_t chspec;
-			channel = cfg->channel;
-			band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
-				: WL_CHANSPEC_BAND_5G;
-
-			/* Get min_bw set for the interface */
-			bw = wl_cfg80211_ulb_get_min_bw_chspec(dev->ieee80211_ptr, bssidx);
-			if (bw == INVCHANSPEC) {
-				WL_ERR(("Invalid chanspec \n"));
-				kfree(ext_join_params);
-				return BCME_ERROR;
-			}
-
-			ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
-			chspec = (channel | band | bw | ctl_sb);
-			ext_join_params->assoc.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
-			ext_join_params->assoc.chanspec_list[0] |= chspec;
-			ext_join_params->assoc.chanspec_list[0] =
-				wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
-		}
-	}
-	ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
-	if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
-		WL_INFORM(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
-			ext_join_params->ssid.SSID_len));
-	}
-	wl_set_drv_status(cfg, CONNECTING, dev);
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		kfree(ext_join_params);
-		return BCME_ERROR;
-	}
-	err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-
-	if (cfg->rcc_enabled) {
-		WL_ERR(("Connecting with" MACDBG " ssid \"%s\", len (%d) with rcc channels \n\n",
-			MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
-			ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len));
-	} else {
-		WL_ERR(("Connecting with" MACDBG " ssid \"%s\", len (%d) channel=%d\n\n",
-			MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
-			ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, cfg->channel));
-	}
-
-	kfree(ext_join_params);
-	if (err) {
-		wl_clr_drv_status(cfg, CONNECTING, dev);
-		if (err == BCME_UNSUPPORTED) {
-			WL_DBG(("join iovar is not supported\n"));
-			goto set_ssid;
-		} else {
-			WL_ERR(("error (%d)\n", err));
-			goto exit;
-		}
-	} else
-		goto exit;
-
-set_ssid:
-	memset(&join_params, 0, sizeof(join_params));
-	join_params_size = sizeof(join_params.ssid);
-
-	join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
-	memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
-	join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
-	wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
-	if (sme->bssid)
-		memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
-	else
-		memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
-
-	if (wl_ch_to_chanspec(dev, cfg->channel, &join_params, &join_params_size) < 0) {
-		WL_ERR(("Invalid chanspec\n"));
-		return -EINVAL;
-	}
-
-	WL_DBG(("join_param_size %zu\n", join_params_size));
-
-	if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
-		WL_INFORM(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
-			join_params.ssid.SSID_len));
-	}
-	wl_set_drv_status(cfg, CONNECTING, dev);
-	err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
-	if (err) {
-		WL_ERR(("error (%d)\n", err));
-		wl_clr_drv_status(cfg, CONNECTING, dev);
-	}
-exit:
-	return err;
-}
-
-static s32
-wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
-	u16 reason_code)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	scb_val_t scbval;
-	bool act = false;
-	s32 err = 0;
-	u8 *curbssid;
-#ifdef CUSTOM_SET_CPUCORE
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-#endif /* CUSTOM_SET_CPUCORE */
-	WL_ERR(("Reason %d\n", reason_code));
-	RETURN_EIO_IF_NOT_UP(cfg);
-	act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
-	curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
-#ifdef ESCAN_RESULT_PATCH
-	if (wl_get_drv_status(cfg, CONNECTING, dev) && curbssid &&
-		(memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0)) {
-		WL_ERR(("Disconnecting from connecting device: " MACDBG "\n",
-			MAC2STRDBG(curbssid)));
-		act = true;
-	}
-#endif /* ESCAN_RESULT_PATCH */
-
-	if (act) {
-		/*
-		* Cancel ongoing scan to sync up with sme state machine of cfg80211.
-		*/
-#if !defined(ESCAN_RESULT_PATCH)
-		/* Let scan aborted by F/W */
-		if (cfg->scan_request) {
-			WL_TRACE_HW4(("Aborting the scan! \n"));
-			wl_notify_escan_complete(cfg, dev, true, true);
-		}
-#endif /* ESCAN_RESULT_PATCH */
-		if (wl_get_drv_status(cfg, CONNECTING, dev) ||
-			wl_get_drv_status(cfg, CONNECTED, dev)) {
-				wl_set_drv_status(cfg, DISCONNECTING, dev);
-				scbval.val = reason_code;
-				memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
-				scbval.val = htod32(scbval.val);
-				err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
-						sizeof(scb_val_t), true);
-				if (unlikely(err)) {
-					wl_clr_drv_status(cfg, DISCONNECTING, dev);
-					WL_ERR(("error (%d)\n", err));
-					return err;
-				}
-#if defined(BCM4358_CHIP)
-				WL_ERR(("Wait for complete of disconnecting \n"));
-				OSL_SLEEP(200);
-#endif /* BCM4358_CHIP */
-		}
-	}
-#ifdef CUSTOM_SET_CPUCORE
-	/* set default cpucore */
-	if (dev == bcmcfg_to_prmry_ndev(cfg)) {
-		dhd->chan_isvht80 &= ~DHD_FLAG_STA_MODE;
-		if (!(dhd->chan_isvht80))
-			dhd_set_cpucore(dhd, FALSE);
-	}
-#endif /* CUSTOM_SET_CPUCORE */
-
-	return err;
-}
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-static s32
-wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
-	enum nl80211_tx_power_setting type, s32 mbm)
-#else
-static s32
-wl_cfg80211_set_tx_power(struct wiphy *wiphy,
-	enum nl80211_tx_power_setting type, s32 dbm)
-#endif /* WL_CFG80211_P2P_DEV_IF */
-{
-
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-	s32 err = 0;
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	s32 dbm = MBM_TO_DBM(mbm);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
-	defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
-	dbm = MBM_TO_DBM(dbm);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-	switch (type) {
-	case NL80211_TX_POWER_AUTOMATIC:
-		break;
-	case NL80211_TX_POWER_LIMITED:
-		if (dbm < 0) {
-			WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
-			return -EINVAL;
-		}
-		break;
-	case NL80211_TX_POWER_FIXED:
-		if (dbm < 0) {
-			WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
-			return -EINVAL;
-		}
-		break;
-	}
-
-	err = wl_set_tx_power(ndev, type, dbm);
-	if (unlikely(err)) {
-		WL_ERR(("error (%d)\n", err));
-		return err;
-	}
-
-	cfg->conf->tx_power = dbm;
-
-	return err;
-}
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
-	struct wireless_dev *wdev, s32 *dbm)
-#else
-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
-#endif /* WL_CFG80211_P2P_DEV_IF */
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-	s32 err = 0;
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-	err = wl_get_tx_power(ndev, dbm);
-	if (unlikely(err))
-		WL_ERR(("error (%d)\n", err));
-
-	return err;
-}
-
-static s32
-wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
-	u8 key_idx, bool unicast, bool multicast)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	u32 index;
-	s32 wsec;
-	s32 err = 0;
-	s32 bssidx;
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	WL_DBG(("key index (%d)\n", key_idx));
-	RETURN_EIO_IF_NOT_UP(cfg);
-	err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
-	if (unlikely(err)) {
-		WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
-		return err;
-	}
-	if (wsec == WEP_ENABLED) {
-		/* Just select a new current key */
-		index = (u32) key_idx;
-		index = htod32(index);
-		err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
-			sizeof(index), true);
-		if (unlikely(err)) {
-			WL_ERR(("error (%d)\n", err));
-		}
-	}
-	return err;
-}
-
-static s32
-wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
-	u8 key_idx, const u8 *mac_addr, struct key_params *params)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct wl_wsec_key key;
-	s32 err = 0;
-	s32 bssidx;
-	s32 mode = wl_get_mode_by_netdev(cfg, dev);
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-	memset(&key, 0, sizeof(key));
-	key.index = (u32) key_idx;
-
-	if (!ETHER_ISMULTI(mac_addr))
-		memcpy((char *)&key.ea, (const void *)mac_addr, ETHER_ADDR_LEN);
-	key.len = (u32) params->key_len;
-
-	/* check for key index change */
-	if (key.len == 0) {
-		/* key delete */
-		swap_key_from_BE(&key);
-		err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
-			cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-		if (unlikely(err)) {
-			WL_ERR(("key delete error (%d)\n", err));
-			return err;
-		}
-	} else {
-		if (key.len > sizeof(key.data)) {
-			WL_ERR(("Invalid key length (%d)\n", key.len));
-			return -EINVAL;
-		}
-		WL_DBG(("Setting the key index %d\n", key.index));
-		memcpy(key.data, params->key, key.len);
-
-		if ((mode == WL_MODE_BSS) &&
-			(params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
-			u8 keybuf[8];
-			memcpy(keybuf, &key.data[24], sizeof(keybuf));
-			memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
-			memcpy(&key.data[16], keybuf, sizeof(keybuf));
-		}
-
-		/* if IW_ENCODE_EXT_RX_SEQ_VALID set */
-		if (params->seq && params->seq_len == 6) {
-			/* rx iv */
-			u8 *ivptr;
-			ivptr = (u8 *) params->seq;
-			key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
-				(ivptr[3] << 8) | ivptr[2];
-			key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
-			key.iv_initialized = true;
-		}
-
-		switch (params->cipher) {
-		case WLAN_CIPHER_SUITE_WEP40:
-			key.algo = CRYPTO_ALGO_WEP1;
-			WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
-			break;
-		case WLAN_CIPHER_SUITE_WEP104:
-			key.algo = CRYPTO_ALGO_WEP128;
-			WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
-			break;
-		case WLAN_CIPHER_SUITE_TKIP:
-			key.algo = CRYPTO_ALGO_TKIP;
-			WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
-			break;
-		case WLAN_CIPHER_SUITE_AES_CMAC:
-			key.algo = CRYPTO_ALGO_AES_CCM;
-			WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
-			break;
-		case WLAN_CIPHER_SUITE_CCMP:
-			key.algo = CRYPTO_ALGO_AES_CCM;
-			WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
-			break;
-		default:
-			WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
-			return -EINVAL;
-		}
-		swap_key_from_BE(&key);
-		/* need to guarantee EAPOL 4/4 send out before set key */
-		dhd_wait_pend8021x(dev);
-		err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
-			cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-		if (unlikely(err)) {
-			WL_ERR(("WLC_SET_KEY error (%d)\n", err));
-			return err;
-		}
-	}
-	return err;
-}
-
-int
-wl_cfg80211_enable_roam_offload(struct net_device *dev, int enable)
-{
-	int err;
-	wl_eventmsg_buf_t ev_buf;
-
-	if (dev != bcmcfg_to_prmry_ndev(g_bcm_cfg)) {
-		/* roam offload is only for the primary device */
-		return -1;
-	}
-	err = wldev_iovar_setint(dev, "roam_offload", enable);
-	if (err)
-		return err;
-
-	if (enable) {
-		err = wldev_iovar_setint(dev, "sup_wpa_tmo", IDSUP_4WAY_HANDSHAKE_TIMEOUT);
-		if (err) {
-			WL_INFORM(("Setting 'sup_wpa_tmo' failed, err=%d\n", err));
-		}
-	}
-
-	bzero(&ev_buf, sizeof(wl_eventmsg_buf_t));
-	wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
-	wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
-	wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
-	wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
-	wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
-	err = wl_cfg80211_apply_eventbuffer(dev, g_bcm_cfg, &ev_buf);
-	if (!err) {
-		g_bcm_cfg->roam_offload = enable;
-	}
-	return err;
-}
-
-#if defined(WL_VIRTUAL_APSTA)
-int
-wl_cfg80211_interface_create(struct net_device *dev, char *name)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	bcm_struct_cfgdev *new_cfgdev;
-
-	new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
-			NL80211_IFTYPE_STATION, NULL, name);
-	if (!new_cfgdev) {
-		return BCME_ERROR;
-	}
-	else {
-		WL_DBG(("Iface %s created successfuly\n", name));
-		return BCME_OK;
-	}
-}
-
-int
-wl_cfg80211_interface_delete(struct net_device *dev, char *name)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct net_info *iter, *next;
-	int err = BCME_ERROR;
-
-	if (name == NULL) {
-		return BCME_ERROR;
-	}
-
-	for_each_ndev(cfg, iter, next) {
-		if (iter->ndev) {
-			if (strcmp(iter->ndev->name, name) == 0) {
-				err =  wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
-				break;
-			}
-		}
-	}
-	if (!err) {
-		WL_DBG(("Iface %s deleted successfuly", name));
-	}
-	return err;
-}
-#endif /* defined (WL_VIRTUAL_APSTA) */
-
-static s32
-wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
-	u8 key_idx, bool pairwise, const u8 *mac_addr,
-	struct key_params *params)
-{
-	struct wl_wsec_key key;
-	s32 val = 0;
-	s32 wsec = 0;
-	s32 err = 0;
-	u8 keybuf[8];
-	s32 bssidx = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	s32 mode = wl_get_mode_by_netdev(cfg, dev);
-	WL_DBG(("key index (%d)\n", key_idx));
-	RETURN_EIO_IF_NOT_UP(cfg);
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	if (mac_addr &&
-		((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
-		(params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
-			wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
-			goto exit;
-	}
-	memset(&key, 0, sizeof(key));
-	/* Clear any buffered wep key */
-	memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
-
-	key.len = (u32) params->key_len;
-	key.index = (u32) key_idx;
-
-	if (unlikely(key.len > sizeof(key.data))) {
-		WL_ERR(("Too long key length (%u)\n", key.len));
-		return -EINVAL;
-	}
-	memcpy(key.data, params->key, key.len);
-
-	key.flags = WL_PRIMARY_KEY;
-	switch (params->cipher) {
-	case WLAN_CIPHER_SUITE_WEP40:
-		key.algo = CRYPTO_ALGO_WEP1;
-		val = WEP_ENABLED;
-		WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
-		break;
-	case WLAN_CIPHER_SUITE_WEP104:
-		key.algo = CRYPTO_ALGO_WEP128;
-		val = WEP_ENABLED;
-		WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
-		break;
-	case WLAN_CIPHER_SUITE_TKIP:
-		key.algo = CRYPTO_ALGO_TKIP;
-		val = TKIP_ENABLED;
-		/* wpa_supplicant switches the third and fourth quarters of the TKIP key */
-		if (mode == WL_MODE_BSS) {
-			bcopy(&key.data[24], keybuf, sizeof(keybuf));
-			bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
-			bcopy(keybuf, &key.data[16], sizeof(keybuf));
-		}
-		WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
-		break;
-	case WLAN_CIPHER_SUITE_AES_CMAC:
-		key.algo = CRYPTO_ALGO_AES_CCM;
-		val = AES_ENABLED;
-		WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
-		break;
-	case WLAN_CIPHER_SUITE_CCMP:
-		key.algo = CRYPTO_ALGO_AES_CCM;
-		val = AES_ENABLED;
-		WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
-		break;
-	default:
-		WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
-		return -EINVAL;
-	}
-
-	/* Set the new key/index */
-	if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
-		WL_ERR(("IBSS KEY setted\n"));
-		wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
-	}
-	swap_key_from_BE(&key);
-	if ((params->cipher == WLAN_CIPHER_SUITE_WEP40) ||
-		(params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
-		/*
-		 * For AP role, since we are doing a wl down before bringing up AP,
-		 * the plumbed keys will be lost. So for AP once we bring up AP, we
-		 * need to plumb keys again. So buffer the keys for future use. This
-		 * is more like a WAR. If firmware later has the capability to do
-		 * interface upgrade without doing a "wl down" and "wl apsta 0", then
-		 * this will not be required.
-		 */
-		WL_DBG(("Buffering WEP Keys \n"));
-		memcpy(&cfg->wep_key, &key, sizeof(struct wl_wsec_key));
-	}
-	err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
-		WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-	if (unlikely(err)) {
-		WL_ERR(("WLC_SET_KEY error (%d)\n", err));
-		return err;
-	}
-
-exit:
-	err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
-	if (unlikely(err)) {
-		WL_ERR(("get wsec error (%d)\n", err));
-		return err;
-	}
-
-	wsec |= val;
-	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
-	if (unlikely(err)) {
-		WL_ERR(("set wsec error (%d)\n", err));
-		return err;
-	}
-
-	return err;
-}
-
-static s32
-wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
-	u8 key_idx, bool pairwise, const u8 *mac_addr)
-{
-	struct wl_wsec_key key;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	s32 err = 0;
-	s32 bssidx;
-
-	WL_DBG(("Enter. key_idx: %d\n", key_idx));
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
-		return -EINVAL;
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-	memset(&key, 0, sizeof(key));
-
-	key.flags = WL_PRIMARY_KEY;
-	key.algo = CRYPTO_ALGO_OFF;
-	key.index = (u32) key_idx;
-
-	/* Set the new key/index */
-	swap_key_from_BE(&key);
-	err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
-		WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-	if (unlikely(err)) {
-		if (err == -EINVAL) {
-			if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
-				/* we ignore this key index in this case */
-				WL_DBG(("invalid key index (%d)\n", key_idx));
-			}
-		} else {
-			WL_ERR(("WLC_SET_KEY error (%d)\n", err));
-		}
-		return err;
-	}
-	return err;
-}
-
-static s32
-wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
-	u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
-	void (*callback) (void *cookie, struct key_params * params))
-{
-	struct key_params params;
-	struct wl_wsec_key key;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct wl_security *sec;
-	s32 wsec;
-	s32 err = 0;
-	s32 bssidx;
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-	WL_DBG(("key index (%d)\n", key_idx));
-	RETURN_EIO_IF_NOT_UP(cfg);
-	memset(&key, 0, sizeof(key));
-	key.index = key_idx;
-	swap_key_to_BE(&key);
-	memset(&params, 0, sizeof(params));
-	params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
-	memcpy((void *)params.key, key.data, params.key_len);
-
-	err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
-	if (unlikely(err)) {
-		WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
-		return err;
-	}
-	switch (WSEC_ENABLED(wsec)) {
-		case WEP_ENABLED:
-			sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
-			if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
-				params.cipher = WLAN_CIPHER_SUITE_WEP40;
-				WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
-			} else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
-				params.cipher = WLAN_CIPHER_SUITE_WEP104;
-				WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
-			}
-			break;
-		case TKIP_ENABLED:
-			params.cipher = WLAN_CIPHER_SUITE_TKIP;
-			WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
-			break;
-		case AES_ENABLED:
-			params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
-			WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
-			break;
-		default:
-			WL_ERR(("Invalid algo (0x%x)\n", wsec));
-			return -EINVAL;
-	}
-
-	callback(cookie, &params);
-	return err;
-}
-
-static s32
-wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
-	struct net_device *dev, u8 key_idx)
-{
-	WL_INFORM(("Not supported\n"));
-	return -EOPNOTSUPP;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-static s32
-wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
-	const u8 *mac, struct station_info *sinfo)
-#else
-static s32
-wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
-	u8 *mac, struct station_info *sinfo)
-#endif
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	scb_val_t scb_val;
-	s32 rssi;
-	s32 rate;
-	s32 err = 0;
-	sta_info_t *sta;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-	s8 eabuf[ETHER_ADDR_STR_LEN];
-#endif
-	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
-	bool fw_assoc_state = FALSE;
-	u32 dhd_assoc_state = 0;
-	RETURN_EIO_IF_NOT_UP(cfg);
-	if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
-		err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
-			ETHER_ADDR_LEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
-		if (err < 0) {
-			WL_ERR(("GET STA INFO failed, %d\n", err));
-			return err;
-		}
-		sinfo->filled = STA_INFO_BIT(INFO_INACTIVE_TIME);
-		sta = (sta_info_t *)cfg->ioctl_buf;
-		sta->len = dtoh16(sta->len);
-		sta->cap = dtoh16(sta->cap);
-		sta->flags = dtoh32(sta->flags);
-		sta->idle = dtoh32(sta->idle);
-		sta->in = dtoh32(sta->in);
-		sinfo->inactive_time = sta->idle * 1000;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
-		if (sta->flags & WL_STA_ASSOC) {
-			sinfo->filled |= STA_INFO_BIT(INFO_CONNECTED_TIME);
-			sinfo->connected_time = sta->in;
-		}
-		WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n",
-			bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
-			sta->idle * 1000));
-#endif
-	} else if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS ||
-		wl_get_mode_by_netdev(cfg, dev) == WL_MODE_IBSS) {
-		get_pktcnt_t pktcnt;
-		u8 *curmacp;
-
-		if (cfg->roam_offload) {
-			struct ether_addr bssid;
-			err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
-			if (err) {
-				WL_ERR(("Failed to get current BSSID\n"));
-			} else {
-				if (!ETHER_ISNULLADDR(&bssid.octet) &&
-						memcmp(mac, &bssid.octet, ETHER_ADDR_LEN) != 0) {
-					/* roaming is detected */
-					err = wl_cfg80211_delayed_roam(cfg, dev, &bssid);
-					if (err)
-						WL_ERR(("Failed to handle the delayed roam, "
-							"err=%d", err));
-					mac = (u8 *)bssid.octet;
-				}
-			}
-		}
-		dhd_assoc_state = wl_get_drv_status(cfg, CONNECTED, dev);
-		fw_assoc_state = dhd_is_associated(dhd, 0, &err);
-		if (!dhd_assoc_state || !fw_assoc_state) {
-			WL_ERR(("NOT assoc\n"));
-			if (err == -ERESTARTSYS)
-				return err;
-			if (!dhd_assoc_state) {
-				WL_TRACE_HW4(("drv state is not connected \n"));
-			}
-			if (!fw_assoc_state) {
-				WL_TRACE_HW4(("fw state is not associated \n"));
-			}
-			/* Disconnect due to fw is not associated for FW_ASSOC_WATCHDOG_TIME ms.
-			* 'err == 0' of dhd_is_associated() and '!fw_assoc_state'
-			* means that BSSID is null.
-			*/
-			if (dhd_assoc_state && !fw_assoc_state && !err) {
-				if (!fw_assoc_watchdog_started) {
-					fw_assoc_watchdog_ms = OSL_SYSUPTIME();
-					fw_assoc_watchdog_started = TRUE;
-					WL_TRACE_HW4(("fw_assoc_watchdog_started \n"));
-				} else {
-					if (OSL_SYSUPTIME() - fw_assoc_watchdog_ms >
-						FW_ASSOC_WATCHDOG_TIME) {
-						fw_assoc_watchdog_started = FALSE;
-						err = -ENODEV;
-						WL_TRACE_HW4(("fw is not associated for %d ms \n",
-							(OSL_SYSUPTIME() - fw_assoc_watchdog_ms)));
-						goto get_station_err;
-					}
-				}
-			}
-			err = -ENODEV;
-			return err;
-		}
-		fw_assoc_watchdog_started = FALSE;
-		curmacp = wl_read_prof(cfg, dev, WL_PROF_BSSID);
-		if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
-			WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
-				MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
-		}
-
-		/* Report the current tx rate */
-		err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
-		if (err) {
-			WL_ERR(("Could not get rate (%d)\n", err));
-		} else {
-#if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
-			int rxpktglom;
-#endif
-			rate = dtoh32(rate);
-			sinfo->filled |= STA_INFO_BIT(INFO_TX_BITRATE);
-			sinfo->txrate.legacy = rate * 5;
-			WL_DBG(("Rate %d Mbps\n", (rate / 2)));
-#if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
-			rxpktglom = ((rate/2) > 150) ? 20 : 10;
-
-			if (maxrxpktglom != rxpktglom) {
-				maxrxpktglom = rxpktglom;
-				WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
-					maxrxpktglom));
-				err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
-					(char*)&maxrxpktglom, 4, cfg->ioctl_buf,
-					WLC_IOCTL_MAXLEN, NULL);
-				if (err < 0) {
-					WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
-				}
-			}
-#endif
-		}
-
-		memset(&scb_val, 0, sizeof(scb_val));
-		scb_val.val = 0;
-		err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
-			sizeof(scb_val_t), false);
-		if (err) {
-			WL_ERR(("Could not get rssi (%d)\n", err));
-			goto get_station_err;
-		}
-		rssi = wl_rssi_offset(dtoh32(scb_val.val));
-		sinfo->filled |= STA_INFO_BIT(INFO_SIGNAL);
-		sinfo->signal = rssi;
-		WL_DBG(("RSSI %d dBm\n", rssi));
-		err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
-			sizeof(pktcnt), false);
-		if (!err) {
-			sinfo->filled |= (STA_INFO_BIT(INFO_RX_PACKETS) |
-				STA_INFO_BIT(INFO_RX_DROP_MISC) |
-				STA_INFO_BIT(INFO_TX_PACKETS) |
-				STA_INFO_BIT(INFO_TX_FAILED));
-			sinfo->rx_packets = pktcnt.rx_good_pkt;
-			sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
-			sinfo->tx_packets = pktcnt.tx_good_pkt;
-			sinfo->tx_failed  = pktcnt.tx_bad_pkt;
-		}
-get_station_err:
-		if (err && (err != -ERESTARTSYS)) {
-			/* Disconnect due to zero BSSID or error to get RSSI */
-			WL_ERR(("force cfg80211_disconnected: %d\n", err));
-			wl_clr_drv_status(cfg, CONNECTED, dev);
-			CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
-			wl_link_down(cfg);
-		}
-	}
-	else {
-		WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg, dev)));
-	}
-
-	return err;
-}
-
-static s32
-wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
-	bool enabled, s32 timeout)
-{
-	s32 pm;
-	s32 err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-	WL_DBG(("Enter\n"));
-	if (cfg->p2p_net == dev || _net_info == NULL ||
-		!wl_get_drv_status(cfg, CONNECTED, dev) ||
-		(wl_get_mode_by_netdev(cfg, dev) != WL_MODE_BSS &&
-		wl_get_mode_by_netdev(cfg, dev) != WL_MODE_IBSS)) {
-		return err;
-	}
-	/* Enlarge pm_enable_work */
-	wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_LONG);
-
-	pm = enabled ? PM_FAST : PM_OFF;
-	if (_net_info->pm_block) {
-		WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
-			dev->name, _net_info->pm_block));
-		pm = PM_OFF;
-	}
-	pm = htod32(pm);
-	WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
-	err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
-	if (unlikely(err)) {
-		if (err == -ENODEV)
-			WL_DBG(("net_device is not ready yet\n"));
-		else
-			WL_ERR(("error (%d)\n", err));
-		return err;
-	}
-	wl_cfg80211_update_power_mode(dev);
-	return err;
-}
-
-void wl_cfg80211_update_power_mode(struct net_device *dev)
-{
-	int err, pm = -1;
-
-	err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), true);
-	if (err)
-		WL_ERR(("%s:error (%d)\n", __FUNCTION__, err));
-	else if (pm != -1 && dev->ieee80211_ptr)
-		dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true;
-}
-
-void wl_cfg80211_set_passive_scan(struct net_device *dev, char *command)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	if (strcmp(command, "SCAN-ACTIVE") == 0) {
-		cfg->active_scan = 1;
-	} else if (strcmp(command, "SCAN-PASSIVE") == 0) {
-		cfg->active_scan = 0;
-	} else
-		WL_ERR(("Unknown command \n"));
-}
-
-static __used u32 wl_find_msb(u16 bit16)
-{
-	u32 ret = 0;
-
-	if (bit16 & 0xff00) {
-		ret += 8;
-		bit16 >>= 8;
-	}
-
-	if (bit16 & 0xf0) {
-		ret += 4;
-		bit16 >>= 4;
-	}
-
-	if (bit16 & 0xc) {
-		ret += 2;
-		bit16 >>= 2;
-	}
-
-	if (bit16 & 2)
-		ret += bit16 & 2;
-	else if (bit16)
-		ret += bit16;
-
-	return ret;
-}
-
-static s32 wl_cfg80211_resume(struct wiphy *wiphy)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-	s32 err = BCME_OK;
-
-	if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
-		WL_INFORM(("device is not ready\n"));
-		return err;
-	}
-
-	return err;
-}
-
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
-static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
-#else
-static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
-#endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
-{
-	s32 err = BCME_OK;
-#ifdef DHD_CLEAR_ON_SUSPEND
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_info *iter, *next;
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-	unsigned long flags;
-	if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
-		WL_INFORM(("device is not ready : status (%d)\n",
-			(int)cfg->status));
-		return err;
-	}
-	for_each_ndev(cfg, iter, next) {
-		/* p2p discovery iface doesn't have a ndev associated with it (for kernel > 3.8) */
-		if (iter->ndev)
-			wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
-		}
-	spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
-	if (cfg->scan_request) {
-		cfg80211_scan_done(cfg->scan_request, true);
-		cfg->scan_request = NULL;
-	}
-	for_each_ndev(cfg, iter, next) {
-		if (iter->ndev) {
-			wl_clr_drv_status(cfg, SCANNING, iter->ndev);
-			wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
-		}
-	}
-	spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
-	for_each_ndev(cfg, iter, next) {
-		if (iter->ndev) {
-			if (wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
-				wl_bss_connect_done(cfg, iter->ndev, NULL, NULL, false);
-			}
-		}
-	}
-#endif /* DHD_CLEAR_ON_SUSPEND */
-
-
-	return err;
-}
-
-static s32
-wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
-	s32 err)
-{
-	int i, j;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
-
-	if (!pmk_list) {
-		WL_INFORM(("pmk_list is NULL\n"));
-		return -EINVAL;
-	}
-	/* pmk list is supported only for STA interface i.e. primary interface
-	 * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
-	 */
-	if (primary_dev != dev) {
-		WL_INFORM(("Not supporting Flushing pmklist on virtual"
-			" interfaces than primary interface\n"));
-		return err;
-	}
-
-	WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
-	for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
-		WL_DBG(("PMKID[%d]: %pM =\n", i,
-			&pmk_list->pmkids.pmkid[i].BSSID));
-		for (j = 0; j < WPA2_PMKID_LEN; j++) {
-			WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
-		}
-	}
-	if (likely(!err)) {
-		err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
-			sizeof(*pmk_list), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-	}
-
-	return err;
-}
-
-static s32
-wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
-	struct cfg80211_pmksa *pmksa)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	s32 err = 0;
-	int i;
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-	for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
-		if (!memcmp(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
-			ETHER_ADDR_LEN))
-			break;
-	if (i < WL_NUM_PMKIDS_MAX) {
-		memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
-			ETHER_ADDR_LEN);
-		memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
-			WPA2_PMKID_LEN);
-		if (i == cfg->pmk_list->pmkids.npmkid)
-			cfg->pmk_list->pmkids.npmkid++;
-	} else {
-		err = -EINVAL;
-	}
-	WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
-		&cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].BSSID));
-	for (i = 0; i < WPA2_PMKID_LEN; i++) {
-		WL_DBG(("%02x\n",
-			cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].
-			PMKID[i]));
-	}
-
-	err = wl_update_pmklist(dev, cfg->pmk_list, err);
-
-	return err;
-}
-
-static s32
-wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
-	struct cfg80211_pmksa *pmksa)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-
-	struct _pmkid_list pmkid = {.npmkid = 0};
-	s32 err = 0;
-	int i;
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-	memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
-	memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
-
-	WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
-		&pmkid.pmkid[0].BSSID));
-	for (i = 0; i < WPA2_PMKID_LEN; i++) {
-		WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
-	}
-
-	for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
-		if (!memcmp
-		    (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
-		     ETHER_ADDR_LEN))
-			break;
-
-	if ((cfg->pmk_list->pmkids.npmkid > 0) &&
-		(i < cfg->pmk_list->pmkids.npmkid)) {
-		memset(&cfg->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
-		for (; i < (cfg->pmk_list->pmkids.npmkid - 1); i++) {
-			memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
-				&cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
-				ETHER_ADDR_LEN);
-			memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
-				&cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
-				WPA2_PMKID_LEN);
-		}
-		cfg->pmk_list->pmkids.npmkid--;
-	} else {
-		err = -EINVAL;
-	}
-
-	err = wl_update_pmklist(dev, cfg->pmk_list, err);
-
-	return err;
-
-}
-
-static s32
-wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	s32 err = 0;
-	RETURN_EIO_IF_NOT_UP(cfg);
-	memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
-	err = wl_update_pmklist(dev, cfg->pmk_list, err);
-	return err;
-
-}
-
-static wl_scan_params_t *
-wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
-{
-	wl_scan_params_t *params;
-	int params_size;
-	int num_chans;
-	int bssidx = 0;
-
-	*out_params_size = 0;
-
-	/* Our scan params only need space for 1 channel and 0 ssids */
-	params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
-	params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
-	if (params == NULL) {
-		WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
-		return params;
-	}
-	memset(params, 0, params_size);
-	params->nprobes = nprobes;
-
-	num_chans = (channel == 0) ? 0 : 1;
-
-	memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
-	params->bss_type = DOT11_BSSTYPE_ANY;
-	params->scan_type = DOT11_SCANTYPE_ACTIVE;
-	params->nprobes = htod32(1);
-	params->active_time = htod32(-1);
-	params->passive_time = htod32(-1);
-	params->home_time = htod32(10);
-	if (channel == -1)
-		params->channel_list[0] = htodchanspec(channel);
-	else
-		params->channel_list[0] = wl_ch_host_to_driver(bssidx, channel);
-
-	/* Our scan params have 1 channel and 0 ssids */
-	params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
-		(num_chans & WL_SCAN_PARAMS_COUNT_MASK));
-
-	*out_params_size = params_size;	/* rtn size to the caller */
-	return params;
-}
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-static s32
-wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
-	struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
-#else
-static s32
-wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
-	struct ieee80211_channel * channel,
-	enum nl80211_channel_type channel_type,
-	unsigned int duration, u64 *cookie)
-#endif /* WL_CFG80211_P2P_DEV_IF */
-{
-	s32 target_channel;
-	s32 err = BCME_OK;
-	struct ether_addr primary_mac;
-	struct net_device *ndev = NULL;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
-		ieee80211_frequency_to_channel(channel->center_freq),
-		duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
-
-	if (!cfg->p2p) {
-		WL_ERR(("cfg->p2p is not initialized\n"));
-		err = BCME_ERROR;
-		goto exit;
-	}
-
-#ifdef P2P_LISTEN_OFFLOADING
-	if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
-		WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
-		return -EAGAIN;
-	}
-#endif /* P2P_LISTEN_OFFLOADING */
-
-#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-	if (wl_get_drv_status_all(cfg, SCANNING)) {
-		wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
-	}
-#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-
-	target_channel = ieee80211_frequency_to_channel(channel->center_freq);
-	memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
-#if defined(WL_ENABLE_P2P_IF)
-	cfg->remain_on_chan_type = channel_type;
-#endif /* WL_ENABLE_P2P_IF */
-	*cookie = wl_cfg80211_get_new_roc_id(cfg);
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-	if (wl_get_drv_status(cfg, SCANNING, ndev)) {
-		struct timer_list *_timer;
-		WL_DBG(("scan is running. go to fake listen state\n"));
-
-		if (duration > LONG_LISTEN_TIME) {
-			wl_cfg80211_scan_abort(cfg);
-		} else {
-			wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
-
-			if (timer_pending(&cfg->p2p->listen_timer)) {
-				WL_DBG(("cancel current listen timer \n"));
-				del_timer_sync(&cfg->p2p->listen_timer);
-			}
-
-			_timer = &cfg->p2p->listen_timer;
-			wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
-
-			INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
-
-			err = BCME_OK;
-			goto exit;
-		}
-	}
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-
-#ifdef WL_CFG80211_SYNC_GON
-	if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
-		/* do not enter listen mode again if we are in listen mode already for next af.
-		 * remain on channel completion will be returned by waiting next af completion.
-		 */
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-		wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
-#else
-		wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-		goto exit;
-	}
-#endif /* WL_CFG80211_SYNC_GON */
-	if (cfg->p2p && !cfg->p2p->on) {
-		/* In case of p2p_listen command, supplicant send remain_on_channel
-		 * without turning on P2P
-		 */
-		get_primary_mac(cfg, &primary_mac);
-		wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
-		p2p_on(cfg) = true;
-	}
-
-	if (p2p_is_on(cfg)) {
-		err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
-		if (unlikely(err)) {
-			goto exit;
-		}
-#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-		wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
-#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-		err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
-
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-		if (err == BCME_OK) {
-			wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
-		} else {
-			/* if failed, firmware may be internal scanning state.
-			 * so other scan request shall not abort it
-			 */
-			wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
-		}
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-		/* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
-		 * and expire timer will send a completion to the upper layer
-		 */
-		err = BCME_OK;
-	}
-
-exit:
-	if (err == BCME_OK) {
-		WL_INFORM(("Success\n"));
-#if defined(WL_CFG80211_P2P_DEV_IF)
-		cfg80211_ready_on_channel(cfgdev, *cookie, channel,
-			duration, GFP_KERNEL);
-#else
-		cfg80211_ready_on_channel(cfgdev, *cookie, channel,
-			channel_type, duration, GFP_KERNEL);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-	} else {
-		WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
-	}
-	return err;
-}
-
-static s32
-wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
-	bcm_struct_cfgdev *cfgdev, u64 cookie)
-{
-	s32 err = 0;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-#ifdef P2PLISTEN_AP_SAMECHN
-	struct net_device *dev;
-#endif /* P2PLISTEN_AP_SAMECHN */
-
-	RETURN_EIO_IF_NOT_UP(cfg);
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
-		WL_DBG((" enter ) on P2P dedicated discover interface\n"));
-	}
-#else
-	WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-#ifdef P2PLISTEN_AP_SAMECHN
-	if (cfg && cfg->p2p_resp_apchn_status) {
-		dev = bcmcfg_to_prmry_ndev(cfg);
-		wl_cfg80211_set_p2p_resp_ap_chn(dev, 0);
-		cfg->p2p_resp_apchn_status = false;
-		WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
-	}
-#endif /* P2PLISTEN_AP_SAMECHN */
-
-	if (cfg->last_roc_id == cookie) {
-		wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
-			wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
-	} else {
-		WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
-			__FUNCTION__, cookie, cfg->last_roc_id));
-	}
-
-	return err;
-}
-
-static void
-wl_cfg80211_afx_handler(struct work_struct *work)
-{
-	struct afx_hdl *afx_instance;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	s32 ret = BCME_OK;
-
-	BCM_SET_CONTAINER_OF(afx_instance, work, struct afx_hdl, work);
-	if (afx_instance != NULL && cfg->afx_hdl->is_active) {
-		if (cfg->afx_hdl->is_listen && cfg->afx_hdl->my_listen_chan) {
-			ret = wl_cfgp2p_discover_listen(cfg, cfg->afx_hdl->my_listen_chan,
-				(100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
-		} else {
-			ret = wl_cfgp2p_act_frm_search(cfg, cfg->afx_hdl->dev,
-				cfg->afx_hdl->bssidx, cfg->afx_hdl->peer_listen_chan,
-				NULL);
-		}
-		if (unlikely(ret != BCME_OK)) {
-			WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
-			if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL))
-				complete(&cfg->act_frm_scan);
-		}
-	}
-}
-
-static s32
-wl_cfg80211_af_searching_channel(struct bcm_cfg80211 *cfg, struct net_device *dev)
-{
-	u32 max_retry = WL_CHANNEL_SYNC_RETRY;
-	bool is_p2p_gas = false;
-
-	if (dev == NULL)
-		return -1;
-
-	WL_DBG((" enter ) \n"));
-
-	wl_set_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
-	cfg->afx_hdl->is_active = TRUE;
-
-	if (cfg->afx_hdl->pending_tx_act_frm) {
-		wl_action_frame_t *action_frame;
-		action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
-		if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len))
-			is_p2p_gas = true;
-	}
-
-	/* Loop to wait until we find a peer's channel or the
-	 * pending action frame tx is cancelled.
-	 */
-	while ((cfg->afx_hdl->retry < max_retry) &&
-		(cfg->afx_hdl->peer_chan == WL_INVALID)) {
-		cfg->afx_hdl->is_listen = FALSE;
-		wl_set_drv_status(cfg, SCANNING, dev);
-		WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
-			cfg->afx_hdl->retry));
-		/* search peer on peer's listen channel */
-		schedule_work(&cfg->afx_hdl->work);
-		wait_for_completion_timeout(&cfg->act_frm_scan,
-			msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
-
-		if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
-			!(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
-			break;
-
-		if (is_p2p_gas)
-			break;
-
-		if (cfg->afx_hdl->my_listen_chan) {
-			WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
-				cfg->afx_hdl->my_listen_chan));
-			/* listen on my listen channel */
-			cfg->afx_hdl->is_listen = TRUE;
-			schedule_work(&cfg->afx_hdl->work);
-			wait_for_completion_timeout(&cfg->act_frm_scan,
-				msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
-		}
-		if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
-			!(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
-			break;
-
-		cfg->afx_hdl->retry++;
-
-		WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
-	}
-
-	cfg->afx_hdl->is_active = FALSE;
-
-	wl_clr_drv_status(cfg, SCANNING, dev);
-	wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
-
-	return (cfg->afx_hdl->peer_chan);
-}
-
-struct p2p_config_af_params {
-	s32 max_tx_retry;	/* max tx retry count if tx no ack */
-	/* To make sure to send successfully action frame, we have to turn off mpc
-	 * 0: off, 1: on,  (-1): do nothing
-	 */
-	s32 mpc_onoff;
-#ifdef WL_CFG80211_SYNC_GON
-	bool extra_listen;
-#endif
-	bool search_channel;	/* 1: search peer's channel to send af */
-};
-
-static s32
-wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
-	wl_action_frame_t *action_frame, wl_af_params_t *af_params,
-	struct p2p_config_af_params *config_af_params)
-{
-	s32 err = BCME_OK;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	wifi_p2p_pub_act_frame_t *act_frm =
-		(wifi_p2p_pub_act_frame_t *) (action_frame->data);
-
-	/* initialize default value */
-#ifdef WL_CFG80211_SYNC_GON
-	config_af_params->extra_listen = true;
-#endif
-	config_af_params->search_channel = false;
-	config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
-	config_af_params->mpc_onoff = -1;
-	cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
-
-	switch (act_frm->subtype) {
-	case P2P_PAF_GON_REQ: {
-		WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
-		wl_set_p2p_status(cfg, GO_NEG_PHASE);
-
-		config_af_params->mpc_onoff = 0;
-		config_af_params->search_channel = true;
-		cfg->next_af_subtype = act_frm->subtype + 1;
-
-		/* increase dwell time to wait for RESP frame */
-		af_params->dwell_time = WL_MED_DWELL_TIME;
-
-		break;
-	}
-	case P2P_PAF_GON_RSP: {
-		cfg->next_af_subtype = act_frm->subtype + 1;
-		/* increase dwell time to wait for CONF frame */
-		af_params->dwell_time = WL_MED_DWELL_TIME + 100;
-		break;
-	}
-	case P2P_PAF_GON_CONF: {
-		/* If we reached till GO Neg confirmation reset the filter */
-		WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
-		wl_clr_p2p_status(cfg, GO_NEG_PHASE);
-
-		/* turn on mpc again if go nego is done */
-		config_af_params->mpc_onoff = 1;
-
-		/* minimize dwell time */
-		af_params->dwell_time = WL_MIN_DWELL_TIME;
-
-#ifdef WL_CFG80211_SYNC_GON
-		config_af_params->extra_listen = false;
-#endif /* WL_CFG80211_SYNC_GON */
-		break;
-	}
-	case P2P_PAF_INVITE_REQ: {
-		config_af_params->search_channel = true;
-		cfg->next_af_subtype = act_frm->subtype + 1;
-
-		/* increase dwell time */
-		af_params->dwell_time = WL_MED_DWELL_TIME;
-		break;
-	}
-	case P2P_PAF_INVITE_RSP:
-		/* minimize dwell time */
-		af_params->dwell_time = WL_MIN_DWELL_TIME;
-#ifdef WL_CFG80211_SYNC_GON
-		config_af_params->extra_listen = false;
-#endif /* WL_CFG80211_SYNC_GON */
-		break;
-	case P2P_PAF_DEVDIS_REQ: {
-		if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
-			action_frame->len)) {
-			config_af_params->search_channel = true;
-		}
-
-		cfg->next_af_subtype = act_frm->subtype + 1;
-		/* maximize dwell time to wait for RESP frame */
-		af_params->dwell_time = WL_LONG_DWELL_TIME;
-		break;
-	}
-	case P2P_PAF_DEVDIS_RSP:
-		/* minimize dwell time */
-		af_params->dwell_time = WL_MIN_DWELL_TIME;
-#ifdef WL_CFG80211_SYNC_GON
-		config_af_params->extra_listen = false;
-#endif /* WL_CFG80211_SYNC_GON */
-		break;
-	case P2P_PAF_PROVDIS_REQ: {
-		if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
-			action_frame->len)) {
-			config_af_params->search_channel = true;
-		}
-
-		config_af_params->mpc_onoff = 0;
-		cfg->next_af_subtype = act_frm->subtype + 1;
-		/* increase dwell time to wait for RESP frame */
-		af_params->dwell_time = WL_MED_DWELL_TIME;
-		break;
-	}
-	case P2P_PAF_PROVDIS_RSP: {
-		cfg->next_af_subtype = P2P_PAF_GON_REQ;
-		af_params->dwell_time = WL_MIN_DWELL_TIME;
-#ifdef WL_CFG80211_SYNC_GON
-		config_af_params->extra_listen = false;
-#endif /* WL_CFG80211_SYNC_GON */
-		break;
-	}
-	default:
-		WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
-			act_frm->subtype));
-		err = BCME_BADARG;
-	}
-	return err;
-}
-
-#ifdef WL11U
-static bool
-wl_cfg80211_check_DFS_channel(struct bcm_cfg80211 *cfg, wl_af_params_t *af_params,
-	void *frame, u16 frame_len)
-{
-	struct wl_scan_results *bss_list;
-	struct wl_bss_info *bi = NULL;
-	bool result = false;
-	s32 i;
-	chanspec_t chanspec;
-
-	/* If DFS channel is 52~148, check to block it or not */
-	if (af_params &&
-		(af_params->channel >= 52 && af_params->channel <= 148)) {
-		if (!wl_cfgp2p_is_p2p_action(frame, frame_len)) {
-			bss_list = cfg->bss_list;
-			bi = next_bss(bss_list, bi);
-			for_each_bss(bss_list, bi, i) {
-				chanspec = wl_chspec_driver_to_host(bi->chanspec);
-				if (CHSPEC_IS5G(chanspec) &&
-					((bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(chanspec))
-					== af_params->channel)) {
-					result = true;	/* do not block the action frame */
-					break;
-				}
-			}
-		}
-	}
-	else {
-		result = true;
-	}
-
-	WL_DBG(("result=%s", result?"true":"false"));
-	return result;
-}
-#endif /* WL11U */
-static bool
-wl_cfg80211_check_dwell_overflow(int32 requested_dwell, ulong dwell_jiffies)
-{
-	if ((requested_dwell & CUSTOM_RETRY_MASK) &&
-			(jiffies_to_msecs(jiffies - dwell_jiffies) >
-			 (requested_dwell & ~CUSTOM_RETRY_MASK))) {
-		WL_ERR(("Action frame TX retry time over dwell time!\n"));
-		return true;
-	}
-	return false;
-}
-
-static bool
-wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
-	bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
-	wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
-{
-#ifdef WL11U
-	struct net_device *ndev = NULL;
-#endif /* WL11U */
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	bool ack = false;
-	u8 category, action;
-	s32 tx_retry;
-	struct p2p_config_af_params config_af_params;
-	struct net_info *netinfo;
-#ifdef VSDB
-	ulong off_chan_started_jiffies = 0;
-#endif
-	ulong dwell_jiffies = 0;
-	bool dwell_overflow = false;
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-
-	int32 requested_dwell = af_params->dwell_time;
-
-	/* Add the default dwell time
-	 * Dwell time to stay off-channel to wait for a response action frame
-	 * after transmitting an GO Negotiation action frame
-	 */
-	af_params->dwell_time = WL_DWELL_TIME;
-
-#ifdef WL11U
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	ndev = dev;
-#else
-	ndev = ndev_to_cfgdev(cfgdev);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-#endif /* WL11U */
-
-	category = action_frame->data[DOT11_ACTION_CAT_OFF];
-	action = action_frame->data[DOT11_ACTION_ACT_OFF];
-
-	/* initialize variables */
-	tx_retry = 0;
-	cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
-	config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
-	config_af_params.mpc_onoff = -1;
-	config_af_params.search_channel = false;
-#ifdef WL_CFG80211_SYNC_GON
-	config_af_params.extra_listen = false;
-#endif
-
-	/* config parameters */
-	/* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
-	if (category == DOT11_ACTION_CAT_PUBLIC) {
-		if ((action == P2P_PUB_AF_ACTION) &&
-			(action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
-			/* p2p public action frame process */
-			if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
-				action_frame, af_params, &config_af_params)) {
-				WL_DBG(("Unknown subtype.\n"));
-			}
-
-		} else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
-			/* service discovery process */
-			if (action == P2PSD_ACTION_ID_GAS_IREQ ||
-				action == P2PSD_ACTION_ID_GAS_CREQ) {
-				/* configure service discovery query frame */
-
-				config_af_params.search_channel = true;
-
-				/* save next af suptype to cancel remained dwell time */
-				cfg->next_af_subtype = action + 1;
-
-				af_params->dwell_time = WL_MED_DWELL_TIME;
-				if (requested_dwell & CUSTOM_RETRY_MASK) {
-					config_af_params.max_tx_retry =
-						(requested_dwell & CUSTOM_RETRY_MASK) >> 24;
-					af_params->dwell_time =
-						(requested_dwell & ~CUSTOM_RETRY_MASK);
-					WL_DBG(("Custom retry(%d) and dwell time(%d) is set.\n",
-						config_af_params.max_tx_retry,
-						af_params->dwell_time));
-				}
-			} else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
-				action == P2PSD_ACTION_ID_GAS_CRESP) {
-				/* configure service discovery response frame */
-				af_params->dwell_time = WL_MIN_DWELL_TIME;
-			} else {
-				WL_DBG(("Unknown action type: %d\n", action));
-			}
-		} else {
-			WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
-				category, action, action_frame_len));
-	}
-	} else if (category == P2P_AF_CATEGORY) {
-		/* do not configure anything. it will be sent with a default configuration */
-	} else {
-		WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
-			category, action));
-		if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
-			wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
-			return false;
-		}
-	}
-
-	/* To make sure to send successfully action frame, we have to turn off mpc */
-	if (config_af_params.mpc_onoff == 0) {
-		wldev_iovar_setint(dev, "mpc", 0);
-	}
-
-	netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
-	/* validate channel and p2p ies */
-	if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
-		netinfo && netinfo->bss.ies.probe_req_ie_len) {
-		config_af_params.search_channel = true;
-	} else {
-		config_af_params.search_channel = false;
-	}
-#ifdef WL11U
-	if (ndev == bcmcfg_to_prmry_ndev(cfg))
-		config_af_params.search_channel = false;
-#endif /* WL11U */
-
-#ifdef VSDB
-	/* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
-	if (wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {
-		OSL_SLEEP(50);
-	}
-#endif
-
-	/* if scan is ongoing, abort current scan. */
-	if (wl_get_drv_status_all(cfg, SCANNING)) {
-		wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
-	}
-
-	/* Abort P2P listen */
-	if (discover_cfgdev(cfgdev, cfg)) {
-		if (cfg->p2p_supported && cfg->p2p) {
-			wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
-				wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
-		}
-	}
-
-#ifdef WL11U
-	/* handling DFS channel exceptions */
-	if (!wl_cfg80211_check_DFS_channel(cfg, af_params, action_frame->data, action_frame->len)) {
-		return false;	/* the action frame was blocked */
-	}
-#endif /* WL11U */
-
-	/* set status and destination address before sending af */
-	if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
-		/* set this status to cancel the remained dwell time in rx process */
-		wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
-	}
-	wl_set_drv_status(cfg, SENDING_ACT_FRM, dev);
-	memcpy(cfg->afx_hdl->tx_dst_addr.octet,
-		af_params->action_frame.da.octet,
-		sizeof(cfg->afx_hdl->tx_dst_addr.octet));
-
-	/* save af_params for rx process */
-	cfg->afx_hdl->pending_tx_act_frm = af_params;
-
-	if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
-		WL_DBG(("Set GAS action frame config.\n"));
-		config_af_params.search_channel = false;
-		config_af_params.max_tx_retry = 1;
-	}
-
-	/* search peer's channel */
-	if (config_af_params.search_channel) {
-		/* initialize afx_hdl */
-		if ((cfg->afx_hdl->bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-			WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-			goto exit;
-		}
-		cfg->afx_hdl->dev = dev;
-		cfg->afx_hdl->retry = 0;
-		cfg->afx_hdl->peer_chan = WL_INVALID;
-
-		if (wl_cfg80211_af_searching_channel(cfg, dev) == WL_INVALID) {
-			WL_ERR(("couldn't find peer's channel.\n"));
-			wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
-				af_params->channel);
-			goto exit;
-		}
-
-		wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
-		/*
-		 * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
-		 * but after the check of piggyback algorithm.
-		 * To take care of current piggback algo, lets abort the scan here itself.
-		 */
-		wl_notify_escan_complete(cfg, dev, true, true);
-		/* Suspend P2P discovery's search-listen to prevent it from
-		 * starting a scan or changing the channel.
-		 */
-		if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
-			WL_ERR(("Can not disable discovery mode\n"));
-			goto exit;
-		}
-
-		/* update channel */
-		af_params->channel = cfg->afx_hdl->peer_chan;
-	}
-
-#ifdef VSDB
-	off_chan_started_jiffies = jiffies;
-#endif /* VSDB */
-
-	wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
-
-	wl_cfgp2p_need_wait_actfrmae(cfg, action_frame->data, action_frame->len, true);
-
-	dwell_jiffies = jiffies;
-	/* Now send a tx action frame */
-	ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ? false : true;
-	dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
-
-	/* if failed, retry it. tx_retry_max value is configure by .... */
-	while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry) &&
-			!dwell_overflow) {
-#ifdef VSDB
-		if (af_params->channel) {
-			if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
-				OFF_CHAN_TIME_THRESHOLD_MS) {
-				WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
-				off_chan_started_jiffies = jiffies;
-			} else
-				OSL_SLEEP(AF_RETRY_DELAY_TIME);
-		}
-#endif /* VSDB */
-		ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ?
-			false : true;
-		dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
-	}
-
-	if (ack == false) {
-		WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
-	}
-	WL_DBG(("Complete to send action frame\n"));
-exit:
-	/* Clear SENDING_ACT_FRM after all sending af is done */
-	wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
-
-#ifdef WL_CFG80211_SYNC_GON
-	/* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
-	 * if we coundn't get the next action response frame and dongle does not keep
-	 * the dwell time, go to listen state again to get next action response frame.
-	 */
-	if (ack && config_af_params.extra_listen &&
-		wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM) &&
-		cfg->af_sent_channel == cfg->afx_hdl->my_listen_chan) {
-		s32 extar_listen_time;
-
-		extar_listen_time = af_params->dwell_time -
-			jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies);
-
-		if (extar_listen_time > 50) {
-			wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
-			WL_DBG(("Wait more time! actual af time:%d,"
-				"calculated extar listen:%d\n",
-				af_params->dwell_time, extar_listen_time));
-			if (wl_cfgp2p_discover_listen(cfg, cfg->af_sent_channel,
-				extar_listen_time + 100) == BCME_OK) {
-				wait_for_completion_timeout(&cfg->wait_next_af,
-					msecs_to_jiffies(extar_listen_time + 100 + 300));
-			}
-			wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
-		}
-	}
-#endif /* WL_CFG80211_SYNC_GON */
-	wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
-
-	if (cfg->afx_hdl->pending_tx_act_frm)
-		cfg->afx_hdl->pending_tx_act_frm = NULL;
-
-	WL_INFORM(("-- sending Action Frame is %s, listen chan: %d\n",
-		(ack) ? "Succeeded!!":"Failed!!", cfg->afx_hdl->my_listen_chan));
-
-
-	/* if all done, turn mpc on again */
-	if (config_af_params.mpc_onoff == 1) {
-		wldev_iovar_setint(dev, "mpc", 1);
-	}
-
-	return ack;
-}
-
-#define MAX_NUM_OF_ASSOCIATED_DEV       64
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
-static s32
-wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
-	struct cfg80211_mgmt_tx_params *params, u64 *cookie)
-#else
-static s32
-wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
-	struct ieee80211_channel *channel, bool offchan,
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
-	enum nl80211_channel_type channel_type,
-	bool channel_type_valid,
-#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0) */
-	unsigned int wait, const u8* buf, size_t len,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
-	bool no_cck,
-#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
-	bool dont_wait_for_ack,
-#endif
-	u64 *cookie)
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
-{
-	wl_action_frame_t *action_frame;
-	wl_af_params_t *af_params;
-	scb_val_t scb_val;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
-	struct ieee80211_channel *channel = params->chan;
-	const u8 *buf = params->buf;
-	size_t len = params->len;
-#endif
-	const struct ieee80211_mgmt *mgmt;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *dev = NULL;
-	s32 err = BCME_OK;
-	s32 bssidx = 0;
-	u32 id;
-	bool ack = false;
-	s8 eabuf[ETHER_ADDR_STR_LEN];
-
-	WL_DBG(("Enter \n"));
-
-	dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	if (!dev) {
-		WL_ERR(("dev is NULL\n"));
-		return -EINVAL;
-	}
-
-	/* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE)	*/
-	if (discover_cfgdev(cfgdev, cfg)) {
-		if (!cfg->p2p_supported || !cfg->p2p) {
-			WL_ERR(("P2P doesn't setup completed yet\n"));
-			return -EINVAL;
-		}
-		bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-	}
-	else {
-		if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
-			WL_ERR(("Find p2p index failed\n"));
-			return BCME_ERROR;
-		}
-	}
-
-	WL_DBG(("TX target bssidx=%d\n", bssidx));
-
-	if (p2p_is_on(cfg)) {
-		/* Suspend P2P discovery search-listen to prevent it from changing the
-		 * channel.
-		 */
-		if ((err = wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
-			WL_ERR(("Can not disable discovery mode\n"));
-			return -EFAULT;
-		}
-	}
-	*cookie = 0;
-	id = cfg->send_action_id++;
-	if (id == 0)
-		id = cfg->send_action_id++;
-	*cookie = id;
-	mgmt = (const struct ieee80211_mgmt *)buf;
-	if (ieee80211_is_mgmt(mgmt->frame_control)) {
-		if (ieee80211_is_probe_resp(mgmt->frame_control)) {
-			s32 ie_offset =  DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
-			s32 ie_len = len - ie_offset;
-			if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) {
-				bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-			}
-			wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
-				VNDR_IE_PRBRSP_FLAG, (const u8 *)(buf + ie_offset), ie_len);
-			cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
-#if defined(P2P_IE_MISSING_FIX)
-			if (!cfg->p2p_prb_noti) {
-				cfg->p2p_prb_noti = true;
-				WL_DBG(("%s: TX 802_1X Probe Response first time.\n",
-					__FUNCTION__));
-			}
-#endif
-			goto exit;
-		} else if (ieee80211_is_disassoc(mgmt->frame_control) ||
-			ieee80211_is_deauth(mgmt->frame_control)) {
-			char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
-				sizeof(struct ether_addr) + sizeof(uint)] = {0};
-			int num_associated = 0;
-			struct maclist *assoc_maclist = (struct maclist *)mac_buf;
-			if (!bcmp((const uint8 *)BSSID_BROADCAST,
-				(const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
-				assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
-				err = wldev_ioctl(dev, WLC_GET_ASSOCLIST,
-					assoc_maclist, sizeof(mac_buf), false);
-				if (err < 0)
-					WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
-				else
-					num_associated = assoc_maclist->count;
-			}
-			memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
-			scb_val.val = mgmt->u.disassoc.reason_code;
-			err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
-				sizeof(scb_val_t), true);
-			if (err < 0)
-				WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
-			WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
-				bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
-				scb_val.val));
-
-			if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
-				wl_delay(400);
-
-			cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
-			goto exit;
-
-		} else if (ieee80211_is_action(mgmt->frame_control)) {
-			/* Abort the dwell time of any previous off-channel
-			* action frame that may be still in effect.  Sending
-			* off-channel action frames relies on the driver's
-			* scan engine.  If a previous off-channel action frame
-			* tx is still in progress (including the dwell time),
-			* then this new action frame will not be sent out.
-			*/
-/* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
- * And previous off-channel action frame must be ended before new af tx.
- */
-#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-			wl_notify_escan_complete(cfg, dev, true, true);
-#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-		}
-
-	} else {
-		WL_ERR(("Driver only allows MGMT packet type\n"));
-		goto exit;
-	}
-
-	af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
-
-	if (af_params == NULL)
-	{
-		WL_ERR(("unable to allocate frame\n"));
-		return -ENOMEM;
-	}
-
-	action_frame = &af_params->action_frame;
-
-	/* Add the packet Id */
-	action_frame->packetId = *cookie;
-	WL_DBG(("action frame %d\n", action_frame->packetId));
-	/* Add BSSID */
-	memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
-	memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
-
-	/* Add the length exepted for 802.11 header  */
-	action_frame->len = len - DOT11_MGMT_HDR_LEN;
-	WL_DBG(("action_frame->len: %d\n", action_frame->len));
-
-	/* Add the channel */
-	af_params->channel =
-		ieee80211_frequency_to_channel(channel->center_freq);
-	/* Save listen_chan for searching common channel */
-	cfg->afx_hdl->peer_listen_chan = af_params->channel;
-	WL_DBG(("channel from upper layer %d\n", cfg->afx_hdl->peer_listen_chan));
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
-	af_params->dwell_time = params->wait;
-#else
-	af_params->dwell_time = wait;
-#endif
-
-	memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
-
-	ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
-		action_frame, action_frame->len, bssidx);
-	cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
-
-	kfree(af_params);
-exit:
-	return err;
-}
-
-
-static void
-wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
-	u16 frame_type, bool reg)
-{
-
-	WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg));
-
-	if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
-		return;
-
-	return;
-}
-
-
-static s32
-wl_cfg80211_change_bss(struct wiphy *wiphy,
-	struct net_device *dev,
-	struct bss_parameters *params)
-{
-	s32 err = 0;
-	s32 ap_isolate = 0;
-
-	if (params->use_cts_prot >= 0) {
-	}
-
-	if (params->use_short_preamble >= 0) {
-	}
-
-	if (params->use_short_slot_time >= 0) {
-	}
-
-	if (params->basic_rates) {
-	}
-
-	if (params->ap_isolate >= 0) {
-		ap_isolate = params->ap_isolate;
-		err = wldev_iovar_setint(dev, "ap_isolate", ap_isolate);
-		if (unlikely(err))
-		{
-			WL_ERR(("set ap_isolate Error (%d)\n", err));
-		}
-	}
-
-	if (params->ht_opmode >= 0) {
-	}
-
-
-	return 0;
-}
-
-static s32
-wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
-	struct ieee80211_channel *chan,
-	enum nl80211_channel_type channel_type)
-{
-	s32 _chan;
-	chanspec_t chspec = 0;
-	chanspec_t fw_chspec = 0;
-	u32 bw = WL_CHANSPEC_BW_20;
-#ifdef WL11ULB
-	u32 ulb_bw = wl_cfg80211_get_ulb_bw(dev->ieee80211_ptr);
-#endif /* WL11ULB */
-
-	s32 err = BCME_OK;
-	s32 bw_cap = 0;
-	struct {
-		u32 band;
-		u32 bw_cap;
-	} param = {0, 0};
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-#ifdef CUSTOM_SET_CPUCORE
-	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
-#endif /* CUSTOM_SET_CPUCORE */
-
-	dev = ndev_to_wlc_ndev(dev, cfg);
-	_chan = ieee80211_frequency_to_channel(chan->center_freq);
-	WL_ERR(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
-		dev->ifindex, channel_type, _chan));
-
-
-#ifdef WL11ULB
-	if (ulb_bw) {
-		WL_DBG(("[ULB] setting AP/GO BW to ulb_bw 0x%x \n", ulb_bw));
-		bw = wl_cfg80211_ulbbw_to_ulbchspec(ulb_bw);
-		goto set_channel;
-	}
-#endif /* WL11ULB */
-	if (chan->band == IEEE80211_BAND_5GHZ) {
-		param.band = WLC_BAND_5G;
-		err = wldev_iovar_getbuf(dev, "bw_cap", &param, sizeof(param),
-			cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
-		if (err) {
-			if (err != BCME_UNSUPPORTED) {
-				WL_ERR(("bw_cap failed, %d\n", err));
-				return err;
-			} else {
-				err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
-				if (err) {
-					WL_ERR(("error get mimo_bw_cap (%d)\n", err));
-				}
-				if (bw_cap != WLC_N_BW_20ALL)
-					bw = WL_CHANSPEC_BW_40;
-			}
-		} else {
-			if (WL_BW_CAP_80MHZ(cfg->ioctl_buf[0]))
-				bw = WL_CHANSPEC_BW_80;
-			else if (WL_BW_CAP_40MHZ(cfg->ioctl_buf[0]))
-				bw = WL_CHANSPEC_BW_40;
-			else
-				bw = WL_CHANSPEC_BW_20;
-
-		}
-
-	} else if (chan->band == IEEE80211_BAND_2GHZ)
-		bw = WL_CHANSPEC_BW_20;
-set_channel:
-	chspec = wf_channel2chspec(_chan, bw);
-	if (wf_chspec_valid(chspec)) {
-		fw_chspec = wl_chspec_host_to_driver(chspec);
-		if (fw_chspec != INVCHANSPEC) {
-			if ((err = wldev_iovar_setint(dev, "chanspec",
-				fw_chspec)) == BCME_BADCHAN) {
-				if (bw == WL_CHANSPEC_BW_80)
-					goto change_bw;
-				err = wldev_ioctl(dev, WLC_SET_CHANNEL,
-					&_chan, sizeof(_chan), true);
-				if (err < 0) {
-					WL_ERR(("WLC_SET_CHANNEL error %d"
-					"chip may not be supporting this channel\n", err));
-				}
-			} else if (err) {
-				WL_ERR(("failed to set chanspec error %d\n", err));
-			}
-		} else {
-			WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
-			err = BCME_ERROR;
-		}
-	} else {
-change_bw:
-		if (bw == WL_CHANSPEC_BW_80)
-			bw = WL_CHANSPEC_BW_40;
-		else if (bw == WL_CHANSPEC_BW_40)
-			bw = WL_CHANSPEC_BW_20;
-		else
-			bw = 0;
-		if (bw)
-			goto set_channel;
-		WL_ERR(("Invalid chanspec 0x%x\n", chspec));
-		err = BCME_ERROR;
-	}
-#ifdef CUSTOM_SET_CPUCORE
-	if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
-		WL_DBG(("SoftAP mode do not need to set cpucore\n"));
-	} else if (chspec & WL_CHANSPEC_BW_80) {
-		/* SoftAp only mode do not need to set cpucore */
-		if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) &&
-			dev != bcmcfg_to_prmry_ndev(cfg)) {
-			/* Soft AP on virtual Iface (AP+STA case) */
-			dhd->chan_isvht80 |= DHD_FLAG_HOSTAP_MODE;
-			dhd_set_cpucore(dhd, TRUE);
-		} else if (is_p2p_group_iface(dev->ieee80211_ptr)) {
-			/* If P2P IF is vht80 */
-			dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE;
-			dhd_set_cpucore(dhd, TRUE);
-		}
-	}
-#endif /* CUSTOM_SET_CPUCORE */
-	if (!err && (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) {
-		/* Update AP/GO operating channel */
-		cfg->ap_oper_channel = _chan;
-	}
-	return err;
-}
-
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-struct net_device *
-wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg)
-{
-	struct net_info *_net_info, *next;
-	list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
-		if (_net_info->ndev &&
-			test_bit(WL_STATUS_REMAINING_ON_CHANNEL, &_net_info->sme_state))
-			return _net_info->ndev;
-	}
-	return NULL;
-}
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-
-static s32
-wl_validate_opensecurity(struct net_device *dev, s32 bssidx, bool privacy)
-{
-	s32 err = BCME_OK;
-	u32 wpa_val;
-	s32 wsec = 0;
-
-	/* set auth */
-	err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
-	if (err < 0) {
-		WL_ERR(("auth error %d\n", err));
-		return BCME_ERROR;
-	}
-
-	if (privacy) {
-		/* If privacy bit is set in open mode, then WEP would be enabled */
-		wsec = WEP_ENABLED;
-		WL_DBG(("Setting wsec to %d for WEP \n", wsec));
-	}
-
-	/* set wsec */
-	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
-	if (err < 0) {
-		WL_ERR(("wsec error %d\n", err));
-		return BCME_ERROR;
-	}
-
-	/* set upper-layer auth */
-	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC)
-		wpa_val = WPA_AUTH_NONE;
-	else
-		wpa_val = WPA_AUTH_DISABLED;
-	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_val, bssidx);
-	if (err < 0) {
-		WL_ERR(("wpa_auth error %d\n", err));
-		return BCME_ERROR;
-	}
-
-	return 0;
-}
-
-static s32
-wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
-{
-	s32 len = 0;
-	s32 err = BCME_OK;
-	u16 auth = 0; /* d11 open authentication */
-	u32 wsec;
-	u32 pval = 0;
-	u32 gval = 0;
-	u32 wpa_auth = 0;
-	wpa_suite_mcast_t *mcast;
-	wpa_suite_ucast_t *ucast;
-	wpa_suite_auth_key_mgmt_t *mgmt;
-	wpa_pmkid_list_t *pmkid;
-	int cnt = 0;
-
-	u16 suite_count;
-	u8 rsn_cap[2];
-	u32 wme_bss_disable;
-
-	if (wpa2ie == NULL)
-		goto exit;
-
-	WL_DBG(("Enter \n"));
-	len =  wpa2ie->len - WPA2_VERSION_LEN;
-	/* check the mcast cipher */
-	mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
-	switch (mcast->type) {
-		case WPA_CIPHER_NONE:
-			gval = 0;
-			break;
-		case WPA_CIPHER_WEP_40:
-		case WPA_CIPHER_WEP_104:
-			gval = WEP_ENABLED;
-			break;
-		case WPA_CIPHER_TKIP:
-			gval = TKIP_ENABLED;
-			break;
-		case WPA_CIPHER_AES_CCM:
-			gval = AES_ENABLED;
-			break;
-		default:
-			WL_ERR(("No Security Info\n"));
-			break;
-	}
-	if ((len -= WPA_SUITE_LEN) <= 0)
-		return BCME_BADLEN;
-
-	/* check the unicast cipher */
-	ucast = (wpa_suite_ucast_t *)&mcast[1];
-	suite_count = ltoh16_ua(&ucast->count);
-	switch (ucast->list[0].type) {
-		case WPA_CIPHER_NONE:
-			pval = 0;
-			break;
-		case WPA_CIPHER_WEP_40:
-		case WPA_CIPHER_WEP_104:
-			pval = WEP_ENABLED;
-			break;
-		case WPA_CIPHER_TKIP:
-			pval = TKIP_ENABLED;
-			break;
-		case WPA_CIPHER_AES_CCM:
-			pval = AES_ENABLED;
-			break;
-		default:
-			WL_ERR(("No Security Info\n"));
-	}
-	if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
-		return BCME_BADLEN;
-
-	/* FOR WPS , set SEC_OW_ENABLED */
-	wsec = (pval | gval | SES_OW_ENABLED);
-	/* check the AKM */
-	mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
-	suite_count = cnt = ltoh16_ua(&mgmt->count);
-	while (cnt--) {
-		switch (mgmt->list[cnt].type) {
-		case RSN_AKM_NONE:
-				wpa_auth |= WPA_AUTH_NONE;
-			break;
-		case RSN_AKM_UNSPECIFIED:
-				wpa_auth |= WPA2_AUTH_UNSPECIFIED;
-			break;
-		case RSN_AKM_PSK:
-				wpa_auth |= WPA2_AUTH_PSK;
-				break;
-		default:
-			WL_ERR(("No Key Mgmt Info\n"));
-		}
-	}
-
-	if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
-		rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
-		rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
-
-		if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
-			wme_bss_disable = 0;
-		} else {
-			wme_bss_disable = 1;
-		}
-
-
-		/* set wme_bss_disable to sync RSN Capabilities */
-		err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
-		if (err < 0) {
-			WL_ERR(("wme_bss_disable error %d\n", err));
-			return BCME_ERROR;
-		}
-	} else {
-		WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
-	}
-
-	len -= RSN_CAP_LEN;
-	if (len >= WPA2_PMKID_COUNT_LEN) {
-		pmkid = (wpa_pmkid_list_t *)((u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN);
-		cnt = ltoh16_ua(&pmkid->count);
-		if (cnt != 0) {
-			WL_ERR(("AP has non-zero PMKID count. Wrong!\n"));
-			return BCME_ERROR;
-		}
-		/* since PMKID cnt is known to be 0 for AP, */
-		/* so don't bother to send down this info to firmware */
-	}
-
-
-	/* set auth */
-	err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
-	if (err < 0) {
-		WL_ERR(("auth error %d\n", err));
-		return BCME_ERROR;
-	}
-
-	/* set wsec */
-	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
-	if (err < 0) {
-		WL_ERR(("wsec error %d\n", err));
-		return BCME_ERROR;
-	}
-
-
-	/* set upper-layer auth */
-	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
-	if (err < 0) {
-		WL_ERR(("wpa_auth error %d\n", err));
-		return BCME_ERROR;
-	}
-exit:
-	return 0;
-}
-
-static s32
-wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
-{
-	wpa_suite_mcast_t *mcast;
-	wpa_suite_ucast_t *ucast;
-	wpa_suite_auth_key_mgmt_t *mgmt;
-	u16 auth = 0; /* d11 open authentication */
-	u16 count;
-	s32 err = BCME_OK;
-	s32 len = 0;
-	u32 i;
-	u32 wsec;
-	u32 pval = 0;
-	u32 gval = 0;
-	u32 wpa_auth = 0;
-	u32 tmp = 0;
-
-	if (wpaie == NULL)
-		goto exit;
-	WL_DBG(("Enter \n"));
-	len = wpaie->length;    /* value length */
-	len -= WPA_IE_TAG_FIXED_LEN;
-	/* check for multicast cipher suite */
-	if (len < WPA_SUITE_LEN) {
-		WL_INFORM(("no multicast cipher suite\n"));
-		goto exit;
-	}
-
-	/* pick up multicast cipher */
-	mcast = (wpa_suite_mcast_t *)&wpaie[1];
-	len -= WPA_SUITE_LEN;
-	if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
-		if (IS_WPA_CIPHER(mcast->type)) {
-			tmp = 0;
-			switch (mcast->type) {
-				case WPA_CIPHER_NONE:
-					tmp = 0;
-					break;
-				case WPA_CIPHER_WEP_40:
-				case WPA_CIPHER_WEP_104:
-					tmp = WEP_ENABLED;
-					break;
-				case WPA_CIPHER_TKIP:
-					tmp = TKIP_ENABLED;
-					break;
-				case WPA_CIPHER_AES_CCM:
-					tmp = AES_ENABLED;
-					break;
-				default:
-					WL_ERR(("No Security Info\n"));
-			}
-			gval |= tmp;
-		}
-	}
-	/* Check for unicast suite(s) */
-	if (len < WPA_IE_SUITE_COUNT_LEN) {
-		WL_INFORM(("no unicast suite\n"));
-		goto exit;
-	}
-	/* walk thru unicast cipher list and pick up what we recognize */
-	ucast = (wpa_suite_ucast_t *)&mcast[1];
-	count = ltoh16_ua(&ucast->count);
-	len -= WPA_IE_SUITE_COUNT_LEN;
-	for (i = 0; i < count && len >= WPA_SUITE_LEN;
-		i++, len -= WPA_SUITE_LEN) {
-		if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
-			if (IS_WPA_CIPHER(ucast->list[i].type)) {
-				tmp = 0;
-				switch (ucast->list[i].type) {
-					case WPA_CIPHER_NONE:
-						tmp = 0;
-						break;
-					case WPA_CIPHER_WEP_40:
-					case WPA_CIPHER_WEP_104:
-						tmp = WEP_ENABLED;
-						break;
-					case WPA_CIPHER_TKIP:
-						tmp = TKIP_ENABLED;
-						break;
-					case WPA_CIPHER_AES_CCM:
-						tmp = AES_ENABLED;
-						break;
-					default:
-						WL_ERR(("No Security Info\n"));
-				}
-				pval |= tmp;
-			}
-		}
-	}
-	len -= (count - i) * WPA_SUITE_LEN;
-	/* Check for auth key management suite(s) */
-	if (len < WPA_IE_SUITE_COUNT_LEN) {
-		WL_INFORM((" no auth key mgmt suite\n"));
-		goto exit;
-	}
-	/* walk thru auth management suite list and pick up what we recognize */
-	mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
-	count = ltoh16_ua(&mgmt->count);
-	len -= WPA_IE_SUITE_COUNT_LEN;
-	for (i = 0; i < count && len >= WPA_SUITE_LEN;
-		i++, len -= WPA_SUITE_LEN) {
-		if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
-			if (IS_WPA_AKM(mgmt->list[i].type)) {
-				tmp = 0;
-				switch (mgmt->list[i].type) {
-					case RSN_AKM_NONE:
-						tmp = WPA_AUTH_NONE;
-						break;
-					case RSN_AKM_UNSPECIFIED:
-						tmp = WPA_AUTH_UNSPECIFIED;
-						break;
-					case RSN_AKM_PSK:
-						tmp = WPA_AUTH_PSK;
-						break;
-					default:
-						WL_ERR(("No Key Mgmt Info\n"));
-				}
-				wpa_auth |= tmp;
-			}
-		}
-
-	}
-	/* FOR WPS , set SEC_OW_ENABLED */
-	wsec = (pval | gval | SES_OW_ENABLED);
-	/* set auth */
-	err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
-	if (err < 0) {
-		WL_ERR(("auth error %d\n", err));
-		return BCME_ERROR;
-	}
-	/* set wsec */
-	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
-	if (err < 0) {
-		WL_ERR(("wsec error %d\n", err));
-		return BCME_ERROR;
-	}
-	/* set upper-layer auth */
-	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
-	if (err < 0) {
-		WL_ERR(("wpa_auth error %d\n", err));
-		return BCME_ERROR;
-	}
-exit:
-	return 0;
-}
-
-
-static s32
-wl_cfg80211_bcn_validate_sec(
-	struct net_device *dev,
-	struct parsed_ies *ies,
-	u32 dev_role,
-	s32 bssidx,
-	bool privacy)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
-
-	if (!bss) {
-		WL_ERR(("cfgbss is NULL \n"));
-		return BCME_ERROR;
-	}
-
-	if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
-		/* For P2P GO, the sec type is WPA2-PSK */
-		WL_DBG(("P2P GO: validating wpa2_ie"));
-		if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0)
-			return BCME_ERROR;
-
-	} else if (dev_role == NL80211_IFTYPE_AP) {
-
-		WL_DBG(("SoftAP: validating security"));
-		/* If wpa2_ie or wpa_ie is present validate it */
-
-		if ((ies->wpa2_ie || ies->wpa_ie) &&
-			((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
-			wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
-			bss->security_mode = false;
-			return BCME_ERROR;
-		}
-
-		bss->security_mode = true;
-		if (bss->rsn_ie) {
-			kfree(bss->rsn_ie);
-			bss->rsn_ie = NULL;
-		}
-		if (bss->wpa_ie) {
-			kfree(bss->wpa_ie);
-			bss->wpa_ie = NULL;
-		}
-		if (bss->wps_ie) {
-			kfree(bss->wps_ie);
-			bss->wps_ie = NULL;
-		}
-		if (ies->wpa_ie != NULL) {
-			/* WPAIE */
-			bss->rsn_ie = NULL;
-			bss->wpa_ie = kmemdup(ies->wpa_ie,
-				ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
-				GFP_KERNEL);
-		} else if (ies->wpa2_ie != NULL) {
-			/* RSNIE */
-			bss->wpa_ie = NULL;
-			bss->rsn_ie = kmemdup(ies->wpa2_ie,
-				ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
-				GFP_KERNEL);
-		}
-		if (!ies->wpa2_ie && !ies->wpa_ie) {
-			wl_validate_opensecurity(dev, bssidx, privacy);
-			bss->security_mode = false;
-		}
-
-		if (ies->wps_ie) {
-			bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
-		}
-	}
-
-	return 0;
-
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
-static s32 wl_cfg80211_bcn_set_params(
-	struct cfg80211_ap_settings *info,
-	struct net_device *dev,
-	u32 dev_role, s32 bssidx)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	s32 err = BCME_OK;
-
-	WL_DBG(("interval (%d) \ndtim_period (%d) \n",
-		info->beacon_interval, info->dtim_period));
-
-	if (info->beacon_interval) {
-		if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
-			&info->beacon_interval, sizeof(s32), true)) < 0) {
-			WL_ERR(("Beacon Interval Set Error, %d\n", err));
-			return err;
-		}
-	}
-
-	if (info->dtim_period) {
-		if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
-			&info->dtim_period, sizeof(s32), true)) < 0) {
-			WL_ERR(("DTIM Interval Set Error, %d\n", err));
-			return err;
-		}
-	}
-
-	if ((info->ssid) && (info->ssid_len > 0) &&
-		(info->ssid_len <= 32)) {
-		WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
-		if (dev_role == NL80211_IFTYPE_AP) {
-			/* Store the hostapd SSID */
-			memset(cfg->hostapd_ssid.SSID, 0x00, 32);
-			memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
-			cfg->hostapd_ssid.SSID_len = info->ssid_len;
-		} else {
-				/* P2P GO */
-			memset(cfg->p2p->ssid.SSID, 0x00, 32);
-			memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
-			cfg->p2p->ssid.SSID_len = info->ssid_len;
-		}
-	}
-
-	if (info->hidden_ssid) {
-		if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
-			WL_ERR(("failed to set hidden : %d\n", err));
-		WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
-	}
-
-	return err;
-}
-#endif 
-
-static s32
-wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
-{
-	s32 err = BCME_OK;
-
-	memset(ies, 0, sizeof(struct parsed_ies));
-
-	/* find the WPSIE */
-	if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
-		WL_DBG(("WPSIE in beacon \n"));
-		ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
-	} else {
-		WL_ERR(("No WPSIE in beacon \n"));
-	}
-
-	/* find the RSN_IE */
-	if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
-		DOT11_MNG_RSN_ID)) != NULL) {
-		WL_DBG((" WPA2 IE found\n"));
-		ies->wpa2_ie_len = ies->wpa2_ie->len;
-	}
-
-	/* find the WPA_IE */
-	if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
-		WL_DBG((" WPA found\n"));
-		ies->wpa_ie_len = ies->wpa_ie->length;
-	}
-
-	return err;
-
-}
-
-#define MAX_AP_LINK_WAIT_TIME   10000
-static s32
-wl_cfg80211_bcn_bringup_ap(
-	struct net_device *dev,
-	struct parsed_ies *ies,
-	u32 dev_role, s32 bssidx)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wl_join_params join_params;
-	struct wiphy *wiphy;
-	bool is_bssup = false;
-	s32 infra = 1;
-	s32 join_params_size = 0;
-	s32 ap = 1;
-	s32 pm;
-	s32 wsec;
-#ifdef SOFTAP_UAPSD_OFF
-	uint32 wme_apsd = 0;
-#endif /* SOFTAP_UAPSD_OFF */
-	s32 err = BCME_OK;
-	s32 is_rsdb_supported = BCME_ERROR;
-	u32 timeout;
-#if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
-	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
-#endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
-
-	is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
-	if (is_rsdb_supported < 0)
-		return (-ENODEV);
-
-	WL_DBG(("Enter dev_role:%d bssidx:%d\n", dev_role, bssidx));
-
-	/* Common code for SoftAP and P2P GO */
-	wiphy = bcmcfg_to_wiphy(cfg);
-	if (wl_check_dongle_idle(wiphy) != TRUE) {
-		WL_ERR(("FW is busy to add interface"));
-		return -EINVAL;
-	}
-	wldev_iovar_setint(dev, "mpc", 0);
-
-	wl_clr_drv_status(cfg, AP_CREATED, dev);
-
-	if (dev_role == NL80211_IFTYPE_P2P_GO) {
-		is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
-		if (!is_bssup && (ies->wpa2_ie != NULL)) {
-
-			err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
-			if (err < 0) {
-				WL_ERR(("SET INFRA error %d\n", err));
-				goto exit;
-			}
-
-			err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &cfg->p2p->ssid,
-				sizeof(cfg->p2p->ssid), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
-				bssidx, &cfg->ioctl_buf_sync);
-			if (err < 0) {
-				WL_ERR(("GO SSID setting error %d\n", err));
-				goto exit;
-			}
-
-			/* Do abort scan before creating GO */
-			wl_cfg80211_scan_abort(cfg);
-
-			if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 1)) < 0) {
-				WL_ERR(("GO Bring up error %d\n", err));
-				goto exit;
-			}
-		} else
-			WL_DBG(("Bss is already up\n"));
-	} else if ((dev_role == NL80211_IFTYPE_AP) &&
-		(wl_get_drv_status(cfg, AP_CREATING, dev))) {
-
-		/* Device role SoftAP */
-		WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx, dev_role));
-
-		/* Clear the status bit after use */
-		wl_clr_drv_status(cfg, AP_CREATING, dev);
-
-		/* AP on primary Interface */
-		if (bssidx == 0) {
-			if (is_rsdb_supported) {
-				if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx,
-					NL80211_IFTYPE_AP, 0, NULL)) < 0) {
-					WL_ERR(("wl add_del_bss returned error:%d\n", err));
-					goto exit;
-				}
-			} else if (is_rsdb_supported == 0) {
-			/* AP mode switch not supported. Try setting up AP explicitly */
-				err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
-				if (err < 0) {
-					WL_ERR(("WLC_DOWN error %d\n", err));
-					goto exit;
-				}
-				err = wldev_iovar_setint(dev, "apsta", 0);
-				if (err < 0) {
-					WL_ERR(("wl apsta 0 error %d\n", err));
-					goto exit;
-				}
-
-				if ((err = wldev_ioctl(dev,
-					WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
-					WL_ERR(("setting AP mode failed %d \n", err));
-					goto exit;
-				}
-
-			}
-
-			pm = 0;
-			if ((err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true)) != 0) {
-				WL_ERR(("wl PM 0 returned error:%d\n", err));
-				goto exit;
-			}
-
-			err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
-			if (err < 0) {
-				WL_ERR(("SET INFRA error %d\n", err));
-				goto exit;
-			}
-		} else if (cfg->cfgdev_bssidx && (bssidx == cfg->cfgdev_bssidx)) {
-
-			WL_DBG(("Bringup SoftAP on virtual Interface bssidx:%d \n", bssidx));
-
-			if ((err = wl_cfg80211_add_del_bss(cfg, dev,
-				bssidx, NL80211_IFTYPE_AP, 0, NULL)) < 0) {
-				WL_ERR(("wl bss ap returned error:%d\n", err));
-				goto exit;
-			}
-
-		}
-
-#ifdef SOFTAP_UAPSD_OFF
-		err = wldev_iovar_setbuf_bsscfg(dev, "wme_apsd", &wme_apsd, sizeof(wme_apsd),
-			cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
-		if (err < 0) {
-			WL_ERR(("failed to disable uapsd, error=%d\n", err));
-		}
-#endif /* SOFTAP_UAPSD_OFF */
-
-		err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
-		if (unlikely(err)) {
-			WL_ERR(("WLC_UP error (%d)\n", err));
-			goto exit;
-		}
-
-		err = wldev_iovar_getint(dev, "wsec", (s32 *)&wsec);
-		if (unlikely(err)) {
-			WL_ERR(("Could not get wsec %d\n", err));
-			goto exit;
-		}
-		if ((wsec == WEP_ENABLED) && cfg->wep_key.len) {
-			WL_DBG(("Applying buffered WEP KEY \n"));
-			err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &cfg->wep_key,
-				sizeof(struct wl_wsec_key), cfg->ioctl_buf,
-				WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-			/* clear the key after use */
-			memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
-			if (unlikely(err)) {
-				WL_ERR(("WLC_SET_KEY error (%d)\n", err));
-				goto exit;
-			}
-		}
-
-		memset(&join_params, 0, sizeof(join_params));
-		/* join parameters starts with ssid */
-		join_params_size = sizeof(join_params.ssid);
-		memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
-			cfg->hostapd_ssid.SSID_len);
-		join_params.ssid.SSID_len = htod32(cfg->hostapd_ssid.SSID_len);
-
-		/* create softap */
-		if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
-			join_params_size, true)) != 0) {
-			WL_ERR(("SoftAP/GO set ssid failed! \n"));
-			goto exit;
-		} else {
-			WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
-		}
-
-		if (bssidx != 0) {
-			/* AP on Virtual Interface */
-			if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 1)) < 0) {
-				WL_ERR(("GO Bring up error %d\n", err));
-				goto exit;
-			}
-		}
-
-	}
-	/* Wait for Linkup event to mark successful AP/GO bring up */
-	timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
-		wl_get_drv_status(cfg, AP_CREATED, dev), msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
-	if (timeout <= 0 || !wl_get_drv_status(cfg, AP_CREATED, dev)) {
-		WL_ERR(("Link up didn't come for AP interface. AP/GO creation failed! \n"));
-#if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
-		if (dhdp->memdump_enabled) {
-			dhdp->memdump_type = DUMP_TYPE_AP_LINKUP_FAILURE;
-			dhd_bus_mem_dump(dhdp);
-		}
-#endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
-		err = -ENODEV;
-		goto exit;
-	}
-
-exit:
-	if (cfg->wep_key.len)
-		memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
-	return err;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
-s32
-wl_cfg80211_parse_ap_ies(
-	struct net_device *dev,
-	struct cfg80211_beacon_data *info,
-	struct parsed_ies *ies)
-{
-	struct parsed_ies prb_ies;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-	u8 *vndr = NULL;
-	u32 vndr_ie_len = 0;
-	s32 err = BCME_OK;
-
-	/* Parse Beacon IEs */
-	if (wl_cfg80211_parse_ies((u8 *)info->tail,
-		info->tail_len, ies) < 0) {
-		WL_ERR(("Beacon get IEs failed \n"));
-		err = -EINVAL;
-		goto fail;
-	}
-
-	vndr = (u8 *)info->proberesp_ies;
-	vndr_ie_len = info->proberesp_ies_len;
-
-	if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
-		/* SoftAP mode */
-		struct ieee80211_mgmt *mgmt;
-		mgmt = (struct ieee80211_mgmt *)info->probe_resp;
-		if (mgmt != NULL) {
-			vndr = (u8 *)&mgmt->u.probe_resp.variable;
-			vndr_ie_len = info->probe_resp_len -
-				offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
-		}
-	}
-
-	/* Parse Probe Response IEs */
-	if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
-		WL_ERR(("PROBE RESP get IEs failed \n"));
-		err = -EINVAL;
-	}
-
-fail:
-
-	return err;
-}
-
-s32
-wl_cfg80211_set_ies(
-	struct net_device *dev,
-	struct cfg80211_beacon_data *info,
-	s32 bssidx)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-	u8 *vndr = NULL;
-	u32 vndr_ie_len = 0;
-	s32 err = BCME_OK;
-
-	/* Set Beacon IEs to FW */
-	if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
-		VNDR_IE_BEACON_FLAG, (const u8 *)info->tail,
-		info->tail_len)) < 0) {
-		WL_ERR(("Set Beacon IE Failed \n"));
-	} else {
-		WL_DBG(("Applied Vndr IEs for Beacon \n"));
-	}
-
-	vndr = (u8 *)info->proberesp_ies;
-	vndr_ie_len = info->proberesp_ies_len;
-
-	if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
-		/* SoftAP mode */
-		struct ieee80211_mgmt *mgmt;
-		mgmt = (struct ieee80211_mgmt *)info->probe_resp;
-		if (mgmt != NULL) {
-			vndr = (u8 *)&mgmt->u.probe_resp.variable;
-			vndr_ie_len = info->probe_resp_len -
-				offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
-		}
-	}
-
-	/* Set Probe Response IEs to FW */
-	if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
-		VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
-		WL_ERR(("Set Probe Resp IE Failed \n"));
-	} else {
-		WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
-	}
-
-	return err;
-}
-#endif 
-
-static s32 wl_cfg80211_hostapd_sec(
-	struct net_device *dev,
-	struct parsed_ies *ies,
-	s32 bssidx)
-{
-	bool update_bss = 0;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
-
-	if (!bss) {
-		WL_ERR(("cfgbss is NULL \n"));
-		return -EINVAL;
-	}
-
-	if (ies->wps_ie) {
-		if (bss->wps_ie &&
-			memcmp(bss->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
-			WL_DBG((" WPS IE is changed\n"));
-			kfree(bss->wps_ie);
-			bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
-		} else if (bss->wps_ie == NULL) {
-			WL_DBG((" WPS IE is added\n"));
-			bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
-		}
-
-		if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
-			if (!bss->security_mode) {
-				/* change from open mode to security mode */
-				update_bss = true;
-				if (ies->wpa_ie != NULL) {
-					bss->wpa_ie = kmemdup(ies->wpa_ie,
-					ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
-					GFP_KERNEL);
-				} else {
-					bss->rsn_ie = kmemdup(ies->wpa2_ie,
-					ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
-					GFP_KERNEL);
-				}
-			} else if (bss->wpa_ie) {
-				/* change from WPA2 mode to WPA mode */
-				if (ies->wpa_ie != NULL) {
-					update_bss = true;
-					kfree(bss->rsn_ie);
-					bss->rsn_ie = NULL;
-					bss->wpa_ie = kmemdup(ies->wpa_ie,
-					ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
-					GFP_KERNEL);
-				} else if (memcmp(bss->rsn_ie,
-					ies->wpa2_ie, ies->wpa2_ie->len
-					+ WPA_RSN_IE_TAG_FIXED_LEN)) {
-					update_bss = true;
-					kfree(bss->rsn_ie);
-					bss->rsn_ie = kmemdup(ies->wpa2_ie,
-					ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
-					GFP_KERNEL);
-					bss->wpa_ie = NULL;
-				}
-			}
-			if (update_bss) {
-				bss->security_mode = true;
-				wl_cfgp2p_bss(cfg, dev, bssidx, 0);
-				if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
-					wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
-					return BCME_ERROR;
-				}
-				wl_cfgp2p_bss(cfg, dev, bssidx, 1);
-			}
-		}
-	} else {
-		WL_ERR(("No WPSIE in beacon \n"));
-	}
-	return 0;
-}
-
-#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
-	2, 0))
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
-static s32
-wl_cfg80211_del_station(
-		struct wiphy *wiphy, struct net_device *ndev,
-		struct station_del_parameters *params)
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-static s32
-wl_cfg80211_del_station(
-	struct wiphy *wiphy,
-	struct net_device *ndev,
-	const u8* mac_addr)
-#else
-static s32
-wl_cfg80211_del_station(
-	struct wiphy *wiphy,
-	struct net_device *ndev,
-	u8* mac_addr)
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
-{
-	struct net_device *dev;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	scb_val_t scb_val;
-	s8 eabuf[ETHER_ADDR_STR_LEN];
-	int err;
-	char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
-		sizeof(struct ether_addr) + sizeof(uint)] = {0};
-	struct maclist *assoc_maclist = (struct maclist *)mac_buf;
-	int num_associated = 0;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
-	const u8 *mac_addr = params->mac;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
-
-	WL_DBG(("Entry\n"));
-	if (mac_addr == NULL) {
-		WL_DBG(("mac_addr is NULL ignore it\n"));
-		return 0;
-	}
-
-	dev = ndev_to_wlc_ndev(ndev, cfg);
-
-	if (p2p_is_on(cfg)) {
-		/* Suspend P2P discovery search-listen to prevent it from changing the
-		 * channel.
-		 */
-		if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
-			WL_ERR(("Can not disable discovery mode\n"));
-			return -EFAULT;
-		}
-	}
-
-	assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
-	err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
-		assoc_maclist, sizeof(mac_buf), false);
-	if (err < 0)
-		WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
-	else
-		num_associated = assoc_maclist->count;
-
-	memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
-	scb_val.val = DOT11_RC_DEAUTH_LEAVING;
-	err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
-		sizeof(scb_val_t), true);
-	if (err < 0)
-		WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
-	WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
-		bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
-		scb_val.val));
-
-	if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
-		wl_delay(400);
-
-	return 0;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-static s32
-wl_cfg80211_change_station(
-	struct wiphy *wiphy,
-	struct net_device *dev,
-	const u8 *mac,
-	struct station_parameters *params)
-#else
-static s32
-wl_cfg80211_change_station(
-	struct wiphy *wiphy,
-	struct net_device *dev,
-	u8 *mac,
-	struct station_parameters *params)
-#endif
-{
-	int err;
-#ifdef DHD_LOSSLESS_ROAMING
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-#endif
-
-	WL_DBG(("SCB_AUTHORIZE mac_addr:"MACDBG" sta_flags_mask:0x%x "
-				"sta_flags_set:0x%x iface:%s \n", MAC2STRDBG(mac),
-				params->sta_flags_mask, params->sta_flags_set, dev->name));
-
-	/* Processing only authorize/de-authorize flag for now */
-	if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
-		WL_ERR(("WLC_SCB_AUTHORIZE sta_flags_mask not set \n"));
-		return -ENOTSUPP;
-	}
-
-	if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-		err = wldev_ioctl(dev, WLC_SCB_DEAUTHORIZE, (u8 *)mac, ETH_ALEN, true);
-#else
-		err = wldev_ioctl(dev, WLC_SCB_DEAUTHORIZE, mac, ETH_ALEN, true);
-#endif
-		if (err)
-			WL_ERR(("WLC_SCB_DEAUTHORIZE error (%d)\n", err));
-		return err;
-	}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-	err = wldev_ioctl(dev, WLC_SCB_AUTHORIZE, (u8 *)mac, ETH_ALEN, true);
-#else
-	err = wldev_ioctl(dev, WLC_SCB_AUTHORIZE, mac, ETH_ALEN, true);
-#endif
-	if (err)
-		WL_ERR(("WLC_SCB_AUTHORIZE error (%d)\n", err));
-#ifdef DHD_LOSSLESS_ROAMING
-	wl_del_roam_timeout(cfg);
-#endif
-	return err;
-}
-#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
-
-static s32
-wl_cfg80211_set_scb_timings(
-	struct bcm_cfg80211 *cfg,
-	struct net_device *dev)
-{
-	int err;
-	u32 ps_pretend;
-	wl_scb_probe_t scb_probe;
-
-	bzero(&scb_probe, sizeof(wl_scb_probe_t));
-	scb_probe.scb_timeout = WL_SCB_TIMEOUT;
-	scb_probe.scb_activity_time = WL_SCB_ACTIVITY_TIME;
-	scb_probe.scb_max_probe = WL_SCB_MAX_PROBE;
-	err = wldev_iovar_setbuf(dev, "scb_probe", (void *)&scb_probe,
-		sizeof(wl_scb_probe_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
-		&cfg->ioctl_buf_sync);
-	if (unlikely(err)) {
-		WL_ERR(("set 'scb_probe' failed, error = %d\n", err));
-		return err;
-	}
-
-	ps_pretend = MAX(WL_SCB_MAX_PROBE / 2, WL_MIN_PSPRETEND_THRESHOLD);
-	err = wldev_iovar_setint(dev, "pspretend_threshold", ps_pretend);
-	if (unlikely(err)) {
-		if (err == BCME_UNSUPPORTED) {
-			/* Ignore error if fw doesn't support the iovar */
-			WL_DBG(("wl pspretend_threshold %d set error %d\n",
-				ps_pretend, err));
-		} else {
-			WL_ERR(("wl pspretend_threshold %d set error %d\n",
-				ps_pretend, err));
-			return err;
-		}
-	}
-
-	return 0;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
-static s32
-wl_cfg80211_start_ap(
-	struct wiphy *wiphy,
-	struct net_device *dev,
-	struct cfg80211_ap_settings *info)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	s32 err = BCME_OK;
-	struct parsed_ies ies;
-	s32 bssidx = 0;
-	u32 dev_role = 0;
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-
-	WL_DBG(("Enter \n"));
-
-#if defined(SUPPORT_RANDOM_MAC_SCAN)
-	wl_cfg80211_set_random_mac(dev, FALSE);
-#endif /* SUPPORT_RANDOM_MAC_SCAN */
-
-	if ((dev == bcmcfg_to_prmry_ndev(cfg)) ||
-		(dev == ((struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev)))) {
-		WL_DBG(("Start AP req on iface: %s \n", dev->name));
-		dev_role = NL80211_IFTYPE_AP;
-	}
-#if defined(WL_ENABLE_P2P_IF)
-	else if (dev == cfg->p2p_net) {
-		/* Group Add request on p2p0 */
-		WL_DBG(("Start AP req on P2P iface: GO\n"));
-		dev = bcmcfg_to_prmry_ndev(cfg);
-		dev_role = NL80211_IFTYPE_P2P_GO;
-	}
-#endif /* WL_ENABLE_P2P_IF */
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	if (p2p_is_on(cfg) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) {
-		dev_role = NL80211_IFTYPE_P2P_GO;
-	} else if (dev_role == NL80211_IFTYPE_AP) {
-		dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
-		/*
-		 * Enabling Softap is causing issues with STA NDO operations
-		 * as NDO is not interface specific. So disable NDO while
-		 * Softap is enabled
-		 */
-		err = dhd_ndo_enable(dhd, FALSE);
-		WL_DBG(("%s: Disabling NDO on Hostapd mode %d\n", __FUNCTION__, err));
-		if (err) {
-			/* Non fatal error. */
-			WL_ERR(("%s: Disabling NDO Failed %d\n", __FUNCTION__, err));
-		} else {
-			cfg->revert_ndo_disable = true;
-		}
-
-#ifdef PKT_FILTER_SUPPORT
-		/* Disable packet filter */
-		if (dhd->early_suspended) {
-			WL_ERR(("Disable pkt_filter\n"));
-			dhd_enable_packet_filter(0, dhd);
-		}
-#endif /* PKT_FILTER_SUPPORT */
-#ifdef ARP_OFFLOAD_SUPPORT
-		/* IF SoftAP is enabled, disable arpoe */
-		dhd_arp_offload_set(dhd, 0);
-		dhd_arp_offload_enable(dhd, FALSE);
-#endif /* ARP_OFFLOAD_SUPPORT */
-		if ((dhd->op_mode & DHD_FLAG_STA_MODE) && wl_cfg80211_is_roam_offload()) {
-			WL_ERR(("Cleare roam_offload_bssid_list at STA-SoftAP MODE.\n"));
-			wl_android_set_roam_offload_bssid_list(dev, "0");
-		}
-	} else {
-		/* only AP or GO role need to be handled here. */
-		err = -EINVAL;
-		goto fail;
-	}
-
-	if (!check_dev_role_integrity(cfg, dev_role)) {
-		err = -EINVAL;
-		goto fail;
-	}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
-	if ((err = wl_cfg80211_set_channel(wiphy, dev,
-		dev->ieee80211_ptr->preset_chandef.chan,
-		NL80211_CHAN_HT20) < 0)) {
-		WL_ERR(("Set channel failed \n"));
-		goto fail;
-	}
-#endif 
-
-	if ((err = wl_cfg80211_bcn_set_params(info, dev,
-		dev_role, bssidx)) < 0) {
-		WL_ERR(("Beacon params set failed \n"));
-		goto fail;
-	}
-
-	/* Parse IEs */
-	if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
-		WL_ERR(("Set IEs failed \n"));
-		goto fail;
-	}
-
-	if ((err = wl_cfg80211_bcn_validate_sec(dev, &ies,
-		dev_role, bssidx, info->privacy)) < 0)
-	{
-		WL_ERR(("Beacon set security failed \n"));
-		goto fail;
-	}
-
-	if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
-		dev_role, bssidx)) < 0) {
-		WL_ERR(("Beacon bring up AP/GO failed \n"));
-		goto fail;
-	}
-
-	/* Set GC/STA SCB expiry timings. */
-	if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
-		WL_ERR(("scb setting failed \n"));
-		goto fail;
-	}
-
-	WL_DBG(("** AP/GO Created **\n"));
-
-#ifdef WL_CFG80211_ACL
-	/* Enfoce Admission Control. */
-	if ((err = wl_cfg80211_set_mac_acl(wiphy, dev, info->acl)) < 0) {
-		WL_ERR(("Set ACL failed\n"));
-	}
-#endif /* WL_CFG80211_ACL */
-
-	/* Set IEs to FW */
-	if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
-		WL_ERR(("Set IEs failed \n"));
-
-	/* Enable Probe Req filter, WPS-AP certification 4.2.13 */
-	if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
-		bool pbc = 0;
-		wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
-		if (pbc) {
-			WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
-			wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
-		}
-	}
-
-fail:
-	if (err) {
-		WL_ERR(("ADD/SET beacon failed\n"));
-		wldev_iovar_setint(dev, "mpc", 1);
-		if (dev_role == NL80211_IFTYPE_AP) {
-			dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
-
-#ifdef PKT_FILTER_SUPPORT
-			/* Enable packet filter */
-			if (dhd->early_suspended) {
-				WL_ERR(("Enable pkt_filter\n"));
-				dhd_enable_packet_filter(1, dhd);
-			}
-#endif /* PKT_FILTER_SUPPORT */
-		}
-	}
-
-	return err;
-}
-
-static s32
-wl_cfg80211_stop_ap(
-	struct wiphy *wiphy,
-	struct net_device *dev)
-{
-	int err = 0;
-	u32 dev_role = 0;
-	int infra = 0;
-	int ap = 0;
-	s32 bssidx = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	s32 is_rsdb_supported = BCME_ERROR;
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-
-	WL_DBG(("Enter \n"));
-
-	is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
-	if (is_rsdb_supported < 0)
-		return (-ENODEV);
-
-	wl_clr_drv_status(cfg, AP_CREATING, dev);
-	wl_clr_drv_status(cfg, AP_CREATED, dev);
-	cfg->ap_oper_channel = 0;
-
-	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
-		dev_role = NL80211_IFTYPE_AP;
-		WL_DBG(("stopping AP operation\n"));
-	} else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
-		dev_role = NL80211_IFTYPE_P2P_GO;
-		WL_DBG(("stopping P2P GO operation\n"));
-	} else {
-		WL_ERR(("no AP/P2P GO interface is operational.\n"));
-		return -EINVAL;
-	}
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	if (!check_dev_role_integrity(cfg, dev_role)) {
-		WL_ERR(("role integrity check failed \n"));
-		err = -EINVAL;
-		goto exit;
-	}
-
-	if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 0)) < 0) {
-		WL_ERR(("bss down error %d\n", err));
-	}
-
-	if (dev_role == NL80211_IFTYPE_AP) {
-		if (cfg->revert_ndo_disable == true) {
-			err = dhd_ndo_enable(dhd, TRUE);
-			WL_DBG(("%s: Enabling back NDO on Softap turn off %d\n",
-				__FUNCTION__, err));
-			if (err) {
-				WL_ERR(("%s: Enabling NDO Failed %d\n", __FUNCTION__, err));
-			}
-			cfg->revert_ndo_disable = false;
-		}
-
-#ifdef PKT_FILTER_SUPPORT
-		/* Enable packet filter */
-		if (dhd->early_suspended) {
-			WL_ERR(("Enable pkt_filter\n"));
-			dhd_enable_packet_filter(1, dhd);
-		}
-#endif /* PKT_FILTER_SUPPORT */
-#ifdef ARP_OFFLOAD_SUPPORT
-		/* IF SoftAP is disabled, enable arpoe back for STA mode. */
-		dhd_arp_offload_set(dhd, dhd_arp_mode);
-		dhd_arp_offload_enable(dhd, TRUE);
-#endif /* ARP_OFFLOAD_SUPPORT */
-		/*
-		 * Bring down the AP interface by changing role to STA.
-		 * Don't do a down or "WLC_SET_AP 0" since the shared
-		 * interface may be still running
-		 */
-		if (is_rsdb_supported) {
-			if ((err = wl_cfg80211_add_del_bss(cfg, dev,
-				bssidx, NL80211_IFTYPE_STATION, 0, NULL)) < 0) {
-				if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32),
-					true)) < 0) {
-					WL_ERR(("setting AP mode failed %d \n", err));
-					err = -ENOTSUPP;
-					goto exit;
-				}
-			}
-		} else if (is_rsdb_supported == 0) {
-			err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
-			if (err < 0) {
-				WL_ERR(("SET INFRA error %d\n", err));
-				err = -ENOTSUPP;
-				goto exit;
-			}
-			err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
-			if (unlikely(err)) {
-				WL_ERR(("WLC_UP error (%d)\n", err));
-				err = -EINVAL;
-				goto exit;
-			}
-		}
-
-		/* Turn on the MPC */
-		wldev_iovar_setint(dev, "mpc", 1);
-
-		 wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
-	} else {
-		WL_DBG(("Stopping P2P GO \n"));
-		DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
-			DHD_EVENT_TIMEOUT_MS*3);
-		DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
-	}
-
-exit:
-
-	if (dev_role == NL80211_IFTYPE_AP) {
-		/* clear the AP mode */
-		dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
-	}
-	return err;
-}
-
-static s32
-wl_cfg80211_change_beacon(
-	struct wiphy *wiphy,
-	struct net_device *dev,
-	struct cfg80211_beacon_data *info)
-{
-	s32 err = BCME_OK;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct parsed_ies ies;
-	u32 dev_role = 0;
-	s32 bssidx = 0;
-	bool pbc = 0;
-
-	WL_DBG(("Enter \n"));
-
-	if (dev == bcmcfg_to_prmry_ndev(cfg)) {
-		dev_role = NL80211_IFTYPE_AP;
-	}
-#if defined(WL_ENABLE_P2P_IF)
-	else if (dev == cfg->p2p_net) {
-		/* Group Add request on p2p0 */
-		dev = bcmcfg_to_prmry_ndev(cfg);
-		dev_role = NL80211_IFTYPE_P2P_GO;
-	}
-#endif /* WL_ENABLE_P2P_IF */
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
-		dev_role = NL80211_IFTYPE_P2P_GO;
-	}
-
-	if (!check_dev_role_integrity(cfg, dev_role)) {
-		err = -EINVAL;
-		goto fail;
-	}
-
-	if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
-		WL_ERR(("P2P already down status!\n"));
-		err = BCME_ERROR;
-		goto fail;
-	}
-
-	/* Parse IEs */
-	if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
-		WL_ERR(("Parse IEs failed \n"));
-		goto fail;
-	}
-
-	/* Set IEs to FW */
-	if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
-		WL_ERR(("Set IEs failed \n"));
-		goto fail;
-	}
-
-	if (dev_role == NL80211_IFTYPE_AP) {
-		if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
-			WL_ERR(("Hostapd update sec failed \n"));
-			err = -EINVAL;
-			goto fail;
-		}
-		/* Enable Probe Req filter, WPS-AP certification 4.2.13 */
-		if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
-			wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
-			WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
-			if (pbc)
-				wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
-			else
-				wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
-		}
-	}
-
-fail:
-	return err;
-}
-#else
-static s32
-wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
-	struct beacon_parameters *info)
-{
-	s32 err = BCME_OK;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	s32 ie_offset = 0;
-	s32 bssidx = 0;
-	u32 dev_role = NL80211_IFTYPE_AP;
-	struct parsed_ies ies;
-	bcm_tlv_t *ssid_ie;
-	bool pbc = 0;
-	bool privacy;
-	bool is_bss_up = 0;
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-
-	WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
-		info->interval, info->dtim_period, info->head_len, info->tail_len));
-
-	if (dev == bcmcfg_to_prmry_ndev(cfg)) {
-		dev_role = NL80211_IFTYPE_AP;
-	}
-#if defined(WL_ENABLE_P2P_IF)
-	else if (dev == cfg->p2p_net) {
-		/* Group Add request on p2p0 */
-		dev = bcmcfg_to_prmry_ndev(cfg);
-		dev_role = NL80211_IFTYPE_P2P_GO;
-	}
-#endif /* WL_ENABLE_P2P_IF */
-
-	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
-		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
-		return BCME_ERROR;
-	}
-
-	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
-		dev_role = NL80211_IFTYPE_P2P_GO;
-	} else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
-		dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
-	}
-
-	if (!check_dev_role_integrity(cfg, dev_role)) {
-		err = -ENODEV;
-		goto fail;
-	}
-
-	if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
-		WL_ERR(("P2P already down status!\n"));
-		err = BCME_ERROR;
-		goto fail;
-	}
-
-	ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
-	/* find the SSID */
-	if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
-		info->head_len - ie_offset,
-		DOT11_MNG_SSID_ID)) != NULL) {
-		if (dev_role == NL80211_IFTYPE_AP) {
-			/* Store the hostapd SSID */
-			memset(&cfg->hostapd_ssid.SSID[0], 0x00, 32);
-			memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
-			cfg->hostapd_ssid.SSID_len = ssid_ie->len;
-		} else {
-				/* P2P GO */
-			memset(&cfg->p2p->ssid.SSID[0], 0x00, 32);
-			memcpy(cfg->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
-			cfg->p2p->ssid.SSID_len = ssid_ie->len;
-		}
-	}
-
-	if (wl_cfg80211_parse_ies((u8 *)info->tail,
-		info->tail_len, &ies) < 0) {
-		WL_ERR(("Beacon get IEs failed \n"));
-		err = -EINVAL;
-		goto fail;
-	}
-
-	if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
-		VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
-		info->tail_len)) < 0) {
-		WL_ERR(("Beacon set IEs failed \n"));
-		goto fail;
-	} else {
-		WL_DBG(("Applied Vndr IEs for Beacon \n"));
-	}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
-	if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
-		VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies,
-		info->proberesp_ies_len)) < 0) {
-		WL_ERR(("ProbeRsp set IEs failed \n"));
-		goto fail;
-	} else {
-		WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
-	}
-#endif
-
-	is_bss_up = wl_cfgp2p_bss_isup(dev, bssidx);
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
-	privacy = info->privacy;
-#else
-	privacy = 0;
-#endif
-	if (!is_bss_up &&
-		(wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx, privacy) < 0))
-	{
-		WL_ERR(("Beacon set security failed \n"));
-		err = -EINVAL;
-		goto fail;
-	}
-
-	/* Set BI and DTIM period */
-	if (info->interval) {
-		if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
-			&info->interval, sizeof(s32), true)) < 0) {
-			WL_ERR(("Beacon Interval Set Error, %d\n", err));
-			return err;
-		}
-	}
-	if (info->dtim_period) {
-		if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
-			&info->dtim_period, sizeof(s32), true)) < 0) {
-			WL_ERR(("DTIM Interval Set Error, %d\n", err));
-			return err;
-		}
-	}
-
-	/* If bss is already up, skip bring up */
-	if (!is_bss_up &&
-		(err = wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx)) < 0)
-	{
-		WL_ERR(("Beacon bring up AP/GO failed \n"));
-		goto fail;
-	}
-
-	/* Set GC/STA SCB expiry timings. */
-	if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
-		WL_ERR(("scb setting failed \n"));
-		goto fail;
-	}
-
-	if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
-		/* Soft AP already running. Update changed params */
-		if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
-			WL_ERR(("Hostapd update sec failed \n"));
-			err = -EINVAL;
-			goto fail;
-		}
-	}
-
-	/* Enable Probe Req filter */
-	if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
-		(dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
-		wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
-		if (pbc)
-			wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
-	}
-
-	WL_DBG(("** ADD/SET beacon done **\n"));
-
-fail:
-	if (err) {
-		WL_ERR(("ADD/SET beacon failed\n"));
-		wldev_iovar_setint(dev, "mpc", 1);
-		if (dev_role == NL80211_IFTYPE_AP) {
-			/* clear the AP mode */
-			dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
-		}
-	}
-	return err;
-
-}
-#endif 
-
-#ifdef WL_SCHED_SCAN
-#define PNO_TIME		30
-#define PNO_REPEAT		4
-#define PNO_FREQ_EXPO_MAX	2
-static bool
-is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
-{
-	int i;
-
-	if (!ssid || !ssid_list)
-		return FALSE;
-
-	for (i = 0; i < count; i++) {
-		if (ssid->ssid_len == ssid_list[i].ssid_len) {
-			if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
-				return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-static int
-wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
-                             struct net_device *dev,
-                             struct cfg80211_sched_scan_request *request)
-{
-	ushort pno_time = PNO_TIME;
-	int pno_repeat = PNO_REPEAT;
-	int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
-	wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct cfg80211_ssid *ssid = NULL;
-	struct cfg80211_ssid *hidden_ssid_list = NULL;
-	int ssid_cnt = 0;
-	int i;
-	int ret = 0;
-
-	if (!request) {
-		WL_ERR(("Sched scan request was NULL\n"));
-		return -EINVAL;
-	}
-
-	WL_DBG(("Enter \n"));
-	WL_PNO((">>> SCHED SCAN START\n"));
-	WL_PNO(("Enter n_match_sets:%d   n_ssids:%d \n",
-		request->n_match_sets, request->n_ssids));
-	WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
-		request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
-
-
-	if (!request->n_ssids || !request->n_match_sets) {
-		WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
-		return -EINVAL;
-	}
-
-	memset(&ssids_local, 0, sizeof(ssids_local));
-
-	if (request->n_ssids > 0) {
-		hidden_ssid_list = request->ssids;
-	}
-
-	for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
-		ssid = &request->match_sets[i].ssid;
-		/* No need to include null ssid */
-		if (ssid->ssid_len) {
-			memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid, ssid->ssid_len);
-			ssids_local[ssid_cnt].SSID_len = ssid->ssid_len;
-			if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
-				ssids_local[ssid_cnt].hidden = TRUE;
-				WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
-			} else {
-				ssids_local[ssid_cnt].hidden = FALSE;
-				WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
-			}
-			ssid_cnt++;
-		}
-	}
-
-	if (ssid_cnt) {
-		if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt,
-			pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
-			WL_ERR(("PNO setup failed!! ret=%d \n", ret));
-			return -EINVAL;
-		}
-		cfg->sched_scan_req = request;
-	} else {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int
-wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-
-	WL_DBG(("Enter \n"));
-	WL_PNO((">>> SCHED SCAN STOP\n"));
-
-	if (dhd_dev_pno_stop_for_ssid(dev) < 0)
-		WL_ERR(("PNO Stop for SSID failed"));
-
-	if (cfg->scan_request && cfg->sched_scan_running) {
-		WL_PNO((">>> Sched scan running. Aborting it..\n"));
-		wl_notify_escan_complete(cfg, dev, true, true);
-	}
-
-	 cfg->sched_scan_req = NULL;
-	 cfg->sched_scan_running = FALSE;
-
-	return 0;
-}
-#endif /* WL_SCHED_SCAN */
-
-#ifdef WL_SUPPORT_ACS
-/*
- * Currently the dump_obss IOVAR is returning string as output so we need to
- * parse the output buffer in an unoptimized way. Going forward if we get the
- * IOVAR output in binary format this method can be optimized
- */
-static int wl_parse_dump_obss(char *buf, struct wl_dump_survey *survey)
-{
-	int i;
-	char *token;
-	char delim[] = " \n";
-
-	token = strsep(&buf, delim);
-	while (token != NULL) {
-		if (!strcmp(token, "OBSS")) {
-			for (i = 0; i < OBSS_TOKEN_IDX; i++)
-				token = strsep(&buf, delim);
-			survey->obss = simple_strtoul(token, NULL, 10);
-		}
-
-		if (!strcmp(token, "IBSS")) {
-			for (i = 0; i < IBSS_TOKEN_IDX; i++)
-				token = strsep(&buf, delim);
-			survey->ibss = simple_strtoul(token, NULL, 10);
-		}
-
-		if (!strcmp(token, "TXDur")) {
-			for (i = 0; i < TX_TOKEN_IDX; i++)
-				token = strsep(&buf, delim);
-			survey->tx = simple_strtoul(token, NULL, 10);
-		}
-
-		if (!strcmp(token, "Category")) {
-			for (i = 0; i < CTG_TOKEN_IDX; i++)
-				token = strsep(&buf, delim);
-			survey->no_ctg = simple_strtoul(token, NULL, 10);
-		}
-
-		if (!strcmp(token, "Packet")) {
-			for (i = 0; i < PKT_TOKEN_IDX; i++)
-				token = strsep(&buf, delim);
-			survey->no_pckt = simple_strtoul(token, NULL, 10);
-		}
-
-		if (!strcmp(token, "Opp(time):")) {
-			for (i = 0; i < IDLE_TOKEN_IDX; i++)
-				token = strsep(&buf, delim);
-			survey->idle = simple_strtoul(token, NULL, 10);
-		}
-
-		token = strsep(&buf, delim);
-	}
-
-	return 0;
-}
-
-static int wl_dump_obss(struct net_device *ndev, cca_msrmnt_query req,
-	struct wl_dump_survey *survey)
-{
-	cca_stats_n_flags *results;
-	char *buf;
-	int retry, err;
-
-	buf = kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN, GFP_KERNEL);
-	if (unlikely(!buf)) {
-		WL_ERR(("%s: buf alloc failed\n", __func__));
-		return -ENOMEM;
-	}
-
-	retry = IOCTL_RETRY_COUNT;
-	while (retry--) {
-		err = wldev_iovar_getbuf(ndev, "dump_obss", &req, sizeof(req),
-			buf, WLC_IOCTL_MAXLEN, NULL);
-		if (err >=  0) {
-			break;
-		}
-		WL_DBG(("attempt = %d, err = %d, \n",
-			(IOCTL_RETRY_COUNT - retry), err));
-	}
-
-	if (retry <= 0)	{
-		WL_ERR(("failure, dump_obss IOVAR failed\n"));
-		err = -EINVAL;
-		goto exit;
-	}
-
-	results = (cca_stats_n_flags *)(buf);
-	wl_parse_dump_obss(results->buf, survey);
-	kfree(buf);
-
-	return 0;
-exit:
-	kfree(buf);
-	return err;
-}
-
-static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
-	int idx, struct survey_info *info)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct wl_dump_survey *survey;
-	struct ieee80211_supported_band *band;
-	struct ieee80211_channel*chan;
-	cca_msrmnt_query req;
-	int val, err, noise, retry;
-
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-	if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
-		return -ENOENT;
-	}
-	band = wiphy->bands[IEEE80211_BAND_2GHZ];
-	if (band && idx >= band->n_channels) {
-		idx -= band->n_channels;
-		band = NULL;
-	}
-
-	if (!band || idx >= band->n_channels) {
-		/* Move to 5G band */
-		band = wiphy->bands[IEEE80211_BAND_5GHZ];
-		if (idx >= band->n_channels) {
-			return -ENOENT;
-		}
-	}
-
-	chan = &band->channels[idx];
-	/* Setting current channel to the requested channel */
-	if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
-		NL80211_CHAN_HT20) < 0)) {
-		WL_ERR(("Set channel failed \n"));
-	}
-
-	if (!idx) {
-		/* Disable mpc */
-		val = 0;
-		err = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
-			sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
-			&cfg->ioctl_buf_sync);
-		if (err < 0) {
-			WL_ERR(("set 'mpc' failed, error = %d\n", err));
-		}
-
-		/* Set interface up, explicitly. */
-		val = 1;
-		err = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
-		if (err < 0) {
-			WL_ERR(("set interface up failed, error = %d\n", err));
-		}
-	}
-
-	/* Get noise value */
-	retry = IOCTL_RETRY_COUNT;
-	while (retry--) {
-		err = wldev_ioctl(ndev, WLC_GET_PHY_NOISE, &noise,
-			sizeof(noise), false);
-		if (err >=  0) {
-			break;
-		}
-		WL_DBG(("attempt = %d, err = %d, \n",
-			(IOCTL_RETRY_COUNT - retry), err));
-	}
-
-	if (retry <= 0)	{
-		WL_ERR(("Get Phy Noise failed, error = %d\n", err));
-		noise = CHAN_NOISE_DUMMY;
-	}
-
-	survey = (struct wl_dump_survey *) kzalloc(sizeof(struct wl_dump_survey),
-		GFP_KERNEL);
-	if (unlikely(!survey)) {
-		WL_ERR(("%s: alloc failed\n", __func__));
-		return -ENOMEM;
-	}
-
-	/* Start Measurement for obss stats on current channel */
-	req.msrmnt_query = 0;
-	req.time_req = ACS_MSRMNT_DELAY;
-	if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
-		goto exit;
-	}
-
-	/*
-	 * Wait for the meaurement to complete, adding a buffer value of 10 to take
-	 * into consideration any delay in IOVAR completion
-	 */
-	msleep(ACS_MSRMNT_DELAY + 10);
-
-	/* Issue IOVAR to collect measurement results */
-	req.msrmnt_query = 1;
-	if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
-		goto exit;
-	}
-
-	info->channel = chan;
-	info->noise = noise;
-	info->channel_time = ACS_MSRMNT_DELAY;
-	info->channel_time_busy = ACS_MSRMNT_DELAY - survey->idle;
-	info->channel_time_rx = survey->obss + survey->ibss + survey->no_ctg +
-		survey->no_pckt;
-	info->channel_time_tx = survey->tx;
-	info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
-		SURVEY_INFO_CHANNEL_TIME_BUSY |	SURVEY_INFO_CHANNEL_TIME_RX |
-		SURVEY_INFO_CHANNEL_TIME_TX;
-	kfree(survey);
-
-	return 0;
-exit:
-	kfree(survey);
-	return err;
-}
-#endif /* WL_SUPPORT_ACS */
-
-static struct cfg80211_ops wl_cfg80211_ops = {
-	.add_virtual_intf = wl_cfg80211_add_virtual_iface,
-	.del_virtual_intf = wl_cfg80211_del_virtual_iface,
-	.change_virtual_intf = wl_cfg80211_change_virtual_iface,
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	.start_p2p_device = wl_cfgp2p_start_p2p_device,
-	.stop_p2p_device = wl_cfgp2p_stop_p2p_device,
-#endif /* WL_CFG80211_P2P_DEV_IF */
-	.scan = wl_cfg80211_scan,
-	.set_wiphy_params = wl_cfg80211_set_wiphy_params,
-	.join_ibss = wl_cfg80211_join_ibss,
-	.leave_ibss = wl_cfg80211_leave_ibss,
-	.get_station = wl_cfg80211_get_station,
-	.set_tx_power = wl_cfg80211_set_tx_power,
-	.get_tx_power = wl_cfg80211_get_tx_power,
-	.add_key = wl_cfg80211_add_key,
-	.del_key = wl_cfg80211_del_key,
-	.get_key = wl_cfg80211_get_key,
-	.set_default_key = wl_cfg80211_config_default_key,
-	.set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
-	.set_power_mgmt = wl_cfg80211_set_power_mgmt,
-	.connect = wl_cfg80211_connect,
-	.disconnect = wl_cfg80211_disconnect,
-	.suspend = wl_cfg80211_suspend,
-	.resume = wl_cfg80211_resume,
-	.set_pmksa = wl_cfg80211_set_pmksa,
-	.del_pmksa = wl_cfg80211_del_pmksa,
-	.flush_pmksa = wl_cfg80211_flush_pmksa,
-	.remain_on_channel = wl_cfg80211_remain_on_channel,
-	.cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
-	.mgmt_tx = wl_cfg80211_mgmt_tx,
-	.mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
-	.change_bss = wl_cfg80211_change_bss,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
-	.set_channel = wl_cfg80211_set_channel,
-#endif 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
-	.set_beacon = wl_cfg80211_add_set_beacon,
-	.add_beacon = wl_cfg80211_add_set_beacon,
-#else
-	.change_beacon = wl_cfg80211_change_beacon,
-	.start_ap = wl_cfg80211_start_ap,
-	.stop_ap = wl_cfg80211_stop_ap,
-#endif 
-#ifdef WL_SCHED_SCAN
-	.sched_scan_start = wl_cfg80211_sched_scan_start,
-	.sched_scan_stop = wl_cfg80211_sched_scan_stop,
-#endif /* WL_SCHED_SCAN */
-#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
-	2, 0))
-	.del_station = wl_cfg80211_del_station,
-	.change_station = wl_cfg80211_change_station,
-	.mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
-#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
-	.tdls_mgmt = wl_cfg80211_tdls_mgmt,
-	.tdls_oper = wl_cfg80211_tdls_oper,
-#endif 
-#ifdef WL_SUPPORT_ACS
-	.dump_survey = wl_cfg80211_dump_survey,
-#endif /* WL_SUPPORT_ACS */
-#ifdef WL_CFG80211_ACL
-	.set_mac_acl = wl_cfg80211_set_mac_acl,
-#endif /* WL_CFG80211_ACL */
-};
-
-s32 wl_mode_to_nl80211_iftype(s32 mode)
-{
-	s32 err = 0;
-
-	switch (mode) {
-	case WL_MODE_BSS:
-		return NL80211_IFTYPE_STATION;
-	case WL_MODE_IBSS:
-		return NL80211_IFTYPE_ADHOC;
-	case WL_MODE_AP:
-		return NL80211_IFTYPE_AP;
-	default:
-		return NL80211_IFTYPE_UNSPECIFIED;
-	}
-
-	return err;
-}
-
-#ifdef CONFIG_CFG80211_INTERNAL_REGDB
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-static int
-#else
-static void
-#endif /* kernel version < 3.9.0 */
-wl_cfg80211_reg_notifier(
-	struct wiphy *wiphy,
-	struct regulatory_request *request)
-{
-	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
-	int ret = 0;
-	int revinfo = -1;
-
-	if (!request || !cfg) {
-		WL_ERR(("Invalid arg\n"));
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-		return -EINVAL;
-#else
-		return;
-#endif /* kernel version < 3.9.0 */
-	}
-
-	WL_DBG(("ccode: %c%c Initiator: %d\n",
-		request->alpha2[0], request->alpha2[1], request->initiator));
-
-	/* We support only REGDOM_SET_BY_USER as of now */
-	if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
-		(request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
-		WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
-			request->initiator));
-		/* in case of no supported country by regdb
-		     lets driver setup platform default Locale
-		*/
-	}
-
-	WL_ERR(("Set country code %c%c from %s\n",
-		request->alpha2[0], request->alpha2[1],
-		((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
-
-	if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
-		false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false),
-		revinfo)) < 0) {
-		WL_ERR(("set country Failed :%d\n", ret));
-	}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-	return ret;
-#else
-	return;
-#endif /* kernel version < 3.9.0 */
-}
-#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
-
-#ifdef CONFIG_PM
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
-static const struct wiphy_wowlan_support brcm_wowlan_support = {
-	.flags = WIPHY_WOWLAN_ANY,
-	.n_patterns = WL_WOWLAN_MAX_PATTERNS,
-	.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
-	.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
-	.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
-};
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
-static struct cfg80211_wowlan brcm_wowlan_config = {
-	.disconnect = true,
-	.gtk_rekey_failure = true,
-	.eap_identity_req = true,
-	.four_way_handshake = true,
-};
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
-#endif /* CONFIG_PM */
-
-static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *context)
-{
-	s32 err = 0;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
-	dhd_pub_t *dhd = (dhd_pub_t *)context;
-	BCM_REFERENCE(dhd);
-
-	if (!dhd) {
-		WL_ERR(("DHD is NULL!!"));
-		err = -ENODEV;
-		return err;
-	}
-#endif 
-
-	wdev->wiphy =
-	    wiphy_new(&wl_cfg80211_ops, sizeof(struct bcm_cfg80211));
-	if (unlikely(!wdev->wiphy)) {
-		WL_ERR(("Couldn not allocate wiphy device\n"));
-		err = -ENOMEM;
-		return err;
-	}
-	set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
-	wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
-	/* Report  how many SSIDs Driver can support per Scan request */
-	wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
-	wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
-#ifdef WL_SCHED_SCAN
-	wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
-	wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
-	wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
-	wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
-#endif /* WL_SCHED_SCAN */
-	wdev->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_STATION)
-		| BIT(NL80211_IFTYPE_ADHOC)
-#if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
-		| BIT(NL80211_IFTYPE_MONITOR)
-#endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
-#if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
-		| BIT(NL80211_IFTYPE_P2P_CLIENT)
-		| BIT(NL80211_IFTYPE_P2P_GO)
-#endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
-#if defined(WL_CFG80211_P2P_DEV_IF)
-		| BIT(NL80211_IFTYPE_P2P_DEVICE)
-#endif /* WL_CFG80211_P2P_DEV_IF */
-		| BIT(NL80211_IFTYPE_AP);
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
-	(defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
-	WL_DBG(("Setting interface combinations for common mode\n"));
-	wdev->wiphy->iface_combinations = common_iface_combinations;
-	wdev->wiphy->n_iface_combinations =
-		ARRAY_SIZE(common_iface_combinations);
-#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
-
-	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
-
-	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-	wdev->wiphy->cipher_suites = __wl_cipher_suites;
-	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
-	wdev->wiphy->max_remain_on_channel_duration = 5000;
-	wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
-#ifndef WL_POWERSAVE_DISABLED
-	wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
-#else
-	wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-#endif				/* !WL_POWERSAVE_DISABLED */
-	wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
-		WIPHY_FLAG_4ADDR_AP |
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
-		WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
-#endif
-		WIPHY_FLAG_4ADDR_STATION;
-#if ((defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
-	KERNEL_VERSION(3, 2, 0)))
-	/*
-	 * If FW ROAM flag is advertised, upper layer wouldn't provide
-	 * the bssid & freq in the connect command. This will result a
-	 * delay in initial connection time due to firmware doing a full
-	 * channel scan to figure out the channel & bssid. However kernel
-	 * ver >= 3.15, provides bssid_hint & freq_hint and hence kernel
-	 * ver >= 3.15 won't have any issue. So if this flags need to be
-	 * advertised for kernel < 3.15, suggest to use RCC along with it
-	 * to avoid the initial connection delay.
-	 */
-	wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
-#endif 
-#ifdef UNSET_FW_ROAM_WIPHY_FLAG
-	wdev->wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_FW_ROAM;
-#endif /* UNSET_FW_ROAM_WIPHY_FLAG */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
-	wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
-		WIPHY_FLAG_OFFCHAN_TX;
-#endif
-#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
-	4, 0))
-	/* From 3.4 kernel ownards AP_SME flag can be advertised
-	 * to remove the patch from supplicant
-	 */
-	wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
-
-#ifdef WL_CFG80211_ACL
-	/* Configure ACL capabilities. */
-	wdev->wiphy->max_acl_mac_addrs = MAX_NUM_MAC_FILT;
-#endif
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
-	/* Supplicant distinguish between the SoftAP mode and other
-	 * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
-	 * response frame from Supplicant MR1 and Kernel 3.4.0 or
-	 * later version. To add Vendor specific IE into the
-	 * probe response frame in case of SoftAP mode,
-	 * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
-	 */
-	if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) {
-		wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
-		wdev->wiphy->probe_resp_offload = 0;
-	}
-#endif 
-#endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
-	wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
-#endif
-
-#if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
-	/*
-	 * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
-	 * disconnection of connected network before suspend. So a dummy wowlan
-	 * filter is configured for kernels linux-3.8 and above.
-	 */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
-	wdev->wiphy->wowlan = &brcm_wowlan_support;
-	/* If this is not provided cfg stack will get disconnect
-	 * during suspend.
-	 */
-	wdev->wiphy->wowlan_config = &brcm_wowlan_config;
-#else
-	wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
-	wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
-	wdev->wiphy->wowlan.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN;
-	wdev->wiphy->wowlan.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
-	wdev->wiphy->wowlan.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
-#endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
-
-	WL_DBG(("Registering custom regulatory)\n"));
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
-	wdev->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
-#else
-	wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
-#endif
-	wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
-#if defined(WL_VENDOR_EXT_SUPPORT)
-	WL_ERR(("Registering Vendor80211\n"));
-	err = wl_cfgvendor_attach(wdev->wiphy);
-	if (unlikely(err < 0)) {
-		WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
-	}
-#endif /* defined(WL_VENDOR_EXT_SUPPORT) */
-	/* Now we can register wiphy with cfg80211 module */
-	err = wiphy_register(wdev->wiphy);
-	if (unlikely(err < 0)) {
-		WL_ERR(("Couldn not register wiphy device (%d)\n", err));
-		wiphy_free(wdev->wiphy);
-	}
-
-#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
-	KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
-	wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
-#endif
-
-	return err;
-}
-
-static void wl_free_wdev(struct bcm_cfg80211 *cfg)
-{
-	struct wireless_dev *wdev = cfg->wdev;
-	struct wiphy *wiphy = NULL;
-	if (!wdev) {
-		WL_ERR(("wdev is invalid\n"));
-		return;
-	}
-	if (wdev->wiphy) {
-		wiphy = wdev->wiphy;
-
-#if defined(WL_VENDOR_EXT_SUPPORT)
-		wl_cfgvendor_detach(wdev->wiphy);
-#endif /* if defined(WL_VENDOR_EXT_SUPPORT) */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
-		/* Reset wowlan & wowlan_config before Unregister to avoid  Kernel Panic */
-		WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
-		wdev->wiphy->wowlan = NULL;
-		wdev->wiphy->wowlan_config = NULL;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
-		wiphy_unregister(wdev->wiphy);
-		wdev->wiphy->dev.parent = NULL;
-		wdev->wiphy = NULL;
-	}
-
-	wl_delete_all_netinfo(cfg);
-	if (wiphy)
-		wiphy_free(wiphy);
-
-	/* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
-	 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
-	 */
-}
-
-static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
-{
-	struct wl_scan_results *bss_list;
-	struct wl_bss_info *bi = NULL;	/* must be initialized */
-	s32 err = 0;
-	s32 i;
-
-	bss_list = cfg->bss_list;
-	WL_DBG(("scanned AP count (%d)\n", bss_list->count));
-	bi = next_bss(bss_list, bi);
-	for_each_bss(bss_list, bi, i) {
-		err = wl_inform_single_bss(cfg, bi, false);
-		if (unlikely(err))
-			break;
-	}
-	return err;
-}
-
-static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam)
-{
-	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
-	struct ieee80211_mgmt *mgmt;
-	struct ieee80211_channel *channel;
-	struct ieee80211_supported_band *band;
-	struct wl_cfg80211_bss_info *notif_bss_info;
-	struct wl_scan_req *sr = wl_to_sr(cfg);
-	struct beacon_proberesp *beacon_proberesp;
-	struct cfg80211_bss *cbss = NULL;
-	s32 mgmt_type;
-	s32 signal;
-	u32 freq;
-	s32 err = 0;
-	gfp_t aflags;
-
-	if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
-		WL_DBG(("Beacon is larger than buffer. Discarding\n"));
-		return err;
-	}
-	aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
-	notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
-		- sizeof(u8) + WL_BSS_INFO_MAX, aflags);
-	if (unlikely(!notif_bss_info)) {
-		WL_ERR(("notif_bss_info alloc failed\n"));
-		return -ENOMEM;
-	}
-	mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
-	notif_bss_info->channel =
-		wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
-
-	if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
-		band = wiphy->bands[IEEE80211_BAND_2GHZ];
-	else
-		band = wiphy->bands[IEEE80211_BAND_5GHZ];
-	if (!band) {
-		WL_ERR(("No valid band"));
-		kfree(notif_bss_info);
-		return -EINVAL;
-	}
-	notif_bss_info->rssi = wl_rssi_offset(dtoh16(bi->RSSI));
-	memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
-	mgmt_type = cfg->active_scan ?
-		IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
-	if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
-	    mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
-	}
-	beacon_proberesp = cfg->active_scan ?
-		(struct beacon_proberesp *)&mgmt->u.probe_resp :
-		(struct beacon_proberesp *)&mgmt->u.beacon;
-	beacon_proberesp->timestamp = 0;
-	beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
-	beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
-	wl_rst_ie(cfg);
-	wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, roam);
-	wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
-	wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
-		offsetof(struct wl_cfg80211_bss_info, frame_buf));
-	notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
-		u.beacon.variable) + wl_get_ielen(cfg);
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
-	freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
-	(void)band->band;
-#else
-	freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
-#endif
-	if (freq == 0) {
-		WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
-		kfree(notif_bss_info);
-		return -EINVAL;
-	}
-	channel = ieee80211_get_channel(wiphy, freq);
-	if (unlikely(!channel)) {
-		WL_ERR(("ieee80211_get_channel error\n"));
-		kfree(notif_bss_info);
-		return -EINVAL;
-	}
-	WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
-			"mgmt_type %d frame_len %d\n", bi->SSID,
-			notif_bss_info->rssi, notif_bss_info->channel,
-			mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
-			notif_bss_info->frame_len));
-
-	signal = notif_bss_info->rssi * 100;
-	if (!mgmt->u.probe_resp.timestamp) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
-		struct timespec ts;
-		get_monotonic_boottime(&ts);
-		mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
-				+ ts.tv_nsec / 1000;
-#else
-		struct timeval tv;
-		do_gettimeofday(&tv);
-		mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
-				+ tv.tv_usec;
-#endif
-	}
-
-
-	cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
-		le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
-	if (unlikely(!cbss)) {
-		WL_ERR(("cfg80211_inform_bss_frame error\n"));
-		kfree(notif_bss_info);
-		return -EINVAL;
-	}
-
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
-	cfg80211_put_bss(wiphy, cbss);
-#else
-	cfg80211_put_bss(cbss);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
-	kfree(notif_bss_info);
-	return err;
-}
-
-static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, struct net_device *ndev)
-{
-	u32 event = ntoh32(e->event_type);
-	u32 status =  ntoh32(e->status);
-	u16 flags = ntoh16(e->flags);
-
-	WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
-	if (event == WLC_E_SET_SSID) {
-		if (status == WLC_E_STATUS_SUCCESS) {
-			if (!wl_is_ibssmode(cfg, ndev))
-				return true;
-		}
-	} else if (event == WLC_E_LINK) {
-		if (flags & WLC_EVENT_MSG_LINK)
-			return true;
-	}
-
-	WL_DBG(("wl_is_linkup false\n"));
-	return false;
-}
-
-static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
-{
-	u32 event = ntoh32(e->event_type);
-	u16 flags = ntoh16(e->flags);
-
-	if (event == WLC_E_DEAUTH_IND ||
-	event == WLC_E_DISASSOC_IND ||
-	event == WLC_E_DISASSOC ||
-	event == WLC_E_DEAUTH) {
-#if (WL_DBG_LEVEL > 0)
-	WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
-#endif /* (WL_DBG_LEVEL > 0) */
-		return true;
-	} else if (event == WLC_E_LINK) {
-		if (!(flags & WLC_EVENT_MSG_LINK)) {
-#if (WL_DBG_LEVEL > 0)
-	WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
-#endif /* (WL_DBG_LEVEL > 0) */
-			return true;
-		}
-	}
-
-	return false;
-}
-
-static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
-{
-	u32 event = ntoh32(e->event_type);
-	u32 status = ntoh32(e->status);
-
-	if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
-		return true;
-	if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
-		return true;
-
-	return false;
-}
-
-/* The mainline kernel >= 3.2.0 has support for indicating new/del station
- * to AP/P2P GO via events. If this change is backported to kernel for which
- * this driver is being built, then define WL_CFG80211_STA_EVENT. You
- * should use this new/del sta event mechanism for BRCM supplicant >= 22.
- */
-static s32
-wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, void *data)
-{
-	s32 err = 0;
-	u32 event = ntoh32(e->event_type);
-	u32 reason = ntoh32(e->reason);
-	u32 len = ntoh32(e->datalen);
-	u32 status = ntoh32(e->status);
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
-	bool isfree = false;
-	u8 *mgmt_frame;
-	u8 bsscfgidx = e->bsscfgidx;
-	s32 freq;
-	s32 channel;
-	u8 *body = NULL;
-	u16 fc = 0;
-
-	struct ieee80211_supported_band *band;
-	struct ether_addr da;
-	struct ether_addr bssid;
-	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
-	channel_info_t ci;
-#else
-	struct station_info sinfo;
-#endif 
-
-	WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
-	/* if link down, bsscfg is disabled. */
-	if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
-		wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
-		wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
-		WL_INFORM(("AP mode link down !! \n"));
-		complete(&cfg->iface_disable);
-		return 0;
-	}
-
-	if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
-		(reason == WLC_E_REASON_INITIAL_ASSOC) &&
-		(wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
-		if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
-			/* AP/GO brought up successfull in firmware */
-			WL_ERR(("** AP/GO Link up event **\n"));
-			wl_set_drv_status(cfg, AP_CREATED, ndev);
-			wake_up_interruptible(&cfg->netif_change_event);
-			return 0;
-		}
-	}
-
-	if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
-		WL_ERR(("event %s(%d) status %d reason %d\n",
-		bcmevent_get_name(event), event, ntoh32(e->status), reason));
-	}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
-	WL_DBG(("Enter \n"));
-	if (!len && (event == WLC_E_DEAUTH)) {
-		len = 2; /* reason code field */
-		data = &reason;
-	}
-	if (len) {
-		body = kzalloc(len, GFP_KERNEL);
-
-		if (body == NULL) {
-			WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
-			return WL_INVALID;
-		}
-	}
-	memset(&bssid, 0, ETHER_ADDR_LEN);
-	WL_DBG(("Enter event %d ndev %p\n", event, ndev));
-	if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
-		kfree(body);
-		return WL_INVALID;
-	}
-	if (len)
-		memcpy(body, data, len);
-
-	wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
-		NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
-	memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
-	err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
-	switch (event) {
-		case WLC_E_ASSOC_IND:
-			fc = FC_ASSOC_REQ;
-			break;
-		case WLC_E_REASSOC_IND:
-			fc = FC_REASSOC_REQ;
-			break;
-		case WLC_E_DISASSOC_IND:
-			fc = FC_DISASSOC;
-			break;
-		case WLC_E_DEAUTH_IND:
-			fc = FC_DISASSOC;
-			break;
-		case WLC_E_DEAUTH:
-			fc = FC_DISASSOC;
-			break;
-		default:
-			fc = 0;
-			goto exit;
-	}
-	if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
-		kfree(body);
-		return err;
-	}
-
-	channel = dtoh32(ci.hw_channel);
-	if (channel <= CH_MAX_2G_CHANNEL)
-		band = wiphy->bands[IEEE80211_BAND_2GHZ];
-	else
-		band = wiphy->bands[IEEE80211_BAND_5GHZ];
-	if (!band) {
-		WL_ERR(("No valid band"));
-		if (body)
-			kfree(body);
-		return -EINVAL;
-	}
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
-	freq = ieee80211_channel_to_frequency(channel);
-	(void)band->band;
-#else
-	freq = ieee80211_channel_to_frequency(channel, band->band);
-#endif
-
-	err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
-		&mgmt_frame, &len, body);
-	if (err < 0)
-		goto exit;
-	isfree = true;
-
-	if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
-#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) && (LINUX_VERSION_CODE < \
-	KERNEL_VERSION(3, 18, 0)))
-		cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
-
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-		cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len);
-#else
-		cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
-#endif 
-	} else if (event == WLC_E_DISASSOC_IND) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
-		cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
-#else
-		cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
-#endif 
-	} else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
-		cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
-#else
-		cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
-#endif 
-	}
-
-exit:
-	if (isfree)
-		kfree(mgmt_frame);
-	if (body)
-		kfree(body);
-#else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
-	sinfo.filled = 0;
-	if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
-		reason == DOT11_SC_SUCCESS) {
-		/* Linux ver >= 4.0 assoc_req_ies_len is used instead of
-		 * STATION_INFO_ASSOC_REQ_IES flag
-		 */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
-		sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
-#endif /*  (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
-		if (!data) {
-			WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
-			return -EINVAL;
-		}
-		sinfo.assoc_req_ies = data;
-		sinfo.assoc_req_ies_len = len;
-		cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
-	} else if (event == WLC_E_DISASSOC_IND) {
-		cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
-	} else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
-		cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
-	}
-#endif 
-	return err;
-}
-
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-#define MAX_ASSOC_REJECT_ERR_STATUS 5
-int wl_get_connect_failed_status(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
-{
-	u32 status = ntoh32(e->status);
-
-	cfg->assoc_reject_status = 0;
-
-	if (status == WLC_E_STATUS_FAIL) {
-		WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
-			ntoh32(cfg->event_auth_assoc.event_type),
-			(int)ntoh32(cfg->event_auth_assoc.status),
-			(int)ntoh32(cfg->event_auth_assoc.reason)));
-
-		switch ((int)ntoh32(cfg->event_auth_assoc.status)) {
-			case WLC_E_STATUS_NO_ACK:
-				cfg->assoc_reject_status = 1;
-				break;
-			case WLC_E_STATUS_FAIL:
-				cfg->assoc_reject_status = 2;
-				break;
-			case WLC_E_STATUS_UNSOLICITED:
-				cfg->assoc_reject_status = 3;
-				break;
-			case WLC_E_STATUS_TIMEOUT:
-				cfg->assoc_reject_status = 4;
-				break;
-			case WLC_E_STATUS_ABORT:
-				cfg->assoc_reject_status = 5;
-				break;
-			default:
-				break;
-		}
-		if (cfg->assoc_reject_status) {
-			if (ntoh32(cfg->event_auth_assoc.event_type) == WLC_E_ASSOC) {
-				cfg->assoc_reject_status += MAX_ASSOC_REJECT_ERR_STATUS;
-			}
-		}
-	}
-
-	WL_ERR(("assoc_reject_status %d \n", cfg->assoc_reject_status));
-
-	return 0;
-}
-
-s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int total_len)
-{
-	struct bcm_cfg80211 *cfg = NULL;
-	int bytes_written = 0;
-
-	cfg = g_bcm_cfg;
-
-	if (cfg == NULL) {
-		return -1;
-	}
-
-	memset(cmd, 0, total_len);
-	bytes_written = snprintf(cmd, 30, "assoc_reject.status %d", cfg->assoc_reject_status);
-
-	WL_ERR(("cmd: %s \n", cmd));
-
-	return bytes_written;
-}
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-
-static s32
-wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e)
-{
-	u32 reason = ntoh32(e->reason);
-	u32 event = ntoh32(e->event_type);
-	struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
-	WL_DBG(("event type : %d, reason : %d\n", event, reason));
-
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-	memcpy(&cfg->event_auth_assoc, e, sizeof(wl_event_msg_t));
-	WL_ERR(("event=%d status %d reason %d \n",
-		ntoh32(cfg->event_auth_assoc.event_type),
-		ntoh32(cfg->event_auth_assoc.status),
-		ntoh32(cfg->event_auth_assoc.reason)));
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-	if (sec) {
-		switch (event) {
-		case WLC_E_ASSOC:
-		case WLC_E_AUTH:
-				sec->auth_assoc_res_status = reason;
-		default:
-			break;
-		}
-	} else
-		WL_ERR(("sec is NULL\n"));
-	return 0;
-}
-
-static s32
-wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, void *data)
-{
-	s32 err = 0;
-	u32 event = ntoh32(e->event_type);
-	u16 flags = ntoh16(e->flags);
-	u32 status =  ntoh32(e->status);
-	bool active;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
-	struct ieee80211_channel *channel = NULL;
-	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
-	u32 chanspec, chan;
-	u32 freq, band;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
-
-	if (event == WLC_E_JOIN) {
-		WL_DBG(("joined in IBSS network\n"));
-	}
-	if (event == WLC_E_START) {
-		WL_DBG(("started IBSS network\n"));
-	}
-	if (event == WLC_E_JOIN || event == WLC_E_START ||
-		(event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
-		err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
-		if (unlikely(err)) {
-			WL_ERR(("Could not get chanspec %d\n", err));
-			return err;
-		}
-		chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
-		band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-		freq = ieee80211_channel_to_frequency(chan, band);
-		channel = ieee80211_get_channel(wiphy, freq);
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
-		if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
-			/* ROAM or Redundant */
-			u8 *cur_bssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
-			if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
-				WL_DBG(("IBSS connected event from same BSSID("
-					MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
-				return err;
-			}
-			WL_INFORM(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
-				MAC2STRDBG(cur_bssid), MAC2STRDBG((const u8 *)&e->addr)));
-			wl_get_assoc_ies(cfg, ndev);
-			wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
-			wl_update_bss_info(cfg, ndev, false);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
-			cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
-#else
-			cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
-#endif
-		}
-		else {
-			/* New connection */
-			WL_INFORM(("IBSS connected to " MACDBG "\n",
-				MAC2STRDBG((const u8 *)&e->addr)));
-			wl_link_up(cfg);
-			wl_get_assoc_ies(cfg, ndev);
-			wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
-			wl_update_bss_info(cfg, ndev, false);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
-			cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
-#else
-			cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
-#endif
-			wl_set_drv_status(cfg, CONNECTED, ndev);
-			active = true;
-			wl_update_prof(cfg, ndev, NULL, (const void *)&active, WL_PROF_ACT);
-		}
-	} else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
-		event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
-		wl_clr_drv_status(cfg, CONNECTED, ndev);
-		wl_link_down(cfg);
-		wl_init_prof(cfg, ndev);
-	}
-	else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
-		WL_DBG(("no action - join fail (IBSS mode)\n"));
-	}
-	else {
-		WL_DBG(("no action (IBSS mode)\n"));
-}
-	return err;
-}
-
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-#define WiFiALL_OUI         "\x50\x6F\x9A"  /* Wi-FiAll OUI */
-#define WiFiALL_OUI_LEN     3
-#define WiFiALL_OUI_TYPE    16
-
-int wl_get_bss_info(struct bcm_cfg80211 *cfg, struct net_device *dev, uint8 *mac)
-{
-	s32 err = 0;
-	struct wl_bss_info *bi;
-	uint8 eabuf[ETHER_ADDR_LEN];
-	u32 rate, channel, freq, supported_rate, nss = 0, mcs_map, mode_80211 = 0;
-	char rate_str[4];
-	u8 *ie = NULL;
-	u32 ie_len;
-	struct wiphy *wiphy;
-	struct cfg80211_bss *bss;
-	bcm_tlv_t *interworking_ie = NULL;
-	bcm_tlv_t *tlv_ie = NULL;
-	bcm_tlv_t *vht_ie = NULL;
-	vndr_ie_t *vndrie;
-	int16 ie_11u_rel_num = -1, ie_mu_mimo_cap = -1;
-	u32 i, remained_len, count = 0;
-	char roam_count_str[4], akm_str[4];
-	s32 val = 0;
-
-	/* get BSS information */
-
-	strncpy(cfg->bss_info, "x x x x x x x x x x x x x", GET_BSS_INFO_LEN);
-
-	*(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
-
-	err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
-	if (unlikely(err)) {
-		WL_ERR(("Could not get bss info %d\n", err));
-		cfg->roam_count = 0;
-		return -1;
-	}
-
-	if (!mac) {
-		WL_ERR(("mac is null \n"));
-		cfg->roam_count = 0;
-		return -1;
-	}
-
-	memcpy(eabuf, mac, ETHER_ADDR_LEN);
-
-	bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
-	channel = wf_chspec_ctlchan(bi->chanspec);
-
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
-	freq = ieee80211_channel_to_frequency(channel);
-#else
-	if (channel > 14) {
-		freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
-	} else {
-		freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
-	}
-#endif
-
-	err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
-	if (err) {
-		WL_ERR(("Could not get rate (%d)\n", err));
-		snprintf(rate_str, sizeof(rate_str), "x"); // Unknown
-
-	} else {
-		rate = dtoh32(rate);
-		snprintf(rate_str, sizeof(rate_str), "%d", (rate/2));
-	}
-
-	//supported maximum rate
-	supported_rate = (bi->rateset.rates[bi->rateset.count - 1] & 0x7f) / 2;
-
-	if (supported_rate < 12) {
-		mode_80211 = 0; //11b maximum rate is 11Mbps. 11b mode
-	} else {
-		//It's not HT Capable case.
-		if (channel > 14) {
-			mode_80211 = 3; // 11a mode
-		} else {
-			mode_80211 = 1; // 11g mode
-		}
-	}
-
-	if (bi->n_cap) {
-		/* check Rx MCS Map for HT */
-		nss = 0;
-		mode_80211 = 2;
-		for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
-			int8 bitmap = 0xFF;
-			if (i == MAX_STREAMS_SUPPORTED-1) {
-				bitmap = 0x7F;
-			}
-			if (bi->basic_mcs[i] & bitmap) {
-				nss++;
-			}
-		}
-	}
-
-	if (bi->vht_cap) {
-		nss = 0;
-		mode_80211 = 4;
-		for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
-			mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
-			if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
-				nss++;
-			}
-		}
-	}
-
-	if (nss) {
-		nss = nss - 1;
-	}
-
-	wiphy = bcmcfg_to_wiphy(cfg);
-	bss = cfg80211_get_bss(wiphy, NULL, eabuf,
-			bi->SSID, strlen(bi->SSID), WLAN_CAPABILITY_ESS,
-			WLAN_CAPABILITY_ESS);
-
-	if (!bss) {
-		WL_ERR(("Could not find the AP\n"));
-	} else {
-#if defined(WL_CFG80211_P2P_DEV_IF)
-		ie = (u8 *)bss->ies->data;
-		ie_len = bss->ies->len;
-#else
-		ie = bss->information_elements;
-		ie_len = bss->len_information_elements;
-#endif /* WL_CFG80211_P2P_DEV_IF */
-	}
-
-	if (ie) {
-		ie_mu_mimo_cap = 0;
-		ie_11u_rel_num = 0;
-
-		if (bi->vht_cap) {
-			if ((vht_ie = bcm_parse_tlvs(ie, (u32)ie_len,
-					DOT11_MNG_VHT_CAP_ID)) != NULL) {
-				ie_mu_mimo_cap = (vht_ie->data[2] & 0x08) >> 3;
-			}
-		}
-
-		if ((interworking_ie = bcm_parse_tlvs(ie, (u32)ie_len,
-				DOT11_MNG_INTERWORKING_ID)) != NULL) {
-			if ((tlv_ie = bcm_parse_tlvs(ie, (u32)ie_len, DOT11_MNG_VS_ID)) != NULL) {
-				remained_len = ie_len;
-
-				while (tlv_ie) {
-					if (count > MAX_VNDR_IE_NUMBER)
-						break;
-
-					if (tlv_ie->id == DOT11_MNG_VS_ID) {
-						vndrie = (vndr_ie_t *) tlv_ie;
-
-						if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
-							WL_ERR(("%s: invalid vndr ie."
-								"length is too small %d\n",
-								__FUNCTION__, vndrie->len));
-							break;
-						}
-
-						if (!bcmp(vndrie->oui,
-							(u8*)WiFiALL_OUI, WiFiALL_OUI_LEN) &&
-							(vndrie->data[0] == WiFiALL_OUI_TYPE))
-						{
-							WL_ERR(("Found Wi-FiAll OUI oui.\n"));
-							ie_11u_rel_num = vndrie->data[1];
-							ie_11u_rel_num = (ie_11u_rel_num & 0xf0)>>4;
-							ie_11u_rel_num += 1;
-
-							break;
-						}
-					}
-					count++;
-					tlv_ie = bcm_next_tlv(tlv_ie, &remained_len);
-				}
-			}
-		}
-	}
-
-	for (i = 0; i < bi->SSID_len; i++) {
-		if (bi->SSID[i] == ' ') {
-			bi->SSID[i] = '_';
-		}
-	}
-
-	//0 : None, 1 : OKC, 2 : FT, 3 : CCKM
-	err = wldev_iovar_getint(dev, "wpa_auth", &val);
-	if (unlikely(err)) {
-		WL_ERR(("could not get wpa_auth (%d)\n", err));
-		snprintf(akm_str, sizeof(akm_str), "x"); // Unknown
-	} else {
-		WL_ERR(("wpa_auth val %d \n", val));
-#if defined(BCMEXTCCX)
-		if (val & (WPA_AUTH_CCKM | WPA2_AUTH_CCKM)) {
-			snprintf(akm_str, sizeof(akm_str), "3");
-		} else
-#endif  
-		if (val & WPA2_AUTH_FT) {
-			snprintf(akm_str, sizeof(akm_str), "2");
-		} else if (val & (WPA_AUTH_UNSPECIFIED | WPA2_AUTH_UNSPECIFIED)) {
-			snprintf(akm_str, sizeof(akm_str), "1");
-		} else {
-			snprintf(akm_str, sizeof(akm_str), "0");
-		}
-	}
-
-	if (cfg->roam_offload) {
-		snprintf(roam_count_str, sizeof(roam_count_str), "x"); // Unknown
-	} else {
-		snprintf(roam_count_str, sizeof(roam_count_str), "%d", cfg->roam_count);
-	}
-	cfg->roam_count = 0;
-
-	WL_ERR(("BSSID:" MACDBG " SSID %s \n", MAC2STRDBG(eabuf), bi->SSID));
-	WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
-				"MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
-				"akm:%s roam:%s \n",
-				freq, wf_chspec_to_bw_str(bi->chanspec),
-				dtoh32(bi->RSSI), (rate / 2), mode_80211, nss,
-				ie_mu_mimo_cap, ie_11u_rel_num, bi->SNR, bi->phy_noise,
-				akm_str, roam_count_str));
-
-	if (ie) {
-		snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
-				"%02x:%02x:%02x %d %s %d %s %d %d %d %d %d %d %s %s",
-				eabuf[0], eabuf[1], eabuf[2],
-				freq, wf_chspec_to_bw_str(bi->chanspec),
-				dtoh32(bi->RSSI), rate_str, mode_80211, nss,
-				ie_mu_mimo_cap, ie_11u_rel_num,
-				bi->SNR, bi->phy_noise, akm_str, roam_count_str);
-	} else {
-		//ie_mu_mimo_cap and ie_11u_rel_num is unknow.
-		snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
-				"%02x:%02x:%02x %d %s %d %s %d %d x x %d %d %s %s",
-				eabuf[0], eabuf[1], eabuf[2],
-				freq, wf_chspec_to_bw_str(bi->chanspec),
-				dtoh32(bi->RSSI), rate_str, mode_80211, nss,
-				bi->SNR, bi->phy_noise, akm_str, roam_count_str);
-	}
-
-
-	return 0;
-}
-
-s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len)
-{
-	struct bcm_cfg80211 *cfg = NULL;
-
-	cfg = g_bcm_cfg;
-
-	if (cfg == NULL) {
-		return -1;
-	}
-
-	memset(cmd, 0, total_len);
-	memcpy(cmd, cfg->bss_info, GET_BSS_INFO_LEN);
-
-	WL_ERR(("cmd: %s \n", cmd));
-
-	return GET_BSS_INFO_LEN;
-}
-
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-
-static s32
-wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	bool act;
-	struct net_device *ndev = NULL;
-	s32 err = 0;
-	u32 event = ntoh32(e->event_type);
-	struct wiphy *wiphy = NULL;
-	struct cfg80211_bss *bss = NULL;
-	struct wlc_ssid *ssid = NULL;
-	u8 *bssid = 0;
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
-		err = wl_notify_connect_status_ap(cfg, ndev, e, data);
-	} else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS) {
-		err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
-	} else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) {
-		WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
-			ntoh32(e->event_type), ntoh32(e->status), ndev));
-		if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
-			wl_get_auth_assoc_status(cfg, ndev, e);
-			return 0;
-		}
-		DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
-		if (wl_is_linkup(cfg, e, ndev)) {
-			wl_link_up(cfg);
-			act = true;
-			if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
-#ifdef DHD_LOSSLESS_ROAMING
-					bool is_connected = wl_get_drv_status(cfg, CONNECTED, ndev);
-#endif
-
-					WL_ERR(("wl_bss_connect_done succeeded with " MACDBG "\n",
-						MAC2STRDBG((const u8*)(&e->addr))));
-					wl_bss_connect_done(cfg, ndev, e, data, true);
-					WL_DBG(("joined in BSS network \"%s\"\n",
-					((struct wlc_ssid *)
-					 wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID));
-#ifdef DHD_LOSSLESS_ROAMING
-					if (event == WLC_E_LINK && is_connected &&
-							!cfg->roam_offload) {
-						wl_bss_roaming_done(cfg, ndev, e, data);
-					}
-#endif /* DHD_LOSSLESS_ROAMING */
-
-				}
-			wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
-			wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
-
-		} else if (wl_is_linkdown(cfg, e)) {
-#ifdef DHD_LOSSLESS_ROAMING
-			wl_del_roam_timeout(cfg);
-#endif
-#ifdef P2PLISTEN_AP_SAMECHN
-			if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
-				wl_cfg80211_set_p2p_resp_ap_chn(ndev, 0);
-				cfg->p2p_resp_apchn_status = false;
-				WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
-			}
-#endif /* P2PLISTEN_AP_SAMECHN */
-			wl_cfg80211_cancel_scan(cfg);
-
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-			if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
-				wl_get_bss_info(cfg, ndev, (u8*)(&e->addr));
-			}
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-			/* Explicitly calling unlink to remove BSS in CFG */
-			wiphy = bcmcfg_to_wiphy(cfg);
-			ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
-			bssid = (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID);
-			if (ssid && bssid) {
-				bss = cfg80211_get_bss(wiphy, NULL, bssid,
-					ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
-					WLAN_CAPABILITY_ESS);
-				if (bss) {
-					cfg80211_unlink_bss(wiphy, bss);
-				}
-			}
-
-			if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
-				scb_val_t scbval;
-				u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
-				s32 reason = 0;
-				struct ether_addr bssid_dongle;
-				struct ether_addr bssid_null = {{0, 0, 0, 0, 0, 0}};
-
-				if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
-					reason = ntoh32(e->reason);
-				/* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
-				reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
-
-				WL_ERR(("link down if %s may call cfg80211_disconnected. "
-					"event : %d, reason=%d from " MACDBG "\n",
-					ndev->name, event, ntoh32(e->reason),
-					MAC2STRDBG((const u8*)(&e->addr))));
-
-				/* roam offload does not sync BSSID always, get it from dongle */
-				if (cfg->roam_offload) {
-					if (wldev_ioctl(ndev, WLC_GET_BSSID, &bssid_dongle,
-							sizeof(bssid_dongle), false) == BCME_OK) {
-						/* if not roam case, it would return null bssid */
-						if (memcmp(&bssid_dongle, &bssid_null,
-								ETHER_ADDR_LEN) != 0) {
-							curbssid = (u8 *)&bssid_dongle;
-						}
-					}
-				}
-				if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
-					bool fw_assoc_state = TRUE;
-					dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
-					fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
-					if (!fw_assoc_state) {
-						WL_ERR(("Even sends up even different BSSID"
-							" cur: " MACDBG " event: " MACDBG"\n",
-							MAC2STRDBG(curbssid),
-							MAC2STRDBG((const u8*)(&e->addr))));
-					} else {
-						WL_ERR(("BSSID of event is not the connected BSSID"
-							"(ignore it) cur: " MACDBG
-							" event: " MACDBG"\n",
-							MAC2STRDBG(curbssid),
-							MAC2STRDBG((const u8*)(&e->addr))));
-						return 0;
-					}
-				}
-				wl_clr_drv_status(cfg, CONNECTED, ndev);
-				if (! wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
-					/* To make sure disconnect, explictly send dissassoc
-					*  for BSSID 00:00:00:00:00:00 issue
-					*/
-					scbval.val = WLAN_REASON_DEAUTH_LEAVING;
-
-					memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
-					scbval.val = htod32(scbval.val);
-					err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
-						sizeof(scb_val_t), true);
-					if (err < 0) {
-						WL_ERR(("WLC_DISASSOC error %d\n", err));
-						err = 0;
-					}
-					CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
-							false, GFP_KERNEL);
-					wl_link_down(cfg);
-					wl_init_prof(cfg, ndev);
-					memset(&cfg->last_roamed_addr, 0, ETHER_ADDR_LEN);
-				}
-			}
-			else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
-				WL_ERR(("link down, during connecting\n"));
-#ifdef ESCAN_RESULT_PATCH
-				if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
-					(memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
-					(memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
-					/* In case this event comes while associating another AP */
-#endif /* ESCAN_RESULT_PATCH */
-					wl_bss_connect_done(cfg, ndev, e, data, false);
-			}
-			wl_clr_drv_status(cfg, DISCONNECTING, ndev);
-
-			/* if link down, bsscfg is diabled */
-			if (ndev != bcmcfg_to_prmry_ndev(cfg))
-				complete(&cfg->iface_disable);
-
-		} else if (wl_is_nonetwork(cfg, e)) {
-			WL_ERR(("connect failed event=%d e->status %d e->reason %d \n",
-				event, (int)ntoh32(e->status), (int)ntoh32(e->reason)));
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-			if (event == WLC_E_SET_SSID) {
-				wl_get_connect_failed_status(cfg, e);
-			}
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-			/* Clean up any pending scan request */
-			wl_cfg80211_cancel_scan(cfg);
-			if (wl_get_drv_status(cfg, CONNECTING, ndev))
-				wl_bss_connect_done(cfg, ndev, e, data, false);
-		} else {
-			WL_DBG(("%s nothing\n", __FUNCTION__));
-		}
-		DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
-	}
-		else {
-		WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
-	}
-	return err;
-}
-
-void wl_cfg80211_set_rmc_pid(int pid)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	if (pid > 0)
-		cfg->rmc_event_pid = pid;
-	WL_DBG(("set pid for rmc event : pid=%d\n", pid));
-}
-
-#ifdef WL_RELMCAST
-static s32
-wl_notify_rmc_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	u32 evt = ntoh32(e->event_type);
-	u32 reason = ntoh32(e->reason);
-	int ret = -1;
-
-	switch (reason) {
-		case WLC_E_REASON_RMC_AR_LOST:
-		case WLC_E_REASON_RMC_AR_NO_ACK:
-			if (cfg->rmc_event_pid != 0) {
-				ret = wl_netlink_send_msg(cfg->rmc_event_pid,
-					RMC_EVENT_LEADER_CHECK_FAIL,
-					cfg->rmc_event_seq++, NULL, 0);
-			}
-			break;
-		default:
-			break;
-	}
-	WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt, cfg->rmc_event_pid, ret));
-	return ret;
-}
-#endif /* WL_RELMCAST */
-static s32
-wl_notify_roaming_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	bool act;
-	struct net_device *ndev = NULL;
-	s32 err = 0;
-	u32 event = be32_to_cpu(e->event_type);
-	u32 status = be32_to_cpu(e->status);
-#ifdef DHD_LOSSLESS_ROAMING
-	struct wl_security *sec;
-#endif
-	WL_DBG(("Enter \n"));
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	if ((!cfg->disable_roam_event) && (event == WLC_E_BSSID)) {
-		wl_add_remove_eventmsg(ndev, WLC_E_ROAM, false);
-		cfg->disable_roam_event = TRUE;
-	}
-
-	if ((cfg->disable_roam_event) && (event == WLC_E_ROAM))
-		return err;
-
-	if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status == WLC_E_STATUS_SUCCESS) {
-		if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
-#ifdef DHD_LOSSLESS_ROAMING
-			if (cfg->roam_offload) {
-				wl_bss_roaming_done(cfg, ndev, e, data);
-				wl_del_roam_timeout(cfg);
-			}
-			else {
-				sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
-				/* In order to reduce roaming delay, wl_bss_roaming_done is
-				 * early called with WLC_E_LINK event. It is called from
-				 * here only if WLC_E_LINK event is blocked for specific
-				 * security type.
-				 */
-				if (IS_AKM_SUITE_FT(sec)) {
-					wl_bss_roaming_done(cfg, ndev, e, data);
-				}
-				/* Roam timer is deleted mostly from wl_cfg80211_change_station
-				 * after roaming is finished successfully. We need to delete
-				 * the timer from here only for some security types that aren't
-				 * using wl_cfg80211_change_station to authorize SCB
-				 */
-				if (IS_AKM_SUITE_FT(sec) || IS_AKM_SUITE_CCKM(sec)) {
-					wl_del_roam_timeout(cfg);
-				}
-			}
-#else
-			wl_bss_roaming_done(cfg, ndev, e, data);
-#endif /* DHD_LOSSLESS_ROAMING */
-		} else {
-			wl_bss_connect_done(cfg, ndev, e, data, true);
-		}
-		act = true;
-		wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
-		wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
-	}
-#ifdef DHD_LOSSLESS_ROAMING
-	else if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status != WLC_E_STATUS_SUCCESS) {
-		wl_del_roam_timeout(cfg);
-	}
-#endif
-	return err;
-}
-
-#ifdef QOS_MAP_SET
-/* up range from low to high with up value */
-static bool
-up_table_set(uint8 *up_table, uint8 up, uint8 low, uint8 high)
-{
-	int i;
-
-	if (up > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) {
-		return FALSE;
-	}
-
-	for (i = low; i <= high; i++) {
-		up_table[i] = up;
-	}
-
-	return TRUE;
-}
-
-/* set user priority table */
-static void
-wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie)
-{
-	uint8 len;
-
-	if (up_table == NULL || qos_map_ie == NULL) {
-		return;
-	}
-
-	/* clear table to check table was set or not */
-	memset(up_table, 0xff, UP_TABLE_MAX);
-
-	/* length of QoS Map IE must be 16+n*2, n is number of exceptions */
-	if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID &&
-			(len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH &&
-			(len % 2) == 0) {
-		uint8 *except_ptr = (uint8 *)qos_map_ie->data;
-		uint8 except_len = len - QOS_MAP_FIXED_LENGTH;
-		uint8 *range_ptr = except_ptr + except_len;
-		int i;
-
-		/* fill in ranges */
-		for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) {
-			uint8 low = range_ptr[i];
-			uint8 high = range_ptr[i + 1];
-			if (low == 255 && high == 255) {
-				continue;
-			}
-
-			if (!up_table_set(up_table, i / 2, low, high)) {
-				/* clear the table on failure */
-				memset(up_table, 0xff, UP_TABLE_MAX);
-				return;
-			}
-		}
-
-		/* update exceptions */
-		for (i = 0; i < except_len; i += 2) {
-			uint8 dscp = except_ptr[i];
-			uint8 up = except_ptr[i+1];
-
-			/* exceptions with invalid dscp/up are ignored */
-			up_table_set(up_table, up, dscp, dscp);
-		}
-	}
-
-	if (wl_dbg_level & WL_DBG_DBG) {
-		prhex("UP table", up_table, UP_TABLE_MAX);
-	}
-}
-
-/* get user priority table */
-uint8 *
-wl_get_up_table(void)
-{
-	return (uint8 *)(g_bcm_cfg->up_table);
-}
-#endif /* QOS_MAP_SET */
-
-#ifdef DHD_LOSSLESS_ROAMING
-static s32
-wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	s32 err = 0;
-	struct wl_security *sec;
-	struct net_device *ndev;
-	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
-	/* Disable Lossless Roaming for specific AKM suite
-	 * Any other AKM suite can be added below if transition time
-	 * is delayed because of Lossless Roaming
-	 * and it causes any certication failure
-	 */
-	if (IS_AKM_SUITE_FT(sec)) {
-		return err;
-	}
-
-	dhdp->dequeue_prec_map = 1 << PRIO_8021D_NC;
-	/* Restore flow control  */
-	dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
-
-	mod_timer(&cfg->roam_timeout, jiffies + msecs_to_jiffies(WL_ROAM_TIMEOUT_MS));
-
-	return err;
-}
-#endif /* DHD_LOSSLESS_ROAMING */
-
-static s32
-wl_notify_idsup_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-		const wl_event_msg_t *e, void *data)
-{
-	s32 err = 0;
-#if defined(WL_VENDOR_EXT_SUPPORT)
-	u32 idsup_status;
-	u32 reason = ntoh32(e->reason);
-	struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
-#endif /* defined(WL_VENDOR_EXT_SUPPORT) */
-
-	if (cfg->roam_offload) {
-#if defined(WL_VENDOR_EXT_SUPPORT)
-		switch (reason) {
-			case WLC_E_SUP_WPA_PSK_TMO:
-				idsup_status = IDSUP_EVENT_4WAY_HANDSHAKE_TIMEOUT;
-				break;
-			case WLC_E_SUP_OTHER:
-				idsup_status = IDSUP_EVENT_SUCCESS;
-				break;
-			default:
-				WL_ERR(("Other type at IDSUP. "
-						"event=%d e->status %d e->reason %d \n",
-						(int)ntoh32(e->event_type), (int)ntoh32(e->status),
-						(int)ntoh32(e->reason)));
-				return err;
-		}
-
-		err = wl_cfgvendor_send_async_event(wiphy, ndev,
-				BRCM_VENDOR_EVENT_IDSUP_STATUS, &idsup_status, sizeof(u32));
-#endif /* defined(WL_VENDOR_EXT_SUPPORT) */
-	}
-	return err;
-}
-
-#ifdef CUSTOM_EVENT_PM_WAKE
-static s32
-wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-		const wl_event_msg_t *e, void *data)
-{
-	s32 err = 0;
-	struct net_device *ndev = NULL;
-	u8 *pbuf = NULL;
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	pbuf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
-	if (pbuf == NULL) {
-		WL_ERR(("failed to allocate local pbuf\n"));
-		return -ENOMEM;
-	}
-
-	err = wldev_iovar_getbuf_bsscfg(ndev, "dump",
-		"pm", strlen("pm"), pbuf, WLC_IOCTL_MEDLEN, 0, &cfg->ioctl_buf_sync);
-
-	if (err) {
-		WL_ERR(("dump ioctl err = %d", err));
-	} else {
-		WL_ERR(("PM status : %s\n", pbuf));
-	}
-
-	if (pbuf) {
-		kfree(pbuf);
-	}
-	return err;
-}
-#endif /* CUSTOM_EVENT_PM_WAKE */
-
-static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev)
-{
-	wl_assoc_info_t assoc_info;
-	struct wl_connect_info *conn_info = wl_to_conn(cfg);
-	s32 err = 0;
-#ifdef QOS_MAP_SET
-	bcm_tlv_t * qos_map_ie = NULL;
-#endif /* QOS_MAP_SET */
-
-	WL_DBG(("Enter \n"));
-	err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, cfg->extra_buf,
-		WL_ASSOC_INFO_MAX, NULL);
-	if (unlikely(err)) {
-		WL_ERR(("could not get assoc info (%d)\n", err));
-		return err;
-	}
-	memcpy(&assoc_info, cfg->extra_buf, sizeof(wl_assoc_info_t));
-	assoc_info.req_len = htod32(assoc_info.req_len);
-	assoc_info.resp_len = htod32(assoc_info.resp_len);
-	assoc_info.flags = htod32(assoc_info.flags);
-	if (conn_info->req_ie_len) {
-		conn_info->req_ie_len = 0;
-		bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
-	}
-	if (conn_info->resp_ie_len) {
-		conn_info->resp_ie_len = 0;
-		bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
-	}
-	if (assoc_info.req_len) {
-		err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, cfg->extra_buf,
-			WL_ASSOC_INFO_MAX, NULL);
-		if (unlikely(err)) {
-			WL_ERR(("could not get assoc req (%d)\n", err));
-			return err;
-		}
-		conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
-		if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
-			conn_info->req_ie_len -= ETHER_ADDR_LEN;
-		}
-		if (conn_info->req_ie_len <= MAX_REQ_LINE)
-			memcpy(conn_info->req_ie, cfg->extra_buf, conn_info->req_ie_len);
-		else {
-			WL_ERR(("IE size %d above max %d size \n",
-				conn_info->req_ie_len, MAX_REQ_LINE));
-			return err;
-		}
-	} else {
-		conn_info->req_ie_len = 0;
-	}
-	if (assoc_info.resp_len) {
-		err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, cfg->extra_buf,
-			WL_ASSOC_INFO_MAX, NULL);
-		if (unlikely(err)) {
-			WL_ERR(("could not get assoc resp (%d)\n", err));
-			return err;
-		}
-		conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
-		if (conn_info->resp_ie_len <= MAX_REQ_LINE) {
-			memcpy(conn_info->resp_ie, cfg->extra_buf, conn_info->resp_ie_len);
-		} else {
-			WL_ERR(("IE size %d above max %d size \n",
-				conn_info->resp_ie_len, MAX_REQ_LINE));
-			return err;
-		}
-
-#ifdef QOS_MAP_SET
-		/* find qos map set ie */
-		if ((qos_map_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
-				DOT11_MNG_QOS_MAP_ID)) != NULL) {
-			WL_DBG((" QoS map set IE found in assoc response\n"));
-			if (!cfg->up_table) {
-				cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
-			}
-			wl_set_up_table(cfg->up_table, qos_map_ie);
-		} else {
-			kfree(cfg->up_table);
-			cfg->up_table = NULL;
-		}
-#endif /* QOS_MAP_SET */
-	} else {
-		conn_info->resp_ie_len = 0;
-	}
-	WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
-		conn_info->resp_ie_len));
-
-	return err;
-}
-
-static s32 wl_ch_to_chanspec(struct net_device *dev, int ch, struct wl_join_params *join_params,
-        size_t *join_params_size)
-{
-	struct bcm_cfg80211 *cfg;
-	s32 bssidx = -1;
-	chanspec_t chanspec = 0, chspec;
-
-	if (ch != 0) {
-		cfg = (struct bcm_cfg80211 *)wiphy_priv(dev->ieee80211_ptr->wiphy);
-		if (cfg && cfg->rcc_enabled) {
-		} else {
-			join_params->params.chanspec_num = 1;
-			join_params->params.chanspec_list[0] = ch;
-
-			if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
-				chanspec |= WL_CHANSPEC_BAND_2G;
-			else
-				chanspec |= WL_CHANSPEC_BAND_5G;
-
-			/* Get the min_bw set for the interface */
-			chspec = wl_cfg80211_ulb_get_min_bw_chspec(dev->ieee80211_ptr, bssidx);
-			if (chspec == INVCHANSPEC) {
-				WL_ERR(("Invalid chanspec \n"));
-				return -EINVAL;
-			}
-			chanspec |= chspec;
-			chanspec |= WL_CHANSPEC_CTL_SB_NONE;
-
-			*join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
-				join_params->params.chanspec_num * sizeof(chanspec_t);
-
-			join_params->params.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
-			join_params->params.chanspec_list[0] |= chanspec;
-			join_params->params.chanspec_list[0] =
-				wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
-
-			join_params->params.chanspec_num =
-				htod32(join_params->params.chanspec_num);
-		}
-
-		WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
-			join_params->params.chanspec_list[0],
-			join_params->params.chanspec_num));
-	}
-	return 0;
-}
-
-static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam)
-{
-	struct wl_bss_info *bi;
-	struct wlc_ssid *ssid;
-	struct bcm_tlv *tim;
-	s32 beacon_interval;
-	s32 dtim_period;
-	size_t ie_len;
-	u8 *ie;
-	u8 *curbssid;
-	s32 err = 0;
-	struct wiphy *wiphy;
-	u32 channel;
-
-	wiphy = bcmcfg_to_wiphy(cfg);
-
-	ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
-	curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
-
-	mutex_lock(&cfg->usr_sync);
-
-	*(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
-	err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
-		cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
-	if (unlikely(err)) {
-		WL_ERR(("Could not get bss info %d\n", err));
-		goto update_bss_info_out;
-	}
-	bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
-	channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
-	wl_update_prof(cfg, ndev, NULL, &channel, WL_PROF_CHAN);
-
-	if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
-		WL_ERR(("Bssid doesn't match\n"));
-		err = -EIO;
-		goto update_bss_info_out;
-	}
-	err = wl_inform_single_bss(cfg, bi, roam);
-	if (unlikely(err))
-		goto update_bss_info_out;
-
-	ie = ((u8 *)bi) + bi->ie_offset;
-	ie_len = bi->ie_length;
-	beacon_interval = cpu_to_le16(bi->beacon_period);
-	tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
-	if (tim) {
-		dtim_period = tim->data[1];
-	} else {
-		/*
-		* active scan was done so we could not get dtim
-		* information out of probe response.
-		* so we speficially query dtim information.
-		*/
-		err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
-			&dtim_period, sizeof(dtim_period), false);
-		if (unlikely(err)) {
-			WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
-			goto update_bss_info_out;
-		}
-	}
-
-	wl_update_prof(cfg, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
-	wl_update_prof(cfg, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
-
-update_bss_info_out:
-	if (unlikely(err)) {
-		WL_ERR(("Failed with error %d\n", err));
-	}
-	mutex_unlock(&cfg->usr_sync);
-	return err;
-}
-
-static s32
-wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, void *data)
-{
-	struct wl_connect_info *conn_info = wl_to_conn(cfg);
-	s32 err = 0;
-	u8 *curbssid;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
-	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
-	struct ieee80211_supported_band *band;
-	struct ieee80211_channel *notify_channel = NULL;
-	u32 *channel;
-	u32 freq;
-#endif 
-
-
-	if (memcmp(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN) == 0) {
-		WL_INFORM(("BSSID already updated\n"));
-		return err;
-	}
-
-	/* Skip calling cfg80211_roamed If current bssid and
-	 * roamed bssid are same. Also clear timer roam_timeout.
-	 */
-	curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
-	if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) {
-		WL_ERR(("BSS already present, Skipping roamed event to upper layer\n"));
-#ifdef DHD_LOSSLESS_ROAMING
-		wl_del_roam_timeout(cfg);
-#endif  /* DHD_LOSSLESS_ROAMING */
-		return  err;
-	}
-
-	wl_get_assoc_ies(cfg, ndev);
-	wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet), WL_PROF_BSSID);
-	curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
-	wl_update_bss_info(cfg, ndev, true);
-	wl_update_pmklist(ndev, cfg->pmk_list, err);
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
-	/* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
-	channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
-	if (*channel <= CH_MAX_2G_CHANNEL)
-		band = wiphy->bands[IEEE80211_BAND_2GHZ];
-	else
-		band = wiphy->bands[IEEE80211_BAND_5GHZ];
-	freq = ieee80211_channel_to_frequency(*channel, band->band);
-	notify_channel = ieee80211_get_channel(wiphy, freq);
-#endif 
-	WL_ERR(("wl_bss_roaming_done succeeded to " MACDBG "\n",
-		MAC2STRDBG((const u8*)(&e->addr))));
-
-	cfg80211_roamed(ndev,
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
-		notify_channel,
-#endif
-		curbssid,
-		conn_info->req_ie, conn_info->req_ie_len,
-		conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
-	WL_DBG(("Report roaming result\n"));
-
-	memcpy(&cfg->last_roamed_addr, (void *)&e->addr, ETHER_ADDR_LEN);
-	wl_set_drv_status(cfg, CONNECTED, ndev);
-
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-	cfg->roam_count++;
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-
-	return err;
-}
-
-static s32
-wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, void *data, bool completed)
-{
-	struct wl_connect_info *conn_info = wl_to_conn(cfg);
-	struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
-#if defined(CUSTOM_SET_CPUCORE)
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-#endif 
-	s32 err = 0;
-	u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
-	if (!sec) {
-		WL_ERR(("sec is NULL\n"));
-		return -ENODEV;
-	}
-	WL_DBG((" enter\n"));
-#ifdef ESCAN_RESULT_PATCH
-	if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
-		if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
-			WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
-				ntoh32(e->event_type), ntoh32(e->status)));
-			return err;
-		}
-	}
-	if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
-		memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
-		WL_DBG(("copy bssid\n"));
-		memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
-	}
-
-#else
-	if (cfg->scan_request) {
-		wl_notify_escan_complete(cfg, ndev, true, true);
-	}
-#endif /* ESCAN_RESULT_PATCH */
-	if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
-		wl_cfg80211_scan_abort(cfg);
-		wl_clr_drv_status(cfg, CONNECTING, ndev);
-		if (completed) {
-			wl_get_assoc_ies(cfg, ndev);
-			wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet),
-				WL_PROF_BSSID);
-			curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
-			wl_update_bss_info(cfg, ndev, false);
-			wl_update_pmklist(ndev, cfg->pmk_list, err);
-			wl_set_drv_status(cfg, CONNECTED, ndev);
-			if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
-				init_completion(&cfg->iface_disable);
-#else
-				/* reinitialize completion to clear previous count */
-				INIT_COMPLETION(cfg->iface_disable);
-#endif
-			}
-#ifdef CUSTOM_SET_CPUCORE
-			if (wl_get_chan_isvht80(ndev, dhd)) {
-				if (ndev == bcmcfg_to_prmry_ndev(cfg))
-					dhd->chan_isvht80 |= DHD_FLAG_STA_MODE; /* STA mode */
-				else if (is_p2p_group_iface(ndev->ieee80211_ptr))
-					dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE; /* p2p mode */
-				dhd_set_cpucore(dhd, TRUE);
-			}
-#endif /* CUSTOM_SET_CPUCORE */
-
-		}
-		cfg80211_connect_result(ndev,
-			curbssid,
-			conn_info->req_ie,
-			conn_info->req_ie_len,
-			conn_info->resp_ie,
-			conn_info->resp_ie_len,
-			completed ? WLAN_STATUS_SUCCESS :
-			(sec->auth_assoc_res_status) ?
-			sec->auth_assoc_res_status :
-			WLAN_STATUS_UNSPECIFIED_FAILURE,
-			GFP_KERNEL);
-		if (completed)
-			WL_INFORM(("Report connect result - connection succeeded\n"));
-		else
-			WL_ERR(("Report connect result - connection failed\n"));
-	}
-#ifdef CONFIG_TCPACK_FASTTX
-	if (wl_get_chan_isvht80(ndev, dhd))
-		wldev_iovar_setint(ndev, "tcpack_fast_tx", 0);
-	else
-		wldev_iovar_setint(ndev, "tcpack_fast_tx", 1);
-#endif /* CONFIG_TCPACK_FASTTX */
-
-	return err;
-}
-
-static s32
-wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	struct net_device *ndev = NULL;
-	u16 flags = ntoh16(e->flags);
-	enum nl80211_key_type key_type;
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	mutex_lock(&cfg->usr_sync);
-	if (flags & WLC_EVENT_MSG_GROUP)
-		key_type = NL80211_KEYTYPE_GROUP;
-	else
-		key_type = NL80211_KEYTYPE_PAIRWISE;
-
-	cfg80211_michael_mic_failure(ndev, (const u8 *)&e->addr, key_type, -1,
-		NULL, GFP_KERNEL);
-	mutex_unlock(&cfg->usr_sync);
-
-	return 0;
-}
-
-#ifdef BT_WIFI_HANDOVER
-static s32
-wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	struct net_device *ndev = NULL;
-	u32 event = ntoh32(e->event_type);
-	u32 datalen = ntoh32(e->datalen);
-	s32 err;
-
-	WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event, datalen));
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-	err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
-
-	return err;
-}
-#endif /* BT_WIFI_HANDOVER */
-
-#ifdef PNO_SUPPORT
-static s32
-wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	struct net_device *ndev = NULL;
-
-	WL_ERR((">>> PNO Event\n"));
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-#ifndef WL_SCHED_SCAN
-	mutex_lock(&cfg->usr_sync);
-	/* TODO: Use cfg80211_sched_scan_results(wiphy); */
-	CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
-	mutex_unlock(&cfg->usr_sync);
-#else
-	/* If cfg80211 scheduled scan is supported, report the pno results via sched
-	 * scan results
-	 */
-	wl_notify_sched_scan_results(cfg, ndev, e, data);
-#endif /* WL_SCHED_SCAN */
-	return 0;
-}
-#endif /* PNO_SUPPORT */
-
-#ifdef GSCAN_SUPPORT
-static s32
-wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	s32 err = 0;
-	u32 event = be32_to_cpu(e->event_type);
-	void *ptr;
-	int send_evt_bytes = 0;
-	int batch_event_result_dummy = 0;
-	struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
-	u32 len = ntoh32(e->datalen);
-
-	switch (event) {
-		case WLC_E_PFN_SWC:
-			ptr = dhd_dev_swc_scan_event(ndev, data, &send_evt_bytes);
-			if (send_evt_bytes) {
-				wl_cfgvendor_send_async_event(wiphy, ndev,
-				    GOOGLE_GSCAN_SIGNIFICANT_EVENT, ptr, send_evt_bytes);
-				kfree(ptr);
-			}
-			break;
-		case WLC_E_PFN_BEST_BATCHING:
-			err = dhd_dev_retrieve_batch_scan(ndev);
-			if (err < 0) {
-				WL_ERR(("Batch retrieval already in progress %d\n", err));
-			} else {
-				wl_cfgvendor_send_async_event(wiphy, ndev,
-				    GOOGLE_GSCAN_BATCH_SCAN_EVENT,
-				     &batch_event_result_dummy, sizeof(int));
-			}
-			break;
-		case WLC_E_PFN_SCAN_COMPLETE:
-			batch_event_result_dummy = WIFI_SCAN_COMPLETE;
-			wl_cfgvendor_send_async_event(wiphy, ndev,
-				GOOGLE_SCAN_COMPLETE_EVENT,
-				&batch_event_result_dummy, sizeof(int));
-			break;
-		case WLC_E_PFN_BSSID_NET_FOUND:
-			ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
-			      HOTLIST_FOUND);
-			if (ptr) {
-				wl_cfgvendor_send_hotlist_event(wiphy, ndev,
-				 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT);
-				dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_FOUND);
-			}
-			break;
-		case WLC_E_PFN_BSSID_NET_LOST:
-			/* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
-			 * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
-			 */
-			if (len) {
-				ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
-				            HOTLIST_LOST);
-				if (ptr) {
-					wl_cfgvendor_send_hotlist_event(wiphy, ndev,
-					 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT);
-					dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_LOST);
-				}
-			}
-			break;
-		case WLC_E_PFN_GSCAN_FULL_RESULT:
-			ptr = dhd_dev_process_full_gscan_result(ndev, data, &send_evt_bytes);
-			if (ptr) {
-				wl_cfgvendor_send_async_event(wiphy, ndev,
-				    GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes);
-				kfree(ptr);
-			}
-			break;
-		default:
-			WL_ERR(("%s: Unexpected event! - %d\n", __FUNCTION__, event));
-
-	}
-	return err;
-}
-#endif /* GSCAN_SUPPORT */
-
-static s32
-wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	struct channel_info channel_inform;
-	struct wl_scan_results *bss_list;
-	struct net_device *ndev = NULL;
-	u32 len = WL_SCAN_BUF_MAX;
-	s32 err = 0;
-	unsigned long flags;
-
-	WL_DBG(("Enter \n"));
-	if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
-		WL_ERR(("scan is not ready \n"));
-		return err;
-	}
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	mutex_lock(&cfg->usr_sync);
-	wl_clr_drv_status(cfg, SCANNING, ndev);
-	err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
-		sizeof(channel_inform), false);
-	if (unlikely(err)) {
-		WL_ERR(("scan busy (%d)\n", err));
-		goto scan_done_out;
-	}
-	channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
-	if (unlikely(channel_inform.scan_channel)) {
-
-		WL_DBG(("channel_inform.scan_channel (%d)\n",
-			channel_inform.scan_channel));
-	}
-	cfg->bss_list = cfg->scan_results;
-	bss_list = cfg->bss_list;
-	memset(bss_list, 0, len);
-	bss_list->buflen = htod32(len);
-	err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
-	if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
-		WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
-		err = -EINVAL;
-		goto scan_done_out;
-	}
-	bss_list->buflen = dtoh32(bss_list->buflen);
-	bss_list->version = dtoh32(bss_list->version);
-	bss_list->count = dtoh32(bss_list->count);
-
-	err = wl_inform_bss(cfg);
-
-scan_done_out:
-	del_timer_sync(&cfg->scan_timeout);
-	spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
-	if (cfg->scan_request) {
-		cfg80211_scan_done(cfg->scan_request, false);
-		cfg->scan_request = NULL;
-	}
-	spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
-	WL_DBG(("cfg80211_scan_done\n"));
-	mutex_unlock(&cfg->usr_sync);
-	return err;
-}
-
-static s32
-wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
-	const struct ether_addr *sa, const struct ether_addr *bssid,
-	u8 **pheader, u32 *body_len, u8 *pbody)
-{
-	struct dot11_management_header *hdr;
-	u32 totlen = 0;
-	s32 err = 0;
-	u8 *offset;
-	u32 prebody_len = *body_len;
-	switch (fc) {
-		case FC_ASSOC_REQ:
-			/* capability , listen interval */
-			totlen = DOT11_ASSOC_REQ_FIXED_LEN;
-			*body_len += DOT11_ASSOC_REQ_FIXED_LEN;
-			break;
-
-		case FC_REASSOC_REQ:
-			/* capability, listen inteval, ap address */
-			totlen = DOT11_REASSOC_REQ_FIXED_LEN;
-			*body_len += DOT11_REASSOC_REQ_FIXED_LEN;
-			break;
-	}
-	totlen += DOT11_MGMT_HDR_LEN + prebody_len;
-	*pheader = kzalloc(totlen, GFP_KERNEL);
-	if (*pheader == NULL) {
-		WL_ERR(("memory alloc failed \n"));
-		return -ENOMEM;
-	}
-	hdr = (struct dot11_management_header *) (*pheader);
-	hdr->fc = htol16(fc);
-	hdr->durid = 0;
-	hdr->seq = 0;
-	offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
-	bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
-	bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
-	bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
-	if ((pbody != NULL) && prebody_len)
-		bcopy((const char*)pbody, offset, prebody_len);
-	*body_len = totlen;
-	return err;
-}
-
-
-void
-wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev)
-{
-	if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
-		if (timer_pending(&cfg->p2p->listen_timer)) {
-			del_timer_sync(&cfg->p2p->listen_timer);
-		}
-		if (cfg->afx_hdl != NULL) {
-			if (cfg->afx_hdl->dev != NULL) {
-				wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
-				wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, cfg->afx_hdl->dev);
-			}
-			cfg->afx_hdl->peer_chan = WL_INVALID;
-		}
-		complete(&cfg->act_frm_scan);
-		WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
-	} else if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
-		if (!(wl_get_p2p_status(cfg, ACTION_TX_COMPLETED) ||
-			wl_get_p2p_status(cfg, ACTION_TX_NOACK)))
-			wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
-
-		WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
-		/* if channel is not zero, "actfame" uses off channel scan.
-		 * So abort scan for off channel completion.
-		 */
-		if (cfg->af_sent_channel)
-			wl_cfg80211_scan_abort(cfg);
-	}
-#ifdef WL_CFG80211_SYNC_GON
-	else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
-		WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
-		/* So abort scan to cancel listen */
-		wl_cfg80211_scan_abort(cfg);
-	}
-#endif /* WL_CFG80211_SYNC_GON */
-}
-
-#if defined(WLTDLS)
-bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len)
-{
-	unsigned char *data;
-
-	if (frame == NULL) {
-		WL_ERR(("Invalid frame \n"));
-		return false;
-	}
-
-	if (frame_len < 5) {
-		WL_ERR(("Invalid frame length [%d] \n", frame_len));
-		return false;
-	}
-
-	data = frame;
-
-	if (!memcmp(data, TDLS_TUNNELED_PRB_REQ, 5) ||
-		!memcmp(data, TDLS_TUNNELED_PRB_RESP, 5)) {
-		WL_DBG(("TDLS Vendor Specific Received type\n"));
-		return true;
-	}
-
-	return false;
-}
-#endif /* WLTDLS */
-
-
-int wl_cfg80211_get_ioctl_version(void)
-{
-	return ioctl_version;
-}
-
-static s32
-wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	struct ieee80211_supported_band *band;
-	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
-	struct ether_addr da;
-	struct ether_addr bssid;
-	bool isfree = false;
-	s32 err = 0;
-	s32 freq;
-	struct net_device *ndev = NULL;
-	wifi_p2p_pub_act_frame_t *act_frm = NULL;
-	wifi_p2p_action_frame_t *p2p_act_frm = NULL;
-	wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
-#if defined(WLTDLS) && defined(TDLS_MSG_ONLY_WFD)
-	dhd_pub_t *dhdp;
-#endif /* WLTDLS && TDLS_MSG_ONLY_WFD */
-	wl_event_rx_frame_data_t *rxframe =
-		(wl_event_rx_frame_data_t*)data;
-	u32 event = ntoh32(e->event_type);
-	u8 *mgmt_frame;
-	u8 bsscfgidx = e->bsscfgidx;
-	u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
-	u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
-
-	memset(&bssid, 0, ETHER_ADDR_LEN);
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	if (channel <= CH_MAX_2G_CHANNEL)
-		band = wiphy->bands[IEEE80211_BAND_2GHZ];
-	else
-		band = wiphy->bands[IEEE80211_BAND_5GHZ];
-	if (!band) {
-		WL_ERR(("No valid band"));
-		return -EINVAL;
-	}
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
-	freq = ieee80211_channel_to_frequency(channel);
-	(void)band->band;
-#else
-	freq = ieee80211_channel_to_frequency(channel, band->band);
-#endif
-	if (event == WLC_E_ACTION_FRAME_RX) {
-		wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
-			NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
-
-		err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
-		if (err < 0)
-			 WL_ERR(("WLC_GET_BSSID error %d\n", err));
-		memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
-		err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
-			&mgmt_frame, &mgmt_frame_len,
-			(u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
-		if (err < 0) {
-			WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
-				mgmt_frame_len, channel, freq));
-			goto exit;
-		}
-		isfree = true;
-		if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
-			mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
-			act_frm = (wifi_p2p_pub_act_frame_t *)
-					(&mgmt_frame[DOT11_MGMT_HDR_LEN]);
-		} else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
-			mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
-			p2p_act_frm = (wifi_p2p_action_frame_t *)
-					(&mgmt_frame[DOT11_MGMT_HDR_LEN]);
-			(void) p2p_act_frm;
-		} else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
-			mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
-
-			sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
-					(&mgmt_frame[DOT11_MGMT_HDR_LEN]);
-			if (sd_act_frm && wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
-				if (cfg->next_af_subtype == sd_act_frm->action) {
-					WL_DBG(("We got a right next frame of SD!(%d)\n",
-						sd_act_frm->action));
-					wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
-
-					/* Stop waiting for next AF. */
-					wl_stop_wait_next_action_frame(cfg, ndev);
-				}
-			}
-			(void) sd_act_frm;
-#ifdef WLTDLS
-		} else if ((mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) ||
-				(wl_cfg80211_is_tdls_tunneled_frame(
-				    &mgmt_frame[DOT11_MGMT_HDR_LEN],
-				    mgmt_frame_len - DOT11_MGMT_HDR_LEN))) {
-			if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) {
-				WL_ERR((" TDLS Action Frame Received type = %d \n",
-					mgmt_frame[DOT11_MGMT_HDR_LEN + 1]));
-			}
-#ifdef TDLS_MSG_ONLY_WFD
-			dhdp = (dhd_pub_t *)(cfg->pub);
-			if (!dhdp->tdls_mode) {
-				WL_DBG((" TDLS Frame filtered \n"));
-				return 0;
-			}
-#else
-			if (mgmt_frame[DOT11_MGMT_HDR_LEN + 1] == TDLS_ACTION_SETUP_RESP) {
-				cfg->tdls_mgmt_frame = mgmt_frame;
-				cfg->tdls_mgmt_frame_len = mgmt_frame_len;
-				cfg->tdls_mgmt_freq = freq;
-				return 0;
-			}
-#endif /* TDLS_MSG_ONLY_WFD */
-#endif /* WLTDLS */
-#ifdef QOS_MAP_SET
-		} else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_QOS) {
-			/* update QoS map set table */
-			bcm_tlv_t * qos_map_ie = NULL;
-			if ((qos_map_ie = bcm_parse_tlvs(&mgmt_frame[DOT11_MGMT_HDR_LEN],
-					mgmt_frame_len - DOT11_MGMT_HDR_LEN,
-					DOT11_MNG_QOS_MAP_ID)) != NULL) {
-				WL_DBG((" QoS map set IE found in QoS action frame\n"));
-				if (!cfg->up_table) {
-					cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
-				}
-				wl_set_up_table(cfg->up_table, qos_map_ie);
-			} else {
-				kfree(cfg->up_table);
-				cfg->up_table = NULL;
-			}
-#endif /* QOS_MAP_SET */
-		} else {
-			/*
-			 *  if we got normal action frame and ndev is p2p0,
-			 *  we have to change ndev from p2p0 to wlan0
-			 */
-
-
-			if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
-				u8 action = 0;
-				if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
-					mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
-					WL_DBG(("Recived action is not public action frame\n"));
-				} else if (cfg->next_af_subtype == action) {
-					WL_DBG(("Recived action is the waiting action(%d)\n",
-						action));
-					wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
-
-					/* Stop waiting for next AF. */
-					wl_stop_wait_next_action_frame(cfg, ndev);
-				}
-			}
-		}
-
-		if (act_frm) {
-
-			if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
-				if (cfg->next_af_subtype == act_frm->subtype) {
-					WL_DBG(("We got a right next frame!(%d)\n",
-						act_frm->subtype));
-					wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
-
-					if (cfg->next_af_subtype == P2P_PAF_GON_CONF) {
-						OSL_SLEEP(20);
-					}
-
-					/* Stop waiting for next AF. */
-					wl_stop_wait_next_action_frame(cfg, ndev);
-				}
-			}
-		}
-
-		wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
-			mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
-		/*
-		 * After complete GO Negotiation, roll back to mpc mode
-		 */
-		if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
-			(act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
-			wldev_iovar_setint(ndev, "mpc", 1);
-		}
-		if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
-			WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
-			wl_clr_p2p_status(cfg, GO_NEG_PHASE);
-		}
-	} else if (event == WLC_E_PROBREQ_MSG) {
-
-		/* Handle probe reqs frame
-		 * WPS-AP certification 4.2.13
-		 */
-		struct parsed_ies prbreq_ies;
-		u32 prbreq_ie_len = 0;
-		bool pbc = 0;
-
-		WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
-		mgmt_frame = (u8 *)(data);
-		mgmt_frame_len = ntoh32(e->datalen);
-
-		prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN;
-
-		/* Parse prob_req IEs */
-		if (wl_cfg80211_parse_ies(&mgmt_frame[DOT11_MGMT_HDR_LEN],
-			prbreq_ie_len, &prbreq_ies) < 0) {
-			WL_ERR(("Prob req get IEs failed\n"));
-			return 0;
-		}
-		if (prbreq_ies.wps_ie != NULL) {
-			wl_validate_wps_ie((char *)prbreq_ies.wps_ie, prbreq_ies.wps_ie_len, &pbc);
-			WL_DBG((" wps_ie exist pbc = %d\n", pbc));
-			/* if pbc method, send prob_req mgmt frame to upper layer */
-			if (!pbc)
-				return 0;
-		} else
-			return 0;
-	} else {
-		mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
-
-		/* wpa supplicant use probe request event for restarting another GON Req.
-		 * but it makes GON Req repetition.
-		 * so if src addr of prb req is same as my target device,
-		 * do not send probe request event during sending action frame.
-		 */
-		if (event == WLC_E_P2P_PROBREQ_MSG) {
-			WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
-				"WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
-
-
-			/* Filter any P2P probe reqs arriving during the
-			 * GO-NEG Phase
-			 */
-			if (cfg->p2p &&
-#if defined(P2P_IE_MISSING_FIX)
-				cfg->p2p_prb_noti &&
-#endif
-				wl_get_p2p_status(cfg, GO_NEG_PHASE)) {
-				WL_DBG(("Filtering P2P probe_req while "
-					"being in GO-Neg state\n"));
-				return 0;
-			}
-		}
-	}
-
-	if (discover_cfgdev(cfgdev, cfg))
-		WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
-	else
-		WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev->name));
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-	cfg80211_rx_mgmt(cfgdev, freq, 0,  mgmt_frame, mgmt_frame_len, 0);
-#elif(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
-	cfg80211_rx_mgmt(cfgdev, freq, 0,  mgmt_frame, mgmt_frame_len, 0, GFP_ATOMIC);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
-	defined(WL_COMPAT_WIRELESS)
-	cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
-#else
-	cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
-#endif /* LINUX_VERSION >= VERSION(3, 14, 0) */
-
-	WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
-		mgmt_frame_len, ntoh32(e->datalen), channel, freq));
-exit:
-	if (isfree)
-		kfree(mgmt_frame);
-	return 0;
-}
-
-#ifdef WL_SCHED_SCAN
-/* If target scan is not reliable, set the below define to "1" to do a
- * full escan
- */
-#define FULL_ESCAN_ON_PFN_NET_FOUND		0
-static s32
-wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, void *data)
-{
-	wl_pfn_net_info_t *netinfo, *pnetinfo;
-	struct wiphy *wiphy	= bcmcfg_to_wiphy(cfg);
-	int err = 0;
-	struct cfg80211_scan_request *request = NULL;
-	struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
-	struct ieee80211_channel *channel = NULL;
-	int channel_req = 0;
-	int band = 0;
-	struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
-	int n_pfn_results = pfn_result->count;
-
-	WL_DBG(("Enter\n"));
-
-	if (e->event_type == WLC_E_PFN_NET_LOST) {
-		WL_PNO(("PFN NET LOST event. Do Nothing \n"));
-		return 0;
-	}
-	WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
-	if (n_pfn_results > 0) {
-		int i;
-
-		if (n_pfn_results > MAX_PFN_LIST_COUNT)
-			n_pfn_results = MAX_PFN_LIST_COUNT;
-		pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
-				- sizeof(wl_pfn_net_info_t));
-
-		memset(&ssid, 0x00, sizeof(ssid));
-
-		request = kzalloc(sizeof(*request)
-			+ sizeof(*request->channels) * n_pfn_results,
-			GFP_KERNEL);
-		channel = (struct ieee80211_channel *)kzalloc(
-			(sizeof(struct ieee80211_channel) * n_pfn_results),
-			GFP_KERNEL);
-		if (!request || !channel) {
-			WL_ERR(("No memory"));
-			err = -ENOMEM;
-			goto out_err;
-		}
-
-		request->wiphy = wiphy;
-
-		for (i = 0; i < n_pfn_results; i++) {
-			netinfo = &pnetinfo[i];
-			if (!netinfo) {
-				WL_ERR(("Invalid netinfo ptr. index:%d", i));
-				err = -EINVAL;
-				goto out_err;
-			}
-			WL_PNO((">>> SSID:%s Channel:%d \n",
-				netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
-			/* PFN result doesn't have all the info which are required by the supplicant
-			 * (For e.g IEs) Do a target Escan so that sched scan results are reported
-			 * via wl_inform_single_bss in the required format. Escan does require the
-			 * scan request in the form of cfg80211_scan_request. For timebeing, create
-			 * cfg80211_scan_request one out of the received PNO event.
-			 */
-			ssid[i].ssid_len = MIN(DOT11_MAX_SSID_LEN, netinfo->pfnsubnet.SSID_len);
-			memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
-			       ssid[i].ssid_len);
-			request->n_ssids++;
-
-			channel_req = netinfo->pfnsubnet.channel;
-			band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
-				: NL80211_BAND_5GHZ;
-			channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
-			channel[i].band = band;
-			channel[i].flags |= IEEE80211_CHAN_NO_HT40;
-			request->channels[i] = &channel[i];
-			request->n_channels++;
-		}
-
-		/* assign parsed ssid array */
-		if (request->n_ssids)
-			request->ssids = &ssid[0];
-
-		if (wl_get_drv_status_all(cfg, SCANNING)) {
-			/* Abort any on-going scan */
-			wl_notify_escan_complete(cfg, ndev, true, true);
-		}
-
-		if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
-			WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
-			err = wl_cfgp2p_discover_enable_search(cfg, false);
-			if (unlikely(err)) {
-				wl_clr_drv_status(cfg, SCANNING, ndev);
-				goto out_err;
-			}
-			p2p_scan(cfg) = false;
-		}
-
-		wl_set_drv_status(cfg, SCANNING, ndev);
-#if FULL_ESCAN_ON_PFN_NET_FOUND
-		WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
-		err = wl_do_escan(cfg, wiphy, ndev, NULL);
-#else
-		WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
-		err = wl_do_escan(cfg, wiphy, ndev, request);
-#endif
-		if (err) {
-			wl_clr_drv_status(cfg, SCANNING, ndev);
-			goto out_err;
-		}
-		cfg->sched_scan_running = TRUE;
-	}
-	else {
-		WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
-	}
-out_err:
-	if (request)
-		kfree(request);
-	if (channel)
-		kfree(channel);
-	return err;
-}
-#endif /* WL_SCHED_SCAN */
-
-static void wl_init_conf(struct wl_conf *conf)
-{
-	WL_DBG(("Enter \n"));
-	conf->frag_threshold = (u32)-1;
-	conf->rts_threshold = (u32)-1;
-	conf->retry_short = (u32)-1;
-	conf->retry_long = (u32)-1;
-	conf->tx_power = -1;
-}
-
-static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev)
-{
-	unsigned long flags;
-	struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
-
-	spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
-	memset(profile, 0, sizeof(struct wl_profile));
-	spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
-}
-
-static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
-{
-	memset(cfg->evt_handler, 0, sizeof(cfg->evt_handler));
-
-	cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
-	cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
-	cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
-	cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
-	cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
-	cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
-	cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
-	cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
-	cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
-	cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
-	cfg->evt_handler[WLC_E_START] = wl_notify_connect_status;
-#ifdef PNO_SUPPORT
-	cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
-#endif /* PNO_SUPPORT */
-#ifdef GSCAN_SUPPORT
-	cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event;
-	cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event;
-	cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event;
-	cfg->evt_handler[WLC_E_PFN_SWC] = wl_notify_gscan_event;
-	cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;
-	cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event;
-#endif /* GSCAN_SUPPORT */
-#ifdef WLTDLS
-	cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
-#endif /* WLTDLS */
-	cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status;
-#ifdef	WL_RELMCAST
-	cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status;
-#endif
-#ifdef BT_WIFI_HANDOVER
-	cfg->evt_handler[WLC_E_BT_WIFI_HANDOVER_REQ] = wl_notify_bt_wifi_handover_req;
-#endif
-#ifdef WL_NAN
-	cfg->evt_handler[WLC_E_NAN] = wl_cfgnan_notify_nan_status;
-	cfg->evt_handler[WLC_E_PROXD] = wl_cfgnan_notify_proxd_status;
-#endif /* WL_NAN */
-	cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind;
-#ifdef DHD_LOSSLESS_ROAMING
-	cfg->evt_handler[WLC_E_ROAM_PREP] = wl_notify_roam_prep_status;
-#endif
-	cfg->evt_handler[WLC_E_AP_STARTED] = wl_ap_start_ind;
-#ifdef CUSTOM_EVENT_PM_WAKE
-	cfg->evt_handler[WLC_E_EXCESS_PM_WAKE_EVENT] = wl_check_pmstatus;
-#endif /* CUSTOM_EVENT_PM_WAKE */
-	cfg->evt_handler[WLC_E_PSK_SUP] = wl_notify_idsup_status;
-}
-
-#if defined(STATIC_WL_PRIV_STRUCT)
-static void
-wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
-{
-	cfg->escan_info.escan_buf = DHD_OS_PREALLOC(cfg->pub,
-		DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
-	bzero(cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
-}
-
-static void
-wl_deinit_escan_result_buf(struct bcm_cfg80211 *cfg)
-{
-	cfg->escan_info.escan_buf = NULL;
-
-}
-#endif /* STATIC_WL_PRIV_STRUCT */
-
-static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg)
-{
-	WL_DBG(("Enter \n"));
-
-	cfg->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
-	if (unlikely(!cfg->scan_results)) {
-		WL_ERR(("Scan results alloc failed\n"));
-		goto init_priv_mem_out;
-	}
-	cfg->conf = (void *)kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
-	if (unlikely(!cfg->conf)) {
-		WL_ERR(("wl_conf alloc failed\n"));
-		goto init_priv_mem_out;
-	}
-	cfg->scan_req_int =
-	    (void *)kzalloc(sizeof(*cfg->scan_req_int), GFP_KERNEL);
-	if (unlikely(!cfg->scan_req_int)) {
-		WL_ERR(("Scan req alloc failed\n"));
-		goto init_priv_mem_out;
-	}
-	cfg->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
-	if (unlikely(!cfg->ioctl_buf)) {
-		WL_ERR(("Ioctl buf alloc failed\n"));
-		goto init_priv_mem_out;
-	}
-	cfg->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
-	if (unlikely(!cfg->escan_ioctl_buf)) {
-		WL_ERR(("Ioctl buf alloc failed\n"));
-		goto init_priv_mem_out;
-	}
-	cfg->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
-	if (unlikely(!cfg->extra_buf)) {
-		WL_ERR(("Extra buf alloc failed\n"));
-		goto init_priv_mem_out;
-	}
-	cfg->pmk_list = (void *)kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
-	if (unlikely(!cfg->pmk_list)) {
-		WL_ERR(("pmk list alloc failed\n"));
-		goto init_priv_mem_out;
-	}
-#if defined(STATIC_WL_PRIV_STRUCT)
-	cfg->conn_info = (void *)kzalloc(sizeof(*cfg->conn_info), GFP_KERNEL);
-	if (unlikely(!cfg->conn_info)) {
-		WL_ERR(("cfg->conn_info  alloc failed\n"));
-		goto init_priv_mem_out;
-	}
-	cfg->ie = (void *)kzalloc(sizeof(*cfg->ie), GFP_KERNEL);
-	if (unlikely(!cfg->ie)) {
-		WL_ERR(("cfg->ie  alloc failed\n"));
-		goto init_priv_mem_out;
-	}
-	wl_init_escan_result_buf(cfg);
-#endif /* STATIC_WL_PRIV_STRUCT */
-	cfg->afx_hdl = (void *)kzalloc(sizeof(*cfg->afx_hdl), GFP_KERNEL);
-	if (unlikely(!cfg->afx_hdl)) {
-		WL_ERR(("afx hdl  alloc failed\n"));
-		goto init_priv_mem_out;
-	} else {
-		init_completion(&cfg->act_frm_scan);
-		init_completion(&cfg->wait_next_af);
-
-		INIT_WORK(&cfg->afx_hdl->work, wl_cfg80211_afx_handler);
-	}
-#ifdef WLTDLS
-	if (cfg->tdls_mgmt_frame) {
-		kfree(cfg->tdls_mgmt_frame);
-		cfg->tdls_mgmt_frame = NULL;
-	}
-#endif /* WLTDLS */
-	return 0;
-
-init_priv_mem_out:
-	wl_deinit_priv_mem(cfg);
-
-	return -ENOMEM;
-}
-
-static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg)
-{
-	kfree(cfg->scan_results);
-	cfg->scan_results = NULL;
-	kfree(cfg->conf);
-	cfg->conf = NULL;
-	kfree(cfg->scan_req_int);
-	cfg->scan_req_int = NULL;
-	kfree(cfg->ioctl_buf);
-	cfg->ioctl_buf = NULL;
-	kfree(cfg->escan_ioctl_buf);
-	cfg->escan_ioctl_buf = NULL;
-	kfree(cfg->extra_buf);
-	cfg->extra_buf = NULL;
-	kfree(cfg->pmk_list);
-	cfg->pmk_list = NULL;
-#if defined(STATIC_WL_PRIV_STRUCT)
-	kfree(cfg->conn_info);
-	cfg->conn_info = NULL;
-	kfree(cfg->ie);
-	cfg->ie = NULL;
-	wl_deinit_escan_result_buf(cfg);
-#endif /* STATIC_WL_PRIV_STRUCT */
-	if (cfg->afx_hdl) {
-		cancel_work_sync(&cfg->afx_hdl->work);
-		kfree(cfg->afx_hdl);
-		cfg->afx_hdl = NULL;
-	}
-
-}
-
-static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg)
-{
-	int ret = 0;
-	WL_DBG(("Enter \n"));
-
-	/* Do not use DHD in cfg driver */
-	cfg->event_tsk.thr_pid = -1;
-
-	PROC_START(wl_event_handler, cfg, &cfg->event_tsk, 0, "wl_event_handler");
-	if (cfg->event_tsk.thr_pid < 0)
-		ret = -ENOMEM;
-	return ret;
-}
-
-static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg)
-{
-	if (cfg->event_tsk.thr_pid >= 0)
-		PROC_STOP(&cfg->event_tsk);
-}
-
-void wl_terminate_event_handler(void)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	if (cfg) {
-		wl_destroy_event_handler(cfg);
-		wl_flush_eq(cfg);
-	}
-}
-
-static void wl_scan_timeout(unsigned long data)
-{
-	wl_event_msg_t msg;
-	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
-	struct wireless_dev *wdev = NULL;
-	struct net_device *ndev = NULL;
-	struct wl_scan_results *bss_list;
-	struct wl_bss_info *bi = NULL;
-	s32 i;
-	u32 channel;
-#if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
-	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
-	uint32 prev_memdump_mode = dhdp->memdump_enabled;
-#endif /* DHD_DEBUG && BCMPCIE */
-
-	if (!(cfg->scan_request)) {
-		WL_ERR(("timer expired but no scan request\n"));
-		return;
-	}
-
-	bss_list = wl_escan_get_buf(cfg, FALSE);
-	if (!bss_list) {
-		WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
-	} else {
-		WL_ERR(("scanned AP count (%d)\n", bss_list->count));
-
-		bi = next_bss(bss_list, bi);
-		for_each_bss(bss_list, bi, i) {
-			channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
-			WL_ERR(("SSID :%s  Channel :%d\n", bi->SSID, channel));
-		}
-	}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
-	if (cfg->scan_request->dev)
-		wdev = cfg->scan_request->dev->ieee80211_ptr;
-#else
-	wdev = cfg->scan_request->wdev;
-#endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
-	if (!wdev) {
-		WL_ERR(("No wireless_dev present\n"));
-		return;
-	}
-	ndev = wdev_to_wlc_ndev(wdev, cfg);
-
-	bzero(&msg, sizeof(wl_event_msg_t));
-	WL_ERR(("timer expired\n"));
-#if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
-	if (dhdp->memdump_enabled) {
-		dhdp->memdump_enabled = DUMP_MEMFILE;
-		dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
-		dhd_bus_mem_dump(dhdp);
-		dhdp->memdump_enabled = prev_memdump_mode;
-	}
-#endif /* DHD_DEBUG && BCMPCIE */
-	msg.event_type = hton32(WLC_E_ESCAN_RESULT);
-	msg.status = hton32(WLC_E_STATUS_TIMEOUT);
-	msg.reason = 0xFFFFFFFF;
-	wl_cfg80211_event(ndev, &msg, NULL);
-#ifdef CUSTOMER_HW4_DEBUG
-	if (!wl_scan_timeout_dbg_enabled)
-		wl_scan_timeout_dbg_set();
-#endif /* CUSTOMER_HW4_DEBUG */
-}
-
-#ifdef DHD_LOSSLESS_ROAMING
-static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg)
-{
-	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
-
-	/* restore prec_map to ALLPRIO */
-	dhdp->dequeue_prec_map = ALLPRIO;
-	if (timer_pending(&cfg->roam_timeout)) {
-		del_timer_sync(&cfg->roam_timeout);
-	}
-
-}
-
-static void wl_roam_timeout(unsigned long data)
-{
-	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
-	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
-
-	WL_ERR(("roam timer expired\n"));
-
-	/* restore prec_map to ALLPRIO */
-	dhdp->dequeue_prec_map = ALLPRIO;
-}
-
-#endif /* DHD_LOSSLESS_ROAMING */
-
-static s32
-wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
-	unsigned long state, void *ptr)
-{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
-	struct net_device *dev = ptr;
-#else
-	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-#endif /* LINUX_VERSION < VERSION(3, 11, 0) */
-	struct wireless_dev *wdev = ndev_to_wdev(dev);
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-#ifdef DHD_IFDEBUG
-	WL_ERR(("Enter \n"));
-#endif
-
-	if (!wdev || !cfg || dev == bcmcfg_to_prmry_ndev(cfg))
-		return NOTIFY_DONE;
-
-	switch (state) {
-		case NETDEV_DOWN:
-		{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
-			int max_wait_timeout = 2;
-			int max_wait_count = 100;
-			int refcnt = 0;
-			unsigned long limit = jiffies + max_wait_timeout * HZ;
-#ifdef DHD_IFDEBUG
-			WL_ERR(("NETDEV_DOWN(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
-#endif
-			while (work_pending(&wdev->cleanup_work)) {
-				if (refcnt%5 == 0) {
-					WL_ERR(("[NETDEV_DOWN] wait for "
-						"complete of cleanup_work"
-						" (%d th)\n", refcnt));
-				}
-				if (!time_before(jiffies, limit)) {
-					WL_ERR(("[NETDEV_DOWN] cleanup_work"
-						" of CFG80211 is not"
-						" completed in %d sec\n",
-						max_wait_timeout));
-					break;
-				}
-				if (refcnt >= max_wait_count) {
-					WL_ERR(("[NETDEV_DOWN] cleanup_work"
-						" of CFG80211 is not"
-						" completed in %d loop\n",
-						max_wait_count));
-					break;
-				}
-				set_current_state(TASK_INTERRUPTIBLE);
-				(void)schedule_timeout(100);
-				set_current_state(TASK_RUNNING);
-				refcnt++;
-			}
-#ifdef DHD_IFDEBUG
-			WL_ERR(("NETDEV_DOWN(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
-#endif
-#endif /* LINUX_VERSION < VERSION(3, 14, 0) */
-			break;
-		}
-		case NETDEV_UNREGISTER:
-#ifdef DHD_IFDEBUG
-			WL_ERR(("NETDEV_UNREGISTER(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
-#endif
-			/* after calling list_del_rcu(&wdev->list) */
-			wl_cfg80211_clear_per_bss_ies(cfg,
-				wl_get_bssidx_by_wdev(cfg, wdev));
-			wl_dealloc_netinfo_by_wdev(cfg, wdev);
-#ifdef DHD_IFDEBUG
-			WL_ERR(("NETDEV_UNREGISTER(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
-#endif
-			break;
-		case NETDEV_GOING_DOWN:
-			/*
-			 * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
-			 * In front of door, the function checks whether current scan
-			 * is working or not. If the scanning is still working,
-			 * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
-			 */
-#ifdef DHD_IFDEBUG
-			WL_ERR(("NETDEV_GOING_DOWN wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
-#endif
-			if (wl_get_drv_status(cfg, SCANNING, dev))
-				wl_notify_escan_complete(cfg, dev, true, true);
-			break;
-	}
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block wl_cfg80211_netdev_notifier = {
-	.notifier_call = wl_cfg80211_netdev_notifier_call,
-};
-
-/*
- * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
- * created in kernel notifier link list (with 'next' pointing to itself)
- */
-static bool wl_cfg80211_netdev_notifier_registered = FALSE;
-
-static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
-{
-	struct wireless_dev *wdev = NULL;
-	struct net_device *ndev = NULL;
-
-	if (!cfg->scan_request)
-		return;
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
-	if (cfg->scan_request->dev)
-		wdev = cfg->scan_request->dev->ieee80211_ptr;
-#else
-	wdev = cfg->scan_request->wdev;
-#endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
-
-	if (!wdev) {
-		WL_ERR(("No wireless_dev present\n"));
-		return;
-	}
-
-	ndev = wdev_to_wlc_ndev(wdev, cfg);
-	wl_notify_escan_complete(cfg, ndev, true, true);
-	WL_ERR(("Scan aborted! \n"));
-}
-
-static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
-{
-	wl_scan_params_t *params = NULL;
-	s32 params_size = 0;
-	s32 err = BCME_OK;
-	struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
-	if (!in_atomic()) {
-		/* Our scan params only need space for 1 channel and 0 ssids */
-		params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
-		if (params == NULL) {
-			WL_ERR(("scan params allocation failed \n"));
-			err = -ENOMEM;
-		} else {
-			/* Do a scan abort to stop the driver's scan engine */
-			err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
-			if (err < 0) {
-				WL_ERR(("scan abort  failed \n"));
-			}
-			kfree(params);
-		}
-	}
-#ifdef WLTDLS
-	if (cfg->tdls_mgmt_frame) {
-		kfree(cfg->tdls_mgmt_frame);
-		cfg->tdls_mgmt_frame = NULL;
-	}
-#endif /* WLTDLS */
-}
-
-static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
-	struct net_device *ndev,
-	bool aborted, bool fw_abort)
-{
-	s32 err = BCME_OK;
-	unsigned long flags;
-	struct net_device *dev;
-
-	WL_DBG(("Enter \n"));
-
-	mutex_lock(&cfg->scan_complete);
-
-	if (!ndev) {
-		WL_ERR(("ndev is null\n"));
-		err = BCME_ERROR;
-		goto out;
-	}
-
-	if (cfg->escan_info.ndev != ndev) {
-		WL_ERR(("ndev is different %p %p\n", cfg->escan_info.ndev, ndev));
-		err = BCME_ERROR;
-		goto out;
-	}
-
-	if (cfg->scan_request) {
-		dev = bcmcfg_to_prmry_ndev(cfg);
-#if defined(WL_ENABLE_P2P_IF)
-		if (cfg->scan_request->dev != cfg->p2p_net)
-			dev = cfg->scan_request->dev;
-#elif defined(WL_CFG80211_P2P_DEV_IF)
-		if (cfg->scan_request->wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) {
-#ifdef DHD_IFDEBUG
-			WL_ERR(("%s: dev: %p\n", __FUNCTION__, cfg->scan_request->wdev->netdev));
-#endif
-			dev = cfg->scan_request->wdev->netdev;
-		}
-#endif /* WL_ENABLE_P2P_IF */
-	}
-	else {
-		WL_DBG(("cfg->scan_request is NULL may be internal scan."
-			"doing scan_abort for ndev %p primary %p",
-				ndev, bcmcfg_to_prmry_ndev(cfg)));
-		dev = ndev;
-	}
-	if (fw_abort && !in_atomic())
-		wl_cfg80211_scan_abort(cfg);
-	if (timer_pending(&cfg->scan_timeout))
-		del_timer_sync(&cfg->scan_timeout);
-#if defined(ESCAN_RESULT_PATCH)
-	if (likely(cfg->scan_request)) {
-		cfg->bss_list = wl_escan_get_buf(cfg, aborted);
-		wl_inform_bss(cfg);
-	}
-#endif /* ESCAN_RESULT_PATCH */
-	spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
-#ifdef WL_SCHED_SCAN
-	if (cfg->sched_scan_req && !cfg->scan_request) {
-		WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
-		if (!aborted)
-			cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy);
-		cfg->sched_scan_running = FALSE;
-		cfg->sched_scan_req = NULL;
-	}
-#endif /* WL_SCHED_SCAN */
-	if (likely(cfg->scan_request)) {
-		cfg80211_scan_done(cfg->scan_request, aborted);
-		cfg->scan_request = NULL;
-		DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
-		DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
-	}
-	if (p2p_is_on(cfg))
-		wl_clr_p2p_status(cfg, SCANNING);
-	wl_clr_drv_status(cfg, SCANNING, dev);
-	spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
-
-out:
-	mutex_unlock(&cfg->scan_complete);
-	return err;
-}
-
-#ifdef ESCAN_BUF_OVERFLOW_MGMT
-static void
-wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
-{
-	int idx;
-	for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
-		int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
-		if (bss->RSSI < candidate[idx].RSSI) {
-			if (len)
-				memcpy(&candidate[idx + 1], &candidate[idx],
-					sizeof(removal_element_t) * len);
-			candidate[idx].RSSI = bss->RSSI;
-			candidate[idx].length = bss->length;
-			memcpy(&candidate[idx].BSSID, &bss->BSSID, ETHER_ADDR_LEN);
-			return;
-		}
-	}
-}
-
-static void
-wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
-	wl_bss_info_t *bi)
-{
-	int idx1, idx2;
-	int total_delete_len = 0;
-	for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
-		int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
-		wl_bss_info_t *bss = NULL;
-		if (candidate[idx1].RSSI >= bi->RSSI)
-			continue;
-		for (idx2 = 0; idx2 < list->count; idx2++) {
-			bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
-				list->bss_info;
-			if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
-				candidate[idx1].RSSI == bss->RSSI &&
-				candidate[idx1].length == dtoh32(bss->length)) {
-				u32 delete_len = dtoh32(bss->length);
-				WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
-					MAC2STRDBG(bss->BSSID.octet)));
-				if (idx2 < list->count -1) {
-					memmove((u8 *)bss, (u8 *)bss + delete_len,
-						list->buflen - cur_len - delete_len);
-				}
-				list->buflen -= delete_len;
-				list->count--;
-				total_delete_len += delete_len;
-				/* if delete_len is greater than or equal to result length */
-				if (total_delete_len >= bi->length) {
-					return;
-				}
-				break;
-			}
-			cur_len += dtoh32(bss->length);
-		}
-	}
-}
-#endif /* ESCAN_BUF_OVERFLOW_MGMT */
-
-static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	s32 err = BCME_OK;
-	s32 status = ntoh32(e->status);
-	wl_bss_info_t *bi;
-	wl_escan_result_t *escan_result;
-	wl_bss_info_t *bss = NULL;
-	wl_scan_results_t *list;
-	wifi_p2p_ie_t * p2p_ie;
-	struct net_device *ndev = NULL;
-	u32 bi_length;
-	u32 i;
-	u8 *p2p_dev_addr = NULL;
-
-	WL_DBG((" enter event type : %d, status : %d \n",
-		ntoh32(e->event_type), ntoh32(e->status)));
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	mutex_lock(&cfg->usr_sync);
-	/* P2P SCAN is coming from primary interface */
-	if (wl_get_p2p_status(cfg, SCANNING)) {
-		if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
-			ndev = cfg->afx_hdl->dev;
-		else
-			ndev = cfg->escan_info.ndev;
-
-	}
-	if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
-		WL_ERR(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
-			ndev, wl_get_drv_status(cfg, SCANNING, ndev),
-			ntoh32(e->event_type), ntoh32(e->status)));
-		goto exit;
-	}
-	escan_result = (wl_escan_result_t *)data;
-
-	if (status == WLC_E_STATUS_PARTIAL) {
-		WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
-		if (!escan_result) {
-			WL_ERR(("Invalid escan result (NULL pointer)\n"));
-			goto exit;
-		}
-		if (dtoh16(escan_result->bss_count) != 1) {
-			WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
-			goto exit;
-		}
-		bi = escan_result->bss_info;
-		if (!bi) {
-			WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
-			goto exit;
-		}
-		bi_length = dtoh32(bi->length);
-		if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
-			WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
-			goto exit;
-		}
-		if (wl_escan_check_sync_id(status, escan_result->sync_id,
-			cfg->escan_info.cur_sync_id) < 0)
-			goto exit;
-
-		if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
-			if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
-				WL_DBG(("Ignoring IBSS result\n"));
-				goto exit;
-			}
-		}
-
-		if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
-			p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
-			if (p2p_dev_addr && !memcmp(p2p_dev_addr,
-				cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
-				s32 channel = wf_chspec_ctlchan(
-					wl_chspec_driver_to_host(bi->chanspec));
-
-				if ((channel > MAXCHANNEL) || (channel <= 0))
-					channel = WL_INVALID;
-				else
-					WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
-						" channel : %d\n",
-						MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
-						channel));
-
-				wl_clr_p2p_status(cfg, SCANNING);
-				cfg->afx_hdl->peer_chan = channel;
-				complete(&cfg->act_frm_scan);
-				goto exit;
-			}
-
-		} else {
-			int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
-#ifdef ESCAN_BUF_OVERFLOW_MGMT
-			removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
-			int remove_lower_rssi = FALSE;
-
-			bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
-#endif /* ESCAN_BUF_OVERFLOW_MGMT */
-
-			list = wl_escan_get_buf(cfg, FALSE);
-			if (scan_req_match(cfg)) {
-				/* p2p scan && allow only probe response */
-				if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
-					(bi->flags & WL_BSS_FLAGS_FROM_BEACON))
-					goto exit;
-				if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
-					bi->ie_length)) == NULL) {
-						WL_ERR(("Couldn't find P2PIE in probe"
-							" response/beacon\n"));
-						goto exit;
-				}
-			}
-#ifdef ESCAN_BUF_OVERFLOW_MGMT
-			if (bi_length > ESCAN_BUF_SIZE - list->buflen)
-				remove_lower_rssi = TRUE;
-#endif /* ESCAN_BUF_OVERFLOW_MGMT */
-
-			for (i = 0; i < list->count; i++) {
-				bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
-					: list->bss_info;
-#ifdef ESCAN_BUF_OVERFLOW_MGMT
-				WL_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
-					bss->SSID, MAC2STRDBG(bss->BSSID.octet),
-					i, bss->RSSI, list->count));
-
-				if (remove_lower_rssi)
-					wl_cfg80211_find_removal_candidate(bss, candidate);
-#endif /* ESCAN_BUF_OVERFLOW_MGMT */
-
-				if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
-					(CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
-					== CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
-					bi->SSID_len == bss->SSID_len &&
-					!bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
-
-					/* do not allow beacon data to update
-					*the data recd from a probe response
-					*/
-					if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
-						(bi->flags & WL_BSS_FLAGS_FROM_BEACON))
-						goto exit;
-
-					WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d"
-						" flags 0x%x, new: RSSI %d flags 0x%x\n",
-						bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
-						bss->RSSI, bss->flags, bi->RSSI, bi->flags));
-
-					if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
-						(bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
-						/* preserve max RSSI if the measurements are
-						* both on-channel or both off-channel
-						*/
-						WL_SCAN(("%s("MACDBG"), same onchan"
-						", RSSI: prev %d new %d\n",
-						bss->SSID, MAC2STRDBG(bi->BSSID.octet),
-						bss->RSSI, bi->RSSI));
-						bi->RSSI = MAX(bss->RSSI, bi->RSSI);
-					} else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
-						(bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
-						/* preserve the on-channel rssi measurement
-						* if the new measurement is off channel
-						*/
-						WL_SCAN(("%s("MACDBG"), prev onchan"
-						", RSSI: prev %d new %d\n",
-						bss->SSID, MAC2STRDBG(bi->BSSID.octet),
-						bss->RSSI, bi->RSSI));
-						bi->RSSI = bss->RSSI;
-						bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
-					}
-					if (dtoh32(bss->length) != bi_length) {
-						u32 prev_len = dtoh32(bss->length);
-
-						WL_SCAN(("bss info replacement"
-							" is occured(bcast:%d->probresp%d)\n",
-							bss->ie_length, bi->ie_length));
-						WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n",
-						bss->SSID, MAC2STRDBG(bi->BSSID.octet),
-						prev_len, bi_length));
-
-						if (list->buflen - prev_len + bi_length
-							> ESCAN_BUF_SIZE) {
-							WL_ERR(("Buffer is too small: keep the"
-								" previous result of this AP\n"));
-							/* Only update RSSI */
-							bss->RSSI = bi->RSSI;
-							bss->flags |= (bi->flags
-								& WL_BSS_FLAGS_RSSI_ONCHANNEL);
-							goto exit;
-						}
-
-						if (i < list->count - 1) {
-							/* memory copy required by this case only */
-							memmove((u8 *)bss + bi_length,
-								(u8 *)bss + prev_len,
-								list->buflen - cur_len - prev_len);
-						}
-						list->buflen -= prev_len;
-						list->buflen += bi_length;
-					}
-					list->version = dtoh32(bi->version);
-					memcpy((u8 *)bss, (u8 *)bi, bi_length);
-					goto exit;
-				}
-				cur_len += dtoh32(bss->length);
-			}
-			if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
-#ifdef ESCAN_BUF_OVERFLOW_MGMT
-				wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
-				if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
-					WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
-						MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
-					goto exit;
-				}
-#else
-				WL_ERR(("Buffer is too small: ignoring\n"));
-				goto exit;
-#endif /* ESCAN_BUF_OVERFLOW_MGMT */
-			}
-
-			memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
-			list->version = dtoh32(bi->version);
-			list->buflen += bi_length;
-			list->count++;
-
-			/*
-			 * !Broadcast && number of ssid = 1 && number of channels =1
-			 * means specific scan to association
-			 */
-			if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
-				WL_ERR(("P2P assoc scan fast aborted.\n"));
-				wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false, true);
-				goto exit;
-			}
-		}
-	}
-	else if (status == WLC_E_STATUS_SUCCESS) {
-		cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
-		wl_escan_print_sync_id(status, cfg->escan_info.cur_sync_id,
-			escan_result->sync_id);
-
-		if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
-			WL_INFORM(("ACTION FRAME SCAN DONE\n"));
-			wl_clr_p2p_status(cfg, SCANNING);
-			wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
-			if (cfg->afx_hdl->peer_chan == WL_INVALID)
-				complete(&cfg->act_frm_scan);
-		} else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
-			WL_INFORM(("ESCAN COMPLETED\n"));
-			cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
-			if (!scan_req_match(cfg)) {
-				WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
-					cfg->bss_list->count));
-			}
-			wl_inform_bss(cfg);
-			wl_notify_escan_complete(cfg, ndev, false, false);
-		}
-		wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
-#ifdef CUSTOMER_HW4_DEBUG
-		if (wl_scan_timeout_dbg_enabled)
-			wl_scan_timeout_dbg_clear();
-#endif /* CUSTOMER_HW4_DEBUG */
-	} else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
-		(status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
-		(status == WLC_E_STATUS_NEWASSOC)) {
-		/* Handle all cases of scan abort */
-		cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
-		wl_escan_print_sync_id(status, escan_result->sync_id,
-			cfg->escan_info.cur_sync_id);
-		WL_DBG(("ESCAN ABORT reason: %d\n", status));
-		if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
-			WL_INFORM(("ACTION FRAME SCAN DONE\n"));
-			wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
-			wl_clr_p2p_status(cfg, SCANNING);
-			if (cfg->afx_hdl->peer_chan == WL_INVALID)
-				complete(&cfg->act_frm_scan);
-		} else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
-			WL_INFORM(("ESCAN ABORTED\n"));
-			cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
-			if (!scan_req_match(cfg)) {
-				WL_TRACE_HW4(("scan_req_match=0: scanned AP count=%d\n",
-					cfg->bss_list->count));
-			}
-			wl_inform_bss(cfg);
-			wl_notify_escan_complete(cfg, ndev, true, false);
-		} else {
-			/* If there is no pending host initiated scan, do nothing */
-			WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
-		}
-		wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
-	} else if (status == WLC_E_STATUS_TIMEOUT) {
-		WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
-		WL_ERR(("reason[0x%x]\n", e->reason));
-		if (e->reason == 0xFFFFFFFF) {
-			wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
-		}
-	} else {
-		WL_ERR(("unexpected Escan Event %d : abort\n", status));
-		cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
-		wl_escan_print_sync_id(status, escan_result->sync_id,
-			cfg->escan_info.cur_sync_id);
-		if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
-			WL_INFORM(("ACTION FRAME SCAN DONE\n"));
-			wl_clr_p2p_status(cfg, SCANNING);
-			wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
-			if (cfg->afx_hdl->peer_chan == WL_INVALID)
-				complete(&cfg->act_frm_scan);
-		} else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
-			cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
-			if (!scan_req_match(cfg)) {
-				WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
-					"scanned AP count=%d\n",
-					cfg->bss_list->count));
-			}
-			wl_inform_bss(cfg);
-			wl_notify_escan_complete(cfg, ndev, true, false);
-		}
-		wl_escan_increment_sync_id(cfg, 2);
-	}
-exit:
-	mutex_unlock(&cfg->usr_sync);
-	return err;
-}
-
-static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211 *cfg, int enable)
-{
-	u32 connected_cnt  = wl_get_drv_status_all(cfg, CONNECTED);
-	bool p2p_connected  = wl_cfgp2p_vif_created(cfg);
-	struct net_info *iter, *next;
-
-	if (!cfg->roamoff_on_concurrent)
-		return;
-	if (enable && (p2p_connected||(connected_cnt > 1))) {
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-		for_each_ndev(cfg, iter, next) {
-			if (iter->ndev && iter->wdev &&
-					iter->wdev->iftype == NL80211_IFTYPE_STATION) {
-				if (wldev_iovar_setint(iter->ndev, "roam_off", TRUE)
-						== BCME_OK) {
-					iter->roam_off = TRUE;
-				}
-				else {
-					WL_ERR(("error to enable roam_off\n"));
-				}
-			}
-		}
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-	}
-	else if (!enable) {
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-		for_each_ndev(cfg, iter, next) {
-			if (iter->ndev && iter->wdev &&
-					iter->wdev->iftype == NL80211_IFTYPE_STATION) {
-				if (iter->roam_off != WL_INVALID) {
-					if (wldev_iovar_setint(iter->ndev, "roam_off", FALSE)
-							== BCME_OK) {
-						iter->roam_off = FALSE;
-					}
-					else {
-						WL_ERR(("error to disable roam_off\n"));
-					}
-				}
-			}
-		}
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-	}
-	return;
-}
-
-static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211 *cfg)
-{
-	struct net_info *iter, *next;
-	u32 ctl_chan = 0;
-	u32 chanspec = 0;
-	u32 pre_ctl_chan = 0;
-	u32 connected_cnt  = wl_get_drv_status_all(cfg, CONNECTED);
-	cfg->vsdb_mode = false;
-
-	if (connected_cnt <= 1)  {
-		return;
-	}
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-	for_each_ndev(cfg, iter, next) {
-		/* p2p discovery iface ndev could be null */
-		if (iter->ndev) {
-			chanspec = 0;
-			ctl_chan = 0;
-			if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
-				if (wldev_iovar_getint(iter->ndev, "chanspec",
-					(s32 *)&chanspec) == BCME_OK) {
-					chanspec = wl_chspec_driver_to_host(chanspec);
-					ctl_chan = wf_chspec_ctlchan(chanspec);
-					wl_update_prof(cfg, iter->ndev, NULL,
-						&ctl_chan, WL_PROF_CHAN);
-				}
-				if (!cfg->vsdb_mode) {
-					if (!pre_ctl_chan && ctl_chan)
-						pre_ctl_chan = ctl_chan;
-					else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
-						cfg->vsdb_mode = true;
-					}
-				}
-			}
-		}
-	}
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-	WL_ERR(("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel"));
-	return;
-}
-
-#if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
-extern int g_frameburst;
-#endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
-
-static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
-	enum wl_status state, bool set)
-{
-	s32 pm = PM_FAST;
-	s32 err = BCME_OK;
-	u32 mode;
-	u32 chan = 0;
-	struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
-	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
-	if (dhd->busstate == DHD_BUS_DOWN) {
-		WL_ERR(("%s : busstate is DHD_BUS_DOWN!\n", __FUNCTION__));
-		return 0;
-	}
-	WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
-		state, set, _net_info->pm_restore, _net_info->ndev->name));
-
-	if (state != WL_STATUS_CONNECTED)
-		return 0;
-	mode = wl_get_mode_by_netdev(cfg, _net_info->ndev);
-	if (set) {
-		wl_cfg80211_concurrent_roam(cfg, 1);
-		wl_cfg80211_determine_vsdb_mode(cfg);
-		if (mode == WL_MODE_AP) {
-			if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
-				WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
-		}
-
-		pm = PM_OFF;
-		if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
-				sizeof(pm), true)) != 0) {
-			if (err == -ENODEV)
-				WL_DBG(("%s:netdev not ready\n",
-					_net_info->ndev->name));
-			else
-				WL_ERR(("%s:error (%d)\n",
-					_net_info->ndev->name, err));
-
-			wl_cfg80211_update_power_mode(_net_info->ndev);
-		}
-		wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_SHORT);
-#if defined(WLTDLS)
-		if (wl_cfg80211_is_concurrent_mode()) {
-			err = wldev_iovar_setint(primary_dev, "tdls_enable", 0);
-		}
-#endif /* defined(WLTDLS) */
-
-#ifdef DISABLE_FRAMEBURST_VSDB
-#ifdef USE_WFA_CERT_CONF
-		if (g_frameburst)
-#endif /* USE_WFA_CERT_CONF */
-		{
-			if (wl_cfg80211_is_concurrent_mode()) {
-				int frameburst = 0;
-				if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
-					sizeof(frameburst), true) != 0) {
-					WL_DBG(("frameburst set error\n"));
-				}
-				WL_DBG(("Frameburst Disabled\n"));
-			}
-		}
-#endif /* DISABLE_FRAMEBURST_VSDB */
-	} else { /* clear */
-		chan = 0;
-		/* clear chan information when the net device is disconnected */
-		wl_update_prof(cfg, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
-		wl_cfg80211_determine_vsdb_mode(cfg);
-		if (primary_dev == _net_info->ndev) {
-			pm = PM_FAST;
-			if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
-					sizeof(pm), true)) != 0) {
-				if (err == -ENODEV)
-					WL_DBG(("%s:netdev not ready\n",
-						_net_info->ndev->name));
-				else
-					WL_ERR(("%s:error (%d)\n",
-						_net_info->ndev->name, err));
-
-				wl_cfg80211_update_power_mode(_net_info->ndev);
-			}
-		}
-
-		wl_cfg80211_concurrent_roam(cfg, 0);
-#if defined(WLTDLS)
-		if (!wl_cfg80211_is_concurrent_mode()) {
-			err = wldev_iovar_setint(primary_dev, "tdls_enable", 1);
-		}
-#endif /* defined(WLTDLS) */
-
-#ifdef DISABLE_FRAMEBURST_VSDB
-#ifdef USE_WFA_CERT_CONF
-		if (g_frameburst)
-#endif /* USE_WFA_CERT_CONF */
-		{
-			int frameburst = 1;
-			if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
-				sizeof(frameburst), true) != 0) {
-				WL_DBG(("frameburst set error\n"));
-			}
-			WL_DBG(("Frameburst Enabled\n"));
-		}
-#endif /* DISABLE_FRAMEBURST_VSDB */
-	}
-	return err;
-}
-static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
-{
-	int err = 0;
-
-	cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
-	cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
-	wl_escan_init_sync_id(cfg);
-
-	/* Init scan_timeout timer */
-	init_timer(&cfg->scan_timeout);
-	cfg->scan_timeout.data = (unsigned long) cfg;
-	cfg->scan_timeout.function = wl_scan_timeout;
-
-	return err;
-}
-
-#ifdef DHD_LOSSLESS_ROAMING
-static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg)
-{
-	int err = 0;
-
-	/* Init roam timer */
-	init_timer(&cfg->roam_timeout);
-	cfg->roam_timeout.data = (unsigned long) cfg;
-	cfg->roam_timeout.function = wl_roam_timeout;
-
-	return err;
-}
-#endif /* DHD_LOSSLESS_ROAMING */
-
-static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
-{
-	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-	s32 err = 0;
-
-	cfg->scan_request = NULL;
-	cfg->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
-	cfg->roam_on = false;
-	cfg->active_scan = true;
-	cfg->rf_blocked = false;
-	cfg->vsdb_mode = false;
-#if defined(BCMSDIO)
-	cfg->wlfc_on = false;
-#endif 
-	cfg->roamoff_on_concurrent = true;
-	cfg->disable_roam_event = false;
-	cfg->cfgdev_bssidx = -1;
-	/* register interested state */
-	set_bit(WL_STATUS_CONNECTED, &cfg->interrested_state);
-	spin_lock_init(&cfg->cfgdrv_lock);
-	mutex_init(&cfg->ioctl_buf_sync);
-	init_waitqueue_head(&cfg->netif_change_event);
-	init_completion(&cfg->send_af_done);
-	init_completion(&cfg->iface_disable);
-	wl_init_eq(cfg);
-	err = wl_init_priv_mem(cfg);
-	if (err)
-		return err;
-	if (wl_create_event_handler(cfg))
-		return -ENOMEM;
-	wl_init_event_handler(cfg);
-	mutex_init(&cfg->usr_sync);
-	mutex_init(&cfg->event_sync);
-	mutex_init(&cfg->scan_complete);
-	err = wl_init_scan(cfg);
-	if (err)
-		return err;
-#ifdef DHD_LOSSLESS_ROAMING
-	err = wl_init_roam_timeout(cfg);
-	if (err) {
-		return err;
-	}
-#endif /* DHD_LOSSLESS_ROAMING */
-	wl_init_conf(cfg->conf);
-	wl_init_prof(cfg, ndev);
-	wl_link_down(cfg);
-	DNGL_FUNC(dhd_cfg80211_init, (cfg));
-
-	return err;
-}
-
-static void wl_deinit_priv(struct bcm_cfg80211 *cfg)
-{
-	DNGL_FUNC(dhd_cfg80211_deinit, (cfg));
-	wl_destroy_event_handler(cfg);
-	wl_flush_eq(cfg);
-	wl_link_down(cfg);
-	del_timer_sync(&cfg->scan_timeout);
-#ifdef DHD_LOSSLESS_ROAMING
-	del_timer_sync(&cfg->roam_timeout);
-#endif
-	wl_deinit_priv_mem(cfg);
-	if (wl_cfg80211_netdev_notifier_registered) {
-		wl_cfg80211_netdev_notifier_registered = FALSE;
-		unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
-	}
-}
-
-#if defined(WL_ENABLE_P2P_IF)
-static s32 wl_cfg80211_attach_p2p(void)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	WL_TRACE(("Enter \n"));
-
-	if (wl_cfgp2p_register_ndev(cfg) < 0) {
-		WL_ERR(("P2P attach failed. \n"));
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static s32  wl_cfg80211_detach_p2p(void)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wireless_dev *wdev;
-
-	WL_DBG(("Enter \n"));
-	if (!cfg) {
-		WL_ERR(("Invalid Ptr\n"));
-		return -EINVAL;
-	} else
-		wdev = cfg->p2p_wdev;
-
-	if (!wdev) {
-		WL_ERR(("Invalid Ptr\n"));
-		return -EINVAL;
-	}
-
-	wl_cfgp2p_unregister_ndev(cfg);
-
-	cfg->p2p_wdev = NULL;
-	cfg->p2p_net = NULL;
-	WL_DBG(("Freeing 0x%p \n", wdev));
-	kfree(wdev);
-
-	return 0;
-}
-#endif 
-
-s32 wl_cfg80211_attach_post(struct net_device *ndev)
-{
-	struct bcm_cfg80211 * cfg = NULL;
-	s32 err = 0;
-	s32 ret = 0;
-	WL_TRACE(("In\n"));
-	if (unlikely(!ndev)) {
-		WL_ERR(("ndev is invaild\n"));
-		return -ENODEV;
-	}
-	cfg = g_bcm_cfg;
-	if (unlikely(!cfg)) {
-		WL_ERR(("cfg is invaild\n"));
-		return -EINVAL;
-	}
-	if (!wl_get_drv_status(cfg, READY, ndev)) {
-		if (cfg->wdev) {
-			ret = wl_cfgp2p_supported(cfg, ndev);
-			if (ret > 0) {
-#if !defined(WL_ENABLE_P2P_IF)
-				cfg->wdev->wiphy->interface_modes |=
-					(BIT(NL80211_IFTYPE_P2P_CLIENT)|
-					BIT(NL80211_IFTYPE_P2P_GO));
-#endif /* !WL_ENABLE_P2P_IF */
-				if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
-					goto fail;
-
-#if defined(WL_ENABLE_P2P_IF)
-				if (cfg->p2p_net) {
-					/* Update MAC addr for p2p0 interface here. */
-					memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
-					cfg->p2p_net->dev_addr[0] |= 0x02;
-					WL_ERR(("%s: p2p_dev_addr="MACDBG "\n",
-						cfg->p2p_net->name,
-						MAC2STRDBG(cfg->p2p_net->dev_addr)));
-				} else {
-					WL_ERR(("p2p_net not yet populated."
-					" Couldn't update the MAC Address for p2p0 \n"));
-					return -ENODEV;
-				}
-#endif /* WL_ENABLE_P2P_IF */
-				cfg->p2p_supported = true;
-			} else if (ret == 0) {
-				if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
-					goto fail;
-			} else {
-				/* SDIO bus timeout */
-				err = -ENODEV;
-				goto fail;
-			}
-		}
-	}
-	wl_set_drv_status(cfg, READY, ndev);
-fail:
-	return err;
-}
-
-s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
-{
-	struct wireless_dev *wdev;
-	struct bcm_cfg80211 *cfg;
-	s32 err = 0;
-	struct device *dev;
-
-	WL_TRACE(("In\n"));
-	if (!ndev) {
-		WL_ERR(("ndev is invaild\n"));
-		return -ENODEV;
-	}
-	WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
-	dev = wl_cfg80211_get_parent_dev();
-
-	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
-	if (unlikely(!wdev)) {
-		WL_ERR(("Could not allocate wireless device\n"));
-		return -ENOMEM;
-	}
-	err = wl_setup_wiphy(wdev, dev, context);
-	if (unlikely(err)) {
-		kfree(wdev);
-		return -ENOMEM;
-	}
-	wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
-	cfg = (struct bcm_cfg80211 *)wiphy_priv(wdev->wiphy);
-	cfg->wdev = wdev;
-	cfg->pub = context;
-	INIT_LIST_HEAD(&cfg->net_list);
-	spin_lock_init(&cfg->net_list_sync);
-	ndev->ieee80211_ptr = wdev;
-	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
-	wdev->netdev = ndev;
-	cfg->state_notifier = wl_notifier_change_state;
-	err = wl_alloc_netinfo(cfg, ndev, wdev, WL_MODE_BSS, PM_ENABLE, 0);
-	if (err) {
-		WL_ERR(("Failed to alloc net_info (%d)\n", err));
-		goto cfg80211_attach_out;
-	}
-	err = wl_init_priv(cfg);
-	if (err) {
-		WL_ERR(("Failed to init iwm_priv (%d)\n", err));
-		goto cfg80211_attach_out;
-	}
-
-	err = wl_setup_rfkill(cfg, TRUE);
-	if (err) {
-		WL_ERR(("Failed to setup rfkill %d\n", err));
-		goto cfg80211_attach_out;
-	}
-#ifdef DEBUGFS_CFG80211
-	err = wl_setup_debugfs(cfg);
-	if (err) {
-		WL_ERR(("Failed to setup debugfs %d\n", err));
-		goto cfg80211_attach_out;
-	}
-#endif
-	if (!wl_cfg80211_netdev_notifier_registered) {
-		wl_cfg80211_netdev_notifier_registered = TRUE;
-		err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
-		if (err) {
-			wl_cfg80211_netdev_notifier_registered = FALSE;
-			WL_ERR(("Failed to register notifierl %d\n", err));
-			goto cfg80211_attach_out;
-		}
-	}
-#if defined(COEX_DHCP)
-	cfg->btcoex_info = wl_cfg80211_btcoex_init(cfg->wdev->netdev);
-	if (!cfg->btcoex_info)
-		goto cfg80211_attach_out;
-#endif 
-#if defined(SUPPORT_RANDOM_MAC_SCAN)
-	cfg->random_mac_enabled = FALSE;
-#endif /* SUPPORT_RANDOM_MAC_SCAN */
-	g_bcm_cfg = cfg;
-
-#ifdef CONFIG_CFG80211_INTERNAL_REGDB
-	wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
-#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
-
-#if defined(WL_ENABLE_P2P_IF)
-	err = wl_cfg80211_attach_p2p();
-	if (err)
-		goto cfg80211_attach_out;
-#endif 
-
-	INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
-	mutex_init(&cfg->pm_sync);
-
-	return err;
-
-cfg80211_attach_out:
-	wl_setup_rfkill(cfg, FALSE);
-	wl_free_wdev(cfg);
-	return err;
-}
-
-void wl_cfg80211_detach(void *para)
-{
-	struct bcm_cfg80211 *cfg;
-
-	(void)para;
-	cfg = g_bcm_cfg;
-
-	WL_TRACE(("In\n"));
-
-	wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
-
-#if defined(COEX_DHCP)
-	wl_cfg80211_btcoex_deinit();
-	cfg->btcoex_info = NULL;
-#endif 
-
-	wl_setup_rfkill(cfg, FALSE);
-#ifdef DEBUGFS_CFG80211
-	wl_free_debugfs(cfg);
-#endif
-	if (cfg->p2p_supported) {
-		if (timer_pending(&cfg->p2p->listen_timer))
-			del_timer_sync(&cfg->p2p->listen_timer);
-		wl_cfgp2p_deinit_priv(cfg);
-	}
-
-	if (timer_pending(&cfg->scan_timeout))
-		del_timer_sync(&cfg->scan_timeout);
-#ifdef DHD_LOSSLESS_ROAMING
-	if (timer_pending(&cfg->roam_timeout)) {
-		del_timer_sync(&cfg->roam_timeout);
-	}
-#endif /* DHD_LOSSLESS_ROAMING */
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	if (cfg->p2p_wdev)
-		wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
-#endif /* WL_CFG80211_P2P_DEV_IF  */
-#if defined(WL_ENABLE_P2P_IF)
-	wl_cfg80211_detach_p2p();
-#endif 
-
-	wl_cfg80211_ibss_vsie_free(cfg);
-	wl_cfg80211_clear_mgmt_vndr_ies(cfg);
-	wl_deinit_priv(cfg);
-	g_bcm_cfg = NULL;
-	wl_cfg80211_clear_parent_dev();
-	wl_free_wdev(cfg);
-	/* PLEASE do NOT call any function after wl_free_wdev, the driver's private
-	 * structure "cfg", which is the private part of wiphy, has been freed in
-	 * wl_free_wdev !!!!!!!!!!!
-	 */
-}
-
-static void wl_wakeup_event(struct bcm_cfg80211 *cfg)
-{
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-
-	if (dhd->up && (cfg->event_tsk.thr_pid >= 0)) {
-		up(&cfg->event_tsk.sema);
-	}
-}
-
-static s32 wl_event_handler(void *data)
-{
-	struct bcm_cfg80211 *cfg = NULL;
-	struct wl_event_q *e;
-	tsk_ctl_t *tsk = (tsk_ctl_t *)data;
-	struct wireless_dev *wdev = NULL;
-
-	cfg = (struct bcm_cfg80211 *)tsk->parent;
-
-	WL_ERR(("tsk Enter, tsk = 0x%p\n", tsk));
-
-	while (down_interruptible (&tsk->sema) == 0) {
-		SMP_RD_BARRIER_DEPENDS();
-		if (tsk->terminated) {
-			break;
-		}
-		while ((e = wl_deq_event(cfg))) {
-			WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",
-				e->etype, e->emsg.ifidx, e->emsg.bsscfgidx));
-
-			if (e->emsg.ifidx > WL_MAX_IFS) {
-				WL_ERR((" Event ifidx not in range. val:%d \n", e->emsg.ifidx));
-				goto fail;
-			}
-
-			if (!(wdev = wl_get_wdev_by_bssidx(cfg, e->emsg.bsscfgidx))) {
-				/* For WLC_E_IF would be handled by wl_host_event */
-				if (e->etype != WLC_E_IF)
-					WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
-						" Ignoring event.\n", e->emsg.bsscfgidx));
-			} else if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {
-				dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
-				if (dhd->busstate == DHD_BUS_DOWN) {
-					WL_ERR((": BUS is DOWN.\n"));
-				} else {
-#ifdef DHD_IFDEBUG
-					if (cfg->iface_cnt == 0) {
-						wl_dump_ifinfo(cfg);
-					}
-#endif
-					cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),
-						&e->emsg, e->edata);
-				}
-			} else {
-				WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
-			}
-fail:
-			wl_put_event(e);
-			DHD_EVENT_WAKE_UNLOCK(cfg->pub);
-		}
-	}
-	WL_ERR(("was terminated\n"));
-	complete_and_exit(&tsk->completed, 0);
-	return 0;
-}
-
-void
-wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
-{
-	u32 event_type = ntoh32(e->event_type);
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct net_info *netinfo;
-
-#if (WL_DBG_LEVEL > 0)
-	s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
-	    wl_dbg_estr[event_type] : (s8 *) "Unknown";
-	WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
-#endif /* (WL_DBG_LEVEL > 0) */
-
-	if (cfg->event_tsk.thr_pid == -1) {
-		WL_ERR(("Event handler is not created\n"));
-		return;
-	}
-
-	if ((cfg == NULL) || (cfg->p2p_supported && cfg->p2p == NULL)) {
-		WL_ERR(("Stale event ignored\n"));
-		return;
-	}
-
-	if (wl_get_p2p_status(cfg, IF_CHANGING) || wl_get_p2p_status(cfg, IF_ADDING)) {
-		WL_ERR(("during IF change, ignore event %d\n", event_type));
-		return;
-	}
-
-#ifdef DHD_IFDEBUG
-	if (event_type != WLC_E_ESCAN_RESULT) {
-		WL_ERR(("Event_type %d , status : %d, reason : %d, bssidx:%d \n",
-			event_type, ntoh32(e->status), ntoh32(e->reason), e->bsscfgidx));
-	}
-#endif
-	netinfo = wl_get_netinfo_by_bssidx(cfg, e->bsscfgidx);
-	if (!netinfo) {
-		/* Since the netinfo entry is not there, the netdev entry is not
-		 * created via cfg80211 interface. so the event is not of interest
-		 * to the cfg80211 layer.
-		 */
-		WL_ERR(("ignore event %d, not interested\n", event_type));
-		return;
-	}
-
-	if (event_type == WLC_E_PFN_NET_FOUND) {
-		WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
-	}
-	else if (event_type == WLC_E_PFN_NET_LOST) {
-		WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
-	}
-
-	DHD_EVENT_WAKE_LOCK(cfg->pub);
-	if (likely(!wl_enq_event(cfg, ndev, event_type, e, data))) {
-		wl_wakeup_event(cfg);
-	} else {
-		DHD_EVENT_WAKE_UNLOCK(cfg->pub);
-	}
-}
-
-static void wl_init_eq(struct bcm_cfg80211 *cfg)
-{
-	wl_init_eq_lock(cfg);
-	INIT_LIST_HEAD(&cfg->eq_list);
-}
-
-static void wl_flush_eq(struct bcm_cfg80211 *cfg)
-{
-	struct wl_event_q *e;
-	unsigned long flags;
-
-	flags = wl_lock_eq(cfg);
-	while (!list_empty_careful(&cfg->eq_list)) {
-		BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
-		list_del(&e->eq_list);
-		kfree(e);
-	}
-	wl_unlock_eq(cfg, flags);
-}
-
-/*
-* retrieve first queued event from head
-*/
-
-static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg)
-{
-	struct wl_event_q *e = NULL;
-	unsigned long flags;
-
-	flags = wl_lock_eq(cfg);
-	if (likely(!list_empty(&cfg->eq_list))) {
-		BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
-		list_del(&e->eq_list);
-	}
-	wl_unlock_eq(cfg, flags);
-
-	return e;
-}
-
-/*
- * push event to tail of the queue
- */
-
-static s32
-wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 event,
-	const wl_event_msg_t *msg, void *data)
-{
-	struct wl_event_q *e;
-	s32 err = 0;
-	uint32 evtq_size;
-	uint32 data_len;
-	unsigned long flags;
-	gfp_t aflags;
-
-	data_len = 0;
-	if (data)
-		data_len = ntoh32(msg->datalen);
-	evtq_size = sizeof(struct wl_event_q) + data_len;
-	aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
-	e = kzalloc(evtq_size, aflags);
-	if (unlikely(!e)) {
-		WL_ERR(("event alloc failed\n"));
-		return -ENOMEM;
-	}
-	e->etype = event;
-	memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
-	if (data)
-		memcpy(e->edata, data, data_len);
-	flags = wl_lock_eq(cfg);
-	list_add_tail(&e->eq_list, &cfg->eq_list);
-	wl_unlock_eq(cfg, flags);
-
-	return err;
-}
-
-static void wl_put_event(struct wl_event_q *e)
-{
-	kfree(e);
-}
-
-static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype)
-{
-	s32 infra = 0;
-	s32 err = 0;
-	s32 mode = 0;
-	switch (iftype) {
-	case NL80211_IFTYPE_MONITOR:
-	case NL80211_IFTYPE_WDS:
-		WL_ERR(("type (%d) : currently we do not support this mode\n",
-			iftype));
-		err = -EINVAL;
-		return err;
-	case NL80211_IFTYPE_ADHOC:
-		mode = WL_MODE_IBSS;
-		break;
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_P2P_CLIENT:
-		mode = WL_MODE_BSS;
-		infra = 1;
-		break;
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_P2P_GO:
-		mode = WL_MODE_AP;
-		infra = 1;
-		break;
-	default:
-		err = -EINVAL;
-		WL_ERR(("invalid type (%d)\n", iftype));
-		return err;
-	}
-	infra = htod32(infra);
-	err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
-	if (unlikely(err)) {
-		WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
-		return err;
-	}
-
-	wl_set_mode_by_netdev(cfg, ndev, mode);
-
-	return 0;
-}
-
-void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
-{
-	if (!ev || (event > WLC_E_LAST))
-		return;
-
-	if (ev->num < MAX_EVENT_BUF_NUM) {
-		ev->event[ev->num].type = event;
-		ev->event[ev->num].set = set;
-		ev->num++;
-	} else {
-		WL_ERR(("evenbuffer doesn't support > %u events. Update"
-			" the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
-		ASSERT(0);
-	}
-}
-
-s32 wl_cfg80211_apply_eventbuffer(
-	struct net_device *ndev,
-	struct bcm_cfg80211 *cfg,
-	wl_eventmsg_buf_t *ev)
-{
-	char eventmask[WL_EVENTING_MASK_LEN];
-	int i, ret = 0;
-	s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
-
-	if (!ev || (!ev->num))
-		return -EINVAL;
-
-	mutex_lock(&cfg->event_sync);
-
-	/* Read event_msgs mask */
-	bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
-		sizeof(iovbuf));
-	ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
-	if (unlikely(ret)) {
-		WL_ERR(("Get event_msgs error (%d)\n", ret));
-		goto exit;
-	}
-	memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
-
-	/* apply the set bits */
-	for (i = 0; i < ev->num; i++) {
-		if (ev->event[i].set)
-			setbit(eventmask, ev->event[i].type);
-		else
-			clrbit(eventmask, ev->event[i].type);
-	}
-
-	/* Write updated Event mask */
-	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
-		sizeof(iovbuf));
-	ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
-	if (unlikely(ret)) {
-		WL_ERR(("Set event_msgs error (%d)\n", ret));
-	}
-
-exit:
-	mutex_unlock(&cfg->event_sync);
-	return ret;
-}
-
-s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
-{
-	s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
-	s8 eventmask[WL_EVENTING_MASK_LEN];
-	s32 err = 0;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	if (!ndev || !cfg)
-		return -ENODEV;
-
-	mutex_lock(&cfg->event_sync);
-
-	/* Setup event_msgs */
-	bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
-		sizeof(iovbuf));
-	err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
-	if (unlikely(err)) {
-		WL_ERR(("Get event_msgs error (%d)\n", err));
-		goto eventmsg_out;
-	}
-	memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
-	if (add) {
-		setbit(eventmask, event);
-	} else {
-		clrbit(eventmask, event);
-	}
-	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
-		sizeof(iovbuf));
-	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
-	if (unlikely(err)) {
-		WL_ERR(("Set event_msgs error (%d)\n", err));
-		goto eventmsg_out;
-	}
-
-eventmsg_out:
-	mutex_unlock(&cfg->event_sync);
-	return err;
-}
-
-static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
-{
-	struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
-	struct ieee80211_channel *band_chan_arr = NULL;
-	wl_uint32_list_t *list;
-	u32 i, j, index, n_2g, n_5g, band, channel, array_size;
-	u32 *n_cnt = NULL;
-	chanspec_t c = 0;
-	s32 err = BCME_OK;
-	bool update;
-	bool ht40_allowed;
-	u8 *pbuf = NULL;
-	bool dfs_radar_disabled = FALSE;
-
-#define LOCAL_BUF_LEN 1024
-	pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
-
-	if (pbuf == NULL) {
-		WL_ERR(("failed to allocate local buf\n"));
-		return -ENOMEM;
-	}
-	list = (wl_uint32_list_t *)(void *)pbuf;
-	list->count = htod32(WL_NUMCHANSPECS);
-
-
-	err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
-		0, pbuf, LOCAL_BUF_LEN, 0, &cfg->ioctl_buf_sync);
-	if (err != 0) {
-		WL_ERR(("get chanspecs failed with %d\n", err));
-		kfree(pbuf);
-		return err;
-	}
-#undef LOCAL_BUF_LEN
-
-	list = (wl_uint32_list_t *)(void *)pbuf;
-	band = array_size = n_2g = n_5g = 0;
-	for (i = 0; i < dtoh32(list->count); i++) {
-		index = 0;
-		update = false;
-		ht40_allowed = false;
-		c = (chanspec_t)dtoh32(list->element[i]);
-		c = wl_chspec_driver_to_host(c);
-		channel = wf_chspec_ctlchan(c);
-
-		if (!CHSPEC_IS40(c) && ! CHSPEC_IS20(c)) {
-			WL_DBG(("HT80/160/80p80 center channel : %d\n", channel));
-			continue;
-		}
-		if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
-			(channel <= CH_MAX_2G_CHANNEL)) {
-			band_chan_arr = __wl_2ghz_channels;
-			array_size = ARRAYSIZE(__wl_2ghz_channels);
-			n_cnt = &n_2g;
-			band = IEEE80211_BAND_2GHZ;
-			ht40_allowed = (bw_cap  == WLC_N_BW_40ALL)? true : false;
-		} else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
-			band_chan_arr = __wl_5ghz_a_channels;
-			array_size = ARRAYSIZE(__wl_5ghz_a_channels);
-			n_cnt = &n_5g;
-			band = IEEE80211_BAND_5GHZ;
-			ht40_allowed = (bw_cap  == WLC_N_BW_20ALL)? false : true;
-		} else {
-			WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
-			continue;
-		}
-		if (!ht40_allowed && CHSPEC_IS40(c))
-			continue;
-		for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
-			if (band_chan_arr[j].hw_value == channel) {
-				update = true;
-				break;
-			}
-		}
-		if (update)
-			index = j;
-		else
-			index = *n_cnt;
-		if (index <  array_size) {
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
-			band_chan_arr[index].center_freq =
-				ieee80211_channel_to_frequency(channel);
-#else
-			band_chan_arr[index].center_freq =
-				ieee80211_channel_to_frequency(channel, band);
-#endif
-			band_chan_arr[index].hw_value = channel;
-
-			if (CHSPEC_IS40(c) && ht40_allowed) {
-				/* assuming the order is HT20, HT40 Upper,
-				 *  HT40 lower from chanspecs
-				 */
-				u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
-				if (CHSPEC_SB_UPPER(c)) {
-					if (ht40_flag == IEEE80211_CHAN_NO_HT40)
-						band_chan_arr[index].flags &=
-							~IEEE80211_CHAN_NO_HT40;
-					band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
-				} else {
-					/* It should be one of
-					 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
-					 */
-					band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
-					if (ht40_flag == IEEE80211_CHAN_NO_HT40)
-						band_chan_arr[index].flags |=
-							IEEE80211_CHAN_NO_HT40MINUS;
-				}
-			} else {
-				band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
-				if (!dfs_radar_disabled) {
-					if (band == IEEE80211_BAND_2GHZ)
-						channel |= WL_CHANSPEC_BAND_2G;
-					else
-						channel |= WL_CHANSPEC_BAND_5G;
-					channel |= WL_CHANSPEC_BW_20;
-					channel = wl_chspec_host_to_driver(channel);
-					err = wldev_iovar_getint(dev, "per_chan_info", &channel);
-					if (!err) {
-						if (channel & WL_CHAN_RADAR) {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
-							band_chan_arr[index].flags |=
-								(IEEE80211_CHAN_RADAR
-								| IEEE80211_CHAN_NO_IBSS);
-#else
-							band_chan_arr[index].flags |=
-								IEEE80211_CHAN_RADAR;
-#endif
-						}
-
-						if (channel & WL_CHAN_PASSIVE)
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
-							band_chan_arr[index].flags |=
-								IEEE80211_CHAN_PASSIVE_SCAN;
-#else
-							band_chan_arr[index].flags |=
-								IEEE80211_CHAN_NO_IR;
-#endif
-					} else if (err == BCME_UNSUPPORTED) {
-						dfs_radar_disabled = TRUE;
-						WL_ERR(("does not support per_chan_info\n"));
-					}
-				}
-			}
-			if (!update)
-				(*n_cnt)++;
-		}
-
-	}
-	__wl_band_2ghz.n_channels = n_2g;
-	__wl_band_5ghz_a.n_channels = n_5g;
-	kfree(pbuf);
-	return err;
-}
-
-s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
-{
-	struct wiphy *wiphy;
-	struct net_device *dev;
-	u32 bandlist[3];
-	u32 nband = 0;
-	u32 i = 0;
-	s32 err = 0;
-	s32 index = 0;
-	s32 nmode = 0;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
-	u32 j = 0;
-	s32 vhtmode = 0;
-	s32 txstreams = 0;
-	s32 rxstreams = 0;
-	s32 ldpc_cap = 0;
-	s32 stbc_rx = 0;
-	s32 stbc_tx = 0;
-	s32 txbf_bfe_cap = 0;
-	s32 txbf_bfr_cap = 0;
-#endif 
-	bool rollback_lock = false;
-	s32 bw_cap = 0;
-	s32 cur_band = -1;
-	struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
-
-	if (cfg == NULL) {
-		cfg = g_bcm_cfg;
-		mutex_lock(&cfg->usr_sync);
-		rollback_lock = true;
-	}
-	dev = bcmcfg_to_prmry_ndev(cfg);
-
-	memset(bandlist, 0, sizeof(bandlist));
-	err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
-		sizeof(bandlist), false);
-	if (unlikely(err)) {
-		WL_ERR(("error read bandlist (%d)\n", err));
-		goto end_bands;
-	}
-	err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
-		sizeof(s32), false);
-	if (unlikely(err)) {
-		WL_ERR(("error (%d)\n", err));
-		goto end_bands;
-	}
-
-	err = wldev_iovar_getint(dev, "nmode", &nmode);
-	if (unlikely(err)) {
-		WL_ERR(("error reading nmode (%d)\n", err));
-	}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
-	err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
-	if (unlikely(err)) {
-		WL_ERR(("error reading vhtmode (%d)\n", err));
-	}
-
-	if (vhtmode) {
-		err = wldev_iovar_getint(dev, "txstreams", &txstreams);
-		if (unlikely(err)) {
-			WL_ERR(("error reading txstreams (%d)\n", err));
-		}
-
-		err = wldev_iovar_getint(dev, "rxstreams", &rxstreams);
-		if (unlikely(err)) {
-			WL_ERR(("error reading rxstreams (%d)\n", err));
-		}
-
-		err = wldev_iovar_getint(dev, "ldpc_cap", &ldpc_cap);
-		if (unlikely(err)) {
-			WL_ERR(("error reading ldpc_cap (%d)\n", err));
-		}
-
-		err = wldev_iovar_getint(dev, "stbc_rx", &stbc_rx);
-		if (unlikely(err)) {
-			WL_ERR(("error reading stbc_rx (%d)\n", err));
-		}
-
-		err = wldev_iovar_getint(dev, "stbc_tx", &stbc_tx);
-		if (unlikely(err)) {
-			WL_ERR(("error reading stbc_tx (%d)\n", err));
-		}
-
-		err = wldev_iovar_getint(dev, "txbf_bfe_cap", &txbf_bfe_cap);
-		if (unlikely(err)) {
-			WL_ERR(("error reading txbf_bfe_cap (%d)\n", err));
-		}
-
-		err = wldev_iovar_getint(dev, "txbf_bfr_cap", &txbf_bfr_cap);
-		if (unlikely(err)) {
-			WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
-		}
-	}
-#endif 
-
-	/* For nmode and vhtmode   check bw cap */
-	if (nmode ||
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
-		vhtmode ||
-#endif 
-		0) {
-		err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
-		if (unlikely(err)) {
-			WL_ERR(("error get mimo_bw_cap (%d)\n", err));
-		}
-	}
-
-	err = wl_construct_reginfo(cfg, bw_cap);
-	if (err) {
-		WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
-		if (err != BCME_UNSUPPORTED)
-			goto end_bands;
-		err = 0;
-	}
-	wiphy = bcmcfg_to_wiphy(cfg);
-	nband = bandlist[0];
-
-	for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
-		index = -1;
-		if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
-			bands[IEEE80211_BAND_5GHZ] =
-				&__wl_band_5ghz_a;
-			index = IEEE80211_BAND_5GHZ;
-			if (nmode && (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G))
-				bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
-			/* VHT capabilities. */
-			if (vhtmode) {
-				/* Supported */
-				bands[index]->vht_cap.vht_supported = TRUE;
-
-				for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
-					/* TX stream rates. */
-					if (j <= txstreams) {
-						VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
-							bands[index]->vht_cap.vht_mcs.tx_mcs_map);
-					} else {
-						VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
-							bands[index]->vht_cap.vht_mcs.tx_mcs_map);
-					}
-
-					/* RX stream rates. */
-					if (j <= rxstreams) {
-						VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
-							bands[index]->vht_cap.vht_mcs.rx_mcs_map);
-					} else {
-						VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
-							bands[index]->vht_cap.vht_mcs.rx_mcs_map);
-					}
-				}
-
-
-				/* Capabilities */
-				/* 80 MHz is mandatory */
-				bands[index]->vht_cap.cap |=
-					IEEE80211_VHT_CAP_SHORT_GI_80;
-
-				if (WL_BW_CAP_160MHZ(bw_cap)) {
-					bands[index]->vht_cap.cap |=
-						IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
-					bands[index]->vht_cap.cap |=
-						IEEE80211_VHT_CAP_SHORT_GI_160;
-				}
-
-				bands[index]->vht_cap.cap |=
-					IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
-
-				if (ldpc_cap)
-					bands[index]->vht_cap.cap |=
-						IEEE80211_VHT_CAP_RXLDPC;
-
-				if (stbc_tx)
-					bands[index]->vht_cap.cap |=
-						IEEE80211_VHT_CAP_TXSTBC;
-
-				if (stbc_rx)
-					bands[index]->vht_cap.cap |=
-						(stbc_rx << VHT_CAP_INFO_RX_STBC_SHIFT);
-
-				if (txbf_bfe_cap)
-					bands[index]->vht_cap.cap |=
-						IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
-
-				if (txbf_bfr_cap) {
-					bands[index]->vht_cap.cap |=
-						IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
-				}
-
-				if (txbf_bfe_cap || txbf_bfr_cap) {
-					bands[index]->vht_cap.cap |=
-						(2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT);
-					bands[index]->vht_cap.cap |=
-						((txstreams - 1) <<
-							VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT);
-					bands[index]->vht_cap.cap |=
-						IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
-				}
-
-				/* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
-				bands[index]->vht_cap.cap |=
-					(7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT);
-				WL_INFORM(("%s band[%d] vht_enab=%d vht_cap=%08x "
-					"vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
-					__FUNCTION__, index,
-					bands[index]->vht_cap.vht_supported,
-					bands[index]->vht_cap.cap,
-					bands[index]->vht_cap.vht_mcs.rx_mcs_map,
-					bands[index]->vht_cap.vht_mcs.tx_mcs_map));
-			}
-#endif 
-		}
-		else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
-			bands[IEEE80211_BAND_2GHZ] =
-				&__wl_band_2ghz;
-			index = IEEE80211_BAND_2GHZ;
-			if (bw_cap == WLC_N_BW_40ALL)
-				bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
-		}
-
-		if ((index >= 0) && nmode) {
-			bands[index]->ht_cap.cap |=
-				(IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
-			bands[index]->ht_cap.ht_supported = TRUE;
-			bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
-			bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
-			/* An HT shall support all EQM rates for one spatial stream */
-			bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
-		}
-
-	}
-
-	wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
-	wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
-
-	/* check if any bands populated otherwise makes 2Ghz as default */
-	if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
-		wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
-		/* Setup 2Ghz band as default */
-		wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
-	}
-
-	if (notify)
-		wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
-
-	end_bands:
-		if (rollback_lock)
-			mutex_unlock(&cfg->usr_sync);
-	return err;
-}
-
-static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg)
-{
-	s32 err = 0;
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-	struct wireless_dev *wdev = ndev->ieee80211_ptr;
-
-	WL_DBG(("In\n"));
-
-	err = dhd_config_dongle(cfg);
-	if (unlikely(err))
-		return err;
-
-	err = wl_config_ifmode(cfg, ndev, wdev->iftype);
-	if (unlikely(err && err != -EINPROGRESS)) {
-		WL_ERR(("wl_config_ifmode failed\n"));
-		if (err == -1) {
-			WL_ERR(("return error %d\n", err));
-			return err;
-		}
-	}
-	err = wl_update_wiphybands(cfg, true);
-	if (unlikely(err)) {
-		WL_ERR(("wl_update_wiphybands failed\n"));
-		if (err == -1) {
-			WL_ERR(("return error %d\n", err));
-			return err;
-		}
-	}
-
-	err = wl_create_event_handler(cfg);
-	if (err) {
-		WL_ERR(("wl_create_event_handler failed\n"));
-		return err;
-	}
-	wl_init_event_handler(cfg);
-
-	err = wl_init_scan(cfg);
-	if (err) {
-		WL_ERR(("wl_init_scan failed\n"));
-		return err;
-	}
-#ifdef DHD_LOSSLESS_ROAMING
-	if (timer_pending(&cfg->roam_timeout)) {
-		del_timer_sync(&cfg->roam_timeout);
-	}
-#endif /* DHD_LOSSLESS_ROAMING */
-
-	err = dhd_monitor_init(cfg->pub);
-
-	wl_set_drv_status(cfg, READY, ndev);
-	return err;
-}
-
-static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
-{
-	s32 err = 0;
-	unsigned long flags;
-	struct net_info *iter, *next;
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-#if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
-	struct net_device *p2p_net = cfg->p2p_net;
-#endif 
-#ifdef PROP_TXSTATUS_VSDB
-#if defined(BCMSDIO)
-	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
-#endif
-#endif /* PROP_TXSTATUS_VSDB */
-	WL_DBG(("In\n"));
-	/* Delete pm_enable_work */
-	wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
-
-#ifdef WL_NAN
-	wl_cfgnan_stop_handler(ndev, g_bcm_cfg, NULL, 0, NULL);
-#endif /* WL_NAN */
-
-	if (cfg->p2p_supported) {
-		wl_clr_p2p_status(cfg, GO_NEG_PHASE);
-#ifdef PROP_TXSTATUS_VSDB
-#if defined(BCMSDIO)
-		if (wl_cfgp2p_vif_created(cfg)) {
-			bool enabled = false;
-			dhd_wlfc_get_enable(dhd, &enabled);
-			if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
-				dhd->op_mode != DHD_FLAG_IBSS_MODE) {
-				dhd_wlfc_deinit(dhd);
-				cfg->wlfc_on = false;
-			}
-		}
-#endif 
-#endif /* PROP_TXSTATUS_VSDB */
-	}
-
-
-	/* If primary BSS is operational (for e.g SoftAP), bring it down */
-	if (wl_cfgp2p_bss_isup(ndev, 0)) {
-		if (wl_cfgp2p_bss(cfg, ndev, 0, 0) < 0)
-			WL_ERR(("BSS down failed \n"));
-	}
-
-	/* Check if cfg80211 interface is already down */
-	if (!wl_get_drv_status(cfg, READY, ndev))
-		return err;	/* it is even not ready */
-
-	/* clear all the security setting on primary Interface */
-	wl_cfg80211_clear_security(cfg);
-
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-	for_each_ndev(cfg, iter, next) {
-		if (iter->ndev) /* p2p discovery iface is null */
-			wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
-	}
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-
-#ifdef P2P_LISTEN_OFFLOADING
-	wl_cfg80211_p2plo_deinit(cfg);
-#endif /* P2P_LISTEN_OFFLOADING */
-
-	spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
-	if (cfg->scan_request) {
-		cfg80211_scan_done(cfg->scan_request, true);
-		cfg->scan_request = NULL;
-	}
-	spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-	for_each_ndev(cfg, iter, next) {
-		/* p2p discovery iface ndev ptr could be null */
-		if (iter->ndev == NULL)
-			continue;
-		wl_clr_drv_status(cfg, READY, iter->ndev);
-		wl_clr_drv_status(cfg, SCANNING, iter->ndev);
-		wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
-		wl_clr_drv_status(cfg, CONNECTING, iter->ndev);
-		wl_clr_drv_status(cfg, CONNECTED, iter->ndev);
-		wl_clr_drv_status(cfg, DISCONNECTING, iter->ndev);
-		wl_clr_drv_status(cfg, AP_CREATED, iter->ndev);
-		wl_clr_drv_status(cfg, AP_CREATING, iter->ndev);
-	}
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-	bcmcfg_to_prmry_ndev(cfg)->ieee80211_ptr->iftype =
-		NL80211_IFTYPE_STATION;
-#if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
-		if (p2p_net)
-			dev_close(p2p_net);
-#endif 
-
-	/* Avoid deadlock from wl_cfg80211_down */
-	mutex_unlock(&cfg->usr_sync);
-	wl_destroy_event_handler(cfg);
-	mutex_lock(&cfg->usr_sync);
-	wl_flush_eq(cfg);
-	wl_link_down(cfg);
-	if (cfg->p2p_supported) {
-		if (timer_pending(&cfg->p2p->listen_timer))
-			del_timer_sync(&cfg->p2p->listen_timer);
-		wl_cfgp2p_down(cfg);
-	}
-
-	if (timer_pending(&cfg->scan_timeout)) {
-		del_timer_sync(&cfg->scan_timeout);
-	}
-
-	DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
-
-	dhd_monitor_uninit();
-#ifdef WLAIBSS_MCHAN
-	bcm_cfg80211_del_ibss_if(cfg->wdev->wiphy, cfg->ibss_cfgdev);
-#endif /* WLAIBSS_MCHAN */
-
-#if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
-	/* Clean up if not removed already */
-	if (cfg->bss_cfgdev)
-		wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
-#endif /* defined (WL_VIRTUAL_APSTA) || defined (DUAL_STA_STATIC_IF) */
-
-#ifdef WL11U
-	/* Clear interworking element. */
-	if (cfg->wl11u) {
-		cfg->wl11u = FALSE;
-		cfg->iw_ie_len = 0;
-		memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
-	}
-#endif /* WL11U */
-
-#ifdef CUSTOMER_HW4_DEBUG
-	if (wl_scan_timeout_dbg_enabled)
-		wl_scan_timeout_dbg_clear();
-#endif /* CUSTOMER_HW4_DEBUG */
-
-	cfg->disable_roam_event = false;
-
-	DNGL_FUNC(dhd_cfg80211_down, (cfg));
-
-#ifdef DHD_IFDEBUG
-	/* Printout all netinfo entries */
-	wl_probe_wdev_all(cfg);
-#endif /* DHD_IFDEBUG */
-
-	return err;
-}
-
-s32 wl_cfg80211_up(void *para)
-{
-	struct bcm_cfg80211 *cfg;
-	s32 err = 0;
-	int val = 1;
-	dhd_pub_t *dhd;
-#ifdef DISABLE_PM_BCNRX
-	s32 interr = 0;
-	uint param = 0;
-	s8 iovbuf[WLC_IOCTL_SMLEN];
-#endif /* DISABLE_PM_BCNRX */
-
-	(void)para;
-	WL_DBG(("In\n"));
-	cfg = g_bcm_cfg;
-
-	if ((err = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_GET_VERSION, &val,
-		sizeof(int), false) < 0)) {
-		WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
-		return err;
-	}
-	val = dtoh32(val);
-	if (val != WLC_IOCTL_VERSION && val != 1) {
-		WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
-			val, WLC_IOCTL_VERSION));
-		return BCME_VERSION;
-	}
-	ioctl_version = val;
-	WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
-
-	mutex_lock(&cfg->usr_sync);
-	dhd = (dhd_pub_t *)(cfg->pub);
-	if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
-		err = wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg));
-		if (unlikely(err)) {
-			mutex_unlock(&cfg->usr_sync);
-			return err;
-		}
-	}
-	err = __wl_cfg80211_up(cfg);
-	if (unlikely(err))
-		WL_ERR(("__wl_cfg80211_up failed\n"));
-
-
-
-	/* IOVAR configurations with 'up' condition */
-#ifdef DISABLE_PM_BCNRX
-	bcm_mkiovar("pm_bcnrx", (char *)&param, 4, iovbuf, sizeof(iovbuf));
-	interr = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
-	if (unlikely(interr))
-		WL_ERR(("Set pm_bcnrx returned (%d)\n", interr));
-#endif /* DISABLE_PM_BCNRX */
-
-	mutex_unlock(&cfg->usr_sync);
-
-#ifdef WLAIBSS_MCHAN
-	bcm_cfg80211_add_ibss_if(cfg->wdev->wiphy, IBSS_IF_NAME);
-#endif /* WLAIBSS_MCHAN */
-
-#ifdef DUAL_STA_STATIC_IF
-#ifdef WL_VIRTUAL_APSTA
-#error "Both DUAL STA and DUAL_STA_STATIC_IF can't be enabled together"
-#endif
-	/* Static Interface support is currently supported only for STA only builds (without P2P) */
-	wl_cfg80211_create_iface(cfg->wdev->wiphy, NL80211_IFTYPE_STATION, NULL, "wlan%d");
-#endif /* DUAL_STA_STATIC_IF */
-
-	return err;
-}
-
-/* Private Event to Supplicant with indication that chip hangs */
-int wl_cfg80211_hang(struct net_device *dev, u16 reason)
-{
-	struct bcm_cfg80211 *cfg;
-	dhd_pub_t *dhd;
-#if defined(SOFTAP_SEND_HANGEVT)
-	/* specifc mac address used for hang event */
-	uint8 hang_mac[ETHER_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
-#endif /* SOFTAP_SEND_HANGEVT */
-	if (!g_bcm_cfg) {
-		return BCME_ERROR;
-	}
-
-	cfg = g_bcm_cfg;
-	dhd = (dhd_pub_t *)(cfg->pub);
-
-#ifdef DHD_USE_EXTENDED_HANG_REASON
-	if (dhd->hang_reason != 0) {
-		reason = dhd->hang_reason;
-	}
-#endif /* DHD_USE_EXTENDED_HANG_REASON */
-
-	WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32)(dhd->hang_reason)));
-	wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
-#if defined(SOFTAP_SEND_HANGEVT)
-	if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
-		cfg80211_del_sta(dev, hang_mac, GFP_ATOMIC);
-	} else
-#endif /* SOFTAP_SEND_HANGEVT */
-	{
-		CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
-	}
-	if (cfg != NULL) {
-		wl_link_down(cfg);
-	}
-	return 0;
-}
-
-s32 wl_cfg80211_down(void *para)
-{
-	struct bcm_cfg80211 *cfg;
-	s32 err = 0;
-
-	(void)para;
-	WL_DBG(("In\n"));
-	cfg = g_bcm_cfg;
-	mutex_lock(&cfg->usr_sync);
-	err = __wl_cfg80211_down(cfg);
-	mutex_unlock(&cfg->usr_sync);
-
-	return err;
-}
-
-static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item)
-{
-	unsigned long flags;
-	void *rptr = NULL;
-	struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
-
-	if (!profile)
-		return NULL;
-	spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
-	switch (item) {
-	case WL_PROF_SEC:
-		rptr = &profile->sec;
-		break;
-	case WL_PROF_ACT:
-		rptr = &profile->active;
-		break;
-	case WL_PROF_BSSID:
-		rptr = profile->bssid;
-		break;
-	case WL_PROF_SSID:
-		rptr = &profile->ssid;
-		break;
-	case WL_PROF_CHAN:
-		rptr = &profile->channel;
-		break;
-	}
-	spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
-	if (!rptr)
-		WL_ERR(("invalid item (%d)\n", item));
-	return rptr;
-}
-
-static s32
-wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const wl_event_msg_t *e, const void *data, s32 item)
-{
-	s32 err = 0;
-	const struct wlc_ssid *ssid;
-	unsigned long flags;
-	struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
-
-	if (!profile)
-		return WL_INVALID;
-	spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
-	switch (item) {
-	case WL_PROF_SSID:
-		ssid = (const wlc_ssid_t *) data;
-		memset(profile->ssid.SSID, 0,
-			sizeof(profile->ssid.SSID));
-		memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
-		profile->ssid.SSID_len = ssid->SSID_len;
-		break;
-	case WL_PROF_BSSID:
-		if (data)
-			memcpy(profile->bssid, data, ETHER_ADDR_LEN);
-		else
-			memset(profile->bssid, 0, ETHER_ADDR_LEN);
-		break;
-	case WL_PROF_SEC:
-		memcpy(&profile->sec, data, sizeof(profile->sec));
-		break;
-	case WL_PROF_ACT:
-		profile->active = *(const bool *)data;
-		break;
-	case WL_PROF_BEACONINT:
-		profile->beacon_interval = *(const u16 *)data;
-		break;
-	case WL_PROF_DTIMPERIOD:
-		profile->dtim_period = *(const u8 *)data;
-		break;
-	case WL_PROF_CHAN:
-		profile->channel = *(const u32*)data;
-		break;
-	default:
-		err = -EOPNOTSUPP;
-		break;
-	}
-	spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
-
-	if (err == -EOPNOTSUPP)
-		WL_ERR(("unsupported item (%d)\n", item));
-
-	return err;
-}
-
-void wl_cfg80211_dbg_level(u32 level)
-{
-	/*
-	* prohibit to change debug level
-	* by insmod parameter.
-	* eventually debug level will be configured
-	* in compile time by using CONFIG_XXX
-	*/
-	/* wl_dbg_level = level; */
-}
-
-static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev)
-{
-	return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS;
-}
-
-static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg)
-{
-	return cfg->ibss_starter;
-}
-
-static void wl_rst_ie(struct bcm_cfg80211 *cfg)
-{
-	struct wl_ie *ie = wl_to_ie(cfg);
-
-	ie->offset = 0;
-}
-
-static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
-{
-	struct wl_ie *ie = wl_to_ie(cfg);
-	s32 err = 0;
-
-	if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
-		WL_ERR(("ei crosses buffer boundary\n"));
-		return -ENOSPC;
-	}
-	ie->buf[ie->offset] = t;
-	ie->buf[ie->offset + 1] = l;
-	memcpy(&ie->buf[ie->offset + 2], v, l);
-	ie->offset += l + 2;
-
-	return err;
-}
-
-static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
-	bool roam)
-{
-	u8 *ssidie;
-	/* cfg80211_find_ie defined in kernel returning const u8 */
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-	ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-	if (!ssidie)
-		return;
-	if (ssidie[1] != bi->SSID_len) {
-		if (ssidie[1]) {
-			WL_ERR(("%s: Wrong SSID len: %d != %d\n",
-				__FUNCTION__, ssidie[1], bi->SSID_len));
-		}
-		if (roam) {
-			WL_ERR(("Changing the SSID Info.\n"));
-			memmove(ssidie + bi->SSID_len + 2,
-				(ssidie + 2) + ssidie[1],
-				*ie_size - (ssidie + 2 + ssidie[1] - ie_stream));
-			memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
-			*ie_size = *ie_size + bi->SSID_len - ssidie[1];
-			ssidie[1] = bi->SSID_len;
-		}
-		return;
-	}
-	if (*(ssidie + 2) == '\0')
-		 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
-	return;
-}
-
-static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
-{
-	struct wl_ie *ie = wl_to_ie(cfg);
-	s32 err = 0;
-
-	if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
-		WL_ERR(("ei_stream crosses buffer boundary\n"));
-		return -ENOSPC;
-	}
-	memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
-	ie->offset += ie_size;
-
-	return err;
-}
-
-static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
-{
-	struct wl_ie *ie = wl_to_ie(cfg);
-	s32 err = 0;
-
-	if (unlikely(ie->offset > dst_size)) {
-		WL_ERR(("dst_size is not enough\n"));
-		return -ENOSPC;
-	}
-	memcpy(dst, &ie->buf[0], ie->offset);
-
-	return err;
-}
-
-static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
-{
-	struct wl_ie *ie = wl_to_ie(cfg);
-
-	return ie->offset;
-}
-
-static void wl_link_up(struct bcm_cfg80211 *cfg)
-{
-	cfg->link_up = true;
-}
-
-static void wl_link_down(struct bcm_cfg80211 *cfg)
-{
-	struct wl_connect_info *conn_info = wl_to_conn(cfg);
-
-	WL_DBG(("In\n"));
-	cfg->link_up = false;
-	conn_info->req_ie_len = 0;
-	conn_info->resp_ie_len = 0;
-}
-
-static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&cfg->eq_lock, flags);
-	return flags;
-}
-
-static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags)
-{
-	spin_unlock_irqrestore(&cfg->eq_lock, flags);
-}
-
-static void wl_init_eq_lock(struct bcm_cfg80211 *cfg)
-{
-	spin_lock_init(&cfg->eq_lock);
-}
-
-static void wl_delay(u32 ms)
-{
-	if (in_atomic() || (ms < jiffies_to_msecs(1))) {
-		OSL_DELAY(ms*1000);
-	} else {
-		OSL_SLEEP(ms);
-	}
-}
-
-s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct ether_addr primary_mac;
-	if (!cfg->p2p)
-		return -1;
-	if (!p2p_is_on(cfg)) {
-		get_primary_mac(cfg, &primary_mac);
-		wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
-	} else {
-		memcpy(p2pdev_addr->octet, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE).octet,
-			ETHER_ADDR_LEN);
-	}
-
-	return 0;
-}
-s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
-{
-	struct bcm_cfg80211 *cfg;
-
-	cfg = g_bcm_cfg;
-
-	return wl_cfgp2p_set_p2p_noa(cfg, net, buf, len);
-}
-
-s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
-{
-	struct bcm_cfg80211 *cfg;
-	cfg = g_bcm_cfg;
-
-	return wl_cfgp2p_get_p2p_noa(cfg, net, buf, len);
-}
-
-s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
-{
-	struct bcm_cfg80211 *cfg;
-	cfg = g_bcm_cfg;
-
-	return wl_cfgp2p_set_p2p_ps(cfg, net, buf, len);
-}
-
-s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
-{
-	struct bcm_cfg80211 *cfg;
-	cfg = g_bcm_cfg;
-
-	return wl_cfgp2p_set_p2p_ecsa(cfg, net, buf, len);
-}
-
-#ifdef P2PLISTEN_AP_SAMECHN
-s32 wl_cfg80211_set_p2p_resp_ap_chn(struct net_device *net, s32 enable)
-{
-	s32 ret = wldev_iovar_setint(net, "p2p_resp_ap_chn", enable);
-
-	if ((ret == 0) && enable) {
-		/* disable PM for p2p responding on infra AP channel */
-		s32 pm = PM_OFF;
-
-		ret = wldev_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), true);
-	}
-
-	return ret;
-}
-#endif /* P2PLISTEN_AP_SAMECHN */
-
-s32 wl_cfg80211_channel_to_freq(u32 channel)
-{
-	int freq = 0;
-
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
-	freq = ieee80211_channel_to_frequency(channel);
-#else
-	{
-		u16 band = 0;
-		if (channel <= CH_MAX_2G_CHANNEL)
-			band = IEEE80211_BAND_2GHZ;
-		else
-			band = IEEE80211_BAND_5GHZ;
-		freq = ieee80211_channel_to_frequency(channel, band);
-	}
-#endif
-	return freq;
-}
-
-
-#ifdef WLTDLS
-static s32
-wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data) {
-
-	struct net_device *ndev = NULL;
-	u32 reason = ntoh32(e->reason);
-	s8 *msg = NULL;
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	switch (reason) {
-	case WLC_E_TDLS_PEER_DISCOVERED :
-		msg = " TDLS PEER DISCOVERD ";
-		break;
-	case WLC_E_TDLS_PEER_CONNECTED :
-#ifdef PCIE_FULL_DONGLE
-		dhd_tdls_update_peer_info(ndev, TRUE, (uint8 *)&e->addr.octet[0]);
-#endif /* PCIE_FULL_DONGLE */
-		if (cfg->tdls_mgmt_frame) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-			cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
-				cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
-				0);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
-			cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
-				cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
-				0, GFP_ATOMIC);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
-	defined(WL_COMPAT_WIRELESS)
-			cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
-				cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
-				GFP_ATOMIC);
-#else
-			cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
-				cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
-				GFP_ATOMIC);
-#endif /* LINUX_VERSION >= VERSION(3, 12, 0) */
-		}
-		msg = " TDLS PEER CONNECTED ";
-		break;
-	case WLC_E_TDLS_PEER_DISCONNECTED :
-#ifdef PCIE_FULL_DONGLE
-		dhd_tdls_update_peer_info(ndev, FALSE, (uint8 *)&e->addr.octet[0]);
-#endif /* PCIE_FULL_DONGLE */
-		if (cfg->tdls_mgmt_frame) {
-			kfree(cfg->tdls_mgmt_frame);
-			cfg->tdls_mgmt_frame = NULL;
-			cfg->tdls_mgmt_freq = 0;
-		}
-		msg = "TDLS PEER DISCONNECTED ";
-		break;
-	}
-	if (msg) {
-		WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
-			(bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
-	}
-	return 0;
-
-}
-#endif  /* WLTDLS */
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
-static s32
-#if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
-	KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
-wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
-        u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
-        u32 peer_capability, const u8 *data, size_t len)
-#elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
-		(LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
-wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
-	const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
-	u32 peer_capability, const u8 *data, size_t len)
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
-	const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
-	u32 peer_capability, bool initiator, const u8 *data, size_t len)
-#else
-wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
-	u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
-	size_t len)
-#endif  /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
-{
-	s32 ret = 0;
-#ifdef WLTDLS
-	struct bcm_cfg80211 *cfg;
-	tdls_wfd_ie_iovar_t info;
-	memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
-	cfg = g_bcm_cfg;
-
-#if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
-	/* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
-	* and that cuases build error
-	*/
-	BCM_REFERENCE(peer_capability);
-#endif  /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
-
-	switch (action_code) {
-	/* We need to set TDLS Wifi Display IE to firmware
-	 * using tdls_wfd_ie iovar
-	 */
-	case WLAN_TDLS_SET_PROBE_WFD_IE:
-		WL_ERR(("%s WLAN_TDLS_SET_PROBE_WFD_IE\n", __FUNCTION__));
-		info.mode = TDLS_WFD_PROBE_IE_TX;
-		memcpy(&info.data, data, len);
-		info.length = len;
-		break;
-	case WLAN_TDLS_SET_SETUP_WFD_IE:
-		WL_ERR(("%s WLAN_TDLS_SET_SETUP_WFD_IE\n", __FUNCTION__));
-		info.mode = TDLS_WFD_IE_TX;
-		memcpy(&info.data, data, len);
-		info.length = len;
-		break;
-	case WLAN_TDLS_SET_WFD_ENABLED:
-		WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_ENABLED\n", __FUNCTION__));
-		dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), true);
-		goto out;
-	case WLAN_TDLS_SET_WFD_DISABLED:
-		WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_DISABLED\n", __FUNCTION__));
-		dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), false);
-		goto out;
-	default:
-		WL_ERR(("Unsupported action code : %d\n", action_code));
-		goto out;
-	}
-
-	ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-
-	if (ret) {
-		WL_ERR(("tdls_wfd_ie error %d\n", ret));
-	}
-out:
-#endif /* WLTDLS */
-	return ret;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
-static s32
-wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
-	const u8 *peer, enum nl80211_tdls_operation oper)
-#else
-static s32
-wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
-	u8 *peer, enum nl80211_tdls_operation oper)
-#endif
-{
-	s32 ret = 0;
-#ifdef WLTDLS
-	struct bcm_cfg80211 *cfg;
-	tdls_iovar_t info;
-	dhd_pub_t *dhdp;
-	bool tdls_auto_mode = false;
-	cfg = g_bcm_cfg;
-	dhdp = (dhd_pub_t *)(cfg->pub);
-	memset(&info, 0, sizeof(tdls_iovar_t));
-	if (peer) {
-		memcpy(&info.ea, peer, ETHER_ADDR_LEN);
-	} else {
-		return -1;
-	}
-	switch (oper) {
-	case NL80211_TDLS_DISCOVERY_REQ:
-		/* If the discovery request is broadcast then we need to set
-		 * info.mode to Tunneled Probe Request
-		 */
-		if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
-			info.mode = TDLS_MANUAL_EP_WFD_TPQ;
-			WL_ERR(("%s TDLS TUNNELED PRBOBE REQUEST\n", __FUNCTION__));
-		} else {
-			info.mode = TDLS_MANUAL_EP_DISCOVERY;
-		}
-		break;
-	case NL80211_TDLS_SETUP:
-		if (dhdp->tdls_mode == true) {
-			info.mode = TDLS_MANUAL_EP_CREATE;
-			tdls_auto_mode = false;
-			ret = dhd_tdls_enable(dev, false, tdls_auto_mode, NULL);
-			if (ret < 0) {
-				return ret;
-			}
-		} else {
-			tdls_auto_mode = true;
-		}
-		break;
-	case NL80211_TDLS_TEARDOWN:
-		info.mode = TDLS_MANUAL_EP_DELETE;
-		break;
-	default:
-		WL_ERR(("Unsupported operation : %d\n", oper));
-		goto out;
-	}
-	/* turn on TDLS */
-	ret = dhd_tdls_enable(dev, true, tdls_auto_mode, NULL);
-	if (ret < 0) {
-		return ret;
-	}
-	if (info.mode) {
-		ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
-			cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-		if (ret) {
-			WL_ERR(("tdls_endpoint error %d\n", ret));
-		}
-	}
-out:
-#endif /* WLTDLS */
-	return ret;
-}
-#endif 
-
-s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *ndev, char *buf, int len,
-	enum wl_management_type type)
-{
-	struct bcm_cfg80211 *cfg;
-	s32 ret = 0;
-	struct ether_addr primary_mac;
-	s32 bssidx = 0;
-	s32 pktflag = 0;
-	cfg = g_bcm_cfg;
-
-	if (wl_get_drv_status(cfg, AP_CREATING, ndev)) {
-		/* Vendor IEs should be set to FW
-		 * after SoftAP interface is brought up
-		 */
-		WL_DBG(("Skipping set IE since AP is not up \n"));
-		goto exit;
-	} else  if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
-		/* Either stand alone AP case or P2P discovery */
-		if (wl_get_drv_status(cfg, AP_CREATED, ndev)) {
-			/* Stand alone AP case on primary interface */
-			WL_DBG(("Apply IEs for Primary AP Interface \n"));
-			bssidx = 0;
-		} else {
-			/* P2P Discovery case (p2p listen) */
-			if (!cfg->p2p->on) {
-				/* Turn on Discovery interface */
-				get_primary_mac(cfg, &primary_mac);
-				wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
-				p2p_on(cfg) = true;
-				ret = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
-				if (unlikely(ret)) {
-					WL_ERR(("Enable discovery failed \n"));
-					goto exit;
-				}
-			}
-			WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
-			ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
-			bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-		}
-	} else {
-		/* Virtual AP/ P2P Group Interface */
-		WL_DBG(("Apply IEs for iface:%s\n", ndev->name));
-		bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
-	}
-
-	if (ndev != NULL) {
-		switch (type) {
-			case WL_BEACON:
-				pktflag = VNDR_IE_BEACON_FLAG;
-				break;
-			case WL_PROBE_RESP:
-				pktflag = VNDR_IE_PRBRSP_FLAG;
-				break;
-			case WL_ASSOC_RESP:
-				pktflag = VNDR_IE_ASSOCRSP_FLAG;
-				break;
-		}
-		if (pktflag) {
-			ret = wl_cfg80211_set_mgmt_vndr_ies(cfg,
-				ndev_to_cfgdev(ndev), bssidx, pktflag, buf, len);
-		}
-	}
-exit:
-	return ret;
-}
-
-#ifdef WL_SUPPORT_AUTO_CHANNEL
-static s32
-wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
-{
-	u32 val = 0;
-	s32 ret = BCME_ERROR;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wiphy *wiphy;
-	/* Disable mpc, to avoid automatic interface down. */
-	val = 0;
-
-	wiphy = bcmcfg_to_wiphy(cfg);
-	if (wl_check_dongle_idle(wiphy) != TRUE) {
-		WL_ERR(("FW is busy to add interface"));
-		return ret;
-	}
-	ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
-		sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
-		&cfg->ioctl_buf_sync);
-	if (ret < 0) {
-		WL_ERR(("set 'mpc' failed, error = %d\n", ret));
-		goto done;
-	}
-
-	/* Set interface up, explicitly. */
-	val = 1;
-
-	ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
-	if (ret < 0) {
-		WL_ERR(("set interface up failed, error = %d\n", ret));
-		goto done;
-	}
-
-	/* Stop all scan explicitly, till auto channel selection complete. */
-	wl_set_drv_status(cfg, SCANNING, ndev);
-	if (cfg->escan_info.ndev == NULL) {
-		ret = BCME_OK;
-		goto done;
-	}
-	ret = wl_notify_escan_complete(cfg, ndev, true, true);
-	if (ret < 0) {
-		WL_ERR(("set scan abort failed, error = %d\n", ret));
-		goto done;
-	}
-
-done:
-	return ret;
-}
-
-static bool
-wl_cfg80211_valid_channel_p2p(int channel)
-{
-	bool valid = false;
-
-	/* channel 1 to 14 */
-	if ((channel >= 1) && (channel <= 14)) {
-		valid = true;
-	}
-	/* channel 36 to 48 */
-	else if ((channel >= 36) && (channel <= 48)) {
-		valid = true;
-	}
-	/* channel 149 to 161 */
-	else if ((channel >= 149) && (channel <= 161)) {
-		valid = true;
-	}
-	else {
-		valid = false;
-		WL_INFORM(("invalid P2P chanspec, channel = %d\n", channel));
-	}
-
-	return valid;
-}
-
-s32
-wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
-{
-	s32 ret = BCME_ERROR;
-	struct bcm_cfg80211 *cfg = NULL;
-	wl_uint32_list_t *list = NULL;
-	chanspec_t chanspec = 0;
-
-	memset(buf, 0, buflen);
-
-	cfg = g_bcm_cfg;
-	list = (wl_uint32_list_t *)buf;
-	list->count = htod32(WL_NUMCHANSPECS);
-
-	/* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
-	chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
-		WL_CHANSPEC_CTL_SB_NONE);
-	chanspec = wl_chspec_host_to_driver(chanspec);
-
-	ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
-		sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
-	if (ret < 0) {
-		WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
-	}
-
-	return ret;
-}
-
-s32
-wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
-{
-	u32 channel = 0;
-	s32 ret = BCME_ERROR;
-	s32 i = 0;
-	s32 j = 0;
-	struct bcm_cfg80211 *cfg = NULL;
-	wl_uint32_list_t *list = NULL;
-	chanspec_t chanspec = 0;
-
-	memset(buf, 0, buflen);
-
-	cfg = g_bcm_cfg;
-	list = (wl_uint32_list_t *)buf;
-	list->count = htod32(WL_NUMCHANSPECS);
-
-	/* Restrict channels to 5GHz, 20MHz BW, no SB. */
-	chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
-		WL_CHANSPEC_CTL_SB_NONE);
-	chanspec = wl_chspec_host_to_driver(chanspec);
-
-	ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
-		sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
-	if (ret < 0) {
-		WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
-		goto done;
-	}
-
-	/* Skip DFS and inavlid P2P channel. */
-	for (i = 0, j = 0; i < dtoh32(list->count); i++) {
-		chanspec = (chanspec_t) dtoh32(list->element[i]);
-		channel = CHSPEC_CHANNEL(chanspec);
-
-		ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
-		if (ret < 0) {
-			WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
-			goto done;
-		}
-
-		if (CHANNEL_IS_RADAR(channel) ||
-			!(wl_cfg80211_valid_channel_p2p(CHSPEC_CHANNEL(chanspec)))) {
-			continue;
-		} else {
-			list->element[j] = list->element[i];
-		}
-
-		j++;
-	}
-
-	list->count = j;
-
-done:
-	return ret;
-}
-
-static s32
-wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
-	int *channel)
-{
-	s32 ret = BCME_ERROR;
-	int chosen = 0;
-	int retry = 0;
-
-	/* Start auto channel selection scan. */
-	ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
-	if (ret < 0) {
-		WL_ERR(("can't start auto channel scan, error = %d\n", ret));
-		*channel = 0;
-		goto done;
-	}
-
-	/* Wait for auto channel selection, worst case possible delay is 5250ms. */
-	retry = CHAN_SEL_RETRY_COUNT;
-
-	while (retry--) {
-		OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
-
-		ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
-			false);
-		if ((ret == 0) && (dtoh32(chosen) != 0)) {
-			*channel = (u16)(chosen & 0x00FF);
-			WL_INFORM(("selected channel = %d\n", *channel));
-			break;
-		}
-		WL_INFORM(("attempt = %d, ret = %d, chosen = %d\n",
-			(CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
-	}
-
-	if (retry <= 0)	{
-		WL_ERR(("failure, auto channel selection timed out\n"));
-		*channel = 0;
-		ret = BCME_ERROR;
-	}
-
-done:
-	return ret;
-}
-
-static s32
-wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
-{
-	u32 val = 0;
-	s32 ret = BCME_ERROR;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	/* Clear scan stop driver status. */
-	wl_clr_drv_status(cfg, SCANNING, ndev);
-
-	/* Enable mpc back to 1, irrespective of initial state. */
-	val = 1;
-
-	ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
-		sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
-		&cfg->ioctl_buf_sync);
-	if (ret < 0) {
-		WL_ERR(("set 'mpc' failed, error = %d\n", ret));
-	}
-
-	return ret;
-}
-
-s32
-wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
-{
-	int channel = 0;
-	s32 ret = BCME_ERROR;
-	u8 *buf = NULL;
-	char *pos = cmd;
-	struct bcm_cfg80211 *cfg = NULL;
-	struct net_device *ndev = NULL;
-
-	memset(cmd, 0, total_len);
-
-	buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
-	if (buf == NULL) {
-		WL_ERR(("failed to allocate chanspec buffer\n"));
-		return -ENOMEM;
-	}
-
-	/*
-	 * Always use primary interface, irrespective of interface on which
-	 * command came.
-	 */
-	cfg = g_bcm_cfg;
-	ndev = bcmcfg_to_prmry_ndev(cfg);
-
-	/*
-	 * Make sure that FW and driver are in right state to do auto channel
-	 * selection scan.
-	 */
-	ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
-	if (ret < 0) {
-		WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
-		goto done;
-	}
-
-	/* Best channel selection in 2.4GHz band. */
-	ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
-	if (ret < 0) {
-		WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
-		goto done;
-	}
-
-	ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
-		&channel);
-	if (ret < 0) {
-		WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
-		goto done;
-	}
-
-	if (CHANNEL_IS_2G(channel)) {
-		channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
-	} else {
-		WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
-		channel = 0;
-	}
-
-	pos += snprintf(pos, total_len, "%04d ", channel);
-
-	/* Best channel selection in 5GHz band. */
-	ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
-	if (ret < 0) {
-		WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
-		goto done;
-	}
-
-	ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
-		&channel);
-	if (ret < 0) {
-		WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
-		goto done;
-	}
-
-	if (CHANNEL_IS_5G(channel)) {
-		channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
-	} else {
-		WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
-		channel = 0;
-	}
-
-	pos += snprintf(pos, total_len, "%04d ", channel);
-
-	/* Set overall best channel same as 5GHz best channel. */
-	pos += snprintf(pos, total_len, "%04d ", channel);
-
-done:
-	if (NULL != buf) {
-		kfree(buf);
-	}
-
-	/* Restore FW and driver back to normal state. */
-	ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
-	if (ret < 0) {
-		WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
-	}
-
-	return (pos - cmd);
-}
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
-
-static const struct rfkill_ops wl_rfkill_ops = {
-	.set_block = wl_rfkill_set
-};
-
-static int wl_rfkill_set(void *data, bool blocked)
-{
-	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
-
-	WL_DBG(("Enter \n"));
-	WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
-
-	if (!cfg)
-		return -EINVAL;
-
-	cfg->rf_blocked = blocked;
-
-	return 0;
-}
-
-static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup)
-{
-	s32 err = 0;
-
-	WL_DBG(("Enter \n"));
-	if (!cfg)
-		return -EINVAL;
-	if (setup) {
-		cfg->rfkill = rfkill_alloc("brcmfmac-wifi",
-			wl_cfg80211_get_parent_dev(),
-			RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)cfg);
-
-		if (!cfg->rfkill) {
-			err = -ENOMEM;
-			goto err_out;
-		}
-
-		err = rfkill_register(cfg->rfkill);
-
-		if (err)
-			rfkill_destroy(cfg->rfkill);
-	} else {
-		if (!cfg->rfkill) {
-			err = -ENOMEM;
-			goto err_out;
-		}
-
-		rfkill_unregister(cfg->rfkill);
-		rfkill_destroy(cfg->rfkill);
-	}
-
-err_out:
-	return err;
-}
-
-#ifdef DEBUGFS_CFG80211
-/**
-* Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
-* to turn on SCAN and DBG log.
-* To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
-* To see current setting of debug level,
-* cat /sys/kernel/debug/dhd/debug_level
-*/
-static ssize_t
-wl_debuglevel_write(struct file *file, const char __user *userbuf,
-	size_t count, loff_t *ppos)
-{
-	char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
-	char *params, *token, *colon;
-	uint i, tokens, log_on = 0;
-	memset(tbuf, 0, sizeof(tbuf));
-	memset(sublog, 0, sizeof(sublog));
-	if (copy_from_user(&tbuf, userbuf, min_t(size_t, (sizeof(tbuf) - 1), count)))
-		return -EFAULT;
-
-	params = &tbuf[0];
-	colon = strchr(params, '\n');
-	if (colon != NULL)
-		*colon = '\0';
-	while ((token = strsep(&params, " ")) != NULL) {
-		memset(sublog, 0, sizeof(sublog));
-		if (token == NULL || !*token)
-			break;
-		if (*token == '\0')
-			continue;
-		colon = strchr(token, ':');
-		if (colon != NULL) {
-			*colon = ' ';
-		}
-		tokens = sscanf(token, "%s %u", sublog, &log_on);
-		if (colon != NULL)
-			*colon = ':';
-
-		if (tokens == 2) {
-				for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
-					if (!strncmp(sublog, sublogname_map[i].sublogname,
-						strlen(sublogname_map[i].sublogname))) {
-						if (log_on)
-							wl_dbg_level |=
-							(sublogname_map[i].log_level);
-						else
-							wl_dbg_level &=
-							~(sublogname_map[i].log_level);
-					}
-				}
-		} else
-			WL_ERR(("%s: can't parse '%s' as a "
-			       "SUBMODULE:LEVEL (%d tokens)\n",
-			       tbuf, token, tokens));
-
-
-	}
-	return count;
-}
-
-static ssize_t
-wl_debuglevel_read(struct file *file, char __user *user_buf,
-	size_t count, loff_t *ppos)
-{
-	char *param;
-	char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
-	uint i;
-	memset(tbuf, 0, sizeof(tbuf));
-	param = &tbuf[0];
-	for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
-		param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
-			sublogname_map[i].sublogname,
-			(wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
-	}
-	*param = '\n';
-	return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
-
-}
-static const struct file_operations fops_debuglevel = {
-	.open = NULL,
-	.write = wl_debuglevel_write,
-	.read = wl_debuglevel_read,
-	.owner = THIS_MODULE,
-	.llseek = NULL,
-};
-
-static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg)
-{
-	s32 err = 0;
-	struct dentry *_dentry;
-	if (!cfg)
-		return -EINVAL;
-	cfg->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
-	if (!cfg->debugfs || IS_ERR(cfg->debugfs)) {
-		if (cfg->debugfs == ERR_PTR(-ENODEV))
-			WL_ERR(("Debugfs is not enabled on this kernel\n"));
-		else
-			WL_ERR(("Can not create debugfs directory\n"));
-		cfg->debugfs = NULL;
-		goto exit;
-
-	}
-	_dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
-		cfg->debugfs, cfg, &fops_debuglevel);
-	if (!_dentry || IS_ERR(_dentry)) {
-		WL_ERR(("failed to create debug_level debug file\n"));
-		wl_free_debugfs(cfg);
-	}
-exit:
-	return err;
-}
-static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg)
-{
-	if (!cfg)
-		return -EINVAL;
-	if (cfg->debugfs)
-		debugfs_remove_recursive(cfg->debugfs);
-	cfg->debugfs = NULL;
-	return 0;
-}
-#endif /* DEBUGFS_CFG80211 */
-
-struct device *wl_cfg80211_get_parent_dev(void)
-{
-	return cfg80211_parent_dev;
-}
-
-void wl_cfg80211_set_parent_dev(void *dev)
-{
-	cfg80211_parent_dev = dev;
-}
-
-static void wl_cfg80211_clear_parent_dev(void)
-{
-	cfg80211_parent_dev = NULL;
-}
-
-void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
-{
-	wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr", NULL,
-		0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
-	memcpy(mac->octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
-}
-static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role)
-{
-	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-	if (((dev_role == NL80211_IFTYPE_AP) &&
-		!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
-		((dev_role == NL80211_IFTYPE_P2P_GO) &&
-		!(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
-	{
-		WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
-		return false;
-	}
-	return true;
-}
-
-int wl_cfg80211_do_driver_init(struct net_device *net)
-{
-	struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
-
-	if (!cfg || !cfg->wdev)
-		return -EINVAL;
-
-	if (dhd_do_driver_init(cfg->wdev->netdev) < 0)
-		return -1;
-
-	return 0;
-}
-
-void wl_cfg80211_enable_trace(bool set, u32 level)
-{
-	if (set)
-		wl_dbg_level = level & WL_DBG_LEVEL;
-	else
-		wl_dbg_level |= (WL_DBG_LEVEL & level);
-}
-#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
-	2, 0))
-static s32
-wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
-	bcm_struct_cfgdev *cfgdev, u64 cookie)
-{
-	/* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
-	 * is passed with CMD_FRAME. This callback is supposed to cancel
-	 * the OFFCHANNEL Wait. Since we are already taking care of that
-	 *  with the tx_mgmt logic, do nothing here.
-	 */
-
-	return 0;
-}
-#endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
-
-#ifdef WL11U
-bcm_tlv_t *
-wl_cfg80211_find_interworking_ie(u8 *parse, u32 len)
-{
-	bcm_tlv_t *ie;
-
-	while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_INTERWORKING_ID))) {
-			return (bcm_tlv_t *)ie;
-	}
-	return NULL;
-}
-
-
-static s32
-wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
-            uint8 ie_id, uint8 *data, uint8 data_len)
-{
-	s32 err = BCME_OK;
-	s32 buf_len;
-	s32 iecount;
-	ie_setbuf_t *ie_setbuf;
-
-	if (ie_id != DOT11_MNG_INTERWORKING_ID)
-		return BCME_UNSUPPORTED;
-
-	/* Validate the pktflag parameter */
-	if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
-	            VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
-	            VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
-	            VNDR_IE_CUSTOM_FLAG))) {
-		WL_ERR(("cfg80211 Add IE: Invalid packet flag 0x%x\n", pktflag));
-		return -1;
-	}
-
-	/* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
-	pktflag = htod32(pktflag);
-
-	buf_len = sizeof(ie_setbuf_t) + data_len - 1;
-	ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
-
-	if (!ie_setbuf) {
-		WL_ERR(("Error allocating buffer for IE\n"));
-		return -ENOMEM;
-	}
-
-	if (cfg->iw_ie_len == data_len && !memcmp(cfg->iw_ie, data, data_len)) {
-		WL_ERR(("Previous IW IE is equals to current IE\n"));
-		err = BCME_OK;
-		goto exit;
-	}
-
-	strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
-	ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
-
-	/* Buffer contains only 1 IE */
-	iecount = htod32(1);
-	memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
-	memcpy((void *)&ie_setbuf->ie_buffer.ie_list[0].pktflag, &pktflag, sizeof(uint32));
-
-	/* Now, add the IE to the buffer */
-	ie_setbuf->ie_buffer.ie_list[0].ie_data.id = ie_id;
-
-	/* if already set with previous values, delete it first */
-	if (cfg->iw_ie_len != 0) {
-		WL_DBG(("Different IW_IE was already set. clear first\n"));
-
-		ie_setbuf->ie_buffer.ie_list[0].ie_data.len = 0;
-
-		err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
-			cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-
-		if (err != BCME_OK)
-			goto exit;
-	}
-
-	ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
-	memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
-
-	err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-
-	if (err == BCME_OK) {
-		memcpy(cfg->iw_ie, data, data_len);
-		cfg->iw_ie_len = data_len;
-		cfg->wl11u = TRUE;
-
-		err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
-	}
-
-exit:
-	if (ie_setbuf)
-		kfree(ie_setbuf);
-	return err;
-}
-#endif /* WL11U */
-
-s32
-wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data, char *command, int total_len)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	char ioctl_buf[50];
-	int err = 0;
-	uint32 val = 0;
-	chanspec_t chanspec = 0;
-	int abort;
-	int bytes_written = 0;
-	wl_dfs_ap_move_status_t *status;
-	char chanbuf[CHANSPEC_STR_LEN];
-	const char *dfs_state_str[DFS_SCAN_S_MAX] = {
-		"Radar Free On Channel",
-		"Radar Found On Channel",
-		"Radar Scan In Progress",
-		"Radar Scan Aborted",
-		"RSDB Mode switch in Progress For Scan"
-	};
-	if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
-		bytes_written = snprintf(command, total_len, "AP is not UP\n");
-		return bytes_written;
-	}
-	if (!*data) {
-		if ((err = wldev_iovar_getbuf(ndev, "dfs_ap_move", NULL, 0,
-				cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
-			WL_ERR(("setting dfs_ap_move failed with err=%d \n", err));
-			return err;
-		}
-		status = (wl_dfs_ap_move_status_t *)cfg->ioctl_buf;
-
-		if (status->version != WL_DFS_AP_MOVE_VERSION) {
-			err = BCME_UNSUPPORTED;
-			WL_ERR(("err=%d version=%d\n", err, status->version));
-			return err;
-		}
-
-		if (status->move_status != (int8) DFS_SCAN_S_IDLE) {
-			chanspec = wl_chspec_driver_to_host(status->chanspec);
-			if (chanspec != 0 && chanspec != INVCHANSPEC) {
-				wf_chspec_ntoa(chanspec, chanbuf);
-				bytes_written = snprintf(command, total_len,
-					"AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
-			}
-			bytes_written += snprintf(command + bytes_written, total_len,
-					 "%s\n", dfs_state_str[status->move_status]);
-			return bytes_written;
-		} else {
-			bytes_written = snprintf(command, total_len, "dfs AP move in IDLE state\n");
-			return bytes_written;
-		}
-
-	}
-
-	abort = bcm_atoi(data);
-	if (abort == -1) {
-		if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &abort,
-				sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
-			WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
-			return err;
-		}
-	} else {
-		chanspec = wf_chspec_aton(data);
-		if (chanspec != 0) {
-			val = wl_chspec_host_to_driver(chanspec);
-			if (val != INVCHANSPEC) {
-				if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &val,
-					sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
-					WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
-					return err;
-				}
-				WL_DBG((" set dfs_ap_move successfull"));
-			} else {
-				err = BCME_USAGE_ERROR;
-			}
-		}
-	}
-	return err;
-}
-
-s32
-wl_cfg80211_wbtext_config(struct net_device *ndev, char *data, char *command, int total_len)
-{
-	uint i = 0;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	wl_roam_prof_band_t *rp;
-	int err = -EINVAL, bytes_written = 0;
-	size_t len = strlen(data);
-	int rp_len = 0;
-	data[len] = '\0';
-	rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
-			* WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
-	if (unlikely(!rp)) {
-		WL_ERR(("%s: failed to allocate memory\n", __func__));
-		err =  -ENOMEM;
-		goto exit;
-	}
-
-	rp->ver = WL_MAX_ROAM_PROF_VER;
-	if (*data && (!strncmp(data, "b", 1))) {
-		rp->band = WLC_BAND_2G;
-	} else if (*data && (!strncmp(data, "a", 1))) {
-		rp->band = WLC_BAND_5G;
-	} else {
-		err = snprintf(command, total_len, "Missing band\n");
-		goto exit;
-	}
-	data++;
-	rp->len = 0;
-	/* Getting roam profile  from fw */
-	if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
-		WL_ERR(("Getting roam_profile failed with err=%d \n", err));
-		goto exit;
-	}
-	memcpy(rp, cfg->ioctl_buf, sizeof(*rp) * WL_MAX_ROAM_PROF_BRACKETS);
-	/* roam_prof version get */
-	if (rp->ver != WL_MAX_ROAM_PROF_VER) {
-		WL_ERR(("bad version (=%d) in return data\n", rp->ver));
-		err = -EINVAL;
-		goto exit;
-	}
-	if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
-		WL_ERR(("bad length (=%d) in return data\n", rp->len));
-		err = -EINVAL;
-		goto exit;
-	}
-
-	if (!*data) {
-		for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
-			/* printing contents of roam profile data from fw and exits
-			 * if code hits any of one of the below condtion. If remaining
-			 * length of buffer is less than roam profile size or
-			 * if there is no valid entry.
-			 */
-			if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
-				(rp->roam_prof[i].fullscan_period == 0)) {
-				break;
-			}
-			bytes_written += snprintf(command+bytes_written,
-					total_len, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)\n",
-					rp->roam_prof[i].roam_trigger, rp->roam_prof[i].rssi_lower,
-					rp->roam_prof[i].channel_usage,
-					rp->roam_prof[i].cu_avg_calc_dur);
-		}
-		err = bytes_written;
-		goto exit;
-	} else {
-		for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
-			/* reading contents of roam profile data from fw and exits
-			 * if code hits any of one of the below condtion, If remaining
-			 * length of buffer is less than roam profile size or if there
-			 * is no valid entry.
-			 */
-			if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
-				(rp->roam_prof[i].fullscan_period == 0)) {
-				break;
-			}
-		}
-		/* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
-		if (i != 2) {
-			WL_ERR(("FW must have 2 rows to fill roam_prof\n"));
-			err = -EINVAL;
-			goto exit;
-		}
-		/* setting roam profile to fw */
-		data++;
-		for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
-			rp->roam_prof[i].roam_trigger = simple_strtol(data, &data, 10);
-			data++;
-			rp->roam_prof[i].rssi_lower = simple_strtol(data, &data, 10);
-			data++;
-			rp->roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
-			data++;
-			rp->roam_prof[i].cu_avg_calc_dur = simple_strtol(data, &data, 10);
-
-			rp_len += sizeof(wl_roam_prof_t);
-			if (*data == '\0') {
-				break;
-			}
-			data++;
-		}
-		if (i != 1) {
-			WL_ERR(("Only two roam_prof rows supported.\n"));
-			err = -EINVAL;
-			goto exit;
-		}
-		rp->len = rp_len;
-		if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
-				sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
-			WL_ERR(("seting roam_profile failed with err %d\n", err));
-		}
-	}
-exit:
-	if (rp) {
-		kfree(rp);
-	}
-	return err;
-}
-
-int wl_cfg80211_wbtext_weight_config(struct net_device *ndev, char *data,
-		char *command, int total_len)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	int bytes_written = 0, err = -EINVAL, argc = 0;
-	char rssi[5], band[5], weight[5];
-	char *endptr = NULL;
-	wnm_bss_select_weight_cfg_t *bwcfg;
-
-	bwcfg = kzalloc(sizeof(*bwcfg), GFP_KERNEL);
-	if (unlikely(!bwcfg)) {
-		WL_ERR(("%s: failed to allocate memory\n", __func__));
-		err = -ENOMEM;
-		goto exit;
-	}
-	bwcfg->version =  WNM_BSSLOAD_MONITOR_VERSION;
-	bwcfg->type = 0;
-	bwcfg->weight = 0;
-
-	argc = sscanf(data, "%s %s %s", rssi, band, weight);
-
-	if (!strcasecmp(rssi, "rssi"))
-		bwcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
-	else if (!strcasecmp(rssi, "cu"))
-		bwcfg->type = WNM_BSS_SELECT_TYPE_CU;
-	else {
-		/* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu> <band> <weight> */
-		WL_ERR(("%s: Command usage error\n", __func__));
-		goto exit;
-	}
-
-	if (!strcasecmp(band, "a"))
-		bwcfg->band = WLC_BAND_5G;
-	else if (!strcasecmp(band, "b"))
-		bwcfg->band = WLC_BAND_2G;
-	else if (!strcasecmp(band, "all"))
-		bwcfg->band = WLC_BAND_ALL;
-	else {
-		WL_ERR(("%s: Command usage error\n", __func__));
-		goto exit;
-	}
-
-	if (argc == 2) {
-		/* If there is no data after band, getting wnm_bss_select_weight from fw */
-		if (bwcfg->band == WLC_BAND_ALL) {
-			WL_ERR(("band option \"all\" is for set only, not get\n"));
-			goto exit;
-		}
-		if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_weight", bwcfg,
-				sizeof(*bwcfg),
-				cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
-			WL_ERR(("Getting wnm_bss_select_weight failed with err=%d \n", err));
-			goto exit;
-		}
-		memcpy(bwcfg, cfg->ioctl_buf, sizeof(*bwcfg));
-		bytes_written = snprintf(command, total_len, "%s %s weight = %d\n",
-			(bwcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU",
-			(bwcfg->band == WLC_BAND_2G) ? "2G" : "5G", bwcfg->weight);
-		err = bytes_written;
-		goto exit;
-	} else {
-		/* if weight is non integer returns command usage error */
-		bwcfg->weight = simple_strtol(weight, &endptr, 0);
-		if (*endptr != '\0') {
-			WL_ERR(("%s: Command usage error", __func__));
-			goto exit;
-		}
-		/* setting weight for iovar wnm_bss_select_weight to fw */
-		if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_weight", bwcfg,
-				sizeof(*bwcfg),
-				cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
-			WL_ERR(("Getting wnm_bss_select_weight failed with err=%d\n", err));
-		}
-	}
-exit:
-	if (bwcfg) {
-		kfree(bwcfg);
-	}
-	return err;
-}
-
-/* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
-#define WBTEXT_TUPLE_MIN_LEN_CHECK 5
-
-int wl_cfg80211_wbtext_table_config(struct net_device *ndev, char *data,
-	char *command, int total_len)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	int bytes_written = 0, err = -EINVAL;
-	char rssi[5], band[5];
-	int btcfg_len = 0, i = 0, parsed_len = 0;
-	wnm_bss_select_factor_cfg_t *btcfg;
-	size_t slen = strlen(data);
-	char *start_addr = NULL;
-	data[slen] = '\0';
-
-	btcfg = kzalloc((sizeof(*btcfg) + sizeof(*btcfg) *
-			WL_FACTOR_TABLE_MAX_LIMIT), GFP_KERNEL);
-	if (unlikely(!btcfg)) {
-		WL_ERR(("%s: failed to allocate memory\n", __func__));
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	btcfg->version = WNM_BSS_SELECT_FACTOR_VERSION;
-	btcfg->band = WLC_BAND_AUTO;
-	btcfg->type = 0;
-	btcfg->count = 0;
-
-	sscanf(data, "%s %s", rssi, band);
-
-	if (!strcasecmp(rssi, "rssi")) {
-		btcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
-	}
-	else if (!strcasecmp(rssi, "cu")) {
-		btcfg->type = WNM_BSS_SELECT_TYPE_CU;
-	}
-	else {
-		WL_ERR(("%s: Command usage error\n", __func__));
-		goto exit;
-	}
-
-	if (!strcasecmp(band, "a")) {
-		btcfg->band = WLC_BAND_5G;
-	}
-	else if (!strcasecmp(band, "b")) {
-		btcfg->band = WLC_BAND_2G;
-	}
-	else if (!strcasecmp(band, "all")) {
-		btcfg->band = WLC_BAND_ALL;
-	}
-	else {
-		WL_ERR(("%s: Command usage, Wrong band\n", __func__));
-		goto exit;
-	}
-
-	if ((slen - 1) == (strlen(rssi) + strlen(band))) {
-		/* Getting factor table using iovar 'wnm_bss_select_table' from fw */
-		if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_table", btcfg,
-				sizeof(*btcfg),
-				cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
-			WL_ERR(("Getting wnm_bss_select_table failed with err=%d \n", err));
-			goto exit;
-		}
-		memcpy(btcfg, cfg->ioctl_buf, sizeof(*btcfg));
-		memcpy(btcfg, cfg->ioctl_buf, (btcfg->count+1) * sizeof(*btcfg));
-
-		bytes_written += snprintf(command + bytes_written, total_len,
-					"No of entries in table: %d\n", btcfg->count);
-		bytes_written += snprintf(command + bytes_written, total_len, "%s factor table\n",
-				(btcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU");
-		bytes_written += snprintf(command + bytes_written, total_len,
-					"low\thigh\tfactor\n");
-		for (i = 0; i <= btcfg->count-1; i++) {
-			bytes_written += snprintf(command + bytes_written, total_len,
-				"%d\t%d\t%d\n", btcfg->params[i].low, btcfg->params[i].high,
-				btcfg->params[i].factor);
-		}
-		err = bytes_written;
-		goto exit;
-	} else {
-		memset(btcfg->params, 0, sizeof(*btcfg) * WL_FACTOR_TABLE_MAX_LIMIT);
-		data += (strlen(rssi) + strlen(band) + 2);
-		start_addr = data;
-		slen = slen - (strlen(rssi) + strlen(band) + 2);
-		for (i = 0; i < WL_FACTOR_TABLE_MAX_LIMIT; i++) {
-			if (parsed_len + WBTEXT_TUPLE_MIN_LEN_CHECK <= slen) {
-				btcfg->params[i].low = simple_strtol(data, &data, 10);
-				data++;
-				btcfg->params[i].high = simple_strtol(data, &data, 10);
-				data++;
-				btcfg->params[i].factor = simple_strtol(data, &data, 10);
-				btcfg->count++;
-				if (*data == '\0') {
-					break;
-				}
-				data++;
-				parsed_len = data - start_addr;
-			} else {
-				WL_ERR(("%s:Command usage:less no of args\n", __func__));
-				goto exit;
-			}
-		}
-		btcfg_len = sizeof(*btcfg) + ((btcfg->count) * sizeof(*btcfg));
-		if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_table", btcfg, btcfg_len,
-				cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
-			WL_ERR(("seting wnm_bss_select_table failed with err %d\n", err));
-			goto exit;
-		}
-	}
-exit:
-	if (btcfg) {
-		kfree(btcfg);
-	}
-	return err;
-}
-
-s32
-wl_cfg80211_wbtext_delta_config(struct net_device *ndev, char *data, char *command, int total_len)
-{
-	uint i = 0;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	int err = -EINVAL, bytes_written = 0, argc = 0, val, len = 0;
-	char delta[5], band[5], *endptr = NULL;
-	wl_roam_prof_band_t *rp;
-
-	rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
-			* WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
-	if (unlikely(!rp)) {
-		WL_ERR(("%s: failed to allocate memory\n", __func__));
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	argc = sscanf(data, "%s %s", band, delta);
-	if (!strcasecmp(band, "a"))
-		rp->band = WLC_BAND_5G;
-	else if (!strcasecmp(band, "b"))
-		rp->band = WLC_BAND_2G;
-	else {
-		WL_ERR(("%s: Missing band\n", __func__));
-		goto exit;
-	}
-	/* Getting roam profile  from fw */
-	if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
-		WL_ERR(("Getting roam_profile failed with err=%d \n", err));
-		goto exit;
-	}
-	memcpy(rp, cfg->ioctl_buf, sizeof(wl_roam_prof_band_t));
-	if (rp->ver != WL_MAX_ROAM_PROF_VER) {
-		WL_ERR(("bad version (=%d) in return data\n", rp->ver));
-		err = -EINVAL;
-		goto exit;
-	}
-	if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
-		WL_ERR(("bad length (=%d) in return data\n", rp->len));
-		err = -EINVAL;
-		goto exit;
-	}
-
-	if (argc == 2) {
-		/* if delta is non integer returns command usage error */
-		val = simple_strtol(delta, &endptr, 0);
-		if (*endptr != '\0') {
-			WL_ERR(("%s: Command usage error", __func__));
-			goto exit;
-		}
-		for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
-		/*
-		 * Checking contents of roam profile data from fw and exits
-		 * if code hits below condtion. If remaining length of buffer is
-		 * less than roam profile size or if there is no valid entry.
-		 */
-			if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
-				(rp->roam_prof[i].fullscan_period == 0)) {
-				break;
-			}
-			if (rp->roam_prof[i].channel_usage != 0) {
-				rp->roam_prof[i].roam_delta = val;
-			}
-			len += sizeof(wl_roam_prof_t);
-		}
-	}
-	else {
-		if (rp->roam_prof[i].channel_usage != 0) {
-			bytes_written = snprintf(command, total_len,
-				"%s Delta %d\n", (rp->band == WLC_BAND_2G) ? "2G" : "5G",
-				rp->roam_prof[0].roam_delta);
-		}
-		err = bytes_written;
-		goto exit;
-	}
-	rp->len = len;
-	if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
-			sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
-		WL_ERR(("seting roam_profile failed with err %d\n", err));
-	}
-exit :
-	if (rp) {
-		kfree(rp);
-	}
-	return err;
-}
-
-
-int wl_cfg80211_scan_stop(bcm_struct_cfgdev *cfgdev)
-{
-	struct bcm_cfg80211 *cfg = NULL;
-	struct net_device *ndev = NULL;
-	unsigned long flags;
-	int clear_flag = 0;
-	int ret = 0;
-
-	WL_TRACE(("Enter\n"));
-
-	cfg = g_bcm_cfg;
-	if (!cfg)
-		return -EINVAL;
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
-#ifdef WL_CFG80211_P2P_DEV_IF
-	if (cfg->scan_request && cfg->scan_request->wdev == cfgdev) {
-#else
-	if (cfg->scan_request && cfg->scan_request->dev == cfgdev) {
-#endif
-		cfg80211_scan_done(cfg->scan_request, true);
-		cfg->scan_request = NULL;
-		clear_flag = 1;
-	}
-	spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
-
-	if (clear_flag)
-		wl_clr_drv_status(cfg, SCANNING, ndev);
-
-	return ret;
-}
-
-bool wl_cfg80211_is_concurrent_mode(void)
-{
-	if ((g_bcm_cfg) && (wl_get_drv_status_all(g_bcm_cfg, CONNECTED) > 1)) {
-		return true;
-	} else {
-		return false;
-	}
-}
-
-void* wl_cfg80211_get_dhdp()
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	return cfg->pub;
-}
-
-bool wl_cfg80211_is_p2p_active(void)
-{
-	return (g_bcm_cfg && g_bcm_cfg->p2p);
-}
-
-bool wl_cfg80211_is_roam_offload(void)
-{
-	return (g_bcm_cfg && g_bcm_cfg->roam_offload);
-}
-
-bool wl_cfg80211_is_event_from_connected_bssid(const wl_event_msg_t *e, int ifidx)
-{
-	dhd_pub_t *dhd = NULL;
-	struct net_device *ndev = NULL;
-	u8 *curbssid = NULL;
-
-	dhd = (dhd_pub_t *)(g_bcm_cfg->pub);
-
-	if (dhd) {
-		ndev = dhd_idx2net(dhd, ifidx);
-	}
-
-	if (!dhd || !ndev) {
-		return false;
-	}
-
-	curbssid = wl_read_prof(g_bcm_cfg, ndev, WL_PROF_BSSID);
-
-	return memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0;
-}
-
-static void wl_cfg80211_work_handler(struct work_struct * work)
-{
-	struct bcm_cfg80211 *cfg = NULL;
-	struct net_info *iter, *next;
-	s32 err = BCME_OK;
-	s32 pm = PM_FAST;
-	BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, pm_enable_work.work);
-	WL_DBG(("Enter \n"));
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-	for_each_ndev(cfg, iter, next) {
-		/* p2p discovery iface ndev could be null */
-		if (iter->ndev) {
-			if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev) ||
-				(wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS &&
-				wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_IBSS))
-				continue;
-			if (iter->ndev) {
-				if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
-						&pm, sizeof(pm), true)) != 0) {
-					if (err == -ENODEV)
-						WL_DBG(("%s:netdev not ready\n",
-							iter->ndev->name));
-					else
-						WL_ERR(("%s:error (%d)\n",
-							iter->ndev->name, err));
-				} else
-					wl_cfg80211_update_power_mode(iter->ndev);
-			}
-		}
-	}
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-	_Pragma("GCC diagnostic pop")
-#endif
-	DHD_OS_WAKE_UNLOCK(cfg->pub);
-}
-
-u8
-wl_get_action_category(void *frame, u32 frame_len)
-{
-	u8 category;
-	u8 *ptr = (u8 *)frame;
-	if (frame == NULL)
-		return DOT11_ACTION_CAT_ERR_MASK;
-	if (frame_len < DOT11_ACTION_HDR_LEN)
-		return DOT11_ACTION_CAT_ERR_MASK;
-	category = ptr[DOT11_ACTION_CAT_OFF];
-	WL_INFORM(("Action Category: %d\n", category));
-	return category;
-}
-
-int
-wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
-{
-	u8 *ptr = (u8 *)frame;
-	if (frame == NULL || ret_action == NULL)
-		return BCME_ERROR;
-	if (frame_len < DOT11_ACTION_HDR_LEN)
-		return BCME_ERROR;
-	if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
-		return BCME_ERROR;
-	*ret_action = ptr[DOT11_ACTION_ACT_OFF];
-	WL_INFORM(("Public Action : %d\n", *ret_action));
-	return BCME_OK;
-}
-
-
-static int
-wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	const struct ether_addr *bssid)
-{
-	s32 err;
-	wl_event_msg_t e;
-
-	bzero(&e, sizeof(e));
-	e.event_type = cpu_to_be32(WLC_E_BSSID);
-	memcpy(&e.addr, bssid, ETHER_ADDR_LEN);
-	/* trigger the roam event handler */
-	WL_INFORM(("Delayed roam to " MACDBG "\n", MAC2STRDBG((u8*)(bssid))));
-	err = wl_notify_roaming_status(cfg, ndev_to_cfgdev(ndev), &e, NULL);
-
-	return err;
-}
-
-static s32
-wl_cfg80211_parse_vndr_ies(u8 *parse, u32 len,
-    struct parsed_vndr_ies *vndr_ies)
-{
-	s32 err = BCME_OK;
-	vndr_ie_t *vndrie;
-	bcm_tlv_t *ie;
-	struct parsed_vndr_ie_info *parsed_info;
-	u32 count = 0;
-	s32 remained_len;
-
-	remained_len = (s32)len;
-	memset(vndr_ies, 0, sizeof(*vndr_ies));
-
-	WL_INFORM(("---> len %d\n", len));
-	ie = (bcm_tlv_t *) parse;
-	if (!bcm_valid_tlv(ie, remained_len))
-		ie = NULL;
-	while (ie) {
-		if (count >= MAX_VNDR_IE_NUMBER)
-			break;
-		if (ie->id == DOT11_MNG_VS_ID) {
-			vndrie = (vndr_ie_t *) ie;
-			/* len should be bigger than OUI length + one data length at least */
-			if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
-				WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
-					__FUNCTION__, vndrie->len));
-				goto end;
-			}
-			/* if wpa or wme ie, do not add ie */
-			if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
-				((vndrie->data[0] == WPA_OUI_TYPE) ||
-				(vndrie->data[0] == WME_OUI_TYPE))) {
-				CFGP2P_DBG(("Found WPA/WME oui. Do not add it\n"));
-				goto end;
-			}
-
-			parsed_info = &vndr_ies->ie_info[count++];
-
-			/* save vndr ie information */
-			parsed_info->ie_ptr = (char *)vndrie;
-			parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
-			memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
-			vndr_ies->count = count;
-
-			WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
-			parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1],
-			parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0],
-			parsed_info->ie_len));
-		}
-end:
-		ie = bcm_next_tlv(ie, &remained_len);
-	}
-	return err;
-}
-
-s32
-wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx)
-{
-	s32 index;
-	struct net_info *netinfo;
-	s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
-		VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
-
-	netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
-	if (!netinfo || !netinfo->wdev) {
-		WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
-		return -1;
-	}
-
-	WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx));
-	/* Clear the IEs set in the firmware so that host is in sync with firmware */
-	for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
-		if (wl_cfg80211_set_mgmt_vndr_ies(cfg, wdev_to_cfgdev(netinfo->wdev),
-			bssidx, vndrie_flag[index], NULL, 0) < 0)
-			WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
-	}
-
-	return 0;
-}
-
-s32
-wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg)
-{
-	struct net_info *iter, *next;
-
-	WL_DBG(("clear management vendor IEs \n"));
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-	for_each_ndev(cfg, iter, next) {
-		wl_cfg80211_clear_per_bss_ies(cfg, iter->bssidx);
-	}
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-	return 0;
-}
-
-#define WL_VNDR_IE_MAXLEN 2048
-static s8 g_mgmt_ie_buf[WL_VNDR_IE_MAXLEN];
-int
-wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
-{
-	struct net_device *ndev = NULL;
-	s32 ret = BCME_OK;
-	u8  *curr_ie_buf = NULL;
-	u8  *mgmt_ie_buf = NULL;
-	u32 mgmt_ie_buf_len = 0;
-	u32 *mgmt_ie_len = 0;
-	u32 del_add_ie_buf_len = 0;
-	u32 total_ie_buf_len = 0;
-	u32 parsed_ie_buf_len = 0;
-	struct parsed_vndr_ies old_vndr_ies;
-	struct parsed_vndr_ies new_vndr_ies;
-	s32 i;
-	u8 *ptr;
-	s32 remained_buf_len;
-	wl_bss_vndr_ies_t *ies = NULL;
-	struct net_info *netinfo;
-
-	WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
-		pktflag, bssidx, vndr_ie_len));
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	if (bssidx > WL_MAX_IFS) {
-		WL_ERR(("bssidx > supported concurrent Ifaces \n"));
-		return -EINVAL;
-	}
-
-	netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
-	if (!netinfo) {
-		WL_ERR(("net_info ptr is NULL \n"));
-		return -EINVAL;
-	}
-
-	/* Clear the global buffer */
-	memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf));
-	curr_ie_buf = g_mgmt_ie_buf;
-	ies = &netinfo->bss.ies;
-
-	switch (pktflag) {
-		case VNDR_IE_PRBRSP_FLAG :
-			mgmt_ie_buf = ies->probe_res_ie;
-			mgmt_ie_len = &ies->probe_res_ie_len;
-			mgmt_ie_buf_len = sizeof(ies->probe_res_ie);
-			break;
-		case VNDR_IE_ASSOCRSP_FLAG :
-			mgmt_ie_buf = ies->assoc_res_ie;
-			mgmt_ie_len = &ies->assoc_res_ie_len;
-			mgmt_ie_buf_len = sizeof(ies->assoc_res_ie);
-			break;
-		case VNDR_IE_BEACON_FLAG :
-			mgmt_ie_buf = ies->beacon_ie;
-			mgmt_ie_len = &ies->beacon_ie_len;
-			mgmt_ie_buf_len = sizeof(ies->beacon_ie);
-			break;
-		case VNDR_IE_PRBREQ_FLAG :
-			mgmt_ie_buf = ies->probe_req_ie;
-			mgmt_ie_len = &ies->probe_req_ie_len;
-			mgmt_ie_buf_len = sizeof(ies->probe_req_ie);
-			break;
-		case VNDR_IE_ASSOCREQ_FLAG :
-			mgmt_ie_buf = ies->assoc_req_ie;
-			mgmt_ie_len = &ies->assoc_req_ie_len;
-			mgmt_ie_buf_len = sizeof(ies->assoc_req_ie);
-			break;
-		default:
-			mgmt_ie_buf = NULL;
-			mgmt_ie_len = NULL;
-			WL_ERR(("not suitable packet type (%d)\n", pktflag));
-			return BCME_ERROR;
-	}
-
-	if (vndr_ie_len > mgmt_ie_buf_len) {
-		WL_ERR(("extra IE size too big\n"));
-		ret = -ENOMEM;
-	} else {
-		/* parse and save new vndr_ie in curr_ie_buff before comparing it */
-		if (vndr_ie && vndr_ie_len && curr_ie_buf) {
-			ptr = curr_ie_buf;
-/* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
- * causes cascade of errors in other places, fix involves const casts there
- */
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-			if ((ret = wl_cfg80211_parse_vndr_ies((u8 *)vndr_ie,
-				vndr_ie_len, &new_vndr_ies)) < 0) {
-				WL_ERR(("parse vndr ie failed \n"));
-				goto exit;
-			}
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-			for (i = 0; i < new_vndr_ies.count; i++) {
-				struct parsed_vndr_ie_info *vndrie_info =
-					&new_vndr_ies.ie_info[i];
-
-				if ((parsed_ie_buf_len + vndrie_info->ie_len) > WL_VNDR_IE_MAXLEN) {
-					WL_ERR(("IE size is too big (%d > %d)\n",
-						parsed_ie_buf_len, WL_VNDR_IE_MAXLEN));
-					ret = -EINVAL;
-					goto exit;
-				}
-
-				memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
-					vndrie_info->ie_len);
-				parsed_ie_buf_len += vndrie_info->ie_len;
-			}
-		}
-
-		if (mgmt_ie_buf != NULL) {
-			if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
-				(memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
-				WL_INFORM(("Previous mgmt IE is equals to current IE"));
-				goto exit;
-			}
-
-			/* parse old vndr_ie */
-			if ((ret = wl_cfg80211_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
-				&old_vndr_ies)) < 0) {
-				WL_ERR(("parse vndr ie failed \n"));
-				goto exit;
-			}
-			/* make a command to delete old ie */
-			for (i = 0; i < old_vndr_ies.count; i++) {
-				struct parsed_vndr_ie_info *vndrie_info =
-				&old_vndr_ies.ie_info[i];
-
-				WL_INFORM(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
-					vndrie_info->vndrie.id, vndrie_info->vndrie.len,
-					vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
-					vndrie_info->vndrie.oui[2]));
-
-				del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
-					pktflag, vndrie_info->vndrie.oui,
-					vndrie_info->vndrie.id,
-					vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
-					vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
-					"del");
-
-				curr_ie_buf += del_add_ie_buf_len;
-				total_ie_buf_len += del_add_ie_buf_len;
-			}
-		}
-
-		*mgmt_ie_len = 0;
-		/* Add if there is any extra IE */
-		if (mgmt_ie_buf && parsed_ie_buf_len) {
-			ptr = mgmt_ie_buf;
-
-			remained_buf_len = mgmt_ie_buf_len;
-
-			/* make a command to add new ie */
-			for (i = 0; i < new_vndr_ies.count; i++) {
-				struct parsed_vndr_ie_info *vndrie_info =
-					&new_vndr_ies.ie_info[i];
-
-				WL_INFORM(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
-					vndrie_info->vndrie.id, vndrie_info->vndrie.len,
-					vndrie_info->ie_len - 2,
-					vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
-					vndrie_info->vndrie.oui[2]));
-
-				del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
-					pktflag, vndrie_info->vndrie.oui,
-					vndrie_info->vndrie.id,
-					vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
-					vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
-					"add");
-
-				/* verify remained buf size before copy data */
-				if (remained_buf_len >= vndrie_info->ie_len) {
-					remained_buf_len -= vndrie_info->ie_len;
-				} else {
-					WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
-					"found vndr ies # = %d(cur %d), remained len %d, "
-					"cur mgmt_ie_len %d, new ie len = %d\n",
-					pktflag, new_vndr_ies.count, i, remained_buf_len,
-					*mgmt_ie_len, vndrie_info->ie_len));
-					break;
-				}
-
-				/* save the parsed IE in cfg struct */
-				memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
-					vndrie_info->ie_len);
-				*mgmt_ie_len += vndrie_info->ie_len;
-				curr_ie_buf += del_add_ie_buf_len;
-				total_ie_buf_len += del_add_ie_buf_len;
-			}
-		}
-
-		if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
-			ret  = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
-				total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
-				bssidx, &cfg->ioctl_buf_sync);
-			if (ret)
-				WL_ERR(("vndr ie set error : %d\n", ret));
-		}
-	}
-exit:
-
-return ret;
-}
-
-#ifdef WL_CFG80211_ACL
-static int
-wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
-	const struct cfg80211_acl_data *acl)
-{
-	int i;
-	int ret = 0;
-	int macnum = 0;
-	int macmode = MACLIST_MODE_DISABLED;
-	struct maclist *list;
-
-	/* get the MAC filter mode */
-	if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
-		macmode = MACLIST_MODE_ALLOW;
-	} else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
-	acl->n_acl_entries) {
-		macmode = MACLIST_MODE_DENY;
-	}
-
-	/* if acl == NULL, macmode is still disabled.. */
-	if (macmode == MACLIST_MODE_DISABLED) {
-		if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
-			WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
-
-		return ret;
-	}
-
-	macnum = acl->n_acl_entries;
-	if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
-		WL_ERR(("%s : invalid number of MAC address entries %d\n",
-			__FUNCTION__, macnum));
-		return -1;
-	}
-
-	/* allocate memory for the MAC list */
-	list = (struct maclist*)kmalloc(sizeof(int) +
-		sizeof(struct ether_addr) * macnum, GFP_KERNEL);
-	if (!list) {
-		WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__));
-		return -1;
-	}
-
-	/* prepare the MAC list */
-	list->count = htod32(macnum);
-	for (i = 0; i < macnum; i++) {
-		memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
-	}
-	/* set the list */
-	if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
-		WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
-
-	kfree(list);
-
-	return ret;
-}
-#endif /* WL_CFG80211_ACL */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-int wl_chspec_chandef(chanspec_t chanspec,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-	struct cfg80211_chan_def *chandef,
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
-	\
-	\
-	\
-	0)))
-	struct chan_info *chaninfo,
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
-struct wiphy *wiphy)
-
-{
-	uint16 freq = 0;
-	int chan_type = 0;
-	int channel = 0;
-	struct ieee80211_channel *chan;
-
-	if (!chandef) {
-		return -1;
-	}
-	channel = CHSPEC_CHANNEL(chanspec);
-
-	switch (CHSPEC_BW(chanspec)) {
-		case WL_CHANSPEC_BW_20:
-			chan_type = NL80211_CHAN_HT20;
-			break;
-		case WL_CHANSPEC_BW_40:
-		{
-			if (CHSPEC_SB_UPPER(chanspec)) {
-				channel += CH_10MHZ_APART;
-			} else {
-				channel -= CH_10MHZ_APART;
-			}
-		}
-			chan_type = NL80211_CHAN_HT40PLUS;
-			break;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
-		case WL_CHANSPEC_BW_80:
-		case WL_CHANSPEC_BW_8080:
-		{
-			uint16 sb = CHSPEC_CTL_SB(chanspec);
-
-			if (sb == WL_CHANSPEC_CTL_SB_LL) {
-				channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
-			} else if (sb == WL_CHANSPEC_CTL_SB_LU) {
-				channel -= CH_10MHZ_APART;
-			} else if (sb == WL_CHANSPEC_CTL_SB_UL) {
-				channel += CH_10MHZ_APART;
-			} else {
-				/* WL_CHANSPEC_CTL_SB_UU */
-				channel += (CH_10MHZ_APART + CH_20MHZ_APART);
-			}
-
-			if (sb == WL_CHANSPEC_CTL_SB_LL || sb == WL_CHANSPEC_CTL_SB_LU)
-				chan_type = NL80211_CHAN_HT40MINUS;
-			else if (sb == WL_CHANSPEC_CTL_SB_UL || sb == WL_CHANSPEC_CTL_SB_UU)
-				chan_type = NL80211_CHAN_HT40PLUS;
-		}
-			break;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
-		default:
-			chan_type = NL80211_CHAN_HT20;
-			break;
-
-	}
-
-	if (CHSPEC_IS5G(chanspec))
-		freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
-	else
-		freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
-
-	chan = ieee80211_get_channel(wiphy, freq);
-	WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
-		channel, freq, chan_type, chan));
-
-	if (unlikely(!chan)) {
-		/* fw and cfg80211 channel lists are not in sync */
-		WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
-		ASSERT(0);
-		return -EINVAL;
-	}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
-	cfg80211_chandef_create(chandef, chan, chan_type);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
-	\
-	\
-	\
-	0)))
-	chaninfo->freq = freq;
-	chaninfo->chan_type = chan_type;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
-	return 0;
-}
-
-void
-wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
-{
-	u32 freq;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
-	struct cfg80211_chan_def chandef;
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
-	\
-	\
-	\
-	0)))
-	struct chan_info chaninfo;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
-
-	if (!wiphy) {
-		WL_ERR(("wiphy is null\n"));
-		return;
-	}
-#ifndef ALLOW_CHSW_EVT
-	/* Channel switch support is only for AP/GO/ADHOC/MESH */
-	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
-		dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
-		WL_ERR(("No channel switch notify support for STA/GC\n"));
-		return;
-	}
-#endif /* !ALLOW_CHSW_EVT */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
-	if (wl_chspec_chandef(chanspec, &chandef, wiphy)) {
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
-	\
-	\
-	\
-	0)))
-	if (wl_chspec_chandef(chanspec, &chaninfo, wiphy)) {
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
-
-		WL_ERR(("chspec_chandef failed\n"));
-		return;
-	}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
-	freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
-	cfg80211_ch_switch_notify(dev, &chandef);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
-	\
-	\
-	\
-	0)))
-	freq = chan_info.freq;
-	cfg80211_ch_switch_notify(dev, chan_info.freq, chan_info.chan_type);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
-
-	WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq, chanspec));
-	return;
-}
-#endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
-
-#ifdef WL11ULB
-s32
-wl_cfg80211_set_ulb_mode(struct net_device *dev, int mode)
-{
-	int ret;
-	int cur_mode;
-
-	ret = wldev_iovar_getint(dev, "ulb_mode", &cur_mode);
-	if (unlikely(ret)) {
-		WL_ERR(("[ULB] ulb_mode get failed. ret:%d \n", ret));
-		return ret;
-	}
-
-	if (cur_mode == mode) {
-		/* If request mode is same as that of the current mode, then
-		 * do nothing (Avoid unnecessary wl down and up).
-		 */
-		WL_INFORM(("[ULB] No change in ulb_mode. Do nothing.\n"));
-		return 0;
-	}
-
-	/* setting of ulb_mode requires wl to be down */
-	ret = wldev_ioctl(dev, WLC_DOWN, NULL, 0, true);
-	if (unlikely(ret)) {
-		WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
-		return ret;
-	}
-
-	if (mode >= MAX_SUPP_ULB_MODES) {
-		WL_ERR(("[ULB] unsupported ulb_mode :[%d]\n", mode));
-		return -EINVAL;
-	}
-
-	ret = wldev_iovar_setint(dev, "ulb_mode", mode);
-	if (unlikely(ret)) {
-		WL_ERR(("[ULB] ulb_mode set failed. ret:%d \n", ret));
-		return ret;
-	}
-
-	ret = wldev_ioctl(dev, WLC_UP, NULL, 0, true);
-	if (unlikely(ret)) {
-		WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
-		return ret;
-	}
-
-	WL_DBG(("[ULB] ulb_mode set to %d successfully \n", mode));
-
-	return ret;
-}
-
-static s32
-wl_cfg80211_ulbbw_to_ulbchspec(u32 bw)
-{
-	if (bw == ULB_BW_DISABLED) {
-		return WL_CHANSPEC_BW_20;
-	} else if (bw == ULB_BW_10MHZ) {
-		return WL_CHANSPEC_BW_10;
-	} else if (bw == ULB_BW_5MHZ) {
-		return WL_CHANSPEC_BW_5;
-	} else if (bw == ULB_BW_2P5MHZ) {
-		return WL_CHANSPEC_BW_2P5;
-	} else {
-		WL_ERR(("[ULB] unsupported value for ulb_bw \n"));
-		return -EINVAL;
-	}
-}
-
-static chanspec_t
-wl_cfg80211_ulb_get_min_bw_chspec(struct wireless_dev *wdev, s32 bssidx)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct net_info *_netinfo;
-
-	/*
-	 *  Return the chspec value corresponding to the
-	 *  BW setting for a particular interface
-	 */
-	if (wdev) {
-		/* if wdev is provided, use it */
-		_netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
-	} else if (bssidx >= 0) {
-		/* if wdev is not provided, use it */
-		_netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
-	} else {
-		WL_ERR(("[ULB] wdev/bssidx not provided\n"));
-		return INVCHANSPEC;
-	}
-
-	if (unlikely(!_netinfo)) {
-		WL_ERR(("[ULB] net_info is null \n"));
-		return INVCHANSPEC;
-	}
-
-	if (_netinfo->ulb_bw) {
-		WL_DBG(("[ULB] wdev_ptr:%p ulb_bw:0x%x \n", _netinfo->wdev, _netinfo->ulb_bw));
-		return wl_cfg80211_ulbbw_to_ulbchspec(_netinfo->ulb_bw);
-	} else {
-		return WL_CHANSPEC_BW_20;
-	}
-}
-
-static s32
-wl_cfg80211_get_ulb_bw(struct wireless_dev *wdev)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct net_info *_netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
-
-	/*
-	 *  Return the ulb_bw setting for a
-	 *  particular interface
-	 */
-	if (unlikely(!_netinfo)) {
-		WL_ERR(("[ULB] net_info is null \n"));
-		return -1;
-	}
-
-	return _netinfo->ulb_bw;
-}
-
-s32
-wl_cfg80211_set_ulb_bw(struct net_device *dev,
-	u32 ulb_bw,  char *ifname)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	int ret;
-	int mode;
-	struct net_info *_netinfo = NULL, *iter, *next;
-	u32 bssidx;
-	enum nl80211_iftype iftype;
-
-	if (!ifname)
-		return -EINVAL;
-
-	WL_DBG(("[ULB] Enter. bw_type:%d \n", ulb_bw));
-
-	ret = wldev_iovar_getint(dev, "ulb_mode", &mode);
-	if (unlikely(ret)) {
-		WL_ERR(("[ULB] ulb_mode not supported \n"));
-		return ret;
-	}
-
-	if (mode != ULB_MODE_STD_ALONE_MODE) {
-		WL_ERR(("[ULB] ulb bw modification allowed only in stand-alone mode\n"));
-		return -EINVAL;
-	}
-
-	if (ulb_bw >= MAX_SUPP_ULB_BW) {
-		WL_ERR(("[ULB] unsupported value (%d) for ulb_bw \n", ulb_bw));
-		return -EINVAL;
-	}
-
-#ifdef WL_CFG80211_P2P_DEV_IF
-	if (strcmp(ifname, "p2p-dev-wlan0") == 0) {
-		iftype = NL80211_IFTYPE_P2P_DEVICE;
-		/* Use wdev corresponding to the dedicated p2p discovery interface */
-		if (likely(cfg->p2p_wdev)) {
-			_netinfo = wl_get_netinfo_by_wdev(cfg, cfg->p2p_wdev);
-		} else {
-			return -ENODEV;
-		}
-	}
-#endif /* WL_CFG80211_P2P_DEV_IF */
-	if (!_netinfo) {
-		for_each_ndev(cfg, iter, next) {
-			if (iter->ndev) {
-				if (strncmp(iter->ndev->name, ifname, strlen(ifname)) == 0) {
-					_netinfo = wl_get_netinfo_by_netdev(cfg, iter->ndev);
-					iftype = NL80211_IFTYPE_STATION;
-				}
-			}
-		}
-	}
-
-	if (!_netinfo)
-		return -ENODEV;
-	bssidx = _netinfo->bssidx;
-	_netinfo->ulb_bw = ulb_bw;
-
-
-	WL_DBG(("[ULB] Applying ulb_bw:%d for bssidx:%d \n", ulb_bw, bssidx));
-	ret = wldev_iovar_setbuf_bsscfg(dev, "ulb_bw", (void *)&ulb_bw, 4,
-		cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx,
-		&cfg->ioctl_buf_sync);
-	if (unlikely(ret)) {
-		WL_ERR(("[ULB] ulb_bw set failed. ret:%d \n", ret));
-		return ret;
-	}
-
-	return ret;
-}
-#endif /* WL11ULB */
-
-static void
-wl_ap_channel_ind(struct bcm_cfg80211 *cfg,
-	struct net_device *ndev,
-	chanspec_t chanspec)
-{
-	u32 channel = LCHSPEC_CHANNEL(chanspec);
-
-	WL_DBG(("(%s) AP channel:%d chspec:0x%x \n",
-		ndev->name, channel, chanspec));
-	if (cfg->ap_oper_channel && (cfg->ap_oper_channel != channel)) {
-		/*
-		 * If cached channel is different from the channel indicated
-		 * by the event, notify user space about the channel switch.
-		 */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-		wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
-#endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
-		cfg->ap_oper_channel = channel;
-	}
-}
-
-static s32
-wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-const wl_event_msg_t *e, void *data)
-{
-	struct net_device *ndev = NULL;
-	chanspec_t chanspec;
-	u32 channel;
-
-	WL_DBG(("Enter\n"));
-	if (unlikely(e->status)) {
-		WL_ERR(("status:0x%x \n", e->status));
-		return -1;
-	}
-
-	if (!data) {
-		return -EINVAL;
-	}
-
-	if (likely(cfgdev)) {
-		ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-		chanspec = *((chanspec_t *)data);
-		channel =  LCHSPEC_CHANNEL(chanspec);
-
-		if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
-			/* For AP/GO role */
-			wl_ap_channel_ind(cfg, ndev, chanspec);
-		}
-	}
-
-	return 0;
-}
-
-static s32
-wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-const wl_event_msg_t *e, void *data)
-{
-	int error = 0;
-	u32 chanspec = 0;
-	struct net_device *ndev = NULL;
-	struct wiphy *wiphy = NULL;
-
-	WL_DBG(("Enter\n"));
-	if (unlikely(e->status)) {
-		WL_ERR(("status:0x%x \n", e->status));
-		return -1;
-	}
-
-	if (likely(cfgdev)) {
-		ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-		wiphy = bcmcfg_to_wiphy(cfg);
-		error = wldev_iovar_getint(ndev, "chanspec", &chanspec);
-		if (unlikely(error)) {
-			WL_ERR(("Get chanspec error: %d \n", error));
-			return -1;
-		}
-
-		if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
-			/* For AP/GO role */
-			wl_ap_channel_ind(cfg, ndev, chanspec);
-		} else {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-			wl_cfg80211_ch_switch_notify(ndev, chanspec, wiphy);
-#endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
-		}
-
-	}
-
-	return 0;
-}
-
-#ifdef WL_NAN
-int
-wl_cfg80211_nan_cmd_handler(struct net_device *ndev, char *cmd, int cmd_len)
-{
-	return wl_cfgnan_cmd_handler(ndev, g_bcm_cfg, cmd, cmd_len);
-}
-#endif /* WL_NAN */
-
-void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg)
-{
-	struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
-	int err;
-
-	/* Clear the security settings on the primary Interface */
-	err = wldev_iovar_setint(dev, "wsec", 0);
-	if (unlikely(err)) {
-		WL_ERR(("wsec clear failed \n"));
-	}
-	err = wldev_iovar_setint(dev, "auth", 0);
-	if (unlikely(err)) {
-		WL_ERR(("auth clear failed \n"));
-	}
-	err = wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
-	if (unlikely(err)) {
-		WL_ERR(("wpa_auth clear failed \n"));
-	}
-}
-
-#ifdef WL_CFG80211_P2P_DEV_IF
-void wl_cfg80211_del_p2p_wdev(void)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct wireless_dev *wdev = NULL;
-
-	WL_DBG(("Enter \n"));
-	if (!cfg) {
-		WL_ERR(("Invalid Ptr\n"));
-		return;
-	} else {
-		wdev = cfg->p2p_wdev;
-	}
-
-	if (wdev && cfg->down_disc_if) {
-		wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
-		cfg->down_disc_if = FALSE;
-	}
-}
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-#if defined(WL_SUPPORT_AUTO_CHANNEL)
-int
-wl_cfg80211_set_spect(struct net_device *dev, int spect)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	int down = 1;
-	int up = 1;
-	int err = BCME_OK;
-
-	if (!wl_get_drv_status_all(cfg, CONNECTED)) {
-		err = wldev_ioctl(dev, WLC_DOWN, &down, sizeof(down), true);
-		if (err) {
-			WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
-			return err;
-		}
-
-		err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect), true);
-		if (err) {
-			WL_ERR(("%s: error setting spect: code: %d\n", __func__, err));
-			return err;
-		}
-
-		err = wldev_ioctl(dev, WLC_UP, &up, sizeof(up), true);
-		if (err) {
-			WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__, err));
-			return err;
-		}
-	}
-	return err;
-}
-
-int
-wl_cfg80211_get_sta_channel(void)
-{
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(g_bcm_cfg);
-	int channel = 0;
-
-	if (wl_get_drv_status(g_bcm_cfg, CONNECTED, ndev)) {
-		channel = g_bcm_cfg->channel;
-	}
-	return channel;
-}
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
-#ifdef P2P_LISTEN_OFFLOADING
-s32
-wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg)
-{
-	s32 bssidx;
-	int ret = 0;
-	int p2plo_pause = 0;
-	if (!cfg || !cfg->p2p) {
-		WL_ERR(("Wl %p or cfg->p2p %p is null\n",
-			cfg, cfg ? cfg->p2p : 0));
-		return 0;
-	}
-
-	bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-	ret = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg),
-			"p2po_stop", (void*)&p2plo_pause, sizeof(p2plo_pause),
-			cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL);
-	if (ret < 0) {
-		WL_ERR(("p2po_stop Failed :%d\n", ret));
-	}
-
-	return  ret;
-}
-s32
-wl_cfg80211_p2plo_listen_start(struct net_device *dev, u8 *buf,	int len)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-	wl_p2plo_listen_t p2plo_listen;
-	int ret = -EAGAIN;
-	int channel = 0;
-	int period = 0;
-	int interval = 0;
-	int count = 0;
-
-	if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
-		WL_ERR(("Sending Action Frames. Try it again.\n"));
-		goto exit;
-	}
-
-	if (wl_get_drv_status_all(cfg, SCANNING)) {
-		WL_ERR(("Scanning already\n"));
-		goto exit;
-	}
-
-	if (wl_get_drv_status(cfg, SCAN_ABORTING, dev)) {
-		WL_ERR(("Scanning being aborted\n"));
-		goto exit;
-	}
-
-	if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
-		WL_ERR(("p2p listen offloading already running\n"));
-		goto exit;
-	}
-
-	/* Just in case if it is not enabled */
-	if ((ret = wl_cfgp2p_enable_discovery(cfg, dev, NULL, 0)) < 0) {
-		WL_ERR(("cfgp2p_enable discovery failed"));
-		goto exit;
-	}
-
-	bzero(&p2plo_listen, sizeof(wl_p2plo_listen_t));
-
-	if (len) {
-		sscanf(buf, " %10d %10d %10d %10d", &channel, &period, &interval, &count);
-		if ((channel == 0) || (period == 0) ||
-			(interval == 0) || (count == 0)) {
-			WL_ERR(("Wrong argument %d/%d/%d/%d \n",
-				channel, period, interval, count));
-			ret = -EAGAIN;
-			goto exit;
-		}
-		p2plo_listen.period = period;
-		p2plo_listen.interval = interval;
-		p2plo_listen.count = count;
-
-		WL_ERR(("channel:%d period:%d, interval:%d count:%d\n",
-				channel, period, interval, count));
-	} else {
-		WL_ERR(("Argument len is wrong.\n"));
-		ret = -EAGAIN;
-		goto exit;
-	}
-
-	if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
-			sizeof(channel), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
-			bssidx, &cfg->ioctl_buf_sync)) < 0) {
-		WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
-		goto exit;
-	}
-
-	if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&p2plo_listen,
-			sizeof(wl_p2plo_listen_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
-			bssidx, &cfg->ioctl_buf_sync)) < 0) {
-		WL_ERR(("p2po_listen Failed :%d\n", ret));
-		goto exit;
-	}
-
-	wl_set_p2p_status(cfg, DISC_IN_PROGRESS);
-	cfg->last_roc_id = P2PO_COOKIE;
-exit :
-	return ret;
-}
-s32
-wl_cfg80211_p2plo_listen_stop(struct net_device *dev)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-	int ret = -EAGAIN;
-
-	if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", NULL,
-			0, cfg->ioctl_buf, WLC_IOCTL_SMLEN,
-			bssidx, &cfg->ioctl_buf_sync)) < 0) {
-		WL_ERR(("p2po_stop Failed :%d\n", ret));
-		goto exit;
-	}
-
-exit:
-	return ret;
-}
-#endif /* P2P_LISTEN_OFFLOADING */
-u64
-wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg)
-{
-	u64 id = 0;
-	id = ++cfg->last_roc_id;
-#ifdef  P2P_LISTEN_OFFLOADING
-	if (id == P2PO_COOKIE) {
-		id = ++cfg->last_roc_id;
-	}
-#endif /* P2P_LISTEN_OFFLOADING */
-	if (id == 0)
-		id = ++cfg->last_roc_id;
-	return id;
-}
-
-#if defined(SUPPORT_RANDOM_MAC_SCAN)
-int
-wl_cfg80211_set_random_mac(struct net_device *dev, bool enable)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	int ret;
-
-	if (cfg->random_mac_enabled == enable) {
-		WL_ERR(("Random MAC already %s\n", enable ? "Enabled" : "Disabled"));
-		return BCME_OK;
-	}
-
-	if (enable) {
-		ret = wl_cfg80211_random_mac_enable(dev);
-	} else {
-		ret = wl_cfg80211_random_mac_disable(dev);
-	}
-
-	if (!ret) {
-		cfg->random_mac_enabled = enable;
-	}
-
-	return ret;
-}
-
-int
-wl_cfg80211_random_mac_enable(struct net_device *dev)
-{
-	u8 current_mac[ETH_ALEN] = {0, };
-	s32 err = BCME_ERROR;
-	uint8 buffer[20] = {0, };
-	wl_scanmac_t *sm = NULL;
-	int len = 0;
-	wl_scanmac_enable_t *sm_enable = NULL;
-	wl_scanmac_config_t *sm_config = NULL;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	if (wl_get_drv_status_all(cfg, CONNECTED) || wl_get_drv_status_all(cfg, CONNECTING) ||
-	    wl_get_drv_status_all(cfg, AP_CREATED) || wl_get_drv_status_all(cfg, AP_CREATING)) {
-		WL_ERR(("Fail to Set random mac, current state is wrong\n"));
-		return err;
-	}
-
-	/* Read current mac address */
-	err = wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr",
-		NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
-
-	if (err != BCME_OK) {
-		WL_ERR(("failed to get current dongle mac address\n"));
-		return err;
-	}
-
-	memcpy(current_mac, cfg->ioctl_buf, ETH_ALEN);
-
-	/* Enable scan mac */
-	sm = (wl_scanmac_t *)buffer;
-	sm_enable = (wl_scanmac_enable_t *)sm->data;
-	sm->len = sizeof(*sm_enable);
-	sm_enable->enable = 1;
-	len = OFFSETOF(wl_scanmac_t, data) + sm->len;
-	sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
-
-	err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
-		sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
-
-	if (err != BCME_OK) {
-		WL_ERR(("failed to enable scanmac, err=%d\n", err));
-		return err;
-	}
-
-	/* Configure scanmac */
-	memset(buffer, 0x0, sizeof(buffer));
-	sm_config = (wl_scanmac_config_t *)sm->data;
-	sm->len = sizeof(*sm_config);
-	sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
-	sm_config->scan_bitmap = WL_SCANMAC_SCAN_UNASSOC;
-
-	/* Set current mac address */
-	memcpy(&sm_config->mac.octet, current_mac, ETH_ALEN);
-	sm_config->mac.octet[3] = 0x0;
-	sm_config->mac.octet[4] = 0x0;
-	sm_config->mac.octet[5] = 0x0;
-
-	/* Set randomize mac address(last 3bytes) */
-	memset(&sm_config->random_mask.octet, 0x0, ETH_ALEN);
-	sm_config->random_mask.octet[3] = 0xff;
-	sm_config->random_mask.octet[4] = 0xff;
-	sm_config->random_mask.octet[5] = 0xff;
-
-	len = OFFSETOF(wl_scanmac_t, data) + sm->len;
-
-	err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
-		sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
-
-	if (err != BCME_OK) {
-		WL_ERR(("failed scanmac configuration\n"));
-
-		/* Disable scan mac for clean-up */
-		wl_cfg80211_random_mac_disable(dev);
-		return err;
-	}
-
-	WL_ERR(("random MAC enable done"));
-	return err;
-}
-
-int
-wl_cfg80211_random_mac_disable(struct net_device *dev)
-{
-	s32 err = BCME_ERROR;
-	uint8 buffer[20] = {0, };
-	wl_scanmac_t *sm = NULL;
-	int len = 0;
-	wl_scanmac_enable_t *sm_enable = NULL;
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-
-	sm = (wl_scanmac_t *)buffer;
-	sm_enable = (wl_scanmac_enable_t *)sm->data;
-	sm->len = sizeof(*sm_enable);
-	sm_enable->enable = 0;
-	len = OFFSETOF(wl_scanmac_t, data) + sm->len;
-
-	sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
-
-	err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
-		sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
-
-	if (err != BCME_OK) {
-		WL_ERR(("failed to disable scanmac, err=%d\n", err));
-		return err;
-	}
-
-	WL_ERR(("random MAC disable done\n"));
-	return err;
-}
-#endif /* SUPPORT_RANDOM_MAC_SCAN */
-
-int
-wl_cfg80211_iface_count(void)
-{
-	struct bcm_cfg80211 *cfg = g_bcm_cfg;
-	struct net_info *iter, *next;
-	int iface_count = 0;
-
-	for_each_ndev(cfg, iter, next) {
-		if (iter->ndev) {
-			iface_count++;
-		}
-	}
-	return iface_count;
-}
-
-#ifdef DHD_LOG_DUMP
-struct bcm_cfg80211*
-wl_get_bcm_cfg80211_ptr(void)
-{
-	return g_bcm_cfg;
-}
-#endif /* DHD_LOG_DUMP */
-
-#define CHECK_DONGLE_IDLE_TIME	50
-#define CHECK_DONGLE_IDLE_CNT	100
-int
-wl_check_dongle_idle(struct wiphy *wiphy)
-{
-	int error = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct net_device *primary_ndev;
-	int retry = 0;
-	struct channel_info ci;
-	if (!cfg)
-		return FALSE;
-	/* Use primary I/F for sending cmds down to firmware */
-	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
-
-	while (retry++ < CHECK_DONGLE_IDLE_CNT) {
-		error = wldev_ioctl(primary_ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false);
-		if (error != BCME_OK || ci.scan_channel != 0) {
-			WL_ERR(("Firmware is busy(err:%d scan channel:%d). wait %dms\n",
-				error, ci.scan_channel, CHECK_DONGLE_IDLE_TIME));
-		} else {
-			break;
-		}
-		wl_delay(CHECK_DONGLE_IDLE_TIME);
-	}
-	if (retry >= CHECK_DONGLE_IDLE_CNT) {
-		WL_ERR(("DONGLE is BUSY too long\n"));
-		return FALSE;
-	}
-	WL_DBG(("DONGLE is idle\n"));
-	return TRUE;
-}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
deleted file mode 100644
index 945ab58..0000000
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ /dev/null
@@ -1,1442 +0,0 @@
-/*
- * Linux cfg80211 driver
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_cfg80211.h 608788 2015-12-29 10:59:33Z $
- */
-
-/**
- * Older Linux versions support the 'iw' interface, more recent ones the 'cfg80211' interface.
- */
-
-#ifndef _wl_cfg80211_h_
-#define _wl_cfg80211_h_
-
-#include <linux/wireless.h>
-#include <typedefs.h>
-#include <proto/ethernet.h>
-#include <wlioctl.h>
-#include <linux/wireless.h>
-#include <net/cfg80211.h>
-#include <linux/rfkill.h>
-
-#include <wl_cfgp2p.h>
-#include <linux/time.h>
-
-struct wl_conf;
-struct wl_iface;
-struct bcm_cfg80211;
-struct wl_security;
-struct wl_ibss;
-
-
-#define htod32(i) (i)
-#define htod16(i) (i)
-#define dtoh64(i) (i)
-#define dtoh32(i) (i)
-#define dtoh16(i) (i)
-#define htodchanspec(i) (i)
-#define dtohchanspec(i) (i)
-
-#define WL_DBG_NONE	0
-#define WL_DBG_P2P_ACTION (1 << 5)
-#define WL_DBG_TRACE	(1 << 4)
-#define WL_DBG_SCAN 	(1 << 3)
-#define WL_DBG_DBG 	(1 << 2)
-#define WL_DBG_INFO	(1 << 1)
-#define WL_DBG_ERR	(1 << 0)
-
-#ifdef DHD_LOG_DUMP
-extern void dhd_log_dump_print(const char *fmt, ...);
-extern char *dhd_log_dump_get_timestamp(void);
-struct bcm_cfg80211 *wl_get_bcm_cfg80211_ptr(void);
-#endif /* DHD_LOG_DUMP */
-
-/* 0 invalidates all debug messages.  default is 1 */
-#define WL_DBG_LEVEL 0xFF
-
-#ifdef CUSTOMER_HW4_DEBUG
-#define CFG80211_ERROR_TEXT		"CFG80211-INFO2) "
-#else
-#define CFG80211_ERROR_TEXT		"CFG80211-ERROR) "
-#endif /* CUSTOMER_HW4_DEBUG */
-
-#if defined(DHD_DEBUG)
-#ifdef DHD_LOG_DUMP
-#define	WL_ERR(args)	\
-do {	\
-	if (wl_dbg_level & WL_DBG_ERR) {	\
-		printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__);	\
-		printk args;	\
-		dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__);	\
-		dhd_log_dump_print args;	\
-	}	\
-} while (0)
-#else
-#define	WL_ERR(args)									\
-do {										\
-	if (wl_dbg_level & WL_DBG_ERR) {				\
-			printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__);	\
-			printk args;						\
-		}								\
-} while (0)
-#endif /* DHD_LOG_DUMP */
-#else /* defined(DHD_DEBUG) */
-#define	WL_ERR(args)									\
-do {										\
-	if ((wl_dbg_level & WL_DBG_ERR) && net_ratelimit()) {				\
-			printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__);	\
-			printk args;						\
-		}								\
-} while (0)
-#endif /* defined(DHD_DEBUG) */
-
-#ifdef WL_INFORM
-#undef WL_INFORM
-#endif
-
-#define	WL_INFORM(args)									\
-do {										\
-	if (wl_dbg_level & WL_DBG_INFO) {				\
-			printk(KERN_INFO "CFG80211-INFO) %s : ", __func__);	\
-			printk args;						\
-		}								\
-} while (0)
-
-
-#ifdef WL_SCAN
-#undef WL_SCAN
-#endif
-#define	WL_SCAN(args)								\
-do {									\
-	if (wl_dbg_level & WL_DBG_SCAN) {			\
-		printk(KERN_INFO "CFG80211-SCAN) %s :", __func__);	\
-		printk args;							\
-	}									\
-} while (0)
-#ifdef WL_TRACE
-#undef WL_TRACE
-#endif
-#define	WL_TRACE(args)								\
-do {									\
-	if (wl_dbg_level & WL_DBG_TRACE) {			\
-		printk(KERN_INFO "CFG80211-TRACE) %s :", __func__);	\
-		printk args;							\
-	}									\
-} while (0)
-#ifdef WL_TRACE_HW4
-#undef WL_TRACE_HW4
-#endif
-#ifdef CUSTOMER_HW4_DEBUG
-#define	WL_TRACE_HW4(args)					\
-do {										\
-	if (wl_dbg_level & WL_DBG_ERR) {				\
-			printk(KERN_INFO "CFG80211-TRACE) %s : ", __func__);	\
-			printk args;						\
-		} 								\
-} while (0)
-#else
-#define	WL_TRACE_HW4			WL_TRACE
-#endif /* CUSTOMER_HW4_DEBUG */
-#if (WL_DBG_LEVEL > 0)
-#define	WL_DBG(args)								\
-do {									\
-	if (wl_dbg_level & WL_DBG_DBG) {			\
-		printk(KERN_DEBUG "CFG80211-DEBUG) %s :", __func__);	\
-		printk args;							\
-	}									\
-} while (0)
-#else				/* !(WL_DBG_LEVEL > 0) */
-#define	WL_DBG(args)
-#endif				/* (WL_DBG_LEVEL > 0) */
-#define WL_PNO(x)
-#define WL_SD(x)
-
-
-#define WL_SCAN_RETRY_MAX	3
-#define WL_NUM_PMKIDS_MAX	MAXPMKID
-#define WL_SCAN_BUF_MAX 	(1024 * 8)
-#define WL_TLV_INFO_MAX 	1500
-#define WL_SCAN_IE_LEN_MAX      2048
-#define WL_BSS_INFO_MAX		2048
-#define WL_ASSOC_INFO_MAX	512
-#define WL_IOCTL_LEN_MAX	2048
-#define WL_EXTRA_BUF_MAX	2048
-#define WL_SCAN_ERSULTS_LAST 	(WL_SCAN_RESULTS_NO_MEM+1)
-#define WL_AP_MAX			256
-#define WL_FILE_NAME_MAX	256
-#define WL_DWELL_TIME		200
-#define WL_MED_DWELL_TIME	400
-#define WL_MIN_DWELL_TIME	100
-#define WL_LONG_DWELL_TIME	1000
-#define IFACE_MAX_CNT	4
-#define WL_SCAN_CONNECT_DWELL_TIME_MS		200
-#define WL_SCAN_JOIN_PROBE_INTERVAL_MS		20
-#define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS	320
-#define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS	400
-#define WL_AF_TX_MAX_RETRY	5
-
-#define WL_AF_SEARCH_TIME_MAX		450
-#define WL_AF_TX_EXTRA_TIME_MAX		200
-
-#define WL_SCAN_TIMER_INTERVAL_MS	10000 /* Scan timeout */
-#define WL_CHANNEL_SYNC_RETRY 	5
-#define WL_INVALID 		-1
-
-#ifdef DHD_LOSSLESS_ROAMING
-#define WL_ROAM_TIMEOUT_MS	1000 /* Roam timeout */
-#endif
-/* Bring down SCB Timeout to 20secs from 60secs default */
-#ifndef WL_SCB_TIMEOUT
-#define WL_SCB_TIMEOUT	20
-#endif
-
-#ifndef WL_SCB_ACTIVITY_TIME
-#define WL_SCB_ACTIVITY_TIME	5
-#endif
-
-#ifndef WL_SCB_MAX_PROBE
-#define WL_SCB_MAX_PROBE	3
-#endif
-
-#ifndef WL_MIN_PSPRETEND_THRESHOLD
-#define WL_MIN_PSPRETEND_THRESHOLD	2
-#endif
-
-/* SCAN_SUPPRESS timer values in ms */
-#define WL_SCAN_SUPPRESS_TIMEOUT 31000 /* default Framwork DHCP timeout is 30 sec */
-#define WL_SCAN_SUPPRESS_RETRY 3000
-
-#define WL_PM_ENABLE_TIMEOUT 10000
-
-/* cfg80211 wowlan definitions */
-#define WL_WOWLAN_MAX_PATTERNS			8
-#define WL_WOWLAN_MIN_PATTERN_LEN		1
-#define WL_WOWLAN_MAX_PATTERN_LEN		255
-#define WL_WOWLAN_PKT_FILTER_ID_FIRST	201
-#define WL_WOWLAN_PKT_FILTER_ID_LAST	(WL_WOWLAN_PKT_FILTER_ID_FIRST + \
-									WL_WOWLAN_MAX_PATTERNS - 1)
-
-#ifdef WLTDLS
-#define TDLS_TUNNELED_PRB_REQ	"\x7f\x50\x6f\x9a\04"
-#define TDLS_TUNNELED_PRB_RESP	"\x7f\x50\x6f\x9a\05"
-#endif /* WLTDLS */
-
-
-/* driver status */
-enum wl_status {
-	WL_STATUS_READY = 0,
-	WL_STATUS_SCANNING,
-	WL_STATUS_SCAN_ABORTING,
-	WL_STATUS_CONNECTING,
-	WL_STATUS_CONNECTED,
-	WL_STATUS_DISCONNECTING,
-	WL_STATUS_AP_CREATING,
-	WL_STATUS_AP_CREATED,
-	/* whole sending action frame procedure:
-	 * includes a) 'finding common channel' for public action request frame
-	 * and b) 'sending af via 'actframe' iovar'
-	 */
-	WL_STATUS_SENDING_ACT_FRM,
-	/* find a peer to go to a common channel before sending public action req frame */
-	WL_STATUS_FINDING_COMMON_CHANNEL,
-	/* waiting for next af to sync time of supplicant.
-	 * it includes SENDING_ACT_FRM and WAITING_NEXT_ACT_FRM_LISTEN
-	 */
-	WL_STATUS_WAITING_NEXT_ACT_FRM,
-#ifdef WL_CFG80211_SYNC_GON
-	/* go to listen state to wait for next af after SENDING_ACT_FRM */
-	WL_STATUS_WAITING_NEXT_ACT_FRM_LISTEN,
-#endif /* WL_CFG80211_SYNC_GON */
-	/* it will be set when upper layer requests listen and succeed in setting listen mode.
-	 * if set, other scan request can abort current listen state
-	 */
-	WL_STATUS_REMAINING_ON_CHANNEL,
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-	/* it's fake listen state to keep current scan state.
-	 * it will be set when upper layer requests listen but scan is running. then just run
-	 * a expire timer without actual listen state.
-	 * if set, other scan request does not need to abort scan.
-	 */
-	WL_STATUS_FAKE_REMAINING_ON_CHANNEL
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-};
-
-/* wi-fi mode */
-enum wl_mode {
-	WL_MODE_BSS,
-	WL_MODE_IBSS,
-	WL_MODE_AP
-};
-
-/* driver profile list */
-enum wl_prof_list {
-	WL_PROF_MODE,
-	WL_PROF_SSID,
-	WL_PROF_SEC,
-	WL_PROF_IBSS,
-	WL_PROF_BAND,
-	WL_PROF_CHAN,
-	WL_PROF_BSSID,
-	WL_PROF_ACT,
-	WL_PROF_BEACONINT,
-	WL_PROF_DTIMPERIOD
-};
-
-/* donlge escan state */
-enum wl_escan_state {
-	WL_ESCAN_STATE_IDLE,
-	WL_ESCAN_STATE_SCANING
-};
-/* fw downloading status */
-enum wl_fw_status {
-	WL_FW_LOADING_DONE,
-	WL_NVRAM_LOADING_DONE
-};
-
-enum wl_management_type {
-	WL_BEACON = 0x1,
-	WL_PROBE_RESP = 0x2,
-	WL_ASSOC_RESP = 0x4
-};
-
-enum wl_pm_workq_act_type {
-	WL_PM_WORKQ_SHORT,
-	WL_PM_WORKQ_LONG,
-	WL_PM_WORKQ_DEL
-};
-
-/* beacon / probe_response */
-struct beacon_proberesp {
-	__le64 timestamp;
-	__le16 beacon_int;
-	__le16 capab_info;
-	u8 variable[0];
-} __attribute__ ((packed));
-
-/* driver configuration */
-struct wl_conf {
-	u32 frag_threshold;
-	u32 rts_threshold;
-	u32 retry_short;
-	u32 retry_long;
-	s32 tx_power;
-	struct ieee80211_channel channel;
-};
-
-typedef s32(*EVENT_HANDLER) (struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-                            const wl_event_msg_t *e, void *data);
-
-/* bss inform structure for cfg80211 interface */
-struct wl_cfg80211_bss_info {
-	u16 band;
-	u16 channel;
-	s16 rssi;
-	u16 frame_len;
-	u8 frame_buf[1];
-};
-
-/* basic structure of scan request */
-struct wl_scan_req {
-	struct wlc_ssid ssid;
-};
-
-/* basic structure of information element */
-struct wl_ie {
-	u16 offset;
-	u8 buf[WL_TLV_INFO_MAX];
-};
-
-/* event queue for cfg80211 main event */
-struct wl_event_q {
-	struct list_head eq_list;
-	u32 etype;
-	wl_event_msg_t emsg;
-	s8 edata[1];
-};
-
-/* security information with currently associated ap */
-struct wl_security {
-	u32 wpa_versions;
-	u32 auth_type;
-	u32 cipher_pairwise;
-	u32 cipher_group;
-	u32 wpa_auth;
-	u32 auth_assoc_res_status;
-};
-
-/* ibss information for currently joined ibss network */
-struct wl_ibss {
-	u8 beacon_interval;	/* in millisecond */
-	u8 atim;		/* in millisecond */
-	s8 join_only;
-	u8 band;
-	u8 channel;
-};
-
-typedef struct wl_bss_vndr_ies {
-	u8  probe_req_ie[VNDR_IES_BUF_LEN];
-	u8  probe_res_ie[VNDR_IES_MAX_BUF_LEN];
-	u8  assoc_req_ie[VNDR_IES_BUF_LEN];
-	u8  assoc_res_ie[VNDR_IES_BUF_LEN];
-	u8  beacon_ie[VNDR_IES_MAX_BUF_LEN];
-	u32 probe_req_ie_len;
-	u32 probe_res_ie_len;
-	u32 assoc_req_ie_len;
-	u32 assoc_res_ie_len;
-	u32 beacon_ie_len;
-} wl_bss_vndr_ies_t;
-
-typedef struct wl_cfgbss {
-	u8 *wpa_ie;
-	u8 *rsn_ie;
-	u8 *wps_ie;
-	bool security_mode;
-	struct wl_bss_vndr_ies ies;	/* Common for STA, P2P GC, GO, AP, P2P Disc Interface */
-} wl_cfgbss_t;
-
-/* cfg driver profile */
-struct wl_profile {
-	u32 mode;
-	s32 band;
-	u32 channel;
-	struct wlc_ssid ssid;
-	struct wl_security sec;
-	struct wl_ibss ibss;
-	u8 bssid[ETHER_ADDR_LEN];
-	u16 beacon_interval;
-	u8 dtim_period;
-	bool active;
-};
-
-struct net_info {
-	struct net_device *ndev;
-	struct wireless_dev *wdev;
-	struct wl_profile profile;
-	s32 mode;
-	s32 roam_off;
-	unsigned long sme_state;
-	bool pm_restore;
-	bool pm_block;
-	s32 pm;
-	s32 bssidx;
-	wl_cfgbss_t bss;
-	u32 ulb_bw;
-	struct list_head list; /* list of all net_info structure */
-};
-
-/* association inform */
-#define MAX_REQ_LINE 1024
-struct wl_connect_info {
-	u8 req_ie[MAX_REQ_LINE];
-	s32 req_ie_len;
-	u8 resp_ie[MAX_REQ_LINE];
-	s32 resp_ie_len;
-};
-
-/* firmware /nvram downloading controller */
-struct wl_fw_ctrl {
-	const struct firmware *fw_entry;
-	unsigned long status;
-	u32 ptr;
-	s8 fw_name[WL_FILE_NAME_MAX];
-	s8 nvram_name[WL_FILE_NAME_MAX];
-};
-
-/* assoc ie length */
-struct wl_assoc_ielen {
-	u32 req_len;
-	u32 resp_len;
-};
-
-/* wpa2 pmk list */
-struct wl_pmk_list {
-	pmkid_list_t pmkids;
-	pmkid_t foo[MAXPMKID - 1];
-};
-
-#ifdef DHD_MAX_IFS
-#define WL_MAX_IFS DHD_MAX_IFS
-#else
-#define WL_MAX_IFS 16
-#endif
-
-#define ESCAN_BUF_SIZE (64 * 1024)
-
-struct escan_info {
-	u32 escan_state;
-#if defined(STATIC_WL_PRIV_STRUCT)
-#ifndef CONFIG_DHD_USE_STATIC_BUF
-#error STATIC_WL_PRIV_STRUCT should be used with CONFIG_DHD_USE_STATIC_BUF
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-	u8 *escan_buf;
-#else
-	u8 escan_buf[ESCAN_BUF_SIZE];
-#endif /* STATIC_WL_PRIV_STRUCT */
-	struct wiphy *wiphy;
-	struct net_device *ndev;
-};
-
-#ifdef ESCAN_BUF_OVERFLOW_MGMT
-#define BUF_OVERFLOW_MGMT_COUNT 3
-typedef struct {
-	int RSSI;
-	int length;
-	struct ether_addr BSSID;
-} removal_element_t;
-#endif /* ESCAN_BUF_OVERFLOW_MGMT */
-
-struct afx_hdl {
-	wl_af_params_t *pending_tx_act_frm;
-	struct ether_addr	tx_dst_addr;
-	struct net_device *dev;
-	struct work_struct work;
-	s32 bssidx;
-	u32 retry;
-	s32 peer_chan;
-	s32 peer_listen_chan; /* search channel: configured by upper layer */
-	s32 my_listen_chan;	/* listen chanel: extract it from prb req or gon req */
-	bool is_listen;
-	bool ack_recv;
-	bool is_active;
-};
-
-struct parsed_ies {
-	wpa_ie_fixed_t *wps_ie;
-	u32 wps_ie_len;
-	wpa_ie_fixed_t *wpa_ie;
-	u32 wpa_ie_len;
-	bcm_tlv_t *wpa2_ie;
-	u32 wpa2_ie_len;
-};
-
-
-#ifdef P2P_LISTEN_OFFLOADING
-typedef struct {
-	uint16	period;                 /* listen offload period */
-	uint16	interval;               /* listen offload interval */
-	uint16	count;			/* listen offload count */
-	uint16	pad;                    /* pad for 32bit align */
-} wl_p2plo_listen_t;
-#endif /* P2P_LISTEN_OFFLOADING */
-
-#ifdef WL11U
-/* Max length of Interworking element */
-#define IW_IES_MAX_BUF_LEN 		9
-#endif
-#define MAX_EVENT_BUF_NUM 16
-typedef struct wl_eventmsg_buf {
-	u16 num;
-	struct {
-		u16 type;
-		bool set;
-	} event [MAX_EVENT_BUF_NUM];
-} wl_eventmsg_buf_t;
-
-typedef struct wl_if_event_info {
-	bool valid;
-	int ifidx;
-	int bssidx;
-	uint8 mac[ETHER_ADDR_LEN];
-	char name[IFNAMSIZ+1];
-} wl_if_event_info;
-
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-#define GET_BSS_INFO_LEN 90
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-
-/* private data of cfg80211 interface */
-struct bcm_cfg80211 {
-	struct wireless_dev *wdev;	/* representing cfg cfg80211 device */
-
-	struct wireless_dev *p2p_wdev;	/* representing cfg cfg80211 device for P2P */
-	struct net_device *p2p_net;    /* reference to p2p0 interface */
-
-	struct wl_conf *conf;
-	struct cfg80211_scan_request *scan_request;	/* scan request object */
-	EVENT_HANDLER evt_handler[WLC_E_LAST];
-	struct list_head eq_list;	/* used for event queue */
-	struct list_head net_list;     /* used for struct net_info */
-	spinlock_t net_list_sync;	/* to protect scan status (and others if needed) */
-	spinlock_t eq_lock;	/* for event queue synchronization */
-	spinlock_t cfgdrv_lock;	/* to protect scan status (and others if needed) */
-	struct completion act_frm_scan;
-	struct completion iface_disable;
-	struct completion wait_next_af;
-	struct mutex usr_sync;	/* maily for up/down synchronization */
-	struct mutex scan_complete;	/* serialize scan_complete call */
-	struct wl_scan_results *bss_list;
-	struct wl_scan_results *scan_results;
-
-	/* scan request object for internal purpose */
-	struct wl_scan_req *scan_req_int;
-	/* information element object for internal purpose */
-#if defined(STATIC_WL_PRIV_STRUCT)
-	struct wl_ie *ie;
-#else
-	struct wl_ie ie;
-#endif
-
-	/* association information container */
-#if defined(STATIC_WL_PRIV_STRUCT)
-	struct wl_connect_info *conn_info;
-#else
-	struct wl_connect_info conn_info;
-#endif
-#ifdef DEBUGFS_CFG80211
-	struct dentry		*debugfs;
-#endif /* DEBUGFS_CFG80211 */
-	struct wl_pmk_list *pmk_list;	/* wpa2 pmk list */
-	tsk_ctl_t event_tsk;  		/* task of main event handler thread */
-	void *pub;
-	u32 iface_cnt;
-	u32 channel;		/* current channel */
-	u32 af_sent_channel;	/* channel action frame is sent */
-	/* next af subtype to cancel the remained dwell time in rx process */
-	u8 next_af_subtype;
-#ifdef WL_CFG80211_SYNC_GON
-	ulong af_tx_sent_jiffies;
-#endif /* WL_CFG80211_SYNC_GON */
-	struct escan_info escan_info;   /* escan information */
-	bool active_scan;	/* current scan mode */
-	bool ibss_starter;	/* indicates this sta is ibss starter */
-	bool link_up;		/* link/connection up flag */
-
-	/* indicate whether chip to support power save mode */
-	bool pwr_save;
-	bool roam_on;		/* on/off switch for self-roaming */
-	bool scan_tried;	/* indicates if first scan attempted */
-#if defined(BCMSDIO) || defined(BCMPCIE)
-	bool wlfc_on;
-#endif 
-	bool vsdb_mode;
-	bool roamoff_on_concurrent;
-	u8 *ioctl_buf;		/* ioctl buffer */
-	struct mutex ioctl_buf_sync;
-	u8 *escan_ioctl_buf;
-	u8 *extra_buf;	/* maily to grab assoc information */
-	struct dentry *debugfsdir;
-	struct rfkill *rfkill;
-	bool rf_blocked;
-	struct ieee80211_channel remain_on_chan;
-	enum nl80211_channel_type remain_on_chan_type;
-	u64 send_action_id;
-	u64 last_roc_id;
-	wait_queue_head_t netif_change_event;
-	wl_if_event_info if_event_info;
-	struct completion send_af_done;
-	struct afx_hdl *afx_hdl;
-	struct p2p_info *p2p;
-	bool p2p_supported;
-	void *btcoex_info;
-	struct timer_list scan_timeout;   /* Timer for catch scan event timeout */
-#if defined(P2P_IE_MISSING_FIX)
-	bool p2p_prb_noti;
-#endif
-	s32(*state_notifier) (struct bcm_cfg80211 *cfg,
-		struct net_info *_net_info, enum wl_status state, bool set);
-	unsigned long interrested_state;
-	wlc_ssid_t hostapd_ssid;
-#ifdef WL11U
-	bool wl11u;
-	u8 iw_ie[IW_IES_MAX_BUF_LEN];
-	u32 iw_ie_len;
-#endif /* WL11U */
-	bool sched_scan_running;	/* scheduled scan req status */
-#ifdef WL_SCHED_SCAN
-	struct cfg80211_sched_scan_request *sched_scan_req;	/* scheduled scan req */
-#endif /* WL_SCHED_SCAN */
-	bool scan_suppressed;
-	struct timer_list scan_supp_timer;
-	struct work_struct wlan_work;
-	struct mutex event_sync;	/* maily for up/down synchronization */
-	bool disable_roam_event;
-	struct delayed_work pm_enable_work;
-	struct mutex pm_sync;	/* mainly for pm work synchronization */
-
-	vndr_ie_setbuf_t *ibss_vsie;	/* keep the VSIE for IBSS */
-	int ibss_vsie_len;
-	u32 rmc_event_pid;
-	u32 rmc_event_seq;
-#ifdef WLAIBSS_MCHAN
-	struct ether_addr ibss_if_addr;
-	bcm_struct_cfgdev *ibss_cfgdev; /* For AIBSS */
-#endif /* WLAIBSS_MCHAN */
-	bcm_struct_cfgdev *bss_cfgdev;  /* For DUAL STA/STA+AP */
-	s32 cfgdev_bssidx;
-	bool bss_pending_op;		/* indicate where there is a pending IF operation */
-	int roam_offload;
-#ifdef WL_NAN
-	bool nan_enable;
-	bool nan_running;
-#endif /* WL_NAN */
-#ifdef WL_CFG80211_P2P_DEV_IF
-	bool down_disc_if;
-#endif /* WL_CFG80211_P2P_DEV_IF */
-#ifdef P2PLISTEN_AP_SAMECHN
-	bool p2p_resp_apchn_status;
-#endif /* P2PLISTEN_AP_SAMECHN */
-	struct wl_wsec_key wep_key;
-#ifdef WLTDLS
-	u8 *tdls_mgmt_frame;
-	u32 tdls_mgmt_frame_len;
-	s32 tdls_mgmt_freq;
-#endif /* WLTDLS */
-	bool need_wait_afrx;
-#ifdef QOS_MAP_SET
-	uint8	 *up_table;	/* user priority table, size is UP_TABLE_MAX */
-#endif /* QOS_MAP_SET */
-	struct ether_addr last_roamed_addr;
-#ifdef DHD_LOSSLESS_ROAMING
-	struct timer_list roam_timeout;   /* Timer for catch roam timeout */
-#endif
-	bool rcc_enabled;	/* flag for Roam channel cache feature */
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-	char bss_info[GET_BSS_INFO_LEN];
-	wl_event_msg_t event_auth_assoc;
-	u32 assoc_reject_status;
-	u32 roam_count;
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-	u16 ap_oper_channel;
-	bool revert_ndo_disable;
-#if defined(SUPPORT_RANDOM_MAC_SCAN)
-	bool random_mac_enabled;
-#endif /* SUPPORT_RANDOM_MAC_SCAN */
-};
-
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-	4 && __GNUC_MINOR__ >= 6))
-
-#define BCM_LIST_FOR_EACH_ENTRY_SAFE(pos, next, head, member) \
-_Pragma("GCC diagnostic push") \
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
-list_for_each_entry_safe((pos), (next), (head), member) \
-_Pragma("GCC diagnostic pop") \
-
-#else
-#define BCM_LIST_FOR_EACH_ENTRY_SAFE(pos, next, head, member) \
-list_for_each_entry_safe((pos), (next), (head), member) \
-
-#endif /* STRICT_GCC_WARNINGS */
-
-static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
-{
-	return bss = bss ?
-		(struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info;
-}
-
-static inline void
-wl_probe_wdev_all(struct bcm_cfg80211 *cfg)
-{
-	struct net_info *_net_info, *next;
-	unsigned long int flags;
-	int idx = 0;
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next,
-		&cfg->net_list, list) {
-		WL_ERR(("%s: net_list[%d] bssidx: %d, "
-			"ndev: %p, wdev: %p \n", __FUNCTION__,
-			idx++, _net_info->bssidx,
-			_net_info->ndev, _net_info->wdev));
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return;
-}
-
-static inline struct net_info *
-wl_get_netinfo_by_bssidx(struct bcm_cfg80211 *cfg, s32 bssidx)
-{
-	struct net_info *_net_info, *next, *info = NULL;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if ((bssidx >= 0) && (_net_info->bssidx == bssidx)) {
-			info = _net_info;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return info;
-}
-
-static inline void
-wl_dealloc_netinfo_by_wdev(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev)
-{
-	struct net_info *_net_info, *next;
-	unsigned long int flags;
-
-#ifdef DHD_IFDEBUG
-	WL_ERR(("dealloc_netinfo enter wdev=%p \n", wdev));
-#endif
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (wdev && (_net_info->wdev == wdev)) {
-			wl_cfgbss_t *bss = &_net_info->bss;
-
-			kfree(bss->wpa_ie);
-			bss->wpa_ie = NULL;
-			kfree(bss->rsn_ie);
-			bss->rsn_ie = NULL;
-			kfree(bss->wps_ie);
-			bss->wps_ie = NULL;
-			list_del(&_net_info->list);
-			cfg->iface_cnt--;
-			kfree(_net_info);
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-#ifdef DHD_IFDEBUG
-	WL_ERR(("dealloc_netinfo exit iface_cnt=%d \n", cfg->iface_cnt));
-#endif
-}
-
-static inline s32
-wl_alloc_netinfo(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	struct wireless_dev * wdev, s32 mode, bool pm_block, u8 bssidx)
-{
-	struct net_info *_net_info;
-	s32 err = 0;
-	unsigned long int flags;
-#ifdef DHD_IFDEBUG
-	WL_ERR(("alloc_netinfo enter bssidx=%d wdev=%p ndev=%p\n", bssidx, wdev, ndev));
-#endif
-	/* Check whether there is any duplicate entry for the
-	 *  same bssidx *
-	 */
-	if ((_net_info = wl_get_netinfo_by_bssidx(cfg, bssidx))) {
-		/* We have a duplicate entry for the same bssidx
-		 * already present which shouldn't have been the case.
-		 * Attempt recovery.
-		 */
-		WL_ERR(("Duplicate entry for bssidx=%d present\n", bssidx));
-		wl_probe_wdev_all(cfg);
-#ifdef DHD_DEBUG
-		ASSERT(0);
-#endif /* DHD_DEBUG */
-		WL_ERR(("Removing the Dup entry for bssidx=%d \n", bssidx));
-		wl_dealloc_netinfo_by_wdev(cfg, _net_info->wdev);
-	}
-	if (cfg->iface_cnt == IFACE_MAX_CNT)
-		return -ENOMEM;
-	_net_info = kzalloc(sizeof(struct net_info), GFP_KERNEL);
-	if (!_net_info)
-		err = -ENOMEM;
-	else {
-		_net_info->mode = mode;
-		_net_info->ndev = ndev;
-		_net_info->wdev = wdev;
-		_net_info->pm_restore = 0;
-		_net_info->pm = 0;
-		_net_info->pm_block = pm_block;
-		_net_info->roam_off = WL_INVALID;
-		_net_info->bssidx = bssidx;
-		spin_lock_irqsave(&cfg->net_list_sync, flags);
-		cfg->iface_cnt++;
-		list_add(&_net_info->list, &cfg->net_list);
-		spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	}
-#ifdef DHD_IFDEBUG
-	WL_ERR(("alloc_netinfo exit iface_cnt=%d \n", cfg->iface_cnt));
-#endif
-	return err;
-}
-
-static inline void
-wl_delete_all_netinfo(struct bcm_cfg80211 *cfg)
-{
-	struct net_info *_net_info, *next;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		wl_cfgbss_t *bss = &_net_info->bss;
-
-		kfree(bss->wpa_ie);
-		bss->wpa_ie = NULL;
-		kfree(bss->rsn_ie);
-		bss->rsn_ie = NULL;
-		kfree(bss->wps_ie);
-		bss->wps_ie = NULL;
-		list_del(&_net_info->list);
-		if (_net_info->wdev)
-			kfree(_net_info->wdev);
-		kfree(_net_info);
-	}
-	cfg->iface_cnt = 0;
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-}
-static inline u32
-wl_get_status_all(struct bcm_cfg80211 *cfg, s32 status)
-
-{
-	struct net_info *_net_info, *next;
-	u32 cnt = 0;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (_net_info->ndev &&
-			test_bit(status, &_net_info->sme_state))
-			cnt++;
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return cnt;
-}
-static inline void
-wl_set_status_all(struct bcm_cfg80211 *cfg, s32 status, u32 op)
-{
-	struct net_info *_net_info, *next;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		switch (op) {
-			case 1:
-				break; /* set all status is not allowed */
-			case 2:
-				/*
-				 * Release the spinlock before calling notifier. Else there
-				 * will be nested calls
-				 */
-				spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-				clear_bit(status, &_net_info->sme_state);
-				if (cfg->state_notifier &&
-					test_bit(status, &(cfg->interrested_state)))
-					cfg->state_notifier(cfg, _net_info, status, false);
-				return;
-			case 4:
-				break; /* change all status is not allowed */
-			default:
-				break; /* unknown operation */
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-}
-static inline void
-wl_set_status_by_netdev(struct bcm_cfg80211 *cfg, s32 status,
-	struct net_device *ndev, u32 op)
-{
-
-	struct net_info *_net_info, *next;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (ndev && (_net_info->ndev == ndev)) {
-			switch (op) {
-				case 1:
-					/*
-					 * Release the spinlock before calling notifier. Else there
-					 * will be nested calls
-					 */
-					spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-					set_bit(status, &_net_info->sme_state);
-					if (cfg->state_notifier &&
-						test_bit(status, &(cfg->interrested_state)))
-						cfg->state_notifier(cfg, _net_info, status, true);
-					return;
-				case 2:
-					/*
-					 * Release the spinlock before calling notifier. Else there
-					 * will be nested calls
-					 */
-					spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-					clear_bit(status, &_net_info->sme_state);
-					if (cfg->state_notifier &&
-						test_bit(status, &(cfg->interrested_state)))
-						cfg->state_notifier(cfg, _net_info, status, false);
-					return;
-				case 4:
-					change_bit(status, &_net_info->sme_state);
-					break;
-			}
-		}
-
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-
-}
-
-static inline wl_cfgbss_t *
-wl_get_cfgbss_by_wdev(struct bcm_cfg80211 *cfg,
-	struct wireless_dev *wdev)
-{
-	struct net_info *_net_info, *next;
-	wl_cfgbss_t *bss = NULL;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (wdev && (_net_info->wdev == wdev)) {
-			bss = &_net_info->bss;
-			break;
-		}
-	}
-
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return bss;
-}
-
-static inline u32
-wl_get_status_by_netdev(struct bcm_cfg80211 *cfg, s32 status,
-	struct net_device *ndev)
-{
-	struct net_info *_net_info, *next;
-	u32 stat = 0;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (ndev && (_net_info->ndev == ndev)) {
-			stat = test_bit(status, &_net_info->sme_state);
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return stat;
-}
-
-static inline s32
-wl_get_mode_by_netdev(struct bcm_cfg80211 *cfg, struct net_device *ndev)
-{
-	struct net_info *_net_info, *next;
-	s32 mode = -1;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (ndev && (_net_info->ndev == ndev)) {
-			mode = _net_info->mode;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return mode;
-}
-
-static inline void
-wl_set_mode_by_netdev(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	s32 mode)
-{
-	struct net_info *_net_info, *next;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (ndev && (_net_info->ndev == ndev))
-			_net_info->mode = mode;
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-}
-
-static inline s32
-wl_get_bssidx_by_wdev(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev)
-{
-	struct net_info *_net_info, *next;
-	s32 bssidx = -1;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (_net_info->wdev && (_net_info->wdev == wdev)) {
-			bssidx = _net_info->bssidx;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return bssidx;
-}
-
-static inline struct wireless_dev *
-wl_get_wdev_by_bssidx(struct bcm_cfg80211 *cfg, s32 bssidx)
-{
-	struct net_info *_net_info, *next;
-	struct wireless_dev *wdev = NULL;
-	unsigned long int flags;
-
-	if (bssidx < 0)
-		return NULL;
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (_net_info->bssidx == bssidx) {
-				wdev = _net_info->wdev;
-				break;
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return wdev;
-}
-
-static inline struct wl_profile *
-wl_get_profile_by_netdev(struct bcm_cfg80211 *cfg, struct net_device *ndev)
-{
-	struct net_info *_net_info, *next;
-	struct wl_profile *prof = NULL;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (ndev && (_net_info->ndev == ndev)) {
-			prof = &_net_info->profile;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return prof;
-}
-static inline struct net_info *
-wl_get_netinfo_by_netdev(struct bcm_cfg80211 *cfg, struct net_device *ndev)
-{
-	struct net_info *_net_info, *next, *info = NULL;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (ndev && (_net_info->ndev == ndev)) {
-			info = _net_info;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return info;
-}
-
-static inline struct net_info *
-wl_get_netinfo_by_wdev(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev)
-{
-	struct net_info *_net_info, *next, *info = NULL;
-	unsigned long int flags;
-
-	spin_lock_irqsave(&cfg->net_list_sync, flags);
-	BCM_LIST_FOR_EACH_ENTRY_SAFE(_net_info, next, &cfg->net_list, list) {
-		if (wdev && (_net_info->wdev == wdev)) {
-			info = _net_info;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&cfg->net_list_sync, flags);
-	return info;
-}
-
-#define is_p2p_group_iface(wdev) (((wdev->iftype == NL80211_IFTYPE_P2P_GO) || \
-		(wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) ? 1 : 0)
-#define bcmcfg_to_wiphy(cfg) (cfg->wdev->wiphy)
-#define bcmcfg_to_prmry_ndev(cfg) (cfg->wdev->netdev)
-#define bcmcfg_to_prmry_wdev(cfg) (cfg->wdev)
-#define bcmcfg_to_p2p_wdev(cfg) (cfg->p2p_wdev)
-#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr))
-#define ndev_to_wdev(ndev) (ndev->ieee80211_ptr)
-#define wdev_to_ndev(wdev) (wdev->netdev)
-
-#if defined(WL_ENABLE_P2P_IF)
-#define ndev_to_wlc_ndev(ndev, cfg)	((ndev == cfg->p2p_net) ? \
-	bcmcfg_to_prmry_ndev(cfg) : ndev)
-#else
-#define ndev_to_wlc_ndev(ndev, cfg)	(ndev)
-#endif /* WL_ENABLE_P2P_IF */
-
-#define wdev_to_wlc_ndev(wdev, cfg)	\
-	(wdev_to_ndev(wdev) ? \
-	wdev_to_ndev(wdev) : bcmcfg_to_prmry_ndev(cfg))
-#if defined(WL_CFG80211_P2P_DEV_IF)
-#define cfgdev_to_wlc_ndev(cfgdev, cfg)	wdev_to_wlc_ndev(cfgdev, cfg)
-#define bcmcfg_to_prmry_cfgdev(cfgdev, cfg) bcmcfg_to_prmry_wdev(cfg)
-#elif defined(WL_ENABLE_P2P_IF)
-#define cfgdev_to_wlc_ndev(cfgdev, cfg)	ndev_to_wlc_ndev(cfgdev, cfg)
-#define bcmcfg_to_prmry_cfgdev(cfgdev, cfg) bcmcfg_to_prmry_ndev(cfg)
-#else
-#define cfgdev_to_wlc_ndev(cfgdev, cfg)	(cfgdev)
-#define bcmcfg_to_prmry_cfgdev(cfgdev, cfg) (cfgdev)
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-#define cfgdev_to_wdev(cfgdev)	(cfgdev)
-#define ndev_to_cfgdev(ndev)	ndev_to_wdev(ndev)
-#define cfgdev_to_ndev(cfgdev)	(cfgdev ? (cfgdev->netdev) : NULL)
-#define wdev_to_cfgdev(cfgdev)	(cfgdev)
-#define discover_cfgdev(cfgdev, cfg) (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE)
-#else
-#define cfgdev_to_wdev(cfgdev)	(cfgdev->ieee80211_ptr)
-#define wdev_to_cfgdev(cfgdev)	cfgdev ? (cfgdev->netdev) : NULL
-#define ndev_to_cfgdev(ndev)	(ndev)
-#define cfgdev_to_ndev(cfgdev)	(cfgdev)
-#define discover_cfgdev(cfgdev, cfg) (cfgdev == cfg->p2p_net)
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-#define scan_req_match(cfg)	(((cfg) && (cfg->scan_request) && \
-	(cfg->scan_request->wdev == cfg->p2p_wdev)) ? true : false)
-#elif defined(WL_ENABLE_P2P_IF)
-#define scan_req_match(cfg)	(((cfg) && (cfg->scan_request) && \
-	(cfg->scan_request->dev == cfg->p2p_net)) ? true : false)
-#else
-#define scan_req_match(cfg)	(((cfg) && p2p_is_on(cfg) && p2p_scan(cfg)) ? \
-	true : false)
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
-#define scan_req_iftype(req) (req->dev->ieee80211_ptr->iftype)
-#else
-#define scan_req_iftype(req) (req->wdev->iftype)
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) */
-
-#define wl_to_sr(w) (w->scan_req_int)
-#if defined(STATIC_WL_PRIV_STRUCT)
-#define wl_to_ie(w) (w->ie)
-#define wl_to_conn(w) (w->conn_info)
-#else
-#define wl_to_ie(w) (&w->ie)
-#define wl_to_conn(w) (&w->conn_info)
-#endif
-#define wiphy_from_scan(w) (w->escan_info.wiphy)
-#define wl_get_drv_status_all(cfg, stat) \
-	(wl_get_status_all(cfg, WL_STATUS_ ## stat))
-#define wl_get_drv_status(cfg, stat, ndev)  \
-	(wl_get_status_by_netdev(cfg, WL_STATUS_ ## stat, ndev))
-#define wl_set_drv_status(cfg, stat, ndev)  \
-	(wl_set_status_by_netdev(cfg, WL_STATUS_ ## stat, ndev, 1))
-#define wl_clr_drv_status(cfg, stat, ndev)  \
-	(wl_set_status_by_netdev(cfg, WL_STATUS_ ## stat, ndev, 2))
-#define wl_clr_drv_status_all(cfg, stat)  \
-	(wl_set_status_all(cfg, WL_STATUS_ ## stat, 2))
-#define wl_chg_drv_status(cfg, stat, ndev)  \
-	(wl_set_status_by_netdev(cfg, WL_STATUS_ ## stat, ndev, 4))
-
-#define for_each_bss(list, bss, __i)	\
-	for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
-
-#define for_each_ndev(cfg, iter, next) \
-	list_for_each_entry_safe(iter, next, &cfg->net_list, list)
-
-/* In case of WPS from wpa_supplicant, pairwise siute and group suite is 0.
- * In addtion to that, wpa_version is WPA_VERSION_1
- */
-#define is_wps_conn(_sme) \
-	((wl_cfgp2p_find_wpsie((u8 *)_sme->ie, _sme->ie_len) != NULL) && \
-	 (!_sme->crypto.n_ciphers_pairwise) && \
-	 (!_sme->crypto.cipher_group))
-
-#define IS_AKM_SUITE_FT(sec) false
-
-#define IS_AKM_SUITE_CCKM(sec) false
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
-#define STA_INFO_BIT(info) (1ul << NL80211_STA_ ## info)
-#define strnicmp(str1, str2, len) strncasecmp((str1), (str2), (len))
-#else
-#define STA_INFO_BIT(info) (STATION_ ## info)
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
-
-extern s32 wl_cfg80211_attach(struct net_device *ndev, void *context);
-extern s32 wl_cfg80211_attach_post(struct net_device *ndev);
-extern void wl_cfg80211_detach(void *para);
-
-extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e,
-            void *data);
-void wl_cfg80211_set_parent_dev(void *dev);
-struct device *wl_cfg80211_get_parent_dev(void);
-
-/* clear IEs */
-extern s32 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg);
-extern s32 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx);
-
-extern s32 wl_cfg80211_up(void *para);
-extern s32 wl_cfg80211_down(void *para);
-extern s32 wl_cfg80211_notify_ifadd(int ifidx, char *name, uint8 *mac, uint8 bssidx);
-extern s32 wl_cfg80211_notify_ifdel(int ifidx, char *name, uint8 *mac, uint8 bssidx);
-extern s32 wl_cfg80211_notify_ifchange(int ifidx, char *name, uint8 *mac, uint8 bssidx);
-extern struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, char *name,
-	uint8 *mac, uint8 bssidx, char *dngl_name);
-extern int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev);
-extern int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev);
-extern int wl_cfg80211_scan_stop(bcm_struct_cfgdev *cfgdev);
-extern bool wl_cfg80211_is_concurrent_mode(void);
-extern void* wl_cfg80211_get_dhdp(void);
-extern bool wl_cfg80211_is_p2p_active(void);
-extern bool wl_cfg80211_is_roam_offload(void);
-extern bool wl_cfg80211_is_event_from_connected_bssid(const wl_event_msg_t *e, int ifidx);
-extern void wl_cfg80211_dbg_level(u32 level);
-extern s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
-extern s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len);
-extern s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len);
-extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
-	enum wl_management_type type);
-extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len);
-extern s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len);
-#ifdef WL11ULB
-extern s32 wl_cfg80211_set_ulb_mode(struct net_device *dev, int mode);
-extern s32 wl_cfg80211_set_ulb_bw(struct net_device *dev,
-	u32 ulb_bw,  char *ifname);
-#endif /* WL11ULB */
-#ifdef P2PLISTEN_AP_SAMECHN
-extern s32 wl_cfg80211_set_p2p_resp_ap_chn(struct net_device *net, s32 enable);
-#endif /* P2PLISTEN_AP_SAMECHN */
-
-/* btcoex functions */
-void* wl_cfg80211_btcoex_init(struct net_device *ndev);
-void wl_cfg80211_btcoex_deinit(void);
-
-#ifdef WL_SUPPORT_AUTO_CHANNEL
-#define CHANSPEC_BUF_SIZE	1024
-#define CHAN_SEL_IOCTL_DELAY	300
-#define CHAN_SEL_RETRY_COUNT	15
-#define CHANNEL_IS_RADAR(channel)	(((channel & WL_CHAN_RADAR) || \
-	(channel & WL_CHAN_PASSIVE)) ? true : false)
-#define CHANNEL_IS_2G(channel)	(((channel >= 1) && (channel <= 14)) ? \
-	true : false)
-#define CHANNEL_IS_5G(channel)	(((channel >= 36) && (channel <= 165)) ? \
-	true : false)
-extern s32 wl_cfg80211_get_best_channels(struct net_device *dev, char* command,
-	int total_len);
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
-extern int wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n);
-extern int wl_cfg80211_hang(struct net_device *dev, u16 reason);
-extern s32 wl_mode_to_nl80211_iftype(s32 mode);
-int wl_cfg80211_do_driver_init(struct net_device *net);
-void wl_cfg80211_enable_trace(bool set, u32 level);
-extern s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify);
-extern s32 wl_cfg80211_if_is_group_owner(void);
-extern chanspec_t wl_chspec_host_to_driver(chanspec_t chanspec);
-extern chanspec_t wl_ch_host_to_driver(s32 bssidx, u16 channel);
-extern s32 wl_set_tx_power(struct net_device *dev,
-	enum nl80211_tx_power_setting type, s32 dbm);
-extern s32 wl_get_tx_power(struct net_device *dev, s32 *dbm);
-extern s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add);
-extern void wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev);
-extern void wl_cfg80211_add_to_eventbuffer(wl_eventmsg_buf_t *ev, u16 event, bool set);
-extern s32 wl_cfg80211_apply_eventbuffer(struct net_device *ndev,
-	struct bcm_cfg80211 *cfg, wl_eventmsg_buf_t *ev);
-extern void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac);
-extern void wl_cfg80211_update_power_mode(struct net_device *dev);
-extern void wl_cfg80211_set_passive_scan(struct net_device *dev, char *command);
-extern void wl_terminate_event_handler(void);
-#if defined(DHD_ENABLE_BIGDATA_LOGGING)
-extern s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len);
-extern s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int total_len);
-#endif /* DHD_ENABLE_BIGDATA_LOGGING */
-
-#define SCAN_BUF_CNT	2
-#define SCAN_BUF_NEXT	1
-#define WL_SCANTYPE_LEGACY	0x1
-#define WL_SCANTYPE_P2P		0x2
-#define wl_escan_set_sync_id(a, b) ((a) = htod16(0x1234))
-#define wl_escan_set_type(a, b)
-#define wl_escan_get_buf(a, b) ((wl_scan_results_t *) (a)->escan_info.escan_buf)
-#define wl_escan_check_sync_id(a, b, c) 0
-#define wl_escan_print_sync_id(a, b, c)
-#define wl_escan_increment_sync_id(a, b)
-#define wl_escan_init_sync_id(a)
-extern void wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len);
-extern s32 wl_cfg80211_ibss_vsie_delete(struct net_device *dev);
-extern void wl_cfg80211_set_rmc_pid(int pid);
-extern int wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg,
-	bcm_struct_cfgdev *cfgdev, s32 bssidx, s32 pktflag,
-	const u8 *vndr_ie, u32 vndr_ie_len);
-
-
-/* Action frame specific functions */
-extern u8 wl_get_action_category(void *frame, u32 frame_len);
-extern int wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action);
-
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-struct net_device *wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg);
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-
-#ifdef WL_SUPPORT_ACS
-#define ACS_MSRMNT_DELAY 1000 /* dump_obss delay in ms */
-#define IOCTL_RETRY_COUNT 5
-#define CHAN_NOISE_DUMMY -80
-#define OBSS_TOKEN_IDX 15
-#define IBSS_TOKEN_IDX 15
-#define TX_TOKEN_IDX 14
-#define CTG_TOKEN_IDX 13
-#define PKT_TOKEN_IDX 15
-#define IDLE_TOKEN_IDX 12
-#endif /* WL_SUPPORT_ACS */
-
-extern int wl_cfg80211_get_ioctl_version(void);
-extern int wl_cfg80211_enable_roam_offload(struct net_device *dev, int enable);
-extern s32 wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data,
-		char *command, int total_len);
-extern s32 wl_cfg80211_wbtext_config(struct net_device *ndev, char *data,
-		char *command, int total_len);
-extern int wl_cfg80211_wbtext_weight_config(struct net_device *ndev, char *data,
-		char *command, int total_len);
-extern int wl_cfg80211_wbtext_table_config(struct net_device *ndev, char *data,
-		char *command, int total_len);
-extern s32 wl_cfg80211_wbtext_delta_config(struct net_device *ndev, char *data,
-		char *command, int total_len);
-extern s32 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev,
-		void *buf, s32 buflen);
-extern s32 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev,
-		void *buf, s32 buflen);
-#if defined(WL_VIRTUAL_APSTA)
-extern int wl_cfg80211_interface_create(struct net_device *dev, char *name);
-extern int wl_cfg80211_interface_delete(struct net_device *dev, char *name);
-#endif /* defined (WL_VIRTUAL_APSTA) */
-
-#ifdef WL_NAN
-extern int wl_cfg80211_nan_cmd_handler(struct net_device *ndev, char *cmd,
-	int cmd_len);
-#endif /* WL_NAN */
-
-#ifdef WL_CFG80211_P2P_DEV_IF
-extern void wl_cfg80211_del_p2p_wdev(void);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-#if defined(WL_SUPPORT_AUTO_CHANNEL)
-extern int wl_cfg80211_set_spect(struct net_device *dev, int spect);
-extern int wl_cfg80211_get_sta_channel(void);
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
-
-#ifdef P2P_LISTEN_OFFLOADING
-extern s32 wl_cfg80211_p2plo_listen_start(struct net_device *dev, u8 *buf, int len);
-extern s32 wl_cfg80211_p2plo_listen_stop(struct net_device *dev);
-#endif /* P2P_LISTEN_OFFLOADING */
-
-#define RETURN_EIO_IF_NOT_UP(wlpriv)                        \
-do {                                    \
-	struct net_device *checkSysUpNDev = bcmcfg_to_prmry_ndev(wlpriv);           \
-	if (unlikely(!wl_get_drv_status(wlpriv, READY, checkSysUpNDev))) {  \
-		WL_INFORM(("device is not ready\n"));           \
-		return -EIO;                        \
-	}                               \
-} while (0)
-
-#ifdef QOS_MAP_SET
-extern uint8 *wl_get_up_table(void);
-#endif /* QOS_MAP_SET */
-
-#define P2PO_COOKIE     65535
-u64 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg);
-#if defined(SUPPORT_RANDOM_MAC_SCAN)
-int wl_cfg80211_set_random_mac(struct net_device *dev, bool enable);
-int wl_cfg80211_random_mac_enable(struct net_device *dev);
-int wl_cfg80211_random_mac_disable(struct net_device *dev);
-#endif /* SUPPORT_RANDOM_MAC_SCAN */
-int wl_cfg80211_iface_count(void);
-int wl_check_dongle_idle(struct wiphy *wiphy);
-#endif /* _wl_cfg80211_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg_btcoex.c b/drivers/net/wireless/bcmdhd/wl_cfg_btcoex.c
deleted file mode 100644
index 81e42ab..0000000
--- a/drivers/net/wireless/bcmdhd/wl_cfg_btcoex.c
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * Linux cfg80211 driver - Dongle Host Driver (DHD) related
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_cfg_btcoex.c 514727 2014-11-12 03:02:48Z $
- */
-
-#include <net/rtnetlink.h>
-
-#include <bcmutils.h>
-#include <wldev_common.h>
-#include <wl_cfg80211.h>
-#include <dhd_cfg80211.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhdioctl.h>
-#include <wlioctl.h>
-
-#ifdef PKT_FILTER_SUPPORT
-extern uint dhd_pkt_filter_enable;
-extern uint dhd_master_mode;
-extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
-#endif
-
-struct btcoex_info {
-	struct timer_list timer;
-	u32 timer_ms;
-	u32 timer_on;
-	u32 ts_dhcp_start;	/* ms ts ecord time stats */
-	u32 ts_dhcp_ok;		/* ms ts ecord time stats */
-	bool dhcp_done;	/* flag, indicates that host done with
-					 * dhcp before t1/t2 expiration
-					 */
-	s32 bt_state;
-	struct work_struct work;
-	struct net_device *dev;
-};
-
-static struct btcoex_info *btcoex_info_loc = NULL;
-
-/* TODO: clean up the BT-Coex code, it still have some legacy ioctl/iovar functions */
-
-/* use New SCO/eSCO smart YG suppression */
-#define BT_DHCP_eSCO_FIX
-/* this flag boost wifi pkt priority to max, caution: -not fair to sco */
-#define BT_DHCP_USE_FLAGS
-/* T1 start SCO/ESCo priority suppression */
-#define BT_DHCP_OPPR_WIN_TIME	2500
-/* T2 turn off SCO/SCO supperesion is (timeout) */
-#define BT_DHCP_FLAG_FORCE_TIME 5500
-
-enum wl_cfg80211_btcoex_status {
-	BT_DHCP_IDLE,
-	BT_DHCP_START,
-	BT_DHCP_OPPR_WIN,
-	BT_DHCP_FLAG_FORCE_TIMEOUT
-};
-
-/*
- * get named driver variable to uint register value and return error indication
- * calling example: dev_wlc_intvar_get_reg(dev, "btc_params",66, &reg_value)
- */
-static int
-dev_wlc_intvar_get_reg(struct net_device *dev, char *name,
-	uint reg, int *retval)
-{
-	union {
-		char buf[WLC_IOCTL_SMLEN];
-		int val;
-	} var;
-	int error;
-
-	bcm_mkiovar(name, (char *)(&reg), sizeof(reg),
-		(char *)(&var), sizeof(var.buf));
-	error = wldev_ioctl(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf), false);
-
-	*retval = dtoh32(var.val);
-	return (error);
-}
-
-static int
-dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
-	char ioctlbuf_local[1024];
-#else
-	static char ioctlbuf_local[1024];
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
-
-	bcm_mkiovar(name, buf, len, ioctlbuf_local, sizeof(ioctlbuf_local));
-
-	return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf_local, sizeof(ioctlbuf_local), true));
-}
-/*
-get named driver variable to uint register value and return error indication
-calling example: dev_wlc_intvar_set_reg(dev, "btc_params",66, value)
-*/
-static int
-dev_wlc_intvar_set_reg(struct net_device *dev, char *name, char *addr, char * val)
-{
-	char reg_addr[8];
-
-	memset(reg_addr, 0, sizeof(reg_addr));
-	memcpy((char *)&reg_addr[0], (char *)addr, 4);
-	memcpy((char *)&reg_addr[4], (char *)val, 4);
-
-	return (dev_wlc_bufvar_set(dev, name, (char *)&reg_addr[0], sizeof(reg_addr)));
-}
-
-static bool btcoex_is_sco_active(struct net_device *dev)
-{
-	int ioc_res = 0;
-	bool res = FALSE;
-	int sco_id_cnt = 0;
-	int param27;
-	int i;
-
-	for (i = 0; i < 12; i++) {
-
-		ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, &param27);
-
-		WL_TRACE(("sample[%d], btc params: 27:%x\n", i, param27));
-
-		if (ioc_res < 0) {
-			WL_ERR(("ioc read btc params error\n"));
-			break;
-		}
-
-		if ((param27 & 0x6) == 2) { /* count both sco & esco  */
-			sco_id_cnt++;
-		}
-
-		if (sco_id_cnt > 2) {
-			WL_TRACE(("sco/esco detected, pkt id_cnt:%d  samples:%d\n",
-				sco_id_cnt, i));
-			res = TRUE;
-			break;
-		}
-
-		OSL_SLEEP(5);
-	}
-
-	return res;
-}
-
-#if defined(BT_DHCP_eSCO_FIX)
-/* Enhanced BT COEX settings for eSCO compatibility during DHCP window */
-static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
-{
-	static bool saved_status = FALSE;
-
-	char buf_reg50va_dhcp_on[8] =
-		{ 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 };
-	char buf_reg51va_dhcp_on[8] =
-		{ 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
-	char buf_reg64va_dhcp_on[8] =
-		{ 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
-	char buf_reg65va_dhcp_on[8] =
-		{ 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
-	char buf_reg71va_dhcp_on[8] =
-		{ 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
-	uint32 regaddr;
-	static uint32 saved_reg50;
-	static uint32 saved_reg51;
-	static uint32 saved_reg64;
-	static uint32 saved_reg65;
-	static uint32 saved_reg71;
-
-	if (trump_sco) {
-		/* this should reduce eSCO agressive retransmit
-		 * w/o breaking it
-		 */
-
-		/* 1st save current */
-		WL_TRACE(("Do new SCO/eSCO coex algo {save &"
-			  "override}\n"));
-		if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) &&
-			(!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) &&
-			(!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) &&
-			(!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) &&
-			(!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) {
-			saved_status = TRUE;
-			WL_TRACE(("saved bt_params[50,51,64,65,71]:"
-				  "0x%x 0x%x 0x%x 0x%x 0x%x\n",
-				  saved_reg50, saved_reg51,
-				  saved_reg64, saved_reg65, saved_reg71));
-		} else {
-			WL_ERR((":%s: save btc_params failed\n",
-				__FUNCTION__));
-			saved_status = FALSE;
-			return -1;
-		}
-
-		WL_TRACE(("override with [50,51,64,65,71]:"
-			  "0x%x 0x%x 0x%x 0x%x 0x%x\n",
-			  *(u32 *)(buf_reg50va_dhcp_on+4),
-			  *(u32 *)(buf_reg51va_dhcp_on+4),
-			  *(u32 *)(buf_reg64va_dhcp_on+4),
-			  *(u32 *)(buf_reg65va_dhcp_on+4),
-			  *(u32 *)(buf_reg71va_dhcp_on+4)));
-
-		dev_wlc_bufvar_set(dev, "btc_params",
-			(char *)&buf_reg50va_dhcp_on[0], 8);
-		dev_wlc_bufvar_set(dev, "btc_params",
-			(char *)&buf_reg51va_dhcp_on[0], 8);
-		dev_wlc_bufvar_set(dev, "btc_params",
-			(char *)&buf_reg64va_dhcp_on[0], 8);
-		dev_wlc_bufvar_set(dev, "btc_params",
-			(char *)&buf_reg65va_dhcp_on[0], 8);
-		dev_wlc_bufvar_set(dev, "btc_params",
-			(char *)&buf_reg71va_dhcp_on[0], 8);
-
-		saved_status = TRUE;
-	} else if (saved_status) {
-		/* restore previously saved bt params */
-		WL_TRACE(("Do new SCO/eSCO coex algo {save &"
-			  "override}\n"));
-
-		regaddr = 50;
-		dev_wlc_intvar_set_reg(dev, "btc_params",
-			(char *)&regaddr, (char *)&saved_reg50);
-		regaddr = 51;
-		dev_wlc_intvar_set_reg(dev, "btc_params",
-			(char *)&regaddr, (char *)&saved_reg51);
-		regaddr = 64;
-		dev_wlc_intvar_set_reg(dev, "btc_params",
-			(char *)&regaddr, (char *)&saved_reg64);
-		regaddr = 65;
-		dev_wlc_intvar_set_reg(dev, "btc_params",
-			(char *)&regaddr, (char *)&saved_reg65);
-		regaddr = 71;
-		dev_wlc_intvar_set_reg(dev, "btc_params",
-			(char *)&regaddr, (char *)&saved_reg71);
-
-		WL_TRACE(("restore bt_params[50,51,64,65,71]:"
-			"0x%x 0x%x 0x%x 0x%x 0x%x\n",
-			saved_reg50, saved_reg51, saved_reg64,
-			saved_reg65, saved_reg71));
-
-		saved_status = FALSE;
-	} else {
-		WL_ERR((":%s att to restore not saved BTCOEX params\n",
-			__FUNCTION__));
-		return -1;
-	}
-	return 0;
-}
-#endif /* BT_DHCP_eSCO_FIX */
-
-static void
-wl_cfg80211_bt_setflag(struct net_device *dev, bool set)
-{
-#if defined(BT_DHCP_USE_FLAGS)
-	char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
-	char buf_flag7_default[8]   = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
-#endif
-
-
-#if defined(BT_DHCP_eSCO_FIX)
-	/* set = 1, save & turn on  0 - off & restore prev settings */
-	set_btc_esco_params(dev, set);
-#endif
-
-#if defined(BT_DHCP_USE_FLAGS)
-	WL_TRACE(("WI-FI priority boost via bt flags, set:%d\n", set));
-	if (set == TRUE)
-		/* Forcing bt_flag7  */
-		dev_wlc_bufvar_set(dev, "btc_flags",
-			(char *)&buf_flag7_dhcp_on[0],
-			sizeof(buf_flag7_dhcp_on));
-	else
-		/* Restoring default bt flag7 */
-		dev_wlc_bufvar_set(dev, "btc_flags",
-			(char *)&buf_flag7_default[0],
-			sizeof(buf_flag7_default));
-#endif
-}
-
-static void wl_cfg80211_bt_timerfunc(ulong data)
-{
-	struct btcoex_info *bt_local = (struct btcoex_info *)data;
-	WL_TRACE(("Enter\n"));
-	bt_local->timer_on = 0;
-	schedule_work(&bt_local->work);
-}
-
-static void wl_cfg80211_bt_handler(struct work_struct *work)
-{
-	struct btcoex_info *btcx_inf;
-
-	btcx_inf = container_of(work, struct btcoex_info, work);
-
-	if (btcx_inf->timer_on) {
-		btcx_inf->timer_on = 0;
-		del_timer_sync(&btcx_inf->timer);
-	}
-
-	switch (btcx_inf->bt_state) {
-		case BT_DHCP_START:
-			/* DHCP started
-			 * provide OPPORTUNITY window to get DHCP address
-			 */
-			WL_TRACE(("bt_dhcp stm: started \n"));
-
-			btcx_inf->bt_state = BT_DHCP_OPPR_WIN;
-			mod_timer(&btcx_inf->timer,
-				jiffies + msecs_to_jiffies(BT_DHCP_OPPR_WIN_TIME));
-			btcx_inf->timer_on = 1;
-			break;
-
-		case BT_DHCP_OPPR_WIN:
-			if (btcx_inf->dhcp_done) {
-				WL_TRACE(("DHCP Done before T1 expiration\n"));
-				goto btc_coex_idle;
-			}
-
-			/* DHCP is not over yet, start lowering BT priority
-			 * enforce btc_params + flags if necessary
-			 */
-			WL_TRACE(("DHCP T1:%d expired\n", BT_DHCP_OPPR_WIN_TIME));
-			if (btcx_inf->dev)
-				wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE);
-			btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
-			mod_timer(&btcx_inf->timer,
-				jiffies + msecs_to_jiffies(BT_DHCP_FLAG_FORCE_TIME));
-			btcx_inf->timer_on = 1;
-			break;
-
-		case BT_DHCP_FLAG_FORCE_TIMEOUT:
-			if (btcx_inf->dhcp_done) {
-				WL_TRACE(("DHCP Done before T2 expiration\n"));
-			} else {
-				/* Noo dhcp during T1+T2, restore BT priority */
-				WL_TRACE(("DHCP wait interval T2:%d msec expired\n",
-					BT_DHCP_FLAG_FORCE_TIME));
-			}
-
-			/* Restoring default bt priority */
-			if (btcx_inf->dev)
-				wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
-btc_coex_idle:
-			btcx_inf->bt_state = BT_DHCP_IDLE;
-			btcx_inf->timer_on = 0;
-			break;
-
-		default:
-			WL_ERR(("error g_status=%d !!!\n",	btcx_inf->bt_state));
-			if (btcx_inf->dev)
-				wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
-			btcx_inf->bt_state = BT_DHCP_IDLE;
-			btcx_inf->timer_on = 0;
-			break;
-	}
-
-	net_os_wake_unlock(btcx_inf->dev);
-}
-
-void* wl_cfg80211_btcoex_init(struct net_device *ndev)
-{
-	struct btcoex_info *btco_inf = NULL;
-
-	btco_inf = kmalloc(sizeof(struct btcoex_info), GFP_KERNEL);
-	if (!btco_inf)
-		return NULL;
-
-	btco_inf->bt_state = BT_DHCP_IDLE;
-	btco_inf->ts_dhcp_start = 0;
-	btco_inf->ts_dhcp_ok = 0;
-	/* Set up timer for BT  */
-	btco_inf->timer_ms = 10;
-	init_timer(&btco_inf->timer);
-	btco_inf->timer.data = (ulong)btco_inf;
-	btco_inf->timer.function = wl_cfg80211_bt_timerfunc;
-
-	btco_inf->dev = ndev;
-
-	INIT_WORK(&btco_inf->work, wl_cfg80211_bt_handler);
-
-	btcoex_info_loc = btco_inf;
-	return btco_inf;
-}
-
-void wl_cfg80211_btcoex_deinit()
-{
-	if (!btcoex_info_loc)
-		return;
-
-	if (btcoex_info_loc->timer_on) {
-		btcoex_info_loc->timer_on = 0;
-		del_timer_sync(&btcoex_info_loc->timer);
-	}
-
-	cancel_work_sync(&btcoex_info_loc->work);
-
-	kfree(btcoex_info_loc);
-}
-
-int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, dhd_pub_t *dhd, char *command)
-{
-
-	struct btcoex_info *btco_inf = btcoex_info_loc;
-	char powermode_val = 0;
-	char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 };
-	char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
-	char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
-
-	uint32 regaddr;
-	static uint32 saved_reg66;
-	static uint32 saved_reg41;
-	static uint32 saved_reg68;
-	static bool saved_status = FALSE;
-
-	char buf_flag7_default[8] =   { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
-
-	/* Figure out powermode 1 or o command */
-	strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1);
-
-	if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
-		WL_TRACE_HW4(("DHCP session starts\n"));
-
-
-#ifdef PKT_FILTER_SUPPORT
-		dhd->dhcp_in_progress = 1;
-
-		if (dhd->early_suspended) {
-			WL_TRACE_HW4(("DHCP in progressing , disable packet filter!!!\n"));
-			dhd_enable_packet_filter(0, dhd);
-		}
-#endif
-
-		/* Retrieve and saved orig regs value */
-		if ((saved_status == FALSE) &&
-			(!dev_wlc_intvar_get_reg(dev, "btc_params", 66,  &saved_reg66)) &&
-			(!dev_wlc_intvar_get_reg(dev, "btc_params", 41,  &saved_reg41)) &&
-			(!dev_wlc_intvar_get_reg(dev, "btc_params", 68,  &saved_reg68)))   {
-				saved_status = TRUE;
-				WL_TRACE(("Saved 0x%x 0x%x 0x%x\n",
-					saved_reg66, saved_reg41, saved_reg68));
-
-				/* Disable PM mode during dhpc session */
-
-				/* Disable PM mode during dhpc session */
-				/* Start  BT timer only for SCO connection */
-				if (btcoex_is_sco_active(dev)) {
-					/* btc_params 66 */
-					dev_wlc_bufvar_set(dev, "btc_params",
-						(char *)&buf_reg66va_dhcp_on[0],
-						sizeof(buf_reg66va_dhcp_on));
-					/* btc_params 41 0x33 */
-					dev_wlc_bufvar_set(dev, "btc_params",
-						(char *)&buf_reg41va_dhcp_on[0],
-						sizeof(buf_reg41va_dhcp_on));
-					/* btc_params 68 0x190 */
-					dev_wlc_bufvar_set(dev, "btc_params",
-						(char *)&buf_reg68va_dhcp_on[0],
-						sizeof(buf_reg68va_dhcp_on));
-					saved_status = TRUE;
-
-					btco_inf->bt_state = BT_DHCP_START;
-					btco_inf->timer_on = 1;
-					mod_timer(&btco_inf->timer, btco_inf->timer.expires);
-					WL_TRACE(("enable BT DHCP Timer\n"));
-				}
-		}
-		else if (saved_status == TRUE) {
-			WL_ERR(("was called w/o DHCP OFF. Continue\n"));
-		}
-	}
-	else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) {
-
-
-
-#ifdef PKT_FILTER_SUPPORT
-		dhd->dhcp_in_progress = 0;
-		WL_TRACE_HW4(("DHCP is complete \n"));
-
-		/* Enable packet filtering */
-		if (dhd->early_suspended) {
-			WL_TRACE_HW4(("DHCP is complete , enable packet filter!!!\n"));
-			dhd_enable_packet_filter(1, dhd);
-		}
-#endif /* PKT_FILTER_SUPPORT */
-
-		/* Restoring PM mode */
-
-		/* Stop any bt timer because DHCP session is done */
-		WL_TRACE(("disable BT DHCP Timer\n"));
-		if (btco_inf->timer_on) {
-			btco_inf->timer_on = 0;
-			del_timer_sync(&btco_inf->timer);
-
-			if (btco_inf->bt_state != BT_DHCP_IDLE) {
-			/* need to restore original btc flags & extra btc params */
-				WL_TRACE(("bt->bt_state:%d\n", btco_inf->bt_state));
-				/* wake up btcoex thread to restore btlags+params  */
-				schedule_work(&btco_inf->work);
-			}
-		}
-
-		/* Restoring btc_flag paramter anyway */
-		if (saved_status == TRUE)
-			dev_wlc_bufvar_set(dev, "btc_flags",
-				(char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
-
-		/* Restore original values */
-		if (saved_status == TRUE) {
-			regaddr = 66;
-			dev_wlc_intvar_set_reg(dev, "btc_params",
-				(char *)&regaddr, (char *)&saved_reg66);
-			regaddr = 41;
-			dev_wlc_intvar_set_reg(dev, "btc_params",
-				(char *)&regaddr, (char *)&saved_reg41);
-			regaddr = 68;
-			dev_wlc_intvar_set_reg(dev, "btc_params",
-				(char *)&regaddr, (char *)&saved_reg68);
-
-			WL_TRACE(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n",
-				saved_reg66, saved_reg41, saved_reg68));
-		}
-		saved_status = FALSE;
-
-	}
-	else {
-		WL_ERR(("Unkwown yet power setting, ignored\n"));
-	}
-
-	snprintf(command, 3, "OK");
-
-	return (strlen("OK"));
-}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
deleted file mode 100644
index 18e66f5..0000000
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ /dev/null
@@ -1,2578 +0,0 @@
-/*
- * Linux cfgp2p driver
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_cfgp2p.c 604795 2015-12-08 13:45:42Z $
- *
- */
-#include <typedefs.h>
-#include <linuxver.h>
-#include <osl.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/if_arp.h>
-#include <asm/uaccess.h>
-
-#include <bcmutils.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
-#include <proto/802.11.h>
-#include <net/rtnetlink.h>
-
-#include <wl_cfg80211.h>
-#include <wl_cfgp2p.h>
-#include <wldev_common.h>
-#include <wl_android.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_linux.h>
-#include <dhdioctl.h>
-#include <wlioctl.h>
-#include <dhd_cfg80211.h>
-
-static s8 scanparambuf[WLC_IOCTL_SMLEN];
-static bool
-wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
-
-static s32 wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	struct wireless_dev *wdev, bool notify);
-
-#if defined(WL_ENABLE_P2P_IF)
-static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
-static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
-static int wl_cfgp2p_if_open(struct net_device *net);
-static int wl_cfgp2p_if_stop(struct net_device *net);
-
-static const struct net_device_ops wl_cfgp2p_if_ops = {
-	.ndo_open       = wl_cfgp2p_if_open,
-	.ndo_stop       = wl_cfgp2p_if_stop,
-	.ndo_do_ioctl   = wl_cfgp2p_do_ioctl,
-	.ndo_start_xmit = wl_cfgp2p_start_xmit,
-};
-#endif /* WL_ENABLE_P2P_IF */
-
-
-bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len)
-{
-	wifi_p2p_pub_act_frame_t *pact_frm;
-
-	if (frame == NULL)
-		return false;
-	pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
-	if (frame_len < sizeof(wifi_p2p_pub_act_frame_t) -1)
-		return false;
-
-	if (pact_frm->category == P2P_PUB_AF_CATEGORY &&
-		pact_frm->action == P2P_PUB_AF_ACTION &&
-		pact_frm->oui_type == P2P_VER &&
-		memcmp(pact_frm->oui, P2P_OUI, sizeof(pact_frm->oui)) == 0) {
-		return true;
-	}
-
-	return false;
-}
-
-bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len)
-{
-	wifi_p2p_action_frame_t *act_frm;
-
-	if (frame == NULL)
-		return false;
-	act_frm = (wifi_p2p_action_frame_t *)frame;
-	if (frame_len < sizeof(wifi_p2p_action_frame_t) -1)
-		return false;
-
-	if (act_frm->category == P2P_AF_CATEGORY &&
-		act_frm->type  == P2P_VER &&
-		memcmp(act_frm->OUI, P2P_OUI, DOT11_OUI_LEN) == 0) {
-		return true;
-	}
-
-	return false;
-}
-
-#define GAS_RESP_LEN		2
-#define DOUBLE_TLV_BODY_OFF	4
-#define GAS_RESP_OFFSET		4
-#define GAS_CRESP_OFFSET	5
-
-bool wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len)
-{
-	bcm_tlv_t *ie = (bcm_tlv_t *)data;
-	u8 *frame = NULL;
-	u16 id, flen;
-
-	/* Skipped first ANQP Element, if frame has anqp elemnt */
-	ie = bcm_parse_tlvs(ie, (int)len, DOT11_MNG_ADVERTISEMENT_ID);
-
-	if (ie == NULL)
-		return false;
-
-	frame = (uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
-	id = ((u16) (((frame)[1] << 8) | (frame)[0]));
-	flen = ((u16) (((frame)[3] << 8) | (frame)[2]));
-
-	/* If the contents match the OUI and the type */
-	if (flen >= WFA_OUI_LEN + 1 &&
-		id ==  P2PSD_GAS_NQP_INFOID &&
-		!bcmp(&frame[DOUBLE_TLV_BODY_OFF], (const uint8*)WFA_OUI, WFA_OUI_LEN) &&
-		subtype == frame[DOUBLE_TLV_BODY_OFF+WFA_OUI_LEN]) {
-		return true;
-	}
-
-	return false;
-}
-
-bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len)
-{
-
-	wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
-
-	if (frame == NULL)
-		return false;
-
-	sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
-	if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1))
-		return false;
-	if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
-		return false;
-
-#ifdef WL11U
-	if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP)
-		return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE,
-			(u8 *)sd_act_frm->query_data + GAS_RESP_OFFSET,
-			frame_len);
-
-	else if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP)
-		return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE,
-			(u8 *)sd_act_frm->query_data + GAS_CRESP_OFFSET,
-			frame_len);
-	else if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ ||
-		sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ)
-		return true;
-	else
-		return false;
-#else
-	if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ ||
-		sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP ||
-		sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ ||
-		sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP)
-		return true;
-	else
-		return false;
-#endif /* WL11U */
-}
-
-bool wl_cfgp2p_is_p2p_gas_action(void *frame, u32 frame_len)
-{
-
-	wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
-
-	if (frame == NULL)
-		return false;
-
-	sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
-	if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1))
-		return false;
-	if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
-		return false;
-
-	if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ)
-		return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE,
-			(u8 *)sd_act_frm->query_data,
-			frame_len);
-	else
-		return false;
-}
-
-void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel)
-{
-	wifi_p2p_pub_act_frame_t *pact_frm;
-	wifi_p2p_action_frame_t *act_frm;
-	wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
-	if (!frame || frame_len <= 2)
-		return;
-
-	if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
-		pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
-		switch (pact_frm->subtype) {
-			case P2P_PAF_GON_REQ:
-				CFGP2P_ACTION(("%s P2P Group Owner Negotiation Req Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_PAF_GON_RSP:
-				CFGP2P_ACTION(("%s P2P Group Owner Negotiation Rsp Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_PAF_GON_CONF:
-				CFGP2P_ACTION(("%s P2P Group Owner Negotiation Confirm Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_PAF_INVITE_REQ:
-				CFGP2P_ACTION(("%s P2P Invitation Request  Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_PAF_INVITE_RSP:
-				CFGP2P_ACTION(("%s P2P Invitation Response Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_PAF_DEVDIS_REQ:
-				CFGP2P_ACTION(("%s P2P Device Discoverability Request Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_PAF_DEVDIS_RSP:
-				CFGP2P_ACTION(("%s P2P Device Discoverability Response Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_PAF_PROVDIS_REQ:
-				CFGP2P_ACTION(("%s P2P Provision Discovery Request Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_PAF_PROVDIS_RSP:
-				CFGP2P_ACTION(("%s P2P Provision Discovery Response Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			default:
-				CFGP2P_ACTION(("%s Unknown Public Action Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-
-		}
-
-	} else if (wl_cfgp2p_is_p2p_action(frame, frame_len)) {
-		act_frm = (wifi_p2p_action_frame_t *)frame;
-		switch (act_frm->subtype) {
-			case P2P_AF_NOTICE_OF_ABSENCE:
-				CFGP2P_ACTION(("%s P2P Notice of Absence Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_AF_PRESENCE_REQ:
-				CFGP2P_ACTION(("%s P2P Presence Request Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_AF_PRESENCE_RSP:
-				CFGP2P_ACTION(("%s P2P Presence Response Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			case P2P_AF_GO_DISC_REQ:
-				CFGP2P_ACTION(("%s P2P Discoverability Request Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-				break;
-			default:
-				CFGP2P_ACTION(("%s Unknown P2P Action Frame,"
-					" channel=%d\n", (tx)? "TX": "RX", channel));
-		}
-
-	} else if (wl_cfgp2p_is_gas_action(frame, frame_len)) {
-		sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
-		switch (sd_act_frm->action) {
-			case P2PSD_ACTION_ID_GAS_IREQ:
-				CFGP2P_ACTION(("%s GAS Initial Request,"
-					" channel=%d\n", (tx)? "TX" : "RX", channel));
-				break;
-			case P2PSD_ACTION_ID_GAS_IRESP:
-				CFGP2P_ACTION(("%s GAS Initial Response,"
-					" channel=%d\n", (tx)? "TX" : "RX", channel));
-				break;
-			case P2PSD_ACTION_ID_GAS_CREQ:
-				CFGP2P_ACTION(("%s GAS Comback Request,"
-					" channel=%d\n", (tx)? "TX" : "RX", channel));
-				break;
-			case P2PSD_ACTION_ID_GAS_CRESP:
-				CFGP2P_ACTION(("%s GAS Comback Response,"
-					" channel=%d\n", (tx)? "TX" : "RX", channel));
-				break;
-			default:
-				CFGP2P_ACTION(("%s Unknown GAS Frame,"
-					" channel=%d\n", (tx)? "TX" : "RX", channel));
-		}
-
-
-	}
-}
-
-/*
- *  Initialize variables related to P2P
- *
- */
-s32
-wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg)
-{
-	if (!(cfg->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) {
-		CFGP2P_ERR(("struct p2p_info allocation failed\n"));
-		return -ENOMEM;
-	}
-
-	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY) = bcmcfg_to_prmry_ndev(cfg);
-	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY) = 0;
-	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
-	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
-	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1) = NULL;
-	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) = -1;
-	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2) = NULL;
-	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2) = -1;
-	return BCME_OK;
-
-}
-/*
- *  Deinitialize variables related to P2P
- *
- */
-void
-wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg)
-{
-	CFGP2P_ERR(("In\n"));
-	if (cfg->p2p) {
-		kfree(cfg->p2p);
-		cfg->p2p = NULL;
-	}
-	cfg->p2p_supported = 0;
-}
-/*
- * Set P2P functions into firmware
- */
-s32
-wl_cfgp2p_set_firm_p2p(struct bcm_cfg80211 *cfg)
-{
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-	struct ether_addr null_eth_addr = { { 0, 0, 0, 0, 0, 0 } };
-	s32 ret = BCME_OK;
-	s32 val = 0;
-	/* Do we have to check whether APSTA is enabled or not ? */
-	ret = wldev_iovar_getint(ndev, "apsta", &val);
-	if (ret < 0) {
-		CFGP2P_ERR(("get apsta error %d\n", ret));
-		return ret;
-	}
-	if (val == 0) {
-		val = 1;
-		ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true);
-		if (ret < 0) {
-			CFGP2P_ERR(("WLC_DOWN error %d\n", ret));
-			return ret;
-		}
-
-		ret = wldev_iovar_setint(ndev, "apsta", val);
-		if (ret < 0) {
-			/* return error and fail the initialization */
-			CFGP2P_ERR(("wl apsta %d set error. ret: %d\n", val, ret));
-			return ret;
-		}
-
-		ret = wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true);
-		if (ret < 0) {
-			CFGP2P_ERR(("WLC_UP error %d\n", ret));
-			return ret;
-		}
-	}
-
-	/* In case of COB type, firmware has default mac address
-	 * After Initializing firmware, we have to set current mac address to
-	 * firmware for P2P device address
-	 */
-	ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr,
-		sizeof(null_eth_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &cfg->ioctl_buf_sync);
-	if (ret && ret != BCME_UNSUPPORTED) {
-		CFGP2P_ERR(("failed to update device address ret %d\n", ret));
-	}
-	return ret;
-}
-
-int wl_cfg_multip2p_operational(struct bcm_cfg80211 *cfg)
-{
-	if (!cfg->p2p) {
-		CFGP2P_DBG(("p2p not enabled! \n"));
-		return false;
-	}
-
-	if ((wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) != -1) &&
-	    (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2) != -1))
-		return true;
-	else
-		return false;
-}
-
-/* Create a new P2P BSS.
- * Parameters:
- * @mac      : MAC address of the BSS to create
- * @if_type  : interface type: WL_P2P_IF_GO or WL_P2P_IF_CLIENT
- * @chspec   : chspec to use if creating a GO BSS.
- * Returns 0 if success.
- */
-s32
-wl_cfgp2p_ifadd(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
-            chanspec_t chspec)
-{
-	wl_p2p_if_t ifreq;
-	s32 err;
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-
-	ifreq.type = if_type;
-	ifreq.chspec = chspec;
-	memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
-
-	CFGP2P_DBG(("---cfg p2p_ifadd "MACDBG" %s %u\n",
-		MAC2STRDBG(ifreq.addr.octet),
-		(if_type == WL_P2P_IF_GO) ? "go" : "client",
-	        (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
-
-	err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-	if (unlikely(err < 0)) {
-		printk("'cfg p2p_ifadd' error %d\n", err);
-		return err;
-	}
-
-	return err;
-}
-
-/* Disable a P2P BSS.
- * Parameters:
- * @mac      : MAC address of the BSS to disable
- * Returns 0 if success.
- */
-s32
-wl_cfgp2p_ifdisable(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
-{
-	s32 ret;
-	struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
-
-	CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdis "MACDBG"\n",
-		netdev->ifindex, MAC2STRDBG(mac->octet)));
-	ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-	if (unlikely(ret < 0)) {
-		printk("'cfg p2p_ifdis' error %d\n", ret);
-	}
-	return ret;
-}
-
-/* Delete a P2P BSS.
- * Parameters:
- * @mac      : MAC address of the BSS to delete
- * Returns 0 if success.
- */
-s32
-wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
-{
-	s32 ret;
-	struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
-
-	CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdel "MACDBG"\n",
-	    netdev->ifindex, MAC2STRDBG(mac->octet)));
-	ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-	if (unlikely(ret < 0)) {
-		printk("'cfg p2p_ifdel' error %d\n", ret);
-	}
-	return ret;
-}
-
-/* Change a P2P Role.
- * Parameters:
- * @mac      : MAC address of the BSS to change a role
- * Returns 0 if success.
- */
-s32
-wl_cfgp2p_ifchange(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
-            chanspec_t chspec, s32 conn_idx)
-{
-	wl_p2p_if_t ifreq;
-	s32 err;
-
-	struct net_device *netdev =  wl_to_p2p_bss_ndev(cfg, conn_idx);
-
-	ifreq.type = if_type;
-	ifreq.chspec = chspec;
-	memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
-
-	CFGP2P_INFO(("---cfg p2p_ifchange "MACDBG" %s %u"
-		" chanspec 0x%04x\n", MAC2STRDBG(ifreq.addr.octet),
-		(if_type == WL_P2P_IF_GO) ? "go" : "client",
-		(chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT,
-		ifreq.chspec));
-
-	err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-	if (unlikely(err < 0)) {
-		printk("'cfg p2p_ifupd' error %d\n", err);
-	} else if (if_type == WL_P2P_IF_GO) {
-		cfg->p2p->p2p_go_count++;
-	}
-	return err;
-}
-
-
-/* Get the index of a created P2P BSS.
- * Parameters:
- * @mac      : MAC address of the created BSS
- * @index    : output: index of created BSS
- * Returns 0 if success.
- */
-s32
-wl_cfgp2p_ifidx(struct bcm_cfg80211 *cfg, struct ether_addr *mac, s32 *index)
-{
-	s32 ret;
-	u8 getbuf[64];
-	struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
-
-	CFGP2P_INFO(("---cfg p2p_if "MACDBG"\n", MAC2STRDBG(mac->octet)));
-
-	ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), getbuf,
-		sizeof(getbuf), wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY), NULL);
-
-	if (ret == 0) {
-		memcpy(index, getbuf, sizeof(s32));
-		CFGP2P_INFO(("---cfg p2p_if   ==> %d\n", *index));
-	}
-
-	return ret;
-}
-
-static s32
-wl_cfgp2p_set_discovery(struct bcm_cfg80211 *cfg, s32 on)
-{
-	s32 ret = BCME_OK;
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-	CFGP2P_DBG(("enter\n"));
-
-	ret = wldev_iovar_setint(ndev, "p2p_disc", on);
-
-	if (unlikely(ret < 0)) {
-		CFGP2P_ERR(("p2p_disc %d error %d\n", on, ret));
-	}
-
-	return ret;
-}
-
-/* Set the WL driver's P2P mode.
- * Parameters :
- * @mode      : is one of WL_P2P_DISC_ST_{SCAN,LISTEN,SEARCH}.
- * @channel   : the channel to listen
- * @listen_ms : the time (milli seconds) to wait
- * @bssidx    : bss index for BSSCFG
- * Returns 0 if success
- */
-
-s32
-wl_cfgp2p_set_p2p_mode(struct bcm_cfg80211 *cfg, u8 mode, u32 channel, u16 listen_ms, int bssidx)
-{
-	wl_p2p_disc_st_t discovery_mode;
-	s32 ret;
-	struct net_device *dev;
-	CFGP2P_DBG(("enter\n"));
-
-	if (unlikely(bssidx == WL_INVALID)) {
-		CFGP2P_ERR((" %d index out of range\n", bssidx));
-		return -1;
-	}
-
-	dev = wl_cfgp2p_find_ndev(cfg, bssidx);
-	if (unlikely(dev == NULL)) {
-		CFGP2P_ERR(("bssidx %d is not assigned\n", bssidx));
-		return BCME_NOTFOUND;
-	}
-
-#ifdef P2PLISTEN_AP_SAMECHN
-	CFGP2P_DBG(("p2p0 listen channel %d  AP connection chan %d \n",
-		channel, cfg->channel));
-	if ((mode == WL_P2P_DISC_ST_LISTEN) && (cfg->channel == channel)) {
-		struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
-
-		if (cfg->p2p_resp_apchn_status) {
-			CFGP2P_DBG(("p2p_resp_apchn_status already ON \n"));
-			return BCME_OK;
-		}
-
-		if (wl_get_drv_status(cfg, CONNECTED, primary_ndev)) {
-			ret = wl_cfg80211_set_p2p_resp_ap_chn(primary_ndev, 1);
-			cfg->p2p_resp_apchn_status = true;
-			CFGP2P_DBG(("p2p_resp_apchn_status ON \n"));
-			return ret;
-		}
-	}
-#endif /* P2PLISTEN_AP_SAMECHN */
-
-	/* Put the WL driver into P2P Listen Mode to respond to P2P probe reqs */
-	discovery_mode.state = mode;
-	discovery_mode.chspec = wl_ch_host_to_driver(bssidx, channel);
-	discovery_mode.dwell = listen_ms;
-	ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode,
-		sizeof(discovery_mode), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
-		bssidx, &cfg->ioctl_buf_sync);
-
-	return ret;
-}
-
-/* Get the index of the P2P Discovery BSS */
-static s32
-wl_cfgp2p_get_disc_idx(struct bcm_cfg80211 *cfg, s32 *index)
-{
-	s32 ret;
-	struct net_device *dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
-
-	ret = wldev_iovar_getint(dev, "p2p_dev", index);
-	CFGP2P_INFO(("p2p_dev bsscfg_idx=%d ret=%d\n", *index, ret));
-
-	if (unlikely(ret <  0)) {
-	    CFGP2P_ERR(("'p2p_dev' error %d\n", ret));
-		return ret;
-	}
-	return ret;
-}
-
-int wl_cfgp2p_get_conn_idx(struct bcm_cfg80211 *cfg)
-{
-	int i;
-	s32 connected_cnt;
-	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
-	if (!dhd)
-		return (-ENODEV);
-	for (i = P2PAPI_BSSCFG_CONNECTION1; i < P2PAPI_BSSCFG_MAX; i++) {
-		if (wl_to_p2p_bss_bssidx(cfg, i) == -1) {
-			if (i == P2PAPI_BSSCFG_CONNECTION2) {
-				if (!(dhd->op_mode & DHD_FLAG_MP2P_MODE)) {
-					CFGP2P_ERR(("Multi p2p not supported"));
-					return BCME_ERROR;
-				}
-				if ((connected_cnt = wl_get_drv_status_all(cfg, CONNECTED)) > 1) {
-					CFGP2P_ERR(("Failed to create second p2p interface"
-						"Already one connection exists"));
-					return BCME_ERROR;
-				}
-			}
-		return i;
-		}
-	}
-	return BCME_ERROR;
-}
-
-s32
-wl_cfgp2p_init_discovery(struct bcm_cfg80211 *cfg)
-{
-
-	s32 bssidx = 0;
-	s32 ret = BCME_OK;
-
-	CFGP2P_DBG(("enter\n"));
-
-	if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) > 0) {
-		CFGP2P_ERR(("do nothing, already initialized\n"));
-		return ret;
-	}
-
-	ret = wl_cfgp2p_set_discovery(cfg, 1);
-	if (ret < 0) {
-		CFGP2P_ERR(("set discover error\n"));
-		return ret;
-	}
-	/* Enable P2P Discovery in the WL Driver */
-	ret = wl_cfgp2p_get_disc_idx(cfg, &bssidx);
-
-	if (ret < 0) {
-		return ret;
-	}
-	/* In case of CFG80211 case, check if p2p_discovery interface has allocated p2p_wdev */
-	if (!cfg->p2p_wdev) {
-		CFGP2P_ERR(("p2p_wdev is NULL.\n"));
-		return BCME_NODEVICE;
-	}
-	/* Make an entry in the netinfo */
-	wl_alloc_netinfo(cfg, NULL, cfg->p2p_wdev, WL_MODE_BSS, 0, bssidx);
-
-	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) =
-	    wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
-	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = bssidx;
-
-	/* Set the initial discovery state to SCAN */
-	ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
-		wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
-
-	if (unlikely(ret != 0)) {
-		CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
-		wl_cfgp2p_set_discovery(cfg, 0);
-		wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
-		wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
-		return 0;
-	}
-	return ret;
-}
-
-/* Deinitialize P2P Discovery
- * Parameters :
- * @cfg        : wl_private data
- * Returns 0 if succes
- */
-static s32
-wl_cfgp2p_deinit_discovery(struct bcm_cfg80211 *cfg)
-{
-	s32 ret = BCME_OK;
-	s32 bssidx;
-
-	CFGP2P_DBG(("enter\n"));
-	bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-	if (bssidx <= 0) {
-		CFGP2P_ERR(("do nothing, not initialized\n"));
-		return -1;
-	}
-
-	/* Clear our saved WPS and P2P IEs for the discovery BSS */
-	wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
-
-	/* Set the discovery state to SCAN */
-	wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
-	            bssidx);
-	/* Disable P2P discovery in the WL driver (deletes the discovery BSSCFG) */
-	ret = wl_cfgp2p_set_discovery(cfg, 0);
-
-	/* Remove the p2p disc entry in the netinfo */
-#ifdef DHD_IFDEBUG
-	WL_ERR(("dealloc_net_info by wdev=%p\n", cfg->p2p_wdev));
-#endif
-	wl_dealloc_netinfo_by_wdev(cfg, cfg->p2p_wdev);
-
-	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = WL_INVALID;
-	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
-
-	return ret;
-
-}
-/* Enable P2P Discovery
- * Parameters:
- * @cfg	: wl_private data
- * @ie  : probe request ie (WPS IE + P2P IE)
- * @ie_len   : probe request ie length
- * Returns 0 if success.
- */
-s32
-wl_cfgp2p_enable_discovery(struct bcm_cfg80211 *cfg, struct net_device *dev,
-	const u8 *ie, u32 ie_len)
-{
-	s32 ret = BCME_OK;
-	s32 bssidx;
-
-	CFGP2P_DBG(("enter\n"));
-	if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
-		CFGP2P_INFO((" DISCOVERY is already initialized, we have nothing to do\n"));
-		goto set_ie;
-	}
-
-	ret = wl_cfgp2p_init_discovery(cfg);
-	if (unlikely(ret < 0)) {
-		CFGP2P_ERR((" init discovery error %d\n", ret));
-		goto exit;
-	}
-
-	wl_set_p2p_status(cfg, DISCOVERY_ON);
-	/* Set wsec to any non-zero value in the discovery bsscfg to ensure our
-	 * P2P probe responses have the privacy bit set in the 802.11 WPA IE.
-	 * Some peer devices may not initiate WPS with us if this bit is not set.
-	 */
-	ret = wldev_iovar_setint_bsscfg(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE),
-			"wsec", AES_ENABLED, wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
-	if (unlikely(ret < 0)) {
-		CFGP2P_ERR((" wsec error %d\n", ret));
-	}
-set_ie:
-	if (ie_len) {
-
-		if (bcmcfg_to_prmry_ndev(cfg) == dev) {
-			bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-		} else if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfg->p2p_wdev)) < 0) {
-			WL_ERR(("Find p2p index from wdev(%p) failed\n", cfg->p2p_wdev));
-			return BCME_ERROR;
-		}
-
-		ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev),
-			bssidx,
-			VNDR_IE_PRBREQ_FLAG, ie, ie_len);
-
-		if (unlikely(ret < 0)) {
-			CFGP2P_ERR(("set probreq ie occurs error %d\n", ret));
-			goto exit;
-		}
-	}
-exit:
-	return ret;
-}
-
-/* Disable P2P Discovery
- * Parameters:
- * @cfg       : wl_private_data
- * Returns 0 if success.
- */
-s32
-wl_cfgp2p_disable_discovery(struct bcm_cfg80211 *cfg)
-{
-	s32 ret = BCME_OK;
-	s32 bssidx;
-
-	CFGP2P_DBG((" enter\n"));
-	wl_clr_p2p_status(cfg, DISCOVERY_ON);
-
-#ifdef DHD_IFDEBUG
-	WL_ERR(("%s: (cfg)->p2p->bss[type].bssidx: %d\n",
-		__FUNCTION__, (cfg)->p2p->bss[P2PAPI_BSSCFG_DEVICE].bssidx));
-#endif
-	bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-	if (bssidx <= 0) {
-		CFGP2P_ERR((" do nothing, not initialized\n"));
-		return 0;
-	}
-
-	ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
-	            bssidx);
-	if (unlikely(ret < 0)) {
-		CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
-	}
-	/* Do a scan abort to stop the driver's scan engine in case it is still
-	 * waiting out an action frame tx dwell time.
-	 */
-	wl_clr_p2p_status(cfg, DISCOVERY_ON);
-	ret = wl_cfgp2p_deinit_discovery(cfg);
-
-	return ret;
-}
-
-s32
-wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active,
-	u32 num_chans, u16 *channels,
-	s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr,
-	p2p_scan_purpose_t p2p_scan_purpose)
-{
-	s32 ret = BCME_OK;
-	s32 memsize;
-	s32 eparams_size;
-	u32 i;
-	s8 *memblk;
-	wl_p2p_scan_t *p2p_params;
-	wl_escan_params_t *eparams;
-	wlc_ssid_t ssid;
-	/* Scan parameters */
-#define P2PAPI_SCAN_NPROBES 1
-#define P2PAPI_SCAN_DWELL_TIME_MS 80
-#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
-#define P2PAPI_SCAN_HOME_TIME_MS 60
-#define P2PAPI_SCAN_NPROBS_TIME_MS 30
-#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
-
-	struct net_device *pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
-	/* Allocate scan params which need space for 3 channels and 0 ssids */
-	eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
-	    OFFSETOF(wl_escan_params_t, params)) +
-		num_chans * sizeof(eparams->params.channel_list[0]);
-
-	memsize = sizeof(wl_p2p_scan_t) + eparams_size;
-	memblk = scanparambuf;
-	if (memsize > sizeof(scanparambuf)) {
-		CFGP2P_ERR((" scanpar buf too small (%u > %zu)\n",
-		    memsize, sizeof(scanparambuf)));
-		return -1;
-	}
-	memset(memblk, 0, memsize);
-	memset(cfg->ioctl_buf, 0, WLC_IOCTL_MAXLEN);
-	if (search_state == WL_P2P_DISC_ST_SEARCH) {
-		/*
-		 * If we in SEARCH STATE, we don't need to set SSID explictly
-		 * because dongle use P2P WILDCARD internally by default
-		 */
-		wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx);
-		/* use null ssid */
-		ssid.SSID_len = 0;
-		memset(&ssid.SSID, 0, sizeof(ssid.SSID));
-	} else if (search_state == WL_P2P_DISC_ST_SCAN) {
-		/* SCAN STATE 802.11 SCAN
-		 * WFD Supplicant has p2p_find command with (type=progressive, type= full)
-		 * So if P2P_find command with type=progressive,
-		 * we have to set ssid to P2P WILDCARD because
-		 * we just do broadcast scan unless setting SSID
-		 */
-		wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
-		/* use wild card ssid */
-		ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN;
-		memset(&ssid.SSID, 0, sizeof(ssid.SSID));
-		memcpy(&ssid.SSID, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN);
-	} else {
-		CFGP2P_ERR((" invalid search state %d\n", search_state));
-		return -1;
-	}
-
-
-	/* Fill in the P2P scan structure at the start of the iovar param block */
-	p2p_params = (wl_p2p_scan_t*) memblk;
-	p2p_params->type = 'E';
-	/* Fill in the Scan structure that follows the P2P scan structure */
-	eparams = (wl_escan_params_t*) (p2p_params + 1);
-	eparams->params.bss_type = DOT11_BSSTYPE_ANY;
-	if (active)
-		eparams->params.scan_type = DOT11_SCANTYPE_ACTIVE;
-	else
-		eparams->params.scan_type = DOT11_SCANTYPE_PASSIVE;
-
-	if (tx_dst_addr == NULL)
-		memcpy(&eparams->params.bssid, &ether_bcast, ETHER_ADDR_LEN);
-	else
-		memcpy(&eparams->params.bssid, tx_dst_addr, ETHER_ADDR_LEN);
-
-	if (ssid.SSID_len)
-		memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t));
-
-	eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
-
-	switch (p2p_scan_purpose) {
-		case P2P_SCAN_SOCIAL_CHANNEL:
-		eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS);
-			break;
-		case P2P_SCAN_AFX_PEER_NORMAL:
-		case P2P_SCAN_AFX_PEER_REDUCED:
-		eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS);
-			break;
-		case P2P_SCAN_CONNECT_TRY:
-			eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
-			break;
-		default :
-			if (wl_get_drv_status_all(cfg, CONNECTED))
-		eparams->params.active_time = -1;
-	else
-		eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS);
-			break;
-	}
-
-	if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY)
-		eparams->params.nprobes = htod32(eparams->params.active_time /
-			WL_SCAN_JOIN_PROBE_INTERVAL_MS);
-	else
-	eparams->params.nprobes = htod32((eparams->params.active_time /
-		P2PAPI_SCAN_NPROBS_TIME_MS));
-
-
-	if (eparams->params.nprobes <= 0)
-		eparams->params.nprobes = 1;
-	CFGP2P_DBG(("nprobes # %d, active_time %d\n",
-		eparams->params.nprobes, eparams->params.active_time));
-	eparams->params.passive_time = htod32(-1);
-	eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
-	    (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
-
-	for (i = 0; i < num_chans; i++) {
-		eparams->params.channel_list[i] = wl_ch_host_to_driver(bssidx, channels[i]);
-	}
-	eparams->version = htod32(ESCAN_REQ_VERSION);
-	eparams->action =  htod16(action);
-	wl_escan_set_sync_id(eparams->sync_id, cfg);
-	wl_escan_set_type(cfg, WL_SCANTYPE_P2P);
-	CFGP2P_INFO(("SCAN CHANNELS : "));
-
-	for (i = 0; i < num_chans; i++) {
-		if (i == 0) CFGP2P_INFO(("%d", channels[i]));
-		else CFGP2P_INFO((",%d", channels[i]));
-	}
-
-	CFGP2P_INFO(("\n"));
-
-	ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan",
-		memblk, memsize, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-	WL_SCAN(("P2P_SEARCH sync ID: %d, bssidx: %d\n", eparams->sync_id, bssidx));
-	if (ret == BCME_OK)
-		wl_set_p2p_status(cfg, SCANNING);
-	return ret;
-}
-
-/* search function to reach at common channel to send action frame
- * Parameters:
- * @cfg       : wl_private data
- * @ndev     : net device for bssidx
- * @bssidx   : bssidx for BSS
- * Returns 0 if success.
- */
-s32
-wl_cfgp2p_act_frm_search(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr)
-{
-	s32 ret = 0;
-	u32 chan_cnt = 0;
-	u16 *default_chan_list = NULL;
-	p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_AFX_PEER_NORMAL;
-	if (!p2p_is_on(cfg) || ndev == NULL || bssidx == WL_INVALID)
-		return -EINVAL;
-	WL_TRACE_HW4((" Enter\n"));
-	if (bssidx == wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY))
-		bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-	if (channel)
-		chan_cnt = AF_PEER_SEARCH_CNT;
-	else
-		chan_cnt = SOCIAL_CHAN_CNT;
-
-	if (cfg->afx_hdl->pending_tx_act_frm && cfg->afx_hdl->is_active) {
-		wl_action_frame_t *action_frame;
-		action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
-		if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len))	{
-			chan_cnt = 1;
-			p2p_scan_purpose = P2P_SCAN_AFX_PEER_REDUCED;
-		}
-	}
-
-	default_chan_list = kzalloc(chan_cnt * sizeof(*default_chan_list), GFP_KERNEL);
-	if (default_chan_list == NULL) {
-		CFGP2P_ERR(("channel list allocation failed \n"));
-		ret = -ENOMEM;
-		goto exit;
-	}
-	if (channel) {
-		u32 i;
-		/* insert same channel to the chan_list */
-		for (i = 0; i < chan_cnt; i++) {
-			default_chan_list[i] = channel;
-		}
-	} else {
-		default_chan_list[0] = SOCIAL_CHAN_1;
-		default_chan_list[1] = SOCIAL_CHAN_2;
-		default_chan_list[2] = SOCIAL_CHAN_3;
-	}
-	ret = wl_cfgp2p_escan(cfg, ndev, true, chan_cnt,
-		default_chan_list, WL_P2P_DISC_ST_SEARCH,
-		WL_SCAN_ACTION_START, bssidx, NULL, p2p_scan_purpose);
-	kfree(default_chan_list);
-exit:
-	return ret;
-}
-
-/* Check whether pointed-to IE looks like WPA. */
-#define wl_cfgp2p_is_wpa_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
-		(const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE)
-/* Check whether pointed-to IE looks like WPS. */
-#define wl_cfgp2p_is_wps_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
-		(const uint8 *)WPS_OUI, WPS_OUI_LEN, WPS_OUI_TYPE)
-/* Check whether the given IE looks like WFA P2P IE. */
-#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
-		(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
-/* Check whether the given IE looks like WFA WFDisplay IE. */
-#ifndef WFA_OUI_TYPE_WFD
-#define WFA_OUI_TYPE_WFD	0x0a			/* WiFi Display OUI TYPE */
-#endif
-#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
-		(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
-
-
-/* Is any of the tlvs the expected entry? If
- * not update the tlvs buffer pointer/length.
- */
-static bool
-wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type)
-{
-	/* If the contents match the OUI and the type */
-	if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
-		!bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
-		type == ie[TLV_BODY_OFF + oui_len]) {
-		return TRUE;
-	}
-
-	if (tlvs == NULL)
-		return FALSE;
-	/* point to the next ie */
-	ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
-	/* calculate the length of the rest of the buffer */
-	*tlvs_len -= (int)(ie - *tlvs);
-	/* update the pointer to the start of the buffer */
-	*tlvs = ie;
-
-	return FALSE;
-}
-
-wpa_ie_fixed_t *
-wl_cfgp2p_find_wpaie(u8 *parse, u32 len)
-{
-	bcm_tlv_t *ie;
-
-	while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_wpa_ie((u8*)ie, &parse, &len)) {
-			return (wpa_ie_fixed_t *)ie;
-		}
-	}
-	return NULL;
-}
-
-wpa_ie_fixed_t *
-wl_cfgp2p_find_wpsie(u8 *parse, u32 len)
-{
-	bcm_tlv_t *ie;
-
-	while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_wps_ie((u8*)ie, &parse, &len)) {
-			return (wpa_ie_fixed_t *)ie;
-		}
-	}
-	return NULL;
-}
-
-wifi_p2p_ie_t *
-wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
-{
-	bcm_tlv_t *ie;
-
-	while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len)) {
-			return (wifi_p2p_ie_t *)ie;
-		}
-	}
-	return NULL;
-}
-
-wifi_wfd_ie_t *
-wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
-{
-	bcm_tlv_t *ie;
-
-	while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
-			return (wifi_wfd_ie_t *)ie;
-		}
-	}
-	return NULL;
-}
-u32
-wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
-            s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd)
-{
-	vndr_ie_setbuf_t hdr;	/* aligned temporary vndr_ie buffer header */
-	s32 iecount;
-	u32 data_offset;
-
-	/* Validate the pktflag parameter */
-	if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
-	            VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
-	            VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG))) {
-		CFGP2P_ERR(("p2pwl_vndr_ie: Invalid packet flag 0x%x\n", pktflag));
-		return -1;
-	}
-
-	/* Copy the vndr_ie SET command ("add"/"del") to the buffer */
-	strncpy(hdr.cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
-	hdr.cmd[VNDR_IE_CMD_LEN - 1] = '\0';
-
-	/* Set the IE count - the buffer contains only 1 IE */
-	iecount = htod32(1);
-	memcpy((void *)&hdr.vndr_ie_buffer.iecount, &iecount, sizeof(s32));
-
-	/* Copy packet flags that indicate which packets will contain this IE */
-	pktflag = htod32(pktflag);
-	memcpy((void *)&hdr.vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
-		sizeof(u32));
-
-	/* Add the IE ID to the buffer */
-	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = ie_id;
-
-	/* Add the IE length to the buffer */
-	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len =
-		(uint8) VNDR_IE_MIN_LEN + datalen;
-
-	/* Add the IE OUI to the buffer */
-	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[0] = oui[0];
-	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[1] = oui[1];
-	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[2] = oui[2];
-
-	/* Copy the aligned temporary vndr_ie buffer header to the IE buffer */
-	memcpy(iebuf, &hdr, sizeof(hdr) - 1);
-
-	/* Copy the IE data to the IE buffer */
-	data_offset =
-		(u8*)&hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0] -
-		(u8*)&hdr;
-	memcpy(iebuf + data_offset, data, datalen);
-	return data_offset + datalen;
-
-}
-
-struct net_device *
-wl_cfgp2p_find_ndev(struct bcm_cfg80211 *cfg, s32 bssidx)
-{
-	u32 i;
-	struct net_device *ndev = NULL;
-	if (bssidx < 0) {
-		CFGP2P_ERR((" bsscfg idx is invalid\n"));
-		goto exit;
-	}
-
-	for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
-		if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
-			ndev = wl_to_p2p_bss_ndev(cfg, i);
-			break;
-		}
-	}
-
-exit:
-	return ndev;
-}
-/*
- * Search the driver array idx based on bssidx argument
- * Parameters: Note that this idx is applicable only
- * for primary and P2P interfaces. The virtual AP/STA is not
- * covered here.
- * @cfg     : wl_private data
- * @bssidx : bssidx which indicate bsscfg->idx of firmware.
- * @type   : output arg to store array idx of p2p->bss.
- * Returns error
- */
-
-s32
-wl_cfgp2p_find_type(struct bcm_cfg80211 *cfg, s32 bssidx, s32 *type)
-{
-	u32 i;
-	if (bssidx < 0 || type == NULL) {
-		CFGP2P_ERR((" argument is invalid\n"));
-		goto exit;
-	}
-
-	for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
-		if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
-			*type = i;
-			return BCME_OK;
-		}
-	}
-
-exit:
-	return BCME_BADARG;
-}
-
-/*
- * Callback function for WLC_E_P2P_DISC_LISTEN_COMPLETE
- */
-s32
-wl_cfgp2p_listen_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data)
-{
-	s32 ret = BCME_OK;
-	struct net_device *ndev = NULL;
-
-	if (!cfg || !cfg->p2p || !cfgdev)
-		return BCME_ERROR;
-
-	CFGP2P_DBG((" Enter\n"));
-
-#ifdef DHD_IFDEBUG
-	WL_ERR(("%s: cfg: %p, cfgdev: %p, cfg->wdev: %p, cfg->p2p_wdev: %p\n",
-		__FUNCTION__, cfg, cfgdev, cfg->wdev, cfg->p2p_wdev));
-#endif
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-#ifdef P2P_LISTEN_OFFLOADING
-	if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
-		wl_clr_p2p_status(cfg, DISC_IN_PROGRESS);
-		CFGP2P_ERR(("DISC_IN_PROGRESS cleared\n"));
-		if (ndev && (ndev->ieee80211_ptr != NULL)) {
-#if defined(WL_CFG80211_P2P_DEV_IF)
-			if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy) {
-				cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
-						&cfg->remain_on_chan, GFP_KERNEL);
-			} else {
-				CFGP2P_ERR(("Invalid cfgdev. Dropping the"
-						"remain_on_channel_expired event.\n"));
-			}
-#else
-			cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
-					&cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-		}
-	}
-#endif /* P2P_LISTEN_OFFLOADING */
-
-	if (wl_get_p2p_status(cfg, LISTEN_EXPIRED) == 0) {
-		wl_set_p2p_status(cfg, LISTEN_EXPIRED);
-		if (timer_pending(&cfg->p2p->listen_timer)) {
-			del_timer_sync(&cfg->p2p->listen_timer);
-		}
-
-		if (cfg->afx_hdl->is_listen == TRUE &&
-			wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
-			WL_DBG(("Listen DONE for action frame\n"));
-			complete(&cfg->act_frm_scan);
-		}
-#ifdef WL_CFG80211_SYNC_GON
-		else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
-			wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, ndev);
-			WL_DBG(("Listen DONE and wake up wait_next_af !!(%d)\n",
-				jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies)));
-
-			if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM))
-				wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
-
-			complete(&cfg->wait_next_af);
-		}
-#endif /* WL_CFG80211_SYNC_GON */
-
-#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-		if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL)) {
-#else
-		if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL) ||
-			wl_get_drv_status_all(cfg, FAKE_REMAINING_ON_CHANNEL)) {
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-			WL_DBG(("Listen DONE for remain on channel expired\n"));
-			wl_clr_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-			wl_clr_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-			if (ndev && (ndev->ieee80211_ptr != NULL)) {
-#if defined(WL_CFG80211_P2P_DEV_IF)
-				if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy) {
-					/*
-					 * To prevent kernel panic,
-					 * if cfgdev->wiphy may be invalid, adding explicit check
-					 */
-					cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
-						&cfg->remain_on_chan, GFP_KERNEL);
-				} else {
-					CFGP2P_ERR(("Invalid cfgdev. Dropping the"
-						"remain_on_channel_expired event.\n"));
-				}
-#else
-				cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
-					&cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-			}
-		}
-		if (wl_add_remove_eventmsg(bcmcfg_to_prmry_ndev(cfg),
-			WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) {
-			CFGP2P_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
-		}
-	} else
-		wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
-
-	return ret;
-
-}
-
-/*
- *  Timer expire callback function for LISTEN
- *  We can't report cfg80211_remain_on_channel_expired from Timer ISR context,
- *  so lets do it from thread context.
- */
-void
-wl_cfgp2p_listen_expired(unsigned long data)
-{
-	wl_event_msg_t msg;
-	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
-	CFGP2P_DBG((" Enter\n"));
-	bzero(&msg, sizeof(wl_event_msg_t));
-	msg.event_type =  hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
-	msg.bsscfgidx  =  wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
-#if defined(WL_ENABLE_P2P_IF)
-	wl_cfg80211_event(cfg->p2p_net ? cfg->p2p_net :
-		wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
-#else
-	wl_cfg80211_event(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg,
-		NULL);
-#endif /* WL_ENABLE_P2P_IF */
-}
-/*
- *  Routine for cancelling the P2P LISTEN
- */
-static s32
-wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-                         struct wireless_dev *wdev, bool notify)
-{
-	WL_DBG(("Enter \n"));
-	/* Irrespective of whether timer is running or not, reset
-	 * the LISTEN state.
-	 */
-	if (timer_pending(&cfg->p2p->listen_timer)) {
-		del_timer_sync(&cfg->p2p->listen_timer);
-		if (notify) {
-#if defined(WL_CFG80211_P2P_DEV_IF)
-			if (wdev)
-				cfg80211_remain_on_channel_expired(wdev, cfg->last_roc_id,
-					&cfg->remain_on_chan, GFP_KERNEL);
-#else
-			if (ndev && ndev->ieee80211_ptr)
-				cfg80211_remain_on_channel_expired(ndev, cfg->last_roc_id,
-					&cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-		}
-	}
-	return 0;
-}
-/*
- * Do a P2P Listen on the given channel for the given duration.
- * A listen consists of sitting idle and responding to P2P probe requests
- * with a P2P probe response.
- *
- * This fn assumes dongle p2p device discovery is already enabled.
- * Parameters   :
- * @cfg          : wl_private data
- * @channel     : channel to listen
- * @duration_ms : the time (milli seconds) to wait
- */
-s32
-wl_cfgp2p_discover_listen(struct bcm_cfg80211 *cfg, s32 channel, u32 duration_ms)
-{
-#define EXTRA_DELAY_TIME	100
-	s32 ret = BCME_OK;
-	struct timer_list *_timer;
-	s32 extra_delay;
-	struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
-
-	CFGP2P_DBG((" Enter Listen Channel : %d, Duration : %d\n", channel, duration_ms));
-	if (unlikely(wl_get_p2p_status(cfg, DISCOVERY_ON) == 0)) {
-
-		CFGP2P_ERR((" Discovery is not set, so we have noting to do\n"));
-
-		ret = BCME_NOTREADY;
-		goto exit;
-	}
-	if (timer_pending(&cfg->p2p->listen_timer)) {
-		CFGP2P_DBG(("previous LISTEN is not completed yet\n"));
-		goto exit;
-
-	}
-#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-	else
-		wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
-#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-	if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, true) != BCME_OK) {
-			CFGP2P_ERR((" failed to set WLC_E_P2P_PROPREQ_MSG\n"));
-	}
-
-	ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms,
-	            wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
-	_timer = &cfg->p2p->listen_timer;
-
-	/*  We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle ,
-	 *  otherwise we will wait up to duration_ms + 100ms + duration / 10
-	 */
-	if (ret == BCME_OK) {
-		extra_delay = EXTRA_DELAY_TIME + (duration_ms / 10);
-	} else {
-		/* if failed to set listen, it doesn't need to wait whole duration. */
-		duration_ms = 100 + duration_ms / 20;
-		extra_delay = 0;
-	}
-
-	INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration_ms, extra_delay);
-#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-	wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
-#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-
-#undef EXTRA_DELAY_TIME
-exit:
-	return ret;
-}
-
-
-s32
-wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable)
-{
-	s32 ret = BCME_OK;
-	CFGP2P_DBG((" Enter\n"));
-	if (!wl_get_p2p_status(cfg, DISCOVERY_ON)) {
-
-		CFGP2P_DBG((" do nothing, discovery is off\n"));
-		return ret;
-	}
-	if (wl_get_p2p_status(cfg, SEARCH_ENABLED) == enable) {
-		CFGP2P_DBG(("already : %d\n", enable));
-		return ret;
-	}
-
-	wl_chg_p2p_status(cfg, SEARCH_ENABLED);
-	/* When disabling Search, reset the WL driver's p2p discovery state to
-	 * WL_P2P_DISC_ST_SCAN.
-	 */
-	if (!enable) {
-		wl_clr_p2p_status(cfg, SCANNING);
-		ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
-		            wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
-	}
-
-	return ret;
-}
-
-/*
- * Callback function for WLC_E_ACTION_FRAME_COMPLETE, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE
- */
-s32
-wl_cfgp2p_action_tx_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-            const wl_event_msg_t *e, void *data)
-{
-	s32 ret = BCME_OK;
-	u32 event_type = ntoh32(e->event_type);
-	u32 status = ntoh32(e->status);
-	struct net_device *ndev = NULL;
-	CFGP2P_DBG((" Enter\n"));
-
-	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
-
-	if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
-		if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
-
-			CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
-			if (status == WLC_E_STATUS_SUCCESS) {
-				wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
-				CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n"));
-				if (!cfg->need_wait_afrx && cfg->af_sent_channel) {
-					CFGP2P_DBG(("no need to wait next AF.\n"));
-					wl_stop_wait_next_action_frame(cfg, ndev);
-				}
-			}
-			else if (!wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
-				wl_set_p2p_status(cfg, ACTION_TX_NOACK);
-				CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"));
-				wl_stop_wait_next_action_frame(cfg, ndev);
-			}
-		} else {
-			CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
-						"status : %d\n", status));
-
-			if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
-				complete(&cfg->send_af_done);
-		}
-	}
-	return ret;
-}
-/* Send an action frame immediately without doing channel synchronization.
- *
- * This function does not wait for a completion event before returning.
- * The WLC_E_ACTION_FRAME_COMPLETE event will be received when the action
- * frame is transmitted.
- * The WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE event will be received when an
- * 802.11 ack has been received for the sent action frame.
- */
-s32
-wl_cfgp2p_tx_action_frame(struct bcm_cfg80211 *cfg, struct net_device *dev,
-	wl_af_params_t *af_params, s32 bssidx)
-{
-	s32 ret = BCME_OK;
-	s32 evt_ret = BCME_OK;
-	s32 timeout = 0;
-	wl_eventmsg_buf_t buf;
-
-
-	CFGP2P_INFO(("\n"));
-	CFGP2P_INFO(("channel : %u , dwell time : %u\n",
-	    af_params->channel, af_params->dwell_time));
-
-	wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
-	wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
-
-	bzero(&buf, sizeof(wl_eventmsg_buf_t));
-	wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, true);
-	wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, true);
-	if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0)
-		return evt_ret;
-
-	cfg->af_sent_channel  = af_params->channel;
-#ifdef WL_CFG80211_SYNC_GON
-	cfg->af_tx_sent_jiffies = jiffies;
-#endif /* WL_CFG80211_SYNC_GON */
-
-	ret = wldev_iovar_setbuf_bsscfg(dev, "actframe", af_params, sizeof(*af_params),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-
-	if (ret < 0) {
-		CFGP2P_ERR((" sending action frame is failed\n"));
-		goto exit;
-	}
-
-	timeout = wait_for_completion_timeout(&cfg->send_af_done,
-		msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX));
-
-	if (timeout >= 0 && wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
-		CFGP2P_INFO(("tx action frame operation is completed\n"));
-		ret = BCME_OK;
-	} else if (ETHER_ISBCAST(&cfg->afx_hdl->tx_dst_addr)) {
-		CFGP2P_INFO(("bcast tx action frame operation is completed\n"));
-		ret = BCME_OK;
-	} else {
-		ret = BCME_ERROR;
-		CFGP2P_INFO(("tx action frame operation is failed\n"));
-	}
-	/* clear status bit for action tx */
-	wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
-	wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
-
-exit:
-	CFGP2P_INFO((" via act frame iovar : status = %d\n", ret));
-
-	bzero(&buf, sizeof(wl_eventmsg_buf_t));
-	wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false);
-	wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, false);
-	if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0) {
-		WL_ERR(("TX frame events revert back failed \n"));
-		return evt_ret;
-	}
-
-	return ret;
-}
-
-/* Generate our P2P Device Address and P2P Interface Address from our primary
- * MAC address.
- */
-void
-wl_cfgp2p_generate_bss_mac(struct bcm_cfg80211 *cfg, struct ether_addr *primary_addr)
-{
-	struct ether_addr *mac_addr = wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE);
-	struct ether_addr *int_addr;
-
-	memcpy(mac_addr, primary_addr, sizeof(struct ether_addr));
-	mac_addr->octet[0] |= 0x02;
-	WL_DBG(("P2P Discovery address:"MACDBG "\n", MAC2STRDBG(mac_addr->octet)));
-
-	int_addr = wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_CONNECTION1);
-	memcpy(int_addr, mac_addr, sizeof(struct ether_addr));
-	int_addr->octet[4] ^= 0x80;
-	WL_DBG(("Primary P2P Interface address:"MACDBG "\n", MAC2STRDBG(int_addr->octet)));
-
-	int_addr = wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_CONNECTION2);
-	memcpy(int_addr, mac_addr, sizeof(struct ether_addr));
-	int_addr->octet[4] ^= 0x90;
-}
-
-/* P2P IF Address change to Virtual Interface MAC Address */
-void
-wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id)
-{
-	wifi_p2p_ie_t *ie = (wifi_p2p_ie_t*) buf;
-	u16 len = ie->len;
-	u8 *subel;
-	u8 subelt_id;
-	u16 subelt_len;
-	CFGP2P_DBG((" Enter\n"));
-
-	/* Point subel to the P2P IE's subelt field.
-	 * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
-	 */
-	subel = ie->subelts;
-	len -= 4;	/* exclude OUI + OUI_TYPE */
-
-	while (len >= 3) {
-	/* attribute id */
-		subelt_id = *subel;
-		subel += 1;
-		len -= 1;
-
-		/* 2-byte little endian */
-		subelt_len = *subel++;
-		subelt_len |= *subel++ << 8;
-
-		len -= 2;
-		len -= subelt_len;	/* for the remaining subelt fields */
-
-		if (subelt_id == element_id) {
-			if (subelt_id == P2P_SEID_INTINTADDR) {
-				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
-				CFGP2P_INFO(("Intended P2P Interface Address ATTR FOUND\n"));
-			} else if (subelt_id == P2P_SEID_DEV_ID) {
-				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
-				CFGP2P_INFO(("Device ID ATTR FOUND\n"));
-			} else if (subelt_id == P2P_SEID_DEV_INFO) {
-				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
-				CFGP2P_INFO(("Device INFO ATTR FOUND\n"));
-			} else if (subelt_id == P2P_SEID_GROUP_ID) {
-				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
-				CFGP2P_INFO(("GROUP ID ATTR FOUND\n"));
-			}			return;
-		} else {
-			CFGP2P_DBG(("OTHER id : %d\n", subelt_id));
-		}
-		subel += subelt_len;
-	}
-}
-/*
- * Check if a BSS is up.
- * This is a common implementation called by most OSL implementations of
- * p2posl_bss_isup().  DO NOT call this function directly from the
- * common code -- call p2posl_bss_isup() instead to allow the OSL to
- * override the common implementation if necessary.
- */
-bool
-wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx)
-{
-	s32 result, val;
-	bool isup = false;
-	s8 getbuf[64];
-
-	/* Check if the BSS is up */
-	*(int*)getbuf = -1;
-	result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
-		sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL);
-	if (result != 0) {
-		CFGP2P_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result));
-		CFGP2P_ERR(("NOTE: this ioctl error is normal "
-					"when the BSS has not been created yet.\n"));
-	} else {
-		val = *(int*)getbuf;
-		val = dtoh32(val);
-		CFGP2P_INFO(("---cfg bss -C %d   ==> %d\n", bsscfg_idx, val));
-		isup = (val ? TRUE : FALSE);
-	}
-	return isup;
-}
-
-
-/* Bring up or down a BSS */
-s32
-wl_cfgp2p_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 is_up)
-{
-	s32 ret = BCME_OK;
-	s32 val = is_up ? 1 : 0;
-
-	struct {
-		s32 cfg;
-		s32 val;
-	} bss_setbuf;
-
-	bss_setbuf.cfg = htod32(bsscfg_idx);
-	bss_setbuf.val = htod32(val);
-	CFGP2P_INFO(("---cfg bss -C %d %s\n", bsscfg_idx, is_up ? "up" : "down"));
-	ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-
-	if (ret != 0) {
-		CFGP2P_ERR(("'bss %d' failed with %d\n", is_up, ret));
-	}
-
-	return ret;
-}
-
-/* Check if 'p2p' is supported in the driver */
-s32
-wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev)
-{
-	s32 ret = BCME_OK;
-	s32 p2p_supported = 0;
-	ret = wldev_iovar_getint(ndev, "p2p",
-	               &p2p_supported);
-	if (ret < 0) {
-		if (ret == BCME_UNSUPPORTED) {
-			CFGP2P_INFO(("p2p is unsupported\n"));
-			return 0;
-		} else {
-			CFGP2P_ERR(("cfg p2p error %d\n", ret));
-			return ret;
-		}
-	}
-	if (p2p_supported == 1) {
-		CFGP2P_INFO(("p2p is supported\n"));
-	} else {
-		CFGP2P_INFO(("p2p is unsupported\n"));
-		p2p_supported = 0;
-	}
-	return p2p_supported;
-}
-/* Cleanup P2P resources */
-s32
-wl_cfgp2p_down(struct bcm_cfg80211 *cfg)
-{
-	struct net_device *ndev = NULL;
-	struct wireless_dev *wdev = NULL;
-	s32 i = 0, index = -1;
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-	ndev = bcmcfg_to_prmry_ndev(cfg);
-	wdev = bcmcfg_to_p2p_wdev(cfg);
-#elif defined(WL_ENABLE_P2P_IF)
-	ndev = cfg->p2p_net ? cfg->p2p_net : bcmcfg_to_prmry_ndev(cfg);
-	wdev = ndev_to_wdev(ndev);
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-	wl_cfgp2p_cancel_listen(cfg, ndev, wdev, TRUE);
-	wl_cfgp2p_disable_discovery(cfg);
-
-#if defined(WL_CFG80211_P2P_DEV_IF) && !defined(KEEP_WIFION_OPTION)
-	if (cfg->p2p_wdev) {
-		/* If p2p wdev is left out, clean it up */
-		WL_ERR(("Clean up the p2p discovery IF\n"));
-		wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
-	}
-#endif /* WL_CFG80211_P2P_DEV_IF !defined(KEEP_WIFION_OPTION) */
-
-	for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
-			index = wl_to_p2p_bss_bssidx(cfg, i);
-			if (index != WL_INVALID)
-				wl_cfg80211_clear_per_bss_ies(cfg, index);
-	}
-	wl_cfgp2p_deinit_priv(cfg);
-	return 0;
-}
-
-int wl_cfgp2p_vif_created(struct bcm_cfg80211 *cfg)
-{
-	if (cfg->p2p && ((wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) != -1) ||
-		(wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2) != -1)))
-		return true;
-	else
-		return false;
-
-}
-
-s32
-wl_cfgp2p_set_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
-{
-	s32 ret = -1;
-	int count, start, duration;
-	wl_p2p_sched_t dongle_noa;
-	s32 bssidx, type;
-	int iovar_len = sizeof(dongle_noa);
-	CFGP2P_DBG((" Enter\n"));
-
-	memset(&dongle_noa, 0, sizeof(dongle_noa));
-
-	if (wl_cfgp2p_vif_created(cfg)) {
-		cfg->p2p->noa.desc[0].start = 0;
-
-		sscanf(buf, "%10d %10d %10d", &count, &start, &duration);
-		CFGP2P_DBG(("set_p2p_noa count %d start %d duration %d\n",
-			count, start, duration));
-		if (count != -1)
-			cfg->p2p->noa.desc[0].count = count;
-
-		/* supplicant gives interval as start */
-		if (start != -1)
-			cfg->p2p->noa.desc[0].interval = start;
-
-		if (duration != -1)
-			cfg->p2p->noa.desc[0].duration = duration;
-
-		if (cfg->p2p->noa.desc[0].count != 255 && cfg->p2p->noa.desc[0].count != 0) {
-			cfg->p2p->noa.desc[0].start = 200;
-			dongle_noa.type = WL_P2P_SCHED_TYPE_REQ_ABS;
-			dongle_noa.action = WL_P2P_SCHED_ACTION_GOOFF;
-			dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS;
-		}
-		else if (cfg->p2p->noa.desc[0].count == 0) {
-			cfg->p2p->noa.desc[0].start = 0;
-			dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
-			dongle_noa.option = WL_P2P_SCHED_OPTION_NORMAL;
-			dongle_noa.action = WL_P2P_SCHED_ACTION_RESET;
-		}
-		else {
-			/* Continuous NoA interval. */
-			dongle_noa.action = WL_P2P_SCHED_ACTION_DOZE;
-			dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
-			if ((cfg->p2p->noa.desc[0].interval == 102) ||
-				(cfg->p2p->noa.desc[0].interval == 100)) {
-				cfg->p2p->noa.desc[0].start = 100 -
-					cfg->p2p->noa.desc[0].duration;
-				dongle_noa.option = WL_P2P_SCHED_OPTION_BCNPCT;
-			}
-			else {
-				dongle_noa.option = WL_P2P_SCHED_OPTION_NORMAL;
-			}
-		}
-		/* Put the noa descriptor in dongle format for dongle */
-		dongle_noa.desc[0].count = htod32(cfg->p2p->noa.desc[0].count);
-		if (dongle_noa.option == WL_P2P_SCHED_OPTION_BCNPCT) {
-			dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start);
-			dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration);
-		}
-		else {
-			dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start*1000);
-			dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration*1000);
-		}
-		dongle_noa.desc[0].interval = htod32(cfg->p2p->noa.desc[0].interval*1000);
-		bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
-		if (wl_cfgp2p_find_type(cfg, bssidx, &type) != BCME_OK)
-			return BCME_ERROR;
-
-		if (dongle_noa.action == WL_P2P_SCHED_ACTION_RESET) {
-			iovar_len -= sizeof(wl_p2p_sched_desc_t);
-		}
-
-		ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(cfg, type),
-			"p2p_noa", &dongle_noa, iovar_len, cfg->ioctl_buf,
-			WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-
-		if (ret < 0) {
-			CFGP2P_ERR(("fw set p2p_noa failed %d\n", ret));
-		}
-	}
-	else {
-		CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
-	}
-	return ret;
-}
-s32
-wl_cfgp2p_get_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int buf_len)
-{
-
-	wifi_p2p_noa_desc_t *noa_desc;
-	int len = 0, i;
-	char _buf[200];
-
-	CFGP2P_DBG((" Enter\n"));
-	buf[0] = '\0';
-	if (wl_cfgp2p_vif_created(cfg)) {
-		if (cfg->p2p->noa.desc[0].count || cfg->p2p->ops.ops) {
-			_buf[0] = 1; /* noa index */
-			_buf[1] = (cfg->p2p->ops.ops ? 0x80: 0) |
-				(cfg->p2p->ops.ctw & 0x7f); /* ops + ctw */
-			len += 2;
-			if (cfg->p2p->noa.desc[0].count) {
-				noa_desc = (wifi_p2p_noa_desc_t*)&_buf[len];
-				noa_desc->cnt_type = cfg->p2p->noa.desc[0].count;
-				noa_desc->duration = cfg->p2p->noa.desc[0].duration;
-				noa_desc->interval = cfg->p2p->noa.desc[0].interval;
-				noa_desc->start = cfg->p2p->noa.desc[0].start;
-				len += sizeof(wifi_p2p_noa_desc_t);
-			}
-			if (buf_len <= len * 2) {
-				CFGP2P_ERR(("ERROR: buf_len %d in not enough for"
-					"returning noa in string format\n", buf_len));
-				return -1;
-			}
-			/* We have to convert the buffer data into ASCII strings */
-			for (i = 0; i < len; i++) {
-				snprintf(buf, 3, "%02x", _buf[i]);
-				buf += 2;
-			}
-			buf[i*2] = '\0';
-		}
-	}
-	else {
-		CFGP2P_ERR(("ERROR: get_noa in non-p2p mode\n"));
-		return -1;
-	}
-	return len * 2;
-}
-s32
-wl_cfgp2p_set_p2p_ps(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
-{
-	int ps, ctw;
-	int ret = -1;
-	s32 legacy_ps;
-	s32 conn_idx;
-	s32 bssidx;
-	struct net_device *dev;
-
-	CFGP2P_DBG((" Enter\n"));
-	if (wl_cfgp2p_vif_created(cfg)) {
-		sscanf(buf, "%10d %10d %10d", &legacy_ps, &ps, &ctw);
-		CFGP2P_DBG((" Enter legacy_ps %d ps %d ctw %d\n", legacy_ps, ps, ctw));
-
-		bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
-		if (wl_cfgp2p_find_type(cfg, bssidx, &conn_idx) != BCME_OK)
-			return BCME_ERROR;
-		dev = wl_to_p2p_bss_ndev(cfg, conn_idx);
-		if (ctw != -1) {
-			cfg->p2p->ops.ctw = ctw;
-			ret = 0;
-		}
-		if (ps != -1) {
-			cfg->p2p->ops.ops = ps;
-			ret = wldev_iovar_setbuf(dev,
-				"p2p_ops", &cfg->p2p->ops, sizeof(cfg->p2p->ops),
-				cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-			if (ret < 0) {
-				CFGP2P_ERR(("fw set p2p_ops failed %d\n", ret));
-			}
-		}
-
-		if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) {
-			ret = wldev_ioctl(dev,
-				WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true);
-			if (unlikely(ret))
-				CFGP2P_ERR(("error (%d)\n", ret));
-			wl_cfg80211_update_power_mode(dev);
-		}
-		else
-			CFGP2P_ERR(("ilegal setting\n"));
-	}
-	else {
-		CFGP2P_ERR(("ERROR: set_p2p_ps in non-p2p mode\n"));
-		ret = -1;
-	}
-	return ret;
-}
-
-s32
-wl_cfgp2p_set_p2p_ecsa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
-{
-	int ch, bw;
-	s32 conn_idx;
-	s32 bssidx;
-	struct net_device *dev;
-	char smbuf[WLC_IOCTL_SMLEN];
-	wl_chan_switch_t csa_arg;
-	u32 chnsp = 0;
-	int err = 0;
-
-	CFGP2P_DBG((" Enter\n"));
-	if (wl_cfgp2p_vif_created(cfg)) {
-		sscanf(buf, "%10d %10d", &ch, &bw);
-		CFGP2P_DBG(("Enter ch %d bw %d\n", ch, bw));
-
-		bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
-		if (wl_cfgp2p_find_type(cfg, bssidx, &conn_idx) != BCME_OK) {
-			return BCME_ERROR;
-		}
-		dev = wl_to_p2p_bss_ndev(cfg, conn_idx);
-		if (ch <= 0 || bw <= 0) {
-			CFGP2P_ERR(("Negative value not permitted!\n"));
-			return BCME_ERROR;
-		}
-
-		csa_arg.mode = DOT11_CSA_MODE_ADVISORY;
-		csa_arg.count = P2P_ECSA_CNT;
-		csa_arg.reg = 0;
-
-		sprintf(buf, "%d/%d", ch, bw);
-		chnsp = wf_chspec_aton(buf);
-		if (chnsp == 0) {
-			CFGP2P_ERR(("%s:chsp is not correct\n", __FUNCTION__));
-			return BCME_ERROR;
-		}
-		chnsp = wl_chspec_host_to_driver(chnsp);
-		csa_arg.chspec = chnsp;
-
-		err = wldev_iovar_setbuf(dev, "csa", &csa_arg, sizeof(csa_arg),
-			smbuf, sizeof(smbuf), NULL);
-		if (err) {
-			CFGP2P_ERR(("%s:set p2p_ecsa failed:%d\n", __FUNCTION__, err));
-			return BCME_ERROR;
-		}
-	} else {
-		CFGP2P_ERR(("ERROR: set_p2p_ecsa in non-p2p mode\n"));
-		return BCME_ERROR;
-	}
-	return BCME_OK;
-}
-
-u8 *
-wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id)
-{
-	wifi_p2p_ie_t *ie = NULL;
-	u16 len = 0;
-	u8 *subel;
-	u8 subelt_id;
-	u16 subelt_len;
-
-	if (!buf) {
-		WL_ERR(("P2P IE not present"));
-		return 0;
-	}
-
-	ie = (wifi_p2p_ie_t*) buf;
-	len = ie->len;
-
-	/* Point subel to the P2P IE's subelt field.
-	 * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
-	 */
-	subel = ie->subelts;
-	len -= 4;	/* exclude OUI + OUI_TYPE */
-
-	while (len >= 3) {
-		/* attribute id */
-		subelt_id = *subel;
-		subel += 1;
-		len -= 1;
-
-		/* 2-byte little endian */
-		subelt_len = *subel++;
-		subelt_len |= *subel++ << 8;
-
-		len -= 2;
-		len -= subelt_len;	/* for the remaining subelt fields */
-
-		if (subelt_id == element_id) {
-			/* This will point to start of subelement attrib after
-			 * attribute id & len
-			 */
-			return subel;
-		}
-
-		/* Go to next subelement */
-		subel += subelt_len;
-	}
-
-	/* Not Found */
-	return NULL;
-}
-
-#define P2P_GROUP_CAPAB_GO_BIT	0x01
-
-u8*
-wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib)
-{
-	bcm_tlv_t *ie;
-	u8* pAttrib;
-
-	CFGP2P_INFO(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
-	while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len) == TRUE) {
-			/* Have the P2p ie. Now check for attribute */
-			if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(parse, attrib)) != NULL) {
-				CFGP2P_INFO(("P2P attribute %d was found at parse %p",
-					attrib, parse));
-				return pAttrib;
-			}
-			else {
-				parse += (ie->len + TLV_HDR_LEN);
-				len -= (ie->len + TLV_HDR_LEN);
-				CFGP2P_INFO(("P2P Attribute %d not found Moving parse"
-					" to %p len to %d", attrib, parse, len));
-			}
-		}
-		else {
-			/* It was not p2p IE. parse will get updated automatically to next TLV */
-			CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, len));
-		}
-	}
-	CFGP2P_ERR(("P2P attribute %d was NOT found", attrib));
-	return NULL;
-}
-
-u8 *
-wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length)
-{
-	u8 *capability = NULL;
-	bool p2p_go	= 0;
-	u8 *ptr = NULL;
-
-	if ((capability = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
-	bi->ie_length, P2P_SEID_P2P_INFO)) == NULL) {
-		WL_ERR(("P2P Capability attribute not found"));
-		return NULL;
-	}
-
-	/* Check Group capability for Group Owner bit */
-	p2p_go = capability[1] & P2P_GROUP_CAPAB_GO_BIT;
-	if (!p2p_go) {
-		return bi->BSSID.octet;
-	}
-
-	/* In probe responses, DEVICE INFO attribute will be present */
-	if (!(ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
-	bi->ie_length,  P2P_SEID_DEV_INFO))) {
-		/* If DEVICE_INFO is not found, this might be a beacon frame.
-		 * check for DEVICE_ID in the beacon frame.
-		 */
-		ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
-		bi->ie_length,  P2P_SEID_DEV_ID);
-	}
-
-	if (!ptr)
-		WL_ERR((" Both DEVICE_ID & DEVICE_INFO attribute not present in P2P IE "));
-
-	return ptr;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
-static void
-wl_cfgp2p_ethtool_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
-{
-	snprintf(info->driver, sizeof(info->driver), "p2p");
-	snprintf(info->version, sizeof(info->version), "%lu", (unsigned long)(0));
-}
-
-struct ethtool_ops cfgp2p_ethtool_ops = {
-	.get_drvinfo = wl_cfgp2p_ethtool_get_drvinfo
-};
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
-
-#if defined(WL_ENABLE_P2P_IF)
-s32
-wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg)
-{
-	int ret = 0;
-	struct net_device* net = NULL;
-	struct wireless_dev *wdev = NULL;
-	uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 };
-
-	if (cfg->p2p_net) {
-		CFGP2P_ERR(("p2p_net defined already.\n"));
-		return -EINVAL;
-	}
-
-	/* Allocate etherdev, including space for private structure */
-	if (!(net = alloc_etherdev(sizeof(struct bcm_cfg80211 *)))) {
-		CFGP2P_ERR(("%s: OOM - alloc_etherdev\n", __FUNCTION__));
-		return -ENODEV;
-	}
-
-	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
-	if (unlikely(!wdev)) {
-		WL_ERR(("Could not allocate wireless device\n"));
-		free_netdev(net);
-		return -ENOMEM;
-	}
-
-	strncpy(net->name, "p2p%d", sizeof(net->name) - 1);
-	net->name[IFNAMSIZ - 1] = '\0';
-
-	/* Copy the reference to bcm_cfg80211 */
-	memcpy((void *)netdev_priv(net), &cfg, sizeof(struct bcm_cfg80211 *));
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
-	ASSERT(!net->open);
-	net->do_ioctl = wl_cfgp2p_do_ioctl;
-	net->hard_start_xmit = wl_cfgp2p_start_xmit;
-	net->open = wl_cfgp2p_if_open;
-	net->stop = wl_cfgp2p_if_stop;
-#else
-	ASSERT(!net->netdev_ops);
-	net->netdev_ops = &wl_cfgp2p_if_ops;
-#endif
-
-	/* Register with a dummy MAC addr */
-	memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
-
-	wdev->wiphy = cfg->wdev->wiphy;
-
-	wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
-
-	net->ieee80211_ptr = wdev;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
-	net->ethtool_ops = &cfgp2p_ethtool_ops;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
-
-	SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy));
-
-	/* Associate p2p0 network interface with new wdev */
-	wdev->netdev = net;
-
-	ret = register_netdev(net);
-	if (ret) {
-		CFGP2P_ERR((" register_netdevice failed (%d)\n", ret));
-		free_netdev(net);
-		kfree(wdev);
-		return -ENODEV;
-	}
-
-	/* store p2p net ptr for further reference. Note that iflist won't have this
-	 * entry as there corresponding firmware interface is a "Hidden" interface.
-	 */
-	cfg->p2p_wdev = wdev;
-	cfg->p2p_net = net;
-
-	printk("%s: P2P Interface Registered\n", net->name);
-
-	return ret;
-}
-
-s32
-wl_cfgp2p_unregister_ndev(struct bcm_cfg80211 *cfg)
-{
-
-	if (!cfg || !cfg->p2p_net) {
-		CFGP2P_ERR(("Invalid Ptr\n"));
-		return -EINVAL;
-	}
-
-	unregister_netdev(cfg->p2p_net);
-	free_netdev(cfg->p2p_net);
-
-	return 0;
-}
-static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-
-	if (skb)
-	{
-		CFGP2P_DBG(("(%s) is not used for data operations.Droping the packet.\n",
-			ndev->name));
-		dev_kfree_skb_any(skb);
-	}
-
-	return 0;
-}
-
-static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd)
-{
-	int ret = 0;
-	struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
-	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
-
-	/* There is no ifidx corresponding to p2p0 in our firmware. So we should
-	 * not Handle any IOCTL cmds on p2p0 other than ANDROID PRIVATE CMDs.
-	 * For Android PRIV CMD handling map it to primary I/F
-	 */
-	if (cmd == SIOCDEVPRIVATE+1) {
-		ret = wl_android_priv_cmd(ndev, ifr, cmd);
-
-	} else {
-		CFGP2P_ERR(("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n",
-		__FUNCTION__, cmd));
-		return -1;
-	}
-
-	return ret;
-}
-#endif 
-
-#if defined(WL_ENABLE_P2P_IF)
-static int wl_cfgp2p_if_open(struct net_device *net)
-{
-	struct wireless_dev *wdev = net->ieee80211_ptr;
-
-	if (!wdev || !wl_cfg80211_is_p2p_active())
-		return -EINVAL;
-	WL_TRACE(("Enter\n"));
-#if !defined(WL_IFACE_COMB_NUM_CHANNELS)
-	/* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now,
-	 * do it here. This will make sure that in concurrent mode, supplicant
-	 * is not dependent on a particular order of interface initialization.
-	 * i.e you may give wpa_supp -iwlan0 -N -ip2p0 or wpa_supp -ip2p0 -N
-	 * -iwlan0.
-	 */
-	wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)
-		| BIT(NL80211_IFTYPE_P2P_GO));
-#endif /* !WL_IFACE_COMB_NUM_CHANNELS */
-	wl_cfg80211_do_driver_init(net);
-
-	return 0;
-}
-
-static int wl_cfgp2p_if_stop(struct net_device *net)
-{
-	struct wireless_dev *wdev = net->ieee80211_ptr;
-
-	if (!wdev)
-		return -EINVAL;
-
-	wl_cfg80211_scan_stop(net);
-
-#if !defined(WL_IFACE_COMB_NUM_CHANNELS)
-	wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes)
-					& (~(BIT(NL80211_IFTYPE_P2P_CLIENT)|
-					BIT(NL80211_IFTYPE_P2P_GO)));
-#endif /* !WL_IFACE_COMB_NUM_CHANNELS */
-	return 0;
-}
-
-bool wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops)
-{
-	return (if_ops == &wl_cfgp2p_if_ops);
-}
-#endif /* WL_ENABLE_P2P_IF */
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-struct wireless_dev *
-wl_cfgp2p_add_p2p_disc_if(struct bcm_cfg80211 *cfg)
-{
-	struct wireless_dev *wdev = NULL;
-	struct ether_addr primary_mac;
-
-	if (!cfg || !cfg->p2p_supported)
-		return ERR_PTR(-EINVAL);
-
-	WL_TRACE(("Enter\n"));
-
-	if (cfg->p2p_wdev) {
-#ifndef EXPLICIT_DISCIF_CLEANUP
-		dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
-#endif /* EXPLICIT_DISCIF_CLEANUP */
-		/*
-		 * This is not expected. This can happen due to
-		 * supplicant crash/unclean de-initialization which
-		 * didn't free the p2p discovery interface. Indicate
-		 * driver hang to user space so that the framework
-		 * can rei-init the Wi-Fi.
-		 */
-		CFGP2P_ERR(("p2p_wdev defined already.\n"));
-		wl_probe_wdev_all(cfg);
-#ifdef EXPLICIT_DISCIF_CLEANUP
-		/*
-		 * CUSTOMER_HW4 design doesn't delete the p2p discovery
-		 * interface on ifconfig wlan0 down context which comes
-		 * without a preceeding NL80211_CMD_DEL_INTERFACE for p2p
-		 * discovery. But during supplicant crash the DEL_IFACE
-		 * command will not happen and will cause a left over iface
-		 * even after ifconfig wlan0 down. So delete the iface
-		 * first and then indicate the HANG event
-		 */
-		wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
-#else
-		dhd->hang_reason = HANG_REASON_P2P_IFACE_DEL_FAILURE;
-		net_os_send_hang_message(bcmcfg_to_prmry_ndev(cfg));
-		return ERR_PTR(-ENODEV);
-#endif /* EXPLICIT_DISCIF_CLEANUP */
-	}
-
-	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
-	if (unlikely(!wdev)) {
-		WL_ERR(("Could not allocate wireless device\n"));
-		return ERR_PTR(-ENOMEM);
-	}
-
-	memset(&primary_mac, 0, sizeof(primary_mac));
-	get_primary_mac(cfg, &primary_mac);
-	wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
-
-	wdev->wiphy = cfg->wdev->wiphy;
-	wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
-	memcpy(wdev->address, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE), ETHER_ADDR_LEN);
-
-
-	/* store p2p wdev ptr for further reference. */
-	cfg->p2p_wdev = wdev;
-
-	CFGP2P_ERR(("P2P interface registered\n"));
-#ifdef DHD_IFDEBUG
-	WL_ERR(("%s: wdev: %p, wdev->net: %p\n", __FUNCTION__, wdev, wdev->netdev));
-#endif
-	return wdev;
-}
-
-int
-wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
-{
-	int ret = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-
-	if (!cfg)
-		return -EINVAL;
-
-	WL_TRACE(("Enter\n"));
-
-	ret = wl_cfgp2p_set_firm_p2p(cfg);
-	if (unlikely(ret < 0)) {
-		CFGP2P_ERR(("Set P2P in firmware failed, ret=%d\n", ret));
-		goto exit;
-	}
-
-	ret = wl_cfgp2p_enable_discovery(cfg, bcmcfg_to_prmry_ndev(cfg), NULL, 0);
-	if (unlikely(ret < 0)) {
-		CFGP2P_ERR(("P2P enable discovery failed, ret=%d\n", ret));
-		goto exit;
-	}
-
-	p2p_on(cfg) = true;
-#if defined(P2P_IE_MISSING_FIX)
-	cfg->p2p_prb_noti = false;
-#endif
-
-	CFGP2P_DBG(("P2P interface started\n"));
-
-exit:
-	return ret;
-}
-
-void
-wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
-{
-	int ret = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-
-	if (!cfg)
-		return;
-
-	CFGP2P_DBG(("Enter\n"));
-
-	ret = wl_cfg80211_scan_stop(wdev);
-	if (unlikely(ret < 0)) {
-		CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
-	}
-
-	if (!cfg->p2p)
-		return;
-
-	ret = wl_cfgp2p_disable_discovery(cfg);
-	if (unlikely(ret < 0)) {
-		CFGP2P_ERR(("P2P disable discovery failed, ret=%d\n", ret));
-	}
-
-	p2p_on(cfg) = false;
-
-	CFGP2P_DBG(("Exit. P2P interface stopped\n"));
-
-	return;
-}
-
-int
-wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev, struct bcm_cfg80211 *cfg)
-{
-	bool rollback_lock = false;
-
-	if (!wdev)
-		return -EINVAL;
-
-	WL_TRACE(("Enter\n"));
-#ifdef DHD_IFDEBUG
-	WL_ERR(("%s: wdev: %p, wdev->net: %p\n", __FUNCTION__, wdev, wdev->netdev));
-#endif
-
-	if (!rtnl_is_locked()) {
-		rtnl_lock();
-		rollback_lock = true;
-	}
-
-	cfg80211_unregister_wdev(wdev);
-
-	if (rollback_lock)
-		rtnl_unlock();
-
-	synchronize_rcu();
-
-	kfree(wdev);
-
-	if (cfg)
-		cfg->p2p_wdev = NULL;
-
-	CFGP2P_ERR(("P2P interface unregistered\n"));
-
-	return 0;
-}
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-void
-wl_cfgp2p_need_wait_actfrmae(struct bcm_cfg80211 *cfg, void *frame, u32 frame_len, bool tx)
-{
-	wifi_p2p_pub_act_frame_t *pact_frm;
-	int status = 0;
-
-	if (!frame || (frame_len < (sizeof(*pact_frm) + WL_P2P_AF_STATUS_OFFSET - 1))) {
-		return;
-	}
-
-	if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
-		pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
-		if (pact_frm->subtype == P2P_PAF_GON_RSP && tx) {
-			CFGP2P_ACTION(("Check TX P2P Group Owner Negotiation Rsp Frame status\n"));
-			status = pact_frm->elts[WL_P2P_AF_STATUS_OFFSET];
-			if (status) {
-				cfg->need_wait_afrx = false;
-				return;
-			}
-		}
-	}
-
-	cfg->need_wait_afrx = true;
-	return;
-}
-
-int
-wl_cfgp2p_is_p2p_specific_scan(struct cfg80211_scan_request *request)
-{
-	if (request && (request->n_ssids == 1) &&
-		(request->n_channels == 1) &&
-		IS_P2P_SSID(request->ssids[0].ssid, WL_P2P_WILDCARD_SSID_LEN) &&
-		(request->ssids[0].ssid_len > WL_P2P_WILDCARD_SSID_LEN)) {
-		return true;
-	}
-	return false;
-}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
deleted file mode 100644
index a57ca39..0000000
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Linux cfgp2p driver
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_cfgp2p.h 608203 2015-12-24 05:30:44Z $
- */
-#ifndef _wl_cfgp2p_h_
-#define _wl_cfgp2p_h_
-#include <proto/802.11.h>
-#include <proto/p2p.h>
-
-struct bcm_cfg80211;
-extern u32 wl_dbg_level;
-
-typedef struct wifi_p2p_ie wifi_wfd_ie_t;
-/* Enumeration of the usages of the BSSCFGs used by the P2P Library.  Do not
- * confuse this with a bsscfg index.  This value is an index into the
- * saved_ie[] array of structures which in turn contains a bsscfg index field.
- */
-typedef enum {
-	P2PAPI_BSSCFG_PRIMARY, /* maps to driver's primary bsscfg */
-	P2PAPI_BSSCFG_DEVICE, /* maps to driver's P2P device discovery bsscfg */
-	P2PAPI_BSSCFG_CONNECTION1, /* maps to driver's P2P connection bsscfg */
-	P2PAPI_BSSCFG_CONNECTION2,
-	P2PAPI_BSSCFG_MAX
-} p2p_bsscfg_type_t;
-
-typedef enum {
-	P2P_SCAN_PURPOSE_MIN,
-	P2P_SCAN_SOCIAL_CHANNEL, /* scan for social channel */
-	P2P_SCAN_AFX_PEER_NORMAL, /* scan for action frame search */
-	P2P_SCAN_AFX_PEER_REDUCED, /* scan for action frame search with short time */
-	P2P_SCAN_DURING_CONNECTED, /* scan during connected status */
-	P2P_SCAN_CONNECT_TRY, /* scan for connecting */
-	P2P_SCAN_NORMAL, /* scan during not-connected status */
-	P2P_SCAN_PURPOSE_MAX
-} p2p_scan_purpose_t;
-
-/* vendor ies max buffer length for probe response or beacon */
-#define VNDR_IES_MAX_BUF_LEN	1400
-/* normal vendor ies buffer length */
-#define VNDR_IES_BUF_LEN 		512
-
-struct p2p_bss {
-	s32 bssidx;
-	struct net_device *dev;
-	void *private_data;
-	struct ether_addr mac_addr;
-};
-
-struct p2p_info {
-	bool on;    /* p2p on/off switch */
-	bool scan;
-	int16 search_state;
-	s8 vir_ifname[IFNAMSIZ];
-	unsigned long status;
-	struct p2p_bss bss[P2PAPI_BSSCFG_MAX];
-	struct timer_list listen_timer;
-	wl_p2p_sched_t noa;
-	wl_p2p_ops_t ops;
-	wlc_ssid_t ssid;
-	s8 p2p_go_count;
-};
-
-#define MAX_VNDR_IE_NUMBER	10
-
-struct parsed_vndr_ie_info {
-	char *ie_ptr;
-	u32 ie_len;	/* total length including id & length field */
-	vndr_ie_t vndrie;
-};
-
-struct parsed_vndr_ies {
-	u32 count;
-	struct parsed_vndr_ie_info ie_info[MAX_VNDR_IE_NUMBER];
-};
-
-/* dongle status */
-enum wl_cfgp2p_status {
-	WLP2P_STATUS_DISCOVERY_ON = 0,
-	WLP2P_STATUS_SEARCH_ENABLED,
-	WLP2P_STATUS_IF_ADDING,
-	WLP2P_STATUS_IF_DELETING,
-	WLP2P_STATUS_IF_CHANGING,
-	WLP2P_STATUS_IF_CHANGED,
-	WLP2P_STATUS_LISTEN_EXPIRED,
-	WLP2P_STATUS_ACTION_TX_COMPLETED,
-	WLP2P_STATUS_ACTION_TX_NOACK,
-	WLP2P_STATUS_SCANNING,
-	WLP2P_STATUS_GO_NEG_PHASE,
-	WLP2P_STATUS_DISC_IN_PROGRESS
-};
-
-
-#define wl_to_p2p_bss_ndev(cfg, type)		((cfg)->p2p->bss[type].dev)
-#define wl_to_p2p_bss_bssidx(cfg, type)		((cfg)->p2p->bss[type].bssidx)
-#define wl_to_p2p_bss_macaddr(cfg, type)     &((cfg)->p2p->bss[type].mac_addr)
-#define wl_to_p2p_bss_saved_ie(cfg, type)	((cfg)->p2p->bss[type].saved_ie)
-#define wl_to_p2p_bss_private(cfg, type)		((cfg)->p2p->bss[type].private_data)
-#define wl_to_p2p_bss(cfg, type)			((cfg)->p2p->bss[type])
-#define wl_get_p2p_status(cfg, stat) ((!(cfg)->p2p_supported) ? 0 : \
-		test_bit(WLP2P_STATUS_ ## stat, &(cfg)->p2p->status))
-#define wl_set_p2p_status(cfg, stat) ((!(cfg)->p2p_supported) ? 0 : \
-		set_bit(WLP2P_STATUS_ ## stat, &(cfg)->p2p->status))
-#define wl_clr_p2p_status(cfg, stat) ((!(cfg)->p2p_supported) ? 0 : \
-		clear_bit(WLP2P_STATUS_ ## stat, &(cfg)->p2p->status))
-#define wl_chg_p2p_status(cfg, stat) ((!(cfg)->p2p_supported) ? 0 : \
-	change_bit(WLP2P_STATUS_ ## stat, &(cfg)->p2p->status))
-#define p2p_on(cfg) ((cfg)->p2p->on)
-#define p2p_scan(cfg) ((cfg)->p2p->scan)
-#define p2p_is_on(cfg) ((cfg)->p2p && (cfg)->p2p->on)
-
-/* dword align allocation */
-#define WLC_IOCTL_MAXLEN 8192
-
-#ifdef CUSTOMER_HW4_DEBUG
-#define CFGP2P_ERROR_TEXT		"CFGP2P-INFO2) "
-#else
-#define CFGP2P_ERROR_TEXT		"CFGP2P-ERROR) "
-#endif /* CUSTOMER_HW4_DEBUG */
-
-#ifdef DHD_LOG_DUMP
-#define CFGP2P_ERR(args)									\
-	do {										\
-		if (wl_dbg_level & WL_DBG_ERR) {				\
-			printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__);	\
-			printk args;						\
-			dhd_log_dump_print("[%s] %s: ",	\
-			dhd_log_dump_get_timestamp(), __func__);	\
-			dhd_log_dump_print args;	\
-		}									\
-	} while (0)
-#else
-#define CFGP2P_ERR(args)									\
-	do {										\
-		if (wl_dbg_level & WL_DBG_ERR) {				\
-			printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__);	\
-			printk args;						\
-		}									\
-	} while (0)
-#endif /* DHD_LOG_DUMP */
-#define	CFGP2P_INFO(args)									\
-	do {										\
-		if (wl_dbg_level & WL_DBG_INFO) {				\
-			printk(KERN_INFO "CFGP2P-INFO) %s : ", __func__);	\
-			printk args;						\
-		}									\
-	} while (0)
-#define	CFGP2P_DBG(args)								\
-	do {									\
-		if (wl_dbg_level & WL_DBG_DBG) {			\
-			printk(KERN_DEBUG "CFGP2P-DEBUG) %s :", __func__);	\
-			printk args;							\
-		}									\
-	} while (0)
-
-#define	CFGP2P_ACTION(args)								\
-	do {									\
-		if (wl_dbg_level & WL_DBG_P2P_ACTION) {			\
-			printk(KERN_DEBUG "CFGP2P-ACTION) %s :", __func__);	\
-			printk args;							\
-		}									\
-	} while (0)
-#define INIT_TIMER(timer, func, duration, extra_delay)	\
-	do {				   \
-		init_timer(timer); \
-		timer->function = func; \
-		timer->expires = jiffies + msecs_to_jiffies(duration + extra_delay); \
-		timer->data = (unsigned long) cfg; \
-		add_timer(timer); \
-	} while (0);
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) && !defined(WL_CFG80211_P2P_DEV_IF)
-#define WL_CFG80211_P2P_DEV_IF
-
-#ifdef WL_ENABLE_P2P_IF
-#undef WL_ENABLE_P2P_IF
-#endif
-
-#ifdef WL_SUPPORT_BACKPORTED_KPATCHES
-#undef WL_SUPPORT_BACKPORTED_KPATCHES
-#endif
-#else
-#ifdef WLP2P
-#ifndef WL_ENABLE_P2P_IF
-/* Enable P2P network Interface if P2P support is enabled */
-#define WL_ENABLE_P2P_IF
-#endif /* WL_ENABLE_P2P_IF */
-#endif /* WLP2P */
-#endif /* (LINUX_VERSION >= VERSION(3, 8, 0)) */
-
-#ifndef WL_CFG80211_P2P_DEV_IF
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-#if defined(WL_ENABLE_P2P_IF) && (defined(WL_CFG80211_P2P_DEV_IF) || \
-	(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)))
-#error Disable 'WL_ENABLE_P2P_IF', if 'WL_CFG80211_P2P_DEV_IF' is enabled \
-	or kernel version is 3.8.0 or above
-#endif /* WL_ENABLE_P2P_IF && (WL_CFG80211_P2P_DEV_IF || (LINUX_VERSION >= VERSION(3, 8, 0))) */
-
-#if !defined(WLP2P) && (defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF))
-#error WLP2P not defined
-#endif /* !WLP2P && (WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF) */
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-#define bcm_struct_cfgdev	struct wireless_dev
-#else
-#define bcm_struct_cfgdev	struct net_device
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-#define P2P_ECSA_CNT 50
-
-extern void
-wl_cfgp2p_listen_expired(unsigned long data);
-extern bool
-wl_cfgp2p_is_pub_action(void *frame, u32 frame_len);
-extern bool
-wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len);
-extern bool
-wl_cfgp2p_is_gas_action(void *frame, u32 frame_len);
-extern bool
-wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len);
-extern bool
-wl_cfgp2p_is_p2p_gas_action(void *frame, u32 frame_len);
-extern void
-wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel);
-extern s32
-wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg);
-extern void
-wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg);
-extern s32
-wl_cfgp2p_set_firm_p2p(struct bcm_cfg80211 *cfg);
-extern s32
-wl_cfgp2p_set_p2p_mode(struct bcm_cfg80211 *cfg, u8 mode,
-            u32 channel, u16 listen_ms, int bssidx);
-extern s32
-wl_cfgp2p_ifadd(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
-            chanspec_t chspec);
-extern s32
-wl_cfgp2p_ifdisable(struct bcm_cfg80211 *cfg, struct ether_addr *mac);
-extern s32
-wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac);
-extern s32
-wl_cfgp2p_ifchange(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
-	chanspec_t chspec, s32 conn_idx);
-
-extern s32
-wl_cfgp2p_ifidx(struct bcm_cfg80211 *cfg, struct ether_addr *mac, s32 *index);
-
-extern s32
-wl_cfgp2p_init_discovery(struct bcm_cfg80211 *cfg);
-extern s32
-wl_cfgp2p_enable_discovery(struct bcm_cfg80211 *cfg, struct net_device *dev, const u8 *ie,
-	u32 ie_len);
-extern s32
-wl_cfgp2p_disable_discovery(struct bcm_cfg80211 *cfg);
-extern s32
-wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active, u32 num_chans,
-	u16 *channels,
-	s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr,
-	p2p_scan_purpose_t p2p_scan_purpose);
-
-extern s32
-wl_cfgp2p_act_frm_search(struct bcm_cfg80211 *cfg, struct net_device *ndev,
-	s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr);
-
-extern wpa_ie_fixed_t *
-wl_cfgp2p_find_wpaie(u8 *parse, u32 len);
-
-extern wpa_ie_fixed_t *
-wl_cfgp2p_find_wpsie(u8 *parse, u32 len);
-
-extern wifi_p2p_ie_t *
-wl_cfgp2p_find_p2pie(u8 *parse, u32 len);
-
-extern wifi_wfd_ie_t *
-wl_cfgp2p_find_wfdie(u8 *parse, u32 len);
-extern s32
-wl_cfgp2p_set_management_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx,
-            s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len);
-extern s32
-wl_cfgp2p_clear_management_ie(struct bcm_cfg80211 *cfg, s32 bssidx);
-
-extern struct net_device *
-wl_cfgp2p_find_ndev(struct bcm_cfg80211 *cfg, s32 bssidx);
-extern s32
-wl_cfgp2p_find_type(struct bcm_cfg80211 *cfg, s32 bssidx, s32 *type);
-
-
-extern s32
-wl_cfgp2p_listen_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-extern s32
-wl_cfgp2p_discover_listen(struct bcm_cfg80211 *cfg, s32 channel, u32 duration_ms);
-
-extern s32
-wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable);
-
-extern s32
-wl_cfgp2p_action_tx_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
-	const wl_event_msg_t *e, void *data);
-
-extern s32
-wl_cfgp2p_tx_action_frame(struct bcm_cfg80211 *cfg, struct net_device *dev,
-	wl_af_params_t *af_params, s32 bssidx);
-
-extern void
-wl_cfgp2p_generate_bss_mac(struct bcm_cfg80211 *cfg, struct ether_addr *primary_addr);
-
-extern void
-wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id);
-extern bool
-wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx);
-
-extern s32
-wl_cfgp2p_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 up);
-
-
-extern s32
-wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev);
-
-extern s32
-wl_cfgp2p_down(struct bcm_cfg80211 *cfg);
-
-extern s32
-wl_cfgp2p_set_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len);
-
-extern s32
-wl_cfgp2p_get_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len);
-
-extern s32
-wl_cfgp2p_set_p2p_ps(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len);
-
-extern s32
-wl_cfgp2p_set_p2p_ecsa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len);
-
-extern u8 *
-wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id);
-
-extern u8*
-wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib);
-
-extern u8 *
-wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length);
-
-extern s32
-wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg);
-
-extern s32
-wl_cfgp2p_unregister_ndev(struct bcm_cfg80211 *cfg);
-
-extern bool
-wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops);
-
-extern u32
-wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
-	s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd);
-
-extern int wl_cfgp2p_get_conn_idx(struct bcm_cfg80211 *cfg);
-
-extern
-int wl_cfg_multip2p_operational(struct bcm_cfg80211 *cfg);
-
-extern
-int wl_cfgp2p_vif_created(struct bcm_cfg80211 *cfg);
-
-#if defined(WL_CFG80211_P2P_DEV_IF)
-extern struct wireless_dev *
-wl_cfgp2p_add_p2p_disc_if(struct bcm_cfg80211 *cfg);
-
-extern int
-wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev);
-
-extern void
-wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev);
-
-extern int
-wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev, struct bcm_cfg80211 *cfg);
-
-#endif /* WL_CFG80211_P2P_DEV_IF */
-
-extern void
-wl_cfgp2p_need_wait_actfrmae(struct bcm_cfg80211 *cfg, void *frame, u32 frame_len, bool tx);
-
-extern int
-wl_cfgp2p_is_p2p_specific_scan(struct cfg80211_scan_request *request);
-
-/* WiFi Direct */
-#define SOCIAL_CHAN_1 1
-#define SOCIAL_CHAN_2 6
-#define SOCIAL_CHAN_3 11
-#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \
-					(channel == SOCIAL_CHAN_2) || \
-					(channel == SOCIAL_CHAN_3))
-#define SOCIAL_CHAN_CNT 3
-#define AF_PEER_SEARCH_CNT 2
-#define WL_P2P_WILDCARD_SSID "DIRECT-"
-#define WL_P2P_WILDCARD_SSID_LEN 7
-#define WL_P2P_INTERFACE_PREFIX "p2p"
-#define WL_P2P_TEMP_CHAN 11
-#define WL_P2P_AF_STATUS_OFFSET 9
-
-/* If the provision discovery is for JOIN operations,
- * or the device discoverablity frame is destined to GO
- * then we need not do an internal scan to find GO.
- */
-#define IS_ACTPUB_WITHOUT_GROUP_ID(p2p_ie, len) \
-	(wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID) == NULL)
-
-#define IS_GAS_REQ(frame, len) (wl_cfgp2p_is_gas_action(frame, len) && \
-					((frame->action == P2PSD_ACTION_ID_GAS_IREQ) || \
-					(frame->action == P2PSD_ACTION_ID_GAS_CREQ)))
-
-#define IS_P2P_PUB_ACT_RSP_SUBTYPE(subtype) ((subtype == P2P_PAF_GON_RSP) || \
-							((subtype == P2P_PAF_GON_CONF) || \
-							(subtype == P2P_PAF_INVITE_RSP) || \
-							(subtype == P2P_PAF_PROVDIS_RSP)))
-#define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3))
-#define IS_P2P_SSID(ssid, len) (!memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) && \
-					(len == WL_P2P_WILDCARD_SSID_LEN))
-#endif				/* _wl_cfgp2p_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
deleted file mode 100644
index 75dd877..0000000
--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
+++ /dev/null
@@ -1,1548 +0,0 @@
-/*
- * Linux cfg80211 Vendor Extension Code
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_cfgvendor.c 605796 2015-12-11 13:45:36Z $
- */
-
-/*
- * New vendor interface additon to nl80211/cfg80211 to allow vendors
- * to implement proprietary features over the cfg80211 stack.
-*/
-
-#include <typedefs.h>
-#include <linuxver.h>
-#include <osl.h>
-#include <linux/kernel.h>
-#include <linux/vmalloc.h>
-
-#include <bcmutils.h>
-#include <bcmwifi_channels.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
-#include <proto/802.11.h>
-#include <linux/if_arp.h>
-#include <asm/uaccess.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhdioctl.h>
-#include <wlioctl.h>
-#include <wlioctl_utils.h>
-#include <dhd_cfg80211.h>
-#ifdef PNO_SUPPORT
-#include <dhd_pno.h>
-#endif /* PNO_SUPPORT */
-#ifdef RTT_SUPPORT
-#include <dhd_rtt.h>
-#endif /* RTT_SUPPORT */
-#include <proto/ethernet.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-#include <linux/ieee80211.h>
-#include <linux/wait.h>
-#include <net/cfg80211.h>
-#include <net/rtnetlink.h>
-
-#include <wlioctl.h>
-#include <wldev_common.h>
-#include <wl_cfg80211.h>
-#include <wl_cfgp2p.h>
-#include <wl_android.h>
-#include <wl_cfgvendor.h>
-
-#ifdef PROP_TXSTATUS
-#include <dhd_wlfc.h>
-#endif
-#include <brcm_nl80211.h>
-
-#if defined(WL_VENDOR_EXT_SUPPORT)
-/*
- * This API is to be used for asynchronous vendor events. This
- * shouldn't be used in response to a vendor command from its
- * do_it handler context (instead wl_cfgvendor_send_cmd_reply should
- * be used).
- */
-int wl_cfgvendor_send_async_event(struct wiphy *wiphy,
-	struct net_device *dev, int event_id, const void  *data, int len)
-{
-	u16 kflags;
-	struct sk_buff *skb;
-
-	kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
-
-	/* Alloc the SKB for vendor_event */
-#if defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)
-	skb = cfg80211_vendor_event_alloc(wiphy, NULL, len, event_id, kflags);
-#else
-	skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, kflags);
-#endif /* CONFIG_ARCH_MSM && SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC */
-	if (!skb) {
-		WL_ERR(("skb alloc failed"));
-		return -ENOMEM;
-	}
-
-	/* Push the data to the skb */
-	nla_put_nohdr(skb, len, data);
-
-	cfg80211_vendor_event(skb, kflags);
-
-	return 0;
-}
-
-static int
-wl_cfgvendor_send_cmd_reply(struct wiphy *wiphy,
-	struct net_device *dev, const void  *data, int len)
-{
-	struct sk_buff *skb;
-
-	/* Alloc the SKB for vendor_event */
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
-	if (unlikely(!skb)) {
-		WL_ERR(("skb alloc failed"));
-		return -ENOMEM;
-	}
-
-	/* Push the data to the skb */
-	nla_put_nohdr(skb, len, data);
-
-	return cfg80211_vendor_cmd_reply(skb);
-}
-
-static int
-wl_cfgvendor_get_feature_set(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	int reply;
-
-	reply = dhd_dev_get_feature_set(bcmcfg_to_prmry_ndev(cfg));
-
-	err =  wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
-			&reply, sizeof(int));
-	if (unlikely(err))
-		WL_ERR(("Vendor Command reply failed ret:%d \n", err));
-
-	return err;
-}
-
-static int
-wl_cfgvendor_get_feature_set_matrix(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	struct sk_buff *skb;
-	int *reply;
-	int num, mem_needed, i;
-
-	reply = dhd_dev_get_feature_set_matrix(bcmcfg_to_prmry_ndev(cfg), &num);
-
-	if (!reply) {
-		WL_ERR(("Could not get feature list matrix\n"));
-		err = -EINVAL;
-		return err;
-	}
-	mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * num) +
-	             ATTRIBUTE_U32_LEN;
-
-	/* Alloc the SKB for vendor_event */
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
-	if (unlikely(!skb)) {
-		WL_ERR(("skb alloc failed"));
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, num);
-	for (i = 0; i < num; i++) {
-		nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, reply[i]);
-	}
-
-	err =  cfg80211_vendor_cmd_reply(skb);
-
-	if (unlikely(err))
-		WL_ERR(("Vendor Command reply failed ret:%d \n", err));
-
-exit:
-	kfree(reply);
-	return err;
-}
-
-static int
-wl_cfgvendor_set_pno_mac_oui(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	int type;
-	uint8 pno_random_mac_oui[DOT11_OUI_LEN];
-
-	type = nla_type(data);
-
-	if (type == ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI) {
-		memcpy(pno_random_mac_oui, nla_data(data), DOT11_OUI_LEN);
-
-		err = dhd_dev_pno_set_mac_oui(bcmcfg_to_prmry_ndev(cfg), pno_random_mac_oui);
-
-		if (unlikely(err))
-			WL_ERR(("Bad OUI, could not set:%d \n", err));
-
-
-	} else {
-		err = -1;
-	}
-
-	return err;
-}
-
-#ifdef CUSTOM_FORCE_NODFS_FLAG
-static int
-wl_cfgvendor_set_nodfs_flag(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	int type;
-	u32 nodfs;
-
-	type = nla_type(data);
-	if (type == ANDR_WIFI_ATTRIBUTE_NODFS_SET) {
-		nodfs = nla_get_u32(data);
-		err = dhd_dev_set_nodfs(bcmcfg_to_prmry_ndev(cfg), nodfs);
-	} else {
-		err = -1;
-	}
-	return err;
-}
-#endif /* CUSTOM_FORCE_NODFS_FLAG */
-
-#ifdef GSCAN_SUPPORT
-int
-wl_cfgvendor_send_hotlist_event(struct wiphy *wiphy,
-	struct net_device *dev, void  *data, int len, wl_vendor_event_t event)
-{
-	u16 kflags;
-	const void *ptr;
-	struct sk_buff *skb;
-	int malloc_len, total, iter_cnt_to_send, cnt;
-	gscan_results_cache_t *cache = (gscan_results_cache_t *)data;
-	total = len/sizeof(wifi_gscan_result_t);
-	while (total > 0) {
-		malloc_len = (total * sizeof(wifi_gscan_result_t)) + VENDOR_DATA_OVERHEAD;
-		if (malloc_len > NLMSG_DEFAULT_SIZE) {
-			malloc_len = NLMSG_DEFAULT_SIZE;
-		}
-		iter_cnt_to_send =
-		   (malloc_len - VENDOR_DATA_OVERHEAD)/sizeof(wifi_gscan_result_t);
-		total = total - iter_cnt_to_send;
-
-		kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
-
-		/* Alloc the SKB for vendor_event */
-#if defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)
-		skb = cfg80211_vendor_event_alloc(wiphy, NULL, malloc_len, event, kflags);
-#else
-		skb = cfg80211_vendor_event_alloc(wiphy, malloc_len, event, kflags);
-#endif /* CONFIG_ARCH_MSM && SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC */
-		if (!skb) {
-			WL_ERR(("skb alloc failed"));
-			return -ENOMEM;
-		}
-
-		while (cache && iter_cnt_to_send) {
-			ptr = (const void *) &cache->results[cache->tot_consumed];
-
-			if (iter_cnt_to_send < (cache->tot_count - cache->tot_consumed)) {
-				cnt = iter_cnt_to_send;
-			} else {
-				cnt = (cache->tot_count - cache->tot_consumed);
-			}
-
-			iter_cnt_to_send -= cnt;
-			cache->tot_consumed += cnt;
-			/* Push the data to the skb */
-			nla_append(skb, cnt * sizeof(wifi_gscan_result_t), ptr);
-			if (cache->tot_consumed == cache->tot_count) {
-				cache = cache->next;
-			}
-
-		}
-
-		cfg80211_vendor_event(skb, kflags);
-	}
-
-	return 0;
-}
-
-
-static int
-wl_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	dhd_pno_gscan_capabilities_t *reply = NULL;
-	uint32 reply_len = 0;
-
-
-	reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
-	DHD_PNO_GET_CAPABILITIES, NULL, &reply_len);
-	if (!reply) {
-		WL_ERR(("Could not get capabilities\n"));
-		err = -EINVAL;
-		return err;
-	}
-
-	err =  wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
-	               reply, reply_len);
-
-	if (unlikely(err)) {
-		WL_ERR(("Vendor Command reply failed ret:%d \n", err));
-	}
-
-	kfree(reply);
-	return err;
-}
-
-static int
-wl_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0, type, band;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	uint16 *reply = NULL;
-	uint32 reply_len = 0, num_channels, mem_needed;
-	struct sk_buff *skb;
-
-	type = nla_type(data);
-
-	if (type == GSCAN_ATTRIBUTE_BAND) {
-		band = nla_get_u32(data);
-	} else {
-		return -EINVAL;
-	}
-
-	reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
-	                 DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);
-
-	if (!reply) {
-		WL_ERR(("Could not get channel list\n"));
-		err = -EINVAL;
-		return err;
-	}
-	num_channels =  reply_len/ sizeof(uint32);
-	mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
-
-	/* Alloc the SKB for vendor_event */
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
-	if (unlikely(!skb)) {
-		WL_ERR(("skb alloc failed"));
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels);
-	nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply);
-
-	err =  cfg80211_vendor_cmd_reply(skb);
-
-	if (unlikely(err)) {
-		WL_ERR(("Vendor Command reply failed ret:%d \n", err));
-	}
-exit:
-	kfree(reply);
-	return err;
-}
-
-static int
-wl_cfgvendor_gscan_get_batch_results(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	gscan_results_cache_t *results, *iter;
-	uint32 reply_len, complete = 0, num_results_iter;
-	int32 mem_needed;
-	wifi_gscan_result_t *ptr;
-	uint16 num_scan_ids, num_results;
-	struct sk_buff *skb;
-	struct nlattr *scan_hdr;
-
-	dhd_dev_wait_batch_results_complete(bcmcfg_to_prmry_ndev(cfg));
-	dhd_dev_pno_lock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
-	results = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
-	             DHD_PNO_GET_BATCH_RESULTS, NULL, &reply_len);
-
-	if (!results) {
-		WL_ERR(("No results to send %d\n", err));
-		err =  wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
-		        results, 0);
-
-		if (unlikely(err))
-			WL_ERR(("Vendor Command reply failed ret:%d \n", err));
-		dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
-		return err;
-	}
-	num_scan_ids = reply_len & 0xFFFF;
-	num_results = (reply_len & 0xFFFF0000) >> 16;
-	mem_needed = (num_results * sizeof(wifi_gscan_result_t)) +
-	             (num_scan_ids * GSCAN_BATCH_RESULT_HDR_LEN) +
-	             VENDOR_REPLY_OVERHEAD + SCAN_RESULTS_COMPLETE_FLAG_LEN;
-
-	if (mem_needed > (int32)NLMSG_DEFAULT_SIZE) {
-		mem_needed = (int32)NLMSG_DEFAULT_SIZE;
-		complete = 0;
-	} else {
-		complete = 1;
-	}
-
-	WL_TRACE(("complete %d mem_needed %d max_mem %d\n", complete, mem_needed,
-		(int)NLMSG_DEFAULT_SIZE));
-	/* Alloc the SKB for vendor_event */
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
-	if (unlikely(!skb)) {
-		WL_ERR(("skb alloc failed"));
-		dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
-		return -ENOMEM;
-	}
-		iter = results;
-
-		nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, complete);
-		mem_needed = mem_needed - (SCAN_RESULTS_COMPLETE_FLAG_LEN + VENDOR_REPLY_OVERHEAD);
-		while (iter && ((mem_needed - GSCAN_BATCH_RESULT_HDR_LEN)  > 0)) {
-
-		scan_hdr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS);
-		nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, iter->scan_id);
-		nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, iter->flag);
-
-		num_results_iter =
-		(mem_needed - GSCAN_BATCH_RESULT_HDR_LEN)/sizeof(wifi_gscan_result_t);
-
-		if ((iter->tot_count - iter->tot_consumed) < num_results_iter)
-			num_results_iter = iter->tot_count - iter->tot_consumed;
-		nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results_iter);
-		if (num_results_iter) {
-			ptr = &iter->results[iter->tot_consumed];
-			iter->tot_consumed += num_results_iter;
-			nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS,
-			 num_results_iter * sizeof(wifi_gscan_result_t), ptr);
-		}
-		nla_nest_end(skb, scan_hdr);
-		mem_needed -= GSCAN_BATCH_RESULT_HDR_LEN +
-			(num_results_iter * sizeof(wifi_gscan_result_t));
-		iter = iter->next;
-	}
-
-	dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg));
-	dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
-
-	return cfg80211_vendor_cmd_reply(skb);
-}
-
-static int
-wl_cfgvendor_initiate_gscan(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	int type, tmp = len;
-	int run = 0xFF;
-	int flush = 0;
-	const struct nlattr *iter;
-
-	nla_for_each_attr(iter, data, len, tmp) {
-		type = nla_type(iter);
-		if (type == GSCAN_ATTRIBUTE_ENABLE_FEATURE)
-			run = nla_get_u32(iter);
-		else if (type == GSCAN_ATTRIBUTE_FLUSH_FEATURE)
-			flush = nla_get_u32(iter);
-	}
-
-	if (run != 0xFF) {
-		err = dhd_dev_pno_run_gscan(bcmcfg_to_prmry_ndev(cfg), run, flush);
-
-		if (unlikely(err)) {
-			WL_ERR(("Could not run gscan:%d \n", err));
-		}
-		return err;
-	} else {
-		return -EINVAL;
-	}
-
-
-}
-
-static int
-wl_cfgvendor_enable_full_scan_result(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	int type;
-	bool real_time = FALSE;
-
-	type = nla_type(data);
-
-	if (type == GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS) {
-		real_time = nla_get_u32(data);
-
-		err = dhd_dev_pno_enable_full_scan_result(bcmcfg_to_prmry_ndev(cfg), real_time);
-
-		if (unlikely(err)) {
-			WL_ERR(("Could not run gscan:%d \n", err));
-		}
-
-	} else {
-		err = -EINVAL;
-	}
-
-	return err;
-}
-
-static int
-wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	gscan_scan_params_t *scan_param;
-	int j = 0;
-	int type, tmp, tmp1, tmp2, k = 0;
-	const struct nlattr *iter, *iter1, *iter2;
-	struct dhd_pno_gscan_channel_bucket  *ch_bucket;
-
-	scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL);
-	if (!scan_param) {
-		WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
-		err = -EINVAL;
-		return err;
-
-	}
-
-	scan_param->scan_fr = PNO_SCAN_MIN_FW_SEC;
-	nla_for_each_attr(iter, data, len, tmp) {
-		type = nla_type(iter);
-
-		if (j >= GSCAN_MAX_CH_BUCKETS) {
-			break;
-		}
-
-		switch (type) {
-			case GSCAN_ATTRIBUTE_BASE_PERIOD:
-				scan_param->scan_fr = nla_get_u32(iter)/1000;
-				break;
-			case GSCAN_ATTRIBUTE_NUM_BUCKETS:
-				scan_param->nchannel_buckets = nla_get_u32(iter);
-				break;
-			case GSCAN_ATTRIBUTE_CH_BUCKET_1:
-			case GSCAN_ATTRIBUTE_CH_BUCKET_2:
-			case GSCAN_ATTRIBUTE_CH_BUCKET_3:
-			case GSCAN_ATTRIBUTE_CH_BUCKET_4:
-			case GSCAN_ATTRIBUTE_CH_BUCKET_5:
-			case GSCAN_ATTRIBUTE_CH_BUCKET_6:
-			case GSCAN_ATTRIBUTE_CH_BUCKET_7:
-				nla_for_each_nested(iter1, iter, tmp1) {
-					type = nla_type(iter1);
-					ch_bucket =
-					scan_param->channel_bucket;
-
-					switch (type) {
-						case GSCAN_ATTRIBUTE_BUCKET_ID:
-						break;
-						case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
-							ch_bucket[j].bucket_freq_multiple =
-							    nla_get_u32(iter1)/1000;
-							break;
-						case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
-							ch_bucket[j].num_channels =
-							     nla_get_u32(iter1);
-							break;
-						case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:
-							nla_for_each_nested(iter2, iter1, tmp2) {
-								if (k >= PFN_SWC_RSSI_WINDOW_MAX)
-									break;
-								ch_bucket[j].chan_list[k] =
-								     nla_get_u32(iter2);
-								k++;
-							}
-							k = 0;
-							break;
-						case GSCAN_ATTRIBUTE_BUCKETS_BAND:
-							ch_bucket[j].band = (uint16)
-							     nla_get_u32(iter1);
-							break;
-						case GSCAN_ATTRIBUTE_REPORT_EVENTS:
-							ch_bucket[j].report_flag = (uint8)
-							     nla_get_u32(iter1);
-							break;
-						default:
-							WL_ERR(("bucket attribute type error %d\n",
-							             type));
-							break;
-					}
-				}
-				j++;
-				break;
-			default:
-				WL_ERR(("Unknown type %d\n", type));
-				break;
-		}
-	}
-
-	if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
-	     DHD_PNO_SCAN_CFG_ID, scan_param, 0) < 0) {
-		WL_ERR(("Could not set GSCAN scan cfg\n"));
-		err = -EINVAL;
-	}
-
-	kfree(scan_param);
-	return err;
-
-}
-
-static int
-wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	gscan_hotlist_scan_params_t *hotlist_params;
-	int tmp, tmp1, tmp2, type, j = 0, dummy;
-	const struct nlattr *outer, *inner, *iter;
-	uint8 flush = 0;
-	struct bssid_t *pbssid;
-
-	hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL);
-	if (!hotlist_params) {
-		WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len));
-		return -ENOMEM;
-	}
-
-	hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT;
-
-	nla_for_each_attr(iter, data, len, tmp2) {
-		type = nla_type(iter);
-		switch (type) {
-			case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
-				pbssid = hotlist_params->bssid;
-				nla_for_each_nested(outer, iter, tmp) {
-					nla_for_each_nested(inner, outer, tmp1) {
-						type = nla_type(inner);
-
-						switch (type) {
-							case GSCAN_ATTRIBUTE_BSSID:
-								memcpy(&(pbssid[j].macaddr),
-								  nla_data(inner), ETHER_ADDR_LEN);
-								break;
-							case GSCAN_ATTRIBUTE_RSSI_LOW:
-								pbssid[j].rssi_reporting_threshold =
-								         (int8) nla_get_u8(inner);
-								break;
-							case GSCAN_ATTRIBUTE_RSSI_HIGH:
-								dummy = (int8) nla_get_u8(inner);
-								break;
-							default:
-								WL_ERR(("ATTR unknown %d\n",
-								            type));
-								break;
-						}
-					}
-					j++;
-				}
-				hotlist_params->nbssid = j;
-				break;
-			case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
-				flush = nla_get_u8(iter);
-				break;
-			case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
-				hotlist_params->lost_ap_window = nla_get_u32(iter);
-				break;
-			default:
-				WL_ERR(("Unknown type %d\n", type));
-				break;
-			}
-
-	}
-
-	if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
-	                DHD_PNO_GEOFENCE_SCAN_CFG_ID,
-	                hotlist_params, flush) < 0) {
-		WL_ERR(("Could not set GSCAN HOTLIST cfg\n"));
-		err = -EINVAL;
-		goto exit;
-	}
-exit:
-	kfree(hotlist_params);
-	return err;
-}
-static int
-wl_cfgvendor_set_batch_scan_cfg(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0, tmp, type;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	gscan_batch_params_t batch_param;
-	const struct nlattr *iter;
-
-	batch_param.mscan = batch_param.bestn = 0;
-	batch_param.buffer_threshold = GSCAN_BATCH_NO_THR_SET;
-
-	nla_for_each_attr(iter, data, len, tmp) {
-		type = nla_type(iter);
-
-		switch (type) {
-			case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN:
-				batch_param.bestn = nla_get_u32(iter);
-				break;
-			case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE:
-				batch_param.mscan = nla_get_u32(iter);
-				break;
-			case GSCAN_ATTRIBUTE_REPORT_THRESHOLD:
-				batch_param.buffer_threshold = nla_get_u32(iter);
-				break;
-			default:
-				WL_ERR(("Unknown type %d\n", type));
-				break;
-		}
-	}
-
-	if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
-	                DHD_PNO_BATCH_SCAN_CFG_ID,
-	                &batch_param, 0) < 0) {
-		WL_ERR(("Could not set batch cfg\n"));
-		err = -EINVAL;
-		return err;
-	}
-
-	return err;
-}
-
-static int
-wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	gscan_swc_params_t *significant_params;
-	int tmp, tmp1, tmp2, type, j = 0;
-	const struct nlattr *outer, *inner, *iter;
-	uint8 flush = 0;
-	wl_pfn_significant_bssid_t *bssid;
-
-	significant_params = (gscan_swc_params_t *) kzalloc(len, GFP_KERNEL);
-	if (!significant_params) {
-		WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len));
-		return -ENOMEM;
-	}
-
-	nla_for_each_attr(iter, data, len, tmp2) {
-		type = nla_type(iter);
-
-		switch (type) {
-			case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH:
-			flush = nla_get_u8(iter);
-			break;
-			case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE:
-				significant_params->rssi_window = nla_get_u16(iter);
-				break;
-			case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
-				significant_params->lost_ap_window = nla_get_u16(iter);
-				break;
-			case GSCAN_ATTRIBUTE_MIN_BREACHING:
-				significant_params->swc_threshold = nla_get_u16(iter);
-				break;
-			case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS:
-				bssid = significant_params->bssid_elem_list;
-				nla_for_each_nested(outer, iter, tmp) {
-					nla_for_each_nested(inner, outer, tmp1) {
-							switch (nla_type(inner)) {
-								case GSCAN_ATTRIBUTE_BSSID:
-									memcpy(&(bssid[j].macaddr),
-									       nla_data(inner),
-									       ETHER_ADDR_LEN);
-									break;
-								case GSCAN_ATTRIBUTE_RSSI_HIGH:
-									bssid[j].rssi_high_threshold
-									 = (int8) nla_get_u8(inner);
-									break;
-								case GSCAN_ATTRIBUTE_RSSI_LOW:
-									bssid[j].rssi_low_threshold
-									 = (int8) nla_get_u8(inner);
-									break;
-								default:
-									WL_ERR(("ATTR unknown %d\n",
-									          type));
-									break;
-							}
-						}
-					j++;
-				}
-				break;
-			default:
-				WL_ERR(("Unknown type %d\n", type));
-				break;
-		}
-	}
-	significant_params->nbssid = j;
-
-	if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
-	              DHD_PNO_SIGNIFICANT_SCAN_CFG_ID,
-	              significant_params, flush) < 0) {
-		WL_ERR(("Could not set GSCAN significant cfg\n"));
-		err = -EINVAL;
-		goto exit;
-	}
-exit:
-	kfree(significant_params);
-	return err;
-}
-#endif /* GSCAN_SUPPORT */
-
-#ifdef RTT_SUPPORT
-void
-wl_cfgvendor_rtt_evt(void *ctx, void *rtt_data)
-{
-	struct wireless_dev *wdev = (struct wireless_dev *)ctx;
-	struct wiphy *wiphy;
-	struct sk_buff *skb;
-	uint32 tot_len = NLMSG_DEFAULT_SIZE, entry_len = 0;
-	gfp_t kflags;
-	rtt_report_t *rtt_report = NULL;
-	rtt_result_t *rtt_result = NULL;
-	struct list_head *rtt_list;
-	wiphy = wdev->wiphy;
-
-	WL_DBG(("In\n"));
-	/* Push the data to the skb */
-	if (!rtt_data) {
-		WL_ERR(("rtt_data is NULL\n"));
-		goto exit;
-	}
-	rtt_list = (struct list_head *)rtt_data;
-	kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
-	/* Alloc the SKB for vendor_event */
-#if defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)
-	skb = cfg80211_vendor_event_alloc(wiphy, NULL, tot_len, GOOGLE_RTT_COMPLETE_EVENT, kflags);
-#else
-	skb = cfg80211_vendor_event_alloc(wiphy, tot_len, GOOGLE_RTT_COMPLETE_EVENT, kflags);
-#endif /* CONFIG_ARCH_MSM && SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC */
-	if (!skb) {
-		WL_ERR(("skb alloc failed"));
-		goto exit;
-	}
-	/* fill in the rtt results on each entry */
-	list_for_each_entry(rtt_result, rtt_list, list) {
-		entry_len = 0;
-		entry_len = sizeof(rtt_report_t);
-		rtt_report = kzalloc(entry_len, kflags);
-		if (!rtt_report) {
-			WL_ERR(("rtt_report alloc failed"));
-			kfree_skb(skb);
-			goto exit;
-		}
-		rtt_report->addr = rtt_result->peer_mac;
-		rtt_report->num_measurement = 1; /* ONE SHOT */
-		rtt_report->status = rtt_result->err_code;
-		rtt_report->type =
-			(rtt_result->TOF_type == TOF_TYPE_ONE_WAY) ? RTT_ONE_WAY: RTT_TWO_WAY;
-		rtt_report->peer = rtt_result->target_info->peer;
-		rtt_report->channel = rtt_result->target_info->channel;
-		rtt_report->rssi = rtt_result->avg_rssi;
-		/* tx_rate */
-		rtt_report->tx_rate = rtt_result->tx_rate;
-		/* RTT */
-		rtt_report->rtt = rtt_result->meanrtt;
-		rtt_report->rtt_sd = rtt_result->sdrtt/10;
-		/* convert to centi meter */
-		if (rtt_result->distance != 0xffffffff)
-			rtt_report->distance = (rtt_result->distance >> 2) * 25;
-		else /* invalid distance */
-			rtt_report->distance = -1;
-		rtt_report->ts = rtt_result->ts;
-		nla_append(skb, entry_len, rtt_report);
-		kfree(rtt_report);
-	}
-	cfg80211_vendor_event(skb, kflags);
-exit:
-	return;
-}
-
-static int
-wl_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev,
-	const void *data, int len) {
-	int err = 0, rem, rem1, rem2, type;
-	rtt_config_params_t rtt_param;
-	rtt_target_info_t* rtt_target = NULL;
-	const struct nlattr *iter, *iter1, *iter2;
-	int8 eabuf[ETHER_ADDR_STR_LEN];
-	int8 chanbuf[CHANSPEC_STR_LEN];
-	int32 feature_set = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	feature_set = dhd_dev_get_feature_set(bcmcfg_to_prmry_ndev(cfg));
-
-	WL_DBG(("In\n"));
-	err = dhd_dev_rtt_register_noti_callback(wdev->netdev, wdev, wl_cfgvendor_rtt_evt);
-	if (err < 0) {
-		WL_ERR(("failed to register rtt_noti_callback\n"));
-		goto exit;
-	}
-	memset(&rtt_param, 0, sizeof(rtt_param));
-	nla_for_each_attr(iter, data, len, rem) {
-		type = nla_type(iter);
-		switch (type) {
-		case RTT_ATTRIBUTE_TARGET_CNT:
-			rtt_param.rtt_target_cnt = nla_get_u8(iter);
-			if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) {
-				WL_ERR(("exceed max target count : %d\n",
-					rtt_param.rtt_target_cnt));
-				err = BCME_RANGE;
-				goto exit;
-			}
-			break;
-		case RTT_ATTRIBUTE_TARGET_INFO:
-			rtt_target = rtt_param.target_info;
-			nla_for_each_nested(iter1, iter, rem1) {
-				nla_for_each_nested(iter2, iter1, rem2) {
-					type = nla_type(iter2);
-					switch (type) {
-					case RTT_ATTRIBUTE_TARGET_MAC:
-						memcpy(&rtt_target->addr, nla_data(iter2),
-							ETHER_ADDR_LEN);
-						break;
-					case RTT_ATTRIBUTE_TARGET_TYPE:
-						rtt_target->type = nla_get_u8(iter2);
-						if (!(feature_set & WIFI_FEATURE_D2D_RTT)) {
-							if (rtt_target->type == RTT_TWO_WAY ||
-								rtt_target->type == RTT_INVALID) {
-								WL_ERR(("doesn't support RTT type"
-									" : %d\n",
-									rtt_target->type));
-								err = -EINVAL;
-								goto exit;
-							} else if (rtt_target->type == RTT_AUTO) {
-								rtt_target->type = RTT_ONE_WAY;
-							}
-						} else if (rtt_target->type == RTT_INVALID) {
-							WL_ERR(("doesn't support RTT type"
-								" : %d\n",
-								rtt_target->type));
-							err = -EINVAL;
-							goto exit;
-						}
-						break;
-					case RTT_ATTRIBUTE_TARGET_PEER:
-						rtt_target->peer = nla_get_u8(iter2);
-						if (rtt_target->peer != RTT_PEER_AP) {
-							WL_ERR(("doesn't support peer type : %d\n",
-								rtt_target->peer));
-							err = -EINVAL;
-							goto exit;
-						}
-						break;
-					case RTT_ATTRIBUTE_TARGET_CHAN:
-						memcpy(&rtt_target->channel, nla_data(iter2),
-							sizeof(rtt_target->channel));
-						break;
-					case RTT_ATTRIBUTE_TARGET_MODE:
-						rtt_target->continuous = nla_get_u8(iter2);
-						break;
-					case RTT_ATTRIBUTE_TARGET_INTERVAL:
-						rtt_target->interval = nla_get_u32(iter2);
-						break;
-					case RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT:
-						rtt_target->measure_cnt = nla_get_u32(iter2);
-						break;
-					case RTT_ATTRIBUTE_TARGET_NUM_PKT:
-						rtt_target->ftm_cnt = nla_get_u32(iter2);
-						break;
-					case RTT_ATTRIBUTE_TARGET_NUM_RETRY:
-						rtt_target->retry_cnt = nla_get_u32(iter2);
-					}
-				}
-				/* convert to chanspec value */
-				rtt_target->chanspec =
-					dhd_rtt_convert_to_chspec(rtt_target->channel);
-				if (rtt_target->chanspec == 0) {
-					WL_ERR(("Channel is not valid \n"));
-					goto exit;
-				}
-				WL_INFORM(("Target addr %s, Channel : %s for RTT \n",
-					bcm_ether_ntoa((const struct ether_addr *)&rtt_target->addr,
-					eabuf),
-					wf_chspec_ntoa(rtt_target->chanspec, chanbuf)));
-				rtt_target++;
-			}
-			break;
-		}
-	}
-	WL_DBG(("leave :target_cnt : %d\n", rtt_param.rtt_target_cnt));
-	if (dhd_dev_rtt_set_cfg(bcmcfg_to_prmry_ndev(cfg), &rtt_param) < 0) {
-		WL_ERR(("Could not set RTT configuration\n"));
-		err = -EINVAL;
-	}
-exit:
-	return err;
-}
-
-static int
-wl_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev,
-	const void *data, int len)
-{
-	int err = 0, rem, type, target_cnt = 0;
-	int target_cnt_chk = 0;
-	const struct nlattr *iter;
-	struct ether_addr *mac_list = NULL, *mac_addr = NULL;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-
-	nla_for_each_attr(iter, data, len, rem) {
-		type = nla_type(iter);
-		switch (type) {
-		case RTT_ATTRIBUTE_TARGET_CNT:
-			if (mac_list != NULL) {
-				WL_ERR(("mac_list is not NULL\n"));
-				goto exit;
-			}
-			target_cnt = nla_get_u8(iter);
-			mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN,
-				GFP_KERNEL);
-			if (mac_list == NULL) {
-				WL_ERR(("failed to allocate mem for mac list\n"));
-				goto exit;
-			}
-			mac_addr = &mac_list[0];
-			break;
-		case RTT_ATTRIBUTE_TARGET_MAC:
-			if (mac_addr) {
-				memcpy(mac_addr++, nla_data(iter), ETHER_ADDR_LEN);
-				target_cnt_chk++;
-				if (target_cnt_chk > target_cnt) {
-					WL_ERR(("over target count\n"));
-					goto exit;
-				}
-				break;
-			} else {
-				WL_ERR(("mac_list is NULL\n"));
-				goto exit;
-			}
-		}
-	}
-	if (dhd_dev_rtt_cancel_cfg(bcmcfg_to_prmry_ndev(cfg), mac_list, target_cnt) < 0) {
-		WL_ERR(("Could not cancel RTT configuration\n"));
-		err = -EINVAL;
-		goto exit;
-	}
-
-exit:
-	if (mac_list) {
-		kfree(mac_list);
-	}
-	return err;
-}
-static int
-wl_cfgvendor_rtt_get_capability(struct wiphy *wiphy, struct wireless_dev *wdev,
-	const void *data, int len)
-{
-	int err = 0;
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	rtt_capabilities_t capability;
-
-	err = dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg), &capability);
-	if (unlikely(err)) {
-		WL_ERR(("Vendor Command reply failed ret:%d \n", err));
-		goto exit;
-	}
-	err =  wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
-	        &capability, sizeof(capability));
-
-	if (unlikely(err)) {
-		WL_ERR(("Vendor Command reply failed ret:%d \n", err));
-	}
-exit:
-	return err;
-}
-
-#endif /* RTT_SUPPORT */
-
-static int
-wl_cfgvendor_priv_string_handler(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	int ret = 0;
-	int ret_len = 0, payload = 0, msglen;
-	const struct bcm_nlmsg_hdr *nlioc = data;
-	void *buf = NULL, *cur;
-	int maxmsglen = PAGE_SIZE - 0x100;
-	struct sk_buff *reply;
-
-	WL_ERR(("entry: cmd = %d\n", nlioc->cmd));
-
-	len -= sizeof(struct bcm_nlmsg_hdr);
-	ret_len = nlioc->len;
-	if (ret_len > 0 || len > 0) {
-		if (len > DHD_IOCTL_MAXLEN) {
-			WL_ERR(("oversize input buffer %d\n", len));
-			len = DHD_IOCTL_MAXLEN;
-		}
-		if (ret_len > DHD_IOCTL_MAXLEN) {
-			WL_ERR(("oversize return buffer %d\n", ret_len));
-			ret_len = DHD_IOCTL_MAXLEN;
-		}
-		payload = max(ret_len, len) + 1;
-		buf = vzalloc(payload);
-		if (!buf) {
-			return -ENOMEM;
-		}
-		memcpy(buf, (void *)nlioc + nlioc->offset, len);
-		*(char *)(buf + len) = '\0';
-	}
-
-	ret = dhd_cfgvendor_priv_string_handler(cfg, wdev, nlioc, buf);
-	if (ret) {
-		WL_ERR(("dhd_cfgvendor returned error %d", ret));
-		vfree(buf);
-		return ret;
-	}
-	cur = buf;
-	while (ret_len > 0) {
-		msglen = nlioc->len > maxmsglen ? maxmsglen : ret_len;
-		ret_len -= msglen;
-		payload = msglen + sizeof(msglen);
-		reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
-		if (!reply) {
-			WL_ERR(("Failed to allocate reply msg\n"));
-			ret = -ENOMEM;
-			break;
-		}
-
-		if (nla_put(reply, BCM_NLATTR_DATA, msglen, cur) ||
-			nla_put_u16(reply, BCM_NLATTR_LEN, msglen)) {
-			kfree_skb(reply);
-			ret = -ENOBUFS;
-			break;
-		}
-
-		ret = cfg80211_vendor_cmd_reply(reply);
-		if (ret) {
-			WL_ERR(("testmode reply failed:%d\n", ret));
-			break;
-		}
-		cur += msglen;
-	}
-
-	return ret;
-}
-
-static int
-wl_cfgvendor_priv_bcm_handler(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	int err = 0;
-	int data_len = 0;
-
-	WL_INFORM(("%s: Enter \n", __func__));
-
-	bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
-
-	if (strncmp((char *)data, BRCM_VENDOR_SCMD_CAPA, strlen(BRCM_VENDOR_SCMD_CAPA)) == 0) {
-		err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "cap", NULL, 0,
-			cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-		if (unlikely(err)) {
-			WL_ERR(("error (%d)\n", err));
-			return err;
-		}
-		data_len = strlen(cfg->ioctl_buf);
-	cfg->ioctl_buf[data_len] = '\0';
-	}
-
-	err =  wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
-		cfg->ioctl_buf, data_len+1);
-	if (unlikely(err))
-		WL_ERR(("Vendor Command reply failed ret:%d \n", err));
-	else
-		WL_INFORM(("Vendor Command reply sent successfully!\n"));
-
-	return err;
-}
-
-#ifdef LINKSTAT_SUPPORT
-#define NUM_RATE 32
-#define NUM_PEER 1
-#define NUM_CHAN 11
-#define HEADER_SIZE sizeof(ver_len)
-static int wl_cfgvendor_lstats_get_info(struct wiphy *wiphy,
-	struct wireless_dev *wdev, const void  *data, int len)
-{
-	static char iovar_buf[WLC_IOCTL_MAXLEN];
-	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
-	int err = 0, i;
-	wifi_iface_stat *iface;
-	wifi_radio_stat *radio;
-	wl_wme_cnt_t *wl_wme_cnt;
-	wl_cnt_v_le10_mcst_t *macstat_cnt;
-	wl_cnt_wlc_t *wlc_cnt;
-	scb_val_t scbval;
-	char *output;
-
-	WL_INFORM(("%s: Enter \n", __func__));
-	RETURN_EIO_IF_NOT_UP(cfg);
-
-	bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
-	bzero(iovar_buf, WLC_IOCTL_MAXLEN);
-
-	output = cfg->ioctl_buf;
-
-	err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "radiostat", NULL, 0,
-		iovar_buf, WLC_IOCTL_MAXLEN, NULL);
-	if (err != BCME_OK && err != BCME_UNSUPPORTED) {
-		WL_ERR(("error (%d) - size = %zu\n", err, sizeof(wifi_radio_stat)));
-		return err;
-	}
-	radio = (wifi_radio_stat *)iovar_buf;
-	radio->num_channels = NUM_CHAN;
-	memcpy(output, iovar_buf+HEADER_SIZE, sizeof(wifi_radio_stat)-HEADER_SIZE);
-
-	output += (sizeof(wifi_radio_stat) - HEADER_SIZE);
-	output += (NUM_CHAN*sizeof(wifi_channel_stat));
-
-	err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "wme_counters", NULL, 0,
-		iovar_buf, WLC_IOCTL_MAXLEN, NULL);
-	if (unlikely(err)) {
-		WL_ERR(("error (%d)\n", err));
-		return err;
-	}
-	wl_wme_cnt = (wl_wme_cnt_t *)iovar_buf;
-	iface = (wifi_iface_stat *)output;
-
-	iface->ac[WIFI_AC_VO].ac = WIFI_AC_VO;
-	iface->ac[WIFI_AC_VO].tx_mpdu = wl_wme_cnt->tx[AC_VO].packets;
-	iface->ac[WIFI_AC_VO].rx_mpdu = wl_wme_cnt->rx[AC_VO].packets;
-	iface->ac[WIFI_AC_VO].mpdu_lost = wl_wme_cnt->tx_failed[WIFI_AC_VO].packets;
-
-	iface->ac[WIFI_AC_VI].ac = WIFI_AC_VI;
-	iface->ac[WIFI_AC_VI].tx_mpdu = wl_wme_cnt->tx[AC_VI].packets;
-	iface->ac[WIFI_AC_VI].rx_mpdu = wl_wme_cnt->rx[AC_VI].packets;
-	iface->ac[WIFI_AC_VI].mpdu_lost = wl_wme_cnt->tx_failed[WIFI_AC_VI].packets;
-
-	iface->ac[WIFI_AC_BE].ac = WIFI_AC_BE;
-	iface->ac[WIFI_AC_BE].tx_mpdu = wl_wme_cnt->tx[AC_BE].packets;
-	iface->ac[WIFI_AC_BE].rx_mpdu = wl_wme_cnt->rx[AC_BE].packets;
-	iface->ac[WIFI_AC_BE].mpdu_lost = wl_wme_cnt->tx_failed[WIFI_AC_BE].packets;
-
-	iface->ac[WIFI_AC_BK].ac = WIFI_AC_BK;
-	iface->ac[WIFI_AC_BK].tx_mpdu = wl_wme_cnt->tx[AC_BK].packets;
-	iface->ac[WIFI_AC_BK].rx_mpdu = wl_wme_cnt->rx[AC_BK].packets;
-	iface->ac[WIFI_AC_BK].mpdu_lost = wl_wme_cnt->tx_failed[WIFI_AC_BK].packets;
-	bzero(iovar_buf, WLC_IOCTL_MAXLEN);
-
-	err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "counters", NULL, 0,
-		iovar_buf, WLC_IOCTL_MAXLEN, NULL);
-	if (unlikely(err)) {
-		WL_ERR(("error (%d) - size = %zu\n", err, sizeof(wl_cnt_wlc_t)));
-		return err;
-	}
-
-	/* Translate traditional (ver <= 10) counters struct to new xtlv type struct */
-	err = wl_cntbuf_to_xtlv_format(NULL, iovar_buf, WL_CNTBUF_MAX_SIZE, 0);
-	if (err != BCME_OK) {
-		WL_ERR(("%s wl_cntbuf_to_xtlv_format ERR %d\n",  __FUNCTION__, err));
-	return err;
-	}
-
-	if (!(wlc_cnt = GET_WLCCNT_FROM_CNTBUF(iovar_buf))) {
-		WL_ERR(("%s wlc_cnt NULL!\n", __FUNCTION__));
-		return BCME_ERROR;
-	}
-
-	iface->ac[WIFI_AC_BE].retries = wlc_cnt->txretry;
-
-	if ((macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
-			((wl_cnt_info_t *)iovar_buf)->datalen,
-			WL_CNT_XTLV_CNTV_LE10_UCODE, NULL,
-			BCM_XTLV_OPTION_ALIGN32)) == NULL) {
-		macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
-				((wl_cnt_info_t *)iovar_buf)->datalen,
-				WL_CNT_XTLV_LT40_UCODE_V1, NULL,
-				BCM_XTLV_OPTION_ALIGN32);
-	}
-
-	if (macstat_cnt == NULL) {
-		printf("wlmTxGetAckedPackets: macstat_cnt NULL!\n");
-		return FALSE;
-	}
-
-	iface->beacon_rx = macstat_cnt->rxbeaconmbss;
-
-	err = wldev_get_rssi(bcmcfg_to_prmry_ndev(cfg), &scbval);
-	if (unlikely(err)) {
-		WL_ERR(("get_rssi error (%d)\n", err));
-		return err;
-	}
-	iface->rssi_mgmt = scbval.val;
-
-	iface->num_peers = NUM_PEER;
-	iface->peer_info->num_rate = NUM_RATE;
-
-	bzero(iovar_buf, WLC_IOCTL_MAXLEN);
-	output = (char *)iface + sizeof(wifi_iface_stat) + NUM_PEER*sizeof(wifi_peer_info);
-
-	err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "ratestat", NULL, 0,
-		iovar_buf, WLC_IOCTL_MAXLEN, NULL);
-	if (err != BCME_OK && err != BCME_UNSUPPORTED) {
-		WL_ERR(("error (%d) - size = %zu\n", err, NUM_RATE*sizeof(wifi_rate_stat)));
-		return err;
-	}
-	for (i = 0; i < NUM_RATE; i++)
-		memcpy(output, iovar_buf+HEADER_SIZE+i*sizeof(wifi_rate_stat),
-		sizeof(wifi_rate_stat)-HEADER_SIZE);
-
-	err =  wl_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
-		cfg->ioctl_buf,
-		sizeof(wifi_radio_stat)-HEADER_SIZE +
-		NUM_CHAN*sizeof(wifi_channel_stat) +
-		sizeof(wifi_iface_stat)+NUM_PEER*sizeof(wifi_peer_info) +
-		NUM_RATE*(sizeof(wifi_rate_stat)-HEADER_SIZE));
-	if (unlikely(err))
-		WL_ERR(("Vendor Command reply failed ret:%d \n", err));
-
-	return err;
-}
-#endif /* LINKSTAT_SUPPORT */
-
-static const struct wiphy_vendor_command wl_vendor_cmds [] = {
-	{
-		{
-			.vendor_id = OUI_BRCM,
-			.subcmd = BRCM_VENDOR_SCMD_PRIV_STR
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_priv_string_handler
-	},
-	{
-		{
-			.vendor_id = OUI_BRCM,
-			.subcmd = BRCM_VENDOR_SCMD_BCM_STR
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_priv_bcm_handler
-	},
-#ifdef GSCAN_SUPPORT
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_gscan_get_capabilities
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = GSCAN_SUBCMD_SET_CONFIG
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_set_scan_cfg
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_set_batch_scan_cfg
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_initiate_gscan
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_enable_full_scan_result
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = GSCAN_SUBCMD_SET_HOTLIST
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_hotlist_cfg
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_significant_change_cfg
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_gscan_get_batch_results
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_gscan_get_channel_list
-	},
-#endif /* GSCAN_SUPPORT */
-#ifdef RTT_SUPPORT
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = RTT_SUBCMD_SET_CONFIG
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_rtt_set_config
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = RTT_SUBCMD_CANCEL_CONFIG
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_rtt_cancel_config
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = RTT_SUBCMD_GETCAPABILITY
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_rtt_get_capability
-	},
-#endif /* RTT_SUPPORT */
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_get_feature_set
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_get_feature_set_matrix
-	},
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = ANDR_WIFI_PNO_RANDOM_MAC_OUI
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_set_pno_mac_oui
-	},
-#ifdef CUSTOM_FORCE_NODFS_FLAG
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = ANDR_WIFI_NODFS_CHANNELS
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_set_nodfs_flag
-
-	},
-#endif /* CUSTOM_FORCE_NODFS_FLAG */
-#ifdef LINKSTAT_SUPPORT
-	{
-		{
-			.vendor_id = OUI_GOOGLE,
-			.subcmd = LSTATS_SUBCMD_GET_INFO
-		},
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wl_cfgvendor_lstats_get_info
-	},
-#endif /* LINKSTAT_SUPPORT */
-};
-
-static const struct  nl80211_vendor_cmd_info wl_vendor_events [] = {
-		{ OUI_BRCM, BRCM_VENDOR_EVENT_UNSPEC },
-		{ OUI_BRCM, BRCM_VENDOR_EVENT_PRIV_STR },
-#ifdef GSCAN_SUPPORT
-		{ OUI_GOOGLE, GOOGLE_GSCAN_SIGNIFICANT_EVENT },
-		{ OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT },
-		{ OUI_GOOGLE, GOOGLE_GSCAN_BATCH_SCAN_EVENT },
-		{ OUI_GOOGLE, GOOGLE_SCAN_FULL_RESULTS_EVENT },
-#endif /* GSCAN_SUPPORT */
-#ifdef RTT_SUPPORT
-		{ OUI_GOOGLE, GOOGLE_RTT_COMPLETE_EVENT },
-#endif /* RTT_SUPPORT */
-#ifdef GSCAN_SUPPORT
-		{ OUI_GOOGLE, GOOGLE_SCAN_COMPLETE_EVENT },
-		{ OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT },
-#endif /* GSCAN_SUPPORT */
-		{ OUI_BRCM, BRCM_VENDOR_EVENT_IDSUP_STATUS }
-};
-
-int wl_cfgvendor_attach(struct wiphy *wiphy)
-{
-
-	WL_INFORM(("Vendor: Register BRCM cfg80211 vendor cmd(0x%x) interface \n",
-		NL80211_CMD_VENDOR));
-
-	wiphy->vendor_commands	= wl_vendor_cmds;
-	wiphy->n_vendor_commands = ARRAY_SIZE(wl_vendor_cmds);
-	wiphy->vendor_events	= wl_vendor_events;
-	wiphy->n_vendor_events	= ARRAY_SIZE(wl_vendor_events);
-
-	return 0;
-}
-
-int wl_cfgvendor_detach(struct wiphy *wiphy)
-{
-	WL_INFORM(("Vendor: Unregister BRCM cfg80211 vendor interface \n"));
-
-	wiphy->vendor_commands  = NULL;
-	wiphy->vendor_events    = NULL;
-	wiphy->n_vendor_commands = 0;
-	wiphy->n_vendor_events  = 0;
-
-	return 0;
-}
-#endif /* defined(WL_VENDOR_EXT_SUPPORT) */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.h b/drivers/net/wireless/bcmdhd/wl_cfgvendor.h
deleted file mode 100644
index f3e464e..0000000
--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Linux cfg80211 Vendor Extension Code
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_cfgvendor.h 605796 2015-12-11 13:45:36Z $
- */
-
-
-#ifndef _wl_cfgvendor_h_
-#define _wl_cfgvendor_h_
-
-#define OUI_BRCM    0x001018
-#define OUI_GOOGLE  0x001A11
-#define BRCM_VENDOR_SUBCMD_PRIV_STR	1
-#define ATTRIBUTE_U32_LEN                  (NLA_HDRLEN  + 4)
-#define VENDOR_ID_OVERHEAD                 ATTRIBUTE_U32_LEN
-#define VENDOR_SUBCMD_OVERHEAD             ATTRIBUTE_U32_LEN
-#define VENDOR_DATA_OVERHEAD               (NLA_HDRLEN)
-
-#define SCAN_RESULTS_COMPLETE_FLAG_LEN       ATTRIBUTE_U32_LEN
-#define SCAN_INDEX_HDR_LEN                   (NLA_HDRLEN)
-#define SCAN_ID_HDR_LEN                      ATTRIBUTE_U32_LEN
-#define SCAN_FLAGS_HDR_LEN                   ATTRIBUTE_U32_LEN
-#define GSCAN_NUM_RESULTS_HDR_LEN            ATTRIBUTE_U32_LEN
-#define GSCAN_RESULTS_HDR_LEN                (NLA_HDRLEN)
-#define GSCAN_BATCH_RESULT_HDR_LEN  (SCAN_INDEX_HDR_LEN + SCAN_ID_HDR_LEN + \
-									SCAN_FLAGS_HDR_LEN + \
-							        GSCAN_NUM_RESULTS_HDR_LEN + \
-									GSCAN_RESULTS_HDR_LEN)
-
-#define VENDOR_REPLY_OVERHEAD       (VENDOR_ID_OVERHEAD + \
-									VENDOR_SUBCMD_OVERHEAD + \
-									VENDOR_DATA_OVERHEAD)
-
-#define GSCAN_ATTR_SET1				10
-#define GSCAN_ATTR_SET2				20
-#define GSCAN_ATTR_SET3				30
-#define GSCAN_ATTR_SET4				40
-#define GSCAN_ATTR_SET5				50
-#define GSCAN_ATTR_SET6				60
-
-typedef enum {
-	/* don't use 0 as a valid subcommand */
-	VENDOR_NL80211_SUBCMD_UNSPECIFIED,
-
-	/* define all vendor startup commands between 0x0 and 0x0FFF */
-	VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
-	VENDOR_NL80211_SUBCMD_RANGE_END   = 0x0FFF,
-
-	/* define all GScan related commands between 0x1000 and 0x10FF */
-	ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
-	ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END   = 0x10FF,
-
-	/* define all NearbyDiscovery related commands between 0x1100 and 0x11FF */
-	ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100,
-	ANDROID_NL80211_SUBCMD_NBD_RANGE_END   = 0x11FF,
-
-	/* define all RTT related commands between 0x1100 and 0x11FF */
-	ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
-	ANDROID_NL80211_SUBCMD_RTT_RANGE_END   = 0x11FF,
-
-	ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
-	ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END   = 0x12FF,
-
-	ANDROID_NL80211_SUBCMD_TDLS_RANGE_START = 0x1300,
-	ANDROID_NL80211_SUBCMD_TDLS_RANGE_END	= 0x13FF,
-	/* This is reserved for future usage */
-
-} ANDROID_VENDOR_SUB_COMMAND;
-
-enum andr_vendor_subcmd {
-	GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
-	GSCAN_SUBCMD_SET_CONFIG,
-	GSCAN_SUBCMD_SET_SCAN_CONFIG,
-	GSCAN_SUBCMD_ENABLE_GSCAN,
-	GSCAN_SUBCMD_GET_SCAN_RESULTS,
-	GSCAN_SUBCMD_SCAN_RESULTS,
-	GSCAN_SUBCMD_SET_HOTLIST,
-	GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG,
-	GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS,
-	GSCAN_SUBCMD_GET_CHANNEL_LIST,
-	/* ANDR_WIFI_XXX although not related to gscan are defined here */
-	ANDR_WIFI_SUBCMD_GET_FEATURE_SET,
-	ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX,
-	ANDR_WIFI_PNO_RANDOM_MAC_OUI,
-	ANDR_WIFI_NODFS_CHANNELS,
-	RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
-	RTT_SUBCMD_CANCEL_CONFIG,
-	RTT_SUBCMD_GETCAPABILITY,
-
-	LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,
-    /* Add more sub commands here */
-	VENDOR_SUBCMD_MAX
-};
-
-enum gscan_attributes {
-    GSCAN_ATTRIBUTE_NUM_BUCKETS = GSCAN_ATTR_SET1,
-    GSCAN_ATTRIBUTE_BASE_PERIOD,
-    GSCAN_ATTRIBUTE_BUCKETS_BAND,
-    GSCAN_ATTRIBUTE_BUCKET_ID,
-    GSCAN_ATTRIBUTE_BUCKET_PERIOD,
-    GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
-    GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
-    GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
-    GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
-    GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
-    GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
-
-    GSCAN_ATTRIBUTE_ENABLE_FEATURE = GSCAN_ATTR_SET2,
-    GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE,
-    GSCAN_ATTRIBUTE_FLUSH_FEATURE,
-    GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS,
-    GSCAN_ATTRIBUTE_REPORT_EVENTS,
-    /* remaining reserved for additional attributes */
-    GSCAN_ATTRIBUTE_NUM_OF_RESULTS = GSCAN_ATTR_SET3,
-    GSCAN_ATTRIBUTE_FLUSH_RESULTS,
-    GSCAN_ATTRIBUTE_SCAN_RESULTS,                       /* flat array of wifi_scan_result */
-    GSCAN_ATTRIBUTE_SCAN_ID,                            /* indicates scan number */
-    GSCAN_ATTRIBUTE_SCAN_FLAGS,                         /* indicates if scan was aborted */
-    GSCAN_ATTRIBUTE_AP_FLAGS,                           /* flags on significant change event */
-    GSCAN_ATTRIBUTE_NUM_CHANNELS,
-    GSCAN_ATTRIBUTE_CHANNEL_LIST,
-
-	/* remaining reserved for additional attributes */
-
-    GSCAN_ATTRIBUTE_SSID = GSCAN_ATTR_SET4,
-    GSCAN_ATTRIBUTE_BSSID,
-    GSCAN_ATTRIBUTE_CHANNEL,
-    GSCAN_ATTRIBUTE_RSSI,
-    GSCAN_ATTRIBUTE_TIMESTAMP,
-    GSCAN_ATTRIBUTE_RTT,
-    GSCAN_ATTRIBUTE_RTTSD,
-
-    /* remaining reserved for additional attributes */
-
-    GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = GSCAN_ATTR_SET5,
-    GSCAN_ATTRIBUTE_RSSI_LOW,
-    GSCAN_ATTRIBUTE_RSSI_HIGH,
-    GSCAN_ATTRIBUTE_HOSTLIST_BSSID_ELEM,
-    GSCAN_ATTRIBUTE_HOTLIST_FLUSH,
-
-    /* remaining reserved for additional attributes */
-    GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = GSCAN_ATTR_SET6,
-    GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE,
-    GSCAN_ATTRIBUTE_MIN_BREACHING,
-    GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS,
-    GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH,
-    GSCAN_ATTRIBUTE_MAX
-};
-
-enum gscan_bucket_attributes {
-	GSCAN_ATTRIBUTE_CH_BUCKET_1,
-	GSCAN_ATTRIBUTE_CH_BUCKET_2,
-	GSCAN_ATTRIBUTE_CH_BUCKET_3,
-	GSCAN_ATTRIBUTE_CH_BUCKET_4,
-	GSCAN_ATTRIBUTE_CH_BUCKET_5,
-	GSCAN_ATTRIBUTE_CH_BUCKET_6,
-	GSCAN_ATTRIBUTE_CH_BUCKET_7
-};
-
-enum gscan_ch_attributes {
-	GSCAN_ATTRIBUTE_CH_ID_1,
-	GSCAN_ATTRIBUTE_CH_ID_2,
-	GSCAN_ATTRIBUTE_CH_ID_3,
-	GSCAN_ATTRIBUTE_CH_ID_4,
-	GSCAN_ATTRIBUTE_CH_ID_5,
-	GSCAN_ATTRIBUTE_CH_ID_6,
-	GSCAN_ATTRIBUTE_CH_ID_7
-};
-
-enum rtt_attributes {
-	RTT_ATTRIBUTE_TARGET_CNT,
-	RTT_ATTRIBUTE_TARGET_INFO,
-	RTT_ATTRIBUTE_TARGET_MAC,
-	RTT_ATTRIBUTE_TARGET_TYPE,
-	RTT_ATTRIBUTE_TARGET_PEER,
-	RTT_ATTRIBUTE_TARGET_CHAN,
-	RTT_ATTRIBUTE_TARGET_MODE,
-	RTT_ATTRIBUTE_TARGET_INTERVAL,
-	RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT,
-	RTT_ATTRIBUTE_TARGET_NUM_PKT,
-	RTT_ATTRIBUTE_TARGET_NUM_RETRY
-};
-
-typedef enum wl_vendor_event {
-	BRCM_VENDOR_EVENT_UNSPEC,
-	BRCM_VENDOR_EVENT_PRIV_STR,
-	GOOGLE_GSCAN_SIGNIFICANT_EVENT,
-	GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT,
-	GOOGLE_GSCAN_BATCH_SCAN_EVENT,
-	GOOGLE_SCAN_FULL_RESULTS_EVENT,
-	GOOGLE_RTT_COMPLETE_EVENT,
-	GOOGLE_SCAN_COMPLETE_EVENT,
-	GOOGLE_GSCAN_GEOFENCE_LOST_EVENT,
-	BRCM_VENDOR_EVENT_IDSUP_STATUS
-} wl_vendor_event_t;
-
-enum andr_wifi_attr {
-	ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
-	ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
-	ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
-	ANDR_WIFI_ATTRIBUTE_NODFS_SET
-};
-
-typedef enum wl_vendor_gscan_attribute {
-	ATTR_START_GSCAN,
-	ATTR_STOP_GSCAN,
-	ATTR_SET_SCAN_BATCH_CFG_ID, /* set batch scan params */
-	ATTR_SET_SCAN_GEOFENCE_CFG_ID, /* set list of bssids to track */
-	ATTR_SET_SCAN_SIGNIFICANT_CFG_ID, /* set list of bssids, rssi threshold etc.. */
-	ATTR_SET_SCAN_CFG_ID, /* set common scan config params here */
-	ATTR_GET_GSCAN_CAPABILITIES_ID,
-    /* Add more sub commands here */
-	ATTR_GSCAN_MAX
-} wl_vendor_gscan_attribute_t;
-
-typedef enum gscan_batch_attribute {
-	ATTR_GSCAN_BATCH_BESTN,
-	ATTR_GSCAN_BATCH_MSCAN,
-	ATTR_GSCAN_BATCH_BUFFER_THRESHOLD
-} gscan_batch_attribute_t;
-
-typedef enum gscan_geofence_attribute {
-	ATTR_GSCAN_NUM_HOTLIST_BSSID,
-	ATTR_GSCAN_HOTLIST_BSSID
-} gscan_geofence_attribute_t;
-
-typedef enum gscan_complete_event {
-	WIFI_SCAN_BUFFER_FULL,
-	WIFI_SCAN_COMPLETE
-} gscan_complete_event_t;
-
-/* Capture the BRCM_VENDOR_SUBCMD_PRIV_STRINGS* here */
-#define BRCM_VENDOR_SCMD_CAPA	"cap"
-
-#if defined(WL_VENDOR_EXT_SUPPORT) || defined(CONFIG_BCMDHD_VENDOR_EXT)
-extern int wl_cfgvendor_attach(struct wiphy *wiphy);
-extern int wl_cfgvendor_detach(struct wiphy *wiphy);
-extern int wl_cfgvendor_send_async_event(struct wiphy *wiphy,
-                  struct net_device *dev, int event_id, const void  *data, int len);
-extern int wl_cfgvendor_send_hotlist_event(struct wiphy *wiphy,
-                struct net_device *dev, void  *data, int len, wl_vendor_event_t event);
-#else
-static INLINE int cfgvendor_attach(struct wiphy *wiphy) { return 0; }
-static INLINE int cfgvendor_detach(struct wiphy *wiphy) { return 0; }
-#endif /* defined(WL_VENDOR_EXT_SUPPORT) */
-
-#endif /* _wl_cfgvendor_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_dbg.h b/drivers/net/wireless/bcmdhd/wl_dbg.h
deleted file mode 100644
index 2919116..0000000
--- a/drivers/net/wireless/bcmdhd/wl_dbg.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Minimal debug/trace/assert driver definitions for
- * Broadcom 802.11 Networking Adapter.
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_dbg.h 519338 2014-12-05 21:23:30Z $
- */
-
-
-#ifndef _wl_dbg_h_
-#define _wl_dbg_h_
-
-/* wl_msg_level is a bit vector with defs in wlioctl.h */
-extern uint32 wl_msg_level;
-extern uint32 wl_msg_level2;
-
-#define WL_TIMESTAMP()
-
-#define WL_PRINT(args)		do { WL_TIMESTAMP(); printf args; } while (0)
-
-#if defined(EVENT_LOG_COMPILE) && defined(WLMSG_SRSCAN)
-#define _WL_SRSCAN(fmt, ...)	EVENT_LOG(EVENT_LOG_TAG_SRSCAN, fmt, ##__VA_ARGS__)
-#define WL_SRSCAN(args)		_WL_SRSCAN args
-#else
-#define WL_SRSCAN(args)
-#endif
-
-#if defined(BCMCONDITIONAL_LOGGING)
-
-/* Ideally this should be some include file that vendors can include to conditionalize logging */
-
-/* DBGONLY() macro to reduce ifdefs in code for statements that are only needed when
- * BCMDBG is defined.
- */
-#define DBGONLY(x)
-
-/* To disable a message completely ... until you need it again */
-#define WL_NONE(args)
-#define WL_ERROR(args)		do {if (wl_msg_level & WL_ERROR_VAL) WL_PRINT(args);} while (0)
-#define WL_TRACE(args)
-#define WL_PRHDRS_MSG(args)
-#define WL_PRHDRS(i, p, f, t, r, l)
-#define WL_PRPKT(m, b, n)
-#define WL_INFORM(args)
-#define WL_TMP(args)
-#define WL_OID(args)
-#define WL_RATE(args)		do {if (wl_msg_level & WL_RATE_VAL) WL_PRINT(args);} while (0)
-#define WL_ASSOC(args)		do {if (wl_msg_level & WL_ASSOC_VAL) WL_PRINT(args);} while (0)
-#define WL_PRUSR(m, b, n)
-#define WL_PS(args)		do {if (wl_msg_level & WL_PS_VAL) WL_PRINT(args);} while (0)
-
-#define WL_PORT(args)
-#define WL_DUAL(args)
-#define WL_REGULATORY(args)	do {if (wl_msg_level & WL_REGULATORY_VAL) WL_PRINT(args);} while (0)
-
-#define WL_MPC(args)
-#define WL_APSTA(args)
-#define WL_APSTA_BCN(args)
-#define WL_APSTA_TX(args)
-#define WL_APSTA_TSF(args)
-#define WL_APSTA_BSSID(args)
-#define WL_BA(args)
-#define WL_MBSS(args)
-#define WL_PROTO(args)
-
-#define	WL_CAC(args)		do {if (wl_msg_level & WL_CAC_VAL) WL_PRINT(args);} while (0)
-#define WL_AMSDU(args)
-#define WL_AMPDU(args)
-#define WL_FFPLD(args)
-#define WL_MCHAN(args)
-
-#define WL_DFS(args)
-#define WL_WOWL(args)
-#define WL_DPT(args)
-#define WL_ASSOC_OR_DPT(args)
-#define WL_SCAN(args)		do {if (wl_msg_level2 & WL_SCAN_VAL) WL_PRINT(args);} while (0)
-#define WL_COEX(args)
-#define WL_RTDC(w, s, i, j)
-#define WL_RTDC2(w, s, i, j)
-#define WL_CHANINT(args)
-#define WL_BTA(args)
-#define WL_P2P(args)
-#define WL_ITFR(args)
-#define WL_TDLS(args)
-#define WL_MCNX(args)
-#define WL_PROT(args)
-#define WL_PSTA(args)
-#define WL_WFDS(m, b, n)
-#define WL_TRF_MGMT(args)
-#define WL_L2FILTER(args)
-#define WL_MQ(args)
-#define WL_TXBF(args)
-#define WL_P2PO(args)
-#define WL_ROAM(args)
-#define WL_WNM(args)
-
-
-#define WL_AMPDU_UPDN(args)
-#define WL_AMPDU_RX(args)
-#define WL_AMPDU_ERR(args)
-#define WL_AMPDU_TX(args)
-#define WL_AMPDU_CTL(args)
-#define WL_AMPDU_HW(args)
-#define WL_AMPDU_HWTXS(args)
-#define WL_AMPDU_HWDBG(args)
-#define WL_AMPDU_STAT(args)
-#define WL_AMPDU_ERR_ON()       0
-#define WL_AMPDU_HW_ON()        0
-#define WL_AMPDU_HWTXS_ON()     0
-
-#define WL_APSTA_UPDN(args)
-#define WL_APSTA_RX(args)
-#define WL_WSEC(args)
-#define WL_WSEC_DUMP(args)
-#define WL_PCIE(args)
-#define WL_TSLOG(w, s, i, j)
-#define WL_FBT(args)
-
-#define WL_ERROR_ON()		(wl_msg_level & WL_ERROR_VAL)
-#define WL_TRACE_ON()		0
-#define WL_PRHDRS_ON()		0
-#define WL_PRPKT_ON()		0
-#define WL_INFORM_ON()		0
-#define WL_TMP_ON()		0
-#define WL_OID_ON()		0
-#define WL_RATE_ON()		(wl_msg_level & WL_RATE_VAL)
-#define WL_ASSOC_ON()		(wl_msg_level & WL_ASSOC_VAL)
-#define WL_PRUSR_ON()		0
-#define WL_PS_ON()		(wl_msg_level & WL_PS_VAL)
-#define WL_PORT_ON()		0
-#define WL_WSEC_ON()		0
-#define WL_WSEC_DUMP_ON()	0
-#define WL_MPC_ON()		0
-#define WL_REGULATORY_ON()	(wl_msg_level & WL_REGULATORY_VAL)
-#define WL_APSTA_ON()		0
-#define WL_DFS_ON()		0
-#define WL_MBSS_ON()		0
-#define WL_CAC_ON()		(wl_msg_level & WL_CAC_VAL)
-#define WL_AMPDU_ON()		0
-#define WL_DPT_ON()		0
-#define WL_WOWL_ON()		0
-#define WL_SCAN_ON()		(wl_msg_level2 & WL_SCAN_VAL)
-#define WL_BTA_ON()		0
-#define WL_P2P_ON()		0
-#define WL_ITFR_ON()		0
-#define WL_MCHAN_ON()		0
-#define WL_TDLS_ON()		0
-#define WL_MCNX_ON()		0
-#define WL_PROT_ON()		0
-#define WL_PSTA_ON()		0
-#define WL_TRF_MGMT_ON()	0
-#define WL_LPC_ON()		0
-#define WL_L2FILTER_ON()	0
-#define WL_TXBF_ON()		0
-#define WL_P2PO_ON()		0
-#define WL_TSLOG_ON()		0
-#define WL_WNM_ON()		0
-#define WL_PCIE_ON()		0
-
-#else /* !BCMDBG */
-
-/* DBGONLY() macro to reduce ifdefs in code for statements that are only needed when
- * BCMDBG is defined.
- */
-#define DBGONLY(x)
-
-/* To disable a message completely ... until you need it again */
-#define WL_NONE(args)
-
-#define	WL_ERROR(args)
-#define	WL_TRACE(args)
-#define WL_APSTA_UPDN(args)
-#define WL_APSTA_RX(args)
-#ifdef WLMSG_WSEC
-#define WL_WSEC(args)		WL_PRINT(args)
-#define WL_WSEC_DUMP(args)	WL_PRINT(args)
-#else
-#define WL_WSEC(args)
-#define WL_WSEC_DUMP(args)
-#endif
-#define WL_PCIE(args)		do {if (wl_msg_level2 & WL_PCIE_VAL) WL_PRINT(args);} while (0)
-#define WL_PCIE_ON()		(wl_msg_level2 & WL_PCIE_VAL)
-#define WL_PFN(args)      do {if (wl_msg_level & WL_PFN_VAL) WL_PRINT(args);} while (0)
-#define WL_PFN_ON()		(wl_msg_level & WL_PFN_VAL)
-#endif 
-
-extern uint32 wl_msg_level;
-extern uint32 wl_msg_level2;
-#endif /* _wl_dbg_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
deleted file mode 100644
index 78336e2..0000000
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ /dev/null
@@ -1,3795 +0,0 @@
-/*
- * Linux Wireless Extensions support
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_iw.c 591286 2015-10-07 11:59:26Z $
- */
-
-#if defined(USE_IW)
-#define LINUX_PORT
-
-#include <typedefs.h>
-#include <linuxver.h>
-#include <osl.h>
-
-#include <bcmutils.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
-
-#include <linux/if_arp.h>
-#include <asm/uaccess.h>
-
-#include <wlioctl.h>
-#include <wlioctl_utils.h>
-
-typedef const struct si_pub	si_t;
-
-#include <wl_dbg.h>
-#include <wl_iw.h>
-
-
-/* Broadcom extensions to WEXT, linux upstream has obsoleted WEXT */
-#ifndef IW_AUTH_KEY_MGMT_FT_802_1X
-#define IW_AUTH_KEY_MGMT_FT_802_1X 0x04
-#endif
-
-#ifndef IW_AUTH_KEY_MGMT_FT_PSK
-#define IW_AUTH_KEY_MGMT_FT_PSK 0x08
-#endif
-
-#ifndef IW_ENC_CAPA_FW_ROAM_ENABLE
-#define IW_ENC_CAPA_FW_ROAM_ENABLE	0x00000020
-#endif
-
-
-/* FC9: wireless.h 2.6.25-14.fc9.i686 is missing these, even though WIRELESS_EXT is set to latest
- * version 22.
- */
-#ifndef IW_ENCODE_ALG_PMK
-#define IW_ENCODE_ALG_PMK 4
-#endif
-#ifndef IW_ENC_CAPA_4WAY_HANDSHAKE
-#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010
-#endif
-/* End FC9. */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-#include <linux/rtnetlink.h>
-#endif
-#if defined(SOFTAP)
-struct net_device *ap_net_dev = NULL;
-tsk_ctl_t ap_eth_ctl;  /* apsta AP netdev waiter thread */
-#endif /* SOFTAP */
-
-extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
-	uint32 reason, char* stringBuf, uint buflen);
-
-uint wl_msg_level = WL_ERROR_VAL;
-
-#define MAX_WLIW_IOCTL_LEN 1024
-
-/* IOCTL swapping mode for Big Endian host with Little Endian dongle.  Default to off */
-#define htod32(i) (i)
-#define htod16(i) (i)
-#define dtoh32(i) (i)
-#define dtoh16(i) (i)
-#define htodchanspec(i) (i)
-#define dtohchanspec(i) (i)
-
-extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
-extern int dhd_wait_pend8021x(struct net_device *dev);
-
-#if WIRELESS_EXT < 19
-#define IW_IOCTL_IDX(cmd)	((cmd) - SIOCIWFIRST)
-#define IW_EVENT_IDX(cmd)	((cmd) - IWEVFIRST)
-#endif /* WIRELESS_EXT < 19 */
-
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-#define DAEMONIZE(a)	do { \
-		allow_signal(SIGKILL);	\
-		allow_signal(SIGTERM);	\
-	} while (0)
-#elif ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && \
-	(LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)))
-#define DAEMONIZE(a) daemonize(a); \
-	allow_signal(SIGKILL); \
-	allow_signal(SIGTERM);
-#else /* Linux 2.4 (w/o preemption patch) */
-#define RAISE_RX_SOFTIRQ() \
-	cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
-#define DAEMONIZE(a) daemonize(); \
-	do { if (a) \
-		strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \
-	} while (0);
-#endif /* LINUX_VERSION_CODE  */
-
-#define ISCAN_STATE_IDLE   0
-#define ISCAN_STATE_SCANING 1
-
-/* the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */
-#define WLC_IW_ISCAN_MAXLEN   2048
-typedef struct iscan_buf {
-	struct iscan_buf * next;
-	char   iscan_buf[WLC_IW_ISCAN_MAXLEN];
-} iscan_buf_t;
-
-typedef struct iscan_info {
-	struct net_device *dev;
-	struct timer_list timer;
-	uint32 timer_ms;
-	uint32 timer_on;
-	int    iscan_state;
-	iscan_buf_t * list_hdr;
-	iscan_buf_t * list_cur;
-
-	/* Thread to work on iscan */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-	struct task_struct *kthread;
-#endif
-	long sysioc_pid;
-	struct semaphore sysioc_sem;
-	struct completion sysioc_exited;
-
-
-	char ioctlbuf[WLC_IOCTL_SMLEN];
-} iscan_info_t;
-iscan_info_t *g_iscan = NULL;
-static void wl_iw_timerfunc(ulong data);
-static void wl_iw_set_event_mask(struct net_device *dev);
-static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action);
-
-/* priv_link becomes netdev->priv and is the link between netdev and wlif struct */
-typedef struct priv_link {
-	wl_iw_t *wliw;
-} priv_link_t;
-
-/* dev to priv_link */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
-#define WL_DEV_LINK(dev)       (priv_link_t*)(dev->priv)
-#else
-#define WL_DEV_LINK(dev)       (priv_link_t*)netdev_priv(dev)
-#endif
-
-/* dev to wl_iw_t */
-#define IW_DEV_IF(dev)          ((wl_iw_t*)(WL_DEV_LINK(dev))->wliw)
-
-static void swap_key_from_BE(
-	        wl_wsec_key_t *key
-)
-{
-	key->index = htod32(key->index);
-	key->len = htod32(key->len);
-	key->algo = htod32(key->algo);
-	key->flags = htod32(key->flags);
-	key->rxiv.hi = htod32(key->rxiv.hi);
-	key->rxiv.lo = htod16(key->rxiv.lo);
-	key->iv_initialized = htod32(key->iv_initialized);
-}
-
-static void swap_key_to_BE(
-	        wl_wsec_key_t *key
-)
-{
-	key->index = dtoh32(key->index);
-	key->len = dtoh32(key->len);
-	key->algo = dtoh32(key->algo);
-	key->flags = dtoh32(key->flags);
-	key->rxiv.hi = dtoh32(key->rxiv.hi);
-	key->rxiv.lo = dtoh16(key->rxiv.lo);
-	key->iv_initialized = dtoh32(key->iv_initialized);
-}
-
-static int
-dev_wlc_ioctl(
-	struct net_device *dev,
-	int cmd,
-	void *arg,
-	int len
-)
-{
-	struct ifreq ifr;
-	wl_ioctl_t ioc;
-	mm_segment_t fs;
-	int ret;
-
-	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = cmd;
-	ioc.buf = arg;
-	ioc.len = len;
-
-	strncpy(ifr.ifr_name, dev->name, sizeof(ifr.ifr_name));
-	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
-	ifr.ifr_data = (caddr_t) &ioc;
-
-	fs = get_fs();
-	set_fs(get_ds());
-#if defined(WL_USE_NETDEV_OPS)
-	ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#else
-	ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#endif
-	set_fs(fs);
-
-	return ret;
-}
-
-/*
-set named driver variable to int value and return error indication
-calling example: dev_wlc_intvar_set(dev, "arate", rate)
-*/
-
-static int
-dev_wlc_intvar_set(
-	struct net_device *dev,
-	char *name,
-	int val)
-{
-	char buf[WLC_IOCTL_SMLEN];
-	uint len;
-
-	val = htod32(val);
-	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
-	ASSERT(len);
-
-	return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
-}
-
-static int
-dev_iw_iovar_setbuf(
-	struct net_device *dev,
-	char *iovar,
-	void *param,
-	int paramlen,
-	void *bufptr,
-	int buflen)
-{
-	int iolen;
-
-	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	ASSERT(iolen);
-	BCM_REFERENCE(iolen);
-
-	return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen));
-}
-
-static int
-dev_iw_iovar_getbuf(
-	struct net_device *dev,
-	char *iovar,
-	void *param,
-	int paramlen,
-	void *bufptr,
-	int buflen)
-{
-	int iolen;
-
-	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	ASSERT(iolen);
-	BCM_REFERENCE(iolen);
-
-	return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen));
-}
-
-#if WIRELESS_EXT > 17
-static int
-dev_wlc_bufvar_set(
-	struct net_device *dev,
-	char *name,
-	char *buf, int len)
-{
-	char *ioctlbuf;
-	uint buflen;
-	int error;
-
-	ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
-	if (!ioctlbuf)
-		return -ENOMEM;
-
-	buflen = bcm_mkiovar(name, buf, len, ioctlbuf, MAX_WLIW_IOCTL_LEN);
-	ASSERT(buflen);
-	error = dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen);
-
-	kfree(ioctlbuf);
-	return error;
-}
-#endif /* WIRELESS_EXT > 17 */
-
-/*
-get named driver variable to int value and return error indication
-calling example: dev_wlc_bufvar_get(dev, "arate", &rate)
-*/
-
-static int
-dev_wlc_bufvar_get(
-	struct net_device *dev,
-	char *name,
-	char *buf, int buflen)
-{
-	char *ioctlbuf;
-	int error;
-
-	uint len;
-
-	ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
-	if (!ioctlbuf)
-		return -ENOMEM;
-	len = bcm_mkiovar(name, NULL, 0, ioctlbuf, MAX_WLIW_IOCTL_LEN);
-	ASSERT(len);
-	BCM_REFERENCE(len);
-	error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN);
-	if (!error)
-		bcopy(ioctlbuf, buf, buflen);
-
-	kfree(ioctlbuf);
-	return (error);
-}
-
-/*
-get named driver variable to int value and return error indication
-calling example: dev_wlc_intvar_get(dev, "arate", &rate)
-*/
-
-static int
-dev_wlc_intvar_get(
-	struct net_device *dev,
-	char *name,
-	int *retval)
-{
-	union {
-		char buf[WLC_IOCTL_SMLEN];
-		int val;
-	} var;
-	int error;
-
-	uint len;
-	uint data_null;
-
-	len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
-	ASSERT(len);
-	error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
-
-	*retval = dtoh32(var.val);
-
-	return (error);
-}
-
-/* Maintain backward compatibility */
-#if WIRELESS_EXT < 13
-struct iw_request_info
-{
-	__u16		cmd;		/* Wireless Extension command */
-	__u16		flags;		/* More to come ;-) */
-};
-
-typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
-	void *wrqu, char *extra);
-#endif /* WIRELESS_EXT < 13 */
-
-#if WIRELESS_EXT > 12
-static int
-wl_iw_set_leddc(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra
-)
-{
-	int dc = *(int *)extra;
-	int error;
-
-	error = dev_wlc_intvar_set(dev, "leddc", dc);
-	return error;
-}
-
-static int
-wl_iw_set_vlanmode(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra
-)
-{
-	int mode = *(int *)extra;
-	int error;
-
-	mode = htod32(mode);
-	error = dev_wlc_intvar_set(dev, "vlan_mode", mode);
-	return error;
-}
-
-static int
-wl_iw_set_pm(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra
-)
-{
-	int pm = *(int *)extra;
-	int error;
-
-	pm = htod32(pm);
-	error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
-	return error;
-}
-
-#if WIRELESS_EXT > 17
-#endif /* WIRELESS_EXT > 17 */
-#endif /* WIRELESS_EXT > 12 */
-
-int
-wl_iw_send_priv_event(
-	struct net_device *dev,
-	char *flag
-)
-{
-	union iwreq_data wrqu;
-	char extra[IW_CUSTOM_MAX + 1];
-	int cmd;
-
-	cmd = IWEVCUSTOM;
-	memset(&wrqu, 0, sizeof(wrqu));
-	if (strlen(flag) > sizeof(extra))
-		return -1;
-
-	strncpy(extra, flag, sizeof(extra));
-	extra[sizeof(extra) - 1] = '\0';
-	wrqu.data.length = strlen(extra);
-	wireless_send_event(dev, cmd, &wrqu, extra);
-	WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
-
-	return 0;
-}
-
-static int
-wl_iw_config_commit(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	void *zwrq,
-	char *extra
-)
-{
-	wlc_ssid_t ssid;
-	int error;
-	struct sockaddr bssid;
-
-	WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name));
-
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid))))
-		return error;
-
-	ssid.SSID_len = dtoh32(ssid.SSID_len);
-
-	if (!ssid.SSID_len)
-		return 0;
-
-	bzero(&bssid, sizeof(struct sockaddr));
-	if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) {
-		WL_ERROR(("%s: WLC_REASSOC failed (%d)\n", __FUNCTION__, error));
-		return error;
-	}
-
-	return 0;
-}
-
-static int
-wl_iw_get_name(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *cwrq,
-	char *extra
-)
-{
-	int phytype, err;
-	uint band[3];
-	char cap[5];
-
-	WL_TRACE(("%s: SIOCGIWNAME\n", dev->name));
-
-	cap[0] = 0;
-	if ((err = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))) < 0)
-		goto done;
-	if ((err = dev_wlc_ioctl(dev, WLC_GET_BANDLIST, band, sizeof(band))) < 0)
-		goto done;
-
-	band[0] = dtoh32(band[0]);
-	switch (phytype) {
-		case WLC_PHY_TYPE_A:
-			strncpy(cap, "a", sizeof(cap));
-			break;
-		case WLC_PHY_TYPE_B:
-			strncpy(cap, "b", sizeof(cap));
-			break;
-		case WLC_PHY_TYPE_G:
-			if (band[0] >= 2)
-				strncpy(cap, "abg", sizeof(cap));
-			else
-				strncpy(cap, "bg", sizeof(cap));
-			break;
-		case WLC_PHY_TYPE_N:
-			if (band[0] >= 2)
-				strncpy(cap, "abgn", sizeof(cap));
-			else
-				strncpy(cap, "bgn", sizeof(cap));
-			break;
-	}
-done:
-	(void)snprintf(cwrq->name, IFNAMSIZ, "IEEE 802.11%s", cap);
-
-	return 0;
-}
-
-static int
-wl_iw_set_freq(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_freq *fwrq,
-	char *extra
-)
-{
-	int error, chan;
-	uint sf = 0;
-
-	WL_TRACE(("%s: SIOCSIWFREQ\n", dev->name));
-
-	/* Setting by channel number */
-	if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
-		chan = fwrq->m;
-	}
-
-	/* Setting by frequency */
-	else {
-		/* Convert to MHz as best we can */
-		if (fwrq->e >= 6) {
-			fwrq->e -= 6;
-			while (fwrq->e--)
-				fwrq->m *= 10;
-		} else if (fwrq->e < 6) {
-			while (fwrq->e++ < 6)
-				fwrq->m /= 10;
-		}
-	/* handle 4.9GHz frequencies as Japan 4 GHz based channelization */
-	if (fwrq->m > 4000 && fwrq->m < 5000)
-		sf = WF_CHAN_FACTOR_4_G; /* start factor for 4 GHz */
-
-		chan = wf_mhz2channel(fwrq->m, sf);
-	}
-	chan = htod32(chan);
-	if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
-		return error;
-
-	/* -EINPROGRESS: Call commit handler */
-	return -EINPROGRESS;
-}
-
-static int
-wl_iw_get_freq(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_freq *fwrq,
-	char *extra
-)
-{
-	channel_info_t ci;
-	int error;
-
-	WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
-
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
-		return error;
-
-	/* Return radio channel in channel form */
-	fwrq->m = dtoh32(ci.hw_channel);
-	fwrq->e = dtoh32(0);
-	return 0;
-}
-
-static int
-wl_iw_set_mode(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	__u32 *uwrq,
-	char *extra
-)
-{
-	int infra = 0, ap = 0, error = 0;
-
-	WL_TRACE(("%s: SIOCSIWMODE\n", dev->name));
-
-	switch (*uwrq) {
-	case IW_MODE_MASTER:
-		infra = ap = 1;
-		break;
-	case IW_MODE_ADHOC:
-	case IW_MODE_AUTO:
-		break;
-	case IW_MODE_INFRA:
-		infra = 1;
-		break;
-	default:
-		return -EINVAL;
-	}
-	infra = htod32(infra);
-	ap = htod32(ap);
-
-	if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) ||
-	    (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap))))
-		return error;
-
-	/* -EINPROGRESS: Call commit handler */
-	return -EINPROGRESS;
-}
-
-static int
-wl_iw_get_mode(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	__u32 *uwrq,
-	char *extra
-)
-{
-	int error, infra = 0, ap = 0;
-
-	WL_TRACE(("%s: SIOCGIWMODE\n", dev->name));
-
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) ||
-	    (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap))))
-		return error;
-
-	infra = dtoh32(infra);
-	ap = dtoh32(ap);
-	*uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
-
-	return 0;
-}
-
-static int
-wl_iw_get_range(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	struct iw_range *range = (struct iw_range *) extra;
-	static int channels[MAXCHANNEL+1];
-	wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
-	wl_rateset_t rateset;
-	int error, i, k;
-	uint sf, ch;
-
-	int phytype;
-	int bw_cap = 0, sgi_tx = 0, nmode = 0;
-	channel_info_t ci;
-	uint8 nrate_list2copy = 0;
-	uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
-		{14, 29, 43, 58, 87, 116, 130, 144},
-		{27, 54, 81, 108, 162, 216, 243, 270},
-		{30, 60, 90, 120, 180, 240, 270, 300}};
-	int fbt_cap = 0;
-
-	WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	dwrq->length = sizeof(struct iw_range);
-	memset(range, 0, sizeof(*range));
-
-	/* We don't use nwids */
-	range->min_nwid = range->max_nwid = 0;
-
-	/* Set available channels/frequencies */
-	list->count = htod32(MAXCHANNEL);
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels))))
-		return error;
-	for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
-		range->freq[i].i = dtoh32(list->element[i]);
-
-		ch = dtoh32(list->element[i]);
-		if (ch <= CH_MAX_2G_CHANNEL)
-			sf = WF_CHAN_FACTOR_2_4_G;
-		else
-			sf = WF_CHAN_FACTOR_5_G;
-
-		range->freq[i].m = wf_channel2mhz(ch, sf);
-		range->freq[i].e = 6;
-	}
-	range->num_frequency = range->num_channels = i;
-
-	/* Link quality (use NDIS cutoffs) */
-	range->max_qual.qual = 5;
-	/* Signal level (use RSSI) */
-	range->max_qual.level = 0x100 - 200;	/* -200 dBm */
-	/* Noise level (use noise) */
-	range->max_qual.noise = 0x100 - 200;	/* -200 dBm */
-	/* Signal level threshold range (?) */
-	range->sensitivity = 65535;
-
-#if WIRELESS_EXT > 11
-	/* Link quality (use NDIS cutoffs) */
-	range->avg_qual.qual = 3;
-	/* Signal level (use RSSI) */
-	range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD;
-	/* Noise level (use noise) */
-	range->avg_qual.noise = 0x100 - 75;	/* -75 dBm */
-#endif /* WIRELESS_EXT > 11 */
-
-	/* Set available bitrates */
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
-		return error;
-	rateset.count = dtoh32(rateset.count);
-	range->num_bitrates = rateset.count;
-	for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
-		range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000; /* convert to bps */
-	if ((error = dev_wlc_intvar_get(dev, "nmode", &nmode)))
-		return error;
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))))
-		return error;
-	if (nmode == 1 && (((phytype == WLC_PHY_TYPE_LCN) ||
-	                    (phytype == WLC_PHY_TYPE_LCN40)))) {
-		if ((error = dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap)))
-			return error;
-		if ((error = dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx)))
-			return error;
-		if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t))))
-			return error;
-		ci.hw_channel = dtoh32(ci.hw_channel);
-
-		if (bw_cap == 0 ||
-			(bw_cap == 2 && ci.hw_channel <= 14)) {
-			if (sgi_tx == 0)
-				nrate_list2copy = 0;
-			else
-				nrate_list2copy = 1;
-		}
-		if (bw_cap == 1 ||
-			(bw_cap == 2 && ci.hw_channel >= 36)) {
-			if (sgi_tx == 0)
-				nrate_list2copy = 2;
-			else
-				nrate_list2copy = 3;
-		}
-		range->num_bitrates += 8;
-		ASSERT(range->num_bitrates < IW_MAX_BITRATES);
-		for (k = 0; i < range->num_bitrates; k++, i++) {
-			/* convert to bps */
-			range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
-		}
-	}
-
-	/* Set an indication of the max TCP throughput
-	 * in bit/s that we can expect using this interface.
-	 * May be use for QoS stuff... Jean II
-	 */
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i))))
-		return error;
-	i = dtoh32(i);
-	if (i == WLC_PHY_TYPE_A)
-		range->throughput = 24000000;	/* 24 Mbits/s */
-	else
-		range->throughput = 1500000;	/* 1.5 Mbits/s */
-
-	/* RTS and fragmentation thresholds */
-	range->min_rts = 0;
-	range->max_rts = 2347;
-	range->min_frag = 256;
-	range->max_frag = 2346;
-
-	range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
-	range->num_encoding_sizes = 4;
-	range->encoding_size[0] = WEP1_KEY_SIZE;
-	range->encoding_size[1] = WEP128_KEY_SIZE;
-#if WIRELESS_EXT > 17
-	range->encoding_size[2] = TKIP_KEY_SIZE;
-#else
-	range->encoding_size[2] = 0;
-#endif
-	range->encoding_size[3] = AES_KEY_SIZE;
-
-	/* Do not support power micro-management */
-	range->min_pmp = 0;
-	range->max_pmp = 0;
-	range->min_pmt = 0;
-	range->max_pmt = 0;
-	range->pmp_flags = 0;
-	range->pm_capa = 0;
-
-	/* Transmit Power - values are in mW */
-	range->num_txpower = 2;
-	range->txpower[0] = 1;
-	range->txpower[1] = 255;
-	range->txpower_capa = IW_TXPOW_MWATT;
-
-#if WIRELESS_EXT > 10
-	range->we_version_compiled = WIRELESS_EXT;
-	range->we_version_source = 19;
-
-	/* Only support retry limits */
-	range->retry_capa = IW_RETRY_LIMIT;
-	range->retry_flags = IW_RETRY_LIMIT;
-	range->r_time_flags = 0;
-	/* SRL and LRL limits */
-	range->min_retry = 1;
-	range->max_retry = 255;
-	/* Retry lifetime limits unsupported */
-	range->min_r_time = 0;
-	range->max_r_time = 0;
-#endif /* WIRELESS_EXT > 10 */
-
-#if WIRELESS_EXT > 17
-	range->enc_capa = IW_ENC_CAPA_WPA;
-	range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
-	range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
-	range->enc_capa |= IW_ENC_CAPA_WPA2;
-
-	/* Determine driver FBT capability. */
-	if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) {
-		if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) {
-			/* Tell the host (e.g. wpa_supplicant) to let driver do the handshake */
-			range->enc_capa |= IW_ENC_CAPA_4WAY_HANDSHAKE;
-		}
-	}
-
-#ifdef BCMFW_ROAM_ENABLE_WEXT
-	/* Advertise firmware roam capability to the external supplicant */
-	range->enc_capa |= IW_ENC_CAPA_FW_ROAM_ENABLE;
-#endif /* BCMFW_ROAM_ENABLE_WEXT */
-
-	/* Event capability (kernel) */
-	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
-	/* Event capability (driver) */
-	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
-	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
-	IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
-	IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
-	IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
-	IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
-	IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
-
-#if WIRELESS_EXT >= 22 && defined(IW_SCAN_CAPA_ESSID)
-	/* FC7 wireless.h defines EXT 22 but doesn't define scan_capa bits */
-	range->scan_capa = IW_SCAN_CAPA_ESSID;
-#endif
-#endif /* WIRELESS_EXT > 17 */
-
-	return 0;
-}
-
-static int
-rssi_to_qual(int rssi)
-{
-	if (rssi <= WL_IW_RSSI_NO_SIGNAL)
-		return 0;
-	else if (rssi <= WL_IW_RSSI_VERY_LOW)
-		return 1;
-	else if (rssi <= WL_IW_RSSI_LOW)
-		return 2;
-	else if (rssi <= WL_IW_RSSI_GOOD)
-		return 3;
-	else if (rssi <= WL_IW_RSSI_VERY_GOOD)
-		return 4;
-	else
-		return 5;
-}
-
-static int
-wl_iw_set_spy(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_iw_t *iw = IW_DEV_IF(dev);
-	struct sockaddr *addr = (struct sockaddr *) extra;
-	int i;
-
-	WL_TRACE(("%s: SIOCSIWSPY\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length);
-	for (i = 0; i < iw->spy_num; i++)
-		memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN);
-	memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
-
-	return 0;
-}
-
-static int
-wl_iw_get_spy(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_iw_t *iw = IW_DEV_IF(dev);
-	struct sockaddr *addr = (struct sockaddr *) extra;
-	struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num];
-	int i;
-
-	WL_TRACE(("%s: SIOCGIWSPY\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	dwrq->length = iw->spy_num;
-	for (i = 0; i < iw->spy_num; i++) {
-		memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN);
-		addr[i].sa_family = AF_UNIX;
-		memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
-		iw->spy_qual[i].updated = 0;
-	}
-
-	return 0;
-}
-
-static int
-wl_iw_set_wap(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct sockaddr *awrq,
-	char *extra
-)
-{
-	int error = -EINVAL;
-
-	WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
-
-	if (awrq->sa_family != ARPHRD_ETHER) {
-		WL_ERROR(("%s: Invalid Header...sa_family\n", __FUNCTION__));
-		return -EINVAL;
-	}
-
-	/* Ignore "auto" or "off" */
-	if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
-		scb_val_t scbval;
-		bzero(&scbval, sizeof(scb_val_t));
-		if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) {
-			WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error));
-		}
-		return 0;
-	}
-	/* WL_ASSOC(("Assoc to %s\n", bcm_ether_ntoa((struct ether_addr *)&(awrq->sa_data),
-	 * eabuf)));
-	 */
-	/* Reassociate to the specified AP */
-	if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) {
-		WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error));
-		return error;
-	}
-
-	return 0;
-}
-
-static int
-wl_iw_get_wap(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct sockaddr *awrq,
-	char *extra
-)
-{
-	WL_TRACE(("%s: SIOCGIWAP\n", dev->name));
-
-	awrq->sa_family = ARPHRD_ETHER;
-	memset(awrq->sa_data, 0, ETHER_ADDR_LEN);
-
-	/* Ignore error (may be down or disassociated) */
-	(void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN);
-
-	return 0;
-}
-
-#if WIRELESS_EXT > 17
-static int
-wl_iw_mlme(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct sockaddr *awrq,
-	char *extra
-)
-{
-	struct iw_mlme *mlme;
-	scb_val_t scbval;
-	int error  = -EINVAL;
-
-	WL_TRACE(("%s: SIOCSIWMLME\n", dev->name));
-
-	mlme = (struct iw_mlme *)extra;
-	if (mlme == NULL) {
-		WL_ERROR(("Invalid ioctl data.\n"));
-		return error;
-	}
-
-	scbval.val = mlme->reason_code;
-	bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN);
-
-	if (mlme->cmd == IW_MLME_DISASSOC) {
-		scbval.val = htod32(scbval.val);
-		error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
-	}
-	else if (mlme->cmd == IW_MLME_DEAUTH) {
-		scbval.val = htod32(scbval.val);
-		error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
-			sizeof(scb_val_t));
-	}
-	else {
-		WL_ERROR(("%s: Invalid ioctl data.\n", __FUNCTION__));
-		return error;
-	}
-
-	return error;
-}
-#endif /* WIRELESS_EXT > 17 */
-
-static int
-wl_iw_get_aplist(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_scan_results_t *list;
-	struct sockaddr *addr = (struct sockaddr *) extra;
-	struct iw_quality qual[IW_MAX_AP];
-	wl_bss_info_t *bi = NULL;
-	int error, i;
-	uint buflen = dwrq->length;
-
-	WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	/* Get scan results (too large to put on the stack) */
-	list = kmalloc(buflen, GFP_KERNEL);
-	if (!list)
-		return -ENOMEM;
-	memset(list, 0, buflen);
-	list->buflen = htod32(buflen);
-	if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
-		WL_ERROR(("%d: Scan results error %d\n", __LINE__, error));
-		kfree(list);
-		return error;
-	}
-	list->buflen = dtoh32(list->buflen);
-	list->version = dtoh32(list->version);
-	list->count = dtoh32(list->count);
-	ASSERT(list->version == WL_BSS_INFO_VERSION);
-
-	for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
-		bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
-		ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
-			buflen));
-
-		/* Infrastructure only */
-		if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
-			continue;
-
-		/* BSSID */
-		memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
-		addr[dwrq->length].sa_family = ARPHRD_ETHER;
-		qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
-		qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
-		qual[dwrq->length].noise = 0x100 + bi->phy_noise;
-
-		/* Updated qual, level, and noise */
-#if WIRELESS_EXT > 18
-		qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-#else
-		qual[dwrq->length].updated = 7;
-#endif /* WIRELESS_EXT > 18 */
-
-		dwrq->length++;
-	}
-
-	kfree(list);
-
-	if (dwrq->length) {
-		memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
-		/* Provided qual */
-		dwrq->flags = 1;
-	}
-
-	return 0;
-}
-
-static int
-wl_iw_iscan_get_aplist(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_scan_results_t *list;
-	iscan_buf_t * buf;
-	iscan_info_t *iscan = g_iscan;
-
-	struct sockaddr *addr = (struct sockaddr *) extra;
-	struct iw_quality qual[IW_MAX_AP];
-	wl_bss_info_t *bi = NULL;
-	int i;
-
-	WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	if ((!iscan) || (iscan->sysioc_pid < 0)) {
-		return wl_iw_get_aplist(dev, info, dwrq, extra);
-	}
-
-	buf = iscan->list_hdr;
-	/* Get scan results (too large to put on the stack) */
-	while (buf) {
-	    list = &((wl_iscan_results_t*)buf->iscan_buf)->results;
-	    ASSERT(list->version == WL_BSS_INFO_VERSION);
-
-	    bi = NULL;
-	for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
-		bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
-		ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
-			WLC_IW_ISCAN_MAXLEN));
-
-		/* Infrastructure only */
-		if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
-			continue;
-
-		/* BSSID */
-		memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
-		addr[dwrq->length].sa_family = ARPHRD_ETHER;
-		qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
-		qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
-		qual[dwrq->length].noise = 0x100 + bi->phy_noise;
-
-		/* Updated qual, level, and noise */
-#if WIRELESS_EXT > 18
-		qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-#else
-		qual[dwrq->length].updated = 7;
-#endif /* WIRELESS_EXT > 18 */
-
-		dwrq->length++;
-	    }
-	    buf = buf->next;
-	}
-	if (dwrq->length) {
-		memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
-		/* Provided qual */
-		dwrq->flags = 1;
-	}
-
-	return 0;
-}
-
-#if WIRELESS_EXT > 13
-static int
-wl_iw_set_scan(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra
-)
-{
-	wlc_ssid_t ssid;
-
-	WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
-
-	/* default Broadcast scan */
-	memset(&ssid, 0, sizeof(ssid));
-
-#if WIRELESS_EXT > 17
-	/* check for given essid */
-	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
-		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
-			struct iw_scan_req *req = (struct iw_scan_req *)extra;
-			ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
-			memcpy(ssid.SSID, req->essid, ssid.SSID_len);
-			ssid.SSID_len = htod32(ssid.SSID_len);
-		}
-	}
-#endif
-	/* Ignore error (most likely scan in progress) */
-	(void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid));
-
-	return 0;
-}
-
-static int
-wl_iw_iscan_set_scan(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	union iwreq_data *wrqu,
-	char *extra
-)
-{
-	wlc_ssid_t ssid;
-	iscan_info_t *iscan = g_iscan;
-
-	WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
-
-	/* use backup if our thread is not successful */
-	if ((!iscan) || (iscan->sysioc_pid < 0)) {
-		return wl_iw_set_scan(dev, info, wrqu, extra);
-	}
-	if (iscan->iscan_state == ISCAN_STATE_SCANING) {
-		return 0;
-	}
-
-	/* default Broadcast scan */
-	memset(&ssid, 0, sizeof(ssid));
-
-#if WIRELESS_EXT > 17
-	/* check for given essid */
-	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
-		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
-			struct iw_scan_req *req = (struct iw_scan_req *)extra;
-			ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
-			memcpy(ssid.SSID, req->essid, ssid.SSID_len);
-			ssid.SSID_len = htod32(ssid.SSID_len);
-		}
-	}
-#endif
-
-	iscan->list_cur = iscan->list_hdr;
-	iscan->iscan_state = ISCAN_STATE_SCANING;
-
-
-	wl_iw_set_event_mask(dev);
-	wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
-
-	iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
-	add_timer(&iscan->timer);
-	iscan->timer_on = 1;
-
-	return 0;
-}
-
-#if WIRELESS_EXT > 17
-static bool
-ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len)
-{
-/* Is this body of this tlvs entry a WPA entry? If */
-/* not update the tlvs buffer pointer/length */
-	uint8 *ie = *wpaie;
-
-	/* If the contents match the WPA_OUI and type=1 */
-	if ((ie[1] >= 6) &&
-		!bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) {
-		return TRUE;
-	}
-
-	/* point to the next ie */
-	ie += ie[1] + 2;
-	/* calculate the length of the rest of the buffer */
-	*tlvs_len -= (int)(ie - *tlvs);
-	/* update the pointer to the start of the buffer */
-	*tlvs = ie;
-	return FALSE;
-}
-
-static bool
-ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
-{
-/* Is this body of this tlvs entry a WPS entry? If */
-/* not update the tlvs buffer pointer/length */
-	uint8 *ie = *wpsie;
-
-	/* If the contents match the WPA_OUI and type=4 */
-	if ((ie[1] >= 4) &&
-		!bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) {
-		return TRUE;
-	}
-
-	/* point to the next ie */
-	ie += ie[1] + 2;
-	/* calculate the length of the rest of the buffer */
-	*tlvs_len -= (int)(ie - *tlvs);
-	/* update the pointer to the start of the buffer */
-	*tlvs = ie;
-	return FALSE;
-}
-#endif /* WIRELESS_EXT > 17 */
-
-
-static int
-wl_iw_handle_scanresults_ies(char **event_p, char *end,
-	struct iw_request_info *info, wl_bss_info_t *bi)
-{
-#if WIRELESS_EXT > 17
-	struct iw_event	iwe;
-	char *event;
-
-	event = *event_p;
-	if (bi->ie_length) {
-		/* look for wpa/rsn ies in the ie list... */
-		bcm_tlv_t *ie;
-		uint8 *ptr = ((uint8 *)bi) + bi->ie_offset;
-		int ptr_len = bi->ie_length;
-
-		/* OSEN IE */
-		if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_VS_ID)) &&
-			ie->len > WFA_OUI_LEN + 1 &&
-			!bcmp((const void *)&ie->data[0], (const void *)WFA_OUI, WFA_OUI_LEN) &&
-			ie->data[WFA_OUI_LEN] == WFA_OUI_TYPE_OSEN) {
-			iwe.cmd = IWEVGENIE;
-			iwe.u.data.length = ie->len + 2;
-			event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
-		}
-		ptr = ((uint8 *)bi) + bi->ie_offset;
-
-		if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
-			iwe.cmd = IWEVGENIE;
-			iwe.u.data.length = ie->len + 2;
-			event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
-		}
-		ptr = ((uint8 *)bi) + bi->ie_offset;
-
-		if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_MDIE_ID))) {
-			iwe.cmd = IWEVGENIE;
-			iwe.u.data.length = ie->len + 2;
-			event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
-		}
-		ptr = ((uint8 *)bi) + bi->ie_offset;
-
-		while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
-			/* look for WPS IE */
-			if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
-				iwe.cmd = IWEVGENIE;
-				iwe.u.data.length = ie->len + 2;
-				event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
-				break;
-			}
-		}
-
-		ptr = ((uint8 *)bi) + bi->ie_offset;
-		ptr_len = bi->ie_length;
-		while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
-			if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
-				iwe.cmd = IWEVGENIE;
-				iwe.u.data.length = ie->len + 2;
-				event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
-				break;
-			}
-		}
-
-	*event_p = event;
-	}
-
-#endif /* WIRELESS_EXT > 17 */
-	return 0;
-}
-static int
-wl_iw_get_scan(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	channel_info_t ci;
-	wl_scan_results_t *list;
-	struct iw_event	iwe;
-	wl_bss_info_t *bi = NULL;
-	int error, i, j;
-	char *event = extra, *end = extra + dwrq->length, *value;
-	uint buflen = dwrq->length;
-
-	WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	/* Check for scan in progress */
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
-		return error;
-	ci.scan_channel = dtoh32(ci.scan_channel);
-	if (ci.scan_channel)
-		return -EAGAIN;
-
-	/* Get scan results (too large to put on the stack) */
-	list = kmalloc(buflen, GFP_KERNEL);
-	if (!list)
-		return -ENOMEM;
-	memset(list, 0, buflen);
-	list->buflen = htod32(buflen);
-	if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
-		kfree(list);
-		return error;
-	}
-	list->buflen = dtoh32(list->buflen);
-	list->version = dtoh32(list->version);
-	list->count = dtoh32(list->count);
-
-	ASSERT(list->version == WL_BSS_INFO_VERSION);
-
-	for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
-		bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
-		ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
-			buflen));
-
-		/* First entry must be the BSSID */
-		iwe.cmd = SIOCGIWAP;
-		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-		memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
-		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
-
-		/* SSID */
-		iwe.u.data.length = dtoh32(bi->SSID_len);
-		iwe.cmd = SIOCGIWESSID;
-		iwe.u.data.flags = 1;
-		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
-
-		/* Mode */
-		if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
-			iwe.cmd = SIOCGIWMODE;
-			if (dtoh16(bi->capability) & DOT11_CAP_ESS)
-				iwe.u.mode = IW_MODE_INFRA;
-			else
-				iwe.u.mode = IW_MODE_ADHOC;
-			event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
-		}
-
-		/* Channel */
-		iwe.cmd = SIOCGIWFREQ;
-
-		iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
-			(CHSPEC_IS2G(bi->chanspec)) ?
-			WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
-		iwe.u.freq.e = 6;
-		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
-
-		/* Channel quality */
-		iwe.cmd = IWEVQUAL;
-		iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
-		iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
-		iwe.u.qual.noise = 0x100 + bi->phy_noise;
-		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
-
-		 wl_iw_handle_scanresults_ies(&event, end, info, bi);
-
-		/* Encryption */
-		iwe.cmd = SIOCGIWENCODE;
-		if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
-			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-		else
-			iwe.u.data.flags = IW_ENCODE_DISABLED;
-		iwe.u.data.length = 0;
-		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
-
-		/* Rates */
-		if (bi->rateset.count) {
-			value = event + IW_EV_LCP_LEN;
-			iwe.cmd = SIOCGIWRATE;
-			/* Those two flags are ignored... */
-			iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-			for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
-				iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
-				value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
-					IW_EV_PARAM_LEN);
-			}
-			event = value;
-		}
-	}
-
-	kfree(list);
-
-	dwrq->length = event - extra;
-	dwrq->flags = 0;	/* todo */
-
-	return 0;
-}
-
-static int
-wl_iw_iscan_get_scan(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_scan_results_t *list;
-	struct iw_event	iwe;
-	wl_bss_info_t *bi = NULL;
-	int ii, j;
-	int apcnt;
-	char *event = extra, *end = extra + dwrq->length, *value;
-	iscan_info_t *iscan = g_iscan;
-	iscan_buf_t * p_buf;
-
-	WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	/* use backup if our thread is not successful */
-	if ((!iscan) || (iscan->sysioc_pid < 0)) {
-		return wl_iw_get_scan(dev, info, dwrq, extra);
-	}
-
-	/* Check for scan in progress */
-	if (iscan->iscan_state == ISCAN_STATE_SCANING)
-		return -EAGAIN;
-
-	apcnt = 0;
-	p_buf = iscan->list_hdr;
-	/* Get scan results */
-	while (p_buf != iscan->list_cur) {
-	    list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
-
-	    if (list->version != WL_BSS_INFO_VERSION) {
-		WL_ERROR(("list->version %d != WL_BSS_INFO_VERSION\n", list->version));
-	    }
-
-	    bi = NULL;
-	    for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
-		bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
-		ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
-			WLC_IW_ISCAN_MAXLEN));
-
-		/* overflow check cover fields before wpa IEs */
-		if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
-			IW_EV_QUAL_LEN >= end)
-			return -E2BIG;
-		/* First entry must be the BSSID */
-		iwe.cmd = SIOCGIWAP;
-		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-		memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
-		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
-
-		/* SSID */
-		iwe.u.data.length = dtoh32(bi->SSID_len);
-		iwe.cmd = SIOCGIWESSID;
-		iwe.u.data.flags = 1;
-		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
-
-		/* Mode */
-		if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
-			iwe.cmd = SIOCGIWMODE;
-			if (dtoh16(bi->capability) & DOT11_CAP_ESS)
-				iwe.u.mode = IW_MODE_INFRA;
-			else
-				iwe.u.mode = IW_MODE_ADHOC;
-			event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
-		}
-
-		/* Channel */
-		iwe.cmd = SIOCGIWFREQ;
-
-		iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
-			(CHSPEC_IS2G(bi->chanspec)) ?
-			WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
-		iwe.u.freq.e = 6;
-		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
-
-		/* Channel quality */
-		iwe.cmd = IWEVQUAL;
-		iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
-		iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
-		iwe.u.qual.noise = 0x100 + bi->phy_noise;
-		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
-
-		wl_iw_handle_scanresults_ies(&event, end, info, bi);
-
-		/* Encryption */
-		iwe.cmd = SIOCGIWENCODE;
-		if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
-			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-		else
-			iwe.u.data.flags = IW_ENCODE_DISABLED;
-		iwe.u.data.length = 0;
-		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
-
-		/* Rates */
-		if (bi->rateset.count <= sizeof(bi->rateset.rates)) {
-			if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
-				return -E2BIG;
-
-			value = event + IW_EV_LCP_LEN;
-			iwe.cmd = SIOCGIWRATE;
-			/* Those two flags are ignored... */
-			iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-			for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
-				iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
-				value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
-					IW_EV_PARAM_LEN);
-			}
-			event = value;
-		}
-	    }
-	    p_buf = p_buf->next;
-	} /* while (p_buf) */
-
-	dwrq->length = event - extra;
-	dwrq->flags = 0;	/* todo */
-
-	return 0;
-}
-
-#endif /* WIRELESS_EXT > 13 */
-
-
-static int
-wl_iw_set_essid(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wlc_ssid_t ssid;
-	int error;
-
-	WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
-
-	/* default Broadcast SSID */
-	memset(&ssid, 0, sizeof(ssid));
-	if (dwrq->length && extra) {
-#if WIRELESS_EXT > 20
-		ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length);
-#else
-		ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1);
-#endif
-		memcpy(ssid.SSID, extra, ssid.SSID_len);
-		ssid.SSID_len = htod32(ssid.SSID_len);
-
-		if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))
-			return error;
-	}
-	/* If essid null then it is "iwconfig <interface> essid off" command */
-	else {
-		scb_val_t scbval;
-		bzero(&scbval, sizeof(scb_val_t));
-		if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t))))
-			return error;
-	}
-	return 0;
-}
-
-static int
-wl_iw_get_essid(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wlc_ssid_t ssid;
-	int error;
-
-	WL_TRACE(("%s: SIOCGIWESSID\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) {
-		WL_ERROR(("Error getting the SSID\n"));
-		return error;
-	}
-
-	ssid.SSID_len = dtoh32(ssid.SSID_len);
-
-	/* Get the current SSID */
-	memcpy(extra, ssid.SSID, ssid.SSID_len);
-
-	dwrq->length = ssid.SSID_len;
-
-	dwrq->flags = 1; /* active */
-
-	return 0;
-}
-
-static int
-wl_iw_set_nick(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_iw_t *iw = IW_DEV_IF(dev);
-	WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	/* Check the size of the string */
-	if (dwrq->length > sizeof(iw->nickname))
-		return -E2BIG;
-
-	memcpy(iw->nickname, extra, dwrq->length);
-	iw->nickname[dwrq->length - 1] = '\0';
-
-	return 0;
-}
-
-static int
-wl_iw_get_nick(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_iw_t *iw = IW_DEV_IF(dev);
-	WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name));
-
-	if (!extra)
-		return -EINVAL;
-
-	strcpy(extra, iw->nickname);
-	dwrq->length = strlen(extra) + 1;
-
-	return 0;
-}
-
-static int wl_iw_set_rate(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	wl_rateset_t rateset;
-	int error, rate, i, error_bg, error_a;
-
-	WL_TRACE(("%s: SIOCSIWRATE\n", dev->name));
-
-	/* Get current rateset */
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
-		return error;
-
-	rateset.count = dtoh32(rateset.count);
-
-	if (vwrq->value < 0) {
-		/* Select maximum rate */
-		rate = rateset.rates[rateset.count - 1] & 0x7f;
-	} else if (vwrq->value < rateset.count) {
-		/* Select rate by rateset index */
-		rate = rateset.rates[vwrq->value] & 0x7f;
-	} else {
-		/* Specified rate in bps */
-		rate = vwrq->value / 500000;
-	}
-
-	if (vwrq->fixed) {
-		/*
-			Set rate override,
-			Since the is a/b/g-blind, both a/bg_rate are enforced.
-		*/
-		error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate);
-		error_a = dev_wlc_intvar_set(dev, "a_rate", rate);
-
-		if (error_bg && error_a)
-			return (error_bg | error_a);
-	} else {
-		/*
-			clear rate override
-			Since the is a/b/g-blind, both a/bg_rate are enforced.
-		*/
-		/* 0 is for clearing rate override */
-		error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0);
-		/* 0 is for clearing rate override */
-		error_a = dev_wlc_intvar_set(dev, "a_rate", 0);
-
-		if (error_bg && error_a)
-			return (error_bg | error_a);
-
-		/* Remove rates above selected rate */
-		for (i = 0; i < rateset.count; i++)
-			if ((rateset.rates[i] & 0x7f) > rate)
-				break;
-		rateset.count = htod32(i);
-
-		/* Set current rateset */
-		if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset))))
-			return error;
-	}
-
-	return 0;
-}
-
-static int wl_iw_get_rate(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, rate;
-
-	WL_TRACE(("%s: SIOCGIWRATE\n", dev->name));
-
-	/* Report the current tx rate */
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate))))
-		return error;
-	rate = dtoh32(rate);
-	vwrq->value = rate * 500000;
-
-	return 0;
-}
-
-static int
-wl_iw_set_rts(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, rts;
-
-	WL_TRACE(("%s: SIOCSIWRTS\n", dev->name));
-
-	if (vwrq->disabled)
-		rts = DOT11_DEFAULT_RTS_LEN;
-	else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN)
-		return -EINVAL;
-	else
-		rts = vwrq->value;
-
-	if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts)))
-		return error;
-
-	return 0;
-}
-
-static int
-wl_iw_get_rts(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, rts;
-
-	WL_TRACE(("%s: SIOCGIWRTS\n", dev->name));
-
-	if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts)))
-		return error;
-
-	vwrq->value = rts;
-	vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN);
-	vwrq->fixed = 1;
-
-	return 0;
-}
-
-static int
-wl_iw_set_frag(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, frag;
-
-	WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name));
-
-	if (vwrq->disabled)
-		frag = DOT11_DEFAULT_FRAG_LEN;
-	else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN)
-		return -EINVAL;
-	else
-		frag = vwrq->value;
-
-	if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag)))
-		return error;
-
-	return 0;
-}
-
-static int
-wl_iw_get_frag(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, fragthreshold;
-
-	WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name));
-
-	if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold)))
-		return error;
-
-	vwrq->value = fragthreshold;
-	vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN);
-	vwrq->fixed = 1;
-
-	return 0;
-}
-
-static int
-wl_iw_set_txpow(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, disable;
-	uint16 txpwrmw;
-	WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name));
-
-	/* Make sure radio is off or on as far as software is concerned */
-	disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
-	disable += WL_RADIO_SW_DISABLE << 16;
-
-	disable = htod32(disable);
-	if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable))))
-		return error;
-
-	/* If Radio is off, nothing more to do */
-	if (disable & WL_RADIO_SW_DISABLE)
-		return 0;
-
-	/* Only handle mW */
-	if (!(vwrq->flags & IW_TXPOW_MWATT))
-		return -EINVAL;
-
-	/* Value < 0 means just "on" or "off" */
-	if (vwrq->value < 0)
-		return 0;
-
-	if (vwrq->value > 0xffff) txpwrmw = 0xffff;
-	else txpwrmw = (uint16)vwrq->value;
-
-
-	error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
-	return error;
-}
-
-static int
-wl_iw_get_txpow(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, disable, txpwrdbm;
-	uint8 result;
-
-	WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name));
-
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) ||
-	    (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm)))
-		return error;
-
-	disable = dtoh32(disable);
-	result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE);
-	vwrq->value = (int32)bcm_qdbm_to_mw(result);
-	vwrq->fixed = 0;
-	vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0;
-	vwrq->flags = IW_TXPOW_MWATT;
-
-	return 0;
-}
-
-#if WIRELESS_EXT > 10
-static int
-wl_iw_set_retry(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, lrl, srl;
-
-	WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name));
-
-	/* Do not handle "off" or "lifetime" */
-	if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME))
-		return -EINVAL;
-
-	/* Handle "[min|max] limit" */
-	if (vwrq->flags & IW_RETRY_LIMIT) {
-		/* "max limit" or just "limit" */
-#if WIRELESS_EXT > 20
-		if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) ||
-			!((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) {
-#else
-		if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
-#endif /* WIRELESS_EXT > 20 */
-
-			lrl = htod32(vwrq->value);
-			if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl))))
-				return error;
-		}
-		/* "min limit" or just "limit" */
-#if WIRELESS_EXT > 20
-		if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) ||
-			!((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) {
-#else
-		if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) {
-#endif /* WIRELESS_EXT > 20 */
-
-			srl = htod32(vwrq->value);
-			if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl))))
-				return error;
-		}
-	}
-
-	return 0;
-}
-
-static int
-wl_iw_get_retry(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, lrl, srl;
-
-	WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name));
-
-	vwrq->disabled = 0;      /* Can't be disabled */
-
-	/* Do not handle lifetime queries */
-	if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
-		return -EINVAL;
-
-	/* Get retry limits */
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) ||
-	    (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl))))
-		return error;
-
-	lrl = dtoh32(lrl);
-	srl = dtoh32(srl);
-
-	/* Note : by default, display the min retry number */
-	if (vwrq->flags & IW_RETRY_MAX) {
-		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-		vwrq->value = lrl;
-	} else {
-		vwrq->flags = IW_RETRY_LIMIT;
-		vwrq->value = srl;
-		if (srl != lrl)
-			vwrq->flags |= IW_RETRY_MIN;
-	}
-
-	return 0;
-}
-#endif /* WIRELESS_EXT > 10 */
-
-static int
-wl_iw_set_encode(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_wsec_key_t key;
-	int error, val, wsec;
-
-	WL_TRACE(("%s: SIOCSIWENCODE\n", dev->name));
-
-	memset(&key, 0, sizeof(key));
-
-	if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
-		/* Find the current key */
-		for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
-			val = htod32(key.index);
-			if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
-				return error;
-			val = dtoh32(val);
-			if (val)
-				break;
-		}
-		/* Default to 0 */
-		if (key.index == DOT11_MAX_DEFAULT_KEYS)
-			key.index = 0;
-	} else {
-		key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-		if (key.index >= DOT11_MAX_DEFAULT_KEYS)
-			return -EINVAL;
-	}
-
-	/* Interpret "off" to mean no encryption */
-	wsec = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED;
-
-	if ((error = dev_wlc_intvar_set(dev, "wsec", wsec)))
-		return error;
-
-	/* Old API used to pass a NULL pointer instead of IW_ENCODE_NOKEY */
-	if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
-		/* Just select a new current key */
-		val = htod32(key.index);
-		if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val))))
-			return error;
-	} else {
-		key.len = dwrq->length;
-
-		if (dwrq->length > sizeof(key.data))
-			return -EINVAL;
-
-		memcpy(key.data, extra, dwrq->length);
-
-		key.flags = WL_PRIMARY_KEY;
-		switch (key.len) {
-		case WEP1_KEY_SIZE:
-			key.algo = CRYPTO_ALGO_WEP1;
-			break;
-		case WEP128_KEY_SIZE:
-			key.algo = CRYPTO_ALGO_WEP128;
-			break;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
-		case TKIP_KEY_SIZE:
-			key.algo = CRYPTO_ALGO_TKIP;
-			break;
-#endif
-		case AES_KEY_SIZE:
-			key.algo = CRYPTO_ALGO_AES_CCM;
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		/* Set the new key/index */
-		swap_key_from_BE(&key);
-		if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))
-			return error;
-	}
-
-	/* Interpret "restricted" to mean shared key authentication */
-	val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
-	val = htod32(val);
-	if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))
-		return error;
-
-	return 0;
-}
-
-static int
-wl_iw_get_encode(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_wsec_key_t key;
-	int error, val, wsec, auth;
-
-	WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name));
-
-	/* assure default values of zero for things we don't touch */
-	bzero(&key, sizeof(wl_wsec_key_t));
-
-	if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
-		/* Find the current key */
-		for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
-			val = key.index;
-			if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
-				return error;
-			val = dtoh32(val);
-			if (val)
-				break;
-		}
-	} else
-		key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-
-	if (key.index >= DOT11_MAX_DEFAULT_KEYS)
-		key.index = 0;
-
-	/* Get info */
-
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) ||
-	    (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth))))
-		return error;
-
-	swap_key_to_BE(&key);
-
-	wsec = dtoh32(wsec);
-	auth = dtoh32(auth);
-	/* Get key length */
-	dwrq->length = MIN(IW_ENCODING_TOKEN_MAX, key.len);
-
-	/* Get flags */
-	dwrq->flags = key.index + 1;
-	if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) {
-		/* Interpret "off" to mean no encryption */
-		dwrq->flags |= IW_ENCODE_DISABLED;
-	}
-	if (auth) {
-		/* Interpret "restricted" to mean shared key authentication */
-		dwrq->flags |= IW_ENCODE_RESTRICTED;
-	}
-
-	/* Get key */
-	if (dwrq->length && extra)
-		memcpy(extra, key.data, dwrq->length);
-
-	return 0;
-}
-
-static int
-wl_iw_set_power(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, pm;
-
-	WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name));
-
-	pm = vwrq->disabled ? PM_OFF : PM_MAX;
-
-	pm = htod32(pm);
-	if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))
-		return error;
-
-	return 0;
-}
-
-static int
-wl_iw_get_power(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error, pm;
-
-	WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name));
-
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))))
-		return error;
-
-	pm = dtoh32(pm);
-	vwrq->disabled = pm ? 0 : 1;
-	vwrq->flags = IW_POWER_ALL_R;
-
-	return 0;
-}
-
-#if WIRELESS_EXT > 17
-static int
-wl_iw_set_wpaie(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *iwp,
-	char *extra
-)
-{
-		dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
-
-	return 0;
-}
-
-static int
-wl_iw_get_wpaie(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *iwp,
-	char *extra
-)
-{
-	WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name));
-	iwp->length = 64;
-	dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
-	return 0;
-}
-
-static int
-wl_iw_set_encodeext(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_point *dwrq,
-	char *extra
-)
-{
-	wl_wsec_key_t key;
-	int error;
-	struct iw_encode_ext *iwe;
-
-	WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name));
-
-	memset(&key, 0, sizeof(key));
-	iwe = (struct iw_encode_ext *)extra;
-
-	/* disable encryption completely  */
-	if (dwrq->flags & IW_ENCODE_DISABLED) {
-
-	}
-
-	/* get the key index */
-	key.index = 0;
-	if (dwrq->flags & IW_ENCODE_INDEX)
-		key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-
-	key.len = iwe->key_len;
-
-	/* Instead of bcast for ea address for default wep keys, driver needs it to be Null */
-	if (!ETHER_ISMULTI(iwe->addr.sa_data))
-		bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN);
-
-	/* check for key index change */
-	if (key.len == 0) {
-		if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
-			WL_WSEC(("Changing the the primary Key to %d\n", key.index));
-			/* change the key index .... */
-			key.index = htod32(key.index);
-			error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
-				&key.index, sizeof(key.index));
-			if (error)
-				return error;
-		}
-		/* key delete */
-		else {
-			swap_key_from_BE(&key);
-			error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
-			if (error)
-				return error;
-		}
-	}
-	/* This case is used to allow an external 802.1x supplicant
-	 * to pass the PMK to the in-driver supplicant for use in
-	 * the 4-way handshake.
-	 */
-	else if (iwe->alg == IW_ENCODE_ALG_PMK) {
-		int j;
-		wsec_pmk_t pmk;
-		char keystring[WSEC_MAX_PSK_LEN + 1];
-		char* charptr = keystring;
-		uint len;
-
-		/* copy the raw hex key to the appropriate format */
-		for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) {
-			(void)snprintf(charptr, 3, "%02x", iwe->key[j]);
-			charptr += 2;
-		}
-		len = strlen(keystring);
-		pmk.key_len = htod16(len);
-		bcopy(keystring, pmk.key, len);
-		pmk.flags = htod16(WSEC_PASSPHRASE);
-
-		error = dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk));
-		if (error)
-			return error;
-	}
-
-	else {
-		if (iwe->key_len > sizeof(key.data))
-			return -EINVAL;
-
-		WL_WSEC(("Setting the key index %d\n", key.index));
-		if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
-			WL_WSEC(("key is a Primary Key\n"));
-			key.flags = WL_PRIMARY_KEY;
-		}
-
-		bcopy((void *)iwe->key, key.data, iwe->key_len);
-
-		if (iwe->alg == IW_ENCODE_ALG_TKIP) {
-			uint8 keybuf[8];
-			bcopy(&key.data[24], keybuf, sizeof(keybuf));
-			bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
-			bcopy(keybuf, &key.data[16], sizeof(keybuf));
-		}
-
-		/* rx iv */
-		if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
-			uchar *ivptr;
-			ivptr = (uchar *)iwe->rx_seq;
-			key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
-				(ivptr[3] << 8) | ivptr[2];
-			key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
-			key.iv_initialized = TRUE;
-		}
-
-		switch (iwe->alg) {
-			case IW_ENCODE_ALG_NONE:
-				key.algo = CRYPTO_ALGO_OFF;
-				break;
-			case IW_ENCODE_ALG_WEP:
-				if (iwe->key_len == WEP1_KEY_SIZE)
-					key.algo = CRYPTO_ALGO_WEP1;
-				else
-					key.algo = CRYPTO_ALGO_WEP128;
-				break;
-			case IW_ENCODE_ALG_TKIP:
-				key.algo = CRYPTO_ALGO_TKIP;
-				break;
-			case IW_ENCODE_ALG_CCMP:
-				key.algo = CRYPTO_ALGO_AES_CCM;
-				break;
-			default:
-				break;
-		}
-		swap_key_from_BE(&key);
-
-		dhd_wait_pend8021x(dev);
-
-		error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
-		if (error)
-			return error;
-	}
-	return 0;
-}
-
-
-#if WIRELESS_EXT > 17
-struct {
-	pmkid_list_t pmkids;
-	pmkid_t foo[MAXPMKID-1];
-} pmkid_list;
-static int
-wl_iw_set_pmksa(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	struct iw_pmksa *iwpmksa;
-	uint i;
-	char eabuf[ETHER_ADDR_STR_LEN];
-	pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid;
-
-	WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name));
-	iwpmksa = (struct iw_pmksa *)extra;
-	bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
-	if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
-		WL_TRACE(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
-		bzero((char *)&pmkid_list, sizeof(pmkid_list));
-	}
-	if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
-		pmkid_list_t pmkid, *pmkidptr;
-		pmkidptr = &pmkid;
-		bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
-		bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
-		{
-			uint j;
-			WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
-				bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID,
-				eabuf)));
-			for (j = 0; j < WPA2_PMKID_LEN; j++)
-				WL_TRACE(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
-			WL_TRACE(("\n"));
-		}
-		for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
-			if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID,
-				ETHER_ADDR_LEN))
-				break;
-		for (; i < pmkid_list.pmkids.npmkid; i++) {
-			bcopy(&pmkid_array[i+1].BSSID,
-				&pmkid_array[i].BSSID,
-				ETHER_ADDR_LEN);
-			bcopy(&pmkid_array[i+1].PMKID,
-				&pmkid_array[i].PMKID,
-				WPA2_PMKID_LEN);
-		}
-		pmkid_list.pmkids.npmkid--;
-	}
-	if (iwpmksa->cmd == IW_PMKSA_ADD) {
-		bcopy(&iwpmksa->bssid.sa_data[0],
-			&pmkid_array[pmkid_list.pmkids.npmkid].BSSID,
-			ETHER_ADDR_LEN);
-		bcopy(&iwpmksa->pmkid[0], &pmkid_array[pmkid_list.pmkids.npmkid].PMKID,
-			WPA2_PMKID_LEN);
-		{
-			uint j;
-			uint k;
-			k = pmkid_list.pmkids.npmkid;
-			BCM_REFERENCE(k);
-			WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
-				bcm_ether_ntoa(&pmkid_array[k].BSSID,
-				eabuf)));
-			for (j = 0; j < WPA2_PMKID_LEN; j++)
-				WL_TRACE(("%02x ", pmkid_array[k].PMKID[j]));
-			WL_TRACE(("\n"));
-		}
-		pmkid_list.pmkids.npmkid++;
-	}
-	WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid));
-	for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
-		uint j;
-		WL_TRACE(("PMKID[%d]: %s = ", i,
-			bcm_ether_ntoa(&pmkid_array[i].BSSID,
-			eabuf)));
-		for (j = 0; j < WPA2_PMKID_LEN; j++)
-			WL_TRACE(("%02x ", pmkid_array[i].PMKID[j]));
-		printf("\n");
-	}
-	WL_TRACE(("\n"));
-	dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list));
-	return 0;
-}
-#endif /* WIRELESS_EXT > 17 */
-
-static int
-wl_iw_get_encodeext(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name));
-	return 0;
-}
-
-static int
-wl_iw_set_wpaauth(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error = 0;
-	int paramid;
-	int paramval;
-	uint32 cipher_combined;
-	int val = 0;
-	wl_iw_t *iw = IW_DEV_IF(dev);
-
-	WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name));
-
-	paramid = vwrq->flags & IW_AUTH_INDEX;
-	paramval = vwrq->value;
-
-	WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
-		dev->name, paramid, paramval));
-
-	switch (paramid) {
-
-	case IW_AUTH_WPA_VERSION:
-		/* supported wpa version disabled or wpa or wpa2 */
-		if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
-			val = WPA_AUTH_DISABLED;
-		else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
-			val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
-		else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
-			val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
-		WL_TRACE(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
-		if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
-			return error;
-		break;
-
-	case IW_AUTH_CIPHER_PAIRWISE:
-	case IW_AUTH_CIPHER_GROUP: {
-		int fbt_cap = 0;
-
-		if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
-			iw->pwsec = paramval;
-		}
-		else {
-			iw->gwsec = paramval;
-		}
-
-		if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
-			return error;
-
-		cipher_combined = iw->gwsec | iw->pwsec;
-		val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
-		if (cipher_combined & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
-			val |= WEP_ENABLED;
-		if (cipher_combined & IW_AUTH_CIPHER_TKIP)
-			val |= TKIP_ENABLED;
-		if (cipher_combined & IW_AUTH_CIPHER_CCMP)
-			val |= AES_ENABLED;
-
-		if (iw->privacy_invoked && !val) {
-			WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming "
-			         "we're a WPS enrollee\n", dev->name, __FUNCTION__));
-			if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
-				WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
-				return error;
-			}
-		} else if (val) {
-			if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
-				WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
-				return error;
-			}
-		}
-
-		if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
-			return error;
-
-		/* Ensure in-dongle supplicant is turned on when FBT wants to do the 4-way
-		 * handshake.
-		 */
-		if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) {
-			if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) {
-				if ((paramid == IW_AUTH_CIPHER_PAIRWISE) && (val & AES_ENABLED)) {
-					if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 1)))
-						return error;
-				}
-				else if (val == 0) {
-					if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 0)))
-						return error;
-				}
-			}
-		}
-		break;
-	}
-
-	case IW_AUTH_KEY_MGMT:
-		if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
-			return error;
-
-		if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
-			if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK))
-				val = WPA_AUTH_PSK;
-			else
-				val = WPA_AUTH_UNSPECIFIED;
-			if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK))
-				val |= WPA2_AUTH_FT;
-		}
-		else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
-			if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK))
-				val = WPA2_AUTH_PSK;
-			else
-				val = WPA2_AUTH_UNSPECIFIED;
-			if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK))
-				val |= WPA2_AUTH_FT;
-		}
-		WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
-		if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
-			return error;
-		break;
-
-	case IW_AUTH_TKIP_COUNTERMEASURES:
-		dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_80211_AUTH_ALG:
-		/* open shared */
-		WL_ERROR(("Setting the D11auth %d\n", paramval));
-		if (paramval & IW_AUTH_ALG_OPEN_SYSTEM)
-			val = 0;
-		else if (paramval & IW_AUTH_ALG_SHARED_KEY)
-			val = 1;
-		else
-			error = 1;
-		if (!error && (error = dev_wlc_intvar_set(dev, "auth", val)))
-			return error;
-		break;
-
-	case IW_AUTH_WPA_ENABLED:
-		if (paramval == 0) {
-			val = 0;
-			WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
-			error = dev_wlc_intvar_set(dev, "wpa_auth", val);
-			return error;
-		}
-		else {
-			/* If WPA is enabled, wpa_auth is set elsewhere */
-		}
-		break;
-
-	case IW_AUTH_DROP_UNENCRYPTED:
-		dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-		dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
-		break;
-
-#if WIRELESS_EXT > 17
-
-	case IW_AUTH_ROAMING_CONTROL:
-		WL_TRACE(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
-		/* driver control or user space app control */
-		break;
-
-	case IW_AUTH_PRIVACY_INVOKED: {
-		int wsec;
-
-		if (paramval == 0) {
-			iw->privacy_invoked = FALSE;
-			if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
-				WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
-				return error;
-			}
-		} else {
-			iw->privacy_invoked = TRUE;
-			if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec)))
-				return error;
-
-			if (!WSEC_ENABLED(wsec)) {
-				/* if privacy is true, but wsec is false, we are a WPS enrollee */
-				if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
-					WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
-					return error;
-				}
-			} else {
-				if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
-					WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
-					return error;
-				}
-			}
-		}
-		break;
-	}
-
-
-#endif /* WIRELESS_EXT > 17 */
-
-
-	default:
-		break;
-	}
-	return 0;
-}
-#define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK))
-
-static int
-wl_iw_get_wpaauth(
-	struct net_device *dev,
-	struct iw_request_info *info,
-	struct iw_param *vwrq,
-	char *extra
-)
-{
-	int error;
-	int paramid;
-	int paramval = 0;
-	int val;
-	wl_iw_t *iw = IW_DEV_IF(dev);
-
-	WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name));
-
-	paramid = vwrq->flags & IW_AUTH_INDEX;
-
-	switch (paramid) {
-	case IW_AUTH_WPA_VERSION:
-		/* supported wpa version disabled or wpa or wpa2 */
-		if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
-			return error;
-		if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED))
-			paramval = IW_AUTH_WPA_VERSION_DISABLED;
-		else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED))
-			paramval = IW_AUTH_WPA_VERSION_WPA;
-		else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED))
-			paramval = IW_AUTH_WPA_VERSION_WPA2;
-		break;
-
-	case IW_AUTH_CIPHER_PAIRWISE:
-		paramval = iw->pwsec;
-		break;
-
-	case IW_AUTH_CIPHER_GROUP:
-		paramval = iw->gwsec;
-		break;
-
-	case IW_AUTH_KEY_MGMT:
-		/* psk, 1x */
-		if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
-			return error;
-		if (VAL_PSK(val))
-			paramval = IW_AUTH_KEY_MGMT_PSK;
-		else
-			paramval = IW_AUTH_KEY_MGMT_802_1X;
-
-		break;
-	case IW_AUTH_TKIP_COUNTERMEASURES:
-		dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_DROP_UNENCRYPTED:
-		dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-		dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_80211_AUTH_ALG:
-		/* open, shared, leap */
-		if ((error = dev_wlc_intvar_get(dev, "auth", &val)))
-			return error;
-		if (!val)
-			paramval = IW_AUTH_ALG_OPEN_SYSTEM;
-		else
-			paramval = IW_AUTH_ALG_SHARED_KEY;
-		break;
-	case IW_AUTH_WPA_ENABLED:
-		if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
-			return error;
-		if (val)
-			paramval = TRUE;
-		else
-			paramval = FALSE;
-		break;
-
-#if WIRELESS_EXT > 17
-
-	case IW_AUTH_ROAMING_CONTROL:
-		WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
-		/* driver control or user space app control */
-		break;
-
-	case IW_AUTH_PRIVACY_INVOKED:
-		paramval = iw->privacy_invoked;
-		break;
-
-#endif /* WIRELESS_EXT > 17 */
-	}
-	vwrq->value = paramval;
-	return 0;
-}
-#endif /* WIRELESS_EXT > 17 */
-
-static const iw_handler wl_iw_handler[] =
-{
-	(iw_handler) wl_iw_config_commit,	/* SIOCSIWCOMMIT */
-	(iw_handler) wl_iw_get_name,		/* SIOCGIWNAME */
-	(iw_handler) NULL,			/* SIOCSIWNWID */
-	(iw_handler) NULL,			/* SIOCGIWNWID */
-	(iw_handler) wl_iw_set_freq,		/* SIOCSIWFREQ */
-	(iw_handler) wl_iw_get_freq,		/* SIOCGIWFREQ */
-	(iw_handler) wl_iw_set_mode,		/* SIOCSIWMODE */
-	(iw_handler) wl_iw_get_mode,		/* SIOCGIWMODE */
-	(iw_handler) NULL,			/* SIOCSIWSENS */
-	(iw_handler) NULL,			/* SIOCGIWSENS */
-	(iw_handler) NULL,			/* SIOCSIWRANGE */
-	(iw_handler) wl_iw_get_range,		/* SIOCGIWRANGE */
-	(iw_handler) NULL,			/* SIOCSIWPRIV */
-	(iw_handler) NULL,			/* SIOCGIWPRIV */
-	(iw_handler) NULL,			/* SIOCSIWSTATS */
-	(iw_handler) NULL,			/* SIOCGIWSTATS */
-	(iw_handler) wl_iw_set_spy,		/* SIOCSIWSPY */
-	(iw_handler) wl_iw_get_spy,		/* SIOCGIWSPY */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) wl_iw_set_wap,		/* SIOCSIWAP */
-	(iw_handler) wl_iw_get_wap,		/* SIOCGIWAP */
-#if WIRELESS_EXT > 17
-	(iw_handler) wl_iw_mlme,		/* SIOCSIWMLME */
-#else
-	(iw_handler) NULL,			/* -- hole -- */
-#endif
-	(iw_handler) wl_iw_iscan_get_aplist,	/* SIOCGIWAPLIST */
-#if WIRELESS_EXT > 13
-	(iw_handler) wl_iw_iscan_set_scan,	/* SIOCSIWSCAN */
-	(iw_handler) wl_iw_iscan_get_scan,	/* SIOCGIWSCAN */
-#else	/* WIRELESS_EXT > 13 */
-	(iw_handler) NULL,			/* SIOCSIWSCAN */
-	(iw_handler) NULL,			/* SIOCGIWSCAN */
-#endif	/* WIRELESS_EXT > 13 */
-	(iw_handler) wl_iw_set_essid,		/* SIOCSIWESSID */
-	(iw_handler) wl_iw_get_essid,		/* SIOCGIWESSID */
-	(iw_handler) wl_iw_set_nick,		/* SIOCSIWNICKN */
-	(iw_handler) wl_iw_get_nick,		/* SIOCGIWNICKN */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) wl_iw_set_rate,		/* SIOCSIWRATE */
-	(iw_handler) wl_iw_get_rate,		/* SIOCGIWRATE */
-	(iw_handler) wl_iw_set_rts,		/* SIOCSIWRTS */
-	(iw_handler) wl_iw_get_rts,		/* SIOCGIWRTS */
-	(iw_handler) wl_iw_set_frag,		/* SIOCSIWFRAG */
-	(iw_handler) wl_iw_get_frag,		/* SIOCGIWFRAG */
-	(iw_handler) wl_iw_set_txpow,		/* SIOCSIWTXPOW */
-	(iw_handler) wl_iw_get_txpow,		/* SIOCGIWTXPOW */
-#if WIRELESS_EXT > 10
-	(iw_handler) wl_iw_set_retry,		/* SIOCSIWRETRY */
-	(iw_handler) wl_iw_get_retry,		/* SIOCGIWRETRY */
-#endif /* WIRELESS_EXT > 10 */
-	(iw_handler) wl_iw_set_encode,		/* SIOCSIWENCODE */
-	(iw_handler) wl_iw_get_encode,		/* SIOCGIWENCODE */
-	(iw_handler) wl_iw_set_power,		/* SIOCSIWPOWER */
-	(iw_handler) wl_iw_get_power,		/* SIOCGIWPOWER */
-#if WIRELESS_EXT > 17
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) wl_iw_set_wpaie,		/* SIOCSIWGENIE */
-	(iw_handler) wl_iw_get_wpaie,		/* SIOCGIWGENIE */
-	(iw_handler) wl_iw_set_wpaauth,		/* SIOCSIWAUTH */
-	(iw_handler) wl_iw_get_wpaauth,		/* SIOCGIWAUTH */
-	(iw_handler) wl_iw_set_encodeext,	/* SIOCSIWENCODEEXT */
-	(iw_handler) wl_iw_get_encodeext,	/* SIOCGIWENCODEEXT */
-	(iw_handler) wl_iw_set_pmksa,		/* SIOCSIWPMKSA */
-#endif /* WIRELESS_EXT > 17 */
-};
-
-#if WIRELESS_EXT > 12
-enum {
-	WL_IW_SET_LEDDC = SIOCIWFIRSTPRIV,
-	WL_IW_SET_VLANMODE,
-	WL_IW_SET_PM,
-#if WIRELESS_EXT > 17
-#endif /* WIRELESS_EXT > 17 */
-	WL_IW_SET_LAST
-};
-
-static iw_handler wl_iw_priv_handler[] = {
-	wl_iw_set_leddc,
-	wl_iw_set_vlanmode,
-	wl_iw_set_pm,
-#if WIRELESS_EXT > 17
-#endif /* WIRELESS_EXT > 17 */
-	NULL
-};
-
-static struct iw_priv_args wl_iw_priv_args[] = {
-	{
-		WL_IW_SET_LEDDC,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-		0,
-		"set_leddc"
-	},
-	{
-		WL_IW_SET_VLANMODE,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-		0,
-		"set_vlanmode"
-	},
-	{
-		WL_IW_SET_PM,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-		0,
-		"set_pm"
-	},
-#if WIRELESS_EXT > 17
-#endif /* WIRELESS_EXT > 17 */
-	{ 0, 0, 0, { 0 } }
-};
-
-const struct iw_handler_def wl_iw_handler_def =
-{
-	.num_standard = ARRAYSIZE(wl_iw_handler),
-	.num_private = ARRAY_SIZE(wl_iw_priv_handler),
-	.num_private_args = ARRAY_SIZE(wl_iw_priv_args),
-	.standard = (const iw_handler *) wl_iw_handler,
-	.private = wl_iw_priv_handler,
-	.private_args = wl_iw_priv_args,
-#if WIRELESS_EXT >= 19
-	get_wireless_stats: dhd_get_wireless_stats,
-#endif /* WIRELESS_EXT >= 19 */
-	};
-#endif /* WIRELESS_EXT > 12 */
-
-int
-wl_iw_ioctl(
-	struct net_device *dev,
-	struct ifreq *rq,
-	int cmd
-)
-{
-	struct iwreq *wrq = (struct iwreq *) rq;
-	struct iw_request_info info;
-	iw_handler handler;
-	char *extra = NULL;
-	size_t token_size = 1;
-	int max_tokens = 0, ret = 0;
-
-	if (cmd < SIOCIWFIRST ||
-		IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
-		!(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)]))
-		return -EOPNOTSUPP;
-
-	switch (cmd) {
-
-	case SIOCSIWESSID:
-	case SIOCGIWESSID:
-	case SIOCSIWNICKN:
-	case SIOCGIWNICKN:
-		max_tokens = IW_ESSID_MAX_SIZE + 1;
-		break;
-
-	case SIOCSIWENCODE:
-	case SIOCGIWENCODE:
-#if WIRELESS_EXT > 17
-	case SIOCSIWENCODEEXT:
-	case SIOCGIWENCODEEXT:
-#endif
-		max_tokens = IW_ENCODING_TOKEN_MAX;
-		break;
-
-	case SIOCGIWRANGE:
-		max_tokens = sizeof(struct iw_range);
-		break;
-
-	case SIOCGIWAPLIST:
-		token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
-		max_tokens = IW_MAX_AP;
-		break;
-
-#if WIRELESS_EXT > 13
-	case SIOCGIWSCAN:
-	if (g_iscan)
-		max_tokens = wrq->u.data.length;
-	else
-		max_tokens = IW_SCAN_MAX_DATA;
-		break;
-#endif /* WIRELESS_EXT > 13 */
-
-	case SIOCSIWSPY:
-		token_size = sizeof(struct sockaddr);
-		max_tokens = IW_MAX_SPY;
-		break;
-
-	case SIOCGIWSPY:
-		token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
-		max_tokens = IW_MAX_SPY;
-		break;
-	default:
-		break;
-	}
-
-	if (max_tokens && wrq->u.data.pointer) {
-		if (wrq->u.data.length > max_tokens)
-			return -E2BIG;
-
-		if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL)))
-			return -ENOMEM;
-
-		if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) {
-			kfree(extra);
-			return -EFAULT;
-		}
-	}
-
-	info.cmd = cmd;
-	info.flags = 0;
-
-	ret = handler(dev, &info, &wrq->u, extra);
-
-	if (extra) {
-		if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) {
-			kfree(extra);
-			return -EFAULT;
-		}
-
-		kfree(extra);
-	}
-
-	return ret;
-}
-
-/* Convert a connection status event into a connection status string.
- * Returns TRUE if a matching connection status string was found.
- */
-bool
-wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason,
-	char* stringBuf, uint buflen)
-{
-	typedef struct conn_fail_event_map_t {
-		uint32 inEvent;			/* input: event type to match */
-		uint32 inStatus;		/* input: event status code to match */
-		uint32 inReason;		/* input: event reason code to match */
-		const char* outName;	/* output: failure type */
-		const char* outCause;	/* output: failure cause */
-	} conn_fail_event_map_t;
-
-	/* Map of WLC_E events to connection failure strings */
-#	define WL_IW_DONT_CARE	9999
-	const conn_fail_event_map_t event_map [] = {
-		/* inEvent           inStatus                inReason         */
-		/* outName outCause                                           */
-		{WLC_E_SET_SSID,     WLC_E_STATUS_SUCCESS,   WL_IW_DONT_CARE,
-		"Conn", "Success"},
-		{WLC_E_SET_SSID,     WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE,
-		"Conn", "NoNetworks"},
-		{WLC_E_SET_SSID,     WLC_E_STATUS_FAIL,      WL_IW_DONT_CARE,
-		"Conn", "ConfigMismatch"},
-		{WLC_E_PRUNE,        WL_IW_DONT_CARE,        WLC_E_PRUNE_ENCR_MISMATCH,
-		"Conn", "EncrypMismatch"},
-		{WLC_E_PRUNE,        WL_IW_DONT_CARE,        WLC_E_RSN_MISMATCH,
-		"Conn", "RsnMismatch"},
-		{WLC_E_AUTH,         WLC_E_STATUS_TIMEOUT,   WL_IW_DONT_CARE,
-		"Conn", "AuthTimeout"},
-		{WLC_E_AUTH,         WLC_E_STATUS_FAIL,      WL_IW_DONT_CARE,
-		"Conn", "AuthFail"},
-		{WLC_E_AUTH,         WLC_E_STATUS_NO_ACK,    WL_IW_DONT_CARE,
-		"Conn", "AuthNoAck"},
-		{WLC_E_REASSOC,      WLC_E_STATUS_FAIL,      WL_IW_DONT_CARE,
-		"Conn", "ReassocFail"},
-		{WLC_E_REASSOC,      WLC_E_STATUS_TIMEOUT,   WL_IW_DONT_CARE,
-		"Conn", "ReassocTimeout"},
-		{WLC_E_REASSOC,      WLC_E_STATUS_ABORT,     WL_IW_DONT_CARE,
-		"Conn", "ReassocAbort"},
-		{WLC_E_PSK_SUP,      WLC_SUP_KEYED,          WL_IW_DONT_CARE,
-		"Sup", "ConnSuccess"},
-		{WLC_E_PSK_SUP,      WL_IW_DONT_CARE,        WL_IW_DONT_CARE,
-		"Sup", "WpaHandshakeFail"},
-		{WLC_E_DEAUTH_IND,   WL_IW_DONT_CARE,        WL_IW_DONT_CARE,
-		"Conn", "Deauth"},
-		{WLC_E_DISASSOC_IND, WL_IW_DONT_CARE,        WL_IW_DONT_CARE,
-		"Conn", "DisassocInd"},
-		{WLC_E_DISASSOC,     WL_IW_DONT_CARE,        WL_IW_DONT_CARE,
-		"Conn", "Disassoc"}
-	};
-
-	const char* name = "";
-	const char* cause = NULL;
-	int i;
-
-	/* Search the event map table for a matching event */
-	for (i = 0;  i < sizeof(event_map)/sizeof(event_map[0]);  i++) {
-		const conn_fail_event_map_t* row = &event_map[i];
-		if (row->inEvent == event_type &&
-		    (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) &&
-		    (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) {
-			name = row->outName;
-			cause = row->outCause;
-			break;
-		}
-	}
-
-	/* If found, generate a connection failure string and return TRUE */
-	if (cause) {
-		memset(stringBuf, 0, buflen);
-		(void)snprintf(stringBuf, buflen, "%s %s %02d %02d", name, cause, status, reason);
-		WL_TRACE(("Connection status: %s\n", stringBuf));
-		return TRUE;
-	} else {
-		return FALSE;
-	}
-}
-
-#if (WIRELESS_EXT > 14)
-/* Check if we have received an event that indicates connection failure
- * If so, generate a connection failure report string.
- * The caller supplies a buffer to hold the generated string.
- */
-static bool
-wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen)
-{
-	uint32 event = ntoh32(e->event_type);
-	uint32 status =  ntoh32(e->status);
-	uint32 reason =  ntoh32(e->reason);
-
-	if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
-		return TRUE;
-	} else
-	{
-		return FALSE;
-	}
-}
-#endif /* WIRELESS_EXT > 14 */
-
-#ifndef IW_CUSTOM_MAX
-#define IW_CUSTOM_MAX 256 /* size of extra buffer used for translation of events */
-#endif /* IW_CUSTOM_MAX */
-
-void
-wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
-{
-#if WIRELESS_EXT > 13
-	union iwreq_data wrqu;
-	char extra[IW_CUSTOM_MAX + 1];
-	int cmd = 0;
-	uint32 event_type = ntoh32(e->event_type);
-	uint16 flags =  ntoh16(e->flags);
-	uint32 datalen = ntoh32(e->datalen);
-	uint32 status =  ntoh32(e->status);
-
-	memset(&wrqu, 0, sizeof(wrqu));
-	memset(extra, 0, sizeof(extra));
-
-	memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
-	wrqu.addr.sa_family = ARPHRD_ETHER;
-
-	switch (event_type) {
-	case WLC_E_TXFAIL:
-		cmd = IWEVTXDROP;
-		break;
-#if WIRELESS_EXT > 14
-	case WLC_E_JOIN:
-	case WLC_E_ASSOC_IND:
-	case WLC_E_REASSOC_IND:
-		cmd = IWEVREGISTERED;
-		break;
-	case WLC_E_DEAUTH_IND:
-	case WLC_E_DISASSOC_IND:
-		cmd = SIOCGIWAP;
-		wrqu.data.length = strlen(extra);
-		bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
-		bzero(&extra, ETHER_ADDR_LEN);
-		break;
-
-	case WLC_E_LINK:
-		cmd = SIOCGIWAP;
-		wrqu.data.length = strlen(extra);
-		if (!(flags & WLC_EVENT_MSG_LINK)) {
-			bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
-			bzero(&extra, ETHER_ADDR_LEN);
-		}
-		break;
-	case WLC_E_ACTION_FRAME:
-		cmd = IWEVCUSTOM;
-		if (datalen + 1 <= sizeof(extra)) {
-			wrqu.data.length = datalen + 1;
-			extra[0] = WLC_E_ACTION_FRAME;
-			memcpy(&extra[1], data, datalen);
-			WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length));
-		}
-		break;
-
-	case WLC_E_ACTION_FRAME_COMPLETE:
-		cmd = IWEVCUSTOM;
-		if (sizeof(status) + 1 <= sizeof(extra)) {
-			wrqu.data.length = sizeof(status) + 1;
-			extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
-			memcpy(&extra[1], &status, sizeof(status));
-			WL_TRACE(("wl_iw_event status %d  \n", status));
-		}
-		break;
-#endif /* WIRELESS_EXT > 14 */
-#if WIRELESS_EXT > 17
-	case WLC_E_MIC_ERROR: {
-		struct	iw_michaelmicfailure  *micerrevt = (struct  iw_michaelmicfailure  *)&extra;
-		cmd = IWEVMICHAELMICFAILURE;
-		wrqu.data.length = sizeof(struct iw_michaelmicfailure);
-		if (flags & WLC_EVENT_MSG_GROUP)
-			micerrevt->flags |= IW_MICFAILURE_GROUP;
-		else
-			micerrevt->flags |= IW_MICFAILURE_PAIRWISE;
-		memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN);
-		micerrevt->src_addr.sa_family = ARPHRD_ETHER;
-
-		break;
-	}
-
-	case WLC_E_ASSOC_REQ_IE:
-		cmd = IWEVASSOCREQIE;
-		wrqu.data.length = datalen;
-		if (datalen < sizeof(extra))
-			memcpy(extra, data, datalen);
-		break;
-
-	case WLC_E_ASSOC_RESP_IE:
-		cmd = IWEVASSOCRESPIE;
-		wrqu.data.length = datalen;
-		if (datalen < sizeof(extra))
-			memcpy(extra, data, datalen);
-		break;
-
-	case WLC_E_PMKID_CACHE: {
-		struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra;
-		pmkid_cand_list_t *pmkcandlist;
-		pmkid_cand_t	*pmkidcand;
-		int count;
-
-		if (data == NULL)
-			break;
-
-		cmd = IWEVPMKIDCAND;
-		pmkcandlist = data;
-		count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand);
-		wrqu.data.length = sizeof(struct iw_pmkid_cand);
-		pmkidcand = pmkcandlist->pmkid_cand;
-		while (count) {
-			bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand));
-			if (pmkidcand->preauth)
-				iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH;
-			bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data,
-			      ETHER_ADDR_LEN);
-			wireless_send_event(dev, cmd, &wrqu, extra);
-			pmkidcand++;
-			count--;
-		}
-		break;
-	}
-#endif /* WIRELESS_EXT > 17 */
-
-	case WLC_E_SCAN_COMPLETE:
-#if WIRELESS_EXT > 14
-		cmd = SIOCGIWSCAN;
-#endif
-		WL_TRACE(("event WLC_E_SCAN_COMPLETE\n"));
-		if ((g_iscan) && (g_iscan->sysioc_pid >= 0) &&
-			(g_iscan->iscan_state != ISCAN_STATE_IDLE))
-			up(&g_iscan->sysioc_sem);
-		break;
-
-	default:
-		/* Cannot translate event */
-		break;
-	}
-
-	if (cmd) {
-		if (cmd == SIOCGIWSCAN)
-			wireless_send_event(dev, cmd, &wrqu, NULL);
-		else
-			wireless_send_event(dev, cmd, &wrqu, extra);
-	}
-
-#if WIRELESS_EXT > 14
-	/* Look for WLC events that indicate a connection failure.
-	 * If found, generate an IWEVCUSTOM event.
-	 */
-	memset(extra, 0, sizeof(extra));
-	if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
-		cmd = IWEVCUSTOM;
-		wrqu.data.length = strlen(extra);
-		wireless_send_event(dev, cmd, &wrqu, extra);
-	}
-#endif /* WIRELESS_EXT > 14 */
-
-#endif /* WIRELESS_EXT > 13 */
-}
-
-static int wl_iw_get_wireless_stats_cbfn(void *ctx, uint8 *data, uint16 type, uint16 len)
-{
-	struct iw_statistics *wstats = ctx;
-	int res = BCME_OK;
-
-	switch (type) {
-		case WL_CNT_XTLV_WLC: {
-			wl_cnt_wlc_t *cnt = (wl_cnt_wlc_t *)data;
-			if (len > sizeof(wl_cnt_wlc_t)) {
-				printf("counter structure length invalid! %d > %d\n",
-					len, (int)sizeof(wl_cnt_wlc_t));
-			}
-			wstats->discard.nwid = 0;
-			wstats->discard.code = dtoh32(cnt->rxundec);
-			wstats->discard.fragment = dtoh32(cnt->rxfragerr);
-			wstats->discard.retries = dtoh32(cnt->txfail);
-			wstats->discard.misc = dtoh32(cnt->rxrunt) + dtoh32(cnt->rxgiant);
-			wstats->miss.beacon = 0;
-			WL_TRACE(("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n",
-				dtoh32(cnt->txframe), dtoh32(cnt->txbyte)));
-			WL_TRACE(("wl_iw_get_wireless_stats counters rxundec=%d\n",
-				dtoh32(cnt->rxundec)));
-			WL_TRACE(("wl_iw_get_wireless_stats counters txfail=%d\n",
-				dtoh32(cnt->txfail)));
-			WL_TRACE(("wl_iw_get_wireless_stats counters rxfragerr=%d\n",
-				dtoh32(cnt->rxfragerr)));
-			WL_TRACE(("wl_iw_get_wireless_stats counters rxrunt=%d\n",
-				dtoh32(cnt->rxrunt)));
-			WL_TRACE(("wl_iw_get_wireless_stats counters rxgiant=%d\n",
-				dtoh32(cnt->rxgiant)));
-			break;
-		}
-		case WL_CNT_XTLV_CNTV_LE10_UCODE:
-		case WL_CNT_XTLV_LT40_UCODE_V1:
-		case WL_CNT_XTLV_GE40_UCODE_V1:
-		{
-			/* Offsets of rxfrmtoolong and rxbadplcp are the same in
-			 * wl_cnt_v_le10_mcst_t, wl_cnt_lt40mcst_v1_t, and wl_cnt_ge40mcst_v1_t.
-			 * So we can just cast to wl_cnt_v_le10_mcst_t here.
-			 */
-			wl_cnt_v_le10_mcst_t *cnt = (wl_cnt_v_le10_mcst_t *)data;
-			if (len != WL_CNT_MCST_STRUCT_SZ) {
-				printf("counter structure length mismatch! %d != %d\n",
-					len, WL_CNT_MCST_STRUCT_SZ);
-			}
-			WL_TRACE(("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n",
-				dtoh32(cnt->rxfrmtoolong)));
-			WL_TRACE(("wl_iw_get_wireless_stats counters rxbadplcp=%d\n",
-				dtoh32(cnt->rxbadplcp)));
-			BCM_REFERENCE(cnt);
-			break;
-		}
-		default:
-			WL_ERROR(("%s %d: Unsupported type %d\n", __FUNCTION__, __LINE__, type));
-			break;
-	}
-	return res;
-}
-
-int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
-{
-	int res = 0;
-	int phy_noise;
-	int rssi;
-	scb_val_t scb_val;
-#if WIRELESS_EXT > 11
-	char *cntbuf = NULL;
-	wl_cnt_info_t *cntinfo;
-	uint16 ver;
-	uint32 corerev = 0;
-#endif /* WIRELESS_EXT > 11 */
-
-	phy_noise = 0;
-	if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise))))
-		goto done;
-
-	phy_noise = dtoh32(phy_noise);
-	WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n *****", phy_noise));
-
-	scb_val.val = 0;
-	if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
-		goto done;
-
-	rssi = dtoh32(scb_val.val);
-	WL_TRACE(("wl_iw_get_wireless_stats rssi=%d ****** \n", rssi));
-	if (rssi <= WL_IW_RSSI_NO_SIGNAL)
-		wstats->qual.qual = 0;
-	else if (rssi <= WL_IW_RSSI_VERY_LOW)
-		wstats->qual.qual = 1;
-	else if (rssi <= WL_IW_RSSI_LOW)
-		wstats->qual.qual = 2;
-	else if (rssi <= WL_IW_RSSI_GOOD)
-		wstats->qual.qual = 3;
-	else if (rssi <= WL_IW_RSSI_VERY_GOOD)
-		wstats->qual.qual = 4;
-	else
-		wstats->qual.qual = 5;
-
-	/* Wraps to 0 if RSSI is 0 */
-	wstats->qual.level = 0x100 + rssi;
-	wstats->qual.noise = 0x100 + phy_noise;
-#if WIRELESS_EXT > 18
-	wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
-#else
-	wstats->qual.updated |= 7;
-#endif /* WIRELESS_EXT > 18 */
-
-#if WIRELESS_EXT > 11
-	WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n *****", WL_CNTBUF_MAX_SIZE));
-
-	if (WL_CNTBUF_MAX_SIZE > MAX_WLIW_IOCTL_LEN)
-	{
-		WL_ERROR(("wl_iw_get_wireless_stats buffer too short %d < %d\n",
-			WL_CNTBUF_MAX_SIZE, MAX_WLIW_IOCTL_LEN));
-		res = BCME_BUFTOOSHORT;
-		goto done;
-	}
-
-	cntbuf = kmalloc(WL_CNTBUF_MAX_SIZE, GFP_KERNEL);
-	if (!cntbuf) {
-		res = BCME_NOMEM;
-		goto done;
-	}
-
-	memset(cntbuf, 0, WL_CNTBUF_MAX_SIZE);
-	res = dev_wlc_bufvar_get(dev, "counters", cntbuf, WL_CNTBUF_MAX_SIZE);
-	if (res)
-	{
-		WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d ****** \n", res));
-		goto done;
-	}
-
-	cntinfo = (wl_cnt_info_t *)cntbuf;
-	cntinfo->version = dtoh16(cntinfo->version);
-	cntinfo->datalen = dtoh16(cntinfo->datalen);
-	ver = cntinfo->version;
-	if (ver > WL_CNT_T_VERSION) {
-		WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n",
-			WL_CNT_T_VERSION, ver));
-		res = BCME_VERSION;
-		goto done;
-	}
-
-	if (ver == WL_CNT_VERSION_11) {
-		wlc_rev_info_t revinfo;
-		memset(&revinfo, 0, sizeof(revinfo));
-		res = dev_wlc_ioctl(dev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
-		if (res) {
-			WL_ERROR(("%s: WLC_GET_REVINFO failed %d\n", __FUNCTION__, res));
-			goto done;
-		}
-		corerev = dtoh32(revinfo.corerev);
-	}
-
-	res = wl_cntbuf_to_xtlv_format(NULL, cntinfo, WL_CNTBUF_MAX_SIZE, corerev);
-	if (res) {
-		WL_ERROR(("%s: wl_cntbuf_to_xtlv_format failed %d\n", __FUNCTION__, res));
-		goto done;
-	}
-
-	if ((res = bcm_unpack_xtlv_buf(wstats, cntinfo->data, cntinfo->datalen,
-		BCM_XTLV_OPTION_ALIGN32, wl_iw_get_wireless_stats_cbfn))) {
-		goto done;
-	}
-#endif /* WIRELESS_EXT > 11 */
-
-done:
-#if WIRELESS_EXT > 11
-	if (cntbuf) {
-		kfree(cntbuf);
-	}
-#endif /* WIRELESS_EXT > 11 */
-	return res;
-}
-
-static void
-wl_iw_timerfunc(ulong data)
-{
-	iscan_info_t *iscan = (iscan_info_t *)data;
-	iscan->timer_on = 0;
-	if (iscan->iscan_state != ISCAN_STATE_IDLE) {
-		WL_TRACE(("timer trigger\n"));
-		up(&iscan->sysioc_sem);
-	}
-}
-
-static void
-wl_iw_set_event_mask(struct net_device *dev)
-{
-	char eventmask[WL_EVENTING_MASK_LEN];
-	char iovbuf[WL_EVENTING_MASK_LEN + 12];	/* Room for "event_msgs" + '\0' + bitvec */
-
-	dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
-	bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
-	setbit(eventmask, WLC_E_SCAN_COMPLETE);
-	dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
-		iovbuf, sizeof(iovbuf));
-
-}
-
-static int
-wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
-{
-	int err = 0;
-
-	memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
-	params->bss_type = DOT11_BSSTYPE_ANY;
-	params->scan_type = 0;
-	params->nprobes = -1;
-	params->active_time = -1;
-	params->passive_time = -1;
-	params->home_time = -1;
-	params->channel_num = 0;
-
-	params->nprobes = htod32(params->nprobes);
-	params->active_time = htod32(params->active_time);
-	params->passive_time = htod32(params->passive_time);
-	params->home_time = htod32(params->home_time);
-	if (ssid && ssid->SSID_len)
-		memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
-
-	return err;
-}
-
-static int
-wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
-{
-	int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
-	wl_iscan_params_t *params;
-	int err = 0;
-
-	if (ssid && ssid->SSID_len) {
-		params_size += sizeof(wlc_ssid_t);
-	}
-	params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
-	if (params == NULL) {
-		return -ENOMEM;
-	}
-	memset(params, 0, params_size);
-	ASSERT(params_size < WLC_IOCTL_SMLEN);
-
-	err = wl_iw_iscan_prep(&params->params, ssid);
-
-	if (!err) {
-		params->version = htod32(ISCAN_REQ_VERSION);
-		params->action = htod16(action);
-		params->scan_duration = htod16(0);
-
-		/* params_size += OFFSETOF(wl_iscan_params_t, params); */
-		(void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size,
-			iscan->ioctlbuf, WLC_IOCTL_SMLEN);
-	}
-
-	kfree(params);
-	return err;
-}
-
-static uint32
-wl_iw_iscan_get(iscan_info_t *iscan)
-{
-	iscan_buf_t * buf;
-	iscan_buf_t * ptr;
-	wl_iscan_results_t * list_buf;
-	wl_iscan_results_t list;
-	wl_scan_results_t *results;
-	uint32 status;
-
-	/* buffers are allocated on demand */
-	if (iscan->list_cur) {
-		buf = iscan->list_cur;
-		iscan->list_cur = buf->next;
-	}
-	else {
-		buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL);
-		if (!buf)
-			return WL_SCAN_RESULTS_ABORTED;
-		buf->next = NULL;
-		if (!iscan->list_hdr)
-			iscan->list_hdr = buf;
-		else {
-			ptr = iscan->list_hdr;
-			while (ptr->next) {
-				ptr = ptr->next;
-			}
-			ptr->next = buf;
-		}
-	}
-	memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
-	list_buf = (wl_iscan_results_t*)buf->iscan_buf;
-	results = &list_buf->results;
-	results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
-	results->version = 0;
-	results->count = 0;
-
-	memset(&list, 0, sizeof(list));
-	list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
-	(void) dev_iw_iovar_getbuf(
-		iscan->dev,
-		"iscanresults",
-		&list,
-		WL_ISCAN_RESULTS_FIXED_SIZE,
-		buf->iscan_buf,
-		WLC_IW_ISCAN_MAXLEN);
-	results->buflen = dtoh32(results->buflen);
-	results->version = dtoh32(results->version);
-	results->count = dtoh32(results->count);
-	WL_TRACE(("results->count = %d\n", results->count));
-
-	WL_TRACE(("results->buflen = %d\n", results->buflen));
-	status = dtoh32(list_buf->status);
-	return status;
-}
-
-static void wl_iw_send_scan_complete(iscan_info_t *iscan)
-{
-	union iwreq_data wrqu;
-
-	memset(&wrqu, 0, sizeof(wrqu));
-
-	/* wext expects to get no data for SIOCGIWSCAN Event  */
-	wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
-}
-
-static int
-_iscan_sysioc_thread(void *data)
-{
-	uint32 status;
-	iscan_info_t *iscan = (iscan_info_t *)data;
-
-	DAEMONIZE("iscan_sysioc");
-
-	status = WL_SCAN_RESULTS_PARTIAL;
-	while (down_interruptible(&iscan->sysioc_sem) == 0) {
-		if (iscan->timer_on) {
-			del_timer(&iscan->timer);
-			iscan->timer_on = 0;
-		}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-		rtnl_lock();
-#endif
-		status = wl_iw_iscan_get(iscan);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-		rtnl_unlock();
-#endif
-
-		switch (status) {
-			case WL_SCAN_RESULTS_PARTIAL:
-				WL_TRACE(("iscanresults incomplete\n"));
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-				rtnl_lock();
-#endif
-				/* make sure our buffer size is enough before going next round */
-				wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-				rtnl_unlock();
-#endif
-				/* Reschedule the timer */
-				iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
-				add_timer(&iscan->timer);
-				iscan->timer_on = 1;
-				break;
-			case WL_SCAN_RESULTS_SUCCESS:
-				WL_TRACE(("iscanresults complete\n"));
-				iscan->iscan_state = ISCAN_STATE_IDLE;
-				wl_iw_send_scan_complete(iscan);
-				break;
-			case WL_SCAN_RESULTS_PENDING:
-				WL_TRACE(("iscanresults pending\n"));
-				/* Reschedule the timer */
-				iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
-				add_timer(&iscan->timer);
-				iscan->timer_on = 1;
-				break;
-			case WL_SCAN_RESULTS_ABORTED:
-				WL_TRACE(("iscanresults aborted\n"));
-				iscan->iscan_state = ISCAN_STATE_IDLE;
-				wl_iw_send_scan_complete(iscan);
-				break;
-			default:
-				WL_TRACE(("iscanresults returned unknown status %d\n", status));
-				break;
-		 }
-	}
-	complete_and_exit(&iscan->sysioc_exited, 0);
-}
-
-int
-wl_iw_attach(struct net_device *dev, void * dhdp)
-{
-	iscan_info_t *iscan = NULL;
-
-	if (!dev)
-		return 0;
-
-	iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
-	if (!iscan)
-		return -ENOMEM;
-	memset(iscan, 0, sizeof(iscan_info_t));
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-	iscan->kthread = NULL;
-#endif
-	iscan->sysioc_pid = -1;
-	/* we only care about main interface so save a global here */
-	g_iscan = iscan;
-	iscan->dev = dev;
-	iscan->iscan_state = ISCAN_STATE_IDLE;
-
-
-	/* Set up the timer */
-	iscan->timer_ms    = 2000;
-	init_timer(&iscan->timer);
-	iscan->timer.data = (ulong)iscan;
-	iscan->timer.function = wl_iw_timerfunc;
-
-	sema_init(&iscan->sysioc_sem, 0);
-	init_completion(&iscan->sysioc_exited);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
-	iscan->kthread = kthread_run(_iscan_sysioc_thread, iscan, "iscan_sysioc");
-	iscan->sysioc_pid = iscan->kthread->pid;
-#else
-	iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0);
-#endif
-	if (iscan->sysioc_pid < 0)
-		return -ENOMEM;
-	return 0;
-}
-
-void wl_iw_detach(void)
-{
-	iscan_buf_t  *buf;
-	iscan_info_t *iscan = g_iscan;
-	if (!iscan)
-		return;
-	if (iscan->sysioc_pid >= 0) {
-		KILL_PROC(iscan->sysioc_pid, SIGTERM);
-		wait_for_completion(&iscan->sysioc_exited);
-	}
-
-	while (iscan->list_hdr) {
-		buf = iscan->list_hdr->next;
-		kfree(iscan->list_hdr);
-		iscan->list_hdr = buf;
-	}
-	kfree(iscan);
-	g_iscan = NULL;
-}
-
-#endif /* USE_IW */
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h
deleted file mode 100644
index 6b86bb1..0000000
--- a/drivers/net/wireless/bcmdhd/wl_iw.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Linux Wireless Extensions support
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_iw.h 514727 2014-11-12 03:02:48Z $
- */
-
-#ifndef _wl_iw_h_
-#define _wl_iw_h_
-
-#include <linux/wireless.h>
-
-#include <typedefs.h>
-#include <proto/ethernet.h>
-#include <wlioctl.h>
-
-#define WL_SCAN_PARAMS_SSID_MAX 	10
-#define GET_SSID			"SSID="
-#define GET_CHANNEL			"CH="
-#define GET_NPROBE 			"NPROBE="
-#define GET_ACTIVE_ASSOC_DWELL  	"ACTIVE="
-#define GET_PASSIVE_ASSOC_DWELL  	"PASSIVE="
-#define GET_HOME_DWELL  		"HOME="
-#define GET_SCAN_TYPE			"TYPE="
-
-#define BAND_GET_CMD				"GETBAND"
-#define BAND_SET_CMD				"SETBAND"
-#define DTIM_SKIP_GET_CMD			"DTIMSKIPGET"
-#define DTIM_SKIP_SET_CMD			"DTIMSKIPSET"
-#define SETSUSPEND_CMD				"SETSUSPENDOPT"
-#define PNOSSIDCLR_SET_CMD			"PNOSSIDCLR"
-/* Lin - Is the extra space needed? */
-#define PNOSETUP_SET_CMD			"PNOSETUP " /* TLV command has extra end space */
-#define PNOENABLE_SET_CMD			"PNOFORCE"
-#define PNODEBUG_SET_CMD			"PNODEBUG"
-#define TXPOWER_SET_CMD			"TXPOWER"
-
-#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
-#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
-
-/* Structure to keep global parameters */
-typedef struct wl_iw_extra_params {
-	int 	target_channel; /* target channel */
-} wl_iw_extra_params_t;
-
-struct cntry_locales_custom {
-	char iso_abbrev[WLC_CNTRY_BUF_SZ];	/* ISO 3166-1 country abbreviation */
-	char custom_locale[WLC_CNTRY_BUF_SZ];	/* Custom firmware locale */
-	int32 custom_locale_rev;		/* Custom local revisin default -1 */
-};
-/* ============================================== */
-/* Defines from wlc_pub.h */
-#define	WL_IW_RSSI_MINVAL		-200	/* Low value, e.g. for forcing roam */
-#define	WL_IW_RSSI_NO_SIGNAL	-91	/* NDIS RSSI link quality cutoffs */
-#define	WL_IW_RSSI_VERY_LOW	-80	/* Very low quality cutoffs */
-#define	WL_IW_RSSI_LOW		-70	/* Low quality cutoffs */
-#define	WL_IW_RSSI_GOOD		-68	/* Good quality cutoffs */
-#define	WL_IW_RSSI_VERY_GOOD	-58	/* Very good quality cutoffs */
-#define	WL_IW_RSSI_EXCELLENT	-57	/* Excellent quality cutoffs */
-#define	WL_IW_RSSI_INVALID	 0	/* invalid RSSI value */
-#define MAX_WX_STRING 80
-#define SSID_FMT_BUF_LEN	((4 * 32) + 1)
-#define isprint(c) bcm_isprint(c)
-#define WL_IW_SET_ACTIVE_SCAN	(SIOCIWFIRSTPRIV+1)
-#define WL_IW_GET_RSSI			(SIOCIWFIRSTPRIV+3)
-#define WL_IW_SET_PASSIVE_SCAN	(SIOCIWFIRSTPRIV+5)
-#define WL_IW_GET_LINK_SPEED	(SIOCIWFIRSTPRIV+7)
-#define WL_IW_GET_CURR_MACADDR	(SIOCIWFIRSTPRIV+9)
-#define WL_IW_SET_STOP				(SIOCIWFIRSTPRIV+11)
-#define WL_IW_SET_START			(SIOCIWFIRSTPRIV+13)
-
-#define 		G_SCAN_RESULTS 8*1024
-#define 		WE_ADD_EVENT_FIX	0x80
-#define          G_WLAN_SET_ON	0
-#define          G_WLAN_SET_OFF	1
-
-
-typedef struct wl_iw {
-	char nickname[IW_ESSID_MAX_SIZE];
-
-	struct iw_statistics wstats;
-
-	int spy_num;
-	uint32 pwsec;			/* pairwise wsec setting */
-	uint32 gwsec;			/* group wsec setting  */
-	bool privacy_invoked; 		/* IW_AUTH_PRIVACY_INVOKED setting */
-	struct ether_addr spy_addr[IW_MAX_SPY];
-	struct iw_quality spy_qual[IW_MAX_SPY];
-	void  *wlinfo;
-} wl_iw_t;
-
-struct wl_ctrl {
-	struct timer_list *timer;
-	struct net_device *dev;
-	long sysioc_pid;
-	struct semaphore sysioc_sem;
-	struct completion sysioc_exited;
-};
-
-
-#if WIRELESS_EXT > 12
-#include <net/iw_handler.h>
-extern const struct iw_handler_def wl_iw_handler_def;
-#endif /* WIRELESS_EXT > 12 */
-
-extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data);
-extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats);
-int wl_iw_attach(struct net_device *dev, void * dhdp);
-int wl_iw_send_priv_event(struct net_device *dev, char *flag);
-
-void wl_iw_detach(void);
-
-#define CSCAN_COMMAND				"CSCAN "
-#define CSCAN_TLV_PREFIX 			'S'
-#define CSCAN_TLV_VERSION			1
-#define CSCAN_TLV_SUBVERSION			0
-#define CSCAN_TLV_TYPE_SSID_IE          'S'
-#define CSCAN_TLV_TYPE_CHANNEL_IE   'C'
-#define CSCAN_TLV_TYPE_NPROBE_IE     'N'
-#define CSCAN_TLV_TYPE_ACTIVE_IE      'A'
-#define CSCAN_TLV_TYPE_PASSIVE_IE    'P'
-#define CSCAN_TLV_TYPE_HOME_IE         'H'
-#define CSCAN_TLV_TYPE_STYPE_IE        'T'
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
-	iwe_stream_add_event(info, stream, ends, iwe, extra)
-#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \
-	iwe_stream_add_value(info, event, value, ends, iwe, event_len)
-#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \
-	iwe_stream_add_point(info, stream, ends, iwe, extra)
-#else
-#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
-	iwe_stream_add_event(stream, ends, iwe, extra)
-#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \
-	iwe_stream_add_value(event, value, ends, iwe, event_len)
-#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \
-	iwe_stream_add_point(stream, ends, iwe, extra)
-#endif
-
-#endif /* _wl_iw_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_linux_mon.c b/drivers/net/wireless/bcmdhd/wl_linux_mon.c
deleted file mode 100644
index 65e6240..0000000
--- a/drivers/net/wireless/bcmdhd/wl_linux_mon.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Broadcom Dongle Host Driver (DHD), Linux monitor network interface
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_linux_mon.c 514727 2014-11-12 03:02:48Z $
- */
-
-#include <osl.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-#include <linux/ieee80211.h>
-#include <linux/rtnetlink.h>
-#include <net/ieee80211_radiotap.h>
-
-#include <wlioctl.h>
-#include <bcmutils.h>
-#include <dhd_dbg.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-
-typedef enum monitor_states
-{
-	MONITOR_STATE_DEINIT = 0x0,
-	MONITOR_STATE_INIT = 0x1,
-	MONITOR_STATE_INTERFACE_ADDED = 0x2,
-	MONITOR_STATE_INTERFACE_DELETED = 0x4
-} monitor_states_t;
-int dhd_add_monitor(char *name, struct net_device **new_ndev);
-extern int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
-int dhd_del_monitor(struct net_device *ndev);
-int dhd_monitor_init(void *dhd_pub);
-int dhd_monitor_uninit(void);
-
-/**
- * Local declarations and defintions (not exposed)
- */
-#ifndef DHD_MAX_IFS
-#define DHD_MAX_IFS 16
-#endif
-#define MON_PRINT(format, ...) printk("DHD-MON: %s " format, __func__, ##__VA_ARGS__)
-#define MON_TRACE MON_PRINT
-
-typedef struct monitor_interface {
-	int radiotap_enabled;
-	struct net_device* real_ndev;	/* The real interface that the monitor is on */
-	struct net_device* mon_ndev;
-} monitor_interface;
-
-typedef struct dhd_linux_monitor {
-	void *dhd_pub;
-	monitor_states_t monitor_state;
-	monitor_interface mon_if[DHD_MAX_IFS];
-	struct mutex lock;		/* lock to protect mon_if */
-} dhd_linux_monitor_t;
-
-static dhd_linux_monitor_t g_monitor;
-
-static struct net_device* lookup_real_netdev(char *name);
-static monitor_interface* ndev_to_monif(struct net_device *ndev);
-static int dhd_mon_if_open(struct net_device *ndev);
-static int dhd_mon_if_stop(struct net_device *ndev);
-static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev);
-static void dhd_mon_if_set_multicast_list(struct net_device *ndev);
-static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr);
-
-static const struct net_device_ops dhd_mon_if_ops = {
-	.ndo_open		= dhd_mon_if_open,
-	.ndo_stop		= dhd_mon_if_stop,
-	.ndo_start_xmit		= dhd_mon_if_subif_start_xmit,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
-	.ndo_set_rx_mode = dhd_mon_if_set_multicast_list,
-#else
-	.ndo_set_multicast_list = dhd_mon_if_set_multicast_list,
-#endif
-	.ndo_set_mac_address 	= dhd_mon_if_change_mac,
-};
-
-/**
- * Local static function defintions
- */
-
-/* Look up dhd's net device table to find a match (e.g. interface "eth0" is a match for "mon.eth0"
- * "p2p-eth0-0" is a match for "mon.p2p-eth0-0")
- */
-static struct net_device* lookup_real_netdev(char *name)
-{
-	struct net_device *ndev_found = NULL;
-
-	int i;
-	int len = 0;
-	int last_name_len = 0;
-	struct net_device *ndev;
-
-	/* We need to find interface "p2p-p2p-0" corresponding to monitor interface "mon-p2p-0",
-	 * Once mon iface name reaches IFNAMSIZ, it is reset to p2p0-0 and corresponding mon
-	 * iface would be mon-p2p0-0.
-	 */
-	for (i = 0; i < DHD_MAX_IFS; i++) {
-		ndev = dhd_idx2net(g_monitor.dhd_pub, i);
-
-		/* Skip "p2p" and look for "-p2p0-x" in monitor interface name. If it
-		 * it matches, then this netdev is the corresponding real_netdev.
-		 */
-		if (ndev && strstr(ndev->name, "p2p-p2p0")) {
-			len = strlen("p2p");
-		} else {
-		/* if p2p- is not present, then the IFNAMSIZ have reached and name
-		 * would have got reset. In this casse,look for p2p0-x in mon-p2p0-x
-		 */
-			len = 0;
-		}
-		if (ndev && strstr(name, (ndev->name + len))) {
-			if (strlen(ndev->name) > last_name_len) {
-				ndev_found = ndev;
-				last_name_len = strlen(ndev->name);
-			}
-		}
-	}
-
-	return ndev_found;
-}
-
-static monitor_interface* ndev_to_monif(struct net_device *ndev)
-{
-	int i;
-
-	for (i = 0; i < DHD_MAX_IFS; i++) {
-		if (g_monitor.mon_if[i].mon_ndev == ndev)
-			return &g_monitor.mon_if[i];
-	}
-
-	return NULL;
-}
-
-static int dhd_mon_if_open(struct net_device *ndev)
-{
-	int ret = 0;
-
-	MON_PRINT("enter\n");
-	return ret;
-}
-
-static int dhd_mon_if_stop(struct net_device *ndev)
-{
-	int ret = 0;
-
-	MON_PRINT("enter\n");
-	return ret;
-}
-
-static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-	int ret = 0;
-	int rtap_len;
-	int qos_len = 0;
-	int dot11_hdr_len = 24;
-	int snap_len = 6;
-	unsigned char *pdata;
-	unsigned short frame_ctl;
-	unsigned char src_mac_addr[6];
-	unsigned char dst_mac_addr[6];
-	struct ieee80211_hdr *dot11_hdr;
-	struct ieee80211_radiotap_header *rtap_hdr;
-	monitor_interface* mon_if;
-
-	MON_PRINT("enter\n");
-
-	mon_if = ndev_to_monif(ndev);
-	if (mon_if == NULL || mon_if->real_ndev == NULL) {
-		MON_PRINT(" cannot find matched net dev, skip the packet\n");
-		goto fail;
-	}
-
-	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
-		goto fail;
-
-	rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
-	if (unlikely(rtap_hdr->it_version))
-		goto fail;
-
-	rtap_len = ieee80211_get_radiotap_len(skb->data);
-	if (unlikely(skb->len < rtap_len))
-		goto fail;
-
-	MON_PRINT("radiotap len (should be 14): %d\n", rtap_len);
-
-	/* Skip the ratio tap header */
-	skb_pull(skb, rtap_len);
-
-	dot11_hdr = (struct ieee80211_hdr *)skb->data;
-	frame_ctl = le16_to_cpu(dot11_hdr->frame_control);
-	/* Check if the QoS bit is set */
-	if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
-		/* Check if this ia a Wireless Distribution System (WDS) frame
-		 * which has 4 MAC addresses
-		 */
-		if (dot11_hdr->frame_control & 0x0080)
-			qos_len = 2;
-		if ((dot11_hdr->frame_control & 0x0300) == 0x0300)
-			dot11_hdr_len += 6;
-
-		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
-		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
-
-		/* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for
-		 * for two MAC addresses
-		 */
-		skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2);
-		pdata = (unsigned char*)skb->data;
-		memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));
-		memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr));
-		PKTSETPRIO(skb, 0);
-
-		MON_PRINT("if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name);
-
-		/* Use the real net device to transmit the packet */
-		ret = dhd_start_xmit(skb, mon_if->real_ndev);
-
-		return ret;
-	}
-fail:
-	dev_kfree_skb(skb);
-	return 0;
-}
-
-static void dhd_mon_if_set_multicast_list(struct net_device *ndev)
-{
-	monitor_interface* mon_if;
-
-	mon_if = ndev_to_monif(ndev);
-	if (mon_if == NULL || mon_if->real_ndev == NULL) {
-		MON_PRINT(" cannot find matched net dev, skip the packet\n");
-	} else {
-		MON_PRINT("enter, if name: %s, matched if name %s\n",
-		ndev->name, mon_if->real_ndev->name);
-	}
-}
-
-static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr)
-{
-	int ret = 0;
-	monitor_interface* mon_if;
-
-	mon_if = ndev_to_monif(ndev);
-	if (mon_if == NULL || mon_if->real_ndev == NULL) {
-		MON_PRINT(" cannot find matched net dev, skip the packet\n");
-	} else {
-		MON_PRINT("enter, if name: %s, matched if name %s\n",
-		ndev->name, mon_if->real_ndev->name);
-	}
-	return ret;
-}
-
-/**
- * Global function definitions (declared in dhd_linux_mon.h)
- */
-
-int dhd_add_monitor(char *name, struct net_device **new_ndev)
-{
-	int i;
-	int idx = -1;
-	int ret = 0;
-	struct net_device* ndev = NULL;
-	dhd_linux_monitor_t **dhd_mon;
-
-	mutex_lock(&g_monitor.lock);
-
-	MON_TRACE("enter, if name: %s\n", name);
-	if (!name || !new_ndev) {
-		MON_PRINT("invalid parameters\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/*
-	 * Find a vacancy
-	 */
-	for (i = 0; i < DHD_MAX_IFS; i++)
-		if (g_monitor.mon_if[i].mon_ndev == NULL) {
-			idx = i;
-			break;
-		}
-	if (idx == -1) {
-		MON_PRINT("exceeds maximum interfaces\n");
-		ret = -EFAULT;
-		goto out;
-	}
-
-	ndev = alloc_etherdev(sizeof(dhd_linux_monitor_t*));
-	if (!ndev) {
-		MON_PRINT("failed to allocate memory\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ndev->type = ARPHRD_IEEE80211_RADIOTAP;
-	strncpy(ndev->name, name, IFNAMSIZ);
-	ndev->name[IFNAMSIZ - 1] = 0;
-	ndev->netdev_ops = &dhd_mon_if_ops;
-
-	ret = register_netdevice(ndev);
-	if (ret) {
-		MON_PRINT(" register_netdevice failed (%d)\n", ret);
-		goto out;
-	}
-
-	*new_ndev = ndev;
-	g_monitor.mon_if[idx].radiotap_enabled = TRUE;
-	g_monitor.mon_if[idx].mon_ndev = ndev;
-	g_monitor.mon_if[idx].real_ndev = lookup_real_netdev(name);
-	dhd_mon = (dhd_linux_monitor_t **)netdev_priv(ndev);
-	*dhd_mon = &g_monitor;
-	g_monitor.monitor_state = MONITOR_STATE_INTERFACE_ADDED;
-	MON_PRINT("net device returned: 0x%p\n", ndev);
-	MON_PRINT("found a matched net device, name %s\n", g_monitor.mon_if[idx].real_ndev->name);
-
-out:
-	if (ret && ndev)
-		free_netdev(ndev);
-
-	mutex_unlock(&g_monitor.lock);
-	return ret;
-
-}
-
-int dhd_del_monitor(struct net_device *ndev)
-{
-	int i;
-	if (!ndev)
-		return -EINVAL;
-	mutex_lock(&g_monitor.lock);
-	for (i = 0; i < DHD_MAX_IFS; i++) {
-		if (g_monitor.mon_if[i].mon_ndev == ndev ||
-			g_monitor.mon_if[i].real_ndev == ndev) {
-
-			g_monitor.mon_if[i].real_ndev = NULL;
-			unregister_netdevice(g_monitor.mon_if[i].mon_ndev);
-			free_netdev(g_monitor.mon_if[i].mon_ndev);
-			g_monitor.mon_if[i].mon_ndev = NULL;
-			g_monitor.monitor_state = MONITOR_STATE_INTERFACE_DELETED;
-			break;
-		}
-	}
-
-	if (g_monitor.monitor_state != MONITOR_STATE_INTERFACE_DELETED)
-		MON_PRINT("IF not found in monitor array, is this a monitor IF? 0x%p\n", ndev);
-	mutex_unlock(&g_monitor.lock);
-
-	return 0;
-}
-
-int dhd_monitor_init(void *dhd_pub)
-{
-	if (g_monitor.monitor_state == MONITOR_STATE_DEINIT) {
-		g_monitor.dhd_pub = dhd_pub;
-		mutex_init(&g_monitor.lock);
-		g_monitor.monitor_state = MONITOR_STATE_INIT;
-	}
-	return 0;
-}
-
-int dhd_monitor_uninit(void)
-{
-	int i;
-	struct net_device *ndev;
-	mutex_lock(&g_monitor.lock);
-	if (g_monitor.monitor_state != MONITOR_STATE_DEINIT) {
-		for (i = 0; i < DHD_MAX_IFS; i++) {
-			ndev = g_monitor.mon_if[i].mon_ndev;
-			if (ndev) {
-				unregister_netdevice(ndev);
-				free_netdev(ndev);
-				g_monitor.mon_if[i].real_ndev = NULL;
-				g_monitor.mon_if[i].mon_ndev = NULL;
-			}
-		}
-		g_monitor.monitor_state = MONITOR_STATE_DEINIT;
-	}
-	mutex_unlock(&g_monitor.lock);
-	return 0;
-}
diff --git a/drivers/net/wireless/bcmdhd/wl_roam.c b/drivers/net/wireless/bcmdhd/wl_roam.c
deleted file mode 100644
index bddc755..0000000
--- a/drivers/net/wireless/bcmdhd/wl_roam.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Linux roam cache
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_roam.c 599089 2015-11-12 10:41:33Z $
- */
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c
deleted file mode 100644
index 8478de9..0000000
--- a/drivers/net/wireless/bcmdhd/wldev_common.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * Common function shared by Linux WEXT, cfg80211 and p2p drivers
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wldev_common.c 585478 2015-09-10 13:33:58Z $
- */
-
-#include <osl.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/netdevice.h>
-
-#include <wldev_common.h>
-#include <bcmutils.h>
-
-#define htod32(i) (i)
-#define htod16(i) (i)
-#define dtoh32(i) (i)
-#define dtoh16(i) (i)
-#define htodchanspec(i) (i)
-#define dtohchanspec(i) (i)
-
-#define	WLDEV_ERROR(args)						\
-	do {										\
-		printk(KERN_ERR "WLDEV-ERROR) ");	\
-		printk args;							\
-	} while (0)
-
-#define	WLDEV_INFO(args)						\
-	do {										\
-		printk(KERN_INFO "WLDEV-INFO) ");	\
-		printk args;							\
-	} while (0)
-
-extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd);
-
-s32 wldev_ioctl(
-	struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
-{
-	s32 ret = 0;
-	struct wl_ioctl ioc;
-
-
-	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = cmd;
-	ioc.buf = arg;
-	ioc.len = len;
-	ioc.set = set;
-
-	ret = dhd_ioctl_entry_local(dev, &ioc, cmd);
-
-	return ret;
-}
-
-/* Format a iovar buffer, not bsscfg indexed. The bsscfg index will be
- * taken care of in dhd_ioctl_entry. Internal use only, not exposed to
- * wl_iw, wl_cfg80211 and wl_cfgp2p
- */
-static s32 wldev_mkiovar(
-	const s8 *iovar_name, s8 *param, s32 paramlen,
-	s8 *iovar_buf, u32 buflen)
-{
-	s32 iolen = 0;
-
-	iolen = bcm_mkiovar(iovar_name, param, paramlen, iovar_buf, buflen);
-	return iolen;
-}
-
-s32 wldev_iovar_getbuf(
-	struct net_device *dev, s8 *iovar_name,
-	void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync)
-{
-	s32 ret = 0;
-	if (buf_sync) {
-		mutex_lock(buf_sync);
-	}
-	wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
-	ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE);
-	if (buf_sync)
-		mutex_unlock(buf_sync);
-	return ret;
-}
-
-
-s32 wldev_iovar_setbuf(
-	struct net_device *dev, s8 *iovar_name,
-	void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync)
-{
-	s32 ret = 0;
-	s32 iovar_len;
-	if (buf_sync) {
-		mutex_lock(buf_sync);
-	}
-	iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
-	if (iovar_len > 0)
-		ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
-	else
-		ret = BCME_BUFTOOSHORT;
-
-	if (buf_sync)
-		mutex_unlock(buf_sync);
-	return ret;
-}
-
-s32 wldev_iovar_setint(
-	struct net_device *dev, s8 *iovar, s32 val)
-{
-	s8 iovar_buf[WLC_IOCTL_SMLEN];
-
-	val = htod32(val);
-	memset(iovar_buf, 0, sizeof(iovar_buf));
-	return wldev_iovar_setbuf(dev, iovar, &val, sizeof(val), iovar_buf,
-		sizeof(iovar_buf), NULL);
-}
-
-
-s32 wldev_iovar_getint(
-	struct net_device *dev, s8 *iovar, s32 *pval)
-{
-	s8 iovar_buf[WLC_IOCTL_SMLEN];
-	s32 err;
-
-	memset(iovar_buf, 0, sizeof(iovar_buf));
-	err = wldev_iovar_getbuf(dev, iovar, pval, sizeof(*pval), iovar_buf,
-		sizeof(iovar_buf), NULL);
-	if (err == 0)
-	{
-		memcpy(pval, iovar_buf, sizeof(*pval));
-		*pval = dtoh32(*pval);
-	}
-	return err;
-}
-
-/** Format a bsscfg indexed iovar buffer. The bsscfg index will be
- *  taken care of in dhd_ioctl_entry. Internal use only, not exposed to
- *  wl_iw, wl_cfg80211 and wl_cfgp2p
- */
-s32 wldev_mkiovar_bsscfg(
-	const s8 *iovar_name, s8 *param, s32 paramlen,
-	s8 *iovar_buf, s32 buflen, s32 bssidx)
-{
-	const s8 *prefix = "bsscfg:";
-	s8 *p;
-	u32 prefixlen;
-	u32 namelen;
-	u32 iolen;
-
-	if (bssidx == 0) {
-		return wldev_mkiovar(iovar_name, param, paramlen,
-			iovar_buf, buflen);
-	}
-
-	prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
-	namelen = (u32) strlen(iovar_name) + 1; /* lengh of iovar  name + null */
-	iolen = prefixlen + namelen + sizeof(u32) + paramlen;
-
-	if (buflen < 0 || iolen > (u32)buflen)
-	{
-		WLDEV_ERROR(("%s: buffer is too short\n", __FUNCTION__));
-		return BCME_BUFTOOSHORT;
-	}
-
-	p = (s8 *)iovar_buf;
-
-	/* copy prefix, no null */
-	memcpy(p, prefix, prefixlen);
-	p += prefixlen;
-
-	/* copy iovar name including null */
-	memcpy(p, iovar_name, namelen);
-	p += namelen;
-
-	/* bss config index as first param */
-	bssidx = htod32(bssidx);
-	memcpy(p, &bssidx, sizeof(u32));
-	p += sizeof(u32);
-
-	/* parameter buffer follows */
-	if (paramlen)
-		memcpy(p, param, paramlen);
-
-	return iolen;
-
-}
-
-s32 wldev_iovar_getbuf_bsscfg(
-	struct net_device *dev, s8 *iovar_name,
-	void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
-{
-	s32 ret = 0;
-	if (buf_sync) {
-		mutex_lock(buf_sync);
-	}
-
-	wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
-	ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE);
-	if (buf_sync) {
-		mutex_unlock(buf_sync);
-	}
-	return ret;
-
-}
-
-s32 wldev_iovar_setbuf_bsscfg(
-	struct net_device *dev, s8 *iovar_name,
-	void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
-{
-	s32 ret = 0;
-	s32 iovar_len;
-	if (buf_sync) {
-		mutex_lock(buf_sync);
-	}
-	iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
-	if (iovar_len > 0)
-		ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
-	else {
-		ret = BCME_BUFTOOSHORT;
-	}
-
-	if (buf_sync) {
-		mutex_unlock(buf_sync);
-	}
-	return ret;
-}
-
-s32 wldev_iovar_setint_bsscfg(
-	struct net_device *dev, s8 *iovar, s32 val, s32 bssidx)
-{
-	s8 iovar_buf[WLC_IOCTL_SMLEN];
-
-	val = htod32(val);
-	memset(iovar_buf, 0, sizeof(iovar_buf));
-	return wldev_iovar_setbuf_bsscfg(dev, iovar, &val, sizeof(val), iovar_buf,
-		sizeof(iovar_buf), bssidx, NULL);
-}
-
-
-s32 wldev_iovar_getint_bsscfg(
-	struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx)
-{
-	s8 iovar_buf[WLC_IOCTL_SMLEN];
-	s32 err;
-
-	memset(iovar_buf, 0, sizeof(iovar_buf));
-	err = wldev_iovar_getbuf_bsscfg(dev, iovar, pval, sizeof(*pval), iovar_buf,
-		sizeof(iovar_buf), bssidx, NULL);
-	if (err == 0)
-	{
-		memcpy(pval, iovar_buf, sizeof(*pval));
-		*pval = dtoh32(*pval);
-	}
-	return err;
-}
-
-int wldev_get_link_speed(
-	struct net_device *dev, int *plink_speed)
-{
-	int error;
-
-	if (!plink_speed)
-		return -ENOMEM;
-	error = wldev_ioctl(dev, WLC_GET_RATE, plink_speed, sizeof(int), 0);
-	if (unlikely(error))
-		return error;
-
-	/* Convert internal 500Kbps to Kbps */
-	*plink_speed *= 500;
-	return error;
-}
-
-int wldev_get_rssi(
-	struct net_device *dev, scb_val_t *scb_val)
-{
-	int error;
-
-	if (!scb_val)
-		return -ENOMEM;
-
-	error = wldev_ioctl(dev, WLC_GET_RSSI, scb_val, sizeof(scb_val_t), 0);
-	if (unlikely(error))
-		return error;
-
-	return error;
-}
-
-int wldev_get_ssid(
-	struct net_device *dev, wlc_ssid_t *pssid)
-{
-	int error;
-
-	if (!pssid)
-		return -ENOMEM;
-	error = wldev_ioctl(dev, WLC_GET_SSID, pssid, sizeof(wlc_ssid_t), 0);
-	if (unlikely(error))
-		return error;
-	pssid->SSID_len = dtoh32(pssid->SSID_len);
-	return error;
-}
-
-int wldev_get_band(
-	struct net_device *dev, uint *pband)
-{
-	int error;
-
-	error = wldev_ioctl(dev, WLC_GET_BAND, pband, sizeof(uint), 0);
-	return error;
-}
-
-int wldev_set_band(
-	struct net_device *dev, uint band)
-{
-	int error = -1;
-
-	if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
-		error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
-		if (!error)
-			dhd_bus_band_set(dev, band);
-	}
-	return error;
-}
-int wldev_get_datarate(struct net_device *dev, int *datarate)
-{
-	int error = 0;
-
-	error = wldev_ioctl(dev, WLC_GET_RATE, datarate, sizeof(int), false);
-	if (error) {
-		return -1;
-	} else {
-		*datarate = dtoh32(*datarate);
-	}
-
-	return error;
-}
-
-extern chanspec_t
-wl_chspec_driver_to_host(chanspec_t chanspec);
-#define WL_EXTRA_BUF_MAX 2048
-int wldev_get_mode(
-	struct net_device *dev, uint8 *cap)
-{
-	int error = 0;
-	int chanspec = 0;
-	uint16 band = 0;
-	uint16 bandwidth = 0;
-	wl_bss_info_t *bss = NULL;
-	char* buf = kmalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
-	if (!buf)
-		return -1;
-	*(u32*) buf = htod32(WL_EXTRA_BUF_MAX);
-	error = wldev_ioctl(dev, WLC_GET_BSS_INFO, (void*)buf, WL_EXTRA_BUF_MAX, false);
-	if (error) {
-		WLDEV_ERROR(("%s:failed:%d\n", __FUNCTION__, error));
-		return -1;
-	}
-	bss = (struct  wl_bss_info *)(buf + 4);
-	chanspec = wl_chspec_driver_to_host(bss->chanspec);
-
-	band = chanspec & WL_CHANSPEC_BAND_MASK;
-	bandwidth = chanspec & WL_CHANSPEC_BW_MASK;
-
-	if (band == WL_CHANSPEC_BAND_2G) {
-		if (bss->n_cap)
-			strcpy(cap, "n");
-		else
-			strcpy(cap, "bg");
-	} else if (band == WL_CHANSPEC_BAND_5G) {
-		if (bandwidth == WL_CHANSPEC_BW_80)
-			strcpy(cap, "ac");
-		else if ((bandwidth == WL_CHANSPEC_BW_40) || (bandwidth == WL_CHANSPEC_BW_20)) {
-			if ((bss->nbss_cap & 0xf00) && (bss->n_cap))
-				strcpy(cap, "n|ac");
-			else if (bss->n_cap)
-				strcpy(cap, "n");
-			else if (bss->vht_cap)
-				strcpy(cap, "ac");
-			else
-				strcpy(cap, "a");
-		} else {
-			WLDEV_ERROR(("%s:Mode get failed\n", __FUNCTION__));
-			return -1;
-		}
-
-	}
-	return error;
-}
-int wldev_set_country(
-	struct net_device *dev, char *country_code, bool notify, bool user_enforced, int revinfo)
-{
-	int error = -1;
-	wl_country_t cspec = {{0}, 0, {0}};
-	scb_val_t scbval;
-	char smbuf[WLC_IOCTL_SMLEN];
-
-	if (!country_code)
-		return error;
-
-	bzero(&scbval, sizeof(scb_val_t));
-	error = wldev_iovar_getbuf(dev, "country", NULL, 0, &cspec, sizeof(cspec), NULL);
-	if (error < 0) {
-		WLDEV_ERROR(("%s: get country failed = %d\n", __FUNCTION__, error));
-		return error;
-	}
-
-	if ((error < 0) ||
-			dhd_force_country_change(dev) ||
-	    (strncmp(country_code, cspec.ccode, WLC_CNTRY_BUF_SZ) != 0)) {
-
-		if (user_enforced) {
-			bzero(&scbval, sizeof(scb_val_t));
-			error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true);
-			if (error < 0) {
-				WLDEV_ERROR(("%s: set country failed due to Disassoc error %d\n",
-					__FUNCTION__, error));
-				return error;
-			}
-		}
-
-		cspec.rev = revinfo;
-		memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ);
-		memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ);
-		dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec);
-		error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec),
-			smbuf, sizeof(smbuf), NULL);
-		if (error < 0) {
-			WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n",
-				__FUNCTION__, country_code, cspec.ccode, cspec.rev));
-			return error;
-		}
-		dhd_bus_country_set(dev, &cspec, notify);
-		WLDEV_INFO(("%s: set country for %s as %s rev %d\n",
-			__FUNCTION__, country_code, cspec.ccode, cspec.rev));
-	}
-	return 0;
-}
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h
deleted file mode 100644
index 4cf421c..0000000
--- a/drivers/net/wireless/bcmdhd/wldev_common.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Common function shared by Linux WEXT, cfg80211 and p2p drivers
- *
- * Copyright (C) 1999-2016, Broadcom Corporation
- * 
- *      Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- * 
- *      As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module.  An independent module is a module which is not
- * derived from this software.  The special exception does not apply to any
- * modifications of the software.
- * 
- *      Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wldev_common.h 556083 2015-05-12 14:03:00Z $
- */
-#ifndef __WLDEV_COMMON_H__
-#define __WLDEV_COMMON_H__
-
-#include <wlioctl.h>
-
-/* wl_dev_ioctl - get/set IOCTLs, will call net_device's do_ioctl (or
- *  netdev_ops->ndo_do_ioctl in new kernels)
- *  @dev: the net_device handle
- */
-s32 wldev_ioctl(
-	struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set);
-
-/** Retrieve named IOVARs, this function calls wl_dev_ioctl with
- *  WLC_GET_VAR IOCTL code
- */
-s32 wldev_iovar_getbuf(
-	struct net_device *dev, s8 *iovar_name,
-	void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync);
-
-/** Set named IOVARs, this function calls wl_dev_ioctl with
- *  WLC_SET_VAR IOCTL code
- */
-s32 wldev_iovar_setbuf(
-	struct net_device *dev, s8 *iovar_name,
-	void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync);
-
-s32 wldev_iovar_setint(
-	struct net_device *dev, s8 *iovar, s32 val);
-
-s32 wldev_iovar_getint(
-	struct net_device *dev, s8 *iovar, s32 *pval);
-
-/** The following function can be implemented if there is a need for bsscfg
- *  indexed IOVARs
- */
-
-s32 wldev_mkiovar_bsscfg(
-	const s8 *iovar_name, s8 *param, s32 paramlen,
-	s8 *iovar_buf, s32 buflen, s32 bssidx);
-
-/** Retrieve named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
- *  WLC_GET_VAR IOCTL code
- */
-s32 wldev_iovar_getbuf_bsscfg(
-	struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen,
-	void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync);
-
-/** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
- *  WLC_SET_VAR IOCTL code
- */
-s32 wldev_iovar_setbuf_bsscfg(
-	struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen,
-	void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync);
-
-s32 wldev_iovar_getint_bsscfg(
-	struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx);
-
-s32 wldev_iovar_setint_bsscfg(
-	struct net_device *dev, s8 *iovar, s32 val, s32 bssidx);
-
-extern int dhd_net_set_fw_path(struct net_device *dev, char *fw);
-extern int dhd_net_bus_suspend(struct net_device *dev);
-extern int dhd_net_bus_resume(struct net_device *dev, uint8 stage);
-extern int dhd_net_wifi_platform_set_power(struct net_device *dev, bool on,
-	unsigned long delay_msec);
-extern void dhd_get_customized_country_code(struct net_device *dev, char *country_iso_code,
-	wl_country_t *cspec);
-extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify);
-extern bool dhd_force_country_change(struct net_device *dev);
-extern void dhd_bus_band_set(struct net_device *dev, uint band);
-extern int wldev_set_country(struct net_device *dev, char *country_code, bool notify,
-	bool user_enforced, int revinfo);
-extern int net_os_wake_lock(struct net_device *dev);
-extern int net_os_wake_unlock(struct net_device *dev);
-extern int net_os_wake_lock_timeout(struct net_device *dev);
-extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val);
-extern int net_os_set_dtim_skip(struct net_device *dev, int val);
-extern int net_os_set_suspend_disable(struct net_device *dev, int val);
-extern int net_os_set_suspend(struct net_device *dev, int val, int force);
-extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_ext_t* ssid,
-	int max, int *bytes_left);
-
-/* Get the link speed from dongle, speed is in kpbs */
-int wldev_get_link_speed(struct net_device *dev, int *plink_speed);
-
-int wldev_get_rssi(struct net_device *dev, scb_val_t *prssi);
-
-int wldev_get_ssid(struct net_device *dev, wlc_ssid_t *pssid);
-
-int wldev_get_band(struct net_device *dev, uint *pband);
-int wldev_get_mode(struct net_device *dev, uint8 *pband);
-int wldev_get_datarate(struct net_device *dev, int *datarate);
-int wldev_set_band(struct net_device *dev, uint band);
-
-#endif /* __WLDEV_COMMON_H__ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 410a664..59cef6c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -726,8 +726,10 @@
 			return -ENOMEM;
 		err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
 					 glom_skb);
-		if (err)
+		if (err) {
+			brcmu_pkt_buf_free_skb(glom_skb);
 			goto done;
+		}
 
 		skb_queue_walk(pktq, skb) {
 			memcpy(skb->data, glom_skb->data, skb->len);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
index deb5f78..70a6985 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
@@ -2408,7 +2408,7 @@
 				     WL_BSS_INFO_MAX);
 	if (err) {
 		brcmf_err("Failed to get bss info (%d)\n", err);
-		return;
+		goto out_kfree;
 	}
 	si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
 	si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
@@ -2420,6 +2420,9 @@
 		si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
 	if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
 		si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
+
+out_kfree:
+	kfree(buf);
 }
 
 static s32
@@ -4099,7 +4102,7 @@
 				(u8 *)&settings->beacon.head[ie_offset],
 				settings->beacon.head_len - ie_offset,
 				WLAN_EID_SSID);
-		if (!ssid_ie)
+		if (!ssid_ie || ssid_ie->len > IEEE80211_MAX_SSID_LEN)
 			return -EINVAL;
 
 		memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index b5ab98e..82753e7 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -211,7 +211,7 @@
 	int ret;
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_pub *drvr = ifp->drvr;
-	struct ethhdr *eh = (struct ethhdr *)(skb->data);
+	struct ethhdr *eh;
 
 	brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx);
 
@@ -232,22 +232,13 @@
 		goto done;
 	}
 
-	/* Make sure there's enough room for any header */
-	if (skb_headroom(skb) < drvr->hdrlen) {
-		struct sk_buff *skb2;
-
-		brcmf_dbg(INFO, "%s: insufficient headroom\n",
+	/* Make sure there's enough writable headroom*/
+	ret = skb_cow_head(skb, drvr->hdrlen);
+	if (ret < 0) {
+		brcmf_err("%s: skb_cow_head failed\n",
 			  brcmf_ifname(drvr, ifp->bssidx));
-		drvr->bus_if->tx_realloc++;
-		skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
 		dev_kfree_skb(skb);
-		skb = skb2;
-		if (skb == NULL) {
-			brcmf_err("%s: skb_realloc_headroom failed\n",
-				  brcmf_ifname(drvr, ifp->bssidx));
-			ret = -ENOMEM;
-			goto done;
-		}
+		goto done;
 	}
 
 	/* validate length for ether packet */
@@ -257,6 +248,8 @@
 		goto done;
 	}
 
+	eh = (struct ethhdr *)(skb->data);
+
 	if (eh->h_proto == htons(ETH_P_PAE))
 		atomic_inc(&ifp->pend_8021x_cnt);
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
index 7e74ac3..bcf29bf 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
@@ -3401,10 +3401,6 @@
 		goto err;
 	}
 
-	/* Allow full data communication using DPC from now on. */
-	brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
-	bcmerror = 0;
-
 err:
 	brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
 	sdio_release_host(bus->sdiodev->func[1]);
@@ -4112,6 +4108,9 @@
 	}
 
 	if (err == 0) {
+		/* Allow full data communication using DPC from now on. */
+		brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
+
 		err = brcmf_sdiod_intr_register(sdiodev);
 		if (err != 0)
 			brcmf_err("intr register failed:%d\n", err);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
index 796f5f9..b7df576 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
@@ -1079,8 +1079,10 @@
 
 		pa = dma_map_single(di->dmadev, p->data, di->rxbufsize,
 				    DMA_FROM_DEVICE);
-		if (dma_mapping_error(di->dmadev, pa))
+		if (dma_mapping_error(di->dmadev, pa)) {
+			brcmu_pkt_buf_free_skb(p);
 			return false;
+		}
 
 		/* save the free packet pointer */
 		di->rxp[rxout] = p;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index bec2dc1..61ae276 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -818,13 +818,15 @@
 static int
 brcms_ops_ampdu_action(struct ieee80211_hw *hw,
 		    struct ieee80211_vif *vif,
-		    enum ieee80211_ampdu_mlme_action action,
-		    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-		    u8 buf_size, bool amsdu)
+		    struct ieee80211_ampdu_params *params)
 {
 	struct brcms_info *wl = hw->priv;
 	struct scb *scb = &wl->wlc->pri_scb;
 	int status;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u8 buf_size = params->buf_size;
 
 	if (WARN_ON(scb->magic != SCB_MAGIC))
 		return -EIDRM;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
index dd91627..0ab865d 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/stf.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
@@ -87,7 +87,7 @@
 brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
 			    u16 chanspec)
 {
-	struct tx_power power;
+	struct tx_power power = { };
 	u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
 
 	/* Clear previous settings */
diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c
index 95a7fdb..c602a1e 100644
--- a/drivers/net/wireless/cw1200/sta.c
+++ b/drivers/net/wireless/cw1200/sta.c
@@ -2135,9 +2135,7 @@
 
 int cw1200_ampdu_action(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			u8 buf_size, bool amsdu)
+			struct ieee80211_ampdu_params *params)
 {
 	/* Aggregation is implemented fully in firmware,
 	 * including block ack negotiation. Do not allow
diff --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h
index bebb337..a0bacaa 100644
--- a/drivers/net/wireless/cw1200/sta.h
+++ b/drivers/net/wireless/cw1200/sta.h
@@ -109,9 +109,7 @@
 			     u32 changed);
 int cw1200_ampdu_action(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			u8 buf_size, bool amsdu);
+			struct ieee80211_ampdu_params *params);
 
 void cw1200_suspend_resume(struct cw1200_common *priv,
 			  struct wsm_suspend_resume *arg);
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 6df3ee5..515aa3f 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -836,25 +836,30 @@
 	spin_lock_bh(&local->baplock);
 
 	res = hfa384x_setup_bap(dev, BAP0, rid, 0);
-	if (!res)
-		res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec));
+	if (res)
+		goto unlock;
+
+	res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec));
+	if (res)
+		goto unlock;
 
 	if (le16_to_cpu(rec.len) == 0) {
 		/* RID not available */
 		res = -ENODATA;
+		goto unlock;
 	}
 
 	rlen = (le16_to_cpu(rec.len) - 1) * 2;
-	if (!res && exact_len && rlen != len) {
+	if (exact_len && rlen != len) {
 		printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: "
 		       "rid=0x%04x, len=%d (expected %d)\n",
 		       dev->name, rid, rlen, len);
 		res = -ENODATA;
 	}
 
-	if (!res)
-		res = hfa384x_from_bap(dev, BAP0, buf, len);
+	res = hfa384x_from_bap(dev, BAP0, buf, len);
 
+unlock:
 	spin_unlock_bh(&local->baplock);
 	mutex_unlock(&local->rid_bap_mtx);
 
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index 93bdf68..ae047ab 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -1019,12 +1019,13 @@
 	int txq_id;
 
 	/* Tx queues */
-	if (il->txq)
+	if (il->txq) {
 		for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
 			if (txq_id == IL39_CMD_QUEUE_NUM)
 				il_cmd_queue_free(il);
 			else
 				il_tx_queue_free(il, txq_id);
+	}
 
 	/* free tx queue structure */
 	il_free_txq_mem(il);
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 6656215..04b0349 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -5982,12 +5982,14 @@
 
 int
 il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 * ssn,
-			u8 buf_size, bool amsdu)
+			struct ieee80211_ampdu_params *params)
 {
 	struct il_priv *il = hw->priv;
 	int ret = -EINVAL;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid);
 
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
index 8ab8706..e432715 100644
--- a/drivers/net/wireless/iwlegacy/4965.h
+++ b/drivers/net/wireless/iwlegacy/4965.h
@@ -182,9 +182,7 @@
 				struct ieee80211_sta *sta, u32 iv32,
 				u16 *phase1key);
 int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 * ssn,
-			    u8 buf_size, bool amsdu);
+			    struct ieee80211_ampdu_params *params);
 int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta);
 void
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c
index 20e6aa9..c148085 100644
--- a/drivers/net/wireless/iwlwifi/dvm/calib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/calib.c
@@ -901,7 +901,7 @@
 		/* bound gain by 2 bits value max, 3rd bit is sign */
 		data->delta_gain_code[i] =
 			min(abs(delta_g),
-			(long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
+			(s32) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
 
 		if (delta_g < 0)
 			/*
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index b3ad34e..1eb1a82 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -729,12 +729,15 @@
 
 static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif,
-				   enum ieee80211_ampdu_mlme_action action,
-				   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-				   u8 buf_size, bool amsdu)
+				   struct ieee80211_ampdu_params *params)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
 	int ret = -EINVAL;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
+	u8 buf_size = params->buf_size;
 	struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
 
 	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 610c442..9584f95 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -935,7 +935,8 @@
 	}
 
 	mvm->fw_dbg_conf = conf_id;
-	return ret;
+
+	return 0;
 }
 
 static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index f96ab2f..1a8ea77 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -826,13 +826,16 @@
 
 static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
-				    enum ieee80211_ampdu_mlme_action action,
-				    struct ieee80211_sta *sta, u16 tid,
-				    u16 *ssn, u8 buf_size, bool amsdu)
+				    struct ieee80211_ampdu_params *params)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	int ret;
 	bool tx_agg_ref = false;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
+	u8 buf_size = params->buf_size;
 
 	IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n",
 		     sta->addr, tid, action);
@@ -3992,8 +3995,8 @@
 	if (idx != 0)
 		return -ENOENT;
 
-	if (fw_has_capa(&mvm->fw->ucode_capa,
-			IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
+	if (!fw_has_capa(&mvm->fw->ucode_capa,
+			 IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
 		return -ENOENT;
 
 	mutex_lock(&mvm->mutex);
@@ -4039,8 +4042,8 @@
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
-	if (fw_has_capa(&mvm->fw->ucode_capa,
-			IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
+	if (!fw_has_capa(&mvm->fw->ucode_capa,
+			 IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
 		return;
 
 	/* if beacon filtering isn't on mac80211 does it anyway */
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c
index b0f59fd..d7d72ad 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sf.c
@@ -215,7 +215,7 @@
 			     enum iwl_sf_state new_state)
 {
 	struct iwl_sf_cfg_cmd sf_cmd = {
-		.state = cpu_to_le32(SF_FULL_ON),
+		.state = cpu_to_le32(new_state),
 	};
 	struct ieee80211_sta *sta;
 	int ret = 0;
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index d58c094..f7e6a09 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -475,48 +475,64 @@
 MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
 
 #ifdef CONFIG_ACPI
-#define SPL_METHOD		"SPLC"
-#define SPL_DOMAINTYPE_MODULE	BIT(0)
-#define SPL_DOMAINTYPE_WIFI	BIT(1)
-#define SPL_DOMAINTYPE_WIGIG	BIT(2)
-#define SPL_DOMAINTYPE_RFEM	BIT(3)
+#define ACPI_SPLC_METHOD	"SPLC"
+#define ACPI_SPLC_DOMAIN_WIFI	(0x07)
 
-static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx)
+static u64 splc_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splc)
 {
-	union acpi_object *limits, *domain_type, *power_limit;
+	union acpi_object *data_pkg, *dflt_pwr_limit;
+	int i;
 
-	if (splx->type != ACPI_TYPE_PACKAGE ||
-	    splx->package.count != 2 ||
-	    splx->package.elements[0].type != ACPI_TYPE_INTEGER ||
-	    splx->package.elements[0].integer.value != 0) {
-		IWL_ERR(trans, "Unsupported splx structure\n");
+	/* We need at least two elements, one for the revision and one
+	 * for the data itself.  Also check that the revision is
+	 * supported (currently only revision 0).
+	*/
+	if (splc->type != ACPI_TYPE_PACKAGE ||
+	    splc->package.count < 2 ||
+	    splc->package.elements[0].type != ACPI_TYPE_INTEGER ||
+	    splc->package.elements[0].integer.value != 0) {
+		IWL_DEBUG_INFO(trans,
+			       "Unsupported structure returned by the SPLC method.  Ignoring.\n");
 		return 0;
 	}
 
-	limits = &splx->package.elements[1];
-	if (limits->type != ACPI_TYPE_PACKAGE ||
-	    limits->package.count < 2 ||
-	    limits->package.elements[0].type != ACPI_TYPE_INTEGER ||
-	    limits->package.elements[1].type != ACPI_TYPE_INTEGER) {
-		IWL_ERR(trans, "Invalid limits element\n");
+	/* loop through all the packages to find the one for WiFi */
+	for (i = 1; i < splc->package.count; i++) {
+		union acpi_object *domain;
+
+		data_pkg = &splc->package.elements[i];
+
+		/* Skip anything that is not a package with the right
+		 * amount of elements (i.e. at least 2 integers).
+		 */
+		if (data_pkg->type != ACPI_TYPE_PACKAGE ||
+		    data_pkg->package.count < 2 ||
+		    data_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
+		    data_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
+			continue;
+
+		domain = &data_pkg->package.elements[0];
+		if (domain->integer.value == ACPI_SPLC_DOMAIN_WIFI)
+			break;
+
+		data_pkg = NULL;
+	}
+
+	if (!data_pkg) {
+		IWL_DEBUG_INFO(trans,
+			       "No element for the WiFi domain returned by the SPLC method.\n");
 		return 0;
 	}
 
-	domain_type = &limits->package.elements[0];
-	power_limit = &limits->package.elements[1];
-	if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) {
-		IWL_DEBUG_INFO(trans, "WiFi power is not limited\n");
-		return 0;
-	}
-
-	return power_limit->integer.value;
+	dflt_pwr_limit = &data_pkg->package.elements[1];
+	return dflt_pwr_limit->integer.value;
 }
 
 static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev)
 {
 	acpi_handle pxsx_handle;
 	acpi_handle handle;
-	struct acpi_buffer splx = {ACPI_ALLOCATE_BUFFER, NULL};
+	struct acpi_buffer splc = {ACPI_ALLOCATE_BUFFER, NULL};
 	acpi_status status;
 
 	pxsx_handle = ACPI_HANDLE(&pdev->dev);
@@ -527,23 +543,24 @@
 	}
 
 	/* Get the method's handle */
-	status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle);
+	status = acpi_get_handle(pxsx_handle, (acpi_string)ACPI_SPLC_METHOD,
+				 &handle);
 	if (ACPI_FAILURE(status)) {
-		IWL_DEBUG_INFO(trans, "SPL method not found\n");
+		IWL_DEBUG_INFO(trans, "SPLC method not found\n");
 		return;
 	}
 
 	/* Call SPLC with no arguments */
-	status = acpi_evaluate_object(handle, NULL, NULL, &splx);
+	status = acpi_evaluate_object(handle, NULL, NULL, &splc);
 	if (ACPI_FAILURE(status)) {
 		IWL_ERR(trans, "SPLC invocation failed (0x%x)\n", status);
 		return;
 	}
 
-	trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer);
+	trans->dflt_pwr_limit = splc_get_pwr_limit(trans, splc.pointer);
 	IWL_DEBUG_INFO(trans, "Default power limit set to %lld\n",
 		       trans->dflt_pwr_limit);
-	kfree(splx.pointer);
+	kfree(splc.pointer);
 }
 
 #else /* CONFIG_ACPI */
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index a8c8a4a..8dfe6b2 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1508,9 +1508,9 @@
 
 	/* start the TFD with the scratchbuf */
 	scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE);
-	memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size);
+	memcpy(&txq->scratchbufs[idx], &out_cmd->hdr, scratch_size);
 	iwl_pcie_txq_build_tfd(trans, txq,
-			       iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr),
+			       iwl_pcie_get_scratchbuf_dma(txq, idx),
 			       scratch_size, true);
 
 	/* map first command fragment, if any remains */
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c00a7daaa..019d716 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1817,10 +1817,12 @@
 
 static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
-				       enum ieee80211_ampdu_mlme_action action,
-				       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-				       u8 buf_size, bool amsdu)
+				       struct ieee80211_ampdu_params *params)
 {
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
 		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
@@ -2537,7 +2539,7 @@
 
 	tasklet_hrtimer_init(&data->beacon_timer,
 			     mac80211_hwsim_beacon,
-			     CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS);
+			     CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
 
 	spin_lock_bh(&hwsim_radio_lock);
 	list_add_tail(&data->list, &hwsim_radios);
@@ -2723,6 +2725,7 @@
 	if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
 	    !info->attrs[HWSIM_ATTR_FLAGS] ||
 	    !info->attrs[HWSIM_ATTR_COOKIE] ||
+	    !info->attrs[HWSIM_ATTR_SIGNAL] ||
 	    !info->attrs[HWSIM_ATTR_TX_INFO])
 		goto out;
 
diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c
index f715eee..e70dd95 100644
--- a/drivers/net/wireless/mediatek/mt7601u/main.c
+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
@@ -334,11 +334,13 @@
 
 static int
 mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		  enum ieee80211_ampdu_mlme_action action,
-		  struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
-		  bool amsdu)
+		  struct ieee80211_ampdu_params *params)
 {
 	struct mt7601u_dev *dev = hw->priv;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 	struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
 
 	WARN_ON(msta->wcid.idx > GROUP_WCID(0));
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index aa498e0..49f3e17 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -101,13 +101,6 @@
 {
 	struct txpd *local_tx_pd;
 	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
-	unsigned int pad;
-	int headroom = (priv->adapter->iface_type ==
-			MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
-
-	pad = ((void *)skb->data - sizeof(*local_tx_pd) -
-		headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1);
-	skb_push(skb, pad);
 
 	skb_push(skb, sizeof(*local_tx_pd));
 
@@ -121,12 +114,10 @@
 	local_tx_pd->bss_num = priv->bss_num;
 	local_tx_pd->bss_type = priv->bss_type;
 	/* Always zero as the data is followed by struct txpd */
-	local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) +
-						 pad);
+	local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
 	local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU);
 	local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len -
-						 sizeof(*local_tx_pd) -
-						 pad);
+						 sizeof(*local_tx_pd));
 
 	if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
 		local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
@@ -190,7 +181,11 @@
 				       ra_list_flags);
 		return -1;
 	}
-	skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN);
+
+	/* skb_aggr->data already 64 byte align, just reserve bus interface
+	 * header and txpd.
+	 */
+	skb_reserve(skb_aggr, headroom + sizeof(struct txpd));
 	tx_info_aggr =  MWIFIEX_SKB_TXCB(skb_aggr);
 
 	memset(tx_info_aggr, 0, sizeof(*tx_info_aggr));
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 4073116..c3331d6 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2144,8 +2144,9 @@
 			is_scanning_required = 1;
 		} else {
 			mwifiex_dbg(priv->adapter, MSG,
-				    "info: trying to associate to '%s' bssid %pM\n",
-				    (char *)req_ssid.ssid, bss->bssid);
+				    "info: trying to associate to '%.*s' bssid %pM\n",
+				    req_ssid.ssid_len, (char *)req_ssid.ssid,
+				    bss->bssid);
 			memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
 			break;
 		}
@@ -2202,8 +2203,8 @@
 	}
 
 	mwifiex_dbg(adapter, INFO,
-		    "info: Trying to associate to %s and bssid %pM\n",
-		    (char *)sme->ssid, sme->bssid);
+		    "info: Trying to associate to %.*s and bssid %pM\n",
+		    (int)sme->ssid_len, (char *)sme->ssid, sme->bssid);
 
 	ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
 				     priv->bss_mode, sme->channel, sme, 0);
@@ -2333,8 +2334,8 @@
 	}
 
 	mwifiex_dbg(priv->adapter, MSG,
-		    "info: trying to join to %s and bssid %pM\n",
-		    (char *)params->ssid, params->bssid);
+		    "info: trying to join to %.*s and bssid %pM\n",
+		    params->ssid_len, (char *)params->ssid, params->bssid);
 
 	mwifiex_set_ibss_params(priv, params);
 
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index 9824d8d..45d97b6 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -115,7 +115,8 @@
 	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
 		p += sprintf(p, "multicast_count=\"%d\"\n",
 			     netdev_mc_count(netdev));
-		p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
+		p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len,
+			     info.ssid.ssid);
 		p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
 		p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
 		p += sprintf(p, "country_code = \"%s\"\n", info.country_code);
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 3cda1f9..6378dfd 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -661,9 +661,8 @@
 	priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN,
 				   sizeof(priv->assoc_rsp_buf));
 
-	memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size);
-
 	assoc_rsp->a_id = cpu_to_le16(aid);
+	memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size);
 
 	if (status_code) {
 		priv->adapter->dbg.num_cmd_assoc_failure++;
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 21192b6..268e50b 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -947,6 +947,7 @@
 	if (card && card->cmd_buf) {
 		mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
 					 PCI_DMA_TODEVICE);
+		dev_kfree_skb_any(card->cmd_buf);
 	}
 	return 0;
 }
@@ -1513,6 +1514,11 @@
 		return -1;
 
 	card->cmd_buf = skb;
+	/*
+	 * Need to keep a reference, since core driver might free up this
+	 * buffer before we've unmapped it.
+	 */
+	skb_get(skb);
 
 	/* To send a command, the driver will:
 		1. Write the 64bit physical address of the data buffer to
@@ -1610,6 +1616,7 @@
 	if (card->cmd_buf) {
 		mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
 					 PCI_DMA_TODEVICE);
+		dev_kfree_skb_any(card->cmd_buf);
 		card->cmd_buf = NULL;
 	}
 
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index d6c4f0f..6cfa296 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -1098,8 +1098,6 @@
 			encrypt_key.is_rx_seq_valid = true;
 		}
 	} else {
-		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
-			return 0;
 		encrypt_key.key_disable = true;
 		if (mac_addr)
 			memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 30e3aaa..088429d 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -5421,11 +5421,13 @@
 
 static int
 mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		   enum ieee80211_ampdu_mlme_action action,
-		   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-		   u8 buf_size, bool amsdu)
+		   struct ieee80211_ampdu_params *params)
 {
-
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
+	u8 buf_size = params->buf_size;
 	int i, rc = 0;
 	struct mwl8k_priv *priv = hw->priv;
 	struct mwl8k_ampdu_stream *stream;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
index 6aed923..7d820c3 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
@@ -5375,13 +5375,13 @@
 
 static int
 rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		      enum ieee80211_ampdu_mlme_action action,
-		      struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
-		      bool amsdu)
+		      struct ieee80211_ampdu_params *params)
 {
 	struct rtl8xxxu_priv *priv = hw->priv;
 	struct device *dev = &priv->udev->dev;
 	u8 ampdu_factor, ampdu_density;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
 
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 0517a4f..aab7523 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -1303,12 +1303,13 @@
 
 static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc)
 {
+	struct ieee80211_hw *hw = rtlpriv->hw;
+
 	rtlpriv->ra.is_special_data = true;
 	if (rtlpriv->cfg->ops->get_btc_status())
 		rtlpriv->btcoexist.btc_ops->btc_special_packet_notify(
 					rtlpriv, 1);
-	rtlpriv->enter_ps = false;
-	schedule_work(&rtlpriv->works.lps_change_work);
+	rtl_lps_leave(hw);
 	ppsc->last_delaylps_stamp_jiffies = jiffies;
 }
 
@@ -1381,8 +1382,7 @@
 
 		if (is_tx) {
 			rtlpriv->ra.is_special_data = true;
-			rtlpriv->enter_ps = false;
-			schedule_work(&rtlpriv->works.lps_change_work);
+			rtl_lps_leave(hw);
 			ppsc->last_delaylps_stamp_jiffies = jiffies;
 		}
 
@@ -1660,9 +1660,9 @@
 		if (((rtlpriv->link_info.num_rx_inperiod +
 		      rtlpriv->link_info.num_tx_inperiod) > 8) ||
 		    (rtlpriv->link_info.num_rx_inperiod > 2))
-			rtl_lps_enter(hw);
-		else
 			rtl_lps_leave(hw);
+		else
+			rtl_lps_enter(hw);
 	}
 
 	rtlpriv->link_info.num_rx_inperiod = 0;
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
index f2b9d11..e85f165 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
@@ -1203,7 +1203,6 @@
 
 		/* Force GNT_BT to low */
 		btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0);
-		btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
 
 		if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) {
 			/* tell firmware "no antenna inverse" */
@@ -1211,19 +1210,25 @@
 			h2c_parameter[1] = 1;  /* ext switch type */
 			btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
 						h2c_parameter);
+			btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
 		} else {
 			/* tell firmware "antenna inverse" */
 			h2c_parameter[0] = 1;
 			h2c_parameter[1] = 1;  /* ext switch type */
 			btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
 						h2c_parameter);
+			btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280);
 		}
 	}
 
 	/* ext switch setting */
 	if (use_ext_switch) {
 		/* fixed internal switch S1->WiFi, S0->BT */
-		btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
+		if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT)
+			btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
+		else
+			btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280);
+
 		switch (antpos_type) {
 		case BTC_ANT_WIFI_AT_MAIN:
 			/* ext switch main at wifi */
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index b2791c8..babd149 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -965,13 +965,38 @@
 	}
 }
 
-void exhalbtc_set_ant_num(u8 type, u8 ant_num)
+void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num)
 {
 	if (BT_COEX_ANT_TYPE_PG == type) {
 		gl_bt_coexist.board_info.pg_ant_num = ant_num;
 		gl_bt_coexist.board_info.btdm_ant_num = ant_num;
+		/* The antenna position:
+		 * Main (default) or Aux for pgAntNum=2 && btdmAntNum =1.
+		 * The antenna position should be determined by
+		 * auto-detect mechanism.
+		 * The following is assumed to main,
+		 * and those must be modified
+		 * if y auto-detect mechanism is ready
+		 */
+		if ((gl_bt_coexist.board_info.pg_ant_num == 2) &&
+		    (gl_bt_coexist.board_info.btdm_ant_num == 1))
+			gl_bt_coexist.board_info.btdm_ant_pos =
+						       BTC_ANTENNA_AT_MAIN_PORT;
+		else
+			gl_bt_coexist.board_info.btdm_ant_pos =
+						       BTC_ANTENNA_AT_MAIN_PORT;
 	} else if (BT_COEX_ANT_TYPE_ANTDIV == type) {
 		gl_bt_coexist.board_info.btdm_ant_num = ant_num;
+		gl_bt_coexist.board_info.btdm_ant_pos =
+						       BTC_ANTENNA_AT_MAIN_PORT;
+	} else if (type == BT_COEX_ANT_TYPE_DETECTED) {
+		gl_bt_coexist.board_info.btdm_ant_num = ant_num;
+		if (rtlpriv->cfg->mod_params->ant_sel == 1)
+			gl_bt_coexist.board_info.btdm_ant_pos =
+				BTC_ANTENNA_AT_AUX_PORT;
+		else
+			gl_bt_coexist.board_info.btdm_ant_pos =
+				BTC_ANTENNA_AT_MAIN_PORT;
 	}
 }
 
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
index 0a903ea..f41ca57 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -535,7 +535,7 @@
 void exhalbtc_update_min_bt_rssi(char bt_rssi);
 void exhalbtc_set_bt_exist(bool bt_exist);
 void exhalbtc_set_chip_type(u8 chip_type);
-void exhalbtc_set_ant_num(u8 type, u8 ant_num);
+void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num);
 void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist);
 void exhalbtc_signal_compensation(struct btc_coexist *btcoexist,
 				  u8 *rssi_wifi, u8 *rssi_bt);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
index b9b0cb7..d3fd921 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
@@ -72,7 +72,10 @@
 		 __func__, bt_type);
 	exhalbtc_set_chip_type(bt_type);
 
-	exhalbtc_set_ant_num(BT_COEX_ANT_TYPE_PG, ant_num);
+	if (rtlpriv->cfg->mod_params->ant_sel == 1)
+		exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_DETECTED, 1);
+	else
+		exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_PG, ant_num);
 }
 
 void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index c925a4d..8b537a5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1153,10 +1153,8 @@
 		} else {
 			mstatus = RT_MEDIA_DISCONNECT;
 
-			if (mac->link_state == MAC80211_LINKED) {
-				rtlpriv->enter_ps = false;
-				schedule_work(&rtlpriv->works.lps_change_work);
-			}
+			if (mac->link_state == MAC80211_LINKED)
+				rtl_lps_leave(hw);
 			if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
 				rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
 			mac->link_state = MAC80211_NOLINK;
@@ -1371,11 +1369,13 @@
 
 static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
-			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			       u8 buf_size, bool amsdu)
+			       struct ieee80211_ampdu_params *params)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
@@ -1432,8 +1432,7 @@
 	}
 
 	if (mac->link_state == MAC80211_LINKED) {
-		rtlpriv->enter_ps = false;
-		schedule_work(&rtlpriv->works.lps_change_work);
+		rtl_lps_leave(hw);
 		mac->link_state = MAC80211_LINKED_SCANNING;
 	} else {
 		rtl_ips_nic_on(hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 7f471bf..a5223037 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -664,11 +664,9 @@
 	}
 
 	if (((rtlpriv->link_info.num_rx_inperiod +
-		rtlpriv->link_info.num_tx_inperiod) > 8) ||
-		(rtlpriv->link_info.num_rx_inperiod > 2)) {
-		rtlpriv->enter_ps = false;
-		schedule_work(&rtlpriv->works.lps_change_work);
-	}
+	      rtlpriv->link_info.num_tx_inperiod) > 8) ||
+	      (rtlpriv->link_info.num_rx_inperiod > 2))
+		rtl_lps_leave(hw);
 }
 
 static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
@@ -919,10 +917,8 @@
 		}
 		if (((rtlpriv->link_info.num_rx_inperiod +
 		      rtlpriv->link_info.num_tx_inperiod) > 8) ||
-		      (rtlpriv->link_info.num_rx_inperiod > 2)) {
-			rtlpriv->enter_ps = false;
-			schedule_work(&rtlpriv->works.lps_change_work);
-		}
+		      (rtlpriv->link_info.num_rx_inperiod > 2))
+			rtl_lps_leave(hw);
 		skb = new_skb;
 no_new:
 		if (rtlpriv->use_new_trx_flow) {
@@ -1573,7 +1569,7 @@
 							 true,
 							 HW_DESC_TXBUFF_ADDR),
 						 skb->len, PCI_DMA_TODEVICE);
-				kfree_skb(skb);
+				dev_kfree_skb_irq(skb);
 				ring->idx = (ring->idx + 1) % ring->entries;
 			}
 			ring->idx = 0;
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h
index 5da6703..672f81e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.h
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.h
@@ -275,10 +275,10 @@
 };
 
 struct rtl_pci_priv {
+	struct bt_coexist_info bt_coexist;
+	struct rtl_led_ctl ledctl;
 	struct rtl_pci dev;
 	struct mp_adapter ndis_adapter;
-	struct rtl_led_ctl ledctl;
-	struct bt_coexist_info bt_coexist;
 };
 
 #define rtl_pcipriv(hw)		(((struct rtl_pci_priv *)(rtl_priv(hw))->priv))
diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c
index b69321d..626ff30 100644
--- a/drivers/net/wireless/realtek/rtlwifi/ps.c
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
@@ -414,8 +414,8 @@
 	}
 }
 
-/*Enter the leisure power save mode.*/
-void rtl_lps_enter(struct ieee80211_hw *hw)
+/* Interrupt safe routine to enter the leisure power save mode.*/
+static void rtl_lps_enter_core(struct ieee80211_hw *hw)
 {
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -455,10 +455,9 @@
 
 	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
-EXPORT_SYMBOL(rtl_lps_enter);
 
-/*Leave the leisure power save mode.*/
-void rtl_lps_leave(struct ieee80211_hw *hw)
+/* Interrupt safe routine to leave the leisure power save mode.*/
+static void rtl_lps_leave_core(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -488,7 +487,6 @@
 	}
 	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
-EXPORT_SYMBOL(rtl_lps_leave);
 
 /* For sw LPS*/
 void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
@@ -681,12 +679,34 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
 	if (rtlpriv->enter_ps)
-		rtl_lps_enter(hw);
+		rtl_lps_enter_core(hw);
 	else
-		rtl_lps_leave(hw);
+		rtl_lps_leave_core(hw);
 }
 EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback);
 
+void rtl_lps_enter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (!in_interrupt())
+		return rtl_lps_enter_core(hw);
+	rtlpriv->enter_ps = true;
+	schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_enter);
+
+void rtl_lps_leave(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (!in_interrupt())
+		return rtl_lps_leave_core(hw);
+	rtlpriv->enter_ps = false;
+	schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_leave);
+
 void rtl_swlps_wq_callback(void *data)
 {
 	struct rtl_works *rtlworks = container_of_dwork_rtl(data,
diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c
index 5be3411..f67e7e5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/regd.c
+++ b/drivers/net/wireless/realtek/rtlwifi/regd.c
@@ -345,9 +345,9 @@
 		return &rtl_regdom_no_midband;
 	case COUNTRY_CODE_IC:
 		return &rtl_regdom_11;
-	case COUNTRY_CODE_ETSI:
 	case COUNTRY_CODE_TELEC_NETGEAR:
 		return &rtl_regdom_60_64;
+	case COUNTRY_CODE_ETSI:
 	case COUNTRY_CODE_SPAIN:
 	case COUNTRY_CODE_FRANCE:
 	case COUNTRY_CODE_ISRAEL:
@@ -406,6 +406,8 @@
 		return COUNTRY_CODE_WORLD_WIDE_13;
 	case 0x22:
 		return COUNTRY_CODE_IC;
+	case 0x25:
+		return COUNTRY_CODE_ETSI;
 	case 0x32:
 		return COUNTRY_CODE_TELEC_NETGEAR;
 	case 0x41:
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
index 5f14308..b160144 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
@@ -1003,7 +1003,7 @@
 	rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x100a);
 
 	/* Note Data sheet don't define */
-	rtl_write_word(rtlpriv, 0x4C7, 0x80);
+	rtl_write_byte(rtlpriv, 0x4C7, 0x80);
 
 	rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20);
 
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index c983d2f..5a3df91 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
@@ -2684,6 +2684,7 @@
 					      bool auto_load_fail, u8 *hwinfo)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mod_params *mod_params = rtlpriv->cfg->mod_params;
 	u8 value;
 	u32 tmpu_32;
 
@@ -2702,6 +2703,10 @@
 		rtlpriv->btcoexist.btc_info.ant_num = ANT_X2;
 	}
 
+	/* override ant_num / ant_path */
+	if (mod_params->ant_sel)
+		rtlpriv->btcoexist.btc_info.ant_num =
+			(mod_params->ant_sel == 1 ? ANT_X2 : ANT_X1);
 }
 
 void rtl8723be_bt_reg_init(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
index a78eaed..2101793 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
@@ -273,6 +273,7 @@
 	.msi_support = false,
 	.disable_watchdog = false,
 	.debug = DBG_EMERG,
+	.ant_sel = 0,
 };
 
 static struct rtl_hal_cfg rtl8723be_hal_cfg = {
@@ -394,6 +395,7 @@
 module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444);
 module_param_named(disable_watchdog, rtl8723be_mod_params.disable_watchdog,
 		   bool, 0444);
+module_param_named(ant_sel, rtl8723be_mod_params.ant_sel, int, 0444);
 MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
 MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
 MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
@@ -402,6 +404,7 @@
 MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
 MODULE_PARM_DESC(disable_watchdog,
 		 "Set to 1 to disable the watchdog (default 0)\n");
+MODULE_PARM_DESC(ant_sel, "Set to 1 or 2 to force antenna number (default 0)\n");
 
 static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
 
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index bbb789f..c2103e7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -1127,7 +1127,7 @@
 	}
 	if (0 == tmp) {
 		read_addr = REG_DBI_RDATA + addr % 4;
-		ret = rtl_read_word(rtlpriv, read_addr);
+		ret = rtl_read_byte(rtlpriv, read_addr);
 	}
 	return ret;
 }
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
index 9b4d8a6..4b35491 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
@@ -359,6 +359,107 @@
 	return rtl8821ae_phy_rf6052_config(hw);
 }
 
+static void _rtl8812ae_phy_set_rfe_reg_24g(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp;
+
+	switch (rtlhal->rfe_type) {
+	case 3:
+		rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x54337770);
+		rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x54337770);
+		rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010);
+		rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010);
+		rtl_set_bbreg(hw, 0x900, 0x00000303, 0x1);
+		break;
+	case 4:
+		rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77777777);
+		rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777);
+		rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x001);
+		rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x001);
+		break;
+	case 5:
+		rtl_write_byte(rtlpriv, RA_RFE_PINMUX + 2, 0x77);
+		rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777);
+		tmp = rtl_read_byte(rtlpriv, RA_RFE_INV + 3);
+		rtl_write_byte(rtlpriv, RA_RFE_INV + 3, tmp & ~0x1);
+		rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000);
+		break;
+	case 1:
+		if (rtlpriv->btcoexist.bt_coexistence) {
+			rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xffffff, 0x777777);
+			rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD,
+				      0x77777777);
+			rtl_set_bbreg(hw, RA_RFE_INV, 0x33f00000, 0x000);
+			rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000);
+			break;
+		}
+	case 0:
+	case 2:
+	default:
+		rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77777777);
+		rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777);
+		rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x000);
+		rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000);
+		break;
+	}
+}
+
+static void _rtl8812ae_phy_set_rfe_reg_5g(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp;
+
+	switch (rtlhal->rfe_type) {
+	case 0:
+		rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77337717);
+		rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337717);
+		rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010);
+		rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010);
+		break;
+	case 1:
+		if (rtlpriv->btcoexist.bt_coexistence) {
+			rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xffffff, 0x337717);
+			rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD,
+				      0x77337717);
+			rtl_set_bbreg(hw, RA_RFE_INV, 0x33f00000, 0x000);
+			rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000);
+		} else {
+			rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD,
+				      0x77337717);
+			rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD,
+				      0x77337717);
+			rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x000);
+			rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000);
+		}
+		break;
+	case 3:
+		rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x54337717);
+		rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x54337717);
+		rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010);
+		rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010);
+		rtl_set_bbreg(hw, 0x900, 0x00000303, 0x1);
+		break;
+	case 5:
+		rtl_write_byte(rtlpriv, RA_RFE_PINMUX + 2, 0x33);
+		rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337777);
+		tmp = rtl_read_byte(rtlpriv, RA_RFE_INV + 3);
+		rtl_write_byte(rtlpriv, RA_RFE_INV + 3, tmp | 0x1);
+		rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010);
+		break;
+	case 2:
+	case 4:
+	default:
+		rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77337777);
+		rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337777);
+		rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010);
+		rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010);
+		break;
+	}
+}
+
 u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8	band,
 			   u8 rf_path)
 {
@@ -553,14 +654,9 @@
 			/* 0x82C[1:0] = 2b'00 */
 			rtl_set_bbreg(hw, 0x82c, 0x3, 0);
 		}
-		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
-			rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD,
-				      0x77777777);
-			rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD,
-				      0x77777777);
-			rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x000);
-			rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x000);
-		}
+
+		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
+			_rtl8812ae_phy_set_rfe_reg_24g(hw);
 
 		rtl_set_bbreg(hw, RTXPATH, 0xf0, 0x1);
 		rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0x1);
@@ -615,14 +711,8 @@
 			/* 0x82C[1:0] = 2'b00 */
 			rtl_set_bbreg(hw, 0x82c, 0x3, 1);
 
-		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
-			rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD,
-				      0x77337777);
-			rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD,
-				      0x77337777);
-			rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x010);
-			rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x010);
-		}
+		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
+			_rtl8812ae_phy_set_rfe_reg_5g(hw);
 
 		rtl_set_bbreg(hw, RTXPATH, 0xf0, 0);
 		rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0xf);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
index 1d6110f..ed69dbe 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
@@ -2424,6 +2424,7 @@
 #define	BMASKH4BITS			0xf0000000
 #define BMASKOFDM_D			0xffc00000
 #define	BMASKCCK			0x3f3f3f3f
+#define BMASKRFEINV			0x3ff00000
 
 #define BRFREGOFFSETMASK		0xfffff
 
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index aac1ed3..ad8390d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -834,12 +834,30 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct urb *urb;
 
 	/* should after adapter start and interrupt enable. */
 	set_hal_stop(rtlhal);
 	cancel_work_sync(&rtlpriv->works.fill_h2c_cmd);
 	/* Enable software */
 	SET_USB_STOP(rtlusb);
+
+	/* free pre-allocated URBs from rtl_usb_start() */
+	usb_kill_anchored_urbs(&rtlusb->rx_submitted);
+
+	tasklet_kill(&rtlusb->rx_work_tasklet);
+	cancel_work_sync(&rtlpriv->works.lps_change_work);
+
+	flush_workqueue(rtlpriv->works.rtl_wq);
+
+	skb_queue_purge(&rtlusb->rx_queue);
+
+	while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) {
+		usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+				urb->transfer_buffer, urb->transfer_dma);
+		usb_free_urb(urb);
+	}
+
 	rtlpriv->cfg->ops->hw_disable(hw);
 }
 
@@ -1073,6 +1091,7 @@
 		return -ENOMEM;
 	}
 	rtlpriv = hw->priv;
+	rtlpriv->hw = hw;
 	rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
 				    GFP_KERNEL);
 	if (!rtlpriv->usb_data)
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h
index 685273c..441c441 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.h
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.h
@@ -150,8 +150,9 @@
 };
 
 struct rtl_usb_priv {
-	struct rtl_usb dev;
+	struct bt_coexist_info bt_coexist;
 	struct rtl_led_ctl ledctl;
+	struct rtl_usb dev;
 };
 
 #define rtl_usbpriv(hw)	 (((struct rtl_usb_priv *)(rtl_priv(hw))->priv))
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index 4544752..b6faf62 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -2252,6 +2252,9 @@
 
 	/* default 0: 1 means do not disable interrupts */
 	bool int_clear;
+
+	/* select antenna */
+	int ant_sel;
 };
 
 struct rtl_hal_usbint_cfg {
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index b5bcc93..4df992d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -659,29 +659,24 @@
  *				 informs the f/w regarding this.
  * @hw: Pointer to the ieee80211_hw structure.
  * @vif: Pointer to the ieee80211_vif structure.
- * @action: ieee80211_ampdu_mlme_action enum.
- * @sta: Pointer to the ieee80211_sta structure.
- * @tid: Traffic identifier.
- * @ssn: Pointer to ssn value.
- * @buf_size: Buffer size (for kernel version > 2.6.38).
- * @amsdu: is AMSDU in AMPDU allowed
+ * @params: Pointer to A-MPDU action parameters
  *
  * Return: status: 0 on success, negative error code on failure.
  */
 static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
-				     enum ieee80211_ampdu_mlme_action action,
-				     struct ieee80211_sta *sta,
-				     unsigned short tid,
-				     unsigned short *ssn,
-				     unsigned char buf_size,
-				     bool amsdu)
+				     struct ieee80211_ampdu_params *params)
 {
 	int status = -EOPNOTSUPP;
 	struct rsi_hw *adapter = hw->priv;
 	struct rsi_common *common = adapter->priv;
 	u16 seq_no = 0;
 	u8 ii = 0;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
+	u8 buf_size = params->buf_size;
 
 	for (ii = 0; ii < RSI_MAX_VIFS; ii++) {
 		if (vif == adapter->vifs[ii])
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 9733b31..69c1c09 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7935,10 +7935,11 @@
 EXPORT_SYMBOL_GPL(rt2800_get_tsf);
 
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			u8 buf_size, bool amsdu)
+			struct ieee80211_ampdu_params *params)
 {
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
 	struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
 	int ret = 0;
 
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 440790b..83f1a44 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -218,9 +218,7 @@
 		   const struct ieee80211_tx_queue_params *params);
 u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			u8 buf_size, bool amsdu);
+			struct ieee80211_ampdu_params *params);
 int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
 		      struct survey_info *survey);
 void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c
index 09c7e09..085ef5c 100644
--- a/drivers/net/wireless/ti/wl18xx/event.c
+++ b/drivers/net/wireless/ti/wl18xx/event.c
@@ -206,5 +206,33 @@
 						 mbox->sc_pwd_len,
 						 mbox->sc_pwd);
 
+	if (vector & RX_BA_WIN_SIZE_CHANGE_EVENT_ID) {
+		struct wl12xx_vif *wlvif;
+		struct ieee80211_vif *vif;
+		struct ieee80211_sta *sta;
+		u8 link_id = mbox->rx_ba_link_id;
+		u8 win_size = mbox->rx_ba_win_size;
+		const u8 *addr;
+
+		wlvif = wl->links[link_id].wlvif;
+		vif = wl12xx_wlvif_to_vif(wlvif);
+
+		/* Update RX aggregation window size and call
+		 * MAC routine to stop active RX aggregations for this link
+		 */
+		if (wlvif->bss_type != BSS_TYPE_AP_BSS)
+			addr = vif->bss_conf.bssid;
+		else
+			addr = wl->links[link_id].addr;
+
+		sta = ieee80211_find_sta(vif, addr);
+		if (sta) {
+			sta->max_rx_aggregation_subframes = win_size;
+			ieee80211_stop_rx_ba_session(vif,
+						wl->links[link_id].ba_bitmap,
+						addr);
+		}
+	}
+
 	return 0;
 }
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h
index f3d4f13..9495fad 100644
--- a/drivers/net/wireless/ti/wl18xx/event.h
+++ b/drivers/net/wireless/ti/wl18xx/event.h
@@ -38,6 +38,7 @@
 	REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID      = BIT(18),
 	DFS_CHANNELS_CONFIG_COMPLETE_EVENT       = BIT(19),
 	PERIODIC_SCAN_REPORT_EVENT_ID            = BIT(20),
+	RX_BA_WIN_SIZE_CHANGE_EVENT_ID           = BIT(21),
 	SMART_CONFIG_SYNC_EVENT_ID               = BIT(22),
 	SMART_CONFIG_DECODE_EVENT_ID             = BIT(23),
 	TIME_SYNC_EVENT_ID                       = BIT(24),
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 50cce42..47f355e 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1029,7 +1029,8 @@
 		DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
 		SMART_CONFIG_SYNC_EVENT_ID |
 		SMART_CONFIG_DECODE_EVENT_ID |
-		TIME_SYNC_EVENT_ID;
+		TIME_SYNC_EVENT_ID |
+		RX_BA_WIN_SIZE_CHANGE_EVENT_ID;
 
 	wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
 
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index f28fa3b..0646c9b 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -1419,7 +1419,8 @@
 
 /* setup BA session receiver setting in the FW. */
 int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
-				       u16 ssn, bool enable, u8 peer_hlid)
+				       u16 ssn, bool enable, u8 peer_hlid,
+				       u8 win_size)
 {
 	struct wl1271_acx_ba_receiver_setup *acx;
 	int ret;
@@ -1435,7 +1436,7 @@
 	acx->hlid = peer_hlid;
 	acx->tid = tid_index;
 	acx->enable = enable;
-	acx->win_size = wl->conf.ht.rx_ba_win_size;
+	acx->win_size =	win_size;
 	acx->ssn = ssn;
 
 	ret = wlcore_cmd_configure_failsafe(wl, ACX_BA_SESSION_RX_SETUP, acx,
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index 954d57e..524aea4 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -1112,7 +1112,8 @@
 int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl,
 				       struct wl12xx_vif *wlvif);
 int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
-				       u16 ssn, bool enable, u8 peer_hlid);
+				       u16 ssn, bool enable, u8 peer_hlid,
+				       u8 win_size);
 int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 			u64 *mactime);
 int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index ec7f6af..7b27c7e 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5261,14 +5261,16 @@
 
 static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
-				  enum ieee80211_ampdu_mlme_action action,
-				  struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-				  u8 buf_size, bool amsdu)
+				  struct ieee80211_ampdu_params *params)
 {
 	struct wl1271 *wl = hw->priv;
 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 	int ret;
 	u8 hlid, *ba_bitmap;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action,
 		     tid);
@@ -5326,7 +5328,9 @@
 		}
 
 		ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true,
-							 hlid);
+				hlid,
+				params->buf_size);
+
 		if (!ret) {
 			*ba_bitmap |= BIT(tid);
 			wl->ba_rx_session_count++;
@@ -5347,7 +5351,7 @@
 		}
 
 		ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false,
-							 hlid);
+							 hlid, 0);
 		if (!ret) {
 			*ba_bitmap &= ~BIT(tid);
 			wl->ba_rx_session_count--;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d6abf19..34a062c 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -304,7 +304,7 @@
 		queue->rx_skbs[id] = skb;
 
 		ref = gnttab_claim_grant_reference(&queue->gref_rx_head);
-		BUG_ON((signed short)ref < 0);
+		WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref));
 		queue->grant_rx_ref[id] = ref;
 
 		page = skb_frag_page(&skb_shinfo(skb)->frags[0]);
@@ -321,7 +321,7 @@
 	queue->rx.req_prod_pvt = req_prod;
 
 	/* Not enough requests? Try again later. */
-	if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN) {
+	if (req_prod - queue->rx.sring->req_prod < NET_RX_SLOTS_MIN) {
 		mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10));
 		return;
 	}
@@ -437,7 +437,7 @@
 	id = get_id_from_freelist(&queue->tx_skb_freelist, queue->tx_skbs);
 	tx = RING_GET_REQUEST(&queue->tx, queue->tx.req_prod_pvt++);
 	ref = gnttab_claim_grant_reference(&queue->gref_tx_head);
-	BUG_ON((signed short)ref < 0);
+	WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref));
 
 	gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id,
 					gfn, GNTMAP_readonly);
@@ -1391,6 +1391,8 @@
 	for (i = 0; i < num_queues && info->queues; ++i) {
 		struct netfront_queue *queue = &info->queues[i];
 
+		del_timer_sync(&queue->rx_refill_timer);
+
 		if (queue->tx_irq && (queue->tx_irq == queue->rx_irq))
 			unbind_from_irqhandler(queue->tx_irq, queue);
 		if (queue->tx_irq && (queue->tx_irq != queue->rx_irq)) {
@@ -1745,7 +1747,6 @@
 
 		if (netif_running(info->netdev))
 			napi_disable(&queue->napi);
-		del_timer_sync(&queue->rx_refill_timer);
 		netif_napi_del(&queue->napi);
 	}
 
diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c
index ccb07a1..23e5378 100644
--- a/drivers/nfc/fdp/fdp.c
+++ b/drivers/nfc/fdp/fdp.c
@@ -352,7 +352,7 @@
 {
 	struct fdp_nci_info *info = nci_get_drvdata(ndev);
 	struct device *dev = &info->phy->i2c_dev->dev;
-	u8 conn_id;
+	int conn_id;
 	int r = 0;
 
 	if (info->otp_version >= info->otp_patch_version)
@@ -423,7 +423,7 @@
 {
 	struct fdp_nci_info *info = nci_get_drvdata(ndev);
 	struct device *dev = &info->phy->i2c_dev->dev;
-	u8 conn_id;
+	int conn_id;
 	int r = 0;
 
 	if (info->ram_version >= info->ram_patch_version)
diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c
index 83deda4..6f9563a 100644
--- a/drivers/nfc/mei_phy.c
+++ b/drivers/nfc/mei_phy.c
@@ -133,7 +133,7 @@
 		return -ENOMEM;
 
 	bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply, if_version_length);
-	if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
+	if (bytes_recv < 0 || bytes_recv < if_version_length) {
 		pr_err("Could not read IF version\n");
 		r = -EIO;
 		goto err;
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 60654d5..ecc6fb9 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -1623,7 +1623,7 @@
 
 	node = dev_to_node(&ndev->dev);
 
-	free_queue = ffs(nt->qp_bitmap);
+	free_queue = ffs(nt->qp_bitmap_free);
 	if (!free_queue)
 		goto err;
 
@@ -2082,9 +2082,8 @@
 
 static void __exit ntb_transport_exit(void)
 {
-	debugfs_remove_recursive(nt_debugfs_dir);
-
 	ntb_unregister_client(&ntb_transport_client);
 	bus_unregister(&ntb_transport_bus);
+	debugfs_remove_recursive(nt_debugfs_dir);
 }
 module_exit(ntb_transport_exit);
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 5f47356..254b0ee 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -590,8 +590,14 @@
 	rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len);
 	if (rc < 0)
 		goto out_unlock;
+	nvdimm_bus_unlock(&nvdimm_bus->dev);
+
 	if (copy_to_user(p, buf, buf_len))
 		rc = -EFAULT;
+
+	vfree(buf);
+	return rc;
+
  out_unlock:
 	nvdimm_bus_unlock(&nvdimm_bus->dev);
  out:
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 62120c3..aae7379 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -1534,6 +1534,7 @@
 static int find_pmem_label_set(struct nd_region *nd_region,
 		struct nd_namespace_pmem *nspm)
 {
+	u64 altcookie = nd_region_interleave_set_altcookie(nd_region);
 	u64 cookie = nd_region_interleave_set_cookie(nd_region);
 	struct nd_namespace_label *nd_label;
 	u8 select_id[NSLABEL_UUID_LEN];
@@ -1542,8 +1543,10 @@
 	int rc = -ENODEV, l;
 	u16 i;
 
-	if (cookie == 0)
+	if (cookie == 0) {
+		dev_dbg(&nd_region->dev, "invalid interleave-set-cookie\n");
 		return -ENXIO;
+	}
 
 	/*
 	 * Find a complete set of labels by uuid.  By definition we can start
@@ -1552,13 +1555,24 @@
 	for_each_label(l, nd_label, nd_region->mapping[0].labels) {
 		u64 isetcookie = __le64_to_cpu(nd_label->isetcookie);
 
-		if (isetcookie != cookie)
-			continue;
+		if (isetcookie != cookie) {
+			dev_dbg(&nd_region->dev, "invalid cookie in label: %pUb\n",
+					nd_label->uuid);
+			if (isetcookie != altcookie)
+				continue;
 
-		for (i = 0; nd_region->ndr_mappings; i++)
-			if (!has_uuid_at_pos(nd_region, nd_label->uuid,
-						cookie, i))
-				break;
+			dev_dbg(&nd_region->dev, "valid altcookie in label: %pUb\n",
+					nd_label->uuid);
+		}
+
+		for (i = 0; nd_region->ndr_mappings; i++) {
+			if (has_uuid_at_pos(nd_region, nd_label->uuid, cookie, i))
+				continue;
+			if (has_uuid_at_pos(nd_region, nd_label->uuid, altcookie, i))
+				continue;
+			break;
+		}
+
 		if (i < nd_region->ndr_mappings) {
 			/*
 			 * Give up if we don't find an instance of a
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 417e521..fc870e5 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -245,6 +245,7 @@
 int nd_region_to_nstype(struct nd_region *nd_region);
 int nd_region_register_namespaces(struct nd_region *nd_region, int *err);
 u64 nd_region_interleave_set_cookie(struct nd_region *nd_region);
+u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region);
 void nvdimm_bus_lock(struct device *dev);
 void nvdimm_bus_unlock(struct device *dev);
 bool is_nvdimm_bus_locked(struct device *dev);
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 9521696..dc2e919 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -379,6 +379,15 @@
 	return 0;
 }
 
+u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region)
+{
+	struct nd_interleave_set *nd_set = nd_region->nd_set;
+
+	if (nd_set)
+		return nd_set->altcookie;
+	return 0;
+}
+
 /*
  * Upon successful probe/remove, take/release a reference on the
  * associated interleave set (if present), and plant new btt + namespace
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 044253d..b8a5a8e 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -27,6 +27,13 @@
 	NVME_NS_LIGHTNVM	= 1,
 };
 
+/* The below value is the specific amount of delay needed before checking
+ * readiness in case of the PCI_DEVICE(0x1c58, 0x0003), which needs the
+ * NVME_QUIRK_DELAY_BEFORE_CHK_RDY quirk enabled. The value (in ms) was
+ * found empirically.
+ */
+#define NVME_QUIRK_DELAY_AMOUNT		2000
+
 /*
  * Represents an NVM Express device.  Each nvme_dev is a PCI function.
  */
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 0c67b57..4c673d4 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -1633,10 +1633,15 @@
  */
 static int nvme_disable_ctrl(struct nvme_dev *dev, u64 cap)
 {
+	struct pci_dev *pdev = to_pci_dev(dev->dev);
+
 	dev->ctrl_config &= ~NVME_CC_SHN_MASK;
 	dev->ctrl_config &= ~NVME_CC_ENABLE;
 	writel(dev->ctrl_config, &dev->bar->cc);
 
+	if (pdev->vendor == 0x1c58 && pdev->device == 0x0003)
+		msleep(NVME_QUIRK_DELAY_AMOUNT);
+
 	return nvme_wait_ready(dev, cap, false);
 }
 
@@ -2672,10 +2677,10 @@
 	return 0;
 }
 
-static int nvme_dev_map(struct nvme_dev *dev)
+static int nvme_pci_enable(struct nvme_dev *dev)
 {
 	u64 cap;
-	int bars, result = -ENOMEM;
+	int result = -ENOMEM;
 	struct pci_dev *pdev = to_pci_dev(dev->dev);
 
 	if (pci_enable_device_mem(pdev))
@@ -2683,24 +2688,14 @@
 
 	dev->entry[0].vector = pdev->irq;
 	pci_set_master(pdev);
-	bars = pci_select_bars(pdev, IORESOURCE_MEM);
-	if (!bars)
-		goto disable_pci;
-
-	if (pci_request_selected_regions(pdev, bars, "nvme"))
-		goto disable_pci;
 
 	if (dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)) &&
 	    dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(32)))
 		goto disable;
 
-	dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
-	if (!dev->bar)
-		goto disable;
-
 	if (readl(&dev->bar->csts) == -1) {
 		result = -ENODEV;
-		goto unmap;
+		goto disable;
 	}
 
 	/*
@@ -2710,7 +2705,7 @@
 	if (!pdev->irq) {
 		result = pci_enable_msix(pdev, dev->entry, 1);
 		if (result < 0)
-			goto unmap;
+			goto disable;
 	}
 
 	cap = lo_hi_readq(&dev->bar->cap);
@@ -2734,18 +2729,21 @@
 
 	return 0;
 
- unmap:
-	iounmap(dev->bar);
-	dev->bar = NULL;
  disable:
-	pci_release_regions(pdev);
- disable_pci:
 	pci_disable_device(pdev);
+
 	return result;
 }
 
 static void nvme_dev_unmap(struct nvme_dev *dev)
 {
+	if (dev->bar)
+		iounmap(dev->bar);
+	pci_release_regions(to_pci_dev(dev->dev));
+}
+
+static void nvme_pci_disable(struct nvme_dev *dev)
+{
 	struct pci_dev *pdev = to_pci_dev(dev->dev);
 
 	if (pdev->msi_enabled)
@@ -2753,12 +2751,6 @@
 	else if (pdev->msix_enabled)
 		pci_disable_msix(pdev);
 
-	if (dev->bar) {
-		iounmap(dev->bar);
-		dev->bar = NULL;
-		pci_release_regions(pdev);
-	}
-
 	if (pci_is_enabled(pdev))
 		pci_disable_device(pdev);
 }
@@ -2962,7 +2954,7 @@
 
 	nvme_dev_list_remove(dev);
 
-	if (dev->bar) {
+	if (pci_is_enabled(to_pci_dev(dev->dev))) {
 		nvme_freeze_queues(dev);
 		csts = readl(&dev->bar->csts);
 	}
@@ -2976,7 +2968,7 @@
 		nvme_shutdown_ctrl(dev);
 		nvme_disable_queue(dev, 0);
 	}
-	nvme_dev_unmap(dev);
+	nvme_pci_disable(dev);
 
 	for (i = dev->queue_count - 1; i >= 0; i--)
 		nvme_clear_queue(dev->queues[i]);
@@ -3136,7 +3128,7 @@
 	bool start_thread = false;
 	int result;
 
-	result = nvme_dev_map(dev);
+	result = nvme_pci_enable(dev);
 	if (result)
 		goto out;
 
@@ -3292,6 +3284,27 @@
 }
 static DEVICE_ATTR(reset_controller, S_IWUSR, NULL, nvme_sysfs_reset);
 
+static int nvme_dev_map(struct nvme_dev *dev)
+{
+	int bars;
+	struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+	bars = pci_select_bars(pdev, IORESOURCE_MEM);
+	if (!bars)
+		return -ENODEV;
+	if (pci_request_selected_regions(pdev, bars, "nvme"))
+		return -ENODEV;
+
+	dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
+	if (!dev->bar)
+		goto release;
+
+	return 0;
+release:
+	pci_release_regions(pdev);
+	return -ENODEV;
+}
+
 static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int node, result = -ENOMEM;
@@ -3317,6 +3330,11 @@
 	INIT_WORK(&dev->reset_work, nvme_reset_work);
 	dev->dev = get_device(&pdev->dev);
 	pci_set_drvdata(pdev, dev);
+
+	result = nvme_dev_map(dev);
+	if (result)
+		goto free;
+
 	result = nvme_set_instance(dev);
 	if (result)
 		goto put_pci;
@@ -3355,6 +3373,7 @@
 	nvme_release_instance(dev);
  put_pci:
 	put_device(dev->dev);
+	nvme_dev_unmap(dev);
  free:
 	kfree(dev->queues);
 	kfree(dev->entry);
@@ -3398,6 +3417,7 @@
 	nvme_free_queues(dev, 0);
 	nvme_release_cmb(dev);
 	nvme_release_prp_pools(dev);
+	nvme_dev_unmap(dev);
 	kref_put(&dev->kref, nvme_free_dev);
 }
 
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 9582c57..4fe5fe2 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -260,7 +260,7 @@
 	if (!parser->range || parser->range + parser->np > parser->end)
 		return NULL;
 
-	range->pci_space = parser->range[0];
+	range->pci_space = be32_to_cpup(parser->range);
 	range->flags = of_bus_pci_get_flags(parser->range);
 	range->pci_addr = of_read_number(parser->range + 1, ns);
 	range->cpu_addr = of_translate_address(parser->node,
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 017dd94..3134129 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -112,6 +112,7 @@
 	return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length);
 }
 
+/* always return newly allocated name, caller must free after use */
 static const char *safe_name(struct kobject *kobj, const char *orig_name)
 {
 	const char *name = orig_name;
@@ -126,9 +127,12 @@
 		name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i);
 	}
 
-	if (name != orig_name)
+	if (name == orig_name) {
+		name = kstrdup(orig_name, GFP_KERNEL);
+	} else {
 		pr_warn("device-tree: Duplicate name in %s, renamed to \"%s\"\n",
 			kobject_name(kobj), name);
+	}
 	return name;
 }
 
@@ -159,6 +163,7 @@
 int __of_attach_node_sysfs(struct device_node *np)
 {
 	const char *name;
+	struct kobject *parent;
 	struct property *pp;
 	int rc;
 
@@ -171,15 +176,16 @@
 	np->kobj.kset = of_kset;
 	if (!np->parent) {
 		/* Nodes without parents are new top level trees */
-		rc = kobject_add(&np->kobj, NULL, "%s",
-				 safe_name(&of_kset->kobj, "base"));
+		name = safe_name(&of_kset->kobj, "base");
+		parent = NULL;
 	} else {
 		name = safe_name(&np->parent->kobj, kbasename(np->full_name));
-		if (!name || !name[0])
-			return -EINVAL;
-
-		rc = kobject_add(&np->kobj, &np->parent->kobj, "%s", name);
+		parent = &np->parent->kobj;
 	}
+	if (!name)
+		return -ENOMEM;
+	rc = kobject_add(&np->kobj, parent, "%s", name);
+	kfree(name);
 	if (rc)
 		return rc;
 
@@ -1753,6 +1759,12 @@
 	return 0;
 }
 
+void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop)
+{
+	sysfs_remove_bin_file(&np->kobj, &prop->attr);
+	kfree(prop->attr.attr.name);
+}
+
 void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
 {
 	if (!IS_ENABLED(CONFIG_SYSFS))
@@ -1760,7 +1772,7 @@
 
 	/* at early boot, bail here and defer setup to of_init() */
 	if (of_kset && of_node_is_attached(np))
-		sysfs_remove_bin_file(&np->kobj, &prop->attr);
+		__of_sysfs_remove_bin_file(np, prop);
 }
 
 /**
@@ -1830,7 +1842,7 @@
 		return;
 
 	if (oldprop)
-		sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
+		__of_sysfs_remove_bin_file(np, oldprop);
 	__of_add_property_sysfs(np, newprop);
 }
 
@@ -2241,20 +2253,13 @@
 	const struct device_node *parent, int port_reg, int reg)
 {
 	struct of_endpoint endpoint;
-	struct device_node *node, *prev_node = NULL;
+	struct device_node *node = NULL;
 
-	while (1) {
-		node = of_graph_get_next_endpoint(parent, prev_node);
-		of_node_put(prev_node);
-		if (!node)
-			break;
-
+	for_each_endpoint_of_node(parent, node) {
 		of_graph_parse_endpoint(node, &endpoint);
 		if (((port_reg == -1) || (endpoint.port == port_reg)) &&
 			((reg == -1) || (endpoint.id == reg)))
 			return node;
-
-		prev_node = node;
 	}
 
 	return NULL;
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 53826b8..2d72ddc 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -55,7 +55,7 @@
 	/* only remove properties if on sysfs */
 	if (of_node_is_attached(np)) {
 		for_each_property_of_node(np, pp)
-			sysfs_remove_bin_file(&np->kobj, &pp->attr);
+			__of_sysfs_remove_bin_file(np, pp);
 		kobject_del(&np->kobj);
 	}
 
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 86fff62..901dd1c 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -632,9 +632,12 @@
 	const char *pathp;
 	int offset, rc = 0, depth = -1;
 
-        for (offset = fdt_next_node(blob, -1, &depth);
-             offset >= 0 && depth >= 0 && !rc;
-             offset = fdt_next_node(blob, offset, &depth)) {
+	if (!blob)
+		return 0;
+
+	for (offset = fdt_next_node(blob, -1, &depth);
+	     offset >= 0 && depth >= 0 && !rc;
+	     offset = fdt_next_node(blob, offset, &depth)) {
 
 		pathp = fdt_get_name(blob, offset, NULL);
 		if (*pathp == '/')
@@ -760,6 +763,16 @@
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
+#ifndef __early_init_dt_declare_initrd
+static void __early_init_dt_declare_initrd(unsigned long start,
+					   unsigned long end)
+{
+	initrd_start = (unsigned long)__va(start);
+	initrd_end = (unsigned long)__va(end);
+	initrd_below_start_ok = 1;
+}
+#endif
+
 /**
  * early_init_dt_check_for_initrd - Decode initrd location from flat tree
  * @node: reference to node containing initrd location ('chosen')
@@ -782,9 +795,7 @@
 		return;
 	end = of_read_number(prop, len/4);
 
-	initrd_start = (unsigned long)__va(start);
-	initrd_end = (unsigned long)__va(end);
-	initrd_below_start_ok = 1;
+	__early_init_dt_declare_initrd(start, end);
 
 	pr_debug("initrd_start=0x%llx  initrd_end=0x%llx\n",
 		 (unsigned long long)start, (unsigned long long)end);
@@ -1006,13 +1017,16 @@
 }
 
 #ifdef CONFIG_HAVE_MEMBLOCK
+#ifndef MIN_MEMBLOCK_ADDR
+#define MIN_MEMBLOCK_ADDR	__pa(PAGE_OFFSET)
+#endif
 #ifndef MAX_MEMBLOCK_ADDR
 #define MAX_MEMBLOCK_ADDR	((phys_addr_t)~0)
 #endif
 
 void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
 {
-	const u64 phys_offset = __pa(PAGE_OFFSET);
+	const u64 phys_offset = MIN_MEMBLOCK_ADDR;
 
 	if (!PAGE_ALIGNED(base)) {
 		if (size < PAGE_SIZE - (base & ~PAGE_MASK)) {
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 72a2c19..28da624 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -386,13 +386,13 @@
 EXPORT_SYMBOL_GPL(of_irq_to_resource);
 
 /**
- * of_irq_get - Decode a node's IRQ and return it as a Linux irq number
+ * of_irq_get - Decode a node's IRQ and return it as a Linux IRQ number
  * @dev: pointer to device tree node
- * @index: zero-based index of the irq
+ * @index: zero-based index of the IRQ
  *
- * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
- * is not yet created.
- *
+ * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
+ * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
+ * of any other failure.
  */
 int of_irq_get(struct device_node *dev, int index)
 {
@@ -413,12 +413,13 @@
 EXPORT_SYMBOL_GPL(of_irq_get);
 
 /**
- * of_irq_get_byname - Decode a node's IRQ and return it as a Linux irq number
+ * of_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number
  * @dev: pointer to device tree node
- * @name: irq name
+ * @name: IRQ name
  *
- * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
- * is not yet created, or error code in case of any other failure.
+ * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
+ * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
+ * of any other failure.
  */
 int of_irq_get_byname(struct device_node *dev, const char *name)
 {
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 8e882e7..46ddbee 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -81,6 +81,9 @@
 extern void __of_detach_node(struct device_node *np);
 extern void __of_detach_node_sysfs(struct device_node *np);
 
+extern void __of_sysfs_remove_bin_file(struct device_node *np,
+				       struct property *prop);
+
 /* iterators for transactions, used for overlays */
 /* forward iterator */
 #define for_each_transaction_entry(_oft, _te) \
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index ed01c01..07dd815 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -127,8 +127,12 @@
 	}
 
 	/* Need adjust the alignment to satisfy the CMA requirement */
-	if (IS_ENABLED(CONFIG_CMA) && of_flat_dt_is_compatible(node, "shared-dma-pool"))
-		align = max(align, (phys_addr_t)PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order));
+	if (IS_ENABLED(CONFIG_CMA) && of_flat_dt_is_compatible(node, "shared-dma-pool")) {
+		unsigned long order =
+			max_t(unsigned long, MAX_ORDER - 1, pageblock_order);
+
+		align = max(align, (phys_addr_t)PAGE_SIZE << order);
+	}
 
 	prop = of_get_flat_dt_prop(node, "alloc-ranges", &len);
 	if (prop) {
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 6e3a60c..50f3bb0 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -293,7 +293,7 @@
 		p->irq = PARPORT_IRQ_NONE;
 	}
 	if (p->irq != PARPORT_IRQ_NONE) {
-		printk(", irq %d", p->irq);
+		pr_cont(", irq %d", p->irq);
 
 		if (p->dma == PARPORT_DMA_AUTO) {
 			p->dma = PARPORT_DMA_NONE;
@@ -303,8 +303,8 @@
                                            is mandatory (see above) */
 		p->dma = PARPORT_DMA_NONE;
 
-	printk(" [");
-#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}}
+	pr_cont(" [");
+#define printmode(x) {if(p->modes&PARPORT_MODE_##x){pr_cont("%s%s",f?",":"",#x);f++;}}
 	{
 		int f = 0;
 		printmode(PCSPP);
@@ -315,7 +315,7 @@
 //		printmode(DMA);
 	}
 #undef printmode
-	printk("]\n");
+	pr_cont("]\n");
 
 	if (p->irq != PARPORT_IRQ_NONE) {
 		if (request_irq (p->irq, parport_irq_handler,
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 5ce5ef2..754f21f 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -936,8 +936,10 @@
 	 * pardevice fields. -arca
 	 */
 	port->ops->init_state(par_dev, par_dev->state);
-	port->proc_device = par_dev;
-	parport_device_proc_register(par_dev);
+	if (!test_and_set_bit(PARPORT_DEVPROC_REGISTERED, &port->devflags)) {
+		port->proc_device = par_dev;
+		parport_device_proc_register(par_dev);
+	}
 
 	return par_dev;
 
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index e12bafd..f2fcbe9 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -258,8 +258,13 @@
 
 static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
 {
-	if (vio_find_node(dn))
+	struct vio_dev *vio_dev;
+
+	vio_dev = vio_find_node(dn);
+	if (vio_dev) {
+		put_device(&vio_dev->dev);
 		return -EINVAL;
+	}
 
 	if (!vio_register_device_node(dn)) {
 		printk(KERN_ERR
@@ -335,6 +340,9 @@
 		return -EINVAL;
 
 	vio_unregister_device(vio_dev);
+
+	put_device(&vio_dev->dev);
+
 	return 0;
 }
 
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 31f31d4..3575277 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -303,13 +303,6 @@
 			return rc;
 	}
 
-	pci_iov_set_numvfs(dev, nr_virtfn);
-	iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
-	pci_cfg_access_lock(dev);
-	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
-	msleep(100);
-	pci_cfg_access_unlock(dev);
-
 	iov->initial_VFs = initial;
 	if (nr_virtfn < initial)
 		initial = nr_virtfn;
@@ -320,6 +313,13 @@
 		goto err_pcibios;
 	}
 
+	pci_iov_set_numvfs(dev, nr_virtfn);
+	iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
+	pci_cfg_access_lock(dev);
+	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
+	msleep(100);
+	pci_cfg_access_unlock(dev);
+
 	for (i = 0; i < initial; i++) {
 		rc = virtfn_add(dev, i, 0);
 		if (rc)
@@ -555,21 +555,61 @@
 }
 
 /**
- * pci_iov_resource_bar - get position of the SR-IOV BAR
+ * pci_iov_update_resource - update a VF BAR
  * @dev: the PCI device
  * @resno: the resource number
  *
- * Returns position of the BAR encapsulated in the SR-IOV capability.
+ * Update a VF BAR in the SR-IOV capability of a PF.
  */
-int pci_iov_resource_bar(struct pci_dev *dev, int resno)
+void pci_iov_update_resource(struct pci_dev *dev, int resno)
 {
-	if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END)
-		return 0;
+	struct pci_sriov *iov = dev->is_physfn ? dev->sriov : NULL;
+	struct resource *res = dev->resource + resno;
+	int vf_bar = resno - PCI_IOV_RESOURCES;
+	struct pci_bus_region region;
+	u16 cmd;
+	u32 new;
+	int reg;
 
-	BUG_ON(!dev->is_physfn);
+	/*
+	 * The generic pci_restore_bars() path calls this for all devices,
+	 * including VFs and non-SR-IOV devices.  If this is not a PF, we
+	 * have nothing to do.
+	 */
+	if (!iov)
+		return;
 
-	return dev->sriov->pos + PCI_SRIOV_BAR +
-		4 * (resno - PCI_IOV_RESOURCES);
+	pci_read_config_word(dev, iov->pos + PCI_SRIOV_CTRL, &cmd);
+	if ((cmd & PCI_SRIOV_CTRL_VFE) && (cmd & PCI_SRIOV_CTRL_MSE)) {
+		dev_WARN(&dev->dev, "can't update enabled VF BAR%d %pR\n",
+			 vf_bar, res);
+		return;
+	}
+
+	/*
+	 * Ignore unimplemented BARs, unused resource slots for 64-bit
+	 * BARs, and non-movable resources, e.g., those described via
+	 * Enhanced Allocation.
+	 */
+	if (!res->flags)
+		return;
+
+	if (res->flags & IORESOURCE_UNSET)
+		return;
+
+	if (res->flags & IORESOURCE_PCI_FIXED)
+		return;
+
+	pcibios_resource_to_bus(dev->bus, &region, res);
+	new = region.start;
+	new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
+
+	reg = iov->pos + PCI_SRIOV_BAR + 4 * vf_bar;
+	pci_write_config_dword(dev, reg, new);
+	if (res->flags & IORESOURCE_MEM_64) {
+		new = region.start >> 16 >> 16;
+		pci_write_config_dword(dev, reg + 4, new);
+	}
 }
 
 resource_size_t __weak pcibios_iov_resource_alignment(struct pci_dev *dev,
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 7eaa4c8..10a6a8e 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1278,6 +1278,8 @@
 	if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
 		pci_msi_domain_update_chip_ops(info);
 
+	info->flags |= MSI_FLAG_ACTIVATE_EARLY;
+
 	domain = msi_create_irq_domain(fwnode, info, parent);
 	if (!domain)
 		return NULL;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index eead54c..f8b2b59 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -973,15 +973,19 @@
 int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
 		  enum pci_mmap_api mmap_api)
 {
-	unsigned long nr, start, size, pci_start;
+	unsigned long nr, start, size;
+	resource_size_t pci_start = 0, pci_end;
 
 	if (pci_resource_len(pdev, resno) == 0)
 		return 0;
 	nr = vma_pages(vma);
 	start = vma->vm_pgoff;
 	size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
-	pci_start = (mmap_api == PCI_MMAP_PROCFS) ?
-			pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
+	if (mmap_api == PCI_MMAP_PROCFS) {
+		pci_resource_to_user(pdev, resno, &pdev->resource[resno],
+				     &pci_start, &pci_end);
+		pci_start >>= PAGE_SHIFT;
+	}
 	if (start >= pci_start && start < pci_start + size &&
 			start + nr <= pci_start + size)
 		return 1;
@@ -1372,10 +1376,10 @@
 	if (!sysfs_initialized)
 		return -EACCES;
 
-	if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
-		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
-	else
+	if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
 		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+	else
+		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
 	if (retval)
 		goto err;
 
@@ -1427,10 +1431,10 @@
 err_resource_files:
 	pci_remove_resource_files(pdev);
 err_config_file:
-	if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
-		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
-	else
+	if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+	else
+		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
 err:
 	return retval;
 }
@@ -1464,10 +1468,10 @@
 
 	pci_remove_capabilities_sysfs(pdev);
 
-	if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
-		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
-	else
+	if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+	else
+		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
 
 	pci_remove_resource_files(pdev);
 
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 42d8617..1a14ca8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -519,10 +519,6 @@
 {
 	int i;
 
-	/* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
-	if (dev->is_virtfn)
-		return;
-
 	for (i = 0; i < PCI_BRIDGE_RESOURCES; i++)
 		pci_update_resource(dev, i);
 }
@@ -1736,8 +1732,8 @@
 		}
 	}
 	if (!list_empty(&pci_pme_list))
-		schedule_delayed_work(&pci_pme_work,
-				      msecs_to_jiffies(PME_TIMEOUT));
+		queue_delayed_work(system_freezable_wq, &pci_pme_work,
+				   msecs_to_jiffies(PME_TIMEOUT));
 	mutex_unlock(&pci_pme_list_mutex);
 }
 
@@ -1802,8 +1798,9 @@
 			mutex_lock(&pci_pme_list_mutex);
 			list_add(&pme_dev->list, &pci_pme_list);
 			if (list_is_singular(&pci_pme_list))
-				schedule_delayed_work(&pci_pme_work,
-						      msecs_to_jiffies(PME_TIMEOUT));
+				queue_delayed_work(system_freezable_wq,
+						   &pci_pme_work,
+						   msecs_to_jiffies(PME_TIMEOUT));
 			mutex_unlock(&pci_pme_list_mutex);
 		} else {
 			mutex_lock(&pci_pme_list_mutex);
@@ -2043,6 +2040,10 @@
 	if (!dev->pme_support)
 		return false;
 
+	/* PME-capable in principle, but not from the intended sleep state */
+	if (!pci_pme_capable(dev, pci_target_state(dev)))
+		return false;
+
 	while (bus->parent) {
 		struct pci_dev *bridge = bus->self;
 
@@ -4468,36 +4469,6 @@
 }
 EXPORT_SYMBOL(pci_select_bars);
 
-/**
- * pci_resource_bar - get position of the BAR associated with a resource
- * @dev: the PCI device
- * @resno: the resource number
- * @type: the BAR type to be filled in
- *
- * Returns BAR position in config space, or 0 if the BAR is invalid.
- */
-int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
-{
-	int reg;
-
-	if (resno < PCI_ROM_RESOURCE) {
-		*type = pci_bar_unknown;
-		return PCI_BASE_ADDRESS_0 + 4 * resno;
-	} else if (resno == PCI_ROM_RESOURCE) {
-		*type = pci_bar_mem32;
-		return dev->rom_base_reg;
-	} else if (resno < PCI_BRIDGE_RESOURCES) {
-		/* device specific resource */
-		*type = pci_bar_unknown;
-		reg = pci_iov_resource_bar(dev, resno);
-		if (reg)
-			return reg;
-	}
-
-	dev_err(&dev->dev, "BAR %d: invalid resource\n", resno);
-	return 0;
-}
-
 /* Some architectures require additional programming to enable VGA */
 static arch_set_vga_state_t arch_set_vga_state;
 
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d390fc1..c43e448 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -232,7 +232,6 @@
 int pci_setup_device(struct pci_dev *dev);
 int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
 		    struct resource *res, unsigned int reg);
-int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type);
 void pci_configure_ari(struct pci_dev *dev);
 void __pci_bus_size_bridges(struct pci_bus *bus,
 			struct list_head *realloc_head);
@@ -276,7 +275,7 @@
 #ifdef CONFIG_PCI_IOV
 int pci_iov_init(struct pci_dev *dev);
 void pci_iov_release(struct pci_dev *dev);
-int pci_iov_resource_bar(struct pci_dev *dev, int resno);
+void pci_iov_update_resource(struct pci_dev *dev, int resno);
 resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
 void pci_restore_iov_state(struct pci_dev *dev);
 int pci_iov_bus_range(struct pci_bus *bus);
@@ -290,10 +289,6 @@
 
 {
 }
-static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno)
-{
-	return 0;
-}
 static inline void pci_restore_iov_state(struct pci_dev *dev)
 {
 }
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 182224a..58f1419 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer/aer_inject.c
@@ -283,20 +283,6 @@
 	return 0;
 }
 
-static struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
-{
-	while (1) {
-		if (!pci_is_pcie(dev))
-			break;
-		if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
-			return dev;
-		if (!dev->bus->self)
-			break;
-		dev = dev->bus->self;
-	}
-	return NULL;
-}
-
 static int find_aer_device_iter(struct device *device, void *data)
 {
 	struct pcie_device **result = data;
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 317e355..c6a012b5 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -518,25 +518,32 @@
 	link = kzalloc(sizeof(*link), GFP_KERNEL);
 	if (!link)
 		return NULL;
+
 	INIT_LIST_HEAD(&link->sibling);
 	INIT_LIST_HEAD(&link->children);
 	INIT_LIST_HEAD(&link->link);
 	link->pdev = pdev;
-	if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) {
+
+	/*
+	 * Root Ports and PCI/PCI-X to PCIe Bridges are roots of PCIe
+	 * hierarchies.
+	 */
+	if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
+	    pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE) {
+		link->root = link;
+	} else {
 		struct pcie_link_state *parent;
+
 		parent = pdev->bus->parent->self->link_state;
 		if (!parent) {
 			kfree(link);
 			return NULL;
 		}
+
 		link->parent = parent;
+		link->root = link->parent->root;
 		list_add(&link->link, &parent->children);
 	}
-	/* Setup a pointer to the root port link */
-	if (!link->parent)
-		link->root = link;
-	else
-		link->root = link->parent->root;
 
 	list_add(&link->sibling, &link_list);
 	pdev->link_state = link;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 7aafb5f..b83df94 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -179,9 +179,6 @@
 	u16 orig_cmd;
 	struct pci_bus_region region, inverted_region;
 
-	if (dev->non_compliant_bars)
-		return 0;
-
 	mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
 
 	/* No printks while decoding is disabled! */
@@ -229,7 +226,8 @@
 			mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
 		}
 	} else {
-		res->flags |= (l & IORESOURCE_ROM_ENABLE);
+		if (l & PCI_ROM_ADDRESS_ENABLE)
+			res->flags |= IORESOURCE_ROM_ENABLE;
 		l64 = l & PCI_ROM_ADDRESS_MASK;
 		sz64 = sz & PCI_ROM_ADDRESS_MASK;
 		mask64 = (u32)PCI_ROM_ADDRESS_MASK;
@@ -322,6 +320,9 @@
 {
 	unsigned int pos, reg;
 
+	if (dev->non_compliant_bars)
+		return;
+
 	for (pos = 0; pos < howmany; pos++) {
 		struct resource *res = &dev->resource[pos];
 		reg = PCI_BASE_ADDRESS_0 + (pos << 2);
@@ -1019,6 +1020,7 @@
 	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
 	if (!pos)
 		return;
+
 	pdev->pcie_cap = pos;
 	pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
 	pdev->pcie_flags_reg = reg16;
@@ -1026,13 +1028,14 @@
 	pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
 
 	/*
-	 * A Root Port is always the upstream end of a Link.  No PCIe
-	 * component has two Links.  Two Links are connected by a Switch
-	 * that has a Port on each Link and internal logic to connect the
-	 * two Ports.
+	 * A Root Port or a PCI-to-PCIe bridge is always the upstream end
+	 * of a Link.  No PCIe component has two Links.  Two Links are
+	 * connected by a Switch that has a Port on each Link and internal
+	 * logic to connect the two Ports.
 	 */
 	type = pci_pcie_type(pdev);
-	if (type == PCI_EXP_TYPE_ROOT_PORT)
+	if (type == PCI_EXP_TYPE_ROOT_PORT ||
+	    type == PCI_EXP_TYPE_PCIE_BRIDGE)
 		pdev->has_secondary_link = 1;
 	else if (type == PCI_EXP_TYPE_UPSTREAM ||
 		 type == PCI_EXP_TYPE_DOWNSTREAM) {
@@ -1415,6 +1418,21 @@
 		dev_warn(&dev->dev, "PCI-X settings not supported\n");
 }
 
+static bool pcie_root_rcb_set(struct pci_dev *dev)
+{
+	struct pci_dev *rp = pcie_find_root_port(dev);
+	u16 lnkctl;
+
+	if (!rp)
+		return false;
+
+	pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl);
+	if (lnkctl & PCI_EXP_LNKCTL_RCB)
+		return true;
+
+	return false;
+}
+
 static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
 {
 	int pos;
@@ -1444,9 +1462,20 @@
 			~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
 
 	/* Initialize Link Control Register */
-	if (pcie_cap_has_lnkctl(dev))
+	if (pcie_cap_has_lnkctl(dev)) {
+
+		/*
+		 * If the Root Port supports Read Completion Boundary of
+		 * 128, set RCB to 128.  Otherwise, clear it.
+		 */
+		hpp->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB;
+		hpp->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB;
+		if (pcie_root_rcb_set(dev))
+			hpp->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB;
+
 		pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
 			~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
+	}
 
 	/* Find Advanced Error Reporting Enhanced Capability */
 	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7e32730..254192b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -287,6 +287,18 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CITRINE,	quirk_citrine);
 
+/*
+ * This chip can cause bus lockups if config addresses above 0x600
+ * are read or written.
+ */
+static void quirk_nfp6000(struct pci_dev *dev)
+{
+	dev->cfg_size = 0x600;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME,	PCI_DEVICE_ID_NETRONOME_NFP4000,	quirk_nfp6000);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME,	PCI_DEVICE_ID_NETRONOME_NFP6000,	quirk_nfp6000);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME,	PCI_DEVICE_ID_NETRONOME_NFP6000_VF,	quirk_nfp6000);
+
 /*  On IBM Crocodile ipr SAS adapters, expand BAR to system page size */
 static void quirk_extend_bar_to_page(struct pci_dev *dev)
 {
@@ -3115,13 +3127,16 @@
 }
 
 /*
- * Atheros AR93xx chips do not behave after a bus reset.  The device will
- * throw a Link Down error on AER-capable systems and regardless of AER,
- * config space of the device is never accessible again and typically
- * causes the system to hang or reset when access is attempted.
+ * Some Atheros AR9xxx and QCA988x chips do not behave after a bus reset.
+ * The device will throw a Link Down error on AER-capable systems and
+ * regardless of AER, config space of the device is never accessible again
+ * and typically causes the system to hang or reset when access is attempted.
  * http://www.spinics.net/lists/linux-pci/msg34797.html
  */
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset);
 
 static void quirk_no_pm_reset(struct pci_dev *dev)
 {
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index eb0ad53..3eea7fc 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -31,6 +31,11 @@
 	if (!res->flags)
 		return -1;
 
+	/*
+	 * Ideally pci_update_resource() would update the ROM BAR address,
+	 * and we would only set the enable bit here.  But apparently some
+	 * devices have buggy ROM BARs that read as zero when disabled.
+	 */
 	pcibios_resource_to_bus(pdev->bus, &region, res);
 	pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
 	rom_addr &= ~PCI_ROM_ADDRESS_MASK;
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 604011e..2506296 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -25,21 +25,18 @@
 #include <linux/slab.h>
 #include "pci.h"
 
-
-void pci_update_resource(struct pci_dev *dev, int resno)
+static void pci_std_update_resource(struct pci_dev *dev, int resno)
 {
 	struct pci_bus_region region;
 	bool disable;
 	u16 cmd;
 	u32 new, check, mask;
 	int reg;
-	enum pci_bar_type type;
 	struct resource *res = dev->resource + resno;
 
-	if (dev->is_virtfn) {
-		dev_warn(&dev->dev, "can't update VF BAR%d\n", resno);
+	/* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
+	if (dev->is_virtfn)
 		return;
-	}
 
 	/*
 	 * Ignore resources for unimplemented BARs and unused resource slots
@@ -60,21 +57,34 @@
 		return;
 
 	pcibios_resource_to_bus(dev->bus, &region, res);
+	new = region.start;
 
-	new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
-	if (res->flags & IORESOURCE_IO)
+	if (res->flags & IORESOURCE_IO) {
 		mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
-	else
+		new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK;
+	} else if (resno == PCI_ROM_RESOURCE) {
+		mask = (u32)PCI_ROM_ADDRESS_MASK;
+	} else {
 		mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
+		new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
+	}
 
-	reg = pci_resource_bar(dev, resno, &type);
-	if (!reg)
-		return;
-	if (type != pci_bar_unknown) {
+	if (resno < PCI_ROM_RESOURCE) {
+		reg = PCI_BASE_ADDRESS_0 + 4 * resno;
+	} else if (resno == PCI_ROM_RESOURCE) {
+
+		/*
+		 * Apparently some Matrox devices have ROM BARs that read
+		 * as zero when disabled, so don't update ROM BARs unless
+		 * they're enabled.  See https://lkml.org/lkml/2005/8/30/138.
+		 */
 		if (!(res->flags & IORESOURCE_ROM_ENABLE))
 			return;
+
+		reg = dev->rom_base_reg;
 		new |= PCI_ROM_ADDRESS_ENABLE;
-	}
+	} else
+		return;
 
 	/*
 	 * We can't update a 64-bit BAR atomically, so when possible,
@@ -110,6 +120,16 @@
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
+void pci_update_resource(struct pci_dev *dev, int resno)
+{
+	if (resno <= PCI_ROM_RESOURCE)
+		pci_std_update_resource(dev, resno);
+#ifdef CONFIG_PCI_IOV
+	else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
+		pci_iov_update_resource(dev, resno);
+#endif
+}
+
 int pci_claim_resource(struct pci_dev *dev, int resource)
 {
 	struct resource *res = &dev->resource[resource];
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index be3755c..64b07b2 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -13,6 +13,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/cpumask.h>
+#include <linux/cpu_pm.h>
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/of_device.h>
@@ -718,6 +719,104 @@
 	return NOTIFY_OK;
 }
 
+#ifdef CONFIG_CPU_PM
+static void cpu_pm_pmu_setup(struct arm_pmu *armpmu, unsigned long cmd)
+{
+	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
+	struct perf_event *event;
+	int idx;
+
+	for (idx = 0; idx < armpmu->num_events; idx++) {
+		/*
+		 * If the counter is not used skip it, there is no
+		 * need of stopping/restarting it.
+		 */
+		if (!test_bit(idx, hw_events->used_mask))
+			continue;
+
+		event = hw_events->events[idx];
+
+		switch (cmd) {
+		case CPU_PM_ENTER:
+			/*
+			 * Stop and update the counter
+			 */
+			armpmu_stop(event, PERF_EF_UPDATE);
+			break;
+		case CPU_PM_EXIT:
+		case CPU_PM_ENTER_FAILED:
+			 /*
+			  * Restore and enable the counter.
+			  * armpmu_start() indirectly calls
+			  *
+			  * perf_event_update_userpage()
+			  *
+			  * that requires RCU read locking to be functional,
+			  * wrap the call within RCU_NONIDLE to make the
+			  * RCU subsystem aware this cpu is not idle from
+			  * an RCU perspective for the armpmu_start() call
+			  * duration.
+			  */
+			RCU_NONIDLE(armpmu_start(event, PERF_EF_RELOAD));
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
+			     void *v)
+{
+	struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
+	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
+	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+
+	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
+		return NOTIFY_DONE;
+
+	/*
+	 * Always reset the PMU registers on power-up even if
+	 * there are no events running.
+	 */
+	if (cmd == CPU_PM_EXIT && armpmu->reset)
+		armpmu->reset(armpmu);
+
+	if (!enabled)
+		return NOTIFY_OK;
+
+	switch (cmd) {
+	case CPU_PM_ENTER:
+		armpmu->stop(armpmu);
+		cpu_pm_pmu_setup(armpmu, cmd);
+		break;
+	case CPU_PM_EXIT:
+		cpu_pm_pmu_setup(armpmu, cmd);
+	case CPU_PM_ENTER_FAILED:
+		armpmu->start(armpmu);
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+
+	return NOTIFY_OK;
+}
+
+static int cpu_pm_pmu_register(struct arm_pmu *cpu_pmu)
+{
+	cpu_pmu->cpu_pm_nb.notifier_call = cpu_pm_pmu_notify;
+	return cpu_pm_register_notifier(&cpu_pmu->cpu_pm_nb);
+}
+
+static void cpu_pm_pmu_unregister(struct arm_pmu *cpu_pmu)
+{
+	cpu_pm_unregister_notifier(&cpu_pmu->cpu_pm_nb);
+}
+#else
+static inline int cpu_pm_pmu_register(struct arm_pmu *cpu_pmu) { return 0; }
+static inline void cpu_pm_pmu_unregister(struct arm_pmu *cpu_pmu) { }
+#endif
+
 static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
 {
 	int err;
@@ -733,6 +832,10 @@
 	if (err)
 		goto out_hw_events;
 
+	err = cpu_pm_pmu_register(cpu_pmu);
+	if (err)
+		goto out_unregister;
+
 	for_each_possible_cpu(cpu) {
 		struct pmu_hw_events *events = per_cpu_ptr(cpu_hw_events, cpu);
 		raw_spin_lock_init(&events->pmu_lock);
@@ -754,6 +857,8 @@
 
 	return 0;
 
+out_unregister:
+	unregister_cpu_notifier(&cpu_pmu->hotplug_nb);
 out_hw_events:
 	free_percpu(cpu_hw_events);
 	return err;
@@ -761,6 +866,7 @@
 
 static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu)
 {
+	cpu_pm_pmu_unregister(cpu_pmu);
 	unregister_cpu_notifier(&cpu_pmu->hotplug_nb);
 	free_percpu(cpu_pmu->hw_events);
 }
@@ -815,6 +921,7 @@
 			if (i > 0 && spi != using_spi) {
 				pr_err("PPI/SPI IRQ type mismatch for %s!\n",
 					dn->name);
+				of_node_put(dn);
 				kfree(irqs);
 				return -EINVAL;
 			}
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 03cb3ea..b5679fb 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -368,6 +368,7 @@
 config PHY_TUSB1210
 	tristate "TI TUSB1210 ULPI PHY module"
 	depends on USB_ULPI_BUS
+	depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
 	select GENERIC_PHY
 	help
 	  Support for TI TUSB1210 USB ULPI PHY.
diff --git a/drivers/pinctrl/berlin/berlin-bg4ct.c b/drivers/pinctrl/berlin/berlin-bg4ct.c
index 0917204..c617ec4 100644
--- a/drivers/pinctrl/berlin/berlin-bg4ct.c
+++ b/drivers/pinctrl/berlin/berlin-bg4ct.c
@@ -217,7 +217,7 @@
 	BERLIN_PINCTRL_GROUP("SCRD0_CRD_PRES", 0xc, 0x3, 0x15,
 			BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO20 */
 			BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* crd pres */
-			BERLIN_PINCTRL_FUNCTION(0x1, "sd1a")), /* DAT3 */
+			BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* DAT3 */
 	BERLIN_PINCTRL_GROUP("SPI1_SS0n", 0xc, 0x3, 0x18,
 			BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS0n */
 			BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO37 */
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index 1029aa7..398ec45 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -207,9 +207,9 @@
 		pin_reg = &info->pin_regs[pin_id];
 
 		if (pin_reg->mux_reg == -1) {
-			dev_err(ipctl->dev, "Pin(%s) does not support mux function\n",
+			dev_dbg(ipctl->dev, "Pin(%s) does not support mux function\n",
 				info->pins[pin_id].name);
-			return -EINVAL;
+			continue;
 		}
 
 		if (info->flags & SHARE_MUX_CONF_REG) {
diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c
index 6bbda6b..5da9c95 100644
--- a/drivers/pinctrl/freescale/pinctrl-mxs.c
+++ b/drivers/pinctrl/freescale/pinctrl-mxs.c
@@ -195,6 +195,16 @@
 	return 0;
 }
 
+static void mxs_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg)
+{
+	u32 tmp;
+
+	tmp = readl(reg);
+	tmp &= ~(mask << shift);
+	tmp |= value << shift;
+	writel(tmp, reg);
+}
+
 static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
 			       unsigned group)
 {
@@ -212,8 +222,7 @@
 		reg += bank * 0x20 + pin / 16 * 0x10;
 		shift = pin % 16 * 2;
 
-		writel(0x3 << shift, reg + CLR);
-		writel(g->muxsel[i] << shift, reg + SET);
+		mxs_pinctrl_rmwl(g->muxsel[i], 0x3, shift, reg);
 	}
 
 	return 0;
@@ -280,8 +289,7 @@
 			/* mA */
 			if (config & MA_PRESENT) {
 				shift = pin % 8 * 4;
-				writel(0x3 << shift, reg + CLR);
-				writel(ma << shift, reg + SET);
+				mxs_pinctrl_rmwl(ma, 0x3, shift, reg);
 			}
 
 			/* vol */
diff --git a/drivers/pinctrl/intel/pinctrl-broxton.c b/drivers/pinctrl/intel/pinctrl-broxton.c
index 5979d38..7329500 100644
--- a/drivers/pinctrl/intel/pinctrl-broxton.c
+++ b/drivers/pinctrl/intel/pinctrl-broxton.c
@@ -19,7 +19,7 @@
 
 #define BXT_PAD_OWN	0x020
 #define BXT_HOSTSW_OWN	0x080
-#define BXT_PADCFGLOCK	0x090
+#define BXT_PADCFGLOCK	0x060
 #define BXT_GPI_IE	0x110
 
 #define BXT_COMMUNITY(s, e)				\
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 84936ba..930f0f2 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -160,7 +160,6 @@
  * @pctldev: Pointer to the pin controller device
  * @chip: GPIO chip in this pin controller
  * @regs: MMIO registers
- * @lock: Lock to serialize register accesses
  * @intr_lines: Stores mapping between 16 HW interrupt wires and GPIO
  *		offset (in GPIO number space)
  * @community: Community this pinctrl instance represents
@@ -174,7 +173,6 @@
 	struct pinctrl_dev *pctldev;
 	struct gpio_chip chip;
 	void __iomem *regs;
-	raw_spinlock_t lock;
 	unsigned intr_lines[16];
 	const struct chv_community *community;
 	u32 saved_intmask;
@@ -659,6 +657,17 @@
 	&southeast_community,
 };
 
+/*
+ * Lock to serialize register accesses
+ *
+ * Due to a silicon issue, a shared lock must be used to prevent
+ * concurrent accesses across the 4 GPIO controllers.
+ *
+ * See Intel Atom Z8000 Processor Series Specification Update (Rev. 005),
+ * errata #CHT34, for further information.
+ */
+static DEFINE_RAW_SPINLOCK(chv_lock);
+
 static void __iomem *chv_padreg(struct chv_pinctrl *pctrl, unsigned offset,
 				unsigned reg)
 {
@@ -720,13 +729,13 @@
 	u32 ctrl0, ctrl1;
 	bool locked;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 
 	ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
 	ctrl1 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL1));
 	locked = chv_pad_locked(pctrl, offset);
 
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	if (ctrl0 & CHV_PADCTRL0_GPIOEN) {
 		seq_puts(s, "GPIO ");
@@ -789,14 +798,14 @@
 
 	grp = &pctrl->community->groups[group];
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 
 	/* Check first that the pad is not locked */
 	for (i = 0; i < grp->npins; i++) {
 		if (chv_pad_locked(pctrl, grp->pins[i])) {
 			dev_warn(pctrl->dev, "unable to set mode for locked pin %u\n",
 				 grp->pins[i]);
-			raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+			raw_spin_unlock_irqrestore(&chv_lock, flags);
 			return -EBUSY;
 		}
 	}
@@ -839,7 +848,7 @@
 			pin, altfunc->mode, altfunc->invert_oe ? "" : "not ");
 	}
 
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	return 0;
 }
@@ -853,13 +862,13 @@
 	void __iomem *reg;
 	u32 value;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 
 	if (chv_pad_locked(pctrl, offset)) {
 		value = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
 		if (!(value & CHV_PADCTRL0_GPIOEN)) {
 			/* Locked so cannot enable */
-			raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+			raw_spin_unlock_irqrestore(&chv_lock, flags);
 			return -EBUSY;
 		}
 	} else {
@@ -899,7 +908,7 @@
 		chv_writel(value, reg);
 	}
 
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	return 0;
 }
@@ -913,13 +922,13 @@
 	void __iomem *reg;
 	u32 value;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 
 	reg = chv_padreg(pctrl, offset, CHV_PADCTRL0);
 	value = readl(reg) & ~CHV_PADCTRL0_GPIOEN;
 	chv_writel(value, reg);
 
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 }
 
 static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
@@ -931,7 +940,7 @@
 	unsigned long flags;
 	u32 ctrl0;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 
 	ctrl0 = readl(reg) & ~CHV_PADCTRL0_GPIOCFG_MASK;
 	if (input)
@@ -940,7 +949,7 @@
 		ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPO << CHV_PADCTRL0_GPIOCFG_SHIFT;
 	chv_writel(ctrl0, reg);
 
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	return 0;
 }
@@ -965,10 +974,10 @@
 	u16 arg = 0;
 	u32 term;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 	ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
 	ctrl1 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL1));
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	term = (ctrl0 & CHV_PADCTRL0_TERM_MASK) >> CHV_PADCTRL0_TERM_SHIFT;
 
@@ -1042,7 +1051,7 @@
 	unsigned long flags;
 	u32 ctrl0, pull;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 	ctrl0 = readl(reg);
 
 	switch (param) {
@@ -1065,7 +1074,7 @@
 			pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT;
 			break;
 		default:
-			raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+			raw_spin_unlock_irqrestore(&chv_lock, flags);
 			return -EINVAL;
 		}
 
@@ -1083,7 +1092,7 @@
 			pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT;
 			break;
 		default:
-			raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+			raw_spin_unlock_irqrestore(&chv_lock, flags);
 			return -EINVAL;
 		}
 
@@ -1091,12 +1100,12 @@
 		break;
 
 	default:
-		raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+		raw_spin_unlock_irqrestore(&chv_lock, flags);
 		return -EINVAL;
 	}
 
 	chv_writel(ctrl0, reg);
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	return 0;
 }
@@ -1162,9 +1171,9 @@
 	unsigned long flags;
 	u32 ctrl0, cfg;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 	ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
 	cfg >>= CHV_PADCTRL0_GPIOCFG_SHIFT;
@@ -1182,7 +1191,7 @@
 	void __iomem *reg;
 	u32 ctrl0;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 
 	reg = chv_padreg(pctrl, pin, CHV_PADCTRL0);
 	ctrl0 = readl(reg);
@@ -1194,7 +1203,7 @@
 
 	chv_writel(ctrl0, reg);
 
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 }
 
 static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
@@ -1204,9 +1213,9 @@
 	u32 ctrl0, direction;
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 	ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
 	direction >>= CHV_PADCTRL0_GPIOCFG_SHIFT;
@@ -1244,14 +1253,14 @@
 	int pin = chv_gpio_offset_to_pin(pctrl, irqd_to_hwirq(d));
 	u32 intr_line;
 
-	raw_spin_lock(&pctrl->lock);
+	raw_spin_lock(&chv_lock);
 
 	intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
 	intr_line &= CHV_PADCTRL0_INTSEL_MASK;
 	intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT;
 	chv_writel(BIT(intr_line), pctrl->regs + CHV_INTSTAT);
 
-	raw_spin_unlock(&pctrl->lock);
+	raw_spin_unlock(&chv_lock);
 }
 
 static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
@@ -1262,7 +1271,7 @@
 	u32 value, intr_line;
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 
 	intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
 	intr_line &= CHV_PADCTRL0_INTSEL_MASK;
@@ -1275,7 +1284,7 @@
 		value |= BIT(intr_line);
 	chv_writel(value, pctrl->regs + CHV_INTMASK);
 
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 }
 
 static void chv_gpio_irq_mask(struct irq_data *d)
@@ -1309,7 +1318,7 @@
 		unsigned long flags;
 		u32 intsel, value;
 
-		raw_spin_lock_irqsave(&pctrl->lock, flags);
+		raw_spin_lock_irqsave(&chv_lock, flags);
 		intsel = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
 		intsel &= CHV_PADCTRL0_INTSEL_MASK;
 		intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
@@ -1324,7 +1333,7 @@
 			irq_set_handler_locked(d, handler);
 			pctrl->intr_lines[intsel] = offset;
 		}
-		raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+		raw_spin_unlock_irqrestore(&chv_lock, flags);
 	}
 
 	chv_gpio_irq_unmask(d);
@@ -1340,7 +1349,7 @@
 	unsigned long flags;
 	u32 value;
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	raw_spin_lock_irqsave(&chv_lock, flags);
 
 	/*
 	 * Pins which can be used as shared interrupt are configured in
@@ -1389,7 +1398,7 @@
 	else if (type & IRQ_TYPE_LEVEL_MASK)
 		irq_set_handler_locked(d, handle_level_irq);
 
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	return 0;
 }
@@ -1457,12 +1466,11 @@
 		offset += range->npins;
 	}
 
-	/* Mask and clear all interrupts */
-	chv_writel(0, pctrl->regs + CHV_INTMASK);
+	/* Clear all interrupts */
 	chv_writel(0xffff, pctrl->regs + CHV_INTSTAT);
 
 	ret = gpiochip_irqchip_add(chip, &chv_gpio_irqchip, 0,
-				   handle_simple_irq, IRQ_TYPE_NONE);
+				   handle_bad_irq, IRQ_TYPE_NONE);
 	if (ret) {
 		dev_err(pctrl->dev, "failed to add IRQ chip\n");
 		goto fail;
@@ -1501,7 +1509,6 @@
 	if (i == ARRAY_SIZE(chv_communities))
 		return -ENODEV;
 
-	raw_spin_lock_init(&pctrl->lock);
 	pctrl->dev = &pdev->dev;
 
 #ifdef CONFIG_PM_SLEEP
@@ -1556,12 +1563,15 @@
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int chv_pinctrl_suspend(struct device *dev)
+static int chv_pinctrl_suspend_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct chv_pinctrl *pctrl = platform_get_drvdata(pdev);
+	unsigned long flags;
 	int i;
 
+	raw_spin_lock_irqsave(&chv_lock, flags);
+
 	pctrl->saved_intmask = readl(pctrl->regs + CHV_INTMASK);
 
 	for (i = 0; i < pctrl->community->npins; i++) {
@@ -1582,15 +1592,20 @@
 		ctx->padctrl1 = readl(reg);
 	}
 
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
+
 	return 0;
 }
 
-static int chv_pinctrl_resume(struct device *dev)
+static int chv_pinctrl_resume_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct chv_pinctrl *pctrl = platform_get_drvdata(pdev);
+	unsigned long flags;
 	int i;
 
+	raw_spin_lock_irqsave(&chv_lock, flags);
+
 	/*
 	 * Mask all interrupts before restoring per-pin configuration
 	 * registers because we don't know in which state BIOS left them
@@ -1635,12 +1650,15 @@
 	chv_writel(0xffff, pctrl->regs + CHV_INTSTAT);
 	chv_writel(pctrl->saved_intmask, pctrl->regs + CHV_INTMASK);
 
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
+
 	return 0;
 }
 #endif
 
 static const struct dev_pm_ops chv_pinctrl_pm_ops = {
-	SET_LATE_SYSTEM_SLEEP_PM_OPS(chv_pinctrl_suspend, chv_pinctrl_resume)
+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(chv_pinctrl_suspend_noirq,
+				      chv_pinctrl_resume_noirq)
 };
 
 static const struct acpi_device_id chv_pinctrl_acpi_match[] = {
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 3d8019e..181b358 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1191,9 +1191,10 @@
 	const struct mtk_desc_pin *pin;
 
 	chained_irq_enter(chip, desc);
-	for (eint_num = 0; eint_num < pctl->devdata->ap_num; eint_num += 32) {
+	for (eint_num = 0;
+	     eint_num < pctl->devdata->ap_num;
+	     eint_num += 32, reg += 4) {
 		status = readl(reg);
-		reg += 4;
 		while (status) {
 			offset = __ffs(status);
 			index = eint_num + offset;
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 84943e4..13730ca 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -246,7 +246,7 @@
 {
 	struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
 
-	meson_pmx_disable_other_groups(pc, range->pin_base + offset, -1);
+	meson_pmx_disable_other_groups(pc, offset, -1);
 
 	return 0;
 }
diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c
index 9677807..b505b87 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8b.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8b.c
@@ -732,8 +732,8 @@
 static const char * const nand_groups[] = {
 	"nand_io", "nand_io_ce0", "nand_io_ce1",
 	"nand_io_rb0", "nand_ale", "nand_cle",
-	"nand_wen_clk", "nand_ren_clk", "nand_dqs0",
-	"nand_dqs1"
+	"nand_wen_clk", "nand_ren_clk", "nand_dqs_0",
+	"nand_dqs_1"
 };
 
 static const char * const nor_groups[] = {
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 3318f1d..7340ff7 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -48,17 +48,6 @@
 
 	spin_lock_irqsave(&gpio_dev->lock, flags);
 	pin_reg = readl(gpio_dev->base + offset * 4);
-	/*
-	 * Suppose BIOS or Bootloader sets specific debounce for the
-	 * GPIO. if not, set debounce to be  2.75ms and remove glitch.
-	*/
-	if ((pin_reg & DB_TMR_OUT_MASK) == 0) {
-		pin_reg |= 0xf;
-		pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
-		pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
-		pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
-	}
-
 	pin_reg &= ~BIT(OUTPUT_ENABLE_OFF);
 	writel(pin_reg, gpio_dev->base + offset * 4);
 	spin_unlock_irqrestore(&gpio_dev->lock, flags);
@@ -331,15 +320,6 @@
 
 	spin_lock_irqsave(&gpio_dev->lock, flags);
 	pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
-	/*
-		Suppose BIOS or Bootloader sets specific debounce for the
-		GPIO. if not, set debounce to be  2.75ms.
-	*/
-	if ((pin_reg & DB_TMR_OUT_MASK) == 0) {
-		pin_reg |= 0xf;
-		pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
-		pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
-	}
 	pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
 	pin_reg |= BIT(INTERRUPT_MASK_OFF);
 	writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 33edd07..271cca6 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -717,9 +717,11 @@
 			break;
 		case PIN_CONFIG_BIAS_PULL_UP:
 			conf |= ATMEL_PIO_PUEN_MASK;
+			conf &= (~ATMEL_PIO_PDEN_MASK);
 			break;
 		case PIN_CONFIG_BIAS_PULL_DOWN:
 			conf |= ATMEL_PIO_PDEN_MASK;
+			conf &= (~ATMEL_PIO_PUEN_MASK);
 			break;
 		case PIN_CONFIG_DRIVE_OPEN_DRAIN:
 			if (arg == 0)
@@ -1000,7 +1002,7 @@
 		atmel_pioctrl->irqs[i] = res->start;
 		irq_set_chained_handler(res->start, atmel_gpio_irq_handler);
 		irq_set_handler_data(res->start, atmel_pioctrl);
-		dev_dbg(dev, "bank %i: hwirq=%u\n", i, res->start);
+		dev_dbg(dev, "bank %i: irq=%pr\n", i, res);
 	}
 
 	atmel_pioctrl->irq_domain = irq_domain_add_linear(dev->of_node,
diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c
index 6b1a47f..98a459b 100644
--- a/drivers/pinctrl/pinctrl-pistachio.c
+++ b/drivers/pinctrl/pinctrl-pistachio.c
@@ -809,17 +809,17 @@
 			   PADS_FUNCTION_SELECT2, 12, 0x3),
 	MFIO_MUX_PIN_GROUP(83, MIPS_PLL_LOCK, MIPS_TRACE_DATA, USB_DEBUG,
 			   PADS_FUNCTION_SELECT2, 14, 0x3),
-	MFIO_MUX_PIN_GROUP(84, SYS_PLL_LOCK, MIPS_TRACE_DATA, USB_DEBUG,
+	MFIO_MUX_PIN_GROUP(84, AUDIO_PLL_LOCK, MIPS_TRACE_DATA, USB_DEBUG,
 			   PADS_FUNCTION_SELECT2, 16, 0x3),
-	MFIO_MUX_PIN_GROUP(85, WIFI_PLL_LOCK, MIPS_TRACE_DATA, SDHOST_DEBUG,
+	MFIO_MUX_PIN_GROUP(85, RPU_V_PLL_LOCK, MIPS_TRACE_DATA, SDHOST_DEBUG,
 			   PADS_FUNCTION_SELECT2, 18, 0x3),
-	MFIO_MUX_PIN_GROUP(86, BT_PLL_LOCK, MIPS_TRACE_DATA, SDHOST_DEBUG,
+	MFIO_MUX_PIN_GROUP(86, RPU_L_PLL_LOCK, MIPS_TRACE_DATA, SDHOST_DEBUG,
 			   PADS_FUNCTION_SELECT2, 20, 0x3),
-	MFIO_MUX_PIN_GROUP(87, RPU_V_PLL_LOCK, DREQ2, SOCIF_DEBUG,
+	MFIO_MUX_PIN_GROUP(87, SYS_PLL_LOCK, DREQ2, SOCIF_DEBUG,
 			   PADS_FUNCTION_SELECT2, 22, 0x3),
-	MFIO_MUX_PIN_GROUP(88, RPU_L_PLL_LOCK, DREQ3, SOCIF_DEBUG,
+	MFIO_MUX_PIN_GROUP(88, WIFI_PLL_LOCK, DREQ3, SOCIF_DEBUG,
 			   PADS_FUNCTION_SELECT2, 24, 0x3),
-	MFIO_MUX_PIN_GROUP(89, AUDIO_PLL_LOCK, DREQ4, DREQ5,
+	MFIO_MUX_PIN_GROUP(89, BT_PLL_LOCK, DREQ4, DREQ5,
 			   PADS_FUNCTION_SELECT2, 26, 0x3),
 	PIN_GROUP(TCK, "tck"),
 	PIN_GROUP(TRSTN, "trstn"),
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 23b6b8c..73d8d47 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1576,6 +1576,9 @@
 		else
 			mask &= ~soc_mask;
 		pcs->write(mask, pcswi->reg);
+
+		/* flush posted write */
+		mask = pcs->read(pcswi->reg);
 		raw_spin_unlock(&pcs->lock);
 	}
 
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 146264a..9736f9b 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -597,10 +597,6 @@
 
 	spin_lock_irqsave(&pctrl->lock, flags);
 
-	val = readl(pctrl->regs + g->intr_status_reg);
-	val &= ~BIT(g->intr_status_bit);
-	writel(val, pctrl->regs + g->intr_status_reg);
-
 	val = readl(pctrl->regs + g->intr_cfg_reg);
 	val |= BIT(g->intr_enable_bit);
 	writel(val, pctrl->regs + g->intr_cfg_reg);
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
index 82dc109..3149a87 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
@@ -107,6 +107,7 @@
  * @nr_groups: number of pin groups available.
  * @pmx_functions: list of pin functions parsed from device tree.
  * @nr_functions: number of pin functions available.
+ * @range: gpio range to register with pinctrl
  */
 struct exynos5440_pinctrl_priv_data {
 	void __iomem			*reg_base;
@@ -117,6 +118,7 @@
 	unsigned int			nr_groups;
 	const struct exynos5440_pmx_func	*pmx_functions;
 	unsigned int			nr_functions;
+	struct pinctrl_gpio_range	range;
 };
 
 /**
@@ -742,7 +744,6 @@
 	struct pinctrl_desc *ctrldesc;
 	struct pinctrl_dev *pctl_dev;
 	struct pinctrl_pin_desc *pindesc, *pdesc;
-	struct pinctrl_gpio_range grange;
 	char *pin_names;
 	int pin, ret;
 
@@ -794,12 +795,12 @@
 		return PTR_ERR(pctl_dev);
 	}
 
-	grange.name = "exynos5440-pctrl-gpio-range";
-	grange.id = 0;
-	grange.base = 0;
-	grange.npins = EXYNOS5440_MAX_PINS;
-	grange.gc = priv->gc;
-	pinctrl_add_gpio_range(pctl_dev, &grange);
+	priv->range.name = "exynos5440-pctrl-gpio-range";
+	priv->range.id = 0;
+	priv->range.base = 0;
+	priv->range.npins = EXYNOS5440_MAX_PINS;
+	priv->range.gc = priv->gc;
+	pinctrl_add_gpio_range(pctl_dev, &priv->range);
 	return 0;
 }
 
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index 2b0d702..699efb1 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -543,6 +543,9 @@
 		ret = info->ops->init(pfc);
 		if (ret < 0)
 			return ret;
+
+		/* .init() may have overridden pfc->info */
+		info = pfc->info;
 	}
 
 	/* Enable dummy states for those platforms without pinctrl support */
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 87a4f44..42ffa87 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -1102,7 +1102,7 @@
 	PINMUX_IPSR_MSEL(IP6_5_3, FMIN_E, SEL_FM_4),
 	PINMUX_IPSR_DATA(IP6_7_6, AUDIO_CLKOUT),
 	PINMUX_IPSR_MSEL(IP6_7_6, MSIOF1_SS1_B, SEL_SOF1_1),
-	PINMUX_IPSR_MSEL(IP6_5_3, TX2, SEL_SCIF2_0),
+	PINMUX_IPSR_MSEL(IP6_7_6, TX2, SEL_SCIF2_0),
 	PINMUX_IPSR_MSEL(IP6_7_6, SCIFA2_TXD, SEL_SCIFA2_0),
 	PINMUX_IPSR_DATA(IP6_9_8, IRQ0),
 	PINMUX_IPSR_MSEL(IP6_9_8, SCIFB1_RXD_D, SEL_SCIFB1_3),
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index 863c3e3..50f2014 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -483,7 +483,8 @@
 
 	switch (param) {
 	case PIN_CONFIG_BIAS_DISABLE:
-		return true;
+		return pin->configs &
+			(SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN);
 
 	case PIN_CONFIG_BIAS_PULL_UP:
 		return pin->configs & SH_PFC_PIN_CFG_PULL_UP;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
index 55083d2..51fbf85 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
@@ -485,12 +485,12 @@
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
 		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 8)),	/* PG_EINT8 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
 		  SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 9)),	/* PG_EINT9 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
index 8b381d6..584cded 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
@@ -407,12 +407,12 @@
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart2"),		/* RTS */
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
 		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 8)),	/* PG_EINT8 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "uart2"),		/* CTS */
+		  SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
 		  SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 9)),	/* PG_EINT9 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
index 90b973e..a7c81e9 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
@@ -394,7 +394,7 @@
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 18),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x3, "owa")),		/* DOUT */
+		  SUNXI_FUNCTION(0x3, "spdif")),	/* DOUT */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 19),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out")),
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 589872c..a19c29c 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -73,6 +73,12 @@
 	case UNIPHIER_PIN_PULL_DOWN:
 		pull_dir = "DOWN";
 		break;
+	case UNIPHIER_PIN_PULL_UP_FIXED:
+		pull_dir = "UP(FIXED)";
+		break;
+	case UNIPHIER_PIN_PULL_DOWN_FIXED:
+		pull_dir = "DOWN(FIXED)";
+		break;
 	case UNIPHIER_PIN_PULL_NONE:
 		pull_dir = "NONE";
 		break;
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index c11db8b..5bd93a2 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -4,7 +4,6 @@
 if MIPS
 source "drivers/platform/mips/Kconfig"
 endif
-
 source "drivers/platform/goldfish/Kconfig"
 
 source "drivers/platform/chrome/Kconfig"
diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
index d45cd25..2b331d5 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -147,13 +147,19 @@
 		goto exit;
 	}
 
+	if (u_cmd.outsize != s_cmd->outsize ||
+	    u_cmd.insize != s_cmd->insize) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
 	s_cmd->command += ec->cmd_offset;
 	ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd);
 	/* Only copy data to userland if data was received. */
 	if (ret < 0)
 		goto exit;
 
-	if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + u_cmd.insize))
+	if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + s_cmd->insize))
 		ret = -EFAULT;
 exit:
 	kfree(s_cmd);
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index 990308c..92430f7 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -380,3 +380,20 @@
 	return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+			    struct cros_ec_command *msg)
+{
+	int ret;
+
+	ret = cros_ec_cmd_xfer(ec_dev, msg);
+	if (ret < 0) {
+		dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+	} else if (msg->result != EC_RES_SUCCESS) {
+		dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result);
+		return -EPROTO;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/drivers/platform/goldfish/Makefile b/drivers/platform/goldfish/Makefile
index d348712..277a820 100644
--- a/drivers/platform/goldfish/Makefile
+++ b/drivers/platform/goldfish/Makefile
@@ -2,4 +2,5 @@
 # Makefile for Goldfish platform specific drivers
 #
 obj-$(CONFIG_GOLDFISH_BUS)	+= pdev_bus.o
-obj-$(CONFIG_GOLDFISH_PIPE)	+= goldfish_pipe.o
+obj-$(CONFIG_GOLDFISH_PIPE)	+= goldfish_pipe_all.o
+goldfish_pipe_all-objs := goldfish_pipe.o goldfish_pipe_v2.o
diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c
index ffd7713..fd1452e2 100644
--- a/drivers/platform/goldfish/goldfish_pipe.c
+++ b/drivers/platform/goldfish/goldfish_pipe.c
@@ -15,51 +15,11 @@
  *
  */
 
-/* This source file contains the implementation of a special device driver
- * that intends to provide a *very* fast communication channel between the
- * guest system and the QEMU emulator.
- *
- * Usage from the guest is simply the following (error handling simplified):
- *
- *    int  fd = open("/dev/qemu_pipe",O_RDWR);
- *    .... write() or read() through the pipe.
- *
- * This driver doesn't deal with the exact protocol used during the session.
- * It is intended to be as simple as something like:
- *
- *    // do this _just_ after opening the fd to connect to a specific
- *    // emulator service.
- *    const char*  msg = "<pipename>";
- *    if (write(fd, msg, strlen(msg)+1) < 0) {
- *       ... could not connect to <pipename> service
- *       close(fd);
- *    }
- *
- *    // after this, simply read() and write() to communicate with the
- *    // service. Exact protocol details left as an exercise to the reader.
- *
- * This driver is very fast because it doesn't copy any data through
- * intermediate buffers, since the emulator is capable of translating
- * guest user addresses into host ones.
- *
- * Note that we must however ensure that each user page involved in the
- * exchange is properly mapped during a transfer.
+/* This source file contains the implementation of the legacy version of
+ * a goldfish pipe device driver. See goldfish_pipe_v2.c for the current
+ * version.
  */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/goldfish.h>
-#include <linux/mm.h>
-#include <linux/acpi.h>
+#include "goldfish_pipe.h"
 
 /*
  * IMPORTANT: The following constants must match the ones used and defined
@@ -109,29 +69,15 @@
 #define PIPE_WAKE_READ         (1 << 1)  /* pipe can now be read from */
 #define PIPE_WAKE_WRITE        (1 << 2)  /* pipe can now be written to */
 
-struct access_params {
-	unsigned long channel;
-	u32 size;
-	unsigned long address;
-	u32 cmd;
-	u32 result;
-	/* reserved for future extension */
-	u32 flags;
-};
+#define MAX_PAGES_TO_GRAB 32
 
-/* The global driver data. Holds a reference to the i/o page used to
- * communicate with the emulator, and a wake queue for blocked tasks
- * waiting to be awoken.
- */
-struct goldfish_pipe_dev {
-	spinlock_t lock;
-	unsigned char __iomem *base;
-	struct access_params *aps;
-	int irq;
-	u32 version;
-};
+#define DEBUG 0
 
-static struct goldfish_pipe_dev   pipe_dev[1];
+#if DEBUG
+#define DPRINT(...) { printk(KERN_ERR __VA_ARGS__); }
+#else
+#define DPRINT(...)
+#endif
 
 /* This data type models a given pipe instance */
 struct goldfish_pipe {
@@ -141,6 +87,15 @@
 	wait_queue_head_t wake_queue;
 };
 
+struct access_params {
+	unsigned long channel;
+	u32 size;
+	unsigned long address;
+	u32 cmd;
+	u32 result;
+	/* reserved for future extension */
+	u32 flags;
+};
 
 /* Bit flags for the 'flags' field */
 enum {
@@ -231,8 +186,10 @@
 	if (valid_batchbuffer_addr(dev, aps)) {
 		dev->aps = aps;
 		return 0;
-	} else
+	} else {
+		devm_kfree(&pdev->dev, aps);
 		return -1;
+	}
 }
 
 /* A value that will not be set by qemu emulator */
@@ -263,12 +220,13 @@
 }
 
 static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer,
-				       size_t bufflen, int is_write)
+				    size_t bufflen, int is_write)
 {
 	unsigned long irq_flags;
 	struct goldfish_pipe *pipe = filp->private_data;
 	struct goldfish_pipe_dev *dev = pipe->dev;
 	unsigned long address, address_end;
+	struct page* pages[MAX_PAGES_TO_GRAB] = {};
 	int count = 0, ret = -EINVAL;
 
 	/* If the emulator already closed the pipe, no need to go further */
@@ -293,45 +251,61 @@
 
 	while (address < address_end) {
 		unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE;
-		unsigned long next     = page_end < address_end ? page_end
-								: address_end;
-		unsigned long avail    = next - address;
-		int status, wakeBit;
-		struct page *page;
-
-		/* Either vaddr or paddr depending on the device version */
-		unsigned long xaddr;
+		unsigned long next, avail;
+		int status, wakeBit, page_i, num_contiguous_pages;
+		long first_page, last_page, requested_pages;
+		unsigned long xaddr, xaddr_prev, xaddr_i;
 
 		/*
-		 * We grab the pages on a page-by-page basis in case user
-		 * space gives us a potentially huge buffer but the read only
-		 * returns a small amount, then there's no need to pin that
-		 * much memory to the process.
+		 * Attempt to grab multiple physically contiguous pages.
 		 */
-		down_read(&current->mm->mmap_sem);
-		ret = get_user_pages(current, current->mm, address, 1,
-				     !is_write, 0, &page, NULL);
-		up_read(&current->mm->mmap_sem);
-		if (ret < 0)
-			return ret;
-
-		if (dev->version) {
-			/* Device version 1 or newer (qemu-android) expects the
-			 * physical address.
-			 */
-			xaddr = page_to_phys(page) | (address & ~PAGE_MASK);
-		} else {
-			/* Device version 0 (classic emulator) expects the
-			 * virtual address.
-			 */
-			xaddr = address;
+		first_page = address & PAGE_MASK;
+		last_page = (address_end - 1) & PAGE_MASK;
+		requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1;
+		if (requested_pages > MAX_PAGES_TO_GRAB) {
+			requested_pages = MAX_PAGES_TO_GRAB;
 		}
+		ret = get_user_pages_fast(first_page, requested_pages,
+				!is_write, pages);
+
+		DPRINT("%s: requested pages: %d %d %p\n", __FUNCTION__,
+			ret, requested_pages, first_page);
+		if (ret == 0) {
+			DPRINT("%s: error: (requested pages == 0) (wanted %d)\n",
+					__FUNCTION__, requested_pages);
+			mutex_unlock(&pipe->lock);
+			return ret;
+		}
+		if (ret < 0) {
+			DPRINT("%s: (requested pages < 0) %d \n",
+				 	__FUNCTION__, requested_pages);
+			mutex_unlock(&pipe->lock);
+			return ret;
+		}
+
+		xaddr = page_to_phys(pages[0]) | (address & ~PAGE_MASK);
+		xaddr_prev = xaddr;
+		num_contiguous_pages = ret == 0 ? 0 : 1;
+		for (page_i = 1; page_i < ret; page_i++) {
+			xaddr_i = page_to_phys(pages[page_i]) | (address & ~PAGE_MASK);
+			if (xaddr_i == xaddr_prev + PAGE_SIZE) {
+				page_end += PAGE_SIZE;
+				xaddr_prev = xaddr_i;
+				num_contiguous_pages++;
+			} else {
+				DPRINT("%s: discontinuous page boundary: %d pages instead\n",
+						__FUNCTION__, page_i);
+				break;
+			}
+		}
+		next = page_end < address_end ? page_end : address_end;
+		avail = next - address;
 
 		/* Now, try to transfer the bytes in the current page */
 		spin_lock_irqsave(&dev->lock, irq_flags);
 		if (access_with_param(dev,
-				is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER,
-				xaddr, avail, pipe, &status)) {
+					is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER,
+					xaddr, avail, pipe, &status)) {
 			gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
 				     dev->base + PIPE_REG_CHANNEL_HIGH);
 			writel(avail, dev->base + PIPE_REG_SIZE);
@@ -339,14 +313,18 @@
 				     dev->base + PIPE_REG_ADDRESS,
 				     dev->base + PIPE_REG_ADDRESS_HIGH);
 			writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER,
-					dev->base + PIPE_REG_COMMAND);
+			       dev->base + PIPE_REG_COMMAND);
 			status = readl(dev->base + PIPE_REG_STATUS);
 		}
 		spin_unlock_irqrestore(&dev->lock, irq_flags);
 
-		if (status > 0 && !is_write)
-			set_page_dirty(page);
-		put_page(page);
+		for (page_i = 0; page_i < ret; page_i++) {
+			if (status > 0 && !is_write &&
+				page_i < num_contiguous_pages) {
+				set_page_dirty(pages[page_i]);
+			}
+			put_page(pages[page_i]);
+		}
 
 		if (status > 0) { /* Correct transfer */
 			count += status;
@@ -357,7 +335,7 @@
 			break;
 		} else if (status < 0 && count > 0) {
 			/*
-			 * An error occurred and we already transferred
+			 * An error occured and we already transfered
 			 * something on one of the previous pages.
 			 * Just return what we already copied and log this
 			 * err.
@@ -368,7 +346,7 @@
 			 */
 			if (status != PIPE_ERROR_AGAIN)
 				pr_info_ratelimited("goldfish_pipe: backend returned error %d on %s\n",
-					status, is_write ? "write" : "read");
+						status, is_write ? "write" : "read");
 			ret = 0;
 			break;
 		}
@@ -378,7 +356,7 @@
 		 * non-blocking mode, just return the error code.
 		 */
 		if (status != PIPE_ERROR_AGAIN ||
-			(filp->f_flags & O_NONBLOCK) != 0) {
+				(filp->f_flags & O_NONBLOCK) != 0) {
 			ret = goldfish_pipe_error_convert(status);
 			break;
 		}
@@ -392,7 +370,7 @@
 
 		/* Tell the emulator we're going to wait for a wake event */
 		goldfish_cmd(pipe,
-			is_write ? CMD_WAKE_ON_WRITE : CMD_WAKE_ON_READ);
+				is_write ? CMD_WAKE_ON_WRITE : CMD_WAKE_ON_READ);
 
 		/* Unlock the pipe, then wait for the wake signal */
 		mutex_unlock(&pipe->lock);
@@ -400,22 +378,16 @@
 		while (test_bit(wakeBit, &pipe->flags)) {
 			if (wait_event_interruptible(
 					pipe->wake_queue,
-					!test_bit(wakeBit, &pipe->flags))) {
-				ret = -ERESTARTSYS;
-				break;
-			}
+					!test_bit(wakeBit, &pipe->flags)))
+				return -ERESTARTSYS;
 
-			if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) {
-				ret = -EIO;
-				break;
-			}
+			if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))
+				return -EIO;
 		}
 
 		/* Try to re-acquire the lock */
-		if (mutex_lock_interruptible(&pipe->lock)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
+		if (mutex_lock_interruptible(&pipe->lock))
+			return -ERESTARTSYS;
 	}
 	mutex_unlock(&pipe->lock);
 
@@ -477,7 +449,7 @@
 
 	/*
 	 * We're going to read from the emulator a list of (channel,flags)
-	 * pairs corresponding to the wake events that occurred on each
+	 * pairs corresponding to the wake events that occured on each
 	 * blocked pipe (i.e. channel).
 	 */
 	spin_lock_irqsave(&dev->lock, irq_flags);
@@ -544,6 +516,8 @@
 
 	pipe->dev = dev;
 	mutex_init(&pipe->lock);
+	DPRINT("%s: call. pipe_dev pipe_dev=0x%lx new_pipe_addr=0x%lx file=0x%lx\n", __FUNCTION__, pipe_dev, pipe, file);
+	// spin lock init, write head of list, i guess
 	init_waitqueue_head(&pipe->wake_queue);
 
 	/*
@@ -566,6 +540,7 @@
 {
 	struct goldfish_pipe *pipe = filp->private_data;
 
+	DPRINT("%s: call. pipe=0x%lx file=0x%lx\n", __FUNCTION__, pipe, filp);
 	/* The guest is closing the channel, so tell the emulator right now */
 	goldfish_cmd(pipe, CMD_CLOSE);
 	kfree(pipe);
@@ -582,97 +557,33 @@
 	.release = goldfish_pipe_release,
 };
 
-static struct miscdevice goldfish_pipe_device = {
+static struct miscdevice goldfish_pipe_dev = {
 	.minor = MISC_DYNAMIC_MINOR,
 	.name = "goldfish_pipe",
 	.fops = &goldfish_pipe_fops,
 };
 
-static int goldfish_pipe_probe(struct platform_device *pdev)
+int goldfish_pipe_device_init_v1(struct platform_device *pdev)
 {
-	int err;
-	struct resource *r;
 	struct goldfish_pipe_dev *dev = pipe_dev;
-
-	/* not thread safe, but this should not happen */
-	WARN_ON(dev->base != NULL);
-
-	spin_lock_init(&dev->lock);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL || resource_size(r) < PAGE_SIZE) {
-		dev_err(&pdev->dev, "can't allocate i/o page\n");
-		return -EINVAL;
-	}
-	dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
-	if (dev->base == NULL) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		return -EINVAL;
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (r == NULL) {
-		err = -EINVAL;
-		goto error;
-	}
-	dev->irq = r->start;
-
-	err = devm_request_irq(&pdev->dev, dev->irq, goldfish_pipe_interrupt,
+	int err = devm_request_irq(&pdev->dev, dev->irq, goldfish_pipe_interrupt,
 				IRQF_SHARED, "goldfish_pipe", dev);
 	if (err) {
-		dev_err(&pdev->dev, "unable to allocate IRQ\n");
-		goto error;
+		dev_err(&pdev->dev, "unable to allocate IRQ for v1\n");
+		return err;
 	}
 
-	err = misc_register(&goldfish_pipe_device);
+	err = misc_register(&goldfish_pipe_dev);
 	if (err) {
-		dev_err(&pdev->dev, "unable to register device\n");
-		goto error;
+		dev_err(&pdev->dev, "unable to register v1 device\n");
+		return err;
 	}
+
 	setup_access_params_addr(pdev, dev);
-
-	/* Although the pipe device in the classic Android emulator does not
-	 * recognize the 'version' register, it won't treat this as an error
-	 * either and will simply return 0, which is fine.
-	 */
-	dev->version = readl(dev->base + PIPE_REG_VERSION);
 	return 0;
-
-error:
-	dev->base = NULL;
-	return err;
 }
 
-static int goldfish_pipe_remove(struct platform_device *pdev)
+void goldfish_pipe_device_deinit_v1(struct platform_device *pdev)
 {
-	struct goldfish_pipe_dev *dev = pipe_dev;
-	misc_deregister(&goldfish_pipe_device);
-	dev->base = NULL;
-	return 0;
+    misc_deregister(&goldfish_pipe_dev);
 }
-
-static const struct acpi_device_id goldfish_pipe_acpi_match[] = {
-	{ "GFSH0003", 0 },
-	{ },
-};
-MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match);
-
-static const struct of_device_id goldfish_pipe_of_match[] = {
-	{ .compatible = "google,android-pipe", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match);
-
-static struct platform_driver goldfish_pipe = {
-	.probe = goldfish_pipe_probe,
-	.remove = goldfish_pipe_remove,
-	.driver = {
-		.name = "goldfish_pipe",
-		.of_match_table = goldfish_pipe_of_match,
-		.acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match),
-	}
-};
-
-module_platform_driver(goldfish_pipe);
-MODULE_AUTHOR("David Turner <digit@google.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/platform/goldfish/goldfish_pipe.h b/drivers/platform/goldfish/goldfish_pipe.h
new file mode 100644
index 0000000..9b75a51
--- /dev/null
+++ b/drivers/platform/goldfish/goldfish_pipe.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef GOLDFISH_PIPE_H
+#define GOLDFISH_PIPE_H
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/goldfish.h>
+#include <linux/mm.h>
+#include <linux/acpi.h>
+
+
+/* Initialize the legacy version of the pipe device driver */
+int goldfish_pipe_device_init_v1(struct platform_device *pdev);
+
+/* Deinitialize the legacy version of the pipe device driver */
+void goldfish_pipe_device_deinit_v1(struct platform_device *pdev);
+
+/* Forward declarations for the device struct */
+struct goldfish_pipe;
+struct goldfish_pipe_device_buffers;
+
+/* The global driver data. Holds a reference to the i/o page used to
+ * communicate with the emulator, and a wake queue for blocked tasks
+ * waiting to be awoken.
+ */
+struct goldfish_pipe_dev {
+	/*
+	 * Global device spinlock. Protects the following members:
+	 *  - pipes, pipes_capacity
+	 *  - [*pipes, *pipes + pipes_capacity) - array data
+	 *  - first_signalled_pipe,
+	 *      goldfish_pipe::prev_signalled,
+	 *      goldfish_pipe::next_signalled,
+	 *      goldfish_pipe::signalled_flags - all singnalled-related fields,
+	 *                                       in all allocated pipes
+	 *  - open_command_params - PIPE_CMD_OPEN-related buffers
+	 *
+	 * It looks like a lot of different fields, but the trick is that the only
+	 * operation that happens often is the signalled pipes array manipulation.
+	 * That's why it's OK for now to keep the rest of the fields under the same
+	 * lock. If we notice too much contention because of PIPE_CMD_OPEN,
+	 * then we should add a separate lock there.
+	 */
+	spinlock_t lock;
+
+	/*
+	 * Array of the pipes of |pipes_capacity| elements,
+	 * indexed by goldfish_pipe::id
+	 */
+	struct goldfish_pipe **pipes;
+	u32 pipes_capacity;
+
+	/* Pointers to the buffers host uses for interaction with this driver */
+	struct goldfish_pipe_dev_buffers *buffers;
+
+	/* Head of a doubly linked list of signalled pipes */
+	struct goldfish_pipe *first_signalled_pipe;
+
+	/* Some device-specific data */
+	int irq;
+	int version;
+	unsigned char __iomem *base;
+
+	/* v1-specific access parameters */
+	struct access_params *aps;
+};
+
+extern struct goldfish_pipe_dev pipe_dev[1];
+
+#endif /* GOLDFISH_PIPE_H */
diff --git a/drivers/platform/goldfish/goldfish_pipe_v2.c b/drivers/platform/goldfish/goldfish_pipe_v2.c
new file mode 100644
index 0000000..ad373ed
--- /dev/null
+++ b/drivers/platform/goldfish/goldfish_pipe_v2.c
@@ -0,0 +1,889 @@
+/*
+ * Copyright (C) 2012 Intel, Inc.
+ * Copyright (C) 2013 Intel, Inc.
+ * Copyright (C) 2014 Linaro Limited
+ * Copyright (C) 2011-2016 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/* This source file contains the implementation of a special device driver
+ * that intends to provide a *very* fast communication channel between the
+ * guest system and the QEMU emulator.
+ *
+ * Usage from the guest is simply the following (error handling simplified):
+ *
+ *    int  fd = open("/dev/qemu_pipe",O_RDWR);
+ *    .... write() or read() through the pipe.
+ *
+ * This driver doesn't deal with the exact protocol used during the session.
+ * It is intended to be as simple as something like:
+ *
+ *    // do this _just_ after opening the fd to connect to a specific
+ *    // emulator service.
+ *    const char*  msg = "<pipename>";
+ *    if (write(fd, msg, strlen(msg)+1) < 0) {
+ *       ... could not connect to <pipename> service
+ *       close(fd);
+ *    }
+ *
+ *    // after this, simply read() and write() to communicate with the
+ *    // service. Exact protocol details left as an exercise to the reader.
+ *
+ * This driver is very fast because it doesn't copy any data through
+ * intermediate buffers, since the emulator is capable of translating
+ * guest user addresses into host ones.
+ *
+ * Note that we must however ensure that each user page involved in the
+ * exchange is properly mapped during a transfer.
+ */
+
+#include "goldfish_pipe.h"
+
+
+/*
+ * Update this when something changes in the driver's behavior so the host
+ * can benefit from knowing it
+ */
+enum {
+	PIPE_DRIVER_VERSION = 2,
+	PIPE_CURRENT_DEVICE_VERSION = 2
+};
+
+/*
+ * IMPORTANT: The following constants must match the ones used and defined
+ * in external/qemu/hw/goldfish_pipe.c in the Android source tree.
+ */
+
+/* List of bitflags returned in status of CMD_POLL command */
+enum PipePollFlags {
+	PIPE_POLL_IN	= 1 << 0,
+	PIPE_POLL_OUT	= 1 << 1,
+	PIPE_POLL_HUP	= 1 << 2
+};
+
+/* Possible status values used to signal errors - see goldfish_pipe_error_convert */
+enum PipeErrors {
+	PIPE_ERROR_INVAL  = -1,
+	PIPE_ERROR_AGAIN  = -2,
+	PIPE_ERROR_NOMEM  = -3,
+	PIPE_ERROR_IO     = -4
+};
+
+/* Bit-flags used to signal events from the emulator */
+enum PipeWakeFlags {
+	PIPE_WAKE_CLOSED = 1 << 0,  /* emulator closed pipe */
+	PIPE_WAKE_READ   = 1 << 1,  /* pipe can now be read from */
+	PIPE_WAKE_WRITE  = 1 << 2  /* pipe can now be written to */
+};
+
+/* Bit flags for the 'flags' field */
+enum PipeFlagsBits {
+	BIT_CLOSED_ON_HOST = 0,  /* pipe closed by host */
+	BIT_WAKE_ON_WRITE  = 1,  /* want to be woken on writes */
+	BIT_WAKE_ON_READ   = 2,  /* want to be woken on reads */
+};
+
+enum PipeRegs {
+	PIPE_REG_CMD = 0,
+
+	PIPE_REG_SIGNAL_BUFFER_HIGH = 4,
+	PIPE_REG_SIGNAL_BUFFER = 8,
+	PIPE_REG_SIGNAL_BUFFER_COUNT = 12,
+
+	PIPE_REG_OPEN_BUFFER_HIGH = 20,
+	PIPE_REG_OPEN_BUFFER = 24,
+
+	PIPE_REG_VERSION = 36,
+
+	PIPE_REG_GET_SIGNALLED = 48,
+};
+
+enum PipeCmdCode {
+	PIPE_CMD_OPEN = 1,	/* to be used by the pipe device itself */
+	PIPE_CMD_CLOSE,
+	PIPE_CMD_POLL,
+	PIPE_CMD_WRITE,
+	PIPE_CMD_WAKE_ON_WRITE,
+	PIPE_CMD_READ,
+	PIPE_CMD_WAKE_ON_READ,
+
+	/*
+	 * TODO(zyy): implement a deferred read/write execution to allow parallel
+	 *  processing of pipe operations on the host.
+	*/
+	PIPE_CMD_WAKE_ON_DONE_IO,
+};
+
+enum {
+	MAX_BUFFERS_PER_COMMAND = 336,
+	MAX_SIGNALLED_PIPES = 64,
+	INITIAL_PIPES_CAPACITY = 64
+};
+
+struct goldfish_pipe_dev;
+struct goldfish_pipe;
+struct goldfish_pipe_command;
+
+/* A per-pipe command structure, shared with the host */
+struct goldfish_pipe_command {
+	s32 cmd;		/* PipeCmdCode, guest -> host */
+	s32 id;			/* pipe id, guest -> host */
+	s32 status;		/* command execution status, host -> guest */
+	s32 reserved;	/* to pad to 64-bit boundary */
+	union {
+		/* Parameters for PIPE_CMD_{READ,WRITE} */
+		struct {
+			u32 buffers_count;					/* number of buffers, guest -> host */
+			s32 consumed_size;					/* number of consumed bytes, host -> guest */
+			u64 ptrs[MAX_BUFFERS_PER_COMMAND]; 	/* buffer pointers, guest -> host */
+			u32 sizes[MAX_BUFFERS_PER_COMMAND];	/* buffer sizes, guest -> host */
+		} rw_params;
+	};
+};
+
+/* A single signalled pipe information */
+struct signalled_pipe_buffer {
+	u32 id;
+	u32 flags;
+};
+
+/* Parameters for the PIPE_CMD_OPEN command */
+struct open_command_param {
+	u64 command_buffer_ptr;
+	u32 rw_params_max_count;
+};
+
+/* Device-level set of buffers shared with the host */
+struct goldfish_pipe_dev_buffers {
+	struct open_command_param open_command_params;
+	struct signalled_pipe_buffer signalled_pipe_buffers[MAX_SIGNALLED_PIPES];
+};
+
+/* This data type models a given pipe instance */
+struct goldfish_pipe {
+	u32 id;							/* pipe ID - index into goldfish_pipe_dev::pipes array */
+	unsigned long flags;			/* The wake flags pipe is waiting for
+									 * Note: not protected with any lock, uses atomic operations
+									 *  and barriers to make it thread-safe.
+									 */
+	unsigned long signalled_flags;	/* wake flags host have signalled,
+									 *  - protected by goldfish_pipe_dev::lock */
+
+	struct goldfish_pipe_command *command_buffer;	/* A pointer to command buffer */
+
+	/* doubly linked list of signalled pipes, protected by goldfish_pipe_dev::lock */
+	struct goldfish_pipe *prev_signalled;
+	struct goldfish_pipe *next_signalled;
+
+	/*
+	 * A pipe's own lock. Protects the following:
+	 *  - *command_buffer - makes sure a command can safely write its parameters
+	 *    to the host and read the results back.
+	 */
+	struct mutex lock;
+
+	wait_queue_head_t wake_queue;	/* A wake queue for sleeping until host signals an event */
+	struct goldfish_pipe_dev *dev;	/* Pointer to the parent goldfish_pipe_dev instance */
+};
+
+struct goldfish_pipe_dev pipe_dev[1] = {};
+
+static int goldfish_cmd_locked(struct goldfish_pipe *pipe, enum PipeCmdCode cmd)
+{
+	pipe->command_buffer->cmd = cmd;
+	pipe->command_buffer->status = PIPE_ERROR_INVAL;	/* failure by default */
+	writel(pipe->id, pipe->dev->base + PIPE_REG_CMD);
+	return pipe->command_buffer->status;
+}
+
+static int goldfish_cmd(struct goldfish_pipe *pipe, enum PipeCmdCode cmd)
+{
+	int status;
+	if (mutex_lock_interruptible(&pipe->lock))
+		return PIPE_ERROR_IO;
+	status = goldfish_cmd_locked(pipe, cmd);
+	mutex_unlock(&pipe->lock);
+	return status;
+}
+
+/*
+ * This function converts an error code returned by the emulator through
+ * the PIPE_REG_STATUS i/o register into a valid negative errno value.
+ */
+static int goldfish_pipe_error_convert(int status)
+{
+	switch (status) {
+	case PIPE_ERROR_AGAIN:
+		return -EAGAIN;
+	case PIPE_ERROR_NOMEM:
+		return -ENOMEM;
+	case PIPE_ERROR_IO:
+		return -EIO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int pin_user_pages(unsigned long first_page, unsigned long last_page,
+	unsigned last_page_size, int is_write,
+	struct page *pages[MAX_BUFFERS_PER_COMMAND], unsigned *iter_last_page_size)
+{
+	int ret;
+	int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1;
+	if (requested_pages > MAX_BUFFERS_PER_COMMAND) {
+		requested_pages = MAX_BUFFERS_PER_COMMAND;
+		*iter_last_page_size = PAGE_SIZE;
+	} else {
+		*iter_last_page_size = last_page_size;
+	}
+
+	ret = get_user_pages_fast(
+			first_page, requested_pages, !is_write, pages);
+	if (ret <= 0)
+		return -EFAULT;
+	if (ret < requested_pages)
+		*iter_last_page_size = PAGE_SIZE;
+	return ret;
+
+}
+
+static void release_user_pages(struct page **pages, int pages_count,
+	int is_write, s32 consumed_size)
+{
+	int i;
+	for (i = 0; i < pages_count; i++) {
+		if (!is_write && consumed_size > 0) {
+			set_page_dirty(pages[i]);
+		}
+		put_page(pages[i]);
+	}
+}
+
+/* Populate the call parameters, merging adjacent pages together */
+static void populate_rw_params(
+	struct page **pages, int pages_count,
+	unsigned long address, unsigned long address_end,
+	unsigned long first_page, unsigned long last_page,
+	unsigned iter_last_page_size, int is_write,
+	struct goldfish_pipe_command *command)
+{
+	/*
+	 * Process the first page separately - it's the only page that
+	 * needs special handling for its start address.
+	 */
+	unsigned long xaddr = page_to_phys(pages[0]);
+	unsigned long xaddr_prev = xaddr;
+	int buffer_idx = 0;
+	int i = 1;
+	int size_on_page = first_page == last_page
+			? (int)(address_end - address)
+			: (PAGE_SIZE - (address & ~PAGE_MASK));
+	command->rw_params.ptrs[0] = (u64)(xaddr | (address & ~PAGE_MASK));
+	command->rw_params.sizes[0] = size_on_page;
+	for (; i < pages_count; ++i) {
+		xaddr = page_to_phys(pages[i]);
+		size_on_page = (i == pages_count - 1) ? iter_last_page_size : PAGE_SIZE;
+		if (xaddr == xaddr_prev + PAGE_SIZE) {
+			command->rw_params.sizes[buffer_idx] += size_on_page;
+		} else {
+			++buffer_idx;
+			command->rw_params.ptrs[buffer_idx] = (u64)xaddr;
+			command->rw_params.sizes[buffer_idx] = size_on_page;
+		}
+		xaddr_prev = xaddr;
+	}
+	command->rw_params.buffers_count = buffer_idx + 1;
+}
+
+static int transfer_max_buffers(struct goldfish_pipe* pipe,
+	unsigned long address, unsigned long address_end, int is_write,
+	unsigned long last_page, unsigned int last_page_size,
+	s32* consumed_size, int* status)
+{
+	struct page *pages[MAX_BUFFERS_PER_COMMAND];
+	unsigned long first_page = address & PAGE_MASK;
+	unsigned int iter_last_page_size;
+	int pages_count = pin_user_pages(first_page, last_page,
+			last_page_size, is_write,
+			pages, &iter_last_page_size);
+	if (pages_count < 0)
+		return pages_count;
+
+	/* Serialize access to the pipe command buffers */
+	if (mutex_lock_interruptible(&pipe->lock))
+		return -ERESTARTSYS;
+
+	populate_rw_params(pages, pages_count, address, address_end,
+		first_page, last_page, iter_last_page_size, is_write,
+		pipe->command_buffer);
+
+	/* Transfer the data */
+	*status = goldfish_cmd_locked(pipe,
+						is_write ? PIPE_CMD_WRITE : PIPE_CMD_READ);
+
+	*consumed_size = pipe->command_buffer->rw_params.consumed_size;
+
+	mutex_unlock(&pipe->lock);
+
+	release_user_pages(pages, pages_count, is_write, *consumed_size);
+
+	return 0;
+}
+
+static int wait_for_host_signal(struct goldfish_pipe *pipe, int is_write)
+{
+	u32 wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ;
+	set_bit(wakeBit, &pipe->flags);
+
+	/* Tell the emulator we're going to wait for a wake event */
+	(void)goldfish_cmd(pipe,
+			is_write ? PIPE_CMD_WAKE_ON_WRITE : PIPE_CMD_WAKE_ON_READ);
+
+	while (test_bit(wakeBit, &pipe->flags)) {
+		if (wait_event_interruptible(
+				pipe->wake_queue,
+				!test_bit(wakeBit, &pipe->flags)))
+			return -ERESTARTSYS;
+
+		if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))
+			return -EIO;
+	}
+
+	return 0;
+}
+
+static ssize_t goldfish_pipe_read_write(struct file *filp,
+	char __user *buffer, size_t bufflen, int is_write)
+{
+	struct goldfish_pipe *pipe = filp->private_data;
+	int count = 0, ret = -EINVAL;
+	unsigned long address, address_end, last_page;
+	unsigned int last_page_size;
+
+	/* If the emulator already closed the pipe, no need to go further */
+	if (unlikely(test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)))
+		return -EIO;
+	/* Null reads or writes succeeds */
+	if (unlikely(bufflen == 0))
+		return 0;
+	/* Check the buffer range for access */
+	if (unlikely(!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ,
+			buffer, bufflen)))
+		return -EFAULT;
+
+	address = (unsigned long)buffer;
+	address_end = address + bufflen;
+	last_page = (address_end - 1) & PAGE_MASK;
+	last_page_size = ((address_end - 1) & ~PAGE_MASK) + 1;
+
+	while (address < address_end) {
+		s32 consumed_size;
+		int status;
+		ret = transfer_max_buffers(pipe, address, address_end, is_write,
+				last_page, last_page_size, &consumed_size, &status);
+		if (ret < 0)
+			break;
+
+		if (consumed_size > 0) {
+			/* No matter what's the status, we've transfered something */
+			count += consumed_size;
+			address += consumed_size;
+		}
+		if (status > 0)
+			continue;
+		if (status == 0) {
+			/* EOF */
+			ret = 0;
+			break;
+		}
+		if (count > 0) {
+			/*
+			 * An error occured, but we already transfered
+			 * something on one of the previous iterations.
+			 * Just return what we already copied and log this
+			 * err.
+			 */
+			if (status != PIPE_ERROR_AGAIN)
+				pr_info_ratelimited("goldfish_pipe: backend error %d on %s\n",
+									status, is_write ? "write" : "read");
+			break;
+		}
+
+		/*
+		 * If the error is not PIPE_ERROR_AGAIN, or if we are in
+		 * non-blocking mode, just return the error code.
+		 */
+		if (status != PIPE_ERROR_AGAIN || (filp->f_flags & O_NONBLOCK) != 0) {
+			ret = goldfish_pipe_error_convert(status);
+			break;
+		}
+
+		status = wait_for_host_signal(pipe, is_write);
+		if (status < 0)
+			return status;
+	}
+
+	if (count > 0)
+		return count;
+	return ret;
+}
+
+static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer,
+				size_t bufflen, loff_t *ppos)
+{
+	return goldfish_pipe_read_write(filp, buffer, bufflen, /* is_write */ 0);
+}
+
+static ssize_t goldfish_pipe_write(struct file *filp,
+				const char __user *buffer, size_t bufflen,
+				loff_t *ppos)
+{
+	return goldfish_pipe_read_write(filp,
+			/* cast away the const */(char __user *)buffer, bufflen,
+			/* is_write */ 1);
+}
+
+static unsigned int goldfish_pipe_poll(struct file *filp, poll_table *wait)
+{
+	struct goldfish_pipe *pipe = filp->private_data;
+	unsigned int mask = 0;
+	int status;
+
+	poll_wait(filp, &pipe->wake_queue, wait);
+
+	status = goldfish_cmd(pipe, PIPE_CMD_POLL);
+	if (status < 0) {
+		return -ERESTARTSYS;
+	}
+
+	if (status & PIPE_POLL_IN)
+		mask |= POLLIN | POLLRDNORM;
+	if (status & PIPE_POLL_OUT)
+		mask |= POLLOUT | POLLWRNORM;
+	if (status & PIPE_POLL_HUP)
+		mask |= POLLHUP;
+	if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))
+		mask |= POLLERR;
+
+	return mask;
+}
+
+static void signalled_pipes_add_locked(struct goldfish_pipe_dev *dev,
+	u32 id, u32 flags)
+{
+	struct goldfish_pipe *pipe;
+
+	BUG_ON(id >= dev->pipes_capacity);
+
+	pipe = dev->pipes[id];
+	if (!pipe)
+		return;
+	pipe->signalled_flags |= flags;
+
+	if (pipe->prev_signalled || pipe->next_signalled
+		|| dev->first_signalled_pipe == pipe)
+		return;	/* already in the list */
+	pipe->next_signalled = dev->first_signalled_pipe;
+	if (dev->first_signalled_pipe) {
+		dev->first_signalled_pipe->prev_signalled = pipe;
+	}
+	dev->first_signalled_pipe = pipe;
+}
+
+static void signalled_pipes_remove_locked(struct goldfish_pipe_dev *dev,
+	struct goldfish_pipe *pipe) {
+	if (pipe->prev_signalled)
+		pipe->prev_signalled->next_signalled = pipe->next_signalled;
+	if (pipe->next_signalled)
+		pipe->next_signalled->prev_signalled = pipe->prev_signalled;
+	if (pipe == dev->first_signalled_pipe)
+		dev->first_signalled_pipe = pipe->next_signalled;
+	pipe->prev_signalled = NULL;
+	pipe->next_signalled = NULL;
+}
+
+static struct goldfish_pipe *signalled_pipes_pop_front(struct goldfish_pipe_dev *dev,
+		int *wakes)
+{
+	struct goldfish_pipe *pipe;
+	unsigned long flags;
+	spin_lock_irqsave(&dev->lock, flags);
+
+	pipe = dev->first_signalled_pipe;
+	if (pipe) {
+		*wakes = pipe->signalled_flags;
+		pipe->signalled_flags = 0;
+		/*
+		 * This is an optimized version of signalled_pipes_remove_locked() -
+		 * we want to make it as fast as possible to wake the sleeping pipe
+		 * operations faster
+		 */
+		dev->first_signalled_pipe = pipe->next_signalled;
+		if (dev->first_signalled_pipe)
+			dev->first_signalled_pipe->prev_signalled = NULL;
+		pipe->next_signalled = NULL;
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return pipe;
+}
+
+static void goldfish_interrupt_task(unsigned long unused)
+{
+	struct goldfish_pipe_dev *dev = pipe_dev;
+	/* Iterate over the signalled pipes and wake them one by one */
+	struct goldfish_pipe *pipe;
+	int wakes;
+	while ((pipe = signalled_pipes_pop_front(dev, &wakes)) != NULL) {
+		if (wakes & PIPE_WAKE_CLOSED) {
+			pipe->flags = 1 << BIT_CLOSED_ON_HOST;
+		} else {
+			if (wakes & PIPE_WAKE_READ)
+				clear_bit(BIT_WAKE_ON_READ, &pipe->flags);
+			if (wakes & PIPE_WAKE_WRITE)
+				clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags);
+		}
+		/*
+		 * wake_up_interruptible() implies a write barrier, so don't explicitly
+		 * add another one here.
+		 */
+		wake_up_interruptible(&pipe->wake_queue);
+	}
+}
+DECLARE_TASKLET(goldfish_interrupt_tasklet, goldfish_interrupt_task, 0);
+
+/*
+ * The general idea of the interrupt handling:
+ *
+ *  1. device raises an interrupt if there's at least one signalled pipe
+ *  2. IRQ handler reads the signalled pipes and their count from the device
+ *  3. device writes them into a shared buffer and returns the count
+ *      it only resets the IRQ if it has returned all signalled pipes,
+ *      otherwise it leaves it raised, so IRQ handler will be called
+ *      again for the next chunk
+ *  4. IRQ handler adds all returned pipes to the device's signalled pipes list
+ *  5. IRQ handler launches a tasklet to process the signalled pipes from the
+ *      list in a separate context
+ */
+static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id)
+{
+	u32 count;
+	u32 i;
+	unsigned long flags;
+	struct goldfish_pipe_dev *dev = dev_id;
+	if (dev != pipe_dev)
+		return IRQ_NONE;
+
+	/* Request the signalled pipes from the device */
+	spin_lock_irqsave(&dev->lock, flags);
+
+	count = readl(dev->base + PIPE_REG_GET_SIGNALLED);
+	if (count == 0) {
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return IRQ_NONE;
+	}
+	if (count > MAX_SIGNALLED_PIPES)
+		count = MAX_SIGNALLED_PIPES;
+
+	for (i = 0; i < count; ++i)
+		signalled_pipes_add_locked(dev,
+			dev->buffers->signalled_pipe_buffers[i].id,
+			dev->buffers->signalled_pipe_buffers[i].flags);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	tasklet_schedule(&goldfish_interrupt_tasklet);
+	return IRQ_HANDLED;
+}
+
+static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev)
+{
+	int id;
+	for (id = 0; id < dev->pipes_capacity; ++id)
+		if (!dev->pipes[id])
+			return id;
+
+	{
+		/* Reallocate the array */
+		u32 new_capacity = 2 * dev->pipes_capacity;
+		struct goldfish_pipe **pipes =
+				kcalloc(new_capacity, sizeof(*pipes),
+					GFP_ATOMIC);
+		if (!pipes)
+			return -ENOMEM;
+		memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity);
+		kfree(dev->pipes);
+		dev->pipes = pipes;
+		id = dev->pipes_capacity;
+		dev->pipes_capacity = new_capacity;
+	}
+	return id;
+}
+
+/**
+ *	goldfish_pipe_open - open a channel to the AVD
+ *	@inode: inode of device
+ *	@file: file struct of opener
+ *
+ *	Create a new pipe link between the emulator and the use application.
+ *	Each new request produces a new pipe.
+ *
+ *	Note: we use the pipe ID as a mux. All goldfish emulations are 32bit
+ *	right now so this is fine. A move to 64bit will need this addressing
+ */
+static int goldfish_pipe_open(struct inode *inode, struct file *file)
+{
+	struct goldfish_pipe_dev *dev = pipe_dev;
+	unsigned long flags;
+	int id;
+	int status;
+
+	/* Allocate new pipe kernel object */
+	struct goldfish_pipe *pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
+	if (pipe == NULL)
+		return -ENOMEM;
+
+	pipe->dev = dev;
+	mutex_init(&pipe->lock);
+	init_waitqueue_head(&pipe->wake_queue);
+
+	/*
+	 * Command buffer needs to be allocated on its own page to make sure it is
+	 * physically contiguous in host's address space.
+	 */
+	pipe->command_buffer =
+			(struct goldfish_pipe_command*)__get_free_page(GFP_KERNEL);
+	if (!pipe->command_buffer) {
+		status = -ENOMEM;
+		goto err_pipe;
+	}
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	id = get_free_pipe_id_locked(dev);
+	if (id < 0) {
+		status = id;
+		goto err_id_locked;
+	}
+
+	dev->pipes[id] = pipe;
+	pipe->id = id;
+	pipe->command_buffer->id = id;
+
+	/* Now tell the emulator we're opening a new pipe. */
+	dev->buffers->open_command_params.rw_params_max_count =
+			MAX_BUFFERS_PER_COMMAND;
+	dev->buffers->open_command_params.command_buffer_ptr =
+			(u64)(unsigned long)__pa(pipe->command_buffer);
+	status = goldfish_cmd_locked(pipe, PIPE_CMD_OPEN);
+	spin_unlock_irqrestore(&dev->lock, flags);
+	if (status < 0)
+		goto err_cmd;
+	/* All is done, save the pipe into the file's private data field */
+	file->private_data = pipe;
+	return 0;
+
+err_cmd:
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->pipes[id] = NULL;
+err_id_locked:
+	spin_unlock_irqrestore(&dev->lock, flags);
+	free_page((unsigned long)pipe->command_buffer);
+err_pipe:
+	kfree(pipe);
+	return status;
+}
+
+static int goldfish_pipe_release(struct inode *inode, struct file *filp)
+{
+	unsigned long flags;
+	struct goldfish_pipe *pipe = filp->private_data;
+	struct goldfish_pipe_dev *dev = pipe->dev;
+
+	/* The guest is closing the channel, so tell the emulator right now */
+	(void)goldfish_cmd(pipe, PIPE_CMD_CLOSE);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->pipes[pipe->id] = NULL;
+	signalled_pipes_remove_locked(dev, pipe);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	filp->private_data = NULL;
+	free_page((unsigned long)pipe->command_buffer);
+	kfree(pipe);
+	return 0;
+}
+
+static const struct file_operations goldfish_pipe_fops = {
+	.owner = THIS_MODULE,
+	.read = goldfish_pipe_read,
+	.write = goldfish_pipe_write,
+	.poll = goldfish_pipe_poll,
+	.open = goldfish_pipe_open,
+	.release = goldfish_pipe_release,
+};
+
+static struct miscdevice goldfish_pipe_dev = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "goldfish_pipe",
+	.fops = &goldfish_pipe_fops,
+};
+
+static int goldfish_pipe_device_init_v2(struct platform_device *pdev)
+{
+	char *page;
+	struct goldfish_pipe_dev *dev = pipe_dev;
+	int err = devm_request_irq(&pdev->dev, dev->irq, goldfish_pipe_interrupt,
+				IRQF_SHARED, "goldfish_pipe", dev);
+	if (err) {
+		dev_err(&pdev->dev, "unable to allocate IRQ for v2\n");
+		return err;
+	}
+
+	err = misc_register(&goldfish_pipe_dev);
+	if (err) {
+		dev_err(&pdev->dev, "unable to register v2 device\n");
+		return err;
+	}
+
+	dev->first_signalled_pipe = NULL;
+	dev->pipes_capacity = INITIAL_PIPES_CAPACITY;
+	dev->pipes = kcalloc(dev->pipes_capacity, sizeof(*dev->pipes), GFP_KERNEL);
+	if (!dev->pipes)
+		return -ENOMEM;
+
+	/*
+	 * We're going to pass two buffers, open_command_params and
+	 * signalled_pipe_buffers, to the host. This means each of those buffers
+	 * needs to be contained in a single physical page. The easiest choice is
+	 * to just allocate a page and place the buffers in it.
+	 */
+	BUG_ON(sizeof(*dev->buffers) > PAGE_SIZE);
+	page = (char*)__get_free_page(GFP_KERNEL);
+	if (!page) {
+		kfree(dev->pipes);
+		return -ENOMEM;
+	}
+	dev->buffers = (struct goldfish_pipe_dev_buffers*)page;
+
+	/* Send the buffer addresses to the host */
+	{
+		u64 paddr = __pa(&dev->buffers->signalled_pipe_buffers);
+		writel((u32)(unsigned long)(paddr >> 32), dev->base + PIPE_REG_SIGNAL_BUFFER_HIGH);
+		writel((u32)(unsigned long)paddr, dev->base + PIPE_REG_SIGNAL_BUFFER);
+		writel((u32)MAX_SIGNALLED_PIPES, dev->base + PIPE_REG_SIGNAL_BUFFER_COUNT);
+
+		paddr = __pa(&dev->buffers->open_command_params);
+		writel((u32)(unsigned long)(paddr >> 32), dev->base + PIPE_REG_OPEN_BUFFER_HIGH);
+		writel((u32)(unsigned long)paddr, dev->base + PIPE_REG_OPEN_BUFFER);
+	}
+	return 0;
+}
+
+static void goldfish_pipe_device_deinit_v2(struct platform_device *pdev) {
+	struct goldfish_pipe_dev *dev = pipe_dev;
+	misc_deregister(&goldfish_pipe_dev);
+	kfree(dev->pipes);
+	free_page((unsigned long)dev->buffers);
+}
+
+static int goldfish_pipe_probe(struct platform_device *pdev)
+{
+	int err;
+	struct resource *r;
+	struct goldfish_pipe_dev *dev = pipe_dev;
+
+	BUG_ON(sizeof(struct goldfish_pipe_command) > PAGE_SIZE);
+
+	/* not thread safe, but this should not happen */
+	WARN_ON(dev->base != NULL);
+
+	spin_lock_init(&dev->lock);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL || resource_size(r) < PAGE_SIZE) {
+		dev_err(&pdev->dev, "can't allocate i/o page\n");
+		return -EINVAL;
+	}
+	dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
+	if (dev->base == NULL) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		return -EINVAL;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (r == NULL) {
+		err = -EINVAL;
+		goto error;
+	}
+	dev->irq = r->start;
+
+	/*
+	 * Exchange the versions with the host device
+	 *
+	 * Note: v1 driver used to not report its version, so we write it before
+	 *  reading device version back: this allows the host implementation to
+	 *  detect the old driver (if there was no version write before read).
+	 */
+	writel((u32)PIPE_DRIVER_VERSION, dev->base + PIPE_REG_VERSION);
+	dev->version = readl(dev->base + PIPE_REG_VERSION);
+	if (dev->version < PIPE_CURRENT_DEVICE_VERSION) {
+		/* initialize the old device version */
+		err = goldfish_pipe_device_init_v1(pdev);
+	} else {
+		/* Host device supports the new interface */
+		err = goldfish_pipe_device_init_v2(pdev);
+	}
+	if (!err)
+		return 0;
+
+error:
+	dev->base = NULL;
+	return err;
+}
+
+static int goldfish_pipe_remove(struct platform_device *pdev)
+{
+	struct goldfish_pipe_dev *dev = pipe_dev;
+	if (dev->version < PIPE_CURRENT_DEVICE_VERSION)
+		goldfish_pipe_device_deinit_v1(pdev);
+	else
+		goldfish_pipe_device_deinit_v2(pdev);
+	dev->base = NULL;
+	return 0;
+}
+
+static const struct acpi_device_id goldfish_pipe_acpi_match[] = {
+	{ "GFSH0003", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match);
+
+static const struct of_device_id goldfish_pipe_of_match[] = {
+	{ .compatible = "google,android-pipe", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match);
+
+static struct platform_driver goldfish_pipe_driver = {
+	.probe = goldfish_pipe_probe,
+	.remove = goldfish_pipe_remove,
+	.driver = {
+		.name = "goldfish_pipe",
+		.of_match_table = goldfish_pipe_of_match,
+		.acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match),
+	}
+};
+
+module_platform_driver(goldfish_pipe_driver);
+MODULE_AUTHOR("David Turner <digit@google.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/goldfish/pdev_bus.c b/drivers/platform/goldfish/pdev_bus.c
index 1f52462..dd9ea46 100644
--- a/drivers/platform/goldfish/pdev_bus.c
+++ b/drivers/platform/goldfish/pdev_bus.c
@@ -157,23 +157,26 @@
 static irqreturn_t goldfish_pdev_bus_interrupt(int irq, void *dev_id)
 {
 	irqreturn_t ret = IRQ_NONE;
+
 	while (1) {
 		u32 op = readl(pdev_bus_base + PDEV_BUS_OP);
-		switch (op) {
-		case PDEV_BUS_OP_DONE:
-			return IRQ_NONE;
 
+		switch (op) {
 		case PDEV_BUS_OP_REMOVE_DEV:
 			goldfish_pdev_remove();
+			ret = IRQ_HANDLED;
 			break;
 
 		case PDEV_BUS_OP_ADD_DEV:
 			goldfish_new_pdev();
+			ret = IRQ_HANDLED;
 			break;
+
+		case PDEV_BUS_OP_DONE:
+		default:
+			return ret;
 		}
-		ret = IRQ_HANDLED;
 	}
-	return ret;
 }
 
 static int goldfish_pdev_bus_probe(struct platform_device *pdev)
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 1062fa4..b2cdc1a 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1816,11 +1816,24 @@
 	return status;
 }
 
+#define ACER_WMID_ACCEL_HID	"BST0001"
+
 static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level,
 						void *ctx, void **retval)
 {
+	struct acpi_device *dev;
+
+	if (!strcmp(ctx, "SENR")) {
+		if (acpi_bus_get_device(ah, &dev))
+			return AE_OK;
+		if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev)))
+			return AE_OK;
+	} else
+		return AE_OK;
+
 	*(acpi_handle *)retval = ah;
-	return AE_OK;
+
+	return AE_CTRL_TERMINATE;
 }
 
 static int __init acer_wmi_get_handle(const char *name, const char *prop,
@@ -1847,7 +1860,7 @@
 {
 	int err;
 
-	err = acer_wmi_get_handle("SENR", "BST0001", &gsensor_handle);
+	err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, &gsensor_handle);
 	if (err)
 		return err;
 
@@ -2185,10 +2198,11 @@
 		err = acer_wmi_input_setup();
 		if (err)
 			return err;
+		err = acer_wmi_accel_setup();
+		if (err)
+			return err;
 	}
 
-	acer_wmi_accel_setup();
-
 	err = platform_driver_register(&acer_platform_driver);
 	if (err) {
 		pr_err("Unable to register platform driver\n");
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 131fee2..a3661cc 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -128,6 +128,15 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. X45U",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X45U"),
+		},
+		.driver_data = &quirk_asus_wapf4,
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "ASUSTeK COMPUTER INC. X456UA",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
diff --git a/drivers/platform/x86/dell-rbtn.c b/drivers/platform/x86/dell-rbtn.c
index cd410e3..d33e9ad 100644
--- a/drivers/platform/x86/dell-rbtn.c
+++ b/drivers/platform/x86/dell-rbtn.c
@@ -28,6 +28,7 @@
 	enum rbtn_type type;
 	struct rfkill *rfkill;
 	struct input_dev *input_dev;
+	bool suspended;
 };
 
 
@@ -220,9 +221,55 @@
 	{ "", 0 },
 };
 
+#ifdef CONFIG_PM_SLEEP
+static void ACPI_SYSTEM_XFACE rbtn_clear_suspended_flag(void *context)
+{
+	struct rbtn_data *rbtn_data = context;
+
+	rbtn_data->suspended = false;
+}
+
+static int rbtn_suspend(struct device *dev)
+{
+	struct acpi_device *device = to_acpi_device(dev);
+	struct rbtn_data *rbtn_data = acpi_driver_data(device);
+
+	rbtn_data->suspended = true;
+
+	return 0;
+}
+
+static int rbtn_resume(struct device *dev)
+{
+	struct acpi_device *device = to_acpi_device(dev);
+	struct rbtn_data *rbtn_data = acpi_driver_data(device);
+	acpi_status status;
+
+	/*
+	 * Upon resume, some BIOSes send an ACPI notification thet triggers
+	 * an unwanted input event. In order to ignore it, we use a flag
+	 * that we set at suspend and clear once we have received the extra
+	 * ACPI notification. Since ACPI notifications are delivered
+	 * asynchronously to drivers, we clear the flag from the workqueue
+	 * used to deliver the notifications. This should be enough
+	 * to have the flag cleared only after we received the extra
+	 * notification, if any.
+	 */
+	status = acpi_os_execute(OSL_NOTIFY_HANDLER,
+			 rbtn_clear_suspended_flag, rbtn_data);
+	if (ACPI_FAILURE(status))
+		rbtn_clear_suspended_flag(rbtn_data);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(rbtn_pm_ops, rbtn_suspend, rbtn_resume);
+
 static struct acpi_driver rbtn_driver = {
 	.name = "dell-rbtn",
 	.ids = rbtn_ids,
+	.drv.pm = &rbtn_pm_ops,
 	.ops = {
 		.add = rbtn_add,
 		.remove = rbtn_remove,
@@ -384,6 +431,15 @@
 {
 	struct rbtn_data *rbtn_data = device->driver_data;
 
+	/*
+	 * Some BIOSes send a notification at resume.
+	 * Ignore it to prevent unwanted input events.
+	 */
+	if (rbtn_data->suspended) {
+		dev_dbg(&device->dev, "ACPI notification ignored\n");
+		return;
+	}
+
 	if (event != 0x80) {
 		dev_info(&device->dev, "Received unknown event (0x%x)\n",
 			 event);
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index fb4dd7b..af2046c 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -723,6 +723,11 @@
 	if (err)
 		return err;
 
+	err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, &wireless,
+				   sizeof(wireless), 0);
+	if (err)
+		return err;
+
 	if (wireless & 0x1) {
 		wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
 					   RFKILL_TYPE_WLAN,
@@ -910,7 +915,7 @@
 	gps_rfkill = NULL;
 	rfkill2_count = 0;
 
-	if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device))
+	if (hp_wmi_rfkill_setup(device))
 		hp_wmi_rfkill2_setup(device);
 
 	err = device_create_file(&device->dev, &dev_attr_display);
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index be3bc2f..09cc64b 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -807,6 +807,7 @@
 			case 11:
 			case 7:
 			case 6:
+			case 1:
 				ideapad_input_report(priv, vpc_bit);
 				break;
 			case 5:
diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c
index 1fc0de8..3617705 100644
--- a/drivers/platform/x86/intel_mid_powerbtn.c
+++ b/drivers/platform/x86/intel_mid_powerbtn.c
@@ -77,7 +77,7 @@
 
 	input_set_capability(input, EV_KEY, KEY_POWER);
 
-	error = request_threaded_irq(irq, NULL, mfld_pb_isr, 0,
+	error = request_threaded_irq(irq, NULL, mfld_pb_isr, IRQF_ONESHOT,
 				     DRIVER_NAME, input);
 	if (error) {
 		dev_err(&pdev->dev, "Unable to request irq %d for mfld power"
diff --git a/drivers/platform/x86/toshiba-wmi.c b/drivers/platform/x86/toshiba-wmi.c
index feac457..2df07ee 100644
--- a/drivers/platform/x86/toshiba-wmi.c
+++ b/drivers/platform/x86/toshiba-wmi.c
@@ -24,14 +24,15 @@
 #include <linux/acpi.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
+#include <linux/dmi.h>
 
 MODULE_AUTHOR("Azael Avalos");
 MODULE_DESCRIPTION("Toshiba WMI Hotkey Driver");
 MODULE_LICENSE("GPL");
 
-#define TOSHIBA_WMI_EVENT_GUID	"59142400-C6A3-40FA-BADB-8A2652834100"
+#define WMI_EVENT_GUID	"59142400-C6A3-40FA-BADB-8A2652834100"
 
-MODULE_ALIAS("wmi:"TOSHIBA_WMI_EVENT_GUID);
+MODULE_ALIAS("wmi:"WMI_EVENT_GUID);
 
 static struct input_dev *toshiba_wmi_input_dev;
 
@@ -63,6 +64,16 @@
 	kfree(response.pointer);
 }
 
+static struct dmi_system_id toshiba_wmi_dmi_table[] __initdata = {
+	{
+		.ident = "Toshiba laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		},
+	},
+	{}
+};
+
 static int __init toshiba_wmi_input_setup(void)
 {
 	acpi_status status;
@@ -81,7 +92,7 @@
 	if (err)
 		goto err_free_dev;
 
-	status = wmi_install_notify_handler(TOSHIBA_WMI_EVENT_GUID,
+	status = wmi_install_notify_handler(WMI_EVENT_GUID,
 					    toshiba_wmi_notify, NULL);
 	if (ACPI_FAILURE(status)) {
 		err = -EIO;
@@ -95,7 +106,7 @@
 	return 0;
 
  err_remove_notifier:
-	wmi_remove_notify_handler(TOSHIBA_WMI_EVENT_GUID);
+	wmi_remove_notify_handler(WMI_EVENT_GUID);
  err_free_keymap:
 	sparse_keymap_free(toshiba_wmi_input_dev);
  err_free_dev:
@@ -105,7 +116,7 @@
 
 static void toshiba_wmi_input_destroy(void)
 {
-	wmi_remove_notify_handler(TOSHIBA_WMI_EVENT_GUID);
+	wmi_remove_notify_handler(WMI_EVENT_GUID);
 	sparse_keymap_free(toshiba_wmi_input_dev);
 	input_unregister_device(toshiba_wmi_input_dev);
 }
@@ -114,7 +125,8 @@
 {
 	int ret;
 
-	if (!wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
+	if (!wmi_has_guid(WMI_EVENT_GUID) ||
+	    !dmi_check_system(toshiba_wmi_dmi_table))
 		return -ENODEV;
 
 	ret = toshiba_wmi_input_setup();
@@ -130,7 +142,7 @@
 
 static void __exit toshiba_wmi_exit(void)
 {
-	if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
+	if (wmi_has_guid(WMI_EVENT_GUID))
 		toshiba_wmi_input_destroy();
 }
 
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 943c1cb..d28e3ab 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -342,7 +342,9 @@
 /* Device IDs of parts that have 32KB MCH space */
 static const unsigned int mch_quirk_devices[] = {
 	0x0154,	/* Ivy Bridge */
+	0x0a04, /* Haswell-ULT */
 	0x0c00,	/* Haswell */
+	0x1604, /* Broadwell */
 };
 
 static struct pci_dev *get_intel_host(void)
diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c
index f5746b9..f05d277 100644
--- a/drivers/power/bq24190_charger.c
+++ b/drivers/power/bq24190_charger.c
@@ -144,10 +144,7 @@
  * so the first read after a fault returns the latched value and subsequent
  * reads return the current value.  In order to return the fault status
  * to the user, have the interrupt handler save the reg's value and retrieve
- * it in the appropriate health/status routine.  Each routine has its own
- * flag indicating whether it should use the value stored by the last run
- * of the interrupt handler or do an actual reg read.  That way each routine
- * can report back whatever fault may have occured.
+ * it in the appropriate health/status routine.
  */
 struct bq24190_dev_info {
 	struct i2c_client		*client;
@@ -159,10 +156,6 @@
 	unsigned int			gpio_int;
 	unsigned int			irq;
 	struct mutex			f_reg_lock;
-	bool				first_time;
-	bool				charger_health_valid;
-	bool				battery_health_valid;
-	bool				battery_status_valid;
 	u8				f_reg;
 	u8				ss_reg;
 	u8				watchdog;
@@ -636,21 +629,11 @@
 		union power_supply_propval *val)
 {
 	u8 v;
-	int health, ret;
+	int health;
 
 	mutex_lock(&bdi->f_reg_lock);
-
-	if (bdi->charger_health_valid) {
-		v = bdi->f_reg;
-		bdi->charger_health_valid = false;
-		mutex_unlock(&bdi->f_reg_lock);
-	} else {
-		mutex_unlock(&bdi->f_reg_lock);
-
-		ret = bq24190_read(bdi, BQ24190_REG_F, &v);
-		if (ret < 0)
-			return ret;
-	}
+	v = bdi->f_reg;
+	mutex_unlock(&bdi->f_reg_lock);
 
 	if (v & BQ24190_REG_F_BOOST_FAULT_MASK) {
 		/*
@@ -937,18 +920,8 @@
 	int status, ret;
 
 	mutex_lock(&bdi->f_reg_lock);
-
-	if (bdi->battery_status_valid) {
-		chrg_fault = bdi->f_reg;
-		bdi->battery_status_valid = false;
-		mutex_unlock(&bdi->f_reg_lock);
-	} else {
-		mutex_unlock(&bdi->f_reg_lock);
-
-		ret = bq24190_read(bdi, BQ24190_REG_F, &chrg_fault);
-		if (ret < 0)
-			return ret;
-	}
+	chrg_fault = bdi->f_reg;
+	mutex_unlock(&bdi->f_reg_lock);
 
 	chrg_fault &= BQ24190_REG_F_CHRG_FAULT_MASK;
 	chrg_fault >>= BQ24190_REG_F_CHRG_FAULT_SHIFT;
@@ -996,21 +969,11 @@
 		union power_supply_propval *val)
 {
 	u8 v;
-	int health, ret;
+	int health;
 
 	mutex_lock(&bdi->f_reg_lock);
-
-	if (bdi->battery_health_valid) {
-		v = bdi->f_reg;
-		bdi->battery_health_valid = false;
-		mutex_unlock(&bdi->f_reg_lock);
-	} else {
-		mutex_unlock(&bdi->f_reg_lock);
-
-		ret = bq24190_read(bdi, BQ24190_REG_F, &v);
-		if (ret < 0)
-			return ret;
-	}
+	v = bdi->f_reg;
+	mutex_unlock(&bdi->f_reg_lock);
 
 	if (v & BQ24190_REG_F_BAT_FAULT_MASK) {
 		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
@@ -1197,9 +1160,12 @@
 static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
 {
 	struct bq24190_dev_info *bdi = data;
-	bool alert_userspace = false;
+	const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK;
+	const u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK
+				| BQ24190_REG_F_NTC_FAULT_MASK;
+	bool alert_charger = false, alert_battery = false;
 	u8 ss_reg = 0, f_reg = 0;
-	int ret;
+	int i, ret;
 
 	pm_runtime_get_sync(bdi->dev);
 
@@ -1209,6 +1175,32 @@
 		goto out;
 	}
 
+	i = 0;
+	do {
+		ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg);
+		if (ret < 0) {
+			dev_err(bdi->dev, "Can't read F reg: %d\n", ret);
+			goto out;
+		}
+	} while (f_reg && ++i < 2);
+
+	if (f_reg != bdi->f_reg) {
+		dev_info(bdi->dev,
+			"Fault: boost %d, charge %d, battery %d, ntc %d\n",
+			!!(f_reg & BQ24190_REG_F_BOOST_FAULT_MASK),
+			!!(f_reg & BQ24190_REG_F_CHRG_FAULT_MASK),
+			!!(f_reg & BQ24190_REG_F_BAT_FAULT_MASK),
+			!!(f_reg & BQ24190_REG_F_NTC_FAULT_MASK));
+
+		mutex_lock(&bdi->f_reg_lock);
+		if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f))
+			alert_battery = true;
+		if ((bdi->f_reg & ~battery_mask_f) != (f_reg & ~battery_mask_f))
+			alert_charger = true;
+		bdi->f_reg = f_reg;
+		mutex_unlock(&bdi->f_reg_lock);
+	}
+
 	if (ss_reg != bdi->ss_reg) {
 		/*
 		 * The device is in host mode so when PG_STAT goes from 1->0
@@ -1225,47 +1217,17 @@
 					ret);
 		}
 
+		if ((bdi->ss_reg & battery_mask_ss) != (ss_reg & battery_mask_ss))
+			alert_battery = true;
+		if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss))
+			alert_charger = true;
 		bdi->ss_reg = ss_reg;
-		alert_userspace = true;
 	}
 
-	mutex_lock(&bdi->f_reg_lock);
-
-	ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg);
-	if (ret < 0) {
-		mutex_unlock(&bdi->f_reg_lock);
-		dev_err(bdi->dev, "Can't read F reg: %d\n", ret);
-		goto out;
-	}
-
-	if (f_reg != bdi->f_reg) {
-		bdi->f_reg = f_reg;
-		bdi->charger_health_valid = true;
-		bdi->battery_health_valid = true;
-		bdi->battery_status_valid = true;
-
-		alert_userspace = true;
-	}
-
-	mutex_unlock(&bdi->f_reg_lock);
-
-	/*
-	 * Sometimes bq24190 gives a steady trickle of interrupts even
-	 * though the watchdog timer is turned off and neither the STATUS
-	 * nor FAULT registers have changed.  Weed out these sprurious
-	 * interrupts so userspace isn't alerted for no reason.
-	 * In addition, the chip always generates an interrupt after
-	 * register reset so we should ignore that one (the very first
-	 * interrupt received).
-	 */
-	if (alert_userspace) {
-		if (!bdi->first_time) {
-			power_supply_changed(bdi->charger);
-			power_supply_changed(bdi->battery);
-		} else {
-			bdi->first_time = false;
-		}
-	}
+	if (alert_charger)
+		power_supply_changed(bdi->charger);
+	if (alert_battery)
+		power_supply_changed(bdi->battery);
 
 out:
 	pm_runtime_put_sync(bdi->dev);
@@ -1300,6 +1262,10 @@
 		goto out;
 
 	ret = bq24190_set_mode_host(bdi);
+	if (ret < 0)
+		goto out;
+
+	ret = bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
 out:
 	pm_runtime_put_sync(bdi->dev);
 	return ret;
@@ -1375,10 +1341,8 @@
 	bdi->model = id->driver_data;
 	strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
 	mutex_init(&bdi->f_reg_lock);
-	bdi->first_time = true;
-	bdi->charger_health_valid = false;
-	bdi->battery_health_valid = false;
-	bdi->battery_status_valid = false;
+	bdi->f_reg = 0;
+	bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */
 
 	i2c_set_clientdata(client, bdi);
 
@@ -1392,22 +1356,13 @@
 		return -EINVAL;
 	}
 
-	ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
-			bq24190_irq_handler_thread,
-			IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-			"bq24190-charger", bdi);
-	if (ret < 0) {
-		dev_err(dev, "Can't set up irq handler\n");
-		goto out1;
-	}
-
 	pm_runtime_enable(dev);
 	pm_runtime_resume(dev);
 
 	ret = bq24190_hw_init(bdi);
 	if (ret < 0) {
 		dev_err(dev, "Hardware init failed\n");
-		goto out2;
+		goto out1;
 	}
 
 	charger_cfg.drv_data = bdi;
@@ -1418,7 +1373,7 @@
 	if (IS_ERR(bdi->charger)) {
 		dev_err(dev, "Can't register charger\n");
 		ret = PTR_ERR(bdi->charger);
-		goto out2;
+		goto out1;
 	}
 
 	battery_cfg.drv_data = bdi;
@@ -1427,24 +1382,34 @@
 	if (IS_ERR(bdi->battery)) {
 		dev_err(dev, "Can't register battery\n");
 		ret = PTR_ERR(bdi->battery);
-		goto out3;
+		goto out2;
 	}
 
 	ret = bq24190_sysfs_create_group(bdi);
 	if (ret) {
 		dev_err(dev, "Can't create sysfs entries\n");
+		goto out3;
+	}
+
+	ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
+			bq24190_irq_handler_thread,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+			"bq24190-charger", bdi);
+	if (ret < 0) {
+		dev_err(dev, "Can't set up irq handler\n");
 		goto out4;
 	}
 
 	return 0;
 
 out4:
-	power_supply_unregister(bdi->battery);
+	bq24190_sysfs_remove_group(bdi);
 out3:
-	power_supply_unregister(bdi->charger);
+	power_supply_unregister(bdi->battery);
 out2:
-	pm_runtime_disable(dev);
+	power_supply_unregister(bdi->charger);
 out1:
+	pm_runtime_disable(dev);
 	if (bdi->gpio_int)
 		gpio_free(bdi->gpio_int);
 
@@ -1488,12 +1453,13 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
 
-	bdi->charger_health_valid = false;
-	bdi->battery_health_valid = false;
-	bdi->battery_status_valid = false;
+	bdi->f_reg = 0;
+	bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */
 
 	pm_runtime_get_sync(bdi->dev);
 	bq24190_register_reset(bdi);
+	bq24190_set_mode_host(bdi);
+	bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
 	pm_runtime_put_sync(bdi->dev);
 
 	/* Things may have changed while suspended so alert upper layer */
diff --git a/drivers/power/bq24257_charger.c b/drivers/power/bq24257_charger.c
index 1fea2c7..6fc31bd 100644
--- a/drivers/power/bq24257_charger.c
+++ b/drivers/power/bq24257_charger.c
@@ -1068,6 +1068,12 @@
 		return ret;
 	}
 
+	ret = bq24257_power_supply_init(bq);
+	if (ret < 0) {
+		dev_err(dev, "Failed to register power supply\n");
+		return ret;
+	}
+
 	ret = devm_request_threaded_irq(dev, client->irq, NULL,
 					bq24257_irq_handler_thread,
 					IRQF_TRIGGER_FALLING |
@@ -1078,12 +1084,6 @@
 		return ret;
 	}
 
-	ret = bq24257_power_supply_init(bq);
-	if (ret < 0) {
-		dev_err(dev, "Failed to register power supply\n");
-		return ret;
-	}
-
 	ret = sysfs_create_group(&bq->charger->dev.kobj, &bq24257_attr_group);
 	if (ret < 0) {
 		dev_err(dev, "Can't create sysfs entries\n");
diff --git a/drivers/power/goldfish_battery.c b/drivers/power/goldfish_battery.c
index a50bb98..f5c525e 100644
--- a/drivers/power/goldfish_battery.c
+++ b/drivers/power/goldfish_battery.c
@@ -24,6 +24,7 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/acpi.h>
 
 struct goldfish_battery_data {
 	void __iomem *reg_base;
@@ -227,11 +228,25 @@
 	return 0;
 }
 
+static const struct of_device_id goldfish_battery_of_match[] = {
+	{ .compatible = "google,goldfish-battery", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, goldfish_battery_of_match);
+
+static const struct acpi_device_id goldfish_battery_acpi_match[] = {
+	{ "GFSH0001", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, goldfish_battery_acpi_match);
+
 static struct platform_driver goldfish_battery_device = {
 	.probe		= goldfish_battery_probe,
 	.remove		= goldfish_battery_remove,
 	.driver = {
-		.name = "goldfish-battery"
+		.name = "goldfish-battery",
+		.of_match_table = goldfish_battery_of_match,
+		.acpi_match_table = ACPI_PTR(goldfish_battery_acpi_match),
 	}
 };
 module_platform_driver(goldfish_battery_device);
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index 9c65f13..da7a75f 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -457,13 +457,16 @@
 }
 
 static inline void max17042_read_model_data(struct max17042_chip *chip,
-					u8 addr, u32 *data, int size)
+					u8 addr, u16 *data, int size)
 {
 	struct regmap *map = chip->regmap;
 	int i;
+	u32 tmp;
 
-	for (i = 0; i < size; i++)
-		regmap_read(map, addr + i, &data[i]);
+	for (i = 0; i < size; i++) {
+		regmap_read(map, addr + i, &tmp);
+		data[i] = (u16)tmp;
+	}
 }
 
 static inline int max17042_model_data_compare(struct max17042_chip *chip,
@@ -486,7 +489,7 @@
 {
 	int ret;
 	int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
-	u32 *temp_data;
+	u16 *temp_data;
 
 	temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL);
 	if (!temp_data)
@@ -501,7 +504,7 @@
 	ret = max17042_model_data_compare(
 		chip,
 		chip->pdata->config_data->cell_char_tbl,
-		(u16 *)temp_data,
+		temp_data,
 		table_size);
 
 	max10742_lock_model(chip);
@@ -514,7 +517,7 @@
 {
 	int i;
 	int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
-	u32 *temp_data;
+	u16 *temp_data;
 	int ret = 0;
 
 	temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 456987c..b13cd07 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -565,11 +565,12 @@
 
 	WARN_ON(tzd == NULL);
 	psy = tzd->devdata;
-	ret = psy->desc->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
+	ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
+	if (ret)
+		return ret;
 
 	/* Convert tenths of degree Celsius to milli degree Celsius. */
-	if (!ret)
-		*temp = val.intval * 100;
+	*temp = val.intval * 100;
 
 	return ret;
 }
@@ -612,10 +613,12 @@
 	int ret;
 
 	psy = tcd->devdata;
-	ret = psy->desc->get_property(psy,
-		POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val);
-	if (!ret)
-		*state = val.intval;
+	ret = power_supply_get_property(psy,
+			POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val);
+	if (ret)
+		return ret;
+
+	*state = val.intval;
 
 	return ret;
 }
@@ -628,10 +631,12 @@
 	int ret;
 
 	psy = tcd->devdata;
-	ret = psy->desc->get_property(psy,
-		POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
-	if (!ret)
-		*state = val.intval;
+	ret = power_supply_get_property(psy,
+			POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
+	if (ret)
+		return ret;
+
+	*state = val.intval;
 
 	return ret;
 }
diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c
index e9e24df..2579f02 100644
--- a/drivers/power/reset/at91-poweroff.c
+++ b/drivers/power/reset/at91-poweroff.c
@@ -14,9 +14,12 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/printk.h>
 
+#include <soc/at91/at91sam9_ddrsdr.h>
+
 #define AT91_SHDW_CR	0x00		/* Shut Down Control Register */
 #define AT91_SHDW_SHDW		BIT(0)			/* Shut Down command */
 #define AT91_SHDW_KEY		(0xa5 << 24)		/* KEY Password */
@@ -50,6 +53,7 @@
 
 static void __iomem *at91_shdwc_base;
 static struct clk *sclk;
+static void __iomem *mpddrc_base;
 
 static void __init at91_wakeup_status(void)
 {
@@ -73,6 +77,29 @@
 	writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR);
 }
 
+static void at91_lpddr_poweroff(void)
+{
+	asm volatile(
+		/* Align to cache lines */
+		".balign 32\n\t"
+
+		/* Ensure AT91_SHDW_CR is in the TLB by reading it */
+		"	ldr	r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
+
+		/* Power down SDRAM0 */
+		"	str	%1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
+		/* Shutdown CPU */
+		"	str	%3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"
+
+		"	b	.\n\t"
+		:
+		: "r" (mpddrc_base),
+		  "r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF),
+		  "r" (at91_shdwc_base),
+		  "r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW)
+		: "r0");
+}
+
 static int at91_poweroff_get_wakeup_mode(struct device_node *np)
 {
 	const char *pm;
@@ -124,6 +151,8 @@
 static int __init at91_poweroff_probe(struct platform_device *pdev)
 {
 	struct resource *res;
+	struct device_node *np;
+	u32 ddr_type;
 	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -150,12 +179,30 @@
 
 	pm_power_off = at91_poweroff;
 
+	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc");
+	if (!np)
+		return 0;
+
+	mpddrc_base = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (!mpddrc_base)
+		return 0;
+
+	ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD;
+	if ((ddr_type == AT91_DDRSDRC_MD_LPDDR2) ||
+	    (ddr_type == AT91_DDRSDRC_MD_LPDDR3))
+		pm_power_off = at91_lpddr_poweroff;
+	else
+		iounmap(mpddrc_base);
+
 	return 0;
 }
 
 static int __exit at91_poweroff_remove(struct platform_device *pdev)
 {
-	if (pm_power_off == at91_poweroff)
+	if (pm_power_off == at91_poweroff ||
+	    pm_power_off == at91_lpddr_poweroff)
 		pm_power_off = NULL;
 
 	clk_disable_unprepare(sclk);
@@ -163,6 +210,11 @@
 	return 0;
 }
 
+static const struct of_device_id at91_ramc_of_match[] = {
+	{ .compatible = "atmel,sama5d3-ddramc", },
+	{ /* sentinel */ }
+};
+
 static const struct of_device_id at91_poweroff_of_match[] = {
 	{ .compatible = "atmel,at91sam9260-shdwc", },
 	{ .compatible = "atmel,at91sam9rl-shdwc", },
diff --git a/drivers/power/reset/hisi-reboot.c b/drivers/power/reset/hisi-reboot.c
index 9ab7f56..f69387e 100644
--- a/drivers/power/reset/hisi-reboot.c
+++ b/drivers/power/reset/hisi-reboot.c
@@ -53,13 +53,16 @@
 
 	if (of_property_read_u32(np, "reboot-offset", &reboot_offset) < 0) {
 		pr_err("failed to find reboot-offset property\n");
+		iounmap(base);
 		return -EINVAL;
 	}
 
 	err = register_restart_handler(&hisi_restart_nb);
-	if (err)
+	if (err) {
 		dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n",
 			err);
+		iounmap(base);
+	}
 
 	return err;
 }
diff --git a/drivers/power/tps65217_charger.c b/drivers/power/tps65217_charger.c
index d9f5673..040a40b 100644
--- a/drivers/power/tps65217_charger.c
+++ b/drivers/power/tps65217_charger.c
@@ -205,6 +205,7 @@
 	if (!charger)
 		return -ENOMEM;
 
+	platform_set_drvdata(pdev, charger);
 	charger->tps = tps;
 	charger->dev = &pdev->dev;
 
diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c
index 38a8bbe..83797d8 100644
--- a/drivers/pps/clients/pps_parport.c
+++ b/drivers/pps/clients/pps_parport.c
@@ -195,7 +195,7 @@
 	struct pps_client_pp *device;
 
 	/* FIXME: oooh, this is ugly! */
-	if (strcmp(pardev->name, KBUILD_MODNAME))
+	if (!pardev || strcmp(pardev->name, KBUILD_MODNAME))
 		/* not our port */
 		return;
 
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index d24ca5f..ec84ff8 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -321,6 +321,8 @@
 	unsigned int i;
 	int ret = 0;
 
+	pwmchip_sysfs_unexport_children(chip);
+
 	mutex_lock(&pwm_lock);
 
 	for (i = 0; i < chip->npwm; i++) {
@@ -889,7 +891,7 @@
   */
 bool pwm_can_sleep(struct pwm_device *pwm)
 {
-	return pwm->chip->can_sleep;
+	return true;
 }
 EXPORT_SYMBOL_GPL(pwm_can_sleep);
 
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c
index f9dfc8b..7225ac6 100644
--- a/drivers/pwm/pwm-fsl-ftm.c
+++ b/drivers/pwm/pwm-fsl-ftm.c
@@ -80,7 +80,6 @@
 
 	struct mutex lock;
 
-	unsigned int use_count;
 	unsigned int cnt_select;
 	unsigned int clk_ps;
 
@@ -300,9 +299,6 @@
 {
 	int ret;
 
-	if (fpc->use_count++ != 0)
-		return 0;
-
 	/* select counter clock source */
 	regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK,
 			   FTM_SC_CLK(fpc->cnt_select));
@@ -334,25 +330,6 @@
 	return ret;
 }
 
-static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc)
-{
-	/*
-	 * already disabled, do nothing
-	 */
-	if (fpc->use_count == 0)
-		return;
-
-	/* there are still users, so can't disable yet */
-	if (--fpc->use_count > 0)
-		return;
-
-	/* no users left, disable PWM counter clock */
-	regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK, 0);
-
-	clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
-	clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
-}
-
 static void fsl_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
@@ -362,7 +339,8 @@
 	regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm),
 			   BIT(pwm->hwpwm));
 
-	fsl_counter_clock_disable(fpc);
+	clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
+	clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
 
 	regmap_read(fpc->regmap, FTM_OUTMASK, &val);
 	if ((val & 0xFF) == 0xFF)
@@ -492,17 +470,24 @@
 static int fsl_pwm_suspend(struct device *dev)
 {
 	struct fsl_pwm_chip *fpc = dev_get_drvdata(dev);
-	u32 val;
+	int i;
 
 	regcache_cache_only(fpc->regmap, true);
 	regcache_mark_dirty(fpc->regmap);
 
-	/* read from cache */
-	regmap_read(fpc->regmap, FTM_OUTMASK, &val);
-	if ((val & 0xFF) != 0xFF) {
+	for (i = 0; i < fpc->chip.npwm; i++) {
+		struct pwm_device *pwm = &fpc->chip.pwms[i];
+
+		if (!test_bit(PWMF_REQUESTED, &pwm->flags))
+			continue;
+
+		clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+
+		if (!pwm_is_enabled(pwm))
+			continue;
+
 		clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
 		clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
-		clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
 	}
 
 	return 0;
@@ -511,12 +496,19 @@
 static int fsl_pwm_resume(struct device *dev)
 {
 	struct fsl_pwm_chip *fpc = dev_get_drvdata(dev);
-	u32 val;
+	int i;
 
-	/* read from cache */
-	regmap_read(fpc->regmap, FTM_OUTMASK, &val);
-	if ((val & 0xFF) != 0xFF) {
+	for (i = 0; i < fpc->chip.npwm; i++) {
+		struct pwm_device *pwm = &fpc->chip.pwms[i];
+
+		if (!test_bit(PWMF_REQUESTED, &pwm->flags))
+			continue;
+
 		clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+
+		if (!pwm_is_enabled(pwm))
+			continue;
+
 		clk_prepare_enable(fpc->clk[fpc->cnt_select]);
 		clk_prepare_enable(fpc->clk[FSL_PWM_CLK_CNTEN]);
 	}
diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
index 9fde60c..6e203a6 100644
--- a/drivers/pwm/pwm-lpc32xx.c
+++ b/drivers/pwm/pwm-lpc32xx.c
@@ -24,9 +24,7 @@
 	void __iomem *base;
 };
 
-#define PWM_ENABLE	(1 << 31)
-#define PWM_RELOADV(x)	(((x) & 0xFF) << 8)
-#define PWM_DUTY(x)	((x) & 0xFF)
+#define PWM_ENABLE	BIT(31)
 
 #define to_lpc32xx_pwm_chip(_chip) \
 	container_of(_chip, struct lpc32xx_pwm_chip, chip)
@@ -38,40 +36,27 @@
 	unsigned long long c;
 	int period_cycles, duty_cycles;
 	u32 val;
+	c = clk_get_rate(lpc32xx->clk);
 
-	c = clk_get_rate(lpc32xx->clk) / 256;
-	c = c * period_ns;
-	do_div(c, NSEC_PER_SEC);
+	/* The highest acceptable divisor is 256, which is represented by 0 */
+	period_cycles = div64_u64(c * period_ns,
+			       (unsigned long long)NSEC_PER_SEC * 256);
+	if (!period_cycles)
+		period_cycles = 1;
+	if (period_cycles > 255)
+		period_cycles = 0;
 
-	/* Handle high and low extremes */
-	if (c == 0)
-		c = 1;
-	if (c > 255)
-		c = 0; /* 0 set division by 256 */
-	period_cycles = c;
-
-	/* The duty-cycle value is as follows:
-	 *
-	 *  DUTY-CYCLE     HIGH LEVEL
-	 *      1            99.9%
-	 *      25           90.0%
-	 *      128          50.0%
-	 *      220          10.0%
-	 *      255           0.1%
-	 *      0             0.0%
-	 *
-	 * In other words, the register value is duty-cycle % 256 with
-	 * duty-cycle in the range 1-256.
-	 */
-	c = 256 * duty_ns;
-	do_div(c, period_ns);
-	if (c > 255)
-		c = 255;
-	duty_cycles = 256 - c;
+	/* Compute 256 x #duty/period value and care for corner cases */
+	duty_cycles = div64_u64((unsigned long long)(period_ns - duty_ns) * 256,
+				period_ns);
+	if (!duty_cycles)
+		duty_cycles = 1;
+	if (duty_cycles > 255)
+		duty_cycles = 255;
 
 	val = readl(lpc32xx->base + (pwm->hwpwm << 2));
 	val &= ~0xFFFF;
-	val |= PWM_RELOADV(period_cycles) | PWM_DUTY(duty_cycles);
+	val |= (period_cycles << 8) | duty_cycles;
 	writel(val, lpc32xx->base + (pwm->hwpwm << 2));
 
 	return 0;
@@ -134,7 +119,7 @@
 
 	lpc32xx->chip.dev = &pdev->dev;
 	lpc32xx->chip.ops = &lpc32xx_pwm_ops;
-	lpc32xx->chip.npwm = 2;
+	lpc32xx->chip.npwm = 1;
 	lpc32xx->chip.base = -1;
 
 	ret = pwmchip_add(&lpc32xx->chip);
diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
index 117fccf..01a6a83 100644
--- a/drivers/pwm/pwm-pca9685.c
+++ b/drivers/pwm/pwm-pca9685.c
@@ -65,7 +65,6 @@
 #define PCA9685_MAXCHAN		0x10
 
 #define LED_FULL		(1 << 4)
-#define MODE1_RESTART		(1 << 7)
 #define MODE1_SLEEP		(1 << 4)
 #define MODE2_INVRT		(1 << 4)
 #define MODE2_OUTDRV		(1 << 2)
@@ -117,16 +116,6 @@
 			udelay(500);
 
 			pca->period_ns = period_ns;
-
-			/*
-			 * If the duty cycle did not change, restart PWM with
-			 * the same duty cycle to period ratio and return.
-			 */
-			if (duty_ns == pca->duty_ns) {
-				regmap_update_bits(pca->regmap, PCA9685_MODE1,
-						   MODE1_RESTART, 0x1);
-				return 0;
-			}
 		} else {
 			dev_err(chip->dev,
 				"prescaler not set: period out of bounds!\n");
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 9c90886..375008e 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -350,6 +350,26 @@
 	}
 }
 
+void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
+{
+	struct device *parent;
+	unsigned int i;
+
+	parent = class_find_device(&pwm_class, NULL, chip,
+				   pwmchip_sysfs_match);
+	if (!parent)
+		return;
+
+	for (i = 0; i < chip->npwm; i++) {
+		struct pwm_device *pwm = &chip->pwms[i];
+
+		if (test_bit(PWMF_EXPORTED, &pwm->flags))
+			pwm_unexport_child(parent, pwm);
+	}
+
+	put_device(parent);
+}
+
 static int __init pwm_sysfs_init(void)
 {
 	return class_register(&pwm_class);
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 63cd5e6..3a6d029 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -296,7 +296,7 @@
 		if (!sreg->sel && !strcmp(sreg->name, "vddpu"))
 			sreg->sel = 22;
 
-		if (!sreg->sel) {
+		if (!sreg->bypass && !sreg->sel) {
 			dev_err(&pdev->dev, "Failed to read a valid default voltage selector.\n");
 			return -EINVAL;
 		}
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index f2e1a39..5cf4a97 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -221,10 +221,10 @@
 		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
 	AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
 		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
-	AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 1800, 3300, 100,
+	AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
 		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
 		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
-	AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 1800, 3300, 100,
+	AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
 		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
 		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
 	AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 732ac71..f9b8c44 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1519,6 +1519,7 @@
 		ret = regulator_enable(rdev->supply);
 		if (ret < 0) {
 			_regulator_put(rdev->supply);
+			rdev->supply = NULL;
 			return ret;
 		}
 	}
@@ -4273,12 +4274,13 @@
 	seq_puts(s, "\n");
 
 	list_for_each_entry(consumer, &rdev->consumer_list, list) {
-		if (consumer->dev->class == &regulator_class)
+		if (consumer->dev && consumer->dev->class == &regulator_class)
 			continue;
 
 		seq_printf(s, "%*s%-*s ",
 			   (level + 1) * 3 + 1, "",
-			   30 - (level + 1) * 3, dev_name(consumer->dev));
+			   30 - (level + 1) * 3,
+			   consumer->dev ? dev_name(consumer->dev) : "deviceless");
 
 		switch (rdev->desc->type) {
 		case REGULATOR_VOLTAGE:
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
index 6fa0c7d..4bda998 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -166,29 +166,30 @@
 static const struct regulator_desc pm8841_ftsmps = {
 	.linear_ranges = (struct regulator_linear_range[]) {
 		REGULATOR_LINEAR_RANGE(350000,  0, 184, 5000),
-		REGULATOR_LINEAR_RANGE(700000, 185, 339, 10000),
+		REGULATOR_LINEAR_RANGE(1280000, 185, 261, 10000),
 	},
 	.n_linear_ranges = 2,
-	.n_voltages = 340,
+	.n_voltages = 262,
 	.ops = &rpm_smps_ldo_ops,
 };
 
 static const struct regulator_desc pm8941_boost = {
 	.linear_ranges = (struct regulator_linear_range[]) {
-		REGULATOR_LINEAR_RANGE(4000000, 0, 15, 100000),
+		REGULATOR_LINEAR_RANGE(4000000, 0, 30, 50000),
 	},
 	.n_linear_ranges = 1,
-	.n_voltages = 16,
+	.n_voltages = 31,
 	.ops = &rpm_smps_ldo_ops,
 };
 
 static const struct regulator_desc pm8941_pldo = {
 	.linear_ranges = (struct regulator_linear_range[]) {
-		REGULATOR_LINEAR_RANGE( 750000,  0,  30, 25000),
-		REGULATOR_LINEAR_RANGE(1500000, 31, 99, 50000),
+		REGULATOR_LINEAR_RANGE( 750000,  0,  63, 12500),
+		REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
+		REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
 	},
-	.n_linear_ranges = 2,
-	.n_voltages = 100,
+	.n_linear_ranges = 3,
+	.n_voltages = 164,
 	.ops = &rpm_smps_ldo_ops,
 };
 
diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c
index 88a5dc8..fee6457 100644
--- a/drivers/regulator/qcom_spmi-regulator.c
+++ b/drivers/regulator/qcom_spmi-regulator.c
@@ -1050,6 +1050,8 @@
 	.set_pull_down		= spmi_regulator_common_set_pull_down,
 	.set_soft_start		= spmi_regulator_common_set_soft_start,
 	.set_over_current_protection = spmi_regulator_vs_ocp,
+	.set_mode		= spmi_regulator_common_set_mode,
+	.get_mode		= spmi_regulator_common_get_mode,
 };
 
 static struct regulator_ops spmi_boost_ops = {
@@ -1440,6 +1442,7 @@
 	{ "s1", 0x1400, "vdd_s1", },
 	{ "s2", 0x1700, "vdd_s2", },
 	{ "s3", 0x1a00, "vdd_s3", },
+	{ "s4", 0xa000, },
 	{ "l1", 0x4000, "vdd_l1_l3", },
 	{ "l2", 0x4100, "vdd_l2_lvs_1_2_3", },
 	{ "l3", 0x4200, "vdd_l1_l3", },
@@ -1467,8 +1470,8 @@
 	{ "lvs1", 0x8000, "vdd_l2_lvs_1_2_3", },
 	{ "lvs2", 0x8100, "vdd_l2_lvs_1_2_3", },
 	{ "lvs3", 0x8200, "vdd_l2_lvs_1_2_3", },
-	{ "mvs1", 0x8300, "vin_5vs", },
-	{ "mvs2", 0x8400, "vin_5vs", },
+	{ "5vs1", 0x8300, "vin_5vs", "ocp-5vs1", },
+	{ "5vs2", 0x8400, "vin_5vs", "ocp-5vs2", },
 	{ }
 };
 
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 72fc3c3..b6d831b 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -305,7 +305,7 @@
 	.enable_mask	= S2MPS11_ENABLE_MASK			\
 }
 
-#define regulator_desc_s2mps11_buck6_10(num, min, step) {	\
+#define regulator_desc_s2mps11_buck67810(num, min, step) {	\
 	.name		= "BUCK"#num,				\
 	.id		= S2MPS11_BUCK##num,			\
 	.ops		= &s2mps11_buck_ops,			\
@@ -321,6 +321,22 @@
 	.enable_mask	= S2MPS11_ENABLE_MASK			\
 }
 
+#define regulator_desc_s2mps11_buck9 {				\
+	.name		= "BUCK9",				\
+	.id		= S2MPS11_BUCK9,			\
+	.ops		= &s2mps11_buck_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= MIN_3000_MV,				\
+	.uV_step	= STEP_25_MV,				\
+	.n_voltages	= S2MPS11_BUCK9_N_VOLTAGES,		\
+	.ramp_delay	= S2MPS11_RAMP_DELAY,			\
+	.vsel_reg	= S2MPS11_REG_B9CTRL2,			\
+	.vsel_mask	= S2MPS11_BUCK9_VSEL_MASK,		\
+	.enable_reg	= S2MPS11_REG_B9CTRL1,			\
+	.enable_mask	= S2MPS11_ENABLE_MASK			\
+}
+
 static const struct regulator_desc s2mps11_regulators[] = {
 	regulator_desc_s2mps11_ldo(1, STEP_25_MV),
 	regulator_desc_s2mps11_ldo(2, STEP_50_MV),
@@ -365,11 +381,11 @@
 	regulator_desc_s2mps11_buck1_4(3),
 	regulator_desc_s2mps11_buck1_4(4),
 	regulator_desc_s2mps11_buck5,
-	regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV),
-	regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV),
-	regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV),
-	regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV),
-	regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV),
+	regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV),
+	regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV),
+	regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV),
+	regulator_desc_s2mps11_buck9,
+	regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV),
 };
 
 static struct regulator_ops s2mps14_reg_ops;
diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c
index 7d2ae3e..342f5da 100644
--- a/drivers/regulator/stw481x-vmmc.c
+++ b/drivers/regulator/stw481x-vmmc.c
@@ -47,7 +47,8 @@
 	.volt_table = stw481x_vmmc_voltages,
 	.enable_time = 200, /* FIXME: look this up */
 	.enable_reg = STW_CONF1,
-	.enable_mask = STW_CONF1_PDN_VMMC,
+	.enable_mask = STW_CONF1_PDN_VMMC | STW_CONF1_MMC_LS_STATUS,
+	.enable_val = STW_CONF1_PDN_VMMC,
 	.vsel_reg = STW_CONF1,
 	.vsel_mask = STW_CONF1_VMMC_MASK,
 };
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index d2c3d7c..5ca6d21 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -311,8 +311,7 @@
 
 	/* Enable setting output voltage by I2C */
 	regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2,
-					TPS65023_REG_CTRL2_CORE_ADJ,
-					TPS65023_REG_CTRL2_CORE_ADJ);
+			   TPS65023_REG_CTRL2_CORE_ADJ, 0);
 
 	return 0;
 }
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index fb991ec..696116e 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -1111,6 +1111,12 @@
 		pmic->num_regulators = ARRAY_SIZE(tps65910_regs);
 		pmic->ext_sleep_control = tps65910_ext_sleep_control;
 		info = tps65910_regs;
+		/* Work around silicon erratum SWCZ010: output programmed
+		 * voltage level can go higher than expected or crash
+		 * Workaround: use no synchronization of DCDC clocks
+		 */
+		tps65910_reg_clear_bits(pmic->mfd, TPS65910_DCDCCTRL,
+					DCDCCTRL_DCDCCKSYNC_MASK);
 		break;
 	case TPS65911:
 		pmic->get_ctrl_reg = &tps65911_get_ctrl_register;
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 9e03d15..4f7ce00 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1239,11 +1239,6 @@
 	if (ret < 0)
 		return ret;
 
-	/* expose to rproc_get_by_phandle users */
-	mutex_lock(&rproc_list_mutex);
-	list_add(&rproc->node, &rproc_list);
-	mutex_unlock(&rproc_list_mutex);
-
 	dev_info(dev, "%s is available\n", rproc->name);
 
 	dev_info(dev, "Note: remoteproc is still under development and considered experimental.\n");
@@ -1251,8 +1246,16 @@
 
 	/* create debugfs entries */
 	rproc_create_debug_dir(rproc);
+	ret = rproc_add_virtio_devices(rproc);
+	if (ret < 0)
+		return ret;
 
-	return rproc_add_virtio_devices(rproc);
+	/* expose to rproc_get_by_phandle users */
+	mutex_lock(&rproc_list_mutex);
+	list_add(&rproc->node, &rproc_list);
+	mutex_unlock(&rproc_list_mutex);
+
+	return 0;
 }
 EXPORT_SYMBOL(rproc_add);
 
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 5836751..9bb934e 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -748,9 +748,23 @@
  */
 static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
 {
+	struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
+	struct rtc_time tm;
+	ktime_t now;
+
 	timer->enabled = 1;
+	__rtc_read_time(rtc, &tm);
+	now = rtc_tm_to_ktime(tm);
+
+	/* Skip over expired timers */
+	while (next) {
+		if (next->expires.tv64 >= now.tv64)
+			break;
+		next = timerqueue_iterate_next(next);
+	}
+
 	timerqueue_add(&rtc->timerqueue, &timer->node);
-	if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) {
+	if (!next) {
 		struct rtc_wkalrm alarm;
 		int err;
 		alarm.time = rtc_ktime_to_tm(timer->node.expires);
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index ec2e9c5..22394fe 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -109,6 +109,7 @@
 /* OMAP_RTC_OSC_REG bit fields: */
 #define OMAP_RTC_OSC_32KCLK_EN		BIT(6)
 #define OMAP_RTC_OSC_SEL_32KCLK_SRC	BIT(3)
+#define OMAP_RTC_OSC_OSC32K_GZ_DISABLE	BIT(4)
 
 /* OMAP_RTC_IRQWAKEEN bit fields: */
 #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN	BIT(1)
@@ -646,8 +647,9 @@
 	 */
 	if (rtc->has_ext_clk) {
 		reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
-		rtc_write(rtc, OMAP_RTC_OSC_REG,
-			  reg | OMAP_RTC_OSC_SEL_32KCLK_SRC);
+		reg &= ~OMAP_RTC_OSC_OSC32K_GZ_DISABLE;
+		reg |= OMAP_RTC_OSC_32KCLK_EN | OMAP_RTC_OSC_SEL_32KCLK_SRC;
+		rtc_writel(rtc, OMAP_RTC_OSC_REG, reg);
 	}
 
 	rtc->type->lock(rtc);
diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
index 7ea2c47..3e9663d 100644
--- a/drivers/rtc/rtc-palmas.c
+++ b/drivers/rtc/rtc-palmas.c
@@ -45,6 +45,42 @@
 /* Total number of RTC registers needed to set time*/
 #define PALMAS_NUM_TIME_REGS	(PALMAS_YEARS_REG - PALMAS_SECONDS_REG + 1)
 
+/*
+ * Special bin2bcd mapping to deal with bcd storage of year.
+ *
+ *   0-69                -> 0xD0
+ *  70-99  (1970 - 1999) -> 0xD0 - 0xF9 (correctly rolls to 0x00)
+ * 100-199 (2000 - 2099) -> 0x00 - 0x99 (does not roll to 0xA0 :-( )
+ * 200-229 (2100 - 2129) -> 0xA0 - 0xC9 (really for completeness)
+ * 230-                  -> 0xC9
+ *
+ * Confirmed: the only transition that does not work correctly for this rtc
+ * clock is the transition from 2099 to 2100, it proceeds to 2000. We will
+ * accept this issue since the clock retains and transitions the year correctly
+ * in all other conditions.
+ */
+static unsigned char year_bin2bcd(int val)
+{
+	if (val < 70)
+		return 0xD0;
+	if (val < 100)
+		return bin2bcd(val - 20) | 0x80; /* KISS leverage of bin2bcd */
+	if (val >= 230)
+		return 0xC9;
+	if (val >= 200)
+		return bin2bcd(val - 180) | 0x80;
+	return bin2bcd(val - 100);
+}
+
+static int year_bcd2bin(unsigned char val)
+{
+	if (val >= 0xD0)
+		return bcd2bin(val & 0x7F) + 20;
+	if (val >= 0xA0)
+		return bcd2bin(val & 0x7F) + 180;
+	return bcd2bin(val) + 100;
+}
+
 static int palmas_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	unsigned char rtc_data[PALMAS_NUM_TIME_REGS];
@@ -71,7 +107,7 @@
 	tm->tm_hour = bcd2bin(rtc_data[2]);
 	tm->tm_mday = bcd2bin(rtc_data[3]);
 	tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
-	tm->tm_year = bcd2bin(rtc_data[5]) + 100;
+	tm->tm_year = year_bcd2bin(rtc_data[5]);
 
 	return ret;
 }
@@ -87,7 +123,7 @@
 	rtc_data[2] = bin2bcd(tm->tm_hour);
 	rtc_data[3] = bin2bcd(tm->tm_mday);
 	rtc_data[4] = bin2bcd(tm->tm_mon + 1);
-	rtc_data[5] = bin2bcd(tm->tm_year - 100);
+	rtc_data[5] = year_bin2bcd(tm->tm_year);
 
 	/* Stop RTC while updating the RTC time registers */
 	ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG,
@@ -142,7 +178,7 @@
 	alm->time.tm_hour = bcd2bin(alarm_data[2]);
 	alm->time.tm_mday = bcd2bin(alarm_data[3]);
 	alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1;
-	alm->time.tm_year = bcd2bin(alarm_data[5]) + 100;
+	alm->time.tm_year = year_bcd2bin(alarm_data[5]);
 
 	ret = palmas_read(palmas, PALMAS_RTC_BASE, PALMAS_RTC_INTERRUPTS_REG,
 			&int_val);
@@ -173,7 +209,7 @@
 	alarm_data[2] = bin2bcd(alm->time.tm_hour);
 	alarm_data[3] = bin2bcd(alm->time.tm_mday);
 	alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
-	alarm_data[5] = bin2bcd(alm->time.tm_year - 100);
+	alarm_data[5] = year_bin2bcd(alm->time.tm_year);
 
 	ret = palmas_bulk_write(palmas, PALMAS_RTC_BASE,
 		PALMAS_ALARM_SECONDS_REG, alarm_data, PALMAS_NUM_TIME_REGS);
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index f40afdd0..00662dd 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -15,6 +15,7 @@
 #include <linux/bitrev.h>
 #include <linux/bcd.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 
 #define S35390A_CMD_STATUS1	0
 #define S35390A_CMD_STATUS2	1
@@ -34,10 +35,14 @@
 #define S35390A_ALRM_BYTE_HOURS	1
 #define S35390A_ALRM_BYTE_MINS	2
 
+/* flags for STATUS1 */
 #define S35390A_FLAG_POC	0x01
 #define S35390A_FLAG_BLD	0x02
+#define S35390A_FLAG_INT2	0x04
 #define S35390A_FLAG_24H	0x40
 #define S35390A_FLAG_RESET	0x80
+
+/* flag for STATUS2 */
 #define S35390A_FLAG_TEST	0x01
 
 #define S35390A_INT2_MODE_MASK		0xF0
@@ -94,19 +99,63 @@
 	return 0;
 }
 
-static int s35390a_reset(struct s35390a *s35390a)
+/*
+ * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset.
+ * To keep the information if an irq is pending, pass the value read from
+ * STATUS1 to the caller.
+ */
+static int s35390a_reset(struct s35390a *s35390a, char *status1)
 {
-	char buf[1];
+	char buf;
+	int ret;
+	unsigned initcount = 0;
 
-	if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0)
-		return -EIO;
+	ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1);
+	if (ret < 0)
+		return ret;
 
-	if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD)))
+	if (*status1 & S35390A_FLAG_POC)
+		/*
+		 * Do not communicate for 0.5 seconds since the power-on
+		 * detection circuit is in operation.
+		 */
+		msleep(500);
+	else if (!(*status1 & S35390A_FLAG_BLD))
+		/*
+		 * If both POC and BLD are unset everything is fine.
+		 */
 		return 0;
 
-	buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H);
-	buf[0] &= 0xf0;
-	return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
+	/*
+	 * At least one of POC and BLD are set, so reinitialise chip. Keeping
+	 * this information in the hardware to know later that the time isn't
+	 * valid is unfortunately not possible because POC and BLD are cleared
+	 * on read. So the reset is best done now.
+	 *
+	 * The 24H bit is kept over reset, so set it already here.
+	 */
+initialize:
+	*status1 = S35390A_FLAG_24H;
+	buf = S35390A_FLAG_RESET | S35390A_FLAG_24H;
+	ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
+
+	if (ret < 0)
+		return ret;
+
+	ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
+	if (ret < 0)
+		return ret;
+
+	if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) {
+		/* Try up to five times to reset the chip */
+		if (initcount < 5) {
+			++initcount;
+			goto initialize;
+		} else
+			return -EIO;
+	}
+
+	return 1;
 }
 
 static int s35390a_disable_test_mode(struct s35390a *s35390a)
@@ -242,6 +291,8 @@
 
 	if (alm->time.tm_wday != -1)
 		buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;
+	else
+		buf[S35390A_ALRM_BYTE_WDAY] = 0;
 
 	buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
 			alm->time.tm_hour) | 0x80;
@@ -265,27 +316,61 @@
 	char buf[3], sts;
 	int i, err;
 
+	/*
+	 * initialize all members to -1 to signal the core that they are not
+	 * defined by the hardware.
+	 */
+	alm->time.tm_sec = -1;
+	alm->time.tm_min = -1;
+	alm->time.tm_hour = -1;
+	alm->time.tm_mday = -1;
+	alm->time.tm_mon = -1;
+	alm->time.tm_year = -1;
+	alm->time.tm_wday = -1;
+	alm->time.tm_yday = -1;
+	alm->time.tm_isdst = -1;
+
 	err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
 	if (err < 0)
 		return err;
 
-	if (bitrev8(sts) != S35390A_INT2_MODE_ALARM)
-		return -EINVAL;
+	if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
+		/*
+		 * When the alarm isn't enabled, the register to configure
+		 * the alarm time isn't accessible.
+		 */
+		alm->enabled = 0;
+		return 0;
+	} else {
+		alm->enabled = 1;
+	}
 
 	err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
 	if (err < 0)
 		return err;
 
 	/* This chip returns the bits of each byte in reverse order */
-	for (i = 0; i < 3; ++i) {
+	for (i = 0; i < 3; ++i)
 		buf[i] = bitrev8(buf[i]);
-		buf[i] &= ~0x80;
-	}
 
-	alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]);
-	alm->time.tm_hour = s35390a_reg2hr(s35390a,
-						buf[S35390A_ALRM_BYTE_HOURS]);
-	alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]);
+	/*
+	 * B0 of the three matching registers is an enable flag. Iff it is set
+	 * the configured value is used for matching.
+	 */
+	if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)
+		alm->time.tm_wday =
+			bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);
+
+	if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
+		alm->time.tm_hour =
+			s35390a_reg2hr(s35390a,
+				       buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
+
+	if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
+		alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
+
+	/* alarm triggers always at s=0 */
+	alm->time.tm_sec = 0;
 
 	dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
 			__func__, alm->time.tm_min, alm->time.tm_hour,
@@ -327,11 +412,11 @@
 static int s35390a_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
-	int err;
+	int err, err_reset;
 	unsigned int i;
 	struct s35390a *s35390a;
 	struct rtc_time tm;
-	char buf[1];
+	char buf, status1;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		err = -ENODEV;
@@ -360,29 +445,35 @@
 		}
 	}
 
-	err = s35390a_reset(s35390a);
-	if (err < 0) {
+	err_reset = s35390a_reset(s35390a, &status1);
+	if (err_reset < 0) {
+		err = err_reset;
 		dev_err(&client->dev, "error resetting chip\n");
 		goto exit_dummy;
 	}
 
-	err = s35390a_disable_test_mode(s35390a);
-	if (err < 0) {
-		dev_err(&client->dev, "error disabling test mode\n");
-		goto exit_dummy;
-	}
-
-	err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
-	if (err < 0) {
-		dev_err(&client->dev, "error checking 12/24 hour mode\n");
-		goto exit_dummy;
-	}
-	if (buf[0] & S35390A_FLAG_24H)
+	if (status1 & S35390A_FLAG_24H)
 		s35390a->twentyfourhour = 1;
 	else
 		s35390a->twentyfourhour = 0;
 
-	if (s35390a_get_datetime(client, &tm) < 0)
+	if (status1 & S35390A_FLAG_INT2) {
+		/* disable alarm (and maybe test mode) */
+		buf = 0;
+		err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
+		if (err < 0) {
+			dev_err(&client->dev, "error disabling alarm");
+			goto exit_dummy;
+		}
+	} else {
+		err = s35390a_disable_test_mode(s35390a);
+		if (err < 0) {
+			dev_err(&client->dev, "error disabling test mode\n");
+			goto exit_dummy;
+		}
+	}
+
+	if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0)
 		dev_warn(&client->dev, "clock needs to be set\n");
 
 	device_set_wakeup_capable(&client->dev, 1);
@@ -395,6 +486,10 @@
 		err = PTR_ERR(s35390a->rtc);
 		goto exit_dummy;
 	}
+
+	if (status1 & S35390A_FLAG_INT2)
+		rtc_update_irq(s35390a->rtc, 1, RTC_AF);
+
 	return 0;
 
 exit_dummy:
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index ffb860d..f925288 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -149,12 +149,14 @@
 	if (!is_power_of_2(freq))
 		return -EINVAL;
 
+	s3c_rtc_enable_clk(info);
 	spin_lock_irq(&info->pie_lock);
 
 	if (info->data->set_freq)
 		info->data->set_freq(info, freq);
 
 	spin_unlock_irq(&info->pie_lock);
+	s3c_rtc_disable_clk(info);
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index c169a2c..e29cc9f 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -37,9 +37,11 @@
 
 /* Control register */
 #define SUN6I_LOSC_CTRL				0x0000
+#define SUN6I_LOSC_CTRL_KEY			(0x16aa << 16)
 #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC		BIT(9)
 #define SUN6I_LOSC_CTRL_RTC_HMS_ACC		BIT(8)
 #define SUN6I_LOSC_CTRL_RTC_YMD_ACC		BIT(7)
+#define SUN6I_LOSC_CTRL_EXT_OSC			BIT(0)
 #define SUN6I_LOSC_CTRL_ACC_MASK		GENMASK(9, 7)
 
 /* RTC */
@@ -114,13 +116,17 @@
 	void __iomem *base;
 	int irq;
 	unsigned long alarm;
+
+	spinlock_t lock;
 };
 
 static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id)
 {
 	struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id;
+	irqreturn_t ret = IRQ_NONE;
 	u32 val;
 
+	spin_lock(&chip->lock);
 	val = readl(chip->base + SUN6I_ALRM_IRQ_STA);
 
 	if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) {
@@ -129,10 +135,11 @@
 
 		rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF);
 
-		return IRQ_HANDLED;
+		ret = IRQ_HANDLED;
 	}
+	spin_unlock(&chip->lock);
 
-	return IRQ_NONE;
+	return ret;
 }
 
 static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip)
@@ -140,6 +147,7 @@
 	u32 alrm_val = 0;
 	u32 alrm_irq_val = 0;
 	u32 alrm_wake_val = 0;
+	unsigned long flags;
 
 	if (to) {
 		alrm_val = SUN6I_ALRM_EN_CNT_EN;
@@ -150,9 +158,11 @@
 		       chip->base + SUN6I_ALRM_IRQ_STA);
 	}
 
+	spin_lock_irqsave(&chip->lock, flags);
 	writel(alrm_val, chip->base + SUN6I_ALRM_EN);
 	writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN);
 	writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG);
+	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
@@ -191,11 +201,15 @@
 static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 {
 	struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
+	unsigned long flags;
 	u32 alrm_st;
 	u32 alrm_en;
 
+	spin_lock_irqsave(&chip->lock, flags);
 	alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN);
 	alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA);
+	spin_unlock_irqrestore(&chip->lock, flags);
+
 	wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN);
 	wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN);
 	rtc_time_to_tm(chip->alarm, &wkalrm->time);
@@ -356,6 +370,7 @@
 	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
+	spin_lock_init(&chip->lock);
 
 	platform_set_drvdata(pdev, chip);
 	chip->dev = &pdev->dev;
@@ -404,6 +419,10 @@
 	/* disable alarm wakeup */
 	writel(0, chip->base + SUN6I_ALARM_CONFIG);
 
+	/* switch to the external, more precise, oscillator */
+	writel(SUN6I_LOSC_CTRL_KEY | SUN6I_LOSC_CTRL_EXT_OSC,
+	       chip->base + SUN6I_LOSC_CTRL);
+
 	chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev,
 					&sun6i_rtc_ops, THIS_MODULE);
 	if (IS_ERR(chip->rtc)) {
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index 60232bd..71216aa 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -18,6 +18,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 #include <linux/kernel.h>
+#include <linux/clk.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -59,6 +60,7 @@
 	struct platform_device	*pdev;
 	struct rtc_device	*rtc_dev;
 	void __iomem		*rtc_base; /* NULL if not initialized. */
+	struct clk		*clk;
 	int			tegra_rtc_irq; /* alarm and periodic irq */
 	spinlock_t		tegra_rtc_lock;
 };
@@ -332,6 +334,14 @@
 	if (info->tegra_rtc_irq <= 0)
 		return -EBUSY;
 
+	info->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(info->clk))
+		return PTR_ERR(info->clk);
+
+	ret = clk_prepare_enable(info->clk);
+	if (ret < 0)
+		return ret;
+
 	/* set context info. */
 	info->pdev = pdev;
 	spin_lock_init(&info->tegra_rtc_lock);
@@ -352,7 +362,7 @@
 		ret = PTR_ERR(info->rtc_dev);
 		dev_err(&pdev->dev, "Unable to register device (err=%d).\n",
 			ret);
-		return ret;
+		goto disable_clk;
 	}
 
 	ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq,
@@ -362,12 +372,25 @@
 		dev_err(&pdev->dev,
 			"Unable to request interrupt for device (err=%d).\n",
 			ret);
-		return ret;
+		goto disable_clk;
 	}
 
 	dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
 
 	return 0;
+
+disable_clk:
+	clk_disable_unprepare(info->clk);
+	return ret;
+}
+
+static int tegra_rtc_remove(struct platform_device *pdev)
+{
+	struct tegra_rtc_info *info = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(info->clk);
+
+	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -419,6 +442,7 @@
 
 MODULE_ALIAS("platform:tegra_rtc");
 static struct platform_driver tegra_rtc_driver = {
+	.remove		= tegra_rtc_remove,
 	.shutdown	= tegra_rtc_shutdown,
 	.driver		= {
 		.name	= "tegra_rtc",
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 4abfbdb..84c13df 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1584,9 +1584,18 @@
 	unsigned long long now;
 	int expires;
 
+	cqr = (struct dasd_ccw_req *) intparm;
 	if (IS_ERR(irb)) {
 		switch (PTR_ERR(irb)) {
 		case -EIO:
+			if (cqr && cqr->status == DASD_CQR_CLEAR_PENDING) {
+				device = (struct dasd_device *) cqr->startdev;
+				cqr->status = DASD_CQR_CLEARED;
+				dasd_device_clear_timer(device);
+				wake_up(&dasd_flush_wq);
+				dasd_schedule_device_bh(device);
+				return;
+			}
 			break;
 		case -ETIMEDOUT:
 			DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: "
@@ -1602,7 +1611,6 @@
 	}
 
 	now = get_tod_clock();
-	cqr = (struct dasd_ccw_req *) intparm;
 	/* check for conditions that should be handled immediately */
 	if (!cqr ||
 	    !(scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 94a8f4a..ae1dc37 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -892,7 +892,7 @@
 	dev_info = bdev->bd_disk->private_data;
 	if (!dev_info)
 		return -ENODEV;
-	dev_sz = dev_info->end - dev_info->start;
+	dev_sz = dev_info->end - dev_info->start + 1;
 	offset = secnum * 512;
 	addr = (void *) (dev_info->start + offset);
 	*pfn = virt_to_phys(addr) >> PAGE_SHIFT;
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 7c511ad..bae9852 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -124,7 +124,12 @@
 static void
 con3270_update_string(struct con3270 *cp, struct string *s, int nr)
 {
-	if (s->len >= cp->view.cols - 5)
+	if (s->len < 4) {
+		/* This indicates a bug, but printing a warning would
+		 * cause a deadlock. */
+		return;
+	}
+	if (s->string[s->len - 4] != TO_RA)
 		return;
 	raw3270_buffer_address(cp->view.dev, s->string + s->len - 3,
 			       cp->view.cols * (nr + 1));
@@ -461,11 +466,11 @@
 		cp->cline->len + 4 : cp->view.cols;
 	s = con3270_alloc_string(cp, size);
 	memcpy(s->string, cp->cline->string, cp->cline->len);
-	if (s->len < cp->view.cols - 5) {
+	if (cp->cline->len < cp->view.cols - 5) {
 		s->string[s->len - 4] = TO_RA;
 		s->string[s->len - 1] = 0;
 	} else {
-		while (--size > cp->cline->len)
+		while (--size >= cp->cline->len)
 			s->string[size] = cp->view.ascebc[' '];
 	}
 	/* Replace cline with allocated line s and reset cline. */
diff --git a/drivers/s390/char/sclp_ctl.c b/drivers/s390/char/sclp_ctl.c
index 648cb86..ea607a4 100644
--- a/drivers/s390/char/sclp_ctl.c
+++ b/drivers/s390/char/sclp_ctl.c
@@ -56,6 +56,7 @@
 {
 	struct sclp_ctl_sccb ctl_sccb;
 	struct sccb_header *sccb;
+	unsigned long copied;
 	int rc;
 
 	if (copy_from_user(&ctl_sccb, user_area, sizeof(ctl_sccb)))
@@ -65,14 +66,15 @@
 	sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!sccb)
 		return -ENOMEM;
-	if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sizeof(*sccb))) {
+	copied = PAGE_SIZE -
+		copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), PAGE_SIZE);
+	if (offsetof(struct sccb_header, length) +
+	    sizeof(sccb->length) > copied || sccb->length > copied) {
 		rc = -EFAULT;
 		goto out_free;
 	}
-	if (sccb->length > PAGE_SIZE || sccb->length < 8)
-		return -EINVAL;
-	if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sccb->length)) {
-		rc = -EFAULT;
+	if (sccb->length < 8) {
+		rc = -EINVAL;
 		goto out_free;
 	}
 	rc = sclp_sync_request(ctl_sccb.cmdw, sccb);
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 799c152..4b8de3e 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -872,7 +872,7 @@
 		goto cleanup;
 
 	for (i=0; i < MAXMINOR; ++i ) {
-		sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL);
+		sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 		if (!sys_ser[i].buffer) {
 			rc = -ENOMEM;
 			break;
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index c692dfe..50597f9 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -139,11 +139,11 @@
 
 	device = container_of(kobj, struct device, kobj);
 	chp = to_channelpath(device);
-	if (!chp->cmg_chars)
+	if (chp->cmg == -1)
 		return 0;
 
-	return memory_read_from_buffer(buf, count, &off,
-				chp->cmg_chars, sizeof(struct cmg_chars));
+	return memory_read_from_buffer(buf, count, &off, &chp->cmg_chars,
+				       sizeof(chp->cmg_chars));
 }
 
 static struct bin_attribute chp_measurement_chars_attr = {
@@ -416,7 +416,8 @@
  * chp_update_desc - update channel-path description
  * @chp - channel-path
  *
- * Update the channel-path description of the specified channel-path.
+ * Update the channel-path description of the specified channel-path
+ * including channel measurement related information.
  * Return zero on success, non-zero otherwise.
  */
 int chp_update_desc(struct channel_path *chp)
@@ -428,8 +429,10 @@
 		return rc;
 
 	rc = chsc_determine_fmt1_channel_path_desc(chp->chpid, &chp->desc_fmt1);
+	if (rc)
+		return rc;
 
-	return rc;
+	return chsc_get_channel_measurement_chars(chp);
 }
 
 /**
@@ -466,14 +469,6 @@
 		ret = -ENODEV;
 		goto out_free;
 	}
-	/* Get channel-measurement characteristics. */
-	if (css_chsc_characteristics.scmc && css_chsc_characteristics.secm) {
-		ret = chsc_get_channel_measurement_chars(chp);
-		if (ret)
-			goto out_free;
-	} else {
-		chp->cmg = -1;
-	}
 	dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id);
 
 	/* make it known to the system */
diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h
index 4efd5b8..af02322 100644
--- a/drivers/s390/cio/chp.h
+++ b/drivers/s390/cio/chp.h
@@ -48,7 +48,7 @@
 	/* Channel-measurement related stuff: */
 	int cmg;
 	int shared;
-	void *cmg_chars;
+	struct cmg_chars cmg_chars;
 };
 
 /* Return channel_path struct for given chpid. */
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index a831d18..1e16331 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <linux/pci.h>
 
 #include <asm/cio.h>
@@ -94,12 +95,13 @@
 int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
 {
 	struct chsc_ssd_area *ssd_area;
+	unsigned long flags;
 	int ccode;
 	int ret;
 	int i;
 	int mask;
 
-	spin_lock_irq(&chsc_page_lock);
+	spin_lock_irqsave(&chsc_page_lock, flags);
 	memset(chsc_page, 0, PAGE_SIZE);
 	ssd_area = chsc_page;
 	ssd_area->request.length = 0x0010;
@@ -143,7 +145,7 @@
 			ssd->fla[i] = ssd_area->fla[i];
 	}
 out:
-	spin_unlock_irq(&chsc_page_lock);
+	spin_unlock_irqrestore(&chsc_page_lock, flags);
 	return ret;
 }
 
@@ -224,8 +226,9 @@
 
 void chsc_chp_offline(struct chp_id chpid)
 {
-	char dbf_txt[15];
+	struct channel_path *chp = chpid_to_chp(chpid);
 	struct chp_link link;
+	char dbf_txt[15];
 
 	sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id);
 	CIO_TRACE_EVENT(2, dbf_txt);
@@ -236,6 +239,11 @@
 	link.chpid = chpid;
 	/* Wait until previous actions have settled. */
 	css_wait_for_slow_path();
+
+	mutex_lock(&chp->lock);
+	chp_update_desc(chp);
+	mutex_unlock(&chp->lock);
+
 	for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link);
 }
 
@@ -690,8 +698,9 @@
 
 void chsc_chp_online(struct chp_id chpid)
 {
-	char dbf_txt[15];
+	struct channel_path *chp = chpid_to_chp(chpid);
 	struct chp_link link;
+	char dbf_txt[15];
 
 	sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id);
 	CIO_TRACE_EVENT(2, dbf_txt);
@@ -701,6 +710,11 @@
 		link.chpid = chpid;
 		/* Wait until previous actions have settled. */
 		css_wait_for_slow_path();
+
+		mutex_lock(&chp->lock);
+		chp_update_desc(chp);
+		mutex_unlock(&chp->lock);
+
 		for_each_subchannel_staged(__s390_process_res_acc, NULL,
 					   &link);
 		css_schedule_reprobe();
@@ -819,9 +833,10 @@
 		u32 fmt : 4;
 		u32 : 16;
 	} __attribute__ ((packed)) *secm_area;
+	unsigned long flags;
 	int ret, ccode;
 
-	spin_lock_irq(&chsc_page_lock);
+	spin_lock_irqsave(&chsc_page_lock, flags);
 	memset(chsc_page, 0, PAGE_SIZE);
 	secm_area = chsc_page;
 	secm_area->request.length = 0x0050;
@@ -851,7 +866,7 @@
 		CIO_CRW_EVENT(2, "chsc: secm failed (rc=%04x)\n",
 			      secm_area->response.code);
 out:
-	spin_unlock_irq(&chsc_page_lock);
+	spin_unlock_irqrestore(&chsc_page_lock, flags);
 	return ret;
 }
 
@@ -967,22 +982,20 @@
 chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
 			  struct cmg_chars *chars)
 {
-	struct cmg_chars *cmg_chars;
 	int i, mask;
 
-	cmg_chars = chp->cmg_chars;
 	for (i = 0; i < NR_MEASUREMENT_CHARS; i++) {
 		mask = 0x80 >> (i + 3);
 		if (cmcv & mask)
-			cmg_chars->values[i] = chars->values[i];
+			chp->cmg_chars.values[i] = chars->values[i];
 		else
-			cmg_chars->values[i] = 0;
+			chp->cmg_chars.values[i] = 0;
 	}
 }
 
 int chsc_get_channel_measurement_chars(struct channel_path *chp)
 {
-	struct cmg_chars *cmg_chars;
+	unsigned long flags;
 	int ccode, ret;
 
 	struct {
@@ -1006,12 +1019,13 @@
 		u32 data[NR_MEASUREMENT_CHARS];
 	} __attribute__ ((packed)) *scmc_area;
 
-	chp->cmg_chars = NULL;
-	cmg_chars = kmalloc(sizeof(*cmg_chars), GFP_KERNEL);
-	if (!cmg_chars)
-		return -ENOMEM;
+	chp->shared = -1;
+	chp->cmg = -1;
 
-	spin_lock_irq(&chsc_page_lock);
+	if (!css_chsc_characteristics.scmc || !css_chsc_characteristics.secm)
+		return 0;
+
+	spin_lock_irqsave(&chsc_page_lock, flags);
 	memset(chsc_page, 0, PAGE_SIZE);
 	scmc_area = chsc_page;
 	scmc_area->request.length = 0x0010;
@@ -1031,25 +1045,19 @@
 			      scmc_area->response.code);
 		goto out;
 	}
-	if (scmc_area->not_valid) {
-		chp->cmg = -1;
-		chp->shared = -1;
+	if (scmc_area->not_valid)
 		goto out;
-	}
+
 	chp->cmg = scmc_area->cmg;
 	chp->shared = scmc_area->shared;
 	if (chp->cmg != 2 && chp->cmg != 3) {
 		/* No cmg-dependent data. */
 		goto out;
 	}
-	chp->cmg_chars = cmg_chars;
 	chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
 				  (struct cmg_chars *) &scmc_area->data);
 out:
-	spin_unlock_irq(&chsc_page_lock);
-	if (!chp->cmg_chars)
-		kfree(cmg_chars);
-
+	spin_unlock_irqrestore(&chsc_page_lock, flags);
 	return ret;
 }
 
@@ -1130,6 +1138,7 @@
 int __init
 chsc_determine_css_characteristics(void)
 {
+	unsigned long flags;
 	int result;
 	struct {
 		struct chsc_header request;
@@ -1142,7 +1151,7 @@
 		u32 chsc_char[508];
 	} __attribute__ ((packed)) *scsc_area;
 
-	spin_lock_irq(&chsc_page_lock);
+	spin_lock_irqsave(&chsc_page_lock, flags);
 	memset(chsc_page, 0, PAGE_SIZE);
 	scsc_area = chsc_page;
 	scsc_area->request.length = 0x0010;
@@ -1164,7 +1173,7 @@
 		CIO_CRW_EVENT(2, "chsc: scsc failed (rc=%04x)\n",
 			      scsc_area->response.code);
 exit:
-	spin_unlock_irq(&chsc_page_lock);
+	spin_unlock_irqrestore(&chsc_page_lock, flags);
 	return result;
 }
 
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index b2afad5..2a34eb5 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -753,6 +753,17 @@
 	cmf_generic_reset(cdev);
 }
 
+static int cmf_enabled(struct ccw_device *cdev)
+{
+	int enabled;
+
+	spin_lock_irq(cdev->ccwlock);
+	enabled = !!cdev->private->cmb;
+	spin_unlock_irq(cdev->ccwlock);
+
+	return enabled;
+}
+
 static struct attribute_group cmf_attr_group;
 
 static struct cmb_operations cmbops_basic = {
@@ -1153,13 +1164,8 @@
 			       char *buf)
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
-	int enabled;
 
-	spin_lock_irq(cdev->ccwlock);
-	enabled = !!cdev->private->cmb;
-	spin_unlock_irq(cdev->ccwlock);
-
-	return sprintf(buf, "%d\n", enabled);
+	return sprintf(buf, "%d\n", cmf_enabled(cdev));
 }
 
 static ssize_t cmb_enable_store(struct device *dev,
@@ -1199,15 +1205,20 @@
  *  @cdev:	The ccw device to be enabled
  *
  *  Returns %0 for success or a negative error value.
- *
+ *  Note: If this is called on a device for which channel measurement is already
+ *	  enabled a reset of the measurement data is triggered.
  *  Context:
  *    non-atomic
  */
 int enable_cmf(struct ccw_device *cdev)
 {
-	int ret;
+	int ret = 0;
 
 	device_lock(&cdev->dev);
+	if (cmf_enabled(cdev)) {
+		cmbops->reset(cdev);
+		goto out_unlock;
+	}
 	get_device(&cdev->dev);
 	ret = cmbops->alloc(cdev);
 	if (ret)
@@ -1226,7 +1237,7 @@
 out:
 	if (ret)
 		put_device(&cdev->dev);
-
+out_unlock:
 	device_unlock(&cdev->dev);
 	return ret;
 }
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 5d06253..30e9fbbf 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -147,11 +147,11 @@
 	struct qdio_q *q;
 	int i;
 
-	for_each_input_queue(irq, q, i) {
-		if (!references_shared_dsci(irq) &&
-		    has_multiple_inq_on_dsci(irq))
-			xchg(q->irq_ptr->dsci, 0);
+	if (!references_shared_dsci(irq) &&
+	    has_multiple_inq_on_dsci(irq))
+		xchg(irq->dsci, 0);
 
+	for_each_input_queue(irq, q, i) {
 		if (q->u.in.queue_start_poll) {
 			/* skip if polling is enabled or already in work */
 			if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 24ec282..7c3b8d3 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -1651,6 +1651,9 @@
 		ap_dev->queue_depth = queue_depth;
 		ap_dev->raw_hwtype = device_type;
 		ap_dev->device_type = device_type;
+		/* CEX6 toleration: map to CEX5 */
+		if (device_type == AP_DEVICE_TYPE_CEX6)
+			ap_dev->device_type = AP_DEVICE_TYPE_CEX5;
 		ap_dev->functions = device_functions;
 		spin_lock_init(&ap_dev->lock);
 		INIT_LIST_HEAD(&ap_dev->pendingq);
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 6adcbdf..cc741e9 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -105,6 +105,7 @@
 #define AP_DEVICE_TYPE_CEX3C	9
 #define AP_DEVICE_TYPE_CEX4	10
 #define AP_DEVICE_TYPE_CEX5	11
+#define AP_DEVICE_TYPE_CEX6	12
 
 /*
  * Known function facilities
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 1766a20..741f3ee 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -717,6 +717,7 @@
 };
 
 struct qeth_discipline {
+	const struct device_type *devtype;
 	void (*start_poll)(struct ccw_device *, int, unsigned long);
 	qdio_handler_t *input_handler;
 	qdio_handler_t *output_handler;
@@ -881,6 +882,9 @@
 extern struct qeth_discipline qeth_l3_discipline;
 extern const struct attribute_group *qeth_generic_attr_groups[];
 extern const struct attribute_group *qeth_osn_attr_groups[];
+extern const struct attribute_group qeth_device_attr_group;
+extern const struct attribute_group qeth_device_blkt_group;
+extern const struct device_type qeth_generic_devtype;
 extern struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 31ac53f..d10bf3d 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -5449,10 +5449,12 @@
 	card->discipline = NULL;
 }
 
-static const struct device_type qeth_generic_devtype = {
+const struct device_type qeth_generic_devtype = {
 	.name = "qeth_generic",
 	.groups = qeth_generic_attr_groups,
 };
+EXPORT_SYMBOL_GPL(qeth_generic_devtype);
+
 static const struct device_type qeth_osn_devtype = {
 	.name = "qeth_osn",
 	.groups = qeth_osn_attr_groups,
@@ -5578,23 +5580,22 @@
 		goto err_card;
 	}
 
-	if (card->info.type == QETH_CARD_TYPE_OSN)
-		gdev->dev.type = &qeth_osn_devtype;
-	else
-		gdev->dev.type = &qeth_generic_devtype;
-
 	switch (card->info.type) {
 	case QETH_CARD_TYPE_OSN:
 	case QETH_CARD_TYPE_OSM:
 		rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
 		if (rc)
 			goto err_card;
+
+		gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN)
+					? card->discipline->devtype
+					: &qeth_osn_devtype;
 		rc = card->discipline->setup(card->gdev);
 		if (rc)
 			goto err_disc;
-	case QETH_CARD_TYPE_OSD:
-	case QETH_CARD_TYPE_OSX:
+		break;
 	default:
+		gdev->dev.type = &qeth_generic_devtype;
 		break;
 	}
 
@@ -5650,8 +5651,10 @@
 		if (rc)
 			goto err;
 		rc = card->discipline->setup(card->gdev);
-		if (rc)
+		if (rc) {
+			qeth_core_free_discipline(card);
 			goto err;
+		}
 	}
 	rc = card->discipline->set_online(gdev);
 err:
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index e6e5b96..fa844b0 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -409,12 +409,16 @@
 
 	if (card->options.layer2 == newdis)
 		goto out;
-	else {
-		card->info.mac_bits  = 0;
-		if (card->discipline) {
-			card->discipline->remove(card->gdev);
-			qeth_core_free_discipline(card);
-		}
+	if (card->info.type == QETH_CARD_TYPE_OSM) {
+		/* fixed layer, can't switch */
+		rc = -EOPNOTSUPP;
+		goto out;
+	}
+
+	card->info.mac_bits = 0;
+	if (card->discipline) {
+		card->discipline->remove(card->gdev);
+		qeth_core_free_discipline(card);
 	}
 
 	rc = qeth_core_load_discipline(card, newdis);
@@ -422,6 +426,8 @@
 		goto out;
 
 	rc = card->discipline->setup(card->gdev);
+	if (rc)
+		qeth_core_free_discipline(card);
 out:
 	mutex_unlock(&card->discipline_mutex);
 	return rc ? rc : count;
@@ -699,10 +705,11 @@
 	&dev_attr_inter_jumbo.attr,
 	NULL,
 };
-static struct attribute_group qeth_device_blkt_group = {
+const struct attribute_group qeth_device_blkt_group = {
 	.name = "blkt",
 	.attrs = qeth_blkt_device_attrs,
 };
+EXPORT_SYMBOL_GPL(qeth_device_blkt_group);
 
 static struct attribute *qeth_device_attrs[] = {
 	&dev_attr_state.attr,
@@ -722,9 +729,10 @@
 	&dev_attr_switch_attrs.attr,
 	NULL,
 };
-static struct attribute_group qeth_device_attr_group = {
+const struct attribute_group qeth_device_attr_group = {
 	.attrs = qeth_device_attrs,
 };
+EXPORT_SYMBOL_GPL(qeth_device_attr_group);
 
 const struct attribute_group *qeth_generic_attr_groups[] = {
 	&qeth_device_attr_group,
diff --git a/drivers/s390/net/qeth_l2.h b/drivers/s390/net/qeth_l2.h
index 0767556..eb87bf9 100644
--- a/drivers/s390/net/qeth_l2.h
+++ b/drivers/s390/net/qeth_l2.h
@@ -8,6 +8,8 @@
 
 #include "qeth_core.h"
 
+extern const struct attribute_group *qeth_l2_attr_groups[];
+
 int qeth_l2_create_device_attributes(struct device *);
 void qeth_l2_remove_device_attributes(struct device *);
 void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 8f1b091..bf1e0e3 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1027,11 +1027,21 @@
 	return 0;
 }
 
+static const struct device_type qeth_l2_devtype = {
+	.name = "qeth_layer2",
+	.groups = qeth_l2_attr_groups,
+};
+
 static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+	int rc;
 
-	qeth_l2_create_device_attributes(&gdev->dev);
+	if (gdev->dev.type == &qeth_generic_devtype) {
+		rc = qeth_l2_create_device_attributes(&gdev->dev);
+		if (rc)
+			return rc;
+	}
 	INIT_LIST_HEAD(&card->vid_list);
 	hash_init(card->mac_htable);
 	card->options.layer2 = 1;
@@ -1043,7 +1053,8 @@
 {
 	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
 
-	qeth_l2_remove_device_attributes(&cgdev->dev);
+	if (cgdev->dev.type == &qeth_generic_devtype)
+		qeth_l2_remove_device_attributes(&cgdev->dev);
 	qeth_set_allowed_threads(card, 0, 1);
 	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
 
@@ -1051,6 +1062,7 @@
 		qeth_l2_set_offline(cgdev);
 
 	if (card->dev) {
+		netif_napi_del(&card->napi);
 		unregister_netdev(card->dev);
 		card->dev = NULL;
 	}
@@ -1100,7 +1112,6 @@
 	case QETH_CARD_TYPE_OSN:
 		card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
 					 ether_setup);
-		card->dev->flags |= IFF_NOARP;
 		break;
 	default:
 		card->dev = alloc_etherdev(0);
@@ -1113,9 +1124,12 @@
 	card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
 	card->dev->mtu = card->info.initial_mtu;
 	card->dev->netdev_ops = &qeth_l2_netdev_ops;
-	card->dev->ethtool_ops =
-		(card->info.type != QETH_CARD_TYPE_OSN) ?
-		&qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
+	if (card->info.type == QETH_CARD_TYPE_OSN) {
+		card->dev->ethtool_ops = &qeth_l2_osn_ops;
+		card->dev->flags |= IFF_NOARP;
+	} else {
+		card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
+	}
 	card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 	if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
 		card->dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
@@ -1126,6 +1140,7 @@
 	qeth_l2_request_initial_mac(card);
 	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
 	netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT);
+	netif_carrier_off(card->dev);
 	return register_netdev(card->dev);
 }
 
@@ -1427,6 +1442,7 @@
 }
 
 struct qeth_discipline qeth_l2_discipline = {
+	.devtype = &qeth_l2_devtype,
 	.start_poll = qeth_qdio_start_poll,
 	.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
 	.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
diff --git a/drivers/s390/net/qeth_l2_sys.c b/drivers/s390/net/qeth_l2_sys.c
index 692db49..a48ed9e 100644
--- a/drivers/s390/net/qeth_l2_sys.c
+++ b/drivers/s390/net/qeth_l2_sys.c
@@ -272,3 +272,11 @@
 	} else
 		qeth_bridgeport_an_set(card, 0);
 }
+
+const struct attribute_group *qeth_l2_attr_groups[] = {
+	&qeth_device_attr_group,
+	&qeth_device_blkt_group,
+	/* l2 specific, see l2_{create,remove}_device_attributes(): */
+	&qeth_l2_bridgeport_attr_group,
+	NULL,
+};
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 543960e..285fe0b 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3220,14 +3220,18 @@
 
 	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
 	netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT);
+	netif_carrier_off(card->dev);
 	return register_netdev(card->dev);
 }
 
 static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+	int rc;
 
-	qeth_l3_create_device_attributes(&gdev->dev);
+	rc = qeth_l3_create_device_attributes(&gdev->dev);
+	if (rc)
+		return rc;
 	card->options.layer2 = 0;
 	card->info.hwtrap = 0;
 	return 0;
@@ -3246,6 +3250,7 @@
 		qeth_l3_set_offline(cgdev);
 
 	if (card->dev) {
+		netif_napi_del(&card->napi);
 		unregister_netdev(card->dev);
 		card->dev = NULL;
 	}
@@ -3517,6 +3522,7 @@
 }
 
 struct qeth_discipline qeth_l3_discipline = {
+	.devtype = &qeth_generic_devtype,
 	.start_poll = qeth_qdio_start_poll,
 	.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
 	.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 5d7fbe4..d5bf36e 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -3,7 +3,7 @@
  *
  * Debug traces for zfcp.
  *
- * Copyright IBM Corp. 2002, 2013
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -65,7 +65,7 @@
  * @tag: tag indicating which kind of unsolicited status has been received
  * @req: request for which a response was received
  */
-void zfcp_dbf_hba_fsf_res(char *tag, struct zfcp_fsf_req *req)
+void zfcp_dbf_hba_fsf_res(char *tag, int level, struct zfcp_fsf_req *req)
 {
 	struct zfcp_dbf *dbf = req->adapter->dbf;
 	struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix;
@@ -85,6 +85,8 @@
 	rec->u.res.req_issued = req->issued;
 	rec->u.res.prot_status = q_pref->prot_status;
 	rec->u.res.fsf_status = q_head->fsf_status;
+	rec->u.res.port_handle = q_head->port_handle;
+	rec->u.res.lun_handle = q_head->lun_handle;
 
 	memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual,
 	       FSF_PROT_STATUS_QUAL_SIZE);
@@ -97,7 +99,7 @@
 				  rec->pl_len, "fsf_res", req->req_id);
 	}
 
-	debug_event(dbf->hba, 1, rec, sizeof(*rec));
+	debug_event(dbf->hba, level, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->hba_lock, flags);
 }
 
@@ -241,7 +243,8 @@
 	if (sdev) {
 		rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status);
 		rec->lun = zfcp_scsi_dev_lun(sdev);
-	}
+	} else
+		rec->lun = ZFCP_DBF_INVALID_LUN;
 }
 
 /**
@@ -286,11 +289,12 @@
 
 
 /**
- * zfcp_dbf_rec_run - trace event related to running recovery
+ * zfcp_dbf_rec_run_lvl - trace event related to running recovery
+ * @level: trace level to be used for event
  * @tag: identifier for event
  * @erp: erp_action running
  */
-void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp)
+void zfcp_dbf_rec_run_lvl(int level, char *tag, struct zfcp_erp_action *erp)
 {
 	struct zfcp_dbf *dbf = erp->adapter->dbf;
 	struct zfcp_dbf_rec *rec = &dbf->rec_buf;
@@ -316,17 +320,62 @@
 	else
 		rec->u.run.rec_count = atomic_read(&erp->adapter->erp_counter);
 
+	debug_event(dbf->rec, level, rec, sizeof(*rec));
+	spin_unlock_irqrestore(&dbf->rec_lock, flags);
+}
+
+/**
+ * zfcp_dbf_rec_run - trace event related to running recovery
+ * @tag: identifier for event
+ * @erp: erp_action running
+ */
+void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp)
+{
+	zfcp_dbf_rec_run_lvl(1, tag, erp);
+}
+
+/**
+ * zfcp_dbf_rec_run_wka - trace wka port event with info like running recovery
+ * @tag: identifier for event
+ * @wka_port: well known address port
+ * @req_id: request ID to correlate with potential HBA trace record
+ */
+void zfcp_dbf_rec_run_wka(char *tag, struct zfcp_fc_wka_port *wka_port,
+			  u64 req_id)
+{
+	struct zfcp_dbf *dbf = wka_port->adapter->dbf;
+	struct zfcp_dbf_rec *rec = &dbf->rec_buf;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dbf->rec_lock, flags);
+	memset(rec, 0, sizeof(*rec));
+
+	rec->id = ZFCP_DBF_REC_RUN;
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	rec->port_status = wka_port->status;
+	rec->d_id = wka_port->d_id;
+	rec->lun = ZFCP_DBF_INVALID_LUN;
+
+	rec->u.run.fsf_req_id = req_id;
+	rec->u.run.rec_status = ~0;
+	rec->u.run.rec_step = ~0;
+	rec->u.run.rec_action = ~0;
+	rec->u.run.rec_count = ~0;
+
 	debug_event(dbf->rec, 1, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
 
 static inline
-void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, void *data, u8 id, u16 len,
-		  u64 req_id, u32 d_id)
+void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf,
+		  char *paytag, struct scatterlist *sg, u8 id, u16 len,
+		  u64 req_id, u32 d_id, u16 cap_len)
 {
 	struct zfcp_dbf_san *rec = &dbf->san_buf;
 	u16 rec_len;
 	unsigned long flags;
+	struct zfcp_dbf_pay *payload = &dbf->pay_buf;
+	u16 pay_sum = 0;
 
 	spin_lock_irqsave(&dbf->san_lock, flags);
 	memset(rec, 0, sizeof(*rec));
@@ -334,10 +383,41 @@
 	rec->id = id;
 	rec->fsf_req_id = req_id;
 	rec->d_id = d_id;
-	rec_len = min(len, (u16)ZFCP_DBF_SAN_MAX_PAYLOAD);
-	memcpy(rec->payload, data, rec_len);
 	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	rec->pl_len = len; /* full length even if we cap pay below */
+	if (!sg)
+		goto out;
+	rec_len = min_t(unsigned int, sg->length, ZFCP_DBF_SAN_MAX_PAYLOAD);
+	memcpy(rec->payload, sg_virt(sg), rec_len); /* part of 1st sg entry */
+	if (len <= rec_len)
+		goto out; /* skip pay record if full content in rec->payload */
 
+	/* if (len > rec_len):
+	 * dump data up to cap_len ignoring small duplicate in rec->payload
+	 */
+	spin_lock(&dbf->pay_lock);
+	memset(payload, 0, sizeof(*payload));
+	memcpy(payload->area, paytag, ZFCP_DBF_TAG_LEN);
+	payload->fsf_req_id = req_id;
+	payload->counter = 0;
+	for (; sg && pay_sum < cap_len; sg = sg_next(sg)) {
+		u16 pay_len, offset = 0;
+
+		while (offset < sg->length && pay_sum < cap_len) {
+			pay_len = min((u16)ZFCP_DBF_PAY_MAX_REC,
+				      (u16)(sg->length - offset));
+			/* cap_len <= pay_sum < cap_len+ZFCP_DBF_PAY_MAX_REC */
+			memcpy(payload->data, sg_virt(sg) + offset, pay_len);
+			debug_event(dbf->pay, 1, payload,
+				    zfcp_dbf_plen(pay_len));
+			payload->counter++;
+			offset += pay_len;
+			pay_sum += pay_len;
+		}
+	}
+	spin_unlock(&dbf->pay_lock);
+
+out:
 	debug_event(dbf->san, 1, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->san_lock, flags);
 }
@@ -354,9 +434,62 @@
 	struct zfcp_fsf_ct_els *ct_els = fsf->data;
 	u16 length;
 
-	length = (u16)(ct_els->req->length + FC_CT_HDR_LEN);
-	zfcp_dbf_san(tag, dbf, sg_virt(ct_els->req), ZFCP_DBF_SAN_REQ, length,
-		     fsf->req_id, d_id);
+	length = (u16)zfcp_qdio_real_bytes(ct_els->req);
+	zfcp_dbf_san(tag, dbf, "san_req", ct_els->req, ZFCP_DBF_SAN_REQ,
+		     length, fsf->req_id, d_id, length);
+}
+
+static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
+					      struct zfcp_fsf_req *fsf,
+					      u16 len)
+{
+	struct zfcp_fsf_ct_els *ct_els = fsf->data;
+	struct fc_ct_hdr *reqh = sg_virt(ct_els->req);
+	struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1);
+	struct scatterlist *resp_entry = ct_els->resp;
+	struct fc_gpn_ft_resp *acc;
+	int max_entries, x, last = 0;
+
+	if (!(memcmp(tag, "fsscth2", 7) == 0
+	      && ct_els->d_id == FC_FID_DIR_SERV
+	      && reqh->ct_rev == FC_CT_REV
+	      && reqh->ct_in_id[0] == 0
+	      && reqh->ct_in_id[1] == 0
+	      && reqh->ct_in_id[2] == 0
+	      && reqh->ct_fs_type == FC_FST_DIR
+	      && reqh->ct_fs_subtype == FC_NS_SUBTYPE
+	      && reqh->ct_options == 0
+	      && reqh->_ct_resvd1 == 0
+	      && reqh->ct_cmd == FC_NS_GPN_FT
+	      /* reqh->ct_mr_size can vary so do not match but read below */
+	      && reqh->_ct_resvd2 == 0
+	      && reqh->ct_reason == 0
+	      && reqh->ct_explan == 0
+	      && reqh->ct_vendor == 0
+	      && reqn->fn_resvd == 0
+	      && reqn->fn_domain_id_scope == 0
+	      && reqn->fn_area_id_scope == 0
+	      && reqn->fn_fc4_type == FC_TYPE_FCP))
+		return len; /* not GPN_FT response so do not cap */
+
+	acc = sg_virt(resp_entry);
+	max_entries = (reqh->ct_mr_size * 4 / sizeof(struct fc_gpn_ft_resp))
+		+ 1 /* zfcp_fc_scan_ports: bytes correct, entries off-by-one
+		     * to account for header as 1st pseudo "entry" */;
+
+	/* the basic CT_IU preamble is the same size as one entry in the GPN_FT
+	 * response, allowing us to skip special handling for it - just skip it
+	 */
+	for (x = 1; x < max_entries && !last; x++) {
+		if (x % (ZFCP_FC_GPN_FT_ENT_PAGE + 1))
+			acc++;
+		else
+			acc = sg_virt(++resp_entry);
+
+		last = acc->fp_flags & FC_NS_FID_LAST;
+	}
+	len = min(len, (u16)(x * sizeof(struct fc_gpn_ft_resp)));
+	return len; /* cap after last entry */
 }
 
 /**
@@ -370,9 +503,10 @@
 	struct zfcp_fsf_ct_els *ct_els = fsf->data;
 	u16 length;
 
-	length = (u16)(ct_els->resp->length + FC_CT_HDR_LEN);
-	zfcp_dbf_san(tag, dbf, sg_virt(ct_els->resp), ZFCP_DBF_SAN_RES, length,
-		     fsf->req_id, 0);
+	length = (u16)zfcp_qdio_real_bytes(ct_els->resp);
+	zfcp_dbf_san(tag, dbf, "san_res", ct_els->resp, ZFCP_DBF_SAN_RES,
+		     length, fsf->req_id, ct_els->d_id,
+		     zfcp_dbf_san_res_cap_len_if_gpn_ft(tag, fsf, length));
 }
 
 /**
@@ -386,11 +520,13 @@
 	struct fsf_status_read_buffer *srb =
 		(struct fsf_status_read_buffer *) fsf->data;
 	u16 length;
+	struct scatterlist sg;
 
 	length = (u16)(srb->length -
 			offsetof(struct fsf_status_read_buffer, payload));
-	zfcp_dbf_san(tag, dbf, srb->payload.data, ZFCP_DBF_SAN_ELS, length,
-		     fsf->req_id, ntoh24(srb->d_id));
+	sg_init_one(&sg, srb->payload.data, length);
+	zfcp_dbf_san(tag, dbf, "san_els", &sg, ZFCP_DBF_SAN_ELS, length,
+		     fsf->req_id, ntoh24(srb->d_id), length);
 }
 
 /**
@@ -399,7 +535,8 @@
  * @sc: pointer to struct scsi_cmnd
  * @fsf: pointer to struct zfcp_fsf_req
  */
-void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf)
+void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc,
+		   struct zfcp_fsf_req *fsf)
 {
 	struct zfcp_adapter *adapter =
 		(struct zfcp_adapter *) sc->device->host->hostdata[0];
@@ -442,7 +579,7 @@
 		}
 	}
 
-	debug_event(dbf->scsi, 1, rec, sizeof(*rec));
+	debug_event(dbf->scsi, level, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->scsi_lock, flags);
 }
 
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 0be3d48..db186d4 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -2,7 +2,7 @@
  * zfcp device driver
  * debug feature declarations
  *
- * Copyright IBM Corp. 2008, 2010
+ * Copyright IBM Corp. 2008, 2016
  */
 
 #ifndef ZFCP_DBF_H
@@ -17,6 +17,11 @@
 
 #define ZFCP_DBF_INVALID_LUN	0xFFFFFFFFFFFFFFFFull
 
+enum zfcp_dbf_pseudo_erp_act_type {
+	ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD = 0xff,
+	ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL = 0xfe,
+};
+
 /**
  * struct zfcp_dbf_rec_trigger - trace record for triggered recovery action
  * @ready: number of ready recovery actions
@@ -110,6 +115,7 @@
 	u32 d_id;
 #define ZFCP_DBF_SAN_MAX_PAYLOAD (FC_CT_HDR_LEN + 32)
 	char payload[ZFCP_DBF_SAN_MAX_PAYLOAD];
+	u16 pl_len;
 } __packed;
 
 /**
@@ -126,6 +132,8 @@
 	u8  prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
 	u32 fsf_status;
 	u8  fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
+	u32 port_handle;
+	u32 lun_handle;
 } __packed;
 
 /**
@@ -275,11 +283,35 @@
 	struct zfcp_dbf_scsi		scsi_buf;
 };
 
+/**
+ * zfcp_dbf_hba_fsf_resp_suppress - true if we should not trace by default
+ * @req: request that has been completed
+ *
+ * Returns true if FCP response with only benign residual under count.
+ */
+static inline
+bool zfcp_dbf_hba_fsf_resp_suppress(struct zfcp_fsf_req *req)
+{
+	struct fsf_qtcb *qtcb = req->qtcb;
+	u32 fsf_stat = qtcb->header.fsf_status;
+	struct fcp_resp *fcp_rsp;
+	u8 rsp_flags, fr_status;
+
+	if (qtcb->prefix.qtcb_type != FSF_IO_COMMAND)
+		return false; /* not an FCP response */
+	fcp_rsp = (struct fcp_resp *)&qtcb->bottom.io.fcp_rsp;
+	rsp_flags = fcp_rsp->fr_flags;
+	fr_status = fcp_rsp->fr_status;
+	return (fsf_stat == FSF_FCP_RSP_AVAILABLE) &&
+		(rsp_flags == FCP_RESID_UNDER) &&
+		(fr_status == SAM_STAT_GOOD);
+}
+
 static inline
 void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req)
 {
 	if (debug_level_enabled(req->adapter->dbf->hba, level))
-		zfcp_dbf_hba_fsf_res(tag, req);
+		zfcp_dbf_hba_fsf_res(tag, level, req);
 }
 
 /**
@@ -296,7 +328,9 @@
 		zfcp_dbf_hba_fsf_resp("fs_perr", 1, req);
 
 	} else if (qtcb->header.fsf_status != FSF_GOOD) {
-		zfcp_dbf_hba_fsf_resp("fs_ferr", 1, req);
+		zfcp_dbf_hba_fsf_resp("fs_ferr",
+				      zfcp_dbf_hba_fsf_resp_suppress(req)
+				      ? 5 : 1, req);
 
 	} else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
 		   (req->fsf_command == FSF_QTCB_OPEN_LUN)) {
@@ -318,7 +352,7 @@
 					scmd->device->host->hostdata[0];
 
 	if (debug_level_enabled(adapter->dbf->scsi, level))
-		zfcp_dbf_scsi(tag, scmd, req);
+		zfcp_dbf_scsi(tag, level, scmd, req);
 }
 
 /**
@@ -380,4 +414,15 @@
 	_zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL);
 }
 
+/**
+ * zfcp_dbf_scsi_nullcmnd() - trace NULLify of SCSI command in dev/tgt-reset.
+ * @scmnd: SCSI command that was NULLified.
+ * @fsf_req: request that owned @scmnd.
+ */
+static inline void zfcp_dbf_scsi_nullcmnd(struct scsi_cmnd *scmnd,
+					  struct zfcp_fsf_req *fsf_req)
+{
+	_zfcp_dbf_scsi("scfc__1", 3, scmnd, fsf_req);
+}
+
 #endif /* ZFCP_DBF_H */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 3fb4109..7ccfce5 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -3,7 +3,7 @@
  *
  * Error Recovery Procedures (ERP).
  *
- * Copyright IBM Corp. 2002, 2010
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -1204,6 +1204,62 @@
 	}
 }
 
+/**
+ * zfcp_erp_try_rport_unblock - unblock rport if no more/new recovery
+ * @port: zfcp_port whose fc_rport we should try to unblock
+ */
+static void zfcp_erp_try_rport_unblock(struct zfcp_port *port)
+{
+	unsigned long flags;
+	struct zfcp_adapter *adapter = port->adapter;
+	int port_status;
+	struct Scsi_Host *shost = adapter->scsi_host;
+	struct scsi_device *sdev;
+
+	write_lock_irqsave(&adapter->erp_lock, flags);
+	port_status = atomic_read(&port->status);
+	if ((port_status & ZFCP_STATUS_COMMON_UNBLOCKED)    == 0 ||
+	    (port_status & (ZFCP_STATUS_COMMON_ERP_INUSE |
+			    ZFCP_STATUS_COMMON_ERP_FAILED)) != 0) {
+		/* new ERP of severity >= port triggered elsewhere meanwhile or
+		 * local link down (adapter erp_failed but not clear unblock)
+		 */
+		zfcp_dbf_rec_run_lvl(4, "ertru_p", &port->erp_action);
+		write_unlock_irqrestore(&adapter->erp_lock, flags);
+		return;
+	}
+	spin_lock(shost->host_lock);
+	__shost_for_each_device(sdev, shost) {
+		struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev);
+		int lun_status;
+
+		if (zsdev->port != port)
+			continue;
+		/* LUN under port of interest */
+		lun_status = atomic_read(&zsdev->status);
+		if ((lun_status & ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
+			continue; /* unblock rport despite failed LUNs */
+		/* LUN recovery not given up yet [maybe follow-up pending] */
+		if ((lun_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 ||
+		    (lun_status & ZFCP_STATUS_COMMON_ERP_INUSE) != 0) {
+			/* LUN blocked:
+			 * not yet unblocked [LUN recovery pending]
+			 * or meanwhile blocked [new LUN recovery triggered]
+			 */
+			zfcp_dbf_rec_run_lvl(4, "ertru_l", &zsdev->erp_action);
+			spin_unlock(shost->host_lock);
+			write_unlock_irqrestore(&adapter->erp_lock, flags);
+			return;
+		}
+	}
+	/* now port has no child or all children have completed recovery,
+	 * and no ERP of severity >= port was meanwhile triggered elsewhere
+	 */
+	zfcp_scsi_schedule_rport_register(port);
+	spin_unlock(shost->host_lock);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
+}
+
 static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
 {
 	struct zfcp_adapter *adapter = act->adapter;
@@ -1214,11 +1270,18 @@
 	case ZFCP_ERP_ACTION_REOPEN_LUN:
 		if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
 			scsi_device_put(sdev);
+		zfcp_erp_try_rport_unblock(port);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
-		if (result == ZFCP_ERP_SUCCEEDED)
-			zfcp_scsi_schedule_rport_register(port);
+		/* This switch case might also happen after a forced reopen
+		 * was successfully done and thus overwritten with a new
+		 * non-forced reopen at `ersfs_2'. In this case, we must not
+		 * do the clean-up of the non-forced version.
+		 */
+		if (act->step != ZFCP_ERP_STEP_UNINITIALIZED)
+			if (result == ZFCP_ERP_SUCCEEDED)
+				zfcp_erp_try_rport_unblock(port);
 		/* fall through */
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
 		put_device(&port->dev);
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 5b50065..21c8c68 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -3,7 +3,7 @@
  *
  * External function declarations.
  *
- * Copyright IBM Corp. 2002, 2010
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #ifndef ZFCP_EXT_H
@@ -35,8 +35,11 @@
 extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *,
 			      struct zfcp_port *, struct scsi_device *, u8, u8);
 extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *);
+extern void zfcp_dbf_rec_run_lvl(int level, char *tag,
+				 struct zfcp_erp_action *erp);
+extern void zfcp_dbf_rec_run_wka(char *, struct zfcp_fc_wka_port *, u64);
 extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
-extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_hba_fsf_res(char *, int, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **);
@@ -44,7 +47,8 @@
 extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
 extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
-extern void zfcp_dbf_scsi(char *, struct scsi_cmnd *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_scsi(char *, int, struct scsi_cmnd *,
+			  struct zfcp_fsf_req *);
 
 /* zfcp_erp.c */
 extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 522a633..27ff38f 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -3,7 +3,7 @@
  *
  * Implementation of FSF commands.
  *
- * Copyright IBM Corp. 2002, 2013
+ * Copyright IBM Corp. 2002, 2015
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -508,7 +508,10 @@
 		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
 		break;
 	case FSF_TOPO_FABRIC:
-		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+		if (bottom->connection_features & FSF_FEATURE_NPIV_MODE)
+			fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
+		else
+			fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
 		break;
 	case FSF_TOPO_AL:
 		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
@@ -613,7 +616,6 @@
 
 	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
 		fc_host_permanent_port_name(shost) = bottom->wwpn;
-		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
 	} else
 		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
 	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
@@ -982,8 +984,12 @@
 	if (zfcp_adapter_multi_buffer_active(adapter)) {
 		if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
 			return -EIO;
+		qtcb->bottom.support.req_buf_length =
+			zfcp_qdio_real_bytes(sg_req);
 		if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
 			return -EIO;
+		qtcb->bottom.support.resp_buf_length =
+			zfcp_qdio_real_bytes(sg_resp);
 
 		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
 					zfcp_qdio_sbale_count(sg_req));
@@ -1073,6 +1079,7 @@
 
 	req->handler = zfcp_fsf_send_ct_handler;
 	req->qtcb->header.port_handle = wka_port->handle;
+	ct->d_id = wka_port->d_id;
 	req->data = ct;
 
 	zfcp_dbf_san_req("fssct_1", req, wka_port->d_id);
@@ -1169,6 +1176,7 @@
 
 	hton24(req->qtcb->bottom.support.d_id, d_id);
 	req->handler = zfcp_fsf_send_els_handler;
+	els->d_id = d_id;
 	req->data = els;
 
 	zfcp_dbf_san_req("fssels1", req, d_id);
@@ -1604,6 +1612,8 @@
 		zfcp_fsf_req_free(req);
 out:
 	spin_unlock_irq(&qdio->req_q_lock);
+	if (!retval)
+		zfcp_dbf_rec_run_wka("fsowp_1", wka_port, req->req_id);
 	return retval;
 }
 
@@ -1657,6 +1667,8 @@
 		zfcp_fsf_req_free(req);
 out:
 	spin_unlock_irq(&qdio->req_q_lock);
+	if (!retval)
+		zfcp_dbf_rec_run_wka("fscwp_1", wka_port, req->req_id);
 	return retval;
 }
 
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 57ae3ae..ea3c76a 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -3,7 +3,7 @@
  *
  * Interface to the FSF support functions.
  *
- * Copyright IBM Corp. 2002, 2010
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #ifndef FSF_H
@@ -78,6 +78,7 @@
 #define FSF_APP_TAG_CHECK_FAILURE		0x00000082
 #define FSF_REF_TAG_CHECK_FAILURE		0x00000083
 #define FSF_ADAPTER_STATUS_AVAILABLE		0x000000AD
+#define FSF_FCP_RSP_AVAILABLE			0x000000AF
 #define FSF_UNKNOWN_COMMAND			0x000000E2
 #define FSF_UNKNOWN_OP_SUBTYPE                  0x000000E3
 #define FSF_INVALID_COMMAND_OPTION              0x000000E5
@@ -436,6 +437,7 @@
  * @handler_data: data passed to handler function
  * @port: Optional pointer to port for zfcp internal ELS (only test link ADISC)
  * @status: used to pass error status to calling function
+ * @d_id: Destination ID of either open WKA port for CT or of D_ID for ELS
  */
 struct zfcp_fsf_ct_els {
 	struct scatterlist *req;
@@ -444,6 +446,7 @@
 	void *handler_data;
 	struct zfcp_port *port;
 	int status;
+	u32 d_id;
 };
 
 #endif				/* FSF_H */
diff --git a/drivers/s390/scsi/zfcp_reqlist.h b/drivers/s390/scsi/zfcp_reqlist.h
index 7c2c619..703fce5 100644
--- a/drivers/s390/scsi/zfcp_reqlist.h
+++ b/drivers/s390/scsi/zfcp_reqlist.h
@@ -4,7 +4,7 @@
  * Data structure and helper functions for tracking pending FSF
  * requests.
  *
- * Copyright IBM Corp. 2009
+ * Copyright IBM Corp. 2009, 2016
  */
 
 #ifndef ZFCP_REQLIST_H
@@ -180,4 +180,32 @@
 	spin_unlock_irqrestore(&rl->lock, flags);
 }
 
+/**
+ * zfcp_reqlist_apply_for_all() - apply a function to every request.
+ * @rl: the requestlist that contains the target requests.
+ * @f: the function to apply to each request; the first parameter of the
+ *     function will be the target-request; the second parameter is the same
+ *     pointer as given with the argument @data.
+ * @data: freely chosen argument; passed through to @f as second parameter.
+ *
+ * Uses :c:macro:`list_for_each_entry` to iterate over the lists in the hash-
+ * table (not a 'safe' variant, so don't modify the list).
+ *
+ * Holds @rl->lock over the entire request-iteration.
+ */
+static inline void
+zfcp_reqlist_apply_for_all(struct zfcp_reqlist *rl,
+			   void (*f)(struct zfcp_fsf_req *, void *), void *data)
+{
+	struct zfcp_fsf_req *req;
+	unsigned long flags;
+	unsigned int i;
+
+	spin_lock_irqsave(&rl->lock, flags);
+	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
+		list_for_each_entry(req, &rl->buckets[i], list)
+			f(req, data);
+	spin_unlock_irqrestore(&rl->lock, flags);
+}
+
 #endif /* ZFCP_REQLIST_H */
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index b3c6ff4..07ffdbb 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -3,7 +3,7 @@
  *
  * Interface to Linux SCSI midlayer.
  *
- * Copyright IBM Corp. 2002, 2013
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -88,9 +88,7 @@
 	}
 
 	if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
-		/* This could be either
-		 * open LUN pending: this is temporary, will result in
-		 *	open LUN or ERP_FAILED, so retry command
+		/* This could be
 		 * call to rport_delete pending: mimic retry from
 		 * 	fc_remote_port_chkready until rport is BLOCKED
 		 */
@@ -209,6 +207,57 @@
 	return retval;
 }
 
+struct zfcp_scsi_req_filter {
+	u8 tmf_scope;
+	u32 lun_handle;
+	u32 port_handle;
+};
+
+static void zfcp_scsi_forget_cmnd(struct zfcp_fsf_req *old_req, void *data)
+{
+	struct zfcp_scsi_req_filter *filter =
+		(struct zfcp_scsi_req_filter *)data;
+
+	/* already aborted - prevent side-effects - or not a SCSI command */
+	if (old_req->data == NULL || old_req->fsf_command != FSF_QTCB_FCP_CMND)
+		return;
+
+	/* (tmf_scope == FCP_TMF_TGT_RESET || tmf_scope == FCP_TMF_LUN_RESET) */
+	if (old_req->qtcb->header.port_handle != filter->port_handle)
+		return;
+
+	if (filter->tmf_scope == FCP_TMF_LUN_RESET &&
+	    old_req->qtcb->header.lun_handle != filter->lun_handle)
+		return;
+
+	zfcp_dbf_scsi_nullcmnd((struct scsi_cmnd *)old_req->data, old_req);
+	old_req->data = NULL;
+}
+
+static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags)
+{
+	struct zfcp_adapter *adapter = zsdev->port->adapter;
+	struct zfcp_scsi_req_filter filter = {
+		.tmf_scope = FCP_TMF_TGT_RESET,
+		.port_handle = zsdev->port->handle,
+	};
+	unsigned long flags;
+
+	if (tm_flags == FCP_TMF_LUN_RESET) {
+		filter.tmf_scope = FCP_TMF_LUN_RESET;
+		filter.lun_handle = zsdev->lun_handle;
+	}
+
+	/*
+	 * abort_lock secures against other processings - in the abort-function
+	 * and normal cmnd-handler - of (struct zfcp_fsf_req *)->data
+	 */
+	write_lock_irqsave(&adapter->abort_lock, flags);
+	zfcp_reqlist_apply_for_all(adapter->req_list, zfcp_scsi_forget_cmnd,
+				   &filter);
+	write_unlock_irqrestore(&adapter->abort_lock, flags);
+}
+
 static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 {
 	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
@@ -241,8 +290,10 @@
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
 		zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
 		retval = FAILED;
-	} else
+	} else {
 		zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
+		zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags);
+	}
 
 	zfcp_fsf_req_free(fsf_req);
 	return retval;
@@ -556,6 +607,9 @@
 	ids.port_id = port->d_id;
 	ids.roles = FC_RPORT_ROLE_FCP_TARGET;
 
+	zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL,
+			  ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD,
+			  ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD);
 	rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
 	if (!rport) {
 		dev_err(&port->adapter->ccw_device->dev,
@@ -577,6 +631,9 @@
 	struct fc_rport *rport = port->rport;
 
 	if (rport) {
+		zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL,
+				  ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL,
+				  ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL);
 		fc_remote_port_delete(rport);
 		port->rport = NULL;
 	}
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index d4c2856..3ddc85e 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1122,7 +1122,7 @@
 		} else {
 			struct scsi_cmnd *SCp;
 
-			SCp = scsi_host_find_tag(SDp->host, SCSI_NO_TAG);
+			SCp = SDp->current_cmnd;
 			if(unlikely(SCp == NULL)) {
 				sdev_printk(KERN_ERR, SDp,
 					"no saved request for untagged cmd\n");
@@ -1826,7 +1826,7 @@
 		       slot->tag, slot);
 	} else {
 		slot->tag = SCSI_NO_TAG;
-		/* must populate current_cmnd for scsi_host_find_tag to work */
+		/* save current command for reselection */
 		SCp->device->current_cmnd = SCp;
 	}
 	/* sanity check: some of the commands generated by the mid-layer
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 64eed87..433c5e3 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1637,7 +1637,7 @@
 
 config MAC_SCSI
 	tristate "Macintosh NCR5380 SCSI"
-	depends on MAC && SCSI=y
+	depends on MAC && SCSI
 	select SCSI_SPI_ATTRS
 	help
 	  This is the NCR 5380 SCSI controller included on most of the 68030
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index d044f3f..4677730 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -29,6 +29,7 @@
 #define AAC_INT_MODE_MSI		(1<<1)
 #define AAC_INT_MODE_AIF		(1<<2)
 #define AAC_INT_MODE_SYNC		(1<<3)
+#define AAC_INT_MODE_MSIX		(1<<16)
 
 #define AAC_INT_ENABLE_TYPE1_INTX	0xfffffffb
 #define AAC_INT_ENABLE_TYPE1_MSIX	0xfffffffa
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 54195a1..f78cc94 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -63,7 +63,7 @@
 	struct fib *fibptr;
 	struct hw_fib * hw_fib = (struct hw_fib *)0;
 	dma_addr_t hw_fib_pa = (dma_addr_t)0LL;
-	unsigned size;
+	unsigned int size, osize;
 	int retval;
 
 	if (dev->in_reset) {
@@ -87,7 +87,8 @@
 	 *	will not overrun the buffer when we copy the memory. Return
 	 *	an error if we would.
 	 */
-	size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr);
+	osize = size = le16_to_cpu(kfib->header.Size) +
+		sizeof(struct aac_fibhdr);
 	if (size < le16_to_cpu(kfib->header.SenderSize))
 		size = le16_to_cpu(kfib->header.SenderSize);
 	if (size > dev->max_fib_size) {
@@ -118,6 +119,14 @@
 		goto cleanup;
 	}
 
+	/* Sanity check the second copy */
+	if ((osize != le16_to_cpu(kfib->header.Size) +
+		sizeof(struct aac_fibhdr))
+		|| (size < le16_to_cpu(kfib->header.SenderSize))) {
+		retval = -EINVAL;
+		goto cleanup;
+	}
+
 	if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) {
 		aac_adapter_interrupt(dev);
 		/*
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 0e954e3..26d38b1 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -37,6 +37,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
+#include <linux/delay.h>
 #include <linux/completion.h>
 #include <linux/mm.h>
 #include <scsi/scsi_host.h>
@@ -47,6 +48,24 @@
 	.irq_mod = 1
 };
 
+static inline int aac_is_msix_mode(struct aac_dev *dev)
+{
+	u32 status = 0;
+
+	if (dev->pdev->device == PMC_DEVICE_S6 ||
+		dev->pdev->device == PMC_DEVICE_S7 ||
+		dev->pdev->device == PMC_DEVICE_S8) {
+		status = src_readl(dev, MUnit.OMR);
+	}
+	return (status & AAC_INT_MODE_MSIX);
+}
+
+static inline void aac_change_to_intx(struct aac_dev *dev)
+{
+	aac_src_access_devreg(dev, AAC_DISABLE_MSIX);
+	aac_src_access_devreg(dev, AAC_ENABLE_INTX);
+}
+
 static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign)
 {
 	unsigned char *base;
@@ -425,6 +444,15 @@
 	dev->comm_interface = AAC_COMM_PRODUCER;
 	dev->raw_io_interface = dev->raw_io_64 = 0;
 
+
+	/*
+	 * Enable INTX mode, if not done already Enabled
+	 */
+	if (aac_is_msix_mode(dev)) {
+		aac_change_to_intx(dev);
+		dev_info(&dev->pdev->dev, "Changed firmware to INTX mode");
+	}
+
 	if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
 		0, 0, 0, 0, 0, 0,
 		status+0, status+1, status+2, status+3, NULL)) &&
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 4cbf549..8c758c3 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -611,10 +611,10 @@
 					}
 					return -EFAULT;
 				}
-				/* We used to udelay() here but that absorbed
-				 * a CPU when a timeout occured. Not very
-				 * useful. */
-				cpu_relax();
+				/*
+				 * Allow other processes / CPUS to use core
+				 */
+				schedule();
 			}
 		} else if (down_interruptible(&fibptr->event_wait)) {
 			/* Do nothing ... satisfy
@@ -1970,6 +1970,10 @@
 		if (difference <= 0)
 			difference = 1;
 		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (kthread_should_stop())
+			break;
+
 		schedule_timeout(difference);
 
 		if (kthread_should_stop())
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index bc0203f..e415e1c 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -413,16 +413,23 @@
 	u32 status = src_readl(dev, MUnit.OMR);
 
 	/*
-	 *	Check to see if the board failed any self tests.
-	 */
-	if (unlikely(status & SELF_TEST_FAILED))
-		return -1;
-
-	/*
 	 *	Check to see if the board panic'd.
 	 */
 	if (unlikely(status & KERNEL_PANIC))
-		return (status >> 16) & 0xFF;
+		goto err_blink;
+
+	/*
+	 *	Check to see if the board failed any self tests.
+	 */
+	if (unlikely(status & SELF_TEST_FAILED))
+		goto err_out;
+
+	/*
+	 *	Check to see if the board failed any self tests.
+	 */
+	if (unlikely(status & MONITOR_PANIC))
+		goto err_out;
+
 	/*
 	 *	Wait for the adapter to be up and running.
 	 */
@@ -432,6 +439,12 @@
 	 *	Everything is OK
 	 */
 	return 0;
+
+err_out:
+	return -1;
+
+err_blink:
+	return (status > 16) & 0xFF;
 }
 
 /**
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 333db59..7aa01c1 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -2297,15 +2297,23 @@
 	}
 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
 		unsigned char *ver_addr;
-		int32_t user_len, cnt2end;
+		uint32_t user_len;
+		int32_t cnt2end;
 		uint8_t *pQbuffer, *ptmpuserbuffer;
+
+		user_len = pcmdmessagefld->cmdmessage.Length;
+		if (user_len > ARCMSR_API_DATA_BUFLEN) {
+			retvalue = ARCMSR_MESSAGE_FAIL;
+			goto message_out;
+		}
+
 		ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC);
 		if (!ver_addr) {
 			retvalue = ARCMSR_MESSAGE_FAIL;
 			goto message_out;
 		}
 		ptmpuserbuffer = ver_addr;
-		user_len = pcmdmessagefld->cmdmessage.Length;
+
 		memcpy(ptmpuserbuffer,
 			pcmdmessagefld->messagedatabuffer, user_len);
 		spin_lock_irqsave(&acb->wqbuffer_lock, flags);
@@ -2537,18 +2545,9 @@
 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
 	struct CommandControlBlock *ccb;
 	int target = cmd->device->id;
-	int lun = cmd->device->lun;
-	uint8_t scsicmd = cmd->cmnd[0];
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 	cmd->result = 0;
-	if ((scsicmd == SYNCHRONIZE_CACHE) ||(scsicmd == SEND_DIAGNOSTIC)){
-		if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
-    			cmd->result = (DID_NO_CONNECT << 16);
-		}
-		cmd->scsi_done(cmd);
-		return 0;
-	}
 	if (target == 16) {
 		/* virtual device for iop message transfer */
 		arcmsr_handle_virtual_command(acb, cmd);
@@ -2664,7 +2663,7 @@
 	if (!arcmsr_hbaB_wait_msgint_ready(acb)) {
 		printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \
 			miscellaneous data' timeout \n", acb->host->host_no);
-		return false;
+		goto err_free_dma;
 	}
 	count = 8;
 	while (count){
@@ -2694,19 +2693,23 @@
 		acb->firm_model,
 		acb->firm_version);
 
-	acb->signature = readl(&reg->message_rwbuffer[1]);
+	acb->signature = readl(&reg->message_rwbuffer[0]);
 	/*firm_signature,1,00-03*/
-	acb->firm_request_len = readl(&reg->message_rwbuffer[2]);
+	acb->firm_request_len = readl(&reg->message_rwbuffer[1]);
 	/*firm_request_len,1,04-07*/
-	acb->firm_numbers_queue = readl(&reg->message_rwbuffer[3]);
+	acb->firm_numbers_queue = readl(&reg->message_rwbuffer[2]);
 	/*firm_numbers_queue,2,08-11*/
-	acb->firm_sdram_size = readl(&reg->message_rwbuffer[4]);
+	acb->firm_sdram_size = readl(&reg->message_rwbuffer[3]);
 	/*firm_sdram_size,3,12-15*/
-	acb->firm_hd_channels = readl(&reg->message_rwbuffer[5]);
+	acb->firm_hd_channels = readl(&reg->message_rwbuffer[4]);
 	/*firm_ide_channels,4,16-19*/
 	acb->firm_cfg_version = readl(&reg->message_rwbuffer[25]);  /*firm_cfg_version,25,100-103*/
 	/*firm_ide_channels,4,16-19*/
 	return true;
+err_free_dma:
+	dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize,
+			acb->dma_coherent2, acb->dma_coherent_handle2);
+	return false;
 }
 
 static bool arcmsr_hbaC_get_config(struct AdapterControlBlock *pACB)
@@ -2880,15 +2883,15 @@
 		iop_device_map++;
 		count--;
 	}
-	acb->signature = readl(&reg->msgcode_rwbuffer[1]);
+	acb->signature = readl(&reg->msgcode_rwbuffer[0]);
 	/*firm_signature,1,00-03*/
-	acb->firm_request_len = readl(&reg->msgcode_rwbuffer[2]);
+	acb->firm_request_len = readl(&reg->msgcode_rwbuffer[1]);
 	/*firm_request_len,1,04-07*/
-	acb->firm_numbers_queue = readl(&reg->msgcode_rwbuffer[3]);
+	acb->firm_numbers_queue = readl(&reg->msgcode_rwbuffer[2]);
 	/*firm_numbers_queue,2,08-11*/
-	acb->firm_sdram_size = readl(&reg->msgcode_rwbuffer[4]);
+	acb->firm_sdram_size = readl(&reg->msgcode_rwbuffer[3]);
 	/*firm_sdram_size,3,12-15*/
-	acb->firm_hd_channels = readl(&reg->msgcode_rwbuffer[5]);
+	acb->firm_hd_channels = readl(&reg->msgcode_rwbuffer[4]);
 	/*firm_hd_channels,4,16-19*/
 	acb->firm_cfg_version = readl(&reg->msgcode_rwbuffer[25]);
 	pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index fa09d4b..2b456ca 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -1181,8 +1181,9 @@
 
 /* Get sense key string or NULL if not available */
 const char *
-scsi_sense_key_string(unsigned char key) {
-	if (key <= 0xE)
+scsi_sense_key_string(unsigned char key)
+{
+	if (key < ARRAY_SIZE(snstext))
 		return snstext[key];
 	return NULL;
 }
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index c11cd19..a8ac4c0 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -34,7 +34,6 @@
 								   sectors
 								*/
 
-#define NUM_RRQ_ENTRY    16     /* for master issued cmds */
 #define MAX_RHT_PER_CONTEXT (PAGE_SIZE / sizeof(struct sisl_rht_entry))
 
 /* AFU command retry limit */
@@ -48,9 +47,12 @@
 							   index derivation
 							 */
 
-#define CXLFLASH_MAX_CMDS               16
+#define CXLFLASH_MAX_CMDS               256
 #define CXLFLASH_MAX_CMDS_PER_LUN       CXLFLASH_MAX_CMDS
 
+/* RRQ for master issued cmds */
+#define NUM_RRQ_ENTRY                   CXLFLASH_MAX_CMDS
+
 
 static inline void check_sizes(void)
 {
@@ -149,7 +151,7 @@
 struct afu {
 	/* Stuff requiring alignment go first. */
 
-	u64 rrq_entry[NUM_RRQ_ENTRY];	/* 128B RRQ */
+	u64 rrq_entry[NUM_RRQ_ENTRY];	/* 2K RRQ */
 	/*
 	 * Command & data for AFU commands.
 	 */
@@ -165,6 +167,8 @@
 	struct sisl_host_map __iomem *host_map;		/* MC host map */
 	struct sisl_ctrl_map __iomem *ctrl_map;		/* MC control map */
 
+	struct kref mapcount;
+
 	ctx_hndl_t ctx_hndl;	/* master's context handle */
 	u64 *hrrq_start;
 	u64 *hrrq_end;
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 1e5bf0c..0b09673 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -289,7 +289,7 @@
 		atomic64_set(&afu->room, room);
 		if (room)
 			goto write_rrin;
-		udelay(nretry);
+		udelay(1 << nretry);
 	} while (nretry++ < MC_ROOM_RETRY_CNT);
 
 	pr_err("%s: no cmd_room to send reset\n", __func__);
@@ -303,7 +303,7 @@
 		if (rrin != 0x1)
 			break;
 		/* Double delay each time */
-		udelay(2 << nretry);
+		udelay(1 << nretry);
 	} while (nretry++ < MC_ROOM_RETRY_CNT);
 }
 
@@ -338,7 +338,7 @@
 			atomic64_set(&afu->room, room);
 			if (room)
 				goto write_ioarrin;
-			udelay(nretry);
+			udelay(1 << nretry);
 		} while (nretry++ < MC_ROOM_RETRY_CNT);
 
 		dev_err(dev, "%s: no cmd_room to send 0x%X\n",
@@ -352,7 +352,7 @@
 		 * afu->room.
 		 */
 		if (nretry++ < MC_ROOM_RETRY_CNT) {
-			udelay(nretry);
+			udelay(1 << nretry);
 			goto retry;
 		}
 
@@ -368,6 +368,7 @@
 
 no_room:
 	afu->read_room = true;
+	kref_get(&cfg->afu->mapcount);
 	schedule_work(&cfg->work_q);
 	rc = SCSI_MLQUEUE_HOST_BUSY;
 	goto out;
@@ -473,6 +474,16 @@
 	return rc;
 }
 
+static void afu_unmap(struct kref *ref)
+{
+	struct afu *afu = container_of(ref, struct afu, mapcount);
+
+	if (likely(afu->afu_map)) {
+		cxl_psa_unmap((void __iomem *)afu->afu_map);
+		afu->afu_map = NULL;
+	}
+}
+
 /**
  * cxlflash_driver_info() - information handler for this host driver
  * @host:	SCSI host associated with device.
@@ -503,6 +514,7 @@
 	ulong lock_flags;
 	short lflag = 0;
 	int rc = 0;
+	int kref_got = 0;
 
 	dev_dbg_ratelimited(dev, "%s: (scp=%p) %d/%d/%d/%llu "
 			    "cdb=(%08X-%08X-%08X-%08X)\n",
@@ -547,6 +559,9 @@
 		goto out;
 	}
 
+	kref_get(&cfg->afu->mapcount);
+	kref_got = 1;
+
 	cmd->rcb.ctx_id = afu->ctx_hndl;
 	cmd->rcb.port_sel = port_sel;
 	cmd->rcb.lun_id = lun_to_lunid(scp->device->lun);
@@ -587,6 +602,8 @@
 	}
 
 out:
+	if (kref_got)
+		kref_put(&afu->mapcount, afu_unmap);
 	pr_devel("%s: returning rc=%d\n", __func__, rc);
 	return rc;
 }
@@ -632,20 +649,36 @@
  * @cfg:	Internal structure associated with the host.
  *
  * Safe to call with AFU in a partially allocated/initialized state.
+ *
+ * Cleans up all state associated with the command queue, and unmaps
+ * the MMIO space.
+ *
+ *  - complete() will take care of commands we initiated (they'll be checked
+ *  in as part of the cleanup that occurs after the completion)
+ *
+ *  - cmd_checkin() will take care of entries that we did not initiate and that
+ *  have not (and will not) complete because they are sitting on a [now stale]
+ *  hardware queue
  */
 static void stop_afu(struct cxlflash_cfg *cfg)
 {
 	int i;
 	struct afu *afu = cfg->afu;
+	struct afu_cmd *cmd;
 
 	if (likely(afu)) {
-		for (i = 0; i < CXLFLASH_NUM_CMDS; i++)
-			complete(&afu->cmd[i].cevent);
+		for (i = 0; i < CXLFLASH_NUM_CMDS; i++) {
+			cmd = &afu->cmd[i];
+			complete(&cmd->cevent);
+			if (!atomic_read(&cmd->free))
+				cmd_checkin(cmd);
+		}
 
 		if (likely(afu->afu_map)) {
 			cxl_psa_unmap((void __iomem *)afu->afu_map);
 			afu->afu_map = NULL;
 		}
+		kref_put(&afu->mapcount, afu_unmap);
 	}
 }
 
@@ -731,8 +764,8 @@
 		scsi_remove_host(cfg->host);
 		/* fall through */
 	case INIT_STATE_AFU:
-		term_afu(cfg);
 		cancel_work_sync(&cfg->work_q);
+		term_afu(cfg);
 	case INIT_STATE_PCI:
 		pci_release_regions(cfg->dev);
 		pci_disable_device(pdev);
@@ -963,6 +996,8 @@
 	do {
 		msleep(delay_us / 1000);
 		status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
+		if (status == U64_MAX)
+			nretry /= 2;
 	} while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_ONLINE &&
 		 nretry--);
 
@@ -994,6 +1029,8 @@
 	do {
 		msleep(delay_us / 1000);
 		status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
+		if (status == U64_MAX)
+			nretry /= 2;
 	} while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_OFFLINE &&
 		 nretry--);
 
@@ -1104,15 +1141,15 @@
 	{SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR},
 	{SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST},
 	{SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0},
-	{SISL_ASTATUS_FC0_LINK_UP, "link up", 0, SCAN_HOST},
+	{SISL_ASTATUS_FC0_LINK_UP, "link up", 0, 0},
 	{SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET},
 	{SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0},
 	{SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET},
-	{SISL_ASTATUS_FC1_LOGI_R, "login timed out, retrying", 1, 0},
+	{SISL_ASTATUS_FC1_LOGI_R, "login timed out, retrying", 1, LINK_RESET},
 	{SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR},
 	{SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST},
 	{SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0},
-	{SISL_ASTATUS_FC1_LINK_UP, "link up", 1, SCAN_HOST},
+	{SISL_ASTATUS_FC1_LINK_UP, "link up", 1, 0},
 	{0x0, "", 0, 0}		/* terminator */
 };
 
@@ -1316,6 +1353,7 @@
 				__func__, port);
 			cfg->lr_state = LINK_RESET_REQUIRED;
 			cfg->lr_port = port;
+			kref_get(&cfg->afu->mapcount);
 			schedule_work(&cfg->work_q);
 		}
 
@@ -1336,6 +1374,7 @@
 
 		if (info->action & SCAN_HOST) {
 			atomic_inc(&cfg->scan_host_needed);
+			kref_get(&cfg->afu->mapcount);
 			schedule_work(&cfg->work_q);
 		}
 	}
@@ -1731,6 +1770,7 @@
 		rc = -ENOMEM;
 		goto err1;
 	}
+	kref_init(&afu->mapcount);
 
 	/* No byte reverse on reading afu_version or string will be backwards */
 	reg = readq(&afu->afu_map->global.regs.afu_version);
@@ -1765,8 +1805,7 @@
 	return rc;
 
 err2:
-	cxl_psa_unmap((void __iomem *)afu->afu_map);
-	afu->afu_map = NULL;
+	kref_put(&afu->mapcount, afu_unmap);
 err1:
 	term_mc(cfg, UNDO_START);
 	goto out;
@@ -1927,6 +1966,11 @@
  * cxlflash_eh_host_reset_handler() - reset the host adapter
  * @scp:	SCSI command from stack identifying host.
  *
+ * Following a reset, the state is evaluated again in case an EEH occurred
+ * during the reset. In such a scenario, the host reset will either yield
+ * until the EEH recovery is complete or return success or failure based
+ * upon the current device state.
+ *
  * Return:
  *	SUCCESS as defined in scsi/scsi.h
  *	FAILED as defined in scsi/scsi.h
@@ -1958,7 +2002,8 @@
 		} else
 			cfg->state = STATE_NORMAL;
 		wake_up_all(&cfg->reset_waitq);
-		break;
+		ssleep(1);
+		/* fall through */
 	case STATE_RESET:
 		wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
 		if (cfg->state == STATE_NORMAL)
@@ -2114,6 +2159,16 @@
 	rc = kstrtouint(buf, 10, &lun_mode);
 	if (!rc && (lun_mode < 5) && (lun_mode != afu->internal_lun)) {
 		afu->internal_lun = lun_mode;
+
+		/*
+		 * When configured for internal LUN, there is only one channel,
+		 * channel number 0, else there will be 2 (default).
+		 */
+		if (afu->internal_lun)
+			shost->max_channel = 0;
+		else
+			shost->max_channel = NUM_FC_PORTS - 1;
+
 		afu_reset(cfg);
 		scsi_scan_host(cfg->host);
 	}
@@ -2260,7 +2315,7 @@
 	.eh_device_reset_handler = cxlflash_eh_device_reset_handler,
 	.eh_host_reset_handler = cxlflash_eh_host_reset_handler,
 	.change_queue_depth = cxlflash_change_queue_depth,
-	.cmd_per_lun = 16,
+	.cmd_per_lun = CXLFLASH_MAX_CMDS_PER_LUN,
 	.can_queue = CXLFLASH_MAX_CMDS,
 	.this_id = -1,
 	.sg_tablesize = SG_NONE,	/* No scatter gather support */
@@ -2274,6 +2329,7 @@
  * Device dependent values
  */
 static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS };
+static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS };
 
 /*
  * PCI device binding table
@@ -2281,6 +2337,8 @@
 static struct pci_device_id cxlflash_pci_table[] = {
 	{PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CORSA,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, (kernel_ulong_t)&dev_corsa_vals},
+	{PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_FLASH_GT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, (kernel_ulong_t)&dev_flash_gt_vals},
 	{}
 };
 
@@ -2339,6 +2397,7 @@
 
 	if (atomic_dec_if_positive(&cfg->scan_host_needed) >= 0)
 		scsi_scan_host(cfg->host);
+	kref_put(&afu->mapcount, afu_unmap);
 }
 
 /**
@@ -2485,6 +2544,9 @@
  * @pdev:	PCI device struct.
  * @state:	PCI channel state.
  *
+ * When an EEH occurs during an active reset, wait until the reset is
+ * complete and then take action based upon the device state.
+ *
  * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
  */
 static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev,
@@ -2498,6 +2560,10 @@
 
 	switch (state) {
 	case pci_channel_io_frozen:
+		wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
+		if (cfg->state == STATE_FAILTERM)
+			return PCI_ERS_RESULT_DISCONNECT;
+
 		cfg->state = STATE_RESET;
 		scsi_block_requests(cfg->host);
 		drain_ioctls(cfg);
diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h
index 6032456..3d2d606 100644
--- a/drivers/scsi/cxlflash/main.h
+++ b/drivers/scsi/cxlflash/main.h
@@ -24,8 +24,8 @@
 #define CXLFLASH_ADAPTER_NAME	"IBM POWER CXL Flash Adapter"
 #define CXLFLASH_DRIVER_DATE	"(August 13, 2015)"
 
-#define PCI_DEVICE_ID_IBM_CORSA	0x04F0
-#define CXLFLASH_SUBS_DEV_ID	0x04F0
+#define PCI_DEVICE_ID_IBM_CORSA		0x04F0
+#define PCI_DEVICE_ID_IBM_FLASH_GT	0x0600
 
 /* Since there is only one target, make it 0 */
 #define CXLFLASH_TARGET		0
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c
index cac2e6a..babe7cc 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -1380,7 +1380,7 @@
 	}
 
 	ctxid = cxl_process_element(ctx);
-	if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) {
+	if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
 		dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid);
 		rc = -EPERM;
 		goto err2;
@@ -1508,7 +1508,7 @@
 	}
 
 	ctxid = cxl_process_element(ctx);
-	if (unlikely((ctxid > MAX_CONTEXT) || (ctxid < 0))) {
+	if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
 		dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid);
 		rc = -EPERM;
 		goto err1;
@@ -1590,6 +1590,13 @@
  * place at the same time and the failure was due to CXL services being
  * unable to keep up.
  *
+ * As this routine is called on ioctl context, it holds the ioctl r/w
+ * semaphore that is used to drain ioctls in recovery scenarios. The
+ * implementation to achieve the pacing described above (a local mutex)
+ * requires that the ioctl r/w semaphore be dropped and reacquired to
+ * avoid a 3-way deadlock when multiple process recoveries operate in
+ * parallel.
+ *
  * Because a user can detect an error condition before the kernel, it is
  * quite possible for this routine to act as the kernel's EEH detection
  * source (MMIO read of mbox_r). Because of this, there is a window of
@@ -1617,9 +1624,17 @@
 	int rc = 0;
 
 	atomic_inc(&cfg->recovery_threads);
+	up_read(&cfg->ioctl_rwsem);
 	rc = mutex_lock_interruptible(mutex);
+	down_read(&cfg->ioctl_rwsem);
 	if (rc)
 		goto out;
+	rc = check_state(cfg);
+	if (rc) {
+		dev_err(dev, "%s: Failed state! rc=%d\n", __func__, rc);
+		rc = -ENODEV;
+		goto out;
+	}
 
 	dev_dbg(dev, "%s: reason 0x%016llX rctxid=%016llX\n",
 		__func__, recover->reason, rctxid);
diff --git a/drivers/scsi/cxlflash/vlun.c b/drivers/scsi/cxlflash/vlun.c
index a53f583..50f8e93 100644
--- a/drivers/scsi/cxlflash/vlun.c
+++ b/drivers/scsi/cxlflash/vlun.c
@@ -1008,6 +1008,8 @@
 	virt->last_lba = last_lba;
 	virt->rsrc_handle = rsrc_handle;
 
+	if (lli->port_sel == BOTH_PORTS)
+		virt->hdr.return_flags |= DK_CXLFLASH_ALL_PORTS_ACTIVE;
 out:
 	if (likely(ctxi))
 		put_context(ctxi);
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 67669a9..f3a3331 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -954,8 +954,8 @@
 	skb_put(skb, len);
 	pa = pci_map_single(fnic->pdev, skb->data, len, PCI_DMA_FROMDEVICE);
 
-	r = pci_dma_mapping_error(fnic->pdev, pa);
-	if (r) {
+	if (pci_dma_mapping_error(fnic->pdev, pa)) {
+		r = -ENOMEM;
 		printk(KERN_ERR "PCI mapping failed with error %d\n", r);
 		goto free_skb;
 	}
@@ -1093,8 +1093,8 @@
 
 	pa = pci_map_single(fnic->pdev, eth_hdr, tot_len, PCI_DMA_TODEVICE);
 
-	ret = pci_dma_mapping_error(fnic->pdev, pa);
-	if (ret) {
+	if (pci_dma_mapping_error(fnic->pdev, pa)) {
+		ret = -ENOMEM;
 		printk(KERN_ERR "DMA map failed with error %d\n", ret);
 		goto free_skb_on_err;
 	}
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a386036..e9ce74a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3930,6 +3930,70 @@
 	return rc;
 }
 
+static bool hpsa_is_disk_spare(struct ctlr_info *h, u8 *lunaddrbytes)
+{
+	struct bmic_identify_physical_device *id_phys;
+	bool is_spare = false;
+	int rc;
+
+	id_phys = kzalloc(sizeof(*id_phys), GFP_KERNEL);
+	if (!id_phys)
+		return false;
+
+	rc = hpsa_bmic_id_physical_device(h,
+					lunaddrbytes,
+					GET_BMIC_DRIVE_NUMBER(lunaddrbytes),
+					id_phys, sizeof(*id_phys));
+	if (rc == 0)
+		is_spare = (id_phys->more_flags >> 6) & 0x01;
+
+	kfree(id_phys);
+	return is_spare;
+}
+
+#define RPL_DEV_FLAG_NON_DISK                           0x1
+#define RPL_DEV_FLAG_UNCONFIG_DISK_REPORTING_SUPPORTED  0x2
+#define RPL_DEV_FLAG_UNCONFIG_DISK                      0x4
+
+#define BMIC_DEVICE_TYPE_ENCLOSURE  6
+
+static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes,
+				struct ext_report_lun_entry *rle)
+{
+	u8 device_flags;
+	u8 device_type;
+
+	if (!MASKED_DEVICE(lunaddrbytes))
+		return false;
+
+	device_flags = rle->device_flags;
+	device_type = rle->device_type;
+
+	if (device_flags & RPL_DEV_FLAG_NON_DISK) {
+		if (device_type == BMIC_DEVICE_TYPE_ENCLOSURE)
+			return false;
+		return true;
+	}
+
+	if (!(device_flags & RPL_DEV_FLAG_UNCONFIG_DISK_REPORTING_SUPPORTED))
+		return false;
+
+	if (device_flags & RPL_DEV_FLAG_UNCONFIG_DISK)
+		return false;
+
+	/*
+	 * Spares may be spun down, we do not want to
+	 * do an Inquiry to a RAID set spare drive as
+	 * that would have them spun up, that is a
+	 * performance hit because I/O to the RAID device
+	 * stops while the spin up occurs which can take
+	 * over 50 seconds.
+	 */
+	if (hpsa_is_disk_spare(h, lunaddrbytes))
+		return true;
+
+	return false;
+}
 
 static void hpsa_update_scsi_devices(struct ctlr_info *h)
 {
@@ -4023,6 +4087,7 @@
 		u8 *lunaddrbytes, is_OBDR = 0;
 		int rc = 0;
 		int phys_dev_index = i - (raid_ctlr_position == 0);
+		bool skip_device = false;
 
 		physical_device = i < nphysicals + (raid_ctlr_position == 0);
 
@@ -4030,10 +4095,15 @@
 		lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
 			i, nphysicals, nlogicals, physdev_list, logdev_list);
 
-		/* skip masked non-disk devices */
-		if (MASKED_DEVICE(lunaddrbytes) && physical_device &&
-			(physdev_list->LUN[phys_dev_index].device_flags & 0x01))
-			continue;
+		/*
+		 * Skip over some devices such as a spare.
+		 */
+		if (!tmpdevice->external && physical_device) {
+			skip_device = hpsa_skip_device(h, lunaddrbytes,
+					&physdev_list->LUN[phys_dev_index]);
+			if (skip_device)
+				continue;
+		}
 
 		/* Get device type, vendor, model, device id */
 		rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice,
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 6aa317c..1f9f9e5 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -717,7 +717,6 @@
 	spin_lock_irqsave(vhost->host->host_lock, flags);
 	vhost->state = IBMVFC_NO_CRQ;
 	vhost->logged_in = 0;
-	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
 
 	/* Clean out the queue */
 	memset(crq->msgs, 0, PAGE_SIZE);
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 43ac626..7a58128 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -10095,6 +10095,7 @@
 		ioa_cfg->intr_flag = IPR_USE_MSI;
 	else {
 		ioa_cfg->intr_flag = IPR_USE_LSI;
+		ioa_cfg->clear_isr = 1;
 		ioa_cfg->nvectors = 1;
 		dev_info(&pdev->dev, "Cannot enable MSI.\n");
 	}
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 6bffd91..c1ccf1e 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -560,8 +560,12 @@
 	WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
 	task->state = state;
 
-	if (!list_empty(&task->running))
+	spin_lock_bh(&conn->taskqueuelock);
+	if (!list_empty(&task->running)) {
+		pr_debug_once("%s while task on list", __func__);
 		list_del_init(&task->running);
+	}
+	spin_unlock_bh(&conn->taskqueuelock);
 
 	if (conn->task == task)
 		conn->task = NULL;
@@ -783,7 +787,9 @@
 		if (session->tt->xmit_task(task))
 			goto free_task;
 	} else {
+		spin_lock_bh(&conn->taskqueuelock);
 		list_add_tail(&task->running, &conn->mgmtqueue);
+		spin_unlock_bh(&conn->taskqueuelock);
 		iscsi_conn_queue_work(conn);
 	}
 
@@ -1474,8 +1480,10 @@
 	 * this may be on the requeue list already if the xmit_task callout
 	 * is handling the r2ts while we are adding new ones
 	 */
+	spin_lock_bh(&conn->taskqueuelock);
 	if (list_empty(&task->running))
 		list_add_tail(&task->running, &conn->requeue);
+	spin_unlock_bh(&conn->taskqueuelock);
 	iscsi_conn_queue_work(conn);
 }
 EXPORT_SYMBOL_GPL(iscsi_requeue_task);
@@ -1512,22 +1520,26 @@
 	 * only have one nop-out as a ping from us and targets should not
 	 * overflow us with nop-ins
 	 */
+	spin_lock_bh(&conn->taskqueuelock);
 check_mgmt:
 	while (!list_empty(&conn->mgmtqueue)) {
 		conn->task = list_entry(conn->mgmtqueue.next,
 					 struct iscsi_task, running);
 		list_del_init(&conn->task->running);
+		spin_unlock_bh(&conn->taskqueuelock);
 		if (iscsi_prep_mgmt_task(conn, conn->task)) {
 			/* regular RX path uses back_lock */
 			spin_lock_bh(&conn->session->back_lock);
 			__iscsi_put_task(conn->task);
 			spin_unlock_bh(&conn->session->back_lock);
 			conn->task = NULL;
+			spin_lock_bh(&conn->taskqueuelock);
 			continue;
 		}
 		rc = iscsi_xmit_task(conn);
 		if (rc)
 			goto done;
+		spin_lock_bh(&conn->taskqueuelock);
 	}
 
 	/* process pending command queue */
@@ -1535,19 +1547,24 @@
 		conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task,
 					running);
 		list_del_init(&conn->task->running);
+		spin_unlock_bh(&conn->taskqueuelock);
 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
 			fail_scsi_task(conn->task, DID_IMM_RETRY);
+			spin_lock_bh(&conn->taskqueuelock);
 			continue;
 		}
 		rc = iscsi_prep_scsi_cmd_pdu(conn->task);
 		if (rc) {
 			if (rc == -ENOMEM || rc == -EACCES) {
+				spin_lock_bh(&conn->taskqueuelock);
 				list_add_tail(&conn->task->running,
 					      &conn->cmdqueue);
 				conn->task = NULL;
+				spin_unlock_bh(&conn->taskqueuelock);
 				goto done;
 			} else
 				fail_scsi_task(conn->task, DID_ABORT);
+			spin_lock_bh(&conn->taskqueuelock);
 			continue;
 		}
 		rc = iscsi_xmit_task(conn);
@@ -1558,6 +1575,7 @@
 		 * we need to check the mgmt queue for nops that need to
 		 * be sent to aviod starvation
 		 */
+		spin_lock_bh(&conn->taskqueuelock);
 		if (!list_empty(&conn->mgmtqueue))
 			goto check_mgmt;
 	}
@@ -1577,12 +1595,15 @@
 		conn->task = task;
 		list_del_init(&conn->task->running);
 		conn->task->state = ISCSI_TASK_RUNNING;
+		spin_unlock_bh(&conn->taskqueuelock);
 		rc = iscsi_xmit_task(conn);
 		if (rc)
 			goto done;
+		spin_lock_bh(&conn->taskqueuelock);
 		if (!list_empty(&conn->mgmtqueue))
 			goto check_mgmt;
 	}
+	spin_unlock_bh(&conn->taskqueuelock);
 	spin_unlock_bh(&conn->session->frwd_lock);
 	return -ENODATA;
 
@@ -1738,7 +1759,9 @@
 			goto prepd_reject;
 		}
 	} else {
+		spin_lock_bh(&conn->taskqueuelock);
 		list_add_tail(&task->running, &conn->cmdqueue);
+		spin_unlock_bh(&conn->taskqueuelock);
 		iscsi_conn_queue_work(conn);
 	}
 
@@ -2900,6 +2923,7 @@
 	INIT_LIST_HEAD(&conn->mgmtqueue);
 	INIT_LIST_HEAD(&conn->cmdqueue);
 	INIT_LIST_HEAD(&conn->requeue);
+	spin_lock_init(&conn->taskqueuelock);
 	INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
 
 	/* allocate login_task used for the login/text sequences */
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 9c706d8..6f5e272 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -218,7 +218,7 @@
 		task->num_scatter = qc->n_elem;
 	} else {
 		for_each_sg(qc->sg, sg, qc->n_elem, si)
-			xfer += sg->length;
+			xfer += sg_dma_len(sg);
 
 		task->total_xfer_len = xfer;
 		task->num_scatter = si;
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index b0e6fe4..80d3c74 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -72,6 +72,7 @@
 void lpfc_retry_pport_discovery(struct lpfc_hba *);
 void lpfc_release_rpi(struct lpfc_hba *, struct lpfc_vport *, uint16_t);
 
+void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index b6fa257..0e6aaef 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -455,9 +455,9 @@
 lpfc_issue_reg_vfi(struct lpfc_vport *vport)
 {
 	struct lpfc_hba  *phba = vport->phba;
-	LPFC_MBOXQ_t *mboxq;
+	LPFC_MBOXQ_t *mboxq = NULL;
 	struct lpfc_nodelist *ndlp;
-	struct lpfc_dmabuf *dmabuf;
+	struct lpfc_dmabuf *dmabuf = NULL;
 	int rc = 0;
 
 	/* move forward in case of SLI4 FC port loopback test and pt2pt mode */
@@ -471,25 +471,33 @@
 		}
 	}
 
-	dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-	if (!dmabuf) {
-		rc = -ENOMEM;
-		goto fail;
-	}
-	dmabuf->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &dmabuf->phys);
-	if (!dmabuf->virt) {
-		rc = -ENOMEM;
-		goto fail_free_dmabuf;
-	}
-
 	mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!mboxq) {
 		rc = -ENOMEM;
-		goto fail_free_coherent;
+		goto fail;
 	}
+
+	/* Supply CSP's only if we are fabric connect or pt-to-pt connect */
+	if ((vport->fc_flag & FC_FABRIC) || (vport->fc_flag & FC_PT2PT)) {
+		dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+		if (!dmabuf) {
+			rc = -ENOMEM;
+			goto fail;
+		}
+		dmabuf->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &dmabuf->phys);
+		if (!dmabuf->virt) {
+			rc = -ENOMEM;
+			goto fail;
+		}
+		memcpy(dmabuf->virt, &phba->fc_fabparam,
+		       sizeof(struct serv_parm));
+	}
+
 	vport->port_state = LPFC_FABRIC_CFG_LINK;
-	memcpy(dmabuf->virt, &phba->fc_fabparam, sizeof(vport->fc_sparam));
-	lpfc_reg_vfi(mboxq, vport, dmabuf->phys);
+	if (dmabuf)
+		lpfc_reg_vfi(mboxq, vport, dmabuf->phys);
+	else
+		lpfc_reg_vfi(mboxq, vport, 0);
 
 	mboxq->mbox_cmpl = lpfc_mbx_cmpl_reg_vfi;
 	mboxq->vport = vport;
@@ -497,17 +505,19 @@
 	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
 	if (rc == MBX_NOT_FINISHED) {
 		rc = -ENXIO;
-		goto fail_free_mbox;
+		goto fail;
 	}
 	return 0;
 
-fail_free_mbox:
-	mempool_free(mboxq, phba->mbox_mem_pool);
-fail_free_coherent:
-	lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
-fail_free_dmabuf:
-	kfree(dmabuf);
 fail:
+	if (mboxq)
+		mempool_free(mboxq, phba->mbox_mem_pool);
+	if (dmabuf) {
+		if (dmabuf->virt)
+			lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
+		kfree(dmabuf);
+	}
+
 	lpfc_vport_set_state(vport, FC_VPORT_FAILED);
 	lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
 		"0289 Issue Register VFI failed: Err %d\n", rc);
@@ -711,9 +721,10 @@
 	 * For FC we need to do some special processing because of the SLI
 	 * Port's default settings of the Common Service Parameters.
 	 */
-	if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) {
+	if ((phba->sli_rev == LPFC_SLI_REV4) &&
+	    (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC)) {
 		/* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */
-		if ((phba->sli_rev == LPFC_SLI_REV4) && fabric_param_changed)
+		if (fabric_param_changed)
 			lpfc_unregister_fcf_prep(phba);
 
 		/* This should just update the VFI CSPs*/
@@ -824,13 +835,21 @@
 
 	spin_lock_irq(shost->host_lock);
 	vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+	vport->fc_flag |= FC_PT2PT;
 	spin_unlock_irq(shost->host_lock);
 
-	phba->fc_edtov = FF_DEF_EDTOV;
-	phba->fc_ratov = FF_DEF_RATOV;
+	/* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */
+	if ((phba->sli_rev == LPFC_SLI_REV4) && phba->fc_topology_changed) {
+		lpfc_unregister_fcf_prep(phba);
+
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag &= ~FC_VFI_REGISTERED;
+		spin_unlock_irq(shost->host_lock);
+		phba->fc_topology_changed = 0;
+	}
+
 	rc = memcmp(&vport->fc_portname, &sp->portName,
 		    sizeof(vport->fc_portname));
-	memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
 
 	if (rc >= 0) {
 		/* This side will initiate the PLOGI */
@@ -839,38 +858,14 @@
 		spin_unlock_irq(shost->host_lock);
 
 		/*
-		 * N_Port ID cannot be 0, set our to LocalID the other
-		 * side will be RemoteID.
+		 * N_Port ID cannot be 0, set our Id to LocalID
+		 * the other side will be RemoteID.
 		 */
 
 		/* not equal */
 		if (rc)
 			vport->fc_myDID = PT2PT_LocalID;
 
-		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-		if (!mbox)
-			goto fail;
-
-		lpfc_config_link(phba, mbox);
-
-		mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-		mbox->vport = vport;
-		rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
-		if (rc == MBX_NOT_FINISHED) {
-			mempool_free(mbox, phba->mbox_mem_pool);
-			goto fail;
-		}
-
-		/*
-		 * For SLI4, the VFI/VPI are registered AFTER the
-		 * Nport with the higher WWPN sends the PLOGI with
-		 * an assigned NPortId.
-		 */
-
-		/* not equal */
-		if ((phba->sli_rev == LPFC_SLI_REV4) && rc)
-			lpfc_issue_reg_vfi(vport);
-
 		/* Decrement ndlp reference count indicating that ndlp can be
 		 * safely released when other references to it are done.
 		 */
@@ -912,29 +907,20 @@
 	/* If we are pt2pt with another NPort, force NPIV off! */
 	phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
 
-	spin_lock_irq(shost->host_lock);
-	vport->fc_flag |= FC_PT2PT;
-	spin_unlock_irq(shost->host_lock);
-	/* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */
-	if ((phba->sli_rev == LPFC_SLI_REV4) && phba->fc_topology_changed) {
-		lpfc_unregister_fcf_prep(phba);
+	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!mbox)
+		goto fail;
 
-		/* The FC_VFI_REGISTERED flag will get clear in the cmpl
-		 * handler for unreg_vfi, but if we don't force the
-		 * FC_VFI_REGISTERED flag then the reg_vfi mailbox could be
-		 * built with the update bit set instead of just the vp bit to
-		 * change the Nport ID.  We need to have the vp set and the
-		 * Upd cleared on topology changes.
-		 */
-		spin_lock_irq(shost->host_lock);
-		vport->fc_flag &= ~FC_VFI_REGISTERED;
-		spin_unlock_irq(shost->host_lock);
-		phba->fc_topology_changed = 0;
-		lpfc_issue_reg_vfi(vport);
+	lpfc_config_link(phba, mbox);
+
+	mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
+	mbox->vport = vport;
+	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+	if (rc == MBX_NOT_FINISHED) {
+		mempool_free(mbox, phba->mbox_mem_pool);
+		goto fail;
 	}
 
-	/* Start discovery - this should just do CLEAR_LA */
-	lpfc_disc_start(vport);
 	return 0;
 fail:
 	return -ENXIO;
@@ -1157,6 +1143,7 @@
 	spin_lock_irq(&phba->hbalock);
 	phba->fcf.fcf_flag &= ~FCF_DISCOVERY;
 	spin_unlock_irq(&phba->hbalock);
+
 	lpfc_nlp_put(ndlp);
 
 	if (!lpfc_error_lost_link(irsp)) {
@@ -3576,12 +3563,14 @@
 		} else {
 			buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
 			lpfc_els_free_data(phba, buf_ptr1);
+			elsiocb->context2 = NULL;
 		}
 	}
 
 	if (elsiocb->context3) {
 		buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
 		lpfc_els_free_bpl(phba, buf_ptr);
+		elsiocb->context3 = NULL;
 	}
 	lpfc_sli_release_iocbq(phba, elsiocb);
 	return 0;
@@ -3792,14 +3781,17 @@
 				lpfc_nlp_set_state(vport, ndlp,
 					   NLP_STE_REG_LOGIN_ISSUE);
 			}
+
+			ndlp->nlp_flag |= NLP_REG_LOGIN_SEND;
 			if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
 			    != MBX_NOT_FINISHED)
 				goto out;
-			else
-				/* Decrement the ndlp reference count we
-				 * set for this failed mailbox command.
-				 */
-				lpfc_nlp_put(ndlp);
+
+			/* Decrement the ndlp reference count we
+			 * set for this failed mailbox command.
+			 */
+			lpfc_nlp_put(ndlp);
+			ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
 
 			/* ELS rsp: Cannot issue reg_login for <NPortid> */
 			lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -3856,6 +3848,7 @@
 				 * the routine lpfc_els_free_iocb.
 				 */
 				cmdiocb->context1 = NULL;
+
 	}
 
 	lpfc_els_free_iocb(phba, cmdiocb);
@@ -3898,6 +3891,7 @@
 	IOCB_t *oldcmd;
 	struct lpfc_iocbq *elsiocb;
 	uint8_t *pcmd;
+	struct serv_parm *sp;
 	uint16_t cmdsize;
 	int rc;
 	ELS_PKT *els_pkt_ptr;
@@ -3927,6 +3921,7 @@
 			"Issue ACC:       did:x%x flg:x%x",
 			ndlp->nlp_DID, ndlp->nlp_flag, 0);
 		break;
+	case ELS_CMD_FLOGI:
 	case ELS_CMD_PLOGI:
 		cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t));
 		elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
@@ -3944,10 +3939,34 @@
 
 		*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
 		pcmd += sizeof(uint32_t);
-		memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
+		sp = (struct serv_parm *)pcmd;
+
+		if (flag == ELS_CMD_FLOGI) {
+			/* Copy the received service parameters back */
+			memcpy(sp, &phba->fc_fabparam,
+			       sizeof(struct serv_parm));
+
+			/* Clear the F_Port bit */
+			sp->cmn.fPort = 0;
+
+			/* Mark all class service parameters as invalid */
+			sp->cls1.classValid = 0;
+			sp->cls2.classValid = 0;
+			sp->cls3.classValid = 0;
+			sp->cls4.classValid = 0;
+
+			/* Copy our worldwide names */
+			memcpy(&sp->portName, &vport->fc_sparam.portName,
+			       sizeof(struct lpfc_name));
+			memcpy(&sp->nodeName, &vport->fc_sparam.nodeName,
+			       sizeof(struct lpfc_name));
+		} else {
+			memcpy(pcmd, &vport->fc_sparam,
+			       sizeof(struct serv_parm));
+		}
 
 		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-			"Issue ACC PLOGI: did:x%x flg:x%x",
+			"Issue ACC FLOGI/PLOGI: did:x%x flg:x%x",
 			ndlp->nlp_DID, ndlp->nlp_flag, 0);
 		break;
 	case ELS_CMD_PRLO:
@@ -4681,28 +4700,25 @@
 
 	desc->tag = cpu_to_be32(RDP_PORT_SPEED_DESC_TAG);
 
-	switch (phba->sli4_hba.link_state.speed) {
-	case LPFC_FC_LA_SPEED_1G:
+	switch (phba->fc_linkspeed) {
+	case LPFC_LINK_SPEED_1GHZ:
 		rdp_speed = RDP_PS_1GB;
 		break;
-	case LPFC_FC_LA_SPEED_2G:
+	case LPFC_LINK_SPEED_2GHZ:
 		rdp_speed = RDP_PS_2GB;
 		break;
-	case LPFC_FC_LA_SPEED_4G:
+	case LPFC_LINK_SPEED_4GHZ:
 		rdp_speed = RDP_PS_4GB;
 		break;
-	case LPFC_FC_LA_SPEED_8G:
+	case LPFC_LINK_SPEED_8GHZ:
 		rdp_speed = RDP_PS_8GB;
 		break;
-	case LPFC_FC_LA_SPEED_10G:
+	case LPFC_LINK_SPEED_10GHZ:
 		rdp_speed = RDP_PS_10GB;
 		break;
-	case LPFC_FC_LA_SPEED_16G:
+	case LPFC_LINK_SPEED_16GHZ:
 		rdp_speed = RDP_PS_16GB;
 		break;
-	case LPFC_FC_LA_SPEED_32G:
-		rdp_speed = RDP_PS_32GB;
-		break;
 	default:
 		rdp_speed = RDP_PS_UNKNOWN;
 		break;
@@ -5739,7 +5755,6 @@
 	IOCB_t *icmd = &cmdiocb->iocb;
 	struct serv_parm *sp;
 	LPFC_MBOXQ_t *mbox;
-	struct ls_rjt stat;
 	uint32_t cmd, did;
 	int rc;
 	uint32_t fc_flag = 0;
@@ -5765,135 +5780,92 @@
 		return 1;
 	}
 
-	if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) {
-		/* For a FLOGI we accept, then if our portname is greater
-		 * then the remote portname we initiate Nport login.
-		 */
+	(void) lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1);
 
-		rc = memcmp(&vport->fc_portname, &sp->portName,
-			    sizeof(struct lpfc_name));
 
-		if (!rc) {
-			if (phba->sli_rev < LPFC_SLI_REV4) {
-				mbox = mempool_alloc(phba->mbox_mem_pool,
-						     GFP_KERNEL);
-				if (!mbox)
-					return 1;
-				lpfc_linkdown(phba);
-				lpfc_init_link(phba, mbox,
-					       phba->cfg_topology,
-					       phba->cfg_link_speed);
-				mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0;
-				mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-				mbox->vport = vport;
-				rc = lpfc_sli_issue_mbox(phba, mbox,
-							 MBX_NOWAIT);
-				lpfc_set_loopback_flag(phba);
-				if (rc == MBX_NOT_FINISHED)
-					mempool_free(mbox, phba->mbox_mem_pool);
+	/*
+	 * If our portname is greater than the remote portname,
+	 * then we initiate Nport login.
+	 */
+
+	rc = memcmp(&vport->fc_portname, &sp->portName,
+		    sizeof(struct lpfc_name));
+
+	if (!rc) {
+		if (phba->sli_rev < LPFC_SLI_REV4) {
+			mbox = mempool_alloc(phba->mbox_mem_pool,
+					     GFP_KERNEL);
+			if (!mbox)
 				return 1;
-			} else {
-				/* abort the flogi coming back to ourselves
-				 * due to external loopback on the port.
-				 */
-				lpfc_els_abort_flogi(phba);
-				return 0;
-			}
-		} else if (rc > 0) {	/* greater than */
-			spin_lock_irq(shost->host_lock);
-			vport->fc_flag |= FC_PT2PT_PLOGI;
-			spin_unlock_irq(shost->host_lock);
+			lpfc_linkdown(phba);
+			lpfc_init_link(phba, mbox,
+				       phba->cfg_topology,
+				       phba->cfg_link_speed);
+			mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0;
+			mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+			mbox->vport = vport;
+			rc = lpfc_sli_issue_mbox(phba, mbox,
+						 MBX_NOWAIT);
+			lpfc_set_loopback_flag(phba);
+			if (rc == MBX_NOT_FINISHED)
+				mempool_free(mbox, phba->mbox_mem_pool);
+			return 1;
+		}
 
-			/* If we have the high WWPN we can assign our own
-			 * myDID; otherwise, we have to WAIT for a PLOGI
-			 * from the remote NPort to find out what it
-			 * will be.
-			 */
-			vport->fc_myDID = PT2PT_LocalID;
-		} else
-			vport->fc_myDID = PT2PT_RemoteID;
-
-		/*
-		 * The vport state should go to LPFC_FLOGI only
-		 * AFTER we issue a FLOGI, not receive one.
+		/* abort the flogi coming back to ourselves
+		 * due to external loopback on the port.
 		 */
+		lpfc_els_abort_flogi(phba);
+		return 0;
+
+	} else if (rc > 0) {	/* greater than */
 		spin_lock_irq(shost->host_lock);
-		fc_flag = vport->fc_flag;
-		port_state = vport->port_state;
-		vport->fc_flag |= FC_PT2PT;
-		vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+		vport->fc_flag |= FC_PT2PT_PLOGI;
 		spin_unlock_irq(shost->host_lock);
-		lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
-				 "3311 Rcv Flogi PS x%x new PS x%x "
-				 "fc_flag x%x new fc_flag x%x\n",
-				 port_state, vport->port_state,
-				 fc_flag, vport->fc_flag);
 
-		/*
-		 * We temporarily set fc_myDID to make it look like we are
-		 * a Fabric. This is done just so we end up with the right
-		 * did / sid on the FLOGI ACC rsp.
+		/* If we have the high WWPN we can assign our own
+		 * myDID; otherwise, we have to WAIT for a PLOGI
+		 * from the remote NPort to find out what it
+		 * will be.
 		 */
-		did = vport->fc_myDID;
-		vport->fc_myDID = Fabric_DID;
-
+		vport->fc_myDID = PT2PT_LocalID;
 	} else {
-		/* Reject this request because invalid parameters */
-		stat.un.b.lsRjtRsvd0 = 0;
-		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-		stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
-		stat.un.b.vendorUnique = 0;
-
-		/*
-		 * We temporarily set fc_myDID to make it look like we are
-		 * a Fabric. This is done just so we end up with the right
-		 * did / sid on the FLOGI LS_RJT rsp.
-		 */
-		did = vport->fc_myDID;
-		vport->fc_myDID = Fabric_DID;
-
-		lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
-			NULL);
-
-		/* Now lets put fc_myDID back to what its supposed to be */
-		vport->fc_myDID = did;
-
-		return 1;
+		vport->fc_myDID = PT2PT_RemoteID;
 	}
 
-	/* send our FLOGI first */
-	if (vport->port_state < LPFC_FLOGI) {
-		vport->fc_myDID = 0;
-		lpfc_initial_flogi(vport);
-		vport->fc_myDID = Fabric_DID;
-	}
+	/*
+	 * The vport state should go to LPFC_FLOGI only
+	 * AFTER we issue a FLOGI, not receive one.
+	 */
+	spin_lock_irq(shost->host_lock);
+	fc_flag = vport->fc_flag;
+	port_state = vport->port_state;
+	vport->fc_flag |= FC_PT2PT;
+	vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+	spin_unlock_irq(shost->host_lock);
+	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+			 "3311 Rcv Flogi PS x%x new PS x%x "
+			 "fc_flag x%x new fc_flag x%x\n",
+			 port_state, vport->port_state,
+			 fc_flag, vport->fc_flag);
+
+	/*
+	 * We temporarily set fc_myDID to make it look like we are
+	 * a Fabric. This is done just so we end up with the right
+	 * did / sid on the FLOGI ACC rsp.
+	 */
+	did = vport->fc_myDID;
+	vport->fc_myDID = Fabric_DID;
+
+	memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
 
 	/* Send back ACC */
-	lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
+	lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, cmdiocb, ndlp, NULL);
 
 	/* Now lets put fc_myDID back to what its supposed to be */
 	vport->fc_myDID = did;
 
-	if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
-
-		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-		if (!mbox)
-			goto fail;
-
-		lpfc_config_link(phba, mbox);
-
-		mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-		mbox->vport = vport;
-		rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
-		if (rc == MBX_NOT_FINISHED) {
-			mempool_free(mbox, phba->mbox_mem_pool);
-			goto fail;
-		}
-	}
-
 	return 0;
-fail:
-	return 1;
 }
 
 /**
@@ -7345,7 +7317,7 @@
 
 	/* reject till our FLOGI completes */
 	if ((vport->port_state < LPFC_FABRIC_CFG_LINK) &&
-		(cmd != ELS_CMD_FLOGI)) {
+	    (cmd != ELS_CMD_FLOGI)) {
 		rjt_err = LSRJT_UNABLE_TPC;
 		rjt_exp = LSEXP_NOTHING_MORE;
 		goto lsrjt;
@@ -7381,6 +7353,7 @@
 			rjt_exp = LSEXP_NOTHING_MORE;
 			break;
 		}
+
 		if (vport->port_state < LPFC_DISC_AUTH) {
 			if (!(phba->pport->fc_flag & FC_PT2PT) ||
 				(phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index bfc2442..d3668aa 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1083,7 +1083,7 @@
 }
 
 
-static void
+void
 lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
 	struct lpfc_vport *vport = pmb->vport;
@@ -1113,8 +1113,10 @@
 	/* Start discovery by sending a FLOGI. port_state is identically
 	 * LPFC_FLOGI while waiting for FLOGI cmpl
 	 */
-	if (vport->port_state != LPFC_FLOGI || vport->fc_flag & FC_PT2PT_PLOGI)
+	if (vport->port_state != LPFC_FLOGI)
 		lpfc_initial_flogi(vport);
+	else if (vport->fc_flag & FC_PT2PT)
+		lpfc_disc_start(vport);
 	return;
 
 out:
@@ -2963,8 +2965,10 @@
 
 out_free_mem:
 	mempool_free(mboxq, phba->mbox_mem_pool);
-	lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
-	kfree(dmabuf);
+	if (dmabuf) {
+		lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
+		kfree(dmabuf);
+	}
 	return;
 }
 
@@ -3448,10 +3452,10 @@
 		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
 		spin_unlock_irq(shost->host_lock);
-	} else
-		/* Good status, call state machine */
-		lpfc_disc_state_machine(vport, ndlp, pmb,
-				NLP_EVT_CMPL_REG_LOGIN);
+	}
+
+	/* Call state machine */
+	lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
 
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 	kfree(mp);
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 33ec4fa..f224cdb 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -1182,6 +1182,7 @@
 #define lpfc_mbx_wq_create_page_size_SHIFT	0
 #define lpfc_mbx_wq_create_page_size_MASK	0x000000FF
 #define lpfc_mbx_wq_create_page_size_WORD	word1
+#define LPFC_WQ_PAGE_SIZE_4096	0x1
 #define lpfc_mbx_wq_create_wqe_size_SHIFT	8
 #define lpfc_mbx_wq_create_wqe_size_MASK	0x0000000F
 #define lpfc_mbx_wq_create_wqe_size_WORD	word1
@@ -1253,6 +1254,7 @@
 #define lpfc_rq_context_page_size_SHIFT	0		/* Version 1 Only */
 #define lpfc_rq_context_page_size_MASK	0x000000FF
 #define lpfc_rq_context_page_size_WORD	word0
+#define	LPFC_RQ_PAGE_SIZE_4096	0x1
 	uint32_t reserved1;
 	uint32_t word2;
 #define lpfc_rq_context_cq_id_SHIFT	16
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b0d92b8..60c2109 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -8834,9 +8834,12 @@
 				 * already mapped to this phys_id.
 				 */
 				if (cpup->irq != LPFC_VECTOR_MAP_EMPTY) {
-					chann[saved_chann] =
-						cpup->channel_id;
-					saved_chann++;
+					if (saved_chann <=
+					    LPFC_FCP_IO_CHAN_MAX) {
+						chann[saved_chann] =
+							cpup->channel_id;
+						saved_chann++;
+					}
 					goto out;
 				}
 
@@ -11384,6 +11387,7 @@
 	.id_table	= lpfc_id_table,
 	.probe		= lpfc_pci_probe_one,
 	.remove		= lpfc_pci_remove_one,
+	.shutdown	= lpfc_pci_remove_one,
 	.suspend        = lpfc_pci_suspend_one,
 	.resume		= lpfc_pci_resume_one,
 	.err_handler    = &lpfc_err_handler,
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index f87f90e..1e34b54 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -2145,10 +2145,12 @@
 	reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]);
 	reg_vfi->e_d_tov = phba->fc_edtov;
 	reg_vfi->r_a_tov = phba->fc_ratov;
-	reg_vfi->bde.addrHigh = putPaddrHigh(phys);
-	reg_vfi->bde.addrLow = putPaddrLow(phys);
-	reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam);
-	reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+	if (phys) {
+		reg_vfi->bde.addrHigh = putPaddrHigh(phys);
+		reg_vfi->bde.addrLow = putPaddrLow(phys);
+		reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam);
+		reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+	}
 	bf_set(lpfc_reg_vfi_nport_id, reg_vfi, vport->fc_myDID);
 
 	/* Only FC supports upd bit */
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index ed9a2c8..193733e 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -280,38 +280,12 @@
 	uint32_t *lp;
 	IOCB_t *icmd;
 	struct serv_parm *sp;
+	uint32_t ed_tov;
 	LPFC_MBOXQ_t *mbox;
 	struct ls_rjt stat;
 	int rc;
 
 	memset(&stat, 0, sizeof (struct ls_rjt));
-	if (vport->port_state <= LPFC_FDISC) {
-		/* Before responding to PLOGI, check for pt2pt mode.
-		 * If we are pt2pt, with an outstanding FLOGI, abort
-		 * the FLOGI and resend it first.
-		 */
-		if (vport->fc_flag & FC_PT2PT) {
-			 lpfc_els_abort_flogi(phba);
-		        if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
-				/* If the other side is supposed to initiate
-				 * the PLOGI anyway, just ACC it now and
-				 * move on with discovery.
-				 */
-				phba->fc_edtov = FF_DEF_EDTOV;
-				phba->fc_ratov = FF_DEF_RATOV;
-				/* Start discovery - this should just do
-				   CLEAR_LA */
-				lpfc_disc_start(vport);
-			} else
-				lpfc_initial_flogi(vport);
-		} else {
-			stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
-			stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
-			lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
-					    ndlp, NULL);
-			return 0;
-		}
-	}
 	pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
 	lp = (uint32_t *) pcmd->virt;
 	sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
@@ -404,30 +378,46 @@
 	/* Check for Nport to NPort pt2pt protocol */
 	if ((vport->fc_flag & FC_PT2PT) &&
 	    !(vport->fc_flag & FC_PT2PT_PLOGI)) {
-
 		/* rcv'ed PLOGI decides what our NPortId will be */
 		vport->fc_myDID = icmd->un.rcvels.parmRo;
-		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-		if (mbox == NULL)
-			goto out;
-		lpfc_config_link(phba, mbox);
-		mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-		mbox->vport = vport;
-		rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
-		if (rc == MBX_NOT_FINISHED) {
-			mempool_free(mbox, phba->mbox_mem_pool);
-			goto out;
+
+		ed_tov = be32_to_cpu(sp->cmn.e_d_tov);
+		if (sp->cmn.edtovResolution) {
+			/* E_D_TOV ticks are in nanoseconds */
+			ed_tov = (phba->fc_edtov + 999999) / 1000000;
 		}
+
 		/*
-		 * For SLI4, the VFI/VPI are registered AFTER the
-		 * Nport with the higher WWPN sends us a PLOGI with
-		 * our assigned NPortId.
+		 * For pt-to-pt, use the larger EDTOV
+		 * RATOV = 2 * EDTOV
 		 */
+		if (ed_tov > phba->fc_edtov)
+			phba->fc_edtov = ed_tov;
+		phba->fc_ratov = (2 * phba->fc_edtov) / 1000;
+
+		memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
+
+		/* Issue config_link / reg_vfi to account for updated TOV's */
+
 		if (phba->sli_rev == LPFC_SLI_REV4)
 			lpfc_issue_reg_vfi(vport);
+		else {
+			mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+			if (mbox == NULL)
+				goto out;
+			lpfc_config_link(phba, mbox);
+			mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+			mbox->vport = vport;
+			rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+			if (rc == MBX_NOT_FINISHED) {
+				mempool_free(mbox, phba->mbox_mem_pool);
+				goto out;
+			}
+		}
 
 		lpfc_can_disctmo(vport);
 	}
+
 	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!mbox)
 		goto out;
@@ -1038,7 +1028,9 @@
 	uint32_t *lp;
 	IOCB_t *irsp;
 	struct serv_parm *sp;
+	uint32_t ed_tov;
 	LPFC_MBOXQ_t *mbox;
+	int rc;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 	rspiocb = cmdiocb->context_un.rsp_iocb;
@@ -1094,18 +1086,63 @@
 	ndlp->nlp_maxframe =
 		((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
 
-	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mbox) {
-		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
-			"0133 PLOGI: no memory for reg_login "
-			"Data: x%x x%x x%x x%x\n",
-			ndlp->nlp_DID, ndlp->nlp_state,
-			ndlp->nlp_flag, ndlp->nlp_rpi);
-		goto out;
+	if ((vport->fc_flag & FC_PT2PT) &&
+	    (vport->fc_flag & FC_PT2PT_PLOGI)) {
+		ed_tov = be32_to_cpu(sp->cmn.e_d_tov);
+		if (sp->cmn.edtovResolution) {
+			/* E_D_TOV ticks are in nanoseconds */
+			ed_tov = (phba->fc_edtov + 999999) / 1000000;
+		}
+
+		/*
+		 * Use the larger EDTOV
+		 * RATOV = 2 * EDTOV for pt-to-pt
+		 */
+		if (ed_tov > phba->fc_edtov)
+			phba->fc_edtov = ed_tov;
+		phba->fc_ratov = (2 * phba->fc_edtov) / 1000;
+
+		memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
+
+		/* Issue config_link / reg_vfi to account for updated TOV's */
+		if (phba->sli_rev == LPFC_SLI_REV4) {
+			lpfc_issue_reg_vfi(vport);
+		} else {
+			mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+			if (!mbox) {
+				lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+						 "0133 PLOGI: no memory "
+						 "for config_link "
+						 "Data: x%x x%x x%x x%x\n",
+						 ndlp->nlp_DID, ndlp->nlp_state,
+						 ndlp->nlp_flag, ndlp->nlp_rpi);
+				goto out;
+			}
+
+			lpfc_config_link(phba, mbox);
+
+			mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+			mbox->vport = vport;
+			rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+			if (rc == MBX_NOT_FINISHED) {
+				mempool_free(mbox, phba->mbox_mem_pool);
+				goto out;
+			}
+		}
 	}
 
 	lpfc_unreg_rpi(vport, ndlp);
 
+	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!mbox) {
+		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+				 "0018 PLOGI: no memory for reg_login "
+				 "Data: x%x x%x x%x x%x\n",
+				 ndlp->nlp_DID, ndlp->nlp_state,
+				 ndlp->nlp_flag, ndlp->nlp_rpi);
+		goto out;
+	}
+
 	if (lpfc_reg_rpi(phba, vport->vpi, irsp->un.elsreq64.remoteID,
 			 (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) {
 		switch (ndlp->nlp_DID) {
@@ -2299,6 +2336,9 @@
 		if (vport->phba->sli_rev < LPFC_SLI_REV4)
 			ndlp->nlp_rpi = mb->un.varWords[0];
 		ndlp->nlp_flag |= NLP_RPI_REGISTERED;
+		if (ndlp->nlp_flag & NLP_LOGO_ACC) {
+			lpfc_unreg_rpi(vport, ndlp);
+		}
 	} else {
 		if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
 			lpfc_drop_node(vport, ndlp);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 4679ed4..bae36cc 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -3859,7 +3859,7 @@
 	uint32_t tag;
 	uint16_t hwq;
 
-	if (shost_use_blk_mq(cmnd->device->host)) {
+	if (cmnd && shost_use_blk_mq(cmnd->device->host)) {
 		tag = blk_mq_unique_tag(cmnd->request);
 		hwq = blk_mq_unique_tag_to_hwq(tag);
 
@@ -3908,9 +3908,9 @@
 	uint32_t logit = LOG_FCP;
 
 	/* Sanity check on return of outstanding command */
-	if (!(lpfc_cmd->pCmd))
-		return;
 	cmd = lpfc_cmd->pCmd;
+	if (!cmd)
+		return;
 	shost = cmd->device->host;
 
 	lpfc_cmd->result = (pIocbOut->iocb.un.ulpWord[4] & IOERR_PARAM_MASK);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index f9585cd..38e90d9 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5887,18 +5887,25 @@
 
  free_vfi_bmask:
 	kfree(phba->sli4_hba.vfi_bmask);
+	phba->sli4_hba.vfi_bmask = NULL;
  free_xri_ids:
 	kfree(phba->sli4_hba.xri_ids);
+	phba->sli4_hba.xri_ids = NULL;
  free_xri_bmask:
 	kfree(phba->sli4_hba.xri_bmask);
+	phba->sli4_hba.xri_bmask = NULL;
  free_vpi_ids:
 	kfree(phba->vpi_ids);
+	phba->vpi_ids = NULL;
  free_vpi_bmask:
 	kfree(phba->vpi_bmask);
+	phba->vpi_bmask = NULL;
  free_rpi_ids:
 	kfree(phba->sli4_hba.rpi_ids);
+	phba->sli4_hba.rpi_ids = NULL;
  free_rpi_bmask:
 	kfree(phba->sli4_hba.rpi_bmask);
+	phba->sli4_hba.rpi_bmask = NULL;
  err_exit:
 	return rc;
 }
@@ -13475,7 +13482,7 @@
 			       LPFC_WQ_WQE_SIZE_128);
 			bf_set(lpfc_mbx_wq_create_page_size,
 			       &wq_create->u.request_1,
-			       (PAGE_SIZE/SLI4_PAGE_SIZE));
+			       LPFC_WQ_PAGE_SIZE_4096);
 			page = wq_create->u.request_1.page;
 			break;
 		}
@@ -13501,8 +13508,9 @@
 			       LPFC_WQ_WQE_SIZE_128);
 			break;
 		}
-		bf_set(lpfc_mbx_wq_create_page_size, &wq_create->u.request_1,
-		       (PAGE_SIZE/SLI4_PAGE_SIZE));
+		bf_set(lpfc_mbx_wq_create_page_size,
+		       &wq_create->u.request_1,
+		       LPFC_WQ_PAGE_SIZE_4096);
 		page = wq_create->u.request_1.page;
 		break;
 	default:
@@ -13688,7 +13696,7 @@
 		       LPFC_RQE_SIZE_8);
 		bf_set(lpfc_rq_context_page_size,
 		       &rq_create->u.request.context,
-		       (PAGE_SIZE/SLI4_PAGE_SIZE));
+		       LPFC_RQ_PAGE_SIZE_4096);
 	} else {
 		switch (hrq->entry_count) {
 		default:
@@ -14842,10 +14850,12 @@
 	struct lpfc_dmabuf *h_buf;
 	struct hbq_dmabuf *seq_dmabuf = NULL;
 	struct hbq_dmabuf *temp_dmabuf = NULL;
+	uint8_t	found = 0;
 
 	INIT_LIST_HEAD(&dmabuf->dbuf.list);
 	dmabuf->time_stamp = jiffies;
 	new_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
+
 	/* Use the hdr_buf to find the sequence that this frame belongs to */
 	list_for_each_entry(h_buf, &vport->rcv_buffer_list, list) {
 		temp_hdr = (struct fc_frame_header *)h_buf->virt;
@@ -14885,7 +14895,8 @@
 		return seq_dmabuf;
 	}
 	/* find the correct place in the sequence to insert this frame */
-	list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) {
+	d_buf = list_entry(seq_dmabuf->dbuf.list.prev, typeof(*d_buf), list);
+	while (!found) {
 		temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
 		temp_hdr = (struct fc_frame_header *)temp_dmabuf->hbuf.virt;
 		/*
@@ -14895,9 +14906,17 @@
 		if (be16_to_cpu(new_hdr->fh_seq_cnt) >
 			be16_to_cpu(temp_hdr->fh_seq_cnt)) {
 			list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list);
-			return seq_dmabuf;
+			found = 1;
+			break;
 		}
+
+		if (&d_buf->list == &seq_dmabuf->dbuf.list)
+			break;
+		d_buf = list_entry(d_buf->list.prev, typeof(*d_buf), list);
 	}
+
+	if (found)
+		return seq_dmabuf;
 	return NULL;
 }
 
@@ -16173,7 +16192,7 @@
 }
 
 /**
- * lpfc_check_next_fcf_pri
+ * lpfc_check_next_fcf_pri_level
  * phba pointer to the lpfc_hba struct for this port.
  * This routine is called from the lpfc_sli4_fcf_rr_next_index_get
  * routine when the rr_bmask is empty. The FCF indecies are put into the
@@ -16329,8 +16348,12 @@
 
 	if (next_fcf_index < LPFC_SLI4_FCF_TBL_INDX_MAX &&
 		phba->fcf.fcf_pri[next_fcf_index].fcf_rec.flag &
-		LPFC_FCF_FLOGI_FAILED)
+		LPFC_FCF_FLOGI_FAILED) {
+		if (list_is_singular(&phba->fcf.fcf_pri_list))
+			return LPFC_FCOE_FCF_NEXT_NONE;
+
 		goto next_priority;
+	}
 
 	lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
 			"2845 Get next roundrobin failover FCF (x%x)\n",
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index c0f7c8c..aaf7da0 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1083,6 +1083,8 @@
 
 #define VD_EXT_DEBUG 0
 
+#define SCAN_PD_CHANNEL	0x1
+#define SCAN_VD_CHANNEL	0x2
 
 enum MR_SCSI_CMD_TYPE {
 	READ_WRITE_LDIO = 0,
@@ -1921,7 +1923,7 @@
 };
 
 #define MEGASAS_IS_LOGICAL(scp)						\
-	(scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1
+	((scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1)
 
 #define MEGASAS_DEV_INDEX(scp)						\
 	(((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) +	\
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 00ce3e2..17c440b 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -735,6 +735,7 @@
 	       &(regs)->inbound_high_queue_port);
 	writel((lower_32_bits(frame_phys_addr) | (frame_count<<1))|1,
 	       &(regs)->inbound_low_queue_port);
+	mmiowb();
 	spin_unlock_irqrestore(&instance->hba_lock, flags);
 }
 
@@ -1687,16 +1688,13 @@
 		goto out_done;
 	}
 
-	switch (scmd->cmnd[0]) {
-	case SYNCHRONIZE_CACHE:
-		/*
-		 * FW takes care of flush cache on its own
-		 * No need to send it down
-		 */
+	/*
+	 * FW takes care of flush cache on its own for Virtual Disk.
+	 * No need to send it down for VD. For JBOD send SYNCHRONIZE_CACHE to FW.
+	 */
+	if ((scmd->cmnd[0] == SYNCHRONIZE_CACHE) && MEGASAS_IS_LOGICAL(scmd)) {
 		scmd->result = DID_OK << 16;
 		goto out_done;
-	default:
-		break;
 	}
 
 	if (instance->instancet->build_and_issue_cmd(instance, scmd)) {
@@ -4669,7 +4667,7 @@
 	/* Find first memory bar */
 	bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
 	instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
-	if (pci_request_selected_regions(instance->pdev, instance->bar,
+	if (pci_request_selected_regions(instance->pdev, 1<<instance->bar,
 					 "megasas: LSI")) {
 		dev_printk(KERN_DEBUG, &instance->pdev->dev, "IO memory region busy!\n");
 		return -EBUSY;
@@ -4960,7 +4958,7 @@
 	iounmap(instance->reg_set);
 
       fail_ioremap:
-	pci_release_selected_regions(instance->pdev, instance->bar);
+	pci_release_selected_regions(instance->pdev, 1<<instance->bar);
 
 	return -EINVAL;
 }
@@ -4981,7 +4979,7 @@
 
 	iounmap(instance->reg_set);
 
-	pci_release_selected_regions(instance->pdev, instance->bar);
+	pci_release_selected_regions(instance->pdev, 1<<instance->bar);
 }
 
 /**
@@ -5476,7 +5474,6 @@
 	spin_lock_init(&instance->hba_lock);
 	spin_lock_init(&instance->completion_lock);
 
-	mutex_init(&instance->aen_mutex);
 	mutex_init(&instance->reset_mutex);
 
 	/*
@@ -5941,11 +5938,11 @@
 			if (fusion->ld_drv_map[i])
 				free_pages((ulong)fusion->ld_drv_map[i],
 					fusion->drv_map_pages);
-				if (fusion->pd_seq_sync)
-					dma_free_coherent(&instance->pdev->dev,
-						pd_seq_map_sz,
-						fusion->pd_seq_sync[i],
-						fusion->pd_seq_phys[i]);
+			if (fusion->pd_seq_sync[i])
+				dma_free_coherent(&instance->pdev->dev,
+					pd_seq_map_sz,
+					fusion->pd_seq_sync[i],
+					fusion->pd_seq_phys[i]);
 		}
 		free_pages((ulong)instance->ctrl_context,
 			instance->ctrl_context_pages);
@@ -6443,10 +6440,10 @@
 	}
 	spin_unlock_irqrestore(&instance->hba_lock, flags);
 
-	mutex_lock(&instance->aen_mutex);
+	mutex_lock(&instance->reset_mutex);
 	error = megasas_register_aen(instance, aen.seq_num,
 				     aen.class_locale_word);
-	mutex_unlock(&instance->aen_mutex);
+	mutex_unlock(&instance->reset_mutex);
 	return error;
 }
 
@@ -6477,9 +6474,9 @@
 	int i;
 	int error = 0;
 	compat_uptr_t ptr;
-	unsigned long local_raw_ptr;
 	u32 local_sense_off;
 	u32 local_sense_len;
+	u32 user_sense_off;
 
 	if (clear_user(ioc, sizeof(*ioc)))
 		return -EFAULT;
@@ -6497,17 +6494,16 @@
 	 * sense_len is not null, so prepare the 64bit value under
 	 * the same condition.
 	 */
-	if (get_user(local_raw_ptr, ioc->frame.raw) ||
-		get_user(local_sense_off, &ioc->sense_off) ||
-		get_user(local_sense_len, &ioc->sense_len))
+	if (get_user(local_sense_off, &ioc->sense_off) ||
+		get_user(local_sense_len, &ioc->sense_len) ||
+		get_user(user_sense_off, &cioc->sense_off))
 		return -EFAULT;
 
-
 	if (local_sense_len) {
 		void __user **sense_ioc_ptr =
-			(void __user **)((u8*)local_raw_ptr + local_sense_off);
+			(void __user **)((u8 *)((unsigned long)&ioc->frame.raw) + local_sense_off);
 		compat_uptr_t *sense_cioc_ptr =
-			(compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
+			(compat_uptr_t *)(((unsigned long)&cioc->frame.raw) + user_sense_off);
 		if (get_user(ptr, sense_cioc_ptr) ||
 		    put_user(compat_ptr(ptr), sense_ioc_ptr))
 			return -EFAULT;
@@ -6648,6 +6644,7 @@
 	int     i, j, doscan = 0;
 	u32 seq_num, wait_time = MEGASAS_RESET_WAIT_TIME;
 	int error;
+	u8  dcmd_ret = 0;
 
 	if (!instance) {
 		printk(KERN_ERR "invalid instance!\n");
@@ -6660,16 +6657,7 @@
 		wait_time = MEGASAS_ROUTINE_WAIT_TIME_VF;
 
 	/* Don't run the event workqueue thread if OCR is running */
-	for (i = 0; i < wait_time; i++) {
-		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL)
-			break;
-		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
-			dev_notice(&instance->pdev->dev, "%s waiting for "
-			       "controller reset to finish for scsi%d\n",
-			       __func__, instance->host->host_no);
-		}
-		msleep(1000);
-	}
+	mutex_lock(&instance->reset_mutex);
 
 	instance->ev = NULL;
 	host = instance->host;
@@ -6677,47 +6665,73 @@
 		megasas_decode_evt(instance);
 
 		switch (le32_to_cpu(instance->evt_detail->code)) {
+
 		case MR_EVT_PD_INSERTED:
-			if (megasas_get_pd_list(instance) == 0) {
-			for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
-				for (j = 0;
-				j < MEGASAS_MAX_DEV_PER_CHANNEL;
-				j++) {
-
-				pd_index =
-				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
-
-				sdev1 = scsi_device_lookup(host, i, j, 0);
-
-				if (instance->pd_list[pd_index].driveState
-						== MR_PD_STATE_SYSTEM) {
-					if (!sdev1)
-						scsi_add_device(host, i, j, 0);
-
-					if (sdev1)
-						scsi_device_put(sdev1);
-					}
-				}
-			}
-			}
-			doscan = 0;
+		case MR_EVT_PD_REMOVED:
+			dcmd_ret = megasas_get_pd_list(instance);
+			if (dcmd_ret == 0)
+				doscan = SCAN_PD_CHANNEL;
 			break;
 
-		case MR_EVT_PD_REMOVED:
-			if (megasas_get_pd_list(instance) == 0) {
-			for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
-				for (j = 0;
-				j < MEGASAS_MAX_DEV_PER_CHANNEL;
-				j++) {
+		case MR_EVT_LD_OFFLINE:
+		case MR_EVT_CFG_CLEARED:
+		case MR_EVT_LD_DELETED:
+		case MR_EVT_LD_CREATED:
+			if (!instance->requestorId ||
+				(instance->requestorId && megasas_get_ld_vf_affiliation(instance, 0)))
+				dcmd_ret = megasas_ld_list_query(instance, MR_LD_QUERY_TYPE_EXPOSED_TO_HOST);
 
-				pd_index =
-				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+			if (dcmd_ret == 0)
+				doscan = SCAN_VD_CHANNEL;
 
+			break;
+
+		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
+		case MR_EVT_FOREIGN_CFG_IMPORTED:
+		case MR_EVT_LD_STATE_CHANGE:
+			dcmd_ret = megasas_get_pd_list(instance);
+
+			if (dcmd_ret != 0)
+				break;
+
+			if (!instance->requestorId ||
+				(instance->requestorId && megasas_get_ld_vf_affiliation(instance, 0)))
+				dcmd_ret = megasas_ld_list_query(instance, MR_LD_QUERY_TYPE_EXPOSED_TO_HOST);
+
+			if (dcmd_ret != 0)
+				break;
+
+			doscan = SCAN_VD_CHANNEL | SCAN_PD_CHANNEL;
+			dev_info(&instance->pdev->dev, "scanning for scsi%d...\n",
+				instance->host->host_no);
+			break;
+
+		case MR_EVT_CTRL_PROP_CHANGED:
+				dcmd_ret = megasas_get_ctrl_info(instance);
+				break;
+		default:
+			doscan = 0;
+			break;
+		}
+	} else {
+		dev_err(&instance->pdev->dev, "invalid evt_detail!\n");
+		mutex_unlock(&instance->reset_mutex);
+		kfree(ev);
+		return;
+	}
+
+	mutex_unlock(&instance->reset_mutex);
+
+	if (doscan & SCAN_PD_CHANNEL) {
+		for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
+			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
+				pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j;
 				sdev1 = scsi_device_lookup(host, i, j, 0);
-
-				if (instance->pd_list[pd_index].driveState
-					== MR_PD_STATE_SYSTEM) {
-					if (sdev1)
+				if (instance->pd_list[pd_index].driveState ==
+							MR_PD_STATE_SYSTEM) {
+					if (!sdev1)
+						scsi_add_device(host, i, j, 0);
+					else
 						scsi_device_put(sdev1);
 				} else {
 					if (sdev1) {
@@ -6725,164 +6739,53 @@
 						scsi_device_put(sdev1);
 					}
 				}
-				}
 			}
-			}
-			doscan = 0;
-			break;
-
-		case MR_EVT_LD_OFFLINE:
-		case MR_EVT_CFG_CLEARED:
-		case MR_EVT_LD_DELETED:
-			if (!instance->requestorId ||
-			    megasas_get_ld_vf_affiliation(instance, 0)) {
-				if (megasas_ld_list_query(instance,
-							  MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
-					megasas_get_ld_list(instance);
-				for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
-					for (j = 0;
-					     j < MEGASAS_MAX_DEV_PER_CHANNEL;
-					     j++) {
-
-						ld_index =
-							(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
-
-						sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
-
-						if (instance->ld_ids[ld_index]
-						    != 0xff) {
-							if (sdev1)
-								scsi_device_put(sdev1);
-						} else {
-							if (sdev1) {
-								scsi_remove_device(sdev1);
-								scsi_device_put(sdev1);
-							}
-						}
-					}
-				}
-				doscan = 0;
-			}
-			break;
-		case MR_EVT_LD_CREATED:
-			if (!instance->requestorId ||
-			    megasas_get_ld_vf_affiliation(instance, 0)) {
-				if (megasas_ld_list_query(instance,
-							  MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
-					megasas_get_ld_list(instance);
-				for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
-					for (j = 0;
-					     j < MEGASAS_MAX_DEV_PER_CHANNEL;
-					     j++) {
-						ld_index =
-							(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
-
-						sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
-
-						if (instance->ld_ids[ld_index]
-						    != 0xff) {
-							if (!sdev1)
-								scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
-						}
-						if (sdev1)
-							scsi_device_put(sdev1);
-					}
-				}
-				doscan = 0;
-			}
-			break;
-		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
-		case MR_EVT_FOREIGN_CFG_IMPORTED:
-		case MR_EVT_LD_STATE_CHANGE:
-			doscan = 1;
-			break;
-		case MR_EVT_CTRL_PROP_CHANGED:
-			megasas_get_ctrl_info(instance);
-			break;
-		default:
-			doscan = 0;
-			break;
 		}
-	} else {
-		dev_err(&instance->pdev->dev, "invalid evt_detail!\n");
-		kfree(ev);
-		return;
 	}
 
-	if (doscan) {
-		dev_info(&instance->pdev->dev, "scanning for scsi%d...\n",
-		       instance->host->host_no);
-		if (megasas_get_pd_list(instance) == 0) {
-			for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
-				for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
-					pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j;
-					sdev1 = scsi_device_lookup(host, i, j, 0);
-					if (instance->pd_list[pd_index].driveState ==
-					    MR_PD_STATE_SYSTEM) {
-						if (!sdev1) {
-							scsi_add_device(host, i, j, 0);
-						}
-						if (sdev1)
-							scsi_device_put(sdev1);
-					} else {
-						if (sdev1) {
-							scsi_remove_device(sdev1);
-							scsi_device_put(sdev1);
-						}
-					}
-				}
-			}
-		}
-
-		if (!instance->requestorId ||
-		    megasas_get_ld_vf_affiliation(instance, 0)) {
-			if (megasas_ld_list_query(instance,
-						  MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
-				megasas_get_ld_list(instance);
-			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
-				for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL;
-				     j++) {
-					ld_index =
-						(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
-
-					sdev1 = scsi_device_lookup(host,
-								   MEGASAS_MAX_PD_CHANNELS + i, j, 0);
-					if (instance->ld_ids[ld_index]
-					    != 0xff) {
-						if (!sdev1)
-							scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
-						else
-							scsi_device_put(sdev1);
-					} else {
-						if (sdev1) {
-							scsi_remove_device(sdev1);
-							scsi_device_put(sdev1);
-						}
+	if (doscan & SCAN_VD_CHANNEL) {
+		for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
+			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
+				ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+				sdev1 = scsi_device_lookup(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
+				if (instance->ld_ids[ld_index] != 0xff) {
+					if (!sdev1)
+						scsi_add_device(host, MEGASAS_MAX_PD_CHANNELS + i, j, 0);
+					else
+						scsi_device_put(sdev1);
+				} else {
+					if (sdev1) {
+						scsi_remove_device(sdev1);
+						scsi_device_put(sdev1);
 					}
 				}
 			}
 		}
 	}
 
-	if (instance->aen_cmd != NULL) {
-		kfree(ev);
-		return ;
-	}
-
-	seq_num = le32_to_cpu(instance->evt_detail->seq_num) + 1;
+	if (dcmd_ret == 0)
+		seq_num = le32_to_cpu(instance->evt_detail->seq_num) + 1;
+	else
+		seq_num = instance->last_seq_num;
 
 	/* Register AEN with FW for latest sequence number plus 1 */
 	class_locale.members.reserved = 0;
 	class_locale.members.locale = MR_EVT_LOCALE_ALL;
 	class_locale.members.class = MR_EVT_CLASS_DEBUG;
-	mutex_lock(&instance->aen_mutex);
+
+	if (instance->aen_cmd != NULL) {
+		kfree(ev);
+		return;
+	}
+
+	mutex_lock(&instance->reset_mutex);
 	error = megasas_register_aen(instance, seq_num,
 					class_locale.word);
-	mutex_unlock(&instance->aen_mutex);
-
 	if (error)
-		dev_err(&instance->pdev->dev, "register aen failed error %x\n", error);
+		dev_err(&instance->pdev->dev,
+			"register aen failed error %x\n", error);
 
+	mutex_unlock(&instance->reset_mutex);
 	kfree(ev);
 }
 
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 8d630a5..9600763 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -201,6 +201,7 @@
 		&instance->reg_set->inbound_low_queue_port);
 	writel(le32_to_cpu(req_desc->u.high),
 		&instance->reg_set->inbound_high_queue_port);
+	mmiowb();
 	spin_unlock_irqrestore(&instance->hba_lock, flags);
 #endif
 }
@@ -1855,6 +1856,8 @@
 		io_request->DevHandle = pd_sync->seq[pd_index].devHandle;
 		pRAID_Context->regLockFlags |=
 			(MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA);
+		pRAID_Context->Type = MPI2_TYPE_CUDA;
+		pRAID_Context->nseg = 0x1;
 	} else if (fusion->fast_path_io) {
 		pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
 		pRAID_Context->configSeqNum = 0;
@@ -1890,12 +1893,10 @@
 		pRAID_Context->timeoutValue =
 			cpu_to_le16((os_timeout_value > timeout_limit) ?
 			timeout_limit : os_timeout_value);
-		if (fusion->adapter_type == INVADER_SERIES) {
-			pRAID_Context->Type = MPI2_TYPE_CUDA;
-			pRAID_Context->nseg = 0x1;
+		if (fusion->adapter_type == INVADER_SERIES)
 			io_request->IoFlags |=
 				cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
-		}
+
 		cmd->request_desc->SCSIIO.RequestFlags =
 			(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
 				MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
@@ -2437,7 +2438,7 @@
 
 	iounmap(instance->reg_set);
 
-	pci_release_selected_regions(instance->pdev, instance->bar);
+	pci_release_selected_regions(instance->pdev, 1<<instance->bar);
 }
 
 /**
@@ -2647,6 +2648,7 @@
 		dev_err(&instance->pdev->dev, "pending commands remain after waiting, "
 		       "will reset adapter scsi%d.\n",
 		       instance->host->host_no);
+		*convert = 1;
 		retval = 1;
 	}
 out:
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 11393eb..5b2c37f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2020,8 +2020,10 @@
 	_base_free_irq(ioc);
 	_base_disable_msix(ioc);
 
-	if (ioc->msix96_vector)
+	if (ioc->msix96_vector) {
 		kfree(ioc->replyPostRegisterIndex);
+		ioc->replyPostRegisterIndex = NULL;
+	}
 
 	if (ioc->chip_phys) {
 		iounmap(ioc->chip);
@@ -2155,6 +2157,17 @@
 	} else
 		ioc->msix96_vector = 0;
 
+	if (ioc->is_warpdrive) {
+		ioc->reply_post_host_index[0] = (resource_size_t __iomem *)
+		    &ioc->chip->ReplyPostHostIndex;
+
+		for (i = 1; i < ioc->cpu_msix_table_sz; i++)
+			ioc->reply_post_host_index[i] =
+			(resource_size_t __iomem *)
+			((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
+			* 4)));
+	}
+
 	list_for_each_entry(reply_q, &ioc->reply_queue_list, list)
 		pr_info(MPT3SAS_FMT "%s: IRQ %d\n",
 		    reply_q->name,  ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
@@ -2229,6 +2242,12 @@
 	return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
 }
 
+static inline u8
+_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc)
+{
+	return ioc->cpu_msix_table[raw_smp_processor_id()];
+}
+
 /**
  * mpt3sas_base_get_smid - obtain a free smid from internal queue
  * @ioc: per adapter object
@@ -2289,6 +2308,7 @@
 	request->scmd = scmd;
 	request->cb_idx = cb_idx;
 	smid = request->smid;
+	request->msix_io = _base_get_msix_index(ioc);
 	list_del(&request->tracker_list);
 	spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
 	return smid;
@@ -2411,12 +2431,6 @@
 }
 #endif
 
-static inline u8
-_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc)
-{
-	return ioc->cpu_msix_table[raw_smp_processor_id()];
-}
-
 /**
  * mpt3sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
  * @ioc: per adapter object
@@ -2470,18 +2484,19 @@
  * mpt3sas_base_put_smid_hi_priority - send Task Managment request to firmware
  * @ioc: per adapter object
  * @smid: system request message index
- *
+ * @msix_task: msix_task will be same as msix of IO incase of task abort else 0.
  * Return nothing.
  */
 void
-mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+	u16 msix_task)
 {
 	Mpi2RequestDescriptorUnion_t descriptor;
 	u64 *request = (u64 *)&descriptor;
 
 	descriptor.HighPriority.RequestFlags =
 	    MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
-	descriptor.HighPriority.MSIxIndex =  0;
+	descriptor.HighPriority.MSIxIndex =  msix_task;
 	descriptor.HighPriority.SMID = cpu_to_le16(smid);
 	descriptor.HighPriority.LMID = 0;
 	descriptor.HighPriority.Reserved1 = 0;
@@ -5201,17 +5216,6 @@
 	if (r)
 		goto out_free_resources;
 
-	if (ioc->is_warpdrive) {
-		ioc->reply_post_host_index[0] = (resource_size_t __iomem *)
-		    &ioc->chip->ReplyPostHostIndex;
-
-		for (i = 1; i < ioc->cpu_msix_table_sz; i++)
-			ioc->reply_post_host_index[i] =
-			(resource_size_t __iomem *)
-			((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
-			* 4)));
-	}
-
 	pci_set_drvdata(ioc->pdev, ioc->shost);
 	r = _base_get_ioc_facts(ioc, CAN_SLEEP);
 	if (r)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 5ad271e..63f5965 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -390,6 +390,7 @@
  * @eedp_enable: eedp support enable bit
  * @eedp_type: 0(type_1), 1(type_2), 2(type_3)
  * @eedp_block_length: block size
+ * @ata_command_pending: SATL passthrough outstanding for device
  */
 struct MPT3SAS_DEVICE {
 	struct MPT3SAS_TARGET *sas_target;
@@ -398,6 +399,17 @@
 	u8	configured_lun;
 	u8	block;
 	u8	tlr_snoop_check;
+	/*
+	 * Bug workaround for SATL handling: the mpt2/3sas firmware
+	 * doesn't return BUSY or TASK_SET_FULL for subsequent
+	 * commands while a SATL pass through is in operation as the
+	 * spec requires, it simply does nothing with them until the
+	 * pass through completes, causing them possibly to timeout if
+	 * the passthrough is a long executing command (like format or
+	 * secure erase).  This variable allows us to do the right
+	 * thing while a SATL command is pending.
+	 */
+	unsigned long ata_command_pending;
 };
 
 #define MPT3_CMD_NOT_USED	0x8000	/* free */
@@ -643,6 +655,7 @@
  * @cb_idx: callback index
  * @direct_io: To indicate whether I/O is direct (WARPDRIVE)
  * @tracker_list: list of free request (ioc->free_list)
+ * @msix_io: IO's msix
  */
 struct scsiio_tracker {
 	u16	smid;
@@ -651,6 +664,7 @@
 	u8	direct_io;
 	struct list_head chain_list;
 	struct list_head tracker_list;
+	u16     msix_io;
 };
 
 /**
@@ -1213,7 +1227,8 @@
 	u16 handle);
 void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
 	u16 handle);
-void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid);
+void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc,
+	u16 smid, u16 msix_task);
 void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid);
 void mpt3sas_base_initialize_callback_handler(void);
 u8 mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index d8366b0..4ccde5a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -817,7 +817,7 @@
 		    tm_request->DevHandle));
 		ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
 		    data_in_dma, data_in_sz);
-		mpt3sas_base_put_smid_hi_priority(ioc, smid);
+		mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
 		break;
 	}
 	case MPI2_FUNCTION_SMP_PASSTHROUGH:
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 9ab77b0..e333029 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -51,6 +51,7 @@
 #include <linux/workqueue.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/interrupt.h>
 #include <linux/aer.h>
 #include <linux/raid_class.h>
@@ -1275,9 +1276,9 @@
 			sas_target_priv_data->handle = raid_device->handle;
 			sas_target_priv_data->sas_address = raid_device->wwid;
 			sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
-			sas_target_priv_data->raid_device = raid_device;
 			if (ioc->is_warpdrive)
-				raid_device->starget = starget;
+				sas_target_priv_data->raid_device = raid_device;
+			raid_device->starget = starget;
 		}
 		spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
 		return 0;
@@ -2193,6 +2194,7 @@
 	unsigned long timeleft;
 	struct scsiio_tracker *scsi_lookup = NULL;
 	int rc;
+	u16 msix_task = 0;
 
 	if (m_type == TM_MUTEX_ON)
 		mutex_lock(&ioc->tm_cmds.mutex);
@@ -2256,7 +2258,12 @@
 	int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
 	mpt3sas_scsih_set_tm_flag(ioc, handle);
 	init_completion(&ioc->tm_cmds.done);
-	mpt3sas_base_put_smid_hi_priority(ioc, smid);
+	if ((type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) &&
+			(scsi_lookup->msix_io < ioc->reply_queue_count))
+		msix_task = scsi_lookup->msix_io;
+	else
+		msix_task = 0;
+	mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task);
 	timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
 	if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
 		pr_err(MPT3SAS_FMT "%s: timeout\n",
@@ -3151,7 +3158,7 @@
 	mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
 	mpi_request->DevHandle = cpu_to_le16(handle);
 	mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
-	mpt3sas_base_put_smid_hi_priority(ioc, smid);
+	mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
 	mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
 
 out:
@@ -3332,7 +3339,7 @@
 	mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
 	mpi_request->DevHandle = cpu_to_le16(handle);
 	mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
-	mpt3sas_base_put_smid_hi_priority(ioc, smid);
+	mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
 }
 
 /**
@@ -3700,6 +3707,20 @@
 	}
 }
 
+static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending)
+{
+	struct MPT3SAS_DEVICE *priv = scmd->device->hostdata;
+
+	if (scmd->cmnd[0] != ATA_12 && scmd->cmnd[0] != ATA_16)
+		return 0;
+
+	if (pending)
+		return test_and_set_bit(0, &priv->ata_command_pending);
+
+	clear_bit(0, &priv->ata_command_pending);
+	return 0;
+}
+
 /**
  * _scsih_flush_running_cmds - completing outstanding commands.
  * @ioc: per adapter object
@@ -3721,6 +3742,7 @@
 		if (!scmd)
 			continue;
 		count++;
+		_scsih_set_satl_pending(scmd, false);
 		mpt3sas_base_free_smid(ioc, smid);
 		scsi_dma_unmap(scmd);
 		if (ioc->pci_error_recovery)
@@ -3825,8 +3847,6 @@
 	    SAM_STAT_CHECK_CONDITION;
 }
 
-
-
 /**
  * scsih_qcmd - main scsi request entry point
  * @scmd: pointer to scsi command object
@@ -3866,6 +3886,19 @@
 		return 0;
 	}
 
+	/*
+	 * Bug work around for firmware SATL handling.  The loop
+	 * is based on atomic operations and ensures consistency
+	 * since we're lockless at this point
+	 */
+	do {
+		if (test_bit(0, &sas_device_priv_data->ata_command_pending)) {
+			scmd->result = SAM_STAT_BUSY;
+			scmd->scsi_done(scmd);
+			return 0;
+		}
+	} while (_scsih_set_satl_pending(scmd, true));
+
 	sas_target_priv_data = sas_device_priv_data->sas_target;
 
 	/* invalid device handle */
@@ -4419,12 +4452,15 @@
 	struct MPT3SAS_DEVICE *sas_device_priv_data;
 	u32 response_code = 0;
 	unsigned long flags;
+	unsigned int sector_sz;
 
 	mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
 	scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
 	if (scmd == NULL)
 		return 1;
 
+	_scsih_set_satl_pending(scmd, false);
+
 	mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
 
 	if (mpi_reply == NULL) {
@@ -4475,6 +4511,20 @@
 	}
 
 	xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
+
+	/* In case of bogus fw or device, we could end up having
+	 * unaligned partial completion. We can force alignment here,
+	 * then scsi-ml does not need to handle this misbehavior.
+	 */
+	sector_sz = scmd->device->sector_size;
+	if (unlikely(scmd->request->cmd_type == REQ_TYPE_FS && sector_sz &&
+		     xfer_cnt % sector_sz)) {
+		sdev_printk(KERN_INFO, scmd->device,
+		    "unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n",
+			    xfer_cnt, sector_sz);
+		xfer_cnt = round_down(xfer_cnt, sector_sz);
+	}
+
 	scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
 	if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
 		log_info =  le32_to_cpu(mpi_reply->IOCLogInfo);
@@ -4504,7 +4554,7 @@
 			    le16_to_cpu(mpi_reply->DevHandle));
 		mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
 
-		if (!(ioc->logging_level & MPT_DEBUG_REPLY) &&
+		if ((ioc->logging_level & MPT_DEBUG_REPLY) &&
 		     ((scmd->sense_buffer[2] == UNIT_ATTENTION) ||
 		     (scmd->sense_buffer[2] == MEDIUM_ERROR) ||
 		     (scmd->sense_buffer[2] == HARDWARE_ERROR)))
@@ -8461,6 +8511,8 @@
 
 	switch (hba_mpi_version) {
 	case MPI2_VERSION:
+		pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
+			PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
 		/* Use mpt2sas driver host template for SAS 2.0 HBA's */
 		shost = scsi_host_alloc(&mpt2sas_driver_template,
 		  sizeof(struct MPT3SAS_ADAPTER));
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c
index 9270d15..7353ac8 100644
--- a/drivers/scsi/mvsas/mv_94xx.c
+++ b/drivers/scsi/mvsas/mv_94xx.c
@@ -621,7 +621,7 @@
 {
 	u32 tmp;
 	tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3));
-	if (tmp && 1 << (slot_idx % 32)) {
+	if (tmp & 1 << (slot_idx % 32)) {
 		mv_printk("command active %08X,  slot [%x].\n", tmp, slot_idx);
 		mvs_cw32(mvi, MVS_COMMAND_ACTIVE + (slot_idx >> 3),
 			1 << (slot_idx % 32));
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 9c78074..e712fe7 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -737,8 +737,8 @@
 			mv_dprintk("device %016llx not ready.\n",
 				SAS_ADDR(dev->sas_addr));
 
-			rc = SAS_PHY_DOWN;
-			return rc;
+		rc = SAS_PHY_DOWN;
+		return rc;
 	}
 	tei.port = dev->port->lldd_port;
 	if (tei.port && !tei.port->port_attached && !tmf) {
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 5d0ec42..634254a 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -4214,7 +4214,7 @@
 	.eh_bus_reset_handler	= qla1280_eh_bus_reset,
 	.eh_host_reset_handler	= qla1280_eh_adapter_reset,
 	.bios_param		= qla1280_biosparam,
-	.can_queue		= 0xfffff,
+	.can_queue		= MAX_OUTSTANDING_COMMANDS,
 	.this_id		= -1,
 	.sg_tablesize		= SG_ALL,
 	.use_clustering		= ENABLE_CLUSTERING,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 0e59731..1f6a3b8 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -2466,6 +2466,10 @@
 	if (pkt->entry_status & RF_BUSY)
 		res = DID_BUS_BUSY << 16;
 
+	if (pkt->entry_type == NOTIFY_ACK_TYPE &&
+	    pkt->handle == QLA_TGT_SKIP_HANDLE)
+		return;
+
 	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
 	if (sp) {
 		sp->done(ha, sp, res);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index fc6674d..5cbf20a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2257,6 +2257,8 @@
 {
 	scsi_qla_host_t *vha = shost_priv(shost);
 
+	if (test_bit(UNLOADING, &vha->dpc_flags))
+		return 1;
 	if (!vha->host)
 		return 1;
 	if (time > vha->hw->loop_reset_delay * HZ)
@@ -2309,10 +2311,10 @@
 
 	if (mem_only) {
 		if (pci_enable_device_mem(pdev))
-			goto probe_out;
+			return ret;
 	} else {
 		if (pci_enable_device(pdev))
-			goto probe_out;
+			return ret;
 	}
 
 	/* This may fail but that's ok */
@@ -2322,7 +2324,7 @@
 	if (!ha) {
 		ql_log_pci(ql_log_fatal, pdev, 0x0009,
 		    "Unable to allocate memory for ha.\n");
-		goto probe_out;
+		goto disable_device;
 	}
 	ql_dbg_pci(ql_dbg_init, pdev, 0x000a,
 	    "Memory allocated for ha=%p.\n", ha);
@@ -2921,7 +2923,7 @@
 	kfree(ha);
 	ha = NULL;
 
-probe_out:
+disable_device:
 	pci_disable_device(pdev);
 	return ret;
 }
@@ -3363,7 +3365,7 @@
 				sizeof(struct ct6_dsd), 0,
 				SLAB_HWCACHE_ALIGN, NULL);
 			if (!ctx_cachep)
-				goto fail_free_gid_list;
+				goto fail_free_srb_mempool;
 		}
 		ha->ctx_mempool = mempool_create_slab_pool(SRB_MIN_REQ,
 			ctx_cachep);
@@ -3516,7 +3518,7 @@
 	ha->loop_id_map = kzalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE) * sizeof(long),
 	    GFP_KERNEL);
 	if (!ha->loop_id_map)
-		goto fail_async_pd;
+		goto fail_loop_id_map;
 	else {
 		qla2x00_set_reserved_loop_ids(ha);
 		ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0123,
@@ -3525,6 +3527,8 @@
 
 	return 0;
 
+fail_loop_id_map:
+	dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);
 fail_async_pd:
 	dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
 fail_ex_init_cb:
@@ -3552,6 +3556,10 @@
 	dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
 	ha->ms_iocb = NULL;
 	ha->ms_iocb_dma = 0;
+
+	if (ha->sns_cmd)
+		dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
+		    ha->sns_cmd, ha->sns_cmd_dma);
 fail_dma_pool:
 	if (IS_QLA82XX(ha) || ql2xenabledif) {
 		dma_pool_destroy(ha->fcp_cmnd_dma_pool);
@@ -3569,10 +3577,12 @@
 	kfree(ha->nvram);
 	ha->nvram = NULL;
 fail_free_ctx_mempool:
-	mempool_destroy(ha->ctx_mempool);
+	if (ha->ctx_mempool)
+		mempool_destroy(ha->ctx_mempool);
 	ha->ctx_mempool = NULL;
 fail_free_srb_mempool:
-	mempool_destroy(ha->srb_mempool);
+	if (ha->srb_mempool)
+		mempool_destroy(ha->srb_mempool);
 	ha->srb_mempool = NULL;
 fail_free_gid_list:
 	dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 75514a1..e6faa0b 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1578,7 +1578,7 @@
 		qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy,
 		    0, 0, 0, 0, 0, 0);
 	else {
-		if (mcmd->se_cmd.se_tmr_req->function == TMR_ABORT_TASK)
+		if (mcmd->orig_iocb.atio.u.raw.entry_type == ABTS_RECV_24XX)
 			qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts,
 			    mcmd->fc_tm_rsp, false);
 		else
@@ -2865,7 +2865,7 @@
 
 	pkt->entry_type = NOTIFY_ACK_TYPE;
 	pkt->entry_count = 1;
-	pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
+	pkt->handle = QLA_TGT_SKIP_HANDLE;
 
 	nack = (struct nack_to_isp *)pkt;
 	nack->ox_id = ntfy->ox_id;
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index d09d602..e357a39 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -4981,6 +4981,7 @@
 	bus_unregister(&pseudo_lld_bus);
 	root_device_unregister(pseudo_primary);
 
+	vfree(map_storep);
 	vfree(dif_storep);
 	vfree(fake_storep);
 }
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index da2e068..11cdb17 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -227,6 +227,7 @@
 	{"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
 	{"Promise", "", NULL, BLIST_SPARSELUN},
+	{"QEMU", "QEMU CD-ROM", NULL, BLIST_SKIP_VPD_PAGES},
 	{"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024},
 	{"SYNOLOGY", "iSCSI Storage", NULL, BLIST_MAX_1024},
 	{"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
@@ -425,7 +426,7 @@
 	 * here, and we don't know what device it is
 	 * trying to work with, leave it as-is.
 	 */
-	vmax = 8;	/* max length of vendor */
+	vmax = sizeof(devinfo->vendor);
 	vskip = vendor;
 	while (vmax > 0 && *vskip == ' ') {
 		vmax--;
@@ -435,7 +436,7 @@
 	while (vmax > 0 && vskip[vmax - 1] == ' ')
 		--vmax;
 
-	mmax = 16;	/* max length of model */
+	mmax = sizeof(devinfo->model);
 	mskip = model;
 	while (mmax > 0 && *mskip == ' ') {
 		mmax--;
@@ -451,10 +452,12 @@
 			 * Behave like the older version of get_device_flags.
 			 */
 			if (memcmp(devinfo->vendor, vskip, vmax) ||
-					devinfo->vendor[vmax])
+					(vmax < sizeof(devinfo->vendor) &&
+						devinfo->vendor[vmax]))
 				continue;
 			if (memcmp(devinfo->model, mskip, mmax) ||
-					devinfo->model[mmax])
+					(mmax < sizeof(devinfo->model) &&
+						devinfo->model[mmax]))
 				continue;
 			return devinfo;
 		} else {
diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index e7649ed..4d655b5 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -289,20 +289,6 @@
 }
 EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
 
-static struct scsi_device *get_sdev_from_queue(struct request_queue *q)
-{
-	struct scsi_device *sdev;
-	unsigned long flags;
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	sdev = q->queuedata;
-	if (!sdev || !get_device(&sdev->sdev_gendev))
-		sdev = NULL;
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
-	return sdev;
-}
-
 /*
  * scsi_dh_activate - activate the path associated with the scsi_device
  *      corresponding to the given request queue.
@@ -321,7 +307,7 @@
 	struct scsi_device *sdev;
 	int err = SCSI_DH_NOSYS;
 
-	sdev = get_sdev_from_queue(q);
+	sdev = scsi_device_from_queue(q);
 	if (!sdev) {
 		if (fn)
 			fn(data, err);
@@ -368,7 +354,7 @@
 	struct scsi_device *sdev;
 	int err = -SCSI_DH_NOSYS;
 
-	sdev = get_sdev_from_queue(q);
+	sdev = scsi_device_from_queue(q);
 	if (!sdev)
 		return err;
 
@@ -391,7 +377,7 @@
 	struct scsi_device_handler *scsi_dh;
 	int err = 0;
 
-	sdev = get_sdev_from_queue(q);
+	sdev = scsi_device_from_queue(q);
 	if (!sdev)
 		return -ENODEV;
 
@@ -429,7 +415,7 @@
 	struct scsi_device *sdev;
 	const char *handler_name = NULL;
 
-	sdev = get_sdev_from_queue(q);
+	sdev = scsi_device_from_queue(q);
 	if (!sdev)
 		return NULL;
 
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 984ddcb..1b9c049 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1127,7 +1127,6 @@
  */
 void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
 {
-	scmd->device->host->host_failed--;
 	scmd->eh_eflags = 0;
 	list_move_tail(&scmd->eh_entry, done_q);
 }
@@ -2226,6 +2225,9 @@
 		else
 			scsi_unjam_host(shost);
 
+		/* All scmds have been handled */
+		shost->host_failed = 0;
+
 		/*
 		 * Note - if the above fails completely, the action is to take
 		 * individual devices offline and flush the queue of any
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index dd8ad2a..887045a 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -910,9 +910,12 @@
 	}
 
 	/*
-	 * If we finished all bytes in the request we are done now.
+	 * special case: failed zero length commands always need to
+	 * drop down into the retry code. Otherwise, if we finished
+	 * all bytes in the request we are done now.
 	 */
-	if (!scsi_end_request(req, error, good_bytes, 0))
+	if (!(blk_rq_bytes(req) == 0 && error) &&
+	    !scsi_end_request(req, error, good_bytes, 0))
 		return;
 
 	/*
@@ -1117,7 +1120,8 @@
 	bool is_mq = (rq->mq_ctx != NULL);
 	int error;
 
-	BUG_ON(!rq->nr_phys_segments);
+	if (WARN_ON_ONCE(!rq->nr_phys_segments))
+		return -EINVAL;
 
 	error = scsi_init_sgtable(rq, &cmd->sdb);
 	if (error)
@@ -2211,6 +2215,29 @@
 	blk_mq_free_tag_set(&shost->tag_set);
 }
 
+/**
+ * scsi_device_from_queue - return sdev associated with a request_queue
+ * @q: The request queue to return the sdev from
+ *
+ * Return the sdev associated with a request queue or NULL if the
+ * request_queue does not reference a SCSI device.
+ */
+struct scsi_device *scsi_device_from_queue(struct request_queue *q)
+{
+	struct scsi_device *sdev = NULL;
+
+	if (q->mq_ops) {
+		if (q->mq_ops == &scsi_mq_ops)
+			sdev = q->queuedata;
+	} else if (q->request_fn == scsi_request_fn)
+		sdev = q->queuedata;
+	if (!sdev || !get_device(&sdev->sdev_gendev))
+		sdev = NULL;
+
+	return sdev;
+}
+EXPORT_SYMBOL_GPL(scsi_device_from_queue);
+
 /*
  * Function:    scsi_block_requests()
  *
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 054923e..692445b 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -314,6 +314,7 @@
 	struct Scsi_Host *shost = dev_to_shost(dev->parent);
 	unsigned long flags;
 
+	BUG_ON(starget->state == STARGET_DEL);
 	starget->state = STARGET_DEL;
 	transport_destroy_device(dev);
 	spin_lock_irqsave(shost->host_lock, flags);
@@ -1458,12 +1459,12 @@
  out_err:
 	kfree(lun_data);
  out:
-	scsi_device_put(sdev);
 	if (scsi_device_created(sdev))
 		/*
 		 * the sdev we used didn't appear in the report luns scan
 		 */
 		__scsi_remove_device(sdev);
+	scsi_device_put(sdev);
 	return ret;
 }
 
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index c8115b4..4477e99 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1031,10 +1031,6 @@
 	struct request_queue *rq = sdev->request_queue;
 	struct scsi_target *starget = sdev->sdev_target;
 
-	error = scsi_device_set_state(sdev, SDEV_RUNNING);
-	if (error)
-		return error;
-
 	error = scsi_target_add(starget);
 	if (error)
 		return error;
@@ -1058,11 +1054,12 @@
 	}
 
 	error = scsi_dh_add_device(sdev);
-	if (error) {
+	if (error)
+		/*
+		 * device_handler is optional, so any error can be ignored
+		 */
 		sdev_printk(KERN_INFO, sdev,
 				"failed to add device handler: %d\n", error);
-		return error;
-	}
 
 	device_enable_async_suspend(&sdev->sdev_dev);
 	error = device_add(&sdev->sdev_dev);
@@ -1192,18 +1189,18 @@
 void scsi_remove_target(struct device *dev)
 {
 	struct Scsi_Host *shost = dev_to_shost(dev->parent);
-	struct scsi_target *starget, *last_target = NULL;
+	struct scsi_target *starget;
 	unsigned long flags;
 
 restart:
 	spin_lock_irqsave(shost->host_lock, flags);
 	list_for_each_entry(starget, &shost->__targets, siblings) {
 		if (starget->state == STARGET_DEL ||
-		    starget == last_target)
+		    starget->state == STARGET_REMOVE)
 			continue;
 		if (starget->dev.parent == dev || &starget->dev == dev) {
 			kref_get(&starget->reap_ref);
-			last_target = starget;
+			starget->state = STARGET_REMOVE;
 			spin_unlock_irqrestore(shost->host_lock, flags);
 			__scsi_remove_target(starget);
 			scsi_target_reap(starget);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 0d7c6e8..8750c86 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1398,11 +1398,15 @@
  **/
 static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
 {
-	struct scsi_disk *sdkp = scsi_disk(disk);
-	struct scsi_device *sdp = sdkp->device;
+	struct scsi_disk *sdkp = scsi_disk_get(disk);
+	struct scsi_device *sdp;
 	struct scsi_sense_hdr *sshdr = NULL;
 	int retval;
 
+	if (!sdkp)
+		return 0;
+
+	sdp = sdkp->device;
 	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n"));
 
 	/*
@@ -1459,6 +1463,7 @@
 	kfree(sshdr);
 	retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0;
 	sdp->changed = 0;
+	scsi_disk_put(sdkp);
 	return retval;
 }
 
@@ -2046,6 +2051,22 @@
 
 #define READ_CAPACITY_RETRIES_ON_RESET	10
 
+/*
+ * Ensure that we don't overflow sector_t when CONFIG_LBDAF is not set
+ * and the reported logical block size is bigger than 512 bytes. Note
+ * that last_sector is a u64 and therefore logical_to_sectors() is not
+ * applicable.
+ */
+static bool sd_addressable_capacity(u64 lba, unsigned int sector_size)
+{
+	u64 last_sector = (lba + 1ULL) << (ilog2(sector_size) - 9);
+
+	if (sizeof(sector_t) == 4 && last_sector > U32_MAX)
+		return false;
+
+	return true;
+}
+
 static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
 						unsigned char *buffer)
 {
@@ -2111,7 +2132,7 @@
 		return -ENODEV;
 	}
 
-	if ((sizeof(sdkp->capacity) == 4) && (lba >= 0xffffffffULL)) {
+	if (!sd_addressable_capacity(lba, sector_size)) {
 		sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
 			"kernel compiled with support for large block "
 			"devices.\n");
@@ -2197,7 +2218,7 @@
 		return sector_size;
 	}
 
-	if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) {
+	if (!sd_addressable_capacity(lba, sector_size)) {
 		sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
 			"kernel compiled with support for large block "
 			"devices.\n");
@@ -2545,7 +2566,8 @@
 		if (sdp->broken_fua) {
 			sd_first_printk(KERN_NOTICE, sdkp, "Disabling FUA\n");
 			sdkp->DPOFUA = 0;
-		} else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
+		} else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw &&
+			   !sdkp->device->use_16_for_rw) {
 			sd_first_printk(KERN_NOTICE, sdkp,
 				  "Uses READ/WRITE(6), disabling FUA\n");
 			sdkp->DPOFUA = 0;
@@ -2879,11 +2901,12 @@
 	if (sdkp->opt_xfer_blocks &&
 	    sdkp->opt_xfer_blocks <= dev_max &&
 	    sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS &&
-	    sdkp->opt_xfer_blocks * sdp->sector_size >= PAGE_CACHE_SIZE)
-		rw_max = q->limits.io_opt =
-			sdkp->opt_xfer_blocks * sdp->sector_size;
-	else
-		rw_max = BLK_DEF_MAX_SECTORS;
+	    logical_to_bytes(sdp, sdkp->opt_xfer_blocks) >= PAGE_CACHE_SIZE) {
+		q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks);
+		rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
+	} else
+		rw_max = min_not_zero(logical_to_sectors(sdp, dev_max),
+				      (sector_t)BLK_DEF_MAX_SECTORS);
 
 	/* Combine with controller limits */
 	q->limits.max_sectors = min(rw_max, queue_max_hw_sectors(q));
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 654630b..765a6f1 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -151,6 +151,11 @@
 	return blocks << (ilog2(sdev->sector_size) - 9);
 }
 
+static inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t blocks)
+{
+	return blocks * sdev->sector_size;
+}
+
 /*
  * A DIF-capable target device can be formatted with different
  * protection schemes.  Currently 0 through 3 are defined:
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ae7d9bd..6514636 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -592,6 +592,9 @@
 	sg_io_hdr_t *hp;
 	unsigned char cmnd[SG_MAX_CDB_SIZE];
 
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+		return -EINVAL;
+
 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
 		return -ENXIO;
 	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
@@ -1005,6 +1008,8 @@
 		result = get_user(val, ip);
 		if (result)
 			return result;
+		if (val > SG_MAX_CDB_SIZE)
+			return -ENOMEM;
 		sfp->next_cmd_len = (val > 0) ? val : 0;
 		return 0;
 	case SG_GET_VERSION_NUM:
@@ -1760,6 +1765,10 @@
 			return res;
 
 		iov_iter_truncate(&i, hp->dxfer_len);
+		if (!iov_iter_count(&i)) {
+			kfree(iov);
+			return -EINVAL;
+		}
 
 		res = blk_rq_map_user_iov(q, rq, md, &i, GFP_ATOMIC);
 		kfree(iov);
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 64c8674..804586a 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -834,6 +834,7 @@
 	unsigned char *buffer;
 	struct scsi_mode_data data;
 	struct scsi_sense_hdr sshdr;
+	unsigned int ms_len = 128;
 	int rc, n;
 
 	static const char *loadmech[] =
@@ -860,10 +861,11 @@
 	scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
 
 	/* ask for mode page 0x2a */
-	rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,
+	rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len,
 			     SR_TIMEOUT, 3, &data, NULL);
 
-	if (!scsi_status_is_good(rc)) {
+	if (!scsi_status_is_good(rc) || data.length > ms_len ||
+	    data.header_length + data.block_descriptor_length > data.length) {
 		/* failed, drive doesn't have capabilities mode page */
 		cd->cdi.speed = 1;
 		cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 0f636cc..cd5c1c0 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -135,6 +135,8 @@
 #define SRB_FLAGS_PORT_DRIVER_RESERVED		0x0F000000
 #define SRB_FLAGS_CLASS_DRIVER_RESERVED		0xF0000000
 
+#define SP_UNTAGGED			((unsigned char) ~0)
+#define SRB_SIMPLE_TAG_REQUEST		0x20
 
 /*
  * Platform neutral description of a scsi request -
@@ -354,6 +356,7 @@
 #define SRB_STATUS_SUCCESS	0x01
 #define SRB_STATUS_ABORTED	0x02
 #define SRB_STATUS_ERROR	0x04
+#define SRB_STATUS_DATA_OVERRUN	0x12
 
 #define SRB_STATUS(status) \
 	(status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN))
@@ -864,6 +867,13 @@
 	switch (SRB_STATUS(vm_srb->srb_status)) {
 	case SRB_STATUS_ERROR:
 		/*
+		 * Let upper layer deal with error when
+		 * sense message is present.
+		 */
+
+		if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID)
+			break;
+		/*
 		 * If there is an error; offline the device since all
 		 * error recovery strategies would have already been
 		 * deployed on the host side. However, if the command
@@ -927,6 +937,7 @@
 	struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
 	struct scsi_sense_hdr sense_hdr;
 	struct vmscsi_request *vm_srb;
+	u32 data_transfer_length;
 	struct Scsi_Host *host;
 	struct storvsc_device *stor_dev;
 	struct hv_device *dev = host_dev->dev;
@@ -937,6 +948,7 @@
 	host = stor_dev->host;
 
 	vm_srb = &cmd_request->vstor_packet.vm_srb;
+	data_transfer_length = vm_srb->data_transfer_length;
 
 	scmnd->result = vm_srb->scsi_status;
 
@@ -947,13 +959,20 @@
 					     &sense_hdr);
 	}
 
-	if (vm_srb->srb_status != SRB_STATUS_SUCCESS)
+	if (vm_srb->srb_status != SRB_STATUS_SUCCESS) {
 		storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc,
 					 sense_hdr.ascq);
+		/*
+		 * The Windows driver set data_transfer_length on
+		 * SRB_STATUS_DATA_OVERRUN. On other errors, this value
+		 * is untouched.  In these cases we set it to 0.
+		 */
+		if (vm_srb->srb_status != SRB_STATUS_DATA_OVERRUN)
+			data_transfer_length = 0;
+	}
 
 	scsi_set_resid(scmnd,
-		cmd_request->payload->range.len -
-		vm_srb->data_transfer_length);
+		cmd_request->payload->range.len - data_transfer_length);
 
 	scmnd->scsi_done(scmnd);
 
@@ -1409,6 +1428,13 @@
 	vm_srb->win8_extension.srb_flags |=
 		SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
 
+	if (scmnd->device->tagged_supported) {
+		vm_srb->win8_extension.srb_flags |=
+		(SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE);
+		vm_srb->win8_extension.queue_tag = SP_UNTAGGED;
+		vm_srb->win8_extension.queue_action = SRB_SIMPLE_TAG_REQUEST;
+	}
+
 	/* Build the SRB */
 	switch (scmnd->sc_data_direction) {
 	case DMA_TO_DEVICE:
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 85cd256..4167bdb 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -39,6 +39,7 @@
 
 #include <linux/async.h>
 #include <linux/devfreq.h>
+#include <linux/blkdev.h>
 
 #include "ufshcd.h"
 #include "unipro.h"
@@ -1332,6 +1333,17 @@
 		clear_bit_unlock(tag, &hba->lrb_in_use);
 		goto out;
 	}
+
+	/* IO svc time latency histogram */
+	if (hba != NULL && cmd->request != NULL) {
+		if (hba->latency_hist_enabled &&
+		    (cmd->request->cmd_type == REQ_TYPE_FS)) {
+			cmd->request->lat_hist_io_start = ktime_get();
+			cmd->request->lat_hist_enabled = 1;
+		} else
+			cmd->request->lat_hist_enabled = 0;
+	}
+
 	WARN_ON(hba->clk_gating.state != CLKS_ON);
 
 	lrbp = &hba->lrb[tag];
@@ -3160,6 +3172,7 @@
 	u32 tr_doorbell;
 	int result;
 	int index;
+	struct request *req;
 
 	/* Resetting interrupt aggregation counters first and reading the
 	 * DOOR_BELL afterward allows us to handle all the completed requests.
@@ -3184,6 +3197,22 @@
 			/* Mark completed command as NULL in LRB */
 			lrbp->cmd = NULL;
 			clear_bit_unlock(index, &hba->lrb_in_use);
+			req = cmd->request;
+			if (req) {
+				/* Update IO svc time latency histogram */
+				if (req->lat_hist_enabled) {
+					ktime_t completion;
+					u_int64_t delta_us;
+
+					completion = ktime_get();
+					delta_us = ktime_us_delta(completion,
+						  req->lat_hist_io_start);
+					/* rq_data_dir() => true if WRITE */
+					blk_update_latency_hist(&hba->io_lat_s,
+						(rq_data_dir(req) == READ),
+						delta_us);
+				}
+			}
 			/* Do not touch lrbp after scsi done */
 			cmd->scsi_done(cmd);
 			__ufshcd_release(hba);
@@ -5327,6 +5356,54 @@
 }
 EXPORT_SYMBOL(ufshcd_shutdown);
 
+/*
+ * Values permitted 0, 1, 2.
+ * 0 -> Disable IO latency histograms (default)
+ * 1 -> Enable IO latency histograms
+ * 2 -> Zero out IO latency histograms
+ */
+static ssize_t
+latency_hist_store(struct device *dev, struct device_attribute *attr,
+		   const char *buf, size_t count)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+	long value;
+
+	if (kstrtol(buf, 0, &value))
+		return -EINVAL;
+	if (value == BLK_IO_LAT_HIST_ZERO)
+		blk_zero_latency_hist(&hba->io_lat_s);
+	else if (value == BLK_IO_LAT_HIST_ENABLE ||
+		 value == BLK_IO_LAT_HIST_DISABLE)
+		hba->latency_hist_enabled = value;
+	return count;
+}
+
+ssize_t
+latency_hist_show(struct device *dev, struct device_attribute *attr,
+		  char *buf)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+
+	return blk_latency_hist_show(&hba->io_lat_s, buf);
+}
+
+static DEVICE_ATTR(latency_hist, S_IRUGO | S_IWUSR,
+		   latency_hist_show, latency_hist_store);
+
+static void
+ufshcd_init_latency_hist(struct ufs_hba *hba)
+{
+	if (device_create_file(hba->dev, &dev_attr_latency_hist))
+		dev_err(hba->dev, "Failed to create latency_hist sysfs entry\n");
+}
+
+static void
+ufshcd_exit_latency_hist(struct ufs_hba *hba)
+{
+	device_create_file(hba->dev, &dev_attr_latency_hist);
+}
+
 /**
  * ufshcd_remove - de-allocate SCSI host and host memory space
  *		data structure memory
@@ -5342,6 +5419,7 @@
 	scsi_host_put(hba->host);
 
 	ufshcd_exit_clk_gating(hba);
+	ufshcd_exit_latency_hist(hba);
 	if (ufshcd_is_clkscaling_enabled(hba))
 		devfreq_remove_device(hba->devfreq);
 	ufshcd_hba_exit(hba);
@@ -5639,6 +5717,8 @@
 	/* Hold auto suspend until async scan completes */
 	pm_runtime_get_sync(dev);
 
+	ufshcd_init_latency_hist(hba);
+
 	/*
 	 * The device-initialize-sequence hasn't been invoked yet.
 	 * Set the device to power-off state
@@ -5653,6 +5733,7 @@
 	scsi_remove_host(hba->host);
 exit_gating:
 	ufshcd_exit_clk_gating(hba);
+	ufshcd_exit_latency_hist(hba);
 out_disable:
 	hba->is_irq_enabled = false;
 	scsi_host_put(host);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 2570d94..f3780cf 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -532,6 +532,9 @@
 	struct devfreq *devfreq;
 	struct ufs_clk_scaling clk_scaling;
 	bool is_sys_suspended;
+
+	int			latency_hist_enabled;
+	struct io_latency_state io_lat_s;
 };
 
 /* Returns true if clocks can be gated. Otherwise false */
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 7dbbb29..03a2aad 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -533,7 +533,9 @@
 {
 	struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
 	struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc);
+	unsigned long flags;
 	int req_size;
+	int ret;
 
 	BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize);
 
@@ -561,8 +563,15 @@
 		req_size = sizeof(cmd->req.cmd);
 	}
 
-	if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)) != 0)
+	ret = virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd));
+	if (ret == -EIO) {
+		cmd->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
+		spin_lock_irqsave(&req_vq->vq_lock, flags);
+		virtscsi_complete_cmd(vscsi, cmd);
+		spin_unlock_irqrestore(&req_vq->vq_lock, flags);
+	} else if (ret != 0) {
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 	return 0;
 }
 
diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c
index b04b05a..65bce1e 100644
--- a/drivers/soc/qcom/spm.c
+++ b/drivers/soc/qcom/spm.c
@@ -288,7 +288,7 @@
 	struct spm_driver_data *drv = NULL;
 	struct device_node *cpu_node, *saw_node;
 	int cpu;
-	bool found;
+	bool found = 0;
 
 	for_each_possible_cpu(cpu) {
 		cpu_node = of_cpu_device_node_get(cpu);
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 7d3af3e..1ddba9a 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -651,7 +651,7 @@
 			buf = t->rx_buf;
 		t->rx_dma = dma_map_single(&spi->dev, buf,
 				t->len, DMA_FROM_DEVICE);
-		if (!t->rx_dma) {
+		if (dma_mapping_error(&spi->dev, !t->rx_dma)) {
 			ret = -EFAULT;
 			goto err_rx_map;
 		}
@@ -665,7 +665,7 @@
 			buf = (void *)t->tx_buf;
 		t->tx_dma = dma_map_single(&spi->dev, buf,
 				t->len, DMA_TO_DEVICE);
-		if (!t->tx_dma) {
+		if (dma_mapping_error(&spi->dev, t->tx_dma)) {
 			ret = -EFAULT;
 			goto err_tx_map;
 		}
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 39412c9..a3965ca 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -753,7 +753,6 @@
 	/* Disconnect from the SPI framework */
 	clk_disable_unprepare(dspi->clk);
 	spi_unregister_master(dspi->master);
-	spi_master_put(dspi->master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index a87cfd4..61a86d3 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -127,37 +127,62 @@
 	tclk_hz = clk_get_rate(orion_spi->clk);
 
 	if (devdata->typ == ARMADA_SPI) {
-		unsigned int clk, spr, sppr, sppr2, err;
-		unsigned int best_spr, best_sppr, best_err;
+		/*
+		 * Given the core_clk (tclk_hz) and the target rate (speed) we
+		 * determine the best values for SPR (in [0 .. 15]) and SPPR (in
+		 * [0..7]) such that
+		 *
+		 * 	core_clk / (SPR * 2 ** SPPR)
+		 *
+		 * is as big as possible but not bigger than speed.
+		 */
 
-		best_err = speed;
-		best_spr = 0;
-		best_sppr = 0;
+		/* best integer divider: */
+		unsigned divider = DIV_ROUND_UP(tclk_hz, speed);
+		unsigned spr, sppr;
 
-		/* Iterate over the valid range looking for best fit */
-		for (sppr = 0; sppr < 8; sppr++) {
-			sppr2 = 0x1 << sppr;
+		if (divider < 16) {
+			/* This is the easy case, divider is less than 16 */
+			spr = divider;
+			sppr = 0;
 
-			spr = tclk_hz / sppr2;
-			spr = DIV_ROUND_UP(spr, speed);
-			if ((spr == 0) || (spr > 15))
-				continue;
+		} else {
+			unsigned two_pow_sppr;
+			/*
+			 * Find the highest bit set in divider. This and the
+			 * three next bits define SPR (apart from rounding).
+			 * SPPR is then the number of zero bits that must be
+			 * appended:
+			 */
+			sppr = fls(divider) - 4;
 
-			clk = tclk_hz / (spr * sppr2);
-			err = speed - clk;
+			/*
+			 * As SPR only has 4 bits, we have to round divider up
+			 * to the next multiple of 2 ** sppr.
+			 */
+			two_pow_sppr = 1 << sppr;
+			divider = (divider + two_pow_sppr - 1) & -two_pow_sppr;
 
-			if (err < best_err) {
-				best_spr = spr;
-				best_sppr = sppr;
-				best_err = err;
-			}
+			/*
+			 * recalculate sppr as rounding up divider might have
+			 * increased it enough to change the position of the
+			 * highest set bit. In this case the bit that now
+			 * doesn't make it into SPR is 0, so there is no need to
+			 * round again.
+			 */
+			sppr = fls(divider) - 4;
+			spr = divider >> sppr;
+
+			/*
+			 * Now do range checking. SPR is constructed to have a
+			 * width of 4 bits, so this is fine for sure. So we
+			 * still need to check for sppr to fit into 3 bits:
+			 */
+			if (sppr > 7)
+				return -EINVAL;
 		}
 
-		if ((best_sppr == 0) && (best_spr == 0))
-			return -EINVAL;
-
-		prescale = ((best_sppr & 0x6) << 5) |
-			((best_sppr & 0x1) << 4) | best_spr;
+		prescale = ((sppr & 0x6) << 5) | ((sppr & 0x1) << 4) | spr;
 	} else {
 		/*
 		 * the supported rates are: 4,6,8...30
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index b25dc71..3cac73e 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -111,7 +111,7 @@
 		.reg_general = -1,
 		.reg_ssp = 0x20,
 		.reg_cs_ctrl = 0x24,
-		.reg_capabilities = 0xfc,
+		.reg_capabilities = -1,
 		.rx_threshold = 1,
 		.tx_threshold_lo = 32,
 		.tx_threshold_hi = 56,
@@ -548,7 +548,14 @@
 	u32 sccr1_reg;
 
 	sccr1_reg = pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1;
-	sccr1_reg &= ~SSCR1_RFT;
+	switch (drv_data->ssp_type) {
+	case QUARK_X1000_SSP:
+		sccr1_reg &= ~QUARK_X1000_SSCR1_RFT;
+		break;
+	default:
+		sccr1_reg &= ~SSCR1_RFT;
+		break;
+	}
 	sccr1_reg |= chip->threshold;
 	pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg);
 }
diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index b368f26..035767c 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -199,7 +199,6 @@
 	struct sg_table rx_sg;
 	struct rockchip_spi_dma_data dma_rx;
 	struct rockchip_spi_dma_data dma_tx;
-	struct dma_slave_caps dma_caps;
 };
 
 static inline void spi_enable_chip(struct rockchip_spi *rs, int enable)
@@ -455,10 +454,7 @@
 		rxconf.direction = rs->dma_rx.direction;
 		rxconf.src_addr = rs->dma_rx.addr;
 		rxconf.src_addr_width = rs->n_bytes;
-		if (rs->dma_caps.max_burst > 4)
-			rxconf.src_maxburst = 4;
-		else
-			rxconf.src_maxburst = 1;
+		rxconf.src_maxburst = rs->n_bytes;
 		dmaengine_slave_config(rs->dma_rx.ch, &rxconf);
 
 		rxdesc = dmaengine_prep_slave_sg(
@@ -475,10 +471,7 @@
 		txconf.direction = rs->dma_tx.direction;
 		txconf.dst_addr = rs->dma_tx.addr;
 		txconf.dst_addr_width = rs->n_bytes;
-		if (rs->dma_caps.max_burst > 4)
-			txconf.dst_maxburst = 4;
-		else
-			txconf.dst_maxburst = 1;
+		txconf.dst_maxburst = rs->n_bytes;
 		dmaengine_slave_config(rs->dma_tx.ch, &txconf);
 
 		txdesc = dmaengine_prep_slave_sg(
@@ -742,7 +735,6 @@
 	}
 
 	if (rs->dma_tx.ch && rs->dma_rx.ch) {
-		dma_get_slave_caps(rs->dma_rx.ch, &(rs->dma_caps));
 		rs->dma_tx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_TXDR);
 		rs->dma_rx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_RXDR);
 		rs->dma_tx.direction = DMA_MEM_TO_DEV;
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index a7934ab..d22de4c 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -263,6 +263,9 @@
 
 	for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_div_table); k++) {
 		brps = DIV_ROUND_UP(div, sh_msiof_spi_div_table[k].div);
+		/* SCR_BRDV_DIV_1 is valid only if BRPS is x 1/1 or x 1/2 */
+		if (sh_msiof_spi_div_table[k].div == 1 && brps > 2)
+			continue;
 		if (brps <= 32) /* max of brdv is 32 */
 			break;
 	}
diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index fbb0a4d..39d7c7c 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -170,13 +170,17 @@
 {
 	struct sun4i_spi *sspi = spi_master_get_devdata(master);
 	unsigned int mclk_rate, div, timeout;
+	unsigned int start, end, tx_time;
 	unsigned int tx_len = 0;
 	int ret = 0;
 	u32 reg;
 
 	/* We don't support transfer larger than the FIFO */
 	if (tfr->len > SUN4I_FIFO_DEPTH)
-		return -EINVAL;
+		return -EMSGSIZE;
+
+	if (tfr->tx_buf && tfr->len >= SUN4I_FIFO_DEPTH)
+		return -EMSGSIZE;
 
 	reinit_completion(&sspi->done);
 	sspi->tx_buf = tfr->tx_buf;
@@ -269,8 +273,12 @@
 	sun4i_spi_write(sspi, SUN4I_BURST_CNT_REG, SUN4I_BURST_CNT(tfr->len));
 	sun4i_spi_write(sspi, SUN4I_XMIT_CNT_REG, SUN4I_XMIT_CNT(tx_len));
 
-	/* Fill the TX FIFO */
-	sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
+	/*
+	 * Fill the TX FIFO
+	 * Filling the FIFO fully causes timeout for some reason
+	 * at least on spi2 on A10s
+	 */
+	sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1);
 
 	/* Enable the interrupts */
 	sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC);
@@ -279,9 +287,16 @@
 	reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
 	sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
 
+	tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
+	start = jiffies;
 	timeout = wait_for_completion_timeout(&sspi->done,
-					      msecs_to_jiffies(1000));
+					      msecs_to_jiffies(tx_time));
+	end = jiffies;
 	if (!timeout) {
+		dev_warn(&master->dev,
+			 "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+			 dev_name(&spi->dev), tfr->len, tfr->speed_hz,
+			 jiffies_to_msecs(end - start), tx_time);
 		ret = -ETIMEDOUT;
 		goto out;
 	}
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index ac48f59..e77add0 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -160,6 +160,7 @@
 {
 	struct sun6i_spi *sspi = spi_master_get_devdata(master);
 	unsigned int mclk_rate, div, timeout;
+	unsigned int start, end, tx_time;
 	unsigned int tx_len = 0;
 	int ret = 0;
 	u32 reg;
@@ -269,9 +270,16 @@
 	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
 	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
 
+	tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
+	start = jiffies;
 	timeout = wait_for_completion_timeout(&sspi->done,
-					      msecs_to_jiffies(1000));
+					      msecs_to_jiffies(tx_time));
+	end = jiffies;
 	if (!timeout) {
+		dev_warn(&master->dev,
+			 "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+			 dev_name(&spi->dev), tfr->len, tfr->speed_hz,
+			 jiffies_to_msecs(end - start), tx_time);
 		ret = -ETIMEDOUT;
 		goto out;
 	}
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 64318fc..5044c61 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -94,6 +94,7 @@
 #define QSPI_FLEN(n)			((n - 1) << 0)
 #define QSPI_WLEN_MAX_BITS		128
 #define QSPI_WLEN_MAX_BYTES		16
+#define QSPI_WLEN_MASK			QSPI_WLEN(QSPI_WLEN_MAX_BITS)
 
 /* STATUS REGISTER */
 #define BUSY				0x01
@@ -224,16 +225,16 @@
 	return  -ETIMEDOUT;
 }
 
-static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
+static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t,
+			  int count)
 {
-	int wlen, count, xfer_len;
+	int wlen, xfer_len;
 	unsigned int cmd;
 	const u8 *txbuf;
 	u32 data;
 
 	txbuf = t->tx_buf;
 	cmd = qspi->cmd | QSPI_WR_SNGL;
-	count = t->len;
 	wlen = t->bits_per_word >> 3;	/* in bytes */
 	xfer_len = wlen;
 
@@ -293,9 +294,10 @@
 	return 0;
 }
 
-static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
+static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
+			 int count)
 {
-	int wlen, count;
+	int wlen;
 	unsigned int cmd;
 	u8 *rxbuf;
 
@@ -312,7 +314,6 @@
 		cmd |= QSPI_RD_SNGL;
 		break;
 	}
-	count = t->len;
 	wlen = t->bits_per_word >> 3;	/* in bytes */
 
 	while (count) {
@@ -343,12 +344,13 @@
 	return 0;
 }
 
-static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
+static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t,
+			     int count)
 {
 	int ret;
 
 	if (t->tx_buf) {
-		ret = qspi_write_msg(qspi, t);
+		ret = qspi_write_msg(qspi, t, count);
 		if (ret) {
 			dev_dbg(qspi->dev, "Error while writing\n");
 			return ret;
@@ -356,7 +358,7 @@
 	}
 
 	if (t->rx_buf) {
-		ret = qspi_read_msg(qspi, t);
+		ret = qspi_read_msg(qspi, t, count);
 		if (ret) {
 			dev_dbg(qspi->dev, "Error while reading\n");
 			return ret;
@@ -373,7 +375,8 @@
 	struct spi_device *spi = m->spi;
 	struct spi_transfer *t;
 	int status = 0, ret;
-	int frame_length;
+	unsigned int frame_len_words, transfer_len_words;
+	int wlen;
 
 	/* setup device control reg */
 	qspi->dc = 0;
@@ -385,30 +388,38 @@
 	if (spi->mode & SPI_CS_HIGH)
 		qspi->dc |= QSPI_CSPOL(spi->chip_select);
 
-	frame_length = (m->frame_length << 3) / spi->bits_per_word;
-
-	frame_length = clamp(frame_length, 0, QSPI_FRAME);
+	frame_len_words = 0;
+	list_for_each_entry(t, &m->transfers, transfer_list)
+		frame_len_words += t->len / (t->bits_per_word >> 3);
+	frame_len_words = min_t(unsigned int, frame_len_words, QSPI_FRAME);
 
 	/* setup command reg */
 	qspi->cmd = 0;
 	qspi->cmd |= QSPI_EN_CS(spi->chip_select);
-	qspi->cmd |= QSPI_FLEN(frame_length);
+	qspi->cmd |= QSPI_FLEN(frame_len_words);
 
 	ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG);
 
 	mutex_lock(&qspi->list_lock);
 
 	list_for_each_entry(t, &m->transfers, transfer_list) {
-		qspi->cmd |= QSPI_WLEN(t->bits_per_word);
+		qspi->cmd = ((qspi->cmd & ~QSPI_WLEN_MASK) |
+			     QSPI_WLEN(t->bits_per_word));
 
-		ret = qspi_transfer_msg(qspi, t);
+		wlen = t->bits_per_word >> 3;
+		transfer_len_words = min(t->len / wlen, frame_len_words);
+
+		ret = qspi_transfer_msg(qspi, t, transfer_len_words * wlen);
 		if (ret) {
 			dev_dbg(qspi->dev, "transfer message failed\n");
 			mutex_unlock(&qspi->list_lock);
 			return -EINVAL;
 		}
 
-		m->actual_length += t->len;
+		m->actual_length += transfer_len_words * wlen;
+		frame_len_words -= transfer_len_words;
+		if (frame_len_words == 0)
+			break;
 	}
 
 	mutex_unlock(&qspi->list_lock);
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 0f28c08..77b551d 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -909,6 +909,7 @@
 			if (err) {
 				ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
 					 err);
+				goto out_free;
 			} else {
 				ssb_dbg("Using SPROM revision %d provided by platform\n",
 					sprom->revision);
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 6e8557f..0c0c092 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -77,6 +77,8 @@
 
 source "drivers/staging/android/ion/Kconfig"
 
+source "drivers/staging/android/fiq_debugger/Kconfig"
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index c7b6c99..fcb7edc 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -1,6 +1,7 @@
 ccflags-y += -I$(src)			# needed for trace events
 
 obj-y					+= ion/
+obj-$(CONFIG_FIQ_DEBUGGER)		+= fiq_debugger/
 
 obj-$(CONFIG_ASHMEM)			+= ashmem.o
 obj-$(CONFIG_ANDROID_TIMED_OUTPUT)	+= timed_output.o
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 3f11332..e4530ac 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -392,6 +392,7 @@
 			ret = PTR_ERR(vmfile);
 			goto out;
 		}
+		vmfile->f_mode |= FMODE_LSEEK;
 		asma->file = vmfile;
 	}
 	get_file(asma->file);
diff --git a/drivers/staging/android/fiq_debugger/Kconfig b/drivers/staging/android/fiq_debugger/Kconfig
new file mode 100644
index 0000000..60fc224
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/Kconfig
@@ -0,0 +1,58 @@
+config FIQ_DEBUGGER
+	bool "FIQ Mode Serial Debugger"
+	default n
+	depends on ARM || ARM64
+	help
+	  The FIQ serial debugger can accept commands even when the
+	  kernel is unresponsive due to being stuck with interrupts
+	  disabled.
+
+config FIQ_DEBUGGER_NO_SLEEP
+	bool "Keep serial debugger active"
+	depends on FIQ_DEBUGGER
+	default n
+	help
+	  Enables the serial debugger at boot. Passing
+	  fiq_debugger.no_sleep on the kernel commandline will
+	  override this config option.
+
+config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
+	bool "Don't disable wakeup IRQ when debugger is active"
+	depends on FIQ_DEBUGGER
+	default n
+	help
+	  Don't disable the wakeup irq when enabling the uart clock.  This will
+	  cause extra interrupts, but it makes the serial debugger usable with
+	  on some MSM radio builds that ignore the uart clock request in power
+	  collapse.
+
+config FIQ_DEBUGGER_CONSOLE
+	bool "Console on FIQ Serial Debugger port"
+	depends on FIQ_DEBUGGER
+	default n
+	help
+	  Enables a console so that printk messages are displayed on
+	  the debugger serial port as the occur.
+
+config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
+	bool "Put the FIQ debugger into console mode by default"
+	depends on FIQ_DEBUGGER_CONSOLE
+	default n
+	help
+	  If enabled, this puts the fiq debugger into console mode by default.
+	  Otherwise, the fiq debugger will start out in debug mode.
+
+config FIQ_DEBUGGER_UART_OVERLAY
+	bool "Install uart DT overlay"
+	depends on FIQ_DEBUGGER
+	select OF_OVERLAY
+	default n
+	help
+	  If enabled, fiq debugger is calling fiq_debugger_uart_overlay()
+	  that will apply overlay uart_overlay@0 to disable proper uart.
+
+config FIQ_WATCHDOG
+	bool
+	select FIQ_DEBUGGER
+	select PSTORE_RAM
+	default n
diff --git a/drivers/staging/android/fiq_debugger/Makefile b/drivers/staging/android/fiq_debugger/Makefile
new file mode 100644
index 0000000..a7ca487
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/Makefile
@@ -0,0 +1,4 @@
+obj-y			+= fiq_debugger.o
+obj-$(CONFIG_ARM)	+= fiq_debugger_arm.o
+obj-$(CONFIG_ARM64)	+= fiq_debugger_arm64.o
+obj-$(CONFIG_FIQ_WATCHDOG)	+= fiq_watchdog.o
diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.c b/drivers/staging/android/fiq_debugger/fiq_debugger.c
new file mode 100644
index 0000000..b132cff
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/fiq_debugger.c
@@ -0,0 +1,1248 @@
+/*
+ * drivers/staging/android/fiq_debugger.c
+ *
+ * Serial Debugger Interface accessed through an FIQ interrupt.
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdarg.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/console.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/kernel_stat.h>
+#include <linux/kmsg_dump.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/timer.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/wakelock.h>
+
+#ifdef CONFIG_FIQ_GLUE
+#include <asm/fiq_glue.h>
+#endif
+
+#ifdef CONFIG_FIQ_DEBUGGER_UART_OVERLAY
+#include <linux/of.h>
+#endif
+
+#include <linux/uaccess.h>
+
+#include "fiq_debugger.h"
+#include "fiq_debugger_priv.h"
+#include "fiq_debugger_ringbuf.h"
+
+#define DEBUG_MAX 64
+#define MAX_UNHANDLED_FIQ_COUNT 1000000
+
+#define MAX_FIQ_DEBUGGER_PORTS 4
+
+struct fiq_debugger_state {
+#ifdef CONFIG_FIQ_GLUE
+	struct fiq_glue_handler handler;
+#endif
+	struct fiq_debugger_output output;
+
+	int fiq;
+	int uart_irq;
+	int signal_irq;
+	int wakeup_irq;
+	bool wakeup_irq_no_set_wake;
+	struct clk *clk;
+	struct fiq_debugger_pdata *pdata;
+	struct platform_device *pdev;
+
+	char debug_cmd[DEBUG_MAX];
+	int debug_busy;
+	int debug_abort;
+
+	char debug_buf[DEBUG_MAX];
+	int debug_count;
+
+	bool no_sleep;
+	bool debug_enable;
+	bool ignore_next_wakeup_irq;
+	struct timer_list sleep_timer;
+	spinlock_t sleep_timer_lock;
+	bool uart_enabled;
+	struct wake_lock debugger_wake_lock;
+	bool console_enable;
+	int current_cpu;
+	atomic_t unhandled_fiq_count;
+	bool in_fiq;
+
+	struct work_struct work;
+	spinlock_t work_lock;
+	char work_cmd[DEBUG_MAX];
+
+#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE
+	spinlock_t console_lock;
+	struct console console;
+	struct tty_port tty_port;
+	struct fiq_debugger_ringbuf *tty_rbuf;
+	bool syslog_dumping;
+#endif
+
+	unsigned int last_irqs[NR_IRQS];
+	unsigned int last_local_timer_irqs[NR_CPUS];
+};
+
+#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE
+struct tty_driver *fiq_tty_driver;
+#endif
+
+#ifdef CONFIG_FIQ_DEBUGGER_NO_SLEEP
+static bool initial_no_sleep = true;
+#else
+static bool initial_no_sleep;
+#endif
+
+#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
+static bool initial_debug_enable = true;
+static bool initial_console_enable = true;
+#else
+static bool initial_debug_enable;
+static bool initial_console_enable;
+#endif
+
+static bool fiq_kgdb_enable;
+static bool fiq_debugger_disable;
+
+module_param_named(no_sleep, initial_no_sleep, bool, 0644);
+module_param_named(debug_enable, initial_debug_enable, bool, 0644);
+module_param_named(console_enable, initial_console_enable, bool, 0644);
+module_param_named(kgdb_enable, fiq_kgdb_enable, bool, 0644);
+module_param_named(disable, fiq_debugger_disable, bool, 0644);
+
+#ifdef CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
+static inline
+void fiq_debugger_enable_wakeup_irq(struct fiq_debugger_state *state) {}
+static inline
+void fiq_debugger_disable_wakeup_irq(struct fiq_debugger_state *state) {}
+#else
+static inline
+void fiq_debugger_enable_wakeup_irq(struct fiq_debugger_state *state)
+{
+	if (state->wakeup_irq < 0)
+		return;
+	enable_irq(state->wakeup_irq);
+	if (!state->wakeup_irq_no_set_wake)
+		enable_irq_wake(state->wakeup_irq);
+}
+static inline
+void fiq_debugger_disable_wakeup_irq(struct fiq_debugger_state *state)
+{
+	if (state->wakeup_irq < 0)
+		return;
+	disable_irq_nosync(state->wakeup_irq);
+	if (!state->wakeup_irq_no_set_wake)
+		disable_irq_wake(state->wakeup_irq);
+}
+#endif
+
+static inline bool fiq_debugger_have_fiq(struct fiq_debugger_state *state)
+{
+	return (state->fiq >= 0);
+}
+
+#ifdef CONFIG_FIQ_GLUE
+static void fiq_debugger_force_irq(struct fiq_debugger_state *state)
+{
+	unsigned int irq = state->signal_irq;
+
+	if (WARN_ON(!fiq_debugger_have_fiq(state)))
+		return;
+	if (state->pdata->force_irq) {
+		state->pdata->force_irq(state->pdev, irq);
+	} else {
+		struct irq_chip *chip = irq_get_chip(irq);
+		if (chip && chip->irq_retrigger)
+			chip->irq_retrigger(irq_get_irq_data(irq));
+	}
+}
+#endif
+
+static void fiq_debugger_uart_enable(struct fiq_debugger_state *state)
+{
+	if (state->clk)
+		clk_enable(state->clk);
+	if (state->pdata->uart_enable)
+		state->pdata->uart_enable(state->pdev);
+}
+
+static void fiq_debugger_uart_disable(struct fiq_debugger_state *state)
+{
+	if (state->pdata->uart_disable)
+		state->pdata->uart_disable(state->pdev);
+	if (state->clk)
+		clk_disable(state->clk);
+}
+
+static void fiq_debugger_uart_flush(struct fiq_debugger_state *state)
+{
+	if (state->pdata->uart_flush)
+		state->pdata->uart_flush(state->pdev);
+}
+
+static void fiq_debugger_putc(struct fiq_debugger_state *state, char c)
+{
+	state->pdata->uart_putc(state->pdev, c);
+}
+
+static void fiq_debugger_puts(struct fiq_debugger_state *state, char *s)
+{
+	unsigned c;
+	while ((c = *s++)) {
+		if (c == '\n')
+			fiq_debugger_putc(state, '\r');
+		fiq_debugger_putc(state, c);
+	}
+}
+
+static void fiq_debugger_prompt(struct fiq_debugger_state *state)
+{
+	fiq_debugger_puts(state, "debug> ");
+}
+
+static void fiq_debugger_dump_kernel_log(struct fiq_debugger_state *state)
+{
+	char buf[512];
+	size_t len;
+	struct kmsg_dumper dumper = { .active = true };
+
+
+	kmsg_dump_rewind_nolock(&dumper);
+	while (kmsg_dump_get_line_nolock(&dumper, true, buf,
+					 sizeof(buf) - 1, &len)) {
+		buf[len] = 0;
+		fiq_debugger_puts(state, buf);
+	}
+}
+
+static void fiq_debugger_printf(struct fiq_debugger_output *output,
+			       const char *fmt, ...)
+{
+	struct fiq_debugger_state *state;
+	char buf[256];
+	va_list ap;
+
+	state = container_of(output, struct fiq_debugger_state, output);
+	va_start(ap, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, ap);
+	va_end(ap);
+
+	fiq_debugger_puts(state, buf);
+}
+
+/* Safe outside fiq context */
+static int fiq_debugger_printf_nfiq(void *cookie, const char *fmt, ...)
+{
+	struct fiq_debugger_state *state = cookie;
+	char buf[256];
+	va_list ap;
+	unsigned long irq_flags;
+
+	va_start(ap, fmt);
+	vsnprintf(buf, 128, fmt, ap);
+	va_end(ap);
+
+	local_irq_save(irq_flags);
+	fiq_debugger_puts(state, buf);
+	fiq_debugger_uart_flush(state);
+	local_irq_restore(irq_flags);
+	return state->debug_abort;
+}
+
+static void fiq_debugger_dump_irqs(struct fiq_debugger_state *state)
+{
+	int n;
+	struct irq_desc *desc;
+
+	fiq_debugger_printf(&state->output,
+			"irqnr       total  since-last   status  name\n");
+	for_each_irq_desc(n, desc) {
+		struct irqaction *act = desc->action;
+		if (!act && !kstat_irqs(n))
+			continue;
+		fiq_debugger_printf(&state->output, "%5d: %10u %11u %8x  %s\n", n,
+			kstat_irqs(n),
+			kstat_irqs(n) - state->last_irqs[n],
+			desc->status_use_accessors,
+			(act && act->name) ? act->name : "???");
+		state->last_irqs[n] = kstat_irqs(n);
+	}
+}
+
+static void fiq_debugger_do_ps(struct fiq_debugger_state *state)
+{
+	struct task_struct *g;
+	struct task_struct *p;
+	unsigned task_state;
+	static const char stat_nam[] = "RSDTtZX";
+
+	fiq_debugger_printf(&state->output, "pid   ppid  prio task            pc\n");
+	read_lock(&tasklist_lock);
+	do_each_thread(g, p) {
+		task_state = p->state ? __ffs(p->state) + 1 : 0;
+		fiq_debugger_printf(&state->output,
+			     "%5d %5d %4d ", p->pid, p->parent->pid, p->prio);
+		fiq_debugger_printf(&state->output, "%-13.13s %c", p->comm,
+			     task_state >= sizeof(stat_nam) ? '?' : stat_nam[task_state]);
+		if (task_state == TASK_RUNNING)
+			fiq_debugger_printf(&state->output, " running\n");
+		else
+			fiq_debugger_printf(&state->output, " %08lx\n",
+					thread_saved_pc(p));
+	} while_each_thread(g, p);
+	read_unlock(&tasklist_lock);
+}
+
+#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE
+static void fiq_debugger_begin_syslog_dump(struct fiq_debugger_state *state)
+{
+	state->syslog_dumping = true;
+}
+
+static void fiq_debugger_end_syslog_dump(struct fiq_debugger_state *state)
+{
+	state->syslog_dumping = false;
+}
+#else
+extern int do_syslog(int type, char __user *bug, int count);
+static void fiq_debugger_begin_syslog_dump(struct fiq_debugger_state *state)
+{
+	do_syslog(5 /* clear */, NULL, 0);
+}
+
+static void fiq_debugger_end_syslog_dump(struct fiq_debugger_state *state)
+{
+	fiq_debugger_dump_kernel_log(state);
+}
+#endif
+
+static void fiq_debugger_do_sysrq(struct fiq_debugger_state *state, char rq)
+{
+	if ((rq == 'g' || rq == 'G') && !fiq_kgdb_enable) {
+		fiq_debugger_printf(&state->output, "sysrq-g blocked\n");
+		return;
+	}
+	fiq_debugger_begin_syslog_dump(state);
+	handle_sysrq(rq);
+	fiq_debugger_end_syslog_dump(state);
+}
+
+#ifdef CONFIG_KGDB
+static void fiq_debugger_do_kgdb(struct fiq_debugger_state *state)
+{
+	if (!fiq_kgdb_enable) {
+		fiq_debugger_printf(&state->output, "kgdb through fiq debugger not enabled\n");
+		return;
+	}
+
+	fiq_debugger_printf(&state->output, "enabling console and triggering kgdb\n");
+	state->console_enable = true;
+	handle_sysrq('g');
+}
+#endif
+
+static void fiq_debugger_schedule_work(struct fiq_debugger_state *state,
+		char *cmd)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&state->work_lock, flags);
+	if (state->work_cmd[0] != '\0') {
+		fiq_debugger_printf(&state->output, "work command processor busy\n");
+		spin_unlock_irqrestore(&state->work_lock, flags);
+		return;
+	}
+
+	strlcpy(state->work_cmd, cmd, sizeof(state->work_cmd));
+	spin_unlock_irqrestore(&state->work_lock, flags);
+
+	schedule_work(&state->work);
+}
+
+static void fiq_debugger_work(struct work_struct *work)
+{
+	struct fiq_debugger_state *state;
+	char work_cmd[DEBUG_MAX];
+	char *cmd;
+	unsigned long flags;
+
+	state = container_of(work, struct fiq_debugger_state, work);
+
+	spin_lock_irqsave(&state->work_lock, flags);
+
+	strlcpy(work_cmd, state->work_cmd, sizeof(work_cmd));
+	state->work_cmd[0] = '\0';
+
+	spin_unlock_irqrestore(&state->work_lock, flags);
+
+	cmd = work_cmd;
+	if (!strncmp(cmd, "reboot", 6)) {
+		cmd += 6;
+		while (*cmd == ' ')
+			cmd++;
+		if (cmd != '\0')
+			kernel_restart(cmd);
+		else
+			kernel_restart(NULL);
+	} else {
+		fiq_debugger_printf(&state->output, "unknown work command '%s'\n",
+				work_cmd);
+	}
+}
+
+/* This function CANNOT be called in FIQ context */
+static void fiq_debugger_irq_exec(struct fiq_debugger_state *state, char *cmd)
+{
+	if (!strcmp(cmd, "ps"))
+		fiq_debugger_do_ps(state);
+	if (!strcmp(cmd, "sysrq"))
+		fiq_debugger_do_sysrq(state, 'h');
+	if (!strncmp(cmd, "sysrq ", 6))
+		fiq_debugger_do_sysrq(state, cmd[6]);
+#ifdef CONFIG_KGDB
+	if (!strcmp(cmd, "kgdb"))
+		fiq_debugger_do_kgdb(state);
+#endif
+	if (!strncmp(cmd, "reboot", 6))
+		fiq_debugger_schedule_work(state, cmd);
+}
+
+static void fiq_debugger_help(struct fiq_debugger_state *state)
+{
+	fiq_debugger_printf(&state->output,
+				"FIQ Debugger commands:\n"
+				" pc            PC status\n"
+				" regs          Register dump\n"
+				" allregs       Extended Register dump\n"
+				" bt            Stack trace\n"
+				" reboot [<c>]  Reboot with command <c>\n"
+				" reset [<c>]   Hard reset with command <c>\n"
+				" irqs          Interupt status\n"
+				" kmsg          Kernel log\n"
+				" version       Kernel version\n");
+	fiq_debugger_printf(&state->output,
+				" sleep         Allow sleep while in FIQ\n"
+				" nosleep       Disable sleep while in FIQ\n"
+				" console       Switch terminal to console\n"
+				" cpu           Current CPU\n"
+				" cpu <number>  Switch to CPU<number>\n");
+	fiq_debugger_printf(&state->output,
+				" ps            Process list\n"
+				" sysrq         sysrq options\n"
+				" sysrq <param> Execute sysrq with <param>\n");
+#ifdef CONFIG_KGDB
+	fiq_debugger_printf(&state->output,
+				" kgdb          Enter kernel debugger\n");
+#endif
+}
+
+static void fiq_debugger_take_affinity(void *info)
+{
+	struct fiq_debugger_state *state = info;
+	struct cpumask cpumask;
+
+	cpumask_clear(&cpumask);
+	cpumask_set_cpu(get_cpu(), &cpumask);
+
+	irq_set_affinity(state->uart_irq, &cpumask);
+}
+
+static void fiq_debugger_switch_cpu(struct fiq_debugger_state *state, int cpu)
+{
+	if (!fiq_debugger_have_fiq(state))
+		smp_call_function_single(cpu, fiq_debugger_take_affinity, state,
+				false);
+	state->current_cpu = cpu;
+}
+
+static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state,
+			const char *cmd, const struct pt_regs *regs,
+			void *svc_sp)
+{
+	bool signal_helper = false;
+
+	if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) {
+		fiq_debugger_help(state);
+	} else if (!strcmp(cmd, "pc")) {
+		fiq_debugger_dump_pc(&state->output, regs);
+	} else if (!strcmp(cmd, "regs")) {
+		fiq_debugger_dump_regs(&state->output, regs);
+	} else if (!strcmp(cmd, "allregs")) {
+		fiq_debugger_dump_allregs(&state->output, regs);
+	} else if (!strcmp(cmd, "bt")) {
+		fiq_debugger_dump_stacktrace(&state->output, regs, 100, svc_sp);
+	} else if (!strncmp(cmd, "reset", 5)) {
+		cmd += 5;
+		while (*cmd == ' ')
+			cmd++;
+		if (*cmd) {
+			char tmp_cmd[32];
+			strlcpy(tmp_cmd, cmd, sizeof(tmp_cmd));
+			machine_restart(tmp_cmd);
+		} else {
+			machine_restart(NULL);
+		}
+	} else if (!strcmp(cmd, "irqs")) {
+		fiq_debugger_dump_irqs(state);
+	} else if (!strcmp(cmd, "kmsg")) {
+		fiq_debugger_dump_kernel_log(state);
+	} else if (!strcmp(cmd, "version")) {
+		fiq_debugger_printf(&state->output, "%s\n", linux_banner);
+	} else if (!strcmp(cmd, "sleep")) {
+		state->no_sleep = false;
+		fiq_debugger_printf(&state->output, "enabling sleep\n");
+	} else if (!strcmp(cmd, "nosleep")) {
+		state->no_sleep = true;
+		fiq_debugger_printf(&state->output, "disabling sleep\n");
+	} else if (!strcmp(cmd, "console")) {
+		fiq_debugger_printf(&state->output, "console mode\n");
+		fiq_debugger_uart_flush(state);
+		state->console_enable = true;
+	} else if (!strcmp(cmd, "cpu")) {
+		fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu);
+	} else if (!strncmp(cmd, "cpu ", 4)) {
+		unsigned long cpu = 0;
+		if (kstrtoul(cmd + 4, 10, &cpu) == 0)
+			fiq_debugger_switch_cpu(state, cpu);
+		else
+			fiq_debugger_printf(&state->output, "invalid cpu\n");
+		fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu);
+	} else {
+		if (state->debug_busy) {
+			fiq_debugger_printf(&state->output,
+				"command processor busy. trying to abort.\n");
+			state->debug_abort = -1;
+		} else {
+			strcpy(state->debug_cmd, cmd);
+			state->debug_busy = 1;
+		}
+
+		return true;
+	}
+	if (!state->console_enable)
+		fiq_debugger_prompt(state);
+
+	return signal_helper;
+}
+
+static void fiq_debugger_sleep_timer_expired(unsigned long data)
+{
+	struct fiq_debugger_state *state = (struct fiq_debugger_state *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&state->sleep_timer_lock, flags);
+	if (state->uart_enabled && !state->no_sleep) {
+		if (state->debug_enable && !state->console_enable) {
+			state->debug_enable = false;
+			fiq_debugger_printf_nfiq(state,
+					"suspending fiq debugger\n");
+		}
+		state->ignore_next_wakeup_irq = true;
+		fiq_debugger_uart_disable(state);
+		state->uart_enabled = false;
+		fiq_debugger_enable_wakeup_irq(state);
+	}
+	wake_unlock(&state->debugger_wake_lock);
+	spin_unlock_irqrestore(&state->sleep_timer_lock, flags);
+}
+
+static void fiq_debugger_handle_wakeup(struct fiq_debugger_state *state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&state->sleep_timer_lock, flags);
+	if (state->wakeup_irq >= 0 && state->ignore_next_wakeup_irq) {
+		state->ignore_next_wakeup_irq = false;
+	} else if (!state->uart_enabled) {
+		wake_lock(&state->debugger_wake_lock);
+		fiq_debugger_uart_enable(state);
+		state->uart_enabled = true;
+		fiq_debugger_disable_wakeup_irq(state);
+		mod_timer(&state->sleep_timer, jiffies + HZ / 2);
+	}
+	spin_unlock_irqrestore(&state->sleep_timer_lock, flags);
+}
+
+static irqreturn_t fiq_debugger_wakeup_irq_handler(int irq, void *dev)
+{
+	struct fiq_debugger_state *state = dev;
+
+	if (!state->no_sleep)
+		fiq_debugger_puts(state, "WAKEUP\n");
+	fiq_debugger_handle_wakeup(state);
+
+	return IRQ_HANDLED;
+}
+
+static
+void fiq_debugger_handle_console_irq_context(struct fiq_debugger_state *state)
+{
+#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
+	if (state->tty_port.ops) {
+		int i;
+		int count = fiq_debugger_ringbuf_level(state->tty_rbuf);
+		for (i = 0; i < count; i++) {
+			int c = fiq_debugger_ringbuf_peek(state->tty_rbuf, 0);
+			tty_insert_flip_char(&state->tty_port, c, TTY_NORMAL);
+			if (!fiq_debugger_ringbuf_consume(state->tty_rbuf, 1))
+				pr_warn("fiq tty failed to consume byte\n");
+		}
+		tty_flip_buffer_push(&state->tty_port);
+	}
+#endif
+}
+
+static void fiq_debugger_handle_irq_context(struct fiq_debugger_state *state)
+{
+	if (!state->no_sleep) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&state->sleep_timer_lock, flags);
+		wake_lock(&state->debugger_wake_lock);
+		mod_timer(&state->sleep_timer, jiffies + HZ * 5);
+		spin_unlock_irqrestore(&state->sleep_timer_lock, flags);
+	}
+	fiq_debugger_handle_console_irq_context(state);
+	if (state->debug_busy) {
+		fiq_debugger_irq_exec(state, state->debug_cmd);
+		if (!state->console_enable)
+			fiq_debugger_prompt(state);
+		state->debug_busy = 0;
+	}
+}
+
+static int fiq_debugger_getc(struct fiq_debugger_state *state)
+{
+	return state->pdata->uart_getc(state->pdev);
+}
+
+static bool fiq_debugger_handle_uart_interrupt(struct fiq_debugger_state *state,
+			int this_cpu, const struct pt_regs *regs, void *svc_sp)
+{
+	int c;
+	static int last_c;
+	int count = 0;
+	bool signal_helper = false;
+
+	if (this_cpu != state->current_cpu) {
+		if (state->in_fiq)
+			return false;
+
+		if (atomic_inc_return(&state->unhandled_fiq_count) !=
+					MAX_UNHANDLED_FIQ_COUNT)
+			return false;
+
+		fiq_debugger_printf(&state->output,
+			"fiq_debugger: cpu %d not responding, "
+			"reverting to cpu %d\n", state->current_cpu,
+			this_cpu);
+
+		atomic_set(&state->unhandled_fiq_count, 0);
+		fiq_debugger_switch_cpu(state, this_cpu);
+		return false;
+	}
+
+	state->in_fiq = true;
+
+	while ((c = fiq_debugger_getc(state)) != FIQ_DEBUGGER_NO_CHAR) {
+		count++;
+		if (!state->debug_enable) {
+			if ((c == 13) || (c == 10)) {
+				state->debug_enable = true;
+				state->debug_count = 0;
+				fiq_debugger_prompt(state);
+			}
+		} else if (c == FIQ_DEBUGGER_BREAK) {
+			state->console_enable = false;
+			fiq_debugger_puts(state, "fiq debugger mode\n");
+			state->debug_count = 0;
+			fiq_debugger_prompt(state);
+#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE
+		} else if (state->console_enable && state->tty_rbuf) {
+			fiq_debugger_ringbuf_push(state->tty_rbuf, c);
+			signal_helper = true;
+#endif
+		} else if ((c >= ' ') && (c < 127)) {
+			if (state->debug_count < (DEBUG_MAX - 1)) {
+				state->debug_buf[state->debug_count++] = c;
+				fiq_debugger_putc(state, c);
+			}
+		} else if ((c == 8) || (c == 127)) {
+			if (state->debug_count > 0) {
+				state->debug_count--;
+				fiq_debugger_putc(state, 8);
+				fiq_debugger_putc(state, ' ');
+				fiq_debugger_putc(state, 8);
+			}
+		} else if ((c == 13) || (c == 10)) {
+			if (c == '\r' || (c == '\n' && last_c != '\r')) {
+				fiq_debugger_putc(state, '\r');
+				fiq_debugger_putc(state, '\n');
+			}
+			if (state->debug_count) {
+				state->debug_buf[state->debug_count] = 0;
+				state->debug_count = 0;
+				signal_helper |=
+					fiq_debugger_fiq_exec(state,
+							state->debug_buf,
+							regs, svc_sp);
+			} else {
+				fiq_debugger_prompt(state);
+			}
+		}
+		last_c = c;
+	}
+	if (!state->console_enable)
+		fiq_debugger_uart_flush(state);
+	if (state->pdata->fiq_ack)
+		state->pdata->fiq_ack(state->pdev, state->fiq);
+
+	/* poke sleep timer if necessary */
+	if (state->debug_enable && !state->no_sleep)
+		signal_helper = true;
+
+	atomic_set(&state->unhandled_fiq_count, 0);
+	state->in_fiq = false;
+
+	return signal_helper;
+}
+
+#ifdef CONFIG_FIQ_GLUE
+static void fiq_debugger_fiq(struct fiq_glue_handler *h,
+		const struct pt_regs *regs, void *svc_sp)
+{
+	struct fiq_debugger_state *state =
+		container_of(h, struct fiq_debugger_state, handler);
+	unsigned int this_cpu = THREAD_INFO(svc_sp)->cpu;
+	bool need_irq;
+
+	need_irq = fiq_debugger_handle_uart_interrupt(state, this_cpu, regs,
+			svc_sp);
+	if (need_irq)
+		fiq_debugger_force_irq(state);
+}
+#endif
+
+/*
+ * When not using FIQs, we only use this single interrupt as an entry point.
+ * This just effectively takes over the UART interrupt and does all the work
+ * in this context.
+ */
+static irqreturn_t fiq_debugger_uart_irq(int irq, void *dev)
+{
+	struct fiq_debugger_state *state = dev;
+	bool not_done;
+
+	fiq_debugger_handle_wakeup(state);
+
+	/* handle the debugger irq in regular context */
+	not_done = fiq_debugger_handle_uart_interrupt(state, smp_processor_id(),
+					      get_irq_regs(),
+					      current_thread_info());
+	if (not_done)
+		fiq_debugger_handle_irq_context(state);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * If FIQs are used, not everything can happen in fiq context.
+ * FIQ handler does what it can and then signals this interrupt to finish the
+ * job in irq context.
+ */
+static irqreturn_t fiq_debugger_signal_irq(int irq, void *dev)
+{
+	struct fiq_debugger_state *state = dev;
+
+	if (state->pdata->force_irq_ack)
+		state->pdata->force_irq_ack(state->pdev, state->signal_irq);
+
+	fiq_debugger_handle_irq_context(state);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_FIQ_GLUE
+static void fiq_debugger_resume(struct fiq_glue_handler *h)
+{
+	struct fiq_debugger_state *state =
+		container_of(h, struct fiq_debugger_state, handler);
+	if (state->pdata->uart_resume)
+		state->pdata->uart_resume(state->pdev);
+}
+#endif
+
+#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
+struct tty_driver *fiq_debugger_console_device(struct console *co, int *index)
+{
+	*index = co->index;
+	return fiq_tty_driver;
+}
+
+static void fiq_debugger_console_write(struct console *co,
+				const char *s, unsigned int count)
+{
+	struct fiq_debugger_state *state;
+	unsigned long flags;
+
+	state = container_of(co, struct fiq_debugger_state, console);
+
+	if (!state->console_enable && !state->syslog_dumping)
+		return;
+
+	fiq_debugger_uart_enable(state);
+	spin_lock_irqsave(&state->console_lock, flags);
+	while (count--) {
+		if (*s == '\n')
+			fiq_debugger_putc(state, '\r');
+		fiq_debugger_putc(state, *s++);
+	}
+	fiq_debugger_uart_flush(state);
+	spin_unlock_irqrestore(&state->console_lock, flags);
+	fiq_debugger_uart_disable(state);
+}
+
+static struct console fiq_debugger_console = {
+	.name = "ttyFIQ",
+	.device = fiq_debugger_console_device,
+	.write = fiq_debugger_console_write,
+	.flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED,
+};
+
+int fiq_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	int line = tty->index;
+	struct fiq_debugger_state **states = tty->driver->driver_state;
+	struct fiq_debugger_state *state = states[line];
+
+	return tty_port_open(&state->tty_port, tty, filp);
+}
+
+void fiq_tty_close(struct tty_struct *tty, struct file *filp)
+{
+	tty_port_close(tty->port, tty, filp);
+}
+
+int  fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	int i;
+	int line = tty->index;
+	struct fiq_debugger_state **states = tty->driver->driver_state;
+	struct fiq_debugger_state *state = states[line];
+
+	if (!state->console_enable)
+		return count;
+
+	fiq_debugger_uart_enable(state);
+	spin_lock_irq(&state->console_lock);
+	for (i = 0; i < count; i++)
+		fiq_debugger_putc(state, *buf++);
+	spin_unlock_irq(&state->console_lock);
+	fiq_debugger_uart_disable(state);
+
+	return count;
+}
+
+int  fiq_tty_write_room(struct tty_struct *tty)
+{
+	return 16;
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+static int fiq_tty_poll_init(struct tty_driver *driver, int line, char *options)
+{
+	return 0;
+}
+
+static int fiq_tty_poll_get_char(struct tty_driver *driver, int line)
+{
+	struct fiq_debugger_state **states = driver->driver_state;
+	struct fiq_debugger_state *state = states[line];
+	int c = NO_POLL_CHAR;
+
+	fiq_debugger_uart_enable(state);
+	if (fiq_debugger_have_fiq(state)) {
+		int count = fiq_debugger_ringbuf_level(state->tty_rbuf);
+		if (count > 0) {
+			c = fiq_debugger_ringbuf_peek(state->tty_rbuf, 0);
+			fiq_debugger_ringbuf_consume(state->tty_rbuf, 1);
+		}
+	} else {
+		c = fiq_debugger_getc(state);
+		if (c == FIQ_DEBUGGER_NO_CHAR)
+			c = NO_POLL_CHAR;
+	}
+	fiq_debugger_uart_disable(state);
+
+	return c;
+}
+
+static void fiq_tty_poll_put_char(struct tty_driver *driver, int line, char ch)
+{
+	struct fiq_debugger_state **states = driver->driver_state;
+	struct fiq_debugger_state *state = states[line];
+	fiq_debugger_uart_enable(state);
+	fiq_debugger_putc(state, ch);
+	fiq_debugger_uart_disable(state);
+}
+#endif
+
+static const struct tty_port_operations fiq_tty_port_ops;
+
+static const struct tty_operations fiq_tty_driver_ops = {
+	.write = fiq_tty_write,
+	.write_room = fiq_tty_write_room,
+	.open = fiq_tty_open,
+	.close = fiq_tty_close,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_init = fiq_tty_poll_init,
+	.poll_get_char = fiq_tty_poll_get_char,
+	.poll_put_char = fiq_tty_poll_put_char,
+#endif
+};
+
+static int fiq_debugger_tty_init(void)
+{
+	int ret;
+	struct fiq_debugger_state **states = NULL;
+
+	states = kzalloc(sizeof(*states) * MAX_FIQ_DEBUGGER_PORTS, GFP_KERNEL);
+	if (!states) {
+		pr_err("Failed to allocate fiq debugger state structres\n");
+		return -ENOMEM;
+	}
+
+	fiq_tty_driver = alloc_tty_driver(MAX_FIQ_DEBUGGER_PORTS);
+	if (!fiq_tty_driver) {
+		pr_err("Failed to allocate fiq debugger tty\n");
+		ret = -ENOMEM;
+		goto err_free_state;
+	}
+
+	fiq_tty_driver->owner		= THIS_MODULE;
+	fiq_tty_driver->driver_name	= "fiq-debugger";
+	fiq_tty_driver->name		= "ttyFIQ";
+	fiq_tty_driver->type		= TTY_DRIVER_TYPE_SERIAL;
+	fiq_tty_driver->subtype		= SERIAL_TYPE_NORMAL;
+	fiq_tty_driver->init_termios	= tty_std_termios;
+	fiq_tty_driver->flags		= TTY_DRIVER_REAL_RAW |
+					  TTY_DRIVER_DYNAMIC_DEV;
+	fiq_tty_driver->driver_state	= states;
+
+	fiq_tty_driver->init_termios.c_cflag =
+					B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+	fiq_tty_driver->init_termios.c_ispeed = 115200;
+	fiq_tty_driver->init_termios.c_ospeed = 115200;
+
+	tty_set_operations(fiq_tty_driver, &fiq_tty_driver_ops);
+
+	ret = tty_register_driver(fiq_tty_driver);
+	if (ret) {
+		pr_err("Failed to register fiq tty: %d\n", ret);
+		goto err_free_tty;
+	}
+
+	pr_info("Registered FIQ tty driver\n");
+	return 0;
+
+err_free_tty:
+	put_tty_driver(fiq_tty_driver);
+	fiq_tty_driver = NULL;
+err_free_state:
+	kfree(states);
+	return ret;
+}
+
+static int fiq_debugger_tty_init_one(struct fiq_debugger_state *state)
+{
+	int ret;
+	struct device *tty_dev;
+	struct fiq_debugger_state **states = fiq_tty_driver->driver_state;
+
+	states[state->pdev->id] = state;
+
+	state->tty_rbuf = fiq_debugger_ringbuf_alloc(1024);
+	if (!state->tty_rbuf) {
+		pr_err("Failed to allocate fiq debugger ringbuf\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	tty_port_init(&state->tty_port);
+	state->tty_port.ops = &fiq_tty_port_ops;
+
+	tty_dev = tty_port_register_device(&state->tty_port, fiq_tty_driver,
+					   state->pdev->id, &state->pdev->dev);
+	if (IS_ERR(tty_dev)) {
+		pr_err("Failed to register fiq debugger tty device\n");
+		ret = PTR_ERR(tty_dev);
+		goto err;
+	}
+
+	device_set_wakeup_capable(tty_dev, 1);
+
+	pr_info("Registered fiq debugger ttyFIQ%d\n", state->pdev->id);
+
+	return 0;
+
+err:
+	fiq_debugger_ringbuf_free(state->tty_rbuf);
+	state->tty_rbuf = NULL;
+	return ret;
+}
+#endif
+
+static int fiq_debugger_dev_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fiq_debugger_state *state = platform_get_drvdata(pdev);
+
+	if (state->pdata->uart_dev_suspend)
+		return state->pdata->uart_dev_suspend(pdev);
+	return 0;
+}
+
+static int fiq_debugger_dev_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fiq_debugger_state *state = platform_get_drvdata(pdev);
+
+	if (state->pdata->uart_dev_resume)
+		return state->pdata->uart_dev_resume(pdev);
+	return 0;
+}
+
+static int fiq_debugger_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct fiq_debugger_pdata *pdata = dev_get_platdata(&pdev->dev);
+	struct fiq_debugger_state *state;
+	int fiq;
+	int uart_irq;
+
+	if (pdev->id >= MAX_FIQ_DEBUGGER_PORTS)
+		return -EINVAL;
+
+	if (!pdata->uart_getc || !pdata->uart_putc)
+		return -EINVAL;
+	if ((pdata->uart_enable && !pdata->uart_disable) ||
+	    (!pdata->uart_enable && pdata->uart_disable))
+		return -EINVAL;
+
+	fiq = platform_get_irq_byname(pdev, "fiq");
+	uart_irq = platform_get_irq_byname(pdev, "uart_irq");
+
+	/* uart_irq mode and fiq mode are mutually exclusive, but one of them
+	 * is required */
+	if ((uart_irq < 0 && fiq < 0) || (uart_irq >= 0 && fiq >= 0))
+		return -EINVAL;
+	if (fiq >= 0 && !pdata->fiq_enable)
+		return -EINVAL;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	state->output.printf = fiq_debugger_printf;
+	setup_timer(&state->sleep_timer, fiq_debugger_sleep_timer_expired,
+		    (unsigned long)state);
+	state->pdata = pdata;
+	state->pdev = pdev;
+	state->no_sleep = initial_no_sleep;
+	state->debug_enable = initial_debug_enable;
+	state->console_enable = initial_console_enable;
+
+	state->fiq = fiq;
+	state->uart_irq = uart_irq;
+	state->signal_irq = platform_get_irq_byname(pdev, "signal");
+	state->wakeup_irq = platform_get_irq_byname(pdev, "wakeup");
+
+	INIT_WORK(&state->work, fiq_debugger_work);
+	spin_lock_init(&state->work_lock);
+
+	platform_set_drvdata(pdev, state);
+
+	spin_lock_init(&state->sleep_timer_lock);
+
+	if (state->wakeup_irq < 0 && fiq_debugger_have_fiq(state))
+		state->no_sleep = true;
+	state->ignore_next_wakeup_irq = !state->no_sleep;
+
+	wake_lock_init(&state->debugger_wake_lock,
+			WAKE_LOCK_SUSPEND, "serial-debug");
+
+	state->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(state->clk))
+		state->clk = NULL;
+
+	/* do not call pdata->uart_enable here since uart_init may still
+	 * need to do some initialization before uart_enable can work.
+	 * So, only try to manage the clock during init.
+	 */
+	if (state->clk)
+		clk_enable(state->clk);
+
+	if (pdata->uart_init) {
+		ret = pdata->uart_init(pdev);
+		if (ret)
+			goto err_uart_init;
+	}
+
+	fiq_debugger_printf_nfiq(state,
+				"<hit enter %sto activate fiq debugger>\n",
+				state->no_sleep ? "" : "twice ");
+
+#ifdef CONFIG_FIQ_GLUE
+	if (fiq_debugger_have_fiq(state)) {
+		state->handler.fiq = fiq_debugger_fiq;
+		state->handler.resume = fiq_debugger_resume;
+		ret = fiq_glue_register_handler(&state->handler);
+		if (ret) {
+			pr_err("%s: could not install fiq handler\n", __func__);
+			goto err_register_irq;
+		}
+
+		pdata->fiq_enable(pdev, state->fiq, 1);
+	} else
+#endif
+	{
+		ret = request_irq(state->uart_irq, fiq_debugger_uart_irq,
+				  IRQF_NO_SUSPEND, "debug", state);
+		if (ret) {
+			pr_err("%s: could not install irq handler\n", __func__);
+			goto err_register_irq;
+		}
+
+		/* for irq-only mode, we want this irq to wake us up, if it
+		 * can.
+		 */
+		enable_irq_wake(state->uart_irq);
+	}
+
+	if (state->clk)
+		clk_disable(state->clk);
+
+	if (state->signal_irq >= 0) {
+		ret = request_irq(state->signal_irq, fiq_debugger_signal_irq,
+			  IRQF_TRIGGER_RISING, "debug-signal", state);
+		if (ret)
+			pr_err("serial_debugger: could not install signal_irq");
+	}
+
+	if (state->wakeup_irq >= 0) {
+		ret = request_irq(state->wakeup_irq,
+				  fiq_debugger_wakeup_irq_handler,
+				  IRQF_TRIGGER_FALLING,
+				  "debug-wakeup", state);
+		if (ret) {
+			pr_err("serial_debugger: "
+				"could not install wakeup irq\n");
+			state->wakeup_irq = -1;
+		} else {
+			ret = enable_irq_wake(state->wakeup_irq);
+			if (ret) {
+				pr_err("serial_debugger: "
+					"could not enable wakeup\n");
+				state->wakeup_irq_no_set_wake = true;
+			}
+		}
+	}
+	if (state->no_sleep)
+		fiq_debugger_handle_wakeup(state);
+
+#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
+	spin_lock_init(&state->console_lock);
+	state->console = fiq_debugger_console;
+	state->console.index = pdev->id;
+	if (!console_set_on_cmdline)
+		add_preferred_console(state->console.name,
+			state->console.index, NULL);
+	register_console(&state->console);
+	fiq_debugger_tty_init_one(state);
+#endif
+	return 0;
+
+err_register_irq:
+	if (pdata->uart_free)
+		pdata->uart_free(pdev);
+err_uart_init:
+	if (state->clk)
+		clk_disable(state->clk);
+	if (state->clk)
+		clk_put(state->clk);
+	wake_lock_destroy(&state->debugger_wake_lock);
+	platform_set_drvdata(pdev, NULL);
+	kfree(state);
+	return ret;
+}
+
+static const struct dev_pm_ops fiq_debugger_dev_pm_ops = {
+	.suspend	= fiq_debugger_dev_suspend,
+	.resume		= fiq_debugger_dev_resume,
+};
+
+static struct platform_driver fiq_debugger_driver = {
+	.probe	= fiq_debugger_probe,
+	.driver	= {
+		.name	= "fiq_debugger",
+		.pm	= &fiq_debugger_dev_pm_ops,
+	},
+};
+
+#if defined(CONFIG_FIQ_DEBUGGER_UART_OVERLAY)
+int fiq_debugger_uart_overlay(void)
+{
+	struct device_node *onp = of_find_node_by_path("/uart_overlay@0");
+	int ret;
+
+	if (!onp) {
+		pr_err("serial_debugger: uart overlay not found\n");
+		return -ENODEV;
+	}
+
+	ret = of_overlay_create(onp);
+	if (ret < 0) {
+		pr_err("serial_debugger: fail to create overlay: %d\n", ret);
+		of_node_put(onp);
+		return ret;
+	}
+
+	pr_info("serial_debugger: uart overlay applied\n");
+	return 0;
+}
+#endif
+
+static int __init fiq_debugger_init(void)
+{
+	if (fiq_debugger_disable) {
+		pr_err("serial_debugger: disabled\n");
+		return -ENODEV;
+	}
+#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
+	fiq_debugger_tty_init();
+#endif
+#if defined(CONFIG_FIQ_DEBUGGER_UART_OVERLAY)
+	fiq_debugger_uart_overlay();
+#endif
+	return platform_driver_register(&fiq_debugger_driver);
+}
+
+postcore_initcall(fiq_debugger_init);
diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.h b/drivers/staging/android/fiq_debugger/fiq_debugger.h
new file mode 100644
index 0000000..c9ec4f8
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/fiq_debugger.h
@@ -0,0 +1,64 @@
+/*
+ * drivers/staging/android/fiq_debugger/fiq_debugger.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARCH_ARM_MACH_TEGRA_FIQ_DEBUGGER_H_
+#define _ARCH_ARM_MACH_TEGRA_FIQ_DEBUGGER_H_
+
+#include <linux/serial_core.h>
+
+#define FIQ_DEBUGGER_NO_CHAR NO_POLL_CHAR
+#define FIQ_DEBUGGER_BREAK 0x00ff0100
+
+#define FIQ_DEBUGGER_FIQ_IRQ_NAME	"fiq"
+#define FIQ_DEBUGGER_SIGNAL_IRQ_NAME	"signal"
+#define FIQ_DEBUGGER_WAKEUP_IRQ_NAME	"wakeup"
+
+/**
+ * struct fiq_debugger_pdata - fiq debugger platform data
+ * @uart_resume:	used to restore uart state right before enabling
+ *			the fiq.
+ * @uart_enable:	Do the work necessary to communicate with the uart
+ *			hw (enable clocks, etc.). This must be ref-counted.
+ * @uart_disable:	Do the work necessary to disable the uart hw
+ *			(disable clocks, etc.). This must be ref-counted.
+ * @uart_dev_suspend:	called during PM suspend, generally not needed
+ *			for real fiq mode debugger.
+ * @uart_dev_resume:	called during PM resume, generally not needed
+ *			for real fiq mode debugger.
+ */
+struct fiq_debugger_pdata {
+	int (*uart_init)(struct platform_device *pdev);
+	void (*uart_free)(struct platform_device *pdev);
+	int (*uart_resume)(struct platform_device *pdev);
+	int (*uart_getc)(struct platform_device *pdev);
+	void (*uart_putc)(struct platform_device *pdev, unsigned int c);
+	void (*uart_flush)(struct platform_device *pdev);
+	void (*uart_enable)(struct platform_device *pdev);
+	void (*uart_disable)(struct platform_device *pdev);
+
+	int (*uart_dev_suspend)(struct platform_device *pdev);
+	int (*uart_dev_resume)(struct platform_device *pdev);
+
+	void (*fiq_enable)(struct platform_device *pdev, unsigned int fiq,
+								bool enable);
+	void (*fiq_ack)(struct platform_device *pdev, unsigned int fiq);
+
+	void (*force_irq)(struct platform_device *pdev, unsigned int irq);
+	void (*force_irq_ack)(struct platform_device *pdev, unsigned int irq);
+};
+
+#endif
diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger_arm.c b/drivers/staging/android/fiq_debugger/fiq_debugger_arm.c
new file mode 100644
index 0000000..8b3e013
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/fiq_debugger_arm.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/ptrace.h>
+#include <linux/uaccess.h>
+
+#include <asm/stacktrace.h>
+
+#include "fiq_debugger_priv.h"
+
+static char *mode_name(unsigned cpsr)
+{
+	switch (cpsr & MODE_MASK) {
+	case USR_MODE: return "USR";
+	case FIQ_MODE: return "FIQ";
+	case IRQ_MODE: return "IRQ";
+	case SVC_MODE: return "SVC";
+	case ABT_MODE: return "ABT";
+	case UND_MODE: return "UND";
+	case SYSTEM_MODE: return "SYS";
+	default: return "???";
+	}
+}
+
+void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
+		const struct pt_regs *regs)
+{
+	output->printf(output, " pc %08x cpsr %08x mode %s\n",
+		regs->ARM_pc, regs->ARM_cpsr, mode_name(regs->ARM_cpsr));
+}
+
+void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
+		const struct pt_regs *regs)
+{
+	output->printf(output,
+			" r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
+			regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
+	output->printf(output,
+			" r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
+			regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
+	output->printf(output,
+			" r8 %08x  r9 %08x r10 %08x r11 %08x  mode %s\n",
+			regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp,
+			mode_name(regs->ARM_cpsr));
+	output->printf(output,
+			" ip %08x  sp %08x  lr %08x  pc %08x cpsr %08x\n",
+			regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc,
+			regs->ARM_cpsr);
+}
+
+struct mode_regs {
+	unsigned long sp_svc;
+	unsigned long lr_svc;
+	unsigned long spsr_svc;
+
+	unsigned long sp_abt;
+	unsigned long lr_abt;
+	unsigned long spsr_abt;
+
+	unsigned long sp_und;
+	unsigned long lr_und;
+	unsigned long spsr_und;
+
+	unsigned long sp_irq;
+	unsigned long lr_irq;
+	unsigned long spsr_irq;
+
+	unsigned long r8_fiq;
+	unsigned long r9_fiq;
+	unsigned long r10_fiq;
+	unsigned long r11_fiq;
+	unsigned long r12_fiq;
+	unsigned long sp_fiq;
+	unsigned long lr_fiq;
+	unsigned long spsr_fiq;
+};
+
+static void __naked get_mode_regs(struct mode_regs *regs)
+{
+	asm volatile (
+	"mrs	r1, cpsr\n"
+	"msr	cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n"
+	"stmia	r0!, {r13 - r14}\n"
+	"mrs	r2, spsr\n"
+	"msr	cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n"
+	"stmia	r0!, {r2, r13 - r14}\n"
+	"mrs	r2, spsr\n"
+	"msr	cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n"
+	"stmia	r0!, {r2, r13 - r14}\n"
+	"mrs	r2, spsr\n"
+	"msr	cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
+	"stmia	r0!, {r2, r13 - r14}\n"
+	"mrs	r2, spsr\n"
+	"msr	cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
+	"stmia	r0!, {r2, r8 - r14}\n"
+	"mrs	r2, spsr\n"
+	"stmia	r0!, {r2}\n"
+	"msr	cpsr_c, r1\n"
+	"bx	lr\n");
+}
+
+
+void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
+		const struct pt_regs *regs)
+{
+	struct mode_regs mode_regs;
+	unsigned long mode = regs->ARM_cpsr & MODE_MASK;
+
+	fiq_debugger_dump_regs(output, regs);
+	get_mode_regs(&mode_regs);
+
+	output->printf(output,
+			"%csvc: sp %08x  lr %08x  spsr %08x\n",
+			mode == SVC_MODE ? '*' : ' ',
+			mode_regs.sp_svc, mode_regs.lr_svc, mode_regs.spsr_svc);
+	output->printf(output,
+			"%cabt: sp %08x  lr %08x  spsr %08x\n",
+			mode == ABT_MODE ? '*' : ' ',
+			mode_regs.sp_abt, mode_regs.lr_abt, mode_regs.spsr_abt);
+	output->printf(output,
+			"%cund: sp %08x  lr %08x  spsr %08x\n",
+			mode == UND_MODE ? '*' : ' ',
+			mode_regs.sp_und, mode_regs.lr_und, mode_regs.spsr_und);
+	output->printf(output,
+			"%cirq: sp %08x  lr %08x  spsr %08x\n",
+			mode == IRQ_MODE ? '*' : ' ',
+			mode_regs.sp_irq, mode_regs.lr_irq, mode_regs.spsr_irq);
+	output->printf(output,
+			"%cfiq: r8 %08x  r9 %08x  r10 %08x  r11 %08x  r12 %08x\n",
+			mode == FIQ_MODE ? '*' : ' ',
+			mode_regs.r8_fiq, mode_regs.r9_fiq, mode_regs.r10_fiq,
+			mode_regs.r11_fiq, mode_regs.r12_fiq);
+	output->printf(output,
+			" fiq: sp %08x  lr %08x  spsr %08x\n",
+			mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq);
+}
+
+struct stacktrace_state {
+	struct fiq_debugger_output *output;
+	unsigned int depth;
+};
+
+static int report_trace(struct stackframe *frame, void *d)
+{
+	struct stacktrace_state *sts = d;
+
+	if (sts->depth) {
+		sts->output->printf(sts->output,
+			"  pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
+			frame->pc, frame->pc, frame->lr, frame->lr,
+			frame->sp, frame->fp);
+		sts->depth--;
+		return 0;
+	}
+	sts->output->printf(sts->output, "  ...\n");
+
+	return sts->depth == 0;
+}
+
+struct frame_tail {
+	struct frame_tail *fp;
+	unsigned long sp;
+	unsigned long lr;
+} __attribute__((packed));
+
+static struct frame_tail *user_backtrace(struct fiq_debugger_output *output,
+					struct frame_tail *tail)
+{
+	struct frame_tail buftail[2];
+
+	/* Also check accessibility of one struct frame_tail beyond */
+	if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) {
+		output->printf(output, "  invalid frame pointer %p\n",
+				tail);
+		return NULL;
+	}
+	if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) {
+		output->printf(output,
+			"  failed to copy frame pointer %p\n", tail);
+		return NULL;
+	}
+
+	output->printf(output, "  %p\n", buftail[0].lr);
+
+	/* frame pointers should strictly progress back up the stack
+	 * (towards higher addresses) */
+	if (tail >= buftail[0].fp)
+		return NULL;
+
+	return buftail[0].fp-1;
+}
+
+void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
+		const struct pt_regs *regs, unsigned int depth, void *ssp)
+{
+	struct frame_tail *tail;
+	struct thread_info *real_thread_info = THREAD_INFO(ssp);
+	struct stacktrace_state sts;
+
+	sts.depth = depth;
+	sts.output = output;
+	*current_thread_info() = *real_thread_info;
+
+	if (!current)
+		output->printf(output, "current NULL\n");
+	else
+		output->printf(output, "pid: %d  comm: %s\n",
+			current->pid, current->comm);
+	fiq_debugger_dump_regs(output, regs);
+
+	if (!user_mode(regs)) {
+		struct stackframe frame;
+		frame.fp = regs->ARM_fp;
+		frame.sp = regs->ARM_sp;
+		frame.lr = regs->ARM_lr;
+		frame.pc = regs->ARM_pc;
+		output->printf(output,
+			"  pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
+			regs->ARM_pc, regs->ARM_pc, regs->ARM_lr, regs->ARM_lr,
+			regs->ARM_sp, regs->ARM_fp);
+		walk_stackframe(&frame, report_trace, &sts);
+		return;
+	}
+
+	tail = ((struct frame_tail *) regs->ARM_fp) - 1;
+	while (depth-- && tail && !((unsigned long) tail & 3))
+		tail = user_backtrace(output, tail);
+}
diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger_arm64.c b/drivers/staging/android/fiq_debugger/fiq_debugger_arm64.c
new file mode 100644
index 0000000..97246bc
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/fiq_debugger_arm64.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/ptrace.h>
+#include <asm/stacktrace.h>
+
+#include "fiq_debugger_priv.h"
+
+static char *mode_name(const struct pt_regs *regs)
+{
+	if (compat_user_mode(regs)) {
+		return "USR";
+	} else {
+		switch (processor_mode(regs)) {
+		case PSR_MODE_EL0t: return "EL0t";
+		case PSR_MODE_EL1t: return "EL1t";
+		case PSR_MODE_EL1h: return "EL1h";
+		case PSR_MODE_EL2t: return "EL2t";
+		case PSR_MODE_EL2h: return "EL2h";
+		default: return "???";
+		}
+	}
+}
+
+void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
+		const struct pt_regs *regs)
+{
+	output->printf(output, " pc %016lx cpsr %08lx mode %s\n",
+		regs->pc, regs->pstate, mode_name(regs));
+}
+
+void fiq_debugger_dump_regs_aarch32(struct fiq_debugger_output *output,
+		const struct pt_regs *regs)
+{
+	output->printf(output, " r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
+			regs->compat_usr(0), regs->compat_usr(1),
+			regs->compat_usr(2), regs->compat_usr(3));
+	output->printf(output, " r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
+			regs->compat_usr(4), regs->compat_usr(5),
+			regs->compat_usr(6), regs->compat_usr(7));
+	output->printf(output, " r8 %08x  r9 %08x r10 %08x r11 %08x\n",
+			regs->compat_usr(8), regs->compat_usr(9),
+			regs->compat_usr(10), regs->compat_usr(11));
+	output->printf(output, " ip %08x  sp %08x  lr %08x  pc %08x\n",
+			regs->compat_usr(12), regs->compat_sp,
+			regs->compat_lr, regs->pc);
+	output->printf(output, " cpsr %08x (%s)\n",
+			regs->pstate, mode_name(regs));
+}
+
+void fiq_debugger_dump_regs_aarch64(struct fiq_debugger_output *output,
+		const struct pt_regs *regs)
+{
+
+	output->printf(output, "  x0 %016lx   x1 %016lx\n",
+			regs->regs[0], regs->regs[1]);
+	output->printf(output, "  x2 %016lx   x3 %016lx\n",
+			regs->regs[2], regs->regs[3]);
+	output->printf(output, "  x4 %016lx   x5 %016lx\n",
+			regs->regs[4], regs->regs[5]);
+	output->printf(output, "  x6 %016lx   x7 %016lx\n",
+			regs->regs[6], regs->regs[7]);
+	output->printf(output, "  x8 %016lx   x9 %016lx\n",
+			regs->regs[8], regs->regs[9]);
+	output->printf(output, " x10 %016lx  x11 %016lx\n",
+			regs->regs[10], regs->regs[11]);
+	output->printf(output, " x12 %016lx  x13 %016lx\n",
+			regs->regs[12], regs->regs[13]);
+	output->printf(output, " x14 %016lx  x15 %016lx\n",
+			regs->regs[14], regs->regs[15]);
+	output->printf(output, " x16 %016lx  x17 %016lx\n",
+			regs->regs[16], regs->regs[17]);
+	output->printf(output, " x18 %016lx  x19 %016lx\n",
+			regs->regs[18], regs->regs[19]);
+	output->printf(output, " x20 %016lx  x21 %016lx\n",
+			regs->regs[20], regs->regs[21]);
+	output->printf(output, " x22 %016lx  x23 %016lx\n",
+			regs->regs[22], regs->regs[23]);
+	output->printf(output, " x24 %016lx  x25 %016lx\n",
+			regs->regs[24], regs->regs[25]);
+	output->printf(output, " x26 %016lx  x27 %016lx\n",
+			regs->regs[26], regs->regs[27]);
+	output->printf(output, " x28 %016lx  x29 %016lx\n",
+			regs->regs[28], regs->regs[29]);
+	output->printf(output, " x30 %016lx   sp %016lx\n",
+			regs->regs[30], regs->sp);
+	output->printf(output, "  pc %016lx cpsr %08x (%s)\n",
+			regs->pc, regs->pstate, mode_name(regs));
+}
+
+void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
+		const struct pt_regs *regs)
+{
+	if (compat_user_mode(regs))
+		fiq_debugger_dump_regs_aarch32(output, regs);
+	else
+		fiq_debugger_dump_regs_aarch64(output, regs);
+}
+
+#define READ_SPECIAL_REG(x) ({ \
+	u64 val; \
+	asm volatile ("mrs %0, " # x : "=r"(val)); \
+	val; \
+})
+
+void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
+		const struct pt_regs *regs)
+{
+	u32 pstate = READ_SPECIAL_REG(CurrentEl);
+	bool in_el2 = (pstate & PSR_MODE_MASK) >= PSR_MODE_EL2t;
+
+	fiq_debugger_dump_regs(output, regs);
+
+	output->printf(output, " sp_el0   %016lx\n",
+			READ_SPECIAL_REG(sp_el0));
+
+	if (in_el2)
+		output->printf(output, " sp_el1   %016lx\n",
+				READ_SPECIAL_REG(sp_el1));
+
+	output->printf(output, " elr_el1  %016lx\n",
+			READ_SPECIAL_REG(elr_el1));
+
+	output->printf(output, " spsr_el1 %08lx\n",
+			READ_SPECIAL_REG(spsr_el1));
+
+	if (in_el2) {
+		output->printf(output, " spsr_irq %08lx\n",
+				READ_SPECIAL_REG(spsr_irq));
+		output->printf(output, " spsr_abt %08lx\n",
+				READ_SPECIAL_REG(spsr_abt));
+		output->printf(output, " spsr_und %08lx\n",
+				READ_SPECIAL_REG(spsr_und));
+		output->printf(output, " spsr_fiq %08lx\n",
+				READ_SPECIAL_REG(spsr_fiq));
+		output->printf(output, " spsr_el2 %08lx\n",
+				READ_SPECIAL_REG(elr_el2));
+		output->printf(output, " spsr_el2 %08lx\n",
+				READ_SPECIAL_REG(spsr_el2));
+	}
+}
+
+struct stacktrace_state {
+	struct fiq_debugger_output *output;
+	unsigned int depth;
+};
+
+static int report_trace(struct stackframe *frame, void *d)
+{
+	struct stacktrace_state *sts = d;
+
+	if (sts->depth) {
+		sts->output->printf(sts->output, "%pF:\n", frame->pc);
+		sts->output->printf(sts->output,
+				"  pc %016lx   sp %016lx   fp %016lx\n",
+				frame->pc, frame->sp, frame->fp);
+		sts->depth--;
+		return 0;
+	}
+	sts->output->printf(sts->output, "  ...\n");
+
+	return sts->depth == 0;
+}
+
+void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
+		const struct pt_regs *regs, unsigned int depth, void *ssp)
+{
+	struct thread_info *real_thread_info = THREAD_INFO(ssp);
+	struct stacktrace_state sts;
+
+	sts.depth = depth;
+	sts.output = output;
+	*current_thread_info() = *real_thread_info;
+
+	if (!current)
+		output->printf(output, "current NULL\n");
+	else
+		output->printf(output, "pid: %d  comm: %s\n",
+			current->pid, current->comm);
+	fiq_debugger_dump_regs(output, regs);
+
+	if (!user_mode(regs)) {
+		struct stackframe frame;
+		frame.fp = regs->regs[29];
+		frame.sp = regs->sp;
+		frame.pc = regs->pc;
+		output->printf(output, "\n");
+		walk_stackframe(current, &frame, report_trace, &sts);
+	}
+}
diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger_priv.h b/drivers/staging/android/fiq_debugger/fiq_debugger_priv.h
new file mode 100644
index 0000000..d5d051f
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/fiq_debugger_priv.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _FIQ_DEBUGGER_PRIV_H_
+#define _FIQ_DEBUGGER_PRIV_H_
+
+#define THREAD_INFO(sp) ((struct thread_info *) \
+		((unsigned long)(sp) & ~(THREAD_SIZE - 1)))
+
+struct fiq_debugger_output {
+	void (*printf)(struct fiq_debugger_output *output, const char *fmt, ...);
+};
+
+struct pt_regs;
+
+void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
+		const struct pt_regs *regs);
+void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
+		const struct pt_regs *regs);
+void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
+		const struct pt_regs *regs);
+void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
+		const struct pt_regs *regs, unsigned int depth, void *ssp);
+
+#endif
diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h b/drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h
new file mode 100644
index 0000000..10c3c5d
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h
@@ -0,0 +1,94 @@
+/*
+ * drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h
+ *
+ * simple lockless ringbuffer
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+struct fiq_debugger_ringbuf {
+	int len;
+	int head;
+	int tail;
+	u8 buf[];
+};
+
+
+static inline struct fiq_debugger_ringbuf *fiq_debugger_ringbuf_alloc(int len)
+{
+	struct fiq_debugger_ringbuf *rbuf;
+
+	rbuf = kzalloc(sizeof(*rbuf) + len, GFP_KERNEL);
+	if (rbuf == NULL)
+		return NULL;
+
+	rbuf->len = len;
+	rbuf->head = 0;
+	rbuf->tail = 0;
+	smp_mb();
+
+	return rbuf;
+}
+
+static inline void fiq_debugger_ringbuf_free(struct fiq_debugger_ringbuf *rbuf)
+{
+	kfree(rbuf);
+}
+
+static inline int fiq_debugger_ringbuf_level(struct fiq_debugger_ringbuf *rbuf)
+{
+	int level = rbuf->head - rbuf->tail;
+
+	if (level < 0)
+		level = rbuf->len + level;
+
+	return level;
+}
+
+static inline int fiq_debugger_ringbuf_room(struct fiq_debugger_ringbuf *rbuf)
+{
+	return rbuf->len - fiq_debugger_ringbuf_level(rbuf) - 1;
+}
+
+static inline u8
+fiq_debugger_ringbuf_peek(struct fiq_debugger_ringbuf *rbuf, int i)
+{
+	return rbuf->buf[(rbuf->tail + i) % rbuf->len];
+}
+
+static inline int
+fiq_debugger_ringbuf_consume(struct fiq_debugger_ringbuf *rbuf, int count)
+{
+	count = min(count, fiq_debugger_ringbuf_level(rbuf));
+
+	rbuf->tail = (rbuf->tail + count) % rbuf->len;
+	smp_mb();
+
+	return count;
+}
+
+static inline int
+fiq_debugger_ringbuf_push(struct fiq_debugger_ringbuf *rbuf, u8 datum)
+{
+	if (fiq_debugger_ringbuf_room(rbuf) == 0)
+		return 0;
+
+	rbuf->buf[rbuf->head] = datum;
+	smp_mb();
+	rbuf->head = (rbuf->head + 1) % rbuf->len;
+	smp_mb();
+
+	return 1;
+}
diff --git a/drivers/staging/android/fiq_debugger/fiq_watchdog.c b/drivers/staging/android/fiq_debugger/fiq_watchdog.c
new file mode 100644
index 0000000..194b541
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/fiq_watchdog.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/pstore_ram.h>
+
+#include "fiq_watchdog.h"
+#include "fiq_debugger_priv.h"
+
+static DEFINE_RAW_SPINLOCK(fiq_watchdog_lock);
+
+static void fiq_watchdog_printf(struct fiq_debugger_output *output,
+				const char *fmt, ...)
+{
+	char buf[256];
+	va_list ap;
+	int len;
+
+	va_start(ap, fmt);
+	len = vscnprintf(buf, sizeof(buf), fmt, ap);
+	va_end(ap);
+
+	ramoops_console_write_buf(buf, len);
+}
+
+struct fiq_debugger_output fiq_watchdog_output = {
+	.printf = fiq_watchdog_printf,
+};
+
+void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp)
+{
+	char msg[24];
+	int len;
+
+	raw_spin_lock(&fiq_watchdog_lock);
+
+	len = scnprintf(msg, sizeof(msg), "watchdog fiq cpu %d\n",
+			THREAD_INFO(svc_sp)->cpu);
+	ramoops_console_write_buf(msg, len);
+
+	fiq_debugger_dump_stacktrace(&fiq_watchdog_output, regs, 100, svc_sp);
+
+	raw_spin_unlock(&fiq_watchdog_lock);
+}
diff --git a/drivers/staging/android/fiq_debugger/fiq_watchdog.h b/drivers/staging/android/fiq_debugger/fiq_watchdog.h
new file mode 100644
index 0000000..c6b507f
--- /dev/null
+++ b/drivers/staging/android/fiq_debugger/fiq_watchdog.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _FIQ_WATCHDOG_H_
+#define _FIQ_WATCHDOG_H_
+
+void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp);
+
+#endif
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index df56021..374f840 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -387,13 +387,22 @@
 	kref_get(&handle->ref);
 }
 
-static int ion_handle_put(struct ion_handle *handle)
+static int ion_handle_put_nolock(struct ion_handle *handle)
+{
+	int ret;
+
+	ret = kref_put(&handle->ref, ion_handle_destroy);
+
+	return ret;
+}
+
+int ion_handle_put(struct ion_handle *handle)
 {
 	struct ion_client *client = handle->client;
 	int ret;
 
 	mutex_lock(&client->lock);
-	ret = kref_put(&handle->ref, ion_handle_destroy);
+	ret = ion_handle_put_nolock(handle);
 	mutex_unlock(&client->lock);
 
 	return ret;
@@ -417,18 +426,28 @@
 	return ERR_PTR(-EINVAL);
 }
 
-static struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
+static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client,
+						int id)
+{
+	struct ion_handle *handle;
+
+	handle = idr_find(&client->idr, id);
+	if (handle)
+		ion_handle_get(handle);
+
+	return handle ? handle : ERR_PTR(-EINVAL);
+}
+
+struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
 						int id)
 {
 	struct ion_handle *handle;
 
 	mutex_lock(&client->lock);
-	handle = idr_find(&client->idr, id);
-	if (handle)
-		ion_handle_get(handle);
+	handle = ion_handle_get_by_id_nolock(client, id);
 	mutex_unlock(&client->lock);
 
-	return handle ? handle : ERR_PTR(-EINVAL);
+	return handle;
 }
 
 static bool ion_handle_validate(struct ion_client *client,
@@ -532,22 +551,28 @@
 }
 EXPORT_SYMBOL(ion_alloc);
 
-void ion_free(struct ion_client *client, struct ion_handle *handle)
+static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle)
 {
 	bool valid_handle;
 
 	BUG_ON(client != handle->client);
 
-	mutex_lock(&client->lock);
 	valid_handle = ion_handle_validate(client, handle);
 
 	if (!valid_handle) {
 		WARN(1, "%s: invalid handle passed to free.\n", __func__);
-		mutex_unlock(&client->lock);
 		return;
 	}
+	ion_handle_put_nolock(handle);
+}
+
+void ion_free(struct ion_client *client, struct ion_handle *handle)
+{
+	BUG_ON(client != handle->client);
+
+	mutex_lock(&client->lock);
+	ion_free_nolock(client, handle);
 	mutex_unlock(&client->lock);
-	ion_handle_put(handle);
 }
 EXPORT_SYMBOL(ion_free);
 
@@ -1283,11 +1308,15 @@
 	{
 		struct ion_handle *handle;
 
-		handle = ion_handle_get_by_id(client, data.handle.handle);
-		if (IS_ERR(handle))
+		mutex_lock(&client->lock);
+		handle = ion_handle_get_by_id_nolock(client, data.handle.handle);
+		if (IS_ERR(handle)) {
+			mutex_unlock(&client->lock);
 			return PTR_ERR(handle);
-		ion_free(client, handle);
-		ion_handle_put(handle);
+		}
+		ion_free_nolock(client, handle);
+		ion_handle_put_nolock(handle);
+		mutex_unlock(&client->lock);
 		break;
 	}
 	case ION_IOC_SHARE:
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 0895834..606d13a 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -94,6 +94,7 @@
 	int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
 	int other_file = global_page_state(NR_FILE_PAGES) -
 						global_page_state(NR_SHMEM) -
+						global_page_state(NR_UNEVICTABLE) -
 						total_swapcache_pages();
 
 	if (lowmem_adj_size < array_size)
@@ -176,10 +177,10 @@
 			mark_oom_victim(selected);
 		task_unlock(selected);
 		trace_lowmemory_kill(selected, cache_size, cache_limit, free);
-		lowmem_print(1, "Killing '%s' (%d), adj %hd,\n"
-				 "   to free %ldkB on behalf of '%s' (%d) because\n"
-				 "   cache %ldkB is below limit %ldkB for oom_score_adj %hd\n"
-				 "   Free memory is %ldkB above reserved\n",
+		lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" \
+			        "   to free %ldkB on behalf of '%s' (%d) because\n" \
+			        "   cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" \
+			        "   Free memory is %ldkB above reserved\n",
 			     selected->comm, selected->pid,
 			     selected_oom_score_adj,
 			     selected_tasksize * (long)(PAGE_SIZE / 1024),
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 7b4af51..8fed553 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -2911,6 +2911,7 @@
 		dev = comedi_alloc_board_minor(NULL);
 		if (IS_ERR(dev)) {
 			comedi_cleanup_board_minors();
+			class_destroy(comedi_class);
 			cdev_del(&comedi_cdev);
 			unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
 						 COMEDI_NUM_MINORS);
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index 4ab1866..ec5b9a2 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -56,11 +56,6 @@
 
 #define N_CHANS 8
 
-enum waveform_state_bits {
-	WAVEFORM_AI_RUNNING,
-	WAVEFORM_AO_RUNNING
-};
-
 /* Data unique to this driver */
 struct waveform_private {
 	struct timer_list ai_timer;	/* timer for AI commands */
@@ -68,7 +63,6 @@
 	unsigned int wf_amplitude;	/* waveform amplitude in microvolts */
 	unsigned int wf_period;		/* waveform period in microseconds */
 	unsigned int wf_current;	/* current time in waveform period */
-	unsigned long state_bits;
 	unsigned int ai_scan_period;	/* AI scan period in usec */
 	unsigned int ai_convert_period;	/* AI conversion period in usec */
 	struct timer_list ao_timer;	/* timer for AO commands */
@@ -191,10 +185,6 @@
 	unsigned int nsamples;
 	unsigned int time_increment;
 
-	/* check command is still active */
-	if (!test_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits))
-		return;
-
 	now = ktime_to_us(ktime_get());
 	nsamples = comedi_nsamples_left(s, UINT_MAX);
 
@@ -386,11 +376,6 @@
 	 */
 	devpriv->ai_timer.expires =
 		jiffies + usecs_to_jiffies(devpriv->ai_convert_period) + 1;
-
-	/* mark command as active */
-	smp_mb__before_atomic();
-	set_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits);
-	smp_mb__after_atomic();
 	add_timer(&devpriv->ai_timer);
 	return 0;
 }
@@ -400,11 +385,12 @@
 {
 	struct waveform_private *devpriv = dev->private;
 
-	/* mark command as no longer active */
-	clear_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits);
-	smp_mb__after_atomic();
-	/* cannot call del_timer_sync() as may be called from timer routine */
-	del_timer(&devpriv->ai_timer);
+	if (in_softirq()) {
+		/* Assume we were called from the timer routine itself. */
+		del_timer(&devpriv->ai_timer);
+	} else {
+		del_timer_sync(&devpriv->ai_timer);
+	}
 	return 0;
 }
 
@@ -436,10 +422,6 @@
 	u64 scans_since;
 	unsigned int scans_avail = 0;
 
-	/* check command is still active */
-	if (!test_bit(WAVEFORM_AO_RUNNING, &devpriv->state_bits))
-		return;
-
 	/* determine number of scan periods since last time */
 	now = ktime_to_us(ktime_get());
 	scans_since = now - devpriv->ao_last_scan_time;
@@ -518,11 +500,6 @@
 	devpriv->ao_last_scan_time = ktime_to_us(ktime_get());
 	devpriv->ao_timer.expires =
 		jiffies + usecs_to_jiffies(devpriv->ao_scan_period);
-
-	/* mark command as active */
-	smp_mb__before_atomic();
-	set_bit(WAVEFORM_AO_RUNNING, &devpriv->state_bits);
-	smp_mb__after_atomic();
 	add_timer(&devpriv->ao_timer);
 
 	return 1;
@@ -608,11 +585,12 @@
 	struct waveform_private *devpriv = dev->private;
 
 	s->async->inttrig = NULL;
-	/* mark command as no longer active */
-	clear_bit(WAVEFORM_AO_RUNNING, &devpriv->state_bits);
-	smp_mb__after_atomic();
-	/* cannot call del_timer_sync() as may be called from timer routine */
-	del_timer(&devpriv->ao_timer);
+	if (in_softirq()) {
+		/* Assume we were called from the timer routine itself. */
+		del_timer(&devpriv->ao_timer);
+	} else {
+		del_timer_sync(&devpriv->ao_timer);
+	}
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index 57ab668..e5fee6e 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -636,7 +636,7 @@
 	const struct daq200_boardtype *board;
 	int i;
 
-	if (pcidev->subsystem_device != PCI_VENDOR_ID_IOTECH)
+	if (pcidev->subsystem_vendor != PCI_VENDOR_ID_IOTECH)
 		return NULL;
 
 	for (i = 0; i < ARRAY_SIZE(boardtypes); i++) {
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 94078118..3be1096 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -567,14 +567,17 @@
 	struct comedi_isadma_desc *desc;
 	int i;
 
-	outb(0x0, dev->iobase + DAS1800_STATUS);	/* disable conversions */
-	outb(0x0, dev->iobase + DAS1800_CONTROL_B);	/* disable interrupts and dma */
-	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* disable and clear fifo and stop triggering */
+	/* disable and stop conversions */
+	outb(0x0, dev->iobase + DAS1800_STATUS);
+	outb(0x0, dev->iobase + DAS1800_CONTROL_B);
+	outb(0x0, dev->iobase + DAS1800_CONTROL_A);
 
-	for (i = 0; i < 2; i++) {
-		desc = &dma->desc[i];
-		if (desc->chan)
-			comedi_isadma_disable(desc->chan);
+	if (dma) {
+		for (i = 0; i < 2; i++) {
+			desc = &dma->desc[i];
+			if (desc->chan)
+				comedi_isadma_disable(desc->chan);
+		}
 	}
 
 	return 0;
@@ -934,13 +937,14 @@
 {
 	struct das1800_private *devpriv = dev->private;
 	struct comedi_isadma *dma = devpriv->dma;
-	struct comedi_isadma_desc *desc = &dma->desc[0];
+	struct comedi_isadma_desc *desc;
 	unsigned int bytes;
 
 	if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
 		return;
 
 	dma->cur_dma = 0;
+	desc = &dma->desc[0];
 
 	/* determine a dma transfer size to fill buffer in 0.3 sec */
 	bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000);
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 5a536a0..b63472d 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -69,48 +69,49 @@
  * Register map
  */
 #define DT2821_ADCSR_REG		0x00
-#define DT2821_ADCSR_ADERR		(1 << 15)
-#define DT2821_ADCSR_ADCLK		(1 << 9)
-#define DT2821_ADCSR_MUXBUSY		(1 << 8)
-#define DT2821_ADCSR_ADDONE		(1 << 7)
-#define DT2821_ADCSR_IADDONE		(1 << 6)
+#define DT2821_ADCSR_ADERR		BIT(15)
+#define DT2821_ADCSR_ADCLK		BIT(9)
+#define DT2821_ADCSR_MUXBUSY		BIT(8)
+#define DT2821_ADCSR_ADDONE		BIT(7)
+#define DT2821_ADCSR_IADDONE		BIT(6)
 #define DT2821_ADCSR_GS(x)		(((x) & 0x3) << 4)
 #define DT2821_ADCSR_CHAN(x)		(((x) & 0xf) << 0)
 #define DT2821_CHANCSR_REG		0x02
-#define DT2821_CHANCSR_LLE		(1 << 15)
-#define DT2821_CHANCSR_PRESLA(x)	(((x) & 0xf) >> 8)
+#define DT2821_CHANCSR_LLE		BIT(15)
+#define DT2821_CHANCSR_TO_PRESLA(x)	(((x) >> 8) & 0xf)
 #define DT2821_CHANCSR_NUMB(x)		((((x) - 1) & 0xf) << 0)
 #define DT2821_ADDAT_REG		0x04
 #define DT2821_DACSR_REG		0x06
-#define DT2821_DACSR_DAERR		(1 << 15)
+#define DT2821_DACSR_DAERR		BIT(15)
 #define DT2821_DACSR_YSEL(x)		((x) << 9)
-#define DT2821_DACSR_SSEL		(1 << 8)
-#define DT2821_DACSR_DACRDY		(1 << 7)
-#define DT2821_DACSR_IDARDY		(1 << 6)
-#define DT2821_DACSR_DACLK		(1 << 5)
-#define DT2821_DACSR_HBOE		(1 << 1)
-#define DT2821_DACSR_LBOE		(1 << 0)
+#define DT2821_DACSR_SSEL		BIT(8)
+#define DT2821_DACSR_DACRDY		BIT(7)
+#define DT2821_DACSR_IDARDY		BIT(6)
+#define DT2821_DACSR_DACLK		BIT(5)
+#define DT2821_DACSR_HBOE		BIT(1)
+#define DT2821_DACSR_LBOE		BIT(0)
 #define DT2821_DADAT_REG		0x08
 #define DT2821_DIODAT_REG		0x0a
 #define DT2821_SUPCSR_REG		0x0c
-#define DT2821_SUPCSR_DMAD		(1 << 15)
-#define DT2821_SUPCSR_ERRINTEN		(1 << 14)
-#define DT2821_SUPCSR_CLRDMADNE		(1 << 13)
-#define DT2821_SUPCSR_DDMA		(1 << 12)
-#define DT2821_SUPCSR_DS_PIO		(0 << 10)
-#define DT2821_SUPCSR_DS_AD_CLK		(1 << 10)
-#define DT2821_SUPCSR_DS_DA_CLK		(2 << 10)
-#define DT2821_SUPCSR_DS_AD_TRIG	(3 << 10)
-#define DT2821_SUPCSR_BUFFB		(1 << 9)
-#define DT2821_SUPCSR_SCDN		(1 << 8)
-#define DT2821_SUPCSR_DACON		(1 << 7)
-#define DT2821_SUPCSR_ADCINIT		(1 << 6)
-#define DT2821_SUPCSR_DACINIT		(1 << 5)
-#define DT2821_SUPCSR_PRLD		(1 << 4)
-#define DT2821_SUPCSR_STRIG		(1 << 3)
-#define DT2821_SUPCSR_XTRIG		(1 << 2)
-#define DT2821_SUPCSR_XCLK		(1 << 1)
-#define DT2821_SUPCSR_BDINIT		(1 << 0)
+#define DT2821_SUPCSR_DMAD		BIT(15)
+#define DT2821_SUPCSR_ERRINTEN		BIT(14)
+#define DT2821_SUPCSR_CLRDMADNE		BIT(13)
+#define DT2821_SUPCSR_DDMA		BIT(12)
+#define DT2821_SUPCSR_DS(x)		(((x) & 0x3) << 10)
+#define DT2821_SUPCSR_DS_PIO		DT2821_SUPCSR_DS(0)
+#define DT2821_SUPCSR_DS_AD_CLK		DT2821_SUPCSR_DS(1)
+#define DT2821_SUPCSR_DS_DA_CLK		DT2821_SUPCSR_DS(2)
+#define DT2821_SUPCSR_DS_AD_TRIG	DT2821_SUPCSR_DS(3)
+#define DT2821_SUPCSR_BUFFB		BIT(9)
+#define DT2821_SUPCSR_SCDN		BIT(8)
+#define DT2821_SUPCSR_DACON		BIT(7)
+#define DT2821_SUPCSR_ADCINIT		BIT(6)
+#define DT2821_SUPCSR_DACINIT		BIT(5)
+#define DT2821_SUPCSR_PRLD		BIT(4)
+#define DT2821_SUPCSR_STRIG		BIT(3)
+#define DT2821_SUPCSR_XTRIG		BIT(2)
+#define DT2821_SUPCSR_XCLK		BIT(1)
+#define DT2821_SUPCSR_BDINIT		BIT(0)
 #define DT2821_TMRCTR_REG		0x0e
 
 static const struct comedi_lrange range_dt282x_ai_lo_bipolar = {
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index b87192e..109becd 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -610,7 +610,7 @@
 		s = &dev->subdevices[i];
 		spriv = s->private;
 
-		if (now > spriv->next_time_min) {
+		if (time_after_eq(now, spriv->next_time_min)) {
 			struct jr3_pci_poll_delay sub_delay;
 
 			sub_delay = jr3_pci_poll_subdevice(s);
@@ -726,11 +726,12 @@
 		s->insn_read	= jr3_pci_ai_insn_read;
 
 		spriv = jr3_pci_alloc_spriv(dev, s);
-		if (spriv) {
-			/* Channel specific range and maxdata */
-			s->range_table_list	= spriv->range_table_list;
-			s->maxdata_list		= spriv->maxdata_list;
-		}
+		if (!spriv)
+			return -ENOMEM;
+
+		/* Channel specific range and maxdata */
+		s->range_table_list	= spriv->range_table_list;
+		s->maxdata_list		= spriv->maxdata_list;
 	}
 
 	/*  Reset DSP card */
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 27fbf1a..c975f6e 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -1929,7 +1929,7 @@
 			   unsigned int *data)
 {
 	struct ni_private *devpriv = dev->private;
-	unsigned int mask = (s->maxdata + 1) >> 1;
+	unsigned int mask = s->maxdata;
 	int i, n;
 	unsigned signbits;
 	unsigned int d;
@@ -1972,7 +1972,7 @@
 				return -ETIME;
 			}
 			d += signbits;
-			data[n] = d;
+			data[n] = d & 0xffff;
 		}
 	} else if (devpriv->is_6143) {
 		for (n = 0; n < insn->n; n++) {
@@ -2017,8 +2017,8 @@
 				data[n] = dl;
 			} else {
 				d = ni_readw(dev, NI_E_AI_FIFO_DATA_REG);
-				d += signbits;	/* subtle: needs to be short addition */
-				data[n] = d;
+				d += signbits;
+				data[n] = d & 0xffff;
 			}
 		}
 	}
@@ -2823,7 +2823,15 @@
 	int i;
 	static const int timeout = 1000;
 
-	if (trig_num != cmd->start_arg)
+	/*
+	 * Require trig_num == cmd->start_arg when cmd->start_src == TRIG_INT.
+	 * For backwards compatibility, also allow trig_num == 0 when
+	 * cmd->start_src != TRIG_INT (i.e. when cmd->start_src == TRIG_EXT);
+	 * in that case, the internal trigger is being used as a pre-trigger
+	 * before the external trigger.
+	 */
+	if (!(trig_num == cmd->start_arg ||
+	      (trig_num == 0 && cmd->start_src != TRIG_INT)))
 		return -EINVAL;
 
 	/* Null trig at beginning prevent ao start trigger from executing more than
@@ -5346,7 +5354,7 @@
 		s->maxdata	= (devpriv->is_m_series) ? 0xffffffff
 							 : 0x00ffffff;
 		s->insn_read	= ni_tio_insn_read;
-		s->insn_write	= ni_tio_insn_read;
+		s->insn_write	= ni_tio_insn_write;
 		s->insn_config	= ni_tio_insn_config;
 #ifdef PCIDMA
 		if (dev->irq && devpriv->mite) {
diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c
index 4e6c16a..91ff8fb 100644
--- a/drivers/staging/emxx_udc/emxx_udc.c
+++ b/drivers/staging/emxx_udc/emxx_udc.c
@@ -3181,7 +3181,7 @@
 };
 
 /*-------------------------------------------------------------------------*/
-static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc)
+static void nbu2ss_drv_ep_init(struct nbu2ss_udc *udc)
 {
 	int	i;
 
@@ -3211,7 +3211,7 @@
 
 /*-------------------------------------------------------------------------*/
 /* platform_driver */
-static int __init nbu2ss_drv_contest_init(
+static int nbu2ss_drv_contest_init(
 	struct platform_device *pdev,
 	struct nbu2ss_udc *udc)
 {
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index b1e4516..18c2b6d 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -392,11 +392,11 @@
 
 	if (unlikely(timeit)) {
 		ts_end = ktime_get();
-		if (ktime_to_ns(par->update_time))
+		if (!ktime_to_ns(par->update_time))
 			par->update_time = ts_start;
 
-		par->update_time = ts_start;
 		fps = ktime_us_delta(ts_start, par->update_time);
+		par->update_time = ts_start;
 		fps = fps ? 1000000 / fps : 0;
 
 		throughput = ktime_us_delta(ts_end, ts_start);
diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c
index 445f836..fb4f3fe 100644
--- a/drivers/staging/gdm724x/gdm_mux.c
+++ b/drivers/staging/gdm724x/gdm_mux.c
@@ -670,14 +670,14 @@
 
 static void __exit gdm_usb_mux_exit(void)
 {
-	unregister_lte_tty_driver();
-
 	if (mux_rx_wq) {
 		flush_workqueue(mux_rx_wq);
 		destroy_workqueue(mux_rx_wq);
 	}
 
 	usb_deregister(&gdm_mux_driver);
+	unregister_lte_tty_driver();
+
 }
 
 module_init(gdm_usb_mux_init);
diff --git a/drivers/staging/goldfish/Kconfig b/drivers/staging/goldfish/Kconfig
index 4e09460..c579141 100644
--- a/drivers/staging/goldfish/Kconfig
+++ b/drivers/staging/goldfish/Kconfig
@@ -4,6 +4,12 @@
 	---help---
 	  Emulated audio channel for the Goldfish Android Virtual Device
 
+config GOLDFISH_SYNC
+    tristate "Goldfish AVD Sync Driver"
+    depends on GOLDFISH
+	---help---
+	  Emulated sync fences for the Goldfish Android Virtual Device
+
 config MTD_GOLDFISH_NAND
 	tristate "Goldfish NAND device"
 	depends on GOLDFISH
diff --git a/drivers/staging/goldfish/Makefile b/drivers/staging/goldfish/Makefile
index dec34ad..0cf5255 100644
--- a/drivers/staging/goldfish/Makefile
+++ b/drivers/staging/goldfish/Makefile
@@ -4,3 +4,8 @@
 
 obj-$(CONFIG_GOLDFISH_AUDIO) += goldfish_audio.o
 obj-$(CONFIG_MTD_GOLDFISH_NAND)	+= goldfish_nand.o
+
+# and sync
+
+ccflags-y := -Idrivers/staging/android
+obj-$(CONFIG_GOLDFISH_SYNC) += goldfish_sync.o
diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c
index b0927e4..63b79c0 100644
--- a/drivers/staging/goldfish/goldfish_audio.c
+++ b/drivers/staging/goldfish/goldfish_audio.c
@@ -26,7 +26,9 @@
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
 #include <linux/uaccess.h>
+#include <linux/slab.h>
 #include <linux/goldfish.h>
+#include <linux/acpi.h>
 
 MODULE_AUTHOR("Google, Inc.");
 MODULE_DESCRIPTION("Android QEMU Audio Driver");
@@ -115,6 +117,7 @@
 				   size_t count, loff_t *pos)
 {
 	struct goldfish_audio *data = fp->private_data;
+	unsigned long irq_flags;
 	int length;
 	int result = 0;
 
@@ -128,6 +131,10 @@
 		wait_event_interruptible(data->wait, data->buffer_status &
 					 AUDIO_INT_READ_BUFFER_FULL);
 
+		spin_lock_irqsave(&data->lock, irq_flags);
+		data->buffer_status &= ~AUDIO_INT_READ_BUFFER_FULL;
+		spin_unlock_irqrestore(&data->lock, irq_flags);
+
 		length = AUDIO_READ(data, AUDIO_READ_BUFFER_AVAILABLE);
 
 		/* copy data to user space */
@@ -344,11 +351,25 @@
 	return 0;
 }
 
+static const struct of_device_id goldfish_audio_of_match[] = {
+	{ .compatible = "google,goldfish-audio", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, goldfish_audio_of_match);
+
+static const struct acpi_device_id goldfish_audio_acpi_match[] = {
+	{ "GFSH0005", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, goldfish_audio_acpi_match);
+
 static struct platform_driver goldfish_audio_driver = {
 	.probe		= goldfish_audio_probe,
 	.remove		= goldfish_audio_remove,
 	.driver = {
-		.name = "goldfish_audio"
+		.name = "goldfish_audio",
+		.of_match_table = goldfish_audio_of_match,
+		.acpi_match_table = ACPI_PTR(goldfish_audio_acpi_match),
 	}
 };
 
diff --git a/drivers/staging/goldfish/goldfish_sync.c b/drivers/staging/goldfish/goldfish_sync.c
new file mode 100644
index 0000000..ba8def2
--- /dev/null
+++ b/drivers/staging/goldfish/goldfish_sync.c
@@ -0,0 +1,987 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/fdtable.h>
+#include <linux/file.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <linux/interrupt.h>
+#include <linux/kref.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/acpi.h>
+
+#include <linux/string.h>
+#include <linux/syscalls.h>
+
+#include "sw_sync.h"
+#include "sync.h"
+
+#define ERR(...) printk(KERN_ERR __VA_ARGS__);
+
+#define INFO(...) printk(KERN_INFO __VA_ARGS__);
+
+#define DPRINT(...) pr_debug(__VA_ARGS__);
+
+#define DTRACE() DPRINT("%s: enter", __func__)
+
+/* The Goldfish sync driver is designed to provide a interface
+ * between the underlying host's sync device and the kernel's
+ * sw_sync.
+ * The purpose of the device/driver is to enable lightweight
+ * creation and signaling of timelines and fences
+ * in order to synchronize the guest with host-side graphics events.
+ *
+ * Each time the interrupt trips, the driver
+ * may perform a sw_sync operation.
+ */
+
+/* The operations are: */
+
+/* Ready signal - used to mark when irq should lower */
+#define CMD_SYNC_READY            0
+
+/* Create a new timeline. writes timeline handle */
+#define CMD_CREATE_SYNC_TIMELINE  1
+
+/* Create a fence object. reads timeline handle and time argument.
+ * Writes fence fd to the SYNC_REG_HANDLE register. */
+#define CMD_CREATE_SYNC_FENCE     2
+
+/* Increments timeline. reads timeline handle and time argument */
+#define CMD_SYNC_TIMELINE_INC     3
+
+/* Destroys a timeline. reads timeline handle */
+#define CMD_DESTROY_SYNC_TIMELINE 4
+
+/* Starts a wait on the host with
+ * the given glsync object and sync thread handle. */
+#define CMD_TRIGGER_HOST_WAIT     5
+
+/* The register layout is: */
+
+#define SYNC_REG_BATCH_COMMAND                0x00 /* host->guest batch commands */
+#define SYNC_REG_BATCH_GUESTCOMMAND           0x04 /* guest->host batch commands */
+#define SYNC_REG_BATCH_COMMAND_ADDR           0x08 /* communicate physical address of host->guest batch commands */
+#define SYNC_REG_BATCH_COMMAND_ADDR_HIGH      0x0c /* 64-bit part */
+#define SYNC_REG_BATCH_GUESTCOMMAND_ADDR      0x10 /* communicate physical address of guest->host commands */
+#define SYNC_REG_BATCH_GUESTCOMMAND_ADDR_HIGH 0x14 /* 64-bit part */
+#define SYNC_REG_INIT                         0x18 /* signals that the device has been probed */
+
+/* There is an ioctl associated with goldfish sync driver.
+ * Make it conflict with ioctls that are not likely to be used
+ * in the emulator.
+ *
+ * '@'	00-0F	linux/radeonfb.h	conflict!
+ * '@'	00-0F	drivers/video/aty/aty128fb.c	conflict!
+ */
+#define GOLDFISH_SYNC_IOC_MAGIC	'@'
+
+#define GOLDFISH_SYNC_IOC_QUEUE_WORK	_IOWR(GOLDFISH_SYNC_IOC_MAGIC, 0, struct goldfish_sync_ioctl_info)
+
+/* The above definitions (command codes, register layout, ioctl definitions)
+ * need to be in sync with the following files:
+ *
+ * Host-side (emulator):
+ * external/qemu/android/emulation/goldfish_sync.h
+ * external/qemu-android/hw/misc/goldfish_sync.c
+ *
+ * Guest-side (system image):
+ * device/generic/goldfish-opengl/system/egl/goldfish_sync.h
+ * device/generic/goldfish/ueventd.ranchu.rc
+ * platform/build/target/board/generic/sepolicy/file_contexts
+ */
+struct goldfish_sync_hostcmd {
+	/* sorted for alignment */
+	uint64_t handle;
+	uint64_t hostcmd_handle;
+	uint32_t cmd;
+	uint32_t time_arg;
+};
+
+struct goldfish_sync_guestcmd {
+	uint64_t host_command; /* uint64_t for alignment */
+	uint64_t glsync_handle;
+	uint64_t thread_handle;
+	uint64_t guest_timeline_handle;
+};
+
+#define GOLDFISH_SYNC_MAX_CMDS 64
+
+struct goldfish_sync_state {
+	char __iomem *reg_base;
+	int irq;
+
+	/* Spinlock protects |to_do| / |to_do_end|. */
+	spinlock_t lock;
+	/* |mutex_lock| protects all concurrent access
+	 * to timelines for both kernel and user space. */
+	struct mutex mutex_lock;
+
+	/* Buffer holding commands issued from host. */
+	struct goldfish_sync_hostcmd to_do[GOLDFISH_SYNC_MAX_CMDS];
+	uint32_t to_do_end;
+
+	/* Addresses for the reading or writing
+	 * of individual commands. The host can directly write
+	 * to |batch_hostcmd| (and then this driver immediately
+	 * copies contents to |to_do|). This driver either replies
+	 * through |batch_hostcmd| or simply issues a
+	 * guest->host command through |batch_guestcmd|.
+	 */
+	struct goldfish_sync_hostcmd *batch_hostcmd;
+	struct goldfish_sync_guestcmd *batch_guestcmd;
+
+	/* Used to give this struct itself to a work queue
+	 * function for executing actual sync commands. */
+	struct work_struct work_item;
+};
+
+static struct goldfish_sync_state global_sync_state[1];
+
+struct goldfish_sync_timeline_obj {
+	struct sw_sync_timeline *sw_sync_tl;
+	uint32_t current_time;
+	/* We need to be careful about when we deallocate
+	 * this |goldfish_sync_timeline_obj| struct.
+	 * In order to ensure proper cleanup, we need to
+	 * consider the triggered host-side wait that may
+	 * still be in flight when the guest close()'s a
+	 * goldfish_sync device's sync context fd (and
+	 * destroys the |sw_sync_tl| field above).
+	 * The host-side wait may raise IRQ
+	 * and tell the kernel to increment the timeline _after_
+	 * the |sw_sync_tl| has already been set to null.
+	 *
+	 * From observations on OpenGL apps and CTS tests, this
+	 * happens at some very low probability upon context
+	 * destruction or process close, but it does happen
+	 * and it needs to be handled properly. Otherwise,
+	 * if we clean up the surrounding |goldfish_sync_timeline_obj|
+	 * too early, any |handle| field of any host->guest command
+	 * might not even point to a null |sw_sync_tl| field,
+	 * but to garbage memory or even a reclaimed |sw_sync_tl|.
+	 * If we do not count such "pending waits" and kfree the object
+	 * immediately upon |goldfish_sync_timeline_destroy|,
+	 * we might get mysterous RCU stalls after running a long
+	 * time because the garbage memory that is being read
+	 * happens to be interpretable as a |spinlock_t| struct
+	 * that is currently in the locked state.
+	 *
+	 * To track when to free the |goldfish_sync_timeline_obj|
+	 * itself, we maintain a kref.
+	 * The kref essentially counts the timeline itself plus
+	 * the number of waits in flight. kref_init/kref_put
+	 * are issued on
+	 * |goldfish_sync_timeline_create|/|goldfish_sync_timeline_destroy|
+	 * and kref_get/kref_put are issued on
+	 * |goldfish_sync_fence_create|/|goldfish_sync_timeline_inc|.
+	 *
+	 * The timeline is destroyed after reference count
+	 * reaches zero, which would happen after
+	 * |goldfish_sync_timeline_destroy| and all pending
+	 * |goldfish_sync_timeline_inc|'s are fulfilled.
+	 *
+	 * NOTE (1): We assume that |fence_create| and
+	 * |timeline_inc| calls are 1:1, otherwise the kref scheme
+	 * will not work. This is a valid assumption as long
+	 * as the host-side virtual device implementation
+	 * does not insert any timeline increments
+	 * that we did not trigger from here.
+	 *
+	 * NOTE (2): The use of kref by itself requires no locks,
+	 * but this does not mean everything works without locks.
+	 * Related timeline operations do require a lock of some sort,
+	 * or at least are not proven to work without it.
+	 * In particualr, we assume that all the operations
+	 * done on the |kref| field above are done in contexts where
+	 * |global_sync_state->mutex_lock| is held. Do not
+	 * remove that lock until everything is proven to work
+	 * without it!!! */
+	struct kref kref;
+};
+
+/* We will call |delete_timeline_obj| when the last reference count
+ * of the kref is decremented. This deletes the sw_sync
+ * timeline object along with the wrapper itself. */
+static void delete_timeline_obj(struct kref* kref) {
+	struct goldfish_sync_timeline_obj* obj =
+		container_of(kref, struct goldfish_sync_timeline_obj, kref);
+
+	sync_timeline_destroy(&obj->sw_sync_tl->obj);
+	obj->sw_sync_tl = NULL;
+	kfree(obj);
+}
+
+static uint64_t gensym_ctr;
+static void gensym(char *dst)
+{
+	sprintf(dst, "goldfish_sync:gensym:%llu", gensym_ctr);
+	gensym_ctr++;
+}
+
+/* |goldfish_sync_timeline_create| assumes that |global_sync_state->mutex_lock|
+ * is held. */
+static struct goldfish_sync_timeline_obj*
+goldfish_sync_timeline_create(void)
+{
+
+	char timeline_name[256];
+	struct sw_sync_timeline *res_sync_tl = NULL;
+	struct goldfish_sync_timeline_obj *res;
+
+	DTRACE();
+
+	gensym(timeline_name);
+
+	res_sync_tl = sw_sync_timeline_create(timeline_name);
+	if (!res_sync_tl) {
+		ERR("Failed to create sw_sync timeline.");
+		return NULL;
+	}
+
+	res = kzalloc(sizeof(struct goldfish_sync_timeline_obj), GFP_KERNEL);
+	res->sw_sync_tl = res_sync_tl;
+	res->current_time = 0;
+	kref_init(&res->kref);
+
+	DPRINT("new timeline_obj=0x%p", res);
+	return res;
+}
+
+/* |goldfish_sync_fence_create| assumes that |global_sync_state->mutex_lock|
+ * is held. */
+static int
+goldfish_sync_fence_create(struct goldfish_sync_timeline_obj *obj,
+							uint32_t val)
+{
+
+	int fd;
+	char fence_name[256];
+	struct sync_pt *syncpt = NULL;
+	struct sync_fence *sync_obj = NULL;
+	struct sw_sync_timeline *tl;
+
+	DTRACE();
+
+	if (!obj) return -1;
+
+	tl = obj->sw_sync_tl;
+
+	syncpt = sw_sync_pt_create(tl, val);
+	if (!syncpt) {
+		ERR("could not create sync point! "
+			"sync_timeline=0x%p val=%d",
+			   tl, val);
+		return -1;
+	}
+
+	fd = get_unused_fd_flags(O_CLOEXEC);
+	if (fd < 0) {
+		ERR("could not get unused fd for sync fence. "
+			"errno=%d", fd);
+		goto err_cleanup_pt;
+	}
+
+	gensym(fence_name);
+
+	sync_obj = sync_fence_create(fence_name, syncpt);
+	if (!sync_obj) {
+		ERR("could not create sync fence! "
+			"sync_timeline=0x%p val=%d sync_pt=0x%p",
+			   tl, val, syncpt);
+		goto err_cleanup_fd_pt;
+	}
+
+	DPRINT("installing sync fence into fd %d sync_obj=0x%p", fd, sync_obj);
+	sync_fence_install(sync_obj, fd);
+	kref_get(&obj->kref);
+
+	return fd;
+
+err_cleanup_fd_pt:
+	put_unused_fd(fd);
+err_cleanup_pt:
+	sync_pt_free(syncpt);
+	return -1;
+}
+
+/* |goldfish_sync_timeline_inc| assumes that |global_sync_state->mutex_lock|
+ * is held. */
+static void
+goldfish_sync_timeline_inc(struct goldfish_sync_timeline_obj *obj, uint32_t inc)
+{
+	DTRACE();
+	/* Just give up if someone else nuked the timeline.
+	 * Whoever it was won't care that it doesn't get signaled. */
+	if (!obj) return;
+
+	DPRINT("timeline_obj=0x%p", obj);
+	sw_sync_timeline_inc(obj->sw_sync_tl, inc);
+	DPRINT("incremented timeline. increment max_time");
+	obj->current_time += inc;
+
+	/* Here, we will end up deleting the timeline object if it
+	 * turns out that this call was a pending increment after
+	 * |goldfish_sync_timeline_destroy| was called. */
+	kref_put(&obj->kref, delete_timeline_obj);
+	DPRINT("done");
+}
+
+/* |goldfish_sync_timeline_destroy| assumes
+ * that |global_sync_state->mutex_lock| is held. */
+static void
+goldfish_sync_timeline_destroy(struct goldfish_sync_timeline_obj *obj)
+{
+	DTRACE();
+	/* See description of |goldfish_sync_timeline_obj| for why we
+	 * should not immediately destroy |obj| */
+	kref_put(&obj->kref, delete_timeline_obj);
+}
+
+static inline void
+goldfish_sync_cmd_queue(struct goldfish_sync_state *sync_state,
+						uint32_t cmd,
+						uint64_t handle,
+						uint32_t time_arg,
+						uint64_t hostcmd_handle)
+{
+	struct goldfish_sync_hostcmd *to_add;
+
+	DTRACE();
+
+	BUG_ON(sync_state->to_do_end == GOLDFISH_SYNC_MAX_CMDS);
+
+	to_add = &sync_state->to_do[sync_state->to_do_end];
+
+	to_add->cmd = cmd;
+	to_add->handle = handle;
+	to_add->time_arg = time_arg;
+	to_add->hostcmd_handle = hostcmd_handle;
+
+	sync_state->to_do_end += 1;
+}
+
+static inline void
+goldfish_sync_hostcmd_reply(struct goldfish_sync_state *sync_state,
+							uint32_t cmd,
+							uint64_t handle,
+							uint32_t time_arg,
+							uint64_t hostcmd_handle)
+{
+	unsigned long irq_flags;
+	struct goldfish_sync_hostcmd *batch_hostcmd =
+		sync_state->batch_hostcmd;
+
+	DTRACE();
+
+	spin_lock_irqsave(&sync_state->lock, irq_flags);
+
+	batch_hostcmd->cmd = cmd;
+	batch_hostcmd->handle = handle;
+	batch_hostcmd->time_arg = time_arg;
+	batch_hostcmd->hostcmd_handle = hostcmd_handle;
+	writel(0, sync_state->reg_base + SYNC_REG_BATCH_COMMAND);
+
+	spin_unlock_irqrestore(&sync_state->lock, irq_flags);
+}
+
+static inline void
+goldfish_sync_send_guestcmd(struct goldfish_sync_state *sync_state,
+							uint32_t cmd,
+							uint64_t glsync_handle,
+							uint64_t thread_handle,
+							uint64_t timeline_handle)
+{
+	unsigned long irq_flags;
+	struct goldfish_sync_guestcmd *batch_guestcmd =
+		sync_state->batch_guestcmd;
+
+	DTRACE();
+
+	spin_lock_irqsave(&sync_state->lock, irq_flags);
+
+	batch_guestcmd->host_command = (uint64_t)cmd;
+	batch_guestcmd->glsync_handle = (uint64_t)glsync_handle;
+	batch_guestcmd->thread_handle = (uint64_t)thread_handle;
+	batch_guestcmd->guest_timeline_handle = (uint64_t)timeline_handle;
+	writel(0, sync_state->reg_base + SYNC_REG_BATCH_GUESTCOMMAND);
+
+	spin_unlock_irqrestore(&sync_state->lock, irq_flags);
+}
+
+/* |goldfish_sync_interrupt| handles IRQ raises from the virtual device.
+ * In the context of OpenGL, this interrupt will fire whenever we need
+ * to signal a fence fd in the guest, with the command
+ * |CMD_SYNC_TIMELINE_INC|.
+ * However, because this function will be called in an interrupt context,
+ * it is necessary to do the actual work of signaling off of interrupt context.
+ * The shared work queue is used for this purpose. At the end when
+ * all pending commands are intercepted by the interrupt handler,
+ * we call |schedule_work|, which will later run the actual
+ * desired sync command in |goldfish_sync_work_item_fn|.
+ */
+static irqreturn_t goldfish_sync_interrupt(int irq, void *dev_id)
+{
+
+	struct goldfish_sync_state *sync_state = dev_id;
+
+	uint32_t nextcmd;
+	uint32_t command_r;
+	uint64_t handle_rw;
+	uint32_t time_r;
+	uint64_t hostcmd_handle_rw;
+
+	int count = 0;
+
+	DTRACE();
+
+	sync_state = dev_id;
+
+	spin_lock(&sync_state->lock);
+
+	for (;;) {
+
+		readl(sync_state->reg_base + SYNC_REG_BATCH_COMMAND);
+		nextcmd = sync_state->batch_hostcmd->cmd;
+
+		if (nextcmd == 0)
+			break;
+
+		command_r = nextcmd;
+		handle_rw = sync_state->batch_hostcmd->handle;
+		time_r = sync_state->batch_hostcmd->time_arg;
+		hostcmd_handle_rw = sync_state->batch_hostcmd->hostcmd_handle;
+
+		goldfish_sync_cmd_queue(
+				sync_state,
+				command_r,
+				handle_rw,
+				time_r,
+				hostcmd_handle_rw);
+
+		count++;
+	}
+
+	spin_unlock(&sync_state->lock);
+
+	schedule_work(&sync_state->work_item);
+
+	return (count == 0) ? IRQ_NONE : IRQ_HANDLED;
+}
+
+/* |goldfish_sync_work_item_fn| does the actual work of servicing
+ * host->guest sync commands. This function is triggered whenever
+ * the IRQ for the goldfish sync device is raised. Once it starts
+ * running, it grabs the contents of the buffer containing the
+ * commands it needs to execute (there may be multiple, because
+ * our IRQ is active high and not edge triggered), and then
+ * runs all of them one after the other.
+ */
+static void goldfish_sync_work_item_fn(struct work_struct *input)
+{
+
+	struct goldfish_sync_state *sync_state;
+	int sync_fence_fd;
+
+	struct goldfish_sync_timeline_obj *timeline;
+	uint64_t timeline_ptr;
+
+	uint64_t hostcmd_handle;
+
+	uint32_t cmd;
+	uint64_t handle;
+	uint32_t time_arg;
+
+	struct goldfish_sync_hostcmd *todo;
+	uint32_t todo_end;
+
+	unsigned long irq_flags;
+
+	struct goldfish_sync_hostcmd to_run[GOLDFISH_SYNC_MAX_CMDS];
+	uint32_t i = 0;
+
+	sync_state = container_of(input, struct goldfish_sync_state, work_item);
+
+	mutex_lock(&sync_state->mutex_lock);
+
+	spin_lock_irqsave(&sync_state->lock, irq_flags); {
+
+		todo_end = sync_state->to_do_end;
+
+		DPRINT("num sync todos: %u", sync_state->to_do_end);
+
+		for (i = 0; i < todo_end; i++)
+			to_run[i] = sync_state->to_do[i];
+
+		/* We expect that commands will come in at a slow enough rate
+		 * so that incoming items will not be more than
+		 * GOLDFISH_SYNC_MAX_CMDS.
+		 *
+		 * This is because the way the sync device is used,
+		 * it's only for managing buffer data transfers per frame,
+		 * with a sequential dependency between putting things in
+		 * to_do and taking them out. Once a set of commands is
+		 * queued up in to_do, the user of the device waits for
+		 * them to be processed before queuing additional commands,
+		 * which limits the rate at which commands come in
+		 * to the rate at which we take them out here.
+		 *
+		 * We also don't expect more than MAX_CMDS to be issued
+		 * at once; there is a correspondence between
+		 * which buffers need swapping to the (display / buffer queue)
+		 * to particular commands, and we don't expect there to be
+		 * enough display or buffer queues in operation at once
+		 * to overrun GOLDFISH_SYNC_MAX_CMDS.
+		 */
+		sync_state->to_do_end = 0;
+
+	} spin_unlock_irqrestore(&sync_state->lock, irq_flags);
+
+	for (i = 0; i < todo_end; i++) {
+		DPRINT("todo index: %u", i);
+
+		todo = &to_run[i];
+
+		cmd = todo->cmd;
+
+		handle = (uint64_t)todo->handle;
+		time_arg = todo->time_arg;
+		hostcmd_handle = (uint64_t)todo->hostcmd_handle;
+
+		DTRACE();
+
+		timeline = (struct goldfish_sync_timeline_obj *)(uintptr_t)handle;
+
+		switch (cmd) {
+		case CMD_SYNC_READY:
+			break;
+		case CMD_CREATE_SYNC_TIMELINE:
+			DPRINT("exec CMD_CREATE_SYNC_TIMELINE: "
+					"handle=0x%llx time_arg=%d",
+					handle, time_arg);
+			timeline = goldfish_sync_timeline_create();
+			timeline_ptr = (uintptr_t)timeline;
+			goldfish_sync_hostcmd_reply(sync_state, CMD_CREATE_SYNC_TIMELINE,
+										timeline_ptr,
+										0,
+										hostcmd_handle);
+			DPRINT("sync timeline created: %p", timeline);
+			break;
+		case CMD_CREATE_SYNC_FENCE:
+			DPRINT("exec CMD_CREATE_SYNC_FENCE: "
+					"handle=0x%llx time_arg=%d",
+					handle, time_arg);
+			sync_fence_fd = goldfish_sync_fence_create(timeline, time_arg);
+			goldfish_sync_hostcmd_reply(sync_state, CMD_CREATE_SYNC_FENCE,
+										sync_fence_fd,
+										0,
+										hostcmd_handle);
+			break;
+		case CMD_SYNC_TIMELINE_INC:
+			DPRINT("exec CMD_SYNC_TIMELINE_INC: "
+					"handle=0x%llx time_arg=%d",
+					handle, time_arg);
+			goldfish_sync_timeline_inc(timeline, time_arg);
+			break;
+		case CMD_DESTROY_SYNC_TIMELINE:
+			DPRINT("exec CMD_DESTROY_SYNC_TIMELINE: "
+					"handle=0x%llx time_arg=%d",
+					handle, time_arg);
+			goldfish_sync_timeline_destroy(timeline);
+			break;
+		}
+		DPRINT("Done executing sync command");
+	}
+	mutex_unlock(&sync_state->mutex_lock);
+}
+
+/* Guest-side interface: file operations */
+
+/* Goldfish sync context and ioctl info.
+ *
+ * When a sync context is created by open()-ing the goldfish sync device, we
+ * create a sync context (|goldfish_sync_context|).
+ *
+ * Currently, the only data required to track is the sync timeline itself
+ * along with the current time, which are all packed up in the
+ * |goldfish_sync_timeline_obj| field. We use a |goldfish_sync_context|
+ * as the filp->private_data.
+ *
+ * Next, when a sync context user requests that work be queued and a fence
+ * fd provided, we use the |goldfish_sync_ioctl_info| struct, which holds
+ * information about which host handles to touch for this particular
+ * queue-work operation. We need to know about the host-side sync thread
+ * and the particular host-side GLsync object. We also possibly write out
+ * a file descriptor.
+ */
+struct goldfish_sync_context {
+	struct goldfish_sync_timeline_obj *timeline;
+};
+
+struct goldfish_sync_ioctl_info {
+	uint64_t host_glsync_handle_in;
+	uint64_t host_syncthread_handle_in;
+	int fence_fd_out;
+};
+
+static int goldfish_sync_open(struct inode *inode, struct file *file)
+{
+
+	struct goldfish_sync_context *sync_context;
+
+	DTRACE();
+
+	mutex_lock(&global_sync_state->mutex_lock);
+
+	sync_context = kzalloc(sizeof(struct goldfish_sync_context), GFP_KERNEL);
+
+	if (sync_context == NULL) {
+		ERR("Creation of goldfish sync context failed!");
+		mutex_unlock(&global_sync_state->mutex_lock);
+		return -ENOMEM;
+	}
+
+	sync_context->timeline = NULL;
+
+	file->private_data = sync_context;
+
+	DPRINT("successfully create a sync context @0x%p", sync_context);
+
+	mutex_unlock(&global_sync_state->mutex_lock);
+
+	return 0;
+}
+
+static int goldfish_sync_release(struct inode *inode, struct file *file)
+{
+
+	struct goldfish_sync_context *sync_context;
+
+	DTRACE();
+
+	mutex_lock(&global_sync_state->mutex_lock);
+
+	sync_context = file->private_data;
+
+	if (sync_context->timeline)
+		goldfish_sync_timeline_destroy(sync_context->timeline);
+
+	sync_context->timeline = NULL;
+
+	kfree(sync_context);
+
+	mutex_unlock(&global_sync_state->mutex_lock);
+
+	return 0;
+}
+
+/* |goldfish_sync_ioctl| is the guest-facing interface of goldfish sync
+ * and is used in conjunction with eglCreateSyncKHR to queue up the
+ * actual work of waiting for the EGL sync command to complete,
+ * possibly returning a fence fd to the guest.
+ */
+static long goldfish_sync_ioctl(struct file *file,
+								unsigned int cmd,
+								unsigned long arg)
+{
+	struct goldfish_sync_context *sync_context_data;
+	struct goldfish_sync_timeline_obj *timeline;
+	int fd_out;
+	struct goldfish_sync_ioctl_info ioctl_data;
+
+	DTRACE();
+
+	sync_context_data = file->private_data;
+	fd_out = -1;
+
+	switch (cmd) {
+	case GOLDFISH_SYNC_IOC_QUEUE_WORK:
+
+		DPRINT("exec GOLDFISH_SYNC_IOC_QUEUE_WORK");
+
+		mutex_lock(&global_sync_state->mutex_lock);
+
+		if (copy_from_user(&ioctl_data,
+						(void __user *)arg,
+						sizeof(ioctl_data))) {
+			ERR("Failed to copy memory for ioctl_data from user.");
+			mutex_unlock(&global_sync_state->mutex_lock);
+			return -EFAULT;
+		}
+
+		if (ioctl_data.host_syncthread_handle_in == 0) {
+			DPRINT("Error: zero host syncthread handle!!!");
+			mutex_unlock(&global_sync_state->mutex_lock);
+			return -EFAULT;
+		}
+
+		if (!sync_context_data->timeline) {
+			DPRINT("no timeline yet, create one.");
+			sync_context_data->timeline = goldfish_sync_timeline_create();
+			DPRINT("timeline: 0x%p", &sync_context_data->timeline);
+		}
+
+		timeline = sync_context_data->timeline;
+		fd_out = goldfish_sync_fence_create(timeline,
+											timeline->current_time + 1);
+		DPRINT("Created fence with fd %d and current time %u (timeline: 0x%p)",
+			   fd_out,
+			   sync_context_data->timeline->current_time + 1,
+			   sync_context_data->timeline);
+
+		ioctl_data.fence_fd_out = fd_out;
+
+		if (copy_to_user((void __user *)arg,
+						&ioctl_data,
+						sizeof(ioctl_data))) {
+			DPRINT("Error, could not copy to user!!!");
+
+			sys_close(fd_out);
+			/* We won't be doing an increment, kref_put immediately. */
+			kref_put(&timeline->kref, delete_timeline_obj);
+			mutex_unlock(&global_sync_state->mutex_lock);
+			return -EFAULT;
+		}
+
+		/* We are now about to trigger a host-side wait;
+		 * accumulate on |pending_waits|. */
+		goldfish_sync_send_guestcmd(global_sync_state,
+				CMD_TRIGGER_HOST_WAIT,
+				ioctl_data.host_glsync_handle_in,
+				ioctl_data.host_syncthread_handle_in,
+				(uint64_t)(uintptr_t)(sync_context_data->timeline));
+
+		mutex_unlock(&global_sync_state->mutex_lock);
+		return 0;
+	default:
+		return -ENOTTY;
+	}
+}
+
+static const struct file_operations goldfish_sync_fops = {
+	.owner = THIS_MODULE,
+	.open = goldfish_sync_open,
+	.release = goldfish_sync_release,
+	.unlocked_ioctl = goldfish_sync_ioctl,
+	.compat_ioctl = goldfish_sync_ioctl,
+};
+
+static struct miscdevice goldfish_sync_device = {
+	.name = "goldfish_sync",
+	.fops = &goldfish_sync_fops,
+};
+
+
+static bool setup_verify_batch_cmd_addr(struct goldfish_sync_state *sync_state,
+										void *batch_addr,
+										uint32_t addr_offset,
+										uint32_t addr_offset_high)
+{
+	uint64_t batch_addr_phys;
+	uint32_t batch_addr_phys_test_lo;
+	uint32_t batch_addr_phys_test_hi;
+
+	if (!batch_addr) {
+		ERR("Could not use batch command address!");
+		return false;
+	}
+
+	batch_addr_phys = virt_to_phys(batch_addr);
+	writel((uint32_t)(batch_addr_phys),
+			sync_state->reg_base + addr_offset);
+	writel((uint32_t)(batch_addr_phys >> 32),
+			sync_state->reg_base + addr_offset_high);
+
+	batch_addr_phys_test_lo =
+		readl(sync_state->reg_base + addr_offset);
+	batch_addr_phys_test_hi =
+		readl(sync_state->reg_base + addr_offset_high);
+
+	if (virt_to_phys(batch_addr) !=
+			(((uint64_t)batch_addr_phys_test_hi << 32) |
+			 batch_addr_phys_test_lo)) {
+		ERR("Invalid batch command address!");
+		return false;
+	}
+
+	return true;
+}
+
+int goldfish_sync_probe(struct platform_device *pdev)
+{
+	struct resource *ioresource;
+	struct goldfish_sync_state *sync_state = global_sync_state;
+	int status;
+
+	DTRACE();
+
+	sync_state->to_do_end = 0;
+
+	spin_lock_init(&sync_state->lock);
+	mutex_init(&sync_state->mutex_lock);
+
+	platform_set_drvdata(pdev, sync_state);
+
+	ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (ioresource == NULL) {
+		ERR("platform_get_resource failed");
+		return -ENODEV;
+	}
+
+	sync_state->reg_base = devm_ioremap(&pdev->dev, ioresource->start, PAGE_SIZE);
+	if (sync_state->reg_base == NULL) {
+		ERR("Could not ioremap");
+		return -ENOMEM;
+	}
+
+	sync_state->irq = platform_get_irq(pdev, 0);
+	if (sync_state->irq < 0) {
+		ERR("Could not platform_get_irq");
+		return -ENODEV;
+	}
+
+	status = devm_request_irq(&pdev->dev,
+							sync_state->irq,
+							goldfish_sync_interrupt,
+							IRQF_SHARED,
+							pdev->name,
+							sync_state);
+	if (status) {
+		ERR("request_irq failed");
+		return -ENODEV;
+	}
+
+	INIT_WORK(&sync_state->work_item,
+			  goldfish_sync_work_item_fn);
+
+	misc_register(&goldfish_sync_device);
+
+	/* Obtain addresses for batch send/recv of commands. */
+	{
+		struct goldfish_sync_hostcmd *batch_addr_hostcmd;
+		struct goldfish_sync_guestcmd *batch_addr_guestcmd;
+
+		batch_addr_hostcmd = devm_kzalloc(&pdev->dev, sizeof(struct goldfish_sync_hostcmd),
+				GFP_KERNEL);
+		batch_addr_guestcmd = devm_kzalloc(&pdev->dev, sizeof(struct goldfish_sync_guestcmd),
+				GFP_KERNEL);
+
+		if (!setup_verify_batch_cmd_addr(sync_state,
+					batch_addr_hostcmd,
+					SYNC_REG_BATCH_COMMAND_ADDR,
+					SYNC_REG_BATCH_COMMAND_ADDR_HIGH)) {
+			ERR("goldfish_sync: Could not setup batch command address");
+			return -ENODEV;
+		}
+
+		if (!setup_verify_batch_cmd_addr(sync_state,
+					batch_addr_guestcmd,
+					SYNC_REG_BATCH_GUESTCOMMAND_ADDR,
+					SYNC_REG_BATCH_GUESTCOMMAND_ADDR_HIGH)) {
+			ERR("goldfish_sync: Could not setup batch guest command address");
+			return -ENODEV;
+		}
+
+		sync_state->batch_hostcmd = batch_addr_hostcmd;
+		sync_state->batch_guestcmd = batch_addr_guestcmd;
+	}
+
+	INFO("goldfish_sync: Initialized goldfish sync device");
+
+	writel(0, sync_state->reg_base + SYNC_REG_INIT);
+
+	return 0;
+}
+
+static int goldfish_sync_remove(struct platform_device *pdev)
+{
+	struct goldfish_sync_state *sync_state = global_sync_state;
+
+	DTRACE();
+
+	misc_deregister(&goldfish_sync_device);
+	memset(sync_state, 0, sizeof(struct goldfish_sync_state));
+	return 0;
+}
+
+static const struct of_device_id goldfish_sync_of_match[] = {
+	{ .compatible = "google,goldfish-sync", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, goldfish_sync_of_match);
+
+static const struct acpi_device_id goldfish_sync_acpi_match[] = {
+	{ "GFSH0006", 0 },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(acpi, goldfish_sync_acpi_match);
+
+static struct platform_driver goldfish_sync = {
+	.probe = goldfish_sync_probe,
+	.remove = goldfish_sync_remove,
+	.driver = {
+		.name = "goldfish_sync",
+		.of_match_table = goldfish_sync_of_match,
+		.acpi_match_table = ACPI_PTR(goldfish_sync_acpi_match),
+	}
+};
+
+module_platform_driver(goldfish_sync);
+
+MODULE_AUTHOR("Google, Inc.");
+MODULE_DESCRIPTION("Android QEMU Sync Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+
+/* This function is only to run a basic test of sync framework.
+ * It creates a timeline and fence object whose signal point is at 1.
+ * The timeline is incremented, and we use the sync framework's
+ * sync_fence_wait on that fence object. If everything works out,
+ * we should not hang in the wait and return immediately.
+ * There is no way to explicitly run this test yet, but it
+ * can be used by inserting it at the end of goldfish_sync_probe.
+ */
+void test_kernel_sync(void)
+{
+	struct goldfish_sync_timeline_obj *test_timeline;
+	int test_fence_fd;
+
+	DTRACE();
+
+	DPRINT("test sw_sync");
+
+	test_timeline = goldfish_sync_timeline_create();
+	DPRINT("sw_sync_timeline_create -> 0x%p", test_timeline);
+
+	test_fence_fd = goldfish_sync_fence_create(test_timeline, 1);
+	DPRINT("sync_fence_create -> %d", test_fence_fd);
+
+	DPRINT("incrementing test timeline");
+	goldfish_sync_timeline_inc(test_timeline, 1);
+
+	DPRINT("test waiting (should NOT hang)");
+	sync_fence_wait(
+			sync_fence_fdget(test_fence_fd), -1);
+
+	DPRINT("test waiting (afterward)");
+}
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 02e930c..e4839ee 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -595,7 +595,7 @@
 		goto error_ret_mut;
 	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
 	mutex_unlock(&st->lock);
-	if (ret)
+	if (ret < 0)
 		goto error_ret;
 	val = ret;
 	if (base_freq > 0)
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index bb40f37..20314ff 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -236,7 +236,7 @@
 			st->mclk = pdata->ext_clk_hz;
 		else
 			st->mclk = AD7192_INT_FREQ_MHZ;
-			break;
+		break;
 	default:
 		ret = -EINVAL;
 		goto out;
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c
index 5796ed2..39bbbaa 100644
--- a/drivers/staging/iio/adc/ad7606_core.c
+++ b/drivers/staging/iio/adc/ad7606_core.c
@@ -189,7 +189,7 @@
 	mutex_lock(&indio_dev->mlock);
 	gpio_set_value(st->pdata->gpio_os0, (ret >> 0) & 1);
 	gpio_set_value(st->pdata->gpio_os1, (ret >> 1) & 1);
-	gpio_set_value(st->pdata->gpio_os1, (ret >> 2) & 1);
+	gpio_set_value(st->pdata->gpio_os2, (ret >> 2) & 1);
 	st->oversampling = lval;
 	mutex_unlock(&indio_dev->mlock);
 
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 10c43dda..196da09 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -647,6 +647,7 @@
 	__be16 buf[2];
 	int val[2];
 	unsigned char status;
+	int ret;
 
 	mutex_lock(&indio_dev->mlock);
 	if (st->state == AD5933_CTRL_INIT_START_FREQ) {
@@ -654,19 +655,22 @@
 		ad5933_cmd(st, AD5933_CTRL_START_SWEEP);
 		st->state = AD5933_CTRL_START_SWEEP;
 		schedule_delayed_work(&st->work, st->poll_time_jiffies);
-		mutex_unlock(&indio_dev->mlock);
-		return;
+		goto out;
 	}
 
-	ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status);
+	ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status);
+	if (ret)
+		goto out;
 
 	if (status & AD5933_STAT_DATA_VALID) {
 		int scan_count = bitmap_weight(indio_dev->active_scan_mask,
 					       indio_dev->masklength);
-		ad5933_i2c_read(st->client,
+		ret = ad5933_i2c_read(st->client,
 				test_bit(1, indio_dev->active_scan_mask) ?
 				AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
 				scan_count * 2, (u8 *)buf);
+		if (ret)
+			goto out;
 
 		if (scan_count == 2) {
 			val[0] = be16_to_cpu(buf[0]);
@@ -678,8 +682,7 @@
 	} else {
 		/* no data available - try again later */
 		schedule_delayed_work(&st->work, st->poll_time_jiffies);
-		mutex_unlock(&indio_dev->mlock);
-		return;
+		goto out;
 	}
 
 	if (status & AD5933_STAT_SWEEP_DONE) {
@@ -691,7 +694,7 @@
 		ad5933_cmd(st, AD5933_CTRL_INC_FREQ);
 		schedule_delayed_work(&st->work, st->poll_time_jiffies);
 	}
-
+out:
 	mutex_unlock(&indio_dev->mlock);
 }
 
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index 9096d31..c2d9b79 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -631,8 +631,6 @@
 
 struct lov_stripe_md;
 
-extern spinlock_t inode_lock;
-
 extern struct dentry *llite_root;
 extern struct kset *llite_kset;
 
diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c
index 2fb1e97..e11b100 100644
--- a/drivers/staging/lustre/lustre/lov/lov_pack.c
+++ b/drivers/staging/lustre/lustre/lov/lov_pack.c
@@ -399,18 +399,10 @@
 	struct lov_mds_md *lmmk = NULL;
 	int rc, lmm_size;
 	int lum_size;
-	mm_segment_t seg;
 
 	if (!lsm)
 		return -ENODATA;
 
-	/*
-	 * "Switch to kernel segment" to allow copying from kernel space by
-	 * copy_{to,from}_user().
-	 */
-	seg = get_fs();
-	set_fs(KERNEL_DS);
-
 	/* we only need the header part from user space to get lmm_magic and
 	 * lmm_stripe_count, (the header part is common to v1 and v3) */
 	lum_size = sizeof(struct lov_user_md_v1);
@@ -485,6 +477,5 @@
 
 	obd_free_diskmd(exp, &lmmk);
 out_set:
-	set_fs(seg);
 	return rc;
 }
diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c
index 0922dd3..196f6b0 100644
--- a/drivers/staging/nvec/nvec_ps2.c
+++ b/drivers/staging/nvec/nvec_ps2.c
@@ -106,13 +106,12 @@
 {
 	struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
 	struct serio *ser_dev;
-	char mouse_reset[] = { NVEC_PS2, SEND_COMMAND, PSMOUSE_RST, 3 };
 
-	ser_dev = devm_kzalloc(&pdev->dev, sizeof(struct serio), GFP_KERNEL);
+	ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL);
 	if (!ser_dev)
 		return -ENOMEM;
 
-	ser_dev->id.type = SERIO_PS_PSTHRU;
+	ser_dev->id.type = SERIO_8042;
 	ser_dev->write = ps2_sendcommand;
 	ser_dev->start = ps2_startstreaming;
 	ser_dev->stop = ps2_stopstreaming;
@@ -127,9 +126,6 @@
 
 	serio_register_port(ser_dev);
 
-	/* mouse reset */
-	nvec_write_async(nvec, mouse_reset, sizeof(mouse_reset));
-
 	return 0;
 }
 
diff --git a/drivers/staging/rdma/ehca/ehca_mrmw.c b/drivers/staging/rdma/ehca/ehca_mrmw.c
index f914b30..4d52ca4 100644
--- a/drivers/staging/rdma/ehca/ehca_mrmw.c
+++ b/drivers/staging/rdma/ehca/ehca_mrmw.c
@@ -1921,7 +1921,7 @@
 				  u64 *kpage)
 {
 	int ret = 0;
-	u64 pgaddr, prev_pgaddr;
+	u64 pgaddr, prev_pgaddr = 0;
 	u32 j = 0;
 	int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE;
 	int nr_kpages = kpages_per_hwpage;
@@ -2417,6 +2417,7 @@
 		ehca_err(&shca->ib_device, "kpage alloc failed");
 		return -ENOMEM;
 	}
+	hret = H_SUCCESS;
 	for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
 		if (!ehca_bmap_valid(ehca_bmap->top[top]))
 			continue;
diff --git a/drivers/staging/rdma/ipath/ipath_file_ops.c b/drivers/staging/rdma/ipath/ipath_file_ops.c
index 13c3cd1..05d30f4 100644
--- a/drivers/staging/rdma/ipath/ipath_file_ops.c
+++ b/drivers/staging/rdma/ipath/ipath_file_ops.c
@@ -45,6 +45,8 @@
 #include <linux/uio.h>
 #include <asm/pgtable.h>
 
+#include <rdma/ib.h>
+
 #include "ipath_kernel.h"
 #include "ipath_common.h"
 #include "ipath_user_sdma.h"
@@ -2243,6 +2245,9 @@
 	ssize_t ret = 0;
 	void *dest;
 
+	if (WARN_ON_ONCE(!ib_safe_file_access(fp)))
+		return -EACCES;
+
 	if (count < sizeof(cmd.type)) {
 		ret = -EINVAL;
 		goto bail;
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 3cdb40f..f5cedbb 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -894,7 +894,7 @@
 		return _FAIL;
 
 
-	if (len > MAX_IE_SZ)
+	if (len < 0 || len > MAX_IE_SZ)
 		return _FAIL;
 
 	pbss_network->IELength = len;
diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c
index 9b7026e..45d0a87 100644
--- a/drivers/staging/rtl8188eu/core/rtw_cmd.c
+++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c
@@ -718,13 +718,13 @@
 	u8	res = _SUCCESS;
 
 
-	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 	if (ph2c == NULL) {
 		res = _FAIL;
 		goto exit;
 	}
 
-	paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_KERNEL);
+	paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC);
 	if (paddbareq_parm == NULL) {
 		kfree(ph2c);
 		res = _FAIL;
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index 110b8c0..0f2fe34 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -1405,6 +1405,9 @@
 		ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
 	}
 
+	if (!ptr)
+		return _FAIL;
+
 	memcpy(ptr, pattrib->dst, ETH_ALEN);
 	memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
 
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index e9c4f97..7a8ceb9 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -97,8 +97,9 @@
 
 	switch (variable) {
 	case HW_VAR_BSSID:
-		rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]);
-		rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]);
+		/* BSSIDR 2 byte alignment */
+		rtl92e_writew(dev, BSSIDR, *(u16 *)val);
+		rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(val + 2));
 		break;
 
 	case HW_VAR_MEDIA_STATUS:
@@ -626,7 +627,7 @@
 	struct r8192_priv *priv = rtllib_priv(dev);
 
 	RT_TRACE(COMP_INIT, "===========>%s()\n", __func__);
-	curCR = rtl92e_readl(dev, EPROM_CMD);
+	curCR = rtl92e_readw(dev, EPROM_CMD);
 	RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD,
 		 curCR);
 	priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 :
@@ -963,8 +964,8 @@
 	rtl92e_config_rate(dev, &rate_config);
 	priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
 	 priv->basic_rate = rate_config &= 0x15f;
-	rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]);
-	rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
+	rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid);
+	rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2));
 
 	if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
 		rtl92e_writew(dev, ATIMWND, 2);
@@ -1184,8 +1185,7 @@
 			  struct cb_desc *cb_desc, struct sk_buff *skb)
 {
 	struct r8192_priv *priv = rtllib_priv(dev);
-	dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
-			 PCI_DMA_TODEVICE);
+	dma_addr_t mapping;
 	struct tx_fwinfo_8190pci *pTxFwInfo = NULL;
 
 	pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data;
@@ -1196,8 +1196,6 @@
 	pTxFwInfo->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT,
 						  pTxFwInfo->TxRate, cb_desc);
 
-	if (pci_dma_mapping_error(priv->pdev, mapping))
-		netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
 	if (cb_desc->bAMPDUEnable) {
 		pTxFwInfo->AllowAggregation = 1;
 		pTxFwInfo->RxMF = cb_desc->ampdu_factor;
@@ -1232,6 +1230,14 @@
 	}
 
 	memset((u8 *)pdesc, 0, 12);
+
+	mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+				 PCI_DMA_TODEVICE);
+	if (pci_dma_mapping_error(priv->pdev, mapping)) {
+		netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
+		return;
+	}
+
 	pdesc->LINIP = 0;
 	pdesc->CmdInit = 1;
 	pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8;
diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c
index 4ff5301..04ac23c 100644
--- a/drivers/staging/rtl8712/rtl871x_recv.c
+++ b/drivers/staging/rtl8712/rtl871x_recv.c
@@ -641,11 +641,16 @@
 		/* append rx status for mp test packets */
 		ptr = recvframe_pull(precvframe, (rmv_len -
 		      sizeof(struct ethhdr) + 2) - 24);
+		if (!ptr)
+			return _FAIL;
 		memcpy(ptr, get_rxmem(precvframe), 24);
 		ptr += 24;
-	} else
+	} else {
 		ptr = recvframe_pull(precvframe, (rmv_len -
 		      sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
+		if (!ptr)
+			return _FAIL;
+	}
 
 	memcpy(ptr, pattrib->dst, ETH_ALEN);
 	memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 01e642d..f35ee85 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -529,6 +529,9 @@
 		goto free_all;
 	}
 
+	if (vnt_key_init_table(priv))
+		goto free_all;
+
 	priv->int_interval = 1;  /* bInterval is set to 1 */
 
 	vnt_int_start_interrupt(priv);
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index c975c3b..cfc3017 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -50,15 +50,25 @@
 		u16 index, u16 length, u8 *buffer)
 {
 	int status = 0;
+	u8 *usb_buffer;
 
 	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
 		return STATUS_FAILURE;
 
 	mutex_lock(&priv->usb_lock);
 
+	usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
+	if (!usb_buffer) {
+		mutex_unlock(&priv->usb_lock);
+		return -ENOMEM;
+	}
+
 	status = usb_control_msg(priv->usb,
-		usb_sndctrlpipe(priv->usb, 0), request, 0x40, value,
-			index, buffer, length, USB_CTL_WAIT);
+				 usb_sndctrlpipe(priv->usb, 0),
+				 request, 0x40, value,
+				 index, usb_buffer, length, USB_CTL_WAIT);
+
+	kfree(usb_buffer);
 
 	mutex_unlock(&priv->usb_lock);
 
@@ -78,15 +88,28 @@
 		u16 index, u16 length, u8 *buffer)
 {
 	int status;
+	u8 *usb_buffer;
 
 	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
 		return STATUS_FAILURE;
 
 	mutex_lock(&priv->usb_lock);
 
+	usb_buffer = kmalloc(length, GFP_KERNEL);
+	if (!usb_buffer) {
+		mutex_unlock(&priv->usb_lock);
+		return -ENOMEM;
+	}
+
 	status = usb_control_msg(priv->usb,
-		usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value,
-			index, buffer, length, USB_CTL_WAIT);
+				 usb_rcvctrlpipe(priv->usb, 0),
+				 request, 0xc0, value,
+				 index, usb_buffer, length, USB_CTL_WAIT);
+
+	if (status == length)
+		memcpy(buffer, usb_buffer, length);
+
+	kfree(usb_buffer);
 
 	mutex_unlock(&priv->usb_lock);
 
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
index a9c1e0b..e35fbec 100644
--- a/drivers/staging/wlan-ng/p80211netdev.c
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -232,7 +232,7 @@
 	struct p80211_hdr_a3 *hdr;
 
 	hdr = (struct p80211_hdr_a3 *) skb->data;
-	if (p80211_rx_typedrop(wlandev, hdr->fc))
+	if (p80211_rx_typedrop(wlandev, le16_to_cpu(hdr->fc)))
 		return CONV_TO_ETHER_SKIPPED;
 
 	/* perform mcast filtering: allow my local address through but reject
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 72204fb..a180c00 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -492,7 +492,8 @@
 	bool scsi_cmd = (cmd->iscsi_opcode == ISCSI_OP_SCSI_CMD);
 
 	spin_lock_bh(&conn->cmd_lock);
-	if (!list_empty(&cmd->i_conn_node))
+	if (!list_empty(&cmd->i_conn_node) &&
+	    !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP))
 		list_del_init(&cmd->i_conn_node);
 	spin_unlock_bh(&conn->cmd_lock);
 
@@ -1111,6 +1112,18 @@
 	 */
 	if (dump_payload)
 		goto after_immediate_data;
+	/*
+	 * Check for underflow case where both EDTL and immediate data payload
+	 * exceeds what is presented by CDB's TRANSFER LENGTH, and what has
+	 * already been set in target_cmd_size_check() as se_cmd->data_length.
+	 *
+	 * For this special case, fail the command and dump the immediate data
+	 * payload.
+	 */
+	if (cmd->first_burst_len > cmd->se_cmd.data_length) {
+		cmd->sense_reason = TCM_INVALID_CDB_FIELD;
+		goto after_immediate_data;
+	}
 
 	immed_ret = iscsit_handle_immediate_data(cmd, hdr,
 					cmd->first_burst_len);
@@ -3435,7 +3448,7 @@
 
 			if ((tpg->tpg_attrib.generate_node_acls == 0) &&
 			    (tpg->tpg_attrib.demo_mode_discovery == 0) &&
-			    (!core_tpg_get_initiator_node_acl(&tpg->tpg_se_tpg,
+			    (!target_tpg_has_node_acl(&tpg->tpg_se_tpg,
 				cmd->conn->sess->sess_ops->InitiatorName))) {
 				continue;
 			}
@@ -4194,6 +4207,7 @@
 
 static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
 {
+	LIST_HEAD(tmp_list);
 	struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
 	struct iscsi_session *sess = conn->sess;
 	/*
@@ -4202,18 +4216,26 @@
 	 * has been reset -> returned sleeping pre-handler state.
 	 */
 	spin_lock_bh(&conn->cmd_lock);
-	list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
+	list_splice_init(&conn->conn_cmd_list, &tmp_list);
 
-		list_del_init(&cmd->i_conn_node);
-		spin_unlock_bh(&conn->cmd_lock);
+	list_for_each_entry(cmd, &tmp_list, i_conn_node) {
+		struct se_cmd *se_cmd = &cmd->se_cmd;
 
-		iscsit_increment_maxcmdsn(cmd, sess);
-
-		iscsit_free_cmd(cmd, true);
-
-		spin_lock_bh(&conn->cmd_lock);
+		if (se_cmd->se_tfo != NULL) {
+			spin_lock(&se_cmd->t_state_lock);
+			se_cmd->transport_state |= CMD_T_FABRIC_STOP;
+			spin_unlock(&se_cmd->t_state_lock);
+		}
 	}
 	spin_unlock_bh(&conn->cmd_lock);
+
+	list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
+		list_del_init(&cmd->i_conn_node);
+
+		iscsit_increment_maxcmdsn(cmd, sess);
+		iscsit_free_cmd(cmd, true);
+
+	}
 }
 
 static void iscsit_stop_timers_for_cmds(
@@ -4811,6 +4833,7 @@
 			continue;
 		}
 		atomic_set(&sess->session_reinstatement, 1);
+		atomic_set(&sess->session_fall_back_to_erl0, 1);
 		spin_unlock(&sess->conn_lock);
 
 		list_move_tail(&se_sess->sess_list, &free_list);
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index b4bfd70..dc1bd1f 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -725,11 +725,8 @@
 
 	if (iscsit_get_tpg(tpg) < 0)
 		return -EINVAL;
-	/*
-	 * iscsit_tpg_set_initiator_node_queue_depth() assumes force=1
-	 */
-	ret = iscsit_tpg_set_initiator_node_queue_depth(tpg,
-				config_item_name(acl_ci), cmdsn_depth, 1);
+
+	ret = core_tpg_set_initiator_node_queue_depth(se_nacl, cmdsn_depth);
 
 	pr_debug("LIO_Target_ConfigFS: %s/%s Set CmdSN Window: %u for"
 		"InitiatorName: %s\n", config_item_name(wwn_ci),
@@ -1593,42 +1590,31 @@
 }
 
 /*
- * Called with spin_lock_irq(struct se_portal_group->session_lock) held
- * or not held.
- *
- * Also, this function calls iscsit_inc_session_usage_count() on the
+ * This function calls iscsit_inc_session_usage_count() on the
  * struct iscsi_session in question.
  */
 static int lio_tpg_shutdown_session(struct se_session *se_sess)
 {
 	struct iscsi_session *sess = se_sess->fabric_sess_ptr;
-	struct se_portal_group *se_tpg = se_sess->se_tpg;
-	bool local_lock = false;
+	struct se_portal_group *se_tpg = &sess->tpg->tpg_se_tpg;
 
-	if (!spin_is_locked(&se_tpg->session_lock)) {
-		spin_lock_irq(&se_tpg->session_lock);
-		local_lock = true;
-	}
-
+	spin_lock_bh(&se_tpg->session_lock);
 	spin_lock(&sess->conn_lock);
 	if (atomic_read(&sess->session_fall_back_to_erl0) ||
 	    atomic_read(&sess->session_logout) ||
 	    (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
 		spin_unlock(&sess->conn_lock);
-		if (local_lock)
-			spin_unlock_irq(&sess->conn_lock);
+		spin_unlock_bh(&se_tpg->session_lock);
 		return 0;
 	}
 	atomic_set(&sess->session_reinstatement, 1);
+	atomic_set(&sess->session_fall_back_to_erl0, 1);
 	spin_unlock(&sess->conn_lock);
 
 	iscsit_stop_time2retain_timer(sess);
-	spin_unlock_irq(&se_tpg->session_lock);
+	spin_unlock_bh(&se_tpg->session_lock);
 
 	iscsit_stop_session(sess, 1, 1);
-	if (!local_lock)
-		spin_lock_irq(&se_tpg->session_lock);
-
 	return 1;
 }
 
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 96e78c8..4a137b0 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -195,6 +195,7 @@
 			    initiatorname_param->value) &&
 		   (sess_p->sess_ops->SessionType == sessiontype))) {
 			atomic_set(&sess_p->session_reinstatement, 1);
+			atomic_set(&sess_p->session_fall_back_to_erl0, 1);
 			spin_unlock(&sess_p->conn_lock);
 			iscsit_inc_session_usage_count(sess_p);
 			iscsit_stop_time2retain_timer(sess_p);
@@ -1357,8 +1358,9 @@
 	}
 	login->zero_tsih = zero_tsih;
 
-	conn->sess->se_sess->sup_prot_ops =
-		conn->conn_transport->iscsit_get_sup_prot_ops(conn);
+	if (conn->sess)
+		conn->sess->se_sess->sup_prot_ops =
+			conn->conn_transport->iscsit_get_sup_prot_ops(conn);
 
 	tpg = conn->tpg;
 	if (!tpg) {
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 2cbea2a..6d1b0ac 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -781,22 +781,6 @@
 		if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH))
 			SET_PSTATE_REPLY_OPTIONAL(param);
 		/*
-		 * The GlobalSAN iSCSI Initiator for MacOSX does
-		 * not respond to MaxBurstLength, FirstBurstLength,
-		 * DefaultTime2Wait or DefaultTime2Retain parameter keys.
-		 * So, we set them to 'reply optional' here, and assume the
-		 * the defaults from iscsi_parameters.h if the initiator
-		 * is not RFC compliant and the keys are not negotiated.
-		 */
-		if (!strcmp(param->name, MAXBURSTLENGTH))
-			SET_PSTATE_REPLY_OPTIONAL(param);
-		if (!strcmp(param->name, FIRSTBURSTLENGTH))
-			SET_PSTATE_REPLY_OPTIONAL(param);
-		if (!strcmp(param->name, DEFAULTTIME2WAIT))
-			SET_PSTATE_REPLY_OPTIONAL(param);
-		if (!strcmp(param->name, DEFAULTTIME2RETAIN))
-			SET_PSTATE_REPLY_OPTIONAL(param);
-		/*
 		 * Required for gPXE iSCSI boot client
 		 */
 		if (!strcmp(param->name, MAXCONNECTIONS))
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index 23c95cd..205a509 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -260,7 +260,6 @@
 		iscsi_release_param_list(tpg->param_list);
 		tpg->param_list = NULL;
 	}
-	kfree(tpg);
 	return -ENOMEM;
 }
 
@@ -590,16 +589,6 @@
 	return iscsit_tpg_release_np(tpg_np, tpg, np);
 }
 
-int iscsit_tpg_set_initiator_node_queue_depth(
-	struct iscsi_portal_group *tpg,
-	unsigned char *initiatorname,
-	u32 queue_depth,
-	int force)
-{
-	return core_tpg_set_initiator_node_queue_depth(&tpg->tpg_se_tpg,
-		initiatorname, queue_depth, force);
-}
-
 int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication)
 {
 	unsigned char buf1[256], buf2[256], *none = NULL;
diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h
index 9db32bd..2da2119 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.h
+++ b/drivers/target/iscsi/iscsi_target_tpg.h
@@ -26,8 +26,6 @@
 			int);
 extern int iscsit_tpg_del_network_portal(struct iscsi_portal_group *,
 			struct iscsi_tpg_np *);
-extern int iscsit_tpg_set_initiator_node_queue_depth(struct iscsi_portal_group *,
-			unsigned char *, u32, int);
 extern int iscsit_ta_authentication(struct iscsi_portal_group *, u32);
 extern int iscsit_ta_login_timeout(struct iscsi_portal_group *, u32);
 extern int iscsit_ta_netif_timeout(struct iscsi_portal_group *, u32);
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 428b0d9..9359052 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -731,21 +731,23 @@
 {
 	struct se_cmd *se_cmd = NULL;
 	int rc;
+	bool op_scsi = false;
 	/*
 	 * Determine if a struct se_cmd is associated with
 	 * this struct iscsi_cmd.
 	 */
 	switch (cmd->iscsi_opcode) {
 	case ISCSI_OP_SCSI_CMD:
-		se_cmd = &cmd->se_cmd;
-		__iscsit_free_cmd(cmd, true, shutdown);
+		op_scsi = true;
 		/*
 		 * Fallthrough
 		 */
 	case ISCSI_OP_SCSI_TMFUNC:
-		rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
-		if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
-			__iscsit_free_cmd(cmd, true, shutdown);
+		se_cmd = &cmd->se_cmd;
+		__iscsit_free_cmd(cmd, op_scsi, shutdown);
+		rc = transport_generic_free_cmd(se_cmd, shutdown);
+		if (!rc && shutdown && se_cmd->se_sess) {
+			__iscsit_free_cmd(cmd, op_scsi, shutdown);
 			target_put_sess_cmd(se_cmd);
 		}
 		break;
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 3436a83..bb6a6c3 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -77,12 +77,16 @@
 					&deve->read_bytes);
 
 		se_lun = rcu_dereference(deve->se_lun);
+
+		if (!percpu_ref_tryget_live(&se_lun->lun_ref)) {
+			se_lun = NULL;
+			goto out_unlock;
+		}
+
 		se_cmd->se_lun = rcu_dereference(deve->se_lun);
 		se_cmd->pr_res_key = deve->pr_res_key;
 		se_cmd->orig_fe_lun = unpacked_lun;
 		se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
-
-		percpu_ref_get(&se_lun->lun_ref);
 		se_cmd->lun_ref_active = true;
 
 		if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
@@ -96,6 +100,7 @@
 			goto ref_dev;
 		}
 	}
+out_unlock:
 	rcu_read_unlock();
 
 	if (!se_lun) {
@@ -362,7 +367,15 @@
 			kfree(new);
 			return -EINVAL;
 		}
-		BUG_ON(orig->se_lun_acl != NULL);
+		if (orig->se_lun_acl != NULL) {
+			pr_warn_ratelimited("Detected existing explicit"
+				" se_lun_acl->se_lun_group reference for %s"
+				" mapped_lun: %llu, failing\n",
+				 nacl->initiatorname, mapped_lun);
+			mutex_unlock(&nacl->lun_entry_mutex);
+			kfree(new);
+			return -EINVAL;
+		}
 
 		rcu_assign_pointer(new->se_lun, lun);
 		rcu_assign_pointer(new->se_lun_acl, lun_acl);
@@ -818,6 +831,7 @@
 	xcopy_lun = &dev->xcopy_lun;
 	rcu_assign_pointer(xcopy_lun->lun_se_dev, dev);
 	init_completion(&xcopy_lun->lun_ref_comp);
+	init_completion(&xcopy_lun->lun_shutdown_comp);
 	INIT_LIST_HEAD(&xcopy_lun->lun_deve_list);
 	INIT_LIST_HEAD(&xcopy_lun->lun_dev_link);
 	mutex_init(&xcopy_lun->lun_tg_pt_md_mutex);
@@ -832,13 +846,15 @@
  * in ATA and we need to set TPE=1
  */
 bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
-				       struct request_queue *q, int block_size)
+				       struct request_queue *q)
 {
+	int block_size = queue_logical_block_size(q);
+
 	if (!blk_queue_discard(q))
 		return false;
 
-	attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) /
-								block_size;
+	attrib->max_unmap_lba_count =
+		q->limits.max_discard_sectors >> (ilog2(block_size) - 9);
 	/*
 	 * Currently hardcoded to 1 in Linux/SCSI code..
 	 */
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 75f0f08..041a569 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -161,8 +161,7 @@
 			dev_size, div_u64(dev_size, fd_dev->fd_block_size),
 			fd_dev->fd_block_size);
 
-		if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
-						      fd_dev->fd_block_size))
+		if (target_configure_unmap_from_queue(&dev->dev_attrib, q))
 			pr_debug("IFILE: BLOCK Discard support available,"
 				 " disabled by default\n");
 		/*
@@ -595,8 +594,7 @@
 	if (ret < 0)
 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	if (ret)
-		target_complete_cmd(cmd, SAM_STAT_GOOD);
+	target_complete_cmd(cmd, SAM_STAT_GOOD);
 	return 0;
 }
 
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 2c53dce..4620c1d 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -121,8 +121,7 @@
 	dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q);
 	dev->dev_attrib.hw_queue_depth = q->nr_requests;
 
-	if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
-					      dev->dev_attrib.hw_block_size))
+	if (target_configure_unmap_from_queue(&dev->dev_attrib, q))
 		pr_debug("IBLOCK: BLOCK Discard support available,"
 			 " disabled by default\n");
 
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index dae0750c..272e6f7 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -132,7 +132,7 @@
 void	release_se_kmem_caches(void);
 u32	scsi_get_new_index(scsi_index_t);
 void	transport_subsystem_check_init(void);
-void	transport_cmd_finish_abort(struct se_cmd *, int);
+int	transport_cmd_finish_abort(struct se_cmd *, int);
 unsigned char *transport_dump_cmd_direction(struct se_cmd *);
 void	transport_dump_dev_state(struct se_device *, char *, int *);
 void	transport_dump_dev_info(struct se_device *, struct se_lun *,
@@ -148,6 +148,7 @@
 void	target_qf_do_work(struct work_struct *work);
 bool	target_check_wce(struct se_device *dev);
 bool	target_check_fua(struct se_device *dev);
+void	__target_execute_cmd(struct se_cmd *, bool);
 
 /* target_core_stat.c */
 void	target_stat_setup_dev_default_groups(struct se_device *);
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index de18790..d72a405 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -154,7 +154,7 @@
 
 	buf = kzalloc(12, GFP_KERNEL);
 	if (!buf)
-		return;
+		goto out_free;
 
 	memset(cdb, 0, MAX_COMMAND_SIZE);
 	cdb[0] = MODE_SENSE;
@@ -169,9 +169,10 @@
 	 * If MODE_SENSE still returns zero, set the default value to 1024.
 	 */
 	sdev->sector_size = (buf[9] << 16) | (buf[10] << 8) | (buf[11]);
+out_free:
 	if (!sdev->sector_size)
 		sdev->sector_size = 1024;
-out_free:
+
 	kfree(buf);
 }
 
@@ -314,9 +315,10 @@
 				sd->lun, sd->queue_depth);
 	}
 
-	dev->dev_attrib.hw_block_size = sd->sector_size;
+	dev->dev_attrib.hw_block_size =
+		min_not_zero((int)sd->sector_size, 512);
 	dev->dev_attrib.hw_max_sectors =
-		min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q));
+		min_not_zero(sd->host->max_sectors, queue_max_hw_sectors(q));
 	dev->dev_attrib.hw_queue_depth = sd->queue_depth;
 
 	/*
@@ -339,8 +341,10 @@
 	/*
 	 * For TYPE_TAPE, attempt to determine blocksize with MODE_SENSE.
 	 */
-	if (sd->type == TYPE_TAPE)
+	if (sd->type == TYPE_TAPE) {
 		pscsi_tape_read_blocksize(dev, sd);
+		dev->dev_attrib.hw_block_size = sd->sector_size;
+	}
 	return 0;
 }
 
@@ -406,7 +410,7 @@
 /*
  * Called with struct Scsi_Host->host_lock called.
  */
-static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd)
+static int pscsi_create_type_nondisk(struct se_device *dev, struct scsi_device *sd)
 	__releases(sh->host_lock)
 {
 	struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
@@ -433,28 +437,6 @@
 	return 0;
 }
 
-/*
- * Called with struct Scsi_Host->host_lock called.
- */
-static int pscsi_create_type_other(struct se_device *dev,
-		struct scsi_device *sd)
-	__releases(sh->host_lock)
-{
-	struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
-	struct Scsi_Host *sh = sd->host;
-	int ret;
-
-	spin_unlock_irq(sh->host_lock);
-	ret = pscsi_add_device_to_list(dev, sd);
-	if (ret)
-		return ret;
-
-	pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%llu\n",
-		phv->phv_host_id, scsi_device_type(sd->type), sh->host_no,
-		sd->channel, sd->id, sd->lun);
-	return 0;
-}
-
 static int pscsi_configure_device(struct se_device *dev)
 {
 	struct se_hba *hba = dev->se_hba;
@@ -542,11 +524,8 @@
 		case TYPE_DISK:
 			ret = pscsi_create_type_disk(dev, sd);
 			break;
-		case TYPE_ROM:
-			ret = pscsi_create_type_rom(dev, sd);
-			break;
 		default:
-			ret = pscsi_create_type_other(dev, sd);
+			ret = pscsi_create_type_nondisk(dev, sd);
 			break;
 		}
 
@@ -611,8 +590,7 @@
 		else if (pdv->pdv_lld_host)
 			scsi_host_put(pdv->pdv_lld_host);
 
-		if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM))
-			scsi_device_put(sd);
+		scsi_device_put(sd);
 
 		pdv->pdv_sd = NULL;
 	}
@@ -1088,7 +1066,6 @@
 	if (pdv->pdv_bd && pdv->pdv_bd->bd_part)
 		return pdv->pdv_bd->bd_part->nr_sects;
 
-	dump_stack();
 	return 0;
 }
 
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 98698d8..6081178 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -442,6 +442,7 @@
 					     int *post_ret)
 {
 	struct se_device *dev = cmd->se_dev;
+	sense_reason_t ret = TCM_NO_SENSE;
 
 	/*
 	 * Only set SCF_COMPARE_AND_WRITE_POST to force a response fall-through
@@ -449,9 +450,12 @@
 	 * sent to the backend driver.
 	 */
 	spin_lock_irq(&cmd->t_state_lock);
-	if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status) {
+	if (cmd->transport_state & CMD_T_SENT) {
 		cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
 		*post_ret = 1;
+
+		if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	spin_unlock_irq(&cmd->t_state_lock);
 
@@ -461,7 +465,7 @@
 	 */
 	up(&dev->caw_sem);
 
-	return TCM_NO_SENSE;
+	return ret;
 }
 
 static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success,
@@ -494,8 +498,11 @@
 	 * been failed with a non-zero SCSI status.
 	 */
 	if (cmd->scsi_status) {
-		pr_err("compare_and_write_callback: non zero scsi_status:"
+		pr_debug("compare_and_write_callback: non zero scsi_status:"
 			" 0x%02x\n", cmd->scsi_status);
+		*post_ret = 1;
+		if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		goto out;
 	}
 
@@ -594,7 +601,7 @@
 	cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
 	spin_unlock_irq(&cmd->t_state_lock);
 
-	__target_execute_cmd(cmd);
+	__target_execute_cmd(cmd, false);
 
 	kfree(buf);
 	return ret;
@@ -1092,9 +1099,15 @@
 			return ret;
 		break;
 	case VERIFY:
+	case VERIFY_16:
 		size = 0;
-		sectors = transport_get_sectors_10(cdb);
-		cmd->t_task_lba = transport_lba_32(cdb);
+		if (cdb[0] == VERIFY) {
+			sectors = transport_get_sectors_10(cdb);
+			cmd->t_task_lba = transport_lba_32(cdb);
+		} else {
+			sectors = transport_get_sectors_16(cdb);
+			cmd->t_task_lba = transport_lba_64(cdb);
+		}
 		cmd->execute_cmd = sbc_emulate_noop;
 		goto check_lba;
 	case REZERO_UNIT:
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index 46b1991..c9be953 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -75,7 +75,7 @@
 	kfree(tmr);
 }
 
-static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
+static int core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
 {
 	unsigned long flags;
 	bool remove = true, send_tas;
@@ -91,7 +91,7 @@
 		transport_send_task_abort(cmd);
 	}
 
-	transport_cmd_finish_abort(cmd, remove);
+	return transport_cmd_finish_abort(cmd, remove);
 }
 
 static int target_check_cdb_and_preempt(struct list_head *list,
@@ -185,8 +185,8 @@
 		cancel_work_sync(&se_cmd->work);
 		transport_wait_for_tasks(se_cmd);
 
-		transport_cmd_finish_abort(se_cmd, true);
-		target_put_sess_cmd(se_cmd);
+		if (!transport_cmd_finish_abort(se_cmd, true))
+			target_put_sess_cmd(se_cmd);
 
 		printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
 				" ref_tag: %llu\n", ref_tag);
@@ -286,8 +286,8 @@
 		cancel_work_sync(&cmd->work);
 		transport_wait_for_tasks(cmd);
 
-		transport_cmd_finish_abort(cmd, 1);
-		target_put_sess_cmd(cmd);
+		if (!transport_cmd_finish_abort(cmd, 1))
+			target_put_sess_cmd(cmd);
 	}
 }
 
@@ -385,8 +385,8 @@
 		cancel_work_sync(&cmd->work);
 		transport_wait_for_tasks(cmd);
 
-		core_tmr_handle_tas_abort(cmd, tas);
-		target_put_sess_cmd(cmd);
+		if (!core_tmr_handle_tas_abort(cmd, tas))
+			target_put_sess_cmd(cmd);
 	}
 }
 
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index 5fb9dd7..899c33b 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -75,9 +75,21 @@
 	unsigned char *initiatorname)
 {
 	struct se_node_acl *acl;
-
+	/*
+	 * Obtain se_node_acl->acl_kref using fabric driver provided
+	 * initiatorname[] during node acl endpoint lookup driven by
+	 * new se_session login.
+	 *
+	 * The reference is held until se_session shutdown -> release
+	 * occurs via fabric driver invoked transport_deregister_session()
+	 * or transport_free_session() code.
+	 */
 	mutex_lock(&tpg->acl_node_mutex);
 	acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
+	if (acl) {
+		if (!kref_get_unless_zero(&acl->acl_kref))
+			acl = NULL;
+	}
 	mutex_unlock(&tpg->acl_node_mutex);
 
 	return acl;
@@ -157,28 +169,25 @@
 	mutex_unlock(&tpg->tpg_lun_mutex);
 }
 
-/*      core_set_queue_depth_for_node():
- *
- *
- */
-static int core_set_queue_depth_for_node(
-	struct se_portal_group *tpg,
-	struct se_node_acl *acl)
+static void
+target_set_nacl_queue_depth(struct se_portal_group *tpg,
+			    struct se_node_acl *acl, u32 queue_depth)
 {
+	acl->queue_depth = queue_depth;
+
 	if (!acl->queue_depth) {
-		pr_err("Queue depth for %s Initiator Node: %s is 0,"
+		pr_warn("Queue depth for %s Initiator Node: %s is 0,"
 			"defaulting to 1.\n", tpg->se_tpg_tfo->get_fabric_name(),
 			acl->initiatorname);
 		acl->queue_depth = 1;
 	}
-
-	return 0;
 }
 
 static struct se_node_acl *target_alloc_node_acl(struct se_portal_group *tpg,
 		const unsigned char *initiatorname)
 {
 	struct se_node_acl *acl;
+	u32 queue_depth;
 
 	acl = kzalloc(max(sizeof(*acl), tpg->se_tpg_tfo->node_acl_size),
 			GFP_KERNEL);
@@ -193,24 +202,20 @@
 	spin_lock_init(&acl->nacl_sess_lock);
 	mutex_init(&acl->lun_entry_mutex);
 	atomic_set(&acl->acl_pr_ref_count, 0);
+
 	if (tpg->se_tpg_tfo->tpg_get_default_depth)
-		acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
+		queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
 	else
-		acl->queue_depth = 1;
+		queue_depth = 1;
+	target_set_nacl_queue_depth(tpg, acl, queue_depth);
+
 	snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
 	acl->se_tpg = tpg;
 	acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
 
 	tpg->se_tpg_tfo->set_default_node_attributes(acl);
 
-	if (core_set_queue_depth_for_node(tpg, acl) < 0)
-		goto out_free_acl;
-
 	return acl;
-
-out_free_acl:
-	kfree(acl);
-	return NULL;
 }
 
 static void target_add_node_acl(struct se_node_acl *acl)
@@ -232,6 +237,25 @@
 		acl->initiatorname);
 }
 
+bool target_tpg_has_node_acl(struct se_portal_group *tpg,
+			     const char *initiatorname)
+{
+	struct se_node_acl *acl;
+	bool found = false;
+
+	mutex_lock(&tpg->acl_node_mutex);
+	list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
+		if (!strcmp(acl->initiatorname, initiatorname)) {
+			found = true;
+			break;
+		}
+	}
+	mutex_unlock(&tpg->acl_node_mutex);
+
+	return found;
+}
+EXPORT_SYMBOL(target_tpg_has_node_acl);
+
 struct se_node_acl *core_tpg_check_initiator_node_acl(
 	struct se_portal_group *tpg,
 	unsigned char *initiatorname)
@@ -248,6 +272,15 @@
 	acl = target_alloc_node_acl(tpg, initiatorname);
 	if (!acl)
 		return NULL;
+	/*
+	 * When allocating a dynamically generated node_acl, go ahead
+	 * and take the extra kref now before returning to the fabric
+	 * driver caller.
+	 *
+	 * Note this reference will be released at session shutdown
+	 * time within transport_free_session() code.
+	 */
+	kref_get(&acl->acl_kref);
 	acl->dynamic_node_acl = 1;
 
 	/*
@@ -329,7 +362,8 @@
 		if (sess->sess_tearing_down != 0)
 			continue;
 
-		target_get_session(sess);
+		if (!target_get_session(sess))
+			continue;
 		list_move(&sess->sess_acl_list, &sess_list);
 	}
 	spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
@@ -366,108 +400,52 @@
  *
  */
 int core_tpg_set_initiator_node_queue_depth(
-	struct se_portal_group *tpg,
-	unsigned char *initiatorname,
-	u32 queue_depth,
-	int force)
+	struct se_node_acl *acl,
+	u32 queue_depth)
 {
-	struct se_session *sess, *init_sess = NULL;
-	struct se_node_acl *acl;
+	LIST_HEAD(sess_list);
+	struct se_portal_group *tpg = acl->se_tpg;
+	struct se_session *sess, *sess_tmp;
 	unsigned long flags;
-	int dynamic_acl = 0;
-
-	mutex_lock(&tpg->acl_node_mutex);
-	acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
-	if (!acl) {
-		pr_err("Access Control List entry for %s Initiator"
-			" Node %s does not exists for TPG %hu, ignoring"
-			" request.\n", tpg->se_tpg_tfo->get_fabric_name(),
-			initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
-		mutex_unlock(&tpg->acl_node_mutex);
-		return -ENODEV;
-	}
-	if (acl->dynamic_node_acl) {
-		acl->dynamic_node_acl = 0;
-		dynamic_acl = 1;
-	}
-	mutex_unlock(&tpg->acl_node_mutex);
-
-	spin_lock_irqsave(&tpg->session_lock, flags);
-	list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) {
-		if (sess->se_node_acl != acl)
-			continue;
-
-		if (!force) {
-			pr_err("Unable to change queue depth for %s"
-				" Initiator Node: %s while session is"
-				" operational.  To forcefully change the queue"
-				" depth and force session reinstatement"
-				" use the \"force=1\" parameter.\n",
-				tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
-			spin_unlock_irqrestore(&tpg->session_lock, flags);
-
-			mutex_lock(&tpg->acl_node_mutex);
-			if (dynamic_acl)
-				acl->dynamic_node_acl = 1;
-			mutex_unlock(&tpg->acl_node_mutex);
-			return -EEXIST;
-		}
-		/*
-		 * Determine if the session needs to be closed by our context.
-		 */
-		if (!tpg->se_tpg_tfo->shutdown_session(sess))
-			continue;
-
-		init_sess = sess;
-		break;
-	}
+	int rc;
 
 	/*
 	 * User has requested to change the queue depth for a Initiator Node.
 	 * Change the value in the Node's struct se_node_acl, and call
-	 * core_set_queue_depth_for_node() to add the requested queue depth.
-	 *
-	 * Finally call  tpg->se_tpg_tfo->close_session() to force session
-	 * reinstatement to occur if there is an active session for the
-	 * $FABRIC_MOD Initiator Node in question.
+	 * target_set_nacl_queue_depth() to set the new queue depth.
 	 */
-	acl->queue_depth = queue_depth;
+	target_set_nacl_queue_depth(tpg, acl, queue_depth);
 
-	if (core_set_queue_depth_for_node(tpg, acl) < 0) {
-		spin_unlock_irqrestore(&tpg->session_lock, flags);
+	spin_lock_irqsave(&acl->nacl_sess_lock, flags);
+	list_for_each_entry_safe(sess, sess_tmp, &acl->acl_sess_list,
+				 sess_acl_list) {
+		if (sess->sess_tearing_down != 0)
+			continue;
+		if (!target_get_session(sess))
+			continue;
+		spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
+
 		/*
-		 * Force session reinstatement if
-		 * core_set_queue_depth_for_node() failed, because we assume
-		 * the $FABRIC_MOD has already the set session reinstatement
-		 * bit from tpg->se_tpg_tfo->shutdown_session() called above.
+		 * Finally call tpg->se_tpg_tfo->close_session() to force session
+		 * reinstatement to occur if there is an active session for the
+		 * $FABRIC_MOD Initiator Node in question.
 		 */
-		if (init_sess)
-			tpg->se_tpg_tfo->close_session(init_sess);
-
-		mutex_lock(&tpg->acl_node_mutex);
-		if (dynamic_acl)
-			acl->dynamic_node_acl = 1;
-		mutex_unlock(&tpg->acl_node_mutex);
-		return -EINVAL;
+		rc = tpg->se_tpg_tfo->shutdown_session(sess);
+		target_put_session(sess);
+		if (!rc) {
+			spin_lock_irqsave(&acl->nacl_sess_lock, flags);
+			continue;
+		}
+		target_put_session(sess);
+		spin_lock_irqsave(&acl->nacl_sess_lock, flags);
 	}
-	spin_unlock_irqrestore(&tpg->session_lock, flags);
-	/*
-	 * If the $FABRIC_MOD session for the Initiator Node ACL exists,
-	 * forcefully shutdown the $FABRIC_MOD session/nexus.
-	 */
-	if (init_sess)
-		tpg->se_tpg_tfo->close_session(init_sess);
+	spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
 
 	pr_debug("Successfully changed queue depth to: %d for Initiator"
-		" Node: %s on %s Target Portal Group: %u\n", queue_depth,
-		initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
+		" Node: %s on %s Target Portal Group: %u\n", acl->queue_depth,
+		acl->initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
 		tpg->se_tpg_tfo->tpg_get_tag(tpg));
 
-	mutex_lock(&tpg->acl_node_mutex);
-	if (dynamic_acl)
-		acl->dynamic_node_acl = 1;
-	mutex_unlock(&tpg->acl_node_mutex);
-
 	return 0;
 }
 EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth);
@@ -499,7 +477,7 @@
 {
 	struct se_lun *lun = container_of(ref, struct se_lun, lun_ref);
 
-	complete(&lun->lun_ref_comp);
+	complete(&lun->lun_shutdown_comp);
 }
 
 int core_tpg_register(
@@ -626,6 +604,7 @@
 	lun->lun_link_magic = SE_LUN_LINK_MAGIC;
 	atomic_set(&lun->lun_acl_count, 0);
 	init_completion(&lun->lun_ref_comp);
+	init_completion(&lun->lun_shutdown_comp);
 	INIT_LIST_HEAD(&lun->lun_deve_list);
 	INIT_LIST_HEAD(&lun->lun_dev_link);
 	atomic_set(&lun->lun_tg_pt_secondary_offline, 0);
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index d151bc3..37c77db 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -341,7 +341,6 @@
 					&buf[0], PR_REG_ISID_LEN);
 			se_sess->sess_bin_isid = get_unaligned_be64(&buf[0]);
 		}
-		kref_get(&se_nacl->acl_kref);
 
 		spin_lock_irq(&se_nacl->nacl_sess_lock);
 		/*
@@ -384,9 +383,9 @@
 	se_tpg->se_tpg_tfo->close_session(se_sess);
 }
 
-void target_get_session(struct se_session *se_sess)
+int target_get_session(struct se_session *se_sess)
 {
-	kref_get(&se_sess->sess_kref);
+	return kref_get_unless_zero(&se_sess->sess_kref);
 }
 EXPORT_SYMBOL(target_get_session);
 
@@ -424,14 +423,27 @@
 {
 	struct se_node_acl *nacl = container_of(kref,
 				struct se_node_acl, acl_kref);
+	struct se_portal_group *se_tpg = nacl->se_tpg;
 
-	complete(&nacl->acl_free_comp);
+	if (!nacl->dynamic_stop) {
+		complete(&nacl->acl_free_comp);
+		return;
+	}
+
+	mutex_lock(&se_tpg->acl_node_mutex);
+	list_del(&nacl->acl_list);
+	mutex_unlock(&se_tpg->acl_node_mutex);
+
+	core_tpg_wait_for_nacl_pr_ref(nacl);
+	core_free_device_list_for_node(nacl, se_tpg);
+	kfree(nacl);
 }
 
 void target_put_nacl(struct se_node_acl *nacl)
 {
 	kref_put(&nacl->acl_kref, target_complete_nacl);
 }
+EXPORT_SYMBOL(target_put_nacl);
 
 void transport_deregister_session_configfs(struct se_session *se_sess)
 {
@@ -464,6 +476,42 @@
 
 void transport_free_session(struct se_session *se_sess)
 {
+	struct se_node_acl *se_nacl = se_sess->se_node_acl;
+
+	/*
+	 * Drop the se_node_acl->nacl_kref obtained from within
+	 * core_tpg_get_initiator_node_acl().
+	 */
+	if (se_nacl) {
+		struct se_portal_group *se_tpg = se_nacl->se_tpg;
+		const struct target_core_fabric_ops *se_tfo = se_tpg->se_tpg_tfo;
+		unsigned long flags;
+
+		se_sess->se_node_acl = NULL;
+
+		/*
+		 * Also determine if we need to drop the extra ->cmd_kref if
+		 * it had been previously dynamically generated, and
+		 * the endpoint is not caching dynamic ACLs.
+		 */
+		mutex_lock(&se_tpg->acl_node_mutex);
+		if (se_nacl->dynamic_node_acl &&
+		    !se_tfo->tpg_check_demo_mode_cache(se_tpg)) {
+			spin_lock_irqsave(&se_nacl->nacl_sess_lock, flags);
+			if (list_empty(&se_nacl->acl_sess_list))
+				se_nacl->dynamic_stop = true;
+			spin_unlock_irqrestore(&se_nacl->nacl_sess_lock, flags);
+
+			if (se_nacl->dynamic_stop)
+				list_del(&se_nacl->acl_list);
+		}
+		mutex_unlock(&se_tpg->acl_node_mutex);
+
+		if (se_nacl->dynamic_stop)
+			target_put_nacl(se_nacl);
+
+		target_put_nacl(se_nacl);
+	}
 	if (se_sess->sess_cmd_map) {
 		percpu_ida_destroy(&se_sess->sess_tag_pool);
 		kvfree(se_sess->sess_cmd_map);
@@ -475,16 +523,12 @@
 void transport_deregister_session(struct se_session *se_sess)
 {
 	struct se_portal_group *se_tpg = se_sess->se_tpg;
-	const struct target_core_fabric_ops *se_tfo;
-	struct se_node_acl *se_nacl;
 	unsigned long flags;
-	bool comp_nacl = true, drop_nacl = false;
 
 	if (!se_tpg) {
 		transport_free_session(se_sess);
 		return;
 	}
-	se_tfo = se_tpg->se_tpg_tfo;
 
 	spin_lock_irqsave(&se_tpg->session_lock, flags);
 	list_del(&se_sess->sess_list);
@@ -492,37 +536,16 @@
 	se_sess->fabric_sess_ptr = NULL;
 	spin_unlock_irqrestore(&se_tpg->session_lock, flags);
 
-	/*
-	 * Determine if we need to do extra work for this initiator node's
-	 * struct se_node_acl if it had been previously dynamically generated.
-	 */
-	se_nacl = se_sess->se_node_acl;
-
-	mutex_lock(&se_tpg->acl_node_mutex);
-	if (se_nacl && se_nacl->dynamic_node_acl) {
-		if (!se_tfo->tpg_check_demo_mode_cache(se_tpg)) {
-			list_del(&se_nacl->acl_list);
-			se_tpg->num_node_acls--;
-			drop_nacl = true;
-		}
-	}
-	mutex_unlock(&se_tpg->acl_node_mutex);
-
-	if (drop_nacl) {
-		core_tpg_wait_for_nacl_pr_ref(se_nacl);
-		core_free_device_list_for_node(se_nacl, se_tpg);
-		kfree(se_nacl);
-		comp_nacl = false;
-	}
 	pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n",
 		se_tpg->se_tpg_tfo->get_fabric_name());
 	/*
 	 * If last kref is dropping now for an explicit NodeACL, awake sleeping
 	 * ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group
-	 * removal context.
+	 * removal context from within transport_free_session() code.
+	 *
+	 * For dynamic ACL, target_put_nacl() uses target_complete_nacl()
+	 * to release all remaining generate_node_acl=1 created ACL resources.
 	 */
-	if (se_nacl && comp_nacl)
-		target_put_nacl(se_nacl);
 
 	transport_free_session(se_sess);
 }
@@ -616,9 +639,10 @@
 		percpu_ref_put(&lun->lun_ref);
 }
 
-void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
+int transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 {
 	bool ack_kref = (cmd->se_cmd_flags & SCF_ACK_KREF);
+	int ret = 0;
 
 	if (cmd->se_cmd_flags & SCF_SE_LUN_CMD)
 		transport_lun_remove_cmd(cmd);
@@ -630,9 +654,11 @@
 		cmd->se_tfo->aborted_task(cmd);
 
 	if (transport_cmd_check_stop_to_fabric(cmd))
-		return;
+		return 1;
 	if (remove && ack_kref)
-		transport_put_cmd(cmd);
+		ret = transport_put_cmd(cmd);
+
+	return ret;
 }
 
 static void target_complete_failure_work(struct work_struct *work)
@@ -1131,15 +1157,28 @@
 	if (cmd->unknown_data_length) {
 		cmd->data_length = size;
 	} else if (size != cmd->data_length) {
-		pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
+		pr_warn_ratelimited("TARGET_CORE[%s]: Expected Transfer Length:"
 			" %u does not match SCSI CDB Length: %u for SAM Opcode:"
 			" 0x%02x\n", cmd->se_tfo->get_fabric_name(),
 				cmd->data_length, size, cmd->t_task_cdb[0]);
 
-		if (cmd->data_direction == DMA_TO_DEVICE &&
-		    cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
-			pr_err("Rejecting underflow/overflow WRITE data\n");
-			return TCM_INVALID_CDB_FIELD;
+		if (cmd->data_direction == DMA_TO_DEVICE) {
+			if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
+				pr_err_ratelimited("Rejecting underflow/overflow"
+						   " for WRITE data CDB\n");
+				return TCM_INVALID_CDB_FIELD;
+			}
+			/*
+			 * Some fabric drivers like iscsi-target still expect to
+			 * always reject overflow writes.  Reject this case until
+			 * full fabric driver level support for overflow writes
+			 * is introduced tree-wide.
+			 */
+			if (size > cmd->data_length) {
+				pr_err_ratelimited("Rejecting overflow for"
+						   " WRITE control CDB\n");
+				return TCM_INVALID_CDB_FIELD;
+			}
 		}
 		/*
 		 * Reject READ_* or WRITE_* with overflow/underflow for
@@ -1270,23 +1309,6 @@
 
 	trace_target_sequencer_start(cmd);
 
-	/*
-	 * Check for an existing UNIT ATTENTION condition
-	 */
-	ret = target_scsi3_ua_check(cmd);
-	if (ret)
-		return ret;
-
-	ret = target_alua_state_check(cmd);
-	if (ret)
-		return ret;
-
-	ret = target_check_reservation(cmd);
-	if (ret) {
-		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
-		return ret;
-	}
-
 	ret = dev->transport->parse_cdb(cmd);
 	if (ret == TCM_UNSUPPORTED_SCSI_OPCODE)
 		pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n",
@@ -1697,6 +1719,7 @@
 	case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
 	case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
 	case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
+	case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE:
 		break;
 	case TCM_OUT_OF_RESOURCES:
 		sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -1749,20 +1772,45 @@
 }
 EXPORT_SYMBOL(transport_generic_request_failure);
 
-void __target_execute_cmd(struct se_cmd *cmd)
+void __target_execute_cmd(struct se_cmd *cmd, bool do_checks)
 {
 	sense_reason_t ret;
 
-	if (cmd->execute_cmd) {
-		ret = cmd->execute_cmd(cmd);
-		if (ret) {
-			spin_lock_irq(&cmd->t_state_lock);
-			cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
-			spin_unlock_irq(&cmd->t_state_lock);
+	if (!cmd->execute_cmd) {
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		goto err;
+	}
+	if (do_checks) {
+		/*
+		 * Check for an existing UNIT ATTENTION condition after
+		 * target_handle_task_attr() has done SAM task attr
+		 * checking, and possibly have already defered execution
+		 * out to target_restart_delayed_cmds() context.
+		 */
+		ret = target_scsi3_ua_check(cmd);
+		if (ret)
+			goto err;
 
-			transport_generic_request_failure(cmd, ret);
+		ret = target_alua_state_check(cmd);
+		if (ret)
+			goto err;
+
+		ret = target_check_reservation(cmd);
+		if (ret) {
+			cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
+			goto err;
 		}
 	}
+
+	ret = cmd->execute_cmd(cmd);
+	if (!ret)
+		return;
+err:
+	spin_lock_irq(&cmd->t_state_lock);
+	cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
+	spin_unlock_irq(&cmd->t_state_lock);
+
+	transport_generic_request_failure(cmd, ret);
 }
 
 static int target_write_prot_action(struct se_cmd *cmd)
@@ -1807,6 +1855,8 @@
 	if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
 		return false;
 
+	cmd->se_cmd_flags |= SCF_TASK_ATTR_SET;
+
 	/*
 	 * Check for the existence of HEAD_OF_QUEUE, and if true return 1
 	 * to allow the passed struct se_cmd list of tasks to the front of the list.
@@ -1887,7 +1937,7 @@
 		return;
 	}
 
-	__target_execute_cmd(cmd);
+	__target_execute_cmd(cmd, true);
 }
 EXPORT_SYMBOL(target_execute_cmd);
 
@@ -1911,7 +1961,7 @@
 		list_del(&cmd->se_delayed_node);
 		spin_unlock(&dev->delayed_cmd_lock);
 
-		__target_execute_cmd(cmd);
+		__target_execute_cmd(cmd, true);
 
 		if (cmd->sam_task_attr == TCM_ORDERED_TAG)
 			break;
@@ -1929,6 +1979,9 @@
 	if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
 		return;
 
+	if (!(cmd->se_cmd_flags & SCF_TASK_ATTR_SET))
+		goto restart;
+
 	if (cmd->sam_task_attr == TCM_SIMPLE_TAG) {
 		atomic_dec_mb(&dev->simple_cmds);
 		dev->dev_cur_ordered_id++;
@@ -1945,7 +1998,7 @@
 		pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n",
 			 dev->dev_cur_ordered_id);
 	}
-
+restart:
 	target_restart_delayed_cmds(dev);
 }
 
@@ -2496,8 +2549,10 @@
 	 * fabric acknowledgement that requires two target_put_sess_cmd()
 	 * invocations before se_cmd descriptor release.
 	 */
-	if (ack_kref)
+	if (ack_kref) {
 		kref_get(&se_cmd->cmd_kref);
+		se_cmd->se_cmd_flags |= SCF_ACK_KREF;
+	}
 
 	spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
 	if (se_sess->sess_tearing_down) {
@@ -2533,15 +2588,10 @@
 	bool fabric_stop;
 
 	spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
-	if (list_empty(&se_cmd->se_cmd_list)) {
-		spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
-		target_free_cmd_mem(se_cmd);
-		se_cmd->se_tfo->release_cmd(se_cmd);
-		return;
-	}
 
 	spin_lock(&se_cmd->t_state_lock);
-	fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP);
+	fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) &&
+		      (se_cmd->transport_state & CMD_T_ABORTED);
 	spin_unlock(&se_cmd->t_state_lock);
 
 	if (se_cmd->cmd_wait_set || fabric_stop) {
@@ -2646,10 +2696,39 @@
 }
 EXPORT_SYMBOL(target_wait_for_sess_cmds);
 
+static void target_lun_confirm(struct percpu_ref *ref)
+{
+	struct se_lun *lun = container_of(ref, struct se_lun, lun_ref);
+
+	complete(&lun->lun_ref_comp);
+}
+
 void transport_clear_lun_ref(struct se_lun *lun)
 {
-	percpu_ref_kill(&lun->lun_ref);
+	/*
+	 * Mark the percpu-ref as DEAD, switch to atomic_t mode, drop
+	 * the initial reference and schedule confirm kill to be
+	 * executed after one full RCU grace period has completed.
+	 */
+	percpu_ref_kill_and_confirm(&lun->lun_ref, target_lun_confirm);
+	/*
+	 * The first completion waits for percpu_ref_switch_to_atomic_rcu()
+	 * to call target_lun_confirm after lun->lun_ref has been marked
+	 * as __PERCPU_REF_DEAD on all CPUs, and switches to atomic_t
+	 * mode so that percpu_ref_tryget_live() lookup of lun->lun_ref
+	 * fails for all new incoming I/O.
+	 */
 	wait_for_completion(&lun->lun_ref_comp);
+	/*
+	 * The second completion waits for percpu_ref_put_many() to
+	 * invoke ->release() after lun->lun_ref has switched to
+	 * atomic_t mode, and lun->lun_ref.count has reached zero.
+	 *
+	 * At this point all target-core lun->lun_ref references have
+	 * been dropped via transport_lun_remove_cmd(), and it's safe
+	 * to proceed with the remaining LUN shutdown.
+	 */
+	wait_for_completion(&lun->lun_shutdown_comp);
 }
 
 static bool
@@ -2825,6 +2904,12 @@
 		.ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
 		.add_sector_info = true,
 	},
+	[TCM_COPY_TARGET_DEVICE_NOT_REACHABLE] = {
+		.key = COPY_ABORTED,
+		.asc = 0x0d,
+		.ascq = 0x02, /* COPY TARGET DEVICE NOT REACHABLE */
+
+	},
 	[TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = {
 		/*
 		 * Returning ILLEGAL REQUEST would cause immediate IO errors on
@@ -3041,7 +3126,6 @@
 		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		goto check_stop;
 	}
-	cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
 	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	cmd->se_tfo->queue_tm_rsp(cmd);
@@ -3054,11 +3138,25 @@
 	struct se_cmd *cmd)
 {
 	unsigned long flags;
+	bool aborted = false;
 
 	spin_lock_irqsave(&cmd->t_state_lock, flags);
-	cmd->transport_state |= CMD_T_ACTIVE;
+	if (cmd->transport_state & CMD_T_ABORTED) {
+		aborted = true;
+	} else {
+		cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
+		cmd->transport_state |= CMD_T_ACTIVE;
+	}
 	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
+	if (aborted) {
+		pr_warn_ratelimited("handle_tmr caught CMD_T_ABORTED TMR %d"
+			"ref_tag: %llu tag: %llu\n", cmd->se_tmr_req->function,
+			cmd->se_tmr_req->ref_task_tag, cmd->tag);
+		transport_cmd_check_stop_to_fabric(cmd);
+		return 0;
+	}
+
 	INIT_WORK(&cmd->work, target_tmr_work);
 	queue_work(cmd->se_dev->tmr_wq, &cmd->work);
 	return 0;
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 5e6d6cb..a7d30e8 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -645,8 +645,6 @@
 	target_complete_cmd(cmd->se_cmd, SAM_STAT_CHECK_CONDITION);
 	cmd->se_cmd = NULL;
 
-	kmem_cache_free(tcmu_cmd_cache, cmd);
-
 	return 0;
 }
 
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 47fe94e..6415e9b 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -104,7 +104,7 @@
 	}
 	mutex_unlock(&g_device_mutex);
 
-	pr_err("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
+	pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
 	return -EINVAL;
 }
 
@@ -185,7 +185,7 @@
 
 static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
 				struct xcopy_op *xop, unsigned char *p,
-				unsigned short tdll)
+				unsigned short tdll, sense_reason_t *sense_ret)
 {
 	struct se_device *local_dev = se_cmd->se_dev;
 	unsigned char *desc = p;
@@ -193,6 +193,8 @@
 	unsigned short start = 0;
 	bool src = true;
 
+	*sense_ret = TCM_INVALID_PARAMETER_LIST;
+
 	if (offset != 0) {
 		pr_err("XCOPY target descriptor list length is not"
 			" multiple of %d\n", XCOPY_TARGET_DESC_LEN);
@@ -243,9 +245,16 @@
 		rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true);
 	else
 		rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false);
-
-	if (rc < 0)
+	/*
+	 * If a matching IEEE NAA 0x83 descriptor for the requested device
+	 * is not located on this node, return COPY_ABORTED with ASQ/ASQC
+	 * 0x0d/0x02 - COPY_TARGET_DEVICE_NOT_REACHABLE to request the
+	 * initiator to fall back to normal copy method.
+	 */
+	if (rc < 0) {
+		*sense_ret = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE;
 		goto out;
+	}
 
 	pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n",
 		 xop->src_dev, &xop->src_tid_wwn[0]);
@@ -653,6 +662,7 @@
 	rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0],
 				remote_port, true);
 	if (rc < 0) {
+		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
 		transport_generic_free_cmd(se_cmd, 0);
 		return rc;
 	}
@@ -664,6 +674,7 @@
 
 	rc = target_xcopy_issue_pt_cmd(xpt_cmd);
 	if (rc < 0) {
+		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
 		transport_generic_free_cmd(se_cmd, 0);
 		return rc;
 	}
@@ -714,6 +725,7 @@
 				remote_port, false);
 	if (rc < 0) {
 		struct se_cmd *src_cmd = &xop->src_pt_cmd->se_cmd;
+		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
 		/*
 		 * If the failure happened before the t_mem_list hand-off in
 		 * target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that
@@ -729,6 +741,7 @@
 
 	rc = target_xcopy_issue_pt_cmd(xpt_cmd);
 	if (rc < 0) {
+		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
 		se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
 		transport_generic_free_cmd(se_cmd, 0);
 		return rc;
@@ -815,10 +828,15 @@
 out:
 	xcopy_pt_undepend_remotedev(xop);
 	kfree(xop);
-
-	pr_warn("target_xcopy_do_work: Setting X-COPY CHECK_CONDITION -> sending response\n");
-	ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
-	target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION);
+	/*
+	 * Don't override an error scsi status if it has already been set
+	 */
+	if (ec_cmd->scsi_status == SAM_STAT_GOOD) {
+		pr_warn_ratelimited("target_xcopy_do_work: rc: %d, Setting X-COPY"
+			" CHECK_CONDITION -> sending response\n", rc);
+		ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
+	}
+	target_complete_cmd(ec_cmd, ec_cmd->scsi_status);
 }
 
 sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
@@ -875,7 +893,7 @@
 		" tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
 		tdll, sdll, inline_dl);
 
-	rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll);
+	rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
 	if (rc <= 0)
 		goto out;
 
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 6ceac4f..5b4b47e 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -857,14 +857,6 @@
 		goto free_power_table;
 	}
 
-	snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
-		 cpufreq_dev->id);
-
-	cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev,
-						      &cpufreq_cooling_ops);
-	if (IS_ERR(cool_dev))
-		goto remove_idr;
-
 	/* Fill freq-table in descending order of frequencies */
 	for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) {
 		freq = find_next_max(table, freq);
@@ -877,6 +869,14 @@
 			pr_debug("%s: freq:%u KHz\n", __func__, freq);
 	}
 
+	snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
+		 cpufreq_dev->id);
+
+	cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev,
+						      &cpufreq_cooling_ops);
+	if (IS_ERR(cool_dev))
+		goto remove_idr;
+
 	cpufreq_dev->clipped_freq = cpufreq_dev->freq_table[0];
 	cpufreq_dev->cool_dev = cool_dev;
 
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
index 06fd2ed9..705b0ca 100644
--- a/drivers/thermal/thermal_hwmon.c
+++ b/drivers/thermal/thermal_hwmon.c
@@ -98,7 +98,7 @@
 	int temperature;
 	int ret;
 
-	ret = tz->ops->get_trip_temp(tz, 0, &temperature);
+	ret = tz->ops->get_crit_temp(tz, &temperature);
 	if (ret)
 		return ret;
 
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 0dde34e..545c60c 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -444,6 +444,7 @@
 	return tb_drom_parse_entries(sw);
 err:
 	kfree(sw->drom);
+	sw->drom = NULL;
 	return -EIO;
 
 }
diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c
index 0f82c0b..1e33285 100644
--- a/drivers/tty/goldfish.c
+++ b/drivers/tty/goldfish.c
@@ -68,8 +68,7 @@
 
 static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
 {
-	struct platform_device *pdev = dev_id;
-	struct goldfish_tty *qtty = &goldfish_ttys[pdev->id];
+	struct goldfish_tty *qtty = dev_id;
 	void __iomem *base = qtty->base;
 	unsigned long irq_flags;
 	unsigned char *buf;
@@ -233,6 +232,7 @@
 	struct device *ttydev;
 	void __iomem *base;
 	u32 irq;
+	unsigned int line;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (r == NULL)
@@ -248,10 +248,16 @@
 
 	irq = r->start;
 
-	if (pdev->id >= goldfish_tty_line_count)
-		goto err_unmap;
-
 	mutex_lock(&goldfish_tty_lock);
+
+	if (pdev->id == PLATFORM_DEVID_NONE)
+		line = goldfish_tty_current_line_count;
+	else
+		line = pdev->id;
+
+	if (line >= goldfish_tty_line_count)
+		goto err_create_driver_failed;
+
 	if (goldfish_tty_current_line_count == 0) {
 		ret = goldfish_tty_create_driver();
 		if (ret)
@@ -259,7 +265,7 @@
 	}
 	goldfish_tty_current_line_count++;
 
-	qtty = &goldfish_ttys[pdev->id];
+	qtty = &goldfish_ttys[line];
 	spin_lock_init(&qtty->lock);
 	tty_port_init(&qtty->port);
 	qtty->port.ops = &goldfish_port_ops;
@@ -269,13 +275,13 @@
 	writel(GOLDFISH_TTY_CMD_INT_DISABLE, base + GOLDFISH_TTY_CMD);
 
 	ret = request_irq(irq, goldfish_tty_interrupt, IRQF_SHARED,
-						"goldfish_tty", pdev);
+						"goldfish_tty", qtty);
 	if (ret)
 		goto err_request_irq_failed;
 
 
 	ttydev = tty_port_register_device(&qtty->port, goldfish_tty_driver,
-							pdev->id, &pdev->dev);
+							line, &pdev->dev);
 	if (IS_ERR(ttydev)) {
 		ret = PTR_ERR(ttydev);
 		goto err_tty_register_device_failed;
@@ -286,8 +292,9 @@
 	qtty->console.device = goldfish_tty_console_device;
 	qtty->console.setup = goldfish_tty_console_setup;
 	qtty->console.flags = CON_PRINTBUFFER;
-	qtty->console.index = pdev->id;
+	qtty->console.index = line;
 	register_console(&qtty->console);
+	platform_set_drvdata(pdev, qtty);
 
 	mutex_unlock(&goldfish_tty_lock);
 	return 0;
@@ -307,13 +314,12 @@
 
 static int goldfish_tty_remove(struct platform_device *pdev)
 {
-	struct goldfish_tty *qtty;
+	struct goldfish_tty *qtty = platform_get_drvdata(pdev);
 
 	mutex_lock(&goldfish_tty_lock);
 
-	qtty = &goldfish_ttys[pdev->id];
 	unregister_console(&qtty->console);
-	tty_unregister_device(goldfish_tty_driver, pdev->id);
+	tty_unregister_device(goldfish_tty_driver, qtty->console.index);
 	iounmap(qtty->base);
 	qtty->base = NULL;
 	free_irq(qtty->irq, pdev);
@@ -324,11 +330,19 @@
 	return 0;
 }
 
+static const struct of_device_id goldfish_tty_of_match[] = {
+	{ .compatible = "google,goldfish-tty", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, goldfish_tty_of_match);
+
 static struct platform_driver goldfish_tty_platform_driver = {
 	.probe = goldfish_tty_probe,
 	.remove = goldfish_tty_remove,
 	.driver = {
-		.name = "goldfish_tty"
+		.name = "goldfish_tty",
+		.of_match_table = goldfish_tty_of_match,
 	}
 };
 
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index c3fe026..9aff371 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2045,7 +2045,9 @@
 		}
 	}
 	spin_unlock(&gsm_mux_lock);
-	WARN_ON(i == MAX_MUX);
+	/* open failed before registering => nothing to do */
+	if (i == MAX_MUX)
+		return;
 
 	/* In theory disconnecting DLCI 0 is sufficient but for some
 	   modems this is apparently not the case. */
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
index bbc4ce6..6d1e2f7 100644
--- a/drivers/tty/n_hdlc.c
+++ b/drivers/tty/n_hdlc.c
@@ -114,7 +114,7 @@
 #define DEFAULT_TX_BUF_COUNT 3
 
 struct n_hdlc_buf {
-	struct n_hdlc_buf *link;
+	struct list_head  list_item;
 	int		  count;
 	char		  buf[1];
 };
@@ -122,8 +122,7 @@
 #define	N_HDLC_BUF_SIZE	(sizeof(struct n_hdlc_buf) + maxframe)
 
 struct n_hdlc_buf_list {
-	struct n_hdlc_buf *head;
-	struct n_hdlc_buf *tail;
+	struct list_head  list;
 	int		  count;
 	spinlock_t	  spinlock;
 };
@@ -136,7 +135,6 @@
  * @backup_tty - TTY to use if tty gets closed
  * @tbusy - reentrancy flag for tx wakeup code
  * @woke_up - FIXME: describe this field
- * @tbuf - currently transmitting tx buffer
  * @tx_buf_list - list of pending transmit frame buffers
  * @rx_buf_list - list of received frame buffers
  * @tx_free_buf_list - list unused transmit frame buffers
@@ -149,7 +147,6 @@
 	struct tty_struct	*backup_tty;
 	int			tbusy;
 	int			woke_up;
-	struct n_hdlc_buf	*tbuf;
 	struct n_hdlc_buf_list	tx_buf_list;
 	struct n_hdlc_buf_list	rx_buf_list;
 	struct n_hdlc_buf_list	tx_free_buf_list;
@@ -159,7 +156,8 @@
 /*
  * HDLC buffer list manipulation functions
  */
-static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list);
+static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list,
+						struct n_hdlc_buf *buf);
 static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
 			   struct n_hdlc_buf *buf);
 static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list);
@@ -209,16 +207,9 @@
 {
 	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
 	struct n_hdlc_buf *buf;
-	unsigned long flags;
 
 	while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list)))
 		n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf);
- 	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
-	if (n_hdlc->tbuf) {
-		n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, n_hdlc->tbuf);
-		n_hdlc->tbuf = NULL;
-	}
-	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
 }
 
 static struct tty_ldisc_ops n_hdlc_ldisc = {
@@ -284,7 +275,6 @@
 		} else
 			break;
 	}
-	kfree(n_hdlc->tbuf);
 	kfree(n_hdlc);
 	
 }	/* end of n_hdlc_release() */
@@ -403,13 +393,7 @@
 	n_hdlc->woke_up = 0;
 	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
 
-	/* get current transmit buffer or get new transmit */
-	/* buffer from list of pending transmit buffers */
-		
-	tbuf = n_hdlc->tbuf;
-	if (!tbuf)
-		tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
-		
+	tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
 	while (tbuf) {
 		if (debuglevel >= DEBUG_LEVEL_INFO)	
 			printk("%s(%d)sending frame %p, count=%d\n",
@@ -421,7 +405,7 @@
 
 		/* rollback was possible and has been done */
 		if (actual == -ERESTARTSYS) {
-			n_hdlc->tbuf = tbuf;
+			n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf);
 			break;
 		}
 		/* if transmit error, throw frame away by */
@@ -436,10 +420,7 @@
 					
 			/* free current transmit buffer */
 			n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf);
-			
-			/* this tx buffer is done */
-			n_hdlc->tbuf = NULL;
-			
+
 			/* wait up sleeping writers */
 			wake_up_interruptible(&tty->write_wait);
 	
@@ -449,10 +430,12 @@
 			if (debuglevel >= DEBUG_LEVEL_INFO)	
 				printk("%s(%d)frame %p pending\n",
 					__FILE__,__LINE__,tbuf);
-					
-			/* buffer not accepted by driver */
-			/* set this buffer as pending buffer */
-			n_hdlc->tbuf = tbuf;
+
+			/*
+			 * the buffer was not accepted by driver,
+			 * return it back into tx queue
+			 */
+			n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf);
 			break;
 		}
 	}
@@ -600,7 +583,7 @@
 	add_wait_queue(&tty->read_wait, &wait);
 
 	for (;;) {
-		if (test_bit(TTY_OTHER_DONE, &tty->flags)) {
+		if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
 			ret = -EIO;
 			break;
 		}
@@ -750,7 +733,8 @@
 	int error = 0;
 	int count;
 	unsigned long flags;
-	
+	struct n_hdlc_buf *buf = NULL;
+
 	if (debuglevel >= DEBUG_LEVEL_INFO)	
 		printk("%s(%d)n_hdlc_tty_ioctl() called %d\n",
 			__FILE__,__LINE__,cmd);
@@ -764,8 +748,10 @@
 		/* report count of read data available */
 		/* in next available frame (if any) */
 		spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock,flags);
-		if (n_hdlc->rx_buf_list.head)
-			count = n_hdlc->rx_buf_list.head->count;
+		buf = list_first_entry_or_null(&n_hdlc->rx_buf_list.list,
+						struct n_hdlc_buf, list_item);
+		if (buf)
+			count = buf->count;
 		else
 			count = 0;
 		spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock,flags);
@@ -777,8 +763,10 @@
 		count = tty_chars_in_buffer(tty);
 		/* add size of next output frame in queue */
 		spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags);
-		if (n_hdlc->tx_buf_list.head)
-			count += n_hdlc->tx_buf_list.head->count;
+		buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list,
+						struct n_hdlc_buf, list_item);
+		if (buf)
+			count += buf->count;
 		spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock,flags);
 		error = put_user(count, (int __user *)arg);
 		break;
@@ -826,14 +814,14 @@
 		poll_wait(filp, &tty->write_wait, wait);
 
 		/* set bits for operations that won't block */
-		if (n_hdlc->rx_buf_list.head)
+		if (!list_empty(&n_hdlc->rx_buf_list.list))
 			mask |= POLLIN | POLLRDNORM;	/* readable */
-		if (test_bit(TTY_OTHER_DONE, &tty->flags))
+		if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
 			mask |= POLLHUP;
 		if (tty_hung_up_p(filp))
 			mask |= POLLHUP;
 		if (!tty_is_writelocked(tty) &&
-				n_hdlc->tx_free_buf_list.head)
+				!list_empty(&n_hdlc->tx_free_buf_list.list))
 			mask |= POLLOUT | POLLWRNORM;	/* writable */
 	}
 	return mask;
@@ -853,11 +841,16 @@
 	if (!n_hdlc)
 		return NULL;
 
-	n_hdlc_buf_list_init(&n_hdlc->rx_free_buf_list);
-	n_hdlc_buf_list_init(&n_hdlc->tx_free_buf_list);
-	n_hdlc_buf_list_init(&n_hdlc->rx_buf_list);
-	n_hdlc_buf_list_init(&n_hdlc->tx_buf_list);
-	
+	spin_lock_init(&n_hdlc->rx_free_buf_list.spinlock);
+	spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock);
+	spin_lock_init(&n_hdlc->rx_buf_list.spinlock);
+	spin_lock_init(&n_hdlc->tx_buf_list.spinlock);
+
+	INIT_LIST_HEAD(&n_hdlc->rx_free_buf_list.list);
+	INIT_LIST_HEAD(&n_hdlc->tx_free_buf_list.list);
+	INIT_LIST_HEAD(&n_hdlc->rx_buf_list.list);
+	INIT_LIST_HEAD(&n_hdlc->tx_buf_list.list);
+
 	/* allocate free rx buffer list */
 	for(i=0;i<DEFAULT_RX_BUF_COUNT;i++) {
 		buf = kmalloc(N_HDLC_BUF_SIZE, GFP_KERNEL);
@@ -885,63 +878,65 @@
 }	/* end of n_hdlc_alloc() */
 
 /**
- * n_hdlc_buf_list_init - initialize specified HDLC buffer list
- * @list - pointer to buffer list
+ * n_hdlc_buf_return - put the HDLC buffer after the head of the specified list
+ * @buf_list - pointer to the buffer list
+ * @buf - pointer to the buffer
  */
-static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list)
+static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list,
+						struct n_hdlc_buf *buf)
 {
-	memset(list, 0, sizeof(*list));
-	spin_lock_init(&list->spinlock);
-}	/* end of n_hdlc_buf_list_init() */
+	unsigned long flags;
+
+	spin_lock_irqsave(&buf_list->spinlock, flags);
+
+	list_add(&buf->list_item, &buf_list->list);
+	buf_list->count++;
+
+	spin_unlock_irqrestore(&buf_list->spinlock, flags);
+}
 
 /**
  * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list
- * @list - pointer to buffer list
+ * @buf_list - pointer to buffer list
  * @buf	- pointer to buffer
  */
-static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
+static void n_hdlc_buf_put(struct n_hdlc_buf_list *buf_list,
 			   struct n_hdlc_buf *buf)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&list->spinlock,flags);
-	
-	buf->link=NULL;
-	if (list->tail)
-		list->tail->link = buf;
-	else
-		list->head = buf;
-	list->tail = buf;
-	(list->count)++;
-	
-	spin_unlock_irqrestore(&list->spinlock,flags);
-	
+
+	spin_lock_irqsave(&buf_list->spinlock, flags);
+
+	list_add_tail(&buf->list_item, &buf_list->list);
+	buf_list->count++;
+
+	spin_unlock_irqrestore(&buf_list->spinlock, flags);
 }	/* end of n_hdlc_buf_put() */
 
 /**
  * n_hdlc_buf_get - remove and return an HDLC buffer from list
- * @list - pointer to HDLC buffer list
+ * @buf_list - pointer to HDLC buffer list
  * 
  * Remove and return an HDLC buffer from the head of the specified HDLC buffer
  * list.
  * Returns a pointer to HDLC buffer if available, otherwise %NULL.
  */
-static struct n_hdlc_buf* n_hdlc_buf_get(struct n_hdlc_buf_list *list)
+static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list)
 {
 	unsigned long flags;
 	struct n_hdlc_buf *buf;
-	spin_lock_irqsave(&list->spinlock,flags);
-	
-	buf = list->head;
+
+	spin_lock_irqsave(&buf_list->spinlock, flags);
+
+	buf = list_first_entry_or_null(&buf_list->list,
+						struct n_hdlc_buf, list_item);
 	if (buf) {
-		list->head = buf->link;
-		(list->count)--;
+		list_del(&buf->list_item);
+		buf_list->count--;
 	}
-	if (!list->head)
-		list->tail = NULL;
-	
-	spin_unlock_irqrestore(&list->spinlock,flags);
+
+	spin_unlock_irqrestore(&buf_list->spinlock, flags);
 	return buf;
-	
 }	/* end of n_hdlc_buf_get() */
 
 static char hdlc_banner[] __initdata =
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index cf000b3..84e71bd 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1955,18 +1955,6 @@
 		return ldata->commit_head - ldata->read_tail >= amt;
 }
 
-static inline int check_other_done(struct tty_struct *tty)
-{
-	int done = test_bit(TTY_OTHER_DONE, &tty->flags);
-	if (done) {
-		/* paired with cmpxchg() in check_other_closed(); ensures
-		 * read buffer head index is not stale
-		 */
-		smp_mb__after_atomic();
-	}
-	return done;
-}
-
 /**
  *	copy_from_read_buf	-	copy read data directly
  *	@tty: terminal device
@@ -2171,7 +2159,7 @@
 	struct n_tty_data *ldata = tty->disc_data;
 	unsigned char __user *b = buf;
 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
-	int c, done;
+	int c;
 	int minimum, time;
 	ssize_t retval = 0;
 	long timeout;
@@ -2239,32 +2227,35 @@
 		    ((minimum - (b - buf)) >= 1))
 			ldata->minimum_to_wake = (minimum - (b - buf));
 
-		done = check_other_done(tty);
-
 		if (!input_available_p(tty, 0)) {
-			if (done) {
-				retval = -EIO;
-				break;
-			}
-			if (tty_hung_up_p(file))
-				break;
-			if (!timeout)
-				break;
-			if (file->f_flags & O_NONBLOCK) {
-				retval = -EAGAIN;
-				break;
-			}
-			if (signal_pending(current)) {
-				retval = -ERESTARTSYS;
-				break;
-			}
 			up_read(&tty->termios_rwsem);
-
-			timeout = wait_woken(&wait, TASK_INTERRUPTIBLE,
-					     timeout);
-
+			tty_buffer_flush_work(tty->port);
 			down_read(&tty->termios_rwsem);
-			continue;
+			if (!input_available_p(tty, 0)) {
+				if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
+					retval = -EIO;
+					break;
+				}
+				if (tty_hung_up_p(file))
+					break;
+				if (!timeout)
+					break;
+				if (file->f_flags & O_NONBLOCK) {
+					retval = -EAGAIN;
+					break;
+				}
+				if (signal_pending(current)) {
+					retval = -ERESTARTSYS;
+					break;
+				}
+				up_read(&tty->termios_rwsem);
+
+				timeout = wait_woken(&wait, TASK_INTERRUPTIBLE,
+						timeout);
+
+				down_read(&tty->termios_rwsem);
+				continue;
+			}
 		}
 
 		if (ldata->icanon && !L_EXTPROC(tty)) {
@@ -2446,12 +2437,17 @@
 
 	poll_wait(file, &tty->read_wait, wait);
 	poll_wait(file, &tty->write_wait, wait);
-	if (check_other_done(tty))
-		mask |= POLLHUP;
 	if (input_available_p(tty, 1))
 		mask |= POLLIN | POLLRDNORM;
+	else {
+		tty_buffer_flush_work(tty->port);
+		if (input_available_p(tty, 1))
+			mask |= POLLIN | POLLRDNORM;
+	}
 	if (tty->packet && tty->link->ctrl_status)
 		mask |= POLLPRI | POLLIN | POLLRDNORM;
+	if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
+		mask |= POLLHUP;
 	if (tty_hung_up_p(file))
 		mask |= POLLHUP;
 	if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index 80f9de9..5cc80b8 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -823,7 +823,7 @@
 	struct tty_struct *tty = tty_port_tty_get(&port->port);
 	int i, ret;
 
-	read_mem32((u32 *) &size, addr, 4);
+	size = __le32_to_cpu(readl(addr));
 	/*  DBG1( "%d bytes port: %d", size, index); */
 
 	if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 78e9836..96aa0ad 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -59,7 +59,7 @@
 	if (!tty->link)
 		return;
 	set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
-	tty_flip_buffer_push(tty->link->port);
+	wake_up_interruptible(&tty->link->read_wait);
 	wake_up_interruptible(&tty->link->write_wait);
 	if (tty->driver->subtype == PTY_TYPE_MASTER) {
 		set_bit(TTY_OTHER_CLOSED, &tty->flags);
@@ -216,16 +216,11 @@
 static void pty_flush_buffer(struct tty_struct *tty)
 {
 	struct tty_struct *to = tty->link;
-	struct tty_ldisc *ld;
 
 	if (!to)
 		return;
 
-	ld = tty_ldisc_ref(to);
-	tty_buffer_flush(to, ld);
-	if (ld)
-		tty_ldisc_deref(ld);
-
+	tty_buffer_flush(to, NULL);
 	if (to->packet) {
 		spin_lock_irq(&tty->ctrl_lock);
 		tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
@@ -247,9 +242,7 @@
 		goto out;
 
 	clear_bit(TTY_IO_ERROR, &tty->flags);
-	/* TTY_OTHER_CLOSED must be cleared before TTY_OTHER_DONE */
 	clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
-	clear_bit(TTY_OTHER_DONE, &tty->link->flags);
 	set_bit(TTY_THROTTLED, &tty->flags);
 	return 0;
 
@@ -681,14 +674,14 @@
 /* this is called once with whichever end is closed last */
 static void pty_unix98_shutdown(struct tty_struct *tty)
 {
-	struct inode *ptmx_inode;
+	struct pts_fs_info *fsi;
 
 	if (tty->driver->subtype == PTY_TYPE_MASTER)
-		ptmx_inode = tty->driver_data;
+		fsi = tty->driver_data;
 	else
-		ptmx_inode = tty->link->driver_data;
-	devpts_kill_index(ptmx_inode, tty->index);
-	devpts_del_ref(ptmx_inode);
+		fsi = tty->link->driver_data;
+	devpts_kill_index(fsi, tty->index);
+	devpts_put_ref(fsi);
 }
 
 static const struct tty_operations ptm_unix98_ops = {
@@ -740,6 +733,7 @@
 
 static int ptmx_open(struct inode *inode, struct file *filp)
 {
+	struct pts_fs_info *fsi;
 	struct tty_struct *tty;
 	struct inode *slave_inode;
 	int retval;
@@ -754,47 +748,41 @@
 	if (retval)
 		return retval;
 
+	fsi = devpts_get_ref(inode, filp);
+	retval = -ENODEV;
+	if (!fsi)
+		goto out_free_file;
+
 	/* find a device that is not in use. */
 	mutex_lock(&devpts_mutex);
-	index = devpts_new_index(inode);
-	if (index < 0) {
-		retval = index;
-		mutex_unlock(&devpts_mutex);
-		goto err_file;
-	}
-
+	index = devpts_new_index(fsi);
 	mutex_unlock(&devpts_mutex);
 
+	retval = index;
+	if (index < 0)
+		goto out_put_ref;
+
+
 	mutex_lock(&tty_mutex);
 	tty = tty_init_dev(ptm_driver, index);
-
-	if (IS_ERR(tty)) {
-		retval = PTR_ERR(tty);
-		goto out;
-	}
-
 	/* The tty returned here is locked so we can safely
 	   drop the mutex */
 	mutex_unlock(&tty_mutex);
 
-	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
-	tty->driver_data = inode;
+	retval = PTR_ERR(tty);
+	if (IS_ERR(tty))
+		goto out;
 
 	/*
-	 * In the case where all references to ptmx inode are dropped and we
-	 * still have /dev/tty opened pointing to the master/slave pair (ptmx
-	 * is closed/released before /dev/tty), we must make sure that the inode
-	 * is still valid when we call the final pty_unix98_shutdown, thus we
-	 * hold an additional reference to the ptmx inode. For the same /dev/tty
-	 * last close case, we also need to make sure the super_block isn't
-	 * destroyed (devpts instance unmounted), before /dev/tty is closed and
-	 * on its release devpts_kill_index is called.
+	 * From here on out, the tty is "live", and the index and
+	 * fsi will be killed/put by the tty_release()
 	 */
-	devpts_add_ref(inode);
+	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
+	tty->driver_data = fsi;
 
 	tty_add_file(tty, filp);
 
-	slave_inode = devpts_pty_new(inode,
+	slave_inode = devpts_pty_new(fsi,
 			MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index,
 			tty->link);
 	if (IS_ERR(slave_inode)) {
@@ -813,12 +801,14 @@
 	return 0;
 err_release:
 	tty_unlock(tty);
+	// This will also put-ref the fsi
 	tty_release(inode, filp);
 	return retval;
 out:
-	mutex_unlock(&tty_mutex);
-	devpts_kill_index(inode, index);
-err_file:
+	devpts_kill_index(fsi, index);
+out_put_ref:
+	devpts_put_ref(fsi);
+out_free_file:
 	tty_free_file(filp);
 	return retval;
 }
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index a5d319e..8435c3f 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -440,7 +440,7 @@
 	}
 
 	data->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
-	if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) {
+	if (IS_ERR(data->pclk) && PTR_ERR(data->pclk) == -EPROBE_DEFER) {
 		err = -EPROBE_DEFER;
 		goto err_clk;
 	}
diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
index 88531a3..83b3988 100644
--- a/drivers/tty/serial/8250/8250_mid.c
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -14,6 +14,7 @@
 #include <linux/pci.h>
 
 #include <linux/dma/hsu.h>
+#include <linux/8250_pci.h>
 
 #include "8250.h"
 
@@ -24,6 +25,7 @@
 #define PCI_DEVICE_ID_INTEL_DNV_UART	0x19d8
 
 /* Intel MID Specific registers */
+#define INTEL_MID_UART_DNV_FISR		0x08
 #define INTEL_MID_UART_PS		0x30
 #define INTEL_MID_UART_MUL		0x34
 #define INTEL_MID_UART_DIV		0x38
@@ -31,6 +33,7 @@
 struct mid8250;
 
 struct mid8250_board {
+	unsigned int flags;
 	unsigned long freq;
 	unsigned int base_baud;
 	int (*setup)(struct mid8250 *, struct uart_port *p);
@@ -88,16 +91,16 @@
 static int dnv_handle_irq(struct uart_port *p)
 {
 	struct mid8250 *mid = p->private_data;
-	int ret;
+	unsigned int fisr = serial_port_in(p, INTEL_MID_UART_DNV_FISR);
+	int ret = IRQ_NONE;
 
-	ret = hsu_dma_irq(&mid->dma_chip, 0);
-	ret |= hsu_dma_irq(&mid->dma_chip, 1);
-
-	/* For now, letting the HW generate separate interrupt for the UART */
-	if (ret)
-		return ret;
-
-	return serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
+	if (fisr & BIT(2))
+		ret |= hsu_dma_irq(&mid->dma_chip, 1);
+	if (fisr & BIT(1))
+		ret |= hsu_dma_irq(&mid->dma_chip, 0);
+	if (fisr & BIT(0))
+		ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
+	return ret;
 }
 
 #define DNV_DMA_CHAN_OFFSET 0x80
@@ -106,12 +109,13 @@
 {
 	struct hsu_dma_chip *chip = &mid->dma_chip;
 	struct pci_dev *pdev = to_pci_dev(p->dev);
+	unsigned int bar = FL_GET_BASE(mid->board->flags);
 	int ret;
 
 	chip->dev = &pdev->dev;
 	chip->irq = pdev->irq;
 	chip->regs = p->membase;
-	chip->length = pci_resource_len(pdev, 0);
+	chip->length = pci_resource_len(pdev, bar);
 	chip->offset = DNV_DMA_CHAN_OFFSET;
 
 	/* Falling back to PIO mode if DMA probing fails */
@@ -145,6 +149,9 @@
 	unsigned long w = BIT(24) - 1;
 	unsigned long mul, div;
 
+	/* Gracefully handle the B0 case: fall back to B9600 */
+	fuart = fuart ? fuart : 9600 * 16;
+
 	if (mid->board->freq < fuart) {
 		/* Find prescaler value that satisfies Fuart < Fref */
 		if (mid->board->freq > baud)
@@ -217,6 +224,7 @@
 {
 	struct uart_8250_port uart;
 	struct mid8250 *mid;
+	unsigned int bar;
 	int ret;
 
 	ret = pcim_enable_device(pdev);
@@ -230,6 +238,7 @@
 		return -ENOMEM;
 
 	mid->board = (struct mid8250_board *)id->driver_data;
+	bar = FL_GET_BASE(mid->board->flags);
 
 	memset(&uart, 0, sizeof(struct uart_8250_port));
 
@@ -242,8 +251,8 @@
 	uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
 	uart.port.set_termios = mid8250_set_termios;
 
-	uart.port.mapbase = pci_resource_start(pdev, 0);
-	uart.port.membase = pcim_iomap(pdev, 0, 0);
+	uart.port.mapbase = pci_resource_start(pdev, bar);
+	uart.port.membase = pcim_iomap(pdev, bar, 0);
 	if (!uart.port.membase)
 		return -ENOMEM;
 
@@ -282,18 +291,21 @@
 }
 
 static const struct mid8250_board pnw_board = {
+	.flags = FL_BASE0,
 	.freq = 50000000,
 	.base_baud = 115200,
 	.setup = pnw_setup,
 };
 
 static const struct mid8250_board tng_board = {
+	.flags = FL_BASE0,
 	.freq = 38400000,
 	.base_baud = 1843200,
 	.setup = tng_setup,
 };
 
 static const struct mid8250_board dnv_board = {
+	.flags = FL_BASE1,
 	.freq = 133333333,
 	.base_baud = 115200,
 	.setup = dnv_setup,
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index a2c0734..e8dd296 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -1235,7 +1235,8 @@
 	pm_runtime_put_autosuspend(&pdev->dev);
 	return 0;
 err:
-	pm_runtime_put(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	return ret;
 }
@@ -1244,6 +1245,7 @@
 {
 	struct omap8250_priv *priv = platform_get_drvdata(pdev);
 
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	serial8250_unregister_port(priv->line);
@@ -1343,6 +1345,10 @@
 	struct omap8250_priv *priv = dev_get_drvdata(dev);
 	struct uart_8250_port *up;
 
+	/* In case runtime-pm tries this before we are setup */
+	if (!priv)
+		return 0;
+
 	up = serial8250_get_port(priv->line);
 	/*
 	 * When using 'no_console_suspend', the console UART must not be
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 7cd6f9a..cf3da51 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -57,6 +57,7 @@
 	unsigned int		nr;
 	void __iomem		*remapped_bar[PCI_NUM_BAR_RESOURCES];
 	struct pci_serial_quirk	*quirk;
+	const struct pciserial_board *board;
 	int			line[0];
 };
 
@@ -1401,6 +1402,9 @@
 	unsigned long m, n;
 	u32 reg;
 
+	/* Gracefully handle the B0 case: fall back to B9600 */
+	fuart = fuart ? fuart : 9600 * 16;
+
 	/* Get Fuart closer to Fref */
 	fuart *= rounddown_pow_of_two(fref / fuart);
 
@@ -1949,6 +1953,43 @@
 #define PCI_DEVICE_ID_PERICOM_PI7C9X7954	0x7954
 #define PCI_DEVICE_ID_PERICOM_PI7C9X7958	0x7958
 
+#define PCI_VENDOR_ID_ACCESIO			0x494f
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB	0x1051
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S	0x1053
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB	0x105C
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S	0x105E
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB	0x1091
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2	0x1093
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB	0x1099
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4	0x109B
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB	0x10D1
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM	0x10D3
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB	0x10DA
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM	0x10DC
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1	0x1108
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2	0x1110
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2	0x1111
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4	0x1118
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4	0x1119
+#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S	0x1152
+#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S	0x115A
+#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2	0x1190
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2	0x1191
+#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4	0x1198
+#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4	0x1199
+#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM	0x11D0
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4	0x105A
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4	0x105B
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8	0x106A
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8	0x106B
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4	0x1098
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8	0x10A9
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM	0x10D9
+#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM	0x10E9
+#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM	0x11D8
+
+
+
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584	0x1584
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1588	0x1588
@@ -2840,6 +2881,8 @@
 	pbn_b0_4_1152000_200,
 	pbn_b0_8_1152000_200,
 
+	pbn_b0_4_1250000,
+
 	pbn_b0_2_1843200,
 	pbn_b0_4_1843200,
 
@@ -3073,6 +3116,13 @@
 		.uart_offset	= 0x200,
 	},
 
+	[pbn_b0_4_1250000] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 4,
+		.base_baud	= 1250000,
+		.uart_offset	= 8,
+	},
+
 	[pbn_b0_2_1843200] = {
 		.flags		= FL_BASE0,
 		.num_ports	= 2,
@@ -4009,6 +4059,7 @@
 		}
 	}
 	priv->nr = i;
+	priv->board = board;
 	return priv;
 
 err_deinit:
@@ -4019,7 +4070,7 @@
 }
 EXPORT_SYMBOL_GPL(pciserial_init_ports);
 
-void pciserial_remove_ports(struct serial_private *priv)
+void pciserial_detach_ports(struct serial_private *priv)
 {
 	struct pci_serial_quirk *quirk;
 	int i;
@@ -4039,7 +4090,11 @@
 	quirk = find_quirk(priv->dev);
 	if (quirk->exit)
 		quirk->exit(priv->dev);
+}
 
+void pciserial_remove_ports(struct serial_private *priv)
+{
+	pciserial_detach_ports(priv);
 	kfree(priv);
 }
 EXPORT_SYMBOL_GPL(pciserial_remove_ports);
@@ -5117,6 +5172,108 @@
 		0,
 		0, pbn_pericom_PI7C9X7958 },
 	/*
+	 * ACCES I/O Products quad
+	 */
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7954 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7958 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7958 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7958 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7958 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7958 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7958 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7958 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7958 },
+	{	PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_pericom_PI7C9X7958 },
+	/*
 	 * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
 	 */
 	{	PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
@@ -5636,6 +5793,10 @@
 	{ PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 },
 	{ PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 },
 
+	/* MKS Tenta SCOM-080x serial cards */
+	{ PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 },
+	{ PCI_DEVICE(0x1601, 0xa801), .driver_data = pbn_b0_4_1250000 },
+
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
@@ -5664,7 +5825,7 @@
 		return PCI_ERS_RESULT_DISCONNECT;
 
 	if (priv)
-		pciserial_suspend_ports(priv);
+		pciserial_detach_ports(priv);
 
 	pci_disable_device(dev);
 
@@ -5689,9 +5850,16 @@
 static void serial8250_io_resume(struct pci_dev *dev)
 {
 	struct serial_private *priv = pci_get_drvdata(dev);
+	struct serial_private *new;
 
-	if (priv)
-		pciserial_resume_ports(priv);
+	if (!priv)
+		return;
+
+	new = pciserial_init_ports(dev, priv->board);
+	if (!IS_ERR(new)) {
+		pci_set_drvdata(dev, new);
+		kfree(priv);
+	}
 }
 
 static const struct pci_error_handlers serial8250_err_handler = {
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 9429455..53e4d50 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -277,6 +277,13 @@
 	return atmel_port->use_dma_rx;
 }
 
+static bool atmel_use_fifo(struct uart_port *port)
+{
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+	return atmel_port->fifo_size;
+}
+
 static unsigned int atmel_get_lines_status(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
@@ -463,6 +470,14 @@
 		/* disable PDC transmit */
 		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 	}
+
+	/*
+	 * Disable the transmitter.
+	 * This is mandatory when DMA is used, otherwise the DMA buffer
+	 * is fully transmitted.
+	 */
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS);
+
 	/* Disable interrupts */
 	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
@@ -478,21 +493,26 @@
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	if (atmel_use_pdc_tx(port)) {
-		if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
-			/* The transmitter is already running.  Yes, we
-			   really need this.*/
-			return;
+	if (atmel_use_pdc_tx(port) && (atmel_uart_readl(port, ATMEL_PDC_PTSR)
+				       & ATMEL_PDC_TXTEN))
+		/* The transmitter is already running.  Yes, we
+		   really need this.*/
+		return;
 
+	if (atmel_use_pdc_tx(port) || atmel_use_dma_tx(port))
 		if ((port->rs485.flags & SER_RS485_ENABLED) &&
 		    !(port->rs485.flags & SER_RS485_RX_DURING_TX))
 			atmel_stop_rx(port);
 
+	if (atmel_use_pdc_tx(port))
 		/* re-enable PDC transmit */
 		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
-	}
+
 	/* Enable interrupts */
 	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
+
+	/* re-enable the transmitter */
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN);
 }
 
 /*
@@ -790,6 +810,11 @@
 	 */
 	if (!uart_circ_empty(xmit))
 		tasklet_schedule(&atmel_port->tasklet);
+	else if ((port->rs485.flags & SER_RS485_ENABLED) &&
+		 !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
+		/* DMA done, stop TX, start RX for RS485 */
+		atmel_start_rx(port);
+	}
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -892,12 +917,6 @@
 		desc->callback = atmel_complete_tx_dma;
 		desc->callback_param = atmel_port;
 		atmel_port->cookie_tx = dmaengine_submit(desc);
-
-	} else {
-		if (port->rs485.flags & SER_RS485_ENABLED) {
-			/* DMA done, stop TX, start RX for RS485 */
-			atmel_start_rx(port);
-		}
 	}
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
@@ -1967,6 +1986,11 @@
 		atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
 		atmel_port->pdc_tx.ofs = 0;
 	}
+	/*
+	 * in uart_flush_buffer(), the xmit circular buffer has just
+	 * been cleared, so we have to reset tx_len accordingly.
+	 */
+	atmel_port->tx_len = 0;
 }
 
 /*
@@ -2066,6 +2090,7 @@
 static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 			      struct ktermios *old)
 {
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	unsigned long flags;
 	unsigned int old_mode, mode, imr, quot, baud;
 
@@ -2169,7 +2194,30 @@
 		mode |= ATMEL_US_USMODE_RS485;
 	} else if (termios->c_cflag & CRTSCTS) {
 		/* RS232 with hardware handshake (RTS/CTS) */
-		mode |= ATMEL_US_USMODE_HWHS;
+		if (atmel_use_fifo(port) &&
+		    !mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) {
+			/*
+			 * with ATMEL_US_USMODE_HWHS set, the controller will
+			 * be able to drive the RTS pin high/low when the RX
+			 * FIFO is above RXFTHRES/below RXFTHRES2.
+			 * It will also disable the transmitter when the CTS
+			 * pin is high.
+			 * This mode is not activated if CTS pin is a GPIO
+			 * because in this case, the transmitter is always
+			 * disabled (there must be an internal pull-up
+			 * responsible for this behaviour).
+			 * If the RTS pin is a GPIO, the controller won't be
+			 * able to drive it according to the FIFO thresholds,
+			 * but it will be handled by the driver.
+			 */
+			mode |= ATMEL_US_USMODE_HWHS;
+		} else {
+			/*
+			 * For platforms without FIFO, the flow control is
+			 * handled by the driver.
+			 */
+			mode |= ATMEL_US_USMODE_NORMAL;
+		}
 	} else {
 		/* RS232 without hadware handshake */
 		mode |= ATMEL_US_USMODE_NORMAL;
@@ -2455,6 +2503,9 @@
 	pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
 	atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 
+	/* Make sure that tx path is actually able to send characters */
+	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN);
+
 	uart_console_write(port, s, count, atmel_console_putchar);
 
 	/*
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
index 195acc8..5d47691 100644
--- a/drivers/tty/serial/efm32-uart.c
+++ b/drivers/tty/serial/efm32-uart.c
@@ -27,6 +27,7 @@
 #define UARTn_FRAME		0x04
 #define UARTn_FRAME_DATABITS__MASK	0x000f
 #define UARTn_FRAME_DATABITS(n)		((n) - 3)
+#define UARTn_FRAME_PARITY__MASK	0x0300
 #define UARTn_FRAME_PARITY_NONE		0x0000
 #define UARTn_FRAME_PARITY_EVEN		0x0200
 #define UARTn_FRAME_PARITY_ODD		0x0300
@@ -572,12 +573,16 @@
 			16 * (4 + (clkdiv >> 6)));
 
 	frame = efm32_uart_read32(efm_port, UARTn_FRAME);
-	if (frame & UARTn_FRAME_PARITY_ODD)
+	switch (frame & UARTn_FRAME_PARITY__MASK) {
+	case UARTn_FRAME_PARITY_ODD:
 		*parity = 'o';
-	else if (frame & UARTn_FRAME_PARITY_EVEN)
+		break;
+	case UARTn_FRAME_PARITY_EVEN:
 		*parity = 'e';
-	else
+		break;
+	default:
 		*parity = 'n';
+	}
 
 	*bits = (frame & UARTn_FRAME_DATABITS__MASK) -
 			UARTn_FRAME_DATABITS(4) + 4;
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 88246f7..0f23dda 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -1378,9 +1378,9 @@
 static void __exit ifx_spi_exit(void)
 {
 	/* unregister */
+	spi_unregister_driver(&ifx_spi_driver);
 	tty_unregister_driver(tty_drv);
 	put_tty_driver(tty_drv);
-	spi_unregister_driver(&ifx_spi_driver);
 	unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
 }
 
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index dcde955..8c4707d 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -726,7 +726,7 @@
 		return;
 	}
 
-	pio_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
+	pio_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
 	dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
 
 	dma_min = 1;	/* Always DMA */
@@ -1615,6 +1615,7 @@
 	{ .compatible = "qcom,msm-uartdm" },
 	{}
 };
+MODULE_DEVICE_TABLE(of, msm_match_table);
 
 static struct platform_driver msm_platform_driver = {
 	.remove = msm_serial_remove,
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 24280d9..de1c143 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1712,7 +1712,8 @@
 	return 0;
 
 err_add_port:
-	pm_runtime_put(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_qos_remove_request(&up->pm_qos_request);
 	device_init_wakeup(up->dev, false);
@@ -1725,9 +1726,13 @@
 {
 	struct uart_omap_port *up = platform_get_drvdata(dev);
 
+	pm_runtime_get_sync(up->dev);
+
+	uart_remove_one_port(&serial_omap_reg, &up->port);
+
+	pm_runtime_dont_use_autosuspend(up->dev);
 	pm_runtime_put_sync(up->dev);
 	pm_runtime_disable(up->dev);
-	uart_remove_one_port(&serial_omap_reg, &up->port);
 	pm_qos_remove_request(&up->pm_qos_request);
 	device_init_wakeup(&dev->dev, false);
 
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index d72cd73..e6bc1a6 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -900,14 +900,13 @@
 		return -ENOMEM;
 	}
 
-	dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf,
+	dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf,
 				dma->rx_size, DMA_FROM_DEVICE);
 
 	spin_lock_irqsave(&p->port.lock, flags);
 
 	/* TX buffer */
-	dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
-				p->port.state->xmit.buf,
+	dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf,
 				UART_XMIT_SIZE, DMA_TO_DEVICE);
 
 	spin_unlock_irqrestore(&p->port.lock, flags);
@@ -921,7 +920,7 @@
 
 	if (dma->rx_chan) {
 		dmaengine_terminate_all(dma->rx_chan);
-		dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
+		dma_unmap_single(p->port.dev, dma->rx_addr,
 				dma->rx_size, DMA_FROM_DEVICE);
 		kfree(dma->rx_buf);
 		dma_release_channel(dma->rx_chan);
@@ -930,7 +929,7 @@
 
 	if (dma->tx_chan) {
 		dmaengine_terminate_all(dma->tx_chan);
-		dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr,
+		dma_unmap_single(p->port.dev, dma->tx_addr,
 				UART_XMIT_SIZE, DMA_TO_DEVICE);
 		dma_release_channel(dma->tx_chan);
 		dma->tx_chan = NULL;
@@ -1030,8 +1029,10 @@
 	if (ourport->dma) {
 		ret = s3c24xx_serial_request_dma(ourport);
 		if (ret < 0) {
-			dev_warn(port->dev, "DMA request failed\n");
-			return ret;
+			dev_warn(port->dev,
+				 "DMA request failed, DMA will not be used\n");
+			devm_kfree(port->dev, ourport->dma);
+			ourport->dma = NULL;
 		}
 	}
 
@@ -1263,6 +1264,8 @@
 	/* check to see if we need  to change clock source */
 
 	if (ourport->baudclk != clk) {
+		clk_prepare_enable(clk);
+
 		s3c24xx_serial_setsource(port, clk_sel);
 
 		if (!IS_ERR(ourport->baudclk)) {
@@ -1270,8 +1273,6 @@
 			ourport->baudclk = ERR_PTR(-EINVAL);
 		}
 
-		clk_prepare_enable(clk);
-
 		ourport->baudclk = clk;
 		ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
 	}
@@ -1676,7 +1677,7 @@
 		return -ENODEV;
 
 	if (port->mapbase != 0)
-		return 0;
+		return -EINVAL;
 
 	/* setup info for port */
 	port->dev	= &platdev->dev;
@@ -1730,22 +1731,25 @@
 		ourport->dma = devm_kzalloc(port->dev,
 					    sizeof(*ourport->dma),
 					    GFP_KERNEL);
-		if (!ourport->dma)
-			return -ENOMEM;
+		if (!ourport->dma) {
+			ret = -ENOMEM;
+			goto err;
+		}
 	}
 
 	ourport->clk	= clk_get(&platdev->dev, "uart");
 	if (IS_ERR(ourport->clk)) {
 		pr_err("%s: Controller clock not found\n",
 				dev_name(&platdev->dev));
-		return PTR_ERR(ourport->clk);
+		ret = PTR_ERR(ourport->clk);
+		goto err;
 	}
 
 	ret = clk_prepare_enable(ourport->clk);
 	if (ret) {
 		pr_err("uart: clock failed to prepare+enable: %d\n", ret);
 		clk_put(ourport->clk);
-		return ret;
+		goto err;
 	}
 
 	/* Keep all interrupts masked and cleared */
@@ -1761,7 +1765,12 @@
 
 	/* reset the fifos (and setup the uart) */
 	s3c24xx_serial_resetport(port, cfg);
+
 	return 0;
+
+err:
+	port->mapbase = 0;
+	return ret;
 }
 
 /* Device driver serial port probe */
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index edb5305..7d5ee8a 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1230,7 +1230,7 @@
 
 	/* Setup interrupt */
 	ret = devm_request_irq(dev, irq, sc16is7xx_irq,
-			       IRQF_ONESHOT | flags, dev_name(dev), s);
+			       flags, dev_name(dev), s);
 	if (!ret)
 		return 0;
 
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 63a06ab..235e150 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1800,12 +1800,14 @@
 
 	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
 
-	ret = sci_request_irq(s);
-	if (unlikely(ret < 0))
-		return ret;
-
 	sci_request_dma(port);
 
+	ret = sci_request_irq(s);
+	if (unlikely(ret < 0)) {
+		sci_free_dma(port);
+		return ret;
+	}
+
 	spin_lock_irqsave(&port->lock, flags);
 	sci_start_tx(port);
 	sci_start_rx(port);
@@ -1834,8 +1836,8 @@
 	}
 #endif
 
-	sci_free_dma(port);
 	sci_free_irq(s);
+	sci_free_dma(port);
 }
 
 static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index ca0d380..4e603d0 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -490,12 +490,6 @@
 		locked = spin_trylock_irqsave(&port->lock, flags);
 	else
 		spin_lock_irqsave(&port->lock, flags);
-	if (port->sysrq) {
-		locked = 0;
-	} else if (oops_in_progress) {
-		locked = spin_trylock(&port->lock);
-	} else
-		spin_lock(&port->lock);
 
 	for (i = 0; i < n; i++) {
 		if (*s == '\n')
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 73190f5..71d26c8 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -1478,6 +1478,9 @@
 		.type = "serial",
 		.compatible = "ucc_uart",
 	},
+	{
+		.compatible = "fsl,t1040-ucc-uart",
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, ucc_uart_match);
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 5381a72..1fa4128 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -939,8 +939,8 @@
 	{
 		.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
 				INPUT_DEVICE_ID_MATCH_KEYBIT,
-		.evbit = { BIT_MASK(EV_KEY) },
-		.keybit = { BIT_MASK(KEY_LEFTALT) },
+		.evbit = { [BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY) },
+		.keybit = { [BIT_WORD(KEY_LEFTALT)] = BIT_MASK(KEY_LEFTALT) },
 	},
 	{ },
 };
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 3cd31e0..fb31eec 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -37,29 +37,6 @@
 
 #define TTY_BUFFER_PAGE	(((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF)
 
-/*
- * If all tty flip buffers have been processed by flush_to_ldisc() or
- * dropped by tty_buffer_flush(), check if the linked pty has been closed.
- * If so, wake the reader/poll to process
- */
-static inline void check_other_closed(struct tty_struct *tty)
-{
-	unsigned long flags, old;
-
-	/* transition from TTY_OTHER_CLOSED => TTY_OTHER_DONE must be atomic */
-	for (flags = ACCESS_ONCE(tty->flags);
-	     test_bit(TTY_OTHER_CLOSED, &flags);
-	     ) {
-		old = flags;
-		__set_bit(TTY_OTHER_DONE, &flags);
-		flags = cmpxchg(&tty->flags, old, flags);
-		if (old == flags) {
-			wake_up_interruptible(&tty->read_wait);
-			break;
-		}
-	}
-}
-
 /**
  *	tty_buffer_lock_exclusive	-	gain exclusive access to buffer
  *	tty_buffer_unlock_exclusive	-	release exclusive access
@@ -254,8 +231,6 @@
 	if (ld && ld->ops->flush_buffer)
 		ld->ops->flush_buffer(tty);
 
-	check_other_closed(tty);
-
 	atomic_dec(&buf->priority);
 	mutex_unlock(&buf->lock);
 }
@@ -505,10 +480,8 @@
 		 */
 		count = smp_load_acquire(&head->commit) - head->read;
 		if (!count) {
-			if (next == NULL) {
-				check_other_closed(tty);
+			if (next == NULL)
 				break;
-			}
 			buf->head = next;
 			tty_buffer_free(port, head);
 			continue;
@@ -597,3 +570,8 @@
 {
 	return cancel_work_sync(&port->buf.work);
 }
+
+void tty_buffer_flush_work(struct tty_port *port)
+{
+	flush_work(&port->buf.work);
+}
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 7cef543..1bb629a 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2070,13 +2070,12 @@
 		if (tty) {
 			mutex_unlock(&tty_mutex);
 			retval = tty_lock_interruptible(tty);
+			tty_kref_put(tty);  /* drop kref from tty_driver_lookup_tty() */
 			if (retval) {
 				if (retval == -EINTR)
 					retval = -ERESTARTSYS;
 				goto err_unref;
 			}
-			/* safe to drop the kref from tty_driver_lookup_tty() */
-			tty_kref_put(tty);
 			retval = tty_reopen(tty);
 			if (retval < 0) {
 				tty_unlock(tty);
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 629e3c8..9bee25c 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -417,6 +417,10 @@
  *	they are not on hot paths so a little discipline won't do
  *	any harm.
  *
+ *	The line discipline-related tty_struct fields are reset to
+ *	prevent the ldisc driver from re-using stale information for
+ *	the new ldisc instance.
+ *
  *	Locking: takes termios_rwsem
  */
 
@@ -425,6 +429,9 @@
 	down_write(&tty->termios_rwsem);
 	tty->termios.c_line = num;
 	up_write(&tty->termios_rwsem);
+
+	tty->disc_data = NULL;
+	tty->receive_room = 0;
 }
 
 /**
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index d09293b..cff304a 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -24,10 +24,15 @@
 
 int tty_lock_interruptible(struct tty_struct *tty)
 {
+	int ret;
+
 	if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
 		return -EIO;
 	tty_kref_get(tty);
-	return mutex_lock_interruptible(&tty->legacy_mutex);
+	ret = mutex_lock_interruptible(&tty->legacy_mutex);
+	if (ret)
+		tty_kref_put(tty);
+	return ret;
 }
 
 void __lockfunc tty_unlock(struct tty_struct *tty)
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 6f0336f..988c564 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -366,34 +366,22 @@
 
 static void do_compute_shiftstate(void)
 {
-	unsigned int i, j, k, sym, val;
+	unsigned int k, sym, val;
 
 	shift_state = 0;
 	memset(shift_down, 0, sizeof(shift_down));
 
-	for (i = 0; i < ARRAY_SIZE(key_down); i++) {
-
-		if (!key_down[i])
+	for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) {
+		sym = U(key_maps[0][k]);
+		if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
 			continue;
 
-		k = i * BITS_PER_LONG;
+		val = KVAL(sym);
+		if (val == KVAL(K_CAPSSHIFT))
+			val = KVAL(K_SHIFT);
 
-		for (j = 0; j < BITS_PER_LONG; j++, k++) {
-
-			if (!test_bit(k, key_down))
-				continue;
-
-			sym = U(key_maps[0][k]);
-			if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
-				continue;
-
-			val = KVAL(sym);
-			if (val == KVAL(K_CAPSSHIFT))
-				val = KVAL(K_SHIFT);
-
-			shift_down[val]++;
-			shift_state |= (1 << val);
-		}
+		shift_down[val]++;
+		shift_state |= BIT(val);
 	}
 }
 
@@ -994,7 +982,7 @@
 	KBD_LED_TRIGGER((_led_bit) + 8, _name)
 
 static struct kbd_led_trigger kbd_led_triggers[] = {
-	KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"),
+	KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrolllock"),
 	KBD_LED_TRIGGER(VC_NUMLOCK,   "kbd-numlock"),
 	KBD_LED_TRIGGER(VC_CAPSLOCK,  "kbd-capslock"),
 	KBD_LED_TRIGGER(VC_KANALOCK,  "kbd-kanalock"),
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4462d16..5ab54ef 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -750,6 +750,7 @@
 	vc->vc_complement_mask = 0;
 	vc->vc_can_do_color = 0;
 	vc->vc_panic_force_write = false;
+	vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
 	vc->vc_sw->con_init(vc, init);
 	if (!vc->vc_complement_mask)
 		vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
@@ -871,10 +872,15 @@
 	if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
 		return 0;
 
+	if (new_screen_size > (4 << 20))
+		return -EINVAL;
 	newscreen = kmalloc(new_screen_size, GFP_USER);
 	if (!newscreen)
 		return -ENOMEM;
 
+	if (vc == sel_cons)
+		clear_selection();
+
 	old_rows = vc->vc_rows;
 	old_row_size = vc->vc_size_row;
 
@@ -1172,7 +1178,7 @@
 			break;
 		case 3: /* erase scroll-back buffer (and whole display) */
 			scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
-				    vc->vc_screenbuf_size >> 1);
+				    vc->vc_screenbuf_size);
 			set_origin(vc);
 			if (CON_IS_VISIBLE(vc))
 				update_screen(vc);
@@ -3583,9 +3589,10 @@
 		goto err;
 
 	desc = csw->con_startup();
-
-	if (!desc)
+	if (!desc) {
+		retval = -ENODEV;
 		goto err;
+	}
 
 	retval = -EINVAL;
 
diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c
index 915facb..e1134a4 100644
--- a/drivers/uio/uio_dmem_genirq.c
+++ b/drivers/uio/uio_dmem_genirq.c
@@ -229,7 +229,7 @@
 		++uiomem;
 	}
 
-	priv->dmem_region_start = i;
+	priv->dmem_region_start = uiomem - &uioinfo->mem[0];
 	priv->num_dmem_regions = pdata->num_dynamic_regions;
 
 	for (i = 0; i < pdata->num_dynamic_regions; ++i) {
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 41d7cf6..858c308 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -428,9 +428,6 @@
 
 u8 hw_port_test_get(struct ci_hdrc *ci);
 
-int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
-				u32 value, unsigned int timeout_ms);
-
 void ci_platform_configure(struct ci_hdrc *ci);
 
 #endif	/* __DRIVERS_USB_CHIPIDEA_CI_H */
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 5a048b7..2949289 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -244,7 +244,6 @@
 	struct ci_hdrc_platform_data pdata = {
 		.name		= dev_name(&pdev->dev),
 		.capoffset	= DEF_CAPOFFSET,
-		.flags		= CI_HDRC_SET_NON_ZERO_TTHA,
 	};
 	int ret;
 	const struct of_device_id *of_id;
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 965d0e2..939c6ad 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -518,38 +518,6 @@
 	return 0;
 }
 
-/**
- * hw_wait_reg: wait the register value
- *
- * Sometimes, it needs to wait register value before going on.
- * Eg, when switch to device mode, the vbus value should be lower
- * than OTGSC_BSV before connects to host.
- *
- * @ci: the controller
- * @reg: register index
- * @mask: mast bit
- * @value: the bit value to wait
- * @timeout_ms: timeout in millisecond
- *
- * This function returns an error code if timeout
- */
-int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
-				u32 value, unsigned int timeout_ms)
-{
-	unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms);
-
-	while (hw_read(ci, reg, mask) != value) {
-		if (time_after(jiffies, elapse)) {
-			dev_err(ci->dev, "timeout waiting for %08x in %d\n",
-					mask, reg);
-			return -ETIMEDOUT;
-		}
-		msleep(20);
-	}
-
-	return 0;
-}
-
 static irqreturn_t ci_irq(int irq, void *data)
 {
 	struct ci_hdrc *ci = data;
@@ -926,6 +894,7 @@
 	if (!ci)
 		return -ENOMEM;
 
+	spin_lock_init(&ci->lock);
 	ci->dev = dev;
 	ci->platdata = dev_get_platdata(dev);
 	ci->imx28_write_fix = !!(ci->platdata->flags &
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index 58c8485..9233799 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -295,7 +295,8 @@
 {
 	struct ci_hdrc *ci = s->private;
 
-	seq_printf(s, "%s\n", ci_role(ci)->name);
+	if (ci->role != CI_ROLE_END)
+		seq_printf(s, "%s\n", ci_role(ci)->name);
 
 	return 0;
 }
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 03b6743..0cf149e 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -44,12 +44,15 @@
 		else
 			val &= ~OTGSC_BSVIS;
 
-		cable->changed = false;
-
 		if (cable->state)
 			val |= OTGSC_BSV;
 		else
 			val &= ~OTGSC_BSV;
+
+		if (cable->enabled)
+			val |= OTGSC_BSVIE;
+		else
+			val &= ~OTGSC_BSVIE;
 	}
 
 	cable = &ci->platdata->id_extcon;
@@ -59,15 +62,18 @@
 		else
 			val &= ~OTGSC_IDIS;
 
-		cable->changed = false;
-
 		if (cable->state)
 			val |= OTGSC_ID;
 		else
 			val &= ~OTGSC_ID;
+
+		if (cable->enabled)
+			val |= OTGSC_IDIE;
+		else
+			val &= ~OTGSC_IDIE;
 	}
 
-	return val;
+	return val & mask;
 }
 
 /**
@@ -77,6 +83,36 @@
  */
 void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data)
 {
+	struct ci_hdrc_cable *cable;
+
+	cable = &ci->platdata->vbus_extcon;
+	if (!IS_ERR(cable->edev)) {
+		if (data & mask & OTGSC_BSVIS)
+			cable->changed = false;
+
+		/* Don't enable vbus interrupt if using external notifier */
+		if (data & mask & OTGSC_BSVIE) {
+			cable->enabled = true;
+			data &= ~OTGSC_BSVIE;
+		} else if (mask & OTGSC_BSVIE) {
+			cable->enabled = false;
+		}
+	}
+
+	cable = &ci->platdata->id_extcon;
+	if (!IS_ERR(cable->edev)) {
+		if (data & mask & OTGSC_IDIS)
+			cable->changed = false;
+
+		/* Don't enable id interrupt if using external notifier */
+		if (data & mask & OTGSC_IDIE) {
+			cable->enabled = true;
+			data &= ~OTGSC_IDIE;
+		} else if (mask & OTGSC_IDIE) {
+			cable->enabled = false;
+		}
+	}
+
 	hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data);
 }
 
@@ -104,7 +140,31 @@
 		usb_gadget_vbus_disconnect(&ci->gadget);
 }
 
-#define CI_VBUS_STABLE_TIMEOUT_MS 5000
+/**
+ * When we switch to device mode, the vbus value should be lower
+ * than OTGSC_BSV before connecting to host.
+ *
+ * @ci: the controller
+ *
+ * This function returns an error code if timeout
+ */
+static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
+{
+	unsigned long elapse = jiffies + msecs_to_jiffies(5000);
+	u32 mask = OTGSC_BSV;
+
+	while (hw_read_otgsc(ci, mask)) {
+		if (time_after(jiffies, elapse)) {
+			dev_err(ci->dev, "timeout waiting for %08x in OTGSC\n",
+					mask);
+			return -ETIMEDOUT;
+		}
+		msleep(20);
+	}
+
+	return 0;
+}
+
 static void ci_handle_id_switch(struct ci_hdrc *ci)
 {
 	enum ci_role role = ci_otg_role(ci);
@@ -116,9 +176,11 @@
 		ci_role_stop(ci);
 
 		if (role == CI_ROLE_GADGET)
-			/* wait vbus lower than OTGSC_BSV */
-			hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
-					CI_VBUS_STABLE_TIMEOUT_MS);
+			/*
+			 * wait vbus lower than OTGSC_BSV before connecting
+			 * to host
+			 */
+			hw_wait_vbus_lower_bsv(ci);
 
 		ci_role_start(ci, role);
 	}
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 391a122..aff086c 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -939,6 +939,15 @@
 	int retval;
 	struct ci_hw_ep *hwep;
 
+	/*
+	 * Unexpected USB controller behavior, caused by bad signal integrity
+	 * or ground reference problems, can lead to isr_setup_status_phase
+	 * being called with ci->status equal to NULL.
+	 * If this situation occurs, you should review your USB hardware design.
+	 */
+	if (WARN_ON_ONCE(!ci->status))
+		return -EPIPE;
+
 	hwep = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in;
 	ci->status->context = ci;
 	ci->status->complete = isr_setup_status_complete;
@@ -1585,8 +1594,11 @@
 {
 	struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
 
-	/* Data+ pullup controlled by OTG state machine in OTG fsm mode */
-	if (ci_otg_is_fsm_mode(ci))
+	/*
+	 * Data+ pullup controlled by OTG state machine in OTG fsm mode;
+	 * and don't touch Data+ in host mode for dual role config.
+	 */
+	if (ci_otg_is_fsm_mode(ci) || ci->role == CI_ROLE_HOST)
 		return 0;
 
 	pm_runtime_get_sync(&ci->gadget.dev);
@@ -1872,8 +1884,6 @@
 	struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps;
 	int retval = 0;
 
-	spin_lock_init(&ci->lock);
-
 	ci->gadget.ops          = &usb_gadget_ops;
 	ci->gadget.speed        = USB_SPEED_UNKNOWN;
 	ci->gadget.max_speed    = USB_SPEED_HIGH;
@@ -1972,6 +1982,7 @@
 int ci_hdrc_gadget_init(struct ci_hdrc *ci)
 {
 	struct ci_role_driver *rdrv;
+	int ret;
 
 	if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC))
 		return -ENXIO;
@@ -1984,7 +1995,10 @@
 	rdrv->stop	= udc_id_switch_for_host;
 	rdrv->irq	= udc_irq;
 	rdrv->name	= "gadget";
-	ci->roles[CI_ROLE_GADGET] = rdrv;
 
-	return udc_start(ci);
+	ret = udc_start(ci);
+	if (!ret)
+		ci->roles[CI_ROLE_GADGET] = rdrv;
+
+	return ret;
 }
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index d37fdcc..0b71940 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -311,6 +311,12 @@
 		break;
 
 	case USB_CDC_NOTIFY_SERIAL_STATE:
+		if (le16_to_cpu(dr->wLength) != 2) {
+			dev_dbg(&acm->control->dev,
+				"%s - malformed serial state\n", __func__);
+			break;
+		}
+
 		newctrl = get_unaligned_le16(data);
 
 		if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
@@ -347,11 +353,10 @@
 
 	default:
 		dev_dbg(&acm->control->dev,
-			"%s - unknown notification %d received: index %d "
-			"len %d data0 %d data1 %d\n",
+			"%s - unknown notification %d received: index %d len %d\n",
 			__func__,
-			dr->bNotificationType, dr->wIndex,
-			dr->wLength, data[0], data[1]);
+			dr->bNotificationType, dr->wIndex, dr->wLength);
+
 		break;
 	}
 exit:
@@ -877,8 +882,6 @@
 	DECLARE_WAITQUEUE(wait, current);
 	struct async_icount old, new;
 
-	if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD ))
-		return -EINVAL;
 	do {
 		spin_lock_irq(&acm->read_lock);
 		old = acm->oldcount;
@@ -1336,7 +1339,6 @@
 	spin_lock_init(&acm->write_lock);
 	spin_lock_init(&acm->read_lock);
 	mutex_init(&acm->mutex);
-	acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
 	acm->is_int_ep = usb_endpoint_xfer_int(epread);
 	if (acm->is_int_ep)
 		acm->bInterval = epread->bInterval;
@@ -1376,14 +1378,14 @@
 		urb->transfer_dma = rb->dma;
 		if (acm->is_int_ep) {
 			usb_fill_int_urb(urb, acm->dev,
-					 acm->rx_endpoint,
+					 usb_rcvintpipe(usb_dev, epread->bEndpointAddress),
 					 rb->base,
 					 acm->readsize,
 					 acm_read_bulk_callback, rb,
 					 acm->bInterval);
 		} else {
 			usb_fill_bulk_urb(urb, acm->dev,
-					  acm->rx_endpoint,
+					  usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
 					  rb->base,
 					  acm->readsize,
 					  acm_read_bulk_callback, rb);
@@ -1711,6 +1713,7 @@
 	{ USB_DEVICE(0x20df, 0x0001), /* Simtec Electronics Entropy Key */
 	.driver_info = QUIRK_CONTROL_LINE_STATE, },
 	{ USB_DEVICE(0x2184, 0x001c) },	/* GW Instek AFG-2225 */
+	{ USB_DEVICE(0x2184, 0x0036) },	/* GW Instek AFG-125 */
 	{ USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
 	},
 	/* Motorola H24 HSPA module: */
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index ccfaba9..b30ac5f 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -95,7 +95,6 @@
 	struct urb *read_urbs[ACM_NR];
 	struct acm_rb read_buffers[ACM_NR];
 	int rx_buflimit;
-	int rx_endpoint;
 	spinlock_t read_lock;
 	int write_used;					/* number of non-empty write buffers */
 	int transmitting;
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 7a11a82..24337ac 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -121,6 +121,7 @@
 	struct usbtmc_device_data *data = to_usbtmc_data(kref);
 
 	usb_put_dev(data->usb_dev);
+	kfree(data);
 }
 
 static int usbtmc_open(struct inode *inode, struct file *filp)
@@ -1104,7 +1105,7 @@
 
 	dev_dbg(&intf->dev, "%s called\n", __func__);
 
-	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -1162,6 +1163,12 @@
 		}
 	}
 
+	if (!data->bulk_out || !data->bulk_in) {
+		dev_err(&intf->dev, "bulk endpoints not found\n");
+		retcode = -ENODEV;
+		goto err_put;
+	}
+
 	retcode = get_capabilities(data);
 	if (retcode)
 		dev_err(&intf->dev, "can't read capabilities\n");
@@ -1185,6 +1192,7 @@
 error_register:
 	sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
 	sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
+err_put:
 	kref_put(&data->kref, usbtmc_delete);
 	return retcode;
 }
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index 673d530..a00bfb9 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -50,6 +50,7 @@
 	[USB_SPEED_HIGH] = "high-speed",
 	[USB_SPEED_WIRELESS] = "wireless",
 	[USB_SPEED_SUPER] = "super-speed",
+	[USB_SPEED_SUPER_PLUS] = "super-speed-plus",
 };
 
 const char *usb_speed_string(enum usb_device_speed speed)
diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index 61d538a..4f4f06a 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -21,6 +21,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/mutex.h>
@@ -365,3 +366,4 @@
 	return state_changed;
 }
 EXPORT_SYMBOL_GPL(otg_statemachine);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 5050760..325cbc9 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -142,6 +142,31 @@
 	}
 }
 
+static const unsigned short low_speed_maxpacket_maxes[4] = {
+	[USB_ENDPOINT_XFER_CONTROL] = 8,
+	[USB_ENDPOINT_XFER_ISOC] = 0,
+	[USB_ENDPOINT_XFER_BULK] = 0,
+	[USB_ENDPOINT_XFER_INT] = 8,
+};
+static const unsigned short full_speed_maxpacket_maxes[4] = {
+	[USB_ENDPOINT_XFER_CONTROL] = 64,
+	[USB_ENDPOINT_XFER_ISOC] = 1023,
+	[USB_ENDPOINT_XFER_BULK] = 64,
+	[USB_ENDPOINT_XFER_INT] = 64,
+};
+static const unsigned short high_speed_maxpacket_maxes[4] = {
+	[USB_ENDPOINT_XFER_CONTROL] = 64,
+	[USB_ENDPOINT_XFER_ISOC] = 1024,
+	[USB_ENDPOINT_XFER_BULK] = 512,
+	[USB_ENDPOINT_XFER_INT] = 1024,
+};
+static const unsigned short super_speed_maxpacket_maxes[4] = {
+	[USB_ENDPOINT_XFER_CONTROL] = 512,
+	[USB_ENDPOINT_XFER_ISOC] = 1024,
+	[USB_ENDPOINT_XFER_BULK] = 1024,
+	[USB_ENDPOINT_XFER_INT] = 1024,
+};
+
 static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
     int asnum, struct usb_host_interface *ifp, int num_ep,
     unsigned char *buffer, int size)
@@ -150,6 +175,8 @@
 	struct usb_endpoint_descriptor *d;
 	struct usb_host_endpoint *endpoint;
 	int n, i, j, retval;
+	unsigned int maxp;
+	const unsigned short *maxpacket_maxes;
 
 	d = (struct usb_endpoint_descriptor *) buffer;
 	buffer += d->bLength;
@@ -178,32 +205,57 @@
 	if (ifp->desc.bNumEndpoints >= num_ep)
 		goto skip_to_next_endpoint_or_interface_descriptor;
 
+	/* Check for duplicate endpoint addresses */
+	for (i = 0; i < ifp->desc.bNumEndpoints; ++i) {
+		if (ifp->endpoint[i].desc.bEndpointAddress ==
+		    d->bEndpointAddress) {
+			dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
+			    cfgno, inum, asnum, d->bEndpointAddress);
+			goto skip_to_next_endpoint_or_interface_descriptor;
+		}
+	}
+
 	endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
 	++ifp->desc.bNumEndpoints;
 
 	memcpy(&endpoint->desc, d, n);
 	INIT_LIST_HEAD(&endpoint->urb_list);
 
-	/* Fix up bInterval values outside the legal range. Use 32 ms if no
-	 * proper value can be guessed. */
+	/*
+	 * Fix up bInterval values outside the legal range.
+	 * Use 10 or 8 ms if no proper value can be guessed.
+	 */
 	i = 0;		/* i = min, j = max, n = default */
 	j = 255;
 	if (usb_endpoint_xfer_int(d)) {
 		i = 1;
 		switch (to_usb_device(ddev)->speed) {
+		case USB_SPEED_SUPER_PLUS:
 		case USB_SPEED_SUPER:
 		case USB_SPEED_HIGH:
-			/* Many device manufacturers are using full-speed
+			/*
+			 * Many device manufacturers are using full-speed
 			 * bInterval values in high-speed interrupt endpoint
-			 * descriptors. Try to fix those and fall back to a
-			 * 32 ms default value otherwise. */
+			 * descriptors. Try to fix those and fall back to an
+			 * 8-ms default value otherwise.
+			 */
 			n = fls(d->bInterval*8);
 			if (n == 0)
-				n = 9;	/* 32 ms = 2^(9-1) uframes */
+				n = 7;	/* 8 ms = 2^(7-1) uframes */
 			j = 16;
 
 			/*
 			 * Adjust bInterval for quirked devices.
+			 */
+			/*
+			 * This quirk fixes bIntervals reported in ms.
+			 */
+			if (to_usb_device(ddev)->quirks &
+				USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) {
+				n = clamp(fls(d->bInterval) + 3, i, j);
+				i = j = n;
+			}
+			/*
 			 * This quirk fixes bIntervals reported in
 			 * linear microframes.
 			 */
@@ -214,10 +266,12 @@
 			}
 			break;
 		default:		/* USB_SPEED_FULL or _LOW */
-			/* For low-speed, 10 ms is the official minimum.
+			/*
+			 * For low-speed, 10 ms is the official minimum.
 			 * But some "overclocked" devices might want faster
-			 * polling so we'll allow it. */
-			n = 32;
+			 * polling so we'll allow it.
+			 */
+			n = 10;
 			break;
 		}
 	} else if (usb_endpoint_xfer_isoc(d)) {
@@ -225,10 +279,10 @@
 		j = 16;
 		switch (to_usb_device(ddev)->speed) {
 		case USB_SPEED_HIGH:
-			n = 9;		/* 32 ms = 2^(9-1) uframes */
+			n = 7;		/* 8 ms = 2^(7-1) uframes */
 			break;
 		default:		/* USB_SPEED_FULL */
-			n = 6;		/* 32 ms = 2^(6-1) frames */
+			n = 4;		/* 8 ms = 2^(4-1) frames */
 			break;
 		}
 	}
@@ -256,6 +310,42 @@
 			endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
 	}
 
+	/* Validate the wMaxPacketSize field */
+	maxp = usb_endpoint_maxp(&endpoint->desc);
+
+	/* Find the highest legal maxpacket size for this endpoint */
+	i = 0;		/* additional transactions per microframe */
+	switch (to_usb_device(ddev)->speed) {
+	case USB_SPEED_LOW:
+		maxpacket_maxes = low_speed_maxpacket_maxes;
+		break;
+	case USB_SPEED_FULL:
+		maxpacket_maxes = full_speed_maxpacket_maxes;
+		break;
+	case USB_SPEED_HIGH:
+		/* Bits 12..11 are allowed only for HS periodic endpoints */
+		if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) {
+			i = maxp & (BIT(12) | BIT(11));
+			maxp &= ~i;
+		}
+		/* fallthrough */
+	default:
+		maxpacket_maxes = high_speed_maxpacket_maxes;
+		break;
+	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
+		maxpacket_maxes = super_speed_maxpacket_maxes;
+		break;
+	}
+	j = maxpacket_maxes[usb_endpoint_type(&endpoint->desc)];
+
+	if (maxp > j) {
+		dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid maxpacket %d, setting to %d\n",
+		    cfgno, inum, asnum, d->bEndpointAddress, maxp, j);
+		maxp = j;
+		endpoint->desc.wMaxPacketSize = cpu_to_le16(i | maxp);
+	}
+
 	/*
 	 * Some buggy high speed devices have bulk endpoints using
 	 * maxpacket sizes other than 512.  High speed HCDs may not
@@ -263,9 +353,6 @@
 	 */
 	if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
 			&& usb_endpoint_xfer_bulk(d)) {
-		unsigned maxp;
-
-		maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff;
 		if (maxp != 512)
 			dev_warn(ddev, "config %d interface %d altsetting %d "
 				"bulk endpoint 0x%X has invalid maxpacket %d\n",
@@ -274,7 +361,7 @@
 	}
 
 	/* Parse a possible SuperSpeed endpoint companion descriptor */
-	if (to_usb_device(ddev)->speed == USB_SPEED_SUPER)
+	if (to_usb_device(ddev)->speed >= USB_SPEED_SUPER)
 		usb_parse_ss_endpoint_companion(ddev, cfgno,
 				inum, asnum, endpoint, buffer, size);
 
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 2a3bbdf..332ed27 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -221,7 +221,7 @@
 		break;
 	case USB_ENDPOINT_XFER_INT:
 		type = "Int.";
-		if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER)
+		if (speed == USB_SPEED_HIGH || speed >= USB_SPEED_SUPER)
 			interval = 1 << (desc->bInterval - 1);
 		else
 			interval = desc->bInterval;
@@ -230,7 +230,7 @@
 		return start;
 	}
 	interval *= (speed == USB_SPEED_HIGH ||
-		     speed == USB_SPEED_SUPER) ? 125 : 1000;
+		     speed >= USB_SPEED_SUPER) ? 125 : 1000;
 	if (interval % 1000)
 		unit = 'u';
 	else {
@@ -322,7 +322,7 @@
 
 	if (start > end)
 		return start;
-	if (speed == USB_SPEED_SUPER)
+	if (speed >= USB_SPEED_SUPER)
 		mul = 8;
 	else
 		mul = 2;
@@ -534,6 +534,8 @@
 		speed = "480"; break;
 	case USB_SPEED_SUPER:
 		speed = "5000"; break;
+	case USB_SPEED_SUPER_PLUS:
+		speed = "10000"; break;
 	default:
 		speed = "??";
 	}
@@ -553,7 +555,7 @@
 
 		/* super/high speed reserves 80%, full/low reserves 90% */
 		if (usbdev->speed == USB_SPEED_HIGH ||
-		    usbdev->speed == USB_SPEED_SUPER)
+		    usbdev->speed >= USB_SPEED_SUPER)
 			max = 800;
 		else
 			max = FRAME_TIME_MAX_USECS_ALLOC;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 3ffb01f..54d2d6b 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -373,11 +373,11 @@
 
 	if (userurb) {		/* Async */
 		if (when == SUBMIT)
-			dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
+			dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
 					"length %u\n",
 					userurb, ep, t, d, length);
 		else
-			dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
+			dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
 					"actual_length %u status %d\n",
 					userurb, ep, t, d, length,
 					timeout_or_status);
@@ -1530,11 +1530,17 @@
 	as->urb->start_frame = uurb->start_frame;
 	as->urb->number_of_packets = number_of_packets;
 	as->urb->stream_id = stream_id;
-	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
-			ps->dev->speed == USB_SPEED_HIGH)
-		as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
-	else
-		as->urb->interval = ep->desc.bInterval;
+
+	if (ep->desc.bInterval) {
+		if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
+				ps->dev->speed == USB_SPEED_HIGH ||
+				ps->dev->speed >= USB_SPEED_SUPER)
+			as->urb->interval = 1 <<
+					min(15, ep->desc.bInterval - 1);
+		else
+			as->urb->interval = ep->desc.bInterval;
+	}
+
 	as->urb->context = as;
 	as->urb->complete = async_completed;
 	for (totlen = u = 0; u < number_of_packets; u++) {
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 2057d91..0bb380a 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -284,7 +284,7 @@
 	struct usb_device *udev = interface_to_usbdev(intf);
 	const struct usb_device_id *id;
 	int error = -ENODEV;
-	int lpm_disable_error;
+	int lpm_disable_error = -ENODEV;
 
 	dev_dbg(dev, "%s\n", __func__);
 
@@ -336,12 +336,14 @@
 	 * setting during probe, that should also be fine.  usb_set_interface()
 	 * will attempt to disable LPM, and fail if it can't disable it.
 	 */
-	lpm_disable_error = usb_unlocked_disable_lpm(udev);
-	if (lpm_disable_error && driver->disable_hub_initiated_lpm) {
-		dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.",
-				__func__, driver->name);
-		error = lpm_disable_error;
-		goto err;
+	if (driver->disable_hub_initiated_lpm) {
+		lpm_disable_error = usb_unlocked_disable_lpm(udev);
+		if (lpm_disable_error) {
+			dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.",
+					__func__, driver->name);
+			error = lpm_disable_error;
+			goto err;
+		}
 	}
 
 	/* Carry out a deferred switch to altsetting 0 */
@@ -391,7 +393,8 @@
 	struct usb_interface *intf = to_usb_interface(dev);
 	struct usb_host_endpoint *ep, **eps = NULL;
 	struct usb_device *udev;
-	int i, j, error, r, lpm_disable_error;
+	int i, j, error, r;
+	int lpm_disable_error = -ENODEV;
 
 	intf->condition = USB_INTERFACE_UNBINDING;
 
@@ -399,12 +402,13 @@
 	udev = interface_to_usbdev(intf);
 	error = usb_autoresume_device(udev);
 
-	/* Hub-initiated LPM policy may change, so attempt to disable LPM until
+	/* If hub-initiated LPM policy may change, attempt to disable LPM until
 	 * the driver is unbound.  If LPM isn't disabled, that's fine because it
 	 * wouldn't be enabled unless all the bound interfaces supported
 	 * hub-initiated LPM.
 	 */
-	lpm_disable_error = usb_unlocked_disable_lpm(udev);
+	if (driver->disable_hub_initiated_lpm)
+		lpm_disable_error = usb_unlocked_disable_lpm(udev);
 
 	/*
 	 * Terminate all URBs for this interface unless the driver
@@ -505,7 +509,7 @@
 	struct device *dev;
 	struct usb_device *udev;
 	int retval = 0;
-	int lpm_disable_error;
+	int lpm_disable_error = -ENODEV;
 
 	if (!iface)
 		return -ENODEV;
@@ -526,12 +530,14 @@
 
 	iface->condition = USB_INTERFACE_BOUND;
 
-	/* Disable LPM until this driver is bound. */
-	lpm_disable_error = usb_unlocked_disable_lpm(udev);
-	if (lpm_disable_error && driver->disable_hub_initiated_lpm) {
-		dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.",
-				__func__, driver->name);
-		return -ENOMEM;
+	/* See the comment about disabling LPM in usb_probe_interface(). */
+	if (driver->disable_hub_initiated_lpm) {
+		lpm_disable_error = usb_unlocked_disable_lpm(udev);
+		if (lpm_disable_error) {
+			dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.",
+					__func__, driver->name);
+			return -ENOMEM;
+		}
 	}
 
 	/* Claimed interfaces are initially inactive (suspended) and
@@ -1322,6 +1328,24 @@
 		 */
 		if (udev->parent && !PMSG_IS_AUTO(msg))
 			status = 0;
+
+		/*
+		 * If the device is inaccessible, don't try to resume
+		 * suspended interfaces and just return the error.
+		 */
+		if (status && status != -EBUSY) {
+			int err;
+			u16 devstat;
+
+			err = usb_get_status(udev, USB_RECIP_DEVICE, 0,
+					     &devstat);
+			if (err) {
+				dev_err(&udev->dev,
+					"Failed to suspend device, error %d\n",
+					status);
+				goto done;
+			}
+		}
 	}
 
 	/* If the suspend failed, resume interfaces that did get suspended */
@@ -1754,6 +1778,9 @@
 	int			w, i;
 	struct usb_interface	*intf;
 
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return -ENODEV;
+
 	/* Fail if autosuspend is disabled, or any interfaces are in use, or
 	 * any interface drivers require remote wakeup but it isn't available.
 	 */
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index ea337a7..b3de806 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -26,6 +26,7 @@
 #define MAX_USB_MINORS	256
 static const struct file_operations *usb_minors[MAX_USB_MINORS];
 static DECLARE_RWSEM(minor_rwsem);
+static DEFINE_MUTEX(init_usb_class_mutex);
 
 static int usb_open(struct inode *inode, struct file *file)
 {
@@ -108,8 +109,9 @@
 
 static void destroy_usb_class(void)
 {
-	if (usb_class)
-		kref_put(&usb_class->kref, release_usb_class);
+	mutex_lock(&init_usb_class_mutex);
+	kref_put(&usb_class->kref, release_usb_class);
+	mutex_unlock(&init_usb_class_mutex);
 }
 
 int usb_major_init(void)
@@ -171,7 +173,10 @@
 	if (intf->minor >= 0)
 		return -EADDRINUSE;
 
+	mutex_lock(&init_usb_class_mutex);
 	retval = init_usb_class();
+	mutex_unlock(&init_usb_class_mutex);
+
 	if (retval)
 		return retval;
 
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index b8b580e..4037848 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -206,7 +206,7 @@
 	 * The xHCI driver has its own irq management
 	 * make sure irq setup is not touched for xhci in generic hcd code
 	 */
-	if ((driver->flags & HCD_MASK) != HCD_USB3) {
+	if ((driver->flags & HCD_MASK) < HCD_USB3) {
 		if (!dev->irq) {
 			dev_err(&dev->dev,
 			"Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 1c102d6..b403596 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -499,8 +499,10 @@
 	 */
 	tbuf_size =  max_t(u16, sizeof(struct usb_hub_descriptor), wLength);
 	tbuf = kzalloc(tbuf_size, GFP_KERNEL);
-	if (!tbuf)
-		return -ENOMEM;
+	if (!tbuf) {
+		status = -ENOMEM;
+		goto err_alloc;
+	}
 
 	bufp = tbuf;
 
@@ -705,6 +707,7 @@
 	}
 
 	kfree(tbuf);
+ err_alloc:
 
 	/* any errors get returned through the urb completion */
 	spin_lock_irq(&hcd_root_hub_lock);
@@ -966,7 +969,7 @@
 	bus->bandwidth_allocated = 0;
 	bus->bandwidth_int_reqs  = 0;
 	bus->bandwidth_isoc_reqs = 0;
-	mutex_init(&bus->usb_address0_mutex);
+	mutex_init(&bus->devnum_next_mutex);
 
 	INIT_LIST_HEAD (&bus->bus_list);
 }
@@ -1078,7 +1081,7 @@
 		retval = usb_get_bos_descriptor(usb_dev);
 		if (!retval) {
 			usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev);
-		} else if (usb_dev->speed == USB_SPEED_SUPER) {
+		} else if (usb_dev->speed >= USB_SPEED_SUPER) {
 			mutex_unlock(&usb_bus_list_lock);
 			dev_dbg(parent_dev, "can't read %s bos descriptor %d\n",
 					dev_name(&usb_dev->dev), retval);
@@ -1693,7 +1696,7 @@
 		if (retval == 0)
 			retval = -EINPROGRESS;
 		else if (retval != -EIDRM && retval != -EBUSY)
-			dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n",
+			dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n",
 					urb, retval);
 		usb_put_dev(udev);
 	}
@@ -1860,7 +1863,7 @@
 		/* kick hcd */
 		unlink1(hcd, urb, -ESHUTDOWN);
 		dev_dbg (hcd->self.controller,
-			"shutdown urb %p ep%d%s%s\n",
+			"shutdown urb %pK ep%d%s%s\n",
 			urb, usb_endpoint_num(&ep->desc),
 			is_in ? "in" : "out",
 			({	char *s;
@@ -2112,7 +2115,7 @@
 	hcd = bus_to_hcd(dev->bus);
 	if (!hcd->driver->alloc_streams || !hcd->driver->free_streams)
 		return -EINVAL;
-	if (dev->speed != USB_SPEED_SUPER)
+	if (dev->speed < USB_SPEED_SUPER)
 		return -EINVAL;
 	if (dev->state < USB_STATE_CONFIGURED)
 		return -ENODEV;
@@ -2160,7 +2163,7 @@
 
 	dev = interface_to_usbdev(interface);
 	hcd = bus_to_hcd(dev->bus);
-	if (dev->speed != USB_SPEED_SUPER)
+	if (dev->speed < USB_SPEED_SUPER)
 		return -EINVAL;
 
 	/* Double-free is not allowed */
@@ -2497,9 +2500,18 @@
 		return NULL;
 	}
 	if (primary_hcd == NULL) {
+		hcd->address0_mutex = kmalloc(sizeof(*hcd->address0_mutex),
+				GFP_KERNEL);
+		if (!hcd->address0_mutex) {
+			kfree(hcd);
+			dev_dbg(dev, "hcd address0 mutex alloc failed\n");
+			return NULL;
+		}
+		mutex_init(hcd->address0_mutex);
 		hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex),
 				GFP_KERNEL);
 		if (!hcd->bandwidth_mutex) {
+			kfree(hcd->address0_mutex);
 			kfree(hcd);
 			dev_dbg(dev, "hcd bandwidth mutex alloc failed\n");
 			return NULL;
@@ -2508,6 +2520,7 @@
 		dev_set_drvdata(dev, hcd);
 	} else {
 		mutex_lock(&usb_port_peer_mutex);
+		hcd->address0_mutex = primary_hcd->address0_mutex;
 		hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex;
 		hcd->primary_hcd = primary_hcd;
 		primary_hcd->primary_hcd = primary_hcd;
@@ -2564,24 +2577,23 @@
  * Don't deallocate the bandwidth_mutex until the last shared usb_hcd is
  * deallocated.
  *
- * Make sure to only deallocate the bandwidth_mutex when the primary HCD is
- * freed.  When hcd_release() is called for either hcd in a peer set
- * invalidate the peer's ->shared_hcd and ->primary_hcd pointers to
- * block new peering attempts
+ * Make sure to deallocate the bandwidth_mutex only when the last HCD is
+ * freed.  When hcd_release() is called for either hcd in a peer set,
+ * invalidate the peer's ->shared_hcd and ->primary_hcd pointers.
  */
 static void hcd_release(struct kref *kref)
 {
 	struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
 
 	mutex_lock(&usb_port_peer_mutex);
-	if (usb_hcd_is_primary_hcd(hcd))
-		kfree(hcd->bandwidth_mutex);
 	if (hcd->shared_hcd) {
 		struct usb_hcd *peer = hcd->shared_hcd;
 
 		peer->shared_hcd = NULL;
-		if (peer->primary_hcd == hcd)
-			peer->primary_hcd = NULL;
+		peer->primary_hcd = NULL;
+	} else {
+		kfree(hcd->address0_mutex);
+		kfree(hcd->bandwidth_mutex);
 	}
 	mutex_unlock(&usb_port_peer_mutex);
 	kfree(hcd);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 84df093..1d59d48 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -101,6 +101,7 @@
 
 static void hub_release(struct kref *kref);
 static int usb_reset_and_verify_device(struct usb_device *udev);
+static int hub_port_disable(struct usb_hub *hub, int port1, int set_state);
 
 static inline char *portspeed(struct usb_hub *hub, int portstatus)
 {
@@ -298,7 +299,7 @@
 	unsigned int hub_u1_del;
 	unsigned int hub_u2_del;
 
-	if (!udev->lpm_capable || udev->speed != USB_SPEED_SUPER)
+	if (!udev->lpm_capable || udev->speed < USB_SPEED_SUPER)
 		return;
 
 	hub = usb_hub_to_struct_hub(udev->parent);
@@ -357,7 +358,8 @@
 }
 
 /* USB 2.0 spec Section 11.24.4.5 */
-static int get_hub_descriptor(struct usb_device *hdev, void *data)
+static int get_hub_descriptor(struct usb_device *hdev,
+		struct usb_hub_descriptor *desc)
 {
 	int i, ret, size;
 	unsigned dtype;
@@ -373,10 +375,18 @@
 	for (i = 0; i < 3; i++) {
 		ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
 			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
-			dtype << 8, 0, data, size,
+			dtype << 8, 0, desc, size,
 			USB_CTRL_GET_TIMEOUT);
-		if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2))
+		if (hub_is_superspeed(hdev)) {
+			if (ret == size)
+				return ret;
+		} else if (ret >= USB_DT_HUB_NONVAR_SIZE + 2) {
+			/* Make sure we have the DeviceRemovable field. */
+			size = USB_DT_HUB_NONVAR_SIZE + desc->bNbrPorts / 8 + 1;
+			if (ret < size)
+				return -EMSGSIZE;
 			return ret;
+		}
 	}
 	return -EINVAL;
 }
@@ -883,88 +893,6 @@
 }
 
 /*
- * If USB 3.0 ports are placed into the Disabled state, they will no longer
- * detect any device connects or disconnects.  This is generally not what the
- * USB core wants, since it expects a disabled port to produce a port status
- * change event when a new device connects.
- *
- * Instead, set the link state to Disabled, wait for the link to settle into
- * that state, clear any change bits, and then put the port into the RxDetect
- * state.
- */
-static int hub_usb3_port_disable(struct usb_hub *hub, int port1)
-{
-	int ret;
-	int total_time;
-	u16 portchange, portstatus;
-
-	if (!hub_is_superspeed(hub->hdev))
-		return -EINVAL;
-
-	ret = hub_port_status(hub, port1, &portstatus, &portchange);
-	if (ret < 0)
-		return ret;
-
-	/*
-	 * USB controller Advanced Micro Devices, Inc. [AMD] FCH USB XHCI
-	 * Controller [1022:7814] will have spurious result making the following
-	 * usb 3.0 device hotplugging route to the 2.0 root hub and recognized
-	 * as high-speed device if we set the usb 3.0 port link state to
-	 * Disabled. Since it's already in USB_SS_PORT_LS_RX_DETECT state, we
-	 * check the state here to avoid the bug.
-	 */
-	if ((portstatus & USB_PORT_STAT_LINK_STATE) ==
-				USB_SS_PORT_LS_RX_DETECT) {
-		dev_dbg(&hub->ports[port1 - 1]->dev,
-			 "Not disabling port; link state is RxDetect\n");
-		return ret;
-	}
-
-	ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED);
-	if (ret)
-		return ret;
-
-	/* Wait for the link to enter the disabled state. */
-	for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
-		ret = hub_port_status(hub, port1, &portstatus, &portchange);
-		if (ret < 0)
-			return ret;
-
-		if ((portstatus & USB_PORT_STAT_LINK_STATE) ==
-				USB_SS_PORT_LS_SS_DISABLED)
-			break;
-		if (total_time >= HUB_DEBOUNCE_TIMEOUT)
-			break;
-		msleep(HUB_DEBOUNCE_STEP);
-	}
-	if (total_time >= HUB_DEBOUNCE_TIMEOUT)
-		dev_warn(&hub->ports[port1 - 1]->dev,
-				"Could not disable after %d ms\n", total_time);
-
-	return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT);
-}
-
-static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
-{
-	struct usb_port *port_dev = hub->ports[port1 - 1];
-	struct usb_device *hdev = hub->hdev;
-	int ret = 0;
-
-	if (port_dev->child && set_state)
-		usb_set_device_state(port_dev->child, USB_STATE_NOTATTACHED);
-	if (!hub->error) {
-		if (hub_is_superspeed(hub->hdev))
-			ret = hub_usb3_port_disable(hub, port1);
-		else
-			ret = usb_clear_port_feature(hdev, port1,
-					USB_PORT_FEAT_ENABLE);
-	}
-	if (ret && ret != -ENODEV)
-		dev_err(&port_dev->dev, "cannot disable (err = %d)\n", ret);
-	return ret;
-}
-
-/*
  * Disable a port and mark a logical connect-change event, so that some
  * time later hub_wq will disconnect() any existing usb_device on the port
  * and will re-enumerate if there actually is a device attached.
@@ -1036,14 +964,11 @@
 
 	/* Continue a partial initialization */
 	if (type == HUB_INIT2 || type == HUB_INIT3) {
-		device_lock(hub->intfdev);
+		device_lock(&hdev->dev);
 
 		/* Was the hub disconnected while we were waiting? */
-		if (hub->disconnected) {
-			device_unlock(hub->intfdev);
-			kref_put(&hub->kref, hub_release);
-			return;
-		}
+		if (hub->disconnected)
+			goto disconnected;
 		if (type == HUB_INIT2)
 			goto init2;
 		goto init3;
@@ -1132,6 +1057,9 @@
 
 		portstatus = portchange = 0;
 		status = hub_port_status(hub, port1, &portstatus, &portchange);
+		if (status)
+			goto abort;
+
 		if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
 			dev_dbg(&port_dev->dev, "status %04x change %04x\n",
 					portstatus, portchange);
@@ -1246,7 +1174,7 @@
 			queue_delayed_work(system_power_efficient_wq,
 					&hub->init_work,
 					msecs_to_jiffies(delay));
-			device_unlock(hub->intfdev);
+			device_unlock(&hdev->dev);
 			return;		/* Continues at init3: below */
 		} else {
 			msleep(delay);
@@ -1264,13 +1192,13 @@
 
 	/* Scan all ports that need attention */
 	kick_hub_wq(hub);
-
-	/* Allow autosuspend if it was suppressed */
-	if (type <= HUB_INIT3)
+ abort:
+	if (type == HUB_INIT2 || type == HUB_INIT3) {
+		/* Allow autosuspend if it was suppressed */
+ disconnected:
 		usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
-
-	if (type == HUB_INIT2 || type == HUB_INIT3)
-		device_unlock(hub->intfdev);
+		device_unlock(&hdev->dev);
+	}
 
 	kref_put(&hub->kref, hub_release);
 }
@@ -1299,8 +1227,6 @@
 	struct usb_device *hdev = hub->hdev;
 	int i;
 
-	cancel_delayed_work_sync(&hub->init_work);
-
 	/* hub_wq and related activity won't re-trigger */
 	hub->quiescing = 1;
 
@@ -1378,7 +1304,7 @@
 	}
 	mutex_init(&hub->status_mutex);
 
-	hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
+	hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL);
 	if (!hub->descriptor) {
 		ret = -ENOMEM;
 		goto fail;
@@ -1386,13 +1312,19 @@
 
 	/* Request the entire hub descriptor.
 	 * hub->descriptor can handle USB_MAXCHILDREN ports,
-	 * but the hub can/will return fewer bytes here.
+	 * but a (non-SS) hub can/will return fewer bytes here.
 	 */
 	ret = get_hub_descriptor(hdev, hub->descriptor);
 	if (ret < 0) {
 		message = "can't read hub descriptor";
 		goto fail;
-	} else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) {
+	}
+
+	maxchild = USB_MAXCHILDREN;
+	if (hub_is_superspeed(hdev))
+		maxchild = min_t(unsigned, maxchild, USB_SS_MAXPORTS);
+
+	if (hub->descriptor->bNbrPorts > maxchild) {
 		message = "hub has too many ports!";
 		ret = -ENODEV;
 		goto fail;
@@ -2066,7 +1998,7 @@
 	struct usb_bus	*bus = udev->bus;
 
 	/* be safe when more hub events are proceed in parallel */
-	mutex_lock(&bus->usb_address0_mutex);
+	mutex_lock(&bus->devnum_next_mutex);
 	if (udev->wusb) {
 		devnum = udev->portnum + 1;
 		BUG_ON(test_bit(devnum, bus->devmap.devicemap));
@@ -2084,7 +2016,7 @@
 		set_bit(devnum, bus->devmap.devicemap);
 		udev->devnum = devnum;
 	}
-	mutex_unlock(&bus->usb_address0_mutex);
+	mutex_unlock(&bus->devnum_next_mutex);
 }
 
 static void release_devnum(struct usb_device *udev)
@@ -2154,6 +2086,12 @@
 	dev_info(&udev->dev, "USB disconnect, device number %d\n",
 			udev->devnum);
 
+	/*
+	 * Ensure that the pm runtime code knows that the USB device
+	 * is in the process of being disconnected.
+	 */
+	pm_runtime_barrier(&udev->dev);
+
 	usb_lock_device(udev);
 
 	hub_disconnect_children(udev);
@@ -2645,7 +2583,7 @@
  */
 static bool use_new_scheme(struct usb_device *udev, int retry)
 {
-	if (udev->speed == USB_SPEED_SUPER)
+	if (udev->speed >= USB_SPEED_SUPER)
 		return false;
 
 	return USE_NEW_SCHEME(retry);
@@ -2688,8 +2626,15 @@
 		if (ret < 0)
 			return ret;
 
-		/* The port state is unknown until the reset completes. */
-		if (!(portstatus & USB_PORT_STAT_RESET))
+		/*
+		 * The port state is unknown until the reset completes.
+		 *
+		 * On top of that, some chips may require additional time
+		 * to re-establish a connection after the reset is complete,
+		 * so also wait for the connection to be re-established.
+		 */
+		if (!(portstatus & USB_PORT_STAT_RESET) &&
+		    (portstatus & USB_PORT_STAT_CONNECTION))
 			break;
 
 		/* switch to the long delay after two short delay failures */
@@ -3985,7 +3930,7 @@
 	struct usb_hcd *hcd;
 
 	if (!udev || !udev->parent ||
-			udev->speed != USB_SPEED_SUPER ||
+			udev->speed < USB_SPEED_SUPER ||
 			!udev->lpm_capable ||
 			udev->state < USB_STATE_DEFAULT)
 		return 0;
@@ -4042,7 +3987,7 @@
 	struct usb_hcd *hcd;
 
 	if (!udev || !udev->parent ||
-			udev->speed != USB_SPEED_SUPER ||
+			udev->speed < USB_SPEED_SUPER ||
 			!udev->lpm_capable ||
 			udev->state < USB_STATE_DEFAULT)
 		return;
@@ -4078,6 +4023,26 @@
 }
 EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm);
 
+/* usb3 devices use U3 for disabled, make sure remote wakeup is disabled */
+static void hub_usb3_port_prepare_disable(struct usb_hub *hub,
+					  struct usb_port *port_dev)
+{
+	struct usb_device *udev = port_dev->child;
+	int ret;
+
+	if (udev && udev->port_is_suspended && udev->do_remote_wakeup) {
+		ret = hub_set_port_link_state(hub, port_dev->portnum,
+					      USB_SS_PORT_LS_U0);
+		if (!ret) {
+			msleep(USB_RESUME_TIMEOUT);
+			ret = usb_disable_remote_wakeup(udev);
+		}
+		if (ret)
+			dev_warn(&udev->dev,
+				 "Port disable: can't disable remote wake\n");
+		udev->do_remote_wakeup = 0;
+	}
+}
 
 #else	/* CONFIG_PM */
 
@@ -4085,6 +4050,9 @@
 #define hub_resume		NULL
 #define hub_reset_resume	NULL
 
+static inline void hub_usb3_port_prepare_disable(struct usb_hub *hub,
+						 struct usb_port *port_dev) { }
+
 int usb_disable_lpm(struct usb_device *udev)
 {
 	return 0;
@@ -4120,6 +4088,34 @@
 
 #endif	/* CONFIG_PM */
 
+/*
+ * USB-3 does not have a similar link state as USB-2 that will avoid negotiating
+ * a connection with a plugged-in cable but will signal the host when the cable
+ * is unplugged. Disable remote wake and set link state to U3 for USB-3 devices
+ */
+static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
+{
+	struct usb_port *port_dev = hub->ports[port1 - 1];
+	struct usb_device *hdev = hub->hdev;
+	int ret = 0;
+
+	if (!hub->error) {
+		if (hub_is_superspeed(hub->hdev)) {
+			hub_usb3_port_prepare_disable(hub, port_dev);
+			ret = hub_set_port_link_state(hub, port_dev->portnum,
+						      USB_SS_PORT_LS_U3);
+		} else {
+			ret = usb_clear_port_feature(hdev, port1,
+					USB_PORT_FEAT_ENABLE);
+		}
+	}
+	if (port_dev->child && set_state)
+		usb_set_device_state(port_dev->child, USB_STATE_NOTATTACHED);
+	if (ret && ret != -ENODEV)
+		dev_err(&port_dev->dev, "cannot disable (err = %d)\n", ret);
+	return ret;
+}
+
 
 /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
  *
@@ -4234,7 +4230,7 @@
 	struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
 	int connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;
 
-	if (!udev->usb2_hw_lpm_capable)
+	if (!udev->usb2_hw_lpm_capable || !udev->bos)
 		return;
 
 	if (hub)
@@ -4297,7 +4293,7 @@
 	if (oldspeed == USB_SPEED_LOW)
 		delay = HUB_LONG_RESET_TIME;
 
-	mutex_lock(&hdev->bus->usb_address0_mutex);
+	mutex_lock(hcd->address0_mutex);
 
 	/* Reset the device; full speed may morph to high speed */
 	/* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */
@@ -4308,7 +4304,9 @@
 
 	retval = -ENODEV;
 
-	if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) {
+	/* Don't allow speed changes at reset, except usb 3.0 to faster */
+	if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed &&
+	    !(oldspeed == USB_SPEED_SUPER && udev->speed > oldspeed)) {
 		dev_dbg(&udev->dev, "device reset changed speed!\n");
 		goto fail;
 	}
@@ -4320,6 +4318,7 @@
 	 * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
 	 */
 	switch (udev->speed) {
+	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_SUPER:
 	case USB_SPEED_WIRELESS:	/* fixed at 512 */
 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
@@ -4346,7 +4345,7 @@
 	else
 		speed = usb_speed_string(udev->speed);
 
-	if (udev->speed != USB_SPEED_SUPER)
+	if (udev->speed < USB_SPEED_SUPER)
 		dev_info(&udev->dev,
 				"%s %s USB device number %d using %s\n",
 				(udev->config) ? "reset" : "new", speed,
@@ -4476,11 +4475,12 @@
 							devnum, retval);
 				goto fail;
 			}
-			if (udev->speed == USB_SPEED_SUPER) {
+			if (udev->speed >= USB_SPEED_SUPER) {
 				devnum = udev->devnum;
 				dev_info(&udev->dev,
-						"%s SuperSpeed USB device number %d using %s\n",
+						"%s SuperSpeed%s USB device number %d using %s\n",
 						(udev->config) ? "reset" : "new",
+					 (udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "",
 						devnum, udev->bus->controller->driver->name);
 			}
 
@@ -4519,7 +4519,7 @@
 	 * got from those devices show they aren't superspeed devices. Warm
 	 * reset the port attached by the devices can fix them.
 	 */
-	if ((udev->speed == USB_SPEED_SUPER) &&
+	if ((udev->speed >= USB_SPEED_SUPER) &&
 			(le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
 		dev_err(&udev->dev, "got a wrong device descriptor, "
 				"warm reset device\n");
@@ -4530,7 +4530,7 @@
 	}
 
 	if (udev->descriptor.bMaxPacketSize0 == 0xff ||
-			udev->speed == USB_SPEED_SUPER)
+			udev->speed >= USB_SPEED_SUPER)
 		i = 512;
 	else
 		i = udev->descriptor.bMaxPacketSize0;
@@ -4579,7 +4579,7 @@
 		hub_port_disable(hub, port1, 0);
 		update_devnum(udev, devnum);	/* for disconnect processing */
 	}
-	mutex_unlock(&hdev->bus->usb_address0_mutex);
+	mutex_unlock(hcd->address0_mutex);
 	return retval;
 }
 
@@ -4740,7 +4740,7 @@
 		udev->level = hdev->level + 1;
 		udev->wusb = hub_is_wusb(hub);
 
-		/* Only USB 3.0 devices are connected to SuperSpeed hubs. */
+		/* Devices connected to SuperSpeed hubs are USB 3.0 or later */
 		if (hub_is_superspeed(hub->hdev))
 			udev->speed = USB_SPEED_SUPER;
 		else
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 6dc810b..3116edf 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -37,6 +37,10 @@
 	/* CBM - Flash disk */
 	{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* WORLDE easy key (easykey.25) MIDI controller  */
+	{ USB_DEVICE(0x0218, 0x0401), .driver_info =
+			USB_QUIRK_CONFIG_INTF_STRINGS },
+
 	/* HP 5300/5370C scanner */
 	{ USB_DEVICE(0x03f0, 0x0701), .driver_info =
 			USB_QUIRK_STRING_FETCH_255 },
@@ -44,6 +48,9 @@
 	/* Creative SB Audigy 2 NX */
 	{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* USB3503 */
+	{ USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },
+
 	/* Microsoft Wireless Laser Mouse 6000 Receiver */
 	{ USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -125,6 +132,9 @@
 	{ USB_DEVICE(0x04f3, 0x016f), .driver_info =
 			USB_QUIRK_DEVICE_QUALIFIER },
 
+	{ USB_DEVICE(0x04f3, 0x0381), .driver_info =
+			USB_QUIRK_NO_LPM },
+
 	{ USB_DEVICE(0x04f3, 0x21b8), .driver_info =
 			USB_QUIRK_DEVICE_QUALIFIER },
 
@@ -160,6 +170,14 @@
 	/* M-Systems Flash Disk Pioneers */
 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* Baum Vario Ultra */
+	{ USB_DEVICE(0x0904, 0x6101), .driver_info =
+			USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
+	{ USB_DEVICE(0x0904, 0x6102), .driver_info =
+			USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
+	{ USB_DEVICE(0x0904, 0x6103), .driver_info =
+			USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
+
 	/* Keytouch QWERTY Panel keyboard */
 	{ USB_DEVICE(0x0926, 0x3333), .driver_info =
 			USB_QUIRK_CONFIG_INTF_STRINGS },
@@ -173,6 +191,10 @@
 	/* MAYA44USB sound device */
 	{ USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* ASUS Base Station(T100) */
+	{ USB_DEVICE(0x0b05, 0x17e0), .driver_info =
+			USB_QUIRK_IGNORE_REMOTE_WAKEUP },
+
 	/* Action Semiconductor flash disk */
 	{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
 			USB_QUIRK_STRING_FETCH_255 },
@@ -188,26 +210,26 @@
 	{ USB_DEVICE(0x1908, 0x1315), .driver_info =
 			USB_QUIRK_HONOR_BNUMINTERFACES },
 
-	/* INTEL VALUE SSD */
-	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* USB3503 */
-	{ USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* ASUS Base Station(T100) */
-	{ USB_DEVICE(0x0b05, 0x17e0), .driver_info =
-			USB_QUIRK_IGNORE_REMOTE_WAKEUP },
-
 	/* Protocol and OTG Electrical Test Device */
 	{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
 			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
 
+	/* Acer C120 LED Projector */
+	{ USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },
+
 	/* Blackmagic Design Intensity Shuttle */
 	{ USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM },
 
 	/* Blackmagic Design UltraStudio SDI */
 	{ USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
 
+	/* Hauppauge HVR-950q */
+	{ USB_DEVICE(0x2040, 0x7200), .driver_info =
+			USB_QUIRK_CONFIG_INTF_STRINGS },
+
+	/* INTEL VALUE SSD */
+	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+
 	{ }  /* terminating entry must be last */
 };
 
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 3d27477..e43ef7d 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -335,7 +335,7 @@
 	if (!urb || !urb->complete)
 		return -EINVAL;
 	if (urb->hcpriv) {
-		WARN_ONCE(1, "URB %p submitted while active\n", urb);
+		WARN_ONCE(1, "URB %pK submitted while active\n", urb);
 		return -EBUSY;
 	}
 
@@ -401,7 +401,7 @@
 		/* SuperSpeed isoc endpoints have up to 16 bursts of up to
 		 * 3 packets each
 		 */
-		if (dev->speed == USB_SPEED_SUPER) {
+		if (dev->speed >= USB_SPEED_SUPER) {
 			int     burst = 1 + ep->ss_ep_comp.bMaxBurst;
 			int     mult = USB_SS_MULT(ep->ss_ep_comp.bmAttributes);
 			max *= burst;
@@ -499,6 +499,7 @@
 		}
 		/* too big? */
 		switch (dev->speed) {
+		case USB_SPEED_SUPER_PLUS:
 		case USB_SPEED_SUPER:	/* units are 125us */
 			/* Handle up to 2^(16-1) microframes */
 			if (urb->interval > (1 << 15))
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 05b5e17..5331812 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -45,7 +45,7 @@
 		struct usb_host_config *c)
 {
 	/* SuperSpeed power is in 8 mA units; others are in 2 mA units */
-	unsigned mul = (udev->speed == USB_SPEED_SUPER ? 8 : 2);
+	unsigned mul = (udev->speed >= USB_SPEED_SUPER ? 8 : 2);
 
 	return c->desc.bMaxPower * mul;
 }
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index a66d3cb..a738a68 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -44,6 +44,17 @@
 #include <linux/usb/phy.h>
 #include "hw.h"
 
+#ifdef CONFIG_MIPS
+/*
+ * There are some MIPS machines that can run in either big-endian
+ * or little-endian mode and that use the dwc2 register without
+ * a byteswap in both ways.
+ * Unlike other architectures, MIPS apparently does not require a
+ * barrier before the __raw_writel() to synchronize with DMA but does
+ * require the barrier after the __raw_writel() to serialize a set of
+ * writes. This set of operations was added specifically for MIPS and
+ * should only be used there.
+ */
 static inline u32 dwc2_readl(const void __iomem *addr)
 {
 	u32 value = __raw_readl(addr);
@@ -70,6 +81,22 @@
 	pr_info("INFO:: wrote %08x to %p\n", value, addr);
 #endif
 }
+#else
+/* Normal architectures just use readl/write */
+static inline u32 dwc2_readl(const void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static inline void dwc2_writel(u32 value, void __iomem *addr)
+{
+	writel(value, addr);
+
+#ifdef DWC2_LOG_WRITES
+	pr_info("info:: wrote %08x to %p\n", value, addr);
+#endif
+}
+#endif
 
 /* Maximum number of Endpoints/HostChannels */
 #define MAX_EPS_CHANNELS	16
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 78be201..68d11d7 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -42,9 +42,7 @@
 #define DWC3_XHCI_RESOURCES_NUM	2
 
 #define DWC3_SCRATCHBUF_SIZE	4096	/* each buffer is assumed to be 4KiB */
-#define DWC3_EVENT_SIZE		4	/* bytes */
-#define DWC3_EVENT_MAX_NUM	64	/* 2 events/endpoint */
-#define DWC3_EVENT_BUFFERS_SIZE	(DWC3_EVENT_SIZE * DWC3_EVENT_MAX_NUM)
+#define DWC3_EVENT_BUFFERS_SIZE	4096
 #define DWC3_EVENT_TYPE_MASK	0xfe
 
 #define DWC3_EVENT_TYPE_DEV	0
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index dd5cb55..9eba51b 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -128,12 +128,6 @@
 
 	platform_set_drvdata(pdev, exynos);
 
-	ret = dwc3_exynos_register_phys(exynos);
-	if (ret) {
-		dev_err(dev, "couldn't register PHYs\n");
-		return ret;
-	}
-
 	exynos->dev	= dev;
 
 	exynos->clk = devm_clk_get(dev, "usbdrd30");
@@ -154,7 +148,8 @@
 		exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
 		if (IS_ERR(exynos->axius_clk)) {
 			dev_err(dev, "no AXI UpScaler clk specified\n");
-			return -ENODEV;
+			ret = -ENODEV;
+			goto axius_clk_err;
 		}
 		clk_prepare_enable(exynos->axius_clk);
 	} else {
@@ -183,26 +178,36 @@
 		goto err3;
 	}
 
+	ret = dwc3_exynos_register_phys(exynos);
+	if (ret) {
+		dev_err(dev, "couldn't register PHYs\n");
+		goto err4;
+	}
+
 	if (node) {
 		ret = of_platform_populate(node, NULL, NULL, dev);
 		if (ret) {
 			dev_err(dev, "failed to add dwc3 core\n");
-			goto err4;
+			goto err5;
 		}
 	} else {
 		dev_err(dev, "no device node, failed to add dwc3 core\n");
 		ret = -ENODEV;
-		goto err4;
+		goto err5;
 	}
 
 	return 0;
 
+err5:
+	platform_device_unregister(exynos->usb2_phy);
+	platform_device_unregister(exynos->usb3_phy);
 err4:
 	regulator_disable(exynos->vdd10);
 err3:
 	regulator_disable(exynos->vdd33);
 err2:
 	clk_disable_unprepare(exynos->axius_clk);
+axius_clk_err:
 	clk_disable_unprepare(exynos->susp_clk);
 	clk_disable_unprepare(exynos->clk);
 	return ret;
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 009d830..d2c0c1a 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -36,6 +36,8 @@
 #define PCI_DEVICE_ID_INTEL_SPTH		0xa130
 #define PCI_DEVICE_ID_INTEL_BXT			0x0aaa
 #define PCI_DEVICE_ID_INTEL_APL			0x5aaa
+#define PCI_DEVICE_ID_INTEL_KBP			0xa2b0
+#define PCI_DEVICE_ID_INTEL_GLK			0x31aa
 
 static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
 static const struct acpi_gpio_params cs_gpios = { 1, 0, false };
@@ -214,6 +216,8 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
 	{  }	/* Terminating Entry */
 };
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index 5c0adb9..81db2fa 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -224,7 +224,7 @@
 
 	dwc3_data->syscfg_reg_off = res->start;
 
-	dev_vdbg(&pdev->dev, "glue-logic addr 0x%p, syscfg-reg offset 0x%x\n",
+	dev_vdbg(&pdev->dev, "glue-logic addr 0x%pK, syscfg-reg offset 0x%x\n",
 		 dwc3_data->glue_base, dwc3_data->syscfg_reg_off);
 
 	dwc3_data->rstc_pwrdn = devm_reset_control_get(dev, "powerdown");
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index b13912d..f13e9e9 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -55,20 +55,13 @@
 	}
 }
 
-static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
-		u32 len, u32 type, bool chain)
+static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum,
+		dma_addr_t buf_dma, u32 len, u32 type, bool chain)
 {
-	struct dwc3_gadget_ep_cmd_params params;
 	struct dwc3_trb			*trb;
 	struct dwc3_ep			*dep;
 
-	int				ret;
-
 	dep = dwc->eps[epnum];
-	if (dep->flags & DWC3_EP_BUSY) {
-		dwc3_trace(trace_dwc3_ep0, "%s still busy", dep->name);
-		return 0;
-	}
 
 	trb = &dwc->ep0_trb[dep->free_slot];
 
@@ -89,15 +82,25 @@
 		trb->ctrl |= (DWC3_TRB_CTRL_IOC
 				| DWC3_TRB_CTRL_LST);
 
-	if (chain)
+	trace_dwc3_prepare_trb(dep, trb);
+}
+
+static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum)
+{
+	struct dwc3_gadget_ep_cmd_params params;
+	struct dwc3_ep			*dep;
+	int				ret;
+
+	dep = dwc->eps[epnum];
+	if (dep->flags & DWC3_EP_BUSY) {
+		dwc3_trace(trace_dwc3_ep0, "%s still busy", dep->name);
 		return 0;
+	}
 
 	memset(&params, 0, sizeof(params));
 	params.param0 = upper_32_bits(dwc->ep0_trb_addr);
 	params.param1 = lower_32_bits(dwc->ep0_trb_addr);
 
-	trace_dwc3_prepare_trb(dep, trb);
-
 	ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
 			DWC3_DEPCMD_STARTTRANSFER, &params);
 	if (ret < 0) {
@@ -311,8 +314,9 @@
 {
 	int				ret;
 
-	ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
+	dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ctrl_req_addr, 8,
 			DWC3_TRBCTL_CONTROL_SETUP, false);
+	ret = dwc3_ep0_start_trans(dwc, 0);
 	WARN_ON(ret < 0);
 }
 
@@ -871,9 +875,9 @@
 
 			dwc->ep0_next_event = DWC3_EP0_COMPLETE;
 
-			ret = dwc3_ep0_start_trans(dwc, epnum,
-					dwc->ctrl_req_addr, 0,
-					DWC3_TRBCTL_CONTROL_DATA, false);
+			dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ctrl_req_addr,
+					0, DWC3_TRBCTL_CONTROL_DATA, false);
+			ret = dwc3_ep0_start_trans(dwc, epnum);
 			WARN_ON(ret < 0);
 		}
 	}
@@ -955,9 +959,10 @@
 	req->direction = !!dep->number;
 
 	if (req->request.length == 0) {
-		ret = dwc3_ep0_start_trans(dwc, dep->number,
+		dwc3_ep0_prepare_one_trb(dwc, dep->number,
 				dwc->ctrl_req_addr, 0,
 				DWC3_TRBCTL_CONTROL_DATA, false);
+		ret = dwc3_ep0_start_trans(dwc, dep->number);
 	} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
 			&& (dep->number == 0)) {
 		u32	transfer_size = 0;
@@ -975,7 +980,7 @@
 		if (req->request.length > DWC3_EP0_BOUNCE_SIZE) {
 			transfer_size = ALIGN(req->request.length - maxpacket,
 					      maxpacket);
-			ret = dwc3_ep0_start_trans(dwc, dep->number,
+			dwc3_ep0_prepare_one_trb(dwc, dep->number,
 						   req->request.dma,
 						   transfer_size,
 						   DWC3_TRBCTL_CONTROL_DATA,
@@ -987,9 +992,10 @@
 
 		dwc->ep0_bounced = true;
 
-		ret = dwc3_ep0_start_trans(dwc, dep->number,
+		dwc3_ep0_prepare_one_trb(dwc, dep->number,
 				dwc->ep0_bounce_addr, transfer_size,
 				DWC3_TRBCTL_CONTROL_DATA, false);
+		ret = dwc3_ep0_start_trans(dwc, dep->number);
 	} else {
 		ret = usb_gadget_map_request(&dwc->gadget, &req->request,
 				dep->number);
@@ -998,9 +1004,10 @@
 			return;
 		}
 
-		ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
+		dwc3_ep0_prepare_one_trb(dwc, dep->number, req->request.dma,
 				req->request.length, DWC3_TRBCTL_CONTROL_DATA,
 				false);
+		ret = dwc3_ep0_start_trans(dwc, dep->number);
 	}
 
 	WARN_ON(ret < 0);
@@ -1014,8 +1021,9 @@
 	type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3
 		: DWC3_TRBCTL_CONTROL_STATUS2;
 
-	return dwc3_ep0_start_trans(dwc, dep->number,
+	dwc3_ep0_prepare_one_trb(dwc, dep->number,
 			dwc->ctrl_req_addr, 0, type, false);
+	return dwc3_ep0_start_trans(dwc, dep->number);
 }
 
 static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 69ffe6e..d3bd1af 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -235,6 +235,7 @@
 		int status)
 {
 	struct dwc3			*dwc = dep->dwc;
+	unsigned int			unmap_after_complete = false;
 	int				i;
 
 	if (req->queued) {
@@ -259,11 +260,19 @@
 	if (req->request.status == -EINPROGRESS)
 		req->request.status = status;
 
-	if (dwc->ep0_bounced && dep->number == 0)
+	/*
+	 * NOTICE we don't want to unmap before calling ->complete() if we're
+	 * dealing with a bounced ep0 request. If we unmap it here, we would end
+	 * up overwritting the contents of req->buf and this could confuse the
+	 * gadget driver.
+	 */
+	if (dwc->ep0_bounced && dep->number <= 1) {
 		dwc->ep0_bounced = false;
-	else
-		usb_gadget_unmap_request(&dwc->gadget, &req->request,
-				req->direction);
+		unmap_after_complete = true;
+	} else {
+		usb_gadget_unmap_request(&dwc->gadget,
+				&req->request, req->direction);
+	}
 
 	dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
 			req, dep->name, req->request.actual,
@@ -273,6 +282,10 @@
 	spin_unlock(&dwc->lock);
 	usb_gadget_giveback_request(&dep->endpoint, &req->request);
 	spin_lock(&dwc->lock);
+
+	if (unmap_after_complete)
+		usb_gadget_unmap_request(&dwc->gadget,
+				&req->request, req->direction);
 }
 
 int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param)
@@ -1206,7 +1219,7 @@
 		goto out;
 	}
 
-	if (WARN(req->dep != dep, "request %p belongs to '%s'\n",
+	if (WARN(req->dep != dep, "request %pK belongs to '%s'\n",
 				request, req->dep->name)) {
 		ret = -EINVAL;
 		goto out;
@@ -1251,7 +1264,7 @@
 			dwc3_stop_active_transfer(dwc, dep->number, true);
 			goto out1;
 		}
-		dev_err(dwc->dev, "request %p was not queued to %s\n",
+		dev_err(dwc->dev, "request %pK was not queued to %s\n",
 				request, ep->name);
 		ret = -EINVAL;
 		goto out0;
@@ -1853,7 +1866,7 @@
 		 * would help. Lets hope that if this occurs, someone
 		 * fixes the root cause instead of looking away :)
 		 */
-		dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n",
+		dev_err(dwc->dev, "%s's TRB (%pK) still owned by HW\n",
 				dep->name, trb);
 	count = trb->size & DWC3_TRB_SIZE_MASK;
 
@@ -1892,14 +1905,6 @@
 			s_pkt = 1;
 	}
 
-	/*
-	 * We assume here we will always receive the entire data block
-	 * which we should receive. Meaning, if we program RX to
-	 * receive 4K but we receive only 2K, we assume that's all we
-	 * should receive and we simply bounce the request back to the
-	 * gadget driver for further processing.
-	 */
-	req->request.actual += req->request.length - count;
 	if (s_pkt)
 		return 1;
 	if ((event->status & DEPEVT_STATUS_LST) &&
@@ -1919,6 +1924,7 @@
 	struct dwc3_trb		*trb;
 	unsigned int		slot;
 	unsigned int		i;
+	int			count = 0;
 	int			ret;
 
 	do {
@@ -1935,6 +1941,8 @@
 				slot++;
 			slot %= DWC3_TRB_NUM;
 			trb = &dep->trb_pool[slot];
+			count += trb->size & DWC3_TRB_SIZE_MASK;
+
 
 			ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
 					event, status);
@@ -1942,6 +1950,14 @@
 				break;
 		} while (++i < req->request.num_mapped_sgs);
 
+		/*
+		 * We assume here we will always receive the entire data block
+		 * which we should receive. Meaning, if we program RX to
+		 * receive 4K but we receive only 2K, we assume that's all we
+		 * should receive and we simply bounce the request back to the
+		 * gadget driver for further processing.
+		 */
+		req->request.actual += req->request.length - count;
 		dwc3_gadget_giveback(dep, req, status);
 
 		if (ret)
@@ -1965,6 +1981,10 @@
 		return 1;
 	}
 
+	if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
+		if ((event->status & DEPEVT_STATUS_IOC) &&
+				(trb->ctrl & DWC3_TRB_CTRL_IOC))
+			return 0;
 	return 1;
 }
 
@@ -2838,7 +2858,7 @@
 	kfree(dwc->setup_buf);
 
 err2:
-	dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+	dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
 			dwc->ep0_trb, dwc->ep0_trb_addr);
 
 err1:
@@ -2862,7 +2882,7 @@
 
 	kfree(dwc->setup_buf);
 
-	dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+	dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
 			dwc->ep0_trb, dwc->ep0_trb_addr);
 
 	dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index 18ae3ea..ccd9694 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -28,23 +28,23 @@
 #define gadget_to_dwc(g)	(container_of(g, struct dwc3, gadget))
 
 /* DEPCFG parameter 1 */
-#define DWC3_DEPCFG_INT_NUM(n)		((n) << 0)
+#define DWC3_DEPCFG_INT_NUM(n)		(((n) & 0x1f) << 0)
 #define DWC3_DEPCFG_XFER_COMPLETE_EN	(1 << 8)
 #define DWC3_DEPCFG_XFER_IN_PROGRESS_EN	(1 << 9)
 #define DWC3_DEPCFG_XFER_NOT_READY_EN	(1 << 10)
 #define DWC3_DEPCFG_FIFO_ERROR_EN	(1 << 11)
 #define DWC3_DEPCFG_STREAM_EVENT_EN	(1 << 13)
-#define DWC3_DEPCFG_BINTERVAL_M1(n)	((n) << 16)
+#define DWC3_DEPCFG_BINTERVAL_M1(n)	(((n) & 0xff) << 16)
 #define DWC3_DEPCFG_STREAM_CAPABLE	(1 << 24)
-#define DWC3_DEPCFG_EP_NUMBER(n)	((n) << 25)
+#define DWC3_DEPCFG_EP_NUMBER(n)	(((n) & 0x1f) << 25)
 #define DWC3_DEPCFG_BULK_BASED		(1 << 30)
 #define DWC3_DEPCFG_FIFO_BASED		(1 << 31)
 
 /* DEPCFG parameter 0 */
-#define DWC3_DEPCFG_EP_TYPE(n)		((n) << 1)
-#define DWC3_DEPCFG_MAX_PACKET_SIZE(n)	((n) << 3)
-#define DWC3_DEPCFG_FIFO_NUMBER(n)	((n) << 17)
-#define DWC3_DEPCFG_BURST_SIZE(n)	((n) << 22)
+#define DWC3_DEPCFG_EP_TYPE(n)		(((n) & 0x3) << 1)
+#define DWC3_DEPCFG_MAX_PACKET_SIZE(n)	(((n) & 0x7ff) << 3)
+#define DWC3_DEPCFG_FIFO_NUMBER(n)	(((n) & 0x1f) << 17)
+#define DWC3_DEPCFG_BURST_SIZE(n)	(((n) & 0xf) << 22)
 #define DWC3_DEPCFG_DATA_SEQ_NUM(n)	((n) << 26)
 /* This applies for core versions earlier than 1.94a */
 #define DWC3_DEPCFG_IGN_SEQ_NUM		(1 << 31)
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index afddd91..5cf6802 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -203,7 +203,7 @@
 	tristate
 
 config USB_F_PTP
-	tristate
+        tristate
 
 config USB_F_AUDIO_SRC
 	tristate
@@ -406,7 +406,7 @@
 
 config USB_CONFIGFS_F_AUDIO_SRC
 	boolean "Audio Source gadget"
-	depends on USB_CONFIGFS
+	depends on USB_CONFIGFS && USB_CONFIGFS_F_ACC
 	depends on SND
 	select SND_PCM
 	select USB_F_AUDIO_SRC
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index ffa2a68..a5ebfa9 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -144,11 +144,16 @@
 
 ep_found:
 	/* commit results */
-	_ep->maxpacket = usb_endpoint_maxp(chosen_desc);
+	_ep->maxpacket = usb_endpoint_maxp(chosen_desc) & 0x7ff;
 	_ep->desc = chosen_desc;
 	_ep->comp_desc = NULL;
 	_ep->maxburst = 0;
-	_ep->mult = 0;
+	_ep->mult = 1;
+
+	if (g->speed == USB_SPEED_HIGH && (usb_endpoint_xfer_isoc(_ep->desc) ||
+				usb_endpoint_xfer_int(_ep->desc)))
+		_ep->mult = ((usb_endpoint_maxp(_ep->desc) & 0x1800) >> 11) + 1;
+
 	if (!want_comp_desc)
 		return 0;
 
@@ -165,7 +170,7 @@
 		switch (usb_endpoint_type(_ep->desc)) {
 		case USB_ENDPOINT_XFER_ISOC:
 			/* mult: bits 1:0 of bmAttributes */
-			_ep->mult = comp_desc->bmAttributes & 0x3;
+			_ep->mult = (comp_desc->bmAttributes & 0x3) + 1;
 		case USB_ENDPOINT_XFER_BULK:
 		case USB_ENDPOINT_XFER_INT:
 			_ep->maxburst = comp_desc->bMaxBurst + 1;
@@ -1596,9 +1601,7 @@
 		value = min(w_length, (u16) 1);
 		break;
 
-	/* function drivers must handle get/set altsetting; if there's
-	 * no get() method, we know only altsetting zero works.
-	 */
+	/* function drivers must handle get/set altsetting */
 	case USB_REQ_SET_INTERFACE:
 		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
 			goto unknown;
@@ -1607,7 +1610,13 @@
 		f = cdev->config->interface[intf];
 		if (!f)
 			break;
-		if (w_value && !f->set_alt)
+
+		/*
+		 * If there's no get_alt() method, we know only altsetting zero
+		 * works. There is no need to check if set_alt() is not NULL
+		 * as we check this in usb_add_function().
+		 */
+		if (w_value && !f->get_alt)
 			break;
 		value = f->set_alt(f, w_index, w_value);
 		if (value == USB_GADGET_DELAYED_STATUS) {
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index b27ce07..54849fe9 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -425,11 +425,6 @@
 	}
 
 	f = usb_get_function(fi);
-	if (f == NULL) {
-		/* Are we trying to symlink PTP without MTP function? */
-		ret = -EINVAL; /* Invalid Configuration */
-		goto out;
-	}
 	if (IS_ERR(f)) {
 		ret = PTR_ERR(f);
 		goto out;
@@ -1737,7 +1732,9 @@
 {
 	struct gadget_info *gi = to_gadget_info(item);
 
+	mutex_lock(&gi->lock);
 	unregister_gadget(gi);
+	mutex_unlock(&gi->lock);
 }
 EXPORT_SYMBOL_GPL(unregister_gadget_item);
 
diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c
index c621235..76b8ae0 100644
--- a/drivers/usb/gadget/function/f_accessory.c
+++ b/drivers/usb/gadget/function/f_accessory.c
@@ -77,9 +77,13 @@
 	struct usb_ep *ep_in;
 	struct usb_ep *ep_out;
 
-	/* set to 1 when we connect */
+	/* online indicates state of function_set_alt & function_unbind
+	 * set to 1 when we connect
+	 */
 	int online:1;
-	/* Set to 1 when we disconnect.
+
+	/* disconnected indicates state of open & release
+	 * Set to 1 when we disconnect.
 	 * Not cleared until our file is closed.
 	 */
 	int disconnected:1;
@@ -211,6 +215,7 @@
 static struct usb_request *acc_request_new(struct usb_ep *ep, int buffer_size)
 {
 	struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
+
 	if (!req)
 		return NULL;
 
@@ -262,7 +267,6 @@
 
 static void acc_set_disconnected(struct acc_dev *dev)
 {
-	dev->online = 0;
 	dev->disconnected = 1;
 }
 
@@ -531,15 +535,6 @@
 	ep->driver_data = dev;		/* claim the endpoint */
 	dev->ep_out = ep;
 
-	ep = usb_ep_autoconfig(cdev->gadget, out_desc);
-	if (!ep) {
-		DBG(cdev, "usb_ep_autoconfig for ep_out failed\n");
-		return -ENODEV;
-	}
-	DBG(cdev, "usb_ep_autoconfig for ep_out got %s\n", ep->name);
-	ep->driver_data = dev;		/* claim the endpoint */
-	dev->ep_out = ep;
-
 	/* now allocate requests for our endpoints */
 	for (i = 0; i < TX_REQ_MAX; i++) {
 		req = acc_request_new(dev->ep_in, BULK_BUFFER_SIZE);
@@ -684,9 +679,10 @@
 			req->zero = 0;
 		} else {
 			xfer = count;
-			/* If the data length is a multple of the
+			/*
+			 * If the data length is a multple of the
 			 * maxpacket size then send a zero length packet(ZLP).
-			*/
+			 */
 			req->zero = ((xfer % dev->ep_in->maxpacket) == 0);
 		}
 		if (copy_from_user(req->buf, buf, xfer)) {
@@ -771,7 +767,10 @@
 	printk(KERN_INFO "acc_release\n");
 
 	WARN_ON(!atomic_xchg(&_acc_dev->open_excl, 0));
-	_acc_dev->disconnected = 0;
+	/* indicate that we are disconnected
+	 * still could be online so don't touch online flag
+	 */
+	_acc_dev->disconnected = 1;
 	return 0;
 }
 
@@ -828,11 +827,11 @@
 	unsigned long flags;
 
 /*
-	printk(KERN_INFO "acc_ctrlrequest "
-			"%02x.%02x v%04x i%04x l%u\n",
-			b_requestType, b_request,
-			w_value, w_index, w_length);
-*/
+ *	printk(KERN_INFO "acc_ctrlrequest "
+ *			"%02x.%02x v%04x i%04x l%u\n",
+ *			b_requestType, b_request,
+ *			w_value, w_index, w_length);
+ */
 
 	if (b_requestType == (USB_DIR_OUT | USB_TYPE_VENDOR)) {
 		if (b_request == ACCESSORY_START) {
@@ -1019,6 +1018,10 @@
 	struct usb_request *req;
 	int i;
 
+	dev->online = 0;		/* clear online flag */
+	wake_up(&dev->read_wq);		/* unblock reads on closure */
+	wake_up(&dev->write_wq);	/* likewise for writes */
+
 	while ((req = req_get(dev, &dev->tx_idle)))
 		acc_request_free(req, dev->ep_in);
 	for (i = 0; i < RX_REQ_MAX; i++)
@@ -1030,6 +1033,7 @@
 static void acc_start_work(struct work_struct *data)
 {
 	char *envp[2] = { "ACCESSORY=START", NULL };
+
 	kobject_uevent_env(&acc_device.this_device->kobj, KOBJ_CHANGE, envp);
 }
 
@@ -1149,6 +1153,7 @@
 	}
 
 	dev->online = 1;
+	dev->disconnected = 0; /* if online then not disconnected */
 
 	/* readers may be blocked waiting for us to go online */
 	wake_up(&dev->read_wq);
@@ -1161,7 +1166,8 @@
 	struct usb_composite_dev	*cdev = dev->cdev;
 
 	DBG(cdev, "acc_function_disable\n");
-	acc_set_disconnected(dev);
+	acc_set_disconnected(dev); /* this now only sets disconnected */
+	dev->online = 0; /* so now need to clear online flag here too */
 	usb_ep_disable(dev->ep_in);
 	usb_ep_disable(dev->ep_out);
 
diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c
index 2fa1e80..67e474b 100644
--- a/drivers/usb/gadget/function/f_acm.c
+++ b/drivers/usb/gadget/function/f_acm.c
@@ -535,13 +535,15 @@
 {
 	struct usb_composite_dev *cdev = acm->port.func.config->cdev;
 	int			status;
+	__le16			serial_state;
 
 	spin_lock(&acm->lock);
 	if (acm->notify_req) {
 		dev_dbg(&cdev->gadget->dev, "acm ttyGS%d serial state %04x\n",
 			acm->port_num, acm->serial_state);
+		serial_state = cpu_to_le16(acm->serial_state);
 		status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
-				0, &acm->serial_state, sizeof(acm->serial_state));
+				0, &serial_state, sizeof(acm->serial_state));
 	} else {
 		acm->pending = true;
 		status = 0;
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index bcd8174..8124af3 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/usb/audio.h>
 #include <linux/wait.h>
+#include <linux/pm_qos.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
@@ -268,6 +269,8 @@
 	/* number of frames sent since start_time */
 	s64				frames_sent;
 	struct audio_source_config	*config;
+	/* for creating and issuing QoS requests */
+	struct pm_qos_request pm_qos;
 };
 
 static inline struct audio_dev *func_to_audio(struct usb_function *f)
@@ -310,6 +313,7 @@
 static struct usb_request *audio_request_new(struct usb_ep *ep, int buffer_size)
 {
 	struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
+
 	if (!req)
 		return NULL;
 
@@ -377,10 +381,9 @@
 
 	/* compute number of frames to send */
 	now = ktime_get();
-	msecs = ktime_to_ns(now) - ktime_to_ns(audio->start_time);
-	do_div(msecs, 1000000);
-	frames = msecs * SAMPLE_RATE;
-	do_div(frames, 1000);
+	msecs = div_s64((ktime_to_ns(now) - ktime_to_ns(audio->start_time)),
+			1000000);
+	frames = div_s64((msecs * SAMPLE_RATE), 1000);
 
 	/* Readjust our frames_sent if we fall too far behind.
 	 * If we get too far behind it is better to drop some frames than
@@ -740,6 +743,10 @@
 	runtime->hw.channels_max = 2;
 
 	audio->substream = substream;
+
+	/* Add the QoS request and set the latency to 0 */
+	pm_qos_add_request(&audio->pm_qos, PM_QOS_CPU_DMA_LATENCY, 0);
+
 	return 0;
 }
 
@@ -749,6 +756,10 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&audio->lock, flags);
+
+	/* Remove the QoS request */
+	pm_qos_remove_request(&audio->pm_qos);
+
 	audio->substream = NULL;
 	spin_unlock_irqrestore(&audio->lock, flags);
 
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 79d895c..732e6ed 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -651,7 +651,7 @@
 	if (io_data->read && ret > 0) {
 		use_mm(io_data->mm);
 		ret = copy_to_iter(io_data->buf, ret, &io_data->data);
-		if (iov_iter_count(&io_data->data))
+		if (ret != io_data->req->actual && iov_iter_count(&io_data->data))
 			ret = -EFAULT;
 		unuse_mm(io_data->mm);
 	}
@@ -1643,11 +1643,14 @@
 	spin_lock_irqsave(&func->ffs->eps_lock, flags);
 	do {
 		struct usb_endpoint_descriptor *ds;
+		struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
+		int needs_comp_desc = false;
 		int desc_idx;
 
-		if (ffs->gadget->speed == USB_SPEED_SUPER)
+		if (ffs->gadget->speed == USB_SPEED_SUPER) {
 			desc_idx = 2;
-		else if (ffs->gadget->speed == USB_SPEED_HIGH)
+			needs_comp_desc = true;
+		} else if (ffs->gadget->speed == USB_SPEED_HIGH)
 			desc_idx = 1;
 		else
 			desc_idx = 0;
@@ -1664,6 +1667,14 @@
 
 		ep->ep->driver_data = ep;
 		ep->ep->desc = ds;
+
+		if (needs_comp_desc) {
+			comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds +
+					USB_DT_ENDPOINT_SIZE);
+			ep->ep->maxburst = comp_desc->bMaxBurst + 1;
+			ep->ep->comp_desc = comp_desc;
+		}
+
 		ret = usb_ep_enable(ep->ep);
 		if (likely(!ret)) {
 			epfile->ep = ep;
@@ -2079,6 +2090,8 @@
 		if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
 			return -EINVAL;
 		length = le32_to_cpu(d->dwSize);
+		if (len < length)
+			return -EINVAL;
 		type = le32_to_cpu(d->dwPropertyDataType);
 		if (type < USB_EXT_PROP_UNICODE ||
 		    type > USB_EXT_PROP_UNICODE_MULTI) {
@@ -2087,6 +2100,11 @@
 			return -EINVAL;
 		}
 		pnl = le16_to_cpu(d->wPropertyNameLength);
+		if (length < 14 + pnl) {
+			pr_vdebug("invalid os descriptor length: %d pnl:%d (descriptor %d)\n",
+				  length, pnl, type);
+			return -EINVAL;
+		}
 		pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
 		if (length != 14 + pnl + pdl) {
 			pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
@@ -2171,6 +2189,9 @@
 		}
 	}
 	if (flags & (1 << i)) {
+		if (len < 4) {
+			goto error;
+		}
 		os_descs_count = get_unaligned_le32(data);
 		data += 4;
 		len -= 4;
@@ -2243,7 +2264,8 @@
 
 	ENTER();
 
-	if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
+	if (unlikely(len < 16 ||
+		     get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
 		     get_unaligned_le32(data + 4) != len))
 		goto error;
 	str_count  = get_unaligned_le32(data + 8);
@@ -2740,6 +2762,7 @@
 		func->ffs->ss_descs_count;
 
 	int fs_len, hs_len, ss_len, ret, i;
+	struct ffs_ep *eps_ptr;
 
 	/* Make it a single chunk, less management later on */
 	vla_group(d);
@@ -2788,12 +2811,9 @@
 	       ffs->raw_descs_length);
 
 	memset(vla_ptr(vlabuf, d, inums), 0xff, d_inums__sz);
-	for (ret = ffs->eps_count; ret; --ret) {
-		struct ffs_ep *ptr;
-
-		ptr = vla_ptr(vlabuf, d, eps);
-		ptr[ret].num = -1;
-	}
+	eps_ptr = vla_ptr(vlabuf, d, eps);
+	for (i = 0; i < ffs->eps_count; i++)
+		eps_ptr[i].num = -1;
 
 	/* Save pointers
 	 * d_eps == vlabuf, func->eps used to kfree vlabuf later
@@ -3443,6 +3463,7 @@
 {
 	struct ffs_dev *ffs_obj;
 	struct f_fs_opts *opts;
+	struct config_item *ci;
 
 	ENTER();
 	ffs_dev_lock();
@@ -3466,8 +3487,11 @@
 	    || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount))
 		goto done;
 
-	unregister_gadget_item(ffs_obj->opts->
-			       func_inst.group.cg_item.ci_parent->ci_parent);
+	ci = opts->func_inst.group.cg_item.ci_parent->ci_parent;
+	ffs_dev_unlock();
+
+	unregister_gadget_item(ci);
+	return;
 done:
 	ffs_dev_unlock();
 }
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 223ccf8..a069726 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -399,7 +399,11 @@
 /* Caller must hold fsg->lock */
 static void wakeup_thread(struct fsg_common *common)
 {
-	smp_wmb();	/* ensure the write of bh->state is complete */
+	/*
+	 * Ensure the reading of thread_wakeup_needed
+	 * and the writing of bh->state are completed
+	 */
+	smp_mb();
 	/* Tell the main thread that something has happened */
 	common->thread_wakeup_needed = 1;
 	if (common->thread_task)
@@ -630,7 +634,12 @@
 	}
 	__set_current_state(TASK_RUNNING);
 	common->thread_wakeup_needed = 0;
-	smp_rmb();	/* ensure the latest bh->state is visible */
+
+	/*
+	 * Ensure the writing of thread_wakeup_needed
+	 * and the reading of bh->state are completed
+	 */
+	smp_mb();
 	return rc;
 }
 
@@ -2977,25 +2986,6 @@
 }
 EXPORT_SYMBOL_GPL(fsg_common_set_inquiry_string);
 
-int fsg_common_run_thread(struct fsg_common *common)
-{
-	common->state = FSG_STATE_IDLE;
-	/* Tell the thread to start working */
-	common->thread_task =
-		kthread_create(fsg_main_thread, common, "file-storage");
-	if (IS_ERR(common->thread_task)) {
-		common->state = FSG_STATE_TERMINATED;
-		return PTR_ERR(common->thread_task);
-	}
-
-	DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task));
-
-	wake_up_process(common->thread_task);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(fsg_common_run_thread);
-
 static void fsg_common_release(struct kref *ref)
 {
 	struct fsg_common *common = container_of(ref, struct fsg_common, ref);
@@ -3005,6 +2995,7 @@
 	if (common->state != FSG_STATE_TERMINATED) {
 		raise_exception(common, FSG_STATE_EXIT);
 		wait_for_completion(&common->thread_notifier);
+		common->thread_task = NULL;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
@@ -3050,9 +3041,21 @@
 		if (ret)
 			return ret;
 		fsg_common_set_inquiry_string(fsg->common, NULL, NULL);
-		ret = fsg_common_run_thread(fsg->common);
-		if (ret)
+	}
+
+	if (!common->thread_task) {
+		common->state = FSG_STATE_IDLE;
+		common->thread_task =
+			kthread_create(fsg_main_thread, common, "file-storage");
+		if (IS_ERR(common->thread_task)) {
+			int ret = PTR_ERR(common->thread_task);
+			common->thread_task = NULL;
+			common->state = FSG_STATE_TERMINATED;
 			return ret;
+		}
+		DBG(common, "I/O thread pid: %d\n",
+		    task_pid_nr(common->thread_task));
+		wake_up_process(common->thread_task);
 	}
 
 	fsg->gadget = gadget;
diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h
index 445df67..b6a9918 100644
--- a/drivers/usb/gadget/function/f_mass_storage.h
+++ b/drivers/usb/gadget/function/f_mass_storage.h
@@ -153,8 +153,6 @@
 void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
 				   const char *pn);
 
-int fsg_common_run_thread(struct fsg_common *common);
-
 void fsg_config_from_params(struct fsg_config *cfg,
 			    const struct fsg_module_parameters *params,
 			    unsigned int fsg_num_buffers);
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 847f703..315c269 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -361,7 +361,9 @@
 	/* allocate a bunch of read buffers and queue them all at once. */
 	for (i = 0; i < midi->qlen && err == 0; i++) {
 		struct usb_request *req =
-			midi_alloc_ep_req(midi->out_ep, midi->buflen);
+			midi_alloc_ep_req(midi->out_ep,
+				max_t(unsigned, midi->buflen,
+					bulk_out_desc.wMaxPacketSize));
 		if (req == NULL)
 			return -ENOMEM;
 
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index 74195be..b25cb35 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -43,6 +43,7 @@
 #define MTP_BULK_BUFFER_SIZE       16384
 #define INTR_BUFFER_SIZE           28
 #define MAX_INST_NAME_LEN          40
+#define MTP_MAX_FILE_SIZE          0xFFFFFFFFL
 
 /* String IDs */
 #define INTERFACE_STRING_INDEX	0
@@ -361,6 +362,7 @@
 static struct usb_request *mtp_request_new(struct usb_ep *ep, int buffer_size)
 {
 	struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
+
 	if (!req)
 		return NULL;
 
@@ -539,12 +541,10 @@
 	ssize_t r = count;
 	unsigned xfer;
 	int ret = 0;
+	size_t len = 0;
 
 	DBG(cdev, "mtp_read(%zu)\n", count);
 
-	if (count > MTP_BULK_BUFFER_SIZE)
-		return -EINVAL;
-
 	/* we will block until we're online */
 	DBG(cdev, "mtp_read: waiting for online state\n");
 	ret = wait_event_interruptible(dev->read_wq,
@@ -554,6 +554,14 @@
 		goto done;
 	}
 	spin_lock_irq(&dev->lock);
+	if (dev->ep_out->desc) {
+		len = usb_ep_align_maybe(cdev->gadget, dev->ep_out, count);
+		if (len > MTP_BULK_BUFFER_SIZE) {
+			spin_unlock_irq(&dev->lock);
+			return -EINVAL;
+		}
+	}
+
 	if (dev->state == STATE_CANCELED) {
 		/* report cancelation to userspace */
 		dev->state = STATE_READY;
@@ -566,7 +574,7 @@
 requeue_req:
 	/* queue a request */
 	req = dev->rx_req[0];
-	req->length = count;
+	req->length = len;
 	dev->rx_done = 0;
 	ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL);
 	if (ret < 0) {
@@ -763,7 +771,12 @@
 		if (hdr_size) {
 			/* prepend MTP data header */
 			header = (struct mtp_data_header *)req->buf;
-			header->length = __cpu_to_le32(count);
+			/*
+                         * set file size with header according to
+                         * MTP Specification v1.0
+                         */
+			header->length = (count > MTP_MAX_FILE_SIZE) ?
+				MTP_MAX_FILE_SIZE : __cpu_to_le32(count);
 			header->type = __cpu_to_le16(2); /* data packet */
 			header->command = __cpu_to_le16(dev->xfer_command);
 			header->transaction_id =
@@ -864,6 +877,10 @@
 					usb_ep_dequeue(dev->ep_out, read_req);
 				break;
 			}
+			if (read_req->status) {
+				r = read_req->status;
+				break;
+			}
 			/* if xfer_file_length is 0xFFFFFFFF, then we read until
 			 * we get a zero length packet
 			 */
@@ -1121,6 +1138,7 @@
 		} else if (ctrl->bRequest == MTP_REQ_GET_DEVICE_STATUS
 				&& w_index == 0 && w_value == 0) {
 			struct mtp_device_status *status = cdev->req->buf;
+
 			status->wLength =
 				__constant_cpu_to_le16(sizeof(*status));
 
@@ -1143,6 +1161,7 @@
 	/* respond with data transfer or status phase? */
 	if (value >= 0) {
 		int rc;
+
 		cdev->req->zero = value < w_length;
 		cdev->req->length = value;
 		rc = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
@@ -1378,6 +1397,7 @@
 static void mtp_attr_release(struct config_item *item)
 {
 	struct mtp_instance *fi_mtp = to_mtp_instance(item);
+
 	usb_put_function_instance(&fi_mtp->func_inst);
 }
 
@@ -1498,7 +1518,7 @@
 		pr_err("\t2: Create MTP function\n");
 		pr_err("\t3: Create and symlink PTP function"
 				" with a gadget configuration\n");
-		return NULL;
+		return ERR_PTR(-EINVAL); /* Invalid Configuration */
 	}
 
 	dev = fi_mtp->dev;
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 044ca79..12064d3 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -1079,13 +1079,13 @@
 	agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
 	if (!agdev->out_ep) {
 		dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
-		goto err;
+		return ret;
 	}
 
 	agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
 	if (!agdev->in_ep) {
 		dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
-		goto err;
+		return ret;
 	}
 
 	uac2->p_prm.uac2 = uac2;
@@ -1102,7 +1102,7 @@
 
 	ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
 	if (ret)
-		goto err;
+		return ret;
 
 	prm = &agdev->uac2.c_prm;
 	prm->max_psize = hs_epout_desc.wMaxPacketSize;
@@ -1117,19 +1117,19 @@
 	prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
 	if (!prm->rbuf) {
 		prm->max_psize = 0;
-		goto err_free_descs;
+		goto err;
 	}
 
 	ret = alsa_uac2_init(agdev);
 	if (ret)
-		goto err_free_descs;
+		goto err;
 	return 0;
 
-err_free_descs:
-	usb_free_all_descriptors(fn);
 err:
 	kfree(agdev->uac2.p_prm.rbuf);
 	kfree(agdev->uac2.c_prm.rbuf);
+err_free_descs:
+	usb_free_all_descriptors(fn);
 	return -EINVAL;
 }
 
@@ -1291,6 +1291,7 @@
 
 	if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
 		struct cntrl_cur_lay3 c;
+		memset(&c, 0, sizeof(struct cntrl_cur_lay3));
 
 		if (entity_id == USB_IN_CLK_ID)
 			c.dCUR = p_srate;
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index 29b41b5..c7689d0 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -625,7 +625,7 @@
 	uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst;
 	uvc_ss_streaming_comp.wBytesPerInterval =
 		cpu_to_le16(max_packet_size * max_packet_mult *
-			    opts->streaming_maxburst);
+			    (opts->streaming_maxburst + 1));
 
 	/* Allocate endpoints. */
 	ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 74e9f5b..21bf0a8 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -66,7 +66,7 @@
 
 	spinlock_t		req_lock;	/* guard {rx,tx}_reqs */
 	struct list_head	tx_reqs, rx_reqs;
-	unsigned		tx_qlen;
+	atomic_t		tx_qlen;
 /* Minimum number of TX USB request queued to UDC */
 #define TX_REQ_THRESHOLD	5
 	int			no_tx_req_used;
@@ -568,6 +568,7 @@
 		dev_kfree_skb_any(skb);
 	}
 
+	atomic_dec(&dev->tx_qlen);
 	if (netif_carrier_ok(dev->net))
 		netif_wake_queue(dev->net);
 }
@@ -741,19 +742,13 @@
 
 	req->length = length;
 
-	/* throttle highspeed IRQ rate back slightly */
-	if (gadget_is_dualspeed(dev->gadget) &&
-			 (dev->gadget->speed == USB_SPEED_HIGH)) {
-		dev->tx_qlen++;
-		if (dev->tx_qlen == (dev->qmult/2)) {
-			req->no_interrupt = 0;
-			dev->tx_qlen = 0;
-		} else {
-			req->no_interrupt = 1;
-		}
-	} else {
-		req->no_interrupt = 0;
-	}
+	/* throttle high/super speed IRQ rate back slightly */
+	if (gadget_is_dualspeed(dev->gadget))
+		req->no_interrupt = (((dev->gadget->speed == USB_SPEED_HIGH ||
+				       dev->gadget->speed == USB_SPEED_SUPER)) &&
+					!list_empty(&dev->tx_reqs))
+			? ((atomic_read(&dev->tx_qlen) % dev->qmult) != 0)
+			: 0;
 
 	retval = usb_ep_queue(in, req, GFP_ATOMIC);
 	switch (retval) {
@@ -762,6 +757,7 @@
 		break;
 	case 0:
 		net->trans_start = jiffies;
+		atomic_inc(&dev->tx_qlen);
 	}
 
 	if (retval) {
@@ -790,7 +786,7 @@
 	rx_fill(dev, gfp_flags);
 
 	/* and open the tx floodgates */
-	dev->tx_qlen = 0;
+	atomic_set(&dev->tx_qlen, 0);
 	netif_wake_queue(dev->net);
 }
 
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
index 3d0d5d9..0f01c04 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -243,7 +243,7 @@
 
 	req_size = video->ep->maxpacket
 		 * max_t(unsigned int, video->ep->maxburst, 1)
-		 * (video->ep->mult + 1);
+		 * (video->ep->mult);
 
 	for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
 		video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
diff --git a/drivers/usb/gadget/functions.c b/drivers/usb/gadget/functions.c
index 389c1f3..b13f839 100644
--- a/drivers/usb/gadget/functions.c
+++ b/drivers/usb/gadget/functions.c
@@ -58,7 +58,7 @@
 	struct usb_function *f;
 
 	f = fi->fd->alloc_func(fi);
-	if ((f == NULL) || IS_ERR(f))
+	if (IS_ERR(f))
 		return f;
 	f->fi = fi;
 	return f;
diff --git a/drivers/usb/gadget/legacy/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c
index 4b158e2..64b2cbb 100644
--- a/drivers/usb/gadget/legacy/acm_ms.c
+++ b/drivers/usb/gadget/legacy/acm_ms.c
@@ -133,10 +133,6 @@
 	if (status < 0)
 		goto put_msg;
 
-	status = fsg_common_run_thread(opts->common);
-	if (status)
-		goto remove_acm;
-
 	status = usb_add_function(c, f_msg);
 	if (status)
 		goto remove_acm;
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index f454c7a..43ce2cf 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -541,7 +541,7 @@
 	 */
 	spin_lock_irq(&epdata->dev->lock);
 	value = -ENODEV;
-	if (unlikely(epdata->ep))
+	if (unlikely(epdata->ep == NULL))
 		goto fail;
 
 	req = usb_ep_alloc_request(epdata->ep, GFP_ATOMIC);
@@ -937,8 +937,11 @@
 			struct usb_ep		*ep = dev->gadget->ep0;
 			struct usb_request	*req = dev->req;
 
-			if ((retval = setup_req (ep, req, 0)) == 0)
-				retval = usb_ep_queue (ep, req, GFP_ATOMIC);
+			if ((retval = setup_req (ep, req, 0)) == 0) {
+				spin_unlock_irq (&dev->lock);
+				retval = usb_ep_queue (ep, req, GFP_KERNEL);
+				spin_lock_irq (&dev->lock);
+			}
 			dev->state = STATE_DEV_CONNECTED;
 
 			/* assume that was SET_CONFIGURATION */
@@ -1122,7 +1125,7 @@
 	/* data and/or status stage for control request */
 	} else if (dev->state == STATE_DEV_SETUP) {
 
-		/* IN DATA+STATUS caller makes len <= wLength */
+		len = min_t(size_t, len, dev->setup_wLength);
 		if (dev->setup_in) {
 			retval = setup_req (dev->gadget->ep0, dev->req, len);
 			if (retval == 0) {
@@ -1456,8 +1459,11 @@
 							w_length);
 				if (value < 0)
 					break;
+
+				spin_unlock (&dev->lock);
 				value = usb_ep_queue (gadget->ep0, dev->req,
-							GFP_ATOMIC);
+							GFP_KERNEL);
+				spin_lock (&dev->lock);
 				if (value < 0) {
 					clean_req (gadget->ep0, dev->req);
 					break;
@@ -1480,11 +1486,14 @@
 	if (value >= 0 && dev->state != STATE_DEV_SETUP) {
 		req->length = value;
 		req->zero = value < w_length;
-		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
+
+		spin_unlock (&dev->lock);
+		value = usb_ep_queue (gadget->ep0, req, GFP_KERNEL);
 		if (value < 0) {
 			DBG (dev, "ep_queue --> %d\n", value);
 			req->status = 0;
 		}
+		return value;
 	}
 
 	/* device stalls when value < 0 */
@@ -1667,9 +1676,10 @@
 gadgetfs_suspend (struct usb_gadget *gadget)
 {
 	struct dev_data		*dev = get_gadget_data (gadget);
+	unsigned long		flags;
 
 	INFO (dev, "suspended from state %d\n", dev->state);
-	spin_lock (&dev->lock);
+	spin_lock_irqsave(&dev->lock, flags);
 	switch (dev->state) {
 	case STATE_DEV_SETUP:		// VERY odd... host died??
 	case STATE_DEV_CONNECTED:
@@ -1680,7 +1690,7 @@
 	default:
 		break;
 	}
-	spin_unlock (&dev->lock);
+	spin_unlock_irqrestore(&dev->lock, flags);
 }
 
 static struct usb_gadget_driver gadgetfs_driver = {
@@ -1746,10 +1756,12 @@
  * such as configuration notifications.
  */
 
-static int is_valid_config (struct usb_config_descriptor *config)
+static int is_valid_config(struct usb_config_descriptor *config,
+		unsigned int total)
 {
 	return config->bDescriptorType == USB_DT_CONFIG
 		&& config->bLength == USB_DT_CONFIG_SIZE
+		&& total >= USB_DT_CONFIG_SIZE
 		&& config->bConfigurationValue != 0
 		&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
 		&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
@@ -1774,7 +1786,8 @@
 	}
 	spin_unlock_irq(&dev->lock);
 
-	if (len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4))
+	if ((len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4)) ||
+	    (len > PAGE_SIZE * 4))
 		return -EINVAL;
 
 	/* we might need to change message format someday */
@@ -1798,7 +1811,8 @@
 	/* full or low speed config */
 	dev->config = (void *) kbuf;
 	total = le16_to_cpu(dev->config->wTotalLength);
-	if (!is_valid_config (dev->config) || total >= length)
+	if (!is_valid_config(dev->config, total) ||
+			total > length - USB_DT_DEVICE_SIZE)
 		goto fail;
 	kbuf += total;
 	length -= total;
@@ -1807,10 +1821,13 @@
 	if (kbuf [1] == USB_DT_CONFIG) {
 		dev->hs_config = (void *) kbuf;
 		total = le16_to_cpu(dev->hs_config->wTotalLength);
-		if (!is_valid_config (dev->hs_config) || total >= length)
+		if (!is_valid_config(dev->hs_config, total) ||
+				total > length - USB_DT_DEVICE_SIZE)
 			goto fail;
 		kbuf += total;
 		length -= total;
+	} else {
+		dev->hs_config = NULL;
 	}
 
 	/* could support multiple configs, using another encoding! */
diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c
index bda3c51..99aa22c 100644
--- a/drivers/usb/gadget/legacy/mass_storage.c
+++ b/drivers/usb/gadget/legacy/mass_storage.c
@@ -132,10 +132,6 @@
 	if (IS_ERR(f_msg))
 		return PTR_ERR(f_msg);
 
-	ret = fsg_common_run_thread(opts->common);
-	if (ret)
-		goto put_func;
-
 	ret = usb_add_function(c, f_msg);
 	if (ret)
 		goto put_func;
diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c
index 4fe794d..09c7c28 100644
--- a/drivers/usb/gadget/legacy/multi.c
+++ b/drivers/usb/gadget/legacy/multi.c
@@ -137,7 +137,6 @@
 
 static int rndis_do_config(struct usb_configuration *c)
 {
-	struct fsg_opts *fsg_opts;
 	int ret;
 
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -169,11 +168,6 @@
 		goto err_fsg;
 	}
 
-	fsg_opts = fsg_opts_from_func_inst(fi_msg);
-	ret = fsg_common_run_thread(fsg_opts->common);
-	if (ret)
-		goto err_run;
-
 	ret = usb_add_function(c, f_msg_rndis);
 	if (ret)
 		goto err_run;
@@ -225,7 +219,6 @@
 
 static int cdc_do_config(struct usb_configuration *c)
 {
-	struct fsg_opts *fsg_opts;
 	int ret;
 
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -258,11 +251,6 @@
 		goto err_fsg;
 	}
 
-	fsg_opts = fsg_opts_from_func_inst(fi_msg);
-	ret = fsg_common_run_thread(fsg_opts->common);
-	if (ret)
-		goto err_run;
-
 	ret = usb_add_function(c, f_msg_multi);
 	if (ret)
 		goto err_run;
diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c
index 8b3f6fb..05d3f79 100644
--- a/drivers/usb/gadget/legacy/nokia.c
+++ b/drivers/usb/gadget/legacy/nokia.c
@@ -152,7 +152,6 @@
 	struct usb_function *f_ecm;
 	struct usb_function *f_obex2 = NULL;
 	struct usb_function *f_msg;
-	struct fsg_opts *fsg_opts;
 	int status = 0;
 	int obex1_stat = -1;
 	int obex2_stat = -1;
@@ -222,12 +221,6 @@
 		goto err_ecm;
 	}
 
-	fsg_opts = fsg_opts_from_func_inst(fi_msg);
-
-	status = fsg_common_run_thread(fsg_opts->common);
-	if (status)
-		goto err_msg;
-
 	status = usb_add_function(c, f_msg);
 	if (status)
 		goto err_msg;
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index dde4445..64f404a 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -330,7 +330,7 @@
 /* caller must hold lock */
 static void stop_activity(struct dummy *dum)
 {
-	struct dummy_ep	*ep;
+	int i;
 
 	/* prevent any more requests */
 	dum->address = 0;
@@ -338,8 +338,8 @@
 	/* The timer is left running so that outstanding URBs can fail */
 
 	/* nuke any pending requests first, so driver i/o is quiesced */
-	list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list)
-		nuke(dum, ep);
+	for (i = 0; i < DUMMY_ENDPOINTS; ++i)
+		nuke(dum, &dum->ep[i]);
 
 	/* driver now does any non-usb quiescing necessary */
 }
@@ -442,23 +442,16 @@
 		/* Report reset and disconnect events to the driver */
 		if (dum->driver && (disconnect || reset)) {
 			stop_activity(dum);
-			spin_unlock(&dum->lock);
 			if (reset)
 				usb_gadget_udc_reset(&dum->gadget, dum->driver);
 			else
 				dum->driver->disconnect(&dum->gadget);
-			spin_lock(&dum->lock);
 		}
 	} else if (dum_hcd->active != dum_hcd->old_active) {
-		if (dum_hcd->old_active && dum->driver->suspend) {
-			spin_unlock(&dum->lock);
+		if (dum_hcd->old_active && dum->driver->suspend)
 			dum->driver->suspend(&dum->gadget);
-			spin_lock(&dum->lock);
-		} else if (!dum_hcd->old_active &&  dum->driver->resume) {
-			spin_unlock(&dum->lock);
+		else if (!dum_hcd->old_active &&  dum->driver->resume)
 			dum->driver->resume(&dum->gadget);
-			spin_lock(&dum->lock);
-		}
 	}
 
 	dum_hcd->old_status = dum_hcd->port_status;
@@ -985,7 +978,9 @@
 	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
 	struct dummy		*dum = dum_hcd->dum;
 
+	spin_lock_irq(&dum->lock);
 	dum->driver = NULL;
+	spin_unlock_irq(&dum->lock);
 
 	return 0;
 }
@@ -1033,6 +1028,8 @@
 	int		rc;
 
 	dum = *((void **)dev_get_platdata(&pdev->dev));
+	/* Clear usb_gadget region for new registration to udc-core */
+	memzero_explicit(&dum->gadget, sizeof(struct usb_gadget));
 	dum->gadget.name = gadget_name;
 	dum->gadget.ops = &dummy_ops;
 	dum->gadget.max_speed = USB_SPEED_SUPER;
@@ -2009,7 +2006,7 @@
 			HUB_CHAR_COMMON_OCPM);
 	desc->bNbrPorts = 1;
 	desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
-	desc->u.ss.DeviceRemovable = 0xffff;
+	desc->u.ss.DeviceRemovable = 0;
 }
 
 static inline void hub_descriptor(struct usb_hub_descriptor *desc)
@@ -2021,8 +2018,8 @@
 			HUB_CHAR_INDV_PORT_LPSM |
 			HUB_CHAR_COMMON_OCPM);
 	desc->bNbrPorts = 1;
-	desc->u.hs.DeviceRemovable[0] = 0xff;
-	desc->u.hs.DeviceRemovable[1] = 0xff;
+	desc->u.hs.DeviceRemovable[0] = 0;
+	desc->u.hs.DeviceRemovable[1] = 0xff;	/* PortPwrCtrlMask */
 }
 
 static int dummy_hub_control(
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index 5fb6f8b..b38a335 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -1878,11 +1878,8 @@
 
 	tmp = in_be16(&udc->usb_param->frame_n);
 	if (tmp & 0x8000)
-		tmp = tmp & 0x07ff;
-	else
-		tmp = -EINVAL;
-
-	return (int)tmp;
+		return tmp & 0x07ff;
+	return -EINVAL;
 }
 
 static int fsl_qe_start(struct usb_gadget *gadget,
@@ -2053,7 +2050,7 @@
 			struct qe_ep *ep;
 
 			if (wValue != 0 || wLength != 0
-				|| pipe > USB_MAX_ENDPOINTS)
+				|| pipe >= USB_MAX_ENDPOINTS)
 				break;
 			ep = &udc->eps[pipe];
 
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index aab5221..aac0ce8 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -1249,6 +1249,12 @@
 	.udc_stop = fsl_udc_stop,
 };
 
+/*
+ * Empty complete function used by this driver to fill in the req->complete
+ * field when creating a request since the complete field is mandatory.
+ */
+static void fsl_noop_complete(struct usb_ep *ep, struct usb_request *req) { }
+
 /* Set protocol stall on ep0, protocol stall will automatically be cleared
    on new transaction */
 static void ep0stall(struct fsl_udc *udc)
@@ -1283,7 +1289,7 @@
 	req->req.length = 0;
 	req->req.status = -EINPROGRESS;
 	req->req.actual = 0;
-	req->req.complete = NULL;
+	req->req.complete = fsl_noop_complete;
 	req->dtd_count = 0;
 
 	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
@@ -1366,7 +1372,7 @@
 	req->req.length = 2;
 	req->req.status = -EINPROGRESS;
 	req->req.actual = 0;
-	req->req.complete = NULL;
+	req->req.complete = fsl_noop_complete;
 	req->dtd_count = 0;
 
 	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index 6706aef..a47de8c 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -2425,11 +2425,8 @@
 		nuke(&dev->ep[i]);
 
 	/* report disconnect; the driver is already quiesced */
-	if (driver) {
-		spin_unlock(&dev->lock);
+	if (driver)
 		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
 
 	usb_reinit(dev);
 }
@@ -3275,8 +3272,6 @@
 		BIT(PCI_RETRY_ABORT_INTERRUPT))
 
 static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
-__releases(dev->lock)
-__acquires(dev->lock)
 {
 	struct net2280_ep	*ep;
 	u32			tmp, num, mask, scratch;
@@ -3317,14 +3312,12 @@
 			if (disconnect || reset) {
 				stop_activity(dev, dev->driver);
 				ep0_start(dev);
-				spin_unlock(&dev->lock);
 				if (reset)
 					usb_gadget_udc_reset
 						(&dev->gadget, dev->driver);
 				else
 					(dev->driver->disconnect)
 						(&dev->gadget);
-				spin_lock(&dev->lock);
 				return;
 			}
 		}
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index f660afb..89f7cd6 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -71,7 +71,7 @@
 		mapped = dma_map_sg(dev, req->sg, req->num_sgs,
 				is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 		if (mapped == 0) {
-			dev_err(&gadget->dev, "failed to map SGs\n");
+			dev_err(dev, "failed to map SGs\n");
 			return -EFAULT;
 		}
 
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index df538fd..46f5354 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -77,10 +77,12 @@
 		if (IS_ERR(phy)) {
 			ret = PTR_ERR(phy);
 			if (ret == -EPROBE_DEFER) {
+				of_node_put(child);
 				return ret;
 			} else if (ret != -ENOSYS && ret != -ENODEV) {
 				dev_err(dev,
 					"Error retrieving usb2 phy: %d\n", ret);
+				of_node_put(child);
 				return ret;
 			}
 		}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 48c92bf..f7661d9 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -332,11 +332,11 @@
 	int	port = HCS_N_PORTS(ehci->hcs_params);
 
 	while (port--) {
-		ehci_writel(ehci, PORT_RWC_BITS,
-				&ehci->regs->port_status[port]);
 		spin_unlock_irq(&ehci->lock);
 		ehci_port_power(ehci, port, false);
 		spin_lock_irq(&ehci->lock);
+		ehci_writel(ehci, PORT_RWC_BITS,
+				&ehci->regs->port_status[port]);
 	}
 }
 
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 4031b37..c1c1024 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -89,7 +89,7 @@
 	if (!usb1_reset_attempted) {
 		struct reset_control *usb1_reset;
 
-		usb1_reset = of_reset_control_get(phy_np, "usb");
+		usb1_reset = of_reset_control_get(phy_np, "utmi-pads");
 		if (IS_ERR(usb1_reset)) {
 			dev_warn(&pdev->dev,
 				 "can't get utmi-pads reset from the PHY\n");
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 2cd105b..6865b91 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -66,10 +66,12 @@
 		if (IS_ERR(phy)) {
 			ret = PTR_ERR(phy);
 			if (ret == -EPROBE_DEFER) {
+				of_node_put(child);
 				return ret;
 			} else if (ret != -ENOSYS && ret != -ENODEV) {
 				dev_err(dev,
 					"Error retrieving usb2 phy: %d\n", ret);
+				of_node_put(child);
 				return ret;
 			}
 		}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 760cb57..9d1192a 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -72,7 +72,7 @@
 static const char	hcd_name [] = "ohci_hcd";
 
 #define	STATECHANGE_DELAY	msecs_to_jiffies(300)
-#define	IO_WATCHDOG_DELAY	msecs_to_jiffies(250)
+#define	IO_WATCHDOG_DELAY	msecs_to_jiffies(275)
 
 #include "ohci.h"
 #include "pci-quirks.h"
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index d029bbe..641fed6 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -183,7 +183,6 @@
 {
 	int	branch;
 
-	ed->state = ED_OPER;
 	ed->ed_prev = NULL;
 	ed->ed_next = NULL;
 	ed->hwNextED = 0;
@@ -259,6 +258,8 @@
 	/* the HC may not see the schedule updates yet, but if it does
 	 * then they'll be properly ordered.
 	 */
+
+	ed->state = ED_OPER;
 	return 0;
 }
 
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 4cbd063..a11c2c8 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -1269,7 +1269,7 @@
 			time = 30;
 			break;
 		default:
-			time = 300;
+			time = 50;
 			break;
 		}
 
@@ -1785,6 +1785,7 @@
 		pipe = td->pipe;
 		pipe_stop(r8a66597, pipe);
 
+		/* Select a different address or endpoint */
 		new_td = td;
 		do {
 			list_move_tail(&new_td->queue,
@@ -1794,7 +1795,8 @@
 				new_td = td;
 				break;
 			}
-		} while (td != new_td && td->address == new_td->address);
+		} while (td != new_td && td->address == new_td->address &&
+			td->pipe->info.epnum == new_td->pipe->info.epnum);
 
 		start_transfer(r8a66597, new_td);
 
diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c
index 940304c..02260cf 100644
--- a/drivers/usb/host/uhci-pci.c
+++ b/drivers/usb/host/uhci-pci.c
@@ -129,6 +129,10 @@
 	if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_HP)
 		uhci->wait_for_hp = 1;
 
+	/* Intel controllers use non-PME wakeup signalling */
+	if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_INTEL)
+		device_set_run_wake(uhci_dev(uhci), 1);
+
 	/* Set up pointers to PCI-specific functions */
 	uhci->reset_hc = uhci_pci_reset_hc;
 	uhci->check_and_reset_hc = uhci_pci_check_and_reset_hc;
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 74c42f7..3425154 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -111,7 +111,7 @@
 	xhci_dbg(xhci, "RTSOFF 0x%x:\n", temp & RTSOFF_MASK);
 
 	/* xhci 1.1 controllers have the HCCPARAMS2 register */
-	if (hci_version > 100) {
+	if (hci_version > 0x100) {
 		temp = readl(&xhci->cap_regs->hcc_params2);
 		xhci_dbg(xhci, "HCC PARAMS2 0x%x:\n", (unsigned int) temp);
 		xhci_dbg(xhci, "  HC %s Force save context capability",
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index f980c23..e9675e8 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -377,6 +377,9 @@
 
 	ret = 0;
 	virt_dev = xhci->devs[slot_id];
+	if (!virt_dev)
+		return -ENODEV;
+
 	cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
 	if (!cmd) {
 		xhci_dbg(xhci, "Couldn't allocate command structure.\n");
@@ -1154,7 +1157,7 @@
 				xhci_set_link_state(xhci, port_array, wIndex,
 							XDEV_RESUME);
 				spin_unlock_irqrestore(&xhci->lock, flags);
-				msleep(20);
+				msleep(USB_RESUME_TIMEOUT);
 				spin_lock_irqsave(&xhci->lock, flags);
 				xhci_set_link_state(xhci, port_array, wIndex,
 							XDEV_U0);
@@ -1343,6 +1346,35 @@
 	return 0;
 }
 
+/*
+ * Workaround for missing Cold Attach Status (CAS) if device re-plugged in S3.
+ * warm reset a USB3 device stuck in polling or compliance mode after resume.
+ * See Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8
+ */
+static bool xhci_port_missing_cas_quirk(int port_index,
+					     __le32 __iomem **port_array)
+{
+	u32 portsc;
+
+	portsc = readl(port_array[port_index]);
+
+	/* if any of these are set we are not stuck */
+	if (portsc & (PORT_CONNECT | PORT_CAS))
+		return false;
+
+	if (((portsc & PORT_PLS_MASK) != XDEV_POLLING) &&
+	    ((portsc & PORT_PLS_MASK) != XDEV_COMP_MODE))
+		return false;
+
+	/* clear wakeup/change bits, and do a warm port reset */
+	portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
+	portsc |= PORT_WR;
+	writel(portsc, port_array[port_index]);
+	/* flush write */
+	readl(port_array[port_index]);
+	return true;
+}
+
 int xhci_bus_resume(struct usb_hcd *hcd)
 {
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
@@ -1380,6 +1412,14 @@
 		u32 temp;
 
 		temp = readl(port_array[port_index]);
+
+		/* warm reset CAS limited ports stuck in polling/compliance */
+		if ((xhci->quirks & XHCI_MISSING_CAS) &&
+		    (hcd->speed >= HCD_USB3) &&
+		    xhci_port_missing_cas_quirk(port_index, port_array)) {
+			xhci_dbg(xhci, "reset stuck port %d\n", port_index);
+			continue;
+		}
 		if (DEV_SUPERSPEED_ANY(temp))
 			temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
 		else
@@ -1398,7 +1438,7 @@
 
 	if (need_usb2_u3_exit) {
 		spin_unlock_irqrestore(&xhci->lock, flags);
-		msleep(20);
+		msleep(USB_RESUME_TIMEOUT);
 		spin_lock_irqsave(&xhci->lock, flags);
 	}
 
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d8dbd7e..cf6bbaf 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -964,6 +964,40 @@
 	xhci->devs[slot_id] = NULL;
 }
 
+/*
+ * Free a virt_device structure.
+ * If the virt_device added a tt_info (a hub) and has children pointing to
+ * that tt_info, then free the child first. Recursive.
+ * We can't rely on udev at this point to find child-parent relationships.
+ */
+void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_id)
+{
+	struct xhci_virt_device *vdev;
+	struct list_head *tt_list_head;
+	struct xhci_tt_bw_info *tt_info, *next;
+	int i;
+
+	vdev = xhci->devs[slot_id];
+	if (!vdev)
+		return;
+
+	tt_list_head = &(xhci->rh_bw[vdev->real_port - 1].tts);
+	list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) {
+		/* is this a hub device that added a tt_info to the tts list */
+		if (tt_info->slot_id == slot_id) {
+			/* are any devices using this tt_info? */
+			for (i = 1; i < HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
+				vdev = xhci->devs[i];
+				if (vdev && (vdev->tt_info == tt_info))
+					xhci_free_virt_devices_depth_first(
+						xhci, i);
+			}
+		}
+	}
+	/* we are now at a leaf device */
+	xhci_free_virt_device(xhci, slot_id);
+}
+
 int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
 		struct usb_device *udev, gfp_t flags)
 {
@@ -1072,7 +1106,7 @@
 	struct usb_device *top_dev;
 	struct usb_hcd *hcd;
 
-	if (udev->speed == USB_SPEED_SUPER)
+	if (udev->speed >= USB_SPEED_SUPER)
 		hcd = xhci->shared_hcd;
 	else
 		hcd = xhci->main_hcd;
@@ -1107,6 +1141,7 @@
 	/* 3) Only the control endpoint is valid - one endpoint context */
 	slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route);
 	switch (udev->speed) {
+	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_SUPER:
 		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS);
 		max_packets = MAX_PACKET(512);
@@ -1294,6 +1329,7 @@
 		}
 		/* Fall through - SS and HS isoc/int have same decoding */
 
+	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_SUPER:
 		if (usb_endpoint_xfer_int(&ep->desc) ||
 		    usb_endpoint_xfer_isoc(&ep->desc)) {
@@ -1334,7 +1370,7 @@
 static u32 xhci_get_endpoint_mult(struct usb_device *udev,
 		struct usb_host_endpoint *ep)
 {
-	if (udev->speed != USB_SPEED_SUPER ||
+	if (udev->speed < USB_SPEED_SUPER ||
 			!usb_endpoint_xfer_isoc(&ep->desc))
 		return 0;
 	return ep->ss_ep_comp.bmAttributes;
@@ -1384,7 +1420,7 @@
 			usb_endpoint_xfer_bulk(&ep->desc))
 		return 0;
 
-	if (udev->speed == USB_SPEED_SUPER)
+	if (udev->speed >= USB_SPEED_SUPER)
 		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
 
 	max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
@@ -1455,6 +1491,7 @@
 	max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
 	max_burst = 0;
 	switch (udev->speed) {
+	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_SUPER:
 		/* dig out max burst from ep companion desc */
 		max_burst = ep->ss_ep_comp.bMaxBurst;
@@ -1672,7 +1709,7 @@
 	xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma);
 	for (i = 0; i < num_sp; i++) {
 		dma_addr_t dma;
-		void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma,
+		void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma,
 				flags);
 		if (!buf)
 			goto fail_sp5;
@@ -1792,7 +1829,7 @@
 	int size;
 	int i, j, num_ports;
 
-	del_timer_sync(&xhci->cmd_timer);
+	cancel_delayed_work_sync(&xhci->cmd_timer);
 
 	/* Free the Event Ring Segment Table and the actual Event Ring */
 	size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
@@ -1825,8 +1862,8 @@
 		}
 	}
 
-	for (i = 1; i < MAX_HC_SLOTS; ++i)
-		xhci_free_virt_device(xhci, i);
+	for (i = HCS_MAX_SLOTS(xhci->hcs_params1); i > 0; i--)
+		xhci_free_virt_devices_depth_first(xhci, i);
 
 	dma_pool_destroy(xhci->segment_pool);
 	xhci->segment_pool = NULL;
@@ -2358,9 +2395,9 @@
 
 	INIT_LIST_HEAD(&xhci->cmd_list);
 
-	/* init command timeout timer */
-	setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
-		    (unsigned long)xhci);
+	/* init command timeout work */
+	INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout);
+	init_completion(&xhci->cmd_ring_stop_completion);
 
 	page_size = readl(&xhci->op_regs->page_size);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
@@ -2399,7 +2436,7 @@
 	 * "physically contiguous and 64-byte (cache line) aligned".
 	 */
 	xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma,
-			GFP_KERNEL);
+			flags);
 	if (!xhci->dcbaa)
 		goto fail;
 	memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa));
@@ -2456,7 +2493,7 @@
 		(xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
 		xhci->cmd_ring->cycle_state;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"// Setting command ring address to 0x%x", val);
+			"// Setting command ring address to 0x%016llx", val_64);
 	xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
 	xhci_dbg_cmd_ptrs(xhci);
 
@@ -2495,7 +2532,7 @@
 
 	xhci->erst.entries = dma_alloc_coherent(dev,
 			sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS, &dma,
-			GFP_KERNEL);
+			flags);
 	if (!xhci->erst.entries)
 		goto fail;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index ea4fb4b..e8f9906 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -37,6 +37,7 @@
 /* Device for a quirk */
 #define PCI_VENDOR_ID_FRESCO_LOGIC	0x1b73
 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK	0x1000
+#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1009	0x1009
 #define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400	0x1400
 
 #define PCI_VENDOR_ID_ETRON		0x1b6f
@@ -44,11 +45,14 @@
 
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI	0x8c31
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI	0x9c31
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI	0x9cb1
 #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI		0x22b5
 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI		0xa12f
 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI	0x9d2f
 #define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI		0x0aa8
 #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI		0x1aa8
+#define PCI_DEVICE_ID_INTEL_APL_XHCI			0x5aa8
+#define PCI_DEVICE_ID_INTEL_DNV_XHCI			0x19d0
 
 static const char hcd_name[] = "xhci_hcd";
 
@@ -115,6 +119,10 @@
 		xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 	}
 
+	if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
+			pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1009)
+		xhci->quirks |= XHCI_BROKEN_STREAMS;
+
 	if (pdev->vendor == PCI_VENDOR_ID_NEC)
 		xhci->quirks |= XHCI_NEC_HOST;
 
@@ -149,7 +157,8 @@
 		xhci->quirks |= XHCI_SPURIOUS_REBOOT;
 	}
 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
-		pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
+		(pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI ||
+		 pdev->device == PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI)) {
 		xhci->quirks |= XHCI_SPURIOUS_REBOOT;
 		xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
 	}
@@ -158,9 +167,17 @@
 		 pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
 		 pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
 		 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI ||
-		 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI)) {
+		 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI ||
+		 pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
+		 pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) {
 		xhci->quirks |= XHCI_PME_STUCK_QUIRK;
 	}
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+	    (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+	     pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
+	     pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI))
+		xhci->quirks |= XHCI_MISSING_CAS;
+
 	if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
 			pdev->device == PCI_DEVICE_ID_EJ168) {
 		xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -181,6 +198,9 @@
 	if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
 			pdev->device == 0x1042)
 		xhci->quirks |= XHCI_BROKEN_STREAMS;
+	if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+			pdev->device == 0x1142)
+		xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 
 	if (xhci->quirks & XHCI_RESET_ON_RESUME)
 		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
@@ -306,11 +326,12 @@
 		usb_remove_hcd(xhci->shared_hcd);
 		usb_put_hcd(xhci->shared_hcd);
 	}
-	usb_hcd_pci_remove(dev);
 
 	/* Workaround for spurious wakeups at shutdown with HSW */
 	if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
 		pci_set_power_state(dev, PCI_D3hot);
+
+	usb_hcd_pci_remove(dev);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 05647e6..062cf8a 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -92,7 +92,7 @@
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
-		return -ENODEV;
+		return irq;
 
 	/* Try to set 64-bit DMA first */
 	if (WARN_ON(!pdev->dev.dma_mask))
@@ -132,6 +132,9 @@
 		ret = clk_prepare_enable(clk);
 		if (ret)
 			goto put_hcd;
+	} else if (PTR_ERR(clk) == -EPROBE_DEFER) {
+		ret = -EPROBE_DEFER;
+		goto put_hcd;
 	}
 
 	if (of_device_is_compatible(pdev->dev.of_node,
@@ -159,9 +162,6 @@
 			(pdata && pdata->usb3_lpm_capable))
 		xhci->quirks |= XHCI_LPM_SUPPORT;
 
-	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
-		xhci->shared_hcd->can_do_streams = 1;
-
 	hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
 	if (IS_ERR(hcd->usb_phy)) {
 		ret = PTR_ERR(hcd->usb_phy);
@@ -178,6 +178,9 @@
 	if (ret)
 		goto disable_usb_phy;
 
+	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+		xhci->shared_hcd->can_do_streams = 1;
+
 	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
 	if (ret)
 		goto dealloc_usb2_hcd;
@@ -210,6 +213,8 @@
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	struct clk *clk = xhci->clk;
 
+	xhci->xhc_state |= XHCI_STATE_REMOVING;
+
 	usb_remove_hcd(xhci->shared_hcd);
 	usb_phy_shutdown(hcd->usb_phy);
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2b63969..de7dce6 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -280,15 +280,76 @@
 	readl(&xhci->dba->doorbell[0]);
 }
 
-static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
+static bool xhci_mod_cmd_timer(struct xhci_hcd *xhci, unsigned long delay)
+{
+	return mod_delayed_work(system_wq, &xhci->cmd_timer, delay);
+}
+
+static struct xhci_command *xhci_next_queued_cmd(struct xhci_hcd *xhci)
+{
+	return list_first_entry_or_null(&xhci->cmd_list, struct xhci_command,
+					cmd_list);
+}
+
+/*
+ * Turn all commands on command ring with status set to "aborted" to no-op trbs.
+ * If there are other commands waiting then restart the ring and kick the timer.
+ * This must be called with command ring stopped and xhci->lock held.
+ */
+static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
+					 struct xhci_command *cur_cmd)
+{
+	struct xhci_command *i_cmd;
+	u32 cycle_state;
+
+	/* Turn all aborted commands in list to no-ops, then restart */
+	list_for_each_entry(i_cmd, &xhci->cmd_list, cmd_list) {
+
+		if (i_cmd->status != COMP_CMD_ABORT)
+			continue;
+
+		i_cmd->status = COMP_CMD_STOP;
+
+		xhci_dbg(xhci, "Turn aborted command %p to no-op\n",
+			 i_cmd->command_trb);
+		/* get cycle state from the original cmd trb */
+		cycle_state = le32_to_cpu(
+			i_cmd->command_trb->generic.field[3]) &	TRB_CYCLE;
+		/* modify the command trb to no-op command */
+		i_cmd->command_trb->generic.field[0] = 0;
+		i_cmd->command_trb->generic.field[1] = 0;
+		i_cmd->command_trb->generic.field[2] = 0;
+		i_cmd->command_trb->generic.field[3] = cpu_to_le32(
+			TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
+
+		/*
+		 * caller waiting for completion is called when command
+		 *  completion event is received for these no-op commands
+		 */
+	}
+
+	xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
+
+	/* ring command ring doorbell to restart the command ring */
+	if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
+	    !(xhci->xhc_state & XHCI_STATE_DYING)) {
+		xhci->current_cmd = cur_cmd;
+		xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
+		xhci_ring_cmd_db(xhci);
+	}
+}
+
+/* Must be called with xhci->lock held, releases and aquires lock back */
+static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
 {
 	u64 temp_64;
 	int ret;
 
 	xhci_dbg(xhci, "Abort command ring\n");
 
+	reinit_completion(&xhci->cmd_ring_stop_completion);
+
 	temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
-	xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
 	xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
 			&xhci->op_regs->cmd_ring);
 
@@ -308,15 +369,30 @@
 		udelay(1000);
 		ret = xhci_handshake(&xhci->op_regs->cmd_ring,
 				     CMD_RING_RUNNING, 0, 3 * 1000 * 1000);
-		if (ret == 0)
-			return 0;
-
-		xhci_err(xhci, "Stopped the command ring failed, "
-				"maybe the host is dead\n");
-		xhci->xhc_state |= XHCI_STATE_DYING;
-		xhci_quiesce(xhci);
-		xhci_halt(xhci);
-		return -ESHUTDOWN;
+		if (ret < 0) {
+			xhci_err(xhci, "Stopped the command ring failed, "
+				 "maybe the host is dead\n");
+			xhci->xhc_state |= XHCI_STATE_DYING;
+			xhci_quiesce(xhci);
+			xhci_halt(xhci);
+			return -ESHUTDOWN;
+		}
+	}
+	/*
+	 * Writing the CMD_RING_ABORT bit should cause a cmd completion event,
+	 * however on some host hw the CMD_RING_RUNNING bit is correctly cleared
+	 * but the completion event in never sent. Wait 2 secs (arbitrary
+	 * number) to handle those cases after negation of CMD_RING_RUNNING.
+	 */
+	spin_unlock_irqrestore(&xhci->lock, flags);
+	ret = wait_for_completion_timeout(&xhci->cmd_ring_stop_completion,
+					  msecs_to_jiffies(2000));
+	spin_lock_irqsave(&xhci->lock, flags);
+	if (!ret) {
+		xhci_dbg(xhci, "No stop event for abort, ring start fail?\n");
+		xhci_cleanup_command_queue(xhci);
+	} else {
+		xhci_handle_stopped_cmd_ring(xhci, xhci_next_queued_cmd(xhci));
 	}
 
 	return 0;
@@ -837,13 +913,6 @@
 	spin_lock_irqsave(&xhci->lock, flags);
 
 	ep->stop_cmds_pending--;
-	if (xhci->xhc_state & XHCI_STATE_DYING) {
-		xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-				"Stop EP timer ran, but another timer marked "
-				"xHCI as DYING, exiting.");
-		spin_unlock_irqrestore(&xhci->lock, flags);
-		return;
-	}
 	if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) {
 		xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 				"Stop EP timer ran, but no command pending, "
@@ -890,7 +959,7 @@
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 			"Calling usb_hc_died()");
-	usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
+	usb_hc_died(xhci_to_hcd(xhci));
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 			"xHCI host controller is dead.");
 }
@@ -1195,93 +1264,62 @@
 		xhci_complete_del_and_free_cmd(cur_cmd, COMP_CMD_ABORT);
 }
 
-/*
- * Turn all commands on command ring with status set to "aborted" to no-op trbs.
- * If there are other commands waiting then restart the ring and kick the timer.
- * This must be called with command ring stopped and xhci->lock held.
- */
-static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
-					 struct xhci_command *cur_cmd)
-{
-	struct xhci_command *i_cmd, *tmp_cmd;
-	u32 cycle_state;
-
-	/* Turn all aborted commands in list to no-ops, then restart */
-	list_for_each_entry_safe(i_cmd, tmp_cmd, &xhci->cmd_list,
-				 cmd_list) {
-
-		if (i_cmd->status != COMP_CMD_ABORT)
-			continue;
-
-		i_cmd->status = COMP_CMD_STOP;
-
-		xhci_dbg(xhci, "Turn aborted command %p to no-op\n",
-			 i_cmd->command_trb);
-		/* get cycle state from the original cmd trb */
-		cycle_state = le32_to_cpu(
-			i_cmd->command_trb->generic.field[3]) &	TRB_CYCLE;
-		/* modify the command trb to no-op command */
-		i_cmd->command_trb->generic.field[0] = 0;
-		i_cmd->command_trb->generic.field[1] = 0;
-		i_cmd->command_trb->generic.field[2] = 0;
-		i_cmd->command_trb->generic.field[3] = cpu_to_le32(
-			TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
-
-		/*
-		 * caller waiting for completion is called when command
-		 *  completion event is received for these no-op commands
-		 */
-	}
-
-	xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
-
-	/* ring command ring doorbell to restart the command ring */
-	if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
-	    !(xhci->xhc_state & XHCI_STATE_DYING)) {
-		xhci->current_cmd = cur_cmd;
-		mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
-		xhci_ring_cmd_db(xhci);
-	}
-	return;
-}
-
-
-void xhci_handle_command_timeout(unsigned long data)
+void xhci_handle_command_timeout(struct work_struct *work)
 {
 	struct xhci_hcd *xhci;
 	int ret;
 	unsigned long flags;
 	u64 hw_ring_state;
-	struct xhci_command *cur_cmd = NULL;
-	xhci = (struct xhci_hcd *) data;
 
-	/* mark this command to be cancelled */
+	xhci = container_of(to_delayed_work(work), struct xhci_hcd, cmd_timer);
+
 	spin_lock_irqsave(&xhci->lock, flags);
-	if (xhci->current_cmd) {
-		cur_cmd = xhci->current_cmd;
-		cur_cmd->status = COMP_CMD_ABORT;
-	}
 
+	/*
+	 * If timeout work is pending, or current_cmd is NULL, it means we
+	 * raced with command completion. Command is handled so just return.
+	 */
+	if (!xhci->current_cmd || delayed_work_pending(&xhci->cmd_timer)) {
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		return;
+	}
+	/* mark this command to be cancelled */
+	xhci->current_cmd->status = COMP_CMD_ABORT;
 
 	/* Make sure command ring is running before aborting it */
 	hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
 	if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
 	    (hw_ring_state & CMD_RING_RUNNING))  {
-
-		spin_unlock_irqrestore(&xhci->lock, flags);
+		/* Prevent new doorbell, and start command abort */
+		xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
 		xhci_dbg(xhci, "Command timeout\n");
-		ret = xhci_abort_cmd_ring(xhci);
+		ret = xhci_abort_cmd_ring(xhci, flags);
 		if (unlikely(ret == -ESHUTDOWN)) {
 			xhci_err(xhci, "Abort command ring failed\n");
 			xhci_cleanup_command_queue(xhci);
+			spin_unlock_irqrestore(&xhci->lock, flags);
 			usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
 			xhci_dbg(xhci, "xHCI host controller is dead.\n");
+
+			return;
 		}
-		return;
+
+		goto time_out_completed;
 	}
+
+	/* host removed. Bail out */
+	if (xhci->xhc_state & XHCI_STATE_REMOVING) {
+		xhci_dbg(xhci, "host removed, ring start fail?\n");
+		xhci_cleanup_command_queue(xhci);
+
+		goto time_out_completed;
+	}
+
 	/* command timeout on stopped ring, ring can't be aborted */
 	xhci_dbg(xhci, "Command timeout on stopped ring\n");
 	xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
+
+time_out_completed:
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	return;
 }
@@ -1314,13 +1352,7 @@
 
 	cmd = list_entry(xhci->cmd_list.next, struct xhci_command, cmd_list);
 
-	if (cmd->command_trb != xhci->cmd_ring->dequeue) {
-		xhci_err(xhci,
-			 "Command completion event does not match command\n");
-		return;
-	}
-
-	del_timer(&xhci->cmd_timer);
+	cancel_delayed_work(&xhci->cmd_timer);
 
 	trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
 
@@ -1328,9 +1360,16 @@
 
 	/* If CMD ring stopped we own the trbs between enqueue and dequeue */
 	if (cmd_comp_code == COMP_CMD_STOP) {
-		xhci_handle_stopped_cmd_ring(xhci, cmd);
+		complete_all(&xhci->cmd_ring_stop_completion);
 		return;
 	}
+
+	if (cmd->command_trb != xhci->cmd_ring->dequeue) {
+		xhci_err(xhci,
+			 "Command completion event does not match command\n");
+		return;
+	}
+
 	/*
 	 * Host aborted the command ring, check if the current command was
 	 * supposed to be aborted, otherwise continue normally.
@@ -1339,8 +1378,11 @@
 	 */
 	if (cmd_comp_code == COMP_CMD_ABORT) {
 		xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
-		if (cmd->status == COMP_CMD_ABORT)
+		if (cmd->status == COMP_CMD_ABORT) {
+			if (xhci->current_cmd == cmd)
+				xhci->current_cmd = NULL;
 			goto event_handled;
+		}
 	}
 
 	cmd_type = TRB_FIELD_TO_TYPE(le32_to_cpu(cmd_trb->generic.field[3]));
@@ -1401,7 +1443,9 @@
 	if (cmd->cmd_list.next != &xhci->cmd_list) {
 		xhci->current_cmd = list_entry(cmd->cmd_list.next,
 					       struct xhci_command, cmd_list);
-		mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+		xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
+	} else if (xhci->current_cmd == cmd) {
+		xhci->current_cmd = NULL;
 	}
 
 event_handled:
@@ -2727,7 +2771,8 @@
 		writel(irq_pending, &xhci->ir_set->irq_pending);
 	}
 
-	if (xhci->xhc_state & XHCI_STATE_DYING) {
+	if (xhci->xhc_state & XHCI_STATE_DYING ||
+	    xhci->xhc_state & XHCI_STATE_HALTED) {
 		xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
 				"Shouldn't IRQs be disabled?\n");
 		/* Clear the event handler busy flag (RW1C);
@@ -3557,7 +3602,7 @@
 {
 	unsigned int max_burst;
 
-	if (xhci->hci_version < 0x100 || udev->speed != USB_SPEED_SUPER)
+	if (xhci->hci_version < 0x100 || udev->speed < USB_SPEED_SUPER)
 		return 0;
 
 	max_burst = urb->ep->ss_ep_comp.bMaxBurst;
@@ -3583,6 +3628,7 @@
 		return 0;
 
 	switch (udev->speed) {
+	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_SUPER:
 		/* bMaxBurst is zero based: 0 means 1 packet per burst */
 		max_burst = urb->ep->ss_ep_comp.bMaxBurst;
@@ -4032,9 +4078,9 @@
 
 	/* if there are no other commands queued we start the timeout timer */
 	if (xhci->cmd_list.next == &cmd->cmd_list &&
-	    !timer_pending(&xhci->cmd_timer)) {
+	    !delayed_work_pending(&xhci->cmd_timer)) {
 		xhci->current_cmd = cmd;
-		mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+		xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
 	}
 
 	queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index ec9e758..f2e9f59 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -680,20 +680,23 @@
 	u32 temp;
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
-	if (xhci->xhc_state & XHCI_STATE_HALTED)
-		return;
-
 	mutex_lock(&xhci->mutex);
-	spin_lock_irq(&xhci->lock);
-	xhci->xhc_state |= XHCI_STATE_HALTED;
-	xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
 
-	/* Make sure the xHC is halted for a USB3 roothub
-	 * (xhci_stop() could be called as part of failed init).
-	 */
-	xhci_halt(xhci);
-	xhci_reset(xhci);
-	spin_unlock_irq(&xhci->lock);
+	if (!(xhci->xhc_state & XHCI_STATE_HALTED)) {
+		spin_lock_irq(&xhci->lock);
+
+		xhci->xhc_state |= XHCI_STATE_HALTED;
+		xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+		xhci_halt(xhci);
+		xhci_reset(xhci);
+
+		spin_unlock_irq(&xhci->lock);
+	}
+
+	if (!usb_hcd_is_primary_hcd(hcd)) {
+		mutex_unlock(&xhci->mutex);
+		return;
+	}
 
 	xhci_cleanup_msix(xhci);
 
@@ -1566,19 +1569,6 @@
 		xhci_urb_free_priv(urb_priv);
 		return ret;
 	}
-	if ((xhci->xhc_state & XHCI_STATE_DYING) ||
-			(xhci->xhc_state & XHCI_STATE_HALTED)) {
-		xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-				"Ep 0x%x: URB %p to be canceled on "
-				"non-responsive xHCI host.",
-				urb->ep->desc.bEndpointAddress, urb);
-		/* Let the stop endpoint command watchdog timer (which set this
-		 * state) finish cleaning up the endpoint TD lists.  We must
-		 * have caught it in the middle of dropping a lock and giving
-		 * back an URB.
-		 */
-		goto done;
-	}
 
 	ep_index = xhci_get_endpoint_index(&urb->ep->desc);
 	ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index];
@@ -2070,6 +2060,7 @@
 	case USB_SPEED_HIGH:
 		return HS_BLOCK;
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
 		return SS_BLOCK;
 	case USB_SPEED_UNKNOWN:
 	case USB_SPEED_WIRELESS:
@@ -2195,7 +2186,7 @@
 	unsigned int packets_remaining = 0;
 	unsigned int i;
 
-	if (virt_dev->udev->speed == USB_SPEED_SUPER)
+	if (virt_dev->udev->speed >= USB_SPEED_SUPER)
 		return xhci_check_ss_bw(xhci, virt_dev);
 
 	if (virt_dev->udev->speed == USB_SPEED_HIGH) {
@@ -2396,7 +2387,7 @@
 	if (xhci_is_async_ep(ep_bw->type))
 		return;
 
-	if (udev->speed == USB_SPEED_SUPER) {
+	if (udev->speed >= USB_SPEED_SUPER) {
 		if (xhci_is_sync_in_ep(ep_bw->type))
 			xhci->devs[udev->slot_id]->bw_table->ss_bw_in -=
 				xhci_get_ss_bw_consumed(ep_bw);
@@ -2434,6 +2425,7 @@
 		interval_bw->overhead[HS_OVERHEAD_TYPE] -= 1;
 		break;
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_UNKNOWN:
 	case USB_SPEED_WIRELESS:
 		/* Should never happen because only LS/FS/HS endpoints will get
@@ -2493,6 +2485,7 @@
 		interval_bw->overhead[HS_OVERHEAD_TYPE] += 1;
 		break;
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
 	case USB_SPEED_UNKNOWN:
 	case USB_SPEED_WIRELESS:
 		/* Should never happen because only LS/FS/HS endpoints will get
@@ -3802,8 +3795,10 @@
 
 	mutex_lock(&xhci->mutex);
 
-	if (xhci->xhc_state)	/* dying, removing or halted */
+	if (xhci->xhc_state) {	/* dying, removing or halted */
+		ret = -ESHUTDOWN;
 		goto out;
+	}
 
 	if (!udev->slot_id) {
 		xhci_dbg_trace(xhci, trace_xhci_dbg_address,
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 99ac228..fc2ee6c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -312,6 +312,8 @@
 #define XDEV_U2		(0x2 << 5)
 #define XDEV_U3		(0x3 << 5)
 #define XDEV_INACTIVE	(0x6 << 5)
+#define XDEV_POLLING	(0x7 << 5)
+#define XDEV_COMP_MODE  (0xa << 5)
 #define XDEV_RESUME	(0xf << 5)
 /* true: port has power (see HCC_PPC) */
 #define PORT_POWER	(1 << 9)
@@ -1550,7 +1552,8 @@
 #define CMD_RING_STATE_STOPPED         (1 << 2)
 	struct list_head        cmd_list;
 	unsigned int		cmd_ring_reserved_trbs;
-	struct timer_list	cmd_timer;
+	struct delayed_work	cmd_timer;
+	struct completion	cmd_ring_stop_completion;
 	struct xhci_command	*current_cmd;
 	struct xhci_ring	*event_ring;
 	struct xhci_erst	erst;
@@ -1631,6 +1634,7 @@
 /* For controllers with a broken beyond repair streams implementation */
 #define XHCI_BROKEN_STREAMS	(1 << 19)
 #define XHCI_PME_STUCK_QUIRK	(1 << 20)
+#define XHCI_MISSING_CAS	(1 << 24)
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
 	/* There are two roothubs to keep track of bus suspend info for */
@@ -1912,7 +1916,7 @@
 		unsigned int slot_id, unsigned int ep_index,
 		struct xhci_dequeue_state *deq_state);
 void xhci_stop_endpoint_command_watchdog(unsigned long arg);
-void xhci_handle_command_timeout(unsigned long data);
+void xhci_handle_command_timeout(struct work_struct *work);
 
 void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
 		unsigned int ep_index, unsigned int stream_id);
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 4e38683c..6d4e757 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -346,6 +346,9 @@
 	if (iface_desc->desc.bInterfaceClass != 0x0A)
 		return -ENODEV;
 
+	if (iface_desc->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	/* allocate memory for our device state and initialize it */
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL)
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 1950e87..5e43fd8 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -557,7 +557,7 @@
 			info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice);
 
 			/* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */
-			info.speed = le16_to_cpu(dev->udev->speed);
+			info.speed = dev->udev->speed;
 			info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber;
 			info.report_size = dev->report_size;
 
@@ -787,12 +787,6 @@
 	iface_desc = interface->cur_altsetting;
 	dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
 
-	if (iface_desc->desc.bNumEndpoints < 1) {
-		dev_err(&interface->dev, "Invalid number of endpoints\n");
-		retval = -EINVAL;
-		goto error;
-	}
-
 	/* set up the endpoint information */
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
@@ -803,6 +797,21 @@
 			/* this one will match for the IOWarrior56 only */
 			dev->int_out_endpoint = endpoint;
 	}
+
+	if (!dev->int_in_endpoint) {
+		dev_err(&interface->dev, "no interrupt-in endpoint found\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
+	if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) {
+		if (!dev->int_out_endpoint) {
+			dev_err(&interface->dev, "no interrupt-out endpoint found\n");
+			retval = -ENODEV;
+			goto error;
+		}
+	}
+
 	/* we have to check the report_size often, so remember it in the endianness suitable for our machine */
 	dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint);
 	if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 7771be3..0ec9ee5 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -317,9 +317,16 @@
 	int subminor;
 	int retval = 0;
 	struct usb_interface *interface;
-	struct tower_reset_reply reset_reply;
+	struct tower_reset_reply *reset_reply;
 	int result;
 
+	reset_reply = kmalloc(sizeof(*reset_reply), GFP_KERNEL);
+
+	if (!reset_reply) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	nonseekable_open(inode, file);
 	subminor = iminor(inode);
 
@@ -364,8 +371,8 @@
 				  USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
 				  0,
 				  0,
-				  &reset_reply,
-				  sizeof(reset_reply),
+				  reset_reply,
+				  sizeof(*reset_reply),
 				  1000);
 	if (result < 0) {
 		dev_err(&dev->udev->dev,
@@ -406,6 +413,7 @@
 	mutex_unlock(&dev->lock);
 
 exit:
+	kfree(reset_reply);
 	return retval;
 }
 
@@ -808,7 +816,7 @@
 	struct lego_usb_tower *dev = NULL;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor* endpoint;
-	struct tower_get_version_reply get_version_reply;
+	struct tower_get_version_reply *get_version_reply = NULL;
 	int i;
 	int retval = -ENOMEM;
 	int result;
@@ -898,6 +906,34 @@
 	dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
 	dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
 
+	get_version_reply = kmalloc(sizeof(*get_version_reply), GFP_KERNEL);
+
+	if (!get_version_reply) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	/* get the firmware version and log it */
+	result = usb_control_msg (udev,
+				  usb_rcvctrlpipe(udev, 0),
+				  LEGO_USB_TOWER_REQUEST_GET_VERSION,
+				  USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+				  0,
+				  0,
+				  get_version_reply,
+				  sizeof(*get_version_reply),
+				  1000);
+	if (result < 0) {
+		dev_err(idev, "LEGO USB Tower get version control request failed\n");
+		retval = result;
+		goto error;
+	}
+	dev_info(&interface->dev,
+		 "LEGO USB Tower firmware version is %d.%d build %d\n",
+		 get_version_reply->major,
+		 get_version_reply->minor,
+		 le16_to_cpu(get_version_reply->build_no));
+
 	/* we can register the device now, as it is ready */
 	usb_set_intfdata (interface, dev);
 
@@ -916,31 +952,12 @@
 		 "%d minor %d\n", (dev->minor - LEGO_USB_TOWER_MINOR_BASE),
 		 USB_MAJOR, dev->minor);
 
-	/* get the firmware version and log it */
-	result = usb_control_msg (udev,
-				  usb_rcvctrlpipe(udev, 0),
-				  LEGO_USB_TOWER_REQUEST_GET_VERSION,
-				  USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
-				  0,
-				  0,
-				  &get_version_reply,
-				  sizeof(get_version_reply),
-				  1000);
-	if (result < 0) {
-		dev_err(idev, "LEGO USB Tower get version control request failed\n");
-		retval = result;
-		goto error;
-	}
-	dev_info(&interface->dev, "LEGO USB Tower firmware version is %d.%d "
-		 "build %d\n", get_version_reply.major,
-		 get_version_reply.minor,
-		 le16_to_cpu(get_version_reply.build_no));
-
-
 exit:
+	kfree(get_version_reply);
 	return retval;
 
 error:
+	kfree(get_version_reply);
 	tower_delete(dev);
 	return retval;
 }
diff --git a/drivers/usb/misc/lvstest.c b/drivers/usb/misc/lvstest.c
index 86b4e4b..383fa00 100644
--- a/drivers/usb/misc/lvstest.c
+++ b/drivers/usb/misc/lvstest.c
@@ -370,6 +370,10 @@
 
 	hdev = interface_to_usbdev(intf);
 	desc = intf->cur_altsetting;
+
+	if (desc->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	endpoint = &desc->endpoint[0].desc;
 
 	/* valid only for SS root hub */
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 637f3f7..2e947dc 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -135,6 +135,7 @@
 			case USB_ENDPOINT_XFER_INT:
 				if (dev->info->intr)
 					goto try_intr;
+				continue;
 			case USB_ENDPOINT_XFER_ISOC:
 				if (dev->info->iso)
 					goto try_iso;
@@ -505,6 +506,7 @@
 alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe)
 {
 	struct scatterlist	*sg;
+	unsigned int		n_size = 0;
 	unsigned		i;
 	unsigned		size = max;
 	unsigned		maxpacket =
@@ -537,7 +539,8 @@
 			break;
 		case 1:
 			for (j = 0; j < size; j++)
-				*buf++ = (u8) ((j % maxpacket) % 63);
+				*buf++ = (u8) (((j + n_size) % maxpacket) % 63);
+			n_size += size;
 			break;
 		}
 
@@ -556,7 +559,6 @@
 {
 	struct usb_sg_request	*req = (struct usb_sg_request *) _req;
 
-	req->status = -ETIMEDOUT;
 	usb_sg_cancel(req);
 }
 
@@ -587,8 +589,10 @@
 		mod_timer(&sg_timer, jiffies +
 				msecs_to_jiffies(SIMPLE_IO_TIMEOUT));
 		usb_sg_wait(req);
-		del_timer_sync(&sg_timer);
-		retval = req->status;
+		if (!del_timer_sync(&sg_timer))
+			retval = -ETIMEDOUT;
+		else
+			retval = req->status;
 
 		/* FIXME check resulting data pattern */
 
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index bbd029c..442b663 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -711,6 +711,11 @@
 
 	interface = intf->cur_altsetting;
 
+	if (interface->desc.bNumEndpoints < 3) {
+		usb_put_dev(usbdev);
+		return -ENODEV;
+	}
+
 	/*
 	 * Allocate parport interface 
 	 */
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 310238c..8967980 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -469,6 +469,7 @@
 	.init		= bfin_musb_init,
 	.exit		= bfin_musb_exit,
 
+	.fifo_offset	= bfin_fifo_offset,
 	.readb		= bfin_readb,
 	.writeb		= bfin_writeb,
 	.readw		= bfin_readw,
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index b03d3b8..9a9c82a 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -458,15 +458,11 @@
 }
 
 static const struct musb_platform_ops da8xx_ops = {
-	.quirks		= MUSB_DMA_CPPI | MUSB_INDEXED_EP,
+	.quirks		= MUSB_INDEXED_EP,
 	.init		= da8xx_musb_init,
 	.exit		= da8xx_musb_exit,
 
 	.fifo_mode	= 2,
-#ifdef CONFIG_USB_TI_CPPI_DMA
-	.dma_init	= cppi_dma_controller_create,
-	.dma_exit	= cppi_dma_controller_destroy,
-#endif
 	.enable		= da8xx_musb_enable,
 	.disable	= da8xx_musb_disable,
 
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index ee9ff70..00eed5d 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2401,7 +2401,8 @@
 	musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
 	musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
 	musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
-	musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
+	if (musb->context.devctl & MUSB_DEVCTL_SESSION)
+		musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
 
 	for (i = 0; i < musb->config->num_eps; ++i) {
 		struct musb_hw_ep	*hw_ep;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 2337d7a..90de790 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -214,6 +214,7 @@
 				dma_addr_t *dma_addr, u32 *len);
 	void	(*pre_root_reset_end)(struct musb *musb);
 	void	(*post_root_reset_end)(struct musb *musb);
+	void	(*clear_ep_rxintr)(struct musb *musb, int epnum);
 };
 
 /*
@@ -612,4 +613,10 @@
 		musb->ops->post_root_reset_end(musb);
 }
 
+static inline void musb_platform_clear_ep_rxintr(struct musb *musb, int epnum)
+{
+	if (musb->ops->clear_ep_rxintr)
+		musb->ops->clear_ep_rxintr(musb, epnum);
+}
+
 #endif	/* __MUSB_CORE_H__ */
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index e499b86..88f26ac 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -250,8 +250,27 @@
 			transferred < cppi41_channel->packet_sz)
 		cppi41_channel->prog_len = 0;
 
-	if (cppi41_channel->is_tx)
-		empty = musb_is_tx_fifo_empty(hw_ep);
+	if (cppi41_channel->is_tx) {
+		u8 type;
+
+		if (is_host_active(musb))
+			type = hw_ep->out_qh->type;
+		else
+			type = hw_ep->ep_in.type;
+
+		if (type == USB_ENDPOINT_XFER_ISOC)
+			/*
+			 * Don't use the early-TX-interrupt workaround below
+			 * for Isoch transfter. Since Isoch are periodic
+			 * transfer, by the time the next transfer is
+			 * scheduled, the current one should be done already.
+			 *
+			 * This avoids audio playback underrun issue.
+			 */
+			empty = true;
+		else
+			empty = musb_is_tx_fifo_empty(hw_ep);
+	}
 
 	if (!cppi41_channel->is_tx || empty) {
 		cppi41_trans_done(cppi41_channel);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index eeb7d9e..5a021b2 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -301,6 +301,17 @@
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
+void dsps_musb_clear_ep_rxintr(struct musb *musb, int epnum)
+{
+	u32 epintr;
+	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
+	const struct dsps_musb_wrapper *wrp = glue->wrp;
+
+	/* musb->lock might already been held */
+	epintr = (1 << epnum) << wrp->rxep_shift;
+	musb_writel(musb->ctrl_base, wrp->epintr_status, epintr);
+}
+
 static irqreturn_t dsps_interrupt(int irq, void *hci)
 {
 	struct musb  *musb = hci;
@@ -647,6 +658,7 @@
 	.try_idle	= dsps_musb_try_idle,
 	.set_mode	= dsps_musb_set_mode,
 	.recover	= dsps_musb_recover,
+	.clear_ep_rxintr = dsps_musb_clear_ep_rxintr,
 };
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 795a45b..13d5614 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -594,14 +594,13 @@
 		musb_writew(ep->regs, MUSB_TXCSR, 0);
 
 	/* scrub all previous state, clearing toggle */
-	} else {
-		csr = musb_readw(ep->regs, MUSB_RXCSR);
-		if (csr & MUSB_RXCSR_RXPKTRDY)
-			WARNING("rx%d, packet/%d ready?\n", ep->epnum,
-				musb_readw(ep->regs, MUSB_RXCOUNT));
-
-		musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
 	}
+	csr = musb_readw(ep->regs, MUSB_RXCSR);
+	if (csr & MUSB_RXCSR_RXPKTRDY)
+		WARNING("rx%d, packet/%d ready?\n", ep->epnum,
+			musb_readw(ep->regs, MUSB_RXCOUNT));
+
+	musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
 
 	/* target addr and (for multipoint) hub addr/port */
 	if (musb->is_multipoint) {
@@ -662,7 +661,7 @@
 		csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
 		csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
 	}
-	channel->desired_mode = mode;
+	channel->desired_mode = *mode;
 	musb_writew(epio, MUSB_TXCSR, csr);
 
 	return 0;
@@ -995,9 +994,15 @@
 	if (is_in) {
 		dma = is_dma_capable() ? ep->rx_channel : NULL;
 
-		/* clear nak timeout bit */
+		/*
+		 * Need to stop the transaction by clearing REQPKT first
+		 * then the NAK Timeout bit ref MUSBMHDRC USB 2.0 HIGH-SPEED
+		 * DUAL-ROLE CONTROLLER Programmer's Guide, section 9.2.2
+		 */
 		rx_csr = musb_readw(epio, MUSB_RXCSR);
 		rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+		rx_csr &= ~MUSB_RXCSR_H_REQPKT;
+		musb_writew(epio, MUSB_RXCSR, rx_csr);
 		rx_csr &= ~MUSB_RXCSR_DATAERROR;
 		musb_writew(epio, MUSB_RXCSR, rx_csr);
 
@@ -1551,7 +1556,7 @@
 				  struct urb *urb,
 				  size_t len)
 {
-	struct dma_channel *channel = hw_ep->tx_channel;
+	struct dma_channel *channel = hw_ep->rx_channel;
 	void __iomem *epio = hw_ep->regs;
 	dma_addr_t *buf;
 	u32 length, res;
@@ -2003,10 +2008,8 @@
 				qh->offset,
 				urb->transfer_buffer_length);
 
-			done = musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh,
-							      urb, xfer_len,
-							      iso_err);
-			if (done)
+			if (musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh, urb,
+							   xfer_len, iso_err))
 				goto finish;
 			else
 				dev_err(musb->controller, "error: rx_dma failed\n");
@@ -2387,12 +2390,11 @@
 	int			is_in = usb_pipein(urb->pipe);
 	int			status = 0;
 	u16			csr;
+	struct dma_channel	*dma = NULL;
 
 	musb_ep_select(regs, hw_end);
 
 	if (is_dma_capable()) {
-		struct dma_channel	*dma;
-
 		dma = is_in ? ep->rx_channel : ep->tx_channel;
 		if (dma) {
 			status = ep->musb->dma_controller->channel_abort(dma);
@@ -2409,10 +2411,9 @@
 		/* giveback saves bulk toggle */
 		csr = musb_h_flush_rxfifo(ep, 0);
 
-		/* REVISIT we still get an irq; should likely clear the
-		 * endpoint's irq status here to avoid bogus irqs.
-		 * clearing that status is platform-specific...
-		 */
+		/* clear the endpoint's irq status here to avoid bogus irqs */
+		if (is_dma_capable() && dma)
+			musb_platform_clear_ep_rxintr(musb, ep->epnum);
 	} else if (ep->epnum) {
 		musb_h_tx_flush_fifo(ep);
 		csr = musb_readw(epio, MUSB_TXCSR);
diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h
index f7b13fd2..a3dcbd5 100644
--- a/drivers/usb/musb/musbhsdma.h
+++ b/drivers/usb/musb/musbhsdma.h
@@ -157,5 +157,5 @@
 	void __iomem			*base;
 	u8				channel_count;
 	u8				used_channels;
-	u8				irq;
+	int				irq;
 };
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 4c82077..6020024 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -220,6 +220,7 @@
 	u32				dma_remaining;
 	int				src_burst, dst_burst;
 	u16				csr;
+	u32				psize;
 	int				ch;
 	s8				dmareq;
 	s8				sync_dev;
@@ -391,15 +392,19 @@
 
 	if (chdat->tx) {
 		/* Send transfer_packet_sz packets at a time */
-		musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
-			chdat->transfer_packet_sz);
+		psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
+		psize &= ~0x7ff;
+		psize |= chdat->transfer_packet_sz;
+		musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
 
 		musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
 			TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
 	} else {
 		/* Receive transfer_packet_sz packets at a time */
-		musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
-			chdat->transfer_packet_sz << 16);
+		psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
+		psize &= ~(0x7ff << 16);
+		psize |= (chdat->transfer_packet_sz << 16);
+		musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
 
 		musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
 			TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c
index 7b3035f..1b4d742 100644
--- a/drivers/usb/phy/phy-am335x-control.c
+++ b/drivers/usb/phy/phy-am335x-control.c
@@ -126,10 +126,12 @@
 		return NULL;
 
 	dev = bus_find_device(&platform_bus_type, NULL, node, match);
+	of_node_put(node);
 	if (!dev)
 		return NULL;
 
 	ctrl_usb = dev_get_drvdata(dev);
+	put_device(dev);
 	if (!ctrl_usb)
 		return NULL;
 	return &ctrl_usb->phy_ctrl;
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index f1893e0..36e5b5c 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -808,20 +808,27 @@
 {
 	struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
 	struct usbhs_pipe *pipe = pkt->pipe;
-	struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
+	struct usbhs_fifo *fifo;
 	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
 	struct dma_async_tx_descriptor *desc;
-	struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt);
+	struct dma_chan *chan;
 	struct device *dev = usbhs_priv_to_dev(priv);
 	enum dma_transfer_direction dir;
+	unsigned long flags;
 
+	usbhs_lock(priv, flags);
+	fifo = usbhs_pipe_to_fifo(pipe);
+	if (!fifo)
+		goto xfer_work_end;
+
+	chan = usbhsf_dma_chan_get(fifo, pkt);
 	dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
 
 	desc = dmaengine_prep_slave_single(chan, pkt->dma + pkt->actual,
 					pkt->trans, dir,
 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc)
-		return;
+		goto xfer_work_end;
 
 	desc->callback		= usbhsf_dma_complete;
 	desc->callback_param	= pipe;
@@ -829,7 +836,7 @@
 	pkt->cookie = dmaengine_submit(desc);
 	if (pkt->cookie < 0) {
 		dev_err(dev, "Failed to submit dma descriptor\n");
-		return;
+		goto xfer_work_end;
 	}
 
 	dev_dbg(dev, "  %s %d (%d/ %d)\n",
@@ -840,6 +847,9 @@
 	usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
 	dma_async_issue_pending(chan);
 	usbhs_pipe_enable(pipe);
+
+xfer_work_end:
+	usbhs_unlock(priv, flags);
 }
 
 /*
@@ -859,7 +869,7 @@
 
 	/* use PIO if packet is less than pio_dma_border or pipe is DCP */
 	if ((len < usbhs_get_dparam(priv, pio_dma_border)) ||
-	    usbhs_pipe_is_dcp(pipe))
+	    usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC))
 		goto usbhsf_pio_prepare_push;
 
 	/* check data length if this driver don't use USB-DMAC */
@@ -964,7 +974,7 @@
 
 	/* use PIO if packet is less than pio_dma_border or pipe is DCP */
 	if ((pkt->length < usbhs_get_dparam(priv, pio_dma_border)) ||
-	    usbhs_pipe_is_dcp(pipe))
+	    usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC))
 		goto usbhsf_pio_prepare_pop;
 
 	fifo = usbhsf_get_dma_fifo(priv, pkt);
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index d4be5d5..28965ef 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -282,9 +282,16 @@
 	if (usbhs_mod_is_host(priv))
 		usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
 
-	usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
+	/*
+	 * The driver should not clear the xxxSTS after the line of
+	 * "call irq callback functions" because each "if" statement is
+	 * possible to call the callback function for avoiding any side effects.
+	 */
+	if (irq_state.intsts0 & BRDY)
+		usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
 	usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
-	usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
+	if (irq_state.intsts0 & BEMP)
+		usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
 
 	/*
 	 * call irq callback functions
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index fa14198..efc4fae 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -586,6 +586,9 @@
 	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
 	struct usbhs_pipe *pipe;
 	int ret = -EIO;
+	unsigned long flags;
+
+	usbhs_lock(priv, flags);
 
 	/*
 	 * if it already have pipe,
@@ -594,7 +597,8 @@
 	if (uep->pipe) {
 		usbhs_pipe_clear(uep->pipe);
 		usbhs_pipe_sequence_data0(uep->pipe);
-		return 0;
+		ret = 0;
+		goto usbhsg_ep_enable_end;
 	}
 
 	pipe = usbhs_pipe_malloc(priv,
@@ -614,14 +618,20 @@
 		 * use dmaengine if possible.
 		 * It will use pio handler if impossible.
 		 */
-		if (usb_endpoint_dir_in(desc))
+		if (usb_endpoint_dir_in(desc)) {
 			pipe->handler = &usbhs_fifo_dma_push_handler;
-		else
+		} else {
 			pipe->handler = &usbhs_fifo_dma_pop_handler;
+			usbhs_xxxsts_clear(priv, BRDYSTS,
+					   usbhs_pipe_number(pipe));
+		}
 
 		ret = 0;
 	}
 
+usbhsg_ep_enable_end:
+	usbhs_unlock(priv, flags);
+
 	return ret;
 }
 
@@ -1065,7 +1075,7 @@
 
 	gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
 	dev_info(dev, "%stransceiver found\n",
-		 gpriv->transceiver ? "" : "no ");
+		 !IS_ERR(gpriv->transceiver) ? "" : "no ");
 
 	/*
 	 * CAUTION
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 1532cde..754fc3e 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -99,10 +99,17 @@
 				 usb_rcvctrlpipe(serial->dev, 0),
 				 0xfe, 0xc0, 0, reg,
 				 buf, 1, ARK_TIMEOUT);
-	if (result < 0)
+	if (result < 1) {
+		dev_err(&serial->interface->dev,
+				"failed to read register %u: %d\n",
+				reg, result);
+		if (result >= 0)
+			result = -EIO;
+
 		return result;
-	else
-		return buf[0];
+	}
+
+	return buf[0];
 }
 
 static inline int calc_divisor(int bps)
@@ -366,23 +373,29 @@
 		dev_dbg(&port->dev,
 			"%s - usb_serial_generic_open failed: %d\n",
 			__func__, result);
-		goto err_out;
+		goto err_free;
 	}
 
 	/* remove any data still left: also clears error state */
 	ark3116_read_reg(serial, UART_RX, buf);
 
 	/* read modem status */
-	priv->msr = ark3116_read_reg(serial, UART_MSR, buf);
+	result = ark3116_read_reg(serial, UART_MSR, buf);
+	if (result < 0)
+		goto err_close;
+	priv->msr = *buf;
+
 	/* read line status */
-	priv->lsr = ark3116_read_reg(serial, UART_LSR, buf);
+	result = ark3116_read_reg(serial, UART_LSR, buf);
+	if (result < 0)
+		goto err_close;
+	priv->lsr = *buf;
 
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 	if (result) {
 		dev_err(&port->dev, "submit irq_in urb failed %d\n",
 			result);
-		ark3116_close(port);
-		goto err_out;
+		goto err_close;
 	}
 
 	/* activate interrupts */
@@ -395,8 +408,15 @@
 	if (tty)
 		ark3116_set_termios(tty, port, NULL);
 
-err_out:
 	kfree(buf);
+
+	return 0;
+
+err_close:
+	usb_serial_generic_close(port);
+err_free:
+	kfree(buf);
+
 	return result;
 }
 
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index c73808f..71133d9 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -99,6 +99,8 @@
 	r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
 			    USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
 			    value, index, NULL, 0, DEFAULT_TIMEOUT);
+	if (r < 0)
+		dev_err(&dev->dev, "failed to send control message: %d\n", r);
 
 	return r;
 }
@@ -116,7 +118,20 @@
 	r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
 			    USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 			    value, index, buf, bufsize, DEFAULT_TIMEOUT);
-	return r;
+	if (r < bufsize) {
+		if (r >= 0) {
+			dev_err(&dev->dev,
+				"short control message received (%d < %u)\n",
+				r, bufsize);
+			r = -EIO;
+		}
+
+		dev_err(&dev->dev, "failed to receive control message: %d\n",
+			r);
+		return r;
+	}
+
+	return 0;
 }
 
 static int ch341_set_baudrate(struct usb_device *dev,
@@ -158,9 +173,9 @@
 
 static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
 {
+	const unsigned int size = 2;
 	char *buffer;
 	int r;
-	const unsigned size = 8;
 	unsigned long flags;
 
 	buffer = kmalloc(size, GFP_KERNEL);
@@ -171,14 +186,9 @@
 	if (r < 0)
 		goto out;
 
-	/* setup the private status if available */
-	if (r == 2) {
-		r = 0;
-		spin_lock_irqsave(&priv->lock, flags);
-		priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
-		spin_unlock_irqrestore(&priv->lock, flags);
-	} else
-		r = -EPROTO;
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 out:	kfree(buffer);
 	return r;
@@ -188,9 +198,9 @@
 
 static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
 {
+	const unsigned int size = 2;
 	char *buffer;
 	int r;
-	const unsigned size = 8;
 
 	buffer = kmalloc(size, GFP_KERNEL);
 	if (!buffer)
@@ -253,7 +263,6 @@
 
 	spin_lock_init(&priv->lock);
 	priv->baud_rate = DEFAULT_BAUD_RATE;
-	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
 	r = ch341_configure(port->serial->dev, priv);
 	if (r < 0)
@@ -315,7 +324,7 @@
 
 	r = ch341_configure(serial->dev, priv);
 	if (r)
-		goto out;
+		return r;
 
 	if (tty)
 		ch341_set_termios(tty, port, NULL);
@@ -325,12 +334,19 @@
 	if (r) {
 		dev_err(&port->dev, "%s - failed to submit interrupt urb: %d\n",
 			__func__, r);
-		goto out;
+		return r;
 	}
 
 	r = usb_serial_generic_open(tty, port);
+	if (r)
+		goto err_kill_interrupt_urb;
 
-out:	return r;
+	return 0;
+
+err_kill_interrupt_urb:
+	usb_kill_urb(port->interrupt_in_urb);
+
+	return r;
 }
 
 /* Old_termios contains the original termios settings and
@@ -345,26 +361,25 @@
 
 	baud_rate = tty_get_baud_rate(tty);
 
-	priv->baud_rate = baud_rate;
-
 	if (baud_rate) {
-		spin_lock_irqsave(&priv->lock, flags);
-		priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
-		spin_unlock_irqrestore(&priv->lock, flags);
+		priv->baud_rate = baud_rate;
 		ch341_set_baudrate(port->serial->dev, priv);
-	} else {
-		spin_lock_irqsave(&priv->lock, flags);
-		priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
-		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 
-	ch341_set_handshake(port->serial->dev, priv->line_control);
-
 	/* Unimplemented:
 	 * (cflag & CSIZE) : data bits [5, 8]
 	 * (cflag & PARENB) : parity {NONE, EVEN, ODD}
 	 * (cflag & CSTOPB) : stop bits [1, 2]
 	 */
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (C_BAUD(tty) == B0)
+		priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
+	else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
+		priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	ch341_set_handshake(port->serial->dev, priv->line_control);
 }
 
 static void ch341_break_ctl(struct tty_struct *tty, int break_state)
@@ -539,14 +554,23 @@
 
 static int ch341_reset_resume(struct usb_serial *serial)
 {
-	struct ch341_private *priv;
-
-	priv = usb_get_serial_port_data(serial->port[0]);
+	struct usb_serial_port *port = serial->port[0];
+	struct ch341_private *priv = usb_get_serial_port_data(port);
+	int ret;
 
 	/* reconfigure ch341 serial port after bus-reset */
 	ch341_configure(serial->dev, priv);
 
-	return 0;
+	if (test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
+		ret = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
+		if (ret) {
+			dev_err(&port->dev, "failed to submit interrupt urb: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	return usb_serial_generic_resume(serial);
 }
 
 static struct usb_serial_driver ch341_device = {
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index a2b43a6..b0dc6da 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -117,6 +117,7 @@
 	{ USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
 	{ USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
 	{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
+	{ USB_DEVICE(0x10C4, 0x8470) }, /* Juniper Networks BX Series System Console */
 	{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
 	{ USB_DEVICE(0x10C4, 0x84B6) }, /* Starizona Hyperion */
 	{ USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
@@ -129,9 +130,11 @@
 	{ USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
 	{ USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
 	{ USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */
+	{ USB_DEVICE(0x10C4, 0x8962) }, /* Brim Brothers charging dock */
 	{ USB_DEVICE(0x10C4, 0x8977) },	/* CEL MeshWorks DevKit Device */
 	{ USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */
 	{ USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */
+	{ USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
@@ -169,6 +172,8 @@
 	{ USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
 	{ USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
 	{ USB_DEVICE(0x1901, 0x0194) },	/* GE Healthcare Remote Alarm Box */
+	{ USB_DEVICE(0x1901, 0x0195) },	/* GE B850/B650/B450 CP2104 DP UART interface */
+	{ USB_DEVICE(0x1901, 0x0196) },	/* GE B850 CP2105 DP UART interface */
 	{ USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
 	{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
 	{ USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
@@ -784,7 +789,7 @@
 		} else {
 			modem_ctl[0] &= ~0x7B;
 			modem_ctl[0] |= 0x01;
-			modem_ctl[1] |= 0x40;
+			modem_ctl[1] = 0x40;
 			dev_dbg(dev, "%s - flow control = NONE\n", __func__);
 		}
 
@@ -844,7 +849,9 @@
 	unsigned int control;
 	int result;
 
-	cp210x_get_config(port, CP210X_GET_MDMSTS, &control, 1);
+	result = cp210x_get_config(port, CP210X_GET_MDMSTS, &control, 1);
+	if (result)
+		return result;
 
 	result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
 		|((control & CONTROL_RTS) ? TIOCM_RTS : 0)
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 2916dea..8948f37 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -50,6 +50,7 @@
 #define CYBERJACK_PRODUCT_ID	0x0100
 
 /* Function prototypes */
+static int cyberjack_attach(struct usb_serial *serial);
 static int cyberjack_port_probe(struct usb_serial_port *port);
 static int cyberjack_port_remove(struct usb_serial_port *port);
 static int  cyberjack_open(struct tty_struct *tty,
@@ -77,6 +78,7 @@
 	.description =		"Reiner SCT Cyberjack USB card reader",
 	.id_table =		id_table,
 	.num_ports =		1,
+	.attach =		cyberjack_attach,
 	.port_probe =		cyberjack_port_probe,
 	.port_remove =		cyberjack_port_remove,
 	.open =			cyberjack_open,
@@ -100,6 +102,14 @@
 	short		wrsent;		/* Data already sent */
 };
 
+static int cyberjack_attach(struct usb_serial *serial)
+{
+	if (serial->num_bulk_out < serial->num_ports)
+		return -ENODEV;
+
+	return 0;
+}
+
 static int cyberjack_port_probe(struct usb_serial_port *port)
 {
 	struct cyberjack_private *priv;
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 3df7b7e..be93b9f 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -1399,25 +1399,30 @@
 {
 	struct usb_serial_port *port = urb->context;
 	struct digi_port *priv = usb_get_serial_port_data(port);
-	int opcode = ((unsigned char *)urb->transfer_buffer)[0];
-	int len = ((unsigned char *)urb->transfer_buffer)[1];
-	int port_status = ((unsigned char *)urb->transfer_buffer)[2];
-	unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3;
+	unsigned char *buf = urb->transfer_buffer;
+	int opcode;
+	int len;
+	int port_status;
+	unsigned char *data;
 	int flag, throttled;
-	int status = urb->status;
-
-	/* do not process callbacks on closed ports */
-	/* but do continue the read chain */
-	if (urb->status == -ENOENT)
-		return 0;
 
 	/* short/multiple packet check */
+	if (urb->actual_length < 2) {
+		dev_warn(&port->dev, "short packet received\n");
+		return -1;
+	}
+
+	opcode = buf[0];
+	len = buf[1];
+
 	if (urb->actual_length != len + 2) {
-		dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, "
-			"status=%d, port=%d, opcode=%d, len=%d, "
-			"actual_length=%d, status=%d\n", __func__, status,
-			priv->dp_port_num, opcode, len, urb->actual_length,
-			port_status);
+		dev_err(&port->dev, "malformed packet received: port=%d, opcode=%d, len=%d, actual_length=%u\n",
+			priv->dp_port_num, opcode, len, urb->actual_length);
+		return -1;
+	}
+
+	if (opcode == DIGI_CMD_RECEIVE_DATA && len < 1) {
+		dev_err(&port->dev, "malformed data packet received\n");
 		return -1;
 	}
 
@@ -1431,6 +1436,9 @@
 
 	/* receive data */
 	if (opcode == DIGI_CMD_RECEIVE_DATA) {
+		port_status = buf[2];
+		data = &buf[3];
+
 		/* get flag from port_status */
 		flag = 0;
 
@@ -1483,16 +1491,20 @@
 	struct usb_serial *serial = port->serial;
 	struct tty_struct *tty;
 	struct digi_port *priv = usb_get_serial_port_data(port);
+	unsigned char *buf = urb->transfer_buffer;
 	int opcode, line, status, val;
 	int i;
 	unsigned int rts;
 
+	if (urb->actual_length < 4)
+		return -1;
+
 	/* handle each oob command */
-	for (i = 0; i < urb->actual_length - 3;) {
-		opcode = ((unsigned char *)urb->transfer_buffer)[i++];
-		line = ((unsigned char *)urb->transfer_buffer)[i++];
-		status = ((unsigned char *)urb->transfer_buffer)[i++];
-		val = ((unsigned char *)urb->transfer_buffer)[i++];
+	for (i = 0; i < urb->actual_length - 3; i += 4) {
+		opcode = buf[i];
+		line = buf[i + 1];
+		status = buf[i + 2];
+		val = buf[i + 3];
 
 		dev_dbg(&port->dev, "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d\n",
 			opcode, line, status, val);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index b61f121..e0385d6 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -648,6 +648,8 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_TFD128_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FM3RX_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS777_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_PALMSENS_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IVIUM_XSTAT_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
@@ -807,10 +809,10 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
 	{ USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID, 1) },
+	{ USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID, 1) },
+	{ USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_PID, 1) },
+	{ USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_H_PID, 1) },
 	{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID),
@@ -871,6 +873,7 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
 					USB_CLASS_VENDOR_SPEC,
 					USB_SUBCLASS_VENDOR_SPEC, 0x00) },
+	{ USB_DEVICE_INTERFACE_NUMBER(ACTEL_VID, MICROSEMI_ARROW_SF2PLUS_BOARD_PID, 2) },
 	{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
 	{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -984,7 +987,8 @@
 	/* ekey Devices */
 	{ USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) },
 	/* Infineon Devices */
-	{ USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
+	{ USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_TC1798_PID, 1) },
+	{ USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_TC2X7_PID, 1) },
 	/* GE Healthcare devices */
 	{ USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
 	/* Active Research (Actisense) devices */
@@ -1008,6 +1012,9 @@
 	{ USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) },
 	{ USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) },
 	{ USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) },
+	{ USB_DEVICE(WICED_VID, WICED_USB20706V2_PID) },
+	{ USB_DEVICE(TI_VID, TI_CC3200_LAUNCHPAD_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ }					/* Terminating entry */
 };
 
@@ -1433,10 +1440,13 @@
 			     FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
 			     0, priv->interface,
 			     buf, 1, WDR_TIMEOUT);
-	if (rv < 0)
+	if (rv < 1) {
 		dev_err(&port->dev, "Unable to read latency timer: %i\n", rv);
-	else
+		if (rv >= 0)
+			rv = -EIO;
+	} else {
 		priv->latency = buf[0];
+	}
 
 	kfree(buf);
 
@@ -1498,9 +1508,9 @@
 					(new_serial.flags & ASYNC_FLAGS));
 	priv->custom_divisor = new_serial.custom_divisor;
 
+check_and_exit:
 	write_latency_timer(port);
 
-check_and_exit:
 	if ((old_priv.flags & ASYNC_SPD_MASK) !=
 	     (priv->flags & ASYNC_SPD_MASK)) {
 		if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
@@ -1801,8 +1811,6 @@
 
 	mutex_init(&priv->cfg_lock);
 
-	priv->flags = ASYNC_LOW_LATENCY;
-
 	if (quirk && quirk->port_probe)
 		quirk->port_probe(priv);
 
@@ -2066,6 +2074,20 @@
 		priv->prev_status = status;
 	}
 
+	/* save if the transmitter is empty or not */
+	if (packet[1] & FTDI_RS_TEMT)
+		priv->transmit_empty = 1;
+	else
+		priv->transmit_empty = 0;
+
+	len -= 2;
+	if (!len)
+		return 0;	/* status only */
+
+	/*
+	 * Break and error status must only be processed for packets with
+	 * data payload to avoid over-reporting.
+	 */
 	flag = TTY_NORMAL;
 	if (packet[1] & FTDI_RS_ERR_MASK) {
 		/* Break takes precedence over parity, which takes precedence
@@ -2088,15 +2110,6 @@
 		}
 	}
 
-	/* save if the transmitter is empty or not */
-	if (packet[1] & FTDI_RS_TEMT)
-		priv->transmit_empty = 1;
-	else
-		priv->transmit_empty = 0;
-
-	len -= 2;
-	if (!len)
-		return 0;	/* status only */
 	port->icount.rx += len;
 	ch = packet + 2;
 
@@ -2427,8 +2440,12 @@
 			FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
 			0, priv->interface,
 			buf, len, WDR_TIMEOUT);
-	if (ret < 0) {
+
+	/* NOTE: We allow short responses and handle that below. */
+	if (ret < 1) {
 		dev_err(&port->dev, "failed to get modem status: %d\n", ret);
+		if (ret >= 0)
+			ret = -EIO;
 		ret = usb_translate_errors(ret);
 		goto out;
 	}
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index c5d6c1e..4fcf1ce 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -406,6 +406,12 @@
 #define FTDI_4N_GALAXY_DE_3_PID	0xF3C2
 
 /*
+ * Ivium Technologies product IDs
+ */
+#define FTDI_PALMSENS_PID	0xf440
+#define FTDI_IVIUM_XSTAT_PID	0xf441
+
+/*
  * Linx Technologies product ids
  */
 #define LINX_SDMUSBQSS_PID	0xF448	/* Linx SDM-USB-QS-S */
@@ -590,6 +596,12 @@
 #define STK541_PID		0x2109 /* Zigbee Controller */
 
 /*
+ * Texas Instruments
+ */
+#define TI_VID			0x0451
+#define TI_CC3200_LAUNCHPAD_PID	0xC32A /* SimpleLink Wi-Fi CC3200 LaunchPad */
+
+/*
  * Blackfin gnICE JTAG
  * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice
  */
@@ -620,8 +632,9 @@
 /*
  * Infineon Technologies
  */
-#define INFINEON_VID		0x058b
-#define INFINEON_TRIBOARD_PID	0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */
+#define INFINEON_VID		        0x058b
+#define INFINEON_TRIBOARD_TC1798_PID	0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */
+#define INFINEON_TRIBOARD_TC2X7_PID	0x0043 /* DAS JTAG TriBoard TC2X7 V1.0 */
 
 /*
  * Acton Research Corp.
@@ -673,6 +686,12 @@
 #define INTREPID_NEOVI_PID	0x0701
 
 /*
+ * WICED USB UART
+ */
+#define WICED_VID		0x0A5C
+#define WICED_USB20706V2_PID	0x6422
+
+/*
  * Definitions for ID TECH (www.idt-net.com) devices
  */
 #define IDTECH_VID		0x0ACD	/* ID TECH Vendor ID */
@@ -854,9 +873,17 @@
 #define	FIC_VID			0x1457
 #define	FIC_NEO1973_DEBUG_PID	0x5118
 
+/*
+ * Actel / Microsemi
+ */
+#define ACTEL_VID				0x1514
+#define MICROSEMI_ARROW_SF2PLUS_BOARD_PID	0x2008
+
 /* Olimex */
 #define OLIMEX_VID			0x15BA
 #define OLIMEX_ARM_USB_OCD_PID		0x0003
+#define OLIMEX_ARM_USB_TINY_PID	0x0004
+#define OLIMEX_ARM_USB_TINY_H_PID	0x002a
 #define OLIMEX_ARM_USB_OCD_H_PID	0x002b
 
 /*
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index db591d1..37d0e8c 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1044,6 +1044,7 @@
 		   "%s - usb_submit_urb(write bulk) failed with status = %d\n",
 				__func__, status);
 		count = status;
+		kfree(buffer);
 	}
 
 	/* we are done with this urb, so let the host driver
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index c086697..749e1b6 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -492,20 +492,24 @@
 	int result;
 	struct usb_serial *serial = ep->serial;
 	struct edgeport_product_info *product_info = &ep->product_info;
-	struct edge_compatibility_descriptor *epic = &ep->epic_descriptor;
+	struct edge_compatibility_descriptor *epic;
 	struct edge_compatibility_bits *bits;
 	struct device *dev = &serial->dev->dev;
 
 	ep->is_epic = 0;
+
+	epic = kmalloc(sizeof(*epic), GFP_KERNEL);
+	if (!epic)
+		return -ENOMEM;
+
 	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				 USB_REQUEST_ION_GET_EPIC_DESC,
 				 0xC0, 0x00, 0x00,
-				 &ep->epic_descriptor,
-				 sizeof(struct edge_compatibility_descriptor),
+				 epic, sizeof(*epic),
 				 300);
-
-	if (result > 0) {
+	if (result == sizeof(*epic)) {
 		ep->is_epic = 1;
+		memcpy(&ep->epic_descriptor, epic, sizeof(*epic));
 		memset(product_info, 0, sizeof(struct edgeport_product_info));
 
 		product_info->NumPorts = epic->NumPorts;
@@ -534,8 +538,16 @@
 		dev_dbg(dev, "  IOSPWriteLCR     : %s\n", bits->IOSPWriteLCR	? "TRUE": "FALSE");
 		dev_dbg(dev, "  IOSPSetBaudRate  : %s\n", bits->IOSPSetBaudRate	? "TRUE": "FALSE");
 		dev_dbg(dev, "  TrueEdgeport     : %s\n", bits->TrueEdgeport	? "TRUE": "FALSE");
+
+		result = 0;
+	} else if (result >= 0) {
+		dev_warn(&serial->interface->dev, "short epic descriptor received: %d\n",
+			 result);
+		result = -EIO;
 	}
 
+	kfree(epic);
+
 	return result;
 }
 
@@ -2097,8 +2109,7 @@
  * rom_read
  *	reads a number of bytes from the Edgeport device starting at the given
  *	address.
- *	If successful returns the number of bytes read, otherwise it returns
- *	a negative error number of the problem.
+ *	Returns zero on success or a negative error number.
  ****************************************************************************/
 static int rom_read(struct usb_serial *serial, __u16 extAddr,
 					__u16 addr, __u16 length, __u8 *data)
@@ -2123,12 +2134,17 @@
 					USB_REQUEST_ION_READ_ROM,
 					0xC0, addr, extAddr, transfer_buffer,
 					current_length, 300);
-		if (result < 0)
+		if (result < current_length) {
+			if (result >= 0)
+				result = -EIO;
 			break;
+		}
 		memcpy(data, transfer_buffer, current_length);
 		length -= current_length;
 		addr += current_length;
 		data += current_length;
+
+		result = 0;
 	}
 
 	kfree(transfer_buffer);
@@ -2585,9 +2601,10 @@
 				EDGE_MANUF_DESC_LEN,
 				(__u8 *)(&edge_serial->manuf_descriptor));
 
-	if (response < 1)
-		dev_err(dev, "error in getting manufacturer descriptor\n");
-	else {
+	if (response < 0) {
+		dev_err(dev, "error in getting manufacturer descriptor: %d\n",
+				response);
+	} else {
 		char string[30];
 		dev_dbg(dev, "**Manufacturer Descriptor\n");
 		dev_dbg(dev, "  RomSize:        %dK\n",
@@ -2644,9 +2661,10 @@
 				EDGE_BOOT_DESC_LEN,
 				(__u8 *)(&edge_serial->boot_descriptor));
 
-	if (response < 1)
-		dev_err(dev, "error in getting boot descriptor\n");
-	else {
+	if (response < 0) {
+		dev_err(dev, "error in getting boot descriptor: %d\n",
+				response);
+	} else {
 		dev_dbg(dev, "**Boot Descriptor:\n");
 		dev_dbg(dev, "  BootCodeLength: %d\n",
 			le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
@@ -2761,6 +2779,11 @@
 					EDGE_COMPATIBILITY_MASK1,
 					EDGE_COMPATIBILITY_MASK2 };
 
+	if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	dev = serial->dev;
 
 	/* create our private serial structure */
@@ -2784,7 +2807,7 @@
 	dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name);
 
 	/* Read the epic descriptor */
-	if (get_epic_descriptor(edge_serial) <= 0) {
+	if (get_epic_descriptor(edge_serial) < 0) {
 		/* memcpy descriptor to Supports structures */
 		memcpy(&edge_serial->epic_descriptor.Supports, descriptor,
 		       sizeof(struct edge_compatibility_bits));
@@ -2856,14 +2879,16 @@
 				/* not set up yet, so do it now */
 				edge_serial->interrupt_read_urb =
 						usb_alloc_urb(0, GFP_KERNEL);
-				if (!edge_serial->interrupt_read_urb)
-					return -ENOMEM;
+				if (!edge_serial->interrupt_read_urb) {
+					response = -ENOMEM;
+					break;
+				}
 
 				edge_serial->interrupt_in_buffer =
 					kmalloc(buffer_size, GFP_KERNEL);
 				if (!edge_serial->interrupt_in_buffer) {
-					usb_free_urb(edge_serial->interrupt_read_urb);
-					return -ENOMEM;
+					response = -ENOMEM;
+					break;
 				}
 				edge_serial->interrupt_in_endpoint =
 						endpoint->bEndpointAddress;
@@ -2891,14 +2916,16 @@
 				/* not set up yet, so do it now */
 				edge_serial->read_urb =
 						usb_alloc_urb(0, GFP_KERNEL);
-				if (!edge_serial->read_urb)
-					return -ENOMEM;
+				if (!edge_serial->read_urb) {
+					response = -ENOMEM;
+					break;
+				}
 
 				edge_serial->bulk_in_buffer =
 					kmalloc(buffer_size, GFP_KERNEL);
 				if (!edge_serial->bulk_in_buffer) {
-					usb_free_urb(edge_serial->read_urb);
-					return -ENOMEM;
+					response = -ENOMEM;
+					break;
 				}
 				edge_serial->bulk_in_endpoint =
 						endpoint->bEndpointAddress;
@@ -2924,9 +2951,22 @@
 			}
 		}
 
-		if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) {
-			dev_err(ddev, "Error - the proper endpoints were not found!\n");
-			return -ENODEV;
+		if (response || !interrupt_in_found || !bulk_in_found ||
+							!bulk_out_found) {
+			if (!response) {
+				dev_err(ddev, "expected endpoints not found\n");
+				response = -ENODEV;
+			}
+
+			usb_free_urb(edge_serial->interrupt_read_urb);
+			kfree(edge_serial->interrupt_in_buffer);
+
+			usb_free_urb(edge_serial->read_urb);
+			kfree(edge_serial->bulk_in_buffer);
+
+			kfree(edge_serial);
+
+			return response;
 		}
 
 		/* start interrupt read for this edgeport this interrupt will
@@ -2949,16 +2989,9 @@
 {
 	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
 
-	/* stop reads and writes on all ports */
-	/* free up our endpoint stuff */
 	if (edge_serial->is_epic) {
 		usb_kill_urb(edge_serial->interrupt_read_urb);
-		usb_free_urb(edge_serial->interrupt_read_urb);
-		kfree(edge_serial->interrupt_in_buffer);
-
 		usb_kill_urb(edge_serial->read_urb);
-		usb_free_urb(edge_serial->read_urb);
-		kfree(edge_serial->bulk_in_buffer);
 	}
 }
 
@@ -2971,6 +3004,16 @@
 {
 	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
 
+	if (edge_serial->is_epic) {
+		usb_kill_urb(edge_serial->interrupt_read_urb);
+		usb_free_urb(edge_serial->interrupt_read_urb);
+		kfree(edge_serial->interrupt_in_buffer);
+
+		usb_kill_urb(edge_serial->read_urb);
+		usb_free_urb(edge_serial->read_urb);
+		kfree(edge_serial->bulk_in_buffer);
+	}
+
 	kfree(edge_serial);
 }
 
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index fce82fd..e98532f 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -1499,8 +1499,7 @@
 
 		dev_dbg(dev, "%s - Download successful -- Device rebooting...\n", __func__);
 
-		/* return an error on purpose */
-		return -ENODEV;
+		return 1;
 	}
 
 stayinbootmode:
@@ -1508,7 +1507,7 @@
 	dev_dbg(dev, "%s - STAYING IN BOOT MODE\n", __func__);
 	serial->product_info.TiMode = TI_MODE_BOOT;
 
-	return 0;
+	return 1;
 }
 
 static int ti_do_config(struct edgeport_port *port, int feature, int on)
@@ -1675,6 +1674,12 @@
 	function    = TIUMP_GET_FUNC_FROM_CODE(data[0]);
 	dev_dbg(dev, "%s - port_number %d, function %d, info 0x%x\n", __func__,
 		port_number, function, data[1]);
+
+	if (port_number >= edge_serial->serial->num_ports) {
+		dev_err(dev, "bad port number %d\n", port_number);
+		goto exit;
+	}
+
 	port = edge_serial->serial->port[port_number];
 	edge_port = usb_get_serial_port_data(port);
 	if (!edge_port) {
@@ -1756,7 +1761,7 @@
 
 	port_number = edge_port->port->port_number;
 
-	if (edge_port->lsr_event) {
+	if (urb->actual_length > 0 && edge_port->lsr_event) {
 		edge_port->lsr_event = 0;
 		dev_dbg(dev, "%s ===== Port %u LSR Status = %02x, Data = %02x ======\n",
 			__func__, port_number, edge_port->lsr_mask, *data);
@@ -2344,8 +2349,11 @@
 	if (!baud) {
 		/* pick a default, any default... */
 		baud = 9600;
-	} else
+	} else {
+		/* Avoid a zero divisor. */
+		baud = min(baud, 461550);
 		tty_encode_baud_rate(tty, baud, baud);
+	}
 
 	edge_port->baud_rate = baud;
 	config->wBaudRate = (__u16)((461550L + baud/2) / baud);
@@ -2549,6 +2557,13 @@
 	int status;
 	u16 product_id;
 
+	/* Make sure we have the required endpoints when in download mode. */
+	if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) {
+		if (serial->num_bulk_in < serial->num_ports ||
+				serial->num_bulk_out < serial->num_ports)
+			return -ENODEV;
+	}
+
 	/* create our private serial structure */
 	edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
 	if (!edge_serial)
@@ -2556,14 +2571,18 @@
 
 	mutex_init(&edge_serial->es_lock);
 	edge_serial->serial = serial;
+	INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work);
 	usb_set_serial_data(serial, edge_serial);
 
 	status = download_fw(edge_serial);
-	if (status) {
+	if (status < 0) {
 		kfree(edge_serial);
 		return status;
 	}
 
+	if (status > 0)
+		return 1;	/* bind but do not register any ports */
+
 	product_id = le16_to_cpu(
 			edge_serial->serial->dev->descriptor.idProduct);
 
@@ -2575,7 +2594,6 @@
 		}
 	}
 
-	INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work);
 	edge_heartbeat_schedule(edge_serial);
 
 	return 0;
@@ -2583,6 +2601,9 @@
 
 static void edge_disconnect(struct usb_serial *serial)
 {
+	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+
+	cancel_delayed_work_sync(&edge_serial->heartbeat_work);
 }
 
 static void edge_release(struct usb_serial *serial)
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 5ad4a0f..7ed7d33 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -68,6 +68,16 @@
 	u32 clk;
 };
 
+static int iuu_attach(struct usb_serial *serial)
+{
+	unsigned char num_ports = serial->num_ports;
+
+	if (serial->num_bulk_in < num_ports || serial->num_bulk_out < num_ports)
+		return -ENODEV;
+
+	return 0;
+}
+
 static int iuu_port_probe(struct usb_serial_port *port)
 {
 	struct iuu_private *priv;
@@ -1196,6 +1206,7 @@
 	.tiocmset = iuu_tiocmset,
 	.set_termios = iuu_set_termios,
 	.init_termios = iuu_init_termios,
+	.attach = iuu_attach,
 	.port_probe = iuu_port_probe,
 	.port_remove = iuu_port_remove,
 };
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index e07b15e..7faa901 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -2376,6 +2376,10 @@
 
 	s_priv = usb_get_serial_data(serial);
 
+	/* Make sure to unlink the URBs submitted in attach. */
+	usb_kill_urb(s_priv->instat_urb);
+	usb_kill_urb(s_priv->indat_urb);
+
 	usb_free_urb(s_priv->instat_urb);
 	usb_free_urb(s_priv->indat_urb);
 	usb_free_urb(s_priv->glocont_urb);
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 4f7e072..6b09424 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -139,6 +139,7 @@
 {
 	struct usb_serial_port *port = urb->context;
 	unsigned char *data = urb->transfer_buffer;
+	unsigned int len = urb->actual_length;
 	int retval;
 	int status = urb->status;
 	struct keyspan_pda_private *priv;
@@ -159,18 +160,26 @@
 		goto exit;
 	}
 
+	if (len < 1) {
+		dev_warn(&port->dev, "short message received\n");
+		goto exit;
+	}
+
 	/* see if the message is data or a status interrupt */
 	switch (data[0]) {
 	case 0:
 		 /* rest of message is rx data */
-		if (urb->actual_length) {
-			tty_insert_flip_string(&port->port, data + 1,
-						urb->actual_length - 1);
-			tty_flip_buffer_push(&port->port);
-		}
+		if (len < 2)
+			break;
+		tty_insert_flip_string(&port->port, data + 1, len - 1);
+		tty_flip_buffer_push(&port->port);
 		break;
 	case 1:
 		/* status interrupt */
+		if (len < 3) {
+			dev_warn(&port->dev, "short interrupt message received\n");
+			break;
+		}
 		dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]);
 		switch (data[1]) {
 		case 1: /* modemline change */
@@ -699,6 +708,19 @@
 MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
 #endif
 
+static int keyspan_pda_attach(struct usb_serial *serial)
+{
+	unsigned char num_ports = serial->num_ports;
+
+	if (serial->num_bulk_out < num_ports ||
+			serial->num_interrupt_in < num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int keyspan_pda_port_probe(struct usb_serial_port *port)
 {
 
@@ -776,6 +798,7 @@
 	.break_ctl =		keyspan_pda_break_ctl,
 	.tiocmget =		keyspan_pda_tiocmget,
 	.tiocmset =		keyspan_pda_tiocmset,
+	.attach =		keyspan_pda_attach,
 	.port_probe =		keyspan_pda_port_probe,
 	.port_remove =		keyspan_pda_port_remove,
 };
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index e020ad2..83c823d 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -192,10 +192,11 @@
 			     status_buf, KLSI_STATUSBUF_LEN,
 			     10000
 			     );
-	if (rc < 0)
-		dev_err(&port->dev, "Reading line status failed (error = %d)\n",
-			rc);
-	else {
+	if (rc != KLSI_STATUSBUF_LEN) {
+		dev_err(&port->dev, "reading line status failed: %d\n", rc);
+		if (rc >= 0)
+			rc = -EIO;
+	} else {
 		status = get_unaligned_le16(status_buf);
 
 		dev_info(&port->serial->dev->dev, "read status %x %x\n",
@@ -296,7 +297,7 @@
 	rc = usb_serial_generic_open(tty, port);
 	if (rc) {
 		retval = rc;
-		goto exit;
+		goto err_free_cfg;
 	}
 
 	rc = usb_control_msg(port->serial->dev,
@@ -311,21 +312,38 @@
 	if (rc < 0) {
 		dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc);
 		retval = rc;
+		goto err_generic_close;
 	} else
 		dev_dbg(&port->dev, "%s - enabled reading\n", __func__);
 
 	rc = klsi_105_get_line_state(port, &line_state);
-	if (rc >= 0) {
-		spin_lock_irqsave(&priv->lock, flags);
-		priv->line_state = line_state;
-		spin_unlock_irqrestore(&priv->lock, flags);
-		dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__, line_state);
-		retval = 0;
-	} else
+	if (rc < 0) {
 		retval = rc;
+		goto err_disable_read;
+	}
 
-exit:
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->line_state = line_state;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__,
+			line_state);
+
+	return 0;
+
+err_disable_read:
+	usb_control_msg(port->serial->dev,
+			     usb_sndctrlpipe(port->serial->dev, 0),
+			     KL5KUSB105A_SIO_CONFIGURE,
+			     USB_TYPE_VENDOR | USB_DIR_OUT,
+			     KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+			     0, /* index */
+			     NULL, 0,
+			     KLSI_TIMEOUT);
+err_generic_close:
+	usb_serial_generic_close(port);
+err_free_cfg:
 	kfree(cfg);
+
 	return retval;
 }
 
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 2363654..813035f 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -51,6 +51,7 @@
 
 
 /* Function prototypes */
+static int kobil_attach(struct usb_serial *serial);
 static int kobil_port_probe(struct usb_serial_port *probe);
 static int kobil_port_remove(struct usb_serial_port *probe);
 static int  kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
@@ -86,6 +87,7 @@
 	.description =		"KOBIL USB smart card terminal",
 	.id_table =		id_table,
 	.num_ports =		1,
+	.attach =		kobil_attach,
 	.port_probe =		kobil_port_probe,
 	.port_remove =		kobil_port_remove,
 	.ioctl =		kobil_ioctl,
@@ -113,6 +115,16 @@
 };
 
 
+static int kobil_attach(struct usb_serial *serial)
+{
+	if (serial->num_interrupt_out < serial->num_ports) {
+		dev_err(&serial->interface->dev, "missing interrupt-out endpoint\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int kobil_port_probe(struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 89726f7..a6c07c6b 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -189,7 +189,7 @@
 		return -ENOMEM;
 
 	divisor = mct_u232_calculate_baud_rate(serial, value, &speed);
-	put_unaligned_le32(cpu_to_le32(divisor), buf);
+	put_unaligned_le32(divisor, buf);
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 				MCT_U232_SET_BAUD_RATE_REQUEST,
 				MCT_U232_SET_REQUEST_TYPE,
@@ -322,8 +322,12 @@
 			MCT_U232_GET_REQUEST_TYPE,
 			0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE,
 			WDR_TIMEOUT);
-	if (rc < 0) {
+	if (rc < MCT_U232_GET_MODEM_STAT_SIZE) {
 		dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc);
+
+		if (rc >= 0)
+			rc = -EIO;
+
 		*msr = 0;
 	} else {
 		*msr = buf[0];
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 78b4f64..e56cdb4 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -65,8 +65,6 @@
 	struct urb		*write_urb_pool[NUM_URBS];
 };
 
-static struct usb_serial_driver moschip7720_2port_driver;
-
 #define USB_VENDOR_ID_MOSCHIP		0x9710
 #define MOSCHIP_DEVICE_ID_7720		0x7720
 #define MOSCHIP_DEVICE_ID_7715		0x7715
@@ -970,25 +968,6 @@
 		tty_port_tty_wakeup(&mos7720_port->port->port);
 }
 
-/*
- * mos77xx_probe
- *	this function installs the appropriate read interrupt endpoint callback
- *	depending on whether the device is a 7720 or 7715, thus avoiding costly
- *	run-time checks in the high-frequency callback routine itself.
- */
-static int mos77xx_probe(struct usb_serial *serial,
-			 const struct usb_device_id *id)
-{
-	if (id->idProduct == MOSCHIP_DEVICE_ID_7715)
-		moschip7720_2port_driver.read_int_callback =
-			mos7715_interrupt_callback;
-	else
-		moschip7720_2port_driver.read_int_callback =
-			mos7720_interrupt_callback;
-
-	return 0;
-}
-
 static int mos77xx_calc_num_ports(struct usb_serial *serial)
 {
 	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
@@ -1252,7 +1231,7 @@
 
 	if (urb->transfer_buffer == NULL) {
 		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
-					       GFP_KERNEL);
+					       GFP_ATOMIC);
 		if (!urb->transfer_buffer)
 			goto exit;
 	}
@@ -1920,6 +1899,11 @@
 	u16 product;
 	int ret_val;
 
+	if (serial->num_bulk_in < 2 || serial->num_bulk_out < 2) {
+		dev_err(&serial->interface->dev, "missing bulk endpoints\n");
+		return -ENODEV;
+	}
+
 	product = le16_to_cpu(serial->dev->descriptor.idProduct);
 	dev = serial->dev;
 
@@ -1944,19 +1928,18 @@
 			tmp->interrupt_in_endpointAddress;
 		serial->port[1]->interrupt_in_urb = NULL;
 		serial->port[1]->interrupt_in_buffer = NULL;
+
+		if (serial->port[0]->interrupt_in_urb) {
+			struct urb *urb = serial->port[0]->interrupt_in_urb;
+
+			urb->complete = mos7715_interrupt_callback;
+		}
 	}
 
 	/* setting configuration feature to one */
 	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			(__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000);
 
-	/* start the interrupt urb */
-	ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
-	if (ret_val)
-		dev_err(&dev->dev,
-			"%s - Error %d submitting control urb\n",
-			__func__, ret_val);
-
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
 	if (product == MOSCHIP_DEVICE_ID_7715) {
 		ret_val = mos7715_parport_init(serial);
@@ -1964,6 +1947,13 @@
 			return ret_val;
 	}
 #endif
+	/* start the interrupt urb */
+	ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
+	if (ret_val) {
+		dev_err(&dev->dev, "failed to submit interrupt urb: %d\n",
+			ret_val);
+	}
+
 	/* LSR For Port 1 */
 	read_mos_reg(serial, 0, MOS7720_LSR, &data);
 	dev_dbg(&dev->dev, "LSR:%x\n", data);
@@ -1973,6 +1963,8 @@
 
 static void mos7720_release(struct usb_serial *serial)
 {
+	usb_kill_urb(serial->port[0]->interrupt_in_urb);
+
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
 	/* close the parallel port */
 
@@ -2007,6 +1999,7 @@
 				    urblist_entry)
 			usb_unlink_urb(urbtrack->urb);
 		spin_unlock_irqrestore(&mos_parport->listlock, flags);
+		parport_del_port(mos_parport->pp);
 
 		kref_put(&mos_parport->ref_count, destroy_mos_parport);
 	}
@@ -2055,7 +2048,6 @@
 	.close			= mos7720_close,
 	.throttle		= mos7720_throttle,
 	.unthrottle		= mos7720_unthrottle,
-	.probe			= mos77xx_probe,
 	.attach			= mos7720_startup,
 	.release		= mos7720_release,
 	.port_probe		= mos7720_port_probe,
@@ -2069,7 +2061,7 @@
 	.chars_in_buffer	= mos7720_chars_in_buffer,
 	.break_ctl		= mos7720_break,
 	.read_bulk_callback	= mos7720_bulk_in_callback,
-	.read_int_callback	= NULL  /* dynamically assigned in probe() */
+	.read_int_callback	= mos7720_interrupt_callback,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 8ac9b55..d17685c 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1024,6 +1024,7 @@
 	 * (can't set it up in mos7840_startup as the structures *
 	 * were not set up at that time.)                        */
 	if (port0->open_ports == 1) {
+		/* FIXME: Buffer never NULL, so URB is not submitted. */
 		if (serial->port[0]->interrupt_in_buffer == NULL) {
 			/* set up interrupt urb */
 			usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
@@ -1340,8 +1341,8 @@
 	}
 
 	if (urb->transfer_buffer == NULL) {
-		urb->transfer_buffer =
-		    kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+					       GFP_ATOMIC);
 		if (!urb->transfer_buffer)
 			goto exit;
 	}
@@ -2116,6 +2117,18 @@
 	return mos7840_num_ports;
 }
 
+static int mos7840_attach(struct usb_serial *serial)
+{
+	if (serial->num_bulk_in < serial->num_ports ||
+			serial->num_bulk_out < serial->num_ports ||
+			serial->num_interrupt_in < 1) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int mos7840_port_probe(struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
@@ -2391,6 +2404,7 @@
 	.tiocmset = mos7840_tiocmset,
 	.tiocmiwait = usb_serial_generic_tiocmiwait,
 	.get_icount = usb_serial_generic_get_icount,
+	.attach = mos7840_attach,
 	.port_probe = mos7840_port_probe,
 	.port_remove = mos7840_port_remove,
 	.read_bulk_callback = mos7840_bulk_in_callback,
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index 31a8b47..c6596cb 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -1259,6 +1259,15 @@
 	return 0;
 }
 
+static void mxuport_release(struct usb_serial *serial)
+{
+	struct usb_serial_port *port0 = serial->port[0];
+	struct usb_serial_port *port1 = serial->port[1];
+
+	usb_serial_generic_close(port1);
+	usb_serial_generic_close(port0);
+}
+
 static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	struct mxuport_port *mxport = usb_get_serial_port_data(port);
@@ -1361,6 +1370,7 @@
 	.probe			= mxuport_probe,
 	.port_probe		= mxuport_port_probe,
 	.attach			= mxuport_attach,
+	.release		= mxuport_release,
 	.calc_num_ports		= mxuport_calc_num_ports,
 	.open			= mxuport_open,
 	.close			= mxuport_close,
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index f6c6900..76564b3 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -38,6 +38,7 @@
 				const unsigned char *buf, int count);
 static int  omninet_write_room(struct tty_struct *tty);
 static void omninet_disconnect(struct usb_serial *serial);
+static int omninet_attach(struct usb_serial *serial);
 static int omninet_port_probe(struct usb_serial_port *port);
 static int omninet_port_remove(struct usb_serial_port *port);
 
@@ -56,6 +57,7 @@
 	.description =		"ZyXEL - omni.net lcd plus usb",
 	.id_table =		id_table,
 	.num_ports =		1,
+	.attach =		omninet_attach,
 	.port_probe =		omninet_port_probe,
 	.port_remove =		omninet_port_remove,
 	.open =			omninet_open,
@@ -104,6 +106,17 @@
 	__u8	od_outseq;	/* Sequence number for bulk_out URBs */
 };
 
+static int omninet_attach(struct usb_serial *serial)
+{
+	/* The second bulk-out endpoint is used for writing. */
+	if (serial->num_bulk_out < 2) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int omninet_port_probe(struct usb_serial_port *port)
 {
 	struct omninet_data *od;
@@ -129,12 +142,6 @@
 
 static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
-	struct usb_serial	*serial = port->serial;
-	struct usb_serial_port	*wport;
-
-	wport = serial->port[1];
-	tty_port_tty_set(&wport->port, tty);
-
 	return usb_serial_generic_open(tty, port);
 }
 
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 4b7bfb3..64bf258 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -142,7 +142,7 @@
 	usb_clear_halt(port->serial->dev, port->read_urb->pipe);
 
 	res = usb_serial_generic_open(tty, port);
-	if (!res)
+	if (res)
 		return res;
 
 	/* Request CTS line state, sometimes during opening the current
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index c6f497f..ebe51f1 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -233,6 +233,14 @@
 #define BANDRICH_PRODUCT_1012			0x1012
 
 #define QUALCOMM_VENDOR_ID			0x05C6
+/* These Quectel products use Qualcomm's vendor ID */
+#define QUECTEL_PRODUCT_UC20			0x9003
+#define QUECTEL_PRODUCT_UC15			0x9090
+
+#define QUECTEL_VENDOR_ID			0x2c7c
+/* These Quectel products use Quectel's vendor ID */
+#define QUECTEL_PRODUCT_EC21			0x0121
+#define QUECTEL_PRODUCT_EC25			0x0125
 
 #define CMOTECH_VENDOR_ID			0x16d8
 #define CMOTECH_PRODUCT_6001			0x6001
@@ -268,11 +276,21 @@
 #define TELIT_PRODUCT_CC864_SINGLE		0x1006
 #define TELIT_PRODUCT_DE910_DUAL		0x1010
 #define TELIT_PRODUCT_UE910_V2			0x1012
+#define TELIT_PRODUCT_LE922_USBCFG1		0x1040
+#define TELIT_PRODUCT_LE922_USBCFG2		0x1041
 #define TELIT_PRODUCT_LE922_USBCFG0		0x1042
 #define TELIT_PRODUCT_LE922_USBCFG3		0x1043
 #define TELIT_PRODUCT_LE922_USBCFG5		0x1045
+#define TELIT_PRODUCT_ME910			0x1100
 #define TELIT_PRODUCT_LE920			0x1200
 #define TELIT_PRODUCT_LE910			0x1201
+#define TELIT_PRODUCT_LE910_USBCFG4		0x1206
+#define TELIT_PRODUCT_LE920A4_1207		0x1207
+#define TELIT_PRODUCT_LE920A4_1208		0x1208
+#define TELIT_PRODUCT_LE920A4_1211		0x1211
+#define TELIT_PRODUCT_LE920A4_1212		0x1212
+#define TELIT_PRODUCT_LE920A4_1213		0x1213
+#define TELIT_PRODUCT_LE920A4_1214		0x1214
 
 /* ZTE PRODUCTS */
 #define ZTE_VENDOR_ID				0x19d2
@@ -375,18 +393,22 @@
 #define HAIER_PRODUCT_CE81B			0x10f8
 #define HAIER_PRODUCT_CE100			0x2009
 
-/* Cinterion (formerly Siemens) products */
-#define SIEMENS_VENDOR_ID				0x0681
-#define CINTERION_VENDOR_ID				0x1e2d
+/* Gemalto's Cinterion products (formerly Siemens) */
+#define SIEMENS_VENDOR_ID			0x0681
+#define CINTERION_VENDOR_ID			0x1e2d
+#define CINTERION_PRODUCT_HC25_MDMNET		0x0040
 #define CINTERION_PRODUCT_HC25_MDM		0x0047
-#define CINTERION_PRODUCT_HC25_MDMNET	0x0040
+#define CINTERION_PRODUCT_HC28_MDMNET		0x004A /* same for HC28J */
 #define CINTERION_PRODUCT_HC28_MDM		0x004C
-#define CINTERION_PRODUCT_HC28_MDMNET	0x004A /* same for HC28J */
 #define CINTERION_PRODUCT_EU3_E			0x0051
 #define CINTERION_PRODUCT_EU3_P			0x0052
 #define CINTERION_PRODUCT_PH8			0x0053
 #define CINTERION_PRODUCT_AHXX			0x0055
 #define CINTERION_PRODUCT_PLXX			0x0060
+#define CINTERION_PRODUCT_PH8_2RMNET		0x0082
+#define CINTERION_PRODUCT_PH8_AUDIO		0x0083
+#define CINTERION_PRODUCT_AHXX_2RMNET		0x0084
+#define CINTERION_PRODUCT_AHXX_AUDIO		0x0085
 
 /* Olivetti products */
 #define OLIVETTI_VENDOR_ID			0x0b3c
@@ -514,6 +536,12 @@
 #define VIATELECOM_VENDOR_ID			0x15eb
 #define VIATELECOM_PRODUCT_CDS7			0x0001
 
+/* WeTelecom products */
+#define WETELECOM_VENDOR_ID			0x22de
+#define WETELECOM_PRODUCT_WMD200		0x6801
+#define WETELECOM_PRODUCT_6802			0x6802
+#define WETELECOM_PRODUCT_WMD300		0x6803
+
 struct option_blacklist_info {
 	/* bitmask of interface numbers blacklisted for send_setup */
 	const unsigned long sendsetup;
@@ -613,6 +641,11 @@
 	.reserved = BIT(5) | BIT(6),
 };
 
+static const struct option_blacklist_info telit_me910_blacklist = {
+	.sendsetup = BIT(0),
+	.reserved = BIT(1) | BIT(3),
+};
+
 static const struct option_blacklist_info telit_le910_blacklist = {
 	.sendsetup = BIT(0),
 	.reserved = BIT(1) | BIT(2),
@@ -623,6 +656,11 @@
 	.reserved = BIT(1) | BIT(5),
 };
 
+static const struct option_blacklist_info telit_le920a4_blacklist_1 = {
+	.sendsetup = BIT(0),
+	.reserved = BIT(1),
+};
+
 static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = {
 	.sendsetup = BIT(2),
 	.reserved = BIT(0) | BIT(1) | BIT(3),
@@ -633,6 +671,10 @@
 	.reserved = BIT(1) | BIT(2) | BIT(3),
 };
 
+static const struct option_blacklist_info cinterion_rmnet2_blacklist = {
+	.reserved = BIT(4) | BIT(5),
+};
+
 static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -1133,7 +1175,14 @@
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
-	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */
+	/* Quectel products using Qualcomm vendor ID */
+	{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)},
+	{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	/* Quectel products using Quectel vendor ID */
+	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
@@ -1184,14 +1233,32 @@
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
 		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1),
+		.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG2),
+		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
 		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
 	{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff),
 		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
+		.driver_info = (kernel_ulong_t)&telit_me910_blacklist },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
 		.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4),
+		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
 		.driver_info = (kernel_ulong_t)&telit_le920_blacklist },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1207) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1208),
+		.driver_info = (kernel_ulong_t)&telit_le920a4_blacklist_1 },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1211),
+		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1212),
+		.driver_info = (kernel_ulong_t)&telit_le920a4_blacklist_1 },
+	{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1213, 0xff) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1214),
+		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -1602,7 +1669,79 @@
 		.driver_info = (kernel_ulong_t)&net_intf3_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t)&net_intf3_blacklist },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffe9, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff42, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff43, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff44, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff45, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff46, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff47, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff48, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff49, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4a, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4b, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4c, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4d, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4e, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4f, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff50, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff51, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff52, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff53, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff54, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff55, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff56, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff57, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff58, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff59, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5a, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5b, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5c, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5d, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5e, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5f, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff60, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff61, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff62, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff63, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff64, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff65, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff66, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff67, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff68, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff69, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6a, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6b, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6c, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6d, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6e, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6f, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff70, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff71, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff72, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff73, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff74, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff75, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff76, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff77, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff78, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff79, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7a, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7b, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7c, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7d, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7e, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7f, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff80, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff81, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff82, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff83, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff84, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff85, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff86, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff87, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff88, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff89, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8a, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8b, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8c, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8d, 0xff, 0xff, 0xff) },
@@ -1613,6 +1752,61 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff92, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff93, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff94, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff9f, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa0, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa1, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa2, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa3, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa4, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa5, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa6, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa7, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa8, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa9, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffaa, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffab, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffac, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffae, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffaf, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb0, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb1, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb2, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb3, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb4, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb5, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb6, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb7, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb8, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb9, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffba, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbb, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbc, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbd, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbe, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbf, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc0, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc1, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc2, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc3, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc4, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc5, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc6, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc7, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc8, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc9, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffca, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffcb, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffcc, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffcd, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffce, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffcf, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd0, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd1, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd2, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd3, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd4, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd5, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffe9, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffec, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffee, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xfff6, 0xff, 0xff, 0xff) },
@@ -1683,6 +1877,10 @@
 	  .driver_info = (kernel_ulong_t)&four_g_w100_blacklist
 	},
 	{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9801, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+	{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9803, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
 	{ USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
 	{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
@@ -1712,7 +1910,13 @@
 	{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX, 0xff) },
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
 		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
-	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, 
+	{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8_2RMNET, 0xff),
+		.driver_info = (kernel_ulong_t)&cinterion_rmnet2_blacklist },
+	{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8_AUDIO, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_2RMNET, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_AUDIO, 0xff) },
+	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
 	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
 	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) },
@@ -1818,13 +2022,19 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff) },			/* D-Link DWM-158 */
 	{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff),			/* D-Link DWM-221 B1 */
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */
 	{ USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) },                /* OLICARD300 - MT6225 */
 	{ USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
 	{ USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_6802, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD300, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, 0xff, 0xff, 0xff) }, /* HP lt2523 (Novatel E371) */
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index a4b88bc..b8bf52b 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -134,6 +134,7 @@
 static int oti6858_tiocmget(struct tty_struct *tty);
 static int oti6858_tiocmset(struct tty_struct *tty,
 				unsigned int set, unsigned int clear);
+static int oti6858_attach(struct usb_serial *serial);
 static int oti6858_port_probe(struct usb_serial_port *port);
 static int oti6858_port_remove(struct usb_serial_port *port);
 
@@ -158,6 +159,7 @@
 	.write_bulk_callback =	oti6858_write_bulk_callback,
 	.write_room =		oti6858_write_room,
 	.chars_in_buffer =	oti6858_chars_in_buffer,
+	.attach =		oti6858_attach,
 	.port_probe =		oti6858_port_probe,
 	.port_remove =		oti6858_port_remove,
 };
@@ -324,6 +326,20 @@
 	usb_serial_port_softint(port);
 }
 
+static int oti6858_attach(struct usb_serial *serial)
+{
+	unsigned char num_ports = serial->num_ports;
+
+	if (serial->num_bulk_in < num_ports ||
+			serial->num_bulk_out < num_ports ||
+			serial->num_interrupt_in < num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int oti6858_port_probe(struct usb_serial_port *port)
 {
 	struct oti6858_private *priv;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index ae682e4..1db4b61 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -49,6 +49,7 @@
 	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
 	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
 	{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
+	{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID2) },
 	{ USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
 	{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
 	{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
@@ -220,9 +221,17 @@
 static int pl2303_startup(struct usb_serial *serial)
 {
 	struct pl2303_serial_private *spriv;
+	unsigned char num_ports = serial->num_ports;
 	enum pl2303_type type = TYPE_01;
 	unsigned char *buf;
 
+	if (serial->num_bulk_in < num_ports ||
+			serial->num_bulk_out < num_ports ||
+			serial->num_interrupt_in < num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
 	if (!spriv)
 		return -ENOMEM;
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index e3b7af8..09d9be8 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -27,6 +27,7 @@
 #define ATEN_VENDOR_ID		0x0557
 #define ATEN_VENDOR_ID2		0x0547
 #define ATEN_PRODUCT_ID		0x2008
+#define ATEN_PRODUCT_ID2	0x2118
 
 #define IODATA_VENDOR_ID	0x04bb
 #define IODATA_PRODUCT_ID	0x0a03
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 1bc6089..652b433 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -124,6 +124,7 @@
 	{USB_DEVICE(0x1410, 0xa021)},	/* Novatel Gobi 3000 Composite */
 	{USB_DEVICE(0x413c, 0x8193)},	/* Dell Gobi 3000 QDL */
 	{USB_DEVICE(0x413c, 0x8194)},	/* Dell Gobi 3000 Composite */
+	{USB_DEVICE(0x413c, 0x81a6)},	/* Dell DW5570 QDL (MC8805) */
 	{USB_DEVICE(0x1199, 0x68a4)},	/* Sierra Wireless QDL */
 	{USB_DEVICE(0x1199, 0x68a5)},	/* Sierra Wireless Modem */
 	{USB_DEVICE(0x1199, 0x68a8)},	/* Sierra Wireless QDL */
@@ -157,10 +158,13 @@
 	{DEVICE_SWI(0x1199, 0x9056)},	/* Sierra Wireless Modem */
 	{DEVICE_SWI(0x1199, 0x9060)},	/* Sierra Wireless Modem */
 	{DEVICE_SWI(0x1199, 0x9061)},	/* Sierra Wireless Modem */
+	{DEVICE_SWI(0x1199, 0x9063)},	/* Sierra Wireless EM7305 */
 	{DEVICE_SWI(0x1199, 0x9070)},	/* Sierra Wireless MC74xx */
 	{DEVICE_SWI(0x1199, 0x9071)},	/* Sierra Wireless MC74xx */
 	{DEVICE_SWI(0x1199, 0x9078)},	/* Sierra Wireless EM74xx */
 	{DEVICE_SWI(0x1199, 0x9079)},	/* Sierra Wireless EM74xx */
+	{DEVICE_SWI(0x1199, 0x907a)},	/* Sierra Wireless EM74xx QDL */
+	{DEVICE_SWI(0x1199, 0x907b)},	/* Sierra Wireless EM74xx */
 	{DEVICE_SWI(0x413c, 0x81a2)},	/* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
 	{DEVICE_SWI(0x413c, 0x81a3)},	/* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
 	{DEVICE_SWI(0x413c, 0x81a4)},	/* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
@@ -168,6 +172,8 @@
 	{DEVICE_SWI(0x413c, 0x81a9)},	/* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
 	{DEVICE_SWI(0x413c, 0x81b1)},	/* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
 	{DEVICE_SWI(0x413c, 0x81b3)},	/* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
+	{DEVICE_SWI(0x413c, 0x81b5)},	/* Dell Wireless 5811e QDL */
+	{DEVICE_SWI(0x413c, 0x81b6)},	/* Dell Wireless 5811e QDL */
 
 	/* Huawei devices */
 	{DEVICE_HWI(0x03f0, 0x581d)},	/* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index 504f5bf..af0c872 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -141,6 +141,7 @@
 
 	serial_priv = usb_get_serial_data(serial);
 
+	usb_kill_urb(serial_priv->read_urb);
 	usb_free_urb(serial_priv->read_urb);
 	kfree(serial_priv->read_buffer);
 	kfree(serial_priv);
@@ -187,22 +188,22 @@
 }
 
 
-static inline int qt2_getdevice(struct usb_device *dev, u8 *data)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_DEVICE, 0xc0, 0, 0,
-			       data, 3, QT2_USB_TIMEOUT);
-}
-
 static inline int qt2_getregister(struct usb_device *dev,
 				  u8 uart,
 				  u8 reg,
 				  u8 *data)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_REGISTER, 0xc0, reg,
-			       uart, data, sizeof(*data), QT2_USB_TIMEOUT);
+	int ret;
 
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			      QT_SET_GET_REGISTER, 0xc0, reg,
+			      uart, data, sizeof(*data), QT2_USB_TIMEOUT);
+	if (ret < sizeof(*data)) {
+		if (ret >= 0)
+			ret = -EIO;
+	}
+
+	return ret;
 }
 
 static inline int qt2_setregister(struct usb_device *dev,
@@ -371,9 +372,11 @@
 				 0xc0, 0,
 				 device_port, data, 2, QT2_USB_TIMEOUT);
 
-	if (status < 0) {
+	if (status < 2) {
 		dev_err(&port->dev, "%s - open port failed %i\n", __func__,
 			status);
+		if (status >= 0)
+			status = -EIO;
 		kfree(data);
 		return status;
 	}
@@ -407,16 +410,12 @@
 {
 	struct usb_serial *serial;
 	struct qt2_port_private *port_priv;
-	unsigned long flags;
 	int i;
 
 	serial = port->serial;
 	port_priv = usb_get_serial_port_data(port);
 
-	spin_lock_irqsave(&port_priv->urb_lock, flags);
 	usb_kill_urb(port_priv->write_urb);
-	port_priv->urb_in_use = false;
-	spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
 	/* flush the port transmit buffer */
 	i = usb_control_msg(serial->dev,
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index b2dff0f..236ea43 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -205,6 +205,11 @@
 	if (!safe)
 		goto out;
 
+	if (length < 2) {
+		dev_err(&port->dev, "malformed packet\n");
+		return;
+	}
+
 	fcs = fcs_compute10(data, length, CRC10_INITFCS);
 	if (fcs) {
 		dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs);
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index ef0dbf0..ddfd787 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -154,6 +154,19 @@
 	return 0;
 }
 
+static int spcp8x5_attach(struct usb_serial *serial)
+{
+	unsigned char num_ports = serial->num_ports;
+
+	if (serial->num_bulk_in < num_ports ||
+			serial->num_bulk_out < num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int spcp8x5_port_probe(struct usb_serial_port *port)
 {
 	const struct usb_device_id *id = usb_get_serial_data(port->serial);
@@ -219,11 +232,17 @@
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 			      GET_UART_STATUS, GET_UART_STATUS_TYPE,
 			      0, GET_UART_STATUS_MSR, buf, 1, 100);
-	if (ret < 0)
+	if (ret < 1) {
 		dev_err(&port->dev, "failed to get modem status: %d\n", ret);
+		if (ret >= 0)
+			ret = -EIO;
+		goto out;
+	}
 
 	dev_dbg(&port->dev, "0xc0:0x22:0:6  %d - 0x02%x\n", ret, *buf);
 	*status = *buf;
+	ret = 0;
+out:
 	kfree(buf);
 
 	return ret;
@@ -477,6 +496,7 @@
 	.tiocmget		= spcp8x5_tiocmget,
 	.tiocmset		= spcp8x5_tiocmset,
 	.probe			= spcp8x5_probe,
+	.attach			= spcp8x5_attach,
 	.port_probe		= spcp8x5_port_probe,
 	.port_remove		= spcp8x5_port_remove,
 };
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 70a098d..886e129 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -80,9 +80,17 @@
 
 static inline int ssu100_getdevice(struct usb_device *dev, u8 *data)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_DEVICE, 0xc0, 0, 0,
-			       data, 3, 300);
+	int ret;
+
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			      QT_SET_GET_DEVICE, 0xc0, 0, 0,
+			      data, 3, 300);
+	if (ret < 3) {
+		if (ret >= 0)
+			ret = -EIO;
+	}
+
+	return ret;
 }
 
 static inline int ssu100_getregister(struct usb_device *dev,
@@ -90,10 +98,17 @@
 				     unsigned short reg,
 				     u8 *data)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_REGISTER, 0xc0, reg,
-			       uart, data, sizeof(*data), 300);
+	int ret;
 
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			      QT_SET_GET_REGISTER, 0xc0, reg,
+			      uart, data, sizeof(*data), 300);
+	if (ret < sizeof(*data)) {
+		if (ret >= 0)
+			ret = -EIO;
+	}
+
+	return ret;
 }
 
 
@@ -289,8 +304,10 @@
 				 QT_OPEN_CLOSE_CHANNEL,
 				 QT_TRANSFER_IN, 0x01,
 				 0, data, 2, 300);
-	if (result < 0) {
+	if (result < 2) {
 		dev_dbg(&port->dev, "%s - open failed %i\n", __func__, result);
+		if (result >= 0)
+			result = -EIO;
 		kfree(data);
 		return result;
 	}
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 2694df2..fe7f5ac 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -339,6 +339,13 @@
 		goto free_tdev;
 	}
 
+	if (serial->num_bulk_in < serial->num_ports ||
+			serial->num_bulk_out < serial->num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		status = -ENODEV;
+		goto free_tdev;
+	}
+
 	return 0;
 
 free_tdev:
@@ -1345,13 +1352,10 @@
 		(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
 		value, moduleid, data, size, 1000);
 
-	if (status == size)
-		status = 0;
+	if (status < 0)
+		return status;
 
-	if (status > 0)
-		status = -ECOMM;
-
-	return status;
+	return 0;
 }
 
 
@@ -1367,8 +1371,7 @@
 
 	if (status == size)
 		status = 0;
-
-	if (status > 0)
+	else if (status >= 0)
 		status = -ECOMM;
 
 	return status;
diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c
index a204782..e98b6e5 100644
--- a/drivers/usb/serial/usb-serial-simple.c
+++ b/drivers/usb/serial/usb-serial-simple.c
@@ -54,7 +54,8 @@
 /* Infineon Flashloader driver */
 #define FLASHLOADER_IDS()		\
 	{ USB_DEVICE_INTERFACE_CLASS(0x058b, 0x0041, USB_CLASS_CDC_DATA) }, \
-	{ USB_DEVICE(0x8087, 0x0716) }
+	{ USB_DEVICE(0x8087, 0x0716) }, \
+	{ USB_DEVICE(0x8087, 0x0801) }
 DEVICE(flashloader, FLASHLOADER_IDS);
 
 /* Google Serial USB SubClass */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 46f1f13..e7e29c7 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1077,7 +1077,8 @@
 
 	serial->disconnected = 0;
 
-	usb_serial_console_init(serial->port[0]->minor);
+	if (num_ports > 0)
+		usb_serial_console_init(serial->port[0]->minor);
 exit:
 	module_put(type->driver.owner);
 	return 0;
@@ -1432,7 +1433,7 @@
 
 	rc = usb_register(udriver);
 	if (rc)
-		return rc;
+		goto failed_usb_register;
 
 	for (sd = serial_drivers; *sd; ++sd) {
 		(*sd)->usb_driver = udriver;
@@ -1450,6 +1451,8 @@
 	while (sd-- > serial_drivers)
 		usb_serial_deregister(*sd);
 	usb_deregister(udriver);
+failed_usb_register:
+	kfree(udriver);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(usb_serial_register_drivers);
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index f3cf4ce..091e8ec 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -446,6 +446,10 @@
 #define SD_BLOCK_LEN  9
 
 struct ene_ub6250_info {
+
+	/* I/O bounce buffer */
+	u8		*bbuf;
+
 	/* for 6250 code */
 	struct SD_STATUS	SD_Status;
 	struct MS_STATUS	MS_Status;
@@ -493,8 +497,11 @@
 
 static void ene_ub6250_info_destructor(void *extra)
 {
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) extra;
+
 	if (!extra)
 		return;
+	kfree(info->bbuf);
 }
 
 static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
@@ -858,8 +865,9 @@
 		u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat)
 {
 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+	u8 *bbuf = info->bbuf;
 	int result;
-	u8 ExtBuf[4];
 	u32 bn = PhyBlockAddr * 0x20 + PageNum;
 
 	/* printk(KERN_INFO "MS --- MS_ReaderReadPage,
@@ -902,7 +910,7 @@
 	bcb->CDB[2]     = (unsigned char)(PhyBlockAddr>>16);
 	bcb->CDB[6]     = 0x01;
 
-	result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
+	result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
@@ -911,9 +919,9 @@
 	ExtraDat->status0  = 0x10;  /* Not yet,fireware support */
 
 	ExtraDat->status1  = 0x00;  /* Not yet,fireware support */
-	ExtraDat->ovrflg   = ExtBuf[0];
-	ExtraDat->mngflg   = ExtBuf[1];
-	ExtraDat->logadr   = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
+	ExtraDat->ovrflg   = bbuf[0];
+	ExtraDat->mngflg   = bbuf[1];
+	ExtraDat->logadr   = memstick_logaddr(bbuf[2], bbuf[3]);
 
 	return USB_STOR_TRANSPORT_GOOD;
 }
@@ -1339,8 +1347,9 @@
 				u8 PageNum, struct ms_lib_type_extdat *ExtraDat)
 {
 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+	u8 *bbuf = info->bbuf;
 	int result;
-	u8 ExtBuf[4];
 
 	/* printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n", PhyBlock, PageNum); */
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
@@ -1355,7 +1364,7 @@
 	bcb->CDB[2]     = (unsigned char)(PhyBlock>>16);
 	bcb->CDB[6]     = 0x01;
 
-	result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
+	result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
@@ -1363,9 +1372,9 @@
 	ExtraDat->intr     = 0x80;  /* Not yet, waiting for fireware support */
 	ExtraDat->status0  = 0x10;  /* Not yet, waiting for fireware support */
 	ExtraDat->status1  = 0x00;  /* Not yet, waiting for fireware support */
-	ExtraDat->ovrflg   = ExtBuf[0];
-	ExtraDat->mngflg   = ExtBuf[1];
-	ExtraDat->logadr   = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
+	ExtraDat->ovrflg   = bbuf[0];
+	ExtraDat->mngflg   = bbuf[1];
+	ExtraDat->logadr   = memstick_logaddr(bbuf[2], bbuf[3]);
 
 	return USB_STOR_TRANSPORT_GOOD;
 }
@@ -1569,9 +1578,9 @@
 	u16 PhyBlock, newblk, i;
 	u16 LogStart, LogEnde;
 	struct ms_lib_type_extdat extdat;
-	u8 buf[0x200];
 	u32 count = 0, index = 0;
 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+	u8 *bbuf = info->bbuf;
 
 	for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) {
 		ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde);
@@ -1585,14 +1594,16 @@
 			}
 
 			if (count == PhyBlock) {
-				ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf);
+				ms_lib_read_extrablock(us, PhyBlock, 0, 0x80,
+						bbuf);
 				count += 0x80;
 			}
 			index = (PhyBlock % 0x80) * 4;
 
-			extdat.ovrflg = buf[index];
-			extdat.mngflg = buf[index+1];
-			extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]);
+			extdat.ovrflg = bbuf[index];
+			extdat.mngflg = bbuf[index+1];
+			extdat.logadr = memstick_logaddr(bbuf[index+2],
+					bbuf[index+3]);
 
 			if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) {
 				ms_lib_setacquired_errorblock(us, PhyBlock);
@@ -2075,9 +2086,9 @@
 {
 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
 	int result;
-	u8 buf[0x200];
 	u16 MSP_BlockSize, MSP_UserAreaBlocks;
 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+	u8 *bbuf = info->bbuf;
 
 	printk(KERN_INFO "transport --- ENE_MSInit\n");
 
@@ -2096,13 +2107,13 @@
 	bcb->CDB[0]     = 0xF1;
 	bcb->CDB[1]     = 0x01;
 
-	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
+	result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
 	if (result != USB_STOR_XFER_GOOD) {
 		printk(KERN_ERR "Execution MS Init Code Fail !!\n");
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 	/* the same part to test ENE */
-	info->MS_Status = *(struct MS_STATUS *)&buf[0];
+	info->MS_Status = *(struct MS_STATUS *) bbuf;
 
 	if (info->MS_Status.Insert && info->MS_Status.Ready) {
 		printk(KERN_INFO "Insert     = %x\n", info->MS_Status.Insert);
@@ -2111,15 +2122,15 @@
 		printk(KERN_INFO "IsMSPHG    = %x\n", info->MS_Status.IsMSPHG);
 		printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP);
 		if (info->MS_Status.IsMSPro) {
-			MSP_BlockSize      = (buf[6] << 8) | buf[7];
-			MSP_UserAreaBlocks = (buf[10] << 8) | buf[11];
+			MSP_BlockSize      = (bbuf[6] << 8) | bbuf[7];
+			MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11];
 			info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
 		} else {
 			ms_card_init(us); /* Card is MS (to ms.c)*/
 		}
 		usb_stor_dbg(us, "MS Init Code OK !!\n");
 	} else {
-		usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]);
+		usb_stor_dbg(us, "MS Card Not Ready --- %x\n", bbuf[0]);
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
@@ -2129,9 +2140,9 @@
 static int ene_sd_init(struct us_data *us)
 {
 	int result;
-	u8  buf[0x200];
 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+	u8 *bbuf = info->bbuf;
 
 	usb_stor_dbg(us, "transport --- ENE_SDInit\n");
 	/* SD Init Part-1 */
@@ -2165,17 +2176,17 @@
 	bcb->Flags              = US_BULK_FLAG_IN;
 	bcb->CDB[0]             = 0xF1;
 
-	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
+	result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
 	if (result != USB_STOR_XFER_GOOD) {
 		usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
-	info->SD_Status =  *(struct SD_STATUS *)&buf[0];
+	info->SD_Status =  *(struct SD_STATUS *) bbuf;
 	if (info->SD_Status.Insert && info->SD_Status.Ready) {
 		struct SD_STATUS *s = &info->SD_Status;
 
-		ene_get_card_status(us, (unsigned char *)&buf);
+		ene_get_card_status(us, bbuf);
 		usb_stor_dbg(us, "Insert     = %x\n", s->Insert);
 		usb_stor_dbg(us, "Ready      = %x\n", s->Ready);
 		usb_stor_dbg(us, "IsMMC      = %x\n", s->IsMMC);
@@ -2183,7 +2194,7 @@
 		usb_stor_dbg(us, "HiSpeed    = %x\n", s->HiSpeed);
 		usb_stor_dbg(us, "WtP        = %x\n", s->WtP);
 	} else {
-		usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]);
+		usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]);
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 	return USB_STOR_TRANSPORT_GOOD;
@@ -2193,13 +2204,15 @@
 static int ene_init(struct us_data *us)
 {
 	int result;
-	u8  misc_reg03 = 0;
+	u8  misc_reg03;
 	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+	u8 *bbuf = info->bbuf;
 
-	result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+	result = ene_get_card_type(us, REG_CARD_STATUS, bbuf);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
+	misc_reg03 = bbuf[0];
 	if (misc_reg03 & 0x01) {
 		if (!info->SD_Status.Ready) {
 			result = ene_sd_init(us);
@@ -2316,8 +2329,9 @@
 			 const struct usb_device_id *id)
 {
 	int result;
-	u8  misc_reg03 = 0;
+	u8  misc_reg03;
 	struct us_data *us;
+	struct ene_ub6250_info *info;
 
 	result = usb_stor_probe1(&us, intf, id,
 		   (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list,
@@ -2326,11 +2340,16 @@
 		return result;
 
 	/* FIXME: where should the code alloc extra buf ? */
-	if (!us->extra) {
-		us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
-		if (!us->extra)
-			return -ENOMEM;
-		us->extra_destructor = ene_ub6250_info_destructor;
+	us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
+	if (!us->extra)
+		return -ENOMEM;
+	us->extra_destructor = ene_ub6250_info_destructor;
+
+	info = (struct ene_ub6250_info *)(us->extra);
+	info->bbuf = kmalloc(512, GFP_KERNEL);
+	if (!info->bbuf) {
+		kfree(us->extra);
+		return -ENOMEM;
 	}
 
 	us->transport_name = "ene_ub6250";
@@ -2342,12 +2361,13 @@
 		return result;
 
 	/* probe card type */
-	result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+	result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf);
 	if (result != USB_STOR_XFER_GOOD) {
 		usb_stor_disconnect(intf);
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
+	misc_reg03 = info->bbuf[0];
 	if (!(misc_reg03 & 0x01)) {
 		pr_info("ums_eneub6250: This driver only supports SD/MS cards. "
 			"It does not support SM cards.\n");
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 5e67f63..02f86dd 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -919,10 +919,15 @@
 
 	/* COMMAND STAGE */
 	/* let's send the command via the control pipe */
+	/*
+	 * Command is sometime (f.e. after scsi_eh_prep_cmnd) on the stack.
+	 * Stack may be vmallocated.  So no DMA for us.  Make a copy.
+	 */
+	memcpy(us->iobuf, srb->cmnd, srb->cmd_len);
 	result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
 				      US_CBI_ADSC, 
 				      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
-				      us->ifnum, srb->cmnd, srb->cmd_len);
+				      us->ifnum, us->iobuf, srb->cmd_len);
 
 	/* check the return code for the command */
 	usb_stor_dbg(us, "Call to usb_stor_ctrl_transfer() returned %d\n",
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 9baf081..e26e321 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -811,6 +811,7 @@
 	if (devinfo->flags & US_FL_BROKEN_FUA)
 		sdev->broken_fua = 1;
 
+	scsi_change_queue_depth(sdev, devinfo->qdepth - 2);
 	return 0;
 }
 
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 7ffe420..640a2e2 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -2135,6 +2135,13 @@
 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
+/* Reported-by George Cherian <george.cherian@cavium.com> */
+UNUSUAL_DEV(0x152d, 0x9561, 0x0000, 0x9999,
+		"JMicron",
+		"JMS56x",
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_NO_REPORT_OPCODES),
+
 /*
  * Patch by Constantin Baranov <const@tltsu.ru>
  * Report by Andreas Koenecke.
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c
index 44ab43f..af10f7b 100644
--- a/drivers/usb/usbip/stub_main.c
+++ b/drivers/usb/usbip/stub_main.c
@@ -262,7 +262,11 @@
 		kmem_cache_free(stub_priv_cache, priv);
 
 		kfree(urb->transfer_buffer);
+		urb->transfer_buffer = NULL;
+
 		kfree(urb->setup_packet);
+		urb->setup_packet = NULL;
+
 		usb_free_urb(urb);
 	}
 }
diff --git a/drivers/usb/usbip/stub_tx.c b/drivers/usb/usbip/stub_tx.c
index dbcabc9..021003c 100644
--- a/drivers/usb/usbip/stub_tx.c
+++ b/drivers/usb/usbip/stub_tx.c
@@ -28,7 +28,11 @@
 	struct urb *urb = priv->urb;
 
 	kfree(urb->setup_packet);
+	urb->setup_packet = NULL;
+
 	kfree(urb->transfer_buffer);
+	urb->transfer_buffer = NULL;
+
 	list_del(&priv->list);
 	kmem_cache_free(stub_priv_cache, priv);
 	usb_free_urb(urb);
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 7fbe19d..81b2b9f 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -215,14 +215,19 @@
 
 static inline void hub_descriptor(struct usb_hub_descriptor *desc)
 {
+	int width;
+
 	memset(desc, 0, sizeof(*desc));
 	desc->bDescriptorType = USB_DT_HUB;
-	desc->bDescLength = 9;
 	desc->wHubCharacteristics = cpu_to_le16(
 		HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM);
+
 	desc->bNbrPorts = VHCI_NPORTS;
-	desc->u.hs.DeviceRemovable[0] = 0xff;
-	desc->u.hs.DeviceRemovable[1] = 0xff;
+	BUILD_BUG_ON(VHCI_NPORTS > USB_MAXCHILDREN);
+	width = desc->bNbrPorts / 8 + 1;
+	desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * width;
+	memset(&desc->u.hs.DeviceRemovable[0], 0, width);
+	memset(&desc->u.hs.DeviceRemovable[width], 0xff, width);
 }
 
 static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c
index 252c7bd..d01496f 100644
--- a/drivers/usb/wusbcore/wa-hc.c
+++ b/drivers/usb/wusbcore/wa-hc.c
@@ -39,6 +39,9 @@
 	int result;
 	struct device *dev = &iface->dev;
 
+	if (iface->cur_altsetting->desc.bNumEndpoints < 3)
+		return -ENODEV;
+
 	result = wa_rpipes_create(wa);
 	if (result < 0)
 		goto error_rpipes_create;
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c
index 0257f35..e75bbe5 100644
--- a/drivers/uwb/hwa-rc.c
+++ b/drivers/uwb/hwa-rc.c
@@ -825,6 +825,9 @@
 	struct hwarc *hwarc;
 	struct device *dev = &iface->dev;
 
+	if (iface->cur_altsetting->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	result = -ENOMEM;
 	uwb_rc = uwb_rc_alloc();
 	if (uwb_rc == NULL) {
diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c
index 2bfc846..a50cf45 100644
--- a/drivers/uwb/i1480/dfu/usb.c
+++ b/drivers/uwb/i1480/dfu/usb.c
@@ -341,6 +341,7 @@
 static
 int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id)
 {
+	struct usb_device *udev = interface_to_usbdev(iface);
 	struct i1480_usb *i1480_usb;
 	struct i1480 *i1480;
 	struct device *dev = &iface->dev;
@@ -352,8 +353,8 @@
 			iface->cur_altsetting->desc.bInterfaceNumber);
 		goto error;
 	}
-	if (iface->num_altsetting > 1
-	    && interface_to_usbdev(iface)->descriptor.idProduct == 0xbabe) {
+	if (iface->num_altsetting > 1 &&
+			le16_to_cpu(udev->descriptor.idProduct) == 0xbabe) {
 		/* Need altsetting #1 [HW QUIRK] or EP1 won't work */
 		result = usb_set_interface(interface_to_usbdev(iface), 0, 1);
 		if (result < 0)
@@ -362,6 +363,9 @@
 				 result);
 	}
 
+	if (iface->cur_altsetting->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	result = -ENOMEM;
 	i1480_usb = kzalloc(sizeof(*i1480_usb), GFP_KERNEL);
 	if (i1480_usb == NULL) {
diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c
index d059ad4..97ee1b4 100644
--- a/drivers/uwb/lc-rc.c
+++ b/drivers/uwb/lc-rc.c
@@ -56,8 +56,11 @@
 	struct uwb_rc *rc = NULL;
 
 	dev = class_find_device(&uwb_rc_class, NULL, &index, uwb_rc_index_match);
-	if (dev)
+	if (dev) {
 		rc = dev_get_drvdata(dev);
+		put_device(dev);
+	}
+
 	return rc;
 }
 
@@ -467,7 +470,9 @@
 	if (dev) {
 		rc = dev_get_drvdata(dev);
 		__uwb_rc_get(rc);
+		put_device(dev);
 	}
+
 	return rc;
 }
 EXPORT_SYMBOL_GPL(__uwb_rc_try_get);
@@ -520,8 +525,11 @@
 
 	dev = class_find_device(&uwb_rc_class, NULL, grandpa_dev,
 				find_rc_grandpa);
-	if (dev)
+	if (dev) {
 		rc = dev_get_drvdata(dev);
+		put_device(dev);
+	}
+
 	return rc;
 }
 EXPORT_SYMBOL_GPL(uwb_rc_get_by_grandpa);
@@ -553,8 +561,10 @@
 	struct uwb_rc *rc = NULL;
 
 	dev = class_find_device(&uwb_rc_class, NULL, addr, find_rc_dev);
-	if (dev)
+	if (dev) {
 		rc = dev_get_drvdata(dev);
+		put_device(dev);
+	}
 
 	return rc;
 }
diff --git a/drivers/uwb/pal.c b/drivers/uwb/pal.c
index c1304b8..678e937 100644
--- a/drivers/uwb/pal.c
+++ b/drivers/uwb/pal.c
@@ -97,6 +97,8 @@
 
 	dev = class_find_device(&uwb_rc_class, NULL, target_rc,	find_rc);
 
+	put_device(dev);
+
 	return (dev != NULL);
 }
 
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 9982cb1..830e2fd 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -562,8 +562,9 @@
 
 	} else if (cmd == VFIO_DEVICE_SET_IRQS) {
 		struct vfio_irq_set hdr;
+		size_t size;
 		u8 *data = NULL;
-		int ret = 0;
+		int max, ret = 0;
 
 		minsz = offsetofend(struct vfio_irq_set, count);
 
@@ -571,23 +572,31 @@
 			return -EFAULT;
 
 		if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS ||
+		    hdr.count >= (U32_MAX - hdr.start) ||
 		    hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
 				  VFIO_IRQ_SET_ACTION_TYPE_MASK))
 			return -EINVAL;
 
-		if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
-			size_t size;
-			int max = vfio_pci_get_irq_count(vdev, hdr.index);
+		max = vfio_pci_get_irq_count(vdev, hdr.index);
+		if (hdr.start >= max || hdr.start + hdr.count > max)
+			return -EINVAL;
 
-			if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
-				size = sizeof(uint8_t);
-			else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD)
-				size = sizeof(int32_t);
-			else
-				return -EINVAL;
+		switch (hdr.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
+		case VFIO_IRQ_SET_DATA_NONE:
+			size = 0;
+			break;
+		case VFIO_IRQ_SET_DATA_BOOL:
+			size = sizeof(uint8_t);
+			break;
+		case VFIO_IRQ_SET_DATA_EVENTFD:
+			size = sizeof(int32_t);
+			break;
+		default:
+			return -EINVAL;
+		}
 
-			if (hdr.argsz - minsz < hdr.count * size ||
-			    hdr.start >= max || hdr.start + hdr.count > max)
+		if (size) {
+			if (hdr.argsz - minsz < hdr.count * size)
 				return -EINVAL;
 
 			data = memdup_user((void __user *)(arg + minsz),
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 3b3ba15..5c8f767 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -255,7 +255,7 @@
 	if (!is_irq_none(vdev))
 		return -EINVAL;
 
-	vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);
+	vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);
 	if (!vdev->ctx)
 		return -ENOMEM;
 
@@ -563,67 +563,80 @@
 }
 
 static int vfio_pci_set_ctx_trigger_single(struct eventfd_ctx **ctx,
-					   uint32_t flags, void *data)
+					   unsigned int count, uint32_t flags,
+					   void *data)
 {
-	int32_t fd = *(int32_t *)data;
-
-	if (!(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
-		return -EINVAL;
-
 	/* DATA_NONE/DATA_BOOL enables loopback testing */
 	if (flags & VFIO_IRQ_SET_DATA_NONE) {
-		if (*ctx)
-			eventfd_signal(*ctx, 1);
-		return 0;
+		if (*ctx) {
+			if (count) {
+				eventfd_signal(*ctx, 1);
+			} else {
+				eventfd_ctx_put(*ctx);
+				*ctx = NULL;
+			}
+			return 0;
+		}
 	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
-		uint8_t trigger = *(uint8_t *)data;
+		uint8_t trigger;
+
+		if (!count)
+			return -EINVAL;
+
+		trigger = *(uint8_t *)data;
 		if (trigger && *ctx)
 			eventfd_signal(*ctx, 1);
+
+		return 0;
+	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+		int32_t fd;
+
+		if (!count)
+			return -EINVAL;
+
+		fd = *(int32_t *)data;
+		if (fd == -1) {
+			if (*ctx)
+				eventfd_ctx_put(*ctx);
+			*ctx = NULL;
+		} else if (fd >= 0) {
+			struct eventfd_ctx *efdctx;
+
+			efdctx = eventfd_ctx_fdget(fd);
+			if (IS_ERR(efdctx))
+				return PTR_ERR(efdctx);
+
+			if (*ctx)
+				eventfd_ctx_put(*ctx);
+
+			*ctx = efdctx;
+		}
 		return 0;
 	}
 
-	/* Handle SET_DATA_EVENTFD */
-	if (fd == -1) {
-		if (*ctx)
-			eventfd_ctx_put(*ctx);
-		*ctx = NULL;
-		return 0;
-	} else if (fd >= 0) {
-		struct eventfd_ctx *efdctx;
-		efdctx = eventfd_ctx_fdget(fd);
-		if (IS_ERR(efdctx))
-			return PTR_ERR(efdctx);
-		if (*ctx)
-			eventfd_ctx_put(*ctx);
-		*ctx = efdctx;
-		return 0;
-	} else
-		return -EINVAL;
+	return -EINVAL;
 }
 
 static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
 				    unsigned index, unsigned start,
 				    unsigned count, uint32_t flags, void *data)
 {
-	if (index != VFIO_PCI_ERR_IRQ_INDEX)
+	if (index != VFIO_PCI_ERR_IRQ_INDEX || start != 0 || count > 1)
 		return -EINVAL;
 
-	/*
-	 * We should sanitize start & count, but that wasn't caught
-	 * originally, so this IRQ index must forever ignore them :-(
-	 */
-
-	return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger, flags, data);
+	return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger,
+					       count, flags, data);
 }
 
 static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
 				    unsigned index, unsigned start,
 				    unsigned count, uint32_t flags, void *data)
 {
-	if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count != 1)
+	if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count > 1)
 		return -EINVAL;
 
-	return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger, flags, data);
+	return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger,
+					       count, flags, data);
 }
 
 int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
index 0582b72..34e4b3a 100644
--- a/drivers/vfio/vfio_iommu_spapr_tce.c
+++ b/drivers/vfio/vfio_iommu_spapr_tce.c
@@ -511,6 +511,12 @@
 	unsigned long hpa;
 	enum dma_data_direction dirtmp;
 
+	if (!tbl->it_userspace) {
+		ret = tce_iommu_userspace_view_alloc(tbl);
+		if (ret)
+			return ret;
+	}
+
 	for (i = 0; i < pages; ++i) {
 		struct mm_iommu_table_group_mem_t *mem = NULL;
 		unsigned long *pua = IOMMU_TABLE_USERSPACE_ENTRY(tbl,
@@ -584,15 +590,6 @@
 	WARN_ON(!ret && !(*ptbl)->it_ops->free);
 	WARN_ON(!ret && ((*ptbl)->it_allocated_size != table_size));
 
-	if (!ret && container->v2) {
-		ret = tce_iommu_userspace_view_alloc(*ptbl);
-		if (ret)
-			(*ptbl)->it_ops->free(*ptbl);
-	}
-
-	if (ret)
-		decrement_locked_vm(table_size >> PAGE_SHIFT);
-
 	return ret;
 }
 
@@ -1064,10 +1061,7 @@
 		if (!tbl || !tbl->it_map)
 			continue;
 
-		rc = tce_iommu_userspace_view_alloc(tbl);
-		if (!rc)
-			rc = iommu_take_ownership(tbl);
-
+		rc = iommu_take_ownership(tbl);
 		if (rc) {
 			for (j = 0; j < i; ++j)
 				iommu_release_ownership(
@@ -1169,6 +1163,10 @@
 	/* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n",
 			iommu_group_id(iommu_group), iommu_group); */
 	table_group = iommu_group_get_iommudata(iommu_group);
+	if (!table_group) {
+		ret = -ENODEV;
+		goto unlock_exit;
+	}
 
 	if (tce_groups_attached(container) && (!table_group->ops ||
 			!table_group->ops->take_ownership ||
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index ecb826e..2fa2806 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -130,57 +130,34 @@
 	rb_erase(&old->node, &iommu->dma_list);
 }
 
-struct vwork {
-	struct mm_struct	*mm;
-	long			npage;
-	struct work_struct	work;
-};
-
-/* delayed decrement/increment for locked_vm */
-static void vfio_lock_acct_bg(struct work_struct *work)
+static int vfio_lock_acct(long npage, bool *lock_cap)
 {
-	struct vwork *vwork = container_of(work, struct vwork, work);
-	struct mm_struct *mm;
+	int ret = 0;
 
-	mm = vwork->mm;
-	down_write(&mm->mmap_sem);
-	mm->locked_vm += vwork->npage;
-	up_write(&mm->mmap_sem);
-	mmput(mm);
-	kfree(vwork);
-}
+	if (!npage)
+		return 0;
 
-static void vfio_lock_acct(long npage)
-{
-	struct vwork *vwork;
-	struct mm_struct *mm;
+	if (!current->mm)
+		return -ESRCH; /* process exited */
 
-	if (!current->mm || !npage)
-		return; /* process exited or nothing to do */
+	down_write(&current->mm->mmap_sem);
+	if (npage > 0) {
+		if (lock_cap ? !*lock_cap : !capable(CAP_IPC_LOCK)) {
+			unsigned long limit;
 
-	if (down_write_trylock(&current->mm->mmap_sem)) {
+			limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+
+			if (current->mm->locked_vm + npage > limit)
+				ret = -ENOMEM;
+		}
+	}
+
+	if (!ret)
 		current->mm->locked_vm += npage;
-		up_write(&current->mm->mmap_sem);
-		return;
-	}
 
-	/*
-	 * Couldn't get mmap_sem lock, so must setup to update
-	 * mm->locked_vm later. If locked_vm were atomic, we
-	 * wouldn't need this silliness
-	 */
-	vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL);
-	if (!vwork)
-		return;
-	mm = get_task_mm(current);
-	if (!mm) {
-		kfree(vwork);
-		return;
-	}
-	INIT_WORK(&vwork->work, vfio_lock_acct_bg);
-	vwork->mm = mm;
-	vwork->npage = npage;
-	schedule_work(&vwork->work);
+	up_write(&current->mm->mmap_sem);
+
+	return ret;
 }
 
 /*
@@ -262,9 +239,9 @@
 static long vfio_pin_pages(unsigned long vaddr, long npage,
 			   int prot, unsigned long *pfn_base)
 {
-	unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+	unsigned long pfn = 0, limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
 	bool lock_cap = capable(CAP_IPC_LOCK);
-	long ret, i;
+	long ret, i = 1;
 	bool rsvd;
 
 	if (!current->mm)
@@ -283,16 +260,11 @@
 		return -ENOMEM;
 	}
 
-	if (unlikely(disable_hugepages)) {
-		if (!rsvd)
-			vfio_lock_acct(1);
-		return 1;
-	}
+	if (unlikely(disable_hugepages))
+		goto out;
 
 	/* Lock all the consecutive pages from pfn_base */
-	for (i = 1, vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) {
-		unsigned long pfn = 0;
-
+	for (vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) {
 		ret = vaddr_get_pfn(vaddr, prot, &pfn);
 		if (ret)
 			break;
@@ -308,12 +280,24 @@
 			put_pfn(pfn, prot);
 			pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
 				__func__, limit << PAGE_SHIFT);
-			break;
+			ret = -ENOMEM;
+			goto unpin_out;
 		}
 	}
 
+out:
 	if (!rsvd)
-		vfio_lock_acct(i);
+		ret = vfio_lock_acct(i, &lock_cap);
+
+unpin_out:
+	if (ret) {
+		if (!rsvd) {
+			for (pfn = *pfn_base ; i ; pfn++, i--)
+				put_pfn(pfn, prot);
+		}
+
+		return ret;
+	}
 
 	return i;
 }
@@ -328,7 +312,7 @@
 		unlocked += put_pfn(pfn++, prot);
 
 	if (do_accounting)
-		vfio_lock_acct(-unlocked);
+		vfio_lock_acct(-unlocked, NULL);
 
 	return unlocked;
 }
@@ -390,7 +374,7 @@
 		cond_resched();
 	}
 
-	vfio_lock_acct(-unlocked);
+	vfio_lock_acct(-unlocked, NULL);
 }
 
 static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 29cfc57..e4110d6 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -88,7 +88,7 @@
 	struct scatterlist *tvc_prot_sgl;
 	struct page **tvc_upages;
 	/* Pointer to response header iovec */
-	struct iovec *tvc_resp_iov;
+	struct iovec tvc_resp_iov;
 	/* Pointer to vhost_scsi for our device */
 	struct vhost_scsi *tvc_vhost;
 	/* Pointer to vhost_virtqueue for the cmd */
@@ -557,7 +557,7 @@
 		memcpy(v_rsp.sense, cmd->tvc_sense_buf,
 		       se_cmd->scsi_sense_length);
 
-		iov_iter_init(&iov_iter, READ, cmd->tvc_resp_iov,
+		iov_iter_init(&iov_iter, READ, &cmd->tvc_resp_iov,
 			      cmd->tvc_in_iovs, sizeof(v_rsp));
 		ret = copy_to_iter(&v_rsp, sizeof(v_rsp), &iov_iter);
 		if (likely(ret == sizeof(v_rsp))) {
@@ -1054,7 +1054,7 @@
 		}
 		cmd->tvc_vhost = vs;
 		cmd->tvc_vq = vq;
-		cmd->tvc_resp_iov = &vq->iov[out];
+		cmd->tvc_resp_iov = vq->iov[out];
 		cmd->tvc_in_iovs = in;
 
 		pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e0606c0..35d239e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -29,6 +29,7 @@
 endmenu
 
 source "drivers/video/backlight/Kconfig"
+source "drivers/video/adf/Kconfig"
 
 config VGASTATE
        tristate
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9ad3c17..1a8c4ce 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_VGASTATE)            += vgastate.o
 obj-$(CONFIG_HDMI)                += hdmi.o
 
+obj-$(CONFIG_ADF)		  += adf/
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_LOGO)		  += logo/
 obj-y				  += backlight/
diff --git a/drivers/video/adf/Kconfig b/drivers/video/adf/Kconfig
new file mode 100644
index 0000000..2777db4
--- /dev/null
+++ b/drivers/video/adf/Kconfig
@@ -0,0 +1,14 @@
+menuconfig ADF
+	depends on SYNC
+	depends on DMA_SHARED_BUFFER
+	tristate "Atomic Display Framework"
+
+menuconfig ADF_FBDEV
+	depends on ADF
+	depends on FB
+	tristate "Helper for implementing the fbdev API in ADF drivers"
+
+menuconfig ADF_MEMBLOCK
+	depends on ADF
+	depends on HAVE_MEMBLOCK
+	bool "Helper for using memblocks as buffers in ADF drivers"
diff --git a/drivers/video/adf/Makefile b/drivers/video/adf/Makefile
new file mode 100644
index 0000000..cdf34a6
--- /dev/null
+++ b/drivers/video/adf/Makefile
@@ -0,0 +1,17 @@
+ccflags-y := -Idrivers/staging/android
+
+CFLAGS_adf.o := -I$(src)
+
+obj-$(CONFIG_ADF) += adf_core.o
+
+adf_core-y := adf.o \
+	adf_client.o \
+	adf_fops.o \
+	adf_format.o \
+	adf_sysfs.o
+
+adf_core-$(CONFIG_COMPAT) += adf_fops32.o
+
+obj-$(CONFIG_ADF_FBDEV) += adf_fbdev.o
+
+obj-$(CONFIG_ADF_MEMBLOCK) += adf_memblock.o
diff --git a/drivers/video/adf/adf.c b/drivers/video/adf/adf.c
new file mode 100644
index 0000000..42c30c0
--- /dev/null
+++ b/drivers/video/adf/adf.c
@@ -0,0 +1,1188 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ * adf_modeinfo_{set_name,set_vrefresh} modified from
+ * drivers/gpu/drm/drm_modes.c
+ * adf_format_validate_yuv modified from framebuffer_check in
+ * drivers/gpu/drm/drm_crtc.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/highmem.h>
+#include <linux/memblock.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <video/adf_format.h>
+
+#include "sw_sync.h"
+#include "sync.h"
+
+#include "adf.h"
+#include "adf_fops.h"
+#include "adf_sysfs.h"
+
+#define CREATE_TRACE_POINTS
+#include "adf_trace.h"
+
+#define ADF_SHORT_FENCE_TIMEOUT (1 * MSEC_PER_SEC)
+#define ADF_LONG_FENCE_TIMEOUT (10 * MSEC_PER_SEC)
+
+static DEFINE_IDR(adf_devices);
+
+static void adf_fence_wait(struct adf_device *dev, struct sync_fence *fence)
+{
+	/* sync_fence_wait() dumps debug information on timeout.  Experience
+	   has shown that if the pipeline gets stuck, a short timeout followed
+	   by a longer one provides useful information for debugging. */
+	int err = sync_fence_wait(fence, ADF_SHORT_FENCE_TIMEOUT);
+	if (err >= 0)
+		return;
+
+	if (err == -ETIME)
+		err = sync_fence_wait(fence, ADF_LONG_FENCE_TIMEOUT);
+
+	if (err < 0)
+		dev_warn(&dev->base.dev, "error waiting on fence: %d\n", err);
+}
+
+void adf_buffer_cleanup(struct adf_buffer *buf)
+{
+	size_t i;
+	for (i = 0; i < ARRAY_SIZE(buf->dma_bufs); i++)
+		if (buf->dma_bufs[i])
+			dma_buf_put(buf->dma_bufs[i]);
+
+	if (buf->acquire_fence)
+		sync_fence_put(buf->acquire_fence);
+}
+
+void adf_buffer_mapping_cleanup(struct adf_buffer_mapping *mapping,
+		struct adf_buffer *buf)
+{
+	/* calling adf_buffer_mapping_cleanup() is safe even if mapping is
+	   uninitialized or partially-initialized, as long as it was
+	   zeroed on allocation */
+	size_t i;
+	for (i = 0; i < ARRAY_SIZE(mapping->sg_tables); i++) {
+		if (mapping->sg_tables[i])
+			dma_buf_unmap_attachment(mapping->attachments[i],
+					mapping->sg_tables[i], DMA_TO_DEVICE);
+		if (mapping->attachments[i])
+			dma_buf_detach(buf->dma_bufs[i],
+					mapping->attachments[i]);
+	}
+}
+
+void adf_post_cleanup(struct adf_device *dev, struct adf_pending_post *post)
+{
+	size_t i;
+
+	if (post->state)
+		dev->ops->state_free(dev, post->state);
+
+	for (i = 0; i < post->config.n_bufs; i++) {
+		adf_buffer_mapping_cleanup(&post->config.mappings[i],
+				&post->config.bufs[i]);
+		adf_buffer_cleanup(&post->config.bufs[i]);
+	}
+
+	kfree(post->config.custom_data);
+	kfree(post->config.mappings);
+	kfree(post->config.bufs);
+	kfree(post);
+}
+
+static void adf_sw_advance_timeline(struct adf_device *dev)
+{
+#ifdef CONFIG_SW_SYNC
+	sw_sync_timeline_inc(dev->timeline, 1);
+#else
+	BUG();
+#endif
+}
+
+static void adf_post_work_func(struct kthread_work *work)
+{
+	struct adf_device *dev =
+			container_of(work, struct adf_device, post_work);
+	struct adf_pending_post *post, *next;
+	struct list_head saved_list;
+
+	mutex_lock(&dev->post_lock);
+	memcpy(&saved_list, &dev->post_list, sizeof(saved_list));
+	list_replace_init(&dev->post_list, &saved_list);
+	mutex_unlock(&dev->post_lock);
+
+	list_for_each_entry_safe(post, next, &saved_list, head) {
+		int i;
+
+		for (i = 0; i < post->config.n_bufs; i++) {
+			struct sync_fence *fence =
+					post->config.bufs[i].acquire_fence;
+			if (fence)
+				adf_fence_wait(dev, fence);
+		}
+
+		dev->ops->post(dev, &post->config, post->state);
+
+		if (dev->ops->advance_timeline)
+			dev->ops->advance_timeline(dev, &post->config,
+					post->state);
+		else
+			adf_sw_advance_timeline(dev);
+
+		list_del(&post->head);
+		if (dev->onscreen)
+			adf_post_cleanup(dev, dev->onscreen);
+		dev->onscreen = post;
+	}
+}
+
+void adf_attachment_free(struct adf_attachment_list *attachment)
+{
+	list_del(&attachment->head);
+	kfree(attachment);
+}
+
+struct adf_event_refcount *adf_obj_find_event_refcount(struct adf_obj *obj,
+		enum adf_event_type type)
+{
+	struct rb_root *root = &obj->event_refcount;
+	struct rb_node **new = &(root->rb_node);
+	struct rb_node *parent = NULL;
+	struct adf_event_refcount *refcount;
+
+	while (*new) {
+		refcount = container_of(*new, struct adf_event_refcount, node);
+		parent = *new;
+
+		if (refcount->type > type)
+			new = &(*new)->rb_left;
+		else if (refcount->type < type)
+			new = &(*new)->rb_right;
+		else
+			return refcount;
+	}
+
+	refcount = kzalloc(sizeof(*refcount), GFP_KERNEL);
+	if (!refcount)
+		return NULL;
+	refcount->type = type;
+
+	rb_link_node(&refcount->node, parent, new);
+	rb_insert_color(&refcount->node, root);
+	return refcount;
+}
+
+/**
+ * adf_event_get - increase the refcount for an event
+ *
+ * @obj: the object that produces the event
+ * @type: the event type
+ *
+ * ADF will call the object's set_event() op if needed.  ops are allowed
+ * to sleep, so adf_event_get() must NOT be called from an atomic context.
+ *
+ * Returns 0 if successful, or -%EINVAL if the object does not support the
+ * requested event type.
+ */
+int adf_event_get(struct adf_obj *obj, enum adf_event_type type)
+{
+	struct adf_event_refcount *refcount;
+	int old_refcount;
+	int ret;
+
+	ret = adf_obj_check_supports_event(obj, type);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&obj->event_lock);
+
+	refcount = adf_obj_find_event_refcount(obj, type);
+	if (!refcount) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	old_refcount = refcount->refcount++;
+
+	if (old_refcount == 0) {
+		obj->ops->set_event(obj, type, true);
+		trace_adf_event_enable(obj, type);
+	}
+
+done:
+	mutex_unlock(&obj->event_lock);
+	return ret;
+}
+EXPORT_SYMBOL(adf_event_get);
+
+/**
+ * adf_event_put - decrease the refcount for an event
+ *
+ * @obj: the object that produces the event
+ * @type: the event type
+ *
+ * ADF will call the object's set_event() op if needed.  ops are allowed
+ * to sleep, so adf_event_put() must NOT be called from an atomic context.
+ *
+ * Returns 0 if successful, -%EINVAL if the object does not support the
+ * requested event type, or -%EALREADY if the refcount is already 0.
+ */
+int adf_event_put(struct adf_obj *obj, enum adf_event_type type)
+{
+	struct adf_event_refcount *refcount;
+	int old_refcount;
+	int ret;
+
+	ret = adf_obj_check_supports_event(obj, type);
+	if (ret < 0)
+		return ret;
+
+
+	mutex_lock(&obj->event_lock);
+
+	refcount = adf_obj_find_event_refcount(obj, type);
+	if (!refcount) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	old_refcount = refcount->refcount--;
+
+	if (WARN_ON(old_refcount == 0)) {
+		refcount->refcount++;
+		ret = -EALREADY;
+	} else if (old_refcount == 1) {
+		obj->ops->set_event(obj, type, false);
+		trace_adf_event_disable(obj, type);
+	}
+
+done:
+	mutex_unlock(&obj->event_lock);
+	return ret;
+}
+EXPORT_SYMBOL(adf_event_put);
+
+/**
+ * adf_vsync_wait - wait for a vsync event on a display interface
+ *
+ * @intf: the display interface
+ * @timeout: timeout in jiffies (0 = wait indefinitely)
+ *
+ * adf_vsync_wait() may sleep, so it must NOT be called from an atomic context.
+ *
+ * This function returns -%ERESTARTSYS if it is interrupted by a signal.
+ * If @timeout == 0 then this function returns 0 on vsync. If @timeout > 0 then
+ * this function returns the number of remaining jiffies or -%ETIMEDOUT on
+ * timeout.
+ */
+int adf_vsync_wait(struct adf_interface *intf, long timeout)
+{
+	ktime_t timestamp;
+	int ret;
+	unsigned long flags;
+
+	read_lock_irqsave(&intf->vsync_lock, flags);
+	timestamp = intf->vsync_timestamp;
+	read_unlock_irqrestore(&intf->vsync_lock, flags);
+
+	adf_vsync_get(intf);
+	if (timeout) {
+		ret = wait_event_interruptible_timeout(intf->vsync_wait,
+				!ktime_equal(timestamp,
+						intf->vsync_timestamp),
+				msecs_to_jiffies(timeout));
+		if (ret == 0 && ktime_equal(timestamp, intf->vsync_timestamp))
+			ret = -ETIMEDOUT;
+	} else {
+		ret = wait_event_interruptible(intf->vsync_wait,
+				!ktime_equal(timestamp,
+						intf->vsync_timestamp));
+	}
+	adf_vsync_put(intf);
+
+	return ret;
+}
+EXPORT_SYMBOL(adf_vsync_wait);
+
+static void adf_event_queue(struct adf_obj *obj, struct adf_event *event)
+{
+	struct adf_file *file;
+	unsigned long flags;
+
+	trace_adf_event(obj, event->type);
+
+	spin_lock_irqsave(&obj->file_lock, flags);
+
+	list_for_each_entry(file, &obj->file_list, head)
+		if (test_bit(event->type, file->event_subscriptions))
+			adf_file_queue_event(file, event);
+
+	spin_unlock_irqrestore(&obj->file_lock, flags);
+}
+
+/**
+ * adf_event_notify - notify userspace of a driver-private event
+ *
+ * @obj: the ADF object that produced the event
+ * @event: the event
+ *
+ * adf_event_notify() may be called safely from an atomic context.  It will
+ * copy @event if needed, so @event may point to a variable on the stack.
+ *
+ * Drivers must NOT call adf_event_notify() for vsync and hotplug events.
+ * ADF provides adf_vsync_notify() and
+ * adf_hotplug_notify_{connected,disconnected}() for these events.
+ */
+int adf_event_notify(struct adf_obj *obj, struct adf_event *event)
+{
+	if (WARN_ON(event->type == ADF_EVENT_VSYNC ||
+			event->type == ADF_EVENT_HOTPLUG))
+		return -EINVAL;
+
+	adf_event_queue(obj, event);
+	return 0;
+}
+EXPORT_SYMBOL(adf_event_notify);
+
+/**
+ * adf_vsync_notify - notify ADF of a display interface's vsync event
+ *
+ * @intf: the display interface
+ * @timestamp: the time the vsync occurred
+ *
+ * adf_vsync_notify() may be called safely from an atomic context.
+ */
+void adf_vsync_notify(struct adf_interface *intf, ktime_t timestamp)
+{
+	unsigned long flags;
+	struct adf_vsync_event event;
+
+	write_lock_irqsave(&intf->vsync_lock, flags);
+	intf->vsync_timestamp = timestamp;
+	write_unlock_irqrestore(&intf->vsync_lock, flags);
+
+	wake_up_interruptible_all(&intf->vsync_wait);
+
+	event.base.type = ADF_EVENT_VSYNC;
+	event.base.length = sizeof(event);
+	event.timestamp = ktime_to_ns(timestamp);
+	adf_event_queue(&intf->base, &event.base);
+}
+EXPORT_SYMBOL(adf_vsync_notify);
+
+void adf_hotplug_notify(struct adf_interface *intf, bool connected,
+		struct drm_mode_modeinfo *modelist, size_t n_modes)
+{
+	unsigned long flags;
+	struct adf_hotplug_event event;
+	struct drm_mode_modeinfo *old_modelist;
+
+	write_lock_irqsave(&intf->hotplug_modelist_lock, flags);
+	old_modelist = intf->modelist;
+	intf->hotplug_detect = connected;
+	intf->modelist = modelist;
+	intf->n_modes = n_modes;
+	write_unlock_irqrestore(&intf->hotplug_modelist_lock, flags);
+
+	kfree(old_modelist);
+
+	event.base.length = sizeof(event);
+	event.base.type = ADF_EVENT_HOTPLUG;
+	event.connected = connected;
+	adf_event_queue(&intf->base, &event.base);
+}
+
+/**
+ * adf_hotplug_notify_connected - notify ADF of a display interface being
+ * connected to a display
+ *
+ * @intf: the display interface
+ * @modelist: hardware modes supported by display
+ * @n_modes: length of modelist
+ *
+ * @modelist is copied as needed, so it may point to a variable on the stack.
+ *
+ * adf_hotplug_notify_connected() may NOT be called safely from an atomic
+ * context.
+ *
+ * Returns 0 on success or error code (<0) on error.
+ */
+int adf_hotplug_notify_connected(struct adf_interface *intf,
+		struct drm_mode_modeinfo *modelist, size_t n_modes)
+{
+	struct drm_mode_modeinfo *modelist_copy;
+
+	if (n_modes > ADF_MAX_MODES)
+		return -ENOMEM;
+
+	modelist_copy = kzalloc(sizeof(modelist_copy[0]) * n_modes,
+			GFP_KERNEL);
+	if (!modelist_copy)
+		return -ENOMEM;
+	memcpy(modelist_copy, modelist, sizeof(modelist_copy[0]) * n_modes);
+
+	adf_hotplug_notify(intf, true, modelist_copy, n_modes);
+	return 0;
+}
+EXPORT_SYMBOL(adf_hotplug_notify_connected);
+
+/**
+ * adf_hotplug_notify_disconnected - notify ADF of a display interface being
+ * disconnected from a display
+ *
+ * @intf: the display interface
+ *
+ * adf_hotplug_notify_disconnected() may be called safely from an atomic
+ * context.
+ */
+void adf_hotplug_notify_disconnected(struct adf_interface *intf)
+{
+	adf_hotplug_notify(intf, false, NULL, 0);
+}
+EXPORT_SYMBOL(adf_hotplug_notify_disconnected);
+
+static int adf_obj_init(struct adf_obj *obj, enum adf_obj_type type,
+		struct idr *idr, struct adf_device *parent,
+		const struct adf_obj_ops *ops, const char *fmt, va_list args)
+{
+	int ret;
+
+	if (ops && ops->supports_event && !ops->set_event) {
+		pr_err("%s: %s implements supports_event but not set_event\n",
+				__func__, adf_obj_type_str(type));
+		return -EINVAL;
+	}
+
+	ret = idr_alloc(idr, obj, 0, 0, GFP_KERNEL);
+	if (ret < 0) {
+		pr_err("%s: allocating object id failed: %d\n", __func__, ret);
+		return ret;
+	}
+	obj->id = ret;
+
+	vscnprintf(obj->name, sizeof(obj->name), fmt, args);
+
+	obj->type = type;
+	obj->ops = ops;
+	obj->parent = parent;
+	mutex_init(&obj->event_lock);
+	obj->event_refcount = RB_ROOT;
+	spin_lock_init(&obj->file_lock);
+	INIT_LIST_HEAD(&obj->file_list);
+	return 0;
+}
+
+static void adf_obj_destroy(struct adf_obj *obj, struct idr *idr)
+{
+	struct rb_node *node = rb_first(&obj->event_refcount);
+
+	while (node) {
+		struct adf_event_refcount *refcount =
+				container_of(node, struct adf_event_refcount,
+						node);
+		rb_erase(&refcount->node, &obj->event_refcount);
+		kfree(refcount);
+		node = rb_first(&obj->event_refcount);
+	}
+
+	mutex_destroy(&obj->event_lock);
+	idr_remove(idr, obj->id);
+}
+
+/**
+ * adf_device_init - initialize ADF-internal data for a display device
+ * and create sysfs entries
+ *
+ * @dev: the display device
+ * @parent: the device's parent device
+ * @ops: the device's associated ops
+ * @fmt: formatting string for the display device's name
+ *
+ * @fmt specifies the device's sysfs filename and the name returned to
+ * userspace through the %ADF_GET_DEVICE_DATA ioctl.
+ *
+ * Returns 0 on success or error code (<0) on failure.
+ */
+int adf_device_init(struct adf_device *dev, struct device *parent,
+		const struct adf_device_ops *ops, const char *fmt, ...)
+{
+	int ret;
+	va_list args;
+
+	if (!ops->validate || !ops->post) {
+		pr_err("%s: device must implement validate and post\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	if (!ops->complete_fence && !ops->advance_timeline) {
+		if (!IS_ENABLED(CONFIG_SW_SYNC)) {
+			pr_err("%s: device requires sw_sync but it is not enabled in the kernel\n",
+					__func__);
+			return -EINVAL;
+		}
+	} else if (!(ops->complete_fence && ops->advance_timeline)) {
+		pr_err("%s: device must implement both complete_fence and advance_timeline, or implement neither\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	memset(dev, 0, sizeof(*dev));
+
+	va_start(args, fmt);
+	ret = adf_obj_init(&dev->base, ADF_OBJ_DEVICE, &adf_devices, dev,
+			&ops->base, fmt, args);
+	va_end(args);
+	if (ret < 0)
+		return ret;
+
+	dev->dev = parent;
+	dev->ops = ops;
+	idr_init(&dev->overlay_engines);
+	idr_init(&dev->interfaces);
+	mutex_init(&dev->client_lock);
+	INIT_LIST_HEAD(&dev->post_list);
+	mutex_init(&dev->post_lock);
+	init_kthread_worker(&dev->post_worker);
+	INIT_LIST_HEAD(&dev->attached);
+	INIT_LIST_HEAD(&dev->attach_allowed);
+
+	dev->post_thread = kthread_run(kthread_worker_fn,
+			&dev->post_worker, dev->base.name);
+	if (IS_ERR(dev->post_thread)) {
+		ret = PTR_ERR(dev->post_thread);
+		dev->post_thread = NULL;
+
+		pr_err("%s: failed to run config posting thread: %d\n",
+				__func__, ret);
+		goto err;
+	}
+	init_kthread_work(&dev->post_work, adf_post_work_func);
+
+	ret = adf_device_sysfs_init(dev);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	adf_device_destroy(dev);
+	return ret;
+}
+EXPORT_SYMBOL(adf_device_init);
+
+/**
+ * adf_device_destroy - clean up ADF-internal data for a display device
+ *
+ * @dev: the display device
+ */
+void adf_device_destroy(struct adf_device *dev)
+{
+	struct adf_attachment_list *entry, *next;
+
+	idr_destroy(&dev->interfaces);
+	idr_destroy(&dev->overlay_engines);
+
+	if (dev->post_thread) {
+		flush_kthread_worker(&dev->post_worker);
+		kthread_stop(dev->post_thread);
+	}
+
+	if (dev->onscreen)
+		adf_post_cleanup(dev, dev->onscreen);
+	adf_device_sysfs_destroy(dev);
+	list_for_each_entry_safe(entry, next, &dev->attach_allowed, head) {
+		adf_attachment_free(entry);
+	}
+	list_for_each_entry_safe(entry, next, &dev->attached, head) {
+		adf_attachment_free(entry);
+	}
+	mutex_destroy(&dev->post_lock);
+	mutex_destroy(&dev->client_lock);
+
+	if (dev->timeline)
+		sync_timeline_destroy(&dev->timeline->obj);
+
+	adf_obj_destroy(&dev->base, &adf_devices);
+}
+EXPORT_SYMBOL(adf_device_destroy);
+
+/**
+ * adf_interface_init - initialize ADF-internal data for a display interface
+ * and create sysfs entries
+ *
+ * @intf: the display interface
+ * @dev: the interface's "parent" display device
+ * @type: interface type (see enum @adf_interface_type)
+ * @idx: which interface of type @type;
+ *	e.g. interface DSI.1 -> @type=%ADF_INTF_TYPE_DSI, @idx=1
+ * @flags: informational flags (bitmask of %ADF_INTF_FLAG_* values)
+ * @ops: the interface's associated ops
+ * @fmt: formatting string for the display interface's name
+ *
+ * @dev must have previously been initialized with adf_device_init().
+ *
+ * @fmt affects the name returned to userspace through the
+ * %ADF_GET_INTERFACE_DATA ioctl.  It does not affect the sysfs filename,
+ * which is derived from @dev's name.
+ *
+ * Returns 0 on success or error code (<0) on failure.
+ */
+int adf_interface_init(struct adf_interface *intf, struct adf_device *dev,
+		enum adf_interface_type type, u32 idx, u32 flags,
+		const struct adf_interface_ops *ops, const char *fmt, ...)
+{
+	int ret;
+	va_list args;
+	const u32 allowed_flags = ADF_INTF_FLAG_PRIMARY |
+			ADF_INTF_FLAG_EXTERNAL;
+
+	if (dev->n_interfaces == ADF_MAX_INTERFACES) {
+		pr_err("%s: parent device %s has too many interfaces\n",
+				__func__, dev->base.name);
+		return -ENOMEM;
+	}
+
+	if (type >= ADF_INTF_MEMORY && type <= ADF_INTF_TYPE_DEVICE_CUSTOM) {
+		pr_err("%s: invalid interface type %u\n", __func__, type);
+		return -EINVAL;
+	}
+
+	if (flags & ~allowed_flags) {
+		pr_err("%s: invalid interface flags 0x%X\n", __func__,
+				flags & ~allowed_flags);
+		return -EINVAL;
+	}
+
+	memset(intf, 0, sizeof(*intf));
+
+	va_start(args, fmt);
+	ret = adf_obj_init(&intf->base, ADF_OBJ_INTERFACE, &dev->interfaces,
+			dev, ops ? &ops->base : NULL, fmt, args);
+	va_end(args);
+	if (ret < 0)
+		return ret;
+
+	intf->type = type;
+	intf->idx = idx;
+	intf->flags = flags;
+	intf->ops = ops;
+	intf->dpms_state = DRM_MODE_DPMS_OFF;
+	init_waitqueue_head(&intf->vsync_wait);
+	rwlock_init(&intf->vsync_lock);
+	rwlock_init(&intf->hotplug_modelist_lock);
+
+	ret = adf_interface_sysfs_init(intf);
+	if (ret < 0)
+		goto err;
+	dev->n_interfaces++;
+
+	return 0;
+
+err:
+	adf_obj_destroy(&intf->base, &dev->interfaces);
+	return ret;
+}
+EXPORT_SYMBOL(adf_interface_init);
+
+/**
+ * adf_interface_destroy - clean up ADF-internal data for a display interface
+ *
+ * @intf: the display interface
+ */
+void adf_interface_destroy(struct adf_interface *intf)
+{
+	struct adf_device *dev = adf_interface_parent(intf);
+	struct adf_attachment_list *entry, *next;
+
+	mutex_lock(&dev->client_lock);
+	list_for_each_entry_safe(entry, next, &dev->attach_allowed, head) {
+		if (entry->attachment.interface == intf) {
+			adf_attachment_free(entry);
+			dev->n_attach_allowed--;
+		}
+	}
+	list_for_each_entry_safe(entry, next, &dev->attached, head) {
+		if (entry->attachment.interface == intf) {
+			adf_device_detach_op(dev,
+					entry->attachment.overlay_engine, intf);
+			adf_attachment_free(entry);
+			dev->n_attached--;
+		}
+	}
+	kfree(intf->modelist);
+	adf_interface_sysfs_destroy(intf);
+	adf_obj_destroy(&intf->base, &dev->interfaces);
+	dev->n_interfaces--;
+	mutex_unlock(&dev->client_lock);
+}
+EXPORT_SYMBOL(adf_interface_destroy);
+
+static bool adf_overlay_engine_has_custom_formats(
+		const struct adf_overlay_engine_ops *ops)
+{
+	size_t i;
+	for (i = 0; i < ops->n_supported_formats; i++)
+		if (!adf_format_is_standard(ops->supported_formats[i]))
+			return true;
+	return false;
+}
+
+/**
+ * adf_overlay_engine_init - initialize ADF-internal data for an
+ * overlay engine and create sysfs entries
+ *
+ * @eng: the overlay engine
+ * @dev: the overlay engine's "parent" display device
+ * @ops: the overlay engine's associated ops
+ * @fmt: formatting string for the overlay engine's name
+ *
+ * @dev must have previously been initialized with adf_device_init().
+ *
+ * @fmt affects the name returned to userspace through the
+ * %ADF_GET_OVERLAY_ENGINE_DATA ioctl.  It does not affect the sysfs filename,
+ * which is derived from @dev's name.
+ *
+ * Returns 0 on success or error code (<0) on failure.
+ */
+int adf_overlay_engine_init(struct adf_overlay_engine *eng,
+		struct adf_device *dev,
+		const struct adf_overlay_engine_ops *ops, const char *fmt, ...)
+{
+	int ret;
+	va_list args;
+
+	if (!ops->supported_formats) {
+		pr_err("%s: overlay engine must support at least one format\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	if (ops->n_supported_formats > ADF_MAX_SUPPORTED_FORMATS) {
+		pr_err("%s: overlay engine supports too many formats\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	if (adf_overlay_engine_has_custom_formats(ops) &&
+			!dev->ops->validate_custom_format) {
+		pr_err("%s: overlay engine has custom formats but parent device %s does not implement validate_custom_format\n",
+				__func__, dev->base.name);
+		return -EINVAL;
+	}
+
+	memset(eng, 0, sizeof(*eng));
+
+	va_start(args, fmt);
+	ret = adf_obj_init(&eng->base, ADF_OBJ_OVERLAY_ENGINE,
+			&dev->overlay_engines, dev, &ops->base, fmt, args);
+	va_end(args);
+	if (ret < 0)
+		return ret;
+
+	eng->ops = ops;
+
+	ret = adf_overlay_engine_sysfs_init(eng);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	adf_obj_destroy(&eng->base, &dev->overlay_engines);
+	return ret;
+}
+EXPORT_SYMBOL(adf_overlay_engine_init);
+
+/**
+ * adf_interface_destroy - clean up ADF-internal data for an overlay engine
+ *
+ * @eng: the overlay engine
+ */
+void adf_overlay_engine_destroy(struct adf_overlay_engine *eng)
+{
+	struct adf_device *dev = adf_overlay_engine_parent(eng);
+	struct adf_attachment_list *entry, *next;
+
+	mutex_lock(&dev->client_lock);
+	list_for_each_entry_safe(entry, next, &dev->attach_allowed, head) {
+		if (entry->attachment.overlay_engine == eng) {
+			adf_attachment_free(entry);
+			dev->n_attach_allowed--;
+		}
+	}
+	list_for_each_entry_safe(entry, next, &dev->attached, head) {
+		if (entry->attachment.overlay_engine == eng) {
+			adf_device_detach_op(dev, eng,
+					entry->attachment.interface);
+			adf_attachment_free(entry);
+			dev->n_attached--;
+		}
+	}
+	adf_overlay_engine_sysfs_destroy(eng);
+	adf_obj_destroy(&eng->base, &dev->overlay_engines);
+	mutex_unlock(&dev->client_lock);
+}
+EXPORT_SYMBOL(adf_overlay_engine_destroy);
+
+struct adf_attachment_list *adf_attachment_find(struct list_head *list,
+		struct adf_overlay_engine *eng, struct adf_interface *intf)
+{
+	struct adf_attachment_list *entry;
+	list_for_each_entry(entry, list, head) {
+		if (entry->attachment.interface == intf &&
+				entry->attachment.overlay_engine == eng)
+			return entry;
+	}
+	return NULL;
+}
+
+int adf_attachment_validate(struct adf_device *dev,
+		struct adf_overlay_engine *eng, struct adf_interface *intf)
+{
+	struct adf_device *intf_dev = adf_interface_parent(intf);
+	struct adf_device *eng_dev = adf_overlay_engine_parent(eng);
+
+	if (intf_dev != dev) {
+		dev_err(&dev->base.dev, "can't attach interface %s belonging to device %s\n",
+				intf->base.name, intf_dev->base.name);
+		return -EINVAL;
+	}
+
+	if (eng_dev != dev) {
+		dev_err(&dev->base.dev, "can't attach overlay engine %s belonging to device %s\n",
+				eng->base.name, eng_dev->base.name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * adf_attachment_allow - add a new entry to the list of allowed
+ * attachments
+ *
+ * @dev: the parent device
+ * @eng: the overlay engine
+ * @intf: the interface
+ *
+ * adf_attachment_allow() indicates that the underlying display hardware allows
+ * @intf to scan out @eng's output.  It is intended to be called at
+ * driver initialization for each supported overlay engine + interface pair.
+ *
+ * Returns 0 on success, -%EALREADY if the entry already exists, or -errno on
+ * any other failure.
+ */
+int adf_attachment_allow(struct adf_device *dev,
+		struct adf_overlay_engine *eng, struct adf_interface *intf)
+{
+	int ret;
+	struct adf_attachment_list *entry = NULL;
+
+	ret = adf_attachment_validate(dev, eng, intf);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&dev->client_lock);
+
+	if (dev->n_attach_allowed == ADF_MAX_ATTACHMENTS) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (adf_attachment_find(&dev->attach_allowed, eng, intf)) {
+		ret = -EALREADY;
+		goto done;
+	}
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	entry->attachment.interface = intf;
+	entry->attachment.overlay_engine = eng;
+	list_add_tail(&entry->head, &dev->attach_allowed);
+	dev->n_attach_allowed++;
+
+done:
+	mutex_unlock(&dev->client_lock);
+	if (ret < 0)
+		kfree(entry);
+
+	return ret;
+}
+EXPORT_SYMBOL(adf_attachment_allow);
+
+/**
+ * adf_obj_type_str - string representation of an adf_obj_type
+ *
+ * @type: the object type
+ */
+const char *adf_obj_type_str(enum adf_obj_type type)
+{
+	switch (type) {
+	case ADF_OBJ_OVERLAY_ENGINE:
+		return "overlay engine";
+
+	case ADF_OBJ_INTERFACE:
+		return "interface";
+
+	case ADF_OBJ_DEVICE:
+		return "device";
+
+	default:
+		return "unknown";
+	}
+}
+EXPORT_SYMBOL(adf_obj_type_str);
+
+/**
+ * adf_interface_type_str - string representation of an adf_interface's type
+ *
+ * @intf: the interface
+ */
+const char *adf_interface_type_str(struct adf_interface *intf)
+{
+	switch (intf->type) {
+	case ADF_INTF_DSI:
+		return "DSI";
+
+	case ADF_INTF_eDP:
+		return "eDP";
+
+	case ADF_INTF_DPI:
+		return "DPI";
+
+	case ADF_INTF_VGA:
+		return "VGA";
+
+	case ADF_INTF_DVI:
+		return "DVI";
+
+	case ADF_INTF_HDMI:
+		return "HDMI";
+
+	case ADF_INTF_MEMORY:
+		return "memory";
+
+	default:
+		if (intf->type >= ADF_INTF_TYPE_DEVICE_CUSTOM) {
+			if (intf->ops && intf->ops->type_str)
+				return intf->ops->type_str(intf);
+			return "custom";
+		}
+		return "unknown";
+	}
+}
+EXPORT_SYMBOL(adf_interface_type_str);
+
+/**
+ * adf_event_type_str - string representation of an adf_event_type
+ *
+ * @obj: ADF object that produced the event
+ * @type: event type
+ */
+const char *adf_event_type_str(struct adf_obj *obj, enum adf_event_type type)
+{
+	switch (type) {
+	case ADF_EVENT_VSYNC:
+		return "vsync";
+
+	case ADF_EVENT_HOTPLUG:
+		return "hotplug";
+
+	default:
+		if (type >= ADF_EVENT_DEVICE_CUSTOM) {
+			if (obj->ops && obj->ops->event_type_str)
+				return obj->ops->event_type_str(obj, type);
+			return "custom";
+		}
+		return "unknown";
+	}
+}
+EXPORT_SYMBOL(adf_event_type_str);
+
+/**
+ * adf_format_str - string representation of an ADF/DRM fourcc format
+ *
+ * @format: format fourcc
+ * @buf: target buffer for the format's string representation
+ */
+void adf_format_str(u32 format, char buf[ADF_FORMAT_STR_SIZE])
+{
+	buf[0] = format & 0xFF;
+	buf[1] = (format >> 8) & 0xFF;
+	buf[2] = (format >> 16) & 0xFF;
+	buf[3] = (format >> 24) & 0xFF;
+	buf[4] = '\0';
+}
+EXPORT_SYMBOL(adf_format_str);
+
+/**
+ * adf_format_validate_yuv - validate the number and size of planes in buffers
+ * with a custom YUV format.
+ *
+ * @dev: ADF device performing the validation
+ * @buf: buffer to validate
+ * @num_planes: expected number of planes
+ * @hsub: expected horizontal chroma subsampling factor, in pixels
+ * @vsub: expected vertical chroma subsampling factor, in pixels
+ * @cpp: expected bytes per pixel for each plane (length @num_planes)
+ *
+ * adf_format_validate_yuv() is intended to be called as a helper from @dev's
+ * validate_custom_format() op.
+ *
+ * Returns 0 if @buf has the expected number of planes and each plane
+ * has sufficient size, or -EINVAL otherwise.
+ */
+int adf_format_validate_yuv(struct adf_device *dev, struct adf_buffer *buf,
+		u8 num_planes, u8 hsub, u8 vsub, u8 cpp[])
+{
+	u8 i;
+
+	if (num_planes != buf->n_planes) {
+		char format_str[ADF_FORMAT_STR_SIZE];
+		adf_format_str(buf->format, format_str);
+		dev_err(&dev->base.dev, "%u planes expected for format %s but %u planes provided\n",
+				num_planes, format_str, buf->n_planes);
+		return -EINVAL;
+	}
+
+	if (buf->w == 0 || buf->w % hsub) {
+		dev_err(&dev->base.dev, "bad buffer width %u\n", buf->w);
+		return -EINVAL;
+	}
+
+	if (buf->h == 0 || buf->h % vsub) {
+		dev_err(&dev->base.dev, "bad buffer height %u\n", buf->h);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num_planes; i++) {
+		u32 width = buf->w / (i != 0 ? hsub : 1);
+		u32 height = buf->h / (i != 0 ? vsub : 1);
+		u8 cpp = adf_format_plane_cpp(buf->format, i);
+		u32 last_line_size;
+
+		if (buf->pitch[i] < (u64) width * cpp) {
+			dev_err(&dev->base.dev, "plane %u pitch is shorter than buffer width (pitch = %u, width = %u, bpp = %u)\n",
+					i, buf->pitch[i], width, cpp * 8);
+			return -EINVAL;
+		}
+
+		switch (dev->ops->quirks.buffer_padding) {
+		case ADF_BUFFER_PADDED_TO_PITCH:
+			last_line_size = buf->pitch[i];
+			break;
+
+		case ADF_BUFFER_UNPADDED:
+			last_line_size = width * cpp;
+			break;
+
+		default:
+			BUG();
+		}
+
+		if ((u64) (height - 1) * buf->pitch[i] + last_line_size +
+				buf->offset[i] > buf->dma_bufs[i]->size) {
+			dev_err(&dev->base.dev, "plane %u buffer too small (height = %u, pitch = %u, offset = %u, size = %zu)\n",
+					i, height, buf->pitch[i],
+					buf->offset[i], buf->dma_bufs[i]->size);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(adf_format_validate_yuv);
+
+/**
+ * adf_modeinfo_set_name - sets the name of a mode from its display resolution
+ *
+ * @mode: mode
+ *
+ * adf_modeinfo_set_name() fills in @mode->name in the format
+ * "[hdisplay]x[vdisplay](i)".  It is intended to help drivers create
+ * ADF/DRM-style modelists from other mode formats.
+ */
+void adf_modeinfo_set_name(struct drm_mode_modeinfo *mode)
+{
+	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
+
+	snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s",
+		 mode->hdisplay, mode->vdisplay,
+		 interlaced ? "i" : "");
+}
+EXPORT_SYMBOL(adf_modeinfo_set_name);
+
+/**
+ * adf_modeinfo_set_vrefresh - sets the vrefresh of a mode from its other
+ * timing data
+ *
+ * @mode: mode
+ *
+ * adf_modeinfo_set_vrefresh() calculates @mode->vrefresh from
+ * @mode->{h,v}display and @mode->flags.  It is intended to help drivers
+ * create ADF/DRM-style modelists from other mode formats.
+ */
+void adf_modeinfo_set_vrefresh(struct drm_mode_modeinfo *mode)
+{
+	int refresh = 0;
+	unsigned int calc_val;
+
+	if (mode->vrefresh > 0)
+		return;
+
+	if (mode->htotal <= 0 || mode->vtotal <= 0)
+		return;
+
+	/* work out vrefresh the value will be x1000 */
+	calc_val = (mode->clock * 1000);
+	calc_val /= mode->htotal;
+	refresh = (calc_val + mode->vtotal / 2) / mode->vtotal;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		refresh *= 2;
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		refresh /= 2;
+	if (mode->vscan > 1)
+		refresh /= mode->vscan;
+
+	mode->vrefresh = refresh;
+}
+EXPORT_SYMBOL(adf_modeinfo_set_vrefresh);
+
+static int __init adf_init(void)
+{
+	int err;
+
+	err = adf_sysfs_init();
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static void __exit adf_exit(void)
+{
+	adf_sysfs_destroy();
+}
+
+module_init(adf_init);
+module_exit(adf_exit);
diff --git a/drivers/video/adf/adf.h b/drivers/video/adf/adf.h
new file mode 100644
index 0000000..3bcf1fa
--- /dev/null
+++ b/drivers/video/adf/adf.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __VIDEO_ADF_ADF_H
+#define __VIDEO_ADF_ADF_H
+
+#include <linux/idr.h>
+#include <linux/list.h>
+#include <video/adf.h>
+#include "sync.h"
+
+struct adf_event_refcount {
+	struct rb_node node;
+	enum adf_event_type type;
+	int refcount;
+};
+
+void adf_buffer_cleanup(struct adf_buffer *buf);
+void adf_buffer_mapping_cleanup(struct adf_buffer_mapping *mapping,
+		struct adf_buffer *buf);
+void adf_post_cleanup(struct adf_device *dev, struct adf_pending_post *post);
+
+struct adf_attachment_list *adf_attachment_find(struct list_head *list,
+		struct adf_overlay_engine *eng, struct adf_interface *intf);
+int adf_attachment_validate(struct adf_device *dev,
+		struct adf_overlay_engine *eng, struct adf_interface *intf);
+void adf_attachment_free(struct adf_attachment_list *attachment);
+
+struct adf_event_refcount *adf_obj_find_event_refcount(struct adf_obj *obj,
+		enum adf_event_type type);
+
+static inline int adf_obj_check_supports_event(struct adf_obj *obj,
+		enum adf_event_type type)
+{
+	if (!obj->ops || !obj->ops->supports_event)
+		return -EOPNOTSUPP;
+	if (!obj->ops->supports_event(obj, type))
+		return -EINVAL;
+	return 0;
+}
+
+static inline int adf_device_attach_op(struct adf_device *dev,
+		struct adf_overlay_engine *eng, struct adf_interface *intf)
+{
+	if (!dev->ops->attach)
+		return 0;
+
+	return dev->ops->attach(dev, eng, intf);
+}
+
+static inline int adf_device_detach_op(struct adf_device *dev,
+		struct adf_overlay_engine *eng, struct adf_interface *intf)
+{
+	if (!dev->ops->detach)
+		return 0;
+
+	return dev->ops->detach(dev, eng, intf);
+}
+
+#endif /* __VIDEO_ADF_ADF_H */
diff --git a/drivers/video/adf/adf_client.c b/drivers/video/adf/adf_client.c
new file mode 100644
index 0000000..8061d8e
--- /dev/null
+++ b/drivers/video/adf/adf_client.c
@@ -0,0 +1,811 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include "sw_sync.h"
+
+#include <video/adf.h>
+#include <video/adf_client.h>
+#include <video/adf_format.h>
+
+#include "adf.h"
+
+static inline bool vsync_active(u8 state)
+{
+	return state == DRM_MODE_DPMS_ON || state == DRM_MODE_DPMS_STANDBY;
+}
+
+/**
+ * adf_interface_blank - set interface's DPMS state
+ *
+ * @intf: the interface
+ * @state: one of %DRM_MODE_DPMS_*
+ *
+ * Returns 0 on success or -errno on failure.
+ */
+int adf_interface_blank(struct adf_interface *intf, u8 state)
+{
+	struct adf_device *dev = adf_interface_parent(intf);
+	u8 prev_state;
+	bool disable_vsync;
+	bool enable_vsync;
+	int ret = 0;
+	struct adf_event_refcount *vsync_refcount;
+
+	if (!intf->ops || !intf->ops->blank)
+		return -EOPNOTSUPP;
+
+	if (state > DRM_MODE_DPMS_OFF)
+		return -EINVAL;
+
+	mutex_lock(&dev->client_lock);
+	if (state != DRM_MODE_DPMS_ON)
+		flush_kthread_worker(&dev->post_worker);
+	mutex_lock(&intf->base.event_lock);
+
+	vsync_refcount = adf_obj_find_event_refcount(&intf->base,
+			ADF_EVENT_VSYNC);
+	if (!vsync_refcount) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	prev_state = intf->dpms_state;
+	if (prev_state == state) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	disable_vsync = vsync_active(prev_state) &&
+			!vsync_active(state) &&
+			vsync_refcount->refcount;
+	enable_vsync = !vsync_active(prev_state) &&
+			vsync_active(state) &&
+			vsync_refcount->refcount;
+
+	if (disable_vsync)
+		intf->base.ops->set_event(&intf->base, ADF_EVENT_VSYNC,
+				false);
+
+	ret = intf->ops->blank(intf, state);
+	if (ret < 0) {
+		if (disable_vsync)
+			intf->base.ops->set_event(&intf->base, ADF_EVENT_VSYNC,
+					true);
+		goto done;
+	}
+
+	if (enable_vsync)
+		intf->base.ops->set_event(&intf->base, ADF_EVENT_VSYNC,
+				true);
+
+	intf->dpms_state = state;
+done:
+	mutex_unlock(&intf->base.event_lock);
+	mutex_unlock(&dev->client_lock);
+	return ret;
+}
+EXPORT_SYMBOL(adf_interface_blank);
+
+/**
+ * adf_interface_blank - get interface's current DPMS state
+ *
+ * @intf: the interface
+ *
+ * Returns one of %DRM_MODE_DPMS_*.
+ */
+u8 adf_interface_dpms_state(struct adf_interface *intf)
+{
+	struct adf_device *dev = adf_interface_parent(intf);
+	u8 dpms_state;
+
+	mutex_lock(&dev->client_lock);
+	dpms_state = intf->dpms_state;
+	mutex_unlock(&dev->client_lock);
+
+	return dpms_state;
+}
+EXPORT_SYMBOL(adf_interface_dpms_state);
+
+/**
+ * adf_interface_current_mode - get interface's current display mode
+ *
+ * @intf: the interface
+ * @mode: returns the current mode
+ */
+void adf_interface_current_mode(struct adf_interface *intf,
+		struct drm_mode_modeinfo *mode)
+{
+	struct adf_device *dev = adf_interface_parent(intf);
+
+	mutex_lock(&dev->client_lock);
+	memcpy(mode, &intf->current_mode, sizeof(*mode));
+	mutex_unlock(&dev->client_lock);
+}
+EXPORT_SYMBOL(adf_interface_current_mode);
+
+/**
+ * adf_interface_modelist - get interface's modelist
+ *
+ * @intf: the interface
+ * @modelist: storage for the modelist (optional)
+ * @n_modes: length of @modelist
+ *
+ * If @modelist is not NULL, adf_interface_modelist() will copy up to @n_modes
+ * modelist entries into @modelist.
+ *
+ * Returns the length of the modelist.
+ */
+size_t adf_interface_modelist(struct adf_interface *intf,
+		struct drm_mode_modeinfo *modelist, size_t n_modes)
+{
+	unsigned long flags;
+	size_t retval;
+
+	read_lock_irqsave(&intf->hotplug_modelist_lock, flags);
+	if (modelist)
+		memcpy(modelist, intf->modelist, sizeof(modelist[0]) *
+				min(n_modes, intf->n_modes));
+	retval = intf->n_modes;
+	read_unlock_irqrestore(&intf->hotplug_modelist_lock, flags);
+
+	return retval;
+}
+EXPORT_SYMBOL(adf_interface_modelist);
+
+/**
+ * adf_interface_set_mode - set interface's display mode
+ *
+ * @intf: the interface
+ * @mode: the new mode
+ *
+ * Returns 0 on success or -errno on failure.
+ */
+int adf_interface_set_mode(struct adf_interface *intf,
+		struct drm_mode_modeinfo *mode)
+{
+	struct adf_device *dev = adf_interface_parent(intf);
+	int ret = 0;
+
+	if (!intf->ops || !intf->ops->modeset)
+		return -EOPNOTSUPP;
+
+	mutex_lock(&dev->client_lock);
+	flush_kthread_worker(&dev->post_worker);
+
+	ret = intf->ops->modeset(intf, mode);
+	if (ret < 0)
+		goto done;
+
+	memcpy(&intf->current_mode, mode, sizeof(*mode));
+done:
+	mutex_unlock(&dev->client_lock);
+	return ret;
+}
+EXPORT_SYMBOL(adf_interface_set_mode);
+
+/**
+ * adf_interface_screen_size - get size of screen connected to interface
+ *
+ * @intf: the interface
+ * @width_mm: returns the screen width in mm
+ * @height_mm: returns the screen width in mm
+ *
+ * Returns 0 on success or -errno on failure.
+ */
+int adf_interface_get_screen_size(struct adf_interface *intf, u16 *width_mm,
+		u16 *height_mm)
+{
+	struct adf_device *dev = adf_interface_parent(intf);
+	int ret;
+
+	if (!intf->ops || !intf->ops->screen_size)
+		return -EOPNOTSUPP;
+
+	mutex_lock(&dev->client_lock);
+	ret = intf->ops->screen_size(intf, width_mm, height_mm);
+	mutex_unlock(&dev->client_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(adf_interface_get_screen_size);
+
+/**
+ * adf_overlay_engine_supports_format - returns whether a format is in an
+ * overlay engine's supported list
+ *
+ * @eng: the overlay engine
+ * @format: format fourcc
+ */
+bool adf_overlay_engine_supports_format(struct adf_overlay_engine *eng,
+		u32 format)
+{
+	size_t i;
+	for (i = 0; i < eng->ops->n_supported_formats; i++)
+		if (format == eng->ops->supported_formats[i])
+			return true;
+
+	return false;
+}
+EXPORT_SYMBOL(adf_overlay_engine_supports_format);
+
+static int adf_buffer_validate(struct adf_buffer *buf)
+{
+	struct adf_overlay_engine *eng = buf->overlay_engine;
+	struct device *dev = &eng->base.dev;
+	struct adf_device *parent = adf_overlay_engine_parent(eng);
+	u8 hsub, vsub, num_planes, cpp[ADF_MAX_PLANES], i;
+
+	if (!adf_overlay_engine_supports_format(eng, buf->format)) {
+		char format_str[ADF_FORMAT_STR_SIZE];
+		adf_format_str(buf->format, format_str);
+		dev_err(dev, "unsupported format %s\n", format_str);
+		return -EINVAL;
+	}
+
+	if (!adf_format_is_standard(buf->format))
+		return parent->ops->validate_custom_format(parent, buf);
+
+	hsub = adf_format_horz_chroma_subsampling(buf->format);
+	vsub = adf_format_vert_chroma_subsampling(buf->format);
+	num_planes = adf_format_num_planes(buf->format);
+	for (i = 0; i < num_planes; i++)
+		cpp[i] = adf_format_plane_cpp(buf->format, i);
+
+	return adf_format_validate_yuv(parent, buf, num_planes, hsub, vsub,
+			cpp);
+}
+
+static int adf_buffer_map(struct adf_device *dev, struct adf_buffer *buf,
+		struct adf_buffer_mapping *mapping)
+{
+	int ret = 0;
+	size_t i;
+
+	for (i = 0; i < buf->n_planes; i++) {
+		struct dma_buf_attachment *attachment;
+		struct sg_table *sg_table;
+
+		attachment = dma_buf_attach(buf->dma_bufs[i], dev->dev);
+		if (IS_ERR(attachment)) {
+			ret = PTR_ERR(attachment);
+			dev_err(&dev->base.dev, "attaching plane %zu failed: %d\n",
+					i, ret);
+			goto done;
+		}
+		mapping->attachments[i] = attachment;
+
+		sg_table = dma_buf_map_attachment(attachment, DMA_TO_DEVICE);
+		if (IS_ERR(sg_table)) {
+			ret = PTR_ERR(sg_table);
+			dev_err(&dev->base.dev, "mapping plane %zu failed: %d",
+					i, ret);
+			goto done;
+		} else if (!sg_table) {
+			ret = -ENOMEM;
+			dev_err(&dev->base.dev, "mapping plane %zu failed\n",
+					i);
+			goto done;
+		}
+		mapping->sg_tables[i] = sg_table;
+	}
+
+done:
+	if (ret < 0)
+		adf_buffer_mapping_cleanup(mapping, buf);
+
+	return ret;
+}
+
+static struct sync_fence *adf_sw_complete_fence(struct adf_device *dev)
+{
+	struct sync_pt *pt;
+	struct sync_fence *complete_fence;
+
+	if (!dev->timeline) {
+		dev->timeline = sw_sync_timeline_create(dev->base.name);
+		if (!dev->timeline)
+			return ERR_PTR(-ENOMEM);
+		dev->timeline_max = 1;
+	}
+
+	dev->timeline_max++;
+	pt = sw_sync_pt_create(dev->timeline, dev->timeline_max);
+	if (!pt)
+		goto err_pt_create;
+	complete_fence = sync_fence_create(dev->base.name, pt);
+	if (!complete_fence)
+		goto err_fence_create;
+
+	return complete_fence;
+
+err_fence_create:
+	sync_pt_free(pt);
+err_pt_create:
+	dev->timeline_max--;
+	return ERR_PTR(-ENOSYS);
+}
+
+/**
+ * adf_device_post - flip to a new set of buffers
+ *
+ * @dev: device targeted by the flip
+ * @intfs: interfaces targeted by the flip
+ * @n_intfs: number of targeted interfaces
+ * @bufs: description of buffers displayed
+ * @n_bufs: number of buffers displayed
+ * @custom_data: driver-private data
+ * @custom_data_size: size of driver-private data
+ *
+ * adf_device_post() will copy @intfs, @bufs, and @custom_data, so they may
+ * point to variables on the stack.  adf_device_post() also takes its own
+ * reference on each of the dma-bufs in @bufs.  The adf_device_post_nocopy()
+ * variant transfers ownership of these resources to ADF instead.
+ *
+ * On success, returns a sync fence which signals when the buffers are removed
+ * from the screen.  On failure, returns ERR_PTR(-errno).
+ */
+struct sync_fence *adf_device_post(struct adf_device *dev,
+		struct adf_interface **intfs, size_t n_intfs,
+		struct adf_buffer *bufs, size_t n_bufs, void *custom_data,
+		size_t custom_data_size)
+{
+	struct adf_interface **intfs_copy = NULL;
+	struct adf_buffer *bufs_copy = NULL;
+	void *custom_data_copy = NULL;
+	struct sync_fence *ret;
+	size_t i;
+
+	intfs_copy = kzalloc(sizeof(intfs_copy[0]) * n_intfs, GFP_KERNEL);
+	if (!intfs_copy)
+		return ERR_PTR(-ENOMEM);
+
+	bufs_copy = kzalloc(sizeof(bufs_copy[0]) * n_bufs, GFP_KERNEL);
+	if (!bufs_copy) {
+		ret = ERR_PTR(-ENOMEM);
+		goto err_alloc;
+	}
+
+	custom_data_copy = kzalloc(custom_data_size, GFP_KERNEL);
+	if (!custom_data_copy) {
+		ret = ERR_PTR(-ENOMEM);
+		goto err_alloc;
+	}
+
+	for (i = 0; i < n_bufs; i++) {
+		size_t j;
+		for (j = 0; j < bufs[i].n_planes; j++)
+			get_dma_buf(bufs[i].dma_bufs[j]);
+	}
+
+	memcpy(intfs_copy, intfs, sizeof(intfs_copy[0]) * n_intfs);
+	memcpy(bufs_copy, bufs, sizeof(bufs_copy[0]) * n_bufs);
+	memcpy(custom_data_copy, custom_data, custom_data_size);
+
+	ret = adf_device_post_nocopy(dev, intfs_copy, n_intfs, bufs_copy,
+			n_bufs, custom_data_copy, custom_data_size);
+	if (IS_ERR(ret))
+		goto err_post;
+
+	return ret;
+
+err_post:
+	for (i = 0; i < n_bufs; i++) {
+		size_t j;
+		for (j = 0; j < bufs[i].n_planes; j++)
+			dma_buf_put(bufs[i].dma_bufs[j]);
+	}
+err_alloc:
+	kfree(custom_data_copy);
+	kfree(bufs_copy);
+	kfree(intfs_copy);
+	return ret;
+}
+EXPORT_SYMBOL(adf_device_post);
+
+/**
+ * adf_device_post_nocopy - flip to a new set of buffers
+ *
+ * adf_device_post_nocopy() has the same behavior as adf_device_post(),
+ * except ADF does not copy @intfs, @bufs, or @custom_data, and it does
+ * not take an extra reference on the dma-bufs in @bufs.
+ *
+ * @intfs, @bufs, and @custom_data must point to buffers allocated by
+ * kmalloc().  On success, ADF takes ownership of these buffers and the dma-bufs
+ * in @bufs, and will kfree()/dma_buf_put() them when they are no longer needed.
+ * On failure, adf_device_post_nocopy() does NOT take ownership of these
+ * buffers or the dma-bufs, and the caller must clean them up.
+ *
+ * adf_device_post_nocopy() is mainly intended for implementing ADF's ioctls.
+ * Clients may find the nocopy variant useful in limited cases, but most should
+ * call adf_device_post() instead.
+ */
+struct sync_fence *adf_device_post_nocopy(struct adf_device *dev,
+		struct adf_interface **intfs, size_t n_intfs,
+		struct adf_buffer *bufs, size_t n_bufs,
+		void *custom_data, size_t custom_data_size)
+{
+	struct adf_pending_post *cfg;
+	struct adf_buffer_mapping *mappings;
+	struct sync_fence *ret;
+	size_t i;
+	int err;
+
+	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+	if (!cfg)
+		return ERR_PTR(-ENOMEM);
+
+	mappings = kzalloc(sizeof(mappings[0]) * n_bufs, GFP_KERNEL);
+	if (!mappings) {
+		ret = ERR_PTR(-ENOMEM);
+		goto err_alloc;
+	}
+
+	mutex_lock(&dev->client_lock);
+
+	for (i = 0; i < n_bufs; i++) {
+		err = adf_buffer_validate(&bufs[i]);
+		if (err < 0) {
+			ret = ERR_PTR(err);
+			goto err_buf;
+		}
+
+		err = adf_buffer_map(dev, &bufs[i], &mappings[i]);
+		if (err < 0) {
+			ret = ERR_PTR(err);
+			goto err_buf;
+		}
+	}
+
+	INIT_LIST_HEAD(&cfg->head);
+	cfg->config.n_bufs = n_bufs;
+	cfg->config.bufs = bufs;
+	cfg->config.mappings = mappings;
+	cfg->config.custom_data = custom_data;
+	cfg->config.custom_data_size = custom_data_size;
+
+	err = dev->ops->validate(dev, &cfg->config, &cfg->state);
+	if (err < 0) {
+		ret = ERR_PTR(err);
+		goto err_buf;
+	}
+
+	mutex_lock(&dev->post_lock);
+
+	if (dev->ops->complete_fence)
+		ret = dev->ops->complete_fence(dev, &cfg->config,
+				cfg->state);
+	else
+		ret = adf_sw_complete_fence(dev);
+
+	if (IS_ERR(ret))
+		goto err_fence;
+
+	list_add_tail(&cfg->head, &dev->post_list);
+	queue_kthread_work(&dev->post_worker, &dev->post_work);
+	mutex_unlock(&dev->post_lock);
+	mutex_unlock(&dev->client_lock);
+	kfree(intfs);
+	return ret;
+
+err_fence:
+	mutex_unlock(&dev->post_lock);
+
+err_buf:
+	for (i = 0; i < n_bufs; i++)
+		adf_buffer_mapping_cleanup(&mappings[i], &bufs[i]);
+
+	mutex_unlock(&dev->client_lock);
+	kfree(mappings);
+
+err_alloc:
+	kfree(cfg);
+	return ret;
+}
+EXPORT_SYMBOL(adf_device_post_nocopy);
+
+static void adf_attachment_list_to_array(struct adf_device *dev,
+		struct list_head *src, struct adf_attachment *dst, size_t size)
+{
+	struct adf_attachment_list *entry;
+	size_t i = 0;
+
+	if (!dst)
+		return;
+
+	list_for_each_entry(entry, src, head) {
+		if (i == size)
+			return;
+		dst[i] = entry->attachment;
+		i++;
+	}
+}
+
+/**
+ * adf_device_attachments - get device's list of active attachments
+ *
+ * @dev: the device
+ * @attachments: storage for the attachment list (optional)
+ * @n_attachments: length of @attachments
+ *
+ * If @attachments is not NULL, adf_device_attachments() will copy up to
+ * @n_attachments entries into @attachments.
+ *
+ * Returns the length of the active attachment list.
+ */
+size_t adf_device_attachments(struct adf_device *dev,
+		struct adf_attachment *attachments, size_t n_attachments)
+{
+	size_t retval;
+
+	mutex_lock(&dev->client_lock);
+	adf_attachment_list_to_array(dev, &dev->attached, attachments,
+			n_attachments);
+	retval = dev->n_attached;
+	mutex_unlock(&dev->client_lock);
+
+	return retval;
+}
+EXPORT_SYMBOL(adf_device_attachments);
+
+/**
+ * adf_device_attachments_allowed - get device's list of allowed attachments
+ *
+ * @dev: the device
+ * @attachments: storage for the attachment list (optional)
+ * @n_attachments: length of @attachments
+ *
+ * If @attachments is not NULL, adf_device_attachments_allowed() will copy up to
+ * @n_attachments entries into @attachments.
+ *
+ * Returns the length of the allowed attachment list.
+ */
+size_t adf_device_attachments_allowed(struct adf_device *dev,
+		struct adf_attachment *attachments, size_t n_attachments)
+{
+	size_t retval;
+
+	mutex_lock(&dev->client_lock);
+	adf_attachment_list_to_array(dev, &dev->attach_allowed, attachments,
+			n_attachments);
+	retval = dev->n_attach_allowed;
+	mutex_unlock(&dev->client_lock);
+
+	return retval;
+}
+EXPORT_SYMBOL(adf_device_attachments_allowed);
+
+/**
+ * adf_device_attached - return whether an overlay engine and interface are
+ * attached
+ *
+ * @dev: the parent device
+ * @eng: the overlay engine
+ * @intf: the interface
+ */
+bool adf_device_attached(struct adf_device *dev, struct adf_overlay_engine *eng,
+		struct adf_interface *intf)
+{
+	struct adf_attachment_list *attachment;
+
+	mutex_lock(&dev->client_lock);
+	attachment = adf_attachment_find(&dev->attached, eng, intf);
+	mutex_unlock(&dev->client_lock);
+
+	return attachment != NULL;
+}
+EXPORT_SYMBOL(adf_device_attached);
+
+/**
+ * adf_device_attach_allowed - return whether the ADF device supports attaching
+ * an overlay engine and interface
+ *
+ * @dev: the parent device
+ * @eng: the overlay engine
+ * @intf: the interface
+ */
+bool adf_device_attach_allowed(struct adf_device *dev,
+		struct adf_overlay_engine *eng, struct adf_interface *intf)
+{
+	struct adf_attachment_list *attachment;
+
+	mutex_lock(&dev->client_lock);
+	attachment = adf_attachment_find(&dev->attach_allowed, eng, intf);
+	mutex_unlock(&dev->client_lock);
+
+	return attachment != NULL;
+}
+EXPORT_SYMBOL(adf_device_attach_allowed);
+/**
+ * adf_device_attach - attach an overlay engine to an interface
+ *
+ * @dev: the parent device
+ * @eng: the overlay engine
+ * @intf: the interface
+ *
+ * Returns 0 on success, -%EINVAL if attaching @intf and @eng is not allowed,
+ * -%EALREADY if @intf and @eng are already attached, or -errno on any other
+ * failure.
+ */
+int adf_device_attach(struct adf_device *dev, struct adf_overlay_engine *eng,
+		struct adf_interface *intf)
+{
+	int ret;
+	struct adf_attachment_list *attachment = NULL;
+
+	ret = adf_attachment_validate(dev, eng, intf);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&dev->client_lock);
+
+	if (dev->n_attached == ADF_MAX_ATTACHMENTS) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (!adf_attachment_find(&dev->attach_allowed, eng, intf)) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (adf_attachment_find(&dev->attached, eng, intf)) {
+		ret = -EALREADY;
+		goto done;
+	}
+
+	ret = adf_device_attach_op(dev, eng, intf);
+	if (ret < 0)
+		goto done;
+
+	attachment = kzalloc(sizeof(*attachment), GFP_KERNEL);
+	if (!attachment) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	attachment->attachment.interface = intf;
+	attachment->attachment.overlay_engine = eng;
+	list_add_tail(&attachment->head, &dev->attached);
+	dev->n_attached++;
+
+done:
+	mutex_unlock(&dev->client_lock);
+	if (ret < 0)
+		kfree(attachment);
+
+	return ret;
+}
+EXPORT_SYMBOL(adf_device_attach);
+
+/**
+ * adf_device_detach - detach an overlay engine from an interface
+ *
+ * @dev: the parent device
+ * @eng: the overlay engine
+ * @intf: the interface
+ *
+ * Returns 0 on success, -%EINVAL if @intf and @eng are not attached,
+ * or -errno on any other failure.
+ */
+int adf_device_detach(struct adf_device *dev, struct adf_overlay_engine *eng,
+		struct adf_interface *intf)
+{
+	int ret;
+	struct adf_attachment_list *attachment;
+
+	ret = adf_attachment_validate(dev, eng, intf);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&dev->client_lock);
+
+	attachment = adf_attachment_find(&dev->attached, eng, intf);
+	if (!attachment) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ret = adf_device_detach_op(dev, eng, intf);
+	if (ret < 0)
+		goto done;
+
+	adf_attachment_free(attachment);
+	dev->n_attached--;
+done:
+	mutex_unlock(&dev->client_lock);
+	return ret;
+}
+EXPORT_SYMBOL(adf_device_detach);
+
+/**
+ * adf_interface_simple_buffer_alloc - allocate a simple buffer
+ *
+ * @intf: target interface
+ * @w: width in pixels
+ * @h: height in pixels
+ * @format: format fourcc
+ * @dma_buf: returns the allocated buffer
+ * @offset: returns the byte offset of the allocated buffer's first pixel
+ * @pitch: returns the allocated buffer's pitch
+ *
+ * See &struct adf_simple_buffer_alloc for a description of simple buffers and
+ * their limitations.
+ *
+ * Returns 0 on success or -errno on failure.
+ */
+int adf_interface_simple_buffer_alloc(struct adf_interface *intf, u16 w, u16 h,
+		u32 format, struct dma_buf **dma_buf, u32 *offset, u32 *pitch)
+{
+	if (!intf->ops || !intf->ops->alloc_simple_buffer)
+		return -EOPNOTSUPP;
+
+	if (!adf_format_is_rgb(format))
+		return -EINVAL;
+
+	return intf->ops->alloc_simple_buffer(intf, w, h, format, dma_buf,
+			offset, pitch);
+}
+EXPORT_SYMBOL(adf_interface_simple_buffer_alloc);
+
+/**
+ * adf_interface_simple_post - flip to a single buffer
+ *
+ * @intf: interface targeted by the flip
+ * @buf: buffer to display
+ *
+ * adf_interface_simple_post() can be used generically for simple display
+ * configurations, since the client does not need to provide any driver-private
+ * configuration data.
+ *
+ * adf_interface_simple_post() has the same copying semantics as
+ * adf_device_post().
+ *
+ * On success, returns a sync fence which signals when the buffer is removed
+ * from the screen.  On failure, returns ERR_PTR(-errno).
+ */
+struct sync_fence *adf_interface_simple_post(struct adf_interface *intf,
+		struct adf_buffer *buf)
+{
+	size_t custom_data_size = 0;
+	void *custom_data = NULL;
+	struct sync_fence *ret;
+
+	if (intf->ops && intf->ops->describe_simple_post) {
+		int err;
+
+		custom_data = kzalloc(ADF_MAX_CUSTOM_DATA_SIZE, GFP_KERNEL);
+		if (!custom_data) {
+			ret = ERR_PTR(-ENOMEM);
+			goto done;
+		}
+
+		err = intf->ops->describe_simple_post(intf, buf, custom_data,
+				&custom_data_size);
+		if (err < 0) {
+			ret = ERR_PTR(err);
+			goto done;
+		}
+	}
+
+	ret = adf_device_post(adf_interface_parent(intf), &intf, 1, buf, 1,
+			custom_data, custom_data_size);
+done:
+	kfree(custom_data);
+	return ret;
+}
+EXPORT_SYMBOL(adf_interface_simple_post);
diff --git a/drivers/video/adf/adf_fbdev.c b/drivers/video/adf/adf_fbdev.c
new file mode 100644
index 0000000..a5b53bc
--- /dev/null
+++ b/drivers/video/adf/adf_fbdev.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/vmalloc.h>
+
+#include <video/adf.h>
+#include <video/adf_client.h>
+#include <video/adf_fbdev.h>
+#include <video/adf_format.h>
+
+#include "adf.h"
+
+struct adf_fbdev_format {
+	u32 fourcc;
+	u32 bpp;
+	u32 r_length;
+	u32 g_length;
+	u32 b_length;
+	u32 a_length;
+	u32 r_offset;
+	u32 g_offset;
+	u32 b_offset;
+	u32 a_offset;
+};
+
+static const struct adf_fbdev_format format_table[] = {
+	{DRM_FORMAT_RGB332, 8, 3, 3, 2, 0, 5, 2, 0, 0},
+	{DRM_FORMAT_BGR233, 8, 3, 3, 2, 0, 0, 3, 5, 0},
+
+	{DRM_FORMAT_XRGB4444, 16, 4, 4, 4, 0, 8, 4, 0, 0},
+	{DRM_FORMAT_XBGR4444, 16, 4, 4, 4, 0, 0, 4, 8, 0},
+	{DRM_FORMAT_RGBX4444, 16, 4, 4, 4, 0, 12, 8, 4, 0},
+	{DRM_FORMAT_BGRX4444, 16, 4, 4, 4, 0, 0, 4, 8, 0},
+
+	{DRM_FORMAT_ARGB4444, 16, 4, 4, 4, 4, 8, 4, 0, 12},
+	{DRM_FORMAT_ABGR4444, 16, 4, 4, 4, 4, 0, 4, 8, 12},
+	{DRM_FORMAT_RGBA4444, 16, 4, 4, 4, 4, 12, 8, 4, 0},
+	{DRM_FORMAT_BGRA4444, 16, 4, 4, 4, 4, 0, 4, 8, 0},
+
+	{DRM_FORMAT_XRGB1555, 16, 5, 5, 5, 0, 10, 5, 0, 0},
+	{DRM_FORMAT_XBGR1555, 16, 5, 5, 5, 0, 0, 5, 10, 0},
+	{DRM_FORMAT_RGBX5551, 16, 5, 5, 5, 0, 11, 6, 1, 0},
+	{DRM_FORMAT_BGRX5551, 16, 5, 5, 5, 0, 1, 6, 11, 0},
+
+	{DRM_FORMAT_ARGB1555, 16, 5, 5, 5, 1, 10, 5, 0, 15},
+	{DRM_FORMAT_ABGR1555, 16, 5, 5, 5, 1, 0, 5, 10, 15},
+	{DRM_FORMAT_RGBA5551, 16, 5, 5, 5, 1, 11, 6, 1, 0},
+	{DRM_FORMAT_BGRA5551, 16, 5, 5, 5, 1, 1, 6, 11, 0},
+
+	{DRM_FORMAT_RGB565, 16, 5, 6, 5, 0, 11, 5, 0, 0},
+	{DRM_FORMAT_BGR565, 16, 5, 6, 5, 0, 0, 5, 11, 0},
+
+	{DRM_FORMAT_RGB888, 24, 8, 8, 8, 0, 16, 8, 0, 0},
+	{DRM_FORMAT_BGR888, 24, 8, 8, 8, 0, 0, 8, 16, 0},
+
+	{DRM_FORMAT_XRGB8888, 32, 8, 8, 8, 0, 16, 8, 0, 0},
+	{DRM_FORMAT_XBGR8888, 32, 8, 8, 8, 0, 0, 8, 16, 0},
+	{DRM_FORMAT_RGBX8888, 32, 8, 8, 8, 0, 24, 16, 8, 0},
+	{DRM_FORMAT_BGRX8888, 32, 8, 8, 8, 0, 8, 16, 24, 0},
+
+	{DRM_FORMAT_ARGB8888, 32, 8, 8, 8, 8, 16, 8, 0, 24},
+	{DRM_FORMAT_ABGR8888, 32, 8, 8, 8, 8, 0, 8, 16, 24},
+	{DRM_FORMAT_RGBA8888, 32, 8, 8, 8, 8, 24, 16, 8, 0},
+	{DRM_FORMAT_BGRA8888, 32, 8, 8, 8, 8, 8, 16, 24, 0},
+
+	{DRM_FORMAT_XRGB2101010, 32, 10, 10, 10, 0, 20, 10, 0, 0},
+	{DRM_FORMAT_XBGR2101010, 32, 10, 10, 10, 0, 0, 10, 20, 0},
+	{DRM_FORMAT_RGBX1010102, 32, 10, 10, 10, 0, 22, 12, 2, 0},
+	{DRM_FORMAT_BGRX1010102, 32, 10, 10, 10, 0, 2, 12, 22, 0},
+
+	{DRM_FORMAT_ARGB2101010, 32, 10, 10, 10, 2, 20, 10, 0, 30},
+	{DRM_FORMAT_ABGR2101010, 32, 10, 10, 10, 2, 0, 10, 20, 30},
+	{DRM_FORMAT_RGBA1010102, 32, 10, 10, 10, 2, 22, 12, 2, 0},
+	{DRM_FORMAT_BGRA1010102, 32, 10, 10, 10, 2, 2, 12, 22, 0},
+};
+
+static u32 drm_fourcc_from_fb_var(struct fb_var_screeninfo *var)
+{
+	size_t i;
+	for (i = 0; i < ARRAY_SIZE(format_table); i++) {
+		const struct adf_fbdev_format *f = &format_table[i];
+		if (var->red.length == f->r_length &&
+			var->red.offset == f->r_offset &&
+			var->green.length == f->g_length &&
+			var->green.offset == f->g_offset &&
+			var->blue.length == f->b_length &&
+			var->blue.offset == f->b_offset &&
+			var->transp.length == f->a_length &&
+			(var->transp.length == 0 ||
+					var->transp.offset == f->a_offset))
+			return f->fourcc;
+	}
+
+	return 0;
+}
+
+static const struct adf_fbdev_format *fbdev_format_info(u32 format)
+{
+	size_t i;
+	for (i = 0; i < ARRAY_SIZE(format_table); i++) {
+		const struct adf_fbdev_format *f = &format_table[i];
+		if (f->fourcc == format)
+			return f;
+	}
+
+	BUG();
+}
+
+void adf_modeinfo_to_fb_videomode(const struct drm_mode_modeinfo *mode,
+		struct fb_videomode *vmode)
+{
+	memset(vmode, 0, sizeof(*vmode));
+
+	vmode->refresh = mode->vrefresh;
+
+	vmode->xres = mode->hdisplay;
+	vmode->yres = mode->vdisplay;
+
+	vmode->pixclock = mode->clock ? KHZ2PICOS(mode->clock) : 0;
+	vmode->left_margin = mode->htotal - mode->hsync_end;
+	vmode->right_margin = mode->hsync_start - mode->hdisplay;
+	vmode->upper_margin = mode->vtotal - mode->vsync_end;
+	vmode->lower_margin = mode->vsync_start - mode->vdisplay;
+	vmode->hsync_len = mode->hsync_end - mode->hsync_start;
+	vmode->vsync_len = mode->vsync_end - mode->vsync_start;
+
+	vmode->sync = 0;
+	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+		vmode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+		vmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+	if (mode->flags & DRM_MODE_FLAG_PCSYNC)
+		vmode->sync |= FB_SYNC_COMP_HIGH_ACT;
+	if (mode->flags & DRM_MODE_FLAG_BCAST)
+		vmode->sync |= FB_SYNC_BROADCAST;
+
+	vmode->vmode = 0;
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		vmode->vmode |= FB_VMODE_INTERLACED;
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		vmode->vmode |= FB_VMODE_DOUBLE;
+}
+EXPORT_SYMBOL(adf_modeinfo_to_fb_videomode);
+
+void adf_modeinfo_from_fb_videomode(const struct fb_videomode *vmode,
+		struct drm_mode_modeinfo *mode)
+{
+	memset(mode, 0, sizeof(*mode));
+
+	mode->hdisplay = vmode->xres;
+	mode->hsync_start = mode->hdisplay + vmode->right_margin;
+	mode->hsync_end = mode->hsync_start + vmode->hsync_len;
+	mode->htotal = mode->hsync_end + vmode->left_margin;
+
+	mode->vdisplay = vmode->yres;
+	mode->vsync_start = mode->vdisplay + vmode->lower_margin;
+	mode->vsync_end = mode->vsync_start + vmode->vsync_len;
+	mode->vtotal = mode->vsync_end + vmode->upper_margin;
+
+	mode->clock = vmode->pixclock ? PICOS2KHZ(vmode->pixclock) : 0;
+
+	mode->flags = 0;
+	if (vmode->sync & FB_SYNC_HOR_HIGH_ACT)
+		mode->flags |= DRM_MODE_FLAG_PHSYNC;
+	if (vmode->sync & FB_SYNC_VERT_HIGH_ACT)
+		mode->flags |= DRM_MODE_FLAG_PVSYNC;
+	if (vmode->sync & FB_SYNC_COMP_HIGH_ACT)
+		mode->flags |= DRM_MODE_FLAG_PCSYNC;
+	if (vmode->sync & FB_SYNC_BROADCAST)
+		mode->flags |= DRM_MODE_FLAG_BCAST;
+	if (vmode->vmode & FB_VMODE_INTERLACED)
+		mode->flags |= DRM_MODE_FLAG_INTERLACE;
+	if (vmode->vmode & FB_VMODE_DOUBLE)
+		mode->flags |= DRM_MODE_FLAG_DBLSCAN;
+
+	if (vmode->refresh)
+		mode->vrefresh = vmode->refresh;
+	else
+		adf_modeinfo_set_vrefresh(mode);
+
+	if (vmode->name)
+		strlcpy(mode->name, vmode->name, sizeof(mode->name));
+	else
+		adf_modeinfo_set_name(mode);
+}
+EXPORT_SYMBOL(adf_modeinfo_from_fb_videomode);
+
+static int adf_fbdev_post(struct adf_fbdev *fbdev)
+{
+	struct adf_buffer buf;
+	struct sync_fence *complete_fence;
+	int ret = 0;
+
+	memset(&buf, 0, sizeof(buf));
+	buf.overlay_engine = fbdev->eng;
+	buf.w = fbdev->info->var.xres;
+	buf.h = fbdev->info->var.yres;
+	buf.format = fbdev->format;
+	buf.dma_bufs[0] = fbdev->dma_buf;
+	buf.offset[0] = fbdev->offset +
+			fbdev->info->var.yoffset * fbdev->pitch +
+			fbdev->info->var.xoffset *
+			(fbdev->info->var.bits_per_pixel / 8);
+	buf.pitch[0] = fbdev->pitch;
+	buf.n_planes = 1;
+
+	complete_fence = adf_interface_simple_post(fbdev->intf, &buf);
+	if (IS_ERR(complete_fence)) {
+		ret = PTR_ERR(complete_fence);
+		goto done;
+	}
+
+	sync_fence_put(complete_fence);
+done:
+	return ret;
+}
+
+static const u16 vga_palette[][3] = {
+	{0x0000, 0x0000, 0x0000},
+	{0x0000, 0x0000, 0xAAAA},
+	{0x0000, 0xAAAA, 0x0000},
+	{0x0000, 0xAAAA, 0xAAAA},
+	{0xAAAA, 0x0000, 0x0000},
+	{0xAAAA, 0x0000, 0xAAAA},
+	{0xAAAA, 0x5555, 0x0000},
+	{0xAAAA, 0xAAAA, 0xAAAA},
+	{0x5555, 0x5555, 0x5555},
+	{0x5555, 0x5555, 0xFFFF},
+	{0x5555, 0xFFFF, 0x5555},
+	{0x5555, 0xFFFF, 0xFFFF},
+	{0xFFFF, 0x5555, 0x5555},
+	{0xFFFF, 0x5555, 0xFFFF},
+	{0xFFFF, 0xFFFF, 0x5555},
+	{0xFFFF, 0xFFFF, 0xFFFF},
+};
+
+static int adf_fb_alloc(struct adf_fbdev *fbdev)
+{
+	int ret;
+
+	ret = adf_interface_simple_buffer_alloc(fbdev->intf,
+			fbdev->default_xres_virtual,
+			fbdev->default_yres_virtual,
+			fbdev->default_format,
+			&fbdev->dma_buf, &fbdev->offset, &fbdev->pitch);
+	if (ret < 0) {
+		dev_err(fbdev->info->dev, "allocating fb failed: %d\n", ret);
+		return ret;
+	}
+
+	fbdev->vaddr = dma_buf_vmap(fbdev->dma_buf);
+	if (!fbdev->vaddr) {
+		ret = -ENOMEM;
+		dev_err(fbdev->info->dev, "vmapping fb failed\n");
+		goto err_vmap;
+	}
+	fbdev->info->fix.line_length = fbdev->pitch;
+	fbdev->info->var.xres_virtual = fbdev->default_xres_virtual;
+	fbdev->info->var.yres_virtual = fbdev->default_yres_virtual;
+	fbdev->info->fix.smem_len = fbdev->dma_buf->size;
+	fbdev->info->screen_base = fbdev->vaddr;
+
+	return 0;
+
+err_vmap:
+	dma_buf_put(fbdev->dma_buf);
+	return ret;
+}
+
+static void adf_fb_destroy(struct adf_fbdev *fbdev)
+{
+	dma_buf_vunmap(fbdev->dma_buf, fbdev->vaddr);
+	dma_buf_put(fbdev->dma_buf);
+}
+
+static void adf_fbdev_set_format(struct adf_fbdev *fbdev, u32 format)
+{
+	size_t i;
+	const struct adf_fbdev_format *info = fbdev_format_info(format);
+	for (i = 0; i < ARRAY_SIZE(vga_palette); i++) {
+		u16 r = vga_palette[i][0];
+		u16 g = vga_palette[i][1];
+		u16 b = vga_palette[i][2];
+
+		r >>= (16 - info->r_length);
+		g >>= (16 - info->g_length);
+		b >>= (16 - info->b_length);
+
+		fbdev->pseudo_palette[i] =
+			(r << info->r_offset) |
+			(g << info->g_offset) |
+			(b << info->b_offset);
+
+		if (info->a_length) {
+			u16 a = BIT(info->a_length) - 1;
+			fbdev->pseudo_palette[i] |= (a << info->a_offset);
+		}
+	}
+
+	fbdev->info->var.bits_per_pixel = adf_format_bpp(format);
+	fbdev->info->var.red.length = info->r_length;
+	fbdev->info->var.red.offset = info->r_offset;
+	fbdev->info->var.green.length = info->g_length;
+	fbdev->info->var.green.offset = info->g_offset;
+	fbdev->info->var.blue.length = info->b_length;
+	fbdev->info->var.blue.offset = info->b_offset;
+	fbdev->info->var.transp.length = info->a_length;
+	fbdev->info->var.transp.offset = info->a_offset;
+	fbdev->format = format;
+}
+
+static void adf_fbdev_fill_modelist(struct adf_fbdev *fbdev)
+{
+	struct drm_mode_modeinfo *modelist;
+	struct fb_videomode fbmode;
+	size_t n_modes, i;
+	int ret = 0;
+
+	n_modes = adf_interface_modelist(fbdev->intf, NULL, 0);
+	modelist = kzalloc(sizeof(modelist[0]) * n_modes, GFP_KERNEL);
+	if (!modelist) {
+		dev_warn(fbdev->info->dev, "allocating new modelist failed; keeping old modelist\n");
+		return;
+	}
+	adf_interface_modelist(fbdev->intf, modelist, n_modes);
+
+	fb_destroy_modelist(&fbdev->info->modelist);
+
+	for (i = 0; i < n_modes; i++) {
+		adf_modeinfo_to_fb_videomode(&modelist[i], &fbmode);
+		ret = fb_add_videomode(&fbmode, &fbdev->info->modelist);
+		if (ret < 0)
+			dev_warn(fbdev->info->dev, "adding mode %s to modelist failed: %d\n",
+					modelist[i].name, ret);
+	}
+
+	kfree(modelist);
+}
+
+/**
+ * adf_fbdev_open - default implementation of fbdev open op
+ */
+int adf_fbdev_open(struct fb_info *info, int user)
+{
+	struct adf_fbdev *fbdev = info->par;
+	int ret;
+
+	mutex_lock(&fbdev->refcount_lock);
+
+	if (unlikely(fbdev->refcount == UINT_MAX)) {
+		ret = -EMFILE;
+		goto done;
+	}
+
+	if (!fbdev->refcount) {
+		struct drm_mode_modeinfo mode;
+		struct fb_videomode fbmode;
+		struct adf_device *dev = adf_interface_parent(fbdev->intf);
+
+		ret = adf_device_attach(dev, fbdev->eng, fbdev->intf);
+		if (ret < 0 && ret != -EALREADY)
+			goto done;
+
+		ret = adf_fb_alloc(fbdev);
+		if (ret < 0)
+			goto done;
+
+		adf_interface_current_mode(fbdev->intf, &mode);
+		adf_modeinfo_to_fb_videomode(&mode, &fbmode);
+		fb_videomode_to_var(&fbdev->info->var, &fbmode);
+
+		adf_fbdev_set_format(fbdev, fbdev->default_format);
+		adf_fbdev_fill_modelist(fbdev);
+	}
+
+	ret = adf_fbdev_post(fbdev);
+	if (ret < 0) {
+		if (!fbdev->refcount)
+			adf_fb_destroy(fbdev);
+		goto done;
+	}
+
+	fbdev->refcount++;
+done:
+	mutex_unlock(&fbdev->refcount_lock);
+	return ret;
+}
+EXPORT_SYMBOL(adf_fbdev_open);
+
+/**
+ * adf_fbdev_release - default implementation of fbdev release op
+ */
+int adf_fbdev_release(struct fb_info *info, int user)
+{
+	struct adf_fbdev *fbdev = info->par;
+	mutex_lock(&fbdev->refcount_lock);
+	BUG_ON(!fbdev->refcount);
+	fbdev->refcount--;
+	if (!fbdev->refcount)
+		adf_fb_destroy(fbdev);
+	mutex_unlock(&fbdev->refcount_lock);
+	return 0;
+}
+EXPORT_SYMBOL(adf_fbdev_release);
+
+/**
+ * adf_fbdev_check_var - default implementation of fbdev check_var op
+ */
+int adf_fbdev_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct adf_fbdev *fbdev = info->par;
+	bool valid_format = true;
+	u32 format = drm_fourcc_from_fb_var(var);
+	u32 pitch = var->xres_virtual * var->bits_per_pixel / 8;
+
+	if (!format) {
+		dev_dbg(info->dev, "%s: unrecognized format\n", __func__);
+		valid_format = false;
+	}
+
+	if (valid_format && var->grayscale) {
+		dev_dbg(info->dev, "%s: grayscale modes not supported\n",
+				__func__);
+		valid_format = false;
+	}
+
+	if (valid_format && var->nonstd) {
+		dev_dbg(info->dev, "%s: nonstandard formats not supported\n",
+				__func__);
+		valid_format = false;
+	}
+
+	if (valid_format && !adf_overlay_engine_supports_format(fbdev->eng,
+			format)) {
+		char format_str[ADF_FORMAT_STR_SIZE];
+		adf_format_str(format, format_str);
+		dev_dbg(info->dev, "%s: format %s not supported by overlay engine %s\n",
+				__func__, format_str, fbdev->eng->base.name);
+		valid_format = false;
+	}
+
+	if (valid_format && pitch > fbdev->pitch) {
+		dev_dbg(info->dev, "%s: fb pitch too small for var (pitch = %u, xres_virtual = %u, bits_per_pixel = %u)\n",
+				__func__, fbdev->pitch, var->xres_virtual,
+				var->bits_per_pixel);
+		valid_format = false;
+	}
+
+	if (valid_format && var->yres_virtual > fbdev->default_yres_virtual) {
+		dev_dbg(info->dev, "%s: fb height too small for var (h = %u, yres_virtual = %u)\n",
+				__func__, fbdev->default_yres_virtual,
+				var->yres_virtual);
+		valid_format = false;
+	}
+
+	if (valid_format) {
+		var->activate = info->var.activate;
+		var->height = info->var.height;
+		var->width = info->var.width;
+		var->accel_flags = info->var.accel_flags;
+		var->rotate = info->var.rotate;
+		var->colorspace = info->var.colorspace;
+		/* userspace can't change these */
+	} else {
+		/* if any part of the format is invalid then fixing it up is
+		   impractical, so save just the modesetting bits and
+		   overwrite everything else */
+		struct fb_videomode mode;
+		fb_var_to_videomode(&mode, var);
+		memcpy(var, &info->var, sizeof(*var));
+		fb_videomode_to_var(var, &mode);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(adf_fbdev_check_var);
+
+/**
+ * adf_fbdev_set_par - default implementation of fbdev set_par op
+ */
+int adf_fbdev_set_par(struct fb_info *info)
+{
+	struct adf_fbdev *fbdev = info->par;
+	struct adf_interface *intf = fbdev->intf;
+	struct fb_videomode vmode;
+	struct drm_mode_modeinfo mode;
+	int ret;
+	u32 format = drm_fourcc_from_fb_var(&info->var);
+
+	fb_var_to_videomode(&vmode, &info->var);
+	adf_modeinfo_from_fb_videomode(&vmode, &mode);
+	ret = adf_interface_set_mode(intf, &mode);
+	if (ret < 0)
+		return ret;
+
+	ret = adf_fbdev_post(fbdev);
+	if (ret < 0)
+		return ret;
+
+	if (format != fbdev->format)
+		adf_fbdev_set_format(fbdev, format);
+
+	return 0;
+}
+EXPORT_SYMBOL(adf_fbdev_set_par);
+
+/**
+ * adf_fbdev_blank - default implementation of fbdev blank op
+ */
+int adf_fbdev_blank(int blank, struct fb_info *info)
+{
+	struct adf_fbdev *fbdev = info->par;
+	struct adf_interface *intf = fbdev->intf;
+	u8 dpms_state;
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		dpms_state = DRM_MODE_DPMS_ON;
+		break;
+	case FB_BLANK_NORMAL:
+		dpms_state = DRM_MODE_DPMS_STANDBY;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		dpms_state = DRM_MODE_DPMS_SUSPEND;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		dpms_state = DRM_MODE_DPMS_STANDBY;
+		break;
+	case FB_BLANK_POWERDOWN:
+		dpms_state = DRM_MODE_DPMS_OFF;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return adf_interface_blank(intf, dpms_state);
+}
+EXPORT_SYMBOL(adf_fbdev_blank);
+
+/**
+ * adf_fbdev_pan_display - default implementation of fbdev pan_display op
+ */
+int adf_fbdev_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct adf_fbdev *fbdev = info->par;
+	return adf_fbdev_post(fbdev);
+}
+EXPORT_SYMBOL(adf_fbdev_pan_display);
+
+/**
+ * adf_fbdev_mmap - default implementation of fbdev mmap op
+ */
+int adf_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct adf_fbdev *fbdev = info->par;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	return dma_buf_mmap(fbdev->dma_buf, vma, 0);
+}
+EXPORT_SYMBOL(adf_fbdev_mmap);
+
+/**
+ * adf_fbdev_init - initialize helper to wrap ADF device in fbdev API
+ *
+ * @fbdev: the fbdev helper
+ * @interface: the ADF interface that will display the framebuffer
+ * @eng: the ADF overlay engine that will scan out the framebuffer
+ * @xres_virtual: the virtual width of the framebuffer
+ * @yres_virtual: the virtual height of the framebuffer
+ * @format: the format of the framebuffer
+ * @fbops: the device's fbdev ops
+ * @fmt: formatting for the framebuffer identification string
+ * @...: variable arguments
+ *
+ * @format must be a standard, non-indexed RGB format, i.e.,
+ * adf_format_is_rgb(@format) && @format != @DRM_FORMAT_C8.
+ *
+ * Returns 0 on success or -errno on failure.
+ */
+int adf_fbdev_init(struct adf_fbdev *fbdev, struct adf_interface *interface,
+		struct adf_overlay_engine *eng,
+		u16 xres_virtual, u16 yres_virtual, u32 format,
+		struct fb_ops *fbops, const char *fmt, ...)
+{
+	struct adf_device *parent = adf_interface_parent(interface);
+	struct device *dev = &parent->base.dev;
+	u16 width_mm, height_mm;
+	va_list args;
+	int ret;
+
+	if (!adf_format_is_rgb(format) ||
+			format == DRM_FORMAT_C8) {
+		dev_err(dev, "fbdev helper does not support format %u\n",
+				format);
+		return -EINVAL;
+	}
+
+	memset(fbdev, 0, sizeof(*fbdev));
+	fbdev->intf = interface;
+	fbdev->eng = eng;
+	fbdev->info = framebuffer_alloc(0, dev);
+	if (!fbdev->info) {
+		dev_err(dev, "allocating framebuffer device failed\n");
+		return -ENOMEM;
+	}
+	mutex_init(&fbdev->refcount_lock);
+	fbdev->default_xres_virtual = xres_virtual;
+	fbdev->default_yres_virtual = yres_virtual;
+	fbdev->default_format = format;
+
+	fbdev->info->flags = FBINFO_FLAG_DEFAULT;
+	ret = adf_interface_get_screen_size(interface, &width_mm, &height_mm);
+	if (ret < 0) {
+		width_mm = 0;
+		height_mm = 0;
+	}
+	fbdev->info->var.width = width_mm;
+	fbdev->info->var.height = height_mm;
+	fbdev->info->var.activate = FB_ACTIVATE_VBL;
+	va_start(args, fmt);
+	vsnprintf(fbdev->info->fix.id, sizeof(fbdev->info->fix.id), fmt, args);
+	va_end(args);
+	fbdev->info->fix.type = FB_TYPE_PACKED_PIXELS;
+	fbdev->info->fix.visual = FB_VISUAL_TRUECOLOR;
+	fbdev->info->fix.xpanstep = 1;
+	fbdev->info->fix.ypanstep = 1;
+	INIT_LIST_HEAD(&fbdev->info->modelist);
+	fbdev->info->fbops = fbops;
+	fbdev->info->pseudo_palette = fbdev->pseudo_palette;
+	fbdev->info->par = fbdev;
+
+	ret = register_framebuffer(fbdev->info);
+	if (ret < 0) {
+		dev_err(dev, "registering framebuffer failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(adf_fbdev_init);
+
+/**
+ * adf_fbdev_destroy - destroy helper to wrap ADF device in fbdev API
+ *
+ * @fbdev: the fbdev helper
+ */
+void adf_fbdev_destroy(struct adf_fbdev *fbdev)
+{
+	unregister_framebuffer(fbdev->info);
+	BUG_ON(fbdev->refcount);
+	mutex_destroy(&fbdev->refcount_lock);
+	framebuffer_release(fbdev->info);
+}
+EXPORT_SYMBOL(adf_fbdev_destroy);
diff --git a/drivers/video/adf/adf_fops.c b/drivers/video/adf/adf_fops.c
new file mode 100644
index 0000000..705411b
--- /dev/null
+++ b/drivers/video/adf/adf_fops.c
@@ -0,0 +1,946 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/circ_buf.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <video/adf_client.h>
+#include <video/adf_format.h>
+
+#include "sw_sync.h"
+#include "sync.h"
+
+#include "adf.h"
+#include "adf_fops.h"
+#include "adf_sysfs.h"
+
+#ifdef CONFIG_COMPAT
+#include "adf_fops32.h"
+#endif
+
+static int adf_obj_set_event(struct adf_obj *obj, struct adf_file *file,
+		struct adf_set_event __user *arg)
+{
+	struct adf_set_event data;
+	bool enabled;
+	unsigned long flags;
+	int err;
+
+	if (copy_from_user(&data, arg, sizeof(data)))
+		return -EFAULT;
+
+	err = adf_obj_check_supports_event(obj, data.type);
+	if (err < 0)
+		return err;
+
+	spin_lock_irqsave(&obj->file_lock, flags);
+	if (data.enabled)
+		enabled = test_and_set_bit(data.type,
+				file->event_subscriptions);
+	else
+		enabled = test_and_clear_bit(data.type,
+				file->event_subscriptions);
+	spin_unlock_irqrestore(&obj->file_lock, flags);
+
+	if (data.enabled == enabled)
+		return -EALREADY;
+
+	if (data.enabled)
+		adf_event_get(obj, data.type);
+	else
+		adf_event_put(obj, data.type);
+
+	return 0;
+}
+
+static int adf_obj_copy_custom_data_to_user(struct adf_obj *obj,
+		void __user *dst, size_t *dst_size)
+{
+	void *custom_data;
+	size_t custom_data_size;
+	int ret;
+
+	if (!obj->ops || !obj->ops->custom_data) {
+		dev_dbg(&obj->dev, "%s: no custom_data op\n", __func__);
+		return 0;
+	}
+
+	custom_data = kzalloc(ADF_MAX_CUSTOM_DATA_SIZE, GFP_KERNEL);
+	if (!custom_data)
+		return -ENOMEM;
+
+	ret = obj->ops->custom_data(obj, custom_data, &custom_data_size);
+	if (ret < 0)
+		goto done;
+
+	if (copy_to_user(dst, custom_data, min(*dst_size, custom_data_size))) {
+		ret = -EFAULT;
+		goto done;
+	}
+	*dst_size = custom_data_size;
+
+done:
+	kfree(custom_data);
+	return ret;
+}
+
+static int adf_eng_get_data(struct adf_overlay_engine *eng,
+		struct adf_overlay_engine_data __user *arg)
+{
+	struct adf_device *dev = adf_overlay_engine_parent(eng);
+	struct adf_overlay_engine_data data;
+	size_t n_supported_formats;
+	u32 *supported_formats = NULL;
+	int ret = 0;
+
+	if (copy_from_user(&data, arg, sizeof(data)))
+		return -EFAULT;
+
+	strlcpy(data.name, eng->base.name, sizeof(data.name));
+
+	if (data.n_supported_formats > ADF_MAX_SUPPORTED_FORMATS)
+		return -EINVAL;
+
+	n_supported_formats = data.n_supported_formats;
+	data.n_supported_formats = eng->ops->n_supported_formats;
+
+	if (n_supported_formats) {
+		supported_formats = kzalloc(n_supported_formats *
+				sizeof(supported_formats[0]), GFP_KERNEL);
+		if (!supported_formats)
+			return -ENOMEM;
+	}
+
+	memcpy(supported_formats, eng->ops->supported_formats,
+			sizeof(u32) * min(n_supported_formats,
+					eng->ops->n_supported_formats));
+
+	mutex_lock(&dev->client_lock);
+	ret = adf_obj_copy_custom_data_to_user(&eng->base, data.custom_data,
+			&data.custom_data_size);
+	mutex_unlock(&dev->client_lock);
+
+	if (ret < 0)
+		goto done;
+
+	if (copy_to_user(arg, &data, sizeof(data))) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (supported_formats && copy_to_user(data.supported_formats,
+			supported_formats,
+			n_supported_formats * sizeof(supported_formats[0])))
+		ret = -EFAULT;
+
+done:
+	kfree(supported_formats);
+	return ret;
+}
+
+static int adf_buffer_import(struct adf_device *dev,
+		struct adf_buffer_config __user *cfg, struct adf_buffer *buf)
+{
+	struct adf_buffer_config user_buf;
+	size_t i;
+	int ret = 0;
+
+	if (copy_from_user(&user_buf, cfg, sizeof(user_buf)))
+		return -EFAULT;
+
+	memset(buf, 0, sizeof(*buf));
+
+	if (user_buf.n_planes > ADF_MAX_PLANES) {
+		dev_err(&dev->base.dev, "invalid plane count %u\n",
+				user_buf.n_planes);
+		return -EINVAL;
+	}
+
+	buf->overlay_engine = idr_find(&dev->overlay_engines,
+			user_buf.overlay_engine);
+	if (!buf->overlay_engine) {
+		dev_err(&dev->base.dev, "invalid overlay engine id %u\n",
+				user_buf.overlay_engine);
+		return -ENOENT;
+	}
+
+	buf->w = user_buf.w;
+	buf->h = user_buf.h;
+	buf->format = user_buf.format;
+	for (i = 0; i < user_buf.n_planes; i++) {
+		buf->dma_bufs[i] = dma_buf_get(user_buf.fd[i]);
+		if (IS_ERR(buf->dma_bufs[i])) {
+			ret = PTR_ERR(buf->dma_bufs[i]);
+			dev_err(&dev->base.dev, "importing dma_buf fd %d failed: %d\n",
+					user_buf.fd[i], ret);
+			buf->dma_bufs[i] = NULL;
+			goto done;
+		}
+		buf->offset[i] = user_buf.offset[i];
+		buf->pitch[i] = user_buf.pitch[i];
+	}
+	buf->n_planes = user_buf.n_planes;
+
+	if (user_buf.acquire_fence >= 0) {
+		buf->acquire_fence = sync_fence_fdget(user_buf.acquire_fence);
+		if (!buf->acquire_fence) {
+			dev_err(&dev->base.dev, "getting fence fd %d failed\n",
+					user_buf.acquire_fence);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+done:
+	if (ret < 0)
+		adf_buffer_cleanup(buf);
+	return ret;
+}
+
+static int adf_device_post_config(struct adf_device *dev,
+		struct adf_post_config __user *arg)
+{
+	struct sync_fence *complete_fence;
+	int complete_fence_fd;
+	struct adf_buffer *bufs = NULL;
+	struct adf_interface **intfs = NULL;
+	struct adf_post_config data;
+	size_t i;
+	void *custom_data = NULL;
+	int ret = 0;
+
+	if (copy_from_user(&data, arg, sizeof(data)))
+		return -EFAULT;
+
+	complete_fence_fd = get_unused_fd_flags(O_CLOEXEC);
+	if (complete_fence_fd < 0)
+		return complete_fence_fd;
+
+	if (data.n_interfaces > ADF_MAX_INTERFACES) {
+		ret = -EINVAL;
+		goto err_get_user;
+	}
+
+	if (data.n_bufs > ADF_MAX_BUFFERS) {
+		ret = -EINVAL;
+		goto err_get_user;
+	}
+
+	if (data.custom_data_size > ADF_MAX_CUSTOM_DATA_SIZE) {
+		ret = -EINVAL;
+		goto err_get_user;
+	}
+
+	if (data.n_interfaces) {
+		intfs = kmalloc(sizeof(intfs[0]) * data.n_interfaces,
+			GFP_KERNEL);
+		if (!intfs) {
+			ret = -ENOMEM;
+			goto err_get_user;
+		}
+	}
+
+	for (i = 0; i < data.n_interfaces; i++) {
+		u32 intf_id;
+		if (get_user(intf_id, &data.interfaces[i])) {
+			ret = -EFAULT;
+			goto err_get_user;
+		}
+
+		intfs[i] = idr_find(&dev->interfaces, intf_id);
+		if (!intfs[i]) {
+			ret = -EINVAL;
+			goto err_get_user;
+		}
+	}
+
+	if (data.n_bufs) {
+		bufs = kzalloc(sizeof(bufs[0]) * data.n_bufs, GFP_KERNEL);
+		if (!bufs) {
+			ret = -ENOMEM;
+			goto err_get_user;
+		}
+	}
+
+	for (i = 0; i < data.n_bufs; i++) {
+		ret = adf_buffer_import(dev, &data.bufs[i], &bufs[i]);
+		if (ret < 0) {
+			memset(&bufs[i], 0, sizeof(bufs[i]));
+			goto err_import;
+		}
+	}
+
+	if (data.custom_data_size) {
+		custom_data = kzalloc(data.custom_data_size, GFP_KERNEL);
+		if (!custom_data) {
+			ret = -ENOMEM;
+			goto err_import;
+		}
+
+		if (copy_from_user(custom_data, data.custom_data,
+				data.custom_data_size)) {
+			ret = -EFAULT;
+			goto err_import;
+		}
+	}
+
+	if (put_user(complete_fence_fd, &arg->complete_fence)) {
+		ret = -EFAULT;
+		goto err_import;
+	}
+
+	complete_fence = adf_device_post_nocopy(dev, intfs, data.n_interfaces,
+			bufs, data.n_bufs, custom_data, data.custom_data_size);
+	if (IS_ERR(complete_fence)) {
+		ret = PTR_ERR(complete_fence);
+		goto err_import;
+	}
+
+	sync_fence_install(complete_fence, complete_fence_fd);
+	return 0;
+
+err_import:
+	for (i = 0; i < data.n_bufs; i++)
+		adf_buffer_cleanup(&bufs[i]);
+
+err_get_user:
+	kfree(custom_data);
+	kfree(bufs);
+	kfree(intfs);
+	put_unused_fd(complete_fence_fd);
+	return ret;
+}
+
+static int adf_intf_simple_post_config(struct adf_interface *intf,
+		struct adf_simple_post_config __user *arg)
+{
+	struct adf_device *dev = intf->base.parent;
+	struct sync_fence *complete_fence;
+	int complete_fence_fd;
+	struct adf_buffer buf;
+	int ret = 0;
+
+	complete_fence_fd = get_unused_fd_flags(O_CLOEXEC);
+	if (complete_fence_fd < 0)
+		return complete_fence_fd;
+
+	ret = adf_buffer_import(dev, &arg->buf, &buf);
+	if (ret < 0)
+		goto err_import;
+
+	if (put_user(complete_fence_fd, &arg->complete_fence)) {
+		ret = -EFAULT;
+		goto err_put_user;
+	}
+
+	complete_fence = adf_interface_simple_post(intf, &buf);
+	if (IS_ERR(complete_fence)) {
+		ret = PTR_ERR(complete_fence);
+		goto err_put_user;
+	}
+
+	sync_fence_install(complete_fence, complete_fence_fd);
+	return 0;
+
+err_put_user:
+	adf_buffer_cleanup(&buf);
+err_import:
+	put_unused_fd(complete_fence_fd);
+	return ret;
+}
+
+static int adf_intf_simple_buffer_alloc(struct adf_interface *intf,
+		struct adf_simple_buffer_alloc __user *arg)
+{
+	struct adf_simple_buffer_alloc data;
+	struct dma_buf *dma_buf;
+	int ret = 0;
+
+	if (copy_from_user(&data, arg, sizeof(data)))
+		return -EFAULT;
+
+	data.fd = get_unused_fd_flags(O_CLOEXEC);
+	if (data.fd < 0)
+		return data.fd;
+
+	ret = adf_interface_simple_buffer_alloc(intf, data.w, data.h,
+			data.format, &dma_buf, &data.offset, &data.pitch);
+	if (ret < 0)
+		goto err_alloc;
+
+	if (copy_to_user(arg, &data, sizeof(*arg))) {
+		ret = -EFAULT;
+		goto err_copy;
+	}
+
+	fd_install(data.fd, dma_buf->file);
+	return 0;
+
+err_copy:
+	dma_buf_put(dma_buf);
+
+err_alloc:
+	put_unused_fd(data.fd);
+	return ret;
+}
+
+static int adf_copy_attachment_list_to_user(
+		struct adf_attachment_config __user *to, size_t n_to,
+		struct adf_attachment *from, size_t n_from)
+{
+	struct adf_attachment_config *temp;
+	size_t n = min(n_to, n_from);
+	size_t i;
+	int ret = 0;
+
+	if (!n)
+		return 0;
+
+	temp = kzalloc(n * sizeof(temp[0]), GFP_KERNEL);
+	if (!temp)
+		return -ENOMEM;
+
+	for (i = 0; i < n; i++) {
+		temp[i].interface = from[i].interface->base.id;
+		temp[i].overlay_engine = from[i].overlay_engine->base.id;
+	}
+
+	if (copy_to_user(to, temp, n * sizeof(to[0]))) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	kfree(temp);
+	return ret;
+}
+
+static int adf_device_get_data(struct adf_device *dev,
+		struct adf_device_data __user *arg)
+{
+	struct adf_device_data data;
+	size_t n_attach;
+	struct adf_attachment *attach = NULL;
+	size_t n_allowed_attach;
+	struct adf_attachment *allowed_attach = NULL;
+	int ret = 0;
+
+	if (copy_from_user(&data, arg, sizeof(data)))
+		return -EFAULT;
+
+	if (data.n_attachments > ADF_MAX_ATTACHMENTS ||
+			data.n_allowed_attachments > ADF_MAX_ATTACHMENTS)
+		return -EINVAL;
+
+	strlcpy(data.name, dev->base.name, sizeof(data.name));
+
+	if (data.n_attachments) {
+		attach = kzalloc(data.n_attachments * sizeof(attach[0]),
+				GFP_KERNEL);
+		if (!attach)
+			return -ENOMEM;
+	}
+	n_attach = adf_device_attachments(dev, attach, data.n_attachments);
+
+	if (data.n_allowed_attachments) {
+		allowed_attach = kzalloc(data.n_allowed_attachments *
+				sizeof(allowed_attach[0]), GFP_KERNEL);
+		if (!allowed_attach) {
+			ret = -ENOMEM;
+			goto done;
+		}
+	}
+	n_allowed_attach = adf_device_attachments_allowed(dev, allowed_attach,
+			data.n_allowed_attachments);
+
+	mutex_lock(&dev->client_lock);
+	ret = adf_obj_copy_custom_data_to_user(&dev->base, data.custom_data,
+			&data.custom_data_size);
+	mutex_unlock(&dev->client_lock);
+
+	if (ret < 0)
+		goto done;
+
+	ret = adf_copy_attachment_list_to_user(data.attachments,
+			data.n_attachments, attach, n_attach);
+	if (ret < 0)
+		goto done;
+
+	ret = adf_copy_attachment_list_to_user(data.allowed_attachments,
+			data.n_allowed_attachments, allowed_attach,
+			n_allowed_attach);
+	if (ret < 0)
+		goto done;
+
+	data.n_attachments = n_attach;
+	data.n_allowed_attachments = n_allowed_attach;
+
+	if (copy_to_user(arg, &data, sizeof(data)))
+		ret = -EFAULT;
+
+done:
+	kfree(allowed_attach);
+	kfree(attach);
+	return ret;
+}
+
+static int adf_device_handle_attachment(struct adf_device *dev,
+		struct adf_attachment_config __user *arg, bool attach)
+{
+	struct adf_attachment_config data;
+	struct adf_overlay_engine *eng;
+	struct adf_interface *intf;
+
+	if (copy_from_user(&data, arg, sizeof(data)))
+		return -EFAULT;
+
+	eng = idr_find(&dev->overlay_engines, data.overlay_engine);
+	if (!eng) {
+		dev_err(&dev->base.dev, "invalid overlay engine id %u\n",
+				data.overlay_engine);
+		return -EINVAL;
+	}
+
+	intf = idr_find(&dev->interfaces, data.interface);
+	if (!intf) {
+		dev_err(&dev->base.dev, "invalid interface id %u\n",
+				data.interface);
+		return -EINVAL;
+	}
+
+	if (attach)
+		return adf_device_attach(dev, eng, intf);
+	else
+		return adf_device_detach(dev, eng, intf);
+}
+
+static int adf_intf_set_mode(struct adf_interface *intf,
+		struct drm_mode_modeinfo __user *arg)
+{
+	struct drm_mode_modeinfo mode;
+
+	if (copy_from_user(&mode, arg, sizeof(mode)))
+		return -EFAULT;
+
+	return adf_interface_set_mode(intf, &mode);
+}
+
+static int adf_intf_get_data(struct adf_interface *intf,
+		struct adf_interface_data __user *arg)
+{
+	struct adf_device *dev = adf_interface_parent(intf);
+	struct adf_interface_data data;
+	struct drm_mode_modeinfo *modelist;
+	size_t modelist_size;
+	int err;
+	int ret = 0;
+	unsigned long flags;
+
+	if (copy_from_user(&data, arg, sizeof(data)))
+		return -EFAULT;
+
+	strlcpy(data.name, intf->base.name, sizeof(data.name));
+
+	data.type = intf->type;
+	data.id = intf->idx;
+	data.flags = intf->flags;
+
+	err = adf_interface_get_screen_size(intf, &data.width_mm,
+			&data.height_mm);
+	if (err < 0) {
+		data.width_mm = 0;
+		data.height_mm = 0;
+	}
+
+	modelist = kmalloc(sizeof(modelist[0]) * ADF_MAX_MODES, GFP_KERNEL);
+	if (!modelist)
+		return -ENOMEM;
+
+	mutex_lock(&dev->client_lock);
+	read_lock_irqsave(&intf->hotplug_modelist_lock, flags);
+	data.hotplug_detect = intf->hotplug_detect;
+	modelist_size = min(data.n_available_modes, intf->n_modes) *
+			sizeof(intf->modelist[0]);
+	memcpy(modelist, intf->modelist, modelist_size);
+	data.n_available_modes = intf->n_modes;
+	read_unlock_irqrestore(&intf->hotplug_modelist_lock, flags);
+
+	if (copy_to_user(data.available_modes, modelist, modelist_size)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data.dpms_state = intf->dpms_state;
+	memcpy(&data.current_mode, &intf->current_mode,
+			sizeof(intf->current_mode));
+
+	ret = adf_obj_copy_custom_data_to_user(&intf->base, data.custom_data,
+			&data.custom_data_size);
+done:
+	mutex_unlock(&dev->client_lock);
+	kfree(modelist);
+
+	if (ret < 0)
+		return ret;
+
+	if (copy_to_user(arg, &data, sizeof(data)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+static inline long adf_obj_custom_ioctl(struct adf_obj *obj, unsigned int cmd,
+		unsigned long arg)
+{
+	if (obj->ops && obj->ops->ioctl)
+		return obj->ops->ioctl(obj, cmd, arg);
+	return -ENOTTY;
+}
+
+static long adf_overlay_engine_ioctl(struct adf_overlay_engine *eng,
+		struct adf_file *file, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case ADF_SET_EVENT:
+		return adf_obj_set_event(&eng->base, file,
+				(struct adf_set_event __user *)arg);
+
+	case ADF_GET_OVERLAY_ENGINE_DATA:
+		return adf_eng_get_data(eng,
+			(struct adf_overlay_engine_data __user *)arg);
+
+	case ADF_BLANK:
+	case ADF_POST_CONFIG:
+	case ADF_SET_MODE:
+	case ADF_GET_DEVICE_DATA:
+	case ADF_GET_INTERFACE_DATA:
+	case ADF_SIMPLE_POST_CONFIG:
+	case ADF_SIMPLE_BUFFER_ALLOC:
+	case ADF_ATTACH:
+	case ADF_DETACH:
+		return -EINVAL;
+
+	default:
+		return adf_obj_custom_ioctl(&eng->base, cmd, arg);
+	}
+}
+
+static long adf_interface_ioctl(struct adf_interface *intf,
+		struct adf_file *file, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case ADF_SET_EVENT:
+		return adf_obj_set_event(&intf->base, file,
+				(struct adf_set_event __user *)arg);
+
+	case ADF_BLANK:
+		return adf_interface_blank(intf, arg);
+
+	case ADF_SET_MODE:
+		return adf_intf_set_mode(intf,
+				(struct drm_mode_modeinfo __user *)arg);
+
+	case ADF_GET_INTERFACE_DATA:
+		return adf_intf_get_data(intf,
+				(struct adf_interface_data __user *)arg);
+
+	case ADF_SIMPLE_POST_CONFIG:
+		return adf_intf_simple_post_config(intf,
+				(struct adf_simple_post_config __user *)arg);
+
+	case ADF_SIMPLE_BUFFER_ALLOC:
+		return adf_intf_simple_buffer_alloc(intf,
+				(struct adf_simple_buffer_alloc __user *)arg);
+
+	case ADF_POST_CONFIG:
+	case ADF_GET_DEVICE_DATA:
+	case ADF_GET_OVERLAY_ENGINE_DATA:
+	case ADF_ATTACH:
+	case ADF_DETACH:
+		return -EINVAL;
+
+	default:
+		return adf_obj_custom_ioctl(&intf->base, cmd, arg);
+	}
+}
+
+static long adf_device_ioctl(struct adf_device *dev, struct adf_file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case ADF_SET_EVENT:
+		return adf_obj_set_event(&dev->base, file,
+				(struct adf_set_event __user *)arg);
+
+	case ADF_POST_CONFIG:
+		return adf_device_post_config(dev,
+				(struct adf_post_config __user *)arg);
+
+	case ADF_GET_DEVICE_DATA:
+		return adf_device_get_data(dev,
+				(struct adf_device_data __user *)arg);
+
+	case ADF_ATTACH:
+		return adf_device_handle_attachment(dev,
+				(struct adf_attachment_config __user *)arg,
+				true);
+
+	case ADF_DETACH:
+		return adf_device_handle_attachment(dev,
+				(struct adf_attachment_config __user *)arg,
+				false);
+
+	case ADF_BLANK:
+	case ADF_SET_MODE:
+	case ADF_GET_INTERFACE_DATA:
+	case ADF_GET_OVERLAY_ENGINE_DATA:
+	case ADF_SIMPLE_POST_CONFIG:
+	case ADF_SIMPLE_BUFFER_ALLOC:
+		return -EINVAL;
+
+	default:
+		return adf_obj_custom_ioctl(&dev->base, cmd, arg);
+	}
+}
+
+static int adf_file_open(struct inode *inode, struct file *file)
+{
+	struct adf_obj *obj;
+	struct adf_file *fpriv = NULL;
+	unsigned long flags;
+	int ret = 0;
+
+	obj = adf_obj_sysfs_find(iminor(inode));
+	if (!obj)
+		return -ENODEV;
+
+	dev_dbg(&obj->dev, "opening %s\n", dev_name(&obj->dev));
+
+	if (!try_module_get(obj->parent->ops->owner)) {
+		dev_err(&obj->dev, "getting owner module failed\n");
+		return -ENODEV;
+	}
+
+	fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
+	if (!fpriv) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	INIT_LIST_HEAD(&fpriv->head);
+	fpriv->obj = obj;
+	init_waitqueue_head(&fpriv->event_wait);
+
+	file->private_data = fpriv;
+
+	if (obj->ops && obj->ops->open) {
+		ret = obj->ops->open(obj, inode, file);
+		if (ret < 0)
+			goto done;
+	}
+
+	spin_lock_irqsave(&obj->file_lock, flags);
+	list_add_tail(&fpriv->head, &obj->file_list);
+	spin_unlock_irqrestore(&obj->file_lock, flags);
+
+done:
+	if (ret < 0) {
+		kfree(fpriv);
+		module_put(obj->parent->ops->owner);
+	}
+	return ret;
+}
+
+static int adf_file_release(struct inode *inode, struct file *file)
+{
+	struct adf_file *fpriv = file->private_data;
+	struct adf_obj *obj = fpriv->obj;
+	enum adf_event_type event_type;
+	unsigned long flags;
+
+	if (obj->ops && obj->ops->release)
+		obj->ops->release(obj, inode, file);
+
+	spin_lock_irqsave(&obj->file_lock, flags);
+	list_del(&fpriv->head);
+	spin_unlock_irqrestore(&obj->file_lock, flags);
+
+	for_each_set_bit(event_type, fpriv->event_subscriptions,
+			ADF_EVENT_TYPE_MAX) {
+		adf_event_put(obj, event_type);
+	}
+
+	kfree(fpriv);
+	module_put(obj->parent->ops->owner);
+
+	dev_dbg(&obj->dev, "released %s\n", dev_name(&obj->dev));
+	return 0;
+}
+
+long adf_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct adf_file *fpriv = file->private_data;
+	struct adf_obj *obj = fpriv->obj;
+	long ret = -EINVAL;
+
+	dev_dbg(&obj->dev, "%s ioctl %u\n", dev_name(&obj->dev), _IOC_NR(cmd));
+
+	switch (obj->type) {
+	case ADF_OBJ_OVERLAY_ENGINE:
+		ret = adf_overlay_engine_ioctl(adf_obj_to_overlay_engine(obj),
+				fpriv, cmd, arg);
+		break;
+
+	case ADF_OBJ_INTERFACE:
+		ret = adf_interface_ioctl(adf_obj_to_interface(obj), fpriv, cmd,
+				arg);
+		break;
+
+	case ADF_OBJ_DEVICE:
+		ret = adf_device_ioctl(adf_obj_to_device(obj), fpriv, cmd, arg);
+		break;
+	}
+
+	return ret;
+}
+
+static inline bool adf_file_event_available(struct adf_file *fpriv)
+{
+	int head = fpriv->event_head;
+	int tail = fpriv->event_tail;
+	return CIRC_CNT(head, tail, sizeof(fpriv->event_buf)) != 0;
+}
+
+void adf_file_queue_event(struct adf_file *fpriv, struct adf_event *event)
+{
+	int head = fpriv->event_head;
+	int tail = fpriv->event_tail;
+	size_t space = CIRC_SPACE(head, tail, sizeof(fpriv->event_buf));
+	size_t space_to_end =
+			CIRC_SPACE_TO_END(head, tail, sizeof(fpriv->event_buf));
+
+	if (space < event->length) {
+		dev_dbg(&fpriv->obj->dev,
+				"insufficient buffer space for event %u\n",
+				event->type);
+		return;
+	}
+
+	if (space_to_end >= event->length) {
+		memcpy(fpriv->event_buf + head, event, event->length);
+	} else {
+		memcpy(fpriv->event_buf + head, event, space_to_end);
+		memcpy(fpriv->event_buf, (u8 *)event + space_to_end,
+				event->length - space_to_end);
+	}
+
+	smp_wmb();
+	fpriv->event_head = (fpriv->event_head + event->length) &
+			(sizeof(fpriv->event_buf) - 1);
+	wake_up_interruptible_all(&fpriv->event_wait);
+}
+
+static ssize_t adf_file_copy_to_user(struct adf_file *fpriv,
+		char __user *buffer, size_t buffer_size)
+{
+	int head, tail;
+	u8 *event_buf;
+	size_t cnt, cnt_to_end, copy_size = 0;
+	ssize_t ret = 0;
+	unsigned long flags;
+
+	event_buf = kmalloc(min(buffer_size, sizeof(fpriv->event_buf)),
+			GFP_KERNEL);
+	if (!event_buf)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&fpriv->obj->file_lock, flags);
+
+	if (!adf_file_event_available(fpriv))
+		goto out;
+
+	head = fpriv->event_head;
+	tail = fpriv->event_tail;
+
+	cnt = CIRC_CNT(head, tail, sizeof(fpriv->event_buf));
+	cnt_to_end = CIRC_CNT_TO_END(head, tail, sizeof(fpriv->event_buf));
+	copy_size = min(buffer_size, cnt);
+
+	if (cnt_to_end >= copy_size) {
+		memcpy(event_buf, fpriv->event_buf + tail, copy_size);
+	} else {
+		memcpy(event_buf, fpriv->event_buf + tail, cnt_to_end);
+		memcpy(event_buf + cnt_to_end, fpriv->event_buf,
+				copy_size - cnt_to_end);
+	}
+
+	fpriv->event_tail = (fpriv->event_tail + copy_size) &
+			(sizeof(fpriv->event_buf) - 1);
+
+out:
+	spin_unlock_irqrestore(&fpriv->obj->file_lock, flags);
+	if (copy_size) {
+		if (copy_to_user(buffer, event_buf, copy_size))
+			ret = -EFAULT;
+		else
+			ret = copy_size;
+	}
+	kfree(event_buf);
+	return ret;
+}
+
+ssize_t adf_file_read(struct file *filp, char __user *buffer,
+		 size_t count, loff_t *offset)
+{
+	struct adf_file *fpriv = filp->private_data;
+	int err;
+
+	err = wait_event_interruptible(fpriv->event_wait,
+			adf_file_event_available(fpriv));
+	if (err < 0)
+		return err;
+
+	return adf_file_copy_to_user(fpriv, buffer, count);
+}
+
+unsigned int adf_file_poll(struct file *filp, struct poll_table_struct *wait)
+{
+	struct adf_file *fpriv = filp->private_data;
+	unsigned int mask = 0;
+
+	poll_wait(filp, &fpriv->event_wait, wait);
+
+	if (adf_file_event_available(fpriv))
+		mask |= POLLIN | POLLRDNORM;
+
+	return mask;
+}
+
+const struct file_operations adf_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = adf_file_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = adf_file_compat_ioctl,
+#endif
+	.open = adf_file_open,
+	.release = adf_file_release,
+	.llseek = default_llseek,
+	.read = adf_file_read,
+	.poll = adf_file_poll,
+};
diff --git a/drivers/video/adf/adf_fops.h b/drivers/video/adf/adf_fops.h
new file mode 100644
index 0000000..90a3a74
--- /dev/null
+++ b/drivers/video/adf/adf_fops.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __VIDEO_ADF_ADF_FOPS_H
+#define __VIDEO_ADF_ADF_FOPS_H
+
+#include <linux/bitmap.h>
+#include <linux/fs.h>
+
+extern const struct file_operations adf_fops;
+
+struct adf_file {
+	struct list_head head;
+	struct adf_obj *obj;
+
+	DECLARE_BITMAP(event_subscriptions, ADF_EVENT_TYPE_MAX);
+	u8 event_buf[4096];
+	int event_head;
+	int event_tail;
+	wait_queue_head_t event_wait;
+};
+
+void adf_file_queue_event(struct adf_file *file, struct adf_event *event);
+long adf_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+
+#endif /* __VIDEO_ADF_ADF_FOPS_H */
diff --git a/drivers/video/adf/adf_fops32.c b/drivers/video/adf/adf_fops32.c
new file mode 100644
index 0000000..d299a81
--- /dev/null
+++ b/drivers/video/adf/adf_fops32.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/uaccess.h>
+#include <video/adf.h>
+
+#include "adf_fops.h"
+#include "adf_fops32.h"
+
+long adf_compat_post_config(struct file *file,
+		struct adf_post_config32 __user *arg)
+{
+	struct adf_post_config32 cfg32;
+	struct adf_post_config __user *cfg;
+	int ret;
+
+	if (copy_from_user(&cfg32, arg, sizeof(cfg32)))
+		return -EFAULT;
+
+	cfg = compat_alloc_user_space(sizeof(*cfg));
+	if (!access_ok(VERIFY_WRITE, cfg, sizeof(*cfg)))
+		return -EFAULT;
+
+	if (put_user(cfg32.n_interfaces, &cfg->n_interfaces) ||
+			put_user(compat_ptr(cfg32.interfaces),
+					&cfg->interfaces) ||
+			put_user(cfg32.n_bufs, &cfg->n_bufs) ||
+			put_user(compat_ptr(cfg32.bufs), &cfg->bufs) ||
+			put_user(cfg32.custom_data_size,
+					&cfg->custom_data_size) ||
+			put_user(compat_ptr(cfg32.custom_data),
+					&cfg->custom_data))
+		return -EFAULT;
+
+	ret = adf_file_ioctl(file, ADF_POST_CONFIG, (unsigned long)cfg);
+	if (ret < 0)
+		return ret;
+
+	if (copy_in_user(&arg->complete_fence, &cfg->complete_fence,
+			sizeof(cfg->complete_fence)))
+		return -EFAULT;
+
+	return 0;
+}
+
+long adf_compat_get_device_data(struct file *file,
+		struct adf_device_data32 __user *arg)
+{
+	struct adf_device_data32 data32;
+	struct adf_device_data __user *data;
+	int ret;
+
+	if (copy_from_user(&data32, arg, sizeof(data32)))
+		return -EFAULT;
+
+	data = compat_alloc_user_space(sizeof(*data));
+	if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
+		return -EFAULT;
+
+	if (put_user(data32.n_attachments, &data->n_attachments) ||
+			put_user(compat_ptr(data32.attachments),
+					&data->attachments) ||
+			put_user(data32.n_allowed_attachments,
+					&data->n_allowed_attachments) ||
+			put_user(compat_ptr(data32.allowed_attachments),
+					&data->allowed_attachments) ||
+			put_user(data32.custom_data_size,
+					&data->custom_data_size) ||
+			put_user(compat_ptr(data32.custom_data),
+					&data->custom_data))
+		return -EFAULT;
+
+	ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA, (unsigned long)data);
+	if (ret < 0)
+		return ret;
+
+	if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
+			copy_in_user(&arg->n_attachments, &data->n_attachments,
+					sizeof(arg->n_attachments)) ||
+			copy_in_user(&arg->n_allowed_attachments,
+					&data->n_allowed_attachments,
+					sizeof(arg->n_allowed_attachments)) ||
+			copy_in_user(&arg->custom_data_size,
+					&data->custom_data_size,
+					sizeof(arg->custom_data_size)))
+		return -EFAULT;
+
+	return 0;
+}
+
+long adf_compat_get_interface_data(struct file *file,
+		struct adf_interface_data32 __user *arg)
+{
+	struct adf_interface_data32 data32;
+	struct adf_interface_data __user *data;
+	int ret;
+
+	if (copy_from_user(&data32, arg, sizeof(data32)))
+		return -EFAULT;
+
+	data = compat_alloc_user_space(sizeof(*data));
+	if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
+		return -EFAULT;
+
+	if (put_user(data32.n_available_modes, &data->n_available_modes) ||
+			put_user(compat_ptr(data32.available_modes),
+					&data->available_modes) ||
+			put_user(data32.custom_data_size,
+					&data->custom_data_size) ||
+			put_user(compat_ptr(data32.custom_data),
+					&data->custom_data))
+		return -EFAULT;
+
+	ret = adf_file_ioctl(file, ADF_GET_INTERFACE_DATA, (unsigned long)data);
+	if (ret < 0)
+		return ret;
+
+	if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
+			copy_in_user(&arg->type, &data->type,
+					sizeof(arg->type)) ||
+			copy_in_user(&arg->id, &data->id, sizeof(arg->id)) ||
+			copy_in_user(&arg->flags, &data->flags,
+					sizeof(arg->flags)) ||
+			copy_in_user(&arg->dpms_state, &data->dpms_state,
+					sizeof(arg->dpms_state)) ||
+			copy_in_user(&arg->hotplug_detect,
+					&data->hotplug_detect,
+					sizeof(arg->hotplug_detect)) ||
+			copy_in_user(&arg->width_mm, &data->width_mm,
+					sizeof(arg->width_mm)) ||
+			copy_in_user(&arg->height_mm, &data->height_mm,
+					sizeof(arg->height_mm)) ||
+			copy_in_user(&arg->current_mode, &data->current_mode,
+					sizeof(arg->current_mode)) ||
+			copy_in_user(&arg->n_available_modes,
+					&data->n_available_modes,
+					sizeof(arg->n_available_modes)) ||
+			copy_in_user(&arg->custom_data_size,
+					&data->custom_data_size,
+					sizeof(arg->custom_data_size)))
+		return -EFAULT;
+
+	return 0;
+}
+
+long adf_compat_get_overlay_engine_data(struct file *file,
+		struct adf_overlay_engine_data32 __user *arg)
+{
+	struct adf_overlay_engine_data32 data32;
+	struct adf_overlay_engine_data __user *data;
+	int ret;
+
+	if (copy_from_user(&data32, arg, sizeof(data32)))
+		return -EFAULT;
+
+	data = compat_alloc_user_space(sizeof(*data));
+	if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
+		return -EFAULT;
+
+	if (put_user(data32.n_supported_formats, &data->n_supported_formats) ||
+			put_user(compat_ptr(data32.supported_formats),
+					&data->supported_formats) ||
+			put_user(data32.custom_data_size,
+					&data->custom_data_size) ||
+			put_user(compat_ptr(data32.custom_data),
+					&data->custom_data))
+		return -EFAULT;
+
+	ret = adf_file_ioctl(file, ADF_GET_OVERLAY_ENGINE_DATA,
+			(unsigned long)data);
+	if (ret < 0)
+		return ret;
+
+	if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
+			copy_in_user(&arg->n_supported_formats,
+					&data->n_supported_formats,
+					sizeof(arg->n_supported_formats)) ||
+			copy_in_user(&arg->custom_data_size,
+					&data->custom_data_size,
+					sizeof(arg->custom_data_size)))
+		return -EFAULT;
+
+	return 0;
+}
+
+long adf_file_compat_ioctl(struct file *file, unsigned int cmd,
+		unsigned long arg)
+{
+	switch (cmd) {
+	case ADF_POST_CONFIG32:
+		return adf_compat_post_config(file, compat_ptr(arg));
+
+	case ADF_GET_DEVICE_DATA32:
+		return adf_compat_get_device_data(file, compat_ptr(arg));
+
+	case ADF_GET_INTERFACE_DATA32:
+		return adf_compat_get_interface_data(file, compat_ptr(arg));
+
+	case ADF_GET_OVERLAY_ENGINE_DATA32:
+		return adf_compat_get_overlay_engine_data(file,
+				compat_ptr(arg));
+
+	default:
+		return adf_file_ioctl(file, cmd, arg);
+	}
+}
diff --git a/drivers/video/adf/adf_fops32.h b/drivers/video/adf/adf_fops32.h
new file mode 100644
index 0000000..64034ce
--- /dev/null
+++ b/drivers/video/adf/adf_fops32.h
@@ -0,0 +1,78 @@
+#ifndef __VIDEO_ADF_ADF_FOPS32_H
+#define __VIDEO_ADF_ADF_FOPS32_H
+
+#include <linux/compat.h>
+#include <linux/ioctl.h>
+
+#include <video/adf.h>
+
+#define ADF_POST_CONFIG32 \
+		_IOW(ADF_IOCTL_TYPE, 2, struct adf_post_config32)
+#define ADF_GET_DEVICE_DATA32 \
+		_IOR(ADF_IOCTL_TYPE, 4, struct adf_device_data32)
+#define ADF_GET_INTERFACE_DATA32 \
+		_IOR(ADF_IOCTL_TYPE, 5, struct adf_interface_data32)
+#define ADF_GET_OVERLAY_ENGINE_DATA32 \
+		_IOR(ADF_IOCTL_TYPE, 6, struct adf_overlay_engine_data32)
+
+struct adf_post_config32 {
+	compat_size_t n_interfaces;
+	compat_uptr_t interfaces;
+
+	compat_size_t n_bufs;
+	compat_uptr_t bufs;
+
+	compat_size_t custom_data_size;
+	compat_uptr_t custom_data;
+
+	__s32 complete_fence;
+};
+
+struct adf_device_data32 {
+	char name[ADF_NAME_LEN];
+
+	compat_size_t n_attachments;
+	compat_uptr_t attachments;
+
+	compat_size_t n_allowed_attachments;
+	compat_uptr_t allowed_attachments;
+
+	compat_size_t custom_data_size;
+	compat_uptr_t custom_data;
+};
+
+struct adf_interface_data32 {
+	char name[ADF_NAME_LEN];
+
+	__u8 type;
+	__u32 id;
+	/* e.g. type=ADF_INTF_TYPE_DSI, id=1 => DSI.1 */
+	__u32 flags;
+
+	__u8 dpms_state;
+	__u8 hotplug_detect;
+	__u16 width_mm;
+	__u16 height_mm;
+
+	struct drm_mode_modeinfo current_mode;
+	compat_size_t n_available_modes;
+	compat_uptr_t available_modes;
+
+	compat_size_t custom_data_size;
+	compat_uptr_t custom_data;
+};
+
+struct adf_overlay_engine_data32 {
+	char name[ADF_NAME_LEN];
+
+	compat_size_t n_supported_formats;
+	compat_uptr_t supported_formats;
+
+	compat_size_t custom_data_size;
+	compat_uptr_t custom_data;
+};
+
+long adf_file_compat_ioctl(struct file *file, unsigned int cmd,
+		unsigned long arg);
+
+#endif /* __VIDEO_ADF_ADF_FOPS32_H */
diff --git a/drivers/video/adf/adf_format.c b/drivers/video/adf/adf_format.c
new file mode 100644
index 0000000..e3f22c7
--- /dev/null
+++ b/drivers/video/adf/adf_format.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ * modified from drivers/gpu/drm/drm_crtc.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <drm/drm_fourcc.h>
+#include <video/adf_format.h>
+
+bool adf_format_is_standard(u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB332:
+	case DRM_FORMAT_BGR233:
+	case DRM_FORMAT_XRGB4444:
+	case DRM_FORMAT_XBGR4444:
+	case DRM_FORMAT_RGBX4444:
+	case DRM_FORMAT_BGRX4444:
+	case DRM_FORMAT_ARGB4444:
+	case DRM_FORMAT_ABGR4444:
+	case DRM_FORMAT_RGBA4444:
+	case DRM_FORMAT_BGRA4444:
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_XBGR1555:
+	case DRM_FORMAT_RGBX5551:
+	case DRM_FORMAT_BGRX5551:
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_ABGR1555:
+	case DRM_FORMAT_RGBA5551:
+	case DRM_FORMAT_BGRA5551:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_BGRX8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_BGRA8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_BGRA1010102:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_AYUV:
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+	case DRM_FORMAT_YUV411:
+	case DRM_FORMAT_YVU411:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		return true;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(adf_format_is_standard);
+
+bool adf_format_is_rgb(u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB332:
+	case DRM_FORMAT_BGR233:
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_XBGR1555:
+	case DRM_FORMAT_RGBX5551:
+	case DRM_FORMAT_BGRX5551:
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_ABGR1555:
+	case DRM_FORMAT_RGBA5551:
+	case DRM_FORMAT_BGRA5551:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_BGRX8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_BGRA1010102:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_BGRA8888:
+		return true;
+
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(adf_format_is_rgb);
+
+u8 adf_format_num_planes(u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+	case DRM_FORMAT_YUV411:
+	case DRM_FORMAT_YVU411:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		return 3;
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		return 2;
+	default:
+		return 1;
+	}
+}
+EXPORT_SYMBOL(adf_format_num_planes);
+
+u8 adf_format_bpp(u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB332:
+	case DRM_FORMAT_BGR233:
+		return 8;
+
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_XBGR1555:
+	case DRM_FORMAT_RGBX5551:
+	case DRM_FORMAT_BGRX5551:
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_ABGR1555:
+	case DRM_FORMAT_RGBA5551:
+	case DRM_FORMAT_BGRA5551:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		return 16;
+
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		return 24;
+
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_BGRX8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_BGRA1010102:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_BGRA8888:
+		return 32;
+
+	default:
+		pr_debug("%s: unsupported pixel format %u\n", __func__, format);
+		return 0;
+	}
+}
+EXPORT_SYMBOL(adf_format_bpp);
+
+u8 adf_format_plane_cpp(u32 format, int plane)
+{
+	if (plane >= adf_format_num_planes(format))
+		return 0;
+
+	switch (format) {
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+		return 2;
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		return plane ? 2 : 1;
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+	case DRM_FORMAT_YUV411:
+	case DRM_FORMAT_YVU411:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		return 1;
+	default:
+		return adf_format_bpp(format) / 8;
+	}
+}
+EXPORT_SYMBOL(adf_format_plane_cpp);
+
+u8 adf_format_horz_chroma_subsampling(u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_YUV411:
+	case DRM_FORMAT_YVU411:
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+		return 4;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+		return 2;
+	default:
+		return 1;
+	}
+}
+EXPORT_SYMBOL(adf_format_horz_chroma_subsampling);
+
+u8 adf_format_vert_chroma_subsampling(u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+		return 4;
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+		return 2;
+	default:
+		return 1;
+	}
+}
+EXPORT_SYMBOL(adf_format_vert_chroma_subsampling);
diff --git a/drivers/video/adf/adf_memblock.c b/drivers/video/adf/adf_memblock.c
new file mode 100644
index 0000000..285218a
--- /dev/null
+++ b/drivers/video/adf/adf_memblock.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/dma-buf.h>
+#include <linux/highmem.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+
+struct adf_memblock_pdata {
+	phys_addr_t base;
+};
+
+static struct sg_table *adf_memblock_map(struct dma_buf_attachment *attach,
+		enum dma_data_direction direction)
+{
+	struct adf_memblock_pdata *pdata = attach->dmabuf->priv;
+	unsigned long pfn = PFN_DOWN(pdata->base);
+	struct page *page = pfn_to_page(pfn);
+	struct sg_table *table;
+	int nents, ret;
+
+	table = kzalloc(sizeof(*table), GFP_KERNEL);
+	if (!table)
+		return ERR_PTR(-ENOMEM);
+
+	ret = sg_alloc_table(table, 1, GFP_KERNEL);
+	if (ret < 0)
+		goto err_alloc;
+
+	sg_set_page(table->sgl, page, attach->dmabuf->size, 0);
+
+	nents = dma_map_sg(attach->dev, table->sgl, 1, direction);
+	if (!nents) {
+		ret = -EINVAL;
+		goto err_map;
+	}
+
+	return table;
+
+err_map:
+	sg_free_table(table);
+err_alloc:
+	kfree(table);
+	return ERR_PTR(ret);
+}
+
+static void adf_memblock_unmap(struct dma_buf_attachment *attach,
+		struct sg_table *table, enum dma_data_direction direction)
+{
+	dma_unmap_sg(attach->dev, table->sgl, 1, direction);
+	sg_free_table(table);
+}
+
+static void __init_memblock adf_memblock_release(struct dma_buf *buf)
+{
+	struct adf_memblock_pdata *pdata = buf->priv;
+	int err = memblock_free(pdata->base, buf->size);
+
+	if (err < 0)
+		pr_warn("%s: freeing memblock failed: %d\n", __func__, err);
+	kfree(pdata);
+}
+
+static void *adf_memblock_do_kmap(struct dma_buf *buf, unsigned long pgoffset,
+		bool atomic)
+{
+	struct adf_memblock_pdata *pdata = buf->priv;
+	unsigned long pfn = PFN_DOWN(pdata->base) + pgoffset;
+	struct page *page = pfn_to_page(pfn);
+
+	if (atomic)
+		return kmap_atomic(page);
+	else
+		return kmap(page);
+}
+
+static void *adf_memblock_kmap_atomic(struct dma_buf *buf,
+		unsigned long pgoffset)
+{
+	return adf_memblock_do_kmap(buf, pgoffset, true);
+}
+
+static void adf_memblock_kunmap_atomic(struct dma_buf *buf,
+		unsigned long pgoffset, void *vaddr)
+{
+	kunmap_atomic(vaddr);
+}
+
+static void *adf_memblock_kmap(struct dma_buf *buf, unsigned long pgoffset)
+{
+	return adf_memblock_do_kmap(buf, pgoffset, false);
+}
+
+static void adf_memblock_kunmap(struct dma_buf *buf, unsigned long pgoffset,
+		void *vaddr)
+{
+	kunmap(vaddr);
+}
+
+static int adf_memblock_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
+{
+	struct adf_memblock_pdata *pdata = buf->priv;
+
+	return remap_pfn_range(vma, vma->vm_start, PFN_DOWN(pdata->base),
+			vma->vm_end - vma->vm_start, vma->vm_page_prot);
+}
+
+struct dma_buf_ops adf_memblock_ops = {
+	.map_dma_buf = adf_memblock_map,
+	.unmap_dma_buf = adf_memblock_unmap,
+	.release = adf_memblock_release,
+	.kmap_atomic = adf_memblock_kmap_atomic,
+	.kunmap_atomic = adf_memblock_kunmap_atomic,
+	.kmap = adf_memblock_kmap,
+	.kunmap = adf_memblock_kunmap,
+	.mmap = adf_memblock_mmap,
+};
+
+/**
+ * adf_memblock_export - export a memblock reserved area as a dma-buf
+ *
+ * @base: base physical address
+ * @size: memblock size
+ * @flags: mode flags for the dma-buf's file
+ *
+ * @base and @size must be page-aligned.
+ *
+ * Returns a dma-buf on success or ERR_PTR(-errno) on failure.
+ */
+struct dma_buf *adf_memblock_export(phys_addr_t base, size_t size, int flags)
+{
+	struct adf_memblock_pdata *pdata;
+	struct dma_buf *buf;
+	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+	if (PAGE_ALIGN(base) != base || PAGE_ALIGN(size) != size)
+		return ERR_PTR(-EINVAL);
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	pdata->base = base;
+	exp_info.ops = &adf_memblock_ops;
+	exp_info.size = size;
+	exp_info.flags = flags;
+	exp_info.priv = pdata;
+
+	buf = dma_buf_export(&exp_info);
+	if (IS_ERR(buf))
+		kfree(pdata);
+
+	return buf;
+}
+EXPORT_SYMBOL(adf_memblock_export);
diff --git a/drivers/video/adf/adf_sysfs.c b/drivers/video/adf/adf_sysfs.c
new file mode 100644
index 0000000..8c659c7
--- /dev/null
+++ b/drivers/video/adf/adf_sysfs.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <video/adf_client.h>
+
+#include "adf.h"
+#include "adf_fops.h"
+#include "adf_sysfs.h"
+
+static struct class *adf_class;
+static int adf_major;
+static DEFINE_IDR(adf_minors);
+
+#define dev_to_adf_interface(p) \
+	adf_obj_to_interface(container_of(p, struct adf_obj, dev))
+
+static ssize_t dpms_state_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct adf_interface *intf = dev_to_adf_interface(dev);
+	return scnprintf(buf, PAGE_SIZE, "%u\n",
+			adf_interface_dpms_state(intf));
+}
+
+static ssize_t dpms_state_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct adf_interface *intf = dev_to_adf_interface(dev);
+	u8 dpms_state;
+	int err;
+
+	err = kstrtou8(buf, 0, &dpms_state);
+	if (err < 0)
+		return err;
+
+	err = adf_interface_blank(intf, dpms_state);
+	if (err < 0)
+		return err;
+
+	return count;
+}
+
+static ssize_t current_mode_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct adf_interface *intf = dev_to_adf_interface(dev);
+	struct drm_mode_modeinfo mode;
+
+	adf_interface_current_mode(intf, &mode);
+
+	if (mode.name[0]) {
+		return scnprintf(buf, PAGE_SIZE, "%s\n", mode.name);
+	} else {
+		bool interlaced = !!(mode.flags & DRM_MODE_FLAG_INTERLACE);
+		return scnprintf(buf, PAGE_SIZE, "%ux%u%s\n", mode.hdisplay,
+				mode.vdisplay, interlaced ? "i" : "");
+	}
+}
+
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct adf_interface *intf = dev_to_adf_interface(dev);
+	return scnprintf(buf, PAGE_SIZE, "%s\n",
+			adf_interface_type_str(intf));
+}
+
+static ssize_t vsync_timestamp_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct adf_interface *intf = dev_to_adf_interface(dev);
+	ktime_t timestamp;
+	unsigned long flags;
+
+	read_lock_irqsave(&intf->vsync_lock, flags);
+	memcpy(&timestamp, &intf->vsync_timestamp, sizeof(timestamp));
+	read_unlock_irqrestore(&intf->vsync_lock, flags);
+
+	return scnprintf(buf, PAGE_SIZE, "%llu\n", ktime_to_ns(timestamp));
+}
+
+static ssize_t hotplug_detect_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct adf_interface *intf = dev_to_adf_interface(dev);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", intf->hotplug_detect);
+}
+
+static struct device_attribute adf_interface_attrs[] = {
+	__ATTR(dpms_state, S_IRUGO|S_IWUSR, dpms_state_show, dpms_state_store),
+	__ATTR_RO(current_mode),
+	__ATTR_RO(hotplug_detect),
+	__ATTR_RO(type),
+	__ATTR_RO(vsync_timestamp),
+};
+
+int adf_obj_sysfs_init(struct adf_obj *obj, struct device *parent)
+{
+	int ret = idr_alloc(&adf_minors, obj, 0, 0, GFP_KERNEL);
+	if (ret < 0) {
+		pr_err("%s: allocating adf minor failed: %d\n", __func__,
+				ret);
+		return ret;
+	}
+
+	obj->minor = ret;
+	obj->dev.parent = parent;
+	obj->dev.class = adf_class;
+	obj->dev.devt = MKDEV(adf_major, obj->minor);
+
+	ret = device_register(&obj->dev);
+	if (ret < 0) {
+		pr_err("%s: registering adf object failed: %d\n", __func__,
+				ret);
+		goto err_device_register;
+	}
+
+	return 0;
+
+err_device_register:
+	idr_remove(&adf_minors, obj->minor);
+	return ret;
+}
+
+static char *adf_device_devnode(struct device *dev, umode_t *mode,
+		kuid_t *uid, kgid_t *gid)
+{
+	struct adf_obj *obj = container_of(dev, struct adf_obj, dev);
+	return kasprintf(GFP_KERNEL, "adf%d", obj->id);
+}
+
+static char *adf_interface_devnode(struct device *dev, umode_t *mode,
+		kuid_t *uid, kgid_t *gid)
+{
+	struct adf_obj *obj = container_of(dev, struct adf_obj, dev);
+	struct adf_interface *intf = adf_obj_to_interface(obj);
+	struct adf_device *parent = adf_interface_parent(intf);
+	return kasprintf(GFP_KERNEL, "adf-interface%d.%d",
+			parent->base.id, intf->base.id);
+}
+
+static char *adf_overlay_engine_devnode(struct device *dev, umode_t *mode,
+		kuid_t *uid, kgid_t *gid)
+{
+	struct adf_obj *obj = container_of(dev, struct adf_obj, dev);
+	struct adf_overlay_engine *eng = adf_obj_to_overlay_engine(obj);
+	struct adf_device *parent = adf_overlay_engine_parent(eng);
+	return kasprintf(GFP_KERNEL, "adf-overlay-engine%d.%d",
+			parent->base.id, eng->base.id);
+}
+
+static void adf_noop_release(struct device *dev)
+{
+}
+
+static struct device_type adf_device_type = {
+	.name = "adf_device",
+	.devnode = adf_device_devnode,
+	.release = adf_noop_release,
+};
+
+static struct device_type adf_interface_type = {
+	.name = "adf_interface",
+	.devnode = adf_interface_devnode,
+	.release = adf_noop_release,
+};
+
+static struct device_type adf_overlay_engine_type = {
+	.name = "adf_overlay_engine",
+	.devnode = adf_overlay_engine_devnode,
+	.release = adf_noop_release,
+};
+
+int adf_device_sysfs_init(struct adf_device *dev)
+{
+	dev->base.dev.type = &adf_device_type;
+	dev_set_name(&dev->base.dev, "%s", dev->base.name);
+	return adf_obj_sysfs_init(&dev->base, dev->dev);
+}
+
+int adf_interface_sysfs_init(struct adf_interface *intf)
+{
+	struct adf_device *parent = adf_interface_parent(intf);
+	size_t i, j;
+	int ret;
+
+	intf->base.dev.type = &adf_interface_type;
+	dev_set_name(&intf->base.dev, "%s-interface%d", parent->base.name,
+			intf->base.id);
+
+	ret = adf_obj_sysfs_init(&intf->base, &parent->base.dev);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(adf_interface_attrs); i++) {
+		ret = device_create_file(&intf->base.dev,
+				&adf_interface_attrs[i]);
+		if (ret < 0) {
+			dev_err(&intf->base.dev, "creating sysfs attribute %s failed: %d\n",
+					adf_interface_attrs[i].attr.name, ret);
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	for (j = 0; j < i; j++)
+		device_remove_file(&intf->base.dev, &adf_interface_attrs[j]);
+	return ret;
+}
+
+int adf_overlay_engine_sysfs_init(struct adf_overlay_engine *eng)
+{
+	struct adf_device *parent = adf_overlay_engine_parent(eng);
+
+	eng->base.dev.type = &adf_overlay_engine_type;
+	dev_set_name(&eng->base.dev, "%s-overlay-engine%d", parent->base.name,
+			eng->base.id);
+
+	return adf_obj_sysfs_init(&eng->base, &parent->base.dev);
+}
+
+struct adf_obj *adf_obj_sysfs_find(int minor)
+{
+	return idr_find(&adf_minors, minor);
+}
+
+void adf_obj_sysfs_destroy(struct adf_obj *obj)
+{
+	idr_remove(&adf_minors, obj->minor);
+	device_unregister(&obj->dev);
+}
+
+void adf_device_sysfs_destroy(struct adf_device *dev)
+{
+	adf_obj_sysfs_destroy(&dev->base);
+}
+
+void adf_interface_sysfs_destroy(struct adf_interface *intf)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(adf_interface_attrs); i++)
+		device_remove_file(&intf->base.dev, &adf_interface_attrs[i]);
+	adf_obj_sysfs_destroy(&intf->base);
+}
+
+void adf_overlay_engine_sysfs_destroy(struct adf_overlay_engine *eng)
+{
+	adf_obj_sysfs_destroy(&eng->base);
+}
+
+int adf_sysfs_init(void)
+{
+	struct class *class;
+	int ret;
+
+	class = class_create(THIS_MODULE, "adf");
+	if (IS_ERR(class)) {
+		ret = PTR_ERR(class);
+		pr_err("%s: creating class failed: %d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = register_chrdev(0, "adf", &adf_fops);
+	if (ret < 0) {
+		pr_err("%s: registering device failed: %d\n", __func__, ret);
+		goto err_chrdev;
+	}
+
+	adf_class = class;
+	adf_major = ret;
+	return 0;
+
+err_chrdev:
+	class_destroy(adf_class);
+	return ret;
+}
+
+void adf_sysfs_destroy(void)
+{
+	idr_destroy(&adf_minors);
+	class_destroy(adf_class);
+}
diff --git a/drivers/video/adf/adf_sysfs.h b/drivers/video/adf/adf_sysfs.h
new file mode 100644
index 0000000..0613ac3
--- /dev/null
+++ b/drivers/video/adf/adf_sysfs.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __VIDEO_ADF_ADF_SYSFS_H
+#define __VIDEO_ADF_ADF_SYSFS_H
+
+struct adf_device;
+struct adf_interface;
+struct adf_overlay_engine;
+
+int adf_device_sysfs_init(struct adf_device *dev);
+void adf_device_sysfs_destroy(struct adf_device *dev);
+int adf_interface_sysfs_init(struct adf_interface *intf);
+void adf_interface_sysfs_destroy(struct adf_interface *intf);
+int adf_overlay_engine_sysfs_init(struct adf_overlay_engine *eng);
+void adf_overlay_engine_sysfs_destroy(struct adf_overlay_engine *eng);
+struct adf_obj *adf_obj_sysfs_find(int minor);
+
+int adf_sysfs_init(void);
+void adf_sysfs_destroy(void);
+
+#endif /* __VIDEO_ADF_ADF_SYSFS_H */
diff --git a/drivers/video/adf/adf_trace.h b/drivers/video/adf/adf_trace.h
new file mode 100644
index 0000000..3cb2a84
--- /dev/null
+++ b/drivers/video/adf/adf_trace.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM adf
+
+#if !defined(__VIDEO_ADF_ADF_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __VIDEO_ADF_ADF_TRACE_H
+
+#include <linux/tracepoint.h>
+#include <video/adf.h>
+
+TRACE_EVENT(adf_event,
+	TP_PROTO(struct adf_obj *obj, enum adf_event_type type),
+	TP_ARGS(obj, type),
+
+	TP_STRUCT__entry(
+		__string(name, obj->name)
+		__field(enum adf_event_type, type)
+		__array(char, type_str, 32)
+	),
+	TP_fast_assign(
+		__assign_str(name, obj->name);
+		__entry->type = type;
+		strlcpy(__entry->type_str, adf_event_type_str(obj, type),
+				sizeof(__entry->type_str));
+	),
+	TP_printk("obj=%s type=%u (%s)",
+			__get_str(name),
+			__entry->type,
+			__entry->type_str)
+);
+
+TRACE_EVENT(adf_event_enable,
+	TP_PROTO(struct adf_obj *obj, enum adf_event_type type),
+	TP_ARGS(obj, type),
+
+	TP_STRUCT__entry(
+		__string(name, obj->name)
+		__field(enum adf_event_type, type)
+		__array(char, type_str, 32)
+	),
+	TP_fast_assign(
+		__assign_str(name, obj->name);
+		__entry->type = type;
+		strlcpy(__entry->type_str, adf_event_type_str(obj, type),
+				sizeof(__entry->type_str));
+	),
+	TP_printk("obj=%s type=%u (%s)",
+			__get_str(name),
+			__entry->type,
+			__entry->type_str)
+);
+
+TRACE_EVENT(adf_event_disable,
+	TP_PROTO(struct adf_obj *obj, enum adf_event_type type),
+	TP_ARGS(obj, type),
+
+	TP_STRUCT__entry(
+		__string(name, obj->name)
+		__field(enum adf_event_type, type)
+		__array(char, type_str, 32)
+	),
+	TP_fast_assign(
+		__assign_str(name, obj->name);
+		__entry->type = type;
+		strlcpy(__entry->type_str, adf_event_type_str(obj, type),
+				sizeof(__entry->type_str));
+	),
+	TP_printk("obj=%s type=%u (%s)",
+			__get_str(name),
+			__entry->type,
+			__entry->type_str)
+);
+
+#endif /* __VIDEO_ADF_ADF_TRACE_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE adf_trace
+#include <trace/define_trace.h>
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 6e92917..4e3c78d 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -1168,6 +1168,8 @@
 	p->userfont = 0;
 }
 
+static void set_vc_hi_font(struct vc_data *vc, bool set);
+
 static void fbcon_deinit(struct vc_data *vc)
 {
 	struct display *p = &fb_display[vc->vc_num];
@@ -1203,6 +1205,9 @@
 	if (free_font)
 		vc->vc_font.data = NULL;
 
+	if (vc->vc_hi_font_mask)
+		set_vc_hi_font(vc, false);
+
 	if (!con_is_bound(&fb_con))
 		fbcon_exit();
 
@@ -2439,32 +2444,10 @@
 	return 0;
 }
 
-static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
-			     const u8 * data, int userfont)
+/* set/clear vc_hi_font_mask and update vc attrs accordingly */
+static void set_vc_hi_font(struct vc_data *vc, bool set)
 {
-	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
-	struct fbcon_ops *ops = info->fbcon_par;
-	struct display *p = &fb_display[vc->vc_num];
-	int resize;
-	int cnt;
-	char *old_data = NULL;
-
-	if (CON_IS_VISIBLE(vc) && softback_lines)
-		fbcon_set_origin(vc);
-
-	resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
-	if (p->userfont)
-		old_data = vc->vc_font.data;
-	if (userfont)
-		cnt = FNTCHARCNT(data);
-	else
-		cnt = 256;
-	vc->vc_font.data = (void *)(p->fontdata = data);
-	if ((p->userfont = userfont))
-		REFCOUNT(data)++;
-	vc->vc_font.width = w;
-	vc->vc_font.height = h;
-	if (vc->vc_hi_font_mask && cnt == 256) {
+	if (!set) {
 		vc->vc_hi_font_mask = 0;
 		if (vc->vc_can_do_color) {
 			vc->vc_complement_mask >>= 1;
@@ -2487,7 +2470,7 @@
 			    ((c & 0xfe00) >> 1) | (c & 0xff);
 			vc->vc_attr >>= 1;
 		}
-	} else if (!vc->vc_hi_font_mask && cnt == 512) {
+	} else {
 		vc->vc_hi_font_mask = 0x100;
 		if (vc->vc_can_do_color) {
 			vc->vc_complement_mask <<= 1;
@@ -2519,8 +2502,38 @@
 			} else
 				vc->vc_video_erase_char = c & ~0x100;
 		}
-
 	}
+}
+
+static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
+			     const u8 * data, int userfont)
+{
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+	struct fbcon_ops *ops = info->fbcon_par;
+	struct display *p = &fb_display[vc->vc_num];
+	int resize;
+	int cnt;
+	char *old_data = NULL;
+
+	if (CON_IS_VISIBLE(vc) && softback_lines)
+		fbcon_set_origin(vc);
+
+	resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
+	if (p->userfont)
+		old_data = vc->vc_font.data;
+	if (userfont)
+		cnt = FNTCHARCNT(data);
+	else
+		cnt = 256;
+	vc->vc_font.data = (void *)(p->fontdata = data);
+	if ((p->userfont = userfont))
+		REFCOUNT(data)++;
+	vc->vc_font.width = w;
+	vc->vc_font.height = h;
+	if (vc->vc_hi_font_mask && cnt == 256)
+		set_vc_hi_font(vc, false);
+	else if (!vc->vc_hi_font_mask && cnt == 512)
+		set_vc_hi_font(vc, true);
 
 	if (resize) {
 		int cols, rows;
diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c
index f89245b..68a1135 100644
--- a/drivers/video/fbdev/core/fbcmap.c
+++ b/drivers/video/fbdev/core/fbcmap.c
@@ -163,17 +163,18 @@
 
 int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
 {
-	int tooff = 0, fromoff = 0;
-	int size;
+	unsigned int tooff = 0, fromoff = 0;
+	size_t size;
 
 	if (to->start > from->start)
 		fromoff = to->start - from->start;
 	else
 		tooff = from->start - to->start;
-	size = to->len - tooff;
-	if (size > (int) (from->len - fromoff))
-		size = from->len - fromoff;
-	if (size <= 0)
+	if (fromoff >= from->len || tooff >= to->len)
+		return -EINVAL;
+
+	size = min_t(size_t, to->len - tooff, from->len - fromoff);
+	if (size == 0)
 		return -EINVAL;
 	size *= sizeof(u16);
 
@@ -187,17 +188,18 @@
 
 int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
 {
-	int tooff = 0, fromoff = 0;
-	int size;
+	unsigned int tooff = 0, fromoff = 0;
+	size_t size;
 
 	if (to->start > from->start)
 		fromoff = to->start - from->start;
 	else
 		tooff = from->start - to->start;
-	size = to->len - tooff;
-	if (size > (int) (from->len - fromoff))
-		size = from->len - fromoff;
-	if (size <= 0)
+	if (fromoff >= from->len || tooff >= to->len)
+		return -EINVAL;
+
+	size = min_t(size_t, to->len - tooff, from->len - fromoff);
+	if (size == 0)
 		return -EINVAL;
 	size *= sizeof(u16);
 
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 95d293b..dc2fcda 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -52,9 +52,9 @@
 		return 1;
 
 	if (regno < 16) {
-		red   >>= 8;
-		green >>= 8;
-		blue  >>= 8;
+		red   >>= 16 - info->var.red.length;
+		green >>= 16 - info->var.green.length;
+		blue  >>= 16 - info->var.blue.length;
 		((u32 *)(info->pseudo_palette))[regno] =
 			(red   << info->var.red.offset)   |
 			(green << info->var.green.offset) |
diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c
index 7f6c9e6..1e56b50 100644
--- a/drivers/video/fbdev/goldfishfb.c
+++ b/drivers/video/fbdev/goldfishfb.c
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
+#include <linux/acpi.h>
 
 enum {
 	FB_GET_WIDTH        = 0x00,
@@ -234,7 +235,7 @@
 	fb->fb.var.activate	= FB_ACTIVATE_NOW;
 	fb->fb.var.height	= readl(fb->reg_base + FB_GET_PHYS_HEIGHT);
 	fb->fb.var.width	= readl(fb->reg_base + FB_GET_PHYS_WIDTH);
-	fb->fb.var.pixclock	= 10000;
+	fb->fb.var.pixclock	= 0;
 
 	fb->fb.var.red.offset = 11;
 	fb->fb.var.red.length = 5;
@@ -304,12 +305,25 @@
 	return 0;
 }
 
+static const struct of_device_id goldfish_fb_of_match[] = {
+	{ .compatible = "google,goldfish-fb", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, goldfish_fb_of_match);
+
+static const struct acpi_device_id goldfish_fb_acpi_match[] = {
+	{ "GFSH0004", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, goldfish_fb_acpi_match);
 
 static struct platform_driver goldfish_fb_driver = {
 	.probe		= goldfish_fb_probe,
 	.remove		= goldfish_fb_remove,
 	.driver = {
-		.name = "goldfish_fb"
+		.name = "goldfish_fb",
+		.of_match_table = goldfish_fb_of_match,
+		.acpi_match_table = ACPI_PTR(goldfish_fb_acpi_match),
 	}
 };
 
diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c
index 0567d51..ea2f19f 100644
--- a/drivers/video/fbdev/xen-fbfront.c
+++ b/drivers/video/fbdev/xen-fbfront.c
@@ -644,7 +644,6 @@
 		break;
 
 	case XenbusStateInitWait:
-InitWait:
 		xenbus_switch_state(dev, XenbusStateConnected);
 		break;
 
@@ -655,7 +654,8 @@
 		 * get Connected twice here.
 		 */
 		if (dev->state != XenbusStateConnected)
-			goto InitWait; /* no InitWait seen yet, fudge it */
+			/* no InitWait seen yet, fudge it */
+			xenbus_switch_state(dev, XenbusStateConnected);
 
 		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
 				 "request-update", "%d", &val) < 0)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 7d3e5d0..01d15dc 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -73,7 +73,7 @@
 
 	/* The array of pfns we tell the Host about. */
 	unsigned int num_pfns;
-	u32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
+	__virtio32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
 
 	/* Memory statistics */
 	int need_stats_update;
@@ -125,14 +125,16 @@
 	wait_event(vb->acked, virtqueue_get_buf(vq, &len));
 }
 
-static void set_page_pfns(u32 pfns[], struct page *page)
+static void set_page_pfns(struct virtio_balloon *vb,
+			  __virtio32 pfns[], struct page *page)
 {
 	unsigned int i;
 
 	/* Set balloon pfns pointing at this page.
 	 * Note that the first pfn points at start of the page. */
 	for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++)
-		pfns[i] = page_to_balloon_pfn(page) + i;
+		pfns[i] = cpu_to_virtio32(vb->vdev,
+					  page_to_balloon_pfn(page) + i);
 }
 
 static void fill_balloon(struct virtio_balloon *vb, size_t num)
@@ -155,7 +157,7 @@
 			msleep(200);
 			break;
 		}
-		set_page_pfns(vb->pfns + vb->num_pfns, page);
+		set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
 		vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
 		if (!virtio_has_feature(vb->vdev,
 					VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
@@ -171,10 +173,12 @@
 static void release_pages_balloon(struct virtio_balloon *vb)
 {
 	unsigned int i;
+	struct page *page;
 
 	/* Find pfns pointing at start of each page, get pages and free them. */
 	for (i = 0; i < vb->num_pfns; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
-		struct page *page = balloon_pfn_to_page(vb->pfns[i]);
+		page = balloon_pfn_to_page(virtio32_to_cpu(vb->vdev,
+							   vb->pfns[i]));
 		if (!virtio_has_feature(vb->vdev,
 					VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
 			adjust_managed_page_count(page, 1);
@@ -192,12 +196,14 @@
 	num = min(num, ARRAY_SIZE(vb->pfns));
 
 	mutex_lock(&vb->balloon_lock);
+	/* We can't release more pages than taken */
+	num = min(num, (size_t)vb->num_pages);
 	for (vb->num_pfns = 0; vb->num_pfns < num;
 	     vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
 		page = balloon_page_dequeue(vb_dev_info);
 		if (!page)
 			break;
-		set_page_pfns(vb->pfns + vb->num_pfns, page);
+		set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
 		vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
 	}
 
@@ -410,6 +416,8 @@
 		 * Prime this virtqueue with one buffer so the hypervisor can
 		 * use it to signal us later (it can't be broken yet!).
 		 */
+		update_balloon_stats(vb);
+
 		sg_init_one(&sg, vb->stats, sizeof vb->stats);
 		if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL)
 		    < 0)
@@ -465,13 +473,13 @@
 	__count_vm_event(BALLOON_MIGRATE);
 	spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
 	vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
-	set_page_pfns(vb->pfns, newpage);
+	set_page_pfns(vb, vb->pfns, newpage);
 	tell_host(vb, vb->inflate_vq);
 
 	/* balloon's page migration 2nd step -- deflate "page" */
 	balloon_page_delete(page);
 	vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
-	set_page_pfns(vb->pfns, page);
+	set_page_pfns(vb, vb->pfns, page);
 	tell_host(vb, vb->deflate_vq);
 
 	mutex_unlock(&vb->balloon_lock);
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index ee663c4..a01a41a 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -202,6 +202,8 @@
 		 * host should service the ring ASAP. */
 		if (out_sgs)
 			vq->notify(&vq->vq);
+		if (indirect)
+			kfree(desc);
 		END_USE(vq);
 		return -ENOSPC;
 	}
@@ -546,7 +548,8 @@
 
 	if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) {
 		vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
-		vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
+		if (!vq->event)
+			vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
 	}
 
 }
@@ -578,7 +581,8 @@
 	 * entry. Always do both to keep code simple. */
 	if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {
 		vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT;
-		vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
+		if (!vq->event)
+			vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
 	}
 	vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx);
 	END_USE(vq);
@@ -646,10 +650,11 @@
 	 * more to do. */
 	/* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to
 	 * either clear the flags bit or point the event index at the next
-	 * entry. Always do both to keep code simple. */
+	 * entry. Always update the event index to keep code simple. */
 	if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {
 		vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT;
-		vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
+		if (!vq->event)
+			vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
 	}
 	/* TODO: tune this threshold */
 	bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4;
@@ -768,7 +773,8 @@
 	/* No callback?  Tell other side not to bother us. */
 	if (!callback) {
 		vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
-		vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow);
+		if (!vq->event)
+			vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow);
 	}
 
 	/* Put everything in free lists. */
diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c
index b79a74a..ad94d8a 100644
--- a/drivers/vme/bridges/vme_ca91cx42.c
+++ b/drivers/vme/bridges/vme_ca91cx42.c
@@ -467,7 +467,7 @@
 	vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]);
 	pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]);
 
-	*pci_base = (dma_addr_t)vme_base + pci_offset;
+	*pci_base = (dma_addr_t)*vme_base + pci_offset;
 	*size = (unsigned long long)((vme_bound - *vme_base) + granularity);
 
 	*enabled = 0;
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 049a884..59d74d1 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -153,6 +153,9 @@
 	 */
 	u16			spu_bit;
 
+	u8			st_buf[ST_SIZE];
+	u8			byte_buf;
+
 	struct w1_bus_master	master;
 };
 
@@ -174,7 +177,6 @@
 	u8			data_in_buffer_status;
 	u8			reserved1;
 	u8			reserved2;
-
 };
 
 static struct usb_device_id ds_id_table [] = {
@@ -244,28 +246,6 @@
 	return err;
 }
 
-static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
-				 unsigned char *buf, int size)
-{
-	int count, err;
-
-	memset(st, 0, sizeof(*st));
-
-	count = 0;
-	err = usb_interrupt_msg(dev->udev, usb_rcvintpipe(dev->udev,
-		dev->ep[EP_STATUS]), buf, size, &count, 1000);
-	if (err < 0) {
-		pr_err("Failed to read 1-wire data from 0x%x: err=%d.\n",
-		       dev->ep[EP_STATUS], err);
-		return err;
-	}
-
-	if (count >= sizeof(*st))
-		memcpy(st, buf, sizeof(*st));
-
-	return count;
-}
-
 static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off)
 {
 	pr_info("%45s: %8x\n", str, buf[off]);
@@ -324,6 +304,35 @@
 	}
 }
 
+static int ds_recv_status(struct ds_device *dev, struct ds_status *st,
+			  bool dump)
+{
+	int count, err;
+
+	if (st)
+		memset(st, 0, sizeof(*st));
+
+	count = 0;
+	err = usb_interrupt_msg(dev->udev,
+				usb_rcvintpipe(dev->udev,
+					       dev->ep[EP_STATUS]),
+				dev->st_buf, sizeof(dev->st_buf),
+				&count, 1000);
+	if (err < 0) {
+		pr_err("Failed to read 1-wire data from 0x%x: err=%d.\n",
+		       dev->ep[EP_STATUS], err);
+		return err;
+	}
+
+	if (dump)
+		ds_dump_status(dev, dev->st_buf, count);
+
+	if (st && count >= sizeof(*st))
+		memcpy(st, dev->st_buf, sizeof(*st));
+
+	return count;
+}
+
 static void ds_reset_device(struct ds_device *dev)
 {
 	ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
@@ -344,7 +353,6 @@
 static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
 {
 	int count, err;
-	struct ds_status st;
 
 	/* Careful on size.  If size is less than what is available in
 	 * the input buffer, the device fails the bulk transfer and
@@ -359,14 +367,9 @@
 	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
 				buf, size, &count, 1000);
 	if (err < 0) {
-		u8 buf[ST_SIZE];
-		int count;
-
 		pr_info("Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
 		usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
-
-		count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
-		ds_dump_status(dev, buf, count);
+		ds_recv_status(dev, NULL, true);
 		return err;
 	}
 
@@ -404,7 +407,6 @@
 {
 	struct ds_status st;
 	int count = 0, err = 0;
-	u8 buf[ST_SIZE];
 
 	do {
 		err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
@@ -413,7 +415,7 @@
 		err = ds_send_control(dev, CTL_RESUME_EXE, 0);
 		if (err)
 			break;
-		err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+		err = ds_recv_status(dev, &st, false);
 		if (err)
 			break;
 
@@ -456,18 +458,17 @@
 
 static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
 {
-	u8 buf[ST_SIZE];
 	int err, count = 0;
 
 	do {
 		st->status = 0;
-		err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+		err = ds_recv_status(dev, st, false);
 #if 0
 		if (err >= 0) {
 			int i;
 			printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
 			for (i=0; i<err; ++i)
-				printk("%02x ", buf[i]);
+				printk("%02x ", dev->st_buf[i]);
 			printk("\n");
 		}
 #endif
@@ -485,7 +486,7 @@
 	 * can do something with it).
 	 */
 	if (err > 16 || count >= 100 || err < 0)
-		ds_dump_status(dev, buf, err);
+		ds_dump_status(dev, dev->st_buf, err);
 
 	/* Extended data isn't an error.  Well, a short is, but the dump
 	 * would have already told the user that and we can't do anything
@@ -608,7 +609,6 @@
 {
 	int err;
 	struct ds_status st;
-	u8 rbyte;
 
 	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte);
 	if (err)
@@ -621,11 +621,11 @@
 	if (err)
 		return err;
 
-	err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
+	err = ds_recv_data(dev, &dev->byte_buf, 1);
 	if (err < 0)
 		return err;
 
-	return !(byte == rbyte);
+	return !(byte == dev->byte_buf);
 }
 
 static int ds_read_byte(struct ds_device *dev, u8 *byte)
@@ -712,7 +712,6 @@
 	int err;
 	u16 value, index;
 	struct ds_status st;
-	u8 st_buf[ST_SIZE];
 	int search_limit;
 	int found = 0;
 	int i;
@@ -724,7 +723,12 @@
 	/* FIFO 128 bytes, bulk packet size 64, read a multiple of the
 	 * packet size.
 	 */
-	u64 buf[2*64/8];
+	const size_t bufsize = 2 * 64;
+	u64 *buf;
+
+	buf = kmalloc(bufsize, GFP_KERNEL);
+	if (!buf)
+		return;
 
 	mutex_lock(&master->bus_mutex);
 
@@ -745,10 +749,9 @@
 	do {
 		schedule_timeout(jtime);
 
-		if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) <
-			sizeof(st)) {
+		err = ds_recv_status(dev, &st, false);
+		if (err < 0 || err < sizeof(st))
 			break;
-		}
 
 		if (st.data_in_buffer_status) {
 			/* Bulk in can receive partial ids, but when it does
@@ -758,7 +761,7 @@
 			 * bulk without first checking if status says there
 			 * is data to read.
 			 */
-			err = ds_recv_data(dev, (u8 *)buf, sizeof(buf));
+			err = ds_recv_data(dev, (u8 *)buf, bufsize);
 			if (err < 0)
 				break;
 			for (i = 0; i < err/8; ++i) {
@@ -794,9 +797,14 @@
 	}
 search_out:
 	mutex_unlock(&master->bus_mutex);
+	kfree(buf);
 }
 
 #if 0
+/*
+ * FIXME: if this disabled code is ever used in the future all ds_send_data()
+ * calls must be changed to use a DMAable buffer.
+ */
 static int ds_match_access(struct ds_device *dev, u64 init)
 {
 	int err;
@@ -845,13 +853,12 @@
 
 static u8 ds9490r_touch_bit(void *data, u8 bit)
 {
-	u8 ret;
 	struct ds_device *dev = data;
 
-	if (ds_touch_bit(dev, bit, &ret))
+	if (ds_touch_bit(dev, bit, &dev->byte_buf))
 		return 0;
 
-	return ret;
+	return dev->byte_buf;
 }
 
 #if 0
@@ -866,13 +873,12 @@
 {
 	struct ds_device *dev = data;
 	int err;
-	u8 bit = 0;
 
-	err = ds_touch_bit(dev, 1, &bit);
+	err = ds_touch_bit(dev, 1, &dev->byte_buf);
 	if (err)
 		return 0;
 
-	return bit & 1;
+	return dev->byte_buf & 1;
 }
 #endif
 
@@ -887,32 +893,52 @@
 {
 	struct ds_device *dev = data;
 	int err;
-	u8 byte = 0;
 
-	err = ds_read_byte(dev, &byte);
+	err = ds_read_byte(dev, &dev->byte_buf);
 	if (err)
 		return 0;
 
-	return byte;
+	return dev->byte_buf;
 }
 
 static void ds9490r_write_block(void *data, const u8 *buf, int len)
 {
 	struct ds_device *dev = data;
+	u8 *tbuf;
 
-	ds_write_block(dev, (u8 *)buf, len);
+	if (len <= 0)
+		return;
+
+	tbuf = kmalloc(len, GFP_KERNEL);
+	if (!tbuf)
+		return;
+
+	memcpy(tbuf, buf, len);
+	ds_write_block(dev, tbuf, len);
+
+	kfree(tbuf);
 }
 
 static u8 ds9490r_read_block(void *data, u8 *buf, int len)
 {
 	struct ds_device *dev = data;
 	int err;
+	u8 *tbuf;
 
-	err = ds_read_block(dev, buf, len);
-	if (err < 0)
+	if (len <= 0)
 		return 0;
 
-	return len;
+	tbuf = kmalloc(len, GFP_KERNEL);
+	if (!tbuf)
+		return 0;
+
+	err = ds_read_block(dev, tbuf, len);
+	if (err >= 0)
+		memcpy(buf, tbuf, len);
+
+	kfree(tbuf);
+
+	return err >= 0 ? len : 0;
 }
 
 static u8 ds9490r_reset(void *data)
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index 0e2f43b..0c427d6 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -390,8 +390,6 @@
 		goto out;
 	}
 
-	hdq_data->hdq_irqstatus = 0;
-
 	if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
 		hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS,
 			OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO,
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index c9a7ff6..39886ed 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -763,6 +763,7 @@
 		dev_err(&dev->dev, "%s: Attaching %s failed.\n", __func__,
 			 sl->name);
 		w1_family_put(sl->family);
+		atomic_dec(&sl->master->refcnt);
 		kfree(sl);
 		return err;
 	}
diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c
index e0c9842..11a72bc 100644
--- a/drivers/watchdog/bcm_kona_wdt.c
+++ b/drivers/watchdog/bcm_kona_wdt.c
@@ -304,6 +304,8 @@
 	if (!wdt)
 		return -ENOMEM;
 
+	spin_lock_init(&wdt->lock);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	wdt->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(wdt->base))
@@ -316,7 +318,6 @@
 		return ret;
 	}
 
-	spin_lock_init(&wdt->lock);
 	platform_set_drvdata(pdev, wdt);
 	watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt);
 	bcm_kona_wdt_wdd.parent = &pdev->dev;
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c
index 1a11aed..9eb5b31 100644
--- a/drivers/watchdog/pcwd_usb.c
+++ b/drivers/watchdog/pcwd_usb.c
@@ -630,6 +630,9 @@
 		return -ENODEV;
 	}
 
+	if (iface_desc->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	/* check out the endpoint: it has to be Interrupt & IN */
 	endpoint = &iface_desc->endpoint[0].desc;
 
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 364bc44..cfab1d2 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -152,8 +152,6 @@
 static void balloon_process(struct work_struct *work);
 static DECLARE_DELAYED_WORK(balloon_worker, balloon_process);
 
-static void release_memory_resource(struct resource *resource);
-
 /* When ballooning out (allocating memory to return to Xen) we don't really
    want the kernel to try too hard since that can trigger the oom killer. */
 #define GFP_BALLOON \
@@ -249,6 +247,19 @@
 }
 
 #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+static void release_memory_resource(struct resource *resource)
+{
+	if (!resource)
+		return;
+
+	/*
+	 * No need to reset region to identity mapped since we now
+	 * know that no I/O can be in this region
+	 */
+	release_resource(resource);
+	kfree(resource);
+}
+
 static struct resource *additional_memory_resource(phys_addr_t size)
 {
 	struct resource *res;
@@ -287,19 +298,6 @@
 	return res;
 }
 
-static void release_memory_resource(struct resource *resource)
-{
-	if (!resource)
-		return;
-
-	/*
-	 * No need to reset region to identity mapped since we now
-	 * know that no I/O can be in this region
-	 */
-	release_resource(resource);
-	kfree(resource);
-}
-
 static enum bp_state reserve_additional_memory(void)
 {
 	long credit;
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 4436778..83ec7b8 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -487,7 +487,8 @@
 	if (!VALID_EVTCHN(evtchn))
 		return;
 
-	if (unlikely(irqd_is_setaffinity_pending(data))) {
+	if (unlikely(irqd_is_setaffinity_pending(data)) &&
+	    likely(!irqd_irq_disabled(data))) {
 		int masked = test_and_set_mask(evtchn);
 
 		clear_evtchn(evtchn);
@@ -1370,7 +1371,8 @@
 	if (!VALID_EVTCHN(evtchn))
 		return;
 
-	if (unlikely(irqd_is_setaffinity_pending(data))) {
+	if (unlikely(irqd_is_setaffinity_pending(data)) &&
+	    likely(!irqd_irq_disabled(data))) {
 		int masked = test_and_set_mask(evtchn);
 
 		clear_evtchn(evtchn);
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 1be5dd0..308600a 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -804,7 +804,7 @@
 
 	vma->vm_ops = &gntdev_vmops;
 
-	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_MIXEDMAP;
 
 	if (use_ptemod)
 		vma->vm_flags |= VM_DONTCOPY;
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index df2e6f7..527de56 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -335,8 +335,8 @@
 				st->global_error = 1;
 		}
 	}
-	st->va += PAGE_SIZE * nr;
-	st->index += nr;
+	st->va += XEN_PAGE_SIZE * nr;
+	st->index += nr / XEN_PFN_PER_PAGE;
 
 	return 0;
 }
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 7399782..8a58bbc 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -409,9 +409,9 @@
 	if (map == SWIOTLB_MAP_ERROR)
 		return DMA_ERROR_CODE;
 
+	dev_addr = xen_phys_to_bus(map);
 	xen_dma_map_page(dev, pfn_to_page(map >> PAGE_SHIFT),
 					dev_addr, map & ~PAGE_MASK, size, dir, attrs);
-	dev_addr = xen_phys_to_bus(map);
 
 	/*
 	 * Ensure that the address returned is DMA'ble
@@ -567,13 +567,14 @@
 				sg_dma_len(sgl) = 0;
 				return 0;
 			}
+			dev_addr = xen_phys_to_bus(map);
 			xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT),
 						dev_addr,
 						map & ~PAGE_MASK,
 						sg->length,
 						dir,
 						attrs);
-			sg->dma_address = xen_phys_to_bus(map);
+			sg->dma_address = dev_addr;
 		} else {
 			/* we are not interested in the dma_addr returned by
 			 * xen_dma_map_page, only in the potential cache flushes executed
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 70fa438..2e319d0 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -27,10 +27,10 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/syscore_ops.h>
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 #include <xen/xen.h>
-#include <xen/xen-ops.h>
 #include <xen/interface/platform.h>
 #include <asm/xen/hypercall.h>
 
@@ -423,36 +423,7 @@
 
 	return 0;
 }
-static int __init check_prereq(void)
-{
-	struct cpuinfo_x86 *c = &cpu_data(0);
 
-	if (!xen_initial_domain())
-		return -ENODEV;
-
-	if (!acpi_gbl_FADT.smi_command)
-		return -ENODEV;
-
-	if (c->x86_vendor == X86_VENDOR_INTEL) {
-		if (!cpu_has(c, X86_FEATURE_EST))
-			return -ENODEV;
-
-		return 0;
-	}
-	if (c->x86_vendor == X86_VENDOR_AMD) {
-		/* Copied from powernow-k8.h, can't include ../cpufreq/powernow
-		 * as we get compile warnings for the static functions.
-		 */
-#define CPUID_FREQ_VOLT_CAPABILITIES    0x80000007
-#define USE_HW_PSTATE                   0x00000080
-		u32 eax, ebx, ecx, edx;
-		cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
-		if ((edx & USE_HW_PSTATE) != USE_HW_PSTATE)
-			return -ENODEV;
-		return 0;
-	}
-	return -ENODEV;
-}
 /* acpi_perf_data is a pointer to percpu data. */
 static struct acpi_processor_performance __percpu *acpi_perf_data;
 
@@ -495,24 +466,42 @@
 	return rc;
 }
 
-static int xen_acpi_processor_resume(struct notifier_block *nb,
-				     unsigned long action, void *data)
+static void xen_acpi_processor_resume_worker(struct work_struct *dummy)
 {
+	int rc;
+
 	bitmap_zero(acpi_ids_done, nr_acpi_bits);
-	return xen_upload_processor_pm_data();
+
+	rc = xen_upload_processor_pm_data();
+	if (rc != 0)
+		pr_info("ACPI data upload failed, error = %d\n", rc);
 }
 
-struct notifier_block xen_acpi_processor_resume_nb = {
-	.notifier_call = xen_acpi_processor_resume,
+static void xen_acpi_processor_resume(void)
+{
+	static DECLARE_WORK(wq, xen_acpi_processor_resume_worker);
+
+	/*
+	 * xen_upload_processor_pm_data() calls non-atomic code.
+	 * However, the context for xen_acpi_processor_resume is syscore
+	 * with only the boot CPU online and in an atomic context.
+	 *
+	 * So defer the upload for some point safer.
+	 */
+	schedule_work(&wq);
+}
+
+static struct syscore_ops xap_syscore_ops = {
+	.resume	= xen_acpi_processor_resume,
 };
 
 static int __init xen_acpi_processor_init(void)
 {
 	unsigned int i;
-	int rc = check_prereq();
+	int rc;
 
-	if (rc)
-		return rc;
+	if (!xen_initial_domain())
+		return -ENODEV;
 
 	nr_acpi_bits = get_max_acpi_id() + 1;
 	acpi_ids_done = kcalloc(BITS_TO_LONGS(nr_acpi_bits), sizeof(unsigned long), GFP_KERNEL);
@@ -556,7 +545,7 @@
 	if (rc)
 		goto err_unregister;
 
-	xen_resume_notifier_register(&xen_acpi_processor_resume_nb);
+	register_syscore_ops(&xap_syscore_ops);
 
 	return 0;
 err_unregister:
@@ -573,7 +562,7 @@
 {
 	int i;
 
-	xen_resume_notifier_unregister(&xen_acpi_processor_resume_nb);
+	unregister_syscore_ops(&xap_syscore_ops);
 	kfree(acpi_ids_done);
 	kfree(acpi_id_present);
 	kfree(acpi_id_cst_present);
diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c
index 9c23420..47a4177 100644
--- a/drivers/xen/xen-pciback/conf_space.c
+++ b/drivers/xen/xen-pciback/conf_space.c
@@ -183,8 +183,7 @@
 		field_start = OFFSET(cfg_entry);
 		field_end = OFFSET(cfg_entry) + field->size;
 
-		if ((req_start >= field_start && req_start < field_end)
-		    || (req_end > field_start && req_end <= field_end)) {
+		 if (req_end > field_start && field_end > req_start) {
 			err = conf_space_read(dev, cfg_entry, field_start,
 					      &tmp_val);
 			if (err)
@@ -230,8 +229,7 @@
 		field_start = OFFSET(cfg_entry);
 		field_end = OFFSET(cfg_entry) + field->size;
 
-		if ((req_start >= field_start && req_start < field_end)
-		    || (req_end > field_start && req_end <= field_end)) {
+		 if (req_end > field_start && field_end > req_start) {
 			tmp_val = 0;
 
 			err = xen_pcibk_config_read(dev, field_start,
diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c
index 9433e46..0e0eb10 100644
--- a/drivers/xen/xenbus/xenbus_dev_frontend.c
+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
@@ -316,11 +316,18 @@
 			rc = -ENOMEM;
 			goto out;
 		}
+	} else if (msg_type == XS_TRANSACTION_END) {
+		list_for_each_entry(trans, &u->transactions, list)
+			if (trans->handle.id == u->u.msg.tx_id)
+				break;
+		if (&trans->list == &u->transactions)
+			return -ESRCH;
 	}
 
 	reply = xenbus_dev_request_and_reply(&u->u.msg);
 	if (IS_ERR(reply)) {
-		kfree(trans);
+		if (msg_type == XS_TRANSACTION_START)
+			kfree(trans);
 		rc = PTR_ERR(reply);
 		goto out;
 	}
@@ -333,12 +340,7 @@
 			list_add(&trans->list, &u->transactions);
 		}
 	} else if (u->u.msg.type == XS_TRANSACTION_END) {
-		list_for_each_entry(trans, &u->transactions, list)
-			if (trans->handle.id == u->u.msg.tx_id)
-				break;
-		BUG_ON(&trans->list == &u->transactions);
 		list_del(&trans->list);
-
 		kfree(trans);
 	}
 
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index ba804f3..ce65591 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -250,9 +250,6 @@
 
 	mutex_unlock(&xs_state.request_mutex);
 
-	if (IS_ERR(ret))
-		return ret;
-
 	if ((msg->type == XS_TRANSACTION_END) ||
 	    ((req_msg.type == XS_TRANSACTION_START) &&
 	     (msg->type == XS_ERROR)))
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index a7e2889..c30c6ce 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -282,32 +282,28 @@
 	switch (handler->flags) {
 	case ACL_TYPE_ACCESS:
 		if (acl) {
-			umode_t mode = inode->i_mode;
-			retval = posix_acl_equiv_mode(acl, &mode);
-			if (retval < 0)
+			struct iattr iattr;
+			struct posix_acl *old_acl = acl;
+
+			retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
+			if (retval)
 				goto err_out;
-			else {
-				struct iattr iattr;
-				if (retval == 0) {
-					/*
-					 * ACL can be represented
-					 * by the mode bits. So don't
-					 * update ACL.
-					 */
-					acl = NULL;
-					value = NULL;
-					size = 0;
-				}
-				/* Updte the mode bits */
-				iattr.ia_mode = ((mode & S_IALLUGO) |
-						 (inode->i_mode & ~S_IALLUGO));
-				iattr.ia_valid = ATTR_MODE;
-				/* FIXME should we update ctime ?
-				 * What is the following setxattr update the
-				 * mode ?
+			if (!acl) {
+				/*
+				 * ACL can be represented
+				 * by the mode bits. So don't
+				 * update ACL.
 				 */
-				v9fs_vfs_setattr_dotl(dentry, &iattr);
+				posix_acl_release(old_acl);
+				value = NULL;
+				size = 0;
 			}
+			iattr.ia_valid = ATTR_MODE;
+			/* FIXME should we update ctime ?
+			 * What is the following setxattr update the
+			 * mode ?
+			 */
+			v9fs_vfs_setattr_dotl(dentry, &iattr);
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 7bf835f..12ceaf52 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -74,7 +74,7 @@
 					v9fs_proto_dotu(v9ses));
 	fid = file->private_data;
 	if (!fid) {
-		fid = v9fs_fid_clone(file->f_path.dentry);
+		fid = v9fs_fid_clone(file_dentry(file));
 		if (IS_ERR(fid))
 			return PTR_ERR(fid);
 
@@ -100,7 +100,7 @@
 		 * because we want write after unlink usecase
 		 * to work.
 		 */
-		fid = v9fs_writeback_fid(file->f_path.dentry);
+		fid = v9fs_writeback_fid(file_dentry(file));
 		if (IS_ERR(fid)) {
 			err = PTR_ERR(fid);
 			mutex_unlock(&v9inode->v_mutex);
@@ -516,7 +516,7 @@
 		 * because we want write after unlink usecase
 		 * to work.
 		 */
-		fid = v9fs_writeback_fid(filp->f_path.dentry);
+		fid = v9fs_writeback_fid(file_dentry(filp));
 		if (IS_ERR(fid)) {
 			retval = PTR_ERR(fid);
 			mutex_unlock(&v9inode->v_mutex);
diff --git a/fs/Makefile b/fs/Makefile
index 3b54070..dee2375 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -41,7 +41,7 @@
 obj-$(CONFIG_BINFMT_ELF_FDPIC)	+= binfmt_elf_fdpic.o
 obj-$(CONFIG_BINFMT_FLAT)	+= binfmt_flat.o
 
-obj-$(CONFIG_FS_MBCACHE)	+= mbcache.o
+obj-$(CONFIG_FS_MBCACHE)	+= mbcache.o mbcache2.o
 obj-$(CONFIG_FS_POSIX_ACL)	+= posix_acl.o
 obj-$(CONFIG_NFS_COMMON)	+= nfs_common/
 obj-$(CONFIG_COREDUMP)		+= coredump.o
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 5b50c4c..f90c535 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -528,7 +528,7 @@
 	char			*prefix = NULL;
 
 	new_opts = kstrdup(data, GFP_KERNEL);
-	if (!new_opts)
+	if (data && !new_opts)
 		return -ENOMEM;
 
 	pr_debug("%s(flags=0x%x,opts=\"%s\")\n", __func__, *flags, data);
@@ -546,7 +546,8 @@
 	}
 
 	flush_delayed_work(&sbi->sb_work);
-	replace_mount_options(sb, new_opts);
+	if (new_opts)
+		replace_mount_options(sb, new_opts);
 
 	sbi->s_flags = mount_flags;
 	sbi->s_mode  = mode;
diff --git a/fs/aio.c b/fs/aio.c
index 155f842..fe4f492 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -239,7 +239,12 @@
 	static const struct dentry_operations ops = {
 		.d_dname	= simple_dname,
 	};
-	return mount_pseudo(fs_type, "aio:", NULL, &ops, AIO_RING_MAGIC);
+	struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, &ops,
+					   AIO_RING_MAGIC);
+
+	if (!IS_ERR(root))
+		root->d_sb->s_iflags |= SB_I_NOEXEC;
+	return root;
 }
 
 /* aio_setup
diff --git a/fs/attr.c b/fs/attr.c
index 6530ced..c86b37c 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -187,7 +187,7 @@
  * the file open for write, as there can be no conflicting delegation in
  * that case.
  */
-int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
+int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
 {
 	struct inode *inode = dentry->d_inode;
 	umode_t mode = inode->i_mode;
@@ -202,6 +202,21 @@
 			return -EPERM;
 	}
 
+	/*
+	 * If utimes(2) and friends are called with times == NULL (or both
+	 * times are UTIME_NOW), then we need to check for write permission
+	 */
+	if (ia_valid & ATTR_TOUCH) {
+		if (IS_IMMUTABLE(inode))
+			return -EPERM;
+
+		if (!inode_owner_or_capable(inode)) {
+			error = inode_permission2(mnt, inode, MAY_WRITE);
+			if (error)
+				return error;
+		}
+	}
+
 	if ((ia_valid & ATTR_MODE)) {
 		umode_t amode = attr->ia_mode;
 		/* Flag setting protected by i_mutex */
@@ -262,7 +277,9 @@
 	if (error)
 		return error;
 
-	if (inode->i_op->setattr)
+	if (mnt && inode->i_op->setattr2)
+		error = inode->i_op->setattr2(mnt, dentry, attr);
+	else if (inode->i_op->setattr)
 		error = inode->i_op->setattr(dentry, attr);
 	else
 		error = simple_setattr(dentry, attr);
@@ -275,4 +292,10 @@
 
 	return error;
 }
+EXPORT_SYMBOL(notify_change2);
+
+int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
+{
+	return notify_change2(NULL, dentry, attr, delegated_inode);
+}
 EXPORT_SYMBOL(notify_change);
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index c37149b..502d389 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -79,9 +79,13 @@
 };
 
 #define AUTOFS_INF_EXPIRING	(1<<0) /* dentry is in the process of expiring */
-#define AUTOFS_INF_NO_RCU	(1<<1) /* the dentry is being considered
+#define AUTOFS_INF_WANT_EXPIRE	(1<<1) /* the dentry is being considered
 					* for expiry, so RCU_walk is
-					* not permitted
+					* not permitted.  If it progresses to
+					* actual expiry attempt, the flag is
+					* not cleared when EXPIRING is set -
+					* in that case it gets cleared only
+					* when it comes to clearing EXPIRING.
 					*/
 #define AUTOFS_INF_PENDING	(1<<2) /* dentry pending mount */
 
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index ac7d921..2574255 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -331,7 +331,7 @@
 	int status;
 
 	token = (autofs_wqt_t) param->fail.token;
-	status = param->fail.status ? param->fail.status : -ENOENT;
+	status = param->fail.status < 0 ? param->fail.status : -ENOENT;
 	return autofs4_wait_release(sbi, token, status);
 }
 
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 1cebc3c..7a5a598 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -315,19 +315,17 @@
 	if (ino->flags & AUTOFS_INF_PENDING)
 		goto out;
 	if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
-		ino->flags |= AUTOFS_INF_NO_RCU;
+		ino->flags |= AUTOFS_INF_WANT_EXPIRE;
 		spin_unlock(&sbi->fs_lock);
 		synchronize_rcu();
 		spin_lock(&sbi->fs_lock);
 		if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
 			ino->flags |= AUTOFS_INF_EXPIRING;
-			smp_mb();
-			ino->flags &= ~AUTOFS_INF_NO_RCU;
 			init_completion(&ino->expire_complete);
 			spin_unlock(&sbi->fs_lock);
 			return root;
 		}
-		ino->flags &= ~AUTOFS_INF_NO_RCU;
+		ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
 	}
 out:
 	spin_unlock(&sbi->fs_lock);
@@ -417,6 +415,7 @@
 	}
 	return NULL;
 }
+
 /*
  * Find an eligible tree to time-out
  * A tree is eligible if :-
@@ -432,6 +431,7 @@
 	struct dentry *root = sb->s_root;
 	struct dentry *dentry;
 	struct dentry *expired;
+	struct dentry *found;
 	struct autofs_info *ino;
 
 	if (!root)
@@ -442,48 +442,54 @@
 
 	dentry = NULL;
 	while ((dentry = get_next_positive_subdir(dentry, root))) {
+		int flags = how;
+
 		spin_lock(&sbi->fs_lock);
 		ino = autofs4_dentry_ino(dentry);
-		if (ino->flags & AUTOFS_INF_NO_RCU)
-			expired = NULL;
-		else
-			expired = should_expire(dentry, mnt, timeout, how);
-		if (!expired) {
+		if (ino->flags & AUTOFS_INF_WANT_EXPIRE) {
 			spin_unlock(&sbi->fs_lock);
 			continue;
 		}
+		spin_unlock(&sbi->fs_lock);
+
+		expired = should_expire(dentry, mnt, timeout, flags);
+		if (!expired)
+			continue;
+
+		spin_lock(&sbi->fs_lock);
 		ino = autofs4_dentry_ino(expired);
-		ino->flags |= AUTOFS_INF_NO_RCU;
+		ino->flags |= AUTOFS_INF_WANT_EXPIRE;
 		spin_unlock(&sbi->fs_lock);
 		synchronize_rcu();
-		spin_lock(&sbi->fs_lock);
-		if (should_expire(expired, mnt, timeout, how)) {
-			if (expired != dentry)
-				dput(dentry);
-			goto found;
-		}
 
-		ino->flags &= ~AUTOFS_INF_NO_RCU;
+		/* Make sure a reference is not taken on found if
+		 * things have changed.
+		 */
+		flags &= ~AUTOFS_EXP_LEAVES;
+		found = should_expire(expired, mnt, timeout, how);
+		if (!found || found != expired)
+			/* Something has changed, continue */
+			goto next;
+
+		if (expired != dentry)
+			dput(dentry);
+
+		spin_lock(&sbi->fs_lock);
+		goto found;
+next:
+		spin_lock(&sbi->fs_lock);
+		ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
+		spin_unlock(&sbi->fs_lock);
 		if (expired != dentry)
 			dput(expired);
-		spin_unlock(&sbi->fs_lock);
 	}
 	return NULL;
 
 found:
 	DPRINTK("returning %p %pd", expired, expired);
 	ino->flags |= AUTOFS_INF_EXPIRING;
-	smp_mb();
-	ino->flags &= ~AUTOFS_INF_NO_RCU;
 	init_completion(&ino->expire_complete);
 	spin_unlock(&sbi->fs_lock);
-	spin_lock(&sbi->lookup_lock);
-	spin_lock(&expired->d_parent->d_lock);
-	spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
-	list_move(&expired->d_parent->d_subdirs, &expired->d_child);
-	spin_unlock(&expired->d_lock);
-	spin_unlock(&expired->d_parent->d_lock);
-	spin_unlock(&sbi->lookup_lock);
 	return expired;
 }
 
@@ -492,15 +498,27 @@
 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
 	int status;
+	int state;
 
 	/* Block on any pending expire */
-	if (!(ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU)))
+	if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
 		return 0;
 	if (rcu_walk)
 		return -ECHILD;
 
+retry:
 	spin_lock(&sbi->fs_lock);
-	if (ino->flags & AUTOFS_INF_EXPIRING) {
+	state = ino->flags & (AUTOFS_INF_WANT_EXPIRE | AUTOFS_INF_EXPIRING);
+	if (state == AUTOFS_INF_WANT_EXPIRE) {
+		spin_unlock(&sbi->fs_lock);
+		/*
+		 * Possibly being selected for expire, wait until
+		 * it's selected or not.
+		 */
+		schedule_timeout_uninterruptible(HZ/10);
+		goto retry;
+	}
+	if (state & AUTOFS_INF_EXPIRING) {
 		spin_unlock(&sbi->fs_lock);
 
 		DPRINTK("waiting for expire %p name=%pd", dentry, dentry);
@@ -551,7 +569,7 @@
 	ino = autofs4_dentry_ino(dentry);
 	/* avoid rapid-fire expire attempts if expiry fails */
 	ino->last_used = now;
-	ino->flags &= ~AUTOFS_INF_EXPIRING;
+	ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
 	complete_all(&ino->expire_complete);
 	spin_unlock(&sbi->fs_lock);
 
@@ -579,7 +597,7 @@
 		spin_lock(&sbi->fs_lock);
 		/* avoid rapid-fire expire attempts if expiry fails */
 		ino->last_used = now;
-		ino->flags &= ~AUTOFS_INF_EXPIRING;
+		ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
 		complete_all(&ino->expire_complete);
 		spin_unlock(&sbi->fs_lock);
 		dput(dentry);
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index c6d7d3d..7a54c6a 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -455,7 +455,7 @@
 		 * a mount-trap.
 		 */
 		struct inode *inode;
-		if (ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU))
+		if (ino->flags & AUTOFS_INF_WANT_EXPIRE)
 			return 0;
 		if (d_mountpoint(dentry))
 			return 0;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 0c52941..6c031dd 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -2295,6 +2295,7 @@
 				goto end_coredump;
 		}
 	}
+	dump_truncate(cprm);
 
 	if (!elf_core_write_extra_data(cprm))
 		goto end_coredump;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 44d4a1e..26bbaae 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -88,12 +88,11 @@
 {
 	struct address_space *mapping = bdev->bd_inode->i_mapping;
 
-	if (mapping->nrpages == 0)
-		return;
-
-	invalidate_bh_lrus();
-	lru_add_drain_all();	/* make sure all lru add caches are flushed */
-	invalidate_mapping_pages(mapping, 0, -1);
+	if (mapping->nrpages) {
+		invalidate_bh_lrus();
+		lru_add_drain_all();	/* make sure all lru add caches are flushed */
+		invalidate_mapping_pages(mapping, 0, -1);
+	}
 	/* 99% of the time, we don't need to flush the cleancache on the bdev.
 	 * But, for the strange corners, lets be cautious
 	 */
@@ -759,7 +758,7 @@
 		return true;	 /* already a holder */
 	else if (bdev->bd_holder != NULL)
 		return false; 	 /* held by someone else */
-	else if (bdev->bd_contains == bdev)
+	else if (whole == bdev)
 		return true;  	 /* is a whole device which isn't held */
 
 	else if (whole->bd_holder == bd_may_claim)
@@ -1098,7 +1097,6 @@
 
 	if (disk->fops->revalidate_disk)
 		ret = disk->fops->revalidate_disk(disk);
-	blk_integrity_revalidate(disk);
 	bdev = bdget_disk(disk, 0);
 	if (!bdev)
 		return ret;
@@ -1806,6 +1804,7 @@
 	spin_lock(&blockdev_superblock->s_inode_list_lock);
 	list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) {
 		struct address_space *mapping = inode->i_mapping;
+		struct block_device *bdev;
 
 		spin_lock(&inode->i_lock);
 		if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) ||
@@ -1826,8 +1825,12 @@
 		 */
 		iput(old_inode);
 		old_inode = inode;
+		bdev = I_BDEV(inode);
 
-		func(I_BDEV(inode), arg);
+		mutex_lock(&bdev->bd_mutex);
+		if (bdev->bd_openers)
+			func(bdev, arg);
+		mutex_unlock(&bdev->bd_mutex);
 
 		spin_lock(&blockdev_superblock->s_inode_list_lock);
 	}
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 9a0124a..fb3e64d 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -83,11 +83,9 @@
 	case ACL_TYPE_ACCESS:
 		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			ret = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (ret < 0)
+			ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (ret)
 				return ret;
-			if (ret == 0)
-				acl = NULL;
 		}
 		ret = 0;
 		break;
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c
index 9aba42b..a09264d 100644
--- a/fs/btrfs/async-thread.c
+++ b/fs/btrfs/async-thread.c
@@ -70,6 +70,20 @@
 	normal_work_helper(work);					\
 }
 
+bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq)
+{
+	/*
+	 * We could compare wq->normal->pending with num_online_cpus()
+	 * to support "thresh == NO_THRESHOLD" case, but it requires
+	 * moving up atomic_inc/dec in thresh_queue/exec_hook. Let's
+	 * postpone it until someone needs the support of that case.
+	 */
+	if (wq->normal->thresh == NO_THRESHOLD)
+		return false;
+
+	return atomic_read(&wq->normal->pending) > wq->normal->thresh * 2;
+}
+
 BTRFS_WORK_HELPER(worker_helper);
 BTRFS_WORK_HELPER(delalloc_helper);
 BTRFS_WORK_HELPER(flush_delalloc_helper);
diff --git a/fs/btrfs/async-thread.h b/fs/btrfs/async-thread.h
index ad4d064..8e1d657 100644
--- a/fs/btrfs/async-thread.h
+++ b/fs/btrfs/async-thread.h
@@ -80,4 +80,5 @@
 void btrfs_destroy_workqueue(struct btrfs_workqueue *wq);
 void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max);
 void btrfs_set_work_high_priority(struct btrfs_work *work);
+bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq);
 #endif
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index c473c42..bae05c5 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -694,7 +694,7 @@
 			ret = btrfs_map_bio(root, READ, comp_bio,
 					    mirror_num, 0);
 			if (ret) {
-				bio->bi_error = ret;
+				comp_bio->bi_error = ret;
 				bio_endio(comp_bio);
 			}
 
@@ -723,7 +723,7 @@
 
 	ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0);
 	if (ret) {
-		bio->bi_error = ret;
+		comp_bio->bi_error = ret;
 		bio_endio(comp_bio);
 	}
 
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 5b8e235..0f2b7c6 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1551,6 +1551,7 @@
 		       trans->transid, root->fs_info->generation);
 
 	if (!should_cow_block(trans, root, buf)) {
+		trans->dirty = true;
 		*cow_ret = buf;
 		return 0;
 	}
@@ -2773,8 +2774,10 @@
 			 * then we don't want to set the path blocking,
 			 * so we test it here
 			 */
-			if (!should_cow_block(trans, root, b))
+			if (!should_cow_block(trans, root, b)) {
+				trans->dirty = true;
 				goto cow_done;
+			}
 
 			/*
 			 * must have write locks on this node and the
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 385b449..e847573 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1770,6 +1770,7 @@
 	struct btrfs_workqueue *qgroup_rescan_workers;
 	struct completion qgroup_rescan_completion;
 	struct btrfs_work qgroup_rescan_work;
+	bool qgroup_rescan_running;	/* protected by qgroup_rescan_lock */
 
 	/* filesystem state */
 	unsigned long fs_state;
@@ -3069,6 +3070,8 @@
 	cpu->target = le64_to_cpu(disk->target);
 	cpu->flags = le64_to_cpu(disk->flags);
 	cpu->limit = le64_to_cpu(disk->limit);
+	cpu->stripes_min = le32_to_cpu(disk->stripes_min);
+	cpu->stripes_max = le32_to_cpu(disk->stripes_max);
 }
 
 static inline void
@@ -3087,6 +3090,8 @@
 	disk->target = cpu_to_le64(cpu->target);
 	disk->flags = cpu_to_le64(cpu->flags);
 	disk->limit = cpu_to_le64(cpu->limit);
+	disk->stripes_min = cpu_to_le32(cpu->stripes_min);
+	disk->stripes_max = cpu_to_le32(cpu->stripes_max);
 }
 
 /* struct btrfs_super_block */
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 02b934d..09fa5af 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1375,7 +1375,8 @@
 	total_done++;
 
 	btrfs_release_prepared_delayed_node(delayed_node);
-	if (async_work->nr == 0 || total_done < async_work->nr)
+	if ((async_work->nr == 0 && total_done < BTRFS_DELAYED_WRITEBACK) ||
+	    total_done < async_work->nr)
 		goto again;
 
 free_path:
@@ -1391,7 +1392,8 @@
 {
 	struct btrfs_async_delayed_work *async_work;
 
-	if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND)
+	if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND ||
+	    btrfs_workqueue_normal_congested(fs_info->delayed_workers))
 		return 0;
 
 	async_work = kmalloc(sizeof(*async_work), GFP_NOFS);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 41fb431..85b207d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2276,6 +2276,7 @@
 	fs_info->quota_enabled = 0;
 	fs_info->pending_quota_state = 0;
 	fs_info->qgroup_ulist = NULL;
+	fs_info->qgroup_rescan_running = false;
 	mutex_init(&fs_info->qgroup_rescan_lock);
 }
 
@@ -3811,7 +3812,7 @@
 	smp_mb();
 
 	/* wait for the qgroup rescan worker to stop */
-	btrfs_qgroup_wait_for_completion(fs_info);
+	btrfs_qgroup_wait_for_completion(fs_info, false);
 
 	/* wait for the uuid_scan task to finish */
 	down(&fs_info->uuid_tree_rescan_sem);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 2368cac..c36a03f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2520,11 +2520,11 @@
 		if (ref && ref->seq &&
 		    btrfs_check_delayed_seq(fs_info, delayed_refs, ref->seq)) {
 			spin_unlock(&locked_ref->lock);
-			btrfs_delayed_ref_unlock(locked_ref);
 			spin_lock(&delayed_refs->lock);
 			locked_ref->processing = 0;
 			delayed_refs->num_heads_ready++;
 			spin_unlock(&delayed_refs->lock);
+			btrfs_delayed_ref_unlock(locked_ref);
 			locked_ref = NULL;
 			cond_resched();
 			count++;
@@ -2570,7 +2570,10 @@
 					 */
 					if (must_insert_reserved)
 						locked_ref->must_insert_reserved = 1;
+					spin_lock(&delayed_refs->lock);
 					locked_ref->processing = 0;
+					delayed_refs->num_heads_ready++;
+					spin_unlock(&delayed_refs->lock);
 					btrfs_debug(fs_info, "run_delayed_extent_op returned %d", ret);
 					btrfs_delayed_ref_unlock(locked_ref);
 					return ret;
@@ -3851,6 +3854,7 @@
 				    info->space_info_kobj, "%s",
 				    alloc_name(found->flags));
 	if (ret) {
+		percpu_counter_destroy(&found->total_bytes_pinned);
 		kfree(found);
 		return ret;
 	}
@@ -7856,7 +7860,7 @@
 		set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
 			 buf->start + buf->len - 1, GFP_NOFS);
 	}
-	trans->blocks_used++;
+	trans->dirty = true;
 	/* this returns a buffer locked for blocking */
 	return buf;
 }
@@ -8486,14 +8490,13 @@
 	ret = btrfs_lookup_extent_info(trans, root, bytenr, level - 1, 1,
 				       &wc->refs[level - 1],
 				       &wc->flags[level - 1]);
-	if (ret < 0) {
-		btrfs_tree_unlock(next);
-		return ret;
-	}
+	if (ret < 0)
+		goto out_unlock;
 
 	if (unlikely(wc->refs[level - 1] == 0)) {
 		btrfs_err(root->fs_info, "Missing references.");
-		BUG();
+		ret = -EIO;
+		goto out_unlock;
 	}
 	*lookup_info = 0;
 
@@ -8545,7 +8548,12 @@
 	}
 
 	level--;
-	BUG_ON(level != btrfs_header_level(next));
+	ASSERT(level == btrfs_header_level(next));
+	if (level != btrfs_header_level(next)) {
+		btrfs_err(root->fs_info, "mismatched level");
+		ret = -EIO;
+		goto out_unlock;
+	}
 	path->nodes[level] = next;
 	path->slots[level] = 0;
 	path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
@@ -8560,8 +8568,15 @@
 		if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
 			parent = path->nodes[level]->start;
 		} else {
-			BUG_ON(root->root_key.objectid !=
+			ASSERT(root->root_key.objectid ==
 			       btrfs_header_owner(path->nodes[level]));
+			if (root->root_key.objectid !=
+			    btrfs_header_owner(path->nodes[level])) {
+				btrfs_err(root->fs_info,
+						"mismatched block owner");
+				ret = -EIO;
+				goto out_unlock;
+			}
 			parent = 0;
 		}
 
@@ -8578,12 +8593,18 @@
 		}
 		ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
 				root->root_key.objectid, level - 1, 0);
-		BUG_ON(ret); /* -ENOMEM */
+		if (ret)
+			goto out_unlock;
 	}
+
+	*lookup_info = 1;
+	ret = 1;
+
+out_unlock:
 	btrfs_tree_unlock(next);
 	free_extent_buffer(next);
-	*lookup_info = 1;
-	return 1;
+
+	return ret;
 }
 
 /*
@@ -9686,6 +9707,11 @@
 	struct extent_buffer *leaf;
 	int need_clear = 0;
 	u64 cache_gen;
+	u64 feature;
+	int mixed;
+
+	feature = btrfs_super_incompat_flags(info->super_copy);
+	mixed = !!(feature & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS);
 
 	root = info->extent_root;
 	key.objectid = 0;
@@ -9739,6 +9765,15 @@
 				   btrfs_item_ptr_offset(leaf, path->slots[0]),
 				   sizeof(cache->item));
 		cache->flags = btrfs_block_group_flags(&cache->item);
+		if (!mixed &&
+		    ((cache->flags & BTRFS_BLOCK_GROUP_METADATA) &&
+		    (cache->flags & BTRFS_BLOCK_GROUP_DATA))) {
+			btrfs_err(info,
+"bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups",
+				  cache->key.objectid);
+			ret = -EINVAL;
+			goto error;
+		}
 
 		key.objectid = found_key.objectid + found_key.offset;
 		btrfs_release_path(path);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 9abe187..e767f34 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2786,12 +2786,6 @@
 		btrfs_bio->csum = NULL;
 		btrfs_bio->csum_allocated = NULL;
 		btrfs_bio->end_io = NULL;
-
-#ifdef CONFIG_BLK_CGROUP
-		/* FIXME, put this into bio_clone_bioset */
-		if (bio->bi_css)
-			bio_associate_blkcg(new, bio->bi_css);
-#endif
 	}
 	return new;
 }
@@ -5300,11 +5294,20 @@
 			lock_page(page);
 		}
 		locked_pages++;
+	}
+	/*
+	 * We need to firstly lock all pages to make sure that
+	 * the uptodate bit of our pages won't be affected by
+	 * clear_extent_buffer_uptodate().
+	 */
+	for (i = start_i; i < num_pages; i++) {
+		page = eb->pages[i];
 		if (!PageUptodate(page)) {
 			num_reads++;
 			all_uptodate = 0;
 		}
 	}
+
 	if (all_uptodate) {
 		if (start_i == 0)
 			set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 5e5db36..d4a6eef 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1526,27 +1526,24 @@
 
 		reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
 
-		if (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
-					     BTRFS_INODE_PREALLOC)) {
-			ret = check_can_nocow(inode, pos, &write_bytes);
-			if (ret < 0)
-				break;
-			if (ret > 0) {
-				/*
-				 * For nodata cow case, no need to reserve
-				 * data space.
-				 */
-				only_release_metadata = true;
-				/*
-				 * our prealloc extent may be smaller than
-				 * write_bytes, so scale down.
-				 */
-				num_pages = DIV_ROUND_UP(write_bytes + offset,
-							 PAGE_CACHE_SIZE);
-				reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
-				goto reserve_metadata;
-			}
+		if ((BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
+					      BTRFS_INODE_PREALLOC)) &&
+		    check_can_nocow(inode, pos, &write_bytes) > 0) {
+			/*
+			 * For nodata cow case, no need to reserve
+			 * data space.
+			 */
+			only_release_metadata = true;
+			/*
+			 * our prealloc extent may be smaller than
+			 * write_bytes, so scale down.
+			 */
+			num_pages = DIV_ROUND_UP(write_bytes + offset,
+						 PAGE_CACHE_SIZE);
+			reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
+			goto reserve_metadata;
 		}
+
 		ret = btrfs_check_data_free_space(inode, pos, write_bytes);
 		if (ret < 0)
 			break;
@@ -2774,7 +2771,7 @@
 		if (!ret)
 			ret = btrfs_prealloc_file_range(inode, mode,
 					range->start,
-					range->len, 1 << inode->i_blkbits,
+					range->len, i_blocksize(inode),
 					offset + len, &alloc_hint);
 		list_del(&range->list);
 		kfree(range);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 4bc9dbf..a61926c 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4397,8 +4397,19 @@
 		if (found_type > min_type) {
 			del_item = 1;
 		} else {
-			if (item_end < new_size)
+			if (item_end < new_size) {
+				/*
+				 * With NO_HOLES mode, for the following mapping
+				 *
+				 * [0-4k][hole][8k-12k]
+				 *
+				 * if truncating isize down to 6k, it ends up
+				 * isize being 8k.
+				 */
+				if (btrfs_fs_incompat(root->fs_info, NO_HOLES))
+					last_size = new_size;
 				break;
+			}
 			if (found_key.offset >= new_size)
 				del_item = 1;
 			else
@@ -7318,8 +7329,8 @@
 	int found = false;
 	void **pagep = NULL;
 	struct page *page = NULL;
-	int start_idx;
-	int end_idx;
+	unsigned long start_idx;
+	unsigned long end_idx;
 
 	start_idx = start >> PAGE_CACHE_SHIFT;
 
@@ -8691,9 +8702,14 @@
 	 *    So even we call qgroup_free_data(), it won't decrease reserved
 	 *    space.
 	 * 2) Not written to disk
-	 *    This means the reserved space should be freed here.
+	 *    This means the reserved space should be freed here. However,
+	 *    if a truncate invalidates the page (by clearing PageDirty)
+	 *    and the page is accounted for while allocating extent
+	 *    in btrfs_check_data_free_space() we let delayed_ref to
+	 *    free the entire extent.
 	 */
-	btrfs_qgroup_free_data(inode, page_start, PAGE_CACHE_SIZE);
+	if (PageDirty(page))
+		btrfs_qgroup_free_data(inode, page_start, PAGE_SIZE);
 	if (!inode_evicting) {
 		clear_extent_bit(tree, page_start, page_end,
 				 EXTENT_LOCKED | EXTENT_DIRTY |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index f07d01b..317b99a 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1619,6 +1619,9 @@
 	int namelen;
 	int ret = 0;
 
+	if (!S_ISDIR(file_inode(file)->i_mode))
+		return -ENOTDIR;
+
 	ret = mnt_want_write_file(file);
 	if (ret)
 		goto out;
@@ -1648,7 +1651,7 @@
 
 		src_inode = file_inode(src.file);
 		if (src_inode->i_sb != file_inode(file)->i_sb) {
-			btrfs_info(BTRFS_I(src_inode)->root->fs_info,
+			btrfs_info(BTRFS_I(file_inode(file))->root->fs_info,
 				   "Snapshot src from another FS");
 			ret = -EXDEV;
 		} else if (!inode_owner_or_capable(src_inode)) {
@@ -1676,6 +1679,9 @@
 	struct btrfs_ioctl_vol_args *vol_args;
 	int ret;
 
+	if (!S_ISDIR(file_inode(file)->i_mode))
+		return -ENOTDIR;
+
 	vol_args = memdup_user(arg, sizeof(*vol_args));
 	if (IS_ERR(vol_args))
 		return PTR_ERR(vol_args);
@@ -1699,6 +1705,9 @@
 	bool readonly = false;
 	struct btrfs_qgroup_inherit *inherit = NULL;
 
+	if (!S_ISDIR(file_inode(file)->i_mode))
+		return -ENOTDIR;
+
 	vol_args = memdup_user(arg, sizeof(*vol_args));
 	if (IS_ERR(vol_args))
 		return PTR_ERR(vol_args);
@@ -2345,6 +2354,9 @@
 	int ret;
 	int err = 0;
 
+	if (!S_ISDIR(dir->i_mode))
+		return -ENOTDIR;
+
 	vol_args = memdup_user(arg, sizeof(*vol_args));
 	if (IS_ERR(vol_args))
 		return PTR_ERR(vol_args);
@@ -3813,6 +3825,11 @@
 		}
 		btrfs_release_path(path);
 		key.offset = next_key_min_offset;
+
+		if (fatal_signal_pending(current)) {
+			ret = -EINTR;
+			goto out;
+		}
 	}
 	ret = 0;
 
@@ -5121,7 +5138,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	return btrfs_qgroup_wait_for_completion(root->fs_info);
+	return btrfs_qgroup_wait_for_completion(root->fs_info, true);
 }
 
 static long _btrfs_ioctl_set_received_subvol(struct file *file,
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 5279fda..88d9b66 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -995,7 +995,7 @@
 		goto out;
 	fs_info->quota_enabled = 0;
 	fs_info->pending_quota_state = 0;
-	btrfs_qgroup_wait_for_completion(fs_info);
+	btrfs_qgroup_wait_for_completion(fs_info, false);
 	spin_lock(&fs_info->qgroup_lock);
 	quota_root = fs_info->quota_root;
 	fs_info->quota_root = NULL;
@@ -2349,6 +2349,9 @@
 	}
 
 done:
+	mutex_lock(&fs_info->qgroup_rescan_lock);
+	fs_info->qgroup_rescan_running = false;
+	mutex_unlock(&fs_info->qgroup_rescan_lock);
 	complete_all(&fs_info->qgroup_rescan_completion);
 }
 
@@ -2390,6 +2393,7 @@
 		sizeof(fs_info->qgroup_rescan_progress));
 	fs_info->qgroup_rescan_progress.objectid = progress_objectid;
 	init_completion(&fs_info->qgroup_rescan_completion);
+	fs_info->qgroup_rescan_running = true;
 
 	spin_unlock(&fs_info->qgroup_lock);
 	mutex_unlock(&fs_info->qgroup_rescan_lock);
@@ -2467,20 +2471,26 @@
 	return 0;
 }
 
-int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info)
+int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info,
+				     bool interruptible)
 {
 	int running;
 	int ret = 0;
 
 	mutex_lock(&fs_info->qgroup_rescan_lock);
 	spin_lock(&fs_info->qgroup_lock);
-	running = fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN;
+	running = fs_info->qgroup_rescan_running;
 	spin_unlock(&fs_info->qgroup_lock);
 	mutex_unlock(&fs_info->qgroup_rescan_lock);
 
-	if (running)
+	if (!running)
+		return 0;
+
+	if (interruptible)
 		ret = wait_for_completion_interruptible(
 					&fs_info->qgroup_rescan_completion);
+	else
+		wait_for_completion(&fs_info->qgroup_rescan_completion);
 
 	return ret;
 }
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
index ecb2c14..3d73e4c 100644
--- a/fs/btrfs/qgroup.h
+++ b/fs/btrfs/qgroup.h
@@ -46,7 +46,8 @@
 			struct btrfs_fs_info *fs_info);
 int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
 void btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info);
-int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info);
+int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info,
+				     bool interruptible);
 int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
 			      struct btrfs_fs_info *fs_info, u64 src, u64 dst);
 int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index b4ca545..8ca9aa9 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -921,9 +921,16 @@
 			path2->slots[level]--;
 
 		eb = path2->nodes[level];
-		WARN_ON(btrfs_node_blockptr(eb, path2->slots[level]) !=
-			cur->bytenr);
-
+		if (btrfs_node_blockptr(eb, path2->slots[level]) !=
+		    cur->bytenr) {
+			btrfs_err(root->fs_info,
+	"couldn't find block (%llu) (level %d) in tree (%llu) with key (%llu %u %llu)",
+				  cur->bytenr, level - 1, root->objectid,
+				  node_key->objectid, node_key->type,
+				  node_key->offset);
+			err = -ENOENT;
+			goto out;
+		}
 		lower = cur;
 		need_check = true;
 		for (; level < BTRFS_MAX_LEVEL; level++) {
@@ -2343,6 +2350,10 @@
 	while (!list_empty(list)) {
 		reloc_root = list_entry(list->next, struct btrfs_root,
 					root_list);
+		free_extent_buffer(reloc_root->node);
+		free_extent_buffer(reloc_root->commit_root);
+		reloc_root->node = NULL;
+		reloc_root->commit_root = NULL;
 		__del_reloc_root(reloc_root);
 	}
 }
@@ -2676,11 +2687,15 @@
 
 		if (!upper->eb) {
 			ret = btrfs_search_slot(trans, root, key, path, 0, 1);
-			if (ret < 0) {
-				err = ret;
+			if (ret) {
+				if (ret < 0)
+					err = ret;
+				else
+					err = -ENOENT;
+
+				btrfs_release_path(path);
 				break;
 			}
-			BUG_ON(ret > 0);
 
 			if (!upper->eb) {
 				upper->eb = path->nodes[upper->level];
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index fe609b8..5d34a06 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -239,7 +239,7 @@
 	trans->aborted = errno;
 	/* Nothing used. The other threads that have joined this
 	 * transaction may be able to continue. */
-	if (!trans->blocks_used && list_empty(&trans->new_bgs)) {
+	if (!trans->dirty && list_empty(&trans->new_bgs)) {
 		const char *errstr;
 
 		errstr = btrfs_decode_error(errno);
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 64c8221..1e87292 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -110,7 +110,6 @@
 	u64 chunk_bytes_reserved;
 	unsigned long use_count;
 	unsigned long blocks_reserved;
-	unsigned long blocks_used;
 	unsigned long delayed_ref_updates;
 	struct btrfs_transaction *transaction;
 	struct btrfs_block_rsv *block_rsv;
@@ -121,6 +120,7 @@
 	bool can_flush_pending_bgs;
 	bool reloc_reserved;
 	bool sync;
+	bool dirty;
 	unsigned int type;
 	/*
 	 * this root is only needed to validate that the root passed to
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 0e044d7..ee7832e 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1923,12 +1923,11 @@
 next:
 	/* check the next slot in the tree to see if it is a valid item */
 	nritems = btrfs_header_nritems(path->nodes[0]);
+	path->slots[0]++;
 	if (path->slots[0] >= nritems) {
 		ret = btrfs_next_leaf(root, path);
 		if (ret)
 			goto out;
-	} else {
-		path->slots[0]++;
 	}
 
 	btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
@@ -2696,14 +2695,12 @@
 					     int index, int error)
 {
 	struct btrfs_log_ctx *ctx;
+	struct btrfs_log_ctx *safe;
 
-	if (!error) {
-		INIT_LIST_HEAD(&root->log_ctxs[index]);
-		return;
-	}
-
-	list_for_each_entry(ctx, &root->log_ctxs[index], list)
+	list_for_each_entry_safe(ctx, safe, &root->log_ctxs[index], list) {
+		list_del_init(&ctx->list);
 		ctx->log_ret = error;
+	}
 
 	INIT_LIST_HEAD(&root->log_ctxs[index]);
 }
@@ -2850,6 +2847,7 @@
 
 	if (log_root_tree->log_transid_committed >= root_log_ctx.log_transid) {
 		blk_finish_plug(&plug);
+		list_del_init(&root_log_ctx.list);
 		mutex_unlock(&log_root_tree->log_mutex);
 		ret = root_log_ctx.log_ret;
 		goto out;
@@ -2943,13 +2941,9 @@
 	mutex_unlock(&root->log_mutex);
 
 out_wake_log_root:
-	/*
-	 * We needn't get log_mutex here because we are sure all
-	 * the other tasks are blocked.
-	 */
+	mutex_lock(&log_root_tree->log_mutex);
 	btrfs_remove_all_log_ctxs(log_root_tree, index2, ret);
 
-	mutex_lock(&log_root_tree->log_mutex);
 	log_root_tree->log_transid_committed++;
 	atomic_set(&log_root_tree->log_commit[index2], 0);
 	mutex_unlock(&log_root_tree->log_mutex);
@@ -2960,10 +2954,8 @@
 	if (waitqueue_active(&log_root_tree->log_commit_wait[index2]))
 		wake_up(&log_root_tree->log_commit_wait[index2]);
 out:
-	/* See above. */
-	btrfs_remove_all_log_ctxs(root, index1, ret);
-
 	mutex_lock(&root->log_mutex);
+	btrfs_remove_all_log_ctxs(root, index1, ret);
 	root->log_transid_committed++;
 	atomic_set(&root->log_commit[index1], 0);
 	mutex_unlock(&root->log_mutex);
diff --git a/fs/buffer.c b/fs/buffer.c
index 4f4cd95..6f7d519 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2298,7 +2298,7 @@
 			    loff_t pos, loff_t *bytes)
 {
 	struct inode *inode = mapping->host;
-	unsigned blocksize = 1 << inode->i_blkbits;
+	unsigned int blocksize = i_blocksize(inode);
 	struct page *page;
 	void *fsdata;
 	pgoff_t index, curidx;
@@ -2378,8 +2378,8 @@
 			get_block_t *get_block, loff_t *bytes)
 {
 	struct inode *inode = mapping->host;
-	unsigned blocksize = 1 << inode->i_blkbits;
-	unsigned zerofrom;
+	unsigned int blocksize = i_blocksize(inode);
+	unsigned int zerofrom;
 	int err;
 
 	err = cont_expand_zero(file, mapping, pos, bytes);
@@ -2741,7 +2741,7 @@
 	struct buffer_head map_bh;
 	int err;
 
-	blocksize = 1 << inode->i_blkbits;
+	blocksize = i_blocksize(inode);
 	length = offset & (blocksize - 1);
 
 	/* Block boundary? Nothing to do */
@@ -2819,7 +2819,7 @@
 	struct buffer_head *bh;
 	int err;
 
-	blocksize = 1 << inode->i_blkbits;
+	blocksize = i_blocksize(inode);
 	length = offset & (blocksize - 1);
 
 	/* Block boundary? Nothing to do */
@@ -2931,7 +2931,7 @@
 	struct inode *inode = mapping->host;
 	tmp.b_state = 0;
 	tmp.b_blocknr = 0;
-	tmp.b_size = 1 << inode->i_blkbits;
+	tmp.b_size = i_blocksize(inode);
 	get_block(inode, block, &tmp, 0);
 	return tmp.b_blocknr;
 }
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index 8f84646..bdb9c94 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -94,11 +94,9 @@
 	case ACL_TYPE_ACCESS:
 		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			ret = posix_acl_equiv_mode(acl, &new_mode);
-			if (ret < 0)
+			ret = posix_acl_update_mode(inode, &new_mode, &acl);
+			if (ret)
 				goto out;
-			if (ret == 0)
-				acl = NULL;
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
@@ -130,7 +128,7 @@
 	if (new_mode != old_mode) {
 		newattrs.ia_mode = new_mode;
 		newattrs.ia_valid = ATTR_MODE;
-		ret = ceph_setattr(dentry, &newattrs);
+		ret = __ceph_setattr(dentry, &newattrs);
 		if (ret)
 			goto out_dput;
 	}
@@ -140,7 +138,7 @@
 		if (new_mode != old_mode) {
 			newattrs.ia_mode = old_mode;
 			newattrs.ia_valid = ATTR_MODE;
-			ceph_setattr(dentry, &newattrs);
+			__ceph_setattr(dentry, &newattrs);
 		}
 		goto out_dput;
 	}
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index b7d218a..c6a1ec1 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -697,7 +697,7 @@
 	struct pagevec pvec;
 	int done = 0;
 	int rc = 0;
-	unsigned wsize = 1 << inode->i_blkbits;
+	unsigned int wsize = i_blocksize(inode);
 	struct ceph_osd_request *req = NULL;
 	int do_sync = 0;
 	loff_t snap_size, i_size;
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 3c68e6a..c8222bf 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -929,7 +929,8 @@
 		statret = __ceph_do_getattr(inode, page,
 					    CEPH_STAT_CAP_INLINE_DATA, !!page);
 		if (statret < 0) {
-			 __free_page(page);
+			if (page)
+				__free_page(page);
 			if (statret == -ENODATA) {
 				BUG_ON(retry_op != READ_INLINE);
 				goto again;
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 498dcfa..9f0d990 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1358,15 +1358,20 @@
 
 	if (!ctl->page || pgoff != page_index(ctl->page)) {
 		ceph_readdir_cache_release(ctl);
-		ctl->page  = grab_cache_page(&dir->i_data, pgoff);
+		if (idx == 0)
+			ctl->page = grab_cache_page(&dir->i_data, pgoff);
+		else
+			ctl->page = find_lock_page(&dir->i_data, pgoff);
 		if (!ctl->page) {
 			ctl->index = -1;
-			return -ENOMEM;
+			return idx == 0 ? -ENOMEM : 0;
 		}
 		/* reading/filling the cache are serialized by
 		 * i_mutex, no need to use page lock */
 		unlock_page(ctl->page);
 		ctl->dentries = kmap(ctl->page);
+		if (idx == 0)
+			memset(ctl->dentries, 0, PAGE_CACHE_SIZE);
 	}
 
 	if (req->r_dir_release_cnt == atomic64_read(&ci->i_release_count) &&
@@ -1768,7 +1773,7 @@
 /*
  * setattr
  */
-int ceph_setattr(struct dentry *dentry, struct iattr *attr)
+int __ceph_setattr(struct dentry *dentry, struct iattr *attr)
 {
 	struct inode *inode = d_inode(dentry);
 	struct ceph_inode_info *ci = ceph_inode(inode);
@@ -1970,11 +1975,6 @@
 	if (inode_dirty_flags)
 		__mark_inode_dirty(inode, inode_dirty_flags);
 
-	if (ia_valid & ATTR_MODE) {
-		err = posix_acl_chmod(inode, attr->ia_mode);
-		if (err)
-			goto out_put;
-	}
 
 	if (mask) {
 		req->r_inode = inode;
@@ -1988,13 +1988,23 @@
 	     ceph_cap_string(dirtied), mask);
 
 	ceph_mdsc_put_request(req);
-	if (mask & CEPH_SETATTR_SIZE)
+	ceph_free_cap_flush(prealloc_cf);
+
+	if (err >= 0 && (mask & CEPH_SETATTR_SIZE))
 		__ceph_do_pending_vmtruncate(inode);
-	ceph_free_cap_flush(prealloc_cf);
+
 	return err;
-out_put:
-	ceph_mdsc_put_request(req);
-	ceph_free_cap_flush(prealloc_cf);
+}
+
+int ceph_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	int err;
+
+	err = __ceph_setattr(dentry, attr);
+
+	if (err >= 0 && (attr->ia_valid & ATTR_MODE))
+		err = posix_acl_chmod(d_inode(dentry), attr->ia_mode);
+
 	return err;
 }
 
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index e7b130a..f54f770 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -274,12 +274,13 @@
 				  struct ceph_mds_reply_info_parsed *info,
 				  u64 features)
 {
-	if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
+	u32 op = le32_to_cpu(info->head->op);
+
+	if (op == CEPH_MDS_OP_GETFILELOCK)
 		return parse_reply_info_filelock(p, end, info, features);
-	else if (info->head->op == CEPH_MDS_OP_READDIR ||
-		 info->head->op == CEPH_MDS_OP_LSSNAP)
+	else if (op == CEPH_MDS_OP_READDIR || op == CEPH_MDS_OP_LSSNAP)
 		return parse_reply_info_dir(p, end, info, features);
-	else if (info->head->op == CEPH_MDS_OP_CREATE)
+	else if (op == CEPH_MDS_OP_CREATE)
 		return parse_reply_info_create(p, end, info, features);
 	else
 		return -EIO;
@@ -643,6 +644,9 @@
 {
 	dout("__unregister_request %p tid %lld\n", req, req->r_tid);
 
+	/* Never leave an unregistered request on an unsafe list! */
+	list_del_init(&req->r_unsafe_item);
+
 	if (req->r_tid == mdsc->oldest_tid) {
 		struct rb_node *p = rb_next(&req->r_node);
 		mdsc->oldest_tid = 0;
@@ -1050,7 +1054,6 @@
 	while (!list_empty(&session->s_unsafe)) {
 		req = list_first_entry(&session->s_unsafe,
 				       struct ceph_mds_request, r_unsafe_item);
-		list_del_init(&req->r_unsafe_item);
 		pr_warn_ratelimited(" dropping unsafe request %llu\n",
 				    req->r_tid);
 		__unregister_request(mdsc, req);
@@ -2476,7 +2479,6 @@
 			 * useful we could do with a revised return value.
 			 */
 			dout("got safe reply %llu, mds%d\n", tid, mds);
-			list_del_init(&req->r_unsafe_item);
 
 			/* last unsafe request during umount? */
 			if (mdsc->stopping && !__get_oldest_req(mdsc))
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 75b7d12..8c8cb8f 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -788,6 +788,7 @@
 	return __ceph_do_getattr(inode, NULL, mask, force);
 }
 extern int ceph_permission(struct inode *inode, int mask);
+extern int __ceph_setattr(struct dentry *dentry, struct iattr *attr);
 extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
 extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
 			struct kstat *stat);
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 819163d..b24275e 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -369,6 +369,7 @@
 
 	if (update_xattr) {
 		int err = 0;
+
 		if (xattr && (flags & XATTR_CREATE))
 			err = -EEXIST;
 		else if (!xattr && (flags & XATTR_REPLACE))
@@ -376,12 +377,14 @@
 		if (err) {
 			kfree(name);
 			kfree(val);
+			kfree(*newxattr);
 			return err;
 		}
 		if (update_xattr < 0) {
 			if (xattr)
 				__remove_xattr(ci, xattr);
 			kfree(name);
+			kfree(*newxattr);
 			return 0;
 		}
 	}
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 50b2684..0a3544f 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -152,6 +152,7 @@
 	list_for_each(tmp1, &cifs_tcp_ses_list) {
 		server = list_entry(tmp1, struct TCP_Server_Info,
 				    tcp_ses_list);
+		seq_printf(m, "\nNumber of credits: %d", server->credits);
 		i++;
 		list_for_each(tmp2, &server->smb_ses_list) {
 			ses = list_entry(tmp2, struct cifs_ses,
@@ -255,7 +256,6 @@
 static ssize_t cifs_stats_proc_write(struct file *file,
 		const char __user *buffer, size_t count, loff_t *ppos)
 {
-	char c;
 	bool bv;
 	int rc;
 	struct list_head *tmp1, *tmp2, *tmp3;
@@ -263,11 +263,8 @@
 	struct cifs_ses *ses;
 	struct cifs_tcon *tcon;
 
-	rc = get_user(c, buffer);
-	if (rc)
-		return rc;
-
-	if (strtobool(&c, &bv) == 0) {
+	rc = kstrtobool_from_user(buffer, count, &bv);
+	if (rc == 0) {
 #ifdef CONFIG_CIFS_STATS2
 		atomic_set(&totBufAllocCount, 0);
 		atomic_set(&totSmBufAllocCount, 0);
@@ -290,6 +287,8 @@
 			}
 		}
 		spin_unlock(&cifs_tcp_ses_lock);
+	} else {
+		return rc;
 	}
 
 	return count;
@@ -433,17 +432,17 @@
 static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
 		size_t count, loff_t *ppos)
 {
-	char c;
+	char c[2] = { '\0' };
 	bool bv;
 	int rc;
 
-	rc = get_user(c, buffer);
+	rc = get_user(c[0], buffer);
 	if (rc)
 		return rc;
-	if (strtobool(&c, &bv) == 0)
+	if (strtobool(c, &bv) == 0)
 		cifsFYI = bv;
-	else if ((c > '1') && (c <= '9'))
-		cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
+	else if ((c[0] > '1') && (c[0] <= '9'))
+		cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */
 
 	return count;
 }
@@ -471,20 +470,12 @@
 static ssize_t cifs_linux_ext_proc_write(struct file *file,
 		const char __user *buffer, size_t count, loff_t *ppos)
 {
-	char c;
-	bool bv;
 	int rc;
 
-	rc = get_user(c, buffer);
+	rc = kstrtobool_from_user(buffer, count, &linuxExtEnabled);
 	if (rc)
 		return rc;
 
-	rc = strtobool(&c, &bv);
-	if (rc)
-		return rc;
-
-	linuxExtEnabled = bv;
-
 	return count;
 }
 
@@ -511,20 +502,12 @@
 static ssize_t cifs_lookup_cache_proc_write(struct file *file,
 		const char __user *buffer, size_t count, loff_t *ppos)
 {
-	char c;
-	bool bv;
 	int rc;
 
-	rc = get_user(c, buffer);
+	rc = kstrtobool_from_user(buffer, count, &lookupCacheEnabled);
 	if (rc)
 		return rc;
 
-	rc = strtobool(&c, &bv);
-	if (rc)
-		return rc;
-
-	lookupCacheEnabled = bv;
-
 	return count;
 }
 
@@ -551,20 +534,12 @@
 static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
 		size_t count, loff_t *ppos)
 {
-	char c;
-	bool bv;
 	int rc;
 
-	rc = get_user(c, buffer);
+	rc = kstrtobool_from_user(buffer, count, &traceSMB);
 	if (rc)
 		return rc;
 
-	rc = strtobool(&c, &bv);
-	if (rc)
-		return rc;
-
-	traceSMB = bv;
-
 	return count;
 }
 
@@ -622,7 +597,6 @@
 	int rc;
 	unsigned int flags;
 	char flags_string[12];
-	char c;
 	bool bv;
 
 	if ((count < 1) || (count > 11))
@@ -635,11 +609,10 @@
 
 	if (count < 3) {
 		/* single char or single char followed by null */
-		c = flags_string[0];
-		if (strtobool(&c, &bv) == 0) {
+		if (strtobool(flags_string, &bv) == 0) {
 			global_secflags = bv ? CIFSSEC_MAX : CIFSSEC_DEF;
 			return count;
-		} else if (!isdigit(c)) {
+		} else if (!isdigit(flags_string[0])) {
 			cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
 					flags_string);
 			return -EINVAL;
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index 66cf0f9..c611ca2 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -25,7 +25,7 @@
 void cifs_dump_mem(char *label, void *data, int length);
 void cifs_dump_detail(void *);
 void cifs_dump_mids(struct TCP_Server_Info *);
-extern int traceSMB;		/* flag which enables the function below */
+extern bool traceSMB;		/* flag which enables the function below */
 void dump_smb(void *, int);
 #define CIFS_INFO	0x01
 #define CIFS_RC		0x02
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 3182273..1418daa 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -46,6 +46,9 @@
 #define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */
 #define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */
 #define CIFS_MOUNT_MAP_SFM_CHR	0x800000 /* SFM/MAC mapping for illegal chars */
+#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000 /* make subpath with unaccessible
+					      * root mountable
+					      */
 
 struct cifs_sb_info {
 	struct rb_root tlink_tree;
@@ -67,5 +70,6 @@
 	struct backing_dev_info bdi;
 	struct delayed_work prune_tlinks;
 	struct rcu_head rcu;
+	char *prepath;
 };
 #endif				/* _CIFS_FS_SB_H */
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 5a53ac6..a0b3e7d 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -83,6 +83,9 @@
 	case SFM_COLON:
 		*target = ':';
 		break;
+	case SFM_DOUBLEQUOTE:
+		*target = '"';
+		break;
 	case SFM_ASTERISK:
 		*target = '*';
 		break;
@@ -101,6 +104,12 @@
 	case SFM_SLASH:
 		*target = '\\';
 		break;
+	case SFM_SPACE:
+		*target = ' ';
+		break;
+	case SFM_PERIOD:
+		*target = '.';
+		break;
 	default:
 		return false;
 	}
@@ -404,7 +413,7 @@
 	return dest_char;
 }
 
-static __le16 convert_to_sfm_char(char src_char)
+static __le16 convert_to_sfm_char(char src_char, bool end_of_string)
 {
 	__le16 dest_char;
 
@@ -412,6 +421,9 @@
 	case ':':
 		dest_char = cpu_to_le16(SFM_COLON);
 		break;
+	case '"':
+		dest_char = cpu_to_le16(SFM_DOUBLEQUOTE);
+		break;
 	case '*':
 		dest_char = cpu_to_le16(SFM_ASTERISK);
 		break;
@@ -427,6 +439,18 @@
 	case '|':
 		dest_char = cpu_to_le16(SFM_PIPE);
 		break;
+	case '.':
+		if (end_of_string)
+			dest_char = cpu_to_le16(SFM_PERIOD);
+		else
+			dest_char = 0;
+		break;
+	case ' ':
+		if (end_of_string)
+			dest_char = cpu_to_le16(SFM_SPACE);
+		else
+			dest_char = 0;
+		break;
 	default:
 		dest_char = 0;
 	}
@@ -469,9 +493,16 @@
 		/* see if we must remap this char */
 		if (map_chars == SFU_MAP_UNI_RSVD)
 			dst_char = convert_to_sfu_char(src_char);
-		else if (map_chars == SFM_MAP_UNI_RSVD)
-			dst_char = convert_to_sfm_char(src_char);
-		else
+		else if (map_chars == SFM_MAP_UNI_RSVD) {
+			bool end_of_string;
+
+			if (i == srclen - 1)
+				end_of_string = true;
+			else
+				end_of_string = false;
+
+			dst_char = convert_to_sfm_char(src_char, end_of_string);
+		} else
 			dst_char = 0;
 		/*
 		 * FIXME: We can not handle remapping backslash (UNI_SLASH)
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index bdc52cb..07ade70 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -57,6 +57,7 @@
  * not conflict (although almost does) with the mapping above.
  */
 
+#define SFM_DOUBLEQUOTE ((__u16) 0xF020)
 #define SFM_ASTERISK    ((__u16) 0xF021)
 #define SFM_QUESTION    ((__u16) 0xF025)
 #define SFM_COLON       ((__u16) 0xF022)
@@ -64,6 +65,8 @@
 #define SFM_LESSTHAN    ((__u16) 0xF023)
 #define SFM_PIPE        ((__u16) 0xF027)
 #define SFM_SLASH       ((__u16) 0xF026)
+#define SFM_SPACE	((__u16) 0xF028)
+#define SFM_PERIOD	((__u16) 0xF029)
 
 /*
  * Mapping mechanism to use when one of the seven reserved characters is
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index e682b36..4acbc39 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -731,24 +731,26 @@
 
 	memcpy(ses->auth_key.response + baselen, tiblob, tilen);
 
+	mutex_lock(&ses->server->srv_mutex);
+
 	rc = crypto_hmacmd5_alloc(ses->server);
 	if (rc) {
 		cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
-		goto setup_ntlmv2_rsp_ret;
+		goto unlock;
 	}
 
 	/* calculate ntlmv2_hash */
 	rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
 	if (rc) {
 		cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
-		goto setup_ntlmv2_rsp_ret;
+		goto unlock;
 	}
 
 	/* calculate first part of the client response (CR1) */
 	rc = CalcNTLMv2_response(ses, ntlmv2_hash);
 	if (rc) {
 		cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
-		goto setup_ntlmv2_rsp_ret;
+		goto unlock;
 	}
 
 	/* now calculate the session key for NTLMv2 */
@@ -757,13 +759,13 @@
 	if (rc) {
 		cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
 			 __func__);
-		goto setup_ntlmv2_rsp_ret;
+		goto unlock;
 	}
 
 	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 	if (rc) {
 		cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
-		goto setup_ntlmv2_rsp_ret;
+		goto unlock;
 	}
 
 	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
@@ -771,7 +773,7 @@
 		CIFS_HMAC_MD5_HASH_SIZE);
 	if (rc) {
 		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
-		goto setup_ntlmv2_rsp_ret;
+		goto unlock;
 	}
 
 	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
@@ -779,6 +781,8 @@
 	if (rc)
 		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 
+unlock:
+	mutex_unlock(&ses->server->srv_mutex);
 setup_ntlmv2_rsp_ret:
 	kfree(tiblob);
 
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index cbc0f4b..4f4fc9f 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -54,10 +54,10 @@
 #endif
 
 int cifsFYI = 0;
-int traceSMB = 0;
+bool traceSMB;
 bool enable_oplocks = true;
-unsigned int linuxExtEnabled = 1;
-unsigned int lookupCacheEnabled = 1;
+bool linuxExtEnabled = true;
+bool lookupCacheEnabled = true;
 unsigned int global_secflags = CIFSSEC_DEF;
 /* unsigned int ntlmv2_support = 0; */
 unsigned int sign_CIFS_PDUs = 1;
@@ -268,7 +268,7 @@
 	cifs_inode->createtime = 0;
 	cifs_inode->epoch = 0;
 #ifdef CONFIG_CIFS_SMB2
-	get_random_bytes(cifs_inode->lease_key, SMB2_LEASE_KEY_SIZE);
+	generate_random_uuid(cifs_inode->lease_key);
 #endif
 	/*
 	 * Can not set i_flags here - they get immediately overwritten to zero
@@ -686,6 +686,14 @@
 		goto out_cifs_sb;
 	}
 
+	if (volume_info->prepath) {
+		cifs_sb->prepath = kstrdup(volume_info->prepath, GFP_KERNEL);
+		if (cifs_sb->prepath == NULL) {
+			root = ERR_PTR(-ENOMEM);
+			goto out_cifs_sb;
+		}
+	}
+
 	cifs_setup_cifs_sb(volume_info, cifs_sb);
 
 	rc = cifs_mount(cifs_sb, volume_info);
@@ -724,7 +732,11 @@
 		sb->s_flags |= MS_ACTIVE;
 	}
 
-	root = cifs_get_root(volume_info, sb);
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
+		root = dget(sb->s_root);
+	else
+		root = cifs_get_root(volume_info, sb);
+
 	if (IS_ERR(root))
 		goto out_super;
 
@@ -1198,7 +1210,6 @@
 	GlobalTotalActiveXid = 0;
 	GlobalMaxActiveXid = 0;
 	spin_lock_init(&cifs_tcp_ses_lock);
-	spin_lock_init(&cifs_file_list_lock);
 	spin_lock_init(&GlobalMid_Lock);
 
 	if (cifs_max_pending < 2) {
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 2b510c5..e2f6a79 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -227,6 +227,7 @@
 	/* verify the message */
 	int (*check_message)(char *, unsigned int);
 	bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
+	int (*handle_cancelled_mid)(char *, struct TCP_Server_Info *);
 	void (*downgrade_oplock)(struct TCP_Server_Info *,
 					struct cifsInodeInfo *, bool);
 	/* process transaction2 response */
@@ -627,6 +628,8 @@
 #ifdef CONFIG_CIFS_SMB2
 	unsigned int	max_read;
 	unsigned int	max_write;
+	struct delayed_work reconnect; /* reconnect workqueue job */
+	struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
 #endif /* CONFIG_CIFS_SMB2 */
 };
 
@@ -826,7 +829,9 @@
 struct cifs_tcon {
 	struct list_head tcon_list;
 	int tc_count;
+	struct list_head rlist; /* reconnect list */
 	struct list_head openFileList;
+	spinlock_t open_file_lock; /* protects list above */
 	struct cifs_ses *ses;	/* pointer to session associated with */
 	char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
 	char *nativeFileSystem;
@@ -883,7 +888,7 @@
 #endif /* CONFIG_CIFS_STATS2 */
 	__u64    bytes_read;
 	__u64    bytes_written;
-	spinlock_t stat_lock;
+	spinlock_t stat_lock;  /* protects the two fields above */
 #endif /* CONFIG_CIFS_STATS */
 	FILE_SYSTEM_DEVICE_INFO fsDevInfo;
 	FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
@@ -902,7 +907,6 @@
 	bool use_persistent:1; /* use persistent instead of durable handles */
 #ifdef CONFIG_CIFS_SMB2
 	bool print:1;		/* set if connection to printer share */
-	bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */
 	__le32 capabilities;
 	__u32 share_flags;
 	__u32 maximal_access;
@@ -1034,8 +1038,10 @@
 };
 
 struct cifsFileInfo {
+	/* following two lists are protected by tcon->open_file_lock */
 	struct list_head tlist;	/* pointer to next fid owned by tcon */
 	struct list_head flist;	/* next fid (file instance) for this inode */
+	/* lock list below protected by cifsi->lock_sem */
 	struct cifs_fid_locks *llist;	/* brlocks held by this fid */
 	kuid_t uid;		/* allows finding which FileInfo structure */
 	__u32 pid;		/* process id who opened file */
@@ -1043,11 +1049,12 @@
 	/* BB add lock scope info here if needed */ ;
 	/* lock scope id (0 if none) */
 	struct dentry *dentry;
-	unsigned int f_flags;
 	struct tcon_link *tlink;
+	unsigned int f_flags;
 	bool invalidHandle:1;	/* file closed via session abend */
 	bool oplock_break_cancelled:1;
-	int count;		/* refcount protected by cifs_file_list_lock */
+	int count;
+	spinlock_t file_info_lock; /* protects four flag/count fields above */
 	struct mutex fh_mutex; /* prevents reopen race after dead ses*/
 	struct cifs_search_info srch_inf;
 	struct work_struct oplock_break; /* work for oplock breaks */
@@ -1114,7 +1121,7 @@
 
 /*
  * Take a reference on the file private data. Must be called with
- * cifs_file_list_lock held.
+ * cfile->file_info_lock held.
  */
 static inline void
 cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
@@ -1283,12 +1290,19 @@
 	void *callback_data;	  /* general purpose pointer for callback */
 	void *resp_buf;		/* pointer to received SMB header */
 	int mid_state;	/* wish this were enum but can not pass to wait_event */
+	unsigned int mid_flags;
 	__le16 command;		/* smb command code */
 	bool large_buf:1;	/* if valid response, is pointer to large buf */
 	bool multiRsp:1;	/* multiple trans2 responses for one request  */
 	bool multiEnd:1;	/* both received */
 };
 
+struct close_cancelled_open {
+	struct cifs_fid         fid;
+	struct cifs_tcon        *tcon;
+	struct work_struct      work;
+};
+
 /*	Make code in transport.c a little cleaner by moving
 	update of optional stats into function below */
 #ifdef CONFIG_CIFS_STATS2
@@ -1420,6 +1434,9 @@
 #define   MID_RESPONSE_MALFORMED 0x10
 #define   MID_SHUTDOWN		 0x20
 
+/* Flags */
+#define   MID_WAIT_CANCELLED	 1 /* Cancelled while waiting for response */
+
 /* Types of response buffer returned from SendReceive2 */
 #define   CIFS_NO_BUFFER        0    /* Response buffer not returned */
 #define   CIFS_SMALL_BUFFER     1
@@ -1508,8 +1525,10 @@
  *  GlobalMid_Lock protects:
  *	list operations on pending_mid_q and oplockQ
  *      updates to XID counters, multiplex id  and SMB sequence numbers
- *  cifs_file_list_lock protects:
- *	list operations on tcp and SMB session lists and tCon lists
+ *  tcp_ses_lock protects:
+ *	list operations on tcp and SMB session lists
+ *  tcon->open_file_lock protects the list of open files hanging off the tcon
+ *  cfile->file_info_lock protects counters and fields in cifs file struct
  *  f_owner.lock protects certain per file struct operations
  *  mapping->page_lock protects certain per page operations
  *
@@ -1541,18 +1560,12 @@
  * tcp session, and the list of tcon's per smb session. It also protects
  * the reference counters for the server, smb session, and tcon. Finally,
  * changes to the tcon->tidStatus should be done while holding this lock.
+ * generally the locks should be taken in order tcp_ses_lock before
+ * tcon->open_file_lock and that before file->file_info_lock since the
+ * structure order is cifs_socket-->cifs_ses-->cifs_tcon-->cifs_file
  */
 GLOBAL_EXTERN spinlock_t		cifs_tcp_ses_lock;
 
-/*
- * This lock protects the cifs_file->llist and cifs_file->flist
- * list operations, and updates to some flags (cifs_file->invalidHandle)
- * It will be moved to either use the tcon->stat_lock or equivalent later.
- * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
- * the cifs_tcp_ses_lock must be grabbed first and released last.
- */
-GLOBAL_EXTERN spinlock_t	cifs_file_list_lock;
-
 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
 /* Outstanding dir notify requests */
 GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
@@ -1588,11 +1601,11 @@
 
 /* Misc globals */
 GLOBAL_EXTERN bool enable_oplocks; /* enable or disable oplocks */
-GLOBAL_EXTERN unsigned int lookupCacheEnabled;
+GLOBAL_EXTERN bool lookupCacheEnabled;
 GLOBAL_EXTERN unsigned int global_secflags;	/* if on, session setup sent
 				with more secure ntlmssp2 challenge/resp */
 GLOBAL_EXTERN unsigned int sign_CIFS_PDUs;  /* enable smb packet signing */
-GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
+GLOBAL_EXTERN bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
 GLOBAL_EXTERN unsigned int CIFSMaxBufSize;  /* max size not including hdr */
 GLOBAL_EXTERN unsigned int cifs_min_rcv;    /* min size of big ntwrk buf pool */
 GLOBAL_EXTERN unsigned int cifs_min_small;  /* min size of small buf pool */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index c63fd1d..54590fd 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -205,6 +205,9 @@
 					 struct tcon_link *tlink,
 					 struct cifs_pending_open *open);
 extern void cifs_del_pending_open(struct cifs_pending_open *open);
+extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
+				 int from_reconnect);
+extern void cifs_put_tcon(struct cifs_tcon *tcon);
 
 #if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
 extern void cifs_dfs_release_automount_timer(void);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 76fcb50..b60150e 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -98,13 +98,13 @@
 	struct list_head *tmp1;
 
 	/* list all files open on tree connection and mark them invalid */
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&tcon->open_file_lock);
 	list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
 		open_file = list_entry(tmp, struct cifsFileInfo, tlist);
 		open_file->invalidHandle = true;
 		open_file->oplock_break_cancelled = true;
 	}
-	spin_unlock(&cifs_file_list_lock);
+	spin_unlock(&tcon->open_file_lock);
 	/*
 	 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
 	 * to this tcon.
@@ -717,6 +717,9 @@
 	if (rc)
 		return rc;
 
+	if (server->capabilities & CAP_UNICODE)
+		smb->hdr.Flags2 |= SMBFLG2_UNICODE;
+
 	/* set up echo request */
 	smb->hdr.Tid = 0xffff;
 	smb->hdr.WordCount = 1;
@@ -1424,6 +1427,8 @@
 
 	length = discard_remaining_data(server);
 	dequeue_mid(mid, rdata->result);
+	mid->resp_buf = server->smallbuf;
+	server->smallbuf = NULL;
 	return length;
 }
 
@@ -1538,6 +1543,8 @@
 		return cifs_readv_discard(server, mid);
 
 	dequeue_mid(mid, false);
+	mid->resp_buf = server->smallbuf;
+	server->smallbuf = NULL;
 	return length;
 }
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 3c194ff..53a827c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -52,6 +52,9 @@
 #include "nterr.h"
 #include "rfc1002pdu.h"
 #include "fscache.h"
+#ifdef CONFIG_CIFS_SMB2
+#include "smb2proto.h"
+#endif
 
 #define CIFS_PORT 445
 #define RFC1001_PORT 139
@@ -409,6 +412,9 @@
 		}
 	} while (server->tcpStatus == CifsNeedReconnect);
 
+	if (server->tcpStatus == CifsNeedNegotiate)
+		mod_delayed_work(cifsiod_wq, &server->echo, 0);
+
 	return rc;
 }
 
@@ -418,16 +424,27 @@
 	int rc;
 	struct TCP_Server_Info *server = container_of(work,
 					struct TCP_Server_Info, echo.work);
+	unsigned long echo_interval;
 
 	/*
-	 * We cannot send an echo if it is disabled or until the
-	 * NEGOTIATE_PROTOCOL request is done, which is indicated by
-	 * server->ops->need_neg() == true. Also, no need to ping if
-	 * we got a response recently.
+	 * If we need to renegotiate, set echo interval to zero to
+	 * immediately call echo service where we can renegotiate.
 	 */
-	if (!server->ops->need_neg || server->ops->need_neg(server) ||
+	if (server->tcpStatus == CifsNeedNegotiate)
+		echo_interval = 0;
+	else
+		echo_interval = SMB_ECHO_INTERVAL;
+
+	/*
+	 * We cannot send an echo if it is disabled.
+	 * Also, no need to ping if we got a response recently.
+	 */
+
+	if (server->tcpStatus == CifsNeedReconnect ||
+	    server->tcpStatus == CifsExiting ||
+	    server->tcpStatus == CifsNew ||
 	    (server->ops->can_echo && !server->ops->can_echo(server)) ||
-	    time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
+	    time_before(jiffies, server->lstrp + echo_interval - HZ))
 		goto requeue_echo;
 
 	rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
@@ -919,10 +936,19 @@
 
 		server->lstrp = jiffies;
 		if (mid_entry != NULL) {
+			if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
+			     mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
+					server->ops->handle_cancelled_mid)
+				server->ops->handle_cancelled_mid(
+							mid_entry->resp_buf,
+							server);
+
 			if (!mid_entry->multiRsp || mid_entry->multiEnd)
 				mid_entry->callback(mid_entry);
-		} else if (!server->ops->is_oplock_break ||
-			   !server->ops->is_oplock_break(buf, server)) {
+		} else if (server->ops->is_oplock_break &&
+			   server->ops->is_oplock_break(buf, server)) {
+			cifs_dbg(FYI, "Received oplock break\n");
+		} else {
 			cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
 				 atomic_read(&midCount));
 			cifs_dump_mem("Received Data is: ", buf,
@@ -2111,8 +2137,8 @@
 	return NULL;
 }
 
-static void
-cifs_put_tcp_session(struct TCP_Server_Info *server)
+void
+cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
 {
 	struct task_struct *task;
 
@@ -2129,6 +2155,19 @@
 
 	cancel_delayed_work_sync(&server->echo);
 
+#ifdef CONFIG_CIFS_SMB2
+	if (from_reconnect)
+		/*
+		 * Avoid deadlock here: reconnect work calls
+		 * cifs_put_tcp_session() at its end. Need to be sure
+		 * that reconnect work does nothing with server pointer after
+		 * that step.
+		 */
+		cancel_delayed_work(&server->reconnect);
+	else
+		cancel_delayed_work_sync(&server->reconnect);
+#endif
+
 	spin_lock(&GlobalMid_Lock);
 	server->tcpStatus = CifsExiting;
 	spin_unlock(&GlobalMid_Lock);
@@ -2193,12 +2232,16 @@
 	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
 	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
 	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
+#ifdef CONFIG_CIFS_SMB2
+	INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
+	mutex_init(&tcp_ses->reconnect_mutex);
+#endif
 	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
 	       sizeof(tcp_ses->srcaddr));
 	memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
 		sizeof(tcp_ses->dstaddr));
 #ifdef CONFIG_CIFS_SMB2
-	get_random_bytes(tcp_ses->client_guid, SMB2_CLIENT_GUID_SIZE);
+	generate_random_uuid(tcp_ses->client_guid);
 #endif
 	/*
 	 * at this point we are the only ones with the pointer
@@ -2345,7 +2388,7 @@
 	spin_unlock(&cifs_tcp_ses_lock);
 
 	sesInfoFree(ses);
-	cifs_put_tcp_session(server);
+	cifs_put_tcp_session(server, 0);
 }
 
 #ifdef CONFIG_KEYS
@@ -2519,7 +2562,7 @@
 		mutex_unlock(&ses->session_mutex);
 
 		/* existing SMB ses has a server reference already */
-		cifs_put_tcp_session(server);
+		cifs_put_tcp_session(server, 0);
 		free_xid(xid);
 		return ses;
 	}
@@ -2609,7 +2652,7 @@
 	return NULL;
 }
 
-static void
+void
 cifs_put_tcon(struct cifs_tcon *tcon)
 {
 	unsigned int xid;
@@ -3515,6 +3558,44 @@
 	return volume_info;
 }
 
+static int
+cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
+					unsigned int xid,
+					struct cifs_tcon *tcon,
+					struct cifs_sb_info *cifs_sb,
+					char *full_path)
+{
+	int rc;
+	char *s;
+	char sep, tmp;
+
+	sep = CIFS_DIR_SEP(cifs_sb);
+	s = full_path;
+
+	rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
+	while (rc == 0) {
+		/* skip separators */
+		while (*s == sep)
+			s++;
+		if (!*s)
+			break;
+		/* next separator */
+		while (*s && *s != sep)
+			s++;
+
+		/*
+		 * temporarily null-terminate the path at the end of
+		 * the current component
+		 */
+		tmp = *s;
+		*s = 0;
+		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
+						     full_path);
+		*s = tmp;
+	}
+	return rc;
+}
+
 int
 cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
 {
@@ -3652,6 +3733,18 @@
 			kfree(full_path);
 			goto mount_fail_check;
 		}
+
+		if (rc != -EREMOTE) {
+			rc = cifs_are_all_path_components_accessible(server,
+							     xid, tcon, cifs_sb,
+							     full_path);
+			if (rc != 0) {
+				cifs_dbg(VFS, "cannot query dirs between root and final path, "
+					 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
+				cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
+				rc = 0;
+			}
+		}
 		kfree(full_path);
 	}
 
@@ -3715,7 +3808,7 @@
 		else if (ses)
 			cifs_put_smb_ses(ses);
 		else
-			cifs_put_tcp_session(server);
+			cifs_put_tcp_session(server, 0);
 		bdi_destroy(&cifs_sb->bdi);
 	}
 
@@ -3921,6 +4014,7 @@
 
 	bdi_destroy(&cifs_sb->bdi);
 	kfree(cifs_sb->mountdata);
+	kfree(cifs_sb->prepath);
 	call_rcu(&cifs_sb->rcu, delayed_free);
 }
 
@@ -4025,7 +4119,7 @@
 	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
 	if (IS_ERR(ses)) {
 		tcon = (struct cifs_tcon *)ses;
-		cifs_put_tcp_session(master_tcon->ses->server);
+		cifs_put_tcp_session(master_tcon->ses->server, 0);
 		goto out;
 	}
 
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index c3eb998..26a3b38 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -84,6 +84,7 @@
 	struct dentry *temp;
 	int namelen;
 	int dfsplen;
+	int pplen = 0;
 	char *full_path;
 	char dirsep;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
@@ -95,8 +96,12 @@
 		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
 	else
 		dfsplen = 0;
+
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
+		pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
+
 cifs_bp_rename_retry:
-	namelen = dfsplen;
+	namelen = dfsplen + pplen;
 	seq = read_seqbegin(&rename_lock);
 	rcu_read_lock();
 	for (temp = direntry; !IS_ROOT(temp);) {
@@ -137,7 +142,7 @@
 		}
 	}
 	rcu_read_unlock();
-	if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
+	if (namelen != dfsplen + pplen || read_seqretry(&rename_lock, seq)) {
 		cifs_dbg(FYI, "did not end path lookup where expected. namelen=%ddfsplen=%d\n",
 			 namelen, dfsplen);
 		/* presumably this is only possible if racing with a rename
@@ -153,6 +158,17 @@
 	   those safely to '/' if any are found in the middle of the prepath */
 	/* BB test paths to Windows with '/' in the midst of prepath */
 
+	if (pplen) {
+		int i;
+
+		cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath);
+		memcpy(full_path+dfsplen+1, cifs_sb->prepath, pplen-1);
+		full_path[dfsplen] = '\\';
+		for (i = 0; i < pplen-1; i++)
+			if (full_path[dfsplen+1+i] == '/')
+				full_path[dfsplen+1+i] = CIFS_DIR_SEP(cifs_sb);
+	}
+
 	if (dfsplen) {
 		strncpy(full_path, tcon->treeName, dfsplen);
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
@@ -229,6 +245,13 @@
 				goto cifs_create_get_file_info;
 			}
 
+			if (S_ISDIR(newinode->i_mode)) {
+				CIFSSMBClose(xid, tcon, fid->netfid);
+				iput(newinode);
+				rc = -EISDIR;
+				goto out;
+			}
+
 			if (!S_ISREG(newinode->i_mode)) {
 				/*
 				 * The server may allow us to open things like
@@ -399,10 +422,14 @@
 	if (rc != 0) {
 		cifs_dbg(FYI, "Create worked, get_inode_info failed rc = %d\n",
 			 rc);
-		if (server->ops->close)
-			server->ops->close(xid, tcon, fid);
-		goto out;
+		goto out_err;
 	}
+
+	if (S_ISDIR(newinode->i_mode)) {
+		rc = -EISDIR;
+		goto out_err;
+	}
+
 	d_drop(direntry);
 	d_add(direntry, newinode);
 
@@ -410,6 +437,13 @@
 	kfree(buf);
 	kfree(full_path);
 	return rc;
+
+out_err:
+	if (server->ops->close)
+		server->ops->close(xid, tcon, fid);
+	if (newinode)
+		iput(newinode);
+	goto out;
 }
 
 int
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 0068e82..a0c0a49 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -305,6 +305,7 @@
 	cfile->tlink = cifs_get_tlink(tlink);
 	INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
 	mutex_init(&cfile->fh_mutex);
+	spin_lock_init(&cfile->file_info_lock);
 
 	cifs_sb_active(inode->i_sb);
 
@@ -317,7 +318,7 @@
 		oplock = 0;
 	}
 
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&tcon->open_file_lock);
 	if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock)
 		oplock = fid->pending_open->oplock;
 	list_del(&fid->pending_open->olist);
@@ -326,12 +327,13 @@
 	server->ops->set_fid(cfile, fid, oplock);
 
 	list_add(&cfile->tlist, &tcon->openFileList);
+
 	/* if readable file instance put first in list*/
 	if (file->f_mode & FMODE_READ)
 		list_add(&cfile->flist, &cinode->openFileList);
 	else
 		list_add_tail(&cfile->flist, &cinode->openFileList);
-	spin_unlock(&cifs_file_list_lock);
+	spin_unlock(&tcon->open_file_lock);
 
 	if (fid->purge_cache)
 		cifs_zap_mapping(inode);
@@ -343,16 +345,16 @@
 struct cifsFileInfo *
 cifsFileInfo_get(struct cifsFileInfo *cifs_file)
 {
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&cifs_file->file_info_lock);
 	cifsFileInfo_get_locked(cifs_file);
-	spin_unlock(&cifs_file_list_lock);
+	spin_unlock(&cifs_file->file_info_lock);
 	return cifs_file;
 }
 
 /*
  * Release a reference on the file private data. This may involve closing
  * the filehandle out on the server. Must be called without holding
- * cifs_file_list_lock.
+ * tcon->open_file_lock and cifs_file->file_info_lock.
  */
 void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
 {
@@ -367,11 +369,15 @@
 	struct cifs_pending_open open;
 	bool oplock_break_cancelled;
 
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&tcon->open_file_lock);
+
+	spin_lock(&cifs_file->file_info_lock);
 	if (--cifs_file->count > 0) {
-		spin_unlock(&cifs_file_list_lock);
+		spin_unlock(&cifs_file->file_info_lock);
+		spin_unlock(&tcon->open_file_lock);
 		return;
 	}
+	spin_unlock(&cifs_file->file_info_lock);
 
 	if (server->ops->get_lease_key)
 		server->ops->get_lease_key(inode, &fid);
@@ -395,7 +401,8 @@
 			set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags);
 		cifs_set_oplock_level(cifsi, 0);
 	}
-	spin_unlock(&cifs_file_list_lock);
+
+	spin_unlock(&tcon->open_file_lock);
 
 	oplock_break_cancelled = cancel_work_sync(&cifs_file->oplock_break);
 
@@ -772,10 +779,10 @@
 	server = tcon->ses->server;
 
 	cifs_dbg(FYI, "Freeing private data in close dir\n");
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&cfile->file_info_lock);
 	if (server->ops->dir_needs_close(cfile)) {
 		cfile->invalidHandle = true;
-		spin_unlock(&cifs_file_list_lock);
+		spin_unlock(&cfile->file_info_lock);
 		if (server->ops->close_dir)
 			rc = server->ops->close_dir(xid, tcon, &cfile->fid);
 		else
@@ -784,7 +791,7 @@
 		/* not much we can do if it fails anyway, ignore rc */
 		rc = 0;
 	} else
-		spin_unlock(&cifs_file_list_lock);
+		spin_unlock(&cfile->file_info_lock);
 
 	buf = cfile->srch_inf.ntwrk_buf_start;
 	if (buf) {
@@ -1720,12 +1727,13 @@
 {
 	struct cifsFileInfo *open_file = NULL;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
+	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
 
 	/* only filter by fsuid on multiuser mounts */
 	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
 		fsuid_only = false;
 
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&tcon->open_file_lock);
 	/* we could simply get the first_list_entry since write-only entries
 	   are always at the end of the list but since the first entry might
 	   have a close pending, we go through the whole list */
@@ -1736,8 +1744,8 @@
 			if (!open_file->invalidHandle) {
 				/* found a good file */
 				/* lock it so it will not be closed on us */
-				cifsFileInfo_get_locked(open_file);
-				spin_unlock(&cifs_file_list_lock);
+				cifsFileInfo_get(open_file);
+				spin_unlock(&tcon->open_file_lock);
 				return open_file;
 			} /* else might as well continue, and look for
 			     another, or simply have the caller reopen it
@@ -1745,7 +1753,7 @@
 		} else /* write only file */
 			break; /* write only files are last so must be done */
 	}
-	spin_unlock(&cifs_file_list_lock);
+	spin_unlock(&tcon->open_file_lock);
 	return NULL;
 }
 
@@ -1754,6 +1762,7 @@
 {
 	struct cifsFileInfo *open_file, *inv_file = NULL;
 	struct cifs_sb_info *cifs_sb;
+	struct cifs_tcon *tcon;
 	bool any_available = false;
 	int rc;
 	unsigned int refind = 0;
@@ -1769,15 +1778,16 @@
 	}
 
 	cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
+	tcon = cifs_sb_master_tcon(cifs_sb);
 
 	/* only filter by fsuid on multiuser mounts */
 	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
 		fsuid_only = false;
 
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&tcon->open_file_lock);
 refind_writable:
 	if (refind > MAX_REOPEN_ATT) {
-		spin_unlock(&cifs_file_list_lock);
+		spin_unlock(&tcon->open_file_lock);
 		return NULL;
 	}
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
@@ -1788,8 +1798,8 @@
 		if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
 			if (!open_file->invalidHandle) {
 				/* found a good writable file */
-				cifsFileInfo_get_locked(open_file);
-				spin_unlock(&cifs_file_list_lock);
+				cifsFileInfo_get(open_file);
+				spin_unlock(&tcon->open_file_lock);
 				return open_file;
 			} else {
 				if (!inv_file)
@@ -1805,24 +1815,24 @@
 
 	if (inv_file) {
 		any_available = false;
-		cifsFileInfo_get_locked(inv_file);
+		cifsFileInfo_get(inv_file);
 	}
 
-	spin_unlock(&cifs_file_list_lock);
+	spin_unlock(&tcon->open_file_lock);
 
 	if (inv_file) {
 		rc = cifs_reopen_file(inv_file, false);
 		if (!rc)
 			return inv_file;
 		else {
-			spin_lock(&cifs_file_list_lock);
+			spin_lock(&tcon->open_file_lock);
 			list_move_tail(&inv_file->flist,
 					&cifs_inode->openFileList);
-			spin_unlock(&cifs_file_list_lock);
+			spin_unlock(&tcon->open_file_lock);
 			cifsFileInfo_put(inv_file);
-			spin_lock(&cifs_file_list_lock);
 			++refind;
 			inv_file = NULL;
+			spin_lock(&tcon->open_file_lock);
 			goto refind_writable;
 		}
 	}
@@ -2535,7 +2545,7 @@
 		wdata->credits = credits;
 
 		if (!wdata->cfile->invalidHandle ||
-		    !cifs_reopen_file(wdata->cfile, false))
+		    !(rc = cifs_reopen_file(wdata->cfile, false)))
 			rc = server->ops->async_writev(wdata,
 					cifs_uncached_writedata_release);
 		if (rc) {
@@ -2948,7 +2958,7 @@
 		rdata->credits = credits;
 
 		if (!rdata->cfile->invalidHandle ||
-		    !cifs_reopen_file(rdata->cfile, true))
+		    !(rc = cifs_reopen_file(rdata->cfile, true)))
 			rc = server->ops->async_readv(rdata);
 error:
 		if (rc) {
@@ -3534,7 +3544,7 @@
 		}
 
 		if (!rdata->cfile->invalidHandle ||
-		    !cifs_reopen_file(rdata->cfile, true))
+		    !(rc = cifs_reopen_file(rdata->cfile, true)))
 			rc = server->ops->async_readv(rdata);
 		if (rc) {
 			add_credits_and_wake_if(server, rdata->credits, 0);
@@ -3632,15 +3642,17 @@
 static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
 {
 	struct cifsFileInfo *open_file;
+	struct cifs_tcon *tcon =
+		cifs_sb_master_tcon(CIFS_SB(cifs_inode->vfs_inode.i_sb));
 
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&tcon->open_file_lock);
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
 		if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
-			spin_unlock(&cifs_file_list_lock);
+			spin_unlock(&tcon->open_file_lock);
 			return 1;
 		}
 	}
-	spin_unlock(&cifs_file_list_lock);
+	spin_unlock(&tcon->open_file_lock);
 	return 0;
 }
 
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a329f5b..9cdeb02 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -982,10 +982,26 @@
 	struct inode *inode = NULL;
 	long rc;
 	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+	char *path = NULL;
+	int len;
+
+	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
+	    && cifs_sb->prepath) {
+		len = strlen(cifs_sb->prepath);
+		path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
+		if (path == NULL)
+			return ERR_PTR(-ENOMEM);
+		path[0] = '/';
+		memcpy(path+1, cifs_sb->prepath, len);
+	} else {
+		path = kstrdup("", GFP_KERNEL);
+		if (path == NULL)
+			return ERR_PTR(-ENOMEM);
+	}
 
 	xid = get_xid();
 	if (tcon->unix_ext) {
-		rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
+		rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
 		/* some servers mistakenly claim POSIX support */
 		if (rc != -EOPNOTSUPP)
 			goto iget_no_retry;
@@ -993,7 +1009,8 @@
 		tcon->unix_ext = false;
 	}
 
-	rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
+	convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
+	rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
 
 iget_no_retry:
 	if (!inode) {
@@ -1022,6 +1039,7 @@
 	}
 
 out:
+	kfree(path);
 	/* can not call macro free_xid here since in a void func
 	 * TODO: This is no longer true
 	 */
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 35cf990..a8f5b31 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -272,6 +272,8 @@
 				rc = -EOPNOTSUPP;
 			break;
 		case CIFS_IOC_GET_MNT_INFO:
+			if (pSMBFile == NULL)
+				break;
 			tcon = tlink_tcon(pSMBFile->tlink);
 			rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
 			break;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 8442b8b..2396ab0 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -120,6 +120,7 @@
 		++ret_buf->tc_count;
 		INIT_LIST_HEAD(&ret_buf->openFileList);
 		INIT_LIST_HEAD(&ret_buf->tcon_list);
+		spin_lock_init(&ret_buf->open_file_lock);
 #ifdef CONFIG_CIFS_STATS
 		spin_lock_init(&ret_buf->stat_lock);
 #endif
@@ -465,7 +466,7 @@
 				continue;
 
 			cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
-			spin_lock(&cifs_file_list_lock);
+			spin_lock(&tcon->open_file_lock);
 			list_for_each(tmp2, &tcon->openFileList) {
 				netfile = list_entry(tmp2, struct cifsFileInfo,
 						     tlist);
@@ -495,11 +496,11 @@
 					   &netfile->oplock_break);
 				netfile->oplock_break_cancelled = false;
 
-				spin_unlock(&cifs_file_list_lock);
+				spin_unlock(&tcon->open_file_lock);
 				spin_unlock(&cifs_tcp_ses_lock);
 				return true;
 			}
-			spin_unlock(&cifs_file_list_lock);
+			spin_unlock(&tcon->open_file_lock);
 			spin_unlock(&cifs_tcp_ses_lock);
 			cifs_dbg(FYI, "No matching file for oplock break\n");
 			return true;
@@ -613,9 +614,9 @@
 void
 cifs_del_pending_open(struct cifs_pending_open *open)
 {
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&tlink_tcon(open->tlink)->open_file_lock);
 	list_del(&open->olist);
-	spin_unlock(&cifs_file_list_lock);
+	spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
 }
 
 void
@@ -635,7 +636,7 @@
 cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
 		      struct cifs_pending_open *open)
 {
-	spin_lock(&cifs_file_list_lock);
+	spin_lock(&tlink_tcon(tlink)->open_file_lock);
 	cifs_add_pending_open_locked(fid, tlink, open);
-	spin_unlock(&cifs_file_list_lock);
+	spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
 }
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 848249f..3079b38 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -133,6 +133,6 @@
 
 int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses);
 void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses);
-int build_ntlmssp_auth_blob(unsigned char *pbuffer, u16 *buflen,
+int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
 			struct cifs_ses *ses,
 			const struct nls_table *nls_cp);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b30a4a6..97d1a15 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -282,6 +282,7 @@
 			rc = -ENOMEM;
 			goto error_exit;
 		}
+		spin_lock_init(&cifsFile->file_info_lock);
 		file->private_data = cifsFile;
 		cifsFile->tlink = cifs_get_tlink(tlink);
 		tcon = tlink_tcon(tlink);
@@ -594,14 +595,14 @@
 	     is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
 		/* close and restart search */
 		cifs_dbg(FYI, "search backing up - close and restart search\n");
-		spin_lock(&cifs_file_list_lock);
+		spin_lock(&cfile->file_info_lock);
 		if (server->ops->dir_needs_close(cfile)) {
 			cfile->invalidHandle = true;
-			spin_unlock(&cifs_file_list_lock);
+			spin_unlock(&cfile->file_info_lock);
 			if (server->ops->close_dir)
 				server->ops->close_dir(xid, tcon, &cfile->fid);
 		} else
-			spin_unlock(&cifs_file_list_lock);
+			spin_unlock(&cfile->file_info_lock);
 		if (cfile->srch_inf.ntwrk_buf_start) {
 			cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n");
 			if (cfile->srch_inf.smallBuf)
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 59727e3..e88ffe1 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -364,19 +364,43 @@
 	sec_blob->DomainName.MaximumLength = 0;
 }
 
-/* We do not malloc the blob, it is passed in pbuffer, because its
-   maximum possible size is fixed and small, making this approach cleaner.
-   This function returns the length of the data in the blob */
-int build_ntlmssp_auth_blob(unsigned char *pbuffer,
+static int size_of_ntlmssp_blob(struct cifs_ses *ses)
+{
+	int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len
+		- CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
+
+	if (ses->domainName)
+		sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+	else
+		sz += 2;
+
+	if (ses->user_name)
+		sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
+	else
+		sz += 2;
+
+	return sz;
+}
+
+int build_ntlmssp_auth_blob(unsigned char **pbuffer,
 					u16 *buflen,
 				   struct cifs_ses *ses,
 				   const struct nls_table *nls_cp)
 {
 	int rc;
-	AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
+	AUTHENTICATE_MESSAGE *sec_blob;
 	__u32 flags;
 	unsigned char *tmp;
 
+	rc = setup_ntlmv2_rsp(ses, nls_cp);
+	if (rc) {
+		cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
+		*buflen = 0;
+		goto setup_ntlmv2_ret;
+	}
+	*pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL);
+	sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
+
 	memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
 	sec_blob->MessageType = NtLmAuthenticate;
 
@@ -391,7 +415,7 @@
 			flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
 	}
 
-	tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE);
+	tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
 	sec_blob->NegotiateFlags = cpu_to_le32(flags);
 
 	sec_blob->LmChallengeResponse.BufferOffset =
@@ -399,23 +423,27 @@
 	sec_blob->LmChallengeResponse.Length = 0;
 	sec_blob->LmChallengeResponse.MaximumLength = 0;
 
-	sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
-	rc = setup_ntlmv2_rsp(ses, nls_cp);
-	if (rc) {
-		cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
-		goto setup_ntlmv2_ret;
-	}
-	memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
-			ses->auth_key.len - CIFS_SESS_KEY_SIZE);
-	tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
+	sec_blob->NtChallengeResponse.BufferOffset =
+				cpu_to_le32(tmp - *pbuffer);
+	if (ses->user_name != NULL) {
+		memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+				ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+		tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
 
-	sec_blob->NtChallengeResponse.Length =
-			cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
-	sec_blob->NtChallengeResponse.MaximumLength =
-			cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+		sec_blob->NtChallengeResponse.Length =
+				cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+		sec_blob->NtChallengeResponse.MaximumLength =
+				cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+	} else {
+		/*
+		 * don't send an NT Response for anonymous access
+		 */
+		sec_blob->NtChallengeResponse.Length = 0;
+		sec_blob->NtChallengeResponse.MaximumLength = 0;
+	}
 
 	if (ses->domainName == NULL) {
-		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 		sec_blob->DomainName.Length = 0;
 		sec_blob->DomainName.MaximumLength = 0;
 		tmp += 2;
@@ -424,14 +452,14 @@
 		len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
 				      CIFS_MAX_USERNAME_LEN, nls_cp);
 		len *= 2; /* unicode is 2 bytes each */
-		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 		sec_blob->DomainName.Length = cpu_to_le16(len);
 		sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
 		tmp += len;
 	}
 
 	if (ses->user_name == NULL) {
-		sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+		sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 		sec_blob->UserName.Length = 0;
 		sec_blob->UserName.MaximumLength = 0;
 		tmp += 2;
@@ -440,13 +468,13 @@
 		len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
 				      CIFS_MAX_USERNAME_LEN, nls_cp);
 		len *= 2; /* unicode is 2 bytes each */
-		sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+		sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 		sec_blob->UserName.Length = cpu_to_le16(len);
 		sec_blob->UserName.MaximumLength = cpu_to_le16(len);
 		tmp += len;
 	}
 
-	sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+	sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 	sec_blob->WorkstationName.Length = 0;
 	sec_blob->WorkstationName.MaximumLength = 0;
 	tmp += 2;
@@ -455,19 +483,19 @@
 		(ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
 			&& !calc_seckey(ses)) {
 		memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
-		sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
+		sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 		sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
 		sec_blob->SessionKey.MaximumLength =
 				cpu_to_le16(CIFS_CPHTXT_SIZE);
 		tmp += CIFS_CPHTXT_SIZE;
 	} else {
-		sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
+		sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 		sec_blob->SessionKey.Length = 0;
 		sec_blob->SessionKey.MaximumLength = 0;
 	}
 
+	*buflen = tmp - *pbuffer;
 setup_ntlmv2_ret:
-	*buflen = tmp - pbuffer;
 	return rc;
 }
 
@@ -670,20 +698,24 @@
 
 	pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
 
-	/* no capabilities flags in old lanman negotiation */
-	pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
+	if (ses->user_name != NULL) {
+		/* no capabilities flags in old lanman negotiation */
+		pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
 
-	/* Calculate hash with password and copy into bcc_ptr.
-	 * Encryption Key (stored as in cryptkey) gets used if the
-	 * security mode bit in Negottiate Protocol response states
-	 * to use challenge/response method (i.e. Password bit is 1).
-	 */
-	rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
-			      ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
-			      true : false, lnm_session_key);
+		/* Calculate hash with password and copy into bcc_ptr.
+		 * Encryption Key (stored as in cryptkey) gets used if the
+		 * security mode bit in Negottiate Protocol response states
+		 * to use challenge/response method (i.e. Password bit is 1).
+		 */
+		rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
+				      ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
+				      true : false, lnm_session_key);
 
-	memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
-	bcc_ptr += CIFS_AUTH_RESP_SIZE;
+		memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
+		bcc_ptr += CIFS_AUTH_RESP_SIZE;
+	} else {
+		pSMB->old_req.PasswordLength = 0;
+	}
 
 	/*
 	 * can not sign if LANMAN negotiated so no need
@@ -769,27 +801,32 @@
 	capabilities = cifs_ssetup_hdr(ses, pSMB);
 
 	pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
-	pSMB->req_no_secext.CaseInsensitivePasswordLength =
-			cpu_to_le16(CIFS_AUTH_RESP_SIZE);
-	pSMB->req_no_secext.CaseSensitivePasswordLength =
-			cpu_to_le16(CIFS_AUTH_RESP_SIZE);
+	if (ses->user_name != NULL) {
+		pSMB->req_no_secext.CaseInsensitivePasswordLength =
+				cpu_to_le16(CIFS_AUTH_RESP_SIZE);
+		pSMB->req_no_secext.CaseSensitivePasswordLength =
+				cpu_to_le16(CIFS_AUTH_RESP_SIZE);
 
-	/* calculate ntlm response and session key */
-	rc = setup_ntlm_response(ses, sess_data->nls_cp);
-	if (rc) {
-		cifs_dbg(VFS, "Error %d during NTLM authentication\n",
-				 rc);
-		goto out;
+		/* calculate ntlm response and session key */
+		rc = setup_ntlm_response(ses, sess_data->nls_cp);
+		if (rc) {
+			cifs_dbg(VFS, "Error %d during NTLM authentication\n",
+					 rc);
+			goto out;
+		}
+
+		/* copy ntlm response */
+		memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+				CIFS_AUTH_RESP_SIZE);
+		bcc_ptr += CIFS_AUTH_RESP_SIZE;
+		memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+				CIFS_AUTH_RESP_SIZE);
+		bcc_ptr += CIFS_AUTH_RESP_SIZE;
+	} else {
+		pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
+		pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
 	}
 
-	/* copy ntlm response */
-	memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
-			CIFS_AUTH_RESP_SIZE);
-	bcc_ptr += CIFS_AUTH_RESP_SIZE;
-	memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
-			CIFS_AUTH_RESP_SIZE);
-	bcc_ptr += CIFS_AUTH_RESP_SIZE;
-
 	if (ses->capabilities & CAP_UNICODE) {
 		/* unicode strings must be word aligned */
 		if (sess_data->iov[0].iov_len % 2) {
@@ -878,23 +915,27 @@
 	/* LM2 password would be here if we supported it */
 	pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
 
-	/* calculate nlmv2 response and session key */
-	rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
-	if (rc) {
-		cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
-		goto out;
+	if (ses->user_name != NULL) {
+		/* calculate nlmv2 response and session key */
+		rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
+		if (rc) {
+			cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
+			goto out;
+		}
+
+		memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+				ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+		bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
+
+		/* set case sensitive password length after tilen may get
+		 * assigned, tilen is 0 otherwise.
+		 */
+		pSMB->req_no_secext.CaseSensitivePasswordLength =
+			cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+	} else {
+		pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
 	}
 
-	memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
-			ses->auth_key.len - CIFS_SESS_KEY_SIZE);
-	bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
-
-	/* set case sensitive password length after tilen may get
-	 * assigned, tilen is 0 otherwise.
-	 */
-	pSMB->req_no_secext.CaseSensitivePasswordLength =
-		cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
-
 	if (ses->capabilities & CAP_UNICODE) {
 		if (sess_data->iov[0].iov_len % 2) {
 			*bcc_ptr = 0;
@@ -1245,7 +1286,7 @@
 	struct cifs_ses *ses = sess_data->ses;
 	__u16 bytes_remaining;
 	char *bcc_ptr;
-	char *ntlmsspblob = NULL;
+	unsigned char *ntlmsspblob = NULL;
 	u16 blob_len;
 
 	cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
@@ -1258,19 +1299,7 @@
 	/* Build security blob before we assemble the request */
 	pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
 	smb_buf = (struct smb_hdr *)pSMB;
-	/*
-	 * 5 is an empirical value, large enough to hold
-	 * authenticate message plus max 10 of av paris,
-	 * domain, user, workstation names, flags, etc.
-	 */
-	ntlmsspblob = kzalloc(5*sizeof(struct _AUTHENTICATE_MESSAGE),
-				GFP_KERNEL);
-	if (!ntlmsspblob) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
-	rc = build_ntlmssp_auth_blob(ntlmsspblob,
+	rc = build_ntlmssp_auth_blob(&ntlmsspblob,
 					&blob_len, ses, sess_data->nls_cp);
 	if (rc)
 		goto out_free_ntlmsspblob;
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index fc537c2..efd72e1 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -849,8 +849,13 @@
 		     struct cifs_fid *fid, __u16 search_flags,
 		     struct cifs_search_info *srch_inf)
 {
-	return CIFSFindFirst(xid, tcon, path, cifs_sb,
-			     &fid->netfid, search_flags, srch_inf, true);
+	int rc;
+
+	rc = CIFSFindFirst(xid, tcon, path, cifs_sb,
+			   &fid->netfid, search_flags, srch_inf, true);
+	if (rc)
+		cifs_dbg(FYI, "find first failed=%d\n", rc);
+	return rc;
 }
 
 static int
@@ -1015,6 +1020,15 @@
 	return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
 }
 
+static bool
+cifs_can_echo(struct TCP_Server_Info *server)
+{
+	if (server->tcpStatus == CifsGood)
+		return true;
+
+	return false;
+}
+
 struct smb_version_operations smb1_operations = {
 	.send_cancel = send_nt_cancel,
 	.compare_fids = cifs_compare_fids,
@@ -1049,6 +1063,7 @@
 	.get_dfs_refer = CIFSGetDFSRefer,
 	.qfs_tcon = cifs_qfs_tcon,
 	.is_path_accessible = cifs_is_path_accessible,
+	.can_echo = cifs_can_echo,
 	.query_path_info = cifs_query_path_info,
 	.query_file_info = cifs_query_file_info,
 	.get_srv_inum = cifs_get_srv_inum,
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index f9e766f..b2aff0c 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -260,7 +260,7 @@
 	 * and check it for zero before using.
 	 */
 	max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf;
-	if (!max_buf) {
+	if (max_buf < sizeof(struct smb2_lock_element)) {
 		free_xid(xid);
 		return -EINVAL;
 	}
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
index bc0bb9c..238759c 100644
--- a/fs/cifs/smb2glob.h
+++ b/fs/cifs/smb2glob.h
@@ -44,6 +44,7 @@
 #define SMB2_OP_DELETE 7
 #define SMB2_OP_HARDLINK 8
 #define SMB2_OP_SET_EOF 9
+#define SMB2_OP_RMDIR 10
 
 /* Used when constructing chained read requests. */
 #define CHAINED_REQUEST 1
@@ -60,4 +61,14 @@
 /* Maximum buffer size value we can send with 1 credit */
 #define SMB2_MAX_BUFFER_SIZE 65536
 
+/*
+ * Maximum number of credits to keep available.
+ * This value is chosen somewhat arbitrarily. The Windows client
+ * defaults to 128 credits, the Windows server allows clients up to
+ * 512 credits, and the NetApp server does not limit clients at all.
+ * Choose a high enough value such that the client shouldn't limit
+ * performance.
+ */
+#define SMB2_MAX_CREDITS_AVAILABLE 32000
+
 #endif	/* _SMB2_GLOB_H */
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 899bbc8..1238cd3 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -80,6 +80,10 @@
 		 * SMB2_open() call.
 		 */
 		break;
+	case SMB2_OP_RMDIR:
+		tmprc = SMB2_rmdir(xid, tcon, fid.persistent_fid,
+				   fid.volatile_fid);
+		break;
 	case SMB2_OP_RENAME:
 		tmprc = SMB2_rename(xid, tcon, fid.persistent_fid,
 				    fid.volatile_fid, (__le16 *)data);
@@ -191,8 +195,8 @@
 	   struct cifs_sb_info *cifs_sb)
 {
 	return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
-				  CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE,
-				  NULL, SMB2_OP_DELETE);
+				  CREATE_NOT_FILE,
+				  NULL, SMB2_OP_RMDIR);
 }
 
 int
@@ -262,9 +266,15 @@
 	struct tcon_link *tlink;
 	int rc;
 
+	if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
+	    (buf->LastWriteTime == 0) && (buf->ChangeTime) &&
+	    (buf->Attributes == 0))
+		return 0; /* would be a no op, no sense sending this */
+
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
 		return PTR_ERR(tlink);
+
 	rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path,
 				FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf,
 				SMB2_OP_SET_INFO);
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 1c59070..76ccf20 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -525,19 +525,19 @@
 		list_for_each(tmp1, &server->smb_ses_list) {
 			ses = list_entry(tmp1, struct cifs_ses, smb_ses_list);
 
-			spin_lock(&cifs_file_list_lock);
 			list_for_each(tmp2, &ses->tcon_list) {
 				tcon = list_entry(tmp2, struct cifs_tcon,
 						  tcon_list);
+				spin_lock(&tcon->open_file_lock);
 				cifs_stats_inc(
 				    &tcon->stats.cifs_stats.num_oplock_brks);
 				if (smb2_tcon_has_lease(tcon, rsp, lw)) {
-					spin_unlock(&cifs_file_list_lock);
+					spin_unlock(&tcon->open_file_lock);
 					spin_unlock(&cifs_tcp_ses_lock);
 					return true;
 				}
+				spin_unlock(&tcon->open_file_lock);
 			}
-			spin_unlock(&cifs_file_list_lock);
 		}
 	}
 	spin_unlock(&cifs_tcp_ses_lock);
@@ -579,7 +579,7 @@
 			tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
 
 			cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
-			spin_lock(&cifs_file_list_lock);
+			spin_lock(&tcon->open_file_lock);
 			list_for_each(tmp2, &tcon->openFileList) {
 				cfile = list_entry(tmp2, struct cifsFileInfo,
 						     tlist);
@@ -591,7 +591,7 @@
 
 				cifs_dbg(FYI, "file id match, oplock break\n");
 				cinode = CIFS_I(d_inode(cfile->dentry));
-
+				spin_lock(&cfile->file_info_lock);
 				if (!CIFS_CACHE_WRITE(cinode) &&
 				    rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE)
 					cfile->oplock_break_cancelled = true;
@@ -613,14 +613,14 @@
 					clear_bit(
 					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
 					   &cinode->flags);
-
+				spin_unlock(&cfile->file_info_lock);
 				queue_work(cifsiod_wq, &cfile->oplock_break);
 
-				spin_unlock(&cifs_file_list_lock);
+				spin_unlock(&tcon->open_file_lock);
 				spin_unlock(&cifs_tcp_ses_lock);
 				return true;
 			}
-			spin_unlock(&cifs_file_list_lock);
+			spin_unlock(&tcon->open_file_lock);
 			spin_unlock(&cifs_tcp_ses_lock);
 			cifs_dbg(FYI, "No matching file for oplock break\n");
 			return true;
@@ -630,3 +630,47 @@
 	cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
 	return false;
 }
+
+void
+smb2_cancelled_close_fid(struct work_struct *work)
+{
+	struct close_cancelled_open *cancelled = container_of(work,
+					struct close_cancelled_open, work);
+
+	cifs_dbg(VFS, "Close unmatched open\n");
+
+	SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid,
+		   cancelled->fid.volatile_fid);
+	cifs_put_tcon(cancelled->tcon);
+	kfree(cancelled);
+}
+
+int
+smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
+{
+	struct smb2_hdr *hdr = (struct smb2_hdr *)buffer;
+	struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
+	struct cifs_tcon *tcon;
+	struct close_cancelled_open *cancelled;
+
+	if (hdr->Command != SMB2_CREATE || hdr->Status != STATUS_SUCCESS)
+		return 0;
+
+	cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
+	if (!cancelled)
+		return -ENOMEM;
+
+	tcon = smb2_find_smb_tcon(server, hdr->SessionId, hdr->TreeId);
+	if (!tcon) {
+		kfree(cancelled);
+		return -ENOENT;
+	}
+
+	cancelled->fid.persistent_fid = rsp->PersistentFileId;
+	cancelled->fid.volatile_fid = rsp->VolatileFileId;
+	cancelled->tcon = tcon;
+	INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
+	queue_work(cifsiod_wq, &cancelled->work);
+
+	return 0;
+}
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 53ccdde..1d125d3 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -282,7 +282,7 @@
 		cifs_dbg(FYI, "Link Speed %lld\n",
 			le64_to_cpu(out_buf->LinkSpeed));
 	}
-
+	kfree(out_buf);
 	return rc;
 }
 #endif /* STATS2 */
@@ -536,6 +536,7 @@
 	server->ops->set_oplock_level(cinode, oplock, fid->epoch,
 				      &fid->purge_cache);
 	cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
+	memcpy(cfile->fid.create_guid, fid->create_guid, 16);
 }
 
 static void
@@ -694,6 +695,7 @@
 
 cchunk_out:
 	kfree(pcchunk);
+	kfree(retbuf);
 	return rc;
 }
 
@@ -818,7 +820,6 @@
 {
 	int rc;
 	unsigned int ret_data_len;
-	char *retbuf = NULL;
 	struct duplicate_extents_to_file dup_ext_buf;
 	struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
 
@@ -844,7 +845,7 @@
 			FSCTL_DUPLICATE_EXTENTS_TO_FILE,
 			true /* is_fsctl */, (char *)&dup_ext_buf,
 			sizeof(struct duplicate_extents_to_file),
-			(char **)&retbuf,
+			NULL,
 			&ret_data_len);
 
 	if (ret_data_len > 0)
@@ -867,7 +868,6 @@
 		   struct cifsFileInfo *cfile)
 {
 	struct fsctl_set_integrity_information_req integr_info;
-	char *retbuf = NULL;
 	unsigned int ret_data_len;
 
 	integr_info.ChecksumAlgorithm = cpu_to_le16(CHECKSUM_TYPE_UNCHANGED);
@@ -879,7 +879,7 @@
 			FSCTL_SET_INTEGRITY_INFORMATION,
 			true /* is_fsctl */, (char *)&integr_info,
 			sizeof(struct fsctl_set_integrity_information_req),
-			(char **)&retbuf,
+			NULL,
 			&ret_data_len);
 
 }
@@ -909,7 +909,7 @@
 	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
 	kfree(utf16_path);
 	if (rc) {
-		cifs_dbg(VFS, "open dir failed\n");
+		cifs_dbg(FYI, "open dir failed rc=%d\n", rc);
 		return rc;
 	}
 
@@ -919,7 +919,7 @@
 	rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
 				  fid->volatile_fid, 0, srch_inf);
 	if (rc) {
-		cifs_dbg(VFS, "query directory failed\n");
+		cifs_dbg(FYI, "query directory failed rc=%d\n", rc);
 		SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
 	}
 	return rc;
@@ -1036,9 +1036,12 @@
 static void
 smb2_new_lease_key(struct cifs_fid *fid)
 {
-	get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE);
+	generate_random_uuid(fid->lease_key);
 }
 
+#define SMB2_SYMLINK_STRUCT_SIZE \
+	(sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
+
 static int
 smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 		   const char *full_path, char **target_path,
@@ -1051,7 +1054,10 @@
 	struct cifs_fid fid;
 	struct smb2_err_rsp *err_buf = NULL;
 	struct smb2_symlink_err_rsp *symlink;
-	unsigned int sub_len, sub_offset;
+	unsigned int sub_len;
+	unsigned int sub_offset;
+	unsigned int print_len;
+	unsigned int print_offset;
 
 	cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
 
@@ -1072,11 +1078,33 @@
 		kfree(utf16_path);
 		return -ENOENT;
 	}
+
+	if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
+	    get_rfc1002_length(err_buf) + 4 < SMB2_SYMLINK_STRUCT_SIZE) {
+		kfree(utf16_path);
+		return -ENOENT;
+	}
+
 	/* open must fail on symlink - reset rc */
 	rc = 0;
 	symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData;
 	sub_len = le16_to_cpu(symlink->SubstituteNameLength);
 	sub_offset = le16_to_cpu(symlink->SubstituteNameOffset);
+	print_len = le16_to_cpu(symlink->PrintNameLength);
+	print_offset = le16_to_cpu(symlink->PrintNameOffset);
+
+	if (get_rfc1002_length(err_buf) + 4 <
+			SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
+		kfree(utf16_path);
+		return -ENOENT;
+	}
+
+	if (get_rfc1002_length(err_buf) + 4 <
+			SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
+		kfree(utf16_path);
+		return -ENOENT;
+	}
+
 	*target_path = cifs_strndup_from_utf16(
 				(char *)symlink->PathBuffer + sub_offset,
 				sub_len, true, cifs_sb->local_nls);
@@ -1483,6 +1511,7 @@
 	.clear_stats = smb2_clear_stats,
 	.print_stats = smb2_print_stats,
 	.is_oplock_break = smb2_is_valid_oplock_break,
+	.handle_cancelled_mid = smb2_handle_cancelled_mid,
 	.downgrade_oplock = smb2_downgrade_oplock,
 	.need_neg = smb2_need_neg,
 	.negotiate = smb2_negotiate,
@@ -1561,6 +1590,7 @@
 	.clear_stats = smb2_clear_stats,
 	.print_stats = smb2_print_stats,
 	.is_oplock_break = smb2_is_valid_oplock_break,
+	.handle_cancelled_mid = smb2_handle_cancelled_mid,
 	.downgrade_oplock = smb2_downgrade_oplock,
 	.need_neg = smb2_need_neg,
 	.negotiate = smb2_negotiate,
@@ -1642,6 +1672,7 @@
 	.print_stats = smb2_print_stats,
 	.dump_share_caps = smb2_dump_share_caps,
 	.is_oplock_break = smb2_is_valid_oplock_break,
+	.handle_cancelled_mid = smb2_handle_cancelled_mid,
 	.downgrade_oplock = smb2_downgrade_oplock,
 	.need_neg = smb2_need_neg,
 	.negotiate = smb2_negotiate,
@@ -1729,6 +1760,7 @@
 	.print_stats = smb2_print_stats,
 	.dump_share_caps = smb2_dump_share_caps,
 	.is_oplock_break = smb2_is_valid_oplock_break,
+	.handle_cancelled_mid = smb2_handle_cancelled_mid,
 	.downgrade_oplock = smb2_downgrade_oplock,
 	.need_neg = smb2_need_neg,
 	.negotiate = smb2_negotiate,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 373b5cd..f4afa3b 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -103,7 +103,21 @@
 	hdr->ProtocolId[3] = 'B';
 	hdr->StructureSize = cpu_to_le16(64);
 	hdr->Command = smb2_cmd;
-	hdr->CreditRequest = cpu_to_le16(2); /* BB make this dynamic */
+	if (tcon && tcon->ses && tcon->ses->server) {
+		struct TCP_Server_Info *server = tcon->ses->server;
+
+		spin_lock(&server->req_lock);
+		/* Request up to 2 credits but don't go over the limit. */
+		if (server->credits >= SMB2_MAX_CREDITS_AVAILABLE)
+			hdr->CreditRequest = cpu_to_le16(0);
+		else
+			hdr->CreditRequest = cpu_to_le16(
+				min_t(int, SMB2_MAX_CREDITS_AVAILABLE -
+						server->credits, 2));
+		spin_unlock(&server->req_lock);
+	} else {
+		hdr->CreditRequest = cpu_to_le16(2);
+	}
 	hdr->ProcessId = cpu_to_le32((__u16)current->tgid);
 
 	if (!tcon)
@@ -264,7 +278,7 @@
 	case SMB2_CHANGE_NOTIFY:
 	case SMB2_QUERY_INFO:
 	case SMB2_SET_INFO:
-		return -EAGAIN;
+		rc = -EAGAIN;
 	}
 	unload_nls(nls_codepage);
 	return rc;
@@ -550,8 +564,12 @@
 	}
 
 	if (rsplen != sizeof(struct validate_negotiate_info_rsp)) {
-		cifs_dbg(VFS, "invalid size of protocol negotiate response\n");
-		return -EIO;
+		cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n",
+			 rsplen);
+
+		/* relax check since Mac returns max bufsize allowed on ioctl */
+		if (rsplen > CIFSMaxBufSize)
+			return -EIO;
 	}
 
 	/* check validate negotiate info response matches what we got earlier */
@@ -591,8 +609,9 @@
 	u16 blob_length = 0;
 	struct key *spnego_key = NULL;
 	char *security_blob = NULL;
-	char *ntlmssp_blob = NULL;
+	unsigned char *ntlmssp_blob = NULL;
 	bool use_spnego = false; /* else use raw ntlmssp */
+	u64 previous_session = ses->Suid;
 
 	cifs_dbg(FYI, "Session Setup\n");
 
@@ -630,6 +649,10 @@
 		return rc;
 
 	req->hdr.SessionId = 0; /* First session, not a reauthenticate */
+
+	/* if reconnect, we need to send previous sess id, otherwise it is 0 */
+	req->PreviousSessionId = previous_session;
+
 	req->Flags = 0; /* MBZ */
 	/* to enable echos and oplocks */
 	req->hdr.CreditRequest = cpu_to_le16(3);
@@ -716,13 +739,7 @@
 		iov[1].iov_len = blob_length;
 	} else if (phase == NtLmAuthenticate) {
 		req->hdr.SessionId = ses->Suid;
-		ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500,
-				       GFP_KERNEL);
-		if (ntlmssp_blob == NULL) {
-			rc = -ENOMEM;
-			goto ssetup_exit;
-		}
-		rc = build_ntlmssp_auth_blob(ntlmssp_blob, &blob_length, ses,
+		rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses,
 					     nls_cp);
 		if (rc) {
 			cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n",
@@ -919,9 +936,6 @@
 	else
 		return -EIO;
 
-	if (tcon && tcon->bad_network_name)
-		return -ENOENT;
-
 	if ((tcon && tcon->seal) &&
 	    ((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) {
 		cifs_dbg(VFS, "encryption requested but no server support");
@@ -939,6 +953,10 @@
 		return -EINVAL;
 	}
 
+	/* SMB2 TREE_CONNECT request must be called with TreeId == 0 */
+	if (tcon)
+		tcon->tid = 0;
+
 	rc = small_smb2_init(SMB2_TREE_CONNECT, tcon, (void **) &req);
 	if (rc) {
 		kfree(unc_path);
@@ -1019,8 +1037,6 @@
 tcon_error_exit:
 	if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) {
 		cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
-		if (tcon)
-			tcon->bad_network_name = true;
 	}
 	goto tcon_exit;
 }
@@ -1173,7 +1189,7 @@
 
 	buf->dcontext.Timeout = 0; /* Should this be configurable by workload */
 	buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
-	get_random_bytes(buf->dcontext.CreateGuid, 16);
+	generate_random_uuid(buf->dcontext.CreateGuid);
 	memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
 
 	/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
@@ -1506,8 +1522,12 @@
 	 * than one credit. Windows typically sets this smaller, but for some
 	 * ioctls it may be useful to allow server to send more. No point
 	 * limiting what the server can send as long as fits in one credit
+	 * Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE
+	 * (by default, note that it can be overridden to make max larger)
+	 * in responses (except for read responses which can be bigger.
+	 * We may want to bump this limit up
 	 */
-	req->MaxOutputResponse = cpu_to_le32(0xFF00); /* < 64K uses 1 credit */
+	req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize);
 
 	if (is_fsctl)
 		req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
@@ -1809,6 +1829,54 @@
 	add_credits(server, credits_received, CIFS_ECHO_OP);
 }
 
+void smb2_reconnect_server(struct work_struct *work)
+{
+	struct TCP_Server_Info *server = container_of(work,
+					struct TCP_Server_Info, reconnect.work);
+	struct cifs_ses *ses;
+	struct cifs_tcon *tcon, *tcon2;
+	struct list_head tmp_list;
+	int tcon_exist = false;
+
+	/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
+	mutex_lock(&server->reconnect_mutex);
+
+	INIT_LIST_HEAD(&tmp_list);
+	cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n");
+
+	spin_lock(&cifs_tcp_ses_lock);
+	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+		list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+			if (tcon->need_reconnect) {
+				tcon->tc_count++;
+				list_add_tail(&tcon->rlist, &tmp_list);
+				tcon_exist = true;
+			}
+		}
+	}
+	/*
+	 * Get the reference to server struct to be sure that the last call of
+	 * cifs_put_tcon() in the loop below won't release the server pointer.
+	 */
+	if (tcon_exist)
+		server->srv_count++;
+
+	spin_unlock(&cifs_tcp_ses_lock);
+
+	list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
+		smb2_reconnect(SMB2_ECHO, tcon);
+		list_del_init(&tcon->rlist);
+		cifs_put_tcon(tcon);
+	}
+
+	cifs_dbg(FYI, "Reconnecting tcons finished\n");
+	mutex_unlock(&server->reconnect_mutex);
+
+	/* now we can safely release srv struct */
+	if (tcon_exist)
+		cifs_put_tcp_session(server, 1);
+}
+
 int
 SMB2_echo(struct TCP_Server_Info *server)
 {
@@ -1820,6 +1888,12 @@
 
 	cifs_dbg(FYI, "In echo request\n");
 
+	if (server->tcpStatus == CifsNeedNegotiate) {
+		/* No need to send echo on newly established connections */
+		queue_delayed_work(cifsiod_wq, &server->reconnect, 0);
+		return rc;
+	}
+
 	rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req);
 	if (rc)
 		return rc;
@@ -2038,6 +2112,7 @@
 	if (rdata->credits) {
 		buf->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
 						SMB2_MAX_BUFFER_SIZE));
+		buf->CreditRequest = buf->CreditCharge;
 		spin_lock(&server->req_lock);
 		server->credits += rdata->credits -
 						le16_to_cpu(buf->CreditCharge);
@@ -2224,6 +2299,7 @@
 	if (wdata->credits) {
 		req->hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
 						    SMB2_MAX_BUFFER_SIZE));
+		req->hdr.CreditRequest = req->hdr.CreditCharge;
 		spin_lock(&server->req_lock);
 		server->credits += wdata->credits -
 					le16_to_cpu(req->hdr.CreditCharge);
@@ -2577,6 +2653,22 @@
 }
 
 int
+SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
+		  u64 persistent_fid, u64 volatile_fid)
+{
+	__u8 delete_pending = 1;
+	void *data;
+	unsigned int size;
+
+	data = &delete_pending;
+	size = 1; /* sizeof __u8 */
+
+	return send_set_info(xid, tcon, persistent_fid, volatile_fid,
+			current->tgid, FILE_DISPOSITION_INFORMATION, 1, &data,
+			&size);
+}
+
+int
 SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
 		  u64 persistent_fid, u64 volatile_fid, __le16 *target_file)
 {
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 4af5278..b8f553b 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -276,7 +276,7 @@
 	__le32 Channel;
 	__le16 SecurityBufferOffset;
 	__le16 SecurityBufferLength;
-	__le64 PreviousSessionId;
+	__u64 PreviousSessionId;
 	__u8   Buffer[1];	/* variable length GSS security buffer */
 } __packed;
 
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 79dc650..adc5234 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -47,6 +47,10 @@
 			      struct smb_rqst *rqst);
 extern struct mid_q_entry *smb2_setup_async_request(
 			struct TCP_Server_Info *server, struct smb_rqst *rqst);
+extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
+					   __u64 ses_id);
+extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
+						__u64 ses_id, __u32  tid);
 extern int smb2_calc_signature(struct smb_rqst *rqst,
 				struct TCP_Server_Info *server);
 extern int smb3_calc_signature(struct smb_rqst *rqst,
@@ -95,6 +99,7 @@
 extern int smb2_unlock_range(struct cifsFileInfo *cfile,
 			     struct file_lock *flock, const unsigned int xid);
 extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
+extern void smb2_reconnect_server(struct work_struct *work);
 
 /*
  * SMB2 Worker functions - most of protocol specific implementation details
@@ -140,6 +145,8 @@
 extern int SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
 		       u64 persistent_fid, u64 volatile_fid,
 		       __le16 *target_file);
+extern int SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
+		      u64 persistent_fid, u64 volatile_fid);
 extern int SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
 			     u64 persistent_fid, u64 volatile_fid,
 			     __le16 *target_file);
@@ -154,6 +161,9 @@
 extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
 			     const u64 persistent_fid, const u64 volatile_fid,
 			     const __u8 oplock_level);
+extern int smb2_handle_cancelled_mid(char *buffer,
+					struct TCP_Server_Info *server);
+void smb2_cancelled_close_fid(struct work_struct *work);
 extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
 			 u64 persistent_file_id, u64 volatile_file_id,
 			 struct kstatfs *FSData);
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index d4c5b6f..69e3b32 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -115,22 +115,68 @@
 }
 
 static struct cifs_ses *
-smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server)
+smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
 {
 	struct cifs_ses *ses;
 
-	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
-		if (ses->Suid != smb2hdr->SessionId)
+		if (ses->Suid != ses_id)
 			continue;
-		spin_unlock(&cifs_tcp_ses_lock);
 		return ses;
 	}
-	spin_unlock(&cifs_tcp_ses_lock);
 
 	return NULL;
 }
 
+struct cifs_ses *
+smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
+{
+	struct cifs_ses *ses;
+
+	spin_lock(&cifs_tcp_ses_lock);
+	ses = smb2_find_smb_ses_unlocked(server, ses_id);
+	spin_unlock(&cifs_tcp_ses_lock);
+
+	return ses;
+}
+
+static struct cifs_tcon *
+smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32  tid)
+{
+	struct cifs_tcon *tcon;
+
+	list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+		if (tcon->tid != tid)
+			continue;
+		++tcon->tc_count;
+		return tcon;
+	}
+
+	return NULL;
+}
+
+/*
+ * Obtain tcon corresponding to the tid in the given
+ * cifs_ses
+ */
+
+struct cifs_tcon *
+smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
+{
+	struct cifs_ses *ses;
+	struct cifs_tcon *tcon;
+
+	spin_lock(&cifs_tcp_ses_lock);
+	ses = smb2_find_smb_ses_unlocked(server, ses_id);
+	if (!ses) {
+		spin_unlock(&cifs_tcp_ses_lock);
+		return NULL;
+	}
+	tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
+	spin_unlock(&cifs_tcp_ses_lock);
+
+	return tcon;
+}
 
 int
 smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
@@ -143,7 +189,7 @@
 	struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
 	struct cifs_ses *ses;
 
-	ses = smb2_find_smb_ses(smb2_pdu, server);
+	ses = smb2_find_smb_ses(server, smb2_pdu->SessionId);
 	if (!ses) {
 		cifs_dbg(VFS, "%s: Could not find session\n", __func__);
 		return 0;
@@ -314,7 +360,7 @@
 	struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
 	struct cifs_ses *ses;
 
-	ses = smb2_find_smb_ses(smb2_pdu, server);
+	ses = smb2_find_smb_ses(server, smb2_pdu->SessionId);
 	if (!ses) {
 		cifs_dbg(VFS, "%s: Could not find session\n", __func__);
 		return 0;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 87abe8e..54af102 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -786,9 +786,11 @@
 
 	rc = wait_for_response(ses->server, midQ);
 	if (rc != 0) {
+		cifs_dbg(FYI, "Cancelling wait for mid %llu\n",	midQ->mid);
 		send_cancel(ses->server, buf, midQ);
 		spin_lock(&GlobalMid_Lock);
 		if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
+			midQ->mid_flags |= MID_WAIT_CANCELLED;
 			midQ->callback = DeleteMidQEntry;
 			spin_unlock(&GlobalMid_Lock);
 			cifs_small_buf_release(buf);
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index ec5c832..0525ebc 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -83,14 +83,13 @@
 	ret = -ENOMEM;
 	sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
 	if (sl) {
-		sl->sl_target = config_item_get(item);
 		spin_lock(&configfs_dirent_lock);
 		if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
 			spin_unlock(&configfs_dirent_lock);
-			config_item_put(item);
 			kfree(sl);
 			return -ENOENT;
 		}
+		sl->sl_target = config_item_get(item);
 		list_add(&sl->sl_list, &target_sd->s_links);
 		spin_unlock(&configfs_dirent_lock);
 		ret = configfs_create_link(sl, parent_item->ci_dentry,
diff --git a/fs/coredump.c b/fs/coredump.c
index dfc87c5..2ce5ef4 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -1,6 +1,7 @@
 #include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/fdtable.h>
+#include <linux/freezer.h>
 #include <linux/mm.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
@@ -399,7 +400,9 @@
 	if (core_waiters > 0) {
 		struct core_thread *ptr;
 
+		freezer_do_not_count();
 		wait_for_completion(&core_state->startup);
+		freezer_count();
 		/*
 		 * Wait for all the threads to become inactive, so that
 		 * all the thread context (extended register state, like
@@ -717,7 +720,7 @@
 			goto close_fail;
 		if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
 			goto close_fail;
-		if (do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file))
+		if (do_truncate2(cprm.file->f_path.mnt, cprm.file->f_path.dentry, 0, 0, cprm.file))
 			goto close_fail;
 	}
 
@@ -807,3 +810,21 @@
 	return mod ? dump_skip(cprm, align - mod) : 1;
 }
 EXPORT_SYMBOL(dump_align);
+
+/*
+ * Ensures that file size is big enough to contain the current file
+ * postion. This prevents gdb from complaining about a truncated file
+ * if the last "write" to the file was dump_skip.
+ */
+void dump_truncate(struct coredump_params *cprm)
+{
+	struct file *file = cprm->file;
+	loff_t offset;
+
+	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+		offset = file->f_op->llseek(file, 0, SEEK_CUR);
+		if (i_size_read(file->f_mapping->host) < offset)
+			do_truncate(file->f_path.dentry, offset, 0, file);
+	}
+}
+EXPORT_SYMBOL(dump_truncate);
diff --git a/fs/dcache.c b/fs/dcache.c
index 240935d..7b8feb6 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -578,7 +578,6 @@
 
 failed:
 	spin_unlock(&dentry->d_lock);
-	cpu_relax();
 	return dentry; /* try again with same dentry */
 }
 
@@ -752,6 +751,8 @@
 		return;
 
 repeat:
+	might_sleep();
+
 	rcu_read_lock();
 	if (likely(fast_dput(dentry))) {
 		rcu_read_unlock();
@@ -783,8 +784,10 @@
 
 kill_it:
 	dentry = dentry_kill(dentry);
-	if (dentry)
+	if (dentry) {
+		cond_resched();
 		goto repeat;
+	}
 }
 EXPORT_SYMBOL(dput);
 
@@ -1319,8 +1322,11 @@
 	}
 	spin_lock(&dentry->d_lock);
 	if (!d_unlinked(dentry)) {
-		dentry->d_flags |= DCACHE_MOUNTED;
-		ret = 0;
+		ret = -EBUSY;
+		if (!d_mountpoint(dentry)) {
+			dentry->d_flags |= DCACHE_MOUNTED;
+			ret = 0;
+		}
 	}
  	spin_unlock(&dentry->d_lock);
 out:
@@ -1618,7 +1624,7 @@
 	struct dentry *dentry = __d_alloc(parent->d_sb, name);
 	if (!dentry)
 		return NULL;
-
+	dentry->d_flags |= DCACHE_RCUACCESS;
 	spin_lock(&parent->d_lock);
 	/*
 	 * don't need child lock because it is not subject
@@ -2413,7 +2419,6 @@
 {
 	BUG_ON(!d_unhashed(entry));
 	hlist_bl_lock(b);
-	entry->d_flags |= DCACHE_RCUACCESS;
 	hlist_bl_add_head_rcu(&entry->d_hash, b);
 	hlist_bl_unlock(b);
 }
@@ -2632,6 +2637,7 @@
 	/* ... and switch them in the tree */
 	if (IS_ROOT(dentry)) {
 		/* splicing a tree */
+		dentry->d_flags |= DCACHE_RCUACCESS;
 		dentry->d_parent = target->d_parent;
 		target->d_parent = target;
 		list_del_init(&target->d_child);
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 706de32..c82edb0 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -128,6 +128,7 @@
 struct pts_fs_info {
 	struct ida allocated_ptys;
 	struct pts_mount_opts mount_opts;
+	struct super_block *sb;
 	struct dentry *ptmx_dentry;
 };
 
@@ -358,7 +359,7 @@
 	.show_options	= devpts_show_options,
 };
 
-static void *new_pts_fs_info(void)
+static void *new_pts_fs_info(struct super_block *sb)
 {
 	struct pts_fs_info *fsi;
 
@@ -369,6 +370,7 @@
 	ida_init(&fsi->allocated_ptys);
 	fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
 	fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
+	fsi->sb = sb;
 
 	return fsi;
 }
@@ -384,7 +386,7 @@
 	s->s_op = &devpts_sops;
 	s->s_time_gran = 1;
 
-	s->s_fs_info = new_pts_fs_info();
+	s->s_fs_info = new_pts_fs_info(s);
 	if (!s->s_fs_info)
 		goto fail;
 
@@ -524,17 +526,14 @@
  * to the System V naming convention
  */
 
-int devpts_new_index(struct inode *ptmx_inode)
+int devpts_new_index(struct pts_fs_info *fsi)
 {
-	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
-	struct pts_fs_info *fsi;
 	int index;
 	int ida_ret;
 
-	if (!sb)
+	if (!fsi)
 		return -ENODEV;
 
-	fsi = DEVPTS_SB(sb);
 retry:
 	if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
 		return -ENOMEM;
@@ -564,11 +563,8 @@
 	return index;
 }
 
-void devpts_kill_index(struct inode *ptmx_inode, int idx)
+void devpts_kill_index(struct pts_fs_info *fsi, int idx)
 {
-	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
-	struct pts_fs_info *fsi = DEVPTS_SB(sb);
-
 	mutex_lock(&allocated_ptys_lock);
 	ida_remove(&fsi->allocated_ptys, idx);
 	pty_count--;
@@ -578,21 +574,25 @@
 /*
  * pty code needs to hold extra references in case of last /dev/tty close
  */
-
-void devpts_add_ref(struct inode *ptmx_inode)
+struct pts_fs_info *devpts_get_ref(struct inode *ptmx_inode, struct file *file)
 {
-	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
+	struct super_block *sb;
+	struct pts_fs_info *fsi;
+
+	sb = pts_sb_from_inode(ptmx_inode);
+	if (!sb)
+		return NULL;
+	fsi = DEVPTS_SB(sb);
+	if (!fsi)
+		return NULL;
 
 	atomic_inc(&sb->s_active);
-	ihold(ptmx_inode);
+	return fsi;
 }
 
-void devpts_del_ref(struct inode *ptmx_inode)
+void devpts_put_ref(struct pts_fs_info *fsi)
 {
-	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
-
-	iput(ptmx_inode);
-	deactivate_super(sb);
+	deactivate_super(fsi->sb);
 }
 
 /**
@@ -604,22 +604,21 @@
  *
  * The created inode is returned. Remove it from /dev/pts/ by devpts_pty_kill.
  */
-struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
+struct inode *devpts_pty_new(struct pts_fs_info *fsi, dev_t device, int index,
 		void *priv)
 {
 	struct dentry *dentry;
-	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
+	struct super_block *sb;
 	struct inode *inode;
 	struct dentry *root;
-	struct pts_fs_info *fsi;
 	struct pts_mount_opts *opts;
 	char s[12];
 
-	if (!sb)
+	if (!fsi)
 		return ERR_PTR(-ENODEV);
 
+	sb = fsi->sb;
 	root = sb->s_root;
-	fsi = DEVPTS_SB(sb);
 	opts = &fsi->mount_opts;
 
 	inode = new_inode(sb);
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 01171d8..c772fdf 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -575,7 +575,7 @@
 /*
  * Call into the fs to map some more disk blocks.  We record the current number
  * of available blocks at sdio->blocks_available.  These are in units of the
- * fs blocksize, (1 << inode->i_blkbits).
+ * fs blocksize, i_blocksize(inode).
  *
  * The fs is allowed to map lots of blocks at once.  If it wants to do that,
  * it uses the passed inode-relative block number as the file offset, as usual.
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 3a37bd3..9d7a4a7 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -1607,16 +1607,12 @@
 	mutex_lock(&connections_lock);
 	dlm_allow_conn = 0;
 	foreach_conn(stop_conn);
+	clean_writequeues();
+	foreach_conn(free_conn);
 	mutex_unlock(&connections_lock);
 
 	work_stop();
 
-	mutex_lock(&connections_lock);
-	clean_writequeues();
-
-	foreach_conn(free_conn);
-
-	mutex_unlock(&connections_lock);
 	kmem_cache_destroy(con_cache);
 }
 
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index feef8a9..27794b1 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -112,7 +112,6 @@
 		.sb = inode->i_sb,
 	};
 	lower_file = ecryptfs_file_to_lower(file);
-	lower_file->f_pos = ctx->pos;
 	rc = iterate_dir(lower_file, &buf.ctx);
 	ctx->pos = buf.ctx.pos;
 	if (rc < 0)
@@ -170,6 +169,19 @@
 	return rc;
 }
 
+static int ecryptfs_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct file *lower_file = ecryptfs_file_to_lower(file);
+	/*
+	 * Don't allow mmap on top of file systems that don't support it
+	 * natively.  If FILESYSTEM_MAX_STACK_DEPTH > 2 or ecryptfs
+	 * allows recursive mounting, this will need to be extended.
+	 */
+	if (!lower_file->f_op->mmap)
+		return -ENODEV;
+	return generic_file_mmap(file, vma);
+}
+
 /**
  * ecryptfs_open
  * @inode: inode speciying file to open
@@ -223,14 +235,6 @@
 	}
 	ecryptfs_set_file_lower(
 		file, ecryptfs_inode_to_private(inode)->lower_file);
-	if (d_is_dir(ecryptfs_dentry)) {
-		ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
-		mutex_lock(&crypt_stat->cs_mutex);
-		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
-		mutex_unlock(&crypt_stat->cs_mutex);
-		rc = 0;
-		goto out;
-	}
 	rc = read_or_initialize_metadata(ecryptfs_dentry);
 	if (rc)
 		goto out_put;
@@ -247,6 +251,45 @@
 	return rc;
 }
 
+/**
+ * ecryptfs_dir_open
+ * @inode: inode speciying file to open
+ * @file: Structure to return filled in
+ *
+ * Opens the file specified by inode.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int ecryptfs_dir_open(struct inode *inode, struct file *file)
+{
+	struct dentry *ecryptfs_dentry = file->f_path.dentry;
+	/* Private value of ecryptfs_dentry allocated in
+	 * ecryptfs_lookup() */
+	struct ecryptfs_file_info *file_info;
+	struct file *lower_file;
+
+	/* Released in ecryptfs_release or end of function if failure */
+	file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
+	ecryptfs_set_file_private(file, file_info);
+	if (unlikely(!file_info)) {
+		ecryptfs_printk(KERN_ERR,
+				"Error attempting to allocate memory\n");
+		return -ENOMEM;
+	}
+	lower_file = dentry_open(ecryptfs_dentry_to_lower_path(ecryptfs_dentry),
+				 file->f_flags, current_cred());
+	if (IS_ERR(lower_file)) {
+		printk(KERN_ERR "%s: Error attempting to initialize "
+			"the lower file for the dentry with name "
+			"[%pd]; rc = [%ld]\n", __func__,
+			ecryptfs_dentry, PTR_ERR(lower_file));
+		kmem_cache_free(ecryptfs_file_info_cache, file_info);
+		return PTR_ERR(lower_file);
+	}
+	ecryptfs_set_file_lower(file, lower_file);
+	return 0;
+}
+
 static int ecryptfs_flush(struct file *file, fl_owner_t td)
 {
 	struct file *lower_file = ecryptfs_file_to_lower(file);
@@ -267,6 +310,19 @@
 	return 0;
 }
 
+static int ecryptfs_dir_release(struct inode *inode, struct file *file)
+{
+	fput(ecryptfs_file_to_lower(file));
+	kmem_cache_free(ecryptfs_file_info_cache,
+			ecryptfs_file_to_private(file));
+	return 0;
+}
+
+static loff_t ecryptfs_dir_llseek(struct file *file, loff_t offset, int whence)
+{
+	return vfs_llseek(ecryptfs_file_to_lower(file), offset, whence);
+}
+
 static int
 ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
@@ -346,25 +402,21 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = ecryptfs_compat_ioctl,
 #endif
-	.open = ecryptfs_open,
-	.flush = ecryptfs_flush,
-	.release = ecryptfs_release,
+	.open = ecryptfs_dir_open,
+	.release = ecryptfs_dir_release,
 	.fsync = ecryptfs_fsync,
-	.fasync = ecryptfs_fasync,
-	.splice_read = generic_file_splice_read,
-	.llseek = default_llseek,
+	.llseek = ecryptfs_dir_llseek,
 };
 
 const struct file_operations ecryptfs_main_fops = {
 	.llseek = generic_file_llseek,
 	.read_iter = ecryptfs_read_update_atime,
 	.write_iter = generic_file_write_iter,
-	.iterate = ecryptfs_readdir,
 	.unlocked_ioctl = ecryptfs_unlocked_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = ecryptfs_compat_ioctl,
 #endif
-	.mmap = generic_file_mmap,
+	.mmap = ecryptfs_mmap,
 	.open = ecryptfs_open,
 	.flush = ecryptfs_flush,
 	.release = ecryptfs_release,
diff --git a/fs/exec.c b/fs/exec.c
index b06623a..073ae12 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -19,7 +19,7 @@
  * current->executable is only used by the procfs.  This allows a dispatch
  * table to check for several different types  of binary formats.  We keep
  * trying until we recognize the file or we run out of supported binary
- * formats. 
+ * formats.
  */
 
 #include <linux/slab.h>
@@ -56,6 +56,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/oom.h>
 #include <linux/compat.h>
+#include <linux/user_namespace.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -205,8 +206,26 @@
 
 	if (write) {
 		unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
+		unsigned long ptr_size;
 		struct rlimit *rlim;
 
+		/*
+		 * Since the stack will hold pointers to the strings, we
+		 * must account for them as well.
+		 *
+		 * The size calculation is the entire vma while each arg page is
+		 * built, so each time we get here it's calculating how far it
+		 * is currently (rather than each call being just the newly
+		 * added size from the arg page).  As a result, we need to
+		 * always add the entire size of the pointers, so that on the
+		 * last call to get_arg_page() we'll actually have the entire
+		 * correct size.
+		 */
+		ptr_size = (bprm->argc + bprm->envc) * sizeof(void *);
+		if (ptr_size > ULONG_MAX - size)
+			goto fail;
+		size += ptr_size;
+
 		acct_arg_size(bprm, size / PAGE_SIZE);
 
 		/*
@@ -224,13 +243,15 @@
 		 *    to work from.
 		 */
 		rlim = current->signal->rlim;
-		if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) {
-			put_page(page);
-			return NULL;
-		}
+		if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4)
+			goto fail;
 	}
 
 	return page;
+
+fail:
+	put_page(page);
+	return NULL;
 }
 
 static void put_arg_page(struct page *page)
@@ -1114,6 +1135,13 @@
 	flush_thread();
 	current->personality &= ~bprm->per_clear;
 
+	/*
+	 * We have to apply CLOEXEC before we change whether the process is
+	 * dumpable (in setup_new_exec) to avoid a race with a process in userspace
+	 * trying to access the should-be-closed file descriptors of a process
+	 * undergoing exec(2).
+	 */
+	do_close_on_exec(current->files);
 	return 0;
 
 out:
@@ -1123,8 +1151,24 @@
 
 void would_dump(struct linux_binprm *bprm, struct file *file)
 {
-	if (inode_permission(file_inode(file), MAY_READ) < 0)
+	struct inode *inode = file_inode(file);
+
+	if (inode_permission2(file->f_path.mnt, inode, MAY_READ) < 0) {
+		struct user_namespace *old, *user_ns;
+
 		bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+
+		/* Ensure mm->user_ns contains the executable */
+		user_ns = old = bprm->mm->user_ns;
+		while ((user_ns != &init_user_ns) &&
+		       !privileged_wrt_inode_uidgid(user_ns, inode))
+			user_ns = user_ns->parent;
+
+		if (old != user_ns) {
+			bprm->mm->user_ns = get_user_ns(user_ns);
+			put_user_ns(old);
+		}
+	}
 }
 EXPORT_SYMBOL(would_dump);
 
@@ -1154,7 +1198,6 @@
 	    !gid_eq(bprm->cred->gid, current_egid())) {
 		current->pdeath_signal = 0;
 	} else {
-		would_dump(bprm, bprm->file);
 		if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)
 			set_dumpable(current->mm, suid_dumpable);
 	}
@@ -1163,7 +1206,6 @@
 	   group */
 	current->self_exec_id++;
 	flush_signal_handlers(current, 0);
-	do_close_on_exec(current->files);
 }
 EXPORT_SYMBOL(setup_new_exec);
 
@@ -1254,7 +1296,7 @@
 	unsigned n_fs;
 
 	if (p->ptrace) {
-		if (p->ptrace & PT_PTRACE_CAP)
+		if (ptracer_capable(p, current_user_ns()))
 			bprm->unsafe |= LSM_UNSAFE_PTRACE_CAP;
 		else
 			bprm->unsafe |= LSM_UNSAFE_PTRACE;
@@ -1587,6 +1629,8 @@
 	if (retval < 0)
 		goto out;
 
+	would_dump(bprm, bprm->file);
+
 	retval = exec_binprm(bprm);
 	if (retval < 0)
 		goto out;
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 27695e6..d6aeb84 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -193,15 +193,11 @@
 		case ACL_TYPE_ACCESS:
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
 			if (acl) {
-				error = posix_acl_equiv_mode(acl, &inode->i_mode);
-				if (error < 0)
+				error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+				if (error)
 					return error;
-				else {
-					inode->i_ctime = CURRENT_TIME_SEC;
-					mark_inode_dirty(inode);
-					if (error == 0)
-						acl = NULL;
-				}
+				inode->i_ctime = CURRENT_TIME_SEC;
+				mark_inode_dirty(inode);
 			}
 			break;
 
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 4c69c94..f98ce7e 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -61,6 +61,8 @@
 #define rsv_start rsv_window._rsv_start
 #define rsv_end rsv_window._rsv_end
 
+struct mb2_cache;
+
 /*
  * second extended-fs super-block data in memory
  */
@@ -111,6 +113,7 @@
 	 * of the mount options.
 	 */
 	spinlock_t s_lock;
+	struct mb2_cache *s_mb_cache;
 };
 
 static inline spinlock_t *
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 748d35a..111a317 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -131,7 +131,10 @@
 
 	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
 
-	ext2_xattr_put_super(sb);
+	if (sbi->s_mb_cache) {
+		ext2_xattr_destroy_cache(sbi->s_mb_cache);
+		sbi->s_mb_cache = NULL;
+	}
 	if (!(sb->s_flags & MS_RDONLY)) {
 		struct ext2_super_block *es = sbi->s_es;
 
@@ -1104,6 +1107,14 @@
 		ext2_msg(sb, KERN_ERR, "error: insufficient memory");
 		goto failed_mount3;
 	}
+
+#ifdef CONFIG_EXT2_FS_XATTR
+	sbi->s_mb_cache = ext2_xattr_create_cache();
+	if (!sbi->s_mb_cache) {
+		ext2_msg(sb, KERN_ERR, "Failed to create an mb_cache");
+		goto failed_mount3;
+	}
+#endif
 	/*
 	 * set up enough so that it can read an inode
 	 */
@@ -1149,6 +1160,8 @@
 			sb->s_id);
 	goto failed_mount;
 failed_mount3:
+	if (sbi->s_mb_cache)
+		ext2_xattr_destroy_cache(sbi->s_mb_cache);
 	percpu_counter_destroy(&sbi->s_freeblocks_counter);
 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
 	percpu_counter_destroy(&sbi->s_dirs_counter);
@@ -1555,20 +1568,17 @@
 
 static int __init init_ext2_fs(void)
 {
-	int err = init_ext2_xattr();
-	if (err)
-		return err;
+	int err;
+
 	err = init_inodecache();
 	if (err)
-		goto out1;
+		return err;
         err = register_filesystem(&ext2_fs_type);
 	if (err)
 		goto out;
 	return 0;
 out:
 	destroy_inodecache();
-out1:
-	exit_ext2_xattr();
 	return err;
 }
 
@@ -1576,7 +1586,6 @@
 {
 	unregister_filesystem(&ext2_fs_type);
 	destroy_inodecache();
-	exit_ext2_xattr();
 }
 
 MODULE_AUTHOR("Remy Card and others");
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index fa70848..24736c8 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -56,7 +56,7 @@
 #include <linux/buffer_head.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/mbcache.h>
+#include <linux/mbcache2.h>
 #include <linux/quotaops.h>
 #include <linux/rwsem.h>
 #include <linux/security.h>
@@ -92,14 +92,12 @@
 static int ext2_xattr_set2(struct inode *, struct buffer_head *,
 			   struct ext2_xattr_header *);
 
-static int ext2_xattr_cache_insert(struct buffer_head *);
+static int ext2_xattr_cache_insert(struct mb2_cache *, struct buffer_head *);
 static struct buffer_head *ext2_xattr_cache_find(struct inode *,
 						 struct ext2_xattr_header *);
 static void ext2_xattr_rehash(struct ext2_xattr_header *,
 			      struct ext2_xattr_entry *);
 
-static struct mb_cache *ext2_xattr_cache;
-
 static const struct xattr_handler *ext2_xattr_handler_map[] = {
 	[EXT2_XATTR_INDEX_USER]		     = &ext2_xattr_user_handler,
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
@@ -154,6 +152,7 @@
 	size_t name_len, size;
 	char *end;
 	int error;
+	struct mb2_cache *ext2_mb_cache = EXT2_SB(inode->i_sb)->s_mb_cache;
 
 	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
 		  name_index, name, buffer, (long)buffer_size);
@@ -198,7 +197,7 @@
 			goto found;
 		entry = next;
 	}
-	if (ext2_xattr_cache_insert(bh))
+	if (ext2_xattr_cache_insert(ext2_mb_cache, bh))
 		ea_idebug(inode, "cache insert failed");
 	error = -ENODATA;
 	goto cleanup;
@@ -211,7 +210,7 @@
 	    le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
 		goto bad_block;
 
-	if (ext2_xattr_cache_insert(bh))
+	if (ext2_xattr_cache_insert(ext2_mb_cache, bh))
 		ea_idebug(inode, "cache insert failed");
 	if (buffer) {
 		error = -ERANGE;
@@ -249,6 +248,7 @@
 	char *end;
 	size_t rest = buffer_size;
 	int error;
+	struct mb2_cache *ext2_mb_cache = EXT2_SB(inode->i_sb)->s_mb_cache;
 
 	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
 		  buffer, (long)buffer_size);
@@ -283,7 +283,7 @@
 			goto bad_block;
 		entry = next;
 	}
-	if (ext2_xattr_cache_insert(bh))
+	if (ext2_xattr_cache_insert(ext2_mb_cache, bh))
 		ea_idebug(inode, "cache insert failed");
 
 	/* list the attribute names */
@@ -480,22 +480,23 @@
 	/* Here we know that we can set the new attribute. */
 
 	if (header) {
-		struct mb_cache_entry *ce;
-
 		/* assert(header == HDR(bh)); */
-		ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_bdev,
-					bh->b_blocknr);
 		lock_buffer(bh);
 		if (header->h_refcount == cpu_to_le32(1)) {
+			__u32 hash = le32_to_cpu(header->h_hash);
+
 			ea_bdebug(bh, "modifying in-place");
-			if (ce)
-				mb_cache_entry_free(ce);
+			/*
+			 * This must happen under buffer lock for
+			 * ext2_xattr_set2() to reliably detect modified block
+			 */
+			mb2_cache_entry_delete_block(EXT2_SB(sb)->s_mb_cache,
+						     hash, bh->b_blocknr);
+
 			/* keep the buffer locked while modifying it. */
 		} else {
 			int offset;
 
-			if (ce)
-				mb_cache_entry_release(ce);
 			unlock_buffer(bh);
 			ea_bdebug(bh, "cloning");
 			header = kmalloc(bh->b_size, GFP_KERNEL);
@@ -623,6 +624,7 @@
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *new_bh = NULL;
 	int error;
+	struct mb2_cache *ext2_mb_cache = EXT2_SB(sb)->s_mb_cache;
 
 	if (header) {
 		new_bh = ext2_xattr_cache_find(inode, header);
@@ -650,7 +652,7 @@
 			   don't need to change the reference count. */
 			new_bh = old_bh;
 			get_bh(new_bh);
-			ext2_xattr_cache_insert(new_bh);
+			ext2_xattr_cache_insert(ext2_mb_cache, new_bh);
 		} else {
 			/* We need to allocate a new block */
 			ext2_fsblk_t goal = ext2_group_first_block_no(sb,
@@ -671,7 +673,7 @@
 			memcpy(new_bh->b_data, header, new_bh->b_size);
 			set_buffer_uptodate(new_bh);
 			unlock_buffer(new_bh);
-			ext2_xattr_cache_insert(new_bh);
+			ext2_xattr_cache_insert(ext2_mb_cache, new_bh);
 			
 			ext2_xattr_update_super_block(sb);
 		}
@@ -704,19 +706,21 @@
 
 	error = 0;
 	if (old_bh && old_bh != new_bh) {
-		struct mb_cache_entry *ce;
-
 		/*
 		 * If there was an old block and we are no longer using it,
 		 * release the old block.
 		 */
-		ce = mb_cache_entry_get(ext2_xattr_cache, old_bh->b_bdev,
-					old_bh->b_blocknr);
 		lock_buffer(old_bh);
 		if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
+			__u32 hash = le32_to_cpu(HDR(old_bh)->h_hash);
+
+			/*
+			 * This must happen under buffer lock for
+			 * ext2_xattr_set2() to reliably detect freed block
+			 */
+			mb2_cache_entry_delete_block(ext2_mb_cache,
+						     hash, old_bh->b_blocknr);
 			/* Free the old block. */
-			if (ce)
-				mb_cache_entry_free(ce);
 			ea_bdebug(old_bh, "freeing");
 			ext2_free_blocks(inode, old_bh->b_blocknr, 1);
 			mark_inode_dirty(inode);
@@ -727,8 +731,6 @@
 		} else {
 			/* Decrement the refcount only. */
 			le32_add_cpu(&HDR(old_bh)->h_refcount, -1);
-			if (ce)
-				mb_cache_entry_release(ce);
 			dquot_free_block_nodirty(inode, 1);
 			mark_inode_dirty(inode);
 			mark_buffer_dirty(old_bh);
@@ -754,7 +756,6 @@
 ext2_xattr_delete_inode(struct inode *inode)
 {
 	struct buffer_head *bh = NULL;
-	struct mb_cache_entry *ce;
 
 	down_write(&EXT2_I(inode)->xattr_sem);
 	if (!EXT2_I(inode)->i_file_acl)
@@ -774,19 +775,22 @@
 			EXT2_I(inode)->i_file_acl);
 		goto cleanup;
 	}
-	ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_bdev, bh->b_blocknr);
 	lock_buffer(bh);
 	if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-		if (ce)
-			mb_cache_entry_free(ce);
+		__u32 hash = le32_to_cpu(HDR(bh)->h_hash);
+
+		/*
+		 * This must happen under buffer lock for ext2_xattr_set2() to
+		 * reliably detect freed block
+		 */
+		mb2_cache_entry_delete_block(EXT2_SB(inode->i_sb)->s_mb_cache,
+					     hash, bh->b_blocknr);
 		ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
 		get_bh(bh);
 		bforget(bh);
 		unlock_buffer(bh);
 	} else {
 		le32_add_cpu(&HDR(bh)->h_refcount, -1);
-		if (ce)
-			mb_cache_entry_release(ce);
 		ea_bdebug(bh, "refcount now=%d",
 			le32_to_cpu(HDR(bh)->h_refcount));
 		unlock_buffer(bh);
@@ -803,18 +807,6 @@
 }
 
 /*
- * ext2_xattr_put_super()
- *
- * This is called when a file system is unmounted.
- */
-void
-ext2_xattr_put_super(struct super_block *sb)
-{
-	mb_cache_shrink(sb->s_bdev);
-}
-
-
-/*
  * ext2_xattr_cache_insert()
  *
  * Create a new entry in the extended attribute cache, and insert
@@ -823,28 +815,20 @@
  * Returns 0, or a negative error number on failure.
  */
 static int
-ext2_xattr_cache_insert(struct buffer_head *bh)
+ext2_xattr_cache_insert(struct mb2_cache *cache, struct buffer_head *bh)
 {
 	__u32 hash = le32_to_cpu(HDR(bh)->h_hash);
-	struct mb_cache_entry *ce;
 	int error;
 
-	ce = mb_cache_entry_alloc(ext2_xattr_cache, GFP_NOFS);
-	if (!ce)
-		return -ENOMEM;
-	error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, hash);
+	error = mb2_cache_entry_create(cache, GFP_NOFS, hash, bh->b_blocknr);
 	if (error) {
-		mb_cache_entry_free(ce);
 		if (error == -EBUSY) {
 			ea_bdebug(bh, "already in cache (%d cache entries)",
 				atomic_read(&ext2_xattr_cache->c_entry_count));
 			error = 0;
 		}
-	} else {
-		ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-			  atomic_read(&ext2_xattr_cache->c_entry_count));
-		mb_cache_entry_release(ce);
-	}
+	} else
+		ea_bdebug(bh, "inserting [%x]", (int)hash);
 	return error;
 }
 
@@ -900,23 +884,17 @@
 ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
 {
 	__u32 hash = le32_to_cpu(header->h_hash);
-	struct mb_cache_entry *ce;
+	struct mb2_cache_entry *ce;
+	struct mb2_cache *ext2_mb_cache = EXT2_SB(inode->i_sb)->s_mb_cache;
 
 	if (!header->h_hash)
 		return NULL;  /* never share */
 	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
 again:
-	ce = mb_cache_entry_find_first(ext2_xattr_cache, inode->i_sb->s_bdev,
-				       hash);
+	ce = mb2_cache_entry_find_first(ext2_mb_cache, hash);
 	while (ce) {
 		struct buffer_head *bh;
 
-		if (IS_ERR(ce)) {
-			if (PTR_ERR(ce) == -EAGAIN)
-				goto again;
-			break;
-		}
-
 		bh = sb_bread(inode->i_sb, ce->e_block);
 		if (!bh) {
 			ext2_error(inode->i_sb, "ext2_xattr_cache_find",
@@ -924,7 +902,21 @@
 				inode->i_ino, (unsigned long) ce->e_block);
 		} else {
 			lock_buffer(bh);
-			if (le32_to_cpu(HDR(bh)->h_refcount) >
+			/*
+			 * We have to be careful about races with freeing or
+			 * rehashing of xattr block. Once we hold buffer lock
+			 * xattr block's state is stable so we can check
+			 * whether the block got freed / rehashed or not.
+			 * Since we unhash mbcache entry under buffer lock when
+			 * freeing / rehashing xattr block, checking whether
+			 * entry is still hashed is reliable.
+			 */
+			if (hlist_bl_unhashed(&ce->e_hash_list)) {
+				mb2_cache_entry_put(ext2_mb_cache, ce);
+				unlock_buffer(bh);
+				brelse(bh);
+				goto again;
+			} else if (le32_to_cpu(HDR(bh)->h_refcount) >
 				   EXT2_XATTR_REFCOUNT_MAX) {
 				ea_idebug(inode, "block %ld refcount %d>%d",
 					  (unsigned long) ce->e_block,
@@ -933,13 +925,14 @@
 			} else if (!ext2_xattr_cmp(header, HDR(bh))) {
 				ea_bdebug(bh, "b_count=%d",
 					  atomic_read(&(bh->b_count)));
-				mb_cache_entry_release(ce);
+				mb2_cache_entry_touch(ext2_mb_cache, ce);
+				mb2_cache_entry_put(ext2_mb_cache, ce);
 				return bh;
 			}
 			unlock_buffer(bh);
 			brelse(bh);
 		}
-		ce = mb_cache_entry_find_next(ce, inode->i_sb->s_bdev, hash);
+		ce = mb2_cache_entry_find_next(ext2_mb_cache, ce);
 	}
 	return NULL;
 }
@@ -1012,17 +1005,15 @@
 
 #undef BLOCK_HASH_SHIFT
 
-int __init
-init_ext2_xattr(void)
+#define HASH_BUCKET_BITS 10
+
+struct mb2_cache *ext2_xattr_create_cache(void)
 {
-	ext2_xattr_cache = mb_cache_create("ext2_xattr", 6);
-	if (!ext2_xattr_cache)
-		return -ENOMEM;
-	return 0;
+	return mb2_cache_create(HASH_BUCKET_BITS);
 }
 
-void
-exit_ext2_xattr(void)
+void ext2_xattr_destroy_cache(struct mb2_cache *cache)
 {
-	mb_cache_destroy(ext2_xattr_cache);
+	if (cache)
+		mb2_cache_destroy(cache);
 }
diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h
index 60edf29..6ea38aa 100644
--- a/fs/ext2/xattr.h
+++ b/fs/ext2/xattr.h
@@ -53,6 +53,8 @@
 #define EXT2_XATTR_SIZE(size) \
 	(((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
 
+struct mb2_cache;
+
 # ifdef CONFIG_EXT2_FS_XATTR
 
 extern const struct xattr_handler ext2_xattr_user_handler;
@@ -65,10 +67,9 @@
 extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
 
 extern void ext2_xattr_delete_inode(struct inode *);
-extern void ext2_xattr_put_super(struct super_block *);
 
-extern int init_ext2_xattr(void);
-extern void exit_ext2_xattr(void);
+extern struct mb2_cache *ext2_xattr_create_cache(void);
+extern void ext2_xattr_destroy_cache(struct mb2_cache *cache);
 
 extern const struct xattr_handler *ext2_xattr_handlers[];
 
@@ -93,19 +94,7 @@
 {
 }
 
-static inline void
-ext2_xattr_put_super(struct super_block *sb)
-{
-}
-
-static inline int
-init_ext2_xattr(void)
-{
-	return 0;
-}
-
-static inline void
-exit_ext2_xattr(void)
+static inline void ext2_xattr_destroy_cache(struct mb2_cache *cache)
 {
 }
 
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index b46e9fc..3c82932 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -106,6 +106,7 @@
 	select CRYPTO_ECB
 	select CRYPTO_XTS
 	select CRYPTO_CTS
+	select CRYPTO_HEH
 	select CRYPTO_CTR
 	select CRYPTO_SHA256
 	select KEYS
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 69b1e73..c3fe1e3 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -196,15 +196,11 @@
 	case ACL_TYPE_ACCESS:
 		name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
 		if (acl) {
-			error = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (error < 0)
+			error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (error)
 				return error;
-			else {
-				inode->i_ctime = ext4_current_time(inode);
-				ext4_mark_inode_dirty(handle, inode);
-				if (error == 0)
-					acl = NULL;
-			}
+			inode->i_ctime = ext4_current_time(inode);
+			ext4_mark_inode_dirty(handle, inode);
 		}
 		break;
 
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index fe1f50f..f971104 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -208,6 +208,9 @@
 	memset(bh->b_data, 0, sb->s_blocksize);
 
 	bit_max = ext4_num_base_meta_clusters(sb, block_group);
+	if ((bit_max >> 3) >= bh->b_size)
+		return -EFSCORRUPTED;
+
 	for (bit = 0; bit < bit_max; bit++)
 		ext4_set_bit(bit, bh->b_data);
 
diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
index 1a08350..f240cef 100644
--- a/fs/ext4/crypto.c
+++ b/fs/ext4/crypto.c
@@ -34,6 +34,7 @@
 #include <linux/random.h>
 #include <linux/scatterlist.h>
 #include <linux/spinlock_types.h>
+#include <linux/namei.h>
 
 #include "ext4_extents.h"
 #include "xattr.h"
@@ -93,7 +94,8 @@
  * Return: An allocated and initialized encryption context on success; error
  * value or NULL otherwise.
  */
-struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode,
+					    gfp_t gfp_flags)
 {
 	struct ext4_crypto_ctx *ctx = NULL;
 	int res = 0;
@@ -120,7 +122,7 @@
 		list_del(&ctx->free_list);
 	spin_unlock_irqrestore(&ext4_crypto_ctx_lock, flags);
 	if (!ctx) {
-		ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, GFP_NOFS);
+		ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, gfp_flags);
 		if (!ctx) {
 			res = -ENOMEM;
 			goto out;
@@ -257,7 +259,8 @@
 			    ext4_direction_t rw,
 			    pgoff_t index,
 			    struct page *src_page,
-			    struct page *dest_page)
+			    struct page *dest_page,
+			    gfp_t gfp_flags)
 
 {
 	u8 xts_tweak[EXT4_XTS_TWEAK_SIZE];
@@ -268,7 +271,7 @@
 	struct crypto_ablkcipher *tfm = ci->ci_ctfm;
 	int res = 0;
 
-	req = ablkcipher_request_alloc(tfm, GFP_NOFS);
+	req = ablkcipher_request_alloc(tfm, gfp_flags);
 	if (!req) {
 		printk_ratelimited(KERN_ERR
 				   "%s: crypto_request_alloc() failed\n",
@@ -309,9 +312,10 @@
 	return 0;
 }
 
-static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
+static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx,
+				      gfp_t gfp_flags)
 {
-	ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, GFP_NOWAIT);
+	ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, gfp_flags);
 	if (ctx->w.bounce_page == NULL)
 		return ERR_PTR(-ENOMEM);
 	ctx->flags |= EXT4_WRITE_PATH_FL;
@@ -334,7 +338,8 @@
  * error value or NULL.
  */
 struct page *ext4_encrypt(struct inode *inode,
-			  struct page *plaintext_page)
+			  struct page *plaintext_page,
+			  gfp_t gfp_flags)
 {
 	struct ext4_crypto_ctx *ctx;
 	struct page *ciphertext_page = NULL;
@@ -342,17 +347,17 @@
 
 	BUG_ON(!PageLocked(plaintext_page));
 
-	ctx = ext4_get_crypto_ctx(inode);
+	ctx = ext4_get_crypto_ctx(inode, gfp_flags);
 	if (IS_ERR(ctx))
 		return (struct page *) ctx;
 
 	/* The encryption operation will require a bounce page. */
-	ciphertext_page = alloc_bounce_page(ctx);
+	ciphertext_page = alloc_bounce_page(ctx, gfp_flags);
 	if (IS_ERR(ciphertext_page))
 		goto errout;
 	ctx->w.control_page = plaintext_page;
 	err = ext4_page_crypto(inode, EXT4_ENCRYPT, plaintext_page->index,
-			       plaintext_page, ciphertext_page);
+			       plaintext_page, ciphertext_page, gfp_flags);
 	if (err) {
 		ciphertext_page = ERR_PTR(err);
 	errout:
@@ -380,8 +385,8 @@
 {
 	BUG_ON(!PageLocked(page));
 
-	return ext4_page_crypto(page->mapping->host,
-				EXT4_DECRYPT, page->index, page, page);
+	return ext4_page_crypto(page->mapping->host, EXT4_DECRYPT,
+				page->index, page, page, GFP_NOFS);
 }
 
 int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
@@ -402,11 +407,11 @@
 
 	BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE);
 
-	ctx = ext4_get_crypto_ctx(inode);
+	ctx = ext4_get_crypto_ctx(inode, GFP_NOFS);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
-	ciphertext_page = alloc_bounce_page(ctx);
+	ciphertext_page = alloc_bounce_page(ctx, GFP_NOWAIT);
 	if (IS_ERR(ciphertext_page)) {
 		err = PTR_ERR(ciphertext_page);
 		goto errout;
@@ -414,11 +419,12 @@
 
 	while (len--) {
 		err = ext4_page_crypto(inode, EXT4_ENCRYPT, lblk,
-				       ZERO_PAGE(0), ciphertext_page);
+				       ZERO_PAGE(0), ciphertext_page,
+				       GFP_NOFS);
 		if (err)
 			goto errout;
 
-		bio = bio_alloc(GFP_KERNEL, 1);
+		bio = bio_alloc(GFP_NOWAIT, 1);
 		if (!bio) {
 			err = -ENOMEM;
 			goto errout;
@@ -469,3 +475,61 @@
 		return size;
 	return 0;
 }
+
+/*
+ * Validate dentries for encrypted directories to make sure we aren't
+ * potentially caching stale data after a key has been added or
+ * removed.
+ */
+static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
+{
+	struct dentry *dir;
+	struct ext4_crypt_info *ci;
+	int dir_has_key, cached_with_key;
+
+	if (flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	dir = dget_parent(dentry);
+	if (!ext4_encrypted_inode(d_inode(dir))) {
+		dput(dir);
+		return 0;
+	}
+	ci = EXT4_I(d_inode(dir))->i_crypt_info;
+
+	/* this should eventually be an flag in d_flags */
+	cached_with_key = dentry->d_fsdata != NULL;
+	dir_has_key = (ci != NULL);
+	dput(dir);
+
+	/*
+	 * If the dentry was cached without the key, and it is a
+	 * negative dentry, it might be a valid name.  We can't check
+	 * if the key has since been made available due to locking
+	 * reasons, so we fail the validation so ext4_lookup() can do
+	 * this check.
+	 *
+	 * We also fail the validation if the dentry was created with
+	 * the key present, but we no longer have the key, or vice versa.
+	 */
+	if ((!cached_with_key && d_is_negative(dentry)) ||
+	    (!cached_with_key && dir_has_key) ||
+	    (cached_with_key && !dir_has_key)) {
+#if 0				/* Revalidation debug */
+		char buf[80];
+		char *cp = simple_dname(dentry, buf, sizeof(buf));
+
+		if (IS_ERR(cp))
+			cp = (char *) "???";
+		pr_err("revalidate: %s %p %d %d %d\n", cp, dentry->d_fsdata,
+		       cached_with_key, d_is_negative(dentry),
+		       dir_has_key);
+#endif
+		return 0;
+	}
+	return 1;
+}
+
+const struct dentry_operations ext4_encrypted_d_ops = {
+	.d_revalidate = ext4_d_revalidate,
+};
diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
index 2fbef8a..026716b 100644
--- a/fs/ext4/crypto_fname.c
+++ b/fs/ext4/crypto_fname.c
@@ -44,7 +44,8 @@
 
 bool ext4_valid_filenames_enc_mode(uint32_t mode)
 {
-	return (mode == EXT4_ENCRYPTION_MODE_AES_256_CTS);
+	return (mode == EXT4_ENCRYPTION_MODE_AES_256_CTS ||
+		mode == EXT4_ENCRYPTION_MODE_AES_256_HEH);
 }
 
 static unsigned max_name_len(struct inode *inode)
@@ -343,7 +344,7 @@
 		memcpy(buf+4, &hinfo->minor_hash, 4);
 	} else
 		memset(buf, 0, 8);
-	memcpy(buf + 8, iname->name + iname->len - 16, 16);
+	memcpy(buf + 8, iname->name + ((iname->len - 17) & ~15), 16);
 	oname->name[0] = '_';
 	ret = digest_encode(buf, 24, oname->name+1);
 	oname->len = ret + 1;
diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
index 9a16d1e..22096e3 100644
--- a/fs/ext4/crypto_key.c
+++ b/fs/ext4/crypto_key.c
@@ -29,16 +29,16 @@
 }
 
 /**
- * ext4_derive_key_aes() - Derive a key using AES-128-ECB
+ * ext4_derive_key_v1() - Derive a key using AES-128-ECB
  * @deriving_key: Encryption key used for derivation.
  * @source_key:   Source key to which to apply derivation.
  * @derived_key:  Derived key.
  *
- * Return: Zero on success; non-zero otherwise.
+ * Return: 0 on success, -errno on failure
  */
-static int ext4_derive_key_aes(char deriving_key[EXT4_AES_128_ECB_KEY_SIZE],
-			       char source_key[EXT4_AES_256_XTS_KEY_SIZE],
-			       char derived_key[EXT4_AES_256_XTS_KEY_SIZE])
+static int ext4_derive_key_v1(const char deriving_key[EXT4_AES_128_ECB_KEY_SIZE],
+			      const char source_key[EXT4_AES_256_XTS_KEY_SIZE],
+			      char derived_key[EXT4_AES_256_XTS_KEY_SIZE])
 {
 	int res = 0;
 	struct ablkcipher_request *req = NULL;
@@ -83,13 +83,96 @@
 	return res;
 }
 
+/**
+ * ext4_derive_key_v2() - Derive a key non-reversibly
+ * @nonce: the nonce associated with the file
+ * @master_key: the master key referenced by the file
+ * @derived_key: (output) the resulting derived key
+ *
+ * This function computes the following:
+ *	 derived_key[0:127]   = AES-256-ENCRYPT(master_key[0:255], nonce)
+ *	 derived_key[128:255] = AES-256-ENCRYPT(master_key[0:255], nonce ^ 0x01)
+ *	 derived_key[256:383] = AES-256-ENCRYPT(master_key[256:511], nonce)
+ *	 derived_key[384:511] = AES-256-ENCRYPT(master_key[256:511], nonce ^ 0x01)
+ *
+ * 'nonce ^ 0x01' denotes flipping the low order bit of the last byte.
+ *
+ * Unlike the v1 algorithm, the v2 algorithm is "non-reversible", meaning that
+ * compromising a derived key does not also compromise the master key.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ext4_derive_key_v2(const char nonce[EXT4_KEY_DERIVATION_NONCE_SIZE],
+			      const char master_key[EXT4_MAX_KEY_SIZE],
+			      char derived_key[EXT4_MAX_KEY_SIZE])
+{
+	const int noncelen = EXT4_KEY_DERIVATION_NONCE_SIZE;
+	struct crypto_cipher *tfm;
+	int err;
+	int i;
+
+	/*
+	 * Since we only use each transform for a small number of encryptions,
+	 * requesting just "aes" turns out to be significantly faster than
+	 * "ecb(aes)", by about a factor of two.
+	 */
+	tfm = crypto_alloc_cipher("aes", 0, 0);
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	BUILD_BUG_ON(4 * EXT4_KEY_DERIVATION_NONCE_SIZE != EXT4_MAX_KEY_SIZE);
+	BUILD_BUG_ON(2 * EXT4_AES_256_ECB_KEY_SIZE != EXT4_MAX_KEY_SIZE);
+	for (i = 0; i < 2; i++) {
+		memcpy(derived_key, nonce, noncelen);
+		memcpy(derived_key + noncelen, nonce, noncelen);
+		derived_key[2 * noncelen - 1] ^= 0x01;
+		err = crypto_cipher_setkey(tfm, master_key,
+					   EXT4_AES_256_ECB_KEY_SIZE);
+		if (err)
+			break;
+		crypto_cipher_encrypt_one(tfm, derived_key, derived_key);
+		crypto_cipher_encrypt_one(tfm, derived_key + noncelen,
+					  derived_key + noncelen);
+		master_key += EXT4_AES_256_ECB_KEY_SIZE;
+		derived_key += 2 * noncelen;
+	}
+	crypto_free_cipher(tfm);
+	return err;
+}
+
+/**
+ * ext4_derive_key() - Derive a per-file key from a nonce and master key
+ * @ctx: the encryption context associated with the file
+ * @master_key: the master key referenced by the file
+ * @derived_key: (output) the resulting derived key
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ext4_derive_key(const struct ext4_encryption_context *ctx,
+			   const char master_key[EXT4_MAX_KEY_SIZE],
+			   char derived_key[EXT4_MAX_KEY_SIZE])
+{
+	BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE != EXT4_KEY_DERIVATION_NONCE_SIZE);
+	BUILD_BUG_ON(EXT4_AES_256_XTS_KEY_SIZE != EXT4_MAX_KEY_SIZE);
+
+	/*
+	 * Although the key derivation algorithm is logically independent of the
+	 * choice of encryption modes, in this kernel it is bundled with HEH
+	 * encryption of filenames, which is another crypto improvement that
+	 * requires an on-disk format change and requires userspace to specify
+	 * different encryption policies.
+	 */
+	if (ctx->filenames_encryption_mode == EXT4_ENCRYPTION_MODE_AES_256_HEH)
+		return ext4_derive_key_v2(ctx->nonce, master_key, derived_key);
+	else
+		return ext4_derive_key_v1(ctx->nonce, master_key, derived_key);
+}
+
 void ext4_free_crypt_info(struct ext4_crypt_info *ci)
 {
 	if (!ci)
 		return;
 
-	if (ci->ci_keyring_key)
-		key_put(ci->ci_keyring_key);
 	crypto_free_ablkcipher(ci->ci_ctfm);
 	kmem_cache_free(ext4_crypt_info_cachep, ci);
 }
@@ -111,7 +194,7 @@
 	ext4_free_crypt_info(ci);
 }
 
-int _ext4_get_encryption_info(struct inode *inode)
+int ext4_get_encryption_info(struct inode *inode)
 {
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	struct ext4_crypt_info *crypt_info;
@@ -128,22 +211,15 @@
 	char mode;
 	int res;
 
+	if (ei->i_crypt_info)
+		return 0;
+
 	if (!ext4_read_workqueue) {
 		res = ext4_init_crypto();
 		if (res)
 			return res;
 	}
 
-retry:
-	crypt_info = ACCESS_ONCE(ei->i_crypt_info);
-	if (crypt_info) {
-		if (!crypt_info->ci_keyring_key ||
-		    key_validate(crypt_info->ci_keyring_key) == 0)
-			return 0;
-		ext4_free_encryption_info(inode, crypt_info);
-		goto retry;
-	}
-
 	res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
 				 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
 				 &ctx, sizeof(ctx));
@@ -166,7 +242,6 @@
 	crypt_info->ci_data_mode = ctx.contents_encryption_mode;
 	crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
 	crypt_info->ci_ctfm = NULL;
-	crypt_info->ci_keyring_key = NULL;
 	memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
 	       sizeof(crypt_info->ci_master_key));
 	if (S_ISREG(inode->i_mode))
@@ -182,6 +257,9 @@
 	case EXT4_ENCRYPTION_MODE_AES_256_CTS:
 		cipher_str = "cts(cbc(aes))";
 		break;
+	case EXT4_ENCRYPTION_MODE_AES_256_HEH:
+		cipher_str = "heh(aes)";
+		break;
 	default:
 		printk_once(KERN_WARNING
 			    "ext4: unsupported key mode %d (ino %u)\n",
@@ -206,7 +284,6 @@
 		keyring_key = NULL;
 		goto out;
 	}
-	crypt_info->ci_keyring_key = keyring_key;
 	if (keyring_key->type != &key_type_logon) {
 		printk_once(KERN_WARNING
 			    "ext4: key type must be logon\n");
@@ -231,8 +308,7 @@
 		up_read(&keyring_key->sem);
 		goto out;
 	}
-	res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
-				  raw_key);
+	res = ext4_derive_key(&ctx, master_key->raw, raw_key);
 	up_read(&keyring_key->sem);
 	if (res)
 		goto out;
@@ -253,16 +329,13 @@
 				       ext4_encryption_key_size(mode));
 	if (res)
 		goto out;
-	memzero_explicit(raw_key, sizeof(raw_key));
-	if (cmpxchg(&ei->i_crypt_info, NULL, crypt_info) != NULL) {
-		ext4_free_crypt_info(crypt_info);
-		goto retry;
-	}
-	return 0;
 
+	if (cmpxchg(&ei->i_crypt_info, NULL, crypt_info) == NULL)
+		crypt_info = NULL;
 out:
 	if (res == -ENOKEY)
 		res = 0;
+	key_put(keyring_key);
 	ext4_free_crypt_info(crypt_info);
 	memzero_explicit(raw_key, sizeof(raw_key));
 	return res;
diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
index ad05069..e4f4fc4 100644
--- a/fs/ext4/crypto_policy.c
+++ b/fs/ext4/crypto_policy.c
@@ -102,6 +102,9 @@
 int ext4_process_policy(const struct ext4_encryption_policy *policy,
 			struct inode *inode)
 {
+	if (!inode_owner_or_capable(inode))
+		return -EACCES;
+
 	if (policy->version != 0)
 		return -EINVAL;
 
@@ -145,20 +148,38 @@
 int ext4_is_child_context_consistent_with_parent(struct inode *parent,
 						 struct inode *child)
 {
-	struct ext4_crypt_info *parent_ci, *child_ci;
+	const struct ext4_crypt_info *parent_ci, *child_ci;
+	struct ext4_encryption_context parent_ctx, child_ctx;
 	int res;
 
-	if ((parent == NULL) || (child == NULL)) {
-		pr_err("parent %p child %p\n", parent, child);
-		WARN_ON(1);	/* Should never happen */
-		return 0;
-	}
-	/* no restrictions if the parent directory is not encrypted */
+	/* No restrictions on file types which are never encrypted */
+	if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) &&
+	    !S_ISLNK(child->i_mode))
+		return 1;
+
+	/* No restrictions if the parent directory is unencrypted */
 	if (!ext4_encrypted_inode(parent))
 		return 1;
-	/* if the child directory is not encrypted, this is always a problem */
+
+	/* Encrypted directories must not contain unencrypted files */
 	if (!ext4_encrypted_inode(child))
 		return 0;
+
+	/*
+	 * Both parent and child are encrypted, so verify they use the same
+	 * encryption policy.  Compare the fscrypt_info structs if the keys are
+	 * available, otherwise retrieve and compare the fscrypt_contexts.
+	 *
+	 * Note that the fscrypt_context retrieval will be required frequently
+	 * when accessing an encrypted directory tree without the key.
+	 * Performance-wise this is not a big deal because we already don't
+	 * really optimize for file access without the key (to the extent that
+	 * such access is even possible), given that any attempted access
+	 * already causes a fscrypt_context retrieval and keyring search.
+	 *
+	 * In any case, if an unexpected error occurs, fall back to "forbidden".
+	 */
+
 	res = ext4_get_encryption_info(parent);
 	if (res)
 		return 0;
@@ -167,17 +188,35 @@
 		return 0;
 	parent_ci = EXT4_I(parent)->i_crypt_info;
 	child_ci = EXT4_I(child)->i_crypt_info;
-	if (!parent_ci && !child_ci)
-		return 1;
-	if (!parent_ci || !child_ci)
+	if (parent_ci && child_ci) {
+		return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key,
+			      EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
+			(parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
+			(parent_ci->ci_filename_mode ==
+			 child_ci->ci_filename_mode) &&
+			(parent_ci->ci_flags == child_ci->ci_flags);
+	}
+
+	res = ext4_xattr_get(parent, EXT4_XATTR_INDEX_ENCRYPTION,
+			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
+			     &parent_ctx, sizeof(parent_ctx));
+	if (res != sizeof(parent_ctx))
 		return 0;
 
-	return (memcmp(parent_ci->ci_master_key,
-		       child_ci->ci_master_key,
-		       EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
-		(parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
-		(parent_ci->ci_filename_mode == child_ci->ci_filename_mode) &&
-		(parent_ci->ci_flags == child_ci->ci_flags));
+	res = ext4_xattr_get(child, EXT4_XATTR_INDEX_ENCRYPTION,
+			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
+			     &child_ctx, sizeof(child_ctx));
+	if (res != sizeof(child_ctx))
+		return 0;
+
+	return memcmp(parent_ctx.master_key_descriptor,
+		      child_ctx.master_key_descriptor,
+		      EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
+		(parent_ctx.contents_encryption_mode ==
+		 child_ctx.contents_encryption_mode) &&
+		(parent_ctx.filenames_encryption_mode ==
+		 child_ctx.filenames_encryption_mode) &&
+		(parent_ctx.flags == child_ctx.flags);
 }
 
 /**
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 1d1bca7..6d17f31 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -111,6 +111,12 @@
 	int dir_has_error = 0;
 	struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
 
+	if (ext4_encrypted_inode(inode)) {
+		err = ext4_get_encryption_info(inode);
+		if (err && err != -ENOKEY)
+			return err;
+	}
+
 	if (is_dx_dir(inode)) {
 		err = ext4_dx_readdir(file, ctx);
 		if (err != ERR_BAD_DX_DIR) {
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index b7e921d..6edacb8 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -221,6 +221,7 @@
 #define	EXT4_MAX_BLOCK_SIZE		65536
 #define EXT4_MIN_BLOCK_LOG_SIZE		10
 #define EXT4_MAX_BLOCK_LOG_SIZE		16
+#define EXT4_MAX_CLUSTER_LOG_SIZE	30
 #ifdef __KERNEL__
 # define EXT4_BLOCK_SIZE(s)		((s)->s_blocksize)
 #else
@@ -588,6 +589,7 @@
 #define EXT4_ENCRYPTION_MODE_AES_256_GCM	2
 #define EXT4_ENCRYPTION_MODE_AES_256_CBC	3
 #define EXT4_ENCRYPTION_MODE_AES_256_CTS	4
+#define EXT4_ENCRYPTION_MODE_AES_256_HEH	126
 
 #include "ext4_crypto.h"
 
@@ -1440,7 +1442,7 @@
 	struct list_head s_es_list;	/* List of inodes with reclaimable extents */
 	long s_es_nr_inode;
 	struct ext4_es_stats s_es_stats;
-	struct mb_cache *s_mb_cache;
+	struct mb2_cache *s_mb_cache;
 	spinlock_t s_es_lock ____cacheline_aligned_in_smp;
 
 	/* Ratelimit ext4 messages. */
@@ -2260,13 +2262,16 @@
 bool ext4_valid_contents_enc_mode(uint32_t mode);
 uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size);
 extern struct workqueue_struct *ext4_read_workqueue;
-struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode);
+struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode,
+					    gfp_t gfp_flags);
 void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx);
 void ext4_restore_control_page(struct page *data_page);
 struct page *ext4_encrypt(struct inode *inode,
-			  struct page *plaintext_page);
+			  struct page *plaintext_page,
+			  gfp_t gfp_flags);
 int ext4_decrypt(struct page *page);
 int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex);
+extern const struct dentry_operations ext4_encrypted_d_ops;
 
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
 int ext4_init_crypto(void);
@@ -2329,23 +2334,11 @@
 /* crypto_key.c */
 void ext4_free_crypt_info(struct ext4_crypt_info *ci);
 void ext4_free_encryption_info(struct inode *inode, struct ext4_crypt_info *ci);
-int _ext4_get_encryption_info(struct inode *inode);
 
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
 int ext4_has_encryption_key(struct inode *inode);
 
-static inline int ext4_get_encryption_info(struct inode *inode)
-{
-	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
-
-	if (!ci ||
-	    (ci->ci_keyring_key &&
-	     (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
-					   (1 << KEY_FLAG_REVOKED) |
-					   (1 << KEY_FLAG_DEAD)))))
-		return _ext4_get_encryption_info(inode);
-	return 0;
-}
+int ext4_get_encryption_info(struct inode *inode);
 
 static inline struct ext4_crypt_info *ext4_encryption_info(struct inode *inode)
 {
@@ -2464,7 +2457,8 @@
 		ext4_group_t i, struct ext4_group_desc *desc);
 extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
 				ext4_fsblk_t block, unsigned long count);
-extern int ext4_trim_fs(struct super_block *, struct fstrim_range *);
+extern int ext4_trim_fs(struct super_block *, struct fstrim_range *,
+				unsigned long blkdev_flags);
 
 /* inode.c */
 int ext4_inode_is_fast_symlink(struct inode *inode);
diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
index ac7d4e8..e52637d 100644
--- a/fs/ext4/ext4_crypto.h
+++ b/fs/ext4/ext4_crypto.h
@@ -58,8 +58,10 @@
 #define EXT4_XTS_TWEAK_SIZE 16
 #define EXT4_AES_128_ECB_KEY_SIZE 16
 #define EXT4_AES_256_GCM_KEY_SIZE 32
+#define EXT4_AES_256_ECB_KEY_SIZE 32
 #define EXT4_AES_256_CBC_KEY_SIZE 32
 #define EXT4_AES_256_CTS_KEY_SIZE 32
+#define EXT4_AES_256_HEH_KEY_SIZE 32
 #define EXT4_AES_256_XTS_KEY_SIZE 64
 #define EXT4_MAX_KEY_SIZE 64
 
@@ -78,7 +80,6 @@
 	char		ci_filename_mode;
 	char		ci_flags;
 	struct crypto_ablkcipher *ci_ctfm;
-	struct key	*ci_keyring_key;
 	char		ci_master_key[EXT4_KEY_DESCRIPTOR_SIZE];
 };
 
@@ -121,6 +122,8 @@
 		return EXT4_AES_256_CBC_KEY_SIZE;
 	case EXT4_ENCRYPTION_MODE_AES_256_CTS:
 		return EXT4_AES_256_CTS_KEY_SIZE;
+	case EXT4_ENCRYPTION_MODE_AES_256_HEH:
+		return EXT4_AES_256_HEH_KEY_SIZE;
 	default:
 		BUG();
 	}
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 5f58462..f817ed5 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -395,17 +395,19 @@
 		return EXT4_INODE_WRITEBACK_DATA_MODE;	/* writeback */
 	/* We do not support data journalling with delayed allocation */
 	if (!S_ISREG(inode->i_mode) ||
-	    test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+	    test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
+	    (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
+	    !test_opt(inode->i_sb, DELALLOC))) {
+		/* We do not support data journalling for encrypted data */
+		if (S_ISREG(inode->i_mode) && ext4_encrypted_inode(inode))
+			return EXT4_INODE_ORDERED_DATA_MODE;  /* ordered */
 		return EXT4_INODE_JOURNAL_DATA_MODE;	/* journal data */
-	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
-	    !test_opt(inode->i_sb, DELALLOC))
-		return EXT4_INODE_JOURNAL_DATA_MODE;	/* journal data */
+	}
 	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
 		return EXT4_INODE_ORDERED_DATA_MODE;	/* ordered */
 	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
 		return EXT4_INODE_WRITEBACK_DATA_MODE;	/* writeback */
-	else
-		BUG();
+	BUG();
 }
 
 static inline int ext4_should_journal_data(struct inode *inode)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 3578b25..61d5bfc 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -376,9 +376,13 @@
 	ext4_fsblk_t block = ext4_ext_pblock(ext);
 	int len = ext4_ext_get_actual_len(ext);
 	ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
-	ext4_lblk_t last = lblock + len - 1;
 
-	if (len == 0 || lblock > last)
+	/*
+	 * We allow neither:
+	 *  - zero length
+	 *  - overflow/wrap-around
+	 */
+	if (lblock + len <= lblock)
 		return 0;
 	return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
 }
@@ -469,6 +473,10 @@
 		error_msg = "invalid extent entries";
 		goto corrupted;
 	}
+	if (unlikely(depth > 32)) {
+		error_msg = "too large eh_depth";
+		goto corrupted;
+	}
 	/* Verify checksum on non-root extent tree nodes */
 	if (ext_depth(inode) != depth &&
 	    !ext4_extent_block_csum_verify(inode, eh)) {
@@ -4894,6 +4902,8 @@
 
 	/* Zero out partial block at the edges of the range */
 	ret = ext4_zero_partial_blocks(handle, inode, offset, len);
+	if (ret >= 0)
+		ext4_update_inode_fsync_trans(handle, inode, 1);
 
 	if (file->f_flags & O_SYNC)
 		ext4_handle_sync(handle);
@@ -5354,7 +5364,8 @@
 	ext4_lblk_t stop, *iterator, ex_start, ex_end;
 
 	/* Let path point to the last extent */
-	path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0);
+	path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL,
+				EXT4_EX_NOCACHE);
 	if (IS_ERR(path))
 		return PTR_ERR(path);
 
@@ -5363,15 +5374,15 @@
 	if (!extent)
 		goto out;
 
-	stop = le32_to_cpu(extent->ee_block) +
-			ext4_ext_get_actual_len(extent);
+	stop = le32_to_cpu(extent->ee_block);
 
        /*
 	 * In case of left shift, Don't start shifting extents until we make
 	 * sure the hole is big enough to accommodate the shift.
 	*/
 	if (SHIFT == SHIFT_LEFT) {
-		path = ext4_find_extent(inode, start - 1, &path, 0);
+		path = ext4_find_extent(inode, start - 1, &path,
+					EXT4_EX_NOCACHE);
 		if (IS_ERR(path))
 			return PTR_ERR(path);
 		depth = path->p_depth;
@@ -5403,9 +5414,14 @@
 	else
 		iterator = &stop;
 
-	/* Its safe to start updating extents */
-	while (start < stop) {
-		path = ext4_find_extent(inode, *iterator, &path, 0);
+	/*
+	 * Its safe to start updating extents.  Start and stop are unsigned, so
+	 * in case of right shift if extent with 0 block is reached, iterator
+	 * becomes NULL to indicate the end of the loop.
+	 */
+	while (iterator && start <= stop) {
+		path = ext4_find_extent(inode, *iterator, &path,
+					EXT4_EX_NOCACHE);
 		if (IS_ERR(path))
 			return PTR_ERR(path);
 		depth = path->p_depth;
@@ -5432,8 +5448,11 @@
 					ext4_ext_get_actual_len(extent);
 		} else {
 			extent = EXT_FIRST_EXTENT(path[depth].p_hdr);
-			*iterator =  le32_to_cpu(extent->ee_block) > 0 ?
-				le32_to_cpu(extent->ee_block) - 1 : 0;
+			if (le32_to_cpu(extent->ee_block) > 0)
+				*iterator = le32_to_cpu(extent->ee_block) - 1;
+			else
+				/* Beginning is reached, end of the loop */
+				iterator = NULL;
 			/* Update path extent in case we need to stop */
 			while (le32_to_cpu(extent->ee_block) < start)
 				extent++;
@@ -5580,6 +5599,7 @@
 		ext4_handle_sync(handle);
 	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
 	ext4_mark_inode_dirty(handle, inode);
+	ext4_update_inode_fsync_trans(handle, inode, 1);
 
 out_stop:
 	ext4_journal_stop(handle);
@@ -5730,6 +5750,9 @@
 			up_write(&EXT4_I(inode)->i_data_sem);
 			goto out_stop;
 		}
+	} else {
+		ext4_ext_drop_refs(path);
+		kfree(path);
 	}
 
 	ret = ext4_es_remove_extent(inode, offset_lblk,
@@ -5750,6 +5773,8 @@
 	up_write(&EXT4_I(inode)->i_data_sem);
 	if (IS_SYNC(inode))
 		ext4_handle_sync(handle);
+	if (ret >= 0)
+		ext4_update_inode_fsync_trans(handle, inode, 1);
 
 out_stop:
 	ext4_journal_stop(handle);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 0d24ebc..8772bfc 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -463,47 +463,27 @@
 		num = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
 		nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
 					  (pgoff_t)num);
-		if (nr_pages == 0) {
-			if (whence == SEEK_DATA)
-				break;
-
-			BUG_ON(whence != SEEK_HOLE);
-			/*
-			 * If this is the first time to go into the loop and
-			 * offset is not beyond the end offset, it will be a
-			 * hole at this offset
-			 */
-			if (lastoff == startoff || lastoff < endoff)
-				found = 1;
+		if (nr_pages == 0)
 			break;
-		}
-
-		/*
-		 * If this is the first time to go into the loop and
-		 * offset is smaller than the first page offset, it will be a
-		 * hole at this offset.
-		 */
-		if (lastoff == startoff && whence == SEEK_HOLE &&
-		    lastoff < page_offset(pvec.pages[0])) {
-			found = 1;
-			break;
-		}
 
 		for (i = 0; i < nr_pages; i++) {
 			struct page *page = pvec.pages[i];
 			struct buffer_head *bh, *head;
 
 			/*
-			 * If the current offset is not beyond the end of given
-			 * range, it will be a hole.
+			 * If current offset is smaller than the page offset,
+			 * there is a hole at this offset.
 			 */
-			if (lastoff < endoff && whence == SEEK_HOLE &&
-			    page->index > end) {
+			if (whence == SEEK_HOLE && lastoff < endoff &&
+			    lastoff < page_offset(pvec.pages[i])) {
 				found = 1;
 				*offset = lastoff;
 				goto out;
 			}
 
+			if (page->index > end)
+				goto out;
+
 			lock_page(page);
 
 			if (unlikely(page->mapping != inode->i_mapping)) {
@@ -543,20 +523,18 @@
 			unlock_page(page);
 		}
 
-		/*
-		 * The no. of pages is less than our desired, that would be a
-		 * hole in there.
-		 */
-		if (nr_pages < num && whence == SEEK_HOLE) {
-			found = 1;
-			*offset = lastoff;
+		/* The no. of pages is less than our desired, we are done. */
+		if (nr_pages < num)
 			break;
-		}
 
 		index = pvec.pages[i - 1]->index + 1;
 		pagevec_release(&pvec);
 	} while (index <= end);
 
+	if (whence == SEEK_HOLE && lastoff < endoff) {
+		found = 1;
+		*offset = lastoff;
+	}
 out:
 	pagevec_release(&pvec);
 	return found;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 53f2b98..5388207 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1143,25 +1143,20 @@
 	unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count);
 	ext4_group_t block_group;
 	int bit;
-	struct buffer_head *bitmap_bh;
+	struct buffer_head *bitmap_bh = NULL;
 	struct inode *inode = NULL;
-	long err = -EIO;
+	int err = -EFSCORRUPTED;
 
-	/* Error cases - e2fsck has already cleaned up for us */
-	if (ino > max_ino) {
-		ext4_warning(sb, "bad orphan ino %lu!  e2fsck was run?", ino);
-		err = -EFSCORRUPTED;
-		goto error;
-	}
+	if (ino < EXT4_FIRST_INO(sb) || ino > max_ino)
+		goto bad_orphan;
 
 	block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
 	bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
 	bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
 	if (IS_ERR(bitmap_bh)) {
-		err = PTR_ERR(bitmap_bh);
-		ext4_warning(sb, "inode bitmap error %ld for orphan %lu",
-			     ino, err);
-		goto error;
+		ext4_error(sb, "inode bitmap error %ld for orphan %lu",
+			   ino, PTR_ERR(bitmap_bh));
+		return (struct inode *) bitmap_bh;
 	}
 
 	/* Having the inode bit set should be a 100% indicator that this
@@ -1172,15 +1167,21 @@
 		goto bad_orphan;
 
 	inode = ext4_iget(sb, ino);
-	if (IS_ERR(inode))
-		goto iget_failed;
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
+			   ino, err);
+		return inode;
+	}
 
 	/*
-	 * If the orphans has i_nlinks > 0 then it should be able to be
-	 * truncated, otherwise it won't be removed from the orphan list
-	 * during processing and an infinite loop will result.
+	 * If the orphans has i_nlinks > 0 then it should be able to
+	 * be truncated, otherwise it won't be removed from the orphan
+	 * list during processing and an infinite loop will result.
+	 * Similarly, it must not be a bad inode.
 	 */
-	if (inode->i_nlink && !ext4_can_truncate(inode))
+	if ((inode->i_nlink && !ext4_can_truncate(inode)) ||
+	    is_bad_inode(inode))
 		goto bad_orphan;
 
 	if (NEXT_ORPHAN(inode) > max_ino)
@@ -1188,29 +1189,25 @@
 	brelse(bitmap_bh);
 	return inode;
 
-iget_failed:
-	err = PTR_ERR(inode);
-	inode = NULL;
 bad_orphan:
-	ext4_warning(sb, "bad orphan inode %lu!  e2fsck was run?", ino);
-	printk(KERN_WARNING "ext4_test_bit(bit=%d, block=%llu) = %d\n",
-	       bit, (unsigned long long)bitmap_bh->b_blocknr,
-	       ext4_test_bit(bit, bitmap_bh->b_data));
-	printk(KERN_WARNING "inode=%p\n", inode);
+	ext4_error(sb, "bad orphan inode %lu", ino);
+	if (bitmap_bh)
+		printk(KERN_ERR "ext4_test_bit(bit=%d, block=%llu) = %d\n",
+		       bit, (unsigned long long)bitmap_bh->b_blocknr,
+		       ext4_test_bit(bit, bitmap_bh->b_data));
 	if (inode) {
-		printk(KERN_WARNING "is_bad_inode(inode)=%d\n",
+		printk(KERN_ERR "is_bad_inode(inode)=%d\n",
 		       is_bad_inode(inode));
-		printk(KERN_WARNING "NEXT_ORPHAN(inode)=%u\n",
+		printk(KERN_ERR "NEXT_ORPHAN(inode)=%u\n",
 		       NEXT_ORPHAN(inode));
-		printk(KERN_WARNING "max_ino=%lu\n", max_ino);
-		printk(KERN_WARNING "i_nlink=%u\n", inode->i_nlink);
+		printk(KERN_ERR "max_ino=%lu\n", max_ino);
+		printk(KERN_ERR "i_nlink=%u\n", inode->i_nlink);
 		/* Avoid freeing blocks if we got a bad deleted inode */
 		if (inode->i_nlink == 0)
 			inode->i_blocks = 0;
 		iput(inode);
 	}
 	brelse(bitmap_bh);
-error:
 	return ERR_PTR(err);
 }
 
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index d884989..bc7c082 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -18,6 +18,7 @@
 #include "ext4.h"
 #include "xattr.h"
 #include "truncate.h"
+#include <trace/events/android_fs.h>
 
 #define EXT4_XATTR_SYSTEM_DATA	"data"
 #define EXT4_MIN_INLINE_DATA_SIZE	((sizeof(__le32) * EXT4_N_BLOCKS))
@@ -336,8 +337,10 @@
 
 	len -= EXT4_MIN_INLINE_DATA_SIZE;
 	value = kzalloc(len, GFP_NOFS);
-	if (!value)
+	if (!value) {
+		error = -ENOMEM;
 		goto out;
+	}
 
 	error = ext4_xattr_ibody_get(inode, i.name_index, i.name,
 				     value, len);
@@ -500,6 +503,17 @@
 		return -EAGAIN;
 	}
 
+	if (trace_android_fs_dataread_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_dataread_start(inode, page_offset(page),
+						PAGE_SIZE, current->pid,
+						path, current->comm);
+	}
+
 	/*
 	 * Current inline data can only exist in the 1st page,
 	 * So for all the other pages, just set them uptodate.
@@ -511,6 +525,8 @@
 		SetPageUptodate(page);
 	}
 
+	trace_android_fs_dataread_end(inode, page_offset(page), PAGE_SIZE);
+
 	up_read(&EXT4_I(inode)->xattr_sem);
 
 	unlock_page(page);
@@ -931,8 +947,15 @@
 				  struct page *page)
 {
 	int i_size_changed = 0;
+	int ret;
 
-	copied = ext4_write_inline_data_end(inode, pos, len, copied, page);
+	ret = ext4_write_inline_data_end(inode, pos, len, copied, page);
+	if (ret < 0) {
+		unlock_page(page);
+		put_page(page);
+		return ret;
+	}
+	copied = ret;
 
 	/*
 	 * No need to use i_size_read() here, the i_size
@@ -1149,10 +1172,9 @@
 	set_buffer_uptodate(dir_block);
 	err = ext4_handle_dirty_dirent_node(handle, inode, dir_block);
 	if (err)
-		goto out;
+		return err;
 	set_buffer_verified(dir_block);
-out:
-	return err;
+	return ext4_mark_inode_dirty(handle, inode);
 }
 
 static int ext4_convert_inline_data_nolock(handle_t *handle,
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e31d762..2ac7192 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -44,6 +44,7 @@
 #include "truncate.h"
 
 #include <trace/events/ext4.h>
+#include <trace/events/android_fs.h>
 
 #define MPAGE_DA_EXTENT_TAIL 0x01
 
@@ -51,26 +52,31 @@
 			      struct ext4_inode_info *ei)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-	__u16 csum_lo;
-	__u16 csum_hi = 0;
 	__u32 csum;
+	__u16 dummy_csum = 0;
+	int offset = offsetof(struct ext4_inode, i_checksum_lo);
+	unsigned int csum_size = sizeof(dummy_csum);
 
-	csum_lo = le16_to_cpu(raw->i_checksum_lo);
-	raw->i_checksum_lo = 0;
-	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
-	    EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) {
-		csum_hi = le16_to_cpu(raw->i_checksum_hi);
-		raw->i_checksum_hi = 0;
+	csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)raw, offset);
+	csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, csum_size);
+	offset += csum_size;
+	csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset,
+			   EXT4_GOOD_OLD_INODE_SIZE - offset);
+
+	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
+		offset = offsetof(struct ext4_inode, i_checksum_hi);
+		csum = ext4_chksum(sbi, csum, (__u8 *)raw +
+				   EXT4_GOOD_OLD_INODE_SIZE,
+				   offset - EXT4_GOOD_OLD_INODE_SIZE);
+		if (EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) {
+			csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum,
+					   csum_size);
+			offset += csum_size;
+		}
+		csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset,
+				   EXT4_INODE_SIZE(inode->i_sb) - offset);
 	}
 
-	csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)raw,
-			   EXT4_INODE_SIZE(inode->i_sb));
-
-	raw->i_checksum_lo = cpu_to_le16(csum_lo);
-	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
-	    EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi))
-		raw->i_checksum_hi = cpu_to_le16(csum_hi);
-
 	return csum;
 }
 
@@ -205,9 +211,9 @@
 		 * Note that directories do not have this problem because they
 		 * don't use page cache.
 		 */
-		if (ext4_should_journal_data(inode) &&
-		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode)) &&
-		    inode->i_ino != EXT4_JOURNAL_INO) {
+		if (inode->i_ino != EXT4_JOURNAL_INO &&
+		    ext4_should_journal_data(inode) &&
+		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
 			journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
 			tid_t commit_tid = EXT4_I(inode)->i_datasync_tid;
 
@@ -653,6 +659,20 @@
 		ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
+
+		/*
+		 * Inodes with freshly allocated blocks where contents will be
+		 * visible after transaction commit must be on transaction's
+		 * ordered data list.
+		 */
+		if (map->m_flags & EXT4_MAP_NEW &&
+		    !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+		    !IS_NOQUOTA(inode) &&
+		    ext4_should_order_data(inode)) {
+			ret = ext4_jbd2_file_inode(handle, inode);
+			if (ret)
+				return ret;
+		}
 	}
 	return retval;
 }
@@ -1010,6 +1030,16 @@
 	pgoff_t index;
 	unsigned from, to;
 
+	if (trace_android_fs_datawrite_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_datawrite_start(inode, pos, len,
+						 current->pid, path,
+						 current->comm);
+	}
 	trace_ext4_write_begin(inode, pos, len, flags);
 	/*
 	 * Reserve one block more for addition to orphan list in case
@@ -1146,21 +1176,16 @@
 	int ret = 0, ret2;
 	int i_size_changed = 0;
 
+	trace_android_fs_datawrite_end(inode, pos, len);
 	trace_ext4_write_end(inode, pos, len, copied);
-	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-		ret = ext4_jbd2_file_inode(handle, inode);
-		if (ret) {
-			unlock_page(page);
-			page_cache_release(page);
-			goto errout;
-		}
-	}
-
 	if (ext4_has_inline_data(inode)) {
 		ret = ext4_write_inline_data_end(inode, pos, len,
 						 copied, page);
-		if (ret < 0)
+		if (ret < 0) {
+			unlock_page(page);
+			put_page(page);
 			goto errout;
+		}
 		copied = ret;
 	} else
 		copied = block_write_end(file, mapping, pos,
@@ -1214,7 +1239,9 @@
  * set the buffer to be dirty, since in data=journalled mode we need
  * to call ext4_handle_dirty_metadata() instead.
  */
-static void zero_new_buffers(struct page *page, unsigned from, unsigned to)
+static void ext4_journalled_zero_new_buffers(handle_t *handle,
+					    struct page *page,
+					    unsigned from, unsigned to)
 {
 	unsigned int block_start = 0, block_end;
 	struct buffer_head *head, *bh;
@@ -1231,7 +1258,7 @@
 					size = min(to, block_end) - start;
 
 					zero_user(page, start, size);
-					set_buffer_uptodate(bh);
+					write_end_fn(handle, bh);
 				}
 				clear_buffer_new(bh);
 			}
@@ -1254,24 +1281,32 @@
 	unsigned from, to;
 	int size_changed = 0;
 
+	trace_android_fs_datawrite_end(inode, pos, len);
 	trace_ext4_journalled_write_end(inode, pos, len, copied);
 	from = pos & (PAGE_CACHE_SIZE - 1);
 	to = from + len;
 
 	BUG_ON(!ext4_handle_valid(handle));
 
-	if (ext4_has_inline_data(inode))
-		copied = ext4_write_inline_data_end(inode, pos, len,
-						    copied, page);
-	else {
-		if (copied < len) {
-			if (!PageUptodate(page))
-				copied = 0;
-			zero_new_buffers(page, from+copied, to);
+	if (ext4_has_inline_data(inode)) {
+		ret = ext4_write_inline_data_end(inode, pos, len,
+						 copied, page);
+		if (ret < 0) {
+			unlock_page(page);
+			put_page(page);
+			goto errout;
 		}
-
+		copied = ret;
+	} else if (unlikely(copied < len) && !PageUptodate(page)) {
+		copied = 0;
+		ext4_journalled_zero_new_buffers(handle, page, from, to);
+	} else {
+		if (unlikely(copied < len))
+			ext4_journalled_zero_new_buffers(handle, page,
+							 from + copied, to);
 		ret = ext4_walk_page_buffers(handle, page_buffers(page), from,
-					     to, &partial, write_end_fn);
+					     from + copied, &partial,
+					     write_end_fn);
 		if (!partial)
 			SetPageUptodate(page);
 	}
@@ -1297,6 +1332,7 @@
 		 */
 		ext4_orphan_add(handle, inode);
 
+errout:
 	ret2 = ext4_journal_stop(handle);
 	if (!ret)
 		ret = ret2;
@@ -2026,7 +2062,7 @@
 {
 	struct inode *inode = mpd->inode;
 	int err;
-	ext4_lblk_t blocks = (i_size_read(inode) + (1 << inode->i_blkbits) - 1)
+	ext4_lblk_t blocks = (i_size_read(inode) + i_blocksize(inode) - 1)
 							>> inode->i_blkbits;
 
 	do {
@@ -2589,13 +2625,36 @@
 				done = true;
 			}
 		}
-		ext4_journal_stop(handle);
+		/*
+		 * Caution: If the handle is synchronous,
+		 * ext4_journal_stop() can wait for transaction commit
+		 * to finish which may depend on writeback of pages to
+		 * complete or on page lock to be released.  In that
+		 * case, we have to wait until after after we have
+		 * submitted all the IO, released page locks we hold,
+		 * and dropped io_end reference (for extent conversion
+		 * to be able to complete) before stopping the handle.
+		 */
+		if (!ext4_handle_valid(handle) || handle->h_sync == 0) {
+			ext4_journal_stop(handle);
+			handle = NULL;
+		}
 		/* Submit prepared bio */
 		ext4_io_submit(&mpd.io_submit);
 		/* Unlock pages we didn't use */
 		mpage_release_unused_pages(&mpd, give_up_on_write);
-		/* Drop our io_end reference we got from init */
-		ext4_put_io_end(mpd.io_submit.io_end);
+		/*
+		 * Drop our io_end reference we got from init. We have
+		 * to be careful and use deferred io_end finishing if
+		 * we are still holding the transaction as we can
+		 * release the last reference to io_end which may end
+		 * up doing unwritten extent conversion.
+		 */
+		if (handle) {
+			ext4_put_io_end_defer(mpd.io_submit.io_end);
+			ext4_journal_stop(handle);
+		} else
+			ext4_put_io_end(mpd.io_submit.io_end);
 
 		if (ret == -ENOSPC && sbi->s_journal) {
 			/*
@@ -2698,6 +2757,16 @@
 					len, flags, pagep, fsdata);
 	}
 	*fsdata = (void *)0;
+	if (trace_android_fs_datawrite_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_datawrite_start(inode, pos, len,
+						 current->pid,
+						 path, current->comm);
+	}
 	trace_ext4_da_write_begin(inode, pos, len, flags);
 
 	if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
@@ -2816,6 +2885,7 @@
 		return ext4_write_end(file, mapping, pos,
 				      len, copied, page, fsdata);
 
+	trace_android_fs_datawrite_end(inode, pos, len);
 	trace_ext4_da_write_end(inode, pos, len, copied);
 	start = pos & (PAGE_CACHE_SIZE - 1);
 	end = start + copied - 1;
@@ -3304,12 +3374,42 @@
 	if (ext4_has_inline_data(inode))
 		return 0;
 
+	if (trace_android_fs_dataread_start_enabled() &&
+	    (iov_iter_rw(iter) == READ)) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_dataread_start(inode, offset, count,
+						current->pid, path,
+						current->comm);
+	}
+	if (trace_android_fs_datawrite_start_enabled() &&
+	    (iov_iter_rw(iter) == WRITE)) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_datawrite_start(inode, offset, count,
+						 current->pid, path,
+						 current->comm);
+	}
 	trace_ext4_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
 		ret = ext4_ext_direct_IO(iocb, iter, offset);
 	else
 		ret = ext4_ind_direct_IO(iocb, iter, offset);
 	trace_ext4_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), ret);
+
+	if (trace_android_fs_dataread_start_enabled() &&
+	    (iov_iter_rw(iter) == READ))
+		trace_android_fs_dataread_end(inode, offset, count);
+	if (trace_android_fs_datawrite_start_enabled() &&
+	    (iov_iter_rw(iter) == WRITE))
+		trace_android_fs_datawrite_end(inode, offset, count);
+
 	return ret;
 }
 
@@ -3531,6 +3631,10 @@
 	unsigned blocksize;
 	struct inode *inode = mapping->host;
 
+	/* If we are processing an encrypted inode during orphan list handling */
+	if (ext4_encrypted_inode(inode) && !ext4_has_encryption_key(inode))
+		return 0;
+
 	blocksize = inode->i_sb->s_blocksize;
 	length = blocksize - (offset & (blocksize - 1));
 
@@ -3616,7 +3720,7 @@
 }
 
 /*
- * ext4_punch_hole: punches a hole in a file by releaseing the blocks
+ * ext4_punch_hole: punches a hole in a file by releasing the blocks
  * associated with the given offset and length
  *
  * @inode:  File inode
@@ -3645,7 +3749,7 @@
 	 * Write out all dirty pages to avoid race conditions
 	 * Then release them.
 	 */
-	if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+	if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
 		ret = filemap_write_and_wait_range(mapping, offset,
 						   offset + length - 1);
 		if (ret)
@@ -3748,6 +3852,8 @@
 
 	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
 	ext4_mark_inode_dirty(handle, inode);
+	if (ret >= 0)
+		ext4_update_inode_fsync_trans(handle, inode, 1);
 out_stop:
 	ext4_journal_stop(handle);
 out_dio:
@@ -4146,6 +4252,7 @@
 	struct inode *inode;
 	journal_t *journal = EXT4_SB(sb)->s_journal;
 	long ret;
+	loff_t size;
 	int block;
 	uid_t i_uid;
 	gid_t i_gid;
@@ -4237,6 +4344,11 @@
 		ei->i_file_acl |=
 			((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
 	inode->i_size = ext4_isize(raw_inode);
+	if ((size = i_size_read(inode)) < 0) {
+		EXT4_ERROR_INODE(inode, "bad i_size value: %lld", size);
+		ret = -EFSCORRUPTED;
+		goto bad_inode;
+	}
 	ei->i_disksize = inode->i_size;
 #ifdef CONFIG_QUOTA
 	ei->i_reserved_quota = 0;
@@ -4520,14 +4632,14 @@
  * Fix up interoperability with old kernels. Otherwise, old inodes get
  * re-used with the upper 16 bits of the uid/gid intact
  */
-		if (!ei->i_dtime) {
+		if (ei->i_dtime && list_empty(&ei->i_orphan)) {
+			raw_inode->i_uid_high = 0;
+			raw_inode->i_gid_high = 0;
+		} else {
 			raw_inode->i_uid_high =
 				cpu_to_le16(high_16_bits(i_uid));
 			raw_inode->i_gid_high =
 				cpu_to_le16(high_16_bits(i_gid));
-		} else {
-			raw_inode->i_uid_high = 0;
-			raw_inode->i_gid_high = 0;
 		}
 	} else {
 		raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(i_uid));
@@ -5111,8 +5223,9 @@
 	/* No extended attributes present */
 	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
 	    header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
-		memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0,
-			new_extra_isize);
+		memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE +
+		       EXT4_I(inode)->i_extra_isize, 0,
+		       new_extra_isize - EXT4_I(inode)->i_extra_isize);
 		EXT4_I(inode)->i_extra_isize = new_extra_isize;
 		return 0;
 	}
@@ -5163,8 +5276,6 @@
 						      sbi->s_want_extra_isize,
 						      iloc, handle);
 			if (ret) {
-				ext4_set_inode_state(inode,
-						     EXT4_STATE_NO_EXPAND);
 				if (mnt_count !=
 					le16_to_cpu(sbi->s_es->s_mnt_count)) {
 					ext4_warning(inode->i_sb,
@@ -5344,6 +5455,11 @@
 	file_update_time(vma->vm_file);
 
 	down_read(&EXT4_I(inode)->i_mmap_sem);
+
+	ret = ext4_convert_inline_data(inode);
+	if (ret)
+		goto out_ret;
+
 	/* Delalloc case is easy... */
 	if (test_opt(inode->i_sb, DELALLOC) &&
 	    !ext4_should_journal_data(inode) &&
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 5e872fd..3a25946 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -587,11 +587,13 @@
 		return err;
 	}
 
+	case FIDTRIM:
 	case FITRIM:
 	{
 		struct request_queue *q = bdev_get_queue(sb->s_bdev);
 		struct fstrim_range range;
 		int ret = 0;
+		int flags  = cmd == FIDTRIM ? BLKDEV_DISCARD_SECURE : 0;
 
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
@@ -599,13 +601,15 @@
 		if (!blk_queue_discard(q))
 			return -EOPNOTSUPP;
 
+		if ((flags & BLKDEV_DISCARD_SECURE) && !blk_queue_secdiscard(q))
+			return -EOPNOTSUPP;
 		if (copy_from_user(&range, (struct fstrim_range __user *)arg,
 		    sizeof(range)))
 			return -EFAULT;
 
 		range.minlen = max((unsigned int)range.minlen,
 				   q->limits.discard_granularity);
-		ret = ext4_trim_fs(sb, &range);
+		ret = ext4_trim_fs(sb, &range, flags);
 		if (ret < 0)
 			return ret;
 
@@ -629,7 +633,17 @@
 			goto encryption_policy_out;
 		}
 
+		err = mnt_want_write_file(filp);
+		if (err)
+			goto encryption_policy_out;
+
+		mutex_lock(&inode->i_mutex);
+
 		err = ext4_process_policy(&policy, inode);
+
+		mutex_unlock(&inode->i_mutex);
+
+		mnt_drop_write_file(filp);
 encryption_policy_out:
 		return err;
 #else
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 61eaf74..c281050 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -669,7 +669,7 @@
 	ext4_grpblk_t min;
 	ext4_grpblk_t max;
 	ext4_grpblk_t chunk;
-	unsigned short border;
+	unsigned int border;
 
 	BUG_ON(len > EXT4_CLUSTERS_PER_GROUP(sb));
 
@@ -815,7 +815,7 @@
  * for this page; do not hold this lock when calling this routine!
  */
 
-static int ext4_mb_init_cache(struct page *page, char *incore)
+static int ext4_mb_init_cache(struct page *page, char *incore, gfp_t gfp)
 {
 	ext4_group_t ngroups;
 	int blocksize;
@@ -848,7 +848,7 @@
 	/* allocate buffer_heads to read bitmaps */
 	if (groups_per_page > 1) {
 		i = sizeof(struct buffer_head *) * groups_per_page;
-		bh = kzalloc(i, GFP_NOFS);
+		bh = kzalloc(i, gfp);
 		if (bh == NULL) {
 			err = -ENOMEM;
 			goto out;
@@ -983,7 +983,7 @@
  * are on the same page e4b->bd_buddy_page is NULL and return value is 0.
  */
 static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
-		ext4_group_t group, struct ext4_buddy *e4b)
+		ext4_group_t group, struct ext4_buddy *e4b, gfp_t gfp)
 {
 	struct inode *inode = EXT4_SB(sb)->s_buddy_cache;
 	int block, pnum, poff;
@@ -1002,7 +1002,7 @@
 	block = group * 2;
 	pnum = block / blocks_per_page;
 	poff = block % blocks_per_page;
-	page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
+	page = find_or_create_page(inode->i_mapping, pnum, gfp);
 	if (!page)
 		return -ENOMEM;
 	BUG_ON(page->mapping != inode->i_mapping);
@@ -1016,7 +1016,7 @@
 
 	block++;
 	pnum = block / blocks_per_page;
-	page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
+	page = find_or_create_page(inode->i_mapping, pnum, gfp);
 	if (!page)
 		return -ENOMEM;
 	BUG_ON(page->mapping != inode->i_mapping);
@@ -1042,7 +1042,7 @@
  * calling this routine!
  */
 static noinline_for_stack
-int ext4_mb_init_group(struct super_block *sb, ext4_group_t group)
+int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
 {
 
 	struct ext4_group_info *this_grp;
@@ -1062,7 +1062,7 @@
 	 * The call to ext4_mb_get_buddy_page_lock will mark the
 	 * page accessed.
 	 */
-	ret = ext4_mb_get_buddy_page_lock(sb, group, &e4b);
+	ret = ext4_mb_get_buddy_page_lock(sb, group, &e4b, gfp);
 	if (ret || !EXT4_MB_GRP_NEED_INIT(this_grp)) {
 		/*
 		 * somebody initialized the group
@@ -1072,7 +1072,7 @@
 	}
 
 	page = e4b.bd_bitmap_page;
-	ret = ext4_mb_init_cache(page, NULL);
+	ret = ext4_mb_init_cache(page, NULL, gfp);
 	if (ret)
 		goto err;
 	if (!PageUptodate(page)) {
@@ -1091,7 +1091,7 @@
 	}
 	/* init buddy cache */
 	page = e4b.bd_buddy_page;
-	ret = ext4_mb_init_cache(page, e4b.bd_bitmap);
+	ret = ext4_mb_init_cache(page, e4b.bd_bitmap, gfp);
 	if (ret)
 		goto err;
 	if (!PageUptodate(page)) {
@@ -1109,8 +1109,8 @@
  * calling this routine!
  */
 static noinline_for_stack int
-ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
-					struct ext4_buddy *e4b)
+ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
+		       struct ext4_buddy *e4b, gfp_t gfp)
 {
 	int blocks_per_page;
 	int block;
@@ -1140,7 +1140,7 @@
 		 * we need full data about the group
 		 * to make a good selection
 		 */
-		ret = ext4_mb_init_group(sb, group);
+		ret = ext4_mb_init_group(sb, group, gfp);
 		if (ret)
 			return ret;
 	}
@@ -1168,11 +1168,11 @@
 			 * wait for it to initialize.
 			 */
 			page_cache_release(page);
-		page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
+		page = find_or_create_page(inode->i_mapping, pnum, gfp);
 		if (page) {
 			BUG_ON(page->mapping != inode->i_mapping);
 			if (!PageUptodate(page)) {
-				ret = ext4_mb_init_cache(page, NULL);
+				ret = ext4_mb_init_cache(page, NULL, gfp);
 				if (ret) {
 					unlock_page(page);
 					goto err;
@@ -1204,11 +1204,12 @@
 	if (page == NULL || !PageUptodate(page)) {
 		if (page)
 			page_cache_release(page);
-		page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
+		page = find_or_create_page(inode->i_mapping, pnum, gfp);
 		if (page) {
 			BUG_ON(page->mapping != inode->i_mapping);
 			if (!PageUptodate(page)) {
-				ret = ext4_mb_init_cache(page, e4b->bd_bitmap);
+				ret = ext4_mb_init_cache(page, e4b->bd_bitmap,
+							 gfp);
 				if (ret) {
 					unlock_page(page);
 					goto err;
@@ -1247,6 +1248,12 @@
 	return ret;
 }
 
+static int ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
+			      struct ext4_buddy *e4b)
+{
+	return ext4_mb_load_buddy_gfp(sb, group, e4b, GFP_NOFS);
+}
+
 static void ext4_mb_unload_buddy(struct ext4_buddy *e4b)
 {
 	if (e4b->bd_bitmap_page)
@@ -1259,6 +1266,7 @@
 static int mb_find_order_for_block(struct ext4_buddy *e4b, int block)
 {
 	int order = 1;
+	int bb_incr = 1 << (e4b->bd_blkbits - 1);
 	void *bb;
 
 	BUG_ON(e4b->bd_bitmap == e4b->bd_buddy);
@@ -1271,7 +1279,8 @@
 			/* this block is part of buddy of order 'order' */
 			return order;
 		}
-		bb += 1 << (e4b->bd_blkbits - order);
+		bb += bb_incr;
+		bb_incr >>= 1;
 		order++;
 	}
 	return 0;
@@ -2045,7 +2054,7 @@
 
 	/* We only do this if the grp has never been initialized */
 	if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
-		int ret = ext4_mb_init_group(ac->ac_sb, group);
+		int ret = ext4_mb_init_group(ac->ac_sb, group, GFP_NOFS);
 		if (ret)
 			return ret;
 	}
@@ -2278,7 +2287,7 @@
 	struct ext4_group_info *grinfo;
 	struct sg {
 		struct ext4_group_info info;
-		ext4_grpblk_t counters[16];
+		ext4_grpblk_t counters[EXT4_MAX_BLOCK_LOG_SIZE + 2];
 	} sg;
 
 	group--;
@@ -2576,7 +2585,7 @@
 {
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	unsigned i, j;
-	unsigned offset;
+	unsigned offset, offset_incr;
 	unsigned max;
 	int ret;
 
@@ -2605,11 +2614,13 @@
 
 	i = 1;
 	offset = 0;
+	offset_incr = 1 << (sb->s_blocksize_bits - 1);
 	max = sb->s_blocksize << 2;
 	do {
 		sbi->s_mb_offsets[i] = offset;
 		sbi->s_mb_maxs[i] = max;
-		offset += 1 << (sb->s_blocksize_bits - i);
+		offset += offset_incr;
+		offset_incr = offset_incr >> 1;
 		max = max >> 1;
 		i++;
 	} while (i <= sb->s_blocksize_bits + 1);
@@ -2759,7 +2770,8 @@
 }
 
 static inline int ext4_issue_discard(struct super_block *sb,
-		ext4_group_t block_group, ext4_grpblk_t cluster, int count)
+		ext4_group_t block_group, ext4_grpblk_t cluster, int count,
+		unsigned long flags)
 {
 	ext4_fsblk_t discard_block;
 
@@ -2768,7 +2780,7 @@
 	count = EXT4_C2B(EXT4_SB(sb), count);
 	trace_ext4_discard_blocks(sb,
 			(unsigned long long) discard_block, count);
-	return sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
+	return sb_issue_discard(sb, discard_block, count, GFP_NOFS, flags);
 }
 
 /*
@@ -2790,7 +2802,7 @@
 	if (test_opt(sb, DISCARD)) {
 		err = ext4_issue_discard(sb, entry->efd_group,
 					 entry->efd_start_cluster,
-					 entry->efd_count);
+					 entry->efd_count, 0);
 		if (err && err != -EOPNOTSUPP)
 			ext4_msg(sb, KERN_WARNING, "discard request in"
 				 " group:%d block:%d count:%d failed"
@@ -2928,7 +2940,7 @@
 		ext4_error(sb, "Allocating blocks %llu-%llu which overlap "
 			   "fs metadata", block, block+len);
 		/* File system mounted not to panic on error
-		 * Fix the bitmap and repeat the block allocation
+		 * Fix the bitmap and return EFSCORRUPTED
 		 * We leak some of the blocks here.
 		 */
 		ext4_lock_group(sb, ac->ac_b_ex.fe_group);
@@ -2937,7 +2949,7 @@
 		ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
 		err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
 		if (!err)
-			err = -EAGAIN;
+			err = -EFSCORRUPTED;
 		goto out_err;
 	}
 
@@ -3109,6 +3121,13 @@
 	if (ar->pright && start + size - 1 >= ar->lright)
 		size -= start + size - ar->lright;
 
+	/*
+	 * Trim allocation request for filesystems with artificially small
+	 * groups.
+	 */
+	if (size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb))
+		size = EXT4_BLOCKS_PER_GROUP(ac->ac_sb);
+
 	end = start + size;
 
 	/* check we don't cross already preallocated blocks */
@@ -4502,18 +4521,7 @@
 	}
 	if (likely(ac->ac_status == AC_STATUS_FOUND)) {
 		*errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_clstrs);
-		if (*errp == -EAGAIN) {
-			/*
-			 * drop the reference that we took
-			 * in ext4_mb_use_best_found
-			 */
-			ext4_mb_release_context(ac);
-			ac->ac_b_ex.fe_group = 0;
-			ac->ac_b_ex.fe_start = 0;
-			ac->ac_b_ex.fe_len = 0;
-			ac->ac_status = AC_STATUS_CONTINUE;
-			goto repeat;
-		} else if (*errp) {
+		if (*errp) {
 			ext4_discard_allocated_blocks(ac);
 			goto errout;
 		} else {
@@ -4815,7 +4823,9 @@
 #endif
 	trace_ext4_mballoc_free(sb, inode, block_group, bit, count_clusters);
 
-	err = ext4_mb_load_buddy(sb, block_group, &e4b);
+	/* __GFP_NOFAIL: retry infinitely, ignore TIF_MEMDIE and memcg limit. */
+	err = ext4_mb_load_buddy_gfp(sb, block_group, &e4b,
+				     GFP_NOFS|__GFP_NOFAIL);
 	if (err)
 		goto error_return;
 
@@ -4844,7 +4854,8 @@
 		 * them with group lock_held
 		 */
 		if (test_opt(sb, DISCARD)) {
-			err = ext4_issue_discard(sb, block_group, bit, count);
+			err = ext4_issue_discard(sb, block_group, bit, count,
+						 0);
 			if (err && err != -EOPNOTSUPP)
 				ext4_msg(sb, KERN_WARNING, "discard request in"
 					 " group:%d block:%d count:%lu failed"
@@ -5040,13 +5051,15 @@
  * @count:	number of blocks to TRIM
  * @group:	alloc. group we are working with
  * @e4b:	ext4 buddy for the group
+ * @blkdev_flags: flags for the block device
  *
  * Trim "count" blocks starting at "start" in the "group". To assure that no
  * one will allocate those blocks, mark it as used in buddy bitmap. This must
  * be called with under the group lock.
  */
 static int ext4_trim_extent(struct super_block *sb, int start, int count,
-			     ext4_group_t group, struct ext4_buddy *e4b)
+			    ext4_group_t group, struct ext4_buddy *e4b,
+			    unsigned long blkdev_flags)
 __releases(bitlock)
 __acquires(bitlock)
 {
@@ -5067,7 +5080,7 @@
 	 */
 	mb_mark_used(e4b, &ex);
 	ext4_unlock_group(sb, group);
-	ret = ext4_issue_discard(sb, group, start, count);
+	ret = ext4_issue_discard(sb, group, start, count, blkdev_flags);
 	ext4_lock_group(sb, group);
 	mb_free_blocks(NULL, e4b, start, ex.fe_len);
 	return ret;
@@ -5080,6 +5093,7 @@
  * @start:		first group block to examine
  * @max:		last group block to examine
  * @minblocks:		minimum extent block count
+ * @blkdev_flags:	flags for the block device
  *
  * ext4_trim_all_free walks through group's buddy bitmap searching for free
  * extents. When the free block is found, ext4_trim_extent is called to TRIM
@@ -5094,7 +5108,7 @@
 static ext4_grpblk_t
 ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
 		   ext4_grpblk_t start, ext4_grpblk_t max,
-		   ext4_grpblk_t minblocks)
+		   ext4_grpblk_t minblocks, unsigned long blkdev_flags)
 {
 	void *bitmap;
 	ext4_grpblk_t next, count = 0, free_count = 0;
@@ -5127,7 +5141,8 @@
 
 		if ((next - start) >= minblocks) {
 			ret = ext4_trim_extent(sb, start,
-					       next - start, group, &e4b);
+					       next - start, group, &e4b,
+					       blkdev_flags);
 			if (ret && ret != -EOPNOTSUPP)
 				break;
 			ret = 0;
@@ -5169,6 +5184,7 @@
  * ext4_trim_fs() -- trim ioctl handle function
  * @sb:			superblock for filesystem
  * @range:		fstrim_range structure
+ * @blkdev_flags:	flags for the block device
  *
  * start:	First Byte to trim
  * len:		number of Bytes to trim from start
@@ -5177,7 +5193,8 @@
  * start to start+len. For each such a group ext4_trim_all_free function
  * is invoked to trim all free space.
  */
-int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range,
+			unsigned long blkdev_flags)
 {
 	struct ext4_group_info *grp;
 	ext4_group_t group, first_group, last_group;
@@ -5217,7 +5234,7 @@
 		grp = ext4_get_group_info(sb, group);
 		/* We only do this if the grp has never been initialized */
 		if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
-			ret = ext4_mb_init_group(sb, group);
+			ret = ext4_mb_init_group(sb, group, GFP_NOFS);
 			if (ret)
 				break;
 		}
@@ -5233,7 +5250,7 @@
 
 		if (grp->bb_free >= minlen) {
 			cnt = ext4_trim_all_free(sb, group, first_cluster,
-						end, minlen);
+						end, minlen, blkdev_flags);
 			if (cnt < 0) {
 				ret = cnt;
 				break;
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 9bdbf98..05048fc 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -187,7 +187,7 @@
 	if (PageUptodate(page))
 		return 0;
 
-	blocksize = 1 << inode->i_blkbits;
+	blocksize = i_blocksize(inode);
 	if (!page_has_buffers(page))
 		create_empty_buffers(page, blocksize, 0);
 
@@ -390,6 +390,7 @@
 		*err = ext4_get_block(orig_inode, orig_blk_offset + i, bh, 0);
 		if (*err < 0)
 			break;
+		bh = bh->b_this_page;
 	}
 	if (!*err)
 		*err = block_commit_write(pagep[0], from, from + replaced_size);
@@ -597,6 +598,13 @@
 		return -EOPNOTSUPP;
 	}
 
+	if (ext4_encrypted_inode(orig_inode) ||
+	    ext4_encrypted_inode(donor_inode)) {
+		ext4_msg(orig_inode->i_sb, KERN_ERR,
+			 "Online defrag not supported for encrypted files");
+		return -EOPNOTSUPP;
+	}
+
 	/* Protect orig and donor inodes against a truncate */
 	lock_two_nondirectories(orig_inode, donor_inode);
 
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index a969ab3..1d007e8 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -420,15 +420,14 @@
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	__u32 csum;
-	__le32 save_csum;
 	int size;
+	__u32 dummy_csum = 0;
+	int offset = offsetof(struct dx_tail, dt_checksum);
 
 	size = count_offset + (count * sizeof(struct dx_entry));
-	save_csum = t->dt_checksum;
-	t->dt_checksum = 0;
 	csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)dirent, size);
-	csum = ext4_chksum(sbi, csum, (__u8 *)t, sizeof(struct dx_tail));
-	t->dt_checksum = save_csum;
+	csum = ext4_chksum(sbi, csum, (__u8 *)t, offset);
+	csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum));
 
 	return cpu_to_le32(csum);
 }
@@ -1244,9 +1243,9 @@
 	if (unlikely(!name)) {
 		if (fname->usr_fname->name[0] == '_') {
 			int ret;
-			if (de->name_len < 16)
+			if (de->name_len <= 32)
 				return 0;
-			ret = memcmp(de->name + de->name_len - 16,
+			ret = memcmp(de->name + ((de->name_len - 17) & ~15),
 				     fname->crypto_buf.name + 8, 16);
 			return (ret == 0) ? 1 : 0;
 		}
@@ -1558,6 +1557,24 @@
 	struct ext4_dir_entry_2 *de;
 	struct buffer_head *bh;
 
+       if (ext4_encrypted_inode(dir)) {
+               int res = ext4_get_encryption_info(dir);
+
+		/*
+		 * This should be a properly defined flag for
+		 * dentry->d_flags when we uplift this to the VFS.
+		 * d_fsdata is set to (void *) 1 if if the dentry is
+		 * created while the directory was encrypted and we
+		 * don't have access to the key.
+		 */
+	       dentry->d_fsdata = NULL;
+	       if (ext4_encryption_info(dir))
+		       dentry->d_fsdata = (void *) 1;
+	       d_set_d_op(dentry, &ext4_encrypted_d_ops);
+	       if (res && res != -ENOKEY)
+		       return ERR_PTR(res);
+       }
+
 	if (dentry->d_name.len > EXT4_NAME_LEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
@@ -2018,33 +2035,31 @@
 	frame->entries = entries;
 	frame->at = entries;
 	frame->bh = bh;
-	bh = bh2;
 
 	retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
 	if (retval)
 		goto out_frames;	
-	retval = ext4_handle_dirty_dirent_node(handle, dir, bh);
+	retval = ext4_handle_dirty_dirent_node(handle, dir, bh2);
 	if (retval)
 		goto out_frames;	
 
-	de = do_split(handle,dir, &bh, frame, &fname->hinfo);
+	de = do_split(handle,dir, &bh2, frame, &fname->hinfo);
 	if (IS_ERR(de)) {
 		retval = PTR_ERR(de);
 		goto out_frames;
 	}
-	dx_release(frames);
 
-	retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh);
-	brelse(bh);
-	return retval;
+	retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh2);
 out_frames:
 	/*
 	 * Even if the block split failed, we have to properly write
 	 * out all the changes we did so far. Otherwise we can end up
 	 * with corrupted filesystem.
 	 */
-	ext4_mark_inode_dirty(handle, dir);
+	if (retval)
+		ext4_mark_inode_dirty(handle, dir);
 	dx_release(frames);
+	brelse(bh2);
 	return retval;
 }
 
@@ -2809,7 +2824,7 @@
 			 * list entries can cause panics at unmount time.
 			 */
 			mutex_lock(&sbi->s_orphan_lock);
-			list_del(&EXT4_I(inode)->i_orphan);
+			list_del_init(&EXT4_I(inode)->i_orphan);
 			mutex_unlock(&sbi->s_orphan_lock);
 		}
 	}
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 17fbe38..6ca56f5 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/backing-dev.h>
 
 #include "ext4_jbd2.h"
 #include "xattr.h"
@@ -485,9 +486,20 @@
 
 	if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) &&
 	    nr_to_submit) {
-		data_page = ext4_encrypt(inode, page);
+		gfp_t gfp_flags = GFP_NOFS;
+
+	retry_encrypt:
+		data_page = ext4_encrypt(inode, page, gfp_flags);
 		if (IS_ERR(data_page)) {
 			ret = PTR_ERR(data_page);
+			if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
+				if (io->io_bio) {
+					ext4_io_submit(io);
+					congestion_wait(BLK_RW_ASYNC, HZ/50);
+				}
+				gfp_flags |= __GFP_NOFAIL;
+				goto retry_encrypt;
+			}
 			data_page = NULL;
 			goto out;
 		}
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 5dc5e95..783e33d 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -45,6 +45,7 @@
 #include <linux/cleancache.h>
 
 #include "ext4.h"
+#include <trace/events/android_fs.h>
 
 /*
  * Call ext4_decrypt on every single page, reusing the encryption
@@ -86,6 +87,17 @@
 #endif
 }
 
+static void
+ext4_trace_read_completion(struct bio *bio)
+{
+	struct page *first_page = bio->bi_io_vec[0].bv_page;
+
+	if (first_page != NULL)
+		trace_android_fs_dataread_end(first_page->mapping->host,
+					      page_offset(first_page),
+					      bio->bi_iter.bi_size);
+}
+
 /*
  * I/O completion handler for multipage BIOs.
  *
@@ -103,6 +115,9 @@
 	struct bio_vec *bv;
 	int i;
 
+	if (trace_android_fs_dataread_start_enabled())
+		ext4_trace_read_completion(bio);
+
 	if (ext4_bio_encrypted(bio)) {
 		struct ext4_crypto_ctx *ctx = bio->bi_private;
 
@@ -130,6 +145,30 @@
 	bio_put(bio);
 }
 
+static void
+ext4_submit_bio_read(struct bio *bio)
+{
+	if (trace_android_fs_dataread_start_enabled()) {
+		struct page *first_page = bio->bi_io_vec[0].bv_page;
+
+		if (first_page != NULL) {
+			char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+			path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    first_page->mapping->host);
+			trace_android_fs_dataread_start(
+				first_page->mapping->host,
+				page_offset(first_page),
+				bio->bi_iter.bi_size,
+				current->pid,
+				path,
+				current->comm);
+		}
+	}
+	submit_bio(READ, bio);
+}
+
 int ext4_mpage_readpages(struct address_space *mapping,
 			 struct list_head *pages, struct page *page,
 			 unsigned nr_pages)
@@ -271,7 +310,7 @@
 		 */
 		if (bio && (last_block_in_bio != blocks[0] - 1)) {
 		submit_and_realloc:
-			submit_bio(READ, bio);
+			ext4_submit_bio_read(bio);
 			bio = NULL;
 		}
 		if (bio == NULL) {
@@ -279,7 +318,7 @@
 
 			if (ext4_encrypted_inode(inode) &&
 			    S_ISREG(inode->i_mode)) {
-				ctx = ext4_get_crypto_ctx(inode);
+				ctx = ext4_get_crypto_ctx(inode, GFP_NOFS);
 				if (IS_ERR(ctx))
 					goto set_error_page;
 			}
@@ -303,14 +342,14 @@
 		if (((map.m_flags & EXT4_MAP_BOUNDARY) &&
 		     (relative_block == map.m_len)) ||
 		    (first_hole != blocks_per_page)) {
-			submit_bio(READ, bio);
+			ext4_submit_bio_read(bio);
 			bio = NULL;
 		} else
 			last_block_in_bio = blocks[blocks_per_page - 1];
 		goto next_page;
 	confused:
 		if (bio) {
-			submit_bio(READ, bio);
+			ext4_submit_bio_read(bio);
 			bio = NULL;
 		}
 		if (!PageUptodate(page))
@@ -323,6 +362,6 @@
 	}
 	BUG_ON(pages && !list_empty(pages));
 	if (bio)
-		submit_bio(READ, bio);
+		ext4_submit_bio_read(bio);
 	return 0;
 }
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 852c268..bd8831b 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -793,6 +793,7 @@
 {
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	struct ext4_super_block *es = sbi->s_es;
+	int aborted = 0;
 	int i, err;
 
 	ext4_unregister_li_request(sb);
@@ -802,9 +803,10 @@
 	destroy_workqueue(sbi->rsv_conversion_wq);
 
 	if (sbi->s_journal) {
+		aborted = is_journal_aborted(sbi->s_journal);
 		err = jbd2_journal_destroy(sbi->s_journal);
 		sbi->s_journal = NULL;
-		if (err < 0)
+		if ((err < 0) && !aborted)
 			ext4_abort(sb, "Couldn't clean up the journal");
 	}
 
@@ -814,9 +816,8 @@
 	ext4_release_system_zone(sb);
 	ext4_mb_release(sb);
 	ext4_ext_release(sb);
-	ext4_xattr_put_super(sb);
 
-	if (!(sb->s_flags & MS_RDONLY)) {
+	if (!(sb->s_flags & MS_RDONLY) && !aborted) {
 		ext4_clear_feature_journal_needs_recovery(sb);
 		es->s_state = cpu_to_le16(sbi->s_mount_state);
 	}
@@ -2030,23 +2031,25 @@
 static __le16 ext4_group_desc_csum(struct super_block *sb, __u32 block_group,
 				   struct ext4_group_desc *gdp)
 {
-	int offset;
+	int offset = offsetof(struct ext4_group_desc, bg_checksum);
 	__u16 crc = 0;
 	__le32 le_group = cpu_to_le32(block_group);
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 
 	if (ext4_has_metadata_csum(sbi->s_sb)) {
 		/* Use new metadata_csum algorithm */
-		__le16 save_csum;
 		__u32 csum32;
+		__u16 dummy_csum = 0;
 
-		save_csum = gdp->bg_checksum;
-		gdp->bg_checksum = 0;
 		csum32 = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&le_group,
 				     sizeof(le_group));
-		csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp,
-				     sbi->s_desc_size);
-		gdp->bg_checksum = save_csum;
+		csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp, offset);
+		csum32 = ext4_chksum(sbi, csum32, (__u8 *)&dummy_csum,
+				     sizeof(dummy_csum));
+		offset += sizeof(dummy_csum);
+		if (offset < sbi->s_desc_size)
+			csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp + offset,
+					     sbi->s_desc_size - offset);
 
 		crc = csum32 & 0xFFFF;
 		goto out;
@@ -2056,8 +2059,6 @@
 	if (!ext4_has_feature_gdt_csum(sb))
 		return 0;
 
-	offset = offsetof(struct ext4_group_desc, bg_checksum);
-
 	crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
 	crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
 	crc = crc16(crc, (__u8 *)gdp, offset);
@@ -2093,6 +2094,7 @@
 
 /* Called at mount-time, super-block is locked */
 static int ext4_check_descriptors(struct super_block *sb,
+				  ext4_fsblk_t sb_block,
 				  ext4_group_t *first_not_zeroed)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -2123,6 +2125,11 @@
 			grp = i;
 
 		block_bitmap = ext4_block_bitmap(sb, gdp);
+		if (block_bitmap == sb_block) {
+			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+				 "Block bitmap for group %u overlaps "
+				 "superblock", i);
+		}
 		if (block_bitmap < first_block || block_bitmap > last_block) {
 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
 			       "Block bitmap for group %u not in group "
@@ -2130,6 +2137,11 @@
 			return 0;
 		}
 		inode_bitmap = ext4_inode_bitmap(sb, gdp);
+		if (inode_bitmap == sb_block) {
+			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+				 "Inode bitmap for group %u overlaps "
+				 "superblock", i);
+		}
 		if (inode_bitmap < first_block || inode_bitmap > last_block) {
 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
 			       "Inode bitmap for group %u not in group "
@@ -2137,6 +2149,11 @@
 			return 0;
 		}
 		inode_table = ext4_inode_table(sb, gdp);
+		if (inode_table == sb_block) {
+			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+				 "Inode table for group %u overlaps "
+				 "superblock", i);
+		}
 		if (inode_table < first_block ||
 		    inode_table + sbi->s_itb_per_group - 1 > last_block) {
 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
@@ -2240,6 +2257,16 @@
 	while (es->s_last_orphan) {
 		struct inode *inode;
 
+		/*
+		 * We may have encountered an error during cleanup; if
+		 * so, skip the rest.
+		 */
+		if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
+			jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
+			es->s_last_orphan = 0;
+			break;
+		}
+
 		inode = ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan));
 		if (IS_ERR(inode)) {
 			es->s_last_orphan = 0;
@@ -3011,10 +3038,15 @@
 			ext4_set_bit(s++, buf);
 			count++;
 		}
-		for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) {
-			ext4_set_bit(EXT4_B2C(sbi, s++), buf);
-			count++;
+		j = ext4_bg_num_gdb(sb, grp);
+		if (s + j > EXT4_BLOCKS_PER_GROUP(sb)) {
+			ext4_error(sb, "Invalid number of block group "
+				   "descriptor blocks: %d", j);
+			j = EXT4_BLOCKS_PER_GROUP(sb) - s;
 		}
+		count += j;
+		for (; j > 0; j--)
+			ext4_set_bit(EXT4_B2C(sbi, s++), buf);
 	}
 	if (!count)
 		return 0;
@@ -3104,7 +3136,7 @@
 	char *orig_data = kstrdup(data, GFP_KERNEL);
 	struct buffer_head *bh;
 	struct ext4_super_block *es = NULL;
-	struct ext4_sb_info *sbi;
+	struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	ext4_fsblk_t block;
 	ext4_fsblk_t sb_block = get_sb_block(&data);
 	ext4_fsblk_t logical_sb_block;
@@ -3123,16 +3155,14 @@
 	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
 	ext4_group_t first_not_zeroed;
 
-	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-	if (!sbi)
-		goto out_free_orig;
+	if ((data && !orig_data) || !sbi)
+		goto out_free_base;
 
 	sbi->s_blockgroup_lock =
 		kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
-	if (!sbi->s_blockgroup_lock) {
-		kfree(sbi);
-		goto out_free_orig;
-	}
+	if (!sbi->s_blockgroup_lock)
+		goto out_free_base;
+
 	sb->s_fs_info = sbi;
 	sbi->s_sb = sb;
 	sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
@@ -3278,11 +3308,19 @@
 	 */
 	sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
 
-	if (!parse_options((char *) sbi->s_es->s_mount_opts, sb,
-			   &journal_devnum, &journal_ioprio, 0)) {
-		ext4_msg(sb, KERN_WARNING,
-			 "failed to parse options in superblock: %s",
-			 sbi->s_es->s_mount_opts);
+	if (sbi->s_es->s_mount_opts[0]) {
+		char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts,
+					      sizeof(sbi->s_es->s_mount_opts),
+					      GFP_KERNEL);
+		if (!s_mount_opts)
+			goto failed_mount;
+		if (!parse_options(s_mount_opts, sb, &journal_devnum,
+				   &journal_ioprio, 0)) {
+			ext4_msg(sb, KERN_WARNING,
+				 "failed to parse options in superblock: %s",
+				 s_mount_opts);
+		}
+		kfree(s_mount_opts);
 	}
 	sbi->s_def_mount_opt = sbi->s_mount_opt;
 	if (!parse_options((char *) data, sb, &journal_devnum,
@@ -3308,6 +3346,11 @@
 				 "both data=journal and dax");
 			goto failed_mount;
 		}
+		if (ext4_has_feature_encrypt(sb)) {
+			ext4_msg(sb, KERN_WARNING,
+				 "encrypted files will use data=ordered "
+				 "instead of data journaling mode");
+		}
 		if (test_opt(sb, DELALLOC))
 			clear_opt(sb, DELALLOC);
 	} else {
@@ -3368,7 +3411,22 @@
 	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
 	    blocksize > EXT4_MAX_BLOCK_SIZE) {
 		ext4_msg(sb, KERN_ERR,
-		       "Unsupported filesystem blocksize %d", blocksize);
+		       "Unsupported filesystem blocksize %d (%d log_block_size)",
+			 blocksize, le32_to_cpu(es->s_log_block_size));
+		goto failed_mount;
+	}
+	if (le32_to_cpu(es->s_log_block_size) >
+	    (EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
+		ext4_msg(sb, KERN_ERR,
+			 "Invalid log block size: %u",
+			 le32_to_cpu(es->s_log_block_size));
+		goto failed_mount;
+	}
+
+	if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) {
+		ext4_msg(sb, KERN_ERR,
+			 "Number of reserved GDT blocks insanely large: %d",
+			 le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks));
 		goto failed_mount;
 	}
 
@@ -3455,12 +3513,16 @@
 
 	sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
 	sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
-	if (EXT4_INODE_SIZE(sb) == 0 || EXT4_INODES_PER_GROUP(sb) == 0)
-		goto cantfind_ext4;
 
 	sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);
 	if (sbi->s_inodes_per_block == 0)
 		goto cantfind_ext4;
+	if (sbi->s_inodes_per_group < sbi->s_inodes_per_block ||
+	    sbi->s_inodes_per_group > blocksize * 8) {
+		ext4_msg(sb, KERN_ERR, "invalid inodes per group: %lu\n",
+			 sbi->s_blocks_per_group);
+		goto failed_mount;
+	}
 	sbi->s_itb_per_group = sbi->s_inodes_per_group /
 					sbi->s_inodes_per_block;
 	sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
@@ -3500,6 +3562,13 @@
 				 "block size (%d)", clustersize, blocksize);
 			goto failed_mount;
 		}
+		if (le32_to_cpu(es->s_log_cluster_size) >
+		    (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
+			ext4_msg(sb, KERN_ERR,
+				 "Invalid log cluster size: %u",
+				 le32_to_cpu(es->s_log_cluster_size));
+			goto failed_mount;
+		}
 		sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
 			le32_to_cpu(es->s_log_block_size);
 		sbi->s_clusters_per_group =
@@ -3536,13 +3605,6 @@
 	}
 	sbi->s_cluster_ratio = clustersize / blocksize;
 
-	if (sbi->s_inodes_per_group > blocksize * 8) {
-		ext4_msg(sb, KERN_ERR,
-		       "#inodes per group too big: %lu",
-		       sbi->s_inodes_per_group);
-		goto failed_mount;
-	}
-
 	/* Do we have standard group size of clustersize * 8 blocks ? */
 	if (sbi->s_blocks_per_group == clustersize << 3)
 		set_opt2(sb, STD_GROUP_SIZE);
@@ -3602,6 +3664,15 @@
 			(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
 	db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
 		   EXT4_DESC_PER_BLOCK(sb);
+	if (ext4_has_feature_meta_bg(sb)) {
+		if (le32_to_cpu(es->s_first_meta_bg) > db_count) {
+			ext4_msg(sb, KERN_WARNING,
+				 "first meta block group too large: %u "
+				 "(group descriptor block count %u)",
+				 le32_to_cpu(es->s_first_meta_bg), db_count);
+			goto failed_mount;
+		}
+	}
 	sbi->s_group_desc = ext4_kvmalloc(db_count *
 					  sizeof(struct buffer_head *),
 					  GFP_KERNEL);
@@ -3623,7 +3694,7 @@
 			goto failed_mount2;
 		}
 	}
-	if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
+	if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
 		ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
 		ret = -EFSCORRUPTED;
 		goto failed_mount2;
@@ -3676,7 +3747,8 @@
 	 * root first: it may be modified in the journal!
 	 */
 	if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) {
-		if (ext4_load_journal(sb, es, journal_devnum))
+		err = ext4_load_journal(sb, es, journal_devnum);
+		if (err)
 			goto failed_mount3a;
 	} else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
 		   ext4_has_feature_journal_needs_recovery(sb)) {
@@ -3760,7 +3832,7 @@
 
 no_journal:
 	if (ext4_mballoc_ready) {
-		sbi->s_mb_cache = ext4_xattr_create_cache(sb->s_id);
+		sbi->s_mb_cache = ext4_xattr_create_cache();
 		if (!sbi->s_mb_cache) {
 			ext4_msg(sb, KERN_ERR, "Failed to create an mb_cache");
 			goto failed_mount_wq;
@@ -3946,7 +4018,9 @@
 
 	if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount"))
 		ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
-			 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
+			 "Opts: %.*s%s%s", descr,
+			 (int) sizeof(sbi->s_es->s_mount_opts),
+			 sbi->s_es->s_mount_opts,
 			 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
 
 	if (es->s_error_count)
@@ -3990,6 +4064,10 @@
 	if (EXT4_SB(sb)->rsv_conversion_wq)
 		destroy_workqueue(EXT4_SB(sb)->rsv_conversion_wq);
 failed_mount_wq:
+	if (sbi->s_mb_cache) {
+		ext4_xattr_destroy_cache(sbi->s_mb_cache);
+		sbi->s_mb_cache = NULL;
+	}
 	if (sbi->s_journal) {
 		jbd2_journal_destroy(sbi->s_journal);
 		sbi->s_journal = NULL;
@@ -4016,8 +4094,8 @@
 out_fail:
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
+out_free_base:
 	kfree(sbi);
-out_free_orig:
 	kfree(orig_data);
 	return err ? err : ret;
 }
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index 1420a3c..c2ee23a 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -100,7 +100,7 @@
 	int ret;
 
 	ret = kstrtoull(skip_spaces(buf), 0, &val);
-	if (!ret || val >= clusters)
+	if (ret || val >= clusters)
 		return -EINVAL;
 
 	atomic64_set(&sbi->s_resv_clusters, val);
@@ -223,14 +223,18 @@
 EXT4_ATTR_FEATURE(lazy_itable_init);
 EXT4_ATTR_FEATURE(batched_discard);
 EXT4_ATTR_FEATURE(meta_bg_resize);
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
 EXT4_ATTR_FEATURE(encryption);
+#endif
 EXT4_ATTR_FEATURE(metadata_csum_seed);
 
 static struct attribute *ext4_feat_attrs[] = {
 	ATTR_LIST(lazy_itable_init),
 	ATTR_LIST(batched_discard),
 	ATTR_LIST(meta_bg_resize),
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
 	ATTR_LIST(encryption),
+#endif
 	ATTR_LIST(metadata_csum_seed),
 	NULL,
 };
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 6b6b3e7..b310ed8 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -53,7 +53,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
-#include <linux/mbcache.h>
+#include <linux/mbcache2.h>
 #include <linux/quotaops.h>
 #include "ext4_jbd2.h"
 #include "ext4.h"
@@ -80,10 +80,10 @@
 # define ea_bdebug(bh, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
 #endif
 
-static void ext4_xattr_cache_insert(struct mb_cache *, struct buffer_head *);
+static void ext4_xattr_cache_insert(struct mb2_cache *, struct buffer_head *);
 static struct buffer_head *ext4_xattr_cache_find(struct inode *,
 						 struct ext4_xattr_header *,
-						 struct mb_cache_entry **);
+						 struct mb2_cache_entry **);
 static void ext4_xattr_rehash(struct ext4_xattr_header *,
 			      struct ext4_xattr_entry *);
 static int ext4_xattr_list(struct dentry *dentry, char *buffer,
@@ -123,17 +123,18 @@
 {
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	__u32 csum;
-	__le32 save_csum;
 	__le64 dsk_block_nr = cpu_to_le64(block_nr);
+	__u32 dummy_csum = 0;
+	int offset = offsetof(struct ext4_xattr_header, h_checksum);
 
-	save_csum = hdr->h_checksum;
-	hdr->h_checksum = 0;
 	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&dsk_block_nr,
 			   sizeof(dsk_block_nr));
-	csum = ext4_chksum(sbi, csum, (__u8 *)hdr,
-			   EXT4_BLOCK_SIZE(inode->i_sb));
+	csum = ext4_chksum(sbi, csum, (__u8 *)hdr, offset);
+	csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum));
+	offset += sizeof(dummy_csum);
+	csum = ext4_chksum(sbi, csum, (__u8 *)hdr + offset,
+			   EXT4_BLOCK_SIZE(inode->i_sb) - offset);
 
-	hdr->h_checksum = save_csum;
 	return cpu_to_le32(csum);
 }
 
@@ -232,6 +233,27 @@
 	return error;
 }
 
+static int
+__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
+			 void *end, const char *function, unsigned int line)
+{
+	struct ext4_xattr_entry *entry = IFIRST(header);
+	int error = -EFSCORRUPTED;
+
+	if (((void *) header >= end) ||
+	    (header->h_magic != le32_to_cpu(EXT4_XATTR_MAGIC)))
+		goto errout;
+	error = ext4_xattr_check_names(entry, end, entry);
+errout:
+	if (error)
+		__ext4_error_inode(inode, function, line, 0,
+				   "corrupted in-inode xattr");
+	return error;
+}
+
+#define xattr_check_inode(inode, header, end) \
+	__xattr_check_inode((inode), (header), (end), __func__, __LINE__)
+
 static inline int
 ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size)
 {
@@ -278,7 +300,7 @@
 	struct ext4_xattr_entry *entry;
 	size_t size;
 	int error;
-	struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
+	struct mb2_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
 	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
 		  name_index, name, buffer, (long)buffer_size);
@@ -343,7 +365,7 @@
 	header = IHDR(inode, raw_inode);
 	entry = IFIRST(header);
 	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
-	error = ext4_xattr_check_names(entry, end, entry);
+	error = xattr_check_inode(inode, header, end);
 	if (error)
 		goto cleanup;
 	error = ext4_xattr_find_entry(&entry, name_index, name,
@@ -425,7 +447,7 @@
 	struct inode *inode = d_inode(dentry);
 	struct buffer_head *bh = NULL;
 	int error;
-	struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
+	struct mb2_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
 	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
 		  buffer, (long)buffer_size);
@@ -474,7 +496,7 @@
 	raw_inode = ext4_raw_inode(&iloc);
 	header = IHDR(inode, raw_inode);
 	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
-	error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header));
+	error = xattr_check_inode(inode, header, end);
 	if (error)
 		goto cleanup;
 	error = ext4_xattr_list_entries(dentry, IFIRST(header),
@@ -542,11 +564,8 @@
 ext4_xattr_release_block(handle_t *handle, struct inode *inode,
 			 struct buffer_head *bh)
 {
-	struct mb_cache_entry *ce = NULL;
 	int error = 0;
-	struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
-	ce = mb_cache_entry_get(ext4_mb_cache, bh->b_bdev, bh->b_blocknr);
 	BUFFER_TRACE(bh, "get_write_access");
 	error = ext4_journal_get_write_access(handle, bh);
 	if (error)
@@ -554,9 +573,15 @@
 
 	lock_buffer(bh);
 	if (BHDR(bh)->h_refcount == cpu_to_le32(1)) {
+		__u32 hash = le32_to_cpu(BHDR(bh)->h_hash);
+
 		ea_bdebug(bh, "refcount now=0; freeing");
-		if (ce)
-			mb_cache_entry_free(ce);
+		/*
+		 * This must happen under buffer lock for
+		 * ext4_xattr_block_set() to reliably detect freed block
+		 */
+		mb2_cache_entry_delete_block(EXT4_GET_MB_CACHE(inode), hash,
+					     bh->b_blocknr);
 		get_bh(bh);
 		unlock_buffer(bh);
 		ext4_free_blocks(handle, inode, bh, 0, 1,
@@ -564,8 +589,6 @@
 				 EXT4_FREE_BLOCKS_FORGET);
 	} else {
 		le32_add_cpu(&BHDR(bh)->h_refcount, -1);
-		if (ce)
-			mb_cache_entry_release(ce);
 		/*
 		 * Beware of this ugliness: Releasing of xattr block references
 		 * from different inodes can race and so we have to protect
@@ -778,17 +801,15 @@
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *new_bh = NULL;
 	struct ext4_xattr_search *s = &bs->s;
-	struct mb_cache_entry *ce = NULL;
+	struct mb2_cache_entry *ce = NULL;
 	int error = 0;
-	struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
+	struct mb2_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
 #define header(x) ((struct ext4_xattr_header *)(x))
 
 	if (i->value && i->value_len > sb->s_blocksize)
 		return -ENOSPC;
 	if (s->base) {
-		ce = mb_cache_entry_get(ext4_mb_cache, bs->bh->b_bdev,
-					bs->bh->b_blocknr);
 		BUFFER_TRACE(bs->bh, "get_write_access");
 		error = ext4_journal_get_write_access(handle, bs->bh);
 		if (error)
@@ -796,10 +817,15 @@
 		lock_buffer(bs->bh);
 
 		if (header(s->base)->h_refcount == cpu_to_le32(1)) {
-			if (ce) {
-				mb_cache_entry_free(ce);
-				ce = NULL;
-			}
+			__u32 hash = le32_to_cpu(BHDR(bs->bh)->h_hash);
+
+			/*
+			 * This must happen under buffer lock for
+			 * ext4_xattr_block_set() to reliably detect modified
+			 * block
+			 */
+			mb2_cache_entry_delete_block(ext4_mb_cache, hash,
+						     bs->bh->b_blocknr);
 			ea_bdebug(bs->bh, "modifying in-place");
 			error = ext4_xattr_set_entry(i, s);
 			if (!error) {
@@ -823,10 +849,6 @@
 			int offset = (char *)s->here - bs->bh->b_data;
 
 			unlock_buffer(bs->bh);
-			if (ce) {
-				mb_cache_entry_release(ce);
-				ce = NULL;
-			}
 			ea_bdebug(bs->bh, "cloning");
 			s->base = kmalloc(bs->bh->b_size, GFP_NOFS);
 			error = -ENOMEM;
@@ -881,6 +903,31 @@
 				if (error)
 					goto cleanup_dquot;
 				lock_buffer(new_bh);
+				/*
+				 * We have to be careful about races with
+				 * freeing or rehashing of xattr block. Once we
+				 * hold buffer lock xattr block's state is
+				 * stable so we can check whether the block got
+				 * freed / rehashed or not.  Since we unhash
+				 * mbcache entry under buffer lock when freeing
+				 * / rehashing xattr block, checking whether
+				 * entry is still hashed is reliable.
+				 */
+				if (hlist_bl_unhashed(&ce->e_hash_list)) {
+					/*
+					 * Undo everything and check mbcache
+					 * again.
+					 */
+					unlock_buffer(new_bh);
+					dquot_free_block(inode,
+							 EXT4_C2B(EXT4_SB(sb),
+								  1));
+					brelse(new_bh);
+					mb2_cache_entry_put(ext4_mb_cache, ce);
+					ce = NULL;
+					new_bh = NULL;
+					goto inserted;
+				}
 				le32_add_cpu(&BHDR(new_bh)->h_refcount, 1);
 				ea_bdebug(new_bh, "reusing; refcount now=%d",
 					le32_to_cpu(BHDR(new_bh)->h_refcount));
@@ -891,7 +938,8 @@
 				if (error)
 					goto cleanup_dquot;
 			}
-			mb_cache_entry_release(ce);
+			mb2_cache_entry_touch(ext4_mb_cache, ce);
+			mb2_cache_entry_put(ext4_mb_cache, ce);
 			ce = NULL;
 		} else if (bs->bh && s->base == bs->bh->b_data) {
 			/* We were modifying this block in-place. */
@@ -956,7 +1004,7 @@
 
 cleanup:
 	if (ce)
-		mb_cache_entry_release(ce);
+		mb2_cache_entry_put(ext4_mb_cache, ce);
 	brelse(new_bh);
 	if (!(bs->bh && s->base == bs->bh->b_data))
 		kfree(s->base);
@@ -990,8 +1038,7 @@
 	is->s.here = is->s.first;
 	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
 	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
-		error = ext4_xattr_check_names(IFIRST(header), is->s.end,
-					       IFIRST(header));
+		error = xattr_check_inode(inode, header, is->s.end);
 		if (error)
 			return error;
 		/* Find the named attribute. */
@@ -1264,15 +1311,19 @@
 	size_t min_offs, free;
 	int total_ino;
 	void *base, *start, *end;
-	int extra_isize = 0, error = 0, tried_min_extra_isize = 0;
+	int error = 0, tried_min_extra_isize = 0;
 	int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
+	int isize_diff;	/* How much do we need to grow i_extra_isize */
 
 	down_write(&EXT4_I(inode)->xattr_sem);
+	/*
+	 * Set EXT4_STATE_NO_EXPAND to avoid recursion when marking inode dirty
+	 */
+	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
 retry:
-	if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) {
-		up_write(&EXT4_I(inode)->xattr_sem);
-		return 0;
-	}
+	isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize;
+	if (EXT4_I(inode)->i_extra_isize >= new_extra_isize)
+		goto out;
 
 	header = IHDR(inode, raw_inode);
 	entry = IFIRST(header);
@@ -1288,8 +1339,12 @@
 	last = entry;
 	total_ino = sizeof(struct ext4_xattr_ibody_header);
 
+	error = xattr_check_inode(inode, header, end);
+	if (error)
+		goto cleanup;
+
 	free = ext4_xattr_free_space(last, &min_offs, base, &total_ino);
-	if (free >= new_extra_isize) {
+	if (free >= isize_diff) {
 		entry = IFIRST(header);
 		ext4_xattr_shift_entries(entry,	EXT4_I(inode)->i_extra_isize
 				- new_extra_isize, (void *)raw_inode +
@@ -1297,8 +1352,7 @@
 				(void *)header, total_ino,
 				inode->i_sb->s_blocksize);
 		EXT4_I(inode)->i_extra_isize = new_extra_isize;
-		error = 0;
-		goto cleanup;
+		goto out;
 	}
 
 	/*
@@ -1321,7 +1375,7 @@
 		end = bh->b_data + bh->b_size;
 		min_offs = end - base;
 		free = ext4_xattr_free_space(first, &min_offs, base, NULL);
-		if (free < new_extra_isize) {
+		if (free < isize_diff) {
 			if (!tried_min_extra_isize && s_min_extra_isize) {
 				tried_min_extra_isize++;
 				new_extra_isize = s_min_extra_isize;
@@ -1335,7 +1389,7 @@
 		free = inode->i_sb->s_blocksize;
 	}
 
-	while (new_extra_isize > 0) {
+	while (isize_diff > 0) {
 		size_t offs, size, entry_size;
 		struct ext4_xattr_entry *small_entry = NULL;
 		struct ext4_xattr_info i = {
@@ -1366,7 +1420,7 @@
 			EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) +
 					EXT4_XATTR_LEN(last->e_name_len);
 			if (total_size <= free && total_size < min_total_size) {
-				if (total_size < new_extra_isize) {
+				if (total_size < isize_diff) {
 					small_entry = last;
 				} else {
 					entry = last;
@@ -1421,22 +1475,22 @@
 		error = ext4_xattr_ibody_set(handle, inode, &i, is);
 		if (error)
 			goto cleanup;
+		total_ino -= entry_size;
 
 		entry = IFIRST(header);
-		if (entry_size + EXT4_XATTR_SIZE(size) >= new_extra_isize)
-			shift_bytes = new_extra_isize;
+		if (entry_size + EXT4_XATTR_SIZE(size) >= isize_diff)
+			shift_bytes = isize_diff;
 		else
-			shift_bytes = entry_size + size;
+			shift_bytes = entry_size + EXT4_XATTR_SIZE(size);
 		/* Adjust the offsets and shift the remaining entries ahead */
-		ext4_xattr_shift_entries(entry, EXT4_I(inode)->i_extra_isize -
-			shift_bytes, (void *)raw_inode +
-			EXT4_GOOD_OLD_INODE_SIZE + extra_isize + shift_bytes,
-			(void *)header, total_ino - entry_size,
-			inode->i_sb->s_blocksize);
+		ext4_xattr_shift_entries(entry, -shift_bytes,
+			(void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE +
+			EXT4_I(inode)->i_extra_isize + shift_bytes,
+			(void *)header, total_ino, inode->i_sb->s_blocksize);
 
-		extra_isize += shift_bytes;
-		new_extra_isize -= shift_bytes;
-		EXT4_I(inode)->i_extra_isize = extra_isize;
+		isize_diff -= shift_bytes;
+		EXT4_I(inode)->i_extra_isize += shift_bytes;
+		header = IHDR(inode, raw_inode);
 
 		i.name = b_entry_name;
 		i.value = buffer;
@@ -1458,6 +1512,8 @@
 		kfree(bs);
 	}
 	brelse(bh);
+out:
+	ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
 	up_write(&EXT4_I(inode)->xattr_sem);
 	return 0;
 
@@ -1469,6 +1525,10 @@
 	kfree(is);
 	kfree(bs);
 	brelse(bh);
+	/*
+	 * We deliberately leave EXT4_STATE_NO_EXPAND set here since inode
+	 * size expansion failed.
+	 */
 	up_write(&EXT4_I(inode)->xattr_sem);
 	return error;
 }
@@ -1509,17 +1569,6 @@
 }
 
 /*
- * ext4_xattr_put_super()
- *
- * This is called when a file system is unmounted.
- */
-void
-ext4_xattr_put_super(struct super_block *sb)
-{
-	mb_cache_shrink(sb->s_bdev);
-}
-
-/*
  * ext4_xattr_cache_insert()
  *
  * Create a new entry in the extended attribute cache, and insert
@@ -1528,28 +1577,18 @@
  * Returns 0, or a negative error number on failure.
  */
 static void
-ext4_xattr_cache_insert(struct mb_cache *ext4_mb_cache, struct buffer_head *bh)
+ext4_xattr_cache_insert(struct mb2_cache *ext4_mb_cache, struct buffer_head *bh)
 {
 	__u32 hash = le32_to_cpu(BHDR(bh)->h_hash);
-	struct mb_cache_entry *ce;
 	int error;
 
-	ce = mb_cache_entry_alloc(ext4_mb_cache, GFP_NOFS);
-	if (!ce) {
-		ea_bdebug(bh, "out of memory");
-		return;
-	}
-	error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, hash);
+	error = mb2_cache_entry_create(ext4_mb_cache, GFP_NOFS, hash,
+				       bh->b_blocknr);
 	if (error) {
-		mb_cache_entry_free(ce);
-		if (error == -EBUSY) {
+		if (error == -EBUSY)
 			ea_bdebug(bh, "already in cache");
-			error = 0;
-		}
-	} else {
+	} else
 		ea_bdebug(bh, "inserting [%x]", (int)hash);
-		mb_cache_entry_release(ce);
-	}
 }
 
 /*
@@ -1602,26 +1641,19 @@
  */
 static struct buffer_head *
 ext4_xattr_cache_find(struct inode *inode, struct ext4_xattr_header *header,
-		      struct mb_cache_entry **pce)
+		      struct mb2_cache_entry **pce)
 {
 	__u32 hash = le32_to_cpu(header->h_hash);
-	struct mb_cache_entry *ce;
-	struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
+	struct mb2_cache_entry *ce;
+	struct mb2_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
 	if (!header->h_hash)
 		return NULL;  /* never share */
 	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-again:
-	ce = mb_cache_entry_find_first(ext4_mb_cache, inode->i_sb->s_bdev,
-				       hash);
+	ce = mb2_cache_entry_find_first(ext4_mb_cache, hash);
 	while (ce) {
 		struct buffer_head *bh;
 
-		if (IS_ERR(ce)) {
-			if (PTR_ERR(ce) == -EAGAIN)
-				goto again;
-			break;
-		}
 		bh = sb_bread(inode->i_sb, ce->e_block);
 		if (!bh) {
 			EXT4_ERROR_INODE(inode, "block %lu read error",
@@ -1637,7 +1669,7 @@
 			return bh;
 		}
 		brelse(bh);
-		ce = mb_cache_entry_find_next(ce, inode->i_sb->s_bdev, hash);
+		ce = mb2_cache_entry_find_next(ext4_mb_cache, ce);
 	}
 	return NULL;
 }
@@ -1712,15 +1744,15 @@
 
 #define	HASH_BUCKET_BITS	10
 
-struct mb_cache *
-ext4_xattr_create_cache(char *name)
+struct mb2_cache *
+ext4_xattr_create_cache(void)
 {
-	return mb_cache_create(name, HASH_BUCKET_BITS);
+	return mb2_cache_create(HASH_BUCKET_BITS);
 }
 
-void ext4_xattr_destroy_cache(struct mb_cache *cache)
+void ext4_xattr_destroy_cache(struct mb2_cache *cache)
 {
 	if (cache)
-		mb_cache_destroy(cache);
+		mb2_cache_destroy(cache);
 }
 
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index ddc0957..10b0f73 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -108,7 +108,6 @@
 extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
 
 extern void ext4_xattr_delete_inode(handle_t *, struct inode *);
-extern void ext4_xattr_put_super(struct super_block *);
 
 extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
 			    struct ext4_inode *raw_inode, handle_t *handle);
@@ -124,8 +123,8 @@
 				       struct ext4_xattr_info *i,
 				       struct ext4_xattr_ibody_find *is);
 
-extern struct mb_cache *ext4_xattr_create_cache(char *name);
-extern void ext4_xattr_destroy_cache(struct mb_cache *);
+extern struct mb2_cache *ext4_xattr_create_cache(void);
+extern void ext4_xattr_destroy_cache(struct mb2_cache *);
 
 #ifdef CONFIG_EXT4_FS_SECURITY
 extern int ext4_init_security(handle_t *handle, struct inode *inode,
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index c8f25f7..e9a8d67 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -214,12 +214,10 @@
 	case ACL_TYPE_ACCESS:
 		name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
 		if (acl) {
-			error = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (error < 0)
+			error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (error)
 				return error;
 			set_acl_inode(fi, inode->i_mode);
-			if (error == 0)
-				acl = NULL;
 		}
 		break;
 
diff --git a/fs/f2fs/crypto_fname.c b/fs/f2fs/crypto_fname.c
index ab377d4..38349ed 100644
--- a/fs/f2fs/crypto_fname.c
+++ b/fs/f2fs/crypto_fname.c
@@ -333,7 +333,7 @@
 		memset(buf + 4, 0, 4);
 	} else
 		memset(buf, 0, 8);
-	memcpy(buf + 8, iname->name + iname->len - 16, 16);
+	memcpy(buf + 8, iname->name + ((iname->len - 17) & ~15), 16);
 	oname->name[0] = '_';
 	ret = digest_encode(buf, 24, oname->name + 1);
 	oname->len = ret + 1;
diff --git a/fs/f2fs/crypto_key.c b/fs/f2fs/crypto_key.c
index 5de2d86..18595d7 100644
--- a/fs/f2fs/crypto_key.c
+++ b/fs/f2fs/crypto_key.c
@@ -92,7 +92,6 @@
 	if (!ci)
 		return;
 
-	key_put(ci->ci_keyring_key);
 	crypto_free_ablkcipher(ci->ci_ctfm);
 	kmem_cache_free(f2fs_crypt_info_cachep, ci);
 }
@@ -113,7 +112,7 @@
 	f2fs_free_crypt_info(ci);
 }
 
-int _f2fs_get_encryption_info(struct inode *inode)
+int f2fs_get_encryption_info(struct inode *inode)
 {
 	struct f2fs_inode_info *fi = F2FS_I(inode);
 	struct f2fs_crypt_info *crypt_info;
@@ -129,18 +128,12 @@
 	char mode;
 	int res;
 
+	if (fi->i_crypt_info)
+		return 0;
+
 	res = f2fs_crypto_initialize();
 	if (res)
 		return res;
-retry:
-	crypt_info = ACCESS_ONCE(fi->i_crypt_info);
-	if (crypt_info) {
-		if (!crypt_info->ci_keyring_key ||
-				key_validate(crypt_info->ci_keyring_key) == 0)
-			return 0;
-		f2fs_free_encryption_info(inode, crypt_info);
-		goto retry;
-	}
 
 	res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION,
 				F2FS_XATTR_NAME_ENCRYPTION_CONTEXT,
@@ -159,7 +152,6 @@
 	crypt_info->ci_data_mode = ctx.contents_encryption_mode;
 	crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
 	crypt_info->ci_ctfm = NULL;
-	crypt_info->ci_keyring_key = NULL;
 	memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
 				sizeof(crypt_info->ci_master_key));
 	if (S_ISREG(inode->i_mode))
@@ -197,7 +189,6 @@
 		keyring_key = NULL;
 		goto out;
 	}
-	crypt_info->ci_keyring_key = keyring_key;
 	BUG_ON(keyring_key->type != &key_type_logon);
 	ukp = user_key_payload(keyring_key);
 	if (ukp->datalen != sizeof(struct f2fs_encryption_key)) {
@@ -230,17 +221,12 @@
 	if (res)
 		goto out;
 
-	memzero_explicit(raw_key, sizeof(raw_key));
-	if (cmpxchg(&fi->i_crypt_info, NULL, crypt_info) != NULL) {
-		f2fs_free_crypt_info(crypt_info);
-		goto retry;
-	}
-	return 0;
-
+	if (cmpxchg(&fi->i_crypt_info, NULL, crypt_info) == NULL)
+		crypt_info = NULL;
 out:
 	if (res == -ENOKEY && !S_ISREG(inode->i_mode))
 		res = 0;
-
+	key_put(keyring_key);
 	f2fs_free_crypt_info(crypt_info);
 	memzero_explicit(raw_key, sizeof(raw_key));
 	return res;
diff --git a/fs/f2fs/crypto_policy.c b/fs/f2fs/crypto_policy.c
index d4a96af..884f3f0 100644
--- a/fs/f2fs/crypto_policy.c
+++ b/fs/f2fs/crypto_policy.c
@@ -89,6 +89,9 @@
 int f2fs_process_policy(const struct f2fs_encryption_policy *policy,
 			struct inode *inode)
 {
+	if (!inode_owner_or_capable(inode))
+		return -EACCES;
+
 	if (policy->version != 0)
 		return -EINVAL;
 
@@ -138,20 +141,38 @@
 int f2fs_is_child_context_consistent_with_parent(struct inode *parent,
 						struct inode *child)
 {
-	struct f2fs_crypt_info *parent_ci, *child_ci;
+	const struct f2fs_crypt_info *parent_ci, *child_ci;
+	struct f2fs_encryption_context parent_ctx, child_ctx;
 	int res;
 
-	if ((parent == NULL) || (child == NULL)) {
-		pr_err("parent %p child %p\n", parent, child);
-		BUG_ON(1);
-	}
+	/* No restrictions on file types which are never encrypted */
+	if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) &&
+	    !S_ISLNK(child->i_mode))
+		return 1;
 
-	/* no restrictions if the parent directory is not encrypted */
+	/* No restrictions if the parent directory is unencrypted */
 	if (!f2fs_encrypted_inode(parent))
 		return 1;
-	/* if the child directory is not encrypted, this is always a problem */
+
+	/* Encrypted directories must not contain unencrypted files */
 	if (!f2fs_encrypted_inode(child))
 		return 0;
+
+	/*
+	 * Both parent and child are encrypted, so verify they use the same
+	 * encryption policy.  Compare the fscrypt_info structs if the keys are
+	 * available, otherwise retrieve and compare the fscrypt_contexts.
+	 *
+	 * Note that the fscrypt_context retrieval will be required frequently
+	 * when accessing an encrypted directory tree without the key.
+	 * Performance-wise this is not a big deal because we already don't
+	 * really optimize for file access without the key (to the extent that
+	 * such access is even possible), given that any attempted access
+	 * already causes a fscrypt_context retrieval and keyring search.
+	 *
+	 * In any case, if an unexpected error occurs, fall back to "forbidden".
+	 */
+
 	res = f2fs_get_encryption_info(parent);
 	if (res)
 		return 0;
@@ -160,17 +181,35 @@
 		return 0;
 	parent_ci = F2FS_I(parent)->i_crypt_info;
 	child_ci = F2FS_I(child)->i_crypt_info;
-	if (!parent_ci && !child_ci)
-		return 1;
-	if (!parent_ci || !child_ci)
+	if (parent_ci && child_ci) {
+		return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key,
+			      F2FS_KEY_DESCRIPTOR_SIZE) == 0 &&
+			(parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
+			(parent_ci->ci_filename_mode ==
+			 child_ci->ci_filename_mode) &&
+			(parent_ci->ci_flags == child_ci->ci_flags);
+	}
+
+	res = f2fs_getxattr(parent, F2FS_XATTR_INDEX_ENCRYPTION,
+			    F2FS_XATTR_NAME_ENCRYPTION_CONTEXT,
+			    &parent_ctx, sizeof(parent_ctx), NULL);
+	if (res != sizeof(parent_ctx))
 		return 0;
 
-	return (memcmp(parent_ci->ci_master_key,
-			child_ci->ci_master_key,
-			F2FS_KEY_DESCRIPTOR_SIZE) == 0 &&
-		(parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
-		(parent_ci->ci_filename_mode == child_ci->ci_filename_mode) &&
-		(parent_ci->ci_flags == child_ci->ci_flags));
+	res = f2fs_getxattr(child, F2FS_XATTR_INDEX_ENCRYPTION,
+			    F2FS_XATTR_NAME_ENCRYPTION_CONTEXT,
+			    &child_ctx, sizeof(child_ctx), NULL);
+	if (res != sizeof(child_ctx))
+		return 0;
+
+	return memcmp(parent_ctx.master_key_descriptor,
+		      child_ctx.master_key_descriptor,
+		      F2FS_KEY_DESCRIPTOR_SIZE) == 0 &&
+		(parent_ctx.contents_encryption_mode ==
+		 child_ctx.contents_encryption_mode) &&
+		(parent_ctx.filenames_encryption_mode ==
+		 child_ctx.filenames_encryption_mode) &&
+		(parent_ctx.flags == child_ctx.flags);
 }
 
 /**
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 972eab7..8936044 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -26,6 +26,7 @@
 #include "segment.h"
 #include "trace.h"
 #include <trace/events/f2fs.h>
+#include <trace/events/android_fs.h>
 
 static void f2fs_read_end_io(struct bio *bio)
 {
@@ -1401,6 +1402,16 @@
 	struct dnode_of_data dn;
 	int err = 0;
 
+	if (trace_android_fs_datawrite_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_datawrite_start(inode, pos, len,
+						 current->pid, path,
+						 current->comm);
+	}
 	trace_f2fs_write_begin(inode, pos, len, flags);
 
 	f2fs_balance_fs(sbi);
@@ -1529,6 +1540,7 @@
 {
 	struct inode *inode = page->mapping->host;
 
+	trace_android_fs_datawrite_end(inode, pos, len);
 	trace_f2fs_write_end(inode, pos, len, copied);
 
 	set_page_dirty(page);
@@ -1582,6 +1594,28 @@
 
 	trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
 
+	if (trace_android_fs_dataread_start_enabled() &&
+	    (iov_iter_rw(iter) == READ)) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_dataread_start(inode, offset,
+						count, current->pid, path,
+						current->comm);
+	}
+	if (trace_android_fs_datawrite_start_enabled() &&
+	    (iov_iter_rw(iter) == WRITE)) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_datawrite_start(inode, offset, count,
+						 current->pid, path,
+						 current->comm);
+	}
 	if (iov_iter_rw(iter) == WRITE) {
 		__allocate_data_blocks(inode, offset, count);
 		if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
@@ -1595,6 +1629,13 @@
 	if (err < 0 && iov_iter_rw(iter) == WRITE)
 		f2fs_write_failed(mapping, offset + count);
 
+	if (trace_android_fs_dataread_start_enabled() &&
+	    (iov_iter_rw(iter) == READ))
+		trace_android_fs_dataread_end(inode, offset, count);
+	if (trace_android_fs_datawrite_start_enabled() &&
+	    (iov_iter_rw(iter) == WRITE))
+		trace_android_fs_datawrite_end(inode, offset, count);
+
 	trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
 
 	return err;
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 478e5d5..24d6a51 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -352,6 +352,7 @@
 }
 
 static const struct file_operations stat_fops = {
+	.owner = THIS_MODULE,
 	.open = stat_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 7c1678b..60972a5 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -124,19 +124,29 @@
 
 		de = &d->dentry[bit_pos];
 
-		/* encrypted case */
+		if (de->hash_code != namehash)
+			goto not_match;
+
 		de_name.name = d->filename[bit_pos];
 		de_name.len = le16_to_cpu(de->name_len);
 
-		/* show encrypted name */
-		if (fname->hash) {
-			if (de->hash_code == fname->hash)
-				goto found;
-		} else if (de_name.len == name->len &&
-			de->hash_code == namehash &&
-			!memcmp(de_name.name, name->name, name->len))
+#ifdef CONFIG_F2FS_FS_ENCRYPTION
+		if (unlikely(!name->name)) {
+			if (fname->usr_fname->name[0] == '_') {
+				if (de_name.len > 32 &&
+					!memcmp(de_name.name + ((de_name.len - 17) & ~15),
+						fname->crypto_buf.name + 8, 16))
+					goto found;
+				goto not_match;
+			}
+			name->name = fname->crypto_buf.name;
+			name->len = fname->crypto_buf.len;
+		}
+#endif
+		if (de_name.len == name->len &&
+				!memcmp(de_name.name, name->name, name->len))
 			goto found;
-
+not_match:
 		if (max_slots && max_len > *max_slots)
 			*max_slots = max_len;
 		max_len = 0;
@@ -170,7 +180,7 @@
 	int max_slots;
 	f2fs_hash_t namehash;
 
-	namehash = f2fs_dentry_hash(&name);
+	namehash = f2fs_dentry_hash(&name, fname);
 
 	f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH);
 
@@ -547,7 +557,7 @@
 
 	level = 0;
 	slots = GET_DENTRY_SLOTS(new_name.len);
-	dentry_hash = f2fs_dentry_hash(&new_name);
+	dentry_hash = f2fs_dentry_hash(&new_name, NULL);
 
 	current_depth = F2FS_I(dir)->i_current_depth;
 	if (F2FS_I(dir)->chash == dentry_hash) {
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 9db5500..2871576 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1722,7 +1722,8 @@
 /*
  * hash.c
  */
-f2fs_hash_t f2fs_dentry_hash(const struct qstr *);
+f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info,
+				struct f2fs_filename *fname);
 
 /*
  * node.c
@@ -2149,7 +2150,6 @@
 
 /* crypto_key.c */
 void f2fs_free_encryption_info(struct inode *, struct f2fs_crypt_info *);
-int _f2fs_get_encryption_info(struct inode *inode);
 
 /* crypto_fname.c */
 bool f2fs_valid_filenames_enc_mode(uint32_t);
@@ -2170,18 +2170,7 @@
 
 int f2fs_has_encryption_key(struct inode *);
 
-static inline int f2fs_get_encryption_info(struct inode *inode)
-{
-	struct f2fs_crypt_info *ci = F2FS_I(inode)->i_crypt_info;
-
-	if (!ci ||
-		(ci->ci_keyring_key &&
-		 (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
-					       (1 << KEY_FLAG_REVOKED) |
-					       (1 << KEY_FLAG_DEAD)))))
-		return _f2fs_get_encryption_info(inode);
-	return 0;
-}
+int f2fs_get_encryption_info(struct inode *inode);
 
 void f2fs_fname_crypto_free_buffer(struct f2fs_str *);
 int f2fs_fname_setup_filename(struct inode *, const struct qstr *,
diff --git a/fs/f2fs/f2fs_crypto.h b/fs/f2fs/f2fs_crypto.h
index c2c1c2b..f113f1a 100644
--- a/fs/f2fs/f2fs_crypto.h
+++ b/fs/f2fs/f2fs_crypto.h
@@ -79,7 +79,6 @@
 	char		ci_filename_mode;
 	char		ci_flags;
 	struct crypto_ablkcipher *ci_ctfm;
-	struct key	*ci_keyring_key;
 	char		ci_master_key[F2FS_KEY_DESCRIPTOR_SIZE];
 };
 
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index a197215..4b449d2 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1535,12 +1535,19 @@
 #ifdef CONFIG_F2FS_FS_ENCRYPTION
 	struct f2fs_encryption_policy policy;
 	struct inode *inode = file_inode(filp);
+	int err;
 
 	if (copy_from_user(&policy, (struct f2fs_encryption_policy __user *)arg,
 				sizeof(policy)))
 		return -EFAULT;
 
-	return f2fs_process_policy(&policy, inode);
+	mutex_lock(&inode->i_mutex);
+
+	err = f2fs_process_policy(&policy, inode);
+
+	mutex_unlock(&inode->i_mutex);
+
+	return err;
 #else
 	return -EOPNOTSUPP;
 #endif
diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c
index 71b7206..b238d2f 100644
--- a/fs/f2fs/hash.c
+++ b/fs/f2fs/hash.c
@@ -70,7 +70,8 @@
 		*buf++ = pad;
 }
 
-f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info)
+f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info,
+				struct f2fs_filename *fname)
 {
 	__u32 hash;
 	f2fs_hash_t f2fs_hash;
@@ -79,6 +80,10 @@
 	const unsigned char *name = name_info->name;
 	size_t len = name_info->len;
 
+	/* encrypted bigname case */
+	if (fname && !fname->disk_name.name)
+		return cpu_to_le32(fname->hash);
+
 	if (is_dot_dotdot(name_info))
 		return 0;
 
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index bda7126..f35f3eb 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -13,6 +13,7 @@
 
 #include "f2fs.h"
 #include "node.h"
+#include <trace/events/android_fs.h>
 
 bool f2fs_may_inline_data(struct inode *inode)
 {
@@ -84,14 +85,29 @@
 {
 	struct page *ipage;
 
+	if (trace_android_fs_dataread_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_dataread_start(inode, page_offset(page),
+						PAGE_SIZE, current->pid,
+						path, current->comm);
+	}
+
 	ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
 	if (IS_ERR(ipage)) {
+		trace_android_fs_dataread_end(inode, page_offset(page),
+					      PAGE_SIZE);
 		unlock_page(page);
 		return PTR_ERR(ipage);
 	}
 
 	if (!f2fs_has_inline_data(inode)) {
 		f2fs_put_page(ipage, 1);
+		trace_android_fs_dataread_end(inode, page_offset(page),
+					      PAGE_SIZE);
 		return -EAGAIN;
 	}
 
@@ -102,6 +118,8 @@
 
 	SetPageUptodate(page);
 	f2fs_put_page(ipage, 1);
+	trace_android_fs_dataread_end(inode, page_offset(page),
+				      PAGE_SIZE);
 	unlock_page(page);
 	return 0;
 }
@@ -303,7 +321,7 @@
 	if (IS_ERR(ipage))
 		return NULL;
 
-	namehash = f2fs_dentry_hash(&name);
+	namehash = f2fs_dentry_hash(&name, fname);
 
 	inline_dentry = inline_data_addr(ipage);
 
@@ -468,7 +486,7 @@
 
 	f2fs_wait_on_page_writeback(ipage, NODE);
 
-	name_hash = f2fs_dentry_hash(name);
+	name_hash = f2fs_dentry_hash(name, NULL);
 	make_dentry_ptr(NULL, &d, (void *)dentry_blk, 2);
 	f2fs_update_dentry(ino, mode, &d, name, name_hash, bit_pos);
 
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index f77b325..7965957 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -1623,6 +1623,10 @@
 
 static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
 {
+	struct f2fs_summary_block *s_sits =
+		CURSEG_I(sbi, CURSEG_COLD_DATA)->sum_blk;
+	struct f2fs_summary_block *s_nats =
+		CURSEG_I(sbi, CURSEG_HOT_DATA)->sum_blk;
 	int type = CURSEG_HOT_DATA;
 	int err;
 
@@ -1649,6 +1653,11 @@
 			return err;
 	}
 
+	/* sanity check for summary blocks */
+	if (nats_in_cursum(s_nats) > NAT_JOURNAL_ENTRIES ||
+			sits_in_cursum(s_sits) > SIT_JOURNAL_ENTRIES)
+		return -EINVAL;
+
 	return 0;
 }
 
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 3a65e01..2ac3417 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -918,6 +918,79 @@
 	return result;
 }
 
+static inline bool sanity_check_area_boundary(struct super_block *sb,
+					struct f2fs_super_block *raw_super)
+{
+	u32 segment0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr);
+	u32 cp_blkaddr = le32_to_cpu(raw_super->cp_blkaddr);
+	u32 sit_blkaddr = le32_to_cpu(raw_super->sit_blkaddr);
+	u32 nat_blkaddr = le32_to_cpu(raw_super->nat_blkaddr);
+	u32 ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
+	u32 main_blkaddr = le32_to_cpu(raw_super->main_blkaddr);
+	u32 segment_count_ckpt = le32_to_cpu(raw_super->segment_count_ckpt);
+	u32 segment_count_sit = le32_to_cpu(raw_super->segment_count_sit);
+	u32 segment_count_nat = le32_to_cpu(raw_super->segment_count_nat);
+	u32 segment_count_ssa = le32_to_cpu(raw_super->segment_count_ssa);
+	u32 segment_count_main = le32_to_cpu(raw_super->segment_count_main);
+	u32 segment_count = le32_to_cpu(raw_super->segment_count);
+	u32 log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
+
+	if (segment0_blkaddr != cp_blkaddr) {
+		f2fs_msg(sb, KERN_INFO,
+			"Mismatch start address, segment0(%u) cp_blkaddr(%u)",
+			segment0_blkaddr, cp_blkaddr);
+		return true;
+	}
+
+	if (cp_blkaddr + (segment_count_ckpt << log_blocks_per_seg) !=
+							sit_blkaddr) {
+		f2fs_msg(sb, KERN_INFO,
+			"Wrong CP boundary, start(%u) end(%u) blocks(%u)",
+			cp_blkaddr, sit_blkaddr,
+			segment_count_ckpt << log_blocks_per_seg);
+		return true;
+	}
+
+	if (sit_blkaddr + (segment_count_sit << log_blocks_per_seg) !=
+							nat_blkaddr) {
+		f2fs_msg(sb, KERN_INFO,
+			"Wrong SIT boundary, start(%u) end(%u) blocks(%u)",
+			sit_blkaddr, nat_blkaddr,
+			segment_count_sit << log_blocks_per_seg);
+		return true;
+	}
+
+	if (nat_blkaddr + (segment_count_nat << log_blocks_per_seg) !=
+							ssa_blkaddr) {
+		f2fs_msg(sb, KERN_INFO,
+			"Wrong NAT boundary, start(%u) end(%u) blocks(%u)",
+			nat_blkaddr, ssa_blkaddr,
+			segment_count_nat << log_blocks_per_seg);
+		return true;
+	}
+
+	if (ssa_blkaddr + (segment_count_ssa << log_blocks_per_seg) !=
+							main_blkaddr) {
+		f2fs_msg(sb, KERN_INFO,
+			"Wrong SSA boundary, start(%u) end(%u) blocks(%u)",
+			ssa_blkaddr, main_blkaddr,
+			segment_count_ssa << log_blocks_per_seg);
+		return true;
+	}
+
+	if (main_blkaddr + (segment_count_main << log_blocks_per_seg) !=
+		segment0_blkaddr + (segment_count << log_blocks_per_seg)) {
+		f2fs_msg(sb, KERN_INFO,
+			"Wrong MAIN_AREA boundary, start(%u) end(%u) blocks(%u)",
+			main_blkaddr,
+			segment0_blkaddr + (segment_count << log_blocks_per_seg),
+			segment_count_main << log_blocks_per_seg);
+		return true;
+	}
+
+	return false;
+}
+
 static int sanity_check_raw_super(struct super_block *sb,
 			struct f2fs_super_block *raw_super)
 {
@@ -947,6 +1020,14 @@
 		return 1;
 	}
 
+	/* check log blocks per segment */
+	if (le32_to_cpu(raw_super->log_blocks_per_seg) != 9) {
+		f2fs_msg(sb, KERN_INFO,
+			"Invalid log blocks per segment (%u)\n",
+			le32_to_cpu(raw_super->log_blocks_per_seg));
+		return 1;
+	}
+
 	/* Currently, support 512/1024/2048/4096 bytes sector size */
 	if (le32_to_cpu(raw_super->log_sectorsize) >
 				F2FS_MAX_LOG_SECTOR_SIZE ||
@@ -965,6 +1046,30 @@
 			le32_to_cpu(raw_super->log_sectorsize));
 		return 1;
 	}
+
+	/* check reserved ino info */
+	if (le32_to_cpu(raw_super->node_ino) != 1 ||
+		le32_to_cpu(raw_super->meta_ino) != 2 ||
+		le32_to_cpu(raw_super->root_ino) != 3) {
+		f2fs_msg(sb, KERN_INFO,
+			"Invalid Fs Meta Ino: node(%u) meta(%u) root(%u)",
+			le32_to_cpu(raw_super->node_ino),
+			le32_to_cpu(raw_super->meta_ino),
+			le32_to_cpu(raw_super->root_ino));
+		return 1;
+	}
+
+	if (le32_to_cpu(raw_super->segment_count) > F2FS_MAX_SEGMENT) {
+		f2fs_msg(sb, KERN_INFO,
+			"Invalid segment count (%u)",
+			le32_to_cpu(raw_super->segment_count));
+		return 1;
+	}
+
+	/* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */
+	if (sanity_check_area_boundary(sb, raw_super))
+		return 1;
+
 	return 0;
 }
 
@@ -973,6 +1078,8 @@
 	unsigned int total, fsmeta;
 	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	unsigned int main_segs, blocks_per_seg;
+	int i;
 
 	total = le32_to_cpu(raw_super->segment_count);
 	fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
@@ -984,6 +1091,22 @@
 	if (unlikely(fsmeta >= total))
 		return 1;
 
+	main_segs = le32_to_cpu(sbi->raw_super->segment_count_main);
+	blocks_per_seg = sbi->blocks_per_seg;
+
+	for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) {
+		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
+		    le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg) {
+			return 1;
+		}
+	}
+	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
+		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
+		    le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg) {
+			return 1;
+		}
+	}
+
 	if (unlikely(f2fs_cp_error(sbi))) {
 		f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck");
 		return 1;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 509411d..cf644d5 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -1269,6 +1269,16 @@
 	return 0;
 }
 
+static void fat_dummy_inode_init(struct inode *inode)
+{
+	/* Initialize this dummy inode to work as no-op. */
+	MSDOS_I(inode)->mmu_private = 0;
+	MSDOS_I(inode)->i_start = 0;
+	MSDOS_I(inode)->i_logstart = 0;
+	MSDOS_I(inode)->i_attrs = 0;
+	MSDOS_I(inode)->i_pos = 0;
+}
+
 static int fat_read_root(struct inode *inode)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
@@ -1713,12 +1723,13 @@
 	fat_inode = new_inode(sb);
 	if (!fat_inode)
 		goto out_fail;
-	MSDOS_I(fat_inode)->i_pos = 0;
+	fat_dummy_inode_init(fat_inode);
 	sbi->fat_inode = fat_inode;
 
 	fsinfo_inode = new_inode(sb);
 	if (!fsinfo_inode)
 		goto out_fail;
+	fat_dummy_inode_init(fsinfo_inode);
 	fsinfo_inode->i_ino = MSDOS_FSINFO_INO;
 	sbi->fsinfo_inode = fsinfo_inode;
 	insert_inode_hash(fsinfo_inode);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index ee85cd4..6237645 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -740,16 +740,10 @@
 	 * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
 	 * is defined as O_NONBLOCK on some platforms and not on others.
 	 */
-	BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
-		O_RDONLY	| O_WRONLY	| O_RDWR	|
-		O_CREAT		| O_EXCL	| O_NOCTTY	|
-		O_TRUNC		| O_APPEND	| /* O_NONBLOCK	| */
-		__O_SYNC	| O_DSYNC	| FASYNC	|
-		O_DIRECT	| O_LARGEFILE	| O_DIRECTORY	|
-		O_NOFOLLOW	| O_NOATIME	| O_CLOEXEC	|
-		__FMODE_EXEC	| O_PATH	| __O_TMPFILE	|
-		__FMODE_NONOTIFY
-		));
+	BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
+		HWEIGHT32(
+			(VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
+			__FMODE_EXEC | __FMODE_NONOTIFY));
 
 	fasync_cache = kmem_cache_create("fasync_cache",
 		sizeof(struct fasync_struct), 0, SLAB_PANIC, NULL);
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index 7dca743..940c683 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -44,6 +44,7 @@
 	if (old_pwd.dentry)
 		path_put(&old_pwd);
 }
+EXPORT_SYMBOL(set_fs_pwd);
 
 static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
 {
@@ -89,6 +90,7 @@
 	path_put(&fs->pwd);
 	kmem_cache_free(fs_cachep, fs);
 }
+EXPORT_SYMBOL(free_fs_struct);
 
 void exit_fs(struct task_struct *tsk)
 {
@@ -127,6 +129,7 @@
 	}
 	return fs;
 }
+EXPORT_SYMBOL_GPL(copy_fs_struct);
 
 int unshare_fs_struct(void)
 {
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index 43040721..40d6107 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -542,6 +542,7 @@
 		hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
 			if (invalidate)
 				set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
+			clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
 			fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
 		}
 	} else {
@@ -560,6 +561,10 @@
 		wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
 				 TASK_UNINTERRUPTIBLE);
 
+	/* Make sure any pending writes are cancelled. */
+	if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
+		fscache_invalidate_writes(cookie);
+
 	/* Reset the cookie state if it wasn't relinquished */
 	if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
 		atomic_inc(&cookie->n_active);
diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c
index 9b28649..a8aa00b 100644
--- a/fs/fscache/netfs.c
+++ b/fs/fscache/netfs.c
@@ -48,6 +48,7 @@
 	cookie->flags		= 1 << FSCACHE_COOKIE_ENABLED;
 
 	spin_lock_init(&cookie->lock);
+	spin_lock_init(&cookie->stores_lock);
 	INIT_HLIST_HEAD(&cookie->backing_objects);
 
 	/* check the netfs type is not already present */
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index 9e792e3..7a182c8 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -30,6 +30,7 @@
 static const struct fscache_state *fscache_object_available(struct fscache_object *, int);
 static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int);
 static const struct fscache_state *fscache_update_object(struct fscache_object *, int);
+static const struct fscache_state *fscache_object_dead(struct fscache_object *, int);
 
 #define __STATE_NAME(n) fscache_osm_##n
 #define STATE(n) (&__STATE_NAME(n))
@@ -91,7 +92,7 @@
 static WORK_STATE(KILL_OBJECT,		"KILL", fscache_kill_object);
 static WORK_STATE(KILL_DEPENDENTS,	"KDEP", fscache_kill_dependents);
 static WORK_STATE(DROP_OBJECT,		"DROP", fscache_drop_object);
-static WORK_STATE(OBJECT_DEAD,		"DEAD", (void*)2UL);
+static WORK_STATE(OBJECT_DEAD,		"DEAD", fscache_object_dead);
 
 static WAIT_STATE(WAIT_FOR_INIT,	"?INI",
 		  TRANSIT_TO(INIT_OBJECT,	1 << FSCACHE_OBJECT_EV_NEW_CHILD));
@@ -229,6 +230,10 @@
 	event = -1;
 	if (new_state == NO_TRANSIT) {
 		_debug("{OBJ%x} %s notrans", object->debug_id, state->name);
+		if (unlikely(state == STATE(OBJECT_DEAD))) {
+			_leave(" [dead]");
+			return;
+		}
 		fscache_enqueue_object(object);
 		event_mask = object->oob_event_mask;
 		goto unmask_events;
@@ -239,7 +244,7 @@
 	object->state = state = new_state;
 
 	if (state->work) {
-		if (unlikely(state->work == ((void *)2UL))) {
+		if (unlikely(state == STATE(OBJECT_DEAD))) {
 			_leave(" [dead]");
 			return;
 		}
@@ -645,6 +650,12 @@
 	fscache_mark_object_dead(object);
 	object->oob_event_mask = 0;
 
+	if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
+		/* Reject any new read/write ops and abort any that are pending. */
+		clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
+		fscache_cancel_all_ops(object);
+	}
+
 	if (list_empty(&object->dependents) &&
 	    object->n_ops == 0 &&
 	    object->n_children == 0)
@@ -1077,3 +1088,20 @@
 	}
 }
 EXPORT_SYMBOL(fscache_object_mark_killed);
+
+/*
+ * The object is dead.  We can get here if an object gets queued by an event
+ * that would lead to its death (such as EV_KILL) when the dispatcher is
+ * already running (and so can be requeued) but hasn't yet cleared the event
+ * mask.
+ */
+static const struct fscache_state *fscache_object_dead(struct fscache_object *object,
+						       int event)
+{
+	if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD,
+			      &object->flags))
+		return NO_TRANSIT;
+
+	WARN(true, "FS-Cache object redispatched after death");
+	return NO_TRANSIT;
+}
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 8932c06..fbfec06 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -420,6 +420,10 @@
 static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
 {
 	spin_lock(&fiq->waitq.lock);
+	if (test_bit(FR_FINISHED, &req->flags)) {
+		spin_unlock(&fiq->waitq.lock);
+		return;
+	}
 	if (list_empty(&req->intr_entry)) {
 		list_add_tail(&req->intr_entry, &fiq->interrupts);
 		wake_up_locked(&fiq->waitq);
@@ -2091,7 +2095,6 @@
 		struct fuse_req *req;
 		req = list_entry(head->next, struct fuse_req, list);
 		req->out.h.error = -ECONNABORTED;
-		clear_bit(FR_PENDING, &req->flags);
 		clear_bit(FR_SENT, &req->flags);
 		list_del_init(&req->list);
 		request_end(fc, req);
@@ -2169,6 +2172,8 @@
 		spin_lock(&fiq->waitq.lock);
 		fiq->connected = 0;
 		list_splice_init(&fiq->pending, &to_end2);
+		list_for_each_entry(req, &to_end2, list)
+			clear_bit(FR_PENDING, &req->flags);
 		while (forget_pending(fiq))
 			kfree(dequeue_forget(fiq, 1, NULL));
 		wake_up_all_locked(&fiq->waitq);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 24df0a5..278caed 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1742,14 +1742,46 @@
 static int fuse_setattr(struct dentry *entry, struct iattr *attr)
 {
 	struct inode *inode = d_inode(entry);
+	struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
+	int ret;
 
 	if (!fuse_allow_current_process(get_fuse_conn(inode)))
 		return -EACCES;
 
-	if (attr->ia_valid & ATTR_FILE)
-		return fuse_do_setattr(inode, attr, attr->ia_file);
-	else
-		return fuse_do_setattr(inode, attr, NULL);
+	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
+		int kill;
+
+		attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
+				    ATTR_MODE);
+		/*
+		 * ia_mode calculation may have used stale i_mode.  Refresh and
+		 * recalculate.
+		 */
+		ret = fuse_do_getattr(inode, NULL, file);
+		if (ret)
+			return ret;
+
+		attr->ia_mode = inode->i_mode;
+		kill = should_remove_suid(entry);
+		if (kill & ATTR_KILL_SUID) {
+			attr->ia_valid |= ATTR_MODE;
+			attr->ia_mode &= ~S_ISUID;
+		}
+		if (kill & ATTR_KILL_SGID) {
+			attr->ia_valid |= ATTR_MODE;
+			attr->ia_mode &= ~S_ISGID;
+		}
+	}
+	if (!attr->ia_valid)
+		return 0;
+
+	ret = fuse_do_setattr(inode, attr, file);
+	if (!ret) {
+		/* Directory mode changed, may need to revalidate access */
+		if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
+			fuse_invalidate_entry_cache(entry);
+	}
+	return ret;
 }
 
 static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
@@ -1842,6 +1874,23 @@
 	return ret;
 }
 
+static int fuse_verify_xattr_list(char *list, size_t size)
+{
+	size_t origsize = size;
+
+	while (size) {
+		size_t thislen = strnlen(list, size);
+
+		if (!thislen || thislen == size)
+			return -EIO;
+
+		size -= thislen + 1;
+		list += thislen + 1;
+	}
+
+	return origsize;
+}
+
 static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
 {
 	struct inode *inode = d_inode(entry);
@@ -1877,6 +1926,8 @@
 	ret = fuse_simple_request(fc, &args);
 	if (!ret && !size)
 		ret = outarg.size;
+	if (ret > 0 && size)
+		ret = fuse_verify_xattr_list(list, ret);
 	if (ret == -ENOSYS) {
 		fc->no_listxattr = 1;
 		ret = -EOPNOTSUPP;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index c2e340d..11538a8 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -100,6 +100,7 @@
 			iput(req->misc.release.inode);
 			fuse_put_request(ff->fc, req);
 		} else if (sync) {
+			__set_bit(FR_FORCE, &req->flags);
 			__clear_bit(FR_BACKGROUND, &req->flags);
 			fuse_request_send(ff->fc, req);
 			iput(req->misc.release.inode);
@@ -417,6 +418,15 @@
 	fuse_sync_writes(inode);
 	mutex_unlock(&inode->i_mutex);
 
+	if (test_bit(AS_ENOSPC, &file->f_mapping->flags) &&
+	    test_and_clear_bit(AS_ENOSPC, &file->f_mapping->flags))
+		err = -ENOSPC;
+	if (test_bit(AS_EIO, &file->f_mapping->flags) &&
+	    test_and_clear_bit(AS_EIO, &file->f_mapping->flags))
+		err = -EIO;
+	if (err)
+		return err;
+
 	req = fuse_get_req_nofail_nopages(fc, file);
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.fh = ff->fh;
@@ -462,6 +472,21 @@
 		goto out;
 
 	fuse_sync_writes(inode);
+
+	/*
+	 * Due to implementation of fuse writeback
+	 * filemap_write_and_wait_range() does not catch errors.
+	 * We have to do this directly after fuse_sync_writes()
+	 */
+	if (test_bit(AS_ENOSPC, &file->f_mapping->flags) &&
+	    test_and_clear_bit(AS_ENOSPC, &file->f_mapping->flags))
+		err = -ENOSPC;
+	if (test_bit(AS_EIO, &file->f_mapping->flags) &&
+	    test_and_clear_bit(AS_EIO, &file->f_mapping->flags))
+		err = -EIO;
+	if (err)
+		goto out;
+
 	err = sync_inode_metadata(inode, 1);
 	if (err)
 		goto out;
@@ -516,13 +541,13 @@
 	req->out.args[0].size = count;
 }
 
-static void fuse_release_user_pages(struct fuse_req *req, int write)
+static void fuse_release_user_pages(struct fuse_req *req, bool should_dirty)
 {
 	unsigned i;
 
 	for (i = 0; i < req->num_pages; i++) {
 		struct page *page = req->pages[i];
-		if (write)
+		if (should_dirty)
 			set_page_dirty_lock(page);
 		put_page(page);
 	}
@@ -1307,6 +1332,7 @@
 		       loff_t *ppos, int flags)
 {
 	int write = flags & FUSE_DIO_WRITE;
+	bool should_dirty = !write && iter_is_iovec(iter);
 	int cuse = flags & FUSE_DIO_CUSE;
 	struct file *file = io->file;
 	struct inode *inode = file->f_mapping->host;
@@ -1351,7 +1377,7 @@
 			nres = fuse_send_read(req, io, pos, nbytes, owner);
 
 		if (!io->async)
-			fuse_release_user_pages(req, !write);
+			fuse_release_user_pages(req, should_dirty);
 		if (req->out.h.error) {
 			if (!res)
 				res = req->out.h.error;
@@ -1972,6 +1998,10 @@
 {
 	struct inode *inode = page->mapping->host;
 
+	/* Haven't copied anything?  Skip zeroing, size extending, dirtying. */
+	if (!copied)
+		goto unlock;
+
 	if (!PageUptodate(page)) {
 		/* Zero any unwritten bytes at the end of the page */
 		size_t endoff = (pos + copied) & ~PAGE_CACHE_MASK;
@@ -1982,6 +2012,8 @@
 
 	fuse_write_update_size(inode, pos + copied);
 	set_page_dirty(page);
+
+unlock:
 	unlock_page(page);
 	page_cache_release(page);
 
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 2913db2..0d5e8e5 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -926,7 +926,7 @@
 	arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
 		FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
 		FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ |
-		FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA |
+		FUSE_FLOCK_LOCKS | FUSE_HAS_IOCTL_DIR | FUSE_AUTO_INVAL_DATA |
 		FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO |
 		FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT;
 	req->in.h.opcode = FUSE_INIT;
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 1be3b06..ff0ac96 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -79,17 +79,11 @@
 	if (type == ACL_TYPE_ACCESS) {
 		umode_t mode = inode->i_mode;
 
-		error = posix_acl_equiv_mode(acl, &mode);
-		if (error < 0)
+		error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+		if (error)
 			return error;
-
-		if (error == 0)
-			acl = NULL;
-
-		if (mode != inode->i_mode) {
-			inode->i_mode = mode;
+		if (mode != inode->i_mode)
 			mark_inode_dirty(inode);
-		}
 	}
 
 	if (acl) {
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index ad8a5b7..a443c6e 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -760,7 +760,7 @@
 	int error;
 
 	error = get_leaf_nr(dip, index, &leaf_no);
-	if (!error)
+	if (!IS_ERR_VALUE(error))
 		error = get_leaf(dip, leaf_no, bh_out);
 
 	return error;
@@ -976,7 +976,7 @@
 
 	index = name->hash >> (32 - dip->i_depth);
 	error = get_leaf_nr(dip, index, &leaf_no);
-	if (error)
+	if (IS_ERR_VALUE(error))
 		return error;
 
 	/*  Get the old leaf block  */
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 32e7471..070901e 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -80,9 +80,9 @@
 
 static struct rhashtable gl_hash_table;
 
-void gfs2_glock_free(struct gfs2_glock *gl)
+static void gfs2_glock_dealloc(struct rcu_head *rcu)
 {
-	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+	struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);
 
 	if (gl->gl_ops->go_flags & GLOF_ASPACE) {
 		kmem_cache_free(gfs2_glock_aspace_cachep, gl);
@@ -90,6 +90,13 @@
 		kfree(gl->gl_lksb.sb_lvbptr);
 		kmem_cache_free(gfs2_glock_cachep, gl);
 	}
+}
+
+void gfs2_glock_free(struct gfs2_glock *gl)
+{
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+
+	call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
 	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
 		wake_up(&sdp->sd_glock_wait);
 }
@@ -651,9 +658,11 @@
 	struct kmem_cache *cachep;
 	int ret, tries = 0;
 
+	rcu_read_lock();
 	gl = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
 	if (gl && !lockref_get_not_dead(&gl->gl_lockref))
 		gl = NULL;
+	rcu_read_unlock();
 
 	*glp = gl;
 	if (gl)
@@ -721,15 +730,18 @@
 
 	if (ret == -EEXIST) {
 		ret = 0;
+		rcu_read_lock();
 		tmp = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
 		if (tmp == NULL || !lockref_get_not_dead(&tmp->gl_lockref)) {
 			if (++tries < 100) {
+				rcu_read_unlock();
 				cond_resched();
 				goto again;
 			}
 			tmp = NULL;
 			ret = -ENOMEM;
 		}
+		rcu_read_unlock();
 	} else {
 		WARN_ON_ONCE(ret);
 	}
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index de7b4f9..4a9077e 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -207,7 +207,7 @@
 	struct gfs2_sbd *ln_sbd;
 	u64 ln_number;
 	unsigned int ln_type;
-};
+} __packed __aligned(sizeof(int));
 
 #define lm_name_equal(name1, name2) \
         (((name1)->ln_number == (name2)->ln_number) &&	\
@@ -367,6 +367,7 @@
 			loff_t end;
 		} gl_vm;
 	};
+	struct rcu_head gl_rcu;
 	struct rhash_head gl_node;
 };
 
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c
index df0c9af..71b3087 100644
--- a/fs/hfsplus/posix_acl.c
+++ b/fs/hfsplus/posix_acl.c
@@ -68,8 +68,8 @@
 	case ACL_TYPE_ACCESS:
 		xattr_name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			err = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (err < 0)
+			err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (err)
 				return err;
 		}
 		err = 0;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 5a7b322..f34d6f5 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -959,10 +959,11 @@
 
 	if (S_ISLNK(root_inode->i_mode)) {
 		char *name = follow_link(host_root_path);
-		if (IS_ERR(name))
+		if (IS_ERR(name)) {
 			err = PTR_ERR(name);
-		else
-			err = read_name(root_inode, name);
+			goto out_put;
+		}
+		err = read_name(root_inode, name);
 		kfree(name);
 		if (err)
 			goto out_put;
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index a561591..3713fd5 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
+#include <linux/seq_file.h>
 
 /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
 
@@ -453,10 +454,6 @@
 	int lowercase, eas, chk, errs, chkdsk, timeshift;
 	int o;
 	struct hpfs_sb_info *sbi = hpfs_sb(s);
-	char *new_opts = kstrdup(data, GFP_KERNEL);
-
-	if (!new_opts)
-		return -ENOMEM;
 
 	sync_filesystem(s);
 
@@ -493,17 +490,44 @@
 
 	if (!(*flags & MS_RDONLY)) mark_dirty(s, 1);
 
-	replace_mount_options(s, new_opts);
-
 	hpfs_unlock(s);
 	return 0;
 
 out_err:
 	hpfs_unlock(s);
-	kfree(new_opts);
 	return -EINVAL;
 }
 
+static int hpfs_show_options(struct seq_file *seq, struct dentry *root)
+{
+	struct hpfs_sb_info *sbi = hpfs_sb(root->d_sb);
+
+	seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, sbi->sb_uid));
+	seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, sbi->sb_gid));
+	seq_printf(seq, ",umask=%03o", (~sbi->sb_mode & 0777));
+	if (sbi->sb_lowercase)
+		seq_printf(seq, ",case=lower");
+	if (!sbi->sb_chk)
+		seq_printf(seq, ",check=none");
+	if (sbi->sb_chk == 2)
+		seq_printf(seq, ",check=strict");
+	if (!sbi->sb_err)
+		seq_printf(seq, ",errors=continue");
+	if (sbi->sb_err == 2)
+		seq_printf(seq, ",errors=panic");
+	if (!sbi->sb_chkdsk)
+		seq_printf(seq, ",chkdsk=no");
+	if (sbi->sb_chkdsk == 2)
+		seq_printf(seq, ",chkdsk=always");
+	if (!sbi->sb_eas)
+		seq_printf(seq, ",eas=no");
+	if (sbi->sb_eas == 1)
+		seq_printf(seq, ",eas=ro");
+	if (sbi->sb_timeshift)
+		seq_printf(seq, ",timeshift=%d", sbi->sb_timeshift);
+	return 0;
+}
+
 /* Super operations */
 
 static const struct super_operations hpfs_sops =
@@ -514,7 +538,7 @@
 	.put_super	= hpfs_put_super,
 	.statfs		= hpfs_statfs,
 	.remount_fs	= hpfs_remount_fs,
-	.show_options	= generic_show_options,
+	.show_options	= hpfs_show_options,
 };
 
 static int hpfs_fill_super(struct super_block *s, void *options, int silent)
@@ -537,8 +561,6 @@
 
 	int o;
 
-	save_mount_options(s, options);
-
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi) {
 		return -ENOMEM;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 595ebdb..a17da8b5 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -191,7 +191,7 @@
 		addr = ALIGN(addr, huge_page_size(h));
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
diff --git a/fs/inode.c b/fs/inode.c
index 1be5f90..e89f127 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1715,7 +1715,7 @@
 }
 EXPORT_SYMBOL(dentry_needs_remove_privs);
 
-static int __remove_privs(struct dentry *dentry, int kill)
+static int __remove_privs(struct vfsmount *mnt, struct dentry *dentry, int kill)
 {
 	struct iattr newattrs;
 
@@ -1724,7 +1724,7 @@
 	 * Note we call this on write, so notify_change will not
 	 * encounter any conflicting delegations:
 	 */
-	return notify_change(dentry, &newattrs, NULL);
+	return notify_change2(mnt, dentry, &newattrs, NULL);
 }
 
 /*
@@ -1733,8 +1733,8 @@
  */
 int file_remove_privs(struct file *file)
 {
-	struct dentry *dentry = file->f_path.dentry;
-	struct inode *inode = d_inode(dentry);
+	struct dentry *dentry = file_dentry(file);
+	struct inode *inode = file_inode(file);
 	int kill;
 	int error = 0;
 
@@ -1742,11 +1742,11 @@
 	if (IS_NOSEC(inode))
 		return 0;
 
-	kill = file_needs_remove_privs(file);
+	kill = dentry_needs_remove_privs(dentry);
 	if (kill < 0)
 		return kill;
 	if (kill)
-		error = __remove_privs(dentry, kill);
+		error = __remove_privs(file->f_path.mnt, dentry, kill);
 	if (!error)
 		inode_has_no_xattr(inode);
 
diff --git a/fs/internal.h b/fs/internal.h
index 71859c4d..6387b35 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -84,9 +84,11 @@
  * super.c
  */
 extern int do_remount_sb(struct super_block *, int, void *, int);
+extern int do_remount_sb2(struct vfsmount *, struct super_block *, int,
+								void *, int);
 extern bool trylock_super(struct super_block *sb);
 extern struct dentry *mount_fs(struct file_system_type *,
-			       int, const char *, void *);
+			       int, const char *, struct vfsmount *, void *);
 extern struct super_block *user_get_super(dev_t);
 
 /*
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index d67a16f..350f67f 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -690,6 +690,11 @@
 	pri_bh = NULL;
 
 root_found:
+	/* We don't support read-write mounts */
+	if (!(s->s_flags & MS_RDONLY)) {
+		error = -EACCES;
+		goto out_freebh;
+	}
 
 	if (joliet_level && (pri == NULL || !opt.rock)) {
 		/* This is the case of Joliet with the norock mount flag.
@@ -1503,9 +1508,6 @@
 static struct dentry *isofs_mount(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
-	/* We don't support read-write mounts */
-	if (!(flags & MS_RDONLY))
-		return ERR_PTR(-EACCES);
 	return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
 }
 
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 735d752..204659a 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -203,6 +203,8 @@
 	int retnamlen = 0;
 	int truncate = 0;
 	int ret = 0;
+	char *p;
+	int len;
 
 	if (!ISOFS_SB(inode->i_sb)->s_rock)
 		return 0;
@@ -267,12 +269,17 @@
 					rr->u.NM.flags);
 				break;
 			}
-			if ((strlen(retname) + rr->len - 5) >= 254) {
+			len = rr->len - 5;
+			if (retnamlen + len >= 254) {
 				truncate = 1;
 				break;
 			}
-			strncat(retname, rr->u.NM.name, rr->len - 5);
-			retnamlen += rr->len - 5;
+			p = memchr(rr->u.NM.name, '\0', len);
+			if (unlikely(p))
+				len = p - rr->u.NM.name;
+			memcpy(retname + retnamlen, rr->u.NM.name, len);
+			retnamlen += len;
+			retname[retnamlen] = '\0';
 			break;
 		case SIG('R', 'E'):
 			kfree(rs.buffer);
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 36345fe..2d964ce 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -124,7 +124,7 @@
 	struct commit_header *tmp;
 	struct buffer_head *bh;
 	int ret;
-	struct timespec now = current_kernel_time();
+	struct timespec64 now = current_kernel_time64();
 
 	*cbh = NULL;
 
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index ca181e8..a2e7240 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -1156,6 +1156,7 @@
 		JBUFFER_TRACE(jh, "file as BJ_Reserved");
 		spin_lock(&journal->j_list_lock);
 		__jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
+		spin_unlock(&journal->j_list_lock);
 	} else if (jh->b_transaction == journal->j_committing_transaction) {
 		/* first access by this transaction */
 		jh->b_modified = 0;
@@ -1163,8 +1164,8 @@
 		JBUFFER_TRACE(jh, "set next transaction");
 		spin_lock(&journal->j_list_lock);
 		jh->b_next_transaction = transaction;
+		spin_unlock(&journal->j_list_lock);
 	}
-	spin_unlock(&journal->j_list_lock);
 	jbd_unlock_bh_state(bh);
 
 	/*
@@ -1875,7 +1876,9 @@
 
 	__blist_del_buffer(list, jh);
 	jh->b_jlist = BJ_None;
-	if (test_clear_buffer_jbddirty(bh))
+	if (transaction && is_journal_aborted(transaction->t_journal))
+		clear_buffer_jbddirty(bh);
+	else if (test_clear_buffer_jbddirty(bh))
 		mark_buffer_dirty(bh);	/* Expose it to the VM */
 }
 
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 2f7a3c0..f9f86f8 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -235,9 +235,10 @@
 	case ACL_TYPE_ACCESS:
 		xprefix = JFFS2_XPREFIX_ACL_ACCESS;
 		if (acl) {
-			umode_t mode = inode->i_mode;
-			rc = posix_acl_equiv_mode(acl, &mode);
-			if (rc < 0)
+			umode_t mode;
+
+			rc = posix_acl_update_mode(inode, &mode, &acl);
+			if (rc)
 				return rc;
 			if (inode->i_mode != mode) {
 				struct iattr attr;
@@ -249,8 +250,6 @@
 				if (rc < 0)
 					return rc;
 			}
-			if (rc == 0)
-				acl = NULL;
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 0c8ca83..9fad9f4 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -84,13 +84,11 @@
 	case ACL_TYPE_ACCESS:
 		ea_name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			rc = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (rc < 0)
+			rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (rc)
 				return rc;
 			inode->i_ctime = CURRENT_TIME;
 			mark_inode_dirty(inode);
-			if (rc == 0)
-				acl = NULL;
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 8f9176c..c8d58c5 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -758,7 +758,7 @@
 				sb->s_blocksize - offset : toread;
 
 		tmp_bh.b_state = 0;
-		tmp_bh.b_size = 1 << inode->i_blkbits;
+		tmp_bh.b_size = i_blocksize(inode);
 		err = jfs_get_block(inode, blk, &tmp_bh, 0);
 		if (err)
 			return err;
@@ -798,7 +798,7 @@
 				sb->s_blocksize - offset : towrite;
 
 		tmp_bh.b_state = 0;
-		tmp_bh.b_size = 1 << inode->i_blkbits;
+		tmp_bh.b_size = i_blocksize(inode);
 		err = jfs_get_block(inode, blk, &tmp_bh, 1);
 		if (err)
 			goto out;
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 7247252..6e9a912 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -833,21 +833,35 @@
 	mutex_lock(&kernfs_mutex);
 
 	list_for_each_entry(info, &kernfs_root(kn)->supers, node) {
+		struct kernfs_node *parent;
 		struct inode *inode;
-		struct dentry *dentry;
 
+		/*
+		 * We want fsnotify_modify() on @kn but as the
+		 * modifications aren't originating from userland don't
+		 * have the matching @file available.  Look up the inodes
+		 * and generate the events manually.
+		 */
 		inode = ilookup(info->sb, kn->ino);
 		if (!inode)
 			continue;
 
-		dentry = d_find_any_alias(inode);
-		if (dentry) {
-			fsnotify_parent(NULL, dentry, FS_MODIFY);
-			fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
-				 NULL, 0);
-			dput(dentry);
+		parent = kernfs_get_parent(kn);
+		if (parent) {
+			struct inode *p_inode;
+
+			p_inode = ilookup(info->sb, parent->ino);
+			if (p_inode) {
+				fsnotify(p_inode, FS_MODIFY | FS_EVENT_ON_CHILD,
+					 inode, FSNOTIFY_EVENT_INODE, kn->name, 0);
+				iput(p_inode);
+			}
+
+			kernfs_put(parent);
 		}
 
+		fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
+			 kn->name, 0);
 		iput(inode);
 	}
 
diff --git a/fs/locks.c b/fs/locks.c
index 6333263..8eddae2 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1602,7 +1602,7 @@
 {
 	struct file_lock *fl, *my_fl = NULL, *lease;
 	struct dentry *dentry = filp->f_path.dentry;
-	struct inode *inode = dentry->d_inode;
+	struct inode *inode = file_inode(filp);
 	struct file_lock_context *ctx;
 	bool is_deleg = (*flp)->fl_flags & FL_DELEG;
 	int error;
diff --git a/fs/mbcache2.c b/fs/mbcache2.c
new file mode 100644
index 0000000..5c3e1a8
--- /dev/null
+++ b/fs/mbcache2.c
@@ -0,0 +1,359 @@
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/list_bl.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mbcache2.h>
+
+/*
+ * Mbcache is a simple key-value store. Keys need not be unique, however
+ * key-value pairs are expected to be unique (we use this fact in
+ * mb2_cache_entry_delete_block()).
+ *
+ * Ext2 and ext4 use this cache for deduplication of extended attribute blocks.
+ * They use hash of a block contents as a key and block number as a value.
+ * That's why keys need not be unique (different xattr blocks may end up having
+ * the same hash). However block number always uniquely identifies a cache
+ * entry.
+ *
+ * We provide functions for creation and removal of entries, search by key,
+ * and a special "delete entry with given key-value pair" operation. Fixed
+ * size hash table is used for fast key lookups.
+ */
+
+struct mb2_cache {
+	/* Hash table of entries */
+	struct hlist_bl_head	*c_hash;
+	/* log2 of hash table size */
+	int			c_bucket_bits;
+	/* Protects c_lru_list, c_entry_count */
+	spinlock_t		c_lru_list_lock;
+	struct list_head	c_lru_list;
+	/* Number of entries in cache */
+	unsigned long		c_entry_count;
+	struct shrinker		c_shrink;
+};
+
+static struct kmem_cache *mb2_entry_cache;
+
+/*
+ * mb2_cache_entry_create - create entry in cache
+ * @cache - cache where the entry should be created
+ * @mask - gfp mask with which the entry should be allocated
+ * @key - key of the entry
+ * @block - block that contains data
+ *
+ * Creates entry in @cache with key @key and records that data is stored in
+ * block @block. The function returns -EBUSY if entry with the same key
+ * and for the same block already exists in cache. Otherwise 0 is returned.
+ */
+int mb2_cache_entry_create(struct mb2_cache *cache, gfp_t mask, u32 key,
+			   sector_t block)
+{
+	struct mb2_cache_entry *entry, *dup;
+	struct hlist_bl_node *dup_node;
+	struct hlist_bl_head *head;
+
+	entry = kmem_cache_alloc(mb2_entry_cache, mask);
+	if (!entry)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&entry->e_lru_list);
+	/* One ref for hash, one ref returned */
+	atomic_set(&entry->e_refcnt, 1);
+	entry->e_key = key;
+	entry->e_block = block;
+	head = &cache->c_hash[hash_32(key, cache->c_bucket_bits)];
+	entry->e_hash_list_head = head;
+	hlist_bl_lock(head);
+	hlist_bl_for_each_entry(dup, dup_node, head, e_hash_list) {
+		if (dup->e_key == key && dup->e_block == block) {
+			hlist_bl_unlock(head);
+			kmem_cache_free(mb2_entry_cache, entry);
+			return -EBUSY;
+		}
+	}
+	hlist_bl_add_head(&entry->e_hash_list, head);
+	hlist_bl_unlock(head);
+
+	spin_lock(&cache->c_lru_list_lock);
+	list_add_tail(&entry->e_lru_list, &cache->c_lru_list);
+	/* Grab ref for LRU list */
+	atomic_inc(&entry->e_refcnt);
+	cache->c_entry_count++;
+	spin_unlock(&cache->c_lru_list_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(mb2_cache_entry_create);
+
+void __mb2_cache_entry_free(struct mb2_cache_entry *entry)
+{
+	kmem_cache_free(mb2_entry_cache, entry);
+}
+EXPORT_SYMBOL(__mb2_cache_entry_free);
+
+static struct mb2_cache_entry *__entry_find(struct mb2_cache *cache,
+					    struct mb2_cache_entry *entry,
+					    u32 key)
+{
+	struct mb2_cache_entry *old_entry = entry;
+	struct hlist_bl_node *node;
+	struct hlist_bl_head *head;
+
+	if (entry)
+		head = entry->e_hash_list_head;
+	else
+		head = &cache->c_hash[hash_32(key, cache->c_bucket_bits)];
+	hlist_bl_lock(head);
+	if (entry && !hlist_bl_unhashed(&entry->e_hash_list))
+		node = entry->e_hash_list.next;
+	else
+		node = hlist_bl_first(head);
+	while (node) {
+		entry = hlist_bl_entry(node, struct mb2_cache_entry,
+				       e_hash_list);
+		if (entry->e_key == key) {
+			atomic_inc(&entry->e_refcnt);
+			goto out;
+		}
+		node = node->next;
+	}
+	entry = NULL;
+out:
+	hlist_bl_unlock(head);
+	if (old_entry)
+		mb2_cache_entry_put(cache, old_entry);
+
+	return entry;
+}
+
+/*
+ * mb2_cache_entry_find_first - find the first entry in cache with given key
+ * @cache: cache where we should search
+ * @key: key to look for
+ *
+ * Search in @cache for entry with key @key. Grabs reference to the first
+ * entry found and returns the entry.
+ */
+struct mb2_cache_entry *mb2_cache_entry_find_first(struct mb2_cache *cache,
+						   u32 key)
+{
+	return __entry_find(cache, NULL, key);
+}
+EXPORT_SYMBOL(mb2_cache_entry_find_first);
+
+/*
+ * mb2_cache_entry_find_next - find next entry in cache with the same
+ * @cache: cache where we should search
+ * @entry: entry to start search from
+ *
+ * Finds next entry in the hash chain which has the same key as @entry.
+ * If @entry is unhashed (which can happen when deletion of entry races
+ * with the search), finds the first entry in the hash chain. The function
+ * drops reference to @entry and returns with a reference to the found entry.
+ */
+struct mb2_cache_entry *mb2_cache_entry_find_next(struct mb2_cache *cache,
+						  struct mb2_cache_entry *entry)
+{
+	return __entry_find(cache, entry, entry->e_key);
+}
+EXPORT_SYMBOL(mb2_cache_entry_find_next);
+
+/* mb2_cache_entry_delete_block - remove information about block from cache
+ * @cache - cache we work with
+ * @key - key of the entry to remove
+ * @block - block containing data for @key
+ *
+ * Remove entry from cache @cache with key @key with data stored in @block.
+ */
+void mb2_cache_entry_delete_block(struct mb2_cache *cache, u32 key,
+				  sector_t block)
+{
+	struct hlist_bl_node *node;
+	struct hlist_bl_head *head;
+	struct mb2_cache_entry *entry;
+
+	head = &cache->c_hash[hash_32(key, cache->c_bucket_bits)];
+	hlist_bl_lock(head);
+	hlist_bl_for_each_entry(entry, node, head, e_hash_list) {
+		if (entry->e_key == key && entry->e_block == block) {
+			/* We keep hash list reference to keep entry alive */
+			hlist_bl_del_init(&entry->e_hash_list);
+			hlist_bl_unlock(head);
+			spin_lock(&cache->c_lru_list_lock);
+			if (!list_empty(&entry->e_lru_list)) {
+				list_del_init(&entry->e_lru_list);
+				cache->c_entry_count--;
+				atomic_dec(&entry->e_refcnt);
+			}
+			spin_unlock(&cache->c_lru_list_lock);
+			mb2_cache_entry_put(cache, entry);
+			return;
+		}
+	}
+	hlist_bl_unlock(head);
+}
+EXPORT_SYMBOL(mb2_cache_entry_delete_block);
+
+/* mb2_cache_entry_touch - cache entry got used
+ * @cache - cache the entry belongs to
+ * @entry - entry that got used
+ *
+ * Move entry in lru list to reflect the fact that it was used.
+ */
+void mb2_cache_entry_touch(struct mb2_cache *cache,
+			   struct mb2_cache_entry *entry)
+{
+	spin_lock(&cache->c_lru_list_lock);
+	if (!list_empty(&entry->e_lru_list))
+		list_move_tail(&cache->c_lru_list, &entry->e_lru_list);
+	spin_unlock(&cache->c_lru_list_lock);
+}
+EXPORT_SYMBOL(mb2_cache_entry_touch);
+
+static unsigned long mb2_cache_count(struct shrinker *shrink,
+				     struct shrink_control *sc)
+{
+	struct mb2_cache *cache = container_of(shrink, struct mb2_cache,
+					       c_shrink);
+
+	return cache->c_entry_count;
+}
+
+/* Shrink number of entries in cache */
+static unsigned long mb2_cache_scan(struct shrinker *shrink,
+				    struct shrink_control *sc)
+{
+	int nr_to_scan = sc->nr_to_scan;
+	struct mb2_cache *cache = container_of(shrink, struct mb2_cache,
+					      c_shrink);
+	struct mb2_cache_entry *entry;
+	struct hlist_bl_head *head;
+	unsigned int shrunk = 0;
+
+	spin_lock(&cache->c_lru_list_lock);
+	while (nr_to_scan-- && !list_empty(&cache->c_lru_list)) {
+		entry = list_first_entry(&cache->c_lru_list,
+					 struct mb2_cache_entry, e_lru_list);
+		list_del_init(&entry->e_lru_list);
+		cache->c_entry_count--;
+		/*
+		 * We keep LRU list reference so that entry doesn't go away
+		 * from under us.
+		 */
+		spin_unlock(&cache->c_lru_list_lock);
+		head = entry->e_hash_list_head;
+		hlist_bl_lock(head);
+		if (!hlist_bl_unhashed(&entry->e_hash_list)) {
+			hlist_bl_del_init(&entry->e_hash_list);
+			atomic_dec(&entry->e_refcnt);
+		}
+		hlist_bl_unlock(head);
+		if (mb2_cache_entry_put(cache, entry))
+			shrunk++;
+		cond_resched();
+		spin_lock(&cache->c_lru_list_lock);
+	}
+	spin_unlock(&cache->c_lru_list_lock);
+
+	return shrunk;
+}
+
+/*
+ * mb2_cache_create - create cache
+ * @bucket_bits: log2 of the hash table size
+ *
+ * Create cache for keys with 2^bucket_bits hash entries.
+ */
+struct mb2_cache *mb2_cache_create(int bucket_bits)
+{
+	struct mb2_cache *cache;
+	int bucket_count = 1 << bucket_bits;
+	int i;
+
+	if (!try_module_get(THIS_MODULE))
+		return NULL;
+
+	cache = kzalloc(sizeof(struct mb2_cache), GFP_KERNEL);
+	if (!cache)
+		goto err_out;
+	cache->c_bucket_bits = bucket_bits;
+	INIT_LIST_HEAD(&cache->c_lru_list);
+	spin_lock_init(&cache->c_lru_list_lock);
+	cache->c_hash = kmalloc(bucket_count * sizeof(struct hlist_bl_head),
+				GFP_KERNEL);
+	if (!cache->c_hash) {
+		kfree(cache);
+		goto err_out;
+	}
+	for (i = 0; i < bucket_count; i++)
+		INIT_HLIST_BL_HEAD(&cache->c_hash[i]);
+
+	cache->c_shrink.count_objects = mb2_cache_count;
+	cache->c_shrink.scan_objects = mb2_cache_scan;
+	cache->c_shrink.seeks = DEFAULT_SEEKS;
+	register_shrinker(&cache->c_shrink);
+
+	return cache;
+
+err_out:
+	module_put(THIS_MODULE);
+	return NULL;
+}
+EXPORT_SYMBOL(mb2_cache_create);
+
+/*
+ * mb2_cache_destroy - destroy cache
+ * @cache: the cache to destroy
+ *
+ * Free all entries in cache and cache itself. Caller must make sure nobody
+ * (except shrinker) can reach @cache when calling this.
+ */
+void mb2_cache_destroy(struct mb2_cache *cache)
+{
+	struct mb2_cache_entry *entry, *next;
+
+	unregister_shrinker(&cache->c_shrink);
+
+	/*
+	 * We don't bother with any locking. Cache must not be used at this
+	 * point.
+	 */
+	list_for_each_entry_safe(entry, next, &cache->c_lru_list, e_lru_list) {
+		if (!hlist_bl_unhashed(&entry->e_hash_list)) {
+			hlist_bl_del_init(&entry->e_hash_list);
+			atomic_dec(&entry->e_refcnt);
+		} else
+			WARN_ON(1);
+		list_del(&entry->e_lru_list);
+		WARN_ON(atomic_read(&entry->e_refcnt) != 1);
+		mb2_cache_entry_put(cache, entry);
+	}
+	kfree(cache->c_hash);
+	kfree(cache);
+	module_put(THIS_MODULE);
+}
+EXPORT_SYMBOL(mb2_cache_destroy);
+
+static int __init mb2cache_init(void)
+{
+	mb2_entry_cache = kmem_cache_create("mbcache",
+				sizeof(struct mb2_cache_entry), 0,
+				SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
+	BUG_ON(!mb2_entry_cache);
+	return 0;
+}
+
+static void __exit mb2cache_exit(void)
+{
+	kmem_cache_destroy(mb2_entry_cache);
+}
+
+module_init(mb2cache_init)
+module_exit(mb2cache_exit)
+
+MODULE_AUTHOR("Jan Kara <jack@suse.cz>");
+MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
+MODULE_LICENSE("GPL");
diff --git a/fs/mount.h b/fs/mount.h
index 14db05d..13a4ebb 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -13,6 +13,8 @@
 	u64			seq;	/* Sequence number to prevent loops */
 	wait_queue_head_t poll;
 	u64 event;
+	unsigned int		mounts; /* # of mounts in the namespace */
+	unsigned int		pending_mounts;
 };
 
 struct mnt_pcp {
@@ -86,7 +88,6 @@
 }
 
 extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *);
-extern struct mount *__lookup_mnt_last(struct vfsmount *, struct dentry *);
 
 extern int __legitimize_mnt(struct vfsmount *, unsigned);
 extern bool legitimize_mnt(struct vfsmount *, unsigned);
diff --git a/fs/mpage.c b/fs/mpage.c
index 1480d3a..f37bb01 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -30,6 +30,14 @@
 #include <linux/cleancache.h>
 #include "internal.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/android_fs.h>
+
+EXPORT_TRACEPOINT_SYMBOL(android_fs_datawrite_start);
+EXPORT_TRACEPOINT_SYMBOL(android_fs_datawrite_end);
+EXPORT_TRACEPOINT_SYMBOL(android_fs_dataread_start);
+EXPORT_TRACEPOINT_SYMBOL(android_fs_dataread_end);
+
 /*
  * I/O completion handler for multipage BIOs.
  *
@@ -47,6 +55,16 @@
 	struct bio_vec *bv;
 	int i;
 
+	if (trace_android_fs_dataread_end_enabled() &&
+	    (bio_data_dir(bio) == READ)) {
+		struct page *first_page = bio->bi_io_vec[0].bv_page;
+
+		if (first_page != NULL)
+			trace_android_fs_dataread_end(first_page->mapping->host,
+						      page_offset(first_page),
+						      bio->bi_iter.bi_size);
+	}
+
 	bio_for_each_segment_all(bv, bio, i) {
 		struct page *page = bv->bv_page;
 		page_endio(page, bio_data_dir(bio), bio->bi_error);
@@ -57,6 +75,24 @@
 
 static struct bio *mpage_bio_submit(int rw, struct bio *bio)
 {
+	if (trace_android_fs_dataread_start_enabled() && (rw == READ)) {
+		struct page *first_page = bio->bi_io_vec[0].bv_page;
+
+		if (first_page != NULL) {
+			char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+			path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    first_page->mapping->host);
+			trace_android_fs_dataread_start(
+				first_page->mapping->host,
+				page_offset(first_page),
+				bio->bi_iter.bi_size,
+				current->pid,
+				path,
+				current->comm);
+		}
+	}
 	bio->bi_end_io = mpage_end_io;
 	guard_bio_eod(rw, bio);
 	submit_bio(rw, bio);
@@ -111,7 +147,7 @@
 			SetPageUptodate(page);    
 			return;
 		}
-		create_empty_buffers(page, 1 << inode->i_blkbits, 0);
+		create_empty_buffers(page, i_blocksize(inode), 0);
 	}
 	head = page_buffers(page);
 	page_bh = head;
diff --git a/fs/namei.c b/fs/namei.c
index d8ee4da..d185869 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -373,9 +373,11 @@
  * flag in inode->i_opflags, that says "this has not special
  * permission function, use the fast case".
  */
-static inline int do_inode_permission(struct inode *inode, int mask)
+static inline int do_inode_permission(struct vfsmount *mnt, struct inode *inode, int mask)
 {
 	if (unlikely(!(inode->i_opflags & IOP_FASTPERM))) {
+		if (likely(mnt && inode->i_op->permission2))
+			return inode->i_op->permission2(mnt, inode, mask);
 		if (likely(inode->i_op->permission))
 			return inode->i_op->permission(inode, mask);
 
@@ -399,7 +401,7 @@
  * This does not check for a read-only file system.  You probably want
  * inode_permission().
  */
-int __inode_permission(struct inode *inode, int mask)
+int __inode_permission2(struct vfsmount *mnt, struct inode *inode, int mask)
 {
 	int retval;
 
@@ -411,7 +413,7 @@
 			return -EACCES;
 	}
 
-	retval = do_inode_permission(inode, mask);
+	retval = do_inode_permission(mnt, inode, mask);
 	if (retval)
 		return retval;
 
@@ -419,7 +421,14 @@
 	if (retval)
 		return retval;
 
-	return security_inode_permission(inode, mask);
+	retval = security_inode_permission(inode, mask);
+	return retval;
+}
+EXPORT_SYMBOL(__inode_permission2);
+
+int __inode_permission(struct inode *inode, int mask)
+{
+	return __inode_permission2(NULL, inode, mask);
 }
 EXPORT_SYMBOL(__inode_permission);
 
@@ -455,14 +464,20 @@
  *
  * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
  */
-int inode_permission(struct inode *inode, int mask)
+int inode_permission2(struct vfsmount *mnt, struct inode *inode, int mask)
 {
 	int retval;
 
 	retval = sb_permission(inode->i_sb, inode, mask);
 	if (retval)
 		return retval;
-	return __inode_permission(inode, mask);
+	return __inode_permission2(mnt, inode, mask);
+}
+EXPORT_SYMBOL(inode_permission2);
+
+int inode_permission(struct inode *inode, int mask)
+{
+	return inode_permission2(NULL, inode, mask);
 }
 EXPORT_SYMBOL(inode_permission);
 
@@ -887,6 +902,7 @@
 {
 	const struct inode *inode;
 	const struct inode *parent;
+	kuid_t puid;
 
 	if (!sysctl_protected_symlinks)
 		return 0;
@@ -902,7 +918,8 @@
 		return 0;
 
 	/* Allowed if parent directory and link owner match. */
-	if (uid_eq(parent->i_uid, inode->i_uid))
+	puid = parent->i_uid;
+	if (uid_valid(puid) && uid_eq(puid, inode->i_uid))
 		return 0;
 
 	if (nd->flags & LOOKUP_RCU)
@@ -1643,13 +1660,13 @@
 static inline int may_lookup(struct nameidata *nd)
 {
 	if (nd->flags & LOOKUP_RCU) {
-		int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
+		int err = inode_permission2(nd->path.mnt, nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
 		if (err != -ECHILD)
 			return err;
 		if (unlazy_walk(nd, NULL, 0))
 			return -ECHILD;
 	}
-	return inode_permission(nd->inode, MAY_EXEC);
+	return inode_permission2(nd->path.mnt, nd->inode, MAY_EXEC);
 }
 
 static inline int handle_dots(struct nameidata *nd, int type)
@@ -2003,11 +2020,12 @@
 	nd->depth = 0;
 	if (flags & LOOKUP_ROOT) {
 		struct dentry *root = nd->root.dentry;
+		struct vfsmount *mnt = nd->root.mnt;
 		struct inode *inode = root->d_inode;
 		if (*s) {
 			if (!d_can_lookup(root))
 				return ERR_PTR(-ENOTDIR);
-			retval = inode_permission(inode, MAY_EXEC);
+			retval = inode_permission2(mnt, inode, MAY_EXEC);
 			if (retval)
 				return ERR_PTR(retval);
 		}
@@ -2278,13 +2296,14 @@
 /**
  * lookup_one_len - filesystem helper to lookup single pathname component
  * @name:	pathname component to lookup
+ * @mnt:	mount we are looking up on
  * @base:	base directory to lookup from
  * @len:	maximum length @len should be interpreted to
  *
  * Note that this routine is purely a helper for filesystem usage and should
  * not be called by generic code.
  */
-struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
+struct dentry *lookup_one_len2(const char *name, struct vfsmount *mnt, struct dentry *base, int len)
 {
 	struct qstr this;
 	unsigned int c;
@@ -2318,12 +2337,18 @@
 			return ERR_PTR(err);
 	}
 
-	err = inode_permission(base->d_inode, MAY_EXEC);
+	err = inode_permission2(mnt, base->d_inode, MAY_EXEC);
 	if (err)
 		return ERR_PTR(err);
 
 	return __lookup_hash(&this, base, 0);
 }
+EXPORT_SYMBOL(lookup_one_len2);
+
+struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
+{
+	return lookup_one_len2(name, NULL, base, len);
+}
 EXPORT_SYMBOL(lookup_one_len);
 
 int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
@@ -2550,7 +2575,7 @@
  * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
  *     nfs_async_unlink().
  */
-static int may_delete(struct inode *dir, struct dentry *victim, bool isdir)
+static int may_delete(struct vfsmount *mnt, struct inode *dir, struct dentry *victim, bool isdir)
 {
 	struct inode *inode = d_backing_inode(victim);
 	int error;
@@ -2562,7 +2587,7 @@
 	BUG_ON(victim->d_parent->d_inode != dir);
 	audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
-	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
+	error = inode_permission2(mnt, dir, MAY_WRITE | MAY_EXEC);
 	if (error)
 		return error;
 	if (IS_APPEND(dir))
@@ -2593,14 +2618,14 @@
  *  3. We should have write and exec permissions on dir
  *  4. We can't do it if dir is immutable (done in permission())
  */
-static inline int may_create(struct inode *dir, struct dentry *child)
+static inline int may_create(struct vfsmount *mnt, struct inode *dir, struct dentry *child)
 {
 	audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE);
 	if (child->d_inode)
 		return -EEXIST;
 	if (IS_DEADDIR(dir))
 		return -ENOENT;
-	return inode_permission(dir, MAY_WRITE | MAY_EXEC);
+	return inode_permission2(mnt, dir, MAY_WRITE | MAY_EXEC);
 }
 
 /*
@@ -2647,10 +2672,10 @@
 }
 EXPORT_SYMBOL(unlock_rename);
 
-int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-		bool want_excl)
+int vfs_create2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry,
+		umode_t mode, bool want_excl)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(mnt, dir, dentry);
 	if (error)
 		return error;
 
@@ -2666,11 +2691,19 @@
 		fsnotify_create(dir, dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_create2);
+
+int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+		bool want_excl)
+{
+	return vfs_create2(NULL, dir, dentry, mode, want_excl);
+}
 EXPORT_SYMBOL(vfs_create);
 
 static int may_open(struct path *path, int acc_mode, int flag)
 {
 	struct dentry *dentry = path->dentry;
+	struct vfsmount *mnt = path->mnt;
 	struct inode *inode = dentry->d_inode;
 	int error;
 
@@ -2699,7 +2732,7 @@
 		break;
 	}
 
-	error = inode_permission(inode, acc_mode);
+	error = inode_permission2(mnt, inode, acc_mode);
 	if (error)
 		return error;
 
@@ -2734,7 +2767,7 @@
 	if (!error)
 		error = security_path_truncate(path);
 	if (!error) {
-		error = do_truncate(path->dentry, 0,
+		error = do_truncate2(path->mnt, path->dentry, 0,
 				    ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
 				    filp);
 	}
@@ -2755,7 +2788,7 @@
 	if (error)
 		return error;
 
-	error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
+	error = inode_permission2(dir->mnt, dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
 	if (error)
 		return error;
 
@@ -2906,22 +2939,10 @@
 		dentry = lookup_real(dir, dentry, nd->flags);
 		if (IS_ERR(dentry))
 			return PTR_ERR(dentry);
-
-		if (create_error) {
-			int open_flag = op->open_flag;
-
-			error = create_error;
-			if ((open_flag & O_EXCL)) {
-				if (!dentry->d_inode)
-					goto out;
-			} else if (!dentry->d_inode) {
-				goto out;
-			} else if ((open_flag & O_TRUNC) &&
-				   d_is_reg(dentry)) {
-				goto out;
-			}
-			/* will fail later, go on to get the right error */
-		}
+	}
+	if (create_error && !dentry->d_inode) {
+		error = create_error;
+		goto out;
 	}
 looked_up:
 	path->dentry = dentry;
@@ -2953,6 +2974,7 @@
 			bool got_write, int *opened)
 {
 	struct dentry *dir = nd->path.dentry;
+	struct vfsmount *mnt = nd->path.mnt;
 	struct inode *dir_inode = dir->d_inode;
 	struct dentry *dentry;
 	int error;
@@ -3000,7 +3022,7 @@
 		error = security_path_mknod(&nd->path, dentry, mode, 0);
 		if (error)
 			goto out_dput;
-		error = vfs_create(dir->d_inode, dentry, mode,
+		error = vfs_create2(mnt, dir->d_inode, dentry, mode,
 				   nd->flags & LOOKUP_EXCL);
 		if (error)
 			goto out_dput;
@@ -3262,7 +3284,7 @@
 		goto out;
 	dir = path.dentry->d_inode;
 	/* we want directory to be writable */
-	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
+	error = inode_permission2(path.mnt, dir, MAY_WRITE | MAY_EXEC);
 	if (error)
 		goto out2;
 	if (!dir->i_op->tmpfile) {
@@ -3496,9 +3518,9 @@
 }
 EXPORT_SYMBOL(user_path_create);
 
-int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
+int vfs_mknod2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(mnt, dir, dentry);
 
 	if (error)
 		return error;
@@ -3522,6 +3544,12 @@
 		fsnotify_create(dir, dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_mknod2);
+
+int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
+{
+	return vfs_mknod2(NULL, dir, dentry, mode, dev);
+}
 EXPORT_SYMBOL(vfs_mknod);
 
 static int may_mknod(umode_t mode)
@@ -3564,10 +3592,10 @@
 		goto out;
 	switch (mode & S_IFMT) {
 		case 0: case S_IFREG:
-			error = vfs_create(path.dentry->d_inode,dentry,mode,true);
+			error = vfs_create2(path.mnt, path.dentry->d_inode,dentry,mode,true);
 			break;
 		case S_IFCHR: case S_IFBLK:
-			error = vfs_mknod(path.dentry->d_inode,dentry,mode,
+			error = vfs_mknod2(path.mnt, path.dentry->d_inode,dentry,mode,
 					new_decode_dev(dev));
 			break;
 		case S_IFIFO: case S_IFSOCK:
@@ -3588,9 +3616,9 @@
 	return sys_mknodat(AT_FDCWD, filename, mode, dev);
 }
 
-int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+int vfs_mkdir2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, umode_t mode)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(mnt, dir, dentry);
 	unsigned max_links = dir->i_sb->s_max_links;
 
 	if (error)
@@ -3612,6 +3640,12 @@
 		fsnotify_mkdir(dir, dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_mkdir2);
+
+int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+	return vfs_mkdir2(NULL, dir, dentry, mode);
+}
 EXPORT_SYMBOL(vfs_mkdir);
 
 SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
@@ -3630,7 +3664,7 @@
 		mode &= ~current_umask();
 	error = security_path_mkdir(&path, dentry, mode);
 	if (!error)
-		error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
+		error = vfs_mkdir2(path.mnt, path.dentry->d_inode, dentry, mode);
 	done_path_create(&path, dentry);
 	if (retry_estale(error, lookup_flags)) {
 		lookup_flags |= LOOKUP_REVAL;
@@ -3669,9 +3703,9 @@
 }
 EXPORT_SYMBOL(dentry_unhash);
 
-int vfs_rmdir(struct inode *dir, struct dentry *dentry)
+int vfs_rmdir2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry)
 {
-	int error = may_delete(dir, dentry, 1);
+	int error = may_delete(mnt, dir, dentry, 1);
 
 	if (error)
 		return error;
@@ -3706,6 +3740,12 @@
 		d_delete(dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_rmdir2);
+
+int vfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	return vfs_rmdir2(NULL, dir, dentry);
+}
 EXPORT_SYMBOL(vfs_rmdir);
 
 static long do_rmdir(int dfd, const char __user *pathname)
@@ -3751,7 +3791,7 @@
 	error = security_path_rmdir(&path, dentry);
 	if (error)
 		goto exit3;
-	error = vfs_rmdir(path.dentry->d_inode, dentry);
+	error = vfs_rmdir2(path.mnt, path.dentry->d_inode, dentry);
 exit3:
 	dput(dentry);
 exit2:
@@ -3790,10 +3830,10 @@
  * be appropriate for callers that expect the underlying filesystem not
  * to be NFS exported.
  */
-int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode)
+int vfs_unlink2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, struct inode **delegated_inode)
 {
 	struct inode *target = dentry->d_inode;
-	int error = may_delete(dir, dentry, 0);
+	int error = may_delete(mnt, dir, dentry, 0);
 
 	if (error)
 		return error;
@@ -3828,6 +3868,12 @@
 
 	return error;
 }
+EXPORT_SYMBOL(vfs_unlink2);
+
+int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode)
+{
+	return vfs_unlink2(NULL, dir, dentry, delegated_inode);
+}
 EXPORT_SYMBOL(vfs_unlink);
 
 /*
@@ -3875,7 +3921,7 @@
 		error = security_path_unlink(&path, dentry);
 		if (error)
 			goto exit2;
-		error = vfs_unlink(path.dentry->d_inode, dentry, &delegated_inode);
+		error = vfs_unlink2(path.mnt, path.dentry->d_inode, dentry, &delegated_inode);
 exit2:
 		dput(dentry);
 	}
@@ -3925,9 +3971,9 @@
 	return do_unlinkat(AT_FDCWD, pathname);
 }
 
-int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
+int vfs_symlink2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, const char *oldname)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(mnt, dir, dentry);
 
 	if (error)
 		return error;
@@ -3944,6 +3990,12 @@
 		fsnotify_create(dir, dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_symlink2);
+
+int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
+{
+	return vfs_symlink2(NULL, dir, dentry, oldname);
+}
 EXPORT_SYMBOL(vfs_symlink);
 
 SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
@@ -3966,7 +4018,7 @@
 
 	error = security_path_symlink(&path, dentry, from->name);
 	if (!error)
-		error = vfs_symlink(path.dentry->d_inode, dentry, from->name);
+		error = vfs_symlink2(path.mnt, path.dentry->d_inode, dentry, from->name);
 	done_path_create(&path, dentry);
 	if (retry_estale(error, lookup_flags)) {
 		lookup_flags |= LOOKUP_REVAL;
@@ -4001,7 +4053,7 @@
  * be appropriate for callers that expect the underlying filesystem not
  * to be NFS exported.
  */
-int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, struct inode **delegated_inode)
+int vfs_link2(struct vfsmount *mnt, struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, struct inode **delegated_inode)
 {
 	struct inode *inode = old_dentry->d_inode;
 	unsigned max_links = dir->i_sb->s_max_links;
@@ -4010,7 +4062,7 @@
 	if (!inode)
 		return -ENOENT;
 
-	error = may_create(dir, new_dentry);
+	error = may_create(mnt, dir, new_dentry);
 	if (error)
 		return error;
 
@@ -4053,6 +4105,12 @@
 		fsnotify_link(dir, inode, new_dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_link2);
+
+int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, struct inode **delegated_inode)
+{
+	return vfs_link2(NULL, old_dentry, dir, new_dentry, delegated_inode);
+}
 EXPORT_SYMBOL(vfs_link);
 
 /*
@@ -4108,7 +4166,7 @@
 	error = security_path_link(old_path.dentry, &new_path, new_dentry);
 	if (error)
 		goto out_dput;
-	error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry, &delegated_inode);
+	error = vfs_link2(old_path.mnt, old_path.dentry, new_path.dentry->d_inode, new_dentry, &delegated_inode);
 out_dput:
 	done_path_create(&new_path, new_dentry);
 	if (delegated_inode) {
@@ -4183,7 +4241,8 @@
  *	   ->i_mutex on parents, which works but leads to some truly excessive
  *	   locking].
  */
-int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+int vfs_rename2(struct vfsmount *mnt,
+	       struct inode *old_dir, struct dentry *old_dentry,
 	       struct inode *new_dir, struct dentry *new_dentry,
 	       struct inode **delegated_inode, unsigned int flags)
 {
@@ -4195,22 +4254,26 @@
 	bool new_is_dir = false;
 	unsigned max_links = new_dir->i_sb->s_max_links;
 
-	if (source == target)
+	/*
+	 * Check source == target.
+	 * On overlayfs need to look at underlying inodes.
+	 */
+	if (vfs_select_inode(old_dentry, 0) == vfs_select_inode(new_dentry, 0))
 		return 0;
 
-	error = may_delete(old_dir, old_dentry, is_dir);
+	error = may_delete(mnt, old_dir, old_dentry, is_dir);
 	if (error)
 		return error;
 
 	if (!target) {
-		error = may_create(new_dir, new_dentry);
+		error = may_create(mnt, new_dir, new_dentry);
 	} else {
 		new_is_dir = d_is_dir(new_dentry);
 
 		if (!(flags & RENAME_EXCHANGE))
-			error = may_delete(new_dir, new_dentry, is_dir);
+			error = may_delete(mnt, new_dir, new_dentry, is_dir);
 		else
-			error = may_delete(new_dir, new_dentry, new_is_dir);
+			error = may_delete(mnt, new_dir, new_dentry, new_is_dir);
 	}
 	if (error)
 		return error;
@@ -4227,12 +4290,12 @@
 	 */
 	if (new_dir != old_dir) {
 		if (is_dir) {
-			error = inode_permission(source, MAY_WRITE);
+			error = inode_permission2(mnt, source, MAY_WRITE);
 			if (error)
 				return error;
 		}
 		if ((flags & RENAME_EXCHANGE) && new_is_dir) {
-			error = inode_permission(target, MAY_WRITE);
+			error = inode_permission2(mnt, target, MAY_WRITE);
 			if (error)
 				return error;
 		}
@@ -4315,6 +4378,14 @@
 
 	return error;
 }
+EXPORT_SYMBOL(vfs_rename2);
+
+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+	       struct inode *new_dir, struct dentry *new_dentry,
+	       struct inode **delegated_inode, unsigned int flags)
+{
+	return vfs_rename2(NULL, old_dir, old_dentry, new_dir, new_dentry, delegated_inode, flags);
+}
 EXPORT_SYMBOL(vfs_rename);
 
 SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
@@ -4428,7 +4499,7 @@
 				     &new_path, new_dentry, flags);
 	if (error)
 		goto exit5;
-	error = vfs_rename(old_path.dentry->d_inode, old_dentry,
+	error = vfs_rename2(old_path.mnt, old_path.dentry->d_inode, old_dentry,
 			   new_path.dentry->d_inode, new_dentry,
 			   &delegated_inode, flags);
 exit5:
@@ -4473,7 +4544,7 @@
 
 int vfs_whiteout(struct inode *dir, struct dentry *dentry)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(NULL, dir, dentry);
 	if (error)
 		return error;
 
diff --git a/fs/namespace.c b/fs/namespace.c
index 0570729..a22959c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -27,6 +27,9 @@
 #include "pnode.h"
 #include "internal.h"
 
+/* Maximum number of mounts in a mount namespace */
+unsigned int sysctl_mount_max __read_mostly = 100000;
+
 static unsigned int m_hash_mask __read_mostly;
 static unsigned int m_hash_shift __read_mostly;
 static unsigned int mp_hash_mask __read_mostly;
@@ -577,6 +580,7 @@
 
 static void free_vfsmnt(struct mount *mnt)
 {
+	kfree(mnt->mnt.data);
 	kfree_const(mnt->mnt_devname);
 #ifdef CONFIG_SMP
 	free_percpu(mnt->mnt_pcp);
@@ -638,28 +642,6 @@
 }
 
 /*
- * find the last mount at @dentry on vfsmount @mnt.
- * mount_lock must be held.
- */
-struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry)
-{
-	struct mount *p, *res = NULL;
-	p = __lookup_mnt(mnt, dentry);
-	if (!p)
-		goto out;
-	if (!(p->mnt.mnt_flags & MNT_UMOUNT))
-		res = p;
-	hlist_for_each_entry_continue(p, mnt_hash) {
-		if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry)
-			break;
-		if (!(p->mnt.mnt_flags & MNT_UMOUNT))
-			res = p;
-	}
-out:
-	return res;
-}
-
-/*
  * lookup_mnt - Return the first child mount mounted at path
  *
  * "First" means first mounted chronologically.  If you create the
@@ -743,26 +725,50 @@
 	return NULL;
 }
 
-static struct mountpoint *new_mountpoint(struct dentry *dentry)
+static struct mountpoint *get_mountpoint(struct dentry *dentry)
 {
-	struct hlist_head *chain = mp_hash(dentry);
-	struct mountpoint *mp;
+	struct mountpoint *mp, *new = NULL;
 	int ret;
 
-	mp = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
-	if (!mp)
-		return ERR_PTR(-ENOMEM);
-
-	ret = d_set_mounted(dentry);
-	if (ret) {
-		kfree(mp);
-		return ERR_PTR(ret);
+	if (d_mountpoint(dentry)) {
+mountpoint:
+		read_seqlock_excl(&mount_lock);
+		mp = lookup_mountpoint(dentry);
+		read_sequnlock_excl(&mount_lock);
+		if (mp)
+			goto done;
 	}
 
-	mp->m_dentry = dentry;
-	mp->m_count = 1;
-	hlist_add_head(&mp->m_hash, chain);
-	INIT_HLIST_HEAD(&mp->m_list);
+	if (!new)
+		new = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
+	if (!new)
+		return ERR_PTR(-ENOMEM);
+
+
+	/* Exactly one processes may set d_mounted */
+	ret = d_set_mounted(dentry);
+
+	/* Someone else set d_mounted? */
+	if (ret == -EBUSY)
+		goto mountpoint;
+
+	/* The dentry is not available as a mountpoint? */
+	mp = ERR_PTR(ret);
+	if (ret)
+		goto done;
+
+	/* Add the new mountpoint to the hash table */
+	read_seqlock_excl(&mount_lock);
+	new->m_dentry = dentry;
+	new->m_count = 1;
+	hlist_add_head(&new->m_hash, mp_hash(dentry));
+	INIT_HLIST_HEAD(&new->m_list);
+	read_sequnlock_excl(&mount_lock);
+
+	mp = new;
+	new = NULL;
+done:
+	kfree(new);
 	return mp;
 }
 
@@ -855,6 +861,13 @@
 	hlist_add_head(&child_mnt->mnt_mp_list, &mp->m_list);
 }
 
+static void __attach_mnt(struct mount *mnt, struct mount *parent)
+{
+	hlist_add_head_rcu(&mnt->mnt_hash,
+			   m_hash(&parent->mnt, mnt->mnt_mountpoint));
+	list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
+}
+
 /*
  * vfsmount lock must be held for write
  */
@@ -863,28 +876,45 @@
 			struct mountpoint *mp)
 {
 	mnt_set_mountpoint(parent, mp, mnt);
-	hlist_add_head_rcu(&mnt->mnt_hash, m_hash(&parent->mnt, mp->m_dentry));
-	list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
+	__attach_mnt(mnt, parent);
 }
 
-static void attach_shadowed(struct mount *mnt,
-			struct mount *parent,
-			struct mount *shadows)
+void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct mount *mnt)
 {
-	if (shadows) {
-		hlist_add_behind_rcu(&mnt->mnt_hash, &shadows->mnt_hash);
-		list_add(&mnt->mnt_child, &shadows->mnt_child);
-	} else {
-		hlist_add_head_rcu(&mnt->mnt_hash,
-				m_hash(&parent->mnt, mnt->mnt_mountpoint));
-		list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
-	}
+	struct mountpoint *old_mp = mnt->mnt_mp;
+	struct dentry *old_mountpoint = mnt->mnt_mountpoint;
+	struct mount *old_parent = mnt->mnt_parent;
+
+	list_del_init(&mnt->mnt_child);
+	hlist_del_init(&mnt->mnt_mp_list);
+	hlist_del_init_rcu(&mnt->mnt_hash);
+
+	attach_mnt(mnt, parent, mp);
+
+	put_mountpoint(old_mp);
+
+	/*
+	 * Safely avoid even the suggestion this code might sleep or
+	 * lock the mount hash by taking advantage of the knowledge that
+	 * mnt_change_mountpoint will not release the final reference
+	 * to a mountpoint.
+	 *
+	 * During mounting, the mount passed in as the parent mount will
+	 * continue to use the old mountpoint and during unmounting, the
+	 * old mountpoint will continue to exist until namespace_unlock,
+	 * which happens well after mnt_change_mountpoint.
+	 */
+	spin_lock(&old_mountpoint->d_lock);
+	old_mountpoint->d_lockref.count--;
+	spin_unlock(&old_mountpoint->d_lock);
+
+	mnt_add_count(old_parent, -1);
 }
 
 /*
  * vfsmount lock must be held for write
  */
-static void commit_tree(struct mount *mnt, struct mount *shadows)
+static void commit_tree(struct mount *mnt)
 {
 	struct mount *parent = mnt->mnt_parent;
 	struct mount *m;
@@ -899,7 +929,10 @@
 
 	list_splice(&head, n->list.prev);
 
-	attach_shadowed(mnt, parent, shadows);
+	n->mounts += n->pending_mounts;
+	n->pending_mounts = 0;
+
+	__attach_mnt(mnt, parent);
 	touch_mnt_namespace(n);
 }
 
@@ -942,11 +975,21 @@
 	if (!mnt)
 		return ERR_PTR(-ENOMEM);
 
+	mnt->mnt.data = NULL;
+	if (type->alloc_mnt_data) {
+		mnt->mnt.data = type->alloc_mnt_data();
+		if (!mnt->mnt.data) {
+			mnt_free_id(mnt);
+			free_vfsmnt(mnt);
+			return ERR_PTR(-ENOMEM);
+		}
+	}
 	if (flags & MS_KERNMOUNT)
 		mnt->mnt.mnt_flags = MNT_INTERNAL;
 
-	root = mount_fs(type, flags, name, data);
+	root = mount_fs(type, flags, name, &mnt->mnt, data);
 	if (IS_ERR(root)) {
+		kfree(mnt->mnt.data);
 		mnt_free_id(mnt);
 		free_vfsmnt(mnt);
 		return ERR_CAST(root);
@@ -974,6 +1017,14 @@
 	if (!mnt)
 		return ERR_PTR(-ENOMEM);
 
+	if (sb->s_op->clone_mnt_data) {
+		mnt->mnt.data = sb->s_op->clone_mnt_data(old->mnt.data);
+		if (!mnt->mnt.data) {
+			err = -ENOMEM;
+			goto out_free;
+		}
+	}
+
 	if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
 		mnt->mnt_group_id = 0; /* not a peer of original */
 	else
@@ -1042,6 +1093,7 @@
 	return mnt;
 
  out_free:
+	kfree(mnt->mnt.data);
 	mnt_free_id(mnt);
 	free_vfsmnt(mnt);
 	return ERR_PTR(err);
@@ -1419,11 +1471,16 @@
 		propagate_umount(&tmp_list);
 
 	while (!list_empty(&tmp_list)) {
+		struct mnt_namespace *ns;
 		bool disconnect;
 		p = list_first_entry(&tmp_list, struct mount, mnt_list);
 		list_del_init(&p->mnt_expire);
 		list_del_init(&p->mnt_list);
-		__touch_mnt_namespace(p->mnt_ns);
+		ns = p->mnt_ns;
+		if (ns) {
+			ns->mounts--;
+			__touch_mnt_namespace(ns);
+		}
 		p->mnt_ns = NULL;
 		if (how & UMOUNT_SYNC)
 			p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
@@ -1557,11 +1614,12 @@
 	struct mount *mnt;
 
 	namespace_lock();
+	lock_mount_hash();
 	mp = lookup_mountpoint(dentry);
 	if (IS_ERR_OR_NULL(mp))
 		goto out_unlock;
 
-	lock_mount_hash();
+	event++;
 	while (!hlist_empty(&mp->m_list)) {
 		mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
 		if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
@@ -1570,9 +1628,9 @@
 		}
 		else umount_tree(mnt, UMOUNT_CONNECTED);
 	}
-	unlock_mount_hash();
 	put_mountpoint(mp);
 out_unlock:
+	unlock_mount_hash();
 	namespace_unlock();
 }
 
@@ -1693,7 +1751,6 @@
 			continue;
 
 		for (s = r; s; s = next_mnt(s, r)) {
-			struct mount *t = NULL;
 			if (!(flag & CL_COPY_UNBINDABLE) &&
 			    IS_MNT_UNBINDABLE(s)) {
 				s = skip_mnt_tree(s);
@@ -1715,14 +1772,7 @@
 				goto out;
 			lock_mount_hash();
 			list_add_tail(&q->mnt_list, &res->mnt_list);
-			mnt_set_mountpoint(parent, p->mnt_mp, q);
-			if (!list_empty(&parent->mnt_mounts)) {
-				t = list_last_entry(&parent->mnt_mounts,
-					struct mount, mnt_child);
-				if (t->mnt_mp != p->mnt_mp)
-					t = NULL;
-			}
-			attach_shadowed(q, parent, t);
+			attach_mnt(q, parent, p->mnt_mp);
 			unlock_mount_hash();
 		}
 	}
@@ -1831,6 +1881,28 @@
 	return 0;
 }
 
+int count_mounts(struct mnt_namespace *ns, struct mount *mnt)
+{
+	unsigned int max = READ_ONCE(sysctl_mount_max);
+	unsigned int mounts = 0, old, pending, sum;
+	struct mount *p;
+
+	for (p = mnt; p; p = next_mnt(p, mnt))
+		mounts++;
+
+	old = ns->mounts;
+	pending = ns->pending_mounts;
+	sum = old + pending;
+	if ((old > sum) ||
+	    (pending > sum) ||
+	    (max < sum) ||
+	    (mounts > (max - sum)))
+		return -ENOSPC;
+
+	ns->pending_mounts = pending + mounts;
+	return 0;
+}
+
 /*
  *  @source_mnt : mount tree to be attached
  *  @nd         : place the mount tree @source_mnt is attached
@@ -1900,10 +1972,26 @@
 			struct path *parent_path)
 {
 	HLIST_HEAD(tree_list);
+	struct mnt_namespace *ns = dest_mnt->mnt_ns;
+	struct mountpoint *smp;
 	struct mount *child, *p;
 	struct hlist_node *n;
 	int err;
 
+	/* Preallocate a mountpoint in case the new mounts need
+	 * to be tucked under other mounts.
+	 */
+	smp = get_mountpoint(source_mnt->mnt.mnt_root);
+	if (IS_ERR(smp))
+		return PTR_ERR(smp);
+
+	/* Is there space to add these mounts to the mount namespace? */
+	if (!parent_path) {
+		err = count_mounts(ns, source_mnt);
+		if (err)
+			goto out;
+	}
+
 	if (IS_MNT_SHARED(dest_mnt)) {
 		err = invent_group_ids(source_mnt, true);
 		if (err)
@@ -1923,16 +2011,19 @@
 		touch_mnt_namespace(source_mnt->mnt_ns);
 	} else {
 		mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
-		commit_tree(source_mnt, NULL);
+		commit_tree(source_mnt);
 	}
 
 	hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) {
 		struct mount *q;
 		hlist_del_init(&child->mnt_hash);
-		q = __lookup_mnt_last(&child->mnt_parent->mnt,
-				      child->mnt_mountpoint);
-		commit_tree(child, q);
+		q = __lookup_mnt(&child->mnt_parent->mnt,
+				 child->mnt_mountpoint);
+		if (q)
+			mnt_change_mountpoint(child, smp, q);
+		commit_tree(child);
 	}
+	put_mountpoint(smp);
 	unlock_mount_hash();
 
 	return 0;
@@ -1940,11 +2031,18 @@
  out_cleanup_ids:
 	while (!hlist_empty(&tree_list)) {
 		child = hlist_entry(tree_list.first, struct mount, mnt_hash);
+		child->mnt_parent->mnt_ns->pending_mounts = 0;
 		umount_tree(child, UMOUNT_SYNC);
 	}
 	unlock_mount_hash();
 	cleanup_group_ids(source_mnt, NULL);
  out:
+	ns->pending_mounts = 0;
+
+	read_seqlock_excl(&mount_lock);
+	put_mountpoint(smp);
+	read_sequnlock_excl(&mount_lock);
+
 	return err;
 }
 
@@ -1961,9 +2059,7 @@
 	namespace_lock();
 	mnt = lookup_mnt(path);
 	if (likely(!mnt)) {
-		struct mountpoint *mp = lookup_mountpoint(dentry);
-		if (!mp)
-			mp = new_mountpoint(dentry);
+		struct mountpoint *mp = get_mountpoint(dentry);
 		if (IS_ERR(mp)) {
 			namespace_unlock();
 			mutex_unlock(&dentry->d_inode->i_mutex);
@@ -1982,7 +2078,11 @@
 static void unlock_mount(struct mountpoint *where)
 {
 	struct dentry *dentry = where->m_dentry;
+
+	read_seqlock_excl(&mount_lock);
 	put_mountpoint(where);
+	read_sequnlock_excl(&mount_lock);
+
 	namespace_unlock();
 	mutex_unlock(&dentry->d_inode->i_mutex);
 }
@@ -2207,8 +2307,14 @@
 		err = change_mount_flags(path->mnt, flags);
 	else if (!capable(CAP_SYS_ADMIN))
 		err = -EPERM;
-	else
-		err = do_remount_sb(sb, flags, data, 0);
+	else {
+		err = do_remount_sb2(path->mnt, sb, flags, data, 0);
+		namespace_lock();
+		lock_mount_hash();
+		propagate_remount(mnt);
+		unlock_mount_hash();
+		namespace_unlock();
+	}
 	if (!err) {
 		lock_mount_hash();
 		mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK;
@@ -2401,8 +2507,10 @@
 			mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV;
 		}
 		if (type->fs_flags & FS_USERNS_VISIBLE) {
-			if (!fs_fully_visible(type, &mnt_flags))
+			if (!fs_fully_visible(type, &mnt_flags)) {
+				put_filesystem(type);
 				return -EPERM;
+			}
 		}
 	}
 
@@ -2766,6 +2874,8 @@
 	init_waitqueue_head(&new_ns->poll);
 	new_ns->event = 0;
 	new_ns->user_ns = get_user_ns(user_ns);
+	new_ns->mounts = 0;
+	new_ns->pending_mounts = 0;
 	return new_ns;
 }
 
@@ -2815,6 +2925,7 @@
 	q = new;
 	while (p) {
 		q->mnt_ns = new_ns;
+		new_ns->mounts++;
 		if (new_fs) {
 			if (&p->mnt == new_fs->root.mnt) {
 				new_fs->root.mnt = mntget(&q->mnt);
@@ -2853,6 +2964,7 @@
 		struct mount *mnt = real_mount(m);
 		mnt->mnt_ns = new_ns;
 		new_ns->root = mnt;
+		new_ns->mounts++;
 		list_add(&mnt->mnt_list, &new_ns->list);
 	} else {
 		mntput(m);
@@ -3052,9 +3164,9 @@
 	touch_mnt_namespace(current->nsproxy->mnt_ns);
 	/* A moved mount should not expire automatically */
 	list_del_init(&new_mnt->mnt_expire);
+	put_mountpoint(root_mp);
 	unlock_mount_hash();
 	chroot_fs_refs(&root, &new);
-	put_mountpoint(root_mp);
 	error = 0;
 out4:
 	unlock_mount(old_mp);
@@ -3236,6 +3348,10 @@
 		if (mnt->mnt.mnt_sb->s_iflags & SB_I_NOEXEC)
 			mnt_flags &= ~(MNT_LOCK_NOSUID | MNT_LOCK_NOEXEC);
 
+		/* Don't miss readonly hidden in the superblock flags */
+		if (mnt->mnt.mnt_sb->s_flags & MS_RDONLY)
+			mnt_flags |= MNT_LOCK_READONLY;
+
 		/* Verify the mount flags are equal to or more permissive
 		 * than the proposed new mount.
 		 */
@@ -3262,7 +3378,7 @@
 		list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
 			struct inode *inode = child->mnt_mountpoint->d_inode;
 			/* Only worry about locked mounts */
-			if (!(mnt_flags & MNT_LOCKED))
+			if (!(child->mnt.mnt_flags & MNT_LOCKED))
 				continue;
 			/* Is the directory permanetly empty? */
 			if (!is_empty_dir_inode(inode))
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index a7f2e6e..48efe62 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -261,7 +261,7 @@
 	}
 
 	ret = -EPROTONOSUPPORT;
-	if (minorversion == 0)
+	if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0)
 		ret = nfs4_callback_up_net(serv, net);
 	else if (xprt->ops->bc_up)
 		ret = xprt->ops->bc_up(serv, net);
@@ -275,6 +275,7 @@
 err_socks:
 	svc_rpcb_cleanup(serv, net);
 err_bind:
+	nn->cb_users[minorversion]--;
 	dprintk("NFS: Couldn't create callback socket: err = %d; "
 			"net = %p\n", ret, net);
 	return ret;
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 646cdac..e2e857a 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -912,7 +912,7 @@
 	if (hdr_arg.minorversion == 0) {
 		cps.clp = nfs4_find_client_ident(SVC_NET(rqstp), hdr_arg.cb_ident);
 		if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp))
-			return rpc_drop_reply;
+			goto out_invalidcred;
 	}
 
 	cps.minorversion = hdr_arg.minorversion;
@@ -940,6 +940,10 @@
 	nfs_put_client(cps.clp);
 	dprintk("%s: done, status = %u\n", __func__, ntohl(status));
 	return rpc_success;
+
+out_invalidcred:
+	pr_warn_ratelimited("NFS: NFSv4 callback contains invalid cred\n");
+	return rpc_autherr_badcred;
 }
 
 /*
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 5166adc..7af5eea 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -41,6 +41,17 @@
 	set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
 }
 
+static bool
+nfs4_is_valid_delegation(const struct nfs_delegation *delegation,
+		fmode_t flags)
+{
+	if (delegation != NULL && (delegation->type & flags) == flags &&
+	    !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) &&
+	    !test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
+		return true;
+	return false;
+}
+
 static int
 nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark)
 {
@@ -50,8 +61,7 @@
 	flags &= FMODE_READ|FMODE_WRITE;
 	rcu_read_lock();
 	delegation = rcu_dereference(NFS_I(inode)->delegation);
-	if (delegation != NULL && (delegation->type & flags) == flags &&
-	    !test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
+	if (nfs4_is_valid_delegation(delegation, flags)) {
 		if (mark)
 			nfs_mark_delegation_referenced(delegation);
 		ret = 1;
@@ -892,7 +902,7 @@
 	flags &= FMODE_READ|FMODE_WRITE;
 	rcu_read_lock();
 	delegation = rcu_dereference(nfsi->delegation);
-	ret = (delegation != NULL && (delegation->type & flags) == flags);
+	ret = nfs4_is_valid_delegation(delegation, flags);
 	if (ret) {
 		nfs4_stateid_copy(dst, &delegation->stateid);
 		nfs_mark_delegation_referenced(delegation);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 5fc2162..5b21b1c 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -462,7 +462,7 @@
 {
 	if (!list_empty(&NFS_I(dir)->open_files)) {
 		nfs_advise_use_readdirplus(dir);
-		nfs_zap_mapping(dir, dir->i_mapping);
+		invalidate_mapping_pages(dir->i_mapping, 0, -1);
 	}
 }
 
@@ -847,17 +847,6 @@
 	goto out;
 }
 
-static bool nfs_dir_mapping_need_revalidate(struct inode *dir)
-{
-	struct nfs_inode *nfsi = NFS_I(dir);
-
-	if (nfs_attribute_cache_expired(dir))
-		return true;
-	if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
-		return true;
-	return false;
-}
-
 /* The file offset position represents the dirent entry number.  A
    last cookie cache takes care of the common case of reading the
    whole directory.
@@ -890,7 +879,7 @@
 	desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0;
 
 	nfs_block_sillyrename(dentry);
-	if (ctx->pos == 0 || nfs_dir_mapping_need_revalidate(inode))
+	if (ctx->pos == 0 || nfs_attribute_cache_expired(inode))
 		res = nfs_revalidate_mapping(inode, file->f_mapping);
 	if (res < 0)
 		goto out;
@@ -1531,9 +1520,9 @@
 		err = PTR_ERR(inode);
 		trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
 		put_nfs_open_context(ctx);
+		d_drop(dentry);
 		switch (err) {
 		case -ENOENT:
-			d_drop(dentry);
 			d_add(dentry, NULL);
 			nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 			break;
@@ -2432,6 +2421,20 @@
 }
 EXPORT_SYMBOL_GPL(nfs_may_open);
 
+static int nfs_execute_ok(struct inode *inode, int mask)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	int ret;
+
+	if (mask & MAY_NOT_BLOCK)
+		ret = nfs_revalidate_inode_rcu(server, inode);
+	else
+		ret = nfs_revalidate_inode(server, inode);
+	if (ret == 0 && !execute_ok(inode))
+		ret = -EACCES;
+	return ret;
+}
+
 int nfs_permission(struct inode *inode, int mask)
 {
 	struct rpc_cred *cred;
@@ -2449,6 +2452,9 @@
 		case S_IFLNK:
 			goto out;
 		case S_IFREG:
+			if ((mask & MAY_OPEN) &&
+			   nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN))
+				return 0;
 			break;
 		case S_IFDIR:
 			/*
@@ -2481,8 +2487,8 @@
 			res = PTR_ERR(cred);
 	}
 out:
-	if (!res && (mask & MAY_EXEC) && !execute_ok(inode))
-		res = -EACCES;
+	if (!res && (mask & MAY_EXEC))
+		res = nfs_execute_ok(inode, mask);
 
 	dfprintk(VFS, "NFS: permission(%s/%lu), mask=0x%x, res=%d\n",
 		inode->i_sb->s_id, inode->i_ino, mask, res);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 93e2364..dc875cd 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -407,7 +407,7 @@
 	 */
 	if (!PageUptodate(page)) {
 		unsigned pglen = nfs_page_length(page);
-		unsigned end = offset + len;
+		unsigned end = offset + copied;
 
 		if (pglen == 0) {
 			zero_user_segments(page, 0, offset,
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c
index 02ec079..fd8da63 100644
--- a/fs/nfs/filelayout/filelayout.c
+++ b/fs/nfs/filelayout/filelayout.c
@@ -374,8 +374,7 @@
 		return -EAGAIN;
 	}
 
-	if (data->verf.committed == NFS_UNSTABLE)
-		pnfs_set_layoutcommit(data->inode, data->lseg, data->lwb);
+	pnfs_set_layoutcommit(data->inode, data->lseg, data->lwb);
 
 	return 0;
 }
diff --git a/fs/nfs/filelayout/filelayoutdev.c b/fs/nfs/filelayout/filelayoutdev.c
index 4946ef4..85ef38f 100644
--- a/fs/nfs/filelayout/filelayoutdev.c
+++ b/fs/nfs/filelayout/filelayoutdev.c
@@ -283,7 +283,8 @@
 			     s->nfs_client->cl_rpcclient->cl_auth->au_flavor);
 
 out_test_devid:
-	if (filelayout_test_devid_unavailable(devid))
+	if (ret->ds_clp == NULL ||
+	    filelayout_test_devid_unavailable(devid))
 		ret = NULL;
 out:
 	return ret;
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 2a2e2d8..5431332 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -1414,8 +1414,7 @@
 		return -EAGAIN;
 	}
 
-	if (data->verf.committed == NFS_UNSTABLE
-	    && ff_layout_need_layoutcommit(data->lseg))
+	if (ff_layout_need_layoutcommit(data->lseg))
 		pnfs_set_layoutcommit(data->inode, data->lseg, data->lwb);
 
 	return 0;
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
index 6b1ce98..7f1a0fb 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -269,6 +269,7 @@
 	task = rpc_run_task(&task_setup);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
+	rpc_put_task(task);
 	return 0;
 }
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 98a4415..8e425f2 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2188,8 +2188,6 @@
 	if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
 		return 0;
 
-	/* even though OPEN succeeded, access is denied. Close the file */
-	nfs4_close_state(state, fmode);
 	return -EACCES;
 }
 
@@ -2422,7 +2420,8 @@
 		sattr->ia_valid |= ATTR_MTIME;
 
 	/* Except MODE, it seems harmless of setting twice. */
-	if ((attrset[1] & FATTR4_WORD1_MODE))
+	if (opendata->o_arg.createmode != NFS4_CREATE_EXCLUSIVE &&
+		attrset[1] & FATTR4_WORD1_MODE)
 		sattr->ia_valid &= ~ATTR_MODE;
 
 	if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL)
@@ -2451,6 +2450,7 @@
 	ret = PTR_ERR(state);
 	if (IS_ERR(state))
 		goto out;
+	ctx->state = state;
 	if (server->caps & NFS_CAP_POSIX_LOCK)
 		set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
 
@@ -2473,7 +2473,6 @@
 	if (ret != 0)
 		goto out;
 
-	ctx->state = state;
 	if (d_inode(dentry) == state->inode) {
 		nfs_inode_attach_open_context(ctx);
 		if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
@@ -2854,12 +2853,11 @@
 			call_close |= is_wronly;
 		else if (is_wronly)
 			calldata->arg.fmode |= FMODE_WRITE;
+		if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
+			call_close |= is_rdwr;
 	} else if (is_rdwr)
 		calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
 
-	if (calldata->arg.fmode == 0)
-		call_close |= is_rdwr;
-
 	if (!nfs4_valid_open_stateid(state))
 		call_close = 0;
 	spin_unlock(&state->owner->so_lock);
@@ -4711,7 +4709,7 @@
  */
 static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
 {
-	struct page *pages[NFS4ACL_MAXPAGES] = {NULL, };
+	struct page *pages[NFS4ACL_MAXPAGES + 1] = {NULL, };
 	struct nfs_getaclargs args = {
 		.fh = NFS_FH(inode),
 		.acl_pages = pages,
@@ -4725,13 +4723,9 @@
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
-	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
+	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
 	int ret = -ENOMEM, i;
 
-	/* As long as we're doing a round trip to the server anyway,
-	 * let's be prepared for a page of acl data. */
-	if (npages == 0)
-		npages = 1;
 	if (npages > ARRAY_SIZE(pages))
 		return -ERANGE;
 
@@ -7425,12 +7419,20 @@
 	status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 	trace_nfs4_create_session(clp, status);
 
+	switch (status) {
+	case -NFS4ERR_STALE_CLIENTID:
+	case -NFS4ERR_DELAY:
+	case -ETIMEDOUT:
+	case -EACCES:
+	case -EAGAIN:
+		goto out;
+	};
+
+	clp->cl_seqid++;
 	if (!status) {
 		/* Verify the session's negotiated channel_attrs values */
 		status = nfs4_verify_channel_attrs(&args, &res);
 		/* Increment the clientid slot sequence id */
-		if (clp->cl_seqid == res.seqid)
-			clp->cl_seqid++;
 		if (status)
 			goto out;
 		nfs4_update_session(session, &res);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index d854693..e8d1d6c 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1072,6 +1072,7 @@
 		case -NFS4ERR_BADXDR:
 		case -NFS4ERR_RESOURCE:
 		case -NFS4ERR_NOFILEHANDLE:
+		case -NFS4ERR_MOVED:
 			/* Non-seqid mutating errors */
 			return;
 	};
@@ -1493,6 +1494,9 @@
 					__func__, status);
 			case -ENOENT:
 			case -ENOMEM:
+			case -EACCES:
+			case -EROFS:
+			case -EIO:
 			case -ESTALE:
 				/* Open state on this file cannot be recovered */
 				nfs4_state_mark_recovery_failed(state, status);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 4e44412..1cb50bb 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -2487,7 +2487,7 @@
 	encode_compound_hdr(xdr, req, &hdr);
 	encode_sequence(xdr, &args->seq_args, &hdr);
 	encode_putfh(xdr, args->fh, &hdr);
-	replen = hdr.replen + op_decode_hdr_maxsz + 1;
+	replen = hdr.replen + op_decode_hdr_maxsz;
 	encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr);
 
 	xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index bec0384..3cae072 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -365,6 +365,9 @@
 static bool
 pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo)
 {
+	/* Serialise LAYOUTGET/LAYOUTRETURN */
+	if (atomic_read(&lo->plh_outstanding) != 0)
+		return false;
 	if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
 		return false;
 	lo->plh_return_iomode = 0;
@@ -1182,13 +1185,11 @@
 	 * i_lock */
         spin_lock(&ino->i_lock);
         lo = nfsi->layout;
-        if (lo && test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
-                sleep = true;
-        spin_unlock(&ino->i_lock);
-
-        if (sleep)
+        if (lo && test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) {
                 rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
-
+                sleep = true;
+	}
+        spin_unlock(&ino->i_lock);
         return sleep;
 }
 
@@ -1530,6 +1531,7 @@
 		goto out;
 
 lookup_again:
+	nfs4_client_recover_expired_lease(clp);
 	first = false;
 	spin_lock(&ino->i_lock);
 	lo = pnfs_find_alloc_layout(ino, ctx, gfp_flags);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 7b93164..7a9b6e3 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1261,6 +1261,9 @@
 	dprintk("NFS:       nfs_updatepage(%pD2 %d@%lld)\n",
 		file, count, (long long)(page_file_offset(page) + offset));
 
+	if (!count)
+		goto out;
+
 	if (nfs_can_extend_write(file, page, inode)) {
 		count = max(count + offset, nfs_page_length(page));
 		offset = 0;
@@ -1271,7 +1274,7 @@
 		nfs_set_pageerror(page);
 	else
 		__set_page_dirty_nobuffers(page);
-
+out:
 	dprintk("NFS:       nfs_updatepage returns %d (isize %lld)\n",
 			status, (long long)i_size_read(inode));
 	return status;
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index c29d942..0976f8d 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -50,7 +50,7 @@
 {
 	struct nfsd4_layout_seg *seg = &args->lg_seg;
 	struct super_block *sb = inode->i_sb;
-	u32 block_size = (1 << inode->i_blkbits);
+	u32 block_size = i_blocksize(inode);
 	struct pnfs_block_extent *bex;
 	struct iomap iomap;
 	u32 device_generation = 0;
@@ -151,7 +151,7 @@
 	int error;
 
 	nr_iomaps = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout,
-			lcp->lc_up_len, &iomaps, 1 << inode->i_blkbits);
+			lcp->lc_up_len, &iomaps, i_blocksize(inode));
 	if (nr_iomaps < 0)
 		return nfserrno(nr_iomaps);
 
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 1580ea6..d08cd88 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -104,22 +104,21 @@
 		goto out;
 
 	inode = d_inode(fh->fh_dentry);
-	if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
-		error = -EOPNOTSUPP;
-		goto out_errno;
-	}
 
 	error = fh_want_write(fh);
 	if (error)
 		goto out_errno;
 
-	error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
+	fh_lock(fh);
+
+	error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
 	if (error)
-		goto out_drop_write;
-	error = inode->i_op->set_acl(inode, argp->acl_default,
-				     ACL_TYPE_DEFAULT);
+		goto out_drop_lock;
+	error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
 	if (error)
-		goto out_drop_write;
+		goto out_drop_lock;
+
+	fh_unlock(fh);
 
 	fh_drop_write(fh);
 
@@ -131,7 +130,8 @@
 	posix_acl_release(argp->acl_access);
 	posix_acl_release(argp->acl_default);
 	return nfserr;
-out_drop_write:
+out_drop_lock:
+	fh_unlock(fh);
 	fh_drop_write(fh);
 out_errno:
 	nfserr = nfserrno(error);
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 01df4cd..0c89034 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -95,22 +95,20 @@
 		goto out;
 
 	inode = d_inode(fh->fh_dentry);
-	if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
-		error = -EOPNOTSUPP;
-		goto out_errno;
-	}
 
 	error = fh_want_write(fh);
 	if (error)
 		goto out_errno;
 
-	error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
-	if (error)
-		goto out_drop_write;
-	error = inode->i_op->set_acl(inode, argp->acl_default,
-				     ACL_TYPE_DEFAULT);
+	fh_lock(fh);
 
-out_drop_write:
+	error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
+	if (error)
+		goto out_drop_lock;
+	error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
+
+out_drop_lock:
+	fh_unlock(fh);
 	fh_drop_write(fh);
 out_errno:
 	nfserr = nfserrno(error);
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 00575d7..7162ab7 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -358,6 +358,7 @@
 {
 	unsigned int len, v, hdr, dlen;
 	u32 max_blocksize = svc_max_payload(rqstp);
+	struct kvec *head = rqstp->rq_arg.head;
 
 	p = decode_fh(p, &args->fh);
 	if (!p)
@@ -367,6 +368,8 @@
 	args->count = ntohl(*p++);
 	args->stable = ntohl(*p++);
 	len = args->len = ntohl(*p++);
+	if ((void *)p > head->iov_base + head->iov_len)
+		return 0;
 	/*
 	 * The count must equal the amount of data passed.
 	 */
@@ -377,9 +380,8 @@
 	 * Check to make sure that we got the right number of
 	 * bytes.
 	 */
-	hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
-	dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
-		- hdr;
+	hdr = (void*)p - head->iov_base;
+	dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
 	/*
 	 * Round the length of the data which was specified up to
 	 * the next multiple of XDR units and then compare that
@@ -396,7 +398,7 @@
 		len = args->len = max_blocksize;
 	}
 	rqstp->rq_vec[0].iov_base = (void*)p;
-	rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+	rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
 	v = 0;
 	while (len > rqstp->rq_vec[v].iov_len) {
 		len -= rqstp->rq_vec[v].iov_len;
@@ -471,6 +473,8 @@
 	/* first copy and check from the first page */
 	old = (char*)p;
 	vec = &rqstp->rq_arg.head[0];
+	if ((void *)old > vec->iov_base + vec->iov_len)
+		return 0;
 	avail = vec->iov_len - (old - (char*)vec->iov_base);
 	while (len && avail && *old) {
 		*new++ = *old++;
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 6adabd6..71292a0 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -770,9 +770,6 @@
 	dentry = fhp->fh_dentry;
 	inode = d_inode(dentry);
 
-	if (!inode->i_op->set_acl || !IS_POSIXACL(inode))
-		return nfserr_attrnotsupp;
-
 	if (S_ISDIR(inode->i_mode))
 		flags = NFS4_ACL_DIR;
 
@@ -782,16 +779,19 @@
 	if (host_error < 0)
 		goto out_nfserr;
 
-	host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS);
+	fh_lock(fhp);
+
+	host_error = set_posix_acl(inode, ACL_TYPE_ACCESS, pacl);
 	if (host_error < 0)
-		goto out_release;
+		goto out_drop_lock;
 
 	if (S_ISDIR(inode->i_mode)) {
-		host_error = inode->i_op->set_acl(inode, dpacl,
-						  ACL_TYPE_DEFAULT);
+		host_error = set_posix_acl(inode, ACL_TYPE_DEFAULT, dpacl);
 	}
 
-out_release:
+out_drop_lock:
+	fh_unlock(fhp);
+
 	posix_acl_release(pacl);
 	posix_acl_release(dpacl);
 out_nfserr:
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index e7f50c4..15bdc2d 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -710,22 +710,6 @@
 	}
 }
 
-static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args)
-{
-	struct rpc_xprt *xprt;
-
-	if (args->protocol != XPRT_TRANSPORT_BC_TCP)
-		return rpc_create(args);
-
-	xprt = args->bc_xprt->xpt_bc_xprt;
-	if (xprt) {
-		xprt_get(xprt);
-		return rpc_create_xprt(args, xprt);
-	}
-
-	return rpc_create(args);
-}
-
 static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
 {
 	int maxtime = max_cb_time(clp->net);
@@ -768,7 +752,7 @@
 		args.authflavor = ses->se_cb_sec.flavor;
 	}
 	/* Create RPC client */
-	client = create_backchannel_client(&args);
+	client = rpc_create(&args);
 	if (IS_ERR(client)) {
 		dprintk("NFSD: couldn't create callback client: %ld\n",
 			PTR_ERR(client));
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index c9d6c71..9eed219 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -189,10 +189,11 @@
 	struct nfs4_layout_stateid *ls;
 	struct nfs4_stid *stp;
 
-	stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache);
+	stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache,
+					nfsd4_free_layout_stateid);
 	if (!stp)
 		return NULL;
-	stp->sc_free = nfsd4_free_layout_stateid;
+
 	get_nfs4_file(fp);
 	stp->sc_file = fp;
 
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 7d5351c..209dbfc 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1690,6 +1690,12 @@
 			opdesc->op_get_currentstateid(cstate, &op->u);
 		op->status = opdesc->op_func(rqstp, cstate, &op->u);
 
+		/* Only from SEQUENCE */
+		if (cstate->status == nfserr_replay_cache) {
+			dprintk("%s NFS4.1 replay from cache\n", __func__);
+			status = op->status;
+			goto out;
+		}
 		if (!op->status) {
 			if (opdesc->op_set_currentstateid)
 				opdesc->op_set_currentstateid(cstate, &op->u);
@@ -1700,14 +1706,7 @@
 			if (need_wrongsec_check(rqstp))
 				op->status = check_nfsd_access(current_fh->fh_export, rqstp);
 		}
-
 encode_op:
-		/* Only from SEQUENCE */
-		if (cstate->status == nfserr_replay_cache) {
-			dprintk("%s NFS4.1 replay from cache\n", __func__);
-			status = op->status;
-			goto out;
-		}
 		if (op->status == nfserr_replay_me) {
 			op->replay = &cstate->replay_owner->so_replay;
 			nfsd4_encode_replay(&resp->xdr, op);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6b800b5..c7f1ce4 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -553,8 +553,8 @@
 	return co;
 }
 
-struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
-					 struct kmem_cache *slab)
+struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
+				  void (*sc_free)(struct nfs4_stid *))
 {
 	struct nfs4_stid *stid;
 	int new_id;
@@ -570,6 +570,8 @@
 	idr_preload_end();
 	if (new_id < 0)
 		goto out_free;
+
+	stid->sc_free = sc_free;
 	stid->sc_client = cl;
 	stid->sc_stateid.si_opaque.so_id = new_id;
 	stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid;
@@ -595,15 +597,12 @@
 static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp)
 {
 	struct nfs4_stid *stid;
-	struct nfs4_ol_stateid *stp;
 
-	stid = nfs4_alloc_stid(clp, stateid_slab);
+	stid = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_ol_stateid);
 	if (!stid)
 		return NULL;
 
-	stp = openlockstateid(stid);
-	stp->st_stid.sc_free = nfs4_free_ol_stateid;
-	return stp;
+	return openlockstateid(stid);
 }
 
 static void nfs4_free_deleg(struct nfs4_stid *stid)
@@ -701,11 +700,10 @@
 		goto out_dec;
 	if (delegation_blocked(&current_fh->fh_handle))
 		goto out_dec;
-	dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab));
+	dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab, nfs4_free_deleg));
 	if (dp == NULL)
 		goto out_dec;
 
-	dp->dl_stid.sc_free = nfs4_free_deleg;
 	/*
 	 * delegation seqid's are never incremented.  The 4.1 special
 	 * meaning of seqid 0 isn't meaningful, really, but let's avoid
@@ -1200,27 +1198,6 @@
 	}
 }
 
-static void release_lockowner(struct nfs4_lockowner *lo)
-{
-	struct nfs4_client *clp = lo->lo_owner.so_client;
-	struct nfs4_ol_stateid *stp;
-	struct list_head reaplist;
-
-	INIT_LIST_HEAD(&reaplist);
-
-	spin_lock(&clp->cl_lock);
-	unhash_lockowner_locked(lo);
-	while (!list_empty(&lo->lo_owner.so_stateids)) {
-		stp = list_first_entry(&lo->lo_owner.so_stateids,
-				struct nfs4_ol_stateid, st_perstateowner);
-		WARN_ON(!unhash_lock_stateid(stp));
-		put_ol_stateid_locked(stp, &reaplist);
-	}
-	spin_unlock(&clp->cl_lock);
-	free_ol_stateid_reaplist(&reaplist);
-	nfs4_put_stateowner(&lo->lo_owner);
-}
-
 static void release_open_stateid_locks(struct nfs4_ol_stateid *open_stp,
 				       struct list_head *reaplist)
 {
@@ -3452,6 +3429,10 @@
 	struct nfs4_openowner *oo = open->op_openowner;
 	struct nfs4_ol_stateid *retstp = NULL;
 
+	/* We are moving these outside of the spinlocks to avoid the warnings */
+	mutex_init(&stp->st_mutex);
+	mutex_lock(&stp->st_mutex);
+
 	spin_lock(&oo->oo_owner.so_client->cl_lock);
 	spin_lock(&fp->fi_lock);
 
@@ -3467,13 +3448,17 @@
 	stp->st_access_bmap = 0;
 	stp->st_deny_bmap = 0;
 	stp->st_openstp = NULL;
-	init_rwsem(&stp->st_rwsem);
 	list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
 	list_add(&stp->st_perfile, &fp->fi_stateids);
 
 out_unlock:
 	spin_unlock(&fp->fi_lock);
 	spin_unlock(&oo->oo_owner.so_client->cl_lock);
+	if (retstp) {
+		mutex_lock(&retstp->st_mutex);
+		/* Not that we need to, just for neatness */
+		mutex_unlock(&stp->st_mutex);
+	}
 	return retstp;
 }
 
@@ -4300,32 +4285,34 @@
 	 */
 	if (stp) {
 		/* Stateid was found, this is an OPEN upgrade */
-		down_read(&stp->st_rwsem);
+		mutex_lock(&stp->st_mutex);
 		status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
 		if (status) {
-			up_read(&stp->st_rwsem);
+			mutex_unlock(&stp->st_mutex);
 			goto out;
 		}
 	} else {
 		stp = open->op_stp;
 		open->op_stp = NULL;
+		/*
+		 * init_open_stateid() either returns a locked stateid
+		 * it found, or initializes and locks the new one we passed in
+		 */
 		swapstp = init_open_stateid(stp, fp, open);
 		if (swapstp) {
 			nfs4_put_stid(&stp->st_stid);
 			stp = swapstp;
-			down_read(&stp->st_rwsem);
 			status = nfs4_upgrade_open(rqstp, fp, current_fh,
 						stp, open);
 			if (status) {
-				up_read(&stp->st_rwsem);
+				mutex_unlock(&stp->st_mutex);
 				goto out;
 			}
 			goto upgrade_out;
 		}
-		down_read(&stp->st_rwsem);
 		status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
 		if (status) {
-			up_read(&stp->st_rwsem);
+			mutex_unlock(&stp->st_mutex);
 			release_open_stateid(stp);
 			goto out;
 		}
@@ -4337,7 +4324,7 @@
 	}
 upgrade_out:
 	nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
-	up_read(&stp->st_rwsem);
+	mutex_unlock(&stp->st_mutex);
 
 	if (nfsd4_has_session(&resp->cstate)) {
 		if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
@@ -4872,6 +4859,32 @@
 	return nfs_ok;
 }
 
+static __be32
+nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s)
+{
+	struct nfs4_ol_stateid *stp = openlockstateid(s);
+	__be32 ret;
+
+	mutex_lock(&stp->st_mutex);
+
+	ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
+	if (ret)
+		goto out;
+
+	ret = nfserr_locks_held;
+	if (check_for_locks(stp->st_stid.sc_file,
+			    lockowner(stp->st_stateowner)))
+		goto out;
+
+	release_lock_stateid(stp);
+	ret = nfs_ok;
+
+out:
+	mutex_unlock(&stp->st_mutex);
+	nfs4_put_stid(s);
+	return ret;
+}
+
 __be32
 nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		   struct nfsd4_free_stateid *free_stateid)
@@ -4879,7 +4892,6 @@
 	stateid_t *stateid = &free_stateid->fr_stateid;
 	struct nfs4_stid *s;
 	struct nfs4_delegation *dp;
-	struct nfs4_ol_stateid *stp;
 	struct nfs4_client *cl = cstate->session->se_client;
 	__be32 ret = nfserr_bad_stateid;
 
@@ -4898,18 +4910,9 @@
 		ret = nfserr_locks_held;
 		break;
 	case NFS4_LOCK_STID:
-		ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
-		if (ret)
-			break;
-		stp = openlockstateid(s);
-		ret = nfserr_locks_held;
-		if (check_for_locks(stp->st_stid.sc_file,
-				    lockowner(stp->st_stateowner)))
-			break;
-		WARN_ON(!unhash_lock_stateid(stp));
+		atomic_inc(&s->sc_count);
 		spin_unlock(&cl->cl_lock);
-		nfs4_put_stid(s);
-		ret = nfs_ok;
+		ret = nfsd4_free_lock_stateid(stateid, s);
 		goto out;
 	case NFS4_REVOKED_DELEG_STID:
 		dp = delegstateid(s);
@@ -4950,12 +4953,12 @@
 		 * revoked delegations are kept only for free_stateid.
 		 */
 		return nfserr_bad_stateid;
-	down_write(&stp->st_rwsem);
+	mutex_lock(&stp->st_mutex);
 	status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
 	if (status == nfs_ok)
 		status = nfs4_check_fh(current_fh, &stp->st_stid);
 	if (status != nfs_ok)
-		up_write(&stp->st_rwsem);
+		mutex_unlock(&stp->st_mutex);
 	return status;
 }
 
@@ -5003,7 +5006,7 @@
 		return status;
 	oo = openowner(stp->st_stateowner);
 	if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
-		up_write(&stp->st_rwsem);
+		mutex_unlock(&stp->st_mutex);
 		nfs4_put_stid(&stp->st_stid);
 		return nfserr_bad_stateid;
 	}
@@ -5035,12 +5038,12 @@
 	oo = openowner(stp->st_stateowner);
 	status = nfserr_bad_stateid;
 	if (oo->oo_flags & NFS4_OO_CONFIRMED) {
-		up_write(&stp->st_rwsem);
+		mutex_unlock(&stp->st_mutex);
 		goto put_stateid;
 	}
 	oo->oo_flags |= NFS4_OO_CONFIRMED;
 	nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid);
-	up_write(&stp->st_rwsem);
+	mutex_unlock(&stp->st_mutex);
 	dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
 		__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
 
@@ -5116,7 +5119,7 @@
 	nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid);
 	status = nfs_ok;
 put_stateid:
-	up_write(&stp->st_rwsem);
+	mutex_unlock(&stp->st_mutex);
 	nfs4_put_stid(&stp->st_stid);
 out:
 	nfsd4_bump_seqid(cstate, status);
@@ -5169,7 +5172,7 @@
 	if (status)
 		goto out; 
 	nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid);
-	up_write(&stp->st_rwsem);
+	mutex_unlock(&stp->st_mutex);
 
 	nfsd4_close_open_stateid(stp);
 
@@ -5391,11 +5394,10 @@
 	stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner);
 	get_nfs4_file(fp);
 	stp->st_stid.sc_file = fp;
-	stp->st_stid.sc_free = nfs4_free_lock_stateid;
 	stp->st_access_bmap = 0;
 	stp->st_deny_bmap = open_stp->st_deny_bmap;
 	stp->st_openstp = open_stp;
-	init_rwsem(&stp->st_rwsem);
+	mutex_init(&stp->st_mutex);
 	list_add(&stp->st_locks, &open_stp->st_locks);
 	list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
 	spin_lock(&fp->fi_lock);
@@ -5434,7 +5436,7 @@
 	lst = find_lock_stateid(lo, fi);
 	if (lst == NULL) {
 		spin_unlock(&clp->cl_lock);
-		ns = nfs4_alloc_stid(clp, stateid_slab);
+		ns = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_lock_stateid);
 		if (ns == NULL)
 			return NULL;
 
@@ -5476,7 +5478,7 @@
 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
 			    struct nfs4_ol_stateid *ost,
 			    struct nfsd4_lock *lock,
-			    struct nfs4_ol_stateid **lst, bool *new)
+			    struct nfs4_ol_stateid **plst, bool *new)
 {
 	__be32 status;
 	struct nfs4_file *fi = ost->st_stid.sc_file;
@@ -5484,7 +5486,9 @@
 	struct nfs4_client *cl = oo->oo_owner.so_client;
 	struct inode *inode = d_inode(cstate->current_fh.fh_dentry);
 	struct nfs4_lockowner *lo;
+	struct nfs4_ol_stateid *lst;
 	unsigned int strhashval;
+	bool hashed;
 
 	lo = find_lockowner_str(cl, &lock->lk_new_owner);
 	if (!lo) {
@@ -5500,12 +5504,27 @@
 			goto out;
 	}
 
-	*lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
-	if (*lst == NULL) {
+retry:
+	lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
+	if (lst == NULL) {
 		status = nfserr_jukebox;
 		goto out;
 	}
+
+	mutex_lock(&lst->st_mutex);
+
+	/* See if it's still hashed to avoid race with FREE_STATEID */
+	spin_lock(&cl->cl_lock);
+	hashed = !list_empty(&lst->st_perfile);
+	spin_unlock(&cl->cl_lock);
+
+	if (!hashed) {
+		mutex_unlock(&lst->st_mutex);
+		nfs4_put_stid(&lst->st_stid);
+		goto retry;
+	}
 	status = nfs_ok;
+	*plst = lst;
 out:
 	nfs4_put_stateowner(&lo->lo_owner);
 	return status;
@@ -5564,7 +5583,7 @@
 					&open_stp, nn);
 		if (status)
 			goto out;
-		up_write(&open_stp->st_rwsem);
+		mutex_unlock(&open_stp->st_mutex);
 		open_sop = openowner(open_stp->st_stateowner);
 		status = nfserr_bad_stateid;
 		if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
@@ -5572,8 +5591,6 @@
 			goto out;
 		status = lookup_or_create_lock_state(cstate, open_stp, lock,
 							&lock_stp, &new);
-		if (status == nfs_ok)
-			down_write(&lock_stp->st_rwsem);
 	} else {
 		status = nfs4_preprocess_seqid_op(cstate,
 				       lock->lk_old_lock_seqid,
@@ -5677,7 +5694,7 @@
 		    seqid_mutating_err(ntohl(status)))
 			lock_sop->lo_owner.so_seqid++;
 
-		up_write(&lock_stp->st_rwsem);
+		mutex_unlock(&lock_stp->st_mutex);
 
 		/*
 		 * If this is a new, never-before-used stateid, and we are
@@ -5847,7 +5864,7 @@
 fput:
 	fput(filp);
 put_stateid:
-	up_write(&stp->st_rwsem);
+	mutex_unlock(&stp->st_mutex);
 	nfs4_put_stid(&stp->st_stid);
 out:
 	nfsd4_bump_seqid(cstate, status);
@@ -5911,6 +5928,7 @@
 	__be32 status;
 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 	struct nfs4_client *clp;
+	LIST_HEAD (reaplist);
 
 	dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
 		clid->cl_boot, clid->cl_id);
@@ -5941,9 +5959,23 @@
 		nfs4_get_stateowner(sop);
 		break;
 	}
+	if (!lo) {
+		spin_unlock(&clp->cl_lock);
+		return status;
+	}
+
+	unhash_lockowner_locked(lo);
+	while (!list_empty(&lo->lo_owner.so_stateids)) {
+		stp = list_first_entry(&lo->lo_owner.so_stateids,
+				       struct nfs4_ol_stateid,
+				       st_perstateowner);
+		WARN_ON(!unhash_lock_stateid(stp));
+		put_ol_stateid_locked(stp, &reaplist);
+	}
 	spin_unlock(&clp->cl_lock);
-	if (lo)
-		release_lockowner(lo);
+	free_ol_stateid_reaplist(&reaplist);
+	nfs4_put_stateowner(&lo->lo_owner);
+
 	return status;
 }
 
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1293520..3f68a25 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2753,9 +2753,16 @@
 	}
 #endif /* CONFIG_NFSD_PNFS */
 	if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
-		status = nfsd4_encode_bitmap(xdr, NFSD_SUPPATTR_EXCLCREAT_WORD0,
-						  NFSD_SUPPATTR_EXCLCREAT_WORD1,
-						  NFSD_SUPPATTR_EXCLCREAT_WORD2);
+		u32 supp[3];
+
+		supp[0] = nfsd_suppattrs0(minorversion);
+		supp[1] = nfsd_suppattrs1(minorversion);
+		supp[2] = nfsd_suppattrs2(minorversion);
+		supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
+		supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
+		supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
+
+		status = nfsd4_encode_bitmap(xdr, supp[0], supp[1], supp[2]);
 		if (status)
 			goto out;
 	}
@@ -4041,8 +4048,7 @@
 		struct nfsd4_getdeviceinfo *gdev)
 {
 	struct xdr_stream *xdr = &resp->xdr;
-	const struct nfsd4_layout_ops *ops =
-		nfsd4_layout_ops[gdev->gd_layout_type];
+	const struct nfsd4_layout_ops *ops;
 	u32 starting_len = xdr->buf->len, needed_len;
 	__be32 *p;
 
@@ -4059,6 +4065,7 @@
 
 	/* If maxcount is 0 then just update notifications */
 	if (gdev->gd_maxcount != 0) {
+		ops = nfsd4_layout_ops[gdev->gd_layout_type];
 		nfserr = ops->encode_getdeviceinfo(xdr, gdev);
 		if (nfserr) {
 			/*
@@ -4111,8 +4118,7 @@
 		struct nfsd4_layoutget *lgp)
 {
 	struct xdr_stream *xdr = &resp->xdr;
-	const struct nfsd4_layout_ops *ops =
-		nfsd4_layout_ops[lgp->lg_layout_type];
+	const struct nfsd4_layout_ops *ops;
 	__be32 *p;
 
 	dprintk("%s: err %d\n", __func__, nfserr);
@@ -4135,6 +4141,7 @@
 	*p++ = cpu_to_be32(lgp->lg_seg.iomode);
 	*p++ = cpu_to_be32(lgp->lg_layout_type);
 
+	ops = nfsd4_layout_ops[lgp->lg_layout_type];
 	nfserr = ops->encode_layoutget(xdr, lgp);
 out:
 	kfree(lgp->lg_content);
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index ad4e237..5be1fa6 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -656,6 +656,37 @@
 	return nfserr;
 }
 
+/*
+ * A write procedure can have a large argument, and a read procedure can
+ * have a large reply, but no NFSv2 or NFSv3 procedure has argument and
+ * reply that can both be larger than a page.  The xdr code has taken
+ * advantage of this assumption to be a sloppy about bounds checking in
+ * some cases.  Pending a rewrite of the NFSv2/v3 xdr code to fix that
+ * problem, we enforce these assumptions here:
+ */
+static bool nfs_request_too_big(struct svc_rqst *rqstp,
+				struct svc_procedure *proc)
+{
+	/*
+	 * The ACL code has more careful bounds-checking and is not
+	 * susceptible to this problem:
+	 */
+	if (rqstp->rq_prog != NFS_PROGRAM)
+		return false;
+	/*
+	 * Ditto NFSv4 (which can in theory have argument and reply both
+	 * more than a page):
+	 */
+	if (rqstp->rq_vers >= 4)
+		return false;
+	/* The reply will be small, we're OK: */
+	if (proc->pc_xdrressize > 0 &&
+	    proc->pc_xdrressize < XDR_QUADLEN(PAGE_SIZE))
+		return false;
+
+	return rqstp->rq_arg.len > PAGE_SIZE;
+}
+
 int
 nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 {
@@ -668,6 +699,11 @@
 				rqstp->rq_vers, rqstp->rq_proc);
 	proc = rqstp->rq_procinfo;
 
+	if (nfs_request_too_big(rqstp, proc)) {
+		dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
+		*statp = rpc_garbage_args;
+		return 1;
+	}
 	/*
 	 * Give the xdr decoder a chance to change this if it wants
 	 * (necessary in the NFSv4.0 compound case)
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 79d964a..bf91320 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -280,6 +280,7 @@
 					struct nfsd_writeargs *args)
 {
 	unsigned int len, hdr, dlen;
+	struct kvec *head = rqstp->rq_arg.head;
 	int v;
 
 	p = decode_fh(p, &args->fh);
@@ -300,9 +301,10 @@
 	 * Check to make sure that we got the right number of
 	 * bytes.
 	 */
-	hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
-	dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
-		- hdr;
+	hdr = (void*)p - head->iov_base;
+	if (hdr > head->iov_len)
+		return 0;
+	dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
 
 	/*
 	 * Round the length of the data which was specified up to
@@ -316,7 +318,7 @@
 		return 0;
 
 	rqstp->rq_vec[0].iov_base = (void*)p;
-	rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+	rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
 	v = 0;
 	while (len > rqstp->rq_vec[v].iov_len) {
 		len -= rqstp->rq_vec[v].iov_len;
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 77fdf4d..5134eed 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -535,7 +535,7 @@
 	unsigned char			st_access_bmap;
 	unsigned char			st_deny_bmap;
 	struct nfs4_ol_stateid		*st_openstp;
-	struct rw_semaphore		st_rwsem;
+	struct mutex			st_mutex;
 };
 
 static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
@@ -583,8 +583,8 @@
 __be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
 		     stateid_t *stateid, unsigned char typemask,
 		     struct nfs4_stid **s, struct nfsd_net *nn);
-struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
-		struct kmem_cache *slab);
+struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
+				  void (*sc_free)(struct nfs4_stid *));
 void nfs4_unhash_stid(struct nfs4_stid *s);
 void nfs4_put_stid(struct nfs4_stid *s);
 void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 994d66f..91e0c54 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -369,7 +369,7 @@
 	__be32		err;
 	int		host_err;
 	bool		get_write_count;
-	int		size_change = 0;
+	bool		size_change = (iap->ia_valid & ATTR_SIZE);
 
 	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
 		accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
@@ -382,11 +382,11 @@
 	/* Get inode */
 	err = fh_verify(rqstp, fhp, ftype, accmode);
 	if (err)
-		goto out;
+		return err;
 	if (get_write_count) {
 		host_err = fh_want_write(fhp);
 		if (host_err)
-			return nfserrno(host_err);
+			goto out;
 	}
 
 	dentry = fhp->fh_dentry;
@@ -397,20 +397,28 @@
 		iap->ia_valid &= ~ATTR_MODE;
 
 	if (!iap->ia_valid)
-		goto out;
+		return 0;
 
 	nfsd_sanitize_attrs(inode, iap);
 
+	if (check_guard && guardtime != inode->i_ctime.tv_sec)
+		return nfserr_notsync;
+
 	/*
 	 * The size case is special, it changes the file in addition to the
-	 * attributes.
+	 * attributes, and file systems don't expect it to be mixed with
+	 * "random" attribute changes.  We thus split out the size change
+	 * into a separate call to ->setattr, and do the rest as a separate
+	 * setattr call.
 	 */
-	if (iap->ia_valid & ATTR_SIZE) {
+	if (size_change) {
 		err = nfsd_get_write_access(rqstp, fhp, iap);
 		if (err)
-			goto out;
-		size_change = 1;
+			return err;
+	}
 
+	fh_lock(fhp);
+	if (size_change) {
 		/*
 		 * RFC5661, Section 18.30.4:
 		 *   Changing the size of a file with SETATTR indirectly
@@ -418,29 +426,36 @@
 		 *
 		 * (and similar for the older RFCs)
 		 */
-		if (iap->ia_size != i_size_read(inode))
-			iap->ia_valid |= ATTR_MTIME;
+		struct iattr size_attr = {
+			.ia_valid	= ATTR_SIZE | ATTR_CTIME | ATTR_MTIME,
+			.ia_size	= iap->ia_size,
+		};
+
+		host_err = notify_change(dentry, &size_attr, NULL);
+		if (host_err)
+			goto out_unlock;
+		iap->ia_valid &= ~ATTR_SIZE;
+
+		/*
+		 * Avoid the additional setattr call below if the only other
+		 * attribute that the client sends is the mtime, as we update
+		 * it as part of the size change above.
+		 */
+		if ((iap->ia_valid & ~ATTR_MTIME) == 0)
+			goto out_unlock;
 	}
 
 	iap->ia_valid |= ATTR_CTIME;
-
-	if (check_guard && guardtime != inode->i_ctime.tv_sec) {
-		err = nfserr_notsync;
-		goto out_put_write_access;
-	}
-
-	fh_lock(fhp);
 	host_err = notify_change(dentry, iap, NULL);
-	fh_unlock(fhp);
-	err = nfserrno(host_err);
 
-out_put_write_access:
+out_unlock:
+	fh_unlock(fhp);
 	if (size_change)
 		put_write_access(inode);
-	if (!err)
-		err = nfserrno(commit_metadata(fhp));
 out:
-	return err;
+	if (!host_err)
+		host_err = commit_metadata(fhp);
+	return nfserrno(host_err);
 }
 
 #if defined(CONFIG_NFSD_V4)
diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c
index a35ae35..cd39b57 100644
--- a/fs/nilfs2/btnode.c
+++ b/fs/nilfs2/btnode.c
@@ -55,7 +55,7 @@
 		brelse(bh);
 		BUG();
 	}
-	memset(bh->b_data, 0, 1 << inode->i_blkbits);
+	memset(bh->b_data, 0, i_blocksize(inode));
 	bh->b_bdev = inode->i_sb->s_bdev;
 	bh->b_blocknr = blocknr;
 	set_buffer_mapped(bh);
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index ac2f649..00877ef 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -55,7 +55,7 @@
 {
 	struct nilfs_root *root = NILFS_I(inode)->i_root;
 
-	inode_add_bytes(inode, (1 << inode->i_blkbits) * n);
+	inode_add_bytes(inode, i_blocksize(inode) * n);
 	if (root)
 		atomic64_add(n, &root->blocks_count);
 }
@@ -64,7 +64,7 @@
 {
 	struct nilfs_root *root = NILFS_I(inode)->i_root;
 
-	inode_sub_bytes(inode, (1 << inode->i_blkbits) * n);
+	inode_sub_bytes(inode, i_blocksize(inode) * n);
 	if (root)
 		atomic64_sub(n, &root->blocks_count);
 }
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index 1125f40..612a245 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -60,7 +60,7 @@
 	set_buffer_mapped(bh);
 
 	kaddr = kmap_atomic(bh->b_page);
-	memset(kaddr + bh_offset(bh), 0, 1 << inode->i_blkbits);
+	memset(kaddr + bh_offset(bh), 0, i_blocksize(inode));
 	if (init_block)
 		init_block(inode, bh, kaddr);
 	flush_dcache_page(bh->b_page);
@@ -503,7 +503,7 @@
 	struct nilfs_mdt_info *mi = NILFS_MDT(inode);
 
 	mi->mi_entry_size = entry_size;
-	mi->mi_entries_per_block = (1 << inode->i_blkbits) / entry_size;
+	mi->mi_entries_per_block = i_blocksize(inode) / entry_size;
 	mi->mi_first_entry_offset = DIV_ROUND_UP(header_size, entry_size);
 }
 
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 3b65ada..2f27c93 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -719,7 +719,7 @@
 
 		lock_page(page);
 		if (!page_has_buffers(page))
-			create_empty_buffers(page, 1 << inode->i_blkbits, 0);
+			create_empty_buffers(page, i_blocksize(inode), 0);
 		unlock_page(page);
 
 		bh = head = page_buffers(page);
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 69bd801..37e49cb 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -443,7 +443,7 @@
 	if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC)
 		return 0;
 	bytes = le16_to_cpu(sbp->s_bytes);
-	if (bytes > BLOCK_SIZE)
+	if (bytes < sumoff + 4 || bytes > BLOCK_SIZE)
 		return 0;
 	crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp,
 		       sumoff);
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index d2f97ec..e0e5f7c 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -67,18 +67,7 @@
 
 	pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-	wait_event(group->fanotify_data.access_waitq, event->response ||
-				atomic_read(&group->fanotify_data.bypass_perm));
-
-	if (!event->response) {	/* bypass_perm set */
-		/*
-		 * Event was canceled because group is being destroyed. Remove
-		 * it from group's event list because we are responsible for
-		 * freeing the permission event.
-		 */
-		fsnotify_remove_event(group, &event->fae.fse);
-		return 0;
-	}
+	wait_event(group->fanotify_data.access_waitq, event->response);
 
 	/* userspace responded, convert to something usable */
 	switch (event->response) {
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 8e8e6bc..2958e7a 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -358,16 +358,20 @@
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
 	struct fanotify_perm_event_info *event, *next;
+	struct fsnotify_event *fsn_event;
 
 	/*
-	 * There may be still new events arriving in the notification queue
-	 * but since userspace cannot use fanotify fd anymore, no event can
-	 * enter or leave access_list by now.
+	 * Stop new events from arriving in the notification queue. since
+	 * userspace cannot use fanotify fd anymore, no event can enter or
+	 * leave access_list by now either.
+	 */
+	fsnotify_group_stop_queueing(group);
+
+	/*
+	 * Process all permission events on access_list and notification queue
+	 * and simulate reply from userspace.
 	 */
 	spin_lock(&group->fanotify_data.access_lock);
-
-	atomic_inc(&group->fanotify_data.bypass_perm);
-
 	list_for_each_entry_safe(event, next, &group->fanotify_data.access_list,
 				 fae.fse.list) {
 		pr_debug("%s: found group=%p event=%p\n", __func__, group,
@@ -379,12 +383,21 @@
 	spin_unlock(&group->fanotify_data.access_lock);
 
 	/*
-	 * Since bypass_perm is set, newly queued events will not wait for
-	 * access response. Wake up the already sleeping ones now.
-	 * synchronize_srcu() in fsnotify_destroy_group() will wait for all
-	 * processes sleeping in fanotify_handle_event() waiting for access
-	 * response and thus also for all permission events to be freed.
+	 * Destroy all non-permission events. For permission events just
+	 * dequeue them and set the response. They will be freed once the
+	 * response is consumed and fanotify_get_response() returns.
 	 */
+	mutex_lock(&group->notification_mutex);
+	while (!fsnotify_notify_queue_is_empty(group)) {
+		fsn_event = fsnotify_remove_first_event(group);
+		if (!(fsn_event->mask & FAN_ALL_PERM_EVENTS))
+			fsnotify_destroy_event(group, fsn_event);
+		else
+			FANOTIFY_PE(fsn_event)->response = FAN_ALLOW;
+	}
+	mutex_unlock(&group->notification_mutex);
+
+	/* Response for all permission events it set, wakeup waiters */
 	wake_up(&group->fanotify_data.access_waitq);
 #endif
 
@@ -475,7 +488,7 @@
 	}
 
 	/* you can only watch an inode if you have read permissions on it */
-	ret = inode_permission(path->dentry->d_inode, MAY_READ);
+	ret = inode_permission2(path->mnt, path->dentry->d_inode, MAY_READ);
 	if (ret)
 		path_put(path);
 out:
@@ -755,7 +768,6 @@
 	spin_lock_init(&group->fanotify_data.access_lock);
 	init_waitqueue_head(&group->fanotify_data.access_waitq);
 	INIT_LIST_HEAD(&group->fanotify_data.access_list);
-	atomic_set(&group->fanotify_data.bypass_perm, 0);
 #endif
 	switch (flags & FAN_ALL_CLASS_BITS) {
 	case FAN_CLASS_NOTIF:
diff --git a/fs/notify/group.c b/fs/notify/group.c
index d16b62c..18eb30c 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -40,6 +40,17 @@
 }
 
 /*
+ * Stop queueing new events for this group. Once this function returns
+ * fsnotify_add_event() will not add any new events to the group's queue.
+ */
+void fsnotify_group_stop_queueing(struct fsnotify_group *group)
+{
+	mutex_lock(&group->notification_mutex);
+	group->shutdown = true;
+	mutex_unlock(&group->notification_mutex);
+}
+
+/*
  * Trying to get rid of a group. Remove all marks, flush all events and release
  * the group reference.
  * Note that another thread calling fsnotify_clear_marks_by_group() may still
@@ -47,6 +58,14 @@
  */
 void fsnotify_destroy_group(struct fsnotify_group *group)
 {
+	/*
+	 * Stop queueing new events. The code below is careful enough to not
+	 * require this but fanotify needs to stop queuing events even before
+	 * fsnotify_destroy_group() is called and this makes the other callers
+	 * of fsnotify_destroy_group() to see the same behavior.
+	 */
+	fsnotify_group_stop_queueing(group);
+
 	/* clear all inode marks for this group */
 	fsnotify_clear_marks_by_group(group);
 
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index e2893f1..4c5b43d 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -337,7 +337,7 @@
 	if (error)
 		return error;
 	/* you can only watch an inode if you have read permissions on it */
-	error = inode_permission(path->dentry->d_inode, MAY_READ);
+	error = inode_permission2(path->mnt, path->dentry->d_inode, MAY_READ);
 	if (error)
 		path_put(path);
 	return error;
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index a95d8e0..e455e83 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -82,7 +82,8 @@
  * Add an event to the group notification queue.  The group can later pull this
  * event off the queue to deal with.  The function returns 0 if the event was
  * added to the queue, 1 if the event was merged with some other queued event,
- * 2 if the queue of events has overflown.
+ * 2 if the event was not queued - either the queue of events has overflown
+ * or the group is shutting down.
  */
 int fsnotify_add_event(struct fsnotify_group *group,
 		       struct fsnotify_event *event,
@@ -96,6 +97,11 @@
 
 	mutex_lock(&group->notification_mutex);
 
+	if (group->shutdown) {
+		mutex_unlock(&group->notification_mutex);
+		return 2;
+	}
+
 	if (group->q_len >= group->max_events) {
 		ret = 2;
 		/* Queue overflow event only if it isn't already queued */
@@ -126,21 +132,6 @@
 }
 
 /*
- * Remove @event from group's notification queue. It is the responsibility of
- * the caller to destroy the event.
- */
-void fsnotify_remove_event(struct fsnotify_group *group,
-			   struct fsnotify_event *event)
-{
-	mutex_lock(&group->notification_mutex);
-	if (!list_empty(&event->list)) {
-		list_del_init(&event->list);
-		group->q_len--;
-	}
-	mutex_unlock(&group->notification_mutex);
-}
-
-/*
  * Remove and return the first event from the notification list.  It is the
  * responsibility of the caller to destroy the obtained event
  */
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 0cdf497..164307b 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -241,13 +241,11 @@
 	case ACL_TYPE_ACCESS:
 		name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
 		if (acl) {
-			umode_t mode = inode->i_mode;
-			ret = posix_acl_equiv_mode(acl, &mode);
-			if (ret < 0)
-				return ret;
+			umode_t mode;
 
-			if (ret == 0)
-				acl = NULL;
+			ret = posix_acl_update_mode(inode, &mode, &acl);
+			if (ret)
+				return ret;
 
 			ret = ocfs2_acl_set_mode(inode, di_bh,
 						 handle, mode);
@@ -322,3 +320,90 @@
 	brelse(di_bh);
 	return acl;
 }
+
+int ocfs2_acl_chmod(struct inode *inode, struct buffer_head *bh)
+{
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct posix_acl *acl;
+	int ret;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+		return 0;
+
+	acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, bh);
+	if (IS_ERR(acl) || !acl)
+		return PTR_ERR(acl);
+	ret = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (ret)
+		return ret;
+	ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
+			    acl, NULL, NULL);
+	posix_acl_release(acl);
+	return ret;
+}
+
+/*
+ * Initialize the ACLs of a new inode. If parent directory has default ACL,
+ * then clone to new inode. Called from ocfs2_mknod.
+ */
+int ocfs2_init_acl(handle_t *handle,
+		   struct inode *inode,
+		   struct inode *dir,
+		   struct buffer_head *di_bh,
+		   struct buffer_head *dir_bh,
+		   struct ocfs2_alloc_context *meta_ac,
+		   struct ocfs2_alloc_context *data_ac)
+{
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct posix_acl *acl = NULL;
+	int ret = 0, ret2;
+	umode_t mode;
+
+	if (!S_ISLNK(inode->i_mode)) {
+		if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
+			acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT,
+						   dir_bh);
+			if (IS_ERR(acl))
+				return PTR_ERR(acl);
+		}
+		if (!acl) {
+			mode = inode->i_mode & ~current_umask();
+			ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
+			if (ret) {
+				mlog_errno(ret);
+				goto cleanup;
+			}
+		}
+	}
+	if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
+		if (S_ISDIR(inode->i_mode)) {
+			ret = ocfs2_set_acl(handle, inode, di_bh,
+					    ACL_TYPE_DEFAULT, acl,
+					    meta_ac, data_ac);
+			if (ret)
+				goto cleanup;
+		}
+		mode = inode->i_mode;
+		ret = __posix_acl_create(&acl, GFP_NOFS, &mode);
+		if (ret < 0)
+			return ret;
+
+		ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
+		if (ret2) {
+			mlog_errno(ret2);
+			ret = ret2;
+			goto cleanup;
+		}
+		if (ret > 0) {
+			ret = ocfs2_set_acl(handle, inode,
+					    di_bh, ACL_TYPE_ACCESS,
+					    acl, meta_ac, data_ac);
+		}
+	}
+cleanup:
+	posix_acl_release(acl);
+	return ret;
+}
diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
index 3fce68d..2783a75 100644
--- a/fs/ocfs2/acl.h
+++ b/fs/ocfs2/acl.h
@@ -35,5 +35,10 @@
 			 struct posix_acl *acl,
 			 struct ocfs2_alloc_context *meta_ac,
 			 struct ocfs2_alloc_context *data_ac);
+extern int ocfs2_acl_chmod(struct inode *, struct buffer_head *);
+extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
+			  struct buffer_head *, struct buffer_head *,
+			  struct ocfs2_alloc_context *,
+			  struct ocfs2_alloc_context *);
 
 #endif /* OCFS2_ACL_H */
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index e6795c7..e4184bd 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -1103,7 +1103,7 @@
 	int ret = 0;
 	struct buffer_head *head, *bh, *wait[2], **wait_bh = wait;
 	unsigned int block_end, block_start;
-	unsigned int bsize = 1 << inode->i_blkbits;
+	unsigned int bsize = i_blocksize(inode);
 
 	if (!page_has_buffers(page))
 		create_empty_buffers(page, bsize, 0);
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 709fbbd..acebc35 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -2070,13 +2070,13 @@
 	spin_unlock(&o2hb_live_lock);
 }
 
-static ssize_t o2hb_heartbeat_group_threshold_show(struct config_item *item,
+static ssize_t o2hb_heartbeat_group_dead_threshold_show(struct config_item *item,
 		char *page)
 {
 	return sprintf(page, "%u\n", o2hb_dead_threshold);
 }
 
-static ssize_t o2hb_heartbeat_group_threshold_store(struct config_item *item,
+static ssize_t o2hb_heartbeat_group_dead_threshold_store(struct config_item *item,
 		const char *page, size_t count)
 {
 	unsigned long tmp;
@@ -2125,11 +2125,11 @@
 
 }
 
-CONFIGFS_ATTR(o2hb_heartbeat_group_, threshold);
+CONFIGFS_ATTR(o2hb_heartbeat_group_, dead_threshold);
 CONFIGFS_ATTR(o2hb_heartbeat_group_, mode);
 
 static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = {
-	&o2hb_heartbeat_group_attr_threshold,
+	&o2hb_heartbeat_group_attr_dead_threshold,
 	&o2hb_heartbeat_group_attr_mode,
 	NULL,
 };
diff --git a/fs/ocfs2/dlm/dlmconvert.c b/fs/ocfs2/dlm/dlmconvert.c
index f909313..2e11658 100644
--- a/fs/ocfs2/dlm/dlmconvert.c
+++ b/fs/ocfs2/dlm/dlmconvert.c
@@ -262,7 +262,6 @@
 				  struct dlm_lock *lock, int flags, int type)
 {
 	enum dlm_status status;
-	u8 old_owner = res->owner;
 
 	mlog(0, "type=%d, convert_type=%d, busy=%d\n", lock->ml.type,
 	     lock->ml.convert_type, res->state & DLM_LOCK_RES_IN_PROGRESS);
@@ -329,7 +328,6 @@
 
 	spin_lock(&res->spinlock);
 	res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
-	lock->convert_pending = 0;
 	/* if it failed, move it back to granted queue.
 	 * if master returns DLM_NORMAL and then down before sending ast,
 	 * it may have already been moved to granted queue, reset to
@@ -338,12 +336,14 @@
 		if (status != DLM_NOTQUEUED)
 			dlm_error(status);
 		dlm_revert_pending_convert(res, lock);
-	} else if ((res->state & DLM_LOCK_RES_RECOVERING) ||
-			(old_owner != res->owner)) {
-		mlog(0, "res %.*s is in recovering or has been recovered.\n",
-				res->lockname.len, res->lockname.name);
+	} else if (!lock->convert_pending) {
+		mlog(0, "%s: res %.*s, owner died and lock has been moved back "
+				"to granted list, retry convert.\n",
+				dlm->name, res->lockname.len, res->lockname.name);
 		status = DLM_RECOVERING;
 	}
+
+	lock->convert_pending = 0;
 bail:
 	spin_unlock(&res->spinlock);
 
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index b002acf..60a5f15 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -3321,6 +3321,16 @@
 	mlog(ML_BASTS, "lockres %s, level %d => %d\n", lockres->l_name,
 	     lockres->l_level, new_level);
 
+	/*
+	 * On DLM_LKF_VALBLK, fsdlm behaves differently with o2cb. It always
+	 * expects DLM_LKF_VALBLK being set if the LKB has LVB, so that
+	 * we can recover correctly from node failure. Otherwise, we may get
+	 * invalid LVB in LKB, but without DLM_SBF_VALNOTVALID being set.
+	 */
+	if (!ocfs2_is_o2cb_active() &&
+	    lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
+		lvb = 1;
+
 	if (lvb)
 		dlm_flags |= DLM_LKF_VALBLK;
 
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 0e5b451..1d73872 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -808,7 +808,7 @@
 	/* We know that zero_from is block aligned */
 	for (block_start = zero_from; block_start < zero_to;
 	     block_start = block_end) {
-		block_end = block_start + (1 << inode->i_blkbits);
+		block_end = block_start + i_blocksize(inode);
 
 		/*
 		 * block_start is block-aligned.  Bump it by one to force
@@ -1268,20 +1268,20 @@
 	if (size_change)
 		ocfs2_rw_unlock(inode, 1);
 bail:
-	brelse(bh);
 
 	/* Release quota pointers in case we acquired them */
 	for (qtype = 0; qtype < OCFS2_MAXQUOTAS; qtype++)
 		dqput(transfer_to[qtype]);
 
 	if (!status && attr->ia_valid & ATTR_MODE) {
-		status = posix_acl_chmod(inode, inode->i_mode);
+		status = ocfs2_acl_chmod(inode, bh);
 		if (status < 0)
 			mlog_errno(status);
 	}
 	if (inode_locked)
 		ocfs2_inode_unlock(inode, 1);
 
+	brelse(bh);
 	return status;
 }
 
@@ -1536,7 +1536,8 @@
 				       u64 start, u64 len)
 {
 	int ret = 0;
-	u64 tmpend, end = start + len;
+	u64 tmpend = 0;
+	u64 end = start + len;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	unsigned int csize = osb->s_clustersize;
 	handle_t *handle;
@@ -1568,18 +1569,31 @@
 	}
 
 	/*
-	 * We want to get the byte offset of the end of the 1st cluster.
+	 * If start is on a cluster boundary and end is somewhere in another
+	 * cluster, we have not COWed the cluster starting at start, unless
+	 * end is also within the same cluster. So, in this case, we skip this
+	 * first call to ocfs2_zero_range_for_truncate() truncate and move on
+	 * to the next one.
 	 */
-	tmpend = (u64)osb->s_clustersize + (start & ~(osb->s_clustersize - 1));
-	if (tmpend > end)
-		tmpend = end;
+	if ((start & (csize - 1)) != 0) {
+		/*
+		 * We want to get the byte offset of the end of the 1st
+		 * cluster.
+		 */
+		tmpend = (u64)osb->s_clustersize +
+			(start & ~(osb->s_clustersize - 1));
+		if (tmpend > end)
+			tmpend = end;
 
-	trace_ocfs2_zero_partial_clusters_range1((unsigned long long)start,
-						 (unsigned long long)tmpend);
+		trace_ocfs2_zero_partial_clusters_range1(
+			(unsigned long long)start,
+			(unsigned long long)tmpend);
 
-	ret = ocfs2_zero_range_for_truncate(inode, handle, start, tmpend);
-	if (ret)
-		mlog_errno(ret);
+		ret = ocfs2_zero_range_for_truncate(inode, handle, start,
+						    tmpend);
+		if (ret)
+			mlog_errno(ret);
+	}
 
 	if (tmpend < end) {
 		/*
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 3123408..62af955 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -259,7 +259,6 @@
 	struct ocfs2_dir_lookup_result lookup = { NULL, };
 	sigset_t oldset;
 	int did_block_signals = 0;
-	struct posix_acl *default_acl = NULL, *acl = NULL;
 	struct ocfs2_dentry_lock *dl = NULL;
 
 	trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name,
@@ -367,12 +366,6 @@
 		goto leave;
 	}
 
-	status = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
-	if (status) {
-		mlog_errno(status);
-		goto leave;
-	}
-
 	handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb,
 							    S_ISDIR(mode),
 							    xattr_credits));
@@ -421,16 +414,8 @@
 		inc_nlink(dir);
 	}
 
-	if (default_acl) {
-		status = ocfs2_set_acl(handle, inode, new_fe_bh,
-				       ACL_TYPE_DEFAULT, default_acl,
-				       meta_ac, data_ac);
-	}
-	if (!status && acl) {
-		status = ocfs2_set_acl(handle, inode, new_fe_bh,
-				       ACL_TYPE_ACCESS, acl,
-				       meta_ac, data_ac);
-	}
+	status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
+			 meta_ac, data_ac);
 
 	if (status < 0) {
 		mlog_errno(status);
@@ -472,10 +457,6 @@
 	d_instantiate(dentry, inode);
 	status = 0;
 leave:
-	if (default_acl)
-		posix_acl_release(default_acl);
-	if (acl)
-		posix_acl_release(acl);
 	if (status < 0 && did_quota_inode)
 		dquot_free_inode(inode);
 	if (handle)
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 2521198..6a0c55d 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -4248,20 +4248,12 @@
 	struct inode *inode = d_inode(old_dentry);
 	struct buffer_head *old_bh = NULL;
 	struct inode *new_orphan_inode = NULL;
-	struct posix_acl *default_acl, *acl;
-	umode_t mode;
 
 	if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb)))
 		return -EOPNOTSUPP;
 
-	mode = inode->i_mode;
-	error = posix_acl_create(dir, &mode, &default_acl, &acl);
-	if (error) {
-		mlog_errno(error);
-		return error;
-	}
 
-	error = ocfs2_create_inode_in_orphan(dir, mode,
+	error = ocfs2_create_inode_in_orphan(dir, inode->i_mode,
 					     &new_orphan_inode);
 	if (error) {
 		mlog_errno(error);
@@ -4300,16 +4292,11 @@
 	/* If the security isn't preserved, we need to re-initialize them. */
 	if (!preserve) {
 		error = ocfs2_init_security_and_acl(dir, new_orphan_inode,
-						    &new_dentry->d_name,
-						    default_acl, acl);
+						    &new_dentry->d_name);
 		if (error)
 			mlog_errno(error);
 	}
 out:
-	if (default_acl)
-		posix_acl_release(default_acl);
-	if (acl)
-		posix_acl_release(acl);
 	if (!error) {
 		error = ocfs2_mv_orphaned_inode_to_new(dir, new_orphan_inode,
 						       new_dentry);
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index 5d965e8..783bcdc 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -48,6 +48,12 @@
  */
 static struct ocfs2_stack_plugin *active_stack;
 
+inline int ocfs2_is_o2cb_active(void)
+{
+	return !strcmp(active_stack->sp_name, OCFS2_STACK_PLUGIN_O2CB);
+}
+EXPORT_SYMBOL_GPL(ocfs2_is_o2cb_active);
+
 static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name)
 {
 	struct ocfs2_stack_plugin *p;
diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h
index 66334a3..e1b3093 100644
--- a/fs/ocfs2/stackglue.h
+++ b/fs/ocfs2/stackglue.h
@@ -298,4 +298,7 @@
 int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin);
 void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin);
 
+/* In ocfs2_downconvert_lock(), we need to know which stack we are using */
+int ocfs2_is_o2cb_active(void);
+
 #endif  /* STACKGLUE_H */
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index e9164f0..877830b 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -7197,12 +7197,10 @@
  */
 int ocfs2_init_security_and_acl(struct inode *dir,
 				struct inode *inode,
-				const struct qstr *qstr,
-				struct posix_acl *default_acl,
-				struct posix_acl *acl)
+				const struct qstr *qstr)
 {
-	struct buffer_head *dir_bh = NULL;
 	int ret = 0;
+	struct buffer_head *dir_bh = NULL;
 
 	ret = ocfs2_init_security_get(inode, dir, qstr, NULL);
 	if (ret) {
@@ -7215,11 +7213,9 @@
 		mlog_errno(ret);
 		goto leave;
 	}
-
-	if (!ret && default_acl)
-		ret = ocfs2_iop_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
-	if (!ret && acl)
-		ret = ocfs2_iop_set_acl(inode, acl, ACL_TYPE_ACCESS);
+	ret = ocfs2_init_acl(NULL, inode, dir, NULL, dir_bh, NULL, NULL);
+	if (ret)
+		mlog_errno(ret);
 
 	ocfs2_inode_unlock(dir, 0);
 	brelse(dir_bh);
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
index f10d5b9..1633cc1 100644
--- a/fs/ocfs2/xattr.h
+++ b/fs/ocfs2/xattr.h
@@ -94,7 +94,5 @@
 			 bool preserve_security);
 int ocfs2_init_security_and_acl(struct inode *dir,
 				struct inode *inode,
-				const struct qstr *qstr,
-				struct posix_acl *default_acl,
-				struct posix_acl *acl);
+				const struct qstr *qstr);
 #endif /* OCFS2_XATTR_H */
diff --git a/fs/open.c b/fs/open.c
index 6a24f98..1fd96c5 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -34,8 +34,8 @@
 
 #include "internal.h"
 
-int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
-	struct file *filp)
+int do_truncate2(struct vfsmount *mnt, struct dentry *dentry, loff_t length,
+		unsigned int time_attrs, struct file *filp)
 {
 	int ret;
 	struct iattr newattrs;
@@ -60,17 +60,24 @@
 
 	mutex_lock(&dentry->d_inode->i_mutex);
 	/* Note any delegations or leases have already been broken: */
-	ret = notify_change(dentry, &newattrs, NULL);
+	ret = notify_change2(mnt, dentry, &newattrs, NULL);
 	mutex_unlock(&dentry->d_inode->i_mutex);
 	return ret;
 }
+int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+	struct file *filp)
+{
+	return do_truncate2(NULL, dentry, length, time_attrs, filp);
+}
 
 long vfs_truncate(struct path *path, loff_t length)
 {
 	struct inode *inode;
+	struct vfsmount *mnt;
 	long error;
 
 	inode = path->dentry->d_inode;
+	mnt = path->mnt;
 
 	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
 	if (S_ISDIR(inode->i_mode))
@@ -82,7 +89,7 @@
 	if (error)
 		goto out;
 
-	error = inode_permission(inode, MAY_WRITE);
+	error = inode_permission2(mnt, inode, MAY_WRITE);
 	if (error)
 		goto mnt_drop_write_and_out;
 
@@ -106,7 +113,7 @@
 	if (!error)
 		error = security_path_truncate(path);
 	if (!error)
-		error = do_truncate(path->dentry, length, 0, NULL);
+		error = do_truncate2(mnt, path->dentry, length, 0, NULL);
 
 put_write_and_out:
 	put_write_access(inode);
@@ -155,6 +162,7 @@
 {
 	struct inode *inode;
 	struct dentry *dentry;
+	struct vfsmount *mnt;
 	struct fd f;
 	int error;
 
@@ -171,6 +179,7 @@
 		small = 0;
 
 	dentry = f.file->f_path.dentry;
+	mnt = f.file->f_path.mnt;
 	inode = dentry->d_inode;
 	error = -EINVAL;
 	if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
@@ -190,7 +199,7 @@
 	if (!error)
 		error = security_path_truncate(&f.file->f_path);
 	if (!error)
-		error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, f.file);
+		error = do_truncate2(mnt, dentry, length, ATTR_MTIME|ATTR_CTIME, f.file);
 	sb_end_write(inode->i_sb);
 out_putf:
 	fdput(f);
@@ -340,6 +349,7 @@
 	struct cred *override_cred;
 	struct path path;
 	struct inode *inode;
+	struct vfsmount *mnt;
 	int res;
 	unsigned int lookup_flags = LOOKUP_FOLLOW;
 
@@ -370,6 +380,7 @@
 		goto out;
 
 	inode = d_backing_inode(path.dentry);
+	mnt = path.mnt;
 
 	if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
 		/*
@@ -381,7 +392,7 @@
 			goto out_path_release;
 	}
 
-	res = inode_permission(inode, mode | MAY_ACCESS);
+	res = inode_permission2(mnt, inode, mode | MAY_ACCESS);
 	/* SuS v2 requires we report a read only fs too */
 	if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
 		goto out_path_release;
@@ -425,7 +436,7 @@
 	if (error)
 		goto out;
 
-	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
+	error = inode_permission2(path.mnt, path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
 	if (error)
 		goto dput_and_out;
 
@@ -445,6 +456,7 @@
 {
 	struct fd f = fdget_raw(fd);
 	struct inode *inode;
+	struct vfsmount *mnt;
 	int error = -EBADF;
 
 	error = -EBADF;
@@ -452,12 +464,13 @@
 		goto out;
 
 	inode = file_inode(f.file);
+	mnt = f.file->f_path.mnt;
 
 	error = -ENOTDIR;
 	if (!S_ISDIR(inode->i_mode))
 		goto out_putf;
 
-	error = inode_permission(inode, MAY_EXEC | MAY_CHDIR);
+	error = inode_permission2(mnt, inode, MAY_EXEC | MAY_CHDIR);
 	if (!error)
 		set_fs_pwd(current->fs, &f.file->f_path);
 out_putf:
@@ -476,7 +489,7 @@
 	if (error)
 		goto out;
 
-	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
+	error = inode_permission2(path.mnt, path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
 	if (error)
 		goto dput_and_out;
 
@@ -516,7 +529,7 @@
 		goto out_unlock;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-	error = notify_change(path->dentry, &newattrs, &delegated_inode);
+	error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode);
 out_unlock:
 	mutex_unlock(&inode->i_mutex);
 	if (delegated_inode) {
@@ -596,7 +609,7 @@
 	mutex_lock(&inode->i_mutex);
 	error = security_path_chown(path, uid, gid);
 	if (!error)
-		error = notify_change(path->dentry, &newattrs, &delegated_inode);
+		error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode);
 	mutex_unlock(&inode->i_mutex);
 	if (delegated_inode) {
 		error = break_deleg_wait(&delegated_inode);
@@ -840,16 +853,12 @@
 int vfs_open(const struct path *path, struct file *file,
 	     const struct cred *cred)
 {
-	struct dentry *dentry = path->dentry;
-	struct inode *inode = dentry->d_inode;
+	struct inode *inode = vfs_select_inode(path->dentry, file->f_flags);
+
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
 
 	file->f_path = *path;
-	if (dentry->d_flags & DCACHE_OP_SELECT_INODE) {
-		inode = dentry->d_op->d_select_inode(dentry, file->f_flags);
-		if (IS_ERR(inode))
-			return PTR_ERR(inode);
-	}
-
 	return do_dentry_open(file, inode, NULL, cred);
 }
 
@@ -889,6 +898,12 @@
 	int lookup_flags = 0;
 	int acc_mode;
 
+	/*
+	 * Clear out all open flags we don't know about so that we don't report
+	 * them in fcntl(F_GETFD) or similar interfaces.
+	 */
+	flags &= VALID_OPEN_FLAGS;
+
 	if (flags & (O_CREAT | __O_TMPFILE))
 		op->mode = (mode & S_IALLUGO) | S_IFREG;
 	else
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index eff6319..63a0d0b 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -25,6 +25,7 @@
 	ssize_t list_size, size, value_size = 0;
 	char *buf, *name, *value = NULL;
 	int uninitialized_var(error);
+	size_t slen;
 
 	if (!old->d_inode->i_op->getxattr ||
 	    !new->d_inode->i_op->getxattr)
@@ -47,7 +48,18 @@
 		goto out;
 	}
 
-	for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
+	for (name = buf; list_size; name += slen) {
+		slen = strnlen(name, list_size) + 1;
+
+		/* underlying fs providing us with an broken xattr list? */
+		if (WARN_ON(slen > list_size)) {
+			error = -EIO;
+			break;
+		}
+		list_size -= slen;
+
+		if (ovl_is_private_xattr(name))
+			continue;
 retry:
 		size = vfs_getxattr(old, name, value, value_size);
 		if (size == -ERANGE)
@@ -127,6 +139,8 @@
 		len -= bytes;
 	}
 
+	if (!error)
+		error = vfs_fsync(new_file, 0);
 	fput(new_file);
 out_fput:
 	fput(old_file);
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index a2b1d7c..327177d 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -12,6 +12,7 @@
 #include <linux/xattr.h>
 #include <linux/security.h>
 #include <linux/cred.h>
+#include <linux/atomic.h>
 #include "overlayfs.h"
 
 void ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
@@ -35,8 +36,10 @@
 {
 	struct dentry *temp;
 	char name[20];
+	static atomic_t temp_id = ATOMIC_INIT(0);
 
-	snprintf(name, sizeof(name), "#%lx", (unsigned long) dentry);
+	/* counter is allowed to wrap, since temp dentries are ephemeral */
+	snprintf(name, sizeof(name), "#%x", atomic_inc_return(&temp_id));
 
 	temp = lookup_one_len(name, workdir, strlen(name));
 	if (!IS_ERR(temp) && temp->d_inode) {
@@ -511,6 +514,7 @@
 	struct dentry *upper;
 	struct dentry *opaquedir = NULL;
 	int err;
+	int flags = 0;
 
 	if (WARN_ON(!workdir))
 		return -EROFS;
@@ -540,46 +544,39 @@
 	if (err)
 		goto out_dput;
 
+	upper = lookup_one_len(dentry->d_name.name, upperdir,
+			       dentry->d_name.len);
+	err = PTR_ERR(upper);
+	if (IS_ERR(upper))
+		goto out_unlock;
+
+	err = -ESTALE;
+	if ((opaquedir && upper != opaquedir) ||
+	    (!opaquedir && ovl_dentry_upper(dentry) &&
+	     upper != ovl_dentry_upper(dentry))) {
+		goto out_dput_upper;
+	}
+
 	whiteout = ovl_whiteout(workdir, dentry);
 	err = PTR_ERR(whiteout);
 	if (IS_ERR(whiteout))
-		goto out_unlock;
+		goto out_dput_upper;
 
-	upper = ovl_dentry_upper(dentry);
-	if (!upper) {
-		upper = lookup_one_len(dentry->d_name.name, upperdir,
-				       dentry->d_name.len);
-		err = PTR_ERR(upper);
-		if (IS_ERR(upper))
-			goto kill_whiteout;
+	if (d_is_dir(upper))
+		flags = RENAME_EXCHANGE;
 
-		err = ovl_do_rename(wdir, whiteout, udir, upper, 0);
-		dput(upper);
-		if (err)
-			goto kill_whiteout;
-	} else {
-		int flags = 0;
+	err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
+	if (err)
+		goto kill_whiteout;
+	if (flags)
+		ovl_cleanup(wdir, upper);
 
-		if (opaquedir)
-			upper = opaquedir;
-		err = -ESTALE;
-		if (upper->d_parent != upperdir)
-			goto kill_whiteout;
-
-		if (is_dir)
-			flags |= RENAME_EXCHANGE;
-
-		err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
-		if (err)
-			goto kill_whiteout;
-
-		if (is_dir)
-			ovl_cleanup(wdir, upper);
-	}
 	ovl_dentry_version_inc(dentry->d_parent);
 out_d_drop:
 	d_drop(dentry);
 	dput(whiteout);
+out_dput_upper:
+	dput(upper);
 out_unlock:
 	unlock_rename(workdir, upperdir);
 out_dput:
@@ -596,21 +593,25 @@
 {
 	struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
 	struct inode *dir = upperdir->d_inode;
-	struct dentry *upper = ovl_dentry_upper(dentry);
+	struct dentry *upper;
 	int err;
 
 	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
+	upper = lookup_one_len(dentry->d_name.name, upperdir,
+			       dentry->d_name.len);
+	err = PTR_ERR(upper);
+	if (IS_ERR(upper))
+		goto out_unlock;
+
 	err = -ESTALE;
-	if (upper->d_parent == upperdir) {
-		/* Don't let d_delete() think it can reset d_inode */
-		dget(upper);
+	if (upper == ovl_dentry_upper(dentry)) {
 		if (is_dir)
 			err = vfs_rmdir(dir, upper);
 		else
 			err = vfs_unlink(dir, upper, NULL);
-		dput(upper);
 		ovl_dentry_version_inc(dentry->d_parent);
 	}
+	dput(upper);
 
 	/*
 	 * Keeping this dentry hashed would mean having to release
@@ -620,6 +621,7 @@
 	 */
 	if (!err)
 		d_drop(dentry);
+out_unlock:
 	mutex_unlock(&dir->i_mutex);
 
 	return err;
@@ -840,29 +842,39 @@
 
 	trap = lock_rename(new_upperdir, old_upperdir);
 
-	olddentry = ovl_dentry_upper(old);
-	newdentry = ovl_dentry_upper(new);
-	if (newdentry) {
+
+	olddentry = lookup_one_len(old->d_name.name, old_upperdir,
+				   old->d_name.len);
+	err = PTR_ERR(olddentry);
+	if (IS_ERR(olddentry))
+		goto out_unlock;
+
+	err = -ESTALE;
+	if (olddentry != ovl_dentry_upper(old))
+		goto out_dput_old;
+
+	newdentry = lookup_one_len(new->d_name.name, new_upperdir,
+				   new->d_name.len);
+	err = PTR_ERR(newdentry);
+	if (IS_ERR(newdentry))
+		goto out_dput_old;
+
+	err = -ESTALE;
+	if (ovl_dentry_upper(new)) {
 		if (opaquedir) {
-			newdentry = opaquedir;
-			opaquedir = NULL;
+			if (newdentry != opaquedir)
+				goto out_dput;
 		} else {
-			dget(newdentry);
+			if (newdentry != ovl_dentry_upper(new))
+				goto out_dput;
 		}
 	} else {
 		new_create = true;
-		newdentry = lookup_one_len(new->d_name.name, new_upperdir,
-					   new->d_name.len);
-		err = PTR_ERR(newdentry);
-		if (IS_ERR(newdentry))
-			goto out_unlock;
+		if (!d_is_negative(newdentry) &&
+		    (!new_opaque || !ovl_is_whiteout(newdentry)))
+			goto out_dput;
 	}
 
-	err = -ESTALE;
-	if (olddentry->d_parent != old_upperdir)
-		goto out_dput;
-	if (newdentry->d_parent != new_upperdir)
-		goto out_dput;
 	if (olddentry == trap)
 		goto out_dput;
 	if (newdentry == trap)
@@ -925,6 +937,8 @@
 
 out_dput:
 	dput(newdentry);
+out_dput_old:
+	dput(olddentry);
 out_unlock:
 	unlock_rename(new_upperdir, old_upperdir);
 out_revert_creds:
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 05ac9a9..220b04f 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -63,6 +63,9 @@
 	if (!err) {
 		upperdentry = ovl_dentry_upper(dentry);
 
+		if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+			attr->ia_valid &= ~ATTR_MODE;
+
 		mutex_lock(&upperdentry->d_inode->i_mutex);
 		err = notify_change(upperdentry, attr, NULL);
 		if (!err)
@@ -216,7 +219,7 @@
 }
 
 
-static bool ovl_is_private_xattr(const char *name)
+bool ovl_is_private_xattr(const char *name)
 {
 	return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0;
 }
@@ -274,7 +277,8 @@
 	struct path realpath;
 	enum ovl_path_type type = ovl_path_real(dentry, &realpath);
 	ssize_t res;
-	int off;
+	size_t len;
+	char *s;
 
 	res = vfs_listxattr(realpath.dentry, list, size);
 	if (res <= 0 || size == 0)
@@ -284,17 +288,19 @@
 		return res;
 
 	/* filter out private xattrs */
-	for (off = 0; off < res;) {
-		char *s = list + off;
-		size_t slen = strlen(s) + 1;
+	for (s = list, len = res; len;) {
+		size_t slen = strnlen(s, len) + 1;
 
-		BUG_ON(off + slen > res);
+		/* underlying fs providing us with an broken xattr list? */
+		if (WARN_ON(slen > len))
+			return -EIO;
 
+		len -= slen;
 		if (ovl_is_private_xattr(s)) {
 			res -= slen;
-			memmove(s, s + slen, res - off);
+			memmove(s, s + slen, len);
 		} else {
-			off += slen;
+			s += slen;
 		}
 	}
 
@@ -412,12 +418,11 @@
 	if (!inode)
 		return NULL;
 
-	mode &= S_IFMT;
-
 	inode->i_ino = get_next_ino();
 	inode->i_mode = mode;
 	inode->i_flags |= S_NOATIME | S_NOCMTIME;
 
+	mode &= S_IFMT;
 	switch (mode) {
 	case S_IFDIR:
 		inode->i_private = oe;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index e17154a..c319d5e 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -174,6 +174,7 @@
 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
 int ovl_removexattr(struct dentry *dentry, const char *name);
 struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags);
+bool ovl_is_private_xattr(const char *name);
 
 struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
 			    struct ovl_entry *oe);
@@ -181,6 +182,7 @@
 {
 	to->i_uid = from->i_uid;
 	to->i_gid = from->i_gid;
+	to->i_mode = from->i_mode;
 }
 
 /* dir.c */
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index a1acc60..d70208c 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -376,7 +376,8 @@
 static bool ovl_dentry_remote(struct dentry *dentry)
 {
 	return dentry->d_flags &
-		(DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
+		(DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE |
+		 DCACHE_OP_REAL);
 }
 
 static bool ovl_dentry_weird(struct dentry *dentry)
@@ -762,6 +763,10 @@
 		struct kstat stat = {
 			.mode = S_IFDIR | 0,
 		};
+		struct iattr attr = {
+			.ia_valid = ATTR_MODE,
+			.ia_mode = stat.mode,
+		};
 
 		if (work->d_inode) {
 			err = -EEXIST;
@@ -777,6 +782,21 @@
 		err = ovl_create_real(dir, work, &stat, NULL, NULL, true);
 		if (err)
 			goto out_dput;
+
+		err = vfs_removexattr(work, XATTR_NAME_POSIX_ACL_DEFAULT);
+		if (err && err != -ENODATA && err != -EOPNOTSUPP)
+			goto out_dput;
+
+		err = vfs_removexattr(work, XATTR_NAME_POSIX_ACL_ACCESS);
+		if (err && err != -ENODATA && err != -EOPNOTSUPP)
+			goto out_dput;
+
+		/* Clear any inherited mode bits */
+		inode_lock(work->d_inode);
+		err = notify_change(work, &attr, NULL);
+		inode_unlock(work->d_inode);
+		if (err)
+			goto out_dput;
 	}
 out_unlock:
 	mutex_unlock(&dir->i_mutex);
diff --git a/fs/pipe.c b/fs/pipe.c
index 42cf8dd..ab8dad3 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -38,6 +38,12 @@
  */
 unsigned int pipe_min_size = PAGE_SIZE;
 
+/* Maximum allocatable pages per user. Hard limit is unset by default, soft
+ * matches default values.
+ */
+unsigned long pipe_user_pages_hard;
+unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR;
+
 /*
  * We use a start+len construction, which provides full use of the 
  * allocated memory.
@@ -583,20 +589,49 @@
 	return retval;
 }
 
+static void account_pipe_buffers(struct pipe_inode_info *pipe,
+                                 unsigned long old, unsigned long new)
+{
+	atomic_long_add(new - old, &pipe->user->pipe_bufs);
+}
+
+static bool too_many_pipe_buffers_soft(struct user_struct *user)
+{
+	return pipe_user_pages_soft &&
+	       atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft;
+}
+
+static bool too_many_pipe_buffers_hard(struct user_struct *user)
+{
+	return pipe_user_pages_hard &&
+	       atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard;
+}
+
 struct pipe_inode_info *alloc_pipe_info(void)
 {
 	struct pipe_inode_info *pipe;
 
 	pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
 	if (pipe) {
-		pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL);
+		unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
+		struct user_struct *user = get_current_user();
+
+		if (!too_many_pipe_buffers_hard(user)) {
+			if (too_many_pipe_buffers_soft(user))
+				pipe_bufs = 1;
+			pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
+		}
+
 		if (pipe->bufs) {
 			init_waitqueue_head(&pipe->wait);
 			pipe->r_counter = pipe->w_counter = 1;
-			pipe->buffers = PIPE_DEF_BUFFERS;
+			pipe->buffers = pipe_bufs;
+			pipe->user = user;
+			account_pipe_buffers(pipe, 0, pipe_bufs);
 			mutex_init(&pipe->mutex);
 			return pipe;
 		}
+		free_uid(user);
 		kfree(pipe);
 	}
 
@@ -607,6 +642,8 @@
 {
 	int i;
 
+	account_pipe_buffers(pipe, pipe->buffers, 0);
+	free_uid(pipe->user);
 	for (i = 0; i < pipe->buffers; i++) {
 		struct pipe_buffer *buf = pipe->bufs + i;
 		if (buf->ops)
@@ -998,6 +1035,7 @@
 			memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
 	}
 
+	account_pipe_buffers(pipe, pipe->buffers, nr_pages);
 	pipe->curbuf = 0;
 	kfree(pipe->bufs);
 	pipe->bufs = bufs;
@@ -1069,6 +1107,11 @@
 		if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
 			ret = -EPERM;
 			goto out;
+		} else if ((too_many_pipe_buffers_hard(pipe->user) ||
+			    too_many_pipe_buffers_soft(pipe->user)) &&
+		           !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
+			ret = -EPERM;
+			goto out;
 		}
 		ret = pipe_set_size(pipe, nr_pages);
 		break;
diff --git a/fs/pnode.c b/fs/pnode.c
index 9989970..e4e428d 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -259,7 +259,7 @@
 		read_sequnlock_excl(&mount_lock);
 	}
 	hlist_add_head(&child->mnt_hash, list);
-	return 0;
+	return count_mounts(m->mnt_ns, child);
 }
 
 /*
@@ -324,6 +324,21 @@
 	return ret;
 }
 
+static struct mount *find_topper(struct mount *mnt)
+{
+	/* If there is exactly one mount covering mnt completely return it. */
+	struct mount *child;
+
+	if (!list_is_singular(&mnt->mnt_mounts))
+		return NULL;
+
+	child = list_first_entry(&mnt->mnt_mounts, struct mount, mnt_child);
+	if (child->mnt_mountpoint != mnt->mnt.mnt_root)
+		return NULL;
+
+	return child;
+}
+
 /*
  * return true if the refcount is greater than count
  */
@@ -344,9 +359,8 @@
  */
 int propagate_mount_busy(struct mount *mnt, int refcnt)
 {
-	struct mount *m, *child;
+	struct mount *m, *child, *topper;
 	struct mount *parent = mnt->mnt_parent;
-	int ret = 0;
 
 	if (mnt == parent)
 		return do_refcount_check(mnt, refcnt);
@@ -361,12 +375,24 @@
 
 	for (m = propagation_next(parent, parent); m;
 	     		m = propagation_next(m, parent)) {
-		child = __lookup_mnt_last(&m->mnt, mnt->mnt_mountpoint);
-		if (child && list_empty(&child->mnt_mounts) &&
-		    (ret = do_refcount_check(child, 1)))
-			break;
+		int count = 1;
+		child = __lookup_mnt(&m->mnt, mnt->mnt_mountpoint);
+		if (!child)
+			continue;
+
+		/* Is there exactly one mount on the child that covers
+		 * it completely whose reference should be ignored?
+		 */
+		topper = find_topper(child);
+		if (topper)
+			count += 1;
+		else if (!list_empty(&child->mnt_mounts))
+			continue;
+
+		if (do_refcount_check(child, count))
+			return 1;
 	}
-	return ret;
+	return 0;
 }
 
 /*
@@ -383,7 +409,7 @@
 
 	for (m = propagation_next(parent, parent); m;
 			m = propagation_next(m, parent)) {
-		child = __lookup_mnt_last(&m->mnt, mnt->mnt_mountpoint);
+		child = __lookup_mnt(&m->mnt, mnt->mnt_mountpoint);
 		if (child)
 			child->mnt.mnt_flags &= ~MNT_LOCKED;
 	}
@@ -401,9 +427,11 @@
 
 	for (m = propagation_next(parent, parent); m;
 			m = propagation_next(m, parent)) {
-		struct mount *child = __lookup_mnt_last(&m->mnt,
+		struct mount *child = __lookup_mnt(&m->mnt,
 						mnt->mnt_mountpoint);
-		if (child && (!IS_MNT_LOCKED(child) || IS_MNT_MARKED(m))) {
+		if (!child || (child->mnt.mnt_flags & MNT_UMOUNT))
+			continue;
+		if (!IS_MNT_LOCKED(child) || IS_MNT_MARKED(m)) {
 			SET_MNT_MARK(child);
 		}
 	}
@@ -422,8 +450,8 @@
 
 	for (m = propagation_next(parent, parent); m;
 			m = propagation_next(m, parent)) {
-
-		struct mount *child = __lookup_mnt_last(&m->mnt,
+		struct mount *topper;
+		struct mount *child = __lookup_mnt(&m->mnt,
 						mnt->mnt_mountpoint);
 		/*
 		 * umount the child only if the child has no children
@@ -432,6 +460,15 @@
 		if (!child || !IS_MNT_MARKED(child))
 			continue;
 		CLEAR_MNT_MARK(child);
+
+		/* If there is exactly one mount covering all of child
+		 * replace child with that mount.
+		 */
+		topper = find_topper(child);
+		if (topper)
+			mnt_change_mountpoint(child->mnt_parent, child->mnt_mp,
+					      topper);
+
 		if (list_empty(&child->mnt_mounts)) {
 			list_del_init(&child->mnt_child);
 			child->mnt.mnt_flags |= MNT_UMOUNT;
@@ -458,3 +495,37 @@
 		__propagate_umount(mnt);
 	return 0;
 }
+
+/*
+ *  Iterates over all slaves, and slaves of slaves.
+ */
+static struct mount *next_descendent(struct mount *root, struct mount *cur)
+{
+	if (!IS_MNT_NEW(cur) && !list_empty(&cur->mnt_slave_list))
+		return first_slave(cur);
+	do {
+		struct mount *master = cur->mnt_master;
+
+		if (!master || cur->mnt_slave.next != &master->mnt_slave_list) {
+			struct mount *next = next_slave(cur);
+
+			return (next == root) ? NULL : next;
+		}
+		cur = master;
+	} while (cur != root);
+	return NULL;
+}
+
+void propagate_remount(struct mount *mnt)
+{
+	struct mount *m = mnt;
+	struct super_block *sb = mnt->mnt.mnt_sb;
+
+	if (sb->s_op->copy_mnt_data) {
+		m = next_descendent(mnt, m);
+		while (m) {
+			sb->s_op->copy_mnt_data(m->mnt.data, mnt->mnt.data);
+			m = next_descendent(mnt, m);
+		}
+	}
+}
diff --git a/fs/pnode.h b/fs/pnode.h
index 0fcdbe7..a9a6576 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -44,12 +44,16 @@
 int propagate_umount(struct list_head *);
 int propagate_mount_busy(struct mount *, int);
 void propagate_mount_unlock(struct mount *);
+void propagate_remount(struct mount *);
 void mnt_release_group_id(struct mount *);
 int get_dominating_id(struct mount *mnt, const struct path *root);
 unsigned int mnt_get_count(struct mount *mnt);
 void mnt_set_mountpoint(struct mount *, struct mountpoint *,
 			struct mount *);
+void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp,
+			   struct mount *mnt);
 struct mount *copy_tree(struct mount *, struct dentry *, int);
 bool is_path_reachable(struct mount *, struct dentry *,
 			 const struct path *root);
+int count_mounts(struct mnt_namespace *ns, struct mount *mnt);
 #endif /* _LINUX_PNODE_H */
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 4adde1e..993bb3b 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -592,6 +592,37 @@
 }
 EXPORT_SYMBOL_GPL(posix_acl_create);
 
+/**
+ * posix_acl_update_mode  -  update mode in set_acl
+ *
+ * Update the file mode when setting an ACL: compute the new file permission
+ * bits based on the ACL.  In addition, if the ACL is equivalent to the new
+ * file mode, set *acl to NULL to indicate that no ACL should be set.
+ *
+ * As with chmod, clear the setgit bit if the caller is not in the owning group
+ * or capable of CAP_FSETID (see inode_change_ok).
+ *
+ * Called from set_acl inode operations.
+ */
+int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
+			  struct posix_acl **acl)
+{
+	umode_t mode = inode->i_mode;
+	int error;
+
+	error = posix_acl_equiv_mode(*acl, &mode);
+	if (error < 0)
+		return error;
+	if (error == 0)
+		*acl = NULL;
+	if (!in_group_p(inode->i_gid) &&
+	    !capable_wrt_inode_uidgid(inode, CAP_FSETID))
+		mode &= ~S_ISGID;
+	*mode_p = mode;
+	return 0;
+}
+EXPORT_SYMBOL(posix_acl_update_mode);
+
 /*
  * Fix up the uids and gids in posix acl extended attributes in place.
  */
@@ -788,6 +819,28 @@
 	return error;
 }
 
+int
+set_posix_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+	if (!IS_POSIXACL(inode))
+		return -EOPNOTSUPP;
+	if (!inode->i_op->set_acl)
+		return -EOPNOTSUPP;
+
+	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
+		return acl ? -EACCES : 0;
+	if (!inode_owner_or_capable(inode))
+		return -EPERM;
+
+	if (acl) {
+		int ret = posix_acl_valid(acl);
+		if (ret)
+			return ret;
+	}
+	return inode->i_op->set_acl(inode, acl, type);
+}
+EXPORT_SYMBOL(set_posix_acl);
+
 static int
 posix_acl_xattr_set(const struct xattr_handler *handler,
 		    struct dentry *dentry, const char *name,
@@ -799,30 +852,13 @@
 
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
-	if (!IS_POSIXACL(inode))
-		return -EOPNOTSUPP;
-	if (!inode->i_op->set_acl)
-		return -EOPNOTSUPP;
-
-	if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
-		return value ? -EACCES : 0;
-	if (!inode_owner_or_capable(inode))
-		return -EPERM;
 
 	if (value) {
 		acl = posix_acl_from_xattr(&init_user_ns, value, size);
 		if (IS_ERR(acl))
 			return PTR_ERR(acl);
-
-		if (acl) {
-			ret = posix_acl_valid(acl);
-			if (ret)
-				goto out;
-		}
 	}
-
-	ret = inode->i_op->set_acl(inode, acl, handler->flags);
-out:
+	ret = set_posix_acl(inode, handler->flags, acl);
 	posix_acl_release(acl);
 	return ret;
 }
@@ -867,11 +903,10 @@
 	int error;
 
 	if (type == ACL_TYPE_ACCESS) {
-		error = posix_acl_equiv_mode(acl, &inode->i_mode);
-		if (error < 0)
-			return 0;
-		if (error == 0)
-			acl = NULL;
+		error = posix_acl_update_mode(inode,
+				&inode->i_mode, &acl);
+		if (error)
+			return error;
 	}
 
 	inode->i_ctime = CURRENT_TIME;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index f171c7e..deafb88 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1545,18 +1545,13 @@
 static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
 {
 	struct task_struct *task;
-	struct mm_struct *mm;
 	struct file *exe_file;
 
 	task = get_proc_task(d_inode(dentry));
 	if (!task)
 		return -ENOENT;
-	mm = get_task_mm(task);
+	exe_file = get_task_exe_file(task);
 	put_task_struct(task);
-	if (!mm)
-		return -ENOENT;
-	exe_file = get_mm_exe_file(mm);
-	mmput(mm);
 	if (exe_file) {
 		*exe_path = exe_file->f_path;
 		path_get(&exe_file->f_path);
@@ -2261,16 +2256,27 @@
 	if (!p)
 		return -ESRCH;
 
-	if (ptrace_may_access(p, PTRACE_MODE_ATTACH_FSCREDS)) {
-		task_lock(p);
-		if (slack_ns == 0)
-			p->timer_slack_ns = p->default_timer_slack_ns;
-		else
-			p->timer_slack_ns = slack_ns;
-		task_unlock(p);
-	} else
-		count = -EPERM;
+	if (p != current) {
+		if (!capable(CAP_SYS_NICE)) {
+			count = -EPERM;
+			goto out;
+		}
 
+		err = security_task_setscheduler(p);
+		if (err) {
+			count = err;
+			goto out;
+		}
+	}
+
+	task_lock(p);
+	if (slack_ns == 0)
+		p->timer_slack_ns = p->default_timer_slack_ns;
+	else
+		p->timer_slack_ns = slack_ns;
+	task_unlock(p);
+
+out:
 	put_task_struct(p);
 
 	return count;
@@ -2280,19 +2286,28 @@
 {
 	struct inode *inode = m->private;
 	struct task_struct *p;
-	int err =  0;
+	int err = 0;
 
 	p = get_proc_task(inode);
 	if (!p)
 		return -ESRCH;
 
-	if (ptrace_may_access(p, PTRACE_MODE_ATTACH_FSCREDS)) {
-		task_lock(p);
-		seq_printf(m, "%llu\n", p->timer_slack_ns);
-		task_unlock(p);
-	} else
-		err = -EPERM;
+	if (p != current) {
 
+		if (!capable(CAP_SYS_NICE)) {
+			err = -EPERM;
+			goto out;
+		}
+		err = security_task_getscheduler(p);
+		if (err)
+			goto out;
+	}
+
+	task_lock(p);
+	seq_printf(m, "%llu\n", p->timer_slack_ns);
+	task_unlock(p);
+
+out:
 	put_task_struct(p);
 
 	return err;
@@ -3130,6 +3145,8 @@
 	     iter.tgid += 1, iter = next_tgid(ns, iter)) {
 		char name[PROC_NUMBUF];
 		int len;
+
+		cond_resched();
 		if (!has_pid_permissions(ns, iter.task, 2))
 			continue;
 
@@ -3150,7 +3167,7 @@
  * used for the node /proc/<pid>/task/<tid>/comm.
  * It bypasses generic permission checks in the case where a task of the same
  * task group attempts to access the node.
- * The rationale behind this is that glibc and bionic access this node for
+ * The rational behind this is that glibc and bionic access this node for
  * cross thread naming (pthread_set/getname_np(!self)). However, if
  * PR_SET_DUMPABLE gets set to 0 this node among others becomes uid=0 gid=0,
  * which locks out the cross thread naming implementation.
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index ff3ffc7..3773335 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -469,6 +469,7 @@
 		ent->data = NULL;
 		ent->proc_fops = NULL;
 		ent->proc_iops = NULL;
+		parent->nlink++;
 		if (proc_register(parent, ent) < 0) {
 			kfree(ent);
 			parent->nlink--;
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 92e6726..21f198a 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -430,6 +430,7 @@
 static ssize_t
 read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 {
+	char *buf = file->private_data;
 	ssize_t acc = 0;
 	size_t size, tsz;
 	size_t elf_buflen;
@@ -500,23 +501,20 @@
 			if (clear_user(buffer, tsz))
 				return -EFAULT;
 		} else if (is_vmalloc_or_module_addr((void *)start)) {
-			char * elf_buf;
-
-			elf_buf = kzalloc(tsz, GFP_KERNEL);
-			if (!elf_buf)
-				return -ENOMEM;
-			vread(elf_buf, (char *)start, tsz);
+			vread(buf, (char *)start, tsz);
 			/* we have to zero-fill user buffer even if no read */
-			if (copy_to_user(buffer, elf_buf, tsz)) {
-				kfree(elf_buf);
+			if (copy_to_user(buffer, buf, tsz))
 				return -EFAULT;
-			}
-			kfree(elf_buf);
 		} else {
 			if (kern_addr_valid(start)) {
 				unsigned long n;
 
-				n = copy_to_user(buffer, (char *)start, tsz);
+				/*
+				 * Using bounce buffer to bypass the
+				 * hardened user copy kernel text checks.
+				 */
+				memcpy(buf, (char *) start, tsz);
+				n = copy_to_user(buffer, buf, tsz);
 				/*
 				 * We cannot distinguish between fault on source
 				 * and fault on destination. When this happens
@@ -549,6 +547,11 @@
 {
 	if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
+
+	filp->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!filp->private_data)
+		return -ENOMEM;
+
 	if (kcore_need_update)
 		kcore_update_ram();
 	if (i_size_read(inode) != proc_root_kcore->size) {
@@ -559,10 +562,16 @@
 	return 0;
 }
 
+static int release_kcore(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	return 0;
+}
 
 static const struct file_operations proc_kcore_operations = {
 	.read		= read_kcore,
 	.open		= open_kcore,
+	.release	= release_kcore,
 	.llseek		= default_llseek,
 };
 
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index fe5b6e6..4dbe1e2 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -703,7 +703,7 @@
 	ctl_dir = container_of(head, struct ctl_dir, header);
 
 	if (!dir_emit_dots(file, ctx))
-		return 0;
+		goto out;
 
 	pos = 2;
 
@@ -713,6 +713,7 @@
 			break;
 		}
 	}
+out:
 	sysctl_head_finish(head);
 	return 0;
 }
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 361ab4e..ec649c9 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -121,6 +121,13 @@
 	if (IS_ERR(sb))
 		return ERR_CAST(sb);
 
+	/*
+	 * procfs isn't actually a stacking filesystem; however, there is
+	 * too much magic going on inside it to permit stacking things on
+	 * top of it
+	 */
+	sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH;
+
 	if (!proc_parse_options(options, ns)) {
 		deactivate_locked_super(sb);
 		return ERR_PTR(-EINVAL);
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 3e97da3..fa0af59 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -298,23 +298,29 @@
 				sizeof(struct proc_maps_private));
 }
 
-static pid_t pid_of_stack(struct proc_maps_private *priv,
-				struct vm_area_struct *vma, bool is_pid)
+/*
+ * Indicate if the VMA is a stack for the given task; for
+ * /proc/PID/maps that is the stack of the main task.
+ */
+static int is_stack(struct proc_maps_private *priv,
+		    struct vm_area_struct *vma, int is_pid)
 {
-	struct inode *inode = priv->inode;
-	struct task_struct *task;
-	pid_t ret = 0;
+	int stack = 0;
 
-	rcu_read_lock();
-	task = pid_task(proc_pid(inode), PIDTYPE_PID);
-	if (task) {
-		task = task_of_stack(task, vma, is_pid);
+	if (is_pid) {
+		stack = vma->vm_start <= vma->vm_mm->start_stack &&
+			vma->vm_end >= vma->vm_mm->start_stack;
+	} else {
+		struct inode *inode = priv->inode;
+		struct task_struct *task;
+
+		rcu_read_lock();
+		task = pid_task(proc_pid(inode), PIDTYPE_PID);
 		if (task)
-			ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info);
+			stack = vma_is_stack_for_task(vma, task);
+		rcu_read_unlock();
 	}
-	rcu_read_unlock();
-
-	return ret;
+	return stack;
 }
 
 static void
@@ -339,11 +345,7 @@
 
 	/* We don't show the stack guard page in /proc/maps */
 	start = vma->vm_start;
-	if (stack_guard_page_start(vma, start))
-		start += PAGE_SIZE;
 	end = vma->vm_end;
-	if (stack_guard_page_end(vma, end))
-		end -= PAGE_SIZE;
 
 	seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
 	seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
@@ -374,8 +376,6 @@
 
 	name = arch_vma_name(vma);
 	if (!name) {
-		pid_t tid;
-
 		if (!mm) {
 			name = "[vdso]";
 			goto done;
@@ -387,20 +387,8 @@
 			goto done;
 		}
 
-		tid = pid_of_stack(priv, vma, is_pid);
-		if (tid != 0) {
-			/*
-			 * Thread stack in /proc/PID/task/TID/maps or
-			 * the main process stack.
-			 */
-			if (!is_pid || (vma->vm_start <= mm->start_stack &&
-			    vma->vm_end >= mm->start_stack)) {
-				name = "[stack]";
-			} else {
-				/* Thread stack in /proc/PID/maps */
-				seq_pad(m, ' ');
-				seq_printf(m, "[stack:%d]", tid);
-			}
+		if (is_stack(priv, vma, is_pid)) {
+			name = "[stack]";
 			goto done;
 		}
 
@@ -874,7 +862,14 @@
 static inline void clear_soft_dirty_pmd(struct vm_area_struct *vma,
 		unsigned long addr, pmd_t *pmdp)
 {
-	pmd_t pmd = pmdp_huge_get_and_clear(vma->vm_mm, addr, pmdp);
+	pmd_t pmd = *pmdp;
+
+	/* See comment in change_huge_pmd() */
+	pmdp_invalidate(vma, addr, pmdp);
+	if (pmd_dirty(*pmdp))
+		pmd = pmd_mkdirty(pmd);
+	if (pmd_young(*pmdp))
+		pmd = pmd_mkyoung(pmd);
 
 	pmd = pmd_wrprotect(pmd);
 	pmd = pmd_clear_soft_dirty(pmd);
@@ -1628,19 +1623,8 @@
 		seq_file_path(m, file, "\n\t= ");
 	} else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
 		seq_puts(m, " heap");
-	} else {
-		pid_t tid = pid_of_stack(proc_priv, vma, is_pid);
-		if (tid != 0) {
-			/*
-			 * Thread stack in /proc/PID/task/TID/maps or
-			 * the main process stack.
-			 */
-			if (!is_pid || (vma->vm_start <= mm->start_stack &&
-			    vma->vm_end >= mm->start_stack))
-				seq_puts(m, " stack");
-			else
-				seq_printf(m, " stack:%d", tid);
-		}
+	} else if (is_stack(proc_priv, vma, is_pid)) {
+		seq_puts(m, " stack");
 	}
 
 	if (is_vm_hugetlb_page(vma))
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index e0d64c9..faacb0c 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -123,23 +123,26 @@
 	return size;
 }
 
-static pid_t pid_of_stack(struct proc_maps_private *priv,
-				struct vm_area_struct *vma, bool is_pid)
+static int is_stack(struct proc_maps_private *priv,
+		    struct vm_area_struct *vma, int is_pid)
 {
-	struct inode *inode = priv->inode;
-	struct task_struct *task;
-	pid_t ret = 0;
+	struct mm_struct *mm = vma->vm_mm;
+	int stack = 0;
 
-	rcu_read_lock();
-	task = pid_task(proc_pid(inode), PIDTYPE_PID);
-	if (task) {
-		task = task_of_stack(task, vma, is_pid);
+	if (is_pid) {
+		stack = vma->vm_start <= mm->start_stack &&
+			vma->vm_end >= mm->start_stack;
+	} else {
+		struct inode *inode = priv->inode;
+		struct task_struct *task;
+
+		rcu_read_lock();
+		task = pid_task(proc_pid(inode), PIDTYPE_PID);
 		if (task)
-			ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info);
+			stack = vma_is_stack_for_task(vma, task);
+		rcu_read_unlock();
 	}
-	rcu_read_unlock();
-
-	return ret;
+	return stack;
 }
 
 /*
@@ -181,21 +184,9 @@
 	if (file) {
 		seq_pad(m, ' ');
 		seq_file_path(m, file, "");
-	} else if (mm) {
-		pid_t tid = pid_of_stack(priv, vma, is_pid);
-
-		if (tid != 0) {
-			seq_pad(m, ' ');
-			/*
-			 * Thread stack in /proc/PID/task/TID/maps or
-			 * the main process stack.
-			 */
-			if (!is_pid || (vma->vm_start <= mm->start_stack &&
-			    vma->vm_end >= mm->start_stack))
-				seq_printf(m, "[stack]");
-			else
-				seq_printf(m, "[stack:%d]", tid);
-		}
+	} else if (mm && is_stack(priv, vma, is_pid)) {
+		seq_pad(m, ' ');
+		seq_printf(m, "[stack]");
 	}
 
 	seq_putc(m, '\n');
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
index 876459559..961e597 100644
--- a/fs/proc_namespace.c
+++ b/fs/proc_namespace.c
@@ -118,7 +118,9 @@
 	if (err)
 		goto out;
 	show_mnt_opts(m, mnt);
-	if (sb->s_op->show_options)
+	if (sb->s_op->show_options2)
+			err = sb->s_op->show_options2(mnt, m, mnt_path.dentry);
+	else if (sb->s_op->show_options)
 		err = sb->s_op->show_options(m, mnt_path.dentry);
 	seq_puts(m, " 0 0\n");
 out:
@@ -178,7 +180,9 @@
 	err = show_sb_opts(m, sb);
 	if (err)
 		goto out;
-	if (sb->s_op->show_options)
+	if (sb->s_op->show_options2) {
+		err = sb->s_op->show_options2(mnt, m, mnt->mnt_root);
+	} else if (sb->s_op->show_options)
 		err = sb->s_op->show_options(m, mnt->mnt_root);
 	seq_putc(m, '\n');
 out:
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index d8c439d..ac6c78fe 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -178,7 +178,6 @@
 }
 
 static const struct file_operations pstore_file_operations = {
-	.owner		= THIS_MODULE,
 	.open		= pstore_file_open,
 	.read		= pstore_file_read,
 	.llseek		= pstore_file_llseek,
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 588461b..40a0fe0 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -431,6 +431,40 @@
 			     size, psi);
 }
 
+static int pstore_write_buf_user_compat(enum pstore_type_id type,
+			       enum kmsg_dump_reason reason,
+			       u64 *id, unsigned int part,
+			       const char __user *buf,
+			       bool compressed, size_t size,
+			       struct pstore_info *psi)
+{
+	unsigned long flags = 0;
+	size_t i, bufsize = size;
+	long ret = 0;
+
+	if (unlikely(!access_ok(VERIFY_READ, buf, size)))
+		return -EFAULT;
+	if (bufsize > psinfo->bufsize)
+		bufsize = psinfo->bufsize;
+	spin_lock_irqsave(&psinfo->buf_lock, flags);
+	for (i = 0; i < size; ) {
+		size_t c = min(size - i, bufsize);
+
+		ret = __copy_from_user(psinfo->buf, buf + i, c);
+		if (unlikely(ret != 0)) {
+			ret = -EFAULT;
+			break;
+		}
+		ret = psi->write_buf(type, reason, id, part, psinfo->buf,
+				     compressed, c, psi);
+		if (unlikely(ret < 0))
+			break;
+		i += c;
+	}
+	spin_unlock_irqrestore(&psinfo->buf_lock, flags);
+	return unlikely(ret < 0) ? ret : size;
+}
+
 /*
  * platform specific persistent storage driver registers with
  * us here. If pstore is already mounted, call the platform
@@ -453,6 +487,8 @@
 
 	if (!psi->write)
 		psi->write = pstore_write_compat;
+	if (!psi->write_buf_user)
+		psi->write_buf_user = pstore_write_buf_user_compat;
 	psinfo = psi;
 	mutex_init(&psinfo->read_mutex);
 	spin_unlock(&pstore_lock);
diff --git a/fs/pstore/pmsg.c b/fs/pstore/pmsg.c
index 7de20cd..78f6176 100644
--- a/fs/pstore/pmsg.c
+++ b/fs/pstore/pmsg.c
@@ -19,48 +19,25 @@
 #include "internal.h"
 
 static DEFINE_MUTEX(pmsg_lock);
-#define PMSG_MAX_BOUNCE_BUFFER_SIZE (2*PAGE_SIZE)
 
 static ssize_t write_pmsg(struct file *file, const char __user *buf,
 			  size_t count, loff_t *ppos)
 {
-	size_t i, buffer_size;
-	char *buffer;
+	u64 id;
+	int ret;
 
 	if (!count)
 		return 0;
 
+	/* check outside lock, page in any data. write_buf_user also checks */
 	if (!access_ok(VERIFY_READ, buf, count))
 		return -EFAULT;
 
-	buffer_size = count;
-	if (buffer_size > PMSG_MAX_BOUNCE_BUFFER_SIZE)
-		buffer_size = PMSG_MAX_BOUNCE_BUFFER_SIZE;
-	buffer = vmalloc(buffer_size);
-	if (!buffer)
-		return -ENOMEM;
-
 	mutex_lock(&pmsg_lock);
-	for (i = 0; i < count; ) {
-		size_t c = min(count - i, buffer_size);
-		u64 id;
-		long ret;
-
-		ret = __copy_from_user(buffer, buf + i, c);
-		if (unlikely(ret != 0)) {
-			mutex_unlock(&pmsg_lock);
-			vfree(buffer);
-			return -EFAULT;
-		}
-		psinfo->write_buf(PSTORE_TYPE_PMSG, 0, &id, 0, buffer, 0, c,
-				  psinfo);
-
-		i += c;
-	}
-
+	ret = psinfo->write_buf_user(PSTORE_TYPE_PMSG, 0, &id, 0, buf, 0, count,
+				     psinfo);
 	mutex_unlock(&pmsg_lock);
-	vfree(buffer);
-	return count;
+	return ret ? ret : count;
 }
 
 static const struct file_operations pmsg_fops = {
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index a140f81..8d1e5e2 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -331,6 +331,24 @@
 	return 0;
 }
 
+static int notrace ramoops_pstore_write_buf_user(enum pstore_type_id type,
+						 enum kmsg_dump_reason reason,
+						 u64 *id, unsigned int part,
+						 const char __user *buf,
+						 bool compressed, size_t size,
+						 struct pstore_info *psi)
+{
+	if (type == PSTORE_TYPE_PMSG) {
+		struct ramoops_context *cxt = psi->data;
+
+		if (!cxt->mprz)
+			return -ENOMEM;
+		return persistent_ram_write_user(cxt->mprz, buf, size);
+	}
+
+	return -EINVAL;
+}
+
 static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
 				struct timespec time, struct pstore_info *psi)
 {
@@ -369,6 +387,7 @@
 		.open	= ramoops_pstore_open,
 		.read	= ramoops_pstore_read,
 		.write_buf	= ramoops_pstore_write_buf,
+		.write_buf_user	= ramoops_pstore_write_buf_user,
 		.erase	= ramoops_pstore_erase,
 	},
 };
@@ -377,13 +396,14 @@
 {
 	int i;
 
-	cxt->max_dump_cnt = 0;
 	if (!cxt->przs)
 		return;
 
-	for (i = 0; !IS_ERR_OR_NULL(cxt->przs[i]); i++)
+	for (i = 0; i < cxt->max_dump_cnt; i++)
 		persistent_ram_free(cxt->przs[i]);
+
 	kfree(cxt->przs);
+	cxt->max_dump_cnt = 0;
 }
 
 static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
@@ -408,7 +428,7 @@
 			     GFP_KERNEL);
 	if (!cxt->przs) {
 		dev_err(dev, "failed to initialize a prz array for dumps\n");
-		goto fail_prz;
+		goto fail_mem;
 	}
 
 	for (i = 0; i < cxt->max_dump_cnt; i++) {
@@ -419,6 +439,11 @@
 			err = PTR_ERR(cxt->przs[i]);
 			dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
 				cxt->record_size, (unsigned long long)*paddr, err);
+
+			while (i > 0) {
+				i--;
+				persistent_ram_free(cxt->przs[i]);
+			}
 			goto fail_prz;
 		}
 		*paddr += cxt->record_size;
@@ -426,7 +451,9 @@
 
 	return 0;
 fail_prz:
-	ramoops_free_przs(cxt);
+	kfree(cxt->przs);
+fail_mem:
+	cxt->max_dump_cnt = 0;
 	return err;
 }
 
@@ -460,6 +487,12 @@
 	return 0;
 }
 
+void notrace ramoops_console_write_buf(const char *buf, size_t size)
+{
+	struct ramoops_context *cxt = &oops_cxt;
+	persistent_ram_write(cxt->cprz, buf, size);
+}
+
 static int ramoops_parse_dt_size(struct platform_device *pdev,
 		const char *propname, unsigned long *val)
 {
@@ -682,7 +715,6 @@
 	struct ramoops_context *cxt = &oops_cxt;
 
 	pstore_unregister(&cxt->pstore);
-	cxt->max_dump_cnt = 0;
 
 	kfree(cxt->pstore.buf);
 	cxt->pstore.bufsize = 0;
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 76c3f80..3975dee 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -17,15 +17,16 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/errno.h>
-#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/memblock.h>
+#include <linux/pstore_ram.h>
 #include <linux/rslib.h>
 #include <linux/slab.h>
+#include <linux/uaccess.h>
 #include <linux/vmalloc.h>
-#include <linux/pstore_ram.h>
 #include <asm/page.h>
 
 struct persistent_ram_buffer {
@@ -47,43 +48,10 @@
 	return atomic_read(&prz->buffer->start);
 }
 
-/* increase and wrap the start pointer, returning the old value */
-static size_t buffer_start_add_atomic(struct persistent_ram_zone *prz, size_t a)
-{
-	int old;
-	int new;
-
-	do {
-		old = atomic_read(&prz->buffer->start);
-		new = old + a;
-		while (unlikely(new >= prz->buffer_size))
-			new -= prz->buffer_size;
-	} while (atomic_cmpxchg(&prz->buffer->start, old, new) != old);
-
-	return old;
-}
-
-/* increase the size counter until it hits the max size */
-static void buffer_size_add_atomic(struct persistent_ram_zone *prz, size_t a)
-{
-	size_t old;
-	size_t new;
-
-	if (atomic_read(&prz->buffer->size) == prz->buffer_size)
-		return;
-
-	do {
-		old = atomic_read(&prz->buffer->size);
-		new = old + a;
-		if (new > prz->buffer_size)
-			new = prz->buffer_size;
-	} while (atomic_cmpxchg(&prz->buffer->size, old, new) != old);
-}
-
 static DEFINE_RAW_SPINLOCK(buffer_lock);
 
 /* increase and wrap the start pointer, returning the old value */
-static size_t buffer_start_add_locked(struct persistent_ram_zone *prz, size_t a)
+static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
 {
 	int old;
 	int new;
@@ -103,7 +71,7 @@
 }
 
 /* increase the size counter until it hits the max size */
-static void buffer_size_add_locked(struct persistent_ram_zone *prz, size_t a)
+static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
 {
 	size_t old;
 	size_t new;
@@ -124,9 +92,6 @@
 	raw_spin_unlock_irqrestore(&buffer_lock, flags);
 }
 
-static size_t (*buffer_start_add)(struct persistent_ram_zone *, size_t) = buffer_start_add_atomic;
-static void (*buffer_size_add)(struct persistent_ram_zone *, size_t) = buffer_size_add_atomic;
-
 static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
 	uint8_t *data, size_t len, uint8_t *ecc)
 {
@@ -299,10 +264,20 @@
 	const void *s, unsigned int start, unsigned int count)
 {
 	struct persistent_ram_buffer *buffer = prz->buffer;
-	memcpy(buffer->data + start, s, count);
+	memcpy_toio(buffer->data + start, s, count);
 	persistent_ram_update_ecc(prz, start, count);
 }
 
+static int notrace persistent_ram_update_user(struct persistent_ram_zone *prz,
+	const void __user *s, unsigned int start, unsigned int count)
+{
+	struct persistent_ram_buffer *buffer = prz->buffer;
+	int ret = unlikely(__copy_from_user(buffer->data + start, s, count)) ?
+		-EFAULT : 0;
+	persistent_ram_update_ecc(prz, start, count);
+	return ret;
+}
+
 void persistent_ram_save_old(struct persistent_ram_zone *prz)
 {
 	struct persistent_ram_buffer *buffer = prz->buffer;
@@ -322,8 +297,8 @@
 	}
 
 	prz->old_log_size = size;
-	memcpy(prz->old_log, &buffer->data[start], size - start);
-	memcpy(prz->old_log + size - start, &buffer->data[0], start);
+	memcpy_fromio(prz->old_log, &buffer->data[start], size - start);
+	memcpy_fromio(prz->old_log + size - start, &buffer->data[0], start);
 }
 
 int notrace persistent_ram_write(struct persistent_ram_zone *prz,
@@ -356,6 +331,38 @@
 	return count;
 }
 
+int notrace persistent_ram_write_user(struct persistent_ram_zone *prz,
+	const void __user *s, unsigned int count)
+{
+	int rem, ret = 0, c = count;
+	size_t start;
+
+	if (unlikely(!access_ok(VERIFY_READ, s, count)))
+		return -EFAULT;
+	if (unlikely(c > prz->buffer_size)) {
+		s += c - prz->buffer_size;
+		c = prz->buffer_size;
+	}
+
+	buffer_size_add(prz, c);
+
+	start = buffer_start_add(prz, c);
+
+	rem = prz->buffer_size - start;
+	if (unlikely(rem < c)) {
+		ret = persistent_ram_update_user(prz, s, start, rem);
+		s += rem;
+		c -= rem;
+		start = 0;
+	}
+	if (likely(!ret))
+		ret = persistent_ram_update_user(prz, s, start, c);
+
+	persistent_ram_update_header_ecc(prz);
+
+	return unlikely(ret) ? ret : count;
+}
+
 size_t persistent_ram_old_size(struct persistent_ram_zone *prz)
 {
 	return prz->old_log_size;
@@ -426,9 +433,6 @@
 		return NULL;
 	}
 
-	buffer_start_add = buffer_start_add_locked;
-	buffer_size_add = buffer_size_add_locked;
-
 	if (memtype)
 		va = ioremap(start, size);
 	else
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 96a1bcf..3818730 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -189,7 +189,7 @@
 	int ret = 0;
 
 	th.t_trans_id = 0;
-	blocksize = 1 << inode->i_blkbits;
+	blocksize = i_blocksize(inode);
 
 	if (logit) {
 		reiserfs_write_lock(s);
@@ -260,10 +260,10 @@
 
 const struct inode_operations reiserfs_file_inode_operations = {
 	.setattr = reiserfs_setattr,
-	.setxattr = reiserfs_setxattr,
-	.getxattr = reiserfs_getxattr,
+	.setxattr = generic_setxattr,
+	.getxattr = generic_getxattr,
 	.listxattr = reiserfs_listxattr,
-	.removexattr = reiserfs_removexattr,
+	.removexattr = generic_removexattr,
 	.permission = reiserfs_permission,
 	.get_acl = reiserfs_get_acl,
 	.set_acl = reiserfs_set_acl,
diff --git a/fs/reiserfs/ibalance.c b/fs/reiserfs/ibalance.c
index b751eea..5db6f45 100644
--- a/fs/reiserfs/ibalance.c
+++ b/fs/reiserfs/ibalance.c
@@ -1153,8 +1153,9 @@
 				       insert_ptr);
 	}
 
-	memcpy(new_insert_key_addr, &new_insert_key, KEY_SIZE);
 	insert_ptr[0] = new_insert_ptr;
+	if (new_insert_ptr)
+		memcpy(new_insert_key_addr, &new_insert_key, KEY_SIZE);
 
 	return order;
 }
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 3d8e7e6..60ba350 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -524,7 +524,7 @@
 	 * referenced in convert_tail_for_hole() that may be called from
 	 * reiserfs_get_block()
 	 */
-	bh_result->b_size = (1 << inode->i_blkbits);
+	bh_result->b_size = i_blocksize(inode);
 
 	ret = reiserfs_get_block(inode, iblock, bh_result,
 				 create | GET_BLOCK_NO_DANGLE);
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 47f9698..3ebc701 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1649,10 +1649,10 @@
 	.mknod = reiserfs_mknod,
 	.rename = reiserfs_rename,
 	.setattr = reiserfs_setattr,
-	.setxattr = reiserfs_setxattr,
-	.getxattr = reiserfs_getxattr,
+	.setxattr = generic_setxattr,
+	.getxattr = generic_getxattr,
 	.listxattr = reiserfs_listxattr,
-	.removexattr = reiserfs_removexattr,
+	.removexattr = generic_removexattr,
 	.permission = reiserfs_permission,
 	.get_acl = reiserfs_get_acl,
 	.set_acl = reiserfs_set_acl,
@@ -1667,10 +1667,10 @@
 	.follow_link = page_follow_link_light,
 	.put_link = page_put_link,
 	.setattr = reiserfs_setattr,
-	.setxattr = reiserfs_setxattr,
-	.getxattr = reiserfs_getxattr,
+	.setxattr = generic_setxattr,
+	.getxattr = generic_getxattr,
 	.listxattr = reiserfs_listxattr,
-	.removexattr = reiserfs_removexattr,
+	.removexattr = generic_removexattr,
 	.permission = reiserfs_permission,
 };
 
@@ -1679,10 +1679,10 @@
  */
 const struct inode_operations reiserfs_special_inode_operations = {
 	.setattr = reiserfs_setattr,
-	.setxattr = reiserfs_setxattr,
-	.getxattr = reiserfs_getxattr,
+	.setxattr = generic_setxattr,
+	.getxattr = generic_getxattr,
 	.listxattr = reiserfs_listxattr,
-	.removexattr = reiserfs_removexattr,
+	.removexattr = generic_removexattr,
 	.permission = reiserfs_permission,
 	.get_acl = reiserfs_get_acl,
 	.set_acl = reiserfs_set_acl,
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 4a62fe8..f9f3be5 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -190,7 +190,15 @@
 static int reiserfs_quota_on_mount(struct super_block *, int);
 #endif
 
-/* look for uncompleted unlinks and truncates and complete them */
+/*
+ * Look for uncompleted unlinks and truncates and complete them
+ *
+ * Called with superblock write locked.  If quotas are enabled, we have to
+ * release/retake lest we call dquot_quota_on_mount(), proceed to
+ * schedule_on_each_cpu() in invalidate_bdev() and deadlock waiting for the per
+ * cpu worklets to complete flush_async_commits() that in turn wait for the
+ * superblock write lock.
+ */
 static int finish_unfinished(struct super_block *s)
 {
 	INITIALIZE_PATH(path);
@@ -237,7 +245,9 @@
 				quota_enabled[i] = 0;
 				continue;
 			}
+			reiserfs_write_unlock(s);
 			ret = reiserfs_quota_on_mount(s, i);
+			reiserfs_write_lock(s);
 			if (ret < 0)
 				reiserfs_warning(s, "reiserfs-2500",
 						 "cannot turn on journaled "
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 66b26fd..a8dbc93 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -763,60 +763,6 @@
 	return xah;
 }
 
-
-/*
- * Inode operation getxattr()
- */
-ssize_t
-reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
-		  size_t size)
-{
-	const struct xattr_handler *handler;
-
-	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
-
-	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
-		return -EOPNOTSUPP;
-
-	return handler->get(handler, dentry, name, buffer, size);
-}
-
-/*
- * Inode operation setxattr()
- *
- * d_inode(dentry)->i_mutex down
- */
-int
-reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
-		  size_t size, int flags)
-{
-	const struct xattr_handler *handler;
-
-	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
-
-	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
-		return -EOPNOTSUPP;
-
-	return handler->set(handler, dentry, name, value, size, flags);
-}
-
-/*
- * Inode operation removexattr()
- *
- * d_inode(dentry)->i_mutex down
- */
-int reiserfs_removexattr(struct dentry *dentry, const char *name)
-{
-	const struct xattr_handler *handler;
-
-	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
-
-	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
-		return -EOPNOTSUPP;
-
-	return handler->set(handler, dentry, name, NULL, 0, XATTR_REPLACE);
-}
-
 struct listxattr_buf {
 	struct dir_context ctx;
 	size_t size;
diff --git a/fs/reiserfs/xattr.h b/fs/reiserfs/xattr.h
index 15dde62..613ff5a 100644
--- a/fs/reiserfs/xattr.h
+++ b/fs/reiserfs/xattr.h
@@ -2,6 +2,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/rwsem.h>
+#include <linux/xattr.h>
 
 struct inode;
 struct dentry;
@@ -18,12 +19,7 @@
 
 #ifdef CONFIG_REISERFS_FS_XATTR
 #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir)
-ssize_t reiserfs_getxattr(struct dentry *dentry, const char *name,
-			  void *buffer, size_t size);
-int reiserfs_setxattr(struct dentry *dentry, const char *name,
-		      const void *value, size_t size, int flags);
 ssize_t reiserfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
-int reiserfs_removexattr(struct dentry *dentry, const char *name);
 
 int reiserfs_xattr_get(struct inode *, const char *, void *, size_t);
 int reiserfs_xattr_set(struct inode *, const char *, const void *, size_t, int);
@@ -92,10 +88,7 @@
 
 #else
 
-#define reiserfs_getxattr NULL
-#define reiserfs_setxattr NULL
 #define reiserfs_listxattr NULL
-#define reiserfs_removexattr NULL
 
 static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
 {
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 4b34b9d..9b1824f 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -246,13 +246,9 @@
 	case ACL_TYPE_ACCESS:
 		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			error = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (error < 0)
+			error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (error)
 				return error;
-			else {
-				if (error == 0)
-					acl = NULL;
-			}
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index ac659af..60de069 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -12,26 +12,24 @@
 security_get(const struct xattr_handler *handler, struct dentry *dentry,
 	     const char *name, void *buffer, size_t size)
 {
-	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
-		return -EINVAL;
-
 	if (IS_PRIVATE(d_inode(dentry)))
 		return -EPERM;
 
-	return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
+	return reiserfs_xattr_get(d_inode(dentry),
+				  xattr_full_name(handler, name),
+				  buffer, size);
 }
 
 static int
 security_set(const struct xattr_handler *handler, struct dentry *dentry,
 	     const char *name, const void *buffer, size_t size, int flags)
 {
-	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
-		return -EINVAL;
-
 	if (IS_PRIVATE(d_inode(dentry)))
 		return -EPERM;
 
-	return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
+	return reiserfs_xattr_set(d_inode(dentry),
+				  xattr_full_name(handler, name),
+				  buffer, size, flags);
 }
 
 static size_t security_list(const struct xattr_handler *handler,
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index a338adf..ebba1eb 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -11,26 +11,24 @@
 trusted_get(const struct xattr_handler *handler, struct dentry *dentry,
 	    const char *name, void *buffer, size_t size)
 {
-	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
-		return -EINVAL;
-
 	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
 		return -EPERM;
 
-	return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
+	return reiserfs_xattr_get(d_inode(dentry),
+				  xattr_full_name(handler, name),
+				  buffer, size);
 }
 
 static int
 trusted_set(const struct xattr_handler *handler, struct dentry *dentry,
 	    const char *name, const void *buffer, size_t size, int flags)
 {
-	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
-		return -EINVAL;
-
 	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
 		return -EPERM;
 
-	return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
+	return reiserfs_xattr_set(d_inode(dentry),
+				  xattr_full_name(handler, name),
+				  buffer, size, flags);
 }
 
 static size_t trusted_list(const struct xattr_handler *handler,
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index 39c9667..6ac8a8c 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -10,24 +10,22 @@
 user_get(const struct xattr_handler *handler, struct dentry *dentry,
 	 const char *name, void *buffer, size_t size)
 {
-
-	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
-		return -EINVAL;
 	if (!reiserfs_xattrs_user(dentry->d_sb))
 		return -EOPNOTSUPP;
-	return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
+	return reiserfs_xattr_get(d_inode(dentry),
+				  xattr_full_name(handler, name),
+				  buffer, size);
 }
 
 static int
 user_set(const struct xattr_handler *handler, struct dentry *dentry,
 	 const char *name, const void *buffer, size_t size, int flags)
 {
-	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
-		return -EINVAL;
-
 	if (!reiserfs_xattrs_user(dentry->d_sb))
 		return -EOPNOTSUPP;
-	return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
+	return reiserfs_xattr_set(d_inode(dentry),
+				  xattr_full_name(handler, name),
+				  buffer, size, flags);
 }
 
 static size_t user_list(const struct xattr_handler *handler,
diff --git a/fs/romfs/super.c b/fs/romfs/super.c
index 268733c..5f4f188 100644
--- a/fs/romfs/super.c
+++ b/fs/romfs/super.c
@@ -74,6 +74,7 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/uaccess.h>
+#include <linux/major.h>
 #include "internal.h"
 
 static struct kmem_cache *romfs_inode_cachep;
@@ -415,7 +416,22 @@
 static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct super_block *sb = dentry->d_sb;
-	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
+	u64 id = 0;
+
+	/* When calling huge_encode_dev(),
+	 * use sb->s_bdev->bd_dev when,
+	 *   - CONFIG_ROMFS_ON_BLOCK defined
+	 * use sb->s_dev when,
+	 *   - CONFIG_ROMFS_ON_BLOCK undefined and
+	 *   - CONFIG_ROMFS_ON_MTD defined
+	 * leave id as 0 when,
+	 *   - CONFIG_ROMFS_ON_BLOCK undefined and
+	 *   - CONFIG_ROMFS_ON_MTD undefined
+	 */
+	if (sb->s_bdev)
+		id = huge_encode_dev(sb->s_bdev->bd_dev);
+	else if (sb->s_dev)
+		id = huge_encode_dev(sb->s_dev);
 
 	buf->f_type = ROMFS_MAGIC;
 	buf->f_namelen = ROMFS_MAXFN;
@@ -488,6 +504,11 @@
 	sb->s_flags |= MS_RDONLY | MS_NOATIME;
 	sb->s_op = &romfs_super_ops;
 
+#ifdef CONFIG_ROMFS_ON_MTD
+	/* Use same dev ID from the underlying mtdblock device */
+	if (sb->s_mtd)
+		sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index);
+#endif
 	/* read the image superblock and check it */
 	rsb = kmalloc(512, GFP_KERNEL);
 	if (!rsb)
diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c
index 971928a..13da7e5 100644
--- a/fs/sdcardfs/dentry.c
+++ b/fs/sdcardfs/dentry.c
@@ -34,6 +34,8 @@
 	struct dentry *parent_lower_dentry = NULL;
 	struct dentry *lower_cur_parent_dentry = NULL;
 	struct dentry *lower_dentry = NULL;
+	struct inode *inode;
+	struct sdcardfs_inode_data *data;
 
 	if (flags & LOOKUP_RCU)
 		return -ECHILD;
@@ -46,7 +48,8 @@
 	spin_unlock(&dentry->d_lock);
 
 	/* check uninitialized obb_dentry and
-	 * whether the base obbpath has been changed or not */
+	 * whether the base obbpath has been changed or not
+	 */
 	if (is_obbpath_invalid(dentry)) {
 		d_drop(dentry);
 		return 0;
@@ -59,6 +62,14 @@
 	lower_dentry = lower_path.dentry;
 	lower_cur_parent_dentry = dget_parent(lower_dentry);
 
+	if ((lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) {
+		err = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
+		if (err == 0) {
+			d_drop(dentry);
+			goto out;
+		}
+	}
+
 	spin_lock(&lower_dentry->d_lock);
 	if (d_unhashed(lower_dentry)) {
 		spin_unlock(&lower_dentry->d_lock);
@@ -76,17 +87,13 @@
 
 	if (dentry < lower_dentry) {
 		spin_lock(&dentry->d_lock);
-		spin_lock(&lower_dentry->d_lock);
+		spin_lock_nested(&lower_dentry->d_lock, DENTRY_D_LOCK_NESTED);
 	} else {
 		spin_lock(&lower_dentry->d_lock);
-		spin_lock(&dentry->d_lock);
+		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
 	}
 
-	if (dentry->d_name.len != lower_dentry->d_name.len) {
-		__d_drop(dentry);
-		err = 0;
-	} else if (strncasecmp(dentry->d_name.name, lower_dentry->d_name.name,
-				dentry->d_name.len) != 0) {
+	if (!qstr_case_eq(&dentry->d_name, &lower_dentry->d_name)) {
 		__d_drop(dentry);
 		err = 0;
 	}
@@ -98,6 +105,21 @@
 		spin_unlock(&dentry->d_lock);
 		spin_unlock(&lower_dentry->d_lock);
 	}
+	if (!err)
+		goto out;
+
+	/* If our top's inode is gone, we may be out of date */
+	inode = igrab(d_inode(dentry));
+	if (inode) {
+		data = top_data_get(SDCARDFS_I(inode));
+		if (!data || data->abandoned) {
+			d_drop(dentry);
+			err = 0;
+		}
+		if (data)
+			data_put(data);
+		iput(inode);
+	}
 
 out:
 	dput(parent_dentry);
@@ -110,12 +132,10 @@
 static void sdcardfs_d_release(struct dentry *dentry)
 {
 	/* release and reset the lower paths */
-	if(has_graft_path(dentry)) {
+	if (has_graft_path(dentry))
 		sdcardfs_put_reset_orig_path(dentry);
-	}
 	sdcardfs_put_reset_lower_path(dentry);
 	free_dentry_private_data(dentry);
-	return;
 }
 
 static int sdcardfs_hash_ci(const struct dentry *dentry,
@@ -132,12 +152,10 @@
 	unsigned long hash;
 
 	name = qstr->name;
-	//len = vfat_striptail_len(qstr);
 	len = qstr->len;
 
 	hash = init_name_hash();
 	while (len--)
-		//hash = partial_name_hash(nls_tolower(t, *name++), hash);
 		hash = partial_name_hash(tolower(*name++), hash);
 	qstr->hash = end_name_hash(hash);
 
@@ -151,35 +169,25 @@
 		const struct dentry *dentry,
 		unsigned int len, const char *str, const struct qstr *name)
 {
-	/* This function is copy of vfat_cmpi */
-	// FIXME Should we support national language?
-	//struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
-	//unsigned int alen, blen;
+	/* FIXME Should we support national language? */
 
-	/* A filename cannot end in '.' or we treat it like it has none */
-	/*
-	alen = vfat_striptail_len(name);
-	blen = __vfat_striptail_len(len, str);
-	if (alen == blen) {
-		if (nls_strnicmp(t, name->name, str, alen) == 0)
-			return 0;
-	}
-	*/
 	if (name->len == len) {
-		if (strncasecmp(name->name, str, len) == 0)
+		if (str_n_case_eq(name->name, str, len))
 			return 0;
 	}
 	return 1;
 }
 
-static void sdcardfs_canonical_path(const struct path *path, struct path *actual_path) {
+static void sdcardfs_canonical_path(const struct path *path,
+				struct path *actual_path)
+{
 	sdcardfs_get_real_lower(path->dentry, actual_path);
 }
 
 const struct dentry_operations sdcardfs_ci_dops = {
 	.d_revalidate	= sdcardfs_d_revalidate,
 	.d_release	= sdcardfs_d_release,
-	.d_hash 	= sdcardfs_hash_ci,
+	.d_hash	= sdcardfs_hash_ci,
 	.d_compare	= sdcardfs_cmp_ci,
 	.d_canonical_path = sdcardfs_canonical_path,
 };
diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c
index 41e0e11..85a60fb 100644
--- a/fs/sdcardfs/derived_perm.c
+++ b/fs/sdcardfs/derived_perm.c
@@ -26,100 +26,302 @@
 	struct sdcardfs_inode_info *pi = SDCARDFS_I(parent);
 	struct sdcardfs_inode_info *ci = SDCARDFS_I(child);
 
-	ci->perm = PERM_INHERIT;
-	ci->userid = pi->userid;
-	ci->d_uid = pi->d_uid;
-	ci->under_android = pi->under_android;
+	ci->data->perm = PERM_INHERIT;
+	ci->data->userid = pi->data->userid;
+	ci->data->d_uid = pi->data->d_uid;
+	ci->data->under_android = pi->data->under_android;
+	ci->data->under_cache = pi->data->under_cache;
+	ci->data->under_obb = pi->data->under_obb;
+	set_top(ci, pi->top_data);
 }
 
 /* helper function for derived state */
-void setup_derived_state(struct inode *inode, perm_t perm,
-                        userid_t userid, uid_t uid, bool under_android)
+void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid,
+					uid_t uid, bool under_android,
+					struct sdcardfs_inode_data *top)
 {
 	struct sdcardfs_inode_info *info = SDCARDFS_I(inode);
 
-	info->perm = perm;
-	info->userid = userid;
-	info->d_uid = uid;
-	info->under_android = under_android;
+	info->data->perm = perm;
+	info->data->userid = userid;
+	info->data->d_uid = uid;
+	info->data->under_android = under_android;
+	info->data->under_cache = false;
+	info->data->under_obb = false;
+	set_top(info, top);
 }
 
-/* While renaming, there is a point where we want the path from dentry, but the name from newdentry */
-void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, struct dentry *newdentry)
+/* While renaming, there is a point where we want the path from dentry,
+ * but the name from newdentry
+ */
+void get_derived_permission_new(struct dentry *parent, struct dentry *dentry,
+				const struct qstr *name)
 {
-	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
-	struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode);
-	struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
+	struct sdcardfs_inode_info *info = SDCARDFS_I(d_inode(dentry));
+	struct sdcardfs_inode_data *parent_data =
+			SDCARDFS_I(d_inode(parent))->data;
 	appid_t appid;
+	unsigned long user_num;
+	int err;
+	struct qstr q_Android = QSTR_LITERAL("Android");
+	struct qstr q_data = QSTR_LITERAL("data");
+	struct qstr q_obb = QSTR_LITERAL("obb");
+	struct qstr q_media = QSTR_LITERAL("media");
+	struct qstr q_cache = QSTR_LITERAL("cache");
 
 	/* By default, each inode inherits from its parent.
 	 * the properties are maintained on its private fields
 	 * because the inode attributes will be modified with that of
 	 * its lower inode.
-	 * The derived state will be updated on the last
-	 * stage of each system call by fix_derived_permission(inode).
+	 * These values are used by our custom permission call instead
+	 * of using the inode permissions.
 	 */
 
-	inherit_derived_state(parent->d_inode, dentry->d_inode);
+	inherit_derived_state(d_inode(parent), d_inode(dentry));
 
+	/* Files don't get special labels */
+	if (!S_ISDIR(d_inode(dentry)->i_mode))
+		return;
 	/* Derive custom permissions based on parent and current node */
-	switch (parent_info->perm) {
-		case PERM_INHERIT:
-			/* Already inherited above */
-			break;
-		case PERM_PRE_ROOT:
-			/* Legacy internal layout places users at top level */
-			info->perm = PERM_ROOT;
-			info->userid = simple_strtoul(newdentry->d_name.name, NULL, 10);
-			break;
-		case PERM_ROOT:
-			/* Assume masked off by default. */
-			if (!strcasecmp(newdentry->d_name.name, "Android")) {
-				/* App-specific directories inside; let anyone traverse */
-				info->perm = PERM_ANDROID;
-				info->under_android = true;
-			}
-			break;
-		case PERM_ANDROID:
-			if (!strcasecmp(newdentry->d_name.name, "data")) {
-				/* App-specific directories inside; let anyone traverse */
-				info->perm = PERM_ANDROID_DATA;
-			} else if (!strcasecmp(newdentry->d_name.name, "obb")) {
-				/* App-specific directories inside; let anyone traverse */
-				info->perm = PERM_ANDROID_OBB;
-				/* Single OBB directory is always shared */
-			} else if (!strcasecmp(newdentry->d_name.name, "media")) {
-				/* App-specific directories inside; let anyone traverse */
-				info->perm = PERM_ANDROID_MEDIA;
-			}
-			break;
-		case PERM_ANDROID_DATA:
-		case PERM_ANDROID_OBB:
-		case PERM_ANDROID_MEDIA:
-			appid = get_appid(sbi->pkgl_id, newdentry->d_name.name);
-			if (appid != 0) {
-				info->d_uid = multiuser_get_uid(parent_info->userid, appid);
-			}
-			break;
+	switch (parent_data->perm) {
+	case PERM_INHERIT:
+	case PERM_ANDROID_PACKAGE_CACHE:
+		/* Already inherited above */
+		break;
+	case PERM_PRE_ROOT:
+		/* Legacy internal layout places users at top level */
+		info->data->perm = PERM_ROOT;
+		err = kstrtoul(name->name, 10, &user_num);
+		if (err)
+			info->data->userid = 0;
+		else
+			info->data->userid = user_num;
+		set_top(info, info->data);
+		break;
+	case PERM_ROOT:
+		/* Assume masked off by default. */
+		if (qstr_case_eq(name, &q_Android)) {
+			/* App-specific directories inside; let anyone traverse */
+			info->data->perm = PERM_ANDROID;
+			info->data->under_android = true;
+			set_top(info, info->data);
+		}
+		break;
+	case PERM_ANDROID:
+		if (qstr_case_eq(name, &q_data)) {
+			/* App-specific directories inside; let anyone traverse */
+			info->data->perm = PERM_ANDROID_DATA;
+			set_top(info, info->data);
+		} else if (qstr_case_eq(name, &q_obb)) {
+			/* App-specific directories inside; let anyone traverse */
+			info->data->perm = PERM_ANDROID_OBB;
+			info->data->under_obb = true;
+			set_top(info, info->data);
+			/* Single OBB directory is always shared */
+		} else if (qstr_case_eq(name, &q_media)) {
+			/* App-specific directories inside; let anyone traverse */
+			info->data->perm = PERM_ANDROID_MEDIA;
+			set_top(info, info->data);
+		}
+		break;
+	case PERM_ANDROID_OBB:
+	case PERM_ANDROID_DATA:
+	case PERM_ANDROID_MEDIA:
+		info->data->perm = PERM_ANDROID_PACKAGE;
+		appid = get_appid(name->name);
+		if (appid != 0 && !is_excluded(name->name, parent_data->userid))
+			info->data->d_uid =
+				multiuser_get_uid(parent_data->userid, appid);
+		set_top(info, info->data);
+		break;
+	case PERM_ANDROID_PACKAGE:
+		if (qstr_case_eq(name, &q_cache)) {
+			info->data->perm = PERM_ANDROID_PACKAGE_CACHE;
+			info->data->under_cache = true;
+		}
+		break;
 	}
 }
 
 void get_derived_permission(struct dentry *parent, struct dentry *dentry)
 {
-	get_derived_permission_new(parent, dentry, dentry);
+	get_derived_permission_new(parent, dentry, &dentry->d_name);
 }
 
-void get_derive_permissions_recursive(struct dentry *parent) {
-	struct dentry *dentry;
-	list_for_each_entry(dentry, &parent->d_subdirs, d_child) {
-		if (dentry->d_inode) {
-			mutex_lock(&dentry->d_inode->i_mutex);
-			get_derived_permission(parent, dentry);
-			fix_derived_permission(dentry->d_inode);
-			get_derive_permissions_recursive(dentry);
-			mutex_unlock(&dentry->d_inode->i_mutex);
+static appid_t get_type(const char *name)
+{
+	const char *ext = strrchr(name, '.');
+	appid_t id;
+
+	if (ext && ext[0]) {
+		ext = &ext[1];
+		id = get_ext_gid(ext);
+		return id?:AID_MEDIA_RW;
+	}
+	return AID_MEDIA_RW;
+}
+
+void fixup_lower_ownership(struct dentry *dentry, const char *name)
+{
+	struct path path;
+	struct inode *inode;
+	struct inode *delegated_inode = NULL;
+	int error;
+	struct sdcardfs_inode_info *info;
+	struct sdcardfs_inode_data *info_d;
+	struct sdcardfs_inode_data *info_top;
+	perm_t perm;
+	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
+	uid_t uid = sbi->options.fs_low_uid;
+	gid_t gid = sbi->options.fs_low_gid;
+	struct iattr newattrs;
+
+	info = SDCARDFS_I(d_inode(dentry));
+	info_d = info->data;
+	perm = info_d->perm;
+	if (info_d->under_obb) {
+		perm = PERM_ANDROID_OBB;
+	} else if (info_d->under_cache) {
+		perm = PERM_ANDROID_PACKAGE_CACHE;
+	} else if (perm == PERM_INHERIT) {
+		info_top = top_data_get(info);
+		perm = info_top->perm;
+		data_put(info_top);
+	}
+
+	switch (perm) {
+	case PERM_ROOT:
+	case PERM_ANDROID:
+	case PERM_ANDROID_DATA:
+	case PERM_ANDROID_MEDIA:
+	case PERM_ANDROID_PACKAGE:
+	case PERM_ANDROID_PACKAGE_CACHE:
+		uid = multiuser_get_uid(info_d->userid, uid);
+		break;
+	case PERM_ANDROID_OBB:
+		uid = AID_MEDIA_OBB;
+		break;
+	case PERM_PRE_ROOT:
+	default:
+		break;
+	}
+	switch (perm) {
+	case PERM_ROOT:
+	case PERM_ANDROID:
+	case PERM_ANDROID_DATA:
+	case PERM_ANDROID_MEDIA:
+		if (S_ISDIR(d_inode(dentry)->i_mode))
+			gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW);
+		else
+			gid = multiuser_get_uid(info_d->userid, get_type(name));
+		break;
+	case PERM_ANDROID_OBB:
+		gid = AID_MEDIA_OBB;
+		break;
+	case PERM_ANDROID_PACKAGE:
+		if (uid_is_app(info_d->d_uid))
+			gid = multiuser_get_ext_gid(info_d->d_uid);
+		else
+			gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW);
+		break;
+	case PERM_ANDROID_PACKAGE_CACHE:
+		if (uid_is_app(info_d->d_uid))
+			gid = multiuser_get_ext_cache_gid(info_d->d_uid);
+		else
+			gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW);
+		break;
+	case PERM_PRE_ROOT:
+	default:
+		break;
+	}
+
+	sdcardfs_get_lower_path(dentry, &path);
+	inode = d_inode(path.dentry);
+	if (d_inode(path.dentry)->i_gid.val != gid || d_inode(path.dentry)->i_uid.val != uid) {
+retry_deleg:
+		newattrs.ia_valid = ATTR_GID | ATTR_UID | ATTR_FORCE;
+		newattrs.ia_uid = make_kuid(current_user_ns(), uid);
+		newattrs.ia_gid = make_kgid(current_user_ns(), gid);
+		if (!S_ISDIR(inode->i_mode))
+			newattrs.ia_valid |=
+				ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+		mutex_lock(&inode->i_mutex);
+		error = security_path_chown(&path, newattrs.ia_uid, newattrs.ia_gid);
+		if (!error)
+			error = notify_change2(path.mnt, path.dentry, &newattrs, &delegated_inode);
+		mutex_unlock(&inode->i_mutex);
+		if (delegated_inode) {
+			error = break_deleg_wait(&delegated_inode);
+			if (!error)
+				goto retry_deleg;
+		}
+		if (error)
+			pr_debug("sdcardfs: Failed to touch up lower fs gid/uid for %s\n", name);
+	}
+	sdcardfs_put_lower_path(dentry, &path);
+}
+
+static int descendant_may_need_fixup(struct sdcardfs_inode_data *data,
+		struct limit_search *limit)
+{
+	if (data->perm == PERM_ROOT)
+		return (limit->flags & BY_USERID) ?
+				data->userid == limit->userid : 1;
+	if (data->perm == PERM_PRE_ROOT || data->perm == PERM_ANDROID)
+		return 1;
+	return 0;
+}
+
+static int needs_fixup(perm_t perm)
+{
+	if (perm == PERM_ANDROID_DATA || perm == PERM_ANDROID_OBB
+			|| perm == PERM_ANDROID_MEDIA)
+		return 1;
+	return 0;
+}
+
+static void __fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit, int depth)
+{
+	struct dentry *child;
+	struct sdcardfs_inode_info *info;
+
+	/*
+	 * All paths will terminate their recursion on hitting PERM_ANDROID_OBB,
+	 * PERM_ANDROID_MEDIA, or PERM_ANDROID_DATA. This happens at a depth of
+	 * at most 3.
+	 */
+	WARN(depth > 3, "%s: Max expected depth exceeded!\n", __func__);
+	spin_lock_nested(&dentry->d_lock, depth);
+	if (!d_inode(dentry)) {
+		spin_unlock(&dentry->d_lock);
+		return;
+	}
+	info = SDCARDFS_I(d_inode(dentry));
+
+	if (needs_fixup(info->data->perm)) {
+		list_for_each_entry(child, &dentry->d_subdirs, d_child) {
+			spin_lock_nested(&child->d_lock, depth + 1);
+			if (!(limit->flags & BY_NAME) || qstr_case_eq(&child->d_name, &limit->name)) {
+				if (d_inode(child)) {
+					get_derived_permission(dentry, child);
+					fixup_tmp_permissions(d_inode(child));
+					spin_unlock(&child->d_lock);
+					break;
+				}
+			}
+			spin_unlock(&child->d_lock);
+		}
+	} else if (descendant_may_need_fixup(info->data, limit)) {
+		list_for_each_entry(child, &dentry->d_subdirs, d_child) {
+			__fixup_perms_recursive(child, limit, depth + 1);
 		}
 	}
+	spin_unlock(&dentry->d_lock);
+}
+
+void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit)
+{
+	__fixup_perms_recursive(dentry, limit, 0);
 }
 
 /* main function for updating derived permission */
@@ -127,41 +329,38 @@
 {
 	struct dentry *parent;
 
-	if(!dentry || !dentry->d_inode) {
-		printk(KERN_ERR "sdcardfs: %s: invalid dentry\n", __func__);
+	if (!dentry || !d_inode(dentry)) {
+		pr_err("sdcardfs: %s: invalid dentry\n", __func__);
 		return;
 	}
 	/* FIXME:
 	 * 1. need to check whether the dentry is updated or not
 	 * 2. remove the root dentry update
 	 */
-	mutex_lock(&dentry->d_inode->i_mutex);
-	if(IS_ROOT(dentry)) {
-		//setup_default_pre_root_state(dentry->d_inode);
-	} else {
+	if (!IS_ROOT(dentry)) {
 		parent = dget_parent(dentry);
-		if(parent) {
+		if (parent) {
 			get_derived_permission(parent, dentry);
 			dput(parent);
 		}
 	}
-	fix_derived_permission(dentry->d_inode);
-	mutex_unlock(&dentry->d_inode->i_mutex);
+	fixup_tmp_permissions(d_inode(dentry));
 }
 
 int need_graft_path(struct dentry *dentry)
 {
 	int ret = 0;
 	struct dentry *parent = dget_parent(dentry);
-	struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
+	struct sdcardfs_inode_info *parent_info = SDCARDFS_I(d_inode(parent));
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
+	struct qstr obb = QSTR_LITERAL("obb");
 
-	if(parent_info->perm == PERM_ANDROID &&
-			!strcasecmp(dentry->d_name.name, "obb")) {
+	if (parent_info->data->perm == PERM_ANDROID &&
+			qstr_case_eq(&dentry->d_name, &obb)) {
 
 		/* /Android/obb is the base obbpath of DERIVED_UNIFIED */
-		if(!(sbi->options.multiuser == false
-				&& parent_info->userid == 0)) {
+		if (!(sbi->options.multiuser == false
+				&& parent_info->data->userid == 0)) {
 			ret = 1;
 		}
 	}
@@ -175,36 +374,40 @@
 	struct sdcardfs_dentry_info *di = SDCARDFS_D(dent);
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dent->d_sb);
 	char *path_buf, *obbpath_s;
+	int need_put = 0;
+	struct path lower_path;
 
 	/* check the base obbpath has been changed.
 	 * this routine can check an uninitialized obb dentry as well.
-	 * regarding the uninitialized obb, refer to the sdcardfs_mkdir() */
+	 * regarding the uninitialized obb, refer to the sdcardfs_mkdir()
+	 */
 	spin_lock(&di->lock);
-	if(di->orig_path.dentry) {
- 		if(!di->lower_path.dentry) {
+	if (di->orig_path.dentry) {
+		if (!di->lower_path.dentry) {
 			ret = 1;
 		} else {
 			path_get(&di->lower_path);
-			//lower_parent = lock_parent(lower_path->dentry);
 
 			path_buf = kmalloc(PATH_MAX, GFP_ATOMIC);
-			if(!path_buf) {
+			if (!path_buf) {
 				ret = 1;
-				printk(KERN_ERR "sdcardfs: fail to allocate path_buf in %s.\n", __func__);
+				pr_err("sdcardfs: fail to allocate path_buf in %s.\n", __func__);
 			} else {
 				obbpath_s = d_path(&di->lower_path, path_buf, PATH_MAX);
 				if (d_unhashed(di->lower_path.dentry) ||
-					strcasecmp(sbi->obbpath_s, obbpath_s)) {
+					!str_case_eq(sbi->obbpath_s, obbpath_s)) {
 					ret = 1;
 				}
 				kfree(path_buf);
 			}
 
-			//unlock_dir(lower_parent);
-			path_put(&di->lower_path);
+			pathcpy(&lower_path, &di->lower_path);
+			need_put = 1;
 		}
 	}
 	spin_unlock(&di->lock);
+	if (need_put)
+		path_put(&lower_path);
 	return ret;
 }
 
@@ -212,17 +415,18 @@
 {
 	int ret = 0;
 	struct dentry *parent = dget_parent(dentry);
-	struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
+	struct sdcardfs_inode_info *parent_info = SDCARDFS_I(d_inode(parent));
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
+	struct qstr q_obb = QSTR_LITERAL("obb");
 
 	spin_lock(&SDCARDFS_D(dentry)->lock);
 	if (sbi->options.multiuser) {
-		if(parent_info->perm == PERM_PRE_ROOT &&
-				!strcasecmp(dentry->d_name.name, "obb")) {
+		if (parent_info->data->perm == PERM_PRE_ROOT &&
+				qstr_case_eq(&dentry->d_name, &q_obb)) {
 			ret = 1;
 		}
-	} else  if (parent_info->perm == PERM_ANDROID &&
-			!strcasecmp(dentry->d_name.name, "obb")) {
+	} else  if (parent_info->data->perm == PERM_ANDROID &&
+			qstr_case_eq(&dentry->d_name, &q_obb)) {
 		ret = 1;
 	}
 	spin_unlock(&SDCARDFS_D(dentry)->lock);
@@ -232,7 +436,8 @@
 /* The lower_path will be stored to the dentry's orig_path
  * and the base obbpath will be copyed to the lower_path variable.
  * if an error returned, there's no change in the lower_path
- * returns: -ERRNO if error (0: no error) */
+ * returns: -ERRNO if error (0: no error)
+ */
 int setup_obb_dentry(struct dentry *dentry, struct path *lower_path)
 {
 	int err = 0;
@@ -241,23 +446,24 @@
 
 	/* A local obb dentry must have its own orig_path to support rmdir
 	 * and mkdir of itself. Usually, we expect that the sbi->obbpath
-	 * is avaiable on this stage. */
+	 * is avaiable on this stage.
+	 */
 	sdcardfs_set_orig_path(dentry, lower_path);
 
 	err = kern_path(sbi->obbpath_s,
 			LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &obbpath);
 
-	if(!err) {
+	if (!err) {
 		/* the obbpath base has been found */
-		printk(KERN_INFO "sdcardfs: the sbi->obbpath is found\n");
 		pathcpy(lower_path, &obbpath);
 	} else {
 		/* if the sbi->obbpath is not available, we can optionally
 		 * setup the lower_path with its orig_path.
 		 * but, the current implementation just returns an error
 		 * because the sdcard daemon also regards this case as
-		 * a lookup fail. */
-		printk(KERN_INFO "sdcardfs: the sbi->obbpath is not available\n");
+		 * a lookup fail.
+		 */
+		pr_info("sdcardfs: the sbi->obbpath is not available\n");
 	}
 	return err;
 }
diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c
index c249fa9..6076c34 100644
--- a/fs/sdcardfs/file.c
+++ b/fs/sdcardfs/file.c
@@ -65,7 +65,7 @@
 
 	/* check disk space */
 	if (!check_min_free_space(dentry, count, 0)) {
-		printk(KERN_INFO "No minimum free space.\n");
+		pr_err("No minimum free space.\n");
 		return -ENOSPC;
 	}
 
@@ -113,6 +113,10 @@
 	if (lower_file->f_op->unlocked_ioctl)
 		err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
 
+	/* some ioctls can change inode attributes (EXT2_IOC_SETFLAGS) */
+	if (!err)
+		sdcardfs_copy_and_fix_attrs(file_inode(file),
+				      file_inode(lower_file));
 out:
 	return err;
 }
@@ -160,8 +164,7 @@
 	lower_file = sdcardfs_lower_file(file);
 	if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
 		err = -EINVAL;
-		printk(KERN_ERR "sdcardfs: lower file system does not "
-		       "support writeable mmap\n");
+		pr_err("sdcardfs: lower file system does not support writeable mmap\n");
 		goto out;
 	}
 
@@ -173,16 +176,10 @@
 	if (!SDCARDFS_F(file)->lower_vm_ops) {
 		err = lower_file->f_op->mmap(lower_file, vma);
 		if (err) {
-			printk(KERN_ERR "sdcardfs: lower mmap failed %d\n", err);
+			pr_err("sdcardfs: lower mmap failed %d\n", err);
 			goto out;
 		}
 		saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */
-		err = do_munmap(current->mm, vma->vm_start,
-				vma->vm_end - vma->vm_start);
-		if (err) {
-			printk(KERN_ERR "sdcardfs: do_munmap failed %d\n", err);
-			goto out;
-		}
 	}
 
 	/*
@@ -195,6 +192,9 @@
 	file->f_mapping->a_ops = &sdcardfs_aops; /* set our aops */
 	if (!SDCARDFS_F(file)->lower_vm_ops) /* save for our ->fault */
 		SDCARDFS_F(file)->lower_vm_ops = saved_vm_ops;
+	vma->vm_private_data = file;
+	get_file(lower_file);
+	vma->vm_file = lower_file;
 
 out:
 	return err;
@@ -216,16 +216,13 @@
 		goto out_err;
 	}
 
-	if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-                         "	dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
 		err = -EACCES;
 		goto out_err;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(sbi, saved_cred);
+	OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(inode));
 
 	file->private_data =
 		kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL);
@@ -251,9 +248,8 @@
 
 	if (err)
 		kfree(SDCARDFS_F(file));
-	else {
+	else
 		sdcardfs_copy_and_fix_attrs(inode, sdcardfs_lower_inode(inode));
-	}
 
 out_revert_cred:
 	REVERT_CRED(saved_cred);
@@ -323,6 +319,85 @@
 	return err;
 }
 
+/*
+ * Sdcardfs cannot use generic_file_llseek as ->llseek, because it would
+ * only set the offset of the upper file.  So we have to implement our
+ * own method to set both the upper and lower file offsets
+ * consistently.
+ */
+static loff_t sdcardfs_file_llseek(struct file *file, loff_t offset, int whence)
+{
+	int err;
+	struct file *lower_file;
+
+	err = generic_file_llseek(file, offset, whence);
+	if (err < 0)
+		goto out;
+
+	lower_file = sdcardfs_lower_file(file);
+	err = generic_file_llseek(lower_file, offset, whence);
+
+out:
+	return err;
+}
+
+/*
+ * Sdcardfs read_iter, redirect modified iocb to lower read_iter
+ */
+ssize_t sdcardfs_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+	int err;
+	struct file *file = iocb->ki_filp, *lower_file;
+
+	lower_file = sdcardfs_lower_file(file);
+	if (!lower_file->f_op->read_iter) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	get_file(lower_file); /* prevent lower_file from being released */
+	iocb->ki_filp = lower_file;
+	err = lower_file->f_op->read_iter(iocb, iter);
+	iocb->ki_filp = file;
+	fput(lower_file);
+	/* update upper inode atime as needed */
+	if (err >= 0 || err == -EIOCBQUEUED)
+		fsstack_copy_attr_atime(file->f_path.dentry->d_inode,
+					file_inode(lower_file));
+out:
+	return err;
+}
+
+/*
+ * Sdcardfs write_iter, redirect modified iocb to lower write_iter
+ */
+ssize_t sdcardfs_write_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+	int err;
+	struct file *file = iocb->ki_filp, *lower_file;
+
+	lower_file = sdcardfs_lower_file(file);
+	if (!lower_file->f_op->write_iter) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	get_file(lower_file); /* prevent lower_file from being released */
+	iocb->ki_filp = lower_file;
+	err = lower_file->f_op->write_iter(iocb, iter);
+	iocb->ki_filp = file;
+	fput(lower_file);
+	/* update upper inode times/sizes as needed */
+	if (err >= 0 || err == -EIOCBQUEUED) {
+		fsstack_copy_inode_size(file->f_path.dentry->d_inode,
+					file_inode(lower_file));
+		fsstack_copy_attr_times(file->f_path.dentry->d_inode,
+					file_inode(lower_file));
+	}
+out:
+	return err;
+}
+
 const struct file_operations sdcardfs_main_fops = {
 	.llseek		= generic_file_llseek,
 	.read		= sdcardfs_read,
@@ -337,11 +412,13 @@
 	.release	= sdcardfs_file_release,
 	.fsync		= sdcardfs_fsync,
 	.fasync		= sdcardfs_fasync,
+	.read_iter	= sdcardfs_read_iter,
+	.write_iter	= sdcardfs_write_iter,
 };
 
 /* trimmed directory options */
 const struct file_operations sdcardfs_dir_fops = {
-	.llseek		= generic_file_llseek,
+	.llseek		= sdcardfs_file_llseek,
 	.read		= generic_read_dir,
 	.iterate	= sdcardfs_readdir,
 	.unlocked_ioctl	= sdcardfs_unlocked_ioctl,
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index 2528da0..60fea42 100644
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -19,18 +19,26 @@
  */
 
 #include "sdcardfs.h"
+#include <linux/fs_struct.h>
+#include <linux/ratelimit.h>
 
 /* Do not directly use this function. Use OVERRIDE_CRED() instead. */
-const struct cred * override_fsids(struct sdcardfs_sb_info* sbi)
+const struct cred *override_fsids(struct sdcardfs_sb_info *sbi,
+		struct sdcardfs_inode_data *data)
 {
-	struct cred * cred;
-	const struct cred * old_cred;
+	struct cred *cred;
+	const struct cred *old_cred;
+	uid_t uid;
 
 	cred = prepare_creds();
 	if (!cred)
 		return NULL;
 
-	cred->fsuid = make_kuid(&init_user_ns, sbi->options.fs_low_uid);
+	if (data->under_obb)
+		uid = AID_MEDIA_OBB;
+	else
+		uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid);
+	cred->fsuid = make_kuid(&init_user_ns, uid);
 	cred->fsgid = make_kgid(&init_user_ns, sbi->options.fs_low_gid);
 
 	old_cred = override_creds(cred);
@@ -39,9 +47,9 @@
 }
 
 /* Do not directly use this function, use REVERT_CRED() instead. */
-void revert_fsids(const struct cred * old_cred)
+void revert_fsids(const struct cred *old_cred)
 {
-	const struct cred * cur_cred;
+	const struct cred *cur_cred;
 
 	cur_cred = current->cred;
 	revert_creds(old_cred);
@@ -53,38 +61,54 @@
 {
 	int err;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_dentry_mnt;
 	struct dentry *lower_parent_dentry = NULL;
 	struct path lower_path;
 	const struct cred *saved_cred = NULL;
+	struct fs_struct *saved_fs;
+	struct fs_struct *copied_fs;
 
-	if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(dir, &dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	sdcardfs_get_lower_path(dentry, &lower_path);
 	lower_dentry = lower_path.dentry;
+	lower_dentry_mnt = lower_path.mnt;
 	lower_parent_dentry = lock_parent(lower_dentry);
 
 	/* set last 16bytes of mode field to 0664 */
 	mode = (mode & S_IFMT) | 00664;
-	err = vfs_create(d_inode(lower_parent_dentry), lower_dentry, mode, want_excl);
+
+	/* temporarily change umask for lower fs write */
+	saved_fs = current->fs;
+	copied_fs = copy_fs_struct(current->fs);
+	if (!copied_fs) {
+		err = -ENOMEM;
+		goto out_unlock;
+	}
+	current->fs = copied_fs;
+	current->fs->umask = 0;
+	err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl);
 	if (err)
 		goto out;
 
-	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, SDCARDFS_I(dir)->userid);
+	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path,
+			SDCARDFS_I(dir)->data->userid);
 	if (err)
 		goto out;
 	fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
 	fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry));
+	fixup_lower_ownership(dentry, dentry->d_name.name);
 
 out:
+	current->fs = saved_fs;
+	free_fs_struct(copied_fs);
+out_unlock:
 	unlock_dir(lower_parent_dentry);
 	sdcardfs_put_lower_path(dentry, &lower_path);
 	REVERT_CRED(saved_cred);
@@ -138,28 +162,27 @@
 {
 	int err;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct inode *lower_dir_inode = sdcardfs_lower_inode(dir);
 	struct dentry *lower_dir_dentry;
 	struct path lower_path;
 	const struct cred *saved_cred = NULL;
 
-	if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(dir, &dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	sdcardfs_get_lower_path(dentry, &lower_path);
 	lower_dentry = lower_path.dentry;
+	lower_mnt = lower_path.mnt;
 	dget(lower_dentry);
 	lower_dir_dentry = lock_parent(lower_dentry);
 
-	err = vfs_unlink(lower_dir_inode, lower_dentry, NULL);
+	err = vfs_unlink2(lower_mnt, lower_dir_inode, lower_dentry, NULL);
 
 	/*
 	 * Note: unlinking on top of NFS can cause silly-renamed files.
@@ -219,14 +242,15 @@
 }
 #endif
 
-static int touch(char *abs_path, mode_t mode) {
+static int touch(char *abs_path, mode_t mode)
+{
 	struct file *filp = filp_open(abs_path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, mode);
+
 	if (IS_ERR(filp)) {
 		if (PTR_ERR(filp) == -EEXIST) {
 			return 0;
-		}
-		else {
-			printk(KERN_ERR "sdcardfs: failed to open(%s): %ld\n",
+		} else {
+			pr_err("sdcardfs: failed to open(%s): %ld\n",
 						abs_path, PTR_ERR(filp));
 			return PTR_ERR(filp);
 		}
@@ -240,31 +264,29 @@
 	int err;
 	int make_nomedia_in_obb = 0;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct dentry *lower_parent_dentry = NULL;
 	struct path lower_path;
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
 	const struct cred *saved_cred = NULL;
-	struct sdcardfs_inode_info *pi = SDCARDFS_I(dir);
-	char *page_buf;
-	char *nomedia_dir_name;
-	char *nomedia_fullpath;
-	int fullpath_namelen;
+	struct sdcardfs_inode_data *pd = SDCARDFS_I(dir)->data;
 	int touch_err = 0;
+	struct fs_struct *saved_fs;
+	struct fs_struct *copied_fs;
+	struct qstr q_obb = QSTR_LITERAL("obb");
+	struct qstr q_data = QSTR_LITERAL("data");
 
-	if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(dir, &dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	/* check disk space */
 	if (!check_min_free_space(dentry, 0, 1)) {
-		printk(KERN_INFO "sdcardfs: No minimum free space.\n");
+		pr_err("sdcardfs: No minimum free space.\n");
 		err = -ENOSPC;
 		goto out_revert;
 	}
@@ -272,87 +294,84 @@
 	/* the lower_dentry is negative here */
 	sdcardfs_get_lower_path(dentry, &lower_path);
 	lower_dentry = lower_path.dentry;
+	lower_mnt = lower_path.mnt;
 	lower_parent_dentry = lock_parent(lower_dentry);
 
 	/* set last 16bytes of mode field to 0775 */
 	mode = (mode & S_IFMT) | 00775;
-	err = vfs_mkdir(d_inode(lower_parent_dentry), lower_dentry, mode);
 
-	if (err)
+	/* temporarily change umask for lower fs write */
+	saved_fs = current->fs;
+	copied_fs = copy_fs_struct(current->fs);
+	if (!copied_fs) {
+		err = -ENOMEM;
+		unlock_dir(lower_parent_dentry);
+		goto out_unlock;
+	}
+	current->fs = copied_fs;
+	current->fs->umask = 0;
+	err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode);
+
+	if (err) {
+		unlock_dir(lower_parent_dentry);
 		goto out;
+	}
 
 	/* if it is a local obb dentry, setup it with the base obbpath */
-	if(need_graft_path(dentry)) {
+	if (need_graft_path(dentry)) {
 
 		err = setup_obb_dentry(dentry, &lower_path);
-		if(err) {
+		if (err) {
 			/* if the sbi->obbpath is not available, the lower_path won't be
 			 * changed by setup_obb_dentry() but the lower path is saved to
 			 * its orig_path. this dentry will be revalidated later.
-			 * but now, the lower_path should be NULL */
+			 * but now, the lower_path should be NULL
+			 */
 			sdcardfs_put_reset_lower_path(dentry);
 
 			/* the newly created lower path which saved to its orig_path or
 			 * the lower_path is the base obbpath.
-			 * therefore, an additional path_get is required */
+			 * therefore, an additional path_get is required
+			 */
 			path_get(&lower_path);
 		} else
 			make_nomedia_in_obb = 1;
 	}
 
-	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pi->userid);
-	if (err)
+	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pd->userid);
+	if (err) {
+		unlock_dir(lower_parent_dentry);
 		goto out;
+	}
 
 	fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
 	fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry));
 	/* update number of links on parent directory */
 	set_nlink(dir, sdcardfs_lower_inode(dir)->i_nlink);
-
-	if ((!sbi->options.multiuser) && (!strcasecmp(dentry->d_name.name, "obb"))
-		&& (pi->perm == PERM_ANDROID) && (pi->userid == 0))
+	fixup_lower_ownership(dentry, dentry->d_name.name);
+	unlock_dir(lower_parent_dentry);
+	if ((!sbi->options.multiuser) && (qstr_case_eq(&dentry->d_name, &q_obb))
+		&& (pd->perm == PERM_ANDROID) && (pd->userid == 0))
 		make_nomedia_in_obb = 1;
 
 	/* When creating /Android/data and /Android/obb, mark them as .nomedia */
 	if (make_nomedia_in_obb ||
-		((pi->perm == PERM_ANDROID) && (!strcasecmp(dentry->d_name.name, "data")))) {
-
-		page_buf = (char *)__get_free_page(GFP_KERNEL);
-		if (!page_buf) {
-			printk(KERN_ERR "sdcardfs: failed to allocate page buf\n");
-			goto out;
-		}
-
-		nomedia_dir_name = d_absolute_path(&lower_path, page_buf, PAGE_SIZE);
-		if (IS_ERR(nomedia_dir_name)) {
-			free_page((unsigned long)page_buf);
-			printk(KERN_ERR "sdcardfs: failed to get .nomedia dir name\n");
-			goto out;
-		}
-
-		fullpath_namelen = page_buf + PAGE_SIZE - nomedia_dir_name - 1;
-		fullpath_namelen += strlen("/.nomedia");
-		nomedia_fullpath = kzalloc(fullpath_namelen + 1, GFP_KERNEL);
-		if (!nomedia_fullpath) {
-			free_page((unsigned long)page_buf);
-			printk(KERN_ERR "sdcardfs: failed to allocate .nomedia fullpath buf\n");
-			goto out;
-		}
-
-		strcpy(nomedia_fullpath, nomedia_dir_name);
-		free_page((unsigned long)page_buf);
-		strcat(nomedia_fullpath, "/.nomedia");
-		touch_err = touch(nomedia_fullpath, 0664);
+		((pd->perm == PERM_ANDROID)
+				&& (qstr_case_eq(&dentry->d_name, &q_data)))) {
+		REVERT_CRED(saved_cred);
+		OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(d_inode(dentry)));
+		set_fs_pwd(current->fs, &lower_path);
+		touch_err = touch(".nomedia", 0664);
 		if (touch_err) {
-			printk(KERN_ERR "sdcardfs: failed to touch(%s): %d\n",
-							nomedia_fullpath, touch_err);
-			kfree(nomedia_fullpath);
+			pr_err("sdcardfs: failed to create .nomedia in %s: %d\n",
+							lower_path.dentry->d_name.name, touch_err);
 			goto out;
 		}
-		kfree(nomedia_fullpath);
 	}
 out:
-	unlock_dir(lower_parent_dentry);
+	current->fs = saved_fs;
+	free_fs_struct(copied_fs);
+out_unlock:
 	sdcardfs_put_lower_path(dentry, &lower_path);
 out_revert:
 	REVERT_CRED(saved_cred);
@@ -364,29 +383,29 @@
 {
 	struct dentry *lower_dentry;
 	struct dentry *lower_dir_dentry;
+	struct vfsmount *lower_mnt;
 	int err;
 	struct path lower_path;
 	const struct cred *saved_cred = NULL;
 
-	if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(dir, &dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	/* sdcardfs_get_real_lower(): in case of remove an user's obb dentry
-	 * the dentry on the original path should be deleted. */
+	 * the dentry on the original path should be deleted.
+	 */
 	sdcardfs_get_real_lower(dentry, &lower_path);
 
 	lower_dentry = lower_path.dentry;
+	lower_mnt = lower_path.mnt;
 	lower_dir_dentry = lock_parent(lower_dentry);
 
-	err = vfs_rmdir(d_inode(lower_dir_dentry), lower_dentry);
+	err = vfs_rmdir2(lower_mnt, d_inode(lower_dir_dentry), lower_dentry);
 	if (err)
 		goto out;
 
@@ -450,27 +469,25 @@
 	struct dentry *lower_new_dentry = NULL;
 	struct dentry *lower_old_dir_dentry = NULL;
 	struct dentry *lower_new_dir_dentry = NULL;
+	struct vfsmount *lower_mnt = NULL;
 	struct dentry *trap = NULL;
-	struct dentry *new_parent = NULL;
 	struct path lower_old_path, lower_new_path;
 	const struct cred *saved_cred = NULL;
 
-	if(!check_caller_access_to_name(old_dir, old_dentry->d_name.name) ||
-		!check_caller_access_to_name(new_dir, new_dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  new_dentry: %s, task:%s\n",
-						 __func__, new_dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(old_dir, &old_dentry->d_name) ||
+		!check_caller_access_to_name(new_dir, &new_dentry->d_name)) {
 		err = -EACCES;
 		goto out_eacces;
 	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred);
+	OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred, SDCARDFS_I(new_dir));
 
 	sdcardfs_get_real_lower(old_dentry, &lower_old_path);
 	sdcardfs_get_lower_path(new_dentry, &lower_new_path);
 	lower_old_dentry = lower_old_path.dentry;
 	lower_new_dentry = lower_new_path.dentry;
+	lower_mnt = lower_old_path.mnt;
 	lower_old_dir_dentry = dget_parent(lower_old_dentry);
 	lower_new_dir_dentry = dget_parent(lower_new_dentry);
 
@@ -486,7 +503,8 @@
 		goto out;
 	}
 
-	err = vfs_rename(d_inode(lower_old_dir_dentry), lower_old_dentry,
+	err = vfs_rename2(lower_mnt,
+			 d_inode(lower_old_dir_dentry), lower_old_dentry,
 			 d_inode(lower_new_dir_dentry), lower_new_dentry,
 			 NULL, 0);
 	if (err)
@@ -499,25 +517,11 @@
 	if (new_dir != old_dir) {
 		sdcardfs_copy_and_fix_attrs(old_dir, d_inode(lower_old_dir_dentry));
 		fsstack_copy_inode_size(old_dir, d_inode(lower_old_dir_dentry));
-
-		/* update the derived permission of the old_dentry
-		 * with its new parent
-		 */
-		new_parent = dget_parent(new_dentry);
-		if(new_parent) {
-			if(d_inode(old_dentry)) {
-				update_derived_permission_lock(old_dentry);
-			}
-			dput(new_parent);
-		}
 	}
-	/* At this point, not all dentry information has been moved, so
-	 * we pass along new_dentry for the name.*/
-	mutex_lock(&d_inode(old_dentry)->i_mutex);
-	get_derived_permission_new(new_dentry->d_parent, old_dentry, new_dentry);
-	fix_derived_permission(d_inode(old_dentry));
-	get_derive_permissions_recursive(old_dentry);
-	mutex_unlock(&d_inode(old_dentry)->i_mutex);
+	get_derived_permission_new(new_dentry->d_parent, old_dentry, &new_dentry->d_name);
+	fixup_tmp_permissions(d_inode(old_dentry));
+	fixup_lower_ownership(old_dentry, new_dentry->d_name.name);
+	d_invalidate(old_dentry); /* Can't fixup ownership recursively :( */
 out:
 	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
 	dput(lower_old_dir_dentry);
@@ -586,16 +590,61 @@
 }
 #endif
 
-static int sdcardfs_permission(struct inode *inode, int mask)
+static int sdcardfs_permission_wrn(struct inode *inode, int mask)
+{
+	WARN_RATELIMIT(1, "sdcardfs does not support permission. Use permission2.\n");
+	return -EINVAL;
+}
+
+void copy_attrs(struct inode *dest, const struct inode *src)
+{
+	dest->i_mode = src->i_mode;
+	dest->i_uid = src->i_uid;
+	dest->i_gid = src->i_gid;
+	dest->i_rdev = src->i_rdev;
+	dest->i_atime = src->i_atime;
+	dest->i_mtime = src->i_mtime;
+	dest->i_ctime = src->i_ctime;
+	dest->i_blkbits = src->i_blkbits;
+	dest->i_flags = src->i_flags;
+#ifdef CONFIG_FS_POSIX_ACL
+	dest->i_acl = src->i_acl;
+#endif
+#ifdef CONFIG_SECURITY
+	dest->i_security = src->i_security;
+#endif
+}
+
+static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int mask)
 {
 	int err;
+	struct inode tmp;
+	struct sdcardfs_inode_data *top = top_data_get(SDCARDFS_I(inode));
+
+	if (!top)
+		return -EINVAL;
 
 	/*
 	 * Permission check on sdcardfs inode.
 	 * Calling process should have AID_SDCARD_RW permission
+	 * Since generic_permission only needs i_mode, i_uid,
+	 * i_gid, and i_sb, we can create a fake inode to pass
+	 * this information down in.
+	 *
+	 * The underlying code may attempt to take locks in some
+	 * cases for features we're not using, but if that changes,
+	 * locks must be dealt with to avoid undefined behavior.
 	 */
-	err = generic_permission(inode, mask);
-
+	copy_attrs(&tmp, inode);
+	tmp.i_uid = make_kuid(&init_user_ns, top->d_uid);
+	tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top));
+	tmp.i_mode = (inode->i_mode & S_IFMT)
+			| get_mode(mnt, SDCARDFS_I(inode), top);
+	data_put(top);
+	tmp.i_sb = inode->i_sb;
+	if (IS_POSIXACL(inode))
+		pr_warn("%s: This may be undefined behavior...\n", __func__);
+	err = generic_permission(&tmp, mask);
 	/* XXX
 	 * Original sdcardfs code calls inode_permission(lower_inode,.. )
 	 * for checking inode permission. But doing such things here seems
@@ -612,6 +661,7 @@
 		 * we check it with AID_MEDIA_RW permission
 		 */
 		struct inode *lower_inode;
+
 		OVERRIDE_CRED(SDCARDFS_SB(inode->sb));
 
 		lower_inode = sdcardfs_lower_inode(inode);
@@ -624,47 +674,85 @@
 
 }
 
-static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
+static int sdcardfs_setattr_wrn(struct dentry *dentry, struct iattr *ia)
+{
+	WARN_RATELIMIT(1, "sdcardfs does not support setattr. User setattr2.\n");
+	return -EINVAL;
+}
+
+static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct iattr *ia)
 {
 	int err;
 	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct inode *inode;
 	struct inode *lower_inode;
 	struct path lower_path;
 	struct iattr lower_ia;
 	struct dentry *parent;
+	struct inode tmp;
+	struct sdcardfs_inode_data *top;
+	const struct cred *saved_cred = NULL;
 
 	inode = d_inode(dentry);
+	top = top_data_get(SDCARDFS_I(inode));
+
+	if (!top)
+		return -EINVAL;
+
+	/*
+	 * Permission check on sdcardfs inode.
+	 * Calling process should have AID_SDCARD_RW permission
+	 * Since generic_permission only needs i_mode, i_uid,
+	 * i_gid, and i_sb, we can create a fake inode to pass
+	 * this information down in.
+	 *
+	 * The underlying code may attempt to take locks in some
+	 * cases for features we're not using, but if that changes,
+	 * locks must be dealt with to avoid undefined behavior.
+	 *
+	 */
+	copy_attrs(&tmp, inode);
+	tmp.i_uid = make_kuid(&init_user_ns, top->d_uid);
+	tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top));
+	tmp.i_mode = (inode->i_mode & S_IFMT)
+			| get_mode(mnt, SDCARDFS_I(inode), top);
+	tmp.i_size = i_size_read(inode);
+	data_put(top);
+	tmp.i_sb = inode->i_sb;
 
 	/*
 	 * Check if user has permission to change inode.  We don't check if
 	 * this user can change the lower inode: that should happen when
 	 * calling notify_change on the lower inode.
 	 */
-	err = inode_change_ok(inode, ia);
+	/* prepare our own lower struct iattr (with the lower file) */
+	memcpy(&lower_ia, ia, sizeof(lower_ia));
+	/* Allow touch updating timestamps. A previous permission check ensures
+	 * we have write access. Changes to mode, owner, and group are ignored
+	 */
+	ia->ia_valid |= ATTR_FORCE;
+	err = inode_change_ok(&tmp, ia);
 
-	/* no vfs_XXX operations required, cred overriding will be skipped. wj*/
 	if (!err) {
 		/* check the Android group ID */
 		parent = dget_parent(dentry);
-		if(!check_caller_access_to_name(d_inode(parent), dentry->d_name.name)) {
-			printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-							 "  dentry: %s, task:%s\n",
-							 __func__, dentry->d_name.name, current->comm);
+		if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name))
 			err = -EACCES;
-		}
 		dput(parent);
 	}
 
 	if (err)
 		goto out_err;
 
+	/* save current_cred and override it */
+	OVERRIDE_CRED(SDCARDFS_SB(dentry->d_sb), saved_cred, SDCARDFS_I(inode));
+
 	sdcardfs_get_lower_path(dentry, &lower_path);
 	lower_dentry = lower_path.dentry;
+	lower_mnt = lower_path.mnt;
 	lower_inode = sdcardfs_lower_inode(inode);
 
-	/* prepare our own lower struct iattr (with the lower file) */
-	memcpy(&lower_ia, ia, sizeof(lower_ia));
 	if (ia->ia_valid & ATTR_FILE)
 		lower_ia.ia_file = sdcardfs_lower_file(ia->ia_file);
 
@@ -681,7 +769,7 @@
 	if (current->mm)
 		down_write(&current->mm->mmap_sem);
 	if (ia->ia_valid & ATTR_SIZE) {
-		err = inode_newsize_ok(inode, ia->ia_size);
+		err = inode_newsize_ok(&tmp, ia->ia_size);
 		if (err) {
 			if (current->mm)
 				up_write(&current->mm->mmap_sem);
@@ -704,7 +792,7 @@
 	 * tries to open(), unlink(), then ftruncate() a file.
 	 */
 	mutex_lock(&d_inode(lower_dentry)->i_mutex);
-	err = notify_change(lower_dentry, &lower_ia, /* note: lower_ia */
+	err = notify_change2(lower_mnt, lower_dentry, &lower_ia, /* note: lower_ia */
 			NULL);
 	mutex_unlock(&d_inode(lower_dentry)->i_mutex);
 	if (current->mm)
@@ -723,48 +811,68 @@
 
 out:
 	sdcardfs_put_lower_path(dentry, &lower_path);
+	REVERT_CRED(saved_cred);
 out_err:
 	return err;
 }
 
+static int sdcardfs_fillattr(struct vfsmount *mnt,
+				struct inode *inode, struct kstat *stat)
+{
+	struct sdcardfs_inode_info *info = SDCARDFS_I(inode);
+	struct sdcardfs_inode_data *top = top_data_get(info);
+
+	if (!top)
+		return -EINVAL;
+
+	stat->dev = inode->i_sb->s_dev;
+	stat->ino = inode->i_ino;
+	stat->mode = (inode->i_mode  & S_IFMT) | get_mode(mnt, info, top);
+	stat->nlink = inode->i_nlink;
+	stat->uid = make_kuid(&init_user_ns, top->d_uid);
+	stat->gid = make_kgid(&init_user_ns, get_gid(mnt, top));
+	stat->rdev = inode->i_rdev;
+	stat->size = i_size_read(inode);
+	stat->atime = inode->i_atime;
+	stat->mtime = inode->i_mtime;
+	stat->ctime = inode->i_ctime;
+	stat->blksize = (1 << inode->i_blkbits);
+	stat->blocks = inode->i_blocks;
+	data_put(top);
+	return 0;
+}
+
 static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		 struct kstat *stat)
 {
-	struct dentry *lower_dentry;
-	struct inode *inode;
-	struct inode *lower_inode;
+	struct kstat lower_stat;
 	struct path lower_path;
 	struct dentry *parent;
+	int err;
 
 	parent = dget_parent(dentry);
-	if(!check_caller_access_to_name(d_inode(parent), dentry->d_name.name)) {
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-						 "  dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
+	if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
 		dput(parent);
 		return -EACCES;
 	}
 	dput(parent);
 
-	inode = d_inode(dentry);
-
 	sdcardfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	lower_inode = sdcardfs_lower_inode(inode);
-
-
-	sdcardfs_copy_and_fix_attrs(inode, lower_inode);
-	fsstack_copy_inode_size(inode, lower_inode);
-
-
-	generic_fillattr(inode, stat);
+	err = vfs_getattr(&lower_path, &lower_stat);
+	if (err)
+		goto out;
+	sdcardfs_copy_and_fix_attrs(d_inode(dentry),
+			      d_inode(lower_path.dentry));
+	err = sdcardfs_fillattr(mnt, d_inode(dentry), stat);
+	stat->blocks = lower_stat.blocks;
+out:
 	sdcardfs_put_lower_path(dentry, &lower_path);
-	return 0;
+	return err;
 }
 
 const struct inode_operations sdcardfs_symlink_iops = {
-	.permission	= sdcardfs_permission,
-	.setattr	= sdcardfs_setattr,
+	.permission2	= sdcardfs_permission,
+	.setattr2	= sdcardfs_setattr,
 	/* XXX Following operations are implemented,
 	 *     but FUSE(sdcard) or FAT does not support them
 	 *     These methods are *NOT* perfectly tested.
@@ -777,14 +885,14 @@
 const struct inode_operations sdcardfs_dir_iops = {
 	.create		= sdcardfs_create,
 	.lookup		= sdcardfs_lookup,
-#if 0
-	.permission	= sdcardfs_permission,
-#endif
+	.permission	= sdcardfs_permission_wrn,
+	.permission2	= sdcardfs_permission,
 	.unlink		= sdcardfs_unlink,
 	.mkdir		= sdcardfs_mkdir,
 	.rmdir		= sdcardfs_rmdir,
 	.rename		= sdcardfs_rename,
-	.setattr	= sdcardfs_setattr,
+	.setattr	= sdcardfs_setattr_wrn,
+	.setattr2	= sdcardfs_setattr,
 	.getattr	= sdcardfs_getattr,
 	/* XXX Following operations are implemented,
 	 *     but FUSE(sdcard) or FAT does not support them
@@ -796,7 +904,9 @@
 };
 
 const struct inode_operations sdcardfs_main_iops = {
-	.permission	= sdcardfs_permission,
-	.setattr	= sdcardfs_setattr,
+	.permission	= sdcardfs_permission_wrn,
+	.permission2	= sdcardfs_permission,
+	.setattr	= sdcardfs_setattr_wrn,
+	.setattr2	= sdcardfs_setattr,
 	.getattr	= sdcardfs_getattr,
 };
diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c
index a01b06a..676e394 100644
--- a/fs/sdcardfs/lookup.c
+++ b/fs/sdcardfs/lookup.c
@@ -36,8 +36,7 @@
 
 void sdcardfs_destroy_dentry_cache(void)
 {
-	if (sdcardfs_dentry_cachep)
-		kmem_cache_destroy(sdcardfs_dentry_cachep);
+	kmem_cache_destroy(sdcardfs_dentry_cachep);
 }
 
 void free_dentry_private_data(struct dentry *dentry)
@@ -72,7 +71,8 @@
 static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/)
 {
 	struct inode *current_lower_inode = sdcardfs_lower_inode(inode);
-	userid_t current_userid = SDCARDFS_I(inode)->userid;
+	userid_t current_userid = SDCARDFS_I(inode)->data->userid;
+
 	if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode &&
 			current_userid == ((struct inode_data *)candidate_data)->id)
 		return 1; /* found a match */
@@ -91,7 +91,9 @@
 	struct sdcardfs_inode_info *info;
 	struct inode_data data;
 	struct inode *inode; /* the new inode to return */
-	int err;
+
+	if (!igrab(lower_inode))
+		return ERR_PTR(-ESTALE);
 
 	data.id = id;
 	data.lower_inode = lower_inode;
@@ -102,26 +104,23 @@
 			      * instead.
 			      */
 			     lower_inode->i_ino, /* hashval */
-			     sdcardfs_inode_test,	/* inode comparison function */
+			     sdcardfs_inode_test, /* inode comparison function */
 			     sdcardfs_inode_set, /* inode init function */
 			     &data); /* data passed to test+set fxns */
 	if (!inode) {
-		err = -EACCES;
 		iput(lower_inode);
-		return ERR_PTR(err);
+		return ERR_PTR(-ENOMEM);
 	}
-	/* if found a cached inode, then just return it */
-	if (!(inode->i_state & I_NEW))
+	/* if found a cached inode, then just return it (after iput) */
+	if (!(inode->i_state & I_NEW)) {
+		iput(lower_inode);
 		return inode;
+	}
 
 	/* initialize new inode */
 	info = SDCARDFS_I(inode);
 
 	inode->i_ino = lower_inode->i_ino;
-	if (!igrab(lower_inode)) {
-		err = -ESTALE;
-		return ERR_PTR(err);
-	}
 	sdcardfs_set_lower_inode(inode, lower_inode);
 
 	inode->i_version++;
@@ -164,27 +163,25 @@
 }
 
 /*
- * Connect a sdcardfs inode dentry/inode with several lower ones.  This is
- * the classic stackable file system "vnode interposition" action.
- *
- * @dentry: sdcardfs's dentry which interposes on lower one
- * @sb: sdcardfs's super_block
- * @lower_path: the lower path (caller does path_get/put)
+ * Helper interpose routine, called directly by ->lookup to handle
+ * spliced dentries.
  */
-int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
-		     struct path *lower_path, userid_t id)
+static struct dentry *__sdcardfs_interpose(struct dentry *dentry,
+					 struct super_block *sb,
+					 struct path *lower_path,
+					 userid_t id)
 {
-	int err = 0;
 	struct inode *inode;
 	struct inode *lower_inode;
 	struct super_block *lower_sb;
+	struct dentry *ret_dentry;
 
-	lower_inode = lower_path->dentry->d_inode;
+	lower_inode = d_inode(lower_path->dentry);
 	lower_sb = sdcardfs_lower_super(sb);
 
 	/* check that the lower file system didn't cross a mount point */
 	if (lower_inode->i_sb != lower_sb) {
-		err = -EXDEV;
+		ret_dentry = ERR_PTR(-EXDEV);
 		goto out;
 	}
 
@@ -196,14 +193,55 @@
 	/* inherit lower inode number for sdcardfs's inode */
 	inode = sdcardfs_iget(sb, lower_inode, id);
 	if (IS_ERR(inode)) {
-		err = PTR_ERR(inode);
+		ret_dentry = ERR_CAST(inode);
 		goto out;
 	}
 
-	d_add(dentry, inode);
-	update_derived_permission_lock(dentry);
+	ret_dentry = d_splice_alias(inode, dentry);
+	dentry = ret_dentry ?: dentry;
+	if (!IS_ERR(dentry))
+		update_derived_permission_lock(dentry);
 out:
-	return err;
+	return ret_dentry;
+}
+
+/*
+ * Connect an sdcardfs inode dentry/inode with several lower ones.  This is
+ * the classic stackable file system "vnode interposition" action.
+ *
+ * @dentry: sdcardfs's dentry which interposes on lower one
+ * @sb: sdcardfs's super_block
+ * @lower_path: the lower path (caller does path_get/put)
+ */
+int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
+		     struct path *lower_path, userid_t id)
+{
+	struct dentry *ret_dentry;
+
+	ret_dentry = __sdcardfs_interpose(dentry, sb, lower_path, id);
+	return PTR_ERR(ret_dentry);
+}
+
+struct sdcardfs_name_data {
+	struct dir_context ctx;
+	const struct qstr *to_find;
+	char *name;
+	bool found;
+};
+
+static int sdcardfs_name_match(struct dir_context *ctx, const char *name,
+		int namelen, loff_t offset, u64 ino, unsigned int d_type)
+{
+	struct sdcardfs_name_data *buf = container_of(ctx, struct sdcardfs_name_data, ctx);
+	struct qstr candidate = QSTR_INIT(name, namelen);
+
+	if (qstr_case_eq(buf->to_find, &candidate)) {
+		memcpy(buf->name, name, namelen);
+		buf->name[namelen] = 0;
+		buf->found = true;
+		return 1;
+	}
+	return 0;
 }
 
 /*
@@ -219,9 +257,10 @@
 	struct vfsmount *lower_dir_mnt;
 	struct dentry *lower_dir_dentry = NULL;
 	struct dentry *lower_dentry;
-	const char *name;
+	const struct qstr *name;
 	struct path lower_path;
-	struct qstr this;
+	struct qstr dname;
+	struct dentry *ret_dentry = NULL;
 	struct sdcardfs_sb_info *sbi;
 
 	sbi = SDCARDFS_SB(dentry->d_sb);
@@ -231,47 +270,90 @@
 	if (IS_ROOT(dentry))
 		goto out;
 
-	name = dentry->d_name.name;
+	name = &dentry->d_name;
 
 	/* now start the actual lookup procedure */
 	lower_dir_dentry = lower_parent_path->dentry;
 	lower_dir_mnt = lower_parent_path->mnt;
 
 	/* Use vfs_path_lookup to check if the dentry exists or not */
-	err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0,
+	err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name->name, 0,
 				&lower_path);
+	/* check for other cases */
+	if (err == -ENOENT) {
+		struct file *file;
+		const struct cred *cred = current_cred();
+
+		struct sdcardfs_name_data buffer = {
+			.ctx.actor = sdcardfs_name_match,
+			.to_find = name,
+			.name = __getname(),
+			.found = false,
+		};
+
+		if (!buffer.name) {
+			err = -ENOMEM;
+			goto out;
+		}
+		file = dentry_open(lower_parent_path, O_RDONLY, cred);
+		if (IS_ERR(file)) {
+			err = PTR_ERR(file);
+			goto put_name;
+		}
+		err = iterate_dir(file, &buffer.ctx);
+		fput(file);
+		if (err)
+			goto put_name;
+
+		if (buffer.found)
+			err = vfs_path_lookup(lower_dir_dentry,
+						lower_dir_mnt,
+						buffer.name, 0,
+						&lower_path);
+		else
+			err = -ENOENT;
+put_name:
+		__putname(buffer.name);
+	}
 
 	/* no error: handle positive dentries */
 	if (!err) {
 		/* check if the dentry is an obb dentry
 		 * if true, the lower_inode must be replaced with
-		 * the inode of the graft path */
+		 * the inode of the graft path
+		 */
 
-		if(need_graft_path(dentry)) {
+		if (need_graft_path(dentry)) {
 
 			/* setup_obb_dentry()
- 			 * The lower_path will be stored to the dentry's orig_path
+			 * The lower_path will be stored to the dentry's orig_path
 			 * and the base obbpath will be copyed to the lower_path variable.
 			 * if an error returned, there's no change in the lower_path
-			 * 		returns: -ERRNO if error (0: no error) */
+			 * returns: -ERRNO if error (0: no error)
+			 */
 			err = setup_obb_dentry(dentry, &lower_path);
 
-			if(err) {
+			if (err) {
 				/* if the sbi->obbpath is not available, we can optionally
 				 * setup the lower_path with its orig_path.
 				 * but, the current implementation just returns an error
 				 * because the sdcard daemon also regards this case as
-				 * a lookup fail. */
-				printk(KERN_INFO "sdcardfs: base obbpath is not available\n");
+				 * a lookup fail.
+				 */
+				pr_info("sdcardfs: base obbpath is not available\n");
 				sdcardfs_put_reset_orig_path(dentry);
 				goto out;
 			}
 		}
 
 		sdcardfs_set_lower_path(dentry, &lower_path);
-		err = sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
-		if (err) /* path_put underlying path on error */
+		ret_dentry =
+			__sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
+		if (IS_ERR(ret_dentry)) {
+			err = PTR_ERR(ret_dentry);
+			 /* path_put underlying path on error */
 			sdcardfs_put_reset_lower_path(dentry);
+		}
 		goto out;
 	}
 
@@ -283,21 +365,24 @@
 		goto out;
 
 	/* instatiate a new negative dentry */
-	this.name = name;
-	this.len = strlen(name);
-	this.hash = full_name_hash(this.name, this.len);
-	lower_dentry = d_lookup(lower_dir_dentry, &this);
-	if (lower_dentry)
-		goto setup_lower;
+	dname.name = name->name;
+	dname.len = name->len;
 
-	lower_dentry = d_alloc(lower_dir_dentry, &this);
+	/* See if the low-level filesystem might want
+	 * to use its own hash
+	 */
+	lower_dentry = d_hash_and_lookup(lower_dir_dentry, &dname);
+	if (IS_ERR(lower_dentry))
+		return lower_dentry;
 	if (!lower_dentry) {
-		err = -ENOMEM;
+		/* We called vfs_path_lookup earlier, and did not get a negative
+		 * dentry then. Don't confuse the lower filesystem by forcing
+		 * one on it now...
+		 */
+		err = -ENOENT;
 		goto out;
 	}
-	d_add(lower_dentry, NULL); /* instantiate and hash */
 
-setup_lower:
 	lower_path.dentry = lower_dentry;
 	lower_path.mnt = mntget(lower_dir_mnt);
 	sdcardfs_set_lower_path(dentry, &lower_path);
@@ -311,14 +396,16 @@
 		err = 0;
 
 out:
-	return ERR_PTR(err);
+	if (err)
+		return ERR_PTR(err);
+	return ret_dentry;
 }
 
 /*
  * On success:
- * 	fills dentry object appropriate values and returns NULL.
+ * fills dentry object appropriate values and returns NULL.
  * On fail (== error)
- * 	returns error ptr
+ * returns error ptr
  *
  * @dir : Parent inode. It is locked (dir->i_mutex)
  * @dentry : Target dentry to lookup. we should set each of fields.
@@ -335,16 +422,13 @@
 
 	parent = dget_parent(dentry);
 
-	if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) {
+	if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
 		ret = ERR_PTR(-EACCES);
-		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
-                         "	dentry: %s, task:%s\n",
-						 __func__, dentry->d_name.name, current->comm);
 		goto out_err;
-        }
+	}
 
 	/* save current_cred and override it */
-	OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred);
+	OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
 
 	sdcardfs_get_lower_path(parent, &lower_parent_path);
 
@@ -355,25 +439,23 @@
 		goto out;
 	}
 
-	ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, SDCARDFS_I(dir)->userid);
+	ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path,
+				SDCARDFS_I(dir)->data->userid);
 	if (IS_ERR(ret))
-	{
 		goto out;
-	}
 	if (ret)
 		dentry = ret;
-	if (dentry->d_inode) {
-		fsstack_copy_attr_times(dentry->d_inode,
-					sdcardfs_lower_inode(dentry->d_inode));
-		/* get drived permission */
-		mutex_lock(&dentry->d_inode->i_mutex);
+	if (d_inode(dentry)) {
+		fsstack_copy_attr_times(d_inode(dentry),
+					sdcardfs_lower_inode(d_inode(dentry)));
+		/* get derived permission */
 		get_derived_permission(parent, dentry);
-		fix_derived_permission(dentry->d_inode);
-		mutex_unlock(&dentry->d_inode->i_mutex);
+		fixup_tmp_permissions(d_inode(dentry));
+		fixup_lower_ownership(dentry, dentry->d_name.name);
 	}
 	/* update parent directory's atime */
-	fsstack_copy_attr_atime(parent->d_inode,
-				sdcardfs_lower_inode(parent->d_inode));
+	fsstack_copy_attr_atime(d_inode(parent),
+				sdcardfs_lower_inode(d_inode(parent)));
 
 out:
 	sdcardfs_put_lower_path(parent, &lower_parent_path);
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index a652228..80825b2 100644
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -28,9 +28,8 @@
 	Opt_fsgid,
 	Opt_gid,
 	Opt_debug,
-	Opt_lower_fs,
 	Opt_mask,
-	Opt_multiuser, // May need?
+	Opt_multiuser,
 	Opt_userid,
 	Opt_reserved_mb,
 	Opt_err,
@@ -49,7 +48,8 @@
 };
 
 static int parse_options(struct super_block *sb, char *options, int silent,
-				int *debug, struct sdcardfs_mount_options *opts)
+				int *debug, struct sdcardfs_vfsmount_options *vfsopts,
+				struct sdcardfs_mount_options *opts)
 {
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
@@ -58,10 +58,10 @@
 	/* by default, we use AID_MEDIA_RW as uid, gid */
 	opts->fs_low_uid = AID_MEDIA_RW;
 	opts->fs_low_gid = AID_MEDIA_RW;
-	opts->mask = 0;
+	vfsopts->mask = 0;
 	opts->multiuser = false;
 	opts->fs_user_id = 0;
-	opts->gid = 0;
+	vfsopts->gid = 0;
 	/* by default, 0MB is reserved */
 	opts->reserved_mb = 0;
 
@@ -72,6 +72,7 @@
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
+
 		if (!*p)
 			continue;
 
@@ -94,7 +95,7 @@
 		case Opt_gid:
 			if (match_int(&args[0], &option))
 				return 0;
-			opts->gid = option;
+			vfsopts->gid = option;
 			break;
 		case Opt_userid:
 			if (match_int(&args[0], &option))
@@ -104,7 +105,7 @@
 		case Opt_mask:
 			if (match_int(&args[0], &option))
 				return 0;
-			opts->mask = option;
+			vfsopts->mask = option;
 			break;
 		case Opt_multiuser:
 			opts->multiuser = true;
@@ -116,25 +117,81 @@
 			break;
 		/* unknown option */
 		default:
-			if (!silent) {
-				printk( KERN_ERR "Unrecognized mount option \"%s\" "
-						"or missing value", p);
-			}
+			if (!silent)
+				pr_err("Unrecognized mount option \"%s\" or missing value", p);
 			return -EINVAL;
 		}
 	}
 
 	if (*debug) {
-		printk( KERN_INFO "sdcardfs : options - debug:%d\n", *debug);
-		printk( KERN_INFO "sdcardfs : options - uid:%d\n",
+		pr_info("sdcardfs : options - debug:%d\n", *debug);
+		pr_info("sdcardfs : options - uid:%d\n",
 							opts->fs_low_uid);
-		printk( KERN_INFO "sdcardfs : options - gid:%d\n",
+		pr_info("sdcardfs : options - gid:%d\n",
 							opts->fs_low_gid);
 	}
 
 	return 0;
 }
 
+int parse_options_remount(struct super_block *sb, char *options, int silent,
+				struct sdcardfs_vfsmount_options *vfsopts)
+{
+	char *p;
+	substring_t args[MAX_OPT_ARGS];
+	int option;
+	int debug;
+
+	if (!options)
+		return 0;
+
+	while ((p = strsep(&options, ",")) != NULL) {
+		int token;
+
+		if (!*p)
+			continue;
+
+		token = match_token(p, sdcardfs_tokens, args);
+
+		switch (token) {
+		case Opt_debug:
+			debug = 1;
+			break;
+		case Opt_gid:
+			if (match_int(&args[0], &option))
+				return 0;
+			vfsopts->gid = option;
+
+			break;
+		case Opt_mask:
+			if (match_int(&args[0], &option))
+				return 0;
+			vfsopts->mask = option;
+			break;
+		case Opt_multiuser:
+		case Opt_userid:
+		case Opt_fsuid:
+		case Opt_fsgid:
+		case Opt_reserved_mb:
+			pr_warn("Option \"%s\" can't be changed during remount\n", p);
+			break;
+		/* unknown option */
+		default:
+			if (!silent)
+				pr_err("Unrecognized mount option \"%s\" or missing value", p);
+			return -EINVAL;
+		}
+	}
+
+	if (debug) {
+		pr_info("sdcardfs : options - debug:%d\n", debug);
+		pr_info("sdcardfs : options - gid:%d\n", vfsopts->gid);
+		pr_info("sdcardfs : options - mask:%d\n", vfsopts->mask);
+	}
+
+	return 0;
+}
+
 #if 0
 /*
  * our custom d_alloc_root work-alike
@@ -164,57 +221,58 @@
 #endif
 
 DEFINE_MUTEX(sdcardfs_super_list_lock);
-LIST_HEAD(sdcardfs_super_list);
 EXPORT_SYMBOL_GPL(sdcardfs_super_list_lock);
+LIST_HEAD(sdcardfs_super_list);
 EXPORT_SYMBOL_GPL(sdcardfs_super_list);
 
 /*
  * There is no need to lock the sdcardfs_super_info's rwsem as there is no
  * way anyone can have a reference to the superblock at this point in time.
  */
-static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
-						void *raw_data, int silent)
+static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb,
+		const char *dev_name, void *raw_data, int silent)
 {
 	int err = 0;
 	int debug;
 	struct super_block *lower_sb;
 	struct path lower_path;
 	struct sdcardfs_sb_info *sb_info;
+	struct sdcardfs_vfsmount_options *mnt_opt = mnt->data;
 	struct inode *inode;
 
-	printk(KERN_INFO "sdcardfs version 2.0\n");
+	pr_info("sdcardfs version 2.0\n");
 
 	if (!dev_name) {
-		printk(KERN_ERR
-		       "sdcardfs: read_super: missing dev_name argument\n");
+		pr_err("sdcardfs: read_super: missing dev_name argument\n");
 		err = -EINVAL;
 		goto out;
 	}
 
-	printk(KERN_INFO "sdcardfs: dev_name -> %s\n", dev_name);
-	printk(KERN_INFO "sdcardfs: options -> %s\n", (char *)raw_data);
+	pr_info("sdcardfs: dev_name -> %s\n", dev_name);
+	pr_info("sdcardfs: options -> %s\n", (char *)raw_data);
+	pr_info("sdcardfs: mnt -> %p\n", mnt);
 
 	/* parse lower path */
 	err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
 			&lower_path);
 	if (err) {
-		printk(KERN_ERR	"sdcardfs: error accessing lower directory '%s'\n", dev_name);
+		pr_err("sdcardfs: error accessing lower directory '%s'\n", dev_name);
 		goto out;
 	}
 
 	/* allocate superblock private data */
 	sb->s_fs_info = kzalloc(sizeof(struct sdcardfs_sb_info), GFP_KERNEL);
 	if (!SDCARDFS_SB(sb)) {
-		printk(KERN_CRIT "sdcardfs: read_super: out of memory\n");
+		pr_crit("sdcardfs: read_super: out of memory\n");
 		err = -ENOMEM;
 		goto out_free;
 	}
 
 	sb_info = sb->s_fs_info;
 	/* parse options */
-	err = parse_options(sb, raw_data, silent, &debug, &sb_info->options);
+	err = parse_options(sb, raw_data, silent, &debug, mnt_opt, &sb_info->options);
 	if (err) {
-		printk(KERN_ERR	"sdcardfs: invalid options\n");
+		pr_err("sdcardfs: invalid options\n");
 		goto out_freesbi;
 	}
 
@@ -236,7 +294,7 @@
 	sb->s_op = &sdcardfs_sops;
 
 	/* get a new inode and allocate our root dentry */
-	inode = sdcardfs_iget(sb, lower_path.dentry->d_inode, 0);
+	inode = sdcardfs_iget(sb, d_inode(lower_path.dentry), 0);
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		goto out_sput;
@@ -267,23 +325,24 @@
 	/* setup permission policy */
 	sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL);
 	mutex_lock(&sdcardfs_super_list_lock);
-	if(sb_info->options.multiuser) {
-		setup_derived_state(sb->s_root->d_inode, PERM_PRE_ROOT, sb_info->options.fs_user_id, AID_ROOT, false);
+	if (sb_info->options.multiuser) {
+		setup_derived_state(d_inode(sb->s_root), PERM_PRE_ROOT,
+				sb_info->options.fs_user_id, AID_ROOT,
+				false, SDCARDFS_I(d_inode(sb->s_root))->data);
 		snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name);
-		/*err =  prepare_dir(sb_info->obbpath_s,
-					sb_info->options.fs_low_uid,
-					sb_info->options.fs_low_gid, 00755);*/
 	} else {
-		setup_derived_state(sb->s_root->d_inode, PERM_ROOT, sb_info->options.fs_low_uid, AID_ROOT, false);
+		setup_derived_state(d_inode(sb->s_root), PERM_ROOT,
+				sb_info->options.fs_user_id, AID_ROOT,
+				false, SDCARDFS_I(d_inode(sb->s_root))->data);
 		snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name);
 	}
-	fix_derived_permission(sb->s_root->d_inode);
+	fixup_tmp_permissions(d_inode(sb->s_root));
 	sb_info->sb = sb;
 	list_add(&sb_info->list, &sdcardfs_super_list);
 	mutex_unlock(&sdcardfs_super_list_lock);
 
 	if (!silent)
-		printk(KERN_INFO "sdcardfs: mounted on top of %s type %s\n",
+		pr_info("sdcardfs: mounted on top of %s type %s\n",
 				dev_name, lower_sb->s_type->name);
 	goto out; /* all is well */
 
@@ -305,58 +364,71 @@
 	return err;
 }
 
-/* A feature which supports mount_nodev() with options */
-static struct dentry *mount_nodev_with_options(struct file_system_type *fs_type,
-        int flags, const char *dev_name, void *data,
-        int (*fill_super)(struct super_block *, const char *, void *, int))
+struct sdcardfs_mount_private {
+	struct vfsmount *mnt;
+	const char *dev_name;
+	void *raw_data;
+};
 
+static int __sdcardfs_fill_super(
+	struct super_block *sb,
+	void *_priv, int silent)
 {
-	int error;
-	struct super_block *s = sget(fs_type, NULL, set_anon_super, flags, NULL);
+	struct sdcardfs_mount_private *priv = _priv;
 
-	if (IS_ERR(s))
-		return ERR_CAST(s);
-
-	s->s_flags = flags;
-
-	error = fill_super(s, dev_name, data, flags & MS_SILENT ? 1 : 0);
-	if (error) {
-		deactivate_locked_super(s);
-		return ERR_PTR(error);
-	}
-	s->s_flags |= MS_ACTIVE;
-	return dget(s->s_root);
+	return sdcardfs_read_super(priv->mnt,
+		sb, priv->dev_name, priv->raw_data, silent);
 }
 
-struct dentry *sdcardfs_mount(struct file_system_type *fs_type, int flags,
+static struct dentry *sdcardfs_mount(struct vfsmount *mnt,
+		struct file_system_type *fs_type, int flags,
 			    const char *dev_name, void *raw_data)
 {
-	/*
-	 * dev_name is a lower_path_name,
-	 * raw_data is a option string.
-	 */
-	return mount_nodev_with_options(fs_type, flags, dev_name,
-					raw_data, sdcardfs_read_super);
+	struct sdcardfs_mount_private priv = {
+		.mnt = mnt,
+		.dev_name = dev_name,
+		.raw_data = raw_data
+	};
+
+	return mount_nodev(fs_type, flags,
+		&priv, __sdcardfs_fill_super);
 }
 
-void sdcardfs_kill_sb(struct super_block *sb) {
+static struct dentry *sdcardfs_mount_wrn(struct file_system_type *fs_type,
+		    int flags, const char *dev_name, void *raw_data)
+{
+	WARN(1, "sdcardfs does not support mount. Use mount2.\n");
+	return ERR_PTR(-EINVAL);
+}
+
+void *sdcardfs_alloc_mnt_data(void)
+{
+	return kmalloc(sizeof(struct sdcardfs_vfsmount_options), GFP_KERNEL);
+}
+
+void sdcardfs_kill_sb(struct super_block *sb)
+{
 	struct sdcardfs_sb_info *sbi;
+
 	if (sb->s_magic == SDCARDFS_SUPER_MAGIC) {
 		sbi = SDCARDFS_SB(sb);
 		mutex_lock(&sdcardfs_super_list_lock);
 		list_del(&sbi->list);
 		mutex_unlock(&sdcardfs_super_list_lock);
 	}
-	generic_shutdown_super(sb);
+	kill_anon_super(sb);
 }
 
 static struct file_system_type sdcardfs_fs_type = {
 	.owner		= THIS_MODULE,
 	.name		= SDCARDFS_NAME,
-	.mount		= sdcardfs_mount,
+	.mount		= sdcardfs_mount_wrn,
+	.mount2		= sdcardfs_mount,
+	.alloc_mnt_data = sdcardfs_alloc_mnt_data,
 	.kill_sb	= sdcardfs_kill_sb,
 	.fs_flags	= 0,
 };
+MODULE_ALIAS_FS(SDCARDFS_NAME);
 
 static int __init init_sdcardfs_fs(void)
 {
@@ -392,10 +464,15 @@
 	pr_info("Completed sdcardfs module unload\n");
 }
 
-MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
-	      " (http://www.fsl.cs.sunysb.edu/)");
-MODULE_DESCRIPTION("Wrapfs " SDCARDFS_VERSION
-		   " (http://wrapfs.filesystems.org/)");
+/* Original wrapfs authors */
+MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University (http://www.fsl.cs.sunysb.edu/)");
+
+/* Original sdcardfs authors */
+MODULE_AUTHOR("Woojoong Lee, Daeho Jeong, Kitae Lee, Yeongjin Gil System Memory Lab., Samsung Electronics");
+
+/* Current maintainer */
+MODULE_AUTHOR("Daniel Rosenberg, Google");
+MODULE_DESCRIPTION("Sdcardfs " SDCARDFS_VERSION);
 MODULE_LICENSE("GPL");
 
 module_init(init_sdcardfs_fs);
diff --git a/fs/sdcardfs/mmap.c b/fs/sdcardfs/mmap.c
index e21f646..b61f822 100644
--- a/fs/sdcardfs/mmap.c
+++ b/fs/sdcardfs/mmap.c
@@ -23,28 +23,46 @@
 static int sdcardfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	int err;
-	struct file *file, *lower_file;
+	struct file *file;
 	const struct vm_operations_struct *lower_vm_ops;
-	struct vm_area_struct lower_vma;
 
-	memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
-	file = lower_vma.vm_file;
+	file = (struct file *)vma->vm_private_data;
 	lower_vm_ops = SDCARDFS_F(file)->lower_vm_ops;
 	BUG_ON(!lower_vm_ops);
 
-	lower_file = sdcardfs_lower_file(file);
-	/*
-	 * XXX: vm_ops->fault may be called in parallel.  Because we have to
-	 * resort to temporarily changing the vma->vm_file to point to the
-	 * lower file, a concurrent invocation of sdcardfs_fault could see a
-	 * different value.  In this workaround, we keep a different copy of
-	 * the vma structure in our stack, so we never expose a different
-	 * value of the vma->vm_file called to us, even temporarily.  A
-	 * better fix would be to change the calling semantics of ->fault to
-	 * take an explicit file pointer.
-	 */
-	lower_vma.vm_file = lower_file;
-	err = lower_vm_ops->fault(&lower_vma, vmf);
+	err = lower_vm_ops->fault(vma, vmf);
+	return err;
+}
+
+static void sdcardfs_vm_open(struct vm_area_struct *vma)
+{
+	struct file *file = (struct file *)vma->vm_private_data;
+
+	get_file(file);
+}
+
+static void sdcardfs_vm_close(struct vm_area_struct *vma)
+{
+	struct file *file = (struct file *)vma->vm_private_data;
+
+	fput(file);
+}
+
+static int sdcardfs_page_mkwrite(struct vm_area_struct *vma,
+			       struct vm_fault *vmf)
+{
+	int err = 0;
+	struct file *file;
+	const struct vm_operations_struct *lower_vm_ops;
+
+	file = (struct file *)vma->vm_private_data;
+	lower_vm_ops = SDCARDFS_F(file)->lower_vm_ops;
+	BUG_ON(!lower_vm_ops);
+	if (!lower_vm_ops->page_mkwrite)
+		goto out;
+
+	err = lower_vm_ops->page_mkwrite(vma, vmf);
+out:
 	return err;
 }
 
@@ -52,30 +70,20 @@
 		struct iov_iter *iter, loff_t pos)
 {
 	/*
-     * This function returns zero on purpose in order to support direct IO.
-	 * __dentry_open checks a_ops->direct_IO and returns EINVAL if it is null.
-     *
-	 * However, this function won't be called by certain file operations
-     * including generic fs functions.  * reads and writes are delivered to
-     * the lower file systems and the direct IOs will be handled by them.
-	 *
-     * NOTE: exceptionally, on the recent kernels (since Linux 3.8.x),
-     * swap_writepage invokes this function directly.
+	 * This function should never be called directly.  We need it
+	 * to exist, to get past a check in open_check_o_direct(),
+	 * which is called from do_last().
 	 */
-	printk(KERN_INFO "%s, operation is not supported\n", __func__);
-	return 0;
+	return -EINVAL;
 }
 
-/*
- * XXX: the default address_space_ops for sdcardfs is empty.  We cannot set
- * our inode->i_mapping->a_ops to NULL because too many code paths expect
- * the a_ops vector to be non-NULL.
- */
 const struct address_space_operations sdcardfs_aops = {
-	/* empty on purpose */
 	.direct_IO	= sdcardfs_direct_IO,
 };
 
 const struct vm_operations_struct sdcardfs_vm_ops = {
 	.fault		= sdcardfs_fault,
+	.page_mkwrite	= sdcardfs_page_mkwrite,
+	.open		= sdcardfs_vm_open,
+	.close		= sdcardfs_vm_close,
 };
diff --git a/fs/sdcardfs/multiuser.h b/fs/sdcardfs/multiuser.h
index 923ba10..85341e7 100644
--- a/fs/sdcardfs/multiuser.h
+++ b/fs/sdcardfs/multiuser.h
@@ -18,20 +18,36 @@
  * General Public License.
  */
 
-#define MULTIUSER_APP_PER_USER_RANGE 100000
+#define AID_USER_OFFSET     100000 /* offset for uid ranges for each user */
+#define AID_APP_START        10000 /* first app user */
+#define AID_APP_END          19999 /* last app user */
+#define AID_CACHE_GID_START  20000 /* start of gids for apps to mark cached data */
+#define AID_EXT_GID_START    30000 /* start of gids for apps to mark external data */
+#define AID_EXT_CACHE_GID_START 40000 /* start of gids for apps to mark external cached data */
+#define AID_EXT_CACHE_GID_END 49999   /* end of gids for apps to mark external cached data */
+#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
 
 typedef uid_t userid_t;
 typedef uid_t appid_t;
 
-static inline userid_t multiuser_get_user_id(uid_t uid) {
-    return uid / MULTIUSER_APP_PER_USER_RANGE;
+static inline uid_t multiuser_get_uid(userid_t user_id, appid_t app_id)
+{
+	return (user_id * AID_USER_OFFSET) + (app_id % AID_USER_OFFSET);
 }
 
-static inline appid_t multiuser_get_app_id(uid_t uid) {
-    return uid % MULTIUSER_APP_PER_USER_RANGE;
+static inline bool uid_is_app(uid_t uid)
+{
+	appid_t appid = uid % AID_USER_OFFSET;
+
+	return appid >= AID_APP_START && appid <= AID_APP_END;
 }
 
-static inline uid_t multiuser_get_uid(userid_t userId, appid_t appId) {
-    return userId * MULTIUSER_APP_PER_USER_RANGE + (appId % MULTIUSER_APP_PER_USER_RANGE);
+static inline gid_t multiuser_get_ext_cache_gid(uid_t uid)
+{
+	return uid - AID_APP_START + AID_EXT_CACHE_GID_START;
 }
 
+static inline gid_t multiuser_get_ext_gid(uid_t uid)
+{
+	return uid - AID_APP_START + AID_EXT_GID_START;
+}
diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c
index 9c33405..66c6f8e 100644
--- a/fs/sdcardfs/packagelist.c
+++ b/fs/sdcardfs/packagelist.c
@@ -20,8 +20,10 @@
 
 #include "sdcardfs.h"
 #include <linux/hashtable.h>
+#include <linux/ctype.h>
 #include <linux/delay.h>
-
+#include <linux/radix-tree.h>
+#include <linux/dcache.h>
 
 #include <linux/init.h>
 #include <linux/module.h>
@@ -29,386 +31,822 @@
 
 #include <linux/configfs.h>
 
-#define STRING_BUF_SIZE		(512)
-
 struct hashtable_entry {
 	struct hlist_node hlist;
-	void *key;
-	unsigned int value;
+	struct hlist_node dlist; /* for deletion cleanup */
+	struct qstr key;
+	atomic_t value;
 };
 
-struct sb_list {
-	struct super_block *sb;
-	struct list_head list;
-};
+static DEFINE_HASHTABLE(package_to_appid, 8);
+static DEFINE_HASHTABLE(package_to_userid, 8);
+static DEFINE_HASHTABLE(ext_to_groupid, 8);
 
-struct packagelist_data {
-	DECLARE_HASHTABLE(package_to_appid,8);
-	struct mutex hashtable_lock;
-
-};
-
-static struct packagelist_data *pkgl_data_all;
 
 static struct kmem_cache *hashtable_entry_cachep;
 
-static unsigned int str_hash(const char *key) {
-	int i;
-	unsigned int h = strlen(key);
-	char *data = (char *)key;
+static unsigned int full_name_case_hash(const unsigned char *name, unsigned int len)
+{
+	unsigned long hash = init_name_hash();
 
-	for (i = 0; i < strlen(key); i++) {
-		h = h * 31 + *data;
-		data++;
-	}
-	return h;
+	while (len--)
+		hash = partial_name_hash(tolower(*name++), hash);
+	return end_name_hash(hash);
 }
 
-appid_t get_appid(void *pkgl_id, const char *app_name)
+static inline void qstr_init(struct qstr *q, const char *name)
 {
-	struct packagelist_data *pkgl_dat = pkgl_data_all;
+	q->name = name;
+	q->len = strlen(q->name);
+	q->hash = full_name_case_hash(q->name, q->len);
+}
+
+static inline int qstr_copy(const struct qstr *src, struct qstr *dest)
+{
+	dest->name = kstrdup(src->name, GFP_KERNEL);
+	dest->hash_len = src->hash_len;
+	return !!dest->name;
+}
+
+
+static appid_t __get_appid(const struct qstr *key)
+{
 	struct hashtable_entry *hash_cur;
-	unsigned int hash = str_hash(app_name);
+	unsigned int hash = key->hash;
 	appid_t ret_id;
 
-	mutex_lock(&pkgl_dat->hashtable_lock);
-	hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) {
-		if (!strcasecmp(app_name, hash_cur->key)) {
-			ret_id = (appid_t)hash_cur->value;
-			mutex_unlock(&pkgl_dat->hashtable_lock);
+	rcu_read_lock();
+	hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			ret_id = atomic_read(&hash_cur->value);
+			rcu_read_unlock();
 			return ret_id;
 		}
 	}
-	mutex_unlock(&pkgl_dat->hashtable_lock);
+	rcu_read_unlock();
 	return 0;
 }
 
+appid_t get_appid(const char *key)
+{
+	struct qstr q;
+
+	qstr_init(&q, key);
+	return __get_appid(&q);
+}
+
+static appid_t __get_ext_gid(const struct qstr *key)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = key->hash;
+	appid_t ret_id;
+
+	rcu_read_lock();
+	hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			ret_id = atomic_read(&hash_cur->value);
+			rcu_read_unlock();
+			return ret_id;
+		}
+	}
+	rcu_read_unlock();
+	return 0;
+}
+
+appid_t get_ext_gid(const char *key)
+{
+	struct qstr q;
+
+	qstr_init(&q, key);
+	return __get_ext_gid(&q);
+}
+
+static appid_t __is_excluded(const struct qstr *app_name, userid_t user)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = app_name->hash;
+
+	rcu_read_lock();
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (atomic_read(&hash_cur->value) == user &&
+				qstr_case_eq(app_name, &hash_cur->key)) {
+			rcu_read_unlock();
+			return 1;
+		}
+	}
+	rcu_read_unlock();
+	return 0;
+}
+
+appid_t is_excluded(const char *key, userid_t user)
+{
+	struct qstr q;
+	qstr_init(&q, key);
+	return __is_excluded(&q, user);
+}
+
 /* Kernel has already enforced everything we returned through
  * derive_permissions_locked(), so this is used to lock down access
- * even further, such as enforcing that apps hold sdcard_rw. */
-int check_caller_access_to_name(struct inode *parent_node, const char* name) {
+ * even further, such as enforcing that apps hold sdcard_rw.
+ */
+int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name)
+{
+	struct qstr q_autorun = QSTR_LITERAL("autorun.inf");
+	struct qstr q__android_secure = QSTR_LITERAL(".android_secure");
+	struct qstr q_android_secure = QSTR_LITERAL("android_secure");
 
 	/* Always block security-sensitive files at root */
-	if (parent_node && SDCARDFS_I(parent_node)->perm == PERM_ROOT) {
-		if (!strcasecmp(name, "autorun.inf")
-			|| !strcasecmp(name, ".android_secure")
-			|| !strcasecmp(name, "android_secure")) {
+	if (parent_node && SDCARDFS_I(parent_node)->data->perm == PERM_ROOT) {
+		if (qstr_case_eq(name, &q_autorun)
+			|| qstr_case_eq(name, &q__android_secure)
+			|| qstr_case_eq(name, &q_android_secure)) {
 			return 0;
 		}
 	}
 
 	/* Root always has access; access for any other UIDs should always
-	 * be controlled through packages.list. */
-	if (from_kuid(&init_user_ns, current_fsuid()) == 0) {
+	 * be controlled through packages.list.
+	 */
+	if (from_kuid(&init_user_ns, current_fsuid()) == 0)
 		return 1;
-	}
 
 	/* No extra permissions to enforce */
 	return 1;
 }
 
-/* This function is used when file opening. The open flags must be
- * checked before calling check_caller_access_to_name() */
-int open_flags_to_access_mode(int open_flags) {
-	if((open_flags & O_ACCMODE) == O_RDONLY) {
-		return 0; /* R_OK */
-	} else if ((open_flags & O_ACCMODE) == O_WRONLY) {
-		return 1; /* W_OK */
-	} else {
-		/* Probably O_RDRW, but treat as default to be safe */
-		return 1; /* R_OK | W_OK */
-	}
-}
-
-static int insert_str_to_int_lock(struct packagelist_data *pkgl_dat, char *key,
-		unsigned int value)
+static struct hashtable_entry *alloc_hashtable_entry(const struct qstr *key,
+		appid_t value)
 {
-	struct hashtable_entry *hash_cur;
-	struct hashtable_entry *new_entry;
-	unsigned int hash = str_hash(key);
+	struct hashtable_entry *ret = kmem_cache_alloc(hashtable_entry_cachep,
+			GFP_KERNEL);
+	if (!ret)
+		return NULL;
+	INIT_HLIST_NODE(&ret->dlist);
+	INIT_HLIST_NODE(&ret->hlist);
 
-	hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) {
-		if (!strcasecmp(key, hash_cur->key)) {
-			hash_cur->value = value;
-			return 0;
-		}
+	if (!qstr_copy(key, &ret->key)) {
+		kmem_cache_free(hashtable_entry_cachep, ret);
+		return NULL;
 	}
-	new_entry = kmem_cache_alloc(hashtable_entry_cachep, GFP_KERNEL);
-	if (!new_entry)
-		return -ENOMEM;
-	new_entry->key = kstrdup(key, GFP_KERNEL);
-	new_entry->value = value;
-	hash_add(pkgl_dat->package_to_appid, &new_entry->hlist, hash);
-	return 0;
-}
 
-static void fixup_perms(struct super_block *sb) {
-	if (sb && sb->s_magic == SDCARDFS_SUPER_MAGIC) {
-		mutex_lock(&sb->s_root->d_inode->i_mutex);
-		get_derive_permissions_recursive(sb->s_root);
-		mutex_unlock(&sb->s_root->d_inode->i_mutex);
-	}
-}
-
-static int insert_str_to_int(struct packagelist_data *pkgl_dat, char *key,
-		unsigned int value) {
-	int ret;
-	struct sdcardfs_sb_info *sbinfo;
-	mutex_lock(&sdcardfs_super_list_lock);
-	mutex_lock(&pkgl_dat->hashtable_lock);
-	ret = insert_str_to_int_lock(pkgl_dat, key, value);
-	mutex_unlock(&pkgl_dat->hashtable_lock);
-
-	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
-		if (sbinfo) {
-			fixup_perms(sbinfo->sb);
-		}
-	}
-	mutex_unlock(&sdcardfs_super_list_lock);
+	atomic_set(&ret->value, value);
 	return ret;
 }
 
-static void remove_str_to_int_lock(struct hashtable_entry *h_entry) {
-	kfree(h_entry->key);
-	hash_del(&h_entry->hlist);
-	kmem_cache_free(hashtable_entry_cachep, h_entry);
+static int insert_packagelist_appid_entry_locked(const struct qstr *key, appid_t value)
+{
+	struct hashtable_entry *hash_cur;
+	struct hashtable_entry *new_entry;
+	unsigned int hash = key->hash;
+
+	hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			atomic_set(&hash_cur->value, value);
+			return 0;
+		}
+	}
+	new_entry = alloc_hashtable_entry(key, value);
+	if (!new_entry)
+		return -ENOMEM;
+	hash_add_rcu(package_to_appid, &new_entry->hlist, hash);
+	return 0;
 }
 
-static void remove_str_to_int(struct packagelist_data *pkgl_dat, const char *key)
+static int insert_ext_gid_entry_locked(const struct qstr *key, appid_t value)
+{
+	struct hashtable_entry *hash_cur;
+	struct hashtable_entry *new_entry;
+	unsigned int hash = key->hash;
+
+	/* An extension can only belong to one gid */
+	hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key))
+			return -EINVAL;
+	}
+	new_entry = alloc_hashtable_entry(key, value);
+	if (!new_entry)
+		return -ENOMEM;
+	hash_add_rcu(ext_to_groupid, &new_entry->hlist, hash);
+	return 0;
+}
+
+static int insert_userid_exclude_entry_locked(const struct qstr *key, userid_t value)
+{
+	struct hashtable_entry *hash_cur;
+	struct hashtable_entry *new_entry;
+	unsigned int hash = key->hash;
+
+	/* Only insert if not already present */
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (atomic_read(&hash_cur->value) == value &&
+				qstr_case_eq(key, &hash_cur->key))
+			return 0;
+	}
+	new_entry = alloc_hashtable_entry(key, value);
+	if (!new_entry)
+		return -ENOMEM;
+	hash_add_rcu(package_to_userid, &new_entry->hlist, hash);
+	return 0;
+}
+
+static void fixup_all_perms_name(const struct qstr *key)
 {
 	struct sdcardfs_sb_info *sbinfo;
-	struct hashtable_entry *hash_cur;
-	unsigned int hash = str_hash(key);
+	struct limit_search limit = {
+		.flags = BY_NAME,
+		.name = QSTR_INIT(key->name, key->len),
+	};
+	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
+		if (sbinfo_has_sdcard_magic(sbinfo))
+			fixup_perms_recursive(sbinfo->sb->s_root, &limit);
+	}
+}
+
+static void fixup_all_perms_name_userid(const struct qstr *key, userid_t userid)
+{
+	struct sdcardfs_sb_info *sbinfo;
+	struct limit_search limit = {
+		.flags = BY_NAME | BY_USERID,
+		.name = QSTR_INIT(key->name, key->len),
+		.userid = userid,
+	};
+	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
+		if (sbinfo_has_sdcard_magic(sbinfo))
+			fixup_perms_recursive(sbinfo->sb->s_root, &limit);
+	}
+}
+
+static void fixup_all_perms_userid(userid_t userid)
+{
+	struct sdcardfs_sb_info *sbinfo;
+	struct limit_search limit = {
+		.flags = BY_USERID,
+		.userid = userid,
+	};
+	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
+		if (sbinfo_has_sdcard_magic(sbinfo))
+			fixup_perms_recursive(sbinfo->sb->s_root, &limit);
+	}
+}
+
+static int insert_packagelist_entry(const struct qstr *key, appid_t value)
+{
+	int err;
+
 	mutex_lock(&sdcardfs_super_list_lock);
-	mutex_lock(&pkgl_dat->hashtable_lock);
-	hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) {
-		if (!strcasecmp(key, hash_cur->key)) {
-			remove_str_to_int_lock(hash_cur);
+	err = insert_packagelist_appid_entry_locked(key, value);
+	if (!err)
+		fixup_all_perms_name(key);
+	mutex_unlock(&sdcardfs_super_list_lock);
+
+	return err;
+}
+
+static int insert_ext_gid_entry(const struct qstr *key, appid_t value)
+{
+	int err;
+
+	mutex_lock(&sdcardfs_super_list_lock);
+	err = insert_ext_gid_entry_locked(key, value);
+	mutex_unlock(&sdcardfs_super_list_lock);
+
+	return err;
+}
+
+static int insert_userid_exclude_entry(const struct qstr *key, userid_t value)
+{
+	int err;
+
+	mutex_lock(&sdcardfs_super_list_lock);
+	err = insert_userid_exclude_entry_locked(key, value);
+	if (!err)
+		fixup_all_perms_name_userid(key, value);
+	mutex_unlock(&sdcardfs_super_list_lock);
+
+	return err;
+}
+
+static void free_hashtable_entry(struct hashtable_entry *entry)
+{
+	kfree(entry->key.name);
+	kmem_cache_free(hashtable_entry_cachep, entry);
+}
+
+static void remove_packagelist_entry_locked(const struct qstr *key)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = key->hash;
+	struct hlist_node *h_t;
+	HLIST_HEAD(free_list);
+
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			hash_del_rcu(&hash_cur->hlist);
+			hlist_add_head(&hash_cur->dlist, &free_list);
+		}
+	}
+	hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key)) {
+			hash_del_rcu(&hash_cur->hlist);
+			hlist_add_head(&hash_cur->dlist, &free_list);
 			break;
 		}
 	}
-	mutex_unlock(&pkgl_dat->hashtable_lock);
-	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
-		if (sbinfo) {
-			fixup_perms(sbinfo->sb);
-		}
-	}
-	mutex_unlock(&sdcardfs_super_list_lock);
-	return;
+	synchronize_rcu();
+	hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
+		free_hashtable_entry(hash_cur);
 }
 
-static void remove_all_hashentrys(struct packagelist_data *pkgl_dat)
+static void remove_packagelist_entry(const struct qstr *key)
+{
+	mutex_lock(&sdcardfs_super_list_lock);
+	remove_packagelist_entry_locked(key);
+	fixup_all_perms_name(key);
+	mutex_unlock(&sdcardfs_super_list_lock);
+}
+
+static void remove_ext_gid_entry_locked(const struct qstr *key, gid_t group)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = key->hash;
+
+	hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key) && atomic_read(&hash_cur->value) == group) {
+			hash_del_rcu(&hash_cur->hlist);
+			synchronize_rcu();
+			free_hashtable_entry(hash_cur);
+			break;
+		}
+	}
+}
+
+static void remove_ext_gid_entry(const struct qstr *key, gid_t group)
+{
+	mutex_lock(&sdcardfs_super_list_lock);
+	remove_ext_gid_entry_locked(key, group);
+	mutex_unlock(&sdcardfs_super_list_lock);
+}
+
+static void remove_userid_all_entry_locked(userid_t userid)
 {
 	struct hashtable_entry *hash_cur;
 	struct hlist_node *h_t;
+	HLIST_HEAD(free_list);
 	int i;
-	mutex_lock(&pkgl_dat->hashtable_lock);
-	hash_for_each_safe(pkgl_dat->package_to_appid, i, h_t, hash_cur, hlist)
-		remove_str_to_int_lock(hash_cur);
-	mutex_unlock(&pkgl_dat->hashtable_lock);
-	hash_init(pkgl_dat->package_to_appid);
-}
 
-static struct packagelist_data * packagelist_create(void)
-{
-	struct packagelist_data *pkgl_dat;
-
-	pkgl_dat = kmalloc(sizeof(*pkgl_dat), GFP_KERNEL | __GFP_ZERO);
-	if (!pkgl_dat) {
-                printk(KERN_ERR "sdcardfs: Failed to create hash\n");
-		return ERR_PTR(-ENOMEM);
+	hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) {
+		if (atomic_read(&hash_cur->value) == userid) {
+			hash_del_rcu(&hash_cur->hlist);
+			hlist_add_head(&hash_cur->dlist, &free_list);
+		}
 	}
-
-	mutex_init(&pkgl_dat->hashtable_lock);
-	hash_init(pkgl_dat->package_to_appid);
-
-	return pkgl_dat;
+	synchronize_rcu();
+	hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist) {
+		free_hashtable_entry(hash_cur);
+	}
 }
 
-static void packagelist_destroy(struct packagelist_data *pkgl_dat)
+static void remove_userid_all_entry(userid_t userid)
 {
-	remove_all_hashentrys(pkgl_dat);
-	printk(KERN_INFO "sdcardfs: destroyed packagelist pkgld\n");
-	kfree(pkgl_dat);
+	mutex_lock(&sdcardfs_super_list_lock);
+	remove_userid_all_entry_locked(userid);
+	fixup_all_perms_userid(userid);
+	mutex_unlock(&sdcardfs_super_list_lock);
 }
 
-struct package_appid {
+static void remove_userid_exclude_entry_locked(const struct qstr *key, userid_t userid)
+{
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = key->hash;
+
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(key, &hash_cur->key) &&
+				atomic_read(&hash_cur->value) == userid) {
+			hash_del_rcu(&hash_cur->hlist);
+			synchronize_rcu();
+			free_hashtable_entry(hash_cur);
+			break;
+		}
+	}
+}
+
+static void remove_userid_exclude_entry(const struct qstr *key, userid_t userid)
+{
+	mutex_lock(&sdcardfs_super_list_lock);
+	remove_userid_exclude_entry_locked(key, userid);
+	fixup_all_perms_name_userid(key, userid);
+	mutex_unlock(&sdcardfs_super_list_lock);
+}
+
+static void packagelist_destroy(void)
+{
+	struct hashtable_entry *hash_cur;
+	struct hlist_node *h_t;
+	HLIST_HEAD(free_list);
+	int i;
+
+	mutex_lock(&sdcardfs_super_list_lock);
+	hash_for_each_rcu(package_to_appid, i, hash_cur, hlist) {
+		hash_del_rcu(&hash_cur->hlist);
+		hlist_add_head(&hash_cur->dlist, &free_list);
+	}
+	hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) {
+		hash_del_rcu(&hash_cur->hlist);
+		hlist_add_head(&hash_cur->dlist, &free_list);
+	}
+	synchronize_rcu();
+	hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
+		free_hashtable_entry(hash_cur);
+	mutex_unlock(&sdcardfs_super_list_lock);
+	pr_info("sdcardfs: destroyed packagelist pkgld\n");
+}
+
+#define SDCARDFS_CONFIGFS_ATTR(_pfx, _name)			\
+static struct configfs_attribute _pfx##attr_##_name = {	\
+	.ca_name	= __stringify(_name),		\
+	.ca_mode	= S_IRUGO | S_IWUGO,		\
+	.ca_owner	= THIS_MODULE,			\
+	.show		= _pfx##_name##_show,		\
+	.store		= _pfx##_name##_store,		\
+}
+
+#define SDCARDFS_CONFIGFS_ATTR_RO(_pfx, _name)			\
+static struct configfs_attribute _pfx##attr_##_name = {	\
+	.ca_name	= __stringify(_name),		\
+	.ca_mode	= S_IRUGO,			\
+	.ca_owner	= THIS_MODULE,			\
+	.show		= _pfx##_name##_show,		\
+}
+
+#define SDCARDFS_CONFIGFS_ATTR_WO(_pfx, _name)			\
+static struct configfs_attribute _pfx##attr_##_name = {	\
+	.ca_name	= __stringify(_name),		\
+	.ca_mode	= S_IWUGO,			\
+	.ca_owner	= THIS_MODULE,			\
+	.store		= _pfx##_name##_store,		\
+}
+
+struct package_details {
 	struct config_item item;
-	int add_pid;
+	struct qstr name;
 };
 
-static inline struct package_appid *to_package_appid(struct config_item *item)
+static inline struct package_details *to_package_details(struct config_item *item)
 {
-	return item ? container_of(item, struct package_appid, item) : NULL;
+	return item ? container_of(item, struct package_details, item) : NULL;
 }
 
-static ssize_t package_appid_attr_show(struct config_item *item,
-				      char *page)
+static ssize_t package_details_appid_show(struct config_item *item, char *page)
 {
-	ssize_t count;
-	count = sprintf(page, "%d\n", get_appid(pkgl_data_all, item->ci_name));
-	return count;
+	return scnprintf(page, PAGE_SIZE, "%u\n", __get_appid(&to_package_details(item)->name));
 }
 
-static ssize_t package_appid_attr_store(struct config_item *item,
+static ssize_t package_details_appid_store(struct config_item *item,
 				       const char *page, size_t count)
 {
-	struct package_appid *package_appid = to_package_appid(item);
-	unsigned long tmp;
-	char *p = (char *) page;
+	unsigned int tmp;
 	int ret;
 
-	tmp = simple_strtoul(p, &p, 10);
-	if (!p || (*p && (*p != '\n')))
-		return -EINVAL;
+	ret = kstrtouint(page, 10, &tmp);
+	if (ret)
+		return ret;
 
-	if (tmp > INT_MAX)
-		return -ERANGE;
-	ret = insert_str_to_int(pkgl_data_all, item->ci_name, (unsigned int)tmp);
-	package_appid->add_pid = tmp;
+	ret = insert_packagelist_entry(&to_package_details(item)->name, tmp);
+
 	if (ret)
 		return ret;
 
 	return count;
 }
 
-static struct configfs_attribute package_appid_attr_add_pid = {
-	.ca_owner = THIS_MODULE,
-	.ca_name = "appid",
-	.ca_mode = S_IRUGO | S_IWUGO,
-	.show = package_appid_attr_show,
-	.store = package_appid_attr_store,
-};
+static ssize_t package_details_excluded_userids_show(struct config_item *item,
+				      char *page)
+{
+	struct package_details *package_details = to_package_details(item);
+	struct hashtable_entry *hash_cur;
+	unsigned int hash = package_details->name.hash;
+	int count = 0;
 
-static struct configfs_attribute *package_appid_attrs[] = {
-	&package_appid_attr_add_pid,
+	rcu_read_lock();
+	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
+		if (qstr_case_eq(&package_details->name, &hash_cur->key))
+			count += scnprintf(page + count, PAGE_SIZE - count,
+					"%d ", atomic_read(&hash_cur->value));
+	}
+	rcu_read_unlock();
+	if (count)
+		count--;
+	count += scnprintf(page + count, PAGE_SIZE - count, "\n");
+	return count;
+}
+
+static ssize_t package_details_excluded_userids_store(struct config_item *item,
+				       const char *page, size_t count)
+{
+	unsigned int tmp;
+	int ret;
+
+	ret = kstrtouint(page, 10, &tmp);
+	if (ret)
+		return ret;
+
+	ret = insert_userid_exclude_entry(&to_package_details(item)->name, tmp);
+
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static ssize_t package_details_clear_userid_store(struct config_item *item,
+				       const char *page, size_t count)
+{
+	unsigned int tmp;
+	int ret;
+
+	ret = kstrtouint(page, 10, &tmp);
+	if (ret)
+		return ret;
+	remove_userid_exclude_entry(&to_package_details(item)->name, tmp);
+	return count;
+}
+
+static void package_details_release(struct config_item *item)
+{
+	struct package_details *package_details = to_package_details(item);
+
+	pr_info("sdcardfs: removing %s\n", package_details->name.name);
+	remove_packagelist_entry(&package_details->name);
+	kfree(package_details->name.name);
+	kfree(package_details);
+}
+
+SDCARDFS_CONFIGFS_ATTR(package_details_, appid);
+SDCARDFS_CONFIGFS_ATTR(package_details_, excluded_userids);
+SDCARDFS_CONFIGFS_ATTR_WO(package_details_, clear_userid);
+
+static struct configfs_attribute *package_details_attrs[] = {
+	&package_details_attr_appid,
+	&package_details_attr_excluded_userids,
+	&package_details_attr_clear_userid,
 	NULL,
 };
 
-static void package_appid_release(struct config_item *item)
-{
-	printk(KERN_INFO "sdcardfs: removing %s\n", item->ci_dentry->d_name.name);
-	/* item->ci_name is freed already, so we rely on the dentry */
-	remove_str_to_int(pkgl_data_all, item->ci_dentry->d_name.name);
-	kfree(to_package_appid(item));
-}
-
-static struct configfs_item_operations package_appid_item_ops = {
-	.release		= package_appid_release,
+static struct configfs_item_operations package_details_item_ops = {
+	.release = package_details_release,
 };
 
 static struct config_item_type package_appid_type = {
-	.ct_item_ops	= &package_appid_item_ops,
-	.ct_attrs	= package_appid_attrs,
+	.ct_item_ops	= &package_details_item_ops,
+	.ct_attrs	= package_details_attrs,
 	.ct_owner	= THIS_MODULE,
 };
 
-
-struct sdcardfs_packages {
+struct extensions_value {
 	struct config_group group;
+	unsigned int num;
 };
 
-static inline struct sdcardfs_packages *to_sdcardfs_packages(struct config_item *item)
+struct extension_details {
+	struct config_item item;
+	struct qstr name;
+	unsigned int num;
+};
+
+static inline struct extensions_value *to_extensions_value(struct config_item *item)
 {
-	return item ? container_of(to_config_group(item), struct sdcardfs_packages, group) : NULL;
+	return item ? container_of(to_config_group(item), struct extensions_value, group) : NULL;
 }
 
-static struct config_item *sdcardfs_packages_make_item(struct config_group *group, const char *name)
+static inline struct extension_details *to_extension_details(struct config_item *item)
 {
-	struct package_appid *package_appid;
+	return item ? container_of(item, struct extension_details, item) : NULL;
+}
 
-	package_appid = kzalloc(sizeof(struct package_appid), GFP_KERNEL);
-	if (!package_appid)
+static void extension_details_release(struct config_item *item)
+{
+	struct extension_details *extension_details = to_extension_details(item);
+
+	pr_info("sdcardfs: No longer mapping %s files to gid %d\n",
+			extension_details->name.name, extension_details->num);
+	remove_ext_gid_entry(&extension_details->name, extension_details->num);
+	kfree(extension_details->name.name);
+	kfree(extension_details);
+}
+
+static struct configfs_item_operations extension_details_item_ops = {
+	.release = extension_details_release,
+};
+
+static struct config_item_type extension_details_type = {
+	.ct_item_ops = &extension_details_item_ops,
+	.ct_owner = THIS_MODULE,
+};
+
+static struct config_item *extension_details_make_item(struct config_group *group, const char *name)
+{
+	struct extensions_value *extensions_value = to_extensions_value(&group->cg_item);
+	struct extension_details *extension_details = kzalloc(sizeof(struct extension_details), GFP_KERNEL);
+	const char *tmp;
+	int ret;
+
+	if (!extension_details)
 		return ERR_PTR(-ENOMEM);
 
-	config_item_init_type_name(&package_appid->item, name,
-				   &package_appid_type);
+	tmp = kstrdup(name, GFP_KERNEL);
+	if (!tmp) {
+		kfree(extension_details);
+		return ERR_PTR(-ENOMEM);
+	}
+	qstr_init(&extension_details->name, tmp);
+	ret = insert_ext_gid_entry(&extension_details->name, extensions_value->num);
 
-	package_appid->add_pid = 0;
+	if (ret) {
+		kfree(extension_details->name.name);
+		kfree(extension_details);
+		return ERR_PTR(ret);
+	}
+	config_item_init_type_name(&extension_details->item, name, &extension_details_type);
 
-	return &package_appid->item;
+	return &extension_details->item;
 }
 
-static ssize_t packages_attr_show(struct config_item *item,
-					 char *page)
+static struct configfs_group_operations extensions_value_group_ops = {
+	.make_item = extension_details_make_item,
+};
+
+static struct config_item_type extensions_name_type = {
+	.ct_group_ops	= &extensions_value_group_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *extensions_make_group(struct config_group *group, const char *name)
 {
-	struct hashtable_entry *hash_cur;
-	struct hlist_node *h_t;
+	struct extensions_value *extensions_value;
+	unsigned int tmp;
+	int ret;
+
+	extensions_value = kzalloc(sizeof(struct extensions_value), GFP_KERNEL);
+	if (!extensions_value)
+		return ERR_PTR(-ENOMEM);
+	ret = kstrtouint(name, 10, &tmp);
+	if (ret) {
+		kfree(extensions_value);
+		return ERR_PTR(ret);
+	}
+
+	extensions_value->num = tmp;
+	config_group_init_type_name(&extensions_value->group, name,
+						&extensions_name_type);
+	return &extensions_value->group;
+}
+
+static void extensions_drop_group(struct config_group *group, struct config_item *item)
+{
+	struct extensions_value *value = to_extensions_value(item);
+
+	pr_info("sdcardfs: No longer mapping any files to gid %d\n", value->num);
+	kfree(value);
+}
+
+static struct configfs_group_operations extensions_group_ops = {
+	.make_group	= extensions_make_group,
+	.drop_item	= extensions_drop_group,
+};
+
+static struct config_item_type extensions_type = {
+	.ct_group_ops	= &extensions_group_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+struct config_group extension_group = {
+	.cg_item = {
+		.ci_namebuf = "extensions",
+		.ci_type = &extensions_type,
+	},
+};
+
+static struct config_item *packages_make_item(struct config_group *group, const char *name)
+{
+	struct package_details *package_details;
+	const char *tmp;
+
+	package_details = kzalloc(sizeof(struct package_details), GFP_KERNEL);
+	if (!package_details)
+		return ERR_PTR(-ENOMEM);
+	tmp = kstrdup(name, GFP_KERNEL);
+	if (!tmp) {
+		kfree(package_details);
+		return ERR_PTR(-ENOMEM);
+	}
+	qstr_init(&package_details->name, tmp);
+	config_item_init_type_name(&package_details->item, name,
+						&package_appid_type);
+
+	return &package_details->item;
+}
+
+static ssize_t packages_list_show(struct config_item *item, char *page)
+{
+	struct hashtable_entry *hash_cur_app;
+	struct hashtable_entry *hash_cur_user;
 	int i;
 	int count = 0, written = 0;
-	char errormsg[] = "<truncated>\n";
+	const char errormsg[] = "<truncated>\n";
+	unsigned int hash;
 
-	mutex_lock(&pkgl_data_all->hashtable_lock);
-	hash_for_each_safe(pkgl_data_all->package_to_appid, i, h_t, hash_cur, hlist) {
-		written = scnprintf(page + count, PAGE_SIZE - sizeof(errormsg) - count, "%s %d\n", (char *)hash_cur->key, hash_cur->value);
-		if (count + written == PAGE_SIZE - sizeof(errormsg)) {
+	rcu_read_lock();
+	hash_for_each_rcu(package_to_appid, i, hash_cur_app, hlist) {
+		written = scnprintf(page + count, PAGE_SIZE - sizeof(errormsg) - count, "%s %d\n",
+					hash_cur_app->key.name, atomic_read(&hash_cur_app->value));
+		hash = hash_cur_app->key.hash;
+		hash_for_each_possible_rcu(package_to_userid, hash_cur_user, hlist, hash) {
+			if (qstr_case_eq(&hash_cur_app->key, &hash_cur_user->key)) {
+				written += scnprintf(page + count + written - 1,
+					PAGE_SIZE - sizeof(errormsg) - count - written + 1,
+					" %d\n", atomic_read(&hash_cur_user->value)) - 1;
+			}
+		}
+		if (count + written == PAGE_SIZE - sizeof(errormsg) - 1) {
 			count += scnprintf(page + count, PAGE_SIZE - count, errormsg);
 			break;
 		}
 		count += written;
 	}
-	mutex_unlock(&pkgl_data_all->hashtable_lock);
+	rcu_read_unlock();
 
 	return count;
 }
 
-static struct configfs_attribute sdcardfs_packages_attr_description = {
-	.ca_owner = THIS_MODULE,
-	.ca_name = "packages_gid.list",
-	.ca_mode = S_IRUGO,
-	.show = packages_attr_show,
-};
-
-static struct configfs_attribute *sdcardfs_packages_attrs[] = {
-	&sdcardfs_packages_attr_description,
-	NULL,
-};
-
-static void sdcardfs_packages_release(struct config_item *item)
+static ssize_t packages_remove_userid_store(struct config_item *item,
+				       const char *page, size_t count)
 {
+	unsigned int tmp;
+	int ret;
 
-	printk(KERN_INFO "sdcardfs: destroyed something?\n");
-	kfree(to_sdcardfs_packages(item));
+	ret = kstrtouint(page, 10, &tmp);
+	if (ret)
+		return ret;
+	remove_userid_all_entry(tmp);
+	return count;
 }
 
-static struct configfs_item_operations sdcardfs_packages_item_ops = {
-	.release	= sdcardfs_packages_release,
+static struct configfs_attribute packages_attr_packages_gid_list = {
+	.ca_name	= "packages_gid.list",
+	.ca_mode	= S_IRUGO,
+	.ca_owner	= THIS_MODULE,
+	.show		= packages_list_show,
+};
+
+SDCARDFS_CONFIGFS_ATTR_WO(packages_, remove_userid);
+
+static struct configfs_attribute *packages_attrs[] = {
+	&packages_attr_packages_gid_list,
+	&packages_attr_remove_userid,
+	NULL,
 };
 
 /*
  * Note that, since no extra work is required on ->drop_item(),
  * no ->drop_item() is provided.
  */
-static struct configfs_group_operations sdcardfs_packages_group_ops = {
-	.make_item	= sdcardfs_packages_make_item,
+static struct configfs_group_operations packages_group_ops = {
+	.make_item	= packages_make_item,
 };
 
-static struct config_item_type sdcardfs_packages_type = {
-	.ct_item_ops	= &sdcardfs_packages_item_ops,
-	.ct_group_ops	= &sdcardfs_packages_group_ops,
-	.ct_attrs	= sdcardfs_packages_attrs,
+static struct config_item_type packages_type = {
+	.ct_group_ops	= &packages_group_ops,
+	.ct_attrs	= packages_attrs,
 	.ct_owner	= THIS_MODULE,
 };
 
-static struct configfs_subsystem sdcardfs_packages_subsys = {
+struct config_group *sd_default_groups[] = {
+	&extension_group,
+	NULL,
+};
+
+static struct configfs_subsystem sdcardfs_packages = {
 	.su_group = {
 		.cg_item = {
 			.ci_namebuf = "sdcardfs",
-			.ci_type = &sdcardfs_packages_type,
+			.ci_type = &packages_type,
 		},
+		.default_groups = sd_default_groups,
 	},
 };
 
 static int configfs_sdcardfs_init(void)
 {
-	int ret;
-	struct configfs_subsystem *subsys = &sdcardfs_packages_subsys;
+	int ret, i;
+	struct configfs_subsystem *subsys = &sdcardfs_packages;
 
+	for (i = 0; sd_default_groups[i]; i++)
+		config_group_init(sd_default_groups[i]);
 	config_group_init(&subsys->su_group);
 	mutex_init(&subsys->su_mutex);
 	ret = configfs_register_subsystem(subsys);
 	if (ret) {
-		printk(KERN_ERR "Error %d while registering subsystem %s\n",
+		pr_err("Error %d while registering subsystem %s\n",
 		       ret,
 		       subsys->su_group.cg_item.ci_namebuf);
 	}
@@ -417,7 +855,7 @@
 
 static void configfs_sdcardfs_exit(void)
 {
-	configfs_unregister_subsystem(&sdcardfs_packages_subsys);
+	configfs_unregister_subsystem(&sdcardfs_packages);
 }
 
 int packagelist_init(void)
@@ -426,19 +864,17 @@
 		kmem_cache_create("packagelist_hashtable_entry",
 					sizeof(struct hashtable_entry), 0, 0, NULL);
 	if (!hashtable_entry_cachep) {
-		printk(KERN_ERR "sdcardfs: failed creating pkgl_hashtable entry slab cache\n");
+		pr_err("sdcardfs: failed creating pkgl_hashtable entry slab cache\n");
 		return -ENOMEM;
 	}
 
-	pkgl_data_all = packagelist_create();
 	configfs_sdcardfs_init();
-        return 0;
+	return 0;
 }
 
 void packagelist_exit(void)
 {
 	configfs_sdcardfs_exit();
-	packagelist_destroy(pkgl_data_all);
-	if (hashtable_entry_cachep)
-		kmem_cache_destroy(hashtable_entry_cachep);
+	packagelist_destroy();
+	kmem_cache_destroy(hashtable_entry_cachep);
 }
diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h
index f111f89..b8624fd 100644
--- a/fs/sdcardfs/sdcardfs.h
+++ b/fs/sdcardfs/sdcardfs.h
@@ -29,6 +29,8 @@
 #include <linux/dcache.h>
 #include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/aio.h>
+#include <linux/kref.h>
 #include <linux/mm.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
@@ -52,7 +54,7 @@
 #define SDCARDFS_ROOT_INO     1
 
 /* useful for tracking code reachability */
-#define UDBG printk(KERN_DEFAULT "DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
+#define UDBG pr_default("DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
 
 #define SDCARDFS_DIRENT_SIZE 256
 
@@ -65,71 +67,90 @@
 #define AID_SDCARD_PICS   1033	/* external storage photos access */
 #define AID_SDCARD_AV     1034	/* external storage audio/video access */
 #define AID_SDCARD_ALL    1035	/* access all users external storage */
+#define AID_MEDIA_OBB     1059  /* obb files */
+
+#define AID_SDCARD_IMAGE  1057
 
 #define AID_PACKAGE_INFO  1027
 
-#define fix_derived_permission(x)	\
+
+/*
+ * Permissions are handled by our permission function.
+ * We don't want anyone who happens to look at our inode value to prematurely
+ * block access, so store more permissive values. These are probably never
+ * used.
+ */
+#define fixup_tmp_permissions(x)	\
 	do {						\
-		(x)->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(x)->d_uid);	\
-		(x)->i_gid = make_kgid(&init_user_ns, get_gid(SDCARDFS_I(x)));	\
-		(x)->i_mode = ((x)->i_mode & S_IFMT) | get_mode(SDCARDFS_I(x));\
+		(x)->i_uid = make_kuid(&init_user_ns,	\
+				SDCARDFS_I(x)->data->d_uid);	\
+		(x)->i_gid = make_kgid(&init_user_ns, AID_SDCARD_RW);	\
+		(x)->i_mode = ((x)->i_mode & S_IFMT) | 0775;\
 	} while (0)
 
-
 /* OVERRIDE_CRED() and REVERT_CRED()
- * 	OVERRID_CRED()
- * 		backup original task->cred
- * 		and modifies task->cred->fsuid/fsgid to specified value.
+ *	OVERRIDE_CRED()
+ *		backup original task->cred
+ *		and modifies task->cred->fsuid/fsgid to specified value.
  *	REVERT_CRED()
- * 		restore original task->cred->fsuid/fsgid.
+ *		restore original task->cred->fsuid/fsgid.
  * These two macro should be used in pair, and OVERRIDE_CRED() should be
  * placed at the beginning of a function, right after variable declaration.
  */
-#define OVERRIDE_CRED(sdcardfs_sbi, saved_cred)		\
-	saved_cred = override_fsids(sdcardfs_sbi);	\
-	if (!saved_cred) { return -ENOMEM; }
+#define OVERRIDE_CRED(sdcardfs_sbi, saved_cred, info)		\
+	do {	\
+		saved_cred = override_fsids(sdcardfs_sbi, info->data);	\
+		if (!saved_cred)	\
+			return -ENOMEM;	\
+	} while (0)
 
-#define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred)	\
-	saved_cred = override_fsids(sdcardfs_sbi);	\
-	if (!saved_cred) { return ERR_PTR(-ENOMEM); }
+#define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred, info)	\
+	do {	\
+		saved_cred = override_fsids(sdcardfs_sbi, info->data);	\
+		if (!saved_cred)	\
+			return ERR_PTR(-ENOMEM);	\
+	} while (0)
 
 #define REVERT_CRED(saved_cred)	revert_fsids(saved_cred)
 
-#define DEBUG_CRED()		\
-	printk("KAKJAGI: %s:%d fsuid %d fsgid %d\n", 	\
-		__FUNCTION__, __LINE__, 		\
-		(int)current->cred->fsuid, 		\
-		(int)current->cred->fsgid);
-
 /* Android 5.0 support */
 
 /* Permission mode for a specific node. Controls how file permissions
- * are derived for children nodes. */
+ * are derived for children nodes.
+ */
 typedef enum {
-    /* Nothing special; this node should just inherit from its parent. */
-    PERM_INHERIT,
-    /* This node is one level above a normal root; used for legacy layouts
-     * which use the first level to represent user_id. */
-    PERM_PRE_ROOT,
-    /* This node is "/" */
-    PERM_ROOT,
-    /* This node is "/Android" */
-    PERM_ANDROID,
-    /* This node is "/Android/data" */
-    PERM_ANDROID_DATA,
-    /* This node is "/Android/obb" */
-    PERM_ANDROID_OBB,
-    /* This node is "/Android/media" */
-    PERM_ANDROID_MEDIA,
+	/* Nothing special; this node should just inherit from its parent. */
+	PERM_INHERIT,
+	/* This node is one level above a normal root; used for legacy layouts
+	 * which use the first level to represent user_id.
+	 */
+	PERM_PRE_ROOT,
+	/* This node is "/" */
+	PERM_ROOT,
+	/* This node is "/Android" */
+	PERM_ANDROID,
+	/* This node is "/Android/data" */
+	PERM_ANDROID_DATA,
+	/* This node is "/Android/obb" */
+	PERM_ANDROID_OBB,
+	/* This node is "/Android/media" */
+	PERM_ANDROID_MEDIA,
+	/* This node is "/Android/[data|media|obb]/[package]" */
+	PERM_ANDROID_PACKAGE,
+	/* This node is "/Android/[data|media|obb]/[package]/cache" */
+	PERM_ANDROID_PACKAGE_CACHE,
 } perm_t;
 
 struct sdcardfs_sb_info;
 struct sdcardfs_mount_options;
+struct sdcardfs_inode_info;
+struct sdcardfs_inode_data;
 
 /* Do not directly use this function. Use OVERRIDE_CRED() instead. */
-const struct cred * override_fsids(struct sdcardfs_sb_info* sbi);
+const struct cred *override_fsids(struct sdcardfs_sb_info *sbi,
+			struct sdcardfs_inode_data *data);
 /* Do not directly use this function, use REVERT_CRED() instead. */
-void revert_fsids(const struct cred * old_cred);
+void revert_fsids(const struct cred *old_cred);
 
 /* operations vectors defined in specific files */
 extern const struct file_operations sdcardfs_main_fops;
@@ -161,14 +182,26 @@
 	const struct vm_operations_struct *lower_vm_ops;
 };
 
-/* sdcardfs inode data in memory */
-struct sdcardfs_inode_info {
-	struct inode *lower_inode;
-	/* state derived based on current position in hierachy */
+struct sdcardfs_inode_data {
+	struct kref refcount;
+	bool abandoned;
+
 	perm_t perm;
 	userid_t userid;
 	uid_t d_uid;
 	bool under_android;
+	bool under_cache;
+	bool under_obb;
+};
+
+/* sdcardfs inode data in memory */
+struct sdcardfs_inode_info {
+	struct inode *lower_inode;
+	/* state derived based on current position in hierarchy */
+	struct sdcardfs_inode_data *data;
+
+	/* top folder for ownership */
+	struct sdcardfs_inode_data *top_data;
 
 	struct inode vfs_inode;
 };
@@ -185,18 +218,25 @@
 	uid_t fs_low_uid;
 	gid_t fs_low_gid;
 	userid_t fs_user_id;
-	gid_t gid;
-	mode_t mask;
 	bool multiuser;
 	unsigned int reserved_mb;
 };
 
+struct sdcardfs_vfsmount_options {
+	gid_t gid;
+	mode_t mask;
+};
+
+extern int parse_options_remount(struct super_block *sb, char *options, int silent,
+		struct sdcardfs_vfsmount_options *vfsopts);
+
 /* sdcardfs super-block data in memory */
 struct sdcardfs_sb_info {
 	struct super_block *sb;
 	struct super_block *lower_sb;
 	/* derived perm policy : some of options have been added
-	 * to sdcardfs_mount_options (Android 4.4 support) */
+	 * to sdcardfs_mount_options (Android 4.4 support)
+	 */
 	struct sdcardfs_mount_options options;
 	spinlock_t lock;	/* protects obbpath */
 	char *obbpath_s;
@@ -307,7 +347,7 @@
 { \
 	struct path pname; \
 	spin_lock(&SDCARDFS_D(dent)->lock); \
-	if(SDCARDFS_D(dent)->pname.dentry) { \
+	if (SDCARDFS_D(dent)->pname.dentry) { \
 		pathcpy(&pname, &SDCARDFS_D(dent)->pname); \
 		SDCARDFS_D(dent)->pname.dentry = NULL; \
 		SDCARDFS_D(dent)->pname.mnt = NULL; \
@@ -321,38 +361,97 @@
 SDCARDFS_DENT_FUNC(lower_path)
 SDCARDFS_DENT_FUNC(orig_path)
 
-static inline int get_gid(struct sdcardfs_inode_info *info) {
-	struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb);
-	if (sb_info->options.gid == AID_SDCARD_RW) {
+static inline bool sbinfo_has_sdcard_magic(struct sdcardfs_sb_info *sbinfo)
+{
+	return sbinfo && sbinfo->sb
+			&& sbinfo->sb->s_magic == SDCARDFS_SUPER_MAGIC;
+}
+
+static inline struct sdcardfs_inode_data *data_get(
+		struct sdcardfs_inode_data *data)
+{
+	if (data)
+		kref_get(&data->refcount);
+	return data;
+}
+
+static inline struct sdcardfs_inode_data *top_data_get(
+		struct sdcardfs_inode_info *info)
+{
+	return data_get(info->top_data);
+}
+
+extern void data_release(struct kref *ref);
+
+static inline void data_put(struct sdcardfs_inode_data *data)
+{
+	kref_put(&data->refcount, data_release);
+}
+
+static inline void release_own_data(struct sdcardfs_inode_info *info)
+{
+	/*
+	 * This happens exactly once per inode. At this point, the inode that
+	 * originally held this data is about to be freed, and all references
+	 * to it are held as a top value, and will likely be released soon.
+	 */
+	info->data->abandoned = true;
+	data_put(info->data);
+}
+
+static inline void set_top(struct sdcardfs_inode_info *info,
+			struct sdcardfs_inode_data *top)
+{
+	struct sdcardfs_inode_data *old_top = info->top_data;
+
+	if (top)
+		data_get(top);
+	info->top_data = top;
+	if (old_top)
+		data_put(old_top);
+}
+
+static inline int get_gid(struct vfsmount *mnt,
+		struct sdcardfs_inode_data *data)
+{
+	struct sdcardfs_vfsmount_options *opts = mnt->data;
+
+	if (opts->gid == AID_SDCARD_RW)
 		/* As an optimization, certain trusted system components only run
 		 * as owner but operate across all users. Since we're now handing
 		 * out the sdcard_rw GID only to trusted apps, we're okay relaxing
 		 * the user boundary enforcement for the default view. The UIDs
-		 * assigned to app directories are still multiuser aware. */
+		 * assigned to app directories are still multiuser aware.
+		 */
 		return AID_SDCARD_RW;
-	} else {
-		return multiuser_get_uid(info->userid, sb_info->options.gid);
-	}
+	else
+		return multiuser_get_uid(data->userid, opts->gid);
 }
-static inline int get_mode(struct sdcardfs_inode_info *info) {
+
+static inline int get_mode(struct vfsmount *mnt,
+		struct sdcardfs_inode_info *info,
+		struct sdcardfs_inode_data *data)
+{
 	int owner_mode;
 	int filtered_mode;
-	struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb);
-	int visible_mode = 0775 & ~sb_info->options.mask;
+	struct sdcardfs_vfsmount_options *opts = mnt->data;
+	int visible_mode = 0775 & ~opts->mask;
 
-	if (info->perm == PERM_PRE_ROOT) {
+
+	if (data->perm == PERM_PRE_ROOT) {
 		/* Top of multi-user view should always be visible to ensure
-		* secondary users can traverse inside. */
+		* secondary users can traverse inside.
+		*/
 		visible_mode = 0711;
-	} else if (info->under_android) {
+	} else if (data->under_android) {
 		/* Block "other" access to Android directories, since only apps
 		* belonging to a specific user should be in there; we still
-		* leave +x open for the default view. */
-		if (sb_info->options.gid == AID_SDCARD_RW) {
+		* leave +x open for the default view.
+		*/
+		if (opts->gid == AID_SDCARD_RW)
 			visible_mode = visible_mode & ~0006;
-		} else {
+		else
 			visible_mode = visible_mode & ~0007;
-		}
 	}
 	owner_mode = info->lower_inode->i_mode & 0700;
 	filtered_mode = visible_mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6));
@@ -377,7 +476,7 @@
 	/* in case of a local obb dentry
 	 * the orig_path should be returned
 	 */
-	if(has_graft_path(dent))
+	if (has_graft_path(dent))
 		sdcardfs_get_orig_path(dent, real_lower);
 	else
 		sdcardfs_get_lower_path(dent, real_lower);
@@ -386,7 +485,7 @@
 static inline void sdcardfs_put_real_lower(const struct dentry *dent,
 						struct path *real_lower)
 {
-	if(has_graft_path(dent))
+	if (has_graft_path(dent))
 		sdcardfs_put_orig_path(dent, real_lower);
 	else
 		sdcardfs_put_lower_path(dent, real_lower);
@@ -396,20 +495,31 @@
 extern struct list_head sdcardfs_super_list;
 
 /* for packagelist.c */
-extern appid_t get_appid(void *pkgl_id, const char *app_name);
-extern int check_caller_access_to_name(struct inode *parent_node, const char* name);
-extern int open_flags_to_access_mode(int open_flags);
+extern appid_t get_appid(const char *app_name);
+extern appid_t get_ext_gid(const char *app_name);
+extern appid_t is_excluded(const char *app_name, userid_t userid);
+extern int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name);
 extern int packagelist_init(void);
 extern void packagelist_exit(void);
 
 /* for derived_perm.c */
+#define BY_NAME		(1 << 0)
+#define BY_USERID	(1 << 1)
+struct limit_search {
+	unsigned int flags;
+	struct qstr name;
+	userid_t userid;
+};
+
 extern void setup_derived_state(struct inode *inode, perm_t perm,
-			userid_t userid, uid_t uid, bool under_android);
+		userid_t userid, uid_t uid, bool under_android,
+		struct sdcardfs_inode_data *top);
 extern void get_derived_permission(struct dentry *parent, struct dentry *dentry);
-extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, struct dentry *newdentry);
-extern void get_derive_permissions_recursive(struct dentry *parent);
+extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name);
+extern void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit);
 
 extern void update_derived_permission_lock(struct dentry *dentry);
+void fixup_lower_ownership(struct dentry *dentry, const char *name);
 extern int need_graft_path(struct dentry *dentry);
 extern int is_base_obbpath(struct dentry *dentry);
 extern int is_obbpath_invalid(struct dentry *dentry);
@@ -419,6 +529,7 @@
 static inline struct dentry *lock_parent(struct dentry *dentry)
 {
 	struct dentry *dir = dget_parent(dentry);
+
 	mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
 	return dir;
 }
@@ -444,7 +555,7 @@
 		goto out_unlock;
 	}
 
-	err = vfs_mkdir(d_inode(parent.dentry), dent, mode);
+	err = vfs_mkdir2(parent.mnt, d_inode(parent.dentry), dent, mode);
 	if (err) {
 		if (err == -EEXIST)
 			err = 0;
@@ -455,7 +566,7 @@
 	attrs.ia_gid = make_kgid(&init_user_ns, gid);
 	attrs.ia_valid = ATTR_UID | ATTR_GID;
 	mutex_lock(&d_inode(dent)->i_mutex);
-	notify_change(dent, &attrs, NULL);
+	notify_change2(parent.mnt, dent, &attrs, NULL);
 	mutex_unlock(&d_inode(dent)->i_mutex);
 
 out_dput:
@@ -513,12 +624,16 @@
 		return 1;
 }
 
-/* Copies attrs and maintains sdcardfs managed attrs */
+/*
+ * Copies attrs and maintains sdcardfs managed attrs
+ * Since our permission check handles all special permissions, set those to be open
+ */
 static inline void sdcardfs_copy_and_fix_attrs(struct inode *dest, const struct inode *src)
 {
-	dest->i_mode = (src->i_mode  & S_IFMT) | get_mode(SDCARDFS_I(dest));
-	dest->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(dest)->d_uid);
-	dest->i_gid = make_kgid(&init_user_ns, get_gid(SDCARDFS_I(dest)));
+	dest->i_mode = (src->i_mode  & S_IFMT) | S_IRWXU | S_IRWXG |
+			S_IROTH | S_IXOTH; /* 0775 */
+	dest->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(dest)->data->d_uid);
+	dest->i_gid = make_kgid(&init_user_ns, AID_SDCARD_RW);
 	dest->i_rdev = src->i_rdev;
 	dest->i_atime = src->i_atime;
 	dest->i_mtime = src->i_mtime;
@@ -527,4 +642,22 @@
 	dest->i_flags = src->i_flags;
 	set_nlink(dest, src->i_nlink);
 }
+
+static inline bool str_case_eq(const char *s1, const char *s2)
+{
+	return !strcasecmp(s1, s2);
+}
+
+static inline bool str_n_case_eq(const char *s1, const char *s2, size_t len)
+{
+	return !strncasecmp(s1, s2, len);
+}
+
+static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2)
+{
+	return q1->len == q2->len && str_case_eq(q1->name, q2->name);
+}
+
+#define QSTR_LITERAL(string) QSTR_INIT(string, sizeof(string)-1)
+
 #endif	/* not _SDCARDFS_H_ */
diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c
index 1d64901..7f4539b 100644
--- a/fs/sdcardfs/super.c
+++ b/fs/sdcardfs/super.c
@@ -26,6 +26,23 @@
  */
 static struct kmem_cache *sdcardfs_inode_cachep;
 
+/*
+ * To support the top references, we must track some data separately.
+ * An sdcardfs_inode_info always has a reference to its data, and once set up,
+ * also has a reference to its top. The top may be itself, in which case it
+ * holds two references to its data. When top is changed, it takes a ref to the
+ * new data and then drops the ref to the old data.
+ */
+static struct kmem_cache *sdcardfs_inode_data_cachep;
+
+void data_release(struct kref *ref)
+{
+	struct sdcardfs_inode_data *data =
+		container_of(ref, struct sdcardfs_inode_data, refcount);
+
+	kmem_cache_free(sdcardfs_inode_data_cachep, data);
+}
+
 /* final actions when unmounting a file system */
 static void sdcardfs_put_super(struct super_block *sb)
 {
@@ -36,7 +53,7 @@
 	if (!spd)
 		return;
 
-	if(spd->obbpath_s) {
+	if (spd->obbpath_s) {
 		kfree(spd->obbpath_s);
 		path_put(&spd->obbpath);
 	}
@@ -64,7 +81,7 @@
 	if (sbi->options.reserved_mb) {
 		/* Invalid statfs informations. */
 		if (buf->f_bsize == 0) {
-			printk(KERN_ERR "Returned block size is zero.\n");
+			pr_err("Returned block size is zero.\n");
 			return -EINVAL;
 		}
 
@@ -100,8 +117,7 @@
 	 * SILENT, but anything else left over is an error.
 	 */
 	if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT)) != 0) {
-		printk(KERN_ERR
-		       "sdcardfs: remount flags 0x%x unsupported\n", *flags);
+		pr_err("sdcardfs: remount flags 0x%x unsupported\n", *flags);
 		err = -EINVAL;
 	}
 
@@ -109,6 +125,54 @@
 }
 
 /*
+ * @mnt: mount point we are remounting
+ * @sb: superblock we are remounting
+ * @flags: numeric mount options
+ * @options: mount options string
+ */
+static int sdcardfs_remount_fs2(struct vfsmount *mnt, struct super_block *sb,
+						int *flags, char *options)
+{
+	int err = 0;
+
+	/*
+	 * The VFS will take care of "ro" and "rw" flags among others.  We
+	 * can safely accept a few flags (RDONLY, MANDLOCK), and honor
+	 * SILENT, but anything else left over is an error.
+	 */
+	if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT | MS_REMOUNT)) != 0) {
+		pr_err("sdcardfs: remount flags 0x%x unsupported\n", *flags);
+		err = -EINVAL;
+	}
+	pr_info("Remount options were %s for vfsmnt %p.\n", options, mnt);
+	err = parse_options_remount(sb, options, *flags & ~MS_SILENT, mnt->data);
+
+
+	return err;
+}
+
+static void *sdcardfs_clone_mnt_data(void *data)
+{
+	struct sdcardfs_vfsmount_options *opt = kmalloc(sizeof(struct sdcardfs_vfsmount_options), GFP_KERNEL);
+	struct sdcardfs_vfsmount_options *old = data;
+
+	if (!opt)
+		return NULL;
+	opt->gid = old->gid;
+	opt->mask = old->mask;
+	return opt;
+}
+
+static void sdcardfs_copy_mnt_data(void *data, void *newdata)
+{
+	struct sdcardfs_vfsmount_options *old = data;
+	struct sdcardfs_vfsmount_options *new = newdata;
+
+	old->gid = new->gid;
+	old->mask = new->mask;
+}
+
+/*
  * Called by iput() when the inode reference count reached zero
  * and the inode is not hashed anywhere.  Used to clear anything
  * that needs to be, before the inode is completely destroyed and put
@@ -119,6 +183,7 @@
 	struct inode *lower_inode;
 
 	truncate_inode_pages(&inode->i_data, 0);
+	set_top(SDCARDFS_I(inode), NULL);
 	clear_inode(inode);
 	/*
 	 * Decrement a reference to a lower_inode, which was incremented
@@ -132,6 +197,7 @@
 static struct inode *sdcardfs_alloc_inode(struct super_block *sb)
 {
 	struct sdcardfs_inode_info *i;
+	struct sdcardfs_inode_data *d;
 
 	i = kmem_cache_alloc(sdcardfs_inode_cachep, GFP_KERNEL);
 	if (!i)
@@ -140,13 +206,31 @@
 	/* memset everything up to the inode to 0 */
 	memset(i, 0, offsetof(struct sdcardfs_inode_info, vfs_inode));
 
+	d = kmem_cache_alloc(sdcardfs_inode_data_cachep,
+					GFP_KERNEL | __GFP_ZERO);
+	if (!d) {
+		kmem_cache_free(sdcardfs_inode_cachep, i);
+		return NULL;
+	}
+
+	i->data = d;
+	kref_init(&d->refcount);
+
 	i->vfs_inode.i_version = 1;
 	return &i->vfs_inode;
 }
 
+static void i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+
+	release_own_data(SDCARDFS_I(inode));
+	kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode));
+}
+
 static void sdcardfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode));
+	call_rcu(&inode->i_rcu, i_callback);
 }
 
 /* sdcardfs inode cache constructor */
@@ -159,22 +243,31 @@
 
 int sdcardfs_init_inode_cache(void)
 {
-	int err = 0;
-
 	sdcardfs_inode_cachep =
 		kmem_cache_create("sdcardfs_inode_cache",
 				  sizeof(struct sdcardfs_inode_info), 0,
 				  SLAB_RECLAIM_ACCOUNT, init_once);
+
 	if (!sdcardfs_inode_cachep)
-		err = -ENOMEM;
-	return err;
+		return -ENOMEM;
+
+	sdcardfs_inode_data_cachep =
+		kmem_cache_create("sdcardfs_inode_data_cache",
+				  sizeof(struct sdcardfs_inode_data), 0,
+				  SLAB_RECLAIM_ACCOUNT, NULL);
+	if (!sdcardfs_inode_data_cachep) {
+		kmem_cache_destroy(sdcardfs_inode_cachep);
+		return -ENOMEM;
+	}
+
+	return 0;
 }
 
 /* sdcardfs inode cache destructor */
 void sdcardfs_destroy_inode_cache(void)
 {
-	if (sdcardfs_inode_cachep)
-		kmem_cache_destroy(sdcardfs_inode_cachep);
+	kmem_cache_destroy(sdcardfs_inode_data_cachep);
+	kmem_cache_destroy(sdcardfs_inode_cachep);
 }
 
 /*
@@ -190,19 +283,25 @@
 		lower_sb->s_op->umount_begin(lower_sb);
 }
 
-static int sdcardfs_show_options(struct seq_file *m, struct dentry *root)
+static int sdcardfs_show_options(struct vfsmount *mnt, struct seq_file *m,
+			struct dentry *root)
 {
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(root->d_sb);
 	struct sdcardfs_mount_options *opts = &sbi->options;
+	struct sdcardfs_vfsmount_options *vfsopts = mnt->data;
 
 	if (opts->fs_low_uid != 0)
-		seq_printf(m, ",uid=%u", opts->fs_low_uid);
+		seq_printf(m, ",fsuid=%u", opts->fs_low_uid);
 	if (opts->fs_low_gid != 0)
-		seq_printf(m, ",gid=%u", opts->fs_low_gid);
-
+		seq_printf(m, ",fsgid=%u", opts->fs_low_gid);
+	if (vfsopts->gid != 0)
+		seq_printf(m, ",gid=%u", vfsopts->gid);
 	if (opts->multiuser)
-		seq_printf(m, ",multiuser");
-
+		seq_puts(m, ",multiuser");
+	if (vfsopts->mask)
+		seq_printf(m, ",mask=%u", vfsopts->mask);
+	if (opts->fs_user_id)
+		seq_printf(m, ",userid=%u", opts->fs_user_id);
 	if (opts->reserved_mb != 0)
 		seq_printf(m, ",reserved=%uMB", opts->reserved_mb);
 
@@ -213,9 +312,12 @@
 	.put_super	= sdcardfs_put_super,
 	.statfs		= sdcardfs_statfs,
 	.remount_fs	= sdcardfs_remount_fs,
+	.remount_fs2	= sdcardfs_remount_fs2,
+	.clone_mnt_data	= sdcardfs_clone_mnt_data,
+	.copy_mnt_data	= sdcardfs_copy_mnt_data,
 	.evict_inode	= sdcardfs_evict_inode,
 	.umount_begin	= sdcardfs_umount_begin,
-	.show_options	= sdcardfs_show_options,
+	.show_options2	= sdcardfs_show_options,
 	.alloc_inode	= sdcardfs_alloc_inode,
 	.destroy_inode	= sdcardfs_destroy_inode,
 	.drop_inode	= generic_delete_inode,
diff --git a/fs/seq_file.c b/fs/seq_file.c
index e85664b..d672e2f 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -222,8 +222,10 @@
 		size -= n;
 		buf += n;
 		copied += n;
-		if (!m->count)
+		if (!m->count) {
+			m->from = 0;
 			m->index++;
+		}
 		if (!size)
 			goto Done;
 	}
diff --git a/fs/splice.c b/fs/splice.c
index 0f77e96..8398974 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -211,6 +211,7 @@
 			buf->len = spd->partial[page_nr].len;
 			buf->private = spd->partial[page_nr].private;
 			buf->ops = spd->ops;
+			buf->flags = 0;
 			if (spd->flags & SPLICE_F_GIFT)
 				buf->flags |= PIPE_BUF_FLAG_GIFT;
 
diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index ffb093e..6dd158a 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -26,34 +26,6 @@
 	  If unsure, say N.
 
 choice
-	prompt "File decompression options"
-	depends on SQUASHFS
-	help
-	  Squashfs now supports two options for decompressing file
-	  data.  Traditionally Squashfs has decompressed into an
-	  intermediate buffer and then memcopied it into the page cache.
-	  Squashfs now supports the ability to decompress directly into
-	  the page cache.
-
-	  If unsure, select "Decompress file data into an intermediate buffer"
-
-config SQUASHFS_FILE_CACHE
-	bool "Decompress file data into an intermediate buffer"
-	help
-	  Decompress file data into an intermediate buffer and then
-	  memcopy it into the page cache.
-
-config SQUASHFS_FILE_DIRECT
-	bool "Decompress files directly into the page cache"
-	help
-	  Directly decompress file data into the page cache.
-	  Doing so can significantly improve performance because
-	  it eliminates a memcpy and it also removes the lock contention
-	  on the single buffer.
-
-endchoice
-
-choice
 	prompt "Decompressor parallelisation options"
 	depends on SQUASHFS
 	help
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
index 246a6f3..fe51f15 100644
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -5,8 +5,7 @@
 obj-$(CONFIG_SQUASHFS) += squashfs.o
 squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
 squashfs-y += namei.o super.o symlink.o decompressor.o
-squashfs-$(CONFIG_SQUASHFS_FILE_CACHE) += file_cache.o
-squashfs-$(CONFIG_SQUASHFS_FILE_DIRECT) += file_direct.o page_actor.o
+squashfs-y += file_direct.o page_actor.o
 squashfs-$(CONFIG_SQUASHFS_DECOMP_SINGLE) += decompressor_single.o
 squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI) += decompressor_multi.o
 squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU) += decompressor_multi_percpu.o
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 0cea9b9..b3b95e2 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -28,9 +28,12 @@
 
 #include <linux/fs.h>
 #include <linux/vfs.h>
+#include <linux/bio.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/pagemap.h>
 #include <linux/buffer_head.h>
+#include <linux/workqueue.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
@@ -38,45 +41,381 @@
 #include "decompressor.h"
 #include "page_actor.h"
 
-/*
- * Read the metadata block length, this is stored in the first two
- * bytes of the metadata block.
- */
-static struct buffer_head *get_block_length(struct super_block *sb,
-			u64 *cur_index, int *offset, int *length)
+static struct workqueue_struct *squashfs_read_wq;
+
+struct squashfs_read_request {
+	struct super_block *sb;
+	u64 index;
+	int length;
+	int compressed;
+	int offset;
+	u64 read_end;
+	struct squashfs_page_actor *output;
+	enum {
+		SQUASHFS_COPY,
+		SQUASHFS_DECOMPRESS,
+		SQUASHFS_METADATA,
+	} data_processing;
+	bool synchronous;
+
+	/*
+	 * If the read is synchronous, it is possible to retrieve information
+	 * about the request by setting these pointers.
+	 */
+	int *res;
+	int *bytes_read;
+	int *bytes_uncompressed;
+
+	int nr_buffers;
+	struct buffer_head **bh;
+	struct work_struct offload;
+};
+
+struct squashfs_bio_request {
+	struct buffer_head **bh;
+	int nr_buffers;
+};
+
+static int squashfs_bio_submit(struct squashfs_read_request *req);
+
+int squashfs_init_read_wq(void)
 {
-	struct squashfs_sb_info *msblk = sb->s_fs_info;
-	struct buffer_head *bh;
+	squashfs_read_wq = create_workqueue("SquashFS read wq");
+	return !!squashfs_read_wq;
+}
 
-	bh = sb_bread(sb, *cur_index);
-	if (bh == NULL)
-		return NULL;
+void squashfs_destroy_read_wq(void)
+{
+	flush_workqueue(squashfs_read_wq);
+	destroy_workqueue(squashfs_read_wq);
+}
 
-	if (msblk->devblksize - *offset == 1) {
-		*length = (unsigned char) bh->b_data[*offset];
-		put_bh(bh);
-		bh = sb_bread(sb, ++(*cur_index));
-		if (bh == NULL)
-			return NULL;
-		*length |= (unsigned char) bh->b_data[0] << 8;
-		*offset = 1;
-	} else {
-		*length = (unsigned char) bh->b_data[*offset] |
-			(unsigned char) bh->b_data[*offset + 1] << 8;
-		*offset += 2;
+static void free_read_request(struct squashfs_read_request *req, int error)
+{
+	if (!req->synchronous)
+		squashfs_page_actor_free(req->output, error);
+	if (req->res)
+		*(req->res) = error;
+	kfree(req->bh);
+	kfree(req);
+}
 
-		if (*offset == msblk->devblksize) {
-			put_bh(bh);
-			bh = sb_bread(sb, ++(*cur_index));
-			if (bh == NULL)
-				return NULL;
-			*offset = 0;
+static void squashfs_process_blocks(struct squashfs_read_request *req)
+{
+	int error = 0;
+	int bytes, i, length;
+	struct squashfs_sb_info *msblk = req->sb->s_fs_info;
+	struct squashfs_page_actor *actor = req->output;
+	struct buffer_head **bh = req->bh;
+	int nr_buffers = req->nr_buffers;
+
+	for (i = 0; i < nr_buffers; ++i) {
+		if (!bh[i])
+			continue;
+		wait_on_buffer(bh[i]);
+		if (!buffer_uptodate(bh[i]))
+			error = -EIO;
+	}
+	if (error)
+		goto cleanup;
+
+	if (req->data_processing == SQUASHFS_METADATA) {
+		/* Extract the length of the metadata block */
+		if (req->offset != msblk->devblksize - 1) {
+			length = le16_to_cpup((__le16 *)
+					(bh[0]->b_data + req->offset));
+		} else {
+			length = (unsigned char)bh[0]->b_data[req->offset];
+			length |= (unsigned char)bh[1]->b_data[0] << 8;
+		}
+		req->compressed = SQUASHFS_COMPRESSED(length);
+		req->data_processing = req->compressed ? SQUASHFS_DECOMPRESS
+						       : SQUASHFS_COPY;
+		length = SQUASHFS_COMPRESSED_SIZE(length);
+		if (req->index + length + 2 > req->read_end) {
+			for (i = 0; i < nr_buffers; ++i)
+				put_bh(bh[i]);
+			kfree(bh);
+			req->length = length;
+			req->index += 2;
+			squashfs_bio_submit(req);
+			return;
+		}
+		req->length = length;
+		req->offset = (req->offset + 2) % PAGE_SIZE;
+		if (req->offset < 2) {
+			put_bh(bh[0]);
+			++bh;
+			--nr_buffers;
+		}
+	}
+	if (req->bytes_read)
+		*(req->bytes_read) = req->length;
+
+	if (req->data_processing == SQUASHFS_COPY) {
+		squashfs_bh_to_actor(bh, nr_buffers, req->output, req->offset,
+			req->length, msblk->devblksize);
+	} else if (req->data_processing == SQUASHFS_DECOMPRESS) {
+		req->length = squashfs_decompress(msblk, bh, nr_buffers,
+			req->offset, req->length, actor);
+		if (req->length < 0) {
+			error = -EIO;
+			goto cleanup;
 		}
 	}
 
-	return bh;
+	/* Last page may have trailing bytes not filled */
+	bytes = req->length % PAGE_SIZE;
+	if (bytes && actor->page[actor->pages - 1])
+		zero_user_segment(actor->page[actor->pages - 1], bytes,
+				  PAGE_SIZE);
+
+cleanup:
+	if (req->bytes_uncompressed)
+		*(req->bytes_uncompressed) = req->length;
+	if (error) {
+		for (i = 0; i < nr_buffers; ++i)
+			if (bh[i])
+				put_bh(bh[i]);
+	}
+	free_read_request(req, error);
 }
 
+static void read_wq_handler(struct work_struct *work)
+{
+	squashfs_process_blocks(container_of(work,
+		    struct squashfs_read_request, offload));
+}
+
+static void squashfs_bio_end_io(struct bio *bio)
+{
+	int i;
+	int error = bio->bi_error;
+	struct squashfs_bio_request *bio_req = bio->bi_private;
+
+	bio_put(bio);
+
+	for (i = 0; i < bio_req->nr_buffers; ++i) {
+		if (!bio_req->bh[i])
+			continue;
+		if (!error)
+			set_buffer_uptodate(bio_req->bh[i]);
+		else
+			clear_buffer_uptodate(bio_req->bh[i]);
+		unlock_buffer(bio_req->bh[i]);
+	}
+	kfree(bio_req);
+}
+
+static int bh_is_optional(struct squashfs_read_request *req, int idx)
+{
+	int start_idx, end_idx;
+	struct squashfs_sb_info *msblk = req->sb->s_fs_info;
+
+	start_idx = (idx * msblk->devblksize - req->offset) >> PAGE_SHIFT;
+	end_idx = ((idx + 1) * msblk->devblksize - req->offset + 1) >> PAGE_SHIFT;
+	if (start_idx >= req->output->pages)
+		return 1;
+	if (start_idx < 0)
+		start_idx = end_idx;
+	if (end_idx >= req->output->pages)
+		end_idx = start_idx;
+	return !req->output->page[start_idx] && !req->output->page[end_idx];
+}
+
+static int actor_getblks(struct squashfs_read_request *req, u64 block)
+{
+	int i;
+
+	req->bh = kmalloc_array(req->nr_buffers, sizeof(*(req->bh)), GFP_NOIO);
+	if (!req->bh)
+		return -ENOMEM;
+
+	for (i = 0; i < req->nr_buffers; ++i) {
+		/*
+		 * When dealing with an uncompressed block, the actor may
+		 * contains NULL pages. There's no need to read the buffers
+		 * associated with these pages.
+		 */
+		if (!req->compressed && bh_is_optional(req, i)) {
+			req->bh[i] = NULL;
+			continue;
+		}
+		req->bh[i] = sb_getblk(req->sb, block + i);
+		if (!req->bh[i]) {
+			while (--i) {
+				if (req->bh[i])
+					put_bh(req->bh[i]);
+			}
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int squashfs_bio_submit(struct squashfs_read_request *req)
+{
+	struct bio *bio = NULL;
+	struct buffer_head *bh;
+	struct squashfs_bio_request *bio_req = NULL;
+	int b = 0, prev_block = 0;
+	struct squashfs_sb_info *msblk = req->sb->s_fs_info;
+
+	u64 read_start = round_down(req->index, msblk->devblksize);
+	u64 read_end = round_up(req->index + req->length, msblk->devblksize);
+	sector_t block = read_start >> msblk->devblksize_log2;
+	sector_t block_end = read_end >> msblk->devblksize_log2;
+	int offset = read_start - round_down(req->index, PAGE_SIZE);
+	int nr_buffers = block_end - block;
+	int blksz = msblk->devblksize;
+	int bio_max_pages = nr_buffers > BIO_MAX_PAGES ? BIO_MAX_PAGES
+						       : nr_buffers;
+
+	/* Setup the request */
+	req->read_end = read_end;
+	req->offset = req->index - read_start;
+	req->nr_buffers = nr_buffers;
+	if (actor_getblks(req, block) < 0)
+		goto getblk_failed;
+
+	/* Create and submit the BIOs */
+	for (b = 0; b < nr_buffers; ++b, offset += blksz) {
+		bh = req->bh[b];
+		if (!bh || !trylock_buffer(bh))
+			continue;
+		if (buffer_uptodate(bh)) {
+			unlock_buffer(bh);
+			continue;
+		}
+		offset %= PAGE_SIZE;
+
+		/* Append the buffer to the current BIO if it is contiguous */
+		if (bio && bio_req && prev_block + 1 == b) {
+			if (bio_add_page(bio, bh->b_page, blksz, offset)) {
+				bio_req->nr_buffers += 1;
+				prev_block = b;
+				continue;
+			}
+		}
+
+		/* Otherwise, submit the current BIO and create a new one */
+		if (bio)
+			submit_bio(READ, bio);
+		bio_req = kcalloc(1, sizeof(struct squashfs_bio_request),
+				  GFP_NOIO);
+		if (!bio_req)
+			goto req_alloc_failed;
+		bio_req->bh = &req->bh[b];
+		bio = bio_alloc(GFP_NOIO, bio_max_pages);
+		if (!bio)
+			goto bio_alloc_failed;
+		bio->bi_bdev = req->sb->s_bdev;
+		bio->bi_iter.bi_sector = (block + b)
+				       << (msblk->devblksize_log2 - 9);
+		bio->bi_private = bio_req;
+		bio->bi_end_io = squashfs_bio_end_io;
+
+		bio_add_page(bio, bh->b_page, blksz, offset);
+		bio_req->nr_buffers += 1;
+		prev_block = b;
+	}
+	if (bio)
+		submit_bio(READ, bio);
+
+	if (req->synchronous)
+		squashfs_process_blocks(req);
+	else {
+		INIT_WORK(&req->offload, read_wq_handler);
+		schedule_work(&req->offload);
+	}
+	return 0;
+
+bio_alloc_failed:
+	kfree(bio_req);
+req_alloc_failed:
+	unlock_buffer(bh);
+	while (--nr_buffers >= b)
+		if (req->bh[nr_buffers])
+			put_bh(req->bh[nr_buffers]);
+	while (--b >= 0)
+		if (req->bh[b])
+			wait_on_buffer(req->bh[b]);
+getblk_failed:
+	free_read_request(req, -ENOMEM);
+	return -ENOMEM;
+}
+
+static int read_metadata_block(struct squashfs_read_request *req,
+			       u64 *next_index)
+{
+	int ret, error, bytes_read = 0, bytes_uncompressed = 0;
+	struct squashfs_sb_info *msblk = req->sb->s_fs_info;
+
+	if (req->index + 2 > msblk->bytes_used) {
+		free_read_request(req, -EINVAL);
+		return -EINVAL;
+	}
+	req->length = 2;
+
+	/* Do not read beyond the end of the device */
+	if (req->index + req->length > msblk->bytes_used)
+		req->length = msblk->bytes_used - req->index;
+	req->data_processing = SQUASHFS_METADATA;
+
+	/*
+	 * Reading metadata is always synchronous because we don't know the
+	 * length in advance and the function is expected to update
+	 * 'next_index' and return the length.
+	 */
+	req->synchronous = true;
+	req->res = &error;
+	req->bytes_read = &bytes_read;
+	req->bytes_uncompressed = &bytes_uncompressed;
+
+	TRACE("Metadata block @ 0x%llx, %scompressed size %d, src size %d\n",
+	      req->index, req->compressed ? "" : "un", bytes_read,
+	      req->output->length);
+
+	ret = squashfs_bio_submit(req);
+	if (ret)
+		return ret;
+	if (error)
+		return error;
+	if (next_index)
+		*next_index += 2 + bytes_read;
+	return bytes_uncompressed;
+}
+
+static int read_data_block(struct squashfs_read_request *req, int length,
+			   u64 *next_index, bool synchronous)
+{
+	int ret, error = 0, bytes_uncompressed = 0, bytes_read = 0;
+
+	req->compressed = SQUASHFS_COMPRESSED_BLOCK(length);
+	req->length = length = SQUASHFS_COMPRESSED_SIZE_BLOCK(length);
+	req->data_processing = req->compressed ? SQUASHFS_DECOMPRESS
+					       : SQUASHFS_COPY;
+
+	req->synchronous = synchronous;
+	if (synchronous) {
+		req->res = &error;
+		req->bytes_read = &bytes_read;
+		req->bytes_uncompressed = &bytes_uncompressed;
+	}
+
+	TRACE("Data block @ 0x%llx, %scompressed size %d, src size %d\n",
+	      req->index, req->compressed ? "" : "un", req->length,
+	      req->output->length);
+
+	ret = squashfs_bio_submit(req);
+	if (ret)
+		return ret;
+	if (synchronous)
+		ret = error ? error : bytes_uncompressed;
+	if (next_index)
+		*next_index += length;
+	return ret;
+}
 
 /*
  * Read and decompress a metadata block or datablock.  Length is non-zero
@@ -87,128 +426,50 @@
  * generated a larger block - this does occasionally happen with compression
  * algorithms).
  */
-int squashfs_read_data(struct super_block *sb, u64 index, int length,
-		u64 *next_index, struct squashfs_page_actor *output)
+static int __squashfs_read_data(struct super_block *sb, u64 index, int length,
+	u64 *next_index, struct squashfs_page_actor *output, bool sync)
 {
-	struct squashfs_sb_info *msblk = sb->s_fs_info;
-	struct buffer_head **bh;
-	int offset = index & ((1 << msblk->devblksize_log2) - 1);
-	u64 cur_index = index >> msblk->devblksize_log2;
-	int bytes, compressed, b = 0, k = 0, avail, i;
+	struct squashfs_read_request *req;
 
-	bh = kcalloc(((output->length + msblk->devblksize - 1)
-		>> msblk->devblksize_log2) + 1, sizeof(*bh), GFP_KERNEL);
-	if (bh == NULL)
+	req = kcalloc(1, sizeof(struct squashfs_read_request), GFP_KERNEL);
+	if (!req) {
+		if (!sync)
+			squashfs_page_actor_free(output, -ENOMEM);
 		return -ENOMEM;
-
-	if (length) {
-		/*
-		 * Datablock.
-		 */
-		bytes = -offset;
-		compressed = SQUASHFS_COMPRESSED_BLOCK(length);
-		length = SQUASHFS_COMPRESSED_SIZE_BLOCK(length);
-		if (next_index)
-			*next_index = index + length;
-
-		TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n",
-			index, compressed ? "" : "un", length, output->length);
-
-		if (length < 0 || length > output->length ||
-				(index + length) > msblk->bytes_used)
-			goto read_failure;
-
-		for (b = 0; bytes < length; b++, cur_index++) {
-			bh[b] = sb_getblk(sb, cur_index);
-			if (bh[b] == NULL)
-				goto block_release;
-			bytes += msblk->devblksize;
-		}
-		ll_rw_block(READ, b, bh);
-	} else {
-		/*
-		 * Metadata block.
-		 */
-		if ((index + 2) > msblk->bytes_used)
-			goto read_failure;
-
-		bh[0] = get_block_length(sb, &cur_index, &offset, &length);
-		if (bh[0] == NULL)
-			goto read_failure;
-		b = 1;
-
-		bytes = msblk->devblksize - offset;
-		compressed = SQUASHFS_COMPRESSED(length);
-		length = SQUASHFS_COMPRESSED_SIZE(length);
-		if (next_index)
-			*next_index = index + length + 2;
-
-		TRACE("Block @ 0x%llx, %scompressed size %d\n", index,
-				compressed ? "" : "un", length);
-
-		if (length < 0 || length > output->length ||
-					(index + length) > msblk->bytes_used)
-			goto block_release;
-
-		for (; bytes < length; b++) {
-			bh[b] = sb_getblk(sb, ++cur_index);
-			if (bh[b] == NULL)
-				goto block_release;
-			bytes += msblk->devblksize;
-		}
-		ll_rw_block(READ, b - 1, bh + 1);
 	}
 
-	for (i = 0; i < b; i++) {
-		wait_on_buffer(bh[i]);
-		if (!buffer_uptodate(bh[i]))
-			goto block_release;
+	req->sb = sb;
+	req->index = index;
+	req->output = output;
+
+	if (next_index)
+		*next_index = index;
+
+	if (length)
+		length = read_data_block(req, length, next_index, sync);
+	else
+		length = read_metadata_block(req, next_index);
+
+	if (length < 0) {
+		ERROR("squashfs_read_data failed to read block 0x%llx\n",
+		      (unsigned long long)index);
+		return -EIO;
 	}
 
-	if (compressed) {
-		length = squashfs_decompress(msblk, bh, b, offset, length,
-			output);
-		if (length < 0)
-			goto read_failure;
-	} else {
-		/*
-		 * Block is uncompressed.
-		 */
-		int in, pg_offset = 0;
-		void *data = squashfs_first_page(output);
-
-		for (bytes = length; k < b; k++) {
-			in = min(bytes, msblk->devblksize - offset);
-			bytes -= in;
-			while (in) {
-				if (pg_offset == PAGE_CACHE_SIZE) {
-					data = squashfs_next_page(output);
-					pg_offset = 0;
-				}
-				avail = min_t(int, in, PAGE_CACHE_SIZE -
-						pg_offset);
-				memcpy(data + pg_offset, bh[k]->b_data + offset,
-						avail);
-				in -= avail;
-				pg_offset += avail;
-				offset += avail;
-			}
-			offset = 0;
-			put_bh(bh[k]);
-		}
-		squashfs_finish_page(output);
-	}
-
-	kfree(bh);
 	return length;
+}
 
-block_release:
-	for (; k < b; k++)
-		put_bh(bh[k]);
+int squashfs_read_data(struct super_block *sb, u64 index, int length,
+	u64 *next_index, struct squashfs_page_actor *output)
+{
+	return __squashfs_read_data(sb, index, length, next_index, output,
+				    true);
+}
 
-read_failure:
-	ERROR("squashfs_read_data failed to read block 0x%llx\n",
-					(unsigned long long) index);
-	kfree(bh);
-	return -EIO;
+int squashfs_read_data_async(struct super_block *sb, u64 index, int length,
+	u64 *next_index, struct squashfs_page_actor *output)
+{
+
+	return __squashfs_read_data(sb, index, length, next_index, output,
+				    false);
 }
diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
index 1cb70a0..6785d08 100644
--- a/fs/squashfs/cache.c
+++ b/fs/squashfs/cache.c
@@ -209,17 +209,14 @@
  */
 void squashfs_cache_delete(struct squashfs_cache *cache)
 {
-	int i, j;
+	int i;
 
 	if (cache == NULL)
 		return;
 
 	for (i = 0; i < cache->entries; i++) {
-		if (cache->entry[i].data) {
-			for (j = 0; j < cache->pages; j++)
-				kfree(cache->entry[i].data[j]);
-			kfree(cache->entry[i].data);
-		}
+		if (cache->entry[i].page)
+			free_page_array(cache->entry[i].page, cache->pages);
 		kfree(cache->entry[i].actor);
 	}
 
@@ -236,7 +233,7 @@
 struct squashfs_cache *squashfs_cache_init(char *name, int entries,
 	int block_size)
 {
-	int i, j;
+	int i;
 	struct squashfs_cache *cache = kzalloc(sizeof(*cache), GFP_KERNEL);
 
 	if (cache == NULL) {
@@ -268,22 +265,13 @@
 		init_waitqueue_head(&cache->entry[i].wait_queue);
 		entry->cache = cache;
 		entry->block = SQUASHFS_INVALID_BLK;
-		entry->data = kcalloc(cache->pages, sizeof(void *), GFP_KERNEL);
-		if (entry->data == NULL) {
+		entry->page = alloc_page_array(cache->pages, GFP_KERNEL);
+		if (!entry->page) {
 			ERROR("Failed to allocate %s cache entry\n", name);
 			goto cleanup;
 		}
-
-		for (j = 0; j < cache->pages; j++) {
-			entry->data[j] = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
-			if (entry->data[j] == NULL) {
-				ERROR("Failed to allocate %s buffer\n", name);
-				goto cleanup;
-			}
-		}
-
-		entry->actor = squashfs_page_actor_init(entry->data,
-						cache->pages, 0);
+		entry->actor = squashfs_page_actor_init(entry->page,
+			cache->pages, 0, NULL);
 		if (entry->actor == NULL) {
 			ERROR("Failed to allocate %s cache entry\n", name);
 			goto cleanup;
@@ -314,18 +302,20 @@
 		return min(length, entry->length - offset);
 
 	while (offset < entry->length) {
-		void *buff = entry->data[offset / PAGE_CACHE_SIZE]
-				+ (offset % PAGE_CACHE_SIZE);
+		void *buff = kmap_atomic(entry->page[offset / PAGE_CACHE_SIZE])
+			     + (offset % PAGE_CACHE_SIZE);
 		int bytes = min_t(int, entry->length - offset,
 				PAGE_CACHE_SIZE - (offset % PAGE_CACHE_SIZE));
 
 		if (bytes >= remaining) {
 			memcpy(buffer, buff, remaining);
+			kunmap_atomic(buff);
 			remaining = 0;
 			break;
 		}
 
 		memcpy(buffer, buff, bytes);
+		kunmap_atomic(buff);
 		buffer += bytes;
 		remaining -= bytes;
 		offset += bytes;
@@ -416,43 +406,38 @@
 void *squashfs_read_table(struct super_block *sb, u64 block, int length)
 {
 	int pages = (length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	int i, res;
-	void *table, *buffer, **data;
+	struct page **page;
+	void *buff;
+	int res;
 	struct squashfs_page_actor *actor;
 
-	table = buffer = kmalloc(length, GFP_KERNEL);
-	if (table == NULL)
+	page = alloc_page_array(pages, GFP_KERNEL);
+	if (!page)
 		return ERR_PTR(-ENOMEM);
 
-	data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
-	if (data == NULL) {
+	actor = squashfs_page_actor_init(page, pages, length, NULL);
+	if (actor == NULL) {
 		res = -ENOMEM;
 		goto failed;
 	}
 
-	actor = squashfs_page_actor_init(data, pages, length);
-	if (actor == NULL) {
-		res = -ENOMEM;
-		goto failed2;
-	}
-
-	for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE)
-		data[i] = buffer;
-
 	res = squashfs_read_data(sb, block, length |
 		SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, actor);
 
-	kfree(data);
-	kfree(actor);
-
 	if (res < 0)
-		goto failed;
+		goto failed2;
 
-	return table;
+	buff = kmalloc(length, GFP_KERNEL);
+	if (!buff)
+		goto failed2;
+	squashfs_actor_to_buf(actor, buff, length);
+	squashfs_page_actor_free(actor, 0);
+	free_page_array(page, pages);
+	return buff;
 
 failed2:
-	kfree(data);
+	squashfs_page_actor_free(actor, 0);
 failed:
-	kfree(table);
+	free_page_array(page, pages);
 	return ERR_PTR(res);
 }
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
index e9034bf..7de35bf 100644
--- a/fs/squashfs/decompressor.c
+++ b/fs/squashfs/decompressor.c
@@ -24,7 +24,8 @@
 #include <linux/types.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/buffer_head.h>
+#include <linux/highmem.h>
+#include <linux/fs.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
@@ -94,40 +95,44 @@
 static void *get_comp_opts(struct super_block *sb, unsigned short flags)
 {
 	struct squashfs_sb_info *msblk = sb->s_fs_info;
-	void *buffer = NULL, *comp_opts;
+	void *comp_opts, *buffer = NULL;
+	struct page *page;
 	struct squashfs_page_actor *actor = NULL;
 	int length = 0;
 
+	if (!SQUASHFS_COMP_OPTS(flags))
+		return squashfs_comp_opts(msblk, buffer, length);
+
 	/*
 	 * Read decompressor specific options from file system if present
 	 */
-	if (SQUASHFS_COMP_OPTS(flags)) {
-		buffer = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
-		if (buffer == NULL) {
-			comp_opts = ERR_PTR(-ENOMEM);
-			goto out;
-		}
 
-		actor = squashfs_page_actor_init(&buffer, 1, 0);
-		if (actor == NULL) {
-			comp_opts = ERR_PTR(-ENOMEM);
-			goto out;
-		}
+	page = alloc_page(GFP_KERNEL);
+	if (!page)
+		return ERR_PTR(-ENOMEM);
 
-		length = squashfs_read_data(sb,
-			sizeof(struct squashfs_super_block), 0, NULL, actor);
-
-		if (length < 0) {
-			comp_opts = ERR_PTR(length);
-			goto out;
-		}
+	actor = squashfs_page_actor_init(&page, 1, 0, NULL);
+	if (actor == NULL) {
+		comp_opts = ERR_PTR(-ENOMEM);
+		goto actor_error;
 	}
 
-	comp_opts = squashfs_comp_opts(msblk, buffer, length);
+	length = squashfs_read_data(sb,
+		sizeof(struct squashfs_super_block), 0, NULL, actor);
 
-out:
-	kfree(actor);
-	kfree(buffer);
+	if (length < 0) {
+		comp_opts = ERR_PTR(length);
+		goto read_error;
+	}
+
+	buffer = kmap_atomic(page);
+	comp_opts = squashfs_comp_opts(msblk, buffer, length);
+	kunmap_atomic(buffer);
+
+read_error:
+	squashfs_page_actor_free(actor, 0);
+actor_error:
+	__free_page(page);
 	return comp_opts;
 }
 
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
index e5c9689..6f5ef8d 100644
--- a/fs/squashfs/file.c
+++ b/fs/squashfs/file.c
@@ -47,12 +47,16 @@
 #include <linux/string.h>
 #include <linux/pagemap.h>
 #include <linux/mutex.h>
+#include <linux/mm_inline.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
 #include "squashfs_fs_i.h"
 #include "squashfs.h"
 
+// Backported from 4.5
+#define lru_to_page(head) (list_entry((head)->prev, struct page, lru))
+
 /*
  * Locate cache slot in range [offset, index] for specified inode.  If
  * there's more than one return the slot closest to index.
@@ -438,6 +442,21 @@
 	return res;
 }
 
+static int squashfs_readpages_fragment(struct page *page,
+	struct list_head *readahead_pages, struct address_space *mapping)
+{
+	if (!page) {
+		page = lru_to_page(readahead_pages);
+		list_del(&page->lru);
+		if (add_to_page_cache_lru(page, mapping, page->index,
+			mapping_gfp_constraint(mapping, GFP_KERNEL))) {
+			put_page(page);
+			return 0;
+		}
+	}
+	return squashfs_readpage_fragment(page);
+}
+
 static int squashfs_readpage_sparse(struct page *page, int index, int file_end)
 {
 	struct inode *inode = page->mapping->host;
@@ -450,54 +469,105 @@
 	return 0;
 }
 
-static int squashfs_readpage(struct file *file, struct page *page)
+static int squashfs_readpages_sparse(struct page *page,
+	struct list_head *readahead_pages, int index, int file_end,
+	struct address_space *mapping)
 {
-	struct inode *inode = page->mapping->host;
+	if (!page) {
+		page = lru_to_page(readahead_pages);
+		list_del(&page->lru);
+		if (add_to_page_cache_lru(page, mapping, page->index,
+			mapping_gfp_constraint(mapping, GFP_KERNEL))) {
+			put_page(page);
+			return 0;
+		}
+	}
+	return squashfs_readpage_sparse(page, index, file_end);
+}
+
+static int __squashfs_readpages(struct file *file, struct page *page,
+	struct list_head *readahead_pages, unsigned int nr_pages,
+	struct address_space *mapping)
+{
+	struct inode *inode = mapping->host;
 	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
-	int index = page->index >> (msblk->block_log - PAGE_CACHE_SHIFT);
 	int file_end = i_size_read(inode) >> msblk->block_log;
 	int res;
-	void *pageaddr;
+
+	do {
+		struct page *cur_page = page ? page
+					     : lru_to_page(readahead_pages);
+		int page_index = cur_page->index;
+		int index = page_index >> (msblk->block_log - PAGE_CACHE_SHIFT);
+
+		if (page_index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+						PAGE_CACHE_SHIFT))
+			return 1;
+
+		if (index < file_end || squashfs_i(inode)->fragment_block ==
+						SQUASHFS_INVALID_BLK) {
+			u64 block = 0;
+			int bsize = read_blocklist(inode, index, &block);
+
+			if (bsize < 0)
+				return -1;
+
+			if (bsize == 0) {
+				res = squashfs_readpages_sparse(page,
+					readahead_pages, index, file_end,
+					mapping);
+			} else {
+				res = squashfs_readpages_block(page,
+					readahead_pages, &nr_pages, mapping,
+					page_index, block, bsize);
+			}
+		} else {
+			res = squashfs_readpages_fragment(page,
+				readahead_pages, mapping);
+		}
+		if (res)
+			return 0;
+		page = NULL;
+	} while (readahead_pages && !list_empty(readahead_pages));
+
+	return 0;
+}
+
+static int squashfs_readpage(struct file *file, struct page *page)
+{
+	int ret;
 
 	TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
-				page->index, squashfs_i(inode)->start);
+	      page->index, squashfs_i(page->mapping->host)->start);
 
-	if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
-					PAGE_CACHE_SHIFT))
-		goto out;
+	get_page(page);
 
-	if (index < file_end || squashfs_i(inode)->fragment_block ==
-					SQUASHFS_INVALID_BLK) {
-		u64 block = 0;
-		int bsize = read_blocklist(inode, index, &block);
-		if (bsize < 0)
-			goto error_out;
-
-		if (bsize == 0)
-			res = squashfs_readpage_sparse(page, index, file_end);
+	ret = __squashfs_readpages(file, page, NULL, 1, page->mapping);
+	if (ret) {
+		flush_dcache_page(page);
+		if (ret < 0)
+			SetPageError(page);
 		else
-			res = squashfs_readpage_block(page, block, bsize);
-	} else
-		res = squashfs_readpage_fragment(page);
+			SetPageUptodate(page);
+		zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+		unlock_page(page);
+		put_page(page);
+	}
 
-	if (!res)
-		return 0;
+	return 0;
+}
 
-error_out:
-	SetPageError(page);
-out:
-	pageaddr = kmap_atomic(page);
-	memset(pageaddr, 0, PAGE_CACHE_SIZE);
-	kunmap_atomic(pageaddr);
-	flush_dcache_page(page);
-	if (!PageError(page))
-		SetPageUptodate(page);
-	unlock_page(page);
-
+static int squashfs_readpages(struct file *file, struct address_space *mapping,
+			      struct list_head *pages, unsigned int nr_pages)
+{
+	TRACE("Entered squashfs_readpages, %u pages, first page index %lx\n",
+		nr_pages, lru_to_page(pages)->index);
+	__squashfs_readpages(file, NULL, pages, nr_pages, mapping);
 	return 0;
 }
 
 
 const struct address_space_operations squashfs_aops = {
-	.readpage = squashfs_readpage
+	.readpage = squashfs_readpage,
+	.readpages = squashfs_readpages,
 };
diff --git a/fs/squashfs/file_cache.c b/fs/squashfs/file_cache.c
deleted file mode 100644
index f2310d2..0000000
--- a/fs/squashfs/file_cache.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2013
- * Phillip Lougher <phillip@squashfs.org.uk>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#include <linux/fs.h>
-#include <linux/vfs.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/pagemap.h>
-#include <linux/mutex.h>
-
-#include "squashfs_fs.h"
-#include "squashfs_fs_sb.h"
-#include "squashfs_fs_i.h"
-#include "squashfs.h"
-
-/* Read separately compressed datablock and memcopy into page cache */
-int squashfs_readpage_block(struct page *page, u64 block, int bsize)
-{
-	struct inode *i = page->mapping->host;
-	struct squashfs_cache_entry *buffer = squashfs_get_datablock(i->i_sb,
-		block, bsize);
-	int res = buffer->error;
-
-	if (res)
-		ERROR("Unable to read page, block %llx, size %x\n", block,
-			bsize);
-	else
-		squashfs_copy_cache(page, buffer, buffer->length, 0);
-
-	squashfs_cache_put(buffer);
-	return res;
-}
diff --git a/fs/squashfs/file_direct.c b/fs/squashfs/file_direct.c
index 43e7a7e..c97af4c 100644
--- a/fs/squashfs/file_direct.c
+++ b/fs/squashfs/file_direct.c
@@ -13,6 +13,7 @@
 #include <linux/string.h>
 #include <linux/pagemap.h>
 #include <linux/mutex.h>
+#include <linux/mm_inline.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
@@ -20,157 +21,139 @@
 #include "squashfs.h"
 #include "page_actor.h"
 
-static int squashfs_read_cache(struct page *target_page, u64 block, int bsize,
-	int pages, struct page **page);
+// Backported from 4.5
+#define lru_to_page(head) (list_entry((head)->prev, struct page, lru))
 
-/* Read separately compressed datablock directly into page cache */
-int squashfs_readpage_block(struct page *target_page, u64 block, int bsize)
-
+static void release_actor_pages(struct page **page, int pages, int error)
 {
-	struct inode *inode = target_page->mapping->host;
-	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+	int i;
 
-	int file_end = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
-	int mask = (1 << (msblk->block_log - PAGE_CACHE_SHIFT)) - 1;
-	int start_index = target_page->index & ~mask;
-	int end_index = start_index | mask;
-	int i, n, pages, missing_pages, bytes, res = -ENOMEM;
+	for (i = 0; i < pages; i++) {
+		if (!page[i])
+			continue;
+		flush_dcache_page(page[i]);
+		if (!error)
+			SetPageUptodate(page[i]);
+		else {
+			SetPageError(page[i]);
+			zero_user_segment(page[i], 0, PAGE_CACHE_SIZE);
+		}
+		unlock_page(page[i]);
+		put_page(page[i]);
+	}
+	kfree(page);
+}
+
+/*
+ * Create a "page actor" which will kmap and kunmap the
+ * page cache pages appropriately within the decompressor
+ */
+static struct squashfs_page_actor *actor_from_page_cache(
+	unsigned int actor_pages, struct page *target_page,
+	struct list_head *rpages, unsigned int *nr_pages, int start_index,
+	struct address_space *mapping)
+{
 	struct page **page;
 	struct squashfs_page_actor *actor;
-	void *pageaddr;
+	int i, n;
+	gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL);
 
-	if (end_index > file_end)
-		end_index = file_end;
+	page = kmalloc_array(actor_pages, sizeof(void *), GFP_KERNEL);
+	if (!page)
+		return NULL;
 
-	pages = end_index - start_index + 1;
+	for (i = 0, n = start_index; i < actor_pages; i++, n++) {
+		if (target_page == NULL && rpages && !list_empty(rpages)) {
+			struct page *cur_page = lru_to_page(rpages);
 
-	page = kmalloc_array(pages, sizeof(void *), GFP_KERNEL);
-	if (page == NULL)
-		return res;
+			if (cur_page->index < start_index + actor_pages) {
+				list_del(&cur_page->lru);
+				--(*nr_pages);
+				if (add_to_page_cache_lru(cur_page, mapping,
+							  cur_page->index, gfp))
+					put_page(cur_page);
+				else
+					target_page = cur_page;
+			} else
+				rpages = NULL;
+		}
 
-	/*
-	 * Create a "page actor" which will kmap and kunmap the
-	 * page cache pages appropriately within the decompressor
-	 */
-	actor = squashfs_page_actor_init_special(page, pages, 0);
-	if (actor == NULL)
-		goto out;
-
-	/* Try to grab all the pages covered by the Squashfs block */
-	for (missing_pages = 0, i = 0, n = start_index; i < pages; i++, n++) {
-		page[i] = (n == target_page->index) ? target_page :
-			grab_cache_page_nowait(target_page->mapping, n);
-
-		if (page[i] == NULL) {
-			missing_pages++;
-			continue;
+		if (target_page && target_page->index == n) {
+			page[i] = target_page;
+			target_page = NULL;
+		} else {
+			page[i] = grab_cache_page_nowait(mapping, n);
+			if (page[i] == NULL)
+				continue;
 		}
 
 		if (PageUptodate(page[i])) {
 			unlock_page(page[i]);
-			page_cache_release(page[i]);
+			put_page(page[i]);
 			page[i] = NULL;
-			missing_pages++;
 		}
 	}
 
-	if (missing_pages) {
-		/*
-		 * Couldn't get one or more pages, this page has either
-		 * been VM reclaimed, but others are still in the page cache
-		 * and uptodate, or we're racing with another thread in
-		 * squashfs_readpage also trying to grab them.  Fall back to
-		 * using an intermediate buffer.
-		 */
-		res = squashfs_read_cache(target_page, block, bsize, pages,
-								page);
-		if (res < 0)
-			goto mark_errored;
-
-		goto out;
+	actor = squashfs_page_actor_init(page, actor_pages, 0,
+			release_actor_pages);
+	if (!actor) {
+		release_actor_pages(page, actor_pages, -ENOMEM);
+		kfree(page);
+		return NULL;
 	}
-
-	/* Decompress directly into the page cache buffers */
-	res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
-	if (res < 0)
-		goto mark_errored;
-
-	/* Last page may have trailing bytes not filled */
-	bytes = res % PAGE_CACHE_SIZE;
-	if (bytes) {
-		pageaddr = kmap_atomic(page[pages - 1]);
-		memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
-		kunmap_atomic(pageaddr);
-	}
-
-	/* Mark pages as uptodate, unlock and release */
-	for (i = 0; i < pages; i++) {
-		flush_dcache_page(page[i]);
-		SetPageUptodate(page[i]);
-		unlock_page(page[i]);
-		if (page[i] != target_page)
-			page_cache_release(page[i]);
-	}
-
-	kfree(actor);
-	kfree(page);
-
-	return 0;
-
-mark_errored:
-	/* Decompression failed, mark pages as errored.  Target_page is
-	 * dealt with by the caller
-	 */
-	for (i = 0; i < pages; i++) {
-		if (page[i] == NULL || page[i] == target_page)
-			continue;
-		flush_dcache_page(page[i]);
-		SetPageError(page[i]);
-		unlock_page(page[i]);
-		page_cache_release(page[i]);
-	}
-
-out:
-	kfree(actor);
-	kfree(page);
-	return res;
+	return actor;
 }
 
+int squashfs_readpages_block(struct page *target_page,
+			     struct list_head *readahead_pages,
+			     unsigned int *nr_pages,
+			     struct address_space *mapping,
+			     int page_index, u64 block, int bsize)
 
-static int squashfs_read_cache(struct page *target_page, u64 block, int bsize,
-	int pages, struct page **page)
 {
-	struct inode *i = target_page->mapping->host;
-	struct squashfs_cache_entry *buffer = squashfs_get_datablock(i->i_sb,
-						 block, bsize);
-	int bytes = buffer->length, res = buffer->error, n, offset = 0;
-	void *pageaddr;
+	struct squashfs_page_actor *actor;
+	struct inode *inode = mapping->host;
+	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+	int start_index, end_index, file_end, actor_pages, res;
+	int mask = (1 << (msblk->block_log - PAGE_CACHE_SHIFT)) - 1;
 
-	if (res) {
-		ERROR("Unable to read page, block %llx, size %x\n", block,
-			bsize);
-		goto out;
+	/*
+	 * If readpage() is called on an uncompressed datablock, we can just
+	 * read the pages instead of fetching the whole block.
+	 * This greatly improves the performance when a process keep doing
+	 * random reads because we only fetch the necessary data.
+	 * The readahead algorithm will take care of doing speculative reads
+	 * if necessary.
+	 * We can't read more than 1 block even if readahead provides use more
+	 * pages because we don't know yet if the next block is compressed or
+	 * not.
+	 */
+	if (bsize && !SQUASHFS_COMPRESSED_BLOCK(bsize)) {
+		u64 block_end = block + msblk->block_size;
+
+		block += (page_index & mask) * PAGE_CACHE_SIZE;
+		actor_pages = (block_end - block) / PAGE_CACHE_SIZE;
+		if (*nr_pages < actor_pages)
+			actor_pages = *nr_pages;
+		start_index = page_index;
+		bsize = min_t(int, bsize, (PAGE_CACHE_SIZE * actor_pages)
+					  | SQUASHFS_COMPRESSED_BIT_BLOCK);
+	} else {
+		file_end = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
+		start_index = page_index & ~mask;
+		end_index = start_index | mask;
+		if (end_index > file_end)
+			end_index = file_end;
+		actor_pages = end_index - start_index + 1;
 	}
 
-	for (n = 0; n < pages && bytes > 0; n++,
-			bytes -= PAGE_CACHE_SIZE, offset += PAGE_CACHE_SIZE) {
-		int avail = min_t(int, bytes, PAGE_CACHE_SIZE);
+	actor = actor_from_page_cache(actor_pages, target_page,
+				      readahead_pages, nr_pages, start_index,
+				      mapping);
+	if (!actor)
+		return -ENOMEM;
 
-		if (page[n] == NULL)
-			continue;
-
-		pageaddr = kmap_atomic(page[n]);
-		squashfs_copy_data(pageaddr, buffer, offset, avail);
-		memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
-		kunmap_atomic(pageaddr);
-		flush_dcache_page(page[n]);
-		SetPageUptodate(page[n]);
-		unlock_page(page[n]);
-		if (page[n] != target_page)
-			page_cache_release(page[n]);
-	}
-
-out:
-	squashfs_cache_put(buffer);
-	return res;
+	res = squashfs_read_data_async(inode->i_sb, block, bsize, NULL,
+				       actor);
+	return res < 0 ? res : 0;
 }
diff --git a/fs/squashfs/lz4_wrapper.c b/fs/squashfs/lz4_wrapper.c
index c31e2bc..df4fa3c 100644
--- a/fs/squashfs/lz4_wrapper.c
+++ b/fs/squashfs/lz4_wrapper.c
@@ -94,39 +94,17 @@
 	struct buffer_head **bh, int b, int offset, int length,
 	struct squashfs_page_actor *output)
 {
-	struct squashfs_lz4 *stream = strm;
-	void *buff = stream->input, *data;
-	int avail, i, bytes = length, res;
+	int res;
 	size_t dest_len = output->length;
+	struct squashfs_lz4 *stream = strm;
 
-	for (i = 0; i < b; i++) {
-		avail = min(bytes, msblk->devblksize - offset);
-		memcpy(buff, bh[i]->b_data + offset, avail);
-		buff += avail;
-		bytes -= avail;
-		offset = 0;
-		put_bh(bh[i]);
-	}
-
+	squashfs_bh_to_buf(bh, b, stream->input, offset, length,
+		msblk->devblksize);
 	res = lz4_decompress_unknownoutputsize(stream->input, length,
 					stream->output, &dest_len);
 	if (res)
 		return -EIO;
-
-	bytes = dest_len;
-	data = squashfs_first_page(output);
-	buff = stream->output;
-	while (data) {
-		if (bytes <= PAGE_CACHE_SIZE) {
-			memcpy(data, buff, bytes);
-			break;
-		}
-		memcpy(data, buff, PAGE_CACHE_SIZE);
-		buff += PAGE_CACHE_SIZE;
-		bytes -= PAGE_CACHE_SIZE;
-		data = squashfs_next_page(output);
-	}
-	squashfs_finish_page(output);
+	squashfs_buf_to_actor(stream->output, output, dest_len);
 
 	return dest_len;
 }
diff --git a/fs/squashfs/lzo_wrapper.c b/fs/squashfs/lzo_wrapper.c
index 244b9fb..2c844d5 100644
--- a/fs/squashfs/lzo_wrapper.c
+++ b/fs/squashfs/lzo_wrapper.c
@@ -79,45 +79,19 @@
 	struct buffer_head **bh, int b, int offset, int length,
 	struct squashfs_page_actor *output)
 {
-	struct squashfs_lzo *stream = strm;
-	void *buff = stream->input, *data;
-	int avail, i, bytes = length, res;
+	int res;
 	size_t out_len = output->length;
+	struct squashfs_lzo *stream = strm;
 
-	for (i = 0; i < b; i++) {
-		avail = min(bytes, msblk->devblksize - offset);
-		memcpy(buff, bh[i]->b_data + offset, avail);
-		buff += avail;
-		bytes -= avail;
-		offset = 0;
-		put_bh(bh[i]);
-	}
-
+	squashfs_bh_to_buf(bh, b, stream->input, offset, length,
+		msblk->devblksize);
 	res = lzo1x_decompress_safe(stream->input, (size_t)length,
 					stream->output, &out_len);
 	if (res != LZO_E_OK)
-		goto failed;
+		return -EIO;
+	squashfs_buf_to_actor(stream->output, output, out_len);
 
-	res = bytes = (int)out_len;
-	data = squashfs_first_page(output);
-	buff = stream->output;
-	while (data) {
-		if (bytes <= PAGE_CACHE_SIZE) {
-			memcpy(data, buff, bytes);
-			break;
-		} else {
-			memcpy(data, buff, PAGE_CACHE_SIZE);
-			buff += PAGE_CACHE_SIZE;
-			bytes -= PAGE_CACHE_SIZE;
-			data = squashfs_next_page(output);
-		}
-	}
-	squashfs_finish_page(output);
-
-	return res;
-
-failed:
-	return -EIO;
+	return out_len;
 }
 
 const struct squashfs_decompressor squashfs_lzo_comp_ops = {
diff --git a/fs/squashfs/page_actor.c b/fs/squashfs/page_actor.c
index 5a1c11f..5386350 100644
--- a/fs/squashfs/page_actor.c
+++ b/fs/squashfs/page_actor.c
@@ -9,79 +9,11 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
+#include <linux/buffer_head.h>
 #include "page_actor.h"
 
-/*
- * This file contains implementations of page_actor for decompressing into
- * an intermediate buffer, and for decompressing directly into the
- * page cache.
- *
- * Calling code should avoid sleeping between calls to squashfs_first_page()
- * and squashfs_finish_page().
- */
-
-/* Implementation of page_actor for decompressing into intermediate buffer */
-static void *cache_first_page(struct squashfs_page_actor *actor)
-{
-	actor->next_page = 1;
-	return actor->buffer[0];
-}
-
-static void *cache_next_page(struct squashfs_page_actor *actor)
-{
-	if (actor->next_page == actor->pages)
-		return NULL;
-
-	return actor->buffer[actor->next_page++];
-}
-
-static void cache_finish_page(struct squashfs_page_actor *actor)
-{
-	/* empty */
-}
-
-struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
-	int pages, int length)
-{
-	struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
-
-	if (actor == NULL)
-		return NULL;
-
-	actor->length = length ? : pages * PAGE_CACHE_SIZE;
-	actor->buffer = buffer;
-	actor->pages = pages;
-	actor->next_page = 0;
-	actor->squashfs_first_page = cache_first_page;
-	actor->squashfs_next_page = cache_next_page;
-	actor->squashfs_finish_page = cache_finish_page;
-	return actor;
-}
-
-/* Implementation of page_actor for decompressing directly into page cache. */
-static void *direct_first_page(struct squashfs_page_actor *actor)
-{
-	actor->next_page = 1;
-	return actor->pageaddr = kmap_atomic(actor->page[0]);
-}
-
-static void *direct_next_page(struct squashfs_page_actor *actor)
-{
-	if (actor->pageaddr)
-		kunmap_atomic(actor->pageaddr);
-
-	return actor->pageaddr = actor->next_page == actor->pages ? NULL :
-		kmap_atomic(actor->page[actor->next_page++]);
-}
-
-static void direct_finish_page(struct squashfs_page_actor *actor)
-{
-	if (actor->pageaddr)
-		kunmap_atomic(actor->pageaddr);
-}
-
-struct squashfs_page_actor *squashfs_page_actor_init_special(struct page **page,
-	int pages, int length)
+struct squashfs_page_actor *squashfs_page_actor_init(struct page **page,
+	int pages, int length, void (*release_pages)(struct page **, int, int))
 {
 	struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
 
@@ -93,8 +25,129 @@
 	actor->pages = pages;
 	actor->next_page = 0;
 	actor->pageaddr = NULL;
-	actor->squashfs_first_page = direct_first_page;
-	actor->squashfs_next_page = direct_next_page;
-	actor->squashfs_finish_page = direct_finish_page;
+	actor->release_pages = release_pages;
 	return actor;
 }
+
+void squashfs_page_actor_free(struct squashfs_page_actor *actor, int error)
+{
+	if (!actor)
+		return;
+
+	if (actor->release_pages)
+		actor->release_pages(actor->page, actor->pages, error);
+	kfree(actor);
+}
+
+void squashfs_actor_to_buf(struct squashfs_page_actor *actor, void *buf,
+	int length)
+{
+	void *pageaddr;
+	int pos = 0, avail, i;
+
+	for (i = 0; i < actor->pages && pos < length; ++i) {
+		avail = min_t(int, length - pos, PAGE_CACHE_SIZE);
+		if (actor->page[i]) {
+			pageaddr = kmap_atomic(actor->page[i]);
+			memcpy(buf + pos, pageaddr, avail);
+			kunmap_atomic(pageaddr);
+		}
+		pos += avail;
+	}
+}
+
+void squashfs_buf_to_actor(void *buf, struct squashfs_page_actor *actor,
+	int length)
+{
+	void *pageaddr;
+	int pos = 0, avail, i;
+
+	for (i = 0; i < actor->pages && pos < length; ++i) {
+		avail = min_t(int, length - pos, PAGE_CACHE_SIZE);
+		if (actor->page[i]) {
+			pageaddr = kmap_atomic(actor->page[i]);
+			memcpy(pageaddr, buf + pos, avail);
+			kunmap_atomic(pageaddr);
+		}
+		pos += avail;
+	}
+}
+
+void squashfs_bh_to_actor(struct buffer_head **bh, int nr_buffers,
+	struct squashfs_page_actor *actor, int offset, int length, int blksz)
+{
+	void *kaddr = NULL;
+	int bytes = 0, pgoff = 0, b = 0, p = 0, avail, i;
+
+	while (bytes < length) {
+		if (actor->page[p]) {
+			kaddr = kmap_atomic(actor->page[p]);
+			while (pgoff < PAGE_CACHE_SIZE && bytes < length) {
+				avail = min_t(int, blksz - offset,
+						PAGE_CACHE_SIZE - pgoff);
+				memcpy(kaddr + pgoff, bh[b]->b_data + offset,
+				       avail);
+				pgoff += avail;
+				bytes += avail;
+				offset = (offset + avail) % blksz;
+				if (!offset) {
+					put_bh(bh[b]);
+					++b;
+				}
+			}
+			kunmap_atomic(kaddr);
+			pgoff = 0;
+		} else {
+			for (i = 0; i < PAGE_CACHE_SIZE / blksz; ++i) {
+				if (bh[b])
+					put_bh(bh[b]);
+				++b;
+			}
+			bytes += PAGE_CACHE_SIZE;
+		}
+		++p;
+	}
+}
+
+void squashfs_bh_to_buf(struct buffer_head **bh, int nr_buffers, void *buf,
+	int offset, int length, int blksz)
+{
+	int i, avail, bytes = 0;
+
+	for (i = 0; i < nr_buffers && bytes < length; ++i) {
+		avail = min_t(int, length - bytes, blksz - offset);
+		if (bh[i]) {
+			memcpy(buf + bytes, bh[i]->b_data + offset, avail);
+			put_bh(bh[i]);
+		}
+		bytes += avail;
+		offset = 0;
+	}
+}
+
+void free_page_array(struct page **page, int nr_pages)
+{
+	int i;
+
+	for (i = 0; i < nr_pages; ++i)
+		__free_page(page[i]);
+	kfree(page);
+}
+
+struct page **alloc_page_array(int nr_pages, int gfp_mask)
+{
+	int i;
+	struct page **page;
+
+	page = kcalloc(nr_pages, sizeof(struct page *), gfp_mask);
+	if (!page)
+		return NULL;
+	for (i = 0; i < nr_pages; ++i) {
+		page[i] = alloc_page(gfp_mask);
+		if (!page[i]) {
+			free_page_array(page, i);
+			return NULL;
+		}
+	}
+	return page;
+}
diff --git a/fs/squashfs/page_actor.h b/fs/squashfs/page_actor.h
index 26dd820..aa1ed79 100644
--- a/fs/squashfs/page_actor.h
+++ b/fs/squashfs/page_actor.h
@@ -5,77 +5,61 @@
  * Phillip Lougher <phillip@squashfs.org.uk>
  *
  * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * the COPYING file in the top-level squashfsory.
  */
 
-#ifndef CONFIG_SQUASHFS_FILE_DIRECT
 struct squashfs_page_actor {
-	void	**page;
+	struct page	**page;
+	void	*pageaddr;
 	int	pages;
 	int	length;
 	int	next_page;
+	void	(*release_pages)(struct page **, int, int);
 };
 
-static inline struct squashfs_page_actor *squashfs_page_actor_init(void **page,
-	int pages, int length)
-{
-	struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
+extern struct squashfs_page_actor *squashfs_page_actor_init(struct page **,
+	int, int, void (*)(struct page **, int, int));
+extern void squashfs_page_actor_free(struct squashfs_page_actor *, int);
 
-	if (actor == NULL)
-		return NULL;
+extern void squashfs_actor_to_buf(struct squashfs_page_actor *, void *, int);
+extern void squashfs_buf_to_actor(void *, struct squashfs_page_actor *, int);
+extern void squashfs_bh_to_actor(struct buffer_head **, int,
+	struct squashfs_page_actor *, int, int, int);
+extern void squashfs_bh_to_buf(struct buffer_head **, int, void *, int, int,
+	int);
 
-	actor->length = length ? : pages * PAGE_CACHE_SIZE;
-	actor->page = page;
-	actor->pages = pages;
-	actor->next_page = 0;
-	return actor;
-}
-
+/*
+ * Calling code should avoid sleeping between calls to squashfs_first_page()
+ * and squashfs_finish_page().
+ */
 static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
 {
 	actor->next_page = 1;
-	return actor->page[0];
+	return actor->pageaddr = actor->page[0] ? kmap_atomic(actor->page[0])
+						: NULL;
 }
 
 static inline void *squashfs_next_page(struct squashfs_page_actor *actor)
 {
-	return actor->next_page == actor->pages ? NULL :
-		actor->page[actor->next_page++];
+	if (!IS_ERR_OR_NULL(actor->pageaddr))
+		kunmap_atomic(actor->pageaddr);
+
+	if (actor->next_page == actor->pages)
+		return actor->pageaddr = ERR_PTR(-ENODATA);
+
+	actor->pageaddr = actor->page[actor->next_page] ?
+	    kmap_atomic(actor->page[actor->next_page]) : NULL;
+	++actor->next_page;
+	return actor->pageaddr;
 }
 
 static inline void squashfs_finish_page(struct squashfs_page_actor *actor)
 {
-	/* empty */
+	if (!IS_ERR_OR_NULL(actor->pageaddr))
+		kunmap_atomic(actor->pageaddr);
 }
-#else
-struct squashfs_page_actor {
-	union {
-		void		**buffer;
-		struct page	**page;
-	};
-	void	*pageaddr;
-	void    *(*squashfs_first_page)(struct squashfs_page_actor *);
-	void    *(*squashfs_next_page)(struct squashfs_page_actor *);
-	void    (*squashfs_finish_page)(struct squashfs_page_actor *);
-	int	pages;
-	int	length;
-	int	next_page;
-};
 
-extern struct squashfs_page_actor *squashfs_page_actor_init(void **, int, int);
-extern struct squashfs_page_actor *squashfs_page_actor_init_special(struct page
-							 **, int, int);
-static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
-{
-	return actor->squashfs_first_page(actor);
-}
-static inline void *squashfs_next_page(struct squashfs_page_actor *actor)
-{
-	return actor->squashfs_next_page(actor);
-}
-static inline void squashfs_finish_page(struct squashfs_page_actor *actor)
-{
-	actor->squashfs_finish_page(actor);
-}
-#endif
+extern struct page **alloc_page_array(int, int);
+extern void free_page_array(struct page **, int);
+
 #endif
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 887d6d2..6093579 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -28,8 +28,14 @@
 #define WARNING(s, args...)	pr_warn("SQUASHFS: "s, ## args)
 
 /* block.c */
+extern int squashfs_init_read_wq(void);
+extern void squashfs_destroy_read_wq(void);
 extern int squashfs_read_data(struct super_block *, u64, int, u64 *,
 				struct squashfs_page_actor *);
+extern int squashfs_read_data(struct super_block *, u64, int, u64 *,
+	struct squashfs_page_actor *);
+extern int squashfs_read_data_async(struct super_block *, u64, int, u64 *,
+	struct squashfs_page_actor *);
 
 /* cache.c */
 extern struct squashfs_cache *squashfs_cache_init(char *, int, int);
@@ -70,8 +76,9 @@
 void squashfs_copy_cache(struct page *, struct squashfs_cache_entry *, int,
 				int);
 
-/* file_xxx.c */
-extern int squashfs_readpage_block(struct page *, u64, int);
+/* file_direct.c */
+extern int squashfs_readpages_block(struct page *, struct list_head *,
+	unsigned int *, struct address_space *, int, u64, int);
 
 /* id.c */
 extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *);
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 1da565c..8a6995d 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -49,7 +49,7 @@
 	int			num_waiters;
 	wait_queue_head_t	wait_queue;
 	struct squashfs_cache	*cache;
-	void			**data;
+	struct page		**page;
 	struct squashfs_page_actor	*actor;
 };
 
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 5056bab..61cd0b3 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -444,9 +444,15 @@
 	if (err)
 		return err;
 
+	if (!squashfs_init_read_wq()) {
+		destroy_inodecache();
+		return -ENOMEM;
+        }
+
 	err = register_filesystem(&squashfs_fs_type);
 	if (err) {
 		destroy_inodecache();
+		squashfs_destroy_read_wq();
 		return err;
 	}
 
@@ -460,6 +466,7 @@
 {
 	unregister_filesystem(&squashfs_fs_type);
 	destroy_inodecache();
+	squashfs_destroy_read_wq();
 }
 
 
diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c
index c609624..14cd373 100644
--- a/fs/squashfs/xz_wrapper.c
+++ b/fs/squashfs/xz_wrapper.c
@@ -55,7 +55,7 @@
 	struct comp_opts *opts;
 	int err = 0, n;
 
-	opts = kmalloc(sizeof(*opts), GFP_KERNEL);
+	opts = kmalloc(sizeof(*opts), GFP_ATOMIC);
 	if (opts == NULL) {
 		err = -ENOMEM;
 		goto out2;
@@ -136,6 +136,7 @@
 	enum xz_ret xz_err;
 	int avail, total = 0, k = 0;
 	struct squashfs_xz *stream = strm;
+	void *buf = NULL;
 
 	xz_dec_reset(stream->state);
 	stream->buf.in_pos = 0;
@@ -156,12 +157,20 @@
 
 		if (stream->buf.out_pos == stream->buf.out_size) {
 			stream->buf.out = squashfs_next_page(output);
-			if (stream->buf.out != NULL) {
+			if (!IS_ERR(stream->buf.out)) {
 				stream->buf.out_pos = 0;
 				total += PAGE_CACHE_SIZE;
 			}
 		}
 
+		if (!stream->buf.out) {
+			if (!buf) {
+				buf = kmalloc(PAGE_CACHE_SIZE, GFP_ATOMIC);
+				if (!buf)
+					goto out;
+			}
+			stream->buf.out = buf;
+		}
 		xz_err = xz_dec_run(stream->state, &stream->buf);
 
 		if (stream->buf.in_pos == stream->buf.in_size && k < b)
@@ -173,11 +182,13 @@
 	if (xz_err != XZ_STREAM_END || k < b)
 		goto out;
 
+	kfree(buf);
 	return total + stream->buf.out_pos;
 
 out:
 	for (; k < b; k++)
 		put_bh(bh[k]);
+	kfree(buf);
 
 	return -EIO;
 }
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c
index 8727cab..09c892b 100644
--- a/fs/squashfs/zlib_wrapper.c
+++ b/fs/squashfs/zlib_wrapper.c
@@ -66,6 +66,7 @@
 	struct buffer_head **bh, int b, int offset, int length,
 	struct squashfs_page_actor *output)
 {
+	void *buf = NULL;
 	int zlib_err, zlib_init = 0, k = 0;
 	z_stream *stream = strm;
 
@@ -84,10 +85,19 @@
 
 		if (stream->avail_out == 0) {
 			stream->next_out = squashfs_next_page(output);
-			if (stream->next_out != NULL)
+			if (!IS_ERR(stream->next_out))
 				stream->avail_out = PAGE_CACHE_SIZE;
 		}
 
+		if (!stream->next_out) {
+			if (!buf) {
+				buf = kmalloc(PAGE_CACHE_SIZE, GFP_ATOMIC);
+				if (!buf)
+					goto out;
+			}
+			stream->next_out = buf;
+		}
+
 		if (!zlib_init) {
 			zlib_err = zlib_inflateInit(stream);
 			if (zlib_err != Z_OK) {
@@ -115,11 +125,13 @@
 	if (k < b)
 		goto out;
 
+	kfree(buf);
 	return stream->total_out;
 
 out:
 	for (; k < b; k++)
 		put_bh(bh[k]);
+	kfree(buf);
 
 	return -EIO;
 }
diff --git a/fs/stat.c b/fs/stat.c
index d4a61d8..004dd77 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -31,7 +31,7 @@
 	stat->atime = inode->i_atime;
 	stat->mtime = inode->i_mtime;
 	stat->ctime = inode->i_ctime;
-	stat->blksize = (1 << inode->i_blkbits);
+	stat->blksize = i_blocksize(inode);
 	stat->blocks = inode->i_blocks;
 }
 
@@ -454,6 +454,7 @@
 		inode->i_bytes -= 512;
 	}
 }
+EXPORT_SYMBOL(__inode_add_bytes);
 
 void inode_add_bytes(struct inode *inode, loff_t bytes)
 {
diff --git a/fs/super.c b/fs/super.c
index 8d99a7b..c96434e 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -703,7 +703,8 @@
 }
 
 /**
- *	do_remount_sb - asks filesystem to change mount options.
+ *	do_remount_sb2 - asks filesystem to change mount options.
+ *	@mnt:   mount we are looking at
  *	@sb:	superblock in question
  *	@flags:	numeric part of options
  *	@data:	the rest of options
@@ -711,7 +712,7 @@
  *
  *	Alters the mount options of a mounted file system.
  */
-int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+int do_remount_sb2(struct vfsmount *mnt, struct super_block *sb, int flags, void *data, int force)
 {
 	int retval;
 	int remount_ro;
@@ -753,7 +754,16 @@
 		}
 	}
 
-	if (sb->s_op->remount_fs) {
+	if (mnt && sb->s_op->remount_fs2) {
+		retval = sb->s_op->remount_fs2(mnt, sb, &flags, data);
+		if (retval) {
+			if (!force)
+				goto cancel_readonly;
+			/* If forced remount, go ahead despite any errors */
+			WARN(1, "forced remount of a %s fs returned %i\n",
+			     sb->s_type->name, retval);
+		}
+	} else if (sb->s_op->remount_fs) {
 		retval = sb->s_op->remount_fs(sb, &flags, data);
 		if (retval) {
 			if (!force)
@@ -785,6 +795,11 @@
 	return retval;
 }
 
+int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+{
+	return do_remount_sb2(NULL, sb, flags, data, force);
+}
+
 static void do_emergency_remount(struct work_struct *work)
 {
 	struct super_block *sb, *p = NULL;
@@ -1104,7 +1119,7 @@
 EXPORT_SYMBOL(mount_single);
 
 struct dentry *
-mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
+mount_fs(struct file_system_type *type, int flags, const char *name, struct vfsmount *mnt, void *data)
 {
 	struct dentry *root;
 	struct super_block *sb;
@@ -1121,7 +1136,10 @@
 			goto out_free_secdata;
 	}
 
-	root = type->mount(type, flags, name, data);
+	if (type->mount2)
+		root = type->mount2(mnt, type, flags, name, data);
+	else
+		root = type->mount(type, flags, name, data);
 	if (IS_ERR(root)) {
 		error = PTR_ERR(root);
 		goto out_free_secdata;
@@ -1326,8 +1344,8 @@
 		}
 	}
 	/*
-	 * This is just for debugging purposes so that fs can warn if it
-	 * sees write activity when frozen is set to SB_FREEZE_COMPLETE.
+	 * For debugging purposes so that fs can warn if it sees write activity
+	 * when frozen is set to SB_FREEZE_COMPLETE, and for thaw_super().
 	 */
 	sb->s_writers.frozen = SB_FREEZE_COMPLETE;
 	up_write(&sb->s_umount);
@@ -1346,7 +1364,7 @@
 	int error;
 
 	down_write(&sb->s_umount);
-	if (sb->s_writers.frozen == SB_UNFROZEN) {
+	if (sb->s_writers.frozen != SB_FREEZE_COMPLETE) {
 		up_write(&sb->s_umount);
 		return -EINVAL;
 	}
diff --git a/fs/sync.c b/fs/sync.c
index dd5d171..452179e 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -218,6 +218,7 @@
 	if (f.file) {
 		ret = vfs_fsync(f.file, datasync);
 		fdput(f);
+		inc_syscfs(current);
 	}
 	return ret;
 }
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index f35523d..39c75a8 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -108,16 +108,24 @@
 {
 	const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
 	struct kobject *kobj = of->kn->parent->priv;
-	size_t len;
+	ssize_t len;
 
 	/*
 	 * If buf != of->prealloc_buf, we don't know how
 	 * large it is, so cannot safely pass it to ->show
 	 */
-	if (pos || WARN_ON_ONCE(buf != of->prealloc_buf))
+	if (WARN_ON_ONCE(buf != of->prealloc_buf))
 		return 0;
 	len = ops->show(kobj, of->kn->priv, buf);
-	return min(count, len);
+	if (len < 0)
+		return len;
+	if (pos) {
+		if (len <= pos)
+			return 0;
+		len -= pos;
+		memmove(buf, buf + pos, len);
+	}
+	return min_t(ssize_t, count, len);
 }
 
 /* kernfs write callback for regular sysfs files */
diff --git a/fs/timerfd.c b/fs/timerfd.c
index 053818d..1327a02 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -40,6 +40,7 @@
 	short unsigned settime_flags;	/* to show in fdinfo */
 	struct rcu_head rcu;
 	struct list_head clist;
+	spinlock_t cancel_lock;
 	bool might_cancel;
 };
 
@@ -112,7 +113,7 @@
 	rcu_read_unlock();
 }
 
-static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+static void __timerfd_remove_cancel(struct timerfd_ctx *ctx)
 {
 	if (ctx->might_cancel) {
 		ctx->might_cancel = false;
@@ -122,6 +123,13 @@
 	}
 }
 
+static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+{
+	spin_lock(&ctx->cancel_lock);
+	__timerfd_remove_cancel(ctx);
+	spin_unlock(&ctx->cancel_lock);
+}
+
 static bool timerfd_canceled(struct timerfd_ctx *ctx)
 {
 	if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX)
@@ -132,6 +140,7 @@
 
 static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
 {
+	spin_lock(&ctx->cancel_lock);
 	if ((ctx->clockid == CLOCK_REALTIME ||
 	     ctx->clockid == CLOCK_REALTIME_ALARM) &&
 	    (flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
@@ -141,9 +150,10 @@
 			list_add_rcu(&ctx->clist, &cancel_list);
 			spin_unlock(&cancel_lock);
 		}
-	} else if (ctx->might_cancel) {
-		timerfd_remove_cancel(ctx);
+	} else {
+		__timerfd_remove_cancel(ctx);
 	}
+	spin_unlock(&ctx->cancel_lock);
 }
 
 static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
@@ -395,6 +405,7 @@
 		return -ENOMEM;
 
 	init_waitqueue_head(&ctx->wqh);
+	spin_lock_init(&ctx->cancel_lock);
 	ctx->clockid = clockid;
 
 	if (isalarm(ctx))
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index e49bd28..f5d5ee4 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -350,7 +350,7 @@
  */
 static int ubifs_readdir(struct file *file, struct dir_context *ctx)
 {
-	int err;
+	int err = 0;
 	struct qstr nm;
 	union ubifs_key key;
 	struct ubifs_dent_node *dent;
@@ -452,14 +452,20 @@
 	kfree(file->private_data);
 	file->private_data = NULL;
 
-	if (err != -ENOENT) {
+	if (err != -ENOENT)
 		ubifs_err(c, "cannot find next direntry, error %d", err);
-		return err;
-	}
+	else
+		/*
+		 * -ENOENT is a non-fatal error in this context, the TNC uses
+		 * it to indicate that the cursor moved past the current directory
+		 * and readdir() has to stop.
+		 */
+		err = 0;
+
 
 	/* 2 is a special value indicating that there are no more direntries */
 	ctx->pos = 2;
-	return 0;
+	return err;
 }
 
 /* Free saved readdir() state when the directory is closed */
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 0edc128..b895af7 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -52,6 +52,7 @@
 #include "ubifs.h"
 #include <linux/mount.h>
 #include <linux/slab.h>
+#include <linux/migrate.h>
 
 static int read_block(struct inode *inode, void *addr, unsigned int block,
 		      struct ubifs_data_node *dn)
@@ -1452,6 +1453,26 @@
 	return ret;
 }
 
+#ifdef CONFIG_MIGRATION
+static int ubifs_migrate_page(struct address_space *mapping,
+		struct page *newpage, struct page *page, enum migrate_mode mode)
+{
+	int rc;
+
+	rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
+	if (rc != MIGRATEPAGE_SUCCESS)
+		return rc;
+
+	if (PagePrivate(page)) {
+		ClearPagePrivate(page);
+		SetPagePrivate(newpage);
+	}
+
+	migrate_page_copy(newpage, page);
+	return MIGRATEPAGE_SUCCESS;
+}
+#endif
+
 static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
 {
 	/*
@@ -1591,6 +1612,9 @@
 	.write_end      = ubifs_write_end,
 	.invalidatepage = ubifs_invalidatepage,
 	.set_page_dirty = ubifs_set_page_dirty,
+#ifdef CONFIG_MIGRATION
+	.migratepage	= ubifs_migrate_page,
+#endif
 	.releasepage    = ubifs_releasepage,
 };
 
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index fa9a20c..fe5e8d4 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -34,6 +34,11 @@
 #include <linux/slab.h>
 #include "ubifs.h"
 
+static int try_read_node(const struct ubifs_info *c, void *buf, int type,
+			 int len, int lnum, int offs);
+static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,
+			      struct ubifs_zbranch *zbr, void *node);
+
 /*
  * Returned codes of 'matches_name()' and 'fallible_matches_name()' functions.
  * @NAME_LESS: name corresponding to the first argument is less than second
@@ -402,7 +407,19 @@
 		return 0;
 	}
 
-	err = ubifs_tnc_read_node(c, zbr, node);
+	if (c->replaying) {
+		err = fallible_read_node(c, &zbr->key, zbr, node);
+		/*
+		 * When the node was not found, return -ENOENT, 0 otherwise.
+		 * Negative return codes stay as-is.
+		 */
+		if (err == 0)
+			err = -ENOENT;
+		else if (err == 1)
+			err = 0;
+	} else {
+		err = ubifs_tnc_read_node(c, zbr, node);
+	}
 	if (err)
 		return err;
 
@@ -2766,7 +2783,11 @@
 	if (nm->name) {
 		if (err) {
 			/* Handle collisions */
-			err = resolve_collision(c, key, &znode, &n, nm);
+			if (c->replaying)
+				err = fallible_resolve_collision(c, key, &znode, &n,
+							 nm, 0);
+			else
+				err = resolve_collision(c, key, &znode, &n, nm);
 			dbg_tnc("rc returned %d, znode %p, n %d",
 				err, znode, n);
 			if (unlikely(err < 0))
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index b45345d..51157da 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -370,7 +370,7 @@
 
 	p = c->gap_lebs;
 	do {
-		ubifs_assert(p < c->gap_lebs + sizeof(int) * c->lst.idx_lebs);
+		ubifs_assert(p < c->gap_lebs + c->lst.idx_lebs);
 		written = layout_leb_in_gaps(c, p);
 		if (written < 0) {
 			err = written;
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index e8b01b7..b5bf23b 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -173,6 +173,7 @@
 	host_ui->xattr_cnt -= 1;
 	host_ui->xattr_size -= CALC_DENT_SIZE(nm->len);
 	host_ui->xattr_size -= CALC_XATTR_BYTES(size);
+	host_ui->xattr_names -= nm->len;
 	mutex_unlock(&host_ui->ui_mutex);
 out_free:
 	make_bad_inode(inode);
@@ -533,6 +534,7 @@
 	host_ui->xattr_cnt += 1;
 	host_ui->xattr_size += CALC_DENT_SIZE(nm->len);
 	host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
+	host_ui->xattr_names += nm->len;
 	mutex_unlock(&host_ui->ui_mutex);
 	ubifs_release_budget(c, &req);
 	make_bad_inode(inode);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 566df9b..7be3166 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1206,7 +1206,7 @@
 {
 	int err;
 	struct udf_inode_info *iinfo;
-	int bsize = 1 << inode->i_blkbits;
+	int bsize = i_blocksize(inode);
 
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 	      S_ISLNK(inode->i_mode)))
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index dc5fae6..637e17cb 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -81,7 +81,8 @@
 			ufs_error (sb, "ufs_free_fragments",
 				   "bit already cleared for fragment %u", i);
 	}
-	
+
+	inode_sub_bytes(inode, count << uspi->s_fshift);
 	fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
 	uspi->cs_total.cs_nffree += count;
 	fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
@@ -183,6 +184,7 @@
 			ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
 		}
 		ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
+		inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift);
 		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
 			ufs_clusteracct (sb, ucpi, blkno, 1);
 
@@ -494,6 +496,20 @@
 	return 0;
 }		
 
+static bool try_add_frags(struct inode *inode, unsigned frags)
+{
+	unsigned size = frags * i_blocksize(inode);
+	spin_lock(&inode->i_lock);
+	__inode_add_bytes(inode, size);
+	if (unlikely((u32)inode->i_blocks != inode->i_blocks)) {
+		__inode_sub_bytes(inode, size);
+		spin_unlock(&inode->i_lock);
+		return false;
+	}
+	spin_unlock(&inode->i_lock);
+	return true;
+}
+
 static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
 			     unsigned oldcount, unsigned newcount)
 {
@@ -530,6 +546,9 @@
 	for (i = oldcount; i < newcount; i++)
 		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
 			return 0;
+
+	if (!try_add_frags(inode, count))
+		return 0;
 	/*
 	 * Block can be extended
 	 */
@@ -647,6 +666,7 @@
 			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
 		i = uspi->s_fpb - count;
 
+		inode_sub_bytes(inode, i << uspi->s_fshift);
 		fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
 		uspi->cs_total.cs_nffree += i;
 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
@@ -657,6 +677,8 @@
 	result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
 	if (result == INVBLOCK)
 		return 0;
+	if (!try_add_frags(inode, count))
+		return 0;
 	for (i = 0; i < count; i++)
 		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
 	
@@ -716,6 +738,8 @@
 		return INVBLOCK;
 	ucpi->c_rotor = result;
 gotit:
+	if (!try_add_frags(inode, uspi->s_fpb))
+		return 0;
 	blkno = ufs_fragstoblks(result);
 	ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
 	if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index a064cf44..1f69bb9 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -235,7 +235,8 @@
 
 	p = ufs_get_direct_data_ptr(uspi, ufsi, block);
 	tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p),
-				new_size, err, locked_page);
+				new_size - (lastfrag & uspi->s_fpbmask), err,
+				locked_page);
 	return tmp != 0;
 }
 
@@ -284,7 +285,7 @@
 			goal += uspi->s_fpb;
 	}
 	tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment),
-				goal, uspi->s_fpb, err, locked_page);
+				goal, nfrags, err, locked_page);
 
 	if (!tmp) {
 		*err = -ENOSPC;
@@ -402,7 +403,9 @@
 
 	if (!create) {
 		phys64 = ufs_frag_map(inode, offsets, depth);
-		goto out;
+		if (phys64)
+			map_bh(bh_result, sb, phys64 + frag);
+		return 0;
 	}
 
         /* This code entered only while writing ....? */
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index f6390ee..10f3644 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -746,6 +746,23 @@
 	return;
 }
 
+static u64 ufs_max_bytes(struct super_block *sb)
+{
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+	int bits = uspi->s_apbshift;
+	u64 res;
+
+	if (bits > 21)
+		res = ~0ULL;
+	else
+		res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) +
+			(1LL << (3*bits));
+
+	if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift))
+		return MAX_LFS_FILESIZE;
+	return res << uspi->s_bshift;
+}
+
 static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct ufs_sb_info * sbi;
@@ -1212,6 +1229,7 @@
 			    "fast symlink size (%u)\n", uspi->s_maxsymlinklen);
 		uspi->s_maxsymlinklen = maxsymlen;
 	}
+	sb->s_maxbytes = ufs_max_bytes(sb);
 	sb->s_max_links = UFS_LINK_MAX;
 
 	inode = ufs_iget(sb, UFS_ROOTINO);
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index 9541759..3f9463f 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -473,15 +473,19 @@
 static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi,
 	struct ufs_buffer_head * ubh, unsigned begin, unsigned block)
 {
+	u8 mask;
 	switch (uspi->s_fpb) {
 	case 8:
 	    	return (*ubh_get_addr (ubh, begin + block) == 0xff);
 	case 4:
-		return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2)));
+		mask = 0x0f << ((block & 0x01) << 2);
+		return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask;
 	case 2:
-		return (*ubh_get_addr (ubh, begin + (block >> 2)) == (0x03 << ((block & 0x03) << 1)));
+		mask = 0x03 << ((block & 0x03) << 1);
+		return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask;
 	case 1:
-		return (*ubh_get_addr (ubh, begin + (block >> 3)) == (0x01 << (block & 0x07)));
+		mask = 0x01 << (block & 0x07);
+		return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask;
 	}
 	return 0;	
 }
diff --git a/fs/utimes.c b/fs/utimes.c
index aa138d6..a35e909 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -87,24 +87,11 @@
 		 */
 		newattrs.ia_valid |= ATTR_TIMES_SET;
 	} else {
-		/*
-		 * If times is NULL (or both times are UTIME_NOW),
-		 * then we need to check permissions, because
-		 * inode_change_ok() won't do it.
-		 */
-		error = -EACCES;
-                if (IS_IMMUTABLE(inode))
-			goto mnt_drop_write_and_out;
-
-		if (!inode_owner_or_capable(inode)) {
-			error = inode_permission(inode, MAY_WRITE);
-			if (error)
-				goto mnt_drop_write_and_out;
-		}
+		newattrs.ia_valid |= ATTR_TOUCH;
 	}
 retry_deleg:
 	mutex_lock(&inode->i_mutex);
-	error = notify_change(path->dentry, &newattrs, &delegated_inode);
+	error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode);
 	mutex_unlock(&inode->i_mutex);
 	if (delegated_inode) {
 		error = break_deleg_wait(&delegated_inode);
@@ -112,7 +99,6 @@
 			goto retry_deleg;
 	}
 
-mnt_drop_write_and_out:
 	mnt_drop_write(path->mnt);
 out:
 	return error;
diff --git a/fs/xattr.c b/fs/xattr.c
index 9b932b9..f0da9d2 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -442,7 +442,7 @@
 			size = XATTR_SIZE_MAX;
 		kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
 		if (!kvalue) {
-			vvalue = vmalloc(size);
+			vvalue = vzalloc(size);
 			if (!vvalue)
 				return -ENOMEM;
 			kvalue = vvalue;
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 3479294..e1e7fe3 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -535,6 +535,7 @@
 }
 
 const struct xfs_buf_ops xfs_agfl_buf_ops = {
+	.name = "xfs_agfl",
 	.verify_read = xfs_agfl_read_verify,
 	.verify_write = xfs_agfl_write_verify,
 };
@@ -2339,6 +2340,7 @@
 }
 
 const struct xfs_buf_ops xfs_agf_buf_ops = {
+	.name = "xfs_agf",
 	.verify_read = xfs_agf_read_verify,
 	.verify_write = xfs_agf_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c
index 90de071..eb8bbfe 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.c
+++ b/fs/xfs/libxfs/xfs_alloc_btree.c
@@ -379,6 +379,7 @@
 }
 
 const struct xfs_buf_ops xfs_allocbt_buf_ops = {
+	.name = "xfs_allocbt",
 	.verify_read = xfs_allocbt_read_verify,
 	.verify_write = xfs_allocbt_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index aa187f7..01a5ecf 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -328,6 +328,7 @@
 }
 
 const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = {
+	.name = "xfs_attr3_leaf",
 	.verify_read = xfs_attr3_leaf_read_verify,
 	.verify_write = xfs_attr3_leaf_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index 5ab95ff..f3ed9bf 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -201,6 +201,7 @@
 }
 
 const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
+	.name = "xfs_attr3_rmt",
 	.verify_read = xfs_attr3_rmt_read_verify,
 	.verify_write = xfs_attr3_rmt_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 119c242..75884ae 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -2179,8 +2179,10 @@
 		}
 		temp = xfs_bmap_worst_indlen(bma->ip, temp);
 		temp2 = xfs_bmap_worst_indlen(bma->ip, temp2);
-		diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
-			(bma->cur ? bma->cur->bc_private.b.allocated : 0));
+		diff = (int)(temp + temp2 -
+			     (startblockval(PREV.br_startblock) -
+			      (bma->cur ?
+			       bma->cur->bc_private.b.allocated : 0)));
 		if (diff > 0) {
 			error = xfs_mod_fdblocks(bma->ip->i_mount,
 						 -((int64_t)diff), false);
@@ -2232,7 +2234,6 @@
 		temp = da_new;
 		if (bma->cur)
 			temp += bma->cur->bc_private.b.allocated;
-		ASSERT(temp <= da_old);
 		if (temp < da_old)
 			xfs_mod_fdblocks(bma->ip->i_mount,
 					(int64_t)(da_old - temp), false);
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 6b0cf65..1637c37 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -720,6 +720,7 @@
 }
 
 const struct xfs_buf_ops xfs_bmbt_buf_ops = {
+	.name = "xfs_bmbt",
 	.verify_read = xfs_bmbt_read_verify,
 	.verify_write = xfs_bmbt_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index af1bbee..28bc5e7 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -4064,7 +4064,7 @@
 			xfs_btree_readahead_ptr(cur, ptr, 1);
 
 			/* save for the next iteration of the loop */
-			lptr = *ptr;
+			xfs_btree_copy_ptrs(cur, &lptr, ptr, 1);
 		}
 
 		/* for each buffer in the level */
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index e89a0f8..097bf77 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -245,6 +245,7 @@
 }
 
 const struct xfs_buf_ops xfs_da3_node_buf_ops = {
+	.name = "xfs_da3_node",
 	.verify_read = xfs_da3_node_read_verify,
 	.verify_write = xfs_da3_node_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c
index 9c10e2b..aa17cb7 100644
--- a/fs/xfs/libxfs/xfs_dir2_block.c
+++ b/fs/xfs/libxfs/xfs_dir2_block.c
@@ -123,6 +123,7 @@
 }
 
 const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
+	.name = "xfs_dir3_block",
 	.verify_read = xfs_dir3_block_read_verify,
 	.verify_write = xfs_dir3_block_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_dir2_data.c b/fs/xfs/libxfs/xfs_dir2_data.c
index af71a84..725fc78 100644
--- a/fs/xfs/libxfs/xfs_dir2_data.c
+++ b/fs/xfs/libxfs/xfs_dir2_data.c
@@ -305,11 +305,13 @@
 }
 
 const struct xfs_buf_ops xfs_dir3_data_buf_ops = {
+	.name = "xfs_dir3_data",
 	.verify_read = xfs_dir3_data_read_verify,
 	.verify_write = xfs_dir3_data_write_verify,
 };
 
 static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = {
+	.name = "xfs_dir3_data_reada",
 	.verify_read = xfs_dir3_data_reada_verify,
 	.verify_write = xfs_dir3_data_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_dir2_leaf.c b/fs/xfs/libxfs/xfs_dir2_leaf.c
index 3923e1f..b887fb2 100644
--- a/fs/xfs/libxfs/xfs_dir2_leaf.c
+++ b/fs/xfs/libxfs/xfs_dir2_leaf.c
@@ -245,11 +245,13 @@
 }
 
 const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = {
+	.name = "xfs_dir3_leaf1",
 	.verify_read = xfs_dir3_leaf1_read_verify,
 	.verify_write = xfs_dir3_leaf1_write_verify,
 };
 
 const struct xfs_buf_ops xfs_dir3_leafn_buf_ops = {
+	.name = "xfs_dir3_leafn",
 	.verify_read = xfs_dir3_leafn_read_verify,
 	.verify_write = xfs_dir3_leafn_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
index 70b0cb2..63ee03d 100644
--- a/fs/xfs/libxfs/xfs_dir2_node.c
+++ b/fs/xfs/libxfs/xfs_dir2_node.c
@@ -150,6 +150,7 @@
 }
 
 const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
+	.name = "xfs_dir3_free",
 	.verify_read = xfs_dir3_free_read_verify,
 	.verify_write = xfs_dir3_free_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c
index 5331b7f..ac9a003 100644
--- a/fs/xfs/libxfs/xfs_dquot_buf.c
+++ b/fs/xfs/libxfs/xfs_dquot_buf.c
@@ -54,7 +54,7 @@
 	xfs_dqid_t	 id,
 	uint		 type,	  /* used only when IO_dorepair is true */
 	uint		 flags,
-	char		 *str)
+	const char	 *str)
 {
 	xfs_dqblk_t	 *d = (xfs_dqblk_t *)ddq;
 	int		errs = 0;
@@ -191,8 +191,7 @@
 	if (mp->m_quotainfo)
 		ndquots = mp->m_quotainfo->qi_dqperchunk;
 	else
-		ndquots = xfs_calc_dquots_per_chunk(
-					XFS_BB_TO_FSB(mp, bp->b_length));
+		ndquots = xfs_calc_dquots_per_chunk(bp->b_length);
 
 	for (i = 0; i < ndquots; i++, d++) {
 		if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
@@ -207,7 +206,8 @@
 STATIC bool
 xfs_dquot_buf_verify(
 	struct xfs_mount	*mp,
-	struct xfs_buf		*bp)
+	struct xfs_buf		*bp,
+	int			warn)
 {
 	struct xfs_dqblk	*d = (struct xfs_dqblk *)bp->b_addr;
 	xfs_dqid_t		id = 0;
@@ -240,8 +240,7 @@
 		if (i == 0)
 			id = be32_to_cpu(ddq->d_id);
 
-		error = xfs_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
-				       "xfs_dquot_buf_verify");
+		error = xfs_dqcheck(mp, ddq, id + i, 0, warn, __func__);
 		if (error)
 			return false;
 	}
@@ -256,7 +255,7 @@
 
 	if (!xfs_dquot_buf_verify_crc(mp, bp))
 		xfs_buf_ioerror(bp, -EFSBADCRC);
-	else if (!xfs_dquot_buf_verify(mp, bp))
+	else if (!xfs_dquot_buf_verify(mp, bp, XFS_QMOPT_DOWARN))
 		xfs_buf_ioerror(bp, -EFSCORRUPTED);
 
 	if (bp->b_error)
@@ -264,6 +263,25 @@
 }
 
 /*
+ * readahead errors are silent and simply leave the buffer as !done so a real
+ * read will then be run with the xfs_dquot_buf_ops verifier. See
+ * xfs_inode_buf_verify() for why we use EIO and ~XBF_DONE here rather than
+ * reporting the failure.
+ */
+static void
+xfs_dquot_buf_readahead_verify(
+	struct xfs_buf	*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+
+	if (!xfs_dquot_buf_verify_crc(mp, bp) ||
+	    !xfs_dquot_buf_verify(mp, bp, 0)) {
+		xfs_buf_ioerror(bp, -EIO);
+		bp->b_flags &= ~XBF_DONE;
+	}
+}
+
+/*
  * we don't calculate the CRC here as that is done when the dquot is flushed to
  * the buffer after the update is done. This ensures that the dquot in the
  * buffer always has an up-to-date CRC value.
@@ -274,7 +292,7 @@
 {
 	struct xfs_mount	*mp = bp->b_target->bt_mount;
 
-	if (!xfs_dquot_buf_verify(mp, bp)) {
+	if (!xfs_dquot_buf_verify(mp, bp, XFS_QMOPT_DOWARN)) {
 		xfs_buf_ioerror(bp, -EFSCORRUPTED);
 		xfs_verifier_error(bp);
 		return;
@@ -282,7 +300,13 @@
 }
 
 const struct xfs_buf_ops xfs_dquot_buf_ops = {
+	.name = "xfs_dquot",
 	.verify_read = xfs_dquot_buf_read_verify,
 	.verify_write = xfs_dquot_buf_write_verify,
 };
 
+const struct xfs_buf_ops xfs_dquot_buf_ra_ops = {
+	.name = "xfs_dquot_ra",
+	.verify_read = xfs_dquot_buf_readahead_verify,
+	.verify_write = xfs_dquot_buf_write_verify,
+};
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 70c1db9..66d702e 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -2572,6 +2572,7 @@
 }
 
 const struct xfs_buf_ops xfs_agi_buf_ops = {
+	.name = "xfs_agi",
 	.verify_read = xfs_agi_read_verify,
 	.verify_write = xfs_agi_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index f39b285..6dd44f9 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -304,6 +304,7 @@
 }
 
 const struct xfs_buf_ops xfs_inobt_buf_ops = {
+	.name = "xfs_inobt",
 	.verify_read = xfs_inobt_read_verify,
 	.verify_write = xfs_inobt_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 65485cf..7183b7e 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -68,6 +68,8 @@
  * recovery and we don't get unnecssary panics on debug kernels. We use EIO here
  * because all we want to do is say readahead failed; there is no-one to report
  * the error to, so this will distinguish it from a non-ra verifier failure.
+ * Changes to this readahead error behavour also need to be reflected in
+ * xfs_dquot_buf_readahead_verify().
  */
 static void
 xfs_inode_buf_verify(
@@ -134,11 +136,13 @@
 }
 
 const struct xfs_buf_ops xfs_inode_buf_ops = {
+	.name = "xfs_inode",
 	.verify_read = xfs_inode_buf_read_verify,
 	.verify_write = xfs_inode_buf_write_verify,
 };
 
 const struct xfs_buf_ops xfs_inode_buf_ra_ops = {
+	.name = "xxfs_inode_ra",
 	.verify_read = xfs_inode_buf_readahead_verify,
 	.verify_write = xfs_inode_buf_write_verify,
 };
@@ -295,6 +299,14 @@
 	if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))
 		return false;
 
+	/* don't allow invalid i_size */
+	if (be64_to_cpu(dip->di_size) & (1ULL << 63))
+		return false;
+
+	/* No zero-length symlinks. */
+	if (S_ISLNK(be16_to_cpu(dip->di_mode)) && dip->di_size == 0)
+		return false;
+
 	/* only version 3 or greater inodes are extensively verified here */
 	if (dip->di_version < 3)
 		return true;
diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h
index 1b0a083..f51078f 100644
--- a/fs/xfs/libxfs/xfs_quota_defs.h
+++ b/fs/xfs/libxfs/xfs_quota_defs.h
@@ -153,7 +153,7 @@
 #define XFS_QMOPT_RESBLK_MASK	(XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
 
 extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq,
-		       xfs_dqid_t id, uint type, uint flags, char *str);
+		       xfs_dqid_t id, uint type, uint flags, const char *str);
 extern int xfs_calc_dquots_per_chunk(unsigned int nbblks);
 
 #endif	/* __XFS_QUOTA_H__ */
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index a0b071d..7088be6 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -581,7 +581,8 @@
 	 * Only check the in progress field for the primary superblock as
 	 * mkfs.xfs doesn't clear it from secondary superblocks.
 	 */
-	return xfs_mount_validate_sb(mp, &sb, bp->b_bn == XFS_SB_DADDR,
+	return xfs_mount_validate_sb(mp, &sb,
+				     bp->b_maps[0].bm_bn == XFS_SB_DADDR,
 				     check_version);
 }
 
@@ -679,11 +680,13 @@
 }
 
 const struct xfs_buf_ops xfs_sb_buf_ops = {
+	.name = "xfs_sb",
 	.verify_read = xfs_sb_read_verify,
 	.verify_write = xfs_sb_write_verify,
 };
 
 const struct xfs_buf_ops xfs_sb_quiet_buf_ops = {
+	.name = "xfs_sb_quiet",
 	.verify_read = xfs_sb_quiet_read_verify,
 	.verify_write = xfs_sb_write_verify,
 };
diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h
index 5be5297..15c3ceb 100644
--- a/fs/xfs/libxfs/xfs_shared.h
+++ b/fs/xfs/libxfs/xfs_shared.h
@@ -49,6 +49,7 @@
 extern const struct xfs_buf_ops xfs_inode_buf_ops;
 extern const struct xfs_buf_ops xfs_inode_buf_ra_ops;
 extern const struct xfs_buf_ops xfs_dquot_buf_ops;
+extern const struct xfs_buf_ops xfs_dquot_buf_ra_ops;
 extern const struct xfs_buf_ops xfs_sb_buf_ops;
 extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops;
 extern const struct xfs_buf_ops xfs_symlink_buf_ops;
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
index cb6fd20..2e2c671 100644
--- a/fs/xfs/libxfs/xfs_symlink_remote.c
+++ b/fs/xfs/libxfs/xfs_symlink_remote.c
@@ -168,6 +168,7 @@
 }
 
 const struct xfs_buf_ops xfs_symlink_buf_ops = {
+	.name = "xfs_symlink",
 	.verify_read = xfs_symlink_read_verify,
 	.verify_write = xfs_symlink_write_verify,
 };
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 6bb470f..c5101a3 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -288,16 +288,11 @@
 		return error;
 
 	if (type == ACL_TYPE_ACCESS) {
-		umode_t mode = inode->i_mode;
-		error = posix_acl_equiv_mode(acl, &mode);
+		umode_t mode;
 
-		if (error <= 0) {
-			acl = NULL;
-
-			if (error < 0)
-				return error;
-		}
-
+		error = posix_acl_update_mode(inode, &mode, &acl);
+		if (error)
+			return error;
 		error = xfs_set_mode(inode, mode);
 		if (error)
 			return error;
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 29e7e5d..187b802 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -288,7 +288,7 @@
 {
 	struct xfs_inode	*ip = XFS_I(inode);
 	struct xfs_mount	*mp = ip->i_mount;
-	ssize_t			count = 1 << inode->i_blkbits;
+	ssize_t			count = i_blocksize(inode);
 	xfs_fileoff_t		offset_fsb, end_fsb;
 	int			error = 0;
 	int			bmapi_flags = XFS_BMAPI_ENTIRE;
@@ -921,7 +921,7 @@
 			break;
 		}
 next_buffer:
-		offset += 1 << inode->i_blkbits;
+		offset += i_blocksize(inode);
 
 	} while ((bh = bh->b_this_page) != head);
 
@@ -1363,7 +1363,7 @@
 	    offset + mapping_size >= i_size_read(inode)) {
 		/* limit mapping to block that spans EOF */
 		mapping_size = roundup_64(i_size_read(inode) - offset,
-					  1 << inode->i_blkbits);
+					  i_blocksize(inode));
 	}
 	if (mapping_size > LONG_MAX)
 		mapping_size = LONG_MAX;
@@ -1395,7 +1395,7 @@
 		return -EIO;
 
 	offset = (xfs_off_t)iblock << inode->i_blkbits;
-	ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
+	ASSERT(bh_result->b_size >= i_blocksize(inode));
 	size = bh_result->b_size;
 
 	if (!create && direct && offset >= i_size_read(inode))
@@ -1968,7 +1968,7 @@
 			if (offset < end_offset)
 				set_buffer_dirty(bh);
 			bh = bh->b_this_page;
-			offset += 1 << inode->i_blkbits;
+			offset += i_blocksize(inode);
 		} while (bh != head);
 	}
 	/*
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index dd48245..2343312 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -112,6 +112,7 @@
  *========================================================================*/
 
 
+/* Return 0 on success, or -errno; other state communicated via *context */
 typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, int,
 			      unsigned char *, int, int, unsigned char *);
 
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
index 4fa1482..c8be331 100644
--- a/fs/xfs/xfs_attr_list.c
+++ b/fs/xfs/xfs_attr_list.c
@@ -108,16 +108,14 @@
 					   (int)sfe->namelen,
 					   (int)sfe->valuelen,
 					   &sfe->nameval[sfe->namelen]);
-
+			if (error)
+				return error;
 			/*
 			 * Either search callback finished early or
 			 * didn't fit it all in the buffer after all.
 			 */
 			if (context->seen_enough)
 				break;
-
-			if (error)
-				return error;
 			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 		}
 		trace_xfs_attr_list_sf_all(context);
@@ -581,7 +579,7 @@
 		trace_xfs_attr_list_full(context);
 		alist->al_more = 1;
 		context->seen_enough = 1;
-		return 1;
+		return 0;
 	}
 
 	aep = (attrlist_ent_t *)&context->alist[context->firstu];
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index dbae649..863e1bf 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -682,7 +682,7 @@
 			 * extents.
 			 */
 			if (map[i].br_startblock == DELAYSTARTBLOCK &&
-			    map[i].br_startoff <= XFS_B_TO_FSB(mp, XFS_ISIZE(ip)))
+			    map[i].br_startoff < XFS_B_TO_FSB(mp, XFS_ISIZE(ip)))
 				ASSERT((iflags & BMV_IF_DELALLOC) != 0);
 
                         if (map[i].br_startblock == HOLESTARTBLOCK &&
@@ -1713,6 +1713,7 @@
 	xfs_trans_t	*tp;
 	xfs_bstat_t	*sbp = &sxp->sx_stat;
 	xfs_ifork_t	*tempifp, *ifp, *tifp;
+	xfs_extnum_t	nextents;
 	int		src_log_flags, target_log_flags;
 	int		error = 0;
 	int		aforkblks = 0;
@@ -1899,7 +1900,8 @@
 		 * pointer.  Otherwise it's already NULL or
 		 * pointing to the extent.
 		 */
-		if (ip->i_d.di_nextents <= XFS_INLINE_EXTS) {
+		nextents = ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+		if (nextents <= XFS_INLINE_EXTS) {
 			ifp->if_u1.if_extents =
 				ifp->if_u2.if_inline_ext;
 		}
@@ -1918,7 +1920,8 @@
 		 * pointer.  Otherwise it's already NULL or
 		 * pointing to the extent.
 		 */
-		if (tip->i_d.di_nextents <= XFS_INLINE_EXTS) {
+		nextents = tip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+		if (nextents <= XFS_INLINE_EXTS) {
 			tifp->if_u1.if_extents =
 				tifp->if_u2.if_inline_ext;
 		}
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 39090fc..dcb7096 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -375,6 +375,7 @@
 out_free_pages:
 	for (i = 0; i < bp->b_page_count; i++)
 		__free_page(bp->b_pages[i]);
+	bp->b_flags &= ~_XBF_PAGES;
 	return error;
 }
 
@@ -978,6 +979,8 @@
 xfs_buf_unlock(
 	struct xfs_buf		*bp)
 {
+	ASSERT(xfs_buf_islocked(bp));
+
 	XB_CLEAR_OWNER(bp);
 	up(&bp->b_sema);
 
@@ -1535,7 +1538,7 @@
 	 * ensure here that all reference counts have been dropped before we
 	 * start walking the LRU list.
 	 */
-	drain_workqueue(btp->bt_mount->m_buf_workqueue);
+	flush_workqueue(btp->bt_mount->m_buf_workqueue);
 
 	/* loop until there is nothing left on the lru list. */
 	while (list_lru_count(&btp->bt_lru)) {
@@ -1712,6 +1715,28 @@
 }
 
 /*
+ * Cancel a delayed write list.
+ *
+ * Remove each buffer from the list, clear the delwri queue flag and drop the
+ * associated buffer reference.
+ */
+void
+xfs_buf_delwri_cancel(
+	struct list_head	*list)
+{
+	struct xfs_buf		*bp;
+
+	while (!list_empty(list)) {
+		bp = list_first_entry(list, struct xfs_buf, b_list);
+
+		xfs_buf_lock(bp);
+		bp->b_flags &= ~_XBF_DELWRI_Q;
+		list_del_init(&bp->b_list);
+		xfs_buf_relse(bp);
+	}
+}
+
+/*
  * Add a buffer to the delayed write list.
  *
  * This queues a buffer for writeout if it hasn't already been.  Note that
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index c79b717..149bbd4 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -132,6 +132,7 @@
 	struct xfs_buf_map (map) = { .bm_bn = (blkno), .bm_len = (numblk) };
 
 struct xfs_buf_ops {
+	char *name;
 	void (*verify_read)(struct xfs_buf *);
 	void (*verify_write)(struct xfs_buf *);
 };
@@ -303,6 +304,7 @@
 extern void *xfs_buf_offset(struct xfs_buf *, size_t);
 
 /* Delayed Write Buffer Routines */
+extern void xfs_buf_delwri_cancel(struct list_head *);
 extern bool xfs_buf_delwri_queue(struct xfs_buf *, struct list_head *);
 extern int xfs_buf_delwri_submit(struct list_head *);
 extern int xfs_buf_delwri_submit_nowait(struct list_head *);
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
index 642d55d..2fbf643 100644
--- a/fs/xfs/xfs_dir2_readdir.c
+++ b/fs/xfs/xfs_dir2_readdir.c
@@ -406,6 +406,7 @@
 
 	/*
 	 * Do we need more readahead?
+	 * Each loop tries to process 1 full dir blk; last may be partial.
 	 */
 	blk_start_plug(&plug);
 	for (mip->ra_index = mip->ra_offset = i = 0;
@@ -416,7 +417,8 @@
 		 * Read-ahead a contiguous directory block.
 		 */
 		if (i > mip->ra_current &&
-		    map[mip->ra_index].br_blockcount >= geo->fsbcount) {
+		    (map[mip->ra_index].br_blockcount - mip->ra_offset) >=
+		    geo->fsbcount) {
 			xfs_dir3_data_readahead(dp,
 				map[mip->ra_index].br_startoff + mip->ra_offset,
 				XFS_FSB_TO_DADDR(dp->i_mount,
@@ -437,14 +439,19 @@
 		}
 
 		/*
-		 * Advance offset through the mapping table.
+		 * Advance offset through the mapping table, processing a full
+		 * dir block even if it is fragmented into several extents.
+		 * But stop if we have consumed all valid mappings, even if
+		 * it's not yet a full directory block.
 		 */
-		for (j = 0; j < geo->fsbcount; j += length ) {
+		for (j = 0;
+		     j < geo->fsbcount && mip->ra_index < mip->map_valid;
+		     j += length ) {
 			/*
 			 * The rest of this extent but not more than a dir
 			 * block.
 			 */
-			length = min_t(int, geo->fsbcount,
+			length = min_t(int, geo->fsbcount - j,
 					map[mip->ra_index].br_blockcount -
 							mip->ra_offset);
 			mip->ra_offset += length;
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 74d0e59..88693a9 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -164,9 +164,9 @@
 {
 	struct xfs_mount *mp = bp->b_target->bt_mount;
 
-	xfs_alert(mp, "Metadata %s detected at %pF, block 0x%llx",
+	xfs_alert(mp, "Metadata %s detected at %pF, %s block 0x%llx",
 		  bp->b_error == -EFSBADCRC ? "CRC error" : "corruption",
-		  __return_address, bp->b_bn);
+		  __return_address, bp->b_ops->name, bp->b_bn);
 
 	xfs_alert(mp, "Unmount and run xfs_repair");
 
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index f5392ab..3dd4730 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -947,7 +947,7 @@
 		if (error)
 			goto out_unlock;
 	} else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
-		unsigned blksize_mask = (1 << inode->i_blkbits) - 1;
+		unsigned int blksize_mask = i_blocksize(inode) - 1;
 
 		if (offset & blksize_mask || len & blksize_mask) {
 			error = -EINVAL;
@@ -969,7 +969,7 @@
 		if (error)
 			goto out_unlock;
 	} else if (mode & FALLOC_FL_INSERT_RANGE) {
-		unsigned blksize_mask = (1 << inode->i_blkbits) - 1;
+		unsigned int blksize_mask = i_blocksize(inode) - 1;
 
 		new_size = i_size_read(inode) + len;
 		if (offset & blksize_mask || len & blksize_mask) {
@@ -1208,7 +1208,7 @@
 		unsigned	nr_pages;
 		unsigned int	i;
 
-		want = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
+		want = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
 		nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
 					  want);
 		/*
@@ -1235,17 +1235,6 @@
 			break;
 		}
 
-		/*
-		 * At lease we found one page.  If this is the first time we
-		 * step into the loop, and if the first page index offset is
-		 * greater than the given search offset, a hole was found.
-		 */
-		if (type == HOLE_OFF && lastoff == startoff &&
-		    lastoff < page_offset(pvec.pages[0])) {
-			found = true;
-			break;
-		}
-
 		for (i = 0; i < nr_pages; i++) {
 			struct page	*page = pvec.pages[i];
 			loff_t		b_offset;
@@ -1257,18 +1246,18 @@
 			 * file mapping. However, page->index will not change
 			 * because we have a reference on the page.
 			 *
-			 * Searching done if the page index is out of range.
-			 * If the current offset is not reaches the end of
-			 * the specified search range, there should be a hole
-			 * between them.
+			 * If current page offset is beyond where we've ended,
+			 * we've found a hole.
 			 */
-			if (page->index > end) {
-				if (type == HOLE_OFF && lastoff < endoff) {
-					*offset = lastoff;
-					found = true;
-				}
+			if (type == HOLE_OFF && lastoff < endoff &&
+			    lastoff < page_offset(pvec.pages[i])) {
+				found = true;
+				*offset = lastoff;
 				goto out;
 			}
+			/* Searching done if the page index is out of range. */
+			if (page->index > end)
+				goto out;
 
 			lock_page(page);
 			/*
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index ee3aaa0a..ca0d3eb 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -243,8 +243,8 @@
 		agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
 		agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1);
 		agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
-		agf->agf_flfirst = 0;
-		agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1);
+		agf->agf_flfirst = cpu_to_be32(1);
+		agf->agf_fllast = 0;
 		agf->agf_flcount = 0;
 		tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
 		agf->agf_freeblks = cpu_to_be32(tmpsize);
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index d7a490f..adbc1f5 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -210,14 +210,17 @@
 
 		error = inode_init_always(mp->m_super, inode);
 		if (error) {
+			bool wake;
 			/*
 			 * Re-initializing the inode failed, and we are in deep
 			 * trouble.  Try to re-add it to the reclaim list.
 			 */
 			rcu_read_lock();
 			spin_lock(&ip->i_flags_lock);
-
+			wake = !!__xfs_iflags_test(ip, XFS_INEW);
 			ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM);
+			if (wake)
+				wake_up_bit(&ip->i_flags, __XFS_INEW_BIT);
 			ASSERT(ip->i_flags & XFS_IRECLAIMABLE);
 			trace_xfs_iget_reclaim_fail(ip);
 			goto out_error;
@@ -363,6 +366,22 @@
 	return error;
 }
 
+static void
+xfs_inew_wait(
+	struct xfs_inode	*ip)
+{
+	wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_INEW_BIT);
+	DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_INEW_BIT);
+
+	do {
+		prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
+		if (!xfs_iflags_test(ip, XFS_INEW))
+			break;
+		schedule();
+	} while (true);
+	finish_wait(wq, &wait.wait);
+}
+
 /*
  * Look up an inode by number in the given file system.
  * The inode is looked up in the cache held in each AG.
@@ -467,9 +486,11 @@
 
 STATIC int
 xfs_inode_ag_walk_grab(
-	struct xfs_inode	*ip)
+	struct xfs_inode	*ip,
+	int			flags)
 {
 	struct inode		*inode = VFS_I(ip);
+	bool			newinos = !!(flags & XFS_AGITER_INEW_WAIT);
 
 	ASSERT(rcu_read_lock_held());
 
@@ -487,7 +508,8 @@
 		goto out_unlock_noent;
 
 	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
-	if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
+	if ((!newinos && __xfs_iflags_test(ip, XFS_INEW)) ||
+	    __xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM))
 		goto out_unlock_noent;
 	spin_unlock(&ip->i_flags_lock);
 
@@ -515,7 +537,8 @@
 					   void *args),
 	int			flags,
 	void			*args,
-	int			tag)
+	int			tag,
+	int			iter_flags)
 {
 	uint32_t		first_index;
 	int			last_error = 0;
@@ -557,7 +580,7 @@
 		for (i = 0; i < nr_found; i++) {
 			struct xfs_inode *ip = batch[i];
 
-			if (done || xfs_inode_ag_walk_grab(ip))
+			if (done || xfs_inode_ag_walk_grab(ip, iter_flags))
 				batch[i] = NULL;
 
 			/*
@@ -585,6 +608,9 @@
 		for (i = 0; i < nr_found; i++) {
 			if (!batch[i])
 				continue;
+			if ((iter_flags & XFS_AGITER_INEW_WAIT) &&
+			    xfs_iflags_test(batch[i], XFS_INEW))
+				xfs_inew_wait(batch[i]);
 			error = execute(batch[i], flags, args);
 			IRELE(batch[i]);
 			if (error == -EAGAIN) {
@@ -637,12 +663,13 @@
 }
 
 int
-xfs_inode_ag_iterator(
+xfs_inode_ag_iterator_flags(
 	struct xfs_mount	*mp,
 	int			(*execute)(struct xfs_inode *ip, int flags,
 					   void *args),
 	int			flags,
-	void			*args)
+	void			*args,
+	int			iter_flags)
 {
 	struct xfs_perag	*pag;
 	int			error = 0;
@@ -652,7 +679,8 @@
 	ag = 0;
 	while ((pag = xfs_perag_get(mp, ag))) {
 		ag = pag->pag_agno + 1;
-		error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1);
+		error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1,
+					  iter_flags);
 		xfs_perag_put(pag);
 		if (error) {
 			last_error = error;
@@ -664,6 +692,17 @@
 }
 
 int
+xfs_inode_ag_iterator(
+	struct xfs_mount	*mp,
+	int			(*execute)(struct xfs_inode *ip, int flags,
+					   void *args),
+	int			flags,
+	void			*args)
+{
+	return xfs_inode_ag_iterator_flags(mp, execute, flags, args, 0);
+}
+
+int
 xfs_inode_ag_iterator_tag(
 	struct xfs_mount	*mp,
 	int			(*execute)(struct xfs_inode *ip, int flags,
@@ -680,7 +719,8 @@
 	ag = 0;
 	while ((pag = xfs_perag_get_tag(mp, ag, tag))) {
 		ag = pag->pag_agno + 1;
-		error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag);
+		error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag,
+					  0);
 		xfs_perag_put(pag);
 		if (error) {
 			last_error = error;
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index 62f1f91..147a792 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -48,6 +48,11 @@
 #define XFS_IGET_UNTRUSTED	0x2
 #define XFS_IGET_DONTCACHE	0x4
 
+/*
+ * flags for AG inode iterator
+ */
+#define XFS_AGITER_INEW_WAIT	0x1	/* wait on new inodes */
+
 int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
 	     uint flags, uint lock_flags, xfs_inode_t **ipp);
 
@@ -72,6 +77,9 @@
 int xfs_inode_ag_iterator(struct xfs_mount *mp,
 	int (*execute)(struct xfs_inode *ip, int flags, void *args),
 	int flags, void *args);
+int xfs_inode_ag_iterator_flags(struct xfs_mount *mp,
+	int (*execute)(struct xfs_inode *ip, int flags, void *args),
+	int flags, void *args, int iter_flags);
 int xfs_inode_ag_iterator_tag(struct xfs_mount *mp,
 	int (*execute)(struct xfs_inode *ip, int flags, void *args),
 	int flags, void *args, int tag);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 8ee3939..f0ce28c 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -3220,13 +3220,14 @@
 		 * We need to check under the i_flags_lock for a valid inode
 		 * here. Skip it if it is not valid or the wrong inode.
 		 */
-		spin_lock(&ip->i_flags_lock);
-		if (!ip->i_ino ||
+		spin_lock(&iq->i_flags_lock);
+		if (!iq->i_ino ||
+		    __xfs_iflags_test(iq, XFS_ISTALE) ||
 		    (XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) != first_index) {
-			spin_unlock(&ip->i_flags_lock);
+			spin_unlock(&iq->i_flags_lock);
 			continue;
 		}
-		spin_unlock(&ip->i_flags_lock);
+		spin_unlock(&iq->i_flags_lock);
 
 		/*
 		 * Do an un-protected check to see if the inode is dirty and
@@ -3342,7 +3343,7 @@
 	struct xfs_buf		**bpp)
 {
 	struct xfs_mount	*mp = ip->i_mount;
-	struct xfs_buf		*bp;
+	struct xfs_buf		*bp = NULL;
 	struct xfs_dinode	*dip;
 	int			error;
 
@@ -3384,14 +3385,22 @@
 	}
 
 	/*
-	 * Get the buffer containing the on-disk inode.
+	 * Get the buffer containing the on-disk inode. We are doing a try-lock
+	 * operation here, so we may get  an EAGAIN error. In that case, we
+	 * simply want to return with the inode still dirty.
+	 *
+	 * If we get any other error, we effectively have a corruption situation
+	 * and we cannot flush the inode, so we treat it the same as failing
+	 * xfs_iflush_int().
 	 */
 	error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK,
 			       0);
-	if (error || !bp) {
+	if (error == -EAGAIN) {
 		xfs_ifunlock(ip);
 		return error;
 	}
+	if (error)
+		goto corrupt_out;
 
 	/*
 	 * First flush out the inode that xfs_iflush was called with.
@@ -3419,7 +3428,8 @@
 	return 0;
 
 corrupt_out:
-	xfs_buf_relse(bp);
+	if (bp)
+		xfs_buf_relse(bp);
 	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 cluster_corrupt_out:
 	error = -EFSCORRUPTED;
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index ca9e119..ae1a498 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -208,7 +208,8 @@
 #define XFS_IRECLAIM		(1 << 0) /* started reclaiming this inode */
 #define XFS_ISTALE		(1 << 1) /* inode has been staled */
 #define XFS_IRECLAIMABLE	(1 << 2) /* inode can be reclaimed */
-#define XFS_INEW		(1 << 3) /* inode has just been allocated */
+#define __XFS_INEW_BIT		3	 /* inode has just been allocated */
+#define XFS_INEW		(1 << __XFS_INEW_BIT)
 #define XFS_ITRUNCATED		(1 << 5) /* truncated down so flush-on-close */
 #define XFS_IDIRTY_RELEASE	(1 << 6) /* dirty release already seen */
 #define __XFS_IFLOCK_BIT	7	 /* inode is being flushed right now */
@@ -453,6 +454,7 @@
 	xfs_iflags_clear(ip, XFS_INEW);
 	barrier();
 	unlock_new_inode(VFS_I(ip));
+	wake_up_bit(&ip->i_flags, __XFS_INEW_BIT);
 }
 
 static inline void xfs_setup_existing_inode(struct xfs_inode *ip)
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index d42738d..e4a4f82 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -403,6 +403,7 @@
 {
 	int			error = -ENOMEM;
 	attrlist_cursor_kern_t	*cursor;
+	struct xfs_fsop_attrlist_handlereq __user	*p = arg;
 	xfs_fsop_attrlist_handlereq_t al_hreq;
 	struct dentry		*dentry;
 	char			*kbuf;
@@ -435,6 +436,11 @@
 	if (error)
 		goto out_kfree;
 
+	if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t))) {
+		error = -EFAULT;
+		goto out_kfree;
+	}
+
 	if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
 		error = -EFAULT;
 
@@ -1379,10 +1385,11 @@
 	unsigned int		cmd,
 	void			__user *arg)
 {
-	struct getbmapx		bmx;
+	struct getbmapx		bmx = { 0 };
 	int			error;
 
-	if (copy_from_user(&bmx, arg, sizeof(struct getbmapx)))
+	/* struct getbmap is a strict subset of struct getbmapx. */
+	if (copy_from_user(&bmx, arg, offsetof(struct getbmapx, bmv_iflags)))
 		return -EFAULT;
 
 	if (bmx.bmv_count < 2)
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index c5ecaac..8cab78e 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3204,6 +3204,7 @@
 	struct xfs_disk_dquot	*recddq;
 	struct xfs_dq_logformat	*dq_f;
 	uint			type;
+	int			len;
 
 
 	if (mp->m_qflags == 0)
@@ -3224,8 +3225,12 @@
 	ASSERT(dq_f);
 	ASSERT(dq_f->qlf_len == 1);
 
-	xfs_buf_readahead(mp->m_ddev_targp, dq_f->qlf_blkno,
-			  XFS_FSB_TO_BB(mp, dq_f->qlf_len), NULL);
+	len = XFS_FSB_TO_BB(mp, dq_f->qlf_len);
+	if (xlog_peek_buffer_cancelled(log, dq_f->qlf_blkno, len, 0))
+		return;
+
+	xfs_buf_readahead(mp->m_ddev_targp, dq_f->qlf_blkno, len,
+			  &xfs_dquot_buf_ra_ops);
 }
 
 STATIC void
@@ -3975,6 +3980,7 @@
 	agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
 	offset = offsetof(xfs_agi_t, agi_unlinked) +
 		 (sizeof(xfs_agino_t) * bucket);
+	xfs_trans_buf_set_type(tp, agibp, XFS_BLFT_AGI_BUF);
 	xfs_trans_log_buf(tp, agibp, offset,
 			  (offset + sizeof(xfs_agino_t) - 1));
 
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 532ab79..572b64a 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1355,12 +1355,7 @@
 	mp->m_qflags |= flags;
 
  error_return:
-	while (!list_empty(&buffer_list)) {
-		struct xfs_buf *bp =
-			list_first_entry(&buffer_list, struct xfs_buf, b_list);
-		list_del_init(&bp->b_list);
-		xfs_buf_relse(bp);
-	}
+	xfs_buf_delwri_cancel(&buffer_list);
 
 	if (error) {
 		xfs_warn(mp,
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 3640c6e..4d33444 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -764,5 +764,6 @@
 	uint		 flags)
 {
 	ASSERT(mp->m_quotainfo);
-	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, NULL);
+	xfs_inode_ag_iterator_flags(mp, xfs_dqrele_inode, flags, NULL,
+				    XFS_AGITER_INEW_WAIT);
 }
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 36bd882..ef64a1e 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1233,6 +1233,16 @@
 			return -EINVAL;
 		}
 
+		if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
+		    xfs_sb_has_ro_compat_feature(sbp,
+					XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
+			xfs_warn(mp,
+"ro->rw transition prohibited on unknown (0x%x) ro-compat filesystem",
+				(sbp->sb_features_ro_compat &
+					XFS_SB_FEAT_RO_COMPAT_UNKNOWN));
+			return -EINVAL;
+		}
+
 		mp->m_flags &= ~XFS_MOUNT_RDONLY;
 
 		/*
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index 839b35c..9beaf19 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -180,7 +180,8 @@
 	arraytop = context->count + prefix_len + namelen + 1;
 	if (arraytop > context->firstu) {
 		context->count = -1;	/* insufficient space */
-		return 1;
+		context->seen_enough = 1;
+		return 0;
 	}
 	offset = (char *)context->alist + context->count;
 	strncpy(offset, xfs_xattr_prefix(flags), prefix_len);
@@ -222,12 +223,15 @@
 }
 
 ssize_t
-xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
+xfs_vn_listxattr(
+	struct dentry	*dentry,
+	char		*data,
+	size_t		size)
 {
 	struct xfs_attr_list_context context;
 	struct attrlist_cursor_kern cursor = { 0 };
-	struct inode		*inode = d_inode(dentry);
-	int			error;
+	struct inode	*inode = d_inode(dentry);
+	int		error;
 
 	/*
 	 * First read the regular on-disk attributes.
@@ -245,7 +249,9 @@
 	else
 		context.put_listent = xfs_xattr_put_listent_sizes;
 
-	xfs_attr_list_int(&context);
+	error = xfs_attr_list_int(&context);
+	if (error)
+		return error;
 	if (context.count < 0)
 		return -ERANGE;
 
diff --git a/include/asm-generic/fixmap.h b/include/asm-generic/fixmap.h
index 1cbb833..827e4d3 100644
--- a/include/asm-generic/fixmap.h
+++ b/include/asm-generic/fixmap.h
@@ -70,12 +70,12 @@
 #endif
 
 /* Return a pointer with offset calculated */
-#define __set_fixmap_offset(idx, phys, flags)		      \
-({							      \
-	unsigned long addr;				      \
-	__set_fixmap(idx, phys, flags);			      \
-	addr = fix_to_virt(idx) + ((phys) & (PAGE_SIZE - 1)); \
-	addr;						      \
+#define __set_fixmap_offset(idx, phys, flags)				\
+({									\
+	unsigned long ________addr;					\
+	__set_fixmap(idx, phys, flags);					\
+	________addr = fix_to_virt(idx) + ((phys) & (PAGE_SIZE - 1));	\
+	________addr;							\
 })
 
 #define set_fixmap_offset(idx, phys) \
diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h
index 4b4b056..5148150 100644
--- a/include/asm-generic/memory_model.h
+++ b/include/asm-generic/memory_model.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_MEMORY_MODEL_H
 #define __ASM_MEMORY_MODEL_H
 
+#include <linux/pfn.h>
+
 #ifndef __ASSEMBLY__
 
 #if defined(CONFIG_FLATMEM)
@@ -72,7 +74,7 @@
 /*
  * Convert a physical address to a Page Frame Number and back
  */
-#define	__phys_to_pfn(paddr)	((unsigned long)((paddr) >> PAGE_SHIFT))
+#define	__phys_to_pfn(paddr)	PHYS_PFN(paddr)
 #define	__pfn_to_phys(pfn)	PFN_PHYS(pfn)
 
 #define page_to_pfn __page_to_pfn
diff --git a/include/asm-generic/qspinlock.h b/include/asm-generic/qspinlock.h
index e2aadbc..1885fc4 100644
--- a/include/asm-generic/qspinlock.h
+++ b/include/asm-generic/qspinlock.h
@@ -21,14 +21,33 @@
 #include <asm-generic/qspinlock_types.h>
 
 /**
+ * queued_spin_unlock_wait - wait until the _current_ lock holder releases the lock
+ * @lock : Pointer to queued spinlock structure
+ *
+ * There is a very slight possibility of live-lock if the lockers keep coming
+ * and the waiter is just unfortunate enough to not see any unlock state.
+ */
+#ifndef queued_spin_unlock_wait
+extern void queued_spin_unlock_wait(struct qspinlock *lock);
+#endif
+
+/**
  * queued_spin_is_locked - is the spinlock locked?
  * @lock: Pointer to queued spinlock structure
  * Return: 1 if it is locked, 0 otherwise
  */
+#ifndef queued_spin_is_locked
 static __always_inline int queued_spin_is_locked(struct qspinlock *lock)
 {
+	/*
+	 * See queued_spin_unlock_wait().
+	 *
+	 * Any !0 state indicates it is locked, even if _Q_LOCKED_VAL
+	 * isn't immediately observable.
+	 */
 	return atomic_read(&lock->val);
 }
+#endif
 
 /**
  * queued_spin_value_unlocked - is the spinlock structure unlocked?
@@ -98,19 +117,6 @@
 }
 #endif
 
-/**
- * queued_spin_unlock_wait - wait until current lock holder releases the lock
- * @lock : Pointer to queued spinlock structure
- *
- * There is a very slight possibility of live-lock if the lockers keep coming
- * and the waiter is just unfortunate enough to not see any unlock state.
- */
-static inline void queued_spin_unlock_wait(struct qspinlock *lock)
-{
-	while (atomic_read(&lock->val) & _Q_LOCKED_MASK)
-		cpu_relax();
-}
-
 #ifndef virt_spin_lock
 static __always_inline bool virt_spin_lock(struct qspinlock *lock)
 {
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
index 3d1a3af..a2508a8 100644
--- a/include/asm-generic/siginfo.h
+++ b/include/asm-generic/siginfo.h
@@ -17,21 +17,6 @@
 struct siginfo;
 void do_schedule_next_timer(struct siginfo *info);
 
-#ifndef HAVE_ARCH_COPY_SIGINFO
-
-#include <linux/string.h>
-
-static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
-{
-	if (from->si_code < 0)
-		memcpy(to, from, sizeof(*to));
-	else
-		/* _sigchld is currently the largest know union member */
-		memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
-}
-
-#endif
-
 extern int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from);
 
 #endif
diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
index 1bfa602..32901d1 100644
--- a/include/asm-generic/uaccess.h
+++ b/include/asm-generic/uaccess.h
@@ -230,14 +230,18 @@
 	might_fault();						\
 	access_ok(VERIFY_READ, __p, sizeof(*ptr)) ?		\
 		__get_user((x), (__typeof__(*(ptr)) *)__p) :	\
-		-EFAULT;					\
+		((x) = (__typeof__(*(ptr)))0,-EFAULT);		\
 })
 
 #ifndef __get_user_fn
 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 {
-	size = __copy_from_user(x, ptr, size);
-	return size ? -EFAULT : size;
+	size_t n = __copy_from_user(x, ptr, size);
+	if (unlikely(n)) {
+		memset(x + (size - n), 0, n);
+		return -EFAULT;
+	}
+	return 0;
 }
 
 #define __get_user_fn(sz, u, k)	__get_user_fn(sz, u, k)
@@ -257,11 +261,13 @@
 static inline long copy_from_user(void *to,
 		const void __user * from, unsigned long n)
 {
+	unsigned long res = n;
 	might_fault();
-	if (access_ok(VERIFY_READ, from, n))
-		return __copy_from_user(to, from, n);
-	else
-		return n;
+	if (likely(access_ok(VERIFY_READ, from, n)))
+		res = __copy_from_user(to, from, n);
+	if (unlikely(res))
+		memset(to + (n - res), 0, res);
+	return res;
 }
 
 static inline long copy_to_user(void __user *to,
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index c4bd0e2..a65eedc 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -249,6 +249,14 @@
 	*(.data..init_task)
 
 /*
+ * Allow architectures to handle ro_after_init data on their
+ * own by defining an empty RO_AFTER_INIT_DATA.
+ */
+#ifndef RO_AFTER_INIT_DATA
+#define RO_AFTER_INIT_DATA *(.data..ro_after_init)
+#endif
+
+/*
  * Read only Data
  */
 #define RO_DATA_SECTION(align)						\
@@ -256,6 +264,7 @@
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata) *(.rodata.*)					\
+		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
 		VMLINUX_SYMBOL(__start___tracepoints_ptrs) = .;		\
@@ -531,15 +540,19 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
 #define EXIT_DATA							\
 	*(.exit.data)							\
+	*(.fini_array)							\
+	*(.dtors)							\
 	MEM_DISCARD(exit.data)						\
 	MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT							\
 	*(.exit.text)							\
+	*(.text.exit)							\
 	MEM_DISCARD(exit.text)
 
 #define EXIT_CALL							\
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index c9fe145..04661e1 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -202,6 +202,9 @@
 				   struct blkcipher_walk *walk,
 				   struct crypto_aead *tfm,
 				   unsigned int blocksize);
+int blkcipher_ablkcipher_walk_virt(struct blkcipher_desc *desc,
+				   struct blkcipher_walk *walk,
+				   struct crypto_ablkcipher *tfm);
 
 int ablkcipher_walk_done(struct ablkcipher_request *req,
 			 struct ablkcipher_walk *walk, int err);
diff --git a/include/crypto/gf128mul.h b/include/crypto/gf128mul.h
index da2530e..230760a 100644
--- a/include/crypto/gf128mul.h
+++ b/include/crypto/gf128mul.h
@@ -43,7 +43,7 @@
  ---------------------------------------------------------------------------
  Issue Date: 31/01/2006
 
- An implementation of field multiplication in Galois Field GF(128)
+ An implementation of field multiplication in Galois Field GF(2^128)
 */
 
 #ifndef _CRYPTO_GF128MUL_H
@@ -65,7 +65,7 @@
  * are left and the lsb's are right. char b[16] is an array and b[0] is
  * the first octet.
  *
- * 80000000 00000000 00000000 00000000 .... 00000000 00000000 00000000
+ * 10000000 00000000 00000000 00000000 .... 00000000 00000000 00000000
  *   b[0]     b[1]     b[2]     b[3]          b[13]    b[14]    b[15]
  *
  * Every bit is a coefficient of some power of X. We can store the bits
@@ -99,21 +99,21 @@
  *
  * bbe on a little endian machine u32 x[4]:
  *
- *  MS            x[0]           LS  MS            x[1]		  LS
+ *  MS            x[0]           LS  MS            x[1]           LS
  *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
  *  103..96 111.104 119.112 127.120  71...64 79...72 87...80 95...88
  *
- *  MS            x[2]           LS  MS            x[3]		  LS
+ *  MS            x[2]           LS  MS            x[3]           LS
  *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
  *  39...32 47...40 55...48 63...56  07...00 15...08 23...16 31...24
  *
  * ble on a little endian machine
  *
- *  MS            x[0]           LS  MS            x[1]		  LS
+ *  MS            x[0]           LS  MS            x[1]           LS
  *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
  *  31...24 23...16 15...08 07...00  63...56 55...48 47...40 39...32
  *
- *  MS            x[2]           LS  MS            x[3]		  LS
+ *  MS            x[2]           LS  MS            x[3]           LS
  *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
  *  95...88 87...80 79...72 71...64  127.120 199.112 111.104 103..96
  *
@@ -127,7 +127,7 @@
  * machines this will automatically aligned to wordsize and on a 64-bit
  * machine also.
  */
-/*	Multiply a GF128 field element by x. Field elements are held in arrays
+/*  Multiply a GF128 field element by x. Field elements are held in arrays
     of bytes in which field bits 8n..8n + 7 are held in byte[n], with lower
     indexed bits placed in the more numerically significant bit positions
     within bytes.
@@ -135,62 +135,65 @@
     On little endian machines the bit indexes translate into the bit
     positions within four 32-bit words in the following way
 
-    MS            x[0]           LS  MS            x[1]		  LS
+    MS            x[0]           LS  MS            x[1]           LS
     ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
     24...31 16...23 08...15 00...07  56...63 48...55 40...47 32...39
 
-    MS            x[2]           LS  MS            x[3]		  LS
+    MS            x[2]           LS  MS            x[3]           LS
     ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
     88...95 80...87 72...79 64...71  120.127 112.119 104.111 96..103
 
     On big endian machines the bit indexes translate into the bit
     positions within four 32-bit words in the following way
 
-    MS            x[0]           LS  MS            x[1]		  LS
+    MS            x[0]           LS  MS            x[1]           LS
     ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
     00...07 08...15 16...23 24...31  32...39 40...47 48...55 56...63
 
-    MS            x[2]           LS  MS            x[3]		  LS
+    MS            x[2]           LS  MS            x[3]           LS
     ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
     64...71 72...79 80...87 88...95  96..103 104.111 112.119 120.127
 */
 
-/*	A slow generic version of gf_mul, implemented for lle and bbe
- * 	It multiplies a and b and puts the result in a */
+/*  A slow generic version of gf_mul, implemented for lle, bbe, and ble.
+ *  It multiplies a and b and puts the result in a
+ */
 void gf128mul_lle(be128 *a, const be128 *b);
-
 void gf128mul_bbe(be128 *a, const be128 *b);
+void gf128mul_ble(be128 *a, const be128 *b);
 
-/* multiply by x in ble format, needed by XTS */
+/* multiply by x in ble format, needed by XTS and HEH */
 void gf128mul_x_ble(be128 *a, const be128 *b);
 
 /* 4k table optimization */
-
 struct gf128mul_4k {
 	be128 t[256];
 };
 
 struct gf128mul_4k *gf128mul_init_4k_lle(const be128 *g);
 struct gf128mul_4k *gf128mul_init_4k_bbe(const be128 *g);
+struct gf128mul_4k *gf128mul_init_4k_ble(const be128 *g);
 void gf128mul_4k_lle(be128 *a, struct gf128mul_4k *t);
 void gf128mul_4k_bbe(be128 *a, struct gf128mul_4k *t);
+void gf128mul_4k_ble(be128 *a, struct gf128mul_4k *t);
 
 static inline void gf128mul_free_4k(struct gf128mul_4k *t)
 {
-	kfree(t);
+	kzfree(t);
 }
 
 
-/* 64k table optimization, implemented for lle and bbe */
+/* 64k table optimization, implemented for lle, ble, and bbe */
 
 struct gf128mul_64k {
 	struct gf128mul_4k *t[16];
 };
 
-/* first initialize with the constant factor with which you
- * want to multiply and then call gf128_64k_lle with the other
- * factor in the first argument, the table in the second and a
- * scratch register in the third. Afterwards *a = *r. */
+/* First initialize with the constant factor with which you
+ * want to multiply and then call gf128mul_64k_bbe with the other
+ * factor in the first argument, and the table in the second.
+ * Afterwards, the result is stored in *a.
+ */
 struct gf128mul_64k *gf128mul_init_64k_lle(const be128 *g);
 struct gf128mul_64k *gf128mul_init_64k_bbe(const be128 *g);
 void gf128mul_free_64k(struct gf128mul_64k *t);
diff --git a/include/crypto/ghash.h b/include/crypto/ghash.h
new file mode 100644
index 0000000..2a61c9b
--- /dev/null
+++ b/include/crypto/ghash.h
@@ -0,0 +1,23 @@
+/*
+ * Common values for GHASH algorithms
+ */
+
+#ifndef __CRYPTO_GHASH_H__
+#define __CRYPTO_GHASH_H__
+
+#include <linux/types.h>
+#include <crypto/gf128mul.h>
+
+#define GHASH_BLOCK_SIZE	16
+#define GHASH_DIGEST_SIZE	16
+
+struct ghash_ctx {
+	struct gf128mul_4k *gf128;
+};
+
+struct ghash_desc_ctx {
+	u8 buffer[GHASH_BLOCK_SIZE];
+	u32 bytes;
+};
+
+#endif
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index 3b4af1d..611b3d3 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -102,6 +102,8 @@
 			    struct shash_instance *inst);
 void shash_free_instance(struct crypto_instance *inst);
 
+int crypto_grab_shash(struct crypto_shash_spawn *spawn,
+		      const char *name, u32 type, u32 mask);
 int crypto_init_shash_spawn(struct crypto_shash_spawn *spawn,
 			    struct shash_alg *alg,
 			    struct crypto_instance *inst);
@@ -111,6 +113,12 @@
 	crypto_drop_spawn(&spawn->base);
 }
 
+static inline struct shash_alg *crypto_spawn_shash_alg(
+	struct crypto_shash_spawn *spawn)
+{
+	return container_of(spawn->base.alg, struct shash_alg, base);
+}
+
 struct shash_alg *shash_attr_alg(struct rtattr *rta, u32 type, u32 mask);
 
 int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc);
@@ -173,6 +181,16 @@
 	return crypto_alloc_instance2(name, alg, ahash_instance_headroom());
 }
 
+static inline void ahash_request_complete(struct ahash_request *req, int err)
+{
+	req->base.complete(&req->base, err);
+}
+
+static inline u32 ahash_request_flags(struct ahash_request *req)
+{
+	return req->base.flags;
+}
+
 static inline struct crypto_ahash *crypto_spawn_ahash(
 	struct crypto_ahash_spawn *spawn)
 {
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 0a271ca..a31976c 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1029,7 +1029,8 @@
 #endif
 
 extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
-		struct drm_gem_object *obj, int flags);
+					    struct drm_gem_object *obj,
+					    int flags);
 extern int drm_gem_prime_handle_to_fd(struct drm_device *dev,
 		struct drm_file *file_priv, uint32_t handle, uint32_t flags,
 		int *prime_fd);
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 186adfb..8cba54a 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -42,10 +42,6 @@
 			     struct drm_atomic_state *state,
 			     bool async);
 
-bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev,
-					   struct drm_atomic_state *old_state,
-					   struct drm_crtc *crtc);
-
 void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
 					struct drm_atomic_state *old_state);
 
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index a7d2319..3f0c690 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1233,11 +1233,10 @@
 void drm_bridge_pre_enable(struct drm_bridge *bridge);
 void drm_bridge_enable(struct drm_bridge *bridge);
 
-extern __printf(5, 6)
-int drm_encoder_init(struct drm_device *dev,
-		     struct drm_encoder *encoder,
-		     const struct drm_encoder_funcs *funcs,
-		     int encoder_type, const char *name, ...);
+extern int drm_encoder_init(struct drm_device *dev,
+			    struct drm_encoder *encoder,
+			    const struct drm_encoder_funcs *funcs,
+			    int encoder_type);
 
 /**
  * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h
index 17c4456..2cdc723 100644
--- a/include/drm/i915_pciids.h
+++ b/include/drm/i915_pciids.h
@@ -277,7 +277,9 @@
 	INTEL_VGA_DEVICE(0x191D, info)  /* WKS GT2 */
 
 #define INTEL_SKL_GT3_IDS(info) \
+	INTEL_VGA_DEVICE(0x1923, info), /* ULT GT3 */ \
 	INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \
+	INTEL_VGA_DEVICE(0x1927, info), /* ULT GT3 */ \
 	INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \
 	INTEL_VGA_DEVICE(0x192A, info) /* SRV GT3 */ \
 
@@ -289,6 +291,8 @@
 #define INTEL_BXT_IDS(info) \
 	INTEL_VGA_DEVICE(0x0A84, info), \
 	INTEL_VGA_DEVICE(0x1A84, info), \
-	INTEL_VGA_DEVICE(0x5A84, info)
+	INTEL_VGA_DEVICE(0x1A85, info), \
+	INTEL_VGA_DEVICE(0x5A84, info), /* APL HD Graphics 505 */ \
+	INTEL_VGA_DEVICE(0x5A85, info)  /* APL HD Graphics 500 */
 
 #endif /* _I915_PCIIDS_H */
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index c768ddf..b7bfa51 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -316,6 +316,20 @@
  */
 extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy,
 		       bool interruptible, bool no_wait);
+
+/**
+ * ttm_bo_mem_compat - Check if proposed placement is compatible with a bo
+ *
+ * @placement:  Return immediately if buffer is busy.
+ * @mem:  The struct ttm_mem_reg indicating the region where the bo resides
+ * @new_flags: Describes compatible placement found
+ *
+ * Returns true if the placement is compatible
+ */
+extern bool ttm_bo_mem_compat(struct ttm_placement *placement,
+			      struct ttm_mem_reg *mem,
+			      uint32_t *new_flags);
+
 /**
  * ttm_bo_validate
  *
diff --git a/include/drm/ttm/ttm_object.h b/include/drm/ttm/ttm_object.h
index ed953f9..1487011 100644
--- a/include/drm/ttm/ttm_object.h
+++ b/include/drm/ttm/ttm_object.h
@@ -229,6 +229,8 @@
  * @ref_type: The type of reference.
  * @existed: Upon completion, indicates that an identical reference object
  * already existed, and the refcount was upped on that object instead.
+ * @require_existed: Fail with -EPERM if an identical ref object didn't
+ * already exist.
  *
  * Checks that the base object is shareable and adds a ref object to it.
  *
@@ -243,7 +245,8 @@
  */
 extern int ttm_ref_object_add(struct ttm_object_file *tfile,
 			      struct ttm_base_object *base,
-			      enum ttm_ref_type ref_type, bool *existed);
+			      enum ttm_ref_type ref_type, bool *existed,
+			      bool require_existed);
 
 extern bool ttm_ref_object_exists(struct ttm_object_file *tfile,
 				  struct ttm_base_object *base);
diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h
deleted file mode 100644
index e02f4c0..0000000
--- a/include/dt-bindings/clock/rk3036-cru.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
- * Author: Xing Zheng <zhengxing@rock-chips.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3036_H
-#define _DT_BINDINGS_CLK_ROCKCHIP_RK3036_H
-
-/* core clocks */
-#define PLL_APLL		1
-#define PLL_DPLL		2
-#define PLL_GPLL		3
-#define ARMCLK			4
-
-/* sclk gates (special clocks) */
-#define SCLK_GPU		64
-#define SCLK_SPI		65
-#define SCLK_SDMMC		68
-#define SCLK_SDIO		69
-#define SCLK_EMMC		71
-#define SCLK_NANDC		76
-#define SCLK_UART0		77
-#define SCLK_UART1		78
-#define SCLK_UART2		79
-#define SCLK_I2S		82
-#define SCLK_SPDIF		83
-#define SCLK_TIMER0		85
-#define SCLK_TIMER1		86
-#define SCLK_TIMER2		87
-#define SCLK_TIMER3		88
-#define SCLK_OTGPHY0		93
-#define SCLK_LCDC		100
-#define SCLK_HDMI		109
-#define SCLK_HEVC		111
-#define SCLK_I2S_OUT		113
-#define SCLK_SDMMC_DRV		114
-#define SCLK_SDIO_DRV		115
-#define SCLK_EMMC_DRV		117
-#define SCLK_SDMMC_SAMPLE	118
-#define SCLK_SDIO_SAMPLE	119
-#define SCLK_EMMC_SAMPLE	121
-#define SCLK_PVTM_CORE		123
-#define SCLK_PVTM_GPU		124
-#define SCLK_PVTM_VIDEO		125
-#define SCLK_MAC		151
-#define SCLK_MACREF		152
-#define SCLK_MACPLL           	153
-#define SCLK_SFC		160
-
-/* aclk gates */
-#define ACLK_DMAC2		194
-#define ACLK_LCDC		197
-#define ACLK_VIO		203
-#define ACLK_VCODEC		208
-#define ACLK_CPU		209
-#define ACLK_PERI		210
-
-/* pclk gates */
-#define PCLK_GPIO0		320
-#define PCLK_GPIO1		321
-#define PCLK_GPIO2		322
-#define PCLK_GRF		329
-#define PCLK_I2C0		332
-#define PCLK_I2C1		333
-#define PCLK_I2C2		334
-#define PCLK_SPI		338
-#define PCLK_UART0		341
-#define PCLK_UART1		342
-#define PCLK_UART2		343
-#define PCLK_PWM		350
-#define PCLK_TIMER		353
-#define PCLK_HDMI		360
-#define PCLK_CPU		362
-#define PCLK_PERI		363
-#define PCLK_DDRUPCTL		364
-#define PCLK_WDT		368
-#define PCLK_ACODEC		369
-
-/* hclk gates */
-#define HCLK_OTG0		449
-#define HCLK_OTG1		450
-#define HCLK_NANDC		453
-#define HCLK_SDMMC		456
-#define HCLK_SDIO		457
-#define HCLK_EMMC		459
-#define HCLK_MAC		460
-#define HCLK_I2S		462
-#define HCLK_LCDC		465
-#define HCLK_ROM		467
-#define HCLK_VIO_BUS		472
-#define HCLK_VCODEC		476
-#define HCLK_CPU		477
-#define HCLK_PERI		478
-
-#define CLK_NR_CLKS		(HCLK_PERI + 1)
-
-/* soft-reset indices */
-#define SRST_CORE0		0
-#define SRST_CORE1		1
-#define SRST_CORE0_DBG		4
-#define SRST_CORE1_DBG		5
-#define SRST_CORE0_POR		8
-#define SRST_CORE1_POR		9
-#define SRST_L2C		12
-#define SRST_TOPDBG		13
-#define SRST_STRC_SYS_A		14
-#define SRST_PD_CORE_NIU	15
-
-#define SRST_TIMER2		16
-#define SRST_CPUSYS_H		17
-#define SRST_AHB2APB_H		19
-#define SRST_TIMER3		20
-#define SRST_INTMEM		21
-#define SRST_ROM		22
-#define SRST_PERI_NIU		23
-#define SRST_I2S		24
-#define SRST_DDR_PLL		25
-#define SRST_GPU_DLL		26
-#define SRST_TIMER0		27
-#define SRST_TIMER1		28
-#define SRST_CORE_DLL		29
-#define SRST_EFUSE_P		30
-#define SRST_ACODEC_P		31
-
-#define SRST_GPIO0		32
-#define SRST_GPIO1		33
-#define SRST_GPIO2		34
-#define SRST_UART0		39
-#define SRST_UART1		40
-#define SRST_UART2		41
-#define SRST_I2C0		43
-#define SRST_I2C1		44
-#define SRST_I2C2		45
-#define SRST_SFC		47
-
-#define SRST_PWM0		48
-#define SRST_DAP		51
-#define SRST_DAP_SYS		52
-#define SRST_GRF		55
-#define SRST_PERIPHSYS_A	57
-#define SRST_PERIPHSYS_H	58
-#define SRST_PERIPHSYS_P	59
-#define SRST_CPU_PERI		61
-#define SRST_EMEM_PERI		62
-#define SRST_USB_PERI		63
-
-#define SRST_DMA2		64
-#define SRST_MAC		66
-#define SRST_NANDC		68
-#define SRST_USBOTG0		69
-#define SRST_OTGC0		71
-#define SRST_USBOTG1		72
-#define SRST_OTGC1		74
-#define SRST_DDRMSCH		79
-
-#define SRST_MMC0		81
-#define SRST_SDIO		82
-#define SRST_EMMC		83
-#define SRST_SPI0		84
-#define SRST_WDT		86
-#define SRST_DDRPHY		88
-#define SRST_DDRPHY_P		89
-#define SRST_DDRCTRL		90
-#define SRST_DDRCTRL_P		91
-
-#define SRST_HDMI_P		96
-#define SRST_VIO_BUS_H		99
-#define SRST_UTMI0		103
-#define SRST_UTMI1		104
-#define SRST_USBPOR		105
-
-#define SRST_VCODEC_A		112
-#define SRST_VCODEC_H		113
-#define SRST_VIO1_A		114
-#define SRST_HEVC		115
-#define SRST_VCODEC_NIU_A	116
-#define SRST_LCDC1_A		117
-#define SRST_LCDC1_H		118
-#define SRST_LCDC1_D		119
-#define SRST_GPU		120
-#define SRST_GPU_NIU_A		122
-
-#define SRST_DBG_P		131
-
-#endif
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 1991aea..3672893 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -920,7 +920,7 @@
 	return NULL;
 }
 
-#define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable, validate, data, fn) \
+#define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable, valid, data, fn) \
 	static const void * __acpi_table_##name[]			\
 		__attribute__((unused))					\
 		 = { (void *) table_id,					\
diff --git a/include/linux/android_aid.h b/include/linux/android_aid.h
new file mode 100644
index 0000000..6f1fa179
--- /dev/null
+++ b/include/linux/android_aid.h
@@ -0,0 +1,28 @@
+/* include/linux/android_aid.h
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_ANDROID_AID_H
+#define _LINUX_ANDROID_AID_H
+
+/* AIDs that the kernel treats differently */
+#define AID_OBSOLETE_000 KGIDT_INIT(3001)  /* was NET_BT_ADMIN */
+#define AID_OBSOLETE_001 KGIDT_INIT(3002)  /* was NET_BT */
+#define AID_INET         KGIDT_INIT(3003)
+#define AID_NET_RAW      KGIDT_INIT(3004)
+#define AID_NET_ADMIN    KGIDT_INIT(3005)
+#define AID_NET_BW_STATS KGIDT_INIT(3006)  /* read bandwidth statistics */
+#define AID_NET_BW_ACCT  KGIDT_INIT(3007)  /* change bandwidth statistics accounting */
+
+#endif
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index 1b4d69f..140c296 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -163,6 +163,7 @@
 	wait_queue_head_t wb_waitq;
 
 	struct device *dev;
+	struct device *owner;
 
 	struct timer_list laptop_mode_wb_timer;
 
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index c82794f..89d3de3 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -24,6 +24,7 @@
 int bdi_register(struct backing_dev_info *bdi, struct device *parent,
 		const char *fmt, ...);
 int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
+int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner);
 void bdi_unregister(struct backing_dev_info *bdi);
 
 int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 3feb1b2..14cd6f7 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -156,6 +156,7 @@
 #define BCMA_CORE_DEFAULT		0xFFF
 
 #define BCMA_MAX_NR_CORES		16
+#define BCMA_CORE_SIZE			0x1000
 
 /* Chip IDs of PCIe devices */
 #define BCMA_CHIP_ID_BCM4313	0x4313
diff --git a/include/linux/bio.h b/include/linux/bio.h
index fbe47bc..42e4e3c 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -527,11 +527,14 @@
 int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css);
 int bio_associate_current(struct bio *bio);
 void bio_disassociate_task(struct bio *bio);
+void bio_clone_blkcg_association(struct bio *dst, struct bio *src);
 #else	/* CONFIG_BLK_CGROUP */
 static inline int bio_associate_blkcg(struct bio *bio,
 			struct cgroup_subsys_state *blkcg_css) { return 0; }
 static inline int bio_associate_current(struct bio *bio) { return -ENOENT; }
 static inline void bio_disassociate_task(struct bio *bio) { }
+static inline void bio_clone_blkcg_association(struct bio *dst,
+			struct bio *src) { }
 #endif	/* CONFIG_BLK_CGROUP */
 
 #ifdef CONFIG_HIGHMEM
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 1687557..a9562bb 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -197,6 +197,9 @@
 
 	/* for bidi */
 	struct request *next_rq;
+
+	ktime_t			lat_hist_io_start;
+	int			lat_hist_enabled;
 };
 
 static inline unsigned short req_get_ioprio(struct request *req)
@@ -890,7 +893,7 @@
 {
 	struct request_queue *q = rq->q;
 
-	if (unlikely(rq->cmd_type == REQ_TYPE_BLOCK_PC))
+	if (unlikely(rq->cmd_type != REQ_TYPE_FS))
 		return q->limits.max_hw_sectors;
 
 	if (!q->limits.chunk_sectors || (rq->cmd_flags & REQ_DISCARD))
@@ -1656,6 +1659,79 @@
 						struct writeback_control *);
 extern long bdev_direct_access(struct block_device *, sector_t,
 		void __pmem **addr, unsigned long *pfn, long size);
+
+/*
+ * X-axis for IO latency histogram support.
+ */
+static const u_int64_t latency_x_axis_us[] = {
+	100,
+	200,
+	300,
+	400,
+	500,
+	600,
+	700,
+	800,
+	900,
+	1000,
+	1200,
+	1400,
+	1600,
+	1800,
+	2000,
+	2500,
+	3000,
+	4000,
+	5000,
+	6000,
+	7000,
+	9000,
+	10000
+};
+
+#define BLK_IO_LAT_HIST_DISABLE         0
+#define BLK_IO_LAT_HIST_ENABLE          1
+#define BLK_IO_LAT_HIST_ZERO            2
+
+struct io_latency_state {
+	u_int64_t	latency_y_axis_read[ARRAY_SIZE(latency_x_axis_us) + 1];
+	u_int64_t	latency_reads_elems;
+	u_int64_t	latency_y_axis_write[ARRAY_SIZE(latency_x_axis_us) + 1];
+	u_int64_t	latency_writes_elems;
+};
+
+static inline void
+blk_update_latency_hist(struct io_latency_state *s,
+			int read,
+			u_int64_t delta_us)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(latency_x_axis_us); i++) {
+		if (delta_us < (u_int64_t)latency_x_axis_us[i]) {
+			if (read)
+				s->latency_y_axis_read[i]++;
+			else
+				s->latency_y_axis_write[i]++;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(latency_x_axis_us)) {
+		/* Overflowed the histogram */
+		if (read)
+			s->latency_y_axis_read[i]++;
+		else
+			s->latency_y_axis_write[i]++;
+	}
+	if (read)
+		s->latency_reads_elems++;
+	else
+		s->latency_writes_elems++;
+}
+
+void blk_zero_latency_hist(struct io_latency_state *s);
+ssize_t blk_latency_hist_show(struct io_latency_state *s, char *buf);
+
 #else /* CONFIG_BLOCK */
 
 struct block_device;
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 83d1926..4f6d29c 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -165,12 +165,13 @@
 void bpf_register_map_type(struct bpf_map_type_list *tl);
 
 struct bpf_prog *bpf_prog_get(u32 ufd);
+struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog);
 void bpf_prog_put(struct bpf_prog *prog);
 void bpf_prog_put_rcu(struct bpf_prog *prog);
 
 struct bpf_map *bpf_map_get_with_uref(u32 ufd);
 struct bpf_map *__bpf_map_get(struct fd f);
-void bpf_map_inc(struct bpf_map *map, bool uref);
+struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref);
 void bpf_map_put_with_uref(struct bpf_map *map);
 void bpf_map_put(struct bpf_map *map);
 
@@ -197,6 +198,10 @@
 static inline void bpf_prog_put(struct bpf_prog *prog)
 {
 }
+
+static inline void bpf_prog_put_rcu(struct bpf_prog *prog)
+{
+}
 #endif /* CONFIG_BPF_SYSCALL */
 
 /* verifier prototypes for helper functions called from eBPF programs */
diff --git a/include/linux/cache.h b/include/linux/cache.h
index 17e7e82..1be04f8 100644
--- a/include/linux/cache.h
+++ b/include/linux/cache.h
@@ -12,10 +12,24 @@
 #define SMP_CACHE_BYTES L1_CACHE_BYTES
 #endif
 
+/*
+ * __read_mostly is used to keep rarely changing variables out of frequently
+ * updated cachelines. If an architecture doesn't support it, ignore the
+ * hint.
+ */
 #ifndef __read_mostly
 #define __read_mostly
 #endif
 
+/*
+ * __ro_after_init is used to mark things that are read-only after init (i.e.
+ * after mark_rodata_ro() has been called). These are effectively read-only,
+ * but may get written to during init, so can't live in .rodata (via "const").
+ */
+#ifndef __ro_after_init
+#define __ro_after_init __attribute__((__section__(".data..ro_after_init")))
+#endif
+
 #ifndef ____cacheline_aligned
 #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
 #endif
diff --git a/include/linux/can/core.h b/include/linux/can/core.h
index a087500..df08a41 100644
--- a/include/linux/can/core.h
+++ b/include/linux/can/core.h
@@ -45,10 +45,9 @@
 extern int  can_proto_register(const struct can_proto *cp);
 extern void can_proto_unregister(const struct can_proto *cp);
 
-extern int  can_rx_register(struct net_device *dev, canid_t can_id,
-			    canid_t mask,
-			    void (*func)(struct sk_buff *, void *),
-			    void *data, char *ident);
+int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
+		    void (*func)(struct sk_buff *, void *),
+		    void *data, char *ident, struct sock *sk);
 
 extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
 			      canid_t mask,
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 735f9f8..5f52709 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -32,6 +32,7 @@
  * CAN common private data
  */
 struct can_priv {
+	struct net_device *dev;
 	struct can_device_stats can_stats;
 
 	struct can_bittiming bittiming, data_bittiming;
@@ -40,11 +41,14 @@
 	struct can_clock clock;
 
 	enum can_state state;
-	u32 ctrlmode;
-	u32 ctrlmode_supported;
+
+	/* CAN controller features - see include/uapi/linux/can/netlink.h */
+	u32 ctrlmode;		/* current options setting */
+	u32 ctrlmode_supported;	/* options that can be modified by netlink */
+	u32 ctrlmode_static;	/* static enabled options for driver/hardware */
 
 	int restart_ms;
-	struct timer_list restart_timer;
+	struct delayed_work restart_work;
 
 	int (*do_set_bittiming)(struct net_device *dev);
 	int (*do_set_data_bittiming)(struct net_device *dev);
@@ -108,6 +112,21 @@
 	return skb->len == CANFD_MTU;
 }
 
+/* helper to define static CAN controller features at device creation time */
+static inline void can_set_static_ctrlmode(struct net_device *dev,
+					   u32 static_mode)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	/* alloc_candev() succeeded => netdev_priv() is valid at this point */
+	priv->ctrlmode = static_mode;
+	priv->ctrlmode_static = static_mode;
+
+	/* override MTU which was set by default in can_setup()? */
+	if (static_mode & CAN_CTRLMODE_FD)
+		dev->mtu = CANFD_MTU;
+}
+
 /* get data length from can_dlc with sanitized can_dlc */
 u8 can_dlc2len(u8 can_dlc);
 
diff --git a/include/linux/capability.h b/include/linux/capability.h
index af9f0b9..b20ffe2 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -40,8 +40,6 @@
 struct dentry;
 struct user_namespace;
 
-struct user_namespace *current_user_ns(void);
-
 extern const kernel_cap_t __cap_empty_set;
 extern const kernel_cap_t __cap_init_eff_set;
 
@@ -214,6 +212,7 @@
 				      struct user_namespace *ns, int cap);
 extern bool capable(int cap);
 extern bool ns_capable(struct user_namespace *ns, int cap);
+extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
 #else
 static inline bool has_capability(struct task_struct *t, int cap)
 {
@@ -241,9 +240,15 @@
 {
 	return true;
 }
+static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
+{
+	return true;
+}
 #endif /* CONFIG_MULTIUSER */
+extern bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode);
 extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
 extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
+extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns);
 
 /* audit system wants to get cap info from files as well */
 extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h
index e55c08b..0abc561 100644
--- a/include/linux/ceph/osdmap.h
+++ b/include/linux/ceph/osdmap.h
@@ -49,7 +49,7 @@
 	case CEPH_POOL_TYPE_EC:
 		return false;
 	default:
-		BUG_ON(1);
+		BUG();
 	}
 }
 
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 788c7c4..8da2632 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -431,7 +431,6 @@
 	void (*css_reset)(struct cgroup_subsys_state *css);
 	void (*css_e_css_changed)(struct cgroup_subsys_state *css);
 
-	int (*allow_attach)(struct cgroup_taskset *tset);
 	int (*can_attach)(struct cgroup_taskset *tset);
 	void (*cancel_attach)(struct cgroup_taskset *tset);
 	void (*attach)(struct cgroup_taskset *tset);
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 70358b9..210ccc4 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -340,6 +340,26 @@
 }
 
 /**
+ * css_is_dying - test whether the specified css is dying
+ * @css: target css
+ *
+ * Test whether @css is in the process of offlining or already offline.  In
+ * most cases, ->css_online() and ->css_offline() callbacks should be
+ * enough; however, the actual offline operations are RCU delayed and this
+ * test returns %true also when @css is scheduled to be offlined.
+ *
+ * This is useful, for example, when the use case requires synchronous
+ * behavior with respect to cgroup removal.  cgroup removal schedules css
+ * offlining but the css can seem alive while the operation is being
+ * delayed.  If the delay affects user visible semantics, this test can be
+ * used to resolve the situation.
+ */
+static inline bool css_is_dying(struct cgroup_subsys_state *css)
+{
+	return !(css->flags & CSS_NO_REF) && percpu_ref_is_dying(&css->refcnt);
+}
+
+/**
  * css_put - put a css reference
  * @css: target css
  *
@@ -528,15 +548,24 @@
 	pr_cont_kernfs_path(cgrp->kn);
 }
 
-/*
- * Default Android check for whether the current process is allowed to move a
- * task across cgroups, either because CAP_SYS_NICE is set or because the uid
- * of the calling process is the same as the moved task or because we are
- * running as root.
- * Returns 0 if this is allowed, or -EACCES otherwise.
- */
-int subsys_cgroup_allow_attach(struct cgroup_taskset *tset);
+static inline void cgroup_init_kthreadd(void)
+{
+	/*
+	 * kthreadd is inherited by all kthreads, keep it in the root so
+	 * that the new kthreads are guaranteed to stay in the root until
+	 * initialization is finished.
+	 */
+	current->no_cgroup_migration = 1;
+}
 
+static inline void cgroup_kthread_ready(void)
+{
+	/*
+	 * This kthread finished initialization.  The creator should have
+	 * set PF_NO_SETAFFINITY if this kthread should stay in the root.
+	 */
+	current->no_cgroup_migration = 0;
+}
 
 #else /* !CONFIG_CGROUPS */
 
@@ -561,11 +590,9 @@
 
 static inline int cgroup_init_early(void) { return 0; }
 static inline int cgroup_init(void) { return 0; }
+static inline void cgroup_init_kthreadd(void) {}
+static inline void cgroup_kthread_ready(void) {}
 
-static inline int subsys_cgroup_allow_attach(void *tset)
-{
-	return -EINVAL;
-}
 #endif /* !CONFIG_CGROUPS */
 
 #endif /* _LINUX_CGROUP_H */
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index 1a96fda..e133705 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -26,6 +26,10 @@
 SUBSYS(cpuacct)
 #endif
 
+#if IS_ENABLED(CONFIG_CGROUP_SCHEDTUNE)
+SUBSYS(schedtune)
+#endif
+
 #if IS_ENABLED(CONFIG_BLK_CGROUP)
 SUBSYS(io)
 #endif
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 375cdb9..7cd0171 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -31,7 +31,6 @@
 #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
 #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
 #define CLK_RECALC_NEW_RATES	BIT(9) /* recalc rates after notifications */
-#define CLK_SET_RATE_UNGATE	BIT(10) /* clock needs to run to set rate */
 
 struct clk;
 struct clk_hw;
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index eeae401..287e698 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -251,7 +251,9 @@
 #endif
 #endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
 
-#if GCC_VERSION >= 50000
+#if GCC_VERSION >= 70000
+#define KASAN_ABI_VERSION 5
+#elif GCC_VERSION >= 50000
 #define KASAN_ABI_VERSION 4
 #elif GCC_VERSION >= 40902
 #define KASAN_ABI_VERSION 3
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
index d016a12..28ffa94 100644
--- a/include/linux/coredump.h
+++ b/include/linux/coredump.h
@@ -14,6 +14,7 @@
 extern int dump_skip(struct coredump_params *cprm, size_t nr);
 extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr);
 extern int dump_align(struct coredump_params *cprm, int align);
+extern void dump_truncate(struct coredump_params *cprm);
 #ifdef CONFIG_COREDUMP
 extern void do_coredump(const siginfo_t *siginfo);
 #else
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 7c73824..1c95ef5a 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -131,22 +131,16 @@
 		{ .notifier_call = fn, .priority = pri };	\
 	__register_cpu_notifier(&fn##_nb);			\
 }
-#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
-#define cpu_notifier(fn, pri)	do { (void)(fn); } while (0)
-#define __cpu_notifier(fn, pri)	do { (void)(fn); } while (0)
-#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
 
-#ifdef CONFIG_HOTPLUG_CPU
 extern int register_cpu_notifier(struct notifier_block *nb);
 extern int __register_cpu_notifier(struct notifier_block *nb);
 extern void unregister_cpu_notifier(struct notifier_block *nb);
 extern void __unregister_cpu_notifier(struct notifier_block *nb);
-#else
 
-#ifndef MODULE
-extern int register_cpu_notifier(struct notifier_block *nb);
-extern int __register_cpu_notifier(struct notifier_block *nb);
-#else
+#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
+#define cpu_notifier(fn, pri)	do { (void)(fn); } while (0)
+#define __cpu_notifier(fn, pri)	do { (void)(fn); } while (0)
+
 static inline int register_cpu_notifier(struct notifier_block *nb)
 {
 	return 0;
@@ -156,7 +150,6 @@
 {
 	return 0;
 }
-#endif
 
 static inline void unregister_cpu_notifier(struct notifier_block *nb)
 {
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 3ac0162..b144e74 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -107,6 +107,22 @@
 	 */
 	struct rw_semaphore	rwsem;
 
+
+	/*
+	 * Fast switch flags:
+	 * - fast_switch_possible should be set by the driver if it can
+	 *   guarantee that frequency can be changed on any CPU sharing the
+	 *   policy and that the change will affect all of the policy CPUs then.
+	 * - fast_switch_enabled is to be set by governors that support fast
+	 *   freqnency switching with the help of cpufreq_enable_fast_switch().
+	 */
+	bool                    fast_switch_possible;
+	bool                    fast_switch_enabled;
+
+	/* Cached frequency lookup from cpufreq_driver_resolve_freq. */
+	unsigned int cached_target_freq;
+	int cached_resolved_idx;
+
 	/* Synchronization for frequency transitions */
 	bool			transition_ongoing; /* Tracks transition status */
 	spinlock_t		transition_lock;
@@ -160,6 +176,7 @@
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
 int cpufreq_update_policy(unsigned int cpu);
 bool have_governor_per_policy(void);
+bool cpufreq_driver_is_slow(void);
 struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy);
 #else
 static inline unsigned int cpufreq_get(unsigned int cpu)
@@ -317,6 +334,14 @@
  */
 #define CPUFREQ_NEED_INITIAL_FREQ_CHECK	(1 << 5)
 
+/*
+ * Indicates that it is safe to call cpufreq_driver_target from
+ * non-interruptable context in scheduler hot paths.  Drivers must
+ * opt-in to this flag, as the safe default is that they might sleep
+ * or be too slow for hot path use.
+ */
+#define CPUFREQ_DRIVER_FAST		(1 << 6)
+
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
 
@@ -462,6 +487,8 @@
 int __cpufreq_driver_target(struct cpufreq_policy *policy,
 				   unsigned int target_freq,
 				   unsigned int relation);
+unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy,
+					 unsigned int target_freq);
 int cpufreq_register_governor(struct cpufreq_governor *governor);
 void cpufreq_unregister_governor(struct cpufreq_governor *governor);
 
@@ -490,8 +517,45 @@
 #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE)
 extern struct cpufreq_governor cpufreq_gov_interactive;
 #define CPUFREQ_DEFAULT_GOVERNOR	(&cpufreq_gov_interactive)
+#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_SCHED)
+extern struct cpufreq_governor cpufreq_gov_sched;
+#define CPUFREQ_DEFAULT_GOVERNOR	(&cpufreq_gov_sched)
+#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL)
+extern struct cpufreq_governor cpufreq_gov_schedutil;
+#define CPUFREQ_DEFAULT_GOVERNOR	(&cpufreq_gov_schedutil)
 #endif
 
+static inline void cpufreq_policy_apply_limits(struct cpufreq_policy *policy)
+{
+	if (policy->max < policy->cur)
+		__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
+	else if (policy->min > policy->cur)
+		__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
+}
+
+/* Governor attribute set */
+struct gov_attr_set {
+	struct kobject kobj;
+	struct list_head policy_list;
+	struct mutex update_lock;
+	int usage_count;
+};
+
+/* sysfs ops for cpufreq governors */
+extern const struct sysfs_ops governor_sysfs_ops;
+
+void gov_attr_set_init(struct gov_attr_set *attr_set, struct list_head *list_node);
+void gov_attr_set_get(struct gov_attr_set *attr_set, struct list_head *list_node);
+unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *list_node);
+
+/* Governor sysfs attribute */
+struct governor_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct gov_attr_set *attr_set, char *buf);
+	ssize_t (*store)(struct gov_attr_set *attr_set, const char *buf,
+			 size_t count);
+};
+
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
  *********************************************************************/
@@ -619,4 +683,8 @@
 int cpufreq_generic_init(struct cpufreq_policy *policy,
 		struct cpufreq_frequency_table *table,
 		unsigned int transition_latency);
+
+struct sched_domain;
+unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu);
+unsigned long cpufreq_scale_max_freq_capacity(int cpu);
 #endif /* _LINUX_CPUFREQ_H */
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 786ad32..6eae157 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -204,7 +204,7 @@
 #endif
 
 /* kernel/sched/idle.c */
-extern void sched_idle_set_state(struct cpuidle_state *idle_state);
+extern void sched_idle_set_state(struct cpuidle_state *idle_state, int index);
 extern void default_idle_call(void);
 
 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 59915ea..a91b3b7 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -556,7 +556,7 @@
 static inline int cpumask_parse_user(const char __user *buf, int len,
 				     struct cpumask *dstp)
 {
-	return bitmap_parse_user(buf, len, cpumask_bits(dstp), nr_cpu_ids);
+	return bitmap_parse_user(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
@@ -571,7 +571,7 @@
 				     struct cpumask *dstp)
 {
 	return bitmap_parselist_user(buf, len, cpumask_bits(dstp),
-				     nr_cpu_ids);
+				     nr_cpumask_bits);
 }
 
 /**
@@ -586,7 +586,7 @@
 	char *nl = strchr(buf, '\n');
 	unsigned int len = nl ? (unsigned int)(nl - buf) : strlen(buf);
 
-	return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpu_ids);
+	return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
@@ -598,7 +598,7 @@
  */
 static inline int cpulist_parse(const char *buf, struct cpumask *dstp)
 {
-	return bitmap_parselist(buf, cpumask_bits(dstp), nr_cpu_ids);
+	return bitmap_parselist(buf, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 8d70e13..257db64 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -377,7 +377,10 @@
 #ifdef CONFIG_USER_NS
 #define current_user_ns()	(current_cred_xxx(user_ns))
 #else
-#define current_user_ns()	(&init_user_ns)
+static inline struct user_namespace *current_user_ns(void)
+{
+	return &init_user_ns;
+}
 #endif
 
 
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index da48880..2043af2 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -593,4 +593,28 @@
 		return dentry;
 }
 
+static inline struct inode *vfs_select_inode(struct dentry *dentry,
+					     unsigned open_flags)
+{
+	struct inode *inode = d_inode(dentry);
+
+	if (inode && unlikely(dentry->d_flags & DCACHE_OP_SELECT_INODE))
+		inode = dentry->d_op->d_select_inode(dentry, open_flags);
+
+	return inode;
+}
+
+/**
+ * d_real_inode - Return the real inode
+ * @dentry: The dentry to query
+ *
+ * If dentry is on an union/overlay, then return the underlying, real inode.
+ * Otherwise return d_inode().
+ */
+static inline struct inode *d_real_inode(struct dentry *dentry)
+{
+	return d_backing_inode(d_real(dentry));
+}
+
+
 #endif	/* __LINUX_DCACHE_H */
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 61d042b..6844929 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -163,6 +163,7 @@
 	__u64			 dreq_isr;
 	__u64			 dreq_gsr;
 	__be32			 dreq_service;
+	spinlock_t		 dreq_lock;
 	struct list_head	 dreq_featneg;
 	__u32			 dreq_timestamp_echo;
 	__u32			 dreq_timestamp_time;
diff --git a/include/linux/devfreq-event.h b/include/linux/devfreq-event.h
index 0a83a1e..4db00b0 100644
--- a/include/linux/devfreq-event.h
+++ b/include/linux/devfreq-event.h
@@ -148,11 +148,6 @@
 	return -EINVAL;
 }
 
-static inline void *devfreq_event_get_drvdata(struct devfreq_event_dev *edev)
-{
-	return ERR_PTR(-EINVAL);
-}
-
 static inline struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(
 					struct device *dev, int index)
 {
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 7c8a0c6..f3f87db 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -415,11 +415,12 @@
 
 struct queue_limits *dm_get_queue_limits(struct mapped_device *md);
 
-/*
- * Lock functions.
- */
 void dm_lock_md_type(struct mapped_device *md);
 void dm_unlock_md_type(struct mapped_device *md);
+void dm_set_md_type(struct mapped_device *md, unsigned type);
+unsigned dm_get_md_type(struct mapped_device *md);
+int dm_setup_md_queue(struct mapped_device *md);
+unsigned dm_table_get_type(struct dm_table *t);
 
 /*
  * Geometry functions.
diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
index e0ee0b3..358a4db 100644
--- a/include/linux/devpts_fs.h
+++ b/include/linux/devpts_fs.h
@@ -15,38 +15,24 @@
 
 #include <linux/errno.h>
 
+struct pts_fs_info;
+
 #ifdef CONFIG_UNIX98_PTYS
 
-int devpts_new_index(struct inode *ptmx_inode);
-void devpts_kill_index(struct inode *ptmx_inode, int idx);
-void devpts_add_ref(struct inode *ptmx_inode);
-void devpts_del_ref(struct inode *ptmx_inode);
+/* Look up a pts fs info and get a ref to it */
+struct pts_fs_info *devpts_get_ref(struct inode *, struct file *);
+void devpts_put_ref(struct pts_fs_info *);
+
+int devpts_new_index(struct pts_fs_info *);
+void devpts_kill_index(struct pts_fs_info *, int);
+
 /* mknod in devpts */
-struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
-		void *priv);
+struct inode *devpts_pty_new(struct pts_fs_info *, dev_t, int, void *);
 /* get private structure */
 void *devpts_get_priv(struct inode *pts_inode);
 /* unlink */
 void devpts_pty_kill(struct inode *inode);
 
-#else
-
-/* Dummy stubs in the no-pty case */
-static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
-static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
-static inline void devpts_add_ref(struct inode *ptmx_inode) { }
-static inline void devpts_del_ref(struct inode *ptmx_inode) { }
-static inline struct inode *devpts_pty_new(struct inode *ptmx_inode,
-		dev_t device, int index, void *priv)
-{
-	return ERR_PTR(-EINVAL);
-}
-static inline void *devpts_get_priv(struct inode *pts_inode)
-{
-	return NULL;
-}
-static inline void devpts_pty_kill(struct inode *inode) { }
-
 #endif
 
 
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 9654923..c47c68e 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -401,7 +401,6 @@
  * 	since the enum dma_transfer_direction is not defined as bits for each
  * 	type of direction, the dma controller should fill (1 << <TYPE>) and same
  * 	should be checked by controller as well
- * @max_burst: max burst capability per-transfer
  * @cmd_pause: true, if pause and thereby resume is supported
  * @cmd_terminate: true, if terminate cmd is supported
  * @residue_granularity: granularity of the reported transfer residue
@@ -412,7 +411,6 @@
 	u32 src_addr_widths;
 	u32 dst_addr_widths;
 	u32 directions;
-	u32 max_burst;
 	bool cmd_pause;
 	bool cmd_terminate;
 	enum dma_residue_granularity residue_granularity;
@@ -629,7 +627,6 @@
  * 	the enum dma_transfer_direction is not defined as bits for
  * 	each type of direction, the dma controller should fill (1 <<
  * 	<TYPE>) and same should be checked by controller as well
- * @max_burst: max burst capability per-transfer
  * @residue_granularity: granularity of the transfer residue reported
  *	by tx_status
  * @device_alloc_chan_resources: allocate resources and return the
@@ -684,7 +681,6 @@
 	u32 src_addr_widths;
 	u32 dst_addr_widths;
 	u32 directions;
-	u32 max_burst;
 	enum dma_residue_granularity residue_granularity;
 
 	int (*device_alloc_chan_resources)(struct dma_chan *chan);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 49e77d1..333d0ca 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -299,7 +299,7 @@
 	void *open_protocol_information;
 	void *protocols_per_handle;
 	void *locate_handle_buffer;
-	void *locate_protocol;
+	efi_status_t (*locate_protocol)(efi_guid_t *, void *, void **);
 	void *install_multiple_protocol_interfaces;
 	void *uninstall_multiple_protocol_interfaces;
 	void *calculate_crc32;
@@ -599,9 +599,9 @@
 #define EFI_PROPERTIES_TABLE_GUID \
     EFI_GUID(  0x880aaca3, 0x4adc, 0x4a04, 0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5 )
 
-#define LINUX_EFI_LOADER_ENTRY_GUID \
-	EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, \
-		 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
+#define EFI_RNG_PROTOCOL_GUID \
+	EFI_GUID(0x3152bca5, 0xeade, 0x433d, \
+		 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
 
 typedef struct {
 	efi_guid_t guid;
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index 25c6324..3d6e6ce 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -284,6 +284,12 @@
 #define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry))
 
 /*
+ * F2FS uses 4 bytes to represent block address. As a result, supported size of
+ * disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments.
+ */
+#define F2FS_MAX_SEGMENT       ((16 * 1024 * 1024) / 2)
+
+/*
  * Note that f2fs_sit_entry->vblocks has the following bit-field information.
  * [15:10] : allocation type such as CURSEG_XXXX_TYPE
  * [9:0] : valid block count
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 76ce329..1b48d9c 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -3,6 +3,12 @@
 
 #include <uapi/linux/fcntl.h>
 
+/* list of all valid flags for the open/openat flags argument: */
+#define VALID_OPEN_FLAGS \
+	(O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \
+	 O_APPEND | O_NDELAY | O_NONBLOCK | O_NDELAY | __O_SYNC | O_DSYNC | \
+	 FASYNC	| O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \
+	 O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE)
 
 #ifndef force_o_largefile
 #define force_o_largefile() (BITS_PER_LONG != 32)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 5110d42..ccb98b4 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -421,7 +421,11 @@
 }
 #endif /* CONFIG_DEBUG_SET_MODULE_RONX */
 
-int sk_filter(struct sock *sk, struct sk_buff *skb);
+int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap);
+static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
+{
+	return sk_filter_trim_cap(sk, skb, 1);
+}
 
 int bpf_prog_select_runtime(struct bpf_prog *fp);
 void bpf_prog_free(struct bpf_prog *fp);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ab3d8d9..bff4ce5 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -226,6 +226,7 @@
 #define ATTR_KILL_PRIV	(1 << 14)
 #define ATTR_OPEN	(1 << 15) /* Truncating from open(O_TRUNC) */
 #define ATTR_TIMES_SET	(1 << 16)
+#define ATTR_TOUCH	(1 << 17)
 
 /*
  * Whiteout is represented by a char device.  The following constants define the
@@ -679,6 +680,11 @@
 	void			*i_private; /* fs or device private pointer */
 };
 
+static inline unsigned int i_blocksize(const struct inode *node)
+{
+	return (1 << node->i_blkbits);
+}
+
 static inline int inode_unhashed(struct inode *inode)
 {
 	return hlist_unhashed(&inode->i_hash);
@@ -710,6 +716,31 @@
 	I_MUTEX_PARENT2,
 };
 
+static inline void inode_lock(struct inode *inode)
+{
+	mutex_lock(&inode->i_mutex);
+}
+
+static inline void inode_unlock(struct inode *inode)
+{
+	mutex_unlock(&inode->i_mutex);
+}
+
+static inline int inode_trylock(struct inode *inode)
+{
+	return mutex_trylock(&inode->i_mutex);
+}
+
+static inline int inode_is_locked(struct inode *inode)
+{
+	return mutex_is_locked(&inode->i_mutex);
+}
+
+static inline void inode_lock_nested(struct inode *inode, unsigned subclass)
+{
+	mutex_lock_nested(&inode->i_mutex, subclass);
+}
+
 void lock_two_nondirectories(struct inode *, struct inode*);
 void unlock_two_nondirectories(struct inode *, struct inode*);
 
@@ -1513,13 +1544,21 @@
  * VFS helper functions..
  */
 extern int vfs_create(struct inode *, struct dentry *, umode_t, bool);
+extern int vfs_create2(struct vfsmount *, struct inode *, struct dentry *, umode_t, bool);
 extern int vfs_mkdir(struct inode *, struct dentry *, umode_t);
+extern int vfs_mkdir2(struct vfsmount *, struct inode *, struct dentry *, umode_t);
 extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
+extern int vfs_mknod2(struct vfsmount *, struct inode *, struct dentry *, umode_t, dev_t);
 extern int vfs_symlink(struct inode *, struct dentry *, const char *);
+extern int vfs_symlink2(struct vfsmount *, struct inode *, struct dentry *, const char *);
 extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **);
+extern int vfs_link2(struct vfsmount *, struct dentry *, struct inode *, struct dentry *, struct inode **);
 extern int vfs_rmdir(struct inode *, struct dentry *);
+extern int vfs_rmdir2(struct vfsmount *, struct inode *, struct dentry *);
 extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
+extern int vfs_unlink2(struct vfsmount *, struct inode *, struct dentry *, struct inode **);
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int);
+extern int vfs_rename2(struct vfsmount *, struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int);
 extern int vfs_whiteout(struct inode *, struct dentry *);
 
 /*
@@ -1645,6 +1684,7 @@
 	struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
 	const char * (*follow_link) (struct dentry *, void **);
 	int (*permission) (struct inode *, int);
+	int (*permission2) (struct vfsmount *, struct inode *, int);
 	struct posix_acl * (*get_acl)(struct inode *, int);
 
 	int (*readlink) (struct dentry *, char __user *,int);
@@ -1662,6 +1702,7 @@
 	int (*rename2) (struct inode *, struct dentry *,
 			struct inode *, struct dentry *, unsigned int);
 	int (*setattr) (struct dentry *, struct iattr *);
+	int (*setattr2) (struct vfsmount *, struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
@@ -1707,9 +1748,13 @@
 	int (*unfreeze_fs) (struct super_block *);
 	int (*statfs) (struct dentry *, struct kstatfs *);
 	int (*remount_fs) (struct super_block *, int *, char *);
+	int (*remount_fs2) (struct vfsmount *, struct super_block *, int *, char *);
+	void *(*clone_mnt_data) (void *);
+	void (*copy_mnt_data) (void *, void *);
 	void (*umount_begin) (struct super_block *);
 
 	int (*show_options)(struct seq_file *, struct dentry *);
+	int (*show_options2)(struct vfsmount *,struct seq_file *, struct dentry *);
 	int (*show_devname)(struct seq_file *, struct dentry *);
 	int (*show_path)(struct seq_file *, struct dentry *);
 	int (*show_stats)(struct seq_file *, struct dentry *);
@@ -1941,6 +1986,9 @@
 #define FS_RENAME_DOES_D_MOVE	32768	/* FS will handle d_move() during rename() internally. */
 	struct dentry *(*mount) (struct file_system_type *, int,
 		       const char *, void *);
+	struct dentry *(*mount2) (struct vfsmount *, struct file_system_type *, int,
+			       const char *, void *);
+	void *(*alloc_mnt_data) (void);
 	void (*kill_sb) (struct super_block *);
 	struct module *owner;
 	struct file_system_type * next;
@@ -2220,6 +2268,8 @@
 extern long vfs_truncate(struct path *, loff_t);
 extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
 		       struct file *filp);
+extern int do_truncate2(struct vfsmount *, struct dentry *, loff_t start,
+			unsigned int time_attrs, struct file *filp);
 extern int vfs_fallocate(struct file *file, int mode, loff_t offset,
 			loff_t len);
 extern long do_sys_open(int dfd, const char __user *filename, int flags,
@@ -2444,8 +2494,11 @@
 extern sector_t bmap(struct inode *, sector_t);
 #endif
 extern int notify_change(struct dentry *, struct iattr *, struct inode **);
+extern int notify_change2(struct vfsmount *, struct dentry *, struct iattr *, struct inode **);
 extern int inode_permission(struct inode *, int);
+extern int inode_permission2(struct vfsmount *, struct inode *, int);
 extern int __inode_permission(struct inode *, int);
+extern int __inode_permission2(struct vfsmount *, struct inode *, int);
 extern int generic_permission(struct inode *, int);
 extern int __check_sticky(struct inode *dir, struct inode *inode);
 
@@ -3029,8 +3082,8 @@
 }
 static inline bool dir_relax(struct inode *inode)
 {
-	mutex_unlock(&inode->i_mutex);
-	mutex_lock(&inode->i_mutex);
+	inode_unlock(inode);
+	inode_lock(inode);
 	return !IS_DEADDIR(inode);
 }
 
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 604e152..eb19bf2 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -360,6 +360,7 @@
 #define FSCACHE_OBJECT_IS_AVAILABLE	5	/* T if object has become active */
 #define FSCACHE_OBJECT_RETIRED		6	/* T if object was retired on relinquishment */
 #define FSCACHE_OBJECT_KILLED_BY_CACHE	7	/* T if object was killed by the cache */
+#define FSCACHE_OBJECT_RUN_AFTER_DEAD	8	/* T if object has been dispatched after death */
 
 	struct list_head	cache_link;	/* link in cache->object_list */
 	struct hlist_node	cookie_link;	/* link in cookie->backing_objects */
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 533c440..850d882 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -148,6 +148,7 @@
 	#define FS_PRIO_1	1 /* fanotify content based access control */
 	#define FS_PRIO_2	2 /* fanotify pre-content access */
 	unsigned int priority;
+	bool shutdown;		/* group is being shut down, don't queue more events */
 
 	/* stores all fastpath marks assoc with this group so they can be cleaned on unregister */
 	struct mutex mark_mutex;	/* protect marks_list */
@@ -179,7 +180,6 @@
 			spinlock_t access_lock;
 			struct list_head access_list;
 			wait_queue_head_t access_waitq;
-			atomic_t bypass_perm;
 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
 			int f_flags;
 			unsigned int max_marks;
@@ -308,6 +308,8 @@
 extern void fsnotify_get_group(struct fsnotify_group *group);
 /* drop reference on a group from fsnotify_alloc_group */
 extern void fsnotify_put_group(struct fsnotify_group *group);
+/* group destruction begins, stop queuing new events */
+extern void fsnotify_group_stop_queueing(struct fsnotify_group *group);
 /* destroy group */
 extern void fsnotify_destroy_group(struct fsnotify_group *group);
 /* fasync handler function */
@@ -320,8 +322,6 @@
 			      struct fsnotify_event *event,
 			      int (*merge)(struct list_head *,
 					   struct fsnotify_event *));
-/* Remove passed event from groups notification queue */
-extern void fsnotify_remove_event(struct fsnotify_group *group, struct fsnotify_event *event);
 /* true if the group notification queue is empty */
 extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
 /* return, but do not dequeue the first event on the notification queue */
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 847cc1d..5012fcd 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -742,11 +742,9 @@
 #if defined(CONFIG_BLK_DEV_INTEGRITY)
 extern void blk_integrity_add(struct gendisk *);
 extern void blk_integrity_del(struct gendisk *);
-extern void blk_integrity_revalidate(struct gendisk *);
 #else	/* CONFIG_BLK_DEV_INTEGRITY */
 static inline void blk_integrity_add(struct gendisk *disk) { }
 static inline void blk_integrity_del(struct gendisk *disk) { }
-static inline void blk_integrity_revalidate(struct gendisk *disk) { }
 #endif	/* CONFIG_BLK_DEV_INTEGRITY */
 
 #else /* CONFIG_BLOCK */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 685c262..b0eb064 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -96,9 +96,7 @@
 				struct address_space *mapping,
 				pgoff_t idx, unsigned long address);
 
-#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
 pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud);
-#endif
 
 extern int hugepages_treat_as_movable;
 extern int sysctl_hugetlb_shm_group;
diff --git a/include/linux/i8042.h b/include/linux/i8042.h
index 0f9bafa..d98780c 100644
--- a/include/linux/i8042.h
+++ b/include/linux/i8042.h
@@ -62,7 +62,6 @@
 void i8042_lock_chip(void);
 void i8042_unlock_chip(void);
 int i8042_command(unsigned char *param, int command);
-bool i8042_check_port_owner(const struct serio *);
 int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
 					struct serio *serio));
 int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
@@ -83,11 +82,6 @@
 	return -ENODEV;
 }
 
-static inline bool i8042_check_port_owner(const struct serio *serio)
-{
-	return false;
-}
-
 static inline int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
 					struct serio *serio))
 {
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 67ce5bd..19db03d 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -616,15 +616,16 @@
 static inline netdev_features_t vlan_features_check(const struct sk_buff *skb,
 						    netdev_features_t features)
 {
-	if (skb_vlan_tagged_multi(skb))
-		features = netdev_intersect_features(features,
-						     NETIF_F_SG |
-						     NETIF_F_HIGHDMA |
-						     NETIF_F_FRAGLIST |
-						     NETIF_F_GEN_CSUM |
-						     NETIF_F_HW_VLAN_CTAG_TX |
-						     NETIF_F_HW_VLAN_STAG_TX);
-
+	if (skb_vlan_tagged_multi(skb)) {
+		/* In the case of multi-tagged packets, use a direct mask
+		 * instead of using netdev_interesect_features(), to make
+		 * sure that only devices supporting NETIF_F_HW_CSUM will
+		 * have checksum offloading support.
+		 */
+		features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
+			    NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX |
+			    NETIF_F_HW_VLAN_STAG_TX;
+	}
 	return features;
 }
 
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h
index 7c27fa1..795852d 100644
--- a/include/linux/inet_diag.h
+++ b/include/linux/inet_diag.h
@@ -37,7 +37,7 @@
 		      struct sk_buff *skb, const struct inet_diag_req_v2 *req,
 		      struct user_namespace *user_ns,
 		      u32 pid, u32 seq, u16 nlmsg_flags,
-		      const struct nlmsghdr *unlh);
+		      const struct nlmsghdr *unlh, bool net_admin);
 void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb,
 			 struct netlink_callback *cb,
 			 const struct inet_diag_req_v2 *r,
diff --git a/include/linux/init.h b/include/linux/init.h
index b449f37..aedb254 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -142,6 +142,10 @@
 void __init load_default_modules(void);
 int __init init_rootfs(void);
 
+#ifdef CONFIG_DEBUG_RODATA
+void mark_rodata_ro(void);
+#endif
+
 extern void (*late_time_init)(void);
 
 extern bool initcall_debug;
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 2d9b650..23e129e 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -153,8 +153,8 @@
 #define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
 #define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
 #define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
-#define DMA_TLB_IIRG(type) ((type >> 60) & 7)
-#define DMA_TLB_IAIG(val) (((val) >> 57) & 7)
+#define DMA_TLB_IIRG(type) ((type >> 60) & 3)
+#define DMA_TLB_IAIG(val) (((val) >> 57) & 3)
 #define DMA_TLB_READ_DRAIN (((u64)1) << 49)
 #define DMA_TLB_WRITE_DRAIN (((u64)1) << 48)
 #define DMA_TLB_DID(id)	(((u64)((id) & 0xffff)) << 32)
@@ -164,9 +164,9 @@
 
 /* INVALID_DESC */
 #define DMA_CCMD_INVL_GRANU_OFFSET  61
-#define DMA_ID_TLB_GLOBAL_FLUSH	(((u64)1) << 3)
-#define DMA_ID_TLB_DSI_FLUSH	(((u64)2) << 3)
-#define DMA_ID_TLB_PSI_FLUSH	(((u64)3) << 3)
+#define DMA_ID_TLB_GLOBAL_FLUSH	(((u64)1) << 4)
+#define DMA_ID_TLB_DSI_FLUSH	(((u64)2) << 4)
+#define DMA_ID_TLB_PSI_FLUSH	(((u64)3) << 4)
 #define DMA_ID_TLB_READ_DRAIN	(((u64)1) << 7)
 #define DMA_ID_TLB_WRITE_DRAIN	(((u64)1) << 6)
 #define DMA_ID_TLB_DID(id)	(((u64)((id & 0xffff) << 16)))
@@ -316,8 +316,8 @@
 #define QI_DEV_EIOTLB_SIZE	(((u64)1) << 11)
 #define QI_DEV_EIOTLB_GLOB(g)	((u64)g)
 #define QI_DEV_EIOTLB_PASID(p)	(((u64)p) << 32)
-#define QI_DEV_EIOTLB_SID(sid)	((u64)((sid) & 0xffff) << 32)
-#define QI_DEV_EIOTLB_QDEP(qd)	(((qd) & 0x1f) << 16)
+#define QI_DEV_EIOTLB_SID(sid)	((u64)((sid) & 0xffff) << 16)
+#define QI_DEV_EIOTLB_QDEP(qd)	((u64)((qd) & 0x1f) << 4)
 #define QI_DEV_EIOTLB_MAX_INVS	32
 
 #define QI_PGRP_IDX(idx)	(((u64)(idx)) << 55)
@@ -429,6 +429,7 @@
 	struct page_req_dsc *prq;
 	unsigned char prq_name[16];    /* Name for PRQ interrupt */
 	struct idr pasid_idr;
+	u32 pasid_max;
 #endif
 	struct q_inval  *qi;            /* Queued invalidation info */
 	u32 *iommu_state; /* Store iommu states between suspend and resume.*/
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index ce77726..a0fc3cf 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -18,6 +18,7 @@
 	__s32		dad_transmits;
 	__s32		rtr_solicits;
 	__s32		rtr_solicit_interval;
+	__s32		rtr_solicit_max_interval;
 	__s32		rtr_solicit_delay;
 	__s32		force_mld_version;
 	__s32		mldv1_unsolicited_report_interval;
@@ -36,6 +37,7 @@
 	__s32		accept_ra_rtr_pref;
 	__s32		rtr_probe_interval;
 #ifdef CONFIG_IPV6_ROUTE_INFO
+	__s32		accept_ra_rt_info_min_plen;
 	__s32		accept_ra_rt_info_max_plen;
 #endif
 #endif
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 3c1c967..f7cade0 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -916,6 +916,16 @@
 static inline void irq_gc_unlock(struct irq_chip_generic *gc) { }
 #endif
 
+/*
+ * The irqsave variants are for usage in non interrupt code. Do not use
+ * them in irq_chip callbacks. Use irq_gc_lock() instead.
+ */
+#define irq_gc_lock_irqsave(gc, flags)	\
+	raw_spin_lock_irqsave(&(gc)->lock, flags)
+
+#define irq_gc_unlock_irqrestore(gc, flags)	\
+	raw_spin_unlock_irqrestore(&(gc)->lock, flags)
+
 static inline void irq_reg_writel(struct irq_chip_generic *gc,
 				  u32 val, int reg_offset)
 {
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index d5d798b..54048f3 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -218,7 +218,7 @@
 #define GITS_BASER_TYPE_SHIFT		(56)
 #define GITS_BASER_TYPE(r)		(((r) >> GITS_BASER_TYPE_SHIFT) & 7)
 #define GITS_BASER_ENTRY_SIZE_SHIFT	(48)
-#define GITS_BASER_ENTRY_SIZE(r)	((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0xff) + 1)
+#define GITS_BASER_ENTRY_SIZE(r)	((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
 #define GITS_BASER_NonShareable		(0UL << 10)
 #define GITS_BASER_InnerShareable	(1UL << 10)
 #define GITS_BASER_OuterShareable	(2UL << 10)
@@ -301,7 +301,7 @@
 #define ICC_SGI1R_AFFINITY_1_SHIFT	16
 #define ICC_SGI1R_AFFINITY_1_MASK	(0xff << ICC_SGI1R_AFFINITY_1_SHIFT)
 #define ICC_SGI1R_SGI_ID_SHIFT		24
-#define ICC_SGI1R_SGI_ID_MASK		(0xff << ICC_SGI1R_SGI_ID_SHIFT)
+#define ICC_SGI1R_SGI_ID_MASK		(0xfULL << ICC_SGI1R_SGI_ID_SHIFT)
 #define ICC_SGI1R_AFFINITY_2_SHIFT	32
 #define ICC_SGI1R_AFFINITY_2_MASK	(0xffULL << ICC_SGI1R_AFFINITY_1_SHIFT)
 #define ICC_SGI1R_IRQ_ROUTING_MODE_BIT	40
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 0536524..6890446 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,13 +117,18 @@
 
 #include <linux/atomic.h>
 
+#ifdef HAVE_JUMP_LABEL
+
 static inline int static_key_count(struct static_key *key)
 {
-	return atomic_read(&key->enabled);
+	/*
+	 * -1 means the first static_key_slow_inc() is in progress.
+	 *  static_key_enabled() must return true, so return 1 here.
+	 */
+	int n = atomic_read(&key->enabled);
+	return n >= 0 ? n : 1;
 }
 
-#ifdef HAVE_JUMP_LABEL
-
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
 #define JUMP_TYPE_MASK	1UL
@@ -162,6 +167,11 @@
 
 #else  /* !HAVE_JUMP_LABEL */
 
+static inline int static_key_count(struct static_key *key)
+{
+	return atomic_read(&key->enabled);
+}
+
 static __always_inline void jump_label_init(void)
 {
 	static_key_initialized = true;
diff --git a/include/linux/jump_label_ratelimit.h b/include/linux/jump_label_ratelimit.h
index 089f70f..23da3af 100644
--- a/include/linux/jump_label_ratelimit.h
+++ b/include/linux/jump_label_ratelimit.h
@@ -14,6 +14,7 @@
 
 #ifdef HAVE_JUMP_LABEL
 extern void static_key_slow_dec_deferred(struct static_key_deferred *key);
+extern void static_key_deferred_flush(struct static_key_deferred *key);
 extern void
 jump_label_rate_limit(struct static_key_deferred *key, unsigned long rl);
 
@@ -26,6 +27,10 @@
 	STATIC_KEY_CHECK_USE();
 	static_key_slow_dec(&key->key);
 }
+static inline void static_key_deferred_flush(struct static_key_deferred *key)
+{
+	STATIC_KEY_CHECK_USE();
+}
 static inline void
 jump_label_rate_limit(struct static_key_deferred *key,
 		unsigned long rl)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2955e67..50220ca 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -202,26 +202,26 @@
 
 /**
  * abs - return absolute value of an argument
- * @x: the value.  If it is unsigned type, it is converted to signed type first
- *   (s64, long or int depending on its size).
+ * @x: the value.  If it is unsigned type, it is converted to signed type first.
+ *     char is treated as if it was signed (regardless of whether it really is)
+ *     but the macro's return type is preserved as char.
  *
- * Return: an absolute value of x.  If x is 64-bit, macro's return type is s64,
- *   otherwise it is signed long.
+ * Return: an absolute value of x.
  */
-#define abs(x) __builtin_choose_expr(sizeof(x) == sizeof(s64), ({	\
-		s64 __x = (x);						\
-		(__x < 0) ? -__x : __x;					\
-	}), ({								\
-		long ret;						\
-		if (sizeof(x) == sizeof(long)) {			\
-			long __x = (x);					\
-			ret = (__x < 0) ? -__x : __x;			\
-		} else {						\
-			int __x = (x);					\
-			ret = (__x < 0) ? -__x : __x;			\
-		}							\
-		ret;							\
-	}))
+#define abs(x)	__abs_choose_expr(x, long long,				\
+		__abs_choose_expr(x, long,				\
+		__abs_choose_expr(x, int,				\
+		__abs_choose_expr(x, short,				\
+		__abs_choose_expr(x, char,				\
+		__builtin_choose_expr(					\
+			__builtin_types_compatible_p(typeof(x), char),	\
+			(char)({ signed char __x = (x); __x<0?-__x:__x; }), \
+			((void)0)))))))
+
+#define __abs_choose_expr(x, type, other) __builtin_choose_expr(	\
+	__builtin_types_compatible_p(typeof(x),   signed type) ||	\
+	__builtin_types_compatible_p(typeof(x), unsigned type),		\
+	({ signed type __x = (x); __x < 0 ? -__x : __x; }), other)
 
 /**
  * reciprocal_scale - "scale" a value into range [0, ep_ro)
@@ -356,6 +356,7 @@
 int __must_check kstrtos16(const char *s, unsigned int base, s16 *res);
 int __must_check kstrtou8(const char *s, unsigned int base, u8 *res);
 int __must_check kstrtos8(const char *s, unsigned int base, s8 *res);
+int __must_check kstrtobool(const char *s, bool *res);
 
 int __must_check kstrtoull_from_user(const char __user *s, size_t count, unsigned int base, unsigned long long *res);
 int __must_check kstrtoll_from_user(const char __user *s, size_t count, unsigned int base, long long *res);
@@ -367,6 +368,7 @@
 int __must_check kstrtos16_from_user(const char __user *s, size_t count, unsigned int base, s16 *res);
 int __must_check kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, u8 *res);
 int __must_check kstrtos8_from_user(const char __user *s, size_t count, unsigned int base, s8 *res);
+int __must_check kstrtobool_from_user(const char __user *s, size_t count, bool *res);
 
 static inline int __must_check kstrtou64_from_user(const char __user *s, size_t count, unsigned int base, u64 *res)
 {
@@ -830,8 +832,4 @@
 	 /* OTHER_WRITABLE?  Generally considered a bad idea. */		\
 	 BUILD_BUG_ON_ZERO((perms) & 2) +					\
 	 (perms))
-
-/* To identify board information in panic logs, set this */
-extern char *mach_panic_string;
-
 #endif
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f68490..e233925 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -330,7 +330,9 @@
 					     int write, void __user *buffer,
 					     size_t *length, loff_t *ppos);
 #endif
-
+extern void wait_for_kprobe_optimizer(void);
+#else
+static inline void wait_for_kprobe_optimizer(void) { }
 #endif /* CONFIG_OPTPROBES */
 #ifdef CONFIG_KPROBES_ON_FTRACE
 extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index e691b6a..4289343 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -75,6 +75,8 @@
 	struct list_head	node;
 	kthread_work_func_t	func;
 	struct kthread_worker	*worker;
+	/* Number of canceling calls that are running at the moment. */
+	int			canceling;
 };
 
 #define KTHREAD_WORKER_INIT(worker)	{				\
@@ -129,4 +131,6 @@
 void flush_kthread_work(struct kthread_work *work);
 void flush_kthread_worker(struct kthread_worker *worker);
 
+bool kthread_cancel_work_sync(struct kthread_work *work);
+
 #endif /* _LINUX_KTHREAD_H */
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c923350..d7ce4e3 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -182,8 +182,8 @@
 		    int len, void *val);
 int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 			    int len, struct kvm_io_device *dev);
-int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
-			      struct kvm_io_device *dev);
+void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
+			       struct kvm_io_device *dev);
 
 #ifdef CONFIG_KVM_ASYNC_PF
 struct kvm_async_pf {
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 3f021dc..30201b9 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -83,6 +83,8 @@
 
 struct nd_interleave_set {
 	u64 cookie;
+	/* compatibility with initial buggy Linux implementation */
+	u64 altcookie;
 };
 
 struct nd_region_desc {
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 034117b..782d4e8 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -1,6 +1,8 @@
 #ifndef NVM_H
 #define NVM_H
 
+#include <linux/types.h>
+
 enum {
 	NVM_IO_OK = 0,
 	NVM_IO_REQUEUE = 1,
@@ -11,10 +13,71 @@
 	NVM_IOTYPE_GC = 1,
 };
 
+#define NVM_BLK_BITS (16)
+#define NVM_PG_BITS  (16)
+#define NVM_SEC_BITS (8)
+#define NVM_PL_BITS  (8)
+#define NVM_LUN_BITS (8)
+#define NVM_CH_BITS  (8)
+
+struct ppa_addr {
+	/* Generic structure for all addresses */
+	union {
+		struct {
+			u64 blk		: NVM_BLK_BITS;
+			u64 pg		: NVM_PG_BITS;
+			u64 sec		: NVM_SEC_BITS;
+			u64 pl		: NVM_PL_BITS;
+			u64 lun		: NVM_LUN_BITS;
+			u64 ch		: NVM_CH_BITS;
+		} g;
+
+		u64 ppa;
+	};
+};
+
+struct nvm_rq;
+struct nvm_id;
+struct nvm_dev;
+
+typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *);
+typedef int (nvm_bb_update_fn)(struct ppa_addr, int, u8 *, void *);
+typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
+typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32,
+				nvm_l2p_update_fn *, void *);
+typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, int,
+				nvm_bb_update_fn *, void *);
+typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int);
+typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
+typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *);
+typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *);
+typedef void (nvm_destroy_dma_pool_fn)(void *);
+typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t,
+								dma_addr_t *);
+typedef void (nvm_dev_dma_free_fn)(void *, void*, dma_addr_t);
+
+struct nvm_dev_ops {
+	nvm_id_fn		*identity;
+	nvm_get_l2p_tbl_fn	*get_l2p_tbl;
+	nvm_op_bb_tbl_fn	*get_bb_tbl;
+	nvm_op_set_bb_fn	*set_bb_tbl;
+
+	nvm_submit_io_fn	*submit_io;
+	nvm_erase_blk_fn	*erase_block;
+
+	nvm_create_dma_pool_fn	*create_dma_pool;
+	nvm_destroy_dma_pool_fn	*destroy_dma_pool;
+	nvm_dev_dma_alloc_fn	*dev_dma_alloc;
+	nvm_dev_dma_free_fn	*dev_dma_free;
+
+	unsigned int		max_phys_sect;
+};
+
+
+
 #ifdef CONFIG_NVM
 
 #include <linux/blkdev.h>
-#include <linux/types.h>
 #include <linux/file.h>
 #include <linux/dmapool.h>
 
@@ -58,8 +121,9 @@
 	/* Block Types */
 	NVM_BLK_T_FREE		= 0x0,
 	NVM_BLK_T_BAD		= 0x1,
-	NVM_BLK_T_DEV		= 0x2,
-	NVM_BLK_T_HOST		= 0x4,
+	NVM_BLK_T_GRWN_BAD	= 0x2,
+	NVM_BLK_T_DEV		= 0x4,
+	NVM_BLK_T_HOST		= 0x8,
 };
 
 struct nvm_id_group {
@@ -125,29 +189,6 @@
 #define NVM_VERSION_MINOR 0
 #define NVM_VERSION_PATCH 0
 
-#define NVM_BLK_BITS (16)
-#define NVM_PG_BITS  (16)
-#define NVM_SEC_BITS (8)
-#define NVM_PL_BITS  (8)
-#define NVM_LUN_BITS (8)
-#define NVM_CH_BITS  (8)
-
-struct ppa_addr {
-	/* Generic structure for all addresses */
-	union {
-		struct {
-			u64 blk		: NVM_BLK_BITS;
-			u64 pg		: NVM_PG_BITS;
-			u64 sec		: NVM_SEC_BITS;
-			u64 pl		: NVM_PL_BITS;
-			u64 lun		: NVM_LUN_BITS;
-			u64 ch		: NVM_CH_BITS;
-		} g;
-
-		u64 ppa;
-	};
-};
-
 struct nvm_rq {
 	struct nvm_tgt_instance *ins;
 	struct nvm_dev *dev;
@@ -181,39 +222,6 @@
 
 struct nvm_block;
 
-typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *);
-typedef int (nvm_bb_update_fn)(struct ppa_addr, int, u8 *, void *);
-typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
-typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32,
-				nvm_l2p_update_fn *, void *);
-typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, int,
-				nvm_bb_update_fn *, void *);
-typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int);
-typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
-typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *);
-typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *);
-typedef void (nvm_destroy_dma_pool_fn)(void *);
-typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t,
-								dma_addr_t *);
-typedef void (nvm_dev_dma_free_fn)(void *, void*, dma_addr_t);
-
-struct nvm_dev_ops {
-	nvm_id_fn		*identity;
-	nvm_get_l2p_tbl_fn	*get_l2p_tbl;
-	nvm_op_bb_tbl_fn	*get_bb_tbl;
-	nvm_op_set_bb_fn	*set_bb_tbl;
-
-	nvm_submit_io_fn	*submit_io;
-	nvm_erase_blk_fn	*erase_block;
-
-	nvm_create_dma_pool_fn	*create_dma_pool;
-	nvm_destroy_dma_pool_fn	*destroy_dma_pool;
-	nvm_dev_dma_alloc_fn	*dev_dma_alloc;
-	nvm_dev_dma_free_fn	*dev_dma_free;
-
-	unsigned int		max_phys_sect;
-};
-
 struct nvm_lun {
 	int id;
 
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index c153738..b37dee3 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -355,7 +355,8 @@
 static inline int nlm_compare_locks(const struct file_lock *fl1,
 				    const struct file_lock *fl2)
 {
-	return	fl1->fl_pid   == fl2->fl_pid
+	return file_inode(fl1->fl_file) == file_inode(fl2->fl_file)
+	     && fl1->fl_pid   == fl2->fl_pid
 	     && fl1->fl_owner == fl2->fl_owner
 	     && fl1->fl_start == fl2->fl_start
 	     && fl1->fl_end   == fl2->fl_end
diff --git a/include/linux/log2.h b/include/linux/log2.h
index fd7ff3d..c373295 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -16,12 +16,6 @@
 #include <linux/bitops.h>
 
 /*
- * deal with unrepresentable constant logarithms
- */
-extern __attribute__((const, noreturn))
-int ____ilog2_NaN(void);
-
-/*
  * non-constant log of base 2 calculators
  * - the arch may override these in asm/bitops.h if they can be implemented
  *   more efficiently than using fls() and fls64()
@@ -85,7 +79,7 @@
 #define ilog2(n)				\
 (						\
 	__builtin_constant_p(n) ? (		\
-		(n) < 1 ? ____ilog2_NaN() :	\
+		(n) < 2 ? 0 :			\
 		(n) & (1ULL << 63) ? 63 :	\
 		(n) & (1ULL << 62) ? 62 :	\
 		(n) & (1ULL << 61) ? 61 :	\
@@ -148,10 +142,7 @@
 		(n) & (1ULL <<  4) ?  4 :	\
 		(n) & (1ULL <<  3) ?  3 :	\
 		(n) & (1ULL <<  2) ?  2 :	\
-		(n) & (1ULL <<  1) ?  1 :	\
-		(n) & (1ULL <<  0) ?  0 :	\
-		____ilog2_NaN()			\
-				   ) :		\
+		1 ) :				\
 	(sizeof(n) <= 4) ?			\
 	__ilog2_u32(n) :			\
 	__ilog2_u64(n)				\
@@ -203,6 +194,17 @@
  *  ... and so on.
  */
 
-#define order_base_2(n) ilog2(roundup_pow_of_two(n))
+static inline __attribute_const__
+int __order_base_2(unsigned long n)
+{
+	return n > 1 ? ilog2(n - 1) + 1 : 0;
+}
 
+#define order_base_2(n)				\
+(						\
+	__builtin_constant_p(n) ? (		\
+		((n) == 0 || (n) == 1) ? 0 :	\
+		ilog2((n) - 1) + 1) :		\
+	__order_base_2(n)			\
+)
 #endif /* _LINUX_LOG2_H */
diff --git a/include/linux/mbcache2.h b/include/linux/mbcache2.h
new file mode 100644
index 0000000..b6f160f
--- /dev/null
+++ b/include/linux/mbcache2.h
@@ -0,0 +1,50 @@
+#ifndef _LINUX_MB2CACHE_H
+#define _LINUX_MB2CACHE_H
+
+#include <linux/hash.h>
+#include <linux/list_bl.h>
+#include <linux/list.h>
+#include <linux/atomic.h>
+#include <linux/fs.h>
+
+struct mb2_cache;
+
+struct mb2_cache_entry {
+	/* LRU list - protected by cache->c_lru_list_lock */
+	struct list_head	e_lru_list;
+	/* Hash table list - protected by bitlock in e_hash_list_head */
+	struct hlist_bl_node	e_hash_list;
+	atomic_t		e_refcnt;
+	/* Key in hash - stable during lifetime of the entry */
+	u32			e_key;
+	/* Block number of hashed block - stable during lifetime of the entry */
+	sector_t		e_block;
+	/* Head of hash list (for list bit lock) - stable */
+	struct hlist_bl_head	*e_hash_list_head;
+};
+
+struct mb2_cache *mb2_cache_create(int bucket_bits);
+void mb2_cache_destroy(struct mb2_cache *cache);
+
+int mb2_cache_entry_create(struct mb2_cache *cache, gfp_t mask, u32 key,
+			   sector_t block);
+void __mb2_cache_entry_free(struct mb2_cache_entry *entry);
+static inline int mb2_cache_entry_put(struct mb2_cache *cache,
+				      struct mb2_cache_entry *entry)
+{
+	if (!atomic_dec_and_test(&entry->e_refcnt))
+		return 0;
+	__mb2_cache_entry_free(entry);
+	return 1;
+}
+
+void mb2_cache_entry_delete_block(struct mb2_cache *cache, u32 key,
+				  sector_t block);
+struct mb2_cache_entry *mb2_cache_entry_find_first(struct mb2_cache *cache,
+						   u32 key);
+struct mb2_cache_entry *mb2_cache_entry_find_next(struct mb2_cache *cache,
+						  struct mb2_cache_entry *entry);
+void mb2_cache_entry_touch(struct mb2_cache *cache,
+			   struct mb2_cache_entry *entry);
+
+#endif	/* _LINUX_MB2CACHE_H */
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 24daf8f..f88a536 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -25,6 +25,7 @@
 	MEMBLOCK_NONE		= 0x0,	/* No special request */
 	MEMBLOCK_HOTPLUG	= 0x1,	/* hotpluggable region */
 	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
+	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
 };
 
 struct memblock_region {
@@ -82,6 +83,7 @@
 int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
+int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
 ulong choose_memblock_flags(void);
 
 /* Low level functions */
@@ -184,6 +186,11 @@
 	return m->flags & MEMBLOCK_MIRROR;
 }
 
+static inline bool memblock_is_nomap(struct memblock_region *m)
+{
+	return m->flags & MEMBLOCK_NOMAP;
+}
+
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
 			    unsigned long  *end_pfn);
@@ -319,6 +326,7 @@
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
 int memblock_is_memory(phys_addr_t addr);
+int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
 int memblock_is_reserved(phys_addr_t addr);
 bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
@@ -408,12 +416,20 @@
 }
 #endif
 
+extern unsigned long memblock_reserved_memory_within(phys_addr_t start_addr,
+		phys_addr_t end_addr);
 #else
 static inline phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align)
 {
 	return 0;
 }
 
+static inline unsigned long memblock_reserved_memory_within(phys_addr_t start_addr,
+		phys_addr_t end_addr)
+{
+	return 0;
+}
+
 #endif /* CONFIG_HAVE_MEMBLOCK */
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index cd0e241..435fd84 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -174,6 +174,11 @@
 	struct mem_cgroup_threshold_ary *spare;
 };
 
+struct mem_cgroup_id {
+	int id;
+	atomic_t ref;
+};
+
 /*
  * The memory controller data structure. The memory controller controls both
  * page cache and RSS per cgroup. We would eventually like to provide
@@ -183,6 +188,9 @@
 struct mem_cgroup {
 	struct cgroup_subsys_state css;
 
+	/* Private memcg ID. Used to ID objects that outlive the cgroup */
+	struct mem_cgroup_id id;
+
 	/* Accounted resources */
 	struct page_counter memory;
 	struct page_counter memsw;
diff --git a/include/linux/memory-state-time.h b/include/linux/memory-state-time.h
new file mode 100644
index 0000000..d2212b0
--- /dev/null
+++ b/include/linux/memory-state-time.h
@@ -0,0 +1,42 @@
+/* include/linux/memory-state-time.h
+ *
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/workqueue.h>
+
+#define UPDATE_MEMORY_STATE(BLOCK, VALUE) BLOCK->update_call(BLOCK, VALUE)
+
+struct memory_state_update_block;
+
+typedef void (*memory_state_update_fn_t)(struct memory_state_update_block *ub,
+		int value);
+
+/* This struct is populated when you pass it to a memory_state_register*
+ * function. The update_call function is used for an update and defined in the
+ * typedef memory_state_update_fn_t
+ */
+struct memory_state_update_block {
+	memory_state_update_fn_t update_call;
+	int id;
+};
+
+/* Register a frequency struct memory_state_update_block to provide updates to
+ * memory_state_time about frequency changes using its update_call function.
+ */
+struct memory_state_update_block *memory_state_register_frequency_source(void);
+
+/* Register a bandwidth struct memory_state_update_block to provide updates to
+ * memory_state_time about bandwidth changes using its update_call function.
+ */
+struct memory_state_update_block *memory_state_register_bandwidth_source(void);
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 2ea574f..538488b 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -85,7 +85,8 @@
 extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
 /* VM interface that may be used by firmware interface */
 extern int online_pages(unsigned long, unsigned long, int);
-extern int test_pages_in_a_zone(unsigned long, unsigned long);
+extern int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
+	unsigned long *valid_start, unsigned long *valid_end);
 extern void __offline_isolated_pages(unsigned long, unsigned long);
 
 typedef void (*online_page_callback_t)(struct page *page);
diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h
index d409ceb..c118a7e 100644
--- a/include/linux/mfd/88pm80x.h
+++ b/include/linux/mfd/88pm80x.h
@@ -350,7 +350,7 @@
 	int irq = platform_get_irq(pdev, 0);
 
 	if (device_may_wakeup(dev))
-		set_bit((1 << irq), &chip->wu_flag);
+		set_bit(irq, &chip->wu_flag);
 
 	return 0;
 }
@@ -362,7 +362,7 @@
 	int irq = platform_get_irq(pdev, 0);
 
 	if (device_may_wakeup(dev))
-		clear_bit((1 << irq), &chip->wu_flag);
+		clear_bit(irq, &chip->wu_flag);
 
 	return 0;
 }
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 494682c..3ab3ced 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -224,6 +224,21 @@
 		     struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns success
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+			    struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h
index b288965..2c14eec 100644
--- a/include/linux/mfd/samsung/s2mps11.h
+++ b/include/linux/mfd/samsung/s2mps11.h
@@ -173,10 +173,12 @@
 
 #define S2MPS11_LDO_VSEL_MASK	0x3F
 #define S2MPS11_BUCK_VSEL_MASK	0xFF
+#define S2MPS11_BUCK9_VSEL_MASK	0x1F
 #define S2MPS11_ENABLE_MASK	(0x03 << S2MPS11_ENABLE_SHIFT)
 #define S2MPS11_ENABLE_SHIFT	0x06
 #define S2MPS11_LDO_N_VOLTAGES	(S2MPS11_LDO_VSEL_MASK + 1)
 #define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1)
+#define S2MPS11_BUCK9_N_VOLTAGES (S2MPS11_BUCK9_VSEL_MASK + 1)
 #define S2MPS11_RAMP_DELAY	25000		/* uV/us */
 
 #define S2MPS11_CTRL1_PWRHOLD_MASK	BIT(4)
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 1fd50dc..175c826 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -138,16 +138,16 @@
 /*
  * time in us for processing a single channel, calculated as follows:
  *
- * num cycles = open delay + (sample delay + conv time) * averaging
+ * max num cycles = open delay + (sample delay + conv time) * averaging
  *
- * num cycles: 152 + (1 + 13) * 16 = 376
+ * max num cycles: 262143 + (255 + 13) * 16 = 266431
  *
  * clock frequency: 26MHz / 8 = 3.25MHz
  * clock period: 1 / 3.25MHz = 308ns
  *
- * processing time: 376 * 308ns = 116us
+ * max processing time: 266431 * 308ns = 83ms(approx)
  */
-#define IDLE_TIMEOUT 116 /* microsec */
+#define IDLE_TIMEOUT 83 /* milliseconds */
 
 #define TSCADC_CELLS		2
 
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index af3efd9..412aa98 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -792,9 +792,9 @@
 int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
 				 enum mlx5_port_status *status);
 
-int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu, u8 port);
-void mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu, u8 port);
-void mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu,
+int mlx5_set_port_mtu(struct mlx5_core_dev *dev, u16 mtu, u8 port);
+void mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, u16 *max_mtu, u8 port);
+void mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, u16 *oper_mtu,
 			      u8 port);
 
 int mlx5_query_port_vl_hw_cap(struct mlx5_core_dev *dev,
diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h
index f079fb1..a8786d2 100644
--- a/include/linux/mlx5/qp.h
+++ b/include/linux/mlx5/qp.h
@@ -160,6 +160,7 @@
 enum {
 	MLX5_FENCE_MODE_NONE			= 0 << 5,
 	MLX5_FENCE_MODE_INITIATOR_SMALL		= 1 << 5,
+	MLX5_FENCE_MODE_FENCE			= 2 << 5,
 	MLX5_FENCE_MODE_STRONG_ORDERING		= 3 << 5,
 	MLX5_FENCE_MODE_SMALL_AND_FENCE		= 4 << 5,
 };
@@ -534,9 +535,9 @@
 struct mlx5_modify_qp_mbox_in {
 	struct mlx5_inbox_hdr	hdr;
 	__be32			qpn;
-	u8			rsvd1[4];
-	__be32			optparam;
 	u8			rsvd0[4];
+	__be32			optparam;
+	u8			rsvd1[4];
 	struct mlx5_qp_context	ctx;
 };
 
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fb987b2..e51aafb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1290,41 +1290,12 @@
 
 int get_cmdline(struct task_struct *task, char *buffer, int buflen);
 
-/* Is the vma a continuation of the stack vma above it? */
-static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr)
-{
-	return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
-}
-
 static inline bool vma_is_anonymous(struct vm_area_struct *vma)
 {
 	return !vma->vm_ops;
 }
 
-static inline int stack_guard_page_start(struct vm_area_struct *vma,
-					     unsigned long addr)
-{
-	return (vma->vm_flags & VM_GROWSDOWN) &&
-		(vma->vm_start == addr) &&
-		!vma_growsdown(vma->vm_prev, addr);
-}
-
-/* Is the vma a continuation of the stack vma below it? */
-static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr)
-{
-	return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP);
-}
-
-static inline int stack_guard_page_end(struct vm_area_struct *vma,
-					   unsigned long addr)
-{
-	return (vma->vm_flags & VM_GROWSUP) &&
-		(vma->vm_end == addr) &&
-		!vma_growsup(vma->vm_next, addr);
-}
-
-extern struct task_struct *task_of_stack(struct task_struct *task,
-				struct vm_area_struct *vma, bool in_group);
+int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t);
 
 extern unsigned long move_page_tables(struct vm_area_struct *vma,
 		unsigned long old_addr, struct vm_area_struct *new_vma,
@@ -1708,7 +1679,7 @@
 extern void adjust_managed_page_count(struct page *page, long count);
 extern void mem_init_print_info(const char *str);
 
-extern void reserve_bootmem_region(unsigned long start, unsigned long end);
+extern void reserve_bootmem_region(phys_addr_t start, phys_addr_t end);
 
 /* Free the reserved page into the buddy system, so it gets managed. */
 static inline void __free_reserved_page(struct page *page)
@@ -1911,6 +1882,7 @@
 
 extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
 extern struct file *get_mm_exe_file(struct mm_struct *mm);
+extern struct file *get_task_exe_file(struct task_struct *task);
 
 extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
 extern struct vm_area_struct *_install_special_mapping(struct mm_struct *mm,
@@ -2024,6 +1996,7 @@
 				pgoff_t offset,
 				unsigned long size);
 
+extern unsigned long stack_guard_gap;
 /* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */
 extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
 
@@ -2052,6 +2025,30 @@
 	return vma;
 }
 
+static inline unsigned long vm_start_gap(struct vm_area_struct *vma)
+{
+	unsigned long vm_start = vma->vm_start;
+
+	if (vma->vm_flags & VM_GROWSDOWN) {
+		vm_start -= stack_guard_gap;
+		if (vm_start > vma->vm_start)
+			vm_start = 0;
+	}
+	return vm_start;
+}
+
+static inline unsigned long vm_end_gap(struct vm_area_struct *vma)
+{
+	unsigned long vm_end = vma->vm_end;
+
+	if (vma->vm_flags & VM_GROWSUP) {
+		vm_end += stack_guard_gap;
+		if (vm_end < vma->vm_end)
+			vm_end = -PAGE_SIZE;
+	}
+	return vm_end;
+}
+
 static inline unsigned long vma_pages(struct vm_area_struct *vma)
 {
 	return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
@@ -2124,6 +2121,7 @@
 #define FOLL_MIGRATION	0x400	/* wait for page to replace migration entry */
 #define FOLL_TRIED	0x800	/* a retry, previous pass started an IO */
 #define FOLL_MLOCK	0x1000	/* lock present pages */
+#define FOLL_COW	0x4000	/* internal GUP flag */
 
 typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
 			void *data);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 0a732c5..af25bc1 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -476,6 +476,7 @@
 	 */
 	struct task_struct __rcu *owner;
 #endif
+	struct user_namespace *user_ns;
 
 	/* store ref to file /proc/<pid>/exe symlink points to */
 	struct file __rcu *exe_file;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index eb0151b..8f23fb2 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -118,6 +118,9 @@
 	u8			raw_pwr_cl_ddr_200_360;	/* 253 */
 	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
+	u8			pre_eol_info;		/* 267 */
+	u8			device_life_time_est_typ_a;	/* 268 */
+	u8			device_life_time_est_typ_b;	/* 269 */
 
 	unsigned int            feature_support;
 #define MMC_DISCARD_FEATURE	BIT(0)                  /* CMD38 feature */
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 37967b6..0860efd 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -136,6 +136,10 @@
 	struct completion	completion;
 	void			(*done)(struct mmc_request *);/* completion function */
 	struct mmc_host		*host;
+	ktime_t			io_start;
+#ifdef CONFIG_BLOCK
+	int			lat_hist_enabled;
+#endif
 };
 
 struct mmc_card;
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index f67b2ec..7776afb 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -172,7 +172,7 @@
 	/* For edmac */
 	struct dw_mci_dma_slave *dms;
 	/* Registers's physical base address */
-	void                    *phy_regs;
+	resource_size_t		phy_regs;
 
 	u32			cmd_status;
 	u32			data_status;
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 40025b2..97b2b0b 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/fault-inject.h>
+#include <linux/blkdev.h>
 
 #include <linux/mmc/core.h>
 #include <linux/mmc/card.h>
@@ -379,6 +380,11 @@
 	} embedded_sdio_data;
 #endif
 
+#ifdef CONFIG_BLOCK
+	int			latency_hist_enabled;
+	struct io_latency_state io_lat_s;
+#endif
+
 	unsigned long		private[0] ____cacheline_aligned;
 };
 
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 15f2c4a..2c6b1d4 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -330,6 +330,9 @@
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
 #define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
 #define EXT_CSD_FIRMWARE_VERSION	254	/* RO, 8 bytes */
+#define EXT_CSD_PRE_EOL_INFO		267	/* RO */
+#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A	268	/* RO */
+#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B	269	/* RO */
 #define EXT_CSD_SUPPORTED_MODE		493	/* RO */
 #define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
diff --git a/include/linux/mmc/pm.h b/include/linux/mmc/pm.h
index 4a13920..6e2d6a1 100644
--- a/include/linux/mmc/pm.h
+++ b/include/linux/mmc/pm.h
@@ -26,5 +26,6 @@
 
 #define MMC_PM_KEEP_POWER	(1 << 0)	/* preserve card power during suspend */
 #define MMC_PM_WAKE_SDIO_IRQ	(1 << 1)	/* wake up host system on SDIO IRQ assertion */
+#define MMC_PM_IGNORE_PM_NOTIFY	(1 << 2)	/* ignore mmc pm notify */
 
 #endif /* LINUX_MMC_PM_H */
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index 2e5e4ba..d0a69e7 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -136,6 +136,8 @@
 extern unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz);
 
 extern u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret);
+extern u8 sdio_readb_ext(struct sdio_func *func, unsigned int addr, int *err_ret,
+	unsigned in);
 extern u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret);
 extern u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret);
 
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index e23a9e7..592d532 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -65,8 +65,10 @@
 
 #ifdef CONFIG_CMA
 #  define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
+#  define is_migrate_cma_page(_page) (get_pageblock_migratetype(_page) == MIGRATE_CMA)
 #else
 #  define is_migrate_cma(migratetype) false
+#  define is_migrate_cma_page(_page) false
 #endif
 
 #define for_each_migratetype_order(order, type) \
@@ -688,6 +690,7 @@
 	 * is the first PFN that needs to be initialised.
 	 */
 	unsigned long first_deferred_pfn;
+	unsigned long static_init_size;
 #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
 } pg_data_t;
 
diff --git a/include/linux/mount.h b/include/linux/mount.h
index f822c3c..b606d8f 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -67,6 +67,7 @@
 	struct dentry *mnt_root;	/* root of the mounted tree */
 	struct super_block *mnt_sb;	/* pointer to superblock */
 	int mnt_flags;
+	void *data;
 };
 
 struct file; /* forward dec */
@@ -95,4 +96,6 @@
 
 extern dev_t name_to_dev_t(const char *name);
 
+extern unsigned int sysctl_mount_max;
+
 #endif /* _LINUX_MOUNT_H */
diff --git a/include/linux/mroute.h b/include/linux/mroute.h
index 79aaa9f..d5277fc 100644
--- a/include/linux/mroute.h
+++ b/include/linux/mroute.h
@@ -103,5 +103,5 @@
 struct rtmsg;
 extern int ipmr_get_route(struct net *net, struct sk_buff *skb,
 			  __be32 saddr, __be32 daddr,
-			  struct rtmsg *rtm, int nowait);
+			  struct rtmsg *rtm, int nowait, u32 portid);
 #endif
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
index 66982e7..f831155 100644
--- a/include/linux/mroute6.h
+++ b/include/linux/mroute6.h
@@ -115,7 +115,7 @@
 
 struct rtmsg;
 extern int ip6mr_get_route(struct net *net, struct sk_buff *skb,
-			   struct rtmsg *rtm, int nowait);
+			   struct rtmsg *rtm, int nowait, u32 portid);
 
 #ifdef CONFIG_IPV6_MROUTE
 extern struct sock *mroute6_socket(struct net *net, struct sk_buff *skb);
diff --git a/include/linux/msi.h b/include/linux/msi.h
index f71a25e..f0f43ec 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -254,12 +254,12 @@
 	 * callbacks.
 	 */
 	MSI_FLAG_USE_DEF_CHIP_OPS	= (1 << 1),
-	/* Build identity map between hwirq and irq */
-	MSI_FLAG_IDENTITY_MAP		= (1 << 2),
 	/* Support multiple PCI MSI interrupts */
-	MSI_FLAG_MULTI_PCI_MSI		= (1 << 3),
+	MSI_FLAG_MULTI_PCI_MSI		= (1 << 2),
 	/* Support PCI MSIX interrupts */
-	MSI_FLAG_PCI_MSIX		= (1 << 4),
+	MSI_FLAG_PCI_MSIX		= (1 << 3),
+	/* Needs early activate, required for PCI */
+	MSI_FLAG_ACTIVATE_EARLY		= (1 << 4),
 };
 
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 366cf77..806d0ab 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -122,18 +122,13 @@
 #endif
 
 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
-# ifdef map_bankwidth
-#  undef map_bankwidth
-#  define map_bankwidth(map) ((map)->bankwidth)
-#  undef map_bankwidth_is_large
-#  define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
-#  undef map_words
-#  define map_words(map) map_calc_words(map)
-# else
-#  define map_bankwidth(map) 32
-#  define map_bankwidth_is_large(map) (1)
-#  define map_words(map) map_calc_words(map)
-# endif
+/* always use indirect access for 256-bit to preserve kernel stack */
+# undef map_bankwidth
+# define map_bankwidth(map) ((map)->bankwidth)
+# undef map_bankwidth_is_large
+# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
+# undef map_words
+# define map_words(map) map_calc_words(map)
 #define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
 #undef MAX_MAP_BANKWIDTH
 #define MAX_MAP_BANKWIDTH 32
diff --git a/include/linux/namei.h b/include/linux/namei.h
index d53c254..023359f 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -79,6 +79,7 @@
 		const char *, unsigned int, struct path *);
 
 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+extern struct dentry *lookup_one_len2(const char *, struct vfsmount *mnt, struct dentry *, int);
 
 extern int follow_down_one(struct path *);
 extern int follow_down(struct path *);
diff --git a/include/linux/net.h b/include/linux/net.h
index 0b4ac7d..c00b8d1 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -245,7 +245,16 @@
 	net_ratelimited_function(pr_warn, fmt, ##__VA_ARGS__)
 #define net_info_ratelimited(fmt, ...)				\
 	net_ratelimited_function(pr_info, fmt, ##__VA_ARGS__)
-#if defined(DEBUG)
+#if defined(CONFIG_DYNAMIC_DEBUG)
+#define net_dbg_ratelimited(fmt, ...)					\
+do {									\
+	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);			\
+	if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT) &&	\
+	    net_ratelimit())						\
+		__dynamic_pr_debug(&descriptor, pr_fmt(fmt),		\
+		                   ##__VA_ARGS__);			\
+} while (0)
+#elif defined(DEBUG)
 #define net_dbg_ratelimited(fmt, ...)				\
 	net_ratelimited_function(pr_debug, fmt, ##__VA_ARGS__)
 #else
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 04c068e..4035bbe 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -511,7 +511,6 @@
 	clear_bit(NAPI_STATE_NPSVC, &n->state);
 }
 
-#ifdef CONFIG_SMP
 /**
  *	napi_synchronize - wait until NAPI is not running
  *	@n: napi context
@@ -522,12 +521,12 @@
  */
 static inline void napi_synchronize(const struct napi_struct *n)
 {
-	while (test_bit(NAPI_STATE_SCHED, &n->state))
-		msleep(1);
+	if (IS_ENABLED(CONFIG_SMP))
+		while (test_bit(NAPI_STATE_SCHED, &n->state))
+			msleep(1);
+	else
+		barrier();
 }
-#else
-# define napi_synchronize(n)	barrier()
-#endif
 
 enum netdev_queue_state_t {
 	__QUEUE_STATE_DRV_XOFF,
@@ -1400,6 +1399,7 @@
  *	@mtu:		Interface MTU value
  *	@type:		Interface hardware type
  *	@hard_header_len: Maximum hardware header length.
+ *	@min_header_len:  Minimum hardware header length
  *
  *	@needed_headroom: Extra headroom the hardware may need, but not in all
  *			  cases can this be guaranteed
@@ -1620,6 +1620,7 @@
 	unsigned int		mtu;
 	unsigned short		type;
 	unsigned short		hard_header_len;
+	unsigned short		min_header_len;
 
 	unsigned short		needed_headroom;
 	unsigned short		needed_tailroom;
@@ -1987,8 +1988,8 @@
 	/* This is non-zero if the packet may be of the same flow. */
 	u8	same_flow:1;
 
-	/* Used in udp_gro_receive */
-	u8	udp_mark:1;
+	/* Used in tunnel GRO receive */
+	u8	encap_mark:1;
 
 	/* GRO checksum is valid */
 	u8	csum_valid:1;
@@ -2004,7 +2005,10 @@
 	/* Used in foo-over-udp, set in udp[46]_gro_receive */
 	u8	is_ipv6:1;
 
-	/* 7 bit hole */
+	/* Number of gro_receive callbacks this packet already went through */
+	u8 recursion_counter:4;
+
+	/* 3 bit hole */
 
 	/* used to support CHECKSUM_COMPLETE for tunneling protocols */
 	__wsum	csum;
@@ -2015,6 +2019,25 @@
 
 #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
 
+#define GRO_RECURSION_LIMIT 15
+static inline int gro_recursion_inc_test(struct sk_buff *skb)
+{
+	return ++NAPI_GRO_CB(skb)->recursion_counter == GRO_RECURSION_LIMIT;
+}
+
+typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *);
+static inline struct sk_buff **call_gro_receive(gro_receive_t cb,
+						struct sk_buff **head,
+						struct sk_buff *skb)
+{
+	if (unlikely(gro_recursion_inc_test(skb))) {
+		NAPI_GRO_CB(skb)->flush |= 1;
+		return NULL;
+	}
+
+	return cb(head, skb);
+}
+
 struct packet_type {
 	__be16			type;	/* This is really htons(ether_type). */
 	struct net_device	*dev;	/* NULL is wildcarded here	     */
@@ -2060,6 +2083,22 @@
 	struct udp_offload_callbacks callbacks;
 };
 
+typedef struct sk_buff **(*gro_receive_udp_t)(struct sk_buff **,
+					      struct sk_buff *,
+					      struct udp_offload *);
+static inline struct sk_buff **call_gro_receive_udp(gro_receive_udp_t cb,
+						    struct sk_buff **head,
+						    struct sk_buff *skb,
+						    struct udp_offload *uoff)
+{
+	if (unlikely(gro_recursion_inc_test(skb))) {
+		NAPI_GRO_CB(skb)->flush |= 1;
+		return NULL;
+	}
+
+	return cb(head, skb, uoff);
+}
+
 /* often modified stats are per cpu, other are shared (netdev->stats) */
 struct pcpu_sw_netstats {
 	u64     rx_packets;
@@ -2288,14 +2327,19 @@
 	return NAPI_GRO_CB(skb)->frag0_len < hlen;
 }
 
+static inline void skb_gro_frag0_invalidate(struct sk_buff *skb)
+{
+	NAPI_GRO_CB(skb)->frag0 = NULL;
+	NAPI_GRO_CB(skb)->frag0_len = 0;
+}
+
 static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
 					unsigned int offset)
 {
 	if (!pskb_may_pull(skb, hlen))
 		return NULL;
 
-	NAPI_GRO_CB(skb)->frag0 = NULL;
-	NAPI_GRO_CB(skb)->frag0_len = 0;
+	skb_gro_frag0_invalidate(skb);
 	return skb->data + offset;
 }
 
@@ -2499,6 +2543,8 @@
 {
 	if (likely(len >= dev->hard_header_len))
 		return true;
+	if (len < dev->min_header_len)
+		return false;
 
 	if (capable(CAP_SYS_RAWIO)) {
 		memset(ll_header + len, 0, dev->hard_header_len - len);
@@ -3037,6 +3083,7 @@
 	napi->skb = NULL;
 }
 
+bool netdev_is_rx_handler_busy(struct net_device *dev);
 int netdev_rx_handler_register(struct net_device *dev,
 			       rx_handler_func_t *rx_handler,
 			       void *rx_handler_data);
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index c557741..04078e8 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -239,11 +239,18 @@
 int xt_register_matches(struct xt_match *match, unsigned int n);
 void xt_unregister_matches(struct xt_match *match, unsigned int n);
 
+int xt_check_entry_offsets(const void *base, const char *elems,
+			   unsigned int target_offset,
+			   unsigned int next_offset);
+
 int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto,
 		   bool inv_proto);
 int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto,
 		    bool inv_proto);
 
+void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
+				 struct xt_counters_info *info, bool compat);
+
 struct xt_table *xt_register_table(struct net *net,
 				   const struct xt_table *table,
 				   struct xt_table_info *bootstrap,
@@ -478,7 +485,7 @@
 int xt_compat_calc_jump(u_int8_t af, unsigned int offset);
 
 int xt_compat_match_offset(const struct xt_match *match);
-int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
+void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
 			      unsigned int *size);
 int xt_compat_match_to_user(const struct xt_entry_match *m,
 			    void __user **dstptr, unsigned int *size);
@@ -488,6 +495,9 @@
 				unsigned int *size);
 int xt_compat_target_to_user(const struct xt_entry_target *t,
 			     void __user **dstptr, unsigned int *size);
+int xt_compat_check_entry_offsets(const void *base, const char *elems,
+				  unsigned int target_offset,
+				  unsigned int next_offset);
 
 #endif /* CONFIG_COMPAT */
 #endif /* _X_TABLES_H */
diff --git a/include/linux/netfilter/xt_qtaguid.h b/include/linux/netfilter/xt_qtaguid.h
index ca60fbd..1c67155 100644
--- a/include/linux/netfilter/xt_qtaguid.h
+++ b/include/linux/netfilter/xt_qtaguid.h
@@ -10,4 +10,5 @@
 #define XT_QTAGUID_SOCKET XT_OWNER_SOCKET
 #define xt_qtaguid_match_info xt_owner_match_info
 
+int qtaguid_untag(struct socket *sock, bool kernel);
 #endif /* _XT_QTAGUID_MATCH_H */
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index e7e7853..63a8176 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -266,7 +266,7 @@
 
 static inline bool seqid_mutating_err(u32 err)
 {
-	/* rfc 3530 section 8.1.5: */
+	/* See RFC 7530, section 9.1.7 */
 	switch (err) {
 	case NFS4ERR_STALE_CLIENTID:
 	case NFS4ERR_STALE_STATEID:
@@ -275,6 +275,7 @@
 	case NFS4ERR_BADXDR:
 	case NFS4ERR_RESOURCE:
 	case NFS4ERR_NOFILEHANDLE:
+	case NFS4ERR_MOVED:
 		return false;
 	};
 	return true;
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 9bb77d3..c2256d7 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -74,7 +74,7 @@
 {
 }
 
-static inline char *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
+static inline void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
 {
 	return ERR_PTR(-ENOSYS);
 }
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 26eabf5..fbfadba8 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -601,56 +601,56 @@
  */
 static inline int fault_in_multipages_writeable(char __user *uaddr, int size)
 {
-	int ret = 0;
 	char __user *end = uaddr + size - 1;
 
 	if (unlikely(size == 0))
-		return ret;
+		return 0;
 
+	if (unlikely(uaddr > end))
+		return -EFAULT;
 	/*
 	 * Writing zeroes into userspace here is OK, because we know that if
 	 * the zero gets there, we'll be overwriting it.
 	 */
-	while (uaddr <= end) {
-		ret = __put_user(0, uaddr);
-		if (ret != 0)
-			return ret;
+	do {
+		if (unlikely(__put_user(0, uaddr) != 0))
+			return -EFAULT;
 		uaddr += PAGE_SIZE;
-	}
+	} while (uaddr <= end);
 
 	/* Check whether the range spilled into the next page. */
 	if (((unsigned long)uaddr & PAGE_MASK) ==
 			((unsigned long)end & PAGE_MASK))
-		ret = __put_user(0, end);
+		return __put_user(0, end);
 
-	return ret;
+	return 0;
 }
 
 static inline int fault_in_multipages_readable(const char __user *uaddr,
 					       int size)
 {
 	volatile char c;
-	int ret = 0;
 	const char __user *end = uaddr + size - 1;
 
 	if (unlikely(size == 0))
-		return ret;
+		return 0;
 
-	while (uaddr <= end) {
-		ret = __get_user(c, uaddr);
-		if (ret != 0)
-			return ret;
+	if (unlikely(uaddr > end))
+		return -EFAULT;
+
+	do {
+		if (unlikely(__get_user(c, uaddr) != 0))
+			return -EFAULT;
 		uaddr += PAGE_SIZE;
-	}
+	} while (uaddr <= end);
 
 	/* Check whether the range spilled into the next page. */
 	if (((unsigned long)uaddr & PAGE_MASK) ==
 			((unsigned long)end & PAGE_MASK)) {
-		ret = __get_user(c, end);
-		(void)c;
+		return __get_user(c, end);
 	}
 
-	return ret;
+	return 0;
 }
 
 int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e89c7ee..5f37614 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1802,6 +1802,20 @@
 	return (pcie_caps_reg(dev) & PCI_EXP_FLAGS_TYPE) >> 4;
 }
 
+static inline struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
+{
+	while (1) {
+		if (!pci_is_pcie(dev))
+			break;
+		if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+			return dev;
+		if (!dev->bus->self)
+			break;
+		dev = dev->bus->self;
+	}
+	return NULL;
+}
+
 void pci_request_acs(void);
 bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);
 bool pci_acs_path_enabled(struct pci_dev *start,
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index d9ba49c..37f05cb 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2495,6 +2495,13 @@
 #define PCI_DEVICE_ID_KORENIX_JETCARDF2	0x1700
 #define PCI_DEVICE_ID_KORENIX_JETCARDF3	0x17ff
 
+#define PCI_VENDOR_ID_NETRONOME		0x19ee
+#define PCI_DEVICE_ID_NETRONOME_NFP3200	0x3200
+#define PCI_DEVICE_ID_NETRONOME_NFP3240	0x3240
+#define PCI_DEVICE_ID_NETRONOME_NFP4000	0x4000
+#define PCI_DEVICE_ID_NETRONOME_NFP6000	0x6000
+#define PCI_DEVICE_ID_NETRONOME_NFP6000_VF	0x6003
+
 #define PCI_VENDOR_ID_QMI		0x1a32
 
 #define PCI_VENDOR_ID_AZWAVE		0x1a3b
diff --git a/include/linux/percpu-refcount.h b/include/linux/percpu-refcount.h
index 12c9b48..abd7c01 100644
--- a/include/linux/percpu-refcount.h
+++ b/include/linux/percpu-refcount.h
@@ -206,7 +206,7 @@
 static inline bool percpu_ref_tryget(struct percpu_ref *ref)
 {
 	unsigned long __percpu *percpu_count;
-	int ret;
+	bool ret;
 
 	rcu_read_lock_sched();
 
@@ -240,7 +240,7 @@
 static inline bool percpu_ref_tryget_live(struct percpu_ref *ref)
 {
 	unsigned long __percpu *percpu_count;
-	int ret = false;
+	bool ret = false;
 
 	rcu_read_lock_sched();
 
diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h
index c2fa3ec..146efef 100644
--- a/include/linux/percpu-rwsem.h
+++ b/include/linux/percpu-rwsem.h
@@ -10,30 +10,96 @@
 
 struct percpu_rw_semaphore {
 	struct rcu_sync		rss;
-	unsigned int __percpu	*fast_read_ctr;
+	unsigned int __percpu	*read_count;
 	struct rw_semaphore	rw_sem;
-	atomic_t		slow_read_ctr;
-	wait_queue_head_t	write_waitq;
+	wait_queue_head_t	writer;
+	int			readers_block;
 };
 
-extern void percpu_down_read(struct percpu_rw_semaphore *);
-extern int  percpu_down_read_trylock(struct percpu_rw_semaphore *);
-extern void percpu_up_read(struct percpu_rw_semaphore *);
+extern int __percpu_down_read(struct percpu_rw_semaphore *, int);
+extern void __percpu_up_read(struct percpu_rw_semaphore *);
+
+static inline void percpu_down_read(struct percpu_rw_semaphore *sem)
+{
+	might_sleep();
+
+	rwsem_acquire_read(&sem->rw_sem.dep_map, 0, 0, _RET_IP_);
+
+	preempt_disable();
+	/*
+	 * We are in an RCU-sched read-side critical section, so the writer
+	 * cannot both change sem->state from readers_fast and start checking
+	 * counters while we are here. So if we see !sem->state, we know that
+	 * the writer won't be checking until we're past the preempt_enable()
+	 * and that one the synchronize_sched() is done, the writer will see
+	 * anything we did within this RCU-sched read-size critical section.
+	 */
+	__this_cpu_inc(*sem->read_count);
+	if (unlikely(!rcu_sync_is_idle(&sem->rss)))
+		__percpu_down_read(sem, false); /* Unconditional memory barrier */
+	preempt_enable();
+	/*
+	 * The barrier() from preempt_enable() prevents the compiler from
+	 * bleeding the critical section out.
+	 */
+}
+
+static inline int percpu_down_read_trylock(struct percpu_rw_semaphore *sem)
+{
+	int ret = 1;
+
+	preempt_disable();
+	/*
+	 * Same as in percpu_down_read().
+	 */
+	__this_cpu_inc(*sem->read_count);
+	if (unlikely(!rcu_sync_is_idle(&sem->rss)))
+		ret = __percpu_down_read(sem, true); /* Unconditional memory barrier */
+	preempt_enable();
+	/*
+	 * The barrier() from preempt_enable() prevents the compiler from
+	 * bleeding the critical section out.
+	 */
+
+	if (ret)
+		rwsem_acquire_read(&sem->rw_sem.dep_map, 0, 1, _RET_IP_);
+
+	return ret;
+}
+
+static inline void percpu_up_read(struct percpu_rw_semaphore *sem)
+{
+	/*
+	 * The barrier() in preempt_disable() prevents the compiler from
+	 * bleeding the critical section out.
+	 */
+	preempt_disable();
+	/*
+	 * Same as in percpu_down_read().
+	 */
+	if (likely(rcu_sync_is_idle(&sem->rss)))
+		__this_cpu_dec(*sem->read_count);
+	else
+		__percpu_up_read(sem); /* Unconditional memory barrier */
+	preempt_enable();
+
+	rwsem_release(&sem->rw_sem.dep_map, 1, _RET_IP_);
+}
 
 extern void percpu_down_write(struct percpu_rw_semaphore *);
 extern void percpu_up_write(struct percpu_rw_semaphore *);
 
 extern int __percpu_init_rwsem(struct percpu_rw_semaphore *,
 				const char *, struct lock_class_key *);
+
 extern void percpu_free_rwsem(struct percpu_rw_semaphore *);
 
-#define percpu_init_rwsem(brw)	\
+#define percpu_init_rwsem(sem)					\
 ({								\
 	static struct lock_class_key rwsem_key;			\
-	__percpu_init_rwsem(brw, #brw, &rwsem_key);		\
+	__percpu_init_rwsem(sem, #sem, &rwsem_key);		\
 })
 
-
 #define percpu_rwsem_is_held(sem) lockdep_is_held(&(sem)->rw_sem)
 
 static inline void percpu_rwsem_release(struct percpu_rw_semaphore *sem,
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index bfa673b..0e55e40 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -107,6 +107,7 @@
 	struct platform_device	*plat_device;
 	struct pmu_hw_events	__percpu *hw_events;
 	struct notifier_block	hotplug_nb;
+	struct notifier_block	cpu_pm_nb;
 };
 
 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index aa72940..1e398e6 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -121,6 +121,7 @@
 		struct { /* intel_cqm */
 			int			cqm_state;
 			u32			cqm_rmid;
+			int			is_group_event;
 			struct list_head	cqm_events_entry;
 			struct list_head	cqm_groups_entry;
 			struct list_head	cqm_group_entry;
diff --git a/include/linux/pfn.h b/include/linux/pfn.h
index 7646637..97f3e88 100644
--- a/include/linux/pfn.h
+++ b/include/linux/pfn.h
@@ -9,5 +9,6 @@
 #define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 #define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
 #define PFN_PHYS(x)	((phys_addr_t)(x) << PAGE_SHIFT)
+#define PHYS_PFN(x)	((unsigned long)((x) >> PAGE_SHIFT))
 
 #endif
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index eb8b8ac..24f5470 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -42,6 +42,7 @@
  *	@fasync_readers: reader side fasync
  *	@fasync_writers: writer side fasync
  *	@bufs: the circular array of pipe buffers
+ *	@user: the user who created this pipe
  **/
 struct pipe_inode_info {
 	struct mutex mutex;
@@ -57,6 +58,7 @@
 	struct fasync_struct *fasync_readers;
 	struct fasync_struct *fasync_writers;
 	struct pipe_buffer *bufs;
+	struct user_struct *user;
 };
 
 /*
@@ -123,6 +125,8 @@
 void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
 
 extern unsigned int pipe_max_size, pipe_min_size;
+extern unsigned long pipe_user_pages_hard;
+extern unsigned long pipe_user_pages_soft;
 int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
 
 
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 3e96a6a..d1a8ad7 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -95,6 +95,7 @@
 extern int posix_acl_chmod(struct inode *, umode_t);
 extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **,
 		struct posix_acl **);
+extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **);
 
 extern int simple_set_acl(struct inode *, struct posix_acl *, int);
 extern int simple_acl_create(struct inode *, struct inode *);
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 831479f..5cae2c6 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -22,12 +22,13 @@
 #ifndef _LINUX_PSTORE_H
 #define _LINUX_PSTORE_H
 
-#include <linux/time.h>
+#include <linux/compiler.h>
+#include <linux/errno.h>
 #include <linux/kmsg_dump.h>
 #include <linux/mutex.h>
-#include <linux/types.h>
 #include <linux/spinlock.h>
-#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/types.h>
 
 /* types */
 enum pstore_type_id {
@@ -67,6 +68,10 @@
 			enum kmsg_dump_reason reason, u64 *id,
 			unsigned int part, const char *buf, bool compressed,
 			size_t size, struct pstore_info *psi);
+	int		(*write_buf_user)(enum pstore_type_id type,
+			enum kmsg_dump_reason reason, u64 *id,
+			unsigned int part, const char __user *buf,
+			bool compressed, size_t size, struct pstore_info *psi);
 	int		(*erase)(enum pstore_type_id type, u64 id,
 			int count, struct timespec time,
 			struct pstore_info *psi);
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index 9c9d6c1..45ac5a0 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -17,11 +17,12 @@
 #ifndef __LINUX_PSTORE_RAM_H__
 #define __LINUX_PSTORE_RAM_H__
 
+#include <linux/compiler.h>
 #include <linux/device.h>
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/types.h>
-#include <linux/init.h>
 
 struct persistent_ram_buffer;
 struct rs_control;
@@ -59,7 +60,9 @@
 void persistent_ram_zap(struct persistent_ram_zone *prz);
 
 int persistent_ram_write(struct persistent_ram_zone *prz, const void *s,
-	unsigned int count);
+			 unsigned int count);
+int persistent_ram_write_user(struct persistent_ram_zone *prz,
+			      const void __user *s, unsigned int count);
 
 void persistent_ram_save_old(struct persistent_ram_zone *prz);
 size_t persistent_ram_old_size(struct persistent_ram_zone *prz);
@@ -68,6 +71,8 @@
 ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
 	char *str, size_t len);
 
+void ramoops_console_write_buf(const char *buf, size_t size);
+
 /*
  * Ramoops platform data
  * @mem_size	memory size for ramoops
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 504c98a..81fdf4b 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -19,7 +19,6 @@
 #define PT_SEIZED	0x00010000	/* SEIZE used, enable new behavior */
 #define PT_PTRACED	0x00000001
 #define PT_DTRACE	0x00000002	/* delayed trace (used on m68k, i386) */
-#define PT_PTRACE_CAP	0x00000004	/* ptracer can follow suid-exec */
 
 #define PT_OPT_FLAG_SHIFT	3
 /* PT_TRACE_* event enable flags */
@@ -51,7 +50,8 @@
 			  unsigned long addr, unsigned long data);
 extern void ptrace_notify(int exit_code);
 extern void __ptrace_link(struct task_struct *child,
-			  struct task_struct *new_parent);
+			  struct task_struct *new_parent,
+			  const struct cred *ptracer_cred);
 extern void __ptrace_unlink(struct task_struct *child);
 extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
 #define PTRACE_MODE_READ	0x01
@@ -203,7 +203,7 @@
 
 	if (unlikely(ptrace) && current->ptrace) {
 		child->ptrace = current->ptrace;
-		__ptrace_link(child, current->parent);
+		__ptrace_link(child, current->parent, current->ptracer_cred);
 
 		if (child->ptrace & PT_SEIZED)
 			task_set_jobctl_pending(child, JOBCTL_TRAP_STOP);
@@ -212,6 +212,8 @@
 
 		set_tsk_thread_flag(child, TIF_SIGPENDING);
 	}
+	else
+		child->ptracer_cred = NULL;
 }
 
 /**
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index cfc3ed4..aa8736d 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -331,6 +331,7 @@
 #ifdef CONFIG_PWM_SYSFS
 void pwmchip_sysfs_export(struct pwm_chip *chip);
 void pwmchip_sysfs_unexport(struct pwm_chip *chip);
+void pwmchip_sysfs_unexport_children(struct pwm_chip *chip);
 #else
 static inline void pwmchip_sysfs_export(struct pwm_chip *chip)
 {
@@ -339,6 +340,10 @@
 static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip)
 {
 }
+
+static inline void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
+{
+}
 #endif /* CONFIG_PWM_SYSFS */
 
 #endif /* __LINUX_PWM_H */
diff --git a/include/linux/rcu_sync.h b/include/linux/rcu_sync.h
index a63a33e..ece7ed9 100644
--- a/include/linux/rcu_sync.h
+++ b/include/linux/rcu_sync.h
@@ -59,6 +59,7 @@
 }
 
 extern void rcu_sync_init(struct rcu_sync *, enum rcu_sync_type);
+extern void rcu_sync_enter_start(struct rcu_sync *);
 extern void rcu_sync_enter(struct rcu_sync *);
 extern void rcu_sync_exit(struct rcu_sync *);
 extern void rcu_sync_dtor(struct rcu_sync *);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 239b415..ad2c304 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -173,6 +173,9 @@
 extern unsigned long nr_iowait(void);
 extern unsigned long nr_iowait_cpu(int cpu);
 extern void get_iowait_load(unsigned long *nr_waiters, unsigned long *load);
+#ifdef CONFIG_CPU_QUIET
+extern u64 nr_running_integral(unsigned int cpu);
+#endif
 
 extern void calc_global_load(unsigned long ticks);
 
@@ -314,6 +317,15 @@
 /* Task command name length */
 #define TASK_COMM_LEN 16
 
+enum task_event {
+	PUT_PREV_TASK   = 0,
+	PICK_NEXT_TASK  = 1,
+	TASK_WAKE       = 2,
+	TASK_MIGRATE    = 3,
+	TASK_UPDATE     = 4,
+	IRQ_UPDATE	= 5,
+};
+
 #include <linux/spinlock.h>
 
 /*
@@ -831,6 +843,7 @@
 #endif
 	unsigned long locked_shm; /* How many pages of mlocked shm ? */
 	unsigned long unix_inflight;	/* How many files in flight in unix sockets */
+	atomic_long_t pipe_bufs;  /* how many pages are allocated in pipe buffers */
 
 #ifdef CONFIG_KEYS
 	struct key *uid_keyring;	/* UID specific keyring */
@@ -928,6 +941,14 @@
 #define SCHED_CAPACITY_SHIFT	10
 #define SCHED_CAPACITY_SCALE	(1L << SCHED_CAPACITY_SHIFT)
 
+struct sched_capacity_reqs {
+	unsigned long cfs;
+	unsigned long rt;
+	unsigned long dl;
+
+	unsigned long total;
+};
+
 /*
  * Wake-queues are lists of tasks with a pending wakeup, whose
  * callers have already marked the task as woken internally,
@@ -982,7 +1003,8 @@
 #define SD_BALANCE_FORK		0x0008	/* Balance on fork, clone */
 #define SD_BALANCE_WAKE		0x0010  /* Balance on wakeup */
 #define SD_WAKE_AFFINE		0x0020	/* Wake task to waking CPU */
-#define SD_SHARE_CPUCAPACITY	0x0080	/* Domain members share cpu power */
+#define SD_ASYM_CPUCAPACITY	0x0040  /* Groups have different max cpu capacities */
+#define SD_SHARE_CPUCAPACITY	0x0080	/* Domain members share cpu capacity */
 #define SD_SHARE_POWERDOMAIN	0x0100	/* Domain members share power domain */
 #define SD_SHARE_PKG_RESOURCES	0x0200	/* Domain members share cpu pkg resources */
 #define SD_SERIALIZE		0x0400	/* Only a single load balancing instance */
@@ -990,6 +1012,7 @@
 #define SD_PREFER_SIBLING	0x1000	/* Prefer to place tasks in a sibling domain */
 #define SD_OVERLAP		0x2000	/* sched_domains of this level overlap */
 #define SD_NUMA			0x4000	/* cross-node balancing */
+#define SD_SHARE_CAP_STATES	0x8000  /* Domain members share capacity state */
 
 #ifdef CONFIG_SCHED_SMT
 static inline int cpu_smt_flags(void)
@@ -1022,8 +1045,57 @@
 
 extern int sched_domain_level_max;
 
+struct capacity_state {
+	unsigned long cap;	/* compute capacity */
+	unsigned long power;	/* power consumption at this compute capacity */
+};
+
+struct idle_state {
+	unsigned long power;	 /* power consumption in this idle state */
+};
+
+struct sched_group_energy {
+	unsigned int nr_idle_states;	/* number of idle states */
+	struct idle_state *idle_states;	/* ptr to idle state array */
+	unsigned int nr_cap_states;	/* number of capacity states */
+	struct capacity_state *cap_states; /* ptr to capacity state array */
+};
+
+unsigned long capacity_curr_of(int cpu);
+
 struct sched_group;
 
+struct eas_stats {
+	/* select_idle_sibling() stats */
+	u64 sis_attempts;
+	u64 sis_idle;
+	u64 sis_cache_affine;
+	u64 sis_suff_cap;
+	u64 sis_idle_cpu;
+	u64 sis_count;
+
+	/* select_energy_cpu_brute() stats */
+	u64 secb_attempts;
+	u64 secb_sync;
+	u64 secb_idle_bt;
+	u64 secb_insuff_cap;
+	u64 secb_no_nrg_sav;
+	u64 secb_nrg_sav;
+	u64 secb_count;
+
+	/* find_best_target() stats */
+	u64 fbt_attempts;
+	u64 fbt_no_cpu;
+	u64 fbt_no_sd;
+	u64 fbt_pref_idle;
+	u64 fbt_count;
+
+	/* cas */
+	/* select_task_rq_fair() stats */
+	u64 cas_attempts;
+	u64 cas_count;
+};
+
 struct sched_domain {
 	/* These fields must be setup */
 	struct sched_domain *parent;	/* top domain must be null terminated */
@@ -1084,6 +1156,8 @@
 	unsigned int ttwu_wake_remote;
 	unsigned int ttwu_move_affine;
 	unsigned int ttwu_move_balance;
+
+	struct eas_stats eas_stats;
 #endif
 #ifdef CONFIG_SCHED_DEBUG
 	char *name;
@@ -1120,6 +1194,8 @@
 
 typedef const struct cpumask *(*sched_domain_mask_f)(int cpu);
 typedef int (*sched_domain_flags_f)(void);
+typedef
+const struct sched_group_energy * const(*sched_domain_energy_f)(int cpu);
 
 #define SDTL_OVERLAP	0x01
 
@@ -1132,6 +1208,7 @@
 struct sched_domain_topology_level {
 	sched_domain_mask_f mask;
 	sched_domain_flags_f sd_flags;
+	sched_domain_energy_f energy;
 	int		    flags;
 	int		    numa_level;
 	struct sd_data      data;
@@ -1239,6 +1316,70 @@
 	u64			nr_wakeups_affine_attempts;
 	u64			nr_wakeups_passive;
 	u64			nr_wakeups_idle;
+
+	/* select_idle_sibling() */
+	u64			nr_wakeups_sis_attempts;
+	u64			nr_wakeups_sis_idle;
+	u64			nr_wakeups_sis_cache_affine;
+	u64			nr_wakeups_sis_suff_cap;
+	u64			nr_wakeups_sis_idle_cpu;
+	u64			nr_wakeups_sis_count;
+
+	/* energy_aware_wake_cpu() */
+	u64			nr_wakeups_secb_attempts;
+	u64			nr_wakeups_secb_sync;
+	u64			nr_wakeups_secb_idle_bt;
+	u64			nr_wakeups_secb_insuff_cap;
+	u64			nr_wakeups_secb_no_nrg_sav;
+	u64			nr_wakeups_secb_nrg_sav;
+	u64			nr_wakeups_secb_count;
+
+	/* find_best_target() */
+	u64			nr_wakeups_fbt_attempts;
+	u64			nr_wakeups_fbt_no_cpu;
+	u64			nr_wakeups_fbt_no_sd;
+	u64			nr_wakeups_fbt_pref_idle;
+	u64			nr_wakeups_fbt_count;
+
+	/* cas */
+	/* select_task_rq_fair() */
+	u64			nr_wakeups_cas_attempts;
+	u64			nr_wakeups_cas_count;
+};
+#endif
+
+#ifdef CONFIG_SCHED_WALT
+#define RAVG_HIST_SIZE_MAX  5
+
+/* ravg represents frequency scaled cpu-demand of tasks */
+struct ravg {
+	/*
+	 * 'mark_start' marks the beginning of an event (task waking up, task
+	 * starting to execute, task being preempted) within a window
+	 *
+	 * 'sum' represents how runnable a task has been within current
+	 * window. It incorporates both running time and wait time and is
+	 * frequency scaled.
+	 *
+	 * 'sum_history' keeps track of history of 'sum' seen over previous
+	 * RAVG_HIST_SIZE windows. Windows where task was entirely sleeping are
+	 * ignored.
+	 *
+	 * 'demand' represents maximum sum seen over previous
+	 * sysctl_sched_ravg_hist_size windows. 'demand' could drive frequency
+	 * demand for tasks.
+	 *
+	 * 'curr_window' represents task's contribution to cpu busy time
+	 * statistics (rq->curr_runnable_sum) in current window
+	 *
+	 * 'prev_window' represents task's contribution to cpu busy time
+	 * statistics (rq->prev_runnable_sum) in previous window
+	 */
+	u64 mark_start;
+	u32 sum, demand;
+	u32 sum_history[RAVG_HIST_SIZE_MAX];
+	u32 curr_window, prev_window;
+	u16 active_windows;
 };
 #endif
 
@@ -1399,6 +1540,15 @@
 	const struct sched_class *sched_class;
 	struct sched_entity se;
 	struct sched_rt_entity rt;
+#ifdef CONFIG_SCHED_WALT
+	struct ravg ravg;
+	/*
+	 * 'init_load_pct' represents the initial task load assigned to children
+	 * of this task
+	 */
+	u32 init_load_pct;
+#endif
+
 #ifdef CONFIG_CGROUP_SCHED
 	struct task_group *sched_task_group;
 #endif
@@ -1474,6 +1624,10 @@
 #ifdef CONFIG_COMPAT_BRK
 	unsigned brk_randomized:1;
 #endif
+#ifdef CONFIG_CGROUPS
+	/* disallow userland-initiated cgroup migration */
+	unsigned no_cgroup_migration:1;
+#endif
 
 	unsigned long atomic_flags; /* Flags needing atomic access. */
 
@@ -1539,6 +1693,7 @@
 	struct list_head cpu_timers[3];
 
 /* process credentials */
+	const struct cred __rcu *ptracer_cred; /* Tracer's credentials at attach */
 	const struct cred __rcu *real_cred; /* objective and real subjective task
 					 * credentials (COW) */
 	const struct cred __rcu *cred;	/* effective (overridable) subjective task
@@ -3139,6 +3294,11 @@
 {
 	tsk->ioac.syscw++;
 }
+
+static inline void inc_syscfs(struct task_struct *tsk)
+{
+	tsk->ioac.syscfs++;
+}
 #else
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
@@ -3155,6 +3315,9 @@
 static inline void inc_syscw(struct task_struct *tsk)
 {
 }
+static inline void inc_syscfs(struct task_struct *tsk)
+{
+}
 #endif
 
 #ifndef TASK_SIZE_OF
@@ -3191,4 +3354,19 @@
 	return task_rlimit_max(current, limit);
 }
 
+#define SCHED_CPUFREQ_RT        (1U << 0)
+#define SCHED_CPUFREQ_DL        (1U << 1)
+#define SCHED_CPUFREQ_IOWAIT    (1U << 2)
+
+#ifdef CONFIG_CPU_FREQ
+struct update_util_data {
+	void (*func)(struct update_util_data *data, u64 time, unsigned int flags);
+};
+
+void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
+                       void (*func)(struct update_util_data *data, u64 time,
+                                    unsigned int flags));
+void cpufreq_remove_update_util_hook(int cpu);
+#endif /* CONFIG_CPU_FREQ */
+
 #endif
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
index c9e4731..2bf4520 100644
--- a/include/linux/sched/sysctl.h
+++ b/include/linux/sched/sysctl.h
@@ -39,6 +39,15 @@
 extern unsigned int sysctl_sched_min_granularity;
 extern unsigned int sysctl_sched_wakeup_granularity;
 extern unsigned int sysctl_sched_child_runs_first;
+extern unsigned int sysctl_sched_sync_hint_enable;
+extern unsigned int sysctl_sched_initial_task_util;
+extern unsigned int sysctl_sched_cstate_aware;
+#ifdef CONFIG_SCHED_WALT
+extern unsigned int sysctl_sched_use_walt_cpu_util;
+extern unsigned int sysctl_sched_use_walt_task_util;
+extern unsigned int sysctl_sched_walt_init_task_load_pct;
+extern unsigned int sysctl_sched_walt_cpu_high_irqload;
+#endif
 
 enum sched_tunable_scaling {
 	SCHED_TUNABLESCALING_NONE,
@@ -77,6 +86,22 @@
 extern unsigned int sysctl_sched_cfs_bandwidth_slice;
 #endif
 
+#ifdef CONFIG_SCHED_TUNE
+extern unsigned int sysctl_sched_cfs_boost;
+int sysctl_sched_cfs_boost_handler(struct ctl_table *table, int write,
+				   void __user *buffer, size_t *length,
+				   loff_t *ppos);
+static inline unsigned int get_sysctl_sched_cfs_boost(void)
+{
+	return sysctl_sched_cfs_boost;
+}
+#else
+static inline unsigned int get_sysctl_sched_cfs_boost(void)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_SCHED_AUTOGROUP
 extern unsigned int sysctl_sched_autogroup_enabled;
 #endif
diff --git a/include/linux/sched_energy.h b/include/linux/sched_energy.h
new file mode 100644
index 0000000..1daf3e1
--- /dev/null
+++ b/include/linux/sched_energy.h
@@ -0,0 +1,44 @@
+#ifndef _LINUX_SCHED_ENERGY_H
+#define _LINUX_SCHED_ENERGY_H
+
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+/*
+ * There doesn't seem to be an NR_CPUS style max number of sched domain
+ * levels so here's an arbitrary constant one for the moment.
+ *
+ * The levels alluded to here correspond to entries in struct
+ * sched_domain_topology_level that are meant to be populated by arch
+ * specific code (topology.c).
+ */
+#define NR_SD_LEVELS 8
+
+#define SD_LEVEL0   0
+#define SD_LEVEL1   1
+#define SD_LEVEL2   2
+#define SD_LEVEL3   3
+#define SD_LEVEL4   4
+#define SD_LEVEL5   5
+#define SD_LEVEL6   6
+#define SD_LEVEL7   7
+
+/*
+ * Convenience macro for iterating through said sd levels.
+ */
+#define for_each_possible_sd_level(level)		    \
+	for (level = 0; level < NR_SD_LEVELS; level++)
+
+#ifdef CONFIG_SMP
+
+extern struct sched_group_energy *sge_array[NR_CPUS][NR_SD_LEVELS];
+
+void init_sched_energy_costs(void);
+
+#else
+
+#define init_sched_energy_costs() do { } while (0)
+
+#endif /* CONFIG_SMP */
+
+#endif
diff --git a/include/linux/sem.h b/include/linux/sem.h
index 976ce3a..d0efd6e 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -21,6 +21,7 @@
 	struct list_head	list_id;	/* undo requests on this array */
 	int			sem_nsems;	/* no. of semaphores in array */
 	int			complex_count;	/* pending complex operations */
+	bool			complex_mode;	/* no parallel simple ops */
 };
 
 #ifdef CONFIG_SYSVIPC
diff --git a/include/linux/serio.h b/include/linux/serio.h
index df4ab5d..c733cff 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -31,7 +31,8 @@
 
 	struct serio_device_id id;
 
-	spinlock_t lock;		/* protects critical sections from port's interrupt handler */
+	/* Protects critical sections from port's interrupt handler */
+	spinlock_t lock;
 
 	int (*write)(struct serio *, unsigned char);
 	int (*open)(struct serio *);
@@ -40,16 +41,29 @@
 	void (*stop)(struct serio *);
 
 	struct serio *parent;
-	struct list_head child_node;	/* Entry in parent->children list */
+	/* Entry in parent->children list */
+	struct list_head child_node;
 	struct list_head children;
-	unsigned int depth;		/* level of nesting in serio hierarchy */
+	/* Level of nesting in serio hierarchy */
+	unsigned int depth;
 
-	struct serio_driver *drv;	/* accessed from interrupt, must be protected by serio->lock and serio->sem */
-	struct mutex drv_mutex;		/* protects serio->drv so attributes can pin driver */
+	/*
+	 * serio->drv is accessed from interrupt handlers; when modifying
+	 * caller should acquire serio->drv_mutex and serio->lock.
+	 */
+	struct serio_driver *drv;
+	/* Protects serio->drv so attributes can pin current driver */
+	struct mutex drv_mutex;
 
 	struct device dev;
 
 	struct list_head node;
+
+	/*
+	 * For use by PS/2 layer when several ports share hardware and
+	 * may get indigestion when exposed to concurrent access (i8042).
+	 */
+	struct mutex *ps2_cmd_mutex;
 };
 #define to_serio_port(d)	container_of(d, struct serio, dev)
 
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 92557bb..d80259a 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -28,6 +28,21 @@
 	sigset_t signal;
 };
 
+#ifndef HAVE_ARCH_COPY_SIGINFO
+
+#include <linux/string.h>
+
+static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
+{
+	if (from->si_code < 0)
+		memcpy(to, from, sizeof(*to));
+	else
+		/* _sigchld is currently the largest know union member */
+		memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
+}
+
+#endif
+
 /*
  * Define some primitives to manipulate sigset_t.
  */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 4fde618..3f61c64 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -982,6 +982,7 @@
 }
 
 void __skb_get_hash(struct sk_buff *skb);
+u32 __skb_get_hash_symmetric(struct sk_buff *skb);
 u32 skb_get_poff(const struct sk_buff *skb);
 u32 __skb_get_poff(const struct sk_buff *skb, void *data,
 		   const struct flow_keys *keys, int hlen);
@@ -1083,9 +1084,6 @@
 
 static inline void skb_sender_cpu_clear(struct sk_buff *skb)
 {
-#ifdef CONFIG_XPS
-	skb->sender_cpu = 0;
-#endif
 }
 
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
@@ -2564,6 +2562,13 @@
 	       skb_headroom(skb) + len <= skb->hdr_len;
 }
 
+static inline int skb_try_make_writable(struct sk_buff *skb,
+					unsigned int write_len)
+{
+	return skb_cloned(skb) && !skb_clone_writable(skb, write_len) &&
+	       pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+}
+
 static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
 			    int cloned)
 {
@@ -2766,6 +2771,25 @@
 }
 
 /**
+ *	skb_push_rcsum - push skb and update receive checksum
+ *	@skb: buffer to update
+ *	@len: length of data pulled
+ *
+ *	This function performs an skb_push on the packet and updates
+ *	the CHECKSUM_COMPLETE checksum.  It should be used on
+ *	receive path processing instead of skb_push unless you know
+ *	that the checksum difference is zero (e.g., a valid IP header)
+ *	or you are setting ip_summed to CHECKSUM_NONE.
+ */
+static inline unsigned char *skb_push_rcsum(struct sk_buff *skb,
+					    unsigned int len)
+{
+	skb_push(skb, len);
+	skb_postpush_rcsum(skb, skb->data, len);
+	return skb->data;
+}
+
+/**
  *	pskb_trim_rcsum - trim received skb and update checksum
  *	@skb: buffer to trim
  *	@len: new length
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 2037a86..4ef384b 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -144,6 +144,18 @@
 void kzfree(const void *);
 size_t ksize(const void *);
 
+#ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR
+const char *__check_heap_object(const void *ptr, unsigned long n,
+				struct page *page);
+#else
+static inline const char *__check_heap_object(const void *ptr,
+					      unsigned long n,
+					      struct page *page)
+{
+	return NULL;
+}
+#endif
+
 /*
  * Some archs want to perform DMA into kmalloc caches and need a guaranteed
  * alignment larger than the alignment of a 64-bit integer.
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 3388511..f4e857e 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -81,6 +81,7 @@
 	int reserved;		/* Reserved bytes at the end of slabs */
 	const char *name;	/* Name (only for display!) */
 	struct list_head list;	/* List of slab caches */
+	int red_left_pad;	/* Left redzone padding size */
 #ifdef CONFIG_SYSFS
 	struct kobject kobj;	/* For sysfs */
 #endif
diff --git a/include/linux/smc91x.h b/include/linux/smc91x.h
index 76199b7..e302c44 100644
--- a/include/linux/smc91x.h
+++ b/include/linux/smc91x.h
@@ -1,6 +1,16 @@
 #ifndef __SMC91X_H__
 #define __SMC91X_H__
 
+/*
+ * These bits define which access sizes a platform can support, rather
+ * than the maximal access size.  So, if your platform can do 16-bit
+ * and 32-bit accesses to the SMC91x device, but not 8-bit, set both
+ * SMC91X_USE_16BIT and SMC91X_USE_32BIT.
+ *
+ * The SMC91x driver requires at least one of SMC91X_USE_8BIT or
+ * SMC91X_USE_16BIT to be supported - just setting SMC91X_USE_32BIT is
+ * an invalid configuration.
+ */
 #define SMC91X_USE_8BIT (1 << 0)
 #define SMC91X_USE_16BIT (1 << 1)
 #define SMC91X_USE_32BIT (1 << 2)
diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h
index 4018b48..a0596ca0 100644
--- a/include/linux/sock_diag.h
+++ b/include/linux/sock_diag.h
@@ -36,6 +36,9 @@
 {
 	switch (sk->sk_family) {
 	case AF_INET:
+		if (sk->sk_type == SOCK_RAW)
+			return SKNLGRP_NONE;
+
 		switch (sk->sk_protocol) {
 		case IPPROTO_TCP:
 			return SKNLGRP_INET_TCP_DESTROY;
@@ -45,6 +48,9 @@
 			return SKNLGRP_NONE;
 		}
 	case AF_INET6:
+		if (sk->sk_type == SOCK_RAW)
+			return SKNLGRP_NONE;
+
 		switch (sk->sk_protocol) {
 		case IPPROTO_TCP:
 			return SKNLGRP_INET6_TCP_DESTROY;
diff --git a/include/linux/string.h b/include/linux/string.h
index 9ef7795..aa30789 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -127,7 +127,11 @@
 extern void argv_free(char **argv);
 
 extern bool sysfs_streq(const char *s1, const char *s2);
-extern int strtobool(const char *s, bool *res);
+extern int kstrtobool(const char *s, bool *res);
+static inline int strtobool(const char *s, bool *res)
+{
+	return kstrtobool(s, res);
+}
 
 #ifdef CONFIG_BINARY_PRINTF
 int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 131032f..316a552 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -135,8 +135,6 @@
 #define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT	(1UL << 9)
 
 struct rpc_clnt *rpc_create(struct rpc_create_args *args);
-struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
-					struct rpc_xprt *xprt);
 struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
 				const struct rpc_program *, u32);
 void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt);
@@ -182,5 +180,6 @@
 int		rpc_localaddr(struct rpc_clnt *, struct sockaddr *, size_t);
 
 const char *rpc_proc_name(const struct rpc_task *task);
+void rpc_cleanup_clids(void);
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 7ba7dcc..d8ca2ea 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -266,6 +266,7 @@
 
 static inline void workingset_node_pages_dec(struct radix_tree_node *node)
 {
+	VM_WARN_ON_ONCE(!workingset_node_pages(node));
 	node->count--;
 }
 
@@ -281,6 +282,7 @@
 
 static inline void workingset_node_shadows_dec(struct radix_tree_node *node)
 {
+	VM_WARN_ON_ONCE(!workingset_node_shadows(node));
 	node->count -= 1U << RADIX_TREE_COUNT_SHIFT;
 }
 
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index fa7bc29..ef17db6c 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -41,6 +41,8 @@
 			 void __user *, size_t *, loff_t *);
 extern int proc_dointvec(struct ctl_table *, int,
 			 void __user *, size_t *, loff_t *);
+extern int proc_douintvec(struct ctl_table *, int,
+			 void __user *, size_t *, loff_t *);
 extern int proc_dointvec_minmax(struct ctl_table *, int,
 				void __user *, size_t *, loff_t *);
 extern int proc_dointvec_jiffies(struct ctl_table *, int,
diff --git a/include/linux/task_io_accounting.h b/include/linux/task_io_accounting.h
index bdf855c..2dd338f 100644
--- a/include/linux/task_io_accounting.h
+++ b/include/linux/task_io_accounting.h
@@ -18,6 +18,8 @@
 	u64 syscr;
 	/* # of write syscalls */
 	u64 syscw;
+	/* # of fsync syscalls */
+	u64 syscfs;
 #endif /* CONFIG_TASK_XACCT */
 
 #ifdef CONFIG_TASK_IO_ACCOUNTING
diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h
index 4d090f9..1b505c8 100644
--- a/include/linux/task_io_accounting_ops.h
+++ b/include/linux/task_io_accounting_ops.h
@@ -96,6 +96,7 @@
 	dst->wchar += src->wchar;
 	dst->syscr += src->syscr;
 	dst->syscw += src->syscw;
+	dst->syscfs += src->syscfs;
 }
 #else
 static inline void task_chr_io_accounting_add(struct task_io_accounting *dst,
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index b386361..318c246 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -56,8 +56,13 @@
 
 /* TCP Fast Open Cookie as stored in memory */
 struct tcp_fastopen_cookie {
+	union {
+		u8	val[TCP_FASTOPEN_COOKIE_MAX];
+#if IS_ENABLED(CONFIG_IPV6)
+		struct in6_addr addr;
+#endif
+	};
 	s8	len;
-	u8	val[TCP_FASTOPEN_COOKIE_MAX];
 	bool	exp;	/* In RFC6994 experimental option format */
 };
 
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index ff307b5..4cf8951 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -145,6 +145,31 @@
 #error "no set_restore_sigmask() provided and default one won't work"
 #endif
 
+#ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES
+static inline int arch_within_stack_frames(const void * const stack,
+					   const void * const stackend,
+					   const void *obj, unsigned long len)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_HARDENED_USERCOPY
+extern void __check_object_size(const void *ptr, unsigned long n,
+					bool to_user);
+
+static __always_inline void check_object_size(const void *ptr, unsigned long n,
+					      bool to_user)
+{
+	if (!__builtin_constant_p(n))
+		__check_object_size(ptr, n, to_user);
+}
+#else
+static inline void check_object_size(const void *ptr, unsigned long n,
+				     bool to_user)
+{ }
+#endif /* CONFIG_HARDENED_USERCOPY */
+
 #endif	/* __KERNEL__ */
 
 #endif /* _LINUX_THREAD_INFO_H */
diff --git a/include/linux/time.h b/include/linux/time.h
index beebe3a..297f09f 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -125,6 +125,32 @@
 
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
 
+/*
+ * Validates if a timespec/timeval used to inject a time offset is valid.
+ * Offsets can be postive or negative. The value of the timeval/timespec
+ * is the sum of its fields, but *NOTE*: the field tv_usec/tv_nsec must
+ * always be non-negative.
+ */
+static inline bool timeval_inject_offset_valid(const struct timeval *tv)
+{
+	/* We don't check the tv_sec as it can be positive or negative */
+
+	/* Can't have more microseconds then a second */
+	if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC)
+		return false;
+	return true;
+}
+
+static inline bool timespec_inject_offset_valid(const struct timespec *ts)
+{
+	/* We don't check the tv_sec as it can be positive or negative */
+
+	/* Can't have more nanoseconds then a second */
+	if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC)
+		return false;
+	return true;
+}
+
 #define CURRENT_TIME		(current_kernel_time())
 #define CURRENT_TIME_SEC	((struct timespec) { get_seconds(), 0 })
 
diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index 2524722..f0f1793 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -29,7 +29,6 @@
  */
 struct tk_read_base {
 	struct clocksource	*clock;
-	cycle_t			(*read)(struct clocksource *cs);
 	cycle_t			mask;
 	cycle_t			cycle_last;
 	u32			mult;
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
index ec89d84..b7246d2 100644
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -233,6 +233,7 @@
 
 extern u64 ktime_get_mono_fast_ns(void);
 extern u64 ktime_get_raw_fast_ns(void);
+extern u64 ktime_get_boot_fast_ns(void);
 
 /*
  * Timespec interfaces utilizing the ktime based ones
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 3bf03b6..83b264c 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -338,7 +338,6 @@
 #define TTY_EXCLUSIVE 		3	/* Exclusive open mode */
 #define TTY_DEBUG 		4	/* Debugging */
 #define TTY_DO_WRITE_WAKEUP 	5	/* Call write_wakeup after queuing new */
-#define TTY_OTHER_DONE		6	/* Closed pty has completed input processing */
 #define TTY_LDISC_OPEN	 	11	/* Line discipline is open */
 #define TTY_PTY_LOCK 		16	/* pty private */
 #define TTY_NO_WRITE_SPLIT 	17	/* Preserve write boundaries to driver */
@@ -469,6 +468,7 @@
 extern void tty_buffer_set_lock_subclass(struct tty_port *port);
 extern bool tty_buffer_restart_work(struct tty_port *port);
 extern bool tty_buffer_cancel_work(struct tty_port *port);
+extern void tty_buffer_flush_work(struct tty_port *port);
 extern speed_t tty_termios_baud_rate(struct ktermios *termios);
 extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
 extern void tty_termios_encode_baud_rate(struct ktermios *termios,
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 558129a..f30c187 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -111,4 +111,11 @@
 #define probe_kernel_address(addr, retval)		\
 	probe_kernel_read(&retval, addr, sizeof(retval))
 
+#ifndef user_access_begin
+#define user_access_begin() do { } while (0)
+#define user_access_end() do { } while (0)
+#define unsafe_get_user(x, ptr, err) do { if (unlikely(__get_user(x, ptr))) goto err; } while (0)
+#define unsafe_put_user(x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0)
+#endif
+
 #endif		/* __LINUX_UACCESS_H__ */
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 8b01e1c..e222510 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -76,7 +76,7 @@
 		struct iov_iter *i, unsigned long offset, size_t bytes);
 void iov_iter_advance(struct iov_iter *i, size_t bytes);
 int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
-int iov_iter_fault_in_multipages_readable(struct iov_iter *i, size_t bytes);
+#define iov_iter_fault_in_multipages_readable iov_iter_fault_in_readable
 size_t iov_iter_single_seg_count(const struct iov_iter *i);
 size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
 			 struct iov_iter *i);
@@ -101,12 +101,12 @@
 
 const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags);
 
-static inline size_t iov_iter_count(struct iov_iter *i)
+static inline size_t iov_iter_count(const struct iov_iter *i)
 {
 	return i->count;
 }
 
-static inline bool iter_is_iovec(struct iov_iter *i)
+static inline bool iter_is_iovec(const struct iov_iter *i)
 {
 	return !(i->type & (ITER_BVEC | ITER_KVEC));
 }
diff --git a/include/linux/usb.h b/include/linux/usb.h
index b79925d..8c75af6 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -371,14 +371,13 @@
 
 	int devnum_next;		/* Next open device number in
 					 * round-robin allocation */
+	struct mutex devnum_next_mutex; /* devnum_next mutex */
 
 	struct usb_devmap devmap;	/* device address allocation map */
 	struct usb_device *root_hub;	/* Root hub */
 	struct usb_bus *hs_companion;	/* Companion EHCI bus, if any */
 	struct list_head bus_list;	/* list of busses */
 
-	struct mutex usb_address0_mutex; /* unaddressed device mutex */
-
 	int bandwidth_allocated;	/* on this bus: how much of the time
 					 * reserved for periodic (intr/iso)
 					 * requests is used, on average?
@@ -1068,7 +1067,7 @@
  *	for interfaces bound to this driver.
  * @soft_unbind: if set to 1, the USB core will not kill URBs and disable
  *	endpoints before calling the driver's disconnect method.
- * @disable_hub_initiated_lpm: if set to 0, the USB core will not allow hubs
+ * @disable_hub_initiated_lpm: if set to 1, the USB core will not allow hubs
  *	to initiate lower power link state transitions when an idle timeout
  *	occurs.  Device-initiated USB 3.0 link PM will still be allowed.
  *
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index 5dd75fa..f9be467 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -14,6 +14,7 @@
  * struct ci_hdrc_cable - structure for external connector cable state tracking
  * @state: current state of the line
  * @changed: set to true when extcon event happen
+ * @enabled: set to true if we've enabled the vbus or id interrupt
  * @edev: device which generate events
  * @ci: driver state of the chipidea device
  * @nb: hold event notification callback
@@ -22,6 +23,7 @@
 struct ci_hdrc_cable {
 	bool				state;
 	bool				changed;
+	bool				enabled;
 	struct extcon_dev		*edev;
 	struct ci_hdrc			*ci;
 	struct notifier_block		nb;
diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
index 966889a..e479033 100644
--- a/include/linux/usb/ehci_def.h
+++ b/include/linux/usb/ehci_def.h
@@ -180,11 +180,11 @@
  * PORTSCx
  */
 	/* HOSTPC: offset 0x84 */
-	u32		hostpc[1];	/* HOSTPC extension */
+	u32		hostpc[0];	/* HOSTPC extension */
 #define HOSTPC_PHCD	(1<<22)		/* Phy clock disable */
 #define HOSTPC_PSPD	(3<<25)		/* Port speed detection */
 
-	u32		reserved5[16];
+	u32		reserved5[17];
 
 	/* USBMODE_EX: offset 0xc8 */
 	u32		usbmode_ex;	/* USB Device mode extension */
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index f89c24b..757c554 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -180,6 +180,7 @@
 	 * bandwidth_mutex should be dropped after a successful control message
 	 * to the device, or resetting the bandwidth after a failed attempt.
 	 */
+	struct mutex		*address0_mutex;
 	struct mutex		*bandwidth_mutex;
 	struct usb_hcd		*shared_hcd;
 	struct usb_hcd		*primary_hcd;
@@ -559,9 +560,9 @@
 	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
 
 #define EndpointRequest \
-	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
 #define EndpointOutRequest \
-	((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+	((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
 
 /* class requests from the USB 2.0 hub spec, table 11-15 */
 /* GetBusState and SetHubDescriptor are optional, omitted */
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 1d0043d..de2a722 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -50,4 +50,10 @@
 /* device can't handle Link Power Management */
 #define USB_QUIRK_NO_LPM			BIT(10)
 
+/*
+ * Device reports its bInterval as linear frames instead of the
+ * USB 2.0 calculation.
+ */
+#define USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL	BIT(11)
+
 #endif /* __LINUX_USB_QUIRKS_H */
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 3e5d907..73fae8c 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -189,6 +189,7 @@
 extern void dec_zone_state(struct zone *, enum zone_stat_item);
 extern void __dec_zone_state(struct zone *, enum zone_stat_item);
 
+void quiet_vmstat(void);
 void cpu_vm_stats_fold(int cpu);
 void refresh_zone_stat_thresholds(void);
 
@@ -249,6 +250,7 @@
 
 static inline void refresh_zone_stat_thresholds(void) { }
 static inline void cpu_vm_stats_fold(int cpu) { }
+static inline void quiet_vmstat(void) { }
 
 static inline void drain_zonestat(struct zone *zone,
 			struct per_cpu_pageset *pset) { }
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 3275ddf..9cba490 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -1,8 +1,9 @@
 #ifndef _ADDRCONF_H
 #define _ADDRCONF_H
 
-#define MAX_RTR_SOLICITATIONS		3
+#define MAX_RTR_SOLICITATIONS		-1		/* unlimited */
 #define RTR_SOLICITATION_INTERVAL	(4*HZ)
+#define RTR_SOLICITATION_MAX_INTERVAL	(3600*HZ)	/* 1 hour */
 
 #define MIN_VALID_LIFETIME		(2*3600)	/* 2 hours */
 
@@ -19,6 +20,8 @@
 #define ADDRCONF_TIMER_FUZZ		(HZ / 4)
 #define ADDRCONF_TIMER_FUZZ_MAX		(HZ)
 
+#define ADDRCONF_NOTIFY_PRIORITY	0
+
 #include <linux/in.h>
 #include <linux/in6.h>
 
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 9b4c418..fd60ecc 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -52,7 +52,7 @@
 	struct sock		sk;
 	struct unix_address     *addr;
 	struct path		path;
-	struct mutex		readlock;
+	struct mutex		iolock, bindlock;
 	struct sock		*peer;
 	struct list_head	link;
 	atomic_long_t		inflight;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2c7bdb8..b5f3693 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4258,6 +4258,17 @@
 void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss);
 
 /**
+ * cfg80211_abandon_assoc - notify cfg80211 of abandoned association attempt
+ * @dev: network device
+ * @bss: The BSS entry with which association was abandoned.
+ *
+ * Call this whenever - for reasons reported through other API, like deauth RX,
+ * an association attempt was abandoned.
+ * This function may sleep. The caller must hold the corresponding wdev's mutex.
+ */
+void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss);
+
+/**
  * cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame
  * @dev: network device
  * @buf: 802.11 frame (header + body)
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index 3ebb168..a34b141 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -309,6 +309,10 @@
 	}
 
 	for (opt_iter = 6; opt_iter < opt_len;) {
+		if (opt_iter + 1 == opt_len) {
+			err_offset = opt_iter;
+			goto out;
+		}
 		tag_len = opt[opt_iter + 1];
 		if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
 			err_offset = opt_iter + 1;
diff --git a/include/net/codel.h b/include/net/codel.h
index 267e702..d168aca 100644
--- a/include/net/codel.h
+++ b/include/net/codel.h
@@ -162,12 +162,14 @@
  * struct codel_stats - contains codel shared variables and stats
  * @maxpacket:	largest packet we've seen so far
  * @drop_count:	temp count of dropped packets in dequeue()
+ * @drop_len:	bytes of dropped packets in dequeue()
  * ecn_mark:	number of packets we ECN marked instead of dropping
  * ce_mark:	number of packets CE marked because sojourn time was above ce_threshold
  */
 struct codel_stats {
 	u32		maxpacket;
 	u32		drop_count;
+	u32		drop_len;
 	u32		ecn_mark;
 	u32		ce_mark;
 };
@@ -308,6 +310,7 @@
 								  vars->rec_inv_sqrt);
 					goto end;
 				}
+				stats->drop_len += qdisc_pkt_len(skb);
 				qdisc_drop(skb, sch);
 				stats->drop_count++;
 				skb = dequeue_func(vars, sch);
@@ -330,6 +333,7 @@
 		if (params->ecn && INET_ECN_set_ce(skb)) {
 			stats->ecn_mark++;
 		} else {
+			stats->drop_len += qdisc_pkt_len(skb);
 			qdisc_drop(skb, sch);
 			stats->drop_count++;
 
diff --git a/include/net/dst.h b/include/net/dst.h
index c7329dc..e4f4506 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -110,10 +110,16 @@
 	};
 };
 
+struct dst_metrics {
+	u32		metrics[RTAX_MAX];
+	atomic_t	refcnt;
+};
+extern const struct dst_metrics dst_default_metrics;
+
 u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
-extern const u32 dst_default_metrics[];
 
 #define DST_METRICS_READ_ONLY		0x1UL
+#define DST_METRICS_REFCOUNTED		0x2UL
 #define DST_METRICS_FLAGS		0x3UL
 #define __DST_METRICS_PTR(Y)	\
 	((u32 *)((Y) & ~DST_METRICS_FLAGS))
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 55b5419..bd2b5c0 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -8,6 +8,11 @@
 #include <net/flow.h>
 #include <net/rtnetlink.h>
 
+struct fib_kuid_range {
+	kuid_t start;
+	kuid_t end;
+};
+
 struct fib_rule {
 	struct list_head	list;
 	int			iifindex;
@@ -29,8 +34,7 @@
 	int			suppress_prefixlen;
 	char			iifname[IFNAMSIZ];
 	char			oifname[IFNAMSIZ];
-	kuid_t			uid_start;
-	kuid_t			uid_end;
+	struct fib_kuid_range	uid_range;
 	struct rcu_head		rcu;
 };
 
@@ -89,12 +93,10 @@
 	[FRA_FWMARK]	= { .type = NLA_U32 }, \
 	[FRA_FWMASK]	= { .type = NLA_U32 }, \
 	[FRA_TABLE]     = { .type = NLA_U32 }, \
-	[FRA_GOTO]	= { .type = NLA_U32 }, \
-	[FRA_UID_START]	= { .type = NLA_U32 }, \
-	[FRA_UID_END]	= { .type = NLA_U32 }, \
 	[FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \
 	[FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \
-	[FRA_GOTO]	= { .type = NLA_U32 }
+	[FRA_GOTO]	= { .type = NLA_U32 }, \
+	[FRA_UID_RANGE]	= { .len = sizeof(struct fib_rule_uid_range) }
 
 static inline void fib_rule_get(struct fib_rule *rule)
 {
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 1c8b682..515352c 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -201,6 +201,7 @@
 	struct ipv6_devstat	stats;
 
 	struct timer_list	rs_timer;
+	__s32			rs_interval;	/* in jiffies */
 	__u8			rs_probes;
 
 	__u8			addr_gen_mode;
diff --git a/include/net/ip.h b/include/net/ip.h
index 4f3ef34..f78c3a5 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -554,7 +554,7 @@
  */
 
 void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
-void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int offset);
+void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int tlen, int offset);
 int ip_cmsg_send(struct net *net, struct msghdr *msg,
 		 struct ipcm_cookie *ipc, bool allow_ipv6);
 int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
@@ -576,7 +576,7 @@
 
 static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
 {
-	ip_cmsg_recv_offset(msg, skb, 0);
+	ip_cmsg_recv_offset(msg, skb, 0, 0);
 }
 
 bool icmp_global_allow(void);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index ba82fee..814a13d 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -77,6 +77,7 @@
 struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
 				   int flags);
 
+void ip6_route_init_special_entries(void);
 int ip6_route_init(void);
 void ip6_route_cleanup(void);
 
@@ -118,7 +119,8 @@
 void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif,
 		     u32 mark, kuid_t uid);
 void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu);
-void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+		  kuid_t uid);
 void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
 			    u32 mark);
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index ff788b6..9c2c044 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -86,6 +86,7 @@
 	struct net_device_stats *stats = &dev->stats;
 	int pkt_len, err;
 
+	memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
 	pkt_len = skb->len - skb_inner_network_offset(skb);
 	err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb);
 
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 3f98233..bda1721 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -112,11 +112,11 @@
 	unsigned char		fib_type;
 	__be32			fib_prefsrc;
 	u32			fib_priority;
-	u32			*fib_metrics;
-#define fib_mtu fib_metrics[RTAX_MTU-1]
-#define fib_window fib_metrics[RTAX_WINDOW-1]
-#define fib_rtt fib_metrics[RTAX_RTT-1]
-#define fib_advmss fib_metrics[RTAX_ADVMSS-1]
+	struct dst_metrics	*fib_metrics;
+#define fib_mtu fib_metrics->metrics[RTAX_MTU-1]
+#define fib_window fib_metrics->metrics[RTAX_WINDOW-1]
+#define fib_rtt fib_metrics->metrics[RTAX_RTT-1]
+#define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1]
 	int			fib_nhs;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	int			fib_weight;
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 62a750a..86a7bdd 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -230,6 +230,7 @@
 int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
 int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
 		    u8 *protocol, struct flowi4 *fl4);
+int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict);
 int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
 
 struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
@@ -282,6 +283,22 @@
 struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum,
 					 int gso_type_mask);
 
+static inline int iptunnel_pull_offloads(struct sk_buff *skb)
+{
+	if (skb_is_gso(skb)) {
+		int err;
+
+		err = skb_unclone(skb, GFP_ATOMIC);
+		if (unlikely(err))
+			return err;
+		skb_shinfo(skb)->gso_type &= ~(NETIF_F_GSO_ENCAP_ALL >>
+					       NETIF_F_GSO_SHIFT);
+	}
+
+	skb->encapsulation = 0;
+	return 0;
+}
+
 static inline void iptunnel_xmit_stats(int err,
 				       struct net_device_stats *err_stats,
 				       struct pcpu_sw_netstats __percpu *stats)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 9a5c9f0..7a8066b 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -744,6 +744,11 @@
 {
 	u32 hash;
 
+	/* @flowlabel may include more than a flow label, eg, the traffic class.
+	 * Here we want only the flow label value.
+	 */
+	flowlabel &= IPV6_FLOWLABEL_MASK;
+
 	if (flowlabel ||
 	    net->ipv6.sysctl.auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF ||
 	    (!autolabel &&
@@ -958,6 +963,7 @@
  */
 extern const struct proto_ops inet6_stream_ops;
 extern const struct proto_ops inet6_dgram_ops;
+extern const struct proto_ops inet6_sockraw_ops;
 
 struct group_source_req;
 struct group_filter;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 760bc4d..4e51f9a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1662,6 +1662,9 @@
  * @supp_rates: Bitmap of supported rates (per band)
  * @ht_cap: HT capabilities of this STA; restricted to our own capabilities
  * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities
+ * @max_rx_aggregation_subframes: maximal amount of frames in a single AMPDU
+ *	that this station is allowed to transmit to us.
+ *	Can be modified by driver.
  * @wme: indicates whether the STA supports QoS/WME (if local devices does,
  *	otherwise always false)
  * @drv_priv: data area for driver use, will always be aligned to
@@ -1688,6 +1691,7 @@
 	u16 aid;
 	struct ieee80211_sta_ht_cap ht_cap;
 	struct ieee80211_sta_vht_cap vht_cap;
+	u8 max_rx_aggregation_subframes;
 	bool wme;
 	u8 uapsd_queues;
 	u8 max_sp;
@@ -2674,6 +2678,33 @@
 };
 
 /**
+ * struct ieee80211_ampdu_params - AMPDU action parameters
+ *
+ * @action: the ampdu action, value from %ieee80211_ampdu_mlme_action.
+ * @sta: peer of this AMPDU session
+ * @tid: tid of the BA session
+ * @ssn: start sequence number of the session. TX/RX_STOP can pass 0. When
+ *	action is set to %IEEE80211_AMPDU_RX_START the driver passes back the
+ *	actual ssn value used to start the session and writes the value here.
+ * @buf_size: reorder buffer size  (number of subframes). Valid only when the
+ *	action is set to %IEEE80211_AMPDU_RX_START or
+ *	%IEEE80211_AMPDU_TX_OPERATIONAL
+ * @amsdu: indicates the peer's ability to receive A-MSDU within A-MPDU.
+ *	valid when the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL
+ * @timeout: BA session timeout. Valid only when the action is set to
+ *	%IEEE80211_AMPDU_RX_START
+ */
+struct ieee80211_ampdu_params {
+	enum ieee80211_ampdu_mlme_action action;
+	struct ieee80211_sta *sta;
+	u16 tid;
+	u16 ssn;
+	u8 buf_size;
+	bool amsdu;
+	u16 timeout;
+};
+
+/**
  * enum ieee80211_frame_release_type - frame release reason
  * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll
  * @IEEE80211_FRAME_RELEASE_UAPSD: frame(s) released due to
@@ -3017,13 +3048,9 @@
  * @ampdu_action: Perform a certain A-MPDU action
  * 	The RA/TID combination determines the destination and TID we want
  * 	the ampdu action to be performed for. The action is defined through
- * 	ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
- * 	is the first frame we expect to perform the action on. Notice
- * 	that TX/RX_STOP can pass NULL for this parameter.
- *	The @buf_size parameter is only valid when the action is set to
- *	%IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder
- *	buffer size (number of subframes) for this session -- the driver
- *	may neither send aggregates containing more subframes than this
+ *	ieee80211_ampdu_mlme_action.
+ *	When the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL the driver
+ *	may neither send aggregates containing more subframes than @buf_size
  *	nor send aggregates in a way that lost frames would exceed the
  *	buffer size. If just limiting the aggregate size, this would be
  *	possible with a buf_size of 8:
@@ -3034,9 +3061,6 @@
  *	buffer size of 8. Correct ways to retransmit #1 would be:
  *	 - TX:       1 or 18 or 81
  *	Even "189" would be wrong since 1 could be lost again.
- *	The @amsdu parameter is valid when the action is set to
- *	%IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability
- *	to receive A-MSDU within A-MPDU.
  *
  *	Returns a negative error code on failure.
  *	The callback can sleep.
@@ -3378,9 +3402,7 @@
 	int (*tx_last_beacon)(struct ieee80211_hw *hw);
 	int (*ampdu_action)(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
-			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			    u8 buf_size, bool amsdu);
+			    struct ieee80211_ampdu_params *params);
 	int (*get_survey)(struct ieee80211_hw *hw, int idx,
 		struct survey_info *survey);
 	void (*rfkill_poll)(struct ieee80211_hw *hw);
diff --git a/include/net/route.h b/include/net/route.h
index d016a8c..3adb9c7 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -154,8 +154,7 @@
 	flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos,
 			   RT_SCOPE_UNIVERSE, proto,
 			   sk ? inet_sk_flowi_flags(sk) : 0,
-			   daddr, saddr, dport, sport,
-			   sk ? sock_i_uid(sk) : GLOBAL_ROOT_UID);
+			   daddr, saddr, dport, sport, sock_net_uid(net, sk));
 	if (sk)
 		security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
 	return ip_route_output_flow(net, fl4, sk);
@@ -269,7 +268,7 @@
 
 	flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
 			   protocol, flow_flags, dst, src, dport, sport,
-			   sock_i_uid(sk));
+			   sk->sk_uid);
 }
 
 static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index b2a8e63..e5bba89 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -396,7 +396,8 @@
 			      struct Qdisc *qdisc);
 void qdisc_reset(struct Qdisc *qdisc);
 void qdisc_destroy(struct Qdisc *qdisc);
-void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
+void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n,
+			       unsigned int len);
 struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
 			  const struct Qdisc_ops *ops);
 struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
@@ -407,6 +408,15 @@
 void tcf_destroy_chain(struct tcf_proto __rcu **fl);
 int skb_do_redirect(struct sk_buff *);
 
+static inline bool skb_at_tc_ingress(const struct sk_buff *skb)
+{
+#ifdef CONFIG_NET_CLS_ACT
+	return G_TC_AT(skb->tc_verd) & AT_INGRESS;
+#else
+	return false;
+#endif
+}
+
 /* Reset all TX qdiscs greater then index of a device.  */
 static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
 {
@@ -698,6 +708,23 @@
 	sch->qstats.backlog = 0;
 }
 
+static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new,
+					  struct Qdisc **pold)
+{
+	struct Qdisc *old;
+
+	sch_tree_lock(sch);
+	old = *pold;
+	*pold = new;
+	if (old != NULL) {
+		qdisc_tree_reduce_backlog(old, old->q.qlen, old->qstats.backlog);
+		qdisc_reset(old);
+	}
+	sch_tree_unlock(sch);
+
+	return old;
+}
+
 static inline unsigned int __qdisc_queue_drop(struct Qdisc *sch,
 					      struct sk_buff_head *list)
 {
diff --git a/include/net/sock.h b/include/net/sock.h
index 2d663ee..62c9e22 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -446,6 +446,7 @@
 	void			*sk_security;
 #endif
 	__u32			sk_mark;
+	kuid_t			sk_uid;
 #ifdef CONFIG_CGROUP_NET_CLASSID
 	u32			sk_classid;
 #endif
@@ -1426,6 +1427,16 @@
 	if (!sk_has_account(sk))
 		return;
 	sk->sk_forward_alloc += size;
+
+	/* Avoid a possible overflow.
+	 * TCP send queues can make this happen, if sk_mem_reclaim()
+	 * is not called and more than 2 GBytes are released at once.
+	 *
+	 * If we reach 2 MBytes, reclaim 1 MBytes right now, there is
+	 * no need to hold that much forward allocation anyway.
+	 */
+	if (unlikely(sk->sk_forward_alloc >= 1 << 21))
+		__sk_mem_reclaim(sk, 1 << 20);
 }
 
 static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
@@ -1682,6 +1693,7 @@
 	sk->sk_wq = parent->wq;
 	parent->sk = sk;
 	sk_set_socket(sk, parent);
+	sk->sk_uid = SOCK_INODE(parent)->i_uid;
 	security_sock_graft(sk, parent);
 	write_unlock_bh(&sk->sk_callback_lock);
 }
@@ -1689,6 +1701,11 @@
 kuid_t sock_i_uid(struct sock *sk);
 unsigned long sock_i_ino(struct sock *sk);
 
+static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk)
+{
+	return sk ? sk->sk_uid : make_kuid(net->user_ns, 0);
+}
+
 static inline u32 net_tx_rndhash(void)
 {
 	u32 v = prandom_u32();
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 1d22ce9..31d0e51 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -88,7 +88,7 @@
 	struct switchdev_obj obj;
 	u32 dst;
 	int dst_len;
-	struct fib_info fi;
+	struct fib_info *fi;
 	u8 tos;
 	u8 type;
 	u32 nlflags;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index b36ceba..4ea3739 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1157,6 +1157,7 @@
 }
 
 bool tcp_prequeue(struct sock *sk, struct sk_buff *skb);
+int tcp_filter(struct sock *sk, struct sk_buff *skb);
 
 #undef STATE_TRACE
 
@@ -1513,6 +1514,8 @@
 {
 	if (sk->sk_send_head == skb_unlinked)
 		sk->sk_send_head = NULL;
+	if (tcp_sk(sk)->highest_sack == skb_unlinked)
+		tcp_sk(sk)->highest_sack = NULL;
 }
 
 static inline void tcp_init_send_head(struct sock *sk)
diff --git a/include/net/udp.h b/include/net/udp.h
index 6d4ed18..e57f502 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -238,6 +238,7 @@
 		 int (*saddr_cmp)(const struct sock *,
 				  const struct sock *));
 void udp_err(struct sk_buff *, u32);
+int udp_abort(struct sock *sk, int err);
 int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
 int udp_push_pending_frames(struct sock *sk);
 void udp_flush_pending_frames(struct sock *sk);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index d6f6e50..185fb03 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -948,10 +948,6 @@
 	struct flow_cache_object flo;
 	struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
 	int num_pols, num_xfrms;
-#ifdef CONFIG_XFRM_SUB_POLICY
-	struct flowi *origin;
-	struct xfrm_selector *partner;
-#endif
 	u32 xfrm_genid;
 	u32 policy_genid;
 	u32 route_mtu_cached;
@@ -967,12 +963,6 @@
 	dst_release(xdst->route);
 	if (likely(xdst->u.dst.xfrm))
 		xfrm_state_put(xdst->u.dst.xfrm);
-#ifdef CONFIG_XFRM_SUB_POLICY
-	kfree(xdst->origin);
-	xdst->origin = NULL;
-	kfree(xdst->partner);
-	xdst->partner = NULL;
-#endif
 }
 #endif
 
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
index 1152859..a78ff97 100644
--- a/include/rdma/ib_addr.h
+++ b/include/rdma/ib_addr.h
@@ -197,10 +197,12 @@
 
 	dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
 	if (dev) {
-		ip4 = (struct in_device *)dev->ip_ptr;
-		if (ip4 && ip4->ifa_list && ip4->ifa_list->ifa_address)
+		ip4 = in_dev_get(dev);
+		if (ip4 && ip4->ifa_list && ip4->ifa_list->ifa_address) {
 			ipv6_addr_set_v4mapped(ip4->ifa_list->ifa_address,
 					       (struct in6_addr *)gid);
+			in_dev_put(ip4);
+		}
 		dev_put(dev);
 	}
 }
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index 3019695..b43e64d 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -138,12 +138,12 @@
 	union ib_gid sgid;
 	__be16       dlid;
 	__be16       slid;
-	int          raw_traffic;
+	u8           raw_traffic;
 	/* reserved */
 	__be32       flow_label;
 	u8           hop_limit;
 	u8           traffic_class;
-	int          reversible;
+	u8           reversible;
 	u8           numb_path;
 	__be16       pkey;
 	__be16       qos_class;
@@ -204,7 +204,7 @@
 	u8           hop_limit;
 	u8           scope;
 	u8           join_state;
-	int          proxy_join;
+	u8           proxy_join;
 };
 
 /* Service Record Component Mask Sec 15.2.5.14 Ver 1.1	*/
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 4d1c46a..c7b1dc7 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -196,6 +196,7 @@
 	struct iscsi_task	*task;		/* xmit task in progress */
 
 	/* xmit */
+	spinlock_t		taskqueuelock;  /* protects the next three lists */
 	struct list_head	mgmtqueue;	/* mgmt (control) xmit queue */
 	struct list_head	cmdqueue;	/* data-path cmd queue */
 	struct list_head	requeue;	/* tasks needing another run */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index fe89d7c..293b9a7 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -239,6 +239,7 @@
 enum scsi_target_state {
 	STARGET_CREATED = 1,
 	STARGET_RUNNING,
+	STARGET_REMOVE,
 	STARGET_DEL,
 };
 
@@ -306,6 +307,7 @@
 extern int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh);
 void scsi_attach_vpd(struct scsi_device *sdev);
 
+extern struct scsi_device *scsi_device_from_queue(struct request_queue *q);
 extern int scsi_device_get(struct scsi_device *);
 extern void scsi_device_put(struct scsi_device *);
 extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *,
diff --git a/include/soc/at91/at91sam9_ddrsdr.h b/include/soc/at91/at91sam9_ddrsdr.h
index dc10c52..393362b 100644
--- a/include/soc/at91/at91sam9_ddrsdr.h
+++ b/include/soc/at91/at91sam9_ddrsdr.h
@@ -81,6 +81,7 @@
 #define			AT91_DDRSDRC_LPCB_POWER_DOWN		2
 #define			AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN	3
 #define		AT91_DDRSDRC_CLKFR	(1 << 2)	/* Clock Frozen */
+#define		AT91_DDRSDRC_LPDDR2_PWOFF	(1 << 3)	/* LPDDR Power Off */
 #define		AT91_DDRSDRC_PASR	(7 << 4)	/* Partial Array Self Refresh */
 #define		AT91_DDRSDRC_TCSR	(3 << 8)	/* Temperature Compensated Self Refresh */
 #define		AT91_DDRSDRC_DS		(3 << 10)	/* Drive Strength */
@@ -96,7 +97,9 @@
 #define			AT91_DDRSDRC_MD_SDR		0
 #define			AT91_DDRSDRC_MD_LOW_POWER_SDR	1
 #define			AT91_DDRSDRC_MD_LOW_POWER_DDR	3
+#define			AT91_DDRSDRC_MD_LPDDR3		5
 #define			AT91_DDRSDRC_MD_DDR2		6	/* [SAM9 Only] */
+#define			AT91_DDRSDRC_MD_LPDDR2		7
 #define		AT91_DDRSDRC_DBW	(1 << 4)		/* Data Bus Width */
 #define			AT91_DDRSDRC_DBW_32BITS		(0 <<  4)
 #define			AT91_DDRSDRC_DBW_16BITS		(1 <<  4)
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index 28ee5c2..711322a 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -96,6 +96,6 @@
 bool target_sense_desc_format(struct se_device *dev);
 sector_t target_to_linux_sector(struct se_device *dev, sector_t lb);
 bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
-				       struct request_queue *q, int block_size);
+				       struct request_queue *q);
 
 #endif /* TARGET_CORE_BACKEND_H */
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 689f4d2..ed66414 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -139,6 +139,7 @@
 	SCF_COMPARE_AND_WRITE_POST	= 0x00100000,
 	SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = 0x00200000,
 	SCF_ACK_KREF			= 0x00400000,
+	SCF_TASK_ATTR_SET		= 0x01000000,
 };
 
 /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
@@ -179,6 +180,7 @@
 	TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED	= R(0x15),
 	TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED	= R(0x16),
 	TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED	= R(0x17),
+	TCM_COPY_TARGET_DEVICE_NOT_REACHABLE	= R(0x18),
 #undef R
 };
 
@@ -542,6 +544,7 @@
 	/* Used to signal demo mode created ACL, disabled by default */
 	bool			dynamic_node_acl;
 	bool			acl_stop:1;
+	bool			dynamic_stop;
 	u32			queue_depth;
 	u32			acl_index;
 	enum target_prot_type	saved_prot_type;
@@ -737,6 +740,7 @@
 	struct config_group	lun_group;
 	struct se_port_stat_grps port_stat_grps;
 	struct completion	lun_ref_comp;
+	struct completion	lun_shutdown_comp;
 	struct percpu_ref	lun_ref;
 	struct list_head	lun_dev_link;
 	struct hlist_node	link;
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index 7fb2557..5f9b62c 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -117,7 +117,7 @@
 		struct se_node_acl *, struct se_session *, void *);
 void	transport_register_session(struct se_portal_group *,
 		struct se_node_acl *, struct se_session *, void *);
-void	target_get_session(struct se_session *);
+int	target_get_session(struct se_session *);
 void	target_put_session(struct se_session *);
 ssize_t	target_show_dynamic_sessions(struct se_portal_group *, char *);
 void	transport_free_session(struct se_session *);
@@ -163,16 +163,16 @@
 void	core_tmr_release_req(struct se_tmr_req *);
 int	transport_generic_handle_tmr(struct se_cmd *);
 void	transport_generic_request_failure(struct se_cmd *, sense_reason_t);
-void	__target_execute_cmd(struct se_cmd *);
 int	transport_lookup_tmr_lun(struct se_cmd *, u64);
 void	core_allocate_nexus_loss_ua(struct se_node_acl *acl);
 
 struct se_node_acl *core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
 		unsigned char *);
+bool	target_tpg_has_node_acl(struct se_portal_group *tpg,
+		const char *);
 struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *,
 		unsigned char *);
-int	core_tpg_set_initiator_node_queue_depth(struct se_portal_group *,
-		unsigned char *, u32, int);
+int	core_tpg_set_initiator_node_queue_depth(struct se_node_acl *, u32);
 int	core_tpg_set_initiator_node_tag(struct se_portal_group *,
 		struct se_node_acl *, const char *);
 int	core_tpg_register(struct se_wwn *, struct se_portal_group *, int);
diff --git a/include/trace/events/android_fs.h b/include/trace/events/android_fs.h
new file mode 100644
index 0000000..4950953
--- /dev/null
+++ b/include/trace/events/android_fs.h
@@ -0,0 +1,65 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM android_fs
+
+#if !defined(_TRACE_ANDROID_FS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ANDROID_FS_H
+
+#include <linux/tracepoint.h>
+#include <trace/events/android_fs_template.h>
+
+DEFINE_EVENT(android_fs_data_start_template, android_fs_dataread_start,
+	TP_PROTO(struct inode *inode, loff_t offset, int bytes,
+		 pid_t pid, char *pathname, char *command),
+	TP_ARGS(inode, offset, bytes, pid, pathname, command));
+
+DEFINE_EVENT(android_fs_data_end_template, android_fs_dataread_end,
+	TP_PROTO(struct inode *inode, loff_t offset, int bytes),
+	TP_ARGS(inode, offset, bytes));
+
+DEFINE_EVENT(android_fs_data_start_template, android_fs_datawrite_start,
+	TP_PROTO(struct inode *inode, loff_t offset, int bytes,
+		 pid_t pid, char *pathname, char *command),
+	TP_ARGS(inode, offset, bytes, pid, pathname, command));
+
+DEFINE_EVENT(android_fs_data_end_template, android_fs_datawrite_end,
+	TP_PROTO(struct inode *inode, loff_t offset, int bytes),
+	     TP_ARGS(inode, offset, bytes));
+
+#endif /* _TRACE_ANDROID_FS_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
+
+#ifndef ANDROID_FSTRACE_GET_PATHNAME
+#define ANDROID_FSTRACE_GET_PATHNAME
+
+/* Sizes an on-stack array, so careful if sizing this up ! */
+#define MAX_TRACE_PATHBUF_LEN	256
+
+static inline char *
+android_fstrace_get_pathname(char *buf, int buflen, struct inode *inode)
+{
+	char *path;
+	struct dentry *d;
+
+	/*
+	 * d_obtain_alias() will either iput() if it locates an existing
+	 * dentry or transfer the reference to the new dentry created.
+	 * So get an extra reference here.
+	 */
+	ihold(inode);
+	d = d_obtain_alias(inode);
+	if (likely(!IS_ERR(d))) {
+		path = dentry_path_raw(d, buf, buflen);
+		if (unlikely(IS_ERR(path))) {
+			strcpy(buf, "ERROR");
+			path = buf;
+		}
+		dput(d);
+	} else {
+		strcpy(buf, "ERROR");
+		path = buf;
+	}
+	return path;
+}
+#endif
diff --git a/include/trace/events/android_fs_template.h b/include/trace/events/android_fs_template.h
new file mode 100644
index 0000000..b23d17b
--- /dev/null
+++ b/include/trace/events/android_fs_template.h
@@ -0,0 +1,64 @@
+#if !defined(_TRACE_ANDROID_FS_TEMPLATE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ANDROID_FS_TEMPLATE_H
+
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(android_fs_data_start_template,
+	TP_PROTO(struct inode *inode, loff_t offset, int bytes,
+		 pid_t pid, char *pathname, char *command),
+	TP_ARGS(inode, offset, bytes, pid, pathname, command),
+	TP_STRUCT__entry(
+		__string(pathbuf, pathname);
+		__field(loff_t,	offset);
+		__field(int,	bytes);
+		__field(loff_t,	i_size);
+		__string(cmdline, command);
+		__field(pid_t,	pid);
+		__field(ino_t,	ino);
+	),
+	TP_fast_assign(
+		{
+			/*
+			 * Replace the spaces in filenames and cmdlines
+			 * because this screws up the tooling that parses
+			 * the traces.
+			 */
+			__assign_str(pathbuf, pathname);
+			(void)strreplace(__get_str(pathbuf), ' ', '_');
+			__entry->offset		= offset;
+			__entry->bytes		= bytes;
+			__entry->i_size		= i_size_read(inode);
+			__assign_str(cmdline, command);
+			(void)strreplace(__get_str(cmdline), ' ', '_');
+			__entry->pid		= pid;
+			__entry->ino		= inode->i_ino;
+		}
+	),
+	TP_printk("entry_name %s, offset %llu, bytes %d, cmdline %s,"
+		  " pid %d, i_size %llu, ino %lu",
+		  __get_str(pathbuf), __entry->offset, __entry->bytes,
+		  __get_str(cmdline), __entry->pid, __entry->i_size,
+		  (unsigned long) __entry->ino)
+);
+
+DECLARE_EVENT_CLASS(android_fs_data_end_template,
+	TP_PROTO(struct inode *inode, loff_t offset, int bytes),
+	TP_ARGS(inode, offset, bytes),
+	TP_STRUCT__entry(
+		__field(ino_t,	ino);
+		__field(loff_t,	offset);
+		__field(int,	bytes);
+	),
+	TP_fast_assign(
+		{
+			__entry->ino		= inode->i_ino;
+			__entry->offset		= offset;
+			__entry->bytes		= bytes;
+		}
+	),
+	TP_printk("ino %lu, offset %llu, bytes %d",
+		  (unsigned long) __entry->ino,
+		  __entry->offset, __entry->bytes)
+);
+
+#endif /* _TRACE_ANDROID_FS_TEMPLATE_H */
diff --git a/include/trace/events/cpufreq_sched.h b/include/trace/events/cpufreq_sched.h
new file mode 100644
index 0000000..a46cd08
--- /dev/null
+++ b/include/trace/events/cpufreq_sched.h
@@ -0,0 +1,87 @@
+/*
+ *  Copyright (C)  2015 Steve Muckle <smuckle@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM cpufreq_sched
+
+#if !defined(_TRACE_CPUFREQ_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_CPUFREQ_SCHED_H
+
+#include <linux/sched.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(cpufreq_sched_throttled,
+	    TP_PROTO(unsigned int rem),
+	    TP_ARGS(rem),
+	    TP_STRUCT__entry(
+		    __field(	unsigned int,	rem)
+	    ),
+	    TP_fast_assign(
+		    __entry->rem = rem;
+	    ),
+	    TP_printk("throttled - %d usec remaining", __entry->rem)
+);
+
+TRACE_EVENT(cpufreq_sched_request_opp,
+	    TP_PROTO(int cpu,
+		     unsigned long capacity,
+		     unsigned int freq_new,
+		     unsigned int requested_freq),
+	    TP_ARGS(cpu, capacity, freq_new, requested_freq),
+	    TP_STRUCT__entry(
+		    __field(	int,		cpu)
+		    __field(	unsigned long,	capacity)
+		    __field(	unsigned int,	freq_new)
+		    __field(	unsigned int,	requested_freq)
+		    ),
+	    TP_fast_assign(
+		    __entry->cpu = cpu;
+		    __entry->capacity = capacity;
+		    __entry->freq_new = freq_new;
+		    __entry->requested_freq = requested_freq;
+		    ),
+	    TP_printk("cpu %d cap change, cluster cap request %ld => OPP %d "
+		      "(cur %d)",
+		      __entry->cpu, __entry->capacity, __entry->freq_new,
+		      __entry->requested_freq)
+);
+
+TRACE_EVENT(cpufreq_sched_update_capacity,
+	    TP_PROTO(int cpu,
+		     bool request,
+		     struct sched_capacity_reqs *scr,
+		     unsigned long new_capacity),
+	    TP_ARGS(cpu, request, scr, new_capacity),
+	    TP_STRUCT__entry(
+		    __field(	int,		cpu)
+		    __field(	bool,		request)
+		    __field(	unsigned long,	cfs)
+		    __field(	unsigned long,	rt)
+		    __field(	unsigned long,	dl)
+		    __field(	unsigned long,	total)
+		    __field(	unsigned long,	new_total)
+	    ),
+	    TP_fast_assign(
+		    __entry->cpu = cpu;
+		    __entry->request = request;
+		    __entry->cfs = scr->cfs;
+		    __entry->rt = scr->rt;
+		    __entry->dl = scr->dl;
+		    __entry->total = scr->total;
+		    __entry->new_total = new_capacity;
+	    ),
+	    TP_printk("cpu=%d set_cap=%d cfs=%ld rt=%ld dl=%ld old_tot=%ld "
+		      "new_tot=%ld",
+		      __entry->cpu, __entry->request, __entry->cfs, __entry->rt,
+		      __entry->dl, __entry->total, __entry->new_total)
+);
+
+#endif /* _TRACE_CPUFREQ_SCHED_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/net.h b/include/trace/events/net.h
index 49cc7c3..89d009e 100644
--- a/include/trace/events/net.h
+++ b/include/trace/events/net.h
@@ -57,7 +57,7 @@
 		__entry->gso_type = skb_shinfo(skb)->gso_type;
 	),
 
-	TP_printk("dev=%s queue_mapping=%u skbaddr=%p vlan_tagged=%d vlan_proto=0x%04x vlan_tci=0x%04x protocol=0x%04x ip_summed=%d len=%u data_len=%u network_offset=%d transport_offset_valid=%d transport_offset=%d tx_flags=%d gso_size=%d gso_segs=%d gso_type=%#x",
+	TP_printk("dev=%s queue_mapping=%u skbaddr=%pK vlan_tagged=%d vlan_proto=0x%04x vlan_tci=0x%04x protocol=0x%04x ip_summed=%d len=%u data_len=%u network_offset=%d transport_offset_valid=%d transport_offset=%d tx_flags=%d gso_size=%d gso_segs=%d gso_type=%#x",
 		  __get_str(name), __entry->queue_mapping, __entry->skbaddr,
 		  __entry->vlan_tagged, __entry->vlan_proto, __entry->vlan_tci,
 		  __entry->protocol, __entry->ip_summed, __entry->len,
@@ -90,7 +90,7 @@
 		__assign_str(name, dev->name);
 	),
 
-	TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
+	TP_printk("dev=%s skbaddr=%pK len=%u rc=%d",
 		__get_str(name), __entry->skbaddr, __entry->len, __entry->rc)
 );
 
@@ -112,7 +112,7 @@
 		__assign_str(name, skb->dev->name);
 	),
 
-	TP_printk("dev=%s skbaddr=%p len=%u",
+	TP_printk("dev=%s skbaddr=%pK len=%u",
 		__get_str(name), __entry->skbaddr, __entry->len)
 )
 
@@ -191,7 +191,7 @@
 		__entry->gso_type = skb_shinfo(skb)->gso_type;
 	),
 
-	TP_printk("dev=%s napi_id=%#x queue_mapping=%u skbaddr=%p vlan_tagged=%d vlan_proto=0x%04x vlan_tci=0x%04x protocol=0x%04x ip_summed=%d hash=0x%08x l4_hash=%d len=%u data_len=%u truesize=%u mac_header_valid=%d mac_header=%d nr_frags=%d gso_size=%d gso_type=%#x",
+	TP_printk("dev=%s napi_id=%#x queue_mapping=%u skbaddr=%pK vlan_tagged=%d vlan_proto=0x%04x vlan_tci=0x%04x protocol=0x%04x ip_summed=%d hash=0x%08x l4_hash=%d len=%u data_len=%u truesize=%u mac_header_valid=%d mac_header=%d nr_frags=%d gso_size=%d gso_type=%#x",
 		  __get_str(name), __entry->napi_id, __entry->queue_mapping,
 		  __entry->skbaddr, __entry->vlan_tagged, __entry->vlan_proto,
 		  __entry->vlan_tci, __entry->protocol, __entry->ip_summed,
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 9af0d89..8924cc2 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -145,6 +145,13 @@
 		  (unsigned long)__entry->cpu_id)
 );
 
+DEFINE_EVENT(cpu, cpu_capacity,
+
+	TP_PROTO(unsigned int capacity, unsigned int cpu_id),
+
+	TP_ARGS(capacity, cpu_id)
+);
+
 TRACE_EVENT(device_pm_callback_start,
 
 	TP_PROTO(struct device *dev, const char *pm_ops, int event),
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index d34eba7..433d391 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -611,6 +611,538 @@
 
 	TP_printk("cpu=%d", __entry->cpu)
 );
+
+TRACE_EVENT(sched_contrib_scale_f,
+
+	TP_PROTO(int cpu, unsigned long freq_scale_factor,
+		 unsigned long cpu_scale_factor),
+
+	TP_ARGS(cpu, freq_scale_factor, cpu_scale_factor),
+
+	TP_STRUCT__entry(
+		__field(int, cpu)
+		__field(unsigned long, freq_scale_factor)
+		__field(unsigned long, cpu_scale_factor)
+	),
+
+	TP_fast_assign(
+		__entry->cpu = cpu;
+		__entry->freq_scale_factor = freq_scale_factor;
+		__entry->cpu_scale_factor = cpu_scale_factor;
+	),
+
+	TP_printk("cpu=%d freq_scale_factor=%lu cpu_scale_factor=%lu",
+		  __entry->cpu, __entry->freq_scale_factor,
+		  __entry->cpu_scale_factor)
+);
+
+#ifdef CONFIG_SMP
+
+#ifdef CONFIG_SCHED_WALT
+extern unsigned int sysctl_sched_use_walt_cpu_util;
+extern unsigned int sysctl_sched_use_walt_task_util;
+extern unsigned int walt_ravg_window;
+extern unsigned int walt_disabled;
+#endif
+
+/*
+ * Tracepoint for accounting sched averages for tasks.
+ */
+TRACE_EVENT(sched_load_avg_task,
+
+	TP_PROTO(struct task_struct *tsk, struct sched_avg *avg, void *_ravg),
+
+	TP_ARGS(tsk, avg, _ravg),
+
+	TP_STRUCT__entry(
+		__array( char,	comm,	TASK_COMM_LEN		)
+		__field( pid_t,	pid				)
+		__field( int,	cpu				)
+		__field( unsigned long,	load_avg		)
+		__field( unsigned long,	util_avg		)
+		__field( unsigned long,	util_avg_pelt	)
+		__field( unsigned long,	util_avg_walt	)
+		__field( u64,		load_sum		)
+		__field( u32,		util_sum		)
+		__field( u32,		period_contrib		)
+	),
+
+	TP_fast_assign(
+		memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN);
+		__entry->pid			= tsk->pid;
+		__entry->cpu			= task_cpu(tsk);
+		__entry->load_avg		= avg->load_avg;
+		__entry->util_avg		= avg->util_avg;
+		__entry->load_sum		= avg->load_sum;
+		__entry->util_sum		= avg->util_sum;
+		__entry->period_contrib		= avg->period_contrib;
+		__entry->util_avg_pelt  = avg->util_avg;
+		__entry->util_avg_walt  = 0;
+#ifdef CONFIG_SCHED_WALT
+		__entry->util_avg_walt = (((unsigned long)((struct ravg*)_ravg)->demand) << SCHED_LOAD_SHIFT);
+		do_div(__entry->util_avg_walt, walt_ravg_window);
+		if (!walt_disabled && sysctl_sched_use_walt_task_util)
+			__entry->util_avg = __entry->util_avg_walt;
+#endif
+	),
+	TP_printk("comm=%s pid=%d cpu=%d load_avg=%lu util_avg=%lu "
+			"util_avg_pelt=%lu util_avg_walt=%lu load_sum=%llu"
+		  " util_sum=%u period_contrib=%u",
+		  __entry->comm,
+		  __entry->pid,
+		  __entry->cpu,
+		  __entry->load_avg,
+		  __entry->util_avg,
+		  __entry->util_avg_pelt,
+		  __entry->util_avg_walt,
+		  (u64)__entry->load_sum,
+		  (u32)__entry->util_sum,
+		  (u32)__entry->period_contrib)
+);
+
+/*
+ * Tracepoint for accounting sched averages for cpus.
+ */
+TRACE_EVENT(sched_load_avg_cpu,
+
+	TP_PROTO(int cpu, struct cfs_rq *cfs_rq),
+
+	TP_ARGS(cpu, cfs_rq),
+
+	TP_STRUCT__entry(
+		__field( int,	cpu				)
+		__field( unsigned long,	load_avg		)
+		__field( unsigned long,	util_avg		)
+		__field( unsigned long,	util_avg_pelt	)
+		__field( unsigned long,	util_avg_walt	)
+	),
+
+	TP_fast_assign(
+		__entry->cpu			= cpu;
+		__entry->load_avg		= cfs_rq->avg.load_avg;
+		__entry->util_avg		= cfs_rq->avg.util_avg;
+		__entry->util_avg_pelt	= cfs_rq->avg.util_avg;
+		__entry->util_avg_walt	= 0;
+#ifdef CONFIG_SCHED_WALT
+		__entry->util_avg_walt	=
+				cpu_rq(cpu)->prev_runnable_sum << SCHED_LOAD_SHIFT;
+		do_div(__entry->util_avg_walt, walt_ravg_window);
+		if (!walt_disabled && sysctl_sched_use_walt_cpu_util)
+			__entry->util_avg		= __entry->util_avg_walt;
+#endif
+	),
+
+	TP_printk("cpu=%d load_avg=%lu util_avg=%lu "
+			  "util_avg_pelt=%lu util_avg_walt=%lu",
+		  __entry->cpu, __entry->load_avg, __entry->util_avg,
+		  __entry->util_avg_pelt, __entry->util_avg_walt)
+);
+
+/*
+ * Tracepoint for sched_tune_config settings
+ */
+TRACE_EVENT(sched_tune_config,
+
+	TP_PROTO(int boost),
+
+	TP_ARGS(boost),
+
+	TP_STRUCT__entry(
+		__field( int,	boost		)
+	),
+
+	TP_fast_assign(
+		__entry->boost 	= boost;
+	),
+
+	TP_printk("boost=%d ", __entry->boost)
+);
+
+/*
+ * Tracepoint for accounting CPU  boosted utilization
+ */
+TRACE_EVENT(sched_boost_cpu,
+
+	TP_PROTO(int cpu, unsigned long util, long margin),
+
+	TP_ARGS(cpu, util, margin),
+
+	TP_STRUCT__entry(
+		__field( int,		cpu			)
+		__field( unsigned long,	util			)
+		__field(long,		margin			)
+	),
+
+	TP_fast_assign(
+		__entry->cpu	= cpu;
+		__entry->util	= util;
+		__entry->margin	= margin;
+	),
+
+	TP_printk("cpu=%d util=%lu margin=%ld",
+		  __entry->cpu,
+		  __entry->util,
+		  __entry->margin)
+);
+
+/*
+ * Tracepoint for schedtune_tasks_update
+ */
+TRACE_EVENT(sched_tune_tasks_update,
+
+	TP_PROTO(struct task_struct *tsk, int cpu, int tasks, int idx,
+		int boost, int max_boost),
+
+	TP_ARGS(tsk, cpu, tasks, idx, boost, max_boost),
+
+	TP_STRUCT__entry(
+		__array( char,	comm,	TASK_COMM_LEN	)
+		__field( pid_t,		pid		)
+		__field( int,		cpu		)
+		__field( int,		tasks		)
+		__field( int,		idx		)
+		__field( int,		boost		)
+		__field( int,		max_boost	)
+	),
+
+	TP_fast_assign(
+		memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN);
+		__entry->pid		= tsk->pid;
+		__entry->cpu 		= cpu;
+		__entry->tasks		= tasks;
+		__entry->idx 		= idx;
+		__entry->boost		= boost;
+		__entry->max_boost	= max_boost;
+	),
+
+	TP_printk("pid=%d comm=%s "
+			"cpu=%d tasks=%d idx=%d boost=%d max_boost=%d",
+		__entry->pid, __entry->comm,
+		__entry->cpu, __entry->tasks, __entry->idx,
+		__entry->boost, __entry->max_boost)
+);
+
+/*
+ * Tracepoint for schedtune_boostgroup_update
+ */
+TRACE_EVENT(sched_tune_boostgroup_update,
+
+	TP_PROTO(int cpu, int variation, int max_boost),
+
+	TP_ARGS(cpu, variation, max_boost),
+
+	TP_STRUCT__entry(
+		__field( int,	cpu		)
+		__field( int,	variation	)
+		__field( int,	max_boost	)
+	),
+
+	TP_fast_assign(
+		__entry->cpu		= cpu;
+		__entry->variation	= variation;
+		__entry->max_boost	= max_boost;
+	),
+
+	TP_printk("cpu=%d variation=%d max_boost=%d",
+		__entry->cpu, __entry->variation, __entry->max_boost)
+);
+
+/*
+ * Tracepoint for accounting task boosted utilization
+ */
+TRACE_EVENT(sched_boost_task,
+
+	TP_PROTO(struct task_struct *tsk, unsigned long util, long margin),
+
+	TP_ARGS(tsk, util, margin),
+
+	TP_STRUCT__entry(
+		__array( char,	comm,	TASK_COMM_LEN		)
+		__field( pid_t,		pid			)
+		__field( unsigned long,	util			)
+		__field( long,		margin			)
+
+	),
+
+	TP_fast_assign(
+		memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN);
+		__entry->pid	= tsk->pid;
+		__entry->util	= util;
+		__entry->margin	= margin;
+	),
+
+	TP_printk("comm=%s pid=%d util=%lu margin=%ld",
+		  __entry->comm, __entry->pid,
+		  __entry->util,
+		  __entry->margin)
+);
+
+/*
+ * Tracepoint for accounting sched group energy
+ */
+TRACE_EVENT(sched_energy_diff,
+
+	TP_PROTO(struct task_struct *tsk, int scpu, int dcpu, int udelta,
+		int nrgb, int nrga, int nrgd, int capb, int capa, int capd,
+		int nrgn, int nrgp),
+
+	TP_ARGS(tsk, scpu, dcpu, udelta,
+		nrgb, nrga, nrgd, capb, capa, capd,
+		nrgn, nrgp),
+
+	TP_STRUCT__entry(
+		__array( char,	comm,	TASK_COMM_LEN	)
+		__field( pid_t,	pid	)
+		__field( int,	scpu	)
+		__field( int,	dcpu	)
+		__field( int,	udelta	)
+		__field( int,	nrgb	)
+		__field( int,	nrga	)
+		__field( int,	nrgd	)
+		__field( int,	capb	)
+		__field( int,	capa	)
+		__field( int,	capd	)
+		__field( int,	nrgn	)
+		__field( int,	nrgp	)
+	),
+
+	TP_fast_assign(
+		memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN);
+		__entry->pid		= tsk->pid;
+		__entry->scpu 		= scpu;
+		__entry->dcpu 		= dcpu;
+		__entry->udelta 	= udelta;
+		__entry->nrgb 		= nrgb;
+		__entry->nrga 		= nrga;
+		__entry->nrgd 		= nrgd;
+		__entry->capb 		= capb;
+		__entry->capa 		= capa;
+		__entry->capd 		= capd;
+		__entry->nrgn 		= nrgn;
+		__entry->nrgp 		= nrgp;
+	),
+
+	TP_printk("pid=%d comm=%s "
+			"src_cpu=%d dst_cpu=%d usage_delta=%d "
+			"nrg_before=%d nrg_after=%d nrg_diff=%d "
+			"cap_before=%d cap_after=%d cap_delta=%d "
+			"nrg_delta=%d nrg_payoff=%d",
+		__entry->pid, __entry->comm,
+		__entry->scpu, __entry->dcpu, __entry->udelta,
+		__entry->nrgb, __entry->nrga, __entry->nrgd,
+		__entry->capb, __entry->capa, __entry->capd,
+		__entry->nrgn, __entry->nrgp)
+);
+
+/*
+ * Tracepoint for schedtune_tasks_update
+ */
+TRACE_EVENT(sched_tune_filter,
+
+	TP_PROTO(int nrg_delta, int cap_delta,
+		 int nrg_gain,  int cap_gain,
+		 int payoff, int region),
+
+	TP_ARGS(nrg_delta, cap_delta, nrg_gain, cap_gain, payoff, region),
+
+	TP_STRUCT__entry(
+		__field( int,	nrg_delta	)
+		__field( int,	cap_delta	)
+		__field( int,	nrg_gain	)
+		__field( int,	cap_gain	)
+		__field( int,	payoff		)
+		__field( int,	region		)
+	),
+
+	TP_fast_assign(
+		__entry->nrg_delta	= nrg_delta;
+		__entry->cap_delta	= cap_delta;
+		__entry->nrg_gain	= nrg_gain;
+		__entry->cap_gain	= cap_gain;
+		__entry->payoff		= payoff;
+		__entry->region		= region;
+	),
+
+	TP_printk("nrg_delta=%d cap_delta=%d nrg_gain=%d cap_gain=%d payoff=%d region=%d",
+		__entry->nrg_delta, __entry->cap_delta,
+		__entry->nrg_gain, __entry->cap_gain,
+		__entry->payoff, __entry->region)
+);
+
+/*
+ * Tracepoint for system overutilized flag
+ */
+TRACE_EVENT(sched_overutilized,
+
+	TP_PROTO(bool overutilized),
+
+	TP_ARGS(overutilized),
+
+	TP_STRUCT__entry(
+		__field( bool,	overutilized	)
+	),
+
+	TP_fast_assign(
+		__entry->overutilized	= overutilized;
+	),
+
+	TP_printk("overutilized=%d",
+		__entry->overutilized ? 1 : 0)
+);
+#ifdef CONFIG_SCHED_WALT
+struct rq;
+
+TRACE_EVENT(walt_update_task_ravg,
+
+	TP_PROTO(struct task_struct *p, struct rq *rq, int evt,
+						u64 wallclock, u64 irqtime),
+
+	TP_ARGS(p, rq, evt, wallclock, irqtime),
+
+	TP_STRUCT__entry(
+		__array(	char,	comm,   TASK_COMM_LEN	)
+		__field(	pid_t,	pid			)
+		__field(	pid_t,	cur_pid			)
+		__field(unsigned int,	cur_freq		)
+		__field(	u64,	wallclock		)
+		__field(	u64,	mark_start		)
+		__field(	u64,	delta_m			)
+		__field(	u64,	win_start		)
+		__field(	u64,	delta			)
+		__field(	u64,	irqtime			)
+		__field(        int,    evt			)
+		__field(unsigned int,	demand			)
+		__field(unsigned int,	sum			)
+		__field(	 int,	cpu			)
+		__field(	u64,	cs			)
+		__field(	u64,	ps			)
+		__field(unsigned long,	util			)
+		__field(	u32,	curr_window		)
+		__field(	u32,	prev_window		)
+		__field(	u64,	nt_cs			)
+		__field(	u64,	nt_ps			)
+		__field(	u32,	active_windows		)
+	),
+
+	TP_fast_assign(
+		__entry->wallclock      = wallclock;
+		__entry->win_start      = rq->window_start;
+		__entry->delta          = (wallclock - rq->window_start);
+		__entry->evt            = evt;
+		__entry->cpu            = rq->cpu;
+		__entry->cur_pid        = rq->curr->pid;
+		__entry->cur_freq       = rq->cur_freq;
+		memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
+		__entry->pid            = p->pid;
+		__entry->mark_start     = p->ravg.mark_start;
+		__entry->delta_m        = (wallclock - p->ravg.mark_start);
+		__entry->demand         = p->ravg.demand;
+		__entry->sum            = p->ravg.sum;
+		__entry->irqtime        = irqtime;
+		__entry->cs             = rq->curr_runnable_sum;
+		__entry->ps             = rq->prev_runnable_sum;
+		__entry->util           = rq->prev_runnable_sum << SCHED_LOAD_SHIFT;
+		do_div(__entry->util, walt_ravg_window);
+		__entry->curr_window	= p->ravg.curr_window;
+		__entry->prev_window	= p->ravg.prev_window;
+		__entry->nt_cs		= rq->nt_curr_runnable_sum;
+		__entry->nt_ps		= rq->nt_prev_runnable_sum;
+		__entry->active_windows	= p->ravg.active_windows;
+	),
+
+	TP_printk("wc %llu ws %llu delta %llu event %d cpu %d cur_freq %u cur_pid %d task %d (%s) ms %llu delta %llu demand %u sum %u irqtime %llu"
+		" cs %llu ps %llu util %lu cur_window %u prev_window %u active_wins %u"
+		, __entry->wallclock, __entry->win_start, __entry->delta,
+		__entry->evt, __entry->cpu,
+		__entry->cur_freq, __entry->cur_pid,
+		__entry->pid, __entry->comm, __entry->mark_start,
+		__entry->delta_m, __entry->demand,
+		__entry->sum, __entry->irqtime,
+		__entry->cs, __entry->ps, __entry->util,
+		__entry->curr_window, __entry->prev_window,
+		  __entry->active_windows
+		)
+);
+
+TRACE_EVENT(walt_update_history,
+
+	TP_PROTO(struct rq *rq, struct task_struct *p, u32 runtime, int samples,
+			int evt),
+
+	TP_ARGS(rq, p, runtime, samples, evt),
+
+	TP_STRUCT__entry(
+		__array(	char,	comm,   TASK_COMM_LEN	)
+		__field(	pid_t,	pid			)
+		__field(unsigned int,	runtime			)
+		__field(	 int,	samples			)
+		__field(	 int,	evt			)
+		__field(	 u64,	demand			)
+		__field(	 u64,	walt_avg		)
+		__field(unsigned int,	pelt_avg		)
+		__array(	 u32,	hist, RAVG_HIST_SIZE_MAX)
+		__field(	 int,	cpu			)
+	),
+
+	TP_fast_assign(
+		memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
+		__entry->pid            = p->pid;
+		__entry->runtime        = runtime;
+		__entry->samples        = samples;
+		__entry->evt            = evt;
+		__entry->demand         = p->ravg.demand;
+		__entry->walt_avg	= (__entry->demand << 10);
+		do_div(__entry->walt_avg, walt_ravg_window);
+		__entry->pelt_avg	= p->se.avg.util_avg;
+		memcpy(__entry->hist, p->ravg.sum_history,
+					RAVG_HIST_SIZE_MAX * sizeof(u32));
+		__entry->cpu            = rq->cpu;
+	),
+
+	TP_printk("%d (%s): runtime %u samples %d event %d demand %llu"
+		" walt %llu pelt %u (hist: %u %u %u %u %u) cpu %d",
+		__entry->pid, __entry->comm,
+		__entry->runtime, __entry->samples, __entry->evt,
+		__entry->demand,
+		__entry->walt_avg,
+		__entry->pelt_avg,
+		__entry->hist[0], __entry->hist[1],
+		__entry->hist[2], __entry->hist[3],
+		__entry->hist[4], __entry->cpu)
+);
+
+TRACE_EVENT(walt_migration_update_sum,
+
+	TP_PROTO(struct rq *rq, struct task_struct *p),
+
+	TP_ARGS(rq, p),
+
+	TP_STRUCT__entry(
+		__field(int,		cpu			)
+		__field(int,		pid			)
+		__field(	u64,	cs			)
+		__field(	u64,	ps			)
+		__field(	s64,	nt_cs			)
+		__field(	s64,	nt_ps			)
+	),
+
+	TP_fast_assign(
+		__entry->cpu		= cpu_of(rq);
+		__entry->cs		= rq->curr_runnable_sum;
+		__entry->ps		= rq->prev_runnable_sum;
+		__entry->nt_cs		= (s64)rq->nt_curr_runnable_sum;
+		__entry->nt_ps		= (s64)rq->nt_prev_runnable_sum;
+		__entry->pid		= p->pid;
+	),
+
+	TP_printk("cpu %d: cs %llu ps %llu nt_cs %lld nt_ps %lld pid %d",
+		  __entry->cpu, __entry->cs, __entry->ps,
+		  __entry->nt_cs, __entry->nt_ps, __entry->pid)
+);
+#endif /* CONFIG_SCHED_WALT */
+
+#endif /* CONFIG_SMP */
+
 #endif /* _TRACE_SCHED_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
index 003dca9..5664ca0 100644
--- a/include/trace/events/sunrpc.h
+++ b/include/trace/events/sunrpc.h
@@ -529,20 +529,27 @@
 
 	TP_STRUCT__entry(
 		__field(struct svc_xprt *, xprt)
-		__field_struct(struct sockaddr_storage, ss)
 		__field(int, pid)
 		__field(unsigned long, flags)
+		__dynamic_array(unsigned char, addr, xprt != NULL ?
+			xprt->xpt_remotelen : 0)
 	),
 
 	TP_fast_assign(
 		__entry->xprt = xprt;
-		xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
 		__entry->pid = rqst? rqst->rq_task->pid : 0;
-		__entry->flags = xprt ? xprt->xpt_flags : 0;
+		if (xprt) {
+			memcpy(__get_dynamic_array(addr),
+				&xprt->xpt_remote,
+				xprt->xpt_remotelen);
+			__entry->flags = xprt->xpt_flags;
+		} else
+			__entry->flags = 0;
 	),
 
 	TP_printk("xprt=0x%p addr=%pIScp pid=%d flags=%s", __entry->xprt,
-		(struct sockaddr *)&__entry->ss,
+		__get_dynamic_array_len(addr) != 0 ?
+			(struct sockaddr *)__get_dynamic_array(addr) : NULL,
 		__entry->pid, show_svc_xprt_flags(__entry->flags))
 );
 
@@ -553,18 +560,25 @@
 
 	TP_STRUCT__entry(
 		__field(struct svc_xprt *, xprt)
-		__field_struct(struct sockaddr_storage, ss)
 		__field(unsigned long, flags)
+		__dynamic_array(unsigned char, addr, xprt != NULL ?
+			xprt->xpt_remotelen : 0)
 	),
 
 	TP_fast_assign(
-		__entry->xprt = xprt,
-		xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
-		__entry->flags = xprt ? xprt->xpt_flags : 0;
+		__entry->xprt = xprt;
+		if (xprt) {
+			memcpy(__get_dynamic_array(addr),
+					&xprt->xpt_remote,
+					xprt->xpt_remotelen);
+			__entry->flags = xprt->xpt_flags;
+		} else
+			__entry->flags = 0;
 	),
 
 	TP_printk("xprt=0x%p addr=%pIScp flags=%s", __entry->xprt,
-		(struct sockaddr *)&__entry->ss,
+		__get_dynamic_array_len(addr) != 0 ?
+			(struct sockaddr *)__get_dynamic_array(addr) : NULL,
 		show_svc_xprt_flags(__entry->flags))
 );
 
@@ -592,19 +606,26 @@
 	TP_STRUCT__entry(
 		__field(struct svc_xprt *, xprt)
 		__field(int, len)
-		__field_struct(struct sockaddr_storage, ss)
 		__field(unsigned long, flags)
+		__dynamic_array(unsigned char, addr, xprt != NULL ?
+			xprt->xpt_remotelen : 0)
 	),
 
 	TP_fast_assign(
 		__entry->xprt = xprt;
-		xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
 		__entry->len = len;
-		__entry->flags = xprt ? xprt->xpt_flags : 0;
+		if (xprt) {
+			memcpy(__get_dynamic_array(addr),
+					&xprt->xpt_remote,
+					xprt->xpt_remotelen);
+			__entry->flags = xprt->xpt_flags;
+		} else
+			__entry->flags = 0;
 	),
 
 	TP_printk("xprt=0x%p addr=%pIScp len=%d flags=%s", __entry->xprt,
-		(struct sockaddr *)&__entry->ss,
+		__get_dynamic_array_len(addr) != 0 ?
+			(struct sockaddr *)__get_dynamic_array(addr) : NULL,
 		__entry->len, show_svc_xprt_flags(__entry->flags))
 );
 #endif /* _TRACE_SUNRPC_H */
diff --git a/include/trace/events/syscalls.h b/include/trace/events/syscalls.h
index 14e49c7..b35533b 100644
--- a/include/trace/events/syscalls.h
+++ b/include/trace/events/syscalls.h
@@ -1,5 +1,6 @@
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM raw_syscalls
+#undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE syscalls
 
 #if !defined(_TRACE_EVENTS_SYSCALLS_H) || defined(TRACE_HEADER_MULTI_READ)
diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h
index 41420e3..70e252b 100644
--- a/include/uapi/linux/android/binder.h
+++ b/include/uapi/linux/android/binder.h
@@ -33,11 +33,60 @@
 	BINDER_TYPE_HANDLE	= B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
 	BINDER_TYPE_WEAK_HANDLE	= B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
 	BINDER_TYPE_FD		= B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
+	BINDER_TYPE_FDA		= B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE),
+	BINDER_TYPE_PTR		= B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE),
 };
 
-enum {
+/**
+ * enum flat_binder_object_shifts: shift values for flat_binder_object_flags
+ * @FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT: shift for getting scheduler policy.
+ *
+ */
+enum flat_binder_object_shifts {
+	FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT = 9,
+};
+
+/**
+ * enum flat_binder_object_flags - flags for use in flat_binder_object.flags
+ */
+enum flat_binder_object_flags {
+	/**
+	 * @FLAT_BINDER_FLAG_PRIORITY_MASK: bit-mask for min scheduler priority
+	 *
+	 * These bits can be used to set the minimum scheduler priority
+	 * at which transactions into this node should run. Valid values
+	 * in these bits depend on the scheduler policy encoded in
+	 * @FLAT_BINDER_FLAG_SCHED_POLICY_MASK.
+	 *
+	 * For SCHED_NORMAL/SCHED_BATCH, the valid range is between [-20..19]
+	 * For SCHED_FIFO/SCHED_RR, the value can run between [1..99]
+	 */
 	FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
+	/**
+	 * @FLAT_BINDER_FLAG_ACCEPTS_FDS: whether the node accepts fds.
+	 */
 	FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
+	/**
+	 * @FLAT_BINDER_FLAG_SCHED_POLICY_MASK: bit-mask for scheduling policy
+	 *
+	 * These two bits can be used to set the min scheduling policy at which
+	 * transactions on this node should run. These match the UAPI
+	 * scheduler policy values, eg:
+	 * 00b: SCHED_NORMAL
+	 * 01b: SCHED_FIFO
+	 * 10b: SCHED_RR
+	 * 11b: SCHED_BATCH
+	 */
+	FLAT_BINDER_FLAG_SCHED_POLICY_MASK =
+		3U << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT,
+
+	/**
+	 * @FLAT_BINDER_FLAG_INHERIT_RT: whether the node inherits RT policy
+	 *
+	 * Only when set, calls into this node will inherit a real-time
+	 * scheduling policy from the caller (for synchronous transactions).
+	 */
+	FLAT_BINDER_FLAG_INHERIT_RT = 0x800,
 };
 
 #ifdef BINDER_IPC_32BIT
@@ -48,6 +97,14 @@
 typedef __u64 binder_uintptr_t;
 #endif
 
+/**
+ * struct binder_object_header - header shared by all binder metadata objects.
+ * @type:	type of the object
+ */
+struct binder_object_header {
+	__u32        type;
+};
+
 /*
  * This is the flattened representation of a Binder object for transfer
  * between processes.  The 'offsets' supplied as part of a binder transaction
@@ -56,9 +113,8 @@
  * between processes.
  */
 struct flat_binder_object {
-	/* 8 bytes for large_flat_header. */
-	__u32		type;
-	__u32		flags;
+	struct binder_object_header	hdr;
+	__u32				flags;
 
 	/* 8 bytes of data. */
 	union {
@@ -70,6 +126,86 @@
 	binder_uintptr_t	cookie;
 };
 
+/**
+ * struct binder_fd_object - describes a filedescriptor to be fixed up.
+ * @hdr:	common header structure
+ * @pad_flags:	padding to remain compatible with old userspace code
+ * @pad_binder:	padding to remain compatible with old userspace code
+ * @fd:		file descriptor
+ * @cookie:	opaque data, used by user-space
+ */
+struct binder_fd_object {
+	struct binder_object_header	hdr;
+	__u32				pad_flags;
+	union {
+		binder_uintptr_t	pad_binder;
+		__u32			fd;
+	};
+
+	binder_uintptr_t		cookie;
+};
+
+/* struct binder_buffer_object - object describing a userspace buffer
+ * @hdr:		common header structure
+ * @flags:		one or more BINDER_BUFFER_* flags
+ * @buffer:		address of the buffer
+ * @length:		length of the buffer
+ * @parent:		index in offset array pointing to parent buffer
+ * @parent_offset:	offset in @parent pointing to this buffer
+ *
+ * A binder_buffer object represents an object that the
+ * binder kernel driver can copy verbatim to the target
+ * address space. A buffer itself may be pointed to from
+ * within another buffer, meaning that the pointer inside
+ * that other buffer needs to be fixed up as well. This
+ * can be done by setting the BINDER_BUFFER_FLAG_HAS_PARENT
+ * flag in @flags, by setting @parent buffer to the index
+ * in the offset array pointing to the parent binder_buffer_object,
+ * and by setting @parent_offset to the offset in the parent buffer
+ * at which the pointer to this buffer is located.
+ */
+struct binder_buffer_object {
+	struct binder_object_header	hdr;
+	__u32				flags;
+	binder_uintptr_t		buffer;
+	binder_size_t			length;
+	binder_size_t			parent;
+	binder_size_t			parent_offset;
+};
+
+enum {
+	BINDER_BUFFER_FLAG_HAS_PARENT = 0x01,
+};
+
+/* struct binder_fd_array_object - object describing an array of fds in a buffer
+ * @hdr:		common header structure
+ * @pad:		padding to ensure correct alignment
+ * @num_fds:		number of file descriptors in the buffer
+ * @parent:		index in offset array to buffer holding the fd array
+ * @parent_offset:	start offset of fd array in the buffer
+ *
+ * A binder_fd_array object represents an array of file
+ * descriptors embedded in a binder_buffer_object. It is
+ * different from a regular binder_buffer_object because it
+ * describes a list of file descriptors to fix up, not an opaque
+ * blob of memory, and hence the kernel needs to treat it differently.
+ *
+ * An example of how this would be used is with Android's
+ * native_handle_t object, which is a struct with a list of integers
+ * and a list of file descriptors. The native_handle_t struct itself
+ * will be represented by a struct binder_buffer_objct, whereas the
+ * embedded list of file descriptors is represented by a
+ * struct binder_fd_array_object with that binder_buffer_object as
+ * a parent.
+ */
+struct binder_fd_array_object {
+	struct binder_object_header	hdr;
+	__u32				pad;
+	binder_size_t			num_fds;
+	binder_size_t			parent;
+	binder_size_t			parent_offset;
+};
+
 /*
  * On 64-bit platforms where user code may run in 32-bits the driver must
  * translate the buffer (and local binder) addresses appropriately.
@@ -162,6 +298,11 @@
 	} data;
 };
 
+struct binder_transaction_data_sg {
+	struct binder_transaction_data transaction_data;
+	binder_size_t buffers_size;
+};
+
 struct binder_ptr_cookie {
 	binder_uintptr_t ptr;
 	binder_uintptr_t cookie;
@@ -346,6 +487,12 @@
 	/*
 	 * void *: cookie
 	 */
+
+	BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg),
+	BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg),
+	/*
+	 * binder_transaction_data_sg: the sent command.
+	 */
 };
 
 #endif /* _UAPI_LINUX_BINDER_H */
diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h
index 9692cda..c48d93a 100644
--- a/include/uapi/linux/can.h
+++ b/include/uapi/linux/can.h
@@ -196,5 +196,6 @@
 };
 
 #define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
+#define CAN_RAW_FILTER_MAX 512 /* maximum number of can_filter set via setsockopt() */
 
 #endif /* !_UAPI_CAN_H */
diff --git a/include/uapi/linux/fib_rules.h b/include/uapi/linux/fib_rules.h
index ce19c5b..bbf02a6 100644
--- a/include/uapi/linux/fib_rules.h
+++ b/include/uapi/linux/fib_rules.h
@@ -29,6 +29,11 @@
 	__u32		flags;
 };
 
+struct fib_rule_uid_range {
+	__u32		start;
+	__u32		end;
+};
+
 enum {
 	FRA_UNSPEC,
 	FRA_DST,	/* destination address */
@@ -49,8 +54,9 @@
 	FRA_TABLE,	/* Extended table id */
 	FRA_FWMASK,	/* mask for netfilter mark */
 	FRA_OIFNAME,
-	FRA_UID_START,	/* UID range */
-	FRA_UID_END,
+	FRA_PAD,
+	FRA_L3MDEV,	/* iif or oif is l3mdev goto its table */
+	FRA_UID_RANGE,	/* UID range */
 	__FRA_MAX
 };
 
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index f15d980..cd0c1a1 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -160,6 +160,8 @@
 #define FITHAW		_IOWR('X', 120, int)	/* Thaw */
 #define FITRIM		_IOWR('X', 121, struct fstrim_range)	/* Trim */
 
+#define FIDTRIM	_IOWR('f', 128, struct fstrim_range)	/* Deep discard trim */
+
 #define	FS_IOC_GETFLAGS			_IOR('f', 1, long)
 #define	FS_IOC_SETFLAGS			_IOW('f', 2, long)
 #define	FS_IOC_GETVERSION		_IOR('v', 1, long)
diff --git a/include/uapi/linux/hw_breakpoint.h b/include/uapi/linux/hw_breakpoint.h
index b04000a..2b65efd 100644
--- a/include/uapi/linux/hw_breakpoint.h
+++ b/include/uapi/linux/hw_breakpoint.h
@@ -4,7 +4,11 @@
 enum {
 	HW_BREAKPOINT_LEN_1 = 1,
 	HW_BREAKPOINT_LEN_2 = 2,
+	HW_BREAKPOINT_LEN_3 = 3,
 	HW_BREAKPOINT_LEN_4 = 4,
+	HW_BREAKPOINT_LEN_5 = 5,
+	HW_BREAKPOINT_LEN_6 = 6,
+	HW_BREAKPOINT_LEN_7 = 7,
 	HW_BREAKPOINT_LEN_8 = 8,
 };
 
diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h
index e4c0a35..e347b24 100644
--- a/include/uapi/linux/hyperv.h
+++ b/include/uapi/linux/hyperv.h
@@ -313,6 +313,7 @@
 #define HV_INVALIDARG			0x80070057
 #define HV_GUID_NOTFOUND		0x80041002
 #define HV_ERROR_ALREADY_EXISTS		0x80070050
+#define HV_ERROR_DISK_FULL		0x80070070
 
 #define ADDR_FAMILY_NONE	0x00
 #define ADDR_FAMILY_IPV4	0x01
diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h
index 9cf2394..752f5dc 100644
--- a/include/uapi/linux/if.h
+++ b/include/uapi/linux/if.h
@@ -19,14 +19,20 @@
 #ifndef _LINUX_IF_H
 #define _LINUX_IF_H
 
+#include <linux/libc-compat.h>          /* for compatibility with glibc */
 #include <linux/types.h>		/* for "__kernel_caddr_t" et al	*/
 #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
 #include <linux/compiler.h>		/* for "__user" et al           */
 
+#if __UAPI_DEF_IF_IFNAMSIZ
 #define	IFNAMSIZ	16
+#endif /* __UAPI_DEF_IF_IFNAMSIZ */
 #define	IFALIASZ	256
 #include <linux/hdlc/ioctl.h>
 
+/* For glibc compatibility. An empty enum does not compile. */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 && \
+    __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0
 /**
  * enum net_device_flags - &struct net_device flags
  *
@@ -68,6 +74,8 @@
  * @IFF_ECHO: echo sent packets. Volatile.
  */
 enum net_device_flags {
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
 	IFF_UP				= 1<<0,  /* sysfs */
 	IFF_BROADCAST			= 1<<1,  /* volatile */
 	IFF_DEBUG			= 1<<2,  /* sysfs */
@@ -84,11 +92,17 @@
 	IFF_PORTSEL			= 1<<13, /* sysfs */
 	IFF_AUTOMEDIA			= 1<<14, /* sysfs */
 	IFF_DYNAMIC			= 1<<15, /* sysfs */
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
 	IFF_LOWER_UP			= 1<<16, /* volatile */
 	IFF_DORMANT			= 1<<17, /* volatile */
 	IFF_ECHO			= 1<<18, /* volatile */
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
 };
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 && __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 */
 
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
 #define IFF_UP				IFF_UP
 #define IFF_BROADCAST			IFF_BROADCAST
 #define IFF_DEBUG			IFF_DEBUG
@@ -105,9 +119,13 @@
 #define IFF_PORTSEL			IFF_PORTSEL
 #define IFF_AUTOMEDIA			IFF_AUTOMEDIA
 #define IFF_DYNAMIC			IFF_DYNAMIC
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
+
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
 #define IFF_LOWER_UP			IFF_LOWER_UP
 #define IFF_DORMANT			IFF_DORMANT
 #define IFF_ECHO			IFF_ECHO
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
 
 #define IFF_VOLATILE	(IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
 		IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
@@ -166,6 +184,8 @@
  *	being very small might be worth keeping for clean configuration.
  */
 
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_IFMAP
 struct ifmap {
 	unsigned long mem_start;
 	unsigned long mem_end;
@@ -175,6 +195,7 @@
 	unsigned char port;
 	/* 3 bytes spare */
 };
+#endif /* __UAPI_DEF_IF_IFMAP */
 
 struct if_settings {
 	unsigned int type;	/* Type of physical device or protocol */
@@ -200,6 +221,8 @@
  * remainder may be interface specific.
  */
 
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_IFREQ
 struct ifreq {
 #define IFHWADDRLEN	6
 	union
@@ -223,6 +246,7 @@
 		struct	if_settings ifru_settings;
 	} ifr_ifru;
 };
+#endif /* __UAPI_DEF_IF_IFREQ */
 
 #define ifr_name	ifr_ifrn.ifrn_name	/* interface name 	*/
 #define ifr_hwaddr	ifr_ifru.ifru_hwaddr	/* MAC address 		*/
@@ -249,6 +273,8 @@
  * must know all networks accessible).
  */
 
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_IFCONF
 struct ifconf  {
 	int	ifc_len;			/* size of buffer	*/
 	union {
@@ -256,6 +282,8 @@
 		struct ifreq __user *ifcu_req;
 	} ifc_ifcu;
 };
+#endif /* __UAPI_DEF_IF_IFCONF */
+
 #define	ifc_buf	ifc_ifcu.ifcu_buf		/* buffer address	*/
 #define	ifc_req	ifc_ifcu.ifcu_req		/* array of structures	*/
 
diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h
index 68a1f71..c7f189b 100644
--- a/include/uapi/linux/inet_diag.h
+++ b/include/uapi/linux/inet_diag.h
@@ -72,6 +72,8 @@
 	INET_DIAG_BC_AUTO,
 	INET_DIAG_BC_S_COND,
 	INET_DIAG_BC_D_COND,
+	INET_DIAG_BC_DEV_COND,   /* u32 ifindex */
+	INET_DIAG_BC_MARK_COND,
 };
 
 struct inet_diag_hostcond {
@@ -81,6 +83,11 @@
 	__be32	addr[0];
 };
 
+struct inet_diag_markcond {
+	__u32 mark;
+	__u32 mask;
+};
+
 /* Base info structure. It contains socket identity (addrs/ports/cookie)
  * and, alas, the information shown by netstat. */
 struct inet_diag_msg {
@@ -113,9 +120,13 @@
 	INET_DIAG_DCTCPINFO,
 	INET_DIAG_PROTOCOL,  /* response attribute only */
 	INET_DIAG_SKV6ONLY,
+	INET_DIAG_LOCALS,
+	INET_DIAG_PEERS,
+	INET_DIAG_PAD,
+	INET_DIAG_MARK,
 };
 
-#define INET_DIAG_MAX INET_DIAG_SKV6ONLY
+#define INET_DIAG_MAX INET_DIAG_MARK
 
 /* INET_DIAG_MEM */
 
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index 2b15338..c462f1d 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -175,6 +175,16 @@
 	DEVCONF_USE_OIF_ADDRS_ONLY,
 	DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT,
 	DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN,
+	DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
+	DEVCONF_DROP_UNSOLICITED_NA,
+	DEVCONF_KEEP_ADDR_ON_DOWN,
+	DEVCONF_RTR_SOLICIT_MAX_INTERVAL,
+	DEVCONF_SEG6_ENABLED,
+	DEVCONF_SEG6_REQUIRE_HMAC,
+	DEVCONF_ENHANCED_DAD,
+	DEVCONF_ADDR_GEN_MODE,
+	DEVCONF_DISABLE_POLICY,
+	DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN,
 	DEVCONF_MAX
 };
 
diff --git a/include/uapi/linux/ipv6_route.h b/include/uapi/linux/ipv6_route.h
index f6598d1..316e838 100644
--- a/include/uapi/linux/ipv6_route.h
+++ b/include/uapi/linux/ipv6_route.h
@@ -34,7 +34,7 @@
 #define RTF_PREF(pref)	((pref) << 27)
 #define RTF_PREF_MASK	0x18000000
 
-#define RTF_PCPU	0x40000000
+#define RTF_PCPU	0x40000000	/* read-only: can not be set by user */
 #define RTF_LOCAL	0x80000000
 
 
diff --git a/include/uapi/linux/libc-compat.h b/include/uapi/linux/libc-compat.h
index 7d024ce..e4f048e 100644
--- a/include/uapi/linux/libc-compat.h
+++ b/include/uapi/linux/libc-compat.h
@@ -51,6 +51,40 @@
 /* We have included glibc headers... */
 #if defined(__GLIBC__)
 
+/* Coordinate with glibc net/if.h header. */
+#if defined(_NET_IF_H) && defined(__USE_MISC)
+
+/* GLIBC headers included first so don't define anything
+ * that would already be defined. */
+
+#define __UAPI_DEF_IF_IFCONF 0
+#define __UAPI_DEF_IF_IFMAP 0
+#define __UAPI_DEF_IF_IFNAMSIZ 0
+#define __UAPI_DEF_IF_IFREQ 0
+/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0
+/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
+
+#else /* _NET_IF_H */
+
+/* Linux headers included first, and we must define everything
+ * we need. The expectation is that glibc will check the
+ * __UAPI_DEF_* defines and adjust appropriately. */
+
+#define __UAPI_DEF_IF_IFCONF 1
+#define __UAPI_DEF_IF_IFMAP 1
+#define __UAPI_DEF_IF_IFNAMSIZ 1
+#define __UAPI_DEF_IF_IFREQ 1
+/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
+/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+
+#endif /* _NET_IF_H */
+
 /* Coordinate with glibc netinet/in.h header. */
 #if defined(_NETINET_IN_H)
 
@@ -117,6 +151,16 @@
  * that we need. */
 #else /* !defined(__GLIBC__) */
 
+/* Definitions for if.h */
+#define __UAPI_DEF_IF_IFCONF 1
+#define __UAPI_DEF_IF_IFMAP 1
+#define __UAPI_DEF_IF_IFNAMSIZ 1
+#define __UAPI_DEF_IF_IFREQ 1
+/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
+/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+
 /* Definitions for in.h */
 #define __UAPI_DEF_IN_ADDR		1
 #define __UAPI_DEF_IN_IPPROTO		1
diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
index cfb5c40..e97d5b3 100644
--- a/include/uapi/linux/magic.h
+++ b/include/uapi/linux/magic.h
@@ -52,7 +52,7 @@
 #define REISER2FS_SUPER_MAGIC_STRING	"ReIsEr2Fs"
 #define REISER2FS_JR_SUPER_MAGIC_STRING	"ReIsEr3Fs"
 
-#define SDCARDFS_SUPER_MAGIC	0xb550ca10
+#define SDCARDFS_SUPER_MAGIC	0x5dca2df5
 
 #define SMB_SUPER_MAGIC		0x517B
 #define CGROUP_SUPER_MAGIC	0x27e0eb
diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
index f095155..0dba4e4 100644
--- a/include/uapi/linux/netlink.h
+++ b/include/uapi/linux/netlink.h
@@ -107,8 +107,10 @@
 #define NETLINK_PKTINFO			3
 #define NETLINK_BROADCAST_ERROR		4
 #define NETLINK_NO_ENOBUFS		5
+#ifndef __KERNEL__
 #define NETLINK_RX_RING			6
 #define NETLINK_TX_RING			7
+#endif
 #define NETLINK_LISTEN_ALL_NSID		8
 #define NETLINK_LIST_MEMBERSHIPS	9
 #define NETLINK_CAP_ACK			10
@@ -134,6 +136,7 @@
 	__u32		nm_gid;
 };
 
+#ifndef __KERNEL__
 enum nl_mmap_status {
 	NL_MMAP_STATUS_UNUSED,
 	NL_MMAP_STATUS_RESERVED,
@@ -145,6 +148,7 @@
 #define NL_MMAP_MSG_ALIGNMENT		NLMSG_ALIGNTO
 #define NL_MMAP_MSG_ALIGN(sz)		__ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
 #define NL_MMAP_HDRLEN			NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
+#endif
 
 #define NET_MAJOR 36		/* Major 36 is reserved for networking 						*/
 
diff --git a/include/uapi/linux/netlink_diag.h b/include/uapi/linux/netlink_diag.h
index f2159d3..d793993 100644
--- a/include/uapi/linux/netlink_diag.h
+++ b/include/uapi/linux/netlink_diag.h
@@ -48,6 +48,8 @@
 
 #define NDIAG_SHOW_MEMINFO	0x00000001 /* show memory info of a socket */
 #define NDIAG_SHOW_GROUPS	0x00000002 /* show groups of a netlink socket */
+#ifndef __KERNEL__
 #define NDIAG_SHOW_RING_CFG	0x00000004 /* show ring configuration */
+#endif
 
 #endif
diff --git a/include/uapi/linux/packet_diag.h b/include/uapi/linux/packet_diag.h
index d08c63f..0c5d5dd 100644
--- a/include/uapi/linux/packet_diag.h
+++ b/include/uapi/linux/packet_diag.h
@@ -64,7 +64,7 @@
 	__u32	pdmc_count;
 	__u16	pdmc_type;
 	__u16	pdmc_alen;
-	__u8	pdmc_addr[MAX_ADDR_LEN];
+	__u8	pdmc_addr[32]; /* MAX_ADDR_LEN */
 };
 
 struct packet_diag_ring {
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 77d602f..c1af9b3 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -187,13 +187,6 @@
 
 #define PR_SET_FP_MODE		45
 #define PR_GET_FP_MODE		46
-
-/* Sets the timerslack for arbitrary threads
- * arg2 slack value, 0 means "use default"
- * arg3 pid of the thread whose timer slack needs to be set
- */
-#define PR_SET_TIMERSLACK_PID	47
-
 # define PR_FP_MODE_FR		(1 << 0)	/* 64b FP registers */
 # define PR_FP_MODE_FRE		(1 << 1)	/* 32b compatibility */
 
@@ -204,6 +197,12 @@
 # define PR_CAP_AMBIENT_LOWER		3
 # define PR_CAP_AMBIENT_CLEAR_ALL	4
 
+/* Sets the timerslack for arbitrary threads
+ * arg2 slack value, 0 means "use default"
+ * arg3 pid of the thread whose timer slack needs to be set
+ */
+#define PR_SET_TIMERSLACK_PID	127
+
 #define PR_SET_VMA		0x53564d41
 # define PR_SET_VMA_ANON_NAME		0
 
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 355eea2..d7d7599 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -311,6 +311,8 @@
 	RTA_PREF,
 	RTA_ENCAP_TYPE,
 	RTA_ENCAP,
+	RTA_EXPIRES,
+	RTA_PAD,
 	RTA_UID,
 	__RTA_MAX
 };
@@ -344,7 +346,7 @@
 #define RTNH_F_OFFLOAD		8	/* offloaded route */
 #define RTNH_F_LINKDOWN		16	/* carrier-down on nexthop */
 
-#define RTNH_COMPARE_MASK	(RTNH_F_DEAD | RTNH_F_LINKDOWN)
+#define RTNH_COMPARE_MASK	(RTNH_F_DEAD | RTNH_F_LINKDOWN | RTNH_F_OFFLOAD)
 
 /* Macros to handle hexthops */
 
diff --git a/include/uapi/linux/sysctl.h b/include/uapi/linux/sysctl.h
index 0956373..d18980e 100644
--- a/include/uapi/linux/sysctl.h
+++ b/include/uapi/linux/sysctl.h
@@ -570,6 +570,7 @@
 	NET_IPV6_PROXY_NDP=23,
 	NET_IPV6_ACCEPT_SOURCE_ROUTE=25,
 	NET_IPV6_ACCEPT_RA_FROM_LOCAL=26,
+	NET_IPV6_ACCEPT_RA_RT_INFO_MIN_PLEN=27,
 	__NET_IPV6_MAX
 };
 
diff --git a/include/uapi/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h
index 331499d..9ce10d4 100644
--- a/include/uapi/linux/usb/ch11.h
+++ b/include/uapi/linux/usb/ch11.h
@@ -22,6 +22,9 @@
  */
 #define USB_MAXCHILDREN		31
 
+/* See USB 3.1 spec Table 10-5 */
+#define USB_SS_MAXPORTS		15
+
 /*
  * Hub request types
  */
diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
index 4338eb7..779a62a 100644
--- a/include/uapi/linux/usb/ch9.h
+++ b/include/uapi/linux/usb/ch9.h
@@ -954,6 +954,7 @@
 	USB_SPEED_HIGH,				/* usb 2.0 */
 	USB_SPEED_WIRELESS,			/* wireless (usb 2.5) */
 	USB_SPEED_SUPER,			/* usb 3.0 */
+	USB_SPEED_SUPER_PLUS,			/* usb 3.1 */
 };
 
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index a0e87d1..421d274 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -621,6 +621,9 @@
 #define V4L2_PIX_FMT_JPGL	v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
 #define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
+#define V4L2_PIX_FMT_Y8I      v4l2_fourcc('Y', '8', 'I', ' ') /* Greyscale 8-bit L/R interleaved */
+#define V4L2_PIX_FMT_Y12I     v4l2_fourcc('Y', '1', '2', 'I') /* Greyscale 12-bit L/R interleaved */
+#define V4L2_PIX_FMT_Z16      v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */
 
 /* SDR formats - used only for Software Defined Radio devices */
 #define V4L2_SDR_FMT_CU8          v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */
diff --git a/include/uapi/scsi/cxlflash_ioctl.h b/include/uapi/scsi/cxlflash_ioctl.h
index 831351b..2302f3c 100644
--- a/include/uapi/scsi/cxlflash_ioctl.h
+++ b/include/uapi/scsi/cxlflash_ioctl.h
@@ -31,6 +31,16 @@
 };
 
 /*
+ * Return flag definitions available to all ioctls
+ *
+ * Similar to the input flags, these are grown from the bottom-up with the
+ * intention that ioctl-specific return flag definitions would grow from the
+ * top-down, allowing the two sets to co-exist. While not required/enforced
+ * at this time, this provides future flexibility.
+ */
+#define DK_CXLFLASH_ALL_PORTS_ACTIVE	0x0000000000000001ULL
+
+/*
  * Notes:
  * -----
  * The 'context_id' field of all ioctl structures contains the context
diff --git a/include/uapi/video/adf.h b/include/uapi/video/adf.h
new file mode 100644
index 0000000..c5d2e62
--- /dev/null
+++ b/include/uapi/video/adf.h
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _UAPI_VIDEO_ADF_H_
+#define _UAPI_VIDEO_ADF_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_mode.h>
+
+#define ADF_NAME_LEN 32
+#define ADF_MAX_CUSTOM_DATA_SIZE 4096
+
+enum adf_interface_type {
+	ADF_INTF_DSI = 0,
+	ADF_INTF_eDP = 1,
+	ADF_INTF_DPI = 2,
+	ADF_INTF_VGA = 3,
+	ADF_INTF_DVI = 4,
+	ADF_INTF_HDMI = 5,
+	ADF_INTF_MEMORY = 6,
+	ADF_INTF_TYPE_DEVICE_CUSTOM = 128,
+	ADF_INTF_TYPE_MAX = (~(__u32)0),
+};
+
+#define ADF_INTF_FLAG_PRIMARY (1 << 0)
+#define ADF_INTF_FLAG_EXTERNAL (1 << 1)
+
+enum adf_event_type {
+	ADF_EVENT_VSYNC = 0,
+	ADF_EVENT_HOTPLUG = 1,
+	ADF_EVENT_DEVICE_CUSTOM = 128,
+	ADF_EVENT_TYPE_MAX = 255,
+};
+
+/**
+ * struct adf_set_event - start or stop subscribing to ADF events
+ *
+ * @type: the type of event to (un)subscribe
+ * @enabled: subscribe or unsubscribe
+ *
+ * After subscribing to an event, userspace may poll() the ADF object's fd
+ * to wait for events or read() to consume the event's data.
+ *
+ * ADF reserves event types 0 to %ADF_EVENT_DEVICE_CUSTOM-1 for its own events.
+ * Devices may use event types %ADF_EVENT_DEVICE_CUSTOM to %ADF_EVENT_TYPE_MAX-1
+ * for driver-private events.
+ */
+struct adf_set_event {
+	__u8 type;
+	__u8 enabled;
+};
+
+/**
+ * struct adf_event - common header for ADF event data
+ *
+ * @type: event type
+ * @length: total size of event data, header inclusive
+ */
+struct adf_event {
+	__u8 type;
+	__u32 length;
+};
+
+/**
+ * struct adf_vsync_event - ADF vsync event
+ *
+ * @base: event header (see &struct adf_event)
+ * @timestamp: time of vsync event, in nanoseconds
+ */
+struct adf_vsync_event {
+	struct adf_event base;
+	__aligned_u64 timestamp;
+};
+
+/**
+ * struct adf_vsync_event - ADF display hotplug event
+ *
+ * @base: event header (see &struct adf_event)
+ * @connected: whether a display is now connected to the interface
+ */
+struct adf_hotplug_event {
+	struct adf_event base;
+	__u8 connected;
+};
+
+#define ADF_MAX_PLANES 4
+/**
+ * struct adf_buffer_config - description of buffer displayed by adf_post_config
+ *
+ * @overlay_engine: id of the target overlay engine
+ * @w: width of display region in pixels
+ * @h: height of display region in pixels
+ * @format: DRM-style fourcc, see drm_fourcc.h for standard formats
+ * @fd: dma_buf fd for each plane
+ * @offset: location of first pixel to scan out, in bytes
+ * @pitch: stride (i.e. length of a scanline including padding) in bytes
+ * @n_planes: number of planes in buffer
+ * @acquire_fence: sync_fence fd which will clear when the buffer is
+ *	ready for display, or <0 if the buffer is already ready
+ */
+struct adf_buffer_config {
+	__u32 overlay_engine;
+
+	__u32 w;
+	__u32 h;
+	__u32 format;
+
+	__s32 fd[ADF_MAX_PLANES];
+	__u32 offset[ADF_MAX_PLANES];
+	__u32 pitch[ADF_MAX_PLANES];
+	__u8 n_planes;
+
+	__s32 acquire_fence;
+};
+#define ADF_MAX_BUFFERS (4096 / sizeof(struct adf_buffer_config))
+
+/**
+ * struct adf_post_config - request to flip to a new set of buffers
+ *
+ * @n_interfaces: number of interfaces targeted by the flip (input)
+ * @interfaces: ids of interfaces targeted by the flip (input)
+ * @n_bufs: number of buffers displayed (input)
+ * @bufs: description of buffers displayed (input)
+ * @custom_data_size: size of driver-private data (input)
+ * @custom_data: driver-private data (input)
+ * @complete_fence: sync_fence fd which will clear when this
+ *	configuration has left the screen (output)
+ */
+struct adf_post_config {
+	size_t n_interfaces;
+	__u32 __user *interfaces;
+
+	size_t n_bufs;
+	struct adf_buffer_config __user *bufs;
+
+	size_t custom_data_size;
+	void __user *custom_data;
+
+	__s32 complete_fence;
+};
+#define ADF_MAX_INTERFACES (4096 / sizeof(__u32))
+
+/**
+ * struct adf_simple_buffer_allocate - request to allocate a "simple" buffer
+ *
+ * @w: width of buffer in pixels (input)
+ * @h: height of buffer in pixels (input)
+ * @format: DRM-style fourcc (input)
+ *
+ * @fd: dma_buf fd (output)
+ * @offset: location of first pixel, in bytes (output)
+ * @pitch: length of a scanline including padding, in bytes (output)
+ *
+ * Simple buffers are analogous to DRM's "dumb" buffers.  They have a single
+ * plane of linear RGB data which can be allocated and scanned out without
+ * any driver-private ioctls or data.
+ *
+ * @format must be a standard RGB format defined in drm_fourcc.h.
+ *
+ * ADF clients must NOT assume that an interface can scan out a simple buffer
+ * allocated by a different ADF interface, even if the two interfaces belong to
+ * the same ADF device.
+ */
+struct adf_simple_buffer_alloc {
+	__u16 w;
+	__u16 h;
+	__u32 format;
+
+	__s32 fd;
+	__u32 offset;
+	__u32 pitch;
+};
+
+/**
+ * struct adf_simple_post_config - request to flip to a single buffer without
+ * driver-private data
+ *
+ * @buf: description of buffer displayed (input)
+ * @complete_fence: sync_fence fd which will clear when this buffer has left the
+ * screen (output)
+ */
+struct adf_simple_post_config {
+	struct adf_buffer_config buf;
+	__s32 complete_fence;
+};
+
+/**
+ * struct adf_attachment_config - description of attachment between an overlay
+ * engine and an interface
+ *
+ * @overlay_engine: id of the overlay engine
+ * @interface: id of the interface
+ */
+struct adf_attachment_config {
+	__u32 overlay_engine;
+	__u32 interface;
+};
+
+/**
+ * struct adf_device_data - describes a display device
+ *
+ * @name: display device's name
+ * @n_attachments: the number of current attachments
+ * @attachments: list of current attachments
+ * @n_allowed_attachments: the number of allowed attachments
+ * @allowed_attachments: list of allowed attachments
+ * @custom_data_size: size of driver-private data
+ * @custom_data: driver-private data
+ */
+struct adf_device_data {
+	char name[ADF_NAME_LEN];
+
+	size_t n_attachments;
+	struct adf_attachment_config __user *attachments;
+
+	size_t n_allowed_attachments;
+	struct adf_attachment_config __user *allowed_attachments;
+
+	size_t custom_data_size;
+	void __user *custom_data;
+};
+#define ADF_MAX_ATTACHMENTS (4096 / sizeof(struct adf_attachment_config))
+
+/**
+ * struct adf_device_data - describes a display interface
+ *
+ * @name: display interface's name
+ * @type: interface type (see enum @adf_interface_type)
+ * @id: which interface of type @type;
+ *	e.g. interface DSI.1 -> @type=@ADF_INTF_TYPE_DSI, @id=1
+ * @flags: informational flags (bitmask of %ADF_INTF_FLAG_* values)
+ * @dpms_state: DPMS state (one of @DRM_MODE_DPMS_* defined in drm_mode.h)
+ * @hotplug_detect: whether a display is plugged in
+ * @width_mm: screen width in millimeters, or 0 if unknown
+ * @height_mm: screen height in millimeters, or 0 if unknown
+ * @current_mode: current display mode
+ * @n_available_modes: the number of hardware display modes
+ * @available_modes: list of hardware display modes
+ * @custom_data_size: size of driver-private data
+ * @custom_data: driver-private data
+ */
+struct adf_interface_data {
+	char name[ADF_NAME_LEN];
+
+	__u32 type;
+	__u32 id;
+	/* e.g. type=ADF_INTF_TYPE_DSI, id=1 => DSI.1 */
+	__u32 flags;
+
+	__u8 dpms_state;
+	__u8 hotplug_detect;
+	__u16 width_mm;
+	__u16 height_mm;
+
+	struct drm_mode_modeinfo current_mode;
+	size_t n_available_modes;
+	struct drm_mode_modeinfo __user *available_modes;
+
+	size_t custom_data_size;
+	void __user *custom_data;
+};
+#define ADF_MAX_MODES (4096 / sizeof(struct drm_mode_modeinfo))
+
+/**
+ * struct adf_overlay_engine_data - describes an overlay engine
+ *
+ * @name: overlay engine's name
+ * @n_supported_formats: number of supported formats
+ * @supported_formats: list of supported formats
+ * @custom_data_size: size of driver-private data
+ * @custom_data: driver-private data
+ */
+struct adf_overlay_engine_data {
+	char name[ADF_NAME_LEN];
+
+	size_t n_supported_formats;
+	__u32 __user *supported_formats;
+
+	size_t custom_data_size;
+	void __user *custom_data;
+};
+#define ADF_MAX_SUPPORTED_FORMATS (4096 / sizeof(__u32))
+
+#define ADF_IOCTL_TYPE		'D'
+#define ADF_IOCTL_NR_CUSTOM	128
+
+#define ADF_SET_EVENT		_IOW(ADF_IOCTL_TYPE, 0, struct adf_set_event)
+#define ADF_BLANK		_IOW(ADF_IOCTL_TYPE, 1, __u8)
+#define ADF_POST_CONFIG		_IOW(ADF_IOCTL_TYPE, 2, struct adf_post_config)
+#define ADF_SET_MODE		_IOW(ADF_IOCTL_TYPE, 3, \
+					struct drm_mode_modeinfo)
+#define ADF_GET_DEVICE_DATA	_IOR(ADF_IOCTL_TYPE, 4, struct adf_device_data)
+#define ADF_GET_INTERFACE_DATA	_IOR(ADF_IOCTL_TYPE, 5, \
+					struct adf_interface_data)
+#define ADF_GET_OVERLAY_ENGINE_DATA \
+				_IOR(ADF_IOCTL_TYPE, 6, \
+					struct adf_overlay_engine_data)
+#define ADF_SIMPLE_POST_CONFIG	_IOW(ADF_IOCTL_TYPE, 7, \
+					struct adf_simple_post_config)
+#define ADF_SIMPLE_BUFFER_ALLOC	_IOW(ADF_IOCTL_TYPE, 8, \
+					struct adf_simple_buffer_alloc)
+#define ADF_ATTACH		_IOW(ADF_IOCTL_TYPE, 9, \
+					struct adf_attachment_config)
+#define ADF_DETACH		_IOW(ADF_IOCTL_TYPE, 10, \
+					struct adf_attachment_config)
+
+#endif /* _UAPI_VIDEO_ADF_H_ */
diff --git a/include/video/adf.h b/include/video/adf.h
new file mode 100644
index 0000000..34f10e5
--- /dev/null
+++ b/include/video/adf.h
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VIDEO_ADF_H
+#define _VIDEO_ADF_H
+
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/idr.h>
+#include <linux/kref.h>
+#include <linux/kthread.h>
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <uapi/video/adf.h>
+#include "sync.h"
+
+struct adf_obj;
+struct adf_obj_ops;
+struct adf_device;
+struct adf_device_ops;
+struct adf_interface;
+struct adf_interface_ops;
+struct adf_overlay_engine;
+struct adf_overlay_engine_ops;
+
+/**
+ * struct adf_buffer - buffer displayed by adf_post
+ *
+ * @overlay_engine: target overlay engine
+ * @w: width of display region in pixels
+ * @h: height of display region in pixels
+ * @format: DRM-style fourcc, see drm_fourcc.h for standard formats
+ * @dma_bufs: dma_buf for each plane
+ * @offset: location of first pixel to scan out, in bytes
+ * @pitch: length of a scanline including padding, in bytes
+ * @n_planes: number of planes in buffer
+ * @acquire_fence: sync_fence which will clear when the buffer is
+ *	ready for display
+ *
+ * &struct adf_buffer is the in-kernel counterpart to the userspace-facing
+ * &struct adf_buffer_config.
+ */
+struct adf_buffer {
+	struct adf_overlay_engine *overlay_engine;
+
+	u32 w;
+	u32 h;
+	u32 format;
+
+	struct dma_buf *dma_bufs[ADF_MAX_PLANES];
+	u32 offset[ADF_MAX_PLANES];
+	u32 pitch[ADF_MAX_PLANES];
+	u8 n_planes;
+
+	struct sync_fence *acquire_fence;
+};
+
+/**
+ * struct adf_buffer_mapping - state for mapping a &struct adf_buffer into the
+ * display device
+ *
+ * @attachments: dma-buf attachment for each plane
+ * @sg_tables: SG tables for each plane
+ */
+struct adf_buffer_mapping {
+	struct dma_buf_attachment *attachments[ADF_MAX_PLANES];
+	struct sg_table *sg_tables[ADF_MAX_PLANES];
+};
+
+/**
+ * struct adf_post - request to flip to a new set of buffers
+ *
+ * @n_bufs: number of buffers displayed
+ * @bufs: buffers displayed
+ * @mappings: in-device mapping state for each buffer
+ * @custom_data_size: size of driver-private data
+ * @custom_data: driver-private data
+ *
+ * &struct adf_post is the in-kernel counterpart to the userspace-facing
+ * &struct adf_post_config.
+ */
+struct adf_post {
+	size_t n_bufs;
+	struct adf_buffer *bufs;
+	struct adf_buffer_mapping *mappings;
+
+	size_t custom_data_size;
+	void *custom_data;
+};
+
+/**
+ * struct adf_attachment - description of attachment between an overlay engine
+ * and an interface
+ *
+ * @overlay_engine: the overlay engine
+ * @interface: the interface
+ *
+ * &struct adf_attachment is the in-kernel counterpart to the userspace-facing
+ * &struct adf_attachment_config.
+ */
+struct adf_attachment {
+	struct adf_overlay_engine *overlay_engine;
+	struct adf_interface *interface;
+};
+
+struct adf_pending_post {
+	struct list_head head;
+	struct adf_post config;
+	void *state;
+};
+
+enum adf_obj_type {
+	ADF_OBJ_OVERLAY_ENGINE = 0,
+	ADF_OBJ_INTERFACE = 1,
+	ADF_OBJ_DEVICE = 2,
+};
+
+/**
+ * struct adf_obj_ops - common ADF object implementation ops
+ *
+ * @open: handle opening the object's device node
+ * @release: handle releasing an open file
+ * @ioctl: handle custom ioctls
+ *
+ * @supports_event: return whether the object supports generating events of type
+ *	@type
+ * @set_event: enable or disable events of type @type
+ * @event_type_str: return a string representation of custom event @type
+ *	(@type >= %ADF_EVENT_DEVICE_CUSTOM).
+ *
+ * @custom_data: copy up to %ADF_MAX_CUSTOM_DATA_SIZE bytes of driver-private
+ *	data into @data (allocated by ADF) and return the number of copied bytes
+ *	in @size.  Return 0 on success or an error code (<0) on failure.
+ */
+struct adf_obj_ops {
+	/* optional */
+	int (*open)(struct adf_obj *obj, struct inode *inode,
+			struct file *file);
+	/* optional */
+	void (*release)(struct adf_obj *obj, struct inode *inode,
+			struct file *file);
+	/* optional */
+	long (*ioctl)(struct adf_obj *obj, unsigned int cmd, unsigned long arg);
+
+	/* optional */
+	bool (*supports_event)(struct adf_obj *obj, enum adf_event_type type);
+	/* required if supports_event is implemented */
+	void (*set_event)(struct adf_obj *obj, enum adf_event_type type,
+			bool enabled);
+	/* optional */
+	const char *(*event_type_str)(struct adf_obj *obj,
+			enum adf_event_type type);
+
+	/* optional */
+	int (*custom_data)(struct adf_obj *obj, void *data, size_t *size);
+};
+
+struct adf_obj {
+	enum adf_obj_type type;
+	char name[ADF_NAME_LEN];
+	struct adf_device *parent;
+
+	const struct adf_obj_ops *ops;
+
+	struct device dev;
+
+	struct spinlock file_lock;
+	struct list_head file_list;
+
+	struct mutex event_lock;
+	struct rb_root event_refcount;
+
+	int id;
+	int minor;
+};
+
+/**
+ * struct adf_device_quirks - common display device quirks
+ *
+ * @buffer_padding: whether the last scanline of a buffer extends to the
+ * 	buffer's pitch (@ADF_BUFFER_PADDED_TO_PITCH) or just to the visible
+ * 	width (@ADF_BUFFER_UNPADDED)
+ */
+struct adf_device_quirks {
+	/* optional, defaults to ADF_BUFFER_PADDED_TO_PITCH */
+	enum {
+		ADF_BUFFER_PADDED_TO_PITCH = 0,
+		ADF_BUFFER_UNPADDED = 1,
+	} buffer_padding;
+};
+
+/**
+ * struct adf_device_ops - display device implementation ops
+ *
+ * @owner: device's module
+ * @base: common operations (see &struct adf_obj_ops)
+ * @quirks: device's quirks (see &struct adf_device_quirks)
+ *
+ * @attach: attach overlay engine @eng to interface @intf.  Return 0 on success
+ *	or error code (<0) on failure.
+ * @detach: detach overlay engine @eng from interface @intf.  Return 0 on
+ *	success or error code (<0) on failure.
+ *
+ * @validate_custom_format: validate the number and size of planes
+ *	in buffers with a custom format (i.e., not one of the @DRM_FORMAT_*
+ *	types defined in drm/drm_fourcc.h).  Return 0 if the buffer is valid or
+ *	an error code (<0) otherwise.
+ *
+ * @validate: validate that the proposed configuration @cfg is legal.  The
+ *	driver may optionally allocate and return some driver-private state in
+ *	@driver_state, which will be passed to the corresponding post().  The
+ *	driver may NOT commit any changes to hardware.  Return 0 if @cfg is
+ *	valid or an error code (<0) otherwise.
+ * @complete_fence: create a hardware-backed sync fence to be signaled when
+ *	@cfg is removed from the screen.  If unimplemented, ADF automatically
+ *	creates an sw_sync fence.  Return the sync fence on success or a
+ *	PTR_ERR() on failure.
+ * @post: flip @cfg onto the screen.  Wait for the display to begin scanning out
+ *	@cfg before returning.
+ * @advance_timeline: signal the sync fence for the last configuration to leave
+ *	the display.  If unimplemented, ADF automatically advances an sw_sync
+ *	timeline.
+ * @state_free: free driver-private state allocated during validate()
+ */
+struct adf_device_ops {
+	/* required */
+	struct module *owner;
+	const struct adf_obj_ops base;
+	/* optional */
+	const struct adf_device_quirks quirks;
+
+	/* optional */
+	int (*attach)(struct adf_device *dev, struct adf_overlay_engine *eng,
+			struct adf_interface *intf);
+	/* optional */
+	int (*detach)(struct adf_device *dev, struct adf_overlay_engine *eng,
+			struct adf_interface *intf);
+
+	/* required if any of the device's overlay engines supports at least one
+	   custom format */
+	int (*validate_custom_format)(struct adf_device *dev,
+			struct adf_buffer *buf);
+
+	/* required */
+	int (*validate)(struct adf_device *dev, struct adf_post *cfg,
+			void **driver_state);
+	/* optional */
+	struct sync_fence *(*complete_fence)(struct adf_device *dev,
+			struct adf_post *cfg, void *driver_state);
+	/* required */
+	void (*post)(struct adf_device *dev, struct adf_post *cfg,
+			void *driver_state);
+	/* required if complete_fence is implemented */
+	void (*advance_timeline)(struct adf_device *dev,
+			struct adf_post *cfg, void *driver_state);
+	/* required if validate allocates driver state */
+	void (*state_free)(struct adf_device *dev, void *driver_state);
+};
+
+struct adf_attachment_list {
+	struct adf_attachment attachment;
+	struct list_head head;
+};
+
+struct adf_device {
+	struct adf_obj base;
+	struct device *dev;
+
+	const struct adf_device_ops *ops;
+
+	struct mutex client_lock;
+
+	struct idr interfaces;
+	size_t n_interfaces;
+	struct idr overlay_engines;
+
+	struct list_head post_list;
+	struct mutex post_lock;
+	struct kthread_worker post_worker;
+	struct task_struct *post_thread;
+	struct kthread_work post_work;
+
+	struct list_head attached;
+	size_t n_attached;
+	struct list_head attach_allowed;
+	size_t n_attach_allowed;
+
+	struct adf_pending_post *onscreen;
+
+	struct sw_sync_timeline *timeline;
+	int timeline_max;
+};
+
+/**
+ * struct adf_interface_ops - display interface implementation ops
+ *
+ * @base: common operations (see &struct adf_obj_ops)
+ *
+ * @blank: change the display's DPMS state.  Return 0 on success or error
+ *	code (<0) on failure.
+ *
+ * @alloc_simple_buffer: allocate a buffer with the specified @w, @h, and
+ *	@format.  @format will be a standard RGB format (i.e.,
+ *	adf_format_is_rgb(@format) == true).  Return 0 on success or error code
+ *	(<0) on failure.  On success, return the buffer, offset, and pitch in
+ *	@dma_buf, @offset, and @pitch respectively.
+ * @describe_simple_post: provide driver-private data needed to post a single
+ *	buffer @buf.  Copy up to ADF_MAX_CUSTOM_DATA_SIZE bytes into @data
+ *	(allocated by ADF) and return the number of bytes in @size.  Return 0 on
+ *	success or error code (<0) on failure.
+ *
+ * @modeset: change the interface's mode.  @mode is not necessarily part of the
+ *	modelist passed to adf_hotplug_notify_connected(); the driver may
+ *	accept or reject custom modes at its discretion.  Return 0 on success or
+ *	error code (<0) if the mode could not be set.
+ *
+ * @screen_size: copy the screen dimensions in millimeters into @width_mm
+ *	and @height_mm.  Return 0 on success or error code (<0) if the display
+ *	dimensions are unknown.
+ *
+ * @type_str: return a string representation of custom @intf->type
+ *	(@intf->type >= @ADF_INTF_TYPE_DEVICE_CUSTOM).
+ */
+struct adf_interface_ops {
+	const struct adf_obj_ops base;
+
+	/* optional */
+	int (*blank)(struct adf_interface *intf, u8 state);
+
+	/* optional */
+	int (*alloc_simple_buffer)(struct adf_interface *intf,
+			u16 w, u16 h, u32 format,
+			struct dma_buf **dma_buf, u32 *offset, u32 *pitch);
+	/* optional */
+	int (*describe_simple_post)(struct adf_interface *intf,
+			struct adf_buffer *fb, void *data, size_t *size);
+
+	/* optional */
+	int (*modeset)(struct adf_interface *intf,
+			struct drm_mode_modeinfo *mode);
+
+	/* optional */
+	int (*screen_size)(struct adf_interface *intf, u16 *width_mm,
+			u16 *height_mm);
+
+	/* optional */
+	const char *(*type_str)(struct adf_interface *intf);
+};
+
+struct adf_interface {
+	struct adf_obj base;
+	const struct adf_interface_ops *ops;
+
+	struct drm_mode_modeinfo current_mode;
+
+	enum adf_interface_type type;
+	u32 idx;
+	u32 flags;
+
+	wait_queue_head_t vsync_wait;
+	ktime_t vsync_timestamp;
+	rwlock_t vsync_lock;
+
+	u8 dpms_state;
+
+	bool hotplug_detect;
+	struct drm_mode_modeinfo *modelist;
+	size_t n_modes;
+	rwlock_t hotplug_modelist_lock;
+};
+
+/**
+ * struct adf_interface_ops - overlay engine implementation ops
+ *
+ * @base: common operations (see &struct adf_obj_ops)
+ *
+ * @supported_formats: list of fourccs the overlay engine can scan out
+ * @n_supported_formats: length of supported_formats, up to
+ *	ADF_MAX_SUPPORTED_FORMATS
+ */
+struct adf_overlay_engine_ops {
+	const struct adf_obj_ops base;
+
+	/* required */
+	const u32 *supported_formats;
+	/* required */
+	const size_t n_supported_formats;
+};
+
+struct adf_overlay_engine {
+	struct adf_obj base;
+
+	const struct adf_overlay_engine_ops *ops;
+};
+
+#define adf_obj_to_device(ptr) \
+	container_of((ptr), struct adf_device, base)
+
+#define adf_obj_to_interface(ptr) \
+	container_of((ptr), struct adf_interface, base)
+
+#define adf_obj_to_overlay_engine(ptr) \
+	container_of((ptr), struct adf_overlay_engine, base)
+
+int __printf(4, 5) adf_device_init(struct adf_device *dev,
+		struct device *parent, const struct adf_device_ops *ops,
+		const char *fmt, ...);
+void adf_device_destroy(struct adf_device *dev);
+int __printf(7, 8) adf_interface_init(struct adf_interface *intf,
+		struct adf_device *dev, enum adf_interface_type type, u32 idx,
+		u32 flags, const struct adf_interface_ops *ops, const char *fmt,
+		...);
+void adf_interface_destroy(struct adf_interface *intf);
+static inline struct adf_device *adf_interface_parent(
+		struct adf_interface *intf)
+{
+	return intf->base.parent;
+}
+int __printf(4, 5) adf_overlay_engine_init(struct adf_overlay_engine *eng,
+		struct adf_device *dev,
+		const struct adf_overlay_engine_ops *ops, const char *fmt, ...);
+void adf_overlay_engine_destroy(struct adf_overlay_engine *eng);
+static inline struct adf_device *adf_overlay_engine_parent(
+		struct adf_overlay_engine *eng)
+{
+	return eng->base.parent;
+}
+
+int adf_attachment_allow(struct adf_device *dev, struct adf_overlay_engine *eng,
+		struct adf_interface *intf);
+
+const char *adf_obj_type_str(enum adf_obj_type type);
+const char *adf_interface_type_str(struct adf_interface *intf);
+const char *adf_event_type_str(struct adf_obj *obj, enum adf_event_type type);
+
+#define ADF_FORMAT_STR_SIZE 5
+void adf_format_str(u32 format, char buf[ADF_FORMAT_STR_SIZE]);
+int adf_format_validate_yuv(struct adf_device *dev, struct adf_buffer *buf,
+		u8 num_planes, u8 hsub, u8 vsub, u8 cpp[]);
+/**
+ * adf_format_validate_rgb - validate the number and size of planes in buffers
+ * with a custom RGB format.
+ *
+ * @dev: ADF device performing the validation
+ * @buf: buffer to validate
+ * @cpp: expected bytes per pixel
+ *
+ * adf_format_validate_rgb() is intended to be called as a helper from @dev's
+ * validate_custom_format() op.  @buf must have a single RGB plane.
+ *
+ * Returns 0 if @buf has a single plane with sufficient size, or -EINVAL
+ * otherwise.
+ */
+static inline int adf_format_validate_rgb(struct adf_device *dev,
+		struct adf_buffer *buf, u8 cpp)
+{
+	return adf_format_validate_yuv(dev, buf, 1, 1, 1, &cpp);
+}
+
+int adf_event_get(struct adf_obj *obj, enum adf_event_type type);
+int adf_event_put(struct adf_obj *obj, enum adf_event_type type);
+int adf_event_notify(struct adf_obj *obj, struct adf_event *event);
+
+static inline void adf_vsync_get(struct adf_interface *intf)
+{
+	adf_event_get(&intf->base, ADF_EVENT_VSYNC);
+}
+
+static inline void adf_vsync_put(struct adf_interface *intf)
+{
+	adf_event_put(&intf->base, ADF_EVENT_VSYNC);
+}
+
+int adf_vsync_wait(struct adf_interface *intf, long timeout);
+void adf_vsync_notify(struct adf_interface *intf, ktime_t timestamp);
+
+int adf_hotplug_notify_connected(struct adf_interface *intf,
+		struct drm_mode_modeinfo *modelist, size_t n_modes);
+void adf_hotplug_notify_disconnected(struct adf_interface *intf);
+
+void adf_modeinfo_set_name(struct drm_mode_modeinfo *mode);
+void adf_modeinfo_set_vrefresh(struct drm_mode_modeinfo *mode);
+
+#endif /* _VIDEO_ADF_H */
diff --git a/include/video/adf_client.h b/include/video/adf_client.h
new file mode 100644
index 0000000..983f2b6
--- /dev/null
+++ b/include/video/adf_client.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VIDEO_ADF_CLIENT_H_
+#define _VIDEO_ADF_CLIENT_H_
+
+#include <video/adf.h>
+
+int adf_interface_blank(struct adf_interface *intf, u8 state);
+u8 adf_interface_dpms_state(struct adf_interface *intf);
+
+void adf_interface_current_mode(struct adf_interface *intf,
+		struct drm_mode_modeinfo *mode);
+size_t adf_interface_modelist(struct adf_interface *intf,
+		struct drm_mode_modeinfo *modelist, size_t n_modes);
+int adf_interface_set_mode(struct adf_interface *intf,
+		struct drm_mode_modeinfo *mode);
+int adf_interface_get_screen_size(struct adf_interface *intf, u16 *width,
+		u16 *height);
+int adf_interface_simple_buffer_alloc(struct adf_interface *intf, u16 w, u16 h,
+		u32 format, struct dma_buf **dma_buf, u32 *offset, u32 *pitch);
+struct sync_fence *adf_interface_simple_post(struct adf_interface *intf,
+		struct adf_buffer *buf);
+
+bool adf_overlay_engine_supports_format(struct adf_overlay_engine *eng,
+		u32 format);
+
+size_t adf_device_attachments(struct adf_device *dev,
+		struct adf_attachment *attachments, size_t n_attachments);
+size_t adf_device_attachments_allowed(struct adf_device *dev,
+		struct adf_attachment *attachments, size_t n_attachments);
+bool adf_device_attached(struct adf_device *dev, struct adf_overlay_engine *eng,
+		struct adf_interface *intf);
+bool adf_device_attach_allowed(struct adf_device *dev,
+		struct adf_overlay_engine *eng, struct adf_interface *intf);
+int adf_device_attach(struct adf_device *dev, struct adf_overlay_engine *eng,
+		struct adf_interface *intf);
+int adf_device_detach(struct adf_device *dev, struct adf_overlay_engine *eng,
+		struct adf_interface *intf);
+
+struct sync_fence *adf_device_post(struct adf_device *dev,
+		struct adf_interface **intfs, size_t n_intfs,
+		struct adf_buffer *bufs, size_t n_bufs, void *custom_data,
+		size_t custom_data_size);
+struct sync_fence *adf_device_post_nocopy(struct adf_device *dev,
+		struct adf_interface **intfs, size_t n_intfs,
+		struct adf_buffer *bufs, size_t n_bufs, void *custom_data,
+		size_t custom_data_size);
+
+#endif /* _VIDEO_ADF_CLIENT_H_ */
diff --git a/include/video/adf_fbdev.h b/include/video/adf_fbdev.h
new file mode 100644
index 0000000..b722c6b
--- /dev/null
+++ b/include/video/adf_fbdev.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VIDEO_ADF_FBDEV_H_
+#define _VIDEO_ADF_FBDEV_H_
+
+#include <linux/fb.h>
+#include <linux/mutex.h>
+#include <video/adf.h>
+
+struct adf_fbdev {
+	struct adf_interface *intf;
+	struct adf_overlay_engine *eng;
+	struct fb_info *info;
+	u32 pseudo_palette[16];
+
+	unsigned int refcount;
+	struct mutex refcount_lock;
+
+	struct dma_buf *dma_buf;
+	u32 offset;
+	u32 pitch;
+	void *vaddr;
+	u32 format;
+
+	u16 default_xres_virtual;
+	u16 default_yres_virtual;
+	u32 default_format;
+};
+
+#if IS_ENABLED(CONFIG_ADF_FBDEV)
+void adf_modeinfo_to_fb_videomode(const struct drm_mode_modeinfo *mode,
+		struct fb_videomode *vmode);
+void adf_modeinfo_from_fb_videomode(const struct fb_videomode *vmode,
+		struct drm_mode_modeinfo *mode);
+
+int adf_fbdev_init(struct adf_fbdev *fbdev, struct adf_interface *interface,
+		struct adf_overlay_engine *eng,
+		u16 xres_virtual, u16 yres_virtual, u32 format,
+		struct fb_ops *fbops, const char *fmt, ...);
+void adf_fbdev_destroy(struct adf_fbdev *fbdev);
+
+int adf_fbdev_open(struct fb_info *info, int user);
+int adf_fbdev_release(struct fb_info *info, int user);
+int adf_fbdev_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
+int adf_fbdev_set_par(struct fb_info *info);
+int adf_fbdev_blank(int blank, struct fb_info *info);
+int adf_fbdev_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+int adf_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma);
+#else
+static inline void adf_modeinfo_to_fb_videomode(const struct drm_mode_modeinfo *mode,
+		struct fb_videomode *vmode)
+{
+	WARN_ONCE(1, "%s: CONFIG_ADF_FBDEV is disabled\n", __func__);
+}
+
+static inline void adf_modeinfo_from_fb_videomode(const struct fb_videomode *vmode,
+		struct drm_mode_modeinfo *mode)
+{
+	WARN_ONCE(1, "%s: CONFIG_ADF_FBDEV is disabled\n", __func__);
+}
+
+static inline int adf_fbdev_init(struct adf_fbdev *fbdev,
+		struct adf_interface *interface,
+		struct adf_overlay_engine *eng,
+		u16 xres_virtual, u16 yres_virtual, u32 format,
+		struct fb_ops *fbops, const char *fmt, ...)
+{
+	return -ENODEV;
+}
+
+static inline void adf_fbdev_destroy(struct adf_fbdev *fbdev) { }
+
+static inline int adf_fbdev_open(struct fb_info *info, int user)
+{
+	return -ENODEV;
+}
+
+static inline int adf_fbdev_release(struct fb_info *info, int user)
+{
+	return -ENODEV;
+}
+
+static inline int adf_fbdev_check_var(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	return -ENODEV;
+}
+
+static inline int adf_fbdev_set_par(struct fb_info *info)
+{
+	return -ENODEV;
+}
+
+static inline int adf_fbdev_blank(int blank, struct fb_info *info)
+{
+	return -ENODEV;
+}
+
+static inline int adf_fbdev_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	return -ENODEV;
+}
+
+static inline int adf_fbdev_mmap(struct fb_info *info,
+		struct vm_area_struct *vma)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif /* _VIDEO_ADF_FBDEV_H_ */
diff --git a/include/video/adf_format.h b/include/video/adf_format.h
new file mode 100644
index 0000000..e03182c
--- /dev/null
+++ b/include/video/adf_format.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VIDEO_ADF_FORMAT_H
+#define _VIDEO_ADF_FORMAT_H
+
+bool adf_format_is_standard(u32 format);
+bool adf_format_is_rgb(u32 format);
+u8 adf_format_num_planes(u32 format);
+u8 adf_format_bpp(u32 format);
+u8 adf_format_plane_cpp(u32 format, int plane);
+u8 adf_format_horz_chroma_subsampling(u32 format);
+u8 adf_format_vert_chroma_subsampling(u32 format);
+
+#endif /* _VIDEO_ADF_FORMAT_H */
diff --git a/include/video/adf_memblock.h b/include/video/adf_memblock.h
new file mode 100644
index 0000000..6256e0e
--- /dev/null
+++ b/include/video/adf_memblock.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VIDEO_ADF_MEMBLOCK_H_
+#define _VIDEO_ADF_MEMBLOCK_H_
+
+struct dma_buf *adf_memblock_export(phys_addr_t base, size_t size, int flags);
+
+#endif /* _VIDEO_ADF_MEMBLOCK_H_ */
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index eeba753..c8529ce 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -16,6 +16,7 @@
 #include <linux/videodev2.h>
 #include <linux/bitmap.h>
 #include <linux/fb.h>
+#include <linux/of.h>
 #include <media/v4l2-mediabus.h>
 #include <video/videomode.h>
 
@@ -344,6 +345,7 @@
 	int dc;
 	int dp;
 	int dma[2];
+	struct device_node *of_node;
 };
 
 #endif /* __DRM_IPU_H__ */
diff --git a/init/Kconfig b/init/Kconfig
index 235c7a2..445af12 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -392,6 +392,16 @@
 
 endchoice
 
+config SCHED_WALT
+        bool "Support window based load tracking"
+        depends on SMP
+        depends on FAIR_GROUP_SCHED
+        help
+        This feature will allow the scheduler to maintain a tunable window
+	based set of metrics for tasks and runqueues. These metrics can be
+	used to guide task placement as well as task frequency requirements
+	for cpufreq governors.
+
 config BSD_PROCESS_ACCT
 	bool "BSD Process Accounting"
 	depends on MULTIUSER
@@ -999,6 +1009,23 @@
 	  Provides a simple Resource Controller for monitoring the
 	  total CPU consumed by the tasks in a cgroup.
 
+config CGROUP_SCHEDTUNE
+	bool "CFS tasks boosting cgroup subsystem (EXPERIMENTAL)"
+	depends on SCHED_TUNE
+	help
+	  This option provides the "schedtune" controller which improves the
+	  flexibility of the task boosting mechanism by introducing the support
+	  to define "per task" boost values.
+
+	  This new controller:
+	  1. allows only a two layers hierarchy, where the root defines the
+	     system-wide boost value and its direct childrens define each one a
+	     different "class of tasks" to be boosted with a different value
+	  2. supports up to 16 different task classes, each one which could be
+	     configured with a different boost value
+
+	  Say N if unsure.
+
 config PAGE_COUNTER
        bool
 
@@ -1237,6 +1264,43 @@
 	  desktop applications.  Task group autogeneration is currently based
 	  upon task session.
 
+config SCHED_TUNE
+	bool "Boosting for CFS tasks (EXPERIMENTAL)"
+	depends on SMP
+	help
+	  This option enables the system-wide support for task boosting.
+	  When this support is enabled a new sysctl interface is exposed to
+	  userspace via:
+	     /proc/sys/kernel/sched_cfs_boost
+	  which allows to set a system-wide boost value in range [0..100].
+
+	  The currently boosting strategy is implemented in such a way that:
+	  - a 0% boost value requires to operate in "standard" mode by
+	    scheduling all tasks at the minimum capacities required by their
+	    workload demand
+	  - a 100% boost value requires to push at maximum the task
+	    performances, "regardless" of the incurred energy consumption
+
+	  A boost value in between these two boundaries is used to bias the
+	  power/performance trade-off, the higher the boost value the more the
+	  scheduler is biased toward performance boosting instead of energy
+	  efficiency.
+
+	  Since this support exposes a single system-wide knob, the specified
+	  boost value is applied to all (CFS) tasks in the system.
+
+	  If unsure, say N.
+
+config DEFAULT_USE_ENERGY_AWARE
+	bool "Default to enabling the Energy Aware Scheduler feature"
+	default n
+	help
+	  This option defaults the ENERGY_AWARE scheduling feature to true,
+	  as without SCHED_DEBUG set this feature can't be enabled or disabled
+	  via sysctl.
+
+	  Say N if unsure.
+
 config SYSFS_DEPRECATED
 	bool "Enable deprecated sysfs features to support old userspace tools"
 	depends on SYSFS
@@ -1719,6 +1783,7 @@
 
 config SLAB
 	bool "SLAB"
+	select HAVE_HARDENED_USERCOPY_ALLOCATOR
 	help
 	  The regular slab allocator that is established and known to work
 	  well in all environments. It organizes cache hot objects in
@@ -1726,6 +1791,7 @@
 
 config SLUB
 	bool "SLUB (Unqueued Allocator)"
+	select HAVE_HARDENED_USERCOPY_ALLOCATOR
 	help
 	   SLUB is a slab allocator that minimizes cache line usage
 	   instead of managing queues of cached objects (SLAB approach).
diff --git a/init/do_mounts_dm.c b/init/do_mounts_dm.c
index 7c201a5..bce1c2f 100644
--- a/init/do_mounts_dm.c
+++ b/init/do_mounts_dm.c
@@ -1,9 +1,9 @@
-/*
- * do_mounts_dm.c
+/* do_mounts_dm.c
  * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org>
+ *                    All Rights Reserved.
  * Based on do_mounts_md.c
  *
- * This file is released under the GPLv2.
+ * This file is released under the GPL.
  */
 #include <linux/async.h>
 #include <linux/ctype.h>
@@ -21,23 +21,58 @@
 #define DM_NO_UUID "none"
 
 #define DM_MSG_PREFIX "init"
-#define DMERR_PARSE(fmt, args...) \
-	DMERR("failed to parse " fmt " for device %s<%lu>", args)
 
 /* Separators used for parsing the dm= argument. */
 #define DM_FIELD_SEP " "
 #define DM_LINE_SEP ","
 #define DM_ANY_SEP DM_FIELD_SEP DM_LINE_SEP
 
-/* See Documentation/device-mapper/boot.txt for dm="..." format details. */
+/*
+ * When the device-mapper and any targets are compiled into the kernel
+ * (not a module), one or more device-mappers may be created and used
+ * as the root device at boot time with the parameters given with the
+ * boot line dm=...
+ *
+ * Multiple device-mappers can be stacked specifing the number of
+ * devices. A device can have multiple targets if the the number of
+ * targets is specified.
+ *
+ * TODO(taysom:defect 32847)
+ * In the future, the <num> field will be mandatory.
+ *
+ * <device>        ::= [<num>] <device-mapper>+
+ * <device-mapper> ::= <head> "," <target>+
+ * <head>          ::= <name> <uuid> <mode> [<num>]
+ * <target>        ::= <start> <length> <type> <options> ","
+ * <mode>          ::= "ro" | "rw"
+ * <uuid>          ::= xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | "none"
+ * <type>          ::= "verity" | "bootcache" | ...
+ *
+ * Example:
+ * 2 vboot none ro 1,
+ *     0 1768000 bootcache
+ *       device=aa55b119-2a47-8c45-946a-5ac57765011f+1
+ *       signature=76e9be054b15884a9fa85973e9cb274c93afadb6
+ *       cache_start=1768000 max_blocks=100000 size_limit=23 max_trace=20000,
+ *   vroot none ro 1,
+ *     0 1740800 verity payload=254:0 hashtree=254:0 hashstart=1740800 alg=sha1
+ *       root_hexdigest=76e9be054b15884a9fa85973e9cb274c93afadb6
+ *       salt=5b3549d54d6c7a3837b9b81ed72e49463a64c03680c47835bef94d768e5646fe
+ *
+ * Notes:
+ *  1. uuid is a label for the device and we set it to "none".
+ *  2. The <num> field will be optional initially and assumed to be 1.
+ *     Once all the scripts that set these fields have been set, it will
+ *     be made mandatory.
+ */
 
-struct dm_setup_table {
+struct dm_setup_target {
 	sector_t begin;
 	sector_t length;
 	char *type;
 	char *params;
 	/* simple singly linked list */
-	struct dm_setup_table *next;
+	struct dm_setup_target *next;
 };
 
 struct dm_device {
@@ -45,9 +80,9 @@
 	int ro;
 	char name[DM_MAX_NAME];
 	char uuid[DM_MAX_UUID];
-	unsigned long num_tables;
-	struct dm_setup_table *table;
-	int table_count;
+	unsigned long num_targets;
+	struct dm_setup_target *target;
+	int target_count;
 	struct dm_device *next;
 };
 
@@ -63,7 +98,7 @@
 	char *str;
 } dm_setup_args __initdata;
 
-static int dm_early_setup __initdata;
+static __initdata int dm_early_setup;
 
 static int __init get_dm_option(struct dm_option *opt, const char *accept)
 {
@@ -92,52 +127,37 @@
 	return opt->len != 0;
 }
 
-static int __init get_dm_option_u64(struct dm_option *opt, const char *sep,
-				    unsigned long long *result)
-{
-	char buf[32];
-
-	if (!get_dm_option(opt, sep))
-		return -EINVAL;
-
-	strlcpy(buf, opt->start, min(sizeof(buf), opt->len + 1));
-	return kstrtoull(buf, 0, result);
-}
-
-static void __init dm_setup_cleanup(struct dm_device *devices)
+static int __init dm_setup_cleanup(struct dm_device *devices)
 {
 	struct dm_device *dev = devices;
 
 	while (dev) {
 		struct dm_device *old_dev = dev;
-		struct dm_setup_table *table = dev->table;
-
-		while (table) {
-			struct dm_setup_table *old_table = table;
-
-			kfree(table->type);
-			kfree(table->params);
-			table = table->next;
-			kfree(old_table);
-			dev->table_count--;
+		struct dm_setup_target *target = dev->target;
+		while (target) {
+			struct dm_setup_target *old_target = target;
+			kfree(target->type);
+			kfree(target->params);
+			target = target->next;
+			kfree(old_target);
+			dev->target_count--;
 		}
-		WARN_ON(dev->table_count);
+		BUG_ON(dev->target_count);
 		dev = dev->next;
 		kfree(old_dev);
 	}
+	return 0;
 }
 
-static char * __init dm_parse_device(struct dm_device *dev, char *str,
-				     unsigned long idx)
+static char * __init dm_parse_device(struct dm_device *dev, char *str)
 {
 	struct dm_option opt;
 	size_t len;
-	unsigned long long num_tables;
 
 	/* Grab the logical name of the device to be exported to udev */
 	opt.next = str;
 	if (!get_dm_option(&opt, DM_FIELD_SEP)) {
-		DMERR_PARSE("name", "", idx);
+		DMERR("failed to parse device name");
 		goto parse_fail;
 	}
 	len = min(opt.len + 1, sizeof(dev->name));
@@ -145,7 +165,7 @@
 
 	/* Grab the UUID value or "none" */
 	if (!get_dm_option(&opt, DM_FIELD_SEP)) {
-		DMERR_PARSE("uuid", dev->name, idx);
+		DMERR("failed to parse device uuid");
 		goto parse_fail;
 	}
 	len = min(opt.len + 1, sizeof(dev->uuid));
@@ -158,84 +178,81 @@
 	} else if (!strncmp("rw", opt.start, opt.len)) {
 		dev->ro = 0;
 	} else {
-		DMERR_PARSE("table mode", dev->name, idx);
+		DMERR("failed to parse table mode");
 		goto parse_fail;
 	}
 
 	/* Optional number field */
+	/* XXX: The <num> field will be mandatory in the next round */
 	if (opt.delim == DM_FIELD_SEP[0]) {
-		if (get_dm_option_u64(&opt, DM_LINE_SEP, &num_tables)) {
-			DMERR_PARSE("number of tables", dev->name, idx);
-			goto parse_fail;
-		}
+		if (!get_dm_option(&opt, DM_LINE_SEP))
+			return NULL;
+		dev->num_targets = simple_strtoul(opt.start, NULL, 10);
 	} else {
-		num_tables = 1;
+		dev->num_targets = 1;
 	}
-	if (num_tables > DM_MAX_TARGETS) {
-		DMERR_PARSE("too many tables (%llu > %d)", num_tables,
-			    DM_MAX_TARGETS, dev->name, idx);
+	if (dev->num_targets > DM_MAX_TARGETS) {
+		DMERR("too many targets %lu > %d",
+			dev->num_targets, DM_MAX_TARGETS);
 	}
-	dev->num_tables = num_tables;
-
 	return opt.next;
 
 parse_fail:
 	return NULL;
 }
 
-static char * __init dm_parse_tables(struct dm_device *dev, char *str,
-				     unsigned long idx)
+static char * __init dm_parse_targets(struct dm_device *dev, char *str)
 {
 	struct dm_option opt;
-	struct dm_setup_table **table = &dev->table;
-	unsigned long num_tables = dev->num_tables;
+	struct dm_setup_target **target = &dev->target;
+	unsigned long num_targets = dev->num_targets;
 	unsigned long i;
-	unsigned long long value;
 
-	/*
-	 * Tables are defined as per the normal table format but with a
-	 * comma as a newline separator.
-	 */
+	/* Targets are defined as per the table format but with a
+	 * comma as a newline separator. */
 	opt.next = str;
-	for (i = 0; i < num_tables; i++) {
-		*table = kzalloc(sizeof(struct dm_setup_table), GFP_KERNEL);
-		if (!*table) {
-			DMERR_PARSE("table %lu (out of memory)", i, dev->name,
-				    idx);
+	for (i = 0; i < num_targets; i++) {
+		*target = kzalloc(sizeof(struct dm_setup_target), GFP_KERNEL);
+		if (!*target) {
+			DMERR("failed to allocate memory for target %s<%ld>",
+				dev->name, i);
 			goto parse_fail;
 		}
-		dev->table_count++;
+		dev->target_count++;
 
-		if (get_dm_option_u64(&opt, DM_FIELD_SEP, &value)) {
-			DMERR_PARSE("starting sector for table %lu", i,
-				    dev->name, idx);
+		if (!get_dm_option(&opt, DM_FIELD_SEP)) {
+			DMERR("failed to parse starting sector"
+				" for target %s<%ld>", dev->name, i);
 			goto parse_fail;
 		}
-		(*table)->begin = value;
+		(*target)->begin = simple_strtoull(opt.start, NULL, 10);
 
-		if (get_dm_option_u64(&opt, DM_FIELD_SEP, &value)) {
-			DMERR_PARSE("length for table %lu", i, dev->name, idx);
+		if (!get_dm_option(&opt, DM_FIELD_SEP)) {
+			DMERR("failed to parse length for target %s<%ld>",
+				dev->name, i);
 			goto parse_fail;
 		}
-		(*table)->length = value;
+		(*target)->length = simple_strtoull(opt.start, NULL, 10);
 
 		if (get_dm_option(&opt, DM_FIELD_SEP))
-			(*table)->type = kstrndup(opt.start, opt.len,
+			(*target)->type = kstrndup(opt.start, opt.len,
 							GFP_KERNEL);
-		if (!((*table)->type)) {
-			DMERR_PARSE("type for table %lu", i, dev->name, idx);
+		if (!((*target)->type)) {
+			DMERR("failed to parse type for target %s<%ld>",
+				dev->name, i);
 			goto parse_fail;
 		}
 		if (get_dm_option(&opt, DM_LINE_SEP))
-			(*table)->params = kstrndup(opt.start, opt.len,
-						    GFP_KERNEL);
-		if (!((*table)->params)) {
-			DMERR_PARSE("params for table %lu", i, dev->name, idx);
+			(*target)->params = kstrndup(opt.start, opt.len,
+							GFP_KERNEL);
+		if (!((*target)->params)) {
+			DMERR("failed to parse params for target %s<%ld>",
+				dev->name, i);
 			goto parse_fail;
 		}
-		table = &((*table)->next);
+		target = &((*target)->next);
 	}
-	DMDEBUG("tables parsed: %d", dev->table_count);
+	DMDEBUG("parsed %d targets", dev->target_count);
 
 	return opt.next;
 
@@ -257,7 +274,7 @@
 	for (i = 0; i < num_devices; i++) {
 		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 		if (!dev) {
-			DMERR("failed to allocated memory for device %lu", i);
+			DMERR("failed to allocated memory for dev");
 			goto error;
 		}
 		*tail = dev;
@@ -268,11 +285,11 @@
 		 * string.
 		 */
 		dev->minor = i;
-		str = dm_parse_device(dev, str, i);
+		str = dm_parse_device(dev, str);
 		if (!str)	/* NULL indicates error in parsing, bail */
 			goto error;
 
-		str = dm_parse_tables(dev, str, i);
+		str = dm_parse_targets(dev, str);
 		if (!str)
 			goto error;
 	}
@@ -295,27 +312,29 @@
 static int __init dm_setup(char *str)
 {
 	struct dm_option opt;
-	unsigned long long num_devices;
+	unsigned long num_devices;
 
 	if (!str) {
-		DMERR("setup str is NULL");
+		DMDEBUG("str is NULL");
 		goto parse_fail;
 	}
-
-	DMDEBUG("Want to parse \"%s\"", str);
 	opt.next = str;
-	if (get_dm_option_u64(&opt, DM_FIELD_SEP, &num_devices))
+	if (!get_dm_option(&opt, DM_FIELD_SEP))
 		goto parse_fail;
-	str = opt.next;
-	if (num_devices > DM_MAX_DEVICES) {
-		DMERR("too many devices %llu > %d", num_devices,
-		      DM_MAX_DEVICES);
+	if (isdigit(opt.start[0])) {	/* XXX: Optional number field */
+		num_devices = simple_strtoul(opt.start, NULL, 10);
+		str = opt.next;
+	} else {
+		num_devices = 1;
+		/* Don't advance str */
 	}
-	dm_setup_args.num_devices = num_devices;
+	if (num_devices > DM_MAX_DEVICES) {
+		DMDEBUG("too many devices %lu > %d",
+			num_devices, DM_MAX_DEVICES);
+	}
 	dm_setup_args.str = str;
-
-	DMINFO("will configure %lu device%s", dm_setup_args.num_devices,
-	       dm_setup_args.num_devices == 1 ? "" : "s");
+	dm_setup_args.num_devices = num_devices;
+	DMINFO("will configure %lu devices", num_devices);
 	dm_early_setup = 1;
 	return 1;
 
@@ -327,8 +346,8 @@
 static void __init dm_setup_drives(void)
 {
 	struct mapped_device *md = NULL;
-	struct dm_table *tables = NULL;
-	struct dm_setup_table *table;
+	struct dm_table *table = NULL;
+	struct dm_setup_target *target;
 	struct dm_device *dev;
 	char *uuid;
 	fmode_t fmode = FMODE_READ;
@@ -338,8 +357,8 @@
 
 	for (dev = devices; dev; dev = dev->next) {
 		if (dm_create(dev->minor, &md)) {
-			DMERR("failed to create device %s", dev->name);
-			goto fail;
+			DMDEBUG("failed to create the device");
+			goto dm_create_fail;
 		}
 		DMDEBUG("created device '%s'", dm_device_name(md));
 
@@ -351,74 +370,92 @@
 
 		if (!dev->ro)
 			fmode |= FMODE_WRITE;
-		if (dm_table_create(&tables, fmode, dev->table_count, md)) {
-			DMERR("failed to create device %s tables", dev->name);
-			goto fail_put;
+		if (dm_table_create(&table, fmode, dev->target_count, md)) {
+			DMDEBUG("failed to create the table");
+			goto dm_table_create_fail;
 		}
-		for (table = dev->table; table; table = table->next) {
-			DMINFO("device %s adding table '%llu %llu %s %s'",
-			       dev->name,
-			       (unsigned long long) table->begin,
-			       (unsigned long long) table->length,
-			       table->type, table->params);
-			if (dm_table_add_target(tables, table->type,
-						table->begin,
-						table->length,
-						table->params)) {
-				DMERR("failed to add table to device %s",
-					dev->name);
-				goto fail_put;
+
+		dm_lock_md_type(md);
+
+		for (target = dev->target; target; target = target->next) {
+			DMINFO("adding target '%llu %llu %s %s'",
+			       (unsigned long long) target->begin,
+			       (unsigned long long) target->length,
+			       target->type, target->params);
+			if (dm_table_add_target(table, target->type,
+						target->begin,
+						target->length,
+						target->params)) {
+				DMDEBUG("failed to add the target"
+					" to the table");
+				goto add_target_fail;
 			}
 		}
-		dm_lock_md_type(md);
-		if (dm_table_complete(tables)) {
-			DMERR("failed to complete device %s tables",
-				dev->name);
-			dm_unlock_md_type(md);
-			goto fail_put;
+		if (dm_table_complete(table)) {
+			DMDEBUG("failed to complete the table");
+			goto table_complete_fail;
 		}
-		dm_unlock_md_type(md);
 
-		/* Suspend the device so that we can bind it to the tables. */
+		/* Suspend the device so that we can bind it to the table. */
 		if (dm_suspend(md, 0)) {
-			DMERR("failed to suspend device %s pre-bind",
-				dev->name);
-			goto fail_put;
+			DMDEBUG("failed to suspend the device pre-bind");
+			goto suspend_fail;
+		}
+
+		/* Initial table load: acquire type of table. */
+		dm_set_md_type(md, dm_table_get_type(table));
+
+		/* Setup md->queue to reflect md's type. */
+		if (dm_setup_md_queue(md)) {
+			DMWARN("unable to set up device queue for new table.");
+			goto setup_md_queue_fail;
 		}
 
 		/*
-		 * Bind the tables to the device. This is the only way
-		 * to associate md->map with the tables and set the disk
+		 * Bind the table to the device. This is the only way
+		 * to associate md->map with the table and set the disk
 		 * capacity directly.
 		 */
-		if (dm_swap_table(md, tables)) {  /* should return NULL. */
-			DMERR("failed to bind device %s to tables",
-				dev->name);
-			goto fail_put;
+		if (dm_swap_table(md, table)) {  /* should return NULL. */
+			DMDEBUG("failed to bind the device to the table");
+			goto table_bind_fail;
 		}
 
 		/* Finally, resume and the device should be ready. */
 		if (dm_resume(md)) {
-			DMERR("failed to resume device %s", dev->name);
-			goto fail_put;
+			DMDEBUG("failed to resume the device");
+			goto resume_fail;
 		}
 
 		/* Export the dm device via the ioctl interface */
 		if (!strcmp(DM_NO_UUID, dev->uuid))
 			uuid = NULL;
 		if (dm_ioctl_export(md, dev->name, uuid)) {
-			DMERR("failed to export device %s", dev->name);
-			goto fail_put;
+			DMDEBUG("failed to export device with given"
+				" name and uuid");
+			goto export_fail;
 		}
-		DMINFO("dm-%d (%s) is ready", dev->minor, dev->name);
+
+		dm_unlock_md_type(md);
+
+		DMINFO("dm-%d is ready", dev->minor);
 	}
 	dm_setup_cleanup(devices);
 	return;
 
-fail_put:
+export_fail:
+resume_fail:
+table_bind_fail:
+setup_md_queue_fail:
+suspend_fail:
+table_complete_fail:
+add_target_fail:
+	dm_unlock_md_type(md);
+dm_table_create_fail:
 	dm_put(md);
-fail:
-	DMERR("starting dm-%d (%s) failed", dev->minor, dev->name);
+dm_create_fail:
+	DMWARN("starting dm-%d (%s) failed",
+	       dev->minor, dev->name);
 	dm_setup_cleanup(devices);
 }
 
diff --git a/init/main.c b/init/main.c
index 9e64d70..fbafa27 100644
--- a/init/main.c
+++ b/init/main.c
@@ -93,9 +93,6 @@
 extern void init_IRQ(void);
 extern void fork_init(void);
 extern void radix_tree_init(void);
-#ifndef CONFIG_DEBUG_RODATA
-static inline void mark_rodata_ro(void) { }
-#endif
 
 /*
  * Debug helper: via this flag we know that we are in 'early bootup code'
@@ -929,6 +926,28 @@
 
 static noinline void __init kernel_init_freeable(void);
 
+#ifdef CONFIG_DEBUG_RODATA
+static bool rodata_enabled = true;
+static int __init set_debug_rodata(char *str)
+{
+	return strtobool(str, &rodata_enabled);
+}
+__setup("rodata=", set_debug_rodata);
+
+static void mark_readonly(void)
+{
+	if (rodata_enabled)
+		mark_rodata_ro();
+	else
+		pr_info("Kernel memory protection disabled.\n");
+}
+#else
+static inline void mark_readonly(void)
+{
+	pr_warn("This architecture does not have kernel memory protection.\n");
+}
+#endif
+
 static int __ref kernel_init(void *unused)
 {
 	int ret;
@@ -937,7 +956,7 @@
 	/* need to finish all async __init code before freeing the memory */
 	async_synchronize_full();
 	free_initmem();
-	mark_rodata_ro();
+	mark_readonly();
 	system_state = SYSTEM_RUNNING;
 	numa_default_policy();
 
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 161a180..4643654 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -747,7 +747,7 @@
 	}
 
 	mode &= ~current_umask();
-	ret = vfs_create(dir, path->dentry, mode, true);
+	ret = vfs_create2(path->mnt, dir, path->dentry, mode, true);
 	path->dentry->d_fsdata = NULL;
 	if (ret)
 		return ERR_PTR(ret);
@@ -763,7 +763,7 @@
 	if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
 		return ERR_PTR(-EINVAL);
 	acc = oflag2acc[oflag & O_ACCMODE];
-	if (inode_permission(d_inode(path->dentry), acc))
+	if (inode_permission2(path->mnt, d_inode(path->dentry), acc))
 		return ERR_PTR(-EACCES);
 	return dentry_open(path, oflag, current_cred());
 }
@@ -796,7 +796,7 @@
 	ro = mnt_want_write(mnt);	/* we'll drop it in any case */
 	error = 0;
 	mutex_lock(&d_inode(root)->i_mutex);
-	path.dentry = lookup_one_len(name->name, root, strlen(name->name));
+	path.dentry = lookup_one_len2(name->name, mnt, root, strlen(name->name));
 	if (IS_ERR(path.dentry)) {
 		error = PTR_ERR(path.dentry);
 		goto out_putfd;
@@ -867,7 +867,7 @@
 	if (err)
 		goto out_name;
 	mutex_lock_nested(&d_inode(mnt->mnt_root)->i_mutex, I_MUTEX_PARENT);
-	dentry = lookup_one_len(name->name, mnt->mnt_root,
+	dentry = lookup_one_len2(name->name, mnt, mnt->mnt_root,
 				strlen(name->name));
 	if (IS_ERR(dentry)) {
 		err = PTR_ERR(dentry);
@@ -879,7 +879,7 @@
 		err = -ENOENT;
 	} else {
 		ihold(inode);
-		err = vfs_unlink(d_inode(dentry->d_parent), dentry, NULL);
+		err = vfs_unlink2(mnt, d_inode(dentry->d_parent), dentry, NULL);
 	}
 	dput(dentry);
 
@@ -1251,8 +1251,10 @@
 
 			timeo = MAX_SCHEDULE_TIMEOUT;
 			ret = netlink_attachskb(sock, nc, &timeo, NULL);
-			if (ret == 1)
+			if (ret == 1) {
+				sock = NULL;
 				goto retry;
+			}
 			if (ret) {
 				sock = NULL;
 				nc = NULL;
diff --git a/ipc/msg.c b/ipc/msg.c
index 1471db9..c6521c2 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -680,7 +680,7 @@
 		rcu_read_lock();
 		ipc_lock_object(&msq->q_perm);
 
-		ipc_rcu_putref(msq, ipc_rcu_free);
+		ipc_rcu_putref(msq, msg_rcu_free);
 		/* raced with RMID? */
 		if (!ipc_valid_object(&msq->q_perm)) {
 			err = -EIDRM;
diff --git a/ipc/sem.c b/ipc/sem.c
index b471e5a..9862c3d 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -155,14 +155,21 @@
 
 /*
  * Locking:
+ * a) global sem_lock() for read/write
  *	sem_undo.id_next,
  *	sem_array.complex_count,
- *	sem_array.pending{_alter,_cont},
- *	sem_array.sem_undo: global sem_lock() for read/write
- *	sem_undo.proc_next: only "current" is allowed to read/write that field.
+ *	sem_array.complex_mode
+ *	sem_array.pending{_alter,_const},
+ *	sem_array.sem_undo
  *
+ * b) global or semaphore sem_lock() for read/write:
  *	sem_array.sem_base[i].pending_{const,alter}:
- *		global or semaphore sem_lock() for read/write
+ *	sem_array.complex_mode (for read)
+ *
+ * c) special:
+ *	sem_undo_list.list_proc:
+ *	* undo_list->lock for write
+ *	* rcu for read
  */
 
 #define sc_semmsl	sem_ctls[0]
@@ -263,24 +270,25 @@
 #define ipc_smp_acquire__after_spin_is_unlocked()	smp_rmb()
 
 /*
- * Wait until all currently ongoing simple ops have completed.
+ * Enter the mode suitable for non-simple operations:
  * Caller must own sem_perm.lock.
- * New simple ops cannot start, because simple ops first check
- * that sem_perm.lock is free.
- * that a) sem_perm.lock is free and b) complex_count is 0.
  */
-static void sem_wait_array(struct sem_array *sma)
+static void complexmode_enter(struct sem_array *sma)
 {
 	int i;
 	struct sem *sem;
 
-	if (sma->complex_count)  {
-		/* The thread that increased sma->complex_count waited on
-		 * all sem->lock locks. Thus we don't need to wait again.
-		 */
+	if (sma->complex_mode)  {
+		/* We are already in complex_mode. Nothing to do */
 		return;
 	}
 
+	/* We need a full barrier after seting complex_mode:
+	 * The write to complex_mode must be visible
+	 * before we read the first sem->lock spinlock state.
+	 */
+	smp_store_mb(sma->complex_mode, true);
+
 	for (i = 0; i < sma->sem_nsems; i++) {
 		sem = sma->sem_base + i;
 		spin_unlock_wait(&sem->lock);
@@ -289,6 +297,28 @@
 }
 
 /*
+ * Try to leave the mode that disallows simple operations:
+ * Caller must own sem_perm.lock.
+ */
+static void complexmode_tryleave(struct sem_array *sma)
+{
+	if (sma->complex_count)  {
+		/* Complex ops are sleeping.
+		 * We must stay in complex mode
+		 */
+		return;
+	}
+	/*
+	 * Immediately after setting complex_mode to false,
+	 * a simple op can start. Thus: all memory writes
+	 * performed by the current operation must be visible
+	 * before we set complex_mode to false.
+	 */
+	smp_store_release(&sma->complex_mode, false);
+}
+
+#define SEM_GLOBAL_LOCK	(-1)
+/*
  * If the request contains only one semaphore operation, and there are
  * no complex transactions pending, lock only the semaphore involved.
  * Otherwise, lock the entire semaphore array, since we either have
@@ -304,56 +334,42 @@
 		/* Complex operation - acquire a full lock */
 		ipc_lock_object(&sma->sem_perm);
 
-		/* And wait until all simple ops that are processed
-		 * right now have dropped their locks.
-		 */
-		sem_wait_array(sma);
-		return -1;
+		/* Prevent parallel simple ops */
+		complexmode_enter(sma);
+		return SEM_GLOBAL_LOCK;
 	}
 
 	/*
 	 * Only one semaphore affected - try to optimize locking.
-	 * The rules are:
-	 * - optimized locking is possible if no complex operation
-	 *   is either enqueued or processed right now.
-	 * - The test for enqueued complex ops is simple:
-	 *      sma->complex_count != 0
-	 * - Testing for complex ops that are processed right now is
-	 *   a bit more difficult. Complex ops acquire the full lock
-	 *   and first wait that the running simple ops have completed.
-	 *   (see above)
-	 *   Thus: If we own a simple lock and the global lock is free
-	 *	and complex_count is now 0, then it will stay 0 and
-	 *	thus just locking sem->lock is sufficient.
+	 * Optimized locking is possible if no complex operation
+	 * is either enqueued or processed right now.
+	 *
+	 * Both facts are tracked by complex_mode.
 	 */
 	sem = sma->sem_base + sops->sem_num;
 
-	if (sma->complex_count == 0) {
+	/*
+	 * Initial check for complex_mode. Just an optimization,
+	 * no locking, no memory barrier.
+	 */
+	if (!sma->complex_mode) {
 		/*
 		 * It appears that no complex operation is around.
 		 * Acquire the per-semaphore lock.
 		 */
 		spin_lock(&sem->lock);
 
-		/* Then check that the global lock is free */
-		if (!spin_is_locked(&sma->sem_perm.lock)) {
-			/*
-			 * We need a memory barrier with acquire semantics,
-			 * otherwise we can race with another thread that does:
-			 *	complex_count++;
-			 *	spin_unlock(sem_perm.lock);
-			 */
-			ipc_smp_acquire__after_spin_is_unlocked();
+		/*
+		 * See 51d7d5205d33
+		 * ("powerpc: Add smp_mb() to arch_spin_is_locked()"):
+		 * A full barrier is required: the write of sem->lock
+		 * must be visible before the read is executed
+		 */
+		smp_mb();
 
-			/*
-			 * Now repeat the test of complex_count:
-			 * It can't change anymore until we drop sem->lock.
-			 * Thus: if is now 0, then it will stay 0.
-			 */
-			if (sma->complex_count == 0) {
-				/* fast path successful! */
-				return sops->sem_num;
-			}
+		if (!smp_load_acquire(&sma->complex_mode)) {
+			/* fast path successful! */
+			return sops->sem_num;
 		}
 		spin_unlock(&sem->lock);
 	}
@@ -373,15 +389,16 @@
 		/* Not a false alarm, thus complete the sequence for a
 		 * full lock.
 		 */
-		sem_wait_array(sma);
-		return -1;
+		complexmode_enter(sma);
+		return SEM_GLOBAL_LOCK;
 	}
 }
 
 static inline void sem_unlock(struct sem_array *sma, int locknum)
 {
-	if (locknum == -1) {
+	if (locknum == SEM_GLOBAL_LOCK) {
 		unmerge_queues(sma);
+		complexmode_tryleave(sma);
 		ipc_unlock_object(&sma->sem_perm);
 	} else {
 		struct sem *sem = sma->sem_base + locknum;
@@ -442,7 +459,7 @@
 static inline void sem_lock_and_putref(struct sem_array *sma)
 {
 	sem_lock(sma, NULL, -1);
-	ipc_rcu_putref(sma, ipc_rcu_free);
+	ipc_rcu_putref(sma, sem_rcu_free);
 }
 
 static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
@@ -533,6 +550,7 @@
 	}
 
 	sma->complex_count = 0;
+	sma->complex_mode = true; /* dropped by sem_unlock below */
 	INIT_LIST_HEAD(&sma->pending_alter);
 	INIT_LIST_HEAD(&sma->pending_const);
 	INIT_LIST_HEAD(&sma->list_id);
@@ -1385,7 +1403,7 @@
 			rcu_read_unlock();
 			sem_io = ipc_alloc(sizeof(ushort)*nsems);
 			if (sem_io == NULL) {
-				ipc_rcu_putref(sma, ipc_rcu_free);
+				ipc_rcu_putref(sma, sem_rcu_free);
 				return -ENOMEM;
 			}
 
@@ -1419,20 +1437,20 @@
 		if (nsems > SEMMSL_FAST) {
 			sem_io = ipc_alloc(sizeof(ushort)*nsems);
 			if (sem_io == NULL) {
-				ipc_rcu_putref(sma, ipc_rcu_free);
+				ipc_rcu_putref(sma, sem_rcu_free);
 				return -ENOMEM;
 			}
 		}
 
 		if (copy_from_user(sem_io, p, nsems*sizeof(ushort))) {
-			ipc_rcu_putref(sma, ipc_rcu_free);
+			ipc_rcu_putref(sma, sem_rcu_free);
 			err = -EFAULT;
 			goto out_free;
 		}
 
 		for (i = 0; i < nsems; i++) {
 			if (sem_io[i] > SEMVMX) {
-				ipc_rcu_putref(sma, ipc_rcu_free);
+				ipc_rcu_putref(sma, sem_rcu_free);
 				err = -ERANGE;
 				goto out_free;
 			}
@@ -1722,7 +1740,7 @@
 	/* step 2: allocate new undo structure */
 	new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
 	if (!new) {
-		ipc_rcu_putref(sma, ipc_rcu_free);
+		ipc_rcu_putref(sma, sem_rcu_free);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -2186,10 +2204,10 @@
 	/*
 	 * The proc interface isn't aware of sem_lock(), it calls
 	 * ipc_lock_object() directly (in sysvipc_find_ipc).
-	 * In order to stay compatible with sem_lock(), we must wait until
-	 * all simple semop() calls have left their critical regions.
+	 * In order to stay compatible with sem_lock(), we must
+	 * enter / leave complex_mode.
 	 */
-	sem_wait_array(sma);
+	complexmode_enter(sma);
 
 	sem_otime = get_semotime(sma);
 
@@ -2206,6 +2224,8 @@
 		   sem_otime,
 		   sma->sem_ctime);
 
+	complexmode_tryleave(sma);
+
 	return 0;
 }
 #endif
diff --git a/ipc/shm.c b/ipc/shm.c
index 3174634..4982a4e 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1083,8 +1083,8 @@
  * "raddr" thing points to kernel space, and there has to be a wrapper around
  * this.
  */
-long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
-	      unsigned long shmlba)
+long do_shmat(int shmid, char __user *shmaddr, int shmflg,
+	      ulong *raddr, unsigned long shmlba)
 {
 	struct shmid_kernel *shp;
 	unsigned long addr;
@@ -1105,8 +1105,13 @@
 		goto out;
 	else if ((addr = (ulong)shmaddr)) {
 		if (addr & (shmlba - 1)) {
-			if (shmflg & SHM_RND)
-				addr &= ~(shmlba - 1);	   /* round down */
+			/*
+			 * Round down to the nearest multiple of shmlba.
+			 * For sane do_mmap_pgoff() parameters, avoid
+			 * round downs that trigger nil-page and MAP_FIXED.
+			 */
+			if ((shmflg & SHM_RND) && addr >= shmlba)
+				addr &= ~(shmlba - 1);
 			else
 #ifndef __ARCH_FORCE_SHMLBA
 				if (addr & ~PAGE_MASK)
diff --git a/kernel/audit.c b/kernel/audit.c
index 5ffcbd3..34f690b9 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -870,6 +870,12 @@
 				return err;
 		}
 		if (s.mask & AUDIT_STATUS_PID) {
+			/* NOTE: we are using task_tgid_vnr() below because
+			 *       the s.pid value is relative to the namespace
+			 *       of the caller; at present this doesn't matter
+			 *       much since you can really only run auditd
+			 *       from the initial pid namespace, but something
+			 *       to keep in mind if this changes */
 			int new_pid = s.pid;
 
 			if ((!new_pid) && (task_tgid_vnr(current) != audit_pid))
@@ -1896,7 +1902,7 @@
 			 " euid=%u suid=%u fsuid=%u"
 			 " egid=%u sgid=%u fsgid=%u tty=%s ses=%u",
 			 task_ppid_nr(tsk),
-			 task_pid_nr(tsk),
+			 task_tgid_nr(tsk),
 			 from_kuid(&init_user_ns, audit_get_loginuid(tsk)),
 			 from_kuid(&init_user_ns, cred->uid),
 			 from_kgid(&init_user_ns, cred->gid),
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 656c7e9..939945a 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -19,6 +19,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/file.h>
 #include <linux/kernel.h>
 #include <linux/audit.h>
 #include <linux/kthread.h>
@@ -544,10 +545,11 @@
 	unsigned long ino;
 	dev_t dev;
 
-	rcu_read_lock();
-	exe_file = rcu_dereference(tsk->mm->exe_file);
+	exe_file = get_task_exe_file(tsk);
+	if (!exe_file)
+		return 0;
 	ino = exe_file->f_inode->i_ino;
 	dev = exe_file->f_inode->i_sb->s_dev;
-	rcu_read_unlock();
+	fput(exe_file);
 	return audit_mark_compare(mark, ino, dev);
 }
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index b86cc04..63f0e49 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -73,6 +73,7 @@
 #include <linux/compat.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
+#include <linux/uaccess.h>
 #include <uapi/linux/limits.h>
 
 #include "audit.h"
@@ -82,7 +83,8 @@
 #define AUDITSC_SUCCESS 1
 #define AUDITSC_FAILURE 2
 
-/* no execve audit message should be longer than this (userspace limits) */
+/* no execve audit message should be longer than this (userspace limits),
+ * see the note near the top of audit_log_execve_info() about this value */
 #define MAX_EXECVE_AUDIT_LEN 7500
 
 /* max length to print of cmdline/proctitle value during audit */
@@ -456,7 +458,7 @@
 
 		switch (f->type) {
 		case AUDIT_PID:
-			pid = task_pid_nr(tsk);
+			pid = task_tgid_nr(tsk);
 			result = audit_comparator(pid, f->op, f->val);
 			break;
 		case AUDIT_PPID:
@@ -988,184 +990,178 @@
 	return rc;
 }
 
-/*
- * to_send and len_sent accounting are very loose estimates.  We aren't
- * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being
- * within about 500 bytes (next page boundary)
- *
- * why snprintf?  an int is up to 12 digits long.  if we just assumed when
- * logging that a[%d]= was going to be 16 characters long we would be wasting
- * space in every audit message.  In one 7500 byte message we can log up to
- * about 1000 min size arguments.  That comes down to about 50% waste of space
- * if we didn't do the snprintf to find out how long arg_num_len was.
- */
-static int audit_log_single_execve_arg(struct audit_context *context,
-					struct audit_buffer **ab,
-					int arg_num,
-					size_t *len_sent,
-					const char __user *p,
-					char *buf)
-{
-	char arg_num_len_buf[12];
-	const char __user *tmp_p = p;
-	/* how many digits are in arg_num? 5 is the length of ' a=""' */
-	size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 5;
-	size_t len, len_left, to_send;
-	size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN;
-	unsigned int i, has_cntl = 0, too_long = 0;
-	int ret;
-
-	/* strnlen_user includes the null we don't want to send */
-	len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1;
-
-	/*
-	 * We just created this mm, if we can't find the strings
-	 * we just copied into it something is _very_ wrong. Similar
-	 * for strings that are too long, we should not have created
-	 * any.
-	 */
-	if (WARN_ON_ONCE(len < 0 || len > MAX_ARG_STRLEN - 1)) {
-		send_sig(SIGKILL, current, 0);
-		return -1;
-	}
-
-	/* walk the whole argument looking for non-ascii chars */
-	do {
-		if (len_left > MAX_EXECVE_AUDIT_LEN)
-			to_send = MAX_EXECVE_AUDIT_LEN;
-		else
-			to_send = len_left;
-		ret = copy_from_user(buf, tmp_p, to_send);
-		/*
-		 * There is no reason for this copy to be short. We just
-		 * copied them here, and the mm hasn't been exposed to user-
-		 * space yet.
-		 */
-		if (ret) {
-			WARN_ON(1);
-			send_sig(SIGKILL, current, 0);
-			return -1;
-		}
-		buf[to_send] = '\0';
-		has_cntl = audit_string_contains_control(buf, to_send);
-		if (has_cntl) {
-			/*
-			 * hex messages get logged as 2 bytes, so we can only
-			 * send half as much in each message
-			 */
-			max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2;
-			break;
-		}
-		len_left -= to_send;
-		tmp_p += to_send;
-	} while (len_left > 0);
-
-	len_left = len;
-
-	if (len > max_execve_audit_len)
-		too_long = 1;
-
-	/* rewalk the argument actually logging the message */
-	for (i = 0; len_left > 0; i++) {
-		int room_left;
-
-		if (len_left > max_execve_audit_len)
-			to_send = max_execve_audit_len;
-		else
-			to_send = len_left;
-
-		/* do we have space left to send this argument in this ab? */
-		room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent;
-		if (has_cntl)
-			room_left -= (to_send * 2);
-		else
-			room_left -= to_send;
-		if (room_left < 0) {
-			*len_sent = 0;
-			audit_log_end(*ab);
-			*ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE);
-			if (!*ab)
-				return 0;
-		}
-
-		/*
-		 * first record needs to say how long the original string was
-		 * so we can be sure nothing was lost.
-		 */
-		if ((i == 0) && (too_long))
-			audit_log_format(*ab, " a%d_len=%zu", arg_num,
-					 has_cntl ? 2*len : len);
-
-		/*
-		 * normally arguments are small enough to fit and we already
-		 * filled buf above when we checked for control characters
-		 * so don't bother with another copy_from_user
-		 */
-		if (len >= max_execve_audit_len)
-			ret = copy_from_user(buf, p, to_send);
-		else
-			ret = 0;
-		if (ret) {
-			WARN_ON(1);
-			send_sig(SIGKILL, current, 0);
-			return -1;
-		}
-		buf[to_send] = '\0';
-
-		/* actually log it */
-		audit_log_format(*ab, " a%d", arg_num);
-		if (too_long)
-			audit_log_format(*ab, "[%d]", i);
-		audit_log_format(*ab, "=");
-		if (has_cntl)
-			audit_log_n_hex(*ab, buf, to_send);
-		else
-			audit_log_string(*ab, buf);
-
-		p += to_send;
-		len_left -= to_send;
-		*len_sent += arg_num_len;
-		if (has_cntl)
-			*len_sent += to_send * 2;
-		else
-			*len_sent += to_send;
-	}
-	/* include the null we didn't log */
-	return len + 1;
-}
-
 static void audit_log_execve_info(struct audit_context *context,
 				  struct audit_buffer **ab)
 {
-	int i, len;
-	size_t len_sent = 0;
-	const char __user *p;
+	long len_max;
+	long len_rem;
+	long len_full;
+	long len_buf;
+	long len_abuf;
+	long len_tmp;
+	bool require_data;
+	bool encode;
+	unsigned int iter;
+	unsigned int arg;
+	char *buf_head;
 	char *buf;
+	const char __user *p = (const char __user *)current->mm->arg_start;
 
-	p = (const char __user *)current->mm->arg_start;
+	/* NOTE: this buffer needs to be large enough to hold all the non-arg
+	 *       data we put in the audit record for this argument (see the
+	 *       code below) ... at this point in time 96 is plenty */
+	char abuf[96];
 
-	audit_log_format(*ab, "argc=%d", context->execve.argc);
+	/* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the
+	 *       current value of 7500 is not as important as the fact that it
+	 *       is less than 8k, a setting of 7500 gives us plenty of wiggle
+	 *       room if we go over a little bit in the logging below */
+	WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500);
+	len_max = MAX_EXECVE_AUDIT_LEN;
 
-	/*
-	 * we need some kernel buffer to hold the userspace args.  Just
-	 * allocate one big one rather than allocating one of the right size
-	 * for every single argument inside audit_log_single_execve_arg()
-	 * should be <8k allocation so should be pretty safe.
-	 */
-	buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
-	if (!buf) {
+	/* scratch buffer to hold the userspace args */
+	buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
+	if (!buf_head) {
 		audit_panic("out of memory for argv string");
 		return;
 	}
+	buf = buf_head;
 
-	for (i = 0; i < context->execve.argc; i++) {
-		len = audit_log_single_execve_arg(context, ab, i,
-						  &len_sent, p, buf);
-		if (len <= 0)
-			break;
-		p += len;
-	}
-	kfree(buf);
+	audit_log_format(*ab, "argc=%d", context->execve.argc);
+
+	len_rem = len_max;
+	len_buf = 0;
+	len_full = 0;
+	require_data = true;
+	encode = false;
+	iter = 0;
+	arg = 0;
+	do {
+		/* NOTE: we don't ever want to trust this value for anything
+		 *       serious, but the audit record format insists we
+		 *       provide an argument length for really long arguments,
+		 *       e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but
+		 *       to use strncpy_from_user() to obtain this value for
+		 *       recording in the log, although we don't use it
+		 *       anywhere here to avoid a double-fetch problem */
+		if (len_full == 0)
+			len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1;
+
+		/* read more data from userspace */
+		if (require_data) {
+			/* can we make more room in the buffer? */
+			if (buf != buf_head) {
+				memmove(buf_head, buf, len_buf);
+				buf = buf_head;
+			}
+
+			/* fetch as much as we can of the argument */
+			len_tmp = strncpy_from_user(&buf_head[len_buf], p,
+						    len_max - len_buf);
+			if (len_tmp == -EFAULT) {
+				/* unable to copy from userspace */
+				send_sig(SIGKILL, current, 0);
+				goto out;
+			} else if (len_tmp == (len_max - len_buf)) {
+				/* buffer is not large enough */
+				require_data = true;
+				/* NOTE: if we are going to span multiple
+				 *       buffers force the encoding so we stand
+				 *       a chance at a sane len_full value and
+				 *       consistent record encoding */
+				encode = true;
+				len_full = len_full * 2;
+				p += len_tmp;
+			} else {
+				require_data = false;
+				if (!encode)
+					encode = audit_string_contains_control(
+								buf, len_tmp);
+				/* try to use a trusted value for len_full */
+				if (len_full < len_max)
+					len_full = (encode ?
+						    len_tmp * 2 : len_tmp);
+				p += len_tmp + 1;
+			}
+			len_buf += len_tmp;
+			buf_head[len_buf] = '\0';
+
+			/* length of the buffer in the audit record? */
+			len_abuf = (encode ? len_buf * 2 : len_buf + 2);
+		}
+
+		/* write as much as we can to the audit log */
+		if (len_buf > 0) {
+			/* NOTE: some magic numbers here - basically if we
+			 *       can't fit a reasonable amount of data into the
+			 *       existing audit buffer, flush it and start with
+			 *       a new buffer */
+			if ((sizeof(abuf) + 8) > len_rem) {
+				len_rem = len_max;
+				audit_log_end(*ab);
+				*ab = audit_log_start(context,
+						      GFP_KERNEL, AUDIT_EXECVE);
+				if (!*ab)
+					goto out;
+			}
+
+			/* create the non-arg portion of the arg record */
+			len_tmp = 0;
+			if (require_data || (iter > 0) ||
+			    ((len_abuf + sizeof(abuf)) > len_rem)) {
+				if (iter == 0) {
+					len_tmp += snprintf(&abuf[len_tmp],
+							sizeof(abuf) - len_tmp,
+							" a%d_len=%lu",
+							arg, len_full);
+				}
+				len_tmp += snprintf(&abuf[len_tmp],
+						    sizeof(abuf) - len_tmp,
+						    " a%d[%d]=", arg, iter++);
+			} else
+				len_tmp += snprintf(&abuf[len_tmp],
+						    sizeof(abuf) - len_tmp,
+						    " a%d=", arg);
+			WARN_ON(len_tmp >= sizeof(abuf));
+			abuf[sizeof(abuf) - 1] = '\0';
+
+			/* log the arg in the audit record */
+			audit_log_format(*ab, "%s", abuf);
+			len_rem -= len_tmp;
+			len_tmp = len_buf;
+			if (encode) {
+				if (len_abuf > len_rem)
+					len_tmp = len_rem / 2; /* encoding */
+				audit_log_n_hex(*ab, buf, len_tmp);
+				len_rem -= len_tmp * 2;
+				len_abuf -= len_tmp * 2;
+			} else {
+				if (len_abuf > len_rem)
+					len_tmp = len_rem - 2; /* quotes */
+				audit_log_n_string(*ab, buf, len_tmp);
+				len_rem -= len_tmp + 2;
+				/* don't subtract the "2" because we still need
+				 * to add quotes to the remaining string */
+				len_abuf -= len_tmp;
+			}
+			len_buf -= len_tmp;
+			buf += len_tmp;
+		}
+
+		/* ready to move to the next argument? */
+		if ((len_buf == 0) && !require_data) {
+			arg++;
+			iter = 0;
+			len_full = 0;
+			require_data = true;
+			encode = false;
+		}
+	} while (arg < context->execve.argc);
+
+	/* NOTE: the caller handles the final audit_log_end() call */
+
+out:
+	kfree(buf_head);
 }
 
 static void show_special(struct audit_context *context, int *call_panic)
@@ -1991,7 +1987,7 @@
 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
 	if (!ab)
 		return;
-	audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid);
+	audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid);
 	audit_log_task_context(ab);
 	audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d",
 			 oldloginuid, loginuid, oldsessionid, sessionid, !rc);
@@ -2216,7 +2212,7 @@
 {
 	struct audit_context *context = current->audit_context;
 
-	context->target_pid = task_pid_nr(t);
+	context->target_pid = task_tgid_nr(t);
 	context->target_auid = audit_get_loginuid(t);
 	context->target_uid = task_uid(t);
 	context->target_sessionid = audit_get_sessionid(t);
@@ -2241,7 +2237,7 @@
 
 	if (audit_pid && t->tgid == audit_pid) {
 		if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
-			audit_sig_pid = task_pid_nr(tsk);
+			audit_sig_pid = task_tgid_nr(tsk);
 			if (uid_valid(tsk->loginuid))
 				audit_sig_uid = tsk->loginuid;
 			else
@@ -2341,7 +2337,7 @@
 void __audit_log_capset(const struct cred *new, const struct cred *old)
 {
 	struct audit_context *context = current->audit_context;
-	context->capset.pid = task_pid_nr(current);
+	context->capset.pid = task_tgid_nr(current);
 	context->capset.cap.effective   = new->cap_effective;
 	context->capset.cap.inheritable = new->cap_effective;
 	context->capset.cap.permitted   = new->cap_permitted;
@@ -2373,7 +2369,7 @@
 			 from_kgid(&init_user_ns, gid),
 			 sessionid);
 	audit_log_task_context(ab);
-	audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
+	audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
 	audit_log_untrustedstring(ab, get_task_comm(comm, current));
 	audit_log_d_path_exe(ab, current->mm);
 }
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index 5a8a797..cb85d22 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -31,10 +31,10 @@
 {
 	switch (type) {
 	case BPF_TYPE_PROG:
-		atomic_inc(&((struct bpf_prog *)raw)->aux->refcnt);
+		raw = bpf_prog_inc(raw);
 		break;
 	case BPF_TYPE_MAP:
-		bpf_map_inc(raw, true);
+		raw = bpf_map_inc(raw, true);
 		break;
 	default:
 		WARN_ON_ONCE(1);
@@ -277,7 +277,8 @@
 		goto out;
 
 	raw = bpf_any_get(inode->i_private, *type);
-	touch_atime(&path);
+	if (!IS_ERR(raw))
+		touch_atime(&path);
 
 	path_put(&path);
 	return raw;
@@ -357,7 +358,7 @@
 static struct dentry *bpf_mount(struct file_system_type *type, int flags,
 				const char *dev_name, void *data)
 {
-	return mount_ns(type, flags, current->nsproxy->mnt_ns, bpf_fill_super);
+	return mount_nodev(type, flags, data, bpf_fill_super);
 }
 
 static struct file_system_type bpf_fs_type = {
@@ -365,7 +366,6 @@
 	.name		= "bpf",
 	.mount		= bpf_mount,
 	.kill_sb	= kill_litter_super,
-	.fs_flags	= FS_USERNS_MOUNT,
 };
 
 MODULE_ALIAS_FS("bpf");
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 3b39550..4e32cc9 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -181,11 +181,18 @@
 	return f.file->private_data;
 }
 
-void bpf_map_inc(struct bpf_map *map, bool uref)
+/* prog's and map's refcnt limit */
+#define BPF_MAX_REFCNT 32768
+
+struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
 {
-	atomic_inc(&map->refcnt);
+	if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
+		atomic_dec(&map->refcnt);
+		return ERR_PTR(-EBUSY);
+	}
 	if (uref)
 		atomic_inc(&map->usercnt);
+	return map;
 }
 
 struct bpf_map *bpf_map_get_with_uref(u32 ufd)
@@ -197,7 +204,7 @@
 	if (IS_ERR(map))
 		return map;
 
-	bpf_map_inc(map, true);
+	map = bpf_map_inc(map, true);
 	fdput(f);
 
 	return map;
@@ -580,6 +587,15 @@
 	return f.file->private_data;
 }
 
+struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
+{
+	if (atomic_inc_return(&prog->aux->refcnt) > BPF_MAX_REFCNT) {
+		atomic_dec(&prog->aux->refcnt);
+		return ERR_PTR(-EBUSY);
+	}
+	return prog;
+}
+
 /* called by sockets/tracing/seccomp before attaching program to an event
  * pairs with bpf_prog_put()
  */
@@ -592,7 +608,7 @@
 	if (IS_ERR(prog))
 		return prog;
 
-	atomic_inc(&prog->aux->refcnt);
+	prog = bpf_prog_inc(prog);
 	fdput(f);
 
 	return prog;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 2e7f7ab..85de509 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -239,15 +239,6 @@
 	[CONST_IMM]		= "imm",
 };
 
-static const struct {
-	int map_type;
-	int func_id;
-} func_limit[] = {
-	{BPF_MAP_TYPE_PROG_ARRAY, BPF_FUNC_tail_call},
-	{BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_read},
-	{BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_output},
-};
-
 static void print_verifier_state(struct verifier_env *env)
 {
 	enum bpf_reg_type t;
@@ -322,7 +313,8 @@
 	[BPF_EXIT >> 4] = "exit",
 };
 
-static void print_bpf_insn(struct bpf_insn *insn)
+static void print_bpf_insn(const struct verifier_env *env,
+			   const struct bpf_insn *insn)
 {
 	u8 class = BPF_CLASS(insn->code);
 
@@ -386,9 +378,19 @@
 				insn->code,
 				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
 				insn->src_reg, insn->imm);
-		} else if (BPF_MODE(insn->code) == BPF_IMM) {
-			verbose("(%02x) r%d = 0x%x\n",
-				insn->code, insn->dst_reg, insn->imm);
+		} else if (BPF_MODE(insn->code) == BPF_IMM &&
+			   BPF_SIZE(insn->code) == BPF_DW) {
+			/* At this point, we already made sure that the second
+			 * part of the ldimm64 insn is accessible.
+			 */
+			u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm;
+			bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD;
+
+			if (map_ptr && !env->allow_ptr_leaks)
+				imm = 0;
+
+			verbose("(%02x) r%d = 0x%llx\n", insn->code,
+				insn->dst_reg, (unsigned long long)imm);
 		} else {
 			verbose("BUG_ld_%02x\n", insn->code);
 			return;
@@ -898,24 +900,44 @@
 
 static int check_map_func_compatibility(struct bpf_map *map, int func_id)
 {
-	bool bool_map, bool_func;
-	int i;
-
 	if (!map)
 		return 0;
 
-	for (i = 0; i < ARRAY_SIZE(func_limit); i++) {
-		bool_map = (map->map_type == func_limit[i].map_type);
-		bool_func = (func_id == func_limit[i].func_id);
-		/* only when map & func pair match it can continue.
-		 * don't allow any other map type to be passed into
-		 * the special func;
-		 */
-		if (bool_func && bool_map != bool_func)
-			return -EINVAL;
+	/* We need a two way check, first is from map perspective ... */
+	switch (map->map_type) {
+	case BPF_MAP_TYPE_PROG_ARRAY:
+		if (func_id != BPF_FUNC_tail_call)
+			goto error;
+		break;
+	case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
+		if (func_id != BPF_FUNC_perf_event_read &&
+		    func_id != BPF_FUNC_perf_event_output)
+			goto error;
+		break;
+	default:
+		break;
+	}
+
+	/* ... and second from the function itself. */
+	switch (func_id) {
+	case BPF_FUNC_tail_call:
+		if (map->map_type != BPF_MAP_TYPE_PROG_ARRAY)
+			goto error;
+		break;
+	case BPF_FUNC_perf_event_read:
+	case BPF_FUNC_perf_event_output:
+		if (map->map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY)
+			goto error;
+		break;
+	default:
+		break;
 	}
 
 	return 0;
+error:
+	verbose("cannot pass map_type %d into func %d\n",
+		map->map_type, func_id);
+	return -EINVAL;
 }
 
 static int check_call(struct verifier_env *env, int func_id)
@@ -1348,6 +1370,7 @@
 	}
 
 	if (insn->dst_reg != BPF_REG_0 || insn->off != 0 ||
+	    BPF_SIZE(insn->code) == BPF_DW ||
 	    (mode == BPF_ABS && insn->src_reg != BPF_REG_0)) {
 		verbose("BPF_LD_ABS uses reserved fields\n");
 		return -EINVAL;
@@ -1746,7 +1769,7 @@
 
 		if (log_level) {
 			verbose("%d: ", insn_idx);
-			print_bpf_insn(insn);
+			print_bpf_insn(env, insn);
 		}
 
 		if (class == BPF_ALU || class == BPF_ALU64) {
@@ -2003,7 +2026,6 @@
 			if (IS_ERR(map)) {
 				verbose("fd %d is not pointing to valid bpf_map\n",
 					insn->imm);
-				fdput(f);
 				return PTR_ERR(map);
 			}
 
@@ -2023,15 +2045,18 @@
 				return -E2BIG;
 			}
 
-			/* remember this map */
-			env->used_maps[env->used_map_cnt++] = map;
-
 			/* hold the map. If the program is rejected by verifier,
 			 * the map will be released by release_maps() or it
 			 * will be used by the valid program until it's unloaded
 			 * and all maps are released in free_bpf_prog_info()
 			 */
-			bpf_map_inc(map, false);
+			map = bpf_map_inc(map, false);
+			if (IS_ERR(map)) {
+				fdput(f);
+				return PTR_ERR(map);
+			}
+			env->used_maps[env->used_map_cnt++] = map;
+
 			fdput(f);
 next_insn:
 			insn++;
diff --git a/kernel/capability.c b/kernel/capability.c
index 45432b5..4984e1f 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -361,6 +361,24 @@
 	return has_ns_capability_noaudit(t, &init_user_ns, cap);
 }
 
+static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
+{
+	int capable;
+
+	if (unlikely(!cap_valid(cap))) {
+		pr_crit("capable() called with invalid cap=%u\n", cap);
+		BUG();
+	}
+
+	capable = audit ? security_capable(current_cred(), ns, cap) :
+			  security_capable_noaudit(current_cred(), ns, cap);
+	if (capable == 0) {
+		current->flags |= PF_SUPERPRIV;
+		return true;
+	}
+	return false;
+}
+
 /**
  * ns_capable - Determine if the current task has a superior capability in effect
  * @ns:  The usernamespace we want the capability in
@@ -374,19 +392,27 @@
  */
 bool ns_capable(struct user_namespace *ns, int cap)
 {
-	if (unlikely(!cap_valid(cap))) {
-		pr_crit("capable() called with invalid cap=%u\n", cap);
-		BUG();
-	}
-
-	if (security_capable(current_cred(), ns, cap) == 0) {
-		current->flags |= PF_SUPERPRIV;
-		return true;
-	}
-	return false;
+	return ns_capable_common(ns, cap, true);
 }
 EXPORT_SYMBOL(ns_capable);
 
+/**
+ * ns_capable_noaudit - Determine if the current task has a superior capability
+ * (unaudited) in effect
+ * @ns:  The usernamespace we want the capability in
+ * @cap: The capability to be tested for
+ *
+ * Return true if the current task has the given superior capability currently
+ * available for use, false if not.
+ *
+ * This sets PF_SUPERPRIV on the task if the capability is available on the
+ * assumption that it's about to be used.
+ */
+bool ns_capable_noaudit(struct user_namespace *ns, int cap)
+{
+	return ns_capable_common(ns, cap, false);
+}
+EXPORT_SYMBOL(ns_capable_noaudit);
 
 /**
  * capable - Determine if the current task has a superior capability in effect
@@ -431,6 +457,19 @@
 EXPORT_SYMBOL(file_ns_capable);
 
 /**
+ * privileged_wrt_inode_uidgid - Do capabilities in the namespace work over the inode?
+ * @ns: The user namespace in question
+ * @inode: The inode in question
+ *
+ * Return true if the inode uid and gid are within the namespace.
+ */
+bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode)
+{
+	return kuid_has_mapping(ns, inode->i_uid) &&
+		kgid_has_mapping(ns, inode->i_gid);
+}
+
+/**
  * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped
  * @inode: The inode in question
  * @cap: The capability in question
@@ -443,7 +482,26 @@
 {
 	struct user_namespace *ns = current_user_ns();
 
-	return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid) &&
-		kgid_has_mapping(ns, inode->i_gid);
+	return ns_capable(ns, cap) && privileged_wrt_inode_uidgid(ns, inode);
 }
 EXPORT_SYMBOL(capable_wrt_inode_uidgid);
+
+/**
+ * ptracer_capable - Determine if the ptracer holds CAP_SYS_PTRACE in the namespace
+ * @tsk: The task that may be ptraced
+ * @ns: The user namespace to search for CAP_SYS_PTRACE in
+ *
+ * Return true if the task that is ptracing the current task had CAP_SYS_PTRACE
+ * in the specified user namespace.
+ */
+bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns)
+{
+	int ret = 0;  /* An absent tracer adds no restrictions */
+	const struct cred *cred;
+	rcu_read_lock();
+	cred = rcu_dereference(tsk->ptracer_cred);
+	if (cred)
+		ret = security_capable_noaudit(cred, ns, CAP_SYS_PTRACE);
+	rcu_read_unlock();
+	return (ret == 0);
+}
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 47851db..8ab133d 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -236,6 +236,9 @@
  */
 static bool cgroup_ssid_enabled(int ssid)
 {
+	if (CGROUP_SUBSYS_COUNT == 0)
+		return false;
+
 	return static_key_enabled(cgroup_subsys_enabled_key[ssid]);
 }
 
@@ -2671,45 +2674,6 @@
 	return ret;
 }
 
-int subsys_cgroup_allow_attach(struct cgroup_taskset *tset)
-{
-	const struct cred *cred = current_cred(), *tcred;
-	struct task_struct *task;
-	struct cgroup_subsys_state *css;
-
-	if (capable(CAP_SYS_NICE))
-		return 0;
-
-	cgroup_taskset_for_each(task, css, tset) {
-		tcred = __task_cred(task);
-
-		if (current != task && !uid_eq(cred->euid, tcred->uid) &&
-		    !uid_eq(cred->euid, tcred->suid))
-			return -EACCES;
-	}
-
-	return 0;
-}
-
-static int cgroup_allow_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
-{
-	struct cgroup_subsys_state *css;
-	int i;
-	int ret;
-
-	for_each_css(css, i, cgrp) {
-		if (css->ss->allow_attach) {
-			ret = css->ss->allow_attach(tset);
-			if (ret)
-				return ret;
-		} else {
-			return -EACCES;
-		}
-	}
-
-	return 0;
-}
-
 static int cgroup_procs_write_permission(struct task_struct *task,
 					 struct cgroup *dst_cgrp,
 					 struct kernfs_open_file *of)
@@ -2724,24 +2688,9 @@
 	 */
 	if (!uid_eq(cred->euid, GLOBAL_ROOT_UID) &&
 	    !uid_eq(cred->euid, tcred->uid) &&
-	    !uid_eq(cred->euid, tcred->suid)) {
-		/*
-		 * if the default permission check fails, give each
-		 * cgroup a chance to extend the permission check
-		 */
-		struct cgroup_taskset tset = {
-			.src_csets = LIST_HEAD_INIT(tset.src_csets),
-			.dst_csets = LIST_HEAD_INIT(tset.dst_csets),
-			.csets = &tset.src_csets,
-		};
-		struct css_set *cset;
-		cset = task_css_set(task);
-		list_add(&cset->mg_node, &tset.src_csets);
-		ret = cgroup_allow_attach(dst_cgrp, &tset);
-		list_del(&tset.src_csets);
-		if (ret)
-			ret = -EACCES;
-	}
+	    !uid_eq(cred->euid, tcred->suid) &&
+	    !ns_capable(tcred->user_ns, CAP_SYS_NICE))
+		ret = -EACCES;
 
 	if (!ret && cgroup_on_dfl(dst_cgrp)) {
 		struct super_block *sb = of->file->f_path.dentry->d_sb;
@@ -2804,11 +2753,12 @@
 		tsk = tsk->group_leader;
 
 	/*
-	 * Workqueue threads may acquire PF_NO_SETAFFINITY and become
-	 * trapped in a cpuset, or RT worker may be born in a cgroup
-	 * with no rt_runtime allocated.  Just say no.
+	 * kthreads may acquire PF_NO_SETAFFINITY during initialization.
+	 * If userland migrates such a kthread to a non-root cgroup, it can
+	 * become trapped in a cpuset, or RT kthread may be born in a
+	 * cgroup with no rt_runtime allocated.  Just say no.
 	 */
-	if (tsk == kthreadd_task || (tsk->flags & PF_NO_SETAFFINITY)) {
+	if (tsk->no_cgroup_migration || (tsk->flags & PF_NO_SETAFFINITY)) {
 		ret = -EINVAL;
 		goto out_unlock_rcu;
 	}
@@ -4848,6 +4798,7 @@
 	memset(css, 0, sizeof(*css));
 	css->cgroup = cgrp;
 	css->ss = ss;
+	css->id = -1;
 	INIT_LIST_HEAD(&css->sibling);
 	INIT_LIST_HEAD(&css->children);
 	css->serial_nr = css_serial_nr_next++;
@@ -5379,6 +5330,12 @@
 	BUG_ON(cgroup_init_cftypes(NULL, cgroup_dfl_base_files));
 	BUG_ON(cgroup_init_cftypes(NULL, cgroup_legacy_base_files));
 
+	/*
+	 * The latency of the synchronize_sched() is too high for cgroups,
+	 * avoid it at the cost of forcing all readers into the slow path.
+	 */
+	rcu_sync_enter_start(&cgroup_threadgroup_rwsem.rss);
+
 	mutex_lock(&cgroup_mutex);
 
 	/* Add init_css_set to the hash table */
diff --git a/kernel/configs/tiny.config b/kernel/configs/tiny.config
index c2de56a..7fa0c4a 100644
--- a/kernel/configs/tiny.config
+++ b/kernel/configs/tiny.config
@@ -1,4 +1,12 @@
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
 CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
 CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_SLAB is not set
+# CONFIG_SLUB is not set
 CONFIG_SLOB=y
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 9ced7c7..24ca296 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -185,10 +185,17 @@
 }
 EXPORT_SYMBOL_GPL(cpu_hotplug_disable);
 
+static void __cpu_hotplug_enable(void)
+{
+	if (WARN_ONCE(!cpu_hotplug_disabled, "Unbalanced cpu hotplug enable\n"))
+		return;
+	cpu_hotplug_disabled--;
+}
+
 void cpu_hotplug_enable(void)
 {
 	cpu_maps_update_begin();
-	WARN_ON(--cpu_hotplug_disabled < 0);
+	__cpu_hotplug_enable();
 	cpu_maps_update_done();
 }
 EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
@@ -225,12 +232,6 @@
 	return __cpu_notify(val, v, -1, NULL);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-
-static void cpu_notify_nofail(unsigned long val, void *v)
-{
-	BUG_ON(cpu_notify(val, v));
-}
 EXPORT_SYMBOL(register_cpu_notifier);
 EXPORT_SYMBOL(__register_cpu_notifier);
 
@@ -248,6 +249,12 @@
 }
 EXPORT_SYMBOL(__unregister_cpu_notifier);
 
+#ifdef CONFIG_HOTPLUG_CPU
+static void cpu_notify_nofail(unsigned long val, void *v)
+{
+	BUG_ON(cpu_notify(val, v));
+}
+
 /**
  * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
  * @cpu: a CPU id
@@ -631,7 +638,7 @@
 
 	/* Allow everyone to use the CPU hotplug again */
 	cpu_maps_update_begin();
-	WARN_ON(--cpu_hotplug_disabled < 0);
+	__cpu_hotplug_enable();
 	if (cpumask_empty(frozen_cpus))
 		goto out;
 
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 11eaf14..146292b 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -98,6 +98,7 @@
 
 	/* user-configured CPUs and Memory Nodes allow to tasks */
 	cpumask_var_t cpus_allowed;
+	cpumask_var_t cpus_requested;
 	nodemask_t mems_allowed;
 
 	/* effective CPUs and Memory Nodes allow to tasks */
@@ -173,9 +174,9 @@
 } cpuset_flagbits_t;
 
 /* convenient tests for these bits */
-static inline bool is_cpuset_online(const struct cpuset *cs)
+static inline bool is_cpuset_online(struct cpuset *cs)
 {
-	return test_bit(CS_ONLINE, &cs->flags);
+	return test_bit(CS_ONLINE, &cs->flags) && !css_is_dying(&cs->css);
 }
 
 static inline int is_cpu_exclusive(const struct cpuset *cs)
@@ -324,8 +325,7 @@
 /*
  * Return in pmask the portion of a cpusets's cpus_allowed that
  * are online.  If none are online, walk up the cpuset hierarchy
- * until we find one that does have some online cpus.  The top
- * cpuset always has some cpus online.
+ * until we find one that does have some online cpus.
  *
  * One way or another, we guarantee to return some non-empty subset
  * of cpu_online_mask.
@@ -334,8 +334,20 @@
  */
 static void guarantee_online_cpus(struct cpuset *cs, struct cpumask *pmask)
 {
-	while (!cpumask_intersects(cs->effective_cpus, cpu_online_mask))
+	while (!cpumask_intersects(cs->effective_cpus, cpu_online_mask)) {
 		cs = parent_cs(cs);
+		if (unlikely(!cs)) {
+			/*
+			 * The top cpuset doesn't have any online cpu as a
+			 * consequence of a race between cpuset_hotplug_work
+			 * and cpu hotplug notifier.  But we know the top
+			 * cpuset's effective_cpus is on its way to to be
+			 * identical to cpu_online_mask.
+			 */
+			cpumask_copy(pmask, cpu_online_mask);
+			return;
+		}
+	}
 	cpumask_and(pmask, cs->effective_cpus, cpu_online_mask);
 }
 
@@ -386,7 +398,7 @@
 
 static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q)
 {
-	return	cpumask_subset(p->cpus_allowed, q->cpus_allowed) &&
+	return	cpumask_subset(p->cpus_requested, q->cpus_requested) &&
 		nodes_subset(p->mems_allowed, q->mems_allowed) &&
 		is_cpu_exclusive(p) <= is_cpu_exclusive(q) &&
 		is_mem_exclusive(p) <= is_mem_exclusive(q);
@@ -486,7 +498,7 @@
 	cpuset_for_each_child(c, css, par) {
 		if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) &&
 		    c != cur &&
-		    cpumask_intersects(trial->cpus_allowed, c->cpus_allowed))
+		    cpumask_intersects(trial->cpus_requested, c->cpus_requested))
 			goto out;
 		if ((is_mem_exclusive(trial) || is_mem_exclusive(c)) &&
 		    c != cur &&
@@ -945,17 +957,18 @@
 	if (!*buf) {
 		cpumask_clear(trialcs->cpus_allowed);
 	} else {
-		retval = cpulist_parse(buf, trialcs->cpus_allowed);
+		retval = cpulist_parse(buf, trialcs->cpus_requested);
 		if (retval < 0)
 			return retval;
 
-		if (!cpumask_subset(trialcs->cpus_allowed,
-				    top_cpuset.cpus_allowed))
+		if (!cpumask_subset(trialcs->cpus_requested, cpu_present_mask))
 			return -EINVAL;
+
+		cpumask_and(trialcs->cpus_allowed, trialcs->cpus_requested, cpu_active_mask);
 	}
 
 	/* Nothing to do if the cpus didn't change */
-	if (cpumask_equal(cs->cpus_allowed, trialcs->cpus_allowed))
+	if (cpumask_equal(cs->cpus_requested, trialcs->cpus_requested))
 		return 0;
 
 	retval = validate_change(cs, trialcs);
@@ -964,6 +977,7 @@
 
 	spin_lock_irq(&callback_lock);
 	cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
+	cpumask_copy(cs->cpus_requested, trialcs->cpus_requested);
 	spin_unlock_irq(&callback_lock);
 
 	/* use trialcs->cpus_allowed as a temp variable */
@@ -1754,7 +1768,7 @@
 
 	switch (type) {
 	case FILE_CPULIST:
-		seq_printf(sf, "%*pbl\n", cpumask_pr_args(cs->cpus_allowed));
+		seq_printf(sf, "%*pbl\n", cpumask_pr_args(cs->cpus_requested));
 		break;
 	case FILE_MEMLIST:
 		seq_printf(sf, "%*pbl\n", nodemask_pr_args(&cs->mems_allowed));
@@ -1943,11 +1957,14 @@
 		return ERR_PTR(-ENOMEM);
 	if (!alloc_cpumask_var(&cs->cpus_allowed, GFP_KERNEL))
 		goto free_cs;
+	if (!alloc_cpumask_var(&cs->cpus_requested, GFP_KERNEL))
+		goto free_allowed;
 	if (!alloc_cpumask_var(&cs->effective_cpus, GFP_KERNEL))
-		goto free_cpus;
+		goto free_requested;
 
 	set_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
 	cpumask_clear(cs->cpus_allowed);
+	cpumask_clear(cs->cpus_requested);
 	nodes_clear(cs->mems_allowed);
 	cpumask_clear(cs->effective_cpus);
 	nodes_clear(cs->effective_mems);
@@ -1956,7 +1973,9 @@
 
 	return &cs->css;
 
-free_cpus:
+free_requested:
+	free_cpumask_var(cs->cpus_requested);
+free_allowed:
 	free_cpumask_var(cs->cpus_allowed);
 free_cs:
 	kfree(cs);
@@ -2019,6 +2038,7 @@
 	cs->mems_allowed = parent->mems_allowed;
 	cs->effective_mems = parent->mems_allowed;
 	cpumask_copy(cs->cpus_allowed, parent->cpus_allowed);
+	cpumask_copy(cs->cpus_requested, parent->cpus_requested);
 	cpumask_copy(cs->effective_cpus, parent->cpus_allowed);
 	spin_unlock_irq(&callback_lock);
 out_unlock:
@@ -2053,6 +2073,7 @@
 
 	free_cpumask_var(cs->effective_cpus);
 	free_cpumask_var(cs->cpus_allowed);
+	free_cpumask_var(cs->cpus_requested);
 	kfree(cs);
 }
 
@@ -2074,6 +2095,20 @@
 	mutex_unlock(&cpuset_mutex);
 }
 
+/*
+ * Make sure the new task conform to the current state of its parent,
+ * which could have been changed by cpuset just after it inherits the
+ * state from the parent and before it sits on the cgroup's task list.
+ */
+void cpuset_fork(struct task_struct *task, void *priv)
+{
+	if (task_css_is_root(task, cpuset_cgrp_id))
+		return;
+
+	set_cpus_allowed_ptr(task, &current->cpus_allowed);
+	task->mems_allowed = current->mems_allowed;
+}
+
 struct cgroup_subsys cpuset_cgrp_subsys = {
 	.css_alloc	= cpuset_css_alloc,
 	.css_online	= cpuset_css_online,
@@ -2084,6 +2119,7 @@
 	.attach		= cpuset_attach,
 	.post_attach	= cpuset_post_attach,
 	.bind		= cpuset_bind,
+	.fork		= cpuset_fork,
 	.legacy_cftypes	= files,
 	.early_init	= 1,
 };
@@ -2102,8 +2138,11 @@
 		BUG();
 	if (!alloc_cpumask_var(&top_cpuset.effective_cpus, GFP_KERNEL))
 		BUG();
+	if (!alloc_cpumask_var(&top_cpuset.cpus_requested, GFP_KERNEL))
+		BUG();
 
 	cpumask_setall(top_cpuset.cpus_allowed);
+	cpumask_setall(top_cpuset.cpus_requested);
 	nodes_setall(top_cpuset.mems_allowed);
 	cpumask_setall(top_cpuset.effective_cpus);
 	nodes_setall(top_cpuset.effective_mems);
@@ -2237,7 +2276,7 @@
 		goto retry;
 	}
 
-	cpumask_and(&new_cpus, cs->cpus_allowed, parent_cs(cs)->effective_cpus);
+	cpumask_and(&new_cpus, cs->cpus_requested, parent_cs(cs)->effective_cpus);
 	nodes_and(new_mems, cs->mems_allowed, parent_cs(cs)->effective_mems);
 
 	cpus_updated = !cpumask_equal(&new_cpus, cs->effective_cpus);
diff --git a/kernel/cred.c b/kernel/cred.c
index 71179a0..ff8606f 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -689,6 +689,8 @@
  */
 int set_create_files_as(struct cred *new, struct inode *inode)
 {
+	if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
+		return -EINVAL;
 	new->fsuid = inode->i_uid;
 	new->fsgid = inode->i_gid;
 	return security_kernel_create_files_as(new, inode);
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 0874e2e..79517e5 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -598,11 +598,11 @@
 	/*
 	 * Wait for the other CPUs to be notified and be waiting for us:
 	 */
-	time_left = loops_per_jiffy * HZ;
+	time_left = MSEC_PER_SEC;
 	while (kgdb_do_roundup && --time_left &&
 	       (atomic_read(&masters_in_kgdb) + atomic_read(&slaves_in_kgdb)) !=
 		   online_cpus)
-		cpu_relax();
+		udelay(1000);
 	if (!time_left)
 		pr_crit("Timed out waiting for secondary CPUs.\n");
 
diff --git a/kernel/debug/kdb/kdb_bp.c b/kernel/debug/kdb/kdb_bp.c
index e1dbf4a..90ff129 100644
--- a/kernel/debug/kdb/kdb_bp.c
+++ b/kernel/debug/kdb/kdb_bp.c
@@ -153,13 +153,11 @@
 	} else {
 		kdb_printf("%s: failed to set breakpoint at 0x%lx\n",
 			   __func__, bp->bp_addr);
-#ifdef CONFIG_DEBUG_RODATA
 		if (!bp->bp_type) {
 			kdb_printf("Software breakpoints are unavailable.\n"
-				   "  Change the kernel CONFIG_DEBUG_RODATA=n\n"
+				   "  Boot the kernel with rodata=off\n"
 				   "  OR use hw breaks: help bph\n");
 		}
-#endif
 		return 1;
 	}
 	return 0;
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index fc1ef73..0b89128 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -216,7 +216,7 @@
 	int i;
 	int diag, dtab_count;
 	int key;
-
+	static int last_crlf;
 
 	diag = kdbgetintenv("DTABCOUNT", &dtab_count);
 	if (diag)
@@ -237,6 +237,9 @@
 		return buffer;
 	if (key != 9)
 		tab = 0;
+	if (key != 10 && key != 13)
+		last_crlf = 0;
+
 	switch (key) {
 	case 8: /* backspace */
 		if (cp > buffer) {
@@ -254,7 +257,12 @@
 			*cp = tmp;
 		}
 		break;
-	case 13: /* enter */
+	case 10: /* new line */
+	case 13: /* carriage return */
+		/* handle \n after \r */
+		if (last_crlf && last_crlf != key)
+			break;
+		last_crlf = key;
 		*lastchar++ = '\n';
 		*lastchar++ = '\0';
 		if (!KDB_STATE(KGDB_TRANS)) {
diff --git a/kernel/events/core.c b/kernel/events/core.c
index fb9b3b5..0006c49 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -951,6 +951,7 @@
  * function.
  *
  * Lock order:
+ *    cred_guard_mutex
  *	task_struct::perf_event_mutex
  *	  perf_event_context::mutex
  *	    perf_event_context::lock
@@ -1543,12 +1544,33 @@
 
 core_initcall(perf_workqueue_init);
 
-static inline int pmu_filter_match(struct perf_event *event)
+static inline int __pmu_filter_match(struct perf_event *event)
 {
 	struct pmu *pmu = event->pmu;
 	return pmu->filter_match ? pmu->filter_match(event) : 1;
 }
 
+/*
+ * Check whether we should attempt to schedule an event group based on
+ * PMU-specific filtering. An event group can consist of HW and SW events,
+ * potentially with a SW leader, so we must check all the filters, to
+ * determine whether a group is schedulable:
+ */
+static inline int pmu_filter_match(struct perf_event *event)
+{
+	struct perf_event *child;
+
+	if (!__pmu_filter_match(event))
+		return 0;
+
+	list_for_each_entry(child, &event->sibling_list, group_entry) {
+		if (!__pmu_filter_match(child))
+			return 0;
+	}
+
+	return 1;
+}
+
 static inline int
 event_filter_match(struct perf_event *event)
 {
@@ -3423,7 +3445,6 @@
 find_lively_task_by_vpid(pid_t vpid)
 {
 	struct task_struct *task;
-	int err;
 
 	rcu_read_lock();
 	if (!vpid)
@@ -3437,16 +3458,7 @@
 	if (!task)
 		return ERR_PTR(-ESRCH);
 
-	/* Reuse ptrace permission checks for now. */
-	err = -EACCES;
-	if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS))
-		goto errout;
-
 	return task;
-errout:
-	put_task_struct(task);
-	return ERR_PTR(err);
-
 }
 
 /*
@@ -6032,6 +6044,27 @@
 	char *buf = NULL;
 	char *name;
 
+	if (vma->vm_flags & VM_READ)
+		prot |= PROT_READ;
+	if (vma->vm_flags & VM_WRITE)
+		prot |= PROT_WRITE;
+	if (vma->vm_flags & VM_EXEC)
+		prot |= PROT_EXEC;
+
+	if (vma->vm_flags & VM_MAYSHARE)
+		flags = MAP_SHARED;
+	else
+		flags = MAP_PRIVATE;
+
+	if (vma->vm_flags & VM_DENYWRITE)
+		flags |= MAP_DENYWRITE;
+	if (vma->vm_flags & VM_MAYEXEC)
+		flags |= MAP_EXECUTABLE;
+	if (vma->vm_flags & VM_LOCKED)
+		flags |= MAP_LOCKED;
+	if (vma->vm_flags & VM_HUGETLB)
+		flags |= MAP_HUGETLB;
+
 	if (file) {
 		struct inode *inode;
 		dev_t dev;
@@ -6058,27 +6091,6 @@
 		maj = MAJOR(dev);
 		min = MINOR(dev);
 
-		if (vma->vm_flags & VM_READ)
-			prot |= PROT_READ;
-		if (vma->vm_flags & VM_WRITE)
-			prot |= PROT_WRITE;
-		if (vma->vm_flags & VM_EXEC)
-			prot |= PROT_EXEC;
-
-		if (vma->vm_flags & VM_MAYSHARE)
-			flags = MAP_SHARED;
-		else
-			flags = MAP_PRIVATE;
-
-		if (vma->vm_flags & VM_DENYWRITE)
-			flags |= MAP_DENYWRITE;
-		if (vma->vm_flags & VM_MAYEXEC)
-			flags |= MAP_EXECUTABLE;
-		if (vma->vm_flags & VM_LOCKED)
-			flags |= MAP_LOCKED;
-		if (vma->vm_flags & VM_HUGETLB)
-			flags |= MAP_HUGETLB;
-
 		goto got_name;
 	} else {
 		if (vma->vm_ops && vma->vm_ops->name) {
@@ -6403,6 +6415,21 @@
 	perf_output_end(&handle);
 }
 
+static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs)
+{
+	/*
+	 * Due to interrupt latency (AKA "skid"), we may enter the
+	 * kernel before taking an overflow, even if the PMU is only
+	 * counting user events.
+	 * To avoid leaking information to userspace, we must always
+	 * reject kernel samples when exclude_kernel is set.
+	 */
+	if (event->attr.exclude_kernel && !user_mode(regs))
+		return false;
+
+	return true;
+}
+
 /*
  * Generic event overflow handling, sampling.
  */
@@ -6450,6 +6477,12 @@
 	}
 
 	/*
+	 * For security, drop the skid kernel samples if necessary.
+	 */
+	if (!sample_is_allowed(event, regs))
+		return ret;
+
+	/*
 	 * XXX event_limit might not quite work as expected on inherited
 	 * events
 	 */
@@ -7115,7 +7148,7 @@
 	prog = event->tp_event->prog;
 	if (prog) {
 		event->tp_event->prog = NULL;
-		bpf_prog_put(prog);
+		bpf_prog_put_rcu(prog);
 	}
 }
 
@@ -8243,6 +8276,37 @@
 	return 0;
 }
 
+/*
+ * Variation on perf_event_ctx_lock_nested(), except we take two context
+ * mutexes.
+ */
+static struct perf_event_context *
+__perf_event_ctx_lock_double(struct perf_event *group_leader,
+			     struct perf_event_context *ctx)
+{
+	struct perf_event_context *gctx;
+
+again:
+	rcu_read_lock();
+	gctx = READ_ONCE(group_leader->ctx);
+	if (!atomic_inc_not_zero(&gctx->refcount)) {
+		rcu_read_unlock();
+		goto again;
+	}
+	rcu_read_unlock();
+
+	mutex_lock_double(&gctx->mutex, &ctx->mutex);
+
+	if (group_leader->ctx != gctx) {
+		mutex_unlock(&ctx->mutex);
+		mutex_unlock(&gctx->mutex);
+		put_ctx(gctx);
+		goto again;
+	}
+
+	return gctx;
+}
+
 /**
  * sys_perf_event_open - open a performance event, associate it to a task/cpu
  *
@@ -8336,6 +8400,24 @@
 
 	get_online_cpus();
 
+	if (task) {
+		err = mutex_lock_interruptible(&task->signal->cred_guard_mutex);
+		if (err)
+			goto err_cpus;
+
+		/*
+		 * Reuse ptrace permission checks for now.
+		 *
+		 * We must hold cred_guard_mutex across this and any potential
+		 * perf_install_in_context() call for this new event to
+		 * serialize against exec() altering our credentials (and the
+		 * perf_event_exit_task() that could imply).
+		 */
+		err = -EACCES;
+		if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS))
+			goto err_cred;
+	}
+
 	if (flags & PERF_FLAG_PID_CGROUP)
 		cgroup_fd = pid;
 
@@ -8343,7 +8425,7 @@
 				 NULL, NULL, cgroup_fd);
 	if (IS_ERR(event)) {
 		err = PTR_ERR(event);
-		goto err_cpus;
+		goto err_cred;
 	}
 
 	if (is_sampling_event(event)) {
@@ -8402,11 +8484,6 @@
 		goto err_context;
 	}
 
-	if (task) {
-		put_task_struct(task);
-		task = NULL;
-	}
-
 	/*
 	 * Look up the group leader (we will attach this event to it):
 	 */
@@ -8469,8 +8546,26 @@
 	}
 
 	if (move_group) {
-		gctx = group_leader->ctx;
-		mutex_lock_double(&gctx->mutex, &ctx->mutex);
+		gctx = __perf_event_ctx_lock_double(group_leader, ctx);
+
+		/*
+		 * Check if we raced against another sys_perf_event_open() call
+		 * moving the software group underneath us.
+		 */
+		if (!(group_leader->group_flags & PERF_GROUP_SOFTWARE)) {
+			/*
+			 * If someone moved the group out from under us, check
+			 * if this new event wound up on the same ctx, if so
+			 * its the regular !move_group case, otherwise fail.
+			 */
+			if (gctx != ctx) {
+				err = -EINVAL;
+				goto err_locked;
+			} else {
+				perf_event_ctx_unlock(group_leader, gctx);
+				move_group = 0;
+			}
+		}
 	} else {
 		mutex_lock(&ctx->mutex);
 	}
@@ -8494,6 +8589,11 @@
 
 	WARN_ON_ONCE(ctx->parent_ctx);
 
+	/*
+	 * This is the point on no return; we cannot fail hereafter. This is
+	 * where we start modifying current state.
+	 */
+
 	if (move_group) {
 		/*
 		 * See perf_event_ctx_lock() for comments on the details
@@ -8560,9 +8660,14 @@
 	perf_unpin_context(ctx);
 
 	if (move_group)
-		mutex_unlock(&gctx->mutex);
+		perf_event_ctx_unlock(group_leader, gctx);
 	mutex_unlock(&ctx->mutex);
 
+	if (task) {
+		mutex_unlock(&task->signal->cred_guard_mutex);
+		put_task_struct(task);
+	}
+
 	put_online_cpus();
 
 	event->owner = current;
@@ -8583,7 +8688,7 @@
 
 err_locked:
 	if (move_group)
-		mutex_unlock(&gctx->mutex);
+		perf_event_ctx_unlock(group_leader, gctx);
 	mutex_unlock(&ctx->mutex);
 /* err_file: */
 	fput(event_file);
@@ -8597,6 +8702,9 @@
 	 */
 	if (!event_file)
 		free_event(event);
+err_cred:
+	if (task)
+		mutex_unlock(&task->signal->cred_guard_mutex);
 err_cpus:
 	put_online_cpus();
 err_task:
@@ -8876,6 +8984,9 @@
 
 /*
  * When a child task exits, feed back event values to parent events.
+ *
+ * Can be called with cred_guard_mutex held when called from
+ * install_exec_creds().
  */
 void perf_event_exit_task(struct task_struct *child)
 {
@@ -9197,7 +9308,7 @@
 		ret = inherit_task_group(event, parent, parent_ctx,
 					 child, ctxn, &inherited_all);
 		if (ret)
-			break;
+			goto out_unlock;
 	}
 
 	/*
@@ -9213,7 +9324,7 @@
 		ret = inherit_task_group(event, parent, parent_ctx,
 					 child, ctxn, &inherited_all);
 		if (ret)
-			break;
+			goto out_unlock;
 	}
 
 	raw_spin_lock_irqsave(&parent_ctx->lock, flags);
@@ -9241,6 +9352,7 @@
 	}
 
 	raw_spin_unlock_irqrestore(&parent_ctx->lock, flags);
+out_unlock:
 	mutex_unlock(&parent_ctx->mutex);
 
 	perf_unpin_context(parent_ctx);
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index adfdc05..014b695 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -347,6 +347,7 @@
 			 bool truncated)
 {
 	struct ring_buffer *rb = handle->rb;
+	bool wakeup = truncated;
 	unsigned long aux_head;
 	u64 flags = 0;
 
@@ -375,9 +376,16 @@
 	aux_head = rb->user_page->aux_head = local_read(&rb->aux_head);
 
 	if (aux_head - local_read(&rb->aux_wakeup) >= rb->aux_watermark) {
-		perf_output_wakeup(handle);
+		wakeup = true;
 		local_add(rb->aux_watermark, &rb->aux_wakeup);
 	}
+
+	if (wakeup) {
+		if (truncated)
+			handle->event->pending_disable = 1;
+		perf_output_wakeup(handle);
+	}
+
 	handle->event = NULL;
 
 	local_set(&rb->aux_nest, 0);
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 7dad849..da0c09f 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -171,8 +171,10 @@
 	mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 	err = -EAGAIN;
 	ptep = page_check_address(page, mm, addr, &ptl, 0);
-	if (!ptep)
+	if (!ptep) {
+		mem_cgroup_cancel_charge(kpage, memcg);
 		goto unlock;
+	}
 
 	get_page(kpage);
 	page_add_new_anon_rmap(kpage, vma, addr);
@@ -199,7 +201,6 @@
 
 	err = 0;
  unlock:
-	mem_cgroup_cancel_charge(kpage, memcg);
 	mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 	unlock_page(page);
 	return err;
diff --git a/kernel/exit.c b/kernel/exit.c
index 07110c6..62c4bd4 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -54,6 +54,8 @@
 #include <linux/writeback.h>
 #include <linux/shm.h>
 
+#include "sched/tune.h"
+
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/pgtable.h>
@@ -699,6 +701,9 @@
 	}
 
 	exit_signals(tsk);  /* sets PF_EXITING */
+
+	schedtune_exit_task(tsk);
+
 	/*
 	 * tsk->flags are checked in the futex code to protect against
 	 * an exiting task cleaning up the robust pi futexes.
@@ -918,17 +923,28 @@
 		task_pid_type(p, wo->wo_type) == wo->wo_pid;
 }
 
-static int eligible_child(struct wait_opts *wo, struct task_struct *p)
+static int
+eligible_child(struct wait_opts *wo, bool ptrace, struct task_struct *p)
 {
 	if (!eligible_pid(wo, p))
 		return 0;
-	/* Wait for all children (clone and not) if __WALL is set;
-	 * otherwise, wait for clone children *only* if __WCLONE is
-	 * set; otherwise, wait for non-clone children *only*.  (Note:
-	 * A "clone" child here is one that reports to its parent
-	 * using a signal other than SIGCHLD.) */
-	if (((p->exit_signal != SIGCHLD) ^ !!(wo->wo_flags & __WCLONE))
-	    && !(wo->wo_flags & __WALL))
+
+	/*
+	 * Wait for all children (clone and not) if __WALL is set or
+	 * if it is traced by us.
+	 */
+	if (ptrace || (wo->wo_flags & __WALL))
+		return 1;
+
+	/*
+	 * Otherwise, wait for clone children *only* if __WCLONE is set;
+	 * otherwise, wait for non-clone children *only*.
+	 *
+	 * Note: a "clone" child here is one that reports to its parent
+	 * using a signal other than SIGCHLD, or a non-leader thread which
+	 * we can only see if it is traced by us.
+	 */
+	if ((p->exit_signal != SIGCHLD) ^ !!(wo->wo_flags & __WCLONE))
 		return 0;
 
 	return 1;
@@ -1301,7 +1317,7 @@
 	if (unlikely(exit_state == EXIT_DEAD))
 		return 0;
 
-	ret = eligible_child(wo, p);
+	ret = eligible_child(wo, ptrace, p);
 	if (!ret)
 		return ret;
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 7ec6e99..96891765 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -331,13 +331,14 @@
 	*stackend = STACK_END_MAGIC;	/* for overflow detection */
 }
 
-static struct task_struct *dup_task_struct(struct task_struct *orig)
+static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 {
 	struct task_struct *tsk;
 	struct thread_info *ti;
-	int node = tsk_fork_get_node(orig);
 	int err;
 
+	if (node == NUMA_NO_NODE)
+		node = tsk_fork_get_node(orig);
 	tsk = alloc_task_struct_node(node);
 	if (!tsk)
 		return NULL;
@@ -367,7 +368,7 @@
 	set_task_stack_end_magic(tsk);
 
 #ifdef CONFIG_CC_STACKPROTECTOR
-	tsk->stack_canary = get_random_int();
+	tsk->stack_canary = get_random_long();
 #endif
 
 	/*
@@ -585,7 +586,8 @@
 #endif
 }
 
-static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
+static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
+	struct user_namespace *user_ns)
 {
 	mm->mmap = NULL;
 	mm->mm_rb = RB_ROOT;
@@ -625,6 +627,7 @@
 	if (init_new_context(p, mm))
 		goto fail_nocontext;
 
+	mm->user_ns = get_user_ns(user_ns);
 	return mm;
 
 fail_nocontext:
@@ -670,7 +673,7 @@
 		return NULL;
 
 	memset(mm, 0, sizeof(*mm));
-	return mm_init(mm, current);
+	return mm_init(mm, current, current_user_ns());
 }
 
 /*
@@ -685,6 +688,7 @@
 	destroy_context(mm);
 	mmu_notifier_mm_destroy(mm);
 	check_mm(mm);
+	put_user_ns(mm->user_ns);
 	free_mm(mm);
 }
 EXPORT_SYMBOL_GPL(__mmdrop);
@@ -764,6 +768,29 @@
 EXPORT_SYMBOL(get_mm_exe_file);
 
 /**
+ * get_task_exe_file - acquire a reference to the task's executable file
+ *
+ * Returns %NULL if task's mm (if any) has no associated executable file or
+ * this is a kernel thread with borrowed mm (see the comment above get_task_mm).
+ * User must release file via fput().
+ */
+struct file *get_task_exe_file(struct task_struct *task)
+{
+	struct file *exe_file = NULL;
+	struct mm_struct *mm;
+
+	task_lock(task);
+	mm = task->mm;
+	if (mm) {
+		if (!(task->flags & PF_KTHREAD))
+			exe_file = get_mm_exe_file(mm);
+	}
+	task_unlock(task);
+	return exe_file;
+}
+EXPORT_SYMBOL(get_task_exe_file);
+
+/**
  * get_task_mm - acquire a reference to the task's mm
  *
  * Returns %NULL if the task has no mm.  Checks PF_KTHREAD (meaning
@@ -879,14 +906,12 @@
 	deactivate_mm(tsk, mm);
 
 	/*
-	 * If we're exiting normally, clear a user-space tid field if
-	 * requested.  We leave this alone when dying by signal, to leave
-	 * the value intact in a core dump, and to save the unnecessary
-	 * trouble, say, a killed vfork parent shouldn't touch this mm.
-	 * Userland only wants this done for a sys_exit.
+	 * Signal userspace if we're not exiting with a core dump
+	 * because we want to leave the value intact for debugging
+	 * purposes.
 	 */
 	if (tsk->clear_child_tid) {
-		if (!(tsk->flags & PF_SIGNALED) &&
+		if (!(tsk->signal->flags & SIGNAL_GROUP_COREDUMP) &&
 		    atomic_read(&mm->mm_users) > 1) {
 			/*
 			 * We don't check the error code - if userspace has
@@ -922,7 +947,7 @@
 
 	memcpy(mm, oldmm, sizeof(*mm));
 
-	if (!mm_init(mm, tsk))
+	if (!mm_init(mm, tsk, mm->user_ns))
 		goto fail_nomem;
 
 	err = dup_mmap(mm, oldmm);
@@ -1247,7 +1272,8 @@
 					int __user *child_tidptr,
 					struct pid *pid,
 					int trace,
-					unsigned long tls)
+					unsigned long tls,
+					int node)
 {
 	int retval;
 	struct task_struct *p;
@@ -1300,7 +1326,7 @@
 		goto fork_out;
 
 	retval = -ENOMEM;
-	p = dup_task_struct(current);
+	p = dup_task_struct(current, node);
 	if (!p)
 		goto fork_out;
 
@@ -1370,7 +1396,6 @@
 	p->real_start_time = ktime_get_boot_ns();
 	p->io_context = NULL;
 	p->audit_context = NULL;
-	threadgroup_change_begin(current);
 	cgroup_fork(p);
 #ifdef CONFIG_NUMA
 	p->mempolicy = mpol_dup(p->mempolicy);
@@ -1522,6 +1547,7 @@
 	INIT_LIST_HEAD(&p->thread_group);
 	p->task_works = NULL;
 
+	threadgroup_change_begin(current);
 	/*
 	 * Ensure that the cgroup subsystem policies allow the new process to be
 	 * forked. It should be noted the the new process's css_set can be changed
@@ -1565,11 +1591,13 @@
 	*/
 	recalc_sigpending();
 	if (signal_pending(current)) {
-		spin_unlock(&current->sighand->siglock);
-		write_unlock_irq(&tasklist_lock);
 		retval = -ERESTARTNOINTR;
 		goto bad_fork_cancel_cgroup;
 	}
+	if (unlikely(!(ns_of_pid(pid)->nr_hashed & PIDNS_HASH_ADDING))) {
+		retval = -ENOMEM;
+		goto bad_fork_cancel_cgroup;
+	}
 
 	if (likely(p->pid)) {
 		ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
@@ -1620,8 +1648,11 @@
 	return p;
 
 bad_fork_cancel_cgroup:
+	spin_unlock(&current->sighand->siglock);
+	write_unlock_irq(&tasklist_lock);
 	cgroup_cancel_fork(p, cgrp_ss_priv);
 bad_fork_free_pid:
+	threadgroup_change_end(current);
 	if (pid != &init_struct_pid)
 		free_pid(pid);
 bad_fork_cleanup_io:
@@ -1652,7 +1683,6 @@
 	mpol_put(p->mempolicy);
 bad_fork_cleanup_threadgroup_lock:
 #endif
-	threadgroup_change_end(current);
 	delayacct_tsk_free(p);
 bad_fork_cleanup_count:
 	atomic_dec(&p->cred->user->processes);
@@ -1676,7 +1706,8 @@
 struct task_struct *fork_idle(int cpu)
 {
 	struct task_struct *task;
-	task = copy_process(CLONE_VM, 0, 0, NULL, &init_struct_pid, 0, 0);
+	task = copy_process(CLONE_VM, 0, 0, NULL, &init_struct_pid, 0, 0,
+			    cpu_to_node(cpu));
 	if (!IS_ERR(task)) {
 		init_idle_pids(task->pids);
 		init_idle(task, cpu);
@@ -1721,7 +1752,7 @@
 	}
 
 	p = copy_process(clone_flags, stack_start, stack_size,
-			 child_tidptr, NULL, trace, tls);
+			 child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
 	/*
 	 * Do this prior waking up the new thread - the thread pointer
 	 * might get invalid after that point, if the thread exits quickly.
diff --git a/kernel/futex.c b/kernel/futex.c
index 9d8163a..3057dab 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -2690,7 +2690,6 @@
 {
 	struct hrtimer_sleeper timeout, *to = NULL;
 	struct rt_mutex_waiter rt_waiter;
-	struct rt_mutex *pi_mutex = NULL;
 	struct futex_hash_bucket *hb;
 	union futex_key key2 = FUTEX_KEY_INIT;
 	struct futex_q q = futex_q_init;
@@ -2774,6 +2773,8 @@
 		if (q.pi_state && (q.pi_state->owner != current)) {
 			spin_lock(q.lock_ptr);
 			ret = fixup_pi_state_owner(uaddr2, &q, current);
+			if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current)
+				rt_mutex_unlock(&q.pi_state->pi_mutex);
 			/*
 			 * Drop the reference to the pi state which
 			 * the requeue_pi() code acquired for us.
@@ -2782,6 +2783,8 @@
 			spin_unlock(q.lock_ptr);
 		}
 	} else {
+		struct rt_mutex *pi_mutex;
+
 		/*
 		 * We have been woken up by futex_unlock_pi(), a timeout, or a
 		 * signal.  futex_unlock_pi() will not destroy the lock_ptr nor
@@ -2805,18 +2808,19 @@
 		if (res)
 			ret = (res < 0) ? res : 0;
 
+		/*
+		 * If fixup_pi_state_owner() faulted and was unable to handle
+		 * the fault, unlock the rt_mutex and return the fault to
+		 * userspace.
+		 */
+		if (ret && rt_mutex_owner(pi_mutex) == current)
+			rt_mutex_unlock(pi_mutex);
+
 		/* Unqueue and drop the lock. */
 		unqueue_me_pi(&q);
 	}
 
-	/*
-	 * If fixup_pi_state_owner() faulted and was unable to handle the
-	 * fault, unlock the rt_mutex and return the fault to userspace.
-	 */
-	if (ret == -EFAULT) {
-		if (pi_mutex && rt_mutex_owner(pi_mutex) == current)
-			rt_mutex_unlock(pi_mutex);
-	} else if (ret == -EINTR) {
+	if (ret == -EINTR) {
 		/*
 		 * We've already been requeued, but cannot restart by calling
 		 * futex_lock_pi() directly. We could restart this syscall, but
@@ -3199,4 +3203,4 @@
 
 	return 0;
 }
-__initcall(futex_init);
+core_initcall(futex_init);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 1520645..e4453d9 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -810,8 +810,8 @@
 	if (!desc)
 		return;
 
-	__irq_do_set_handler(desc, handle, 1, NULL);
 	desc->irq_common_data.handler_data = data;
+	__irq_do_set_handler(desc, handle, 1, NULL);
 
 	irq_put_desc_busunlock(desc, flags);
 }
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
index abd286a..a4775f3 100644
--- a/kernel/irq/generic-chip.c
+++ b/kernel/irq/generic-chip.c
@@ -411,8 +411,29 @@
 }
 EXPORT_SYMBOL_GPL(irq_map_generic_chip);
 
+static void irq_unmap_generic_chip(struct irq_domain *d, unsigned int virq)
+{
+	struct irq_data *data = irq_domain_get_irq_data(d, virq);
+	struct irq_domain_chip_generic *dgc = d->gc;
+	unsigned int hw_irq = data->hwirq;
+	struct irq_chip_generic *gc;
+	int irq_idx;
+
+	gc = irq_get_domain_generic_chip(d, hw_irq);
+	if (!gc)
+		return;
+
+	irq_idx = hw_irq % dgc->irqs_per_chip;
+
+	clear_bit(irq_idx, &gc->installed);
+	irq_domain_set_info(d, virq, hw_irq, &no_irq_chip, NULL, NULL, NULL,
+			    NULL);
+
+}
+
 struct irq_domain_ops irq_generic_chip_ops = {
 	.map	= irq_map_generic_chip,
+	.unmap  = irq_unmap_generic_chip,
 	.xlate	= irq_domain_xlate_onetwocell,
 };
 EXPORT_SYMBOL_GPL(irq_generic_chip_ops);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 6ead200..a079ed1 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1287,8 +1287,10 @@
 			ret = __irq_set_trigger(desc,
 						new->flags & IRQF_TRIGGER_MASK);
 
-			if (ret)
+			if (ret) {
+				irq_release_resources(desc);
 				goto out_mask;
+			}
 		}
 
 		desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 6b0c0b7..cd60090 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -268,7 +268,7 @@
 	struct msi_domain_ops *ops = info->ops;
 	msi_alloc_info_t arg;
 	struct msi_desc *desc;
-	int i, ret, virq = -1;
+	int i, ret, virq;
 
 	ret = ops->msi_check(domain, info, dev);
 	if (ret == 0)
@@ -278,12 +278,8 @@
 
 	for_each_msi_entry(desc, dev) {
 		ops->set_desc(&arg, desc);
-		if (info->flags & MSI_FLAG_IDENTITY_MAP)
-			virq = (int)ops->get_hwirq(info, &arg);
-		else
-			virq = -1;
 
-		virq = __irq_domain_alloc_irqs(domain, virq, desc->nvec_used,
+		virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used,
 					       dev_to_node(dev), &arg, false);
 		if (virq < 0) {
 			ret = -ENOSPC;
@@ -302,11 +298,23 @@
 		ops->msi_finish(&arg, 0);
 
 	for_each_msi_entry(desc, dev) {
+		virq = desc->irq;
 		if (desc->nvec_used == 1)
 			dev_dbg(dev, "irq %d for MSI\n", virq);
 		else
 			dev_dbg(dev, "irq [%d-%d] for MSI\n",
 				virq, virq + desc->nvec_used - 1);
+		/*
+		 * This flag is set by the PCI layer as we need to activate
+		 * the MSI entries before the PCI layer enables MSI in the
+		 * card. Otherwise the card latches a random msi message.
+		 */
+		if (info->flags & MSI_FLAG_ACTIVATE_EARLY) {
+			struct irq_data *irq_data;
+
+			irq_data = irq_domain_get_irq_data(domain, desc->irq);
+			irq_domain_activate_irq(irq_data);
+		}
 	}
 
 	return 0;
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 05254ee..453ec42 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -58,13 +58,36 @@
 
 void static_key_slow_inc(struct static_key *key)
 {
+	int v, v1;
+
 	STATIC_KEY_CHECK_USE();
-	if (atomic_inc_not_zero(&key->enabled))
-		return;
+
+	/*
+	 * Careful if we get concurrent static_key_slow_inc() calls;
+	 * later calls must wait for the first one to _finish_ the
+	 * jump_label_update() process.  At the same time, however,
+	 * the jump_label_update() call below wants to see
+	 * static_key_enabled(&key) for jumps to be updated properly.
+	 *
+	 * So give a special meaning to negative key->enabled: it sends
+	 * static_key_slow_inc() down the slow path, and it is non-zero
+	 * so it counts as "enabled" in jump_label_update().  Note that
+	 * atomic_inc_unless_negative() checks >= 0, so roll our own.
+	 */
+	for (v = atomic_read(&key->enabled); v > 0; v = v1) {
+		v1 = atomic_cmpxchg(&key->enabled, v, v + 1);
+		if (likely(v1 == v))
+			return;
+	}
 
 	jump_label_lock();
-	if (atomic_inc_return(&key->enabled) == 1)
+	if (atomic_read(&key->enabled) == 0) {
+		atomic_set(&key->enabled, -1);
 		jump_label_update(key);
+		atomic_set(&key->enabled, 1);
+	} else {
+		atomic_inc(&key->enabled);
+	}
 	jump_label_unlock();
 }
 EXPORT_SYMBOL_GPL(static_key_slow_inc);
@@ -72,6 +95,13 @@
 static void __static_key_slow_dec(struct static_key *key,
 		unsigned long rate_limit, struct delayed_work *work)
 {
+	/*
+	 * The negative count check is valid even when a negative
+	 * key->enabled is in use by static_key_slow_inc(); a
+	 * __static_key_slow_dec() before the first static_key_slow_inc()
+	 * returns is unbalanced, because all other static_key_slow_inc()
+	 * instances block while the update is in progress.
+	 */
 	if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex)) {
 		WARN(atomic_read(&key->enabled) < 0,
 		     "jump label: negative count!\n");
@@ -108,6 +138,13 @@
 }
 EXPORT_SYMBOL_GPL(static_key_slow_dec_deferred);
 
+void static_key_deferred_flush(struct static_key_deferred *key)
+{
+	STATIC_KEY_CHECK_USE();
+	flush_delayed_work(&key->work);
+}
+EXPORT_SYMBOL_GPL(static_key_deferred_flush);
+
 void jump_label_rate_limit(struct static_key_deferred *key,
 		unsigned long rl)
 {
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index b70ada0..6030efd 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -934,7 +934,10 @@
 	return 0;
 out:
 	vfree(pi->sechdrs);
+	pi->sechdrs = NULL;
+
 	vfree(pi->purgatory_buf);
+	pi->purgatory_buf = NULL;
 	return ret;
 }
 
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d10ab6b..6957635 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -563,7 +563,7 @@
 }
 
 /* Wait for completing optimization and unoptimization */
-static void wait_for_kprobe_optimizer(void)
+void wait_for_kprobe_optimizer(void)
 {
 	mutex_lock(&kprobe_mutex);
 
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 9ff173d..698b8de 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -18,6 +18,7 @@
 #include <linux/freezer.h>
 #include <linux/ptrace.h>
 #include <linux/uaccess.h>
+#include <linux/cgroup.h>
 #include <trace/events/sched.h>
 
 static DEFINE_SPINLOCK(kthread_create_lock);
@@ -205,6 +206,7 @@
 	ret = -EINTR;
 
 	if (!test_bit(KTHREAD_SHOULD_STOP, &self.flags)) {
+		cgroup_kthread_ready();
 		__kthread_parkme(&self);
 		ret = threadfn(data);
 	}
@@ -510,6 +512,7 @@
 	set_mems_allowed(node_states[N_MEMORY]);
 
 	current->flags |= PF_NOFREEZE;
+	cgroup_init_kthreadd();
 
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -601,6 +604,19 @@
 }
 EXPORT_SYMBOL_GPL(kthread_worker_fn);
 
+/*
+ * Returns true when the work could not be queued at the moment.
+ * It happens when it is already pending in a worker list
+ * or when it is being cancelled.
+ */
+static inline bool queuing_blocked(struct kthread_worker *worker,
+				   struct kthread_work *work)
+{
+	lockdep_assert_held(&worker->lock);
+
+	return !list_empty(&work->node) || work->canceling;
+}
+
 /* insert @work before @pos in @worker */
 static void insert_kthread_work(struct kthread_worker *worker,
 			       struct kthread_work *work,
@@ -630,7 +646,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&worker->lock, flags);
-	if (list_empty(&work->node)) {
+	if (!queuing_blocked(worker, work)) {
 		insert_kthread_work(worker, work, &worker->work_list);
 		ret = true;
 	}
@@ -691,6 +707,87 @@
 }
 EXPORT_SYMBOL_GPL(flush_kthread_work);
 
+/*
+ * This function removes the work from the worker queue. Also it makes sure
+ * that it won't get queued later via the delayed work's timer.
+ *
+ * The work might still be in use when this function finishes. See the
+ * current_work proceed by the worker.
+ *
+ * Return: %true if @work was pending and successfully canceled,
+ *	%false if @work was not pending
+ */
+static bool __kthread_cancel_work(struct kthread_work *work,
+				  unsigned long *flags)
+{
+	/*
+	 * Try to remove the work from a worker list. It might either
+	 * be from worker->work_list or from worker->delayed_work_list.
+	 */
+	if (!list_empty(&work->node)) {
+		list_del_init(&work->node);
+		return true;
+	}
+
+	return false;
+}
+
+static bool __kthread_cancel_work_sync(struct kthread_work *work)
+{
+	struct kthread_worker *worker = work->worker;
+	unsigned long flags;
+	int ret = false;
+
+	if (!worker)
+		goto out;
+
+	spin_lock_irqsave(&worker->lock, flags);
+	/* Work must not be used with >1 worker, see kthread_queue_work(). */
+	WARN_ON_ONCE(work->worker != worker);
+
+	ret = __kthread_cancel_work(work, &flags);
+
+	if (worker->current_work != work)
+		goto out_fast;
+
+	/*
+	 * The work is in progress and we need to wait with the lock released.
+	 * In the meantime, block any queuing by setting the canceling counter.
+	 */
+	work->canceling++;
+	spin_unlock_irqrestore(&worker->lock, flags);
+	flush_kthread_work(work);
+	spin_lock_irqsave(&worker->lock, flags);
+	work->canceling--;
+
+out_fast:
+	spin_unlock_irqrestore(&worker->lock, flags);
+out:
+	return ret;
+}
+
+/**
+ * kthread_cancel_work_sync - cancel a kthread work and wait for it to finish
+ * @work: the kthread work to cancel
+ *
+ * Cancel @work and wait for its execution to finish.  This function
+ * can be used even if the work re-queues itself. On return from this
+ * function, @work is guaranteed to be not pending or executing on any CPU.
+ *
+ * kthread_cancel_work_sync(&delayed_work->work) must not be used for
+ * delayed_work's. Use kthread_cancel_delayed_work_sync() instead.
+ *
+ * The caller must ensure that the worker on which @work was last
+ * queued can't be destroyed before this function returns.
+ *
+ * Return: %true if @work was pending, %false otherwise.
+ */
+bool kthread_cancel_work_sync(struct kthread_work *work)
+{
+	return __kthread_cancel_work_sync(work);
+}
+EXPORT_SYMBOL_GPL(kthread_cancel_work_sync);
+
 /**
  * flush_kthread_worker - flush all current works on a kthread_worker
  * @worker: worker to flush
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index 0551c21..89350f9 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -486,9 +486,6 @@
 	if (!hold_ctx)
 		return 0;
 
-	if (unlikely(ctx == hold_ctx))
-		return -EALREADY;
-
 	if (ctx->stamp - hold_ctx->stamp <= LONG_MAX &&
 	    (ctx->stamp != hold_ctx->stamp || ctx > hold_ctx)) {
 #ifdef CONFIG_DEBUG_MUTEXES
@@ -514,6 +511,12 @@
 	unsigned long flags;
 	int ret;
 
+	if (use_ww_ctx) {
+		struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
+		if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
+			return -EALREADY;
+	}
+
 	preempt_disable();
 	mutex_acquire_nest(&lock->dep_map, subclass, 0, nest_lock, ip);
 
diff --git a/kernel/locking/percpu-rwsem.c b/kernel/locking/percpu-rwsem.c
index f231e0b..ce18259 100644
--- a/kernel/locking/percpu-rwsem.c
+++ b/kernel/locking/percpu-rwsem.c
@@ -8,151 +8,186 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 
-int __percpu_init_rwsem(struct percpu_rw_semaphore *brw,
+int __percpu_init_rwsem(struct percpu_rw_semaphore *sem,
 			const char *name, struct lock_class_key *rwsem_key)
 {
-	brw->fast_read_ctr = alloc_percpu(int);
-	if (unlikely(!brw->fast_read_ctr))
+	sem->read_count = alloc_percpu(int);
+	if (unlikely(!sem->read_count))
 		return -ENOMEM;
 
 	/* ->rw_sem represents the whole percpu_rw_semaphore for lockdep */
-	__init_rwsem(&brw->rw_sem, name, rwsem_key);
-	rcu_sync_init(&brw->rss, RCU_SCHED_SYNC);
-	atomic_set(&brw->slow_read_ctr, 0);
-	init_waitqueue_head(&brw->write_waitq);
+	rcu_sync_init(&sem->rss, RCU_SCHED_SYNC);
+	__init_rwsem(&sem->rw_sem, name, rwsem_key);
+	init_waitqueue_head(&sem->writer);
+	sem->readers_block = 0;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(__percpu_init_rwsem);
 
-void percpu_free_rwsem(struct percpu_rw_semaphore *brw)
+void percpu_free_rwsem(struct percpu_rw_semaphore *sem)
 {
 	/*
 	 * XXX: temporary kludge. The error path in alloc_super()
 	 * assumes that percpu_free_rwsem() is safe after kzalloc().
 	 */
-	if (!brw->fast_read_ctr)
+	if (!sem->read_count)
 		return;
 
-	rcu_sync_dtor(&brw->rss);
-	free_percpu(brw->fast_read_ctr);
-	brw->fast_read_ctr = NULL; /* catch use after free bugs */
+	rcu_sync_dtor(&sem->rss);
+	free_percpu(sem->read_count);
+	sem->read_count = NULL; /* catch use after free bugs */
 }
+EXPORT_SYMBOL_GPL(percpu_free_rwsem);
 
-/*
- * This is the fast-path for down_read/up_read. If it succeeds we rely
- * on the barriers provided by rcu_sync_enter/exit; see the comments in
- * percpu_down_write() and percpu_up_write().
- *
- * If this helper fails the callers rely on the normal rw_semaphore and
- * atomic_dec_and_test(), so in this case we have the necessary barriers.
- */
-static bool update_fast_ctr(struct percpu_rw_semaphore *brw, unsigned int val)
-{
-	bool success;
-
-	preempt_disable();
-	success = rcu_sync_is_idle(&brw->rss);
-	if (likely(success))
-		__this_cpu_add(*brw->fast_read_ctr, val);
-	preempt_enable();
-
-	return success;
-}
-
-/*
- * Like the normal down_read() this is not recursive, the writer can
- * come after the first percpu_down_read() and create the deadlock.
- *
- * Note: returns with lock_is_held(brw->rw_sem) == T for lockdep,
- * percpu_up_read() does rwsem_release(). This pairs with the usage
- * of ->rw_sem in percpu_down/up_write().
- */
-void percpu_down_read(struct percpu_rw_semaphore *brw)
-{
-	might_sleep();
-	rwsem_acquire_read(&brw->rw_sem.dep_map, 0, 0, _RET_IP_);
-
-	if (likely(update_fast_ctr(brw, +1)))
-		return;
-
-	/* Avoid rwsem_acquire_read() and rwsem_release() */
-	__down_read(&brw->rw_sem);
-	atomic_inc(&brw->slow_read_ctr);
-	__up_read(&brw->rw_sem);
-}
-EXPORT_SYMBOL_GPL(percpu_down_read);
-
-int percpu_down_read_trylock(struct percpu_rw_semaphore *brw)
-{
-	if (unlikely(!update_fast_ctr(brw, +1))) {
-		if (!__down_read_trylock(&brw->rw_sem))
-			return 0;
-		atomic_inc(&brw->slow_read_ctr);
-		__up_read(&brw->rw_sem);
-	}
-
-	rwsem_acquire_read(&brw->rw_sem.dep_map, 0, 1, _RET_IP_);
-	return 1;
-}
-
-void percpu_up_read(struct percpu_rw_semaphore *brw)
-{
-	rwsem_release(&brw->rw_sem.dep_map, 1, _RET_IP_);
-
-	if (likely(update_fast_ctr(brw, -1)))
-		return;
-
-	/* false-positive is possible but harmless */
-	if (atomic_dec_and_test(&brw->slow_read_ctr))
-		wake_up_all(&brw->write_waitq);
-}
-EXPORT_SYMBOL_GPL(percpu_up_read);
-
-static int clear_fast_ctr(struct percpu_rw_semaphore *brw)
-{
-	unsigned int sum = 0;
-	int cpu;
-
-	for_each_possible_cpu(cpu) {
-		sum += per_cpu(*brw->fast_read_ctr, cpu);
-		per_cpu(*brw->fast_read_ctr, cpu) = 0;
-	}
-
-	return sum;
-}
-
-void percpu_down_write(struct percpu_rw_semaphore *brw)
+int __percpu_down_read(struct percpu_rw_semaphore *sem, int try)
 {
 	/*
-	 * Make rcu_sync_is_idle() == F and thus disable the fast-path in
-	 * percpu_down_read() and percpu_up_read(), and wait for gp pass.
+	 * Due to having preemption disabled the decrement happens on
+	 * the same CPU as the increment, avoiding the
+	 * increment-on-one-CPU-and-decrement-on-another problem.
 	 *
-	 * The latter synchronises us with the preceding readers which used
-	 * the fast-past, so we can not miss the result of __this_cpu_add()
-	 * or anything else inside their criticial sections.
+	 * If the reader misses the writer's assignment of readers_block, then
+	 * the writer is guaranteed to see the reader's increment.
+	 *
+	 * Conversely, any readers that increment their sem->read_count after
+	 * the writer looks are guaranteed to see the readers_block value,
+	 * which in turn means that they are guaranteed to immediately
+	 * decrement their sem->read_count, so that it doesn't matter that the
+	 * writer missed them.
 	 */
-	rcu_sync_enter(&brw->rss);
 
-	/* exclude other writers, and block the new readers completely */
-	down_write(&brw->rw_sem);
+	smp_mb(); /* A matches D */
 
-	/* nobody can use fast_read_ctr, move its sum into slow_read_ctr */
-	atomic_add(clear_fast_ctr(brw), &brw->slow_read_ctr);
+	/*
+	 * If !readers_block the critical section starts here, matched by the
+	 * release in percpu_up_write().
+	 */
+	if (likely(!smp_load_acquire(&sem->readers_block)))
+		return 1;
 
-	/* wait for all readers to complete their percpu_up_read() */
-	wait_event(brw->write_waitq, !atomic_read(&brw->slow_read_ctr));
+	/*
+	 * Per the above comment; we still have preemption disabled and
+	 * will thus decrement on the same CPU as we incremented.
+	 */
+	__percpu_up_read(sem);
+
+	if (try)
+		return 0;
+
+	/*
+	 * We either call schedule() in the wait, or we'll fall through
+	 * and reschedule on the preempt_enable() in percpu_down_read().
+	 */
+	preempt_enable_no_resched();
+
+	/*
+	 * Avoid lockdep for the down/up_read() we already have them.
+	 */
+	__down_read(&sem->rw_sem);
+	this_cpu_inc(*sem->read_count);
+	__up_read(&sem->rw_sem);
+
+	preempt_disable();
+	return 1;
+}
+EXPORT_SYMBOL_GPL(__percpu_down_read);
+
+void __percpu_up_read(struct percpu_rw_semaphore *sem)
+{
+	smp_mb(); /* B matches C */
+	/*
+	 * In other words, if they see our decrement (presumably to aggregate
+	 * zero, as that is the only time it matters) they will also see our
+	 * critical section.
+	 */
+	__this_cpu_dec(*sem->read_count);
+
+	/* Prod writer to recheck readers_active */
+	wake_up(&sem->writer);
+}
+EXPORT_SYMBOL_GPL(__percpu_up_read);
+
+#define per_cpu_sum(var)						\
+({									\
+	typeof(var) __sum = 0;						\
+	int cpu;							\
+	compiletime_assert_atomic_type(__sum);				\
+	for_each_possible_cpu(cpu)					\
+		__sum += per_cpu(var, cpu);				\
+	__sum;								\
+})
+
+/*
+ * Return true if the modular sum of the sem->read_count per-CPU variable is
+ * zero.  If this sum is zero, then it is stable due to the fact that if any
+ * newly arriving readers increment a given counter, they will immediately
+ * decrement that same counter.
+ */
+static bool readers_active_check(struct percpu_rw_semaphore *sem)
+{
+	if (per_cpu_sum(*sem->read_count) != 0)
+		return false;
+
+	/*
+	 * If we observed the decrement; ensure we see the entire critical
+	 * section.
+	 */
+
+	smp_mb(); /* C matches B */
+
+	return true;
+}
+
+void percpu_down_write(struct percpu_rw_semaphore *sem)
+{
+	/* Notify readers to take the slow path. */
+	rcu_sync_enter(&sem->rss);
+
+	down_write(&sem->rw_sem);
+
+	/*
+	 * Notify new readers to block; up until now, and thus throughout the
+	 * longish rcu_sync_enter() above, new readers could still come in.
+	 */
+	WRITE_ONCE(sem->readers_block, 1);
+
+	smp_mb(); /* D matches A */
+
+	/*
+	 * If they don't see our writer of readers_block, then we are
+	 * guaranteed to see their sem->read_count increment, and therefore
+	 * will wait for them.
+	 */
+
+	/* Wait for all now active readers to complete. */
+	wait_event(sem->writer, readers_active_check(sem));
 }
 EXPORT_SYMBOL_GPL(percpu_down_write);
 
-void percpu_up_write(struct percpu_rw_semaphore *brw)
+void percpu_up_write(struct percpu_rw_semaphore *sem)
 {
-	/* release the lock, but the readers can't use the fast-path */
-	up_write(&brw->rw_sem);
 	/*
-	 * Enable the fast-path in percpu_down_read() and percpu_up_read()
-	 * but only after another gp pass; this adds the necessary barrier
-	 * to ensure the reader can't miss the changes done by us.
+	 * Signal the writer is done, no fast path yet.
+	 *
+	 * One reason that we cannot just immediately flip to readers_fast is
+	 * that new readers might fail to see the results of this writer's
+	 * critical section.
+	 *
+	 * Therefore we force it through the slow path which guarantees an
+	 * acquire and thereby guarantees the critical section's consistency.
 	 */
-	rcu_sync_exit(&brw->rss);
+	smp_store_release(&sem->readers_block, 0);
+
+	/*
+	 * Release the write lock, this will allow readers back in the game.
+	 */
+	up_write(&sem->rw_sem);
+
+	/*
+	 * Once this completes (at least one RCU-sched grace period hence) the
+	 * reader fast path will be available again. Safe to use outside the
+	 * exclusive write lock because its counting.
+	 */
+	rcu_sync_exit(&sem->rss);
 }
 EXPORT_SYMBOL_GPL(percpu_up_write);
diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
index 87e9ce6a..8173bc7 100644
--- a/kernel/locking/qspinlock.c
+++ b/kernel/locking/qspinlock.c
@@ -255,6 +255,66 @@
 #define queued_spin_lock_slowpath	native_queued_spin_lock_slowpath
 #endif
 
+/*
+ * queued_spin_lock_slowpath() can (load-)ACQUIRE the lock before
+ * issuing an _unordered_ store to set _Q_LOCKED_VAL.
+ *
+ * This means that the store can be delayed, but no later than the
+ * store-release from the unlock. This means that simply observing
+ * _Q_LOCKED_VAL is not sufficient to determine if the lock is acquired.
+ *
+ * There are two paths that can issue the unordered store:
+ *
+ *  (1) clear_pending_set_locked():	*,1,0 -> *,0,1
+ *
+ *  (2) set_locked():			t,0,0 -> t,0,1 ; t != 0
+ *      atomic_cmpxchg_relaxed():	t,0,0 -> 0,0,1
+ *
+ * However, in both cases we have other !0 state we've set before to queue
+ * ourseves:
+ *
+ * For (1) we have the atomic_cmpxchg_acquire() that set _Q_PENDING_VAL, our
+ * load is constrained by that ACQUIRE to not pass before that, and thus must
+ * observe the store.
+ *
+ * For (2) we have a more intersting scenario. We enqueue ourselves using
+ * xchg_tail(), which ends up being a RELEASE. This in itself is not
+ * sufficient, however that is followed by an smp_cond_acquire() on the same
+ * word, giving a RELEASE->ACQUIRE ordering. This again constrains our load and
+ * guarantees we must observe that store.
+ *
+ * Therefore both cases have other !0 state that is observable before the
+ * unordered locked byte store comes through. This means we can use that to
+ * wait for the lock store, and then wait for an unlock.
+ */
+#ifndef queued_spin_unlock_wait
+void queued_spin_unlock_wait(struct qspinlock *lock)
+{
+	u32 val;
+
+	for (;;) {
+		val = atomic_read(&lock->val);
+
+		if (!val) /* not locked, we're done */
+			goto done;
+
+		if (val & _Q_LOCKED_MASK) /* locked, go wait for unlock */
+			break;
+
+		/* not locked, but pending, wait until we observe the lock */
+		cpu_relax();
+	}
+
+	/* any unlock is good */
+	while (atomic_read(&lock->val) & _Q_LOCKED_MASK)
+		cpu_relax();
+
+done:
+	smp_rmb(); /* CTRL + RMB -> ACQUIRE */
+}
+EXPORT_SYMBOL(queued_spin_unlock_wait);
+#endif
+
 #endif /* _GEN_PV_LOCK_SLOWPATH */
 
 /**
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 8251e75..b066724d 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -65,8 +65,72 @@
 
 static void fixup_rt_mutex_waiters(struct rt_mutex *lock)
 {
-	if (!rt_mutex_has_waiters(lock))
-		clear_rt_mutex_waiters(lock);
+	unsigned long owner, *p = (unsigned long *) &lock->owner;
+
+	if (rt_mutex_has_waiters(lock))
+		return;
+
+	/*
+	 * The rbtree has no waiters enqueued, now make sure that the
+	 * lock->owner still has the waiters bit set, otherwise the
+	 * following can happen:
+	 *
+	 * CPU 0	CPU 1		CPU2
+	 * l->owner=T1
+	 *		rt_mutex_lock(l)
+	 *		lock(l->lock)
+	 *		l->owner = T1 | HAS_WAITERS;
+	 *		enqueue(T2)
+	 *		boost()
+	 *		  unlock(l->lock)
+	 *		block()
+	 *
+	 *				rt_mutex_lock(l)
+	 *				lock(l->lock)
+	 *				l->owner = T1 | HAS_WAITERS;
+	 *				enqueue(T3)
+	 *				boost()
+	 *				  unlock(l->lock)
+	 *				block()
+	 *		signal(->T2)	signal(->T3)
+	 *		lock(l->lock)
+	 *		dequeue(T2)
+	 *		deboost()
+	 *		  unlock(l->lock)
+	 *				lock(l->lock)
+	 *				dequeue(T3)
+	 *				 ==> wait list is empty
+	 *				deboost()
+	 *				 unlock(l->lock)
+	 *		lock(l->lock)
+	 *		fixup_rt_mutex_waiters()
+	 *		  if (wait_list_empty(l) {
+	 *		    l->owner = owner
+	 *		    owner = l->owner & ~HAS_WAITERS;
+	 *		      ==> l->owner = T1
+	 *		  }
+	 *				lock(l->lock)
+	 * rt_mutex_unlock(l)		fixup_rt_mutex_waiters()
+	 *				  if (wait_list_empty(l) {
+	 *				    owner = l->owner & ~HAS_WAITERS;
+	 * cmpxchg(l->owner, T1, NULL)
+	 *  ===> Success (l->owner = NULL)
+	 *
+	 *				    l->owner = owner
+	 *				      ==> l->owner = T1
+	 *				  }
+	 *
+	 * With the check for the waiter bit in place T3 on CPU2 will not
+	 * overwrite. All tasks fiddling with the waiters bit are
+	 * serialized by l->lock, so nothing else can modify the waiters
+	 * bit. If the bit is set then nothing can change l->owner either
+	 * so the simple RMW is safe. The cmpxchg() will simply fail if it
+	 * happens in the middle of the RMW because the waiters bit is
+	 * still set.
+	 */
+	owner = READ_ONCE(*p);
+	if (owner & RT_MUTEX_HAS_WAITERS)
+		WRITE_ONCE(*p, owner & ~RT_MUTEX_HAS_WAITERS);
 }
 
 /*
diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h
index 4f5f83c..e317e1c 100644
--- a/kernel/locking/rtmutex_common.h
+++ b/kernel/locking/rtmutex_common.h
@@ -75,8 +75,9 @@
 
 static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
 {
-	return (struct task_struct *)
-		((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL);
+	unsigned long owner = (unsigned long) READ_ONCE(lock->owner);
+
+	return (struct task_struct *) (owner & ~RT_MUTEX_OWNER_MASKALL);
 }
 
 /*
diff --git a/kernel/membarrier.c b/kernel/membarrier.c
index 536c727..9f9284f 100644
--- a/kernel/membarrier.c
+++ b/kernel/membarrier.c
@@ -16,6 +16,7 @@
 
 #include <linux/syscalls.h>
 #include <linux/membarrier.h>
+#include <linux/tick.h>
 
 /*
  * Bitmask made from a "or" of all commands within enum membarrier_cmd,
@@ -51,6 +52,9 @@
  */
 SYSCALL_DEFINE2(membarrier, int, cmd, int, flags)
 {
+	/* MEMBARRIER_CMD_SHARED is not compatible with nohz_full. */
+	if (tick_nohz_full_enabled())
+		return -ENOSYS;
 	if (unlikely(flags))
 		return -EINVAL;
 	switch (cmd) {
diff --git a/kernel/memremap.c b/kernel/memremap.c
index 25ced16..f719c92 100644
--- a/kernel/memremap.c
+++ b/kernel/memremap.c
@@ -159,7 +159,9 @@
 	struct page_map *page_map = res;
 
 	/* pages are dead and unused, undo the arch mapping */
+	mem_hotplug_begin();
 	arch_remove_memory(page_map->res.start, resource_size(&page_map->res));
+	mem_hotplug_done();
 }
 
 void *devm_memremap_pages(struct device *dev, struct resource *res)
@@ -189,7 +191,9 @@
 	if (nid < 0)
 		nid = numa_mem_id();
 
+	mem_hotplug_begin();
 	error = arch_add_memory(nid, res->start, resource_size(res), true);
+	mem_hotplug_done();
 	if (error) {
 		devres_free(page_map);
 		return ERR_PTR(error);
diff --git a/kernel/module.c b/kernel/module.c
index 0e5c711..b14a4f3 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2606,13 +2606,18 @@
 #endif
 
 #ifdef CONFIG_MODULE_SIG
-static int module_sig_check(struct load_info *info)
+static int module_sig_check(struct load_info *info, int flags)
 {
 	int err = -ENOKEY;
 	const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
 	const void *mod = info->hdr;
 
-	if (info->len > markerlen &&
+	/*
+	 * Require flags == 0, as a module with version information
+	 * removed is no longer the module that was signed
+	 */
+	if (flags == 0 &&
+	    info->len > markerlen &&
 	    memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
 		/* We truncate the module to discard the signature */
 		info->len -= markerlen;
@@ -2631,7 +2636,7 @@
 	return err;
 }
 #else /* !CONFIG_MODULE_SIG */
-static int module_sig_check(struct load_info *info)
+static int module_sig_check(struct load_info *info, int flags)
 {
 	return 0;
 }
@@ -3444,7 +3449,7 @@
 	long err;
 	char *after_dashes;
 
-	err = module_sig_check(info);
+	err = module_sig_check(info, flags);
 	if (err)
 		goto free_copy;
 
diff --git a/kernel/padata.c b/kernel/padata.c
index b38bea9..ecc7b3f 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -189,19 +189,20 @@
 
 	reorder = &next_queue->reorder;
 
+	spin_lock(&reorder->lock);
 	if (!list_empty(&reorder->list)) {
 		padata = list_entry(reorder->list.next,
 				    struct padata_priv, list);
 
-		spin_lock(&reorder->lock);
 		list_del_init(&padata->list);
 		atomic_dec(&pd->reorder_objects);
-		spin_unlock(&reorder->lock);
 
 		pd->processed++;
 
+		spin_unlock(&reorder->lock);
 		goto out;
 	}
+	spin_unlock(&reorder->lock);
 
 	if (__this_cpu_read(pd->pqueue->cpu_index) == next_queue->cpu_index) {
 		padata = ERR_PTR(-ENODATA);
@@ -356,7 +357,7 @@
 
 	cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_online_mask);
 	if (!alloc_cpumask_var(&pd->cpumask.cbcpu, GFP_KERNEL)) {
-		free_cpumask_var(pd->cpumask.cbcpu);
+		free_cpumask_var(pd->cpumask.pcpu);
 		return -ENOMEM;
 	}
 
diff --git a/kernel/panic.c b/kernel/panic.c
index 223564d..1d07cf9 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -28,9 +28,6 @@
 #define PANIC_TIMER_STEP 100
 #define PANIC_BLINK_SPD 18
 
-/* Machine specific panic information string */
-char *mach_panic_string;
-
 int panic_on_oops = CONFIG_PANIC_ON_OOPS_VALUE;
 static unsigned long tainted_mask;
 static int pause_on_oops;
@@ -170,7 +167,7 @@
 		 * Delay timeout seconds before rebooting the machine.
 		 * We can't use the "normal" timers since we just panicked.
 		 */
-		pr_emerg("Rebooting in %d seconds..", panic_timeout);
+		pr_emerg("Rebooting in %d seconds..\n", panic_timeout);
 
 		for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) {
 			touch_nmi_watchdog();
@@ -415,11 +412,6 @@
 void print_oops_end_marker(void)
 {
 	init_oops_id();
-
-	if (mach_panic_string)
-		printk(KERN_WARNING "Board Information: %s\n",
-		       mach_panic_string);
-
 	pr_warn("---[ end trace %016llx ]---\n", (unsigned long long)oops_id);
 }
 
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index a65ba13..567ecc8 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -255,7 +255,7 @@
 	 * if reparented.
 	 */
 	for (;;) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (pid_ns->nr_hashed == init_pids)
 			break;
 		schedule();
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index b7dd571..797f19e 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -299,12 +299,12 @@
 	save_processor_state();
 	trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, true);
 	error = swsusp_arch_suspend();
+	/* Restore control flow magically appears here */
+	restore_processor_state();
 	trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, false);
 	if (error)
 		printk(KERN_ERR "PM: Error %d creating hibernation image\n",
 			error);
-	/* Restore control flow magically appears here */
-	restore_processor_state();
 	if (!in_suspend)
 		events_check_enabled = false;
 
@@ -647,7 +647,7 @@
  */
 int hibernate(void)
 {
-	int error;
+	int error, nr_calls = 0;
 
 	if (!hibernation_available()) {
 		pr_debug("PM: Hibernation not available.\n");
@@ -662,9 +662,11 @@
 	}
 
 	pm_prepare_console();
-	error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
-	if (error)
+	error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
+	if (error) {
+		nr_calls--;
 		goto Exit;
+	}
 
 	printk(KERN_INFO "PM: Syncing filesystems ... ");
 	sys_sync();
@@ -714,7 +716,7 @@
 	/* Don't bother checking whether freezer_test_done is true */
 	freezer_test_done = false;
  Exit:
-	pm_notifier_call_chain(PM_POST_HIBERNATION);
+	__pm_notifier_call_chain(PM_POST_HIBERNATION, nr_calls, NULL);
 	pm_restore_console();
 	atomic_inc(&snapshot_device_available);
  Unlock:
@@ -740,7 +742,7 @@
  */
 static int software_resume(void)
 {
-	int error;
+	int error, nr_calls = 0;
 	unsigned int flags;
 
 	/*
@@ -827,9 +829,11 @@
 	}
 
 	pm_prepare_console();
-	error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
-	if (error)
+	error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
+	if (error) {
+		nr_calls--;
 		goto Close_Finish;
+	}
 
 	pr_debug("PM: Preparing processes for restore.\n");
 	error = freeze_processes();
@@ -855,7 +859,7 @@
 	unlock_device_hotplug();
 	thaw_processes();
  Finish:
-	pm_notifier_call_chain(PM_POST_RESTORE);
+	__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
 	pm_restore_console();
 	atomic_inc(&snapshot_device_available);
 	/* For success case, the suspend path will release the lock */
diff --git a/kernel/power/main.c b/kernel/power/main.c
index b2dd4d9..68c0eaa 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -38,12 +38,19 @@
 }
 EXPORT_SYMBOL_GPL(unregister_pm_notifier);
 
-int pm_notifier_call_chain(unsigned long val)
+int __pm_notifier_call_chain(unsigned long val, int nr_to_call, int *nr_calls)
 {
-	int ret = blocking_notifier_call_chain(&pm_chain_head, val, NULL);
+	int ret;
+
+	ret = __blocking_notifier_call_chain(&pm_chain_head, val, NULL,
+						nr_to_call, nr_calls);
 
 	return notifier_to_errno(ret);
 }
+int pm_notifier_call_chain(unsigned long val)
+{
+	return __pm_notifier_call_chain(val, -1, NULL);
+}
 
 /* If set, devices may be suspended and resumed asynchronously. */
 int pm_async_enabled = 1;
diff --git a/kernel/power/power.h b/kernel/power/power.h
index caadb56..436da5b 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -191,6 +191,8 @@
 
 #ifdef CONFIG_PM_SLEEP
 /* kernel/power/main.c */
+extern int __pm_notifier_call_chain(unsigned long val, int nr_to_call,
+				    int *nr_calls);
 extern int pm_notifier_call_chain(unsigned long val);
 #endif
 
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 3a97060..f155c62 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -765,9 +765,9 @@
  */
 static bool rtree_next_node(struct memory_bitmap *bm)
 {
-	bm->cur.node = list_entry(bm->cur.node->list.next,
-				  struct rtree_node, list);
-	if (&bm->cur.node->list != &bm->cur.zone->leaves) {
+	if (!list_is_last(&bm->cur.node->list, &bm->cur.zone->leaves)) {
+		bm->cur.node = list_entry(bm->cur.node->list.next,
+					  struct rtree_node, list);
 		bm->cur.node_pfn += BM_BITS_PER_BLOCK;
 		bm->cur.node_bit  = 0;
 		touch_softlockup_watchdog();
@@ -775,9 +775,9 @@
 	}
 
 	/* No more nodes, goto next zone */
-	bm->cur.zone = list_entry(bm->cur.zone->list.next,
+	if (!list_is_last(&bm->cur.zone->list, &bm->zones)) {
+		bm->cur.zone = list_entry(bm->cur.zone->list.next,
 				  struct mem_zone_bm_rtree, list);
-	if (&bm->cur.zone->list != &bm->zones) {
 		bm->cur.node = list_entry(bm->cur.zone->leaves.next,
 					  struct rtree_node, list);
 		bm->cur.node_pfn = 0;
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index e2e85d7..58209d8 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -26,6 +26,7 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/ftrace.h>
+#include <linux/rtc.h>
 #include <trace/events/power.h>
 #include <linux/compiler.h>
 #include <linux/moduleparam.h>
@@ -267,16 +268,18 @@
  */
 static int suspend_prepare(suspend_state_t state)
 {
-	int error;
+	int error, nr_calls = 0;
 
 	if (!sleep_state_supported(state))
 		return -EPERM;
 
 	pm_prepare_console();
 
-	error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
-	if (error)
+	error = __pm_notifier_call_chain(PM_SUSPEND_PREPARE, -1, &nr_calls);
+	if (error) {
+		nr_calls--;
 		goto Finish;
+	}
 
 	trace_suspend_resume(TPS("freeze_processes"), 0, true);
 	error = suspend_freeze_processes();
@@ -287,7 +290,7 @@
 	suspend_stats.failed_freeze++;
 	dpm_save_failed_step(SUSPEND_FREEZE);
  Finish:
-	pm_notifier_call_chain(PM_POST_SUSPEND);
+	__pm_notifier_call_chain(PM_POST_SUSPEND, nr_calls, NULL);
 	pm_restore_console();
 	return error;
 }
@@ -534,6 +537,18 @@
 	return error;
 }
 
+static void pm_suspend_marker(char *annotation)
+{
+	struct timespec ts;
+	struct rtc_time tm;
+
+	getnstimeofday(&ts);
+	rtc_time_to_tm(ts.tv_sec, &tm);
+	pr_info("PM: suspend %s %d-%02d-%02d %02d:%02d:%02d.%09lu UTC\n",
+		annotation, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+		tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
+}
+
 /**
  * pm_suspend - Externally visible function for suspending the system.
  * @state: System sleep state to enter.
@@ -548,6 +563,7 @@
 	if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
 		return -EINVAL;
 
+	pm_suspend_marker("entry");
 	error = enter_state(state);
 	if (error) {
 		suspend_stats.fail++;
@@ -555,6 +571,7 @@
 	} else {
 		suspend_stats.success++;
 	}
+	pm_suspend_marker("exit");
 	return error;
 }
 EXPORT_SYMBOL(pm_suspend);
diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c
index 084452e..bdff5ed 100644
--- a/kernel/power/suspend_test.c
+++ b/kernel/power/suspend_test.c
@@ -203,8 +203,10 @@
 
 	/* RTCs have initialized by now too ... can we use one? */
 	dev = class_find_device(rtc_class, NULL, NULL, has_wakealarm);
-	if (dev)
+	if (dev) {
 		rtc = rtc_class_open(dev_name(dev));
+		put_device(dev);
+	}
 	if (!rtc) {
 		printk(warn_no_rtc);
 		return 0;
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 526e891..35310b6 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -47,7 +47,7 @@
 static int snapshot_open(struct inode *inode, struct file *filp)
 {
 	struct snapshot_data *data;
-	int error;
+	int error, nr_calls = 0;
 
 	if (!hibernation_available())
 		return -EPERM;
@@ -74,9 +74,9 @@
 			swap_type_of(swsusp_resume_device, 0, NULL) : -1;
 		data->mode = O_RDONLY;
 		data->free_bitmaps = false;
-		error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
+		error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
 		if (error)
-			pm_notifier_call_chain(PM_POST_HIBERNATION);
+			__pm_notifier_call_chain(PM_POST_HIBERNATION, --nr_calls, NULL);
 	} else {
 		/*
 		 * Resuming.  We may need to wait for the image device to
@@ -86,13 +86,15 @@
 
 		data->swap = -1;
 		data->mode = O_WRONLY;
-		error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
+		error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
 		if (!error) {
 			error = create_basic_memory_bitmaps();
 			data->free_bitmaps = !error;
-		}
+		} else
+			nr_calls--;
+
 		if (error)
-			pm_notifier_call_chain(PM_POST_RESTORE);
+			__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
 	}
 	if (error)
 		atomic_inc(&snapshot_device_available);
diff --git a/kernel/printk/braille.c b/kernel/printk/braille.c
index 276762f..d5760c4 100644
--- a/kernel/printk/braille.c
+++ b/kernel/printk/braille.c
@@ -9,10 +9,10 @@
 
 char *_braille_console_setup(char **str, char **brl_options)
 {
-	if (!memcmp(*str, "brl,", 4)) {
+	if (!strncmp(*str, "brl,", 4)) {
 		*brl_options = "";
 		*str += 4;
-	} else if (!memcmp(str, "brl=", 4)) {
+	} else if (!strncmp(*str, "brl=", 4)) {
 		*brl_options = *str + 4;
 		*str = strchr(*brl_options, ',');
 		if (!*str)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index e7e586b..1a69815 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1440,7 +1440,7 @@
 {
 	struct console *con;
 
-	trace_console(text, len);
+	trace_console_rcuidle(text, len);
 
 	if (level >= console_loglevel && !ignore_loglevel)
 		return;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 3189e51..5e2cd10 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -28,17 +28,26 @@
 #include <linux/compat.h>
 
 
+void __ptrace_link(struct task_struct *child, struct task_struct *new_parent,
+		   const struct cred *ptracer_cred)
+{
+	BUG_ON(!list_empty(&child->ptrace_entry));
+	list_add(&child->ptrace_entry, &new_parent->ptraced);
+	child->parent = new_parent;
+	child->ptracer_cred = get_cred(ptracer_cred);
+}
+
 /*
  * ptrace a task: make the debugger its new parent and
  * move it to the ptrace list.
  *
  * Must be called with the tasklist lock write-held.
  */
-void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
+static void ptrace_link(struct task_struct *child, struct task_struct *new_parent)
 {
-	BUG_ON(!list_empty(&child->ptrace_entry));
-	list_add(&child->ptrace_entry, &new_parent->ptraced);
-	child->parent = new_parent;
+	rcu_read_lock();
+	__ptrace_link(child, new_parent, __task_cred(new_parent));
+	rcu_read_unlock();
 }
 
 /**
@@ -71,11 +80,15 @@
  */
 void __ptrace_unlink(struct task_struct *child)
 {
+	const struct cred *old_cred;
 	BUG_ON(!child->ptrace);
 
 	child->ptrace = 0;
 	child->parent = child->real_parent;
 	list_del_init(&child->ptrace_entry);
+	old_cred = child->ptracer_cred;
+	child->ptracer_cred = NULL;
+	put_cred(old_cred);
 
 	spin_lock(&child->sighand->siglock);
 
@@ -144,11 +157,17 @@
 
 	WARN_ON(!task->ptrace || task->parent != current);
 
+	/*
+	 * PTRACE_LISTEN can allow ptrace_trap_notify to wake us up remotely.
+	 * Recheck state under the lock to close this race.
+	 */
 	spin_lock_irq(&task->sighand->siglock);
-	if (__fatal_signal_pending(task))
-		wake_up_state(task, __TASK_TRACED);
-	else
-		task->state = TASK_TRACED;
+	if (task->state == __TASK_TRACED) {
+		if (__fatal_signal_pending(task))
+			wake_up_state(task, __TASK_TRACED);
+		else
+			task->state = TASK_TRACED;
+	}
 	spin_unlock_irq(&task->sighand->siglock);
 }
 
@@ -219,7 +238,7 @@
 static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
 	const struct cred *cred = current_cred(), *tcred;
-	int dumpable = 0;
+	struct mm_struct *mm;
 	kuid_t caller_uid;
 	kgid_t caller_gid;
 
@@ -270,16 +289,11 @@
 	return -EPERM;
 ok:
 	rcu_read_unlock();
-	smp_rmb();
-	if (task->mm)
-		dumpable = get_dumpable(task->mm);
-	rcu_read_lock();
-	if (dumpable != SUID_DUMP_USER &&
-	    !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
-		rcu_read_unlock();
-		return -EPERM;
-	}
-	rcu_read_unlock();
+	mm = task->mm;
+	if (mm &&
+	    ((get_dumpable(mm) != SUID_DUMP_USER) &&
+	     !ptrace_has_cap(mm->user_ns, mode)))
+	    return -EPERM;
 
 	return security_ptrace_access_check(task, mode);
 }
@@ -343,13 +357,9 @@
 
 	if (seize)
 		flags |= PT_SEIZED;
-	rcu_read_lock();
-	if (ns_capable(__task_cred(task)->user_ns, CAP_SYS_PTRACE))
-		flags |= PT_PTRACE_CAP;
-	rcu_read_unlock();
 	task->ptrace = flags;
 
-	__ptrace_link(task, current);
+	ptrace_link(task, current);
 
 	/* SEIZE doesn't trap tracee on attach */
 	if (!seize)
@@ -416,7 +426,7 @@
 		 */
 		if (!ret && !(current->real_parent->flags & PF_EXITING)) {
 			current->ptrace = PT_PTRACED;
-			__ptrace_link(current, current->real_parent);
+			ptrace_link(current, current->real_parent);
 		}
 	}
 	write_unlock_irq(&tasklist_lock);
diff --git a/kernel/rcu/sync.c b/kernel/rcu/sync.c
index be922c9..b49cf3a 100644
--- a/kernel/rcu/sync.c
+++ b/kernel/rcu/sync.c
@@ -68,6 +68,7 @@
 	RCU_LOCKDEP_WARN(!gp_ops[rsp->gp_type].held(),
 			 "suspicious rcu_sync_is_idle() usage");
 }
+EXPORT_SYMBOL_GPL(rcu_sync_lockdep_assert);
 #endif
 
 /**
@@ -83,6 +84,18 @@
 }
 
 /**
+ * Must be called after rcu_sync_init() and before first use.
+ *
+ * Ensures rcu_sync_is_idle() returns false and rcu_sync_{enter,exit}()
+ * pairs turn into NO-OPs.
+ */
+void rcu_sync_enter_start(struct rcu_sync *rsp)
+{
+	rsp->gp_count++;
+	rsp->gp_state = GP_PASSED;
+}
+
+/**
  * rcu_sync_enter() - Force readers onto slowpath
  * @rsp: Pointer to rcu_sync structure to use for synchronization
  *
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 630c197..32cbe72 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -2275,6 +2275,7 @@
 				cl++;
 			c++;
 			local_bh_enable();
+			cond_resched_rcu_qs();
 			list = next;
 		}
 		trace_rcu_batch_end(rdp->rsp->name, c, !!list, 0, 0, 1);
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index 6768797..ca0d940 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -14,8 +14,13 @@
 obj-y += core.o loadavg.o clock.o cputime.o
 obj-y += idle_task.o fair.o rt.o deadline.o stop_task.o
 obj-y += wait.o completion.o idle.o
-obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o
+obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o energy.o
+obj-$(CONFIG_SCHED_WALT) += walt.o
 obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
 obj-$(CONFIG_SCHEDSTATS) += stats.o
 obj-$(CONFIG_SCHED_DEBUG) += debug.o
+obj-$(CONFIG_SCHED_TUNE) += tune.o
 obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o
+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+obj-$(CONFIG_CPU_FREQ_GOV_SCHED) += cpufreq_sched.o
+obj-$(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) += cpufreq_schedutil.o
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index ff6b870..e353de8 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -89,6 +89,7 @@
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/sched.h>
+#include "walt.h"
 
 DEFINE_MUTEX(sched_domains_mutex);
 DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
@@ -287,6 +288,18 @@
 /* cpus with isolated domains */
 cpumask_var_t cpu_isolated_map;
 
+struct rq *
+lock_rq_of(struct task_struct *p, unsigned long *flags)
+{
+	return task_rq_lock(p, flags);
+}
+
+void
+unlock_rq_of(struct rq *rq, struct task_struct *p, unsigned long *flags)
+{
+	task_rq_unlock(rq, p, flags);
+}
+
 /*
  * this_rq_lock - lock this runqueue and disable interrupts.
  */
@@ -627,7 +640,10 @@
 	rcu_read_lock();
 	for_each_domain(cpu, sd) {
 		for_each_cpu(i, sched_domain_span(sd)) {
-			if (!idle_cpu(i) && is_housekeeping_cpu(cpu)) {
+			if (cpu == i)
+				continue;
+
+			if (!idle_cpu(i) && is_housekeeping_cpu(i)) {
 				cpu = i;
 				goto unlock;
 			}
@@ -1073,7 +1089,9 @@
 
 	dequeue_task(rq, p, 0);
 	p->on_rq = TASK_ON_RQ_MIGRATING;
+	double_lock_balance(rq, cpu_rq(new_cpu));
 	set_task_cpu(p, new_cpu);
+	double_unlock_balance(rq, cpu_rq(new_cpu));
 	raw_spin_unlock(&rq->lock);
 
 	rq = cpu_rq(new_cpu);
@@ -1297,6 +1315,8 @@
 			p->sched_class->migrate_task_rq(p);
 		p->se.nr_migrations++;
 		perf_event_task_migrate(p);
+
+		walt_fixup_busy_time(p, new_cpu);
 	}
 
 	__set_task_cpu(p, new_cpu);
@@ -1925,6 +1945,10 @@
 {
 	unsigned long flags;
 	int cpu, success = 0;
+#ifdef CONFIG_SMP
+	struct rq *rq;
+	u64 wallclock;
+#endif
 
 	/*
 	 * If we are going to wake up a thread waiting for CONDITION we
@@ -1942,6 +1966,28 @@
 	success = 1; /* we're going to change ->state */
 	cpu = task_cpu(p);
 
+	/*
+	 * Ensure we load p->on_rq _after_ p->state, otherwise it would
+	 * be possible to, falsely, observe p->on_rq == 0 and get stuck
+	 * in smp_cond_load_acquire() below.
+	 *
+	 * sched_ttwu_pending()                 try_to_wake_up()
+	 *   [S] p->on_rq = 1;                  [L] P->state
+	 *       UNLOCK rq->lock  -----.
+	 *                              \
+	 *				 +---   RMB
+	 * schedule()                   /
+	 *       LOCK rq->lock    -----'
+	 *       UNLOCK rq->lock
+	 *
+	 * [task p]
+	 *   [S] p->state = UNINTERRUPTIBLE     [L] p->on_rq
+	 *
+	 * Pairs with the UNLOCK+LOCK on rq->lock from the
+	 * last wakeup of our task and the schedule that got our task
+	 * current.
+	 */
+	smp_rmb();
 	if (p->on_rq && ttwu_remote(p, wake_flags))
 		goto stat;
 
@@ -1982,6 +2028,14 @@
 	 */
 	smp_rmb();
 
+	rq = cpu_rq(task_cpu(p));
+
+	raw_spin_lock(&rq->lock);
+	wallclock = walt_ktime_clock();
+	walt_update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
+	walt_update_task_ravg(p, rq, TASK_WAKE, wallclock, 0);
+	raw_spin_unlock(&rq->lock);
+
 	p->sched_contributes_to_load = !!task_contributes_to_load(p);
 	p->state = TASK_WAKING;
 
@@ -1989,10 +2043,12 @@
 		p->sched_class->task_waking(p);
 
 	cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags);
+
 	if (task_cpu(p) != cpu) {
 		wake_flags |= WF_MIGRATED;
 		set_task_cpu(p, cpu);
 	}
+
 #endif /* CONFIG_SMP */
 
 	ttwu_queue(p, cpu);
@@ -2041,8 +2097,13 @@
 
 	trace_sched_waking(p);
 
-	if (!task_on_rq_queued(p))
+	if (!task_on_rq_queued(p)) {
+		u64 wallclock = walt_ktime_clock();
+
+		walt_update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
+		walt_update_task_ravg(p, rq, TASK_WAKE, wallclock, 0);
 		ttwu_activate(rq, p, ENQUEUE_WAKEUP);
+	}
 
 	ttwu_do_wakeup(rq, p, 0);
 	ttwu_stat(p, smp_processor_id(), 0);
@@ -2108,6 +2169,7 @@
 	p->se.nr_migrations		= 0;
 	p->se.vruntime			= 0;
 	INIT_LIST_HEAD(&p->se.group_node);
+	walt_init_new_task_load(p);
 
 #ifdef CONFIG_SCHEDSTATS
 	memset(&p->se.statistics, 0, sizeof(p->se.statistics));
@@ -2375,6 +2437,9 @@
 	struct rq *rq;
 
 	raw_spin_lock_irqsave(&p->pi_lock, flags);
+
+	walt_init_new_task_load(p);
+
 	/* Initialize new task's runnable average */
 	init_entity_runnable_average(&p->se);
 #ifdef CONFIG_SMP
@@ -2385,9 +2450,11 @@
 	 */
 	set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));
 #endif
-
 	rq = __task_rq_lock(p);
-	activate_task(rq, p, 0);
+	post_init_entity_util_avg(&p->se);
+
+	walt_mark_task_starting(p);
+	activate_task(rq, p, ENQUEUE_WAKEUP_NEW);
 	p->on_rq = TASK_ON_RQ_QUEUED;
 	trace_sched_wakeup_new(p);
 	check_preempt_curr(rq, p, WF_FORK);
@@ -2768,6 +2835,36 @@
 	return atomic_read(&this->nr_iowait);
 }
 
+#ifdef CONFIG_CPU_QUIET
+u64 nr_running_integral(unsigned int cpu)
+{
+	unsigned int seqcnt;
+	u64 integral;
+	struct rq *q;
+
+	if (cpu >= nr_cpu_ids)
+		return 0;
+
+	q = cpu_rq(cpu);
+
+	/*
+	 * Update average to avoid reading stalled value if there were
+	 * no run-queue changes for a long time. On the other hand if
+	 * the changes are happening right now, just read current value
+	 * directly.
+	 */
+
+	seqcnt = read_seqcount_begin(&q->ave_seqcnt);
+	integral = do_nr_running_integral(q);
+	if (read_seqcount_retry(&q->ave_seqcnt, seqcnt)) {
+		read_seqcount_begin(&q->ave_seqcnt);
+		integral = q->nr_running_integral;
+	}
+
+	return integral;
+}
+#endif
+
 void get_iowait_load(unsigned long *nr_waiters, unsigned long *load)
 {
 	struct rq *rq = this_rq();
@@ -2854,6 +2951,94 @@
 	return ns;
 }
 
+#ifdef CONFIG_CPU_FREQ_GOV_SCHED
+
+static inline
+unsigned long add_capacity_margin(unsigned long cpu_capacity)
+{
+	cpu_capacity  = cpu_capacity * capacity_margin;
+	cpu_capacity /= SCHED_CAPACITY_SCALE;
+	return cpu_capacity;
+}
+
+static inline
+unsigned long sum_capacity_reqs(unsigned long cfs_cap,
+				struct sched_capacity_reqs *scr)
+{
+	unsigned long total = add_capacity_margin(cfs_cap + scr->rt);
+	return total += scr->dl;
+}
+
+unsigned long boosted_cpu_util(int cpu);
+static void sched_freq_tick_pelt(int cpu)
+{
+	unsigned long cpu_utilization = boosted_cpu_util(cpu);
+	unsigned long capacity_curr = capacity_curr_of(cpu);
+	struct sched_capacity_reqs *scr;
+
+	scr = &per_cpu(cpu_sched_capacity_reqs, cpu);
+	if (sum_capacity_reqs(cpu_utilization, scr) < capacity_curr)
+		return;
+
+	/*
+	 * To make free room for a task that is building up its "real"
+	 * utilization and to harm its performance the least, request
+	 * a jump to a higher OPP as soon as the margin of free capacity
+	 * is impacted (specified by capacity_margin).
+	 */
+	set_cfs_cpu_capacity(cpu, true, cpu_utilization);
+}
+
+#ifdef CONFIG_SCHED_WALT
+static void sched_freq_tick_walt(int cpu)
+{
+	unsigned long cpu_utilization = cpu_util(cpu);
+	unsigned long capacity_curr = capacity_curr_of(cpu);
+
+	if (walt_disabled || !sysctl_sched_use_walt_cpu_util)
+		return sched_freq_tick_pelt(cpu);
+
+	/*
+	 * Add a margin to the WALT utilization.
+	 * NOTE: WALT tracks a single CPU signal for all the scheduling
+	 * classes, thus this margin is going to be added to the DL class as
+	 * well, which is something we do not do in sched_freq_tick_pelt case.
+	 */
+	cpu_utilization = add_capacity_margin(cpu_utilization);
+	if (cpu_utilization <= capacity_curr)
+		return;
+
+	/*
+	 * It is likely that the load is growing so we
+	 * keep the added margin in our request as an
+	 * extra boost.
+	 */
+	set_cfs_cpu_capacity(cpu, true, cpu_utilization);
+
+}
+#define _sched_freq_tick(cpu) sched_freq_tick_walt(cpu)
+#else
+#define _sched_freq_tick(cpu) sched_freq_tick_pelt(cpu)
+#endif /* CONFIG_SCHED_WALT */
+
+static void sched_freq_tick(int cpu)
+{
+	unsigned long capacity_orig, capacity_curr;
+
+	if (!sched_freq())
+		return;
+
+	capacity_orig = capacity_orig_of(cpu);
+	capacity_curr = capacity_curr_of(cpu);
+	if (capacity_curr == capacity_orig)
+		return;
+
+	_sched_freq_tick(cpu);
+}
+#else
+static inline void sched_freq_tick(int cpu) { }
+#endif /* CONFIG_CPU_FREQ_GOV_SCHED */
+
 /*
  * This function gets called by the timer code, with HZ frequency.
  * We call it with interrupts disabled.
@@ -2867,10 +3052,14 @@
 	sched_clock_tick();
 
 	raw_spin_lock(&rq->lock);
+	walt_set_window_start(rq);
 	update_rq_clock(rq);
 	curr->sched_class->task_tick(rq, curr, 0);
 	update_cpu_load_active(rq);
+	walt_update_task_ravg(rq->curr, rq, TASK_UPDATE,
+			walt_ktime_clock(), 0);
 	calc_global_load_tick(rq);
+	sched_freq_tick(cpu);
 	raw_spin_unlock(&rq->lock);
 
 	perf_event_task_tick();
@@ -3008,7 +3197,8 @@
 static inline void schedule_debug(struct task_struct *prev)
 {
 #ifdef CONFIG_SCHED_STACK_END_CHECK
-	BUG_ON(task_stack_end_corrupted(prev));
+	if (task_stack_end_corrupted(prev))
+		panic("corrupted stack end detected inside scheduler\n");
 #endif
 
 	if (unlikely(in_atomic_preempt_off())) {
@@ -3106,6 +3296,7 @@
 	unsigned long *switch_count;
 	struct rq *rq;
 	int cpu;
+	u64 wallclock;
 
 	cpu = smp_processor_id();
 	rq = cpu_rq(cpu);
@@ -3167,6 +3358,9 @@
 		update_rq_clock(rq);
 
 	next = pick_next_task(rq, prev);
+	wallclock = walt_ktime_clock();
+	walt_update_task_ravg(prev, rq, PUT_PREV_TASK, wallclock, 0);
+	walt_update_task_ravg(next, rq, PICK_NEXT_TASK, wallclock, 0);
 	clear_tsk_need_resched(prev);
 	clear_preempt_need_resched();
 	rq->clock_skip_update = 0;
@@ -4950,14 +5144,16 @@
 		/*
 		 * reset the NMI-timeout, listing all files on a slow
 		 * console might take a lot of time:
+		 * Also, reset softlockup watchdogs on all CPUs, because
+		 * another CPU might be blocked waiting for us to process
+		 * an IPI.
 		 */
 		touch_nmi_watchdog();
+		touch_all_softlockup_watchdogs();
 		if (!state_filter || (p->state & state_filter))
 			sched_show_task(p);
 	}
 
-	touch_all_softlockup_watchdogs();
-
 #ifdef CONFIG_SCHED_DEBUG
 	sysrq_sched_debug_show();
 #endif
@@ -4991,6 +5187,7 @@
 	raw_spin_lock(&rq->lock);
 
 	__sched_fork(0, idle);
+
 	idle->state = TASK_RUNNING;
 	idle->se.exec_start = sched_clock();
 
@@ -5373,9 +5570,60 @@
 }
 
 static struct ctl_table *
+sd_alloc_ctl_energy_table(struct sched_group_energy *sge)
+{
+	struct ctl_table *table = sd_alloc_ctl_entry(5);
+
+	if (table == NULL)
+		return NULL;
+
+	set_table_entry(&table[0], "nr_idle_states", &sge->nr_idle_states,
+			sizeof(int), 0644, proc_dointvec_minmax, false);
+	set_table_entry(&table[1], "idle_states", &sge->idle_states[0].power,
+			sge->nr_idle_states*sizeof(struct idle_state), 0644,
+			proc_doulongvec_minmax, false);
+	set_table_entry(&table[2], "nr_cap_states", &sge->nr_cap_states,
+			sizeof(int), 0644, proc_dointvec_minmax, false);
+	set_table_entry(&table[3], "cap_states", &sge->cap_states[0].cap,
+			sge->nr_cap_states*sizeof(struct capacity_state), 0644,
+			proc_doulongvec_minmax, false);
+
+	return table;
+}
+
+static struct ctl_table *
+sd_alloc_ctl_group_table(struct sched_group *sg)
+{
+	struct ctl_table *table = sd_alloc_ctl_entry(2);
+
+	if (table == NULL)
+		return NULL;
+
+	table->procname = kstrdup("energy", GFP_KERNEL);
+	table->mode = 0555;
+	table->child = sd_alloc_ctl_energy_table((struct sched_group_energy *)sg->sge);
+
+	return table;
+}
+
+static struct ctl_table *
 sd_alloc_ctl_domain_table(struct sched_domain *sd)
 {
-	struct ctl_table *table = sd_alloc_ctl_entry(14);
+	struct ctl_table *table;
+	unsigned int nr_entries = 14;
+
+	int i = 0;
+	struct sched_group *sg = sd->groups;
+
+	if (sg->sge) {
+		int nr_sgs = 0;
+
+		do {} while (nr_sgs++, sg = sg->next, sg != sd->groups);
+
+		nr_entries += nr_sgs;
+	}
+
+	table = sd_alloc_ctl_entry(nr_entries);
 
 	if (table == NULL)
 		return NULL;
@@ -5408,7 +5656,19 @@
 		sizeof(long), 0644, proc_doulongvec_minmax, false);
 	set_table_entry(&table[12], "name", sd->name,
 		CORENAME_MAX_SIZE, 0444, proc_dostring, false);
-	/* &table[13] is terminator */
+	sg = sd->groups;
+	if (sg->sge) {
+		char buf[32];
+		struct ctl_table *entry = &table[13];
+
+		do {
+			snprintf(buf, 32, "group%d", i);
+			entry->procname = kstrdup(buf, GFP_KERNEL);
+			entry->mode = 0555;
+			entry->child = sd_alloc_ctl_group_table(sg);
+		} while (entry++, i++, sg = sg->next, sg != sd->groups);
+	}
+	/* &table[nr_entries-1] is terminator */
 
 	return table;
 }
@@ -5524,6 +5784,9 @@
 	switch (action & ~CPU_TASKS_FROZEN) {
 
 	case CPU_UP_PREPARE:
+		raw_spin_lock_irqsave(&rq->lock, flags);
+		walt_set_window_start(rq);
+		raw_spin_unlock_irqrestore(&rq->lock, flags);
 		rq->calc_load_update = calc_load_update;
 		account_reset_rq(rq);
 		break;
@@ -5544,6 +5807,7 @@
 		sched_ttwu_pending();
 		/* Update our root-domain */
 		raw_spin_lock_irqsave(&rq->lock, flags);
+		walt_migrate_sync_cpu(cpu);
 		if (rq->rd) {
 			BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
 			set_rq_offline(rq);
@@ -5671,9 +5935,6 @@
 
 	if (!(sd->flags & SD_LOAD_BALANCE)) {
 		printk("does not load-balance\n");
-		if (sd->parent)
-			printk(KERN_ERR "ERROR: !SD_LOAD_BALANCE domain"
-					" has parent");
 		return -1;
 	}
 
@@ -5715,7 +5976,7 @@
 		printk(KERN_CONT " %*pbl",
 		       cpumask_pr_args(sched_group_cpus(group)));
 		if (group->sgc->capacity != SCHED_CAPACITY_SCALE) {
-			printk(KERN_CONT " (cpu_capacity = %d)",
+			printk(KERN_CONT " (cpu_capacity = %lu)",
 				group->sgc->capacity);
 		}
 
@@ -5766,8 +6027,12 @@
 
 static int sd_degenerate(struct sched_domain *sd)
 {
-	if (cpumask_weight(sched_domain_span(sd)) == 1)
-		return 1;
+	if (cpumask_weight(sched_domain_span(sd)) == 1) {
+		if (sd->groups->sge)
+			sd->flags &= ~SD_LOAD_BALANCE;
+		else
+			return 1;
+	}
 
 	/* Following flags need at least 2 groups */
 	if (sd->flags & (SD_LOAD_BALANCE |
@@ -5775,8 +6040,10 @@
 			 SD_BALANCE_FORK |
 			 SD_BALANCE_EXEC |
 			 SD_SHARE_CPUCAPACITY |
+			 SD_ASYM_CPUCAPACITY |
 			 SD_SHARE_PKG_RESOURCES |
-			 SD_SHARE_POWERDOMAIN)) {
+			 SD_SHARE_POWERDOMAIN |
+			 SD_SHARE_CAP_STATES)) {
 		if (sd->groups != sd->groups->next)
 			return 0;
 	}
@@ -5805,10 +6072,16 @@
 				SD_BALANCE_NEWIDLE |
 				SD_BALANCE_FORK |
 				SD_BALANCE_EXEC |
+				SD_ASYM_CPUCAPACITY |
 				SD_SHARE_CPUCAPACITY |
 				SD_SHARE_PKG_RESOURCES |
 				SD_PREFER_SIBLING |
-				SD_SHARE_POWERDOMAIN);
+				SD_SHARE_POWERDOMAIN |
+				SD_SHARE_CAP_STATES);
+		if (parent->groups->sge) {
+			parent->flags &= ~SD_LOAD_BALANCE;
+			return 0;
+		}
 		if (nr_node_ids == 1)
 			pflags &= ~SD_SERIALIZE;
 	}
@@ -5887,6 +6160,11 @@
 
 	if (cpupri_init(&rd->cpupri) != 0)
 		goto free_rto_mask;
+
+	init_max_cpu_capacity(&rd->max_cpu_capacity);
+
+	rd->max_cap_orig_cpu = rd->min_cap_orig_cpu = -1;
+
 	return 0;
 
 free_rto_mask:
@@ -5992,11 +6270,13 @@
 DEFINE_PER_CPU(struct sched_domain *, sd_numa);
 DEFINE_PER_CPU(struct sched_domain *, sd_busy);
 DEFINE_PER_CPU(struct sched_domain *, sd_asym);
+DEFINE_PER_CPU(struct sched_domain *, sd_ea);
+DEFINE_PER_CPU(struct sched_domain *, sd_scs);
 
 static void update_top_cache_domain(int cpu)
 {
 	struct sched_domain *sd;
-	struct sched_domain *busy_sd = NULL;
+	struct sched_domain *busy_sd = NULL, *ea_sd = NULL;
 	int id = cpu;
 	int size = 1;
 
@@ -6017,6 +6297,17 @@
 
 	sd = highest_flag_domain(cpu, SD_ASYM_PACKING);
 	rcu_assign_pointer(per_cpu(sd_asym, cpu), sd);
+
+	for_each_domain(cpu, sd) {
+		if (sd->groups->sge)
+			ea_sd = sd;
+		else
+			break;
+	}
+	rcu_assign_pointer(per_cpu(sd_ea, cpu), ea_sd);
+
+	sd = highest_flag_domain(cpu, SD_SHARE_CAP_STATES);
+	rcu_assign_pointer(per_cpu(sd_scs, cpu), sd);
 }
 
 /*
@@ -6177,6 +6468,8 @@
 		 * die on a /0 trap.
 		 */
 		sg->sgc->capacity = SCHED_CAPACITY_SCALE * cpumask_weight(sg_span);
+		sg->sgc->max_capacity = SCHED_CAPACITY_SCALE;
+		sg->sgc->min_capacity = SCHED_CAPACITY_SCALE;
 
 		/*
 		 * Make sure the first group of this domain contains the
@@ -6306,6 +6599,66 @@
 }
 
 /*
+ * Check that the per-cpu provided sd energy data is consistent for all cpus
+ * within the mask.
+ */
+static inline void check_sched_energy_data(int cpu, sched_domain_energy_f fn,
+					   const struct cpumask *cpumask)
+{
+	const struct sched_group_energy * const sge = fn(cpu);
+	struct cpumask mask;
+	int i;
+
+	if (cpumask_weight(cpumask) <= 1)
+		return;
+
+	cpumask_xor(&mask, cpumask, get_cpu_mask(cpu));
+
+	for_each_cpu(i, &mask) {
+		const struct sched_group_energy * const e = fn(i);
+		int y;
+
+		BUG_ON(e->nr_idle_states != sge->nr_idle_states);
+
+		for (y = 0; y < (e->nr_idle_states); y++) {
+			BUG_ON(e->idle_states[y].power !=
+					sge->idle_states[y].power);
+		}
+
+		BUG_ON(e->nr_cap_states != sge->nr_cap_states);
+
+		for (y = 0; y < (e->nr_cap_states); y++) {
+			BUG_ON(e->cap_states[y].cap != sge->cap_states[y].cap);
+			BUG_ON(e->cap_states[y].power !=
+					sge->cap_states[y].power);
+		}
+	}
+}
+
+static void init_sched_energy(int cpu, struct sched_domain *sd,
+			      sched_domain_energy_f fn)
+{
+	if (!(fn && fn(cpu)))
+		return;
+
+	if (cpu != group_balance_cpu(sd->groups))
+		return;
+
+	if (sd->child && !sd->child->groups->sge) {
+		pr_err("BUG: EAS setup broken for CPU%d\n", cpu);
+#ifdef CONFIG_SCHED_DEBUG
+		pr_err("     energy data on %s but not on %s domain\n",
+			sd->name, sd->child->name);
+#endif
+		return;
+	}
+
+	check_sched_energy_data(cpu, fn, sched_group_cpus(sd->groups));
+
+	sd->groups->sge = fn(cpu);
+}
+
+/*
  * Initializers for schedule domains
  * Non-inlined to reduce accumulated stack pressure in build_sched_domains()
  */
@@ -6409,10 +6762,19 @@
 /*
  * SD_flags allowed in topology descriptions.
  *
- * SD_SHARE_CPUCAPACITY      - describes SMT topologies
- * SD_SHARE_PKG_RESOURCES - describes shared caches
- * SD_NUMA                - describes NUMA topologies
- * SD_SHARE_POWERDOMAIN   - describes shared power domain
+ * These flags are purely descriptive of the topology and do not prescribe
+ * behaviour. Behaviour is artificial and mapped in the below sd_init()
+ * function:
+ *
+ *   SD_SHARE_CPUCAPACITY   - describes SMT topologies
+ *   SD_SHARE_PKG_RESOURCES - describes shared caches
+ *   SD_NUMA                - describes NUMA topologies
+ *   SD_SHARE_POWERDOMAIN   - describes shared power domain
+ *   SD_ASYM_CPUCAPACITY    - describes mixed capacity topologies
+ *   SD_SHARE_CAP_STATES    - describes shared capacity states
+ *
+ * Odd one out, which beside describing the topology has a quirk also
+ * prescribes the desired behaviour that goes along with it:
  *
  * Odd one out:
  * SD_ASYM_PACKING        - describes SMT quirks
@@ -6422,10 +6784,13 @@
 	 SD_SHARE_PKG_RESOURCES |	\
 	 SD_NUMA |			\
 	 SD_ASYM_PACKING |		\
-	 SD_SHARE_POWERDOMAIN)
+	 SD_ASYM_CPUCAPACITY |		\
+	 SD_SHARE_POWERDOMAIN |		\
+	 SD_SHARE_CAP_STATES)
 
 static struct sched_domain *
-sd_init(struct sched_domain_topology_level *tl, int cpu)
+sd_init(struct sched_domain_topology_level *tl,
+	struct sched_domain *child, int cpu)
 {
 	struct sched_domain *sd = *per_cpu_ptr(tl->data.sd, cpu);
 	int sd_weight, sd_flags = 0;
@@ -6477,6 +6842,7 @@
 		.smt_gain		= 0,
 		.max_newidle_lb_cost	= 0,
 		.next_decay_max_lb_cost	= jiffies,
+		.child			= child,
 #ifdef CONFIG_SCHED_DEBUG
 		.name			= tl->name,
 #endif
@@ -6486,6 +6852,13 @@
 	 * Convert topological properties into behaviour.
 	 */
 
+	if (sd->flags & SD_ASYM_CPUCAPACITY) {
+		struct sched_domain *t = sd;
+
+		for_each_lower_domain(t)
+			t->flags |= SD_BALANCE_WAKE;
+	}
+
 	if (sd->flags & SD_SHARE_CPUCAPACITY) {
 		sd->flags |= SD_PREFER_SIBLING;
 		sd->imbalance_pct = 110;
@@ -6932,16 +7305,13 @@
 		const struct cpumask *cpu_map, struct sched_domain_attr *attr,
 		struct sched_domain *child, int cpu)
 {
-	struct sched_domain *sd = sd_init(tl, cpu);
-	if (!sd)
-		return child;
+	struct sched_domain *sd = sd_init(tl, child, cpu);
 
 	cpumask_and(sched_domain_span(sd), cpu_map, tl->mask(cpu));
 	if (child) {
 		sd->level = child->level + 1;
 		sched_domain_level_max = max(sched_domain_level_max, sd->level);
 		child->parent = sd;
-		sd->child = child;
 
 		if (!cpumask_subset(sched_domain_span(child),
 				    sched_domain_span(sd))) {
@@ -6989,8 +7359,6 @@
 				*per_cpu_ptr(d.sd, i) = sd;
 			if (tl->flags & SDTL_OVERLAP || sched_feat(FORCE_SD_OVERLAP))
 				sd->flags |= SD_OVERLAP;
-			if (cpumask_equal(cpu_map, sched_domain_span(sd)))
-				break;
 		}
 	}
 
@@ -7010,10 +7378,13 @@
 
 	/* Calculate CPU capacity for physical packages and nodes */
 	for (i = nr_cpumask_bits-1; i >= 0; i--) {
+		struct sched_domain_topology_level *tl = sched_domain_topology;
+
 		if (!cpumask_test_cpu(i, cpu_map))
 			continue;
 
-		for (sd = *per_cpu_ptr(d.sd, i); sd; sd = sd->parent) {
+		for (sd = *per_cpu_ptr(d.sd, i); sd; sd = sd->parent, tl++) {
+			init_sched_energy(i, sd, tl->energy);
 			claim_allocations(i, sd);
 			init_sched_groups_capacity(i, sd);
 		}
@@ -7022,7 +7393,19 @@
 	/* Attach the domains */
 	rcu_read_lock();
 	for_each_cpu(i, cpu_map) {
+		int max_cpu = READ_ONCE(d.rd->max_cap_orig_cpu);
+		int min_cpu = READ_ONCE(d.rd->min_cap_orig_cpu);
+
+		if ((max_cpu < 0) || (cpu_rq(i)->cpu_capacity_orig >
+		    cpu_rq(max_cpu)->cpu_capacity_orig))
+			WRITE_ONCE(d.rd->max_cap_orig_cpu, i);
+
+		if ((min_cpu < 0) || (cpu_rq(i)->cpu_capacity_orig <
+		    cpu_rq(min_cpu)->cpu_capacity_orig))
+			WRITE_ONCE(d.rd->min_cap_orig_cpu, i);
+
 		sd = *per_cpu_ptr(d.sd, i);
+
 		cpu_attach_domain(sd, d.rd, i);
 	}
 	rcu_read_unlock();
@@ -7303,6 +7686,7 @@
 {
 	cpumask_var_t non_isolated_cpus;
 
+	walt_init_cpu_efficiency();
 	alloc_cpumask_var(&non_isolated_cpus, GFP_KERNEL);
 	alloc_cpumask_var(&fallback_doms, GFP_KERNEL);
 
@@ -7434,6 +7818,7 @@
 #ifdef CONFIG_FAIR_GROUP_SCHED
 		root_task_group.shares = ROOT_TASK_GROUP_LOAD;
 		INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
+		rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
 		/*
 		 * How much cpu bandwidth does root_task_group get?
 		 *
@@ -7480,6 +7865,11 @@
 		rq->idle_stamp = 0;
 		rq->avg_idle = 2*sysctl_sched_migration_cost;
 		rq->max_idle_balance_cost = sysctl_sched_migration_cost;
+#ifdef CONFIG_SCHED_WALT
+		rq->cur_irqload = 0;
+		rq->avg_irqload = 0;
+		rq->irqload_ts = 0;
+#endif
 
 		INIT_LIST_HEAD(&rq->cfs_tasks);
 
@@ -8603,7 +8993,6 @@
 	.fork		= cpu_cgroup_fork,
 	.can_attach	= cpu_cgroup_can_attach,
 	.attach		= cpu_cgroup_attach,
-	.allow_attach   = subsys_cgroup_allow_attach,
 	.legacy_cftypes	= cpu_files,
 	.early_init	= 1,
 };
diff --git a/kernel/sched/cpufreq.c b/kernel/sched/cpufreq.c
new file mode 100644
index 0000000..dbc5144
--- /dev/null
+++ b/kernel/sched/cpufreq.c
@@ -0,0 +1,63 @@
+/*
+ * Scheduler code and data structures related to cpufreq.
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "sched.h"
+
+DEFINE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
+
+/**
+ * cpufreq_add_update_util_hook - Populate the CPU's update_util_data pointer.
+ * @cpu: The CPU to set the pointer for.
+ * @data: New pointer value.
+ * @func: Callback function to set for the CPU.
+ *
+ * Set and publish the update_util_data pointer for the given CPU.
+ *
+ * The update_util_data pointer of @cpu is set to @data and the callback
+ * function pointer in the target struct update_util_data is set to @func.
+ * That function will be called by cpufreq_update_util() from RCU-sched
+ * read-side critical sections, so it must not sleep.  @data will always be
+ * passed to it as the first argument which allows the function to get to the
+ * target update_util_data structure and its container.
+ *
+ * The update_util_data pointer of @cpu must be NULL when this function is
+ * called or it will WARN() and return with no effect.
+ */
+void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
+			void (*func)(struct update_util_data *data, u64 time,
+				     unsigned int flags))
+{
+	if (WARN_ON(!data || !func))
+		return;
+
+	if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
+		return;
+
+	data->func = func;
+	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
+}
+EXPORT_SYMBOL_GPL(cpufreq_add_update_util_hook);
+
+/**
+ * cpufreq_remove_update_util_hook - Clear the CPU's update_util_data pointer.
+ * @cpu: The CPU to clear the pointer for.
+ *
+ * Clear the update_util_data pointer for the given CPU.
+ *
+ * Callers must use RCU-sched callbacks to free any memory that might be
+ * accessed via the old update_util_data pointer or invoke synchronize_sched()
+ * right after this function to avoid use-after-free.
+ */
+void cpufreq_remove_update_util_hook(int cpu)
+{
+	rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), NULL);
+}
+EXPORT_SYMBOL_GPL(cpufreq_remove_update_util_hook);
diff --git a/kernel/sched/cpufreq_sched.c b/kernel/sched/cpufreq_sched.c
new file mode 100644
index 0000000..f10d9f7
--- /dev/null
+++ b/kernel/sched/cpufreq_sched.c
@@ -0,0 +1,513 @@
+/*
+ *  Copyright (C)  2015 Michael Turquette <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/cpufreq.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/percpu.h>
+#include <linux/irq_work.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/cpufreq_sched.h>
+
+#include "sched.h"
+
+#define THROTTLE_DOWN_NSEC	50000000 /* 50ms default */
+#define THROTTLE_UP_NSEC	500000 /* 500us default */
+
+struct static_key __read_mostly __sched_freq = STATIC_KEY_INIT_FALSE;
+static bool __read_mostly cpufreq_driver_slow;
+
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_SCHED
+static struct cpufreq_governor cpufreq_gov_sched;
+#endif
+
+static DEFINE_PER_CPU(unsigned long, enabled);
+DEFINE_PER_CPU(struct sched_capacity_reqs, cpu_sched_capacity_reqs);
+
+struct gov_tunables {
+	struct gov_attr_set attr_set;
+	unsigned int up_throttle_nsec;
+	unsigned int down_throttle_nsec;
+};
+
+/**
+ * gov_data - per-policy data internal to the governor
+ * @up_throttle: next throttling period expiry if increasing OPP
+ * @down_throttle: next throttling period expiry if decreasing OPP
+ * @up_throttle_nsec: throttle period length in nanoseconds if increasing OPP
+ * @down_throttle_nsec: throttle period length in nanoseconds if decreasing OPP
+ * @task: worker thread for dvfs transition that may block/sleep
+ * @irq_work: callback used to wake up worker thread
+ * @requested_freq: last frequency requested by the sched governor
+ *
+ * struct gov_data is the per-policy cpufreq_sched-specific data structure. A
+ * per-policy instance of it is created when the cpufreq_sched governor receives
+ * the CPUFREQ_GOV_START condition and a pointer to it exists in the gov_data
+ * member of struct cpufreq_policy.
+ *
+ * Readers of this data must call down_read(policy->rwsem). Writers must
+ * call down_write(policy->rwsem).
+ */
+struct gov_data {
+	ktime_t up_throttle;
+	ktime_t down_throttle;
+	struct gov_tunables *tunables;
+	struct list_head tunables_hook;
+	struct task_struct *task;
+	struct irq_work irq_work;
+	unsigned int requested_freq;
+};
+
+static void cpufreq_sched_try_driver_target(struct cpufreq_policy *policy,
+					    unsigned int freq)
+{
+	struct gov_data *gd = policy->governor_data;
+
+	/* avoid race with cpufreq_sched_stop */
+	if (!down_write_trylock(&policy->rwsem))
+		return;
+
+	__cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
+
+	gd->up_throttle = ktime_add_ns(ktime_get(),
+				       gd->tunables->up_throttle_nsec);
+	gd->down_throttle = ktime_add_ns(ktime_get(),
+					 gd->tunables->down_throttle_nsec);
+	up_write(&policy->rwsem);
+}
+
+static bool finish_last_request(struct gov_data *gd, unsigned int cur_freq)
+{
+	ktime_t now = ktime_get();
+
+	ktime_t throttle = gd->requested_freq < cur_freq ?
+		gd->down_throttle : gd->up_throttle;
+
+	if (ktime_after(now, throttle))
+		return false;
+
+	while (1) {
+		int usec_left = ktime_to_ns(ktime_sub(throttle, now));
+
+		usec_left /= NSEC_PER_USEC;
+		trace_cpufreq_sched_throttled(usec_left);
+		usleep_range(usec_left, usec_left + 100);
+		now = ktime_get();
+		if (ktime_after(now, throttle))
+			return true;
+	}
+}
+
+/*
+ * we pass in struct cpufreq_policy. This is safe because changing out the
+ * policy requires a call to __cpufreq_governor(policy, CPUFREQ_GOV_STOP),
+ * which tears down all of the data structures and __cpufreq_governor(policy,
+ * CPUFREQ_GOV_START) will do a full rebuild, including this kthread with the
+ * new policy pointer
+ */
+static int cpufreq_sched_thread(void *data)
+{
+	struct sched_param param;
+	struct cpufreq_policy *policy;
+	struct gov_data *gd;
+	unsigned int new_request = 0;
+	unsigned int last_request = 0;
+	int ret;
+
+	policy = (struct cpufreq_policy *) data;
+	gd = policy->governor_data;
+
+	param.sched_priority = 50;
+	ret = sched_setscheduler_nocheck(gd->task, SCHED_FIFO, &param);
+	if (ret) {
+		pr_warn("%s: failed to set SCHED_FIFO\n", __func__);
+		do_exit(-EINVAL);
+	} else {
+		pr_debug("%s: kthread (%d) set to SCHED_FIFO\n",
+				__func__, gd->task->pid);
+	}
+
+	do {
+		new_request = gd->requested_freq;
+		if (new_request == last_request) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (kthread_should_stop())
+				break;
+			schedule();
+		} else {
+			/*
+			 * if the frequency thread sleeps while waiting to be
+			 * unthrottled, start over to check for a newer request
+			 */
+			if (finish_last_request(gd, policy->cur))
+				continue;
+			last_request = new_request;
+			cpufreq_sched_try_driver_target(policy, new_request);
+		}
+	} while (!kthread_should_stop());
+
+	return 0;
+}
+
+static void cpufreq_sched_irq_work(struct irq_work *irq_work)
+{
+	struct gov_data *gd;
+
+	gd = container_of(irq_work, struct gov_data, irq_work);
+	if (!gd)
+		return;
+
+	wake_up_process(gd->task);
+}
+
+static void update_fdomain_capacity_request(int cpu)
+{
+	unsigned int freq_new, index_new, cpu_tmp;
+	struct cpufreq_policy *policy;
+	struct gov_data *gd;
+	unsigned long capacity = 0;
+
+	/*
+	 * Avoid grabbing the policy if possible. A test is still
+	 * required after locking the CPU's policy to avoid racing
+	 * with the governor changing.
+	 */
+	if (!per_cpu(enabled, cpu))
+		return;
+
+	policy = cpufreq_cpu_get(cpu);
+	if (IS_ERR_OR_NULL(policy))
+		return;
+
+	if (policy->governor != &cpufreq_gov_sched ||
+	    !policy->governor_data)
+		goto out;
+
+	gd = policy->governor_data;
+
+	/* find max capacity requested by cpus in this policy */
+	for_each_cpu(cpu_tmp, policy->cpus) {
+		struct sched_capacity_reqs *scr;
+
+		scr = &per_cpu(cpu_sched_capacity_reqs, cpu_tmp);
+		capacity = max(capacity, scr->total);
+	}
+
+	/* Convert the new maximum capacity request into a cpu frequency */
+	freq_new = capacity * policy->max >> SCHED_CAPACITY_SHIFT;
+	if (cpufreq_frequency_table_target(policy, policy->freq_table,
+					   freq_new, CPUFREQ_RELATION_L,
+					   &index_new))
+		goto out;
+	freq_new = policy->freq_table[index_new].frequency;
+
+	if (freq_new > policy->max)
+		freq_new = policy->max;
+
+	if (freq_new < policy->min)
+		freq_new = policy->min;
+
+	trace_cpufreq_sched_request_opp(cpu, capacity, freq_new,
+					gd->requested_freq);
+	if (freq_new == gd->requested_freq)
+		goto out;
+
+	gd->requested_freq = freq_new;
+
+	/*
+	 * Throttling is not yet supported on platforms with fast cpufreq
+	 * drivers.
+	 */
+	if (cpufreq_driver_slow)
+		irq_work_queue_on(&gd->irq_work, cpu);
+	else
+		cpufreq_sched_try_driver_target(policy, freq_new);
+
+out:
+	cpufreq_cpu_put(policy);
+}
+
+void update_cpu_capacity_request(int cpu, bool request)
+{
+	unsigned long new_capacity;
+	struct sched_capacity_reqs *scr;
+
+	/* The rq lock serializes access to the CPU's sched_capacity_reqs. */
+	lockdep_assert_held(&cpu_rq(cpu)->lock);
+
+	scr = &per_cpu(cpu_sched_capacity_reqs, cpu);
+
+	new_capacity = scr->cfs + scr->rt;
+	new_capacity = new_capacity * capacity_margin
+		/ SCHED_CAPACITY_SCALE;
+	new_capacity += scr->dl;
+
+	if (new_capacity == scr->total)
+		return;
+
+	trace_cpufreq_sched_update_capacity(cpu, request, scr, new_capacity);
+
+	scr->total = new_capacity;
+	if (request)
+		update_fdomain_capacity_request(cpu);
+}
+
+static inline void set_sched_freq(void)
+{
+	static_key_slow_inc(&__sched_freq);
+}
+
+static inline void clear_sched_freq(void)
+{
+	static_key_slow_dec(&__sched_freq);
+}
+
+/* Tunables */
+static struct gov_tunables *global_tunables;
+
+static inline struct gov_tunables *to_tunables(struct gov_attr_set *attr_set)
+{
+	return container_of(attr_set, struct gov_tunables, attr_set);
+}
+
+static ssize_t up_throttle_nsec_show(struct gov_attr_set *attr_set, char *buf)
+{
+	struct gov_tunables *tunables = to_tunables(attr_set);
+
+	return sprintf(buf, "%u\n", tunables->up_throttle_nsec);
+}
+
+static ssize_t up_throttle_nsec_store(struct gov_attr_set *attr_set,
+				      const char *buf, size_t count)
+{
+	struct gov_tunables *tunables = to_tunables(attr_set);
+	int ret;
+	long unsigned int val;
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+	tunables->up_throttle_nsec = val;
+	return count;
+}
+
+static ssize_t down_throttle_nsec_show(struct gov_attr_set *attr_set, char *buf)
+{
+	struct gov_tunables *tunables = to_tunables(attr_set);
+
+	return sprintf(buf, "%u\n", tunables->down_throttle_nsec);
+}
+
+static ssize_t down_throttle_nsec_store(struct gov_attr_set *attr_set,
+					const char *buf, size_t count)
+{
+	struct gov_tunables *tunables = to_tunables(attr_set);
+	int ret;
+	long unsigned int val;
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+	tunables->down_throttle_nsec = val;
+	return count;
+}
+
+static struct governor_attr up_throttle_nsec = __ATTR_RW(up_throttle_nsec);
+static struct governor_attr down_throttle_nsec = __ATTR_RW(down_throttle_nsec);
+
+static struct attribute *schedfreq_attributes[] = {
+	&up_throttle_nsec.attr,
+	&down_throttle_nsec.attr,
+	NULL
+};
+
+static struct kobj_type tunables_ktype = {
+	.default_attrs = schedfreq_attributes,
+	.sysfs_ops = &governor_sysfs_ops,
+};
+
+static int cpufreq_sched_policy_init(struct cpufreq_policy *policy)
+{
+	struct gov_data *gd;
+	int cpu;
+	int rc;
+
+	for_each_cpu(cpu, policy->cpus)
+		memset(&per_cpu(cpu_sched_capacity_reqs, cpu), 0,
+		       sizeof(struct sched_capacity_reqs));
+
+	gd = kzalloc(sizeof(*gd), GFP_KERNEL);
+	if (!gd)
+		return -ENOMEM;
+
+	policy->governor_data = gd;
+
+	if (!global_tunables) {
+		gd->tunables = kzalloc(sizeof(*gd->tunables), GFP_KERNEL);
+		if (!gd->tunables)
+			goto free_gd;
+
+		gd->tunables->up_throttle_nsec =
+			policy->cpuinfo.transition_latency ?
+			policy->cpuinfo.transition_latency :
+			THROTTLE_UP_NSEC;
+		gd->tunables->down_throttle_nsec =
+			THROTTLE_DOWN_NSEC;
+
+		rc = kobject_init_and_add(&gd->tunables->attr_set.kobj,
+					  &tunables_ktype,
+					  get_governor_parent_kobj(policy),
+					  "%s", cpufreq_gov_sched.name);
+		if (rc)
+			goto free_tunables;
+
+		gov_attr_set_init(&gd->tunables->attr_set,
+				  &gd->tunables_hook);
+
+		pr_debug("%s: throttle_threshold = %u [ns]\n",
+			 __func__, gd->tunables->up_throttle_nsec);
+
+		if (!have_governor_per_policy())
+			global_tunables = gd->tunables;
+	} else {
+		gd->tunables = global_tunables;
+		gov_attr_set_get(&global_tunables->attr_set,
+				 &gd->tunables_hook);
+	}
+
+	policy->governor_data = gd;
+	if (cpufreq_driver_is_slow()) {
+		cpufreq_driver_slow = true;
+		gd->task = kthread_create(cpufreq_sched_thread, policy,
+					  "kschedfreq:%d",
+					  cpumask_first(policy->related_cpus));
+		if (IS_ERR_OR_NULL(gd->task)) {
+			pr_err("%s: failed to create kschedfreq thread\n",
+			       __func__);
+			goto free_tunables;
+		}
+		get_task_struct(gd->task);
+		kthread_bind_mask(gd->task, policy->related_cpus);
+		wake_up_process(gd->task);
+		init_irq_work(&gd->irq_work, cpufreq_sched_irq_work);
+	}
+
+	set_sched_freq();
+
+	return 0;
+
+free_tunables:
+	kfree(gd->tunables);
+free_gd:
+	policy->governor_data = NULL;
+	kfree(gd);
+	return -ENOMEM;
+}
+
+static int cpufreq_sched_policy_exit(struct cpufreq_policy *policy)
+{
+	unsigned int count;
+	struct gov_data *gd = policy->governor_data;
+
+	clear_sched_freq();
+	if (cpufreq_driver_slow) {
+		kthread_stop(gd->task);
+		put_task_struct(gd->task);
+	}
+
+	count = gov_attr_set_put(&gd->tunables->attr_set, &gd->tunables_hook);
+	if (!count) {
+		if (!have_governor_per_policy())
+			global_tunables = NULL;
+		kfree(gd->tunables);
+	}
+
+	policy->governor_data = NULL;
+
+	kfree(gd);
+	return 0;
+}
+
+static int cpufreq_sched_start(struct cpufreq_policy *policy)
+{
+	int cpu;
+
+	for_each_cpu(cpu, policy->cpus)
+		per_cpu(enabled, cpu) = 1;
+
+	return 0;
+}
+
+static void cpufreq_sched_limits(struct cpufreq_policy *policy)
+{
+	unsigned int clamp_freq;
+	struct gov_data *gd = policy->governor_data;;
+
+	pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz\n",
+		policy->cpu, policy->min, policy->max,
+		policy->cur);
+
+	clamp_freq = clamp(gd->requested_freq, policy->min, policy->max);
+
+	if (policy->cur != clamp_freq)
+		__cpufreq_driver_target(policy, clamp_freq, CPUFREQ_RELATION_L);
+}
+
+static int cpufreq_sched_stop(struct cpufreq_policy *policy)
+{
+	int cpu;
+
+	for_each_cpu(cpu, policy->cpus)
+		per_cpu(enabled, cpu) = 0;
+
+	return 0;
+}
+
+static int cpufreq_sched_setup(struct cpufreq_policy *policy,
+			       unsigned int event)
+{
+	switch (event) {
+	case CPUFREQ_GOV_POLICY_INIT:
+		return cpufreq_sched_policy_init(policy);
+	case CPUFREQ_GOV_POLICY_EXIT:
+		return cpufreq_sched_policy_exit(policy);
+	case CPUFREQ_GOV_START:
+		return cpufreq_sched_start(policy);
+	case CPUFREQ_GOV_STOP:
+		return cpufreq_sched_stop(policy);
+	case CPUFREQ_GOV_LIMITS:
+		cpufreq_sched_limits(policy);
+		break;
+	}
+	return 0;
+}
+
+
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_SCHED
+static
+#endif
+struct cpufreq_governor cpufreq_gov_sched = {
+	.name			= "sched",
+	.governor		= cpufreq_sched_setup,
+	.owner			= THIS_MODULE,
+};
+
+static int __init cpufreq_sched_init(void)
+{
+	int cpu;
+
+	for_each_cpu(cpu, cpu_possible_mask)
+		per_cpu(enabled, cpu) = 0;
+	return cpufreq_register_governor(&cpufreq_gov_sched);
+}
+
+/* Try to make this the default governor */
+fs_initcall(cpufreq_sched_init);
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
new file mode 100644
index 0000000..75bfbb3
--- /dev/null
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -0,0 +1,770 @@
+/*
+ * CPUFreq governor based on scheduler-provided CPU utilization data.
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpufreq.h>
+#include <linux/kthread.h>
+#include <linux/slab.h>
+#include <trace/events/power.h>
+
+#include "sched.h"
+#include "tune.h"
+
+unsigned long boosted_cpu_util(int cpu);
+
+/* Stub out fast switch routines present on mainline to reduce the backport
+ * overhead. */
+#define cpufreq_driver_fast_switch(x, y) 0
+#define cpufreq_enable_fast_switch(x)
+#define cpufreq_disable_fast_switch(x)
+#define LATENCY_MULTIPLIER			(1000)
+#define SUGOV_KTHREAD_PRIORITY	50
+
+struct sugov_tunables {
+	struct gov_attr_set attr_set;
+	unsigned int up_rate_limit_us;
+	unsigned int down_rate_limit_us;
+};
+
+struct sugov_policy {
+	struct cpufreq_policy *policy;
+
+	struct sugov_tunables *tunables;
+	struct list_head tunables_hook;
+
+	raw_spinlock_t update_lock;  /* For shared policies */
+	u64 last_freq_update_time;
+	s64 min_rate_limit_ns;
+	s64 up_rate_delay_ns;
+	s64 down_rate_delay_ns;
+	unsigned int next_freq;
+
+	/* The next fields are only needed if fast switch cannot be used. */
+	struct irq_work irq_work;
+	struct kthread_work work;
+	struct mutex work_lock;
+	struct kthread_worker worker;
+	struct task_struct *thread;
+	bool work_in_progress;
+
+	bool need_freq_update;
+};
+
+struct sugov_cpu {
+	struct update_util_data update_util;
+	struct sugov_policy *sg_policy;
+
+	unsigned int cached_raw_freq;
+	unsigned long iowait_boost;
+	unsigned long iowait_boost_max;
+	u64 last_update;
+
+	/* The fields below are only needed when sharing a policy. */
+	unsigned long util;
+	unsigned long max;
+	unsigned int flags;
+};
+
+static DEFINE_PER_CPU(struct sugov_cpu, sugov_cpu);
+
+/************************ Governor internals ***********************/
+
+static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
+{
+	s64 delta_ns;
+
+	if (sg_policy->work_in_progress)
+		return false;
+
+	if (unlikely(sg_policy->need_freq_update)) {
+		sg_policy->need_freq_update = false;
+		/*
+		 * This happens when limits change, so forget the previous
+		 * next_freq value and force an update.
+		 */
+		sg_policy->next_freq = UINT_MAX;
+		return true;
+	}
+
+	delta_ns = time - sg_policy->last_freq_update_time;
+
+	/* No need to recalculate next freq for min_rate_limit_us at least */
+	return delta_ns >= sg_policy->min_rate_limit_ns;
+}
+
+static bool sugov_up_down_rate_limit(struct sugov_policy *sg_policy, u64 time,
+				     unsigned int next_freq)
+{
+	s64 delta_ns;
+
+	delta_ns = time - sg_policy->last_freq_update_time;
+
+	if (next_freq > sg_policy->next_freq &&
+	    delta_ns < sg_policy->up_rate_delay_ns)
+			return true;
+
+	if (next_freq < sg_policy->next_freq &&
+	    delta_ns < sg_policy->down_rate_delay_ns)
+			return true;
+
+	return false;
+}
+
+static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
+				unsigned int next_freq)
+{
+	struct cpufreq_policy *policy = sg_policy->policy;
+
+	if (sugov_up_down_rate_limit(sg_policy, time, next_freq))
+		return;
+
+	if (policy->fast_switch_enabled) {
+		if (sg_policy->next_freq == next_freq) {
+			trace_cpu_frequency(policy->cur, smp_processor_id());
+			return;
+		}
+		sg_policy->next_freq = next_freq;
+		sg_policy->last_freq_update_time = time;
+		next_freq = cpufreq_driver_fast_switch(policy, next_freq);
+		if (next_freq == CPUFREQ_ENTRY_INVALID)
+			return;
+
+		policy->cur = next_freq;
+		trace_cpu_frequency(next_freq, smp_processor_id());
+	} else if (sg_policy->next_freq != next_freq) {
+		sg_policy->next_freq = next_freq;
+		sg_policy->last_freq_update_time = time;
+		sg_policy->work_in_progress = true;
+		irq_work_queue(&sg_policy->irq_work);
+	}
+}
+
+/**
+ * get_next_freq - Compute a new frequency for a given cpufreq policy.
+ * @sg_cpu: schedutil cpu object to compute the new frequency for.
+ * @util: Current CPU utilization.
+ * @max: CPU capacity.
+ *
+ * If the utilization is frequency-invariant, choose the new frequency to be
+ * proportional to it, that is
+ *
+ * next_freq = C * max_freq * util / max
+ *
+ * Otherwise, approximate the would-be frequency-invariant utilization by
+ * util_raw * (curr_freq / max_freq) which leads to
+ *
+ * next_freq = C * curr_freq * util_raw / max
+ *
+ * Take C = 1.25 for the frequency tipping point at (util / max) = 0.8.
+ *
+ * The lowest driver-supported frequency which is equal or greater than the raw
+ * next_freq (as calculated above) is returned, subject to policy min/max and
+ * cpufreq driver limitations.
+ */
+static unsigned int get_next_freq(struct sugov_cpu *sg_cpu, unsigned long util,
+				  unsigned long max)
+{
+	struct sugov_policy *sg_policy = sg_cpu->sg_policy;
+	struct cpufreq_policy *policy = sg_policy->policy;
+	unsigned int freq = arch_scale_freq_invariant() ?
+				policy->cpuinfo.max_freq : policy->cur;
+
+	freq = (freq + (freq >> 2)) * util / max;
+
+	if (freq == sg_cpu->cached_raw_freq && sg_policy->next_freq != UINT_MAX)
+		return sg_policy->next_freq;
+	sg_cpu->cached_raw_freq = freq;
+	return cpufreq_driver_resolve_freq(policy, freq);
+}
+
+static inline bool use_pelt(void)
+{
+#ifdef CONFIG_SCHED_WALT
+	return (!sysctl_sched_use_walt_cpu_util || walt_disabled);
+#else
+	return true;
+#endif
+}
+
+static void sugov_get_util(unsigned long *util, unsigned long *max, u64 time)
+{
+	int cpu = smp_processor_id();
+	struct rq *rq = cpu_rq(cpu);
+	unsigned long max_cap, rt;
+	s64 delta;
+
+	max_cap = arch_scale_cpu_capacity(NULL, cpu);
+
+	sched_avg_update(rq);
+	delta = time - rq->age_stamp;
+	if (unlikely(delta < 0))
+		delta = 0;
+	rt = div64_u64(rq->rt_avg, sched_avg_period() + delta);
+	rt = (rt * max_cap) >> SCHED_CAPACITY_SHIFT;
+
+	*util = boosted_cpu_util(cpu);
+	if (likely(use_pelt()))
+		*util = min((*util + rt), max_cap);
+
+	*max = max_cap;
+}
+
+static void sugov_set_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,
+				   unsigned int flags)
+{
+	if (flags & SCHED_CPUFREQ_IOWAIT) {
+		sg_cpu->iowait_boost = sg_cpu->iowait_boost_max;
+	} else if (sg_cpu->iowait_boost) {
+		s64 delta_ns = time - sg_cpu->last_update;
+
+		/* Clear iowait_boost if the CPU apprears to have been idle. */
+		if (delta_ns > TICK_NSEC)
+			sg_cpu->iowait_boost = 0;
+	}
+}
+
+static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, unsigned long *util,
+			       unsigned long *max)
+{
+	unsigned long boost_util = sg_cpu->iowait_boost;
+	unsigned long boost_max = sg_cpu->iowait_boost_max;
+
+	if (!boost_util)
+		return;
+
+	if (*util * boost_max < *max * boost_util) {
+		*util = boost_util;
+		*max = boost_max;
+	}
+	sg_cpu->iowait_boost >>= 1;
+}
+
+static void sugov_update_single(struct update_util_data *hook, u64 time,
+				unsigned int flags)
+{
+	struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util);
+	struct sugov_policy *sg_policy = sg_cpu->sg_policy;
+	struct cpufreq_policy *policy = sg_policy->policy;
+	unsigned long util, max;
+	unsigned int next_f;
+
+	sugov_set_iowait_boost(sg_cpu, time, flags);
+	sg_cpu->last_update = time;
+
+	if (!sugov_should_update_freq(sg_policy, time))
+		return;
+
+	if (flags & SCHED_CPUFREQ_DL) {
+		next_f = policy->cpuinfo.max_freq;
+	} else {
+		sugov_get_util(&util, &max, time);
+		sugov_iowait_boost(sg_cpu, &util, &max);
+		next_f = get_next_freq(sg_cpu, util, max);
+	}
+	sugov_update_commit(sg_policy, time, next_f);
+}
+
+static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu,
+					   unsigned long util, unsigned long max,
+					   unsigned int flags)
+{
+	struct sugov_policy *sg_policy = sg_cpu->sg_policy;
+	struct cpufreq_policy *policy = sg_policy->policy;
+	unsigned int max_f = policy->cpuinfo.max_freq;
+	u64 last_freq_update_time = sg_policy->last_freq_update_time;
+	unsigned int j;
+
+	if (flags & SCHED_CPUFREQ_DL)
+		return max_f;
+
+	sugov_iowait_boost(sg_cpu, &util, &max);
+
+	for_each_cpu(j, policy->cpus) {
+		struct sugov_cpu *j_sg_cpu;
+		unsigned long j_util, j_max;
+		s64 delta_ns;
+
+		if (j == smp_processor_id())
+			continue;
+
+		j_sg_cpu = &per_cpu(sugov_cpu, j);
+		/*
+		 * If the CPU utilization was last updated before the previous
+		 * frequency update and the time elapsed between the last update
+		 * of the CPU utilization and the last frequency update is long
+		 * enough, don't take the CPU into account as it probably is
+		 * idle now (and clear iowait_boost for it).
+		 */
+		delta_ns = last_freq_update_time - j_sg_cpu->last_update;
+		if (delta_ns > TICK_NSEC) {
+			j_sg_cpu->iowait_boost = 0;
+			continue;
+		}
+		if (j_sg_cpu->flags & SCHED_CPUFREQ_DL)
+			return max_f;
+
+		j_util = j_sg_cpu->util;
+		j_max = j_sg_cpu->max;
+		if (j_util * max > j_max * util) {
+			util = j_util;
+			max = j_max;
+		}
+
+		sugov_iowait_boost(j_sg_cpu, &util, &max);
+	}
+
+	return get_next_freq(sg_cpu, util, max);
+}
+
+static void sugov_update_shared(struct update_util_data *hook, u64 time,
+				unsigned int flags)
+{
+	struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util);
+	struct sugov_policy *sg_policy = sg_cpu->sg_policy;
+	unsigned long util, max;
+	unsigned int next_f;
+
+	sugov_get_util(&util, &max, time);
+
+	raw_spin_lock(&sg_policy->update_lock);
+
+	sg_cpu->util = util;
+	sg_cpu->max = max;
+	sg_cpu->flags = flags;
+
+	sugov_set_iowait_boost(sg_cpu, time, flags);
+	sg_cpu->last_update = time;
+
+	if (sugov_should_update_freq(sg_policy, time)) {
+		next_f = sugov_next_freq_shared(sg_cpu, util, max, flags);
+		sugov_update_commit(sg_policy, time, next_f);
+	}
+
+	raw_spin_unlock(&sg_policy->update_lock);
+}
+
+static void sugov_work(struct kthread_work *work)
+{
+	struct sugov_policy *sg_policy = container_of(work, struct sugov_policy, work);
+
+	mutex_lock(&sg_policy->work_lock);
+	__cpufreq_driver_target(sg_policy->policy, sg_policy->next_freq,
+				CPUFREQ_RELATION_L);
+	mutex_unlock(&sg_policy->work_lock);
+
+	sg_policy->work_in_progress = false;
+}
+
+static void sugov_irq_work(struct irq_work *irq_work)
+{
+	struct sugov_policy *sg_policy;
+
+	sg_policy = container_of(irq_work, struct sugov_policy, irq_work);
+
+	/*
+	 * For Real Time and Deadline tasks, schedutil governor shoots the
+	 * frequency to maximum. And special care must be taken to ensure that
+	 * this kthread doesn't result in that.
+	 *
+	 * This is (mostly) guaranteed by the work_in_progress flag. The flag is
+	 * updated only at the end of the sugov_work() and before that schedutil
+	 * rejects all other frequency scaling requests.
+	 *
+	 * Though there is a very rare case where the RT thread yields right
+	 * after the work_in_progress flag is cleared. The effects of that are
+	 * neglected for now.
+	 */
+	queue_kthread_work(&sg_policy->worker, &sg_policy->work);
+}
+
+/************************** sysfs interface ************************/
+
+static struct sugov_tunables *global_tunables;
+static DEFINE_MUTEX(global_tunables_lock);
+
+static inline struct sugov_tunables *to_sugov_tunables(struct gov_attr_set *attr_set)
+{
+	return container_of(attr_set, struct sugov_tunables, attr_set);
+}
+
+static DEFINE_MUTEX(min_rate_lock);
+
+static void update_min_rate_limit_us(struct sugov_policy *sg_policy)
+{
+	mutex_lock(&min_rate_lock);
+	sg_policy->min_rate_limit_ns = min(sg_policy->up_rate_delay_ns,
+					   sg_policy->down_rate_delay_ns);
+	mutex_unlock(&min_rate_lock);
+}
+
+static ssize_t up_rate_limit_us_show(struct gov_attr_set *attr_set, char *buf)
+{
+	struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
+
+	return sprintf(buf, "%u\n", tunables->up_rate_limit_us);
+}
+
+static ssize_t down_rate_limit_us_show(struct gov_attr_set *attr_set, char *buf)
+{
+	struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
+
+	return sprintf(buf, "%u\n", tunables->down_rate_limit_us);
+}
+
+static ssize_t up_rate_limit_us_store(struct gov_attr_set *attr_set,
+				      const char *buf, size_t count)
+{
+	struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
+	struct sugov_policy *sg_policy;
+	unsigned int rate_limit_us;
+
+	if (kstrtouint(buf, 10, &rate_limit_us))
+		return -EINVAL;
+
+	tunables->up_rate_limit_us = rate_limit_us;
+
+	list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) {
+		sg_policy->up_rate_delay_ns = rate_limit_us * NSEC_PER_USEC;
+		update_min_rate_limit_us(sg_policy);
+	}
+
+	return count;
+}
+
+static ssize_t down_rate_limit_us_store(struct gov_attr_set *attr_set,
+					const char *buf, size_t count)
+{
+	struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
+	struct sugov_policy *sg_policy;
+	unsigned int rate_limit_us;
+
+	if (kstrtouint(buf, 10, &rate_limit_us))
+		return -EINVAL;
+
+	tunables->down_rate_limit_us = rate_limit_us;
+
+	list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) {
+		sg_policy->down_rate_delay_ns = rate_limit_us * NSEC_PER_USEC;
+		update_min_rate_limit_us(sg_policy);
+	}
+
+	return count;
+}
+
+static struct governor_attr up_rate_limit_us = __ATTR_RW(up_rate_limit_us);
+static struct governor_attr down_rate_limit_us = __ATTR_RW(down_rate_limit_us);
+
+static struct attribute *sugov_attributes[] = {
+	&up_rate_limit_us.attr,
+	&down_rate_limit_us.attr,
+	NULL
+};
+
+static struct kobj_type sugov_tunables_ktype = {
+	.default_attrs = sugov_attributes,
+	.sysfs_ops = &governor_sysfs_ops,
+};
+
+/********************** cpufreq governor interface *********************/
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL
+static
+#endif
+struct cpufreq_governor cpufreq_gov_schedutil;
+
+static struct sugov_policy *sugov_policy_alloc(struct cpufreq_policy *policy)
+{
+	struct sugov_policy *sg_policy;
+
+	sg_policy = kzalloc(sizeof(*sg_policy), GFP_KERNEL);
+	if (!sg_policy)
+		return NULL;
+
+	sg_policy->policy = policy;
+	init_irq_work(&sg_policy->irq_work, sugov_irq_work);
+	mutex_init(&sg_policy->work_lock);
+	raw_spin_lock_init(&sg_policy->update_lock);
+	return sg_policy;
+}
+
+static void sugov_policy_free(struct sugov_policy *sg_policy)
+{
+	mutex_destroy(&sg_policy->work_lock);
+	kfree(sg_policy);
+}
+
+static int sugov_kthread_create(struct sugov_policy *sg_policy)
+{
+	struct task_struct *thread;
+	struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO / 2 };
+	struct cpufreq_policy *policy = sg_policy->policy;
+	int ret;
+
+	/* kthread only required for slow path */
+	if (policy->fast_switch_enabled)
+		return 0;
+
+	init_kthread_work(&sg_policy->work, sugov_work);
+	init_kthread_worker(&sg_policy->worker);
+	thread = kthread_create(kthread_worker_fn, &sg_policy->worker,
+				"sugov:%d",
+				cpumask_first(policy->related_cpus));
+	if (IS_ERR(thread)) {
+		pr_err("failed to create sugov thread: %ld\n", PTR_ERR(thread));
+		return PTR_ERR(thread);
+	}
+
+	ret = sched_setscheduler_nocheck(thread, SCHED_FIFO, &param);
+	if (ret) {
+		kthread_stop(thread);
+		pr_warn("%s: failed to set SCHED_FIFO\n", __func__);
+		return ret;
+	}
+
+	sg_policy->thread = thread;
+	kthread_bind_mask(thread, policy->related_cpus);
+	wake_up_process(thread);
+
+	return 0;
+}
+
+static void sugov_kthread_stop(struct sugov_policy *sg_policy)
+{
+	/* kthread only required for slow path */
+	if (sg_policy->policy->fast_switch_enabled)
+		return;
+
+	flush_kthread_worker(&sg_policy->worker);
+	kthread_stop(sg_policy->thread);
+}
+
+static struct sugov_tunables *sugov_tunables_alloc(struct sugov_policy *sg_policy)
+{
+	struct sugov_tunables *tunables;
+
+	tunables = kzalloc(sizeof(*tunables), GFP_KERNEL);
+	if (tunables) {
+		gov_attr_set_init(&tunables->attr_set, &sg_policy->tunables_hook);
+		if (!have_governor_per_policy())
+			global_tunables = tunables;
+	}
+	return tunables;
+}
+
+static void sugov_tunables_free(struct sugov_tunables *tunables)
+{
+	if (!have_governor_per_policy())
+		global_tunables = NULL;
+
+	kfree(tunables);
+}
+
+static int sugov_init(struct cpufreq_policy *policy)
+{
+	struct sugov_policy *sg_policy;
+	struct sugov_tunables *tunables;
+	unsigned int lat;
+	int ret = 0;
+
+	/* State should be equivalent to EXIT */
+	if (policy->governor_data)
+		return -EBUSY;
+
+	sg_policy = sugov_policy_alloc(policy);
+	if (!sg_policy)
+		return -ENOMEM;
+
+	ret = sugov_kthread_create(sg_policy);
+	if (ret)
+		goto free_sg_policy;
+
+	mutex_lock(&global_tunables_lock);
+
+	if (global_tunables) {
+		if (WARN_ON(have_governor_per_policy())) {
+			ret = -EINVAL;
+			goto stop_kthread;
+		}
+		policy->governor_data = sg_policy;
+		sg_policy->tunables = global_tunables;
+
+		gov_attr_set_get(&global_tunables->attr_set, &sg_policy->tunables_hook);
+		goto out;
+	}
+
+	tunables = sugov_tunables_alloc(sg_policy);
+	if (!tunables) {
+		ret = -ENOMEM;
+		goto stop_kthread;
+	}
+
+	tunables->up_rate_limit_us = LATENCY_MULTIPLIER;
+	tunables->down_rate_limit_us = LATENCY_MULTIPLIER;
+	lat = policy->cpuinfo.transition_latency / NSEC_PER_USEC;
+	if (lat) {
+		tunables->up_rate_limit_us *= lat;
+		tunables->down_rate_limit_us *= lat;
+	}
+
+	policy->governor_data = sg_policy;
+	sg_policy->tunables = tunables;
+
+	ret = kobject_init_and_add(&tunables->attr_set.kobj, &sugov_tunables_ktype,
+				   get_governor_parent_kobj(policy), "%s",
+				   cpufreq_gov_schedutil.name);
+	if (ret)
+		goto fail;
+
+ out:
+	mutex_unlock(&global_tunables_lock);
+
+	cpufreq_enable_fast_switch(policy);
+	return 0;
+
+ fail:
+	policy->governor_data = NULL;
+	sugov_tunables_free(tunables);
+
+stop_kthread:
+	sugov_kthread_stop(sg_policy);
+
+free_sg_policy:
+	mutex_unlock(&global_tunables_lock);
+
+	sugov_policy_free(sg_policy);
+	pr_err("initialization failed (error %d)\n", ret);
+	return ret;
+}
+
+static int sugov_exit(struct cpufreq_policy *policy)
+{
+	struct sugov_policy *sg_policy = policy->governor_data;
+	struct sugov_tunables *tunables = sg_policy->tunables;
+	unsigned int count;
+
+	cpufreq_disable_fast_switch(policy);
+
+	mutex_lock(&global_tunables_lock);
+
+	count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook);
+	policy->governor_data = NULL;
+	if (!count)
+		sugov_tunables_free(tunables);
+
+	mutex_unlock(&global_tunables_lock);
+
+	sugov_kthread_stop(sg_policy);
+	sugov_policy_free(sg_policy);
+
+	return 0;
+}
+
+static int sugov_start(struct cpufreq_policy *policy)
+{
+	struct sugov_policy *sg_policy = policy->governor_data;
+	unsigned int cpu;
+
+	sg_policy->up_rate_delay_ns =
+		sg_policy->tunables->up_rate_limit_us * NSEC_PER_USEC;
+	sg_policy->down_rate_delay_ns =
+		sg_policy->tunables->down_rate_limit_us * NSEC_PER_USEC;
+	update_min_rate_limit_us(sg_policy);
+	sg_policy->last_freq_update_time = 0;
+	sg_policy->next_freq = UINT_MAX;
+	sg_policy->work_in_progress = false;
+	sg_policy->need_freq_update = false;
+
+	for_each_cpu(cpu, policy->cpus) {
+		struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
+
+		sg_cpu->sg_policy = sg_policy;
+		if (policy_is_shared(policy)) {
+			sg_cpu->util = 0;
+			sg_cpu->max = 0;
+			sg_cpu->flags = SCHED_CPUFREQ_DL;
+			sg_cpu->last_update = 0;
+			sg_cpu->cached_raw_freq = 0;
+			sg_cpu->iowait_boost = 0;
+			sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq;
+			cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
+						     sugov_update_shared);
+		} else {
+			cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
+						     sugov_update_single);
+		}
+	}
+	return 0;
+}
+
+static int sugov_stop(struct cpufreq_policy *policy)
+{
+	struct sugov_policy *sg_policy = policy->governor_data;
+	unsigned int cpu;
+
+	for_each_cpu(cpu, policy->cpus)
+		cpufreq_remove_update_util_hook(cpu);
+
+	synchronize_sched();
+
+	irq_work_sync(&sg_policy->irq_work);
+	kthread_cancel_work_sync(&sg_policy->work);
+
+	return 0;
+}
+
+static int sugov_limits(struct cpufreq_policy *policy)
+{
+	struct sugov_policy *sg_policy = policy->governor_data;
+
+	if (!policy->fast_switch_enabled) {
+		mutex_lock(&sg_policy->work_lock);
+		cpufreq_policy_apply_limits(policy);
+		mutex_unlock(&sg_policy->work_lock);
+	}
+
+	sg_policy->need_freq_update = true;
+
+	return 0;
+}
+
+static int cpufreq_schedutil_cb(struct cpufreq_policy *policy,
+				unsigned int event)
+{
+	switch(event) {
+	case CPUFREQ_GOV_POLICY_INIT:
+		return sugov_init(policy);
+	case CPUFREQ_GOV_POLICY_EXIT:
+		return sugov_exit(policy);
+	case CPUFREQ_GOV_START:
+		return sugov_start(policy);
+	case CPUFREQ_GOV_STOP:
+		return sugov_stop(policy);
+	case CPUFREQ_GOV_LIMITS:
+		return sugov_limits(policy);
+	default:
+		BUG();
+	}
+}
+
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL
+static
+#endif
+struct cpufreq_governor cpufreq_gov_schedutil = {
+	.name = "schedutil",
+	.governor = cpufreq_schedutil_cb,
+	.owner = THIS_MODULE,
+};
+
+static int __init sugov_register(void)
+{
+	return cpufreq_register_governor(&cpufreq_gov_schedutil);
+}
+fs_initcall(sugov_register);
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index f74ea89..acde1d7 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -5,6 +5,7 @@
 #include <linux/static_key.h>
 #include <linux/context_tracking.h>
 #include "sched.h"
+#include "walt.h"
 
 
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
@@ -49,6 +50,10 @@
 	unsigned long flags;
 	s64 delta;
 	int cpu;
+#ifdef CONFIG_SCHED_WALT
+	u64 wallclock;
+	bool account = true;
+#endif
 
 	if (!sched_clock_irqtime)
 		return;
@@ -56,6 +61,9 @@
 	local_irq_save(flags);
 
 	cpu = smp_processor_id();
+#ifdef CONFIG_SCHED_WALT
+	wallclock = sched_clock_cpu(cpu);
+#endif
 	delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time);
 	__this_cpu_add(irq_start_time, delta);
 
@@ -70,8 +78,16 @@
 		__this_cpu_add(cpu_hardirq_time, delta);
 	else if (in_serving_softirq() && curr != this_cpu_ksoftirqd())
 		__this_cpu_add(cpu_softirq_time, delta);
+#ifdef CONFIG_SCHED_WALT
+	else
+		account = false;
+#endif
 
 	irq_time_write_end();
+#ifdef CONFIG_SCHED_WALT
+	if (account)
+		walt_account_irqtime(cpu, curr, delta, wallclock);
+#endif
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(irqtime_account_irq);
@@ -600,19 +616,25 @@
 	stime = curr->stime;
 	utime = curr->utime;
 
-	if (utime == 0) {
-		stime = rtime;
+	/*
+	 * If either stime or both stime and utime are 0, assume all runtime is
+	 * userspace. Once a task gets some ticks, the monotonicy code at
+	 * 'update' will ensure things converge to the observed ratio.
+	 */
+	if (stime == 0) {
+		utime = rtime;
 		goto update;
 	}
 
-	if (stime == 0) {
-		utime = rtime;
+	if (utime == 0) {
+		stime = rtime;
 		goto update;
 	}
 
 	stime = scale_stime((__force u64)stime, (__force u64)rtime,
 			    (__force u64)(stime + utime));
 
+update:
 	/*
 	 * Make sure stime doesn't go backwards; this preserves monotonicity
 	 * for utime because rtime is monotonic.
@@ -635,7 +657,6 @@
 		stime = rtime - utime;
 	}
 
-update:
 	prev->stime = stime;
 	prev->utime = utime;
 out:
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 8b0a15e..9ec7f19 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -43,6 +43,24 @@
 	return !RB_EMPTY_NODE(&dl_se->rb_node);
 }
 
+static void add_average_bw(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
+{
+	u64 se_bw = dl_se->dl_bw;
+
+	dl_rq->avg_bw += se_bw;
+}
+
+static void clear_average_bw(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
+{
+	u64 se_bw = dl_se->dl_bw;
+
+	dl_rq->avg_bw -= se_bw;
+	if (dl_rq->avg_bw < 0) {
+		WARN_ON(1);
+		dl_rq->avg_bw = 0;
+	}
+}
+
 static inline int is_leftmost(struct task_struct *p, struct dl_rq *dl_rq)
 {
 	struct sched_dl_entity *dl_se = &p->dl;
@@ -494,6 +512,9 @@
 	struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
 	struct rq *rq = rq_of_dl_rq(dl_rq);
 
+	if (dl_se->dl_new)
+		add_average_bw(dl_se, dl_rq);
+
 	/*
 	 * The arrival of a new instance needs special treatment, i.e.,
 	 * the actual scheduling parameters have to be "renewed".
@@ -732,6 +753,9 @@
 	if (unlikely((s64)delta_exec <= 0))
 		return;
 
+	/* kick cpufreq (see the comment in kernel/sched/sched.h). */
+	cpufreq_update_this_cpu(rq, SCHED_CPUFREQ_DL);
+
 	schedstat_set(curr->se.statistics.exec_max,
 		      max(curr->se.statistics.exec_max, delta_exec));
 
@@ -741,8 +765,6 @@
 	curr->se.exec_start = rq_clock_task(rq);
 	cpuacct_charge(curr, delta_exec);
 
-	sched_rt_avg_update(rq, delta_exec);
-
 	dl_se->runtime -= dl_se->dl_yielded ? 0 : delta_exec;
 	if (dl_runtime_exceeded(dl_se)) {
 		dl_se->dl_throttled = 1;
@@ -1241,6 +1263,8 @@
 static void task_dead_dl(struct task_struct *p)
 {
 	struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
+	struct dl_rq *dl_rq = dl_rq_of_se(&p->dl);
+	struct rq *rq = rq_of_dl_rq(dl_rq);
 
 	/*
 	 * Since we are TASK_DEAD we won't slip out of the domain!
@@ -1249,6 +1273,8 @@
 	/* XXX we should retain the bw until 0-lag */
 	dl_b->total_bw -= p->dl.dl_bw;
 	raw_spin_unlock_irq(&dl_b->lock);
+
+	clear_average_bw(&p->dl, &rq->dl);
 }
 
 static void set_curr_task_dl(struct rq *rq)
@@ -1556,7 +1582,9 @@
 	}
 
 	deactivate_task(rq, next_task, 0);
+	clear_average_bw(&next_task->dl, &rq->dl);
 	set_task_cpu(next_task, later_rq->cpu);
+	add_average_bw(&next_task->dl, &later_rq->dl);
 	activate_task(later_rq, next_task, 0);
 	ret = 1;
 
@@ -1644,7 +1672,9 @@
 			resched = true;
 
 			deactivate_task(src_rq, p, 0);
+			clear_average_bw(&p->dl, &src_rq->dl);
 			set_task_cpu(p, this_cpu);
+			add_average_bw(&p->dl, &this_rq->dl);
 			activate_task(this_rq, p, 0);
 			dmin = p->dl.deadline;
 
@@ -1750,6 +1780,8 @@
 	if (!start_dl_timer(p))
 		__dl_clear_params(p);
 
+	clear_average_bw(&p->dl, &rq->dl);
+
 	/*
 	 * Since this might be the only -deadline task on the rq,
 	 * this is the right place to try to pull some other one
@@ -1771,12 +1803,11 @@
 #ifdef CONFIG_SMP
 		if (p->nr_cpus_allowed > 1 && rq->dl.overloaded)
 			queue_push_tasks(rq);
-#else
+#endif
 		if (dl_task(rq->curr))
 			check_preempt_curr_dl(rq, p, 0);
 		else
 			resched_curr(rq);
-#endif
 	}
 }
 
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index 6415117..7f71166 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -597,6 +597,32 @@
 	P(se.statistics.nr_wakeups_affine_attempts);
 	P(se.statistics.nr_wakeups_passive);
 	P(se.statistics.nr_wakeups_idle);
+	/* eas */
+	/* select_idle_sibling() */
+	P(se.statistics.nr_wakeups_sis_attempts);
+	P(se.statistics.nr_wakeups_sis_idle);
+	P(se.statistics.nr_wakeups_sis_cache_affine);
+	P(se.statistics.nr_wakeups_sis_suff_cap);
+	P(se.statistics.nr_wakeups_sis_idle_cpu);
+	P(se.statistics.nr_wakeups_sis_count);
+	/* select_energy_cpu_brute() */
+	P(se.statistics.nr_wakeups_secb_attempts);
+	P(se.statistics.nr_wakeups_secb_sync);
+	P(se.statistics.nr_wakeups_secb_idle_bt);
+	P(se.statistics.nr_wakeups_secb_insuff_cap);
+	P(se.statistics.nr_wakeups_secb_no_nrg_sav);
+	P(se.statistics.nr_wakeups_secb_nrg_sav);
+	P(se.statistics.nr_wakeups_secb_count);
+	/* find_best_target() */
+	P(se.statistics.nr_wakeups_fbt_attempts);
+	P(se.statistics.nr_wakeups_fbt_no_cpu);
+	P(se.statistics.nr_wakeups_fbt_no_sd);
+	P(se.statistics.nr_wakeups_fbt_pref_idle);
+	P(se.statistics.nr_wakeups_fbt_count);
+	/* cas */
+	/* select_task_rq_fair() */
+	P(se.statistics.nr_wakeups_cas_attempts);
+	P(se.statistics.nr_wakeups_cas_count);
 
 	{
 		u64 avg_atom, avg_per_cpu;
diff --git a/kernel/sched/energy.c b/kernel/sched/energy.c
new file mode 100644
index 0000000..b0656b7
--- /dev/null
+++ b/kernel/sched/energy.c
@@ -0,0 +1,124 @@
+/*
+ * Obtain energy cost data from DT and populate relevant scheduler data
+ * structures.
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#define pr_fmt(fmt) "sched-energy: " fmt
+
+#define DEBUG
+
+#include <linux/gfp.h>
+#include <linux/of.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <linux/sched_energy.h>
+#include <linux/stddef.h>
+
+struct sched_group_energy *sge_array[NR_CPUS][NR_SD_LEVELS];
+
+static void free_resources(void)
+{
+	int cpu, sd_level;
+	struct sched_group_energy *sge;
+
+	for_each_possible_cpu(cpu) {
+		for_each_possible_sd_level(sd_level) {
+			sge = sge_array[cpu][sd_level];
+			if (sge) {
+				kfree(sge->cap_states);
+				kfree(sge->idle_states);
+				kfree(sge);
+			}
+		}
+	}
+}
+
+void init_sched_energy_costs(void)
+{
+	struct device_node *cn, *cp;
+	struct capacity_state *cap_states;
+	struct idle_state *idle_states;
+	struct sched_group_energy *sge;
+	const struct property *prop;
+	int sd_level, i, nstates, cpu;
+	const __be32 *val;
+
+	for_each_possible_cpu(cpu) {
+		cn = of_get_cpu_node(cpu, NULL);
+		if (!cn) {
+			pr_warn("CPU device node missing for CPU %d\n", cpu);
+			return;
+		}
+
+		if (!of_find_property(cn, "sched-energy-costs", NULL)) {
+			pr_warn("CPU device node has no sched-energy-costs\n");
+			return;
+		}
+
+		for_each_possible_sd_level(sd_level) {
+			cp = of_parse_phandle(cn, "sched-energy-costs", sd_level);
+			if (!cp)
+				break;
+
+			prop = of_find_property(cp, "busy-cost-data", NULL);
+			if (!prop || !prop->value) {
+				pr_warn("No busy-cost data, skipping sched_energy init\n");
+				goto out;
+			}
+
+			sge = kcalloc(1, sizeof(struct sched_group_energy),
+				      GFP_NOWAIT);
+
+			nstates = (prop->length / sizeof(u32)) / 2;
+			cap_states = kcalloc(nstates,
+					     sizeof(struct capacity_state),
+					     GFP_NOWAIT);
+
+			for (i = 0, val = prop->value; i < nstates; i++) {
+				cap_states[i].cap = be32_to_cpup(val++);
+				cap_states[i].power = be32_to_cpup(val++);
+			}
+
+			sge->nr_cap_states = nstates;
+			sge->cap_states = cap_states;
+
+			prop = of_find_property(cp, "idle-cost-data", NULL);
+			if (!prop || !prop->value) {
+				pr_warn("No idle-cost data, skipping sched_energy init\n");
+				goto out;
+			}
+
+			nstates = (prop->length / sizeof(u32));
+			idle_states = kcalloc(nstates,
+					      sizeof(struct idle_state),
+					      GFP_NOWAIT);
+
+			for (i = 0, val = prop->value; i < nstates; i++)
+				idle_states[i].power = be32_to_cpup(val++);
+
+			sge->nr_idle_states = nstates;
+			sge->idle_states = idle_states;
+
+			sge_array[cpu][sd_level] = sge;
+		}
+	}
+
+	pr_info("Sched-energy-costs installed from DT\n");
+	return;
+
+out:
+	free_resources();
+}
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index ba24bfe..226d199 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -30,10 +30,13 @@
 #include <linux/mempolicy.h>
 #include <linux/migrate.h>
 #include <linux/task_work.h>
+#include <linux/module.h>
 
 #include <trace/events/sched.h>
 
 #include "sched.h"
+#include "tune.h"
+#include "walt.h"
 
 /*
  * Targeted preemption latency for CPU-bound tasks:
@@ -50,6 +53,16 @@
 unsigned int sysctl_sched_latency = 6000000ULL;
 unsigned int normalized_sysctl_sched_latency = 6000000ULL;
 
+unsigned int sysctl_sched_sync_hint_enable = 1;
+unsigned int sysctl_sched_initial_task_util = 0;
+unsigned int sysctl_sched_cstate_aware = 1;
+
+#ifdef CONFIG_SCHED_WALT
+unsigned int sysctl_sched_use_walt_cpu_util = 1;
+unsigned int sysctl_sched_use_walt_task_util = 1;
+__read_mostly unsigned int sysctl_sched_walt_cpu_high_irqload =
+    (10 * NSEC_PER_MSEC);
+#endif
 /*
  * The initial- and re-scaling of tunables is configurable
  * (default SCHED_TUNABLESCALING_LOG = *(1+ilog(ncpus))
@@ -114,6 +127,12 @@
 unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL;
 #endif
 
+/*
+ * The margin used when comparing utilization with CPU capacity:
+ * util * margin < capacity * 1024
+ */
+unsigned int capacity_margin = 1280; /* ~20% */
+
 static inline void update_load_add(struct load_weight *lw, unsigned long inc)
 {
 	lw->weight += inc;
@@ -286,19 +305,59 @@
 static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
 {
 	if (!cfs_rq->on_list) {
+		struct rq *rq = rq_of(cfs_rq);
+		int cpu = cpu_of(rq);
 		/*
 		 * Ensure we either appear before our parent (if already
 		 * enqueued) or force our parent to appear after us when it is
-		 * enqueued.  The fact that we always enqueue bottom-up
-		 * reduces this to two cases.
+		 * enqueued. The fact that we always enqueue bottom-up
+		 * reduces this to two cases and a special case for the root
+		 * cfs_rq. Furthermore, it also means that we will always reset
+		 * tmp_alone_branch either when the branch is connected
+		 * to a tree or when we reach the beg of the tree
 		 */
 		if (cfs_rq->tg->parent &&
-		    cfs_rq->tg->parent->cfs_rq[cpu_of(rq_of(cfs_rq))]->on_list) {
-			list_add_rcu(&cfs_rq->leaf_cfs_rq_list,
-				&rq_of(cfs_rq)->leaf_cfs_rq_list);
-		} else {
+		    cfs_rq->tg->parent->cfs_rq[cpu]->on_list) {
+			/*
+			 * If parent is already on the list, we add the child
+			 * just before. Thanks to circular linked property of
+			 * the list, this means to put the child at the tail
+			 * of the list that starts by parent.
+			 */
 			list_add_tail_rcu(&cfs_rq->leaf_cfs_rq_list,
-				&rq_of(cfs_rq)->leaf_cfs_rq_list);
+				&(cfs_rq->tg->parent->cfs_rq[cpu]->leaf_cfs_rq_list));
+			/*
+			 * The branch is now connected to its tree so we can
+			 * reset tmp_alone_branch to the beginning of the
+			 * list.
+			 */
+			rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
+		} else if (!cfs_rq->tg->parent) {
+			/*
+			 * cfs rq without parent should be put
+			 * at the tail of the list.
+			 */
+			list_add_tail_rcu(&cfs_rq->leaf_cfs_rq_list,
+				&rq->leaf_cfs_rq_list);
+			/*
+			 * We have reach the beg of a tree so we can reset
+			 * tmp_alone_branch to the beginning of the list.
+			 */
+			rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
+		} else {
+			/*
+			 * The parent has not already been added so we want to
+			 * make sure that it will be put after us.
+			 * tmp_alone_branch points to the beg of the branch
+			 * where we will add parent.
+			 */
+			list_add_rcu(&cfs_rq->leaf_cfs_rq_list,
+				rq->tmp_alone_branch);
+			/*
+			 * update tmp_alone_branch to points to the new beg
+			 * of the branch
+			 */
+			rq->tmp_alone_branch = &cfs_rq->leaf_cfs_rq_list;
 		}
 
 		cfs_rq->on_list = 1;
@@ -656,7 +715,7 @@
 }
 
 #ifdef CONFIG_SMP
-static int select_idle_sibling(struct task_struct *p, int cpu);
+static int select_idle_sibling(struct task_struct *p, int prev_cpu, int cpu);
 static unsigned long task_h_load(struct task_struct *p);
 
 /*
@@ -680,20 +739,115 @@
 	 * will definitely be update (after enqueue).
 	 */
 	sa->period_contrib = 1023;
-	sa->load_avg = scale_load_down(se->load.weight);
+	/*
+	 * Tasks are intialized with full load to be seen as heavy tasks until
+	 * they get a chance to stabilize to their real load level.
+	 * Group entities are intialized with zero load to reflect the fact that
+	 * nothing has been attached to the task group yet.
+	 */
+	if (entity_is_task(se))
+		sa->load_avg = scale_load_down(se->load.weight);
 	sa->load_sum = sa->load_avg * LOAD_AVG_MAX;
-	sa->util_avg = scale_load_down(SCHED_LOAD_SCALE);
-	sa->util_sum = sa->util_avg * LOAD_AVG_MAX;
+	/*
+	 * In previous Android versions, we used to have:
+	 * 	sa->util_avg =  sched_freq() ?
+	 * 		sysctl_sched_initial_task_util :
+	 *		scale_load_down(SCHED_LOAD_SCALE);
+	 * 	sa->util_sum = sa->util_avg * LOAD_AVG_MAX;
+	 * However, that functionality has been moved to enqueue.
+	 * It is unclear if we should restore this in enqueue.
+	 */
+	/*
+	 * At this point, util_avg won't be used in select_task_rq_fair anyway
+	 */
+	sa->util_avg = 0;
+	sa->util_sum = 0;
 	/* when this task enqueue'ed, it will contribute to its cfs_rq's load_avg */
 }
 
-static inline unsigned long cfs_rq_runnable_load_avg(struct cfs_rq *cfs_rq);
-static inline unsigned long cfs_rq_load_avg(struct cfs_rq *cfs_rq);
+static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq);
+static void attach_entity_cfs_rq(struct sched_entity *se);
+
+/*
+ * With new tasks being created, their initial util_avgs are extrapolated
+ * based on the cfs_rq's current util_avg:
+ *
+ *   util_avg = cfs_rq->util_avg / (cfs_rq->load_avg + 1) * se.load.weight
+ *
+ * However, in many cases, the above util_avg does not give a desired
+ * value. Moreover, the sum of the util_avgs may be divergent, such
+ * as when the series is a harmonic series.
+ *
+ * To solve this problem, we also cap the util_avg of successive tasks to
+ * only 1/2 of the left utilization budget:
+ *
+ *   util_avg_cap = (1024 - cfs_rq->avg.util_avg) / 2^n
+ *
+ * where n denotes the nth task.
+ *
+ * For example, a simplest series from the beginning would be like:
+ *
+ *  task  util_avg: 512, 256, 128,  64,  32,   16,    8, ...
+ * cfs_rq util_avg: 512, 768, 896, 960, 992, 1008, 1016, ...
+ *
+ * Finally, that extrapolated util_avg is clamped to the cap (util_avg_cap)
+ * if util_avg > util_avg_cap.
+ */
+void post_init_entity_util_avg(struct sched_entity *se)
+{
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+	struct sched_avg *sa = &se->avg;
+	long cap = (long)(SCHED_CAPACITY_SCALE - cfs_rq->avg.util_avg) / 2;
+
+	if (cap > 0) {
+		if (cfs_rq->avg.util_avg != 0) {
+			sa->util_avg  = cfs_rq->avg.util_avg * se->load.weight;
+			sa->util_avg /= (cfs_rq->avg.load_avg + 1);
+
+			if (sa->util_avg > cap)
+				sa->util_avg = cap;
+		} else {
+			sa->util_avg = cap;
+		}
+		/*
+		 * If we wish to restore tuning via setting initial util,
+		 * this is where we should do it.
+		 */
+		sa->util_sum = sa->util_avg * LOAD_AVG_MAX;
+	}
+
+	if (entity_is_task(se)) {
+		struct task_struct *p = task_of(se);
+		if (p->sched_class != &fair_sched_class) {
+			/*
+			 * For !fair tasks do:
+			 *
+			update_cfs_rq_load_avg(now, cfs_rq, false);
+			attach_entity_load_avg(cfs_rq, se);
+			switched_from_fair(rq, p);
+			 *
+			 * such that the next switched_to_fair() has the
+			 * expected state.
+			 */
+			se->avg.last_update_time = cfs_rq_clock_task(cfs_rq);
+			return;
+		}
+	}
+
+	attach_entity_cfs_rq(se);
+}
+
 #else
 void init_entity_runnable_average(struct sched_entity *se)
 {
 }
-#endif
+void post_init_entity_util_avg(struct sched_entity *se)
+{
+}
+static void update_tg_load_avg(struct cfs_rq *cfs_rq, int force)
+{
+}
+#endif /* CONFIG_SMP */
 
 /*
  * Update the current task's runtime statistics.
@@ -1193,8 +1347,6 @@
 {
 	if (env->best_task)
 		put_task_struct(env->best_task);
-	if (p)
-		get_task_struct(p);
 
 	env->best_task = p;
 	env->best_imp = imp;
@@ -1262,20 +1414,30 @@
 	long imp = env->p->numa_group ? groupimp : taskimp;
 	long moveimp = imp;
 	int dist = env->dist;
+	bool assigned = false;
 
 	rcu_read_lock();
 
 	raw_spin_lock_irq(&dst_rq->lock);
 	cur = dst_rq->curr;
 	/*
-	 * No need to move the exiting task, and this ensures that ->curr
-	 * wasn't reaped and thus get_task_struct() in task_numa_assign()
-	 * is safe under RCU read lock.
-	 * Note that rcu_read_lock() itself can't protect from the final
-	 * put_task_struct() after the last schedule().
+	 * No need to move the exiting task or idle task.
 	 */
 	if ((cur->flags & PF_EXITING) || is_idle_task(cur))
 		cur = NULL;
+	else {
+		/*
+		 * The task_struct must be protected here to protect the
+		 * p->numa_faults access in the task_weight since the
+		 * numa_faults could already be freed in the following path:
+		 * finish_task_switch()
+		 *     --> put_task_struct()
+		 *         --> __put_task_struct()
+		 *             --> task_numa_free()
+		 */
+		get_task_struct(cur);
+	}
+
 	raw_spin_unlock_irq(&dst_rq->lock);
 
 	/*
@@ -1359,6 +1521,7 @@
 		 */
 		if (!load_too_imbalanced(src_load, dst_load, env)) {
 			imp = moveimp - 1;
+			put_task_struct(cur);
 			cur = NULL;
 			goto assign;
 		}
@@ -1381,12 +1544,20 @@
 	 * Call select_idle_sibling to maybe find a better one.
 	 */
 	if (!cur)
-		env->dst_cpu = select_idle_sibling(env->p, env->dst_cpu);
+		env->dst_cpu = select_idle_sibling(env->p, env->src_cpu,
+						   env->dst_cpu);
 
 assign:
+	assigned = true;
 	task_numa_assign(env, cur, imp);
 unlock:
 	rcu_read_unlock();
+	/*
+	 * The dst_rq->curr isn't assigned. The protection for task_struct is
+	 * finished.
+	 */
+	if (cur && !assigned)
+		put_task_struct(cur);
 }
 
 static void task_numa_find_cpu(struct task_numa_env *env,
@@ -2359,28 +2530,22 @@
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 # ifdef CONFIG_SMP
-static inline long calc_tg_weight(struct task_group *tg, struct cfs_rq *cfs_rq)
-{
-	long tg_weight;
-
-	/*
-	 * Use this CPU's real-time load instead of the last load contribution
-	 * as the updating of the contribution is delayed, and we will use the
-	 * the real-time load to calc the share. See update_tg_load_avg().
-	 */
-	tg_weight = atomic_long_read(&tg->load_avg);
-	tg_weight -= cfs_rq->tg_load_avg_contrib;
-	tg_weight += cfs_rq->load.weight;
-
-	return tg_weight;
-}
-
 static long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
 {
 	long tg_weight, load, shares;
 
-	tg_weight = calc_tg_weight(tg, cfs_rq);
-	load = cfs_rq->load.weight;
+	/*
+	 * This really should be: cfs_rq->avg.load_avg, but instead we use
+	 * cfs_rq->load.weight, which is its upper bound. This helps ramp up
+	 * the shares for small weight interactive tasks.
+	 */
+	load = scale_load_down(cfs_rq->load.weight);
+
+	tg_weight = atomic_long_read(&tg->load_avg);
+
+	/* Ensure tg_weight >= load */
+	tg_weight -= cfs_rq->tg_load_avg_contrib;
+	tg_weight += load;
 
 	shares = (tg->shares * load);
 	if (tg_weight)
@@ -2399,6 +2564,7 @@
 	return tg->shares;
 }
 # endif /* CONFIG_SMP */
+
 static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
 			    unsigned long weight)
 {
@@ -2417,16 +2583,20 @@
 
 static inline int throttled_hierarchy(struct cfs_rq *cfs_rq);
 
-static void update_cfs_shares(struct cfs_rq *cfs_rq)
+static void update_cfs_shares(struct sched_entity *se)
 {
+	struct cfs_rq *cfs_rq = group_cfs_rq(se);
 	struct task_group *tg;
-	struct sched_entity *se;
 	long shares;
 
-	tg = cfs_rq->tg;
-	se = tg->se[cpu_of(rq_of(cfs_rq))];
-	if (!se || throttled_hierarchy(cfs_rq))
+	if (!cfs_rq)
 		return;
+
+	if (throttled_hierarchy(cfs_rq))
+		return;
+
+	tg = cfs_rq->tg;
+
 #ifndef CONFIG_SMP
 	if (likely(se->load.weight == tg->shares))
 		return;
@@ -2435,8 +2605,9 @@
 
 	reweight_entity(cfs_rq_of(se), se, shares);
 }
+
 #else /* CONFIG_FAIR_GROUP_SCHED */
-static inline void update_cfs_shares(struct cfs_rq *cfs_rq)
+static inline void update_cfs_shares(struct sched_entity *se)
 {
 }
 #endif /* CONFIG_FAIR_GROUP_SCHED */
@@ -2586,6 +2757,7 @@
 
 	scale_freq = arch_scale_freq_capacity(NULL, cpu);
 	scale_cpu = arch_scale_cpu_capacity(NULL, cpu);
+	trace_sched_contrib_scale_f(cpu, scale_freq, scale_cpu);
 
 	/* delta_w is the amount already accumulated against our next period */
 	delta_w = sa->period_contrib;
@@ -2661,44 +2833,318 @@
 	return decayed;
 }
 
-#ifdef CONFIG_FAIR_GROUP_SCHED
 /*
- * Updating tg's load_avg is necessary before update_cfs_share (which is done)
- * and effective_load (which is not done because it is too costly).
+ * Signed add and clamp on underflow.
+ *
+ * Explicitly do a load-store to ensure the intermediate value never hits
+ * memory. This allows lockless observations without ever seeing the negative
+ * values.
+ */
+#define add_positive(_ptr, _val) do {                           \
+	typeof(_ptr) ptr = (_ptr);                              \
+	typeof(_val) val = (_val);                              \
+	typeof(*ptr) res, var = READ_ONCE(*ptr);                \
+								\
+	res = var + val;                                        \
+								\
+	if (val < 0 && res > var)                               \
+		res = 0;                                        \
+								\
+	WRITE_ONCE(*ptr, res);                                  \
+} while (0)
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/**
+ * update_tg_load_avg - update the tg's load avg
+ * @cfs_rq: the cfs_rq whose avg changed
+ * @force: update regardless of how small the difference
+ *
+ * This function 'ensures': tg->load_avg := \Sum tg->cfs_rq[]->avg.load.
+ * However, because tg->load_avg is a global value there are performance
+ * considerations.
+ *
+ * In order to avoid having to look at the other cfs_rq's, we use a
+ * differential update where we store the last value we propagated. This in
+ * turn allows skipping updates if the differential is 'small'.
+ *
+ * Updating tg's load_avg is necessary before update_cfs_share() (which is
+ * done) and effective_load() (which is not done because it is too costly).
  */
 static inline void update_tg_load_avg(struct cfs_rq *cfs_rq, int force)
 {
 	long delta = cfs_rq->avg.load_avg - cfs_rq->tg_load_avg_contrib;
 
+	/*
+	 * No need to update load_avg for root_task_group as it is not used.
+	 */
+	if (cfs_rq->tg == &root_task_group)
+		return;
+
 	if (force || abs(delta) > cfs_rq->tg_load_avg_contrib / 64) {
 		atomic_long_add(delta, &cfs_rq->tg->load_avg);
 		cfs_rq->tg_load_avg_contrib = cfs_rq->avg.load_avg;
 	}
 }
 
+/*
+ * Called within set_task_rq() right before setting a task's cpu. The
+ * caller only guarantees p->pi_lock is held; no other assumptions,
+ * including the state of rq->lock, should be made.
+ */
+void set_task_rq_fair(struct sched_entity *se,
+		      struct cfs_rq *prev, struct cfs_rq *next)
+{
+	if (!sched_feat(ATTACH_AGE_LOAD))
+		return;
+
+	/*
+	 * We are supposed to update the task to "current" time, then its up to
+	 * date and ready to go to new CPU/cfs_rq. But we have difficulty in
+	 * getting what current time is, so simply throw away the out-of-date
+	 * time. This will result in the wakee task is less decayed, but giving
+	 * the wakee more load sounds not bad.
+	 */
+	if (se->avg.last_update_time && prev) {
+		u64 p_last_update_time;
+		u64 n_last_update_time;
+
+#ifndef CONFIG_64BIT
+		u64 p_last_update_time_copy;
+		u64 n_last_update_time_copy;
+
+		do {
+			p_last_update_time_copy = prev->load_last_update_time_copy;
+			n_last_update_time_copy = next->load_last_update_time_copy;
+
+			smp_rmb();
+
+			p_last_update_time = prev->avg.last_update_time;
+			n_last_update_time = next->avg.last_update_time;
+
+		} while (p_last_update_time != p_last_update_time_copy ||
+			 n_last_update_time != n_last_update_time_copy);
+#else
+		p_last_update_time = prev->avg.last_update_time;
+		n_last_update_time = next->avg.last_update_time;
+#endif
+		__update_load_avg(p_last_update_time, cpu_of(rq_of(prev)),
+				  &se->avg, 0, 0, NULL);
+		se->avg.last_update_time = n_last_update_time;
+	}
+}
+
+/* Take into account change of utilization of a child task group */
+static inline void
+update_tg_cfs_util(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	struct cfs_rq *gcfs_rq = group_cfs_rq(se);
+	long delta = gcfs_rq->avg.util_avg - se->avg.util_avg;
+
+	/* Nothing to update */
+	if (!delta)
+		return;
+
+	/* Set new sched_entity's utilization */
+	se->avg.util_avg = gcfs_rq->avg.util_avg;
+	se->avg.util_sum = se->avg.util_avg * LOAD_AVG_MAX;
+
+	/* Update parent cfs_rq utilization */
+	add_positive(&cfs_rq->avg.util_avg, delta);
+	cfs_rq->avg.util_sum = cfs_rq->avg.util_avg * LOAD_AVG_MAX;
+}
+
+/* Take into account change of load of a child task group */
+static inline void
+update_tg_cfs_load(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	struct cfs_rq *gcfs_rq = group_cfs_rq(se);
+	long delta, load = gcfs_rq->avg.load_avg;
+
+	/*
+	 * If the load of group cfs_rq is null, the load of the
+	 * sched_entity will also be null so we can skip the formula
+	 */
+	if (load) {
+		long tg_load;
+
+		/* Get tg's load and ensure tg_load > 0 */
+		tg_load = atomic_long_read(&gcfs_rq->tg->load_avg) + 1;
+
+		/* Ensure tg_load >= load and updated with current load*/
+		tg_load -= gcfs_rq->tg_load_avg_contrib;
+		tg_load += load;
+
+		/*
+		 * We need to compute a correction term in the case that the
+		 * task group is consuming more CPU than a task of equal
+		 * weight. A task with a weight equals to tg->shares will have
+		 * a load less or equal to scale_load_down(tg->shares).
+		 * Similarly, the sched_entities that represent the task group
+		 * at parent level, can't have a load higher than
+		 * scale_load_down(tg->shares). And the Sum of sched_entities'
+		 * load must be <= scale_load_down(tg->shares).
+		 */
+		if (tg_load > scale_load_down(gcfs_rq->tg->shares)) {
+			/* scale gcfs_rq's load into tg's shares*/
+			load *= scale_load_down(gcfs_rq->tg->shares);
+			load /= tg_load;
+		}
+	}
+
+	delta = load - se->avg.load_avg;
+
+	/* Nothing to update */
+	if (!delta)
+		return;
+
+	/* Set new sched_entity's load */
+	se->avg.load_avg = load;
+	se->avg.load_sum = se->avg.load_avg * LOAD_AVG_MAX;
+
+	/* Update parent cfs_rq load */
+	add_positive(&cfs_rq->avg.load_avg, delta);
+	cfs_rq->avg.load_sum = cfs_rq->avg.load_avg * LOAD_AVG_MAX;
+
+	/*
+	 * If the sched_entity is already enqueued, we also have to update the
+	 * runnable load avg.
+	 */
+	if (se->on_rq) {
+		/* Update parent cfs_rq runnable_load_avg */
+		add_positive(&cfs_rq->runnable_load_avg, delta);
+		cfs_rq->runnable_load_sum = cfs_rq->runnable_load_avg * LOAD_AVG_MAX;
+	}
+}
+
+static inline void set_tg_cfs_propagate(struct cfs_rq *cfs_rq)
+{
+	cfs_rq->propagate_avg = 1;
+}
+
+static inline int test_and_clear_tg_cfs_propagate(struct sched_entity *se)
+{
+	struct cfs_rq *cfs_rq = group_cfs_rq(se);
+
+	if (!cfs_rq->propagate_avg)
+		return 0;
+
+	cfs_rq->propagate_avg = 0;
+	return 1;
+}
+
+/* Update task and its cfs_rq load average */
+static inline int propagate_entity_load_avg(struct sched_entity *se)
+{
+	struct cfs_rq *cfs_rq;
+
+	if (entity_is_task(se))
+		return 0;
+
+	if (!test_and_clear_tg_cfs_propagate(se))
+		return 0;
+
+	cfs_rq = cfs_rq_of(se);
+
+	set_tg_cfs_propagate(cfs_rq);
+
+	update_tg_cfs_util(cfs_rq, se);
+	update_tg_cfs_load(cfs_rq, se);
+
+	return 1;
+}
+
 #else /* CONFIG_FAIR_GROUP_SCHED */
+
 static inline void update_tg_load_avg(struct cfs_rq *cfs_rq, int force) {}
+
+static inline int propagate_entity_load_avg(struct sched_entity *se)
+{
+	return 0;
+}
+
+static inline void set_tg_cfs_propagate(struct cfs_rq *cfs_rq) {}
+
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
+static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq)
+{
+        if (&this_rq()->cfs == cfs_rq) {
+                /*
+                 * There are a few boundary cases this might miss but it should
+                 * get called often enough that that should (hopefully) not be
+                 * a real problem -- added to that it only calls on the local
+                 * CPU, so if we enqueue remotely we'll miss an update, but
+                 * the next tick/schedule should update.
+                 *
+                 * It will not get called when we go idle, because the idle
+                 * thread is a different class (!fair), nor will the utilization
+                 * number include things like RT tasks.
+                 *
+                 * As is, the util number is not freq-invariant (we'd have to
+                 * implement arch_scale_freq_capacity() for that).
+                 *
+                 * See cpu_util().
+                 */
+                cpufreq_update_util(rq_of(cfs_rq), 0);
+        }
+}
+
 static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq);
 
-/* Group cfs_rq's load_avg is used for task_h_load and update_cfs_share */
-static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
+/*
+ * Unsigned subtract and clamp on underflow.
+ *
+ * Explicitly do a load-store to ensure the intermediate value never hits
+ * memory. This allows lockless observations without ever seeing the negative
+ * values.
+ */
+#define sub_positive(_ptr, _val) do {				\
+	typeof(_ptr) ptr = (_ptr);				\
+	typeof(*ptr) val = (_val);				\
+	typeof(*ptr) res, var = READ_ONCE(*ptr);		\
+	res = var - val;					\
+	if (res > var)						\
+		res = 0;					\
+	WRITE_ONCE(*ptr, res);					\
+} while (0)
+
+/**
+ * update_cfs_rq_load_avg - update the cfs_rq's load/util averages
+ * @now: current time, as per cfs_rq_clock_task()
+ * @cfs_rq: cfs_rq to update
+ * @update_freq: should we call cfs_rq_util_change() or will the call do so
+ *
+ * The cfs_rq avg is the direct sum of all its entities (blocked and runnable)
+ * avg. The immediate corollary is that all (fair) tasks must be attached, see
+ * post_init_entity_util_avg().
+ *
+ * cfs_rq->avg is used for task_h_load() and update_cfs_share() for example.
+ *
+ * Returns true if the load decayed or we removed load.
+ *
+ * Since both these conditions indicate a changed cfs_rq->avg.load we should
+ * call update_tg_load_avg() when this function returns true.
+ */
+static inline int
+update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq)
 {
 	struct sched_avg *sa = &cfs_rq->avg;
-	int decayed, removed = 0;
+	int decayed, removed = 0, removed_util = 0;
 
 	if (atomic_long_read(&cfs_rq->removed_load_avg)) {
 		s64 r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0);
-		sa->load_avg = max_t(long, sa->load_avg - r, 0);
-		sa->load_sum = max_t(s64, sa->load_sum - r * LOAD_AVG_MAX, 0);
+		sub_positive(&sa->load_avg, r);
+		sub_positive(&sa->load_sum, r * LOAD_AVG_MAX);
 		removed = 1;
+		set_tg_cfs_propagate(cfs_rq);
 	}
 
 	if (atomic_long_read(&cfs_rq->removed_util_avg)) {
 		long r = atomic_long_xchg(&cfs_rq->removed_util_avg, 0);
-		sa->util_avg = max_t(long, sa->util_avg - r, 0);
-		sa->util_sum = max_t(s32, sa->util_sum - r * LOAD_AVG_MAX, 0);
+		sub_positive(&sa->util_avg, r);
+		sub_positive(&sa->util_sum, r * LOAD_AVG_MAX);
+		removed_util = 1;
+		set_tg_cfs_propagate(cfs_rq);
 	}
 
 	decayed = __update_load_avg(now, cpu_of(rq_of(cfs_rq)), sa,
@@ -2709,65 +3155,93 @@
 	cfs_rq->load_last_update_time_copy = sa->last_update_time;
 #endif
 
+	/* Trace CPU load, unless cfs_rq belongs to a non-root task_group */
+	if (cfs_rq == &rq_of(cfs_rq)->cfs)
+		trace_sched_load_avg_cpu(cpu_of(rq_of(cfs_rq)), cfs_rq);
+
+	if (update_freq && (decayed || removed_util))
+		cfs_rq_util_change(cfs_rq);
+
 	return decayed || removed;
 }
 
+/*
+ * Optional action to be done while updating the load average
+ */
+#define UPDATE_TG	0x1
+#define SKIP_AGE_LOAD	0x2
+
 /* Update task and its cfs_rq load average */
-static inline void update_load_avg(struct sched_entity *se, int update_tg)
+static inline void update_load_avg(struct sched_entity *se, int flags)
 {
 	struct cfs_rq *cfs_rq = cfs_rq_of(se);
 	u64 now = cfs_rq_clock_task(cfs_rq);
 	int cpu = cpu_of(rq_of(cfs_rq));
+	int decayed;
+	void *ptr = NULL;
 
 	/*
 	 * Track task load average for carrying it to new CPU after migrated, and
 	 * track group sched_entity load average for task_h_load calc in migration
 	 */
-	__update_load_avg(now, cpu, &se->avg,
+	if (se->avg.last_update_time && !(flags & SKIP_AGE_LOAD)) {
+		__update_load_avg(now, cpu, &se->avg,
 			  se->on_rq * scale_load_down(se->load.weight),
 			  cfs_rq->curr == se, NULL);
-
-	if (update_cfs_rq_load_avg(now, cfs_rq) && update_tg)
-		update_tg_load_avg(cfs_rq, 0);
-}
-
-static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
-{
-	if (!sched_feat(ATTACH_AGE_LOAD))
-		goto skip_aging;
-
-	/*
-	 * If we got migrated (either between CPUs or between cgroups) we'll
-	 * have aged the average right before clearing @last_update_time.
-	 */
-	if (se->avg.last_update_time) {
-		__update_load_avg(cfs_rq->avg.last_update_time, cpu_of(rq_of(cfs_rq)),
-				  &se->avg, 0, 0, NULL);
-
-		/*
-		 * XXX: we could have just aged the entire load away if we've been
-		 * absent from the fair class for too long.
-		 */
 	}
 
-skip_aging:
+	decayed  = update_cfs_rq_load_avg(now, cfs_rq, true);
+	decayed |= propagate_entity_load_avg(se);
+
+	if (decayed && (flags & UPDATE_TG))
+		update_tg_load_avg(cfs_rq, 0);
+
+	if (entity_is_task(se)) {
+#ifdef CONFIG_SCHED_WALT
+		ptr = (void *)&(task_of(se)->ravg);
+#endif
+		trace_sched_load_avg_task(task_of(se), &se->avg, ptr);
+	}
+}
+
+/**
+ * attach_entity_load_avg - attach this entity to its cfs_rq load avg
+ * @cfs_rq: cfs_rq to attach to
+ * @se: sched_entity to attach
+ *
+ * Must call update_cfs_rq_load_avg() before this, since we rely on
+ * cfs_rq->avg.last_update_time being current.
+ */
+static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
 	se->avg.last_update_time = cfs_rq->avg.last_update_time;
 	cfs_rq->avg.load_avg += se->avg.load_avg;
 	cfs_rq->avg.load_sum += se->avg.load_sum;
 	cfs_rq->avg.util_avg += se->avg.util_avg;
 	cfs_rq->avg.util_sum += se->avg.util_sum;
+	set_tg_cfs_propagate(cfs_rq);
+
+	cfs_rq_util_change(cfs_rq);
 }
 
+/**
+ * detach_entity_load_avg - detach this entity from its cfs_rq load avg
+ * @cfs_rq: cfs_rq to detach from
+ * @se: sched_entity to detach
+ *
+ * Must call update_cfs_rq_load_avg() before this, since we rely on
+ * cfs_rq->avg.last_update_time being current.
+ */
 static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
-	__update_load_avg(cfs_rq->avg.last_update_time, cpu_of(rq_of(cfs_rq)),
-			  &se->avg, se->on_rq * scale_load_down(se->load.weight),
-			  cfs_rq->curr == se, NULL);
 
-	cfs_rq->avg.load_avg = max_t(long, cfs_rq->avg.load_avg - se->avg.load_avg, 0);
-	cfs_rq->avg.load_sum = max_t(s64,  cfs_rq->avg.load_sum - se->avg.load_sum, 0);
-	cfs_rq->avg.util_avg = max_t(long, cfs_rq->avg.util_avg - se->avg.util_avg, 0);
-	cfs_rq->avg.util_sum = max_t(s32,  cfs_rq->avg.util_sum - se->avg.util_sum, 0);
+	sub_positive(&cfs_rq->avg.load_avg, se->avg.load_avg);
+	sub_positive(&cfs_rq->avg.load_sum, se->avg.load_sum);
+	sub_positive(&cfs_rq->avg.util_avg, se->avg.util_avg);
+	sub_positive(&cfs_rq->avg.util_sum, se->avg.util_sum);
+	set_tg_cfs_propagate(cfs_rq);
+
+	cfs_rq_util_change(cfs_rq);
 }
 
 /* Add the load generated by se into cfs_rq's load average */
@@ -2775,40 +3249,60 @@
 enqueue_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
 	struct sched_avg *sa = &se->avg;
-	u64 now = cfs_rq_clock_task(cfs_rq);
-	int migrated, decayed;
-
-	migrated = !sa->last_update_time;
-	if (!migrated) {
-		__update_load_avg(now, cpu_of(rq_of(cfs_rq)), sa,
-			se->on_rq * scale_load_down(se->load.weight),
-			cfs_rq->curr == se, NULL);
-	}
-
-	decayed = update_cfs_rq_load_avg(now, cfs_rq);
 
 	cfs_rq->runnable_load_avg += sa->load_avg;
 	cfs_rq->runnable_load_sum += sa->load_sum;
 
-	if (migrated)
+	if (!sa->last_update_time) {
 		attach_entity_load_avg(cfs_rq, se);
-
-	if (decayed || migrated)
 		update_tg_load_avg(cfs_rq, 0);
+	}
 }
 
 /* Remove the runnable load generated by se from cfs_rq's runnable load average */
 static inline void
 dequeue_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
-	update_load_avg(se, 1);
-
 	cfs_rq->runnable_load_avg =
 		max_t(long, cfs_rq->runnable_load_avg - se->avg.load_avg, 0);
 	cfs_rq->runnable_load_sum =
 		max_t(s64,  cfs_rq->runnable_load_sum - se->avg.load_sum, 0);
 }
 
+#ifndef CONFIG_64BIT
+static inline u64 cfs_rq_last_update_time(struct cfs_rq *cfs_rq)
+{
+	u64 last_update_time_copy;
+	u64 last_update_time;
+
+	do {
+		last_update_time_copy = cfs_rq->load_last_update_time_copy;
+		smp_rmb();
+		last_update_time = cfs_rq->avg.last_update_time;
+	} while (last_update_time != last_update_time_copy);
+
+	return last_update_time;
+}
+#else
+static inline u64 cfs_rq_last_update_time(struct cfs_rq *cfs_rq)
+{
+	return cfs_rq->avg.last_update_time;
+}
+#endif
+
+/*
+ * Synchronize entity load avg of dequeued entity without locking
+ * the previous rq.
+ */
+void sync_entity_load_avg(struct sched_entity *se)
+{
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+	u64 last_update_time;
+
+	last_update_time = cfs_rq_last_update_time(cfs_rq);
+	__update_load_avg(last_update_time, cpu_of(rq_of(cfs_rq)), &se->avg, 0, 0, NULL);
+}
+
 /*
  * Task first catches up with cfs_rq, and then subtract
  * itself from the cfs_rq (task must be off the queue now).
@@ -2816,21 +3310,15 @@
 void remove_entity_load_avg(struct sched_entity *se)
 {
 	struct cfs_rq *cfs_rq = cfs_rq_of(se);
-	u64 last_update_time;
 
-#ifndef CONFIG_64BIT
-	u64 last_update_time_copy;
+	/*
+	 * Newly created task or never used group entity should not be removed
+	 * from its (source) cfs_rq
+	 */
+	if (se->avg.last_update_time == 0)
+		return;
 
-	do {
-		last_update_time_copy = cfs_rq->load_last_update_time_copy;
-		smp_rmb();
-		last_update_time = cfs_rq->avg.last_update_time;
-	} while (last_update_time != last_update_time_copy);
-#else
-	last_update_time = cfs_rq->avg.last_update_time;
-#endif
-
-	__update_load_avg(last_update_time, cpu_of(rq_of(cfs_rq)), &se->avg, 0, 0, NULL);
+	sync_entity_load_avg(se);
 	atomic_long_add(se->avg.load_avg, &cfs_rq->removed_load_avg);
 	atomic_long_add(se->avg.util_avg, &cfs_rq->removed_util_avg);
 }
@@ -2867,7 +3355,16 @@
 
 #else /* CONFIG_SMP */
 
-static inline void update_load_avg(struct sched_entity *se, int update_tg) {}
+static inline int
+update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq)
+{
+	return 0;
+}
+
+#define UPDATE_TG	0x0
+#define SKIP_AGE_LOAD	0x0
+
+static inline void update_load_avg(struct sched_entity *se, int not_used1){}
 static inline void
 enqueue_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se) {}
 static inline void
@@ -3010,9 +3507,10 @@
 	 * Update run-time statistics of the 'current'.
 	 */
 	update_curr(cfs_rq);
+	update_load_avg(se, UPDATE_TG);
 	enqueue_entity_load_avg(cfs_rq, se);
+	update_cfs_shares(se);
 	account_entity_enqueue(cfs_rq, se);
-	update_cfs_shares(cfs_rq);
 
 	if (flags & ENQUEUE_WAKEUP) {
 		place_entity(cfs_rq, se, 0);
@@ -3085,6 +3583,16 @@
 	 * Update run-time statistics of the 'current'.
 	 */
 	update_curr(cfs_rq);
+
+	/*
+	 * When dequeuing a sched_entity, we must:
+	 *   - Update loads to have both entity and cfs_rq synced with now.
+	 *   - Substract its load from the cfs_rq->runnable_avg.
+	 *   - Substract its previous weight from cfs_rq->load.weight.
+	 *   - For group entity, update its weight to reflect the new share
+	 *     of its group cfs_rq.
+	 */
+	update_load_avg(se, UPDATE_TG);
 	dequeue_entity_load_avg(cfs_rq, se);
 
 	update_stats_dequeue(cfs_rq, se);
@@ -3120,7 +3628,7 @@
 	return_cfs_rq_runtime(cfs_rq);
 
 	update_min_vruntime(cfs_rq);
-	update_cfs_shares(cfs_rq);
+	update_cfs_shares(se);
 }
 
 /*
@@ -3175,7 +3683,7 @@
 		 */
 		update_stats_wait_end(cfs_rq, se);
 		__dequeue_entity(cfs_rq, se);
-		update_load_avg(se, 1);
+		update_load_avg(se, UPDATE_TG);
 	}
 
 	update_stats_curr_start(cfs_rq, se);
@@ -3291,8 +3799,8 @@
 	/*
 	 * Ensure that runnable average is periodically updated.
 	 */
-	update_load_avg(curr, 1);
-	update_cfs_shares(cfs_rq);
+	update_load_avg(curr, UPDATE_TG);
+	update_cfs_shares(curr);
 
 #ifdef CONFIG_SCHED_HRTICK
 	/*
@@ -3888,6 +4396,26 @@
 	if (!cfs_bandwidth_used())
 		return;
 
+	/* Synchronize hierarchical throttle counter: */
+	if (unlikely(!cfs_rq->throttle_uptodate)) {
+		struct rq *rq = rq_of(cfs_rq);
+		struct cfs_rq *pcfs_rq;
+		struct task_group *tg;
+
+		cfs_rq->throttle_uptodate = 1;
+
+		/* Get closest up-to-date node, because leaves go first: */
+		for (tg = cfs_rq->tg->parent; tg; tg = tg->parent) {
+			pcfs_rq = tg->cfs_rq[cpu_of(rq)];
+			if (pcfs_rq->throttle_uptodate)
+				break;
+		}
+		if (tg) {
+			cfs_rq->throttle_count = pcfs_rq->throttle_count;
+			cfs_rq->throttled_clock_task = rq_clock_task(rq);
+		}
+	}
+
 	/* an active group must be handled by the update_curr()->put() path */
 	if (!cfs_rq->runtime_enabled || cfs_rq->curr)
 		return;
@@ -4127,6 +4655,28 @@
 }
 #endif
 
+#ifdef CONFIG_SMP
+static bool cpu_overutilized(int cpu);
+unsigned long boosted_cpu_util(int cpu);
+#else
+#define boosted_cpu_util(cpu) cpu_util(cpu)
+#endif
+
+#ifdef CONFIG_SMP
+static void update_capacity_of(int cpu)
+{
+	unsigned long req_cap;
+
+	if (!sched_freq())
+		return;
+
+	/* Convert scale-invariant capacity to cpu. */
+	req_cap = boosted_cpu_util(cpu);
+	req_cap = req_cap * SCHED_CAPACITY_SCALE / capacity_orig_of(cpu);
+	set_cfs_cpu_capacity(cpu, true, req_cap);
+}
+#endif
+
 /*
  * The enqueue_task method is called before nr_running is
  * increased. Here we update the fair scheduling stats and
@@ -4137,6 +4687,18 @@
 {
 	struct cfs_rq *cfs_rq;
 	struct sched_entity *se = &p->se;
+#ifdef CONFIG_SMP
+	int task_new = flags & ENQUEUE_WAKEUP_NEW;
+	int task_wakeup = flags & ENQUEUE_WAKEUP;
+#endif
+
+	/*
+	 * If in_iowait is set, the code below may not trigger any cpufreq
+	 * utilization updates, so do it here explicitly with the IOWAIT flag
+	 * passed.
+	 */
+	if (p->in_iowait)
+		cpufreq_update_this_cpu(rq, SCHED_CPUFREQ_IOWAIT);
 
 	for_each_sched_entity(se) {
 		if (se->on_rq)
@@ -4153,6 +4715,7 @@
 		if (cfs_rq_throttled(cfs_rq))
 			break;
 		cfs_rq->h_nr_running++;
+		walt_inc_cfs_cumulative_runnable_avg(cfs_rq, p);
 
 		flags = ENQUEUE_WAKEUP;
 	}
@@ -4160,17 +4723,59 @@
 	for_each_sched_entity(se) {
 		cfs_rq = cfs_rq_of(se);
 		cfs_rq->h_nr_running++;
+		walt_inc_cfs_cumulative_runnable_avg(cfs_rq, p);
 
 		if (cfs_rq_throttled(cfs_rq))
 			break;
 
-		update_load_avg(se, 1);
-		update_cfs_shares(cfs_rq);
+		update_load_avg(se, UPDATE_TG);
+		update_cfs_shares(se);
 	}
 
 	if (!se)
 		add_nr_running(rq, 1);
 
+#ifdef CONFIG_SMP
+
+	/*
+	 * Update SchedTune accounting.
+	 *
+	 * We do it before updating the CPU capacity to ensure the
+	 * boost value of the current task is accounted for in the
+	 * selection of the OPP.
+	 *
+	 * We do it also in the case where we enqueue a throttled task;
+	 * we could argue that a throttled task should not boost a CPU,
+	 * however:
+	 * a) properly implementing CPU boosting considering throttled
+	 *    tasks will increase a lot the complexity of the solution
+	 * b) it's not easy to quantify the benefits introduced by
+	 *    such a more complex solution.
+	 * Thus, for the time being we go for the simple solution and boost
+	 * also for throttled RQs.
+	 */
+	schedtune_enqueue_task(p, cpu_of(rq));
+
+	if (!se) {
+		walt_inc_cumulative_runnable_avg(rq, p);
+		if (!task_new && !rq->rd->overutilized &&
+		    cpu_overutilized(rq->cpu)) {
+			rq->rd->overutilized = true;
+			trace_sched_overutilized(true);
+		}
+
+		/*
+		 * We want to potentially trigger a freq switch
+		 * request only for tasks that are waking up; this is
+		 * because we get here also during load balancing, but
+		 * in these cases it seems wise to trigger as single
+		 * request after load balancing is done.
+		 */
+		if (task_new || task_wakeup)
+			update_capacity_of(cpu_of(rq));
+	}
+
+#endif /* CONFIG_SMP */
 	hrtick_update(rq);
 }
 
@@ -4200,18 +4805,18 @@
 		if (cfs_rq_throttled(cfs_rq))
 			break;
 		cfs_rq->h_nr_running--;
+		walt_dec_cfs_cumulative_runnable_avg(cfs_rq, p);
 
 		/* Don't dequeue parent if it has other entities besides us */
 		if (cfs_rq->load.weight) {
+			/* Avoid re-evaluating load for this entity: */
+			se = parent_entity(se);
 			/*
 			 * Bias pick_next to pick a task from this cfs_rq, as
 			 * p is sleeping when it is within its sched_slice.
 			 */
-			if (task_sleep && parent_entity(se))
-				set_next_buddy(parent_entity(se));
-
-			/* avoid re-evaluating load for this entity */
-			se = parent_entity(se);
+			if (task_sleep && se && !throttled_hierarchy(cfs_rq))
+				set_next_buddy(se);
 			break;
 		}
 		flags |= DEQUEUE_SLEEP;
@@ -4220,17 +4825,50 @@
 	for_each_sched_entity(se) {
 		cfs_rq = cfs_rq_of(se);
 		cfs_rq->h_nr_running--;
+		walt_dec_cfs_cumulative_runnable_avg(cfs_rq, p);
 
 		if (cfs_rq_throttled(cfs_rq))
 			break;
 
-		update_load_avg(se, 1);
-		update_cfs_shares(cfs_rq);
+		update_load_avg(se, UPDATE_TG);
+		update_cfs_shares(se);
 	}
 
 	if (!se)
 		sub_nr_running(rq, 1);
 
+#ifdef CONFIG_SMP
+
+	/*
+	 * Update SchedTune accounting
+	 *
+	 * We do it before updating the CPU capacity to ensure the
+	 * boost value of the current task is accounted for in the
+	 * selection of the OPP.
+	 */
+	schedtune_dequeue_task(p, cpu_of(rq));
+
+	if (!se) {
+		walt_dec_cumulative_runnable_avg(rq, p);
+
+		/*
+		 * We want to potentially trigger a freq switch
+		 * request only for tasks that are going to sleep;
+		 * this is because we get here also during load
+		 * balancing, but in these cases it seems wise to
+		 * trigger as single request after load balancing is
+		 * done.
+		 */
+		if (task_sleep) {
+			if (rq->cfs.nr_running)
+				update_capacity_of(cpu_of(rq));
+			else if (sched_freq())
+				set_cfs_cpu_capacity(cpu_of(rq), false, 0);
+		}
+	}
+
+#endif /* CONFIG_SMP */
+
 	hrtick_update(rq);
 }
 
@@ -4457,15 +5095,6 @@
 	return max(rq->cpu_load[type-1], total);
 }
 
-static unsigned long capacity_of(int cpu)
-{
-	return cpu_rq(cpu)->cpu_capacity;
-}
-
-static unsigned long capacity_orig_of(int cpu)
-{
-	return cpu_rq(cpu)->cpu_capacity_orig;
-}
 
 static unsigned long cpu_avg_load_per_task(int cpu)
 {
@@ -4578,19 +5207,24 @@
 		return wl;
 
 	for_each_sched_entity(se) {
-		long w, W;
+		struct cfs_rq *cfs_rq = se->my_q;
+		long W, w = cfs_rq_load_avg(cfs_rq);
 
-		tg = se->my_q->tg;
+		tg = cfs_rq->tg;
 
 		/*
 		 * W = @wg + \Sum rw_j
 		 */
-		W = wg + calc_tg_weight(tg, se->my_q);
+		W = wg + atomic_long_read(&tg->load_avg);
+
+		/* Ensure \Sum rw_j >= rw_i */
+		W -= cfs_rq->tg_load_avg_contrib;
+		W += w;
 
 		/*
 		 * w = rw_i + @wl
 		 */
-		w = cfs_rq_load_avg(se->my_q) + wl;
+		w += wl;
 
 		/*
 		 * wl = S * s'_i; see (2)
@@ -4635,6 +5269,416 @@
 #endif
 
 /*
+ * Returns the current capacity of cpu after applying both
+ * cpu and freq scaling.
+ */
+unsigned long capacity_curr_of(int cpu)
+{
+	return cpu_rq(cpu)->cpu_capacity_orig *
+	       arch_scale_freq_capacity(NULL, cpu)
+	       >> SCHED_CAPACITY_SHIFT;
+}
+
+static inline bool energy_aware(void)
+{
+	return sched_feat(ENERGY_AWARE);
+}
+
+struct energy_env {
+	struct sched_group	*sg_top;
+	struct sched_group	*sg_cap;
+	int			cap_idx;
+	int			util_delta;
+	int			src_cpu;
+	int			dst_cpu;
+	int			energy;
+	int			payoff;
+	struct task_struct	*task;
+	struct {
+		int before;
+		int after;
+		int delta;
+		int diff;
+	} nrg;
+	struct {
+		int before;
+		int after;
+		int delta;
+	} cap;
+};
+
+/*
+ * __cpu_norm_util() returns the cpu util relative to a specific capacity,
+ * i.e. it's busy ratio, in the range [0..SCHED_LOAD_SCALE] which is useful for
+ * energy calculations. Using the scale-invariant util returned by
+ * cpu_util() and approximating scale-invariant util by:
+ *
+ *   util ~ (curr_freq/max_freq)*1024 * capacity_orig/1024 * running_time/time
+ *
+ * the normalized util can be found using the specific capacity.
+ *
+ *   capacity = capacity_orig * curr_freq/max_freq
+ *
+ *   norm_util = running_time/time ~ util/capacity
+ */
+static unsigned long __cpu_norm_util(int cpu, unsigned long capacity, int delta)
+{
+	int util = __cpu_util(cpu, delta);
+
+	if (util >= capacity)
+		return SCHED_CAPACITY_SCALE;
+
+	return (util << SCHED_CAPACITY_SHIFT)/capacity;
+}
+
+static int calc_util_delta(struct energy_env *eenv, int cpu)
+{
+	if (cpu == eenv->src_cpu)
+		return -eenv->util_delta;
+	if (cpu == eenv->dst_cpu)
+		return eenv->util_delta;
+	return 0;
+}
+
+static
+unsigned long group_max_util(struct energy_env *eenv)
+{
+	int i, delta;
+	unsigned long max_util = 0;
+
+	for_each_cpu(i, sched_group_cpus(eenv->sg_cap)) {
+		delta = calc_util_delta(eenv, i);
+		max_util = max(max_util, __cpu_util(i, delta));
+	}
+
+	return max_util;
+}
+
+/*
+ * group_norm_util() returns the approximated group util relative to it's
+ * current capacity (busy ratio) in the range [0..SCHED_LOAD_SCALE] for use in
+ * energy calculations. Since task executions may or may not overlap in time in
+ * the group the true normalized util is between max(cpu_norm_util(i)) and
+ * sum(cpu_norm_util(i)) when iterating over all cpus in the group, i. The
+ * latter is used as the estimate as it leads to a more pessimistic energy
+ * estimate (more busy).
+ */
+static unsigned
+long group_norm_util(struct energy_env *eenv, struct sched_group *sg)
+{
+	int i, delta;
+	unsigned long util_sum = 0;
+	unsigned long capacity = sg->sge->cap_states[eenv->cap_idx].cap;
+
+	for_each_cpu(i, sched_group_cpus(sg)) {
+		delta = calc_util_delta(eenv, i);
+		util_sum += __cpu_norm_util(i, capacity, delta);
+	}
+
+	if (util_sum > SCHED_CAPACITY_SCALE)
+		return SCHED_CAPACITY_SCALE;
+	return util_sum;
+}
+
+static int find_new_capacity(struct energy_env *eenv,
+	const struct sched_group_energy * const sge)
+{
+	int idx;
+	unsigned long util = group_max_util(eenv);
+
+	for (idx = 0; idx < sge->nr_cap_states; idx++) {
+		if (sge->cap_states[idx].cap >= util)
+			break;
+	}
+
+	eenv->cap_idx = idx;
+
+	return idx;
+}
+
+static int group_idle_state(struct sched_group *sg)
+{
+	int i, state = INT_MAX;
+
+	/* Find the shallowest idle state in the sched group. */
+	for_each_cpu(i, sched_group_cpus(sg))
+		state = min(state, idle_get_state_idx(cpu_rq(i)));
+
+	/* Take non-cpuidle idling into account (active idle/arch_cpu_idle()) */
+	state++;
+
+	return state;
+}
+
+/*
+ * sched_group_energy(): Computes the absolute energy consumption of cpus
+ * belonging to the sched_group including shared resources shared only by
+ * members of the group. Iterates over all cpus in the hierarchy below the
+ * sched_group starting from the bottom working it's way up before going to
+ * the next cpu until all cpus are covered at all levels. The current
+ * implementation is likely to gather the same util statistics multiple times.
+ * This can probably be done in a faster but more complex way.
+ * Note: sched_group_energy() may fail when racing with sched_domain updates.
+ */
+static int sched_group_energy(struct energy_env *eenv)
+{
+	struct sched_domain *sd;
+	int cpu, total_energy = 0;
+	struct cpumask visit_cpus;
+	struct sched_group *sg;
+
+	WARN_ON(!eenv->sg_top->sge);
+
+	cpumask_copy(&visit_cpus, sched_group_cpus(eenv->sg_top));
+
+	while (!cpumask_empty(&visit_cpus)) {
+		struct sched_group *sg_shared_cap = NULL;
+
+		cpu = cpumask_first(&visit_cpus);
+
+		/*
+		 * Is the group utilization affected by cpus outside this
+		 * sched_group?
+		 */
+		sd = rcu_dereference(per_cpu(sd_scs, cpu));
+
+		if (sd && sd->parent)
+			sg_shared_cap = sd->parent->groups;
+
+		for_each_domain(cpu, sd) {
+			sg = sd->groups;
+
+			/* Has this sched_domain already been visited? */
+			if (sd->child && group_first_cpu(sg) != cpu)
+				break;
+
+			do {
+				unsigned long group_util;
+				int sg_busy_energy, sg_idle_energy;
+				int cap_idx, idle_idx;
+
+				if (sg_shared_cap && sg_shared_cap->group_weight >= sg->group_weight)
+					eenv->sg_cap = sg_shared_cap;
+				else
+					eenv->sg_cap = sg;
+
+				cap_idx = find_new_capacity(eenv, sg->sge);
+
+				if (sg->group_weight == 1) {
+					/* Remove capacity of src CPU (before task move) */
+					if (eenv->util_delta == 0 &&
+					    cpumask_test_cpu(eenv->src_cpu, sched_group_cpus(sg))) {
+						eenv->cap.before = sg->sge->cap_states[cap_idx].cap;
+						eenv->cap.delta -= eenv->cap.before;
+					}
+					/* Add capacity of dst CPU  (after task move) */
+					if (eenv->util_delta != 0 &&
+					    cpumask_test_cpu(eenv->dst_cpu, sched_group_cpus(sg))) {
+						eenv->cap.after = sg->sge->cap_states[cap_idx].cap;
+						eenv->cap.delta += eenv->cap.after;
+					}
+				}
+
+				idle_idx = group_idle_state(sg);
+				group_util = group_norm_util(eenv, sg);
+				sg_busy_energy = (group_util * sg->sge->cap_states[cap_idx].power)
+								>> SCHED_CAPACITY_SHIFT;
+				sg_idle_energy = ((SCHED_LOAD_SCALE-group_util)
+								* sg->sge->idle_states[idle_idx].power)
+								>> SCHED_CAPACITY_SHIFT;
+
+				total_energy += sg_busy_energy + sg_idle_energy;
+
+				if (!sd->child)
+					cpumask_xor(&visit_cpus, &visit_cpus, sched_group_cpus(sg));
+
+				if (cpumask_equal(sched_group_cpus(sg), sched_group_cpus(eenv->sg_top)))
+					goto next_cpu;
+
+			} while (sg = sg->next, sg != sd->groups);
+		}
+
+		/*
+		 * If we raced with hotplug and got an sd NULL-pointer;
+		 * returning a wrong energy estimation is better than
+		 * entering an infinite loop.
+		 */
+		if (cpumask_test_cpu(cpu, &visit_cpus))
+			return -EINVAL;
+next_cpu:
+		cpumask_clear_cpu(cpu, &visit_cpus);
+		continue;
+	}
+
+	eenv->energy = total_energy;
+	return 0;
+}
+
+static inline bool cpu_in_sg(struct sched_group *sg, int cpu)
+{
+	return cpu != -1 && cpumask_test_cpu(cpu, sched_group_cpus(sg));
+}
+
+/*
+ * energy_diff(): Estimate the energy impact of changing the utilization
+ * distribution. eenv specifies the change: utilisation amount, source, and
+ * destination cpu. Source or destination cpu may be -1 in which case the
+ * utilization is removed from or added to the system (e.g. task wake-up). If
+ * both are specified, the utilization is migrated.
+ */
+static inline int __energy_diff(struct energy_env *eenv)
+{
+	struct sched_domain *sd;
+	struct sched_group *sg;
+	int sd_cpu = -1, energy_before = 0, energy_after = 0;
+	int diff, margin;
+
+	struct energy_env eenv_before = {
+		.util_delta	= 0,
+		.src_cpu	= eenv->src_cpu,
+		.dst_cpu	= eenv->dst_cpu,
+		.nrg		= { 0, 0, 0, 0},
+		.cap		= { 0, 0, 0 },
+	};
+
+	if (eenv->src_cpu == eenv->dst_cpu)
+		return 0;
+
+	sd_cpu = (eenv->src_cpu != -1) ? eenv->src_cpu : eenv->dst_cpu;
+	sd = rcu_dereference(per_cpu(sd_ea, sd_cpu));
+
+	if (!sd)
+		return 0; /* Error */
+
+	sg = sd->groups;
+
+	do {
+		if (cpu_in_sg(sg, eenv->src_cpu) || cpu_in_sg(sg, eenv->dst_cpu)) {
+			eenv_before.sg_top = eenv->sg_top = sg;
+
+			if (sched_group_energy(&eenv_before))
+				return 0; /* Invalid result abort */
+			energy_before += eenv_before.energy;
+
+			/* Keep track of SRC cpu (before) capacity */
+			eenv->cap.before = eenv_before.cap.before;
+			eenv->cap.delta = eenv_before.cap.delta;
+
+			if (sched_group_energy(eenv))
+				return 0; /* Invalid result abort */
+			energy_after += eenv->energy;
+		}
+	} while (sg = sg->next, sg != sd->groups);
+
+	eenv->nrg.before = energy_before;
+	eenv->nrg.after = energy_after;
+	eenv->nrg.diff = eenv->nrg.after - eenv->nrg.before;
+	eenv->payoff = 0;
+#ifndef CONFIG_SCHED_TUNE
+	trace_sched_energy_diff(eenv->task,
+			eenv->src_cpu, eenv->dst_cpu, eenv->util_delta,
+			eenv->nrg.before, eenv->nrg.after, eenv->nrg.diff,
+			eenv->cap.before, eenv->cap.after, eenv->cap.delta,
+			eenv->nrg.delta, eenv->payoff);
+#endif
+	/*
+	 * Dead-zone margin preventing too many migrations.
+	 */
+
+	margin = eenv->nrg.before >> 6; /* ~1.56% */
+
+	diff = eenv->nrg.after - eenv->nrg.before;
+
+	eenv->nrg.diff = (abs(diff) < margin) ? 0 : eenv->nrg.diff;
+
+	return eenv->nrg.diff;
+}
+
+#ifdef CONFIG_SCHED_TUNE
+
+struct target_nrg schedtune_target_nrg;
+extern bool schedtune_initialized;
+/*
+ * System energy normalization
+ * Returns the normalized value, in the range [0..SCHED_CAPACITY_SCALE],
+ * corresponding to the specified energy variation.
+ */
+static inline int
+normalize_energy(int energy_diff)
+{
+	u32 normalized_nrg;
+
+	/* during early setup, we don't know the extents */
+	if (unlikely(!schedtune_initialized))
+		return energy_diff < 0 ? -1 : 1 ;
+
+#ifdef CONFIG_SCHED_DEBUG
+	{
+	int max_delta;
+
+	/* Check for boundaries */
+	max_delta  = schedtune_target_nrg.max_power;
+	max_delta -= schedtune_target_nrg.min_power;
+	WARN_ON(abs(energy_diff) >= max_delta);
+	}
+#endif
+
+	/* Do scaling using positive numbers to increase the range */
+	normalized_nrg = (energy_diff < 0) ? -energy_diff : energy_diff;
+
+	/* Scale by energy magnitude */
+	normalized_nrg <<= SCHED_CAPACITY_SHIFT;
+
+	/* Normalize on max energy for target platform */
+	normalized_nrg = reciprocal_divide(
+			normalized_nrg, schedtune_target_nrg.rdiv);
+
+	return (energy_diff < 0) ? -normalized_nrg : normalized_nrg;
+}
+
+static inline int
+energy_diff(struct energy_env *eenv)
+{
+	int boost = schedtune_task_boost(eenv->task);
+	int nrg_delta;
+
+	/* Conpute "absolute" energy diff */
+	__energy_diff(eenv);
+
+	/* Return energy diff when boost margin is 0 */
+	if (boost == 0)
+		return eenv->nrg.diff;
+
+	/* Compute normalized energy diff */
+	nrg_delta = normalize_energy(eenv->nrg.diff);
+	eenv->nrg.delta = nrg_delta;
+
+	eenv->payoff = schedtune_accept_deltas(
+			eenv->nrg.delta,
+			eenv->cap.delta,
+			eenv->task);
+
+	trace_sched_energy_diff(eenv->task,
+			eenv->src_cpu, eenv->dst_cpu, eenv->util_delta,
+			eenv->nrg.before, eenv->nrg.after, eenv->nrg.diff,
+			eenv->cap.before, eenv->cap.after, eenv->cap.delta,
+			eenv->nrg.delta, eenv->payoff);
+
+	/*
+	 * When SchedTune is enabled, the energy_diff() function will return
+	 * the computed energy payoff value. Since the energy_diff() return
+	 * value is expected to be negative by its callers, this evaluation
+	 * function return a negative value each time the evaluation return a
+	 * positive payoff, which is the condition for the acceptance of
+	 * a scheduling decision
+	 */
+	return -eenv->payoff;
+}
+#else /* CONFIG_SCHED_TUNE */
+#define energy_diff(eenv) __energy_diff(eenv)
+#endif
+
+/*
  * Detect M:N waker/wakee relationships via a switching-frequency heuristic.
  * A waker of many should wake a different task than the one last awakened
  * at a frequency roughly N times higher than one of its wakees.  In order
@@ -4659,18 +5703,18 @@
 	return 1;
 }
 
-static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
+static int wake_affine(struct sched_domain *sd, struct task_struct *p,
+		       int prev_cpu, int sync)
 {
 	s64 this_load, load;
 	s64 this_eff_load, prev_eff_load;
-	int idx, this_cpu, prev_cpu;
+	int idx, this_cpu;
 	struct task_group *tg;
 	unsigned long weight;
 	int balanced;
 
 	idx	  = sd->wake_idx;
 	this_cpu  = smp_processor_id();
-	prev_cpu  = task_cpu(p);
 	load	  = source_load(prev_cpu, idx);
 	this_load = target_load(this_cpu, idx);
 
@@ -4725,6 +5769,149 @@
 	return 1;
 }
 
+static inline unsigned long task_util(struct task_struct *p)
+{
+#ifdef CONFIG_SCHED_WALT
+	if (!walt_disabled && sysctl_sched_use_walt_task_util) {
+		unsigned long demand = p->ravg.demand;
+		return (demand << 10) / walt_ravg_window;
+	}
+#endif
+	return p->se.avg.util_avg;
+}
+
+static inline unsigned long boosted_task_util(struct task_struct *task);
+
+static inline bool __task_fits(struct task_struct *p, int cpu, int util)
+{
+	unsigned long capacity = capacity_of(cpu);
+
+	util += boosted_task_util(p);
+
+	return (capacity * 1024) > (util * capacity_margin);
+}
+
+static inline bool task_fits_max(struct task_struct *p, int cpu)
+{
+	unsigned long capacity = capacity_of(cpu);
+	unsigned long max_capacity = cpu_rq(cpu)->rd->max_cpu_capacity.val;
+
+	if (capacity == max_capacity)
+		return true;
+
+	if (capacity * capacity_margin > max_capacity * 1024)
+		return true;
+
+	return __task_fits(p, cpu, 0);
+}
+
+static bool cpu_overutilized(int cpu)
+{
+	return (capacity_of(cpu) * 1024) < (cpu_util(cpu) * capacity_margin);
+}
+
+#ifdef CONFIG_SCHED_TUNE
+
+struct reciprocal_value schedtune_spc_rdiv;
+
+static long
+schedtune_margin(unsigned long signal, long boost)
+{
+	long long margin = 0;
+
+	/*
+	 * Signal proportional compensation (SPC)
+	 *
+	 * The Boost (B) value is used to compute a Margin (M) which is
+	 * proportional to the complement of the original Signal (S):
+	 *   M = B * (SCHED_CAPACITY_SCALE - S)
+	 * The obtained M could be used by the caller to "boost" S.
+	 */
+	if (boost >= 0) {
+		margin  = SCHED_CAPACITY_SCALE - signal;
+		margin *= boost;
+	} else
+		margin = -signal * boost;
+
+	margin  = reciprocal_divide(margin, schedtune_spc_rdiv);
+
+	if (boost < 0)
+		margin *= -1;
+	return margin;
+}
+
+static inline int
+schedtune_cpu_margin(unsigned long util, int cpu)
+{
+	int boost = schedtune_cpu_boost(cpu);
+
+	if (boost == 0)
+		return 0;
+
+	return schedtune_margin(util, boost);
+}
+
+static inline long
+schedtune_task_margin(struct task_struct *task)
+{
+	int boost = schedtune_task_boost(task);
+	unsigned long util;
+	long margin;
+
+	if (boost == 0)
+		return 0;
+
+	util = task_util(task);
+	margin = schedtune_margin(util, boost);
+
+	return margin;
+}
+
+#else /* CONFIG_SCHED_TUNE */
+
+static inline int
+schedtune_cpu_margin(unsigned long util, int cpu)
+{
+	return 0;
+}
+
+static inline int
+schedtune_task_margin(struct task_struct *task)
+{
+	return 0;
+}
+
+#endif /* CONFIG_SCHED_TUNE */
+
+unsigned long
+boosted_cpu_util(int cpu)
+{
+	unsigned long util = cpu_util(cpu);
+	long margin = schedtune_cpu_margin(util, cpu);
+
+	trace_sched_boost_cpu(cpu, util, margin);
+
+	return util + margin;
+}
+
+static inline unsigned long
+boosted_task_util(struct task_struct *task)
+{
+	unsigned long util = task_util(task);
+	long margin = schedtune_task_margin(task);
+
+	trace_sched_boost_task(task, util, margin);
+
+	return util + margin;
+}
+
+static int cpu_util_wake(int cpu, struct task_struct *p);
+
+static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
+{
+	return capacity_orig_of(cpu) - cpu_util_wake(cpu, p);
+}
+
 /*
  * find_idlest_group finds and returns the least busy CPU group within the
  * domain.
@@ -4734,7 +5921,9 @@
 		  int this_cpu, int sd_flag)
 {
 	struct sched_group *idlest = NULL, *group = sd->groups;
+	struct sched_group *most_spare_sg = NULL;
 	unsigned long min_load = ULONG_MAX, this_load = 0;
+	unsigned long most_spare = 0, this_spare = 0;
 	int load_idx = sd->forkexec_idx;
 	int imbalance = 100 + (sd->imbalance_pct-100)/2;
 
@@ -4742,7 +5931,7 @@
 		load_idx = sd->wake_idx;
 
 	do {
-		unsigned long load, avg_load;
+		unsigned long load, avg_load, spare_cap, max_spare_cap;
 		int local_group;
 		int i;
 
@@ -4754,8 +5943,12 @@
 		local_group = cpumask_test_cpu(this_cpu,
 					       sched_group_cpus(group));
 
-		/* Tally up the load of all CPUs in the group */
+		/*
+		 * Tally up the load of all CPUs in the group and find
+		 * the group containing the CPU with most spare capacity.
+		 */
 		avg_load = 0;
+		max_spare_cap = 0;
 
 		for_each_cpu(i, sched_group_cpus(group)) {
 			/* Bias balancing toward cpus of our domain */
@@ -4765,6 +5958,11 @@
 				load = target_load(i, load_idx);
 
 			avg_load += load;
+
+			spare_cap = capacity_spare_wake(i, p);
+
+			if (spare_cap > max_spare_cap)
+				max_spare_cap = spare_cap;
 		}
 
 		/* Adjust by relative CPU capacity of the group */
@@ -4772,12 +5970,33 @@
 
 		if (local_group) {
 			this_load = avg_load;
-		} else if (avg_load < min_load) {
-			min_load = avg_load;
-			idlest = group;
+			this_spare = max_spare_cap;
+		} else {
+			if (avg_load < min_load) {
+				min_load = avg_load;
+				idlest = group;
+			}
+
+			if (most_spare < max_spare_cap) {
+				most_spare = max_spare_cap;
+				most_spare_sg = group;
+			}
 		}
 	} while (group = group->next, group != sd->groups);
 
+	/*
+	 * The cross-over point between using spare capacity or least load
+	 * is too conservative for high utilization tasks on partially
+	 * utilized systems if we require spare_capacity > task_util(p),
+	 * so we allow for some task stuffing by using
+	 * spare_capacity > task_util(p)/2.
+	 */
+	if (this_spare > task_util(p) / 2 &&
+	    imbalance*this_spare > 100*most_spare)
+		return NULL;
+	else if (most_spare > task_util(p) / 2)
+		return most_spare_sg;
+
 	if (!idlest || 100*this_load < imbalance*min_load)
 		return NULL;
 	return idlest;
@@ -4796,6 +6015,10 @@
 	int shallowest_idle_cpu = -1;
 	int i;
 
+	/* Check if we have any choice: */
+	if (group->group_weight == 1)
+		return cpumask_first(sched_group_cpus(group));
+
 	/* Traverse only the allowed CPUs */
 	for_each_cpu_and(i, sched_group_cpus(group), tsk_cpus_allowed(p)) {
 		if (idle_cpu(i)) {
@@ -4835,20 +6058,33 @@
 /*
  * Try and locate an idle CPU in the sched_domain.
  */
-static int select_idle_sibling(struct task_struct *p, int target)
+static int select_idle_sibling(struct task_struct *p, int prev, int target)
 {
 	struct sched_domain *sd;
 	struct sched_group *sg;
-	int i = task_cpu(p);
+	int best_idle_cpu = -1;
+	int best_idle_cstate = INT_MAX;
+	unsigned long best_idle_capacity = ULONG_MAX;
 
-	if (idle_cpu(target))
-		return target;
+	schedstat_inc(p, se.statistics.nr_wakeups_sis_attempts);
+	schedstat_inc(this_rq(), eas_stats.sis_attempts);
 
-	/*
-	 * If the prevous cpu is cache affine and idle, don't be stupid.
-	 */
-	if (i != target && cpus_share_cache(i, target) && idle_cpu(i))
-		return i;
+	if (!sysctl_sched_cstate_aware) {
+		if (idle_cpu(target)) {
+			schedstat_inc(p, se.statistics.nr_wakeups_sis_idle);
+			schedstat_inc(this_rq(), eas_stats.sis_idle);
+			return target;
+		}
+
+		/*
+		 * If the prevous cpu is cache affine and idle, don't be stupid.
+		 */
+		if (prev != target && cpus_share_cache(prev, target) && idle_cpu(prev)) {
+			schedstat_inc(p, se.statistics.nr_wakeups_sis_cache_affine);
+			schedstat_inc(this_rq(), eas_stats.sis_cache_affine);
+			return prev;
+		}
+	}
 
 	/*
 	 * Otherwise, iterate the domains and find an elegible idle cpu.
@@ -4857,60 +6093,327 @@
 	for_each_lower_domain(sd) {
 		sg = sd->groups;
 		do {
+			int i;
 			if (!cpumask_intersects(sched_group_cpus(sg),
 						tsk_cpus_allowed(p)))
 				goto next;
 
-			for_each_cpu(i, sched_group_cpus(sg)) {
-				if (i == target || !idle_cpu(i))
-					goto next;
-			}
+			if (sysctl_sched_cstate_aware) {
+				for_each_cpu_and(i, tsk_cpus_allowed(p), sched_group_cpus(sg)) {
+					int idle_idx = idle_get_state_idx(cpu_rq(i));
+					unsigned long new_usage = boosted_task_util(p);
+					unsigned long capacity_orig = capacity_orig_of(i);
 
-			target = cpumask_first_and(sched_group_cpus(sg),
+					if (new_usage > capacity_orig || !idle_cpu(i))
+						goto next;
+
+					if (i == target && new_usage <= capacity_curr_of(target)) {
+						schedstat_inc(p, se.statistics.nr_wakeups_sis_suff_cap);
+						schedstat_inc(this_rq(), eas_stats.sis_suff_cap);
+						schedstat_inc(sd, eas_stats.sis_suff_cap);
+						return target;
+					}
+
+					if (idle_idx < best_idle_cstate &&
+					    capacity_orig <= best_idle_capacity) {
+						best_idle_cpu = i;
+						best_idle_cstate = idle_idx;
+						best_idle_capacity = capacity_orig;
+					}
+				}
+			} else {
+				for_each_cpu(i, sched_group_cpus(sg)) {
+					if (i == target || !idle_cpu(i))
+						goto next;
+				}
+
+				target = cpumask_first_and(sched_group_cpus(sg),
 					tsk_cpus_allowed(p));
-			goto done;
+				schedstat_inc(p, se.statistics.nr_wakeups_sis_idle_cpu);
+				schedstat_inc(this_rq(), eas_stats.sis_idle_cpu);
+				schedstat_inc(sd, eas_stats.sis_idle_cpu);
+				goto done;
+			}
 next:
 			sg = sg->next;
 		} while (sg != sd->groups);
 	}
+
+	if (best_idle_cpu >= 0)
+		target = best_idle_cpu;
+
 done:
+	schedstat_inc(p, se.statistics.nr_wakeups_sis_count);
+	schedstat_inc(this_rq(), eas_stats.sis_count);
+
 	return target;
 }
 
 /*
- * cpu_util returns the amount of capacity of a CPU that is used by CFS
- * tasks. The unit of the return value must be the one of capacity so we can
- * compare the utilization with the capacity of the CPU that is available for
- * CFS task (ie cpu_capacity).
- *
- * cfs_rq.avg.util_avg is the sum of running time of runnable tasks plus the
- * recent utilization of currently non-runnable tasks on a CPU. It represents
- * the amount of utilization of a CPU in the range [0..capacity_orig] where
- * capacity_orig is the cpu_capacity available at the highest frequency
- * (arch_scale_freq_capacity()).
- * The utilization of a CPU converges towards a sum equal to or less than the
- * current capacity (capacity_curr <= capacity_orig) of the CPU because it is
- * the running time on this CPU scaled by capacity_curr.
- *
- * Nevertheless, cfs_rq.avg.util_avg can be higher than capacity_curr or even
- * higher than capacity_orig because of unfortunate rounding in
- * cfs.avg.util_avg or just after migrating tasks and new task wakeups until
- * the average stabilizes with the new running time. We need to check that the
- * utilization stays within the range of [0..capacity_orig] and cap it if
- * necessary. Without utilization capping, a group could be seen as overloaded
- * (CPU0 utilization at 121% + CPU1 utilization at 80%) whereas CPU1 has 20% of
- * available capacity. We allow utilization to overshoot capacity_curr (but not
- * capacity_orig) as it useful for predicting the capacity required after task
- * migrations (scheduler-driven DVFS).
+ * cpu_util_wake: Compute cpu utilization with any contributions from
+ * the waking task p removed.
  */
-static int cpu_util(int cpu)
+static int cpu_util_wake(int cpu, struct task_struct *p)
 {
-	unsigned long util = cpu_rq(cpu)->cfs.avg.util_avg;
-	unsigned long capacity = capacity_orig_of(cpu);
+	unsigned long util, capacity;
+
+#ifdef CONFIG_SCHED_WALT
+	/*
+	 * WALT does not decay idle tasks in the same manner
+	 * as PELT, so it makes little sense to subtract task
+	 * utilization from cpu utilization. Instead just use
+	 * cpu_util for this case.
+	 */
+	if (!walt_disabled && sysctl_sched_use_walt_cpu_util)
+		return cpu_util(cpu);
+#endif
+	/* Task has no contribution or is new */
+	if (cpu != task_cpu(p) || !p->se.avg.last_update_time)
+		return cpu_util(cpu);
+
+	capacity = capacity_orig_of(cpu);
+	util = max_t(long, cpu_util(cpu) - task_util(p), 0);
 
 	return (util >= capacity) ? capacity : util;
 }
 
+static int start_cpu(bool boosted)
+{
+	struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
+
+	RCU_LOCKDEP_WARN(rcu_read_lock_sched_held(),
+			   "sched RCU must be held");
+
+	return boosted ? rd->max_cap_orig_cpu : rd->min_cap_orig_cpu;
+}
+
+static inline int find_best_target(struct task_struct *p, bool boosted, bool prefer_idle)
+{
+	int target_cpu = -1;
+	unsigned long target_util = prefer_idle ? ULONG_MAX : 0;
+	unsigned long backup_capacity = ULONG_MAX;
+	int best_idle_cpu = -1;
+	int best_idle_cstate = INT_MAX;
+	int backup_cpu = -1;
+	unsigned long min_util = boosted_task_util(p);
+	struct sched_domain *sd;
+	struct sched_group *sg;
+	int cpu = start_cpu(boosted);
+
+	schedstat_inc(p, se.statistics.nr_wakeups_fbt_attempts);
+	schedstat_inc(this_rq(), eas_stats.fbt_attempts);
+
+	if (cpu < 0) {
+		schedstat_inc(p, se.statistics.nr_wakeups_fbt_no_cpu);
+		schedstat_inc(this_rq(), eas_stats.fbt_no_cpu);
+		return target_cpu;
+	}
+
+	sd = rcu_dereference(per_cpu(sd_ea, cpu));
+
+	if (!sd) {
+		schedstat_inc(p, se.statistics.nr_wakeups_fbt_no_sd);
+		schedstat_inc(this_rq(), eas_stats.fbt_no_sd);
+		return target_cpu;
+	}
+
+	sg = sd->groups;
+
+	do {
+		int i;
+
+		for_each_cpu_and(i, tsk_cpus_allowed(p), sched_group_cpus(sg)) {
+			unsigned long cur_capacity, new_util, wake_util;
+			unsigned long min_wake_util = ULONG_MAX;
+
+			if (!cpu_online(i))
+				continue;
+
+			/*
+			 * p's blocked utilization is still accounted for on prev_cpu
+			 * so prev_cpu will receive a negative bias due to the double
+			 * accounting. However, the blocked utilization may be zero.
+			 */
+			wake_util = cpu_util_wake(i, p);
+			new_util = wake_util + task_util(p);
+
+			/*
+			 * Ensure minimum capacity to grant the required boost.
+			 * The target CPU can be already at a capacity level higher
+			 * than the one required to boost the task.
+			 */
+			new_util = max(min_util, new_util);
+
+			if (new_util > capacity_orig_of(i))
+				continue;
+
+#ifdef CONFIG_SCHED_WALT
+			if (walt_cpu_high_irqload(i))
+				continue;
+#endif
+
+			/*
+			 * Unconditionally favoring tasks that prefer idle cpus to
+			 * improve latency.
+			 */
+			if (idle_cpu(i) && prefer_idle) {
+				schedstat_inc(p, se.statistics.nr_wakeups_fbt_pref_idle);
+				schedstat_inc(this_rq(), eas_stats.fbt_pref_idle);
+				return i;
+			}
+
+			cur_capacity = capacity_curr_of(i);
+
+			if (new_util < cur_capacity) {
+				if (cpu_rq(i)->nr_running) {
+					/*
+					 * Find a target cpu with the lowest/highest
+					 * utilization if prefer_idle/!prefer_idle.
+					 */
+					if (prefer_idle) {
+						/* Favor the CPU that last ran the task */
+						if (new_util > target_util ||
+						    wake_util > min_wake_util)
+							continue;
+						min_wake_util = wake_util;
+						target_util = new_util;
+						target_cpu = i;
+					} else if (target_util < new_util) {
+						target_util = new_util;
+						target_cpu = i;
+					}
+				} else if (!prefer_idle) {
+					int idle_idx = idle_get_state_idx(cpu_rq(i));
+
+					if (best_idle_cpu < 0 ||
+						(sysctl_sched_cstate_aware &&
+							best_idle_cstate > idle_idx)) {
+						best_idle_cstate = idle_idx;
+						best_idle_cpu = i;
+					}
+				}
+			} else if (backup_capacity > cur_capacity) {
+				/* Find a backup cpu with least capacity. */
+				backup_capacity = cur_capacity;
+				backup_cpu = i;
+			}
+		}
+	} while (sg = sg->next, sg != sd->groups);
+
+	if (target_cpu < 0)
+		target_cpu = best_idle_cpu >= 0 ? best_idle_cpu : backup_cpu;
+
+	if (target_cpu >= 0) {
+		schedstat_inc(p, se.statistics.nr_wakeups_fbt_count);
+		schedstat_inc(this_rq(), eas_stats.fbt_count);
+	}
+
+	return target_cpu;
+}
+
+/*
+ * Disable WAKE_AFFINE in the case where task @p doesn't fit in the
+ * capacity of either the waking CPU @cpu or the previous CPU @prev_cpu.
+ *
+ * In that case WAKE_AFFINE doesn't make sense and we'll let
+ * BALANCE_WAKE sort things out.
+ */
+static int wake_cap(struct task_struct *p, int cpu, int prev_cpu)
+{
+	long min_cap, max_cap;
+
+	min_cap = min(capacity_orig_of(prev_cpu), capacity_orig_of(cpu));
+	max_cap = cpu_rq(cpu)->rd->max_cpu_capacity.val;
+
+	/* Minimum capacity is close to max, no need to abort wake_affine */
+	if (max_cap - min_cap < max_cap >> 3)
+		return 0;
+
+	/* Bring task utilization in sync with prev_cpu */
+	sync_entity_load_avg(&p->se);
+
+	return min_cap * 1024 < task_util(p) * capacity_margin;
+}
+
+static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu, int sync)
+{
+	struct sched_domain *sd;
+	int target_cpu = prev_cpu, tmp_target;
+	bool boosted, prefer_idle;
+
+	schedstat_inc(p, se.statistics.nr_wakeups_secb_attempts);
+	schedstat_inc(this_rq(), eas_stats.secb_attempts);
+
+	if (sysctl_sched_sync_hint_enable && sync) {
+		int cpu = smp_processor_id();
+
+		if (cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) {
+			schedstat_inc(p, se.statistics.nr_wakeups_secb_sync);
+			schedstat_inc(this_rq(), eas_stats.secb_sync);
+			return cpu;
+		}
+	}
+
+	rcu_read_lock();
+#ifdef CONFIG_CGROUP_SCHEDTUNE
+	boosted = schedtune_task_boost(p) > 0;
+	prefer_idle = schedtune_prefer_idle(p) > 0;
+#else
+	boosted = get_sysctl_sched_cfs_boost() > 0;
+	prefer_idle = 0;
+#endif
+
+	sd = rcu_dereference(per_cpu(sd_ea, prev_cpu));
+	/* Find a cpu with sufficient capacity */
+	tmp_target = find_best_target(p, boosted, prefer_idle);
+
+	if (!sd)
+		goto unlock;
+	if (tmp_target >= 0) {
+		target_cpu = tmp_target;
+		if ((boosted || prefer_idle) && idle_cpu(target_cpu)) {
+			schedstat_inc(p, se.statistics.nr_wakeups_secb_idle_bt);
+			schedstat_inc(this_rq(), eas_stats.secb_idle_bt);
+			goto unlock;
+		}
+	}
+
+	if (target_cpu != prev_cpu) {
+		struct energy_env eenv = {
+			.util_delta     = task_util(p),
+			.src_cpu        = prev_cpu,
+			.dst_cpu        = target_cpu,
+			.task           = p,
+		};
+
+		/* Not enough spare capacity on previous cpu */
+		if (cpu_overutilized(prev_cpu)) {
+			schedstat_inc(p, se.statistics.nr_wakeups_secb_insuff_cap);
+			schedstat_inc(this_rq(), eas_stats.secb_insuff_cap);
+			goto unlock;
+		}
+
+		if (energy_diff(&eenv) >= 0) {
+			schedstat_inc(p, se.statistics.nr_wakeups_secb_no_nrg_sav);
+			schedstat_inc(this_rq(), eas_stats.secb_no_nrg_sav);
+			target_cpu = prev_cpu;
+			goto unlock;
+		}
+
+		schedstat_inc(p, se.statistics.nr_wakeups_secb_nrg_sav);
+		schedstat_inc(this_rq(), eas_stats.secb_nrg_sav);
+		goto unlock;
+	}
+
+	schedstat_inc(p, se.statistics.nr_wakeups_secb_count);
+	schedstat_inc(this_rq(), eas_stats.secb_count);
+
+unlock:
+	rcu_read_unlock();
+
+	return target_cpu;
+}
+
 /*
  * select_task_rq_fair: Select target runqueue for the waking task in domains
  * that have the 'sd_flag' flag set. In practice, this is SD_BALANCE_WAKE,
@@ -4932,8 +6435,19 @@
 	int want_affine = 0;
 	int sync = wake_flags & WF_SYNC;
 
-	if (sd_flag & SD_BALANCE_WAKE)
-		want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, tsk_cpus_allowed(p));
+	if (sd_flag & SD_BALANCE_WAKE) {
+		/*
+		 * do wake_cap unconditionally as it causes task and cpu
+		 * utilization to be synced, and we need that for energy
+		 * aware wakeups
+		 */
+		int _wake_cap = wake_cap(p, cpu, prev_cpu);
+		want_affine = !wake_wide(p) && !_wake_cap
+			      && cpumask_test_cpu(cpu, tsk_cpus_allowed(p));
+	}
+
+	if (energy_aware() && !(cpu_rq(prev_cpu)->rd->overutilized))
+		return select_energy_cpu_brute(p, prev_cpu, sync);
 
 	rcu_read_lock();
 	for_each_domain(cpu, tmp) {
@@ -4958,47 +6472,65 @@
 
 	if (affine_sd) {
 		sd = NULL; /* Prefer wake_affine over balance flags */
-		if (cpu != prev_cpu && wake_affine(affine_sd, p, sync))
+		if (cpu != prev_cpu && wake_affine(affine_sd, p, prev_cpu, sync))
 			new_cpu = cpu;
 	}
 
 	if (!sd) {
 		if (sd_flag & SD_BALANCE_WAKE) /* XXX always ? */
-			new_cpu = select_idle_sibling(p, new_cpu);
+			new_cpu = select_idle_sibling(p, prev_cpu, new_cpu);
 
-	} else while (sd) {
-		struct sched_group *group;
-		int weight;
+	} else {
+		int wu = sd_flag & SD_BALANCE_WAKE;
+		int cas_cpu = -1;
 
-		if (!(sd->flags & sd_flag)) {
-			sd = sd->child;
-			continue;
+		if (wu) {
+			schedstat_inc(p, se.statistics.nr_wakeups_cas_attempts);
+			schedstat_inc(this_rq(), eas_stats.cas_attempts);
 		}
 
-		group = find_idlest_group(sd, p, cpu, sd_flag);
-		if (!group) {
-			sd = sd->child;
-			continue;
+		while (sd) {
+			struct sched_group *group;
+			int weight;
+
+			if (wu)
+				schedstat_inc(sd, eas_stats.cas_attempts);
+
+			if (!(sd->flags & sd_flag)) {
+				sd = sd->child;
+				continue;
+			}
+
+			group = find_idlest_group(sd, p, cpu, sd_flag);
+			if (!group) {
+				sd = sd->child;
+				continue;
+			}
+
+			new_cpu = find_idlest_cpu(group, p, cpu);
+			if (new_cpu == -1 || new_cpu == cpu) {
+				/* Now try balancing at a lower domain level of cpu */
+				sd = sd->child;
+				continue;
+			}
+
+			/* Now try balancing at a lower domain level of new_cpu */
+			cpu = cas_cpu = new_cpu;
+			weight = sd->span_weight;
+			sd = NULL;
+			for_each_domain(cpu, tmp) {
+				if (weight <= tmp->span_weight)
+					break;
+				if (tmp->flags & sd_flag)
+					sd = tmp;
+			}
+			/* while loop will break here if sd == NULL */
 		}
 
-		new_cpu = find_idlest_cpu(group, p, cpu);
-		if (new_cpu == -1 || new_cpu == cpu) {
-			/* Now try balancing at a lower domain level of cpu */
-			sd = sd->child;
-			continue;
+		if (wu && (cas_cpu >= 0)) {
+			schedstat_inc(p, se.statistics.nr_wakeups_cas_count);
+			schedstat_inc(this_rq(), eas_stats.cas_count);
 		}
-
-		/* Now try balancing at a lower domain level of new_cpu */
-		cpu = new_cpu;
-		weight = sd->span_weight;
-		sd = NULL;
-		for_each_domain(cpu, tmp) {
-			if (weight <= tmp->span_weight)
-				break;
-			if (tmp->flags & sd_flag)
-				sd = tmp;
-		}
-		/* while loop will break here if sd == NULL */
 	}
 	rcu_read_unlock();
 
@@ -5033,6 +6565,8 @@
 {
 	remove_entity_load_avg(&p->se);
 }
+#else
+#define task_fits_max(p, cpu) true
 #endif /* CONFIG_SMP */
 
 static unsigned long
@@ -5279,6 +6813,8 @@
 	if (hrtick_enabled(rq))
 		hrtick_start_fair(rq, p);
 
+	rq->misfit_task = !task_fits_max(p, rq->cpu);
+
 	return p;
 simple:
 	cfs_rq = &rq->cfs;
@@ -5300,9 +6836,12 @@
 	if (hrtick_enabled(rq))
 		hrtick_start_fair(rq, p);
 
+	rq->misfit_task = !task_fits_max(p, rq->cpu);
+
 	return p;
 
 idle:
+	rq->misfit_task = 0;
 	/*
 	 * This is OK, because current is on_cpu, which avoids it being picked
 	 * for load-balance and preemption/IRQs are still disabled avoiding
@@ -5515,6 +7054,13 @@
 
 enum fbq_type { regular, remote, all };
 
+enum group_type {
+	group_other = 0,
+	group_misfit_task,
+	group_imbalanced,
+	group_overloaded,
+};
+
 #define LBF_ALL_PINNED	0x01
 #define LBF_NEED_BREAK	0x02
 #define LBF_DST_PINNED  0x04
@@ -5533,6 +7079,7 @@
 	int			new_dst_cpu;
 	enum cpu_idle_type	idle;
 	long			imbalance;
+	unsigned int		src_grp_nr_running;
 	/* The set of CPUs under consideration for load-balancing */
 	struct cpumask		*cpus;
 
@@ -5543,6 +7090,7 @@
 	unsigned int		loop_max;
 
 	enum fbq_type		fbq_type;
+	enum group_type		busiest_group_type;
 	struct list_head	tasks;
 };
 
@@ -5724,7 +7272,9 @@
 
 	deactivate_task(env->src_rq, p, 0);
 	p->on_rq = TASK_ON_RQ_MIGRATING;
+	double_lock_balance(env->src_rq, env->dst_rq);
 	set_task_cpu(p, env->dst_cpu);
+	double_unlock_balance(env->src_rq, env->dst_rq);
 }
 
 /*
@@ -5869,6 +7419,10 @@
 {
 	raw_spin_lock(&rq->lock);
 	attach_task(rq, p);
+	/*
+	 * We want to potentially raise target_cpu's OPP.
+	 */
+	update_capacity_of(cpu_of(rq));
 	raw_spin_unlock(&rq->lock);
 }
 
@@ -5890,6 +7444,11 @@
 		attach_task(env->dst_rq, p);
 	}
 
+	/*
+	 * We want to potentially raise env.dst_cpu's OPP.
+	 */
+	update_capacity_of(env->dst_cpu);
+
 	raw_spin_unlock(&env->dst_rq->lock);
 }
 
@@ -5912,8 +7471,13 @@
 		if (throttled_hierarchy(cfs_rq))
 			continue;
 
-		if (update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq))
+		if (update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq,
+					   true))
 			update_tg_load_avg(cfs_rq, 0);
+
+		/* Propagate pending load changes to the parent */
+		if (cfs_rq->tg->se[cpu])
+			update_load_avg(cfs_rq->tg->se[cpu], 0);
 	}
 	raw_spin_unlock_irqrestore(&rq->lock, flags);
 }
@@ -5973,7 +7537,7 @@
 
 	raw_spin_lock_irqsave(&rq->lock, flags);
 	update_rq_clock(rq);
-	update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq);
+	update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq, true);
 	raw_spin_unlock_irqrestore(&rq->lock, flags);
 }
 
@@ -5985,12 +7549,6 @@
 
 /********** Helpers for find_busiest_group ************************/
 
-enum group_type {
-	group_other = 0,
-	group_imbalanced,
-	group_overloaded,
-};
-
 /*
  * sg_lb_stats - stats of a sched_group required for load_balancing
  */
@@ -6006,6 +7564,7 @@
 	unsigned int group_weight;
 	enum group_type group_type;
 	int group_no_capacity;
+	int group_misfit_task; /* A cpu has a task too big for its capacity */
 #ifdef CONFIG_NUMA_BALANCING
 	unsigned int nr_numa_running;
 	unsigned int nr_preferred_running;
@@ -6097,19 +7656,58 @@
 
 	used = div_u64(avg, total);
 
+	/*
+	 * deadline bandwidth is defined at system level so we must
+	 * weight this bandwidth with the max capacity of the system.
+	 * As a reminder, avg_bw is 20bits width and
+	 * scale_cpu_capacity is 10 bits width
+	 */
+	used += div_u64(rq->dl.avg_bw, arch_scale_cpu_capacity(NULL, cpu));
+
 	if (likely(used < SCHED_CAPACITY_SCALE))
 		return SCHED_CAPACITY_SCALE - used;
 
 	return 1;
 }
 
+void init_max_cpu_capacity(struct max_cpu_capacity *mcc)
+{
+	raw_spin_lock_init(&mcc->lock);
+	mcc->val = 0;
+	mcc->cpu = -1;
+}
+
 static void update_cpu_capacity(struct sched_domain *sd, int cpu)
 {
 	unsigned long capacity = arch_scale_cpu_capacity(sd, cpu);
 	struct sched_group *sdg = sd->groups;
+	struct max_cpu_capacity *mcc;
+	unsigned long max_capacity;
+	int max_cap_cpu;
+	unsigned long flags;
 
 	cpu_rq(cpu)->cpu_capacity_orig = capacity;
 
+	mcc = &cpu_rq(cpu)->rd->max_cpu_capacity;
+
+	raw_spin_lock_irqsave(&mcc->lock, flags);
+	max_capacity = mcc->val;
+	max_cap_cpu = mcc->cpu;
+
+	if ((max_capacity > capacity && max_cap_cpu == cpu) ||
+	    (max_capacity < capacity)) {
+		mcc->val = capacity;
+		mcc->cpu = cpu;
+#ifdef CONFIG_SCHED_DEBUG
+		raw_spin_unlock_irqrestore(&mcc->lock, flags);
+		printk_deferred(KERN_INFO "CPU%d: update max cpu_capacity %lu\n",
+				cpu, capacity);
+		goto skip_unlock;
+#endif
+	}
+	raw_spin_unlock_irqrestore(&mcc->lock, flags);
+
+skip_unlock: __attribute__ ((unused));
 	capacity *= scale_rt_capacity(cpu);
 	capacity >>= SCHED_CAPACITY_SHIFT;
 
@@ -6118,13 +7716,15 @@
 
 	cpu_rq(cpu)->cpu_capacity = capacity;
 	sdg->sgc->capacity = capacity;
+	sdg->sgc->max_capacity = capacity;
+	sdg->sgc->min_capacity = capacity;
 }
 
 void update_group_capacity(struct sched_domain *sd, int cpu)
 {
 	struct sched_domain *child = sd->child;
 	struct sched_group *group, *sdg = sd->groups;
-	unsigned long capacity;
+	unsigned long capacity, max_capacity, min_capacity;
 	unsigned long interval;
 
 	interval = msecs_to_jiffies(sd->balance_interval);
@@ -6137,6 +7737,8 @@
 	}
 
 	capacity = 0;
+	max_capacity = 0;
+	min_capacity = ULONG_MAX;
 
 	if (child->flags & SD_OVERLAP) {
 		/*
@@ -6161,11 +7763,13 @@
 			 */
 			if (unlikely(!rq->sd)) {
 				capacity += capacity_of(cpu);
-				continue;
+			} else {
+				sgc = rq->sd->groups->sgc;
+				capacity += sgc->capacity;
 			}
 
-			sgc = rq->sd->groups->sgc;
-			capacity += sgc->capacity;
+			max_capacity = max(capacity, max_capacity);
+			min_capacity = min(capacity, min_capacity);
 		}
 	} else  {
 		/*
@@ -6175,12 +7779,18 @@
 
 		group = child->groups;
 		do {
-			capacity += group->sgc->capacity;
+			struct sched_group_capacity *sgc = group->sgc;
+
+			capacity += sgc->capacity;
+			max_capacity = max(sgc->max_capacity, max_capacity);
+			min_capacity = min(sgc->min_capacity, min_capacity);
 			group = group->next;
 		} while (group != child->groups);
 	}
 
 	sdg->sgc->capacity = capacity;
+	sdg->sgc->max_capacity = max_capacity;
+	sdg->sgc->min_capacity = min_capacity;
 }
 
 /*
@@ -6275,6 +7885,18 @@
 	return false;
 }
 
+
+/*
+ * group_smaller_cpu_capacity: Returns true if sched_group sg has smaller
+ * per-cpu capacity than sched_group ref.
+ */
+static inline bool
+group_smaller_cpu_capacity(struct sched_group *sg, struct sched_group *ref)
+{
+	return sg->sgc->max_capacity + capacity_margin - SCHED_LOAD_SCALE <
+							ref->sgc->max_capacity;
+}
+
 static inline enum
 group_type group_classify(struct sched_group *group,
 			  struct sg_lb_stats *sgs)
@@ -6285,6 +7907,9 @@
 	if (sg_imbalanced(group))
 		return group_imbalanced;
 
+	if (sgs->group_misfit_task)
+		return group_misfit_task;
+
 	return group_other;
 }
 
@@ -6296,14 +7921,15 @@
  * @local_group: Does group contain this_cpu.
  * @sgs: variable to hold the statistics for this group.
  * @overload: Indicate more than one runnable task for any CPU.
+ * @overutilized: Indicate overutilization for any CPU.
  */
 static inline void update_sg_lb_stats(struct lb_env *env,
 			struct sched_group *group, int load_idx,
 			int local_group, struct sg_lb_stats *sgs,
-			bool *overload)
+			bool *overload, bool *overutilized)
 {
 	unsigned long load;
-	int i;
+	int i, nr_running;
 
 	memset(sgs, 0, sizeof(*sgs));
 
@@ -6320,7 +7946,8 @@
 		sgs->group_util += cpu_util(i);
 		sgs->sum_nr_running += rq->cfs.h_nr_running;
 
-		if (rq->nr_running > 1)
+		nr_running = rq->nr_running;
+		if (nr_running > 1)
 			*overload = true;
 
 #ifdef CONFIG_NUMA_BALANCING
@@ -6328,8 +7955,17 @@
 		sgs->nr_preferred_running += rq->nr_preferred_running;
 #endif
 		sgs->sum_weighted_load += weighted_cpuload(i);
-		if (idle_cpu(i))
+		/*
+		 * No need to call idle_cpu() if nr_running is not 0
+		 */
+		if (!nr_running && idle_cpu(i))
 			sgs->idle_cpus++;
+
+		if (cpu_overutilized(i)) {
+			*overutilized = true;
+			if (!sgs->group_misfit_task && rq->misfit_task)
+				sgs->group_misfit_task = capacity_of(i);
+		}
 	}
 
 	/* Adjust by relative CPU capacity of the group */
@@ -6371,9 +8007,31 @@
 	if (sgs->group_type < busiest->group_type)
 		return false;
 
+	/*
+	 * Candidate sg doesn't face any serious load-balance problems
+	 * so don't pick it if the local sg is already filled up.
+	 */
+	if (sgs->group_type == group_other &&
+	    !group_has_capacity(env, &sds->local_stat))
+		return false;
+
 	if (sgs->avg_load <= busiest->avg_load)
 		return false;
 
+	if (!(env->sd->flags & SD_ASYM_CPUCAPACITY))
+		goto asym_packing;
+
+	/*
+	 * Candidate sg has no more than one task per CPU and
+	 * has higher per-CPU capacity. Migrating tasks to less
+	 * capable CPUs may harm throughput. Maximize throughput,
+	 * power/energy consequences are not considered.
+	 */
+	if (sgs->sum_nr_running <= sgs->group_weight &&
+	    group_smaller_cpu_capacity(sds->local, sg))
+		return false;
+
+asym_packing:
 	/* This is the busiest node in its class. */
 	if (!(env->sd->flags & SD_ASYM_PACKING))
 		return true;
@@ -6424,6 +8082,9 @@
 }
 #endif /* CONFIG_NUMA_BALANCING */
 
+#define lb_sd_parent(sd) \
+	(sd->parent && sd->parent->groups != sd->parent->groups->next)
+
 /**
  * update_sd_lb_stats - Update sched_domain's statistics for load balancing.
  * @env: The load balancing environment.
@@ -6435,7 +8096,7 @@
 	struct sched_group *sg = env->sd->groups;
 	struct sg_lb_stats tmp_sgs;
 	int load_idx, prefer_sibling = 0;
-	bool overload = false;
+	bool overload = false, overutilized = false;
 
 	if (child && child->flags & SD_PREFER_SIBLING)
 		prefer_sibling = 1;
@@ -6457,7 +8118,7 @@
 		}
 
 		update_sg_lb_stats(env, sg, load_idx, local_group, sgs,
-						&overload);
+						&overload, &overutilized);
 
 		if (local_group)
 			goto next_group;
@@ -6479,6 +8140,15 @@
 			sgs->group_type = group_classify(sg, sgs);
 		}
 
+		/*
+		 * Ignore task groups with misfit tasks if local group has no
+		 * capacity or if per-cpu capacity isn't higher.
+		 */
+		if (sgs->group_type == group_misfit_task &&
+		    (!group_has_capacity(env, &sds->local_stat) ||
+		     !group_smaller_cpu_capacity(sg, sds->local)))
+			sgs->group_type = group_other;
+
 		if (update_sd_pick_busiest(env, sds, sg, sgs)) {
 			sds->busiest = sg;
 			sds->busiest_stat = *sgs;
@@ -6495,10 +8165,23 @@
 	if (env->sd->flags & SD_NUMA)
 		env->fbq_type = fbq_classify_group(&sds->busiest_stat);
 
-	if (!env->sd->parent) {
+	env->src_grp_nr_running = sds->busiest_stat.sum_nr_running;
+
+	if (!lb_sd_parent(env->sd)) {
 		/* update overload indicator if we are at root domain */
 		if (env->dst_rq->rd->overload != overload)
 			env->dst_rq->rd->overload = overload;
+
+		/* Update over-utilization (tipping point, U >= 0) indicator */
+		if (env->dst_rq->rd->overutilized != overutilized) {
+			env->dst_rq->rd->overutilized = overutilized;
+			trace_sched_overutilized(overutilized);
+		}
+	} else {
+		if (!env->dst_rq->rd->overutilized && overutilized) {
+			env->dst_rq->rd->overutilized = true;
+			trace_sched_overutilized(true);
+		}
 	}
 
 }
@@ -6647,6 +8330,22 @@
 	 */
 	if (busiest->avg_load <= sds->avg_load ||
 	    local->avg_load >= sds->avg_load) {
+		/* Misfitting tasks should be migrated in any case */
+		if (busiest->group_type == group_misfit_task) {
+			env->imbalance = busiest->group_misfit_task;
+			return;
+		}
+
+		/*
+		 * Busiest group is overloaded, local is not, use the spare
+		 * cycles to maximize throughput
+		 */
+		if (busiest->group_type == group_overloaded &&
+		    local->group_type <= group_misfit_task) {
+			env->imbalance = busiest->load_per_task;
+			return;
+		}
+
 		env->imbalance = 0;
 		return fix_small_imbalance(env, sds);
 	}
@@ -6680,6 +8379,11 @@
 		(sds->avg_load - local->avg_load) * local->group_capacity
 	) / SCHED_CAPACITY_SCALE;
 
+	/* Boost imbalance to allow misfit task to be balanced. */
+	if (busiest->group_type == group_misfit_task)
+		env->imbalance = max_t(long, env->imbalance,
+				     busiest->group_misfit_task);
+
 	/*
 	 * if *imbalance is less than the average load per runnable task
 	 * there is no guarantee that any tasks will be moved so we'll have
@@ -6721,6 +8425,10 @@
 	 * this level.
 	 */
 	update_sd_lb_stats(env, &sds);
+
+	if (energy_aware() && !env->dst_rq->rd->overutilized)
+		goto out_balanced;
+
 	local = &sds.local_stat;
 	busiest = &sds.busiest_stat;
 
@@ -6749,6 +8457,11 @@
 	    busiest->group_no_capacity)
 		goto force_balance;
 
+	/* Misfitting tasks should be dealt with regardless of the avg load */
+	if (busiest->group_type == group_misfit_task) {
+		goto force_balance;
+	}
+
 	/*
 	 * If the local group is busier than the selected busiest group
 	 * don't try and pull any tasks.
@@ -6772,7 +8485,8 @@
 		 * might end up to just move the imbalance on another group
 		 */
 		if ((busiest->group_type != group_overloaded) &&
-				(local->idle_cpus <= (busiest->idle_cpus + 1)))
+		    (local->idle_cpus <= (busiest->idle_cpus + 1)) &&
+		    !group_smaller_cpu_capacity(sds.busiest, sds.local))
 			goto out_balanced;
 	} else {
 		/*
@@ -6785,6 +8499,7 @@
 	}
 
 force_balance:
+	env->busiest_group_type = busiest->group_type;
 	/* Looks like there is an imbalance. Compute it */
 	calculate_imbalance(env, &sds);
 	return sds.busiest;
@@ -6843,7 +8558,8 @@
 		 */
 
 		if (rq->nr_running == 1 && wl > env->imbalance &&
-		    !check_cpu_capacity(rq, env->sd))
+		    !check_cpu_capacity(rq, env->sd) &&
+		    env->busiest_group_type != group_misfit_task)
 			continue;
 
 		/*
@@ -6904,6 +8620,13 @@
 			return 1;
 	}
 
+	if ((capacity_of(env->src_cpu) < capacity_of(env->dst_cpu)) &&
+				env->src_rq->cfs.h_nr_running == 1 &&
+				cpu_overutilized(env->src_cpu) &&
+				!cpu_overutilized(env->dst_cpu)) {
+			return 1;
+	}
+
 	return unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2);
 }
 
@@ -6952,7 +8675,7 @@
 			int *continue_balancing)
 {
 	int ld_moved, cur_ld_moved, active_balance = 0;
-	struct sched_domain *sd_parent = sd->parent;
+	struct sched_domain *sd_parent = lb_sd_parent(sd) ? sd->parent : NULL;
 	struct sched_group *group;
 	struct rq *busiest;
 	unsigned long flags;
@@ -7025,6 +8748,11 @@
 		 * ld_moved     - cumulative load moved across iterations
 		 */
 		cur_ld_moved = detach_tasks(&env);
+		/*
+		 * We want to potentially lower env.src_cpu's OPP.
+		 */
+		if (cur_ld_moved)
+			update_capacity_of(env.src_cpu);
 
 		/*
 		 * We've detached some tasks from busiest_rq. Every
@@ -7116,7 +8844,8 @@
 		 * excessive cache_hot migrations and active balances.
 		 */
 		if (idle != CPU_NEWLY_IDLE)
-			sd->nr_balance_failed++;
+			if (env.src_grp_nr_running > 1)
+				sd->nr_balance_failed++;
 
 		if (need_active_balance(&env)) {
 			raw_spin_lock_irqsave(&busiest->lock, flags);
@@ -7248,6 +8977,7 @@
 	struct sched_domain *sd;
 	int pulled_task = 0;
 	u64 curr_cost = 0;
+	long removed_util=0;
 
 	idle_enter_fair(this_rq);
 
@@ -7257,8 +8987,9 @@
 	 */
 	this_rq->idle_stamp = rq_clock(this_rq);
 
-	if (this_rq->avg_idle < sysctl_sched_migration_cost ||
-	    !this_rq->rd->overload) {
+	if (!energy_aware() &&
+	    (this_rq->avg_idle < sysctl_sched_migration_cost ||
+	     !this_rq->rd->overload)) {
 		rcu_read_lock();
 		sd = rcu_dereference_check_sched_domain(this_rq->sd);
 		if (sd)
@@ -7270,6 +9001,17 @@
 
 	raw_spin_unlock(&this_rq->lock);
 
+	/*
+	 * If removed_util_avg is !0 we most probably migrated some task away
+	 * from this_cpu. In this case we might be willing to trigger an OPP
+	 * update, but we want to do so if we don't find anybody else to pull
+	 * here (we will trigger an OPP update with the pulled task's enqueue
+	 * anyway).
+	 *
+	 * Record removed_util before calling update_blocked_averages, and use
+	 * it below (before returning) to see if an OPP update is required.
+	 */
+	removed_util = atomic_long_read(&(this_rq->cfs).removed_util_avg);
 	update_blocked_averages(this_cpu);
 	rcu_read_lock();
 	for_each_domain(this_cpu, sd) {
@@ -7334,6 +9076,12 @@
 	if (pulled_task) {
 		idle_exit_fair(this_rq);
 		this_rq->idle_stamp = 0;
+	} else if (removed_util) {
+		/*
+		 * No task pulled and someone has been migrated away.
+		 * Good case to trigger an OPP update.
+		 */
+		update_capacity_of(this_cpu);
 	}
 
 	return pulled_task;
@@ -7393,8 +9141,13 @@
 		schedstat_inc(sd, alb_count);
 
 		p = detach_one_task(&env);
-		if (p)
+		if (p) {
 			schedstat_inc(sd, alb_pushed);
+			/*
+			 * We want to potentially lower env.src_cpu's OPP.
+			 */
+			update_capacity_of(env.src_cpu);
+		}
 		else
 			schedstat_inc(sd, alb_failed);
 	}
@@ -7774,12 +9527,13 @@
 	if (time_before(now, nohz.next_balance))
 		return false;
 
-	if (rq->nr_running >= 2)
+	if (rq->nr_running >= 2 &&
+	    (!energy_aware() || cpu_overutilized(cpu)))
 		return true;
 
 	rcu_read_lock();
 	sd = rcu_dereference(per_cpu(sd_busy, cpu));
-	if (sd) {
+	if (sd && !energy_aware()) {
 		sgc = sd->groups->sgc;
 		nr_busy = atomic_read(&sgc->nr_busy_cpus);
 
@@ -7885,6 +9639,16 @@
 
 	if (static_branch_unlikely(&sched_numa_balancing))
 		task_tick_numa(rq, curr);
+
+#ifdef CONFIG_SMP
+	if (!rq->rd->overutilized && cpu_overutilized(task_cpu(curr))) {
+		rq->rd->overutilized = true;
+		trace_sched_overutilized(true);
+	}
+
+	rq->misfit_task = !task_fits_max(curr, rq->cpu);
+#endif
+
 }
 
 /*
@@ -7986,6 +9750,61 @@
 	return false;
 }
 
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/*
+ * Propagate the changes of the sched_entity across the tg tree to make it
+ * visible to the root
+ */
+static void propagate_entity_cfs_rq(struct sched_entity *se)
+{
+	struct cfs_rq *cfs_rq;
+
+	/* Start to propagate at parent */
+	se = se->parent;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+
+		if (cfs_rq_throttled(cfs_rq))
+			break;
+
+		update_load_avg(se, UPDATE_TG);
+	}
+}
+#else
+static void propagate_entity_cfs_rq(struct sched_entity *se) { }
+#endif
+
+static void detach_entity_cfs_rq(struct sched_entity *se)
+{
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+	/* Catch up with the cfs_rq and remove our load when we leave */
+	update_load_avg(se, 0);
+	detach_entity_load_avg(cfs_rq, se);
+	update_tg_load_avg(cfs_rq, false);
+	propagate_entity_cfs_rq(se);
+}
+
+static void attach_entity_cfs_rq(struct sched_entity *se)
+{
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	/*
+	 * Since the real-depth could have been changed (only FAIR
+	 * class maintain depth value), reset depth properly.
+	 */
+	se->depth = se->parent ? se->parent->depth + 1 : 0;
+#endif
+
+	/* Synchronize entity with its cfs_rq */
+	update_load_avg(se, sched_feat(ATTACH_AGE_LOAD) ? 0 : SKIP_AGE_LOAD);
+	attach_entity_load_avg(cfs_rq, se);
+	update_tg_load_avg(cfs_rq, false);
+	propagate_entity_cfs_rq(se);
+}
+
 static void detach_task_cfs_rq(struct task_struct *p)
 {
 	struct sched_entity *se = &p->se;
@@ -8000,8 +9819,7 @@
 		se->vruntime -= cfs_rq->min_vruntime;
 	}
 
-	/* Catch up with the cfs_rq and remove our load when we leave */
-	detach_entity_load_avg(cfs_rq, se);
+	detach_entity_cfs_rq(se);
 }
 
 static void attach_task_cfs_rq(struct task_struct *p)
@@ -8009,16 +9827,7 @@
 	struct sched_entity *se = &p->se;
 	struct cfs_rq *cfs_rq = cfs_rq_of(se);
 
-#ifdef CONFIG_FAIR_GROUP_SCHED
-	/*
-	 * Since the real-depth could have been changed (only FAIR
-	 * class maintain depth value), reset depth properly.
-	 */
-	se->depth = se->parent ? se->parent->depth + 1 : 0;
-#endif
-
-	/* Synchronize task with its cfs_rq */
-	attach_entity_load_avg(cfs_rq, se);
+	attach_entity_cfs_rq(se);
 
 	if (!vruntime_normalized(p))
 		se->vruntime += cfs_rq->min_vruntime;
@@ -8072,6 +9881,9 @@
 	cfs_rq->min_vruntime_copy = cfs_rq->min_vruntime;
 #endif
 #ifdef CONFIG_SMP
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	cfs_rq->propagate_avg = 0;
+#endif
 	atomic_long_set(&cfs_rq->removed_load_avg, 0);
 	atomic_long_set(&cfs_rq->removed_util_avg, 0);
 #endif
@@ -8112,8 +9924,9 @@
 
 int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
 {
-	struct cfs_rq *cfs_rq;
 	struct sched_entity *se;
+	struct cfs_rq *cfs_rq;
+	struct rq *rq;
 	int i;
 
 	tg->cfs_rq = kzalloc(sizeof(cfs_rq) * nr_cpu_ids, GFP_KERNEL);
@@ -8128,6 +9941,8 @@
 	init_cfs_bandwidth(tg_cfs_bandwidth(tg));
 
 	for_each_possible_cpu(i) {
+		rq = cpu_rq(i);
+
 		cfs_rq = kzalloc_node(sizeof(struct cfs_rq),
 				      GFP_KERNEL, cpu_to_node(i));
 		if (!cfs_rq)
@@ -8141,6 +9956,10 @@
 		init_cfs_rq(cfs_rq);
 		init_tg_cfs_entry(tg, cfs_rq, se, i, parent->se[i]);
 		init_entity_runnable_average(se);
+
+		raw_spin_lock_irq(&rq->lock);
+		post_init_entity_util_avg(se);
+		raw_spin_unlock_irq(&rq->lock);
 	}
 
 	return 1;
@@ -8229,8 +10048,10 @@
 
 		/* Possible calls to update_curr() need rq clock */
 		update_rq_clock(rq);
-		for_each_sched_entity(se)
-			update_cfs_shares(group_cfs_rq(se));
+		for_each_sched_entity(se) {
+			update_load_avg(se, UPDATE_TG);
+			update_cfs_shares(se);
+		}
 		raw_spin_unlock_irqrestore(&rq->lock, flags);
 	}
 
diff --git a/kernel/sched/features.h b/kernel/sched/features.h
index 69631fa..55e4610 100644
--- a/kernel/sched/features.h
+++ b/kernel/sched/features.h
@@ -69,3 +69,12 @@
 SCHED_FEAT(LB_MIN, false)
 SCHED_FEAT(ATTACH_AGE_LOAD, true)
 
+/*
+ * Energy aware scheduling. Use platform energy model to guide scheduling
+ * decisions optimizing for energy efficiency.
+ */
+#ifdef CONFIG_DEFAULT_USE_ENERGY_AWARE
+SCHED_FEAT(ENERGY_AWARE, true)
+#else
+SCHED_FEAT(ENERGY_AWARE, false)
+#endif
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index 4a2ef5a..917c94a 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -19,9 +19,10 @@
  * sched_idle_set_state - Record idle state for the current CPU.
  * @idle_state: State to record.
  */
-void sched_idle_set_state(struct cpuidle_state *idle_state)
+void sched_idle_set_state(struct cpuidle_state *idle_state, int index)
 {
 	idle_set_state(this_rq(), idle_state);
+	idle_set_state_idx(this_rq(), index);
 }
 
 static int __read_mostly cpu_idle_force_poll;
@@ -219,6 +220,7 @@
 		 */
 
 		__current_set_polling();
+		quiet_vmstat();
 		tick_nohz_idle_enter();
 
 		while (!need_resched()) {
diff --git a/kernel/sched/loadavg.c b/kernel/sched/loadavg.c
index ef71590..f8e8d68 100644
--- a/kernel/sched/loadavg.c
+++ b/kernel/sched/loadavg.c
@@ -99,10 +99,13 @@
 static unsigned long
 calc_load(unsigned long load, unsigned long exp, unsigned long active)
 {
-	load *= exp;
-	load += active * (FIXED_1 - exp);
-	load += 1UL << (FSHIFT - 1);
-	return load >> FSHIFT;
+	unsigned long newload;
+
+	newload = load * exp + active * (FIXED_1 - exp);
+	if (active >= load)
+		newload += FIXED_1-1;
+
+	return newload / FIXED_1;
 }
 
 #ifdef CONFIG_NO_HZ_COMMON
@@ -198,8 +201,9 @@
 	struct rq *this_rq = this_rq();
 
 	/*
-	 * If we're still before the sample window, we're done.
+	 * If we're still before the pending sample window, we're done.
 	 */
+	this_rq->calc_load_update = calc_load_update;
 	if (time_before(jiffies, this_rq->calc_load_update))
 		return;
 
@@ -208,7 +212,6 @@
 	 * accounted through the nohz accounting, so skip the entire deal and
 	 * sync up for the next window.
 	 */
-	this_rq->calc_load_update = calc_load_update;
 	if (time_before(jiffies, this_rq->calc_load_update + 10))
 		this_rq->calc_load_update += LOAD_FREQ;
 }
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 8ec86ab..6bb51d6 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -8,6 +8,8 @@
 #include <linux/slab.h>
 #include <linux/irq_work.h>
 
+#include "walt.h"
+
 int sched_rr_timeslice = RR_TIMESLICE;
 
 static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun);
@@ -889,6 +891,51 @@
 	return rt_task_of(rt_se)->prio;
 }
 
+static void dump_throttled_rt_tasks(struct rt_rq *rt_rq)
+{
+	struct rt_prio_array *array = &rt_rq->active;
+	struct sched_rt_entity *rt_se;
+	char buf[500];
+	char *pos = buf;
+	char *end = buf + sizeof(buf);
+	int idx;
+
+	pos += snprintf(pos, sizeof(buf),
+		"sched: RT throttling activated for rt_rq %p (cpu %d)\n",
+		rt_rq, cpu_of(rq_of_rt_rq(rt_rq)));
+
+	if (bitmap_empty(array->bitmap, MAX_RT_PRIO))
+		goto out;
+
+	pos += snprintf(pos, end - pos, "potential CPU hogs:\n");
+	idx = sched_find_first_bit(array->bitmap);
+	while (idx < MAX_RT_PRIO) {
+		list_for_each_entry(rt_se, array->queue + idx, run_list) {
+			struct task_struct *p;
+
+			if (!rt_entity_is_task(rt_se))
+				continue;
+
+			p = rt_task_of(rt_se);
+			if (pos < end)
+				pos += snprintf(pos, end - pos, "\t%s (%d)\n",
+					p->comm, p->pid);
+		}
+		idx = find_next_bit(array->bitmap, MAX_RT_PRIO, idx + 1);
+	}
+out:
+#ifdef CONFIG_PANIC_ON_RT_THROTTLING
+	/*
+	 * Use pr_err() in the BUG() case since printk_sched() will
+	 * not get flushed and deadlock is not a concern.
+	 */
+	pr_err("%s", buf);
+	BUG();
+#else
+	printk_deferred("%s", buf);
+#endif
+}
+
 static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)
 {
 	u64 runtime = sched_rt_runtime(rt_rq);
@@ -912,8 +959,14 @@
 		 * but accrue some time due to boosting.
 		 */
 		if (likely(rt_b->rt_runtime)) {
+			static bool once = false;
+
 			rt_rq->rt_throttled = 1;
-			printk_deferred_once("sched: RT throttling activated\n");
+
+			if (!once) {
+				once = true;
+				dump_throttled_rt_tasks(rt_rq);
+			}
 		} else {
 			/*
 			 * In case we did anyway, make it go away,
@@ -949,6 +1002,9 @@
 	if (unlikely((s64)delta_exec <= 0))
 		return;
 
+	/* Kick cpufreq (see the comment in kernel/sched/sched.h). */
+	cpufreq_update_this_cpu(rq, SCHED_CPUFREQ_RT);
+
 	schedstat_set(curr->se.statistics.exec_max,
 		      max(curr->se.statistics.exec_max, delta_exec));
 
@@ -1261,6 +1317,7 @@
 		rt_se->timeout = 0;
 
 	enqueue_rt_entity(rt_se, flags & ENQUEUE_HEAD);
+	walt_inc_cumulative_runnable_avg(rq, p);
 
 	if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
 		enqueue_pushable_task(rq, p);
@@ -1272,6 +1329,7 @@
 
 	update_curr_rt(rq);
 	dequeue_rt_entity(rt_se);
+	walt_dec_cumulative_runnable_avg(rq, p);
 
 	dequeue_pushable_task(rq, p);
 }
@@ -1426,6 +1484,41 @@
 #endif
 }
 
+#ifdef CONFIG_SMP
+static void sched_rt_update_capacity_req(struct rq *rq)
+{
+	u64 total, used, age_stamp, avg;
+	s64 delta;
+
+	if (!sched_freq())
+		return;
+
+	sched_avg_update(rq);
+	/*
+	 * Since we're reading these variables without serialization make sure
+	 * we read them once before doing sanity checks on them.
+	 */
+	age_stamp = READ_ONCE(rq->age_stamp);
+	avg = READ_ONCE(rq->rt_avg);
+	delta = rq_clock(rq) - age_stamp;
+
+	if (unlikely(delta < 0))
+		delta = 0;
+
+	total = sched_avg_period() + delta;
+
+	used = div_u64(avg, total);
+	if (unlikely(used > SCHED_CAPACITY_SCALE))
+		used = SCHED_CAPACITY_SCALE;
+
+	set_rt_cpu_capacity(rq->cpu, 1, (unsigned long)(used));
+}
+#else
+static inline void sched_rt_update_capacity_req(struct rq *rq)
+{ }
+
+#endif
+
 static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq,
 						   struct rt_rq *rt_rq)
 {
@@ -1494,8 +1587,17 @@
 	if (prev->sched_class == &rt_sched_class)
 		update_curr_rt(rq);
 
-	if (!rt_rq->rt_queued)
+	if (!rt_rq->rt_queued) {
+		/*
+		 * The next task to be picked on this rq will have a lower
+		 * priority than rt tasks so we can spend some time to update
+		 * the capacity used by rt tasks based on the last activity.
+		 * This value will be the used as an estimation of the next
+		 * activity.
+		 */
+		sched_rt_update_capacity_req(rq);
 		return NULL;
+	}
 
 	put_prev_task(rq, prev);
 
@@ -2136,10 +2238,9 @@
 #ifdef CONFIG_SMP
 		if (p->nr_cpus_allowed > 1 && rq->rt.overloaded)
 			queue_push_tasks(rq);
-#else
+#endif /* CONFIG_SMP */
 		if (p->prio < rq->curr->prio)
 			resched_curr(rq);
-#endif /* CONFIG_SMP */
 	}
 }
 
@@ -2212,6 +2313,9 @@
 
 	update_curr_rt(rq);
 
+	if (rq->rt.rt_nr_running)
+		sched_rt_update_capacity_req(rq);
+
 	watchdog(rq, p);
 
 	/*
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 0517abd..ce364dd 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -376,6 +376,7 @@
 	unsigned long runnable_load_avg;
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	unsigned long tg_load_avg_contrib;
+	unsigned long propagate_avg;
 #endif
 	atomic_long_t removed_load_avg, removed_util_avg;
 #ifndef CONFIG_64BIT
@@ -410,6 +411,10 @@
 	struct list_head leaf_cfs_rq_list;
 	struct task_group *tg;	/* group that "owns" this runqueue */
 
+#ifdef CONFIG_SCHED_WALT
+	u64 cumulative_runnable_avg;
+#endif
+
 #ifdef CONFIG_CFS_BANDWIDTH
 	int runtime_enabled;
 	u64 runtime_expires;
@@ -417,7 +422,7 @@
 
 	u64 throttled_clock, throttled_clock_task;
 	u64 throttled_clock_task_time;
-	int throttled, throttle_count;
+	int throttled, throttle_count, throttle_uptodate;
 	struct list_head throttled_list;
 #endif /* CONFIG_CFS_BANDWIDTH */
 #endif /* CONFIG_FAIR_GROUP_SCHED */
@@ -506,10 +511,18 @@
 #else
 	struct dl_bw dl_bw;
 #endif
+	/* This is the "average utilization" for this runqueue */
+	s64 avg_bw;
 };
 
 #ifdef CONFIG_SMP
 
+struct max_cpu_capacity {
+	raw_spinlock_t lock;
+	unsigned long val;
+	int cpu;
+};
+
 /*
  * We add the notion of a root-domain which will be used to define per-domain
  * variables. Each exclusive cpuset essentially defines an island domain by
@@ -528,6 +541,9 @@
 	/* Indicate more than one runnable task for any CPU */
 	bool overload;
 
+	/* Indicate one or more cpus over-utilized (tipping point) */
+	bool overutilized;
+
 	/*
 	 * The bit corresponding to a CPU gets set here if such CPU has more
 	 * than one runnable -deadline task (as it is below for RT tasks).
@@ -543,6 +559,12 @@
 	 */
 	cpumask_var_t rto_mask;
 	struct cpupri cpupri;
+
+	/* Maximum cpu capacity in the system. */
+	struct max_cpu_capacity max_cpu_capacity;
+
+	/* First cpu with maximum and minimum original capacity */
+	int max_cap_orig_cpu, min_cap_orig_cpu;
 };
 
 extern struct root_domain def_root_domain;
@@ -572,6 +594,7 @@
 	#define CPU_LOAD_IDX_MAX 5
 	unsigned long cpu_load[CPU_LOAD_IDX_MAX];
 	unsigned long last_load_update_tick;
+	unsigned int misfit_task;
 #ifdef CONFIG_NO_HZ_COMMON
 	u64 nohz_stamp;
 	unsigned long nohz_flags;
@@ -579,6 +602,14 @@
 #ifdef CONFIG_NO_HZ_FULL
 	unsigned long last_sched_tick;
 #endif
+
+#ifdef CONFIG_CPU_QUIET
+	/* time-based average load */
+	u64 nr_last_stamp;
+	u64 nr_running_integral;
+	seqcount_t ave_seqcnt;
+#endif
+
 	/* capture load from *all* tasks on this cpu: */
 	struct load_weight load;
 	unsigned long nr_load_updates;
@@ -591,6 +622,7 @@
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	/* list of leaf cfs_rq on this cpu: */
 	struct list_head leaf_cfs_rq_list;
+	struct list_head *tmp_alone_branch;
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
 	/*
@@ -640,6 +672,30 @@
 	u64 max_idle_balance_cost;
 #endif
 
+#ifdef CONFIG_SCHED_WALT
+	/*
+	 * max_freq = user or thermal defined maximum
+	 * max_possible_freq = maximum supported by hardware
+	 */
+	unsigned int cur_freq, max_freq, min_freq, max_possible_freq;
+	struct cpumask freq_domain_cpumask;
+
+	u64 cumulative_runnable_avg;
+	int efficiency; /* Differentiate cpus with different IPC capability */
+	int load_scale_factor;
+	int capacity;
+	int max_possible_capacity;
+	u64 window_start;
+	u64 curr_runnable_sum;
+	u64 prev_runnable_sum;
+	u64 nt_curr_runnable_sum;
+	u64 nt_prev_runnable_sum;
+	u64 cur_irqload;
+	u64 avg_irqload;
+	u64 irqload_ts;
+#endif /* CONFIG_SCHED_WALT */
+
+
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
 	u64 prev_irq_time;
 #endif
@@ -678,6 +734,9 @@
 	/* try_to_wake_up() stats */
 	unsigned int ttwu_count;
 	unsigned int ttwu_local;
+#ifdef CONFIG_SMP
+	struct eas_stats eas_stats;
+#endif
 #endif
 
 #ifdef CONFIG_SMP
@@ -687,6 +746,7 @@
 #ifdef CONFIG_CPU_IDLE
 	/* Must be inspected within a rcu lock section */
 	struct cpuidle_state *idle_state;
+	int idle_state_idx;
 #endif
 };
 
@@ -836,6 +896,8 @@
 DECLARE_PER_CPU(struct sched_domain *, sd_numa);
 DECLARE_PER_CPU(struct sched_domain *, sd_busy);
 DECLARE_PER_CPU(struct sched_domain *, sd_asym);
+DECLARE_PER_CPU(struct sched_domain *, sd_ea);
+DECLARE_PER_CPU(struct sched_domain *, sd_scs);
 
 struct sched_group_capacity {
 	atomic_t ref;
@@ -843,7 +905,9 @@
 	 * CPU capacity of this group, SCHED_LOAD_SCALE being max capacity
 	 * for a single CPU.
 	 */
-	unsigned int capacity;
+	unsigned long capacity;
+	unsigned long max_capacity; /* Max per-cpu capacity in group */
+	unsigned long min_capacity; /* Min per-CPU capacity in group */
 	unsigned long next_update;
 	int imbalance; /* XXX unrelated to capacity but shared group state */
 	/*
@@ -860,6 +924,7 @@
 
 	unsigned int group_weight;
 	struct sched_group_capacity *sgc;
+	const struct sched_group_energy *sge;
 
 	/*
 	 * The CPUs this group covers.
@@ -1163,6 +1228,7 @@
 #endif
 #define ENQUEUE_REPLENISH	0x08
 #define ENQUEUE_RESTORE	0x10
+#define ENQUEUE_WAKEUP_NEW	0x20
 
 #define DEQUEUE_SLEEP		0x01
 #define DEQUEUE_SAVE		0x02
@@ -1248,6 +1314,7 @@
 
 #ifdef CONFIG_SMP
 
+extern void init_max_cpu_capacity(struct max_cpu_capacity *mcc);
 extern void update_group_capacity(struct sched_domain *sd, int cpu);
 
 extern void trigger_load_balance(struct rq *rq);
@@ -1276,6 +1343,17 @@
 	WARN_ON(!rcu_read_lock_held());
 	return rq->idle_state;
 }
+
+static inline void idle_set_state_idx(struct rq *rq, int idle_state_idx)
+{
+	rq->idle_state_idx = idle_state_idx;
+}
+
+static inline int idle_get_state_idx(struct rq *rq)
+{
+	WARN_ON(!rcu_read_lock_held());
+	return rq->idle_state_idx;
+}
 #else
 static inline void idle_set_state(struct rq *rq,
 				  struct cpuidle_state *idle_state)
@@ -1286,6 +1364,15 @@
 {
 	return NULL;
 }
+
+static inline void idle_set_state_idx(struct rq *rq, int idle_state_idx)
+{
+}
+
+static inline int idle_get_state_idx(struct rq *rq)
+{
+	return -1;
+}
 #endif
 
 extern void sysrq_sched_debug_show(void);
@@ -1309,8 +1396,9 @@
 unsigned long to_ratio(u64 period, u64 runtime);
 
 extern void init_entity_runnable_average(struct sched_entity *se);
+extern void post_init_entity_util_avg(struct sched_entity *se);
 
-static inline void add_nr_running(struct rq *rq, unsigned count)
+static inline void __add_nr_running(struct rq *rq, unsigned count)
 {
 	unsigned prev_nr = rq->nr_running;
 
@@ -1338,11 +1426,48 @@
 	}
 }
 
-static inline void sub_nr_running(struct rq *rq, unsigned count)
+static inline void __sub_nr_running(struct rq *rq, unsigned count)
 {
 	rq->nr_running -= count;
 }
 
+#ifdef CONFIG_CPU_QUIET
+#define NR_AVE_SCALE(x)		((x) << FSHIFT)
+static inline u64 do_nr_running_integral(struct rq *rq)
+{
+	s64 nr, deltax;
+	u64 nr_running_integral = rq->nr_running_integral;
+
+	deltax = rq->clock_task - rq->nr_last_stamp;
+	nr = NR_AVE_SCALE(rq->nr_running);
+
+	nr_running_integral += nr * deltax;
+
+	return nr_running_integral;
+}
+
+static inline void add_nr_running(struct rq *rq, unsigned count)
+{
+	write_seqcount_begin(&rq->ave_seqcnt);
+	rq->nr_running_integral = do_nr_running_integral(rq);
+	rq->nr_last_stamp = rq->clock_task;
+	__add_nr_running(rq, count);
+	write_seqcount_end(&rq->ave_seqcnt);
+}
+
+static inline void sub_nr_running(struct rq *rq, unsigned count)
+{
+	write_seqcount_begin(&rq->ave_seqcnt);
+	rq->nr_running_integral = do_nr_running_integral(rq);
+	rq->nr_last_stamp = rq->clock_task;
+	__sub_nr_running(rq, count);
+	write_seqcount_end(&rq->ave_seqcnt);
+}
+#else
+#define add_nr_running __add_nr_running
+#define sub_nr_running __sub_nr_running
+#endif
+
 static inline void rq_last_tick_reset(struct rq *rq)
 {
 #ifdef CONFIG_NO_HZ_FULL
@@ -1415,10 +1540,146 @@
 }
 #endif
 
+#ifdef CONFIG_SMP
+static inline unsigned long capacity_of(int cpu)
+{
+	return cpu_rq(cpu)->cpu_capacity;
+}
+
+static inline unsigned long capacity_orig_of(int cpu)
+{
+	return cpu_rq(cpu)->cpu_capacity_orig;
+}
+
+extern unsigned int sysctl_sched_use_walt_cpu_util;
+extern unsigned int walt_ravg_window;
+extern unsigned int walt_disabled;
+
+/*
+ * cpu_util returns the amount of capacity of a CPU that is used by CFS
+ * tasks. The unit of the return value must be the one of capacity so we can
+ * compare the utilization with the capacity of the CPU that is available for
+ * CFS task (ie cpu_capacity).
+ *
+ * cfs_rq.avg.util_avg is the sum of running time of runnable tasks plus the
+ * recent utilization of currently non-runnable tasks on a CPU. It represents
+ * the amount of utilization of a CPU in the range [0..capacity_orig] where
+ * capacity_orig is the cpu_capacity available at the highest frequency
+ * (arch_scale_freq_capacity()).
+ * The utilization of a CPU converges towards a sum equal to or less than the
+ * current capacity (capacity_curr <= capacity_orig) of the CPU because it is
+ * the running time on this CPU scaled by capacity_curr.
+ *
+ * Nevertheless, cfs_rq.avg.util_avg can be higher than capacity_curr or even
+ * higher than capacity_orig because of unfortunate rounding in
+ * cfs.avg.util_avg or just after migrating tasks and new task wakeups until
+ * the average stabilizes with the new running time. We need to check that the
+ * utilization stays within the range of [0..capacity_orig] and cap it if
+ * necessary. Without utilization capping, a group could be seen as overloaded
+ * (CPU0 utilization at 121% + CPU1 utilization at 80%) whereas CPU1 has 20% of
+ * available capacity. We allow utilization to overshoot capacity_curr (but not
+ * capacity_orig) as it useful for predicting the capacity required after task
+ * migrations (scheduler-driven DVFS).
+ */
+static inline unsigned long __cpu_util(int cpu, int delta)
+{
+	unsigned long util = cpu_rq(cpu)->cfs.avg.util_avg;
+	unsigned long capacity = capacity_orig_of(cpu);
+
+#ifdef CONFIG_SCHED_WALT
+	if (!walt_disabled && sysctl_sched_use_walt_cpu_util) {
+		util = cpu_rq(cpu)->prev_runnable_sum << SCHED_LOAD_SHIFT;
+		do_div(util, walt_ravg_window);
+	}
+#endif
+	delta += util;
+	if (delta < 0)
+		return 0;
+
+	return (delta >= capacity) ? capacity : delta;
+}
+
+static inline unsigned long cpu_util(int cpu)
+{
+	return __cpu_util(cpu, 0);
+}
+
+#endif
+
+#ifdef CONFIG_CPU_FREQ_GOV_SCHED
+#define capacity_max SCHED_CAPACITY_SCALE
+extern unsigned int capacity_margin;
+extern struct static_key __sched_freq;
+
+static inline bool sched_freq(void)
+{
+	return static_key_false(&__sched_freq);
+}
+
+DECLARE_PER_CPU(struct sched_capacity_reqs, cpu_sched_capacity_reqs);
+void update_cpu_capacity_request(int cpu, bool request);
+
+static inline void set_cfs_cpu_capacity(int cpu, bool request,
+					unsigned long capacity)
+{
+	struct sched_capacity_reqs *scr = &per_cpu(cpu_sched_capacity_reqs, cpu);
+
+#ifdef CONFIG_SCHED_WALT
+       if (!walt_disabled && sysctl_sched_use_walt_cpu_util) {
+		int rtdl = scr->rt + scr->dl;
+		/*
+		 * WALT tracks the utilization of a CPU considering the load
+		 * generated by all the scheduling classes.
+		 * Since the following call to:
+		 *    update_cpu_capacity
+		 * is already adding the RT and DL utilizations let's remove
+		 * these contributions from the WALT signal.
+		 */
+		if (capacity > rtdl)
+			capacity -= rtdl;
+		else
+			capacity = 0;
+	}
+#endif
+	if (scr->cfs != capacity) {
+		scr->cfs = capacity;
+		update_cpu_capacity_request(cpu, request);
+	}
+}
+
+static inline void set_rt_cpu_capacity(int cpu, bool request,
+				       unsigned long capacity)
+{
+	if (per_cpu(cpu_sched_capacity_reqs, cpu).rt != capacity) {
+		per_cpu(cpu_sched_capacity_reqs, cpu).rt = capacity;
+		update_cpu_capacity_request(cpu, request);
+	}
+}
+
+static inline void set_dl_cpu_capacity(int cpu, bool request,
+				       unsigned long capacity)
+{
+	if (per_cpu(cpu_sched_capacity_reqs, cpu).dl != capacity) {
+		per_cpu(cpu_sched_capacity_reqs, cpu).dl = capacity;
+		update_cpu_capacity_request(cpu, request);
+	}
+}
+#else
+static inline bool sched_freq(void) { return false; }
+static inline void set_cfs_cpu_capacity(int cpu, bool request,
+					unsigned long capacity)
+{ }
+static inline void set_rt_cpu_capacity(int cpu, bool request,
+				       unsigned long capacity)
+{ }
+static inline void set_dl_cpu_capacity(int cpu, bool request,
+				       unsigned long capacity)
+{ }
+#endif
+
 static inline void sched_rt_avg_update(struct rq *rq, u64 rt_delta)
 {
 	rq->rt_avg += rt_delta * arch_scale_freq_capacity(NULL, cpu_of(rq));
-	sched_avg_update(rq);
 }
 #else
 static inline void sched_rt_avg_update(struct rq *rq, u64 rt_delta) { }
@@ -1507,6 +1768,9 @@
 	raw_spin_unlock_irqrestore(&p->pi_lock, *flags);
 }
 
+extern struct rq *lock_rq_of(struct task_struct *p, unsigned long *flags);
+extern void unlock_rq_of(struct rq *rq, struct task_struct *p, unsigned long *flags);
+
 #ifdef CONFIG_SMP
 #ifdef CONFIG_PREEMPT
 
@@ -1579,7 +1843,8 @@
 static inline void double_unlock_balance(struct rq *this_rq, struct rq *busiest)
 	__releases(busiest->lock)
 {
-	raw_spin_unlock(&busiest->lock);
+	if (this_rq != busiest)
+		raw_spin_unlock(&busiest->lock);
 	lock_set_subclass(&this_rq->lock.dep_map, 0, _RET_IP_);
 }
 
@@ -1783,3 +2048,55 @@
 	rq->prev_steal_time_rq = 0;
 #endif
 }
+
+#ifdef CONFIG_CPU_FREQ
+DECLARE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
+
+/**
+ * cpufreq_update_util - Take a note about CPU utilization changes.
+ * @rq: Runqueue to carry out the update for.
+ * @flags: Update reason flags.
+ *
+ * This function is called by the scheduler on the CPU whose utilization is
+ * being updated.
+ *
+ * It can only be called from RCU-sched read-side critical sections.
+ *
+ * The way cpufreq is currently arranged requires it to evaluate the CPU
+ * performance state (frequency/voltage) on a regular basis to prevent it from
+ * being stuck in a completely inadequate performance level for too long.
+ * That is not guaranteed to happen if the updates are only triggered from CFS,
+ * though, because they may not be coming in if RT or deadline tasks are active
+ * all the time (or there are RT and DL tasks only).
+ *
+ * As a workaround for that issue, this function is called by the RT and DL
+ * sched classes to trigger extra cpufreq updates to prevent it from stalling,
+ * but that really is a band-aid.  Going forward it should be replaced with
+ * solutions targeted more specifically at RT and DL tasks.
+ */
+static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
+{
+        struct update_util_data *data;
+
+        data = rcu_dereference_sched(*this_cpu_ptr(&cpufreq_update_util_data));
+        if (data)
+                data->func(data, rq_clock(rq), flags);
+}
+
+static inline void cpufreq_update_this_cpu(struct rq *rq, unsigned int flags)
+{
+        if (cpu_of(rq) == smp_processor_id())
+                cpufreq_update_util(rq, flags);
+}
+#else
+static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {}
+static inline void cpufreq_update_this_cpu(struct rq *rq, unsigned int flags) {}
+#endif /* CONFIG_CPU_FREQ */
+
+#ifdef arch_scale_freq_capacity
+#ifndef arch_scale_freq_invariant
+#define arch_scale_freq_invariant()     (true)
+#endif
+#else /* arch_scale_freq_capacity */
+#define arch_scale_freq_invariant()     (false)
+#endif
diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c
index 87e2c9f..6d74a7c 100644
--- a/kernel/sched/stats.c
+++ b/kernel/sched/stats.c
@@ -12,6 +12,28 @@
  */
 #define SCHEDSTAT_VERSION 15
 
+#ifdef CONFIG_SMP
+static inline void show_easstat(struct seq_file *seq, struct eas_stats *stats)
+{
+	/* eas-specific runqueue stats */
+	seq_printf(seq, "eas %llu %llu %llu %llu %llu %llu ",
+	    stats->sis_attempts, stats->sis_idle, stats->sis_cache_affine,
+	    stats->sis_suff_cap, stats->sis_idle_cpu, stats->sis_count);
+
+	seq_printf(seq, "%llu %llu %llu %llu %llu %llu %llu ",
+	    stats->secb_attempts, stats->secb_sync, stats->secb_idle_bt,
+	    stats->secb_insuff_cap, stats->secb_no_nrg_sav,
+	    stats->secb_nrg_sav, stats->secb_count);
+
+	seq_printf(seq, "%llu %llu %llu %llu %llu ",
+	    stats->fbt_attempts, stats->fbt_no_cpu, stats->fbt_no_sd,
+	    stats->fbt_pref_idle, stats->fbt_count);
+
+	seq_printf(seq, "%llu %llu\n",
+	    stats->cas_attempts, stats->cas_count);
+}
+#endif
+
 static int show_schedstat(struct seq_file *seq, void *v)
 {
 	int cpu;
@@ -40,6 +62,8 @@
 		seq_printf(seq, "\n");
 
 #ifdef CONFIG_SMP
+		show_easstat(seq, &rq->eas_stats);
+
 		/* domain-specific stats */
 		rcu_read_lock();
 		for_each_domain(cpu, sd) {
@@ -66,6 +90,8 @@
 			    sd->sbf_count, sd->sbf_balanced, sd->sbf_pushed,
 			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
 			    sd->ttwu_move_balance);
+
+			show_easstat(seq, &sd->eas_stats);
 		}
 		rcu_read_unlock();
 #endif
diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c
index cbc67da..61f852d 100644
--- a/kernel/sched/stop_task.c
+++ b/kernel/sched/stop_task.c
@@ -1,4 +1,5 @@
 #include "sched.h"
+#include "walt.h"
 
 /*
  * stop-task scheduling class.
@@ -42,12 +43,14 @@
 enqueue_task_stop(struct rq *rq, struct task_struct *p, int flags)
 {
 	add_nr_running(rq, 1);
+	walt_inc_cumulative_runnable_avg(rq, p);
 }
 
 static void
 dequeue_task_stop(struct rq *rq, struct task_struct *p, int flags)
 {
 	sub_nr_running(rq, 1);
+	walt_dec_cumulative_runnable_avg(rq, p);
 }
 
 static void yield_task_stop(struct rq *rq)
diff --git a/kernel/sched/tune.c b/kernel/sched/tune.c
new file mode 100644
index 0000000..86d04ca
--- /dev/null
+++ b/kernel/sched/tune.c
@@ -0,0 +1,956 @@
+#include <linux/cgroup.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/percpu.h>
+#include <linux/printk.h>
+#include <linux/rcupdate.h>
+#include <linux/slab.h>
+
+#include <trace/events/sched.h>
+
+#include "sched.h"
+#include "tune.h"
+
+#ifdef CONFIG_CGROUP_SCHEDTUNE
+bool schedtune_initialized = false;
+#endif
+
+unsigned int sysctl_sched_cfs_boost __read_mostly;
+
+extern struct reciprocal_value schedtune_spc_rdiv;
+extern struct target_nrg schedtune_target_nrg;
+
+/* Performance Boost region (B) threshold params */
+static int perf_boost_idx;
+
+/* Performance Constraint region (C) threshold params */
+static int perf_constrain_idx;
+
+/**
+ * Performance-Energy (P-E) Space thresholds constants
+ */
+struct threshold_params {
+	int nrg_gain;
+	int cap_gain;
+};
+
+/*
+ * System specific P-E space thresholds constants
+ */
+static struct threshold_params
+threshold_gains[] = {
+	{ 0, 5 }, /*   < 10% */
+	{ 1, 5 }, /*   < 20% */
+	{ 2, 5 }, /*   < 30% */
+	{ 3, 5 }, /*   < 40% */
+	{ 4, 5 }, /*   < 50% */
+	{ 5, 4 }, /*   < 60% */
+	{ 5, 3 }, /*   < 70% */
+	{ 5, 2 }, /*   < 80% */
+	{ 5, 1 }, /*   < 90% */
+	{ 5, 0 }  /* <= 100% */
+};
+
+static int
+__schedtune_accept_deltas(int nrg_delta, int cap_delta,
+			  int perf_boost_idx, int perf_constrain_idx)
+{
+	int payoff = -INT_MAX;
+	int gain_idx = -1;
+
+	/* Performance Boost (B) region */
+	if (nrg_delta >= 0 && cap_delta > 0)
+		gain_idx = perf_boost_idx;
+	/* Performance Constraint (C) region */
+	else if (nrg_delta < 0 && cap_delta <= 0)
+		gain_idx = perf_constrain_idx;
+
+	/* Default: reject schedule candidate */
+	if (gain_idx == -1)
+		return payoff;
+
+	/*
+	 * Evaluate "Performance Boost" vs "Energy Increase"
+	 *
+	 * - Performance Boost (B) region
+	 *
+	 *   Condition: nrg_delta > 0 && cap_delta > 0
+	 *   Payoff criteria:
+	 *     cap_gain / nrg_gain  < cap_delta / nrg_delta =
+	 *     cap_gain * nrg_delta < cap_delta * nrg_gain
+	 *   Note that since both nrg_gain and nrg_delta are positive, the
+	 *   inequality does not change. Thus:
+	 *
+	 *     payoff = (cap_delta * nrg_gain) - (cap_gain * nrg_delta)
+	 *
+	 * - Performance Constraint (C) region
+	 *
+	 *   Condition: nrg_delta < 0 && cap_delta < 0
+	 *   payoff criteria:
+	 *     cap_gain / nrg_gain  > cap_delta / nrg_delta =
+	 *     cap_gain * nrg_delta < cap_delta * nrg_gain
+	 *   Note that since nrg_gain > 0 while nrg_delta < 0, the
+	 *   inequality change. Thus:
+	 *
+	 *     payoff = (cap_delta * nrg_gain) - (cap_gain * nrg_delta)
+	 *
+	 * This means that, in case of same positive defined {cap,nrg}_gain
+	 * for both the B and C regions, we can use the same payoff formula
+	 * where a positive value represents the accept condition.
+	 */
+	payoff  = cap_delta * threshold_gains[gain_idx].nrg_gain;
+	payoff -= nrg_delta * threshold_gains[gain_idx].cap_gain;
+
+	return payoff;
+}
+
+#ifdef CONFIG_CGROUP_SCHEDTUNE
+
+/*
+ * EAS scheduler tunables for task groups.
+ */
+
+/* SchdTune tunables for a group of tasks */
+struct schedtune {
+	/* SchedTune CGroup subsystem */
+	struct cgroup_subsys_state css;
+
+	/* Boost group allocated ID */
+	int idx;
+
+	/* Boost value for tasks on that SchedTune CGroup */
+	int boost;
+
+	/* Performance Boost (B) region threshold params */
+	int perf_boost_idx;
+
+	/* Performance Constraint (C) region threshold params */
+	int perf_constrain_idx;
+
+	/* Hint to bias scheduling of tasks on that SchedTune CGroup
+	 * towards idle CPUs */
+	int prefer_idle;
+};
+
+static inline struct schedtune *css_st(struct cgroup_subsys_state *css)
+{
+	return css ? container_of(css, struct schedtune, css) : NULL;
+}
+
+static inline struct schedtune *task_schedtune(struct task_struct *tsk)
+{
+	return css_st(task_css(tsk, schedtune_cgrp_id));
+}
+
+static inline struct schedtune *parent_st(struct schedtune *st)
+{
+	return css_st(st->css.parent);
+}
+
+/*
+ * SchedTune root control group
+ * The root control group is used to defined a system-wide boosting tuning,
+ * which is applied to all tasks in the system.
+ * Task specific boost tuning could be specified by creating and
+ * configuring a child control group under the root one.
+ * By default, system-wide boosting is disabled, i.e. no boosting is applied
+ * to tasks which are not into a child control group.
+ */
+static struct schedtune
+root_schedtune = {
+	.boost	= 0,
+	.perf_boost_idx = 0,
+	.perf_constrain_idx = 0,
+	.prefer_idle = 0,
+};
+
+int
+schedtune_accept_deltas(int nrg_delta, int cap_delta,
+			struct task_struct *task)
+{
+	struct schedtune *ct;
+	int perf_boost_idx;
+	int perf_constrain_idx;
+
+	/* Optimal (O) region */
+	if (nrg_delta < 0 && cap_delta > 0) {
+		trace_sched_tune_filter(nrg_delta, cap_delta, 0, 0, 1, 0);
+		return INT_MAX;
+	}
+
+	/* Suboptimal (S) region */
+	if (nrg_delta > 0 && cap_delta < 0) {
+		trace_sched_tune_filter(nrg_delta, cap_delta, 0, 0, -1, 5);
+		return -INT_MAX;
+	}
+
+	/* Get task specific perf Boost/Constraints indexes */
+	rcu_read_lock();
+	ct = task_schedtune(task);
+	perf_boost_idx = ct->perf_boost_idx;
+	perf_constrain_idx = ct->perf_constrain_idx;
+	rcu_read_unlock();
+
+	return __schedtune_accept_deltas(nrg_delta, cap_delta,
+			perf_boost_idx, perf_constrain_idx);
+}
+
+/*
+ * Maximum number of boost groups to support
+ * When per-task boosting is used we still allow only limited number of
+ * boost groups for two main reasons:
+ * 1. on a real system we usually have only few classes of workloads which
+ *    make sense to boost with different values (e.g. background vs foreground
+ *    tasks, interactive vs low-priority tasks)
+ * 2. a limited number allows for a simpler and more memory/time efficient
+ *    implementation especially for the computation of the per-CPU boost
+ *    value
+ */
+#define BOOSTGROUPS_COUNT 5
+
+/* Array of configured boostgroups */
+static struct schedtune *allocated_group[BOOSTGROUPS_COUNT] = {
+	&root_schedtune,
+	NULL,
+};
+
+/* SchedTune boost groups
+ * Keep track of all the boost groups which impact on CPU, for example when a
+ * CPU has two RUNNABLE tasks belonging to two different boost groups and thus
+ * likely with different boost values.
+ * Since on each system we expect only a limited number of boost groups, here
+ * we use a simple array to keep track of the metrics required to compute the
+ * maximum per-CPU boosting value.
+ */
+struct boost_groups {
+	/* Maximum boost value for all RUNNABLE tasks on a CPU */
+	bool idle;
+	int boost_max;
+	struct {
+		/* The boost for tasks on that boost group */
+		int boost;
+		/* Count of RUNNABLE tasks on that boost group */
+		unsigned tasks;
+	} group[BOOSTGROUPS_COUNT];
+	/* CPU's boost group locking */
+	raw_spinlock_t lock;
+};
+
+/* Boost groups affecting each CPU in the system */
+DEFINE_PER_CPU(struct boost_groups, cpu_boost_groups);
+
+static void
+schedtune_cpu_update(int cpu)
+{
+	struct boost_groups *bg;
+	int boost_max;
+	int idx;
+
+	bg = &per_cpu(cpu_boost_groups, cpu);
+
+	/* The root boost group is always active */
+	boost_max = bg->group[0].boost;
+	for (idx = 1; idx < BOOSTGROUPS_COUNT; ++idx) {
+		/*
+		 * A boost group affects a CPU only if it has
+		 * RUNNABLE tasks on that CPU
+		 */
+		if (bg->group[idx].tasks == 0)
+			continue;
+
+		boost_max = max(boost_max, bg->group[idx].boost);
+	}
+	/* Ensures boost_max is non-negative when all cgroup boost values
+	 * are neagtive. Avoids under-accounting of cpu capacity which may cause
+	 * task stacking and frequency spikes.*/
+	boost_max = max(boost_max, 0);
+	bg->boost_max = boost_max;
+}
+
+static int
+schedtune_boostgroup_update(int idx, int boost)
+{
+	struct boost_groups *bg;
+	int cur_boost_max;
+	int old_boost;
+	int cpu;
+
+	/* Update per CPU boost groups */
+	for_each_possible_cpu(cpu) {
+		bg = &per_cpu(cpu_boost_groups, cpu);
+
+		/*
+		 * Keep track of current boost values to compute the per CPU
+		 * maximum only when it has been affected by the new value of
+		 * the updated boost group
+		 */
+		cur_boost_max = bg->boost_max;
+		old_boost = bg->group[idx].boost;
+
+		/* Update the boost value of this boost group */
+		bg->group[idx].boost = boost;
+
+		/* Check if this update increase current max */
+		if (boost > cur_boost_max && bg->group[idx].tasks) {
+			bg->boost_max = boost;
+			trace_sched_tune_boostgroup_update(cpu, 1, bg->boost_max);
+			continue;
+		}
+
+		/* Check if this update has decreased current max */
+		if (cur_boost_max == old_boost && old_boost > boost) {
+			schedtune_cpu_update(cpu);
+			trace_sched_tune_boostgroup_update(cpu, -1, bg->boost_max);
+			continue;
+		}
+
+		trace_sched_tune_boostgroup_update(cpu, 0, bg->boost_max);
+	}
+
+	return 0;
+}
+
+#define ENQUEUE_TASK  1
+#define DEQUEUE_TASK -1
+
+static inline void
+schedtune_tasks_update(struct task_struct *p, int cpu, int idx, int task_count)
+{
+	struct boost_groups *bg = &per_cpu(cpu_boost_groups, cpu);
+	int tasks = bg->group[idx].tasks + task_count;
+
+	/* Update boosted tasks count while avoiding to make it negative */
+	bg->group[idx].tasks = max(0, tasks);
+
+	trace_sched_tune_tasks_update(p, cpu, tasks, idx,
+			bg->group[idx].boost, bg->boost_max);
+
+	/* Boost group activation or deactivation on that RQ */
+	if (tasks == 1 || tasks == 0)
+		schedtune_cpu_update(cpu);
+}
+
+/*
+ * NOTE: This function must be called while holding the lock on the CPU RQ
+ */
+void schedtune_enqueue_task(struct task_struct *p, int cpu)
+{
+	struct boost_groups *bg = &per_cpu(cpu_boost_groups, cpu);
+	unsigned long irq_flags;
+	struct schedtune *st;
+	int idx;
+
+	if (!unlikely(schedtune_initialized))
+		return;
+
+	/*
+	 * When a task is marked PF_EXITING by do_exit() it's going to be
+	 * dequeued and enqueued multiple times in the exit path.
+	 * Thus we avoid any further update, since we do not want to change
+	 * CPU boosting while the task is exiting.
+	 */
+	if (p->flags & PF_EXITING)
+		return;
+
+	/*
+	 * Boost group accouting is protected by a per-cpu lock and requires
+	 * interrupt to be disabled to avoid race conditions for example on
+	 * do_exit()::cgroup_exit() and task migration.
+	 */
+	raw_spin_lock_irqsave(&bg->lock, irq_flags);
+	rcu_read_lock();
+
+	st = task_schedtune(p);
+	idx = st->idx;
+
+	schedtune_tasks_update(p, cpu, idx, ENQUEUE_TASK);
+
+	rcu_read_unlock();
+	raw_spin_unlock_irqrestore(&bg->lock, irq_flags);
+}
+
+int schedtune_can_attach(struct cgroup_taskset *tset)
+{
+	struct task_struct *task;
+	struct cgroup_subsys_state *css;
+	struct boost_groups *bg;
+	unsigned long irq_flags;
+	unsigned int cpu;
+	struct rq *rq;
+	int src_bg; /* Source boost group index */
+	int dst_bg; /* Destination boost group index */
+	int tasks;
+
+	if (!unlikely(schedtune_initialized))
+		return 0;
+
+
+	cgroup_taskset_for_each(task, css, tset) {
+
+		/*
+		 * Lock the CPU's RQ the task is enqueued to avoid race
+		 * conditions with migration code while the task is being
+		 * accounted
+		 */
+		rq = lock_rq_of(task, &irq_flags);
+
+		if (!task->on_rq) {
+			unlock_rq_of(rq, task, &irq_flags);
+			continue;
+		}
+
+		/*
+		 * Boost group accouting is protected by a per-cpu lock and requires
+		 * interrupt to be disabled to avoid race conditions on...
+		 */
+		cpu = cpu_of(rq);
+		bg = &per_cpu(cpu_boost_groups, cpu);
+		raw_spin_lock(&bg->lock);
+
+		dst_bg = css_st(css)->idx;
+		src_bg = task_schedtune(task)->idx;
+
+		/*
+		 * Current task is not changing boostgroup, which can
+		 * happen when the new hierarchy is in use.
+		 */
+		if (unlikely(dst_bg == src_bg)) {
+			raw_spin_unlock(&bg->lock);
+			unlock_rq_of(rq, task, &irq_flags);
+			continue;
+		}
+
+		/*
+		 * This is the case of a RUNNABLE task which is switching its
+		 * current boost group.
+		 */
+
+		/* Move task from src to dst boost group */
+		tasks = bg->group[src_bg].tasks - 1;
+		bg->group[src_bg].tasks = max(0, tasks);
+		bg->group[dst_bg].tasks += 1;
+
+		raw_spin_unlock(&bg->lock);
+		unlock_rq_of(rq, task, &irq_flags);
+
+		/* Update CPU boost group */
+		if (bg->group[src_bg].tasks == 0 || bg->group[dst_bg].tasks == 1)
+			schedtune_cpu_update(task_cpu(task));
+
+	}
+
+	return 0;
+}
+
+void schedtune_cancel_attach(struct cgroup_taskset *tset)
+{
+	/* This can happen only if SchedTune controller is mounted with
+	 * other hierarchies ane one of them fails. Since usually SchedTune is
+	 * mouted on its own hierarcy, for the time being we do not implement
+	 * a proper rollback mechanism */
+	WARN(1, "SchedTune cancel attach not implemented");
+}
+
+/*
+ * NOTE: This function must be called while holding the lock on the CPU RQ
+ */
+void schedtune_dequeue_task(struct task_struct *p, int cpu)
+{
+	struct boost_groups *bg = &per_cpu(cpu_boost_groups, cpu);
+	unsigned long irq_flags;
+	struct schedtune *st;
+	int idx;
+
+	if (!unlikely(schedtune_initialized))
+		return;
+
+	/*
+	 * When a task is marked PF_EXITING by do_exit() it's going to be
+	 * dequeued and enqueued multiple times in the exit path.
+	 * Thus we avoid any further update, since we do not want to change
+	 * CPU boosting while the task is exiting.
+	 * The last dequeue is already enforce by the do_exit() code path
+	 * via schedtune_exit_task().
+	 */
+	if (p->flags & PF_EXITING)
+		return;
+
+	/*
+	 * Boost group accouting is protected by a per-cpu lock and requires
+	 * interrupt to be disabled to avoid race conditions on...
+	 */
+	raw_spin_lock_irqsave(&bg->lock, irq_flags);
+	rcu_read_lock();
+
+	st = task_schedtune(p);
+	idx = st->idx;
+
+	schedtune_tasks_update(p, cpu, idx, DEQUEUE_TASK);
+
+	rcu_read_unlock();
+	raw_spin_unlock_irqrestore(&bg->lock, irq_flags);
+}
+
+void schedtune_exit_task(struct task_struct *tsk)
+{
+	struct schedtune *st;
+	unsigned long irq_flags;
+	unsigned int cpu;
+	struct rq *rq;
+	int idx;
+
+	if (!unlikely(schedtune_initialized))
+		return;
+
+	rq = lock_rq_of(tsk, &irq_flags);
+	rcu_read_lock();
+
+	cpu = cpu_of(rq);
+	st = task_schedtune(tsk);
+	idx = st->idx;
+	schedtune_tasks_update(tsk, cpu, idx, DEQUEUE_TASK);
+
+	rcu_read_unlock();
+	unlock_rq_of(rq, tsk, &irq_flags);
+}
+
+int schedtune_cpu_boost(int cpu)
+{
+	struct boost_groups *bg;
+
+	bg = &per_cpu(cpu_boost_groups, cpu);
+	return bg->boost_max;
+}
+
+int schedtune_task_boost(struct task_struct *p)
+{
+	struct schedtune *st;
+	int task_boost;
+
+	if (!unlikely(schedtune_initialized))
+		return 0;
+
+	/* Get task boost value */
+	rcu_read_lock();
+	st = task_schedtune(p);
+	task_boost = st->boost;
+	rcu_read_unlock();
+
+	return task_boost;
+}
+
+int schedtune_prefer_idle(struct task_struct *p)
+{
+	struct schedtune *st;
+	int prefer_idle;
+
+	if (!unlikely(schedtune_initialized))
+		return 0;
+
+	/* Get prefer_idle value */
+	rcu_read_lock();
+	st = task_schedtune(p);
+	prefer_idle = st->prefer_idle;
+	rcu_read_unlock();
+
+	return prefer_idle;
+}
+
+static u64
+prefer_idle_read(struct cgroup_subsys_state *css, struct cftype *cft)
+{
+	struct schedtune *st = css_st(css);
+
+	return st->prefer_idle;
+}
+
+static int
+prefer_idle_write(struct cgroup_subsys_state *css, struct cftype *cft,
+	    u64 prefer_idle)
+{
+	struct schedtune *st = css_st(css);
+	st->prefer_idle = prefer_idle;
+
+	return 0;
+}
+
+static s64
+boost_read(struct cgroup_subsys_state *css, struct cftype *cft)
+{
+	struct schedtune *st = css_st(css);
+
+	return st->boost;
+}
+
+static int
+boost_write(struct cgroup_subsys_state *css, struct cftype *cft,
+	    s64 boost)
+{
+	struct schedtune *st = css_st(css);
+	unsigned threshold_idx;
+	int boost_pct;
+
+	if (boost < -100 || boost > 100)
+		return -EINVAL;
+	boost_pct = boost;
+
+	/*
+	 * Update threshold params for Performance Boost (B)
+	 * and Performance Constraint (C) regions.
+	 * The current implementatio uses the same cuts for both
+	 * B and C regions.
+	 */
+	threshold_idx = clamp(boost_pct, 0, 99) / 10;
+	st->perf_boost_idx = threshold_idx;
+	st->perf_constrain_idx = threshold_idx;
+
+	st->boost = boost;
+	if (css == &root_schedtune.css) {
+		sysctl_sched_cfs_boost = boost;
+		perf_boost_idx  = threshold_idx;
+		perf_constrain_idx  = threshold_idx;
+	}
+
+	/* Update CPU boost */
+	schedtune_boostgroup_update(st->idx, st->boost);
+
+	trace_sched_tune_config(st->boost);
+
+	return 0;
+}
+
+static struct cftype files[] = {
+	{
+		.name = "boost",
+		.read_s64 = boost_read,
+		.write_s64 = boost_write,
+	},
+	{
+		.name = "prefer_idle",
+		.read_u64 = prefer_idle_read,
+		.write_u64 = prefer_idle_write,
+	},
+	{ }	/* terminate */
+};
+
+static int
+schedtune_boostgroup_init(struct schedtune *st)
+{
+	struct boost_groups *bg;
+	int cpu;
+
+	/* Keep track of allocated boost groups */
+	allocated_group[st->idx] = st;
+
+	/* Initialize the per CPU boost groups */
+	for_each_possible_cpu(cpu) {
+		bg = &per_cpu(cpu_boost_groups, cpu);
+		bg->group[st->idx].boost = 0;
+		bg->group[st->idx].tasks = 0;
+		raw_spin_lock_init(&bg->lock);
+	}
+
+	return 0;
+}
+
+static struct cgroup_subsys_state *
+schedtune_css_alloc(struct cgroup_subsys_state *parent_css)
+{
+	struct schedtune *st;
+	int idx;
+
+	if (!parent_css)
+		return &root_schedtune.css;
+
+	/* Allow only single level hierachies */
+	if (parent_css != &root_schedtune.css) {
+		pr_err("Nested SchedTune boosting groups not allowed\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Allow only a limited number of boosting groups */
+	for (idx = 1; idx < BOOSTGROUPS_COUNT; ++idx)
+		if (!allocated_group[idx])
+			break;
+	if (idx == BOOSTGROUPS_COUNT) {
+		pr_err("Trying to create more than %d SchedTune boosting groups\n",
+		       BOOSTGROUPS_COUNT);
+		return ERR_PTR(-ENOSPC);
+	}
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		goto out;
+
+	/* Initialize per CPUs boost group support */
+	st->idx = idx;
+	if (schedtune_boostgroup_init(st))
+		goto release;
+
+	return &st->css;
+
+release:
+	kfree(st);
+out:
+	return ERR_PTR(-ENOMEM);
+}
+
+static void
+schedtune_boostgroup_release(struct schedtune *st)
+{
+	/* Reset this boost group */
+	schedtune_boostgroup_update(st->idx, 0);
+
+	/* Keep track of allocated boost groups */
+	allocated_group[st->idx] = NULL;
+}
+
+static void
+schedtune_css_free(struct cgroup_subsys_state *css)
+{
+	struct schedtune *st = css_st(css);
+
+	schedtune_boostgroup_release(st);
+	kfree(st);
+}
+
+struct cgroup_subsys schedtune_cgrp_subsys = {
+	.css_alloc	= schedtune_css_alloc,
+	.css_free	= schedtune_css_free,
+	.can_attach     = schedtune_can_attach,
+	.cancel_attach  = schedtune_cancel_attach,
+	.legacy_cftypes	= files,
+	.early_init	= 1,
+};
+
+static inline void
+schedtune_init_cgroups(void)
+{
+	struct boost_groups *bg;
+	int cpu;
+
+	/* Initialize the per CPU boost groups */
+	for_each_possible_cpu(cpu) {
+		bg = &per_cpu(cpu_boost_groups, cpu);
+		memset(bg, 0, sizeof(struct boost_groups));
+		raw_spin_lock_init(&bg->lock);
+	}
+
+	pr_info("schedtune: configured to support %d boost groups\n",
+		BOOSTGROUPS_COUNT);
+
+	schedtune_initialized = true;
+}
+
+#else /* CONFIG_CGROUP_SCHEDTUNE */
+
+int
+schedtune_accept_deltas(int nrg_delta, int cap_delta,
+			struct task_struct *task)
+{
+	/* Optimal (O) region */
+	if (nrg_delta < 0 && cap_delta > 0) {
+		trace_sched_tune_filter(nrg_delta, cap_delta, 0, 0, 1, 0);
+		return INT_MAX;
+	}
+
+	/* Suboptimal (S) region */
+	if (nrg_delta > 0 && cap_delta < 0) {
+		trace_sched_tune_filter(nrg_delta, cap_delta, 0, 0, -1, 5);
+		return -INT_MAX;
+	}
+
+	return __schedtune_accept_deltas(nrg_delta, cap_delta,
+			perf_boost_idx, perf_constrain_idx);
+}
+
+#endif /* CONFIG_CGROUP_SCHEDTUNE */
+
+int
+sysctl_sched_cfs_boost_handler(struct ctl_table *table, int write,
+			       void __user *buffer, size_t *lenp,
+			       loff_t *ppos)
+{
+	int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+	unsigned threshold_idx;
+	int boost_pct;
+
+	if (ret || !write)
+		return ret;
+
+	if (sysctl_sched_cfs_boost < -100 || sysctl_sched_cfs_boost > 100)
+		return -EINVAL;
+	boost_pct = sysctl_sched_cfs_boost;
+
+	/*
+	 * Update threshold params for Performance Boost (B)
+	 * and Performance Constraint (C) regions.
+	 * The current implementatio uses the same cuts for both
+	 * B and C regions.
+	 */
+	threshold_idx = clamp(boost_pct, 0, 99) / 10;
+	perf_boost_idx = threshold_idx;
+	perf_constrain_idx = threshold_idx;
+
+	return 0;
+}
+
+#ifdef CONFIG_SCHED_DEBUG
+static void
+schedtune_test_nrg(unsigned long delta_pwr)
+{
+	unsigned long test_delta_pwr;
+	unsigned long test_norm_pwr;
+	int idx;
+
+	/*
+	 * Check normalization constants using some constant system
+	 * energy values
+	 */
+	pr_info("schedtune: verify normalization constants...\n");
+	for (idx = 0; idx < 6; ++idx) {
+		test_delta_pwr = delta_pwr >> idx;
+
+		/* Normalize on max energy for target platform */
+		test_norm_pwr = reciprocal_divide(
+					test_delta_pwr << SCHED_LOAD_SHIFT,
+					schedtune_target_nrg.rdiv);
+
+		pr_info("schedtune: max_pwr/2^%d: %4lu => norm_pwr: %5lu\n",
+			idx, test_delta_pwr, test_norm_pwr);
+	}
+}
+#else
+#define schedtune_test_nrg(delta_pwr)
+#endif
+
+/*
+ * Compute the min/max power consumption of a cluster and all its CPUs
+ */
+static void
+schedtune_add_cluster_nrg(
+		struct sched_domain *sd,
+		struct sched_group *sg,
+		struct target_nrg *ste)
+{
+	struct sched_domain *sd2;
+	struct sched_group *sg2;
+
+	struct cpumask *cluster_cpus;
+	char str[32];
+
+	unsigned long min_pwr;
+	unsigned long max_pwr;
+	int cpu;
+
+	/* Get Cluster energy using EM data for the first CPU */
+	cluster_cpus = sched_group_cpus(sg);
+	snprintf(str, 32, "CLUSTER[%*pbl]",
+		 cpumask_pr_args(cluster_cpus));
+
+	min_pwr = sg->sge->idle_states[sg->sge->nr_idle_states - 1].power;
+	max_pwr = sg->sge->cap_states[sg->sge->nr_cap_states - 1].power;
+	pr_info("schedtune: %-17s min_pwr: %5lu max_pwr: %5lu\n",
+		str, min_pwr, max_pwr);
+
+	/*
+	 * Keep track of this cluster's energy in the computation of the
+	 * overall system energy
+	 */
+	ste->min_power += min_pwr;
+	ste->max_power += max_pwr;
+
+	/* Get CPU energy using EM data for each CPU in the group */
+	for_each_cpu(cpu, cluster_cpus) {
+		/* Get a SD view for the specific CPU */
+		for_each_domain(cpu, sd2) {
+			/* Get the CPU group */
+			sg2 = sd2->groups;
+			min_pwr = sg2->sge->idle_states[sg2->sge->nr_idle_states - 1].power;
+			max_pwr = sg2->sge->cap_states[sg2->sge->nr_cap_states - 1].power;
+
+			ste->min_power += min_pwr;
+			ste->max_power += max_pwr;
+
+			snprintf(str, 32, "CPU[%d]", cpu);
+			pr_info("schedtune: %-17s min_pwr: %5lu max_pwr: %5lu\n",
+				str, min_pwr, max_pwr);
+
+			/*
+			 * Assume we have EM data only at the CPU and
+			 * the upper CLUSTER level
+			 */
+			BUG_ON(!cpumask_equal(
+				sched_group_cpus(sg),
+				sched_group_cpus(sd2->parent->groups)
+				));
+			break;
+		}
+	}
+}
+
+/*
+ * Initialize the constants required to compute normalized energy.
+ * The values of these constants depends on the EM data for the specific
+ * target system and topology.
+ * Thus, this function is expected to be called by the code
+ * that bind the EM to the topology information.
+ */
+static int
+schedtune_init(void)
+{
+	struct target_nrg *ste = &schedtune_target_nrg;
+	unsigned long delta_pwr = 0;
+	struct sched_domain *sd;
+	struct sched_group *sg;
+
+	pr_info("schedtune: init normalization constants...\n");
+	ste->max_power = 0;
+	ste->min_power = 0;
+
+	rcu_read_lock();
+
+	/*
+	 * When EAS is in use, we always have a pointer to the highest SD
+	 * which provides EM data.
+	 */
+	sd = rcu_dereference(per_cpu(sd_ea, cpumask_first(cpu_online_mask)));
+	if (!sd) {
+		pr_info("schedtune: no energy model data\n");
+		goto nodata;
+	}
+
+	sg = sd->groups;
+	do {
+		schedtune_add_cluster_nrg(sd, sg, ste);
+	} while (sg = sg->next, sg != sd->groups);
+
+	rcu_read_unlock();
+
+	pr_info("schedtune: %-17s min_pwr: %5lu max_pwr: %5lu\n",
+		"SYSTEM", ste->min_power, ste->max_power);
+
+	/* Compute normalization constants */
+	delta_pwr = ste->max_power - ste->min_power;
+	ste->rdiv = reciprocal_value(delta_pwr);
+	pr_info("schedtune: using normalization constants mul: %u sh1: %u sh2: %u\n",
+		ste->rdiv.m, ste->rdiv.sh1, ste->rdiv.sh2);
+
+	schedtune_test_nrg(delta_pwr);
+
+#ifdef CONFIG_CGROUP_SCHEDTUNE
+	schedtune_init_cgroups();
+#else
+	pr_info("schedtune: configured to support global boosting only\n");
+#endif
+
+	schedtune_spc_rdiv = reciprocal_value(100);
+
+	return 0;
+
+nodata:
+	pr_warning("schedtune: disabled!\n");
+	rcu_read_unlock();
+	return -EINVAL;
+}
+postcore_initcall(schedtune_init);
diff --git a/kernel/sched/tune.h b/kernel/sched/tune.h
new file mode 100644
index 0000000..4f64417
--- /dev/null
+++ b/kernel/sched/tune.h
@@ -0,0 +1,55 @@
+
+#ifdef CONFIG_SCHED_TUNE
+
+#include <linux/reciprocal_div.h>
+
+/*
+ * System energy normalization constants
+ */
+struct target_nrg {
+	unsigned long min_power;
+	unsigned long max_power;
+	struct reciprocal_value rdiv;
+};
+
+#ifdef CONFIG_CGROUP_SCHEDTUNE
+
+int schedtune_cpu_boost(int cpu);
+int schedtune_task_boost(struct task_struct *tsk);
+
+int schedtune_prefer_idle(struct task_struct *tsk);
+
+void schedtune_exit_task(struct task_struct *tsk);
+
+void schedtune_enqueue_task(struct task_struct *p, int cpu);
+void schedtune_dequeue_task(struct task_struct *p, int cpu);
+
+#else /* CONFIG_CGROUP_SCHEDTUNE */
+
+#define schedtune_cpu_boost(cpu)  get_sysctl_sched_cfs_boost()
+#define schedtune_task_boost(tsk) get_sysctl_sched_cfs_boost()
+
+#define schedtune_exit_task(task) do { } while (0)
+
+#define schedtune_enqueue_task(task, cpu) do { } while (0)
+#define schedtune_dequeue_task(task, cpu) do { } while (0)
+
+#endif /* CONFIG_CGROUP_SCHEDTUNE */
+
+int schedtune_normalize_energy(int energy);
+int schedtune_accept_deltas(int nrg_delta, int cap_delta,
+			    struct task_struct *task);
+
+#else /* CONFIG_SCHED_TUNE */
+
+#define schedtune_cpu_boost(cpu)  0
+#define schedtune_task_boost(tsk) 0
+
+#define schedtune_exit_task(task) do { } while (0)
+
+#define schedtune_enqueue_task(task, cpu) do { } while (0)
+#define schedtune_dequeue_task(task, cpu) do { } while (0)
+
+#define schedtune_accept_deltas(nrg_delta, cap_delta, task) nrg_delta
+
+#endif /* CONFIG_SCHED_TUNE */
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
new file mode 100644
index 0000000..92c3aae
--- /dev/null
+++ b/kernel/sched/walt.c
@@ -0,0 +1,1133 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * Window Assisted Load Tracking (WALT) implementation credits:
+ * Srivatsa Vaddagiri, Steve Muckle, Syed Rameez Mustafa, Joonwoo Park,
+ * Pavan Kumar Kondeti, Olav Haugan
+ *
+ * 2016-03-06: Integration with EAS/refactoring by Vikram Mulukutla
+ *             and Todd Kjos
+ */
+
+#include <linux/syscore_ops.h>
+#include <linux/cpufreq.h>
+#include <trace/events/sched.h>
+#include "sched.h"
+#include "walt.h"
+
+#define WINDOW_STATS_RECENT		0
+#define WINDOW_STATS_MAX		1
+#define WINDOW_STATS_MAX_RECENT_AVG	2
+#define WINDOW_STATS_AVG		3
+#define WINDOW_STATS_INVALID_POLICY	4
+
+#define EXITING_TASK_MARKER	0xdeaddead
+
+static __read_mostly unsigned int walt_ravg_hist_size = 5;
+static __read_mostly unsigned int walt_window_stats_policy =
+	WINDOW_STATS_MAX_RECENT_AVG;
+static __read_mostly unsigned int walt_account_wait_time = 1;
+static __read_mostly unsigned int walt_freq_account_wait_time = 0;
+static __read_mostly unsigned int walt_io_is_busy = 0;
+
+unsigned int sysctl_sched_walt_init_task_load_pct = 15;
+
+/* 1 -> use PELT based load stats, 0 -> use window-based load stats */
+unsigned int __read_mostly walt_disabled = 0;
+
+static unsigned int max_possible_efficiency = 1024;
+static unsigned int min_possible_efficiency = 1024;
+
+/*
+ * Maximum possible frequency across all cpus. Task demand and cpu
+ * capacity (cpu_power) metrics are scaled in reference to it.
+ */
+static unsigned int max_possible_freq = 1;
+
+/*
+ * Minimum possible max_freq across all cpus. This will be same as
+ * max_possible_freq on homogeneous systems and could be different from
+ * max_possible_freq on heterogenous systems. min_max_freq is used to derive
+ * capacity (cpu_power) of cpus.
+ */
+static unsigned int min_max_freq = 1;
+
+static unsigned int max_load_scale_factor = 1024;
+static unsigned int max_possible_capacity = 1024;
+
+/* Mask of all CPUs that have  max_possible_capacity */
+static cpumask_t mpc_mask = CPU_MASK_ALL;
+
+/* Window size (in ns) */
+__read_mostly unsigned int walt_ravg_window = 20000000;
+
+/* Min window size (in ns) = 10ms */
+#ifdef CONFIG_HZ_300
+/*
+ * Tick interval becomes to 3333333 due to
+ * rounding error when HZ=300.
+ */
+#define MIN_SCHED_RAVG_WINDOW (3333333 * 6)
+#else
+#define MIN_SCHED_RAVG_WINDOW 10000000
+#endif
+
+/* Max window size (in ns) = 1s */
+#define MAX_SCHED_RAVG_WINDOW 1000000000
+
+static unsigned int sync_cpu;
+static ktime_t ktime_last;
+static bool walt_ktime_suspended;
+
+static unsigned int task_load(struct task_struct *p)
+{
+	return p->ravg.demand;
+}
+
+void
+walt_inc_cumulative_runnable_avg(struct rq *rq,
+				 struct task_struct *p)
+{
+	rq->cumulative_runnable_avg += p->ravg.demand;
+}
+
+void
+walt_dec_cumulative_runnable_avg(struct rq *rq,
+				 struct task_struct *p)
+{
+	rq->cumulative_runnable_avg -= p->ravg.demand;
+	BUG_ON((s64)rq->cumulative_runnable_avg < 0);
+}
+
+static void
+fixup_cumulative_runnable_avg(struct rq *rq,
+			      struct task_struct *p, s64 task_load_delta)
+{
+	rq->cumulative_runnable_avg += task_load_delta;
+	if ((s64)rq->cumulative_runnable_avg < 0)
+		panic("cra less than zero: tld: %lld, task_load(p) = %u\n",
+			task_load_delta, task_load(p));
+}
+
+u64 walt_ktime_clock(void)
+{
+	if (unlikely(walt_ktime_suspended))
+		return ktime_to_ns(ktime_last);
+	return ktime_get_ns();
+}
+
+static void walt_resume(void)
+{
+	walt_ktime_suspended = false;
+}
+
+static int walt_suspend(void)
+{
+	ktime_last = ktime_get();
+	walt_ktime_suspended = true;
+	return 0;
+}
+
+static struct syscore_ops walt_syscore_ops = {
+	.resume	= walt_resume,
+	.suspend = walt_suspend
+};
+
+static int __init walt_init_ops(void)
+{
+	register_syscore_ops(&walt_syscore_ops);
+	return 0;
+}
+late_initcall(walt_init_ops);
+
+void walt_inc_cfs_cumulative_runnable_avg(struct cfs_rq *cfs_rq,
+		struct task_struct *p)
+{
+	cfs_rq->cumulative_runnable_avg += p->ravg.demand;
+}
+
+void walt_dec_cfs_cumulative_runnable_avg(struct cfs_rq *cfs_rq,
+		struct task_struct *p)
+{
+	cfs_rq->cumulative_runnable_avg -= p->ravg.demand;
+}
+
+static int exiting_task(struct task_struct *p)
+{
+	if (p->flags & PF_EXITING) {
+		if (p->ravg.sum_history[0] != EXITING_TASK_MARKER) {
+			p->ravg.sum_history[0] = EXITING_TASK_MARKER;
+		}
+		return 1;
+	}
+	return 0;
+}
+
+static int __init set_walt_ravg_window(char *str)
+{
+	get_option(&str, &walt_ravg_window);
+
+	walt_disabled = (walt_ravg_window < MIN_SCHED_RAVG_WINDOW ||
+				walt_ravg_window > MAX_SCHED_RAVG_WINDOW);
+	return 0;
+}
+
+early_param("walt_ravg_window", set_walt_ravg_window);
+
+static void
+update_window_start(struct rq *rq, u64 wallclock)
+{
+	s64 delta;
+	int nr_windows;
+
+	delta = wallclock - rq->window_start;
+	/* If the MPM global timer is cleared, set delta as 0 to avoid kernel BUG happening */
+	if (delta < 0) {
+		delta = 0;
+		WARN_ONCE(1, "WALT wallclock appears to have gone backwards or reset\n");
+	}
+
+	if (delta < walt_ravg_window)
+		return;
+
+	nr_windows = div64_u64(delta, walt_ravg_window);
+	rq->window_start += (u64)nr_windows * (u64)walt_ravg_window;
+}
+
+static u64 scale_exec_time(u64 delta, struct rq *rq)
+{
+	unsigned int cur_freq = rq->cur_freq;
+	int sf;
+
+	if (unlikely(cur_freq > max_possible_freq))
+		cur_freq = rq->max_possible_freq;
+
+	/* round up div64 */
+	delta = div64_u64(delta * cur_freq + max_possible_freq - 1,
+			  max_possible_freq);
+
+	sf = DIV_ROUND_UP(rq->efficiency * 1024, max_possible_efficiency);
+
+	delta *= sf;
+	delta >>= 10;
+
+	return delta;
+}
+
+static int cpu_is_waiting_on_io(struct rq *rq)
+{
+	if (!walt_io_is_busy)
+		return 0;
+
+	return atomic_read(&rq->nr_iowait);
+}
+
+void walt_account_irqtime(int cpu, struct task_struct *curr,
+				 u64 delta, u64 wallclock)
+{
+	struct rq *rq = cpu_rq(cpu);
+	unsigned long flags, nr_windows;
+	u64 cur_jiffies_ts;
+
+	raw_spin_lock_irqsave(&rq->lock, flags);
+
+	/*
+	 * cputime (wallclock) uses sched_clock so use the same here for
+	 * consistency.
+	 */
+	delta += sched_clock() - wallclock;
+	cur_jiffies_ts = get_jiffies_64();
+
+	if (is_idle_task(curr))
+		walt_update_task_ravg(curr, rq, IRQ_UPDATE, walt_ktime_clock(),
+				 delta);
+
+	nr_windows = cur_jiffies_ts - rq->irqload_ts;
+
+	if (nr_windows) {
+		if (nr_windows < 10) {
+			/* Decay CPU's irqload by 3/4 for each window. */
+			rq->avg_irqload *= (3 * nr_windows);
+			rq->avg_irqload = div64_u64(rq->avg_irqload,
+						    4 * nr_windows);
+		} else {
+			rq->avg_irqload = 0;
+		}
+		rq->avg_irqload += rq->cur_irqload;
+		rq->cur_irqload = 0;
+	}
+
+	rq->cur_irqload += delta;
+	rq->irqload_ts = cur_jiffies_ts;
+	raw_spin_unlock_irqrestore(&rq->lock, flags);
+}
+
+
+#define WALT_HIGH_IRQ_TIMEOUT 3
+
+u64 walt_irqload(int cpu) {
+	struct rq *rq = cpu_rq(cpu);
+	s64 delta;
+	delta = get_jiffies_64() - rq->irqload_ts;
+
+        /*
+	 * Current context can be preempted by irq and rq->irqload_ts can be
+	 * updated by irq context so that delta can be negative.
+	 * But this is okay and we can safely return as this means there
+	 * was recent irq occurrence.
+	 */
+
+        if (delta < WALT_HIGH_IRQ_TIMEOUT)
+		return rq->avg_irqload;
+        else
+		return 0;
+}
+
+int walt_cpu_high_irqload(int cpu) {
+	return walt_irqload(cpu) >= sysctl_sched_walt_cpu_high_irqload;
+}
+
+static int account_busy_for_cpu_time(struct rq *rq, struct task_struct *p,
+				     u64 irqtime, int event)
+{
+	if (is_idle_task(p)) {
+		/* TASK_WAKE && TASK_MIGRATE is not possible on idle task! */
+		if (event == PICK_NEXT_TASK)
+			return 0;
+
+		/* PUT_PREV_TASK, TASK_UPDATE && IRQ_UPDATE are left */
+		return irqtime || cpu_is_waiting_on_io(rq);
+	}
+
+	if (event == TASK_WAKE)
+		return 0;
+
+	if (event == PUT_PREV_TASK || event == IRQ_UPDATE ||
+					 event == TASK_UPDATE)
+		return 1;
+
+	/* Only TASK_MIGRATE && PICK_NEXT_TASK left */
+	return walt_freq_account_wait_time;
+}
+
+/*
+ * Account cpu activity in its busy time counters (rq->curr/prev_runnable_sum)
+ */
+static void update_cpu_busy_time(struct task_struct *p, struct rq *rq,
+	     int event, u64 wallclock, u64 irqtime)
+{
+	int new_window, nr_full_windows = 0;
+	int p_is_curr_task = (p == rq->curr);
+	u64 mark_start = p->ravg.mark_start;
+	u64 window_start = rq->window_start;
+	u32 window_size = walt_ravg_window;
+	u64 delta;
+
+	new_window = mark_start < window_start;
+	if (new_window) {
+		nr_full_windows = div64_u64((window_start - mark_start),
+						window_size);
+		if (p->ravg.active_windows < USHRT_MAX)
+			p->ravg.active_windows++;
+	}
+
+	/* Handle per-task window rollover. We don't care about the idle
+	 * task or exiting tasks. */
+	if (new_window && !is_idle_task(p) && !exiting_task(p)) {
+		u32 curr_window = 0;
+
+		if (!nr_full_windows)
+			curr_window = p->ravg.curr_window;
+
+		p->ravg.prev_window = curr_window;
+		p->ravg.curr_window = 0;
+	}
+
+	if (!account_busy_for_cpu_time(rq, p, irqtime, event)) {
+		/* account_busy_for_cpu_time() = 0, so no update to the
+		 * task's current window needs to be made. This could be
+		 * for example
+		 *
+		 *   - a wakeup event on a task within the current
+		 *     window (!new_window below, no action required),
+		 *   - switching to a new task from idle (PICK_NEXT_TASK)
+		 *     in a new window where irqtime is 0 and we aren't
+		 *     waiting on IO */
+
+		if (!new_window)
+			return;
+
+		/* A new window has started. The RQ demand must be rolled
+		 * over if p is the current task. */
+		if (p_is_curr_task) {
+			u64 prev_sum = 0;
+
+			/* p is either idle task or an exiting task */
+			if (!nr_full_windows) {
+				prev_sum = rq->curr_runnable_sum;
+			}
+
+			rq->prev_runnable_sum = prev_sum;
+			rq->curr_runnable_sum = 0;
+		}
+
+		return;
+	}
+
+	if (!new_window) {
+		/* account_busy_for_cpu_time() = 1 so busy time needs
+		 * to be accounted to the current window. No rollover
+		 * since we didn't start a new window. An example of this is
+		 * when a task starts execution and then sleeps within the
+		 * same window. */
+
+		if (!irqtime || !is_idle_task(p) || cpu_is_waiting_on_io(rq))
+			delta = wallclock - mark_start;
+		else
+			delta = irqtime;
+		delta = scale_exec_time(delta, rq);
+		rq->curr_runnable_sum += delta;
+		if (!is_idle_task(p) && !exiting_task(p))
+			p->ravg.curr_window += delta;
+
+		return;
+	}
+
+	if (!p_is_curr_task) {
+		/* account_busy_for_cpu_time() = 1 so busy time needs
+		 * to be accounted to the current window. A new window
+		 * has also started, but p is not the current task, so the
+		 * window is not rolled over - just split up and account
+		 * as necessary into curr and prev. The window is only
+		 * rolled over when a new window is processed for the current
+		 * task.
+		 *
+		 * Irqtime can't be accounted by a task that isn't the
+		 * currently running task. */
+
+		if (!nr_full_windows) {
+			/* A full window hasn't elapsed, account partial
+			 * contribution to previous completed window. */
+			delta = scale_exec_time(window_start - mark_start, rq);
+			if (!exiting_task(p))
+				p->ravg.prev_window += delta;
+		} else {
+			/* Since at least one full window has elapsed,
+			 * the contribution to the previous window is the
+			 * full window (window_size). */
+			delta = scale_exec_time(window_size, rq);
+			if (!exiting_task(p))
+				p->ravg.prev_window = delta;
+		}
+		rq->prev_runnable_sum += delta;
+
+		/* Account piece of busy time in the current window. */
+		delta = scale_exec_time(wallclock - window_start, rq);
+		rq->curr_runnable_sum += delta;
+		if (!exiting_task(p))
+			p->ravg.curr_window = delta;
+
+		return;
+	}
+
+	if (!irqtime || !is_idle_task(p) || cpu_is_waiting_on_io(rq)) {
+		/* account_busy_for_cpu_time() = 1 so busy time needs
+		 * to be accounted to the current window. A new window
+		 * has started and p is the current task so rollover is
+		 * needed. If any of these three above conditions are true
+		 * then this busy time can't be accounted as irqtime.
+		 *
+		 * Busy time for the idle task or exiting tasks need not
+		 * be accounted.
+		 *
+		 * An example of this would be a task that starts execution
+		 * and then sleeps once a new window has begun. */
+
+		if (!nr_full_windows) {
+			/* A full window hasn't elapsed, account partial
+			 * contribution to previous completed window. */
+			delta = scale_exec_time(window_start - mark_start, rq);
+			if (!is_idle_task(p) && !exiting_task(p))
+				p->ravg.prev_window += delta;
+
+			delta += rq->curr_runnable_sum;
+		} else {
+			/* Since at least one full window has elapsed,
+			 * the contribution to the previous window is the
+			 * full window (window_size). */
+			delta = scale_exec_time(window_size, rq);
+			if (!is_idle_task(p) && !exiting_task(p))
+				p->ravg.prev_window = delta;
+
+		}
+		/*
+		 * Rollover for normal runnable sum is done here by overwriting
+		 * the values in prev_runnable_sum and curr_runnable_sum.
+		 * Rollover for new task runnable sum has completed by previous
+		 * if-else statement.
+		 */
+		rq->prev_runnable_sum = delta;
+
+		/* Account piece of busy time in the current window. */
+		delta = scale_exec_time(wallclock - window_start, rq);
+		rq->curr_runnable_sum = delta;
+		if (!is_idle_task(p) && !exiting_task(p))
+			p->ravg.curr_window = delta;
+
+		return;
+	}
+
+	if (irqtime) {
+		/* account_busy_for_cpu_time() = 1 so busy time needs
+		 * to be accounted to the current window. A new window
+		 * has started and p is the current task so rollover is
+		 * needed. The current task must be the idle task because
+		 * irqtime is not accounted for any other task.
+		 *
+		 * Irqtime will be accounted each time we process IRQ activity
+		 * after a period of idleness, so we know the IRQ busy time
+		 * started at wallclock - irqtime. */
+
+		BUG_ON(!is_idle_task(p));
+		mark_start = wallclock - irqtime;
+
+		/* Roll window over. If IRQ busy time was just in the current
+		 * window then that is all that need be accounted. */
+		rq->prev_runnable_sum = rq->curr_runnable_sum;
+		if (mark_start > window_start) {
+			rq->curr_runnable_sum = scale_exec_time(irqtime, rq);
+			return;
+		}
+
+		/* The IRQ busy time spanned multiple windows. Process the
+		 * busy time preceding the current window start first. */
+		delta = window_start - mark_start;
+		if (delta > window_size)
+			delta = window_size;
+		delta = scale_exec_time(delta, rq);
+		rq->prev_runnable_sum += delta;
+
+		/* Process the remaining IRQ busy time in the current window. */
+		delta = wallclock - window_start;
+		rq->curr_runnable_sum = scale_exec_time(delta, rq);
+
+		return;
+	}
+
+	BUG();
+}
+
+static int account_busy_for_task_demand(struct task_struct *p, int event)
+{
+	/* No need to bother updating task demand for exiting tasks
+	 * or the idle task. */
+	if (exiting_task(p) || is_idle_task(p))
+		return 0;
+
+	/* When a task is waking up it is completing a segment of non-busy
+	 * time. Likewise, if wait time is not treated as busy time, then
+	 * when a task begins to run or is migrated, it is not running and
+	 * is completing a segment of non-busy time. */
+	if (event == TASK_WAKE || (!walt_account_wait_time &&
+			 (event == PICK_NEXT_TASK || event == TASK_MIGRATE)))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Called when new window is starting for a task, to record cpu usage over
+ * recently concluded window(s). Normally 'samples' should be 1. It can be > 1
+ * when, say, a real-time task runs without preemption for several windows at a
+ * stretch.
+ */
+static void update_history(struct rq *rq, struct task_struct *p,
+			 u32 runtime, int samples, int event)
+{
+	u32 *hist = &p->ravg.sum_history[0];
+	int ridx, widx;
+	u32 max = 0, avg, demand;
+	u64 sum = 0;
+
+	/* Ignore windows where task had no activity */
+	if (!runtime || is_idle_task(p) || exiting_task(p) || !samples)
+			goto done;
+
+	/* Push new 'runtime' value onto stack */
+	widx = walt_ravg_hist_size - 1;
+	ridx = widx - samples;
+	for (; ridx >= 0; --widx, --ridx) {
+		hist[widx] = hist[ridx];
+		sum += hist[widx];
+		if (hist[widx] > max)
+			max = hist[widx];
+	}
+
+	for (widx = 0; widx < samples && widx < walt_ravg_hist_size; widx++) {
+		hist[widx] = runtime;
+		sum += hist[widx];
+		if (hist[widx] > max)
+			max = hist[widx];
+	}
+
+	p->ravg.sum = 0;
+
+	if (walt_window_stats_policy == WINDOW_STATS_RECENT) {
+		demand = runtime;
+	} else if (walt_window_stats_policy == WINDOW_STATS_MAX) {
+		demand = max;
+	} else {
+		avg = div64_u64(sum, walt_ravg_hist_size);
+		if (walt_window_stats_policy == WINDOW_STATS_AVG)
+			demand = avg;
+		else
+			demand = max(avg, runtime);
+	}
+
+	/*
+	 * A throttled deadline sched class task gets dequeued without
+	 * changing p->on_rq. Since the dequeue decrements hmp stats
+	 * avoid decrementing it here again.
+	 */
+	if (task_on_rq_queued(p) && (!task_has_dl_policy(p) ||
+						!p->dl.dl_throttled))
+		fixup_cumulative_runnable_avg(rq, p, demand);
+
+	p->ravg.demand = demand;
+
+done:
+	trace_walt_update_history(rq, p, runtime, samples, event);
+	return;
+}
+
+static void add_to_task_demand(struct rq *rq, struct task_struct *p,
+				u64 delta)
+{
+	delta = scale_exec_time(delta, rq);
+	p->ravg.sum += delta;
+	if (unlikely(p->ravg.sum > walt_ravg_window))
+		p->ravg.sum = walt_ravg_window;
+}
+
+/*
+ * Account cpu demand of task and/or update task's cpu demand history
+ *
+ * ms = p->ravg.mark_start;
+ * wc = wallclock
+ * ws = rq->window_start
+ *
+ * Three possibilities:
+ *
+ *	a) Task event is contained within one window.
+ *		window_start < mark_start < wallclock
+ *
+ *		ws   ms  wc
+ *		|    |   |
+ *		V    V   V
+ *		|---------------|
+ *
+ *	In this case, p->ravg.sum is updated *iff* event is appropriate
+ *	(ex: event == PUT_PREV_TASK)
+ *
+ *	b) Task event spans two windows.
+ *		mark_start < window_start < wallclock
+ *
+ *		ms   ws   wc
+ *		|    |    |
+ *		V    V    V
+ *		-----|-------------------
+ *
+ *	In this case, p->ravg.sum is updated with (ws - ms) *iff* event
+ *	is appropriate, then a new window sample is recorded followed
+ *	by p->ravg.sum being set to (wc - ws) *iff* event is appropriate.
+ *
+ *	c) Task event spans more than two windows.
+ *
+ *		ms ws_tmp			   ws  wc
+ *		|  |				   |   |
+ *		V  V				   V   V
+ *		---|-------|-------|-------|-------|------
+ *		   |				   |
+ *		   |<------ nr_full_windows ------>|
+ *
+ *	In this case, p->ravg.sum is updated with (ws_tmp - ms) first *iff*
+ *	event is appropriate, window sample of p->ravg.sum is recorded,
+ *	'nr_full_window' samples of window_size is also recorded *iff*
+ *	event is appropriate and finally p->ravg.sum is set to (wc - ws)
+ *	*iff* event is appropriate.
+ *
+ * IMPORTANT : Leave p->ravg.mark_start unchanged, as update_cpu_busy_time()
+ * depends on it!
+ */
+static void update_task_demand(struct task_struct *p, struct rq *rq,
+	     int event, u64 wallclock)
+{
+	u64 mark_start = p->ravg.mark_start;
+	u64 delta, window_start = rq->window_start;
+	int new_window, nr_full_windows;
+	u32 window_size = walt_ravg_window;
+
+	new_window = mark_start < window_start;
+	if (!account_busy_for_task_demand(p, event)) {
+		if (new_window)
+			/* If the time accounted isn't being accounted as
+			 * busy time, and a new window started, only the
+			 * previous window need be closed out with the
+			 * pre-existing demand. Multiple windows may have
+			 * elapsed, but since empty windows are dropped,
+			 * it is not necessary to account those. */
+			update_history(rq, p, p->ravg.sum, 1, event);
+		return;
+	}
+
+	if (!new_window) {
+		/* The simple case - busy time contained within the existing
+		 * window. */
+		add_to_task_demand(rq, p, wallclock - mark_start);
+		return;
+	}
+
+	/* Busy time spans at least two windows. Temporarily rewind
+	 * window_start to first window boundary after mark_start. */
+	delta = window_start - mark_start;
+	nr_full_windows = div64_u64(delta, window_size);
+	window_start -= (u64)nr_full_windows * (u64)window_size;
+
+	/* Process (window_start - mark_start) first */
+	add_to_task_demand(rq, p, window_start - mark_start);
+
+	/* Push new sample(s) into task's demand history */
+	update_history(rq, p, p->ravg.sum, 1, event);
+	if (nr_full_windows)
+		update_history(rq, p, scale_exec_time(window_size, rq),
+			       nr_full_windows, event);
+
+	/* Roll window_start back to current to process any remainder
+	 * in current window. */
+	window_start += (u64)nr_full_windows * (u64)window_size;
+
+	/* Process (wallclock - window_start) next */
+	mark_start = window_start;
+	add_to_task_demand(rq, p, wallclock - mark_start);
+}
+
+/* Reflect task activity on its demand and cpu's busy time statistics */
+void walt_update_task_ravg(struct task_struct *p, struct rq *rq,
+	     int event, u64 wallclock, u64 irqtime)
+{
+	if (walt_disabled || !rq->window_start)
+		return;
+
+	lockdep_assert_held(&rq->lock);
+
+	update_window_start(rq, wallclock);
+
+	if (!p->ravg.mark_start)
+		goto done;
+
+	update_task_demand(p, rq, event, wallclock);
+	update_cpu_busy_time(p, rq, event, wallclock, irqtime);
+
+done:
+	trace_walt_update_task_ravg(p, rq, event, wallclock, irqtime);
+
+	p->ravg.mark_start = wallclock;
+}
+
+unsigned long __weak arch_get_cpu_efficiency(int cpu)
+{
+	return SCHED_LOAD_SCALE;
+}
+
+void walt_init_cpu_efficiency(void)
+{
+	int i, efficiency;
+	unsigned int max = 0, min = UINT_MAX;
+
+	for_each_possible_cpu(i) {
+		efficiency = arch_get_cpu_efficiency(i);
+		cpu_rq(i)->efficiency = efficiency;
+
+		if (efficiency > max)
+			max = efficiency;
+		if (efficiency < min)
+			min = efficiency;
+	}
+
+	if (max)
+		max_possible_efficiency = max;
+
+	if (min)
+		min_possible_efficiency = min;
+}
+
+static void reset_task_stats(struct task_struct *p)
+{
+	u32 sum = 0;
+
+	if (exiting_task(p))
+		sum = EXITING_TASK_MARKER;
+
+	memset(&p->ravg, 0, sizeof(struct ravg));
+	/* Retain EXITING_TASK marker */
+	p->ravg.sum_history[0] = sum;
+}
+
+void walt_mark_task_starting(struct task_struct *p)
+{
+	u64 wallclock;
+	struct rq *rq = task_rq(p);
+
+	if (!rq->window_start) {
+		reset_task_stats(p);
+		return;
+	}
+
+	wallclock = walt_ktime_clock();
+	p->ravg.mark_start = wallclock;
+}
+
+void walt_set_window_start(struct rq *rq)
+{
+	int cpu = cpu_of(rq);
+	struct rq *sync_rq = cpu_rq(sync_cpu);
+
+	if (rq->window_start)
+		return;
+
+	if (cpu == sync_cpu) {
+		rq->window_start = walt_ktime_clock();
+	} else {
+		raw_spin_unlock(&rq->lock);
+		double_rq_lock(rq, sync_rq);
+		rq->window_start = cpu_rq(sync_cpu)->window_start;
+		rq->curr_runnable_sum = rq->prev_runnable_sum = 0;
+		raw_spin_unlock(&sync_rq->lock);
+	}
+
+	rq->curr->ravg.mark_start = rq->window_start;
+}
+
+void walt_migrate_sync_cpu(int cpu)
+{
+	if (cpu == sync_cpu)
+		sync_cpu = smp_processor_id();
+}
+
+void walt_fixup_busy_time(struct task_struct *p, int new_cpu)
+{
+	struct rq *src_rq = task_rq(p);
+	struct rq *dest_rq = cpu_rq(new_cpu);
+	u64 wallclock;
+
+	if (!p->on_rq && p->state != TASK_WAKING)
+		return;
+
+	if (exiting_task(p)) {
+		return;
+	}
+
+	if (p->state == TASK_WAKING)
+		double_rq_lock(src_rq, dest_rq);
+
+	wallclock = walt_ktime_clock();
+
+	walt_update_task_ravg(task_rq(p)->curr, task_rq(p),
+			TASK_UPDATE, wallclock, 0);
+	walt_update_task_ravg(dest_rq->curr, dest_rq,
+			TASK_UPDATE, wallclock, 0);
+
+	walt_update_task_ravg(p, task_rq(p), TASK_MIGRATE, wallclock, 0);
+
+	if (p->ravg.curr_window) {
+		src_rq->curr_runnable_sum -= p->ravg.curr_window;
+		dest_rq->curr_runnable_sum += p->ravg.curr_window;
+	}
+
+	if (p->ravg.prev_window) {
+		src_rq->prev_runnable_sum -= p->ravg.prev_window;
+		dest_rq->prev_runnable_sum += p->ravg.prev_window;
+	}
+
+	if ((s64)src_rq->prev_runnable_sum < 0) {
+		src_rq->prev_runnable_sum = 0;
+		WARN_ON(1);
+	}
+	if ((s64)src_rq->curr_runnable_sum < 0) {
+		src_rq->curr_runnable_sum = 0;
+		WARN_ON(1);
+	}
+
+	trace_walt_migration_update_sum(src_rq, p);
+	trace_walt_migration_update_sum(dest_rq, p);
+
+	if (p->state == TASK_WAKING)
+		double_rq_unlock(src_rq, dest_rq);
+}
+
+/*
+ * Return 'capacity' of a cpu in reference to "least" efficient cpu, such that
+ * least efficient cpu gets capacity of 1024
+ */
+static unsigned long capacity_scale_cpu_efficiency(int cpu)
+{
+	return (1024 * cpu_rq(cpu)->efficiency) / min_possible_efficiency;
+}
+
+/*
+ * Return 'capacity' of a cpu in reference to cpu with lowest max_freq
+ * (min_max_freq), such that one with lowest max_freq gets capacity of 1024.
+ */
+static unsigned long capacity_scale_cpu_freq(int cpu)
+{
+	return (1024 * cpu_rq(cpu)->max_freq) / min_max_freq;
+}
+
+/*
+ * Return load_scale_factor of a cpu in reference to "most" efficient cpu, so
+ * that "most" efficient cpu gets a load_scale_factor of 1
+ */
+static unsigned long load_scale_cpu_efficiency(int cpu)
+{
+	return DIV_ROUND_UP(1024 * max_possible_efficiency,
+			    cpu_rq(cpu)->efficiency);
+}
+
+/*
+ * Return load_scale_factor of a cpu in reference to cpu with best max_freq
+ * (max_possible_freq), so that one with best max_freq gets a load_scale_factor
+ * of 1.
+ */
+static unsigned long load_scale_cpu_freq(int cpu)
+{
+	return DIV_ROUND_UP(1024 * max_possible_freq, cpu_rq(cpu)->max_freq);
+}
+
+static int compute_capacity(int cpu)
+{
+	int capacity = 1024;
+
+	capacity *= capacity_scale_cpu_efficiency(cpu);
+	capacity >>= 10;
+
+	capacity *= capacity_scale_cpu_freq(cpu);
+	capacity >>= 10;
+
+	return capacity;
+}
+
+static int compute_load_scale_factor(int cpu)
+{
+	int load_scale = 1024;
+
+	/*
+	 * load_scale_factor accounts for the fact that task load
+	 * is in reference to "best" performing cpu. Task's load will need to be
+	 * scaled (up) by a factor to determine suitability to be placed on a
+	 * (little) cpu.
+	 */
+	load_scale *= load_scale_cpu_efficiency(cpu);
+	load_scale >>= 10;
+
+	load_scale *= load_scale_cpu_freq(cpu);
+	load_scale >>= 10;
+
+	return load_scale;
+}
+
+static int cpufreq_notifier_policy(struct notifier_block *nb,
+		unsigned long val, void *data)
+{
+	struct cpufreq_policy *policy = (struct cpufreq_policy *)data;
+	int i, update_max = 0;
+	u64 highest_mpc = 0, highest_mplsf = 0;
+	const struct cpumask *cpus = policy->related_cpus;
+	unsigned int orig_min_max_freq = min_max_freq;
+	unsigned int orig_max_possible_freq = max_possible_freq;
+	/* Initialized to policy->max in case policy->related_cpus is empty! */
+	unsigned int orig_max_freq = policy->max;
+
+	if (val != CPUFREQ_NOTIFY)
+		return 0;
+
+	for_each_cpu(i, policy->related_cpus) {
+		cpumask_copy(&cpu_rq(i)->freq_domain_cpumask,
+			     policy->related_cpus);
+		orig_max_freq = cpu_rq(i)->max_freq;
+		cpu_rq(i)->min_freq = policy->min;
+		cpu_rq(i)->max_freq = policy->max;
+		cpu_rq(i)->cur_freq = policy->cur;
+		cpu_rq(i)->max_possible_freq = policy->cpuinfo.max_freq;
+	}
+
+	max_possible_freq = max(max_possible_freq, policy->cpuinfo.max_freq);
+	if (min_max_freq == 1)
+		min_max_freq = UINT_MAX;
+	min_max_freq = min(min_max_freq, policy->cpuinfo.max_freq);
+	BUG_ON(!min_max_freq);
+	BUG_ON(!policy->max);
+
+	/* Changes to policy other than max_freq don't require any updates */
+	if (orig_max_freq == policy->max)
+		return 0;
+
+	/*
+	 * A changed min_max_freq or max_possible_freq (possible during bootup)
+	 * needs to trigger re-computation of load_scale_factor and capacity for
+	 * all possible cpus (even those offline). It also needs to trigger
+	 * re-computation of nr_big_task count on all online cpus.
+	 *
+	 * A changed rq->max_freq otoh needs to trigger re-computation of
+	 * load_scale_factor and capacity for just the cluster of cpus involved.
+	 * Since small task definition depends on max_load_scale_factor, a
+	 * changed load_scale_factor of one cluster could influence
+	 * classification of tasks in another cluster. Hence a changed
+	 * rq->max_freq will need to trigger re-computation of nr_big_task
+	 * count on all online cpus.
+	 *
+	 * While it should be sufficient for nr_big_tasks to be
+	 * re-computed for only online cpus, we have inadequate context
+	 * information here (in policy notifier) with regard to hotplug-safety
+	 * context in which notification is issued. As a result, we can't use
+	 * get_online_cpus() here, as it can lead to deadlock. Until cpufreq is
+	 * fixed up to issue notification always in hotplug-safe context,
+	 * re-compute nr_big_task for all possible cpus.
+	 */
+
+	if (orig_min_max_freq != min_max_freq ||
+		orig_max_possible_freq != max_possible_freq) {
+			cpus = cpu_possible_mask;
+			update_max = 1;
+	}
+
+	/*
+	 * Changed load_scale_factor can trigger reclassification of tasks as
+	 * big or small. Make this change "atomic" so that tasks are accounted
+	 * properly due to changed load_scale_factor
+	 */
+	for_each_cpu(i, cpus) {
+		struct rq *rq = cpu_rq(i);
+
+		rq->capacity = compute_capacity(i);
+		rq->load_scale_factor = compute_load_scale_factor(i);
+
+		if (update_max) {
+			u64 mpc, mplsf;
+
+			mpc = div_u64(((u64) rq->capacity) *
+				rq->max_possible_freq, rq->max_freq);
+			rq->max_possible_capacity = (int) mpc;
+
+			mplsf = div_u64(((u64) rq->load_scale_factor) *
+				rq->max_possible_freq, rq->max_freq);
+
+			if (mpc > highest_mpc) {
+				highest_mpc = mpc;
+				cpumask_clear(&mpc_mask);
+				cpumask_set_cpu(i, &mpc_mask);
+			} else if (mpc == highest_mpc) {
+				cpumask_set_cpu(i, &mpc_mask);
+			}
+
+			if (mplsf > highest_mplsf)
+				highest_mplsf = mplsf;
+		}
+	}
+
+	if (update_max) {
+		max_possible_capacity = highest_mpc;
+		max_load_scale_factor = highest_mplsf;
+	}
+
+	return 0;
+}
+
+static int cpufreq_notifier_trans(struct notifier_block *nb,
+		unsigned long val, void *data)
+{
+	struct cpufreq_freqs *freq = (struct cpufreq_freqs *)data;
+	unsigned int cpu = freq->cpu, new_freq = freq->new;
+	unsigned long flags;
+	int i;
+
+	if (val != CPUFREQ_POSTCHANGE)
+		return 0;
+
+	BUG_ON(!new_freq);
+
+	if (cpu_rq(cpu)->cur_freq == new_freq)
+		return 0;
+
+	for_each_cpu(i, &cpu_rq(cpu)->freq_domain_cpumask) {
+		struct rq *rq = cpu_rq(i);
+
+		raw_spin_lock_irqsave(&rq->lock, flags);
+		walt_update_task_ravg(rq->curr, rq, TASK_UPDATE,
+				      walt_ktime_clock(), 0);
+		rq->cur_freq = new_freq;
+		raw_spin_unlock_irqrestore(&rq->lock, flags);
+	}
+
+	return 0;
+}
+
+static struct notifier_block notifier_policy_block = {
+	.notifier_call = cpufreq_notifier_policy
+};
+
+static struct notifier_block notifier_trans_block = {
+	.notifier_call = cpufreq_notifier_trans
+};
+
+static int register_sched_callback(void)
+{
+	int ret;
+
+	ret = cpufreq_register_notifier(&notifier_policy_block,
+						CPUFREQ_POLICY_NOTIFIER);
+
+	if (!ret)
+		ret = cpufreq_register_notifier(&notifier_trans_block,
+						CPUFREQ_TRANSITION_NOTIFIER);
+
+	return 0;
+}
+
+/*
+ * cpufreq callbacks can be registered at core_initcall or later time.
+ * Any registration done prior to that is "forgotten" by cpufreq. See
+ * initialization of variable init_cpufreq_transition_notifier_list_called
+ * for further information.
+ */
+core_initcall(register_sched_callback);
+
+void walt_init_new_task_load(struct task_struct *p)
+{
+	int i;
+	u32 init_load_windows =
+			div64_u64((u64)sysctl_sched_walt_init_task_load_pct *
+                          (u64)walt_ravg_window, 100);
+	u32 init_load_pct = current->init_load_pct;
+
+	p->init_load_pct = 0;
+	memset(&p->ravg, 0, sizeof(struct ravg));
+
+	if (init_load_pct) {
+		init_load_windows = div64_u64((u64)init_load_pct *
+			  (u64)walt_ravg_window, 100);
+	}
+
+	p->ravg.demand = init_load_windows;
+	for (i = 0; i < RAVG_HIST_SIZE_MAX; ++i)
+		p->ravg.sum_history[i] = init_load_windows;
+}
diff --git a/kernel/sched/walt.h b/kernel/sched/walt.h
new file mode 100644
index 0000000..e181c87
--- /dev/null
+++ b/kernel/sched/walt.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __WALT_H
+#define __WALT_H
+
+#ifdef CONFIG_SCHED_WALT
+
+void walt_update_task_ravg(struct task_struct *p, struct rq *rq, int event,
+		u64 wallclock, u64 irqtime);
+void walt_inc_cumulative_runnable_avg(struct rq *rq, struct task_struct *p);
+void walt_dec_cumulative_runnable_avg(struct rq *rq, struct task_struct *p);
+void walt_inc_cfs_cumulative_runnable_avg(struct cfs_rq *rq,
+		struct task_struct *p);
+void walt_dec_cfs_cumulative_runnable_avg(struct cfs_rq *rq,
+		struct task_struct *p);
+void walt_fixup_busy_time(struct task_struct *p, int new_cpu);
+void walt_init_new_task_load(struct task_struct *p);
+void walt_mark_task_starting(struct task_struct *p);
+void walt_set_window_start(struct rq *rq);
+void walt_migrate_sync_cpu(int cpu);
+void walt_init_cpu_efficiency(void);
+u64 walt_ktime_clock(void);
+void walt_account_irqtime(int cpu, struct task_struct *curr, u64 delta,
+                                  u64 wallclock);
+
+u64 walt_irqload(int cpu);
+int walt_cpu_high_irqload(int cpu);
+
+#else /* CONFIG_SCHED_WALT */
+
+static inline void walt_update_task_ravg(struct task_struct *p, struct rq *rq,
+		int event, u64 wallclock, u64 irqtime) { }
+static inline void walt_inc_cumulative_runnable_avg(struct rq *rq, struct task_struct *p) { }
+static inline void walt_dec_cumulative_runnable_avg(struct rq *rq, struct task_struct *p) { }
+static inline void walt_inc_cfs_cumulative_runnable_avg(struct cfs_rq *rq,
+		struct task_struct *p) { }
+static inline void walt_dec_cfs_cumulative_runnable_avg(struct cfs_rq *rq,
+		struct task_struct *p) { }
+static inline void walt_fixup_busy_time(struct task_struct *p, int new_cpu) { }
+static inline void walt_init_new_task_load(struct task_struct *p) { }
+static inline void walt_mark_task_starting(struct task_struct *p) { }
+static inline void walt_set_window_start(struct rq *rq) { }
+static inline void walt_migrate_sync_cpu(int cpu) { }
+static inline void walt_init_cpu_efficiency(void) { }
+static inline u64 walt_ktime_clock(void) { return 0; }
+
+#endif /* CONFIG_SCHED_WALT */
+
+extern unsigned int walt_disabled;
+
+#endif
diff --git a/kernel/signal.c b/kernel/signal.c
index f3f1f7a..b92a047 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -503,7 +503,8 @@
 	return !tsk->ptrace;
 }
 
-static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+static void collect_signal(int sig, struct sigpending *list, siginfo_t *info,
+			   bool *resched_timer)
 {
 	struct sigqueue *q, *first = NULL;
 
@@ -525,6 +526,12 @@
 still_pending:
 		list_del_init(&first->list);
 		copy_siginfo(info, &first->info);
+
+		*resched_timer =
+			(first->flags & SIGQUEUE_PREALLOC) &&
+			(info->si_code == SI_TIMER) &&
+			(info->si_sys_private);
+
 		__sigqueue_free(first);
 	} else {
 		/*
@@ -541,12 +548,12 @@
 }
 
 static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
-			siginfo_t *info)
+			siginfo_t *info, bool *resched_timer)
 {
 	int sig = next_signal(pending, mask);
 
 	if (sig)
-		collect_signal(sig, pending, info);
+		collect_signal(sig, pending, info, resched_timer);
 	return sig;
 }
 
@@ -558,15 +565,16 @@
  */
 int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
 {
+	bool resched_timer = false;
 	int signr;
 
 	/* We only dequeue private signals from ourselves, we don't let
 	 * signalfd steal them
 	 */
-	signr = __dequeue_signal(&tsk->pending, mask, info);
+	signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer);
 	if (!signr) {
 		signr = __dequeue_signal(&tsk->signal->shared_pending,
-					 mask, info);
+					 mask, info, &resched_timer);
 		/*
 		 * itimer signal ?
 		 *
@@ -611,7 +619,7 @@
 		 */
 		current->jobctl |= JOBCTL_STOP_DEQUEUED;
 	}
-	if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
+	if (resched_timer) {
 		/*
 		 * Release the siglock to ensure proper locking order
 		 * of timer locks outside of siglocks.  Note, we leave
diff --git a/kernel/sys.c b/kernel/sys.c
index 0589f5b..ba3ddb4 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2372,6 +2372,9 @@
 		error = prctl_get_tid_address(me, (int __user **)arg2);
 		break;
 	case PR_SET_TIMERSLACK_PID:
+		if (task_pid_vnr(current) != (pid_t)arg3 &&
+				!capable(CAP_SYS_NICE))
+			return -EPERM;
 		rcu_read_lock();
 		tsk = find_task_by_vpid((pid_t)arg3);
 		if (tsk == NULL) {
@@ -2380,10 +2383,6 @@
 		}
 		get_task_struct(tsk);
 		rcu_read_unlock();
-		if (ptrace_may_access(tsk, PTRACE_MODE_ATTACH)) {
-			put_task_struct(tsk);
-			return -EPERM;
-		}
 		if (arg2 <= 0)
 			tsk->timer_slack_ns =
 				tsk->default_timer_slack_ns;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 35bfe0c..6e64c71 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -65,6 +65,7 @@
 #include <linux/sched/sysctl.h>
 #include <linux/kexec.h>
 #include <linux/bpf.h>
+#include <linux/mount.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>
@@ -174,7 +175,7 @@
 #define SYSCTL_WRITES_WARN	 0
 #define SYSCTL_WRITES_STRICT	 1
 
-static int sysctl_writes_strict = SYSCTL_WRITES_WARN;
+static int sysctl_writes_strict = SYSCTL_WRITES_STRICT;
 
 static int proc_do_cad_pid(struct ctl_table *table, int write,
 		  void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -305,6 +306,57 @@
 		.extra2		= &max_sched_granularity_ns,
 	},
 	{
+		.procname	= "sched_sync_hint_enable",
+		.data		= &sysctl_sched_sync_hint_enable,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+#ifdef CONFIG_SCHED_WALT
+	{
+		.procname	= "sched_use_walt_cpu_util",
+		.data		= &sysctl_sched_use_walt_cpu_util,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "sched_use_walt_task_util",
+		.data		= &sysctl_sched_use_walt_task_util,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "sched_walt_init_task_load_pct",
+		.data		= &sysctl_sched_walt_init_task_load_pct,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "sched_walt_cpu_high_irqload",
+		.data		= &sysctl_sched_walt_cpu_high_irqload,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+#endif
+	{
+		.procname	= "sched_initial_task_util",
+		.data		= &sysctl_sched_initial_task_util,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "sched_cstate_aware",
+		.data		= &sysctl_sched_cstate_aware,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
 		.procname	= "sched_wakeup_granularity_ns",
 		.data		= &sysctl_sched_wakeup_granularity,
 		.maxlen		= sizeof(unsigned int),
@@ -435,6 +487,21 @@
 		.extra1		= &one,
 	},
 #endif
+#ifdef CONFIG_SCHED_TUNE
+	{
+		.procname	= "sched_cfs_boost",
+		.data		= &sysctl_sched_cfs_boost,
+		.maxlen		= sizeof(sysctl_sched_cfs_boost),
+#ifdef CONFIG_CGROUP_SCHEDTUNE
+		.mode		= 0444,
+#else
+		.mode		= 0644,
+#endif
+		.proc_handler	= &sysctl_sched_cfs_boost_handler,
+		.extra1		= &zero,
+		.extra2		= &one_hundred,
+	},
+#endif
 #ifdef CONFIG_PROVE_LOCKING
 	{
 		.procname	= "prove_locking",
@@ -1766,6 +1833,28 @@
 		.proc_handler	= &pipe_proc_fn,
 		.extra1		= &pipe_min_size,
 	},
+	{
+		.procname	= "pipe-user-pages-hard",
+		.data		= &pipe_user_pages_hard,
+		.maxlen		= sizeof(pipe_user_pages_hard),
+		.mode		= 0644,
+		.proc_handler	= proc_doulongvec_minmax,
+	},
+	{
+		.procname	= "pipe-user-pages-soft",
+		.data		= &pipe_user_pages_soft,
+		.maxlen		= sizeof(pipe_user_pages_soft),
+		.mode		= 0644,
+		.proc_handler	= proc_doulongvec_minmax,
+	},
+	{
+		.procname	= "mount-max",
+		.data		= &sysctl_mount_max,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &one,
+	},
 	{ }
 };
 
@@ -2068,6 +2157,24 @@
 	return 0;
 }
 
+static int do_proc_douintvec_conv(bool *negp, unsigned long *lvalp,
+				 int *valp,
+				 int write, void *data)
+{
+	if (write) {
+		if (*negp)
+			return -EINVAL;
+		if (*lvalp > UINT_MAX)
+			return -EINVAL;
+		*valp = *lvalp;
+	} else {
+		unsigned int val = *valp;
+		*negp = false;
+		*lvalp = (unsigned long)val;
+	}
+	return 0;
+}
+
 static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
 
 static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
@@ -2195,8 +2302,27 @@
 int proc_dointvec(struct ctl_table *table, int write,
 		     void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-    return do_proc_dointvec(table,write,buffer,lenp,ppos,
-		    	    NULL,NULL);
+	return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
+}
+
+/**
+ * proc_douintvec - read a vector of unsigned integers
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ * @ppos: file position
+ *
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
+ * values from/to the user buffer, treated as an ASCII string.
+ *
+ * Returns 0 on success.
+ */
+int proc_douintvec(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return do_proc_dointvec(table, write, buffer, lenp, ppos,
+				do_proc_douintvec_conv, NULL);
 }
 
 /*
@@ -2397,6 +2523,7 @@
 				break;
 			if (neg)
 				continue;
+			val = convmul * val / convdiv;
 			if ((min && val < *min) || (max && val > *max))
 				continue;
 			*i = val;
@@ -2809,6 +2936,12 @@
 	return -ENOSYS;
 }
 
+int proc_douintvec(struct ctl_table *table, int write,
+		  void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return -ENOSYS;
+}
+
 int proc_dointvec_minmax(struct ctl_table *table, int write,
 		    void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -2854,6 +2987,7 @@
  * exception granted :-)
  */
 EXPORT_SYMBOL(proc_dointvec);
+EXPORT_SYMBOL(proc_douintvec);
 EXPORT_SYMBOL(proc_dointvec_jiffies);
 EXPORT_SYMBOL(proc_dointvec_minmax);
 EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 7fbba63..2c3a23d 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -339,7 +339,7 @@
 {
 	struct alarm_base *base = &alarm_bases[alarm->type];
 
-	start = ktime_add(start, base->gettime());
+	start = ktime_add_safe(start, base->gettime());
 	alarm_start(alarm, start);
 }
 EXPORT_SYMBOL_GPL(alarm_start_relative);
@@ -425,7 +425,7 @@
 		overrun++;
 	}
 
-	alarm->node.expires = ktime_add(alarm->node.expires, interval);
+	alarm->node.expires = ktime_add_safe(alarm->node.expires, interval);
 	return overrun;
 }
 EXPORT_SYMBOL_GPL(alarm_forward);
@@ -611,13 +611,21 @@
 
 	/* start the timer */
 	timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval);
+
+	/*
+	 * Rate limit to the tick as a hot fix to prevent DOS. Will be
+	 * mopped up later.
+	 */
+	if (ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC)
+		timr->it.alarm.interval = ktime_set(0, TICK_NSEC);
+
 	exp = timespec_to_ktime(new_setting->it_value);
 	/* Convert (if necessary) to absolute time */
 	if (flags != TIMER_ABSTIME) {
 		ktime_t now;
 
 		now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime();
-		exp = ktime_add(now, exp);
+		exp = ktime_add_safe(now, exp);
 	}
 
 	alarm_start(&timr->it.alarm.alarmtimer, exp);
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 1347882..b98810d 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -323,13 +323,42 @@
 		/* cs is a watchdog. */
 		if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
 			cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
-		/* Pick the best watchdog. */
-		if (!watchdog || cs->rating > watchdog->rating) {
-			watchdog = cs;
-			/* Reset watchdog cycles */
-			clocksource_reset_watchdog();
-		}
 	}
+	spin_unlock_irqrestore(&watchdog_lock, flags);
+}
+
+static void clocksource_select_watchdog(bool fallback)
+{
+	struct clocksource *cs, *old_wd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&watchdog_lock, flags);
+	/* save current watchdog */
+	old_wd = watchdog;
+	if (fallback)
+		watchdog = NULL;
+
+	list_for_each_entry(cs, &clocksource_list, list) {
+		/* cs is a clocksource to be watched. */
+		if (cs->flags & CLOCK_SOURCE_MUST_VERIFY)
+			continue;
+
+		/* Skip current if we were requested for a fallback. */
+		if (fallback && cs == old_wd)
+			continue;
+
+		/* Pick the best watchdog. */
+		if (!watchdog || cs->rating > watchdog->rating)
+			watchdog = cs;
+	}
+	/* If we failed to find a fallback restore the old one. */
+	if (!watchdog)
+		watchdog = old_wd;
+
+	/* If we changed the watchdog we need to reset cycles. */
+	if (watchdog != old_wd)
+		clocksource_reset_watchdog();
+
 	/* Check if the watchdog timer needs to be started. */
 	clocksource_start_watchdog();
 	spin_unlock_irqrestore(&watchdog_lock, flags);
@@ -404,6 +433,7 @@
 		cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
 }
 
+static void clocksource_select_watchdog(bool fallback) { }
 static inline void clocksource_dequeue_watchdog(struct clocksource *cs) { }
 static inline void clocksource_resume_watchdog(void) { }
 static inline int __clocksource_watchdog_kthread(void) { return 0; }
@@ -736,6 +766,7 @@
 	clocksource_enqueue(cs);
 	clocksource_enqueue_watchdog(cs);
 	clocksource_select();
+	clocksource_select_watchdog(false);
 	mutex_unlock(&clocksource_mutex);
 	return 0;
 }
@@ -758,6 +789,7 @@
 	mutex_lock(&clocksource_mutex);
 	__clocksource_change_rating(cs, rating);
 	clocksource_select();
+	clocksource_select_watchdog(false);
 	mutex_unlock(&clocksource_mutex);
 }
 EXPORT_SYMBOL(clocksource_change_rating);
@@ -767,12 +799,12 @@
  */
 static int clocksource_unbind(struct clocksource *cs)
 {
-	/*
-	 * I really can't convince myself to support this on hardware
-	 * designed by lobotomized monkeys.
-	 */
-	if (clocksource_is_watchdog(cs))
-		return -EBUSY;
+	if (clocksource_is_watchdog(cs)) {
+		/* Select and try to install a replacement watchdog. */
+		clocksource_select_watchdog(true);
+		if (clocksource_is_watchdog(cs))
+			return -EBUSY;
+	}
 
 	if (cs == curr_clocksource) {
 		/* Select and try to install a replacement clock source */
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 58a321c..405536b 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -94,6 +94,9 @@
 };
 
 static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
+	/* Make sure we catch unsupported clockids */
+	[0 ... MAX_CLOCKS - 1]	= HRTIMER_MAX_CLOCK_BASES,
+
 	[CLOCK_REALTIME]	= HRTIMER_BASE_REALTIME,
 	[CLOCK_MONOTONIC]	= HRTIMER_BASE_MONOTONIC,
 	[CLOCK_BOOTTIME]	= HRTIMER_BASE_BOOTTIME,
@@ -102,7 +105,9 @@
 
 static inline int hrtimer_clockid_to_base(clockid_t clock_id)
 {
-	return hrtimer_clock_to_base_table[clock_id];
+	int base = hrtimer_clock_to_base_table[clock_id];
+	BUG_ON(base == HRTIMER_MAX_CLOCK_BASES);
+	return base;
 }
 
 /*
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 149cc80..ab86177 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -674,8 +674,24 @@
 			return -EINVAL;
 	}
 
-	if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
-		return -EPERM;
+	if (txc->modes & ADJ_SETOFFSET) {
+		/* In order to inject time, you gotta be super-user! */
+		if (!capable(CAP_SYS_TIME))
+			return -EPERM;
+
+		if (txc->modes & ADJ_NANO) {
+			struct timespec ts;
+
+			ts.tv_sec = txc->time.tv_sec;
+			ts.tv_nsec = txc->time.tv_usec;
+			if (!timespec_inject_offset_valid(&ts))
+				return -EINVAL;
+
+		} else {
+			if (!timeval_inject_offset_valid(&txc->time))
+				return -EINVAL;
+		}
+	}
 
 	/*
 	 * Check for potential multiplication overflows that can
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index f5e86d2..80016b3 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -808,6 +808,7 @@
 			timer->it.cpu.expires = 0;
 			sample_to_timespec(timer->it_clock, timer->it.cpu.expires,
 					   &itp->it_value);
+			return;
 		} else {
 			cpu_timer_sample_group(timer->it_clock, p, &now);
 			unlock_task_sighand(p, &flags);
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index f6aae79..d2a20e8 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -871,6 +871,9 @@
 {
 	int cpu = smp_processor_id();
 
+	if (!bc)
+		return;
+
 	/* Set it up only once ! */
 	if (bc->event_handler != tick_handle_oneshot_broadcast) {
 		int was_periodic = clockevent_state_periodic(bc);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 99188ee..738f346 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -116,6 +116,26 @@
 	tk->offs_boot = ktime_add(tk->offs_boot, delta);
 }
 
+/*
+ * tk_clock_read - atomic clocksource read() helper
+ *
+ * This helper is necessary to use in the read paths because, while the
+ * seqlock ensures we don't return a bad value while structures are updated,
+ * it doesn't protect from potential crashes. There is the possibility that
+ * the tkr's clocksource may change between the read reference, and the
+ * clock reference passed to the read function.  This can cause crashes if
+ * the wrong clocksource is passed to the wrong read function.
+ * This isn't necessary to use when holding the timekeeper_lock or doing
+ * a read of the fast-timekeeper tkrs (which is protected by its own locking
+ * and update logic).
+ */
+static inline u64 tk_clock_read(struct tk_read_base *tkr)
+{
+	struct clocksource *clock = READ_ONCE(tkr->clock);
+
+	return clock->read(clock);
+}
+
 #ifdef CONFIG_DEBUG_TIMEKEEPING
 #define WARNING_FREQ (HZ*300) /* 5 minute rate-limiting */
 
@@ -173,7 +193,7 @@
 	 */
 	do {
 		seq = read_seqcount_begin(&tk_core.seq);
-		now = tkr->read(tkr->clock);
+		now = tk_clock_read(tkr);
 		last = tkr->cycle_last;
 		mask = tkr->mask;
 		max = tkr->clock->max_cycles;
@@ -207,7 +227,7 @@
 	cycle_t cycle_now, delta;
 
 	/* read clocksource */
-	cycle_now = tkr->read(tkr->clock);
+	cycle_now = tk_clock_read(tkr);
 
 	/* calculate the delta since the last update_wall_time */
 	delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask);
@@ -235,12 +255,10 @@
 
 	old_clock = tk->tkr_mono.clock;
 	tk->tkr_mono.clock = clock;
-	tk->tkr_mono.read = clock->read;
 	tk->tkr_mono.mask = clock->mask;
-	tk->tkr_mono.cycle_last = tk->tkr_mono.read(clock);
+	tk->tkr_mono.cycle_last = tk_clock_read(&tk->tkr_mono);
 
 	tk->tkr_raw.clock = clock;
-	tk->tkr_raw.read = clock->read;
 	tk->tkr_raw.mask = clock->mask;
 	tk->tkr_raw.cycle_last = tk->tkr_mono.cycle_last;
 
@@ -298,19 +316,36 @@
 static inline u32 arch_gettimeoffset(void) { return 0; }
 #endif
 
-static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
+static inline u64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
+					  cycle_t delta)
 {
-	cycle_t delta;
-	s64 nsec;
+	u64 nsec;
 
-	delta = timekeeping_get_delta(tkr);
-
-	nsec = (delta * tkr->mult + tkr->xtime_nsec) >> tkr->shift;
+	nsec = delta * tkr->mult + tkr->xtime_nsec;
+	nsec >>= tkr->shift;
 
 	/* If arch requires, add in get_arch_timeoffset() */
 	return nsec + arch_gettimeoffset();
 }
 
+static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
+{
+	cycle_t delta;
+
+	delta = timekeeping_get_delta(tkr);
+	return timekeeping_delta_to_ns(tkr, delta);
+}
+
+static inline s64 timekeeping_cycles_to_ns(struct tk_read_base *tkr,
+					    cycle_t cycles)
+{
+	cycle_t delta;
+
+	/* calculate the delta since the last update_wall_time */
+	delta = clocksource_delta(cycles, tkr->cycle_last, tkr->mask);
+	return timekeeping_delta_to_ns(tkr, delta);
+}
+
 /**
  * update_fast_timekeeper - Update the fast and NMI safe monotonic timekeeper.
  * @tkr: Timekeeping readout base from which we take the update
@@ -383,7 +418,13 @@
 	do {
 		seq = raw_read_seqcount_latch(&tkf->seq);
 		tkr = tkf->base + (seq & 0x01);
-		now = ktime_to_ns(tkr->base) + timekeeping_get_ns(tkr);
+		now = ktime_to_ns(tkr->base);
+
+		now += timekeeping_delta_to_ns(tkr,
+				clocksource_delta(
+					tk_clock_read(tkr),
+					tkr->cycle_last,
+					tkr->mask));
 	} while (read_seqcount_retry(&tkf->seq, seq));
 
 	return now;
@@ -401,6 +442,35 @@
 }
 EXPORT_SYMBOL_GPL(ktime_get_raw_fast_ns);
 
+/**
+ * ktime_get_boot_fast_ns - NMI safe and fast access to boot clock.
+ *
+ * To keep it NMI safe since we're accessing from tracing, we're not using a
+ * separate timekeeper with updates to monotonic clock and boot offset
+ * protected with seqlocks. This has the following minor side effects:
+ *
+ * (1) Its possible that a timestamp be taken after the boot offset is updated
+ * but before the timekeeper is updated. If this happens, the new boot offset
+ * is added to the old timekeeping making the clock appear to update slightly
+ * earlier:
+ *    CPU 0                                        CPU 1
+ *    timekeeping_inject_sleeptime64()
+ *    __timekeeping_inject_sleeptime(tk, delta);
+ *                                                 timestamp();
+ *    timekeeping_update(tk, TK_CLEAR_NTP...);
+ *
+ * (2) On 32-bit systems, the 64-bit boot offset (tk->offs_boot) may be
+ * partially updated.  Since the tk->offs_boot update is a rare event, this
+ * should be a rare occurrence which postprocessing should be able to handle.
+ */
+u64 notrace ktime_get_boot_fast_ns(void)
+{
+	struct timekeeper *tk = &tk_core.timekeeper;
+
+	return (ktime_get_mono_fast_ns() + ktime_to_ns(tk->offs_boot));
+}
+EXPORT_SYMBOL_GPL(ktime_get_boot_fast_ns);
+
 /* Suspend-time cycles value for halted fast timekeeper. */
 static cycle_t cycles_at_suspend;
 
@@ -409,6 +479,10 @@
 	return cycles_at_suspend;
 }
 
+static struct clocksource dummy_clock = {
+	.read = dummy_clock_read,
+};
+
 /**
  * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource.
  * @tk: Timekeeper to snapshot.
@@ -425,13 +499,13 @@
 	struct tk_read_base *tkr = &tk->tkr_mono;
 
 	memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
-	cycles_at_suspend = tkr->read(tkr->clock);
-	tkr_dummy.read = dummy_clock_read;
+	cycles_at_suspend = tk_clock_read(tkr);
+	tkr_dummy.clock = &dummy_clock;
 	update_fast_timekeeper(&tkr_dummy, &tk_fast_mono);
 
 	tkr = &tk->tkr_raw;
 	memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
-	tkr_dummy.read = dummy_clock_read;
+	tkr_dummy.clock = &dummy_clock;
 	update_fast_timekeeper(&tkr_dummy, &tk_fast_raw);
 }
 
@@ -595,11 +669,10 @@
  */
 static void timekeeping_forward_now(struct timekeeper *tk)
 {
-	struct clocksource *clock = tk->tkr_mono.clock;
 	cycle_t cycle_now, delta;
 	s64 nsec;
 
-	cycle_now = tk->tkr_mono.read(clock);
+	cycle_now = tk_clock_read(&tk->tkr_mono);
 	delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
 	tk->tkr_mono.cycle_last = cycle_now;
 	tk->tkr_raw.cycle_last  = cycle_now;
@@ -958,7 +1031,7 @@
 	struct timespec64 ts64, tmp;
 	int ret = 0;
 
-	if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
+	if (!timespec_inject_offset_valid(ts))
 		return -EINVAL;
 
 	ts64 = timespec_to_timespec64(*ts);
@@ -1382,7 +1455,7 @@
 	 * The less preferred source will only be tried if there is no better
 	 * usable source. The rtc part is handled separately in rtc core code.
 	 */
-	cycle_now = tk->tkr_mono.read(clock);
+	cycle_now = tk_clock_read(&tk->tkr_mono);
 	if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) &&
 		cycle_now > tk->tkr_mono.cycle_last) {
 		u64 num, max = ULLONG_MAX;
@@ -1777,7 +1850,7 @@
 #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
 	offset = real_tk->cycle_interval;
 #else
-	offset = clocksource_delta(tk->tkr_mono.read(tk->tkr_mono.clock),
+	offset = clocksource_delta(tk_clock_read(&tk->tkr_mono),
 				   tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
 #endif
 
diff --git a/kernel/time/timekeeping_debug.c b/kernel/time/timekeeping_debug.c
index f6bd652..107310a 100644
--- a/kernel/time/timekeeping_debug.c
+++ b/kernel/time/timekeeping_debug.c
@@ -23,7 +23,9 @@
 
 #include "timekeeping_internal.h"
 
-static unsigned int sleep_time_bin[32] = {0};
+#define NUM_BINS 32
+
+static unsigned int sleep_time_bin[NUM_BINS] = {0};
 
 static int tk_debug_show_sleep_time(struct seq_file *s, void *data)
 {
@@ -69,6 +71,9 @@
 
 void tk_debug_account_sleep_time(struct timespec64 *t)
 {
-	sleep_time_bin[fls(t->tv_sec)]++;
+	/* Cap bin index so we don't overflow the array */
+	int bin = min(fls(t->tv_sec), NUM_BINS-1);
+
+	sleep_time_bin[bin]++;
 }
 
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index ba04bf0..a9bba37 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -1,4 +1,8 @@
 
+# We are fully aware of the dangers of __builtin_return_address()
+FRAME_CFLAGS := $(call cc-disable-warning,frame-address)
+KBUILD_CFLAGS += $(FRAME_CFLAGS)
+
 # Do not instrument the tracer itself:
 
 ifdef CONFIG_FUNCTION_TRACER
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 3f743b1..34b2a0d 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3677,23 +3677,24 @@
 	ftrace_probe_registered = 1;
 }
 
-static void __disable_ftrace_function_probe(void)
+static bool __disable_ftrace_function_probe(void)
 {
 	int i;
 
 	if (!ftrace_probe_registered)
-		return;
+		return false;
 
 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
 		struct hlist_head *hhd = &ftrace_func_hash[i];
 		if (hhd->first)
-			return;
+			return false;
 	}
 
 	/* no more funcs left */
 	ftrace_shutdown(&trace_probe_ops, 0);
 
 	ftrace_probe_registered = 0;
+	return true;
 }
 
 
@@ -3820,6 +3821,7 @@
 __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 				  void *data, int flags)
 {
+	struct ftrace_ops_hash old_hash_ops;
 	struct ftrace_func_entry *rec_entry;
 	struct ftrace_func_probe *entry;
 	struct ftrace_func_probe *p;
@@ -3831,6 +3833,7 @@
 	struct hlist_node *tmp;
 	char str[KSYM_SYMBOL_LEN];
 	int i, ret;
+	bool disabled;
 
 	if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
 		func_g.search = NULL;
@@ -3849,6 +3852,10 @@
 
 	mutex_lock(&trace_probe_ops.func_hash->regex_lock);
 
+	old_hash_ops.filter_hash = old_hash;
+	/* Probes only have filters */
+	old_hash_ops.notrace_hash = NULL;
+
 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
 	if (!hash)
 		/* Hmm, should report this somehow */
@@ -3886,12 +3893,17 @@
 		}
 	}
 	mutex_lock(&ftrace_lock);
-	__disable_ftrace_function_probe();
+	disabled = __disable_ftrace_function_probe();
 	/*
 	 * Remove after the disable is called. Otherwise, if the last
 	 * probe is removed, a null hash means *all enabled*.
 	 */
 	ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
+
+	/* still need to update the function call sites */
+	if (ftrace_enabled && !disabled)
+		ftrace_run_modify_code(&trace_probe_ops, FTRACE_UPDATE_CALLS,
+				       &old_hash_ops);
 	synchronize_sched();
 	if (!ret)
 		free_ftrace_hash_rcu(old_hash);
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 9c6045a..1275175 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -437,7 +437,7 @@
 	raw_spinlock_t			reader_lock;	/* serialize readers */
 	arch_spinlock_t			lock;
 	struct lock_class_key		lock_key;
-	unsigned int			nr_pages;
+	unsigned long			nr_pages;
 	unsigned int			current_context;
 	struct list_head		*pages;
 	struct buffer_page		*head_page;	/* read from head */
@@ -458,7 +458,7 @@
 	u64				write_stamp;
 	u64				read_stamp;
 	/* ring buffer pages to update, > 0 to add, < 0 to remove */
-	int				nr_pages_to_update;
+	long				nr_pages_to_update;
 	struct list_head		new_pages; /* new pages to add */
 	struct work_struct		update_pages_work;
 	struct completion		update_done;
@@ -1137,10 +1137,10 @@
 	return 0;
 }
 
-static int __rb_allocate_pages(int nr_pages, struct list_head *pages, int cpu)
+static int __rb_allocate_pages(long nr_pages, struct list_head *pages, int cpu)
 {
-	int i;
 	struct buffer_page *bpage, *tmp;
+	long i;
 
 	for (i = 0; i < nr_pages; i++) {
 		struct page *page;
@@ -1177,7 +1177,7 @@
 }
 
 static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
-			     unsigned nr_pages)
+			     unsigned long nr_pages)
 {
 	LIST_HEAD(pages);
 
@@ -1202,7 +1202,7 @@
 }
 
 static struct ring_buffer_per_cpu *
-rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu)
+rb_allocate_cpu_buffer(struct ring_buffer *buffer, long nr_pages, int cpu)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
 	struct buffer_page *bpage;
@@ -1302,8 +1302,9 @@
 					struct lock_class_key *key)
 {
 	struct ring_buffer *buffer;
+	long nr_pages;
 	int bsize;
-	int cpu, nr_pages;
+	int cpu;
 
 	/* keep it in its own cache line */
 	buffer = kzalloc(ALIGN(sizeof(*buffer), cache_line_size()),
@@ -1429,12 +1430,12 @@
 }
 
 static int
-rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages)
+rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages)
 {
 	struct list_head *tail_page, *to_remove, *next_page;
 	struct buffer_page *to_remove_page, *tmp_iter_page;
 	struct buffer_page *last_page, *first_page;
-	unsigned int nr_removed;
+	unsigned long nr_removed;
 	unsigned long head_bit;
 	int page_entries;
 
@@ -1651,7 +1652,7 @@
 			int cpu_id)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
-	unsigned nr_pages;
+	unsigned long nr_pages;
 	int cpu, err = 0;
 
 	/*
@@ -1665,14 +1666,13 @@
 	    !cpumask_test_cpu(cpu_id, buffer->cpumask))
 		return size;
 
-	size = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
-	size *= BUF_PAGE_SIZE;
+	nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
 
 	/* we need a minimum of two pages */
-	if (size < BUF_PAGE_SIZE * 2)
-		size = BUF_PAGE_SIZE * 2;
+	if (nr_pages < 2)
+		nr_pages = 2;
 
-	nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
+	size = nr_pages * BUF_PAGE_SIZE;
 
 	/*
 	 * Don't succeed if resizing is disabled, as a reader might be
@@ -3440,11 +3440,23 @@
 int ring_buffer_iter_empty(struct ring_buffer_iter *iter)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
+	struct buffer_page *reader;
+	struct buffer_page *head_page;
+	struct buffer_page *commit_page;
+	unsigned commit;
 
 	cpu_buffer = iter->cpu_buffer;
 
-	return iter->head_page == cpu_buffer->commit_page &&
-		iter->head == rb_commit_index(cpu_buffer);
+	/* Remember, trace recording is off when iterator is in use */
+	reader = cpu_buffer->reader_page;
+	head_page = cpu_buffer->head_page;
+	commit_page = cpu_buffer->commit_page;
+	commit = rb_page_commit(commit_page);
+
+	return ((iter->head_page == commit_page && iter->head == commit) ||
+		(iter->head_page == reader && commit_page == head_page &&
+		 head_page->read == commit &&
+		 iter->head == rb_page_commit(cpu_buffer->reader_page)));
 }
 EXPORT_SYMBOL_GPL(ring_buffer_iter_empty);
 
@@ -4645,8 +4657,9 @@
 	struct ring_buffer *buffer =
 		container_of(self, struct ring_buffer, cpu_notify);
 	long cpu = (long)hcpu;
-	int cpu_i, nr_pages_same;
-	unsigned int nr_pages;
+	long nr_pages_same;
+	int cpu_i;
+	unsigned long nr_pages;
 
 	switch (action) {
 	case CPU_UP_PREPARE:
@@ -4874,9 +4887,9 @@
 		rb_data[cpu].cnt = cpu;
 		rb_threads[cpu] = kthread_create(rb_test, &rb_data[cpu],
 						 "rbtester/%d", cpu);
-		if (WARN_ON(!rb_threads[cpu])) {
+		if (WARN_ON(IS_ERR(rb_threads[cpu]))) {
 			pr_cont("FAILED\n");
-			ret = -1;
+			ret = PTR_ERR(rb_threads[cpu]);
 			goto out_free;
 		}
 
@@ -4886,9 +4899,9 @@
 
 	/* Now create the rb hammer! */
 	rb_hammer = kthread_run(rb_hammer_test, NULL, "rbhammer");
-	if (WARN_ON(!rb_hammer)) {
+	if (WARN_ON(IS_ERR(rb_hammer))) {
 		pr_cont("FAILED\n");
-		ret = -1;
+		ret = PTR_ERR(rb_hammer);
 		goto out_free;
 	}
 
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index dd4d86a..6300318 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -890,6 +890,7 @@
 	{ trace_clock,			"perf",		1 },
 	{ ktime_get_mono_fast_ns,	"mono",		1 },
 	{ ktime_get_raw_fast_ns,	"mono_raw",	1 },
+	{ ktime_get_boot_fast_ns,	"boot",		1 },
 	ARCH_TRACE_CLOCKS
 };
 
@@ -4816,19 +4817,20 @@
 	struct trace_iterator *iter = filp->private_data;
 	ssize_t sret;
 
-	/* return any leftover data */
-	sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
-	if (sret != -EBUSY)
-		return sret;
-
-	trace_seq_init(&iter->seq);
-
 	/*
 	 * Avoid more than one consumer on a single file descriptor
 	 * This is just a matter of traces coherency, the ring buffer itself
 	 * is protected.
 	 */
 	mutex_lock(&iter->mutex);
+
+	/* return any leftover data */
+	sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
+	if (sret != -EBUSY)
+		goto out;
+
+	trace_seq_init(&iter->seq);
+
 	if (iter->trace->read) {
 		sret = iter->trace->read(iter, filp, ubuf, cnt, ppos);
 		if (sret)
@@ -5855,9 +5857,6 @@
 		return -EBUSY;
 #endif
 
-	if (splice_grow_spd(pipe, &spd))
-		return -ENOMEM;
-
 	if (*ppos & (PAGE_SIZE - 1))
 		return -EINVAL;
 
@@ -5867,6 +5866,9 @@
 		len &= PAGE_MASK;
 	}
 
+	if (splice_grow_spd(pipe, &spd))
+		return -ENOMEM;
+
  again:
 	trace_access_lock(iter->cpu_file);
 	entries = ring_buffer_entries_cpu(iter->trace_buffer->buffer, iter->cpu_file);
@@ -5924,19 +5926,21 @@
 	/* did we read anything? */
 	if (!spd.nr_pages) {
 		if (ret)
-			return ret;
+			goto out;
 
+		ret = -EAGAIN;
 		if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK))
-			return -EAGAIN;
+			goto out;
 
 		ret = wait_on_pipe(iter, true);
 		if (ret)
-			return ret;
+			goto out;
 
 		goto again;
 	}
 
 	ret = splice_to_pipe(pipe, &spd);
+out:
 	splice_shrink_spd(&spd);
 
 	return ret;
@@ -6146,11 +6150,13 @@
 		return ret;
 
  out_reg:
+	ret = alloc_snapshot(&global_trace);
+	if (ret < 0)
+		goto out;
+
 	ret = register_ftrace_function_probe(glob, ops, count);
 
-	if (ret >= 0)
-		alloc_snapshot(&global_trace);
-
+ out:
 	return ret < 0 ? ret : 0;
 }
 
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 4641bdb..96c75b0 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -785,6 +785,10 @@
 
 		cpu_data = per_cpu_ptr(data->cpu_data, cpu);
 
+		/* If a graph tracer ignored set_graph_notrace */
+		if (call->depth < -1)
+			call->depth += FTRACE_NOTRACE_DEPTH;
+
 		/*
 		 * Comments display at + 1 to depth. Since
 		 * this is a leaf function, keep the comments
@@ -793,7 +797,8 @@
 		cpu_data->depth = call->depth - 1;
 
 		/* No need to keep this function around for this depth */
-		if (call->depth < FTRACE_RETFUNC_DEPTH)
+		if (call->depth < FTRACE_RETFUNC_DEPTH &&
+		    !WARN_ON_ONCE(call->depth < 0))
 			cpu_data->enter_funcs[call->depth] = 0;
 	}
 
@@ -823,11 +828,16 @@
 		struct fgraph_cpu_data *cpu_data;
 		int cpu = iter->cpu;
 
+		/* If a graph tracer ignored set_graph_notrace */
+		if (call->depth < -1)
+			call->depth += FTRACE_NOTRACE_DEPTH;
+
 		cpu_data = per_cpu_ptr(data->cpu_data, cpu);
 		cpu_data->depth = call->depth;
 
 		/* Save this function pointer to see if the exit matches */
-		if (call->depth < FTRACE_RETFUNC_DEPTH)
+		if (call->depth < FTRACE_RETFUNC_DEPTH &&
+		    !WARN_ON_ONCE(call->depth < 0))
 			cpu_data->enter_funcs[call->depth] = call->func;
 	}
 
@@ -1057,7 +1067,8 @@
 		 */
 		cpu_data->depth = trace->depth - 1;
 
-		if (trace->depth < FTRACE_RETFUNC_DEPTH) {
+		if (trace->depth < FTRACE_RETFUNC_DEPTH &&
+		    !WARN_ON_ONCE(trace->depth < 0)) {
 			if (cpu_data->enter_funcs[trace->depth] != trace->func)
 				func_match = 0;
 			cpu_data->enter_funcs[trace->depth] = 0;
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index c995644..e9092a0 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -659,30 +659,25 @@
 		pr_info("Probe point is not specified.\n");
 		return -EINVAL;
 	}
-	if (isdigit(argv[1][0])) {
-		if (is_return) {
-			pr_info("Return probe point must be a symbol.\n");
-			return -EINVAL;
-		}
-		/* an address specified */
-		ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr);
-		if (ret) {
-			pr_info("Failed to parse address.\n");
-			return ret;
-		}
-	} else {
+
+	/* try to parse an address. if that fails, try to read the
+	 * input as a symbol. */
+	if (kstrtoul(argv[1], 0, (unsigned long *)&addr)) {
 		/* a symbol specified */
 		symbol = argv[1];
 		/* TODO: support .init module functions */
 		ret = traceprobe_split_symbol_offset(symbol, &offset);
 		if (ret) {
-			pr_info("Failed to parse symbol.\n");
+			pr_info("Failed to parse either an address or a symbol.\n");
 			return ret;
 		}
 		if (offset && is_return) {
 			pr_info("Return probe must be used without offset.\n");
 			return -EINVAL;
 		}
+	} else if (is_return) {
+		pr_info("Return probe point must be a symbol.\n");
+		return -EINVAL;
 	}
 	argc -= 2; argv += 2;
 
@@ -1471,6 +1466,11 @@
 
 end:
 	release_all_trace_kprobes();
+	/*
+	 * Wait for the optimizer work to finish. Otherwise it might fiddle
+	 * with probes in already freed __init text.
+	 */
+	wait_for_kprobe_optimizer();
 	if (warn)
 		pr_cont("NG: Some tests are failed. Please check them.\n");
 	else
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
index f96f038..ad1d616 100644
--- a/kernel/trace/trace_printk.c
+++ b/kernel/trace/trace_printk.c
@@ -36,6 +36,10 @@
 static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
 {
 	struct trace_bprintk_fmt *pos;
+
+	if (!fmt)
+		return ERR_PTR(-EINVAL);
+
 	list_for_each_entry(pos, &trace_bprintk_fmt_list, list) {
 		if (!strcmp(pos->fmt, fmt))
 			return pos;
@@ -57,7 +61,8 @@
 	for (iter = start; iter < end; iter++) {
 		struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
 		if (tb_fmt) {
-			*iter = tb_fmt->fmt;
+			if (!IS_ERR(tb_fmt))
+				*iter = tb_fmt->fmt;
 			continue;
 		}
 
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 1f1b05f..b718530 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -403,7 +403,6 @@
 	 */
 	if (is_hardlockup()) {
 		int this_cpu = smp_processor_id();
-		struct pt_regs *regs = get_irq_regs();
 
 		/* only print hardlockups once */
 		if (__this_cpu_read(hard_watchdog_warn) == true)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 0ec0594..2c2f971 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -4457,6 +4457,17 @@
 						  pool->attrs->cpumask) < 0);
 
 	spin_lock_irq(&pool->lock);
+
+	/*
+	 * XXX: CPU hotplug notifiers are weird and can call DOWN_FAILED
+	 * w/o preceding DOWN_PREPARE.  Work around it.  CPU hotplug is
+	 * being reworked and this can go away in time.
+	 */
+	if (!(pool->flags & POOL_DISASSOCIATED)) {
+		spin_unlock_irq(&pool->lock);
+		return;
+	}
+
 	pool->flags &= ~POOL_DISASSOCIATED;
 
 	for_each_pool_worker(worker, pool) {
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index fc9f2ad..63d14d9 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -867,6 +867,15 @@
 	bool
 	default n
 
+config PANIC_ON_RT_THROTTLING
+	bool "Panic on RT throttling"
+	help
+	  Say Y here to enable the kernel to panic when a realtime
+	  runqueue is throttled. This may be useful for detecting
+	  and debugging RT throttling issues.
+
+	  Say N if unsure.
+
 config SCHEDSTATS
 	bool "Collect scheduler statistics"
 	depends on DEBUG_KERNEL && PROC_FS
diff --git a/lib/cmdline.c b/lib/cmdline.c
index 8f13cf7..79069d7 100644
--- a/lib/cmdline.c
+++ b/lib/cmdline.c
@@ -22,14 +22,14 @@
  *	the values[M, M+1, ..., N] into the ints array in get_options.
  */
 
-static int get_range(char **str, int *pint)
+static int get_range(char **str, int *pint, int n)
 {
 	int x, inc_counter, upper_range;
 
 	(*str)++;
 	upper_range = simple_strtol((*str), NULL, 0);
 	inc_counter = upper_range - *pint;
-	for (x = *pint; x < upper_range; x++)
+	for (x = *pint; n && x < upper_range; x++, n--)
 		*pint++ = x;
 	return inc_counter;
 }
@@ -96,7 +96,7 @@
 			break;
 		if (res == 3) {
 			int range_nums;
-			range_nums = get_range((char **)&str, ints + i);
+			range_nums = get_range((char **)&str, ints + i, nints - i);
 			if (range_nums < 0)
 				break;
 			/*
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 4a1515f..51a76af 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -657,9 +657,9 @@
 	spin_lock_irqsave(&free_entries_lock, flags);
 
 	if (list_empty(&free_entries)) {
-		pr_err("DMA-API: debugging out of memory - disabling\n");
 		global_disable = true;
 		spin_unlock_irqrestore(&free_entries_lock, flags);
+		pr_err("DMA-API: debugging out of memory - disabling\n");
 		return NULL;
 	}
 
diff --git a/lib/extable.c b/lib/extable.c
index 4cac81e..0be02ad 100644
--- a/lib/extable.c
+++ b/lib/extable.c
@@ -14,7 +14,37 @@
 #include <linux/sort.h>
 #include <asm/uaccess.h>
 
+#ifndef ARCH_HAS_RELATIVE_EXTABLE
+#define ex_to_insn(x)	((x)->insn)
+#else
+static inline unsigned long ex_to_insn(const struct exception_table_entry *x)
+{
+	return (unsigned long)&x->insn + x->insn;
+}
+#endif
+
 #ifndef ARCH_HAS_SORT_EXTABLE
+#ifndef ARCH_HAS_RELATIVE_EXTABLE
+#define swap_ex		NULL
+#else
+static void swap_ex(void *a, void *b, int size)
+{
+	struct exception_table_entry *x = a, *y = b, tmp;
+	int delta = b - a;
+
+	tmp = *x;
+	x->insn = y->insn + delta;
+	y->insn = tmp.insn - delta;
+
+#ifdef swap_ex_entry_fixup
+	swap_ex_entry_fixup(x, y, tmp, delta);
+#else
+	x->fixup = y->fixup + delta;
+	y->fixup = tmp.fixup - delta;
+#endif
+}
+#endif /* ARCH_HAS_RELATIVE_EXTABLE */
+
 /*
  * The exception table needs to be sorted so that the binary
  * search that we use to find entries in it works properly.
@@ -26,9 +56,9 @@
 	const struct exception_table_entry *x = a, *y = b;
 
 	/* avoid overflow */
-	if (x->insn > y->insn)
+	if (ex_to_insn(x) > ex_to_insn(y))
 		return 1;
-	if (x->insn < y->insn)
+	if (ex_to_insn(x) < ex_to_insn(y))
 		return -1;
 	return 0;
 }
@@ -37,7 +67,7 @@
 		  struct exception_table_entry *finish)
 {
 	sort(start, finish - start, sizeof(struct exception_table_entry),
-	     cmp_ex, NULL);
+	     cmp_ex, swap_ex);
 }
 
 #ifdef CONFIG_MODULES
@@ -48,13 +78,15 @@
 void trim_init_extable(struct module *m)
 {
 	/*trim the beginning*/
-	while (m->num_exentries && within_module_init(m->extable[0].insn, m)) {
+	while (m->num_exentries &&
+	       within_module_init(ex_to_insn(&m->extable[0]), m)) {
 		m->extable++;
 		m->num_exentries--;
 	}
 	/*trim the end*/
 	while (m->num_exentries &&
-		within_module_init(m->extable[m->num_exentries-1].insn, m))
+	       within_module_init(ex_to_insn(&m->extable[m->num_exentries - 1]),
+				  m))
 		m->num_exentries--;
 }
 #endif /* CONFIG_MODULES */
@@ -81,13 +113,13 @@
 		 * careful, the distance between value and insn
 		 * can be larger than MAX_LONG:
 		 */
-		if (mid->insn < value)
+		if (ex_to_insn(mid) < value)
 			first = mid + 1;
-		else if (mid->insn > value)
+		else if (ex_to_insn(mid) > value)
 			last = mid - 1;
 		else
 			return mid;
-        }
-        return NULL;
+	}
+	return NULL;
 }
 #endif
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 116a166..27aa9c6 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -273,7 +273,7 @@
 	struct gen_pool_chunk *chunk;
 	unsigned long addr = 0;
 	int order = pool->min_alloc_order;
-	int nbits, start_bit = 0, end_bit, remain;
+	int nbits, start_bit, end_bit, remain;
 
 #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
 	BUG_ON(in_nmi());
@@ -288,6 +288,7 @@
 		if (size > atomic_read(&chunk->avail))
 			continue;
 
+		start_bit = 0;
 		end_bit = chunk_size(chunk) >> order;
 retry:
 		start_bit = pool->algo(chunk->bits, end_bit, start_bit, nbits,
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 75232ad..daca582 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -298,33 +298,13 @@
 }
 
 /*
- * Fault in the first iovec of the given iov_iter, to a maximum length
- * of bytes. Returns 0 on success, or non-zero if the memory could not be
- * accessed (ie. because it is an invalid address).
- *
- * writev-intensive code may want this to prefault several iovecs -- that
- * would be possible (callers must not rely on the fact that _only_ the
- * first iovec will be faulted with the current implementation).
- */
-int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
-{
-	if (!(i->type & (ITER_BVEC|ITER_KVEC))) {
-		char __user *buf = i->iov->iov_base + i->iov_offset;
-		bytes = min(bytes, i->iov->iov_len - i->iov_offset);
-		return fault_in_pages_readable(buf, bytes);
-	}
-	return 0;
-}
-EXPORT_SYMBOL(iov_iter_fault_in_readable);
-
-/*
  * Fault in one or more iovecs of the given iov_iter, to a maximum length of
  * bytes.  For each iovec, fault in each page that constitutes the iovec.
  *
  * Return 0 on success, or non-zero if the memory could not be accessed (i.e.
  * because it is an invalid address).
  */
-int iov_iter_fault_in_multipages_readable(struct iov_iter *i, size_t bytes)
+int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
 {
 	size_t skip = i->iov_offset;
 	const struct iovec *iov;
@@ -341,7 +321,7 @@
 	}
 	return 0;
 }
-EXPORT_SYMBOL(iov_iter_fault_in_multipages_readable);
+EXPORT_SYMBOL(iov_iter_fault_in_readable);
 
 void iov_iter_init(struct iov_iter *i, int direction,
 			const struct iovec *iov, unsigned long nr_segs,
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
index 94be244..d8a5cf6 100644
--- a/lib/kstrtox.c
+++ b/lib/kstrtox.c
@@ -321,6 +321,70 @@
 }
 EXPORT_SYMBOL(kstrtos8);
 
+/**
+ * kstrtobool - convert common user inputs into boolean values
+ * @s: input string
+ * @res: result
+ *
+ * This routine returns 0 iff the first character is one of 'Yy1Nn0', or
+ * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL.  Value
+ * pointed to by res is updated upon finding a match.
+ */
+int kstrtobool(const char *s, bool *res)
+{
+	if (!s)
+		return -EINVAL;
+
+	switch (s[0]) {
+	case 'y':
+	case 'Y':
+	case '1':
+		*res = true;
+		return 0;
+	case 'n':
+	case 'N':
+	case '0':
+		*res = false;
+		return 0;
+	case 'o':
+	case 'O':
+		switch (s[1]) {
+		case 'n':
+		case 'N':
+			*res = true;
+			return 0;
+		case 'f':
+		case 'F':
+			*res = false;
+			return 0;
+		default:
+			break;
+		}
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(kstrtobool);
+
+/*
+ * Since "base" would be a nonsense argument, this open-codes the
+ * _from_user helper instead of using the helper macro below.
+ */
+int kstrtobool_from_user(const char __user *s, size_t count, bool *res)
+{
+	/* Longest string needed to differentiate, newline, terminator */
+	char buf[4];
+
+	count = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, s, count))
+		return -EFAULT;
+	buf[count] = '\0';
+	return kstrtobool(buf, res);
+}
+EXPORT_SYMBOL(kstrtobool_from_user);
+
 #define kstrto_from_user(f, g, type)					\
 int f(const char __user *s, size_t count, unsigned int base, type *res)	\
 {									\
diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c
index 5464c87..e24388a 100644
--- a/lib/mpi/mpi-pow.c
+++ b/lib/mpi/mpi-pow.c
@@ -64,8 +64,13 @@
 	if (!esize) {
 		/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
 		 * depending on if MOD equals 1.  */
-		rp[0] = 1;
 		res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1;
+		if (res->nlimbs) {
+			if (mpi_resize(res, 1) < 0)
+				goto enomem;
+			rp = res->d;
+			rp[0] = 1;
+		}
 		res->sign = 0;
 		goto leave;
 	}
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index e00ff00..e37dbf5 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -367,7 +367,9 @@
 	buf_len = sgl->length;
 	p2 = sg_virt(sgl);
 
-	for (i = a->nlimbs - 1; i >= 0; i--) {
+	for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB,
+			lzeros %= BYTES_PER_MPI_LIMB;
+		i >= 0; i--) {
 		alimb = a->d[i];
 		p = (u8 *)&alimb2;
 #if BYTES_PER_MPI_LIMB == 4
@@ -388,17 +390,12 @@
 #error please implement for this limb size.
 #endif
 		if (lzeros > 0) {
-			if (lzeros >= sizeof(alimb)) {
-				p -= sizeof(alimb);
-				continue;
-			} else {
-				mpi_limb_t *limb1 = (void *)p - sizeof(alimb);
-				mpi_limb_t *limb2 = (void *)p - sizeof(alimb)
-							+ lzeros;
-				*limb1 = *limb2;
-				p -= lzeros;
-				y = lzeros;
-			}
+			mpi_limb_t *limb1 = (void *)p - sizeof(alimb);
+			mpi_limb_t *limb2 = (void *)p - sizeof(alimb)
+				+ lzeros;
+			*limb1 = *limb2;
+			p -= lzeros;
+			y = lzeros;
 			lzeros -= sizeof(alimb);
 		}
 
diff --git a/lib/string.c b/lib/string.c
index 0323c0d..1a90db9 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -630,35 +630,6 @@
 }
 EXPORT_SYMBOL(sysfs_streq);
 
-/**
- * strtobool - convert common user inputs into boolean values
- * @s: input string
- * @res: result
- *
- * This routine returns 0 iff the first character is one of 'Yy1Nn0'.
- * Otherwise it will return -EINVAL.  Value pointed to by res is
- * updated upon finding a match.
- */
-int strtobool(const char *s, bool *res)
-{
-	switch (s[0]) {
-	case 'y':
-	case 'Y':
-	case '1':
-		*res = true;
-		break;
-	case 'n':
-	case 'N':
-	case '0':
-		*res = false;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-EXPORT_SYMBOL(strtobool);
-
 #ifndef __HAVE_ARCH_MEMSET
 /**
  * memset - Fill a region of memory with the given value
diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c
index e0af6ff..05efc1f 100644
--- a/lib/strncpy_from_user.c
+++ b/lib/strncpy_from_user.c
@@ -1,5 +1,6 @@
 #include <linux/compiler.h>
 #include <linux/export.h>
+#include <linux/thread_info.h>
 #include <linux/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -39,8 +40,8 @@
 		unsigned long c, data;
 
 		/* Fall back to byte-at-a-time if we get a page fault */
-		if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
-			break;
+		unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time);
+
 		*(unsigned long *)(dst+res) = c;
 		if (has_zero(c, &data, &constants)) {
 			data = prep_zero_mask(c, data, &constants);
@@ -55,8 +56,7 @@
 	while (max) {
 		char c;
 
-		if (unlikely(__get_user(c,src+res)))
-			return -EFAULT;
+		unsafe_get_user(c,src+res, efault);
 		dst[res] = c;
 		if (!c)
 			return res;
@@ -75,6 +75,7 @@
 	 * Nope: we hit the address space limit, and we still had more
 	 * characters the caller would have wanted. That's an EFAULT.
 	 */
+efault:
 	return -EFAULT;
 }
 
@@ -107,7 +108,13 @@
 	src_addr = (unsigned long)src;
 	if (likely(src_addr < max_addr)) {
 		unsigned long max = max_addr - src_addr;
-		return do_strncpy_from_user(dst, src, count, max);
+		long retval;
+
+		check_object_size(dst, count, false);
+		user_access_begin();
+		retval = do_strncpy_from_user(dst, src, count, max);
+		user_access_end();
+		return retval;
 	}
 	return -EFAULT;
 }
diff --git a/lib/strnlen_user.c b/lib/strnlen_user.c
index 3a5f2b3..8e105ed 100644
--- a/lib/strnlen_user.c
+++ b/lib/strnlen_user.c
@@ -45,8 +45,7 @@
 	src -= align;
 	max += align;
 
-	if (unlikely(__get_user(c,(unsigned long __user *)src)))
-		return 0;
+	unsafe_get_user(c, (unsigned long __user *)src, efault);
 	c |= aligned_byte_mask(align);
 
 	for (;;) {
@@ -61,8 +60,7 @@
 		if (unlikely(max <= sizeof(unsigned long)))
 			break;
 		max -= sizeof(unsigned long);
-		if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
-			return 0;
+		unsafe_get_user(c, (unsigned long __user *)(src+res), efault);
 	}
 	res -= align;
 
@@ -77,6 +75,7 @@
 	 * Nope: we hit the address space limit, and we still had more
 	 * characters the caller would have wanted. That's 0.
 	 */
+efault:
 	return 0;
 }
 
@@ -112,7 +111,12 @@
 	src_addr = (unsigned long)str;
 	if (likely(src_addr < max_addr)) {
 		unsigned long max = max_addr - src_addr;
-		return do_strnlen_user(str, count, max);
+		long retval;
+
+		user_access_begin();
+		retval = do_strnlen_user(str, count, max);
+		user_access_end();
+		return retval;
 	}
 	return 0;
 }
@@ -141,7 +145,12 @@
 	src_addr = (unsigned long)str;
 	if (likely(src_addr < max_addr)) {
 		unsigned long max = max_addr - src_addr;
-		return do_strnlen_user(str, ~0ul, max);
+		long retval;
+
+		user_access_begin();
+		retval = do_strnlen_user(str, ~0ul, max);
+		user_access_end();
+		return retval;
 	}
 	return 0;
 }
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 76f29ec..771234d 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -452,11 +452,11 @@
 		    : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
 
 	/*
-	 * For mappings greater than a page, we limit the stride (and
-	 * hence alignment) to a page size.
+	 * For mappings greater than or equal to a page, we limit the stride
+	 * (and hence alignment) to a page size.
 	 */
 	nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
-	if (size > PAGE_SIZE)
+	if (size >= PAGE_SIZE)
 		stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
 	else
 		stride = 1;
diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 10cd186..7e26aea 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -4315,6 +4315,51 @@
 		{ },
 		{ { 0, 1 } },
 	},
+	{
+		/* Mainly testing JIT + imm64 here. */
+		"JMP_JGE_X: ldimm64 test 1",
+		.u.insns_int = {
+			BPF_ALU32_IMM(BPF_MOV, R0, 0),
+			BPF_LD_IMM64(R1, 3),
+			BPF_LD_IMM64(R2, 2),
+			BPF_JMP_REG(BPF_JGE, R1, R2, 2),
+			BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
+			BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
+			BPF_EXIT_INSN(),
+		},
+		INTERNAL,
+		{ },
+		{ { 0, 0xeeeeeeeeU } },
+	},
+	{
+		"JMP_JGE_X: ldimm64 test 2",
+		.u.insns_int = {
+			BPF_ALU32_IMM(BPF_MOV, R0, 0),
+			BPF_LD_IMM64(R1, 3),
+			BPF_LD_IMM64(R2, 2),
+			BPF_JMP_REG(BPF_JGE, R1, R2, 0),
+			BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
+			BPF_EXIT_INSN(),
+		},
+		INTERNAL,
+		{ },
+		{ { 0, 0xffffffffU } },
+	},
+	{
+		"JMP_JGE_X: ldimm64 test 3",
+		.u.insns_int = {
+			BPF_ALU32_IMM(BPF_MOV, R0, 1),
+			BPF_LD_IMM64(R1, 3),
+			BPF_LD_IMM64(R2, 2),
+			BPF_JMP_REG(BPF_JGE, R1, R2, 4),
+			BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
+			BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
+			BPF_EXIT_INSN(),
+		},
+		INTERNAL,
+		{ },
+		{ { 0, 1 } },
+	},
 	/* BPF_JMP | BPF_JNE | BPF_X */
 	{
 		"JMP_JNE_X: if (3 != 2) return 1",
diff --git a/lib/test_user_copy.c b/lib/test_user_copy.c
index 0ecef3e..5e6db6b 100644
--- a/lib/test_user_copy.c
+++ b/lib/test_user_copy.c
@@ -58,7 +58,9 @@
 	usermem = (char __user *)user_addr;
 	bad_usermem = (char *)user_addr;
 
-	/* Legitimate usage: none of these should fail. */
+	/*
+	 * Legitimate usage: none of these copies should fail.
+	 */
 	ret |= test(copy_from_user(kmem, usermem, PAGE_SIZE),
 		    "legitimate copy_from_user failed");
 	ret |= test(copy_to_user(usermem, kmem, PAGE_SIZE),
@@ -68,19 +70,33 @@
 	ret |= test(put_user(value, (unsigned long __user *)usermem),
 		    "legitimate put_user failed");
 
-	/* Invalid usage: none of these should succeed. */
+	/*
+	 * Invalid usage: none of these copies should succeed.
+	 */
+
+	/* Reject kernel-to-kernel copies through copy_from_user(). */
 	ret |= test(!copy_from_user(kmem, (char __user *)(kmem + PAGE_SIZE),
 				    PAGE_SIZE),
 		    "illegal all-kernel copy_from_user passed");
+
+#if 0
+	/*
+	 * When running with SMAP/PAN/etc, this will Oops the kernel
+	 * due to the zeroing of userspace memory on failure. This needs
+	 * to be tested in LKDTM instead, since this test module does not
+	 * expect to explode.
+	 */
 	ret |= test(!copy_from_user(bad_usermem, (char __user *)kmem,
 				    PAGE_SIZE),
 		    "illegal reversed copy_from_user passed");
+#endif
 	ret |= test(!copy_to_user((char __user *)kmem, kmem + PAGE_SIZE,
 				  PAGE_SIZE),
 		    "illegal all-kernel copy_to_user passed");
 	ret |= test(!copy_to_user((char __user *)kmem, bad_usermem,
 				  PAGE_SIZE),
 		    "illegal reversed copy_to_user passed");
+
 	ret |= test(!get_user(value, (unsigned long __user *)kmem),
 		    "illegal get_user passed");
 	ret |= test(!put_user(value, (unsigned long __user *)kmem),
diff --git a/mm/Makefile b/mm/Makefile
index 2ed4319..8b532c9 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -5,6 +5,9 @@
 KASAN_SANITIZE_slab_common.o := n
 KASAN_SANITIZE_slub.o := n
 
+# Since __builtin_frame_address does work as used, disable the warning.
+CFLAGS_usercopy.o += $(call cc-disable-warning, frame-address)
+
 mmu-y			:= nommu.o
 mmu-$(CONFIG_MMU)	:= gup.o highmem.o memory.o mincore.o \
 			   mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
@@ -81,3 +84,4 @@
 obj-$(CONFIG_USERFAULTFD) += userfaultfd.o
 obj-$(CONFIG_IDLE_PAGE_TRACKING) += page_idle.o
 obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o
+obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index cbe6f0b..a988d4e 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -757,15 +757,20 @@
 	if (!bdi->wb_congested)
 		return -ENOMEM;
 
+	atomic_set(&bdi->wb_congested->refcnt, 1);
+
 	err = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
 	if (err) {
-		kfree(bdi->wb_congested);
+		wb_congested_put(bdi->wb_congested);
 		return err;
 	}
 	return 0;
 }
 
-static void cgwb_bdi_destroy(struct backing_dev_info *bdi) { }
+static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
+{
+	wb_congested_put(bdi->wb_congested);
+}
 
 #endif	/* CONFIG_CGROUP_WRITEBACK */
 
@@ -825,6 +830,20 @@
 }
 EXPORT_SYMBOL(bdi_register_dev);
 
+int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner)
+{
+	int rc;
+
+	rc = bdi_register(bdi, NULL, "%u:%u", MAJOR(owner->devt),
+			MINOR(owner->devt));
+	if (rc)
+		return rc;
+	bdi->owner = owner;
+	get_device(owner);
+	return 0;
+}
+EXPORT_SYMBOL(bdi_register_owner);
+
 /*
  * Remove bdi from bdi_list, and ensure that it is no longer visible
  */
@@ -849,6 +868,11 @@
 		device_unregister(bdi->dev);
 		bdi->dev = NULL;
 	}
+
+	if (bdi->owner) {
+		put_device(bdi->owner);
+		bdi->owner = NULL;
+	}
 }
 
 void bdi_exit(struct backing_dev_info *bdi)
diff --git a/mm/cma.c b/mm/cma.c
index ea506eb..bd0e141 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -183,7 +183,8 @@
 		return -EINVAL;
 
 	/* ensure minimal alignment required by mm core */
-	alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
+	alignment = PAGE_SIZE <<
+			max_t(unsigned long, MAX_ORDER - 1, pageblock_order);
 
 	/* alignment should be aligned with order_per_bit */
 	if (!IS_ALIGNED(alignment >> PAGE_SHIFT, 1 << order_per_bit))
@@ -266,8 +267,8 @@
 	 * migratetype page by page allocator's buddy algorithm. In the case,
 	 * you couldn't get a contiguous memory, which is not what we want.
 	 */
-	alignment = max(alignment,
-		(phys_addr_t)PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order));
+	alignment = max(alignment,  (phys_addr_t)PAGE_SIZE <<
+			  max_t(unsigned long, MAX_ORDER - 1, pageblock_order));
 	base = ALIGN(base, alignment);
 	size = ALIGN(size, alignment);
 	limit &= ~(alignment - 1);
diff --git a/mm/compaction.c b/mm/compaction.c
index 7881e07..dba02de 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -475,25 +475,23 @@
 
 		/* Found a free page, break it into order-0 pages */
 		isolated = split_free_page(page);
+		if (!isolated)
+			break;
+
 		total_isolated += isolated;
+		cc->nr_freepages += isolated;
 		for (i = 0; i < isolated; i++) {
 			list_add(&page->lru, freelist);
 			page++;
 		}
-
-		/* If a page was split, advance to the end of it */
-		if (isolated) {
-			cc->nr_freepages += isolated;
-			if (!strict &&
-				cc->nr_migratepages <= cc->nr_freepages) {
-				blockpfn += isolated;
-				break;
-			}
-
-			blockpfn += isolated - 1;
-			cursor += isolated - 1;
-			continue;
+		if (!strict && cc->nr_migratepages <= cc->nr_freepages) {
+			blockpfn += isolated;
+			break;
 		}
+		/* Advance to the end of split page */
+		blockpfn += isolated - 1;
+		cursor += isolated - 1;
+		continue;
 
 isolate_fail:
 		if (strict)
@@ -503,6 +501,9 @@
 
 	}
 
+	if (locked)
+		spin_unlock_irqrestore(&cc->zone->lock, flags);
+
 	/*
 	 * There is a tiny chance that we have read bogus compound_order(),
 	 * so be careful to not go outside of the pageblock.
@@ -524,9 +525,6 @@
 	if (strict && blockpfn < end_pfn)
 		total_isolated = 0;
 
-	if (locked)
-		spin_unlock_irqrestore(&cc->zone->lock, flags);
-
 	/* Update the pageblock-skip if the whole pageblock was scanned */
 	if (blockpfn == end_pfn)
 		update_pageblock_skip(cc, valid_page, total_isolated, false);
@@ -966,7 +964,6 @@
 				block_end_pfn = block_start_pfn,
 				block_start_pfn -= pageblock_nr_pages,
 				isolate_start_pfn = block_start_pfn) {
-
 		/*
 		 * This can iterate a massively long zone without finding any
 		 * suitable migration targets, so periodically check if we need
@@ -990,32 +987,30 @@
 			continue;
 
 		/* Found a block suitable for isolating free pages from. */
-		isolate_freepages_block(cc, &isolate_start_pfn,
-					block_end_pfn, freelist, false);
+		isolate_freepages_block(cc, &isolate_start_pfn, block_end_pfn,
+					freelist, false);
 
 		/*
-		 * If we isolated enough freepages, or aborted due to async
-		 * compaction being contended, terminate the loop.
-		 * Remember where the free scanner should restart next time,
-		 * which is where isolate_freepages_block() left off.
-		 * But if it scanned the whole pageblock, isolate_start_pfn
-		 * now points at block_end_pfn, which is the start of the next
-		 * pageblock.
-		 * In that case we will however want to restart at the start
-		 * of the previous pageblock.
+		 * If we isolated enough freepages, or aborted due to lock
+		 * contention, terminate.
 		 */
 		if ((cc->nr_freepages >= cc->nr_migratepages)
 							|| cc->contended) {
-			if (isolate_start_pfn >= block_end_pfn)
+			if (isolate_start_pfn >= block_end_pfn) {
+				/*
+				 * Restart at previous pageblock if more
+				 * freepages can be isolated next time.
+				 */
 				isolate_start_pfn =
 					block_start_pfn - pageblock_nr_pages;
+			}
 			break;
-		} else {
+		} else if (isolate_start_pfn < block_end_pfn) {
 			/*
-			 * isolate_freepages_block() should not terminate
-			 * prematurely unless contended, or isolated enough
+			 * If isolation failed early, do not continue
+			 * needlessly.
 			 */
-			VM_BUG_ON(isolate_start_pfn < block_end_pfn);
+			break;
 		}
 	}
 
diff --git a/mm/filemap.c b/mm/filemap.c
index 1bb0076..69f75c7 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -109,6 +109,48 @@
  *   ->tasklist_lock            (memory_failure, collect_procs_ao)
  */
 
+static int page_cache_tree_insert(struct address_space *mapping,
+				  struct page *page, void **shadowp)
+{
+	struct radix_tree_node *node;
+	void **slot;
+	int error;
+
+	error = __radix_tree_create(&mapping->page_tree, page->index,
+				    &node, &slot);
+	if (error)
+		return error;
+	if (*slot) {
+		void *p;
+
+		p = radix_tree_deref_slot_protected(slot, &mapping->tree_lock);
+		if (!radix_tree_exceptional_entry(p))
+			return -EEXIST;
+		if (shadowp)
+			*shadowp = p;
+		mapping->nrshadows--;
+		if (node)
+			workingset_node_shadows_dec(node);
+	}
+	radix_tree_replace_slot(slot, page);
+	mapping->nrpages++;
+	if (node) {
+		workingset_node_pages_inc(node);
+		/*
+		 * Don't track node that contains actual pages.
+		 *
+		 * Avoid acquiring the list_lru lock if already
+		 * untracked.  The list_empty() test is safe as
+		 * node->private_list is protected by
+		 * mapping->tree_lock.
+		 */
+		if (!list_empty(&node->private_list))
+			list_lru_del(&workingset_shadow_nodes,
+				     &node->private_list);
+	}
+	return 0;
+}
+
 static void page_cache_tree_delete(struct address_space *mapping,
 				   struct page *page, void *shadow)
 {
@@ -122,6 +164,14 @@
 
 	__radix_tree_lookup(&mapping->page_tree, page->index, &node, &slot);
 
+	if (!node) {
+		/*
+		 * We need a node to properly account shadow
+		 * entries. Don't plant any without. XXX
+		 */
+		shadow = NULL;
+	}
+
 	if (shadow) {
 		mapping->nrshadows++;
 		/*
@@ -538,9 +588,8 @@
 		memcg = mem_cgroup_begin_page_stat(old);
 		spin_lock_irqsave(&mapping->tree_lock, flags);
 		__delete_from_page_cache(old, NULL, memcg);
-		error = radix_tree_insert(&mapping->page_tree, offset, new);
+		error = page_cache_tree_insert(mapping, new, NULL);
 		BUG_ON(error);
-		mapping->nrpages++;
 
 		/*
 		 * hugetlb pages do not participate in page cache accounting.
@@ -562,48 +611,6 @@
 }
 EXPORT_SYMBOL_GPL(replace_page_cache_page);
 
-static int page_cache_tree_insert(struct address_space *mapping,
-				  struct page *page, void **shadowp)
-{
-	struct radix_tree_node *node;
-	void **slot;
-	int error;
-
-	error = __radix_tree_create(&mapping->page_tree, page->index,
-				    &node, &slot);
-	if (error)
-		return error;
-	if (*slot) {
-		void *p;
-
-		p = radix_tree_deref_slot_protected(slot, &mapping->tree_lock);
-		if (!radix_tree_exceptional_entry(p))
-			return -EEXIST;
-		if (shadowp)
-			*shadowp = p;
-		mapping->nrshadows--;
-		if (node)
-			workingset_node_shadows_dec(node);
-	}
-	radix_tree_replace_slot(slot, page);
-	mapping->nrpages++;
-	if (node) {
-		workingset_node_pages_inc(node);
-		/*
-		 * Don't track node that contains actual pages.
-		 *
-		 * Avoid acquiring the list_lru lock if already
-		 * untracked.  The list_empty() test is safe as
-		 * node->private_list is protected by
-		 * mapping->tree_lock.
-		 */
-		if (!list_empty(&node->private_list))
-			list_lru_del(&workingset_shadow_nodes,
-				     &node->private_list);
-	}
-	return 0;
-}
-
 static int __add_to_page_cache_locked(struct page *page,
 				      struct address_space *mapping,
 				      pgoff_t offset, gfp_t gfp_mask,
@@ -858,9 +865,12 @@
 		unlock_page(page);
 	} else { /* rw == WRITE */
 		if (err) {
+			struct address_space *mapping;
+
 			SetPageError(page);
-			if (page->mapping)
-				mapping_set_error(page->mapping, err);
+			mapping = page_mapping(page);
+			if (mapping)
+				mapping_set_error(mapping, err);
 		}
 		end_page_writeback(page);
 	}
@@ -1552,6 +1562,11 @@
 
 		cond_resched();
 find_page:
+		if (fatal_signal_pending(current)) {
+			error = -EINTR;
+			goto out;
+		}
+
 		page = find_get_page(mapping, index);
 		if (!page) {
 			page_cache_sync_readahead(mapping,
diff --git a/mm/gup.c b/mm/gup.c
index deafa2c..b599526 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -58,6 +58,16 @@
 	return -EEXIST;
 }
 
+/*
+ * FOLL_FORCE can write to even unwritable pte's, but only
+ * after we've gone through a COW cycle and they are dirty.
+ */
+static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
+{
+	return pte_write(pte) ||
+		((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte));
+}
+
 static struct page *follow_page_pte(struct vm_area_struct *vma,
 		unsigned long address, pmd_t *pmd, unsigned int flags)
 {
@@ -92,7 +102,7 @@
 	}
 	if ((flags & FOLL_NUMA) && pte_protnone(pte))
 		goto no_page;
-	if ((flags & FOLL_WRITE) && !pte_write(pte)) {
+	if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) {
 		pte_unmap_unlock(ptep, ptl);
 		return NULL;
 	}
@@ -302,11 +312,6 @@
 	/* mlock all present pages, but do not fault in new pages */
 	if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK)
 		return -ENOENT;
-	/* For mm_populate(), just skip the stack guard page. */
-	if ((*flags & FOLL_POPULATE) &&
-			(stack_guard_page_start(vma, address) ||
-			 stack_guard_page_end(vma, address + PAGE_SIZE)))
-		return -ENOENT;
 	if (*flags & FOLL_WRITE)
 		fault_flags |= FAULT_FLAG_WRITE;
 	if (nonblocking)
@@ -352,7 +357,7 @@
 	 * reCOWed by userspace write).
 	 */
 	if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE))
-		*flags &= ~FOLL_WRITE;
+	        *flags |= FOLL_COW;
 	return 0;
 }
 
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 530e642..6c6f5cc 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1269,6 +1269,16 @@
 	return ret;
 }
 
+/*
+ * FOLL_FORCE can write to even unwritable pmd's, but only
+ * after we've gone through a COW cycle and they are dirty.
+ */
+static inline bool can_follow_write_pmd(pmd_t pmd, unsigned int flags)
+{
+	return pmd_write(pmd) ||
+	       ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pmd_dirty(pmd));
+}
+
 struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
 				   unsigned long addr,
 				   pmd_t *pmd,
@@ -1279,7 +1289,7 @@
 
 	assert_spin_locked(pmd_lockptr(mm, pmd));
 
-	if (flags & FOLL_WRITE && !pmd_write(*pmd))
+	if (flags & FOLL_WRITE && !can_follow_write_pmd(*pmd, flags))
 		goto out;
 
 	/* Avoid dumping huge zero page */
@@ -1353,8 +1363,11 @@
 	 */
 	if (unlikely(pmd_trans_migrating(*pmdp))) {
 		page = pmd_page(*pmdp);
+		if (!get_page_unless_zero(page))
+			goto out_unlock;
 		spin_unlock(ptl);
 		wait_on_page_locked(page);
+		put_page(page);
 		goto out;
 	}
 
@@ -1386,8 +1399,11 @@
 
 	/* Migration could have started since the pmd_trans_migrating check */
 	if (!page_locked) {
+		if (!get_page_unless_zero(page))
+			goto out_unlock;
 		spin_unlock(ptl);
 		wait_on_page_locked(page);
+		put_page(page);
 		page_nid = -1;
 		goto out;
 	}
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ef6963b..7294301 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1416,12 +1416,13 @@
 {
 	spin_lock(&hugetlb_lock);
 	if (PageHuge(page) && !page_count(page)) {
-		struct hstate *h = page_hstate(page);
-		int nid = page_to_nid(page);
-		list_del(&page->lru);
+		struct page *head = compound_head(page);
+		struct hstate *h = page_hstate(head);
+		int nid = page_to_nid(head);
+		list_del(&head->lru);
 		h->free_huge_pages--;
 		h->free_huge_pages_node[nid]--;
-		update_and_free_page(h, page);
+		update_and_free_page(h, head);
 	}
 	spin_unlock(&hugetlb_lock);
 }
@@ -1429,7 +1430,8 @@
 /*
  * Dissolve free hugepages in a given pfn range. Used by memory hotplug to
  * make specified memory blocks removable from the system.
- * Note that start_pfn should aligned with (minimum) hugepage size.
+ * Note that this will dissolve a free gigantic hugepage completely, if any
+ * part of it lies within the given range.
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
@@ -1438,7 +1440,6 @@
 	if (!hugepages_supported())
 		return;
 
-	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << minimum_order));
 	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order)
 		dissolve_free_huge_page(pfn_to_page(pfn));
 }
@@ -1722,23 +1723,32 @@
 }
 
 /*
- * When releasing a hugetlb pool reservation, any surplus pages that were
- * allocated to satisfy the reservation must be explicitly freed if they were
- * never used.
- * Called with hugetlb_lock held.
+ * This routine has two main purposes:
+ * 1) Decrement the reservation count (resv_huge_pages) by the value passed
+ *    in unused_resv_pages.  This corresponds to the prior adjustments made
+ *    to the associated reservation map.
+ * 2) Free any unused surplus pages that may have been allocated to satisfy
+ *    the reservation.  As many as unused_resv_pages may be freed.
+ *
+ * Called with hugetlb_lock held.  However, the lock could be dropped (and
+ * reacquired) during calls to cond_resched_lock.  Whenever dropping the lock,
+ * we must make sure nobody else can claim pages we are in the process of
+ * freeing.  Do this by ensuring resv_huge_page always is greater than the
+ * number of huge pages we plan to free when dropping the lock.
  */
 static void return_unused_surplus_pages(struct hstate *h,
 					unsigned long unused_resv_pages)
 {
 	unsigned long nr_pages;
 
-	/* Uncommit the reservation */
-	h->resv_huge_pages -= unused_resv_pages;
-
 	/* Cannot return gigantic pages currently */
 	if (hstate_is_gigantic(h))
-		return;
+		goto out;
 
+	/*
+	 * Part (or even all) of the reservation could have been backed
+	 * by pre-allocated pages. Only free surplus pages.
+	 */
 	nr_pages = min(unused_resv_pages, h->surplus_huge_pages);
 
 	/*
@@ -1748,12 +1758,22 @@
 	 * when the nodes with surplus pages have no free pages.
 	 * free_pool_huge_page() will balance the the freed pages across the
 	 * on-line nodes with memory and will handle the hstate accounting.
+	 *
+	 * Note that we decrement resv_huge_pages as we free the pages.  If
+	 * we drop the lock, resv_huge_pages will still be sufficiently large
+	 * to cover subsequent pages we may free.
 	 */
 	while (nr_pages--) {
+		h->resv_huge_pages--;
+		unused_resv_pages--;
 		if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1))
-			break;
+			goto out;
 		cond_resched_lock(&hugetlb_lock);
 	}
+
+out:
+	/* Fully uncommit the reservation */
+	h->resv_huge_pages -= unused_resv_pages;
 }
 
 
@@ -2170,6 +2190,10 @@
 		 * and reducing the surplus.
 		 */
 		spin_unlock(&hugetlb_lock);
+
+		/* yield cpu to avoid soft lockup */
+		cond_resched();
+
 		if (hstate_is_gigantic(h))
 			ret = alloc_fresh_gigantic_page(h, nodes_allowed);
 		else
@@ -4209,7 +4233,6 @@
 		if (saddr) {
 			spte = huge_pte_offset(svma->vm_mm, saddr);
 			if (spte) {
-				mm_inc_nr_pmds(mm);
 				get_page(virt_to_page(spte));
 				break;
 			}
@@ -4224,9 +4247,9 @@
 	if (pud_none(*pud)) {
 		pud_populate(mm, pud,
 				(pmd_t *)((unsigned long)spte & PAGE_MASK));
+		mm_inc_nr_pmds(mm);
 	} else {
 		put_page(virt_to_page(spte));
-		mm_inc_nr_pmds(mm);
 	}
 	spin_unlock(ptl);
 out:
@@ -4339,6 +4362,7 @@
 {
 	struct page *page = NULL;
 	spinlock_t *ptl;
+	pte_t pte;
 retry:
 	ptl = pmd_lockptr(mm, pmd);
 	spin_lock(ptl);
@@ -4348,12 +4372,13 @@
 	 */
 	if (!pmd_huge(*pmd))
 		goto out;
-	if (pmd_present(*pmd)) {
+	pte = huge_ptep_get((pte_t *)pmd);
+	if (pte_present(pte)) {
 		page = pmd_page(*pmd) + ((address & ~PMD_MASK) >> PAGE_SHIFT);
 		if (flags & FOLL_GET)
 			get_page(page);
 	} else {
-		if (is_hugetlb_entry_migration(huge_ptep_get((pte_t *)pmd))) {
+		if (is_hugetlb_entry_migration(pte)) {
 			spin_unlock(ptl);
 			__migration_entry_wait(mm, (pte_t *)pmd, ptl);
 			goto retry;
diff --git a/mm/init-mm.c b/mm/init-mm.c
index a56a851..975e49f 100644
--- a/mm/init-mm.c
+++ b/mm/init-mm.c
@@ -6,6 +6,7 @@
 #include <linux/cpumask.h>
 
 #include <linux/atomic.h>
+#include <linux/user_namespace.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 
@@ -21,5 +22,6 @@
 	.mmap_sem	= __RWSEM_INITIALIZER(init_mm.mmap_sem),
 	.page_table_lock =  __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
 	.mmlist		= LIST_HEAD_INIT(init_mm.mmlist),
+	.user_ns	= &init_user_ns,
 	INIT_MM_CONTEXT(init_mm)
 };
diff --git a/mm/internal.h b/mm/internal.h
index 38e24b8..6979b2b 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -22,7 +22,8 @@
  */
 #define GFP_RECLAIM_MASK (__GFP_RECLAIM|__GFP_HIGH|__GFP_IO|__GFP_FS|\
 			__GFP_NOWARN|__GFP_REPEAT|__GFP_NOFAIL|\
-			__GFP_NORETRY|__GFP_MEMALLOC|__GFP_NOMEMALLOC)
+			__GFP_NORETRY|__GFP_MEMALLOC|__GFP_NOMEMALLOC|\
+			__GFP_ATOMIC)
 
 /* The GFP flags allowed during early boot */
 #define GFP_BOOT_MASK (__GFP_BITS_MASK & ~(__GFP_RECLAIM|__GFP_IO|__GFP_FS))
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 4f6c62e..37ff0ab 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -52,6 +52,9 @@
 #if KASAN_ABI_VERSION >= 4
 	struct kasan_source_location *location;
 #endif
+#if KASAN_ABI_VERSION >= 5
+	char *odr_indicator;
+#endif
 };
 
 static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 12f222d..b4e31f7 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/ftrace.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/printk.h>
@@ -251,6 +252,8 @@
 	if (likely(!kasan_report_enabled()))
 		return;
 
+	disable_trace_on_warning();
+
 	info.access_addr = (void *)addr;
 	info.access_size = size;
 	info.is_write = is_write;
diff --git a/mm/ksm.c b/mm/ksm.c
index b5cd647..2f028e6 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -283,7 +283,8 @@
 {
 	struct rmap_item *rmap_item;
 
-	rmap_item = kmem_cache_zalloc(rmap_item_cache, GFP_KERNEL);
+	rmap_item = kmem_cache_zalloc(rmap_item_cache, GFP_KERNEL |
+						__GFP_NORETRY | __GFP_NOWARN);
 	if (rmap_item)
 		ksm_rmap_items++;
 	return rmap_item;
diff --git a/mm/list_lru.c b/mm/list_lru.c
index afc71ea..5d8dffd 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -554,6 +554,8 @@
 	err = memcg_init_list_lru(lru, memcg_aware);
 	if (err) {
 		kfree(lru->node);
+		/* Do this so a list_lru_destroy() doesn't crash: */
+		lru->node = NULL;
 		goto out;
 	}
 
diff --git a/mm/memblock.c b/mm/memblock.c
index d300f13..fc9671d 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -822,6 +822,17 @@
 	return memblock_setclr_flag(base, size, 1, MEMBLOCK_MIRROR);
 }
 
+/**
+ * memblock_mark_nomap - Mark a memory region with flag MEMBLOCK_NOMAP.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
+{
+	return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP);
+}
 
 /**
  * __next_reserved_mem_region - next function for for_each_reserved_region()
@@ -913,6 +924,10 @@
 		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
 			continue;
 
+		/* skip nomap memory unless we were asked for it explicitly */
+		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
+			continue;
+
 		if (!type_b) {
 			if (out_start)
 				*out_start = m_start;
@@ -1022,6 +1037,10 @@
 		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
 			continue;
 
+		/* skip nomap memory unless we were asked for it explicitly */
+		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
+			continue;
+
 		if (!type_b) {
 			if (out_start)
 				*out_start = m_start;
@@ -1519,6 +1538,15 @@
 	return memblock_search(&memblock.memory, addr) != -1;
 }
 
+int __init_memblock memblock_is_map_memory(phys_addr_t addr)
+{
+	int i = memblock_search(&memblock.memory, addr);
+
+	if (i == -1)
+		return false;
+	return !memblock_is_nomap(&memblock.memory.regions[i]);
+}
+
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
 			 unsigned long *start_pfn, unsigned long *end_pfn)
@@ -1634,6 +1662,30 @@
 	}
 }
 
+extern unsigned long __init_memblock
+memblock_reserved_memory_within(phys_addr_t start_addr, phys_addr_t end_addr)
+{
+	struct memblock_type *type = &memblock.reserved;
+	unsigned long size = 0;
+	int idx;
+
+	for (idx = 0; idx < type->cnt; idx++) {
+		struct memblock_region *rgn = &type->regions[idx];
+		phys_addr_t start, end;
+
+		if (rgn->base + rgn->size < start_addr)
+			continue;
+		if (rgn->base > end_addr)
+			continue;
+
+		start = rgn->base;
+		end = start + rgn->size;
+		size += end - start;
+	}
+
+	return size;
+}
+
 void __init_memblock __memblock_dump_all(void)
 {
 	pr_info("MEMBLOCK configuration:\n");
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index b7d8315..e25b93a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -272,21 +272,7 @@
 
 static inline unsigned short mem_cgroup_id(struct mem_cgroup *memcg)
 {
-	return memcg->css.id;
-}
-
-/*
- * A helper function to get mem_cgroup from ID. must be called under
- * rcu_read_lock().  The caller is responsible for calling
- * css_tryget_online() if the mem_cgroup is used for charging. (dropping
- * refcnt from swap can be called against removed memcg.)
- */
-static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
-{
-	struct cgroup_subsys_state *css;
-
-	css = css_from_id(id, &memory_cgrp_subsys);
-	return mem_cgroup_from_css(css);
+	return memcg->id.id;
 }
 
 /* Writing them here to avoid exposing memcg's inner layout */
@@ -2069,6 +2055,15 @@
 		     current->flags & PF_EXITING))
 		goto force;
 
+	/*
+	 * Prevent unbounded recursion when reclaim operations need to
+	 * allocate memory. This might exceed the limits temporarily,
+	 * but we prefer facilitating memory reclaim and getting back
+	 * under the limit over triggering OOM kills in these cases.
+	 */
+	if (unlikely(current->flags & PF_MEMALLOC))
+		goto force;
+
 	if (unlikely(task_in_memcg_oom(current)))
 		goto nomem;
 
@@ -3661,6 +3656,7 @@
 	 * ordering is imposed by list_lru_node->lock taken by
 	 * memcg_drain_all_list_lrus().
 	 */
+	rcu_read_lock(); /* can be called from css_free w/o cgroup_mutex */
 	css_for_each_descendant_pre(css, &memcg->css) {
 		child = mem_cgroup_from_css(css);
 		BUG_ON(child->kmemcg_id != kmemcg_id);
@@ -3668,6 +3664,8 @@
 		if (!memcg->use_hierarchy)
 			break;
 	}
+	rcu_read_unlock();
+
 	memcg_drain_all_list_lrus(kmemcg_id, parent->kmemcg_id);
 
 	memcg_free_cache_id(kmemcg_id);
@@ -4121,6 +4119,70 @@
 	{ },	/* terminate */
 };
 
+/*
+ * Private memory cgroup IDR
+ *
+ * Swap-out records and page cache shadow entries need to store memcg
+ * references in constrained space, so we maintain an ID space that is
+ * limited to 16 bit (MEM_CGROUP_ID_MAX), limiting the total number of
+ * memory-controlled cgroups to 64k.
+ *
+ * However, there usually are many references to the oflline CSS after
+ * the cgroup has been destroyed, such as page cache or reclaimable
+ * slab objects, that don't need to hang on to the ID. We want to keep
+ * those dead CSS from occupying IDs, or we might quickly exhaust the
+ * relatively small ID space and prevent the creation of new cgroups
+ * even when there are much fewer than 64k cgroups - possibly none.
+ *
+ * Maintain a private 16-bit ID space for memcg, and allow the ID to
+ * be freed and recycled when it's no longer needed, which is usually
+ * when the CSS is offlined.
+ *
+ * The only exception to that are records of swapped out tmpfs/shmem
+ * pages that need to be attributed to live ancestors on swapin. But
+ * those references are manageable from userspace.
+ */
+
+static DEFINE_IDR(mem_cgroup_idr);
+
+static void mem_cgroup_id_get_many(struct mem_cgroup *memcg, unsigned int n)
+{
+	atomic_add(n, &memcg->id.ref);
+}
+
+static void mem_cgroup_id_put_many(struct mem_cgroup *memcg, unsigned int n)
+{
+	if (atomic_sub_and_test(n, &memcg->id.ref)) {
+		idr_remove(&mem_cgroup_idr, memcg->id.id);
+		memcg->id.id = 0;
+
+		/* Memcg ID pins CSS */
+		css_put(&memcg->css);
+	}
+}
+
+static inline void mem_cgroup_id_get(struct mem_cgroup *memcg)
+{
+	mem_cgroup_id_get_many(memcg, 1);
+}
+
+static inline void mem_cgroup_id_put(struct mem_cgroup *memcg)
+{
+	mem_cgroup_id_put_many(memcg, 1);
+}
+
+/**
+ * mem_cgroup_from_id - look up a memcg from a memcg id
+ * @id: the memcg id to look up
+ *
+ * Caller must hold rcu_read_lock().
+ */
+struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
+{
+	WARN_ON_ONCE(!rcu_read_lock_held());
+	return idr_find(&mem_cgroup_idr, id);
+}
+
 static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 {
 	struct mem_cgroup_per_node *pn;
@@ -4175,6 +4237,12 @@
 	if (memcg_wb_domain_init(memcg, GFP_KERNEL))
 		goto out_free_stat;
 
+	memcg->id.id = idr_alloc(&mem_cgroup_idr, NULL,
+				 1, MEM_CGROUP_ID_MAX,
+				 GFP_KERNEL);
+	if (memcg->id.id < 0)
+		goto out_free_stat;
+
 	return memcg;
 
 out_free_stat:
@@ -4260,9 +4328,11 @@
 #ifdef CONFIG_CGROUP_WRITEBACK
 	INIT_LIST_HEAD(&memcg->cgwb_list);
 #endif
+	idr_replace(&mem_cgroup_idr, memcg, memcg->id.id);
 	return &memcg->css;
 
 free_out:
+	idr_remove(&mem_cgroup_idr, memcg->id.id);
 	__mem_cgroup_free(memcg);
 	return ERR_PTR(error);
 }
@@ -4274,8 +4344,9 @@
 	struct mem_cgroup *parent = mem_cgroup_from_css(css->parent);
 	int ret;
 
-	if (css->id > MEM_CGROUP_ID_MAX)
-		return -ENOSPC;
+	/* Online state pins memcg ID, memcg ID pins CSS */
+	mem_cgroup_id_get(mem_cgroup_from_css(css));
+	css_get(css);
 
 	if (!parent)
 		return 0;
@@ -4349,6 +4420,8 @@
 	memcg_deactivate_kmem(memcg);
 
 	wb_memcg_offline(memcg);
+
+	mem_cgroup_id_put(memcg);
 }
 
 static void mem_cgroup_css_released(struct cgroup_subsys_state *css)
@@ -4405,9 +4478,9 @@
 		return ret;
 	}
 
-	/* Try charges one by one with reclaim */
+	/* Try charges one by one with reclaim, but do not retry */
 	while (count--) {
-		ret = try_charge(mc.to, GFP_KERNEL & ~__GFP_NORETRY, 1);
+		ret = try_charge(mc.to, GFP_KERNEL | __GFP_NORETRY, 1);
 		if (ret)
 			return ret;
 		mc.precharge++;
@@ -4782,6 +4855,8 @@
 		if (!mem_cgroup_is_root(mc.from))
 			page_counter_uncharge(&mc.from->memsw, mc.moved_swap);
 
+		mem_cgroup_id_put_many(mc.from, mc.moved_swap);
+
 		/*
 		 * we charged both to->memory and to->memsw, so we
 		 * should uncharge to->memory.
@@ -4789,9 +4864,9 @@
 		if (!mem_cgroup_is_root(mc.to))
 			page_counter_uncharge(&mc.to->memory, mc.moved_swap);
 
-		css_put_many(&mc.from->css, mc.moved_swap);
+		mem_cgroup_id_get_many(mc.to, mc.moved_swap);
+		css_put_many(&mc.to->css, mc.moved_swap);
 
-		/* we've already done css_get(mc.to) */
 		mc.moved_swap = 0;
 	}
 	memcg_oom_recover(from);
@@ -4888,11 +4963,6 @@
 	return ret;
 }
 
-static int mem_cgroup_allow_attach(struct cgroup_taskset *tset)
-{
-	return subsys_cgroup_allow_attach(tset);
-}
-
 static void mem_cgroup_cancel_attach(struct cgroup_taskset *tset)
 {
 	if (mc.to)
@@ -5047,10 +5117,6 @@
 {
 	return 0;
 }
-static int mem_cgroup_allow_attach(struct cgroup_taskset *tset)
-{
-	return 0;
-}
 static void mem_cgroup_cancel_attach(struct cgroup_taskset *tset)
 {
 }
@@ -5269,7 +5335,6 @@
 	.can_attach = mem_cgroup_can_attach,
 	.cancel_attach = mem_cgroup_cancel_attach,
 	.post_attach = mem_cgroup_move_task,
-	.allow_attach = mem_cgroup_allow_attach,
 	.bind = mem_cgroup_bind,
 	.dfl_cftypes = memory_files,
 	.legacy_cftypes = mem_cgroup_legacy_files,
@@ -5668,6 +5733,24 @@
 subsys_initcall(mem_cgroup_init);
 
 #ifdef CONFIG_MEMCG_SWAP
+static struct mem_cgroup *mem_cgroup_id_get_online(struct mem_cgroup *memcg)
+{
+	while (!atomic_inc_not_zero(&memcg->id.ref)) {
+		/*
+		 * The root cgroup cannot be destroyed, so it's refcount must
+		 * always be >= 1.
+		 */
+		if (WARN_ON_ONCE(memcg == root_mem_cgroup)) {
+			VM_BUG_ON(1);
+			break;
+		}
+		memcg = parent_mem_cgroup(memcg);
+		if (!memcg)
+			memcg = root_mem_cgroup;
+	}
+	return memcg;
+}
+
 /**
  * mem_cgroup_swapout - transfer a memsw charge to swap
  * @page: page whose memsw charge to transfer
@@ -5677,7 +5760,7 @@
  */
 void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
 {
-	struct mem_cgroup *memcg;
+	struct mem_cgroup *memcg, *swap_memcg;
 	unsigned short oldid;
 
 	VM_BUG_ON_PAGE(PageLRU(page), page);
@@ -5692,15 +5775,27 @@
 	if (!memcg)
 		return;
 
-	oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg));
+	/*
+	 * In case the memcg owning these pages has been offlined and doesn't
+	 * have an ID allocated to it anymore, charge the closest online
+	 * ancestor for the swap instead and transfer the memory+swap charge.
+	 */
+	swap_memcg = mem_cgroup_id_get_online(memcg);
+	oldid = swap_cgroup_record(entry, mem_cgroup_id(swap_memcg));
 	VM_BUG_ON_PAGE(oldid, page);
-	mem_cgroup_swap_statistics(memcg, true);
+	mem_cgroup_swap_statistics(swap_memcg, true);
 
 	page->mem_cgroup = NULL;
 
 	if (!mem_cgroup_is_root(memcg))
 		page_counter_uncharge(&memcg->memory, 1);
 
+	if (memcg != swap_memcg) {
+		if (!mem_cgroup_is_root(swap_memcg))
+			page_counter_charge(&swap_memcg->memsw, 1);
+		page_counter_uncharge(&memcg->memsw, 1);
+	}
+
 	/*
 	 * Interrupts should be disabled here because the caller holds the
 	 * mapping->tree_lock lock which is taken with interrupts-off. It is
@@ -5710,6 +5805,9 @@
 	VM_BUG_ON(!irqs_disabled());
 	mem_cgroup_charge_statistics(memcg, page, -1);
 	memcg_check_events(memcg, page);
+
+	if (!mem_cgroup_is_root(memcg))
+		css_put(&memcg->css);
 }
 
 /**
@@ -5733,7 +5831,7 @@
 		if (!mem_cgroup_is_root(memcg))
 			page_counter_uncharge(&memcg->memsw, 1);
 		mem_cgroup_swap_statistics(memcg, false);
-		css_put(&memcg->css);
+		mem_cgroup_id_put(memcg);
 	}
 	rcu_read_unlock();
 }
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 750b789..091fe9b 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1208,7 +1208,10 @@
 	 * page_remove_rmap() in try_to_unmap_one(). So to determine page status
 	 * correctly, we save a copy of the page flags at this time.
 	 */
-	page_flags = p->flags;
+	if (PageHuge(p))
+		page_flags = hpage->flags;
+	else
+		page_flags = p->flags;
 
 	/*
 	 * unpoison always clear PG_hwpoison inside page lock
@@ -1619,12 +1622,8 @@
 	if (ret) {
 		pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
 			pfn, ret, page->flags);
-		/*
-		 * We know that soft_offline_huge_page() tries to migrate
-		 * only one hugepage pointed to by hpage, so we need not
-		 * run through the pagelist here.
-		 */
-		putback_active_hugepage(hpage);
+		if (!list_empty(&pagelist))
+			putback_movable_pages(&pagelist);
 		if (ret > 0)
 			ret = -EIO;
 	} else {
diff --git a/mm/memory.c b/mm/memory.c
index 76dcee3..e6fa134 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2662,40 +2662,6 @@
 }
 
 /*
- * This is like a special single-page "expand_{down|up}wards()",
- * except we must first make sure that 'address{-|+}PAGE_SIZE'
- * doesn't hit another vma.
- */
-static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address)
-{
-	address &= PAGE_MASK;
-	if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) {
-		struct vm_area_struct *prev = vma->vm_prev;
-
-		/*
-		 * Is there a mapping abutting this one below?
-		 *
-		 * That's only ok if it's the same stack mapping
-		 * that has gotten split..
-		 */
-		if (prev && prev->vm_end == address)
-			return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM;
-
-		return expand_downwards(vma, address - PAGE_SIZE);
-	}
-	if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
-		struct vm_area_struct *next = vma->vm_next;
-
-		/* As VM_GROWSDOWN but s/below/above/ */
-		if (next && next->vm_start == address + PAGE_SIZE)
-			return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
-
-		return expand_upwards(vma, address + PAGE_SIZE);
-	}
-	return 0;
-}
-
-/*
  * We enter with non-exclusive mmap_sem (to exclude vma changes,
  * but allow concurrent faults), and pte mapped but not yet locked.
  * We return with mmap_sem still held, but pte unmapped and unlocked.
@@ -2715,10 +2681,6 @@
 	if (vma->vm_flags & VM_SHARED)
 		return VM_FAULT_SIGBUS;
 
-	/* Check if we need to add a guard page to the stack */
-	if (check_stack_guard_page(vma, address) < 0)
-		return VM_FAULT_SIGSEGV;
-
 	/* Use the zero-page for reads */
 	if (!(flags & FAULT_FLAG_WRITE) && !mm_forbids_zeropage(mm)) {
 		entry = pte_mkspecial(pfn_pte(my_zero_pfn(address),
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index a042a9d..a18923e 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1371,17 +1371,20 @@
 }
 
 /*
- * Confirm all pages in a range [start, end) is belongs to the same zone.
+ * Confirm all pages in a range [start, end) belong to the same zone.
+ * When true, return its valid [start, end).
  */
-int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
+int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
+			 unsigned long *valid_start, unsigned long *valid_end)
 {
 	unsigned long pfn, sec_end_pfn;
+	unsigned long start, end;
 	struct zone *zone = NULL;
 	struct page *page;
 	int i;
-	for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn);
+	for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn + 1);
 	     pfn < end_pfn;
-	     pfn = sec_end_pfn + 1, sec_end_pfn += PAGES_PER_SECTION) {
+	     pfn = sec_end_pfn, sec_end_pfn += PAGES_PER_SECTION) {
 		/* Make sure the memory section is present first */
 		if (!present_section_nr(pfn_to_section_nr(pfn)))
 			continue;
@@ -1397,10 +1400,20 @@
 			page = pfn_to_page(pfn + i);
 			if (zone && page_zone(page) != zone)
 				return 0;
+			if (!zone)
+				start = pfn + i;
 			zone = page_zone(page);
+			end = pfn + MAX_ORDER_NR_PAGES;
 		}
 	}
-	return 1;
+
+	if (zone) {
+		*valid_start = start;
+		*valid_end = end;
+		return 1;
+	} else {
+		return 0;
+	}
 }
 
 /*
@@ -1718,6 +1731,7 @@
 	long offlined_pages;
 	int ret, drain, retry_max, node;
 	unsigned long flags;
+	unsigned long valid_start, valid_end;
 	struct zone *zone;
 	struct memory_notify arg;
 
@@ -1728,10 +1742,10 @@
 		return -EINVAL;
 	/* This makes hotplug much easier...and readable.
 	   we assume this for now. .*/
-	if (!test_pages_in_a_zone(start_pfn, end_pfn))
+	if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end))
 		return -EINVAL;
 
-	zone = page_zone(pfn_to_page(start_pfn));
+	zone = page_zone(pfn_to_page(valid_start));
 	node = zone_to_nid(zone);
 	nr_pages = end_pfn - start_pfn;
 
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index f20eb4e..d56142b 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1493,7 +1493,6 @@
 COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, compat_ulong_t __user *, nmask,
 		       compat_ulong_t, maxnode)
 {
-	long err = 0;
 	unsigned long __user *nm = NULL;
 	unsigned long nr_bits, alloc_size;
 	DECLARE_BITMAP(bm, MAX_NUMNODES);
@@ -1502,14 +1501,13 @@
 	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
 
 	if (nmask) {
-		err = compat_get_bitmap(bm, nmask, nr_bits);
+		if (compat_get_bitmap(bm, nmask, nr_bits))
+			return -EFAULT;
 		nm = compat_alloc_user_space(alloc_size);
-		err |= copy_to_user(nm, bm, alloc_size);
+		if (copy_to_user(nm, bm, alloc_size))
+			return -EFAULT;
 	}
 
-	if (err)
-		return -EFAULT;
-
 	return sys_set_mempolicy(mode, nm, nr_bits+1);
 }
 
@@ -1517,7 +1515,6 @@
 		       compat_ulong_t, mode, compat_ulong_t __user *, nmask,
 		       compat_ulong_t, maxnode, compat_ulong_t, flags)
 {
-	long err = 0;
 	unsigned long __user *nm = NULL;
 	unsigned long nr_bits, alloc_size;
 	nodemask_t bm;
@@ -1526,14 +1523,13 @@
 	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
 
 	if (nmask) {
-		err = compat_get_bitmap(nodes_addr(bm), nmask, nr_bits);
+		if (compat_get_bitmap(nodes_addr(bm), nmask, nr_bits))
+			return -EFAULT;
 		nm = compat_alloc_user_space(alloc_size);
-		err |= copy_to_user(nm, nodes_addr(bm), alloc_size);
+		if (copy_to_user(nm, nodes_addr(bm), alloc_size))
+			return -EFAULT;
 	}
 
-	if (err)
-		return -EFAULT;
-
 	return sys_mbind(start, len, mode, nm, nr_bits+1, flags);
 }
 
@@ -2007,8 +2003,8 @@
 
 	nmask = policy_nodemask(gfp, pol);
 	zl = policy_zonelist(gfp, pol, node);
-	mpol_cond_put(pol);
 	page = __alloc_pages_nodemask(gfp, order, zl, nmask);
+	mpol_cond_put(pol);
 out:
 	if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie)))
 		goto retry_cpuset;
diff --git a/mm/migrate.c b/mm/migrate.c
index bbeb0b7..72c09de 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -429,6 +429,7 @@
 
 	return MIGRATEPAGE_SUCCESS;
 }
+EXPORT_SYMBOL(migrate_page_move_mapping);
 
 /*
  * The expected number of remaining references is the same as that
@@ -579,6 +580,7 @@
 	if (PageWriteback(newpage))
 		end_page_writeback(newpage);
 }
+EXPORT_SYMBOL(migrate_page_copy);
 
 /************************************************************
  *                    Migration functions
diff --git a/mm/mlock.c b/mm/mlock.c
index d843bc9..206e86b 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -277,7 +277,7 @@
 {
 	int i;
 	int nr = pagevec_count(pvec);
-	int delta_munlocked;
+	int delta_munlocked = -nr;
 	struct pagevec pvec_putback;
 	int pgrescued = 0;
 
@@ -297,6 +297,8 @@
 				continue;
 			else
 				__munlock_isolation_failed(page);
+		} else {
+			delta_munlocked++;
 		}
 
 		/*
@@ -308,7 +310,6 @@
 		pagevec_add(&pvec_putback, pvec->pages[i]);
 		pvec->pages[i] = NULL;
 	}
-	delta_munlocked = -nr + pagevec_count(&pvec_putback);
 	__mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
 	spin_unlock_irq(&zone->lru_lock);
 
diff --git a/mm/mmap.c b/mm/mmap.c
index a089cca8..86c03d3 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -300,6 +300,7 @@
 	unsigned long retval;
 	unsigned long newbrk, oldbrk;
 	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *next;
 	unsigned long min_brk;
 	bool populate;
 
@@ -344,7 +345,8 @@
 	}
 
 	/* Check against existing mmap mappings. */
-	if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
+	next = find_vma(mm, oldbrk);
+	if (next && newbrk + PAGE_SIZE > vm_start_gap(next))
 		goto out;
 
 	/* Ok, looks good - let it rip. */
@@ -367,10 +369,22 @@
 
 static long vma_compute_subtree_gap(struct vm_area_struct *vma)
 {
-	unsigned long max, subtree_gap;
-	max = vma->vm_start;
-	if (vma->vm_prev)
-		max -= vma->vm_prev->vm_end;
+	unsigned long max, prev_end, subtree_gap;
+
+	/*
+	 * Note: in the rare case of a VM_GROWSDOWN above a VM_GROWSUP, we
+	 * allow two stack_guard_gaps between them here, and when choosing
+	 * an unmapped area; whereas when expanding we only require one.
+	 * That's a little inconsistent, but keeps the code here simpler.
+	 */
+	max = vm_start_gap(vma);
+	if (vma->vm_prev) {
+		prev_end = vm_end_gap(vma->vm_prev);
+		if (max > prev_end)
+			max -= prev_end;
+		else
+			max = 0;
+	}
 	if (vma->vm_rb.rb_left) {
 		subtree_gap = rb_entry(vma->vm_rb.rb_left,
 				struct vm_area_struct, vm_rb)->rb_subtree_gap;
@@ -463,7 +477,7 @@
 			anon_vma_unlock_read(anon_vma);
 		}
 
-		highest_address = vma->vm_end;
+		highest_address = vm_end_gap(vma);
 		vma = vma->vm_next;
 		i++;
 	}
@@ -632,7 +646,7 @@
 	if (vma->vm_next)
 		vma_gap_update(vma->vm_next);
 	else
-		mm->highest_vm_end = vma->vm_end;
+		mm->highest_vm_end = vm_end_gap(vma);
 
 	/*
 	 * vma->vm_prev wasn't known when we followed the rbtree to find the
@@ -878,7 +892,7 @@
 			vma_gap_update(vma);
 		if (end_changed) {
 			if (!next)
-				mm->highest_vm_end = end;
+				mm->highest_vm_end = vm_end_gap(vma);
 			else if (!adjust_next)
 				vma_gap_update(next);
 		}
@@ -921,7 +935,7 @@
 		else if (next)
 			vma_gap_update(next);
 		else
-			mm->highest_vm_end = end;
+			VM_WARN_ON(mm->highest_vm_end != vm_end_gap(vma));
 	}
 	if (insert && file)
 		uprobe_mmap(insert);
@@ -1762,7 +1776,7 @@
 
 	while (true) {
 		/* Visit left subtree if it looks promising */
-		gap_end = vma->vm_start;
+		gap_end = vm_start_gap(vma);
 		if (gap_end >= low_limit && vma->vm_rb.rb_left) {
 			struct vm_area_struct *left =
 				rb_entry(vma->vm_rb.rb_left,
@@ -1773,12 +1787,13 @@
 			}
 		}
 
-		gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
+		gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0;
 check_current:
 		/* Check if current node has a suitable gap */
 		if (gap_start > high_limit)
 			return -ENOMEM;
-		if (gap_end >= low_limit && gap_end - gap_start >= length)
+		if (gap_end >= low_limit &&
+		    gap_end > gap_start && gap_end - gap_start >= length)
 			goto found;
 
 		/* Visit right subtree if it looks promising */
@@ -1800,8 +1815,8 @@
 			vma = rb_entry(rb_parent(prev),
 				       struct vm_area_struct, vm_rb);
 			if (prev == vma->vm_rb.rb_left) {
-				gap_start = vma->vm_prev->vm_end;
-				gap_end = vma->vm_start;
+				gap_start = vm_end_gap(vma->vm_prev);
+				gap_end = vm_start_gap(vma);
 				goto check_current;
 			}
 		}
@@ -1865,7 +1880,7 @@
 
 	while (true) {
 		/* Visit right subtree if it looks promising */
-		gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
+		gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0;
 		if (gap_start <= high_limit && vma->vm_rb.rb_right) {
 			struct vm_area_struct *right =
 				rb_entry(vma->vm_rb.rb_right,
@@ -1878,10 +1893,11 @@
 
 check_current:
 		/* Check if current node has a suitable gap */
-		gap_end = vma->vm_start;
+		gap_end = vm_start_gap(vma);
 		if (gap_end < low_limit)
 			return -ENOMEM;
-		if (gap_start <= high_limit && gap_end - gap_start >= length)
+		if (gap_start <= high_limit &&
+		    gap_end > gap_start && gap_end - gap_start >= length)
 			goto found;
 
 		/* Visit left subtree if it looks promising */
@@ -1904,7 +1920,7 @@
 				       struct vm_area_struct, vm_rb);
 			if (prev == vma->vm_rb.rb_right) {
 				gap_start = vma->vm_prev ?
-					vma->vm_prev->vm_end : 0;
+					vm_end_gap(vma->vm_prev) : 0;
 				goto check_current;
 			}
 		}
@@ -1942,7 +1958,7 @@
 		unsigned long len, unsigned long pgoff, unsigned long flags)
 {
 	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
+	struct vm_area_struct *vma, *prev;
 	struct vm_unmapped_area_info info;
 
 	if (len > TASK_SIZE - mmap_min_addr)
@@ -1953,9 +1969,10 @@
 
 	if (addr) {
 		addr = PAGE_ALIGN(addr);
-		vma = find_vma(mm, addr);
+		vma = find_vma_prev(mm, addr, &prev);
 		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)) &&
+		    (!prev || addr >= vm_end_gap(prev)))
 			return addr;
 	}
 
@@ -1978,7 +1995,7 @@
 			  const unsigned long len, const unsigned long pgoff,
 			  const unsigned long flags)
 {
-	struct vm_area_struct *vma;
+	struct vm_area_struct *vma, *prev;
 	struct mm_struct *mm = current->mm;
 	unsigned long addr = addr0;
 	struct vm_unmapped_area_info info;
@@ -1993,9 +2010,10 @@
 	/* requesting a specific address */
 	if (addr) {
 		addr = PAGE_ALIGN(addr);
-		vma = find_vma(mm, addr);
+		vma = find_vma_prev(mm, addr, &prev);
 		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
-				(!vma || addr + len <= vma->vm_start))
+				(!vma || addr + len <= vm_start_gap(vma)) &&
+				(!prev || addr >= vm_end_gap(prev)))
 			return addr;
 	}
 
@@ -2120,21 +2138,19 @@
  * update accounting. This is shared with both the
  * grow-up and grow-down cases.
  */
-static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow)
+static int acct_stack_growth(struct vm_area_struct *vma,
+			     unsigned long size, unsigned long grow)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	struct rlimit *rlim = current->signal->rlim;
-	unsigned long new_start, actual_size;
+	unsigned long new_start;
 
 	/* address space limit tests */
 	if (!may_expand_vm(mm, grow))
 		return -ENOMEM;
 
 	/* Stack limit test */
-	actual_size = size;
-	if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN)))
-		actual_size -= PAGE_SIZE;
-	if (actual_size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
+	if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
 		return -ENOMEM;
 
 	/* mlock limit tests */
@@ -2172,16 +2188,32 @@
 int expand_upwards(struct vm_area_struct *vma, unsigned long address)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	struct vm_area_struct *next;
+	unsigned long gap_addr;
 	int error = 0;
 
 	if (!(vma->vm_flags & VM_GROWSUP))
 		return -EFAULT;
 
-	/* Guard against wrapping around to address 0. */
-	if (address < PAGE_ALIGN(address+4))
-		address = PAGE_ALIGN(address+4);
-	else
+	/* Guard against exceeding limits of the address space. */
+	address &= PAGE_MASK;
+	if (address >= TASK_SIZE)
 		return -ENOMEM;
+	address += PAGE_SIZE;
+
+	/* Enforce stack_guard_gap */
+	gap_addr = address + stack_guard_gap;
+
+	/* Guard against overflow */
+	if (gap_addr < address || gap_addr > TASK_SIZE)
+		gap_addr = TASK_SIZE;
+
+	next = vma->vm_next;
+	if (next && next->vm_start < gap_addr) {
+		if (!(next->vm_flags & VM_GROWSUP))
+			return -ENOMEM;
+		/* Check that both stack segments have the same anon_vma? */
+	}
 
 	/* We must make sure the anon_vma is allocated. */
 	if (unlikely(anon_vma_prepare(vma)))
@@ -2227,7 +2259,7 @@
 				if (vma->vm_next)
 					vma_gap_update(vma->vm_next);
 				else
-					mm->highest_vm_end = address;
+					mm->highest_vm_end = vm_end_gap(vma);
 				spin_unlock(&mm->page_table_lock);
 
 				perf_event_mmap(vma);
@@ -2248,6 +2280,8 @@
 				   unsigned long address)
 {
 	struct mm_struct *mm = vma->vm_mm;
+	struct vm_area_struct *prev;
+	unsigned long gap_addr;
 	int error;
 
 	address &= PAGE_MASK;
@@ -2255,6 +2289,17 @@
 	if (error)
 		return error;
 
+	/* Enforce stack_guard_gap */
+	gap_addr = address - stack_guard_gap;
+	if (gap_addr > address)
+		return -ENOMEM;
+	prev = vma->vm_prev;
+	if (prev && prev->vm_end > gap_addr) {
+		if (!(prev->vm_flags & VM_GROWSDOWN))
+			return -ENOMEM;
+		/* Check that both stack segments have the same anon_vma? */
+	}
+
 	/* We must make sure the anon_vma is allocated. */
 	if (unlikely(anon_vma_prepare(vma)))
 		return -ENOMEM;
@@ -2310,28 +2355,25 @@
 	return error;
 }
 
-/*
- * Note how expand_stack() refuses to expand the stack all the way to
- * abut the next virtual mapping, *unless* that mapping itself is also
- * a stack mapping. We want to leave room for a guard page, after all
- * (the guard page itself is not added here, that is done by the
- * actual page faulting logic)
- *
- * This matches the behavior of the guard page logic (see mm/memory.c:
- * check_stack_guard_page()), which only allows the guard page to be
- * removed under these circumstances.
- */
+/* enforced gap between the expanding stack and other mappings. */
+unsigned long stack_guard_gap = 256UL<<PAGE_SHIFT;
+
+static int __init cmdline_parse_stack_guard_gap(char *p)
+{
+	unsigned long val;
+	char *endptr;
+
+	val = simple_strtoul(p, &endptr, 10);
+	if (!*endptr)
+		stack_guard_gap = val << PAGE_SHIFT;
+
+	return 0;
+}
+__setup("stack_guard_gap=", cmdline_parse_stack_guard_gap);
+
 #ifdef CONFIG_STACK_GROWSUP
 int expand_stack(struct vm_area_struct *vma, unsigned long address)
 {
-	struct vm_area_struct *next;
-
-	address &= PAGE_MASK;
-	next = vma->vm_next;
-	if (next && next->vm_start == address + PAGE_SIZE) {
-		if (!(next->vm_flags & VM_GROWSUP))
-			return -ENOMEM;
-	}
 	return expand_upwards(vma, address);
 }
 
@@ -2353,14 +2395,6 @@
 #else
 int expand_stack(struct vm_area_struct *vma, unsigned long address)
 {
-	struct vm_area_struct *prev;
-
-	address &= PAGE_MASK;
-	prev = vma->vm_prev;
-	if (prev && prev->vm_end == address) {
-		if (!(prev->vm_flags & VM_GROWSDOWN))
-			return -ENOMEM;
-	}
 	return expand_downwards(vma, address);
 }
 
@@ -2458,7 +2492,7 @@
 		vma->vm_prev = prev;
 		vma_gap_update(vma);
 	} else
-		mm->highest_vm_end = prev ? prev->vm_end : 0;
+		mm->highest_vm_end = prev ? vm_end_gap(prev) : 0;
 	tail_vma->vm_next = NULL;
 
 	/* Kill the cache */
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index e40c936..fd51ebf 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -359,8 +359,9 @@
 	struct dirty_throttle_control *gdtc = mdtc_gdtc(dtc);
 	unsigned long bytes = vm_dirty_bytes;
 	unsigned long bg_bytes = dirty_background_bytes;
-	unsigned long ratio = vm_dirty_ratio;
-	unsigned long bg_ratio = dirty_background_ratio;
+	/* convert ratios to per-PAGE_SIZE for higher precision */
+	unsigned long ratio = (vm_dirty_ratio * PAGE_SIZE) / 100;
+	unsigned long bg_ratio = (dirty_background_ratio * PAGE_SIZE) / 100;
 	unsigned long thresh;
 	unsigned long bg_thresh;
 	struct task_struct *tsk;
@@ -372,26 +373,28 @@
 		/*
 		 * The byte settings can't be applied directly to memcg
 		 * domains.  Convert them to ratios by scaling against
-		 * globally available memory.
+		 * globally available memory.  As the ratios are in
+		 * per-PAGE_SIZE, they can be obtained by dividing bytes by
+		 * number of pages.
 		 */
 		if (bytes)
-			ratio = min(DIV_ROUND_UP(bytes, PAGE_SIZE) * 100 /
-				    global_avail, 100UL);
+			ratio = min(DIV_ROUND_UP(bytes, global_avail),
+				    PAGE_SIZE);
 		if (bg_bytes)
-			bg_ratio = min(DIV_ROUND_UP(bg_bytes, PAGE_SIZE) * 100 /
-				       global_avail, 100UL);
+			bg_ratio = min(DIV_ROUND_UP(bg_bytes, global_avail),
+				       PAGE_SIZE);
 		bytes = bg_bytes = 0;
 	}
 
 	if (bytes)
 		thresh = DIV_ROUND_UP(bytes, PAGE_SIZE);
 	else
-		thresh = (ratio * available_memory) / 100;
+		thresh = (ratio * available_memory) / PAGE_SIZE;
 
 	if (bg_bytes)
 		bg_thresh = DIV_ROUND_UP(bg_bytes, PAGE_SIZE);
 	else
-		bg_thresh = (bg_ratio * available_memory) / 100;
+		bg_thresh = (bg_ratio * available_memory) / PAGE_SIZE;
 
 	if (bg_thresh >= thresh)
 		bg_thresh = thresh / 2;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 755f29f..f54a86d 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -281,13 +281,35 @@
 #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
 static inline void reset_deferred_meminit(pg_data_t *pgdat)
 {
+	unsigned long max_initialise;
+	unsigned long reserved_lowmem;
+
+	/*
+	 * Initialise at least 2G of a node but also take into account that
+	 * two large system hashes that can take up 1GB for 0.25TB/node.
+	 */
+	max_initialise = max(2UL << (30 - PAGE_SHIFT),
+		(pgdat->node_spanned_pages >> 8));
+
+	/*
+	 * Compensate the all the memblock reservations (e.g. crash kernel)
+	 * from the initial estimation to make sure we will initialize enough
+	 * memory to boot.
+	 */
+	reserved_lowmem = memblock_reserved_memory_within(pgdat->node_start_pfn,
+			pgdat->node_start_pfn + max_initialise);
+	max_initialise += reserved_lowmem;
+
+	pgdat->static_init_size = min(max_initialise, pgdat->node_spanned_pages);
 	pgdat->first_deferred_pfn = ULONG_MAX;
 }
 
 /* Returns true if the struct page for the pfn is uninitialised */
 static inline bool __meminit early_page_uninitialised(unsigned long pfn)
 {
-	if (pfn >= NODE_DATA(early_pfn_to_nid(pfn))->first_deferred_pfn)
+	int nid = early_pfn_to_nid(pfn);
+
+	if (node_online(nid) && pfn >= NODE_DATA(nid)->first_deferred_pfn)
 		return true;
 
 	return false;
@@ -312,10 +334,9 @@
 	/* Always populate low zones for address-contrained allocations */
 	if (zone_end < pgdat_end_pfn(pgdat))
 		return true;
-
 	/* Initialise at least 2G of the highest zone */
 	(*nr_initialised)++;
-	if (*nr_initialised > (2UL << (30 - PAGE_SHIFT)) &&
+	if ((*nr_initialised > pgdat->static_init_size) &&
 	    (pfn & (PAGES_PER_SECTION - 1)) == 0) {
 		pgdat->first_deferred_pfn = pfn;
 		return false;
@@ -963,7 +984,7 @@
  * marks the pages PageReserved. The remaining valid pages are later
  * sent to the buddy page allocator.
  */
-void __meminit reserve_bootmem_region(unsigned long start, unsigned long end)
+void __meminit reserve_bootmem_region(phys_addr_t start, phys_addr_t end)
 {
 	unsigned long start_pfn = PFN_DOWN(start);
 	unsigned long end_pfn = PFN_UP(end);
@@ -1069,7 +1090,7 @@
 	spin_lock(&early_pfn_lock);
 	nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache);
 	if (nid < 0)
-		nid = 0;
+		nid = first_online_node;
 	spin_unlock(&early_pfn_lock);
 
 	return nid;
@@ -2477,7 +2498,7 @@
 
 static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
 {
-	return node_distance(zone_to_nid(local_zone), zone_to_nid(zone)) <
+	return node_distance(zone_to_nid(local_zone), zone_to_nid(zone)) <=
 				RECLAIM_DISTANCE;
 }
 #else	/* CONFIG_NUMA */
@@ -5353,7 +5374,6 @@
 	/* pg_data_t should be reset to zero when it's allocated */
 	WARN_ON(pgdat->nr_zones || pgdat->classzone_idx);
 
-	reset_deferred_meminit(pgdat);
 	pgdat->node_id = nid;
 	pgdat->node_start_pfn = node_start_pfn;
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
@@ -5372,6 +5392,7 @@
 		(unsigned long)pgdat->node_mem_map);
 #endif
 
+	reset_deferred_meminit(pgdat);
 	free_area_init_core(pgdat);
 }
 
@@ -5706,15 +5727,18 @@
 				sizeof(arch_zone_lowest_possible_pfn));
 	memset(arch_zone_highest_possible_pfn, 0,
 				sizeof(arch_zone_highest_possible_pfn));
-	arch_zone_lowest_possible_pfn[0] = find_min_pfn_with_active_regions();
-	arch_zone_highest_possible_pfn[0] = max_zone_pfn[0];
-	for (i = 1; i < MAX_NR_ZONES; i++) {
+
+	start_pfn = find_min_pfn_with_active_regions();
+
+	for (i = 0; i < MAX_NR_ZONES; i++) {
 		if (i == ZONE_MOVABLE)
 			continue;
-		arch_zone_lowest_possible_pfn[i] =
-			arch_zone_highest_possible_pfn[i-1];
-		arch_zone_highest_possible_pfn[i] =
-			max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]);
+
+		end_pfn = max(max_zone_pfn[i], start_pfn);
+		arch_zone_lowest_possible_pfn[i] = start_pfn;
+		arch_zone_highest_possible_pfn[i] = end_pfn;
+
+		start_pfn = end_pfn;
 	}
 	arch_zone_lowest_possible_pfn[ZONE_MOVABLE] = 0;
 	arch_zone_highest_possible_pfn[ZONE_MOVABLE] = 0;
diff --git a/mm/percpu.c b/mm/percpu.c
index 8a943b9..ef6353f 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -110,7 +110,7 @@
 	int			map_used;	/* # of map entries used before the sentry */
 	int			map_alloc;	/* # of map entries allocated */
 	int			*map;		/* allocation map */
-	struct work_struct	map_extend_work;/* async ->map[] extension */
+	struct list_head	map_extend_list;/* on pcpu_map_extend_chunks */
 
 	void			*data;		/* chunk data */
 	int			first_free;	/* no free below this */
@@ -160,10 +160,13 @@
 static int pcpu_reserved_chunk_limit;
 
 static DEFINE_SPINLOCK(pcpu_lock);	/* all internal data structures */
-static DEFINE_MUTEX(pcpu_alloc_mutex);	/* chunk create/destroy, [de]pop */
+static DEFINE_MUTEX(pcpu_alloc_mutex);	/* chunk create/destroy, [de]pop, map ext */
 
 static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */
 
+/* chunks which need their map areas extended, protected by pcpu_lock */
+static LIST_HEAD(pcpu_map_extend_chunks);
+
 /*
  * The number of empty populated pages, protected by pcpu_lock.  The
  * reserved chunk doesn't contribute to the count.
@@ -397,13 +400,19 @@
 {
 	int margin, new_alloc;
 
+	lockdep_assert_held(&pcpu_lock);
+
 	if (is_atomic) {
 		margin = 3;
 
 		if (chunk->map_alloc <
-		    chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW &&
-		    pcpu_async_enabled)
-			schedule_work(&chunk->map_extend_work);
+		    chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW) {
+			if (list_empty(&chunk->map_extend_list)) {
+				list_add_tail(&chunk->map_extend_list,
+					      &pcpu_map_extend_chunks);
+				pcpu_schedule_balance_work();
+			}
+		}
 	} else {
 		margin = PCPU_ATOMIC_MAP_MARGIN_HIGH;
 	}
@@ -437,6 +446,8 @@
 	size_t old_size = 0, new_size = new_alloc * sizeof(new[0]);
 	unsigned long flags;
 
+	lockdep_assert_held(&pcpu_alloc_mutex);
+
 	new = pcpu_mem_zalloc(new_size);
 	if (!new)
 		return -ENOMEM;
@@ -469,20 +480,6 @@
 	return 0;
 }
 
-static void pcpu_map_extend_workfn(struct work_struct *work)
-{
-	struct pcpu_chunk *chunk = container_of(work, struct pcpu_chunk,
-						map_extend_work);
-	int new_alloc;
-
-	spin_lock_irq(&pcpu_lock);
-	new_alloc = pcpu_need_to_extend(chunk, false);
-	spin_unlock_irq(&pcpu_lock);
-
-	if (new_alloc)
-		pcpu_extend_area_map(chunk, new_alloc);
-}
-
 /**
  * pcpu_fit_in_area - try to fit the requested allocation in a candidate area
  * @chunk: chunk the candidate area belongs to
@@ -742,7 +739,7 @@
 	chunk->map_used = 1;
 
 	INIT_LIST_HEAD(&chunk->list);
-	INIT_WORK(&chunk->map_extend_work, pcpu_map_extend_workfn);
+	INIT_LIST_HEAD(&chunk->map_extend_list);
 	chunk->free_size = pcpu_unit_size;
 	chunk->contig_hint = pcpu_unit_size;
 
@@ -897,6 +894,9 @@
 		return NULL;
 	}
 
+	if (!is_atomic)
+		mutex_lock(&pcpu_alloc_mutex);
+
 	spin_lock_irqsave(&pcpu_lock, flags);
 
 	/* serve reserved allocations from the reserved chunk if available */
@@ -969,12 +969,9 @@
 	if (is_atomic)
 		goto fail;
 
-	mutex_lock(&pcpu_alloc_mutex);
-
 	if (list_empty(&pcpu_slot[pcpu_nr_slots - 1])) {
 		chunk = pcpu_create_chunk();
 		if (!chunk) {
-			mutex_unlock(&pcpu_alloc_mutex);
 			err = "failed to allocate new chunk";
 			goto fail;
 		}
@@ -985,7 +982,6 @@
 		spin_lock_irqsave(&pcpu_lock, flags);
 	}
 
-	mutex_unlock(&pcpu_alloc_mutex);
 	goto restart;
 
 area_found:
@@ -995,8 +991,6 @@
 	if (!is_atomic) {
 		int page_start, page_end, rs, re;
 
-		mutex_lock(&pcpu_alloc_mutex);
-
 		page_start = PFN_DOWN(off);
 		page_end = PFN_UP(off + size);
 
@@ -1007,7 +1001,6 @@
 
 			spin_lock_irqsave(&pcpu_lock, flags);
 			if (ret) {
-				mutex_unlock(&pcpu_alloc_mutex);
 				pcpu_free_area(chunk, off, &occ_pages);
 				err = "failed to populate";
 				goto fail_unlock;
@@ -1019,8 +1012,11 @@
 		mutex_unlock(&pcpu_alloc_mutex);
 	}
 
-	if (chunk != pcpu_reserved_chunk)
+	if (chunk != pcpu_reserved_chunk) {
+		spin_lock_irqsave(&pcpu_lock, flags);
 		pcpu_nr_empty_pop_pages -= occ_pages;
+		spin_unlock_irqrestore(&pcpu_lock, flags);
+	}
 
 	if (pcpu_nr_empty_pop_pages < PCPU_EMPTY_POP_PAGES_LOW)
 		pcpu_schedule_balance_work();
@@ -1047,6 +1043,8 @@
 		/* see the flag handling in pcpu_blance_workfn() */
 		pcpu_atomic_alloc_failed = true;
 		pcpu_schedule_balance_work();
+	} else {
+		mutex_unlock(&pcpu_alloc_mutex);
 	}
 	return NULL;
 }
@@ -1131,6 +1129,7 @@
 		if (chunk == list_first_entry(free_head, struct pcpu_chunk, list))
 			continue;
 
+		list_del_init(&chunk->map_extend_list);
 		list_move(&chunk->list, &to_free);
 	}
 
@@ -1148,6 +1147,25 @@
 		pcpu_destroy_chunk(chunk);
 	}
 
+	/* service chunks which requested async area map extension */
+	do {
+		int new_alloc = 0;
+
+		spin_lock_irq(&pcpu_lock);
+
+		chunk = list_first_entry_or_null(&pcpu_map_extend_chunks,
+					struct pcpu_chunk, map_extend_list);
+		if (chunk) {
+			list_del_init(&chunk->map_extend_list);
+			new_alloc = pcpu_need_to_extend(chunk, false);
+		}
+
+		spin_unlock_irq(&pcpu_lock);
+
+		if (new_alloc)
+			pcpu_extend_area_map(chunk, new_alloc);
+	} while (chunk);
+
 	/*
 	 * Ensure there are certain number of free populated pages for
 	 * atomic allocs.  Fill up from the most packed so that atomic
@@ -1646,7 +1664,7 @@
 	 */
 	schunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0);
 	INIT_LIST_HEAD(&schunk->list);
-	INIT_WORK(&schunk->map_extend_work, pcpu_map_extend_workfn);
+	INIT_LIST_HEAD(&schunk->map_extend_list);
 	schunk->base_addr = base_addr;
 	schunk->map = smap;
 	schunk->map_alloc = ARRAY_SIZE(smap);
@@ -1675,7 +1693,7 @@
 	if (dyn_size) {
 		dchunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0);
 		INIT_LIST_HEAD(&dchunk->list);
-		INIT_WORK(&dchunk->map_extend_work, pcpu_map_extend_workfn);
+		INIT_LIST_HEAD(&dchunk->map_extend_list);
 		dchunk->base_addr = base_addr;
 		dchunk->map = dmap;
 		dchunk->map_alloc = ARRAY_SIZE(dmap);
diff --git a/mm/shmem.c b/mm/shmem.c
index b82e56e..79997e8 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2153,9 +2153,11 @@
 									NULL);
 		if (error) {
 			/* Remove the !PageUptodate pages we added */
-			shmem_undo_range(inode,
-				(loff_t)start << PAGE_CACHE_SHIFT,
-				(loff_t)index << PAGE_CACHE_SHIFT, true);
+			if (index > start) {
+				shmem_undo_range(inode,
+				 (loff_t)start << PAGE_CACHE_SHIFT,
+				 ((loff_t)index << PAGE_CACHE_SHIFT) - 1, true);
+			}
 			goto undone;
 		}
 
diff --git a/mm/slab.c b/mm/slab.c
index 4765c97..24a615d 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -4228,6 +4228,36 @@
 module_init(slab_proc_init);
 #endif
 
+#ifdef CONFIG_HARDENED_USERCOPY
+/*
+ * Rejects objects that are incorrectly sized.
+ *
+ * Returns NULL if check passes, otherwise const char * to name of cache
+ * to indicate an error.
+ */
+const char *__check_heap_object(const void *ptr, unsigned long n,
+				struct page *page)
+{
+	struct kmem_cache *cachep;
+	unsigned int objnr;
+	unsigned long offset;
+
+	/* Find and validate object. */
+	cachep = page->slab_cache;
+	objnr = obj_to_index(cachep, page, (void *)ptr);
+	BUG_ON(objnr >= cachep->num);
+
+	/* Find offset within object. */
+	offset = ptr - index_to_obj(cachep, page, objnr) - obj_offset(cachep);
+
+	/* Allow address range falling entirely within object size. */
+	if (offset <= cachep->object_size && n <= cachep->object_size - offset)
+		return NULL;
+
+	return cachep->name;
+}
+#endif /* CONFIG_HARDENED_USERCOPY */
+
 /**
  * ksize - get the actual amount of memory allocated for a given object
  * @objp: Pointer to the object
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 3c6a86b..bec2fce 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -521,8 +521,8 @@
 		goto out_unlock;
 
 	cgroup_name(css->cgroup, memcg_name_buf, sizeof(memcg_name_buf));
-	cache_name = kasprintf(GFP_KERNEL, "%s(%d:%s)", root_cache->name,
-			       css->id, memcg_name_buf);
+	cache_name = kasprintf(GFP_KERNEL, "%s(%llu:%s)", root_cache->name,
+			       css->serial_nr, memcg_name_buf);
 	if (!cache_name)
 		goto out_unlock;
 
diff --git a/mm/slub.c b/mm/slub.c
index 65d5f92..d6fe997 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -124,6 +124,14 @@
 #endif
 }
 
+static inline void *fixup_red_left(struct kmem_cache *s, void *p)
+{
+	if (kmem_cache_debug(s) && s->flags & SLAB_RED_ZONE)
+		p += s->red_left_pad;
+
+	return p;
+}
+
 static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s)
 {
 #ifdef CONFIG_SLUB_CPU_PARTIAL
@@ -224,24 +232,6 @@
  * 			Core slab cache functions
  *******************************************************************/
 
-/* Verify that a pointer has an address that is valid within a slab page */
-static inline int check_valid_pointer(struct kmem_cache *s,
-				struct page *page, const void *object)
-{
-	void *base;
-
-	if (!object)
-		return 1;
-
-	base = page_address(page);
-	if (object < base || object >= base + page->objects * s->size ||
-		(object - base) % s->size) {
-		return 0;
-	}
-
-	return 1;
-}
-
 static inline void *get_freepointer(struct kmem_cache *s, void *object)
 {
 	return *(void **)(object + s->offset);
@@ -271,12 +261,14 @@
 
 /* Loop over all objects in a slab */
 #define for_each_object(__p, __s, __addr, __objects) \
-	for (__p = (__addr); __p < (__addr) + (__objects) * (__s)->size;\
-			__p += (__s)->size)
+	for (__p = fixup_red_left(__s, __addr); \
+		__p < (__addr) + (__objects) * (__s)->size; \
+		__p += (__s)->size)
 
 #define for_each_object_idx(__p, __idx, __s, __addr, __objects) \
-	for (__p = (__addr), __idx = 1; __idx <= __objects;\
-			__p += (__s)->size, __idx++)
+	for (__p = fixup_red_left(__s, __addr), __idx = 1; \
+		__idx <= __objects; \
+		__p += (__s)->size, __idx++)
 
 /* Determine object index from a given position */
 static inline int slab_index(void *p, struct kmem_cache *s, void *addr)
@@ -456,6 +448,22 @@
 		set_bit(slab_index(p, s, addr), map);
 }
 
+static inline int size_from_object(struct kmem_cache *s)
+{
+	if (s->flags & SLAB_RED_ZONE)
+		return s->size - s->red_left_pad;
+
+	return s->size;
+}
+
+static inline void *restore_red_left(struct kmem_cache *s, void *p)
+{
+	if (s->flags & SLAB_RED_ZONE)
+		p -= s->red_left_pad;
+
+	return p;
+}
+
 /*
  * Debug settings:
  */
@@ -489,6 +497,26 @@
 /*
  * Object debugging
  */
+
+/* Verify that a pointer has an address that is valid within a slab page */
+static inline int check_valid_pointer(struct kmem_cache *s,
+				struct page *page, void *object)
+{
+	void *base;
+
+	if (!object)
+		return 1;
+
+	base = page_address(page);
+	object = restore_red_left(s, object);
+	if (object < base || object >= base + page->objects * s->size ||
+		(object - base) % s->size) {
+		return 0;
+	}
+
+	return 1;
+}
+
 static void print_section(char *text, u8 *addr, unsigned int length)
 {
 	metadata_access_enable();
@@ -628,7 +656,9 @@
 	pr_err("INFO: Object 0x%p @offset=%tu fp=0x%p\n\n",
 	       p, p - addr, get_freepointer(s, p));
 
-	if (p > addr + 16)
+	if (s->flags & SLAB_RED_ZONE)
+		print_section("Redzone ", p - s->red_left_pad, s->red_left_pad);
+	else if (p > addr + 16)
 		print_section("Bytes b4 ", p - 16, 16);
 
 	print_section("Object ", p, min_t(unsigned long, s->object_size,
@@ -645,9 +675,9 @@
 	if (s->flags & SLAB_STORE_USER)
 		off += 2 * sizeof(struct track);
 
-	if (off != s->size)
+	if (off != size_from_object(s))
 		/* Beginning of the filler is the free pointer */
-		print_section("Padding ", p + off, s->size - off);
+		print_section("Padding ", p + off, size_from_object(s) - off);
 
 	dump_stack();
 }
@@ -677,6 +707,9 @@
 {
 	u8 *p = object;
 
+	if (s->flags & SLAB_RED_ZONE)
+		memset(p - s->red_left_pad, val, s->red_left_pad);
+
 	if (s->flags & __OBJECT_POISON) {
 		memset(p, POISON_FREE, s->object_size - 1);
 		p[s->object_size - 1] = POISON_END;
@@ -769,11 +802,11 @@
 		/* We also have user information there */
 		off += 2 * sizeof(struct track);
 
-	if (s->size == off)
+	if (size_from_object(s) == off)
 		return 1;
 
 	return check_bytes_and_report(s, page, p, "Object padding",
-				p + off, POISON_INUSE, s->size - off);
+			p + off, POISON_INUSE, size_from_object(s) - off);
 }
 
 /* Check the pad bytes at the end of a slab page */
@@ -818,6 +851,10 @@
 
 	if (s->flags & SLAB_RED_ZONE) {
 		if (!check_bytes_and_report(s, page, object, "Redzone",
+			object - s->red_left_pad, val, s->red_left_pad))
+			return 0;
+
+		if (!check_bytes_and_report(s, page, object, "Redzone",
 			endobject, val, s->inuse - s->object_size))
 			return 0;
 	} else {
@@ -1468,7 +1505,7 @@
 			set_freepointer(s, p, NULL);
 	}
 
-	page->freelist = start;
+	page->freelist = fixup_red_left(s, start);
 	page->inuse = page->objects;
 	page->frozen = 1;
 
@@ -3283,7 +3320,7 @@
 		 */
 		size += 2 * sizeof(struct track);
 
-	if (flags & SLAB_RED_ZONE)
+	if (flags & SLAB_RED_ZONE) {
 		/*
 		 * Add some empty padding so that we can catch
 		 * overwrites from earlier objects rather than let
@@ -3292,6 +3329,11 @@
 		 * of the object.
 		 */
 		size += sizeof(void *);
+
+		s->red_left_pad = sizeof(void *);
+		s->red_left_pad = ALIGN(s->red_left_pad, s->align);
+		size += s->red_left_pad;
+	}
 #endif
 
 	/*
@@ -3585,6 +3627,46 @@
 EXPORT_SYMBOL(__kmalloc_node);
 #endif
 
+#ifdef CONFIG_HARDENED_USERCOPY
+/*
+ * Rejects objects that are incorrectly sized.
+ *
+ * Returns NULL if check passes, otherwise const char * to name of cache
+ * to indicate an error.
+ */
+const char *__check_heap_object(const void *ptr, unsigned long n,
+				struct page *page)
+{
+	struct kmem_cache *s;
+	unsigned long offset;
+	size_t object_size;
+
+	/* Find object and usable object size. */
+	s = page->slab_cache;
+	object_size = slab_ksize(s);
+
+	/* Reject impossible pointers. */
+	if (ptr < page_address(page))
+		return s->name;
+
+	/* Find offset within object. */
+	offset = (ptr - page_address(page)) % s->size;
+
+	/* Adjust for redzone and reject if within the redzone. */
+	if (kmem_cache_debug(s) && s->flags & SLAB_RED_ZONE) {
+		if (offset < s->red_left_pad)
+			return s->name;
+		offset -= s->red_left_pad;
+	}
+
+	/* Allow address range falling entirely within object size. */
+	if (offset <= object_size && n <= object_size - offset)
+		return NULL;
+
+	return s->name;
+}
+#endif /* CONFIG_HARDENED_USERCOPY */
+
 static size_t __ksize(const void *object)
 {
 	struct page *page;
@@ -5261,6 +5343,7 @@
 		char mbuf[64];
 		char *buf;
 		struct slab_attribute *attr = to_slab_attr(slab_attrs[i]);
+		ssize_t len;
 
 		if (!attr || !attr->store || !attr->show)
 			continue;
@@ -5285,8 +5368,9 @@
 			buf = buffer;
 		}
 
-		attr->show(root_cache, buf);
-		attr->store(s, buf, strlen(buf));
+		len = attr->show(root_cache, buf);
+		if (len > 0)
+			attr->store(s, buf, len);
 	}
 
 	if (buffer)
diff --git a/mm/swap_cgroup.c b/mm/swap_cgroup.c
index b5f7f24..09f733b 100644
--- a/mm/swap_cgroup.c
+++ b/mm/swap_cgroup.c
@@ -48,6 +48,9 @@
 		if (!page)
 			goto not_enough_page;
 		ctrl->map[idx] = page;
+
+		if (!(idx % SWAP_CLUSTER_MAX))
+			cond_resched();
 	}
 	return 0;
 not_enough_page:
@@ -202,6 +205,8 @@
 			struct page *page = map[i];
 			if (page)
 				__free_page(page);
+			if (!(i % SWAP_CLUSTER_MAX))
+				cond_resched();
 		}
 		vfree(map);
 	}
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 5887731..c1a0f3d 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2225,6 +2225,8 @@
 		swab32s(&swap_header->info.version);
 		swab32s(&swap_header->info.last_page);
 		swab32s(&swap_header->info.nr_badpages);
+		if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES)
+			return 0;
 		for (i = 0; i < swap_header->info.nr_badpages; i++)
 			swab32s(&swap_header->info.badpages[i]);
 	}
diff --git a/mm/truncate.c b/mm/truncate.c
index 76e35ad..f4c8270 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -732,7 +732,7 @@
  */
 void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to)
 {
-	int bsize = 1 << inode->i_blkbits;
+	int bsize = i_blocksize(inode);
 	loff_t rounded_from;
 	struct page *page;
 	pgoff_t index;
diff --git a/mm/usercopy.c b/mm/usercopy.c
new file mode 100644
index 0000000..b34996a
--- /dev/null
+++ b/mm/usercopy.c
@@ -0,0 +1,278 @@
+/*
+ * This implements the various checks for CONFIG_HARDENED_USERCOPY*,
+ * which are designed to protect kernel memory from needless exposure
+ * and overwrite under many unintended conditions. This code is based
+ * on PAX_USERCOPY, which is:
+ *
+ * Copyright (C) 2001-2016 PaX Team, Bradley Spengler, Open Source
+ * Security Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/sections.h>
+
+enum {
+	BAD_STACK = -1,
+	NOT_STACK = 0,
+	GOOD_FRAME,
+	GOOD_STACK,
+};
+
+/*
+ * Checks if a given pointer and length is contained by the current
+ * stack frame (if possible).
+ *
+ * Returns:
+ *	NOT_STACK: not at all on the stack
+ *	GOOD_FRAME: fully within a valid stack frame
+ *	GOOD_STACK: fully on the stack (when can't do frame-checking)
+ *	BAD_STACK: error condition (invalid stack position or bad stack frame)
+ */
+static noinline int check_stack_object(const void *obj, unsigned long len)
+{
+	const void * const stack = task_stack_page(current);
+	const void * const stackend = stack + THREAD_SIZE;
+	int ret;
+
+	/* Object is not on the stack at all. */
+	if (obj + len <= stack || stackend <= obj)
+		return NOT_STACK;
+
+	/*
+	 * Reject: object partially overlaps the stack (passing the
+	 * the check above means at least one end is within the stack,
+	 * so if this check fails, the other end is outside the stack).
+	 */
+	if (obj < stack || stackend < obj + len)
+		return BAD_STACK;
+
+	/* Check if object is safely within a valid frame. */
+	ret = arch_within_stack_frames(stack, stackend, obj, len);
+	if (ret)
+		return ret;
+
+	return GOOD_STACK;
+}
+
+static void report_usercopy(const void *ptr, unsigned long len,
+			    bool to_user, const char *type)
+{
+	pr_emerg("kernel memory %s attempt detected %s %p (%s) (%lu bytes)\n",
+		to_user ? "exposure" : "overwrite",
+		to_user ? "from" : "to", ptr, type ? : "unknown", len);
+	/*
+	 * For greater effect, it would be nice to do do_group_exit(),
+	 * but BUG() actually hooks all the lock-breaking and per-arch
+	 * Oops code, so that is used here instead.
+	 */
+	BUG();
+}
+
+/* Returns true if any portion of [ptr,ptr+n) over laps with [low,high). */
+static bool overlaps(const void *ptr, unsigned long n, unsigned long low,
+		     unsigned long high)
+{
+	unsigned long check_low = (uintptr_t)ptr;
+	unsigned long check_high = check_low + n;
+
+	/* Does not overlap if entirely above or entirely below. */
+	if (check_low >= high || check_high <= low)
+		return false;
+
+	return true;
+}
+
+/* Is this address range in the kernel text area? */
+static inline const char *check_kernel_text_object(const void *ptr,
+						   unsigned long n)
+{
+	unsigned long textlow = (unsigned long)_stext;
+	unsigned long texthigh = (unsigned long)_etext;
+	unsigned long textlow_linear, texthigh_linear;
+
+	if (overlaps(ptr, n, textlow, texthigh))
+		return "<kernel text>";
+
+	/*
+	 * Some architectures have virtual memory mappings with a secondary
+	 * mapping of the kernel text, i.e. there is more than one virtual
+	 * kernel address that points to the kernel image. It is usually
+	 * when there is a separate linear physical memory mapping, in that
+	 * __pa() is not just the reverse of __va(). This can be detected
+	 * and checked:
+	 */
+	textlow_linear = (unsigned long)__va(__pa(textlow));
+	/* No different mapping: we're done. */
+	if (textlow_linear == textlow)
+		return NULL;
+
+	/* Check the secondary mapping... */
+	texthigh_linear = (unsigned long)__va(__pa(texthigh));
+	if (overlaps(ptr, n, textlow_linear, texthigh_linear))
+		return "<linear kernel text>";
+
+	return NULL;
+}
+
+static inline const char *check_bogus_address(const void *ptr, unsigned long n)
+{
+	/* Reject if object wraps past end of memory. */
+	if ((unsigned long)ptr + n < (unsigned long)ptr)
+		return "<wrapped address>";
+
+	/* Reject if NULL or ZERO-allocation. */
+	if (ZERO_OR_NULL_PTR(ptr))
+		return "<null>";
+
+	return NULL;
+}
+
+/* Checks for allocs that are marked in some way as spanning multiple pages. */
+static inline const char *check_page_span(const void *ptr, unsigned long n,
+					  struct page *page, bool to_user)
+{
+#ifdef CONFIG_HARDENED_USERCOPY_PAGESPAN
+	const void *end = ptr + n - 1;
+	struct page *endpage;
+	bool is_reserved, is_cma;
+
+	/*
+	 * Sometimes the kernel data regions are not marked Reserved (see
+	 * check below). And sometimes [_sdata,_edata) does not cover
+	 * rodata and/or bss, so check each range explicitly.
+	 */
+
+	/* Allow reads of kernel rodata region (if not marked as Reserved). */
+	if (ptr >= (const void *)__start_rodata &&
+	    end <= (const void *)__end_rodata) {
+		if (!to_user)
+			return "<rodata>";
+		return NULL;
+	}
+
+	/* Allow kernel data region (if not marked as Reserved). */
+	if (ptr >= (const void *)_sdata && end <= (const void *)_edata)
+		return NULL;
+
+	/* Allow kernel bss region (if not marked as Reserved). */
+	if (ptr >= (const void *)__bss_start &&
+	    end <= (const void *)__bss_stop)
+		return NULL;
+
+	/* Is the object wholly within one base page? */
+	if (likely(((unsigned long)ptr & (unsigned long)PAGE_MASK) ==
+		   ((unsigned long)end & (unsigned long)PAGE_MASK)))
+		return NULL;
+
+	/* Allow if fully inside the same compound (__GFP_COMP) page. */
+	endpage = virt_to_head_page(end);
+	if (likely(endpage == page))
+		return NULL;
+
+	/*
+	 * Reject if range is entirely either Reserved (i.e. special or
+	 * device memory), or CMA. Otherwise, reject since the object spans
+	 * several independently allocated pages.
+	 */
+	is_reserved = PageReserved(page);
+	is_cma = is_migrate_cma_page(page);
+	if (!is_reserved && !is_cma)
+		return "<spans multiple pages>";
+
+	for (ptr += PAGE_SIZE; ptr <= end; ptr += PAGE_SIZE) {
+		page = virt_to_head_page(ptr);
+		if (is_reserved && !PageReserved(page))
+			return "<spans Reserved and non-Reserved pages>";
+		if (is_cma && !is_migrate_cma_page(page))
+			return "<spans CMA and non-CMA pages>";
+	}
+#endif
+
+	return NULL;
+}
+
+static inline const char *check_heap_object(const void *ptr, unsigned long n,
+					    bool to_user)
+{
+	struct page *page;
+
+	/*
+	 * Some architectures (arm64) return true for virt_addr_valid() on
+	 * vmalloced addresses. Work around this by checking for vmalloc
+	 * first.
+	 */
+	if (is_vmalloc_addr(ptr))
+		return NULL;
+
+	if (!virt_addr_valid(ptr))
+		return NULL;
+
+	page = virt_to_head_page(ptr);
+
+	/* Check slab allocator for flags and size. */
+	if (PageSlab(page))
+		return __check_heap_object(ptr, n, page);
+
+	/* Verify object does not incorrectly span multiple pages. */
+	return check_page_span(ptr, n, page, to_user);
+}
+
+/*
+ * Validates that the given object is:
+ * - not bogus address
+ * - known-safe heap or stack object
+ * - not in kernel text
+ */
+void __check_object_size(const void *ptr, unsigned long n, bool to_user)
+{
+	const char *err;
+
+	/* Skip all tests if size is zero. */
+	if (!n)
+		return;
+
+	/* Check for invalid addresses. */
+	err = check_bogus_address(ptr, n);
+	if (err)
+		goto report;
+
+	/* Check for bad heap object. */
+	err = check_heap_object(ptr, n, to_user);
+	if (err)
+		goto report;
+
+	/* Check for bad stack object. */
+	switch (check_stack_object(ptr, n)) {
+	case NOT_STACK:
+		/* Object is not touching the current process stack. */
+		break;
+	case GOOD_FRAME:
+	case GOOD_STACK:
+		/*
+		 * Object is either in the correct frame (when it
+		 * is possible to check) or just generally on the
+		 * process stack (when frame checking not available).
+		 */
+		return;
+	default:
+		err = "<process stack>";
+		goto report;
+	}
+
+	/* Check for object in kernel to avoid text exposure. */
+	err = check_kernel_text_object(ptr, n);
+	if (!err)
+		return;
+
+report:
+	report_usercopy(ptr, n, to_user, err);
+}
+EXPORT_SYMBOL(__check_object_size);
diff --git a/mm/util.c b/mm/util.c
index 9af1c12..d5259b6 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -199,36 +199,11 @@
 }
 
 /* Check if the vma is being used as a stack by this task */
-static int vm_is_stack_for_task(struct task_struct *t,
-				struct vm_area_struct *vma)
+int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t)
 {
 	return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
 }
 
-/*
- * Check if the vma is being used as a stack.
- * If is_group is non-zero, check in the entire thread group or else
- * just check in the current task. Returns the task_struct of the task
- * that the vma is stack for. Must be called under rcu_read_lock().
- */
-struct task_struct *task_of_stack(struct task_struct *task,
-				struct vm_area_struct *vma, bool in_group)
-{
-	if (vm_is_stack_for_task(task, vma))
-		return task;
-
-	if (in_group) {
-		struct task_struct *t;
-
-		for_each_thread(task, t) {
-			if (vm_is_stack_for_task(t, vma))
-				return t;
-		}
-	}
-
-	return NULL;
-}
-
 #if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT)
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
diff --git a/mm/vmpressure.c b/mm/vmpressure.c
index c5afd57..3fb15c2 100644
--- a/mm/vmpressure.c
+++ b/mm/vmpressure.c
@@ -112,9 +112,16 @@
 						    unsigned long reclaimed)
 {
 	unsigned long scale = scanned + reclaimed;
-	unsigned long pressure;
+	unsigned long pressure = 0;
 
 	/*
+	 * reclaimed can be greater than scanned in cases
+	 * like THP, where the scanned is 1 and reclaimed
+	 * could be 512
+	 */
+	if (reclaimed >= scanned)
+		goto out;
+	/*
 	 * We calculate the ratio (in percents) of how many pages were
 	 * scanned vs. reclaimed in a given time frame (window). Note that
 	 * time is in VM reclaimer's "ticks", i.e. number of pages
@@ -124,6 +131,7 @@
 	pressure = scale - (reclaimed * scale / scanned);
 	pressure = pressure * 100 / scale;
 
+out:
 	pr_debug("%s: %3lu  (s: %lu  r: %lu)\n", __func__, pressure,
 		 scanned, reclaimed);
 
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 0c114e2..440c2df 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -277,6 +277,7 @@
 	int nid = shrinkctl->nid;
 	long batch_size = shrinker->batch ? shrinker->batch
 					  : SHRINK_BATCH;
+	long scanned = 0, next_deferred;
 
 	freeable = shrinker->count_objects(shrinker, shrinkctl);
 	if (freeable == 0)
@@ -298,7 +299,9 @@
 		pr_err("shrink_slab: %pF negative objects to delete nr=%ld\n",
 		       shrinker->scan_objects, total_scan);
 		total_scan = freeable;
-	}
+		next_deferred = nr;
+	} else
+		next_deferred = total_scan;
 
 	/*
 	 * We need to avoid excessive windup on filesystem shrinkers
@@ -355,17 +358,22 @@
 
 		count_vm_events(SLABS_SCANNED, nr_to_scan);
 		total_scan -= nr_to_scan;
+		scanned += nr_to_scan;
 
 		cond_resched();
 	}
 
+	if (next_deferred >= scanned)
+		next_deferred -= scanned;
+	else
+		next_deferred = 0;
 	/*
 	 * move the unused scan count back into the shrinker in a
 	 * manner that handles concurrent updates. If we exhausted the
 	 * scan, there is no need to do an update.
 	 */
-	if (total_scan > 0)
-		new_nr = atomic_long_add_return(total_scan,
+	if (next_deferred > 0)
+		new_nr = atomic_long_add_return(next_deferred,
 						&shrinker->nr_deferred[nid]);
 	else
 		new_nr = atomic_long_read(&shrinker->nr_deferred[nid]);
@@ -2159,23 +2167,6 @@
 	}
 }
 
-#ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
-static void init_tlb_ubc(void)
-{
-	/*
-	 * This deliberately does not clear the cpumask as it's expensive
-	 * and unnecessary. If there happens to be data in there then the
-	 * first SWAP_CLUSTER_MAX pages will send an unnecessary IPI and
-	 * then will be cleared.
-	 */
-	current->tlb_ubc.flush_required = false;
-}
-#else
-static inline void init_tlb_ubc(void)
-{
-}
-#endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */
-
 /*
  * This is a basic per-zone page freer.  Used by both kswapd and direct reclaim.
  */
@@ -2210,8 +2201,6 @@
 	scan_adjusted = (global_reclaim(sc) && !current_is_kswapd() &&
 			 sc->priority == DEF_PRIORITY);
 
-	init_tlb_ubc();
-
 	blk_start_plug(&plug);
 	while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||
 					nr[LRU_INACTIVE_FILE]) {
@@ -2540,7 +2529,7 @@
 		if (!populated_zone(zone))
 			continue;
 
-		classzone_idx = requested_highidx;
+		classzone_idx = gfp_zone(sc->gfp_mask);
 		while (!populated_zone(zone->zone_pgdat->node_zones +
 							classzone_idx))
 			classzone_idx--;
@@ -2929,7 +2918,9 @@
 					    sc.may_writepage,
 					    sc.gfp_mask);
 
+	current->flags |= PF_MEMALLOC;
 	nr_reclaimed = do_try_to_free_pages(zonelist, &sc);
+	current->flags &= ~PF_MEMALLOC;
 
 	trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed);
 
diff --git a/mm/vmstat.c b/mm/vmstat.c
index c54fd29..83a003b 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -460,7 +460,7 @@
  *
  * The function returns the number of global counters updated.
  */
-static int refresh_cpu_vm_stats(void)
+static int refresh_cpu_vm_stats(bool do_pagesets)
 {
 	struct zone *zone;
 	int i;
@@ -484,33 +484,35 @@
 #endif
 			}
 		}
-		cond_resched();
 #ifdef CONFIG_NUMA
-		/*
-		 * Deal with draining the remote pageset of this
-		 * processor
-		 *
-		 * Check if there are pages remaining in this pageset
-		 * if not then there is nothing to expire.
-		 */
-		if (!__this_cpu_read(p->expire) ||
+		if (do_pagesets) {
+			cond_resched();
+			/*
+			 * Deal with draining the remote pageset of this
+			 * processor
+			 *
+			 * Check if there are pages remaining in this pageset
+			 * if not then there is nothing to expire.
+			 */
+			if (!__this_cpu_read(p->expire) ||
 			       !__this_cpu_read(p->pcp.count))
-			continue;
+				continue;
 
-		/*
-		 * We never drain zones local to this processor.
-		 */
-		if (zone_to_nid(zone) == numa_node_id()) {
-			__this_cpu_write(p->expire, 0);
-			continue;
-		}
+			/*
+			 * We never drain zones local to this processor.
+			 */
+			if (zone_to_nid(zone) == numa_node_id()) {
+				__this_cpu_write(p->expire, 0);
+				continue;
+			}
 
-		if (__this_cpu_dec_return(p->expire))
-			continue;
+			if (__this_cpu_dec_return(p->expire))
+				continue;
 
-		if (__this_cpu_read(p->pcp.count)) {
-			drain_zone_pages(zone, this_cpu_ptr(&p->pcp));
-			changes++;
+			if (__this_cpu_read(p->pcp.count)) {
+				drain_zone_pages(zone, this_cpu_ptr(&p->pcp));
+				changes++;
+			}
 		}
 #endif
 	}
@@ -1386,7 +1388,7 @@
 
 static void vmstat_update(struct work_struct *w)
 {
-	if (refresh_cpu_vm_stats()) {
+	if (refresh_cpu_vm_stats(true)) {
 		/*
 		 * Counters were updated so we expect more updates
 		 * to occur in the future. Keep on running the
@@ -1418,6 +1420,23 @@
 }
 
 /*
+ * Switch off vmstat processing and then fold all the remaining differentials
+ * until the diffs stay at zero. The function is used by NOHZ and can only be
+ * invoked when tick processing is not active.
+ */
+void quiet_vmstat(void)
+{
+	if (system_state != SYSTEM_RUNNING)
+		return;
+
+	do {
+		if (!cpumask_test_and_set_cpu(smp_processor_id(), cpu_stat_off))
+			cancel_delayed_work(this_cpu_ptr(&vmstat_work));
+
+	} while (refresh_cpu_vm_stats(false));
+}
+
+/*
  * Check if the diffs for a certain cpu indicate that
  * an update is needed.
  */
@@ -1449,7 +1468,7 @@
  */
 static void vmstat_shepherd(struct work_struct *w);
 
-static DECLARE_DELAYED_WORK(shepherd, vmstat_shepherd);
+static DECLARE_DEFERRABLE_WORK(shepherd, vmstat_shepherd);
 
 static void vmstat_shepherd(struct work_struct *w)
 {
diff --git a/mm/workingset.c b/mm/workingset.c
index aa01713..df66f42 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -341,21 +341,19 @@
 	 * no pages, so we expect to be able to remove them all and
 	 * delete and free the empty node afterwards.
 	 */
-
-	BUG_ON(!node->count);
-	BUG_ON(node->count & RADIX_TREE_COUNT_MASK);
+	BUG_ON(!workingset_node_shadows(node));
+	BUG_ON(workingset_node_pages(node));
 
 	for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) {
 		if (node->slots[i]) {
 			BUG_ON(!radix_tree_exceptional_entry(node->slots[i]));
 			node->slots[i] = NULL;
-			BUG_ON(node->count < (1U << RADIX_TREE_COUNT_SHIFT));
-			node->count -= 1U << RADIX_TREE_COUNT_SHIFT;
+			workingset_node_shadows_dec(node);
 			BUG_ON(!mapping->nrshadows);
 			mapping->nrshadows--;
 		}
 	}
-	BUG_ON(node->count);
+	BUG_ON(workingset_node_shadows(node));
 	inc_zone_state(page_zone(virt_to_page(node)), WORKINGSET_NODERECLAIM);
 	if (!__radix_tree_delete_node(&mapping->page_tree, node))
 		BUG();
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index fc08399..c1ea194 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -1732,10 +1732,13 @@
 static unsigned long zs_can_compact(struct size_class *class)
 {
 	unsigned long obj_wasted;
+	unsigned long obj_allocated = zs_stat_get(class, OBJ_ALLOCATED);
+	unsigned long obj_used = zs_stat_get(class, OBJ_USED);
 
-	obj_wasted = zs_stat_get(class, OBJ_ALLOCATED) -
-		zs_stat_get(class, OBJ_USED);
+	if (obj_allocated <= obj_used)
+		return 0;
 
+	obj_wasted = obj_allocated - obj_used;
 	obj_wasted /= get_maxobj_per_zspage(class->size,
 			class->pages_per_zspage);
 
diff --git a/mm/zswap.c b/mm/zswap.c
index 3402619..45476f4 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -78,7 +78,13 @@
 
 /* Enable/disable zswap (disabled by default) */
 static bool zswap_enabled;
-module_param_named(enabled, zswap_enabled, bool, 0644);
+static int zswap_enabled_param_set(const char *,
+				   const struct kernel_param *);
+static struct kernel_param_ops zswap_enabled_param_ops = {
+	.set =		zswap_enabled_param_set,
+	.get =		param_get_bool,
+};
+module_param_cb(enabled, &zswap_enabled_param_ops, &zswap_enabled, 0644);
 
 /* Crypto compressor to use */
 #define ZSWAP_COMPRESSOR_DEFAULT "lzo"
@@ -176,6 +182,9 @@
 /* used by param callback function */
 static bool zswap_init_started;
 
+/* fatal error during init */
+static bool zswap_init_failed;
+
 /*********************************
 * helpers and fwd declarations
 **********************************/
@@ -702,6 +711,11 @@
 	char *s = strstrip((char *)val);
 	int ret;
 
+	if (zswap_init_failed) {
+		pr_err("can't set param, initialization failed\n");
+		return -ENODEV;
+	}
+
 	/* no change required */
 	if (!strcmp(s, *(char **)kp->arg))
 		return 0;
@@ -781,6 +795,17 @@
 	return __zswap_param_set(val, kp, NULL, zswap_compressor);
 }
 
+static int zswap_enabled_param_set(const char *val,
+				   const struct kernel_param *kp)
+{
+	if (zswap_init_failed) {
+		pr_err("can't enable, initialization failed\n");
+		return -ENODEV;
+	}
+
+	return param_set_bool(val, kp);
+}
+
 /*********************************
 * writeback code
 **********************************/
@@ -1267,6 +1292,9 @@
 dstmem_fail:
 	zswap_entry_cache_destroy();
 cache_fail:
+	/* if built-in, we aren't unloaded on failure; don't allow use */
+	zswap_init_failed = true;
+	zswap_enabled = false;
 	return -ENOMEM;
 }
 /* must be late so crypto has time to come up */
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index d2cd9de..e20ae2d 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -278,7 +278,8 @@
 	return 0;
 
 out_free_newdev:
-	free_netdev(new_dev);
+	if (new_dev->reg_state == NETREG_UNINITIALIZED)
+		free_netdev(new_dev);
 	return err;
 }
 
@@ -659,7 +660,7 @@
 
 	skb_gro_pull(skb, sizeof(*vhdr));
 	skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr));
-	pp = ptype->callbacks.gro_receive(head, skb);
+	pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
 
 out_unlock:
 	rcu_read_unlock();
diff --git a/net/9p/client.c b/net/9p/client.c
index ea79ee9..f5feac4 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -2101,6 +2101,10 @@
 		trace_9p_protocol_dump(clnt, req->rc);
 		goto free_and_error;
 	}
+	if (rsize < count) {
+		pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize);
+		count = rsize;
+	}
 
 	p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
 
diff --git a/net/Kconfig b/net/Kconfig
index 127da94..ce9585c 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -86,6 +86,12 @@
 
 endif # if INET
 
+config ANDROID_PARANOID_NETWORK
+	bool "Only allow certain groups to create sockets"
+	default y
+	help
+		none
+
 config NETWORK_SECMARK
 	bool "Security Marking"
 	help
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index fbd0acf..2fdebab 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -976,7 +976,8 @@
 			release_sock(sk);
 			ax25_disconnect(ax25, 0);
 			lock_sock(sk);
-			ax25_destroy_socket(ax25);
+			if (!sock_flag(ax25->sk, SOCK_DESTROY))
+				ax25_destroy_socket(ax25);
 			break;
 
 		case AX25_STATE_3:
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index 951cd57..5237dff 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -102,6 +102,7 @@
 	switch (ax25->state) {
 
 	case AX25_STATE_0:
+	case AX25_STATE_2:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
 		if (!sk || sock_flag(sk, SOCK_DESTROY) ||
@@ -111,6 +112,7 @@
 				sock_hold(sk);
 				ax25_destroy_socket(ax25);
 				bh_unlock_sock(sk);
+				/* Ungrab socket and destroy it */
 				sock_put(sk);
 			} else
 				ax25_destroy_socket(ax25);
@@ -213,7 +215,8 @@
 	case AX25_STATE_2:
 		if (ax25->n2count == ax25->n2) {
 			ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
-			ax25_disconnect(ax25, ETIMEDOUT);
+			if (!sock_flag(ax25->sk, SOCK_DESTROY))
+				ax25_disconnect(ax25, ETIMEDOUT);
 			return;
 		} else {
 			ax25->n2count++;
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
index 004467c..2c0d6ef 100644
--- a/net/ax25/ax25_std_timer.c
+++ b/net/ax25/ax25_std_timer.c
@@ -38,6 +38,7 @@
 
 	switch (ax25->state) {
 	case AX25_STATE_0:
+	case AX25_STATE_2:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
 		if (!sk || sock_flag(sk, SOCK_DESTROY) ||
@@ -47,6 +48,7 @@
 				sock_hold(sk);
 				ax25_destroy_socket(ax25);
 				bh_unlock_sock(sk);
+				/* Ungrab socket and destroy it */
 				sock_put(sk);
 			} else
 				ax25_destroy_socket(ax25);
@@ -144,7 +146,8 @@
 	case AX25_STATE_2:
 		if (ax25->n2count == ax25->n2) {
 			ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
-			ax25_disconnect(ax25, ETIMEDOUT);
+			if (!sock_flag(ax25->sk, SOCK_DESTROY))
+				ax25_disconnect(ax25, ETIMEDOUT);
 			return;
 		} else {
 			ax25->n2count++;
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index 3b78e84..983f0b5 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -264,7 +264,8 @@
 {
 	ax25_clear_queues(ax25);
 
-	ax25_stop_heartbeat(ax25);
+	if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
+		ax25_stop_heartbeat(ax25);
 	ax25_stop_t1timer(ax25);
 	ax25_stop_t2timer(ax25);
 	ax25_stop_t3timer(ax25);
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 17851d3..6282f02 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -197,18 +197,12 @@
 {
 	struct hlist_node *node_tmp;
 	struct batadv_neigh_ifinfo *neigh_ifinfo;
-	struct batadv_algo_ops *bao;
-
-	bao = neigh_node->orig_node->bat_priv->bat_algo_ops;
 
 	hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
 				  &neigh_node->ifinfo_list, list) {
 		batadv_neigh_ifinfo_free_ref(neigh_ifinfo);
 	}
 
-	if (bao->bat_neigh_free)
-		bao->bat_neigh_free(neigh_node);
-
 	batadv_hardif_free_ref(neigh_node->if_incoming);
 
 	kfree_rcu(neigh_node, rcu);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 83b0ca2..f2079ac 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -2764,7 +2764,7 @@
 							     &tvlv_tt_data,
 							     &tt_change,
 							     &tt_len);
-		if (!tt_len)
+		if (!tt_len || !tvlv_len)
 			goto unlock;
 
 		/* Copy the last orig_node's OGM buffer */
@@ -2782,7 +2782,7 @@
 							     &tvlv_tt_data,
 							     &tt_change,
 							     &tt_len);
-		if (!tt_len)
+		if (!tt_len || !tvlv_len)
 			goto out;
 
 		/* fill the rest of the tvlv with the real TT entries */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index d260efd..cbd347c 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1136,8 +1136,6 @@
  * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or better
  *  than neigh2 for their respective outgoing interface from the metric
  *  prospective
- * @bat_neigh_free: free the resources allocated by the routing algorithm for a
- *  neigh_node object
  * @bat_orig_print: print the originator table (optional)
  * @bat_orig_free: free the resources allocated by the routing algorithm for an
  *  orig_node object
@@ -1165,7 +1163,6 @@
 		 struct batadv_hard_iface *if_outgoing1,
 		 struct batadv_neigh_node *neigh2,
 		 struct batadv_hard_iface *if_outgoing2);
-	void (*bat_neigh_free)(struct batadv_neigh_node *neigh);
 	/* orig_node handling API */
 	void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq,
 			       struct batadv_hard_iface *hard_iface);
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 70306cc..709ce9f 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -106,11 +106,40 @@
 }
 EXPORT_SYMBOL(bt_sock_unregister);
 
+#ifdef CONFIG_PARANOID_NETWORK
+static inline int current_has_bt_admin(void)
+{
+	return !current_euid();
+}
+
+static inline int current_has_bt(void)
+{
+	return current_has_bt_admin();
+}
+# else
+static inline int current_has_bt_admin(void)
+{
+	return 1;
+}
+
+static inline int current_has_bt(void)
+{
+	return 1;
+}
+#endif
+
 static int bt_sock_create(struct net *net, struct socket *sock, int proto,
 			  int kern)
 {
 	int err;
 
+	if (proto == BTPROTO_RFCOMM || proto == BTPROTO_SCO ||
+			proto == BTPROTO_L2CAP) {
+		if (!current_has_bt())
+			return -EPERM;
+	} else if (!current_has_bt_admin())
+		return -EPERM;
+
 	if (net != &init_net)
 		return -EAFNOSUPPORT;
 
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index b1eb8c0..c842f40 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -1164,7 +1164,8 @@
 	if (msg->msg_flags & MSG_OOB)
 		return -EOPNOTSUPP;
 
-	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
+	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE|
+			       MSG_CMSG_COMPAT))
 		return -EINVAL;
 
 	if (len < 4 || len > HCI_MAX_FRAME_SIZE)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 1bb5515..d9bbbde 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -927,7 +927,7 @@
 			break;
 		}
 
-		if (get_user(opt, (u32 __user *) optval)) {
+		if (get_user(opt, (u16 __user *) optval)) {
 			err = -EFAULT;
 			break;
 		}
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index a642bb8..09442e0 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -278,6 +278,8 @@
 	 * change from under us.
 	 */
 	list_for_each_entry(v, &vg->vlan_list, vlist) {
+		if (!br_vlan_should_use(v))
+			continue;
 		f = __br_fdb_get(br, br->dev->dev_addr, v->vid);
 		if (f && f->is_local && !f->dst)
 			fdb_delete_local(br, NULL, f);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index f7fba74..e24754a 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -29,6 +29,7 @@
 static int
 br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+	br_drop_fake_rtable(skb);
 	return netif_receive_skb(skb);
 }
 
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 263b4de..60a3dbf 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -21,18 +21,19 @@
 #include <asm/uaccess.h>
 #include "br_private.h"
 
-/* called with RTNL */
 static int get_bridge_ifindices(struct net *net, int *indices, int num)
 {
 	struct net_device *dev;
 	int i = 0;
 
-	for_each_netdev(net, dev) {
+	rcu_read_lock();
+	for_each_netdev_rcu(net, dev) {
 		if (i >= num)
 			break;
 		if (dev->priv_flags & IFF_EBRIDGE)
 			indices[i++] = dev->ifindex;
 	}
+	rcu_read_unlock();
 
 	return i;
 }
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 03661d9..d80c15d 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -464,8 +464,11 @@
 	if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
 			       &ip6h->saddr)) {
 		kfree_skb(skb);
+		br->has_ipv6_addr = 0;
 		return NULL;
 	}
+
+	br->has_ipv6_addr = 1;
 	ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
 
 	hopopt = (u8 *)(ip6h + 1);
@@ -948,13 +951,12 @@
 		mod_timer(&query->timer, jiffies);
 }
 
-void br_multicast_enable_port(struct net_bridge_port *port)
+static void __br_multicast_enable_port(struct net_bridge_port *port)
 {
 	struct net_bridge *br = port->br;
 
-	spin_lock(&br->multicast_lock);
 	if (br->multicast_disabled || !netif_running(br->dev))
-		goto out;
+		return;
 
 	br_multicast_enable(&port->ip4_own_query);
 #if IS_ENABLED(CONFIG_IPV6)
@@ -962,8 +964,14 @@
 #endif
 	if (port->multicast_router == 2 && hlist_unhashed(&port->rlist))
 		br_multicast_add_router(br, port);
+}
 
-out:
+void br_multicast_enable_port(struct net_bridge_port *port)
+{
+	struct net_bridge *br = port->br;
+
+	spin_lock(&br->multicast_lock);
+	__br_multicast_enable_port(port);
 	spin_unlock(&br->multicast_lock);
 }
 
@@ -1110,7 +1118,7 @@
 		} else {
 			err = br_ip6_multicast_add_group(br, port,
 							 &grec->grec_mca, vid);
-			if (!err)
+			if (err)
 				break;
 		}
 	}
@@ -1270,6 +1278,7 @@
 	struct br_ip saddr;
 	unsigned long max_delay;
 	unsigned long now = jiffies;
+	unsigned int offset = skb_transport_offset(skb);
 	__be32 group;
 	int err = 0;
 
@@ -1280,14 +1289,14 @@
 
 	group = ih->group;
 
-	if (skb->len == sizeof(*ih)) {
+	if (skb->len == offset + sizeof(*ih)) {
 		max_delay = ih->code * (HZ / IGMP_TIMER_SCALE);
 
 		if (!max_delay) {
 			max_delay = 10 * HZ;
 			group = 0;
 		}
-	} else if (skb->len >= sizeof(*ih3)) {
+	} else if (skb->len >= offset + sizeof(*ih3)) {
 		ih3 = igmpv3_query_hdr(skb);
 		if (ih3->nsrcs)
 			goto out;
@@ -1348,6 +1357,7 @@
 	struct br_ip saddr;
 	unsigned long max_delay;
 	unsigned long now = jiffies;
+	unsigned int offset = skb_transport_offset(skb);
 	const struct in6_addr *group = NULL;
 	bool is_general_query;
 	int err = 0;
@@ -1357,8 +1367,8 @@
 	    (port && port->state == BR_STATE_DISABLED))
 		goto out;
 
-	if (skb->len == sizeof(*mld)) {
-		if (!pskb_may_pull(skb, sizeof(*mld))) {
+	if (skb->len == offset + sizeof(*mld)) {
+		if (!pskb_may_pull(skb, offset + sizeof(*mld))) {
 			err = -EINVAL;
 			goto out;
 		}
@@ -1367,7 +1377,7 @@
 		if (max_delay)
 			group = &mld->mld_mca;
 	} else {
-		if (!pskb_may_pull(skb, sizeof(*mld2q))) {
+		if (!pskb_may_pull(skb, offset + sizeof(*mld2q))) {
 			err = -EINVAL;
 			goto out;
 		}
@@ -1734,6 +1744,7 @@
 	br->ip6_other_query.delay_time = 0;
 	br->ip6_querier.port = NULL;
 #endif
+	br->has_ipv6_addr = 1;
 
 	spin_lock_init(&br->multicast_lock);
 	setup_timer(&br->multicast_router_timer,
@@ -1899,8 +1910,9 @@
 
 int br_multicast_toggle(struct net_bridge *br, unsigned long val)
 {
-	int err = 0;
 	struct net_bridge_mdb_htable *mdb;
+	struct net_bridge_port *port;
+	int err = 0;
 
 	spin_lock_bh(&br->multicast_lock);
 	if (br->multicast_disabled == !val)
@@ -1928,10 +1940,9 @@
 			goto rollback;
 	}
 
-	br_multicast_start_querier(br, &br->ip4_own_query);
-#if IS_ENABLED(CONFIG_IPV6)
-	br_multicast_start_querier(br, &br->ip6_own_query);
-#endif
+	br_multicast_open(br);
+	list_for_each_entry(port, &br->port_list, list)
+		__br_multicast_enable_port(port);
 
 unlock:
 	spin_unlock_bh(&br->multicast_lock);
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 7ddbe7e..97fc19f 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -516,21 +516,6 @@
 }
 
 
-/* PF_BRIDGE/LOCAL_IN ************************************************/
-/* The packet is locally destined, which requires a real
- * dst_entry, so detach the fake one.  On the way up, the
- * packet would pass through PRE_ROUTING again (which already
- * took place when the packet entered the bridge), but we
- * register an IPv4 PRE_ROUTING 'sabotage' hook that will
- * prevent this from happening. */
-static unsigned int br_nf_local_in(void *priv,
-				   struct sk_buff *skb,
-				   const struct nf_hook_state *state)
-{
-	br_drop_fake_rtable(skb);
-	return NF_ACCEPT;
-}
-
 /* PF_BRIDGE/FORWARD *************************************************/
 static int br_nf_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
@@ -901,12 +886,6 @@
 		.priority = NF_BR_PRI_BRNF,
 	},
 	{
-		.hook = br_nf_local_in,
-		.pf = NFPROTO_BRIDGE,
-		.hooknum = NF_BR_LOCAL_IN,
-		.priority = NF_BR_PRI_BRNF,
-	},
-	{
 		.hook = br_nf_forward_ip,
 		.pf = NFPROTO_BRIDGE,
 		.hooknum = NF_BR_FORWARD,
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 40197ff..ff8bb41 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -768,25 +768,18 @@
 			return -EPROTONOSUPPORT;
 		}
 	}
+
+	if (data[IFLA_BR_VLAN_DEFAULT_PVID]) {
+		__u16 defpvid = nla_get_u16(data[IFLA_BR_VLAN_DEFAULT_PVID]);
+
+		if (defpvid >= VLAN_VID_MASK)
+			return -EINVAL;
+	}
 #endif
 
 	return 0;
 }
 
-static int br_dev_newlink(struct net *src_net, struct net_device *dev,
-			  struct nlattr *tb[], struct nlattr *data[])
-{
-	struct net_bridge *br = netdev_priv(dev);
-
-	if (tb[IFLA_ADDRESS]) {
-		spin_lock_bh(&br->lock);
-		br_stp_change_bridge_id(br, nla_data(tb[IFLA_ADDRESS]));
-		spin_unlock_bh(&br->lock);
-	}
-
-	return register_netdevice(dev);
-}
-
 static int br_port_slave_changelink(struct net_device *brdev,
 				    struct net_device *dev,
 				    struct nlattr *tb[],
@@ -1068,6 +1061,25 @@
 	return 0;
 }
 
+static int br_dev_newlink(struct net *src_net, struct net_device *dev,
+			  struct nlattr *tb[], struct nlattr *data[])
+{
+	struct net_bridge *br = netdev_priv(dev);
+	int err;
+
+	if (tb[IFLA_ADDRESS]) {
+		spin_lock_bh(&br->lock);
+		br_stp_change_bridge_id(br, nla_data(tb[IFLA_ADDRESS]));
+		spin_unlock_bh(&br->lock);
+	}
+
+	err = br_changelink(dev, tb, data);
+	if (err)
+		return err;
+
+	return register_netdevice(dev);
+}
+
 static size_t br_get_size(const struct net_device *brdev)
 {
 	return nla_total_size(sizeof(u32)) +	/* IFLA_BR_FORWARD_DELAY  */
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 216018c..1001a1b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -301,6 +301,7 @@
 	u8				multicast_disabled:1;
 	u8				multicast_querier:1;
 	u8				multicast_query_use_ifaddr:1;
+	u8				has_ipv6_addr:1;
 
 	u32				hash_elasticity;
 	u32				hash_max;
@@ -574,10 +575,22 @@
 
 static inline bool
 __br_multicast_querier_exists(struct net_bridge *br,
-			      struct bridge_mcast_other_query *querier)
+				struct bridge_mcast_other_query *querier,
+				const bool is_ipv6)
 {
+	bool own_querier_enabled;
+
+	if (br->multicast_querier) {
+		if (is_ipv6 && !br->has_ipv6_addr)
+			own_querier_enabled = false;
+		else
+			own_querier_enabled = true;
+	} else {
+		own_querier_enabled = false;
+	}
+
 	return time_is_before_jiffies(querier->delay_time) &&
-	       (br->multicast_querier || timer_pending(&querier->timer));
+	       (own_querier_enabled || timer_pending(&querier->timer));
 }
 
 static inline bool br_multicast_querier_exists(struct net_bridge *br,
@@ -585,10 +598,12 @@
 {
 	switch (eth->h_proto) {
 	case (htons(ETH_P_IP)):
-		return __br_multicast_querier_exists(br, &br->ip4_other_query);
+		return __br_multicast_querier_exists(br,
+			&br->ip4_other_query, false);
 #if IS_ENABLED(CONFIG_IPV6)
 	case (htons(ETH_P_IPV6)):
-		return __br_multicast_querier_exists(br, &br->ip6_other_query);
+		return __br_multicast_querier_exists(br,
+			&br->ip6_other_query, true);
 #endif
 	default:
 		return false;
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 8a7ada8..bcb4559 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -166,6 +166,8 @@
 		br_debug(br, "using kernel STP\n");
 
 		/* To start timers on any ports left in blocking */
+		if (br->dev->flags & IFF_UP)
+			mod_timer(&br->hello_timer, jiffies + br->hello_time);
 		br_port_state_selection(br);
 	}
 
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 5f0f5af..7dbe6a5 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -40,7 +40,7 @@
 	if (br->dev->flags & IFF_UP) {
 		br_config_bpdu_generation(br);
 
-		if (br->stp_enabled != BR_USER_STP)
+		if (br->stp_enabled == BR_KERNEL_STP)
 			mod_timer(&br->hello_timer,
 				  round_jiffies(jiffies + br->hello_time));
 	}
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c
index f6c3b21..71b6ab2 100644
--- a/net/caif/cfpkt_skbuff.c
+++ b/net/caif/cfpkt_skbuff.c
@@ -81,11 +81,7 @@
 {
 	struct sk_buff *skb;
 
-	if (likely(in_interrupt()))
-		skb = alloc_skb(len + pfx, GFP_ATOMIC);
-	else
-		skb = alloc_skb(len + pfx, GFP_KERNEL);
-
+	skb = alloc_skb(len + pfx, GFP_ATOMIC);
 	if (unlikely(skb == NULL))
 		return NULL;
 
@@ -286,7 +282,7 @@
 		else
 			skb_trim(skb, len);
 
-			return cfpkt_getlen(pkt);
+		return cfpkt_getlen(pkt);
 	}
 
 	/* Need to expand SKB */
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 166d436..928f580 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -445,6 +445,7 @@
  * @func: callback function on filter match
  * @data: returned parameter for callback function
  * @ident: string for calling module identification
+ * @sk: socket pointer (might be NULL)
  *
  * Description:
  *  Invokes the callback function with the received sk_buff and the given
@@ -468,7 +469,7 @@
  */
 int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
 		    void (*func)(struct sk_buff *, void *), void *data,
-		    char *ident)
+		    char *ident, struct sock *sk)
 {
 	struct receiver *r;
 	struct hlist_head *rl;
@@ -496,6 +497,7 @@
 		r->func    = func;
 		r->data    = data;
 		r->ident   = ident;
+		r->sk      = sk;
 
 		hlist_add_head_rcu(&r->list, rl);
 		d->entries++;
@@ -520,8 +522,11 @@
 static void can_rx_delete_receiver(struct rcu_head *rp)
 {
 	struct receiver *r = container_of(rp, struct receiver, rcu);
+	struct sock *sk = r->sk;
 
 	kmem_cache_free(rcv_cache, r);
+	if (sk)
+		sock_put(sk);
 }
 
 /**
@@ -596,8 +601,11 @@
 	spin_unlock(&can_rcvlists_lock);
 
 	/* schedule the receiver item for deletion */
-	if (r)
+	if (r) {
+		if (r->sk)
+			sock_hold(r->sk);
 		call_rcu(&r->rcu, can_rx_delete_receiver);
+	}
 }
 EXPORT_SYMBOL(can_rx_unregister);
 
diff --git a/net/can/af_can.h b/net/can/af_can.h
index fca0fe9..b86f512 100644
--- a/net/can/af_can.h
+++ b/net/can/af_can.h
@@ -50,13 +50,14 @@
 
 struct receiver {
 	struct hlist_node list;
-	struct rcu_head rcu;
 	canid_t can_id;
 	canid_t mask;
 	unsigned long matches;
 	void (*func)(struct sk_buff *, void *);
 	void *data;
 	char *ident;
+	struct sock *sk;
+	struct rcu_head rcu;
 };
 
 #define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 6863310..4ccfd35 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -710,14 +710,23 @@
 
 static void bcm_remove_op(struct bcm_op *op)
 {
-	hrtimer_cancel(&op->timer);
-	hrtimer_cancel(&op->thrtimer);
+	if (op->tsklet.func) {
+		while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) ||
+		       test_bit(TASKLET_STATE_RUN, &op->tsklet.state) ||
+		       hrtimer_active(&op->timer)) {
+			hrtimer_cancel(&op->timer);
+			tasklet_kill(&op->tsklet);
+		}
+	}
 
-	if (op->tsklet.func)
-		tasklet_kill(&op->tsklet);
-
-	if (op->thrtsklet.func)
-		tasklet_kill(&op->thrtsklet);
+	if (op->thrtsklet.func) {
+		while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) ||
+		       test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) ||
+		       hrtimer_active(&op->thrtimer)) {
+			hrtimer_cancel(&op->thrtimer);
+			tasklet_kill(&op->thrtsklet);
+		}
+	}
 
 	if ((op->frames) && (op->frames != &op->sframe))
 		kfree(op->frames);
@@ -1170,7 +1179,7 @@
 				err = can_rx_register(dev, op->can_id,
 						      REGMASK(op->can_id),
 						      bcm_rx_handler, op,
-						      "bcm");
+						      "bcm", sk);
 
 				op->rx_reg_dev = dev;
 				dev_put(dev);
@@ -1179,7 +1188,7 @@
 		} else
 			err = can_rx_register(NULL, op->can_id,
 					      REGMASK(op->can_id),
-					      bcm_rx_handler, op, "bcm");
+					      bcm_rx_handler, op, "bcm", sk);
 		if (err) {
 			/* this bcm rx op is broken -> remove it */
 			list_del(&op->list);
@@ -1500,24 +1509,31 @@
 	struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
 	struct sock *sk = sock->sk;
 	struct bcm_sock *bo = bcm_sk(sk);
+	int ret = 0;
 
 	if (len < sizeof(*addr))
 		return -EINVAL;
 
-	if (bo->bound)
-		return -EISCONN;
+	lock_sock(sk);
+
+	if (bo->bound) {
+		ret = -EISCONN;
+		goto fail;
+	}
 
 	/* bind a device to this socket */
 	if (addr->can_ifindex) {
 		struct net_device *dev;
 
 		dev = dev_get_by_index(&init_net, addr->can_ifindex);
-		if (!dev)
-			return -ENODEV;
-
+		if (!dev) {
+			ret = -ENODEV;
+			goto fail;
+		}
 		if (dev->type != ARPHRD_CAN) {
 			dev_put(dev);
-			return -ENODEV;
+			ret = -ENODEV;
+			goto fail;
 		}
 
 		bo->ifindex = dev->ifindex;
@@ -1528,17 +1544,24 @@
 		bo->ifindex = 0;
 	}
 
-	bo->bound = 1;
-
 	if (proc_dir) {
 		/* unique socket address as filename */
 		sprintf(bo->procname, "%lu", sock_i_ino(sk));
 		bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
 						     proc_dir,
 						     &bcm_proc_fops, sk);
+		if (!bo->bcm_proc_read) {
+			ret = -ENOMEM;
+			goto fail;
+		}
 	}
 
-	return 0;
+	bo->bound = 1;
+
+fail:
+	release_sock(sk);
+
+	return ret;
 }
 
 static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
diff --git a/net/can/gw.c b/net/can/gw.c
index 4551687..77c8af4 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -442,7 +442,7 @@
 {
 	return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
 			       gwj->ccgw.filter.can_mask, can_can_gw_rcv,
-			       gwj, "gw");
+			       gwj, "gw", NULL);
 }
 
 static inline void cgw_unregister_filter(struct cgw_job *gwj)
diff --git a/net/can/raw.c b/net/can/raw.c
index 2e67b14..e9403a2 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -190,7 +190,7 @@
 	for (i = 0; i < count; i++) {
 		err = can_rx_register(dev, filter[i].can_id,
 				      filter[i].can_mask,
-				      raw_rcv, sk, "raw");
+				      raw_rcv, sk, "raw", sk);
 		if (err) {
 			/* clean up successfully registered filters */
 			while (--i >= 0)
@@ -211,7 +211,7 @@
 
 	if (err_mask)
 		err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG,
-				      raw_rcv, sk, "raw");
+				      raw_rcv, sk, "raw", sk);
 
 	return err;
 }
@@ -499,6 +499,9 @@
 		if (optlen % sizeof(struct can_filter) != 0)
 			return -EINVAL;
 
+		if (optlen > CAN_RAW_FILTER_MAX * sizeof(struct can_filter))
+			return -EINVAL;
+
 		count = optlen / sizeof(struct can_filter);
 
 		if (count > 1) {
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index 63ae5dd..a6b2f21 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -7,6 +7,7 @@
 #include <linux/kthread.h>
 #include <linux/net.h>
 #include <linux/nsproxy.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/socket.h>
 #include <linux/string.h>
@@ -478,11 +479,16 @@
 {
 	struct sockaddr_storage *paddr = &con->peer_addr.in_addr;
 	struct socket *sock;
+	unsigned int noio_flag;
 	int ret;
 
 	BUG_ON(con->sock);
+
+	/* sock_create_kern() allocates with GFP_KERNEL */
+	noio_flag = memalloc_noio_save();
 	ret = sock_create_kern(read_pnet(&con->msgr->net), paddr->ss_family,
 			       SOCK_STREAM, IPPROTO_TCP, &sock);
+	memalloc_noio_restore(noio_flag);
 	if (ret)
 		return ret;
 	sock->sk->sk_allocation = GFP_NOFS;
@@ -2042,6 +2048,19 @@
 
 	dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
 
+	if (con->auth_reply_buf) {
+		/*
+		 * Any connection that defines ->get_authorizer()
+		 * should also define ->verify_authorizer_reply().
+		 * See get_connect_authorizer().
+		 */
+		ret = con->ops->verify_authorizer_reply(con, 0);
+		if (ret < 0) {
+			con->error_msg = "bad authorize reply";
+			return ret;
+		}
+	}
+
 	switch (con->in_reply.tag) {
 	case CEPH_MSGR_TAG_FEATURES:
 		pr_err("%s%lld %s feature set mismatch,"
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index 7d8f581..bc95e48 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -1192,6 +1192,114 @@
 }
 
 /*
+ * Encoding order is (new_up_client, new_state, new_weight).  Need to
+ * apply in the (new_weight, new_state, new_up_client) order, because
+ * an incremental map may look like e.g.
+ *
+ *     new_up_client: { osd=6, addr=... } # set osd_state and addr
+ *     new_state: { osd=6, xorstate=EXISTS } # clear osd_state
+ */
+static int decode_new_up_state_weight(void **p, void *end,
+				      struct ceph_osdmap *map)
+{
+	void *new_up_client;
+	void *new_state;
+	void *new_weight_end;
+	u32 len;
+
+	new_up_client = *p;
+	ceph_decode_32_safe(p, end, len, e_inval);
+	len *= sizeof(u32) + sizeof(struct ceph_entity_addr);
+	ceph_decode_need(p, end, len, e_inval);
+	*p += len;
+
+	new_state = *p;
+	ceph_decode_32_safe(p, end, len, e_inval);
+	len *= sizeof(u32) + sizeof(u8);
+	ceph_decode_need(p, end, len, e_inval);
+	*p += len;
+
+	/* new_weight */
+	ceph_decode_32_safe(p, end, len, e_inval);
+	while (len--) {
+		s32 osd;
+		u32 w;
+
+		ceph_decode_need(p, end, 2*sizeof(u32), e_inval);
+		osd = ceph_decode_32(p);
+		w = ceph_decode_32(p);
+		BUG_ON(osd >= map->max_osd);
+		pr_info("osd%d weight 0x%x %s\n", osd, w,
+		     w == CEPH_OSD_IN ? "(in)" :
+		     (w == CEPH_OSD_OUT ? "(out)" : ""));
+		map->osd_weight[osd] = w;
+
+		/*
+		 * If we are marking in, set the EXISTS, and clear the
+		 * AUTOOUT and NEW bits.
+		 */
+		if (w) {
+			map->osd_state[osd] |= CEPH_OSD_EXISTS;
+			map->osd_state[osd] &= ~(CEPH_OSD_AUTOOUT |
+						 CEPH_OSD_NEW);
+		}
+	}
+	new_weight_end = *p;
+
+	/* new_state (up/down) */
+	*p = new_state;
+	len = ceph_decode_32(p);
+	while (len--) {
+		s32 osd;
+		u8 xorstate;
+		int ret;
+
+		osd = ceph_decode_32(p);
+		xorstate = ceph_decode_8(p);
+		if (xorstate == 0)
+			xorstate = CEPH_OSD_UP;
+		BUG_ON(osd >= map->max_osd);
+		if ((map->osd_state[osd] & CEPH_OSD_UP) &&
+		    (xorstate & CEPH_OSD_UP))
+			pr_info("osd%d down\n", osd);
+		if ((map->osd_state[osd] & CEPH_OSD_EXISTS) &&
+		    (xorstate & CEPH_OSD_EXISTS)) {
+			pr_info("osd%d does not exist\n", osd);
+			ret = set_primary_affinity(map, osd,
+						   CEPH_OSD_DEFAULT_PRIMARY_AFFINITY);
+			if (ret)
+				return ret;
+			memset(map->osd_addr + osd, 0, sizeof(*map->osd_addr));
+			map->osd_state[osd] = 0;
+		} else {
+			map->osd_state[osd] ^= xorstate;
+		}
+	}
+
+	/* new_up_client */
+	*p = new_up_client;
+	len = ceph_decode_32(p);
+	while (len--) {
+		s32 osd;
+		struct ceph_entity_addr addr;
+
+		osd = ceph_decode_32(p);
+		ceph_decode_copy(p, &addr, sizeof(addr));
+		ceph_decode_addr(&addr);
+		BUG_ON(osd >= map->max_osd);
+		pr_info("osd%d up\n", osd);
+		map->osd_state[osd] |= CEPH_OSD_EXISTS | CEPH_OSD_UP;
+		map->osd_addr[osd] = addr;
+	}
+
+	*p = new_weight_end;
+	return 0;
+
+e_inval:
+	return -EINVAL;
+}
+
+/*
  * decode and apply an incremental map update.
  */
 struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
@@ -1290,49 +1398,10 @@
 			__remove_pg_pool(&map->pg_pools, pi);
 	}
 
-	/* new_up */
-	ceph_decode_32_safe(p, end, len, e_inval);
-	while (len--) {
-		u32 osd;
-		struct ceph_entity_addr addr;
-		ceph_decode_32_safe(p, end, osd, e_inval);
-		ceph_decode_copy_safe(p, end, &addr, sizeof(addr), e_inval);
-		ceph_decode_addr(&addr);
-		pr_info("osd%d up\n", osd);
-		BUG_ON(osd >= map->max_osd);
-		map->osd_state[osd] |= CEPH_OSD_UP | CEPH_OSD_EXISTS;
-		map->osd_addr[osd] = addr;
-	}
-
-	/* new_state */
-	ceph_decode_32_safe(p, end, len, e_inval);
-	while (len--) {
-		u32 osd;
-		u8 xorstate;
-		ceph_decode_32_safe(p, end, osd, e_inval);
-		xorstate = **(u8 **)p;
-		(*p)++;  /* clean flag */
-		if (xorstate == 0)
-			xorstate = CEPH_OSD_UP;
-		if (xorstate & CEPH_OSD_UP)
-			pr_info("osd%d down\n", osd);
-		if (osd < map->max_osd)
-			map->osd_state[osd] ^= xorstate;
-	}
-
-	/* new_weight */
-	ceph_decode_32_safe(p, end, len, e_inval);
-	while (len--) {
-		u32 osd, off;
-		ceph_decode_need(p, end, sizeof(u32)*2, e_inval);
-		osd = ceph_decode_32(p);
-		off = ceph_decode_32(p);
-		pr_info("osd%d weight 0x%x %s\n", osd, off,
-		     off == CEPH_OSD_IN ? "(in)" :
-		     (off == CEPH_OSD_OUT ? "(out)" : ""));
-		if (osd < map->max_osd)
-			map->osd_weight[osd] = off;
-	}
+	/* new_up_client, new_state, new_weight */
+	err = decode_new_up_state_weight(p, end, map);
+	if (err)
+		goto bad;
 
 	/* new_pg_temp */
 	err = decode_new_pg_temp(p, end, map);
diff --git a/net/core/dev.c b/net/core/dev.c
index 9efbdb3..524d8b2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -182,7 +182,7 @@
 /* protects napi_hash addition/deletion and napi_gen_id */
 static DEFINE_SPINLOCK(napi_hash_lock);
 
-static unsigned int napi_gen_id;
+static unsigned int napi_gen_id = NR_CPUS;
 static DEFINE_HASHTABLE(napi_hash, 8);
 
 static seqcount_t devnet_rename_seq;
@@ -1246,8 +1246,9 @@
 	if (!new_ifalias)
 		return -ENOMEM;
 	dev->ifalias = new_ifalias;
+	memcpy(dev->ifalias, alias, len);
+	dev->ifalias[len] = 0;
 
-	strlcpy(dev->ifalias, alias, len+1);
 	return len;
 }
 
@@ -1676,37 +1677,59 @@
 
 static struct static_key netstamp_needed __read_mostly;
 #ifdef HAVE_JUMP_LABEL
-/* We are not allowed to call static_key_slow_dec() from irq context
- * If net_disable_timestamp() is called from irq context, defer the
- * static_key_slow_dec() calls.
- */
 static atomic_t netstamp_needed_deferred;
+static atomic_t netstamp_wanted;
+static void netstamp_clear(struct work_struct *work)
+{
+	int deferred = atomic_xchg(&netstamp_needed_deferred, 0);
+	int wanted;
+
+	wanted = atomic_add_return(deferred, &netstamp_wanted);
+	if (wanted > 0)
+		static_key_enable(&netstamp_needed);
+	else
+		static_key_disable(&netstamp_needed);
+}
+static DECLARE_WORK(netstamp_work, netstamp_clear);
 #endif
 
 void net_enable_timestamp(void)
 {
 #ifdef HAVE_JUMP_LABEL
-	int deferred = atomic_xchg(&netstamp_needed_deferred, 0);
+	int wanted;
 
-	if (deferred) {
-		while (--deferred)
-			static_key_slow_dec(&netstamp_needed);
-		return;
+	while (1) {
+		wanted = atomic_read(&netstamp_wanted);
+		if (wanted <= 0)
+			break;
+		if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted + 1) == wanted)
+			return;
 	}
-#endif
+	atomic_inc(&netstamp_needed_deferred);
+	schedule_work(&netstamp_work);
+#else
 	static_key_slow_inc(&netstamp_needed);
+#endif
 }
 EXPORT_SYMBOL(net_enable_timestamp);
 
 void net_disable_timestamp(void)
 {
 #ifdef HAVE_JUMP_LABEL
-	if (in_interrupt()) {
-		atomic_inc(&netstamp_needed_deferred);
-		return;
+	int wanted;
+
+	while (1) {
+		wanted = atomic_read(&netstamp_wanted);
+		if (wanted <= 1)
+			break;
+		if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted - 1) == wanted)
+			return;
 	}
-#endif
+	atomic_dec(&netstamp_needed_deferred);
+	schedule_work(&netstamp_work);
+#else
 	static_key_slow_dec(&netstamp_needed);
+#endif
 }
 EXPORT_SYMBOL(net_disable_timestamp);
 
@@ -2462,7 +2485,7 @@
 			goto out;
 	}
 
-	*(__sum16 *)(skb->data + offset) = csum_fold(csum);
+	*(__sum16 *)(skb->data + offset) = csum_fold(csum) ?: CSUM_MANGLED_0;
 out_set_summed:
 	skb->ip_summed = CHECKSUM_NONE;
 out:
@@ -2650,9 +2673,9 @@
 	if (skb->ip_summed != CHECKSUM_NONE &&
 	    !can_checksum_protocol(features, type)) {
 		features &= ~NETIF_F_ALL_CSUM;
-	} else if (illegal_highdma(skb->dev, skb)) {
-		features &= ~NETIF_F_SG;
 	}
+	if (illegal_highdma(skb->dev, skb))
+		features &= ~NETIF_F_SG;
 
 	return features;
 }
@@ -2836,6 +2859,7 @@
 	}
 	return head;
 }
+EXPORT_SYMBOL_GPL(validate_xmit_skb_list);
 
 static void qdisc_pkt_len_init(struct sk_buff *skb)
 {
@@ -3026,7 +3050,9 @@
 	int queue_index = 0;
 
 #ifdef CONFIG_XPS
-	if (skb->sender_cpu == 0)
+	u32 sender_cpu = skb->sender_cpu - 1;
+
+	if (sender_cpu >= (u32)NR_CPUS)
 		skb->sender_cpu = raw_smp_processor_id() + 1;
 #endif
 
@@ -3722,6 +3748,22 @@
 }
 
 /**
+ *	netdev_is_rx_handler_busy - check if receive handler is registered
+ *	@dev: device to check
+ *
+ *	Check if a receive handler is already registered for a given device.
+ *	Return true if there one.
+ *
+ *	The caller must hold the rtnl_mutex.
+ */
+bool netdev_is_rx_handler_busy(struct net_device *dev)
+{
+	ASSERT_RTNL();
+	return dev && rtnl_dereference(dev->rx_handler);
+}
+EXPORT_SYMBOL_GPL(netdev_is_rx_handler_busy);
+
+/**
  *	netdev_rx_handler_register - register receive handler
  *	@dev: device to register a handler for
  *	@rx_handler: receive handler to register
@@ -4170,7 +4212,9 @@
 	    pinfo->nr_frags &&
 	    !PageHighMem(skb_frag_page(frag0))) {
 		NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
-		NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(frag0);
+		NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int,
+						    skb_frag_size(frag0),
+						    skb->end - skb->tail);
 	}
 }
 
@@ -4223,7 +4267,8 @@
 		NAPI_GRO_CB(skb)->same_flow = 0;
 		NAPI_GRO_CB(skb)->flush = 0;
 		NAPI_GRO_CB(skb)->free = 0;
-		NAPI_GRO_CB(skb)->udp_mark = 0;
+		NAPI_GRO_CB(skb)->encap_mark = 0;
+		NAPI_GRO_CB(skb)->recursion_counter = 0;
 		NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
 
 		/* Setup for GRO checksum validation */
@@ -4684,25 +4729,22 @@
 
 void napi_hash_add(struct napi_struct *napi)
 {
-	if (!test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) {
+	if (test_and_set_bit(NAPI_STATE_HASHED, &napi->state))
+		return;
 
-		spin_lock(&napi_hash_lock);
+	spin_lock(&napi_hash_lock);
 
-		/* 0 is not a valid id, we also skip an id that is taken
-		 * we expect both events to be extremely rare
-		 */
-		napi->napi_id = 0;
-		while (!napi->napi_id) {
-			napi->napi_id = ++napi_gen_id;
-			if (napi_by_id(napi->napi_id))
-				napi->napi_id = 0;
-		}
+	/* 0..NR_CPUS+1 range is reserved for sender_cpu use */
+	do {
+		if (unlikely(++napi_gen_id < NR_CPUS + 1))
+			napi_gen_id = NR_CPUS + 1;
+	} while (napi_by_id(napi_gen_id));
+	napi->napi_id = napi_gen_id;
 
-		hlist_add_head_rcu(&napi->napi_hash_node,
-			&napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]);
+	hlist_add_head_rcu(&napi->napi_hash_node,
+			   &napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]);
 
-		spin_unlock(&napi_hash_lock);
-	}
+	spin_unlock(&napi_hash_lock);
 }
 EXPORT_SYMBOL_GPL(napi_hash_add);
 
@@ -5188,6 +5230,7 @@
 
 static int __netdev_adjacent_dev_insert(struct net_device *dev,
 					struct net_device *adj_dev,
+					u16 ref_nr,
 					struct list_head *dev_list,
 					void *private, bool master)
 {
@@ -5197,7 +5240,7 @@
 	adj = __netdev_find_adj(adj_dev, dev_list);
 
 	if (adj) {
-		adj->ref_nr++;
+		adj->ref_nr += ref_nr;
 		return 0;
 	}
 
@@ -5207,7 +5250,7 @@
 
 	adj->dev = adj_dev;
 	adj->master = master;
-	adj->ref_nr = 1;
+	adj->ref_nr = ref_nr;
 	adj->private = private;
 	dev_hold(adj_dev);
 
@@ -5246,6 +5289,7 @@
 
 static void __netdev_adjacent_dev_remove(struct net_device *dev,
 					 struct net_device *adj_dev,
+					 u16 ref_nr,
 					 struct list_head *dev_list)
 {
 	struct netdev_adjacent *adj;
@@ -5258,10 +5302,10 @@
 		BUG();
 	}
 
-	if (adj->ref_nr > 1) {
-		pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name,
-			 adj->ref_nr-1);
-		adj->ref_nr--;
+	if (adj->ref_nr > ref_nr) {
+		pr_debug("%s to %s ref_nr-%d = %d\n", dev->name, adj_dev->name,
+			 ref_nr, adj->ref_nr-ref_nr);
+		adj->ref_nr -= ref_nr;
 		return;
 	}
 
@@ -5280,21 +5324,22 @@
 
 static int __netdev_adjacent_dev_link_lists(struct net_device *dev,
 					    struct net_device *upper_dev,
+					    u16 ref_nr,
 					    struct list_head *up_list,
 					    struct list_head *down_list,
 					    void *private, bool master)
 {
 	int ret;
 
-	ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private,
-					   master);
+	ret = __netdev_adjacent_dev_insert(dev, upper_dev, ref_nr, up_list,
+					   private, master);
 	if (ret)
 		return ret;
 
-	ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private,
-					   false);
+	ret = __netdev_adjacent_dev_insert(upper_dev, dev, ref_nr, down_list,
+					   private, false);
 	if (ret) {
-		__netdev_adjacent_dev_remove(dev, upper_dev, up_list);
+		__netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list);
 		return ret;
 	}
 
@@ -5302,9 +5347,10 @@
 }
 
 static int __netdev_adjacent_dev_link(struct net_device *dev,
-				      struct net_device *upper_dev)
+				      struct net_device *upper_dev,
+				      u16 ref_nr)
 {
-	return __netdev_adjacent_dev_link_lists(dev, upper_dev,
+	return __netdev_adjacent_dev_link_lists(dev, upper_dev, ref_nr,
 						&dev->all_adj_list.upper,
 						&upper_dev->all_adj_list.lower,
 						NULL, false);
@@ -5312,17 +5358,19 @@
 
 static void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
 					       struct net_device *upper_dev,
+					       u16 ref_nr,
 					       struct list_head *up_list,
 					       struct list_head *down_list)
 {
-	__netdev_adjacent_dev_remove(dev, upper_dev, up_list);
-	__netdev_adjacent_dev_remove(upper_dev, dev, down_list);
+	__netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list);
+	__netdev_adjacent_dev_remove(upper_dev, dev, ref_nr, down_list);
 }
 
 static void __netdev_adjacent_dev_unlink(struct net_device *dev,
-					 struct net_device *upper_dev)
+					 struct net_device *upper_dev,
+					 u16 ref_nr)
 {
-	__netdev_adjacent_dev_unlink_lists(dev, upper_dev,
+	__netdev_adjacent_dev_unlink_lists(dev, upper_dev, ref_nr,
 					   &dev->all_adj_list.upper,
 					   &upper_dev->all_adj_list.lower);
 }
@@ -5331,17 +5379,17 @@
 						struct net_device *upper_dev,
 						void *private, bool master)
 {
-	int ret = __netdev_adjacent_dev_link(dev, upper_dev);
+	int ret = __netdev_adjacent_dev_link(dev, upper_dev, 1);
 
 	if (ret)
 		return ret;
 
-	ret = __netdev_adjacent_dev_link_lists(dev, upper_dev,
+	ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, 1,
 					       &dev->adj_list.upper,
 					       &upper_dev->adj_list.lower,
 					       private, master);
 	if (ret) {
-		__netdev_adjacent_dev_unlink(dev, upper_dev);
+		__netdev_adjacent_dev_unlink(dev, upper_dev, 1);
 		return ret;
 	}
 
@@ -5351,8 +5399,8 @@
 static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
 						   struct net_device *upper_dev)
 {
-	__netdev_adjacent_dev_unlink(dev, upper_dev);
-	__netdev_adjacent_dev_unlink_lists(dev, upper_dev,
+	__netdev_adjacent_dev_unlink(dev, upper_dev, 1);
+	__netdev_adjacent_dev_unlink_lists(dev, upper_dev, 1,
 					   &dev->adj_list.upper,
 					   &upper_dev->adj_list.lower);
 }
@@ -5404,7 +5452,7 @@
 		list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
 			pr_debug("Interlinking %s with %s, non-neighbour\n",
 				 i->dev->name, j->dev->name);
-			ret = __netdev_adjacent_dev_link(i->dev, j->dev);
+			ret = __netdev_adjacent_dev_link(i->dev, j->dev, i->ref_nr);
 			if (ret)
 				goto rollback_mesh;
 		}
@@ -5414,7 +5462,7 @@
 	list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
 		pr_debug("linking %s's upper device %s with %s\n",
 			 upper_dev->name, i->dev->name, dev->name);
-		ret = __netdev_adjacent_dev_link(dev, i->dev);
+		ret = __netdev_adjacent_dev_link(dev, i->dev, i->ref_nr);
 		if (ret)
 			goto rollback_upper_mesh;
 	}
@@ -5423,7 +5471,7 @@
 	list_for_each_entry(i, &dev->all_adj_list.lower, list) {
 		pr_debug("linking %s's lower device %s with %s\n", dev->name,
 			 i->dev->name, upper_dev->name);
-		ret = __netdev_adjacent_dev_link(i->dev, upper_dev);
+		ret = __netdev_adjacent_dev_link(i->dev, upper_dev, i->ref_nr);
 		if (ret)
 			goto rollback_lower_mesh;
 	}
@@ -5437,7 +5485,7 @@
 	list_for_each_entry(i, &dev->all_adj_list.lower, list) {
 		if (i == to_i)
 			break;
-		__netdev_adjacent_dev_unlink(i->dev, upper_dev);
+		__netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr);
 	}
 
 	i = NULL;
@@ -5447,7 +5495,7 @@
 	list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
 		if (i == to_i)
 			break;
-		__netdev_adjacent_dev_unlink(dev, i->dev);
+		__netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr);
 	}
 
 	i = j = NULL;
@@ -5459,7 +5507,7 @@
 		list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
 			if (i == to_i && j == to_j)
 				break;
-			__netdev_adjacent_dev_unlink(i->dev, j->dev);
+			__netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr);
 		}
 		if (i == to_i)
 			break;
@@ -5543,16 +5591,16 @@
 	 */
 	list_for_each_entry(i, &dev->all_adj_list.lower, list)
 		list_for_each_entry(j, &upper_dev->all_adj_list.upper, list)
-			__netdev_adjacent_dev_unlink(i->dev, j->dev);
+			__netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr);
 
 	/* remove also the devices itself from lower/upper device
 	 * list
 	 */
 	list_for_each_entry(i, &dev->all_adj_list.lower, list)
-		__netdev_adjacent_dev_unlink(i->dev, upper_dev);
+		__netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr);
 
 	list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
-		__netdev_adjacent_dev_unlink(dev, i->dev);
+		__netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr);
 
 	call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
 				      &changeupper_info.info);
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 252e155..a2270188 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -80,6 +80,7 @@
 	struct nlattr *nla;
 	struct sk_buff *skb;
 	unsigned long flags;
+	void *msg_header;
 
 	al = sizeof(struct net_dm_alert_msg);
 	al += dm_hit_limit * sizeof(struct net_dm_drop_point);
@@ -87,21 +88,41 @@
 
 	skb = genlmsg_new(al, GFP_KERNEL);
 
-	if (skb) {
-		genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
-				0, NET_DM_CMD_ALERT);
-		nla = nla_reserve(skb, NLA_UNSPEC,
-				  sizeof(struct net_dm_alert_msg));
-		msg = nla_data(nla);
-		memset(msg, 0, al);
-	} else {
-		mod_timer(&data->send_timer, jiffies + HZ / 10);
-	}
+	if (!skb)
+		goto err;
 
+	msg_header = genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
+				 0, NET_DM_CMD_ALERT);
+	if (!msg_header) {
+		nlmsg_free(skb);
+		skb = NULL;
+		goto err;
+	}
+	nla = nla_reserve(skb, NLA_UNSPEC,
+			  sizeof(struct net_dm_alert_msg));
+	if (!nla) {
+		nlmsg_free(skb);
+		skb = NULL;
+		goto err;
+	}
+	msg = nla_data(nla);
+	memset(msg, 0, al);
+	goto out;
+
+err:
+	mod_timer(&data->send_timer, jiffies + HZ / 10);
+out:
 	spin_lock_irqsave(&data->lock, flags);
 	swap(data->skb, skb);
 	spin_unlock_irqrestore(&data->lock, flags);
 
+	if (skb) {
+		struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
+		struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlh);
+
+		genlmsg_end(skb, genlmsg_data(gnlh));
+	}
+
 	return skb;
 }
 
diff --git a/net/core/dst.c b/net/core/dst.c
index a1656e3..e72d706 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -151,13 +151,13 @@
 }
 EXPORT_SYMBOL(dst_discard_out);
 
-const u32 dst_default_metrics[RTAX_MAX + 1] = {
+const struct dst_metrics dst_default_metrics = {
 	/* This initializer is needed to force linker to place this variable
 	 * into const section. Otherwise it might end into bss section.
 	 * We really want to avoid false sharing on this variable, and catch
 	 * any writes on it.
 	 */
-	[RTAX_MAX] = 0xdeadbeef,
+	.refcnt = ATOMIC_INIT(1),
 };
 
 void dst_init(struct dst_entry *dst, struct dst_ops *ops,
@@ -169,7 +169,7 @@
 	if (dev)
 		dev_hold(dev);
 	dst->ops = ops;
-	dst_init_metrics(dst, dst_default_metrics, true);
+	dst_init_metrics(dst, dst_default_metrics.metrics, true);
 	dst->expires = 0UL;
 	dst->path = dst;
 	dst->from = NULL;
@@ -315,25 +315,30 @@
 
 u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old)
 {
-	u32 *p = kmalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC);
+	struct dst_metrics *p = kmalloc(sizeof(*p), GFP_ATOMIC);
 
 	if (p) {
-		u32 *old_p = __DST_METRICS_PTR(old);
+		struct dst_metrics *old_p = (struct dst_metrics *)__DST_METRICS_PTR(old);
 		unsigned long prev, new;
 
-		memcpy(p, old_p, sizeof(u32) * RTAX_MAX);
+		atomic_set(&p->refcnt, 1);
+		memcpy(p->metrics, old_p->metrics, sizeof(p->metrics));
 
 		new = (unsigned long) p;
 		prev = cmpxchg(&dst->_metrics, old, new);
 
 		if (prev != old) {
 			kfree(p);
-			p = __DST_METRICS_PTR(prev);
+			p = (struct dst_metrics *)__DST_METRICS_PTR(prev);
 			if (prev & DST_METRICS_READ_ONLY)
 				p = NULL;
+		} else if (prev & DST_METRICS_REFCOUNTED) {
+			if (atomic_dec_and_test(&old_p->refcnt))
+				kfree(old_p);
 		}
 	}
-	return p;
+	BUILD_BUG_ON(offsetof(struct dst_metrics, metrics) != 0);
+	return (u32 *)p;
 }
 EXPORT_SYMBOL(dst_cow_metrics_generic);
 
@@ -342,7 +347,7 @@
 {
 	unsigned long prev, new;
 
-	new = ((unsigned long) dst_default_metrics) | DST_METRICS_READ_ONLY;
+	new = ((unsigned long) &dst_default_metrics) | DST_METRICS_READ_ONLY;
 	prev = cmpxchg(&dst->_metrics, old, new);
 	if (prev == old)
 		kfree(__DST_METRICS_PTR(old));
@@ -457,6 +462,20 @@
 		spin_lock_bh(&dst_garbage.lock);
 		dst = dst_garbage.list;
 		dst_garbage.list = NULL;
+		/* The code in dst_ifdown places a hold on the loopback device.
+		 * If the gc entry processing is set to expire after a lengthy
+		 * interval, this hold can cause netdev_wait_allrefs() to hang
+		 * out and wait for a long time -- until the the loopback
+		 * interface is released.  If we're really unlucky, it'll emit
+		 * pr_emerg messages to console too.  Reset the interval here,
+		 * so dst cleanups occur in a more timely fashion.
+		 */
+		if (dst_garbage.timer_inc > DST_GC_INC) {
+			dst_garbage.timer_inc = DST_GC_INC;
+			dst_garbage.timer_expires = DST_GC_MIN;
+			mod_delayed_work(system_wq, &dst_gc_work,
+					 dst_garbage.timer_expires);
+		}
 		spin_unlock_bh(&dst_garbage.lock);
 
 		if (last)
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 29edf74..b6bca62 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -886,9 +886,12 @@
 	if (regs.len > reglen)
 		regs.len = reglen;
 
-	regbuf = vzalloc(reglen);
-	if (reglen && !regbuf)
-		return -ENOMEM;
+	regbuf = NULL;
+	if (reglen) {
+		regbuf = vzalloc(reglen);
+		if (!regbuf)
+			return -ENOMEM;
+	}
 
 	ops->get_regs(dev, &regs, regbuf);
 
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 3fbd839..cb744a3 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -18,6 +18,11 @@
 #include <net/fib_rules.h>
 #include <net/ip_tunnels.h>
 
+static const struct fib_kuid_range fib_kuid_range_unset = {
+	KUIDT_INIT(0),
+	KUIDT_INIT(~0),
+};
+
 int fib_default_rule_add(struct fib_rules_ops *ops,
 			 u32 pref, u32 table, u32 flags)
 {
@@ -33,8 +38,7 @@
 	r->table = table;
 	r->flags = flags;
 	r->fr_net = ops->fro_net;
-	r->uid_start = INVALID_UID;
-	r->uid_end = INVALID_UID;
+	r->uid_range = fib_kuid_range_unset;
 
 	r->suppress_prefixlen = -1;
 	r->suppress_ifgroup = -1;
@@ -174,21 +178,32 @@
 }
 EXPORT_SYMBOL_GPL(fib_rules_unregister);
 
-static inline kuid_t fib_nl_uid(struct nlattr *nla)
+static int uid_range_set(struct fib_kuid_range *range)
 {
-	return make_kuid(current_user_ns(), nla_get_u32(nla));
+	return uid_valid(range->start) && uid_valid(range->end);
 }
 
-static int nla_put_uid(struct sk_buff *skb, int idx, kuid_t uid)
+static struct fib_kuid_range nla_get_kuid_range(struct nlattr **tb)
 {
-	return nla_put_u32(skb, idx, from_kuid_munged(current_user_ns(), uid));
+	struct fib_rule_uid_range *in;
+	struct fib_kuid_range out;
+
+	in = (struct fib_rule_uid_range *)nla_data(tb[FRA_UID_RANGE]);
+
+	out.start = make_kuid(current_user_ns(), in->start);
+	out.end = make_kuid(current_user_ns(), in->end);
+
+	return out;
 }
 
-static int fib_uid_range_match(struct flowi *fl, struct fib_rule *rule)
+static int nla_put_uid_range(struct sk_buff *skb, struct fib_kuid_range *range)
 {
-	return (!uid_valid(rule->uid_start) && !uid_valid(rule->uid_end)) ||
-	       (uid_gte(fl->flowi_uid, rule->uid_start) &&
-		uid_lte(fl->flowi_uid, rule->uid_end));
+	struct fib_rule_uid_range out = {
+		from_kuid_munged(current_user_ns(), range->start),
+		from_kuid_munged(current_user_ns(), range->end)
+	};
+
+	return nla_put(skb, FRA_UID_RANGE, sizeof(out), &out);
 }
 
 static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
@@ -208,7 +223,8 @@
 	if (rule->tun_id && (rule->tun_id != fl->flowi_tun_key.tun_id))
 		goto out;
 
-	if (!fib_uid_range_match(fl, rule))
+	if (uid_lt(fl->flowi_uid, rule->uid_range.start) ||
+	    uid_gt(fl->flowi_uid, rule->uid_range.end))
 		goto out;
 
 	ret = ops->match(rule, fl, flags);
@@ -393,17 +409,19 @@
 	} else if (rule->action == FR_ACT_GOTO)
 		goto errout_free;
 
-	/* UID start and end must either both be valid or both unspecified. */
-	rule->uid_start = rule->uid_end = INVALID_UID;
-	if (tb[FRA_UID_START] || tb[FRA_UID_END]) {
-		if (tb[FRA_UID_START] && tb[FRA_UID_END]) {
-			rule->uid_start = fib_nl_uid(tb[FRA_UID_START]);
-			rule->uid_end = fib_nl_uid(tb[FRA_UID_END]);
+	if (tb[FRA_UID_RANGE]) {
+		if (current_user_ns() != net->user_ns) {
+			err = -EPERM;
+			goto errout_free;
 		}
-		if (!uid_valid(rule->uid_start) ||
-		    !uid_valid(rule->uid_end) ||
-		    !uid_lte(rule->uid_start, rule->uid_end))
-		goto errout_free;
+
+		rule->uid_range = nla_get_kuid_range(tb);
+
+		if (!uid_range_set(&rule->uid_range) ||
+		    !uid_lte(rule->uid_range.start, rule->uid_range.end))
+			goto errout_free;
+	} else {
+		rule->uid_range = fib_kuid_range_unset;
 	}
 
 	err = ops->configure(rule, skb, frh, tb);
@@ -467,6 +485,7 @@
 	struct fib_rules_ops *ops = NULL;
 	struct fib_rule *rule, *tmp;
 	struct nlattr *tb[FRA_MAX+1];
+	struct fib_kuid_range range;
 	int err = -EINVAL;
 
 	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
@@ -486,6 +505,14 @@
 	if (err < 0)
 		goto errout;
 
+	if (tb[FRA_UID_RANGE]) {
+		range = nla_get_kuid_range(tb);
+		if (!uid_range_set(&range))
+			goto errout;
+	} else {
+		range = fib_kuid_range_unset;
+	}
+
 	list_for_each_entry(rule, &ops->rules_list, list) {
 		if (frh->action && (frh->action != rule->action))
 			continue;
@@ -518,12 +545,9 @@
 		    (rule->tun_id != nla_get_be64(tb[FRA_TUN_ID])))
 			continue;
 
-		if (tb[FRA_UID_START] &&
-		    !uid_eq(rule->uid_start, fib_nl_uid(tb[FRA_UID_START])))
-			continue;
-
-		if (tb[FRA_UID_END] &&
-		    !uid_eq(rule->uid_end, fib_nl_uid(tb[FRA_UID_END])))
+		if (uid_range_set(&range) &&
+		    (!uid_eq(rule->uid_range.start, range.start) ||
+		     !uid_eq(rule->uid_range.end, range.end)))
 			continue;
 
 		if (!ops->compare(rule, frh, tb))
@@ -592,9 +616,8 @@
 			 + nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */
 			 + nla_total_size(4) /* FRA_FWMARK */
 			 + nla_total_size(4) /* FRA_FWMASK */
-			 + nla_total_size(8) /* FRA_TUN_ID */
-			 + nla_total_size(4) /* FRA_UID_START */
-			 + nla_total_size(4); /* FRA_UID_END */
+			 + nla_total_size(8); /* FRA_TUN_ID */
+			 + nla_total_size(sizeof(struct fib_kuid_range));
 
 	if (ops->nlmsg_payload)
 		payload += ops->nlmsg_payload(rule);
@@ -653,10 +676,8 @@
 	     nla_put_u32(skb, FRA_GOTO, rule->target)) ||
 	    (rule->tun_id &&
 	     nla_put_be64(skb, FRA_TUN_ID, rule->tun_id)) ||
-	    (uid_valid(rule->uid_start) &&
-	     nla_put_uid(skb, FRA_UID_START, rule->uid_start)) ||
-	    (uid_valid(rule->uid_end) &&
-	     nla_put_uid(skb, FRA_UID_END, rule->uid_end)))
+	    (uid_range_set(&rule->uid_range) &&
+	     nla_put_uid_range(skb, &rule->uid_range)))
 		goto nla_put_failure;
 
 	if (rule->suppress_ifgroup != -1) {
diff --git a/net/core/filter.c b/net/core/filter.c
index f393a22..e943554 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -52,9 +52,10 @@
 #include <net/dst.h>
 
 /**
- *	sk_filter - run a packet through a socket filter
+ *	sk_filter_trim_cap - run a packet through a socket filter
  *	@sk: sock associated with &sk_buff
  *	@skb: buffer to filter
+ *	@cap: limit on how short the eBPF program may trim the packet
  *
  * Run the eBPF program and then cut skb->data to correct size returned by
  * the program. If pkt_len is 0 we toss packet. If skb->len is smaller
@@ -63,7 +64,7 @@
  * be accepted or -EPERM if the packet should be tossed.
  *
  */
-int sk_filter(struct sock *sk, struct sk_buff *skb)
+int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap)
 {
 	int err;
 	struct sk_filter *filter;
@@ -84,14 +85,13 @@
 	filter = rcu_dereference(sk->sk_filter);
 	if (filter) {
 		unsigned int pkt_len = bpf_prog_run_save_cb(filter->prog, skb);
-
-		err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
+		err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM;
 	}
 	rcu_read_unlock();
 
 	return err;
 }
-EXPORT_SYMBOL(sk_filter);
+EXPORT_SYMBOL(sk_filter_trim_cap);
 
 static u64 __skb_get_pay_offset(u64 ctx, u64 a, u64 x, u64 r4, u64 r5)
 {
@@ -1275,9 +1275,7 @@
 	 */
 	if (unlikely((u32) offset > 0xffff || len > sizeof(buf)))
 		return -EFAULT;
-
-	if (unlikely(skb_cloned(skb) &&
-		     !skb_clone_writable(skb, offset + len)))
+	if (unlikely(skb_try_make_writable(skb, offset + len)))
 		return -EFAULT;
 
 	ptr = skb_header_pointer(skb, offset, len, buf);
@@ -1321,8 +1319,7 @@
 	if (unlikely((u32) offset > 0xffff))
 		return -EFAULT;
 
-	if (unlikely(skb_cloned(skb) &&
-		     !skb_clone_writable(skb, offset + sizeof(sum))))
+	if (unlikely(skb_try_make_writable(skb, offset + sizeof(sum))))
 		return -EFAULT;
 
 	ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
@@ -1367,9 +1364,7 @@
 
 	if (unlikely((u32) offset > 0xffff))
 		return -EFAULT;
-
-	if (unlikely(skb_cloned(skb) &&
-		     !skb_clone_writable(skb, offset + sizeof(sum))))
+	if (unlikely(skb_try_make_writable(skb, offset + sizeof(sum))))
 		return -EFAULT;
 
 	ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
@@ -1554,6 +1549,13 @@
 		return true;
 	if (func == bpf_skb_vlan_pop)
 		return true;
+	if (func == bpf_skb_store_bytes)
+		return true;
+	if (func == bpf_l3_csum_replace)
+		return true;
+	if (func == bpf_l4_csum_replace)
+		return true;
+
 	return false;
 }
 
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 12e7003..ee90827 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -131,7 +131,7 @@
 	struct flow_dissector_key_tags *key_tags;
 	struct flow_dissector_key_keyid *key_keyid;
 	u8 ip_proto = 0;
-	bool ret = false;
+	bool ret;
 
 	if (!data) {
 		data = skb->data;
@@ -492,12 +492,17 @@
 out_good:
 	ret = true;
 
-out_bad:
+	key_control->thoff = (u16)nhoff;
+out:
 	key_basic->n_proto = proto;
 	key_basic->ip_proto = ip_proto;
-	key_control->thoff = (u16)nhoff;
 
 	return ret;
+
+out_bad:
+	ret = false;
+	key_control->thoff = min_t(u16, nhoff, skb ? skb->len : hlen);
+	goto out;
 }
 EXPORT_SYMBOL(__skb_flow_dissect);
 
@@ -662,6 +667,23 @@
 }
 EXPORT_SYMBOL(make_flow_keys_digest);
 
+static struct flow_dissector flow_keys_dissector_symmetric __read_mostly;
+
+u32 __skb_get_hash_symmetric(struct sk_buff *skb)
+{
+	struct flow_keys keys;
+
+	__flow_hash_secret_init();
+
+	memset(&keys, 0, sizeof(keys));
+	__skb_flow_dissect(skb, &flow_keys_dissector_symmetric, &keys,
+			   NULL, 0, 0, 0,
+			   FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
+
+	return __flow_hash_from_keys(&keys, hashrnd);
+}
+EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric);
+
 /**
  * __skb_get_hash: calculate a flow hash
  * @skb: sk_buff to calculate flow hash from
@@ -874,6 +896,29 @@
 	},
 };
 
+static const struct flow_dissector_key flow_keys_dissector_symmetric_keys[] = {
+	{
+		.key_id = FLOW_DISSECTOR_KEY_CONTROL,
+		.offset = offsetof(struct flow_keys, control),
+	},
+	{
+		.key_id = FLOW_DISSECTOR_KEY_BASIC,
+		.offset = offsetof(struct flow_keys, basic),
+	},
+	{
+		.key_id = FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+		.offset = offsetof(struct flow_keys, addrs.v4addrs),
+	},
+	{
+		.key_id = FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+		.offset = offsetof(struct flow_keys, addrs.v6addrs),
+	},
+	{
+		.key_id = FLOW_DISSECTOR_KEY_PORTS,
+		.offset = offsetof(struct flow_keys, ports),
+	},
+};
+
 static const struct flow_dissector_key flow_keys_buf_dissector_keys[] = {
 	{
 		.key_id = FLOW_DISSECTOR_KEY_CONTROL,
@@ -895,10 +940,13 @@
 	skb_flow_dissector_init(&flow_keys_dissector,
 				flow_keys_dissector_keys,
 				ARRAY_SIZE(flow_keys_dissector_keys));
+	skb_flow_dissector_init(&flow_keys_dissector_symmetric,
+				flow_keys_dissector_symmetric_keys,
+				ARRAY_SIZE(flow_keys_dissector_symmetric_keys));
 	skb_flow_dissector_init(&flow_keys_buf_dissector,
 				flow_keys_buf_dissector_keys,
 				ARRAY_SIZE(flow_keys_buf_dissector_keys));
 	return 0;
 }
 
-late_initcall_sync(init_default_flow_dissectors);
+core_initcall(init_default_flow_dissectors);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index f18ae91..ae92131 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -859,7 +859,8 @@
 	if (skb)
 		skb = skb_clone(skb, GFP_ATOMIC);
 	write_unlock(&neigh->lock);
-	neigh->ops->solicit(neigh, skb);
+	if (neigh->ops->solicit)
+		neigh->ops->solicit(neigh, skb);
 	atomic_inc(&neigh->probes);
 	kfree_skb(skb);
 }
@@ -2467,13 +2468,17 @@
 		tbl = neigh_tables[index];
 		if (!tbl)
 			goto out;
+		rcu_read_lock_bh();
 		neigh = __neigh_lookup_noref(tbl, addr, dev);
 		if (!neigh)
 			neigh = __neigh_create(tbl, addr, dev, false);
 		err = PTR_ERR(neigh);
-		if (IS_ERR(neigh))
+		if (IS_ERR(neigh)) {
+			rcu_read_unlock_bh();
 			goto out_kfree_skb;
+		}
 		err = neigh->output(neigh, skb);
+		rcu_read_unlock_bh();
 	}
 	else if (index == NEIGH_LINK_TABLE) {
 		err = dev_hard_header(skb, dev, ntohs(skb->protocol),
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2c2eb1b..2e9a1c2 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -217,6 +217,8 @@
 	bool alloc;
 	int id;
 
+	if (atomic_read(&net->count) == 0)
+		return NETNSA_NSID_NOT_ASSIGNED;
 	spin_lock_irqsave(&net->nsid_lock, flags);
 	alloc = atomic_read(&peer->count) == 0 ? false : true;
 	id = __peernet2id_alloc(net, peer, &alloc);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 94acfc8..440aa9f 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -105,15 +105,21 @@
 	while ((skb = skb_dequeue(&npinfo->txq))) {
 		struct net_device *dev = skb->dev;
 		struct netdev_queue *txq;
+		unsigned int q_index;
 
 		if (!netif_device_present(dev) || !netif_running(dev)) {
 			kfree_skb(skb);
 			continue;
 		}
 
-		txq = skb_get_tx_queue(dev, skb);
-
 		local_irq_save(flags);
+		/* check if skb->queue_mapping is still valid */
+		q_index = skb_get_queue_mapping(skb);
+		if (unlikely(q_index >= dev->real_num_tx_queues)) {
+			q_index = q_index % dev->real_num_tx_queues;
+			skb_set_queue_mapping(skb, q_index);
+		}
+		txq = netdev_get_tx_queue(dev, q_index);
 		HARD_TX_LOCK(dev, txq, smp_processor_id());
 		if (netif_xmit_frozen_or_stopped(txq) ||
 		    netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) {
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 4da4d51..b632760 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -215,8 +215,8 @@
 #define M_NETIF_RECEIVE 	1	/* Inject packets into stack */
 
 /* If lock -- protects updating of if_list */
-#define   if_lock(t)           spin_lock(&(t->if_lock));
-#define   if_unlock(t)           spin_unlock(&(t->if_lock));
+#define   if_lock(t)           mutex_lock(&(t->if_lock));
+#define   if_unlock(t)           mutex_unlock(&(t->if_lock));
 
 /* Used to help with determining the pkts on receive */
 #define PKTGEN_MAGIC 0xbe9be955
@@ -422,7 +422,7 @@
 };
 
 struct pktgen_thread {
-	spinlock_t if_lock;		/* for list of devices */
+	struct mutex if_lock;		/* for list of devices */
 	struct list_head if_list;	/* All device here */
 	struct list_head th_list;
 	struct task_struct *tsk;
@@ -2002,11 +2002,13 @@
 {
 	struct pktgen_thread *t;
 
+	mutex_lock(&pktgen_thread_lock);
+
 	list_for_each_entry(t, &pn->pktgen_threads, th_list) {
 		struct pktgen_dev *pkt_dev;
 
-		rcu_read_lock();
-		list_for_each_entry_rcu(pkt_dev, &t->if_list, list) {
+		if_lock(t);
+		list_for_each_entry(pkt_dev, &t->if_list, list) {
 			if (pkt_dev->odev != dev)
 				continue;
 
@@ -2021,8 +2023,9 @@
 				       dev->name);
 			break;
 		}
-		rcu_read_unlock();
+		if_unlock(t);
 	}
+	mutex_unlock(&pktgen_thread_lock);
 }
 
 static int pktgen_device_event(struct notifier_block *unused,
@@ -2278,7 +2281,7 @@
 
 static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
 {
-	pkt_dev->pkt_overhead = LL_RESERVED_SPACE(pkt_dev->odev);
+	pkt_dev->pkt_overhead = 0;
 	pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32);
 	pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev);
 	pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev);
@@ -2769,13 +2772,13 @@
 }
 
 static struct sk_buff *pktgen_alloc_skb(struct net_device *dev,
-					struct pktgen_dev *pkt_dev,
-					unsigned int extralen)
+					struct pktgen_dev *pkt_dev)
 {
+	unsigned int extralen = LL_RESERVED_SPACE(dev);
 	struct sk_buff *skb = NULL;
-	unsigned int size = pkt_dev->cur_pkt_size + 64 + extralen +
-			    pkt_dev->pkt_overhead;
+	unsigned int size;
 
+	size = pkt_dev->cur_pkt_size + 64 + extralen + pkt_dev->pkt_overhead;
 	if (pkt_dev->flags & F_NODE) {
 		int node = pkt_dev->node >= 0 ? pkt_dev->node : numa_node_id();
 
@@ -2788,8 +2791,9 @@
 		 skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT);
 	}
 
+	/* the caller pre-fetches from skb->data and reserves for the mac hdr */
 	if (likely(skb))
-		skb_reserve(skb, LL_RESERVED_SPACE(dev));
+		skb_reserve(skb, extralen - 16);
 
 	return skb;
 }
@@ -2822,16 +2826,14 @@
 	mod_cur_headers(pkt_dev);
 	queue_map = pkt_dev->cur_queue_map;
 
-	datalen = (odev->hard_header_len + 16) & ~0xf;
-
-	skb = pktgen_alloc_skb(odev, pkt_dev, datalen);
+	skb = pktgen_alloc_skb(odev, pkt_dev);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
 	}
 
 	prefetchw(skb->data);
-	skb_reserve(skb, datalen);
+	skb_reserve(skb, 16);
 
 	/*  Reserve for ethernet and IP header  */
 	eth = (__u8 *) skb_push(skb, 14);
@@ -2951,7 +2953,7 @@
 	mod_cur_headers(pkt_dev);
 	queue_map = pkt_dev->cur_queue_map;
 
-	skb = pktgen_alloc_skb(odev, pkt_dev, 16);
+	skb = pktgen_alloc_skb(odev, pkt_dev);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
@@ -3727,7 +3729,7 @@
 		return -ENOMEM;
 	}
 
-	spin_lock_init(&t->if_lock);
+	mutex_init(&t->if_lock);
 	t->cpu = cpu;
 
 	INIT_LIST_HEAD(&t->if_list);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 87b91ff..2ec5324 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -897,6 +897,7 @@
 	       + nla_total_size(1) /* IFLA_LINKMODE */
 	       + nla_total_size(4) /* IFLA_CARRIER_CHANGES */
 	       + nla_total_size(4) /* IFLA_LINK_NETNSID */
+	       + nla_total_size(4) /* IFLA_GROUP */
 	       + nla_total_size(ext_filter_mask
 			        & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
 	       + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
@@ -1018,7 +1019,7 @@
 		return err;
 	}
 
-	if (nla_put(skb, IFLA_PHYS_PORT_NAME, strlen(name), name))
+	if (nla_put_string(skb, IFLA_PHYS_PORT_NAME, name))
 		return -EMSGSIZE;
 
 	return 0;
@@ -1089,6 +1090,8 @@
 	struct ifla_vf_mac vf_mac;
 	struct ifla_vf_info ivi;
 
+	memset(&ivi, 0, sizeof(ivi));
+
 	/* Not all SR-IOV capable drivers support the
 	 * spoofcheck and "RSS query enable" query.  Preset to
 	 * -1 so the user space tool can detect that the driver
@@ -1097,7 +1100,6 @@
 	ivi.spoofchk = -1;
 	ivi.rss_query_en = -1;
 	ivi.trusted = -1;
-	memset(ivi.mac, 0, sizeof(ivi.mac));
 	/* The default value for VF link state is "auto"
 	 * IFLA_VF_LINK_STATE_AUTO which equals zero
 	 */
@@ -1370,6 +1372,7 @@
 	[IFLA_PHYS_SWITCH_ID]	= { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN },
 	[IFLA_LINK_NETNSID]	= { .type = NLA_S32 },
 	[IFLA_PROTO_DOWN]	= { .type = NLA_U8 },
+	[IFLA_GROUP]		= { .type = NLA_U32 },
 };
 
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -1458,13 +1461,13 @@
 					       cb->nlh->nlmsg_seq, 0,
 					       NLM_F_MULTI,
 					       ext_filter_mask);
-			/* If we ran out of room on the first message,
-			 * we're in trouble
-			 */
-			WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
 
-			if (err < 0)
-				goto out;
+			if (err < 0) {
+				if (likely(skb->len))
+					goto out;
+
+				goto out_err;
+			}
 
 			nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 cont:
@@ -1472,10 +1475,12 @@
 		}
 	}
 out:
+	err = skb->len;
+out_err:
 	cb->args[1] = idx;
 	cb->args[0] = h;
 
-	return skb->len;
+	return err;
 }
 
 int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len)
@@ -2600,7 +2605,10 @@
 
 static inline size_t rtnl_fdb_nlmsg_size(void)
 {
-	return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN);
+	return NLMSG_ALIGN(sizeof(struct ndmsg)) +
+	       nla_total_size(ETH_ALEN) +	/* NDA_LLADDR */
+	       nla_total_size(sizeof(u16)) +	/* NDA_VLAN */
+	       0;
 }
 
 static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type)
@@ -3124,8 +3132,12 @@
 				err = br_dev->netdev_ops->ndo_bridge_getlink(
 						skb, portid, seq, dev,
 						filter_mask, NLM_F_MULTI);
-				if (err < 0 && err != -EOPNOTSUPP)
-					break;
+				if (err < 0 && err != -EOPNOTSUPP) {
+					if (likely(skb->len))
+						break;
+
+					goto out_err;
+				}
 			}
 			idx++;
 		}
@@ -3136,16 +3148,22 @@
 							      seq, dev,
 							      filter_mask,
 							      NLM_F_MULTI);
-				if (err < 0 && err != -EOPNOTSUPP)
-					break;
+				if (err < 0 && err != -EOPNOTSUPP) {
+					if (likely(skb->len))
+						break;
+
+					goto out_err;
+				}
 			}
 			idx++;
 		}
 	}
+	err = skb->len;
+out_err:
 	rcu_read_unlock();
 	cb->args[0] = idx;
 
-	return skb->len;
+	return err;
 }
 
 static inline size_t bridge_nlmsg_size(void)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 8616d11..73dfd77 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2948,24 +2948,6 @@
 EXPORT_SYMBOL_GPL(skb_append_pagefrags);
 
 /**
- *	skb_push_rcsum - push skb and update receive checksum
- *	@skb: buffer to update
- *	@len: length of data pulled
- *
- *	This function performs an skb_push on the packet and updates
- *	the CHECKSUM_COMPLETE checksum.  It should be used on
- *	receive path processing instead of skb_push unless you know
- *	that the checksum difference is zero (e.g., a valid IP header)
- *	or you are setting ip_summed to CHECKSUM_NONE.
- */
-static unsigned char *skb_push_rcsum(struct sk_buff *skb, unsigned len)
-{
-	skb_push(skb, len);
-	skb_postpush_rcsum(skb, skb->data, len);
-	return skb->data;
-}
-
-/**
  *	skb_pull_rcsum - pull skb and update receive checksum
  *	@skb: buffer to update
  *	@len: length of data pulled
@@ -3696,13 +3678,14 @@
 	if (!skb_may_tx_timestamp(sk, false))
 		return;
 
-	/* take a reference to prevent skb_orphan() from freeing the socket */
-	sock_hold(sk);
-
-	*skb_hwtstamps(skb) = *hwtstamps;
-	__skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND);
-
-	sock_put(sk);
+	/* Take a reference to prevent skb_orphan() from freeing the socket,
+	 * but only if the socket refcount is not zero.
+	 */
+	if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) {
+		*skb_hwtstamps(skb) = *hwtstamps;
+		__skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND);
+		sock_put(sk);
+	}
 }
 EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp);
 
@@ -3753,7 +3736,7 @@
 {
 	struct sock *sk = skb->sk;
 	struct sock_exterr_skb *serr;
-	int err;
+	int err = 1;
 
 	skb->wifi_acked_valid = 1;
 	skb->wifi_acked = acked;
@@ -3763,14 +3746,15 @@
 	serr->ee.ee_errno = ENOMSG;
 	serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS;
 
-	/* take a reference to prevent skb_orphan() from freeing the socket */
-	sock_hold(sk);
-
-	err = sock_queue_err_skb(sk, skb);
+	/* Take a reference to prevent skb_orphan() from freeing the socket,
+	 * but only if the socket refcount is not zero.
+	 */
+	if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) {
+		err = sock_queue_err_skb(sk, skb);
+		sock_put(sk);
+	}
 	if (err)
 		kfree_skb(skb);
-
-	sock_put(sk);
 }
 EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
 
@@ -4427,15 +4411,16 @@
 		__skb_push(skb, offset);
 		err = __vlan_insert_tag(skb, skb->vlan_proto,
 					skb_vlan_tag_get(skb));
-		if (err)
+		if (err) {
+			__skb_pull(skb, offset);
 			return err;
+		}
+
 		skb->protocol = skb->vlan_proto;
 		skb->mac_len += VLAN_HLEN;
-		__skb_pull(skb, offset);
 
-		if (skb->ip_summed == CHECKSUM_COMPLETE)
-			skb->csum = csum_add(skb->csum, csum_partial(skb->data
-					+ (2 * ETH_ALEN), VLAN_HLEN, 0));
+		skb_postpush_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
+		__skb_pull(skb, offset);
 	}
 	__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
 	return 0;
diff --git a/net/core/sock.c b/net/core/sock.c
index 0d91f7d..2871364 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -745,7 +745,7 @@
 		val = min_t(u32, val, sysctl_wmem_max);
 set_sndbuf:
 		sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
-		sk->sk_sndbuf = max_t(u32, val * 2, SOCK_MIN_SNDBUF);
+		sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF);
 		/* Wake up sending tasks if we upped the value. */
 		sk->sk_write_space(sk);
 		break;
@@ -781,7 +781,7 @@
 		 * returning the value we actually used in getsockopt
 		 * is the most desirable behavior.
 		 */
-		sk->sk_rcvbuf = max_t(u32, val * 2, SOCK_MIN_RCVBUF);
+		sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF);
 		break;
 
 	case SO_RCVBUFFORCE:
@@ -1459,6 +1459,11 @@
 		pr_debug("%s: optmem leakage (%d bytes) detected\n",
 			 __func__, atomic_read(&sk->sk_omem_alloc));
 
+	if (sk->sk_frag.page) {
+		put_page(sk->sk_frag.page);
+		sk->sk_frag.page = NULL;
+	}
+
 	if (sk->sk_peer_cred)
 		put_cred(sk->sk_peer_cred);
 	put_pid(sk->sk_peer_pid);
@@ -1552,6 +1557,12 @@
 			is_charged = sk_filter_charge(newsk, filter);
 
 		if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) {
+			/* We need to make sure that we don't uncharge the new
+			 * socket if we couldn't charge it in the first place
+			 * as otherwise we uncharge the parent's filter.
+			 */
+			if (!is_charged)
+				RCU_INIT_POINTER(newsk->sk_filter, NULL);
 			/* It is still raw copy of parent, so invalidate
 			 * destructor and make plain sk_free() */
 			newsk->sk_destruct = NULL;
@@ -1562,6 +1573,7 @@
 		}
 
 		newsk->sk_err	   = 0;
+		newsk->sk_err_soft = 0;
 		newsk->sk_priority = 0;
 		newsk->sk_incoming_cpu = raw_smp_processor_id();
 		atomic64_set(&newsk->sk_cookie, 0);
@@ -1678,17 +1690,17 @@
 
 void skb_orphan_partial(struct sk_buff *skb)
 {
-	/* TCP stack sets skb->ooo_okay based on sk_wmem_alloc,
-	 * so we do not completely orphan skb, but transfert all
-	 * accounted bytes but one, to avoid unexpected reorders.
-	 */
 	if (skb->destructor == sock_wfree
 #ifdef CONFIG_INET
 	    || skb->destructor == tcp_wfree
 #endif
 		) {
-		atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc);
-		skb->truesize = 1;
+		struct sock *sk = skb->sk;
+
+		if (atomic_inc_not_zero(&sk->sk_refcnt)) {
+			atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
+			skb->destructor = sock_efree;
+		}
 	} else {
 		skb_orphan(skb);
 	}
@@ -2383,8 +2395,11 @@
 		sk->sk_type	=	sock->type;
 		sk->sk_wq	=	sock->wq;
 		sock->sk	=	sk;
-	} else
+		sk->sk_uid	=	SOCK_INODE(sock)->i_uid;
+	} else {
 		sk->sk_wq	=	NULL;
+		sk->sk_uid	=	make_kuid(sock_net(sk)->user_ns, 0);
+	}
 
 	rwlock_init(&sk->sk_callback_lock);
 	lockdep_set_class_and_name(&sk->sk_callback_lock,
@@ -2690,11 +2705,6 @@
 
 	sk_refcnt_debug_release(sk);
 
-	if (sk->sk_frag.page) {
-		put_page(sk->sk_frag.page);
-		sk->sk_frag.page = NULL;
-	}
-
 	sock_put(sk);
 }
 EXPORT_SYMBOL(sk_common_release);
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index f053198..5e3a730 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -749,6 +749,7 @@
 	for (i = 0; i < hc->tx_seqbufc; i++)
 		kfree(hc->tx_seqbuf[i]);
 	hc->tx_seqbufc = 0;
+	dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks);
 }
 
 static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 3bd14e8..dbe2573 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -606,7 +606,8 @@
 			if (inet_csk(sk)->icsk_af_ops->conn_request(sk,
 								    skb) < 0)
 				return 1;
-			goto discard;
+			consume_skb(skb);
+			return 0;
 		}
 		if (dh->dccph_type == DCCP_PKT_RESET)
 			goto discard;
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 8be8f27..6467bf3 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -235,7 +235,7 @@
 {
 	const struct iphdr *iph = (struct iphdr *)skb->data;
 	const u8 offset = iph->ihl << 2;
-	const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
+	const struct dccp_hdr *dh;
 	struct dccp_sock *dp;
 	struct inet_sock *inet;
 	const int type = icmp_hdr(skb)->type;
@@ -245,11 +245,13 @@
 	int err;
 	struct net *net = dev_net(skb->dev);
 
-	if (skb->len < offset + sizeof(*dh) ||
-	    skb->len < offset + __dccp_basic_hdr_len(dh)) {
-		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
-		return;
-	}
+	/* Only need dccph_dport & dccph_sport which are the first
+	 * 4 bytes in dccp header.
+	 * Our caller (icmp_socket_deliver()) already pulled 8 bytes for us.
+	 */
+	BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8);
+	BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8);
+	dh = (struct dccp_hdr *)(skb->data + offset);
 
 	sk = __inet_lookup_established(net, &dccp_hashinfo,
 				       iph->daddr, dh->dccph_dport,
@@ -287,7 +289,8 @@
 
 	switch (type) {
 	case ICMP_REDIRECT:
-		dccp_do_redirect(skb, sk);
+		if (!sock_owned_by_user(sk))
+			dccp_do_redirect(skb, sk);
 		goto out;
 	case ICMP_SOURCE_QUENCH:
 		/* Just silently ignore these. */
@@ -696,6 +699,7 @@
 {
 	const struct dccp_hdr *dh;
 	unsigned int cscov;
+	u8 dccph_doff;
 
 	if (skb->pkt_type != PACKET_HOST)
 		return 1;
@@ -717,18 +721,19 @@
 	/*
 	 * If P.Data Offset is too small for packet type, drop packet and return
 	 */
-	if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
-		DCCP_WARN("P.Data Offset(%u) too small\n", dh->dccph_doff);
+	dccph_doff = dh->dccph_doff;
+	if (dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
+		DCCP_WARN("P.Data Offset(%u) too small\n", dccph_doff);
 		return 1;
 	}
 	/*
 	 * If P.Data Offset is too too large for packet, drop packet and return
 	 */
-	if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) {
-		DCCP_WARN("P.Data Offset(%u) too large\n", dh->dccph_doff);
+	if (!pskb_may_pull(skb, dccph_doff * sizeof(u32))) {
+		DCCP_WARN("P.Data Offset(%u) too large\n", dccph_doff);
 		return 1;
 	}
-
+	dh = dccp_hdr(skb);
 	/*
 	 * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet
 	 * has short sequence numbers), drop packet and return
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index b8608b7..3470ad1 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -70,7 +70,7 @@
 			u8 type, u8 code, int offset, __be32 info)
 {
 	const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
-	const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
+	const struct dccp_hdr *dh;
 	struct dccp_sock *dp;
 	struct ipv6_pinfo *np;
 	struct sock *sk;
@@ -78,12 +78,13 @@
 	__u64 seq;
 	struct net *net = dev_net(skb->dev);
 
-	if (skb->len < offset + sizeof(*dh) ||
-	    skb->len < offset + __dccp_basic_hdr_len(dh)) {
-		ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
-				   ICMP6_MIB_INERRORS);
-		return;
-	}
+	/* Only need dccph_dport & dccph_sport which are the first
+	 * 4 bytes in dccp header.
+	 * Our caller (icmpv6_notify()) already pulled 8 bytes for us.
+	 */
+	BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8);
+	BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8);
+	dh = (struct dccp_hdr *)(skb->data + offset);
 
 	sk = __inet6_lookup_established(net, &dccp_hashinfo,
 					&hdr->daddr, dh->dccph_dport,
@@ -121,10 +122,12 @@
 	np = inet6_sk(sk);
 
 	if (type == NDISC_REDIRECT) {
-		struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
+		if (!sock_owned_by_user(sk)) {
+			struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
 
-		if (dst)
-			dst->ops->redirect(dst, sk, skb);
+			if (dst)
+				dst->ops->redirect(dst, sk, skb);
+		}
 		goto out;
 	}
 
@@ -419,6 +422,9 @@
 		newsk->sk_backlog_rcv = dccp_v4_do_rcv;
 		newnp->pktoptions  = NULL;
 		newnp->opt	   = NULL;
+		newnp->ipv6_mc_list = NULL;
+		newnp->ipv6_ac_list = NULL;
+		newnp->ipv6_fl_list = NULL;
 		newnp->mcast_oif   = inet6_iif(skb);
 		newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
 
@@ -483,6 +489,9 @@
 	/* Clone RX bits */
 	newnp->rxopt.all = np->rxopt.all;
 
+	newnp->ipv6_mc_list = NULL;
+	newnp->ipv6_ac_list = NULL;
+	newnp->ipv6_fl_list = NULL;
 	newnp->pktoptions = NULL;
 	newnp->opt	  = NULL;
 	newnp->mcast_oif  = inet6_iif(skb);
@@ -947,6 +956,7 @@
 	.getsockopt	   = ipv6_getsockopt,
 	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
 	.sockaddr_len	   = sizeof(struct sockaddr_in6),
+	.bind_conflict	   = inet6_csk_bind_conflict,
 #ifdef CONFIG_COMPAT
 	.compat_setsockopt = compat_ipv6_setsockopt,
 	.compat_getsockopt = compat_ipv6_getsockopt,
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 1994f8a..68eed34 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -122,6 +122,7 @@
 			/* It is still raw copy of parent, so invalidate
 			 * destructor and make plain sk_free() */
 			newsk->sk_destruct = NULL;
+			bh_unlock_sock(newsk);
 			sk_free(newsk);
 			return NULL;
 		}
@@ -145,6 +146,13 @@
 	struct dccp_request_sock *dreq = dccp_rsk(req);
 	bool own_req;
 
+	/* TCP/DCCP listeners became lockless.
+	 * DCCP stores complex state in its request_sock, so we need
+	 * a protection for them, now this code runs without being protected
+	 * by the parent (listener) lock.
+	 */
+	spin_lock_bh(&dreq->dreq_lock);
+
 	/* Check for retransmitted REQUEST */
 	if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
 
@@ -159,7 +167,7 @@
 			inet_rtx_syn_ack(sk, req);
 		}
 		/* Network Duplicate, discard packet */
-		return NULL;
+		goto out;
 	}
 
 	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
@@ -185,20 +193,20 @@
 
 	child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL,
 							 req, &own_req);
-	if (!child)
-		goto listen_overflow;
+	if (child) {
+		child = inet_csk_complete_hashdance(sk, child, req, own_req);
+		goto out;
+	}
 
-	return inet_csk_complete_hashdance(sk, child, req, own_req);
-
-listen_overflow:
-	dccp_pr_debug("listen_overflow!\n");
 	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
 drop:
 	if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
 		req->rsk_ops->send_reset(sk, skb);
 
 	inet_csk_reqsk_queue_drop(sk, req);
-	return NULL;
+out:
+	spin_unlock_bh(&dreq->dreq_lock);
+	return child;
 }
 
 EXPORT_SYMBOL_GPL(dccp_check_req);
@@ -249,6 +257,7 @@
 {
 	struct dccp_request_sock *dreq = dccp_rsk(req);
 
+	spin_lock_init(&dreq->dreq_lock);
 	inet_rsk(req)->ir_rmt_port = dccp_hdr(skb)->dccph_sport;
 	inet_rsk(req)->ir_num	   = ntohs(dccp_hdr(skb)->dccph_dport);
 	inet_rsk(req)->acked	   = 0;
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 41e6580..9fe25bf 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -1009,6 +1009,10 @@
 		__kfree_skb(skb);
 	}
 
+	/* If socket has been already reset kill it. */
+	if (sk->sk_state == DCCP_CLOSED)
+		goto adjudge_to_death;
+
 	if (data_was_unread) {
 		/* Unread data was tossed, send an appropriate Reset Code */
 		DCCP_WARN("ABORT with %u bytes unread\n", data_was_unread);
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 607a14f..403593b 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -188,12 +188,6 @@
 	call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
 }
 
-static inline void dnrt_drop(struct dn_route *rt)
-{
-	dst_release(&rt->dst);
-	call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
-}
-
 static void dn_dst_check_expire(unsigned long dummy)
 {
 	int i;
@@ -248,7 +242,7 @@
 			}
 			*rtp = rt->dst.dn_next;
 			rt->dst.dn_next = NULL;
-			dnrt_drop(rt);
+			dnrt_free(rt);
 			break;
 		}
 		spin_unlock_bh(&dn_rt_hash_table[i].lock);
@@ -350,7 +344,7 @@
 			dst_use(&rth->dst, now);
 			spin_unlock_bh(&dn_rt_hash_table[hash].lock);
 
-			dnrt_drop(rt);
+			dst_free(&rt->dst);
 			*rp = rth;
 			return 0;
 		}
@@ -380,7 +374,7 @@
 		for(; rt; rt = next) {
 			next = rcu_dereference_raw(rt->dst.dn_next);
 			RCU_INIT_POINTER(rt->dst.dn_next, NULL);
-			dst_free((struct dst_entry *)rt);
+			dnrt_free(rt);
 		}
 
 nothing_to_declare:
@@ -1034,10 +1028,13 @@
 	if (!fld.daddr) {
 		fld.daddr = fld.saddr;
 
-		err = -EADDRNOTAVAIL;
 		if (dev_out)
 			dev_put(dev_out);
+		err = -EINVAL;
 		dev_out = init_net.loopback_dev;
+		if (!dev_out->dn_ptr)
+			goto out;
+		err = -EADDRNOTAVAIL;
 		dev_hold(dev_out);
 		if (!fld.daddr) {
 			fld.daddr =
@@ -1110,6 +1107,8 @@
 		if (dev_out == NULL)
 			goto out;
 		dn_db = rcu_dereference_raw(dev_out->dn_ptr);
+		if (!dn_db)
+			goto e_inval;
 		/* Possible improvement - check all devices for local addr */
 		if (dn_dev_islocal(dev_out, fld.daddr)) {
 			dev_put(dev_out);
@@ -1151,6 +1150,8 @@
 			dev_put(dev_out);
 		dev_out = init_net.loopback_dev;
 		dev_hold(dev_out);
+		if (!dev_out->dn_ptr)
+			goto e_inval;
 		fld.flowidn_oif = dev_out->ifindex;
 		if (res.fi)
 			dn_fib_info_put(res.fi);
@@ -1180,7 +1181,7 @@
 	if (dev_out->flags & IFF_LOOPBACK)
 		flags |= RTCF_LOCAL;
 
-	rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, DST_HOST);
+	rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST);
 	if (rt == NULL)
 		goto e_nobufs;
 
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 85f2fdc..29246bc 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -102,7 +102,9 @@
 {
 	struct nlmsghdr *nlh = nlmsg_hdr(skb);
 
-	if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+	if (skb->len < sizeof(*nlh) ||
+	    nlh->nlmsg_len < sizeof(*nlh) ||
+	    skb->len < nlh->nlmsg_len)
 		return;
 
 	if (!netlink_capable(skb, CAP_NET_ADMIN))
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 7bc787b..554c2a9 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1006,10 +1006,8 @@
 	/* Use already configured phy mode */
 	if (p->phy_interface == PHY_INTERFACE_MODE_NA)
 		p->phy_interface = p->phy->interface;
-	phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
-			   p->phy_interface);
-
-	return 0;
+	return phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
+				  p->phy_interface);
 }
 
 static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
@@ -1101,6 +1099,8 @@
 {
 	struct dsa_slave_priv *p = netdev_priv(slave_dev);
 
+	netif_device_detach(slave_dev);
+
 	if (p->phy) {
 		phy_stop(p->phy);
 		p->old_pause = -1;
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 9e63f25..52dcd41 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -353,6 +353,7 @@
 	dev->header_ops		= &eth_header_ops;
 	dev->type		= ARPHRD_ETHER;
 	dev->hard_header_len 	= ETH_HLEN;
+	dev->min_header_len	= ETH_HLEN;
 	dev->mtu		= ETH_DATA_LEN;
 	dev->addr_len		= ETH_ALEN;
 	dev->tx_queue_len	= 1000;	/* Ethernet wants good queues */
@@ -436,7 +437,7 @@
 
 	skb_gro_pull(skb, sizeof(*eh));
 	skb_gro_postpull_rcsum(skb, eh, sizeof(*eh));
-	pp = ptype->callbacks.gro_receive(head, skb);
+	pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
 
 out_unlock:
 	rcu_read_unlock();
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 5c5db66..c31e5fa 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -89,6 +89,7 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/random.h>
 #include <linux/slab.h>
+#include <linux/netfilter/xt_qtaguid.h>
 
 #include <asm/uaccess.h>
 
@@ -121,6 +122,19 @@
 #endif
 #include <net/l3mdev.h>
 
+#ifdef CONFIG_ANDROID_PARANOID_NETWORK
+#include <linux/android_aid.h>
+
+static inline int current_has_network(void)
+{
+	return in_egroup_p(AID_INET) || capable(CAP_NET_RAW);
+}
+#else
+static inline int current_has_network(void)
+{
+	return 1;
+}
+#endif
 
 /* The inetsw table contains everything that inet_create needs to
  * build a new socket.
@@ -260,6 +274,9 @@
 	if (protocol < 0 || protocol >= IPPROTO_MAX)
 		return -EINVAL;
 
+	if (!current_has_network())
+		return -EACCES;
+
 	sock->state = SS_UNCONNECTED;
 
 	/* Look for the requested type/protocol pair. */
@@ -308,8 +325,7 @@
 	}
 
 	err = -EPERM;
-	if (sock->type == SOCK_RAW && !kern &&
-	    !ns_capable(net->user_ns, CAP_NET_RAW))
+	if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
 		goto out_rcu_unlock;
 
 	sock->ops = answer->ops;
@@ -398,6 +414,9 @@
 	if (sk) {
 		long timeout;
 
+#ifdef CONFIG_NETFILTER_XT_MATCH_QTAGUID
+		qtaguid_untag(sock, true);
+#endif
 		/* Applications forget to leave groups before exiting */
 		ip_mc_drop_socket(sk);
 
@@ -1014,7 +1033,7 @@
 		.type =       SOCK_DGRAM,
 		.protocol =   IPPROTO_ICMP,
 		.prot =       &ping_prot,
-		.ops =        &inet_dgram_ops,
+		.ops =        &inet_sockraw_ops,
 		.flags =      INET_PROTOSW_REUSE,
        },
 
@@ -1372,7 +1391,7 @@
 	skb_gro_pull(skb, sizeof(*iph));
 	skb_set_transport_header(skb, skb_gro_offset(skb));
 
-	pp = ops->callbacks.gro_receive(head, skb);
+	pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
 
 out_unlock:
 	rcu_read_unlock();
@@ -1383,6 +1402,19 @@
 	return pp;
 }
 
+static struct sk_buff **ipip_gro_receive(struct sk_buff **head,
+					 struct sk_buff *skb)
+{
+	if (NAPI_GRO_CB(skb)->encap_mark) {
+		NAPI_GRO_CB(skb)->flush = 1;
+		return NULL;
+	}
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
+	return inet_gro_receive(head, skb);
+}
+
 int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
 	if (sk->sk_family == AF_INET)
@@ -1425,6 +1457,13 @@
 	return err;
 }
 
+static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
+{
+	skb->encapsulation = 1;
+	skb_shinfo(skb)->gso_type |= SKB_GSO_IPIP;
+	return inet_gro_complete(skb, nhoff);
+}
+
 int inet_ctl_sock_create(struct sock **sk, unsigned short family,
 			 unsigned short type, unsigned char protocol,
 			 struct net *net)
@@ -1652,8 +1691,8 @@
 static const struct net_offload ipip_offload = {
 	.callbacks = {
 		.gso_segment	= inet_gso_segment,
-		.gro_receive	= inet_gro_receive,
-		.gro_complete	= inet_gro_complete,
+		.gro_receive	= ipip_gro_receive,
+		.gro_complete	= ipip_gro_complete,
 	},
 };
 
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 59b3e0e..711b4df 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1250,7 +1250,7 @@
 /*
  *	ax25 -> ASCII conversion
  */
-static char *ax2asc2(ax25_address *a, char *buf)
+static void ax2asc2(ax25_address *a, char *buf)
 {
 	char c, *s;
 	int n;
@@ -1272,10 +1272,10 @@
 	*s++ = n + '0';
 	*s++ = '\0';
 
-	if (*buf == '\0' || *buf == '-')
-		return "*";
-
-	return buf;
+	if (*buf == '\0' || *buf == '-') {
+		buf[0] = '*';
+		buf[1] = '\0';
+	}
 }
 #endif /* CONFIG_AX25 */
 
@@ -1309,7 +1309,7 @@
 	}
 #endif
 	sprintf(tbuf, "%pI4", n->primary_key);
-	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
+	seq_printf(seq, "%-16s 0x%-10x0x%-10x%-17s     *        %s\n",
 		   tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
 	read_unlock(&n->lock);
 }
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index bdb2a07..6cc3e1d 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1657,6 +1657,10 @@
 				goto validate_return_locked;
 			}
 
+		if (opt_iter + 1 == opt_len) {
+			err_offset = opt_iter;
+			goto validate_return_locked;
+		}
 		tag_len = tag[1];
 		if (tag_len > (opt_len - opt_iter)) {
 			err_offset = opt_iter + 1;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 4779374..20fb25e 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -23,6 +23,11 @@
 	void *tmp;
 };
 
+struct esp_output_extra {
+	__be32 seqhi;
+	u32 esphoff;
+};
+
 #define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
 
 static u32 esp4_get_mtu(struct xfrm_state *x, int mtu);
@@ -35,11 +40,11 @@
  *
  * TODO: Use spare space in skb for this where possible.
  */
-static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqhilen)
+static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int extralen)
 {
 	unsigned int len;
 
-	len = seqhilen;
+	len = extralen;
 
 	len += crypto_aead_ivsize(aead);
 
@@ -57,15 +62,16 @@
 	return kmalloc(len, GFP_ATOMIC);
 }
 
-static inline __be32 *esp_tmp_seqhi(void *tmp)
+static inline void *esp_tmp_extra(void *tmp)
 {
-	return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32));
+	return PTR_ALIGN(tmp, __alignof__(struct esp_output_extra));
 }
-static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen)
+
+static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int extralen)
 {
 	return crypto_aead_ivsize(aead) ?
-	       PTR_ALIGN((u8 *)tmp + seqhilen,
-			 crypto_aead_alignmask(aead) + 1) : tmp + seqhilen;
+	       PTR_ALIGN((u8 *)tmp + extralen,
+			 crypto_aead_alignmask(aead) + 1) : tmp + extralen;
 }
 
 static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv)
@@ -99,7 +105,7 @@
 {
 	struct ip_esp_hdr *esph = (void *)(skb->data + offset);
 	void *tmp = ESP_SKB_CB(skb)->tmp;
-	__be32 *seqhi = esp_tmp_seqhi(tmp);
+	__be32 *seqhi = esp_tmp_extra(tmp);
 
 	esph->seq_no = esph->spi;
 	esph->spi = *seqhi;
@@ -107,7 +113,11 @@
 
 static void esp_output_restore_header(struct sk_buff *skb)
 {
-	esp_restore_header(skb, skb_transport_offset(skb) - sizeof(__be32));
+	void *tmp = ESP_SKB_CB(skb)->tmp;
+	struct esp_output_extra *extra = esp_tmp_extra(tmp);
+
+	esp_restore_header(skb, skb_transport_offset(skb) + extra->esphoff -
+				sizeof(__be32));
 }
 
 static void esp_output_done_esn(struct crypto_async_request *base, int err)
@@ -121,6 +131,7 @@
 static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
+	struct esp_output_extra *extra;
 	struct ip_esp_hdr *esph;
 	struct crypto_aead *aead;
 	struct aead_request *req;
@@ -137,8 +148,7 @@
 	int tfclen;
 	int nfrags;
 	int assoclen;
-	int seqhilen;
-	__be32 *seqhi;
+	int extralen;
 	__be64 seqno;
 
 	/* skb is pure payload to encrypt */
@@ -166,21 +176,21 @@
 	nfrags = err;
 
 	assoclen = sizeof(*esph);
-	seqhilen = 0;
+	extralen = 0;
 
 	if (x->props.flags & XFRM_STATE_ESN) {
-		seqhilen += sizeof(__be32);
-		assoclen += seqhilen;
+		extralen += sizeof(*extra);
+		assoclen += sizeof(__be32);
 	}
 
-	tmp = esp_alloc_tmp(aead, nfrags, seqhilen);
+	tmp = esp_alloc_tmp(aead, nfrags, extralen);
 	if (!tmp) {
 		err = -ENOMEM;
 		goto error;
 	}
 
-	seqhi = esp_tmp_seqhi(tmp);
-	iv = esp_tmp_iv(aead, tmp, seqhilen);
+	extra = esp_tmp_extra(tmp);
+	iv = esp_tmp_iv(aead, tmp, extralen);
 	req = esp_tmp_req(aead, iv);
 	sg = esp_req_sg(aead, req);
 
@@ -247,8 +257,10 @@
 	 * encryption.
 	 */
 	if ((x->props.flags & XFRM_STATE_ESN)) {
-		esph = (void *)(skb_transport_header(skb) - sizeof(__be32));
-		*seqhi = esph->spi;
+		extra->esphoff = (unsigned char *)esph -
+				 skb_transport_header(skb);
+		esph = (struct ip_esp_hdr *)((unsigned char *)esph - 4);
+		extra->seqhi = esph->spi;
 		esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
 		aead_request_set_callback(req, 0, esp_output_done_esn, skb);
 	}
@@ -445,7 +457,7 @@
 		goto out;
 
 	ESP_SKB_CB(skb)->tmp = tmp;
-	seqhi = esp_tmp_seqhi(tmp);
+	seqhi = esp_tmp_extra(tmp);
 	iv = esp_tmp_iv(aead, tmp, seqhilen);
 	req = esp_tmp_req(aead, iv);
 	sg = esp_req_sg(aead, req);
@@ -464,7 +476,7 @@
 		esph = (void *)skb_push(skb, 4);
 		*seqhi = esph->spi;
 		esph->spi = esph->seq_no;
-		esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.input.hi);
+		esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi;
 		aead_request_set_callback(req, 0, esp_input_done_esn, skb);
 	}
 
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index f97ae9d..7c4c881 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -85,7 +85,7 @@
 	if (tb)
 		return tb;
 
-	if (id == RT_TABLE_LOCAL)
+	if (id == RT_TABLE_LOCAL && !net->ipv4.fib_has_custom_rules)
 		alias = fib_new_table(net, RT_TABLE_MAIN);
 
 	tb = fib_trie_table(id, alias);
@@ -758,7 +758,7 @@
 	unsigned int e = 0, s_e;
 	struct fib_table *tb;
 	struct hlist_head *head;
-	int dumped = 0;
+	int dumped = 0, err;
 
 	if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
 	    ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED)
@@ -778,20 +778,27 @@
 			if (dumped)
 				memset(&cb->args[2], 0, sizeof(cb->args) -
 						 2 * sizeof(cb->args[0]));
-			if (fib_table_dump(tb, skb, cb) < 0)
-				goto out;
+			err = fib_table_dump(tb, skb, cb);
+			if (err < 0) {
+				if (likely(skb->len))
+					goto out;
+
+				goto out_err;
+			}
 			dumped = 1;
 next:
 			e++;
 		}
 	}
 out:
+	err = skb->len;
+out_err:
 	rcu_read_unlock();
 
 	cb->args[1] = e;
 	cb->args[0] = h;
 
-	return skb->len;
+	return err;
 }
 
 /* Prepare and feed intra-kernel routing request.
@@ -905,7 +912,11 @@
 	if (ifa->ifa_flags & IFA_F_SECONDARY) {
 		prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
 		if (!prim) {
-			pr_warn("%s: bug: prim == NULL\n", __func__);
+			/* if the device has been deleted, we don't perform
+			 * address promotion
+			 */
+			if (!in_dev->dead)
+				pr_warn("%s: bug: prim == NULL\n", __func__);
 			return;
 		}
 		if (iprim && iprim != prim) {
@@ -1077,7 +1088,8 @@
 
 	net = sock_net(skb->sk);
 	nlh = nlmsg_hdr(skb);
-	if (skb->len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len ||
+	if (skb->len < nlmsg_total_size(sizeof(*frn)) ||
+	    skb->len < nlh->nlmsg_len ||
 	    nlmsg_len(nlh) < sizeof(*frn))
 		return;
 
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index d97268e..b250471 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -204,6 +204,7 @@
 static void free_fib_info_rcu(struct rcu_head *head)
 {
 	struct fib_info *fi = container_of(head, struct fib_info, rcu);
+	struct dst_metrics *m;
 
 	change_nexthops(fi) {
 		if (nexthop_nh->nh_dev)
@@ -214,8 +215,9 @@
 		rt_fibinfo_free(&nexthop_nh->nh_rth_input);
 	} endfor_nexthops(fi);
 
-	if (fi->fib_metrics != (u32 *) dst_default_metrics)
-		kfree(fi->fib_metrics);
+	m = fi->fib_metrics;
+	if (m != &dst_default_metrics && atomic_dec_and_test(&m->refcnt))
+		kfree(m);
 	kfree(fi);
 }
 
@@ -479,6 +481,9 @@
 		if (!rtnh_ok(rtnh, remaining))
 			return -EINVAL;
 
+		if (rtnh->rtnh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN))
+			return -EINVAL;
+
 		nexthop_nh->nh_flags =
 			(cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags;
 		nexthop_nh->nh_oif = rtnh->rtnh_ifindex;
@@ -975,13 +980,15 @@
 			val = 65535 - 40;
 		if (type == RTAX_MTU && val > 65535 - 15)
 			val = 65535 - 15;
+		if (type == RTAX_HOPLIMIT && val > 255)
+			val = 255;
 		if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK))
 			return -EINVAL;
-		fi->fib_metrics[type - 1] = val;
+		fi->fib_metrics->metrics[type - 1] = val;
 	}
 
 	if (ecn_ca)
-		fi->fib_metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA;
+		fi->fib_metrics->metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA;
 
 	return 0;
 }
@@ -1001,6 +1008,9 @@
 	if (fib_props[cfg->fc_type].scope > cfg->fc_scope)
 		goto err_inval;
 
+	if (cfg->fc_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN))
+		goto err_inval;
+
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	if (cfg->fc_mp) {
 		nhs = fib_count_nexthops(cfg->fc_mp, cfg->fc_mp_len);
@@ -1036,11 +1046,12 @@
 		goto failure;
 	fib_info_cnt++;
 	if (cfg->fc_mx) {
-		fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL);
+		fi->fib_metrics = kzalloc(sizeof(*fi->fib_metrics), GFP_KERNEL);
 		if (!fi->fib_metrics)
 			goto failure;
+		atomic_set(&fi->fib_metrics->refcnt, 1);
 	} else
-		fi->fib_metrics = (u32 *) dst_default_metrics;
+		fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics;
 
 	fi->fib_net = net;
 	fi->fib_protocol = cfg->fc_protocol;
@@ -1243,7 +1254,7 @@
 	if (fi->fib_priority &&
 	    nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority))
 		goto nla_put_failure;
-	if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0)
+	if (rtnetlink_put_metrics(skb, fi->fib_metrics->metrics) < 0)
 		goto nla_put_failure;
 
 	if (fi->fib_prefsrc &&
@@ -1269,8 +1280,9 @@
 		    nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid))
 			goto nla_put_failure;
 #endif
-		if (fi->fib_nh->nh_lwtstate)
-			lwtunnel_fill_encap(skb, fi->fib_nh->nh_lwtstate);
+		if (fi->fib_nh->nh_lwtstate &&
+		    lwtunnel_fill_encap(skb, fi->fib_nh->nh_lwtstate) < 0)
+			goto nla_put_failure;
 	}
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	if (fi->fib_nhs > 1) {
@@ -1306,8 +1318,10 @@
 			    nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
 				goto nla_put_failure;
 #endif
-			if (nh->nh_lwtstate)
-				lwtunnel_fill_encap(skb, nh->nh_lwtstate);
+			if (nh->nh_lwtstate &&
+			    lwtunnel_fill_encap(skb, nh->nh_lwtstate) < 0)
+				goto nla_put_failure;
+
 			/* length of rtnetlink header + attributes */
 			rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh;
 		} endfor_nexthops(fi);
@@ -1580,8 +1594,13 @@
 void fib_select_path(struct net *net, struct fib_result *res,
 		     struct flowi4 *fl4, int mp_hash)
 {
+	bool oif_check;
+
+	oif_check = (fl4->flowi4_oif == 0 ||
+		     fl4->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF);
+
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res->fi->fib_nhs > 1 && fl4->flowi4_oif == 0) {
+	if (res->fi->fib_nhs > 1 && oif_check) {
 		if (mp_hash < 0)
 			mp_hash = get_hash_from_flowi4(fl4) >> 1;
 
@@ -1591,7 +1610,7 @@
 #endif
 	if (!res->prefixlen &&
 	    res->table->tb_num_default > 1 &&
-	    res->type == RTN_UNICAST && !fl4->flowi4_oif)
+	    res->type == RTN_UNICAST && oif_check)
 		fib_select_default(fl4, res);
 
 	if (!fl4->saddr)
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 744e593..5c598f9 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1906,6 +1906,8 @@
 
 	/* rcu_read_lock is hold by caller */
 	hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) {
+		int err;
+
 		if (i < s_i) {
 			i++;
 			continue;
@@ -1916,17 +1918,14 @@
 			continue;
 		}
 
-		if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
-				  cb->nlh->nlmsg_seq,
-				  RTM_NEWROUTE,
-				  tb->tb_id,
-				  fa->fa_type,
-				  xkey,
-				  KEYLENGTH - fa->fa_slen,
-				  fa->fa_tos,
-				  fa->fa_info, NLM_F_MULTI) < 0) {
+		err = fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
+				    cb->nlh->nlmsg_seq, RTM_NEWROUTE,
+				    tb->tb_id, fa->fa_type,
+				    xkey, KEYLENGTH - fa->fa_slen,
+				    fa->fa_tos, fa->fa_info, NLM_F_MULTI);
+		if (err < 0) {
 			cb->args[4] = i;
-			return -1;
+			return err;
 		}
 		i++;
 	}
@@ -1948,10 +1947,13 @@
 	t_key key = cb->args[3];
 
 	while ((l = leaf_walk_rcu(&tp, key)) != NULL) {
-		if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
+		int err;
+
+		err = fn_trie_dump_leaf(l, tb, skb, cb);
+		if (err < 0) {
 			cb->args[3] = key;
 			cb->args[2] = count;
-			return -1;
+			return err;
 		}
 
 		++count;
@@ -2453,29 +2455,22 @@
 static struct key_vector *fib_route_get_idx(struct fib_route_iter *iter,
 					    loff_t pos)
 {
-	struct fib_table *tb = iter->main_tb;
 	struct key_vector *l, **tp = &iter->tnode;
-	struct trie *t;
 	t_key key;
 
-	/* use cache location of next-to-find key */
+	/* use cached location of previously found key */
 	if (iter->pos > 0 && pos >= iter->pos) {
-		pos -= iter->pos;
 		key = iter->key;
 	} else {
-		t = (struct trie *)tb->tb_data;
-		iter->tnode = t->kv;
-		iter->pos = 0;
+		iter->pos = 1;
 		key = 0;
 	}
 
-	while ((l = leaf_walk_rcu(tp, key)) != NULL) {
+	pos -= iter->pos;
+
+	while ((l = leaf_walk_rcu(tp, key)) && (pos-- > 0)) {
 		key = l->key + 1;
 		iter->pos++;
-
-		if (--pos <= 0)
-			break;
-
 		l = NULL;
 
 		/* handle unlikely case of a key wrap */
@@ -2484,7 +2479,7 @@
 	}
 
 	if (l)
-		iter->key = key;	/* remember it */
+		iter->key = l->key;	/* remember it */
 	else
 		iter->pos = 0;		/* forget it */
 
@@ -2505,14 +2500,14 @@
 		return NULL;
 
 	iter->main_tb = tb;
+	t = (struct trie *)tb->tb_data;
+	iter->tnode = t->kv;
 
 	if (*pos != 0)
 		return fib_route_get_idx(iter, *pos);
 
-	t = (struct trie *)tb->tb_data;
-	iter->tnode = t->kv;
 	iter->pos = 0;
-	iter->key = 0;
+	iter->key = KEY_MAX;
 
 	return SEQ_START_TOKEN;
 }
@@ -2521,7 +2516,7 @@
 {
 	struct fib_route_iter *iter = seq->private;
 	struct key_vector *l = NULL;
-	t_key key = iter->key;
+	t_key key = iter->key + 1;
 
 	++*pos;
 
@@ -2530,7 +2525,7 @@
 		l = leaf_walk_rcu(&iter->tnode, key);
 
 	if (l) {
-		iter->key = l->key + 1;
+		iter->key = l->key;
 		iter->pos++;
 	} else {
 		iter->pos = 0;
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index bd903fe..08d8ee1 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -48,7 +48,7 @@
 	return sk->sk_user_data;
 }
 
-static void fou_recv_pull(struct sk_buff *skb, size_t len)
+static int fou_recv_pull(struct sk_buff *skb, size_t len)
 {
 	struct iphdr *iph = ip_hdr(skb);
 
@@ -59,6 +59,7 @@
 	__skb_pull(skb, len);
 	skb_postpull_rcsum(skb, udp_hdr(skb), len);
 	skb_reset_transport_header(skb);
+	return iptunnel_pull_offloads(skb);
 }
 
 static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
@@ -68,9 +69,14 @@
 	if (!fou)
 		return 1;
 
-	fou_recv_pull(skb, sizeof(struct udphdr));
+	if (fou_recv_pull(skb, sizeof(struct udphdr)))
+		goto drop;
 
 	return -fou->protocol;
+
+drop:
+	kfree_skb(skb);
+	return 0;
 }
 
 static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
@@ -170,6 +176,9 @@
 	__skb_pull(skb, sizeof(struct udphdr) + hdrlen);
 	skb_reset_transport_header(skb);
 
+	if (iptunnel_pull_offloads(skb))
+		goto drop;
+
 	return -guehdr->proto_ctype;
 
 drop:
@@ -192,7 +201,7 @@
 	if (!ops || !ops->callbacks.gro_receive)
 		goto out_unlock;
 
-	pp = ops->callbacks.gro_receive(head, skb);
+	pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
 
 out_unlock:
 	rcu_read_unlock();
@@ -351,7 +360,7 @@
 	if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive))
 		goto out_unlock;
 
-	pp = ops->callbacks.gro_receive(head, skb);
+	pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
 
 out_unlock:
 	rcu_read_unlock();
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 5a8ee32..79ae0d7 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -128,6 +128,11 @@
 	struct packet_offload *ptype;
 	__be16 type;
 
+	if (NAPI_GRO_CB(skb)->encap_mark)
+		goto out;
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
 	off = skb_gro_offset(skb);
 	hlen = off + sizeof(*greh);
 	greh = skb_gro_header_fast(skb, off);
@@ -214,7 +219,7 @@
 	/* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/
 	skb_gro_postpull_rcsum(skb, greh, grehlen);
 
-	pp = ptype->callbacks.gro_receive(head, skb);
+	pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
 
 out_unlock:
 	rcu_read_unlock();
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 36e2697..ef2d432 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -425,6 +425,7 @@
 	fl4.daddr = daddr;
 	fl4.saddr = saddr;
 	fl4.flowi4_mark = mark;
+	fl4.flowi4_uid = sock_net_uid(net, NULL);
 	fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
 	fl4.flowi4_proto = IPPROTO_ICMP;
 	fl4.flowi4_oif = l3mdev_master_ifindex(skb->dev);
@@ -473,6 +474,7 @@
 		      param->replyopts.opt.opt.faddr : iph->saddr);
 	fl4->saddr = saddr;
 	fl4->flowi4_mark = mark;
+	fl4->flowi4_uid = sock_net_uid(net, NULL);
 	fl4->flowi4_tos = RT_TOS(tos);
 	fl4->flowi4_proto = IPPROTO_ICMP;
 	fl4->fl4_icmp_type = type;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index b3086cf..3809d52 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -225,9 +225,14 @@
 static void igmp_gq_start_timer(struct in_device *in_dev)
 {
 	int tv = prandom_u32() % in_dev->mr_maxdelay;
+	unsigned long exp = jiffies + tv + 2;
+
+	if (in_dev->mr_gq_running &&
+	    time_after_eq(exp, (in_dev->mr_gq_timer).expires))
+		return;
 
 	in_dev->mr_gq_running = 1;
-	if (!mod_timer(&in_dev->mr_gq_timer, jiffies+tv+2))
+	if (!mod_timer(&in_dev->mr_gq_timer, exp))
 		in_dev_hold(in_dev);
 }
 
@@ -1097,6 +1102,7 @@
 	pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
 	if (!pmc)
 		return;
+	spin_lock_init(&pmc->lock);
 	spin_lock_bh(&im->lock);
 	pmc->interface = im->interface;
 	in_dev_hold(in_dev);
@@ -2021,21 +2027,26 @@
 
 static void ip_mc_clear_src(struct ip_mc_list *pmc)
 {
-	struct ip_sf_list *psf, *nextpsf;
+	struct ip_sf_list *psf, *nextpsf, *tomb, *sources;
 
-	for (psf = pmc->tomb; psf; psf = nextpsf) {
-		nextpsf = psf->sf_next;
-		kfree(psf);
-	}
+	spin_lock_bh(&pmc->lock);
+	tomb = pmc->tomb;
 	pmc->tomb = NULL;
-	for (psf = pmc->sources; psf; psf = nextpsf) {
-		nextpsf = psf->sf_next;
-		kfree(psf);
-	}
+	sources = pmc->sources;
 	pmc->sources = NULL;
 	pmc->sfmode = MCAST_EXCLUDE;
 	pmc->sfcount[MCAST_INCLUDE] = 0;
 	pmc->sfcount[MCAST_EXCLUDE] = 1;
+	spin_unlock_bh(&pmc->lock);
+
+	for (psf = tomb; psf; psf = nextpsf) {
+		nextpsf = psf->sf_next;
+		kfree(psf);
+	}
+	for (psf = sources; psf; psf = nextpsf) {
+		nextpsf = psf->sf_next;
+		kfree(psf);
+	}
 }
 
 /* Join a multicast group
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 030cd09..a7e7aa1 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -420,7 +420,7 @@
 			   sk->sk_protocol, inet_sk_flowi_flags(sk),
 			   (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
 			   ireq->ir_loc_addr, ireq->ir_rmt_port,
-			   htons(ireq->ir_num), sock_i_uid((struct sock *)sk));
+			   htons(ireq->ir_num), sk->sk_uid);
 	security_req_classify_flow(req, flowi4_to_flowi(fl4));
 	rt = ip_route_output_flow(net, fl4, sk);
 	if (IS_ERR(rt))
@@ -457,7 +457,7 @@
 			   sk->sk_protocol, inet_sk_flowi_flags(sk),
 			   (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
 			   ireq->ir_loc_addr, ireq->ir_rmt_port,
-			   htons(ireq->ir_num), sock_i_uid((struct sock *)sk));
+			   htons(ireq->ir_num), sk->sk_uid);
 	security_req_classify_flow(req, flowi4_to_flowi(fl4));
 	rt = ip_route_output_flow(net, fl4, sk);
 	if (IS_ERR(rt))
@@ -669,6 +669,8 @@
 		inet_sk(newsk)->inet_sport = htons(inet_rsk(req)->ir_num);
 		newsk->sk_write_space = sk_stream_write_space;
 
+		inet_sk(newsk)->mc_list = NULL;
+
 		newsk->sk_mark = inet_rsk(req)->ir_mark;
 		atomic64_set(&newsk->sk_cookie,
 			     atomic64_read(&inet_rsk(req)->ir_cookie));
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index a403a67..fcb83b2 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -44,6 +44,8 @@
 	u16 dport;
 	u16 family;
 	u16 userlocks;
+	u32 ifindex;
+	u32 mark;
 };
 
 static DEFINE_MUTEX(inet_diag_table_mutex);
@@ -96,6 +98,7 @@
 		+ nla_total_size(1) /* INET_DIAG_SHUTDOWN */
 		+ nla_total_size(1) /* INET_DIAG_TOS */
 		+ nla_total_size(1) /* INET_DIAG_TCLASS */
+		+ nla_total_size(4) /* INET_DIAG_MARK */
 		+ nla_total_size(sizeof(struct inet_diag_meminfo))
 		+ nla_total_size(sizeof(struct inet_diag_msg))
 		+ nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
@@ -108,7 +111,8 @@
 		      struct sk_buff *skb, const struct inet_diag_req_v2 *req,
 		      struct user_namespace *user_ns,
 		      u32 portid, u32 seq, u16 nlmsg_flags,
-		      const struct nlmsghdr *unlh)
+		      const struct nlmsghdr *unlh,
+		      bool net_admin)
 {
 	const struct inet_sock *inet = inet_sk(sk);
 	const struct tcp_congestion_ops *ca_ops;
@@ -158,6 +162,9 @@
 	}
 #endif
 
+	if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, sk->sk_mark))
+		goto errout;
+
 	r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
 	r->idiag_inode = sock_i_ino(sk);
 
@@ -256,10 +263,11 @@
 			      const struct inet_diag_req_v2 *req,
 			      struct user_namespace *user_ns,
 			      u32 portid, u32 seq, u16 nlmsg_flags,
-			      const struct nlmsghdr *unlh)
+			      const struct nlmsghdr *unlh,
+			      bool net_admin)
 {
-	return inet_sk_diag_fill(sk, inet_csk(sk), skb, req,
-				 user_ns, portid, seq, nlmsg_flags, unlh);
+	return inet_sk_diag_fill(sk, inet_csk(sk), skb, req, user_ns,
+				 portid, seq, nlmsg_flags, unlh, net_admin);
 }
 
 static int inet_twsk_diag_fill(struct sock *sk,
@@ -301,8 +309,9 @@
 
 static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
 			      u32 portid, u32 seq, u16 nlmsg_flags,
-			      const struct nlmsghdr *unlh)
+			      const struct nlmsghdr *unlh, bool net_admin)
 {
+	struct request_sock *reqsk = inet_reqsk(sk);
 	struct inet_diag_msg *r;
 	struct nlmsghdr *nlh;
 	long tmo;
@@ -316,7 +325,7 @@
 	inet_diag_msg_common_fill(r, sk);
 	r->idiag_state = TCP_SYN_RECV;
 	r->idiag_timer = 1;
-	r->idiag_retrans = inet_reqsk(sk)->num_retrans;
+	r->idiag_retrans = reqsk->num_retrans;
 
 	BUILD_BUG_ON(offsetof(struct inet_request_sock, ir_cookie) !=
 		     offsetof(struct sock, sk_cookie));
@@ -328,6 +337,10 @@
 	r->idiag_uid	= 0;
 	r->idiag_inode	= 0;
 
+	if (net_admin && nla_put_u32(skb, INET_DIAG_MARK,
+				     inet_rsk(reqsk)->ir_mark))
+		return -EMSGSIZE;
+
 	nlmsg_end(skb, nlh);
 	return 0;
 }
@@ -336,7 +349,7 @@
 			const struct inet_diag_req_v2 *r,
 			struct user_namespace *user_ns,
 			u32 portid, u32 seq, u16 nlmsg_flags,
-			const struct nlmsghdr *unlh)
+			const struct nlmsghdr *unlh, bool net_admin)
 {
 	if (sk->sk_state == TCP_TIME_WAIT)
 		return inet_twsk_diag_fill(sk, skb, portid, seq,
@@ -344,10 +357,10 @@
 
 	if (sk->sk_state == TCP_NEW_SYN_RECV)
 		return inet_req_diag_fill(sk, skb, portid, seq,
-					  nlmsg_flags, unlh);
+					  nlmsg_flags, unlh, net_admin);
 
 	return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq,
-				  nlmsg_flags, unlh);
+				  nlmsg_flags, unlh, net_admin);
 }
 
 struct sock *inet_diag_find_one_icsk(struct net *net,
@@ -414,7 +427,8 @@
 	err = sk_diag_fill(sk, rep, req,
 			   sk_user_ns(NETLINK_CB(in_skb).sk),
 			   NETLINK_CB(in_skb).portid,
-			   nlh->nlmsg_seq, 0, nlh);
+			   nlh->nlmsg_seq, 0, nlh,
+			   netlink_net_capable(in_skb, CAP_NET_ADMIN));
 	if (err < 0) {
 		WARN_ON(err == -EMSGSIZE);
 		nlmsg_free(rep);
@@ -552,6 +566,22 @@
 			yes = 0;
 			break;
 		}
+		case INET_DIAG_BC_DEV_COND: {
+			u32 ifindex;
+
+			ifindex = *((const u32 *)(op + 1));
+			if (ifindex != entry->ifindex)
+				yes = 0;
+			break;
+		}
+		case INET_DIAG_BC_MARK_COND: {
+			struct inet_diag_markcond *cond;
+
+			cond = (struct inet_diag_markcond *)(op + 1);
+			if ((entry->mark & cond->mask) != cond->mark)
+				yes = 0;
+			break;
+		}
 		}
 
 		if (yes) {
@@ -594,7 +624,14 @@
 	entry_fill_addrs(&entry, sk);
 	entry.sport = inet->inet_num;
 	entry.dport = ntohs(inet->inet_dport);
+	entry.ifindex = sk->sk_bound_dev_if;
 	entry.userlocks = sk_fullsock(sk) ? sk->sk_userlocks : 0;
+	if (sk_fullsock(sk))
+		entry.mark = sk->sk_mark;
+	else if (sk->sk_state == TCP_NEW_SYN_RECV)
+		entry.mark = inet_rsk(inet_reqsk(sk))->ir_mark;
+	else
+		entry.mark = 0;
 
 	return inet_diag_bc_run(bc, &entry);
 }
@@ -617,6 +654,17 @@
 	return 0;
 }
 
+/* data is u32 ifindex */
+static bool valid_devcond(const struct inet_diag_bc_op *op, int len,
+			  int *min_len)
+{
+	/* Check ifindex space. */
+	*min_len += sizeof(u32);
+	if (len < *min_len)
+		return false;
+
+	return true;
+}
 /* Validate an inet_diag_hostcond. */
 static bool valid_hostcond(const struct inet_diag_bc_op *op, int len,
 			   int *min_len)
@@ -666,10 +714,25 @@
 	return true;
 }
 
-static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
+static bool valid_markcond(const struct inet_diag_bc_op *op, int len,
+			   int *min_len)
 {
-	const void *bc = bytecode;
-	int  len = bytecode_len;
+	*min_len += sizeof(struct inet_diag_markcond);
+	return len >= *min_len;
+}
+
+static int inet_diag_bc_audit(const struct nlattr *attr,
+			      const struct sk_buff *skb)
+{
+	bool net_admin = netlink_net_capable(skb, CAP_NET_ADMIN);
+	const void *bytecode, *bc;
+	int bytecode_len, len;
+
+	if (!attr || nla_len(attr) < sizeof(struct inet_diag_bc_op))
+		return -EINVAL;
+
+	bytecode = bc = nla_data(attr);
+	len = bytecode_len = nla_len(attr);
 
 	while (len > 0) {
 		int min_len = sizeof(struct inet_diag_bc_op);
@@ -681,6 +744,10 @@
 			if (!valid_hostcond(bc, len, &min_len))
 				return -EINVAL;
 			break;
+		case INET_DIAG_BC_DEV_COND:
+			if (!valid_devcond(bc, len, &min_len))
+				return -EINVAL;
+			break;
 		case INET_DIAG_BC_S_GE:
 		case INET_DIAG_BC_S_LE:
 		case INET_DIAG_BC_D_GE:
@@ -688,6 +755,12 @@
 			if (!valid_port_comparison(bc, len, &min_len))
 				return -EINVAL;
 			break;
+		case INET_DIAG_BC_MARK_COND:
+			if (!net_admin)
+				return -EPERM;
+			if (!valid_markcond(bc, len, &min_len))
+				return -EINVAL;
+			break;
 		case INET_DIAG_BC_AUTO:
 		case INET_DIAG_BC_JMP:
 		case INET_DIAG_BC_NOP:
@@ -716,7 +789,8 @@
 			      struct sk_buff *skb,
 			      struct netlink_callback *cb,
 			      const struct inet_diag_req_v2 *r,
-			      const struct nlattr *bc)
+			      const struct nlattr *bc,
+			      bool net_admin)
 {
 	if (!inet_diag_bc_sk(bc, sk))
 		return 0;
@@ -724,7 +798,8 @@
 	return inet_csk_diag_fill(sk, skb, r,
 				  sk_user_ns(NETLINK_CB(cb->skb).sk),
 				  NETLINK_CB(cb->skb).portid,
-				  cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
+				  cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh,
+				  net_admin);
 }
 
 static void twsk_build_assert(void)
@@ -760,6 +835,7 @@
 	struct net *net = sock_net(skb->sk);
 	int i, num, s_i, s_num;
 	u32 idiag_states = r->idiag_states;
+	bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
 
 	if (idiag_states & TCPF_SYN_RECV)
 		idiag_states |= TCPF_NEW_SYN_RECV;
@@ -801,7 +877,8 @@
 				    cb->args[3] > 0)
 					goto next_listen;
 
-				if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) {
+				if (inet_csk_diag_dump(sk, skb, cb, r,
+						       bc, net_admin) < 0) {
 					spin_unlock_bh(&ilb->lock);
 					goto done;
 				}
@@ -869,7 +946,7 @@
 					   sk_user_ns(NETLINK_CB(cb->skb).sk),
 					   NETLINK_CB(cb->skb).portid,
 					   cb->nlh->nlmsg_seq, NLM_F_MULTI,
-					   cb->nlh);
+					   cb->nlh, net_admin);
 			if (res < 0) {
 				spin_unlock_bh(lock);
 				goto done;
@@ -976,13 +1053,13 @@
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		if (nlmsg_attrlen(nlh, hdrlen)) {
 			struct nlattr *attr;
+			int err;
 
 			attr = nlmsg_find_attr(nlh, hdrlen,
 					       INET_DIAG_REQ_BYTECODE);
-			if (!attr ||
-			    nla_len(attr) < sizeof(struct inet_diag_bc_op) ||
-			    inet_diag_bc_audit(nla_data(attr), nla_len(attr)))
-				return -EINVAL;
+			err = inet_diag_bc_audit(attr, skb);
+			if (err)
+				return err;
 		}
 		{
 			struct netlink_dump_control c = {
@@ -1007,13 +1084,13 @@
 	    h->nlmsg_flags & NLM_F_DUMP) {
 		if (nlmsg_attrlen(h, hdrlen)) {
 			struct nlattr *attr;
+			int err;
 
 			attr = nlmsg_find_attr(h, hdrlen,
 					       INET_DIAG_REQ_BYTECODE);
-			if (!attr ||
-			    nla_len(attr) < sizeof(struct inet_diag_bc_op) ||
-			    inet_diag_bc_audit(nla_data(attr), nla_len(attr)))
-				return -EINVAL;
+			err = inet_diag_bc_audit(attr, skb);
+			if (err)
+				return err;
 		}
 		{
 			struct netlink_dump_control c = {
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 6145214..3e41840 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -180,6 +180,7 @@
 	return flags;
 }
 
+/* Fills in tpi and returns header length to be pulled. */
 static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 			    bool *csum_err)
 {
@@ -239,7 +240,7 @@
 				return -EINVAL;
 		}
 	}
-	return iptunnel_pull_header(skb, hdr_len, tpi->proto);
+	return hdr_len;
 }
 
 static void ipgre_err(struct sk_buff *skb, u32 info,
@@ -342,7 +343,7 @@
 	struct tnl_ptk_info tpi;
 	bool csum_err = false;
 
-	if (parse_gre_header(skb, &tpi, &csum_err)) {
+	if (parse_gre_header(skb, &tpi, &csum_err) < 0) {
 		if (!csum_err)		/* ignore csum errors. */
 			return;
 	}
@@ -420,6 +421,7 @@
 {
 	struct tnl_ptk_info tpi;
 	bool csum_err = false;
+	int hdr_len;
 
 #ifdef CONFIG_NET_IPGRE_BROADCAST
 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
@@ -429,7 +431,10 @@
 	}
 #endif
 
-	if (parse_gre_header(skb, &tpi, &csum_err) < 0)
+	hdr_len = parse_gre_header(skb, &tpi, &csum_err);
+	if (hdr_len < 0)
+		goto drop;
+	if (iptunnel_pull_header(skb, hdr_len, tpi.proto) < 0)
 		goto drop;
 
 	if (ipgre_rcv(skb, &tpi) == PACKET_RCVD)
@@ -1242,6 +1247,14 @@
 	err = ipgre_newlink(net, dev, tb, NULL);
 	if (err < 0)
 		goto out;
+
+	/* openvswitch users expect packet sizes to be unrestricted,
+	 * so set the largest MTU we can.
+	 */
+	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
+	if (err)
+		goto out;
+
 	return dev;
 out:
 	free_netdev(dev);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index dbf7f7e..661bda9 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -102,6 +102,9 @@
 
 	iph->tot_len = htons(skb->len);
 	ip_send_check(iph);
+
+	skb->protocol = htons(ETH_P_IP);
+
 	return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
 		       net, sk, skb, NULL, skb_dst(skb)->dev,
 		       dst_output);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index a501242..f300d1c 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -98,15 +98,17 @@
 }
 
 static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
-				  int offset)
+				  int tlen, int offset)
 {
 	__wsum csum = skb->csum;
 
 	if (skb->ip_summed != CHECKSUM_COMPLETE)
 		return;
 
-	if (offset != 0)
-		csum = csum_sub(csum, csum_partial(skb->data, offset, 0));
+	if (offset != 0) {
+		int tend_off = skb_transport_offset(skb) + tlen;
+		csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0));
+	}
 
 	put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
 }
@@ -152,7 +154,7 @@
 }
 
 void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb,
-			 int offset)
+			 int tlen, int offset)
 {
 	struct inet_sock *inet = inet_sk(skb->sk);
 	unsigned int flags = inet->cmsg_flags;
@@ -215,7 +217,7 @@
 	}
 
 	if (flags & IP_CMSG_CHECKSUM)
-		ip_cmsg_recv_checksum(msg, skb, offset);
+		ip_cmsg_recv_checksum(msg, skb, tlen, offset);
 }
 EXPORT_SYMBOL(ip_cmsg_recv_offset);
 
@@ -1190,7 +1192,14 @@
 		pktinfo->ipi_ifindex = 0;
 		pktinfo->ipi_spec_dst.s_addr = 0;
 	}
-	skb_dst_drop(skb);
+	/* We need to keep the dst for __ip_options_echo()
+	 * We could restrict the test to opt.ts_needtime || opt.srr,
+	 * but the following is good enough as IP options are not often used.
+	 */
+	if (unlikely(IPCB(skb)->opt.optlen))
+		skb_dst_force(skb);
+	else
+		skb_dst_drop(skb);
 }
 
 int ip_setsockopt(struct sock *sk, int level,
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index ce30c8b..3310ac7 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -948,17 +948,31 @@
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);
 
-int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
+int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+	int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
 
-	if (new_mtu < 68 ||
-	    new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen)
+	if (new_mtu < 68)
 		return -EINVAL;
+
+	if (new_mtu > max_mtu) {
+		if (strict)
+			return -EINVAL;
+
+		new_mtu = max_mtu;
+	}
+
 	dev->mtu = new_mtu;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu);
+
+int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
+{
+	return __ip_tunnel_change_mtu(dev, new_mtu, true);
+}
 EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);
 
 static void ip_tunnel_dev_free(struct net_device *dev)
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 6cb9009..dbda056 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -116,7 +116,8 @@
 	skb->vlan_tci = 0;
 	skb_set_queue_mapping(skb, 0);
 	skb->pkt_type = PACKET_HOST;
-	return 0;
+
+	return iptunnel_pull_offloads(skb);
 }
 EXPORT_SYMBOL_GPL(iptunnel_pull_header);
 
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 4d8f0b6..6503689 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -540,6 +540,33 @@
 	.get_link_net	= ip_tunnel_get_link_net,
 };
 
+static bool is_vti_tunnel(const struct net_device *dev)
+{
+	return dev->netdev_ops == &vti_netdev_ops;
+}
+
+static int vti_device_event(struct notifier_block *unused,
+			    unsigned long event, void *ptr)
+{
+	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+
+	if (!is_vti_tunnel(dev))
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_DOWN:
+		if (!net_eq(tunnel->net, dev_net(dev)))
+			xfrm_garbage_collect(tunnel->net);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block vti_notifier_block __read_mostly = {
+	.notifier_call = vti_device_event,
+};
+
 static int __init vti_init(void)
 {
 	const char *msg;
@@ -547,6 +574,8 @@
 
 	pr_info("IPv4 over IPsec tunneling driver\n");
 
+	register_netdevice_notifier(&vti_notifier_block);
+
 	msg = "tunnel device";
 	err = register_pernet_device(&vti_net_ops);
 	if (err < 0)
@@ -579,6 +608,7 @@
 xfrm_proto_esp_failed:
 	unregister_pernet_device(&vti_net_ops);
 pernet_dev_failed:
+	unregister_netdevice_notifier(&vti_notifier_block);
 	pr_err("vti init: failed to register %s\n", msg);
 	return err;
 }
@@ -590,6 +620,7 @@
 	xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
 	xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
 	unregister_pernet_device(&vti_net_ops);
+	unregister_netdevice_notifier(&vti_notifier_block);
 }
 
 module_init(vti_init);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index c3a3835..8e77786 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -882,8 +882,10 @@
 {
 	struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
 
-	if (c)
+	if (c) {
+		c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
 		c->mfc_un.res.minvif = MAXVIFS;
+	}
 	return c;
 }
 
@@ -2190,7 +2192,7 @@
 
 int ipmr_get_route(struct net *net, struct sk_buff *skb,
 		   __be32 saddr, __be32 daddr,
-		   struct rtmsg *rtm, int nowait)
+		   struct rtmsg *rtm, int nowait, u32 portid)
 {
 	struct mfc_cache *cache;
 	struct mr_table *mrt;
@@ -2235,6 +2237,7 @@
 			return -ENOMEM;
 		}
 
+		NETLINK_CB(skb2).portid = portid;
 		skb_push(skb2, sizeof(struct iphdr));
 		skb_reset_network_header(skb2);
 		iph = ip_hdr(skb2);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index e5697e6..6e3e0e8 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -367,6 +367,18 @@
 	       memcmp(&e->arp, &uncond, sizeof(uncond)) == 0;
 }
 
+static bool find_jump_target(const struct xt_table_info *t,
+			     const struct arpt_entry *target)
+{
+	struct arpt_entry *iter;
+
+	xt_entry_foreach(iter, t->entries, t->size) {
+		 if (iter == target)
+			return true;
+	}
+	return false;
+}
+
 /* Figures out from what hook each rule can be called: returns 0 if
  * there are loops.  Puts hook bitmask in comefrom.
  */
@@ -439,6 +451,8 @@
 				size = e->next_offset;
 				e = (struct arpt_entry *)
 					(entry0 + pos + size);
+				if (pos + size >= newinfo->size)
+					return 0;
 				e->counters.pcnt = pos;
 				pos += size;
 			} else {
@@ -458,9 +472,15 @@
 					/* This a jump; chase it. */
 					duprintf("Jump rule %u -> %u\n",
 						 pos, newpos);
+					e = (struct arpt_entry *)
+						(entry0 + newpos);
+					if (!find_jump_target(newinfo, e))
+						return 0;
 				} else {
 					/* ... this is a fallthru */
 					newpos = pos + e->next_offset;
+					if (newpos >= newinfo->size)
+						return 0;
 				}
 				e = (struct arpt_entry *)
 					(entry0 + newpos);
@@ -474,25 +494,6 @@
 	return 1;
 }
 
-static inline int check_entry(const struct arpt_entry *e, const char *name)
-{
-	const struct xt_entry_target *t;
-
-	if (!arp_checkentry(&e->arp)) {
-		duprintf("arp_tables: arp check failed %p %s.\n", e, name);
-		return -EINVAL;
-	}
-
-	if (e->target_offset + sizeof(struct xt_entry_target) > e->next_offset)
-		return -EINVAL;
-
-	t = arpt_get_target_c(e);
-	if (e->target_offset + t->u.target_size > e->next_offset)
-		return -EINVAL;
-
-	return 0;
-}
-
 static inline int check_target(struct arpt_entry *e, const char *name)
 {
 	struct xt_entry_target *t = arpt_get_target(e);
@@ -522,10 +523,6 @@
 	struct xt_target *target;
 	int ret;
 
-	ret = check_entry(e, name);
-	if (ret)
-		return ret;
-
 	e->counters.pcnt = xt_percpu_counter_alloc();
 	if (IS_ERR_VALUE(e->counters.pcnt))
 		return -ENOMEM;
@@ -576,9 +573,11 @@
 					     unsigned int valid_hooks)
 {
 	unsigned int h;
+	int err;
 
 	if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 ||
-	    (unsigned char *)e + sizeof(struct arpt_entry) >= limit) {
+	    (unsigned char *)e + sizeof(struct arpt_entry) >= limit ||
+	    (unsigned char *)e + e->next_offset > limit) {
 		duprintf("Bad offset %p\n", e);
 		return -EINVAL;
 	}
@@ -590,6 +589,14 @@
 		return -EINVAL;
 	}
 
+	if (!arp_checkentry(&e->arp))
+		return -EINVAL;
+
+	err = xt_check_entry_offsets(e, e->elems, e->target_offset,
+				     e->next_offset);
+	if (err)
+		return err;
+
 	/* Check hooks & underflows */
 	for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
 		if (!(valid_hooks & (1 << h)))
@@ -691,10 +698,8 @@
 		}
 	}
 
-	if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) {
-		duprintf("Looping hook\n");
+	if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
 		return -ELOOP;
-	}
 
 	/* Finally, each sanity check must pass */
 	i = 0;
@@ -1125,55 +1130,17 @@
 	unsigned int i;
 	struct xt_counters_info tmp;
 	struct xt_counters *paddc;
-	unsigned int num_counters;
-	const char *name;
-	int size;
-	void *ptmp;
 	struct xt_table *t;
 	const struct xt_table_info *private;
 	int ret = 0;
 	struct arpt_entry *iter;
 	unsigned int addend;
-#ifdef CONFIG_COMPAT
-	struct compat_xt_counters_info compat_tmp;
 
-	if (compat) {
-		ptmp = &compat_tmp;
-		size = sizeof(struct compat_xt_counters_info);
-	} else
-#endif
-	{
-		ptmp = &tmp;
-		size = sizeof(struct xt_counters_info);
-	}
+	paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
+	if (IS_ERR(paddc))
+		return PTR_ERR(paddc);
 
-	if (copy_from_user(ptmp, user, size) != 0)
-		return -EFAULT;
-
-#ifdef CONFIG_COMPAT
-	if (compat) {
-		num_counters = compat_tmp.num_counters;
-		name = compat_tmp.name;
-	} else
-#endif
-	{
-		num_counters = tmp.num_counters;
-		name = tmp.name;
-	}
-
-	if (len != size + num_counters * sizeof(struct xt_counters))
-		return -EINVAL;
-
-	paddc = vmalloc(len - size);
-	if (!paddc)
-		return -ENOMEM;
-
-	if (copy_from_user(paddc, user + size, len - size) != 0) {
-		ret = -EFAULT;
-		goto free;
-	}
-
-	t = xt_find_table_lock(net, NFPROTO_ARP, name);
+	t = xt_find_table_lock(net, NFPROTO_ARP, tmp.name);
 	if (IS_ERR_OR_NULL(t)) {
 		ret = t ? PTR_ERR(t) : -ENOENT;
 		goto free;
@@ -1181,7 +1148,7 @@
 
 	local_bh_disable();
 	private = t->private;
-	if (private->number != num_counters) {
+	if (private->number != tmp.num_counters) {
 		ret = -EINVAL;
 		goto unlock_up_free;
 	}
@@ -1208,6 +1175,18 @@
 }
 
 #ifdef CONFIG_COMPAT
+struct compat_arpt_replace {
+	char				name[XT_TABLE_MAXNAMELEN];
+	u32				valid_hooks;
+	u32				num_entries;
+	u32				size;
+	u32				hook_entry[NF_ARP_NUMHOOKS];
+	u32				underflow[NF_ARP_NUMHOOKS];
+	u32				num_counters;
+	compat_uptr_t			counters;
+	struct compat_arpt_entry	entries[0];
+};
+
 static inline void compat_release_entry(struct compat_arpt_entry *e)
 {
 	struct xt_entry_target *t;
@@ -1216,24 +1195,22 @@
 	module_put(t->u.kernel.target->me);
 }
 
-static inline int
+static int
 check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
 				  struct xt_table_info *newinfo,
 				  unsigned int *size,
 				  const unsigned char *base,
-				  const unsigned char *limit,
-				  const unsigned int *hook_entries,
-				  const unsigned int *underflows,
-				  const char *name)
+				  const unsigned char *limit)
 {
 	struct xt_entry_target *t;
 	struct xt_target *target;
 	unsigned int entry_offset;
-	int ret, off, h;
+	int ret, off;
 
 	duprintf("check_compat_entry_size_and_hooks %p\n", e);
 	if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 ||
-	    (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit) {
+	    (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit ||
+	    (unsigned char *)e + e->next_offset > limit) {
 		duprintf("Bad offset %p, limit = %p\n", e, limit);
 		return -EINVAL;
 	}
@@ -1245,8 +1222,11 @@
 		return -EINVAL;
 	}
 
-	/* For purposes of check_entry casting the compat entry is fine */
-	ret = check_entry((struct arpt_entry *)e, name);
+	if (!arp_checkentry(&e->arp))
+		return -EINVAL;
+
+	ret = xt_compat_check_entry_offsets(e, e->elems, e->target_offset,
+					    e->next_offset);
 	if (ret)
 		return ret;
 
@@ -1270,17 +1250,6 @@
 	if (ret)
 		goto release_target;
 
-	/* Check hooks & underflows */
-	for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
-		if ((unsigned char *)e - base == hook_entries[h])
-			newinfo->hook_entry[h] = hook_entries[h];
-		if ((unsigned char *)e - base == underflows[h])
-			newinfo->underflow[h] = underflows[h];
-	}
-
-	/* Clear counters and comefrom */
-	memset(&e->counters, 0, sizeof(e->counters));
-	e->comefrom = 0;
 	return 0;
 
 release_target:
@@ -1289,18 +1258,17 @@
 	return ret;
 }
 
-static int
+static void
 compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
-			    unsigned int *size, const char *name,
+			    unsigned int *size,
 			    struct xt_table_info *newinfo, unsigned char *base)
 {
 	struct xt_entry_target *t;
 	struct xt_target *target;
 	struct arpt_entry *de;
 	unsigned int origsize;
-	int ret, h;
+	int h;
 
-	ret = 0;
 	origsize = *size;
 	de = (struct arpt_entry *)*dstptr;
 	memcpy(de, e, sizeof(struct arpt_entry));
@@ -1321,148 +1289,82 @@
 		if ((unsigned char *)de - base < newinfo->underflow[h])
 			newinfo->underflow[h] -= origsize - *size;
 	}
-	return ret;
 }
 
-static int translate_compat_table(const char *name,
-				  unsigned int valid_hooks,
-				  struct xt_table_info **pinfo,
+static int translate_compat_table(struct xt_table_info **pinfo,
 				  void **pentry0,
-				  unsigned int total_size,
-				  unsigned int number,
-				  unsigned int *hook_entries,
-				  unsigned int *underflows)
+				  const struct compat_arpt_replace *compatr)
 {
 	unsigned int i, j;
 	struct xt_table_info *newinfo, *info;
 	void *pos, *entry0, *entry1;
 	struct compat_arpt_entry *iter0;
-	struct arpt_entry *iter1;
+	struct arpt_replace repl;
 	unsigned int size;
 	int ret = 0;
 
 	info = *pinfo;
 	entry0 = *pentry0;
-	size = total_size;
-	info->number = number;
-
-	/* Init all hooks to impossible value. */
-	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
-		info->hook_entry[i] = 0xFFFFFFFF;
-		info->underflow[i] = 0xFFFFFFFF;
-	}
+	size = compatr->size;
+	info->number = compatr->num_entries;
 
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(NFPROTO_ARP);
-	xt_compat_init_offsets(NFPROTO_ARP, number);
+	xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries);
 	/* Walk through entries, checking offsets. */
-	xt_entry_foreach(iter0, entry0, total_size) {
+	xt_entry_foreach(iter0, entry0, compatr->size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
 							entry0,
-							entry0 + total_size,
-							hook_entries,
-							underflows,
-							name);
+							entry0 + compatr->size);
 		if (ret != 0)
 			goto out_unlock;
 		++j;
 	}
 
 	ret = -EINVAL;
-	if (j != number) {
+	if (j != compatr->num_entries) {
 		duprintf("translate_compat_table: %u not %u entries\n",
-			 j, number);
+			 j, compatr->num_entries);
 		goto out_unlock;
 	}
 
-	/* Check hooks all assigned */
-	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
-		/* Only hooks which are valid */
-		if (!(valid_hooks & (1 << i)))
-			continue;
-		if (info->hook_entry[i] == 0xFFFFFFFF) {
-			duprintf("Invalid hook entry %u %u\n",
-				 i, hook_entries[i]);
-			goto out_unlock;
-		}
-		if (info->underflow[i] == 0xFFFFFFFF) {
-			duprintf("Invalid underflow %u %u\n",
-				 i, underflows[i]);
-			goto out_unlock;
-		}
-	}
-
 	ret = -ENOMEM;
 	newinfo = xt_alloc_table_info(size);
 	if (!newinfo)
 		goto out_unlock;
 
-	newinfo->number = number;
+	newinfo->number = compatr->num_entries;
 	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
 		newinfo->hook_entry[i] = info->hook_entry[i];
 		newinfo->underflow[i] = info->underflow[i];
 	}
 	entry1 = newinfo->entries;
 	pos = entry1;
-	size = total_size;
-	xt_entry_foreach(iter0, entry0, total_size) {
-		ret = compat_copy_entry_from_user(iter0, &pos, &size,
-						  name, newinfo, entry1);
-		if (ret != 0)
-			break;
-	}
+	size = compatr->size;
+	xt_entry_foreach(iter0, entry0, compatr->size)
+		compat_copy_entry_from_user(iter0, &pos, &size,
+					    newinfo, entry1);
+
+	/* all module references in entry0 are now gone */
+
 	xt_compat_flush_offsets(NFPROTO_ARP);
 	xt_compat_unlock(NFPROTO_ARP);
+
+	memcpy(&repl, compatr, sizeof(*compatr));
+
+	for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
+		repl.hook_entry[i] = newinfo->hook_entry[i];
+		repl.underflow[i] = newinfo->underflow[i];
+	}
+
+	repl.num_counters = 0;
+	repl.counters = NULL;
+	repl.size = newinfo->size;
+	ret = translate_table(newinfo, entry1, &repl);
 	if (ret)
 		goto free_newinfo;
 
-	ret = -ELOOP;
-	if (!mark_source_chains(newinfo, valid_hooks, entry1))
-		goto free_newinfo;
-
-	i = 0;
-	xt_entry_foreach(iter1, entry1, newinfo->size) {
-		iter1->counters.pcnt = xt_percpu_counter_alloc();
-		if (IS_ERR_VALUE(iter1->counters.pcnt)) {
-			ret = -ENOMEM;
-			break;
-		}
-
-		ret = check_target(iter1, name);
-		if (ret != 0) {
-			xt_percpu_counter_free(iter1->counters.pcnt);
-			break;
-		}
-		++i;
-		if (strcmp(arpt_get_target(iter1)->u.user.name,
-		    XT_ERROR_TARGET) == 0)
-			++newinfo->stacksize;
-	}
-	if (ret) {
-		/*
-		 * The first i matches need cleanup_entry (calls ->destroy)
-		 * because they had called ->check already. The other j-i
-		 * entries need only release.
-		 */
-		int skip = i;
-		j -= i;
-		xt_entry_foreach(iter0, entry0, newinfo->size) {
-			if (skip-- > 0)
-				continue;
-			if (j-- == 0)
-				break;
-			compat_release_entry(iter0);
-		}
-		xt_entry_foreach(iter1, entry1, newinfo->size) {
-			if (i-- == 0)
-				break;
-			cleanup_entry(iter1);
-		}
-		xt_free_table_info(newinfo);
-		return ret;
-	}
-
 	*pinfo = newinfo;
 	*pentry0 = entry1;
 	xt_free_table_info(info);
@@ -1470,31 +1372,18 @@
 
 free_newinfo:
 	xt_free_table_info(newinfo);
-out:
-	xt_entry_foreach(iter0, entry0, total_size) {
+	return ret;
+out_unlock:
+	xt_compat_flush_offsets(NFPROTO_ARP);
+	xt_compat_unlock(NFPROTO_ARP);
+	xt_entry_foreach(iter0, entry0, compatr->size) {
 		if (j-- == 0)
 			break;
 		compat_release_entry(iter0);
 	}
 	return ret;
-out_unlock:
-	xt_compat_flush_offsets(NFPROTO_ARP);
-	xt_compat_unlock(NFPROTO_ARP);
-	goto out;
 }
 
-struct compat_arpt_replace {
-	char				name[XT_TABLE_MAXNAMELEN];
-	u32				valid_hooks;
-	u32				num_entries;
-	u32				size;
-	u32				hook_entry[NF_ARP_NUMHOOKS];
-	u32				underflow[NF_ARP_NUMHOOKS];
-	u32				num_counters;
-	compat_uptr_t			counters;
-	struct compat_arpt_entry	entries[0];
-};
-
 static int compat_do_replace(struct net *net, void __user *user,
 			     unsigned int len)
 {
@@ -1527,10 +1416,7 @@
 		goto free_newinfo;
 	}
 
-	ret = translate_compat_table(tmp.name, tmp.valid_hooks,
-				     &newinfo, &loc_cpu_entry, tmp.size,
-				     tmp.num_entries, tmp.hook_entry,
-				     tmp.underflow);
+	ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
 	if (ret != 0)
 		goto free_newinfo;
 
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 2bf6b3f..a399c54 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -443,6 +443,18 @@
 #endif
 }
 
+static bool find_jump_target(const struct xt_table_info *t,
+			     const struct ipt_entry *target)
+{
+	struct ipt_entry *iter;
+
+	xt_entry_foreach(iter, t->entries, t->size) {
+		 if (iter == target)
+			return true;
+	}
+	return false;
+}
+
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
@@ -520,6 +532,8 @@
 				size = e->next_offset;
 				e = (struct ipt_entry *)
 					(entry0 + pos + size);
+				if (pos + size >= newinfo->size)
+					return 0;
 				e->counters.pcnt = pos;
 				pos += size;
 			} else {
@@ -538,9 +552,15 @@
 					/* This a jump; chase it. */
 					duprintf("Jump rule %u -> %u\n",
 						 pos, newpos);
+					e = (struct ipt_entry *)
+						(entry0 + newpos);
+					if (!find_jump_target(newinfo, e))
+						return 0;
 				} else {
 					/* ... this is a fallthru */
 					newpos = pos + e->next_offset;
+					if (newpos >= newinfo->size)
+						return 0;
 				}
 				e = (struct ipt_entry *)
 					(entry0 + newpos);
@@ -568,27 +588,6 @@
 }
 
 static int
-check_entry(const struct ipt_entry *e, const char *name)
-{
-	const struct xt_entry_target *t;
-
-	if (!ip_checkentry(&e->ip)) {
-		duprintf("ip check failed %p %s.\n", e, name);
-		return -EINVAL;
-	}
-
-	if (e->target_offset + sizeof(struct xt_entry_target) >
-	    e->next_offset)
-		return -EINVAL;
-
-	t = ipt_get_target_c(e);
-	if (e->target_offset + t->u.target_size > e->next_offset)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int
 check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
 {
 	const struct ipt_ip *ip = par->entryinfo;
@@ -665,10 +664,6 @@
 	struct xt_mtchk_param mtpar;
 	struct xt_entry_match *ematch;
 
-	ret = check_entry(e, name);
-	if (ret)
-		return ret;
-
 	e->counters.pcnt = xt_percpu_counter_alloc();
 	if (IS_ERR_VALUE(e->counters.pcnt))
 		return -ENOMEM;
@@ -740,9 +735,11 @@
 			   unsigned int valid_hooks)
 {
 	unsigned int h;
+	int err;
 
 	if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
-	    (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
+	    (unsigned char *)e + sizeof(struct ipt_entry) >= limit ||
+	    (unsigned char *)e + e->next_offset > limit) {
 		duprintf("Bad offset %p\n", e);
 		return -EINVAL;
 	}
@@ -754,6 +751,14 @@
 		return -EINVAL;
 	}
 
+	if (!ip_checkentry(&e->ip))
+		return -EINVAL;
+
+	err = xt_check_entry_offsets(e, e->elems, e->target_offset,
+				     e->next_offset);
+	if (err)
+		return err;
+
 	/* Check hooks & underflows */
 	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
 		if (!(valid_hooks & (1 << h)))
@@ -1308,55 +1313,17 @@
 	unsigned int i;
 	struct xt_counters_info tmp;
 	struct xt_counters *paddc;
-	unsigned int num_counters;
-	const char *name;
-	int size;
-	void *ptmp;
 	struct xt_table *t;
 	const struct xt_table_info *private;
 	int ret = 0;
 	struct ipt_entry *iter;
 	unsigned int addend;
-#ifdef CONFIG_COMPAT
-	struct compat_xt_counters_info compat_tmp;
 
-	if (compat) {
-		ptmp = &compat_tmp;
-		size = sizeof(struct compat_xt_counters_info);
-	} else
-#endif
-	{
-		ptmp = &tmp;
-		size = sizeof(struct xt_counters_info);
-	}
+	paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
+	if (IS_ERR(paddc))
+		return PTR_ERR(paddc);
 
-	if (copy_from_user(ptmp, user, size) != 0)
-		return -EFAULT;
-
-#ifdef CONFIG_COMPAT
-	if (compat) {
-		num_counters = compat_tmp.num_counters;
-		name = compat_tmp.name;
-	} else
-#endif
-	{
-		num_counters = tmp.num_counters;
-		name = tmp.name;
-	}
-
-	if (len != size + num_counters * sizeof(struct xt_counters))
-		return -EINVAL;
-
-	paddc = vmalloc(len - size);
-	if (!paddc)
-		return -ENOMEM;
-
-	if (copy_from_user(paddc, user + size, len - size) != 0) {
-		ret = -EFAULT;
-		goto free;
-	}
-
-	t = xt_find_table_lock(net, AF_INET, name);
+	t = xt_find_table_lock(net, AF_INET, tmp.name);
 	if (IS_ERR_OR_NULL(t)) {
 		ret = t ? PTR_ERR(t) : -ENOENT;
 		goto free;
@@ -1364,7 +1331,7 @@
 
 	local_bh_disable();
 	private = t->private;
-	if (private->number != num_counters) {
+	if (private->number != tmp.num_counters) {
 		ret = -EINVAL;
 		goto unlock_up_free;
 	}
@@ -1443,7 +1410,6 @@
 
 static int
 compat_find_calc_match(struct xt_entry_match *m,
-		       const char *name,
 		       const struct ipt_ip *ip,
 		       int *size)
 {
@@ -1478,21 +1444,19 @@
 				  struct xt_table_info *newinfo,
 				  unsigned int *size,
 				  const unsigned char *base,
-				  const unsigned char *limit,
-				  const unsigned int *hook_entries,
-				  const unsigned int *underflows,
-				  const char *name)
+				  const unsigned char *limit)
 {
 	struct xt_entry_match *ematch;
 	struct xt_entry_target *t;
 	struct xt_target *target;
 	unsigned int entry_offset;
 	unsigned int j;
-	int ret, off, h;
+	int ret, off;
 
 	duprintf("check_compat_entry_size_and_hooks %p\n", e);
 	if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
-	    (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
+	    (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit ||
+	    (unsigned char *)e + e->next_offset > limit) {
 		duprintf("Bad offset %p, limit = %p\n", e, limit);
 		return -EINVAL;
 	}
@@ -1504,8 +1468,11 @@
 		return -EINVAL;
 	}
 
-	/* For purposes of check_entry casting the compat entry is fine */
-	ret = check_entry((struct ipt_entry *)e, name);
+	if (!ip_checkentry(&e->ip))
+		return -EINVAL;
+
+	ret = xt_compat_check_entry_offsets(e, e->elems,
+					    e->target_offset, e->next_offset);
 	if (ret)
 		return ret;
 
@@ -1513,7 +1480,7 @@
 	entry_offset = (void *)e - (void *)base;
 	j = 0;
 	xt_ematch_foreach(ematch, e) {
-		ret = compat_find_calc_match(ematch, name, &e->ip, &off);
+		ret = compat_find_calc_match(ematch, &e->ip, &off);
 		if (ret != 0)
 			goto release_matches;
 		++j;
@@ -1536,17 +1503,6 @@
 	if (ret)
 		goto out;
 
-	/* Check hooks & underflows */
-	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
-		if ((unsigned char *)e - base == hook_entries[h])
-			newinfo->hook_entry[h] = hook_entries[h];
-		if ((unsigned char *)e - base == underflows[h])
-			newinfo->underflow[h] = underflows[h];
-	}
-
-	/* Clear counters and comefrom */
-	memset(&e->counters, 0, sizeof(e->counters));
-	e->comefrom = 0;
 	return 0;
 
 out:
@@ -1560,19 +1516,18 @@
 	return ret;
 }
 
-static int
+static void
 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
-			    unsigned int *size, const char *name,
+			    unsigned int *size,
 			    struct xt_table_info *newinfo, unsigned char *base)
 {
 	struct xt_entry_target *t;
 	struct xt_target *target;
 	struct ipt_entry *de;
 	unsigned int origsize;
-	int ret, h;
+	int h;
 	struct xt_entry_match *ematch;
 
-	ret = 0;
 	origsize = *size;
 	de = (struct ipt_entry *)*dstptr;
 	memcpy(de, e, sizeof(struct ipt_entry));
@@ -1581,201 +1536,105 @@
 	*dstptr += sizeof(struct ipt_entry);
 	*size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
 
-	xt_ematch_foreach(ematch, e) {
-		ret = xt_compat_match_from_user(ematch, dstptr, size);
-		if (ret != 0)
-			return ret;
-	}
+	xt_ematch_foreach(ematch, e)
+		xt_compat_match_from_user(ematch, dstptr, size);
+
 	de->target_offset = e->target_offset - (origsize - *size);
 	t = compat_ipt_get_target(e);
 	target = t->u.kernel.target;
 	xt_compat_target_from_user(t, dstptr, size);
 
 	de->next_offset = e->next_offset - (origsize - *size);
+
 	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
 		if ((unsigned char *)de - base < newinfo->hook_entry[h])
 			newinfo->hook_entry[h] -= origsize - *size;
 		if ((unsigned char *)de - base < newinfo->underflow[h])
 			newinfo->underflow[h] -= origsize - *size;
 	}
-	return ret;
-}
-
-static int
-compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
-{
-	struct xt_entry_match *ematch;
-	struct xt_mtchk_param mtpar;
-	unsigned int j;
-	int ret = 0;
-
-	e->counters.pcnt = xt_percpu_counter_alloc();
-	if (IS_ERR_VALUE(e->counters.pcnt))
-		return -ENOMEM;
-
-	j = 0;
-	mtpar.net	= net;
-	mtpar.table     = name;
-	mtpar.entryinfo = &e->ip;
-	mtpar.hook_mask = e->comefrom;
-	mtpar.family    = NFPROTO_IPV4;
-	xt_ematch_foreach(ematch, e) {
-		ret = check_match(ematch, &mtpar);
-		if (ret != 0)
-			goto cleanup_matches;
-		++j;
-	}
-
-	ret = check_target(e, net, name);
-	if (ret)
-		goto cleanup_matches;
-	return 0;
-
- cleanup_matches:
-	xt_ematch_foreach(ematch, e) {
-		if (j-- == 0)
-			break;
-		cleanup_match(ematch, net);
-	}
-
-	xt_percpu_counter_free(e->counters.pcnt);
-
-	return ret;
 }
 
 static int
 translate_compat_table(struct net *net,
-		       const char *name,
-		       unsigned int valid_hooks,
 		       struct xt_table_info **pinfo,
 		       void **pentry0,
-		       unsigned int total_size,
-		       unsigned int number,
-		       unsigned int *hook_entries,
-		       unsigned int *underflows)
+		       const struct compat_ipt_replace *compatr)
 {
 	unsigned int i, j;
 	struct xt_table_info *newinfo, *info;
 	void *pos, *entry0, *entry1;
 	struct compat_ipt_entry *iter0;
-	struct ipt_entry *iter1;
+	struct ipt_replace repl;
 	unsigned int size;
 	int ret;
 
 	info = *pinfo;
 	entry0 = *pentry0;
-	size = total_size;
-	info->number = number;
-
-	/* Init all hooks to impossible value. */
-	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		info->hook_entry[i] = 0xFFFFFFFF;
-		info->underflow[i] = 0xFFFFFFFF;
-	}
+	size = compatr->size;
+	info->number = compatr->num_entries;
 
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(AF_INET);
-	xt_compat_init_offsets(AF_INET, number);
+	xt_compat_init_offsets(AF_INET, compatr->num_entries);
 	/* Walk through entries, checking offsets. */
-	xt_entry_foreach(iter0, entry0, total_size) {
+	xt_entry_foreach(iter0, entry0, compatr->size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
 							entry0,
-							entry0 + total_size,
-							hook_entries,
-							underflows,
-							name);
+							entry0 + compatr->size);
 		if (ret != 0)
 			goto out_unlock;
 		++j;
 	}
 
 	ret = -EINVAL;
-	if (j != number) {
+	if (j != compatr->num_entries) {
 		duprintf("translate_compat_table: %u not %u entries\n",
-			 j, number);
+			 j, compatr->num_entries);
 		goto out_unlock;
 	}
 
-	/* Check hooks all assigned */
-	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		/* Only hooks which are valid */
-		if (!(valid_hooks & (1 << i)))
-			continue;
-		if (info->hook_entry[i] == 0xFFFFFFFF) {
-			duprintf("Invalid hook entry %u %u\n",
-				 i, hook_entries[i]);
-			goto out_unlock;
-		}
-		if (info->underflow[i] == 0xFFFFFFFF) {
-			duprintf("Invalid underflow %u %u\n",
-				 i, underflows[i]);
-			goto out_unlock;
-		}
-	}
-
 	ret = -ENOMEM;
 	newinfo = xt_alloc_table_info(size);
 	if (!newinfo)
 		goto out_unlock;
 
-	newinfo->number = number;
+	newinfo->number = compatr->num_entries;
 	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		newinfo->hook_entry[i] = info->hook_entry[i];
-		newinfo->underflow[i] = info->underflow[i];
+		newinfo->hook_entry[i] = compatr->hook_entry[i];
+		newinfo->underflow[i] = compatr->underflow[i];
 	}
 	entry1 = newinfo->entries;
 	pos = entry1;
-	size = total_size;
-	xt_entry_foreach(iter0, entry0, total_size) {
-		ret = compat_copy_entry_from_user(iter0, &pos, &size,
-						  name, newinfo, entry1);
-		if (ret != 0)
-			break;
-	}
+	size = compatr->size;
+	xt_entry_foreach(iter0, entry0, compatr->size)
+		compat_copy_entry_from_user(iter0, &pos, &size,
+					    newinfo, entry1);
+
+	/* all module references in entry0 are now gone.
+	 * entry1/newinfo contains a 64bit ruleset that looks exactly as
+	 * generated by 64bit userspace.
+	 *
+	 * Call standard translate_table() to validate all hook_entrys,
+	 * underflows, check for loops, etc.
+	 */
 	xt_compat_flush_offsets(AF_INET);
 	xt_compat_unlock(AF_INET);
+
+	memcpy(&repl, compatr, sizeof(*compatr));
+
+	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
+		repl.hook_entry[i] = newinfo->hook_entry[i];
+		repl.underflow[i] = newinfo->underflow[i];
+	}
+
+	repl.num_counters = 0;
+	repl.counters = NULL;
+	repl.size = newinfo->size;
+	ret = translate_table(net, newinfo, entry1, &repl);
 	if (ret)
 		goto free_newinfo;
 
-	ret = -ELOOP;
-	if (!mark_source_chains(newinfo, valid_hooks, entry1))
-		goto free_newinfo;
-
-	i = 0;
-	xt_entry_foreach(iter1, entry1, newinfo->size) {
-		ret = compat_check_entry(iter1, net, name);
-		if (ret != 0)
-			break;
-		++i;
-		if (strcmp(ipt_get_target(iter1)->u.user.name,
-		    XT_ERROR_TARGET) == 0)
-			++newinfo->stacksize;
-	}
-	if (ret) {
-		/*
-		 * The first i matches need cleanup_entry (calls ->destroy)
-		 * because they had called ->check already. The other j-i
-		 * entries need only release.
-		 */
-		int skip = i;
-		j -= i;
-		xt_entry_foreach(iter0, entry0, newinfo->size) {
-			if (skip-- > 0)
-				continue;
-			if (j-- == 0)
-				break;
-			compat_release_entry(iter0);
-		}
-		xt_entry_foreach(iter1, entry1, newinfo->size) {
-			if (i-- == 0)
-				break;
-			cleanup_entry(iter1, net);
-		}
-		xt_free_table_info(newinfo);
-		return ret;
-	}
-
 	*pinfo = newinfo;
 	*pentry0 = entry1;
 	xt_free_table_info(info);
@@ -1783,17 +1642,16 @@
 
 free_newinfo:
 	xt_free_table_info(newinfo);
-out:
-	xt_entry_foreach(iter0, entry0, total_size) {
+	return ret;
+out_unlock:
+	xt_compat_flush_offsets(AF_INET);
+	xt_compat_unlock(AF_INET);
+	xt_entry_foreach(iter0, entry0, compatr->size) {
 		if (j-- == 0)
 			break;
 		compat_release_entry(iter0);
 	}
 	return ret;
-out_unlock:
-	xt_compat_flush_offsets(AF_INET);
-	xt_compat_unlock(AF_INET);
-	goto out;
 }
 
 static int
@@ -1829,10 +1687,7 @@
 		goto free_newinfo;
 	}
 
-	ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
-				     &newinfo, &loc_cpu_entry, tmp.size,
-				     tmp.num_entries, tmp.hook_entry,
-				     tmp.underflow);
+	ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
 	if (ret != 0)
 		goto free_newinfo;
 
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 0d5278c..a989aba 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -154,17 +154,18 @@
 void ping_unhash(struct sock *sk)
 {
 	struct inet_sock *isk = inet_sk(sk);
+
 	pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
+	write_lock_bh(&ping_table.lock);
 	if (sk_hashed(sk)) {
-		write_lock_bh(&ping_table.lock);
 		hlist_nulls_del(&sk->sk_nulls_node);
 		sk_nulls_node_init(&sk->sk_nulls_node);
 		sock_put(sk);
 		isk->inet_num = 0;
 		isk->inet_sport = 0;
 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
-		write_unlock_bh(&ping_table.lock);
 	}
+	write_unlock_bh(&ping_table.lock);
 }
 EXPORT_SYMBOL_GPL(ping_unhash);
 
@@ -645,6 +646,8 @@
 {
 	struct sk_buff *skb = skb_peek(&sk->sk_write_queue);
 
+	if (!skb)
+		return 0;
 	pfh->wcheck = csum_partial((char *)&pfh->icmph,
 		sizeof(struct icmphdr), pfh->wcheck);
 	pfh->icmph.checksum = csum_fold(pfh->wcheck);
@@ -660,6 +663,10 @@
 	if (len > 0xFFFF)
 		return -EMSGSIZE;
 
+	/* Must have at least a full ICMP header. */
+	if (len < icmph_len)
+		return -EINVAL;
+
 	/*
 	 *	Check the flags.
 	 */
@@ -792,7 +799,7 @@
 	flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
 			   RT_SCOPE_UNIVERSE, sk->sk_protocol,
 			   inet_sk_flowi_flags(sk), faddr, saddr, 0, 0,
-			   sock_i_uid(sk));
+			   sk->sk_uid);
 
 	security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
 	rt = ip_route_output_flow(net, &fl4, sk);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index a9b479a..ca10314 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -354,6 +354,9 @@
 			       rt->dst.dev->mtu);
 		return -EMSGSIZE;
 	}
+	if (length < sizeof(struct iphdr))
+		return -EINVAL;
+
 	if (flags&MSG_PROBE)
 		goto out;
 
@@ -601,8 +604,7 @@
 			   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
 			   inet_sk_flowi_flags(sk) |
 			    (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
-			   daddr, saddr, 0, 0,
-			   sock_i_uid(sk));
+			   daddr, saddr, 0, 0, sk->sk_uid);
 
 	if (!saddr && ipc.oif) {
 		err = l3mdev_get_saddr(net, ipc.oif, &fl4);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 79a957e..fd15e55 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -501,7 +501,8 @@
 }
 EXPORT_SYMBOL(__ip_select_ident);
 
-static void __build_flow_key(struct flowi4 *fl4, struct sock *sk,
+static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
+			     const struct sock *sk,
 			     const struct iphdr *iph,
 			     int oif, u8 tos,
 			     u8 prot, u32 mark, int flow_flags)
@@ -518,22 +519,23 @@
 			   RT_SCOPE_UNIVERSE, prot,
 			   flow_flags,
 			   iph->daddr, iph->saddr, 0, 0,
-			   sk ? sock_i_uid(sk) : GLOBAL_ROOT_UID);
+			   sock_net_uid(net, sk));
 }
 
 static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
-			       struct sock *sk)
+			       const struct sock *sk)
 {
+	const struct net *net = dev_net(skb->dev);
 	const struct iphdr *iph = ip_hdr(skb);
 	int oif = skb->dev->ifindex;
 	u8 tos = RT_TOS(iph->tos);
 	u8 prot = iph->protocol;
 	u32 mark = skb->mark;
 
-	__build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0);
+	__build_flow_key(net, fl4, sk, iph, oif, tos, prot, mark, 0);
 }
 
-static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk)
+static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
 {
 	const struct inet_sock *inet = inet_sk(sk);
 	const struct ip_options_rcu *inet_opt;
@@ -547,12 +549,11 @@
 			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
 			   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
 			   inet_sk_flowi_flags(sk),
-			   daddr, inet->inet_saddr, 0, 0,
-			   sock_i_uid(sk));
+			   daddr, inet->inet_saddr, 0, 0, sk->sk_uid);
 	rcu_read_unlock();
 }
 
-static void ip_rt_build_flow_key(struct flowi4 *fl4, struct sock *sk,
+static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk,
 				 const struct sk_buff *skb)
 {
 	if (skb)
@@ -749,7 +750,9 @@
 			goto reject_redirect;
 	}
 
-	n = ipv4_neigh_lookup(&rt->dst, NULL, &new_gw);
+	n = __ipv4_neigh_lookup(rt->dst.dev, new_gw);
+	if (!n)
+		n = neigh_create(&arp_tbl, &new_gw, rt->dst.dev);
 	if (!IS_ERR(n)) {
 		if (!(n->nud_state & NUD_VALID)) {
 			neigh_event_send(n, NULL);
@@ -789,6 +792,7 @@
 	struct rtable *rt;
 	struct flowi4 fl4;
 	const struct iphdr *iph = (const struct iphdr *) skb->data;
+	struct net *net = dev_net(skb->dev);
 	int oif = skb->dev->ifindex;
 	u8 tos = RT_TOS(iph->tos);
 	u8 prot = iph->protocol;
@@ -796,7 +800,7 @@
 
 	rt = (struct rtable *) dst;
 
-	__build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0);
+	__build_flow_key(net, &fl4, sk, iph, oif, tos, prot, mark, 0);
 	__ip_do_redirect(rt, skb, &fl4, true);
 }
 
@@ -1014,7 +1018,7 @@
 	if (!mark)
 		mark = IP4_REPLY_MARK(net, skb->mark);
 
-	__build_flow_key(&fl4, NULL, iph, oif,
+	__build_flow_key(net, &fl4, NULL, iph, oif,
 			 RT_TOS(iph->tos), protocol, mark, flow_flags);
 	rt = __ip_route_output_key(net, &fl4);
 	if (!IS_ERR(rt)) {
@@ -1030,7 +1034,7 @@
 	struct flowi4 fl4;
 	struct rtable *rt;
 
-	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+	__build_flow_key(sock_net(sk), &fl4, sk, iph, 0, 0, 0, 0, 0);
 
 	if (!fl4.flowi4_mark)
 		fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
@@ -1049,6 +1053,7 @@
 	struct rtable *rt;
 	struct dst_entry *odst = NULL;
 	bool new = false;
+	struct net *net = sock_net(sk);
 
 	bh_lock_sock(sk);
 
@@ -1062,7 +1067,7 @@
 		goto out;
 	}
 
-	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+	__build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
 
 	rt = (struct rtable *)odst;
 	if (odst->obsolete && !odst->ops->check(odst, 0)) {
@@ -1102,7 +1107,7 @@
 	struct flowi4 fl4;
 	struct rtable *rt;
 
-	__build_flow_key(&fl4, NULL, iph, oif,
+	__build_flow_key(net, &fl4, NULL, iph, oif,
 			 RT_TOS(iph->tos), protocol, mark, flow_flags);
 	rt = __ip_route_output_key(net, &fl4);
 	if (!IS_ERR(rt)) {
@@ -1117,9 +1122,10 @@
 	const struct iphdr *iph = (const struct iphdr *) skb->data;
 	struct flowi4 fl4;
 	struct rtable *rt;
+	struct net *net = sock_net(sk);
 
-	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
-	rt = __ip_route_output_key(sock_net(sk), &fl4);
+	__build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
+	rt = __ip_route_output_key(net, &fl4);
 	if (!IS_ERR(rt)) {
 		__ip_do_redirect(rt, skb, &fl4, false);
 		ip_rt_put(rt);
@@ -1356,8 +1362,12 @@
 
 static void ipv4_dst_destroy(struct dst_entry *dst)
 {
+	struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst);
 	struct rtable *rt = (struct rtable *) dst;
 
+	if (p != &dst_default_metrics && atomic_dec_and_test(&p->refcnt))
+		kfree(p);
+
 	if (!list_empty(&rt->rt_uncached)) {
 		struct uncached_list *ul = rt->rt_uncached_list;
 
@@ -1409,7 +1419,11 @@
 			rt->rt_gateway = nh->nh_gw;
 			rt->rt_uses_gateway = 1;
 		}
-		dst_init_metrics(&rt->dst, fi->fib_metrics, true);
+		dst_init_metrics(&rt->dst, fi->fib_metrics->metrics, true);
+		if (fi->fib_metrics != &dst_default_metrics) {
+			rt->dst._metrics |= DST_METRICS_REFCOUNTED;
+			atomic_inc(&fi->fib_metrics->refcnt);
+		}
 #ifdef CONFIG_IP_ROUTE_CLASSID
 		rt->dst.tclassid = nh->nh_tclassid;
 #endif
@@ -1958,6 +1972,7 @@
 {
 	int res;
 
+	tos &= IPTOS_RT_MASK;
 	rcu_read_lock();
 
 	/* Multicast recognition logic is moved from route cache to here.
@@ -2047,6 +2062,18 @@
 		 */
 		if (fi && res->prefixlen < 4)
 			fi = NULL;
+	} else if ((type == RTN_LOCAL) && (orig_oif != 0) &&
+		   (orig_oif != dev_out->ifindex)) {
+		/* For local routes that require a particular output interface
+		 * we do not want to cache the result.  Caching the result
+		 * causes incorrect behaviour when there are multiple source
+		 * addresses on the interface, the end result being that if the
+		 * intended recipient is waiting on that interface for the
+		 * packet he won't receive it because it will be delivered on
+		 * the loopback interface and the IP_PKTINFO ipi_ifindex will
+		 * be set to the loopback interface as well.
+		 */
+		fi = NULL;
 	}
 
 	fnhe = NULL;
@@ -2418,7 +2445,7 @@
 	r->rtm_dst_len	= 32;
 	r->rtm_src_len	= 0;
 	r->rtm_tos	= fl4->flowi4_tos;
-	r->rtm_table	= table_id;
+	r->rtm_table	= table_id < 256 ? table_id : RT_TABLE_COMPAT;
 	if (nla_put_u32(skb, RTA_TABLE, table_id))
 		goto nla_put_failure;
 	r->rtm_type	= rt->rt_type;
@@ -2487,7 +2514,8 @@
 		    IPV4_DEVCONF_ALL(net, MC_FORWARDING)) {
 			int err = ipmr_get_route(net, skb,
 						 fl4->saddr, fl4->daddr,
-						 r, nowait);
+						 r, nowait, portid);
+
 			if (err <= 0) {
 				if (!nowait) {
 					if (err == 0)
@@ -2551,7 +2579,7 @@
 	skb_reset_network_header(skb);
 
 	/* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
-	ip_hdr(skb)->protocol = IPPROTO_ICMP;
+	ip_hdr(skb)->protocol = IPPROTO_UDP;
 	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
 
 	src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 31b6a4c..2dc982b 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -374,9 +374,8 @@
 	flowi4_init_output(&fl4, sk->sk_bound_dev_if, ireq->ir_mark,
 			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
 			   inet_sk_flowi_flags(sk),
-			   (opt && opt->srr) ? opt->faddr : ireq->ir_rmt_addr,
-			   ireq->ir_loc_addr, th->source, th->dest,
-			   sock_i_uid(sk));
+			   opt->srr ? opt->faddr : ireq->ir_rmt_addr,
+			   ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid);
 	security_req_classify_flow(req, flowi4_to_flowi(&fl4));
 	rt = ip_route_output_key(sock_net(sk), &fl4);
 	if (IS_ERR(rt)) {
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index b1784c8..4612336 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -97,11 +97,11 @@
 		container_of(table->data, struct net, ipv4.ping_group_range.range);
 	unsigned int seq;
 	do {
-		seq = read_seqbegin(&net->ipv4.ip_local_ports.lock);
+		seq = read_seqbegin(&net->ipv4.ping_group_range.lock);
 
 		*low = data[0];
 		*high = data[1];
-	} while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq));
+	} while (read_seqretry(&net->ipv4.ping_group_range.lock, seq));
 }
 
 /* Update system visible IP port range */
@@ -110,10 +110,10 @@
 	kgid_t *data = table->data;
 	struct net *net =
 		container_of(table->data, struct net, ipv4.ping_group_range.range);
-	write_seqlock(&net->ipv4.ip_local_ports.lock);
+	write_seqlock(&net->ipv4.ping_group_range.lock);
 	data[0] = low;
 	data[1] = high;
-	write_sequnlock(&net->ipv4.ip_local_ports.lock);
+	write_sequnlock(&net->ipv4.ping_group_range.lock);
 }
 
 /* Validate changes from /proc interface. */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 6ecfc9d..c31eff7 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -783,6 +783,12 @@
 				ret = -EAGAIN;
 				break;
 			}
+			/* if __tcp_splice_read() got nothing while we have
+			 * an skb in receive queue, we do not want to loop.
+			 * This might happen with URG data.
+			 */
+			if (!skb_queue_empty(&sk->sk_receive_queue))
+				break;
 			sk_wait_data(sk, &timeo, NULL);
 			if (signal_pending(current)) {
 				ret = sock_intr_errno(timeo);
@@ -1065,9 +1071,12 @@
 				int *copied, size_t size)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
+	struct sockaddr *uaddr = msg->msg_name;
 	int err, flags;
 
-	if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE))
+	if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) ||
+	    (uaddr && msg->msg_namelen >= sizeof(uaddr->sa_family) &&
+	     uaddr->sa_family == AF_UNSPEC))
 		return -EOPNOTSUPP;
 	if (tp->fastopen_req)
 		return -EALREADY; /* Another Fast Open is in progress */
@@ -1080,7 +1089,7 @@
 	tp->fastopen_req->size = size;
 
 	flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
-	err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
+	err = __inet_stream_connect(sk->sk_socket, uaddr,
 				    msg->msg_namelen, flags);
 	*copied = tp->fastopen_req->copied;
 	tcp_free_fastopen_req(tp);
@@ -1212,7 +1221,7 @@
 
 			if (!skb_can_coalesce(skb, i, pfrag->page,
 					      pfrag->offset)) {
-				if (i == sysctl_max_skb_frags || !sg) {
+				if (i >= sysctl_max_skb_frags || !sg) {
 					tcp_mark_push(tp, skb);
 					goto new_segment;
 				}
@@ -2254,6 +2263,7 @@
 	tcp_init_send_head(sk);
 	memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
 	__sk_dst_reset(sk);
+	tcp_saved_syn_free(tp);
 
 	WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
 
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 882caa4..aafe681 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -183,6 +183,7 @@
 {
 	const struct inet_connection_sock *icsk = inet_csk(sk);
 
+	tcp_sk(sk)->prior_ssthresh = 0;
 	if (icsk->icsk_ca_ops->init)
 		icsk->icsk_ca_ops->init(sk);
 	if (tcp_ca_needs_ecn(sk))
diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c
index 7e538f7..55d7da1 100644
--- a/net/ipv4/tcp_dctcp.c
+++ b/net/ipv4/tcp_dctcp.c
@@ -56,6 +56,7 @@
 	u32 next_seq;
 	u32 ce_state;
 	u32 delayed_ack_reserved;
+	u32 loss_cwnd;
 };
 
 static unsigned int dctcp_shift_g __read_mostly = 4; /* g = 1/2^4 */
@@ -96,6 +97,7 @@
 		ca->dctcp_alpha = min(dctcp_alpha_on_init, DCTCP_MAX_ALPHA);
 
 		ca->delayed_ack_reserved = 0;
+		ca->loss_cwnd = 0;
 		ca->ce_state = 0;
 
 		dctcp_reset(tp, ca);
@@ -111,9 +113,10 @@
 
 static u32 dctcp_ssthresh(struct sock *sk)
 {
-	const struct dctcp *ca = inet_csk_ca(sk);
+	struct dctcp *ca = inet_csk_ca(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 
+	ca->loss_cwnd = tp->snd_cwnd;
 	return max(tp->snd_cwnd - ((tp->snd_cwnd * ca->dctcp_alpha) >> 11U), 2U);
 }
 
@@ -308,12 +311,20 @@
 	return 0;
 }
 
+static u32 dctcp_cwnd_undo(struct sock *sk)
+{
+	const struct dctcp *ca = inet_csk_ca(sk);
+
+	return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);
+}
+
 static struct tcp_congestion_ops dctcp __read_mostly = {
 	.init		= dctcp_init,
 	.in_ack_event   = dctcp_update_alpha,
 	.cwnd_event	= dctcp_cwnd_event,
 	.ssthresh	= dctcp_ssthresh,
 	.cong_avoid	= tcp_reno_cong_avoid,
+	.undo_cwnd	= dctcp_cwnd_undo,
 	.set_state	= dctcp_state,
 	.get_info	= dctcp_get_info,
 	.flags		= TCP_CONG_NEEDS_ECN,
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
index 55be6ac..fca6182 100644
--- a/net/ipv4/tcp_fastopen.c
+++ b/net/ipv4/tcp_fastopen.c
@@ -112,7 +112,7 @@
 		struct tcp_fastopen_cookie tmp;
 
 		if (__tcp_fastopen_cookie_gen(&ip6h->saddr, &tmp)) {
-			struct in6_addr *buf = (struct in6_addr *) tmp.val;
+			struct in6_addr *buf = &tmp.addr;
 			int i;
 
 			for (i = 0; i < 4; i++)
@@ -161,6 +161,7 @@
 	 * scaled. So correct it appropriately.
 	 */
 	tp->snd_wnd = ntohs(tcp_hdr(skb)->window);
+	tp->max_window = tp->snd_wnd;
 
 	/* Activate the retrans timer so that SYNACK can be retransmitted.
 	 * The request socket is not added to the ehash
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index da34f83..197a3d2 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -89,7 +89,7 @@
 EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
 
 /* rfc5961 challenge ack rate limiting */
-int sysctl_tcp_challenge_ack_limit = 100;
+int sysctl_tcp_challenge_ack_limit = 1000;
 
 int sysctl_tcp_stdurg __read_mostly;
 int sysctl_tcp_rfc1337 __read_mostly;
@@ -1135,13 +1135,14 @@
 		 */
 		if (pkt_len > mss) {
 			unsigned int new_len = (pkt_len / mss) * mss;
-			if (!in_sack && new_len < pkt_len) {
+			if (!in_sack && new_len < pkt_len)
 				new_len += mss;
-				if (new_len >= skb->len)
-					return 0;
-			}
 			pkt_len = new_len;
 		}
+
+		if (pkt_len >= skb->len && !in_sack)
+			return 0;
+
 		err = tcp_fragment(sk, skb, pkt_len, mss, GFP_ATOMIC);
 		if (err < 0)
 			return err;
@@ -2165,8 +2166,7 @@
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *skb;
-	int cnt, oldcnt;
-	int err;
+	int cnt, oldcnt, lost;
 	unsigned int mss;
 	/* Use SACK to deduce losses of new sequences sent during recovery */
 	const u32 loss_high = tcp_is_sack(tp) ?  tp->snd_nxt : tp->high_seq;
@@ -2206,9 +2206,10 @@
 				break;
 
 			mss = tcp_skb_mss(skb);
-			err = tcp_fragment(sk, skb, (packets - oldcnt) * mss,
-					   mss, GFP_ATOMIC);
-			if (err < 0)
+			/* If needed, chop off the prefix to mark as lost. */
+			lost = (packets - oldcnt) * mss;
+			if (lost < skb->len &&
+			    tcp_fragment(sk, skb, lost, mss, GFP_ATOMIC) < 0)
 				break;
 			cnt = packets;
 		}
@@ -2325,10 +2326,9 @@
 	}
 #if IS_ENABLED(CONFIG_IPV6)
 	else if (sk->sk_family == AF_INET6) {
-		struct ipv6_pinfo *np = inet6_sk(sk);
 		pr_debug("Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n",
 			 msg,
-			 &np->daddr, ntohs(inet->inet_dport),
+			 &sk->sk_v6_daddr, ntohs(inet->inet_dport),
 			 tp->snd_cwnd, tcp_left_out(tp),
 			 tp->snd_ssthresh, tp->prior_ssthresh,
 			 tp->packets_out);
@@ -3221,7 +3221,7 @@
 			int delta;
 
 			/* Non-retransmitted hole got filled? That's reordering */
-			if (reord < prior_fackets)
+			if (reord < prior_fackets && reord <= tp->fackets_out)
 				tcp_update_reordering(sk, tp->fackets_out - reord, 0);
 
 			delta = tcp_is_fack(tp) ? pkts_acked :
@@ -3391,6 +3391,23 @@
 	return flag;
 }
 
+static bool __tcp_oow_rate_limited(struct net *net, int mib_idx,
+				   u32 *last_oow_ack_time)
+{
+	if (*last_oow_ack_time) {
+		s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time);
+
+		if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) {
+			NET_INC_STATS_BH(net, mib_idx);
+			return true;	/* rate-limited: don't send yet! */
+		}
+	}
+
+	*last_oow_ack_time = tcp_time_stamp;
+
+	return false;	/* not rate-limited: go ahead, send dupack now! */
+}
+
 /* Return true if we're currently rate-limiting out-of-window ACKs and
  * thus shouldn't send a dupack right now. We rate-limit dupacks in
  * response to out-of-window SYNs or ACKs to mitigate ACK loops or DoS
@@ -3404,21 +3421,9 @@
 	/* Data packets without SYNs are not likely part of an ACK loop. */
 	if ((TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq) &&
 	    !tcp_hdr(skb)->syn)
-		goto not_rate_limited;
+		return false;
 
-	if (*last_oow_ack_time) {
-		s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time);
-
-		if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) {
-			NET_INC_STATS_BH(net, mib_idx);
-			return true;	/* rate-limited: don't send yet! */
-		}
-	}
-
-	*last_oow_ack_time = tcp_time_stamp;
-
-not_rate_limited:
-	return false;	/* not rate-limited: go ahead, send dupack now! */
+	return __tcp_oow_rate_limited(net, mib_idx, last_oow_ack_time);
 }
 
 /* RFC 5961 7 [ACK Throttling] */
@@ -3428,21 +3433,26 @@
 	static u32 challenge_timestamp;
 	static unsigned int challenge_count;
 	struct tcp_sock *tp = tcp_sk(sk);
-	u32 now;
+	u32 count, now;
 
 	/* First check our per-socket dupack rate limit. */
-	if (tcp_oow_rate_limited(sock_net(sk), skb,
-				 LINUX_MIB_TCPACKSKIPPEDCHALLENGE,
-				 &tp->last_oow_ack_time))
+	if (__tcp_oow_rate_limited(sock_net(sk),
+				   LINUX_MIB_TCPACKSKIPPEDCHALLENGE,
+				   &tp->last_oow_ack_time))
 		return;
 
-	/* Then check the check host-wide RFC 5961 rate limit. */
+	/* Then check host-wide RFC 5961 rate limit. */
 	now = jiffies / HZ;
 	if (now != challenge_timestamp) {
+		u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1;
+
 		challenge_timestamp = now;
-		challenge_count = 0;
+		WRITE_ONCE(challenge_count, half +
+			   prandom_u32_max(sysctl_tcp_challenge_ack_limit));
 	}
-	if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
+	count = READ_ONCE(challenge_count);
+	if (count > 0) {
+		WRITE_ONCE(challenge_count, count - 1);
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
 		tcp_send_ack(sk);
 	}
@@ -5427,6 +5437,7 @@
 	struct inet_connection_sock *icsk = inet_csk(sk);
 
 	tcp_set_state(sk, TCP_ESTABLISHED);
+	icsk->icsk_ack.lrcvtime = tcp_time_stamp;
 
 	if (skb) {
 		icsk->icsk_af_ops->sk_rx_dst_set(sk, skb);
@@ -5639,7 +5650,6 @@
 			 * to stand against the temptation 8)     --ANK
 			 */
 			inet_csk_schedule_ack(sk);
-			icsk->icsk_ack.lrcvtime = tcp_time_stamp;
 			tcp_enter_quickack_mode(sk);
 			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
 						  TCP_DELACK_MAX, TCP_RTO_MAX);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 7decaa4..984de80 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -271,10 +271,13 @@
  */
 void tcp_v4_mtu_reduced(struct sock *sk)
 {
-	struct dst_entry *dst;
 	struct inet_sock *inet = inet_sk(sk);
-	u32 mtu = tcp_sk(sk)->mtu_info;
+	struct dst_entry *dst;
+	u32 mtu;
 
+	if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
+		return;
+	mtu = tcp_sk(sk)->mtu_info;
 	dst = inet_csk_update_pmtu(sk, mtu);
 	if (!dst)
 		return;
@@ -420,7 +423,8 @@
 
 	switch (type) {
 	case ICMP_REDIRECT:
-		do_redirect(icmp_skb, sk);
+		if (!sock_owned_by_user(sk))
+			do_redirect(icmp_skb, sk);
 		goto out;
 	case ICMP_SOURCE_QUENCH:
 		/* Just silently ignore these. */
@@ -687,6 +691,7 @@
 		arg.bound_dev_if = sk->sk_bound_dev_if;
 
 	arg.tos = ip_hdr(skb)->tos;
+	arg.uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
 	ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
 			      skb, &TCP_SKB_CB(skb)->header.h4.opt,
 			      ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
@@ -708,8 +713,8 @@
    outside socket context is ugly, certainly. What can I do?
  */
 
-static void tcp_v4_send_ack(struct net *net,
-			    struct sk_buff *skb, u32 seq, u32 ack,
+static void tcp_v4_send_ack(const struct sock *sk, struct sk_buff *skb,
+			    u32 seq, u32 ack,
 			    u32 win, u32 tsval, u32 tsecr, int oif,
 			    struct tcp_md5sig_key *key,
 			    int reply_flags, u8 tos)
@@ -724,6 +729,7 @@
 			];
 	} rep;
 	struct ip_reply_arg arg;
+	struct net *net = sock_net(sk);
 
 	memset(&rep.th, 0, sizeof(struct tcphdr));
 	memset(&arg, 0, sizeof(arg));
@@ -772,6 +778,7 @@
 	if (oif)
 		arg.bound_dev_if = oif;
 	arg.tos = tos;
+	arg.uid = sock_net_uid(net, sk_fullsock(sk) ? sk : NULL);
 	ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
 			      skb, &TCP_SKB_CB(skb)->header.h4.opt,
 			      ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
@@ -785,8 +792,7 @@
 	struct inet_timewait_sock *tw = inet_twsk(sk);
 	struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
 
-	tcp_v4_send_ack(sock_net(sk), skb,
-			tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+	tcp_v4_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
 			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
 			tcp_time_stamp + tcptw->tw_ts_offset,
 			tcptw->tw_ts_recent,
@@ -805,10 +811,8 @@
 	/* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
 	 * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
 	 */
-	u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 :
-					     tcp_sk(sk)->snd_nxt;
-
-	tcp_v4_send_ack(sock_net(sk), skb, seq,
+	tcp_v4_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ?
+			tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
 			tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd,
 			tcp_time_stamp,
 			req->ts_recent,
@@ -1527,6 +1531,21 @@
 }
 EXPORT_SYMBOL(tcp_prequeue);
 
+int tcp_filter(struct sock *sk, struct sk_buff *skb)
+{
+	struct tcphdr *th = (struct tcphdr *)skb->data;
+	unsigned int eaten = skb->len;
+	int err;
+
+	err = sk_filter_trim_cap(sk, skb, th->doff * 4);
+	if (!err) {
+		eaten -= skb->len;
+		TCP_SKB_CB(skb)->end_seq -= eaten;
+	}
+	return err;
+}
+EXPORT_SYMBOL(tcp_filter);
+
 /*
  *	From tcp_input.c
  */
@@ -1632,8 +1651,10 @@
 
 	nf_reset(skb);
 
-	if (sk_filter(sk, skb))
+	if (tcp_filter(sk, skb))
 		goto discard_and_relse;
+	th = (const struct tcphdr *)skb->data;
+	iph = ip_hdr(skb);
 
 	skb->dev = NULL;
 
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
index 1e70fa8..3861ded 100644
--- a/net/ipv4/tcp_lp.c
+++ b/net/ipv4/tcp_lp.c
@@ -264,13 +264,15 @@
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct lp *lp = inet_csk_ca(sk);
+	u32 delta;
 
 	if (rtt_us > 0)
 		tcp_lp_rtt_sample(sk, rtt_us);
 
 	/* calc inference */
-	if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
-		lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr);
+	delta = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
+	if ((s32)delta > 0)
+		lp->inference = 3 * delta;
 
 	/* test if within inference */
 	if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference))
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 9475a27..4c1c94f 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -472,6 +472,7 @@
 		newtp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT);
 		newtp->rtt_min[0].rtt = ~0U;
 		newicsk->icsk_rto = TCP_TIMEOUT_INIT;
+		newicsk->icsk_ack.lrcvtime = tcp_time_stamp;
 
 		newtp->packets_out = 0;
 		newtp->retrans_out = 0;
@@ -546,6 +547,7 @@
 			newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
 		newtp->rx_opt.mss_clamp = req->mss;
 		tcp_ecn_openreq_child(newtp, req);
+		newtp->fastopen_req = NULL;
 		newtp->fastopen_rsk = NULL;
 		newtp->syn_data_acked = 0;
 		newtp->rack.mstamp.v64 = 0;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9f069bd..2ca323b 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -239,7 +239,8 @@
 		/* Set window scaling on max possible window
 		 * See RFC1323 for an explanation of the limit to 14
 		 */
-		space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max);
+		space = max_t(u32, space, sysctl_tcp_rmem[2]);
+		space = max_t(u32, space, sysctl_rmem_max);
 		space = min_t(u32, space, *window_clamp);
 		while (space > 65535 && (*rcv_wscale) < 14) {
 			space >>= 1;
@@ -1220,7 +1221,7 @@
  * eventually). The difference is that pulled data not copied, but
  * immediately discarded.
  */
-static void __pskb_trim_head(struct sk_buff *skb, int len)
+static int __pskb_trim_head(struct sk_buff *skb, int len)
 {
 	struct skb_shared_info *shinfo;
 	int i, k, eat;
@@ -1230,7 +1231,7 @@
 		__skb_pull(skb, eat);
 		len -= eat;
 		if (!len)
-			return;
+			return 0;
 	}
 	eat = len;
 	k = 0;
@@ -1256,23 +1257,28 @@
 	skb_reset_tail_pointer(skb);
 	skb->data_len -= len;
 	skb->len = skb->data_len;
+	return len;
 }
 
 /* Remove acked data from a packet in the transmit queue. */
 int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
 {
+	u32 delta_truesize;
+
 	if (skb_unclone(skb, GFP_ATOMIC))
 		return -ENOMEM;
 
-	__pskb_trim_head(skb, len);
+	delta_truesize = __pskb_trim_head(skb, len);
 
 	TCP_SKB_CB(skb)->seq += len;
 	skb->ip_summed = CHECKSUM_PARTIAL;
 
-	skb->truesize	     -= len;
-	sk->sk_wmem_queued   -= len;
-	sk_mem_uncharge(sk, len);
-	sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
+	if (delta_truesize) {
+		skb->truesize	   -= delta_truesize;
+		sk->sk_wmem_queued -= delta_truesize;
+		sk_mem_uncharge(sk, delta_truesize);
+		sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
+	}
 
 	/* Any change of skb->len requires recalculation of tso factor. */
 	if (tcp_skb_pcount(skb) > 1)
@@ -1949,12 +1955,14 @@
 	len = 0;
 	tcp_for_write_queue_from_safe(skb, next, sk) {
 		copy = min_t(int, skb->len, probe_size - len);
-		if (nskb->ip_summed)
+		if (nskb->ip_summed) {
 			skb_copy_bits(skb, 0, skb_put(nskb, copy), copy);
-		else
-			nskb->csum = skb_copy_and_csum_bits(skb, 0,
-							    skb_put(nskb, copy),
-							    copy, nskb->csum);
+		} else {
+			__wsum csum = skb_copy_and_csum_bits(skb, 0,
+							     skb_put(nskb, copy),
+							     copy, 0);
+			nskb->csum = csum_block_add(nskb->csum, csum, len);
+		}
 
 		if (skb->len <= copy) {
 			/* We've eaten all the data from this skb.
@@ -2380,9 +2388,11 @@
 	int full_space = min_t(int, tp->window_clamp, allowed_space);
 	int window;
 
-	if (mss > full_space)
+	if (unlikely(mss > full_space)) {
 		mss = full_space;
-
+		if (mss <= 0)
+			return 0;
+	}
 	if (free_space < (full_space >> 1)) {
 		icsk->icsk_ack.quick = 0;
 
@@ -2568,7 +2578,8 @@
 	 * copying overhead: fragmentation, tunneling, mangling etc.
 	 */
 	if (atomic_read(&sk->sk_wmem_alloc) >
-	    min(sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), sk->sk_sndbuf))
+	    min_t(u32, sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2),
+		  sk->sk_sndbuf))
 		return -EAGAIN;
 
 	if (skb_still_in_host_queue(sk, skb))
@@ -2625,8 +2636,10 @@
 	 */
 	if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) ||
 		     skb_headroom(skb) >= 0xFFFF)) {
-		struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
-						   GFP_ATOMIC);
+		struct sk_buff *nskb;
+
+		skb_mstamp_get(&skb->skb_mstamp);
+		nskb = __pskb_copy(skb, MAX_TCP_HEADER, GFP_ATOMIC);
 		err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
 			     -ENOBUFS;
 	} else {
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 193ba1f..ebb34d0 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -223,7 +223,8 @@
 
 	sk_mem_reclaim_partial(sk);
 
-	if (sk->sk_state == TCP_CLOSE || !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
+	if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
+	    !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
 		goto out;
 
 	if (time_after(icsk->icsk_ack.timeout, jiffies)) {
@@ -504,7 +505,8 @@
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	int event;
 
-	if (sk->sk_state == TCP_CLOSE || !icsk->icsk_pending)
+	if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
+	    !icsk->icsk_pending)
 		goto out;
 
 	if (time_after(icsk->icsk_timeout, jiffies)) {
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c
index 3e6a472..92ab5bc 100644
--- a/net/ipv4/tcp_yeah.c
+++ b/net/ipv4/tcp_yeah.c
@@ -75,7 +75,7 @@
 	if (!tcp_is_cwnd_limited(sk))
 		return;
 
-	if (tp->snd_cwnd <= tp->snd_ssthresh)
+	if (tcp_in_slow_start(tp))
 		tcp_slow_start(tp, acked);
 
 	else if (!yeah->doing_reno_now) {
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 2ef43a1..ad3d153 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1026,7 +1026,7 @@
 				   RT_SCOPE_UNIVERSE, sk->sk_protocol,
 				   flow_flags,
 				   faddr, saddr, dport, inet->inet_sport,
-				   sock_i_uid(sk));
+				   sk->sk_uid);
 
 		if (!saddr && ipc.oif) {
 			err = l3mdev_get_saddr(net, ipc.oif, fl4);
@@ -1276,6 +1276,7 @@
 	int peeked, off = 0;
 	int err;
 	int is_udplite = IS_UDPLITE(sk);
+	bool checksum_valid = false;
 	bool slow;
 
 	if (flags & MSG_ERRQUEUE)
@@ -1301,11 +1302,12 @@
 	 */
 
 	if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
-		if (udp_lib_checksum_complete(skb))
+		checksum_valid = !udp_lib_checksum_complete(skb);
+		if (!checksum_valid)
 			goto csum_copy_err;
 	}
 
-	if (skb_csum_unnecessary(skb))
+	if (checksum_valid || skb_csum_unnecessary(skb))
 		err = skb_copy_datagram_msg(skb, sizeof(struct udphdr),
 					    msg, copied);
 	else {
@@ -1341,7 +1343,7 @@
 		*addr_len = sizeof(*sin);
 	}
 	if (inet->cmsg_flags)
-		ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr));
+		ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr), off);
 
 	err = copied;
 	if (flags & MSG_TRUNC)
@@ -1532,7 +1534,7 @@
 
 		/* if we're overly short, let UDP handle it */
 		encap_rcv = ACCESS_ONCE(up->encap_rcv);
-		if (skb->len > sizeof(struct udphdr) && encap_rcv) {
+		if (encap_rcv) {
 			int ret;
 
 			/* Verify checksum before giving to encap */
@@ -2263,6 +2265,20 @@
 }
 EXPORT_SYMBOL(udp_poll);
 
+int udp_abort(struct sock *sk, int err)
+{
+	lock_sock(sk);
+
+	sk->sk_err = err;
+	sk->sk_error_report(sk);
+	udp_disconnect(sk, 0);
+
+	release_sock(sk);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(udp_abort);
+
 struct proto udp_prot = {
 	.name		   = "UDP",
 	.owner		   = THIS_MODULE,
@@ -2294,6 +2310,7 @@
 	.compat_getsockopt = compat_udp_getsockopt,
 #endif
 	.clear_sk	   = sk_prot_clear_portaddr_nulls,
+	.diag_destroy	   = udp_abort,
 };
 EXPORT_SYMBOL(udp_prot);
 
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 6116604..092aa60 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -20,7 +20,7 @@
 static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
 			struct netlink_callback *cb,
 			const struct inet_diag_req_v2 *req,
-			struct nlattr *bc)
+			struct nlattr *bc, bool net_admin)
 {
 	if (!inet_diag_bc_sk(bc, sk))
 		return 0;
@@ -28,7 +28,7 @@
 	return inet_sk_diag_fill(sk, NULL, skb, req,
 			sk_user_ns(NETLINK_CB(cb->skb).sk),
 			NETLINK_CB(cb->skb).portid,
-			cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
+			cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh, net_admin);
 }
 
 static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
@@ -75,7 +75,8 @@
 	err = inet_sk_diag_fill(sk, NULL, rep, req,
 			   sk_user_ns(NETLINK_CB(in_skb).sk),
 			   NETLINK_CB(in_skb).portid,
-			   nlh->nlmsg_seq, 0, nlh);
+			   nlh->nlmsg_seq, 0, nlh,
+			   netlink_net_capable(in_skb, CAP_NET_ADMIN));
 	if (err < 0) {
 		WARN_ON(err == -EMSGSIZE);
 		kfree_skb(rep);
@@ -98,6 +99,7 @@
 {
 	int num, s_num, slot, s_slot;
 	struct net *net = sock_net(skb->sk);
+	bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
 
 	s_slot = cb->args[0];
 	num = s_num = cb->args[1];
@@ -132,7 +134,7 @@
 			    r->id.idiag_dport)
 				goto next;
 
-			if (sk_diag_dump(sk, skb, cb, r, bc) < 0) {
+			if (sk_diag_dump(sk, skb, cb, r, bc, net_admin) < 0) {
 				spin_unlock_bh(&hslot->lock);
 				goto done;
 			}
@@ -165,12 +167,88 @@
 	r->idiag_wqueue = sk_wmem_alloc_get(sk);
 }
 
+#ifdef CONFIG_INET_DIAG_DESTROY
+static int __udp_diag_destroy(struct sk_buff *in_skb,
+			      const struct inet_diag_req_v2 *req,
+			      struct udp_table *tbl)
+{
+	struct net *net = sock_net(in_skb->sk);
+	struct sock *sk;
+	int err;
+
+	rcu_read_lock();
+
+	if (req->sdiag_family == AF_INET)
+		sk = __udp4_lib_lookup(net,
+				req->id.idiag_dst[0], req->id.idiag_dport,
+				req->id.idiag_src[0], req->id.idiag_sport,
+				req->id.idiag_if, tbl);
+#if IS_ENABLED(CONFIG_IPV6)
+	else if (req->sdiag_family == AF_INET6) {
+		if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) &&
+		    ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_src))
+			sk = __udp4_lib_lookup(net,
+					req->id.idiag_dst[3], req->id.idiag_dport,
+					req->id.idiag_src[3], req->id.idiag_sport,
+					req->id.idiag_if, tbl);
+
+		else
+			sk = __udp6_lib_lookup(net,
+					(struct in6_addr *)req->id.idiag_dst,
+					req->id.idiag_dport,
+					(struct in6_addr *)req->id.idiag_src,
+					req->id.idiag_sport,
+					req->id.idiag_if, tbl);
+	}
+#endif
+	else {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
+
+	if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
+		sk = NULL;
+
+	rcu_read_unlock();
+
+	if (!sk)
+		return -ENOENT;
+
+	if (sock_diag_check_cookie(sk, req->id.idiag_cookie)) {
+		sock_put(sk);
+		return -ENOENT;
+	}
+
+	err = sock_diag_destroy(sk, ECONNABORTED);
+
+	sock_put(sk);
+
+	return err;
+}
+
+static int udp_diag_destroy(struct sk_buff *in_skb,
+			    const struct inet_diag_req_v2 *req)
+{
+	return __udp_diag_destroy(in_skb, req, &udp_table);
+}
+
+static int udplite_diag_destroy(struct sk_buff *in_skb,
+				const struct inet_diag_req_v2 *req)
+{
+	return __udp_diag_destroy(in_skb, req, &udplite_table);
+}
+
+#endif
+
 static const struct inet_diag_handler udp_diag_handler = {
 	.dump		 = udp_diag_dump,
 	.dump_one	 = udp_diag_dump_one,
 	.idiag_get_info  = udp_diag_get_info,
 	.idiag_type	 = IPPROTO_UDP,
 	.idiag_info_size = 0,
+#ifdef CONFIG_INET_DIAG_DESTROY
+	.destroy	 = udp_diag_destroy,
+#endif
 };
 
 static void udplite_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
@@ -192,6 +270,9 @@
 	.idiag_get_info  = udp_diag_get_info,
 	.idiag_type	 = IPPROTO_UDPLITE,
 	.idiag_info_size = 0,
+#ifdef CONFIG_INET_DIAG_DESTROY
+	.destroy	 = udplite_diag_destroy,
+#endif
 };
 
 static int __init udp_diag_init(void)
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index f938616..6396f1c 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -299,14 +299,14 @@
 	unsigned int off = skb_gro_offset(skb);
 	int flush = 1;
 
-	if (NAPI_GRO_CB(skb)->udp_mark ||
+	if (NAPI_GRO_CB(skb)->encap_mark ||
 	    (skb->ip_summed != CHECKSUM_PARTIAL &&
 	     NAPI_GRO_CB(skb)->csum_cnt == 0 &&
 	     !NAPI_GRO_CB(skb)->csum_valid))
 		goto out;
 
-	/* mark that this skb passed once through the udp gro layer */
-	NAPI_GRO_CB(skb)->udp_mark = 1;
+	/* mark that this skb passed once through the tunnel gro layer */
+	NAPI_GRO_CB(skb)->encap_mark = 1;
 
 	rcu_read_lock();
 	uo_priv = rcu_dereference(udp_offload_base);
@@ -339,8 +339,8 @@
 	skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */
 	skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr));
 	NAPI_GRO_CB(skb)->proto = uo_priv->offload->ipproto;
-	pp = uo_priv->offload->callbacks.gro_receive(head, skb,
-						     uo_priv->offload);
+	pp = call_gro_receive_udp(uo_priv->offload->callbacks.gro_receive,
+				  head, skb, uo_priv->offload);
 
 out_unlock:
 	rcu_read_unlock();
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3cdf591..77a5c32 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -112,6 +112,27 @@
 	return (cstamp - INITIAL_JIFFIES) * 100UL / HZ;
 }
 
+static inline s32 rfc3315_s14_backoff_init(s32 irt)
+{
+	/* multiply 'initial retransmission time' by 0.9 .. 1.1 */
+	u64 tmp = (900000 + prandom_u32() % 200001) * (u64)irt;
+	do_div(tmp, 1000000);
+	return (s32)tmp;
+}
+
+static inline s32 rfc3315_s14_backoff_update(s32 rt, s32 mrt)
+{
+	/* multiply 'retransmission timeout' by 1.9 .. 2.1 */
+	u64 tmp = (1900000 + prandom_u32() % 200001) * (u64)rt;
+	do_div(tmp, 1000000);
+	if ((s32)tmp > mrt) {
+		/* multiply 'maximum retransmission time' by 0.9 .. 1.1 */
+		tmp = (900000 + prandom_u32() % 200001) * (u64)mrt;
+		do_div(tmp, 1000000);
+	}
+	return (s32)tmp;
+}
+
 #ifdef CONFIG_SYSCTL
 static int addrconf_sysctl_register(struct inet6_dev *idev);
 static void addrconf_sysctl_unregister(struct inet6_dev *idev);
@@ -187,6 +208,7 @@
 	.dad_transmits		= 1,
 	.rtr_solicits		= MAX_RTR_SOLICITATIONS,
 	.rtr_solicit_interval	= RTR_SOLICITATION_INTERVAL,
+	.rtr_solicit_max_interval = RTR_SOLICITATION_MAX_INTERVAL,
 	.rtr_solicit_delay	= MAX_RTR_SOLICITATION_DELAY,
 	.use_tempaddr		= 0,
 	.temp_valid_lft		= TEMP_VALID_LIFETIME,
@@ -202,6 +224,7 @@
 	.accept_ra_rtr_pref	= 1,
 	.rtr_probe_interval	= 60 * HZ,
 #ifdef CONFIG_IPV6_ROUTE_INFO
+	.accept_ra_rt_info_min_plen = 0,
 	.accept_ra_rt_info_max_plen = 0,
 #endif
 #endif
@@ -232,6 +255,7 @@
 	.dad_transmits		= 1,
 	.rtr_solicits		= MAX_RTR_SOLICITATIONS,
 	.rtr_solicit_interval	= RTR_SOLICITATION_INTERVAL,
+	.rtr_solicit_max_interval = RTR_SOLICITATION_MAX_INTERVAL,
 	.rtr_solicit_delay	= MAX_RTR_SOLICITATION_DELAY,
 	.use_tempaddr		= 0,
 	.temp_valid_lft		= TEMP_VALID_LIFETIME,
@@ -247,6 +271,7 @@
 	.accept_ra_rtr_pref	= 1,
 	.rtr_probe_interval	= 60 * HZ,
 #ifdef CONFIG_IPV6_ROUTE_INFO
+	.accept_ra_rt_info_min_plen = 0,
 	.accept_ra_rt_info_max_plen = 0,
 #endif
 #endif
@@ -293,9 +318,9 @@
 static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp,
 				   unsigned long delay)
 {
-	if (!delayed_work_pending(&ifp->dad_work))
-		in6_ifa_hold(ifp);
-	mod_delayed_work(addrconf_wq, &ifp->dad_work, delay);
+	in6_ifa_hold(ifp);
+	if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay))
+		in6_ifa_put(ifp);
 }
 
 static int snmp6_alloc_dev(struct inet6_dev *idev)
@@ -1900,6 +1925,7 @@
 	spin_unlock_bh(&ifp->lock);
 
 	addrconf_mod_dad_work(ifp, 0);
+	in6_ifa_put(ifp);
 }
 
 /* Join to solicited addr multicast group.
@@ -2942,7 +2968,7 @@
 				 * lo device down, release this obsolete dst and
 				 * reallocate a new router for ifa.
 				 */
-				if (sp_ifa->rt->dst.obsolete > 0) {
+				if (!atomic_read(&sp_ifa->rt->rt6i_ref)) {
 					ip6_rt_put(sp_ifa->rt);
 					sp_ifa->rt = NULL;
 				} else {
@@ -3237,9 +3263,15 @@
 			}
 
 			if (idev) {
-				if (idev->if_flags & IF_READY)
-					/* device is already configured. */
+				if (idev->if_flags & IF_READY) {
+					/* device is already configured -
+					 * but resend MLD reports, we might
+					 * have roamed and need to update
+					 * multicast snooping switches
+					 */
+					ipv6_mc_up(idev);
 					break;
+				}
 				idev->if_flags |= IF_READY;
 			}
 
@@ -3332,6 +3364,7 @@
  */
 static struct notifier_block ipv6_dev_notf = {
 	.notifier_call = addrconf_notify,
+	.priority = ADDRCONF_NOTIFY_PRIORITY,
 };
 
 static void addrconf_type_change(struct net_device *dev, unsigned long event)
@@ -3484,7 +3517,7 @@
 	if (idev->if_flags & IF_RA_RCVD)
 		goto out;
 
-	if (idev->rs_probes++ < idev->cnf.rtr_solicits) {
+	if (idev->rs_probes++ < idev->cnf.rtr_solicits || idev->cnf.rtr_solicits < 0) {
 		write_unlock(&idev->lock);
 		if (!ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
 			ndisc_send_rs(dev, &lladdr,
@@ -3493,11 +3526,13 @@
 			goto put;
 
 		write_lock(&idev->lock);
+		idev->rs_interval = rfc3315_s14_backoff_update(
+			idev->rs_interval, idev->cnf.rtr_solicit_max_interval);
 		/* The wait after the last probe can be shorter */
 		addrconf_mod_rs_timer(idev, (idev->rs_probes ==
 					     idev->cnf.rtr_solicits) ?
 				      idev->cnf.rtr_solicit_delay :
-				      idev->cnf.rtr_solicit_interval);
+				      idev->rs_interval);
 	} else {
 		/*
 		 * Note: we do not support deprecated "all on-link"
@@ -3636,6 +3671,7 @@
 		addrconf_dad_begin(ifp);
 		goto out;
 	} else if (action == DAD_ABORT) {
+		in6_ifa_hold(ifp);
 		addrconf_dad_stop(ifp, 1);
 		goto out;
 	}
@@ -3724,7 +3760,7 @@
 	send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp);
 	send_rs = send_mld &&
 		  ipv6_accept_ra(ifp->idev) &&
-		  ifp->idev->cnf.rtr_solicits > 0 &&
+		  ifp->idev->cnf.rtr_solicits != 0 &&
 		  (dev->flags&IFF_LOOPBACK) == 0;
 	read_unlock_bh(&ifp->idev->lock);
 
@@ -3746,10 +3782,11 @@
 
 		write_lock_bh(&ifp->idev->lock);
 		spin_lock(&ifp->lock);
+		ifp->idev->rs_interval = rfc3315_s14_backoff_init(
+			ifp->idev->cnf.rtr_solicit_interval);
 		ifp->idev->rs_probes = 1;
 		ifp->idev->if_flags |= IF_RS_SENT;
-		addrconf_mod_rs_timer(ifp->idev,
-				      ifp->idev->cnf.rtr_solicit_interval);
+		addrconf_mod_rs_timer(ifp->idev, ifp->idev->rs_interval);
 		spin_unlock(&ifp->lock);
 		write_unlock_bh(&ifp->idev->lock);
 	}
@@ -4666,6 +4703,8 @@
 	array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
 	array[DEVCONF_RTR_SOLICIT_INTERVAL] =
 		jiffies_to_msecs(cnf->rtr_solicit_interval);
+	array[DEVCONF_RTR_SOLICIT_MAX_INTERVAL] =
+		jiffies_to_msecs(cnf->rtr_solicit_max_interval);
 	array[DEVCONF_RTR_SOLICIT_DELAY] =
 		jiffies_to_msecs(cnf->rtr_solicit_delay);
 	array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
@@ -4687,6 +4726,7 @@
 	array[DEVCONF_RTR_PROBE_INTERVAL] =
 		jiffies_to_msecs(cnf->rtr_probe_interval);
 #ifdef CONFIG_IPV6_ROUTE_INFO
+	array[DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN] = cnf->accept_ra_rt_info_min_plen;
 	array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
 #endif
 #endif
@@ -4874,7 +4914,7 @@
 		return -EINVAL;
 	if (!ipv6_accept_ra(idev))
 		return -EINVAL;
-	if (idev->cnf.rtr_solicits <= 0)
+	if (idev->cnf.rtr_solicits == 0)
 		return -EINVAL;
 
 	write_lock_bh(&idev->lock);
@@ -4899,8 +4939,10 @@
 
 	if (update_rs) {
 		idev->if_flags |= IF_RS_SENT;
+		idev->rs_interval = rfc3315_s14_backoff_init(
+			idev->cnf.rtr_solicit_interval);
 		idev->rs_probes = 1;
-		addrconf_mod_rs_timer(idev, idev->cnf.rtr_solicit_interval);
+		addrconf_mod_rs_timer(idev, idev->rs_interval);
 	}
 
 	/* Well, that's kinda nasty ... */
@@ -5270,8 +5312,7 @@
 	struct net_device *dev;
 	struct inet6_dev *idev;
 
-	rcu_read_lock();
-	for_each_netdev_rcu(net, dev) {
+	for_each_netdev(net, dev) {
 		idev = __in6_dev_get(dev);
 		if (idev) {
 			int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
@@ -5280,7 +5321,6 @@
 				dev_disable_change(idev);
 		}
 	}
-	rcu_read_unlock();
 }
 
 static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
@@ -5540,6 +5580,13 @@
 			.proc_handler	= proc_dointvec_jiffies,
 		},
 		{
+			.procname	= "router_solicitation_max_interval",
+			.data		= &ipv6_devconf.rtr_solicit_max_interval,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= proc_dointvec_jiffies,
+		},
+		{
 			.procname	= "router_solicitation_delay",
 			.data		= &ipv6_devconf.rtr_solicit_delay,
 			.maxlen		= sizeof(int),
@@ -5649,6 +5696,13 @@
 		},
 #ifdef CONFIG_IPV6_ROUTE_INFO
 		{
+			.procname	= "accept_ra_rt_info_min_plen",
+			.data		= &ipv6_devconf.accept_ra_rt_info_min_plen,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= proc_dointvec,
+		},
+		{
 			.procname	= "accept_ra_rt_info_max_plen",
 			.data		= &ipv6_devconf.accept_ra_rt_info_max_plen,
 			.maxlen		= sizeof(int),
@@ -5975,6 +6029,8 @@
 		goto errlo;
 	}
 
+	ip6_route_init_special_entries();
+
 	for (i = 0; i < IN6_ADDR_HSIZE; i++)
 		INIT_HLIST_HEAD(&inet6_addr_lst[i]);
 
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 669639d..1604163 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -64,6 +64,20 @@
 #include <asm/uaccess.h>
 #include <linux/mroute6.h>
 
+#ifdef CONFIG_ANDROID_PARANOID_NETWORK
+#include <linux/android_aid.h>
+
+static inline int current_has_network(void)
+{
+	return in_egroup_p(AID_INET) || capable(CAP_NET_RAW);
+}
+#else
+static inline int current_has_network(void)
+{
+	return 1;
+}
+#endif
+
 MODULE_AUTHOR("Cast of dozens");
 MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
 MODULE_LICENSE("GPL");
@@ -112,6 +126,9 @@
 	if (protocol < 0 || protocol >= IPPROTO_MAX)
 		return -EINVAL;
 
+	if (!current_has_network())
+		return -EACCES;
+
 	/* Look for the requested type/protocol pair. */
 lookup_protocol:
 	err = -ESOCKTNOSUPPORT;
@@ -158,8 +175,7 @@
 	}
 
 	err = -EPERM;
-	if (sock->type == SOCK_RAW && !kern &&
-	    !ns_capable(net->user_ns, CAP_NET_RAW))
+	if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
 		goto out_rcu_unlock;
 
 	sock->ops = answer->ops;
@@ -662,7 +678,7 @@
 		fl6.flowi6_mark = sk->sk_mark;
 		fl6.fl6_dport = inet->inet_dport;
 		fl6.fl6_sport = inet->inet_sport;
-		fl6.flowi6_uid = sock_i_uid(sk);
+		fl6.flowi6_uid = sk->sk_uid;
 		security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
 		rcu_read_lock();
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index c52b8fc..189eb10 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -662,9 +662,10 @@
 		return 0;
 
 	if (type == NDISC_REDIRECT)
-		ip6_redirect(skb, net, skb->dev->ifindex, 0);
+		ip6_redirect(skb, net, skb->dev->ifindex, 0,
+			     sock_net_uid(net, NULL));
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
 	xfrm_state_put(x);
 
 	return 0;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 183ff87..56528e9 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -76,18 +76,22 @@
 		}
 	}
 
-	addr_type = ipv6_addr_type(&usin->sin6_addr);
-
-	if (addr_type == IPV6_ADDR_ANY) {
+	if (ipv6_addr_any(&usin->sin6_addr)) {
 		/*
 		 *	connect to self
 		 */
-		usin->sin6_addr.s6_addr[15] = 0x01;
+		if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
+			ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
+					       &usin->sin6_addr);
+		else
+			usin->sin6_addr = in6addr_loopback;
 	}
 
+	addr_type = ipv6_addr_type(&usin->sin6_addr);
+
 	daddr = &usin->sin6_addr;
 
-	if (addr_type == IPV6_ADDR_MAPPED) {
+	if (addr_type & IPV6_ADDR_MAPPED) {
 		struct sockaddr_in sin;
 
 		if (__ipv6_only_sock(sk)) {
@@ -161,7 +165,7 @@
 	fl6.flowi6_mark = sk->sk_mark;
 	fl6.fl6_dport = inet->inet_dport;
 	fl6.fl6_sport = inet->inet_sport;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 
 	if (!fl6.flowi6_oif)
 		fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index f921368..cbcdd5d 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -418,7 +418,7 @@
 		esph = (void *)skb_push(skb, 4);
 		*seqhi = esph->spi;
 		esph->spi = esph->seq_no;
-		esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.input.hi);
+		esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi;
 		aead_request_set_callback(req, 0, esp_input_done_esn, skb);
 	}
 
@@ -474,9 +474,10 @@
 		return 0;
 
 	if (type == NDISC_REDIRECT)
-		ip6_redirect(skb, net, skb->dev->ifindex, 0);
+		ip6_redirect(skb, net, skb->dev->ifindex, 0,
+			     sock_net_uid(net, NULL));
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
 	xfrm_state_put(x);
 
 	return 0;
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index ed33abf..9ac4f0c 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -32,7 +32,6 @@
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
 				   int flags, pol_lookup_t lookup)
 {
-	struct rt6_info *rt;
 	struct fib_lookup_arg arg = {
 		.lookup_ptr = lookup,
 		.flags = FIB_LOOKUP_NOREF,
@@ -41,21 +40,11 @@
 	fib_rules_lookup(net->ipv6.fib6_rules_ops,
 			 flowi6_to_flowi(fl6), flags, &arg);
 
-	rt = arg.result;
+	if (arg.result)
+		return arg.result;
 
-	if (!rt) {
-		dst_hold(&net->ipv6.ip6_null_entry->dst);
-		return &net->ipv6.ip6_null_entry->dst;
-	}
-
-	if (rt->rt6i_flags & RTF_REJECT &&
-	    rt->dst.error == -EAGAIN) {
-		ip6_rt_put(rt);
-		rt = net->ipv6.ip6_null_entry;
-		dst_hold(&rt->dst);
-	}
-
-	return &rt->dst;
+	dst_hold(&net->ipv6.ip6_null_entry->dst);
+	return &net->ipv6.ip6_null_entry->dst;
 }
 
 static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
@@ -116,7 +105,8 @@
 			flp6->saddr = saddr;
 		}
 		err = rt->dst.error;
-		goto out;
+		if (err != -EAGAIN)
+			goto out;
 	}
 again:
 	ip6_rt_put(rt);
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index a3ec7a7..3ae2fbe 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -92,13 +92,14 @@
 	struct net *net = dev_net(skb->dev);
 
 	if (type == ICMPV6_PKT_TOOBIG)
-		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
 	else if (type == NDISC_REDIRECT)
-		ip6_redirect(skb, net, skb->dev->ifindex, 0);
+		ip6_redirect(skb, net, skb->dev->ifindex, 0,
+			     sock_net_uid(net, NULL));
 
 	if (!(type & ICMPV6_INFOMSG_MASK))
 		if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
-			ping_err(skb, offset, info);
+			ping_err(skb, offset, ntohl(info));
 }
 
 static int icmpv6_rcv(struct sk_buff *skb);
@@ -478,6 +479,7 @@
 	fl6.flowi6_oif = iif;
 	fl6.fl6_icmp_type = type;
 	fl6.fl6_icmp_code = code;
+	fl6.flowi6_uid = sock_net_uid(net, NULL);
 	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
 	sk = icmpv6_xmit_lock(net);
@@ -585,6 +587,7 @@
 	fl6.flowi6_oif = l3mdev_fib_oif(skb->dev);
 	fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
 	fl6.flowi6_mark = mark;
+	fl6.flowi6_uid = sock_net_uid(net, NULL);
 	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
 	sk = icmpv6_xmit_lock(net);
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 897bb6e..dc79ebc 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -86,7 +86,7 @@
 	fl6->flowi6_mark = ireq->ir_mark;
 	fl6->fl6_dport = ireq->ir_rmt_port;
 	fl6->fl6_sport = htons(ireq->ir_num);
-	fl6->flowi6_uid = sock_i_uid((struct sock *)sk);
+	fl6->flowi6_uid = sk->sk_uid;
 	security_req_classify_flow(req, flowi6_to_flowi(fl6));
 
 	dst = ip6_dst_lookup_flow(sk, fl6, final_p);
@@ -135,7 +135,7 @@
 	fl6->flowi6_mark = sk->sk_mark;
 	fl6->fl6_sport = inet->inet_sport;
 	fl6->fl6_dport = inet->inet_dport;
-	fl6->flowi6_uid = sock_i_uid(sk);
+	fl6->flowi6_uid = sk->sk_uid;
 	security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
 
 	rcu_read_lock();
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 0c7e276..1ac0672 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -179,6 +179,7 @@
 		}
 	}
 
+	free_percpu(non_pcpu_rt->rt6i_pcpu);
 	non_pcpu_rt->rt6i_pcpu = NULL;
 }
 
@@ -289,8 +290,7 @@
 	struct rt6_info *rt;
 
 	rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
-	if (rt->rt6i_flags & RTF_REJECT &&
-	    rt->dst.error == -EAGAIN) {
+	if (rt->dst.error == -EAGAIN) {
 		ip6_rt_put(rt);
 		rt = net->ipv6.ip6_null_entry;
 		dst_hold(&rt->dst);
@@ -902,6 +902,8 @@
 			ins = &rt->dst.rt6_next;
 			iter = *ins;
 			while (iter) {
+				if (iter->rt6i_metric > rt->rt6i_metric)
+					break;
 				if (rt6_qualify_for_ecmp(iter)) {
 					*ins = iter->dst.rt6_next;
 					fib6_purge_rt(iter, fn, info->nl_net);
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 4650c68..ab0efac 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -55,6 +55,7 @@
 #include <net/ip6_fib.h>
 #include <net/ip6_route.h>
 #include <net/ip6_tunnel.h>
+#include <net/gre.h>
 
 
 static bool log_ecn_error = true;
@@ -367,35 +368,37 @@
 
 
 static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-		u8 type, u8 code, int offset, __be32 info)
+		       u8 type, u8 code, int offset, __be32 info)
 {
-	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data;
-	__be16 *p = (__be16 *)(skb->data + offset);
-	int grehlen = offset + 4;
+	const struct gre_base_hdr *greh;
+	const struct ipv6hdr *ipv6h;
+	int grehlen = sizeof(*greh);
 	struct ip6_tnl *t;
+	int key_off = 0;
 	__be16 flags;
+	__be32 key;
 
-	flags = p[0];
-	if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
-		if (flags&(GRE_VERSION|GRE_ROUTING))
-			return;
-		if (flags&GRE_KEY) {
-			grehlen += 4;
-			if (flags&GRE_CSUM)
-				grehlen += 4;
-		}
+	if (!pskb_may_pull(skb, offset + grehlen))
+		return;
+	greh = (const struct gre_base_hdr *)(skb->data + offset);
+	flags = greh->flags;
+	if (flags & (GRE_VERSION | GRE_ROUTING))
+		return;
+	if (flags & GRE_CSUM)
+		grehlen += 4;
+	if (flags & GRE_KEY) {
+		key_off = grehlen + offset;
+		grehlen += 4;
 	}
 
-	/* If only 8 bytes returned, keyed message will be dropped here */
-	if (!pskb_may_pull(skb, grehlen))
+	if (!pskb_may_pull(skb, offset + grehlen))
 		return;
 	ipv6h = (const struct ipv6hdr *)skb->data;
-	p = (__be16 *)(skb->data + offset);
+	greh = (const struct gre_base_hdr *)(skb->data + offset);
+	key = key_off ? *(__be32 *)(skb->data + key_off) : 0;
 
 	t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr,
-				flags & GRE_KEY ?
-				*(((__be32 *)p) + (grehlen / 4) - 1) : 0,
-				p[1]);
+				 key, greh->protocol);
 	if (!t)
 		return;
 
@@ -794,6 +797,8 @@
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
 		fl6.flowi6_mark = skb->mark;
 
+	fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
 	err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
 	if (err != 0) {
 		/* XXX: send ICMP error even if DF is not set. */
@@ -844,6 +849,8 @@
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
 		fl6.flowi6_mark = skb->mark;
 
+	fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
 	err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
 	if (err != 0) {
 		if (err == -EMSGSIZE)
@@ -886,7 +893,6 @@
 		encap_limit = t->parms.encap_limit;
 
 	memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
-	fl6.flowi6_proto = skb->protocol;
 
 	err = ip6gre_xmit2(skb, dev, 0, &fl6, encap_limit, &mtu);
 
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index eeca943..9e2ea4a 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -62,7 +62,6 @@
 	const struct net_offload *ops;
 	int proto;
 	struct frag_hdr *fptr;
-	unsigned int unfrag_ip6hlen;
 	u8 *prevhdr;
 	int offset = 0;
 	bool encap, udpfrag;
@@ -121,8 +120,12 @@
 		skb->network_header = (u8 *)ipv6h - skb->head;
 
 		if (udpfrag) {
-			unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
-			fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen);
+			int err = ip6_find_1stfragopt(skb, &prevhdr);
+			if (err < 0) {
+				kfree_skb_list(segs);
+				return ERR_PTR(err);
+			}
+			fptr = (struct frag_hdr *)((u8 *)ipv6h + err);
 			fptr->frag_off = htons(offset);
 			if (skb->next)
 				fptr->frag_off |= htons(IP6_MF);
@@ -196,6 +199,7 @@
 	ops = rcu_dereference(inet6_offloads[proto]);
 	if (!ops || !ops->callbacks.gro_receive) {
 		__pskb_pull(skb, skb_gro_offset(skb));
+		skb_gro_frag0_invalidate(skb);
 		proto = ipv6_gso_pull_exthdrs(skb, proto);
 		skb_gro_pull(skb, -skb_transport_offset(skb));
 		skb_reset_transport_header(skb);
@@ -247,7 +251,7 @@
 
 	skb_gro_postpull_rcsum(skb, iph, nlen);
 
-	pp = ops->callbacks.gro_receive(head, skb);
+	pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
 
 out_unlock:
 	rcu_read_unlock();
@@ -258,6 +262,19 @@
 	return pp;
 }
 
+static struct sk_buff **sit_gro_receive(struct sk_buff **head,
+					struct sk_buff *skb)
+{
+	if (NAPI_GRO_CB(skb)->encap_mark) {
+		NAPI_GRO_CB(skb)->flush = 1;
+		return NULL;
+	}
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
+	return ipv6_gro_receive(head, skb);
+}
+
 static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
 {
 	const struct net_offload *ops;
@@ -302,7 +319,7 @@
 static const struct net_offload sit_offload = {
 	.callbacks = {
 		.gso_segment	= ipv6_gso_segment,
-		.gro_receive    = ipv6_gro_receive,
+		.gro_receive    = sit_gro_receive,
 		.gro_complete   = sit_gro_complete,
 	},
 };
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index a175152..7d339fc 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -571,7 +571,10 @@
 	int ptr, offset = 0, err = 0;
 	u8 *prevhdr, nexthdr = 0;
 
-	hlen = ip6_find_1stfragopt(skb, &prevhdr);
+	err = ip6_find_1stfragopt(skb, &prevhdr);
+	if (err < 0)
+		goto fail;
+	hlen = err;
 	nexthdr = *prevhdr;
 
 	mtu = ip6_skb_dst_mtu(skb);
@@ -742,13 +745,14 @@
 	 *	Fragment the datagram.
 	 */
 
-	*prevhdr = NEXTHDR_FRAGMENT;
 	troom = rt->dst.dev->needed_tailroom;
 
 	/*
 	 *	Keep copying data until we run out.
 	 */
 	while (left > 0)	{
+		u8 *fragnexthdr_offset;
+
 		len = left;
 		/* IF: it doesn't fit, use 'mtu' - the data space left */
 		if (len > mtu)
@@ -793,6 +797,10 @@
 		 */
 		skb_copy_from_linear_data(skb, skb_network_header(frag), hlen);
 
+		fragnexthdr_offset = skb_network_header(frag);
+		fragnexthdr_offset += prevhdr - skb_network_header(skb);
+		*fragnexthdr_offset = NEXTHDR_FRAGMENT;
+
 		/*
 		 *	Build fragment header.
 		 */
@@ -996,6 +1004,11 @@
 		}
 	}
 #endif
+	if (ipv6_addr_v4mapped(&fl6->saddr) &&
+	    !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) {
+		err = -EAFNOSUPPORT;
+		goto out_err_release;
+	}
 
 	return 0;
 
@@ -1072,17 +1085,12 @@
 					 const struct in6_addr *final_dst)
 {
 	struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
-	int err;
 
 	dst = ip6_sk_dst_check(sk, dst, fl6);
+	if (!dst)
+		dst = ip6_dst_lookup_flow(sk, fl6, final_dst);
 
-	err = ip6_dst_lookup_tail(sock_net(sk), sk, &dst, fl6);
-	if (err)
-		return ERR_PTR(err);
-	if (final_dst)
-		fl6->daddr = *final_dst;
-
-	return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
+	return dst;
 }
 EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow);
 
@@ -1429,6 +1437,11 @@
 			 */
 			alloclen += sizeof(struct frag_hdr);
 
+			copy = datalen - transhdrlen - fraggap;
+			if (copy < 0) {
+				err = -EINVAL;
+				goto error;
+			}
 			if (transhdrlen) {
 				skb = sock_alloc_send_skb(sk,
 						alloclen + hh_len,
@@ -1478,13 +1491,9 @@
 				data += fraggap;
 				pskb_trim_unique(skb_prev, maxfraglen);
 			}
-			copy = datalen - transhdrlen - fraggap;
-
-			if (copy < 0) {
-				err = -EINVAL;
-				kfree_skb(skb);
-				goto error;
-			} else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
+			if (copy > 0 &&
+			    getfrag(from, data + transhdrlen, offset,
+				    copy, fraggap, skb) < 0) {
 				err = -EFAULT;
 				kfree_skb(skb);
 				goto error;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 3991b21..600975c 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -246,6 +246,7 @@
 	hash = HASH(&any, local);
 	for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
 		if (ipv6_addr_equal(local, &t->parms.laddr) &&
+		    ipv6_addr_any(&t->parms.raddr) &&
 		    (t->dev->flags & IFF_UP))
 			return t;
 	}
@@ -253,6 +254,7 @@
 	hash = HASH(remote, &any);
 	for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
 		if (ipv6_addr_equal(remote, &t->parms.raddr) &&
+		    ipv6_addr_any(&t->parms.laddr) &&
 		    (t->dev->flags & IFF_UP))
 			return t;
 	}
@@ -477,18 +479,19 @@
 
 __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
 {
-	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw;
-	__u8 nexthdr = ipv6h->nexthdr;
-	__u16 off = sizeof(*ipv6h);
+	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw;
+	unsigned int nhoff = raw - skb->data;
+	unsigned int off = nhoff + sizeof(*ipv6h);
+	u8 next, nexthdr = ipv6h->nexthdr;
 
 	while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
-		__u16 optlen = 0;
 		struct ipv6_opt_hdr *hdr;
-		if (raw + off + sizeof(*hdr) > skb->data &&
-		    !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr)))
+		u16 optlen;
+
+		if (!pskb_may_pull(skb, off + sizeof(*hdr)))
 			break;
 
-		hdr = (struct ipv6_opt_hdr *) (raw + off);
+		hdr = (struct ipv6_opt_hdr *)(skb->data + off);
 		if (nexthdr == NEXTHDR_FRAGMENT) {
 			struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
 			if (frag_hdr->frag_off)
@@ -499,20 +502,29 @@
 		} else {
 			optlen = ipv6_optlen(hdr);
 		}
+		/* cache hdr->nexthdr, since pskb_may_pull() might
+		 * invalidate hdr
+		 */
+		next = hdr->nexthdr;
 		if (nexthdr == NEXTHDR_DEST) {
-			__u16 i = off + 2;
+			u16 i = 2;
+
+			/* Remember : hdr is no longer valid at this point. */
+			if (!pskb_may_pull(skb, off + optlen))
+				break;
+
 			while (1) {
 				struct ipv6_tlv_tnl_enc_lim *tel;
 
 				/* No more room for encapsulation limit */
-				if (i + sizeof (*tel) > off + optlen)
+				if (i + sizeof(*tel) > optlen)
 					break;
 
-				tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i];
+				tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i);
 				/* return index of option if found and valid */
 				if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
 				    tel->length == 1)
-					return i;
+					return i + off - nhoff;
 				/* else jump to next option */
 				if (tel->type)
 					i += tel->length + 2;
@@ -520,7 +532,7 @@
 					i++;
 			}
 		}
-		nexthdr = hdr->nexthdr;
+		nexthdr = next;
 		off += optlen;
 	}
 	return 0;
@@ -1037,10 +1049,11 @@
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct net *net = t->net;
 	struct net_device_stats *stats = &t->dev->stats;
-	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+	struct ipv6hdr *ipv6h;
 	struct ipv6_tel_txoption opt;
 	struct dst_entry *dst = NULL, *ndst = NULL;
 	struct net_device *tdev;
+	bool use_cache = false;
 	int mtu;
 	unsigned int max_headroom = sizeof(struct ipv6hdr);
 	u8 proto;
@@ -1048,27 +1061,37 @@
 
 	/* NBMA tunnel */
 	if (ipv6_addr_any(&t->parms.raddr)) {
-		struct in6_addr *addr6;
-		struct neighbour *neigh;
-		int addr_type;
+		if (skb->protocol == htons(ETH_P_IPV6)) {
+			struct in6_addr *addr6;
+			struct neighbour *neigh;
+			int addr_type;
 
-		if (!skb_dst(skb))
-			goto tx_err_link_failure;
+			if (!skb_dst(skb))
+				goto tx_err_link_failure;
 
-		neigh = dst_neigh_lookup(skb_dst(skb),
-					 &ipv6_hdr(skb)->daddr);
-		if (!neigh)
-			goto tx_err_link_failure;
+			neigh = dst_neigh_lookup(skb_dst(skb),
+						 &ipv6_hdr(skb)->daddr);
+			if (!neigh)
+				goto tx_err_link_failure;
 
-		addr6 = (struct in6_addr *)&neigh->primary_key;
-		addr_type = ipv6_addr_type(addr6);
+			addr6 = (struct in6_addr *)&neigh->primary_key;
+			addr_type = ipv6_addr_type(addr6);
 
-		if (addr_type == IPV6_ADDR_ANY)
-			addr6 = &ipv6_hdr(skb)->daddr;
+			if (addr_type == IPV6_ADDR_ANY)
+				addr6 = &ipv6_hdr(skb)->daddr;
 
-		memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
-		neigh_release(neigh);
-	} else if (!fl6->flowi6_mark)
+			memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
+			neigh_release(neigh);
+		}
+	} else if (!(t->parms.flags &
+		     (IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FWMARK))) {
+		/* enable the cache only only if the routing decision does
+		 * not depend on the current inner header value
+		 */
+		use_cache = true;
+	}
+
+	if (use_cache)
 		dst = ip6_tnl_dst_get(t);
 
 	if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))
@@ -1132,7 +1155,7 @@
 		skb = new_skb;
 	}
 
-	if (!fl6->flowi6_mark && ndst)
+	if (use_cache && ndst)
 		ip6_tnl_dst_set(t, ndst);
 	skb_dst_set(skb, dst);
 
@@ -1192,6 +1215,8 @@
 	memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
 	fl6.flowi6_proto = IPPROTO_IPIP;
 
+	fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
 	dsfield = ipv4_get_dsfield(iph);
 
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
@@ -1245,6 +1270,7 @@
 
 	memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
 	fl6.flowi6_proto = IPPROTO_IPV6;
+	fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
 
 	dsfield = ipv6_get_dsfield(ipv6h);
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index c76ebc7..5b74338 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -597,9 +597,10 @@
 		return 0;
 
 	if (type == NDISC_REDIRECT)
-		ip6_redirect(skb, net, skb->dev->ifindex, 0);
+		ip6_redirect(skb, net, skb->dev->ifindex, 0,
+			     sock_net_uid(net, NULL));
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
 	xfrm_state_put(x);
 
 	return 0;
@@ -680,6 +681,10 @@
 	u->link = p->link;
 	u->i_key = p->i_key;
 	u->o_key = p->o_key;
+	if (u->i_key)
+		u->i_flags |= GRE_KEY;
+	if (u->o_key)
+		u->o_flags |= GRE_KEY;
 	u->proto = p->proto;
 
 	memcpy(u->name, p->name, sizeof(u->name));
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index a10e771..8361d73 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -774,7 +774,8 @@
  *	Delete a VIF entry
  */
 
-static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
+static int mif6_delete(struct mr6_table *mrt, int vifi, int notify,
+		       struct list_head *head)
 {
 	struct mif_device *v;
 	struct net_device *dev;
@@ -820,7 +821,7 @@
 					     dev->ifindex, &in6_dev->cnf);
 	}
 
-	if (v->flags & MIFF_REGISTER)
+	if ((v->flags & MIFF_REGISTER) && !notify)
 		unregister_netdevice_queue(dev, head);
 
 	dev_put(dev);
@@ -1074,6 +1075,7 @@
 	struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
 	if (!c)
 		return NULL;
+	c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
 	c->mfc_un.res.minvif = MAXMIFS;
 	return c;
 }
@@ -1329,7 +1331,6 @@
 	struct mr6_table *mrt;
 	struct mif_device *v;
 	int ct;
-	LIST_HEAD(list);
 
 	if (event != NETDEV_UNREGISTER)
 		return NOTIFY_DONE;
@@ -1338,10 +1339,9 @@
 		v = &mrt->vif6_table[0];
 		for (ct = 0; ct < mrt->maxvif; ct++, v++) {
 			if (v->dev == dev)
-				mif6_delete(mrt, ct, &list);
+				mif6_delete(mrt, ct, 1, NULL);
 		}
 	}
-	unregister_netdevice_many(&list);
 
 	return NOTIFY_DONE;
 }
@@ -1550,7 +1550,7 @@
 	for (i = 0; i < mrt->maxvif; i++) {
 		if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC))
 			continue;
-		mif6_delete(mrt, i, &list);
+		mif6_delete(mrt, i, 0, &list);
 	}
 	unregister_netdevice_many(&list);
 
@@ -1703,7 +1703,7 @@
 		if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
 			return -EFAULT;
 		rtnl_lock();
-		ret = mif6_delete(mrt, mifi, NULL);
+		ret = mif6_delete(mrt, mifi, 0, NULL);
 		rtnl_unlock();
 		return ret;
 
@@ -2275,8 +2275,8 @@
 	return 1;
 }
 
-int ip6mr_get_route(struct net *net,
-		    struct sk_buff *skb, struct rtmsg *rtm, int nowait)
+int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
+		    int nowait, u32 portid)
 {
 	int err;
 	struct mr6_table *mrt;
@@ -2321,6 +2321,7 @@
 			return -ENOMEM;
 		}
 
+		NETLINK_CB(skb2).portid = portid;
 		skb_reset_transport_header(skb2);
 
 		skb_put(skb2, sizeof(struct ipv6hdr));
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index b247bac..54d165b 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -74,9 +74,10 @@
 		return 0;
 
 	if (type == NDISC_REDIRECT)
-		ip6_redirect(skb, net, skb->dev->ifindex, 0);
+		ip6_redirect(skb, net, skb->dev->ifindex, 0,
+			     sock_net_uid(net, NULL));
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
 	xfrm_state_put(x);
 
 	return 0;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 84afb9a..3452f90 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1358,6 +1358,8 @@
 			if (ri->prefix_len == 0 &&
 			    !in6_dev->cnf.accept_ra_defrtr)
 				continue;
+			if (ri->prefix_len < in6_dev->cnf.accept_ra_rt_info_min_plen)
+				continue;
 			if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
 				continue;
 			rt6_route_rcv(skb->dev, (u8 *)p, (p->nd_opt_len) << 3,
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index d11c468..39970e2 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -26,6 +26,7 @@
 	struct flowi6 fl6 = {
 		.flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
 		.flowi6_mark = skb->mark,
+		.flowi6_uid = sock_net_uid(net, skb->sk),
 		.daddr = iph->daddr,
 		.saddr = iph->saddr,
 	};
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 37e945c..22f39e0 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -455,6 +455,18 @@
 #endif
 }
 
+static bool find_jump_target(const struct xt_table_info *t,
+			     const struct ip6t_entry *target)
+{
+	struct ip6t_entry *iter;
+
+	xt_entry_foreach(iter, t->entries, t->size) {
+		 if (iter == target)
+			return true;
+	}
+	return false;
+}
+
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
@@ -532,6 +544,8 @@
 				size = e->next_offset;
 				e = (struct ip6t_entry *)
 					(entry0 + pos + size);
+				if (pos + size >= newinfo->size)
+					return 0;
 				e->counters.pcnt = pos;
 				pos += size;
 			} else {
@@ -550,9 +564,15 @@
 					/* This a jump; chase it. */
 					duprintf("Jump rule %u -> %u\n",
 						 pos, newpos);
+					e = (struct ip6t_entry *)
+						(entry0 + newpos);
+					if (!find_jump_target(newinfo, e))
+						return 0;
 				} else {
 					/* ... this is a fallthru */
 					newpos = pos + e->next_offset;
+					if (newpos >= newinfo->size)
+						return 0;
 				}
 				e = (struct ip6t_entry *)
 					(entry0 + newpos);
@@ -579,27 +599,6 @@
 	module_put(par.match->me);
 }
 
-static int
-check_entry(const struct ip6t_entry *e, const char *name)
-{
-	const struct xt_entry_target *t;
-
-	if (!ip6_checkentry(&e->ipv6)) {
-		duprintf("ip_tables: ip check failed %p %s.\n", e, name);
-		return -EINVAL;
-	}
-
-	if (e->target_offset + sizeof(struct xt_entry_target) >
-	    e->next_offset)
-		return -EINVAL;
-
-	t = ip6t_get_target_c(e);
-	if (e->target_offset + t->u.target_size > e->next_offset)
-		return -EINVAL;
-
-	return 0;
-}
-
 static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
 {
 	const struct ip6t_ip6 *ipv6 = par->entryinfo;
@@ -678,10 +677,6 @@
 	struct xt_mtchk_param mtpar;
 	struct xt_entry_match *ematch;
 
-	ret = check_entry(e, name);
-	if (ret)
-		return ret;
-
 	e->counters.pcnt = xt_percpu_counter_alloc();
 	if (IS_ERR_VALUE(e->counters.pcnt))
 		return -ENOMEM;
@@ -752,9 +747,11 @@
 			   unsigned int valid_hooks)
 {
 	unsigned int h;
+	int err;
 
 	if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 ||
-	    (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) {
+	    (unsigned char *)e + sizeof(struct ip6t_entry) >= limit ||
+	    (unsigned char *)e + e->next_offset > limit) {
 		duprintf("Bad offset %p\n", e);
 		return -EINVAL;
 	}
@@ -766,6 +763,14 @@
 		return -EINVAL;
 	}
 
+	if (!ip6_checkentry(&e->ipv6))
+		return -EINVAL;
+
+	err = xt_check_entry_offsets(e, e->elems, e->target_offset,
+				     e->next_offset);
+	if (err)
+		return err;
+
 	/* Check hooks & underflows */
 	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
 		if (!(valid_hooks & (1 << h)))
@@ -1320,55 +1325,16 @@
 	unsigned int i;
 	struct xt_counters_info tmp;
 	struct xt_counters *paddc;
-	unsigned int num_counters;
-	char *name;
-	int size;
-	void *ptmp;
 	struct xt_table *t;
 	const struct xt_table_info *private;
 	int ret = 0;
 	struct ip6t_entry *iter;
 	unsigned int addend;
-#ifdef CONFIG_COMPAT
-	struct compat_xt_counters_info compat_tmp;
 
-	if (compat) {
-		ptmp = &compat_tmp;
-		size = sizeof(struct compat_xt_counters_info);
-	} else
-#endif
-	{
-		ptmp = &tmp;
-		size = sizeof(struct xt_counters_info);
-	}
-
-	if (copy_from_user(ptmp, user, size) != 0)
-		return -EFAULT;
-
-#ifdef CONFIG_COMPAT
-	if (compat) {
-		num_counters = compat_tmp.num_counters;
-		name = compat_tmp.name;
-	} else
-#endif
-	{
-		num_counters = tmp.num_counters;
-		name = tmp.name;
-	}
-
-	if (len != size + num_counters * sizeof(struct xt_counters))
-		return -EINVAL;
-
-	paddc = vmalloc(len - size);
-	if (!paddc)
-		return -ENOMEM;
-
-	if (copy_from_user(paddc, user + size, len - size) != 0) {
-		ret = -EFAULT;
-		goto free;
-	}
-
-	t = xt_find_table_lock(net, AF_INET6, name);
+	paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
+	if (IS_ERR(paddc))
+		return PTR_ERR(paddc);
+	t = xt_find_table_lock(net, AF_INET6, tmp.name);
 	if (IS_ERR_OR_NULL(t)) {
 		ret = t ? PTR_ERR(t) : -ENOENT;
 		goto free;
@@ -1376,7 +1342,7 @@
 
 	local_bh_disable();
 	private = t->private;
-	if (private->number != num_counters) {
+	if (private->number != tmp.num_counters) {
 		ret = -EINVAL;
 		goto unlock_up_free;
 	}
@@ -1455,7 +1421,6 @@
 
 static int
 compat_find_calc_match(struct xt_entry_match *m,
-		       const char *name,
 		       const struct ip6t_ip6 *ipv6,
 		       int *size)
 {
@@ -1490,21 +1455,19 @@
 				  struct xt_table_info *newinfo,
 				  unsigned int *size,
 				  const unsigned char *base,
-				  const unsigned char *limit,
-				  const unsigned int *hook_entries,
-				  const unsigned int *underflows,
-				  const char *name)
+				  const unsigned char *limit)
 {
 	struct xt_entry_match *ematch;
 	struct xt_entry_target *t;
 	struct xt_target *target;
 	unsigned int entry_offset;
 	unsigned int j;
-	int ret, off, h;
+	int ret, off;
 
 	duprintf("check_compat_entry_size_and_hooks %p\n", e);
 	if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 ||
-	    (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) {
+	    (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit ||
+	    (unsigned char *)e + e->next_offset > limit) {
 		duprintf("Bad offset %p, limit = %p\n", e, limit);
 		return -EINVAL;
 	}
@@ -1516,8 +1479,11 @@
 		return -EINVAL;
 	}
 
-	/* For purposes of check_entry casting the compat entry is fine */
-	ret = check_entry((struct ip6t_entry *)e, name);
+	if (!ip6_checkentry(&e->ipv6))
+		return -EINVAL;
+
+	ret = xt_compat_check_entry_offsets(e, e->elems,
+					    e->target_offset, e->next_offset);
 	if (ret)
 		return ret;
 
@@ -1525,7 +1491,7 @@
 	entry_offset = (void *)e - (void *)base;
 	j = 0;
 	xt_ematch_foreach(ematch, e) {
-		ret = compat_find_calc_match(ematch, name, &e->ipv6, &off);
+		ret = compat_find_calc_match(ematch, &e->ipv6, &off);
 		if (ret != 0)
 			goto release_matches;
 		++j;
@@ -1548,17 +1514,6 @@
 	if (ret)
 		goto out;
 
-	/* Check hooks & underflows */
-	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
-		if ((unsigned char *)e - base == hook_entries[h])
-			newinfo->hook_entry[h] = hook_entries[h];
-		if ((unsigned char *)e - base == underflows[h])
-			newinfo->underflow[h] = underflows[h];
-	}
-
-	/* Clear counters and comefrom */
-	memset(&e->counters, 0, sizeof(e->counters));
-	e->comefrom = 0;
 	return 0;
 
 out:
@@ -1572,18 +1527,17 @@
 	return ret;
 }
 
-static int
+static void
 compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
-			    unsigned int *size, const char *name,
+			    unsigned int *size,
 			    struct xt_table_info *newinfo, unsigned char *base)
 {
 	struct xt_entry_target *t;
 	struct ip6t_entry *de;
 	unsigned int origsize;
-	int ret, h;
+	int h;
 	struct xt_entry_match *ematch;
 
-	ret = 0;
 	origsize = *size;
 	de = (struct ip6t_entry *)*dstptr;
 	memcpy(de, e, sizeof(struct ip6t_entry));
@@ -1592,11 +1546,9 @@
 	*dstptr += sizeof(struct ip6t_entry);
 	*size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
 
-	xt_ematch_foreach(ematch, e) {
-		ret = xt_compat_match_from_user(ematch, dstptr, size);
-		if (ret != 0)
-			return ret;
-	}
+	xt_ematch_foreach(ematch, e)
+		xt_compat_match_from_user(ematch, dstptr, size);
+
 	de->target_offset = e->target_offset - (origsize - *size);
 	t = compat_ip6t_get_target(e);
 	xt_compat_target_from_user(t, dstptr, size);
@@ -1608,183 +1560,83 @@
 		if ((unsigned char *)de - base < newinfo->underflow[h])
 			newinfo->underflow[h] -= origsize - *size;
 	}
-	return ret;
-}
-
-static int compat_check_entry(struct ip6t_entry *e, struct net *net,
-			      const char *name)
-{
-	unsigned int j;
-	int ret = 0;
-	struct xt_mtchk_param mtpar;
-	struct xt_entry_match *ematch;
-
-	e->counters.pcnt = xt_percpu_counter_alloc();
-	if (IS_ERR_VALUE(e->counters.pcnt))
-		return -ENOMEM;
-	j = 0;
-	mtpar.net	= net;
-	mtpar.table     = name;
-	mtpar.entryinfo = &e->ipv6;
-	mtpar.hook_mask = e->comefrom;
-	mtpar.family    = NFPROTO_IPV6;
-	xt_ematch_foreach(ematch, e) {
-		ret = check_match(ematch, &mtpar);
-		if (ret != 0)
-			goto cleanup_matches;
-		++j;
-	}
-
-	ret = check_target(e, net, name);
-	if (ret)
-		goto cleanup_matches;
-	return 0;
-
- cleanup_matches:
-	xt_ematch_foreach(ematch, e) {
-		if (j-- == 0)
-			break;
-		cleanup_match(ematch, net);
-	}
-
-	xt_percpu_counter_free(e->counters.pcnt);
-
-	return ret;
 }
 
 static int
 translate_compat_table(struct net *net,
-		       const char *name,
-		       unsigned int valid_hooks,
 		       struct xt_table_info **pinfo,
 		       void **pentry0,
-		       unsigned int total_size,
-		       unsigned int number,
-		       unsigned int *hook_entries,
-		       unsigned int *underflows)
+		       const struct compat_ip6t_replace *compatr)
 {
 	unsigned int i, j;
 	struct xt_table_info *newinfo, *info;
 	void *pos, *entry0, *entry1;
 	struct compat_ip6t_entry *iter0;
-	struct ip6t_entry *iter1;
+	struct ip6t_replace repl;
 	unsigned int size;
 	int ret = 0;
 
 	info = *pinfo;
 	entry0 = *pentry0;
-	size = total_size;
-	info->number = number;
-
-	/* Init all hooks to impossible value. */
-	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		info->hook_entry[i] = 0xFFFFFFFF;
-		info->underflow[i] = 0xFFFFFFFF;
-	}
+	size = compatr->size;
+	info->number = compatr->num_entries;
 
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(AF_INET6);
-	xt_compat_init_offsets(AF_INET6, number);
+	xt_compat_init_offsets(AF_INET6, compatr->num_entries);
 	/* Walk through entries, checking offsets. */
-	xt_entry_foreach(iter0, entry0, total_size) {
+	xt_entry_foreach(iter0, entry0, compatr->size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
 							entry0,
-							entry0 + total_size,
-							hook_entries,
-							underflows,
-							name);
+							entry0 + compatr->size);
 		if (ret != 0)
 			goto out_unlock;
 		++j;
 	}
 
 	ret = -EINVAL;
-	if (j != number) {
+	if (j != compatr->num_entries) {
 		duprintf("translate_compat_table: %u not %u entries\n",
-			 j, number);
+			 j, compatr->num_entries);
 		goto out_unlock;
 	}
 
-	/* Check hooks all assigned */
-	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		/* Only hooks which are valid */
-		if (!(valid_hooks & (1 << i)))
-			continue;
-		if (info->hook_entry[i] == 0xFFFFFFFF) {
-			duprintf("Invalid hook entry %u %u\n",
-				 i, hook_entries[i]);
-			goto out_unlock;
-		}
-		if (info->underflow[i] == 0xFFFFFFFF) {
-			duprintf("Invalid underflow %u %u\n",
-				 i, underflows[i]);
-			goto out_unlock;
-		}
-	}
-
 	ret = -ENOMEM;
 	newinfo = xt_alloc_table_info(size);
 	if (!newinfo)
 		goto out_unlock;
 
-	newinfo->number = number;
+	newinfo->number = compatr->num_entries;
 	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
-		newinfo->hook_entry[i] = info->hook_entry[i];
-		newinfo->underflow[i] = info->underflow[i];
+		newinfo->hook_entry[i] = compatr->hook_entry[i];
+		newinfo->underflow[i] = compatr->underflow[i];
 	}
 	entry1 = newinfo->entries;
 	pos = entry1;
-	size = total_size;
-	xt_entry_foreach(iter0, entry0, total_size) {
-		ret = compat_copy_entry_from_user(iter0, &pos, &size,
-						  name, newinfo, entry1);
-		if (ret != 0)
-			break;
-	}
+	size = compatr->size;
+	xt_entry_foreach(iter0, entry0, compatr->size)
+		compat_copy_entry_from_user(iter0, &pos, &size,
+					    newinfo, entry1);
+
+	/* all module references in entry0 are now gone. */
 	xt_compat_flush_offsets(AF_INET6);
 	xt_compat_unlock(AF_INET6);
+
+	memcpy(&repl, compatr, sizeof(*compatr));
+
+	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
+		repl.hook_entry[i] = newinfo->hook_entry[i];
+		repl.underflow[i] = newinfo->underflow[i];
+	}
+
+	repl.num_counters = 0;
+	repl.counters = NULL;
+	repl.size = newinfo->size;
+	ret = translate_table(net, newinfo, entry1, &repl);
 	if (ret)
 		goto free_newinfo;
 
-	ret = -ELOOP;
-	if (!mark_source_chains(newinfo, valid_hooks, entry1))
-		goto free_newinfo;
-
-	i = 0;
-	xt_entry_foreach(iter1, entry1, newinfo->size) {
-		ret = compat_check_entry(iter1, net, name);
-		if (ret != 0)
-			break;
-		++i;
-		if (strcmp(ip6t_get_target(iter1)->u.user.name,
-		    XT_ERROR_TARGET) == 0)
-			++newinfo->stacksize;
-	}
-	if (ret) {
-		/*
-		 * The first i matches need cleanup_entry (calls ->destroy)
-		 * because they had called ->check already. The other j-i
-		 * entries need only release.
-		 */
-		int skip = i;
-		j -= i;
-		xt_entry_foreach(iter0, entry0, newinfo->size) {
-			if (skip-- > 0)
-				continue;
-			if (j-- == 0)
-				break;
-			compat_release_entry(iter0);
-		}
-		xt_entry_foreach(iter1, entry1, newinfo->size) {
-			if (i-- == 0)
-				break;
-			cleanup_entry(iter1, net);
-		}
-		xt_free_table_info(newinfo);
-		return ret;
-	}
-
 	*pinfo = newinfo;
 	*pentry0 = entry1;
 	xt_free_table_info(info);
@@ -1792,17 +1644,16 @@
 
 free_newinfo:
 	xt_free_table_info(newinfo);
-out:
-	xt_entry_foreach(iter0, entry0, total_size) {
+	return ret;
+out_unlock:
+	xt_compat_flush_offsets(AF_INET6);
+	xt_compat_unlock(AF_INET6);
+	xt_entry_foreach(iter0, entry0, compatr->size) {
 		if (j-- == 0)
 			break;
 		compat_release_entry(iter0);
 	}
 	return ret;
-out_unlock:
-	xt_compat_flush_offsets(AF_INET6);
-	xt_compat_unlock(AF_INET6);
-	goto out;
 }
 
 static int
@@ -1838,10 +1689,7 @@
 		goto free_newinfo;
 	}
 
-	ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
-				     &newinfo, &loc_cpu_entry, tmp.size,
-				     tmp.num_entries, tmp.hook_entry,
-				     tmp.underflow);
+	ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
 	if (ret != 0)
 		goto free_newinfo;
 
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index 462f2a7..8b56c52 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -79,14 +79,13 @@
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 {
 	u16 offset = sizeof(struct ipv6hdr);
-	struct ipv6_opt_hdr *exthdr =
-				(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
 	unsigned int packet_len = skb_tail_pointer(skb) -
 		skb_network_header(skb);
 	int found_rhdr = 0;
 	*nexthdr = &ipv6_hdr(skb)->nexthdr;
 
-	while (offset + 1 <= packet_len) {
+	while (offset <= packet_len) {
+		struct ipv6_opt_hdr *exthdr;
 
 		switch (**nexthdr) {
 
@@ -107,13 +106,16 @@
 			return offset;
 		}
 
-		offset += ipv6_optlen(exthdr);
-		*nexthdr = &exthdr->nexthdr;
+		if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
+			return -EINVAL;
+
 		exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
 						 offset);
+		offset += ipv6_optlen(exthdr);
+		*nexthdr = &exthdr->nexthdr;
 	}
 
-	return offset;
+	return -EINVAL;
 }
 EXPORT_SYMBOL(ip6_find_1stfragopt);
 
@@ -148,6 +150,8 @@
 	ipv6_hdr(skb)->payload_len = htons(len);
 	IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
 
+	skb->protocol = htons(ETH_P_IPV6);
+
 	return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
 		       net, sk, skb, NULL, skb_dst(skb)->dev,
 		       dst_output);
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index 2cfaedf..4c753f4 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -50,7 +50,7 @@
 	.type =      SOCK_DGRAM,
 	.protocol =  IPPROTO_ICMPV6,
 	.prot =      &pingv6_prot,
-	.ops =       &inet6_dgram_ops,
+	.ops =       &inet6_sockraw_ops,
 	.flags =     INET_PROTOSW_REUSE,
 };
 
@@ -84,7 +84,7 @@
 	struct icmp6hdr user_icmph;
 	int addr_type;
 	struct in6_addr *daddr;
-	int iif = 0;
+	int oif = 0;
 	struct flowi6 fl6;
 	int err;
 	int hlimit;
@@ -106,25 +106,30 @@
 		if (u->sin6_family != AF_INET6) {
 			return -EAFNOSUPPORT;
 		}
-		if (sk->sk_bound_dev_if &&
-		    sk->sk_bound_dev_if != u->sin6_scope_id) {
-			return -EINVAL;
-		}
 		daddr = &(u->sin6_addr);
-		iif = u->sin6_scope_id;
+		if (__ipv6_addr_needs_scope_id(ipv6_addr_type(daddr)))
+			oif = u->sin6_scope_id;
 	} else {
 		if (sk->sk_state != TCP_ESTABLISHED)
 			return -EDESTADDRREQ;
 		daddr = &sk->sk_v6_daddr;
 	}
 
-	if (!iif)
-		iif = sk->sk_bound_dev_if;
+	if (!oif)
+		oif = sk->sk_bound_dev_if;
+
+	if (!oif)
+		oif = np->sticky_pktinfo.ipi6_ifindex;
+
+	if (!oif && ipv6_addr_is_multicast(daddr))
+		oif = np->mcast_oif;
+	else if (!oif)
+		oif = np->ucast_oif;
 
 	addr_type = ipv6_addr_type(daddr);
-	if (__ipv6_addr_needs_scope_id(addr_type) && !iif)
-		return -EINVAL;
-	if (addr_type & IPV6_ADDR_MAPPED)
+	if ((__ipv6_addr_needs_scope_id(addr_type) && !oif) ||
+	    (addr_type & IPV6_ADDR_MAPPED) ||
+	    (oif && sk->sk_bound_dev_if && oif != sk->sk_bound_dev_if))
 		return -EINVAL;
 
 	/* TODO: use ip6_datagram_send_ctl to get options from cmsg */
@@ -134,30 +139,23 @@
 	fl6.flowi6_proto = IPPROTO_ICMPV6;
 	fl6.saddr = np->saddr;
 	fl6.daddr = *daddr;
+	fl6.flowi6_oif = oif;
 	fl6.flowi6_mark = sk->sk_mark;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 	fl6.fl6_icmp_type = user_icmph.icmp6_type;
 	fl6.fl6_icmp_code = user_icmph.icmp6_code;
 	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-	if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
-		fl6.flowi6_oif = np->mcast_oif;
-	else if (!fl6.flowi6_oif)
-		fl6.flowi6_oif = np->ucast_oif;
-
 	dst = ip6_sk_dst_lookup_flow(sk, &fl6,  daddr);
 	if (IS_ERR(dst))
 		return PTR_ERR(dst);
 	rt = (struct rt6_info *) dst;
 
 	np = inet6_sk(sk);
-	if (!np)
-		return -EBADF;
-
-	if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
-		fl6.flowi6_oif = np->mcast_oif;
-	else if (!fl6.flowi6_oif)
-		fl6.flowi6_oif = np->ucast_oif;
+	if (!np) {
+		err = -EBADF;
+		goto dst_err_out;
+	}
 
 	pfh.icmph.type = user_icmph.icmp6_type;
 	pfh.icmph.code = user_icmph.icmp6_code;
@@ -187,6 +185,9 @@
 	}
 	release_sock(sk);
 
+dst_err_out:
+	dst_release(dst);
+
 	if (err)
 		return err;
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d9ad71a..0ef8e11 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -589,7 +589,11 @@
 	}
 
 	offset += skb_transport_offset(skb);
-	BUG_ON(skb_copy_bits(skb, offset, &csum, 2));
+	err = skb_copy_bits(skb, offset, &csum, 2);
+	if (err < 0) {
+		ip6_flush_pending_frames(sk);
+		goto out;
+	}
 
 	/* in case cksum was not initialized */
 	if (unlikely(csum))
@@ -626,6 +630,8 @@
 		ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu);
 		return -EMSGSIZE;
 	}
+	if (length < sizeof(struct ipv6hdr))
+		return -EINVAL;
 	if (flags&MSG_PROBE)
 		goto out;
 
@@ -768,7 +774,7 @@
 	memset(&fl6, 0, sizeof(fl6));
 
 	fl6.flowi6_mark = sk->sk_mark;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 
 	if (sin6) {
 		if (addr_len < SIN6_LEN_RFC2133)
@@ -1141,8 +1147,7 @@
 		spin_lock_bh(&sk->sk_receive_queue.lock);
 		skb = skb_peek(&sk->sk_receive_queue);
 		if (skb)
-			amount = skb_tail_pointer(skb) -
-				skb_transport_header(skb);
+			amount = skb->len;
 		spin_unlock_bh(&sk->sk_receive_queue.lock);
 		return put_user(amount, (int __user *)arg);
 	}
@@ -1299,7 +1304,7 @@
 #endif	/* CONFIG_PROC_FS */
 
 /* Same as inet6_dgram_ops, sans udp_poll.  */
-static const struct proto_ops inet6_sockraw_ops = {
+const struct proto_ops inet6_sockraw_ops = {
 	.family		   = PF_INET6,
 	.owner		   = THIS_MODULE,
 	.release	   = inet6_release,
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 45f5ae5..a234552 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -496,10 +496,8 @@
 	IP6CB(head)->flags |= IP6SKB_FRAGMENTED;
 
 	/* Yes, and fold redundant checksum back. 8) */
-	if (head->ip_summed == CHECKSUM_COMPLETE)
-		head->csum = csum_partial(skb_network_header(head),
-					  skb_network_header_len(head),
-					  head->csum);
+	skb_postpush_rcsum(head, skb_network_header(head),
+			   skb_network_header_len(head));
 
 	rcu_read_lock();
 	IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index dd76806..1d0595b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1406,7 +1406,7 @@
 void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
 {
 	ip6_update_pmtu(skb, sock_net(sk), mtu,
-			sk->sk_bound_dev_if, sk->sk_mark, sock_i_uid(sk));
+			sk->sk_bound_dev_if, sk->sk_mark, sk->sk_uid);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);
 
@@ -1487,7 +1487,8 @@
 				flags, __ip6_route_redirect);
 }
 
-void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
+void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+		  kuid_t uid)
 {
 	const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
 	struct dst_entry *dst;
@@ -1500,6 +1501,7 @@
 	fl6.daddr = iph->daddr;
 	fl6.saddr = iph->saddr;
 	fl6.flowlabel = ip6_flowinfo(iph);
+	fl6.flowi6_uid = uid;
 
 	dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr);
 	rt6_do_redirect(dst, NULL, skb);
@@ -1521,6 +1523,7 @@
 	fl6.flowi6_mark = mark;
 	fl6.daddr = msg->dest;
 	fl6.saddr = iph->daddr;
+	fl6.flowi6_uid = sock_net_uid(net, NULL);
 
 	dst = ip6_route_redirect(net, &fl6, &iph->saddr);
 	rt6_do_redirect(dst, NULL, skb);
@@ -1529,7 +1532,8 @@
 
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 {
-	ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
+	ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark,
+		     sk->sk_uid);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_redirect);
 
@@ -1724,6 +1728,8 @@
 		} else {
 			val = nla_get_u32(nla);
 		}
+		if (type == RTAX_HOPLIMIT && val > 255)
+			val = 255;
 		if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK))
 			goto err;
 
@@ -1753,6 +1759,10 @@
 	int addr_type;
 	int err = -EINVAL;
 
+	/* RTF_PCPU is an internal flag; can not be set by userspace */
+	if (cfg->fc_flags & RTF_PCPU)
+		goto out;
+
 	if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128)
 		goto out;
 #ifndef CONFIG_IPV6_SUBTREES
@@ -2079,6 +2089,8 @@
 				continue;
 			if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric)
 				continue;
+			if (cfg->fc_protocol && cfg->fc_protocol != rt->rt6i_protocol)
+				continue;
 			dst_hold(&rt->dst);
 			read_unlock_bh(&table->tb6_lock);
 
@@ -3126,7 +3138,9 @@
 	if (iif) {
 #ifdef CONFIG_IPV6_MROUTE
 		if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
-			int err = ip6mr_get_route(net, skb, rtm, nowait);
+			int err = ip6mr_get_route(net, skb, rtm, nowait,
+						  portid);
+
 			if (err <= 0) {
 				if (!nowait) {
 					if (err == 0)
@@ -3180,7 +3194,8 @@
 	if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags)))
 		goto nla_put_failure;
 
-	lwtunnel_fill_encap(skb, rt->dst.lwtstate);
+	if (lwtunnel_fill_encap(skb, rt->dst.lwtstate) < 0)
+		goto nla_put_failure;
 
 	nlmsg_end(skb, nlh);
 	return 0;
@@ -3252,6 +3267,7 @@
 					   nla_get_u32(tb[RTA_UID]));
 	else
 		fl6.flowi6_uid = iif ? INVALID_UID : current_uid();
+
 	if (iif) {
 		struct net_device *dev;
 		int flags = 0;
@@ -3345,7 +3361,10 @@
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 	struct net *net = dev_net(dev);
 
-	if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
+	if (!(dev->flags & IFF_LOOPBACK))
+		return NOTIFY_OK;
+
+	if (event == NETDEV_REGISTER) {
 		net->ipv6.ip6_null_entry->dst.dev = dev;
 		net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
@@ -3354,6 +3373,12 @@
 		net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
 		net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
 #endif
+	 } else if (event == NETDEV_UNREGISTER) {
+		in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev);
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+		in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev);
+		in6_dev_put(net->ipv6.ip6_blk_hole_entry->rt6i_idev);
+#endif
 	}
 
 	return NOTIFY_OK;
@@ -3660,9 +3685,24 @@
 
 static struct notifier_block ip6_route_dev_notifier = {
 	.notifier_call = ip6_route_dev_notify,
-	.priority = 0,
+	.priority = ADDRCONF_NOTIFY_PRIORITY - 10,
 };
 
+void __init ip6_route_init_special_entries(void)
+{
+	/* Registering of the loopback is done before this portion of code,
+	 * the loopback reference in rt6_info will not be taken, do it
+	 * manually for init_net */
+	init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
+	init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
+	init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+	init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
+	init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+  #endif
+}
+
 int __init ip6_route_init(void)
 {
 	int ret;
@@ -3689,17 +3729,6 @@
 
 	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
 
-	/* Registering of the loopback is done before this portion of code,
-	 * the loopback reference in rt6_info will not be taken, do it
-	 * manually for init_net */
-	init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
-	init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
-	init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-	init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
-	init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-  #endif
 	ret = fib6_init();
 	if (ret)
 		goto out_register_subsys;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index dcccae8..184f0fe 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -560,13 +560,13 @@
 
 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
-				 t->parms.link, 0, IPPROTO_IPV6, 0);
+				 t->parms.link, 0, iph->protocol, 0);
 		err = 0;
 		goto out;
 	}
 	if (type == ICMP_REDIRECT) {
 		ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
-			      IPPROTO_IPV6, 0);
+			      iph->protocol, 0);
 		err = 0;
 		goto out;
 	}
@@ -681,14 +681,15 @@
 		skb->mac_header = skb->network_header;
 		skb_reset_network_header(skb);
 		IPCB(skb)->flags = 0;
-		skb->protocol = htons(ETH_P_IPV6);
+		skb->dev = tunnel->dev;
 
 		if (packet_is_spoofed(skb, iph, tunnel)) {
 			tunnel->dev->stats.rx_errors++;
 			goto out;
 		}
 
-		__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
+		if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6)))
+			goto out;
 
 		err = IP_ECN_decapsulate(iph, skb);
 		if (unlikely(err)) {
@@ -1388,6 +1389,7 @@
 	tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
 	if (!tunnel->dst_cache) {
 		free_percpu(dev->tstats);
+		dev->tstats = NULL;
 		return -ENOMEM;
 	}
 
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index a22015f..336843c 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -228,7 +228,7 @@
 		fl6.flowi6_mark = ireq->ir_mark;
 		fl6.fl6_dport = ireq->ir_rmt_port;
 		fl6.fl6_sport = inet_sk(sk)->inet_sport;
-		fl6.flowi6_uid = sock_i_uid(sk);
+		fl6.flowi6_uid = sk->sk_uid;
 		security_req_classify_flow(req, flowi6_to_flowi(&fl6));
 
 		dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index f85b4c4..4618f52 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -149,8 +149,13 @@
 	 *	connect() to INADDR_ANY means loopback (BSD'ism).
 	 */
 
-	if (ipv6_addr_any(&usin->sin6_addr))
-		usin->sin6_addr.s6_addr[15] = 0x1;
+	if (ipv6_addr_any(&usin->sin6_addr)) {
+		if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
+			ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
+					       &usin->sin6_addr);
+		else
+			usin->sin6_addr = in6addr_loopback;
+	}
 
 	addr_type = ipv6_addr_type(&usin->sin6_addr);
 
@@ -189,7 +194,7 @@
 	 *	TCP over IPv4
 	 */
 
-	if (addr_type == IPV6_ADDR_MAPPED) {
+	if (addr_type & IPV6_ADDR_MAPPED) {
 		u32 exthdrlen = icsk->icsk_ext_hdr_len;
 		struct sockaddr_in sin;
 
@@ -234,7 +239,7 @@
 	fl6.flowi6_mark = sk->sk_mark;
 	fl6.fl6_dport = usin->sin6_port;
 	fl6.fl6_sport = inet->inet_sport;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 
 	opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
 	final_p = fl6_update_dst(&fl6, opt, &final);
@@ -377,10 +382,12 @@
 	np = inet6_sk(sk);
 
 	if (type == NDISC_REDIRECT) {
-		struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
+		if (!sock_owned_by_user(sk)) {
+			struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
 
-		if (dst)
-			dst->ops->redirect(dst, sk, skb);
+			if (dst)
+				dst->ops->redirect(dst, sk, skb);
+		}
 		goto out;
 	}
 
@@ -814,6 +821,7 @@
 	fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);
 	fl6.fl6_dport = t1->dest;
 	fl6.fl6_sport = t1->source;
+	fl6.flowi6_uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
 	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
 	/* Pass a socket to ip6_dst_lookup either it is for RST
@@ -933,9 +941,15 @@
 	/* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
 	 * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
 	 */
+	/* RFC 7323 2.3
+	 * The window field (SEG.WND) of every outgoing segment, with the
+	 * exception of <SYN> segments, MUST be right-shifted by
+	 * Rcv.Wind.Shift bits:
+	 */
 	tcp_v6_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ?
 			tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
-			tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd,
+			tcp_rsk(req)->rcv_nxt,
+			req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
 			tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if,
 			tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr),
 			0, 0);
@@ -969,6 +983,16 @@
 	return 0; /* don't send reset */
 }
 
+static void tcp_v6_restore_cb(struct sk_buff *skb)
+{
+	/* We need to move header back to the beginning if xfrm6_policy_check()
+	 * and tcp_v6_fill_cb() are going to be called again.
+	 * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there.
+	 */
+	memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
+		sizeof(struct inet6_skb_parm));
+}
+
 static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
 					 struct request_sock *req,
 					 struct dst_entry *dst,
@@ -1016,6 +1040,7 @@
 		newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
 #endif
 
+		newnp->ipv6_mc_list = NULL;
 		newnp->ipv6_ac_list = NULL;
 		newnp->ipv6_fl_list = NULL;
 		newnp->pktoptions  = NULL;
@@ -1085,6 +1110,7 @@
 	   First: no IPv4 options.
 	 */
 	newinet->inet_opt = NULL;
+	newnp->ipv6_mc_list = NULL;
 	newnp->ipv6_ac_list = NULL;
 	newnp->ipv6_fl_list = NULL;
 
@@ -1158,8 +1184,10 @@
 						      sk_gfp_atomic(sk, GFP_ATOMIC));
 			consume_skb(ireq->pktopts);
 			ireq->pktopts = NULL;
-			if (newnp->pktoptions)
+			if (newnp->pktoptions) {
+				tcp_v6_restore_cb(newnp->pktoptions);
 				skb_set_owner_r(newnp->pktoptions, newsk);
+			}
 		}
 	}
 
@@ -1199,7 +1227,7 @@
 	if (skb->protocol == htons(ETH_P_IP))
 		return tcp_v4_do_rcv(sk, skb);
 
-	if (sk_filter(sk, skb))
+	if (tcp_filter(sk, skb))
 		goto discard;
 
 	/*
@@ -1303,6 +1331,7 @@
 			np->flow_label = ip6_flowlabel(ipv6_hdr(opt_skb));
 		if (ipv6_opt_accepted(sk, opt_skb, &TCP_SKB_CB(opt_skb)->header.h6)) {
 			skb_set_owner_r(opt_skb, sk);
+			tcp_v6_restore_cb(opt_skb);
 			opt_skb = xchg(&np->pktoptions, opt_skb);
 		} else {
 			__kfree_skb(opt_skb);
@@ -1336,15 +1365,6 @@
 	TCP_SKB_CB(skb)->sacked = 0;
 }
 
-static void tcp_v6_restore_cb(struct sk_buff *skb)
-{
-	/* We need to move header back to the beginning if xfrm6_policy_check()
-	 * and tcp_v6_fill_cb() are going to be called again.
-	 */
-	memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
-		sizeof(struct inet6_skb_parm));
-}
-
 static int tcp_v6_rcv(struct sk_buff *skb)
 {
 	const struct tcphdr *th;
@@ -1431,8 +1451,10 @@
 	if (tcp_v6_inbound_md5_hash(sk, skb))
 		goto discard_and_relse;
 
-	if (sk_filter(sk, skb))
+	if (tcp_filter(sk, skb))
 		goto discard_and_relse;
+	th = (const struct tcphdr *)skb->data;
+	hdr = ipv6_hdr(skb);
 
 	skb->dev = NULL;
 
@@ -1707,7 +1729,9 @@
 	destp = ntohs(inet->inet_dport);
 	srcp  = ntohs(inet->inet_sport);
 
-	if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
+	if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
+	    icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
+	    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
 		timer_active	= 1;
 		timer_expires	= icsk->icsk_timeout;
 	} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 9cb0ff3..cedced5 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -402,6 +402,7 @@
 	int peeked, off = 0;
 	int err;
 	int is_udplite = IS_UDPLITE(sk);
+	bool checksum_valid = false;
 	int is_udp4;
 	bool slow;
 
@@ -433,11 +434,12 @@
 	 */
 
 	if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
-		if (udp_lib_checksum_complete(skb))
+		checksum_valid = !udp_lib_checksum_complete(skb);
+		if (!checksum_valid)
 			goto csum_copy_err;
 	}
 
-	if (skb_csum_unnecessary(skb))
+	if (checksum_valid || skb_csum_unnecessary(skb))
 		err = skb_copy_datagram_msg(skb, sizeof(struct udphdr),
 					    msg, copied);
 	else {
@@ -496,7 +498,8 @@
 
 	if (is_udp4) {
 		if (inet->cmsg_flags)
-			ip_cmsg_recv(msg, skb);
+			ip_cmsg_recv_offset(msg, skb,
+					    sizeof(struct udphdr), off);
 	} else {
 		if (np->rxopt.all)
 			ip6_datagram_recv_specific_ctl(sk, msg, skb);
@@ -647,7 +650,7 @@
 
 		/* if we're overly short, let UDP handle it */
 		encap_rcv = ACCESS_ONCE(up->encap_rcv);
-		if (skb->len > sizeof(struct udphdr) && encap_rcv) {
+		if (encap_rcv) {
 			int ret;
 
 			/* Verify checksum before giving to encap */
@@ -1133,6 +1136,10 @@
 			if (addr_len < SIN6_LEN_RFC2133)
 				return -EINVAL;
 			daddr = &sin6->sin6_addr;
+			if (ipv6_addr_any(daddr) &&
+			    ipv6_addr_v4mapped(&np->saddr))
+				ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
+						       daddr);
 			break;
 		case AF_INET:
 			goto do_udp_sendmsg;
@@ -1241,7 +1248,7 @@
 		fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
 
 	fl6.flowi6_mark = sk->sk_mark;
-	fl6.flowi6_uid = sock_i_uid(sk);
+	fl6.flowi6_uid = sk->sk_uid;
 
 	if (msg->msg_controllen) {
 		opt = &opt_space;
@@ -1550,6 +1557,7 @@
 	.compat_getsockopt = compat_udpv6_getsockopt,
 #endif
 	.clear_sk	   = udp_v6_clear_sk,
+	.diag_destroy      = udp_abort,
 };
 
 static struct inet_protosw udpv6_protosw = {
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 7441e1e..0158296 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -29,6 +29,7 @@
 	u8 frag_hdr_sz = sizeof(struct frag_hdr);
 	__wsum csum;
 	int tnl_hlen;
+	int err;
 
 	mss = skb_shinfo(skb)->gso_size;
 	if (unlikely(skb->len <= mss))
@@ -97,7 +98,10 @@
 		/* Find the unfragmentable header and shift it left by frag_hdr_sz
 		 * bytes to insert fragment header.
 		 */
-		unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+		err = ip6_find_1stfragopt(skb, &prevhdr);
+		if (err < 0)
+			return ERR_PTR(err);
+		unfrag_ip6hlen = err;
 		nexthdr = *prevhdr;
 		*prevhdr = NEXTHDR_FRAGMENT;
 		unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index 0e01590..07d3657 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -47,6 +47,8 @@
 	iph = ipv6_hdr(skb);
 
 	hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
+	if (hdr_len < 0)
+		return hdr_len;
 	skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
 	skb_set_network_header(skb, -x->props.header_len);
 	skb->transport_header = skb->network_header + hdr_len;
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 4e34410..1d3bbe6 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -28,6 +28,8 @@
 	iph = ipv6_hdr(skb);
 
 	hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
+	if (hdr_len < 0)
+		return hdr_len;
 	skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
 	skb_set_network_header(skb, -x->props.header_len);
 	skb->transport_header = skb->network_header + hdr_len;
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 48d0dc89b..e735f78 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1168,11 +1168,10 @@
 		sipx->sipx_network	= ipxif->if_netnum;
 		memcpy(sipx->sipx_node, ipxif->if_node,
 			sizeof(sipx->sipx_node));
-		rc = -EFAULT;
-		if (copy_to_user(arg, &ifr, sizeof(ifr)))
-			break;
-		ipxitf_put(ipxif);
 		rc = 0;
+		if (copy_to_user(arg, &ifr, sizeof(ifr)))
+			rc = -EFAULT;
+		ipxitf_put(ipxif);
 		break;
 	}
 	case SIOCAIPXITFCRT:
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 923abd6..8d2f7c9 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1024,8 +1024,11 @@
 	}
 
 	/* Check if we have opened a local TSAP */
-	if (!self->tsap)
-		irda_open_tsap(self, LSAP_ANY, addr->sir_name);
+	if (!self->tsap) {
+		err = irda_open_tsap(self, LSAP_ANY, addr->sir_name);
+		if (err)
+			goto out;
+	}
 
 	/* Move to connecting socket, start sending Connect Requests */
 	sock->state = SS_CONNECTING;
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 4a7ae32a..1138eaf 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -185,8 +185,12 @@
 
 	self->magic = IAS_MAGIC;
 	self->mode = mode;
-	if (mode == IAS_CLIENT)
-		iriap_register_lsap(self, slsap_sel, mode);
+	if (mode == IAS_CLIENT) {
+		if (iriap_register_lsap(self, slsap_sel, mode)) {
+			kfree(self);
+			return NULL;
+		}
+	}
 
 	self->confirm = callback;
 	self->priv = priv;
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
index acbe61c..160dc89 100644
--- a/net/irda/irqueue.c
+++ b/net/irda/irqueue.c
@@ -383,9 +383,6 @@
  *    for deallocating this structure if it's complex. If not the user can
  *    just supply kfree, which should take care of the job.
  */
-#ifdef CONFIG_LOCKDEP
-static int hashbin_lock_depth = 0;
-#endif
 int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
 {
 	irda_queue_t* queue;
@@ -396,22 +393,27 @@
 	IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;);
 
 	/* Synchronize */
-	if ( hashbin->hb_type & HB_LOCK ) {
-		spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags,
-					 hashbin_lock_depth++);
-	}
+	if (hashbin->hb_type & HB_LOCK)
+		spin_lock_irqsave(&hashbin->hb_spinlock, flags);
 
 	/*
 	 *  Free the entries in the hashbin, TODO: use hashbin_clear when
 	 *  it has been shown to work
 	 */
 	for (i = 0; i < HASHBIN_SIZE; i ++ ) {
-		queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
-		while (queue ) {
-			if (free_func)
-				(*free_func)(queue);
-			queue = dequeue_first(
-				(irda_queue_t**) &hashbin->hb_queue[i]);
+		while (1) {
+			queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
+
+			if (!queue)
+				break;
+
+			if (free_func) {
+				if (hashbin->hb_type & HB_LOCK)
+					spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
+				free_func(queue);
+				if (hashbin->hb_type & HB_LOCK)
+					spin_lock_irqsave(&hashbin->hb_spinlock, flags);
+			}
 		}
 	}
 
@@ -420,12 +422,8 @@
 	hashbin->magic = ~HB_MAGIC;
 
 	/* Release lock */
-	if ( hashbin->hb_type & HB_LOCK) {
+	if (hashbin->hb_type & HB_LOCK)
 		spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
-#ifdef CONFIG_LOCKDEP
-		hashbin_lock_depth--;
-#endif
-	}
 
 	/*
 	 *  Free the hashbin structure
diff --git a/net/key/af_key.c b/net/key/af_key.c
index f9c9ecb..e67c28e 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1135,6 +1135,7 @@
 			goto out;
 	}
 
+	err = -ENOBUFS;
 	key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
 	if (sa->sadb_sa_auth) {
 		int keysize = 0;
@@ -1146,8 +1147,10 @@
 		if (key)
 			keysize = (key->sadb_key_bits + 7) / 8;
 		x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
-		if (!x->aalg)
+		if (!x->aalg) {
+			err = -ENOMEM;
 			goto out;
+		}
 		strcpy(x->aalg->alg_name, a->name);
 		x->aalg->alg_key_len = 0;
 		if (key) {
@@ -1166,8 +1169,10 @@
 				goto out;
 			}
 			x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
-			if (!x->calg)
+			if (!x->calg) {
+				err = -ENOMEM;
 				goto out;
+			}
 			strcpy(x->calg->alg_name, a->name);
 			x->props.calgo = sa->sadb_sa_encrypt;
 		} else {
@@ -1181,8 +1186,10 @@
 			if (key)
 				keysize = (key->sadb_key_bits + 7) / 8;
 			x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
-			if (!x->ealg)
+			if (!x->ealg) {
+				err = -ENOMEM;
 				goto out;
+			}
 			strcpy(x->ealg->alg_name, a->name);
 			x->ealg->alg_key_len = 0;
 			if (key) {
@@ -1227,8 +1234,10 @@
 		struct xfrm_encap_tmpl *natt;
 
 		x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
-		if (!x->encap)
+		if (!x->encap) {
+			err = -ENOMEM;
 			goto out;
+		}
 
 		natt = x->encap;
 		n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index afca2eb..d3dec41 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -278,7 +278,8 @@
 }
 EXPORT_SYMBOL_GPL(l2tp_session_find);
 
-struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
+struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
+					  bool do_ref)
 {
 	int hash;
 	struct l2tp_session *session;
@@ -288,6 +289,9 @@
 	for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
 		hlist_for_each_entry(session, &tunnel->session_hlist[hash], hlist) {
 			if (++count > nth) {
+				l2tp_session_inc_refcount(session);
+				if (do_ref && session->ref)
+					session->ref(session);
 				read_unlock_bh(&tunnel->hlist_lock);
 				return session;
 			}
@@ -298,7 +302,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(l2tp_session_find_nth);
+EXPORT_SYMBOL_GPL(l2tp_session_get_nth);
 
 /* Lookup a session by interface name.
  * This is very inefficient but is only used by management interfaces.
@@ -1581,7 +1585,7 @@
 	/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
 	tunnel->encap = encap;
 	if (encap == L2TP_ENCAPTYPE_UDP) {
-		struct udp_tunnel_sock_cfg udp_cfg;
+		struct udp_tunnel_sock_cfg udp_cfg = { };
 
 		udp_cfg.sk_user_data = tunnel;
 		udp_cfg.encap_type = UDP_ENCAP_L2TPINUDP;
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 5871537..555d962 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -243,7 +243,8 @@
 struct l2tp_session *l2tp_session_find(struct net *net,
 				       struct l2tp_tunnel *tunnel,
 				       u32 session_id);
-struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);
+struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
+					  bool do_ref);
 struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
 struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
 struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);
@@ -273,6 +274,7 @@
 int l2tp_nl_register_ops(enum l2tp_pwtype pw_type,
 			 const struct l2tp_nl_cmd_ops *ops);
 void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
+int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 
 /* Session reference counts. Incremented when code obtains a reference
  * to a session.
diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c
index 2d6760a..d100aed 100644
--- a/net/l2tp/l2tp_debugfs.c
+++ b/net/l2tp/l2tp_debugfs.c
@@ -53,7 +53,7 @@
 
 static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd)
 {
-	pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
+	pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
 	pd->session_idx++;
 
 	if (pd->session == NULL) {
@@ -238,10 +238,14 @@
 	}
 
 	/* Show the tunnel or session context */
-	if (pd->session == NULL)
+	if (!pd->session) {
 		l2tp_dfs_seq_tunnel_show(m, pd->tunnel);
-	else
+	} else {
 		l2tp_dfs_seq_session_show(m, pd->session);
+		if (pd->session->deref)
+			pd->session->deref(pd->session);
+		l2tp_session_dec_refcount(pd->session);
+	}
 
 out:
 	return 0;
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 42de4cc..48ab938 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -11,6 +11,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <asm/ioctls.h>
 #include <linux/icmp.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
@@ -251,8 +252,6 @@
 	int ret;
 	int chk_addr_ret;
 
-	if (!sock_flag(sk, SOCK_ZAPPED))
-		return -EINVAL;
 	if (addr_len < sizeof(struct sockaddr_l2tpip))
 		return -EINVAL;
 	if (addr->l2tp_family != AF_INET)
@@ -267,6 +266,9 @@
 	read_unlock_bh(&l2tp_ip_lock);
 
 	lock_sock(sk);
+	if (!sock_flag(sk, SOCK_ZAPPED))
+		goto out;
+
 	if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_l2tpip))
 		goto out;
 
@@ -381,7 +383,7 @@
 drop:
 	IP_INC_STATS(sock_net(sk), IPSTATS_MIB_INDISCARDS);
 	kfree_skb(skb);
-	return -1;
+	return 0;
 }
 
 /* Userspace will call sendmsg() on the tunnel socket to send L2TP
@@ -554,6 +556,30 @@
 	return err ? err : copied;
 }
 
+int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+	struct sk_buff *skb;
+	int amount;
+
+	switch (cmd) {
+	case SIOCOUTQ:
+		amount = sk_wmem_alloc_get(sk);
+		break;
+	case SIOCINQ:
+		spin_lock_bh(&sk->sk_receive_queue.lock);
+		skb = skb_peek(&sk->sk_receive_queue);
+		amount = skb ? skb->len : 0;
+		spin_unlock_bh(&sk->sk_receive_queue.lock);
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return put_user(amount, (int __user *)arg);
+}
+EXPORT_SYMBOL(l2tp_ioctl);
+
 static struct proto l2tp_ip_prot = {
 	.name		   = "L2TP/IP",
 	.owner		   = THIS_MODULE,
@@ -562,7 +588,7 @@
 	.bind		   = l2tp_ip_bind,
 	.connect	   = l2tp_ip_connect,
 	.disconnect	   = l2tp_ip_disconnect,
-	.ioctl		   = udp_ioctl,
+	.ioctl		   = l2tp_ioctl,
 	.destroy	   = l2tp_ip_destroy_sock,
 	.setsockopt	   = ip_setsockopt,
 	.getsockopt	   = ip_getsockopt,
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 9ee4ddb..c8f483c 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -266,8 +266,6 @@
 	int addr_type;
 	int err;
 
-	if (!sock_flag(sk, SOCK_ZAPPED))
-		return -EINVAL;
 	if (addr->l2tp_family != AF_INET6)
 		return -EINVAL;
 	if (addr_len < sizeof(*addr))
@@ -293,6 +291,9 @@
 	lock_sock(sk);
 
 	err = -EINVAL;
+	if (!sock_flag(sk, SOCK_ZAPPED))
+		goto out_unlock;
+
 	if (sk->sk_state != TCP_CLOSE)
 		goto out_unlock;
 
@@ -517,6 +518,7 @@
 	memset(&fl6, 0, sizeof(fl6));
 
 	fl6.flowi6_mark = sk->sk_mark;
+	fl6.flowi6_uid = sk->sk_uid;
 
 	if (lsa) {
 		if (addr_len < SIN6_LEN_RFC2133)
@@ -713,7 +715,7 @@
 	.bind		   = l2tp_ip6_bind,
 	.connect	   = l2tp_ip6_connect,
 	.disconnect	   = l2tp_ip6_disconnect,
-	.ioctl		   = udp_ioctl,
+	.ioctl		   = l2tp_ioctl,
 	.destroy	   = l2tp_ip6_destroy_sock,
 	.setsockopt	   = ipv6_setsockopt,
 	.getsockopt	   = ipv6_getsockopt,
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 2caaa84..665cc74 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -827,7 +827,7 @@
 				goto out;
 		}
 
-		session = l2tp_session_find_nth(tunnel, si);
+		session = l2tp_session_get_nth(tunnel, si, false);
 		if (session == NULL) {
 			ti++;
 			tunnel = NULL;
@@ -837,8 +837,11 @@
 
 		if (l2tp_nl_session_send(skb, NETLINK_CB(cb->skb).portid,
 					 cb->nlh->nlmsg_seq, NLM_F_MULTI,
-					 session, L2TP_CMD_SESSION_GET) < 0)
+					 session, L2TP_CMD_SESSION_GET) < 0) {
+			l2tp_session_dec_refcount(session);
 			break;
+		}
+		l2tp_session_dec_refcount(session);
 
 		si++;
 	}
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 1ad18c5..8ab9c5d 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -467,6 +467,10 @@
 static void pppol2tp_session_destruct(struct sock *sk)
 {
 	struct l2tp_session *session = sk->sk_user_data;
+
+	skb_queue_purge(&sk->sk_receive_queue);
+	skb_queue_purge(&sk->sk_write_queue);
+
 	if (session) {
 		sk->sk_user_data = NULL;
 		BUG_ON(session->magic != L2TP_SESSION_MAGIC);
@@ -505,9 +509,6 @@
 		l2tp_session_queue_purge(session);
 		sock_put(sk);
 	}
-	skb_queue_purge(&sk->sk_receive_queue);
-	skb_queue_purge(&sk->sk_write_queue);
-
 	release_sock(sk);
 
 	/* This will delete the session context via
@@ -1574,7 +1575,7 @@
 
 static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd)
 {
-	pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
+	pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
 	pd->session_idx++;
 
 	if (pd->session == NULL) {
@@ -1701,10 +1702,14 @@
 
 	/* Show the tunnel or session context.
 	 */
-	if (pd->session == NULL)
+	if (!pd->session) {
 		pppol2tp_seq_tunnel_show(m, pd->tunnel);
-	else
+	} else {
 		pppol2tp_seq_session_show(m, pd->session);
+		if (pd->session->deref)
+			pd->session->deref(pd->session);
+		l2tp_session_dec_refcount(pd->session);
+	}
 
 out:
 	return 0;
@@ -1863,4 +1868,4 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(PPPOL2TP_DRV_VERSION);
 MODULE_ALIAS("pppox-proto-" __stringify(PX_PROTO_OL2TP));
-MODULE_ALIAS_L2TP_PWTYPE(11);
+MODULE_ALIAS_L2TP_PWTYPE(7);
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 8dab4e5..bb8edb9 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -626,6 +626,7 @@
 	if (llc->cmsg_flags & LLC_CMSG_PKTINFO) {
 		struct llc_pktinfo info;
 
+		memset(&info, 0, sizeof(info));
 		info.lpi_ifindex = llc_sk(skb->sk)->dev->ifindex;
 		llc_pdu_decode_dsap(skb, &info.lpi_sap);
 		llc_pdu_decode_da(skb, info.lpi_mac);
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index 3e821da..8bc5a1b 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -821,7 +821,10 @@
 		 * another trick required to cope with how the PROCOM state
 		 * machine works. -acme
 		 */
+		skb_orphan(skb);
+		sock_hold(sk);
 		skb->sk = sk;
+		skb->destructor = sock_efree;
 	}
 	if (!sock_owned_by_user(sk))
 		llc_conn_rcv(sk, skb);
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index d0e1e80..5404d0d 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -290,7 +290,10 @@
 
 	ev->type   = LLC_SAP_EV_TYPE_PDU;
 	ev->reason = 0;
+	skb_orphan(skb);
+	sock_hold(sk);
 	skb->sk = sk;
+	skb->destructor = sock_efree;
 	llc_sap_state_process(sap, skb);
 }
 
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 367784b..a830356 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -7,6 +7,7 @@
  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
+ * Copyright(c) 2015 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -61,6 +62,14 @@
 {
 	struct ieee80211_local *local = sta->local;
 	struct tid_ampdu_rx *tid_rx;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.action = IEEE80211_AMPDU_RX_STOP,
+		.tid = tid,
+		.amsdu = false,
+		.timeout = 0,
+		.ssn = 0,
+	};
 
 	lockdep_assert_held(&sta->ampdu_mlme.mtx);
 
@@ -78,8 +87,7 @@
 	       initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator",
 	       (int)reason);
 
-	if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
-			     &sta->sta, tid, NULL, 0, false))
+	if (drv_ampdu_action(local, sta->sdata, &params))
 		sdata_info(sta->sdata,
 			   "HW problem - can not stop rx aggregation for %pM tid %d\n",
 			   sta->sta.addr, tid);
@@ -237,6 +245,15 @@
 {
 	struct ieee80211_local *local = sta->sdata->local;
 	struct tid_ampdu_rx *tid_agg_rx;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.action = IEEE80211_AMPDU_RX_START,
+		.tid = tid,
+		.amsdu = false,
+		.timeout = timeout,
+		.ssn = start_seq_num,
+	};
+
 	int i, ret = -EOPNOTSUPP;
 	u16 status = WLAN_STATUS_REQUEST_DECLINED;
 
@@ -273,8 +290,12 @@
 		buf_size = IEEE80211_MAX_AMPDU_BUF;
 
 	/* make sure the size doesn't exceed the maximum supported by the hw */
-	if (buf_size > local->hw.max_rx_aggregation_subframes)
-		buf_size = local->hw.max_rx_aggregation_subframes;
+	if (buf_size > sta->sta.max_rx_aggregation_subframes)
+		buf_size = sta->sta.max_rx_aggregation_subframes;
+	params.buf_size = buf_size;
+
+	ht_dbg(sta->sdata, "AddBA Req buf_size=%d for %pM\n",
+	       buf_size, sta->sta.addr);
 
 	/* examine state machine */
 	mutex_lock(&sta->ampdu_mlme.mtx);
@@ -322,8 +343,7 @@
 	for (i = 0; i < buf_size; i++)
 		__skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
 
-	ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
-			       &sta->sta, tid, &start_seq_num, 0, false);
+	ret = drv_ampdu_action(local, sta->sdata, &params);
 	ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
 	       sta->sta.addr, tid, ret);
 	if (ret) {
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index ff75718..4932e9f 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -7,6 +7,7 @@
  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
+ * Copyright(c) 2015 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -295,7 +296,14 @@
 {
 	struct ieee80211_local *local = sta->local;
 	struct tid_ampdu_tx *tid_tx;
-	enum ieee80211_ampdu_mlme_action action;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.tid = tid,
+		.buf_size = 0,
+		.amsdu = false,
+		.timeout = 0,
+		.ssn = 0,
+	};
 	int ret;
 
 	lockdep_assert_held(&sta->ampdu_mlme.mtx);
@@ -304,10 +312,10 @@
 	case AGG_STOP_DECLINED:
 	case AGG_STOP_LOCAL_REQUEST:
 	case AGG_STOP_PEER_REQUEST:
-		action = IEEE80211_AMPDU_TX_STOP_CONT;
+		params.action = IEEE80211_AMPDU_TX_STOP_CONT;
 		break;
 	case AGG_STOP_DESTROY_STA:
-		action = IEEE80211_AMPDU_TX_STOP_FLUSH;
+		params.action = IEEE80211_AMPDU_TX_STOP_FLUSH;
 		break;
 	default:
 		WARN_ON_ONCE(1);
@@ -330,9 +338,8 @@
 		spin_unlock_bh(&sta->lock);
 		if (reason != AGG_STOP_DESTROY_STA)
 			return -EALREADY;
-		ret = drv_ampdu_action(local, sta->sdata,
-				       IEEE80211_AMPDU_TX_STOP_FLUSH_CONT,
-				       &sta->sta, tid, NULL, 0, false);
+		params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT;
+		ret = drv_ampdu_action(local, sta->sdata, &params);
 		WARN_ON_ONCE(ret);
 		return 0;
 	}
@@ -381,8 +388,7 @@
 					WLAN_BACK_INITIATOR;
 	tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST;
 
-	ret = drv_ampdu_action(local, sta->sdata, action,
-			       &sta->sta, tid, NULL, 0, false);
+	ret = drv_ampdu_action(local, sta->sdata, &params);
 
 	/* HW shall not deny going back to legacy */
 	if (WARN_ON(ret)) {
@@ -445,7 +451,14 @@
 	struct tid_ampdu_tx *tid_tx;
 	struct ieee80211_local *local = sta->local;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
-	u16 start_seq_num;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.action = IEEE80211_AMPDU_TX_START,
+		.tid = tid,
+		.buf_size = 0,
+		.amsdu = false,
+		.timeout = 0,
+	};
 	int ret;
 
 	tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
@@ -467,10 +480,8 @@
 	 */
 	synchronize_net();
 
-	start_seq_num = sta->tid_seq[tid] >> 4;
-
-	ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
-			       &sta->sta, tid, &start_seq_num, 0, false);
+	params.ssn = sta->tid_seq[tid] >> 4;
+	ret = drv_ampdu_action(local, sdata, &params);
 	if (ret) {
 		ht_dbg(sdata,
 		       "BA request denied - HW unavailable for %pM tid %d\n",
@@ -499,7 +510,7 @@
 
 	/* send AddBA request */
 	ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
-				     tid_tx->dialog_token, start_seq_num,
+				     tid_tx->dialog_token, params.ssn,
 				     IEEE80211_MAX_AMPDU_BUF,
 				     tid_tx->timeout);
 }
@@ -684,18 +695,24 @@
 					 struct sta_info *sta, u16 tid)
 {
 	struct tid_ampdu_tx *tid_tx;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.action = IEEE80211_AMPDU_TX_OPERATIONAL,
+		.tid = tid,
+		.timeout = 0,
+		.ssn = 0,
+	};
 
 	lockdep_assert_held(&sta->ampdu_mlme.mtx);
 
 	tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
+	params.buf_size = tid_tx->buf_size;
+	params.amsdu = tid_tx->amsdu;
 
 	ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n",
 	       sta->sta.addr, tid);
 
-	drv_ampdu_action(local, sta->sdata,
-			 IEEE80211_AMPDU_TX_OPERATIONAL,
-			 &sta->sta, tid, NULL, tid_tx->buf_size,
-			 tid_tx->amsdu);
+	drv_ampdu_action(local, sta->sdata, &params);
 
 	/*
 	 * synchronize with TX path, while splicing the TX path
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index c12f348..19322c0 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -865,7 +865,7 @@
 
 	/* free all potentially still buffered bcast frames */
 	local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf);
-	skb_queue_purge(&sdata->u.ap.ps.bc_buf);
+	ieee80211_purge_tx_queue(&local->hw, &sdata->u.ap.ps.bc_buf);
 
 	mutex_lock(&local->mtx);
 	ieee80211_vif_copy_chanctx_to_vlans(sdata, true);
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index ca1fe55..c258f10 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -284,9 +284,7 @@
 
 int drv_ampdu_action(struct ieee80211_local *local,
 		     struct ieee80211_sub_if_data *sdata,
-		     enum ieee80211_ampdu_mlme_action action,
-		     struct ieee80211_sta *sta, u16 tid,
-		     u16 *ssn, u8 buf_size, bool amsdu)
+		     struct ieee80211_ampdu_params *params)
 {
 	int ret = -EOPNOTSUPP;
 
@@ -296,12 +294,10 @@
 	if (!check_sdata_in_driver(sdata))
 		return -EIO;
 
-	trace_drv_ampdu_action(local, sdata, action, sta, tid,
-			       ssn, buf_size, amsdu);
+	trace_drv_ampdu_action(local, sdata, params);
 
 	if (local->ops->ampdu_action)
-		ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
-					       sta, tid, ssn, buf_size, amsdu);
+		ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params);
 
 	trace_drv_return_int(local, ret);
 
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 154ce4b..18b0d65 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -585,9 +585,7 @@
 
 int drv_ampdu_action(struct ieee80211_local *local,
 		     struct ieee80211_sub_if_data *sdata,
-		     enum ieee80211_ampdu_mlme_action action,
-		     struct ieee80211_sta *sta, u16 tid,
-		     u16 *ssn, u8 buf_size, bool amsdu);
+		     struct ieee80211_ampdu_params *params);
 
 static inline int drv_get_survey(struct ieee80211_local *local, int idx,
 				struct survey_info *survey)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 980e9e9..24ba316 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -66,6 +66,8 @@
 		    2 + (IEEE80211_MAX_SUPP_RATES - 8) +
 		    2 + sizeof(struct ieee80211_ht_cap) +
 		    2 + sizeof(struct ieee80211_ht_operation) +
+		    2 + sizeof(struct ieee80211_vht_cap) +
+		    2 + sizeof(struct ieee80211_vht_operation) +
 		    ifibss->ie_len;
 	presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
 	if (!presp)
@@ -486,14 +488,14 @@
 	struct beacon_data *presp, *old_presp;
 	struct cfg80211_bss *cbss;
 	const struct cfg80211_bss_ies *ies;
-	u16 capability = 0;
+	u16 capability = WLAN_CAPABILITY_IBSS;
 	u64 tsf;
 	int ret = 0;
 
 	sdata_assert_lock(sdata);
 
 	if (ifibss->privacy)
-		capability = WLAN_CAPABILITY_PRIVACY;
+		capability |= WLAN_CAPABILITY_PRIVACY;
 
 	cbss = cfg80211_get_bss(sdata->local->hw.wiphy, ifibss->chandef.chan,
 				ifibss->bssid, ifibss->ssid,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 175ffcf..2ee53dc 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -891,12 +891,17 @@
 		supp_ht = supp_ht || sband->ht_cap.ht_supported;
 		supp_vht = supp_vht || sband->vht_cap.vht_supported;
 
-		if (sband->ht_cap.ht_supported)
-			local->rx_chains =
-				max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
-				    local->rx_chains);
+		if (!sband->ht_cap.ht_supported)
+			continue;
 
 		/* TODO: consider VHT for RX chains, hopefully it's the same */
+		local->rx_chains =
+			max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
+			    local->rx_chains);
+
+		/* no need to mask, SM_PS_DISABLED has all bits set */
+		sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
+			             IEEE80211_HT_CAP_SM_PS_SHIFT;
 	}
 
 	/* if low-level driver supports AP, we also support VLAN */
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6f85b6a..9063e8e 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -151,19 +151,26 @@
 void mesh_sta_cleanup(struct sta_info *sta)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
-	u32 changed;
+	u32 changed = 0;
 
 	/*
 	 * maybe userspace handles peer allocation and peering, but in either
 	 * case the beacon is still generated by the kernel and we might need
 	 * an update.
 	 */
-	changed = mesh_accept_plinks_update(sdata);
+	if (sdata->u.mesh.user_mpm &&
+	    sta->mesh->plink_state == NL80211_PLINK_ESTAB)
+		changed |= mesh_plink_dec_estab_count(sdata);
+	changed |= mesh_accept_plinks_update(sdata);
 	if (!sdata->u.mesh.user_mpm) {
 		changed |= mesh_plink_deactivate(sta);
 		del_timer_sync(&sta->mesh->plink_timer);
 	}
 
+	/* make sure no readers can access nexthop sta from here on */
+	mesh_path_flush_by_nexthop(sta);
+	synchronize_net();
+
 	if (changed)
 		ieee80211_mbss_info_change_notify(sdata, changed);
 }
@@ -348,7 +355,7 @@
 	/* fast-forward to vendor IEs */
 	offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0);
 
-	if (offset) {
+	if (offset < ifmsh->ie_len) {
 		len = ifmsh->ie_len - offset;
 		data = ifmsh->ie + offset;
 		if (skb_tailroom(skb) < len)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 83097c3..23095d5 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2517,7 +2517,7 @@
 }
 
 static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
-					 bool assoc)
+					 bool assoc, bool abandon)
 {
 	struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
 
@@ -2539,6 +2539,9 @@
 		mutex_lock(&sdata->local->mtx);
 		ieee80211_vif_release_channel(sdata);
 		mutex_unlock(&sdata->local->mtx);
+
+		if (abandon)
+			cfg80211_abandon_assoc(sdata->dev, assoc_data->bss);
 	}
 
 	kfree(assoc_data);
@@ -2768,7 +2771,7 @@
 			   bssid, reason_code,
 			   ieee80211_get_reason_code_string(reason_code));
 
-		ieee80211_destroy_assoc_data(sdata, false);
+		ieee80211_destroy_assoc_data(sdata, false, true);
 
 		cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
 		return;
@@ -3173,14 +3176,14 @@
 	if (status_code != WLAN_STATUS_SUCCESS) {
 		sdata_info(sdata, "%pM denied association (code=%d)\n",
 			   mgmt->sa, status_code);
-		ieee80211_destroy_assoc_data(sdata, false);
+		ieee80211_destroy_assoc_data(sdata, false, false);
 		event.u.mlme.status = MLME_DENIED;
 		event.u.mlme.reason = status_code;
 		drv_event_callback(sdata->local, sdata, &event);
 	} else {
 		if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
 			/* oops -- internal error -- send timeout for now */
-			ieee80211_destroy_assoc_data(sdata, false);
+			ieee80211_destroy_assoc_data(sdata, false, false);
 			cfg80211_assoc_timeout(sdata->dev, bss);
 			return;
 		}
@@ -3193,7 +3196,7 @@
 		 * recalc after assoc_data is NULL but before associated
 		 * is set can cause the interface to go idle
 		 */
-		ieee80211_destroy_assoc_data(sdata, true);
+		ieee80211_destroy_assoc_data(sdata, true, false);
 
 		/* get uapsd queues configuration */
 		uapsd_queues = 0;
@@ -3888,7 +3891,7 @@
 				.u.mlme.status = MLME_TIMEOUT,
 			};
 
-			ieee80211_destroy_assoc_data(sdata, false);
+			ieee80211_destroy_assoc_data(sdata, false, false);
 			cfg80211_assoc_timeout(sdata->dev, bss);
 			drv_event_callback(sdata->local, sdata, &event);
 		}
@@ -4029,7 +4032,7 @@
 					       WLAN_REASON_DEAUTH_LEAVING,
 					       false, frame_buf);
 		if (ifmgd->assoc_data)
-			ieee80211_destroy_assoc_data(sdata, false);
+			ieee80211_destroy_assoc_data(sdata, false, true);
 		if (ifmgd->auth_data)
 			ieee80211_destroy_auth_data(sdata, false);
 		cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
@@ -4905,7 +4908,7 @@
 					       IEEE80211_STYPE_DEAUTH,
 					       req->reason_code, tx,
 					       frame_buf);
-		ieee80211_destroy_assoc_data(sdata, false);
+		ieee80211_destroy_assoc_data(sdata, false, true);
 		ieee80211_report_disconnect(sdata, frame_buf,
 					    sizeof(frame_buf), true,
 					    req->reason_code);
@@ -4980,7 +4983,7 @@
 	sdata_lock(sdata);
 	if (ifmgd->assoc_data) {
 		struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
-		ieee80211_destroy_assoc_data(sdata, false);
+		ieee80211_destroy_assoc_data(sdata, false, false);
 		cfg80211_assoc_timeout(sdata->dev, bss);
 	}
 	if (ifmgd->auth_data)
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 00a43a7..0402fa4 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -168,6 +168,7 @@
 			break;
 		}
 
+		flush_delayed_work(&sdata->dec_tailroom_needed_wk);
 		drv_remove_interface(local, sdata);
 	}
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a3bb8f7..3bcabc2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1455,12 +1455,16 @@
 	 */
 	if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) &&
 	    !ieee80211_has_morefrags(hdr->frame_control) &&
+	    !ieee80211_is_back_req(hdr->frame_control) &&
 	    !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
 	    (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
 	     rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
-	    /* PM bit is only checked in frames where it isn't reserved,
+	    /*
+	     * PM bit is only checked in frames where it isn't reserved,
 	     * in AP mode it's reserved in non-bufferable management frames
 	     * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
+	     * BAR frames should be ignored as specified in
+	     * IEEE 802.11-2012 10.2.1.2.
 	     */
 	    (!ieee80211_is_mgmt(hdr->frame_control) ||
 	     ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
@@ -2203,16 +2207,22 @@
 	if (!(status->rx_flags & IEEE80211_RX_AMSDU))
 		return RX_CONTINUE;
 
-	if (ieee80211_has_a4(hdr->frame_control) &&
-	    rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-	    !rx->sdata->u.vlan.sta)
-		return RX_DROP_UNUSABLE;
+	if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
+		switch (rx->sdata->vif.type) {
+		case NL80211_IFTYPE_AP_VLAN:
+			if (!rx->sdata->u.vlan.sta)
+				return RX_DROP_UNUSABLE;
+			break;
+		case NL80211_IFTYPE_STATION:
+			if (!rx->sdata->u.mgd.use_4addr)
+				return RX_DROP_UNUSABLE;
+			break;
+		default:
+			return RX_DROP_UNUSABLE;
+		}
+	}
 
-	if (is_multicast_ether_addr(hdr->addr1) &&
-	    ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-	      rx->sdata->u.vlan.sta) ||
-	     (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
-	      rx->sdata->u.mgd.use_4addr)))
+	if (is_multicast_ether_addr(hdr->addr1))
 		return RX_DROP_UNUSABLE;
 
 	skb->dev = dev;
@@ -3390,6 +3400,27 @@
 			    !ether_addr_equal(bssid, hdr->addr1))
 				return false;
 		}
+
+		/*
+		 * 802.11-2016 Table 9-26 says that for data frames, A1 must be
+		 * the BSSID - we've checked that already but may have accepted
+		 * the wildcard (ff:ff:ff:ff:ff:ff).
+		 *
+		 * It also says:
+		 *	The BSSID of the Data frame is determined as follows:
+		 *	a) If the STA is contained within an AP or is associated
+		 *	   with an AP, the BSSID is the address currently in use
+		 *	   by the STA contained in the AP.
+		 *
+		 * So we should not accept data frames with an address that's
+		 * multicast.
+		 *
+		 * Accepting it also opens a security problem because stations
+		 * could encrypt it with the GTK and inject traffic that way.
+		 */
+		if (ieee80211_is_data(hdr->frame_control) && multicast)
+			return false;
+
 		return true;
 	case NL80211_IFTYPE_WDS:
 		if (bssid || !ieee80211_is_data(hdr->frame_control))
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 67066d0..63ea6cb 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -329,6 +329,9 @@
 
 	memcpy(sta->addr, addr, ETH_ALEN);
 	memcpy(sta->sta.addr, addr, ETH_ALEN);
+	sta->sta.max_rx_aggregation_subframes =
+		local->hw.max_rx_aggregation_subframes;
+
 	sta->local = local;
 	sta->sdata = sdata;
 	sta->rx_stats.last_rx = jiffies;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2cafb21..15b0150 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -269,7 +269,7 @@
 	u8 sa_offs, da_offs, pn_offs;
 	u8 band;
 	u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
-	       sizeof(rfc1042_header)];
+	       sizeof(rfc1042_header)] __aligned(2);
 
 	struct rcu_head rcu_head;
 };
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 56c6d6c..913e959 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -80,7 +80,23 @@
 #define KEY_PR_FMT	" cipher:0x%x, flags=%#x, keyidx=%d, hw_key_idx=%d"
 #define KEY_PR_ARG	__entry->cipher, __entry->flags, __entry->keyidx, __entry->hw_key_idx
 
-
+#define AMPDU_ACTION_ENTRY	__field(enum ieee80211_ampdu_mlme_action,		\
+					ieee80211_ampdu_mlme_action)			\
+				STA_ENTRY						\
+				__field(u16, tid)					\
+				__field(u16, ssn)					\
+				__field(u8, buf_size)					\
+				__field(bool, amsdu)					\
+				__field(u16, timeout)
+#define AMPDU_ACTION_ASSIGN	STA_NAMED_ASSIGN(params->sta);				\
+				__entry->tid = params->tid;				\
+				__entry->ssn = params->ssn;				\
+				__entry->buf_size = params->buf_size;			\
+				__entry->amsdu = params->amsdu;				\
+				__entry->timeout = params->timeout;
+#define AMPDU_ACTION_PR_FMT	STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d"
+#define AMPDU_ACTION_PR_ARG	STA_PR_ARG, __entry->tid, __entry->ssn,			\
+				__entry->buf_size, __entry->amsdu, __entry->timeout
 
 /*
  * Tracing for driver callbacks.
@@ -970,38 +986,25 @@
 TRACE_EVENT(drv_ampdu_action,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata,
-		 enum ieee80211_ampdu_mlme_action action,
-		 struct ieee80211_sta *sta, u16 tid,
-		 u16 *ssn, u8 buf_size, bool amsdu),
+		 struct ieee80211_ampdu_params *params),
 
-	TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu),
+	TP_ARGS(local, sdata, params),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
-		STA_ENTRY
-		__field(u32, action)
-		__field(u16, tid)
-		__field(u16, ssn)
-		__field(u8, buf_size)
-		__field(bool, amsdu)
 		VIF_ENTRY
+		AMPDU_ACTION_ENTRY
 	),
 
 	TP_fast_assign(
 		LOCAL_ASSIGN;
 		VIF_ASSIGN;
-		STA_ASSIGN;
-		__entry->action = action;
-		__entry->tid = tid;
-		__entry->ssn = ssn ? *ssn : 0;
-		__entry->buf_size = buf_size;
-		__entry->amsdu = amsdu;
+		AMPDU_ACTION_ASSIGN;
 	),
 
 	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d",
-		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action,
-		__entry->tid, __entry->buf_size, __entry->amsdu
+		LOCAL_PR_FMT VIF_PR_FMT AMPDU_ACTION_PR_FMT,
+		LOCAL_PR_ARG, VIF_PR_ARG, AMPDU_ACTION_PR_ARG
 	)
 );
 
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index bdc224d..ea5dfef 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -365,7 +365,7 @@
 		skb = skb_dequeue(&ps->bc_buf);
 		if (skb) {
 			purged++;
-			dev_kfree_skb(skb);
+			ieee80211_free_txskb(&local->hw, skb);
 		}
 		total += skb_queue_len(&ps->bc_buf);
 	}
@@ -448,7 +448,7 @@
 	if (skb_queue_len(&ps->bc_buf) >= AP_MAX_BC_BUFFER) {
 		ps_dbg(tx->sdata,
 		       "BC TX buffer full - dropping the oldest frame\n");
-		dev_kfree_skb(skb_dequeue(&ps->bc_buf));
+		ieee80211_free_txskb(&tx->local->hw, skb_dequeue(&ps->bc_buf));
 	} else
 		tx->local->total_ps_buffered++;
 
@@ -2699,7 +2699,7 @@
 	int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
 	int hw_headroom = sdata->local->hw.extra_tx_headroom;
 	struct ethhdr eth;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_tx_info *info;
 	struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
 	struct ieee80211_tx_data tx;
 	ieee80211_tx_result r;
@@ -2761,6 +2761,7 @@
 	memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
 	memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
 
+	info = IEEE80211_SKB_CB(skb);
 	memset(info, 0, sizeof(*info));
 	info->band = fast_tx->band;
 	info->control.vif = &sdata->vif;
@@ -3781,7 +3782,7 @@
 			sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
 		if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb))
 			break;
-		dev_kfree_skb_any(skb);
+		ieee80211_free_txskb(hw, skb);
 	}
 
 	info = IEEE80211_SKB_CB(skb);
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index d824c38..e19ea1c5 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -16,6 +16,7 @@
 #include <asm/unaligned.h>
 #include <net/mac80211.h>
 #include <crypto/aes.h>
+#include <crypto/algapi.h>
 
 #include "ieee80211_i.h"
 #include "michael.h"
@@ -152,7 +153,7 @@
 	data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
 	key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
 	michael_mic(key, hdr, data, data_len, mic);
-	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0)
+	if (crypto_memneq(mic, data + data_len, MICHAEL_MIC_LEN))
 		goto mic_fail;
 
 	/* remove Michael MIC from payload */
@@ -1044,7 +1045,7 @@
 		bip_aad(skb, aad);
 		ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
 				   skb->data + 24, skb->len - 24, mic);
-		if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+		if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
 			key->u.aes_cmac.icverrors++;
 			return RX_DROP_UNUSABLE;
 		}
@@ -1094,7 +1095,7 @@
 		bip_aad(skb, aad);
 		ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
 				       skb->data + 24, skb->len - 24, mic);
-		if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+		if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
 			key->u.aes_cmac.icverrors++;
 			return RX_DROP_UNUSABLE;
 		}
@@ -1198,7 +1199,7 @@
 		if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
 				       skb->data + 24, skb->len - 24,
 				       mic) < 0 ||
-		    memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+		    crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
 			key->u.aes_gmac.icverrors++;
 			return RX_DROP_UNUSABLE;
 		}
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 881bc20..52cfc44 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1567,6 +1567,7 @@
 	for (index = 0; index < platform_labels; index++) {
 		struct mpls_route *rt = rtnl_dereference(platform_label[index]);
 		RCU_INIT_POINTER(platform_label[index], NULL);
+		mpls_notify_route(net, index, rt, NULL, NULL);
 		mpls_rt_free(rt);
 	}
 	rtnl_unlock();
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 803001a..1b07578 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1545,7 +1545,8 @@
 /*
  *      Set up receiving multicast socket over UDP
  */
-static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id)
+static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id,
+					int ifindex)
 {
 	/* multicast addr */
 	union ipvs_sockaddr mcast_addr;
@@ -1566,6 +1567,7 @@
 		set_sock_size(sock->sk, 0, result);
 
 	get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id);
+	sock->sk->sk_bound_dev_if = ifindex;
 	result = sock->ops->bind(sock, (struct sockaddr *)&mcast_addr, salen);
 	if (result < 0) {
 		pr_err("Error binding to the multicast addr\n");
@@ -1868,7 +1870,7 @@
 		if (state == IP_VS_STATE_MASTER)
 			sock = make_send_sock(ipvs, id);
 		else
-			sock = make_receive_sock(ipvs, id);
+			sock = make_receive_sock(ipvs, id, dev->ifindex);
 		if (IS_ERR(sock)) {
 			result = PTR_ERR(sock);
 			goto outtinfo;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 3cb3cb8..86a3c6f 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1757,6 +1757,7 @@
 
 int nf_conntrack_init_net(struct net *net)
 {
+	static atomic64_t unique_id;
 	int ret = -ENOMEM;
 	int cpu;
 
@@ -1779,7 +1780,8 @@
 	if (!net->ct.stat)
 		goto err_pcpu_lists;
 
-	net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%p", net);
+	net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%llu",
+				(u64)atomic64_inc_return(&unique_id));
 	if (!net->ct.slabname)
 		goto err_slabname;
 
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9f52729..e565b2b 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -45,6 +45,8 @@
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <net/netfilter/nf_conntrack_timestamp.h>
 #include <net/netfilter/nf_conntrack_labels.h>
+#include <net/netfilter/nf_conntrack_seqadj.h>
+#include <net/netfilter/nf_conntrack_synproxy.h>
 #ifdef CONFIG_NF_NAT_NEEDED
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_l4proto.h>
@@ -1798,6 +1800,8 @@
 	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
 	nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
 	nf_ct_labels_ext_add(ct);
+	nfct_seqadj_ext_add(ct);
+	nfct_synproxy_ext_add(ct);
 
 	/* we must add conntrack extensions before confirmation. */
 	ct->status |= IPS_CONFIRMED;
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index a5d41df..2c89f90 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -401,7 +401,7 @@
 	size_t size = *lenp;
 	int r = 0;
 	int tindex = (unsigned long)table->extra1;
-	struct net *net = current->nsproxy->net_ns;
+	struct net *net = table->extra2;
 
 	if (write) {
 		if (size > sizeof(buf))
@@ -453,7 +453,6 @@
 				 3, "%d", i);
 			nf_log_sysctl_table[i].procname	=
 				nf_log_sysctl_fnames[i];
-			nf_log_sysctl_table[i].data = NULL;
 			nf_log_sysctl_table[i].maxlen = NFLOGGER_NAME_LEN;
 			nf_log_sysctl_table[i].mode = 0644;
 			nf_log_sysctl_table[i].proc_handler =
@@ -463,6 +462,9 @@
 		}
 	}
 
+	for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
+		table[i].extra2 = net;
+
 	net->nf.nf_log_dir_header = register_net_sysctl(net,
 						"net/netfilter/nf_log",
 						table);
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 77afe91..9adedba 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -326,10 +326,12 @@
 		nlh = nlmsg_hdr(skb);
 		err = 0;
 
-		if (nlmsg_len(nlh) < sizeof(struct nfgenmsg) ||
-		    skb->len < nlh->nlmsg_len) {
-			err = -EINVAL;
-			goto ack;
+		if (nlh->nlmsg_len < NLMSG_HDRLEN ||
+		    skb->len < nlh->nlmsg_len ||
+		    nlmsg_len(nlh) < sizeof(struct nfgenmsg)) {
+			nfnl_err_reset(&err_list);
+			status |= NFNL_BATCH_FAILURE;
+			goto done;
 		}
 
 		/* Only requests are handled by the kernel */
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c
index 9dec3bd..0a5df0c 100644
--- a/net/netfilter/nft_dynset.c
+++ b/net/netfilter/nft_dynset.c
@@ -140,7 +140,8 @@
 	if (tb[NFTA_DYNSET_TIMEOUT] != NULL) {
 		if (!(set->flags & NFT_SET_TIMEOUT))
 			return -EINVAL;
-		timeout = be64_to_cpu(nla_get_be64(tb[NFTA_DYNSET_TIMEOUT]));
+		timeout = msecs_to_jiffies(be64_to_cpu(nla_get_be64(
+						tb[NFTA_DYNSET_TIMEOUT])));
 	}
 
 	priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]);
@@ -227,7 +228,8 @@
 		goto nla_put_failure;
 	if (nla_put_string(skb, NFTA_DYNSET_SET_NAME, priv->set->name))
 		goto nla_put_failure;
-	if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, cpu_to_be64(priv->timeout)))
+	if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT,
+			 cpu_to_be64(jiffies_to_msecs(priv->timeout))))
 		goto nla_put_failure;
 	if (priv->expr && nft_expr_dump(skb, NFTA_DYNSET_EXPR, priv->expr))
 		goto nla_put_failure;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index d4aaad7..2fc6ca9 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -415,6 +415,47 @@
 }
 EXPORT_SYMBOL_GPL(xt_check_match);
 
+/** xt_check_entry_match - check that matches end before start of target
+ *
+ * @match: beginning of xt_entry_match
+ * @target: beginning of this rules target (alleged end of matches)
+ * @alignment: alignment requirement of match structures
+ *
+ * Validates that all matches add up to the beginning of the target,
+ * and that each match covers at least the base structure size.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+static int xt_check_entry_match(const char *match, const char *target,
+				const size_t alignment)
+{
+	const struct xt_entry_match *pos;
+	int length = target - match;
+
+	if (length == 0) /* no matches */
+		return 0;
+
+	pos = (struct xt_entry_match *)match;
+	do {
+		if ((unsigned long)pos % alignment)
+			return -EINVAL;
+
+		if (length < (int)sizeof(struct xt_entry_match))
+			return -EINVAL;
+
+		if (pos->u.match_size < sizeof(struct xt_entry_match))
+			return -EINVAL;
+
+		if (pos->u.match_size > length)
+			return -EINVAL;
+
+		length -= pos->u.match_size;
+		pos = ((void *)((char *)(pos) + (pos)->u.match_size));
+	} while (length > 0);
+
+	return 0;
+}
+
 #ifdef CONFIG_COMPAT
 int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta)
 {
@@ -484,13 +525,14 @@
 }
 EXPORT_SYMBOL_GPL(xt_compat_match_offset);
 
-int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
-			      unsigned int *size)
+void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
+			       unsigned int *size)
 {
 	const struct xt_match *match = m->u.kernel.match;
 	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
 	int pad, off = xt_compat_match_offset(match);
 	u_int16_t msize = cm->u.user.match_size;
+	char name[sizeof(m->u.user.name)];
 
 	m = *dstptr;
 	memcpy(m, cm, sizeof(*cm));
@@ -504,10 +546,12 @@
 
 	msize += off;
 	m->u.user.match_size = msize;
+	strlcpy(name, match->name, sizeof(name));
+	module_put(match->me);
+	strncpy(m->u.user.name, name, sizeof(m->u.user.name));
 
 	*size += off;
 	*dstptr += msize;
-	return 0;
 }
 EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
 
@@ -538,8 +582,125 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
+
+/* non-compat version may have padding after verdict */
+struct compat_xt_standard_target {
+	struct compat_xt_entry_target t;
+	compat_uint_t verdict;
+};
+
+int xt_compat_check_entry_offsets(const void *base, const char *elems,
+				  unsigned int target_offset,
+				  unsigned int next_offset)
+{
+	long size_of_base_struct = elems - (const char *)base;
+	const struct compat_xt_entry_target *t;
+	const char *e = base;
+
+	if (target_offset < size_of_base_struct)
+		return -EINVAL;
+
+	if (target_offset + sizeof(*t) > next_offset)
+		return -EINVAL;
+
+	t = (void *)(e + target_offset);
+	if (t->u.target_size < sizeof(*t))
+		return -EINVAL;
+
+	if (target_offset + t->u.target_size > next_offset)
+		return -EINVAL;
+
+	if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
+	    COMPAT_XT_ALIGN(target_offset + sizeof(struct compat_xt_standard_target)) != next_offset)
+		return -EINVAL;
+
+	/* compat_xt_entry match has less strict aligment requirements,
+	 * otherwise they are identical.  In case of padding differences
+	 * we need to add compat version of xt_check_entry_match.
+	 */
+	BUILD_BUG_ON(sizeof(struct compat_xt_entry_match) != sizeof(struct xt_entry_match));
+
+	return xt_check_entry_match(elems, base + target_offset,
+				    __alignof__(struct compat_xt_entry_match));
+}
+EXPORT_SYMBOL(xt_compat_check_entry_offsets);
 #endif /* CONFIG_COMPAT */
 
+/**
+ * xt_check_entry_offsets - validate arp/ip/ip6t_entry
+ *
+ * @base: pointer to arp/ip/ip6t_entry
+ * @elems: pointer to first xt_entry_match, i.e. ip(6)t_entry->elems
+ * @target_offset: the arp/ip/ip6_t->target_offset
+ * @next_offset: the arp/ip/ip6_t->next_offset
+ *
+ * validates that target_offset and next_offset are sane and that all
+ * match sizes (if any) align with the target offset.
+ *
+ * This function does not validate the targets or matches themselves, it
+ * only tests that all the offsets and sizes are correct, that all
+ * match structures are aligned, and that the last structure ends where
+ * the target structure begins.
+ *
+ * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
+ *
+ * The arp/ip/ip6t_entry structure @base must have passed following tests:
+ * - it must point to a valid memory location
+ * - base to base + next_offset must be accessible, i.e. not exceed allocated
+ *   length.
+ *
+ * A well-formed entry looks like this:
+ *
+ * ip(6)t_entry   match [mtdata]  match [mtdata] target [tgdata] ip(6)t_entry
+ * e->elems[]-----'                              |               |
+ *                matchsize                      |               |
+ *                                matchsize      |               |
+ *                                               |               |
+ * target_offset---------------------------------'               |
+ * next_offset---------------------------------------------------'
+ *
+ * elems[]: flexible array member at end of ip(6)/arpt_entry struct.
+ *          This is where matches (if any) and the target reside.
+ * target_offset: beginning of target.
+ * next_offset: start of the next rule; also: size of this rule.
+ * Since targets have a minimum size, target_offset + minlen <= next_offset.
+ *
+ * Every match stores its size, sum of sizes must not exceed target_offset.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int xt_check_entry_offsets(const void *base,
+			   const char *elems,
+			   unsigned int target_offset,
+			   unsigned int next_offset)
+{
+	long size_of_base_struct = elems - (const char *)base;
+	const struct xt_entry_target *t;
+	const char *e = base;
+
+	/* target start is within the ip/ip6/arpt_entry struct */
+	if (target_offset < size_of_base_struct)
+		return -EINVAL;
+
+	if (target_offset + sizeof(*t) > next_offset)
+		return -EINVAL;
+
+	t = (void *)(e + target_offset);
+	if (t->u.target_size < sizeof(*t))
+		return -EINVAL;
+
+	if (target_offset + t->u.target_size > next_offset)
+		return -EINVAL;
+
+	if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
+	    XT_ALIGN(target_offset + sizeof(struct xt_standard_target)) != next_offset)
+		return -EINVAL;
+
+	return xt_check_entry_match(elems, base + target_offset,
+				    __alignof__(struct xt_entry_match));
+}
+EXPORT_SYMBOL(xt_check_entry_offsets);
+
 int xt_check_target(struct xt_tgchk_param *par,
 		    unsigned int size, u_int8_t proto, bool inv_proto)
 {
@@ -590,6 +751,80 @@
 }
 EXPORT_SYMBOL_GPL(xt_check_target);
 
+/**
+ * xt_copy_counters_from_user - copy counters and metadata from userspace
+ *
+ * @user: src pointer to userspace memory
+ * @len: alleged size of userspace memory
+ * @info: where to store the xt_counters_info metadata
+ * @compat: true if we setsockopt call is done by 32bit task on 64bit kernel
+ *
+ * Copies counter meta data from @user and stores it in @info.
+ *
+ * vmallocs memory to hold the counters, then copies the counter data
+ * from @user to the new memory and returns a pointer to it.
+ *
+ * If @compat is true, @info gets converted automatically to the 64bit
+ * representation.
+ *
+ * The metadata associated with the counters is stored in @info.
+ *
+ * Return: returns pointer that caller has to test via IS_ERR().
+ * If IS_ERR is false, caller has to vfree the pointer.
+ */
+void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
+				 struct xt_counters_info *info, bool compat)
+{
+	void *mem;
+	u64 size;
+
+#ifdef CONFIG_COMPAT
+	if (compat) {
+		/* structures only differ in size due to alignment */
+		struct compat_xt_counters_info compat_tmp;
+
+		if (len <= sizeof(compat_tmp))
+			return ERR_PTR(-EINVAL);
+
+		len -= sizeof(compat_tmp);
+		if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) != 0)
+			return ERR_PTR(-EFAULT);
+
+		strlcpy(info->name, compat_tmp.name, sizeof(info->name));
+		info->num_counters = compat_tmp.num_counters;
+		user += sizeof(compat_tmp);
+	} else
+#endif
+	{
+		if (len <= sizeof(*info))
+			return ERR_PTR(-EINVAL);
+
+		len -= sizeof(*info);
+		if (copy_from_user(info, user, sizeof(*info)) != 0)
+			return ERR_PTR(-EFAULT);
+
+		info->name[sizeof(info->name) - 1] = '\0';
+		user += sizeof(*info);
+	}
+
+	size = sizeof(struct xt_counters);
+	size *= info->num_counters;
+
+	if (size != (u64)len)
+		return ERR_PTR(-EINVAL);
+
+	mem = vmalloc(len);
+	if (!mem)
+		return ERR_PTR(-ENOMEM);
+
+	if (copy_from_user(mem, user, len) == 0)
+		return mem;
+
+	vfree(mem);
+	return ERR_PTR(-EFAULT);
+}
+EXPORT_SYMBOL_GPL(xt_copy_counters_from_user);
+
 #ifdef CONFIG_COMPAT
 int xt_compat_target_offset(const struct xt_target *target)
 {
@@ -605,6 +840,7 @@
 	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
 	int pad, off = xt_compat_target_offset(target);
 	u_int16_t tsize = ct->u.user.target_size;
+	char name[sizeof(t->u.user.name)];
 
 	t = *dstptr;
 	memcpy(t, ct, sizeof(*ct));
@@ -618,6 +854,9 @@
 
 	tsize += off;
 	t->u.user.target_size = tsize;
+	strlcpy(name, target->name, sizeof(name));
+	module_put(target->me);
+	strncpy(t->u.user.name, name, sizeof(t->u.user.name));
 
 	*size += off;
 	*dstptr += tsize;
@@ -658,6 +897,12 @@
 	struct xt_table_info *info = NULL;
 	size_t sz = sizeof(*info) + size;
 
+	if (sz < sizeof(*info))
+		return NULL;
+
+	if (sz < sizeof(*info))
+		return NULL;
+
 	/* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
 	if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages)
 		return NULL;
diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c
index 0975c993..f11aa28 100644
--- a/net/netfilter/xt_IDLETIMER.c
+++ b/net/netfilter/xt_IDLETIMER.c
@@ -49,6 +49,7 @@
 #include <linux/notifier.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
+#include <net/inet_sock.h>
 
 struct idletimer_tg_attr {
 	struct attribute attr;
@@ -355,7 +356,7 @@
 		/* Stores the uid resposible for waking up the radio */
 		if (skb && (skb->sk)) {
 			timer->uid = from_kuid_munged(current_user_ns(),
-						sock_i_uid(skb->sk));
+					sock_i_uid(skb_to_full_sk(skb)));
 		}
 
 		/* checks if there is a pending inactive notification*/
@@ -456,6 +457,7 @@
 		del_timer_sync(&info->timer->timer);
 		sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
 		unregister_pm_notifier(&info->timer->pm_nb);
+		cancel_work_sync(&info->timer->work);
 		kfree(info->timer->attr.attr.name);
 		kfree(info->timer);
 	} else {
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index b7c43de..00f798b 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -104,7 +104,7 @@
 	tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
 	tcp_hdrlen = tcph->doff * 4;
 
-	if (len < tcp_hdrlen)
+	if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr))
 		return -1;
 
 	if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
@@ -156,6 +156,10 @@
 	if (len > tcp_hdrlen)
 		return 0;
 
+	/* tcph->doff has 4 bits, do not wrap it to 0 */
+	if (tcp_hdrlen >= 15 * 4)
+		return 0;
+
 	/*
 	 * MSS Option not found ?! add it..
 	 */
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index e2e7d54..f95aba4 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -321,7 +321,7 @@
 			 st_entry->tag,
 			 get_uid_from_tag(st_entry->tag));
 		rb_erase(&st_entry->sock_node, st_to_free_tree);
-		sockfd_put(st_entry->socket);
+		sock_put(st_entry->sk);
 		kfree(st_entry);
 	}
 }
@@ -1814,8 +1814,11 @@
 }
 
 #ifdef DDEBUG
-/* This function is not in xt_qtaguid_print.c because of locks visibility */
-static void prdebug_full_state(int indent_level, const char *fmt, ...)
+/*
+ * This function is not in xt_qtaguid_print.c because of locks visibility.
+ * The lock of sock_tag_list must be aquired before calling this function
+ */
+static void prdebug_full_state_locked(int indent_level, const char *fmt, ...)
 {
 	va_list args;
 	char *fmt_buff;
@@ -1836,16 +1839,12 @@
 	kfree(buff);
 	va_end(args);
 
-	spin_lock_bh(&sock_tag_list_lock);
 	prdebug_sock_tag_tree(indent_level, &sock_tag_tree);
-	spin_unlock_bh(&sock_tag_list_lock);
 
-	spin_lock_bh(&sock_tag_list_lock);
 	spin_lock_bh(&uid_tag_data_tree_lock);
 	prdebug_uid_tag_data_tree(indent_level, &uid_tag_data_tree);
 	prdebug_proc_qtu_data_tree(indent_level, &proc_qtu_data_tree);
 	spin_unlock_bh(&uid_tag_data_tree_lock);
-	spin_unlock_bh(&sock_tag_list_lock);
 
 	spin_lock_bh(&iface_stat_list_lock);
 	prdebug_iface_stat_list(indent_level, &iface_stat_list);
@@ -1854,7 +1853,7 @@
 	pr_debug("qtaguid: %s(): }\n", __func__);
 }
 #else
-static void prdebug_full_state(int indent_level, const char *fmt, ...) {}
+static void prdebug_full_state_locked(int indent_level, const char *fmt, ...) {}
 #endif
 
 struct proc_ctrl_print_info {
@@ -1930,12 +1929,12 @@
 {
 	struct sock_tag *sock_tag_entry = v;
 	uid_t uid;
-	long f_count;
 
 	CT_DEBUG("qtaguid: proc ctrl pid=%u tgid=%u uid=%u\n",
 		 current->pid, current->tgid, from_kuid(&init_user_ns, current_fsuid()));
 
 	if (sock_tag_entry != SEQ_START_TOKEN) {
+		int sk_ref_count;
 		uid = get_uid_from_tag(sock_tag_entry->tag);
 		CT_DEBUG("qtaguid: proc_read(): sk=%p tag=0x%llx (uid=%u) "
 			 "pid=%u\n",
@@ -1944,13 +1943,13 @@
 			 uid,
 			 sock_tag_entry->pid
 			);
-		f_count = atomic_long_read(
-			&sock_tag_entry->socket->file->f_count);
-		seq_printf(m, "sock=%p tag=0x%llx (uid=%u) pid=%u "
-			   "f_count=%lu\n",
+		sk_ref_count = atomic_read(
+			&sock_tag_entry->sk->sk_refcnt);
+		seq_printf(m, "sock=%pK tag=0x%llx (uid=%u) pid=%u "
+			   "f_count=%d\n",
 			   sock_tag_entry->sk,
 			   sock_tag_entry->tag, uid,
-			   sock_tag_entry->pid, f_count);
+			   sock_tag_entry->pid, sk_ref_count);
 	} else {
 		seq_printf(m, "events: sockets_tagged=%llu "
 			   "sockets_untagged=%llu "
@@ -1977,8 +1976,11 @@
 			   (u64)atomic64_read(&qtu_events.match_no_sk),
 			   (u64)atomic64_read(&qtu_events.match_no_sk_file));
 
-		/* Count the following as part of the last item_index */
-		prdebug_full_state(0, "proc ctrl");
+		/* Count the following as part of the last item_index. No need
+		 * to lock the sock_tag_list here since it is already locked when
+		 * starting the seq_file operation
+		 */
+		prdebug_full_state_locked(0, "proc ctrl");
 	}
 
 	return 0;
@@ -2243,8 +2245,8 @@
 			from_kuid(&init_user_ns, current_fsuid()));
 		goto err;
 	}
-	CT_DEBUG("qtaguid: ctrl_tag(%s): socket->...->f_count=%ld ->sk=%p\n",
-		 input, atomic_long_read(&el_socket->file->f_count),
+	CT_DEBUG("qtaguid: ctrl_tag(%s): socket->...->sk_refcnt=%d ->sk=%p\n",
+		 input, atomic_read(&el_socket->sk->sk_refcnt),
 		 el_socket->sk);
 	if (argc < 3) {
 		acct_tag = make_atag_from_value(0);
@@ -2288,16 +2290,9 @@
 		struct tag_ref *prev_tag_ref_entry;
 
 		CT_DEBUG("qtaguid: ctrl_tag(%s): retag for sk=%p "
-			 "st@%p ...->f_count=%ld\n",
+			 "st@%p ...->sk_refcnt=%d\n",
 			 input, el_socket->sk, sock_tag_entry,
-			 atomic_long_read(&el_socket->file->f_count));
-		/*
-		 * This is a re-tagging, so release the sock_fd that was
-		 * locked at the time of the 1st tagging.
-		 * There is still the ref from this call's sockfd_lookup() so
-		 * it can be done within the spinlock.
-		 */
-		sockfd_put(sock_tag_entry->socket);
+			 atomic_read(&el_socket->sk->sk_refcnt));
 		prev_tag_ref_entry = lookup_tag_ref(sock_tag_entry->tag,
 						    &uid_tag_data_entry);
 		BUG_ON(IS_ERR_OR_NULL(prev_tag_ref_entry));
@@ -2317,8 +2312,12 @@
 			res = -ENOMEM;
 			goto err_tag_unref_put;
 		}
+		/*
+		 * Hold the sk refcount here to make sure the sk pointer cannot
+		 * be freed and reused
+		 */
+		sock_hold(el_socket->sk);
 		sock_tag_entry->sk = el_socket->sk;
-		sock_tag_entry->socket = el_socket;
 		sock_tag_entry->pid = current->tgid;
 		sock_tag_entry->tag = combine_atag_with_uid(acct_tag, uid_int);
 		spin_lock_bh(&uid_tag_data_tree_lock);
@@ -2345,10 +2344,11 @@
 		atomic64_inc(&qtu_events.sockets_tagged);
 	}
 	spin_unlock_bh(&sock_tag_list_lock);
-	/* We keep the ref to the socket (file) until it is untagged */
-	CT_DEBUG("qtaguid: ctrl_tag(%s): done st@%p ...->f_count=%ld\n",
+	/* We keep the ref to the sk until it is untagged */
+	CT_DEBUG("qtaguid: ctrl_tag(%s): done st@%p ...->sk_refcnt=%d\n",
 		 input, sock_tag_entry,
-		 atomic_long_read(&el_socket->file->f_count));
+		 atomic_read(&el_socket->sk->sk_refcnt));
+	sockfd_put(el_socket);
 	return 0;
 
 err_tag_unref_put:
@@ -2356,8 +2356,8 @@
 	tag_ref_entry->num_sock_tags--;
 	free_tag_ref_from_utd_entry(tag_ref_entry, uid_tag_data_entry);
 err_put:
-	CT_DEBUG("qtaguid: ctrl_tag(%s): done. ...->f_count=%ld\n",
-		 input, atomic_long_read(&el_socket->file->f_count) - 1);
+	CT_DEBUG("qtaguid: ctrl_tag(%s): done. ...->sk_refcnt=%d\n",
+		 input, atomic_read(&el_socket->sk->sk_refcnt) - 1);
 	/* Release the sock_fd that was grabbed by sockfd_lookup(). */
 	sockfd_put(el_socket);
 	return res;
@@ -2373,17 +2373,13 @@
 	int sock_fd = 0;
 	struct socket *el_socket;
 	int res, argc;
-	struct sock_tag *sock_tag_entry;
-	struct tag_ref *tag_ref_entry;
-	struct uid_tag_data *utd_entry;
-	struct proc_qtu_data *pqd_entry;
 
 	argc = sscanf(input, "%c %d", &cmd, &sock_fd);
 	CT_DEBUG("qtaguid: ctrl_untag(%s): argc=%d cmd=%c sock_fd=%d\n",
 		 input, argc, cmd, sock_fd);
 	if (argc < 2) {
 		res = -EINVAL;
-		goto err;
+		return res;
 	}
 	el_socket = sockfd_lookup(sock_fd, &res);  /* This locks the file */
 	if (!el_socket) {
@@ -2391,17 +2387,31 @@
 			" sock_fd=%d err=%d pid=%u tgid=%u uid=%u\n",
 			input, sock_fd, res, current->pid, current->tgid,
 			from_kuid(&init_user_ns, current_fsuid()));
-		goto err;
+		return res;
 	}
 	CT_DEBUG("qtaguid: ctrl_untag(%s): socket->...->f_count=%ld ->sk=%p\n",
 		 input, atomic_long_read(&el_socket->file->f_count),
 		 el_socket->sk);
+	res = qtaguid_untag(el_socket, false);
+	sockfd_put(el_socket);
+	return res;
+}
+
+int qtaguid_untag(struct socket *el_socket, bool kernel)
+{
+	int res;
+	pid_t pid;
+	struct sock_tag *sock_tag_entry;
+	struct tag_ref *tag_ref_entry;
+	struct uid_tag_data *utd_entry;
+	struct proc_qtu_data *pqd_entry;
+
 	spin_lock_bh(&sock_tag_list_lock);
 	sock_tag_entry = get_sock_stat_nl(el_socket->sk);
 	if (!sock_tag_entry) {
 		spin_unlock_bh(&sock_tag_list_lock);
 		res = -EINVAL;
-		goto err_put;
+		return res;
 	}
 	/*
 	 * The socket already belongs to the current process
@@ -2413,20 +2423,26 @@
 	BUG_ON(!tag_ref_entry);
 	BUG_ON(tag_ref_entry->num_sock_tags <= 0);
 	spin_lock_bh(&uid_tag_data_tree_lock);
+	if (kernel)
+		pid = sock_tag_entry->pid;
+	else
+		pid = current->tgid;
 	pqd_entry = proc_qtu_data_tree_search(
-		&proc_qtu_data_tree, current->tgid);
+		&proc_qtu_data_tree, pid);
 	/*
 	 * TODO: remove if, and start failing.
 	 * At first, we want to catch user-space code that is not
 	 * opening the /dev/xt_qtaguid.
 	 */
-	if (IS_ERR_OR_NULL(pqd_entry))
+	if (IS_ERR_OR_NULL(pqd_entry) || !sock_tag_entry->list.next) {
 		pr_warn_once("qtaguid: %s(): "
 			     "User space forgot to open /dev/xt_qtaguid? "
-			     "pid=%u tgid=%u uid=%u\n", __func__,
-			     current->pid, current->tgid, from_kuid(&init_user_ns, current_fsuid()));
-	else
+			     "pid=%u tgid=%u sk_pid=%u, uid=%u\n", __func__,
+			     current->pid, current->tgid, sock_tag_entry->pid,
+			     from_kuid(&init_user_ns, current_fsuid()));
+	} else {
 		list_del(&sock_tag_entry->list);
+	}
 	spin_unlock_bh(&uid_tag_data_tree_lock);
 	/*
 	 * We don't free tag_ref from the utd_entry here,
@@ -2435,30 +2451,17 @@
 	tag_ref_entry->num_sock_tags--;
 	spin_unlock_bh(&sock_tag_list_lock);
 	/*
-	 * Release the sock_fd that was grabbed at tag time,
-	 * and once more for the sockfd_lookup() here.
+	 * Release the sock_fd that was grabbed at tag time.
 	 */
-	sockfd_put(sock_tag_entry->socket);
-	CT_DEBUG("qtaguid: ctrl_untag(%s): done. st@%p ...->f_count=%ld\n",
-		 input, sock_tag_entry,
-		 atomic_long_read(&el_socket->file->f_count) - 1);
-	sockfd_put(el_socket);
+	sock_put(sock_tag_entry->sk);
+	CT_DEBUG("qtaguid: done. st@%p ...->sk_refcnt=%d\n",
+		 sock_tag_entry,
+		 atomic_read(&el_socket->sk->sk_refcnt));
 
 	kfree(sock_tag_entry);
 	atomic64_inc(&qtu_events.sockets_untagged);
 
 	return 0;
-
-err_put:
-	CT_DEBUG("qtaguid: ctrl_untag(%s): done. socket->...->f_count=%ld\n",
-		 input, atomic_long_read(&el_socket->file->f_count) - 1);
-	/* Release the sock_fd that was grabbed by sockfd_lookup(). */
-	sockfd_put(el_socket);
-	return res;
-
-err:
-	CT_DEBUG("qtaguid: ctrl_untag(%s): done.\n", input);
-	return res;
 }
 
 static ssize_t qtaguid_ctrl_parse(const char *input, size_t count)
@@ -2548,8 +2551,7 @@
 	uid_t stat_uid = get_uid_from_tag(tag);
 	struct proc_print_info *ppi = m->private;
 	/* Detailed tags are not available to everybody */
-	if (get_atag_from_tag(tag) && !can_read_other_uid_stats(
-						make_kuid(&init_user_ns,stat_uid))) {
+	if (!can_read_other_uid_stats(make_kuid(&init_user_ns,stat_uid))) {
 		CT_DEBUG("qtaguid: stats line: "
 			 "%s 0x%llx %u: insufficient priv "
 			 "from pid=%u tgid=%u uid=%u stats.gid=%u\n",
@@ -2888,8 +2890,10 @@
 
 	sock_tag_tree_erase(&st_to_free_tree);
 
-	prdebug_full_state(0, "%s(): pid=%u tgid=%u", __func__,
+	spin_lock_bh(&sock_tag_list_lock);
+	prdebug_full_state_locked(0, "%s(): pid=%u tgid=%u", __func__,
 			   current->pid, current->tgid);
+	spin_unlock_bh(&sock_tag_list_lock);
 	return 0;
 }
 
diff --git a/net/netfilter/xt_qtaguid_internal.h b/net/netfilter/xt_qtaguid_internal.h
index 6dc14a9..8178fbd 100644
--- a/net/netfilter/xt_qtaguid_internal.h
+++ b/net/netfilter/xt_qtaguid_internal.h
@@ -256,8 +256,6 @@
 struct sock_tag {
 	struct rb_node sock_node;
 	struct sock *sk;  /* Only used as a number, never dereferenced */
-	/* The socket is needed for sockfd_put() */
-	struct socket *socket;
 	/* Used to associate with a given pid */
 	struct list_head list;   /* in proc_qtu_data.sock_tag_list */
 	pid_t pid;
diff --git a/net/netfilter/xt_qtaguid_print.c b/net/netfilter/xt_qtaguid_print.c
index f6a00a3..2a7190d 100644
--- a/net/netfilter/xt_qtaguid_print.c
+++ b/net/netfilter/xt_qtaguid_print.c
@@ -24,7 +24,7 @@
 #include <linux/rbtree.h>
 #include <linux/slab.h>
 #include <linux/spinlock_types.h>
-
+#include <net/sock.h>
 
 #include "xt_qtaguid_internal.h"
 #include "xt_qtaguid_print.h"
@@ -237,10 +237,10 @@
 	tag_str = pp_tag_t(&st->tag);
 	res = kasprintf(GFP_ATOMIC, "sock_tag@%p{"
 			"sock_node=rb_node{...}, "
-			"sk=%p socket=%p (f_count=%lu), list=list_head{...}, "
+			"sk=%p (f_count=%d), list=list_head{...}, "
 			"pid=%u, tag=%s}",
-			st, st->sk, st->socket, atomic_long_read(
-				&st->socket->file->f_count),
+			st, st->sk, atomic_read(
+				&st->sk->sk_refcnt),
 			st->pid, tag_str);
 	_bug_on_err_or_null(res);
 	kfree(tag_str);
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 28cddc8..bfa2b6d 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -824,7 +824,11 @@
  */
 void netlbl_sock_delattr(struct sock *sk)
 {
-	cipso_v4_sock_delattr(sk);
+	switch (sk->sk_family) {
+	case AF_INET:
+		cipso_v4_sock_delattr(sk);
+		break;
+	}
 }
 
 /**
@@ -987,7 +991,11 @@
 */
 void netlbl_req_delattr(struct request_sock *req)
 {
-	cipso_v4_req_delattr(req);
+	switch (req->rsk_ops->family) {
+	case AF_INET:
+		cipso_v4_req_delattr(req);
+		break;
+	}
 }
 
 /**
diff --git a/net/netlink/Kconfig b/net/netlink/Kconfig
index 2c5e95e..5d6e8c0 100644
--- a/net/netlink/Kconfig
+++ b/net/netlink/Kconfig
@@ -2,15 +2,6 @@
 # Netlink Sockets
 #
 
-config NETLINK_MMAP
-	bool "NETLINK: mmaped IO"
-	---help---
-	  This option enables support for memory mapped netlink IO. This
-	  reduces overhead by avoiding copying data between kernel- and
-	  userspace.
-
-	  If unsure, say N.
-
 config NETLINK_DIAG
 	tristate "NETLINK: socket monitoring interface"
 	default n
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 992b35f..acfb16f 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -225,7 +225,7 @@
 
 	dev_hold(dev);
 
-	if (netlink_skb_is_mmaped(skb) || is_vmalloc_addr(skb->head))
+	if (is_vmalloc_addr(skb->head))
 		nskb = netlink_to_full_skb(skb, GFP_ATOMIC);
 	else
 		nskb = skb_clone(skb, GFP_ATOMIC);
@@ -300,610 +300,8 @@
 		wake_up_interruptible(&nlk->wait);
 }
 
-#ifdef CONFIG_NETLINK_MMAP
-static bool netlink_rx_is_mmaped(struct sock *sk)
-{
-	return nlk_sk(sk)->rx_ring.pg_vec != NULL;
-}
-
-static bool netlink_tx_is_mmaped(struct sock *sk)
-{
-	return nlk_sk(sk)->tx_ring.pg_vec != NULL;
-}
-
-static __pure struct page *pgvec_to_page(const void *addr)
-{
-	if (is_vmalloc_addr(addr))
-		return vmalloc_to_page(addr);
-	else
-		return virt_to_page(addr);
-}
-
-static void free_pg_vec(void **pg_vec, unsigned int order, unsigned int len)
-{
-	unsigned int i;
-
-	for (i = 0; i < len; i++) {
-		if (pg_vec[i] != NULL) {
-			if (is_vmalloc_addr(pg_vec[i]))
-				vfree(pg_vec[i]);
-			else
-				free_pages((unsigned long)pg_vec[i], order);
-		}
-	}
-	kfree(pg_vec);
-}
-
-static void *alloc_one_pg_vec_page(unsigned long order)
-{
-	void *buffer;
-	gfp_t gfp_flags = GFP_KERNEL | __GFP_COMP | __GFP_ZERO |
-			  __GFP_NOWARN | __GFP_NORETRY;
-
-	buffer = (void *)__get_free_pages(gfp_flags, order);
-	if (buffer != NULL)
-		return buffer;
-
-	buffer = vzalloc((1 << order) * PAGE_SIZE);
-	if (buffer != NULL)
-		return buffer;
-
-	gfp_flags &= ~__GFP_NORETRY;
-	return (void *)__get_free_pages(gfp_flags, order);
-}
-
-static void **alloc_pg_vec(struct netlink_sock *nlk,
-			   struct nl_mmap_req *req, unsigned int order)
-{
-	unsigned int block_nr = req->nm_block_nr;
-	unsigned int i;
-	void **pg_vec;
-
-	pg_vec = kcalloc(block_nr, sizeof(void *), GFP_KERNEL);
-	if (pg_vec == NULL)
-		return NULL;
-
-	for (i = 0; i < block_nr; i++) {
-		pg_vec[i] = alloc_one_pg_vec_page(order);
-		if (pg_vec[i] == NULL)
-			goto err1;
-	}
-
-	return pg_vec;
-err1:
-	free_pg_vec(pg_vec, order, block_nr);
-	return NULL;
-}
-
-
-static void
-__netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, bool tx_ring, void **pg_vec,
-		   unsigned int order)
-{
-	struct netlink_sock *nlk = nlk_sk(sk);
-	struct sk_buff_head *queue;
-	struct netlink_ring *ring;
-
-	queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue;
-	ring  = tx_ring ? &nlk->tx_ring : &nlk->rx_ring;
-
-	spin_lock_bh(&queue->lock);
-
-	ring->frame_max		= req->nm_frame_nr - 1;
-	ring->head		= 0;
-	ring->frame_size	= req->nm_frame_size;
-	ring->pg_vec_pages	= req->nm_block_size / PAGE_SIZE;
-
-	swap(ring->pg_vec_len, req->nm_block_nr);
-	swap(ring->pg_vec_order, order);
-	swap(ring->pg_vec, pg_vec);
-
-	__skb_queue_purge(queue);
-	spin_unlock_bh(&queue->lock);
-
-	WARN_ON(atomic_read(&nlk->mapped));
-
-	if (pg_vec)
-		free_pg_vec(pg_vec, order, req->nm_block_nr);
-}
-
-static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req,
-			    bool tx_ring)
-{
-	struct netlink_sock *nlk = nlk_sk(sk);
-	struct netlink_ring *ring;
-	void **pg_vec = NULL;
-	unsigned int order = 0;
-
-	ring  = tx_ring ? &nlk->tx_ring : &nlk->rx_ring;
-
-	if (atomic_read(&nlk->mapped))
-		return -EBUSY;
-	if (atomic_read(&ring->pending))
-		return -EBUSY;
-
-	if (req->nm_block_nr) {
-		if (ring->pg_vec != NULL)
-			return -EBUSY;
-
-		if ((int)req->nm_block_size <= 0)
-			return -EINVAL;
-		if (!PAGE_ALIGNED(req->nm_block_size))
-			return -EINVAL;
-		if (req->nm_frame_size < NL_MMAP_HDRLEN)
-			return -EINVAL;
-		if (!IS_ALIGNED(req->nm_frame_size, NL_MMAP_MSG_ALIGNMENT))
-			return -EINVAL;
-
-		ring->frames_per_block = req->nm_block_size /
-					 req->nm_frame_size;
-		if (ring->frames_per_block == 0)
-			return -EINVAL;
-		if (ring->frames_per_block * req->nm_block_nr !=
-		    req->nm_frame_nr)
-			return -EINVAL;
-
-		order = get_order(req->nm_block_size);
-		pg_vec = alloc_pg_vec(nlk, req, order);
-		if (pg_vec == NULL)
-			return -ENOMEM;
-	} else {
-		if (req->nm_frame_nr)
-			return -EINVAL;
-	}
-
-	mutex_lock(&nlk->pg_vec_lock);
-	if (atomic_read(&nlk->mapped) == 0) {
-		__netlink_set_ring(sk, req, tx_ring, pg_vec, order);
-		mutex_unlock(&nlk->pg_vec_lock);
-		return 0;
-	}
-
-	mutex_unlock(&nlk->pg_vec_lock);
-
-	if (pg_vec)
-		free_pg_vec(pg_vec, order, req->nm_block_nr);
-
-	return -EBUSY;
-}
-
-static void netlink_mm_open(struct vm_area_struct *vma)
-{
-	struct file *file = vma->vm_file;
-	struct socket *sock = file->private_data;
-	struct sock *sk = sock->sk;
-
-	if (sk)
-		atomic_inc(&nlk_sk(sk)->mapped);
-}
-
-static void netlink_mm_close(struct vm_area_struct *vma)
-{
-	struct file *file = vma->vm_file;
-	struct socket *sock = file->private_data;
-	struct sock *sk = sock->sk;
-
-	if (sk)
-		atomic_dec(&nlk_sk(sk)->mapped);
-}
-
-static const struct vm_operations_struct netlink_mmap_ops = {
-	.open	= netlink_mm_open,
-	.close	= netlink_mm_close,
-};
-
-static int netlink_mmap(struct file *file, struct socket *sock,
-			struct vm_area_struct *vma)
-{
-	struct sock *sk = sock->sk;
-	struct netlink_sock *nlk = nlk_sk(sk);
-	struct netlink_ring *ring;
-	unsigned long start, size, expected;
-	unsigned int i;
-	int err = -EINVAL;
-
-	if (vma->vm_pgoff)
-		return -EINVAL;
-
-	mutex_lock(&nlk->pg_vec_lock);
-
-	expected = 0;
-	for (ring = &nlk->rx_ring; ring <= &nlk->tx_ring; ring++) {
-		if (ring->pg_vec == NULL)
-			continue;
-		expected += ring->pg_vec_len * ring->pg_vec_pages * PAGE_SIZE;
-	}
-
-	if (expected == 0)
-		goto out;
-
-	size = vma->vm_end - vma->vm_start;
-	if (size != expected)
-		goto out;
-
-	start = vma->vm_start;
-	for (ring = &nlk->rx_ring; ring <= &nlk->tx_ring; ring++) {
-		if (ring->pg_vec == NULL)
-			continue;
-
-		for (i = 0; i < ring->pg_vec_len; i++) {
-			struct page *page;
-			void *kaddr = ring->pg_vec[i];
-			unsigned int pg_num;
-
-			for (pg_num = 0; pg_num < ring->pg_vec_pages; pg_num++) {
-				page = pgvec_to_page(kaddr);
-				err = vm_insert_page(vma, start, page);
-				if (err < 0)
-					goto out;
-				start += PAGE_SIZE;
-				kaddr += PAGE_SIZE;
-			}
-		}
-	}
-
-	atomic_inc(&nlk->mapped);
-	vma->vm_ops = &netlink_mmap_ops;
-	err = 0;
-out:
-	mutex_unlock(&nlk->pg_vec_lock);
-	return err;
-}
-
-static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr, unsigned int nm_len)
-{
-#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 1
-	struct page *p_start, *p_end;
-
-	/* First page is flushed through netlink_{get,set}_status */
-	p_start = pgvec_to_page(hdr + PAGE_SIZE);
-	p_end   = pgvec_to_page((void *)hdr + NL_MMAP_HDRLEN + nm_len - 1);
-	while (p_start <= p_end) {
-		flush_dcache_page(p_start);
-		p_start++;
-	}
-#endif
-}
-
-static enum nl_mmap_status netlink_get_status(const struct nl_mmap_hdr *hdr)
-{
-	smp_rmb();
-	flush_dcache_page(pgvec_to_page(hdr));
-	return hdr->nm_status;
-}
-
-static void netlink_set_status(struct nl_mmap_hdr *hdr,
-			       enum nl_mmap_status status)
-{
-	smp_mb();
-	hdr->nm_status = status;
-	flush_dcache_page(pgvec_to_page(hdr));
-}
-
-static struct nl_mmap_hdr *
-__netlink_lookup_frame(const struct netlink_ring *ring, unsigned int pos)
-{
-	unsigned int pg_vec_pos, frame_off;
-
-	pg_vec_pos = pos / ring->frames_per_block;
-	frame_off  = pos % ring->frames_per_block;
-
-	return ring->pg_vec[pg_vec_pos] + (frame_off * ring->frame_size);
-}
-
-static struct nl_mmap_hdr *
-netlink_lookup_frame(const struct netlink_ring *ring, unsigned int pos,
-		     enum nl_mmap_status status)
-{
-	struct nl_mmap_hdr *hdr;
-
-	hdr = __netlink_lookup_frame(ring, pos);
-	if (netlink_get_status(hdr) != status)
-		return NULL;
-
-	return hdr;
-}
-
-static struct nl_mmap_hdr *
-netlink_current_frame(const struct netlink_ring *ring,
-		      enum nl_mmap_status status)
-{
-	return netlink_lookup_frame(ring, ring->head, status);
-}
-
-static void netlink_increment_head(struct netlink_ring *ring)
-{
-	ring->head = ring->head != ring->frame_max ? ring->head + 1 : 0;
-}
-
-static void netlink_forward_ring(struct netlink_ring *ring)
-{
-	unsigned int head = ring->head;
-	const struct nl_mmap_hdr *hdr;
-
-	do {
-		hdr = __netlink_lookup_frame(ring, ring->head);
-		if (hdr->nm_status == NL_MMAP_STATUS_UNUSED)
-			break;
-		if (hdr->nm_status != NL_MMAP_STATUS_SKIP)
-			break;
-		netlink_increment_head(ring);
-	} while (ring->head != head);
-}
-
-static bool netlink_has_valid_frame(struct netlink_ring *ring)
-{
-	unsigned int head = ring->head, pos = head;
-	const struct nl_mmap_hdr *hdr;
-
-	do {
-		hdr = __netlink_lookup_frame(ring, pos);
-		if (hdr->nm_status == NL_MMAP_STATUS_VALID)
-			return true;
-		pos = pos != 0 ? pos - 1 : ring->frame_max;
-	} while (pos != head);
-
-	return false;
-}
-
-static bool netlink_dump_space(struct netlink_sock *nlk)
-{
-	struct netlink_ring *ring = &nlk->rx_ring;
-	struct nl_mmap_hdr *hdr;
-	unsigned int n;
-
-	hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED);
-	if (hdr == NULL)
-		return false;
-
-	n = ring->head + ring->frame_max / 2;
-	if (n > ring->frame_max)
-		n -= ring->frame_max;
-
-	hdr = __netlink_lookup_frame(ring, n);
-
-	return hdr->nm_status == NL_MMAP_STATUS_UNUSED;
-}
-
-static unsigned int netlink_poll(struct file *file, struct socket *sock,
-				 poll_table *wait)
-{
-	struct sock *sk = sock->sk;
-	struct netlink_sock *nlk = nlk_sk(sk);
-	unsigned int mask;
-	int err;
-
-	if (nlk->rx_ring.pg_vec != NULL) {
-		/* Memory mapped sockets don't call recvmsg(), so flow control
-		 * for dumps is performed here. A dump is allowed to continue
-		 * if at least half the ring is unused.
-		 */
-		while (nlk->cb_running && netlink_dump_space(nlk)) {
-			err = netlink_dump(sk);
-			if (err < 0) {
-				sk->sk_err = -err;
-				sk->sk_error_report(sk);
-				break;
-			}
-		}
-		netlink_rcv_wake(sk);
-	}
-
-	mask = datagram_poll(file, sock, wait);
-
-	/* We could already have received frames in the normal receive
-	 * queue, that will show up as NL_MMAP_STATUS_COPY in the ring,
-	 * so if mask contains pollin/etc already, there's no point
-	 * walking the ring.
-	 */
-	if ((mask & (POLLIN | POLLRDNORM)) != (POLLIN | POLLRDNORM)) {
-		spin_lock_bh(&sk->sk_receive_queue.lock);
-		if (nlk->rx_ring.pg_vec) {
-			if (netlink_has_valid_frame(&nlk->rx_ring))
-				mask |= POLLIN | POLLRDNORM;
-		}
-		spin_unlock_bh(&sk->sk_receive_queue.lock);
-	}
-
-	spin_lock_bh(&sk->sk_write_queue.lock);
-	if (nlk->tx_ring.pg_vec) {
-		if (netlink_current_frame(&nlk->tx_ring, NL_MMAP_STATUS_UNUSED))
-			mask |= POLLOUT | POLLWRNORM;
-	}
-	spin_unlock_bh(&sk->sk_write_queue.lock);
-
-	return mask;
-}
-
-static struct nl_mmap_hdr *netlink_mmap_hdr(struct sk_buff *skb)
-{
-	return (struct nl_mmap_hdr *)(skb->head - NL_MMAP_HDRLEN);
-}
-
-static void netlink_ring_setup_skb(struct sk_buff *skb, struct sock *sk,
-				   struct netlink_ring *ring,
-				   struct nl_mmap_hdr *hdr)
-{
-	unsigned int size;
-	void *data;
-
-	size = ring->frame_size - NL_MMAP_HDRLEN;
-	data = (void *)hdr + NL_MMAP_HDRLEN;
-
-	skb->head	= data;
-	skb->data	= data;
-	skb_reset_tail_pointer(skb);
-	skb->end	= skb->tail + size;
-	skb->len	= 0;
-
-	skb->destructor	= netlink_skb_destructor;
-	NETLINK_CB(skb).flags |= NETLINK_SKB_MMAPED;
-	NETLINK_CB(skb).sk = sk;
-}
-
-static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg,
-				u32 dst_portid, u32 dst_group,
-				struct scm_cookie *scm)
-{
-	struct netlink_sock *nlk = nlk_sk(sk);
-	struct netlink_ring *ring;
-	struct nl_mmap_hdr *hdr;
-	struct sk_buff *skb;
-	unsigned int maxlen;
-	int err = 0, len = 0;
-
-	mutex_lock(&nlk->pg_vec_lock);
-
-	ring   = &nlk->tx_ring;
-	maxlen = ring->frame_size - NL_MMAP_HDRLEN;
-
-	do {
-		unsigned int nm_len;
-
-		hdr = netlink_current_frame(ring, NL_MMAP_STATUS_VALID);
-		if (hdr == NULL) {
-			if (!(msg->msg_flags & MSG_DONTWAIT) &&
-			    atomic_read(&nlk->tx_ring.pending))
-				schedule();
-			continue;
-		}
-
-		nm_len = ACCESS_ONCE(hdr->nm_len);
-		if (nm_len > maxlen) {
-			err = -EINVAL;
-			goto out;
-		}
-
-		netlink_frame_flush_dcache(hdr, nm_len);
-
-		skb = alloc_skb(nm_len, GFP_KERNEL);
-		if (skb == NULL) {
-			err = -ENOBUFS;
-			goto out;
-		}
-		__skb_put(skb, nm_len);
-		memcpy(skb->data, (void *)hdr + NL_MMAP_HDRLEN, nm_len);
-		netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED);
-
-		netlink_increment_head(ring);
-
-		NETLINK_CB(skb).portid	  = nlk->portid;
-		NETLINK_CB(skb).dst_group = dst_group;
-		NETLINK_CB(skb).creds	  = scm->creds;
-
-		err = security_netlink_send(sk, skb);
-		if (err) {
-			kfree_skb(skb);
-			goto out;
-		}
-
-		if (unlikely(dst_group)) {
-			atomic_inc(&skb->users);
-			netlink_broadcast(sk, skb, dst_portid, dst_group,
-					  GFP_KERNEL);
-		}
-		err = netlink_unicast(sk, skb, dst_portid,
-				      msg->msg_flags & MSG_DONTWAIT);
-		if (err < 0)
-			goto out;
-		len += err;
-
-	} while (hdr != NULL ||
-		 (!(msg->msg_flags & MSG_DONTWAIT) &&
-		  atomic_read(&nlk->tx_ring.pending)));
-
-	if (len > 0)
-		err = len;
-out:
-	mutex_unlock(&nlk->pg_vec_lock);
-	return err;
-}
-
-static void netlink_queue_mmaped_skb(struct sock *sk, struct sk_buff *skb)
-{
-	struct nl_mmap_hdr *hdr;
-
-	hdr = netlink_mmap_hdr(skb);
-	hdr->nm_len	= skb->len;
-	hdr->nm_group	= NETLINK_CB(skb).dst_group;
-	hdr->nm_pid	= NETLINK_CB(skb).creds.pid;
-	hdr->nm_uid	= from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid);
-	hdr->nm_gid	= from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid);
-	netlink_frame_flush_dcache(hdr, hdr->nm_len);
-	netlink_set_status(hdr, NL_MMAP_STATUS_VALID);
-
-	NETLINK_CB(skb).flags |= NETLINK_SKB_DELIVERED;
-	kfree_skb(skb);
-}
-
-static void netlink_ring_set_copied(struct sock *sk, struct sk_buff *skb)
-{
-	struct netlink_sock *nlk = nlk_sk(sk);
-	struct netlink_ring *ring = &nlk->rx_ring;
-	struct nl_mmap_hdr *hdr;
-
-	spin_lock_bh(&sk->sk_receive_queue.lock);
-	hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED);
-	if (hdr == NULL) {
-		spin_unlock_bh(&sk->sk_receive_queue.lock);
-		kfree_skb(skb);
-		netlink_overrun(sk);
-		return;
-	}
-	netlink_increment_head(ring);
-	__skb_queue_tail(&sk->sk_receive_queue, skb);
-	spin_unlock_bh(&sk->sk_receive_queue.lock);
-
-	hdr->nm_len	= skb->len;
-	hdr->nm_group	= NETLINK_CB(skb).dst_group;
-	hdr->nm_pid	= NETLINK_CB(skb).creds.pid;
-	hdr->nm_uid	= from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid);
-	hdr->nm_gid	= from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid);
-	netlink_set_status(hdr, NL_MMAP_STATUS_COPY);
-}
-
-#else /* CONFIG_NETLINK_MMAP */
-#define netlink_rx_is_mmaped(sk)	false
-#define netlink_tx_is_mmaped(sk)	false
-#define netlink_mmap			sock_no_mmap
-#define netlink_poll			datagram_poll
-#define netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, scm)	0
-#endif /* CONFIG_NETLINK_MMAP */
-
 static void netlink_skb_destructor(struct sk_buff *skb)
 {
-#ifdef CONFIG_NETLINK_MMAP
-	struct nl_mmap_hdr *hdr;
-	struct netlink_ring *ring;
-	struct sock *sk;
-
-	/* If a packet from the kernel to userspace was freed because of an
-	 * error without being delivered to userspace, the kernel must reset
-	 * the status. In the direction userspace to kernel, the status is
-	 * always reset here after the packet was processed and freed.
-	 */
-	if (netlink_skb_is_mmaped(skb)) {
-		hdr = netlink_mmap_hdr(skb);
-		sk = NETLINK_CB(skb).sk;
-
-		if (NETLINK_CB(skb).flags & NETLINK_SKB_TX) {
-			netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED);
-			ring = &nlk_sk(sk)->tx_ring;
-		} else {
-			if (!(NETLINK_CB(skb).flags & NETLINK_SKB_DELIVERED)) {
-				hdr->nm_len = 0;
-				netlink_set_status(hdr, NL_MMAP_STATUS_VALID);
-			}
-			ring = &nlk_sk(sk)->rx_ring;
-		}
-
-		WARN_ON(atomic_read(&ring->pending) == 0);
-		atomic_dec(&ring->pending);
-		sock_put(sk);
-
-		skb->head = NULL;
-	}
-#endif
 	if (is_vmalloc_addr(skb->head)) {
 		if (!skb->cloned ||
 		    !atomic_dec_return(&(skb_shinfo(skb)->dataref)))
@@ -931,24 +329,11 @@
 	if (nlk->cb_running) {
 		if (nlk->cb.done)
 			nlk->cb.done(&nlk->cb);
-
 		module_put(nlk->cb.module);
 		kfree_skb(nlk->cb.skb);
 	}
 
 	skb_queue_purge(&sk->sk_receive_queue);
-#ifdef CONFIG_NETLINK_MMAP
-	if (1) {
-		struct nl_mmap_req req;
-
-		memset(&req, 0, sizeof(req));
-		if (nlk->rx_ring.pg_vec)
-			__netlink_set_ring(sk, &req, false, NULL, 0);
-		memset(&req, 0, sizeof(req));
-		if (nlk->tx_ring.pg_vec)
-			__netlink_set_ring(sk, &req, true, NULL, 0);
-	}
-#endif /* CONFIG_NETLINK_MMAP */
 
 	if (!sock_flag(sk, SOCK_DEAD)) {
 		printk(KERN_ERR "Freeing alive netlink socket %p\n", sk);
@@ -960,6 +345,14 @@
 	WARN_ON(nlk_sk(sk)->groups);
 }
 
+static void netlink_sock_destruct_work(struct work_struct *work)
+{
+	struct netlink_sock *nlk = container_of(work, struct netlink_sock,
+						work);
+
+	sk_free(&nlk->sk);
+}
+
 /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on
  * SMP. Look, when several writers sleep and reader wakes them up, all but one
  * immediately hit write lock and grab all the cpus. Exclusive sleep solves
@@ -1194,9 +587,6 @@
 		mutex_init(nlk->cb_mutex);
 	}
 	init_waitqueue_head(&nlk->wait);
-#ifdef CONFIG_NETLINK_MMAP
-	mutex_init(&nlk->pg_vec_lock);
-#endif
 
 	sk->sk_destruct = netlink_sock_destruct;
 	sk->sk_protocol = protocol;
@@ -1265,8 +655,18 @@
 static void deferred_put_nlk_sk(struct rcu_head *head)
 {
 	struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu);
+	struct sock *sk = &nlk->sk;
 
-	sock_put(&nlk->sk);
+	if (!atomic_dec_and_test(&sk->sk_refcnt))
+		return;
+
+	if (nlk->cb_running && nlk->cb.done) {
+		INIT_WORK(&nlk->work, netlink_sock_destruct_work);
+		schedule_work(&nlk->work);
+		return;
+	}
+
+	sk_free(sk);
 }
 
 static int netlink_release(struct socket *sock)
@@ -1728,8 +1128,7 @@
 	nlk = nlk_sk(sk);
 
 	if ((atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
-	     test_bit(NETLINK_S_CONGESTED, &nlk->state)) &&
-	    !netlink_skb_is_mmaped(skb)) {
+	     test_bit(NETLINK_S_CONGESTED, &nlk->state))) {
 		DECLARE_WAITQUEUE(wait, current);
 		if (!*timeo) {
 			if (!ssk || netlink_is_kernel(ssk))
@@ -1767,14 +1166,7 @@
 
 	netlink_deliver_tap(skb);
 
-#ifdef CONFIG_NETLINK_MMAP
-	if (netlink_skb_is_mmaped(skb))
-		netlink_queue_mmaped_skb(sk, skb);
-	else if (netlink_rx_is_mmaped(sk))
-		netlink_ring_set_copied(sk, skb);
-	else
-#endif /* CONFIG_NETLINK_MMAP */
-		skb_queue_tail(&sk->sk_receive_queue, skb);
+	skb_queue_tail(&sk->sk_receive_queue, skb);
 	sk->sk_data_ready(sk);
 	return len;
 }
@@ -1798,9 +1190,6 @@
 	int delta;
 
 	WARN_ON(skb->sk != NULL);
-	if (netlink_skb_is_mmaped(skb))
-		return skb;
-
 	delta = skb->end - skb->tail;
 	if (is_vmalloc_addr(skb->head) || delta * 2 < skb->truesize)
 		return skb;
@@ -1880,71 +1269,6 @@
 				    unsigned int ldiff, u32 dst_portid,
 				    gfp_t gfp_mask)
 {
-#ifdef CONFIG_NETLINK_MMAP
-	unsigned int maxlen, linear_size;
-	struct sock *sk = NULL;
-	struct sk_buff *skb;
-	struct netlink_ring *ring;
-	struct nl_mmap_hdr *hdr;
-
-	sk = netlink_getsockbyportid(ssk, dst_portid);
-	if (IS_ERR(sk))
-		goto out;
-
-	ring = &nlk_sk(sk)->rx_ring;
-	/* fast-path without atomic ops for common case: non-mmaped receiver */
-	if (ring->pg_vec == NULL)
-		goto out_put;
-
-	/* We need to account the full linear size needed as a ring
-	 * slot cannot have non-linear parts.
-	 */
-	linear_size = size + ldiff;
-	if (ring->frame_size - NL_MMAP_HDRLEN < linear_size)
-		goto out_put;
-
-	skb = alloc_skb_head(gfp_mask);
-	if (skb == NULL)
-		goto err1;
-
-	spin_lock_bh(&sk->sk_receive_queue.lock);
-	/* check again under lock */
-	if (ring->pg_vec == NULL)
-		goto out_free;
-
-	/* check again under lock */
-	maxlen = ring->frame_size - NL_MMAP_HDRLEN;
-	if (maxlen < linear_size)
-		goto out_free;
-
-	netlink_forward_ring(ring);
-	hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED);
-	if (hdr == NULL)
-		goto err2;
-
-	netlink_ring_setup_skb(skb, sk, ring, hdr);
-	netlink_set_status(hdr, NL_MMAP_STATUS_RESERVED);
-	atomic_inc(&ring->pending);
-	netlink_increment_head(ring);
-
-	spin_unlock_bh(&sk->sk_receive_queue.lock);
-	return skb;
-
-err2:
-	kfree_skb(skb);
-	spin_unlock_bh(&sk->sk_receive_queue.lock);
-	netlink_overrun(sk);
-err1:
-	sock_put(sk);
-	return NULL;
-
-out_free:
-	kfree_skb(skb);
-	spin_unlock_bh(&sk->sk_receive_queue.lock);
-out_put:
-	sock_put(sk);
-out:
-#endif
 	return alloc_skb(size, gfp_mask);
 }
 EXPORT_SYMBOL_GPL(__netlink_alloc_skb);
@@ -2225,8 +1549,7 @@
 	if (level != SOL_NETLINK)
 		return -ENOPROTOOPT;
 
-	if (optname != NETLINK_RX_RING && optname != NETLINK_TX_RING &&
-	    optlen >= sizeof(int) &&
+	if (optlen >= sizeof(int) &&
 	    get_user(val, (unsigned int __user *)optval))
 		return -EFAULT;
 
@@ -2279,25 +1602,6 @@
 		}
 		err = 0;
 		break;
-#ifdef CONFIG_NETLINK_MMAP
-	case NETLINK_RX_RING:
-	case NETLINK_TX_RING: {
-		struct nl_mmap_req req;
-
-		/* Rings might consume more memory than queue limits, require
-		 * CAP_NET_ADMIN.
-		 */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (optlen < sizeof(req))
-			return -EINVAL;
-		if (copy_from_user(&req, optval, sizeof(req)))
-			return -EFAULT;
-		err = netlink_set_ring(sk, &req,
-				       optname == NETLINK_TX_RING);
-		break;
-	}
-#endif /* CONFIG_NETLINK_MMAP */
 	case NETLINK_LISTEN_ALL_NSID:
 		if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_BROADCAST))
 			return -EPERM;
@@ -2467,18 +1771,6 @@
 		smp_rmb();
 	}
 
-	/* It's a really convoluted way for userland to ask for mmaped
-	 * sendmsg(), but that's what we've got...
-	 */
-	if (netlink_tx_is_mmaped(sk) &&
-	    iter_is_iovec(&msg->msg_iter) &&
-	    msg->msg_iter.nr_segs == 1 &&
-	    msg->msg_iter.iov->iov_base == NULL) {
-		err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group,
-					   &scm);
-		goto out;
-	}
-
 	err = -EMSGSIZE;
 	if (len > sk->sk_sndbuf - 32)
 		goto out;
@@ -2557,7 +1849,7 @@
 	/* Record the max length of recvmsg() calls for future allocations */
 	nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len);
 	nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len,
-				     16384);
+				     SKB_WITH_OVERHEAD(32768));
 
 	copied = data_skb->len;
 	if (len < copied) {
@@ -2784,6 +2076,7 @@
 	struct netlink_callback *cb;
 	struct sk_buff *skb = NULL;
 	struct nlmsghdr *nlh;
+	struct module *module;
 	int len, err = -ENOBUFS;
 	int alloc_min_size;
 	int alloc_size;
@@ -2794,8 +2087,7 @@
 		goto errout_skb;
 	}
 
-	if (!netlink_rx_is_mmaped(sk) &&
-	    atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
+	if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
 		goto errout_skb;
 
 	/* NLMSG_GOODSIZE is small to avoid high order allocations being
@@ -2809,9 +2101,8 @@
 	if (alloc_min_size < nlk->max_recvmsg_len) {
 		alloc_size = nlk->max_recvmsg_len;
 		skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
-					GFP_KERNEL |
-					__GFP_NOWARN |
-					__GFP_NORETRY);
+					(GFP_KERNEL & ~__GFP_DIRECT_RECLAIM) |
+					__GFP_NOWARN | __GFP_NORETRY);
 	}
 	if (!skb) {
 		alloc_size = alloc_min_size;
@@ -2863,9 +2154,11 @@
 		cb->done(cb);
 
 	nlk->cb_running = false;
+	module = cb->module;
+	skb = cb->skb;
 	mutex_unlock(nlk->cb_mutex);
-	module_put(cb->module);
-	consume_skb(cb->skb);
+	module_put(module);
+	consume_skb(skb);
 	return 0;
 
 errout_skb:
@@ -2883,16 +2176,7 @@
 	struct netlink_sock *nlk;
 	int ret;
 
-	/* Memory mapped dump requests need to be copied to avoid looping
-	 * on the pending state in netlink_mmap_sendmsg() while the CB hold
-	 * a reference to the skb.
-	 */
-	if (netlink_skb_is_mmaped(skb)) {
-		skb = skb_copy(skb, GFP_KERNEL);
-		if (skb == NULL)
-			return -ENOBUFS;
-	} else
-		atomic_inc(&skb->users);
+	atomic_inc(&skb->users);
 
 	sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid);
 	if (sk == NULL) {
@@ -3236,7 +2520,7 @@
 	.socketpair =	sock_no_socketpair,
 	.accept =	sock_no_accept,
 	.getname =	netlink_getname,
-	.poll =		netlink_poll,
+	.poll =		datagram_poll,
 	.ioctl =	sock_no_ioctl,
 	.listen =	sock_no_listen,
 	.shutdown =	sock_no_shutdown,
@@ -3244,7 +2528,7 @@
 	.getsockopt =	netlink_getsockopt,
 	.sendmsg =	netlink_sendmsg,
 	.recvmsg =	netlink_recvmsg,
-	.mmap =		netlink_mmap,
+	.mmap =		sock_no_mmap,
 	.sendpage =	sock_no_sendpage,
 };
 
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index 14437d9..ea4600a 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -3,6 +3,7 @@
 
 #include <linux/rhashtable.h>
 #include <linux/atomic.h>
+#include <linux/workqueue.h>
 #include <net/sock.h>
 
 #define NLGRPSZ(x)	(ALIGN(x, sizeof(unsigned long) * 8) / 8)
@@ -44,15 +45,10 @@
 	int			(*netlink_bind)(struct net *net, int group);
 	void			(*netlink_unbind)(struct net *net, int group);
 	struct module		*module;
-#ifdef CONFIG_NETLINK_MMAP
-	struct mutex		pg_vec_lock;
-	struct netlink_ring	rx_ring;
-	struct netlink_ring	tx_ring;
-	atomic_t		mapped;
-#endif /* CONFIG_NETLINK_MMAP */
 
 	struct rhash_head	node;
 	struct rcu_head		rcu;
+	struct work_struct	work;
 };
 
 static inline struct netlink_sock *nlk_sk(struct sock *sk)
@@ -60,15 +56,6 @@
 	return container_of(sk, struct netlink_sock, sk);
 }
 
-static inline bool netlink_skb_is_mmaped(const struct sk_buff *skb)
-{
-#ifdef CONFIG_NETLINK_MMAP
-	return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED;
-#else
-	return false;
-#endif /* CONFIG_NETLINK_MMAP */
-}
-
 struct netlink_table {
 	struct rhashtable	hash;
 	struct hlist_head	mc_list;
diff --git a/net/netlink/diag.c b/net/netlink/diag.c
index 3ee63a3cf..8dd836a 100644
--- a/net/netlink/diag.c
+++ b/net/netlink/diag.c
@@ -8,41 +8,6 @@
 
 #include "af_netlink.h"
 
-#ifdef CONFIG_NETLINK_MMAP
-static int sk_diag_put_ring(struct netlink_ring *ring, int nl_type,
-			    struct sk_buff *nlskb)
-{
-	struct netlink_diag_ring ndr;
-
-	ndr.ndr_block_size = ring->pg_vec_pages << PAGE_SHIFT;
-	ndr.ndr_block_nr   = ring->pg_vec_len;
-	ndr.ndr_frame_size = ring->frame_size;
-	ndr.ndr_frame_nr   = ring->frame_max + 1;
-
-	return nla_put(nlskb, nl_type, sizeof(ndr), &ndr);
-}
-
-static int sk_diag_put_rings_cfg(struct sock *sk, struct sk_buff *nlskb)
-{
-	struct netlink_sock *nlk = nlk_sk(sk);
-	int ret;
-
-	mutex_lock(&nlk->pg_vec_lock);
-	ret = sk_diag_put_ring(&nlk->rx_ring, NETLINK_DIAG_RX_RING, nlskb);
-	if (!ret)
-		ret = sk_diag_put_ring(&nlk->tx_ring, NETLINK_DIAG_TX_RING,
-				       nlskb);
-	mutex_unlock(&nlk->pg_vec_lock);
-
-	return ret;
-}
-#else
-static int sk_diag_put_rings_cfg(struct sock *sk, struct sk_buff *nlskb)
-{
-	return 0;
-}
-#endif
-
 static int sk_diag_dump_groups(struct sock *sk, struct sk_buff *nlskb)
 {
 	struct netlink_sock *nlk = nlk_sk(sk);
@@ -87,10 +52,6 @@
 	    sock_diag_put_meminfo(sk, skb, NETLINK_DIAG_MEMINFO))
 		goto out_nlmsg_trim;
 
-	if ((req->ndiag_show & NDIAG_SHOW_RING_CFG) &&
-	    sk_diag_put_rings_cfg(sk, skb))
-		goto out_nlmsg_trim;
-
 	nlmsg_end(skb, nlh);
 	return 0;
 
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index c88d0f2..7cb8184 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -158,9 +158,7 @@
 	new_mpls_lse = (__be32 *)skb_mpls_header(skb);
 	*new_mpls_lse = mpls->mpls_lse;
 
-	if (skb->ip_summed == CHECKSUM_COMPLETE)
-		skb->csum = csum_add(skb->csum, csum_partial(new_mpls_lse,
-							     MPLS_HLEN, 0));
+	skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN);
 
 	hdr = eth_hdr(skb);
 	hdr->h_proto = mpls->mpls_ethertype;
@@ -280,7 +278,7 @@
 	ether_addr_copy_masked(eth_hdr(skb)->h_dest, key->eth_dst,
 			       mask->eth_dst);
 
-	ovs_skb_postpush_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
+	skb_postpush_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
 
 	ether_addr_copy(flow_key->eth.src, eth_hdr(skb)->h_source);
 	ether_addr_copy(flow_key->eth.dst, eth_hdr(skb)->h_dest);
@@ -463,7 +461,7 @@
 		mask_ipv6_addr(saddr, key->ipv6_src, mask->ipv6_src, masked);
 
 		if (unlikely(memcmp(saddr, masked, sizeof(masked)))) {
-			set_ipv6_addr(skb, key->ipv6_proto, saddr, masked,
+			set_ipv6_addr(skb, flow_key->ip.proto, saddr, masked,
 				      true);
 			memcpy(&flow_key->ipv6.addr.src, masked,
 			       sizeof(flow_key->ipv6.addr.src));
@@ -485,7 +483,7 @@
 							     NULL, &flags)
 					       != NEXTHDR_ROUTING);
 
-			set_ipv6_addr(skb, key->ipv6_proto, daddr, masked,
+			set_ipv6_addr(skb, flow_key->ip.proto, daddr, masked,
 				      recalc_csum);
 			memcpy(&flow_key->ipv6.addr.dst, masked,
 			       sizeof(flow_key->ipv6.addr.dst));
@@ -639,7 +637,7 @@
 	/* Reconstruct the MAC header.  */
 	skb_push(skb, data->l2_len);
 	memcpy(skb->data, &data->l2_data, data->l2_len);
-	ovs_skb_postpush_rcsum(skb, skb->data, data->l2_len);
+	skb_postpush_rcsum(skb, skb->data, data->l2_len);
 	skb_reset_mac_header(skb);
 
 	ovs_vport_send(vport, skb);
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index e004067..ad58d2a 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -501,7 +501,7 @@
 
 	/* The conntrack module expects to be working at L3. */
 	nh_ofs = skb_network_offset(skb);
-	skb_pull(skb, nh_ofs);
+	skb_pull_rcsum(skb, nh_ofs);
 
 	if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
 		err = handle_fragments(net, key, info->zone.id, skb);
@@ -527,6 +527,7 @@
 					&info->labels.mask);
 err:
 	skb_push(skb, nh_ofs);
+	skb_postpush_rcsum(skb, skb->data, nh_ofs);
 	if (err)
 		kfree_skb(skb);
 	return err;
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index d1bd4a4..d26b28d 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -588,7 +588,7 @@
 			ipv4 = true;
 			break;
 		case OVS_TUNNEL_KEY_ATTR_IPV6_SRC:
-			SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst,
+			SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.src,
 					nla_get_in6_addr(a), is_mask);
 			ipv6 = true;
 			break;
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 6b0190b..76fcaf1 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -58,7 +58,7 @@
 		return;
 
 	skb_push(skb, ETH_HLEN);
-	ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
+	skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
 	ovs_vport_receive(vport, skb, skb_tunnel_info(skb));
 	return;
 error:
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index d933cb8..5eb7694 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -91,6 +91,8 @@
 	struct vxlan_config conf = {
 		.no_share = true,
 		.flags = VXLAN_F_COLLECT_METADATA | VXLAN_F_UDP_ZERO_CSUM6_RX,
+		/* Don't restrict the packets that can be sent by MTU */
+		.mtu = IP_MAX_MTU,
 	};
 
 	if (!options) {
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 8ea3a96..6e2b62f 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -184,13 +184,6 @@
 int ovs_vport_receive(struct vport *, struct sk_buff *,
 		      const struct ip_tunnel_info *);
 
-static inline void ovs_skb_postpush_rcsum(struct sk_buff *skb,
-				      const void *start, unsigned int len)
-{
-	if (skb->ip_summed == CHECKSUM_COMPLETE)
-		skb->csum = csum_add(skb->csum, csum_partial(start, len, 0));
-}
-
 static inline const char *ovs_vport_name(struct vport *vport)
 {
 	return vport->dev->name;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index da1ae0e..f8d6a0c 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -249,7 +249,7 @@
 static int packet_direct_xmit(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
-	netdev_features_t features;
+	struct sk_buff *orig_skb = skb;
 	struct netdev_queue *txq;
 	int ret = NETDEV_TX_BUSY;
 
@@ -257,9 +257,8 @@
 		     !netif_carrier_ok(dev)))
 		goto drop;
 
-	features = netif_skb_features(skb);
-	if (skb_needs_linearize(skb, features) &&
-	    __skb_linearize(skb))
+	skb = validate_xmit_skb_list(skb, dev);
+	if (skb != orig_skb)
 		goto drop;
 
 	txq = skb_get_tx_queue(dev, skb);
@@ -279,7 +278,7 @@
 	return ret;
 drop:
 	atomic_long_inc(&dev->tx_dropped);
-	kfree_skb(skb);
+	kfree_skb_list(skb);
 	return NET_XMIT_DROP;
 }
 
@@ -1341,7 +1340,7 @@
 				      struct sk_buff *skb,
 				      unsigned int num)
 {
-	return reciprocal_scale(skb_get_hash(skb), num);
+	return reciprocal_scale(__skb_get_hash_symmetric(skb), num);
 }
 
 static unsigned int fanout_demux_lb(struct packet_fanout *f,
@@ -1498,6 +1497,8 @@
 	f->arr[f->num_members] = sk;
 	smp_wmb();
 	f->num_members++;
+	if (f->num_members == 1)
+		dev_add_pack(&f->prot_hook);
 	spin_unlock(&f->lock);
 }
 
@@ -1514,6 +1515,8 @@
 	BUG_ON(i >= f->num_members);
 	f->arr[i] = f->arr[f->num_members - 1];
 	f->num_members--;
+	if (f->num_members == 0)
+		__dev_remove_pack(&f->prot_hook);
 	spin_unlock(&f->lock);
 }
 
@@ -1624,6 +1627,7 @@
 
 static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
 {
+	struct packet_rollover *rollover = NULL;
 	struct packet_sock *po = pkt_sk(sk);
 	struct packet_fanout *f, *match;
 	u8 type = type_flags & 0xff;
@@ -1646,23 +1650,28 @@
 		return -EINVAL;
 	}
 
-	if (!po->running)
-		return -EINVAL;
+	mutex_lock(&fanout_mutex);
 
+	err = -EINVAL;
+	if (!po->running)
+		goto out;
+
+	err = -EALREADY;
 	if (po->fanout)
-		return -EALREADY;
+		goto out;
 
 	if (type == PACKET_FANOUT_ROLLOVER ||
 	    (type_flags & PACKET_FANOUT_FLAG_ROLLOVER)) {
-		po->rollover = kzalloc(sizeof(*po->rollover), GFP_KERNEL);
-		if (!po->rollover)
-			return -ENOMEM;
-		atomic_long_set(&po->rollover->num, 0);
-		atomic_long_set(&po->rollover->num_huge, 0);
-		atomic_long_set(&po->rollover->num_failed, 0);
+		err = -ENOMEM;
+		rollover = kzalloc(sizeof(*rollover), GFP_KERNEL);
+		if (!rollover)
+			goto out;
+		atomic_long_set(&rollover->num, 0);
+		atomic_long_set(&rollover->num_huge, 0);
+		atomic_long_set(&rollover->num_failed, 0);
+		po->rollover = rollover;
 	}
 
-	mutex_lock(&fanout_mutex);
 	match = NULL;
 	list_for_each_entry(f, &fanout_list, list) {
 		if (f->id == id &&
@@ -1692,7 +1701,6 @@
 		match->prot_hook.func = packet_rcv_fanout;
 		match->prot_hook.af_packet_priv = match;
 		match->prot_hook.id_match = match_fanout_group;
-		dev_add_pack(&match->prot_hook);
 		list_add(&match->list, &fanout_list);
 	}
 	err = -EINVAL;
@@ -1709,36 +1717,40 @@
 		}
 	}
 out:
-	mutex_unlock(&fanout_mutex);
-	if (err) {
-		kfree(po->rollover);
+	if (err && rollover) {
+		kfree(rollover);
 		po->rollover = NULL;
 	}
+	mutex_unlock(&fanout_mutex);
 	return err;
 }
 
-static void fanout_release(struct sock *sk)
+/* If pkt_sk(sk)->fanout->sk_ref is zero, this function removes
+ * pkt_sk(sk)->fanout from fanout_list and returns pkt_sk(sk)->fanout.
+ * It is the responsibility of the caller to call fanout_release_data() and
+ * free the returned packet_fanout (after synchronize_net())
+ */
+static struct packet_fanout *fanout_release(struct sock *sk)
 {
 	struct packet_sock *po = pkt_sk(sk);
 	struct packet_fanout *f;
 
-	f = po->fanout;
-	if (!f)
-		return;
-
 	mutex_lock(&fanout_mutex);
-	po->fanout = NULL;
+	f = po->fanout;
+	if (f) {
+		po->fanout = NULL;
 
-	if (atomic_dec_and_test(&f->sk_ref)) {
-		list_del(&f->list);
-		dev_remove_pack(&f->prot_hook);
-		fanout_release_data(f);
-		kfree(f);
+		if (atomic_dec_and_test(&f->sk_ref))
+			list_del(&f->list);
+		else
+			f = NULL;
+
+		if (po->rollover)
+			kfree_rcu(po->rollover, rcu);
 	}
 	mutex_unlock(&fanout_mutex);
 
-	if (po->rollover)
-		kfree_rcu(po->rollover, rcu);
+	return f;
 }
 
 static bool packet_extra_vlan_len_allowed(const struct net_device *dev,
@@ -2638,7 +2650,7 @@
 	int vnet_hdr_len;
 	struct packet_sock *po = pkt_sk(sk);
 	unsigned short gso_type = 0;
-	int hlen, tlen;
+	int hlen, tlen, linear;
 	int extra_len = 0;
 	ssize_t n;
 
@@ -2742,8 +2754,9 @@
 	err = -ENOBUFS;
 	hlen = LL_RESERVED_SPACE(dev);
 	tlen = dev->needed_tailroom;
-	skb = packet_alloc_skb(sk, hlen + tlen, hlen, len,
-			       __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len),
+	linear = __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len);
+	linear = max(linear, min_t(int, len, dev->hard_header_len));
+	skb = packet_alloc_skb(sk, hlen + tlen, hlen, len, linear,
 			       msg->msg_flags & MSG_DONTWAIT, &err);
 	if (skb == NULL)
 		goto out_unlock;
@@ -2846,6 +2859,7 @@
 {
 	struct sock *sk = sock->sk;
 	struct packet_sock *po;
+	struct packet_fanout *f;
 	struct net *net;
 	union tpacket_req_u req_u;
 
@@ -2885,9 +2899,14 @@
 		packet_set_ring(sk, &req_u, 1, 1);
 	}
 
-	fanout_release(sk);
+	f = fanout_release(sk);
 
 	synchronize_net();
+
+	if (f) {
+		fanout_release_data(f);
+		kfree(f);
+	}
 	/*
 	 *	Now the socket is dead. No more input will appear.
 	 */
@@ -3002,7 +3021,7 @@
 			    int addr_len)
 {
 	struct sock *sk = sock->sk;
-	char name[15];
+	char name[sizeof(uaddr->sa_data) + 1];
 
 	/*
 	 *	Check legality
@@ -3010,7 +3029,11 @@
 
 	if (addr_len != sizeof(struct sockaddr))
 		return -EINVAL;
-	strlcpy(name, uaddr->sa_data, sizeof(name));
+	/* uaddr->sa_data comes from the userspace, it's not guaranteed to be
+	 * zero-terminated.
+	 */
+	memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data));
+	name[sizeof(uaddr->sa_data)] = 0;
 
 	return packet_do_bind(sk, name, 0, pkt_sk(sk)->num);
 }
@@ -3436,6 +3459,7 @@
 	i->ifindex = mreq->mr_ifindex;
 	i->alen = mreq->mr_alen;
 	memcpy(i->addr, mreq->mr_address, i->alen);
+	memset(i->addr + i->alen, 0, sizeof(i->addr) - i->alen);
 	i->count = 1;
 	i->next = po->mclist;
 	po->mclist = i;
@@ -3572,19 +3596,25 @@
 
 		if (optlen != sizeof(val))
 			return -EINVAL;
-		if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
-			return -EBUSY;
 		if (copy_from_user(&val, optval, sizeof(val)))
 			return -EFAULT;
 		switch (val) {
 		case TPACKET_V1:
 		case TPACKET_V2:
 		case TPACKET_V3:
-			po->tp_version = val;
-			return 0;
+			break;
 		default:
 			return -EINVAL;
 		}
+		lock_sock(sk);
+		if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) {
+			ret = -EBUSY;
+		} else {
+			po->tp_version = val;
+			ret = 0;
+		}
+		release_sock(sk);
+		return ret;
 	}
 	case PACKET_RESERVE:
 	{
@@ -3596,6 +3626,8 @@
 			return -EBUSY;
 		if (copy_from_user(&val, optval, sizeof(val)))
 			return -EFAULT;
+		if (val > INT_MAX)
+			return -EINVAL;
 		po->tp_reserve = val;
 		return 0;
 	}
@@ -4066,6 +4098,7 @@
 	/* Added to avoid minimal code churn */
 	struct tpacket_req *req = &req_u->req;
 
+	lock_sock(sk);
 	/* Opening a Tx-ring is NOT supported in TPACKET_V3 */
 	if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) {
 		WARN(1, "Tx-ring is not supported.\n");
@@ -4107,8 +4140,8 @@
 		if (unlikely(!PAGE_ALIGNED(req->tp_block_size)))
 			goto out;
 		if (po->tp_version >= TPACKET_V3 &&
-		    (int)(req->tp_block_size -
-			  BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
+		    req->tp_block_size <=
+			  BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv))
 			goto out;
 		if (unlikely(req->tp_frame_size < po->tp_hdrlen +
 					po->tp_reserve))
@@ -4119,6 +4152,8 @@
 		rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
 		if (unlikely(rb->frames_per_block == 0))
 			goto out;
+		if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+			goto out;
 		if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
 					req->tp_frame_nr))
 			goto out;
@@ -4147,7 +4182,6 @@
 			goto out;
 	}
 
-	lock_sock(sk);
 
 	/* Detach socket from network */
 	spin_lock(&po->bind_lock);
@@ -4196,11 +4230,11 @@
 		if (!tx_ring)
 			prb_shutdown_retire_blk_timer(po, rb_queue);
 	}
-	release_sock(sk);
 
 	if (pg_vec)
 		free_pg_vec(pg_vec, order, req->tp_block_nr);
 out:
+	release_sock(sk);
 	return err;
 }
 
diff --git a/net/rds/cong.c b/net/rds/cong.c
index e6144b8..6641bcf 100644
--- a/net/rds/cong.c
+++ b/net/rds/cong.c
@@ -299,7 +299,7 @@
 	i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS;
 	off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS;
 
-	__set_bit_le(off, (void *)map->m_page_addrs[i]);
+	set_bit_le(off, (void *)map->m_page_addrs[i]);
 }
 
 void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port)
@@ -313,7 +313,7 @@
 	i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS;
 	off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS;
 
-	__clear_bit_le(off, (void *)map->m_page_addrs[i]);
+	clear_bit_le(off, (void *)map->m_page_addrs[i]);
 }
 
 static int rds_cong_test_bit(struct rds_cong_map *map, __be16 port)
diff --git a/net/rds/recv.c b/net/rds/recv.c
index a00462b..0514af3 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -545,5 +545,7 @@
 		minfo.fport = inc->i_hdr.h_dport;
 	}
 
+	minfo.flags = 0;
+
 	rds_info_copy(iter, &minfo, sizeof(minfo));
 }
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 9d6ddba..18e50a8 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -421,7 +421,7 @@
 
 	ret = rds_tcp_recv_init();
 	if (ret)
-		goto out_slab;
+		goto out_pernet;
 
 	ret = rds_trans_register(&rds_tcp_transport);
 	if (ret)
@@ -433,8 +433,9 @@
 
 out_recv:
 	rds_tcp_recv_exit();
-out_slab:
+out_pernet:
 	unregister_pernet_subsys(&rds_tcp_net_ops);
+out_slab:
 	kmem_cache_destroy(rds_tcp_conn_slab);
 out:
 	return ret;
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index d778d99..71e1f0d 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -802,8 +802,7 @@
 }
 EXPORT_SYMBOL(rfkill_resume_polling);
 
-#ifdef CONFIG_RFKILL_PM
-static int rfkill_suspend(struct device *dev)
+static __maybe_unused int rfkill_suspend(struct device *dev)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
@@ -812,7 +811,7 @@
 	return 0;
 }
 
-static int rfkill_resume(struct device *dev)
+static __maybe_unused int rfkill_resume(struct device *dev)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 	bool cur;
@@ -828,19 +827,13 @@
 }
 
 static SIMPLE_DEV_PM_OPS(rfkill_pm_ops, rfkill_suspend, rfkill_resume);
-#define RFKILL_PM_OPS (&rfkill_pm_ops)
-#else
-#define RFKILL_PM_OPS NULL
-#endif
 
 static struct class rfkill_class = {
 	.name		= "rfkill",
 	.dev_release	= rfkill_release,
 	.dev_groups	= rfkill_dev_groups,
 	.dev_uevent	= rfkill_dev_uevent,
-#ifdef CONFIG_RFKILL_PM
-	.pm		= RFKILL_PM_OPS,
-#endif
+	.pm		= IS_ENABLED(CONFIG_RFKILL_PM) ? &rfkill_pm_ops : NULL,
 };
 
 bool rfkill_blocked(struct rfkill *rfkill)
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
index da3cc09..91d43ab 100644
--- a/net/rxrpc/ar-key.c
+++ b/net/rxrpc/ar-key.c
@@ -215,7 +215,7 @@
 				       unsigned int *_toklen)
 {
 	const __be32 *xdr = *_xdr;
-	unsigned int toklen = *_toklen, n_parts, loop, tmp;
+	unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen;
 
 	/* there must be at least one name, and at least #names+1 length
 	 * words */
@@ -245,16 +245,16 @@
 		toklen -= 4;
 		if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX)
 			return -EINVAL;
-		if (tmp > toklen)
+		paddedlen = (tmp + 3) & ~3;
+		if (paddedlen > toklen)
 			return -EINVAL;
 		princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL);
 		if (!princ->name_parts[loop])
 			return -ENOMEM;
 		memcpy(princ->name_parts[loop], xdr, tmp);
 		princ->name_parts[loop][tmp] = 0;
-		tmp = (tmp + 3) & ~3;
-		toklen -= tmp;
-		xdr += tmp >> 2;
+		toklen -= paddedlen;
+		xdr += paddedlen >> 2;
 	}
 
 	if (toklen < 4)
@@ -263,16 +263,16 @@
 	toklen -= 4;
 	if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX)
 		return -EINVAL;
-	if (tmp > toklen)
+	paddedlen = (tmp + 3) & ~3;
+	if (paddedlen > toklen)
 		return -EINVAL;
 	princ->realm = kmalloc(tmp + 1, GFP_KERNEL);
 	if (!princ->realm)
 		return -ENOMEM;
 	memcpy(princ->realm, xdr, tmp);
 	princ->realm[tmp] = 0;
-	tmp = (tmp + 3) & ~3;
-	toklen -= tmp;
-	xdr += tmp >> 2;
+	toklen -= paddedlen;
+	xdr += paddedlen >> 2;
 
 	_debug("%s/...@%s", princ->name_parts[0], princ->realm);
 
@@ -291,7 +291,7 @@
 					 unsigned int *_toklen)
 {
 	const __be32 *xdr = *_xdr;
-	unsigned int toklen = *_toklen, len;
+	unsigned int toklen = *_toklen, len, paddedlen;
 
 	/* there must be at least one tag and one length word */
 	if (toklen <= 8)
@@ -305,15 +305,17 @@
 	toklen -= 8;
 	if (len > max_data_size)
 		return -EINVAL;
+	paddedlen = (len + 3) & ~3;
+	if (paddedlen > toklen)
+		return -EINVAL;
 	td->data_len = len;
 
 	if (len > 0) {
 		td->data = kmemdup(xdr, len, GFP_KERNEL);
 		if (!td->data)
 			return -ENOMEM;
-		len = (len + 3) & ~3;
-		toklen -= len;
-		xdr += len >> 2;
+		toklen -= paddedlen;
+		xdr += paddedlen >> 2;
 	}
 
 	_debug("tag %x len %x", td->tag, td->data_len);
@@ -385,7 +387,7 @@
 				    const __be32 **_xdr, unsigned int *_toklen)
 {
 	const __be32 *xdr = *_xdr;
-	unsigned int toklen = *_toklen, len;
+	unsigned int toklen = *_toklen, len, paddedlen;
 
 	/* there must be at least one length word */
 	if (toklen <= 4)
@@ -397,6 +399,9 @@
 	toklen -= 4;
 	if (len > AFSTOKEN_K5_TIX_MAX)
 		return -EINVAL;
+	paddedlen = (len + 3) & ~3;
+	if (paddedlen > toklen)
+		return -EINVAL;
 	*_tktlen = len;
 
 	_debug("ticket len %u", len);
@@ -405,9 +410,8 @@
 		*_ticket = kmemdup(xdr, len, GFP_KERNEL);
 		if (!*_ticket)
 			return -ENOMEM;
-		len = (len + 3) & ~3;
-		toklen -= len;
-		xdr += len >> 2;
+		toklen -= paddedlen;
+		xdr += paddedlen >> 2;
 	}
 
 	*_xdr = xdr;
@@ -550,7 +554,7 @@
 {
 	const __be32 *xdr = prep->data, *token;
 	const char *cp;
-	unsigned int len, tmp, loop, ntoken, toklen, sec_ix;
+	unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
 	size_t datalen = prep->datalen;
 	int ret;
 
@@ -576,22 +580,21 @@
 	if (len < 1 || len > AFSTOKEN_CELL_MAX)
 		goto not_xdr;
 	datalen -= 4;
-	tmp = (len + 3) & ~3;
-	if (tmp > datalen)
+	paddedlen = (len + 3) & ~3;
+	if (paddedlen > datalen)
 		goto not_xdr;
 
 	cp = (const char *) xdr;
 	for (loop = 0; loop < len; loop++)
 		if (!isprint(cp[loop]))
 			goto not_xdr;
-	if (len < tmp)
-		for (; loop < tmp; loop++)
-			if (cp[loop])
-				goto not_xdr;
+	for (; loop < paddedlen; loop++)
+		if (cp[loop])
+			goto not_xdr;
 	_debug("cellname: [%u/%u] '%*.*s'",
-	       len, tmp, len, len, (const char *) xdr);
-	datalen -= tmp;
-	xdr += tmp >> 2;
+	       len, paddedlen, len, len, (const char *) xdr);
+	datalen -= paddedlen;
+	xdr += paddedlen >> 2;
 
 	/* get the token count */
 	if (datalen < 12)
@@ -612,10 +615,11 @@
 		sec_ix = ntohl(*xdr);
 		datalen -= 4;
 		_debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
-		if (toklen < 20 || toklen > datalen)
+		paddedlen = (toklen + 3) & ~3;
+		if (toklen < 20 || toklen > datalen || paddedlen > datalen)
 			goto not_xdr;
-		datalen -= (toklen + 3) & ~3;
-		xdr += (toklen + 3) >> 2;
+		datalen -= paddedlen;
+		xdr += paddedlen >> 2;
 
 	} while (--loop > 0);
 
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 06e7c4a..694a06f 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -820,10 +820,8 @@
 		goto out_module_put;
 
 	err = a.ops->walk(skb, &dcb, RTM_DELACTION, &a);
-	if (err < 0)
+	if (err <= 0)
 		goto out_module_put;
-	if (err == 0)
-		goto noflush_out;
 
 	nla_nest_end(skb, nest);
 
@@ -840,7 +838,6 @@
 out_module_put:
 	module_put(a.ops->owner);
 err_out:
-noflush_out:
 	kfree_skb(skb);
 	return err;
 }
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index bb41699..7ecb14f 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -109,6 +109,9 @@
 	if (ret < 0)
 		return ret;
 
+	if (!tb[TCA_CONNMARK_PARMS])
+		return -EINVAL;
+
 	parm = nla_data(tb[TCA_CONNMARK_PARMS]);
 
 	if (!tcf_hash_check(parm->index, a, bind)) {
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index b07c535..eeb3eb3 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -105,9 +105,7 @@
 	int hl = ihl + jhl;
 
 	if (!pskb_may_pull(skb, ipl + ntkoff) || (ipl < hl) ||
-	    (skb_cloned(skb) &&
-	     !skb_clone_writable(skb, hl + ntkoff) &&
-	     pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+	    skb_try_make_writable(skb, hl + ntkoff))
 		return NULL;
 	else
 		return (void *)(skb_network_header(skb) + ihl);
@@ -365,9 +363,7 @@
 	}
 
 	if (update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) {
-		if (skb_cloned(skb) &&
-		    !skb_clone_writable(skb, sizeof(*iph) + ntkoff) &&
-		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		if (skb_try_make_writable(skb, sizeof(*iph) + ntkoff))
 			goto fail;
 
 		ip_send_check(ip_hdr(skb));
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 32fcdec..1090a52c 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -36,14 +36,15 @@
 static void tcf_mirred_release(struct tc_action *a, int bind)
 {
 	struct tcf_mirred *m = to_mirred(a);
-	struct net_device *dev = rcu_dereference_protected(m->tcfm_dev, 1);
+	struct net_device *dev;
 
 	/* We could be called either in a RCU callback or with RTNL lock held. */
 	spin_lock_bh(&mirred_list_lock);
 	list_del(&m->tcfm_list);
-	spin_unlock_bh(&mirred_list_lock);
+	dev = rcu_dereference_protected(m->tcfm_dev, 1);
 	if (dev)
 		dev_put(dev);
+	spin_unlock_bh(&mirred_list_lock);
 }
 
 static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
@@ -170,7 +171,7 @@
 
 	if (!(at & AT_EGRESS)) {
 		if (m->tcfm_ok_push)
-			skb_push(skb2, skb->mac_len);
+			skb_push_rcsum(skb2, skb->mac_len);
 	}
 
 	/* mirror is always swallowed */
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index b7c4ead..27607b8 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -126,9 +126,7 @@
 		addr = iph->daddr;
 
 	if (!((old_addr ^ addr) & mask)) {
-		if (skb_cloned(skb) &&
-		    !skb_clone_writable(skb, sizeof(*iph) + noff) &&
-		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		if (skb_try_make_writable(skb, sizeof(*iph) + noff))
 			goto drop;
 
 		new_addr &= mask;
@@ -156,9 +154,7 @@
 		struct tcphdr *tcph;
 
 		if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) ||
-		    (skb_cloned(skb) &&
-		     !skb_clone_writable(skb, ihl + sizeof(*tcph) + noff) &&
-		     pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+		    skb_try_make_writable(skb, ihl + sizeof(*tcph) + noff))
 			goto drop;
 
 		tcph = (void *)(skb_network_header(skb) + ihl);
@@ -171,9 +167,7 @@
 		struct udphdr *udph;
 
 		if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) ||
-		    (skb_cloned(skb) &&
-		     !skb_clone_writable(skb, ihl + sizeof(*udph) + noff) &&
-		     pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+		    skb_try_make_writable(skb, ihl + sizeof(*udph) + noff))
 			goto drop;
 
 		udph = (void *)(skb_network_header(skb) + ihl);
@@ -213,10 +207,8 @@
 		if ((old_addr ^ addr) & mask)
 			break;
 
-		if (skb_cloned(skb) &&
-		    !skb_clone_writable(skb, ihl + sizeof(*icmph) +
-					     sizeof(*iph) + noff) &&
-		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		if (skb_try_make_writable(skb, ihl + sizeof(*icmph) +
+					  sizeof(*iph) + noff))
 			goto drop;
 
 		icmph = (void *)(skb_network_header(skb) + ihl);
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index e38a770..c3434e9 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -104,6 +104,17 @@
 	kfree(keys);
 }
 
+static bool offset_valid(struct sk_buff *skb, int offset)
+{
+	if (offset > 0 && offset > skb->len)
+		return false;
+
+	if  (offset < 0 && -offset > skb_headroom(skb))
+		return false;
+
+	return true;
+}
+
 static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
 		     struct tcf_result *res)
 {
@@ -130,6 +141,11 @@
 			if (tkey->offmask) {
 				char *d, _d;
 
+				if (!offset_valid(skb, off + tkey->at)) {
+					pr_info("tc filter pedit 'at' offset %d out of bounds\n",
+						off + tkey->at);
+					goto bad;
+				}
 				d = skb_header_pointer(skb, off + tkey->at, 1,
 						       &_d);
 				if (!d)
@@ -142,10 +158,10 @@
 					" offset must be on 32 bit boundaries\n");
 				goto bad;
 			}
-			if (offset > 0 && offset > skb->len) {
-				pr_info("tc filter pedit"
-					" offset %d can't exceed pkt length %d\n",
-				       offset, skb->len);
+
+			if (!offset_valid(skb, off + offset)) {
+				pr_info("tc filter pedit offset %d out of bounds\n",
+					offset);
 				goto bad;
 			}
 
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 796785e..d7edba4 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -33,6 +33,12 @@
 	bstats_update(&v->tcf_bstats, skb);
 	action = v->tcf_action;
 
+	/* Ensure 'data' points at mac_header prior calling vlan manipulating
+	 * functions.
+	 */
+	if (skb_at_tc_ingress(skb))
+		skb_push_rcsum(skb, skb->mac_len);
+
 	switch (v->tcfv_action) {
 	case TCA_VLAN_ACT_POP:
 		err = skb_vlan_pop(skb);
@@ -54,6 +60,9 @@
 	action = TC_ACT_SHOT;
 	v->tcf_qstats.drops++;
 unlock:
+	if (skb_at_tc_ingress(skb))
+		skb_pull_rcsum(skb, skb->mac_len);
+
 	spin_unlock(&v->tcf_lock);
 	return action;
 }
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index a75864d..20b2f86 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -137,13 +137,15 @@
 	unsigned long cl;
 	unsigned long fh;
 	int err;
-	int tp_created = 0;
+	int tp_created;
 
 	if ((n->nlmsg_type != RTM_GETTFILTER) &&
 	    !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
 		return -EPERM;
 
 replay:
+	tp_created = 0;
+
 	err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
 	if (err < 0)
 		return err;
@@ -315,7 +317,8 @@
 			if (err == 0) {
 				struct tcf_proto *next = rtnl_dereference(tp->next);
 
-				tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER);
+				tfilter_notify(net, skb, n, tp,
+					       t->tcm_handle, RTM_DELTFILTER);
 				if (tcf_destroy(tp, false))
 					RCU_INIT_POINTER(*back, next);
 			}
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 0b8c3ac..1bf1f451 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -62,9 +62,6 @@
 	struct basic_head *head = rtnl_dereference(tp->root);
 	struct basic_filter *f;
 
-	if (head == NULL)
-		return 0UL;
-
 	list_for_each_entry(f, &head->flist, link) {
 		if (f->handle == handle) {
 			l = (unsigned long) f;
@@ -109,7 +106,6 @@
 		tcf_unbind_filter(tp, &f->res);
 		call_rcu(&f->rcu, basic_delete_filter);
 	}
-	RCU_INIT_POINTER(tp->root, NULL);
 	kfree_rcu(head, rcu);
 	return true;
 }
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 5faaa54..3eef021 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -199,7 +199,6 @@
 		call_rcu(&prog->rcu, __cls_bpf_delete_prog);
 	}
 
-	RCU_INIT_POINTER(tp->root, NULL);
 	kfree_rcu(head, rcu);
 	return true;
 }
@@ -210,9 +209,6 @@
 	struct cls_bpf_prog *prog;
 	unsigned long ret = 0UL;
 
-	if (head == NULL)
-		return 0UL;
-
 	list_for_each_entry(prog, &head->plist, link) {
 		if (prog->handle == handle) {
 			ret = (unsigned long) prog;
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 4c85bd3..c104c20 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -130,11 +130,10 @@
 
 	if (!force)
 		return false;
-
-	if (head) {
-		RCU_INIT_POINTER(tp->root, NULL);
+	/* Head can still be NULL due to cls_cgroup_init(). */
+	if (head)
 		call_rcu(&head->rcu, cls_cgroup_destroy_rcu);
-	}
+
 	return true;
 }
 
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index fbfec6a..d7ba2b4 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -583,7 +583,6 @@
 		list_del_rcu(&f->list);
 		call_rcu(&f->rcu, flow_destroy_filter);
 	}
-	RCU_INIT_POINTER(tp->root, NULL);
 	kfree_rcu(head, rcu);
 	return true;
 }
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 95b0212..e5a58c8 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/rhashtable.h>
+#include <linux/workqueue.h>
 
 #include <linux/if_ether.h>
 #include <linux/in6.h>
@@ -55,7 +56,10 @@
 	bool mask_assigned;
 	struct list_head filters;
 	struct rhashtable_params ht_params;
-	struct rcu_head rcu;
+	union {
+		struct work_struct work;
+		struct rcu_head	rcu;
+	};
 };
 
 struct cls_fl_filter {
@@ -165,6 +169,24 @@
 	kfree(f);
 }
 
+static void fl_destroy_sleepable(struct work_struct *work)
+{
+	struct cls_fl_head *head = container_of(work, struct cls_fl_head,
+						work);
+	if (head->mask_assigned)
+		rhashtable_destroy(&head->ht);
+	kfree(head);
+	module_put(THIS_MODULE);
+}
+
+static void fl_destroy_rcu(struct rcu_head *rcu)
+{
+	struct cls_fl_head *head = container_of(rcu, struct cls_fl_head, rcu);
+
+	INIT_WORK(&head->work, fl_destroy_sleepable);
+	schedule_work(&head->work);
+}
+
 static bool fl_destroy(struct tcf_proto *tp, bool force)
 {
 	struct cls_fl_head *head = rtnl_dereference(tp->root);
@@ -177,10 +199,9 @@
 		list_del_rcu(&f->list);
 		call_rcu(&f->rcu, fl_destroy_filter);
 	}
-	RCU_INIT_POINTER(tp->root, NULL);
-	if (head->mask_assigned)
-		rhashtable_destroy(&head->ht);
-	kfree_rcu(head, rcu);
+
+	__module_get(THIS_MODULE);
+	call_rcu(&head->rcu, fl_destroy_rcu);
 	return true;
 }
 
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index f9c9fc0..9992dfa 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -152,7 +152,8 @@
 		return -1;
 	nhptr = ip_hdr(skb);
 #endif
-
+	if (unlikely(!head))
+		return -1;
 restart:
 
 #if RSVP_DST_LEN == 4
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 944c8ff..403746b 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -503,7 +503,6 @@
 	walker.fn = tcindex_destroy_element;
 	tcindex_walk(tp, &walker);
 
-	RCU_INIT_POINTER(tp->root, NULL);
 	call_rcu(&p->rcu, __tcindex_destroy);
 	return true;
 }
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index af1acf0..95b560f 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -744,14 +744,15 @@
 	return 0;
 }
 
-void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
+void qdisc_tree_reduce_backlog(struct Qdisc *sch, unsigned int n,
+			       unsigned int len)
 {
 	const struct Qdisc_class_ops *cops;
 	unsigned long cl;
 	u32 parentid;
 	int drops;
 
-	if (n == 0)
+	if (n == 0 && len == 0)
 		return;
 	drops = max_t(int, n, 0);
 	rcu_read_lock();
@@ -774,11 +775,12 @@
 			cops->put(sch, cl);
 		}
 		sch->q.qlen -= n;
+		sch->qstats.backlog -= len;
 		__qdisc_qstats_drop(sch, drops);
 	}
 	rcu_read_unlock();
 }
-EXPORT_SYMBOL(qdisc_tree_decrease_qlen);
+EXPORT_SYMBOL(qdisc_tree_reduce_backlog);
 
 static void notify_and_destroy(struct net *net, struct sk_buff *skb,
 			       struct nlmsghdr *n, u32 clid,
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index c538d9e..baafddf 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1624,13 +1624,8 @@
 			new->reshape_fail = cbq_reshape_fail;
 #endif
 	}
-	sch_tree_lock(sch);
-	*old = cl->q;
-	cl->q = new;
-	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-	qdisc_reset(*old);
-	sch_tree_unlock(sch);
 
+	*old = qdisc_replace(sch, new, &cl->q);
 	return 0;
 }
 
@@ -1914,7 +1909,7 @@
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
 	struct cbq_class *cl = (struct cbq_class *)arg;
-	unsigned int qlen;
+	unsigned int qlen, backlog;
 
 	if (cl->filters || cl->children || cl == &q->link)
 		return -EBUSY;
@@ -1922,8 +1917,9 @@
 	sch_tree_lock(sch);
 
 	qlen = cl->q->q.qlen;
+	backlog = cl->q->qstats.backlog;
 	qdisc_reset(cl->q);
-	qdisc_tree_decrease_qlen(cl->q, qlen);
+	qdisc_tree_reduce_backlog(cl->q, qlen, backlog);
 
 	if (cl->next_alive)
 		cbq_deactivate_class(cl);
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 5ffb8b8..0a08c86 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -128,8 +128,8 @@
 		choke_zap_tail_holes(q);
 
 	qdisc_qstats_backlog_dec(sch, skb);
+	qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb));
 	qdisc_drop(skb, sch);
-	qdisc_tree_decrease_qlen(sch, 1);
 	--sch->q.qlen;
 }
 
@@ -456,6 +456,7 @@
 		old = q->tab;
 		if (old) {
 			unsigned int oqlen = sch->q.qlen, tail = 0;
+			unsigned dropped = 0;
 
 			while (q->head != q->tail) {
 				struct sk_buff *skb = q->tab[q->head];
@@ -467,11 +468,12 @@
 					ntab[tail++] = skb;
 					continue;
 				}
+				dropped += qdisc_pkt_len(skb);
 				qdisc_qstats_backlog_dec(sch, skb);
 				--sch->q.qlen;
 				qdisc_drop(skb, sch);
 			}
-			qdisc_tree_decrease_qlen(sch, oqlen - sch->q.qlen);
+			qdisc_tree_reduce_backlog(sch, oqlen - sch->q.qlen, dropped);
 			q->head = 0;
 			q->tail = tail;
 		}
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
index 535007d..9b7e298 100644
--- a/net/sched/sch_codel.c
+++ b/net/sched/sch_codel.c
@@ -79,12 +79,13 @@
 
 	skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats, dequeue);
 
-	/* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
+	/* We cant call qdisc_tree_reduce_backlog() if our qlen is 0,
 	 * or HTB crashes. Defer it for next round.
 	 */
 	if (q->stats.drop_count && sch->q.qlen) {
-		qdisc_tree_decrease_qlen(sch, q->stats.drop_count);
+		qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len);
 		q->stats.drop_count = 0;
+		q->stats.drop_len = 0;
 	}
 	if (skb)
 		qdisc_bstats_update(sch, skb);
@@ -116,7 +117,7 @@
 {
 	struct codel_sched_data *q = qdisc_priv(sch);
 	struct nlattr *tb[TCA_CODEL_MAX + 1];
-	unsigned int qlen;
+	unsigned int qlen, dropped = 0;
 	int err;
 
 	if (!opt)
@@ -156,10 +157,11 @@
 	while (sch->q.qlen > sch->limit) {
 		struct sk_buff *skb = __skb_dequeue(&sch->q);
 
+		dropped += qdisc_pkt_len(skb);
 		qdisc_qstats_backlog_dec(sch, skb);
 		qdisc_drop(skb, sch);
 	}
-	qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
+	qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
 
 	sch_tree_unlock(sch);
 	return 0;
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index f26bdea..d6e3ad4 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -53,9 +53,10 @@
 static void drr_purge_queue(struct drr_class *cl)
 {
 	unsigned int len = cl->qdisc->q.qlen;
+	unsigned int backlog = cl->qdisc->qstats.backlog;
 
 	qdisc_reset(cl->qdisc);
-	qdisc_tree_decrease_qlen(cl->qdisc, len);
+	qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
 }
 
 static const struct nla_policy drr_policy[TCA_DRR_MAX + 1] = {
@@ -226,11 +227,7 @@
 			new = &noop_qdisc;
 	}
 
-	sch_tree_lock(sch);
-	drr_purge_queue(cl);
-	*old = cl->qdisc;
-	cl->qdisc = new;
-	sch_tree_unlock(sch);
+	*old = qdisc_replace(sch, new, &cl->qdisc);
 	return 0;
 }
 
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index f357f34..d0dff0c 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -73,13 +73,7 @@
 			new = &noop_qdisc;
 	}
 
-	sch_tree_lock(sch);
-	*old = p->q;
-	p->q = new;
-	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-	qdisc_reset(*old);
-	sch_tree_unlock(sch);
-
+	*old = qdisc_replace(sch, new, &p->q);
 	return 0;
 }
 
@@ -264,6 +258,7 @@
 		return err;
 	}
 
+	qdisc_qstats_backlog_inc(sch, skb);
 	sch->q.qlen++;
 
 	return NET_XMIT_SUCCESS;
@@ -286,6 +281,7 @@
 		return NULL;
 
 	qdisc_bstats_update(sch, skb);
+	qdisc_qstats_backlog_dec(sch, skb);
 	sch->q.qlen--;
 
 	index = skb->tc_index & (p->indices - 1);
@@ -401,6 +397,7 @@
 
 	pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
 	qdisc_reset(p->q);
+	sch->qstats.backlog = 0;
 	sch->q.qlen = 0;
 }
 
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index 2177eac..2e4bd2c 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -37,14 +37,18 @@
 
 static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
+	unsigned int prev_backlog;
+
 	if (likely(skb_queue_len(&sch->q) < sch->limit))
 		return qdisc_enqueue_tail(skb, sch);
 
+	prev_backlog = sch->qstats.backlog;
 	/* queue full, remove one skb to fulfill the limit */
 	__qdisc_queue_drop_head(sch, &sch->q);
 	qdisc_qstats_drop(sch);
 	qdisc_enqueue_tail(skb, sch);
 
+	qdisc_tree_reduce_backlog(sch, 0, prev_backlog - sch->qstats.backlog);
 	return NET_XMIT_CN;
 }
 
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 109b232..3c6a47d 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -662,6 +662,7 @@
 	struct fq_sched_data *q = qdisc_priv(sch);
 	struct nlattr *tb[TCA_FQ_MAX + 1];
 	int err, drop_count = 0;
+	unsigned drop_len = 0;
 	u32 fq_log;
 
 	if (!opt)
@@ -736,10 +737,11 @@
 
 		if (!skb)
 			break;
+		drop_len += qdisc_pkt_len(skb);
 		kfree_skb(skb);
 		drop_count++;
 	}
-	qdisc_tree_decrease_qlen(sch, drop_count);
+	qdisc_tree_reduce_backlog(sch, drop_count, drop_len);
 
 	sch_tree_unlock(sch);
 	return err;
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index 4c834e9..d3fc8f9 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -175,7 +175,7 @@
 static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct fq_codel_sched_data *q = qdisc_priv(sch);
-	unsigned int idx;
+	unsigned int idx, prev_backlog;
 	struct fq_codel_flow *flow;
 	int uninitialized_var(ret);
 
@@ -203,6 +203,7 @@
 	if (++sch->q.qlen <= sch->limit)
 		return NET_XMIT_SUCCESS;
 
+	prev_backlog = sch->qstats.backlog;
 	q->drop_overlimit++;
 	/* Return Congestion Notification only if we dropped a packet
 	 * from this flow.
@@ -211,7 +212,7 @@
 		return NET_XMIT_CN;
 
 	/* As we dropped a packet, better let upper stack know this */
-	qdisc_tree_decrease_qlen(sch, 1);
+	qdisc_tree_reduce_backlog(sch, 1, prev_backlog - sch->qstats.backlog);
 	return NET_XMIT_SUCCESS;
 }
 
@@ -241,6 +242,7 @@
 	struct fq_codel_flow *flow;
 	struct list_head *head;
 	u32 prev_drop_count, prev_ecn_mark;
+	unsigned int prev_backlog;
 
 begin:
 	head = &q->new_flows;
@@ -259,6 +261,7 @@
 
 	prev_drop_count = q->cstats.drop_count;
 	prev_ecn_mark = q->cstats.ecn_mark;
+	prev_backlog = sch->qstats.backlog;
 
 	skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats,
 			    dequeue);
@@ -276,12 +279,14 @@
 	}
 	qdisc_bstats_update(sch, skb);
 	flow->deficit -= qdisc_pkt_len(skb);
-	/* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
+	/* We cant call qdisc_tree_reduce_backlog() if our qlen is 0,
 	 * or HTB crashes. Defer it for next round.
 	 */
 	if (q->cstats.drop_count && sch->q.qlen) {
-		qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
+		qdisc_tree_reduce_backlog(sch, q->cstats.drop_count,
+					  q->cstats.drop_len);
 		q->cstats.drop_count = 0;
+		q->cstats.drop_len = 0;
 	}
 	return skb;
 }
@@ -372,11 +377,13 @@
 	while (sch->q.qlen > sch->limit) {
 		struct sk_buff *skb = fq_codel_dequeue(sch);
 
+		q->cstats.drop_len += qdisc_pkt_len(skb);
 		kfree_skb(skb);
 		q->cstats.drop_count++;
 	}
-	qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
+	qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, q->cstats.drop_len);
 	q->cstats.drop_count = 0;
+	q->cstats.drop_len = 0;
 
 	sch_tree_unlock(sch);
 	return 0;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 16bc83b..aa47250 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -159,12 +159,15 @@
 	if (validate)
 		skb = validate_xmit_skb_list(skb, dev);
 
-	if (skb) {
+	if (likely(skb)) {
 		HARD_TX_LOCK(dev, txq, smp_processor_id());
 		if (!netif_xmit_frozen_or_stopped(txq))
 			skb = dev_hard_start_xmit(skb, dev, txq, &ret);
 
 		HARD_TX_UNLOCK(dev, txq);
+	} else {
+		spin_lock(root_lock);
+		return qdisc_qlen(q);
 	}
 	spin_lock(root_lock);
 
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index b7ebe2c..d783d7c 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -895,9 +895,10 @@
 hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
 {
 	unsigned int len = cl->qdisc->q.qlen;
+	unsigned int backlog = cl->qdisc->qstats.backlog;
 
 	qdisc_reset(cl->qdisc);
-	qdisc_tree_decrease_qlen(cl->qdisc, len);
+	qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
 }
 
 static void
@@ -1215,11 +1216,7 @@
 			new = &noop_qdisc;
 	}
 
-	sch_tree_lock(sch);
-	hfsc_purge_queue(sch, cl);
-	*old = cl->qdisc;
-	cl->qdisc = new;
-	sch_tree_unlock(sch);
+	*old = qdisc_replace(sch, new, &cl->qdisc);
 	return 0;
 }
 
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index 86b04e3..13d6f83 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -382,6 +382,7 @@
 	struct hhf_sched_data *q = qdisc_priv(sch);
 	enum wdrr_bucket_idx idx;
 	struct wdrr_bucket *bucket;
+	unsigned int prev_backlog;
 
 	idx = hhf_classify(skb, sch);
 
@@ -409,6 +410,7 @@
 	if (++sch->q.qlen <= sch->limit)
 		return NET_XMIT_SUCCESS;
 
+	prev_backlog = sch->qstats.backlog;
 	q->drop_overlimit++;
 	/* Return Congestion Notification only if we dropped a packet from this
 	 * bucket.
@@ -417,7 +419,7 @@
 		return NET_XMIT_CN;
 
 	/* As we dropped a packet, better let upper stack know this. */
-	qdisc_tree_decrease_qlen(sch, 1);
+	qdisc_tree_reduce_backlog(sch, 1, prev_backlog - sch->qstats.backlog);
 	return NET_XMIT_SUCCESS;
 }
 
@@ -527,7 +529,7 @@
 {
 	struct hhf_sched_data *q = qdisc_priv(sch);
 	struct nlattr *tb[TCA_HHF_MAX + 1];
-	unsigned int qlen;
+	unsigned int qlen, prev_backlog;
 	int err;
 	u64 non_hh_quantum;
 	u32 new_quantum = q->quantum;
@@ -577,12 +579,14 @@
 	}
 
 	qlen = sch->q.qlen;
+	prev_backlog = sch->qstats.backlog;
 	while (sch->q.qlen > sch->limit) {
 		struct sk_buff *skb = hhf_dequeue(sch);
 
 		kfree_skb(skb);
 	}
-	qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
+	qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen,
+				  prev_backlog - sch->qstats.backlog);
 
 	sch_tree_unlock(sch);
 	return 0;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 15ccd7f..87b02ed3 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -600,6 +600,7 @@
 		htb_activate(q, cl);
 	}
 
+	qdisc_qstats_backlog_inc(sch, skb);
 	sch->q.qlen++;
 	return NET_XMIT_SUCCESS;
 }
@@ -889,6 +890,7 @@
 ok:
 		qdisc_bstats_update(sch, skb);
 		qdisc_unthrottled(sch);
+		qdisc_qstats_backlog_dec(sch, skb);
 		sch->q.qlen--;
 		return skb;
 	}
@@ -955,6 +957,7 @@
 			unsigned int len;
 			if (cl->un.leaf.q->ops->drop &&
 			    (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
+				sch->qstats.backlog -= len;
 				sch->q.qlen--;
 				if (!cl->un.leaf.q->q.qlen)
 					htb_deactivate(q, cl);
@@ -984,12 +987,12 @@
 			}
 			cl->prio_activity = 0;
 			cl->cmode = HTB_CAN_SEND;
-
 		}
 	}
 	qdisc_watchdog_cancel(&q->watchdog);
 	__skb_queue_purge(&q->direct_queue);
 	sch->q.qlen = 0;
+	sch->qstats.backlog = 0;
 	memset(q->hlevel, 0, sizeof(q->hlevel));
 	memset(q->row_mask, 0, sizeof(q->row_mask));
 	for (i = 0; i < TC_HTB_NUMPRIO; i++)
@@ -1163,14 +1166,7 @@
 				     cl->common.classid)) == NULL)
 		return -ENOBUFS;
 
-	sch_tree_lock(sch);
-	*old = cl->un.leaf.q;
-	cl->un.leaf.q = new;
-	if (*old != NULL) {
-		qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-		qdisc_reset(*old);
-	}
-	sch_tree_unlock(sch);
+	*old = qdisc_replace(sch, new, &cl->un.leaf.q);
 	return 0;
 }
 
@@ -1272,7 +1268,6 @@
 {
 	struct htb_sched *q = qdisc_priv(sch);
 	struct htb_class *cl = (struct htb_class *)arg;
-	unsigned int qlen;
 	struct Qdisc *new_q = NULL;
 	int last_child = 0;
 
@@ -1292,9 +1287,11 @@
 	sch_tree_lock(sch);
 
 	if (!cl->level) {
-		qlen = cl->un.leaf.q->q.qlen;
+		unsigned int qlen = cl->un.leaf.q->q.qlen;
+		unsigned int backlog = cl->un.leaf.q->qstats.backlog;
+
 		qdisc_reset(cl->un.leaf.q);
-		qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
+		qdisc_tree_reduce_backlog(cl->un.leaf.q, qlen, backlog);
 	}
 
 	/* delete from hash and active; remainder in destroy_class */
@@ -1428,10 +1425,11 @@
 		sch_tree_lock(sch);
 		if (parent && !parent->level) {
 			unsigned int qlen = parent->un.leaf.q->q.qlen;
+			unsigned int backlog = parent->un.leaf.q->qstats.backlog;
 
 			/* turn parent into inner node */
 			qdisc_reset(parent->un.leaf.q);
-			qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
+			qdisc_tree_reduce_backlog(parent->un.leaf.q, qlen, backlog);
 			qdisc_destroy(parent->un.leaf.q);
 			if (parent->prio_activity)
 				htb_deactivate(q, parent);
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 4e904ca..bcdd54b 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -218,7 +218,8 @@
 		if (q->queues[i] != &noop_qdisc) {
 			struct Qdisc *child = q->queues[i];
 			q->queues[i] = &noop_qdisc;
-			qdisc_tree_decrease_qlen(child, child->q.qlen);
+			qdisc_tree_reduce_backlog(child, child->q.qlen,
+						  child->qstats.backlog);
 			qdisc_destroy(child);
 		}
 	}
@@ -238,8 +239,9 @@
 				q->queues[i] = child;
 
 				if (old != &noop_qdisc) {
-					qdisc_tree_decrease_qlen(old,
-								 old->q.qlen);
+					qdisc_tree_reduce_backlog(old,
+								  old->q.qlen,
+								  old->qstats.backlog);
 					qdisc_destroy(old);
 				}
 				sch_tree_unlock(sch);
@@ -303,13 +305,7 @@
 	if (new == NULL)
 		new = &noop_qdisc;
 
-	sch_tree_lock(sch);
-	*old = q->queues[band];
-	q->queues[band] = new;
-	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-	qdisc_reset(*old);
-	sch_tree_unlock(sch);
-
+	*old = qdisc_replace(sch, new, &q->queues[band]);
 	return 0;
 }
 
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 5abd1d9..b7c29d5 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -395,6 +395,25 @@
 	sch->q.qlen++;
 }
 
+/* netem can't properly corrupt a megapacket (like we get from GSO), so instead
+ * when we statistically choose to corrupt one, we instead segment it, returning
+ * the first packet to be corrupted, and re-enqueue the remaining frames
+ */
+static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct sk_buff *segs;
+	netdev_features_t features = netif_skb_features(skb);
+
+	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+
+	if (IS_ERR_OR_NULL(segs)) {
+		qdisc_reshape_fail(skb, sch);
+		return NULL;
+	}
+	consume_skb(skb);
+	return segs;
+}
+
 /*
  * Insert one skb into qdisc.
  * Note: parent depends on return value to account for queue length.
@@ -407,7 +426,11 @@
 	/* We don't fill cb now as skb_unshare() may invalidate it */
 	struct netem_skb_cb *cb;
 	struct sk_buff *skb2;
+	struct sk_buff *segs = NULL;
+	unsigned int len = 0, last_len, prev_len = qdisc_pkt_len(skb);
+	int nb = 0;
 	int count = 1;
+	int rc = NET_XMIT_SUCCESS;
 
 	/* Random duplication */
 	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
@@ -453,10 +476,23 @@
 	 * do it now in software before we mangle it.
 	 */
 	if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
+		if (skb_is_gso(skb)) {
+			segs = netem_segment(skb, sch);
+			if (!segs)
+				return NET_XMIT_DROP;
+		} else {
+			segs = skb;
+		}
+
+		skb = segs;
+		segs = segs->next;
+
 		if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
 		    (skb->ip_summed == CHECKSUM_PARTIAL &&
-		     skb_checksum_help(skb)))
-			return qdisc_drop(skb, sch);
+		     skb_checksum_help(skb))) {
+			rc = qdisc_drop(skb, sch);
+			goto finish_segs;
+		}
 
 		skb->data[prandom_u32() % skb_headlen(skb)] ^=
 			1<<(prandom_u32() % 8);
@@ -516,6 +552,27 @@
 		sch->qstats.requeues++;
 	}
 
+finish_segs:
+	if (segs) {
+		while (segs) {
+			skb2 = segs->next;
+			segs->next = NULL;
+			qdisc_skb_cb(segs)->pkt_len = segs->len;
+			last_len = segs->len;
+			rc = qdisc_enqueue(segs, sch);
+			if (rc != NET_XMIT_SUCCESS) {
+				if (net_xmit_drop_count(rc))
+					qdisc_qstats_drop(sch);
+			} else {
+				nb++;
+				len += last_len;
+			}
+			segs = skb2;
+		}
+		sch->q.qlen += nb;
+		if (nb > 1)
+			qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len);
+	}
 	return NET_XMIT_SUCCESS;
 }
 
@@ -593,13 +650,14 @@
 #endif
 
 			if (q->qdisc) {
+				unsigned int pkt_len = qdisc_pkt_len(skb);
 				int err = qdisc_enqueue(skb, q->qdisc);
 
-				if (unlikely(err != NET_XMIT_SUCCESS)) {
-					if (net_xmit_drop_count(err)) {
-						qdisc_qstats_drop(sch);
-						qdisc_tree_decrease_qlen(sch, 1);
-					}
+				if (err != NET_XMIT_SUCCESS &&
+				    net_xmit_drop_count(err)) {
+					qdisc_qstats_drop(sch);
+					qdisc_tree_reduce_backlog(sch, 1,
+								  pkt_len);
 				}
 				goto tfifo_dequeue;
 			}
@@ -1037,15 +1095,7 @@
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 
-	sch_tree_lock(sch);
-	*old = q->qdisc;
-	q->qdisc = new;
-	if (*old) {
-		qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-		qdisc_reset(*old);
-	}
-	sch_tree_unlock(sch);
-
+	*old = qdisc_replace(sch, new, &q->qdisc);
 	return 0;
 }
 
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c
index b783a44..71ae3b9 100644
--- a/net/sched/sch_pie.c
+++ b/net/sched/sch_pie.c
@@ -183,7 +183,7 @@
 {
 	struct pie_sched_data *q = qdisc_priv(sch);
 	struct nlattr *tb[TCA_PIE_MAX + 1];
-	unsigned int qlen;
+	unsigned int qlen, dropped = 0;
 	int err;
 
 	if (!opt)
@@ -232,10 +232,11 @@
 	while (sch->q.qlen > sch->limit) {
 		struct sk_buff *skb = __skb_dequeue(&sch->q);
 
+		dropped += qdisc_pkt_len(skb);
 		qdisc_qstats_backlog_dec(sch, skb);
 		qdisc_drop(skb, sch);
 	}
-	qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
+	qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
 
 	sch_tree_unlock(sch);
 	return 0;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index ba6487f..fee1b15 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -191,7 +191,7 @@
 		struct Qdisc *child = q->queues[i];
 		q->queues[i] = &noop_qdisc;
 		if (child != &noop_qdisc) {
-			qdisc_tree_decrease_qlen(child, child->q.qlen);
+			qdisc_tree_reduce_backlog(child, child->q.qlen, child->qstats.backlog);
 			qdisc_destroy(child);
 		}
 	}
@@ -210,8 +210,9 @@
 				q->queues[i] = child;
 
 				if (old != &noop_qdisc) {
-					qdisc_tree_decrease_qlen(old,
-								 old->q.qlen);
+					qdisc_tree_reduce_backlog(old,
+								  old->q.qlen,
+								  old->qstats.backlog);
 					qdisc_destroy(old);
 				}
 				sch_tree_unlock(sch);
@@ -268,13 +269,7 @@
 	if (new == NULL)
 		new = &noop_qdisc;
 
-	sch_tree_lock(sch);
-	*old = q->queues[band];
-	q->queues[band] = new;
-	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-	qdisc_reset(*old);
-	sch_tree_unlock(sch);
-
+	*old = qdisc_replace(sch, new, &q->queues[band]);
 	return 0;
 }
 
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 3dc3a6e..8d2d8d9 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -220,9 +220,10 @@
 static void qfq_purge_queue(struct qfq_class *cl)
 {
 	unsigned int len = cl->qdisc->q.qlen;
+	unsigned int backlog = cl->qdisc->qstats.backlog;
 
 	qdisc_reset(cl->qdisc);
-	qdisc_tree_decrease_qlen(cl->qdisc, len);
+	qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
 }
 
 static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = {
@@ -617,11 +618,7 @@
 			new = &noop_qdisc;
 	}
 
-	sch_tree_lock(sch);
-	qfq_purge_queue(cl);
-	*old = cl->qdisc;
-	cl->qdisc = new;
-	sch_tree_unlock(sch);
+	*old = qdisc_replace(sch, new, &cl->qdisc);
 	return 0;
 }
 
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 6c0534c..8c0508c 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -210,7 +210,8 @@
 	q->flags = ctl->flags;
 	q->limit = ctl->limit;
 	if (child) {
-		qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
+		qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
+					  q->qdisc->qstats.backlog);
 		qdisc_destroy(q->qdisc);
 		q->qdisc = child;
 	}
@@ -313,12 +314,7 @@
 	if (new == NULL)
 		new = &noop_qdisc;
 
-	sch_tree_lock(sch);
-	*old = q->qdisc;
-	q->qdisc = new;
-	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-	qdisc_reset(*old);
-	sch_tree_unlock(sch);
+	*old = qdisc_replace(sch, new, &q->qdisc);
 	return 0;
 }
 
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index 5bbb633..c696116 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -510,7 +510,8 @@
 
 	sch_tree_lock(sch);
 
-	qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
+	qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
+				  q->qdisc->qstats.backlog);
 	qdisc_destroy(q->qdisc);
 	q->qdisc = child;
 
@@ -606,12 +607,7 @@
 	if (new == NULL)
 		new = &noop_qdisc;
 
-	sch_tree_lock(sch);
-	*old = q->qdisc;
-	q->qdisc = new;
-	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-	qdisc_reset(*old);
-	sch_tree_unlock(sch);
+	*old = qdisc_replace(sch, new, &q->qdisc);
 	return 0;
 }
 
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 3abab53..498f0a2 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -346,7 +346,7 @@
 sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct sfq_sched_data *q = qdisc_priv(sch);
-	unsigned int hash;
+	unsigned int hash, dropped;
 	sfq_index x, qlen;
 	struct sfq_slot *slot;
 	int uninitialized_var(ret);
@@ -461,7 +461,7 @@
 		return NET_XMIT_SUCCESS;
 
 	qlen = slot->qlen;
-	sfq_drop(sch);
+	dropped = sfq_drop(sch);
 	/* Return Congestion Notification only if we dropped a packet
 	 * from this flow.
 	 */
@@ -469,7 +469,7 @@
 		return NET_XMIT_CN;
 
 	/* As we dropped a packet, better let upper stack know this */
-	qdisc_tree_decrease_qlen(sch, 1);
+	qdisc_tree_reduce_backlog(sch, 1, dropped);
 	return NET_XMIT_SUCCESS;
 }
 
@@ -537,6 +537,7 @@
 	struct sfq_slot *slot;
 	struct sk_buff_head list;
 	int dropped = 0;
+	unsigned int drop_len = 0;
 
 	__skb_queue_head_init(&list);
 
@@ -565,6 +566,7 @@
 			if (x >= SFQ_MAX_FLOWS) {
 drop:
 				qdisc_qstats_backlog_dec(sch, skb);
+				drop_len += qdisc_pkt_len(skb);
 				kfree_skb(skb);
 				dropped++;
 				continue;
@@ -594,7 +596,7 @@
 		}
 	}
 	sch->q.qlen -= dropped;
-	qdisc_tree_decrease_qlen(sch, dropped);
+	qdisc_tree_reduce_backlog(sch, dropped, drop_len);
 }
 
 static void sfq_perturbation(unsigned long arg)
@@ -618,7 +620,7 @@
 	struct sfq_sched_data *q = qdisc_priv(sch);
 	struct tc_sfq_qopt *ctl = nla_data(opt);
 	struct tc_sfq_qopt_v1 *ctl_v1 = NULL;
-	unsigned int qlen;
+	unsigned int qlen, dropped = 0;
 	struct red_parms *p = NULL;
 
 	if (opt->nla_len < nla_attr_size(sizeof(*ctl)))
@@ -667,8 +669,8 @@
 
 	qlen = sch->q.qlen;
 	while (sch->q.qlen > q->limit)
-		sfq_drop(sch);
-	qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
+		dropped += sfq_drop(sch);
+	qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
 
 	del_timer(&q->perturb_timer);
 	if (q->perturb_period) {
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index a4afde1..c2fbde7 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -160,6 +160,7 @@
 	struct tbf_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *segs, *nskb;
 	netdev_features_t features = netif_skb_features(skb);
+	unsigned int len = 0, prev_len = qdisc_pkt_len(skb);
 	int ret, nb;
 
 	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
@@ -172,6 +173,7 @@
 		nskb = segs->next;
 		segs->next = NULL;
 		qdisc_skb_cb(segs)->pkt_len = segs->len;
+		len += segs->len;
 		ret = qdisc_enqueue(segs, q->qdisc);
 		if (ret != NET_XMIT_SUCCESS) {
 			if (net_xmit_drop_count(ret))
@@ -183,7 +185,7 @@
 	}
 	sch->q.qlen += nb;
 	if (nb > 1)
-		qdisc_tree_decrease_qlen(sch, 1 - nb);
+		qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len);
 	consume_skb(skb);
 	return nb > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
 }
@@ -399,7 +401,8 @@
 
 	sch_tree_lock(sch);
 	if (child) {
-		qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
+		qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
+					  q->qdisc->qstats.backlog);
 		qdisc_destroy(q->qdisc);
 		q->qdisc = child;
 	}
@@ -502,13 +505,7 @@
 	if (new == NULL)
 		new = &noop_qdisc;
 
-	sch_tree_lock(sch);
-	*old = q->qdisc;
-	q->qdisc = new;
-	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
-	qdisc_reset(*old);
-	sch_tree_unlock(sch);
-
+	*old = qdisc_replace(sch, new, &q->qdisc);
 	return 0;
 }
 
diff --git a/net/sctp/input.c b/net/sctp/input.c
index b6493b3..2d7859c 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -472,15 +472,14 @@
 			     struct sctp_association **app,
 			     struct sctp_transport **tpp)
 {
+	struct sctp_init_chunk *chunkhdr, _chunkhdr;
 	union sctp_addr saddr;
 	union sctp_addr daddr;
 	struct sctp_af *af;
 	struct sock *sk = NULL;
 	struct sctp_association *asoc;
 	struct sctp_transport *transport = NULL;
-	struct sctp_init_chunk *chunkhdr;
 	__u32 vtag = ntohl(sctphdr->vtag);
-	int len = skb->len - ((void *)sctphdr - (void *)skb->data);
 
 	*app = NULL; *tpp = NULL;
 
@@ -515,13 +514,16 @@
 	 * discard the packet.
 	 */
 	if (vtag == 0) {
-		chunkhdr = (void *)sctphdr + sizeof(struct sctphdr);
-		if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t)
-			  + sizeof(__be32) ||
+		/* chunk header + first 4 octects of init header */
+		chunkhdr = skb_header_pointer(skb, skb_transport_offset(skb) +
+					      sizeof(struct sctphdr),
+					      sizeof(struct sctp_chunkhdr) +
+					      sizeof(__be32), &_chunkhdr);
+		if (!chunkhdr ||
 		    chunkhdr->chunk_hdr.type != SCTP_CID_INIT ||
-		    ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) {
+		    ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag)
 			goto out;
-		}
+
 	} else if (vtag != asoc->c.peer_vtag) {
 		goto out;
 	}
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ce46f1c..7527c16 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -239,12 +239,10 @@
 	struct sctp_bind_addr *bp;
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sctp_sockaddr_entry *laddr;
-	union sctp_addr *baddr = NULL;
 	union sctp_addr *daddr = &t->ipaddr;
 	union sctp_addr dst_saddr;
 	struct in6_addr *final_p, final;
 	__u8 matchlen = 0;
-	__u8 bmatchlen;
 	sctp_scope_t scope;
 
 	memset(fl6, 0, sizeof(struct flowi6));
@@ -311,23 +309,37 @@
 	 */
 	rcu_read_lock();
 	list_for_each_entry_rcu(laddr, &bp->address_list, list) {
-		if (!laddr->valid)
+		struct dst_entry *bdst;
+		__u8 bmatchlen;
+
+		if (!laddr->valid ||
+		    laddr->state != SCTP_ADDR_SRC ||
+		    laddr->a.sa.sa_family != AF_INET6 ||
+		    scope > sctp_scope(&laddr->a))
 			continue;
-		if ((laddr->state == SCTP_ADDR_SRC) &&
-		    (laddr->a.sa.sa_family == AF_INET6) &&
-		    (scope <= sctp_scope(&laddr->a))) {
-			bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
-			if (!baddr || (matchlen < bmatchlen)) {
-				baddr = &laddr->a;
-				matchlen = bmatchlen;
-			}
-		}
-	}
-	if (baddr) {
-		fl6->saddr = baddr->v6.sin6_addr;
-		fl6->fl6_sport = baddr->v6.sin6_port;
+
+		fl6->saddr = laddr->a.v6.sin6_addr;
+		fl6->fl6_sport = laddr->a.v6.sin6_port;
 		final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
-		dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+		bdst = ip6_dst_lookup_flow(sk, fl6, final_p);
+
+		if (!IS_ERR(bdst) &&
+		    ipv6_chk_addr(dev_net(bdst->dev),
+				  &laddr->a.v6.sin6_addr, bdst->dev, 1)) {
+			if (!IS_ERR_OR_NULL(dst))
+				dst_release(dst);
+			dst = bdst;
+			break;
+		}
+
+		bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
+		if (matchlen > bmatchlen)
+			continue;
+
+		if (!IS_ERR_OR_NULL(dst))
+			dst_release(dst);
+		dst = bdst;
+		matchlen = bmatchlen;
 	}
 	rcu_read_unlock();
 
@@ -662,6 +674,9 @@
 	newnp = inet6_sk(newsk);
 
 	memcpy(newnp, np, sizeof(struct ipv6_pinfo));
+	newnp->ipv6_mc_list = NULL;
+	newnp->ipv6_ac_list = NULL;
+	newnp->ipv6_fl_list = NULL;
 
 	rcu_read_lock();
 	opt = rcu_dereference(np->opt);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 22c2bf3..29c7c43 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3426,6 +3426,12 @@
 			return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
 						  commands);
 
+		/* Report violation if chunk len overflows */
+		ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+		if (ch_end > skb_tail_pointer(skb))
+			return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+						  commands);
+
 		/* Now that we know we at least have a chunk header,
 		 * do things that are type appropriate.
 		 */
@@ -3457,12 +3463,6 @@
 			}
 		}
 
-		/* Report violation if chunk len overflows */
-		ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
-		if (ch_end > skb_tail_pointer(skb))
-			return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
-						  commands);
-
 		ch = (sctp_chunkhdr_t *) ch_end;
 	} while (ch_end < skb_tail_pointer(skb));
 
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index be1489f..3ebf3b6 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -235,8 +235,12 @@
 					      sctp_assoc_t id)
 {
 	struct sctp_association *addr_asoc = NULL, *id_asoc = NULL;
-	struct sctp_transport *transport;
+	struct sctp_af *af = sctp_get_af_specific(addr->ss_family);
 	union sctp_addr *laddr = (union sctp_addr *)addr;
+	struct sctp_transport *transport;
+
+	if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len))
+		return NULL;
 
 	addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
 					       laddr,
@@ -1212,9 +1216,12 @@
 
 	timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
 
-	err = sctp_wait_for_connect(asoc, &timeo);
-	if ((err == 0 || err == -EINPROGRESS) && assoc_id)
+	if (assoc_id)
 		*assoc_id = asoc->assoc_id;
+	err = sctp_wait_for_connect(asoc, &timeo);
+	/* Note: the asoc may be freed after the return of
+	 * sctp_wait_for_connect.
+	 */
 
 	/* Don't free association on exit. */
 	asoc = NULL;
@@ -4371,7 +4378,7 @@
 static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
 				  int __user *optlen)
 {
-	if (len <= 0)
+	if (len == 0)
 		return -EINVAL;
 	if (len > sizeof(struct sctp_event_subscribe))
 		len = sizeof(struct sctp_event_subscribe);
@@ -4419,6 +4426,12 @@
 	if (!asoc)
 		return -EINVAL;
 
+	/* If there is a thread waiting on more sndbuf space for
+	 * sending on this asoc, it cannot be peeled.
+	 */
+	if (waitqueue_active(&asoc->wait))
+		return -EBUSY;
+
 	/* An association cannot be branched off from an already peeled-off
 	 * socket, nor is this supported for tcp style sockets.
 	 */
@@ -5972,6 +5985,9 @@
 	if (get_user(len, optlen))
 		return -EFAULT;
 
+	if (len < 0)
+		return -EINVAL;
+
 	lock_sock(sk);
 
 	switch (optname) {
@@ -6382,6 +6398,9 @@
 	if (sock->state != SS_UNCONNECTED)
 		goto out;
 
+	if (!sctp_sstate(sk, LISTENING) && !sctp_sstate(sk, CLOSED))
+		goto out;
+
 	/* If backlog is zero, disable listening. */
 	if (!backlog) {
 		if (sctp_sstate(sk, CLOSED))
@@ -6954,7 +6973,6 @@
 		 */
 		release_sock(sk);
 		current_timeo = schedule_timeout(current_timeo);
-		BUG_ON(sk != asoc->base.sk);
 		lock_sock(sk);
 
 		*timeo_p = current_timeo;
diff --git a/net/socket.c b/net/socket.c
index 263b334..18aff3d 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -520,9 +520,23 @@
 	return used;
 }
 
+static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+	int err = simple_setattr(dentry, iattr);
+
+	if (!err && (iattr->ia_valid & ATTR_UID)) {
+		struct socket *sock = SOCKET_I(d_inode(dentry));
+
+		sock->sk->sk_uid = iattr->ia_uid;
+	}
+
+	return err;
+}
+
 static const struct inode_operations sockfs_inode_ops = {
 	.getxattr = sockfs_getxattr,
 	.listxattr = sockfs_listxattr,
+	.setattr = sockfs_setattr,
 };
 
 /**
@@ -2041,6 +2055,8 @@
 		if (err)
 			break;
 		++datagrams;
+		if (msg_data_left(&msg_sys))
+			break;
 	}
 
 	fput_light(sock->file, fput_needed);
@@ -2183,8 +2199,10 @@
 		return err;
 
 	err = sock_error(sock->sk);
-	if (err)
+	if (err) {
+		datagrams = err;
 		goto out_put;
+	}
 
 	entry = mmsg;
 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 799e65b..1f0687d 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -340,12 +340,14 @@
 }
 
 static struct gss_upcall_msg *
-__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid)
+__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth)
 {
 	struct gss_upcall_msg *pos;
 	list_for_each_entry(pos, &pipe->in_downcall, list) {
 		if (!uid_eq(pos->uid, uid))
 			continue;
+		if (auth && pos->auth->service != auth->service)
+			continue;
 		atomic_inc(&pos->count);
 		dprintk("RPC:       %s found msg %p\n", __func__, pos);
 		return pos;
@@ -365,7 +367,7 @@
 	struct gss_upcall_msg *old;
 
 	spin_lock(&pipe->lock);
-	old = __gss_find_upcall(pipe, gss_msg->uid);
+	old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth);
 	if (old == NULL) {
 		atomic_inc(&gss_msg->count);
 		list_add(&gss_msg->list, &pipe->in_downcall);
@@ -539,9 +541,13 @@
 		return gss_new;
 	gss_msg = gss_add_msg(gss_new);
 	if (gss_msg == gss_new) {
-		int res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg);
+		int res;
+		atomic_inc(&gss_msg->count);
+		res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg);
 		if (res) {
 			gss_unhash_msg(gss_new);
+			atomic_dec(&gss_msg->count);
+			gss_release_msg(gss_new);
 			gss_msg = ERR_PTR(res);
 		}
 	} else
@@ -714,7 +720,7 @@
 	err = -ENOENT;
 	/* Find a matching upcall */
 	spin_lock(&pipe->lock);
-	gss_msg = __gss_find_upcall(pipe, uid);
+	gss_msg = __gss_find_upcall(pipe, uid, NULL);
 	if (gss_msg == NULL) {
 		spin_unlock(&pipe->lock);
 		goto err_put_ctx;
@@ -834,6 +840,7 @@
 			warn_gssd();
 		gss_release_msg(gss_msg);
 	}
+	gss_release_msg(gss_msg);
 }
 
 static void gss_pipe_dentry_destroy(struct dentry *dir,
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c
index eeeba5a..2410d55 100644
--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
@@ -260,7 +260,7 @@
 	if (!oa->data)
 		return -ENOMEM;
 
-	creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL);
+	creds = kzalloc(sizeof(struct svc_cred), GFP_KERNEL);
 	if (!creds) {
 		kfree(oa->data);
 		return -ENOMEM;
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 1095be9..033fec3 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -857,8 +857,8 @@
 		goto out;
 	if (svc_getnl(&buf->head[0]) != seq)
 		goto out;
-	/* trim off the mic at the end before returning */
-	xdr_buf_trim(buf, mic.len + 4);
+	/* trim off the mic and padding at the end before returning */
+	xdr_buf_trim(buf, round_up_to_quad(mic.len) + 4);
 	stat = 0;
 out:
 	kfree(mic.data);
@@ -1481,7 +1481,7 @@
 	case RPC_GSS_PROC_DESTROY:
 		if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
 			goto auth_err;
-		rsci->h.expiry_time = get_seconds();
+		rsci->h.expiry_time = seconds_since_boot();
 		set_bit(CACHE_NEGATIVE, &rsci->h.flags);
 		if (resv->iov_len + 4 > PAGE_SIZE)
 			goto drop;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 23608eb..f28aeb2 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -337,6 +337,11 @@
 
 static DEFINE_IDA(rpc_clids);
 
+void rpc_cleanup_clids(void)
+{
+	ida_destroy(&rpc_clids);
+}
+
 static int rpc_alloc_clid(struct rpc_clnt *clnt)
 {
 	int clid;
@@ -442,7 +447,7 @@
 	return ERR_PTR(err);
 }
 
-struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
+static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
 					struct rpc_xprt *xprt)
 {
 	struct rpc_clnt *clnt = NULL;
@@ -474,7 +479,6 @@
 
 	return clnt;
 }
-EXPORT_SYMBOL_GPL(rpc_create_xprt);
 
 /**
  * rpc_create - create an RPC client and transport with one call
@@ -500,6 +504,15 @@
 	};
 	char servername[48];
 
+	if (args->bc_xprt) {
+		WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP);
+		xprt = args->bc_xprt->xpt_bc_xprt;
+		if (xprt) {
+			xprt_get(xprt);
+			return rpc_create_xprt(args, xprt);
+		}
+	}
+
 	if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS)
 		xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;
 	if (args->flags & RPC_CLNT_CREATE_NO_IDLE_TIMEOUT)
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index ee5d3d2..3142f38 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -119,6 +119,7 @@
 static void __exit
 cleanup_sunrpc(void)
 {
+	rpc_cleanup_clids();
 	rpcauth_remove_module();
 	cleanup_socket_xprt();
 	svc_cleanup_xprt_sock();
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index cc98528..c5b0cb4 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1188,11 +1188,17 @@
 		*statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
 
 		/* Encode reply */
-		if (test_bit(RQ_DROPME, &rqstp->rq_flags)) {
+		if (*statp == rpc_drop_reply ||
+		    test_bit(RQ_DROPME, &rqstp->rq_flags)) {
 			if (procp->pc_release)
 				procp->pc_release(rqstp, NULL, rqstp->rq_resp);
 			goto dropit;
 		}
+		if (*statp == rpc_autherr_badcred) {
+			if (procp->pc_release)
+				procp->pc_release(rqstp, NULL, rqstp->rq_resp);
+			goto err_bad_auth;
+		}
 		if (*statp == rpc_success &&
 		    (xdr = procp->pc_encode) &&
 		    !xdr(rqstp, resv->iov_base+resv->iov_len, rqstp->rq_resp)) {
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index ff4f01e..d4e0d64 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -346,8 +346,6 @@
 	atomic_inc(&rdma_stat_read);
 	return ret;
  err:
-	ib_dma_unmap_sg(xprt->sc_cm_id->device,
-			frmr->sg, frmr->sg_nents, frmr->direction);
 	svc_rdma_put_context(ctxt, 0);
 	svc_rdma_put_frmr(xprt, frmr);
 	return ret;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 027c9ef..27b6f55 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -474,7 +474,16 @@
 	spin_unlock_bh(&xprt->transport_lock);
 
 	/* Race breaker in case memory is freed before above code is called */
-	sk->sk_write_space(sk);
+	if (ret == -EAGAIN) {
+		struct socket_wq *wq;
+
+		rcu_read_lock();
+		wq = rcu_dereference(sk->sk_wq);
+		set_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags);
+		rcu_read_unlock();
+
+		sk->sk_write_space(sk);
+	}
 	return ret;
 }
 
@@ -2286,6 +2295,10 @@
 		/* SYN_SENT! */
 		if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
 			xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+		break;
+	case -EADDRNOTAVAIL:
+		/* Source port number is unavailable. Try a new one! */
+		transport->srcport = 0;
 	}
 out:
 	return ret;
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index d5d7132..1b58866 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -1169,6 +1169,7 @@
 		.obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
 		.dst = dst,
 		.dst_len = dst_len,
+		.fi = fi,
 		.tos = tos,
 		.type = type,
 		.nlflags = nlflags,
@@ -1177,8 +1178,6 @@
 	struct net_device *dev;
 	int err = 0;
 
-	memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));
-
 	/* Don't offload route if using custom ip rules or if
 	 * IPv4 FIB offloading has been disabled completely.
 	 */
@@ -1222,6 +1221,7 @@
 		.obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
 		.dst = dst,
 		.dst_len = dst_len,
+		.fi = fi,
 		.tos = tos,
 		.type = type,
 		.nlflags = 0,
@@ -1230,8 +1230,6 @@
 	struct net_device *dev;
 	int err = 0;
 
-	memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));
-
 	if (!(fi->fib_flags & RTNH_F_OFFLOAD))
 		return 0;
 
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index ed98c1f..46a71c7 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -46,7 +46,7 @@
 	kgid_t root_gid = make_kgid(net->user_ns, 0);
 
 	/* Allow network administrator to have same access as root. */
-	if (ns_capable(net->user_ns, CAP_NET_ADMIN) ||
+	if (ns_capable_noaudit(net->user_ns, CAP_NET_ADMIN) ||
 	    uid_eq(root_uid, current_euid())) {
 		int mode = (table->mode >> 6) & 7;
 		return (mode << 6) | (mode << 3) | mode;
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 648f2a6..cb13815 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -381,6 +381,10 @@
 	dev = dev_get_by_name(net, driver_name);
 	if (!dev)
 		return -ENODEV;
+	if (tipc_mtu_bad(dev, 0)) {
+		dev_put(dev);
+		return -EINVAL;
+	}
 
 	/* Associate TIPC bearer with L2 bearer */
 	rcu_assign_pointer(b->media_ptr, dev);
@@ -570,14 +574,19 @@
 	if (!b_ptr)
 		return NOTIFY_DONE;
 
-	b_ptr->mtu = dev->mtu;
-
 	switch (evt) {
 	case NETDEV_CHANGE:
 		if (netif_carrier_ok(dev))
 			break;
 	case NETDEV_GOING_DOWN:
+		tipc_reset_bearer(net, b_ptr);
+		break;
 	case NETDEV_CHANGEMTU:
+		if (tipc_mtu_bad(dev, 0)) {
+			bearer_disable(net, b_ptr);
+			break;
+		}
+		b_ptr->mtu = dev->mtu;
 		tipc_reset_bearer(net, b_ptr);
 		break;
 	case NETDEV_CHANGEADDR:
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 552185b..5f11e18 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -39,6 +39,7 @@
 
 #include "netlink.h"
 #include "core.h"
+#include "msg.h"
 #include <net/genetlink.h>
 
 #define MAX_MEDIA	3
@@ -61,6 +62,9 @@
 #define TIPC_MEDIA_TYPE_IB	2
 #define TIPC_MEDIA_TYPE_UDP	3
 
+/* minimum bearer MTU */
+#define TIPC_MIN_BEARER_MTU	(MAX_H_SIZE + INT_H_SIZE)
+
 /**
  * struct tipc_node_map - set of node identifiers
  * @count: # of nodes in set
@@ -226,4 +230,13 @@
 void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
 			 struct sk_buff_head *xmitq);
 
+/* check if device MTU is too low for tipc headers */
+static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve)
+{
+	if (dev->mtu >= TIPC_MIN_BEARER_MTU + reserve)
+		return false;
+	netdev_warn(dev, "MTU too low for tipc bearer\n");
+	return true;
+}
+
 #endif	/* _TIPC_BEARER_H */
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 03a8428..e2bdb07a 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -69,6 +69,7 @@
 	if (err)
 		goto out_nametbl;
 
+	INIT_LIST_HEAD(&tn->dist_queue);
 	err = tipc_topsrv_start(net);
 	if (err)
 		goto out_subscr;
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 18e95a8..fe3b89e 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -103,6 +103,9 @@
 	spinlock_t nametbl_lock;
 	struct name_table *nametbl;
 
+	/* Name dist queue */
+	struct list_head dist_queue;
+
 	/* Topology subscription server */
 	struct tipc_server *topsrv;
 	atomic_t subscription_count;
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 91aea07..72268ea 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1262,6 +1262,8 @@
 		/* fall thru' */
 
 	case ACTIVATE_MSG:
+		skb_linearize(skb);
+		hdr = buf_msg(skb);
 
 		/* Complete own link name with peer's interface name */
 		if_name =  strrchr(l->name, ':') + 1;
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index c07612b..c4c151b 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -40,11 +40,6 @@
 
 int sysctl_tipc_named_timeout __read_mostly = 2000;
 
-/**
- * struct tipc_dist_queue - queue holding deferred name table updates
- */
-static struct list_head tipc_dist_queue = LIST_HEAD_INIT(tipc_dist_queue);
-
 struct distr_queue_item {
 	struct distr_item i;
 	u32 dtype;
@@ -67,6 +62,8 @@
 
 /**
  * named_prepare_buf - allocate & initialize a publication message
+ *
+ * The buffer returned is of size INT_H_SIZE + payload size
  */
 static struct sk_buff *named_prepare_buf(struct net *net, u32 type, u32 size,
 					 u32 dest)
@@ -171,9 +168,9 @@
 	struct publication *publ;
 	struct sk_buff *skb = NULL;
 	struct distr_item *item = NULL;
-	uint msg_dsz = (tipc_node_get_mtu(net, dnode, 0) / ITEM_SIZE) *
-			ITEM_SIZE;
-	uint msg_rem = msg_dsz;
+	u32 msg_dsz = ((tipc_node_get_mtu(net, dnode, 0) - INT_H_SIZE) /
+			ITEM_SIZE) * ITEM_SIZE;
+	u32 msg_rem = msg_dsz;
 
 	list_for_each_entry(publ, pls, local_list) {
 		/* Prepare next buffer: */
@@ -340,9 +337,11 @@
  * tipc_named_add_backlog - add a failed name table update to the backlog
  *
  */
-static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node)
+static void tipc_named_add_backlog(struct net *net, struct distr_item *i,
+				   u32 type, u32 node)
 {
 	struct distr_queue_item *e;
+	struct tipc_net *tn = net_generic(net, tipc_net_id);
 	unsigned long now = get_jiffies_64();
 
 	e = kzalloc(sizeof(*e), GFP_ATOMIC);
@@ -352,7 +351,7 @@
 	e->node = node;
 	e->expires = now + msecs_to_jiffies(sysctl_tipc_named_timeout);
 	memcpy(e, i, sizeof(*i));
-	list_add_tail(&e->next, &tipc_dist_queue);
+	list_add_tail(&e->next, &tn->dist_queue);
 }
 
 /**
@@ -362,10 +361,11 @@
 void tipc_named_process_backlog(struct net *net)
 {
 	struct distr_queue_item *e, *tmp;
+	struct tipc_net *tn = net_generic(net, tipc_net_id);
 	char addr[16];
 	unsigned long now = get_jiffies_64();
 
-	list_for_each_entry_safe(e, tmp, &tipc_dist_queue, next) {
+	list_for_each_entry_safe(e, tmp, &tn->dist_queue, next) {
 		if (time_after(e->expires, now)) {
 			if (!tipc_update_nametbl(net, &e->i, e->node, e->dtype))
 				continue;
@@ -397,6 +397,7 @@
 
 	spin_lock_bh(&tn->nametbl_lock);
 	for (skb = skb_dequeue(inputq); skb; skb = skb_dequeue(inputq)) {
+		skb_linearize(skb);
 		msg = buf_msg(skb);
 		mtype = msg_type(msg);
 		item = (struct distr_item *)msg_data(msg);
@@ -404,7 +405,7 @@
 		node = msg_orignode(msg);
 		while (count--) {
 			if (!tipc_update_nametbl(net, item, node, mtype))
-				tipc_named_add_backlog(item, mtype, node);
+				tipc_named_add_backlog(net, item, mtype, node);
 			item++;
 		}
 		kfree_skb(skb);
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index 1eadc95..a0c9057 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -574,7 +574,8 @@
 
 	link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]);
 	link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP]));
-	strcpy(link_info.str, nla_data(link[TIPC_NLA_LINK_NAME]));
+	nla_strlcpy(link_info.str, link[TIPC_NLA_LINK_NAME],
+		    TIPC_MAX_LINK_NAME);
 
 	return tipc_add_tlv(msg->rep, TIPC_TLV_LINK_INFO,
 			    &link_info, sizeof(link_info));
@@ -802,7 +803,7 @@
 		goto out;
 
 	tipc_tlv_sprintf(msg->rep, "%-10u %s",
-			 nla_get_u32(publ[TIPC_NLA_PUBL_REF]),
+			 nla_get_u32(publ[TIPC_NLA_PUBL_KEY]),
 			 scope_str[nla_get_u32(publ[TIPC_NLA_PUBL_SCOPE])]);
 out:
 	tipc_tlv_sprintf(msg->rep, "\n");
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 3926b56..2df0b98 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -102,9 +102,10 @@
 
 static void tipc_node_kref_release(struct kref *kref)
 {
-	struct tipc_node *node = container_of(kref, struct tipc_node, kref);
+	struct tipc_node *n = container_of(kref, struct tipc_node, kref);
 
-	tipc_node_delete(node);
+	kfree(n->bc_entry.link);
+	kfree_rcu(n, rcu);
 }
 
 void tipc_node_put(struct tipc_node *node)
@@ -216,21 +217,20 @@
 {
 	list_del_rcu(&node->list);
 	hlist_del_rcu(&node->hash);
-	kfree(node->bc_entry.link);
-	kfree_rcu(node, rcu);
+	tipc_node_put(node);
+
+	del_timer_sync(&node->timer);
+	tipc_node_put(node);
 }
 
 void tipc_node_stop(struct net *net)
 {
-	struct tipc_net *tn = net_generic(net, tipc_net_id);
+	struct tipc_net *tn = tipc_net(net);
 	struct tipc_node *node, *t_node;
 
 	spin_lock_bh(&tn->node_list_lock);
-	list_for_each_entry_safe(node, t_node, &tn->node_list, list) {
-		if (del_timer(&node->timer))
-			tipc_node_put(node);
-		tipc_node_put(node);
-	}
+	list_for_each_entry_safe(node, t_node, &tn->node_list, list)
+		tipc_node_delete(node);
 	spin_unlock_bh(&tn->node_list_lock);
 }
 
@@ -313,9 +313,7 @@
 		if (rc & TIPC_LINK_DOWN_EVT)
 			tipc_node_link_down(n, bearer_id, false);
 	}
-	if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))
-		tipc_node_get(n);
-	tipc_node_put(n);
+	mod_timer(&n->timer, jiffies + n->keepalive_intv);
 }
 
 /**
@@ -730,7 +728,7 @@
 			state = SELF_UP_PEER_UP;
 			break;
 		case SELF_LOST_CONTACT_EVT:
-			state = SELF_DOWN_PEER_LEAVING;
+			state = SELF_DOWN_PEER_DOWN;
 			break;
 		case SELF_ESTABL_CONTACT_EVT:
 		case PEER_LOST_CONTACT_EVT:
@@ -749,7 +747,7 @@
 			state = SELF_UP_PEER_UP;
 			break;
 		case PEER_LOST_CONTACT_EVT:
-			state = SELF_LEAVING_PEER_DOWN;
+			state = SELF_DOWN_PEER_DOWN;
 			break;
 		case SELF_LOST_CONTACT_EVT:
 		case PEER_ESTABL_CONTACT_EVT:
diff --git a/net/tipc/server.c b/net/tipc/server.c
index 922e04a..50f5b0c 100644
--- a/net/tipc/server.c
+++ b/net/tipc/server.c
@@ -452,6 +452,11 @@
 	if (!con)
 		return -EINVAL;
 
+	if (!test_bit(CF_CONNECTED, &con->flags)) {
+		conn_put(con);
+		return 0;
+	}
+
 	e = tipc_alloc_entry(data, len);
 	if (!e) {
 		conn_put(con);
@@ -465,12 +470,8 @@
 	list_add_tail(&e->list, &con->outqueue);
 	spin_unlock_bh(&con->outqueue_lock);
 
-	if (test_bit(CF_CONNECTED, &con->flags)) {
-		if (!queue_work(s->send_wq, &con->swork))
-			conn_put(con);
-	} else {
+	if (!queue_work(s->send_wq, &con->swork))
 		conn_put(con);
-	}
 	return 0;
 }
 
@@ -494,7 +495,7 @@
 	int ret;
 
 	spin_lock_bh(&con->outqueue_lock);
-	while (1) {
+	while (test_bit(CF_CONNECTED, &con->flags)) {
 		e = list_entry(con->outqueue.next, struct outqueue_entry,
 			       list);
 		if ((struct list_head *) e == &con->outqueue)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index e53003c..65171f8 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -777,9 +777,11 @@
  * @tsk: receiving socket
  * @skb: pointer to message buffer.
  */
-static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb)
+static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
+			      struct sk_buff_head *xmitq)
 {
 	struct sock *sk = &tsk->sk;
+	u32 onode = tsk_own_node(tsk);
 	struct tipc_msg *hdr = buf_msg(skb);
 	int mtyp = msg_type(hdr);
 	int conn_cong;
@@ -792,7 +794,8 @@
 
 	if (mtyp == CONN_PROBE) {
 		msg_set_type(hdr, CONN_PROBE_REPLY);
-		tipc_sk_respond(sk, skb, TIPC_OK);
+		if (tipc_msg_reverse(onode, &skb, TIPC_OK))
+			__skb_queue_tail(xmitq, skb);
 		return;
 	} else if (mtyp == CONN_ACK) {
 		conn_cong = tsk_conn_cong(tsk);
@@ -1647,7 +1650,8 @@
  *
  * Returns true if message was added to socket receive queue, otherwise false
  */
-static bool filter_rcv(struct sock *sk, struct sk_buff *skb)
+static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
+		       struct sk_buff_head *xmitq)
 {
 	struct socket *sock = sk->sk_socket;
 	struct tipc_sock *tsk = tipc_sk(sk);
@@ -1657,7 +1661,7 @@
 	int usr = msg_user(hdr);
 
 	if (unlikely(msg_user(hdr) == CONN_MANAGER)) {
-		tipc_sk_proto_rcv(tsk, skb);
+		tipc_sk_proto_rcv(tsk, skb, xmitq);
 		return false;
 	}
 
@@ -1700,7 +1704,8 @@
 	return true;
 
 reject:
-	tipc_sk_respond(sk, skb, err);
+	if (tipc_msg_reverse(tsk_own_node(tsk), &skb, err))
+		__skb_queue_tail(xmitq, skb);
 	return false;
 }
 
@@ -1716,9 +1721,24 @@
 static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	unsigned int truesize = skb->truesize;
+	struct sk_buff_head xmitq;
+	u32 dnode, selector;
 
-	if (likely(filter_rcv(sk, skb)))
+	__skb_queue_head_init(&xmitq);
+
+	if (likely(filter_rcv(sk, skb, &xmitq))) {
 		atomic_add(truesize, &tipc_sk(sk)->dupl_rcvcnt);
+		return 0;
+	}
+
+	if (skb_queue_empty(&xmitq))
+		return 0;
+
+	/* Send response/rejected message */
+	skb = __skb_dequeue(&xmitq);
+	dnode = msg_destnode(buf_msg(skb));
+	selector = msg_origport(buf_msg(skb));
+	tipc_node_xmit_skb(sock_net(sk), skb, dnode, selector);
 	return 0;
 }
 
@@ -1732,12 +1752,13 @@
  * Caller must hold socket lock
  */
 static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
-			    u32 dport)
+			    u32 dport, struct sk_buff_head *xmitq)
 {
+	unsigned long time_limit = jiffies + 2;
+	struct sk_buff *skb;
 	unsigned int lim;
 	atomic_t *dcnt;
-	struct sk_buff *skb;
-	unsigned long time_limit = jiffies + 2;
+	u32 onode;
 
 	while (skb_queue_len(inputq)) {
 		if (unlikely(time_after_eq(jiffies, time_limit)))
@@ -1749,20 +1770,22 @@
 
 		/* Add message directly to receive queue if possible */
 		if (!sock_owned_by_user(sk)) {
-			filter_rcv(sk, skb);
+			filter_rcv(sk, skb, xmitq);
 			continue;
 		}
 
 		/* Try backlog, compensating for double-counted bytes */
 		dcnt = &tipc_sk(sk)->dupl_rcvcnt;
-		if (sk->sk_backlog.len)
+		if (!sk->sk_backlog.len)
 			atomic_set(dcnt, 0);
 		lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt);
 		if (likely(!sk_add_backlog(sk, skb, lim)))
 			continue;
 
 		/* Overload => reject message back to sender */
-		tipc_sk_respond(sk, skb, TIPC_ERR_OVERLOAD);
+		onode = tipc_own_addr(sock_net(sk));
+		if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD))
+			__skb_queue_tail(xmitq, skb);
 		break;
 	}
 }
@@ -1775,12 +1798,14 @@
  */
 void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
 {
+	struct sk_buff_head xmitq;
 	u32 dnode, dport = 0;
 	int err;
 	struct tipc_sock *tsk;
 	struct sock *sk;
 	struct sk_buff *skb;
 
+	__skb_queue_head_init(&xmitq);
 	while (skb_queue_len(inputq)) {
 		dport = tipc_skb_peek_port(inputq, dport);
 		tsk = tipc_sk_lookup(net, dport);
@@ -1788,9 +1813,14 @@
 		if (likely(tsk)) {
 			sk = &tsk->sk;
 			if (likely(spin_trylock_bh(&sk->sk_lock.slock))) {
-				tipc_sk_enqueue(inputq, sk, dport);
+				tipc_sk_enqueue(inputq, sk, dport, &xmitq);
 				spin_unlock_bh(&sk->sk_lock.slock);
 			}
+			/* Send pending response/rejected messages, if any */
+			while ((skb = __skb_dequeue(&xmitq))) {
+				dnode = msg_destnode(buf_msg(skb));
+				tipc_node_xmit_skb(net, skb, dnode, dport);
+			}
 			sock_put(sk);
 			continue;
 		}
@@ -2111,7 +2141,8 @@
 					      TIPC_CONN_MSG, SHORT_H_SIZE,
 					      0, dnode, onode, dport, oport,
 					      TIPC_CONN_SHUTDOWN);
-			tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
+			if (skb)
+				tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
 		}
 		tsk->connected = 0;
 		sock->state = SS_DISCONNECTING;
@@ -2814,6 +2845,9 @@
 		if (err)
 			return err;
 
+		if (!attrs[TIPC_NLA_SOCK])
+			return -EINVAL;
+
 		err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX,
 				       attrs[TIPC_NLA_SOCK],
 				       tipc_nl_sock_policy);
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 69ee2ee..f9ff73a 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -296,7 +296,8 @@
 	if (tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscrb, &sub))
 		return tipc_conn_terminate(tn->topsrv, subscrb->conid);
 
-	tipc_nametbl_subscribe(sub);
+	if (sub)
+		tipc_nametbl_subscribe(sub);
 }
 
 /* Handle one request to establish a new subscriber */
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 70c0327..78d6b78 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -48,12 +48,11 @@
 #include <linux/tipc_netlink.h>
 #include "core.h"
 #include "bearer.h"
-#include "msg.h"
 
 /* IANA assigned UDP port */
 #define UDP_PORT_DEFAULT	6118
 
-#define UDP_MIN_HEADROOM        28
+#define UDP_MIN_HEADROOM        48
 
 static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = {
 	[TIPC_NLA_UDP_UNSPEC]	= {.type = NLA_UNSPEC},
@@ -224,10 +223,6 @@
 {
 	struct udp_bearer *ub;
 	struct tipc_bearer *b;
-	int usr = msg_user(buf_msg(skb));
-
-	if ((usr == LINK_PROTOCOL) || (usr == NAME_DISTRIBUTOR))
-		skb_linearize(skb);
 
 	ub = rcu_dereference_sk_user_data(sk);
 	if (!ub) {
@@ -381,6 +376,11 @@
 		udp_conf.local_ip.s_addr = htonl(INADDR_ANY);
 		udp_conf.use_udp_checksums = false;
 		ub->ifindex = dev->ifindex;
+		if (tipc_mtu_bad(dev, sizeof(struct iphdr) +
+				      sizeof(struct udphdr))) {
+			err = -EINVAL;
+			goto err;
+		}
 		b->mtu = dev->mtu - sizeof(struct iphdr)
 			- sizeof(struct udphdr);
 #if IS_ENABLED(CONFIG_IPV6)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 898a53a..e05ec54 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -315,7 +315,7 @@
 		    &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
 		struct dentry *dentry = unix_sk(s)->path.dentry;
 
-		if (dentry && d_backing_inode(dentry) == i) {
+		if (dentry && d_real_inode(dentry) == i) {
 			sock_hold(s);
 			goto found;
 		}
@@ -661,11 +661,11 @@
 {
 	struct unix_sock *u = unix_sk(sk);
 
-	if (mutex_lock_interruptible(&u->readlock))
+	if (mutex_lock_interruptible(&u->iolock))
 		return -EINTR;
 
 	sk->sk_peek_off = val;
-	mutex_unlock(&u->readlock);
+	mutex_unlock(&u->iolock);
 
 	return 0;
 }
@@ -778,7 +778,8 @@
 	spin_lock_init(&u->lock);
 	atomic_long_set(&u->inflight, 0);
 	INIT_LIST_HEAD(&u->link);
-	mutex_init(&u->readlock); /* single task reading lock */
+	mutex_init(&u->iolock); /* single task reading lock */
+	mutex_init(&u->bindlock); /* single task binding lock */
 	init_waitqueue_head(&u->peer_wait);
 	init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay);
 	unix_insert_socket(unix_sockets_unbound(sk), sk);
@@ -847,7 +848,7 @@
 	int err;
 	unsigned int retries = 0;
 
-	err = mutex_lock_interruptible(&u->readlock);
+	err = mutex_lock_interruptible(&u->bindlock);
 	if (err)
 		return err;
 
@@ -894,7 +895,7 @@
 	spin_unlock(&unix_table_lock);
 	err = 0;
 
-out:	mutex_unlock(&u->readlock);
+out:	mutex_unlock(&u->bindlock);
 	return err;
 }
 
@@ -911,7 +912,7 @@
 		err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
 		if (err)
 			goto fail;
-		inode = d_backing_inode(path.dentry);
+		inode = d_real_inode(path.dentry);
 		err = inode_permission(inode, MAY_WRITE);
 		if (err)
 			goto put_fail;
@@ -953,20 +954,32 @@
 	return NULL;
 }
 
-static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode,
-		      struct path *res)
+static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
 {
-	int err;
+	struct dentry *dentry;
+	struct path path;
+	int err = 0;
+	/*
+	 * Get the parent directory, calculate the hash for last
+	 * component.
+	 */
+	dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
+	err = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
+		return err;
 
-	err = security_path_mknod(path, dentry, mode, 0);
+	/*
+	 * All right, let's create it.
+	 */
+	err = security_path_mknod(&path, dentry, mode, 0);
 	if (!err) {
-		err = vfs_mknod(d_inode(path->dentry), dentry, mode, 0);
+		err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0);
 		if (!err) {
-			res->mnt = mntget(path->mnt);
+			res->mnt = mntget(path.mnt);
 			res->dentry = dget(dentry);
 		}
 	}
-
+	done_path_create(&path, dentry);
 	return err;
 }
 
@@ -977,15 +990,15 @@
 	struct unix_sock *u = unix_sk(sk);
 	struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
 	char *sun_path = sunaddr->sun_path;
-	int err, name_err;
+	int err;
 	unsigned int hash;
 	struct unix_address *addr;
 	struct hlist_head *list;
-	struct path path;
-	struct dentry *dentry;
+	struct path path = { NULL, NULL };
 
 	err = -EINVAL;
-	if (sunaddr->sun_family != AF_UNIX)
+	if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
+	    sunaddr->sun_family != AF_UNIX)
 		goto out;
 
 	if (addr_len == sizeof(short)) {
@@ -998,34 +1011,25 @@
 		goto out;
 	addr_len = err;
 
-	name_err = 0;
-	dentry = NULL;
 	if (sun_path[0]) {
-		/* Get the parent directory, calculate the hash for last
-		 * component.
-		 */
-		dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
-
-		if (IS_ERR(dentry)) {
-			/* delay report until after 'already bound' check */
-			name_err = PTR_ERR(dentry);
-			dentry = NULL;
+		umode_t mode = S_IFSOCK |
+		       (SOCK_INODE(sock)->i_mode & ~current_umask());
+		err = unix_mknod(sun_path, mode, &path);
+		if (err) {
+			if (err == -EEXIST)
+				err = -EADDRINUSE;
+			goto out;
 		}
 	}
 
-	err = mutex_lock_interruptible(&u->readlock);
+	err = mutex_lock_interruptible(&u->bindlock);
 	if (err)
-		goto out_path;
+		goto out_put;
 
 	err = -EINVAL;
 	if (u->addr)
 		goto out_up;
 
-	if (name_err) {
-		err = name_err == -EEXIST ? -EADDRINUSE : name_err;
-		goto out_up;
-	}
-
 	err = -ENOMEM;
 	addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
 	if (!addr)
@@ -1036,21 +1040,11 @@
 	addr->hash = hash ^ sk->sk_type;
 	atomic_set(&addr->refcnt, 1);
 
-	if (dentry) {
-		struct path u_path;
-		umode_t mode = S_IFSOCK |
-		       (SOCK_INODE(sock)->i_mode & ~current_umask());
-		err = unix_mknod(dentry, &path, mode, &u_path);
-		if (err) {
-			if (err == -EEXIST)
-				err = -EADDRINUSE;
-			unix_release_addr(addr);
-			goto out_up;
-		}
+	if (sun_path[0]) {
 		addr->hash = UNIX_HASH_SIZE;
-		hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
+		hash = d_real_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1);
 		spin_lock(&unix_table_lock);
-		u->path = u_path;
+		u->path = path;
 		list = &unix_socket_table[hash];
 	} else {
 		spin_lock(&unix_table_lock);
@@ -1072,11 +1066,10 @@
 out_unlock:
 	spin_unlock(&unix_table_lock);
 out_up:
-	mutex_unlock(&u->readlock);
-out_path:
-	if (dentry)
-		done_path_create(&path, dentry);
-
+	mutex_unlock(&u->bindlock);
+out_put:
+	if (err)
+		path_put(&path);
 out:
 	return err;
 }
@@ -1116,6 +1109,10 @@
 	unsigned int hash;
 	int err;
 
+	err = -EINVAL;
+	if (alen < offsetofend(struct sockaddr, sa_family))
+		goto out;
+
 	if (addr->sa_family != AF_UNSPEC) {
 		err = unix_mkname(sunaddr, alen, &hash);
 		if (err < 0)
@@ -1971,17 +1968,17 @@
 	if (false) {
 alloc_skb:
 		unix_state_unlock(other);
-		mutex_unlock(&unix_sk(other)->readlock);
+		mutex_unlock(&unix_sk(other)->iolock);
 		newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT,
 					      &err, 0);
 		if (!newskb)
 			goto err;
 	}
 
-	/* we must acquire readlock as we modify already present
+	/* we must acquire iolock as we modify already present
 	 * skbs in the sk_receive_queue and mess with skb->len
 	 */
-	err = mutex_lock_interruptible(&unix_sk(other)->readlock);
+	err = mutex_lock_interruptible(&unix_sk(other)->iolock);
 	if (err) {
 		err = flags & MSG_DONTWAIT ? -EAGAIN : -ERESTARTSYS;
 		goto err;
@@ -2048,7 +2045,7 @@
 	}
 
 	unix_state_unlock(other);
-	mutex_unlock(&unix_sk(other)->readlock);
+	mutex_unlock(&unix_sk(other)->iolock);
 
 	other->sk_data_ready(other);
 	scm_destroy(&scm);
@@ -2057,7 +2054,7 @@
 err_state_unlock:
 	unix_state_unlock(other);
 err_unlock:
-	mutex_unlock(&unix_sk(other)->readlock);
+	mutex_unlock(&unix_sk(other)->iolock);
 err:
 	kfree_skb(newskb);
 	if (send_sigpipe && !(flags & MSG_NOSIGNAL))
@@ -2122,7 +2119,7 @@
 	if (flags&MSG_OOB)
 		goto out;
 
-	err = mutex_lock_interruptible(&u->readlock);
+	err = mutex_lock_interruptible(&u->iolock);
 	if (unlikely(err)) {
 		/* recvmsg() in non blocking mode is supposed to return -EAGAIN
 		 * sk_rcvtimeo is not honored by mutex_lock_interruptible()
@@ -2198,7 +2195,7 @@
 out_free:
 	skb_free_datagram(sk, skb);
 out_unlock:
-	mutex_unlock(&u->readlock);
+	mutex_unlock(&u->iolock);
 out:
 	return err;
 }
@@ -2207,7 +2204,8 @@
  *	Sleep until more data has arrived. But check for races..
  */
 static long unix_stream_data_wait(struct sock *sk, long timeo,
-				  struct sk_buff *last, unsigned int last_len)
+				  struct sk_buff *last, unsigned int last_len,
+				  bool freezable)
 {
 	struct sk_buff *tail;
 	DEFINE_WAIT(wait);
@@ -2228,7 +2226,10 @@
 
 		sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
 		unix_state_unlock(sk);
-		timeo = freezable_schedule_timeout(timeo);
+		if (freezable)
+			timeo = freezable_schedule_timeout(timeo);
+		else
+			timeo = schedule_timeout(timeo);
 		unix_state_lock(sk);
 
 		if (sock_flag(sk, SOCK_DEAD))
@@ -2258,7 +2259,8 @@
 	unsigned int splice_flags;
 };
 
-static int unix_stream_read_generic(struct unix_stream_read_state *state)
+static int unix_stream_read_generic(struct unix_stream_read_state *state,
+				    bool freezable)
 {
 	struct scm_cookie scm;
 	struct socket *sock = state->socket;
@@ -2293,7 +2295,7 @@
 	/* Lock the socket to prevent queue disordering
 	 * while sleeps in memcpy_tomsg
 	 */
-	mutex_lock(&u->readlock);
+	mutex_lock(&u->iolock);
 
 	if (flags & MSG_PEEK)
 		skip = sk_peek_offset(sk, flags);
@@ -2334,10 +2336,10 @@
 				break;
 			}
 
-			mutex_unlock(&u->readlock);
+			mutex_unlock(&u->iolock);
 
 			timeo = unix_stream_data_wait(sk, timeo, last,
-						      last_len);
+						      last_len, freezable);
 
 			if (signal_pending(current)) {
 				err = sock_intr_errno(timeo);
@@ -2345,7 +2347,7 @@
 				goto out;
 			}
 
-			mutex_lock(&u->readlock);
+			mutex_lock(&u->iolock);
 			continue;
 unlock:
 			unix_state_unlock(sk);
@@ -2448,7 +2450,7 @@
 		}
 	} while (size);
 
-	mutex_unlock(&u->readlock);
+	mutex_unlock(&u->iolock);
 	if (state->msg)
 		scm_recv(sock, state->msg, &scm, flags);
 	else
@@ -2479,7 +2481,7 @@
 		.flags = flags
 	};
 
-	return unix_stream_read_generic(&state);
+	return unix_stream_read_generic(&state, true);
 }
 
 static ssize_t skb_unix_socket_splice(struct sock *sk,
@@ -2489,9 +2491,9 @@
 	int ret;
 	struct unix_sock *u = unix_sk(sk);
 
-	mutex_unlock(&u->readlock);
+	mutex_unlock(&u->iolock);
 	ret = splice_to_pipe(pipe, spd);
-	mutex_lock(&u->readlock);
+	mutex_lock(&u->iolock);
 
 	return ret;
 }
@@ -2525,7 +2527,7 @@
 	    flags & SPLICE_F_NONBLOCK)
 		state.flags = MSG_DONTWAIT;
 
-	return unix_stream_read_generic(&state);
+	return unix_stream_read_generic(&state, false);
 }
 
 static int unix_shutdown(struct socket *sock, int mode)
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 6a0d485..c36757e 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -146,6 +146,7 @@
 	if (s) {
 		struct unix_sock *u = unix_sk(s);
 
+		BUG_ON(!atomic_long_read(&u->inflight));
 		BUG_ON(list_empty(&u->link));
 
 		if (atomic_long_dec_and_test(&u->inflight))
@@ -341,6 +342,14 @@
 	}
 	list_del(&cursor);
 
+	/* Now gc_candidates contains only garbage.  Restore original
+	 * inflight counters for these as well, and remove the skbuffs
+	 * which are creating the cycle(s).
+	 */
+	skb_queue_head_init(&hitlist);
+	list_for_each_entry(u, &gc_candidates, link)
+		scan_children(&u->sk, inc_inflight, &hitlist);
+
 	/* not_cycle_list contains those sockets which do not make up a
 	 * cycle.  Restore these to the inflight list.
 	 */
@@ -350,14 +359,6 @@
 		list_move_tail(&u->link, &gc_inflight_list);
 	}
 
-	/* Now gc_candidates contains only garbage.  Restore original
-	 * inflight counters for these as well, and remove the skbuffs
-	 * which are creating the cycle(s).
-	 */
-	skb_queue_head_init(&hitlist);
-	list_for_each_entry(u, &gc_candidates, link)
-	scan_children(&u->sk, inc_inflight, &hitlist);
-
 	spin_unlock(&unix_gc_lock);
 
 	/* Here we are. Hitlist is filled. Die. */
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 7fd1220..9b5bd6d 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1794,27 +1794,8 @@
 	else if (sk->sk_shutdown & RCV_SHUTDOWN)
 		err = 0;
 
-	if (copied > 0) {
-		/* We only do these additional bookkeeping/notification steps
-		 * if we actually copied something out of the queue pair
-		 * instead of just peeking ahead.
-		 */
-
-		if (!(flags & MSG_PEEK)) {
-			/* If the other side has shutdown for sending and there
-			 * is nothing more to read, then modify the socket
-			 * state.
-			 */
-			if (vsk->peer_shutdown & SEND_SHUTDOWN) {
-				if (vsock_stream_has_data(vsk) <= 0) {
-					sk->sk_state = SS_UNCONNECTED;
-					sock_set_flag(sk, SOCK_DONE);
-					sk->sk_state_change(sk);
-				}
-			}
-		}
+	if (copied > 0)
 		err = copied;
-	}
 
 out_wait:
 	finish_wait(sk_sleep(sk), &wait);
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index 0a369bb..662bdd2 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -842,7 +842,7 @@
 	 * qp_handle.
 	 */
 	if (vmci_handle_is_invalid(e_payload->handle) ||
-	    vmci_handle_is_equal(trans->qp_handle, e_payload->handle))
+	    !vmci_handle_is_equal(trans->qp_handle, e_payload->handle))
 		return;
 
 	/* We don't ask for delayed CBs when we subscribe to this event (we
@@ -2154,7 +2154,7 @@
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMCI transport for Virtual Sockets");
-MODULE_VERSION("1.0.2.0-k");
+MODULE_VERSION("1.0.3.0-k");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("vmware_vsock");
 MODULE_ALIAS_NETPROTO(PF_VSOCK);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a618b4b..47ea169 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -72,6 +72,7 @@
 	struct list_head bss_list;
 	struct rb_root bss_tree;
 	u32 bss_generation;
+	u32 bss_entries;
 	struct cfg80211_scan_request *scan_req; /* protected by RTNL */
 	struct sk_buff *scan_msg;
 	struct cfg80211_sched_scan_request __rcu *sched_scan_req;
@@ -397,6 +398,7 @@
 void cfg80211_sme_deauth(struct wireless_dev *wdev);
 void cfg80211_sme_auth_timeout(struct wireless_dev *wdev);
 void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev);
+void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev);
 
 /* internal helpers */
 bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index fb44fa3..c0e02f7 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -149,6 +149,18 @@
 }
 EXPORT_SYMBOL(cfg80211_assoc_timeout);
 
+void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+
+	cfg80211_sme_abandon_assoc(wdev);
+
+	cfg80211_unhold_bss(bss_from_pub(bss));
+	cfg80211_put_bss(wiphy, bss);
+}
+EXPORT_SYMBOL(cfg80211_abandon_assoc);
+
 void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5d89f13..9d0953e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -492,21 +492,17 @@
 {
 	int err;
 
-	rtnl_lock();
-
 	if (!cb->args[0]) {
 		err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
 				  nl80211_fam.attrbuf, nl80211_fam.maxattr,
 				  nl80211_policy);
 		if (err)
-			goto out_unlock;
+			return err;
 
 		*wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
 						   nl80211_fam.attrbuf);
-		if (IS_ERR(*wdev)) {
-			err = PTR_ERR(*wdev);
-			goto out_unlock;
-		}
+		if (IS_ERR(*wdev))
+			return PTR_ERR(*wdev);
 		*rdev = wiphy_to_rdev((*wdev)->wiphy);
 		/* 0 is the first index - add 1 to parse only once */
 		cb->args[0] = (*rdev)->wiphy_idx + 1;
@@ -516,10 +512,8 @@
 		struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
 		struct wireless_dev *tmp;
 
-		if (!wiphy) {
-			err = -ENODEV;
-			goto out_unlock;
-		}
+		if (!wiphy)
+			return -ENODEV;
 		*rdev = wiphy_to_rdev(wiphy);
 		*wdev = NULL;
 
@@ -530,21 +524,11 @@
 			}
 		}
 
-		if (!*wdev) {
-			err = -ENODEV;
-			goto out_unlock;
-		}
+		if (!*wdev)
+			return -ENODEV;
 	}
 
 	return 0;
- out_unlock:
-	rtnl_unlock();
-	return err;
-}
-
-static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
-{
-	rtnl_unlock();
 }
 
 /* IE validation */
@@ -3884,9 +3868,10 @@
 	int sta_idx = cb->args[2];
 	int err;
 
+	rtnl_lock();
 	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
 	if (err)
-		return err;
+		goto out_err;
 
 	if (!wdev->netdev) {
 		err = -EINVAL;
@@ -3922,7 +3907,7 @@
 	cb->args[2] = sta_idx;
 	err = skb->len;
  out_err:
-	nl80211_finish_wdev_dump(rdev);
+	rtnl_unlock();
 
 	return err;
 }
@@ -4639,9 +4624,10 @@
 	int path_idx = cb->args[2];
 	int err;
 
+	rtnl_lock();
 	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
 	if (err)
-		return err;
+		goto out_err;
 
 	if (!rdev->ops->dump_mpath) {
 		err = -EOPNOTSUPP;
@@ -4675,7 +4661,7 @@
 	cb->args[2] = path_idx;
 	err = skb->len;
  out_err:
-	nl80211_finish_wdev_dump(rdev);
+	rtnl_unlock();
 	return err;
 }
 
@@ -4835,9 +4821,10 @@
 	int path_idx = cb->args[2];
 	int err;
 
+	rtnl_lock();
 	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
 	if (err)
-		return err;
+		goto out_err;
 
 	if (!rdev->ops->dump_mpp) {
 		err = -EOPNOTSUPP;
@@ -4870,7 +4857,7 @@
 	cb->args[2] = path_idx;
 	err = skb->len;
  out_err:
-	nl80211_finish_wdev_dump(rdev);
+	rtnl_unlock();
 	return err;
 }
 
@@ -6628,7 +6615,7 @@
 
 		params.n_counter_offsets_presp = len / sizeof(u16);
 		if (rdev->wiphy.max_num_csa_counters &&
-		    (params.n_counter_offsets_beacon >
+		    (params.n_counter_offsets_presp >
 		     rdev->wiphy.max_num_csa_counters))
 			return -EINVAL;
 
@@ -6806,9 +6793,12 @@
 	int start = cb->args[2], idx = 0;
 	int err;
 
+	rtnl_lock();
 	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
-	if (err)
+	if (err) {
+		rtnl_unlock();
 		return err;
+	}
 
 	wdev_lock(wdev);
 	spin_lock_bh(&rdev->bss_lock);
@@ -6831,7 +6821,7 @@
 	wdev_unlock(wdev);
 
 	cb->args[2] = idx;
-	nl80211_finish_wdev_dump(rdev);
+	rtnl_unlock();
 
 	return skb->len;
 }
@@ -6915,9 +6905,10 @@
 	int res;
 	bool radio_stats;
 
+	rtnl_lock();
 	res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
 	if (res)
-		return res;
+		goto out_err;
 
 	/* prepare_wdev_dump parsed the attributes */
 	radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
@@ -6958,7 +6949,7 @@
 	cb->args[2] = survey_idx;
 	res = skb->len;
  out_err:
-	nl80211_finish_wdev_dump(rdev);
+	rtnl_unlock();
 	return res;
 }
 
@@ -10158,17 +10149,13 @@
 	void *data = NULL;
 	unsigned int data_len = 0;
 
-	rtnl_lock();
-
 	if (cb->args[0]) {
 		/* subtract the 1 again here */
 		struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
 		struct wireless_dev *tmp;
 
-		if (!wiphy) {
-			err = -ENODEV;
-			goto out_unlock;
-		}
+		if (!wiphy)
+			return -ENODEV;
 		*rdev = wiphy_to_rdev(wiphy);
 		*wdev = NULL;
 
@@ -10189,13 +10176,11 @@
 			  nl80211_fam.attrbuf, nl80211_fam.maxattr,
 			  nl80211_policy);
 	if (err)
-		goto out_unlock;
+		return err;
 
 	if (!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID] ||
-	    !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
-		err = -EINVAL;
-		goto out_unlock;
-	}
+	    !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD])
+		return -EINVAL;
 
 	*wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
 					   nl80211_fam.attrbuf);
@@ -10204,10 +10189,8 @@
 
 	*rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
 					   nl80211_fam.attrbuf);
-	if (IS_ERR(*rdev)) {
-		err = PTR_ERR(*rdev);
-		goto out_unlock;
-	}
+	if (IS_ERR(*rdev))
+		return PTR_ERR(*rdev);
 
 	vid = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID]);
 	subcmd = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
@@ -10220,19 +10203,15 @@
 		if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
 			continue;
 
-		if (!vcmd->dumpit) {
-			err = -EOPNOTSUPP;
-			goto out_unlock;
-		}
+		if (!vcmd->dumpit)
+			return -EOPNOTSUPP;
 
 		vcmd_idx = i;
 		break;
 	}
 
-	if (vcmd_idx < 0) {
-		err = -EOPNOTSUPP;
-		goto out_unlock;
-	}
+	if (vcmd_idx < 0)
+		return -EOPNOTSUPP;
 
 	if (nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]) {
 		data = nla_data(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]);
@@ -10249,9 +10228,6 @@
 
 	/* keep rtnl locked in successful case */
 	return 0;
- out_unlock:
-	rtnl_unlock();
-	return err;
 }
 
 static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
@@ -10266,9 +10242,10 @@
 	int err;
 	struct nlattr *vendor_data;
 
+	rtnl_lock();
 	err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
 	if (err)
-		return err;
+		goto out;
 
 	vcmd_idx = cb->args[2];
 	data = (void *)cb->args[3];
@@ -10277,18 +10254,26 @@
 
 	if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
 			   WIPHY_VENDOR_CMD_NEED_NETDEV)) {
-		if (!wdev)
-			return -EINVAL;
+		if (!wdev) {
+			err = -EINVAL;
+			goto out;
+		}
 		if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
-		    !wdev->netdev)
-			return -EINVAL;
+		    !wdev->netdev) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
 			if (wdev->netdev &&
-			    !netif_running(wdev->netdev))
-				return -ENETDOWN;
-			if (!wdev->netdev && !wdev->p2p_started)
-				return -ENETDOWN;
+			    !netif_running(wdev->netdev)) {
+				err = -ENETDOWN;
+				goto out;
+			}
+			if (!wdev->netdev && !wdev->p2p_started) {
+				err = -ENETDOWN;
+				goto out;
+			}
 		}
 	}
 
@@ -13168,13 +13153,17 @@
 
 	list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
 		bool schedule_destroy_work = false;
-		bool schedule_scan_stop = false;
 		struct cfg80211_sched_scan_request *sched_scan_req =
 			rcu_dereference(rdev->sched_scan_req);
 
 		if (sched_scan_req && notify->portid &&
-		    sched_scan_req->owner_nlportid == notify->portid)
-			schedule_scan_stop = true;
+		    sched_scan_req->owner_nlportid == notify->portid) {
+			sched_scan_req->owner_nlportid = 0;
+
+			if (rdev->ops->sched_scan_stop &&
+			    rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
+				schedule_work(&rdev->sched_scan_stop_wk);
+		}
 
 		list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) {
 			cfg80211_mlme_unregister_socket(wdev, notify->portid);
@@ -13205,12 +13194,6 @@
 				spin_unlock(&rdev->destroy_list_lock);
 				schedule_work(&rdev->destroy_work);
 			}
-		} else if (schedule_scan_stop) {
-			sched_scan_req->owner_nlportid = 0;
-
-			if (rdev->ops->sched_scan_stop &&
-			    rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
-				schedule_work(&rdev->sched_scan_stop_wk);
 		}
 	}
 
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 30f9676..6e7b86c 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -56,6 +56,19 @@
  * also linked into the probe response struct.
  */
 
+/*
+ * Limit the number of BSS entries stored in mac80211. Each one is
+ * a bit over 4k at most, so this limits to roughly 4-5M of memory.
+ * If somebody wants to really attack this though, they'd likely
+ * use small beacons, and only one type of frame, limiting each of
+ * the entries to a much smaller size (in order to generate more
+ * entries in total, so overhead is bigger.)
+ */
+static int bss_entries_limit = 1000;
+module_param(bss_entries_limit, int, 0644);
+MODULE_PARM_DESC(bss_entries_limit,
+                 "limit to number of scan BSS entries (per wiphy, default 1000)");
+
 #define IEEE80211_SCAN_RESULT_EXPIRE	(7 * HZ)
 
 static void bss_free(struct cfg80211_internal_bss *bss)
@@ -136,6 +149,10 @@
 
 	list_del_init(&bss->list);
 	rb_erase(&bss->rbn, &rdev->bss_tree);
+	rdev->bss_entries--;
+	WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list),
+		  "rdev bss entries[%d]/list[empty:%d] corruption\n",
+		  rdev->bss_entries, list_empty(&rdev->bss_list));
 	bss_ref_put(rdev, bss);
 	return true;
 }
@@ -162,6 +179,40 @@
 		rdev->bss_generation++;
 }
 
+static bool cfg80211_bss_expire_oldest(struct cfg80211_registered_device *rdev)
+{
+	struct cfg80211_internal_bss *bss, *oldest = NULL;
+	bool ret;
+
+	lockdep_assert_held(&rdev->bss_lock);
+
+	list_for_each_entry(bss, &rdev->bss_list, list) {
+		if (atomic_read(&bss->hold))
+			continue;
+
+		if (!list_empty(&bss->hidden_list) &&
+		    !bss->pub.hidden_beacon_bss)
+			continue;
+
+		if (oldest && time_before(oldest->ts, bss->ts))
+			continue;
+		oldest = bss;
+	}
+
+	if (WARN_ON(!oldest))
+		return false;
+
+	/*
+	 * The callers make sure to increase rdev->bss_generation if anything
+	 * gets removed (and a new entry added), so there's no need to also do
+	 * it here.
+	 */
+
+	ret = __cfg80211_unlink_bss(rdev, oldest);
+	WARN_ON(!ret);
+	return ret;
+}
+
 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
 			   bool send_message)
 {
@@ -687,6 +738,7 @@
 	const u8 *ie;
 	int i, ssidlen;
 	u8 fold = 0;
+	u32 n_entries = 0;
 
 	ies = rcu_access_pointer(new->pub.beacon_ies);
 	if (WARN_ON(!ies))
@@ -710,6 +762,12 @@
 	/* This is the bad part ... */
 
 	list_for_each_entry(bss, &rdev->bss_list, list) {
+		/*
+		 * we're iterating all the entries anyway, so take the
+		 * opportunity to validate the list length accounting
+		 */
+		n_entries++;
+
 		if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid))
 			continue;
 		if (bss->pub.channel != new->pub.channel)
@@ -738,6 +796,10 @@
 				   new->pub.beacon_ies);
 	}
 
+	WARN_ONCE(n_entries != rdev->bss_entries,
+		  "rdev bss entries[%d]/list[len:%d] corruption\n",
+		  rdev->bss_entries, n_entries);
+
 	return true;
 }
 
@@ -890,7 +952,14 @@
 			}
 		}
 
+		if (rdev->bss_entries >= bss_entries_limit &&
+		    !cfg80211_bss_expire_oldest(rdev)) {
+			kfree(new);
+			goto drop;
+		}
+
 		list_add_tail(&new->list, &rdev->bss_list);
+		rdev->bss_entries++;
 		rb_insert_bss(rdev, new);
 		found = new;
 	}
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 8020b5b..18b4a65 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -39,6 +39,7 @@
 		CFG80211_CONN_ASSOCIATING,
 		CFG80211_CONN_ASSOC_FAILED,
 		CFG80211_CONN_DEAUTH,
+		CFG80211_CONN_ABANDON,
 		CFG80211_CONN_CONNECTED,
 	} state;
 	u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
@@ -204,6 +205,8 @@
 		cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
 				     NULL, 0,
 				     WLAN_REASON_DEAUTH_LEAVING, false);
+		/* fall through */
+	case CFG80211_CONN_ABANDON:
 		/* free directly, disconnected event already sent */
 		cfg80211_sme_free(wdev);
 		return 0;
@@ -423,6 +426,17 @@
 	schedule_work(&rdev->conn_work);
 }
 
+void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev)
+{
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+
+	if (!wdev->conn)
+		return;
+
+	wdev->conn->state = CFG80211_CONN_ABANDON;
+	schedule_work(&rdev->conn_work);
+}
+
 static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
 				     const u8 *ies, size_t ies_len,
 				     const u8 **out_ies, size_t *out_ies_len)
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index 7ecd04c..997ff7b 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -277,6 +277,7 @@
 
 	memset(&theirs, 0, sizeof(theirs));
 	memcpy(new, ours, sizeof(*new));
+	memset(dte, 0, sizeof(*dte));
 
 	len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask);
 	if (len < 0)
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index f07224d..9adfdd7 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -239,7 +239,7 @@
 
 	.uinfo = {
 		.auth = {
-			.icv_truncbits = 96,
+			.icv_truncbits = 128,
 			.icv_fullbits = 256,
 		}
 	},
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b5e665b..8a0fdd8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1776,43 +1776,6 @@
 	goto out;
 }
 
-#ifdef CONFIG_XFRM_SUB_POLICY
-static int xfrm_dst_alloc_copy(void **target, const void *src, int size)
-{
-	if (!*target) {
-		*target = kmalloc(size, GFP_ATOMIC);
-		if (!*target)
-			return -ENOMEM;
-	}
-
-	memcpy(*target, src, size);
-	return 0;
-}
-#endif
-
-static int xfrm_dst_update_parent(struct dst_entry *dst,
-				  const struct xfrm_selector *sel)
-{
-#ifdef CONFIG_XFRM_SUB_POLICY
-	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
-	return xfrm_dst_alloc_copy((void **)&(xdst->partner),
-				   sel, sizeof(*sel));
-#else
-	return 0;
-#endif
-}
-
-static int xfrm_dst_update_origin(struct dst_entry *dst,
-				  const struct flowi *fl)
-{
-#ifdef CONFIG_XFRM_SUB_POLICY
-	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
-	return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl));
-#else
-	return 0;
-#endif
-}
-
 static int xfrm_expand_policies(const struct flowi *fl, u16 family,
 				struct xfrm_policy **pols,
 				int *num_pols, int *num_xfrms)
@@ -1884,16 +1847,6 @@
 
 	xdst = (struct xfrm_dst *)dst;
 	xdst->num_xfrms = err;
-	if (num_pols > 1)
-		err = xfrm_dst_update_parent(dst, &pols[1]->selector);
-	else
-		err = xfrm_dst_update_origin(dst, fl);
-	if (unlikely(err)) {
-		dst_free(dst);
-		XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
-		return ERR_PTR(err);
-	}
-
 	xdst->num_pols = num_pols;
 	memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols);
 	xdst->policy_genid = atomic_read(&pols[0]->genid);
@@ -3030,6 +2983,11 @@
 {
 	int rv;
 
+	/* Initialize the per-net locks here */
+	spin_lock_init(&net->xfrm.xfrm_state_lock);
+	rwlock_init(&net->xfrm.xfrm_policy_lock);
+	mutex_init(&net->xfrm.xfrm_cfg_mutex);
+
 	rv = xfrm_statistics_init(net);
 	if (rv < 0)
 		goto out_statistics;
@@ -3046,11 +3004,6 @@
 	if (rv < 0)
 		goto out;
 
-	/* Initialize the per-net locks here */
-	spin_lock_init(&net->xfrm.xfrm_state_lock);
-	rwlock_init(&net->xfrm.xfrm_policy_lock);
-	mutex_init(&net->xfrm.xfrm_cfg_mutex);
-
 	return 0;
 
 out:
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 805681a..7a5a64e 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -412,7 +412,14 @@
 	up = nla_data(rp);
 	ulen = xfrm_replay_state_esn_len(up);
 
-	if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
+	/* Check the overall length and the internal bitmap length to avoid
+	 * potential overflow. */
+	if (nla_len(rp) < ulen ||
+	    xfrm_replay_state_esn_len(replay_esn) != ulen ||
+	    replay_esn->bmp_len != up->bmp_len)
+		return -EINVAL;
+
+	if (up->replay_window > up->bmp_len * sizeof(__u32) * 8)
 		return -EINVAL;
 
 	return 0;
diff --git a/samples/bpf/trace_output_kern.c b/samples/bpf/trace_output_kern.c
index 8d8d1ec..9b96f4f 100644
--- a/samples/bpf/trace_output_kern.c
+++ b/samples/bpf/trace_output_kern.c
@@ -18,7 +18,6 @@
 		u64 cookie;
 	} data;
 
-	memset(&data, 0, sizeof(data));
 	data.pid = bpf_get_current_pid_tgid();
 	data.cookie = 0x12345678;
 
diff --git a/Documentation/mic/mpssd/.gitignore b/samples/mic/mpssd/.gitignore
similarity index 100%
rename from Documentation/mic/mpssd/.gitignore
rename to samples/mic/mpssd/.gitignore
diff --git a/samples/mic/mpssd/Makefile b/samples/mic/mpssd/Makefile
new file mode 100644
index 0000000..3e3ef91
--- /dev/null
+++ b/samples/mic/mpssd/Makefile
@@ -0,0 +1,27 @@
+ifndef CROSS_COMPILE
+uname_M := $(shell uname -m 2>/dev/null || echo not)
+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
+
+ifeq ($(ARCH),x86)
+
+PROGS := mpssd
+CC = $(CROSS_COMPILE)gcc
+CFLAGS := -I../../../usr/include -I../../../tools/include
+
+ifdef DEBUG
+CFLAGS += -DDEBUG=$(DEBUG)
+endif
+
+all: $(PROGS)
+mpssd: mpssd.c sysfs.c
+	$(CC) $(CFLAGS) mpssd.c sysfs.c -o mpssd -lpthread
+
+install:
+	install mpssd /usr/sbin/mpssd
+	install micctrl /usr/sbin/micctrl
+
+clean:
+	rm -fr $(PROGS)
+
+endif
+endif
diff --git a/Documentation/mic/mpssd/micctrl b/samples/mic/mpssd/micctrl
old mode 100755
new mode 100644
similarity index 100%
rename from Documentation/mic/mpssd/micctrl
rename to samples/mic/mpssd/micctrl
diff --git a/Documentation/mic/mpssd/mpss b/samples/mic/mpssd/mpss
old mode 100755
new mode 100644
similarity index 100%
rename from Documentation/mic/mpssd/mpss
rename to samples/mic/mpssd/mpss
diff --git a/Documentation/mic/mpssd/mpssd.c b/samples/mic/mpssd/mpssd.c
similarity index 99%
rename from Documentation/mic/mpssd/mpssd.c
rename to samples/mic/mpssd/mpssd.c
index aaeafa1..c99a759 100644
--- a/Documentation/mic/mpssd/mpssd.c
+++ b/samples/mic/mpssd/mpssd.c
@@ -1538,9 +1538,9 @@
 
 	len = snprintf(buffer, PATH_MAX,
 		"clocksource=tsc highres=off nohz=off ");
-	len += snprintf(buffer + len, PATH_MAX,
+	len += snprintf(buffer + len, PATH_MAX - len,
 		"cpufreq_on;corec6_off;pc3_off;pc6_off ");
-	len += snprintf(buffer + len, PATH_MAX,
+	len += snprintf(buffer + len, PATH_MAX - len,
 		"ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0",
 		mic->id + 1);
 
diff --git a/Documentation/mic/mpssd/mpssd.h b/samples/mic/mpssd/mpssd.h
similarity index 100%
rename from Documentation/mic/mpssd/mpssd.h
rename to samples/mic/mpssd/mpssd.h
diff --git a/Documentation/mic/mpssd/sysfs.c b/samples/mic/mpssd/sysfs.c
similarity index 100%
rename from Documentation/mic/mpssd/sysfs.c
rename to samples/mic/mpssd/sysfs.c
diff --git a/samples/seccomp/bpf-helper.h b/samples/seccomp/bpf-helper.h
index 38ee70f..1d8de9e 100644
--- a/samples/seccomp/bpf-helper.h
+++ b/samples/seccomp/bpf-helper.h
@@ -138,7 +138,7 @@
 #define ARG_32(idx) \
 	BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx))
 
-/* Loads hi into A and lo in X */
+/* Loads lo into M[0] and hi into M[1] and A */
 #define ARG_64(idx) \
 	BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \
 	BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \
@@ -153,62 +153,14 @@
 	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \
 	jt
 
-/* Checks the lo, then swaps to check the hi. A=lo,X=hi */
-#define JEQ64(lo, hi, jt) \
-	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
-	BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
-	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \
-	BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
-	jt, \
-	BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
-
-#define JNE64(lo, hi, jt) \
-	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 5, 0), \
-	BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
-	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \
-	BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
-	jt, \
-	BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
-
 #define JA32(value, jt) \
 	BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
 	jt
 
-#define JA64(lo, hi, jt) \
-	BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \
-	BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
-	BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \
-	BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
-	jt, \
-	BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
-
 #define JGE32(value, jt) \
 	BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
 	jt
 
-#define JLT32(value, jt) \
-	BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
-	jt
-
-/* Shortcut checking if hi > arg.hi. */
-#define JGE64(lo, hi, jt) \
-	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
-	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
-	BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
-	BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \
-	BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
-	jt, \
-	BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
-
-#define JLT64(lo, hi, jt) \
-	BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
-	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
-	BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
-	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
-	BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
-	jt, \
-	BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
-
 #define JGT32(value, jt) \
 	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
 	jt
@@ -217,24 +169,91 @@
 	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
 	jt
 
-/* Check hi > args.hi first, then do the GE checking */
-#define JGT64(lo, hi, jt) \
-	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
+#define JLT32(value, jt) \
+	BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
+	jt
+
+/*
+ * All the JXX64 checks assume lo is saved in M[0] and hi is saved in both
+ * A and M[1]. This invariant is kept by restoring A if necessary.
+ */
+#define JEQ64(lo, hi, jt) \
+	/* if (hi != arg.hi) goto NOMATCH; */ \
 	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
 	BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
-	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \
-	BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+	/* if (lo != arg.lo) goto NOMATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \
+	BPF_STMT(BPF_LD+BPF_MEM, 1), \
 	jt, \
-	BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+	BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+#define JNE64(lo, hi, jt) \
+	/* if (hi != arg.hi) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
+	BPF_STMT(BPF_LD+BPF_MEM, 0), \
+	/* if (lo != arg.lo) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \
+	BPF_STMT(BPF_LD+BPF_MEM, 1), \
+	jt, \
+	BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+#define JA64(lo, hi, jt) \
+	/* if (hi & arg.hi) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \
+	BPF_STMT(BPF_LD+BPF_MEM, 0), \
+	/* if (lo & arg.lo) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \
+	BPF_STMT(BPF_LD+BPF_MEM, 1), \
+	jt, \
+	BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+#define JGE64(lo, hi, jt) \
+	/* if (hi > arg.hi) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
+	/* if (hi != arg.hi) goto NOMATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+	BPF_STMT(BPF_LD+BPF_MEM, 0), \
+	/* if (lo >= arg.lo) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \
+	BPF_STMT(BPF_LD+BPF_MEM, 1), \
+	jt, \
+	BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+#define JGT64(lo, hi, jt) \
+	/* if (hi > arg.hi) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
+	/* if (hi != arg.hi) goto NOMATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+	BPF_STMT(BPF_LD+BPF_MEM, 0), \
+	/* if (lo > arg.lo) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \
+	BPF_STMT(BPF_LD+BPF_MEM, 1), \
+	jt, \
+	BPF_STMT(BPF_LD+BPF_MEM, 1)
 
 #define JLE64(lo, hi, jt) \
-	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 6, 0), \
-	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
-	BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+	/* if (hi < arg.hi) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
+	/* if (hi != arg.hi) goto NOMATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+	BPF_STMT(BPF_LD+BPF_MEM, 0), \
+	/* if (lo <= arg.lo) goto MATCH; */ \
 	BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
-	BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+	BPF_STMT(BPF_LD+BPF_MEM, 1), \
 	jt, \
-	BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+	BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+#define JLT64(lo, hi, jt) \
+	/* if (hi < arg.hi) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
+	/* if (hi != arg.hi) goto NOMATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+	BPF_STMT(BPF_LD+BPF_MEM, 0), \
+	/* if (lo < arg.lo) goto MATCH; */ \
+	BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 2, 0), \
+	BPF_STMT(BPF_LD+BPF_MEM, 1), \
+	jt, \
+	BPF_STMT(BPF_LD+BPF_MEM, 1)
 
 #define LOAD_SYSCALL_NR \
 	BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 55c96cb..a3245ae 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -11,7 +11,7 @@
 
 # The filename Kbuild has precedence over Makefile
 kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
-include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
+-include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
 
 # Figure out what we need to build from the various variables
 # ==========================================================================
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index 4efedcb..da3386a 100644
--- a/scripts/Makefile.extrawarn
+++ b/scripts/Makefile.extrawarn
@@ -24,6 +24,7 @@
 warning-1 += -Wold-style-definition
 warning-1 += $(call cc-option, -Wmissing-include-dirs)
 warning-1 += $(call cc-option, -Wunused-but-set-variable)
+warning-1 += $(call cc-option, -Wunused-const-variable)
 warning-1 += $(call cc-disable-warning, missing-field-initializers)
 
 warning-2 := -Waggregate-return
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 79e8661..c8408088 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -294,6 +294,12 @@
 
 dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
 
+# cat
+# ---------------------------------------------------------------------------
+# Concatentate multiple files together
+quiet_cmd_cat = CAT     $@
+cmd_cat = (cat $(filter-out FORCE,$^) > $@) || (rm -f $@; false)
+
 # Bzip2
 # ---------------------------------------------------------------------------
 
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 2b3c228..e701477 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2348,6 +2348,7 @@
 
 # Check for git id commit length and improperly formed commit descriptions
 		if ($in_commit_log && !$commit_log_possible_stack_dump &&
+		    $line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
 		    ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
 		     ($line =~ /\b[0-9a-f]{12,40}\b/i &&
 		      $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh
index 973e8c1..17867e7 100755
--- a/scripts/gcc-x86_64-has-stack-protector.sh
+++ b/scripts/gcc-x86_64-has-stack-protector.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
+echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fno-PIE -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
 if [ "$?" -eq "0" ] ; then
 	echo y
 else
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
index 8275f0e5..4b2f44c 100644
--- a/scripts/kconfig/nconf.gui.c
+++ b/scripts/kconfig/nconf.gui.c
@@ -364,12 +364,14 @@
 	WINDOW *prompt_win;
 	WINDOW *form_win;
 	PANEL *panel;
-	int i, x, y;
+	int i, x, y, lines, columns, win_lines, win_cols;
 	int res = -1;
 	int cursor_position = strlen(init);
 	int cursor_form_win;
 	char *result = *resultp;
 
+	getmaxyx(stdscr, lines, columns);
+
 	if (strlen(init)+1 > *result_len) {
 		*result_len = strlen(init)+1;
 		*resultp = result = realloc(result, *result_len);
@@ -386,14 +388,19 @@
 	if (title)
 		prompt_width = max(prompt_width, strlen(title));
 
+	win_lines = min(prompt_lines+6, lines-2);
+	win_cols = min(prompt_width+7, columns-2);
+	prompt_lines = max(win_lines-6, 0);
+	prompt_width = max(win_cols-7, 0);
+
 	/* place dialog in middle of screen */
-	y = (getmaxy(stdscr)-(prompt_lines+4))/2;
-	x = (getmaxx(stdscr)-(prompt_width+4))/2;
+	y = (lines-win_lines)/2;
+	x = (columns-win_cols)/2;
 
 	strncpy(result, init, *result_len);
 
 	/* create the windows */
-	win = newwin(prompt_lines+6, prompt_width+7, y, x);
+	win = newwin(win_lines, win_cols, y, x);
 	prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
 	form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
 	keypad(form_win, TRUE);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 5b96206..9f5cdd4 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -695,7 +695,7 @@
 	len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*",
 		      (*type)[0] ? *type : "*");
 
-	if (compatible[0])
+	if ((*compatible)[0])
 		sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
 			*compatible);
 
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index 1aca224..493e226 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -52,7 +52,7 @@
 	$(call cmd,src_tar,$(KERNELPATH),kernel.spec)
 	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
 	mv -f $(objtree)/.tmp_version $(objtree)/.version
-	rpmbuild --target $(UTS_MACHINE) -ta $(KERNELPATH).tar.gz
+	rpmbuild $(RPMOPTS) --target $(UTS_MACHINE) -ta $(KERNELPATH).tar.gz
 	rm $(KERNELPATH).tar.gz kernel.spec
 
 # binrpm-pkg
@@ -63,7 +63,7 @@
 	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
 	mv -f $(objtree)/.tmp_version $(objtree)/.version
 
-	rpmbuild --define "_builddir $(objtree)" --target \
+	rpmbuild $(RPMOPTS) --define "_builddir $(objtree)" --target \
 		$(UTS_MACHINE) -bb $(objtree)/binkernel.spec
 	rm binkernel.spec
 
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index e1675927..42396a7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -33,10 +33,17 @@
 #include <string.h>
 #include <unistd.h>
 
+/*
+ * glibc synced up and added the metag number but didn't add the relocations.
+ * Work around this in a crude manner for now.
+ */
 #ifndef EM_METAG
-/* Remove this when these make it to the standard system elf.h. */
 #define EM_METAG      174
+#endif
+#ifndef R_METAG_ADDR32
 #define R_METAG_ADDR32                   2
+#endif
+#ifndef R_METAG_NONE
 #define R_METAG_NONE                     3
 #endif
 
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index c2423d9..19d8364 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -266,9 +266,9 @@
 		break;
 	}  /* end switch */
 	if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0
-	||  r2(&ehdr->e_type) != ET_EXEC
+	||  (r2(&ehdr->e_type) != ET_EXEC && r2(&ehdr->e_type) != ET_DYN)
 	||  ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
-		fprintf(stderr, "unrecognized ET_EXEC file %s\n", fname);
+		fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file %s\n", fname);
 		fail_file();
 	}
 
@@ -282,12 +282,12 @@
 	case EM_386:
 	case EM_X86_64:
 	case EM_S390:
+	case EM_AARCH64:
 		custom_sort = sort_relative_table;
 		break;
 	case EM_ARCOMPACT:
 	case EM_ARCV2:
 	case EM_ARM:
-	case EM_AARCH64:
 	case EM_MICROBLAZE:
 	case EM_MIPS:
 	case EM_XTENSA:
@@ -304,7 +304,7 @@
 		if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr)
 		||  r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
 			fprintf(stderr,
-				"unrecognized ET_EXEC file: %s\n", fname);
+				"unrecognized ET_EXEC/ET_DYN file: %s\n", fname);
 			fail_file();
 		}
 		do32(ehdr, fname, custom_sort);
@@ -314,7 +314,7 @@
 		if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr)
 		||  r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
 			fprintf(stderr,
-				"unrecognized ET_EXEC file: %s\n", fname);
+				"unrecognized ET_EXEC/ET_DYN file: %s\n", fname);
 			fail_file();
 		}
 		do64(ghdr, fname, custom_sort);
diff --git a/security/Kconfig b/security/Kconfig
index 30a2603..3aa6079 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -127,6 +127,46 @@
 	  this low address space will need the permission specific to the
 	  systems running LSM.
 
+config HAVE_HARDENED_USERCOPY_ALLOCATOR
+	bool
+	help
+	  The heap allocator implements __check_heap_object() for
+	  validating memory ranges against heap object sizes in
+	  support of CONFIG_HARDENED_USERCOPY.
+
+config HAVE_ARCH_HARDENED_USERCOPY
+	bool
+	help
+	  The architecture supports CONFIG_HARDENED_USERCOPY by
+	  calling check_object_size() just before performing the
+	  userspace copies in the low level implementation of
+	  copy_to_user() and copy_from_user().
+
+config HARDENED_USERCOPY
+	bool "Harden memory copies between kernel and userspace"
+	depends on HAVE_ARCH_HARDENED_USERCOPY
+	depends on HAVE_HARDENED_USERCOPY_ALLOCATOR
+	select BUG
+	help
+	  This option checks for obviously wrong memory regions when
+	  copying memory to/from the kernel (via copy_to_user() and
+	  copy_from_user() functions) by rejecting memory ranges that
+	  are larger than the specified heap object, span multiple
+	  separately allocates pages, are not on the process stack,
+	  or are part of the kernel text. This kills entire classes
+	  of heap overflow exploits and similar kernel memory exposures.
+
+config HARDENED_USERCOPY_PAGESPAN
+	bool "Refuse to copy allocations that span multiple pages"
+	depends on HARDENED_USERCOPY
+	depends on !COMPILE_TEST
+	help
+	  When a multi-page allocation is done without __GFP_COMP,
+	  hardened usercopy will reject attempts to copy it. There are,
+	  however, several cases of this in the kernel that have not all
+	  been removed. This config is intended to be used only while
+	  trying to find such users.
+
 source security/selinux/Kconfig
 source security/smack/Kconfig
 source security/tomoyo/Kconfig
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index ad4fa49..9068369 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -331,6 +331,7 @@
 			seq_printf(seq, "%.2x", profile->hash[i]);
 		seq_puts(seq, "\n");
 	}
+	aa_put_profile(profile);
 
 	return 0;
 }
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index dc0027b..53426a6 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -623,8 +623,8 @@
 	/* released below */
 	cred = get_current_cred();
 	cxt = cred_cxt(cred);
-	profile = aa_cred_profile(cred);
-	previous_profile = cxt->previous;
+	profile = aa_get_newest_profile(aa_cred_profile(cred));
+	previous_profile = aa_get_newest_profile(cxt->previous);
 
 	if (unconfined(profile)) {
 		info = "unconfined";
@@ -720,6 +720,8 @@
 out:
 	aa_put_profile(hat);
 	kfree(name);
+	aa_put_profile(profile);
+	aa_put_profile(previous_profile);
 	put_cred(cred);
 
 	return error;
diff --git a/security/commoncap.c b/security/commoncap.c
index 48071ed..7fa251a 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -31,6 +31,10 @@
 #include <linux/binfmts.h>
 #include <linux/personality.h>
 
+#ifdef CONFIG_ANDROID_PARANOID_NETWORK
+#include <linux/android_aid.h>
+#endif
+
 /*
  * If a non-root user executes a setuid-root binary in
  * !secure(SECURE_NOROOT) mode, then we raise capabilities.
@@ -73,6 +77,13 @@
 {
 	struct user_namespace *ns = targ_ns;
 
+#ifdef CONFIG_ANDROID_PARANOID_NETWORK
+	if (cap == CAP_NET_RAW && in_egroup_p(AID_NET_RAW))
+		return 0;
+	if (cap == CAP_NET_ADMIN && in_egroup_p(AID_NET_ADMIN))
+		return 0;
+#endif
+
 	/* See if cred has the capability in the target user namespace
 	 * by examining the target user namespace and all of the target
 	 * user namespace's parents.
diff --git a/security/inode.c b/security/inode.c
index 16622ae..0f1a041 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -100,7 +100,7 @@
 	dir = d_inode(parent);
 
 	mutex_lock(&dir->i_mutex);
-	dentry = lookup_one_len(name, parent, strlen(name));
+	dentry = lookup_one_len2(name, mount, parent, strlen(name));
 	if (IS_ERR(dentry))
 		goto out;
 
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1d950fb..2d1fe34 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -202,7 +202,7 @@
 	} hash;
 
 	if (xattr_value)
-		*xattr_len = ima_read_xattr(file->f_path.dentry, xattr_value);
+		*xattr_len = ima_read_xattr(file_dentry(file), xattr_value);
 
 	if (!(iint->flags & IMA_COLLECTED)) {
 		u64 i_version = file_inode(file)->i_version;
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 1873b55..9ce9d50 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -189,7 +189,7 @@
 {
 	static const char op[] = "appraise_data";
 	char *cause = "unknown";
-	struct dentry *dentry = file->f_path.dentry;
+	struct dentry *dentry = file_dentry(file);
 	struct inode *inode = d_backing_inode(dentry);
 	enum integrity_status status = INTEGRITY_UNKNOWN;
 	int rc = xattr_len, hash_start = 0;
@@ -203,10 +203,11 @@
 
 		cause = "missing-hash";
 		status = INTEGRITY_NOLABEL;
-		if (opened & FILE_CREATED) {
+		if (opened & FILE_CREATED)
 			iint->flags |= IMA_NEW_FILE;
+		if ((iint->flags & IMA_NEW_FILE) &&
+		    !(iint->flags & IMA_DIGSIG_REQUIRED))
 			status = INTEGRITY_PASS;
-		}
 		goto out;
 	}
 
@@ -289,7 +290,7 @@
  */
 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
 {
-	struct dentry *dentry = file->f_path.dentry;
+	struct dentry *dentry = file_dentry(file);
 	int rc = 0;
 
 	/* do not collect and update hash for digital signatures */
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 696ccfa..3189885 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -428,7 +428,7 @@
 static struct key *request_master_key(struct encrypted_key_payload *epayload,
 				      const u8 **master_key, size_t *master_keylen)
 {
-	struct key *mkey = NULL;
+	struct key *mkey = ERR_PTR(-EINVAL);
 
 	if (!strncmp(epayload->master_desc, KEY_TRUSTED_PREFIX,
 		     KEY_TRUSTED_PREFIX_LEN)) {
diff --git a/security/keys/gc.c b/security/keys/gc.c
index addf060..9cb4fe4 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -46,7 +46,7 @@
  * immediately unlinked.
  */
 struct key_type key_type_dead = {
-	.name = "dead",
+	.name = ".dead",
 };
 
 /*
diff --git a/security/keys/key.c b/security/keys/key.c
index 5348089..09c10b1 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -934,12 +934,11 @@
 	/* the key must be writable */
 	ret = key_permission(key_ref, KEY_NEED_WRITE);
 	if (ret < 0)
-		goto error;
+		return ret;
 
 	/* attempt to update it if supported */
-	ret = -EOPNOTSUPP;
 	if (!key->type->update)
-		goto error;
+		return -EOPNOTSUPP;
 
 	memset(&prep, 0, sizeof(prep));
 	prep.data = payload;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 1c3872a..671709d 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -97,7 +97,7 @@
 	/* pull the payload in if one was supplied */
 	payload = NULL;
 
-	if (_payload) {
+	if (plen) {
 		ret = -ENOMEM;
 		payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN);
 		if (!payload) {
@@ -271,7 +271,8 @@
  * Create and join an anonymous session keyring or join a named session
  * keyring, creating it if necessary.  A named session keyring must have Search
  * permission for it to be joined.  Session keyrings without this permit will
- * be skipped over.
+ * be skipped over.  It is not permitted for userspace to create or join
+ * keyrings whose name begin with a dot.
  *
  * If successful, the ID of the joined session keyring will be returned.
  */
@@ -288,12 +289,16 @@
 			ret = PTR_ERR(name);
 			goto error;
 		}
+
+		ret = -EPERM;
+		if (name[0] == '.')
+			goto error_name;
 	}
 
 	/* join the session */
 	ret = join_session_keyring(name);
+error_name:
 	kfree(name);
-
 error:
 	return ret;
 }
@@ -322,7 +327,7 @@
 
 	/* pull the payload in if one was supplied */
 	payload = NULL;
-	if (_payload) {
+	if (plen) {
 		ret = -ENOMEM;
 		payload = kmalloc(plen, GFP_KERNEL);
 		if (!payload)
@@ -1223,8 +1228,8 @@
  * Read or set the default keyring in which request_key() will cache keys and
  * return the old setting.
  *
- * If a process keyring is specified then this will be created if it doesn't
- * yet exist.  The old setting will be returned if successful.
+ * If a thread or process keyring is specified then it will be created if it
+ * doesn't yet exist.  The old setting will be returned if successful.
  */
 long keyctl_set_reqkey_keyring(int reqkey_defl)
 {
@@ -1249,11 +1254,8 @@
 
 	case KEY_REQKEY_DEFL_PROCESS_KEYRING:
 		ret = install_process_keyring_to_cred(new);
-		if (ret < 0) {
-			if (ret != -EEXIST)
-				goto error;
-			ret = 0;
-		}
+		if (ret < 0)
+			goto error;
 		goto set;
 
 	case KEY_REQKEY_DEFL_DEFAULT:
diff --git a/security/keys/proc.c b/security/keys/proc.c
index f0611a6..b9f531c 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -181,7 +181,7 @@
 	struct timespec now;
 	unsigned long timo;
 	key_ref_t key_ref, skey_ref;
-	char xbuf[12];
+	char xbuf[16];
 	int rc;
 
 	struct keyring_search_context ctx = {
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index e6d5017..4ed9091 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -125,13 +125,18 @@
 }
 
 /*
- * Install a fresh thread keyring directly to new credentials.  This keyring is
- * allowed to overrun the quota.
+ * Install a thread keyring to the given credentials struct if it didn't have
+ * one already.  This is allowed to overrun the quota.
+ *
+ * Return: 0 if a thread keyring is now present; -errno on failure.
  */
 int install_thread_keyring_to_cred(struct cred *new)
 {
 	struct key *keyring;
 
+	if (new->thread_keyring)
+		return 0;
+
 	keyring = keyring_alloc("_tid", new->uid, new->gid, new,
 				KEY_POS_ALL | KEY_USR_VIEW,
 				KEY_ALLOC_QUOTA_OVERRUN, NULL);
@@ -143,7 +148,9 @@
 }
 
 /*
- * Install a fresh thread keyring, discarding the old one.
+ * Install a thread keyring to the current task if it didn't have one already.
+ *
+ * Return: 0 if a thread keyring is now present; -errno on failure.
  */
 static int install_thread_keyring(void)
 {
@@ -154,8 +161,6 @@
 	if (!new)
 		return -ENOMEM;
 
-	BUG_ON(new->thread_keyring);
-
 	ret = install_thread_keyring_to_cred(new);
 	if (ret < 0) {
 		abort_creds(new);
@@ -166,17 +171,17 @@
 }
 
 /*
- * Install a process keyring directly to a credentials struct.
+ * Install a process keyring to the given credentials struct if it didn't have
+ * one already.  This is allowed to overrun the quota.
  *
- * Returns -EEXIST if there was already a process keyring, 0 if one installed,
- * and other value on any other error
+ * Return: 0 if a process keyring is now present; -errno on failure.
  */
 int install_process_keyring_to_cred(struct cred *new)
 {
 	struct key *keyring;
 
 	if (new->process_keyring)
-		return -EEXIST;
+		return 0;
 
 	keyring = keyring_alloc("_pid", new->uid, new->gid, new,
 				KEY_POS_ALL | KEY_USR_VIEW,
@@ -189,11 +194,9 @@
 }
 
 /*
- * Make sure a process keyring is installed for the current process.  The
- * existing process keyring is not replaced.
+ * Install a process keyring to the current task if it didn't have one already.
  *
- * Returns 0 if there is a process keyring by the end of this function, some
- * error otherwise.
+ * Return: 0 if a process keyring is now present; -errno on failure.
  */
 static int install_process_keyring(void)
 {
@@ -207,14 +210,18 @@
 	ret = install_process_keyring_to_cred(new);
 	if (ret < 0) {
 		abort_creds(new);
-		return ret != -EEXIST ? ret : 0;
+		return ret;
 	}
 
 	return commit_creds(new);
 }
 
 /*
- * Install a session keyring directly to a credentials struct.
+ * Install the given keyring as the session keyring of the given credentials
+ * struct, replacing the existing one if any.  If the given keyring is NULL,
+ * then install a new anonymous session keyring.
+ *
+ * Return: 0 on success; -errno on failure.
  */
 int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
 {
@@ -249,8 +256,11 @@
 }
 
 /*
- * Install a session keyring, discarding the old one.  If a keyring is not
- * supplied, an empty one is invented.
+ * Install the given keyring as the session keyring of the current task,
+ * replacing the existing one if any.  If the given keyring is NULL, then
+ * install a new anonymous session keyring.
+ *
+ * Return: 0 on success; -errno on failure.
  */
 static int install_session_keyring(struct key *keyring)
 {
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index cccbf30..45d927a 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -220,7 +220,7 @@
 	 */
 	BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
 
-	audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
+	audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
 	audit_log_untrustedstring(ab, memcpy(comm, current->comm, sizeof(comm)));
 
 	switch (a->type) {
@@ -294,7 +294,7 @@
 	case LSM_AUDIT_DATA_TASK: {
 		struct task_struct *tsk = a->u.tsk;
 		if (tsk) {
-			pid_t pid = task_pid_nr(tsk);
+			pid_t pid = task_tgid_nr(tsk);
 			if (pid) {
 				char comm[sizeof(tsk->comm)];
 				audit_log_format(ab, " opid=%d ocomm=", pid);
diff --git a/security/security.c b/security/security.c
index 46f405c..ae05ab1 100644
--- a/security/security.c
+++ b/security/security.c
@@ -498,6 +498,7 @@
 		return 0;
 	return call_int_hook(path_chown, 0, path, uid, gid);
 }
+EXPORT_SYMBOL(security_path_chown);
 
 int security_path_chroot(struct path *path)
 {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 94a0bfc..3442738 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -740,6 +740,7 @@
 		sbsec->flags |= SE_SBPROC | SE_SBGENFS;
 
 	if (!strcmp(sb->s_type->name, "debugfs") ||
+	    !strcmp(sb->s_type->name, "tracefs") ||
 	    !strcmp(sb->s_type->name, "sysfs") ||
 	    !strcmp(sb->s_type->name, "pstore"))
 		sbsec->flags |= SE_SBGENFS;
@@ -5673,7 +5674,7 @@
 		return error;
 
 	/* Obtain a SID for the context, if one was specified. */
-	if (size && str[1] && str[1] != '\n') {
+	if (size && str[0] && str[0] != '\n') {
 		if (str[size-1] == '\n') {
 			str[size-1] = 0;
 			size--;
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 3628d3a..3134537 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -374,6 +374,32 @@
 	       chain2_len_sum);
 }
 
+/*
+ * extended permissions compatibility. Make ToT Android kernels compatible
+ * with Android M releases
+ */
+#define AVTAB_OPTYPE_ALLOWED	0x1000
+#define AVTAB_OPTYPE_AUDITALLOW	0x2000
+#define AVTAB_OPTYPE_DONTAUDIT	0x4000
+#define AVTAB_OPTYPE		(AVTAB_OPTYPE_ALLOWED | \
+				AVTAB_OPTYPE_AUDITALLOW | \
+				AVTAB_OPTYPE_DONTAUDIT)
+#define AVTAB_XPERMS_OPTYPE	4
+
+#define avtab_xperms_to_optype(x) (x << AVTAB_XPERMS_OPTYPE)
+#define avtab_optype_to_xperms(x) (x >> AVTAB_XPERMS_OPTYPE)
+
+static unsigned int avtab_android_m_compat;
+
+static void avtab_android_m_compat_set(void)
+{
+	if (!avtab_android_m_compat) {
+		pr_info("SELinux:  Android master kernel running Android"
+				" M policy in compatibility mode.\n");
+		avtab_android_m_compat = 1;
+	}
+}
+
 static uint16_t spec_order[] = {
 	AVTAB_ALLOWED,
 	AVTAB_AUDITDENY,
@@ -398,6 +424,7 @@
 	struct avtab_datum datum;
 	struct avtab_extended_perms xperms;
 	__le32 buf32[ARRAY_SIZE(xperms.perms.p)];
+	unsigned int android_m_compat_optype = 0;
 	int i, rc;
 	unsigned set;
 
@@ -488,6 +515,13 @@
 	key.target_class = le16_to_cpu(buf16[items++]);
 	key.specified = le16_to_cpu(buf16[items++]);
 
+	if ((key.specified & AVTAB_OPTYPE) &&
+			(vers == POLICYDB_VERSION_XPERMS_IOCTL)) {
+		key.specified = avtab_optype_to_xperms(key.specified);
+		android_m_compat_optype = 1;
+		avtab_android_m_compat_set();
+	}
+
 	if (!policydb_type_isvalid(pol, key.source_type) ||
 	    !policydb_type_isvalid(pol, key.target_type) ||
 	    !policydb_class_isvalid(pol, key.target_class)) {
@@ -518,10 +552,22 @@
 			printk(KERN_ERR "SELinux: avtab: truncated entry\n");
 			return rc;
 		}
-		rc = next_entry(&xperms.driver, fp, sizeof(u8));
-		if (rc) {
-			printk(KERN_ERR "SELinux: avtab: truncated entry\n");
-			return rc;
+		if (avtab_android_m_compat ||
+			    ((xperms.specified != AVTAB_XPERMS_IOCTLFUNCTION) &&
+			    (xperms.specified != AVTAB_XPERMS_IOCTLDRIVER) &&
+			    (vers == POLICYDB_VERSION_XPERMS_IOCTL))) {
+			xperms.driver = xperms.specified;
+			if (android_m_compat_optype)
+				xperms.specified = AVTAB_XPERMS_IOCTLDRIVER;
+			else
+				xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION;
+			avtab_android_m_compat_set();
+		} else {
+			rc = next_entry(&xperms.driver, fp, sizeof(u8));
+			if (rc) {
+				printk(KERN_ERR "SELinux: avtab: truncated entry\n");
+				return rc;
+			}
 		}
 		rc = next_entry(buf32, fp, sizeof(u32)*ARRAY_SIZE(xperms.perms.p));
 		if (rc) {
@@ -607,15 +653,22 @@
 	buf16[0] = cpu_to_le16(cur->key.source_type);
 	buf16[1] = cpu_to_le16(cur->key.target_type);
 	buf16[2] = cpu_to_le16(cur->key.target_class);
-	buf16[3] = cpu_to_le16(cur->key.specified);
+	if (avtab_android_m_compat && (cur->key.specified & AVTAB_XPERMS) &&
+		    (cur->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER))
+		buf16[3] = cpu_to_le16(avtab_xperms_to_optype(cur->key.specified));
+	else
+		buf16[3] = cpu_to_le16(cur->key.specified);
 	rc = put_entry(buf16, sizeof(u16), 4, fp);
 	if (rc)
 		return rc;
 
 	if (cur->key.specified & AVTAB_XPERMS) {
-		rc = put_entry(&cur->datum.u.xperms->specified, sizeof(u8), 1, fp);
-		if (rc)
-			return rc;
+		if (avtab_android_m_compat == 0) {
+			rc = put_entry(&cur->datum.u.xperms->specified,
+					sizeof(u8), 1, fp);
+			if (rc)
+				return rc;
+		}
 		rc = put_entry(&cur->datum.u.xperms->driver, sizeof(u8), 1, fp);
 		if (rc)
 			return rc;
diff --git a/sound/core/control.c b/sound/core/control.c
index a85d455..b4fe9b0 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -160,6 +160,8 @@
 	
 	if (snd_BUG_ON(!card || !id))
 		return;
+	if (card->shutdown)
+		return;
 	read_lock(&card->ctl_files_rwlock);
 #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
 	card->mixer_oss_change_count++;
diff --git a/sound/core/info.c b/sound/core/info.c
index 895362a..8ab72e0 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -325,10 +325,15 @@
 	size_t next;
 	int err = 0;
 
+	if (!entry->c.text.write)
+		return -EIO;
 	pos = *offset;
 	if (!valid_pos(pos, count))
 		return -EIO;
 	next = pos + count;
+	/* don't handle too large text inputs */
+	if (next > 16 * 1024)
+		return -EIO;
 	mutex_lock(&entry->access);
 	buf = data->wbuffer;
 	if (!buf) {
@@ -366,7 +371,9 @@
 	struct snd_info_private_data *data = seq->private;
 	struct snd_info_entry *entry = data->entry;
 
-	if (entry->c.text.read) {
+	if (!entry->c.text.read) {
+		return -EIO;
+	} else {
 		data->rbuffer->buffer = (char *)seq; /* XXX hack! */
 		entry->c.text.read(entry, data->rbuffer);
 	}
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 308c9ec..8e980aa 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -849,6 +849,14 @@
 }
 EXPORT_SYMBOL(snd_pcm_new_internal);
 
+static void free_chmap(struct snd_pcm_str *pstr)
+{
+	if (pstr->chmap_kctl) {
+		snd_ctl_remove(pstr->pcm->card, pstr->chmap_kctl);
+		pstr->chmap_kctl = NULL;
+	}
+}
+
 static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
 {
 	struct snd_pcm_substream *substream, *substream_next;
@@ -871,6 +879,7 @@
 		kfree(setup);
 	}
 #endif
+	free_chmap(pstr);
 	if (pstr->substream_count)
 		put_device(&pstr->dev);
 }
@@ -1135,10 +1144,7 @@
 	for (cidx = 0; cidx < 2; cidx++) {
 		if (!pcm->internal)
 			snd_unregister_device(&pcm->streams[cidx].dev);
-		if (pcm->streams[cidx].chmap_kctl) {
-			snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
-			pcm->streams[cidx].chmap_kctl = NULL;
-		}
+		free_chmap(&pcm->streams[cidx]);
 	}
 	mutex_unlock(&pcm->open_mutex);
 	mutex_unlock(&register_mutex);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 3a9b66c..0aca397 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1886,8 +1886,8 @@
 		snd_timer_interrupt(substream->timer, 1);
 #endif
  _end:
-	snd_pcm_stream_unlock_irqrestore(substream, flags);
 	kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
+	snd_pcm_stream_unlock_irqrestore(substream, flags);
 }
 
 EXPORT_SYMBOL(snd_pcm_period_elapsed);
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 795437b..b450a27 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1633,11 +1633,13 @@
 		return -EBUSY;
 	}
 	list_add_tail(&rmidi->list, &snd_rawmidi_devices);
+	mutex_unlock(&register_mutex);
 	err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
 				  rmidi->card, rmidi->device,
 				  &snd_rawmidi_f_ops, rmidi, &rmidi->dev);
 	if (err < 0) {
 		rmidi_err(rmidi, "unable to register\n");
+		mutex_lock(&register_mutex);
 		list_del(&rmidi->list);
 		mutex_unlock(&register_mutex);
 		return err;
@@ -1645,6 +1647,7 @@
 	if (rmidi->ops && rmidi->ops->dev_register &&
 	    (err = rmidi->ops->dev_register(rmidi)) < 0) {
 		snd_unregister_device(&rmidi->dev);
+		mutex_lock(&register_mutex);
 		list_del(&rmidi->list);
 		mutex_unlock(&register_mutex);
 		return err;
@@ -1677,7 +1680,6 @@
 		}
 	}
 #endif /* CONFIG_SND_OSSEMUL */
-	mutex_unlock(&register_mutex);
 	sprintf(name, "midi%d", rmidi->device);
 	entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root);
 	if (entry) {
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 58e79e0..c67f9c2 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1921,6 +1921,7 @@
 	     info.output_pool != client->pool->size)) {
 		if (snd_seq_write_pool_allocated(client)) {
 			/* remove all existing cells */
+			snd_seq_pool_mark_closing(client->pool);
 			snd_seq_queue_client_leave_cells(client->number);
 			snd_seq_pool_done(client->pool);
 		}
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index 1d5acbe..3490d21 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -70,6 +70,9 @@
 		return;
 	*fifo = NULL;
 
+	if (f->pool)
+		snd_seq_pool_mark_closing(f->pool);
+
 	snd_seq_fifo_clear(f);
 
 	/* wake up clients if any */
@@ -135,6 +138,7 @@
 	f->tail = cell;
 	if (f->head == NULL)
 		f->head = cell;
+	cell->next = NULL;
 	f->cells++;
 	spin_unlock_irqrestore(&f->lock, flags);
 
@@ -214,6 +218,8 @@
 		spin_lock_irqsave(&f->lock, flags);
 		cell->next = f->head;
 		f->head = cell;
+		if (!f->tail)
+			f->tail = cell;
 		f->cells++;
 		spin_unlock_irqrestore(&f->lock, flags);
 	}
@@ -259,6 +265,10 @@
 	/* NOTE: overflow flag is not cleared */
 	spin_unlock_irqrestore(&f->lock, flags);
 
+	/* close the old pool and wait until all users are gone */
+	snd_seq_pool_mark_closing(oldpool);
+	snd_use_lock_sync(&f->use_lock);
+
 	/* release cells in old pool */
 	for (cell = oldhead; cell; cell = next) {
 		next = cell->next;
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
index 3b693e9..12ba833 100644
--- a/sound/core/seq/seq_lock.c
+++ b/sound/core/seq/seq_lock.c
@@ -28,19 +28,16 @@
 /* wait until all locks are released */
 void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
 {
-	int max_count = 5 * HZ;
+	int warn_count = 5 * HZ;
 
 	if (atomic_read(lockp) < 0) {
 		pr_warn("ALSA: seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line);
 		return;
 	}
 	while (atomic_read(lockp) > 0) {
-		if (max_count == 0) {
-			pr_warn("ALSA: seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line);
-			break;
-		}
+		if (warn_count-- == 0)
+			pr_warn("ALSA: seq_lock: waiting [%d left] in %s:%d\n", atomic_read(lockp), file, line);
 		schedule_timeout_uninterruptible(1);
-		max_count--;
 	}
 }
 
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index c850345..5847c44 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -414,32 +414,33 @@
 	return 0;
 }
 
+/* refuse the further insertion to the pool */
+void snd_seq_pool_mark_closing(struct snd_seq_pool *pool)
+{
+	unsigned long flags;
+
+	if (snd_BUG_ON(!pool))
+		return;
+	spin_lock_irqsave(&pool->lock, flags);
+	pool->closing = 1;
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
 /* remove events */
 int snd_seq_pool_done(struct snd_seq_pool *pool)
 {
 	unsigned long flags;
 	struct snd_seq_event_cell *ptr;
-	int max_count = 5 * HZ;
 
 	if (snd_BUG_ON(!pool))
 		return -EINVAL;
 
 	/* wait for closing all threads */
-	spin_lock_irqsave(&pool->lock, flags);
-	pool->closing = 1;
-	spin_unlock_irqrestore(&pool->lock, flags);
-
 	if (waitqueue_active(&pool->output_sleep))
 		wake_up(&pool->output_sleep);
 
-	while (atomic_read(&pool->counter) > 0) {
-		if (max_count == 0) {
-			pr_warn("ALSA: snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter));
-			break;
-		}
+	while (atomic_read(&pool->counter) > 0)
 		schedule_timeout_uninterruptible(1);
-		max_count--;
-	}
 	
 	/* release all resources */
 	spin_lock_irqsave(&pool->lock, flags);
@@ -491,6 +492,7 @@
 	*ppool = NULL;
 	if (pool == NULL)
 		return 0;
+	snd_seq_pool_mark_closing(pool);
 	snd_seq_pool_done(pool);
 	kfree(pool);
 	return 0;
diff --git a/sound/core/seq/seq_memory.h b/sound/core/seq/seq_memory.h
index 4a2ec77..32f959c 100644
--- a/sound/core/seq/seq_memory.h
+++ b/sound/core/seq/seq_memory.h
@@ -84,6 +84,7 @@
 int snd_seq_pool_init(struct snd_seq_pool *pool);
 
 /* done pool - free events */
+void snd_seq_pool_mark_closing(struct snd_seq_pool *pool);
 int snd_seq_pool_done(struct snd_seq_pool *pool);
 
 /* create pool */
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 0bec02e..450c518 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -181,6 +181,8 @@
 	}
 }
 
+static void queue_use(struct snd_seq_queue *queue, int client, int use);
+
 /* allocate a new queue -
  * return queue index value or negative value for error
  */
@@ -192,11 +194,11 @@
 	if (q == NULL)
 		return -ENOMEM;
 	q->info_flags = info_flags;
+	queue_use(q, client, 1);
 	if (queue_list_add(q) < 0) {
 		queue_delete(q);
 		return -ENOMEM;
 	}
-	snd_seq_queue_use(q->queue, client, 1); /* use this queue */
 	return q->queue;
 }
 
@@ -502,19 +504,9 @@
 	return result;
 }
 
-
-/* use or unuse this queue -
- * if it is the first client, starts the timer.
- * if it is not longer used by any clients, stop the timer.
- */
-int snd_seq_queue_use(int queueid, int client, int use)
+/* use or unuse this queue */
+static void queue_use(struct snd_seq_queue *queue, int client, int use)
 {
-	struct snd_seq_queue *queue;
-
-	queue = queueptr(queueid);
-	if (queue == NULL)
-		return -EINVAL;
-	mutex_lock(&queue->timer_mutex);
 	if (use) {
 		if (!test_and_set_bit(client, queue->clients_bitmap))
 			queue->clients++;
@@ -529,6 +521,21 @@
 	} else {
 		snd_seq_timer_close(queue);
 	}
+}
+
+/* use or unuse this queue -
+ * if it is the first client, starts the timer.
+ * if it is not longer used by any clients, stop the timer.
+ */
+int snd_seq_queue_use(int queueid, int client, int use)
+{
+	struct snd_seq_queue *queue;
+
+	queue = queueptr(queueid);
+	if (queue == NULL)
+		return -EINVAL;
+	mutex_lock(&queue->timer_mutex);
+	queue_use(queue, client, use);
 	mutex_unlock(&queue->timer_mutex);
 	queuefree(queue);
 	return 0;
diff --git a/sound/core/timer.c b/sound/core/timer.c
index a3f547b..48eaccb 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -296,8 +296,21 @@
 		get_device(&timer->card->card_dev);
 	timeri->slave_class = tid->dev_sclass;
 	timeri->slave_id = slave_id;
-	if (list_empty(&timer->open_list_head) && timer->hw.open)
-		timer->hw.open(timer);
+
+	if (list_empty(&timer->open_list_head) && timer->hw.open) {
+		int err = timer->hw.open(timer);
+		if (err) {
+			kfree(timeri->owner);
+			kfree(timeri);
+
+			if (timer->card)
+				put_device(&timer->card->card_dev);
+			module_put(timer->module);
+			mutex_unlock(&register_mutex);
+			return err;
+		}
+	}
+
 	list_add_tail(&timeri->open_list, &timer->open_list_head);
 	snd_timer_check_master(timeri);
 	mutex_unlock(&register_mutex);
@@ -837,6 +850,7 @@
 	timer->tmr_subdevice = tid->subdevice;
 	if (id)
 		strlcpy(timer->id, id, sizeof(timer->id));
+	timer->sticks = 1;
 	INIT_LIST_HEAD(&timer->device_list);
 	INIT_LIST_HEAD(&timer->open_list_head);
 	INIT_LIST_HEAD(&timer->active_list_head);
@@ -1607,6 +1621,7 @@
 	if (err < 0)
 		goto __err;
 
+	tu->qhead = tu->qtail = tu->qused = 0;
 	kfree(tu->queue);
 	tu->queue = NULL;
 	kfree(tu->tqueue);
@@ -1686,9 +1701,21 @@
 		return -EBADFD;
 	if (copy_from_user(&params, _params, sizeof(params)))
 		return -EFAULT;
-	if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) {
-		err = -EINVAL;
-		goto _end;
+	if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {
+		u64 resolution;
+
+		if (params.ticks < 1) {
+			err = -EINVAL;
+			goto _end;
+		}
+
+		/* Don't allow resolution less than 1ms */
+		resolution = snd_timer_resolution(tu->timeri);
+		resolution *= params.ticks;
+		if (resolution < 1000000) {
+			err = -EINVAL;
+			goto _end;
+		}
 	}
 	if (params.queue_size > 0 &&
 	    (params.queue_size < 32 || params.queue_size > 1024)) {
@@ -1932,6 +1959,7 @@
 
 	tu = file->private_data;
 	unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read);
+	mutex_lock(&tu->ioctl_lock);
 	spin_lock_irq(&tu->qlock);
 	while ((long)count - result >= unit) {
 		while (!tu->qused) {
@@ -1947,7 +1975,9 @@
 			add_wait_queue(&tu->qchange_sleep, &wait);
 
 			spin_unlock_irq(&tu->qlock);
+			mutex_unlock(&tu->ioctl_lock);
 			schedule();
+			mutex_lock(&tu->ioctl_lock);
 			spin_lock_irq(&tu->qlock);
 
 			remove_wait_queue(&tu->qchange_sleep, &wait);
@@ -1964,6 +1994,7 @@
 
 		qhead = tu->qhead++;
 		tu->qhead %= tu->queue_size;
+		tu->qused--;
 		spin_unlock_irq(&tu->qlock);
 
 		if (tu->tread) {
@@ -1977,7 +2008,6 @@
 		}
 
 		spin_lock_irq(&tu->qlock);
-		tu->qused--;
 		if (err < 0)
 			goto _error;
 		result += unit;
@@ -1985,6 +2015,7 @@
 	}
  _error:
 	spin_unlock_irq(&tu->qlock);
+	mutex_unlock(&tu->ioctl_lock);
 	return result > 0 ? result : err;
 }
 
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index a9f7a75..6762861 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -420,6 +420,7 @@
 
 static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)
 {
+	hrtimer_cancel(&dpcm->timer);
 	tasklet_kill(&dpcm->tasklet);
 }
 
diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h
index c7cb7de..2c316a9 100644
--- a/sound/firewire/fireworks/fireworks.h
+++ b/sound/firewire/fireworks/fireworks.h
@@ -106,7 +106,6 @@
 	u8 *resp_buf;
 	u8 *pull_ptr;
 	u8 *push_ptr;
-	unsigned int resp_queues;
 };
 
 int snd_efw_transaction_cmd(struct fw_unit *unit,
diff --git a/sound/firewire/fireworks/fireworks_hwdep.c b/sound/firewire/fireworks/fireworks_hwdep.c
index 33df865..2e1d9a2 100644
--- a/sound/firewire/fireworks/fireworks_hwdep.c
+++ b/sound/firewire/fireworks/fireworks_hwdep.c
@@ -25,6 +25,7 @@
 {
 	unsigned int length, till_end, type;
 	struct snd_efw_transaction *t;
+	u8 *pull_ptr;
 	long count = 0;
 
 	if (remained < sizeof(type) + sizeof(struct snd_efw_transaction))
@@ -38,8 +39,17 @@
 	buf += sizeof(type);
 
 	/* write into buffer as many responses as possible */
-	while (efw->resp_queues > 0) {
-		t = (struct snd_efw_transaction *)(efw->pull_ptr);
+	spin_lock_irq(&efw->lock);
+
+	/*
+	 * When another task reaches here during this task's access to user
+	 * space, it picks up current position in buffer and can read the same
+	 * series of responses.
+	 */
+	pull_ptr = efw->pull_ptr;
+
+	while (efw->push_ptr != pull_ptr) {
+		t = (struct snd_efw_transaction *)(pull_ptr);
 		length = be32_to_cpu(t->length) * sizeof(__be32);
 
 		/* confirm enough space for this response */
@@ -49,26 +59,39 @@
 		/* copy from ring buffer to user buffer */
 		while (length > 0) {
 			till_end = snd_efw_resp_buf_size -
-				(unsigned int)(efw->pull_ptr - efw->resp_buf);
+				(unsigned int)(pull_ptr - efw->resp_buf);
 			till_end = min_t(unsigned int, length, till_end);
 
-			if (copy_to_user(buf, efw->pull_ptr, till_end))
+			spin_unlock_irq(&efw->lock);
+
+			if (copy_to_user(buf, pull_ptr, till_end))
 				return -EFAULT;
 
-			efw->pull_ptr += till_end;
-			if (efw->pull_ptr >= efw->resp_buf +
-					     snd_efw_resp_buf_size)
-				efw->pull_ptr -= snd_efw_resp_buf_size;
+			spin_lock_irq(&efw->lock);
+
+			pull_ptr += till_end;
+			if (pull_ptr >= efw->resp_buf + snd_efw_resp_buf_size)
+				pull_ptr -= snd_efw_resp_buf_size;
 
 			length -= till_end;
 			buf += till_end;
 			count += till_end;
 			remained -= till_end;
 		}
-
-		efw->resp_queues--;
 	}
 
+	/*
+	 * All of tasks can read from the buffer nearly simultaneously, but the
+	 * last position for each task is different depending on the length of
+	 * given buffer. Here, for simplicity, a position of buffer is set by
+	 * the latest task. It's better for a listening application to allow one
+	 * thread to read from the buffer. Unless, each task can read different
+	 * sequence of responses depending on variation of buffer length.
+	 */
+	efw->pull_ptr = pull_ptr;
+
+	spin_unlock_irq(&efw->lock);
+
 	return count;
 }
 
@@ -76,14 +99,17 @@
 hwdep_read_locked(struct snd_efw *efw, char __user *buf, long count,
 		  loff_t *offset)
 {
-	union snd_firewire_event event;
+	union snd_firewire_event event = {
+		.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS,
+	};
 
-	memset(&event, 0, sizeof(event));
+	spin_lock_irq(&efw->lock);
 
-	event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
 	event.lock_status.status = (efw->dev_lock_count > 0);
 	efw->dev_lock_changed = false;
 
+	spin_unlock_irq(&efw->lock);
+
 	count = min_t(long, count, sizeof(event.lock_status));
 
 	if (copy_to_user(buf, &event, count))
@@ -98,10 +124,15 @@
 {
 	struct snd_efw *efw = hwdep->private_data;
 	DEFINE_WAIT(wait);
+	bool dev_lock_changed;
+	bool queued;
 
 	spin_lock_irq(&efw->lock);
 
-	while ((!efw->dev_lock_changed) && (efw->resp_queues == 0)) {
+	dev_lock_changed = efw->dev_lock_changed;
+	queued = efw->push_ptr != efw->pull_ptr;
+
+	while (!dev_lock_changed && !queued) {
 		prepare_to_wait(&efw->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
 		spin_unlock_irq(&efw->lock);
 		schedule();
@@ -109,15 +140,17 @@
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		spin_lock_irq(&efw->lock);
+		dev_lock_changed = efw->dev_lock_changed;
+		queued = efw->push_ptr != efw->pull_ptr;
 	}
 
-	if (efw->dev_lock_changed)
-		count = hwdep_read_locked(efw, buf, count, offset);
-	else if (efw->resp_queues > 0)
-		count = hwdep_read_resp_buf(efw, buf, count, offset);
-
 	spin_unlock_irq(&efw->lock);
 
+	if (dev_lock_changed)
+		count = hwdep_read_locked(efw, buf, count, offset);
+	else if (queued)
+		count = hwdep_read_resp_buf(efw, buf, count, offset);
+
 	return count;
 }
 
@@ -160,7 +193,7 @@
 	poll_wait(file, &efw->hwdep_wait, wait);
 
 	spin_lock_irq(&efw->lock);
-	if (efw->dev_lock_changed || (efw->resp_queues > 0))
+	if (efw->dev_lock_changed || efw->pull_ptr != efw->push_ptr)
 		events = POLLIN | POLLRDNORM;
 	else
 		events = 0;
diff --git a/sound/firewire/fireworks/fireworks_proc.c b/sound/firewire/fireworks/fireworks_proc.c
index 0639dcb..beb0a0f 100644
--- a/sound/firewire/fireworks/fireworks_proc.c
+++ b/sound/firewire/fireworks/fireworks_proc.c
@@ -188,8 +188,8 @@
 	else
 		consumed = (unsigned int)(efw->push_ptr - efw->pull_ptr);
 
-	snd_iprintf(buffer, "%d %d/%d\n",
-		    efw->resp_queues, consumed, snd_efw_resp_buf_size);
+	snd_iprintf(buffer, "%d/%d\n",
+		    consumed, snd_efw_resp_buf_size);
 }
 
 static void
diff --git a/sound/firewire/fireworks/fireworks_transaction.c b/sound/firewire/fireworks/fireworks_transaction.c
index f550808..36a08ba 100644
--- a/sound/firewire/fireworks/fireworks_transaction.c
+++ b/sound/firewire/fireworks/fireworks_transaction.c
@@ -121,11 +121,11 @@
 	size_t capacity, till_end;
 	struct snd_efw_transaction *t;
 
-	spin_lock_irq(&efw->lock);
-
 	t = (struct snd_efw_transaction *)data;
 	length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length);
 
+	spin_lock_irq(&efw->lock);
+
 	if (efw->push_ptr < efw->pull_ptr)
 		capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr);
 	else
@@ -155,7 +155,6 @@
 	}
 
 	/* for hwdep */
-	efw->resp_queues++;
 	wake_up(&efw->hwdep_wait);
 
 	*rcode = RCODE_COMPLETE;
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h
index f3f6f84..bb5f8cd 100644
--- a/sound/firewire/lib.h
+++ b/sound/firewire/lib.h
@@ -42,7 +42,7 @@
 
 	struct snd_rawmidi_substream *substream;
 	snd_fw_async_midi_port_fill fill;
-	unsigned int consume_bytes;
+	int consume_bytes;
 };
 
 int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c
index 131267c..106406c 100644
--- a/sound/firewire/tascam/tascam-hwdep.c
+++ b/sound/firewire/tascam/tascam-hwdep.c
@@ -16,31 +16,14 @@
 
 #include "tascam.h"
 
-static long hwdep_read_locked(struct snd_tscm *tscm, char __user *buf,
-			      long count)
-{
-	union snd_firewire_event event;
-
-	memset(&event, 0, sizeof(event));
-
-	event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
-	event.lock_status.status = (tscm->dev_lock_count > 0);
-	tscm->dev_lock_changed = false;
-
-	count = min_t(long, count, sizeof(event.lock_status));
-
-	if (copy_to_user(buf, &event, count))
-		return -EFAULT;
-
-	return count;
-}
-
 static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
 		       loff_t *offset)
 {
 	struct snd_tscm *tscm = hwdep->private_data;
 	DEFINE_WAIT(wait);
-	union snd_firewire_event event;
+	union snd_firewire_event event = {
+		.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS,
+	};
 
 	spin_lock_irq(&tscm->lock);
 
@@ -54,10 +37,16 @@
 		spin_lock_irq(&tscm->lock);
 	}
 
-	memset(&event, 0, sizeof(event));
-	count = hwdep_read_locked(tscm, buf, count);
+	event.lock_status.status = (tscm->dev_lock_count > 0);
+	tscm->dev_lock_changed = false;
+
 	spin_unlock_irq(&tscm->lock);
 
+	count = min_t(long, count, sizeof(event.lock_status));
+
+	if (copy_to_user(buf, &event, count))
+		return -EFAULT;
+
 	return count;
 }
 
diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c
index 0e6dd5c6..e4c3063 100644
--- a/sound/firewire/tascam/tascam-stream.c
+++ b/sound/firewire/tascam/tascam-stream.c
@@ -343,7 +343,7 @@
 	if (err < 0)
 		amdtp_stream_destroy(&tscm->rx_stream);
 
-	return 0;
+	return err;
 }
 
 /* At bus reset, streaming is stopped and some registers are clear. */
diff --git a/sound/hda/array.c b/sound/hda/array.c
index 516795b..5dfa610 100644
--- a/sound/hda/array.c
+++ b/sound/hda/array.c
@@ -21,13 +21,15 @@
 		return NULL;
 	if (array->used >= array->alloced) {
 		int num = array->alloced + array->alloc_align;
+		int oldsize = array->alloced * array->elem_size;
 		int size = (num + 1) * array->elem_size;
 		void *nlist;
 		if (snd_BUG_ON(num >= 4096))
 			return NULL;
-		nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO);
+		nlist = krealloc(array->list, size, GFP_KERNEL);
 		if (!nlist)
 			return NULL;
+		memset(nlist + oldsize, 0, size - oldsize);
 		array->list = nlist;
 		array->alloced = num;
 	}
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 36470af..92b819e 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1408,6 +1408,7 @@
 	spin_unlock(&codec->reg_lock);
 	dev_dbg(codec->card->dev, "playback pointer returned cso=%xh.\n", cso);
 
+	cso %= runtime->buffer_size;
 	return cso;
 }
 
@@ -1428,6 +1429,7 @@
 	cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));
 	spin_unlock(&codec->reg_lock);
 
+	cso %= runtime->buffer_size;
 	return cso;
 }
 
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 4667c32..7417718 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -1444,9 +1444,8 @@
 	int page, p, pp, delta, i;
 
 	page =
-	    (hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)) &
-	     WT_SUBBUF_MASK)
-	    >> WT_SUBBUF_SHIFT;
+	    (hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2))
+	     >> WT_SUBBUF_SHIFT) & WT_SUBBUF_MASK;
 	if (dma->nr_periods >= 4)
 		delta = (page - dma->period_real) & 3;
 	else {
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c
index 9667cbf..79edd88 100644
--- a/sound/pci/ctxfi/cthw20k1.c
+++ b/sound/pci/ctxfi/cthw20k1.c
@@ -27,12 +27,6 @@
 #include "cthw20k1.h"
 #include "ct20k1reg.h"
 
-#if BITS_PER_LONG == 32
-#define CT_XFI_DMA_MASK		DMA_BIT_MASK(32) /* 32 bit PTE */
-#else
-#define CT_XFI_DMA_MASK		DMA_BIT_MASK(64) /* 64 bit PTE */
-#endif
-
 struct hw20k1 {
 	struct hw hw;
 	spinlock_t reg_20k1_lock;
@@ -1904,19 +1898,18 @@
 {
 	int err;
 	struct pci_dev *pci = hw->pci;
+	const unsigned int dma_bits = BITS_PER_LONG;
 
 	err = pci_enable_device(pci);
 	if (err < 0)
 		return err;
 
 	/* Set DMA transfer mask */
-	if (dma_set_mask(&pci->dev, CT_XFI_DMA_MASK) < 0 ||
-	    dma_set_coherent_mask(&pci->dev, CT_XFI_DMA_MASK) < 0) {
-		dev_err(hw->card->dev,
-			"architecture does not support PCI busmaster DMA with mask 0x%llx\n",
-			CT_XFI_DMA_MASK);
-		err = -ENXIO;
-		goto error1;
+	if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
+		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
+	} else {
+		dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
+		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
 	}
 
 	if (!hw->io_base) {
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c
index 9dc2950..d86678c 100644
--- a/sound/pci/ctxfi/cthw20k2.c
+++ b/sound/pci/ctxfi/cthw20k2.c
@@ -26,12 +26,6 @@
 #include "cthw20k2.h"
 #include "ct20k2reg.h"
 
-#if BITS_PER_LONG == 32
-#define CT_XFI_DMA_MASK		DMA_BIT_MASK(32) /* 32 bit PTE */
-#else
-#define CT_XFI_DMA_MASK		DMA_BIT_MASK(64) /* 64 bit PTE */
-#endif
-
 struct hw20k2 {
 	struct hw hw;
 	/* for i2c */
@@ -2029,19 +2023,18 @@
 	int err = 0;
 	struct pci_dev *pci = hw->pci;
 	unsigned int gctl;
+	const unsigned int dma_bits = BITS_PER_LONG;
 
 	err = pci_enable_device(pci);
 	if (err < 0)
 		return err;
 
 	/* Set DMA transfer mask */
-	if (dma_set_mask(&pci->dev, CT_XFI_DMA_MASK) < 0 ||
-	    dma_set_coherent_mask(&pci->dev, CT_XFI_DMA_MASK) < 0) {
-		dev_err(hw->card->dev,
-			"architecture does not support PCI busmaster DMA with mask 0x%llx\n",
-			CT_XFI_DMA_MASK);
-		err = -ENXIO;
-		goto error1;
+	if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
+		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
+	} else {
+		dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
+		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
 	}
 
 	if (!hw->io_base) {
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 1cb85ae..286f5e3 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -2200,11 +2200,11 @@
 	u32 pipe_alloc_mask;
 	int err;
 
-	commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
+	commpage_bak = kmalloc(sizeof(*commpage), GFP_KERNEL);
 	if (commpage_bak == NULL)
 		return -ENOMEM;
 	commpage = chip->comm_page;
-	memcpy(commpage_bak, commpage, sizeof(struct comm_page));
+	memcpy(commpage_bak, commpage, sizeof(*commpage));
 
 	err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
 	if (err < 0) {
diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c
index 9c22f95..19d41da 100644
--- a/sound/pci/hda/dell_wmi_helper.c
+++ b/sound/pci/hda/dell_wmi_helper.c
@@ -49,7 +49,7 @@
 		removefunc = true;
 		if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
 			dell_led_value = 0;
-			if (spec->gen.num_adc_nids > 1)
+			if (spec->gen.num_adc_nids > 1 && !spec->gen.dyn_adc_switch)
 				codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
 			else {
 				dell_old_cap_hook = spec->gen.cap_sync_hook;
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 7f57a14..a03cf68 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -884,6 +884,8 @@
 }
 EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
 
+#define IGNORE_SEQ_ASSOC (~(AC_DEFCFG_SEQUENCE | AC_DEFCFG_DEF_ASSOC))
+
 static bool pin_config_match(struct hda_codec *codec,
 			     const struct hda_pintbl *pins)
 {
@@ -901,7 +903,7 @@
 		for (; t_pins->nid; t_pins++) {
 			if (t_pins->nid == nid) {
 				found = 1;
-				if (t_pins->val == cfg)
+				if ((t_pins->val & IGNORE_SEQ_ASSOC) == (cfg & IGNORE_SEQ_ASSOC))
 					break;
 				else if ((cfg & 0xf0000000) == 0x40000000 && (t_pins->val & 0xf0000000) == 0x40000000)
 					break;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 373fcad..776dffa 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -294,6 +294,8 @@
 
 #define list_for_each_codec(c, bus) \
 	list_for_each_entry(c, &(bus)->core.codec_list, core.list)
+#define list_for_each_codec_safe(c, n, bus)				\
+	list_for_each_entry_safe(c, n, &(bus)->core.codec_list, core.list)
 
 /* snd_hda_codec_read/write optional flags */
 #define HDA_RW_NO_RESPONSE_FALLBACK	(1 << 0)
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 22dbfa5..9c6e10f 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -956,7 +956,7 @@
 	status = azx_readb(chip, RIRBSTS);
 	if (status & RIRB_INT_MASK) {
 		if (status & RIRB_INT_RESPONSE) {
-			if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY)
+			if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
 				udelay(80);
 			snd_hdac_bus_update_rirb(bus);
 		}
@@ -1055,11 +1055,6 @@
 	if (chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)
 		bus->core.corbrp_self_clear = true;
 
-	if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) {
-		dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
-		bus->needs_damn_long_delay = 1;
-	}
-
 	if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY)
 		bus->core.align_bdle_4k = true;
 
@@ -1133,8 +1128,12 @@
 /* configure each codec instance */
 int azx_codec_configure(struct azx *chip)
 {
-	struct hda_codec *codec;
-	list_for_each_codec(codec, &chip->bus) {
+	struct hda_codec *codec, *next;
+
+	/* use _safe version here since snd_hda_codec_configure() deregisters
+	 * the device upon error and deletes itself from the bus list.
+	 */
+	list_for_each_codec_safe(codec, next, &chip->bus) {
 		snd_hda_codec_configure(codec);
 	}
 	return 0;
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index 7b635d6..b175395 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -32,8 +32,8 @@
 #define AZX_DCAPS_NO_MSI	(1 << 9)	/* No MSI support */
 #define AZX_DCAPS_SNOOP_MASK	(3 << 10)	/* snoop type mask */
 #define AZX_DCAPS_SNOOP_OFF	(1 << 12)	/* snoop default off */
-#define AZX_DCAPS_RIRB_DELAY	(1 << 13)	/* Long delay in read loop */
-#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14)	/* Put a delay before read */
+/* 13 unused */
+/* 14 unused */
 #define AZX_DCAPS_CTX_WORKAROUND (1 << 15)	/* X-Fi workaround */
 #define AZX_DCAPS_POSFIX_LPIB	(1 << 16)	/* Use LPIB as default */
 #define AZX_DCAPS_POSFIX_VIA	(1 << 17)	/* Use VIACOMBO as default */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 367dbf0..689df78 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3190,6 +3190,7 @@
 						spec->input_paths[i][nums]);
 					spec->input_paths[i][nums] =
 						spec->input_paths[i][n];
+					spec->input_paths[i][n] = 0;
 				}
 			}
 			nums++;
@@ -3994,6 +3995,8 @@
 
 	for (n = 0; n < spec->paths.used; n++) {
 		path = snd_array_elem(&spec->paths, n);
+		if (!path->depth)
+			continue;
 		if (path->path[0] == nid ||
 		    path->path[path->depth - 1] == nid) {
 			bool pin_old = path->pin_enabled;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 411630e..e6de496 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -334,8 +334,7 @@
 
 /* quirks for Nvidia */
 #define AZX_DCAPS_PRESET_NVIDIA \
-	(AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI | /*AZX_DCAPS_ALIGN_BUFSIZE |*/ \
-	 AZX_DCAPS_NO_64BIT | AZX_DCAPS_CORBRP_SELF_CLEAR |\
+	(AZX_DCAPS_NO_MSI | AZX_DCAPS_CORBRP_SELF_CLEAR |\
 	 AZX_DCAPS_SNOOP_TYPE(NVIDIA))
 
 #define AZX_DCAPS_PRESET_CTHDA \
@@ -359,8 +358,12 @@
 
 #define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
 #define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
+#define IS_KBL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa171)
+#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71)
+#define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0)
 #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
-#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
+			IS_KBL(pci) || IS_KBL_LP(pci) || IS_KBL_H(pci)
 
 static char *driver_short_names[] = {
 	[AZX_DRIVER_ICH] = "HDA Intel",
@@ -940,20 +943,23 @@
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip;
 	struct hda_intel *hda;
+	struct hdac_bus *bus;
 
 	if (!card)
 		return 0;
 
 	chip = card->private_data;
 	hda = container_of(chip, struct hda_intel, chip);
+	bus = azx_bus(chip);
 	if (chip->disabled || hda->init_failed || !chip->running)
 		return 0;
 
-	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
-		&& hda->need_i915_power) {
-		snd_hdac_display_power(azx_bus(chip), true);
-		haswell_set_bclk(hda);
+	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
+		snd_hdac_display_power(bus, true);
+		if (hda->need_i915_power)
+			haswell_set_bclk(hda);
 	}
+
 	if (chip->msi)
 		if (pci_enable_msi(pci) < 0)
 			chip->msi = 0;
@@ -963,6 +969,11 @@
 
 	hda_intel_init_chip(chip, true);
 
+	/* power down again for link-controlled chips */
+	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
+	    !hda->need_i915_power)
+		snd_hdac_display_power(bus, false);
+
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 
 	trace_azx_resume(chip);
@@ -1042,6 +1053,7 @@
 
 	chip = card->private_data;
 	hda = container_of(chip, struct hda_intel, chip);
+	bus = azx_bus(chip);
 	if (chip->disabled || hda->init_failed)
 		return 0;
 
@@ -1049,15 +1061,9 @@
 		return 0;
 
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		bus = azx_bus(chip);
-		if (hda->need_i915_power) {
-			snd_hdac_display_power(bus, true);
+		snd_hdac_display_power(bus, true);
+		if (hda->need_i915_power)
 			haswell_set_bclk(hda);
-		} else {
-			/* toggle codec wakeup bit for STATESTS read */
-			snd_hdac_set_codec_wakeup(bus, true);
-			snd_hdac_set_codec_wakeup(bus, false);
-		}
 	}
 
 	/* Read STATESTS before controller reset */
@@ -1077,6 +1083,11 @@
 	azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
 			~STATESTS_INT_MASK);
 
+	/* power down again for link-controlled chips */
+	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
+	    !hda->need_i915_power)
+		snd_hdac_display_power(bus, false);
+
 	trace_azx_runtime_resume(chip);
 	return 0;
 }
@@ -1252,8 +1263,10 @@
 	if (use_vga_switcheroo(hda)) {
 		if (chip->disabled && hda->probe_continued)
 			snd_hda_unlock_devices(&chip->bus);
-		if (hda->vga_switcheroo_registered)
+		if (hda->vga_switcheroo_registered) {
 			vga_switcheroo_unregister_client(chip->pci);
+			vga_switcheroo_fini_domain_pm_ops(chip->card->dev);
+		}
 	}
 
 	if (bus->chip_init) {
@@ -1623,6 +1636,11 @@
 		return err;
 	}
 
+	if (chip->driver_type == AZX_DRIVER_NVIDIA) {
+		dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
+		chip->bus.needs_damn_long_delay = 1;
+	}
+
 	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
 	if (err < 0) {
 		dev_err(card->dev, "Error creating device [card]!\n");
@@ -1706,6 +1724,10 @@
 		}
 	}
 
+	/* NVidia hardware normally only supports up to 40 bits of DMA */
+	if (chip->pci->vendor == PCI_VENDOR_ID_NVIDIA)
+		dma_bits = 40;
+
 	/* disable 64bit DMA address on some devices */
 	if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
 		dev_dbg(card->dev, "Disabling 64bit DMA\n");
@@ -2144,7 +2166,20 @@
 		/* cancel the pending probing work */
 		chip = card->private_data;
 		hda = container_of(chip, struct hda_intel, chip);
+		/* FIXME: below is an ugly workaround.
+		 * Both device_release_driver() and driver_probe_device()
+		 * take *both* the device's and its parent's lock before
+		 * calling the remove() and probe() callbacks.  The codec
+		 * probe takes the locks of both the codec itself and its
+		 * parent, i.e. the PCI controller dev.  Meanwhile, when
+		 * the PCI controller is unbound, it takes its lock, too
+		 * ==> ouch, a deadlock!
+		 * As a workaround, we unlock temporarily here the controller
+		 * device during cancel_work_sync() call.
+		 */
+		device_unlock(&pci->dev);
 		cancel_work_sync(&hda->probe_work);
+		device_lock(&pci->dev);
 
 		snd_card_free(card);
 	}
@@ -2186,9 +2221,9 @@
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
 	/* Lewisburg */
 	{ PCI_DEVICE(0x8086, 0xa1f0),
-	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
 	{ PCI_DEVICE(0x8086, 0xa270),
-	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
 	/* Lynx Point-LP */
 	{ PCI_DEVICE(0x8086, 0x9c20),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
@@ -2204,6 +2239,15 @@
 	/* Sunrise Point-LP */
 	{ PCI_DEVICE(0x8086, 0x9d70),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+	/* Kabylake */
+	{ PCI_DEVICE(0x8086, 0xa171),
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+	/* Kabylake-LP */
+	{ PCI_DEVICE(0x8086, 0x9d71),
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+	/* Kabylake-H */
+	{ PCI_DEVICE(0x8086, 0xa2f0),
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
 	/* Broxton-P(Apollolake) */
 	{ PCI_DEVICE(0x8086, 0x5a98),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON },
@@ -2273,10 +2317,14 @@
 	{ PCI_DEVICE(0x1022, 0x780d),
 	  .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
 	/* ATI HDMI */
+	{ PCI_DEVICE(0x1002, 0x0002),
+	  .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
 	{ PCI_DEVICE(0x1002, 0x1308),
 	  .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
 	{ PCI_DEVICE(0x1002, 0x157a),
 	  .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+	{ PCI_DEVICE(0x1002, 0x15b3),
+	  .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
 	{ PCI_DEVICE(0x1002, 0x793b),
 	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
 	{ PCI_DEVICE(0x1002, 0x7919),
@@ -2339,6 +2387,10 @@
 	  .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
 	{ PCI_DEVICE(0x1002, 0xaae8),
 	  .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+	{ PCI_DEVICE(0x1002, 0xaae0),
+	  .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+	{ PCI_DEVICE(0x1002, 0xaaf0),
+	  .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
 	/* VIA VT8251/VT8237A */
 	{ PCI_DEVICE(0x1106, 0x3288),
 	  .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA },
@@ -2375,14 +2427,12 @@
 	  .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
 	  .class_mask = 0xffffff,
 	  .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
-	  AZX_DCAPS_NO_64BIT |
-	  AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
+	  AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB },
 #else
 	/* this entry seems still valid -- i.e. without emu20kx chip */
 	{ PCI_DEVICE(0x1102, 0x0009),
 	  .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
-	  AZX_DCAPS_NO_64BIT |
-	  AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
+	  AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB },
 #endif
 	/* CM8888 */
 	{ PCI_DEVICE(0x13f6, 0x5011),
diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c
index 64e0d1d..9739fce 100644
--- a/sound/pci/hda/hda_sysfs.c
+++ b/sound/pci/hda/hda_sysfs.c
@@ -141,14 +141,6 @@
 	err = snd_hda_codec_configure(codec);
 	if (err < 0)
 		goto error;
-	/* rebuild PCMs */
-	err = snd_hda_codec_build_pcms(codec);
-	if (err < 0)
-		goto error;
-	/* rebuild mixers */
-	err = snd_hda_codec_build_controls(codec);
-	if (err < 0)
-		goto error;
 	err = snd_card_register(codec->card);
  error:
 	snd_hda_power_down(codec);
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index 58c0aad..17fd817 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -464,6 +464,8 @@
 	if (err < 0)
 		return err;
 
+	chip->bus.needs_damn_long_delay = 1;
+
 	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
 	if (err < 0) {
 		dev_err(card->dev, "Error creating device\n");
@@ -481,8 +483,7 @@
 
 static int hda_tegra_probe(struct platform_device *pdev)
 {
-	const unsigned int driver_flags = AZX_DCAPS_RIRB_DELAY |
-					  AZX_DCAPS_CORBRP_SELF_CLEAR;
+	const unsigned int driver_flags = AZX_DCAPS_CORBRP_SELF_CLEAR;
 	struct snd_card *card;
 	struct azx *chip;
 	struct hda_tegra *hda;
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 9ceb2bc..c146d0d 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -780,6 +780,7 @@
 static const struct snd_pci_quirk ca0132_quirks[] = {
 	SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
 	SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
+	SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
 	{}
 };
 
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 600af58..46f7b02 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -261,6 +261,8 @@
 	CXT_FIXUP_HP_530,
 	CXT_FIXUP_CAP_MIX_AMP_5047,
 	CXT_FIXUP_MUTE_LED_EAPD,
+	CXT_FIXUP_HP_SPECTRE,
+	CXT_FIXUP_HP_GATE_MIC,
 };
 
 /* for hda_fixup_thinkpad_acpi() */
@@ -632,6 +634,17 @@
 				  (1 << AC_AMPCAP_MUTE_SHIFT));
 }
 
+static void cxt_fixup_hp_gate_mic_jack(struct hda_codec *codec,
+				       const struct hda_fixup *fix,
+				       int action)
+{
+	/* the mic pin (0x19) doesn't give an unsolicited event;
+	 * probe the mic pin together with the headphone pin (0x16)
+	 */
+	if (action == HDA_FIXUP_ACT_PROBE)
+		snd_hda_jack_set_gating_jack(codec, 0x19, 0x16);
+}
+
 /* ThinkPad X200 & co with cxt5051 */
 static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
 	{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
@@ -765,6 +778,18 @@
 		.type = HDA_FIXUP_FUNC,
 		.v.func = cxt_fixup_mute_led_eapd,
 	},
+	[CXT_FIXUP_HP_SPECTRE] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			/* enable NID 0x1d for the speaker on top */
+			{ 0x1d, 0x91170111 },
+			{ }
+		}
+	},
+	[CXT_FIXUP_HP_GATE_MIC] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = cxt_fixup_hp_gate_mic_jack,
+	},
 };
 
 static const struct snd_pci_quirk cxt5045_fixups[] = {
@@ -814,6 +839,8 @@
 	SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
 	SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
 	SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
+	SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
+	SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
 	SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
 	SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index f7bcd8d..a8045b8 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -51,8 +51,10 @@
 #define is_broadwell(codec)    ((codec)->core.vendor_id == 0x80862808)
 #define is_skylake(codec) ((codec)->core.vendor_id == 0x80862809)
 #define is_broxton(codec) ((codec)->core.vendor_id == 0x8086280a)
+#define is_kabylake(codec) ((codec)->core.vendor_id == 0x8086280b)
 #define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \
-				|| is_skylake(codec) || is_broxton(codec))
+				|| is_skylake(codec) || is_broxton(codec) \
+				|| is_kabylake(codec))
 
 #define is_valleyview(codec) ((codec)->core.vendor_id == 0x80862882)
 #define is_cherryview(codec) ((codec)->core.vendor_id == 0x80862883)
@@ -3584,6 +3586,7 @@
 HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI",	patch_generic_hdmi),
 HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI",	patch_generic_hdmi),
 HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI",	patch_generic_hdmi),
+HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI",	patch_generic_hdmi),
 HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI",	patch_generic_hdmi),
 HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI",	patch_generic_hdmi),
 HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI",	patch_generic_hdmi),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index ac4490a..46a3403 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -335,6 +335,7 @@
 	case 0x10ec0283:
 	case 0x10ec0286:
 	case 0x10ec0288:
+	case 0x10ec0295:
 	case 0x10ec0298:
 		alc_update_coef_idx(codec, 0x10, 1<<9, 0);
 		break;
@@ -342,6 +343,14 @@
 	case 0x10ec0293:
 		alc_update_coef_idx(codec, 0xa, 1<<13, 0);
 		break;
+	case 0x10ec0234:
+	case 0x10ec0274:
+	case 0x10ec0294:
+	case 0x10ec0700:
+	case 0x10ec0701:
+	case 0x10ec0703:
+		alc_update_coef_idx(codec, 0x10, 1<<15, 0);
+		break;
 	case 0x10ec0662:
 		if ((coef & 0x00f0) == 0x0030)
 			alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
@@ -902,6 +911,7 @@
 	{ 0x10ec0298, 0x1028, 0, "ALC3266" },
 	{ 0x10ec0256, 0x1028, 0, "ALC3246" },
 	{ 0x10ec0225, 0x1028, 0, "ALC3253" },
+	{ 0x10ec0295, 0x1028, 0, "ALC3254" },
 	{ 0x10ec0670, 0x1025, 0, "ALC669X" },
 	{ 0x10ec0676, 0x1025, 0, "ALC679X" },
 	{ 0x10ec0282, 0x1043, 0, "ALC3229" },
@@ -2220,6 +2230,7 @@
 	SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
 	SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
 	SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
+	SND_PCI_QUIRK(0x1043, 0x8691, "ASUS ROG Ranger VIII", ALC882_FIXUP_GPIO3),
 	SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
 	SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
 	SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
@@ -2647,6 +2658,8 @@
 	ALC269_TYPE_ALC255,
 	ALC269_TYPE_ALC256,
 	ALC269_TYPE_ALC225,
+	ALC269_TYPE_ALC294,
+	ALC269_TYPE_ALC700,
 };
 
 /*
@@ -2677,6 +2690,8 @@
 	case ALC269_TYPE_ALC255:
 	case ALC269_TYPE_ALC256:
 	case ALC269_TYPE_ALC225:
+	case ALC269_TYPE_ALC294:
+	case ALC269_TYPE_ALC700:
 		ssids = alc269_ssids;
 		break;
 	default:
@@ -3609,13 +3624,20 @@
 static void alc_headset_mode_unplugged(struct hda_codec *codec)
 {
 	static struct coef_fw coef0255[] = {
-		WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
 		WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
 		UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
 		WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
 		WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
 		{}
 	};
+	static struct coef_fw coef0255_1[] = {
+		WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
+		{}
+	};
+	static struct coef_fw coef0256[] = {
+		WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */
+		{}
+	};
 	static struct coef_fw coef0233[] = {
 		WRITE_COEF(0x1b, 0x0c0b),
 		WRITE_COEF(0x45, 0xc429),
@@ -3668,7 +3690,11 @@
 
 	switch (codec->core.vendor_id) {
 	case 0x10ec0255:
+		alc_process_coef_fw(codec, coef0255_1);
+		alc_process_coef_fw(codec, coef0255);
+		break;
 	case 0x10ec0256:
+		alc_process_coef_fw(codec, coef0256);
 		alc_process_coef_fw(codec, coef0255);
 		break;
 	case 0x10ec0233:
@@ -3690,6 +3716,7 @@
 		alc_process_coef_fw(codec, coef0668);
 		break;
 	case 0x10ec0225:
+	case 0x10ec0295:
 		alc_process_coef_fw(codec, coef0225);
 		break;
 	}
@@ -3790,6 +3817,7 @@
 		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
 		break;
 	case 0x10ec0225:
+	case 0x10ec0295:
 		alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
 		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
 		alc_process_coef_fw(codec, coef0225);
@@ -3847,6 +3875,7 @@
 
 	switch (codec->core.vendor_id) {
 	case 0x10ec0225:
+	case 0x10ec0295:
 		alc_process_coef_fw(codec, coef0225);
 		break;
 	case 0x10ec0255:
@@ -3884,6 +3913,12 @@
 		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
 		{}
 	};
+	static struct coef_fw coef0256[] = {
+		WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
+		WRITE_COEF(0x1b, 0x0c6b),
+		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
+		{}
+	};
 	static struct coef_fw coef0233[] = {
 		WRITE_COEF(0x45, 0xd429),
 		WRITE_COEF(0x1b, 0x0c2b),
@@ -3924,9 +3959,11 @@
 
 	switch (codec->core.vendor_id) {
 	case 0x10ec0255:
-	case 0x10ec0256:
 		alc_process_coef_fw(codec, coef0255);
 		break;
+	case 0x10ec0256:
+		alc_process_coef_fw(codec, coef0256);
+		break;
 	case 0x10ec0233:
 	case 0x10ec0283:
 		alc_process_coef_fw(codec, coef0233);
@@ -3950,6 +3987,7 @@
 		alc_process_coef_fw(codec, coef0688);
 		break;
 	case 0x10ec0225:
+	case 0x10ec0295:
 		alc_process_coef_fw(codec, coef0225);
 		break;
 	}
@@ -3965,6 +4003,12 @@
 		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
 		{}
 	};
+	static struct coef_fw coef0256[] = {
+		WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
+		WRITE_COEF(0x1b, 0x0c6b),
+		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
+		{}
+	};
 	static struct coef_fw coef0233[] = {
 		WRITE_COEF(0x45, 0xe429),
 		WRITE_COEF(0x1b, 0x0c2b),
@@ -4005,9 +4049,11 @@
 
 	switch (codec->core.vendor_id) {
 	case 0x10ec0255:
-	case 0x10ec0256:
 		alc_process_coef_fw(codec, coef0255);
 		break;
+	case 0x10ec0256:
+		alc_process_coef_fw(codec, coef0256);
+		break;
 	case 0x10ec0233:
 	case 0x10ec0283:
 		alc_process_coef_fw(codec, coef0233);
@@ -4031,6 +4077,7 @@
 		alc_process_coef_fw(codec, coef0688);
 		break;
 	case 0x10ec0225:
+	case 0x10ec0295:
 		alc_process_coef_fw(codec, coef0225);
 		break;
 	}
@@ -4114,6 +4161,7 @@
 		is_ctia = (val & 0x1c02) == 0x1c02;
 		break;
 	case 0x10ec0225:
+	case 0x10ec0295:
 		alc_process_coef_fw(codec, coef0225);
 		msleep(800);
 		val = alc_read_coef_idx(codec, 0x46);
@@ -4251,7 +4299,7 @@
 static void alc255_set_default_jack_type(struct hda_codec *codec)
 {
 	/* Set to iphone type */
-	static struct coef_fw fw[] = {
+	static struct coef_fw alc255fw[] = {
 		WRITE_COEF(0x1b, 0x880b),
 		WRITE_COEF(0x45, 0xd089),
 		WRITE_COEF(0x1b, 0x080b),
@@ -4259,7 +4307,22 @@
 		WRITE_COEF(0x1b, 0x0c0b),
 		{}
 	};
-	alc_process_coef_fw(codec, fw);
+	static struct coef_fw alc256fw[] = {
+		WRITE_COEF(0x1b, 0x884b),
+		WRITE_COEF(0x45, 0xd089),
+		WRITE_COEF(0x1b, 0x084b),
+		WRITE_COEF(0x46, 0x0004),
+		WRITE_COEF(0x1b, 0x0c4b),
+		{}
+	};
+	switch (codec->core.vendor_id) {
+	case 0x10ec0255:
+		alc_process_coef_fw(codec, alc255fw);
+		break;
+	case 0x10ec0256:
+		alc_process_coef_fw(codec, alc256fw);
+		break;
+	}
 	msleep(30);
 }
 
@@ -4612,6 +4675,22 @@
 	}
 }
 
+static void alc298_fixup_speaker_volume(struct hda_codec *codec,
+					const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		/* The speaker is routed to the Node 0x06 by a mistake, as a result
+		   we can't adjust the speaker's volume since this node does not has
+		   Amp-out capability. we change the speaker's route to:
+		   Node 0x02 (Audio Output) -> Node 0x0c (Audio Mixer) -> Node 0x17 (
+		   Pin Complex), since Node 0x02 has Amp-out caps, we can adjust
+		   speaker's volume now. */
+
+		hda_nid_t conn1[1] = { 0x0c };
+		snd_hda_override_conn_list(codec, 0x17, 1, conn1);
+	}
+}
+
 /* Hook to update amp GPIO4 for automute */
 static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec,
 					  struct hda_jack_callback *jack)
@@ -4752,6 +4831,7 @@
 	ALC292_FIXUP_DISABLE_AAMIX,
 	ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK,
 	ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
+	ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
 	ALC275_FIXUP_DELL_XPS,
 	ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
 	ALC293_FIXUP_LENOVO_SPK_NOISE,
@@ -4761,6 +4841,8 @@
 	ALC280_FIXUP_HP_HEADSET_MIC,
 	ALC221_FIXUP_HP_FRONT_MIC,
 	ALC292_FIXUP_TPT460,
+	ALC298_FIXUP_SPK_VOLUME,
+	ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -5348,6 +5430,15 @@
 		.chained = true,
 		.chain_id = ALC269_FIXUP_HEADSET_MODE
 	},
+	[ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC269_FIXUP_HEADSET_MODE
+	},
 	[ALC275_FIXUP_DELL_XPS] = {
 		.type = HDA_FIXUP_VERBS,
 		.v.verbs = (const struct hda_verb[]) {
@@ -5416,6 +5507,21 @@
 		.chained = true,
 		.chain_id = ALC293_FIXUP_LENOVO_SPK_NOISE,
 	},
+	[ALC298_FIXUP_SPK_VOLUME] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc298_fixup_speaker_volume,
+		.chained = true,
+		.chain_id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
+	},
+	[ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x1b, 0x90170151 },
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5459,8 +5565,12 @@
 	SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
 	SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
 	SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
-	SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+	SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+	SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
 	SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
+	SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+	SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
+	SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
 	SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -5571,9 +5681,11 @@
 	SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
+	SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
 	SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
 	SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
 	SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
+	SND_PCI_QUIRK(0x17aa, 0x3112, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
 	SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
 	SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
 	SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
@@ -5586,6 +5698,9 @@
 	SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x504a, "ThinkPad X260", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
+	SND_PCI_QUIRK(0x17aa, 0x5050, "Thinkpad T560p", ALC292_FIXUP_TPT460),
+	SND_PCI_QUIRK(0x17aa, 0x5051, "Thinkpad L460", ALC292_FIXUP_TPT460),
+	SND_PCI_QUIRK(0x17aa, 0x5053, "Thinkpad T460", ALC292_FIXUP_TPT460),
 	SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
 	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
@@ -5671,7 +5786,6 @@
 	{}
 };
 #define ALC225_STANDARD_PINS \
-	{0x12, 0xb7a60130}, \
 	{0x21, 0x04211020}
 
 #define ALC256_STANDARD_PINS \
@@ -5689,6 +5803,11 @@
 	{0x14, 0x90170110}, \
 	{0x15, 0x0221401f}
 
+#define ALC295_STANDARD_PINS \
+	{0x12, 0xb7a60130}, \
+	{0x14, 0x90170110}, \
+	{0x21, 0x04211020}
+
 #define ALC298_STANDARD_PINS \
 	{0x12, 0x90a60130}, \
 	{0x21, 0x03211020}
@@ -5696,14 +5815,31 @@
 static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
 	SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
 		ALC225_STANDARD_PINS,
+		{0x12, 0xb7a60130},
 		{0x14, 0x901701a0}),
 	SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
 		ALC225_STANDARD_PINS,
+		{0x12, 0xb7a60130},
 		{0x14, 0x901701b0}),
+	SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
+		ALC225_STANDARD_PINS,
+		{0x12, 0xb7a60150},
+		{0x14, 0x901701a0}),
+	SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
+		ALC225_STANDARD_PINS,
+		{0x12, 0xb7a60150},
+		{0x14, 0x901701b0}),
+	SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
+		ALC225_STANDARD_PINS,
+		{0x12, 0xb7a60130},
+		{0x1b, 0x90170110}),
 	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
 		{0x14, 0x90170110},
 		{0x21, 0x02211020}),
 	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x14, 0x90170130},
+		{0x21, 0x02211040}),
+	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
 		{0x12, 0x90a60140},
 		{0x14, 0x90170110},
 		{0x21, 0x02211020}),
@@ -5712,10 +5848,26 @@
 		{0x14, 0x90170120},
 		{0x21, 0x02211030}),
 	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x14, 0x90170110},
+		{0x1b, 0x02011020},
+		{0x21, 0x0221101f}),
+	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x14, 0x90170110},
+		{0x1b, 0x01011020},
+		{0x21, 0x0221101f}),
+	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
 		{0x14, 0x90170130},
 		{0x1b, 0x01014020},
 		{0x21, 0x0221103f}),
 	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x14, 0x90170130},
+		{0x1b, 0x01011020},
+		{0x21, 0x0221103f}),
+	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x14, 0x90170130},
+		{0x1b, 0x02011020},
+		{0x21, 0x0221103f}),
+	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
 		{0x14, 0x90170150},
 		{0x1b, 0x02011020},
 		{0x21, 0x0221105f}),
@@ -5756,11 +5908,30 @@
 		{0x12, 0x90a60180},
 		{0x14, 0x90170130},
 		{0x21, 0x02211040}),
+	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5565", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x12, 0x90a60180},
+		{0x14, 0x90170120},
+		{0x21, 0x02211030}),
+	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x1b, 0x01011020},
+		{0x21, 0x02211010}),
 	SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
 		{0x12, 0x90a60160},
 		{0x14, 0x90170120},
 		{0x21, 0x02211030}),
 	SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x12, 0x90a60170},
+		{0x14, 0x90170120},
+		{0x21, 0x02211030}),
+	SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell Inspiron 5468", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x12, 0x90a60180},
+		{0x14, 0x90170120},
+		{0x21, 0x02211030}),
+	SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+		{0x12, 0xb7a60130},
+		{0x14, 0x90170110},
+		{0x21, 0x02211020}),
+	SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
 		ALC256_STANDARD_PINS),
 	SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
 		{0x12, 0x90a60130},
@@ -5871,6 +6042,16 @@
 	SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
 		ALC292_STANDARD_PINS,
 		{0x13, 0x90a60140}),
+	SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+		ALC295_STANDARD_PINS,
+		{0x17, 0x21014020},
+		{0x18, 0x21a19030}),
+	SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+		ALC295_STANDARD_PINS,
+		{0x17, 0x21014040},
+		{0x18, 0x21a19050}),
+	SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+		ALC295_STANDARD_PINS),
 	SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
 		ALC298_STANDARD_PINS,
 		{0x17, 0x90170110}),
@@ -5880,6 +6061,12 @@
 	SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
 		ALC298_STANDARD_PINS,
 		{0x17, 0x90170150}),
+	SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_SPK_VOLUME,
+		{0x12, 0xb7a60140},
+		{0x13, 0xb7a60150},
+		{0x17, 0x90170110},
+		{0x1a, 0x03011020},
+		{0x21, 0x03211030}),
 	{}
 };
 
@@ -6026,8 +6213,22 @@
 		alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
 		break;
 	case 0x10ec0225:
+	case 0x10ec0295:
 		spec->codec_variant = ALC269_TYPE_ALC225;
 		break;
+	case 0x10ec0234:
+	case 0x10ec0274:
+	case 0x10ec0294:
+		spec->codec_variant = ALC269_TYPE_ALC294;
+		break;
+	case 0x10ec0700:
+	case 0x10ec0701:
+	case 0x10ec0703:
+		spec->codec_variant = ALC269_TYPE_ALC700;
+		spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
+		alc_update_coef_idx(codec, 0x4a, 0, 1 << 15); /* Combo jack auto trigger control */
+		break;
+
 	}
 
 	if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
@@ -6426,6 +6627,7 @@
 	ALC668_FIXUP_DELL_DISABLE_AAMIX,
 	ALC668_FIXUP_DELL_XPS13,
 	ALC662_FIXUP_ASUS_Nx50,
+	ALC668_FIXUP_ASUS_Nx51,
 };
 
 static const struct hda_fixup alc662_fixups[] = {
@@ -6672,6 +6874,15 @@
 		.chained = true,
 		.chain_id = ALC662_FIXUP_BASS_1A
 	},
+	[ALC668_FIXUP_ASUS_Nx51] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{0x1a, 0x90170151}, /* bass speaker */
+			{}
+		},
+		.chained = true,
+		.chain_id = ALC662_FIXUP_BASS_CHMAP,
+	},
 };
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -6694,11 +6905,15 @@
 	SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
+	SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE),
 	SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50),
 	SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
 	SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50),
 	SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
 	SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
+	SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51),
+	SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51),
+	SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8),
 	SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
 	SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
 	SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
@@ -6929,6 +7144,7 @@
 	HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
+	HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0255, "ALC255", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0256, "ALC256", patch_alc269),
@@ -6939,6 +7155,7 @@
 	HDA_CODEC_ENTRY(0x10ec0269, "ALC269", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0270, "ALC270", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0272, "ALC272", patch_alc662),
+	HDA_CODEC_ENTRY(0x10ec0274, "ALC274", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0275, "ALC275", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0276, "ALC276", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0280, "ALC280", patch_alc269),
@@ -6951,6 +7168,8 @@
 	HDA_CODEC_ENTRY(0x10ec0290, "ALC290", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0292, "ALC292", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0293, "ALC293", patch_alc269),
+	HDA_CODEC_ENTRY(0x10ec0294, "ALC294", patch_alc269),
+	HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
 	HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
 	HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
@@ -6966,6 +7185,9 @@
 	HDA_CODEC_ENTRY(0x10ec0670, "ALC670", patch_alc662),
 	HDA_CODEC_ENTRY(0x10ec0671, "ALC671", patch_alc662),
 	HDA_CODEC_ENTRY(0x10ec0680, "ALC680", patch_alc680),
+	HDA_CODEC_ENTRY(0x10ec0700, "ALC700", patch_alc269),
+	HDA_CODEC_ENTRY(0x10ec0701, "ALC701", patch_alc269),
+	HDA_CODEC_ENTRY(0x10ec0703, "ALC703", patch_alc269),
 	HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc882),
 	HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880),
 	HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882),
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 37b70f8..0abab79 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1537,6 +1537,8 @@
 		      "Dell Inspiron 1501", STAC_9200_DELL_M26),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6,
 		      "unknown Dell", STAC_9200_DELL_M26),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0201,
+		      "Dell Latitude D430", STAC_9200_DELL_M22),
 	/* Panasonic */
 	SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC),
 	/* Gateway machines needs EAPD to be set on resume */
diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c
index 0a4ad5f..12826ac 100644
--- a/sound/pci/hda/thinkpad_helper.c
+++ b/sound/pci/hda/thinkpad_helper.c
@@ -75,7 +75,7 @@
 			removefunc = false;
 		}
 		if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
-			if (spec->num_adc_nids > 1)
+			if (spec->num_adc_nids > 1 && !spec->dyn_adc_switch)
 				codec_dbg(codec,
 					  "Skipping micmute LED control due to several ADCs");
 			else {
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 09da7b5..1468e4b 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -991,6 +991,7 @@
 		if (err < 0)
 			return err;
 	}
+	master_vol = NULL;
 	if (pm7500)
 		err = build_mixers(chip,
 				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
index 8276675..78a9856 100644
--- a/sound/soc/atmel/atmel-classd.c
+++ b/sound/soc/atmel/atmel-classd.c
@@ -343,7 +343,7 @@
 }
 
 #define CLASSD_ACLK_RATE_11M2896_MPY_8 (112896 * 100 * 8)
-#define CLASSD_ACLK_RATE_12M288_MPY_8  (12228 * 1000 * 8)
+#define CLASSD_ACLK_RATE_12M288_MPY_8  (12288 * 1000 * 8)
 
 static struct {
 	int rate;
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index ba8def5..6726143 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -298,8 +298,9 @@
 	clk_enable(ssc_p->ssc->clk);
 	ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk);
 
-	/* Reset the SSC to keep it at a clean status */
-	ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
+	/* Reset the SSC unless initialized to keep it in a clean state */
+	if (!ssc_p->initialized)
+		ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		dir = 0;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index a7f71d1..cfdafc4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -67,7 +67,6 @@
 	select SND_SOC_ES8328_I2C if I2C
 	select SND_SOC_GTM601
 	select SND_SOC_ICS43432
-	select SND_SOC_INNO_RK3036
 	select SND_SOC_ISABELLE if I2C
 	select SND_SOC_JZ4740_CODEC
 	select SND_SOC_LM4857 if I2C
@@ -90,7 +89,6 @@
 	select SND_SOC_PCM512x_SPI if SPI_MASTER
 	select SND_SOC_RT286 if I2C
 	select SND_SOC_RT298 if I2C
-	select SND_SOC_RT5616 if I2C
 	select SND_SOC_RT5631 if I2C
 	select SND_SOC_RT5640 if I2C
 	select SND_SOC_RT5645 if I2C
@@ -473,10 +471,6 @@
 config SND_SOC_ICS43432
 	tristate
 
-config SND_SOC_INNO_RK3036
-	tristate "Inno codec driver for RK3036 SoC"
-	select REGMAP_MMIO
-
 config SND_SOC_ISABELLE
         tristate
 
@@ -529,13 +523,11 @@
 
 config SND_SOC_RL6231
 	tristate
-	default y if SND_SOC_RT5616=y
 	default y if SND_SOC_RT5640=y
 	default y if SND_SOC_RT5645=y
 	default y if SND_SOC_RT5651=y
 	default y if SND_SOC_RT5670=y
 	default y if SND_SOC_RT5677=y
-	default m if SND_SOC_RT5616=m
 	default m if SND_SOC_RT5640=m
 	default m if SND_SOC_RT5645=m
 	default m if SND_SOC_RT5651=m
@@ -557,9 +549,6 @@
 	tristate
 	depends on I2C
 
-config SND_SOC_RT5616
-	tristate "Realtek RT5616 CODEC"
-
 config SND_SOC_RT5631
 	tristate "Realtek ALC5631/RT5631 CODEC"
 	depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 09e3496..f632fc4 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -60,7 +60,6 @@
 snd-soc-es8328-spi-objs := es8328-spi.o
 snd-soc-gtm601-objs := gtm601.o
 snd-soc-ics43432-objs := ics43432.o
-snd-soc-inno-rk3036-objs := inno_rk3036.o
 snd-soc-isabelle-objs := isabelle.o
 snd-soc-jz4740-codec-objs := jz4740.o
 snd-soc-l3-objs := l3.o
@@ -86,7 +85,6 @@
 snd-soc-rl6347a-objs := rl6347a.o
 snd-soc-rt286-objs := rt286.o
 snd-soc-rt298-objs := rt298.o
-snd-soc-rt5616-objs := rt5616.o
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-rt5640-objs := rt5640.o
 snd-soc-rt5645-objs := rt5645.o
@@ -257,7 +255,6 @@
 obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
 obj-$(CONFIG_SND_SOC_GTM601)    += snd-soc-gtm601.o
 obj-$(CONFIG_SND_SOC_ICS43432)	+= snd-soc-ics43432.o
-obj-$(CONFIG_SND_SOC_INNO_RK3036)	+= snd-soc-inno-rk3036.o
 obj-$(CONFIG_SND_SOC_ISABELLE)	+= snd-soc-isabelle.o
 obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
 obj-$(CONFIG_SND_SOC_L3)	+= snd-soc-l3.o
@@ -283,7 +280,6 @@
 obj-$(CONFIG_SND_SOC_RL6347A)	+= snd-soc-rl6347a.o
 obj-$(CONFIG_SND_SOC_RT286)	+= snd-soc-rt286.o
 obj-$(CONFIG_SND_SOC_RT298)	+= snd-soc-rt298.o
-obj-$(CONFIG_SND_SOC_RT5616)	+= snd-soc-rt5616.o
 obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_RT5640)	+= snd-soc-rt5640.o
 obj-$(CONFIG_SND_SOC_RT5645)	+= snd-soc-rt5645.o
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index cda27c2..eb8fe21 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -560,6 +560,7 @@
 	.max_register		= FIL1_3,
 	.reg_defaults		= ak4642_reg,
 	.num_reg_defaults	= NUM_AK4642_REG_DEFAULTS,
+	.cache_type		= REGCACHE_RBTREE,
 };
 
 static const struct regmap_config ak4643_regmap = {
@@ -568,6 +569,7 @@
 	.max_register		= SPK_MS,
 	.reg_defaults		= ak4643_reg,
 	.num_reg_defaults	= ARRAY_SIZE(ak4643_reg),
+	.cache_type		= REGCACHE_RBTREE,
 };
 
 static const struct regmap_config ak4648_regmap = {
@@ -576,6 +578,7 @@
 	.max_register		= EQ_FBEQE,
 	.reg_defaults		= ak4648_reg,
 	.num_reg_defaults	= ARRAY_SIZE(ak4648_reg),
+	.cache_type		= REGCACHE_RBTREE,
 };
 
 static const struct ak4642_drvdata ak4642_drvdata = {
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index e07807d..3670086 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -148,11 +148,11 @@
 };
 
 static const struct snd_soc_dapm_route cs4270_dapm_routes[] = {
-	{ "Capture", NULL, "AINA" },
-	{ "Capture", NULL, "AINB" },
+	{ "Capture", NULL, "AINL" },
+	{ "Capture", NULL, "AINR" },
 
-	{ "AOUTA", NULL, "Playback" },
-	{ "AOUTB", NULL, "Playback" },
+	{ "AOUTL", NULL, "Playback" },
+	{ "AOUTR", NULL, "Playback" },
 };
 
 /**
diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c
deleted file mode 100644
index 9b6e884..0000000
--- a/sound/soc/codecs/inno_rk3036.c
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Driver of Inno codec for rk3036 by Rockchip Inc.
- *
- * Author: Rockchip Inc.
- * Author: Zheng ShunQian<zhengsq@rock-chips.com>
- */
-
-#include <sound/soc.h>
-#include <sound/tlv.h>
-#include <sound/soc-dapm.h>
-#include <sound/soc-dai.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/regmap.h>
-#include <linux/device.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/io.h>
-
-#include "inno_rk3036.h"
-
-struct rk3036_codec_priv {
-	void __iomem *base;
-	struct clk *pclk;
-	struct regmap *regmap;
-	struct device *dev;
-};
-
-static const DECLARE_TLV_DB_MINMAX(rk3036_codec_hp_tlv, -39, 0);
-
-static int rk3036_codec_antipop_info(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_info *uinfo)
-{
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 2;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 1;
-
-	return 0;
-}
-
-static int rk3036_codec_antipop_get(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	int val, ret, regval;
-
-	ret = snd_soc_component_read(component, INNO_R09, &regval);
-	if (ret)
-		return ret;
-	val = ((regval >> INNO_R09_HPL_ANITPOP_SHIFT) &
-	       INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON;
-	ucontrol->value.integer.value[0] = val;
-
-	val = ((regval >> INNO_R09_HPR_ANITPOP_SHIFT) &
-	       INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON;
-	ucontrol->value.integer.value[1] = val;
-
-	return 0;
-}
-
-static int rk3036_codec_antipop_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	int val, ret, regmsk;
-
-	val = (ucontrol->value.integer.value[0] ?
-	       INNO_R09_HP_ANTIPOP_ON : INNO_R09_HP_ANTIPOP_OFF) <<
-	      INNO_R09_HPL_ANITPOP_SHIFT;
-	val |= (ucontrol->value.integer.value[1] ?
-		INNO_R09_HP_ANTIPOP_ON : INNO_R09_HP_ANTIPOP_OFF) <<
-	       INNO_R09_HPR_ANITPOP_SHIFT;
-
-	regmsk = INNO_R09_HP_ANTIPOP_MSK << INNO_R09_HPL_ANITPOP_SHIFT |
-		 INNO_R09_HP_ANTIPOP_MSK << INNO_R09_HPR_ANITPOP_SHIFT;
-
-	ret = snd_soc_component_update_bits(component, INNO_R09,
-					    regmsk, val);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-#define SOC_RK3036_CODEC_ANTIPOP_DECL(xname) \
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-	.info = rk3036_codec_antipop_info, .get = rk3036_codec_antipop_get, \
-	.put = rk3036_codec_antipop_put, }
-
-static const struct snd_kcontrol_new rk3036_codec_dapm_controls[] = {
-	SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", INNO_R07, INNO_R08,
-		INNO_HP_GAIN_SHIFT, INNO_HP_GAIN_N39DB,
-		INNO_HP_GAIN_0DB, 0, rk3036_codec_hp_tlv),
-	SOC_DOUBLE("Zero Cross Switch", INNO_R06, INNO_R06_VOUTL_CZ_SHIFT,
-		INNO_R06_VOUTR_CZ_SHIFT, 1, 0),
-	SOC_DOUBLE("Headphone Switch", INNO_R09, INNO_R09_HPL_MUTE_SHIFT,
-		INNO_R09_HPR_MUTE_SHIFT, 1, 0),
-	SOC_RK3036_CODEC_ANTIPOP_DECL("Anti-pop Switch"),
-};
-
-static const struct snd_kcontrol_new rk3036_codec_hpl_mixer_controls[] = {
-	SOC_DAPM_SINGLE("DAC Left Out Switch", INNO_R09,
-			INNO_R09_DACL_SWITCH_SHIFT, 1, 0),
-};
-
-static const struct snd_kcontrol_new rk3036_codec_hpr_mixer_controls[] = {
-	SOC_DAPM_SINGLE("DAC Right Out Switch", INNO_R09,
-			INNO_R09_DACR_SWITCH_SHIFT, 1, 0),
-};
-
-static const struct snd_kcontrol_new rk3036_codec_hpl_switch_controls[] = {
-	SOC_DAPM_SINGLE("HP Left Out Switch", INNO_R05,
-			INNO_R05_HPL_WORK_SHIFT, 1, 0),
-};
-
-static const struct snd_kcontrol_new rk3036_codec_hpr_switch_controls[] = {
-	SOC_DAPM_SINGLE("HP Right Out Switch", INNO_R05,
-			INNO_R05_HPR_WORK_SHIFT, 1, 0),
-};
-
-static const struct snd_soc_dapm_widget rk3036_codec_dapm_widgets[] = {
-	SND_SOC_DAPM_SUPPLY_S("DAC PWR", 1, INNO_R06,
-			      INNO_R06_DAC_EN_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACL VREF", 2, INNO_R04,
-			      INNO_R04_DACL_VREF_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACR VREF", 2, INNO_R04,
-			      INNO_R04_DACR_VREF_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACL HiLo VREF", 3, INNO_R06,
-			      INNO_R06_DACL_HILO_VREF_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACR HiLo VREF", 3, INNO_R06,
-			      INNO_R06_DACR_HILO_VREF_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACR CLK", 3, INNO_R04,
-			      INNO_R04_DACR_CLK_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY_S("DACL CLK", 3, INNO_R04,
-			      INNO_R04_DACL_CLK_SHIFT, 0, NULL, 0),
-
-	SND_SOC_DAPM_DAC("DACL", "Left Playback", INNO_R04,
-			 INNO_R04_DACL_SW_SHIFT, 0),
-	SND_SOC_DAPM_DAC("DACR", "Right Playback", INNO_R04,
-			 INNO_R04_DACR_SW_SHIFT, 0),
-
-	SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
-		rk3036_codec_hpl_mixer_controls,
-		ARRAY_SIZE(rk3036_codec_hpl_mixer_controls)),
-	SND_SOC_DAPM_MIXER("Right Headphone Mixer", SND_SOC_NOPM, 0, 0,
-		rk3036_codec_hpr_mixer_controls,
-		ARRAY_SIZE(rk3036_codec_hpr_mixer_controls)),
-
-	SND_SOC_DAPM_PGA("HP Left Out", INNO_R05,
-			 INNO_R05_HPL_EN_SHIFT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HP Right Out", INNO_R05,
-			 INNO_R05_HPR_EN_SHIFT, 0, NULL, 0),
-
-	SND_SOC_DAPM_MIXER("HP Left Switch",  SND_SOC_NOPM, 0, 0,
-			   rk3036_codec_hpl_switch_controls,
-			   ARRAY_SIZE(rk3036_codec_hpl_switch_controls)),
-	SND_SOC_DAPM_MIXER("HP Right Switch",  SND_SOC_NOPM, 0, 0,
-			   rk3036_codec_hpr_switch_controls,
-			   ARRAY_SIZE(rk3036_codec_hpr_switch_controls)),
-
-	SND_SOC_DAPM_OUTPUT("HPL"),
-	SND_SOC_DAPM_OUTPUT("HPR"),
-};
-
-static const struct snd_soc_dapm_route rk3036_codec_dapm_routes[] = {
-	{"DACL VREF", NULL, "DAC PWR"},
-	{"DACR VREF", NULL, "DAC PWR"},
-	{"DACL HiLo VREF", NULL, "DAC PWR"},
-	{"DACR HiLo VREF", NULL, "DAC PWR"},
-	{"DACL CLK", NULL, "DAC PWR"},
-	{"DACR CLK", NULL, "DAC PWR"},
-
-	{"DACL", NULL, "DACL VREF"},
-	{"DACL", NULL, "DACL HiLo VREF"},
-	{"DACL", NULL, "DACL CLK"},
-	{"DACR", NULL, "DACR VREF"},
-	{"DACR", NULL, "DACR HiLo VREF"},
-	{"DACR", NULL, "DACR CLK"},
-
-	{"Left Headphone Mixer", "DAC Left Out Switch", "DACL"},
-	{"Right Headphone Mixer", "DAC Right Out Switch", "DACR"},
-	{"HP Left Out", NULL, "Left Headphone Mixer"},
-	{"HP Right Out", NULL, "Right Headphone Mixer"},
-
-	{"HP Left Switch", "HP Left Out Switch", "HP Left Out"},
-	{"HP Right Switch", "HP Right Out Switch", "HP Right Out"},
-
-	{"HPL", NULL, "HP Left Switch"},
-	{"HPR", NULL, "HP Right Switch"},
-};
-
-static int rk3036_codec_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
-	struct snd_soc_codec *codec = dai->codec;
-	unsigned int reg01_val = 0,  reg02_val = 0, reg03_val = 0;
-
-	dev_dbg(codec->dev, "rk3036_codec dai set fmt : %08x\n", fmt);
-
-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-	case SND_SOC_DAIFMT_CBS_CFS:
-		reg01_val |= INNO_R01_PINDIR_IN_SLAVE |
-			     INNO_R01_I2SMODE_SLAVE;
-		break;
-	case SND_SOC_DAIFMT_CBM_CFM:
-		reg01_val |= INNO_R01_PINDIR_OUT_MASTER |
-			     INNO_R01_I2SMODE_MASTER;
-		break;
-	default:
-		dev_err(codec->dev, "invalid fmt\n");
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_DSP_A:
-		reg02_val |= INNO_R02_DACM_PCM;
-		break;
-	case SND_SOC_DAIFMT_I2S:
-		reg02_val |= INNO_R02_DACM_I2S;
-		break;
-	case SND_SOC_DAIFMT_RIGHT_J:
-		reg02_val |= INNO_R02_DACM_RJM;
-		break;
-	case SND_SOC_DAIFMT_LEFT_J:
-		reg02_val |= INNO_R02_DACM_LJM;
-		break;
-	default:
-		dev_err(codec->dev, "set dai format failed\n");
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-	case SND_SOC_DAIFMT_NB_NF:
-		reg02_val |= INNO_R02_LRCP_NORMAL;
-		reg03_val |= INNO_R03_BCP_NORMAL;
-		break;
-	case SND_SOC_DAIFMT_IB_IF:
-		reg02_val |= INNO_R02_LRCP_REVERSAL;
-		reg03_val |= INNO_R03_BCP_REVERSAL;
-		break;
-	case SND_SOC_DAIFMT_IB_NF:
-		reg02_val |= INNO_R02_LRCP_REVERSAL;
-		reg03_val |= INNO_R03_BCP_NORMAL;
-		break;
-	case SND_SOC_DAIFMT_NB_IF:
-		reg02_val |= INNO_R02_LRCP_NORMAL;
-		reg03_val |= INNO_R03_BCP_REVERSAL;
-		break;
-	default:
-		dev_err(codec->dev, "set dai format failed\n");
-		return -EINVAL;
-	}
-
-	snd_soc_update_bits(codec, INNO_R01, INNO_R01_I2SMODE_MSK |
-			    INNO_R01_PINDIR_MSK, reg01_val);
-	snd_soc_update_bits(codec, INNO_R02, INNO_R02_LRCP_MSK |
-			    INNO_R02_DACM_MSK, reg02_val);
-	snd_soc_update_bits(codec, INNO_R03, INNO_R03_BCP_MSK, reg03_val);
-
-	return 0;
-}
-
-static int rk3036_codec_dai_hw_params(struct snd_pcm_substream *substream,
-				      struct snd_pcm_hw_params *hw_params,
-				      struct snd_soc_dai *dai)
-{
-	struct snd_soc_codec *codec = dai->codec;
-	unsigned int reg02_val = 0, reg03_val = 0;
-
-	switch (params_format(hw_params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-		reg02_val |= INNO_R02_VWL_16BIT;
-		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
-		reg02_val |= INNO_R02_VWL_20BIT;
-		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
-		reg02_val |= INNO_R02_VWL_24BIT;
-		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
-		reg02_val |= INNO_R02_VWL_32BIT;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	reg02_val |= INNO_R02_LRCP_NORMAL;
-	reg03_val |= INNO_R03_FWL_32BIT | INNO_R03_DACR_WORK;
-
-	snd_soc_update_bits(codec, INNO_R02, INNO_R02_LRCP_MSK |
-			    INNO_R02_VWL_MSK, reg02_val);
-	snd_soc_update_bits(codec, INNO_R03, INNO_R03_DACR_MSK |
-			    INNO_R03_FWL_MSK, reg03_val);
-	return 0;
-}
-
-#define RK3036_CODEC_RATES (SNDRV_PCM_RATE_8000  | \
-			    SNDRV_PCM_RATE_16000 | \
-			    SNDRV_PCM_RATE_32000 | \
-			    SNDRV_PCM_RATE_44100 | \
-			    SNDRV_PCM_RATE_48000 | \
-			    SNDRV_PCM_RATE_96000)
-
-#define RK3036_CODEC_FMTS (SNDRV_PCM_FMTBIT_S16_LE  | \
-			   SNDRV_PCM_FMTBIT_S20_3LE | \
-			   SNDRV_PCM_FMTBIT_S24_LE  | \
-			   SNDRV_PCM_FMTBIT_S32_LE)
-
-static struct snd_soc_dai_ops rk3036_codec_dai_ops = {
-	.set_fmt	= rk3036_codec_dai_set_fmt,
-	.hw_params	= rk3036_codec_dai_hw_params,
-};
-
-static struct snd_soc_dai_driver rk3036_codec_dai_driver[] = {
-	{
-		.name = "rk3036-codec-dai",
-		.playback = {
-			.stream_name = "Playback",
-			.channels_min = 1,
-			.channels_max = 2,
-			.rates = RK3036_CODEC_RATES,
-			.formats = RK3036_CODEC_FMTS,
-		},
-		.ops = &rk3036_codec_dai_ops,
-		.symmetric_rates = 1,
-	},
-};
-
-static void rk3036_codec_reset(struct snd_soc_codec *codec)
-{
-	snd_soc_write(codec, INNO_R00,
-		      INNO_R00_CSR_RESET | INNO_R00_CDCR_RESET);
-	snd_soc_write(codec, INNO_R00,
-		      INNO_R00_CSR_WORK | INNO_R00_CDCR_WORK);
-}
-
-static int rk3036_codec_probe(struct snd_soc_codec *codec)
-{
-	rk3036_codec_reset(codec);
-	return 0;
-}
-
-static int rk3036_codec_remove(struct snd_soc_codec *codec)
-{
-	rk3036_codec_reset(codec);
-	return 0;
-}
-
-static int rk3036_codec_set_bias_level(struct snd_soc_codec *codec,
-				       enum snd_soc_bias_level level)
-{
-	switch (level) {
-	case SND_SOC_BIAS_STANDBY:
-		/* set a big current for capacitor charging. */
-		snd_soc_write(codec, INNO_R10, INNO_R10_MAX_CUR);
-		/* start precharge */
-		snd_soc_write(codec, INNO_R06, INNO_R06_DAC_PRECHARGE);
-
-		break;
-
-	case SND_SOC_BIAS_OFF:
-		/* set a big current for capacitor discharging. */
-		snd_soc_write(codec, INNO_R10, INNO_R10_MAX_CUR);
-		/* start discharge. */
-		snd_soc_write(codec, INNO_R06, INNO_R06_DAC_DISCHARGE);
-
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static struct snd_soc_codec_driver rk3036_codec_driver = {
-	.probe			= rk3036_codec_probe,
-	.remove			= rk3036_codec_remove,
-	.set_bias_level		= rk3036_codec_set_bias_level,
-	.controls		= rk3036_codec_dapm_controls,
-	.num_controls		= ARRAY_SIZE(rk3036_codec_dapm_controls),
-	.dapm_routes		= rk3036_codec_dapm_routes,
-	.num_dapm_routes	= ARRAY_SIZE(rk3036_codec_dapm_routes),
-	.dapm_widgets		= rk3036_codec_dapm_widgets,
-	.num_dapm_widgets	= ARRAY_SIZE(rk3036_codec_dapm_widgets),
-};
-
-static const struct regmap_config rk3036_codec_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-};
-
-#define GRF_SOC_CON0		0x00140
-#define GRF_ACODEC_SEL		(BIT(10) | BIT(16 + 10))
-
-static int rk3036_codec_platform_probe(struct platform_device *pdev)
-{
-	struct rk3036_codec_priv *priv;
-	struct device_node *of_node = pdev->dev.of_node;
-	struct resource *res;
-	void __iomem *base;
-	struct regmap *grf;
-	int ret;
-
-	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	priv->base = base;
-	priv->regmap = devm_regmap_init_mmio(&pdev->dev, priv->base,
-					     &rk3036_codec_regmap_config);
-	if (IS_ERR(priv->regmap)) {
-		dev_err(&pdev->dev, "init regmap failed\n");
-		return PTR_ERR(priv->regmap);
-	}
-
-	grf = syscon_regmap_lookup_by_phandle(of_node, "rockchip,grf");
-	if (IS_ERR(grf)) {
-		dev_err(&pdev->dev, "needs 'rockchip,grf' property\n");
-		return PTR_ERR(grf);
-	}
-	ret = regmap_write(grf, GRF_SOC_CON0, GRF_ACODEC_SEL);
-	if (ret) {
-		dev_err(&pdev->dev, "Could not write to GRF: %d\n", ret);
-		return ret;
-	}
-
-	priv->pclk = devm_clk_get(&pdev->dev, "acodec_pclk");
-	if (IS_ERR(priv->pclk))
-		return PTR_ERR(priv->pclk);
-
-	ret = clk_prepare_enable(priv->pclk);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to enable clk\n");
-		return ret;
-	}
-
-	priv->dev = &pdev->dev;
-	dev_set_drvdata(&pdev->dev, priv);
-
-	ret = snd_soc_register_codec(&pdev->dev, &rk3036_codec_driver,
-				     rk3036_codec_dai_driver,
-				     ARRAY_SIZE(rk3036_codec_dai_driver));
-	if (ret) {
-		clk_disable_unprepare(priv->pclk);
-		dev_set_drvdata(&pdev->dev, NULL);
-	}
-
-	return ret;
-}
-
-static int rk3036_codec_platform_remove(struct platform_device *pdev)
-{
-	struct rk3036_codec_priv *priv = dev_get_drvdata(&pdev->dev);
-
-	snd_soc_unregister_codec(&pdev->dev);
-	clk_disable_unprepare(priv->pclk);
-
-	return 0;
-}
-
-static const struct of_device_id rk3036_codec_of_match[] = {
-	{ .compatible = "rockchip,rk3036-codec", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, rk3036_codec_of_match);
-
-static struct platform_driver rk3036_codec_platform_driver = {
-	.driver = {
-		.name = "rk3036-codec-platform",
-		.of_match_table = of_match_ptr(rk3036_codec_of_match),
-	},
-	.probe = rk3036_codec_platform_probe,
-	.remove = rk3036_codec_platform_remove,
-};
-
-module_platform_driver(rk3036_codec_platform_driver);
-
-MODULE_AUTHOR("Rockchip Inc.");
-MODULE_DESCRIPTION("Rockchip rk3036 codec driver");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/inno_rk3036.h b/sound/soc/codecs/inno_rk3036.h
deleted file mode 100644
index da759c6..0000000
--- a/sound/soc/codecs/inno_rk3036.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Driver of Inno Codec for rk3036 by Rockchip Inc.
- *
- * Author: Zheng ShunQian<zhengsq@rock-chips.com>
- */
-
-#ifndef _INNO_RK3036_CODEC_H
-#define _INNO_RK3036_CODEC_H
-
-/* codec registers */
-#define INNO_R00	0x00
-#define INNO_R01	0x0c
-#define INNO_R02	0x10
-#define INNO_R03	0x14
-#define INNO_R04	0x88
-#define INNO_R05	0x8c
-#define INNO_R06	0x90
-#define INNO_R07	0x94
-#define INNO_R08	0x98
-#define INNO_R09	0x9c
-#define INNO_R10	0xa0
-
-/* register bit filed */
-#define INNO_R00_CSR_RESET		(0x0 << 0) /*codec system reset*/
-#define INNO_R00_CSR_WORK		(0x1 << 0)
-#define INNO_R00_CDCR_RESET		(0x0 << 1) /*codec digital core reset*/
-#define INNO_R00_CDCR_WORK		(0x1 << 1)
-#define INNO_R00_PRB_DISABLE		(0x0 << 6) /*power reset bypass*/
-#define INNO_R00_PRB_ENABLE		(0x1 << 6)
-
-#define INNO_R01_I2SMODE_MSK		(0x1 << 4)
-#define INNO_R01_I2SMODE_SLAVE		(0x0 << 4)
-#define INNO_R01_I2SMODE_MASTER		(0x1 << 4)
-#define INNO_R01_PINDIR_MSK		(0x1 << 5)
-#define INNO_R01_PINDIR_IN_SLAVE	(0x0 << 5) /*direction of pin*/
-#define INNO_R01_PINDIR_OUT_MASTER	(0x1 << 5)
-
-#define INNO_R02_LRS_MSK		(0x1 << 2)
-#define INNO_R02_LRS_NORMAL		(0x0 << 2) /*DAC Left Right Swap*/
-#define INNO_R02_LRS_SWAP		(0x1 << 2)
-#define INNO_R02_DACM_MSK		(0x3 << 3)
-#define INNO_R02_DACM_PCM		(0x3 << 3) /*DAC Mode*/
-#define INNO_R02_DACM_I2S		(0x2 << 3)
-#define INNO_R02_DACM_LJM		(0x1 << 3)
-#define INNO_R02_DACM_RJM		(0x0 << 3)
-#define INNO_R02_VWL_MSK		(0x3 << 5)
-#define INNO_R02_VWL_32BIT		(0x3 << 5) /*1/2Frame Valid Word Len*/
-#define INNO_R02_VWL_24BIT		(0x2 << 5)
-#define INNO_R02_VWL_20BIT		(0x1 << 5)
-#define INNO_R02_VWL_16BIT		(0x0 << 5)
-#define INNO_R02_LRCP_MSK		(0x1 << 7)
-#define INNO_R02_LRCP_NORMAL		(0x0 << 7) /*Left Right Polarity*/
-#define INNO_R02_LRCP_REVERSAL		(0x1 << 7)
-
-#define INNO_R03_BCP_MSK		(0x1 << 0)
-#define INNO_R03_BCP_NORMAL		(0x0 << 0) /*DAC bit clock polarity*/
-#define INNO_R03_BCP_REVERSAL		(0x1 << 0)
-#define INNO_R03_DACR_MSK		(0x1 << 1)
-#define INNO_R03_DACR_RESET		(0x0 << 1) /*DAC Reset*/
-#define INNO_R03_DACR_WORK		(0x1 << 1)
-#define INNO_R03_FWL_MSK		(0x3 << 2)
-#define INNO_R03_FWL_32BIT		(0x3 << 2) /*1/2Frame Word Length*/
-#define INNO_R03_FWL_24BIT		(0x2 << 2)
-#define INNO_R03_FWL_20BIT		(0x1 << 2)
-#define INNO_R03_FWL_16BIT		(0x0 << 2)
-
-#define INNO_R04_DACR_SW_SHIFT		0
-#define INNO_R04_DACL_SW_SHIFT		1
-#define INNO_R04_DACR_CLK_SHIFT		2
-#define INNO_R04_DACL_CLK_SHIFT		3
-#define INNO_R04_DACR_VREF_SHIFT	4
-#define INNO_R04_DACL_VREF_SHIFT	5
-
-#define INNO_R05_HPR_EN_SHIFT		0
-#define INNO_R05_HPL_EN_SHIFT		1
-#define INNO_R05_HPR_WORK_SHIFT		2
-#define INNO_R05_HPL_WORK_SHIFT		3
-
-#define INNO_R06_VOUTR_CZ_SHIFT		0
-#define INNO_R06_VOUTL_CZ_SHIFT		1
-#define INNO_R06_DACR_HILO_VREF_SHIFT	2
-#define INNO_R06_DACL_HILO_VREF_SHIFT	3
-#define INNO_R06_DAC_EN_SHIFT		5
-
-#define INNO_R06_DAC_PRECHARGE		(0x0 << 4) /*PreCharge control for DAC*/
-#define INNO_R06_DAC_DISCHARGE		(0x1 << 4)
-
-#define INNO_HP_GAIN_SHIFT		0
-/* Gain of output, 1.5db step: -39db(0x0) ~ 0db(0x1a) ~ 6db(0x1f) */
-#define INNO_HP_GAIN_0DB		0x1a
-#define INNO_HP_GAIN_N39DB		0x0
-
-#define INNO_R09_HP_ANTIPOP_MSK		0x3
-#define INNO_R09_HP_ANTIPOP_OFF		0x1
-#define INNO_R09_HP_ANTIPOP_ON		0x2
-#define INNO_R09_HPR_ANITPOP_SHIFT	0
-#define INNO_R09_HPL_ANITPOP_SHIFT	2
-#define INNO_R09_HPR_MUTE_SHIFT		4
-#define INNO_R09_HPL_MUTE_SHIFT		5
-#define INNO_R09_DACR_SWITCH_SHIFT	6
-#define INNO_R09_DACL_SWITCH_SHIFT	7
-
-#define INNO_R10_CHARGE_SEL_CUR_400I_YES	(0x0 << 0)
-#define INNO_R10_CHARGE_SEL_CUR_400I_NO		(0x1 << 0)
-#define INNO_R10_CHARGE_SEL_CUR_260I_YES	(0x0 << 1)
-#define INNO_R10_CHARGE_SEL_CUR_260I_NO		(0x1 << 1)
-#define INNO_R10_CHARGE_SEL_CUR_130I_YES	(0x0 << 2)
-#define INNO_R10_CHARGE_SEL_CUR_130I_NO		(0x1 << 2)
-#define INNO_R10_CHARGE_SEL_CUR_100I_YES	(0x0 << 3)
-#define INNO_R10_CHARGE_SEL_CUR_100I_NO		(0x1 << 3)
-#define INNO_R10_CHARGE_SEL_CUR_050I_YES	(0x0 << 4)
-#define INNO_R10_CHARGE_SEL_CUR_050I_NO		(0x1 << 4)
-#define INNO_R10_CHARGE_SEL_CUR_027I_YES	(0x0 << 5)
-#define INNO_R10_CHARGE_SEL_CUR_027I_NO		(0x1 << 5)
-
-#define INNO_R10_MAX_CUR (INNO_R10_CHARGE_SEL_CUR_400I_YES | \
-			  INNO_R10_CHARGE_SEL_CUR_260I_YES | \
-			  INNO_R10_CHARGE_SEL_CUR_130I_YES | \
-			  INNO_R10_CHARGE_SEL_CUR_100I_YES | \
-			  INNO_R10_CHARGE_SEL_CUR_050I_YES | \
-			  INNO_R10_CHARGE_SEL_CUR_027I_YES)
-
-#endif
diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c
deleted file mode 100644
index 3704d07..0000000
--- a/sound/soc/codecs/rt5616.c
+++ /dev/null
@@ -1,1421 +0,0 @@
-/*
- * rt5616.c  --  RT5616 ALSA SoC audio codec driver
- *
- * Copyright 2015 Realtek Semiconductor Corp.
- * Author: Bard Liao <bardliao@realtek.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/initval.h>
-#include <sound/tlv.h>
-
-#include "rl6231.h"
-#include "rt5616.h"
-
-#define RT5616_PR_RANGE_BASE (0xff + 1)
-#define RT5616_PR_SPACING 0x100
-
-#define RT5616_PR_BASE (RT5616_PR_RANGE_BASE + (0 * RT5616_PR_SPACING))
-
-static const struct regmap_range_cfg rt5616_ranges[] = {
-	{
-		.name = "PR",
-		.range_min = RT5616_PR_BASE,
-		.range_max = RT5616_PR_BASE + 0xf8,
-		.selector_reg = RT5616_PRIV_INDEX,
-		.selector_mask = 0xff,
-		.selector_shift = 0x0,
-		.window_start = RT5616_PRIV_DATA,
-		.window_len = 0x1,
-	},
-};
-
-static const struct reg_sequence init_list[] = {
-	{RT5616_PR_BASE + 0x3d,	0x3e00},
-	{RT5616_PR_BASE + 0x25,	0x6110},
-	{RT5616_PR_BASE + 0x20,	0x611f},
-	{RT5616_PR_BASE + 0x21,	0x4040},
-	{RT5616_PR_BASE + 0x23,	0x0004},
-};
-
-#define RT5616_INIT_REG_LEN ARRAY_SIZE(init_list)
-
-static const struct reg_default rt5616_reg[] = {
-	{ 0x00, 0x0021 },
-	{ 0x02, 0xc8c8 },
-	{ 0x03, 0xc8c8 },
-	{ 0x05, 0x0000 },
-	{ 0x0d, 0x0000 },
-	{ 0x0f, 0x0808 },
-	{ 0x19, 0xafaf },
-	{ 0x1c, 0x2f2f },
-	{ 0x1e, 0x0000 },
-	{ 0x27, 0x7860 },
-	{ 0x29, 0x8080 },
-	{ 0x2a, 0x5252 },
-	{ 0x3b, 0x0000 },
-	{ 0x3c, 0x006f },
-	{ 0x3d, 0x0000 },
-	{ 0x3e, 0x006f },
-	{ 0x45, 0x6000 },
-	{ 0x4d, 0x0000 },
-	{ 0x4e, 0x0000 },
-	{ 0x4f, 0x0279 },
-	{ 0x50, 0x0000 },
-	{ 0x51, 0x0000 },
-	{ 0x52, 0x0279 },
-	{ 0x53, 0xf000 },
-	{ 0x61, 0x0000 },
-	{ 0x62, 0x0000 },
-	{ 0x63, 0x00c0 },
-	{ 0x64, 0x0000 },
-	{ 0x65, 0x0000 },
-	{ 0x66, 0x0000 },
-	{ 0x70, 0x8000 },
-	{ 0x73, 0x1104 },
-	{ 0x74, 0x0c00 },
-	{ 0x80, 0x0000 },
-	{ 0x81, 0x0000 },
-	{ 0x82, 0x0000 },
-	{ 0x8b, 0x0600 },
-	{ 0x8e, 0x0004 },
-	{ 0x8f, 0x1100 },
-	{ 0x90, 0x0000 },
-	{ 0x91, 0x0000 },
-	{ 0x92, 0x0000 },
-	{ 0x93, 0x2000 },
-	{ 0x94, 0x0200 },
-	{ 0x95, 0x0000 },
-	{ 0xb0, 0x2080 },
-	{ 0xb1, 0x0000 },
-	{ 0xb2, 0x0000 },
-	{ 0xb4, 0x2206 },
-	{ 0xb5, 0x1f00 },
-	{ 0xb6, 0x0000 },
-	{ 0xb7, 0x0000 },
-	{ 0xbb, 0x0000 },
-	{ 0xbc, 0x0000 },
-	{ 0xbd, 0x0000 },
-	{ 0xbe, 0x0000 },
-	{ 0xbf, 0x0000 },
-	{ 0xc0, 0x0100 },
-	{ 0xc1, 0x0000 },
-	{ 0xc2, 0x0000 },
-	{ 0xc8, 0x0000 },
-	{ 0xc9, 0x0000 },
-	{ 0xca, 0x0000 },
-	{ 0xcb, 0x0000 },
-	{ 0xcc, 0x0000 },
-	{ 0xcd, 0x0000 },
-	{ 0xce, 0x0000 },
-	{ 0xcf, 0x0013 },
-	{ 0xd0, 0x0680 },
-	{ 0xd1, 0x1c17 },
-	{ 0xd3, 0xb320 },
-	{ 0xd4, 0x0000 },
-	{ 0xd6, 0x0000 },
-	{ 0xd7, 0x0000 },
-	{ 0xd9, 0x0809 },
-	{ 0xda, 0x0000 },
-	{ 0xfa, 0x0010 },
-	{ 0xfb, 0x0000 },
-	{ 0xfc, 0x0000 },
-	{ 0xfe, 0x10ec },
-	{ 0xff, 0x6281 },
-};
-
-struct rt5616_priv {
-	struct snd_soc_codec *codec;
-	struct delayed_work patch_work;
-	struct regmap *regmap;
-	struct clk *mclk;
-
-	int sysclk;
-	int sysclk_src;
-	int lrck[RT5616_AIFS];
-	int bclk[RT5616_AIFS];
-	int master[RT5616_AIFS];
-
-	int pll_src;
-	int pll_in;
-	int pll_out;
-
-};
-
-static bool rt5616_volatile_register(struct device *dev, unsigned int reg)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(rt5616_ranges); i++) {
-		if (reg >= rt5616_ranges[i].range_min &&
-		    reg <= rt5616_ranges[i].range_max)
-			return true;
-	}
-
-	switch (reg) {
-	case RT5616_RESET:
-	case RT5616_PRIV_DATA:
-	case RT5616_EQ_CTRL1:
-	case RT5616_DRC_AGC_1:
-	case RT5616_IRQ_CTRL2:
-	case RT5616_INT_IRQ_ST:
-	case RT5616_PGM_REG_ARR1:
-	case RT5616_PGM_REG_ARR3:
-	case RT5616_VENDOR_ID:
-	case RT5616_DEVICE_ID:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static bool rt5616_readable_register(struct device *dev, unsigned int reg)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(rt5616_ranges); i++) {
-		if (reg >= rt5616_ranges[i].range_min &&
-		    reg <= rt5616_ranges[i].range_max)
-			return true;
-	}
-
-	switch (reg) {
-	case RT5616_RESET:
-	case RT5616_VERSION_ID:
-	case RT5616_VENDOR_ID:
-	case RT5616_DEVICE_ID:
-	case RT5616_HP_VOL:
-	case RT5616_LOUT_CTRL1:
-	case RT5616_LOUT_CTRL2:
-	case RT5616_IN1_IN2:
-	case RT5616_INL1_INR1_VOL:
-	case RT5616_DAC1_DIG_VOL:
-	case RT5616_ADC_DIG_VOL:
-	case RT5616_ADC_BST_VOL:
-	case RT5616_STO1_ADC_MIXER:
-	case RT5616_AD_DA_MIXER:
-	case RT5616_STO_DAC_MIXER:
-	case RT5616_REC_L1_MIXER:
-	case RT5616_REC_L2_MIXER:
-	case RT5616_REC_R1_MIXER:
-	case RT5616_REC_R2_MIXER:
-	case RT5616_HPO_MIXER:
-	case RT5616_OUT_L1_MIXER:
-	case RT5616_OUT_L2_MIXER:
-	case RT5616_OUT_L3_MIXER:
-	case RT5616_OUT_R1_MIXER:
-	case RT5616_OUT_R2_MIXER:
-	case RT5616_OUT_R3_MIXER:
-	case RT5616_LOUT_MIXER:
-	case RT5616_PWR_DIG1:
-	case RT5616_PWR_DIG2:
-	case RT5616_PWR_ANLG1:
-	case RT5616_PWR_ANLG2:
-	case RT5616_PWR_MIXER:
-	case RT5616_PWR_VOL:
-	case RT5616_PRIV_INDEX:
-	case RT5616_PRIV_DATA:
-	case RT5616_I2S1_SDP:
-	case RT5616_ADDA_CLK1:
-	case RT5616_ADDA_CLK2:
-	case RT5616_GLB_CLK:
-	case RT5616_PLL_CTRL1:
-	case RT5616_PLL_CTRL2:
-	case RT5616_HP_OVCD:
-	case RT5616_DEPOP_M1:
-	case RT5616_DEPOP_M2:
-	case RT5616_DEPOP_M3:
-	case RT5616_CHARGE_PUMP:
-	case RT5616_PV_DET_SPK_G:
-	case RT5616_MICBIAS:
-	case RT5616_A_JD_CTL1:
-	case RT5616_A_JD_CTL2:
-	case RT5616_EQ_CTRL1:
-	case RT5616_EQ_CTRL2:
-	case RT5616_WIND_FILTER:
-	case RT5616_DRC_AGC_1:
-	case RT5616_DRC_AGC_2:
-	case RT5616_DRC_AGC_3:
-	case RT5616_SVOL_ZC:
-	case RT5616_JD_CTRL1:
-	case RT5616_JD_CTRL2:
-	case RT5616_IRQ_CTRL1:
-	case RT5616_IRQ_CTRL2:
-	case RT5616_INT_IRQ_ST:
-	case RT5616_GPIO_CTRL1:
-	case RT5616_GPIO_CTRL2:
-	case RT5616_GPIO_CTRL3:
-	case RT5616_PGM_REG_ARR1:
-	case RT5616_PGM_REG_ARR2:
-	case RT5616_PGM_REG_ARR3:
-	case RT5616_PGM_REG_ARR4:
-	case RT5616_PGM_REG_ARR5:
-	case RT5616_SCB_FUNC:
-	case RT5616_SCB_CTRL:
-	case RT5616_BASE_BACK:
-	case RT5616_MP3_PLUS1:
-	case RT5616_MP3_PLUS2:
-	case RT5616_ADJ_HPF_CTRL1:
-	case RT5616_ADJ_HPF_CTRL2:
-	case RT5616_HP_CALIB_AMP_DET:
-	case RT5616_HP_CALIB2:
-	case RT5616_SV_ZCD1:
-	case RT5616_SV_ZCD2:
-	case RT5616_D_MISC:
-	case RT5616_DUMMY2:
-	case RT5616_DUMMY3:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
-static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
-static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
-static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
-static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
-
-/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
-static unsigned int bst_tlv[] = {
-	TLV_DB_RANGE_HEAD(7),
-	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
-	1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
-	2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
-	3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
-	6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
-	7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
-	8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
-};
-
-static const struct snd_kcontrol_new rt5616_snd_controls[] = {
-	/* Headphone Output Volume */
-	SOC_DOUBLE("HP Playback Switch", RT5616_HP_VOL,
-		   RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1),
-	SOC_DOUBLE_TLV("HP Playback Volume", RT5616_HP_VOL,
-		       RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv),
-	/* OUTPUT Control */
-	SOC_DOUBLE("OUT Playback Switch", RT5616_LOUT_CTRL1,
-		   RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1),
-	SOC_DOUBLE("OUT Channel Switch", RT5616_LOUT_CTRL1,
-		   RT5616_VOL_L_SFT, RT5616_VOL_R_SFT, 1, 1),
-	SOC_DOUBLE_TLV("OUT Playback Volume", RT5616_LOUT_CTRL1,
-		       RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv),
-
-	/* DAC Digital Volume */
-	SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5616_DAC1_DIG_VOL,
-		       RT5616_L_VOL_SFT, RT5616_R_VOL_SFT,
-		       175, 0, dac_vol_tlv),
-	/* IN1/IN2 Control */
-	SOC_SINGLE_TLV("IN1 Boost Volume", RT5616_IN1_IN2,
-		       RT5616_BST_SFT1, 8, 0, bst_tlv),
-	SOC_SINGLE_TLV("IN2 Boost Volume", RT5616_IN1_IN2,
-		       RT5616_BST_SFT2, 8, 0, bst_tlv),
-	/* INL/INR Volume Control */
-	SOC_DOUBLE_TLV("IN Capture Volume", RT5616_INL1_INR1_VOL,
-		       RT5616_INL_VOL_SFT, RT5616_INR_VOL_SFT,
-		       31, 1, in_vol_tlv),
-	/* ADC Digital Volume Control */
-	SOC_DOUBLE("ADC Capture Switch", RT5616_ADC_DIG_VOL,
-		   RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1),
-	SOC_DOUBLE_TLV("ADC Capture Volume", RT5616_ADC_DIG_VOL,
-		       RT5616_L_VOL_SFT, RT5616_R_VOL_SFT,
-		       127, 0, adc_vol_tlv),
-
-	/* ADC Boost Volume Control */
-	SOC_DOUBLE_TLV("ADC Boost Volume", RT5616_ADC_BST_VOL,
-		       RT5616_ADC_L_BST_SFT, RT5616_ADC_R_BST_SFT,
-		       3, 0, adc_bst_tlv),
-};
-
-static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
-			       struct snd_soc_dapm_widget *sink)
-{
-	unsigned int val;
-
-	val = snd_soc_read(snd_soc_dapm_to_codec(source->dapm), RT5616_GLB_CLK);
-	val &= RT5616_SCLK_SRC_MASK;
-	if (val == RT5616_SCLK_SRC_PLL1)
-		return 1;
-	else
-		return 0;
-}
-
-/* Digital Mixer */
-static const struct snd_kcontrol_new rt5616_sto1_adc_l_mix[] = {
-	SOC_DAPM_SINGLE("ADC1 Switch", RT5616_STO1_ADC_MIXER,
-			RT5616_M_STO1_ADC_L1_SFT, 1, 1),
-};
-
-static const struct snd_kcontrol_new rt5616_sto1_adc_r_mix[] = {
-	SOC_DAPM_SINGLE("ADC1 Switch", RT5616_STO1_ADC_MIXER,
-			RT5616_M_STO1_ADC_R1_SFT, 1, 1),
-};
-
-static const struct snd_kcontrol_new rt5616_dac_l_mix[] = {
-	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5616_AD_DA_MIXER,
-			RT5616_M_ADCMIX_L_SFT, 1, 1),
-	SOC_DAPM_SINGLE("INF1 Switch", RT5616_AD_DA_MIXER,
-			RT5616_M_IF1_DAC_L_SFT, 1, 1),
-};
-
-static const struct snd_kcontrol_new rt5616_dac_r_mix[] = {
-	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5616_AD_DA_MIXER,
-			RT5616_M_ADCMIX_R_SFT, 1, 1),
-	SOC_DAPM_SINGLE("INF1 Switch", RT5616_AD_DA_MIXER,
-			RT5616_M_IF1_DAC_R_SFT, 1, 1),
-};
-
-static const struct snd_kcontrol_new rt5616_sto_dac_l_mix[] = {
-	SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_STO_DAC_MIXER,
-			RT5616_M_DAC_L1_MIXL_SFT, 1, 1),
-	SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_STO_DAC_MIXER,
-			RT5616_M_DAC_R1_MIXL_SFT, 1, 1),
-};
-
-static const struct snd_kcontrol_new rt5616_sto_dac_r_mix[] = {
-	SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_STO_DAC_MIXER,
-			RT5616_M_DAC_R1_MIXR_SFT, 1, 1),
-	SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_STO_DAC_MIXER,
-			RT5616_M_DAC_L1_MIXR_SFT, 1, 1),
-};
-
-/* Analog Input Mixer */
-static const struct snd_kcontrol_new rt5616_rec_l_mix[] = {
-	SOC_DAPM_SINGLE("INL1 Switch", RT5616_REC_L2_MIXER,
-			RT5616_M_IN1_L_RM_L_SFT, 1, 1),
-	SOC_DAPM_SINGLE("BST2 Switch", RT5616_REC_L2_MIXER,
-			RT5616_M_BST2_RM_L_SFT, 1, 1),
-	SOC_DAPM_SINGLE("BST1 Switch", RT5616_REC_L2_MIXER,
-			RT5616_M_BST1_RM_L_SFT, 1, 1),
-};
-
-static const struct snd_kcontrol_new rt5616_rec_r_mix[] = {
-	SOC_DAPM_SINGLE("INR1 Switch", RT5616_REC_R2_MIXER,
-			RT5616_M_IN1_R_RM_R_SFT, 1, 1),
-	SOC_DAPM_SINGLE("BST2 Switch", RT5616_REC_R2_MIXER,
-			RT5616_M_BST2_RM_R_SFT, 1, 1),
-	SOC_DAPM_SINGLE("BST1 Switch", RT5616_REC_R2_MIXER,
-			RT5616_M_BST1_RM_R_SFT, 1, 1),
-};
-
-/* Analog Output Mixer */
-
-static const struct snd_kcontrol_new rt5616_out_l_mix[] = {
-	SOC_DAPM_SINGLE("BST1 Switch", RT5616_OUT_L3_MIXER,
-			RT5616_M_BST1_OM_L_SFT, 1, 1),
-	SOC_DAPM_SINGLE("BST2 Switch", RT5616_OUT_L3_MIXER,
-			RT5616_M_BST2_OM_L_SFT, 1, 1),
-	SOC_DAPM_SINGLE("INL1 Switch", RT5616_OUT_L3_MIXER,
-			RT5616_M_IN1_L_OM_L_SFT, 1, 1),
-	SOC_DAPM_SINGLE("REC MIXL Switch", RT5616_OUT_L3_MIXER,
-			RT5616_M_RM_L_OM_L_SFT, 1, 1),
-	SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_OUT_L3_MIXER,
-			RT5616_M_DAC_L1_OM_L_SFT, 1, 1),
-};
-
-static const struct snd_kcontrol_new rt5616_out_r_mix[] = {
-	SOC_DAPM_SINGLE("BST2 Switch", RT5616_OUT_R3_MIXER,
-			RT5616_M_BST2_OM_R_SFT, 1, 1),
-	SOC_DAPM_SINGLE("BST1 Switch", RT5616_OUT_R3_MIXER,
-			RT5616_M_BST1_OM_R_SFT, 1, 1),
-	SOC_DAPM_SINGLE("INR1 Switch", RT5616_OUT_R3_MIXER,
-			RT5616_M_IN1_R_OM_R_SFT, 1, 1),
-	SOC_DAPM_SINGLE("REC MIXR Switch", RT5616_OUT_R3_MIXER,
-			RT5616_M_RM_R_OM_R_SFT, 1, 1),
-	SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_OUT_R3_MIXER,
-			RT5616_M_DAC_R1_OM_R_SFT, 1, 1),
-};
-
-static const struct snd_kcontrol_new rt5616_hpo_mix[] = {
-	SOC_DAPM_SINGLE("DAC1 Switch", RT5616_HPO_MIXER,
-			RT5616_M_DAC1_HM_SFT, 1, 1),
-	SOC_DAPM_SINGLE("HPVOL Switch", RT5616_HPO_MIXER,
-			RT5616_M_HPVOL_HM_SFT, 1, 1),
-};
-
-static const struct snd_kcontrol_new rt5616_lout_mix[] = {
-	SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_LOUT_MIXER,
-			RT5616_M_DAC_L1_LM_SFT, 1, 1),
-	SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_LOUT_MIXER,
-			RT5616_M_DAC_R1_LM_SFT, 1, 1),
-	SOC_DAPM_SINGLE("OUTVOL L Switch", RT5616_LOUT_MIXER,
-			RT5616_M_OV_L_LM_SFT, 1, 1),
-	SOC_DAPM_SINGLE("OUTVOL R Switch", RT5616_LOUT_MIXER,
-			RT5616_M_OV_R_LM_SFT, 1, 1),
-};
-
-static int rt5616_adc_event(struct snd_soc_dapm_widget *w,
-			    struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		snd_soc_update_bits(codec, RT5616_ADC_DIG_VOL,
-				    RT5616_L_MUTE | RT5616_R_MUTE, 0);
-		break;
-
-	case SND_SOC_DAPM_POST_PMD:
-		snd_soc_update_bits(codec, RT5616_ADC_DIG_VOL,
-				    RT5616_L_MUTE | RT5616_R_MUTE,
-				    RT5616_L_MUTE | RT5616_R_MUTE);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
-static int rt5616_charge_pump_event(struct snd_soc_dapm_widget *w,
-				    struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		/* depop parameters */
-		snd_soc_update_bits(codec, RT5616_DEPOP_M2,
-				    RT5616_DEPOP_MASK, RT5616_DEPOP_MAN);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_HP_CP_MASK | RT5616_HP_SG_MASK |
-				    RT5616_HP_CB_MASK, RT5616_HP_CP_PU |
-				    RT5616_HP_SG_DIS | RT5616_HP_CB_PU);
-		snd_soc_write(codec, RT5616_PR_BASE +
-			      RT5616_HP_DCC_INT1, 0x9f00);
-		/* headphone amp power on */
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
-				    RT5616_PWR_FV1 | RT5616_PWR_FV2, 0);
-		snd_soc_update_bits(codec, RT5616_PWR_VOL,
-				    RT5616_PWR_HV_L | RT5616_PWR_HV_R,
-				    RT5616_PWR_HV_L | RT5616_PWR_HV_R);
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
-				    RT5616_PWR_HP_L | RT5616_PWR_HP_R |
-				    RT5616_PWR_HA, RT5616_PWR_HP_L |
-				    RT5616_PWR_HP_R | RT5616_PWR_HA);
-		msleep(50);
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
-				    RT5616_PWR_FV1 | RT5616_PWR_FV2,
-				    RT5616_PWR_FV1 | RT5616_PWR_FV2);
-
-		snd_soc_update_bits(codec, RT5616_CHARGE_PUMP,
-				    RT5616_PM_HP_MASK, RT5616_PM_HP_HV);
-		snd_soc_update_bits(codec, RT5616_PR_BASE +
-				    RT5616_CHOP_DAC_ADC, 0x0200, 0x0200);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_HP_CO_MASK | RT5616_HP_SG_MASK,
-				    RT5616_HP_CO_EN | RT5616_HP_SG_EN);
-		break;
-	case SND_SOC_DAPM_PRE_PMD:
-		snd_soc_update_bits(codec, RT5616_PR_BASE +
-				    RT5616_CHOP_DAC_ADC, 0x0200, 0x0);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK |
-				    RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS |
-				    RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS);
-		/* headphone amp power down */
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_SMT_TRIG_MASK |
-				    RT5616_HP_CD_PD_MASK | RT5616_HP_CO_MASK |
-				    RT5616_HP_CP_MASK | RT5616_HP_SG_MASK |
-				    RT5616_HP_CB_MASK,
-				    RT5616_SMT_TRIG_DIS | RT5616_HP_CD_PD_EN |
-				    RT5616_HP_CO_DIS | RT5616_HP_CP_PD |
-				    RT5616_HP_SG_EN | RT5616_HP_CB_PD);
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
-				    RT5616_PWR_HP_L | RT5616_PWR_HP_R |
-				    RT5616_PWR_HA, 0);
-		break;
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
-static int rt5616_hp_event(struct snd_soc_dapm_widget *w,
-			   struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		/* headphone unmute sequence */
-		snd_soc_update_bits(codec, RT5616_DEPOP_M3,
-				    RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK |
-				    RT5616_CP_FQ3_MASK,
-				    RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ1_SFT |
-				    RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT |
-				    RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ3_SFT);
-		snd_soc_write(codec, RT5616_PR_BASE +
-			      RT5616_MAMP_INT_REG2, 0xfc00);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_SMT_TRIG_MASK, RT5616_SMT_TRIG_EN);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_RSTN_MASK, RT5616_RSTN_EN);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_RSTN_MASK | RT5616_HP_L_SMT_MASK |
-				    RT5616_HP_R_SMT_MASK, RT5616_RSTN_DIS |
-				    RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN);
-		snd_soc_update_bits(codec, RT5616_HP_VOL,
-				    RT5616_L_MUTE | RT5616_R_MUTE, 0);
-		msleep(100);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK |
-				    RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS |
-				    RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS);
-		msleep(20);
-		snd_soc_update_bits(codec, RT5616_HP_CALIB_AMP_DET,
-				    RT5616_HPD_PS_MASK, RT5616_HPD_PS_EN);
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-		/* headphone mute sequence */
-		snd_soc_update_bits(codec, RT5616_DEPOP_M3,
-				    RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK |
-				    RT5616_CP_FQ3_MASK,
-				    RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ1_SFT |
-				    RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT |
-				    RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ3_SFT);
-		snd_soc_write(codec, RT5616_PR_BASE +
-			      RT5616_MAMP_INT_REG2, 0xfc00);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_HP_SG_MASK, RT5616_HP_SG_EN);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_RSTP_MASK, RT5616_RSTP_EN);
-		snd_soc_update_bits(codec, RT5616_DEPOP_M1,
-				    RT5616_RSTP_MASK | RT5616_HP_L_SMT_MASK |
-				    RT5616_HP_R_SMT_MASK, RT5616_RSTP_DIS |
-				    RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN);
-		snd_soc_update_bits(codec, RT5616_HP_CALIB_AMP_DET,
-				    RT5616_HPD_PS_MASK, RT5616_HPD_PS_DIS);
-		msleep(90);
-		snd_soc_update_bits(codec, RT5616_HP_VOL,
-				    RT5616_L_MUTE | RT5616_R_MUTE,
-				    RT5616_L_MUTE | RT5616_R_MUTE);
-		msleep(30);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
-static int rt5616_lout_event(struct snd_soc_dapm_widget *w,
-			     struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
-				    RT5616_PWR_LM, RT5616_PWR_LM);
-		snd_soc_update_bits(codec, RT5616_LOUT_CTRL1,
-				    RT5616_L_MUTE | RT5616_R_MUTE, 0);
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-		snd_soc_update_bits(codec, RT5616_LOUT_CTRL1,
-				    RT5616_L_MUTE | RT5616_R_MUTE,
-				    RT5616_L_MUTE | RT5616_R_MUTE);
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
-				    RT5616_PWR_LM, 0);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
-static int rt5616_bst1_event(struct snd_soc_dapm_widget *w,
-			     struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG2,
-				    RT5616_PWR_BST1_OP2, RT5616_PWR_BST1_OP2);
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG2,
-				    RT5616_PWR_BST1_OP2, 0);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
-static int rt5616_bst2_event(struct snd_soc_dapm_widget *w,
-			     struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG2,
-				    RT5616_PWR_BST2_OP2, RT5616_PWR_BST2_OP2);
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-		snd_soc_update_bits(codec, RT5616_PWR_ANLG2,
-				    RT5616_PWR_BST2_OP2, 0);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
-static const struct snd_soc_dapm_widget rt5616_dapm_widgets[] = {
-	SND_SOC_DAPM_SUPPLY("PLL1", RT5616_PWR_ANLG2,
-			    RT5616_PWR_PLL_BIT, 0, NULL, 0),
-	/* Input Side */
-	/* micbias */
-	SND_SOC_DAPM_SUPPLY("LDO", RT5616_PWR_ANLG1,
-			    RT5616_PWR_LDO_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY("micbias1", RT5616_PWR_ANLG2,
-			    RT5616_PWR_MB1_BIT, 0, NULL, 0),
-
-	/* Input Lines */
-	SND_SOC_DAPM_INPUT("MIC1"),
-	SND_SOC_DAPM_INPUT("MIC2"),
-
-	SND_SOC_DAPM_INPUT("IN1P"),
-	SND_SOC_DAPM_INPUT("IN2P"),
-	SND_SOC_DAPM_INPUT("IN2N"),
-
-	/* Boost */
-	SND_SOC_DAPM_PGA_E("BST1", RT5616_PWR_ANLG2,
-			   RT5616_PWR_BST1_BIT, 0, NULL, 0, rt5616_bst1_event,
-			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
-	SND_SOC_DAPM_PGA_E("BST2", RT5616_PWR_ANLG2,
-			   RT5616_PWR_BST2_BIT, 0, NULL, 0, rt5616_bst2_event,
-			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
-	/* Input Volume */
-	SND_SOC_DAPM_PGA("INL1 VOL", RT5616_PWR_VOL,
-			 RT5616_PWR_IN1_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("INR1 VOL", RT5616_PWR_VOL,
-			 RT5616_PWR_IN1_R_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("INL2 VOL", RT5616_PWR_VOL,
-			 RT5616_PWR_IN2_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("INR2 VOL", RT5616_PWR_VOL,
-			 RT5616_PWR_IN2_R_BIT, 0, NULL, 0),
-
-	/* REC Mixer */
-	SND_SOC_DAPM_MIXER("RECMIXL", RT5616_PWR_MIXER, RT5616_PWR_RM_L_BIT, 0,
-			   rt5616_rec_l_mix, ARRAY_SIZE(rt5616_rec_l_mix)),
-	SND_SOC_DAPM_MIXER("RECMIXR", RT5616_PWR_MIXER, RT5616_PWR_RM_R_BIT, 0,
-			   rt5616_rec_r_mix, ARRAY_SIZE(rt5616_rec_r_mix)),
-	/* ADCs */
-	SND_SOC_DAPM_ADC_E("ADC L", NULL, RT5616_PWR_DIG1,
-			   RT5616_PWR_ADC_L_BIT, 0, rt5616_adc_event,
-			   SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
-	SND_SOC_DAPM_ADC_E("ADC R", NULL, RT5616_PWR_DIG1,
-			   RT5616_PWR_ADC_R_BIT, 0, rt5616_adc_event,
-			   SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
-
-	/* ADC Mixer */
-	SND_SOC_DAPM_SUPPLY("stereo1 filter", RT5616_PWR_DIG2,
-			    RT5616_PWR_ADC_STO1_F_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0,
-			   rt5616_sto1_adc_l_mix,
-			   ARRAY_SIZE(rt5616_sto1_adc_l_mix)),
-	SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0,
-			   rt5616_sto1_adc_r_mix,
-			   ARRAY_SIZE(rt5616_sto1_adc_r_mix)),
-
-	/* Digital Interface */
-	SND_SOC_DAPM_SUPPLY("I2S1", RT5616_PWR_DIG1,
-			    RT5616_PWR_I2S1_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("IF1 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
-
-	/* Digital Interface Select */
-
-	/* Audio Interface */
-	SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
-
-	/* Audio DSP */
-	SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
-
-	/* Output Side */
-	/* DAC mixer before sound effect  */
-	SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
-			   rt5616_dac_l_mix, ARRAY_SIZE(rt5616_dac_l_mix)),
-	SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
-			   rt5616_dac_r_mix, ARRAY_SIZE(rt5616_dac_r_mix)),
-
-	SND_SOC_DAPM_SUPPLY("Stero1 DAC Power", RT5616_PWR_DIG2,
-			    RT5616_PWR_DAC_STO1_F_BIT, 0, NULL, 0),
-
-	/* DAC Mixer */
-	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
-			   rt5616_sto_dac_l_mix,
-			   ARRAY_SIZE(rt5616_sto_dac_l_mix)),
-	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
-			   rt5616_sto_dac_r_mix,
-			   ARRAY_SIZE(rt5616_sto_dac_r_mix)),
-
-	/* DACs */
-	SND_SOC_DAPM_DAC("DAC L1", NULL, RT5616_PWR_DIG1,
-			 RT5616_PWR_DAC_L1_BIT, 0),
-	SND_SOC_DAPM_DAC("DAC R1", NULL, RT5616_PWR_DIG1,
-			 RT5616_PWR_DAC_R1_BIT, 0),
-	/* OUT Mixer */
-	SND_SOC_DAPM_MIXER("OUT MIXL", RT5616_PWR_MIXER, RT5616_PWR_OM_L_BIT,
-			   0, rt5616_out_l_mix, ARRAY_SIZE(rt5616_out_l_mix)),
-	SND_SOC_DAPM_MIXER("OUT MIXR", RT5616_PWR_MIXER, RT5616_PWR_OM_R_BIT,
-			   0, rt5616_out_r_mix, ARRAY_SIZE(rt5616_out_r_mix)),
-	/* Output Volume */
-	SND_SOC_DAPM_PGA("OUTVOL L", RT5616_PWR_VOL,
-			 RT5616_PWR_OV_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("OUTVOL R", RT5616_PWR_VOL,
-			 RT5616_PWR_OV_R_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HPOVOL L", RT5616_PWR_VOL,
-			 RT5616_PWR_HV_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HPOVOL R", RT5616_PWR_VOL,
-			 RT5616_PWR_HV_R_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM,
-			 0, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("DAC 2", SND_SOC_NOPM,
-			 0, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HPOVOL", SND_SOC_NOPM,
-			 0, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("INL1", RT5616_PWR_VOL,
-			 RT5616_PWR_IN1_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("INR1", RT5616_PWR_VOL,
-			 RT5616_PWR_IN1_R_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("INL2", RT5616_PWR_VOL,
-			 RT5616_PWR_IN2_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("INR2", RT5616_PWR_VOL,
-			 RT5616_PWR_IN2_R_BIT, 0, NULL, 0),
-	/* HPO/LOUT/Mono Mixer */
-	SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0,
-			   rt5616_hpo_mix, ARRAY_SIZE(rt5616_hpo_mix)),
-	SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0,
-			   rt5616_lout_mix, ARRAY_SIZE(rt5616_lout_mix)),
-
-	SND_SOC_DAPM_PGA_S("HP amp", 1, SND_SOC_NOPM, 0, 0,
-			   rt5616_hp_event, SND_SOC_DAPM_PRE_PMD |
-			   SND_SOC_DAPM_POST_PMU),
-	SND_SOC_DAPM_PGA_S("LOUT amp", 1, SND_SOC_NOPM, 0, 0,
-			   rt5616_lout_event, SND_SOC_DAPM_PRE_PMD |
-			   SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_SUPPLY_S("Charge Pump", 1, SND_SOC_NOPM, 0, 0,
-			      rt5616_charge_pump_event, SND_SOC_DAPM_POST_PMU |
-			      SND_SOC_DAPM_PRE_PMD),
-
-	/* Output Lines */
-	SND_SOC_DAPM_OUTPUT("HPOL"),
-	SND_SOC_DAPM_OUTPUT("HPOR"),
-	SND_SOC_DAPM_OUTPUT("LOUTL"),
-	SND_SOC_DAPM_OUTPUT("LOUTR"),
-};
-
-static const struct snd_soc_dapm_route rt5616_dapm_routes[] = {
-	{"IN1P", NULL, "LDO"},
-	{"IN2P", NULL, "LDO"},
-
-	{"IN1P", NULL, "MIC1"},
-	{"IN2P", NULL, "MIC2"},
-	{"IN2N", NULL, "MIC2"},
-
-	{"BST1", NULL, "IN1P"},
-	{"BST2", NULL, "IN2P"},
-	{"BST2", NULL, "IN2N"},
-	{"BST1", NULL, "micbias1"},
-	{"BST2", NULL, "micbias1"},
-
-	{"INL1 VOL", NULL, "IN2P"},
-	{"INR1 VOL", NULL, "IN2N"},
-
-	{"RECMIXL", "INL1 Switch", "INL1 VOL"},
-	{"RECMIXL", "BST2 Switch", "BST2"},
-	{"RECMIXL", "BST1 Switch", "BST1"},
-
-	{"RECMIXR", "INR1 Switch", "INR1 VOL"},
-	{"RECMIXR", "BST2 Switch", "BST2"},
-	{"RECMIXR", "BST1 Switch", "BST1"},
-
-	{"ADC L", NULL, "RECMIXL"},
-	{"ADC R", NULL, "RECMIXR"},
-
-	{"Stereo1 ADC MIXL", "ADC1 Switch", "ADC L"},
-	{"Stereo1 ADC MIXL", NULL, "stereo1 filter"},
-	{"stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll},
-
-	{"Stereo1 ADC MIXR", "ADC1 Switch", "ADC R"},
-	{"Stereo1 ADC MIXR", NULL, "stereo1 filter"},
-	{"stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll},
-
-	{"IF1 ADC1", NULL, "Stereo1 ADC MIXL"},
-	{"IF1 ADC1", NULL, "Stereo1 ADC MIXR"},
-	{"IF1 ADC1", NULL, "I2S1"},
-
-	{"AIF1TX", NULL, "IF1 ADC1"},
-
-	{"IF1 DAC", NULL, "AIF1RX"},
-	{"IF1 DAC", NULL, "I2S1"},
-
-	{"IF1 DAC1 L", NULL, "IF1 DAC"},
-	{"IF1 DAC1 R", NULL, "IF1 DAC"},
-
-	{"DAC MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL"},
-	{"DAC MIXL", "INF1 Switch", "IF1 DAC1 L"},
-	{"DAC MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR"},
-	{"DAC MIXR", "INF1 Switch", "IF1 DAC1 R"},
-
-	{"Audio DSP", NULL, "DAC MIXL"},
-	{"Audio DSP", NULL, "DAC MIXR"},
-
-	{"Stereo DAC MIXL", "DAC L1 Switch", "Audio DSP"},
-	{"Stereo DAC MIXL", "DAC R1 Switch", "DAC MIXR"},
-	{"Stereo DAC MIXL", NULL, "Stero1 DAC Power"},
-	{"Stereo DAC MIXR", "DAC R1 Switch", "Audio DSP"},
-	{"Stereo DAC MIXR", "DAC L1 Switch", "DAC MIXL"},
-	{"Stereo DAC MIXR", NULL, "Stero1 DAC Power"},
-
-	{"DAC L1", NULL, "Stereo DAC MIXL"},
-	{"DAC L1", NULL, "PLL1", is_sys_clk_from_pll},
-	{"DAC R1", NULL, "Stereo DAC MIXR"},
-	{"DAC R1", NULL, "PLL1", is_sys_clk_from_pll},
-
-	{"OUT MIXL", "BST1 Switch", "BST1"},
-	{"OUT MIXL", "BST2 Switch", "BST2"},
-	{"OUT MIXL", "INL1 Switch", "INL1 VOL"},
-	{"OUT MIXL", "REC MIXL Switch", "RECMIXL"},
-	{"OUT MIXL", "DAC L1 Switch", "DAC L1"},
-
-	{"OUT MIXR", "BST2 Switch", "BST2"},
-	{"OUT MIXR", "BST1 Switch", "BST1"},
-	{"OUT MIXR", "INR1 Switch", "INR1 VOL"},
-	{"OUT MIXR", "REC MIXR Switch", "RECMIXR"},
-	{"OUT MIXR", "DAC R1 Switch", "DAC R1"},
-
-	{"HPOVOL L", NULL, "OUT MIXL"},
-	{"HPOVOL R", NULL, "OUT MIXR"},
-	{"OUTVOL L", NULL, "OUT MIXL"},
-	{"OUTVOL R", NULL, "OUT MIXR"},
-
-	{"DAC 1", NULL, "DAC L1"},
-	{"DAC 1", NULL, "DAC R1"},
-	{"HPOVOL", NULL, "HPOVOL L"},
-	{"HPOVOL", NULL, "HPOVOL R"},
-	{"HPO MIX", "DAC1 Switch", "DAC 1"},
-	{"HPO MIX", "HPVOL Switch", "HPOVOL"},
-
-	{"LOUT MIX", "DAC L1 Switch", "DAC L1"},
-	{"LOUT MIX", "DAC R1 Switch", "DAC R1"},
-	{"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"},
-	{"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"},
-
-	{"HP amp", NULL, "HPO MIX"},
-	{"HP amp", NULL, "Charge Pump"},
-	{"HPOL", NULL, "HP amp"},
-	{"HPOR", NULL, "HP amp"},
-
-	{"LOUT amp", NULL, "LOUT MIX"},
-	{"LOUT amp", NULL, "Charge Pump"},
-	{"LOUTL", NULL, "LOUT amp"},
-	{"LOUTR", NULL, "LOUT amp"},
-
-};
-
-static int rt5616_hw_params(struct snd_pcm_substream *substream,
-			    struct snd_pcm_hw_params *params,
-			    struct snd_soc_dai *dai)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_codec *codec = rtd->codec;
-	struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
-	unsigned int val_len = 0, val_clk, mask_clk;
-	int pre_div, bclk_ms, frame_size;
-
-	rt5616->lrck[dai->id] = params_rate(params);
-
-	pre_div = rl6231_get_clk_info(rt5616->sysclk, rt5616->lrck[dai->id]);
-
-	if (pre_div < 0) {
-		dev_err(codec->dev, "Unsupported clock setting\n");
-		return -EINVAL;
-	}
-	frame_size = snd_soc_params_to_frame_size(params);
-	if (frame_size < 0) {
-		dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
-		return -EINVAL;
-	}
-	bclk_ms = frame_size > 32 ? 1 : 0;
-	rt5616->bclk[dai->id] = rt5616->lrck[dai->id] * (32 << bclk_ms);
-
-	dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
-		rt5616->bclk[dai->id], rt5616->lrck[dai->id]);
-	dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
-		bclk_ms, pre_div, dai->id);
-
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
-		val_len |= RT5616_I2S_DL_20;
-		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
-		val_len |= RT5616_I2S_DL_24;
-		break;
-	case SNDRV_PCM_FORMAT_S8:
-		val_len |= RT5616_I2S_DL_8;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	mask_clk = RT5616_I2S_PD1_MASK;
-	val_clk = pre_div << RT5616_I2S_PD1_SFT;
-	snd_soc_update_bits(codec, RT5616_I2S1_SDP,
-			    RT5616_I2S_DL_MASK, val_len);
-	snd_soc_update_bits(codec, RT5616_ADDA_CLK1, mask_clk, val_clk);
-
-	return 0;
-}
-
-static int rt5616_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
-	struct snd_soc_codec *codec = dai->codec;
-	struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
-	unsigned int reg_val = 0;
-
-	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-	case SND_SOC_DAIFMT_CBM_CFM:
-		rt5616->master[dai->id] = 1;
-		break;
-	case SND_SOC_DAIFMT_CBS_CFS:
-		reg_val |= RT5616_I2S_MS_S;
-		rt5616->master[dai->id] = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-	case SND_SOC_DAIFMT_NB_NF:
-		break;
-	case SND_SOC_DAIFMT_IB_NF:
-		reg_val |= RT5616_I2S_BP_INV;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_I2S:
-		break;
-	case SND_SOC_DAIFMT_LEFT_J:
-		reg_val |= RT5616_I2S_DF_LEFT;
-		break;
-	case SND_SOC_DAIFMT_DSP_A:
-		reg_val |= RT5616_I2S_DF_PCM_A;
-		break;
-	case SND_SOC_DAIFMT_DSP_B:
-		reg_val |= RT5616_I2S_DF_PCM_B;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	snd_soc_update_bits(codec, RT5616_I2S1_SDP,
-			    RT5616_I2S_MS_MASK | RT5616_I2S_BP_MASK |
-			    RT5616_I2S_DF_MASK, reg_val);
-
-	return 0;
-}
-
-static int rt5616_set_dai_sysclk(struct snd_soc_dai *dai,
-				 int clk_id, unsigned int freq, int dir)
-{
-	struct snd_soc_codec *codec = dai->codec;
-	struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
-	unsigned int reg_val = 0;
-
-	if (freq == rt5616->sysclk && clk_id == rt5616->sysclk_src)
-		return 0;
-
-	switch (clk_id) {
-	case RT5616_SCLK_S_MCLK:
-		reg_val |= RT5616_SCLK_SRC_MCLK;
-		break;
-	case RT5616_SCLK_S_PLL1:
-		reg_val |= RT5616_SCLK_SRC_PLL1;
-		break;
-	default:
-		dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
-		return -EINVAL;
-	}
-
-	snd_soc_update_bits(codec, RT5616_GLB_CLK,
-			    RT5616_SCLK_SRC_MASK, reg_val);
-	rt5616->sysclk = freq;
-	rt5616->sysclk_src = clk_id;
-
-	dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
-
-	return 0;
-}
-
-static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
-			      unsigned int freq_in, unsigned int freq_out)
-{
-	struct snd_soc_codec *codec = dai->codec;
-	struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
-	struct rl6231_pll_code pll_code;
-	int ret;
-
-	if (source == rt5616->pll_src && freq_in == rt5616->pll_in &&
-	    freq_out == rt5616->pll_out)
-		return 0;
-
-	if (!freq_in || !freq_out) {
-		dev_dbg(codec->dev, "PLL disabled\n");
-
-		rt5616->pll_in = 0;
-		rt5616->pll_out = 0;
-		snd_soc_update_bits(codec, RT5616_GLB_CLK,
-				    RT5616_SCLK_SRC_MASK,
-				    RT5616_SCLK_SRC_MCLK);
-		return 0;
-	}
-
-	switch (source) {
-	case RT5616_PLL1_S_MCLK:
-		snd_soc_update_bits(codec, RT5616_GLB_CLK,
-				    RT5616_PLL1_SRC_MASK,
-				    RT5616_PLL1_SRC_MCLK);
-		break;
-	case RT5616_PLL1_S_BCLK1:
-	case RT5616_PLL1_S_BCLK2:
-		snd_soc_update_bits(codec, RT5616_GLB_CLK,
-				    RT5616_PLL1_SRC_MASK,
-				    RT5616_PLL1_SRC_BCLK1);
-		break;
-	default:
-		dev_err(codec->dev, "Unknown PLL source %d\n", source);
-		return -EINVAL;
-	}
-
-	ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
-	if (ret < 0) {
-		dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
-		return ret;
-	}
-
-	dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
-		pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
-		pll_code.n_code, pll_code.k_code);
-
-	snd_soc_write(codec, RT5616_PLL_CTRL1,
-		      pll_code.n_code << RT5616_PLL_N_SFT | pll_code.k_code);
-	snd_soc_write(codec, RT5616_PLL_CTRL2,
-		      (pll_code.m_bp ? 0 : pll_code.m_code) <<
-		      RT5616_PLL_M_SFT |
-		      pll_code.m_bp << RT5616_PLL_M_BP_SFT);
-
-	rt5616->pll_in = freq_in;
-	rt5616->pll_out = freq_out;
-	rt5616->pll_src = source;
-
-	return 0;
-}
-
-static int rt5616_set_bias_level(struct snd_soc_codec *codec,
-				 enum snd_soc_bias_level level)
-{
-	struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
-	int ret;
-
-	switch (level) {
-
-	case SND_SOC_BIAS_ON:
-		break;
-
-	case SND_SOC_BIAS_PREPARE:
-		/*
-		 * SND_SOC_BIAS_PREPARE is called while preparing for a
-		 * transition to ON or away from ON. If current bias_level
-		 * is SND_SOC_BIAS_ON, then it is preparing for a transition
-		 * away from ON. Disable the clock in that case, otherwise
-		 * enable it.
-		 */
-		if (IS_ERR(rt5616->mclk))
-			break;
-
-		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) {
-			clk_disable_unprepare(rt5616->mclk);
-		} else {
-			ret = clk_prepare_enable(rt5616->mclk);
-			if (ret)
-				return ret;
-		}
-		break;
-
-	case SND_SOC_BIAS_STANDBY:
-		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
-			snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
-					    RT5616_PWR_VREF1 | RT5616_PWR_MB |
-					    RT5616_PWR_BG | RT5616_PWR_VREF2,
-					    RT5616_PWR_VREF1 | RT5616_PWR_MB |
-					    RT5616_PWR_BG | RT5616_PWR_VREF2);
-			mdelay(10);
-			snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
-					    RT5616_PWR_FV1 | RT5616_PWR_FV2,
-					    RT5616_PWR_FV1 | RT5616_PWR_FV2);
-			snd_soc_update_bits(codec, RT5616_D_MISC,
-					    RT5616_D_GATE_EN,
-					    RT5616_D_GATE_EN);
-		}
-		break;
-
-	case SND_SOC_BIAS_OFF:
-		snd_soc_update_bits(codec, RT5616_D_MISC, RT5616_D_GATE_EN, 0);
-		snd_soc_write(codec, RT5616_PWR_DIG1, 0x0000);
-		snd_soc_write(codec, RT5616_PWR_DIG2, 0x0000);
-		snd_soc_write(codec, RT5616_PWR_VOL, 0x0000);
-		snd_soc_write(codec, RT5616_PWR_MIXER, 0x0000);
-		snd_soc_write(codec, RT5616_PWR_ANLG1, 0x0000);
-		snd_soc_write(codec, RT5616_PWR_ANLG2, 0x0000);
-		break;
-
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int rt5616_probe(struct snd_soc_codec *codec)
-{
-	struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
-
-	/* Check if MCLK provided */
-	rt5616->mclk = devm_clk_get(codec->dev, "mclk");
-	if (PTR_ERR(rt5616->mclk) == -EPROBE_DEFER)
-		return -EPROBE_DEFER;
-
-	rt5616->codec = codec;
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int rt5616_suspend(struct snd_soc_codec *codec)
-{
-	struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
-
-	regcache_cache_only(rt5616->regmap, true);
-	regcache_mark_dirty(rt5616->regmap);
-
-	return 0;
-}
-
-static int rt5616_resume(struct snd_soc_codec *codec)
-{
-	struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
-
-	regcache_cache_only(rt5616->regmap, false);
-	regcache_sync(rt5616->regmap);
-	return 0;
-}
-#else
-#define rt5616_suspend NULL
-#define rt5616_resume NULL
-#endif
-
-#define RT5616_STEREO_RATES SNDRV_PCM_RATE_8000_192000
-#define RT5616_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
-			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
-
-struct snd_soc_dai_ops rt5616_aif_dai_ops = {
-	.hw_params = rt5616_hw_params,
-	.set_fmt = rt5616_set_dai_fmt,
-	.set_sysclk = rt5616_set_dai_sysclk,
-	.set_pll = rt5616_set_dai_pll,
-};
-
-struct snd_soc_dai_driver rt5616_dai[] = {
-	{
-		.name = "rt5616-aif1",
-		.id = RT5616_AIF1,
-		.playback = {
-			.stream_name = "AIF1 Playback",
-			.channels_min = 1,
-			.channels_max = 2,
-			.rates = RT5616_STEREO_RATES,
-			.formats = RT5616_FORMATS,
-		},
-		.capture = {
-			.stream_name = "AIF1 Capture",
-			.channels_min = 1,
-			.channels_max = 2,
-			.rates = RT5616_STEREO_RATES,
-			.formats = RT5616_FORMATS,
-		},
-		.ops = &rt5616_aif_dai_ops,
-	},
-};
-
-static struct snd_soc_codec_driver soc_codec_dev_rt5616 = {
-	.probe = rt5616_probe,
-	.suspend = rt5616_suspend,
-	.resume = rt5616_resume,
-	.set_bias_level = rt5616_set_bias_level,
-	.idle_bias_off = true,
-	.controls = rt5616_snd_controls,
-	.num_controls = ARRAY_SIZE(rt5616_snd_controls),
-	.dapm_widgets = rt5616_dapm_widgets,
-	.num_dapm_widgets = ARRAY_SIZE(rt5616_dapm_widgets),
-	.dapm_routes = rt5616_dapm_routes,
-	.num_dapm_routes = ARRAY_SIZE(rt5616_dapm_routes),
-};
-
-static const struct regmap_config rt5616_regmap = {
-	.reg_bits = 8,
-	.val_bits = 16,
-	.use_single_rw = true,
-	.max_register = RT5616_DEVICE_ID + 1 + (ARRAY_SIZE(rt5616_ranges) *
-					       RT5616_PR_SPACING),
-	.volatile_reg = rt5616_volatile_register,
-	.readable_reg = rt5616_readable_register,
-	.cache_type = REGCACHE_RBTREE,
-	.reg_defaults = rt5616_reg,
-	.num_reg_defaults = ARRAY_SIZE(rt5616_reg),
-	.ranges = rt5616_ranges,
-	.num_ranges = ARRAY_SIZE(rt5616_ranges),
-};
-
-static const struct i2c_device_id rt5616_i2c_id[] = {
-	{ "rt5616", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, rt5616_i2c_id);
-
-#if defined(CONFIG_OF)
-static const struct of_device_id rt5616_of_match[] = {
-	{ .compatible = "realtek,rt5616", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, rt5616_of_match);
-#endif
-
-static int rt5616_i2c_probe(struct i2c_client *i2c,
-			    const struct i2c_device_id *id)
-{
-	struct rt5616_priv *rt5616;
-	unsigned int val;
-	int ret;
-
-	rt5616 = devm_kzalloc(&i2c->dev, sizeof(struct rt5616_priv),
-			      GFP_KERNEL);
-	if (!rt5616)
-		return -ENOMEM;
-
-	i2c_set_clientdata(i2c, rt5616);
-
-	rt5616->regmap = devm_regmap_init_i2c(i2c, &rt5616_regmap);
-	if (IS_ERR(rt5616->regmap)) {
-		ret = PTR_ERR(rt5616->regmap);
-		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
-			ret);
-		return ret;
-	}
-
-	regmap_read(rt5616->regmap, RT5616_DEVICE_ID, &val);
-	if (val != 0x6281) {
-		dev_err(&i2c->dev,
-			"Device with ID register %#x is not rt5616\n",
-			val);
-		return -ENODEV;
-	}
-	regmap_write(rt5616->regmap, RT5616_RESET, 0);
-	regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1,
-			   RT5616_PWR_VREF1 | RT5616_PWR_MB |
-			   RT5616_PWR_BG | RT5616_PWR_VREF2,
-			   RT5616_PWR_VREF1 | RT5616_PWR_MB |
-			   RT5616_PWR_BG | RT5616_PWR_VREF2);
-	mdelay(10);
-	regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1,
-			   RT5616_PWR_FV1 | RT5616_PWR_FV2,
-			   RT5616_PWR_FV1 | RT5616_PWR_FV2);
-
-	ret = regmap_register_patch(rt5616->regmap, init_list,
-				    ARRAY_SIZE(init_list));
-	if (ret != 0)
-		dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
-
-	regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1,
-			   RT5616_PWR_LDO_DVO_MASK, RT5616_PWR_LDO_DVO_1_2V);
-
-	return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5616,
-				      rt5616_dai, ARRAY_SIZE(rt5616_dai));
-}
-
-static int rt5616_i2c_remove(struct i2c_client *i2c)
-{
-	snd_soc_unregister_codec(&i2c->dev);
-
-	return 0;
-}
-
-static void rt5616_i2c_shutdown(struct i2c_client *client)
-{
-	struct rt5616_priv *rt5616 = i2c_get_clientdata(client);
-
-	regmap_write(rt5616->regmap, RT5616_HP_VOL, 0xc8c8);
-	regmap_write(rt5616->regmap, RT5616_LOUT_CTRL1, 0xc8c8);
-}
-
-static struct i2c_driver rt5616_i2c_driver = {
-	.driver = {
-		.name = "rt5616",
-		.of_match_table = of_match_ptr(rt5616_of_match),
-	},
-	.probe = rt5616_i2c_probe,
-	.remove = rt5616_i2c_remove,
-	.shutdown = rt5616_i2c_shutdown,
-	.id_table = rt5616_i2c_id,
-};
-module_i2c_driver(rt5616_i2c_driver);
-
-MODULE_DESCRIPTION("ASoC RT5616 driver");
-MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt5616.h b/sound/soc/codecs/rt5616.h
deleted file mode 100644
index f88cddd..0000000
--- a/sound/soc/codecs/rt5616.h
+++ /dev/null
@@ -1,1819 +0,0 @@
-/*
- * rt5616.h  --  RT5616 ALSA SoC audio driver
- *
- * Copyright 2011 Realtek Microelectronics
- * Author: Johnny Hsu <johnnyhsu@realtek.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __RT5616_H__
-#define __RT5616_H__
-
-/* Info */
-#define RT5616_RESET				0x00
-#define RT5616_VERSION_ID			0xfd
-#define RT5616_VENDOR_ID			0xfe
-#define RT5616_DEVICE_ID			0xff
-/*  I/O - Output */
-#define RT5616_HP_VOL				0x02
-#define RT5616_LOUT_CTRL1			0x03
-#define RT5616_LOUT_CTRL2			0x05
-/* I/O - Input */
-#define RT5616_IN1_IN2				0x0d
-#define RT5616_INL1_INR1_VOL			0x0f
-/* I/O - ADC/DAC/DMIC */
-#define RT5616_DAC1_DIG_VOL			0x19
-#define RT5616_ADC_DIG_VOL			0x1c
-#define RT5616_ADC_BST_VOL			0x1e
-/* Mixer - D-D */
-#define RT5616_STO1_ADC_MIXER			0x27
-#define RT5616_AD_DA_MIXER			0x29
-#define RT5616_STO_DAC_MIXER			0x2a
-
-/* Mixer - ADC */
-#define RT5616_REC_L1_MIXER			0x3b
-#define RT5616_REC_L2_MIXER			0x3c
-#define RT5616_REC_R1_MIXER			0x3d
-#define RT5616_REC_R2_MIXER			0x3e
-/* Mixer - DAC */
-#define RT5616_HPO_MIXER			0x45
-#define RT5616_OUT_L1_MIXER			0x4d
-#define RT5616_OUT_L2_MIXER			0x4e
-#define RT5616_OUT_L3_MIXER			0x4f
-#define RT5616_OUT_R1_MIXER			0x50
-#define RT5616_OUT_R2_MIXER			0x51
-#define RT5616_OUT_R3_MIXER			0x52
-#define RT5616_LOUT_MIXER			0x53
-/* Power */
-#define RT5616_PWR_DIG1				0x61
-#define RT5616_PWR_DIG2				0x62
-#define RT5616_PWR_ANLG1			0x63
-#define RT5616_PWR_ANLG2			0x64
-#define RT5616_PWR_MIXER			0x65
-#define RT5616_PWR_VOL				0x66
-/* Private Register Control */
-#define RT5616_PRIV_INDEX			0x6a
-#define RT5616_PRIV_DATA			0x6c
-/* Format - ADC/DAC */
-#define RT5616_I2S1_SDP				0x70
-#define RT5616_ADDA_CLK1			0x73
-#define RT5616_ADDA_CLK2			0x74
-
-/* Function - Analog */
-#define RT5616_GLB_CLK				0x80
-#define RT5616_PLL_CTRL1			0x81
-#define RT5616_PLL_CTRL2			0x82
-#define RT5616_HP_OVCD				0x8b
-#define RT5616_DEPOP_M1				0x8e
-#define RT5616_DEPOP_M2				0x8f
-#define RT5616_DEPOP_M3				0x90
-#define RT5616_CHARGE_PUMP			0x91
-#define RT5616_PV_DET_SPK_G			0x92
-#define RT5616_MICBIAS				0x93
-#define RT5616_A_JD_CTL1			0x94
-#define RT5616_A_JD_CTL2			0x95
-/* Function - Digital */
-#define RT5616_EQ_CTRL1				0xb0
-#define RT5616_EQ_CTRL2				0xb1
-#define RT5616_WIND_FILTER			0xb2
-#define RT5616_DRC_AGC_1			0xb4
-#define RT5616_DRC_AGC_2			0xb5
-#define RT5616_DRC_AGC_3			0xb6
-#define RT5616_SVOL_ZC				0xb7
-#define RT5616_JD_CTRL1				0xbb
-#define RT5616_JD_CTRL2				0xbc
-#define RT5616_IRQ_CTRL1			0xbd
-#define RT5616_IRQ_CTRL2			0xbe
-#define RT5616_INT_IRQ_ST			0xbf
-#define RT5616_GPIO_CTRL1			0xc0
-#define RT5616_GPIO_CTRL2			0xc1
-#define RT5616_GPIO_CTRL3			0xc2
-#define RT5616_PGM_REG_ARR1			0xc8
-#define RT5616_PGM_REG_ARR2			0xc9
-#define RT5616_PGM_REG_ARR3			0xca
-#define RT5616_PGM_REG_ARR4			0xcb
-#define RT5616_PGM_REG_ARR5			0xcc
-#define RT5616_SCB_FUNC				0xcd
-#define RT5616_SCB_CTRL				0xce
-#define RT5616_BASE_BACK			0xcf
-#define RT5616_MP3_PLUS1			0xd0
-#define RT5616_MP3_PLUS2			0xd1
-#define RT5616_ADJ_HPF_CTRL1			0xd3
-#define RT5616_ADJ_HPF_CTRL2			0xd4
-#define RT5616_HP_CALIB_AMP_DET			0xd6
-#define RT5616_HP_CALIB2			0xd7
-#define RT5616_SV_ZCD1				0xd9
-#define RT5616_SV_ZCD2				0xda
-#define RT5616_D_MISC				0xfa
-/* Dummy Register */
-#define RT5616_DUMMY2				0xfb
-#define RT5616_DUMMY3				0xfc
-
-
-/* Index of Codec Private Register definition */
-#define RT5616_BIAS_CUR1			0x12
-#define RT5616_BIAS_CUR3			0x14
-#define RT5616_CLSD_INT_REG1			0x1c
-#define RT5616_MAMP_INT_REG2			0x37
-#define RT5616_CHOP_DAC_ADC			0x3d
-#define RT5616_3D_SPK				0x63
-#define RT5616_WND_1				0x6c
-#define RT5616_WND_2				0x6d
-#define RT5616_WND_3				0x6e
-#define RT5616_WND_4				0x6f
-#define RT5616_WND_5				0x70
-#define RT5616_WND_8				0x73
-#define RT5616_DIP_SPK_INF			0x75
-#define RT5616_HP_DCC_INT1			0x77
-#define RT5616_EQ_BW_LOP			0xa0
-#define RT5616_EQ_GN_LOP			0xa1
-#define RT5616_EQ_FC_BP1			0xa2
-#define RT5616_EQ_BW_BP1			0xa3
-#define RT5616_EQ_GN_BP1			0xa4
-#define RT5616_EQ_FC_BP2			0xa5
-#define RT5616_EQ_BW_BP2			0xa6
-#define RT5616_EQ_GN_BP2			0xa7
-#define RT5616_EQ_FC_BP3			0xa8
-#define RT5616_EQ_BW_BP3			0xa9
-#define RT5616_EQ_GN_BP3			0xaa
-#define RT5616_EQ_FC_BP4			0xab
-#define RT5616_EQ_BW_BP4			0xac
-#define RT5616_EQ_GN_BP4			0xad
-#define RT5616_EQ_FC_HIP1			0xae
-#define RT5616_EQ_GN_HIP1			0xaf
-#define RT5616_EQ_FC_HIP2			0xb0
-#define RT5616_EQ_BW_HIP2			0xb1
-#define RT5616_EQ_GN_HIP2			0xb2
-#define RT5616_EQ_PRE_VOL			0xb3
-#define RT5616_EQ_PST_VOL			0xb4
-
-
-/* global definition */
-#define RT5616_L_MUTE				(0x1 << 15)
-#define RT5616_L_MUTE_SFT			15
-#define RT5616_VOL_L_MUTE			(0x1 << 14)
-#define RT5616_VOL_L_SFT			14
-#define RT5616_R_MUTE				(0x1 << 7)
-#define RT5616_R_MUTE_SFT			7
-#define RT5616_VOL_R_MUTE			(0x1 << 6)
-#define RT5616_VOL_R_SFT			6
-#define RT5616_L_VOL_MASK			(0x3f << 8)
-#define RT5616_L_VOL_SFT			8
-#define RT5616_R_VOL_MASK			(0x3f)
-#define RT5616_R_VOL_SFT			0
-
-/* LOUT Control 2(0x05) */
-#define RT5616_EN_DFO				(0x1 << 15)
-
-/* IN1 and IN2 Control (0x0d) */
-/* IN3 and IN4 Control (0x0e) */
-#define RT5616_BST_MASK1			(0xf<<12)
-#define RT5616_BST_SFT1				12
-#define RT5616_BST_MASK2			(0xf<<8)
-#define RT5616_BST_SFT2				8
-#define RT5616_IN_DF1				(0x1 << 7)
-#define RT5616_IN_SFT1				7
-#define RT5616_IN_DF2				(0x1 << 6)
-#define RT5616_IN_SFT2				6
-
-/* INL1 and INR1 Volume Control (0x0f) */
-#define RT5616_INL_VOL_MASK			(0x1f << 8)
-#define RT5616_INL_VOL_SFT			8
-#define RT5616_INR_SEL_MASK			(0x1 << 7)
-#define RT5616_INR_SEL_SFT			7
-#define RT5616_INR_SEL_IN4N			(0x0 << 7)
-#define RT5616_INR_SEL_MONON			(0x1 << 7)
-#define RT5616_INR_VOL_MASK			(0x1f)
-#define RT5616_INR_VOL_SFT			0
-
-/* DAC1 Digital Volume (0x19) */
-#define RT5616_DAC_L1_VOL_MASK			(0xff << 8)
-#define RT5616_DAC_L1_VOL_SFT			8
-#define RT5616_DAC_R1_VOL_MASK			(0xff)
-#define RT5616_DAC_R1_VOL_SFT			0
-
-/* DAC2 Digital Volume (0x1a) */
-#define RT5616_DAC_L2_VOL_MASK			(0xff << 8)
-#define RT5616_DAC_L2_VOL_SFT			8
-#define RT5616_DAC_R2_VOL_MASK			(0xff)
-#define RT5616_DAC_R2_VOL_SFT			0
-
-/* ADC Digital Volume Control (0x1c) */
-#define RT5616_ADC_L_VOL_MASK			(0x7f << 8)
-#define RT5616_ADC_L_VOL_SFT			8
-#define RT5616_ADC_R_VOL_MASK			(0x7f)
-#define RT5616_ADC_R_VOL_SFT			0
-
-/* Mono ADC Digital Volume Control (0x1d) */
-#define RT5616_M_MONO_ADC_L			(0x1 << 15)
-#define RT5616_M_MONO_ADC_L_SFT			15
-#define RT5616_MONO_ADC_L_VOL_MASK		(0x7f << 8)
-#define RT5616_MONO_ADC_L_VOL_SFT		8
-#define RT5616_M_MONO_ADC_R			(0x1 << 7)
-#define RT5616_M_MONO_ADC_R_SFT			7
-#define RT5616_MONO_ADC_R_VOL_MASK		(0x7f)
-#define RT5616_MONO_ADC_R_VOL_SFT		0
-
-/* ADC Boost Volume Control (0x1e) */
-#define RT5616_ADC_L_BST_MASK			(0x3 << 14)
-#define RT5616_ADC_L_BST_SFT			14
-#define RT5616_ADC_R_BST_MASK			(0x3 << 12)
-#define RT5616_ADC_R_BST_SFT			12
-#define RT5616_ADC_COMP_MASK			(0x3 << 10)
-#define RT5616_ADC_COMP_SFT			10
-
-/* Stereo ADC1 Mixer Control (0x27) */
-#define RT5616_M_STO1_ADC_L1			(0x1 << 14)
-#define RT5616_M_STO1_ADC_L1_SFT		14
-#define RT5616_M_STO1_ADC_R1			(0x1 << 6)
-#define RT5616_M_STO1_ADC_R1_SFT		6
-
-/* ADC Mixer to DAC Mixer Control (0x29) */
-#define RT5616_M_ADCMIX_L			(0x1 << 15)
-#define RT5616_M_ADCMIX_L_SFT			15
-#define RT5616_M_IF1_DAC_L			(0x1 << 14)
-#define RT5616_M_IF1_DAC_L_SFT			14
-#define RT5616_M_ADCMIX_R			(0x1 << 7)
-#define RT5616_M_ADCMIX_R_SFT			7
-#define RT5616_M_IF1_DAC_R			(0x1 << 6)
-#define RT5616_M_IF1_DAC_R_SFT			6
-
-/* Stereo DAC Mixer Control (0x2a) */
-#define RT5616_M_DAC_L1_MIXL			(0x1 << 14)
-#define RT5616_M_DAC_L1_MIXL_SFT		14
-#define RT5616_DAC_L1_STO_L_VOL_MASK		(0x1 << 13)
-#define RT5616_DAC_L1_STO_L_VOL_SFT		13
-#define RT5616_M_DAC_R1_MIXL			(0x1 << 9)
-#define RT5616_M_DAC_R1_MIXL_SFT		9
-#define RT5616_DAC_R1_STO_L_VOL_MASK		(0x1 << 8)
-#define RT5616_DAC_R1_STO_L_VOL_SFT		8
-#define RT5616_M_DAC_R1_MIXR			(0x1 << 6)
-#define RT5616_M_DAC_R1_MIXR_SFT		6
-#define RT5616_DAC_R1_STO_R_VOL_MASK		(0x1 << 5)
-#define RT5616_DAC_R1_STO_R_VOL_SFT		5
-#define RT5616_M_DAC_L1_MIXR			(0x1 << 1)
-#define RT5616_M_DAC_L1_MIXR_SFT		1
-#define RT5616_DAC_L1_STO_R_VOL_MASK		(0x1)
-#define RT5616_DAC_L1_STO_R_VOL_SFT		0
-
-/* DD Mixer Control (0x2b) */
-#define RT5616_M_STO_DD_L1			(0x1 << 14)
-#define RT5616_M_STO_DD_L1_SFT			14
-#define RT5616_STO_DD_L1_VOL_MASK		(0x1 << 13)
-#define RT5616_DAC_DD_L1_VOL_SFT		13
-#define RT5616_M_STO_DD_L2			(0x1 << 12)
-#define RT5616_M_STO_DD_L2_SFT			12
-#define RT5616_STO_DD_L2_VOL_MASK		(0x1 << 11)
-#define RT5616_STO_DD_L2_VOL_SFT		11
-#define RT5616_M_STO_DD_R2_L			(0x1 << 10)
-#define RT5616_M_STO_DD_R2_L_SFT		10
-#define RT5616_STO_DD_R2_L_VOL_MASK		(0x1 << 9)
-#define RT5616_STO_DD_R2_L_VOL_SFT		9
-#define RT5616_M_STO_DD_R1			(0x1 << 6)
-#define RT5616_M_STO_DD_R1_SFT			6
-#define RT5616_STO_DD_R1_VOL_MASK		(0x1 << 5)
-#define RT5616_STO_DD_R1_VOL_SFT		5
-#define RT5616_M_STO_DD_R2			(0x1 << 4)
-#define RT5616_M_STO_DD_R2_SFT			4
-#define RT5616_STO_DD_R2_VOL_MASK		(0x1 << 3)
-#define RT5616_STO_DD_R2_VOL_SFT		3
-#define RT5616_M_STO_DD_L2_R			(0x1 << 2)
-#define RT5616_M_STO_DD_L2_R_SFT		2
-#define RT5616_STO_DD_L2_R_VOL_MASK		(0x1 << 1)
-#define RT5616_STO_DD_L2_R_VOL_SFT		1
-
-/* Digital Mixer Control (0x2c) */
-#define RT5616_M_STO_L_DAC_L			(0x1 << 15)
-#define RT5616_M_STO_L_DAC_L_SFT		15
-#define RT5616_STO_L_DAC_L_VOL_MASK		(0x1 << 14)
-#define RT5616_STO_L_DAC_L_VOL_SFT		14
-#define RT5616_M_DAC_L2_DAC_L			(0x1 << 13)
-#define RT5616_M_DAC_L2_DAC_L_SFT		13
-#define RT5616_DAC_L2_DAC_L_VOL_MASK		(0x1 << 12)
-#define RT5616_DAC_L2_DAC_L_VOL_SFT		12
-#define RT5616_M_STO_R_DAC_R			(0x1 << 11)
-#define RT5616_M_STO_R_DAC_R_SFT		11
-#define RT5616_STO_R_DAC_R_VOL_MASK		(0x1 << 10)
-#define RT5616_STO_R_DAC_R_VOL_SFT		10
-#define RT5616_M_DAC_R2_DAC_R			(0x1 << 9)
-#define RT5616_M_DAC_R2_DAC_R_SFT		9
-#define RT5616_DAC_R2_DAC_R_VOL_MASK		(0x1 << 8)
-#define RT5616_DAC_R2_DAC_R_VOL_SFT		8
-
-/* DSP Path Control 1 (0x2d) */
-#define RT5616_RXDP_SRC_MASK			(0x1 << 15)
-#define RT5616_RXDP_SRC_SFT			15
-#define RT5616_RXDP_SRC_NOR			(0x0 << 15)
-#define RT5616_RXDP_SRC_DIV3			(0x1 << 15)
-#define RT5616_TXDP_SRC_MASK			(0x1 << 14)
-#define RT5616_TXDP_SRC_SFT			14
-#define RT5616_TXDP_SRC_NOR			(0x0 << 14)
-#define RT5616_TXDP_SRC_DIV3			(0x1 << 14)
-
-/* DSP Path Control 2 (0x2e) */
-#define RT5616_DAC_L2_SEL_MASK			(0x3 << 14)
-#define RT5616_DAC_L2_SEL_SFT			14
-#define RT5616_DAC_L2_SEL_IF2			(0x0 << 14)
-#define RT5616_DAC_L2_SEL_IF3			(0x1 << 14)
-#define RT5616_DAC_L2_SEL_TXDC			(0x2 << 14)
-#define RT5616_DAC_L2_SEL_BASS			(0x3 << 14)
-#define RT5616_DAC_R2_SEL_MASK			(0x3 << 12)
-#define RT5616_DAC_R2_SEL_SFT			12
-#define RT5616_DAC_R2_SEL_IF2			(0x0 << 12)
-#define RT5616_DAC_R2_SEL_IF3			(0x1 << 12)
-#define RT5616_DAC_R2_SEL_TXDC			(0x2 << 12)
-#define RT5616_IF2_ADC_L_SEL_MASK		(0x1 << 11)
-#define RT5616_IF2_ADC_L_SEL_SFT		11
-#define RT5616_IF2_ADC_L_SEL_TXDP		(0x0 << 11)
-#define RT5616_IF2_ADC_L_SEL_PASS		(0x1 << 11)
-#define RT5616_IF2_ADC_R_SEL_MASK		(0x1 << 10)
-#define RT5616_IF2_ADC_R_SEL_SFT		10
-#define RT5616_IF2_ADC_R_SEL_TXDP		(0x0 << 10)
-#define RT5616_IF2_ADC_R_SEL_PASS		(0x1 << 10)
-#define RT5616_RXDC_SEL_MASK			(0x3 << 8)
-#define RT5616_RXDC_SEL_SFT			8
-#define RT5616_RXDC_SEL_NOR			(0x0 << 8)
-#define RT5616_RXDC_SEL_L2R			(0x1 << 8)
-#define RT5616_RXDC_SEL_R2L			(0x2 << 8)
-#define RT5616_RXDC_SEL_SWAP			(0x3 << 8)
-#define RT5616_RXDP_SEL_MASK			(0x3 << 6)
-#define RT5616_RXDP_SEL_SFT			6
-#define RT5616_RXDP_SEL_NOR			(0x0 << 6)
-#define RT5616_RXDP_SEL_L2R			(0x1 << 6)
-#define RT5616_RXDP_SEL_R2L			(0x2 << 6)
-#define RT5616_RXDP_SEL_SWAP			(0x3 << 6)
-#define RT5616_TXDC_SEL_MASK			(0x3 << 4)
-#define RT5616_TXDC_SEL_SFT			4
-#define RT5616_TXDC_SEL_NOR			(0x0 << 4)
-#define RT5616_TXDC_SEL_L2R			(0x1 << 4)
-#define RT5616_TXDC_SEL_R2L			(0x2 << 4)
-#define RT5616_TXDC_SEL_SWAP			(0x3 << 4)
-#define RT5616_TXDP_SEL_MASK			(0x3 << 2)
-#define RT5616_TXDP_SEL_SFT			2
-#define RT5616_TXDP_SEL_NOR			(0x0 << 2)
-#define RT5616_TXDP_SEL_L2R			(0x1 << 2)
-#define RT5616_TXDP_SEL_R2L			(0x2 << 2)
-#define RT5616_TRXDP_SEL_SWAP			(0x3 << 2)
-
-/* REC Left Mixer Control 1 (0x3b) */
-#define RT5616_G_LN_L2_RM_L_MASK		(0x7 << 13)
-#define RT5616_G_IN_L2_RM_L_SFT			13
-#define RT5616_G_LN_L1_RM_L_MASK		(0x7 << 10)
-#define RT5616_G_IN_L1_RM_L_SFT			10
-#define RT5616_G_BST3_RM_L_MASK			(0x7 << 4)
-#define RT5616_G_BST3_RM_L_SFT			4
-#define RT5616_G_BST2_RM_L_MASK			(0x7 << 1)
-#define RT5616_G_BST2_RM_L_SFT			1
-
-/* REC Left Mixer Control 2 (0x3c) */
-#define RT5616_G_BST1_RM_L_MASK			(0x7 << 13)
-#define RT5616_G_BST1_RM_L_SFT			13
-#define RT5616_G_OM_L_RM_L_MASK			(0x7 << 10)
-#define RT5616_G_OM_L_RM_L_SFT			10
-#define RT5616_M_IN2_L_RM_L			(0x1 << 6)
-#define RT5616_M_IN2_L_RM_L_SFT			6
-#define RT5616_M_IN1_L_RM_L			(0x1 << 5)
-#define RT5616_M_IN1_L_RM_L_SFT			5
-#define RT5616_M_BST3_RM_L			(0x1 << 3)
-#define RT5616_M_BST3_RM_L_SFT			3
-#define RT5616_M_BST2_RM_L			(0x1 << 2)
-#define RT5616_M_BST2_RM_L_SFT			2
-#define RT5616_M_BST1_RM_L			(0x1 << 1)
-#define RT5616_M_BST1_RM_L_SFT			1
-#define RT5616_M_OM_L_RM_L			(0x1)
-#define RT5616_M_OM_L_RM_L_SFT			0
-
-/* REC Right Mixer Control 1 (0x3d) */
-#define RT5616_G_IN2_R_RM_R_MASK		(0x7 << 13)
-#define RT5616_G_IN2_R_RM_R_SFT			13
-#define RT5616_G_IN1_R_RM_R_MASK		(0x7 << 10)
-#define RT5616_G_IN1_R_RM_R_SFT			10
-#define RT5616_G_BST3_RM_R_MASK			(0x7 << 4)
-#define RT5616_G_BST3_RM_R_SFT			4
-#define RT5616_G_BST2_RM_R_MASK			(0x7 << 1)
-#define RT5616_G_BST2_RM_R_SFT			1
-
-/* REC Right Mixer Control 2 (0x3e) */
-#define RT5616_G_BST1_RM_R_MASK			(0x7 << 13)
-#define RT5616_G_BST1_RM_R_SFT			13
-#define RT5616_G_OM_R_RM_R_MASK			(0x7 << 10)
-#define RT5616_G_OM_R_RM_R_SFT			10
-#define RT5616_M_IN2_R_RM_R			(0x1 << 6)
-#define RT5616_M_IN2_R_RM_R_SFT			6
-#define RT5616_M_IN1_R_RM_R			(0x1 << 5)
-#define RT5616_M_IN1_R_RM_R_SFT			5
-#define RT5616_M_BST3_RM_R			(0x1 << 3)
-#define RT5616_M_BST3_RM_R_SFT			3
-#define RT5616_M_BST2_RM_R			(0x1 << 2)
-#define RT5616_M_BST2_RM_R_SFT			2
-#define RT5616_M_BST1_RM_R			(0x1 << 1)
-#define RT5616_M_BST1_RM_R_SFT			1
-#define RT5616_M_OM_R_RM_R			(0x1)
-#define RT5616_M_OM_R_RM_R_SFT			0
-
-/* HPMIX Control (0x45) */
-#define RT5616_M_DAC1_HM			(0x1 << 14)
-#define RT5616_M_DAC1_HM_SFT			14
-#define RT5616_M_HPVOL_HM			(0x1 << 13)
-#define RT5616_M_HPVOL_HM_SFT			13
-#define RT5616_G_HPOMIX_MASK			(0x1 << 12)
-#define RT5616_G_HPOMIX_SFT			12
-
-/* SPK Left Mixer Control (0x46) */
-#define RT5616_G_RM_L_SM_L_MASK			(0x3 << 14)
-#define RT5616_G_RM_L_SM_L_SFT			14
-#define RT5616_G_IN_L_SM_L_MASK			(0x3 << 12)
-#define RT5616_G_IN_L_SM_L_SFT			12
-#define RT5616_G_DAC_L1_SM_L_MASK		(0x3 << 10)
-#define RT5616_G_DAC_L1_SM_L_SFT		10
-#define RT5616_G_DAC_L2_SM_L_MASK		(0x3 << 8)
-#define RT5616_G_DAC_L2_SM_L_SFT		8
-#define RT5616_G_OM_L_SM_L_MASK			(0x3 << 6)
-#define RT5616_G_OM_L_SM_L_SFT			6
-#define RT5616_M_RM_L_SM_L			(0x1 << 5)
-#define RT5616_M_RM_L_SM_L_SFT			5
-#define RT5616_M_IN_L_SM_L			(0x1 << 4)
-#define RT5616_M_IN_L_SM_L_SFT			4
-#define RT5616_M_DAC_L1_SM_L			(0x1 << 3)
-#define RT5616_M_DAC_L1_SM_L_SFT		3
-#define RT5616_M_DAC_L2_SM_L			(0x1 << 2)
-#define RT5616_M_DAC_L2_SM_L_SFT		2
-#define RT5616_M_OM_L_SM_L			(0x1 << 1)
-#define RT5616_M_OM_L_SM_L_SFT			1
-
-/* SPK Right Mixer Control (0x47) */
-#define RT5616_G_RM_R_SM_R_MASK			(0x3 << 14)
-#define RT5616_G_RM_R_SM_R_SFT			14
-#define RT5616_G_IN_R_SM_R_MASK			(0x3 << 12)
-#define RT5616_G_IN_R_SM_R_SFT			12
-#define RT5616_G_DAC_R1_SM_R_MASK		(0x3 << 10)
-#define RT5616_G_DAC_R1_SM_R_SFT		10
-#define RT5616_G_DAC_R2_SM_R_MASK		(0x3 << 8)
-#define RT5616_G_DAC_R2_SM_R_SFT		8
-#define RT5616_G_OM_R_SM_R_MASK			(0x3 << 6)
-#define RT5616_G_OM_R_SM_R_SFT			6
-#define RT5616_M_RM_R_SM_R			(0x1 << 5)
-#define RT5616_M_RM_R_SM_R_SFT			5
-#define RT5616_M_IN_R_SM_R			(0x1 << 4)
-#define RT5616_M_IN_R_SM_R_SFT			4
-#define RT5616_M_DAC_R1_SM_R			(0x1 << 3)
-#define RT5616_M_DAC_R1_SM_R_SFT		3
-#define RT5616_M_DAC_R2_SM_R			(0x1 << 2)
-#define RT5616_M_DAC_R2_SM_R_SFT		2
-#define RT5616_M_OM_R_SM_R			(0x1 << 1)
-#define RT5616_M_OM_R_SM_R_SFT			1
-
-/* SPOLMIX Control (0x48) */
-#define RT5616_M_DAC_R1_SPM_L			(0x1 << 15)
-#define RT5616_M_DAC_R1_SPM_L_SFT		15
-#define RT5616_M_DAC_L1_SPM_L			(0x1 << 14)
-#define RT5616_M_DAC_L1_SPM_L_SFT		14
-#define RT5616_M_SV_R_SPM_L			(0x1 << 13)
-#define RT5616_M_SV_R_SPM_L_SFT			13
-#define RT5616_M_SV_L_SPM_L			(0x1 << 12)
-#define RT5616_M_SV_L_SPM_L_SFT			12
-#define RT5616_M_BST1_SPM_L			(0x1 << 11)
-#define RT5616_M_BST1_SPM_L_SFT			11
-
-/* SPORMIX Control (0x49) */
-#define RT5616_M_DAC_R1_SPM_R			(0x1 << 13)
-#define RT5616_M_DAC_R1_SPM_R_SFT		13
-#define RT5616_M_SV_R_SPM_R			(0x1 << 12)
-#define RT5616_M_SV_R_SPM_R_SFT			12
-#define RT5616_M_BST1_SPM_R			(0x1 << 11)
-#define RT5616_M_BST1_SPM_R_SFT			11
-
-/* SPOLMIX / SPORMIX Ratio Control (0x4a) */
-#define RT5616_SPO_CLSD_RATIO_MASK		(0x7)
-#define RT5616_SPO_CLSD_RATIO_SFT		0
-
-/* Mono Output Mixer Control (0x4c) */
-#define RT5616_M_DAC_R2_MM			(0x1 << 15)
-#define RT5616_M_DAC_R2_MM_SFT			15
-#define RT5616_M_DAC_L2_MM			(0x1 << 14)
-#define RT5616_M_DAC_L2_MM_SFT			14
-#define RT5616_M_OV_R_MM			(0x1 << 13)
-#define RT5616_M_OV_R_MM_SFT			13
-#define RT5616_M_OV_L_MM			(0x1 << 12)
-#define RT5616_M_OV_L_MM_SFT			12
-#define RT5616_M_BST1_MM			(0x1 << 11)
-#define RT5616_M_BST1_MM_SFT			11
-#define RT5616_G_MONOMIX_MASK			(0x1 << 10)
-#define RT5616_G_MONOMIX_SFT			10
-
-/* Output Left Mixer Control 1 (0x4d) */
-#define RT5616_G_BST2_OM_L_MASK			(0x7 << 10)
-#define RT5616_G_BST2_OM_L_SFT			10
-#define RT5616_G_BST1_OM_L_MASK			(0x7 << 7)
-#define RT5616_G_BST1_OM_L_SFT			7
-#define RT5616_G_IN1_L_OM_L_MASK		(0x7 << 4)
-#define RT5616_G_IN1_L_OM_L_SFT			4
-#define RT5616_G_RM_L_OM_L_MASK			(0x7 << 1)
-#define RT5616_G_RM_L_OM_L_SFT			1
-
-/* Output Left Mixer Control 2 (0x4e) */
-#define RT5616_G_DAC_L1_OM_L_MASK		(0x7 << 7)
-#define RT5616_G_DAC_L1_OM_L_SFT		7
-#define RT5616_G_IN2_L_OM_L_MASK		(0x7 << 4)
-#define RT5616_G_IN2_L_OM_L_SFT			4
-
-/* Output Left Mixer Control 3 (0x4f) */
-#define RT5616_M_IN2_L_OM_L			(0x1 << 9)
-#define RT5616_M_IN2_L_OM_L_SFT			9
-#define RT5616_M_BST2_OM_L			(0x1 << 6)
-#define RT5616_M_BST2_OM_L_SFT			6
-#define RT5616_M_BST1_OM_L			(0x1 << 5)
-#define RT5616_M_BST1_OM_L_SFT			5
-#define RT5616_M_IN1_L_OM_L			(0x1 << 4)
-#define RT5616_M_IN1_L_OM_L_SFT			4
-#define RT5616_M_RM_L_OM_L			(0x1 << 3)
-#define RT5616_M_RM_L_OM_L_SFT			3
-#define RT5616_M_DAC_L1_OM_L			(0x1)
-#define RT5616_M_DAC_L1_OM_L_SFT		0
-
-/* Output Right Mixer Control 1 (0x50) */
-#define RT5616_G_BST2_OM_R_MASK			(0x7 << 10)
-#define RT5616_G_BST2_OM_R_SFT			10
-#define RT5616_G_BST1_OM_R_MASK			(0x7 << 7)
-#define RT5616_G_BST1_OM_R_SFT			7
-#define RT5616_G_IN1_R_OM_R_MASK		(0x7 << 4)
-#define RT5616_G_IN1_R_OM_R_SFT			4
-#define RT5616_G_RM_R_OM_R_MASK			(0x7 << 1)
-#define RT5616_G_RM_R_OM_R_SFT			1
-
-/* Output Right Mixer Control 2 (0x51) */
-#define RT5616_G_DAC_R1_OM_R_MASK		(0x7 << 7)
-#define RT5616_G_DAC_R1_OM_R_SFT		7
-#define RT5616_G_IN2_R_OM_R_MASK		(0x7 << 4)
-#define RT5616_G_IN2_R_OM_R_SFT			4
-
-/* Output Right Mixer Control 3 (0x52) */
-#define RT5616_M_IN2_R_OM_R			(0x1 << 9)
-#define RT5616_M_IN2_R_OM_R_SFT			9
-#define RT5616_M_BST2_OM_R			(0x1 << 6)
-#define RT5616_M_BST2_OM_R_SFT			6
-#define RT5616_M_BST1_OM_R			(0x1 << 5)
-#define RT5616_M_BST1_OM_R_SFT			5
-#define RT5616_M_IN1_R_OM_R			(0x1 << 4)
-#define RT5616_M_IN1_R_OM_R_SFT			4
-#define RT5616_M_RM_R_OM_R			(0x1 << 3)
-#define RT5616_M_RM_R_OM_R_SFT			3
-#define RT5616_M_DAC_R1_OM_R			(0x1)
-#define RT5616_M_DAC_R1_OM_R_SFT		0
-
-/* LOUT Mixer Control (0x53) */
-#define RT5616_M_DAC_L1_LM			(0x1 << 15)
-#define RT5616_M_DAC_L1_LM_SFT			15
-#define RT5616_M_DAC_R1_LM			(0x1 << 14)
-#define RT5616_M_DAC_R1_LM_SFT			14
-#define RT5616_M_OV_L_LM			(0x1 << 13)
-#define RT5616_M_OV_L_LM_SFT			13
-#define RT5616_M_OV_R_LM			(0x1 << 12)
-#define RT5616_M_OV_R_LM_SFT			12
-#define RT5616_G_LOUTMIX_MASK			(0x1 << 11)
-#define RT5616_G_LOUTMIX_SFT			11
-
-/* Power Management for Digital 1 (0x61) */
-#define RT5616_PWR_I2S1				(0x1 << 15)
-#define RT5616_PWR_I2S1_BIT			15
-#define RT5616_PWR_I2S2				(0x1 << 14)
-#define RT5616_PWR_I2S2_BIT			14
-#define RT5616_PWR_DAC_L1			(0x1 << 12)
-#define RT5616_PWR_DAC_L1_BIT			12
-#define RT5616_PWR_DAC_R1			(0x1 << 11)
-#define RT5616_PWR_DAC_R1_BIT			11
-#define RT5616_PWR_ADC_L			(0x1 << 2)
-#define RT5616_PWR_ADC_L_BIT			2
-#define RT5616_PWR_ADC_R			(0x1 << 1)
-#define RT5616_PWR_ADC_R_BIT			1
-
-/* Power Management for Digital 2 (0x62) */
-#define RT5616_PWR_ADC_STO1_F			(0x1 << 15)
-#define RT5616_PWR_ADC_STO1_F_BIT		15
-#define RT5616_PWR_DAC_STO1_F			(0x1 << 11)
-#define RT5616_PWR_DAC_STO1_F_BIT		11
-
-/* Power Management for Analog 1 (0x63) */
-#define RT5616_PWR_VREF1			(0x1 << 15)
-#define RT5616_PWR_VREF1_BIT			15
-#define RT5616_PWR_FV1				(0x1 << 14)
-#define RT5616_PWR_FV1_BIT			14
-#define RT5616_PWR_MB				(0x1 << 13)
-#define RT5616_PWR_MB_BIT			13
-#define RT5616_PWR_LM				(0x1 << 12)
-#define RT5616_PWR_LM_BIT			12
-#define RT5616_PWR_BG				(0x1 << 11)
-#define RT5616_PWR_BG_BIT			11
-#define RT5616_PWR_HP_L				(0x1 << 7)
-#define RT5616_PWR_HP_L_BIT			7
-#define RT5616_PWR_HP_R				(0x1 << 6)
-#define RT5616_PWR_HP_R_BIT			6
-#define RT5616_PWR_HA				(0x1 << 5)
-#define RT5616_PWR_HA_BIT			5
-#define RT5616_PWR_VREF2			(0x1 << 4)
-#define RT5616_PWR_VREF2_BIT			4
-#define RT5616_PWR_FV2				(0x1 << 3)
-#define RT5616_PWR_FV2_BIT			3
-#define RT5616_PWR_LDO				(0x1 << 2)
-#define RT5616_PWR_LDO_BIT			2
-#define RT5616_PWR_LDO_DVO_MASK			(0x3)
-#define RT5616_PWR_LDO_DVO_1_0V			0
-#define RT5616_PWR_LDO_DVO_1_1V			1
-#define RT5616_PWR_LDO_DVO_1_2V			2
-#define RT5616_PWR_LDO_DVO_1_3V			3
-
-/* Power Management for Analog 2 (0x64) */
-#define RT5616_PWR_BST1				(0x1 << 15)
-#define RT5616_PWR_BST1_BIT			15
-#define RT5616_PWR_BST2				(0x1 << 14)
-#define RT5616_PWR_BST2_BIT			14
-#define RT5616_PWR_MB1				(0x1 << 11)
-#define RT5616_PWR_MB1_BIT			11
-#define RT5616_PWR_PLL				(0x1 << 9)
-#define RT5616_PWR_PLL_BIT			9
-#define RT5616_PWR_BST1_OP2			(0x1 << 5)
-#define RT5616_PWR_BST1_OP2_BIT			5
-#define RT5616_PWR_BST2_OP2			(0x1 << 4)
-#define RT5616_PWR_BST2_OP2_BIT			4
-#define RT5616_PWR_BST3_OP2			(0x1 << 3)
-#define RT5616_PWR_BST3_OP2_BIT			3
-#define RT5616_PWR_JD_M				(0x1 << 2)
-#define RT5616_PWM_JD_M_BIT			2
-#define RT5616_PWR_JD2				(0x1 << 1)
-#define RT5616_PWM_JD2_BIT			1
-#define RT5616_PWR_JD3				(0x1)
-#define RT5616_PWM_JD3_BIT			0
-
-/* Power Management for Mixer (0x65) */
-#define RT5616_PWR_OM_L				(0x1 << 15)
-#define RT5616_PWR_OM_L_BIT			15
-#define RT5616_PWR_OM_R				(0x1 << 14)
-#define RT5616_PWR_OM_R_BIT			14
-#define RT5616_PWR_RM_L				(0x1 << 11)
-#define RT5616_PWR_RM_L_BIT			11
-#define RT5616_PWR_RM_R				(0x1 << 10)
-#define RT5616_PWR_RM_R_BIT			10
-
-/* Power Management for Volume (0x66) */
-#define RT5616_PWR_OV_L				(0x1 << 13)
-#define RT5616_PWR_OV_L_BIT			13
-#define RT5616_PWR_OV_R				(0x1 << 12)
-#define RT5616_PWR_OV_R_BIT			12
-#define RT5616_PWR_HV_L				(0x1 << 11)
-#define RT5616_PWR_HV_L_BIT			11
-#define RT5616_PWR_HV_R				(0x1 << 10)
-#define RT5616_PWR_HV_R_BIT			10
-#define RT5616_PWR_IN1_L			(0x1 << 9)
-#define RT5616_PWR_IN1_L_BIT			9
-#define RT5616_PWR_IN1_R			(0x1 << 8)
-#define RT5616_PWR_IN1_R_BIT			8
-#define RT5616_PWR_IN2_L			(0x1 << 7)
-#define RT5616_PWR_IN2_L_BIT			7
-#define RT5616_PWR_IN2_R			(0x1 << 6)
-#define RT5616_PWR_IN2_R_BIT			6
-
-/* I2S1/2/3 Audio Serial Data Port Control (0x70 0x71) */
-#define RT5616_I2S_MS_MASK			(0x1 << 15)
-#define RT5616_I2S_MS_SFT			15
-#define RT5616_I2S_MS_M				(0x0 << 15)
-#define RT5616_I2S_MS_S				(0x1 << 15)
-#define RT5616_I2S_O_CP_MASK			(0x3 << 10)
-#define RT5616_I2S_O_CP_SFT			10
-#define RT5616_I2S_O_CP_OFF			(0x0 << 10)
-#define RT5616_I2S_O_CP_U_LAW			(0x1 << 10)
-#define RT5616_I2S_O_CP_A_LAW			(0x2 << 10)
-#define RT5616_I2S_I_CP_MASK			(0x3 << 8)
-#define RT5616_I2S_I_CP_SFT			8
-#define RT5616_I2S_I_CP_OFF			(0x0 << 8)
-#define RT5616_I2S_I_CP_U_LAW			(0x1 << 8)
-#define RT5616_I2S_I_CP_A_LAW			(0x2 << 8)
-#define RT5616_I2S_BP_MASK			(0x1 << 7)
-#define RT5616_I2S_BP_SFT			7
-#define RT5616_I2S_BP_NOR			(0x0 << 7)
-#define RT5616_I2S_BP_INV			(0x1 << 7)
-#define RT5616_I2S_DL_MASK			(0x3 << 2)
-#define RT5616_I2S_DL_SFT			2
-#define RT5616_I2S_DL_16			(0x0 << 2)
-#define RT5616_I2S_DL_20			(0x1 << 2)
-#define RT5616_I2S_DL_24			(0x2 << 2)
-#define RT5616_I2S_DL_8				(0x3 << 2)
-#define RT5616_I2S_DF_MASK			(0x3)
-#define RT5616_I2S_DF_SFT			0
-#define RT5616_I2S_DF_I2S			(0x0)
-#define RT5616_I2S_DF_LEFT			(0x1)
-#define RT5616_I2S_DF_PCM_A			(0x2)
-#define RT5616_I2S_DF_PCM_B			(0x3)
-
-/* ADC/DAC Clock Control 1 (0x73) */
-#define RT5616_I2S_PD1_MASK			(0x7 << 12)
-#define RT5616_I2S_PD1_SFT			12
-#define RT5616_I2S_PD1_1			(0x0 << 12)
-#define RT5616_I2S_PD1_2			(0x1 << 12)
-#define RT5616_I2S_PD1_3			(0x2 << 12)
-#define RT5616_I2S_PD1_4			(0x3 << 12)
-#define RT5616_I2S_PD1_6			(0x4 << 12)
-#define RT5616_I2S_PD1_8			(0x5 << 12)
-#define RT5616_I2S_PD1_12			(0x6 << 12)
-#define RT5616_I2S_PD1_16			(0x7 << 12)
-#define RT5616_I2S_BCLK_MS2_MASK		(0x1 << 11)
-#define RT5616_DAC_OSR_MASK			(0x3 << 2)
-#define RT5616_DAC_OSR_SFT			2
-#define RT5616_DAC_OSR_128			(0x0 << 2)
-#define RT5616_DAC_OSR_64			(0x1 << 2)
-#define RT5616_DAC_OSR_32			(0x2 << 2)
-#define RT5616_DAC_OSR_128_3			(0x3 << 2)
-#define RT5616_ADC_OSR_MASK			(0x3)
-#define RT5616_ADC_OSR_SFT			0
-#define RT5616_ADC_OSR_128			(0x0)
-#define RT5616_ADC_OSR_64			(0x1)
-#define RT5616_ADC_OSR_32			(0x2)
-#define RT5616_ADC_OSR_128_3			(0x3)
-
-/* ADC/DAC Clock Control 2 (0x74) */
-#define RT5616_DAHPF_EN				(0x1 << 11)
-#define RT5616_DAHPF_EN_SFT			11
-#define RT5616_ADHPF_EN				(0x1 << 10)
-#define RT5616_ADHPF_EN_SFT			10
-
-/* TDM Control 1 (0x77) */
-#define RT5616_TDM_INTEL_SEL_MASK		(0x1 << 15)
-#define RT5616_TDM_INTEL_SEL_SFT		15
-#define RT5616_TDM_INTEL_SEL_64			(0x0 << 15)
-#define RT5616_TDM_INTEL_SEL_50			(0x1 << 15)
-#define RT5616_TDM_MODE_SEL_MASK		(0x1 << 14)
-#define RT5616_TDM_MODE_SEL_SFT			14
-#define RT5616_TDM_MODE_SEL_NOR			(0x0 << 14)
-#define RT5616_TDM_MODE_SEL_TDM			(0x1 << 14)
-#define RT5616_TDM_CH_NUM_SEL_MASK		(0x3 << 12)
-#define RT5616_TDM_CH_NUM_SEL_SFT		12
-#define RT5616_TDM_CH_NUM_SEL_2			(0x0 << 12)
-#define RT5616_TDM_CH_NUM_SEL_4			(0x1 << 12)
-#define RT5616_TDM_CH_NUM_SEL_6			(0x2 << 12)
-#define RT5616_TDM_CH_NUM_SEL_8			(0x3 << 12)
-#define RT5616_TDM_CH_LEN_SEL_MASK		(0x3 << 10)
-#define RT5616_TDM_CH_LEN_SEL_SFT		10
-#define RT5616_TDM_CH_LEN_SEL_16		(0x0 << 10)
-#define RT5616_TDM_CH_LEN_SEL_20		(0x1 << 10)
-#define RT5616_TDM_CH_LEN_SEL_24		(0x2 << 10)
-#define RT5616_TDM_CH_LEN_SEL_32		(0x3 << 10)
-#define RT5616_TDM_ADC_SEL_MASK			(0x1 << 9)
-#define RT5616_TDM_ADC_SEL_SFT			9
-#define RT5616_TDM_ADC_SEL_NOR			(0x0 << 9)
-#define RT5616_TDM_ADC_SEL_SWAP			(0x1 << 9)
-#define RT5616_TDM_ADC_START_SEL_MASK		(0x1 << 8)
-#define RT5616_TDM_ADC_START_SEL_SFT		8
-#define RT5616_TDM_ADC_START_SEL_SL0		(0x0 << 8)
-#define RT5616_TDM_ADC_START_SEL_SL4		(0x1 << 8)
-#define RT5616_TDM_I2S_CH2_SEL_MASK		(0x3 << 6)
-#define RT5616_TDM_I2S_CH2_SEL_SFT		6
-#define RT5616_TDM_I2S_CH2_SEL_LR		(0x0 << 6)
-#define RT5616_TDM_I2S_CH2_SEL_RL		(0x1 << 6)
-#define RT5616_TDM_I2S_CH2_SEL_LL		(0x2 << 6)
-#define RT5616_TDM_I2S_CH2_SEL_RR		(0x3 << 6)
-#define RT5616_TDM_I2S_CH4_SEL_MASK		(0x3 << 4)
-#define RT5616_TDM_I2S_CH4_SEL_SFT		4
-#define RT5616_TDM_I2S_CH4_SEL_LR		(0x0 << 4)
-#define RT5616_TDM_I2S_CH4_SEL_RL		(0x1 << 4)
-#define RT5616_TDM_I2S_CH4_SEL_LL		(0x2 << 4)
-#define RT5616_TDM_I2S_CH4_SEL_RR		(0x3 << 4)
-#define RT5616_TDM_I2S_CH6_SEL_MASK		(0x3 << 2)
-#define RT5616_TDM_I2S_CH6_SEL_SFT		2
-#define RT5616_TDM_I2S_CH6_SEL_LR		(0x0 << 2)
-#define RT5616_TDM_I2S_CH6_SEL_RL		(0x1 << 2)
-#define RT5616_TDM_I2S_CH6_SEL_LL		(0x2 << 2)
-#define RT5616_TDM_I2S_CH6_SEL_RR		(0x3 << 2)
-#define RT5616_TDM_I2S_CH8_SEL_MASK		(0x3)
-#define RT5616_TDM_I2S_CH8_SEL_SFT		0
-#define RT5616_TDM_I2S_CH8_SEL_LR		(0x0)
-#define RT5616_TDM_I2S_CH8_SEL_RL		(0x1)
-#define RT5616_TDM_I2S_CH8_SEL_LL		(0x2)
-#define RT5616_TDM_I2S_CH8_SEL_RR		(0x3)
-
-/* TDM Control 2 (0x78) */
-#define RT5616_TDM_LRCK_POL_SEL_MASK		(0x1 << 15)
-#define RT5616_TDM_LRCK_POL_SEL_SFT		15
-#define RT5616_TDM_LRCK_POL_SEL_NOR		(0x0 << 15)
-#define RT5616_TDM_LRCK_POL_SEL_INV		(0x1 << 15)
-#define RT5616_TDM_CH_VAL_SEL_MASK		(0x1 << 14)
-#define RT5616_TDM_CH_VAL_SEL_SFT		14
-#define RT5616_TDM_CH_VAL_SEL_CH01		(0x0 << 14)
-#define RT5616_TDM_CH_VAL_SEL_CH0123		(0x1 << 14)
-#define RT5616_TDM_CH_VAL_EN			(0x1 << 13)
-#define RT5616_TDM_CH_VAL_SFT			13
-#define RT5616_TDM_LPBK_EN			(0x1 << 12)
-#define RT5616_TDM_LPBK_SFT			12
-#define RT5616_TDM_LRCK_PULSE_SEL_MASK		(0x1 << 11)
-#define RT5616_TDM_LRCK_PULSE_SEL_SFT		11
-#define RT5616_TDM_LRCK_PULSE_SEL_BCLK		(0x0 << 11)
-#define RT5616_TDM_LRCK_PULSE_SEL_CH		(0x1 << 11)
-#define RT5616_TDM_END_EDGE_SEL_MASK		(0x1 << 10)
-#define RT5616_TDM_END_EDGE_SEL_SFT		10
-#define RT5616_TDM_END_EDGE_SEL_POS		(0x0 << 10)
-#define RT5616_TDM_END_EDGE_SEL_NEG		(0x1 << 10)
-#define RT5616_TDM_END_EDGE_EN			(0x1 << 9)
-#define RT5616_TDM_END_EDGE_EN_SFT		9
-#define RT5616_TDM_TRAN_EDGE_SEL_MASK		(0x1 << 8)
-#define RT5616_TDM_TRAN_EDGE_SEL_SFT		8
-#define RT5616_TDM_TRAN_EDGE_SEL_POS		(0x0 << 8)
-#define RT5616_TDM_TRAN_EDGE_SEL_NEG		(0x1 << 8)
-#define RT5616_M_TDM2_L				(0x1 << 7)
-#define RT5616_M_TDM2_L_SFT			7
-#define RT5616_M_TDM2_R				(0x1 << 6)
-#define RT5616_M_TDM2_R_SFT			6
-#define RT5616_M_TDM4_L				(0x1 << 5)
-#define RT5616_M_TDM4_L_SFT			5
-#define RT5616_M_TDM4_R				(0x1 << 4)
-#define RT5616_M_TDM4_R_SFT			4
-
-/* Global Clock Control (0x80) */
-#define RT5616_SCLK_SRC_MASK			(0x3 << 14)
-#define RT5616_SCLK_SRC_SFT			14
-#define RT5616_SCLK_SRC_MCLK			(0x0 << 14)
-#define RT5616_SCLK_SRC_PLL1			(0x1 << 14)
-#define RT5616_PLL1_SRC_MASK			(0x3 << 12)
-#define RT5616_PLL1_SRC_SFT			12
-#define RT5616_PLL1_SRC_MCLK			(0x0 << 12)
-#define RT5616_PLL1_SRC_BCLK1			(0x1 << 12)
-#define RT5616_PLL1_SRC_BCLK2			(0x2 << 12)
-#define RT5616_PLL1_PD_MASK			(0x1 << 3)
-#define RT5616_PLL1_PD_SFT			3
-#define RT5616_PLL1_PD_1			(0x0 << 3)
-#define RT5616_PLL1_PD_2			(0x1 << 3)
-
-#define RT5616_PLL_INP_MAX			40000000
-#define RT5616_PLL_INP_MIN			256000
-/* PLL M/N/K Code Control 1 (0x81) */
-#define RT5616_PLL_N_MAX			0x1ff
-#define RT5616_PLL_N_MASK			(RT5616_PLL_N_MAX << 7)
-#define RT5616_PLL_N_SFT			7
-#define RT5616_PLL_K_MAX			0x1f
-#define RT5616_PLL_K_MASK			(RT5616_PLL_K_MAX)
-#define RT5616_PLL_K_SFT			0
-
-/* PLL M/N/K Code Control 2 (0x82) */
-#define RT5616_PLL_M_MAX			0xf
-#define RT5616_PLL_M_MASK			(RT5616_PLL_M_MAX << 12)
-#define RT5616_PLL_M_SFT			12
-#define RT5616_PLL_M_BP				(0x1 << 11)
-#define RT5616_PLL_M_BP_SFT			11
-
-/* PLL tracking mode 1 (0x83) */
-#define RT5616_STO1_T_MASK			(0x1 << 15)
-#define RT5616_STO1_T_SFT			15
-#define RT5616_STO1_T_SCLK			(0x0 << 15)
-#define RT5616_STO1_T_LRCK1			(0x1 << 15)
-#define RT5616_STO2_T_MASK			(0x1 << 12)
-#define RT5616_STO2_T_SFT			12
-#define RT5616_STO2_T_I2S2			(0x0 << 12)
-#define RT5616_STO2_T_LRCK2			(0x1 << 12)
-#define RT5616_ASRC2_REF_MASK			(0x1 << 11)
-#define RT5616_ASRC2_REF_SFT			11
-#define RT5616_ASRC2_REF_LRCK2			(0x0 << 11)
-#define RT5616_ASRC2_REF_LRCK1			(0x1 << 11)
-#define RT5616_DMIC_1_M_MASK			(0x1 << 9)
-#define RT5616_DMIC_1_M_SFT			9
-#define RT5616_DMIC_1_M_NOR			(0x0 << 9)
-#define RT5616_DMIC_1_M_ASYN			(0x1 << 9)
-
-/* PLL tracking mode 2 (0x84) */
-#define RT5616_STO1_ASRC_EN			(0x1 << 15)
-#define RT5616_STO1_ASRC_EN_SFT			15
-#define RT5616_STO2_ASRC_EN			(0x1 << 14)
-#define RT5616_STO2_ASRC_EN_SFT			14
-#define RT5616_STO1_DAC_M_MASK			(0x1 << 13)
-#define RT5616_STO1_DAC_M_SFT			13
-#define RT5616_STO1_DAC_M_NOR			(0x0 << 13)
-#define RT5616_STO1_DAC_M_ASRC			(0x1 << 13)
-#define RT5616_STO2_DAC_M_MASK			(0x1 << 12)
-#define RT5616_STO2_DAC_M_SFT			12
-#define RT5616_STO2_DAC_M_NOR			(0x0 << 12)
-#define RT5616_STO2_DAC_M_ASRC			(0x1 << 12)
-#define RT5616_ADC_M_MASK			(0x1 << 11)
-#define RT5616_ADC_M_SFT			11
-#define RT5616_ADC_M_NOR			(0x0 << 11)
-#define RT5616_ADC_M_ASRC			(0x1 << 11)
-#define RT5616_I2S1_R_D_MASK			(0x1 << 4)
-#define RT5616_I2S1_R_D_SFT			4
-#define RT5616_I2S1_R_D_DIS			(0x0 << 4)
-#define RT5616_I2S1_R_D_EN			(0x1 << 4)
-#define RT5616_I2S2_R_D_MASK			(0x1 << 3)
-#define RT5616_I2S2_R_D_SFT			3
-#define RT5616_I2S2_R_D_DIS			(0x0 << 3)
-#define RT5616_I2S2_R_D_EN			(0x1 << 3)
-#define RT5616_PRE_SCLK_MASK			(0x3)
-#define RT5616_PRE_SCLK_SFT			0
-#define RT5616_PRE_SCLK_512			(0x0)
-#define RT5616_PRE_SCLK_1024			(0x1)
-#define RT5616_PRE_SCLK_2048			(0x2)
-
-/* PLL tracking mode 3 (0x85) */
-#define RT5616_I2S1_RATE_MASK			(0xf << 12)
-#define RT5616_I2S1_RATE_SFT			12
-#define RT5616_I2S2_RATE_MASK			(0xf << 8)
-#define RT5616_I2S2_RATE_SFT			8
-#define RT5616_G_ASRC_LP_MASK			(0x1 << 3)
-#define RT5616_G_ASRC_LP_SFT			3
-#define RT5616_ASRC_LP_F_M			(0x1 << 2)
-#define RT5616_ASRC_LP_F_SFT			2
-#define RT5616_ASRC_LP_F_NOR			(0x0 << 2)
-#define RT5616_ASRC_LP_F_SB			(0x1 << 2)
-#define RT5616_FTK_PH_DET_MASK			(0x3)
-#define RT5616_FTK_PH_DET_SFT			0
-#define RT5616_FTK_PH_DET_DIV1			(0x0)
-#define RT5616_FTK_PH_DET_DIV2			(0x1)
-#define RT5616_FTK_PH_DET_DIV4			(0x2)
-#define RT5616_FTK_PH_DET_DIV8			(0x3)
-
-/*PLL tracking mode 6 (0x89) */
-#define RT5616_I2S1_PD_MASK			(0x7 << 12)
-#define RT5616_I2S1_PD_SFT			12
-#define RT5616_I2S2_PD_MASK			(0x7 << 8)
-#define RT5616_I2S2_PD_SFT			8
-
-/*PLL tracking mode 7 (0x8a) */
-#define RT5616_FSI1_RATE_MASK			(0xf << 12)
-#define RT5616_FSI1_RATE_SFT			12
-#define RT5616_FSI2_RATE_MASK			(0xf << 8)
-#define RT5616_FSI2_RATE_SFT			8
-
-/* HPOUT Over Current Detection (0x8b) */
-#define RT5616_HP_OVCD_MASK			(0x1 << 10)
-#define RT5616_HP_OVCD_SFT			10
-#define RT5616_HP_OVCD_DIS			(0x0 << 10)
-#define RT5616_HP_OVCD_EN			(0x1 << 10)
-#define RT5616_HP_OC_TH_MASK			(0x3 << 8)
-#define RT5616_HP_OC_TH_SFT			8
-#define RT5616_HP_OC_TH_90			(0x0 << 8)
-#define RT5616_HP_OC_TH_105			(0x1 << 8)
-#define RT5616_HP_OC_TH_120			(0x2 << 8)
-#define RT5616_HP_OC_TH_135			(0x3 << 8)
-
-/* Depop Mode Control 1 (0x8e) */
-#define RT5616_SMT_TRIG_MASK			(0x1 << 15)
-#define RT5616_SMT_TRIG_SFT			15
-#define RT5616_SMT_TRIG_DIS			(0x0 << 15)
-#define RT5616_SMT_TRIG_EN			(0x1 << 15)
-#define RT5616_HP_L_SMT_MASK			(0x1 << 9)
-#define RT5616_HP_L_SMT_SFT			9
-#define RT5616_HP_L_SMT_DIS			(0x0 << 9)
-#define RT5616_HP_L_SMT_EN			(0x1 << 9)
-#define RT5616_HP_R_SMT_MASK			(0x1 << 8)
-#define RT5616_HP_R_SMT_SFT			8
-#define RT5616_HP_R_SMT_DIS			(0x0 << 8)
-#define RT5616_HP_R_SMT_EN			(0x1 << 8)
-#define RT5616_HP_CD_PD_MASK			(0x1 << 7)
-#define RT5616_HP_CD_PD_SFT			7
-#define RT5616_HP_CD_PD_DIS			(0x0 << 7)
-#define RT5616_HP_CD_PD_EN			(0x1 << 7)
-#define RT5616_RSTN_MASK			(0x1 << 6)
-#define RT5616_RSTN_SFT				6
-#define RT5616_RSTN_DIS				(0x0 << 6)
-#define RT5616_RSTN_EN				(0x1 << 6)
-#define RT5616_RSTP_MASK			(0x1 << 5)
-#define RT5616_RSTP_SFT				5
-#define RT5616_RSTP_DIS				(0x0 << 5)
-#define RT5616_RSTP_EN				(0x1 << 5)
-#define RT5616_HP_CO_MASK			(0x1 << 4)
-#define RT5616_HP_CO_SFT			4
-#define RT5616_HP_CO_DIS			(0x0 << 4)
-#define RT5616_HP_CO_EN				(0x1 << 4)
-#define RT5616_HP_CP_MASK			(0x1 << 3)
-#define RT5616_HP_CP_SFT			3
-#define RT5616_HP_CP_PD				(0x0 << 3)
-#define RT5616_HP_CP_PU				(0x1 << 3)
-#define RT5616_HP_SG_MASK			(0x1 << 2)
-#define RT5616_HP_SG_SFT			2
-#define RT5616_HP_SG_DIS			(0x0 << 2)
-#define RT5616_HP_SG_EN				(0x1 << 2)
-#define RT5616_HP_DP_MASK			(0x1 << 1)
-#define RT5616_HP_DP_SFT			1
-#define RT5616_HP_DP_PD				(0x0 << 1)
-#define RT5616_HP_DP_PU				(0x1 << 1)
-#define RT5616_HP_CB_MASK			(0x1)
-#define RT5616_HP_CB_SFT			0
-#define RT5616_HP_CB_PD				(0x0)
-#define RT5616_HP_CB_PU				(0x1)
-
-/* Depop Mode Control 2 (0x8f) */
-#define RT5616_DEPOP_MASK			(0x1 << 13)
-#define RT5616_DEPOP_SFT			13
-#define RT5616_DEPOP_AUTO			(0x0 << 13)
-#define RT5616_DEPOP_MAN			(0x1 << 13)
-#define RT5616_RAMP_MASK			(0x1 << 12)
-#define RT5616_RAMP_SFT				12
-#define RT5616_RAMP_DIS				(0x0 << 12)
-#define RT5616_RAMP_EN				(0x1 << 12)
-#define RT5616_BPS_MASK				(0x1 << 11)
-#define RT5616_BPS_SFT				11
-#define RT5616_BPS_DIS				(0x0 << 11)
-#define RT5616_BPS_EN				(0x1 << 11)
-#define RT5616_FAST_UPDN_MASK			(0x1 << 10)
-#define RT5616_FAST_UPDN_SFT			10
-#define RT5616_FAST_UPDN_DIS			(0x0 << 10)
-#define RT5616_FAST_UPDN_EN			(0x1 << 10)
-#define RT5616_MRES_MASK			(0x3 << 8)
-#define RT5616_MRES_SFT				8
-#define RT5616_MRES_15MO			(0x0 << 8)
-#define RT5616_MRES_25MO			(0x1 << 8)
-#define RT5616_MRES_35MO			(0x2 << 8)
-#define RT5616_MRES_45MO			(0x3 << 8)
-#define RT5616_VLO_MASK				(0x1 << 7)
-#define RT5616_VLO_SFT				7
-#define RT5616_VLO_3V				(0x0 << 7)
-#define RT5616_VLO_32V				(0x1 << 7)
-#define RT5616_DIG_DP_MASK			(0x1 << 6)
-#define RT5616_DIG_DP_SFT			6
-#define RT5616_DIG_DP_DIS			(0x0 << 6)
-#define RT5616_DIG_DP_EN			(0x1 << 6)
-#define RT5616_DP_TH_MASK			(0x3 << 4)
-#define RT5616_DP_TH_SFT			4
-
-/* Depop Mode Control 3 (0x90) */
-#define RT5616_CP_SYS_MASK			(0x7 << 12)
-#define RT5616_CP_SYS_SFT			12
-#define RT5616_CP_FQ1_MASK			(0x7 << 8)
-#define RT5616_CP_FQ1_SFT			8
-#define RT5616_CP_FQ2_MASK			(0x7 << 4)
-#define RT5616_CP_FQ2_SFT			4
-#define RT5616_CP_FQ3_MASK			(0x7)
-#define RT5616_CP_FQ3_SFT			0
-#define RT5616_CP_FQ_1_5_KHZ			0
-#define RT5616_CP_FQ_3_KHZ			1
-#define RT5616_CP_FQ_6_KHZ			2
-#define RT5616_CP_FQ_12_KHZ			3
-#define RT5616_CP_FQ_24_KHZ			4
-#define RT5616_CP_FQ_48_KHZ			5
-#define RT5616_CP_FQ_96_KHZ			6
-#define RT5616_CP_FQ_192_KHZ			7
-
-/* HPOUT charge pump (0x91) */
-#define RT5616_OSW_L_MASK			(0x1 << 11)
-#define RT5616_OSW_L_SFT			11
-#define RT5616_OSW_L_DIS			(0x0 << 11)
-#define RT5616_OSW_L_EN				(0x1 << 11)
-#define RT5616_OSW_R_MASK			(0x1 << 10)
-#define RT5616_OSW_R_SFT			10
-#define RT5616_OSW_R_DIS			(0x0 << 10)
-#define RT5616_OSW_R_EN				(0x1 << 10)
-#define RT5616_PM_HP_MASK			(0x3 << 8)
-#define RT5616_PM_HP_SFT			8
-#define RT5616_PM_HP_LV				(0x0 << 8)
-#define RT5616_PM_HP_MV				(0x1 << 8)
-#define RT5616_PM_HP_HV				(0x2 << 8)
-#define RT5616_IB_HP_MASK			(0x3 << 6)
-#define RT5616_IB_HP_SFT			6
-#define RT5616_IB_HP_125IL			(0x0 << 6)
-#define RT5616_IB_HP_25IL			(0x1 << 6)
-#define RT5616_IB_HP_5IL			(0x2 << 6)
-#define RT5616_IB_HP_1IL			(0x3 << 6)
-
-/* Micbias Control (0x93) */
-#define RT5616_MIC1_BS_MASK			(0x1 << 15)
-#define RT5616_MIC1_BS_SFT			15
-#define RT5616_MIC1_BS_9AV			(0x0 << 15)
-#define RT5616_MIC1_BS_75AV			(0x1 << 15)
-#define RT5616_MIC1_CLK_MASK			(0x1 << 13)
-#define RT5616_MIC1_CLK_SFT			13
-#define RT5616_MIC1_CLK_DIS			(0x0 << 13)
-#define RT5616_MIC1_CLK_EN			(0x1 << 13)
-#define RT5616_MIC1_OVCD_MASK			(0x1 << 11)
-#define RT5616_MIC1_OVCD_SFT			11
-#define RT5616_MIC1_OVCD_DIS			(0x0 << 11)
-#define RT5616_MIC1_OVCD_EN			(0x1 << 11)
-#define RT5616_MIC1_OVTH_MASK			(0x3 << 9)
-#define RT5616_MIC1_OVTH_SFT			9
-#define RT5616_MIC1_OVTH_600UA			(0x0 << 9)
-#define RT5616_MIC1_OVTH_1500UA			(0x1 << 9)
-#define RT5616_MIC1_OVTH_2000UA			(0x2 << 9)
-#define RT5616_PWR_MB_MASK			(0x1 << 5)
-#define RT5616_PWR_MB_SFT			5
-#define RT5616_PWR_MB_PD			(0x0 << 5)
-#define RT5616_PWR_MB_PU			(0x1 << 5)
-#define RT5616_PWR_CLK12M_MASK			(0x1 << 4)
-#define RT5616_PWR_CLK12M_SFT			4
-#define RT5616_PWR_CLK12M_PD			(0x0 << 4)
-#define RT5616_PWR_CLK12M_PU			(0x1 << 4)
-
-/* Analog JD Control 1 (0x94) */
-#define RT5616_JD2_CMP_MASK			(0x7 << 12)
-#define RT5616_JD2_CMP_SFT			12
-#define RT5616_JD_PU				(0x1 << 11)
-#define RT5616_JD_PU_SFT			11
-#define RT5616_JD_PD				(0x1 << 10)
-#define RT5616_JD_PD_SFT			10
-#define RT5616_JD_MODE_SEL_MASK			(0x3 << 8)
-#define RT5616_JD_MODE_SEL_SFT			8
-#define RT5616_JD_MODE_SEL_M0			(0x0 << 8)
-#define RT5616_JD_MODE_SEL_M1			(0x1 << 8)
-#define RT5616_JD_MODE_SEL_M2			(0x2 << 8)
-#define RT5616_JD_M_CMP				(0x7 << 4)
-#define RT5616_JD_M_CMP_SFT			4
-#define RT5616_JD_M_PU				(0x1 << 3)
-#define RT5616_JD_M_PU_SFT			3
-#define RT5616_JD_M_PD				(0x1 << 2)
-#define RT5616_JD_M_PD_SFT			2
-#define RT5616_JD_M_MODE_SEL_MASK		(0x3)
-#define RT5616_JD_M_MODE_SEL_SFT		0
-#define RT5616_JD_M_MODE_SEL_M0			(0x0)
-#define RT5616_JD_M_MODE_SEL_M1			(0x1)
-#define RT5616_JD_M_MODE_SEL_M2			(0x2)
-
-/* Analog JD Control 2 (0x95) */
-#define RT5616_JD3_CMP_MASK			(0x7 << 12)
-#define RT5616_JD3_CMP_SFT			12
-
-/* EQ Control 1 (0xb0) */
-#define RT5616_EQ_SRC_MASK			(0x1 << 15)
-#define RT5616_EQ_SRC_SFT			15
-#define RT5616_EQ_SRC_DAC			(0x0 << 15)
-#define RT5616_EQ_SRC_ADC			(0x1 << 15)
-#define RT5616_EQ_UPD				(0x1 << 14)
-#define RT5616_EQ_UPD_BIT			14
-#define RT5616_EQ_CD_MASK			(0x1 << 13)
-#define RT5616_EQ_CD_SFT			13
-#define RT5616_EQ_CD_DIS			(0x0 << 13)
-#define RT5616_EQ_CD_EN				(0x1 << 13)
-#define RT5616_EQ_DITH_MASK			(0x3 << 8)
-#define RT5616_EQ_DITH_SFT			8
-#define RT5616_EQ_DITH_NOR			(0x0 << 8)
-#define RT5616_EQ_DITH_LSB			(0x1 << 8)
-#define RT5616_EQ_DITH_LSB_1			(0x2 << 8)
-#define RT5616_EQ_DITH_LSB_2			(0x3 << 8)
-#define RT5616_EQ_CD_F				(0x1 << 7)
-#define RT5616_EQ_CD_F_BIT			7
-#define RT5616_EQ_STA_HP2			(0x1 << 6)
-#define RT5616_EQ_STA_HP2_BIT			6
-#define RT5616_EQ_STA_HP1			(0x1 << 5)
-#define RT5616_EQ_STA_HP1_BIT			5
-#define RT5616_EQ_STA_BP4			(0x1 << 4)
-#define RT5616_EQ_STA_BP4_BIT			4
-#define RT5616_EQ_STA_BP3			(0x1 << 3)
-#define RT5616_EQ_STA_BP3_BIT			3
-#define RT5616_EQ_STA_BP2			(0x1 << 2)
-#define RT5616_EQ_STA_BP2_BIT			2
-#define RT5616_EQ_STA_BP1			(0x1 << 1)
-#define RT5616_EQ_STA_BP1_BIT			1
-#define RT5616_EQ_STA_LP			(0x1)
-#define RT5616_EQ_STA_LP_BIT			0
-
-/* EQ Control 2 (0xb1) */
-#define RT5616_EQ_HPF1_M_MASK			(0x1 << 8)
-#define RT5616_EQ_HPF1_M_SFT			8
-#define RT5616_EQ_HPF1_M_HI			(0x0 << 8)
-#define RT5616_EQ_HPF1_M_1ST			(0x1 << 8)
-#define RT5616_EQ_LPF1_M_MASK			(0x1 << 7)
-#define RT5616_EQ_LPF1_M_SFT			7
-#define RT5616_EQ_LPF1_M_LO			(0x0 << 7)
-#define RT5616_EQ_LPF1_M_1ST			(0x1 << 7)
-#define RT5616_EQ_HPF2_MASK			(0x1 << 6)
-#define RT5616_EQ_HPF2_SFT			6
-#define RT5616_EQ_HPF2_DIS			(0x0 << 6)
-#define RT5616_EQ_HPF2_EN			(0x1 << 6)
-#define RT5616_EQ_HPF1_MASK			(0x1 << 5)
-#define RT5616_EQ_HPF1_SFT			5
-#define RT5616_EQ_HPF1_DIS			(0x0 << 5)
-#define RT5616_EQ_HPF1_EN			(0x1 << 5)
-#define RT5616_EQ_BPF4_MASK			(0x1 << 4)
-#define RT5616_EQ_BPF4_SFT			4
-#define RT5616_EQ_BPF4_DIS			(0x0 << 4)
-#define RT5616_EQ_BPF4_EN			(0x1 << 4)
-#define RT5616_EQ_BPF3_MASK			(0x1 << 3)
-#define RT5616_EQ_BPF3_SFT			3
-#define RT5616_EQ_BPF3_DIS			(0x0 << 3)
-#define RT5616_EQ_BPF3_EN			(0x1 << 3)
-#define RT5616_EQ_BPF2_MASK			(0x1 << 2)
-#define RT5616_EQ_BPF2_SFT			2
-#define RT5616_EQ_BPF2_DIS			(0x0 << 2)
-#define RT5616_EQ_BPF2_EN			(0x1 << 2)
-#define RT5616_EQ_BPF1_MASK			(0x1 << 1)
-#define RT5616_EQ_BPF1_SFT			1
-#define RT5616_EQ_BPF1_DIS			(0x0 << 1)
-#define RT5616_EQ_BPF1_EN			(0x1 << 1)
-#define RT5616_EQ_LPF_MASK			(0x1)
-#define RT5616_EQ_LPF_SFT			0
-#define RT5616_EQ_LPF_DIS			(0x0)
-#define RT5616_EQ_LPF_EN			(0x1)
-#define RT5616_EQ_CTRL_MASK			(0x7f)
-
-/* Memory Test (0xb2) */
-#define RT5616_MT_MASK				(0x1 << 15)
-#define RT5616_MT_SFT				15
-#define RT5616_MT_DIS				(0x0 << 15)
-#define RT5616_MT_EN				(0x1 << 15)
-
-/* DRC/AGC Control 1 (0xb4) */
-#define RT5616_DRC_AGC_P_MASK			(0x1 << 15)
-#define RT5616_DRC_AGC_P_SFT			15
-#define RT5616_DRC_AGC_P_DAC			(0x0 << 15)
-#define RT5616_DRC_AGC_P_ADC			(0x1 << 15)
-#define RT5616_DRC_AGC_MASK			(0x1 << 14)
-#define RT5616_DRC_AGC_SFT			14
-#define RT5616_DRC_AGC_DIS			(0x0 << 14)
-#define RT5616_DRC_AGC_EN			(0x1 << 14)
-#define RT5616_DRC_AGC_UPD			(0x1 << 13)
-#define RT5616_DRC_AGC_UPD_BIT			13
-#define RT5616_DRC_AGC_AR_MASK			(0x1f << 8)
-#define RT5616_DRC_AGC_AR_SFT			8
-#define RT5616_DRC_AGC_R_MASK			(0x7 << 5)
-#define RT5616_DRC_AGC_R_SFT			5
-#define RT5616_DRC_AGC_R_48K			(0x1 << 5)
-#define RT5616_DRC_AGC_R_96K			(0x2 << 5)
-#define RT5616_DRC_AGC_R_192K			(0x3 << 5)
-#define RT5616_DRC_AGC_R_441K			(0x5 << 5)
-#define RT5616_DRC_AGC_R_882K			(0x6 << 5)
-#define RT5616_DRC_AGC_R_1764K			(0x7 << 5)
-#define RT5616_DRC_AGC_RC_MASK			(0x1f)
-#define RT5616_DRC_AGC_RC_SFT			0
-
-/* DRC/AGC Control 2 (0xb5) */
-#define RT5616_DRC_AGC_POB_MASK			(0x3f << 8)
-#define RT5616_DRC_AGC_POB_SFT			8
-#define RT5616_DRC_AGC_CP_MASK			(0x1 << 7)
-#define RT5616_DRC_AGC_CP_SFT			7
-#define RT5616_DRC_AGC_CP_DIS			(0x0 << 7)
-#define RT5616_DRC_AGC_CP_EN			(0x1 << 7)
-#define RT5616_DRC_AGC_CPR_MASK			(0x3 << 5)
-#define RT5616_DRC_AGC_CPR_SFT			5
-#define RT5616_DRC_AGC_CPR_1_1			(0x0 << 5)
-#define RT5616_DRC_AGC_CPR_1_2			(0x1 << 5)
-#define RT5616_DRC_AGC_CPR_1_3			(0x2 << 5)
-#define RT5616_DRC_AGC_CPR_1_4			(0x3 << 5)
-#define RT5616_DRC_AGC_PRB_MASK			(0x1f)
-#define RT5616_DRC_AGC_PRB_SFT			0
-
-/* DRC/AGC Control 3 (0xb6) */
-#define RT5616_DRC_AGC_NGB_MASK			(0xf << 12)
-#define RT5616_DRC_AGC_NGB_SFT			12
-#define RT5616_DRC_AGC_TAR_MASK			(0x1f << 7)
-#define RT5616_DRC_AGC_TAR_SFT			7
-#define RT5616_DRC_AGC_NG_MASK			(0x1 << 6)
-#define RT5616_DRC_AGC_NG_SFT			6
-#define RT5616_DRC_AGC_NG_DIS			(0x0 << 6)
-#define RT5616_DRC_AGC_NG_EN			(0x1 << 6)
-#define RT5616_DRC_AGC_NGH_MASK			(0x1 << 5)
-#define RT5616_DRC_AGC_NGH_SFT			5
-#define RT5616_DRC_AGC_NGH_DIS			(0x0 << 5)
-#define RT5616_DRC_AGC_NGH_EN			(0x1 << 5)
-#define RT5616_DRC_AGC_NGT_MASK			(0x1f)
-#define RT5616_DRC_AGC_NGT_SFT			0
-
-/* Jack Detect Control 1 (0xbb) */
-#define RT5616_JD_MASK				(0x7 << 13)
-#define RT5616_JD_SFT				13
-#define RT5616_JD_DIS				(0x0 << 13)
-#define RT5616_JD_GPIO1				(0x1 << 13)
-#define RT5616_JD_GPIO2				(0x2 << 13)
-#define RT5616_JD_GPIO3				(0x3 << 13)
-#define RT5616_JD_GPIO4				(0x4 << 13)
-#define RT5616_JD_GPIO5				(0x5 << 13)
-#define RT5616_JD_GPIO6				(0x6 << 13)
-#define RT5616_JD_HP_MASK			(0x1 << 11)
-#define RT5616_JD_HP_SFT			11
-#define RT5616_JD_HP_DIS			(0x0 << 11)
-#define RT5616_JD_HP_EN				(0x1 << 11)
-#define RT5616_JD_HP_TRG_MASK			(0x1 << 10)
-#define RT5616_JD_HP_TRG_SFT			10
-#define RT5616_JD_HP_TRG_LO			(0x0 << 10)
-#define RT5616_JD_HP_TRG_HI			(0x1 << 10)
-#define RT5616_JD_SPL_MASK			(0x1 << 9)
-#define RT5616_JD_SPL_SFT			9
-#define RT5616_JD_SPL_DIS			(0x0 << 9)
-#define RT5616_JD_SPL_EN			(0x1 << 9)
-#define RT5616_JD_SPL_TRG_MASK			(0x1 << 8)
-#define RT5616_JD_SPL_TRG_SFT			8
-#define RT5616_JD_SPL_TRG_LO			(0x0 << 8)
-#define RT5616_JD_SPL_TRG_HI			(0x1 << 8)
-#define RT5616_JD_SPR_MASK			(0x1 << 7)
-#define RT5616_JD_SPR_SFT			7
-#define RT5616_JD_SPR_DIS			(0x0 << 7)
-#define RT5616_JD_SPR_EN			(0x1 << 7)
-#define RT5616_JD_SPR_TRG_MASK			(0x1 << 6)
-#define RT5616_JD_SPR_TRG_SFT			6
-#define RT5616_JD_SPR_TRG_LO			(0x0 << 6)
-#define RT5616_JD_SPR_TRG_HI			(0x1 << 6)
-#define RT5616_JD_LO_MASK			(0x1 << 3)
-#define RT5616_JD_LO_SFT			3
-#define RT5616_JD_LO_DIS			(0x0 << 3)
-#define RT5616_JD_LO_EN				(0x1 << 3)
-#define RT5616_JD_LO_TRG_MASK			(0x1 << 2)
-#define RT5616_JD_LO_TRG_SFT			2
-#define RT5616_JD_LO_TRG_LO			(0x0 << 2)
-#define RT5616_JD_LO_TRG_HI			(0x1 << 2)
-
-/* Jack Detect Control 2 (0xbc) */
-#define RT5616_JD_TRG_SEL_MASK			(0x7 << 9)
-#define RT5616_JD_TRG_SEL_SFT			9
-#define RT5616_JD_TRG_SEL_GPIO			(0x0 << 9)
-#define RT5616_JD_TRG_SEL_JD1_1			(0x1 << 9)
-#define RT5616_JD_TRG_SEL_JD1_2			(0x2 << 9)
-#define RT5616_JD_TRG_SEL_JD2			(0x3 << 9)
-#define RT5616_JD_TRG_SEL_JD3			(0x4 << 9)
-#define RT5616_JD3_IRQ_EN			(0x1 << 8)
-#define RT5616_JD3_IRQ_EN_SFT			8
-#define RT5616_JD3_EN_STKY			(0x1 << 7)
-#define RT5616_JD3_EN_STKY_SFT			7
-#define RT5616_JD3_INV				(0x1 << 6)
-#define RT5616_JD3_INV_SFT			6
-
-/* IRQ Control 1 (0xbd) */
-#define RT5616_IRQ_JD_MASK			(0x1 << 15)
-#define RT5616_IRQ_JD_SFT			15
-#define RT5616_IRQ_JD_BP			(0x0 << 15)
-#define RT5616_IRQ_JD_NOR			(0x1 << 15)
-#define RT5616_JD_STKY_MASK			(0x1 << 13)
-#define RT5616_JD_STKY_SFT			13
-#define RT5616_JD_STKY_DIS			(0x0 << 13)
-#define RT5616_JD_STKY_EN			(0x1 << 13)
-#define RT5616_JD_P_MASK			(0x1 << 11)
-#define RT5616_JD_P_SFT				11
-#define RT5616_JD_P_NOR				(0x0 << 11)
-#define RT5616_JD_P_INV				(0x1 << 11)
-#define RT5616_JD1_1_IRQ_EN			(0x1 << 9)
-#define RT5616_JD1_1_IRQ_EN_SFT			9
-#define RT5616_JD1_1_EN_STKY			(0x1 << 8)
-#define RT5616_JD1_1_EN_STKY_SFT			8
-#define RT5616_JD1_1_INV			(0x1 << 7)
-#define RT5616_JD1_1_INV_SFT			7
-#define RT5616_JD1_2_IRQ_EN			(0x1 << 6)
-#define RT5616_JD1_2_IRQ_EN_SFT			6
-#define RT5616_JD1_2_EN_STKY			(0x1 << 5)
-#define RT5616_JD1_2_EN_STKY_SFT			5
-#define RT5616_JD1_2_INV			(0x1 << 4)
-#define RT5616_JD1_2_INV_SFT			4
-#define RT5616_JD2_IRQ_EN			(0x1 << 3)
-#define RT5616_JD2_IRQ_EN_SFT			3
-#define RT5616_JD2_EN_STKY			(0x1 << 2)
-#define RT5616_JD2_EN_STKY_SFT			2
-#define RT5616_JD2_INV				(0x1 << 1)
-#define RT5616_JD2_INV_SFT			1
-
-/* IRQ Control 2 (0xbe) */
-#define RT5616_IRQ_MB1_OC_MASK			(0x1 << 15)
-#define RT5616_IRQ_MB1_OC_SFT			15
-#define RT5616_IRQ_MB1_OC_BP			(0x0 << 15)
-#define RT5616_IRQ_MB1_OC_NOR			(0x1 << 15)
-#define RT5616_MB1_OC_STKY_MASK			(0x1 << 11)
-#define RT5616_MB1_OC_STKY_SFT			11
-#define RT5616_MB1_OC_STKY_DIS			(0x0 << 11)
-#define RT5616_MB1_OC_STKY_EN			(0x1 << 11)
-#define RT5616_MB1_OC_P_MASK			(0x1 << 7)
-#define RT5616_MB1_OC_P_SFT			7
-#define RT5616_MB1_OC_P_NOR			(0x0 << 7)
-#define RT5616_MB1_OC_P_INV			(0x1 << 7)
-#define RT5616_MB2_OC_P_MASK			(0x1 << 6)
-#define RT5616_MB1_OC_CLR			(0x1 << 3)
-#define RT5616_MB1_OC_CLR_SFT			3
-#define RT5616_STA_GPIO8			(0x1)
-#define RT5616_STA_GPIO8_BIT			0
-
-/* Internal Status and GPIO status (0xbf) */
-#define RT5616_STA_JD3				(0x1 << 15)
-#define RT5616_STA_JD3_BIT			15
-#define RT5616_STA_JD2				(0x1 << 14)
-#define RT5616_STA_JD2_BIT			14
-#define RT5616_STA_JD1_2			(0x1 << 13)
-#define RT5616_STA_JD1_2_BIT			13
-#define RT5616_STA_JD1_1			(0x1 << 12)
-#define RT5616_STA_JD1_1_BIT			12
-#define RT5616_STA_GP7				(0x1 << 11)
-#define RT5616_STA_GP7_BIT			11
-#define RT5616_STA_GP6				(0x1 << 10)
-#define RT5616_STA_GP6_BIT			10
-#define RT5616_STA_GP5				(0x1 << 9)
-#define RT5616_STA_GP5_BIT			9
-#define RT5616_STA_GP1				(0x1 << 8)
-#define RT5616_STA_GP1_BIT			8
-#define RT5616_STA_GP2				(0x1 << 7)
-#define RT5616_STA_GP2_BIT			7
-#define RT5616_STA_GP3				(0x1 << 6)
-#define RT5616_STA_GP3_BIT			6
-#define RT5616_STA_GP4				(0x1 << 5)
-#define RT5616_STA_GP4_BIT			5
-#define RT5616_STA_GP_JD			(0x1 << 4)
-#define RT5616_STA_GP_JD_BIT			4
-
-/* GPIO Control 1 (0xc0) */
-#define RT5616_GP1_PIN_MASK			(0x1 << 15)
-#define RT5616_GP1_PIN_SFT			15
-#define RT5616_GP1_PIN_GPIO1			(0x0 << 15)
-#define RT5616_GP1_PIN_IRQ			(0x1 << 15)
-#define RT5616_GP2_PIN_MASK			(0x1 << 14)
-#define RT5616_GP2_PIN_SFT			14
-#define RT5616_GP2_PIN_GPIO2			(0x0 << 14)
-#define RT5616_GP2_PIN_DMIC1_SCL		(0x1 << 14)
-#define RT5616_GPIO_M_MASK			(0x1 << 9)
-#define RT5616_GPIO_M_SFT			9
-#define RT5616_GPIO_M_FLT			(0x0 << 9)
-#define RT5616_GPIO_M_PH			(0x1 << 9)
-#define RT5616_I2S2_SEL_MASK			(0x1 << 8)
-#define RT5616_I2S2_SEL_SFT			8
-#define RT5616_I2S2_SEL_I2S			(0x0 << 8)
-#define RT5616_I2S2_SEL_GPIO			(0x1 << 8)
-#define RT5616_GP5_PIN_MASK			(0x1 << 7)
-#define RT5616_GP5_PIN_SFT			7
-#define RT5616_GP5_PIN_GPIO5			(0x0 << 7)
-#define RT5616_GP5_PIN_IRQ			(0x1 << 7)
-#define RT5616_GP6_PIN_MASK			(0x1 << 6)
-#define RT5616_GP6_PIN_SFT			6
-#define RT5616_GP6_PIN_GPIO6			(0x0 << 6)
-#define RT5616_GP6_PIN_DMIC_SDA			(0x1 << 6)
-#define RT5616_GP7_PIN_MASK			(0x1 << 5)
-#define RT5616_GP7_PIN_SFT			5
-#define RT5616_GP7_PIN_GPIO7			(0x0 << 5)
-#define RT5616_GP7_PIN_IRQ			(0x1 << 5)
-#define RT5616_GP8_PIN_MASK			(0x1 << 4)
-#define RT5616_GP8_PIN_SFT			4
-#define RT5616_GP8_PIN_GPIO8			(0x0 << 4)
-#define RT5616_GP8_PIN_DMIC_SDA			(0x1 << 4)
-#define RT5616_GPIO_PDM_SEL_MASK		(0x1 << 3)
-#define RT5616_GPIO_PDM_SEL_SFT			3
-#define RT5616_GPIO_PDM_SEL_GPIO		(0x0 << 3)
-#define RT5616_GPIO_PDM_SEL_PDM			(0x1 << 3)
-
-/* GPIO Control 2 (0xc1) */
-#define RT5616_GP5_DR_MASK			(0x1 << 14)
-#define RT5616_GP5_DR_SFT			14
-#define RT5616_GP5_DR_IN			(0x0 << 14)
-#define RT5616_GP5_DR_OUT			(0x1 << 14)
-#define RT5616_GP5_OUT_MASK			(0x1 << 13)
-#define RT5616_GP5_OUT_SFT			13
-#define RT5616_GP5_OUT_LO			(0x0 << 13)
-#define RT5616_GP5_OUT_HI			(0x1 << 13)
-#define RT5616_GP5_P_MASK			(0x1 << 12)
-#define RT5616_GP5_P_SFT			12
-#define RT5616_GP5_P_NOR			(0x0 << 12)
-#define RT5616_GP5_P_INV			(0x1 << 12)
-#define RT5616_GP4_DR_MASK			(0x1 << 11)
-#define RT5616_GP4_DR_SFT			11
-#define RT5616_GP4_DR_IN			(0x0 << 11)
-#define RT5616_GP4_DR_OUT			(0x1 << 11)
-#define RT5616_GP4_OUT_MASK			(0x1 << 10)
-#define RT5616_GP4_OUT_SFT			10
-#define RT5616_GP4_OUT_LO			(0x0 << 10)
-#define RT5616_GP4_OUT_HI			(0x1 << 10)
-#define RT5616_GP4_P_MASK			(0x1 << 9)
-#define RT5616_GP4_P_SFT			9
-#define RT5616_GP4_P_NOR			(0x0 << 9)
-#define RT5616_GP4_P_INV			(0x1 << 9)
-#define RT5616_GP3_DR_MASK			(0x1 << 8)
-#define RT5616_GP3_DR_SFT			8
-#define RT5616_GP3_DR_IN			(0x0 << 8)
-#define RT5616_GP3_DR_OUT			(0x1 << 8)
-#define RT5616_GP3_OUT_MASK			(0x1 << 7)
-#define RT5616_GP3_OUT_SFT			7
-#define RT5616_GP3_OUT_LO			(0x0 << 7)
-#define RT5616_GP3_OUT_HI			(0x1 << 7)
-#define RT5616_GP3_P_MASK			(0x1 << 6)
-#define RT5616_GP3_P_SFT			6
-#define RT5616_GP3_P_NOR			(0x0 << 6)
-#define RT5616_GP3_P_INV			(0x1 << 6)
-#define RT5616_GP2_DR_MASK			(0x1 << 5)
-#define RT5616_GP2_DR_SFT			5
-#define RT5616_GP2_DR_IN			(0x0 << 5)
-#define RT5616_GP2_DR_OUT			(0x1 << 5)
-#define RT5616_GP2_OUT_MASK			(0x1 << 4)
-#define RT5616_GP2_OUT_SFT			4
-#define RT5616_GP2_OUT_LO			(0x0 << 4)
-#define RT5616_GP2_OUT_HI			(0x1 << 4)
-#define RT5616_GP2_P_MASK			(0x1 << 3)
-#define RT5616_GP2_P_SFT			3
-#define RT5616_GP2_P_NOR			(0x0 << 3)
-#define RT5616_GP2_P_INV			(0x1 << 3)
-#define RT5616_GP1_DR_MASK			(0x1 << 2)
-#define RT5616_GP1_DR_SFT			2
-#define RT5616_GP1_DR_IN			(0x0 << 2)
-#define RT5616_GP1_DR_OUT			(0x1 << 2)
-#define RT5616_GP1_OUT_MASK			(0x1 << 1)
-#define RT5616_GP1_OUT_SFT			1
-#define RT5616_GP1_OUT_LO			(0x0 << 1)
-#define RT5616_GP1_OUT_HI			(0x1 << 1)
-#define RT5616_GP1_P_MASK			(0x1)
-#define RT5616_GP1_P_SFT			0
-#define RT5616_GP1_P_NOR			(0x0)
-#define RT5616_GP1_P_INV			(0x1)
-
-/* GPIO Control 3 (0xc2) */
-#define RT5616_GP8_DR_MASK			(0x1 << 8)
-#define RT5616_GP8_DR_SFT			8
-#define RT5616_GP8_DR_IN			(0x0 << 8)
-#define RT5616_GP8_DR_OUT			(0x1 << 8)
-#define RT5616_GP8_OUT_MASK			(0x1 << 7)
-#define RT5616_GP8_OUT_SFT			7
-#define RT5616_GP8_OUT_LO			(0x0 << 7)
-#define RT5616_GP8_OUT_HI			(0x1 << 7)
-#define RT5616_GP8_P_MASK			(0x1 << 6)
-#define RT5616_GP8_P_SFT			6
-#define RT5616_GP8_P_NOR			(0x0 << 6)
-#define RT5616_GP8_P_INV			(0x1 << 6)
-#define RT5616_GP7_DR_MASK			(0x1 << 5)
-#define RT5616_GP7_DR_SFT			5
-#define RT5616_GP7_DR_IN			(0x0 << 5)
-#define RT5616_GP7_DR_OUT			(0x1 << 5)
-#define RT5616_GP7_OUT_MASK			(0x1 << 4)
-#define RT5616_GP7_OUT_SFT			4
-#define RT5616_GP7_OUT_LO			(0x0 << 4)
-#define RT5616_GP7_OUT_HI			(0x1 << 4)
-#define RT5616_GP7_P_MASK			(0x1 << 3)
-#define RT5616_GP7_P_SFT			3
-#define RT5616_GP7_P_NOR			(0x0 << 3)
-#define RT5616_GP7_P_INV			(0x1 << 3)
-#define RT5616_GP6_DR_MASK			(0x1 << 2)
-#define RT5616_GP6_DR_SFT			2
-#define RT5616_GP6_DR_IN			(0x0 << 2)
-#define RT5616_GP6_DR_OUT			(0x1 << 2)
-#define RT5616_GP6_OUT_MASK			(0x1 << 1)
-#define RT5616_GP6_OUT_SFT			1
-#define RT5616_GP6_OUT_LO			(0x0 << 1)
-#define RT5616_GP6_OUT_HI			(0x1 << 1)
-#define RT5616_GP6_P_MASK			(0x1)
-#define RT5616_GP6_P_SFT			0
-#define RT5616_GP6_P_NOR			(0x0)
-#define RT5616_GP6_P_INV			(0x1)
-
-/* Scramble Control (0xce) */
-#define RT5616_SCB_SWAP_MASK			(0x1 << 15)
-#define RT5616_SCB_SWAP_SFT			15
-#define RT5616_SCB_SWAP_DIS			(0x0 << 15)
-#define RT5616_SCB_SWAP_EN			(0x1 << 15)
-#define RT5616_SCB_MASK				(0x1 << 14)
-#define RT5616_SCB_SFT				14
-#define RT5616_SCB_DIS				(0x0 << 14)
-#define RT5616_SCB_EN				(0x1 << 14)
-
-/* Baseback Control (0xcf) */
-#define RT5616_BB_MASK				(0x1 << 15)
-#define RT5616_BB_SFT				15
-#define RT5616_BB_DIS				(0x0 << 15)
-#define RT5616_BB_EN				(0x1 << 15)
-#define RT5616_BB_CT_MASK			(0x7 << 12)
-#define RT5616_BB_CT_SFT			12
-#define RT5616_BB_CT_A				(0x0 << 12)
-#define RT5616_BB_CT_B				(0x1 << 12)
-#define RT5616_BB_CT_C				(0x2 << 12)
-#define RT5616_BB_CT_D				(0x3 << 12)
-#define RT5616_M_BB_L_MASK			(0x1 << 9)
-#define RT5616_M_BB_L_SFT			9
-#define RT5616_M_BB_R_MASK			(0x1 << 8)
-#define RT5616_M_BB_R_SFT			8
-#define RT5616_M_BB_HPF_L_MASK			(0x1 << 7)
-#define RT5616_M_BB_HPF_L_SFT			7
-#define RT5616_M_BB_HPF_R_MASK			(0x1 << 6)
-#define RT5616_M_BB_HPF_R_SFT			6
-#define RT5616_G_BB_BST_MASK			(0x3f)
-#define RT5616_G_BB_BST_SFT			0
-
-/* MP3 Plus Control 1 (0xd0) */
-#define RT5616_M_MP3_L_MASK			(0x1 << 15)
-#define RT5616_M_MP3_L_SFT			15
-#define RT5616_M_MP3_R_MASK			(0x1 << 14)
-#define RT5616_M_MP3_R_SFT			14
-#define RT5616_M_MP3_MASK			(0x1 << 13)
-#define RT5616_M_MP3_SFT			13
-#define RT5616_M_MP3_DIS			(0x0 << 13)
-#define RT5616_M_MP3_EN				(0x1 << 13)
-#define RT5616_EG_MP3_MASK			(0x1f << 8)
-#define RT5616_EG_MP3_SFT			8
-#define RT5616_MP3_HLP_MASK			(0x1 << 7)
-#define RT5616_MP3_HLP_SFT			7
-#define RT5616_MP3_HLP_DIS			(0x0 << 7)
-#define RT5616_MP3_HLP_EN			(0x1 << 7)
-#define RT5616_M_MP3_ORG_L_MASK			(0x1 << 6)
-#define RT5616_M_MP3_ORG_L_SFT			6
-#define RT5616_M_MP3_ORG_R_MASK			(0x1 << 5)
-#define RT5616_M_MP3_ORG_R_SFT			5
-
-/* MP3 Plus Control 2 (0xd1) */
-#define RT5616_MP3_WT_MASK			(0x1 << 13)
-#define RT5616_MP3_WT_SFT			13
-#define RT5616_MP3_WT_1_4			(0x0 << 13)
-#define RT5616_MP3_WT_1_2			(0x1 << 13)
-#define RT5616_OG_MP3_MASK			(0x1f << 8)
-#define RT5616_OG_MP3_SFT			8
-#define RT5616_HG_MP3_MASK			(0x3f)
-#define RT5616_HG_MP3_SFT			0
-
-/* 3D HP Control 1 (0xd2) */
-#define RT5616_3D_CF_MASK			(0x1 << 15)
-#define RT5616_3D_CF_SFT			15
-#define RT5616_3D_CF_DIS			(0x0 << 15)
-#define RT5616_3D_CF_EN				(0x1 << 15)
-#define RT5616_3D_HP_MASK			(0x1 << 14)
-#define RT5616_3D_HP_SFT			14
-#define RT5616_3D_HP_DIS			(0x0 << 14)
-#define RT5616_3D_HP_EN				(0x1 << 14)
-#define RT5616_3D_BT_MASK			(0x1 << 13)
-#define RT5616_3D_BT_SFT			13
-#define RT5616_3D_BT_DIS			(0x0 << 13)
-#define RT5616_3D_BT_EN				(0x1 << 13)
-#define RT5616_3D_1F_MIX_MASK			(0x3 << 11)
-#define RT5616_3D_1F_MIX_SFT			11
-#define RT5616_3D_HP_M_MASK			(0x1 << 10)
-#define RT5616_3D_HP_M_SFT			10
-#define RT5616_3D_HP_M_SUR			(0x0 << 10)
-#define RT5616_3D_HP_M_FRO			(0x1 << 10)
-#define RT5616_M_3D_HRTF_MASK			(0x1 << 9)
-#define RT5616_M_3D_HRTF_SFT			9
-#define RT5616_M_3D_D2H_MASK			(0x1 << 8)
-#define RT5616_M_3D_D2H_SFT			8
-#define RT5616_M_3D_D2R_MASK			(0x1 << 7)
-#define RT5616_M_3D_D2R_SFT			7
-#define RT5616_M_3D_REVB_MASK			(0x1 << 6)
-#define RT5616_M_3D_REVB_SFT			6
-
-/* Adjustable high pass filter control 1 (0xd3) */
-#define RT5616_2ND_HPF_MASK			(0x1 << 15)
-#define RT5616_2ND_HPF_SFT			15
-#define RT5616_2ND_HPF_DIS			(0x0 << 15)
-#define RT5616_2ND_HPF_EN			(0x1 << 15)
-#define RT5616_HPF_CF_L_MASK			(0x7 << 12)
-#define RT5616_HPF_CF_L_SFT			12
-#define RT5616_HPF_CF_R_MASK			(0x7 << 8)
-#define RT5616_HPF_CF_R_SFT			8
-#define RT5616_ZD_T_MASK			(0x3 << 6)
-#define RT5616_ZD_T_SFT				6
-#define RT5616_ZD_F_MASK			(0x3 << 4)
-#define RT5616_ZD_F_SFT				4
-#define RT5616_ZD_F_IM				(0x0 << 4)
-#define RT5616_ZD_F_ZC_IM			(0x1 << 4)
-#define RT5616_ZD_F_ZC_IOD			(0x2 << 4)
-#define RT5616_ZD_F_UN				(0x3 << 4)
-
-/* Adjustable high pass filter control 2 (0xd4) */
-#define RT5616_HPF_CF_L_NUM_MASK		(0x3f << 8)
-#define RT5616_HPF_CF_L_NUM_SFT			8
-#define RT5616_HPF_CF_R_NUM_MASK		(0x3f)
-#define RT5616_HPF_CF_R_NUM_SFT			0
-
-/* HP calibration control and Amp detection (0xd6) */
-#define RT5616_SI_DAC_MASK			(0x1 << 11)
-#define RT5616_SI_DAC_SFT			11
-#define RT5616_SI_DAC_AUTO			(0x0 << 11)
-#define RT5616_SI_DAC_TEST			(0x1 << 11)
-#define RT5616_DC_CAL_M_MASK			(0x1 << 10)
-#define RT5616_DC_CAL_M_SFT			10
-#define RT5616_DC_CAL_M_NOR			(0x0 << 10)
-#define RT5616_DC_CAL_M_CAL			(0x1 << 10)
-#define RT5616_DC_CAL_MASK			(0x1 << 9)
-#define RT5616_DC_CAL_SFT			9
-#define RT5616_DC_CAL_DIS			(0x0 << 9)
-#define RT5616_DC_CAL_EN			(0x1 << 9)
-#define RT5616_HPD_RCV_MASK			(0x7 << 6)
-#define RT5616_HPD_RCV_SFT			6
-#define RT5616_HPD_PS_MASK			(0x1 << 5)
-#define RT5616_HPD_PS_SFT			5
-#define RT5616_HPD_PS_DIS			(0x0 << 5)
-#define RT5616_HPD_PS_EN			(0x1 << 5)
-#define RT5616_CAL_M_MASK			(0x1 << 4)
-#define RT5616_CAL_M_SFT			4
-#define RT5616_CAL_M_DEP			(0x0 << 4)
-#define RT5616_CAL_M_CAL			(0x1 << 4)
-#define RT5616_CAL_MASK				(0x1 << 3)
-#define RT5616_CAL_SFT				3
-#define RT5616_CAL_DIS				(0x0 << 3)
-#define RT5616_CAL_EN				(0x1 << 3)
-#define RT5616_CAL_TEST_MASK			(0x1 << 2)
-#define RT5616_CAL_TEST_SFT			2
-#define RT5616_CAL_TEST_DIS			(0x0 << 2)
-#define RT5616_CAL_TEST_EN			(0x1 << 2)
-#define RT5616_CAL_P_MASK			(0x3)
-#define RT5616_CAL_P_SFT			0
-#define RT5616_CAL_P_NONE			(0x0)
-#define RT5616_CAL_P_CAL			(0x1)
-#define RT5616_CAL_P_DAC_CAL			(0x2)
-
-/* Soft volume and zero cross control 1 (0xd9) */
-#define RT5616_SV_MASK				(0x1 << 15)
-#define RT5616_SV_SFT				15
-#define RT5616_SV_DIS				(0x0 << 15)
-#define RT5616_SV_EN				(0x1 << 15)
-#define RT5616_OUT_SV_MASK			(0x1 << 13)
-#define RT5616_OUT_SV_SFT			13
-#define RT5616_OUT_SV_DIS			(0x0 << 13)
-#define RT5616_OUT_SV_EN			(0x1 << 13)
-#define RT5616_HP_SV_MASK			(0x1 << 12)
-#define RT5616_HP_SV_SFT			12
-#define RT5616_HP_SV_DIS			(0x0 << 12)
-#define RT5616_HP_SV_EN				(0x1 << 12)
-#define RT5616_ZCD_DIG_MASK			(0x1 << 11)
-#define RT5616_ZCD_DIG_SFT			11
-#define RT5616_ZCD_DIG_DIS			(0x0 << 11)
-#define RT5616_ZCD_DIG_EN			(0x1 << 11)
-#define RT5616_ZCD_MASK				(0x1 << 10)
-#define RT5616_ZCD_SFT				10
-#define RT5616_ZCD_PD				(0x0 << 10)
-#define RT5616_ZCD_PU				(0x1 << 10)
-#define RT5616_M_ZCD_MASK			(0x3f << 4)
-#define RT5616_M_ZCD_SFT			4
-#define RT5616_M_ZCD_OM_L			(0x1 << 7)
-#define RT5616_M_ZCD_OM_R			(0x1 << 6)
-#define RT5616_M_ZCD_RM_L			(0x1 << 5)
-#define RT5616_M_ZCD_RM_R			(0x1 << 4)
-#define RT5616_SV_DLY_MASK			(0xf)
-#define RT5616_SV_DLY_SFT			0
-
-/* Soft volume and zero cross control 2 (0xda) */
-#define RT5616_ZCD_HP_MASK			(0x1 << 15)
-#define RT5616_ZCD_HP_SFT			15
-#define RT5616_ZCD_HP_DIS			(0x0 << 15)
-#define RT5616_ZCD_HP_EN			(0x1 << 15)
-
-/* Digital Misc Control (0xfa) */
-#define RT5616_I2S2_MS_SP_MASK			(0x1 << 8)
-#define RT5616_I2S2_MS_SP_SEL			8
-#define RT5616_I2S2_MS_SP_64			(0x0 << 8)
-#define RT5616_I2S2_MS_SP_50			(0x1 << 8)
-#define RT5616_CLK_DET_EN			(0x1 << 3)
-#define RT5616_CLK_DET_EN_SFT			3
-#define RT5616_AMP_DET_EN			(0x1 << 1)
-#define RT5616_AMP_DET_EN_SFT			1
-#define RT5616_D_GATE_EN			(0x1)
-#define RT5616_D_GATE_EN_SFT			0
-
-/* Codec Private Register definition */
-/* 3D Speaker Control (0x63) */
-#define RT5616_3D_SPK_MASK			(0x1 << 15)
-#define RT5616_3D_SPK_SFT			15
-#define RT5616_3D_SPK_DIS			(0x0 << 15)
-#define RT5616_3D_SPK_EN			(0x1 << 15)
-#define RT5616_3D_SPK_M_MASK			(0x3 << 13)
-#define RT5616_3D_SPK_M_SFT			13
-#define RT5616_3D_SPK_CG_MASK			(0x1f << 8)
-#define RT5616_3D_SPK_CG_SFT			8
-#define RT5616_3D_SPK_SG_MASK			(0x1f)
-#define RT5616_3D_SPK_SG_SFT			0
-
-/* Wind Noise Detection Control 1 (0x6c) */
-#define RT5616_WND_MASK				(0x1 << 15)
-#define RT5616_WND_SFT				15
-#define RT5616_WND_DIS				(0x0 << 15)
-#define RT5616_WND_EN				(0x1 << 15)
-
-/* Wind Noise Detection Control 2 (0x6d) */
-#define RT5616_WND_FC_NW_MASK			(0x3f << 10)
-#define RT5616_WND_FC_NW_SFT			10
-#define RT5616_WND_FC_WK_MASK			(0x3f << 4)
-#define RT5616_WND_FC_WK_SFT			4
-
-/* Wind Noise Detection Control 3 (0x6e) */
-#define RT5616_HPF_FC_MASK			(0x3f << 6)
-#define RT5616_HPF_FC_SFT			6
-#define RT5616_WND_FC_ST_MASK			(0x3f)
-#define RT5616_WND_FC_ST_SFT			0
-
-/* Wind Noise Detection Control 4 (0x6f) */
-#define RT5616_WND_TH_LO_MASK			(0x3ff)
-#define RT5616_WND_TH_LO_SFT			0
-
-/* Wind Noise Detection Control 5 (0x70) */
-#define RT5616_WND_TH_HI_MASK			(0x3ff)
-#define RT5616_WND_TH_HI_SFT			0
-
-/* Wind Noise Detection Control 8 (0x73) */
-#define RT5616_WND_WIND_MASK			(0x1 << 13) /* Read-Only */
-#define RT5616_WND_WIND_SFT			13
-#define RT5616_WND_STRONG_MASK			(0x1 << 12) /* Read-Only */
-#define RT5616_WND_STRONG_SFT			12
-enum {
-	RT5616_NO_WIND,
-	RT5616_BREEZE,
-	RT5616_STORM,
-};
-
-/* Dipole Speaker Interface (0x75) */
-#define RT5616_DP_ATT_MASK			(0x3 << 14)
-#define RT5616_DP_ATT_SFT			14
-#define RT5616_DP_SPK_MASK			(0x1 << 10)
-#define RT5616_DP_SPK_SFT			10
-#define RT5616_DP_SPK_DIS			(0x0 << 10)
-#define RT5616_DP_SPK_EN			(0x1 << 10)
-
-/* EQ Pre Volume Control (0xb3) */
-#define RT5616_EQ_PRE_VOL_MASK			(0xffff)
-#define RT5616_EQ_PRE_VOL_SFT			0
-
-/* EQ Post Volume Control (0xb4) */
-#define RT5616_EQ_PST_VOL_MASK			(0xffff)
-#define RT5616_EQ_PST_VOL_SFT			0
-
-/* System Clock Source */
-enum {
-	RT5616_SCLK_S_MCLK,
-	RT5616_SCLK_S_PLL1,
-};
-
-/* PLL1 Source */
-enum {
-	RT5616_PLL1_S_MCLK,
-	RT5616_PLL1_S_BCLK1,
-	RT5616_PLL1_S_BCLK2,
-};
-
-enum {
-	RT5616_AIF1,
-	RT5616_AIFS,
-};
-
-#endif /* __RT5616_H__ */
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 0487cfa..2b96b11 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -762,6 +762,9 @@
 	struct sst_data *drv = dev_get_drvdata(dev);
 	int i;
 
+	if (!drv->soc_card)
+		return 0;
+
 	/* suspend all pcms first */
 	snd_soc_suspend(drv->soc_card->dev);
 	snd_soc_poweroff(drv->soc_card->dev);
@@ -784,6 +787,9 @@
 	struct sst_data *drv = dev_get_drvdata(dev);
 	int i;
 
+	if (!drv->soc_card)
+		return;
+
 	/* restart SSPs */
 	for (i = 0; i < drv->soc_card->num_rtd; i++) {
 		struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
diff --git a/sound/soc/intel/atom/sst/sst_pvt.c b/sound/soc/intel/atom/sst/sst_pvt.c
index adb32fe..b1e6b8f 100644
--- a/sound/soc/intel/atom/sst/sst_pvt.c
+++ b/sound/soc/intel/atom/sst/sst_pvt.c
@@ -279,17 +279,15 @@
 
 	if (response) {
 		ret = sst_wait_timeout(sst, block);
-		if (ret < 0) {
+		if (ret < 0)
 			goto out;
-		} else if(block->data) {
-			if (!data)
-				goto out;
-			*data = kzalloc(block->size, GFP_KERNEL);
-			if (!(*data)) {
+
+		if (data && block->data) {
+			*data = kmemdup(block->data, block->size, GFP_KERNEL);
+			if (!*data) {
 				ret = -ENOMEM;
 				goto out;
-			} else
-				memcpy(data, (void *) block->data, block->size);
+			}
 		}
 	}
 out:
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 7a5c9a3..daba8c5 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -139,7 +139,7 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.platform_name = "sst-mfld-platform",
-		.ignore_suspend = 1,
+		.nonatomic = true,
 		.dynamic = 1,
 		.dpcm_playback = 1,
 		.dpcm_capture = 1,
@@ -166,6 +166,7 @@
 						| SND_SOC_DAIFMT_CBS_CFS,
 		.be_hw_params_fixup = byt_codec_fixup,
 		.ignore_suspend = 1,
+		.nonatomic = true,
 		.dpcm_playback = 1,
 		.dpcm_capture = 1,
 		.ops = &byt_be_ssp2_ops,
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index caa69c4..b4844f7 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -464,8 +464,10 @@
 
 	skl->nhlt = skl_nhlt_init(bus->dev);
 
-	if (skl->nhlt == NULL)
+	if (skl->nhlt == NULL) {
+		err = -ENODEV;
 		goto out_free;
+	}
 
 	pci_set_drvdata(skl->pci, ebus);
 
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index b837265..8d0d45d 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -390,8 +390,8 @@
 	pm_runtime_get_sync(mcpdm->dev);
 	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00);
 
-	ret = devm_request_irq(mcpdm->dev, mcpdm->irq, omap_mcpdm_irq_handler,
-				0, "McPDM", (void *)mcpdm);
+	ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, 0, "McPDM",
+			  (void *)mcpdm);
 
 	pm_runtime_put_sync(mcpdm->dev);
 
@@ -416,6 +416,7 @@
 {
 	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 
+	free_irq(mcpdm->irq, (void *)mcpdm);
 	pm_runtime_disable(mcpdm->dev);
 
 	return 0;
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index e163b01..fd6e247 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -1027,12 +1027,13 @@
 static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
 {
 	struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai);
+	unsigned long flags;
 
 	if (!is_secondary(i2s)) {
 		if (i2s->quirks & QUIRK_NEED_RSTCLR) {
-			spin_lock(i2s->lock);
+			spin_lock_irqsave(i2s->lock, flags);
 			writel(0, i2s->addr + I2SCON);
-			spin_unlock(i2s->lock);
+			spin_unlock_irqrestore(i2s->lock, flags);
 		}
 	}
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a1305f8..fa6b74a 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1775,6 +1775,9 @@
 	for (i = 0; i < card->num_aux_devs; i++)
 		soc_remove_aux_dev(card, i);
 
+	/* free the ALSA card at first; this syncs with pending operations */
+	snd_card_free(card->snd_card);
+
 	/* remove and free each DAI */
 	soc_remove_dai_links(card);
 
@@ -1786,9 +1789,7 @@
 
 	snd_soc_dapm_free(&card->dapm);
 
-	snd_card_free(card->snd_card);
 	return 0;
-
 }
 
 /* removes a socdev */
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index afb70a5..b8a256d 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -823,6 +823,7 @@
 			case snd_soc_dapm_switch:
 			case snd_soc_dapm_mixer:
 			case snd_soc_dapm_pga:
+			case snd_soc_dapm_out_drv:
 				wname_in_long_name = true;
 				kcname_in_long_name = true;
 				break;
@@ -3015,6 +3016,9 @@
 	}
 	mutex_unlock(&card->dapm_mutex);
 
+	if (ret)
+		return ret;
+
 	if (invert)
 		ucontrol->value.integer.value[0] = max - val;
 	else
@@ -3166,7 +3170,7 @@
 	if (e->shift_l != e->shift_r) {
 		if (item[1] > e->items)
 			return -EINVAL;
-		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l;
+		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
 		mask |= e->mask << e->shift_r;
 	}
 
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 6963ba2..70396d3 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1484,6 +1484,7 @@
 	if (widget == NULL) {
 		dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n",
 			w->name);
+		ret = -ENOMEM;
 		goto hdr_err;
 	}
 
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 1bb896d..1a4999f 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -575,11 +575,11 @@
 
 	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
 	if (!card)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
 	if (!card->dai_link)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	card->dev		= dev;
 	card->name		= "sun4i-codec";
@@ -661,7 +661,8 @@
 	}
 
 	card = sun4i_codec_create_card(&pdev->dev);
-	if (!card) {
+	if (IS_ERR(card)) {
+		ret = PTR_ERR(card);
 		dev_err(&pdev->dev, "Failed to create our card\n");
 		goto err_unregister_codec;
 	}
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 1f09d95..a1cbaa5f 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -202,7 +202,6 @@
 	if (! snd_usb_parse_audio_interface(chip, interface)) {
 		usb_set_interface(dev, interface, 0); /* reset the current interface */
 		usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
-		return -EINVAL;
 	}
 
 	return 0;
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index c07a7ed..be1f511 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -538,6 +538,11 @@
 			alive, ep->ep_num);
 	clear_bit(EP_FLAG_STOPPING, &ep->flags);
 
+	ep->data_subs = NULL;
+	ep->sync_slave = NULL;
+	ep->retire_data_urb = NULL;
+	ep->prepare_data_urb = NULL;
+
 	return 0;
 }
 
@@ -902,9 +907,7 @@
 /**
  * snd_usb_endpoint_start: start an snd_usb_endpoint
  *
- * @ep:		the endpoint to start
- * @can_sleep:	flag indicating whether the operation is executed in
- * 		non-atomic context
+ * @ep: the endpoint to start
  *
  * A call to this function will increment the use count of the endpoint.
  * In case it is not already running, the URBs for this endpoint will be
@@ -914,7 +917,7 @@
  *
  * Returns an error if the URB submission failed, 0 in all other cases.
  */
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep)
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 {
 	int err;
 	unsigned int i;
@@ -928,8 +931,6 @@
 
 	/* just to be sure */
 	deactivate_urbs(ep, false);
-	if (can_sleep)
-		wait_clear_urbs(ep);
 
 	ep->active_mask = 0;
 	ep->unlink_mask = 0;
@@ -1010,10 +1011,6 @@
 
 	if (--ep->use_count == 0) {
 		deactivate_urbs(ep, false);
-		ep->data_subs = NULL;
-		ep->sync_slave = NULL;
-		ep->retire_data_urb = NULL;
-		ep->prepare_data_urb = NULL;
 		set_bit(EP_FLAG_STOPPING, &ep->flags);
 	}
 }
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 6428392..584f295 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -18,7 +18,7 @@
 				struct audioformat *fmt,
 				struct snd_usb_endpoint *sync_ep);
 
-int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep);
+int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c
index 2c44139..33db205 100644
--- a/sound/usb/hiface/pcm.c
+++ b/sound/usb/hiface/pcm.c
@@ -445,6 +445,8 @@
 
 	mutex_lock(&rt->stream_mutex);
 
+	hiface_pcm_stream_stop(rt);
+
 	sub->dma_off = 0;
 	sub->period_off = 0;
 
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 81b7da8..183311c 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -29,7 +29,7 @@
 /*
 	This is Line 6's MIDI manufacturer ID.
 */
-const unsigned char line6_midi_id[] = {
+const unsigned char line6_midi_id[3] = {
 	0x00, 0x01, 0x0c
 };
 EXPORT_SYMBOL_GPL(line6_midi_id);
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index 204cc07..41aa335 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -55,7 +55,6 @@
 		err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE);
 		if (err < 0) {
 			line6pcm->impulse_volume = 0;
-			line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
 			return err;
 		}
 	} else {
@@ -211,7 +210,9 @@
 	spin_lock_irqsave(&pstr->lock, flags);
 	clear_bit(type, &pstr->running);
 	if (!pstr->running) {
+		spin_unlock_irqrestore(&pstr->lock, flags);
 		line6_unlink_audio_urbs(line6pcm, pstr);
+		spin_lock_irqsave(&pstr->lock, flags);
 		if (direction == SNDRV_PCM_STREAM_CAPTURE) {
 			line6pcm->prev_fbuf = NULL;
 			line6pcm->prev_fsize = 0;
diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c
index daf81d1..45dd348 100644
--- a/sound/usb/line6/pod.c
+++ b/sound/usb/line6/pod.c
@@ -244,8 +244,8 @@
 static ssize_t serial_number_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
+	struct snd_card *card = dev_to_snd_card(dev);
+	struct usb_line6_pod *pod = card->private_data;
 
 	return sprintf(buf, "%u\n", pod->serial_number);
 }
@@ -256,8 +256,8 @@
 static ssize_t firmware_version_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
+	struct snd_card *card = dev_to_snd_card(dev);
+	struct usb_line6_pod *pod = card->private_data;
 
 	return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
 		       pod->firmware_version % 100);
@@ -269,8 +269,8 @@
 static ssize_t device_id_show(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 {
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
+	struct snd_card *card = dev_to_snd_card(dev);
+	struct usb_line6_pod *pod = card->private_data;
 
 	return sprintf(buf, "%d\n", pod->device_id);
 }
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 4f85757..499b03c 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -931,9 +931,10 @@
 	case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */
 	case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */
 	case USB_ID(0x046d, 0x0991):
+	case USB_ID(0x046d, 0x09a2): /* QuickCam Communicate Deluxe/S7500 */
 	/* Most audio usb devices lie about volume resolution.
 	 * Most Logitech webcams have res = 384.
-	 * Proboly there is some logitech magic behind this number --fishor
+	 * Probably there is some logitech magic behind this number --fishor
 	 */
 		if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
 			usb_audio_info(chip,
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index f6c3bf7..04991b0 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -1831,6 +1831,7 @@
 }
 
 static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer,
+					 struct usb_mixer_elem_info *cval,
 					 struct snd_kcontrol *kctl)
 {
 	/* Approximation using 10 ranges based on output measurement on hw v1.2.
@@ -1848,10 +1849,19 @@
 		41, 50, TLV_DB_MINMAX_ITEM(-441, 0),
 	);
 
-	usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk\n");
-	kctl->tlv.p = scale;
-	kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-	kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+	if (cval->min == 0 && cval->max == 50) {
+		usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk (0-50 variant)\n");
+		kctl->tlv.p = scale;
+		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+		kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+
+	} else if (cval->min == 0 && cval->max <= 1000) {
+		/* Some other clearly broken DragonFly variant.
+		 * At least a 0..53 variant (hw v1.0) exists.
+		 */
+		usb_audio_info(mixer->chip, "ignoring too narrow dB range on a DragonFly device");
+		kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+	}
 }
 
 void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
@@ -1860,8 +1870,8 @@
 {
 	switch (mixer->chip->usb_id) {
 	case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
-		if (unitid == 7 && cval->min == 0 && cval->max == 50)
-			snd_dragonfly_quirk_db_scale(mixer, kctl);
+		if (unitid == 7 && cval->control == UAC_FU_VOLUME)
+			snd_dragonfly_quirk_db_scale(mixer, cval, kctl);
 		break;
 	}
 }
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 44d178e..48afae0 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -218,7 +218,7 @@
 	}
 }
 
-static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
+static int start_endpoints(struct snd_usb_substream *subs)
 {
 	int err;
 
@@ -231,7 +231,7 @@
 		dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep);
 
 		ep->data_subs = subs;
-		err = snd_usb_endpoint_start(ep, can_sleep);
+		err = snd_usb_endpoint_start(ep);
 		if (err < 0) {
 			clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
 			return err;
@@ -260,7 +260,7 @@
 		dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep);
 
 		ep->sync_slave = subs->data_endpoint;
-		err = snd_usb_endpoint_start(ep, can_sleep);
+		err = snd_usb_endpoint_start(ep);
 		if (err < 0) {
 			clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
 			return err;
@@ -839,7 +839,7 @@
 	/* for playback, submit the URBs now; otherwise, the first hwptr_done
 	 * updates for all URBs would happen at the same time when starting */
 	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
-		ret = start_endpoints(subs, true);
+		ret = start_endpoints(subs);
 
  unlock:
 	snd_usb_unlock_shutdown(subs->stream->chip);
@@ -1655,7 +1655,7 @@
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		err = start_endpoints(subs, false);
+		err = start_endpoints(subs);
 		if (err < 0)
 			return err;
 
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index c60a776..8a59d47 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2907,6 +2907,23 @@
 AU0828_DEVICE(0x2040, 0x7213, "Hauppauge", "HVR-950Q"),
 AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
 
+/* Syntek STK1160 */
+{
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+		       USB_DEVICE_ID_MATCH_INT_CLASS |
+		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	.idVendor = 0x05e1,
+	.idProduct = 0x0408,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Syntek",
+		.product_name = "STK1160",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_AUDIO_ALIGN_TRANSFER
+	}
+},
+
 /* Digidesign Mbox */
 {
 	/* Thanks to Clemens Ladisch <clemens@ladisch.de> */
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 001fb4d..29f38e2 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1129,17 +1129,24 @@
 {
 	/* devices which do not support reading the sample rate. */
 	switch (chip->usb_id) {
+	case USB_ID(0x041E, 0x4080): /* Creative Live Cam VF0610 */
 	case USB_ID(0x045E, 0x075D): /* MS Lifecam Cinema  */
 	case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */
 	case USB_ID(0x045E, 0x076E): /* MS Lifecam HD-5001 */
 	case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
 	case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
 	case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
+	case USB_ID(0x047F, 0x02F7): /* Plantronics BT-600 */
 	case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */
 	case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
 	case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
+	case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
+	case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */
 	case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
+	case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
+	case USB_ID(0x1de7, 0x0013): /* Phoenix Audio MT202exe */
 	case USB_ID(0x1de7, 0x0014): /* Phoenix Audio TMX320 */
+	case USB_ID(0x1de7, 0x0114): /* Phoenix Audio MT202pcs */
 	case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
 		return true;
 	}
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index 5480e4e..f1d7426 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -37,12 +37,14 @@
 
 static int target_fd;
 static char target_fname[W_MAX_PATH];
+static unsigned long long filesize;
 
 static int hv_start_fcopy(struct hv_start_fcopy *smsg)
 {
 	int error = HV_E_FAIL;
 	char *q, *p;
 
+	filesize = 0;
 	p = (char *)smsg->path_name;
 	snprintf(target_fname, sizeof(target_fname), "%s/%s",
 		 (char *)smsg->path_name, (char *)smsg->file_name);
@@ -98,14 +100,26 @@
 static int hv_copy_data(struct hv_do_fcopy *cpmsg)
 {
 	ssize_t bytes_written;
+	int ret = 0;
 
 	bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size,
 				cpmsg->offset);
 
-	if (bytes_written != cpmsg->size)
-		return HV_E_FAIL;
+	filesize += cpmsg->size;
+	if (bytes_written != cpmsg->size) {
+		switch (errno) {
+		case ENOSPC:
+			ret = HV_ERROR_DISK_FULL;
+			break;
+		default:
+			ret = HV_E_FAIL;
+			break;
+		}
+		syslog(LOG_ERR, "pwrite failed to write %llu bytes: %ld (%s)",
+		       filesize, (long)bytes_written, strerror(errno));
+	}
 
-	return 0;
+	return ret;
 }
 
 static int hv_copy_finished(void)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 0d9f48e..bc7adb8 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1433,7 +1433,7 @@
 	openlog("KVP", 0, LOG_USER);
 	syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
 
-	kvp_fd = open("/dev/vmbus/hv_kvp", O_RDWR);
+	kvp_fd = open("/dev/vmbus/hv_kvp", O_RDWR | O_CLOEXEC);
 
 	if (kvp_fd < 0) {
 		syslog(LOG_ERR, "open /dev/vmbus/hv_kvp failed; error: %d %s",
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index fa7208a..8a679b2 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -115,4 +115,13 @@
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+
+#ifndef __fallthrough
+# if defined(__GNUC__) && __GNUC__ >= 7
+#  define __fallthrough __attribute__ ((fallthrough))
+# else
+#  define __fallthrough
+# endif
+#endif
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
diff --git a/tools/include/linux/log2.h b/tools/include/linux/log2.h
index 4144666..d5677d3 100644
--- a/tools/include/linux/log2.h
+++ b/tools/include/linux/log2.h
@@ -13,12 +13,6 @@
 #define _TOOLS_LINUX_LOG2_H
 
 /*
- * deal with unrepresentable constant logarithms
- */
-extern __attribute__((const, noreturn))
-int ____ilog2_NaN(void);
-
-/*
  * non-constant log of base 2 calculators
  * - the arch may override these in asm/bitops.h if they can be implemented
  *   more efficiently than using fls() and fls64()
@@ -78,7 +72,7 @@
 #define ilog2(n)				\
 (						\
 	__builtin_constant_p(n) ? (		\
-		(n) < 1 ? ____ilog2_NaN() :	\
+		(n) < 2 ? 0 :			\
 		(n) & (1ULL << 63) ? 63 :	\
 		(n) & (1ULL << 62) ? 62 :	\
 		(n) & (1ULL << 61) ? 61 :	\
@@ -141,10 +135,7 @@
 		(n) & (1ULL <<  4) ?  4 :	\
 		(n) & (1ULL <<  3) ?  3 :	\
 		(n) & (1ULL <<  2) ?  2 :	\
-		(n) & (1ULL <<  1) ?  1 :	\
-		(n) & (1ULL <<  0) ?  0 :	\
-		____ilog2_NaN()			\
-				   ) :		\
+		1 ) :				\
 	(sizeof(n) <= 4) ?			\
 	__ilog2_u32(n) :			\
 	__ilog2_u64(n)				\
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index 0144b3d..88cccea 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -1164,11 +1164,11 @@
 		current_op = current_exp;
 
 	ret = collapse_tree(current_op, parg, error_str);
+	/* collapse_tree() may free current_op, and updates parg accordingly */
+	current_op = NULL;
 	if (ret < 0)
 		goto fail;
 
-	*parg = current_op;
-
 	free(token);
 	return 0;
 
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 0d19d54..929a32b 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -420,7 +420,7 @@
 	$(call QUIET_CLEAN, libtraceevent)
 	$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
 
-install-traceevent-plugins: $(LIBTRACEEVENT)
+install-traceevent-plugins: libtraceevent_plugins
 	$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins
 
 $(LIBAPI): fixdep FORCE
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c
index d28c1b6..fa5d17a 100644
--- a/tools/perf/arch/x86/tests/intel-cqm.c
+++ b/tools/perf/arch/x86/tests/intel-cqm.c
@@ -17,7 +17,7 @@
 	if (pid)
 		return pid;
 
-	while(1);
+	while(1)
 		sleep(5);
 	return 0;
 }
diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c
index 9223c16..1f86ee8 100644
--- a/tools/perf/arch/x86/util/dwarf-regs.c
+++ b/tools/perf/arch/x86/util/dwarf-regs.c
@@ -63,6 +63,8 @@
 # define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)}
 #endif
 
+/* TODO: switching by dwarf address size */
+#ifndef __x86_64__
 static const struct pt_regs_offset x86_32_regoffset_table[] = {
 	REG_OFFSET_NAME_32("%ax",	eax),
 	REG_OFFSET_NAME_32("%cx",	ecx),
@@ -75,6 +77,8 @@
 	REG_OFFSET_END,
 };
 
+#define regoffset_table x86_32_regoffset_table
+#else
 static const struct pt_regs_offset x86_64_regoffset_table[] = {
 	REG_OFFSET_NAME_64("%ax",	rax),
 	REG_OFFSET_NAME_64("%dx",	rdx),
@@ -95,11 +99,7 @@
 	REG_OFFSET_END,
 };
 
-/* TODO: switching by dwarf address size */
-#ifdef __x86_64__
 #define regoffset_table x86_64_regoffset_table
-#else
-#define regoffset_table x86_32_regoffset_table
 #endif
 
 /* Minus 1 for the ending REG_OFFSET_END */
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index b02af06..c53f787 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -499,7 +499,7 @@
 	struct intel_pt_recording *ptr =
 			container_of(itr, struct intel_pt_recording, itr);
 	struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu;
-	bool have_timing_info;
+	bool have_timing_info, need_immediate = false;
 	struct perf_evsel *evsel, *intel_pt_evsel = NULL;
 	const struct cpu_map *cpus = evlist->cpus;
 	bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
@@ -653,6 +653,7 @@
 				ptr->have_sched_switch = 3;
 			} else {
 				opts->record_switch_events = true;
+				need_immediate = true;
 				if (cpu_wide)
 					ptr->have_sched_switch = 3;
 				else
@@ -698,6 +699,9 @@
 		tracking_evsel->attr.freq = 0;
 		tracking_evsel->attr.sample_period = 1;
 
+		if (need_immediate)
+			tracking_evsel->immediate = true;
+
 		/* In per-cpu case, always need the time of mmap events etc */
 		if (!cpu_map__empty(cpus)) {
 			perf_evsel__set_sample_bit(tracking_evsel, TIME);
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 492df27..b4eb5b6 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -1570,13 +1570,13 @@
 		"GB/sec,", "total-speed",	"GB/sec total speed");
 
 	if (g->p.show_details >= 2) {
-		char tname[32];
+		char tname[14 + 2 * 10 + 1];
 		struct thread_data *td;
 		for (p = 0; p < g->p.nr_proc; p++) {
 			for (t = 0; t < g->p.nr_threads; t++) {
-				memset(tname, 0, 32);
+				memset(tname, 0, sizeof(tname));
 				td = g->threads + p*g->p.nr_threads + t;
-				snprintf(tname, 32, "process%d:thread%d", p, t);
+				snprintf(tname, sizeof(tname), "process%d:thread%d", p, t);
 				print_res(tname, td->speed_gbs,
 					"GB/sec",	"thread-speed", "GB/sec/thread speed");
 				print_res(tname, td->system_time_ns / 1e9,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 72b5deb..20f0e27 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1252,21 +1252,19 @@
 	return S_ISDIR(st.st_mode);
 }
 
-#define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\
-	while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) &&	\
-	       lang_next)						\
-		if ((lang_dirent.d_type == DT_DIR ||			\
-		     (lang_dirent.d_type == DT_UNKNOWN &&		\
-		      is_directory(scripts_path, &lang_dirent))) &&	\
-		    (strcmp(lang_dirent.d_name, ".")) &&		\
-		    (strcmp(lang_dirent.d_name, "..")))
+#define for_each_lang(scripts_path, scripts_dir, lang_dirent)		\
+	while ((lang_dirent = readdir(scripts_dir)) != NULL)		\
+		if ((lang_dirent->d_type == DT_DIR ||			\
+		     (lang_dirent->d_type == DT_UNKNOWN &&		\
+		      is_directory(scripts_path, lang_dirent))) &&	\
+		    (strcmp(lang_dirent->d_name, ".")) &&		\
+		    (strcmp(lang_dirent->d_name, "..")))
 
-#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\
-	while (!readdir_r(lang_dir, &script_dirent, &script_next) &&	\
-	       script_next)						\
-		if (script_dirent.d_type != DT_DIR &&			\
-		    (script_dirent.d_type != DT_UNKNOWN ||		\
-		     !is_directory(lang_path, &script_dirent)))
+#define for_each_script(lang_path, lang_dir, script_dirent)		\
+	while ((script_dirent = readdir(lang_dir)) != NULL)		\
+		if (script_dirent->d_type != DT_DIR &&			\
+		    (script_dirent->d_type != DT_UNKNOWN ||		\
+		     !is_directory(lang_path, script_dirent)))
 
 
 #define RECORD_SUFFIX			"-record"
@@ -1412,7 +1410,7 @@
 				  const char *s __maybe_unused,
 				  int unset __maybe_unused)
 {
-	struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
+	struct dirent *script_dirent, *lang_dirent;
 	char scripts_path[MAXPATHLEN];
 	DIR *scripts_dir, *lang_dir;
 	char script_path[MAXPATHLEN];
@@ -1427,19 +1425,19 @@
 	if (!scripts_dir)
 		return -1;
 
-	for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
+	for_each_lang(scripts_path, scripts_dir, lang_dirent) {
 		snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
-			 lang_dirent.d_name);
+			 lang_dirent->d_name);
 		lang_dir = opendir(lang_path);
 		if (!lang_dir)
 			continue;
 
-		for_each_script(lang_path, lang_dir, script_dirent, script_next) {
-			script_root = get_script_root(&script_dirent, REPORT_SUFFIX);
+		for_each_script(lang_path, lang_dir, script_dirent) {
+			script_root = get_script_root(script_dirent, REPORT_SUFFIX);
 			if (script_root) {
 				desc = script_desc__findnew(script_root);
 				snprintf(script_path, MAXPATHLEN, "%s/%s",
-					 lang_path, script_dirent.d_name);
+					 lang_path, script_dirent->d_name);
 				read_script_info(desc, script_path);
 				free(script_root);
 			}
@@ -1527,7 +1525,7 @@
  */
 int find_scripts(char **scripts_array, char **scripts_path_array)
 {
-	struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
+	struct dirent *script_dirent, *lang_dirent;
 	char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
 	DIR *scripts_dir, *lang_dir;
 	struct perf_session *session;
@@ -1550,9 +1548,9 @@
 		return -1;
 	}
 
-	for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
+	for_each_lang(scripts_path, scripts_dir, lang_dirent) {
 		snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
-			 lang_dirent.d_name);
+			 lang_dirent->d_name);
 #ifdef NO_LIBPERL
 		if (strstr(lang_path, "perl"))
 			continue;
@@ -1566,16 +1564,16 @@
 		if (!lang_dir)
 			continue;
 
-		for_each_script(lang_path, lang_dir, script_dirent, script_next) {
+		for_each_script(lang_path, lang_dir, script_dirent) {
 			/* Skip those real time scripts: xxxtop.p[yl] */
-			if (strstr(script_dirent.d_name, "top."))
+			if (strstr(script_dirent->d_name, "top."))
 				continue;
 			sprintf(scripts_path_array[i], "%s/%s", lang_path,
-				script_dirent.d_name);
-			temp = strchr(script_dirent.d_name, '.');
+				script_dirent->d_name);
+			temp = strchr(script_dirent->d_name, '.');
 			snprintf(scripts_array[i],
-				(temp - script_dirent.d_name) + 1,
-				"%s", script_dirent.d_name);
+				(temp - script_dirent->d_name) + 1,
+				"%s", script_dirent->d_name);
 
 			if (check_ev_match(lang_path,
 					scripts_array[i], session))
@@ -1593,7 +1591,7 @@
 
 static char *get_script_path(const char *script_root, const char *suffix)
 {
-	struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
+	struct dirent *script_dirent, *lang_dirent;
 	char scripts_path[MAXPATHLEN];
 	char script_path[MAXPATHLEN];
 	DIR *scripts_dir, *lang_dir;
@@ -1606,21 +1604,21 @@
 	if (!scripts_dir)
 		return NULL;
 
-	for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
+	for_each_lang(scripts_path, scripts_dir, lang_dirent) {
 		snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
-			 lang_dirent.d_name);
+			 lang_dirent->d_name);
 		lang_dir = opendir(lang_path);
 		if (!lang_dir)
 			continue;
 
-		for_each_script(lang_path, lang_dir, script_dirent, script_next) {
-			__script_root = get_script_root(&script_dirent, suffix);
+		for_each_script(lang_path, lang_dir, script_dirent) {
+			__script_root = get_script_root(script_dirent, suffix);
 			if (__script_root && !strcmp(script_root, __script_root)) {
 				free(__script_root);
 				closedir(lang_dir);
 				closedir(scripts_dir);
 				snprintf(script_path, MAXPATHLEN, "%s/%s",
-					 lang_path, script_dirent.d_name);
+					 lang_path, script_dirent->d_name);
 				return strdup(script_path);
 			}
 			free(__script_root);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 7e2e72e..4a8a02c 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -636,7 +636,7 @@
 		case -1:
 			if (errno == EINTR)
 				continue;
-			/* Fall trhu */
+			__fallthrough;
 		default:
 			c = getc(stdin);
 			tcsetattr(0, TCSAFLUSH, &save);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index c783d8f..ebe7115 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1617,6 +1617,7 @@
 		color_fprintf(trace->output, PERF_COLOR_RED,
 			      "LOST %" PRIu64 " events!\n", event->lost.lost);
 		ret = machine__process_lost_event(machine, event, sample);
+		break;
 	default:
 		ret = machine__process_event(machine, event, sample);
 		break;
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index ec16f78..6ebfdee 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -146,7 +146,7 @@
 	return obj;
 }
 
-static int __test__bpf(int index)
+static int __test__bpf(int idx)
 {
 	int ret;
 	void *obj_buf;
@@ -154,27 +154,27 @@
 	struct bpf_object *obj;
 
 	ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
-				       bpf_testcase_table[index].prog_id,
+				       bpf_testcase_table[idx].prog_id,
 				       true);
 	if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
 		pr_debug("Unable to get BPF object, %s\n",
-			 bpf_testcase_table[index].msg_compile_fail);
-		if (index == 0)
+			 bpf_testcase_table[idx].msg_compile_fail);
+		if (idx == 0)
 			return TEST_SKIP;
 		else
 			return TEST_FAIL;
 	}
 
 	obj = prepare_bpf(obj_buf, obj_buf_sz,
-			  bpf_testcase_table[index].name);
+			  bpf_testcase_table[idx].name);
 	if (!obj) {
 		ret = TEST_FAIL;
 		goto out;
 	}
 
 	ret = do_test(obj,
-		      bpf_testcase_table[index].target_func,
-		      bpf_testcase_table[index].expect_result);
+		      bpf_testcase_table[idx].target_func,
+		      bpf_testcase_table[idx].expect_result);
 out:
 	bpf__clear();
 	return ret;
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index bc4cf50..366e38b 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -50,7 +50,7 @@
 int
 test_llvm__fetch_bpf_obj(void **p_obj_buf,
 			 size_t *p_obj_buf_sz,
-			 enum test_llvm__testcase index,
+			 enum test_llvm__testcase idx,
 			 bool force)
 {
 	const char *source;
@@ -59,11 +59,11 @@
 	char *tmpl_new = NULL, *clang_opt_new = NULL;
 	int err, old_verbose, ret = TEST_FAIL;
 
-	if (index >= __LLVM_TESTCASE_MAX)
+	if (idx >= __LLVM_TESTCASE_MAX)
 		return TEST_FAIL;
 
-	source = bpf_source_table[index].source;
-	desc = bpf_source_table[index].desc;
+	source = bpf_source_table[idx].source;
+	desc = bpf_source_table[idx].desc;
 
 	perf_config(perf_config_cb, NULL);
 
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 636d7b4..54af2f2 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1727,15 +1727,14 @@
 	}
 
 	while (!ret && (ent = readdir(dir))) {
-#define MAX_NAME 100
 		struct evlist_test e;
-		char name[MAX_NAME];
+		char name[2 * NAME_MAX + 1 + 12 + 3];
 
 		if (!strcmp(ent->d_name, ".") ||
 		    !strcmp(ent->d_name, ".."))
 			continue;
 
-		snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name);
+		snprintf(name, sizeof(name), "cpu/event=%s/u", ent->d_name);
 
 		e.name  = name;
 		e.check = test__checkevent_pmu_events;
@@ -1743,11 +1742,10 @@
 		ret = test_event(&e);
 		if (ret)
 			break;
-		snprintf(name, MAX_NAME, "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
+		snprintf(name, sizeof(name), "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
 		e.name  = name;
 		e.check = test__checkevent_pmu_events_mix;
 		ret = test_event(&e);
-#undef MAX_NAME
 	}
 
 	closedir(dir);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index d4d7cc2..718bd46 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -755,11 +755,11 @@
 				nd = browser->curr_hot;
 			break;
 		case K_UNTAB:
-			if (nd != NULL)
+			if (nd != NULL) {
 				nd = rb_next(nd);
 				if (nd == NULL)
 					nd = rb_first(&browser->entries);
-			else
+			} else
 				nd = browser->curr_hot;
 			break;
 		case K_F1:
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 3900386..d802938 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -684,7 +684,6 @@
 	ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent);
 	ui_browser__printf(arg->b, "%s", hpp->buf);
 
-	advance_hpp(hpp, ret);
 	return ret;
 }
 
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 956187b..26cba64 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -416,7 +416,7 @@
 {
 	char filename[PATH_MAX];
 	DIR *tasks;
-	struct dirent dirent, *next;
+	struct dirent *dirent;
 	pid_t tgid, ppid;
 	int rc = 0;
 
@@ -445,11 +445,11 @@
 		return 0;
 	}
 
-	while (!readdir_r(tasks, &dirent, &next) && next) {
+	while ((dirent = readdir(tasks)) != NULL) {
 		char *end;
 		pid_t _pid;
 
-		_pid = strtol(dirent.d_name, &end, 10);
+		_pid = strtol(dirent->d_name, &end, 10);
 		if (*end)
 			continue;
 
@@ -558,7 +558,7 @@
 {
 	DIR *proc;
 	char proc_path[PATH_MAX];
-	struct dirent dirent, *next;
+	struct dirent *dirent;
 	union perf_event *comm_event, *mmap_event, *fork_event;
 	int err = -1;
 
@@ -583,9 +583,9 @@
 	if (proc == NULL)
 		goto out_free_fork;
 
-	while (!readdir_r(proc, &dirent, &next) && next) {
+	while ((dirent = readdir(proc)) != NULL) {
 		char *end;
-		pid_t pid = strtol(dirent.d_name, &end, 10);
+		pid_t pid = strtol(dirent->d_name, &end, 10);
 
 		if (*end) /* only interested in proper numerical dirents */
 			continue;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 9409d01..933a509 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <linux/compiler.h>
 
 #include "../cache.h"
 #include "../util.h"
@@ -89,6 +90,7 @@
 	bool pge;
 	bool have_tma;
 	bool have_cyc;
+	bool fixup_last_mtc;
 	uint64_t pos;
 	uint64_t last_ip;
 	uint64_t ip;
@@ -584,10 +586,31 @@
 	uint64_t        tsc_timestamp;
 	uint64_t        timestamp;
 	bool            have_tma;
+	bool            fixup_last_mtc;
 	bool            from_mtc;
 	double          cbr_cyc_to_tsc;
 };
 
+/*
+ * MTC provides a 8-bit slice of CTC but the TMA packet only provides the lower
+ * 16 bits of CTC. If mtc_shift > 8 then some of the MTC bits are not in the CTC
+ * provided by the TMA packet. Fix-up the last_mtc calculated from the TMA
+ * packet by copying the missing bits from the current MTC assuming the least
+ * difference between the two, and that the current MTC comes after last_mtc.
+ */
+static void intel_pt_fixup_last_mtc(uint32_t mtc, int mtc_shift,
+				    uint32_t *last_mtc)
+{
+	uint32_t first_missing_bit = 1U << (16 - mtc_shift);
+	uint32_t mask = ~(first_missing_bit - 1);
+
+	*last_mtc |= mtc & mask;
+	if (*last_mtc >= mtc) {
+		*last_mtc -= first_missing_bit;
+		*last_mtc &= 0xff;
+	}
+}
+
 static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
 {
 	struct intel_pt_decoder *decoder = pkt_info->decoder;
@@ -617,6 +640,11 @@
 			return 0;
 
 		mtc = pkt_info->packet.payload;
+		if (decoder->mtc_shift > 8 && data->fixup_last_mtc) {
+			data->fixup_last_mtc = false;
+			intel_pt_fixup_last_mtc(mtc, decoder->mtc_shift,
+						&data->last_mtc);
+		}
 		if (mtc > data->last_mtc)
 			mtc_delta = mtc - data->last_mtc;
 		else
@@ -685,6 +713,7 @@
 
 		data->ctc_delta = 0;
 		data->have_tma = true;
+		data->fixup_last_mtc = true;
 
 		return 0;
 
@@ -751,6 +780,7 @@
 		.tsc_timestamp  = decoder->tsc_timestamp,
 		.timestamp      = decoder->timestamp,
 		.have_tma       = decoder->have_tma,
+		.fixup_last_mtc = decoder->fixup_last_mtc,
 		.from_mtc       = from_mtc,
 		.cbr_cyc_to_tsc = 0,
 	};
@@ -1241,6 +1271,7 @@
 	}
 	decoder->ctc_delta = 0;
 	decoder->have_tma = true;
+	decoder->fixup_last_mtc = true;
 	intel_pt_log("CTC timestamp " x64_fmt " last MTC %#x  CTC rem %#x\n",
 		     decoder->ctc_timestamp, decoder->last_mtc, ctc_rem);
 }
@@ -1255,6 +1286,12 @@
 
 	mtc = decoder->packet.payload;
 
+	if (decoder->mtc_shift > 8 && decoder->fixup_last_mtc) {
+		decoder->fixup_last_mtc = false;
+		intel_pt_fixup_last_mtc(mtc, decoder->mtc_shift,
+					&decoder->last_mtc);
+	}
+
 	if (mtc > decoder->last_mtc)
 		mtc_delta = mtc - decoder->last_mtc;
 	else
@@ -1323,6 +1360,8 @@
 			     timestamp, decoder->timestamp);
 	else
 		decoder->timestamp = timestamp;
+
+	decoder->timestamp_insn_cnt = 0;
 }
 
 /* Walk PSB+ packets when already in sync. */
@@ -1670,6 +1709,7 @@
 		switch (decoder->packet.type) {
 		case INTEL_PT_TIP_PGD:
 			decoder->continuous_period = false;
+			__fallthrough;
 		case INTEL_PT_TIP_PGE:
 		case INTEL_PT_TIP:
 			intel_pt_log("ERROR: Unexpected packet\n");
@@ -1724,6 +1764,8 @@
 			decoder->pge = false;
 			decoder->continuous_period = false;
 			intel_pt_clear_tx_flags(decoder);
+			__fallthrough;
+
 		case INTEL_PT_TNT:
 			decoder->have_tma = false;
 			intel_pt_log("ERROR: Unexpected packet\n");
@@ -1764,6 +1806,7 @@
 		switch (decoder->packet.type) {
 		case INTEL_PT_TIP_PGD:
 			decoder->continuous_period = false;
+			__fallthrough;
 		case INTEL_PT_TIP_PGE:
 		case INTEL_PT_TIP:
 			decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
index b1257c8..9b2fce2 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <endian.h>
 #include <byteswap.h>
+#include <linux/compiler.h>
 
 #include "intel-pt-pkt-decoder.h"
 
@@ -488,6 +489,7 @@
 	case INTEL_PT_FUP:
 		if (!(packet->count))
 			return snprintf(buf, buf_len, "%s no ip", name);
+		__fallthrough;
 	case INTEL_PT_CYC:
 	case INTEL_PT_VMCS:
 	case INTEL_PT_MTC:
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 9227c2f..89927b5 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -238,7 +238,7 @@
 	}
 
 	queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
-
+next:
 	buffer = auxtrace_buffer__next(queue, buffer);
 	if (!buffer) {
 		if (old_buffer)
@@ -261,9 +261,6 @@
 	    intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
 		return -ENOMEM;
 
-	if (old_buffer)
-		auxtrace_buffer__drop_data(old_buffer);
-
 	if (buffer->use_data) {
 		b->len = buffer->use_size;
 		b->buf = buffer->use_data;
@@ -273,6 +270,16 @@
 	}
 	b->ref_timestamp = buffer->reference;
 
+	/*
+	 * If in snapshot mode and the buffer has no usable data, get next
+	 * buffer and again check overlap against old_buffer.
+	 */
+	if (ptq->pt->snapshot_mode && !b->len)
+		goto next;
+
+	if (old_buffer)
+		auxtrace_buffer__drop_data(old_buffer);
+
 	if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
 						      !buffer->consecutive)) {
 		b->consecutive = false;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a35db82..38304b7 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -138,11 +138,11 @@
 #define PERF_EVENT_TYPE(config)		__PERF_EVENT_FIELD(config, TYPE)
 #define PERF_EVENT_ID(config)		__PERF_EVENT_FIELD(config, EVENT)
 
-#define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \
-	while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)	       \
-	if (sys_dirent.d_type == DT_DIR &&				       \
-	   (strcmp(sys_dirent.d_name, ".")) &&				       \
-	   (strcmp(sys_dirent.d_name, "..")))
+#define for_each_subsystem(sys_dir, sys_dirent)			\
+	while ((sys_dirent = readdir(sys_dir)) != NULL)		\
+		if (sys_dirent->d_type == DT_DIR &&		\
+		    (strcmp(sys_dirent->d_name, ".")) &&	\
+		    (strcmp(sys_dirent->d_name, "..")))
 
 static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
 {
@@ -159,12 +159,12 @@
 	return 0;
 }
 
-#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)	       \
-	while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
-	if (evt_dirent.d_type == DT_DIR &&				       \
-	   (strcmp(evt_dirent.d_name, ".")) &&				       \
-	   (strcmp(evt_dirent.d_name, "..")) &&				       \
-	   (!tp_event_has_id(&sys_dirent, &evt_dirent)))
+#define for_each_event(sys_dirent, evt_dir, evt_dirent)		\
+	while ((evt_dirent = readdir(evt_dir)) != NULL)		\
+		if (evt_dirent->d_type == DT_DIR &&		\
+		    (strcmp(evt_dirent->d_name, ".")) &&	\
+		    (strcmp(evt_dirent->d_name, "..")) &&	\
+		    (!tp_event_has_id(sys_dirent, evt_dirent)))
 
 #define MAX_EVENT_LENGTH 512
 
@@ -173,7 +173,7 @@
 {
 	struct tracepoint_path *path = NULL;
 	DIR *sys_dir, *evt_dir;
-	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
+	struct dirent *sys_dirent, *evt_dirent;
 	char id_buf[24];
 	int fd;
 	u64 id;
@@ -184,18 +184,18 @@
 	if (!sys_dir)
 		return NULL;
 
-	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
+	for_each_subsystem(sys_dir, sys_dirent) {
 
 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
-			 sys_dirent.d_name);
+			 sys_dirent->d_name);
 		evt_dir = opendir(dir_path);
 		if (!evt_dir)
 			continue;
 
-		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
+		for_each_event(sys_dirent, evt_dir, evt_dirent) {
 
 			snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
-				 evt_dirent.d_name);
+				 evt_dirent->d_name);
 			fd = open(evt_path, O_RDONLY);
 			if (fd < 0)
 				continue;
@@ -220,9 +220,9 @@
 					free(path);
 					return NULL;
 				}
-				strncpy(path->system, sys_dirent.d_name,
+				strncpy(path->system, sys_dirent->d_name,
 					MAX_EVENT_LENGTH);
-				strncpy(path->name, evt_dirent.d_name,
+				strncpy(path->name, evt_dirent->d_name,
 					MAX_EVENT_LENGTH);
 				return path;
 			}
@@ -1629,7 +1629,7 @@
 			     bool name_only)
 {
 	DIR *sys_dir, *evt_dir;
-	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
+	struct dirent *sys_dirent, *evt_dirent;
 	char evt_path[MAXPATHLEN];
 	char dir_path[MAXPATHLEN];
 	char **evt_list = NULL;
@@ -1647,20 +1647,20 @@
 			goto out_close_sys_dir;
 	}
 
-	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
+	for_each_subsystem(sys_dir, sys_dirent) {
 		if (subsys_glob != NULL &&
-		    !strglobmatch(sys_dirent.d_name, subsys_glob))
+		    !strglobmatch(sys_dirent->d_name, subsys_glob))
 			continue;
 
 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
-			 sys_dirent.d_name);
+			 sys_dirent->d_name);
 		evt_dir = opendir(dir_path);
 		if (!evt_dir)
 			continue;
 
-		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
+		for_each_event(sys_dirent, evt_dir, evt_dirent) {
 			if (event_glob != NULL &&
-			    !strglobmatch(evt_dirent.d_name, event_glob))
+			    !strglobmatch(evt_dirent->d_name, event_glob))
 				continue;
 
 			if (!evt_num_known) {
@@ -1669,7 +1669,7 @@
 			}
 
 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
-				 sys_dirent.d_name, evt_dirent.d_name);
+				 sys_dirent->d_name, evt_dirent->d_name);
 
 			evt_list[evt_i] = strdup(evt_path);
 			if (evt_list[evt_i] == NULL)
@@ -1722,7 +1722,7 @@
 int is_valid_tracepoint(const char *event_string)
 {
 	DIR *sys_dir, *evt_dir;
-	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
+	struct dirent *sys_dirent, *evt_dirent;
 	char evt_path[MAXPATHLEN];
 	char dir_path[MAXPATHLEN];
 
@@ -1730,17 +1730,17 @@
 	if (!sys_dir)
 		return 0;
 
-	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
+	for_each_subsystem(sys_dir, sys_dirent) {
 
 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
-			 sys_dirent.d_name);
+			 sys_dirent->d_name);
 		evt_dir = opendir(dir_path);
 		if (!evt_dir)
 			continue;
 
-		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
+		for_each_event(sys_dirent, evt_dir, evt_dirent) {
 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
-				 sys_dirent.d_name, evt_dirent.d_name);
+				 sys_dirent->d_name, evt_dirent->d_name);
 			if (!strcmp(evt_path, event_string)) {
 				closedir(evt_dir);
 				closedir(sys_dir);
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 6f2a027..593066c 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -153,7 +153,7 @@
 	if (fd == -1)
 		return -1;
 
-		sret = read(fd, alias->unit, UNIT_MAX_LEN);
+	sret = read(fd, alias->unit, UNIT_MAX_LEN);
 	if (sret < 0)
 		goto error;
 
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 05012bb..fdd87c7 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1460,16 +1460,12 @@
 	Dwarf_Addr _addr = 0, baseaddr = 0;
 	const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
 	int baseline = 0, lineno = 0, ret = 0;
-	bool reloc = false;
 
-retry:
+	/* We always need to relocate the address for aranges */
+	if (debuginfo__get_text_offset(dbg, &baseaddr) == 0)
+		addr += baseaddr;
 	/* Find cu die */
 	if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
-		if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) {
-			addr += baseaddr;
-			reloc = true;
-			goto retry;
-		}
 		pr_warning("Failed to find debug information for address %lx\n",
 			   addr);
 		ret = -EINVAL;
diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build
index 6516e22..82d28c6 100644
--- a/tools/perf/util/scripting-engines/Build
+++ b/tools/perf/util/scripting-engines/Build
@@ -1,6 +1,6 @@
 libperf-$(CONFIG_LIBPERL)   += trace-event-perl.o
 libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o
 
-CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default
+CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-nested-externs -Wno-undef -Wno-switch-default
 
 CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 4a3a72c..6ce624c 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -311,6 +311,16 @@
 
 	aggr->val = aggr->ena = aggr->run = 0;
 
+	/*
+	 * We calculate counter's data every interval,
+	 * and the display code shows ps->res_stats
+	 * avg value. We need to zero the stats for
+	 * interval mode, otherwise overall avg running
+	 * averages will be shown for each interval.
+	 */
+	if (config->interval)
+		init_stats(ps->res_stats);
+
 	if (counter->per_pkg)
 		zero_per_pkg(counter);
 
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index bcae659..efb5377 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -269,6 +269,7 @@
 		len = strfilter_node__sprint_pt(node->l, buf);
 		if (len < 0)
 			return len;
+		__fallthrough;
 	case '!':
 		if (buf) {
 			*(buf + len++) = *node->p;
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index fc8781d..accb7ec 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -21,6 +21,8 @@
 		case 'b': case 'B':
 			if (*p)
 				goto out_err;
+
+			__fallthrough;
 		case '\0':
 			return length;
 		default:
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 475d88d..27ae382 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1091,9 +1091,8 @@
 	 * For misannotated, zeroed, ASM function sizes.
 	 */
 	if (nr > 0) {
-		if (!symbol_conf.allow_aliases)
-			symbols__fixup_duplicate(&dso->symbols[map->type]);
 		symbols__fixup_end(&dso->symbols[map->type]);
+		symbols__fixup_duplicate(&dso->symbols[map->type]);
 		if (kmap) {
 			/*
 			 * We need to fixup this here too because we create new
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index cd08027..520a32a 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -151,6 +151,9 @@
 	struct rb_node *nd;
 	struct symbol *curr, *next;
 
+	if (symbol_conf.allow_aliases)
+		return;
+
 	nd = rb_first(symbols);
 
 	while (nd) {
@@ -1275,8 +1278,8 @@
 	if (kallsyms__delta(map, filename, &delta))
 		return -1;
 
-	symbols__fixup_duplicate(&dso->symbols[map->type]);
 	symbols__fixup_end(&dso->symbols[map->type]);
+	symbols__fixup_duplicate(&dso->symbols[map->type]);
 
 	if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
 		dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0a9ae80..829508a 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -227,7 +227,7 @@
 					struct addr_location *al)
 {
 	size_t i;
-	const u8 const cpumodes[] = {
+	const u8 cpumodes[] = {
 		PERF_RECORD_MISC_USER,
 		PERF_RECORD_MISC_KERNEL,
 		PERF_RECORD_MISC_GUEST_USER,
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 6ec3c5c..4e666b9 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -92,8 +92,8 @@
 {
 	DIR *proc;
 	int max_threads = 32, items, i;
-	char path[256];
-	struct dirent dirent, *next, **namelist = NULL;
+	char path[NAME_MAX + 1 + 6];
+	struct dirent *dirent, **namelist = NULL;
 	struct thread_map *threads = thread_map__alloc(max_threads);
 
 	if (threads == NULL)
@@ -106,16 +106,16 @@
 	threads->nr = 0;
 	atomic_set(&threads->refcnt, 1);
 
-	while (!readdir_r(proc, &dirent, &next) && next) {
+	while ((dirent = readdir(proc)) != NULL) {
 		char *end;
 		bool grow = false;
 		struct stat st;
-		pid_t pid = strtol(dirent.d_name, &end, 10);
+		pid_t pid = strtol(dirent->d_name, &end, 10);
 
 		if (*end) /* only interested in proper numerical dirents */
 			continue;
 
-		snprintf(path, sizeof(path), "/proc/%s", dirent.d_name);
+		snprintf(path, sizeof(path), "/proc/%s", dirent->d_name);
 
 		if (stat(path, &st) != 0)
 			continue;
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 9df6105..a2fd6e7 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -95,7 +95,8 @@
 	if (err)
 		die("error registering py script extension");
 
-	scripting_context = malloc(sizeof(struct scripting_context));
+	if (scripting_context == NULL)
+		scripting_context = malloc(sizeof(*scripting_context));
 }
 
 #ifdef NO_LIBPYTHON
@@ -159,7 +160,8 @@
 	if (err)
 		die("error registering pl script extension");
 
-	scripting_context = malloc(sizeof(struct scripting_context));
+	if (scripting_context == NULL)
+		scripting_context = malloc(sizeof(*scripting_context));
 }
 
 #ifdef NO_LIBPERL
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 93b0aa7..39c2c7d 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -156,6 +156,7 @@
 					 */
 			case 0x2C:	/* Westmere EP - Gulftown */
 				cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
+				break;
 			case 0x2A:	/* SNB */
 			case 0x2D:	/* SNB Xeon */
 			case 0x3A:	/* IVB */
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index d08e214..223d88e 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -2629,7 +2629,7 @@
     }
 
     waitpid $child_pid, 0;
-    $child_exit = $?;
+    $child_exit = $? >> 8;
 
     my $end_time = time;
     $test_time = $end_time - $start_time;
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 51cf825..f0d1c8f 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -13,6 +13,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
 #include <linux/libnvdimm.h>
 #include <linux/vmalloc.h>
 #include <linux/device.h>
@@ -1246,6 +1247,7 @@
 	if (nfit_test->setup != nfit_test0_setup)
 		return 0;
 
+	flush_work(&acpi_desc->work);
 	nfit_test->setup_hotplug = 1;
 	nfit_test->setup(nfit_test);
 
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index c8edff6..24ebd3e 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -83,7 +83,7 @@
 	done;
 
 	@# Ask all targets to emit their test scripts
-	echo "#!/bin/bash" > $(ALL_SCRIPT)
+	echo "#!/bin/sh" > $(ALL_SCRIPT)
 	echo "cd \$$(dirname \$$0)" >> $(ALL_SCRIPT)
 	echo "ROOT=\$$PWD" >> $(ALL_SCRIPT)
 
diff --git a/tools/testing/selftests/net/run_netsocktests b/tools/testing/selftests/net/run_netsocktests
index c09a682..16058bb 100755
--- a/tools/testing/selftests/net/run_netsocktests
+++ b/tools/testing/selftests/net/run_netsocktests
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 echo "--------------------"
 echo "running socket test"
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c b/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c
index c22860a..30e1ac6 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c
@@ -66,7 +66,7 @@
 
 	FAIL_IF(ebb_event_enable(&event));
 
-	mtspr(SPRN_PMC1, pmc_sample_period(sample_period));
+	mtspr(SPRN_PMC2, pmc_sample_period(sample_period));
 	mtspr(SPRN_PMC5, 0);
 	mtspr(SPRN_PMC6, 0);
 
diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c
index 31a3035..923e59e 100644
--- a/tools/testing/selftests/x86/ldt_gdt.c
+++ b/tools/testing/selftests/x86/ldt_gdt.c
@@ -394,6 +394,51 @@
 	}
 }
 
+#ifdef __i386__
+
+#ifndef SA_RESTORE
+#define SA_RESTORER 0x04000000
+#endif
+
+/*
+ * The UAPI header calls this 'struct sigaction', which conflicts with
+ * glibc.  Sigh.
+ */
+struct fake_ksigaction {
+	void *handler;  /* the real type is nasty */
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+	unsigned char sigset[8];
+};
+
+static void fix_sa_restorer(int sig)
+{
+	struct fake_ksigaction ksa;
+
+	if (syscall(SYS_rt_sigaction, sig, NULL, &ksa, 8) == 0) {
+		/*
+		 * glibc has a nasty bug: it sometimes writes garbage to
+		 * sa_restorer.  This interacts quite badly with anything
+		 * that fiddles with SS because it can trigger legacy
+		 * stack switching.  Patch it up.  See:
+		 *
+		 * https://sourceware.org/bugzilla/show_bug.cgi?id=21269
+		 */
+		if (!(ksa.sa_flags & SA_RESTORER) && ksa.sa_restorer) {
+			ksa.sa_restorer = NULL;
+			if (syscall(SYS_rt_sigaction, sig, &ksa, NULL,
+				    sizeof(ksa.sigset)) != 0)
+				err(1, "rt_sigaction");
+		}
+	}
+}
+#else
+static void fix_sa_restorer(int sig)
+{
+	/* 64-bit glibc works fine. */
+}
+#endif
+
 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
 		       int flags)
 {
@@ -405,6 +450,7 @@
 	if (sigaction(sig, &sa, 0))
 		err(1, "sigaction");
 
+	fix_sa_restorer(sig);
 }
 
 static jmp_buf jmpbuf;
diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c
index 86e698d..499b881 100644
--- a/tools/vm/slabinfo.c
+++ b/tools/vm/slabinfo.c
@@ -510,10 +510,11 @@
 			s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total);
 	}
 
-	if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail)
+	if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail) {
 		printf("\nCmpxchg_double Looping\n------------------------\n");
 		printf("Locked Cmpxchg Double redos   %lu\nUnlocked Cmpxchg Double redos %lu\n",
 			s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail);
+	}
 }
 
 static void report(struct slabinfo *s)
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 46dbc0a..49001fa8 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -868,7 +868,8 @@
 			continue;
 
 		kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
-		kvm->buses[bus_idx]->ioeventfd_count--;
+		if (kvm->buses[bus_idx])
+			kvm->buses[bus_idx]->ioeventfd_count--;
 		ioeventfd_release(p);
 		ret = 0;
 		break;
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index f0b08a2..7d31d8c 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -40,7 +40,7 @@
 
 	irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu,
 					lockdep_is_held(&kvm->irq_lock));
-	if (gsi < irq_rt->nr_rt_entries) {
+	if (irq_rt && gsi < irq_rt->nr_rt_entries) {
 		hlist_for_each_entry(e, &irq_rt->map[gsi], link) {
 			entries[n] = *e;
 			++n;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index fefbf2d..cb092bd 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -142,6 +142,7 @@
 	put_cpu();
 	return 0;
 }
+EXPORT_SYMBOL_GPL(vcpu_load);
 
 void vcpu_put(struct kvm_vcpu *vcpu)
 {
@@ -151,6 +152,7 @@
 	preempt_enable();
 	mutex_unlock(&vcpu->mutex);
 }
+EXPORT_SYMBOL_GPL(vcpu_put);
 
 static void ack_flush(void *_completed)
 {
@@ -652,8 +654,11 @@
 	list_del(&kvm->vm_list);
 	spin_unlock(&kvm_lock);
 	kvm_free_irq_routing(kvm);
-	for (i = 0; i < KVM_NR_BUSES; i++)
-		kvm_io_bus_destroy(kvm->buses[i]);
+	for (i = 0; i < KVM_NR_BUSES; i++) {
+		if (kvm->buses[i])
+			kvm_io_bus_destroy(kvm->buses[i]);
+		kvm->buses[i] = NULL;
+	}
 	kvm_coalesced_mmio_free(kvm);
 #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
 	mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
@@ -2861,7 +2866,7 @@
 		if (copy_from_user(&routing, argp, sizeof(routing)))
 			goto out;
 		r = -EINVAL;
-		if (routing.nr >= KVM_MAX_IRQ_ROUTES)
+		if (routing.nr > KVM_MAX_IRQ_ROUTES)
 			goto out;
 		if (routing.flags)
 			goto out;
@@ -3269,6 +3274,8 @@
 	};
 
 	bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
+	if (!bus)
+		return -ENOMEM;
 	r = __kvm_io_bus_write(vcpu, bus, &range, val);
 	return r < 0 ? r : 0;
 }
@@ -3286,6 +3293,8 @@
 	};
 
 	bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
+	if (!bus)
+		return -ENOMEM;
 
 	/* First try the device referenced by cookie. */
 	if ((cookie >= 0) && (cookie < bus->dev_count) &&
@@ -3336,6 +3345,8 @@
 	};
 
 	bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
+	if (!bus)
+		return -ENOMEM;
 	r = __kvm_io_bus_read(vcpu, bus, &range, val);
 	return r < 0 ? r : 0;
 }
@@ -3348,6 +3359,9 @@
 	struct kvm_io_bus *new_bus, *bus;
 
 	bus = kvm->buses[bus_idx];
+	if (!bus)
+		return -ENOMEM;
+
 	/* exclude ioeventfd which is limited by maximum fd */
 	if (bus->dev_count - bus->ioeventfd_count > NR_IOBUS_DEVS - 1)
 		return -ENOSPC;
@@ -3367,37 +3381,41 @@
 }
 
 /* Caller must hold slots_lock. */
-int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
-			      struct kvm_io_device *dev)
+void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
+			       struct kvm_io_device *dev)
 {
-	int i, r;
+	int i;
 	struct kvm_io_bus *new_bus, *bus;
 
 	bus = kvm->buses[bus_idx];
-	r = -ENOENT;
+	if (!bus)
+		return;
+
 	for (i = 0; i < bus->dev_count; i++)
 		if (bus->range[i].dev == dev) {
-			r = 0;
 			break;
 		}
 
-	if (r)
-		return r;
+	if (i == bus->dev_count)
+		return;
 
 	new_bus = kmalloc(sizeof(*bus) + ((bus->dev_count - 1) *
 			  sizeof(struct kvm_io_range)), GFP_KERNEL);
-	if (!new_bus)
-		return -ENOMEM;
+	if (!new_bus)  {
+		pr_err("kvm: failed to shrink bus, removing it completely\n");
+		goto broken;
+	}
 
 	memcpy(new_bus, bus, sizeof(*bus) + i * sizeof(struct kvm_io_range));
 	new_bus->dev_count--;
 	memcpy(new_bus->range + i, bus->range + i + 1,
 	       (new_bus->dev_count - i) * sizeof(struct kvm_io_range));
 
+broken:
 	rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
 	synchronize_srcu_expedited(&kvm->srcu);
 	kfree(bus);
-	return r;
+	return;
 }
 
 static struct notifier_block kvm_cpu_notifier = {
diff --git a/virt/lib/irqbypass.c b/virt/lib/irqbypass.c
index 09a03b5..e5d5dde 100644
--- a/virt/lib/irqbypass.c
+++ b/virt/lib/irqbypass.c
@@ -188,7 +188,7 @@
 	mutex_lock(&lock);
 
 	list_for_each_entry(tmp, &consumers, node) {
-		if (tmp->token == consumer->token) {
+		if (tmp->token == consumer->token || tmp == consumer) {
 			mutex_unlock(&lock);
 			module_put(THIS_MODULE);
 			return -EBUSY;
@@ -235,7 +235,7 @@
 	mutex_lock(&lock);
 
 	list_for_each_entry(tmp, &consumers, node) {
-		if (tmp->token != consumer->token)
+		if (tmp != consumer)
 			continue;
 
 		list_for_each_entry(producer, &producers, node) {